2011-05-25

Installing OSX (Snow Leopard) + Linux (Slackware 13.37 x86_64) on a GUID/GPT disk, with Software RAID enabled (ICH8R) - Part 5

Focusing on Linux + LILO setup, to (hopefully) conclude this series.

At this stage, you are supposed to have a standalone GPT/GUID disk, with a bootable OSX (Chameleon, Chimera), as well as free space for a Linux installation.

More disk partitioning

First order of the day is to pick up the latest Slackware distro (13.37 at the time of this post) and fire it up. Earlier versions of Slackware cannot handle GPT disks, and I don't believe they include gdisk either, so make sure you pick the very latest.

Now, since we seeded the partitioning from OSX and left some free space, when firing up gdisk (using sdc here as sda+sdb are used by Windows 7 in ICH8R RAID1) you'll be greeted with the following:
# gdisk /dev/sdc
GPT fdisk (gdisk) version 0.6.14

Partition table scan:
MBR: protective
BSD: not present
APM: not present
GPT: present

Found valid GPT with protective MBR; using GPT.

Command (? for help): p
Disk /dev/sdc: 234441648 sectors, 111.8 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): 592CD063-7F0A-4F52-81EC-A58C5D3F859C
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 234441614
Partitions will be aligned on 8-sector boundaries
Total free space is 175418693 sectors (83.6 GiB)

Number Start (sector) End (sector) Size Code Name
1 40 409639 200.0 MiB EF00 EFI System Partition
2 409640 59022927 27.9 GiB AF00 Snow Leopard

Command (? for help): n
Partition number (3-128, default 3):
First sector (34-234441614, default = 59022928) or {+-}size{KMGTP}:
Last sector (59022928-234441614, default = 59022928) or {+-}size{KMGTP}: +30G
Current type is 'Linux/Windows data'
Hex code or GUID (L to show codes, Enter = 0700):
Changed type of partition to 'Linux/Windows data'

Command (? for help): p
Disk /dev/sdc: 234441648 sectors, 111.8 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): 592CD063-7F0A-4F52-81EC-A58C5D3F859C
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 234441614
Partitions will be aligned on 8-sector boundaries
Total free space is 112504133 sectors (53.6 GiB)

Number Start (sector) End (sector) Size Code Name
1 40 409639 200.0 MiB EF00 EFI System Partition
2 409640 59022927 27.9 GiB AF00 Snow Leopard
3 59022928 121937487 30.0 GiB 0700 Linux/Windows data

Command (? for help): w

Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING PARTITIONS!!

Do you want to proceed, possibly destroying your data? (Y/N): y
OK; writing new GUID partition table (GPT).
The operation has completed successfully.
  • Note 1: You'll notice that there's a 200 MB EFI System Partition. If you want OSX to be happy, even if the OSX bootloader shouldn't need it, better leave it alone.

  • Note 2: You'll have noticed that when firing gdisk, it mentioned something about a "protective MBR". This is because GPT and MBR can coexist on the same disk, and therefore an MBR-only aware utility could potentially destroy data. We'll put the MBR+GPT coexistence to good use later on in this post.

  • Note 3: If you leave OSX's disk utility create the partition for the Linux system and try to change the type in gdisk, the installer might not see your Linux system partition as a valid target. If that occurs, you should delete the non OSX/EFI System partitions in gdisk (d command), and recreate them.

Slackware and LILO setup

The Slackware install is as straightforward as usual, so I'm not going to comment on it. At the end, just install LILO on the MBR of your standalone OSX/Slackware disk (here /dev/sdc) as you'd normally do. Reboot, and you oughta be able to access your newly installed Linux system.

So how about we add OSX boot to our etc/lilo.conf and be done with this whole exercise then? The OSX bootloader (Chameleon, etc.) should be able to take the relay after LILO handoff. And while we're at it, we'll also add Windows boot from /dev/sda.
Off we go then and add the following at the end of /etc/lilo.conf:
other = /dev/sda
label = Windows
other = /dev/sdc2
label = OSX
And now the fun begins...

LILO troubles
# lilo

Reference: disk "/dev/sdb" (8,16) 0810

LILO wants to assign a new Volume ID to this disk drive. However, changing
the Volume ID of a Windows NT, 2000, or XP boot disk is a fatal Windows error.
This caution does not apply to Windows 95 or 98, or to NT data disks.

Is the above disk an NT boot disk? [Y/n]
Hell to the no! What on earth is going on here? Well, a little googling around tells you that LILO is unhappy because our mirrored disks (/dev/sda and /dev/sdb) bear the same volume ID. Two solutions there:
  • Solution 1: add a section:
    disk = /dev/sdb
    inaccessible
    to lilo.conf to make it ignore the second mirrored disk altogether. In this case LILO will issue the warning Warning: bypassing VolumeID scan of drive flagged INACCESSIBLE: /dev/sdb but proceed.

  • Solution 2 (better): enable dmraid access to your drive. The thing is that the Slackware installer actually saw our mirrored volume alright (it listed our device automatically as /dev/md126*) but when booting our newly installed Slackware, the dm volume was no longer there. In case you wonder, this is because the Slackware installer rc.S script issues a /sbin/mdadm -A -s after fuse has been launched, which enables autodetection of mirrored drives.
    Therefore, if you just run that same command, the RAID 1 array will be detected and LILO won't complain about Volume IDs.
    # /sbin/mdadm -A -s
    mdadm: Container /dev/md/imsm0 has been assembled with 2 drives
    mdadm: Started /dev/md/WindowsRAID1_0 with 2 devices
    Probably a good idea to add that line in your system's rc.S script as well.

Now, with the Windows RAID issue being sorted, let's try again, shall we:
# lilo
Added Linux *
Added Windows
Warning: Device 0x0820: Inconsistent partition table, 2nd entry
CHS address in PT: 0:0:0 --> LBA (-1)
LBA address in PT: 0 --> CHS (0:0:1)
Fatal: Either FIX-TABLE or IGNORE-TABLE must be specified
If not sure, first try IGNORE-TABLE (-P ignore)
Son of a "£$%^&!! What's going on there?

Booting GPT partitions using MBR tools

I'll cut to the chase, our actual problem here is that LILO (as well as GRUB) is an MBR bootloader, not a GPT one. Therefore it actually uses the MBR partition table, and if you look at this table, you'll see that as far as MBR is concerned, /dev/sdc2 is nowehere to be found:
# fdisk -l /dev/sdc

WARNING: GPT (GUID Partition Table) detected on '/dev/sdc'! The util fdisk doesn't support GPT. Use GNU Parted.


Disk /dev/sdc: 120.0 GB, 120034123776 bytes
255 heads, 63 sectors/track, 14593 cylinders, total 234441648 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x41b82465

Device Boot Start End Blocks Id System
/dev/sdc1 1 234441647 117220823+ ee GPT
Wait a minute, if that's the case, how comes LILO was able to boot our Linux GPT partition then? Isn't that one GPT too?
Aha! Well, the trick here is that, when booting the system, LILO doesn't need to know how the partition or filesystem is setup. Since the kernel file is always available to the Linux system you want to run LILO from (duh!), LILO can point to the actual kernel image sectors directly, so it actually bypasses the whole partition table (as well the filesystem), and just provides a list of raw blocks to read. Haven't you learned something interesting today? And that is why even a non GPT aware bootloader like LILO is able to boot from a kernel residing on a GPT Linux system partition. But of course, as soon as you leave the system partition, then LILO needs an MBR reference, to know where the start of the target partition is located, which it cannot find.

gptsync to the rescue!

At first glance it looks like we may have to abandon LILO. As far as I know, GRUB is unlikely to perform any better though (it's also an MBR based bootloader), but there exist projects targeted at GPT such as eLILO, though these may also require an EFI platform as well, which may also render them useless for our usage scenario.

Now, remember what I said about protective MBR tables for GPT disks and how both MBR and GPT could coexist? How about we created an MBR table that contains the same partition information as our GPT one then? Well, that's exactly what the rEFIt's gptsync tool is all about. This is a tool that can take a GPT partition table and create an exact MBR clone of it, so that MBR aware tools get the relevant information about the partitions.
Of course, this can only work if the GPT partition doesn't deviate too much from MBR compatibility requirements, which in most case (if your HDD is less than 2 TB as this is the hard limit for maximum MBR), shouldn't be a problem.
At this stage you have two options: pick up the binary gptsync executable for OSX from the Mac disk image or recompile your own from source in Linux. If you want a precompiled gptsync for OSX you can find one here (direct mirror), but considering that we're in Linux right now, we'll go the recompilation route. After having downloaded and extracted the latest refit package, just navigate to the gptsync directory and run make -f Makefile.unix. As these utilities are fairly simple, this should produce a gptsync and showpart executable in the same directory. Might be a good idea to see what showpart reports before going further, right?
# ./showpart /dev/sdc

Current GPT partition table:
Warning: Unknown GPT spec revision 0x00010000
Floating point exception
Dammit! Does no single tool work as expected out of the box these days, or is it just that I'm always one step ahead in trying cutting edge stuff? Long story short, you get this error on 64 bit Linux environments because the tools use unsigned long for 32 bit unsigned, and unsigned long is not 32 bit on x86_64. Easiest way I found to fix this is to include <stdint.h> in gptsync.h and then change the UINT8, UINT16, UINT32, UINT64 typedefs to use uint8_t, uint16_t, etc.... Once this is done:
# ./showpart /dev/sdc

Current GPT partition table:
# Start LBA End LBA Type
1 40 409639 EFI System (FAT)
2 409640 59022927 Mac OS X HFS+
3 59022928 121937487 Basic Data

Current MBR partition table:
# A Start LBA End LBA Type
1 1 234441647 ee EFI Protective

MBR contents:
Boot Code: LILO

Partition at LBA 40:
Boot Code: None (Non-system disk message)
File System: FAT32
Listed in GPT as partition 1, type EFI System (FAT)

Partition at LBA 409640:
Boot Code: None
File System: Unknown
Listed in GPT as partition 2, type Mac OS X HFS+

Partition at LBA 59022928:
Boot Code: None
File System: ext4
Listed in GPT as partition 3, type Basic Data
Much better! Off we go then:
# ./gptsync /dev/sdc

Current GPT partition table:
# Start LBA End LBA Type
1 40 409639 EFI System (FAT)
2 409640 59022927 Mac OS X HFS+
3 59022928 121937487 Basic Data

Current MBR partition table:
# A Start LBA End LBA Type
1 1 234441647 ee EFI Protective

Status: MBR table must be updated.

Proposed new MBR partition table:
# A Start LBA End LBA Type
1 1 409639 ee EFI Protective
2 409640 59022927 af Mac OS X HFS+
3 * 59022928 121937487 83 Linux

May I update the MBR as printed above? [y/N] y
Yes

Writing new MBR...
MBR updated successfully!

Final LILO tuning

Alrighty. Time for a new run at LILO:
# lilo
Added Linux *
Added Windows
Warning: Device 0x0820: Inconsistent partition table, 2nd entry
CHS address in PT: 1023:254:63 --> LBA (16450559)
LBA address in PT: 409640 --> CHS (25:127:15)
Fatal: Either FIX-TABLE or IGNORE-TABLE must be specified
If not sure, first try IGNORE-TABLE (-P ignore)
Well, actually this is not entirely unexpected considering that GPT does away with the MBR requirements of having partitions starting and ending on a cylinder boundary, so of course, if you don't fine tune your GPT partition, you're likely to have an MBR partition table that doesn't meet the MBR specs. However, in this case, we can safely ignore that issue, by making sure we have the following at the top of our /etc/lilo.conf
lba32        # LBA addressing should be default anyway
ignore-table # ignore CHS vs LBA conflicts in the MBR
This time:
# lilo
Added Linux *
Added Windows
Warning: Device 0x0820: Inconsistent partition table, 2nd entry
CHS address in PT: 1023:254:63 --> LBA (16450559)
LBA address in PT: 409640 --> CHS (25:127:15)
Warning: The partition table is *NOT* being adjusted.
Added OSX
2 warnings were issued.
Yay, at long last, our bootloader installed!
NB: if you get an "invalid block" error on your OSX partition in LILO, this means that your OSX bootloader (Chameleon, Chimera) has not been properly installed, so you will need to fix that first.

With LILO in place, you should find that you now have multiboot between Linux, Windows and OSX, and you didn't have to forfeit your ICH8R Windows partition in the slightest.

As is obvious from the length of these posts, this whole process took some fairly heavy lifting, but I hope that was worth it!

No comments:

Post a Comment