Darwin/x86

Project Status

2008 June 29

The booter now has the ability to load additional kernel extensions from a ramdisk supplied by a multiboot loader. The ramdisks are supplied in the form of Multiboot modules. The ramdisks must be in flat format with a partition table (APM, GPT, or MBR) and an HFS or HFS+ partition. Inside the partition you should have a /Library/Application Support/DarwinBoot/Extra/Extensions/ directory containing extensions just like /System/Library/Extensions/ does on a real system. You could also theoretically have a single file /Library/Application Support/DarwinBoot/Extra/Extensions.mkext being an archive of any extra kernel extensions you'd like to pass in to the kernel.

Note that the extensions or the extension archive from the ramdisk is loaded in addition to the extensions or extension archive on the boot volume. For example, you might place ACPIPS2Nub and the ApplePS2Controller extensions on the ramdisk and thus add support for PS/2 devices. You cannot reliably provide modified versions of existing extensions on the boot volume nor can you cause the booter not to load the extensions on the boot volume.

That said because of the way IOKit works it is usually possible to add kernel extensions which match better than other kernel extensions. It is also possible to add kernel extensions which cause existing driver classes in existing kernel extensions to match on more hardware. One example is that of NullCPUPowerManagement which matches on IOResources with the AppleIntelCPUPowerManagement IOMatchCategory and a slightly higher probe score. This ensures that AppleIntelCPUPowerManagement does not load without requiring it to be removed from the system. Another example is LegacyAppleIntelPIIXATA which does not actually contain any binary code. Instead it contains only an Info.plist which matches on legacy PIIX ATA hardware and specifies that the AppleIntelPIIXATARoot class from the com.apple.driver.AppleIntelPIIXATA extension should be used to drive the hardware.

This method can be generally used to add support for a variety of hardware. Unlike the current "hackintosh" methods, this method does not break when Apple updates the OS.

To use this new support you will need something capable of loading the booter as if it were a Multiboot kernel and loading a flat disk image file as if it were a multiboot module. The Multiboot specification is part of the larger GRUB project so obviously GRUB does a fine job. For CDs you might prefer something slimmer like ISOLINUX. You will need the mboot.c32 program that comes as part of the syslinux distribution and unfortunately you will need to make a small patch to it because the existing code does not pass the booted BIOS device through to the booter. This is critical for El Torito "no emulation" boot because the BIOS is free to use any number it wishes. In practice it's typically 0x9f but various reports indicate it can be anything.

You will need a recent syslinux (I used 3.63 although I think 3.53 can work as well) and this patch. You will also need to copy com32/lib/syslinux/dsinfo.c from the latest syslinux git into your 3.63 working copy.

Those of you who have been using my booter in Multiboot mode may remember the 2-second delay giving you an opportunity to enter a different BIOS device. I have ripped this out and replaced it with a biosdev=XX option where XX is two hexadecimal digits (e.g. 80 to boot the first hard drive). Furthermore, once you are in the booter at the boot menu pressing the escape key will now drop you to the drive selector instead of booting the default entry. The drive selector is basically the same as before but it's nice that you can enter it as many times as you wish instead of having to reboot the machine.

Obviously this user-interface is still a work in progress. However, when used correctly it is fully capable of booting an unmodified OS X Leopard DVD. To do so you merely need to provide whatever extensions you need to make OS X work in your initrd file. When you run the booter you won't have any choices on the boot menu. Simply press escape to bring up the drive selector. With the drive selector up and waiting for your input eject the CD and insert the OS X DVD into the same drive. Wait about 10 seconds then press enter to restart the menu without changing the device. You should see the booter do the usual press any key to boot from the CD or press F8 to enter startup options. So do as you wish and in a minute or two you should be up and running Leopard. If you see an EBIOS read error, don't be concerned. The booter will retry the read and it usually works the second time. If not then perhaps you didn't wait for the drive to recognize the disk before hitting enter. If so, press escape and then enter and hopefully this time the drive will have spun up the new disc.

There is more to come soon as well. I am planning to merge in some of the changes from Chameleon that support more hardware and I plan to merge in some changes from some other people that support the kernels from Snow Leopard.

2008 May 25

Yes, I'm still alive! Thanks for asking. It's worth the wait for you though because I come bearing a new version of the bootloader including a number of enhancements and bugfixes. Some of this work is general stuff I had been hacking on in my working copies and some of it is work that I did for VMware. Yes, VMware was kind enough to pay me to do some work on this bootloader. Kudos to the folks at VMware, in particular Regis Duchesne (HPReg) who spearheaded the effort. His hard work on the virtualizer makes VMware Fusion 2 Beta 1 capable of running an unpatched Darwin 9 system. Obviously this is with the goal of officially supporting the virtualization of OS X which will be coming at some point in the future. As Regis mentions on his website, VMware is not doing a "Hackintosh" but a real installation of OS X from a factory-sealed DVD.

The changes I've made are varied. First of all, I've taken some time to make some very low-level changes to the code. As more things are added to the booter it tends to grow in size which becomes problematic because the original code had problems when certain uninitialized static and global variables were located outside of the base 2000h segment. Through a variety of changes to the thunking code I've enabled the booter to grow to exactly 65024 bytes which is the most that the first-stage bootsectors are capable of loading. Furthermore, there will no longer be any guessing as to whether or not the code might or might not work with certain data located above the real-mode segment. So long as all code and initialized data fits within the first segment the bootloader will run correctly. All uninitialized (e.g. zeroed at early starutp) data can be located wholly or partially in the next physical segment without any ill effects.

On the build system side of things I removed the -fomit-frame-pointer option. Without it, that is letting the compiler use the frame pointer, the code generated by the compiler is actually smaller. Beyond that, the frame pointer is required if you want to do any sort of debugging with the code. VMware provides a very nice debug stub that you can attach to with gdb. This makes debugging the code fairly easy although debugging real-mode portions is a bit tricky. At least you can step through instructions and examine registers though you have to do the segment/offset arithmetic yourself to know where in memory the registers are referring to. This is a limitation of gdb expecting a flat32 model.

I've done a few bugfixes to the HFS and HFS+ code. The first was a very nasty memory overwrite bug caused during the decompression of the HFS+ case tables. That bug was extremely annoying as it caused completely unrelated code to fail due to bogus data. In addition to that I discovered a bug in the HFS code. Who cares right? Well, wrong. Although hdiutil makehybrid will generate a hybrid ISO-9660 and HFS+ disk, the open source mkisofs tool generates a hybrid ISO-9660 and HFS disk. Again, this is a particularly nasty bug since the HFS code worked so long as you knew the file you were looking for. In the normal case the booter loads /mach_kernel and then compares the timestamp of /System/Library/Extensions and /System/Library/Extensions.mkext. So long as Extensions.mkext exists and Extensions either does not exist or is exactly 1 second older than Extensions.mkext, the booter will simply read Extensions.mkext. Otherwise it will enumerate the individual .kext bundles from the Extensions directory. The code as shipped by Apple misused strncpy and failed to NUL-terminate the strings. Therefore, enumerating the files in a directly would rarely, if ever, work. It is only because Apple's Darwin ISO's always included a valid Extensions.mkext that this bug was never encountered.

Now what you're probably really wondering is what cool new stuff I added. Well, I added GPT support which is quite useful because OS X will not install to anything other than a GPT disk out of the box. Perhaps not so useful for people dual-booting Darwin with other traditional x86 operating systems but very useful for people booting OS X in a virtualizer. Alex Graf has been using this bootloader with QEMU which he is slowly but surely making capable of running OS X.

I've also finally added FSB detection. This works only for Intel chips which return the multiplier information from a read to MSR 198h. This is exactly what xnu does during its early startup so if you have an Intel system everything works as expected. If you are running Darwin on an AMD machine the booter itself will cause the machine to reboot almost immediately after you attempt to start the kernel. One way to check for this is to use the new ?clocks command which will tell you the speed of the TSC, the multiplier, and the FSB speed that is calculated from those two pieces of information. If executing ?clocks causes the machine to reboot then you will never be able to run an unpatched xnu as it exists today. However, assuming you have built your own patched xnu you can override the check using the new fsbmhz= option. In this case which value you specify depends on what you did to the kernel. It may be that you've patched the kernel such that it ignores whatever the bootloader passes it. In this case you can specify any non-zero value for fsbmhz to keep the booter from trying to determine it.

The booter also checks one additional case which is MSR198h returning 0. This happens in shipping versions of VMware (aside from Fusion 2 betas). In this case it prints a big fat warning reminding you that you had better be using a patched xun. Again, specify any non-zero fsbmhz to bypass this check. In that case your patched kernel should just ignore the value it gets from the bootloader.

I've also made a small change to the way CD-ROM bootup occurs. It no longer defaults to booting the hard drive when it's booting from the CD. I always thought that was stupid. Instead it now boots the CD when you are booting from the CD. If you are for some strange reason using the CD to boot the hard drive then you can simply press 'h'.

The new revision is 122. Yes, that's a huge jump from 28. The reason is that a lot of branching and merging occured in the same svn repository unrelated to the bootloader source. Right now, everything is all rolled into one big patch although I'm working on putting together a changelog. That said, I don't think there's anything I changed that you wouldn't want so you might as well take it all. If for some reason you require the details, let me know. dfe@tgwbd.org

2007 November 8

I've had some reports that the code is not building on a standard OS X installation. One reason is that Apple has never included the uuid/namespace.h header in an OS X install, you have to grab it from Libc. I had basically forgotten that I'd done this. Rather than require users to do this I've now done what BootX's fs.c does and simply define kFSUUIDNamespaceSHA1 directly in the source.

In addition, the md5.h header has changed on Leopard. It is now libkern/crypto/md5.h and one of the function prototypes has a slightly changed signature (const void* instead of const unsigned char*). The new code builds on Leopard and should theoretically still build on pre-Leopard systems, so long as the max allowed OS X version is set properly (actually, maybe min is more appropriate?).

Another cool feature of the new release is the ability to run it under Apple's EFI CSM (e.g. Boot Camp). In addition, I've also made some enhancements to the Multiboot code path (which is, BTW, the only one that I test). The our_printf hack has been replaced with a simple hack of providing a temporary bootArgs good enough for the real libsaio printf to work in the time before the usual boot() entrypoint is called. Also, I've added some preliminary support for chain booting although I'm aware it's incomplete (it does not set ES:SI appropriately) and fixing that would involve some serious changes to the code.

The new release is r28. You can find it at the bottom of this page.

Booting OS X (10.5) with this booter does not seem to consistently work on my MacBook Pro. It seems if I boot to Windows, warm restart, and then boot into this loader I can _sometimes_ get the machine to boot into OS X. Other times it hangs for an indeterminate amount of time, from a few seconds to a few minutes to longer than I cared to wait before holding the power button, then displays some message about not getting an HPET, another message about failing to start the CPU, and then promptly reboots the machine. What bothers me most is that it's very indeterminate as to whether it will or will not boot.

The one time I did get it to successfully boot, OS X worked, albeit with amusingly stretched 1024x768 graphics with no acceleration.

So where does that leave the project? Why am I booting Darwin on a real Mac? Well, the answer is that Darwin no longer includes a license to use critical portions like AppleACPIPlatformExpert. Granted, there is AppleI386GenericPlatform but to function properly on modern hardware, an ACPI runtime is much more ideal. Therefore, in order to check that the booter is maximally compatible with existing code, the only legal way to do it as far as I can tell is to use my OS X license which stipulates that I don't run the OS X code on non-Apple hardware.

Now, I am no lawyer and so my interpretation could be wrong. It could be that the old Darwin binary license still applies, but I've asked Apple for clarification with no response yet so by default I am taking the safe position. I suggest you do the same.

At the moment, my plan is to leave things where they are now and see what happens. There's word that VMware will be making real OS X run under their virtualization products when running on Apple hardware now that the OS X Server license allows this. Being able to boot Darwin under VMware would of course be much nicer than rebooting my MacBook Pro. And who knows, maybe VMware will find this booter useful. Or maybe they won't and they'll just add EFI firmware to their VM and use Apple's booter.

If I have some spare time I may see about modifying xnu to boot under VMware. Right now the biggest problem is lack of emulated HPET. That will be on the xnu page, not this page.

2007 November 5

The bootloader project has progressed from r14 to r21. The new release fixes a major misunderstanding with the contents of the device tree configuration table properties: they are supposed to be the table addresses, not the actual contents of the tables. In addition, it now searches for the ACPI tables, compiles against Leopard headers, provides stub EFI runtime services, and includes semi-bogus firmware-* properties in the "/efi" device node.

I've also upgraded my VPS to a much faster system with more resources and I've restarted mail service for tgwbd.org. Upon installing the mailserver I realized that hundreds of spammers apparently still have the e-mail address I'd been using so there's no point in hiding it. SpamAssassin seems to be doing a fine job at blocking all of it so far. E-mail me at dfe@tgwbd.org if you have any questions about the project or have a patch I could use.

I'm going to try to get a read-only svn repo up real soon now. For now, it's still downloadable patches.


The Bootloader

Most whitebox PCs today are still using normal BIOS and not EFI. Apple provides a boot loader for normal PCs in the boot project. The last release Apple made was boot-132. It appears this release was used with the last version of OS X for the DTK systems. Oddly enough, Apple did not release this source code until it released the 10.4.8 set of tarballs. Perhaps this is because the 10.4.8 set of tarballs is also the release which finally includes xnu source. It does seem odd though when one considers that Apple only shipped a binary of it with the later releases (or possibly only the last release) for the DTK system. No Intel Mac uses this booter because Intel Macs use the boot.efi booter for which Apple does not make the source available.

Compared with the prior boot-122 release there are not many changes except for the struct boot_args which actually comes with the xnu kernel, not the bootloader. To build a proper boot binary one must take care to be doing it on a machine with headers installed suitable for the kernel one wants to boot. The new struct boot_args basically resembles the old one with a couple of changes related to how the video state information is handed to the kernel and a couple of additions of "EFI" fields.

To understand what needs to go in those fields we need to know what xnu expects in those fields. But that is actually getting ahead of ourselves. As discussed on the xnu page the very first thing we need is an FSB frequency in the device tree.

The Device Tree

The device tree is a simple concept. On a PowerPC Mac, the OpenFirmware provides the device tree more or less as is to the kernel. On an Intel Mac, it is the responsibility of the bootloader to set this up. The device tree consists of a tree where each node can have any number of properties. The "name" property is special because it can be used with functions returning a node given a pathname.

The specific node the xnu kernel wants is the /efi/platform node. Within that node, the kernel wants a property called "FSBFrequency" to contain a 64-bit integer which is the frequency of the machine's front-side bus in Hz.

Adding the node to the device tree is easy. The boot loader already contains code for creating the device tree so the only thing required is to add the node then add the property with the correct value to the node.

Using a source built xnu with debug flags including 0x108 and a serial terminal one can clearly see that the addition of this device tree key at least gets the kernel past the EFI_FSB_frequency() function. Assuming a suitable processor (Core or Core 2), the kernel will actually make it much further. In fact, on a Core or Core 2 system with an appropriate chipset the kernel source will not need to be modified at all.

EFI data

The next step to improving the bootloader to meet the requirements of modern xnu kernels is to provide an EFI system table and an EFI runtime services table. The bootloader as shipped by Apple leaves these fields as zero which causes a page fault due to dereferencing the NULL pointer.

A proper EFI system puts all EFI data and code in reserved areas of physical memory and marks these areas as reserved in the ACPI memory map. We are not a proper EFI system but are only trying to provide the data to xnu so we only need to put it somewhere such that xnu won't overwrite it with something else in a memory page that is mapped in to xnu's address space. It turns out that xnu doesn't do anything particularly fancy with the EFI areas of the ACPI memory map but rather maps them as-is into its virtual address space. Because of this, xnu will use the physical address of the efiSystemTable field in the bootArgs struct as a virtual address.

The only requirement left then is to put that table somewhere that will also be mapped as-is into kernel address space. Well, it turns out that there is already an AllocateKernelMemory call which does just that. It's used, of course, for the bootArgs struct itself. So there's no reason it can't be used for the fake EFI data.

The EFI system table is a straightforward structure containing very basic system information and a pointer to the physical address of the EFI runtime services structure. The EFI runtime services structure is basically a collection of function pointers, none of which xnu itself appears to use. It does, however, pass the runtime services table to the IOKit so presumably one or more kernel extensions use it. If I had to take a guess, it would be the AppleEFIRuntime.kext and its plugin AppleEFINVRAM.kext, neither of which are available for a Darwin/x86 system as they are part of OS X only.

After modifying the booter to include the appropriate EFI tables the xnu kernel will actually boot to the point of starting the IOKit. At this point you need a platform driver (a.k.a. Platform Expert) to continue the boot process. Unfortunately, Apple doesn't provide source for this and some quick googling reveals that the GNU/Darwin project has asked. I am not necessarily a free-software purist so a binary blob would be fine with me. Obviously the Hackintosh crowd has been quite successful at using the AppleACPIPlatform.kext provided with OS X so perhaps I could politely ask Apple to give the community a license to use it with Darwin/x86. Also quite obviously, the binary blob is certainly available as several OS X updates have included a copy of it.

At this point we have a nearly bootable system. We have fake EFI tables pointed to by global symbols and passed in to the IOKit start. It remains to be seen which kernel extensions will and will not work correctly with the fake tables. It also remains to be seen which kernel extensions are going to need additional device tree properties.

AppleSMBIOS.kext

One kernel extension mentioned frequently in Hackintosh forums is AppleSMBIOS.kext. The source code to this kernel extension is available from Apple and it reveals to the reader that it requires a node in the device tree with a table property containing the SMBIOS entry point structure.

The specification for SMBIOS is freely available and reveals that the SMBIOS EPS is to be searched for within a particular range of memory. I have gone ahead and done this although I can only assume that AppleSMBIOS will find it correctly.

Inspiration

The inspiration for this project comes from a screenshot at the website of a pseudonymous hacker calling himself netkas. In the screenshot, one can see the IORegistryExplorer application opened to the /efi/configuration-table node. One can also see a number of child nodes, one of which is the SMBIOS GUID. Also in the screenshot, one can see Apple System Profiler opened and showing the processor to be an Intel Celeron running at 2.27 GHz.

Some googling revealed this post where the poster quotes Netkas's thread on hackint0sh.org explaining that he has set up the tianocore shell on a USB stick. For absolute maximum compatibility with EFI on a non-EFI system that makes a lot of sense. If you are just trying to make xnu boot, it's sort of complicated and also requires the proprietary boot.efi.

About EFI

What I've realized about EFI is that it is the classic case of "You can take the trash out of the trailer but you can't take the trailer out of the trash." That is to say that EFI doesn't change anything about the way x86 PCs operate. This was by design. Intel considered moving to the industry-standard OpenFirmware as found on PPC Macs and SPARC Suns but quickly realized that OpenFirmware would supplant things like ACPI and SMBIOS with a nice clean device tree. This would have meant that OS code would have to be updated to handle a totally new (to x86) set of structures. Because most OSes would like to continue booting on older machines they'd also have to continue handling ACPI tables for the older machines.

The flip side of that is that most people with newer machines would like to continue to boot older OSes. In order to make that happen, the system would have to have the various tables that older OSes expect like ACPI tables and SMBIOS tables. If Intel had gone with something like OpenFirmware, any BIOS compatibility code would have to set these up based off of the OpenFirmware device tree. So what Intel did was simply keep the existing specifications as they were but add code around them to make it easier to use them. That added code is EFI.

Apple already had an abstraction for gathering system information at boot time and the x86 Darwin booter already used it long before EFI was used by Apple. By keeping the system information gathering in the booter, xnu is able to avoid mucking about trying to find the ACPI memory ranges or the SMBIOS entry point structure. Instead, the boot loader does all of this mucking about and hands it off to the kernel.

With EFI, the boot loader has a lot less mucking about to do and presumably the boot.efi source code is relatively straightforward. Even without EFI, I don't anticipate that the booter found here is going to become too complex. It had better not, it can't grow too much more before exceeding the size of the 64k real mode code segment it expects to start life in.

Patches requested

Like any good software, this is to be considered a work in progress. Currently, the FSB Frequency is fixed at the 200 MHz used by most modern Intel-based systems. The first patch I'd like to see hit my inbox is one which gets the correct FSB Frequency. Keep in mind that boot options are basically a no-go here because boot options are for the kernel, not for the booter. In other words, try to get it right rather than provide some hack to override it.

If absolutely necessary I've considered adding a boot options scheme using the "?*" namespace of boot command lines similar to the ?video "option" already used by the booter. I would envision something like ?set fsb=166. Other options might include something like ?biosdevice 81 to switch to the second hard drive or ?biosdevice to enumerate available drives (if that information is available).

However, one has to take care not to add too much crap as the booter needs to absolutely stay within a 64k real mode code segment with the code being loaded at offset 0x200 (512 bytes) in that segment. That means the limit is 63.5k but then there is cdboot which is a 2k stub-booter followed by the real booter thus effectively meaning you can have at most 62k of code. The project as shipped is in the high 50k and my changes have already added another k or two. Not much more can be added before the whole thing would have to be rewritten to handle loading a third booter and/or loading the rest of itself which would just be ludicrous.

Multiboot

Writing a modified booter requires a way to test it. We are hacking the stage 2 booter which except in the case of CDs is booted via the stage 1 booter. The stage 1 booter is different depending on whether the system partition is UFS or HFS+. If the partition is UFS then the boot1u code is used. If the partition is HFS+ then the boot1h code is used. We'll ignore UFS since hardly anyone uses it and focus on HFS+. The stage 1 HFS+ (boot1h) boot sector makes use of the HFS+ startup file to find the stage 2 booter. The startupfile is a part of HFS+ that allows a relatively small file to be allocated in a contiguous set of blocks and pointed to by only the startupfile block pointer. Unfortunately, modifying it requires that the HFS+ partition be accessible to a working Darwin or OS X system. Granted, I could have hacked the OpenDarwin startupfiletool to run under Linux but what would be the fun in that?

My idea was simple. Set up a test rig using a Mac to create a base hard drive image I could copy over once to the test rig's hard drive. Then install GRUB in a small ext2 partition where I could simply use Linux to copy the boot loader as a normal file on to the ext2 partition.

There's only one problem. GRUB doesn't know anything about Darwin's boot2. However, GRUB does have this handy specification called Multiboot. As far as I know, no common OS uses Multiboot but a lot of toy operating systems do. It's rather convenient because your Multiboot kernel gets to start in protected mode with the A20 gate enabled. Great!

The neat thing about the Multiboot specification is that it does not require any particular executable format. All it requires is a Multiboot header to be present on any 4-byte aligned offset in the binary. The header specifies which memory address the "kernel" would like to be loaded at and what location to jump to after having loaded the file from disk.

The specification doesn't explicitly state it but GRUB won't load any Multiboot binary below 1 MB. The booter as shipped pretty much has to live in low memory because it makes tons of BIOS calls simply by briefly switching out of protected mode, making a BIOS call, then switching back. It never mucks with the stack or jumps to a special location or anything like that. At this stage of the boot process there aren't too many options for doing anything except by using BIOS calls. Unless of course you want to implement a bunch of hardware drivers. Now I'm seeing why EFI is a really great idea.

So, the name of the game here is to get down into low memory as quickly as possible so we can take advantage of BIOS services like text output ("ooh") and disk reads ("ahhhh").

This doesn't seem too bad until you realize that the multiboot information that the booter gives to us starts life as a GRUB global symbol. That means it is located precisely where we are about to move because GRUB likes to live at the same address as boot. So the very first thing is to accept the fact that we need to run above 1 MB for a bit longer than we'd like, copy the multiboot information somewhere safe, then move ourselves down.

The initial boot has to be done in pure assembler because Multiboot specifies that the stack pointer doesn't necessarily point anywhere useful nor is the GDT necessarily valid. So the initial trick is to avoid doing anything that would cause the GDT to be referenced. That's not too hard, just don't do far jumps or load any segment registers.

I could have implemented the memcpy of the boot info structure in assembler, but why bother. Set up a valid stack, push the eax and ebx registers onto it, and BAM, you've got C. From here we can use most anything in libsa but not libsaio. We can use memcpy, so we do. Nice. We even use it to move ourselves.

Once we've gotten to C it makes little sense to return to assembler just to get back to C so instead I used a neat little hack whereby I call an assembler function that fixes up its return address and jumps to itself at the correct location in the correct segment (selector). Then it just executes a normal ret. I thought it was a rather novel approach.

There is a small bit of code added to allow the user to optionally enter a BIOS device number when booting via Multiboot. This is necessary because there is no way to tell GRUB which BIOS device to send. It will always pass the BIOS device containing what it thinks is the kernel. This is of course not the kernel but this booter. The real kernel (xnu) is on the hard drive.

The drive-selection code is kind of annoying and eventually I think it would be better to implement it from within the booter rather than before the booter. But it works for my purposes. Best thing to do would be to fix GRUB. Note that that code is only used when booted via Multiboot. The booter continues to function normally when booted as the HFS+ startupfile or via the UFS booter.

Why!?

What this does is make it a lot easier to test new boot loader code because the compiled binary can be easily copied on to the ext2 boot partition using any copy of Linux. Or you can even keep grub on the HD and shuffle a disk from your Mac (i.e. w/ a USB floppy drive) to your PC and point grub at the kernel on the floppy disk. The floppy disk is ideally formatted with plain old FAT12 in this case.

Mac OS X

Please note that this boot loader enables booting of binaries built from unmodified xnu kernel source on systems with compatible chips (e.g. Intel Core and Core 2 processors) and compatible chipsets (i.e. including an HPET). In case you haven't figured it out, that implies that assuming Apple's xnu binary is built from that same source tree then it will boot unmodified. You are advised to heed any legal agreements you have made with respect to usage of OS X software, whatever those agreements may be.

You are also advised that this booter does not magically decrypt OS X binaries. You still need a Mac for that or you will have to modify the kernel or add a kernel extension to accomplish this. All that this booter does is allow you to possibly boot an unmodified (source or binary built from unmodified source) xnu kernel.

Downloads

Apple provides the boot-132 tarball from the 10.4.8 for x86 page.
Download boot-132.tar.gz from Apple (Requires free ADC account).

Sorry, I'm not making patches anymore. In lieu of this I've made the public branch of my SVN tree accessible.

Please consider doing me a favor and saving my bandwidth by downloading the base package from Apple and only the patch from this site.
Download diff from boot-132 to boot-132_dfe_r146 (unified format, apply with patch -p0).
Download diff from boot-132_dfe_r28 to boot-132_dfe_r146 (unified format, apply with patch -p0).

The above patch supersedes the r122 patch.
Download diff from boot-132 to boot-132_dfe_r122 (unified format, apply with patch -p0).
Download diff from boot-132_dfe_r28 to boot-132_dfe_r122 (unified format, apply with patch -p0).

The above patch supersedes the r28 patch.
Download diff from boot-132 to boot-132_dfe_r28 (unified format, apply with patch -p0).
Download diff from boot-132_dfe_r21 to boot-132_dfe_r28 (unified format, apply with patch -p0).

The above patch supersedes the r21 patch. The new code has some enhancements.
Download diff from boot-132 to boot-132_dfe_r21 (unified format, apply with patch -p0).
Download diff from boot-132_dfe_r14 to boot-132_dfe_r21 (unified format, apply with patch -p0).

The above patch supersedes the r14 patch. There are a number of bugs in the old code.
Download diff from boot-132 to boot-132_dfe_r14 (unified format, apply with patch -p0).

I am providing my modified source code as a tarball. I have a local svn tree that I am considering making public but right now I'm going to stick with the simple model of accepting patches and doing releases myself.
Download boot-132_dfe_r146.tar.gz

View all Darwin downloads.

At this time I am not providing binaries. If the Darwin/x86 project as a whole progresses to the state where it is actually usable without a C compiler, I might consider providing binaries.