Live CDs are a very popular way to distribute operating systems.
In order to make a PureDarwin Live CD, we essentially need to do two things:
If anyone knows more about how to use NetBoot images locally, please join work on the Live CD.
Mac OS X Installation DVDs are capable of running Mac OS X from a read-only medium. Maybe we can learn from that, hence we are looking at the procedure in this paragraph.
As of Snow Leopard, Mac OS X Installation DVDs contain the launchd LaunchDaemon plist file /System/Library/LaunchDaemons/com.apple.install.cd.plist with the following content:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
Hence, when the system is booted, the script /etc/rc.install is executed. This script mainly launches the Installer. However, there is also a script /etc/rc.cdrom which does the main magic of mounting ramdisks to
# Disable prebinding-on-the-fly while we're CD booted
# mount root_device to update vnode information
mount -u -o ro /
# Create a RAM disk with same perms as mountpoint
echo "Creating RAM Disk for $mntpt"
dev=`hdik -drivekey system-image=yes -nomount ram://$rdsize`
if [ $? -eq 0 ] ; then
# save & restore fs permissions covered by the mount
eval `/usr/bin/stat -s $mntpt`
mount -t hfs -o union -o nobrowse $dev $mntpt
chown $st_uid:$st_gid $mntpt
chmod $st_mode $mntpt
RAMDisk /Volumes 1024
RAMDisk /var/tmp 1024
RAMDisk /var/run 1024
RAMDisk /var/db 1024
mkdir -m 1777 /var/db/mds
# language prefs, colorsync need to be able to write some preferences (5424449)
RAMDisk /Library/Preferences 1024
RAMDisk /Library/ColorSync/Profiles/Displays 2048
# use or create the boot cache playlist, and allow B&I to force 32-bit playlist generation
if nvram boot-args | grep "no64exec" ; then
SIXTYFOURBIT=`sysctl -n hw.cpu64bit_capable`
if [ $SIXTYFOURBIT = "0" -o $FORCETHIRTYTWO = "true" ] ; then
echo "using 32-bit bootcache playlist"
BootCacheControl -f /var/db/BootCache.playlist32 start
elif [ $SIXTYFOURBIT = "1" ] ; then
echo "using 64-bit bootcache playlist"
BootCacheControl -f /var/db/BootCache.playlist start
# tell launchd to commence with loading the system.
# for the OS Install environment only, /etc/rc.install is included in this process.
launchctl load -D system
# this script sleeps forever; the installer or startup disk will always reboot the system.
How does this script get called? How can hdik be replaced with what is in Darwin? Please let us know. Perhaps we could use a MacFUSE based ramdisk from http://thebends.googlecode.com/svn/trunk/ramdisk/
So far, when replacing the above RAMDisk function with one based on MacFUSE's mount_ramdisk, we get
launchctl error: launch_msg(): Socket is not connected
Please let us know if you know how to solve this.
Run the system uncompressed from the CD medium (like PureDarwin nano or like the Mac OS X Install DVD).
This is not a workable option for two reasons: It's slow (since more data needs to be read from the slow optical disc) and it's too small (700 MB is not much space).
The XNU kernel contains some references to "imageboot", e.g., here:
Apparently, one should be able to boot using a boot argument like -v rp=file:///some.dmg
then the system would mount /some.dmg as the root device and continue booting from there.
How this works is largely undocumented. Below is a proof-of-concept for imagebooting PureDarwin nano on a Mac host.
What follows are proof-of-concept instructions that show how to boot into puredarwin.iso (from the PureDarwin nano image on the download page) that is located at / on a Mac running Mac OS X 10.5.4. Please do not try this on a production machine. Only try this if you have a spare Mac.
You have now performed an ImageBoot of PureDarwin nano on a Mac OS X host.
To undo, remove the extra Kernel Flags from your Boot.plist.
There are (unverified) news reports that cite "ImageBoot" as an official feature in the not-yet-released Snow Leopard:
However, all attempts to make this work on a Darwin host so far resulted in di_root_image failed as it appears that IOHDIXController.kext (a kernel extension from Mac OS X that deals with disk images) and its respective plug-ins must be present and loaded for imageboot to work. Unfortunately, this kext seems not to be available for Darwin at this time (even though this posting suggests that it might be available as a binary root under the Driver License).
According to Singh, the kernel can be forced to use the BSD vndevice instead of hdix by specifying vndevice=1 as a boot argument. In this case, the function netboot_setup() from netboot.c is supposed to mount the file system contained in the vndevice node. But we can't get it to work yet (and it would only work for uncompressed images).
Please let us know if you know if you are aware of a working solution that does not involve IOHDIXController.kext, or where a recent version of IOHDIXController.kext can be downloaded under a suitable license. (It used to be available under the Apple Binary License, but it made its last appearance in Darwin 6...)
As a totally desperate worst-case fallback scenario: The source code for mounting filesystem images is available, and there is source code for uncompressing compressed DMGs available. Maybe it would be feasible to write a minimal IOHDIXController.kext replacement that is able to mount compressed DMGs. Volunteers?
A set of NetBoot files created by System Image Utility looks like this:
NetBoot.dmg: Apple Partition data block size: 2048, first type: Apple_partition_map, name: Apple, number of blocks: 63, second type: Apple_Driver43, name: Macintosh, number of blocks: 56, third type: Apple_Free, name: , number of blocks: 0, fourth type: Apple_Driver_ATAPI, name: Macintosh, number of blocks: 56
i386/booter: Universal EFI binary with 2 architectures, i386, x86_64
(to be continued)
Maybe using a compressed ZFS file and manual trickery...
This is a work in progress.
#!/bin/bash -e -x
mount -uw /
/usr/libexec/vndevice attach /dev/vn0 /uncompressed.dmg
/usr/libexec/vndevice shadow /dev/vn0 /shadowfile
mount -t hfs /dev/vn0 /live/
# /usr/libexec/vndevice detach /dev/vn0
For developers >