Darwin

From AwkwardTV
Jump to: navigation, search

<Google>WIKI</Google>

This page is about "Darwinx86" in general. Nothing specific to Apple TV. However, since Darwin is at the core of Apple TV, it is important to know how Darwin works. Everything 100% APSL compliant. We host it here since good, practical documentation for Darwin is hard to find.

Contents

About Darwin

As Apple advertises, Mac OS X is built on a "secure, reliable, Open Source foundation", namely Darwin. See http://www.apple.com/opensource/ for more information.

We want to use this system. There are a couple of reasons why Darwin is great:

  • It can read and write HFS+ Journaled natively
  • Mac and Apple TV users are familiar with the workings of the system
  • There is lots of Open Source applications available, including a graphical X desktop
  • Can be used e.g., for embedded applications
  • Can be legally changed and re-distributed in accordance with APSL

Apple has been publishing installer ISOs at each major release so far. We hope that they will be continuing this practice!

Darwin in itself is a fully usable, command-line operating system. It provides the highest level of compatibility with Mac OS X through the common file systems and network services. Also, a lot of Mac knowledge can be directly applied to Darwin. This makes Darwin preferable over other operating systems (such as BSD or Linux) in Mac-centric environments.

Possible uses include:

  • Rescue OS X based devices (such as the Apple TV)
  • Build OS X compatible gadgets using Darwin as an embedded OS
  • Experimentation

Darwin-related community projects

Initially, there was large interest in Darwin, but as time progressed, the community lost interest (due to reasons that shall not be evaluated here). However, with the switch of Mac OS to Intel, there seems to be a lot of interest of the community again, but mainly focused on Mac OS X rather than Darwin itself.

Mac OS Forge

Mac OS Forge, hosted by Apple, is where Kernel (xnu), Launchd, and other parts of Darwin live.

OpenDarwin

Unfortunately, this project closed due to a perceived "lack of interest" just when it became real interesting due to the move to Intel.

Project was launched by bbraun, a former Apple employee who today insists that this project is dead.

OpenDarwin is not the same as Darwin (since unlike OpenDarwin, Darwin is alive). However, Darwin itself contains references to "OpenDarwin". For example, /etc/rc.cdrom identifies itself as "OpenDarwin install script". Oh well.

GNU/Darwin

Tries to build a complete desktop-oriented, general-purpose distribution on Darwin.

Fink

A collection of Open Source software for Darwin. It is claimed that they also host pre-compiled, ready-made binaries for Intel, however the URLs of those are hard to impossible to find on the site.

Think of Fink as "debian on Darwin". This uses the .deb format and the dpkg tools. There is even a Mac application called "Fink Commander" that is very similar to synaptic.

Project was launched by Christoph Pfisterer (later rEFIt), now working for Google.

DarwinPorts

MacPorts is the successor to DarwinPorts

MacPorts

Describes itself as "the project previously known as DarwinPorts". Hosted by Apple, this seems to be actively developed (Google Summer of Code 2007).

Think of MacPorts as "Gentoo on Darwin". There is no build server yet, which means that there are no pre-built binaries and you have to build everything yourself.

"Pure Darwin on x86"

Maybe a new Project "PureDarwinX86" should be started. It would focus on making pure Darwin usable on generic x86 (Intel) machines with as few changes to Apple's published Open Source code as possible. The goal of the project would be to maintain Darwin as a usable operating system, and to provide support and third-party applications for it.

Please add your name if your are interested in starting PureDarwinX86 or if you know someone who might be.

  • Contact: vmlemon
  • "I have a server colocated in a datacenter in Michigan"... "willing to donate these resources indefinitely": Benjamin

Purpose of this page

The first goal will be to install Darwin on a USB drive and boot a generic PC from there. This serves as a starting point for further projects based on Darwin.

Please note that this page is about 100% legitimate uses of the Darwin Open Source system only.

Minimal hardware requirements for darwinx86-801.iso

Found out by experimentation. Please add.

Processor

SSE2 and SSE3 are NOT required since Darwin 8.0.1 ISO boots fine on a Celeron 400 MHz machine from 1999 with a PIIX4.

(However, this system requires "platform=X86PC" because it otherwise stalls with an ACPI error message.)

Hard Disk

The Darwin installer puts 1.44 GB on disk. There is no apparent way to select less software in the installer. This is far more than what is needed for a minimal Darwin system.

Booting darwinx86-801.iso on a PC

Booting Darwin CD from IDE (works)

This is on a i915 chipset, DVD drive attached to IDE:

IOATAController device blocking bus
AppleIntelPIIXPATA: ICH6 ATA/100 (CMD 0x1f0, CTR 0x3f4, IRQ 14 BM 0xffa0) 
Still waiting for root device
Still waiting for root device
Still waiting for root device

Changing the DVD drive jumper from cable select to Master solved this issue.

It boots up and asks where to install Darwin.

So in principle, darwinx86-801.iso contains a system that is capable of running on a generic PC.

Booting Darwin CD from USB (works)

The same darwinx86-801.iso also boots fine when the DVD drive is connected to the USB bus using a IDE2USB adapter.

So in fact darwinx86-801.iso contains a system that is capable of running on a generic PC from USB.

Can we turn this into a USB "bootstick"?

Booting Darwin CD into single user mode (works)

By default, the Darwin CD boots into a installer. However by using "-s" at the boot prompt, we can boot into "single user mode", which allows us to issue commands on the command line.

Installing darwinx86-801.iso on a PC

Now that we have booted darwinx86-801.iso, let's install it.

Trying to install Darwin to attached USB drive (fails)

Booting Darwin CD as described above, with plugged-in USB drive gives:

USBF: AppleUSBEHCI[0xc181b800]::Found a transaction past the completion deadline on bus 253, timing out!
USBF: AppleUSBEHCI[0xc181b800]::Found a transaction past the completion deadline on bus 253, timing out!
USBF: AppleUSBEHCI[0xc181b800]::Found a transaction which hasn't moved in 5 seconds on bus 253, timing out!

Apparently this is a Darwin bug. Please note here if otherwise.

Installing Darwin to attached IDE drive (works)

As above, but this time the disk is on the IDE bus.

.root.tar.bz2 files

During installation, a lot of .root.tar.bz2 files are uncompressed.

So the installer doesn't actually clone the system that is used to boot the CD, but uses the compressed files. Are they different?

There is no apparent way to determine what gets installed. So We are getting a lot of stuff that is not necessary for a bare bones installation, such as gcc.

What is the minimum configuration of .root.tar.bz2 files necessary?

Updating mkext cache

Wouldn't this be done at next boot anyway?

Personalization

  • Installer asks for a root password
  • Installer asks for a computer name (Bonjour hostname)

Booting into installed Darwin from IDE (works)

Fixing boot issue

If booted without any arguments, the boot fails. However, by entering

rd=disk0s1

Darwin fully boots into a login prompt.

The following procedure fixes the boot issue permanently:

mcedit /Library/Preferences/SystemConfiguration/com.apple.Boot.plist
# edit Boot.plist, remove "Boot Device" entry
reboot

USB issue (fixed)

The installed Darwin seems to fail recognizing any USB devices

kextstat | grep USB
com.apple.iokit.IOUSBFamily (2.2.0) 
com.apple.driver.AppleUSBUHCI (2.2.0) 
com.apple.driver.AppleUSBEHCI (2.2.0)
com.apple.driver.AppleUSBHub (2.2.0) 

Trying to load IOUSBFamily.kext says "check ownership and permissions".

Apparently this is a Darwin bug of the installer. Please note here if otherwise.

So permissions need to be repaired. However, since there is no /Libaray/Receipts and no diskutil in Darwin, we need to do this manually

chmod -R 755 /System/Library/Extensions
chown -R 0:0 /System/Library/Extensions
touch /System/Library/Extensions
reboot

This fixes the USB issue. An USB drive is now correctly recognized as /dev/disk1s, it is not automatically mounted however.

Mounting HFS+ (Journaled) USB drive (works)

 mkdir /Volumes/Test
 mount -t hfs /dev/disk1s1 /Volumes/Test

 or

 mount_hfs /dev/disk1s1 /Volumne/Test

Booting into installed Darwin from USB (works)

Good news of the year!

The very same hard disk that boots from IDE also boots when connected with a IDE2USB cable. Yay!

Note that in addition to the USB kexts above, this time there are additional ones loaded:

kextstat | grep USB
AppleUSBComposite (2.2.0)
IOUSBStorageClass (1.4.0)
IOUSBUserClient (2.2.0)


Exploring Darwin

Enabling sshd

killall sshd
ssh-keygen -t rsa -f /etc/ssh_host_rsa_key # do NOT use passphrase
ssh-keygen -t rsa1 -f /etc/ssh_host_key # do NOT use passphrase
sshd

Edit /System/Library/LaunchDaemons/ssh.plist to launch sshd on each start:

       <key>Disabled</key>
       <false/>

Enabling apache2

apache2 is installed in /opt by default. You can launch it with

/opt/apache2/bin/apachectl start

It is configured to listen on port 8080 by default. So you can access the machine via http://darwin.local:8080/ for example (if your computer name is set to "Dawin").

/etc/hostconfig

Various services are supposed to be automatically started by editing /etc/hostconfig, including

  • AFP
  • Webserver - This does NOT appear to work on Darwin. Is this a leftover from Mac OS X?
  • SMB Server
  • Spotlight - Is this a leftover from Mac OS X and disfunctional on Darwin?

Stuff that is in Darwin but not in Mac OS X

  • /usr/local/bin: Optional binaries
  • /usr/local/SecurityPieces
  • /usr/local/OpenSourceVersions: Contains a .plist file each for the Open Source parts in Darwin. Is the format of this file documented?
    • OpenSourceProject
    • OpenSourceVersion
    • OpenSourceURL
    • OpenSourceSHA1
    • OpenSourceImportDate
    • OpenSourceModifications
    • OpenSourceLicense
    • OpenSourceLicenseFile
  • /usr/local/OpenSourceLicenses: Contains the licenses of the Open Source parts in Darwin.
  • /usr/include: Header files

Unpacking Installer packages

Mac software often comes as .pkg Installer packages.

Here is how to unpack these in Darwin:

gunzip -c *.pkg/Contents/Archive.pax.gz | pax -r

Mounting dmg files

According to this (to be tested):

/usr/libexec/vndevice attach /dev/vn0 my.dmg
mount -t hfs /dev/vn0 /mnt/

Installing third-party software

There is third-party software available for Darwin (even a OpenGL-accellerated X.org server, and graphical applications). However, getting this software in Darwin is not as easy as getting software in Mac OS (yet).

Installing Fink (fails)

Fink hosts precompiled software for Darwinx86. So let's get some. Not so easy actually, since they seem to have designed the fink installation procedure with Mac OS in mind. It does run on Darwin proper, doesn't it?

  • Get Fink dmg
  • Mount dmg as described above
  • Extract .pkg contents as described above
  • Move sw/ to /sw

Unfortunately, most software from /sw/usr/bin fails: "Bad executable (or shared library)".

Further investigation required. Please note any solution here.

Debugging why Fink binaries refuse to run on Darwin 8.0.1

With the help of #fink:

  • Installed cctools-* again, it contains otool (a debugging tool)
  • otool -lv /sw/bin/dpkg and otool -hv /sw/bin/dpkg (output)
  • ktrace and kdump
darwin:~ root# ktrace /sw/bin/dpkg
ktrace: exec of '/sw/bin/dpkg' failed: Bad executable (or shared library)
darwin:~ root# kdump 
    96 ktrace   RET   ktrace 0
    96 ktrace   CALL  execve(0xbffffd43,0xbffffcec,0)
    96 ktrace   NAMI  "/sw/bin/dpkg"
    96 ktrace   RET   execve -1 errno 85 Bad executable (or shared library)
    96 ktrace   CALL  stat(0xbffffd43,0xbffffcec)
    96 ktrace   NAMI  "/sw/bin/dpkg"
    96 ktrace   RET   stat 0
    96 ktrace   CALL  write(0x2,0x8,0)
    96 ktrace   GIO   fd 2 wrote 8 bytes
       "ktrace: "
    96 ktrace   RET   write 8
    96 ktrace   CALL  write(0x2,0x1d,0)
    96 ktrace   GIO   fd 2 wrote 29 bytes
       "exec of '/sw/bin/dpkg' failed"
    96 ktrace   RET   write 29/0x1d
    96 ktrace   CALL  write(0x2,0x2,0)
    96 ktrace   GIO   fd 2 wrote 2 bytes
       ": "
    96 ktrace   RET   write 2
    96 ktrace   CALL  write(0x2,0x23,0)
    96 ktrace   GIO   fd 2 wrote 35 bytes
       "Bad executable (or shared library)
       "
    96 ktrace   RET   write 35/0x23
    96 ktrace   CALL  exit(0x1)
darwin:~ root# 

vasi: "ktrace can only trace userland stuff... the fact that it traced almost nothing would seem to indicate that the kernel is where the problem is seen. You can see that it calls 'execve' which fails. syscall fails => kernel problem"

Can it be that the latest Darwin ISO for x86 that Apple distributes refuses to run even the simplest CLI binaries built for Mac OS X 10.4.x Intel?

Apparently this is a Darwin bug. Please note here if otherwise. Maybe related to this?

Installing software from GNU-Darwin (fails)

GNU-Darwin hosts pre-compiled software for Darwinx86 as well. (Looking at their repository, most packages appear to be five years old however.)

curl http://www.gnu-darwin.org/packages/x86/www/wget-1.8.2_2.tgz -o wget-1.8.2_2.tgz
tar xfvz wget-1.8.2_2.tgz
./bin/wget

Bus error

Further investigation required. Please note any solution here.

Shrinking Darwin

Let's remove things that are not required for (minimal) operation

rm -rf /usr/include (0.2 GB) # header files
find / -type f | grep "\.h$" | xargs -I {} rm -f {} # more header files
rm -rf /opt/apache /usr/libexec/httpd/ # apache
rm -rf /usr/local/ # (0.3 GB) apparently all optional stuff
rm -rf /usr/share/man # (0.1 GB) documentation

It's probably better to do a "bottom-up" approach and install only those packages that we really want.

.root.tar.bz2 "Uninstaller" script

Since there appears to be no "uninstaller" for Darwin's .root.tar.bz2 packages, I wrote one.

It takes two arguments:

  • path/to/root/partition (e.g. /Volumes/Darwin - the files contained in the .root.tar.bz2 are deleted from this volume
  • path/to/package.root.tar.bz2 - the .root.tar.bz2 whose files you want to delete from the installed system
#!/bin/sh

#
# Package deleter script for Darwin
# GPL
# 0.1
#

PACK=$2
PART=$1

function usage {
    echo " "
    echo "Package deleter script for Darwin"
    echo " "
    echo "Usage: $0 path/to/root/partition path/to/package.root.tar.bz2"
    echo " "
    exit 1
}

# Check for correct number of arguments
if [  "x$2" == "x" ] ; then
    usage
fi

# Exit if file is not bzip2
file "$PACK" | grep bzip2 >/dev/null || usage

# Exit if there is no mach_kernel
file "$PART/mach_kernel" | grep Mach-O >/dev/null || usage

FILES=$( tar -tjvf ${PACK} | sort -r | awk '{print $6}' | sed "s|^\.\/|$PART\/|" )

f=0
d=0

for FILE in $FILES; do
  rm -f "$FILE" 2>/dev/null && let "f++"
done

for FILE in $FILES; do
  rmdir -p "$FILE" 2>/dev/null && let "d++"
done

echo "$f files and $d directories deleted"

Removing the following packages brings Darwin down to around 450 MB: apache- apache2- apache_mod_dav- apache_mod_hfs_apple-* apache_mod_perl-* apache_mod_php-* apache_mod_ssl-* autoconf-* automake-* bison-* bsdmake-* bsdmanpages-* cctools-* cctools_ofiles-* cups-* cups_ppc-* cvs-* cvs_wrapped-* cxxfilt-* developer_cmds-* diffstat-* distcc-* doc_cmds-* efax-* emacs-* enscript-* fetchmail-* flex-* gcc-* gcc_os-* gcc_os_35-* gcc_select-* gccfast-* gdb-* gimp_print-* glibtool-* gm4-* gnudiff-* gnumake-* gnuserv-* gperf-* groff-* graphviz-* headerdoc-* iodbc-* jam-* lukemftp-* lukemftpd-* mailman-* man-* modemccl-* net_snmp-* netcat-* objc4-* patch_cmds-* pb_makefiles-* pbx_jamfiles-* portmap-* postfix-* ppp-* procmail-* project_makefiles-* python-* rcs-* ruby-* samba-* screen-* smb-* srm-* stmalloc-* tcl-* tcpdump-* tcsh-* texi2html-* texinfo-* tidy-* vim-* webdavfs-* yacc-* zsh-*

Can perl-* be safely removed?

Installing "Darwin nano" on bootable USB drive

This is not working yet. Any help is greatly appreciated. From the experiments above it is apparent that this should work.

Plan

# Get Darwin 8.0.1 ISO for i386 from Apple
# Boot it into single user mode (see above). From booted Darwin, do:
# Prepare USB stick by formatting it as HFS+ (Journaled) and enabling permissions
# Copy /usr /bin /sbin /System /Library /private /cores /mach_kernel from ISO to USB drive
# (maybe need to use the .root.tar.bz2 files instead, see above)
# Bless USB stick and set partition active
# Change Boot.plist 
# Fix permissions and touch Extensions
# Boot USB stick

This easily fits on a 512 MB USB stick, and probably can be slimmed down further (e.g. for embedded applications).

This does boot, but as soon as the kernel is supposed to appear, it reboots the PC (even before printing a kernel panic).


Minimal number of packages to boot the Darwin kernel

What are the minimum required packages that need to be installed in order to boot the Darwin kernel and to bring up a minimal shell?

# Please collect here
xnu-792.root.tar.bz2 # contains the kernel
objc4-266.root.tar.bz2 # can't log in otherwise (might not be required for -s)
# ...

To look what is inside:

tar -tjvf xnu-792.root.tar.bz2

List of Darwin files

Darwin versions

  • Darwin 8.0.1 = Mac OS X 10.4.x (what this page focuses on)
  • Darwin 7.0.1 = Mac OS X 10.3.x
  • Darwin 6.0.2 = Mac OS X 10.2.x
  • Darwin 1.4.1 = Mac OS X 10.1.x
  • Darwin 1.3.1 = Mac OS X 10.0.x
  • Darwin 1.2.1 = Mac OS X Public Beta
  • Darwin 1.0.2 = Developer Preview 4

Darwin install script

To be reviewed and to be re-used. Despite the fact that it says "OpenDarwin", it is from Darwin proper. Apparently this is a Darwin bug. Please note here if otherwise.

#!/bin/sh
# OpenDarwin install script
# $Id: rc.cdrom,v 1.30 2005/04/28 20:06:46 kevin Exp $

PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/libexec:/etc:/private/etc ; export PATH
ARCH=`arch`
TARGET_MOUNT=/mnt
AVAIL_SHELLS="sh tcsh csh bash zsh"
T_UID_DEFAULT=1000
T_GID_DEFAULT=1000

abort () {
	echo "Aborting the installation"
	echo "Press enter to reboot"
	read REBOOT
	shutdown -r now
}

umount_target_disk () {        
	umount -f ${ROOTPART}
}

finishup () {

	echo "Installation of the base system is now complete."
	echo "You may: "
	until [ ! : ]
	do
		echo "1) add a user to the new system"
		echo "2) Reboot"
		echo "3) Spawn a shell"
		echo -n "Your Choice: "
		read CHOICE
		case ${CHOICE} in
			1) add_user ;;
			2) umount_target_disk
			   shutdown -r now
			   break ;;
			3) umount_target_disk
			   /bin/sh
			   break ;;
		esac
	done
	
}

add_user () {
	
	# a few helper vars
	# make T_PW and T_PW_2 not equal
	ADMIN_USER=0	
	SHELL_VALID=0
	T_PW=0
	T_PW_2=1
	

	echo ""
	echo -n "Username: "
	read T_USERNAME
	echo -n "Realname: "
	read T_REALNAME
	echo -n "UID (default: ${T_UID_DEFAULT}): "
	read T_UID
	echo -n "GID (default: ${T_GID_DEFAULT}): "
	read T_GID
	
	if [ "$T_UID" == "" ]; then
		T_UID=${T_UID_DEFAULT}
	fi
	
	if [ "$T_GID" == "" ]; then
		T_GID=${T_GID_DEFAULT}
	fi

    	until [ "$SHELL_VALID" == "1" ]; do
		echo -n "Available shells: "
		for shell in ${AVAIL_SHELLS} 
		do
			echo -n "${shell} "
		done
		echo ""
		echo -n "Shell: "
		read T_SHELL;

 	      	for shell in ${AVAIL_SHELLS}
       		do
       			if [ "$T_SHELL" == "$shell" ]; then
       			SHELL_VALID=1
       			fi
       		done
    	done

    	echo -n "Home directory (default: /Users/${T_USERNAME}): "
    	read T_HOMEDIR;

    	if [ "$T_HOMEDIR" == "" ]; then
		T_HOMEDIR=/Users/${T_USERNAME}
    	fi

	echo -n "Add ${T_USERNAME} to the admin group? (yes/no): "
	read CHOICE;

	if [ "$CHOICE" == "yes" ]; then
		ADMIN_USER=1
	fi

    	while [ 1 ]; do
		T_PW=`openssl passwd`
		if [ ${?} == "0" ]; then
			break
    		fi
    	done

	echo ""
	echo "Username: ${T_USERNAME}"
	echo "Realname: ${T_REALNAME}"
	echo "UID: ${T_UID}"
	echo "GID: ${T_GID}"
	echo "Shell: ${T_SHELL}"
	echo "Home: ${T_HOMEDIR}"
	echo ""
	echo -n "Add (yes/no): "
	read CHOICE

	if [ "$CHOICE" == "yes" ]; then
		nicl -raw ${TARGET_MOUNT}/var/db/netinfo/local.nidb -create /users/${T_USERNAME} passwd ${T_PW}
		nicl -raw ${TARGET_MOUNT}/var/db/netinfo/local.nidb -create /users/${T_USERNAME} realname ${REALNAME}
		nicl -raw ${TARGET_MOUNT}/var/db/netinfo/local.nidb -create /users/${T_USERNAME} uid ${T_UID}
		nicl -raw ${TARGET_MOUNT}/var/db/netinfo/local.nidb -create /users/${T_USERNAME} gid ${T_GID}
		nicl -raw ${TARGET_MOUNT}/var/db/netinfo/local.nidb -create /users/${T_USERNAME} shell /bin/${T_SHELL}
		nicl -raw ${TARGET_MOUNT}/var/db/netinfo/local.nidb -create /users/${T_USERNAME} home ${T_HOMEDIR}
		nicl -raw ${TARGET_MOUNT}/var/db/netinfo/local.nidb -create /groups/${T_USERNAME} name ${T_USERNAME}
		nicl -raw ${TARGET_MOUNT}/var/db/netinfo/local.nidb -create /groups/${T_USERNAME} gid ${T_GID}
		nicl -raw ${TARGET_MOUNT}/var/db/netinfo/local.nidb -create /groups/${T_USERNAME} passwd "*"

		if [ "$ADMIN_USER" == "1" ]; then
			nicl -raw ${TARGET_MOUNT}/var/db/netinfo/local.nidb -create /groups/admin users ${T_USERNAME}
		fi

		mkdir -p ${TARGET_MOUNT}/${T_HOMEDIR}
		chown ${T_UID}:${T_GID} ${TARGET_MOUNT}/${T_HOMEDIR}
		echo "User ${T_USERNAME} created"
		echo ""
	
		if [ "$T_UID" == "$T_UID_DEFAULT" ]; then
			T_UID_DEFAULT=$(($T_UID_DEFAULT+1))
			T_GID_DEFAULT=$(($T_GID_DEFAULT+1))
		fi
	fi
}

# and a way to iterate through the list of available services
# with a method to initialize them
enable_various_services() {

	echo "Following services can be enabled: "
	chroot ${TARGET_MOUNT} /sbin/service --list

	while [ 1 ]; do
		echo -n "Enter service to enabled ('quit' to abort, list to print list): "
		read SERVICE
		if [ "$SERVICE" == "quit" ]; then
			break
		fi
		if [ "$SERVICE" == "list" ]; then
			chroot ${TARGET_MOUNT} /sbin/service --list
		else
			echo "Enabling service: ${SERVICE}" 
			sed -e 's/disable.*=.*yes/disable = no/' < ${TARGET_MOUNT}/etc/xinetd.d/${SERVICE} > ${TARGET_MOUNT}/etc/xinetd.d/${SERVICE}.new
			mv ${TARGET_MOUNT}/etc/xinetd.d/${SERVICE}.new ${TARGET_MOUNT}/etc/xinetd.d/${SERVICE}
		fi
	done
}

choose_filesystem_type () {
	while [ 1 ]; do
		echo "Choose the filesystem type from the following."
		echo "  hfs) HFS+ (journaled) filesystem"
		echo "  ufs) UFS filesystem"
		echo -n "Filesystem type: "
                read FILESYSTEMTYPE
                if [ "$FILESYSTEMTYPE" == "hfs" -o "$FILESYSTEMTYPE" == "ufs" ]; then
                        break
                fi
	done
}

# This function will nuke the whole disk and create the 0xAB and 0xA8
# partitions.  $INSTALLDEV and $RAWINSTDEV need to be set to the
# device to nuke, and the corresponding raw device.
partition_disk () {
	# needs help on ppc
	echo "Partitioning disk ${INSTALLDEV} using filesystem type ${FILESYSTEMTYPE}"
	echo "Warning: this will destroy all data on the disk!"
	echo -n "Continue? (y/n) "
	read CONT

	if [ "${CONT}" == "y" -o "${CONT}" == "yes" ]; then
		fdisk -i -y -a ${FILESYSTEMTYPE} ${RAWINSTDEV}
	else
		abort
	fi

}

# This will look for partitions on the selected disk, and 
# allow the user to select the 0xA8 partitions to use.
# $INSTALLDEV needs to be set to the device to look for,
# and $ROOTPART will be set to the chosen value upon return.
use_partitions () {
	echo ""
	PARTS=`ls -1 ${INSTALLDEV}s*`

	echo "The following partitions are available:"
	for devs in ${PARTS}
	do
		echo ${devs}
	done

	ROOTPART=""
	until [[ ${ROOTPART} != "" && -b ${ROOTPART} ]]
	do
		echo "Which will be the root partition?"
		read ROOTPART
	done

	echo "Using: "
	echo "${ROOTPART} as the root partition"

}

# This just runs fdisk interactivly on the chosen raw install device
run_fdisk () {
	echo "Starting fdisk"
	if [ "${ARCH}" == "i386" ]; then
		fdisk -e ${RAWINSTDEV}
	elif [ "${ARCH}" == "ppc" ]; then
		/usr/sbin/pdisk
	fi
}

install_booter () {
	if [ "${ARCH}" == "i386" ]; then
		cd /
		umount -f ${ROOTPART}
		RAWROOTPART=`echo ${ROOTPART} | sed 's/disk/rdisk/'`
		if [ "${FILESYSTEMTYPE}" == "ufs" ]; then
			dd if=/usr/standalone/i386/boot1u of=${RAWROOTPART} bs=512 count=15 >>/dev/null 2>&1
		elif [ "${FILESYSTEMTYPE}" == "hfs" ]; then
			dd if=/usr/standalone/i386/boot1h of=${RAWROOTPART} bs=512 count=1 >>/dev/null 2>&1
			/usr/sbin/startupfiletool ${RAWROOTPART} /usr/standalone/i386/boot >/dev/null 2>&1
			bless -device ${ROOTPART} -setBoot >/dev/null 2>&1
		fi
		mount -t ${FILESYSTEMTYPE} ${ROOTPART} ${TARGET_MOUNT}
		bless -mount ${TARGET_MOUNT} -setBoot >/dev/null 2>&1
		cd ${TARGET_MOUNT}
	elif [ "${ARCH}" == "ppc" ]; then
		bless -folder ${TARGET_MOUNT}/System/Library/CoreServices -folder9 ${TARGET_MOUNT}/System/Library/CoreServices -bootinfo ${TARGET_MOUNT}/usr/standalone/ppc/bootx.bootinfo -setBoot
	fi
}

install_packages () {
	VOLUMENAME="Darwin"

	echo "WARNING: answering "yes" here will destroy all data on the partition"
	until [ ! : ]
	do
		echo -n "Would you like to do a clean install? (yes/no)"
		read ANSWER
		if [ "$ANSWER" == "yes" ]; then
		echo -n "Desired Volumename: "
		read VOLUMENAME
			
		echo "Creating ${FILESYSTEMTYPE} Filesystem on ${ROOTPART}"
		if [ "${FILESYSTEMTYPE}" == "hfs" ]; then
			newfs_hfs -J -v "${VOLUMENAME}" ${ROOTPART} >> /dev/null 2>&1
			break
		elif [ "${FILESYSTEMTYPE}" == "ufs" ]; then
			newfs -v "${VOLUMENAME}" ${ROOTPART} >> /dev/null 2>&1
			break
		else
			echo "error: nknown filesystem type: $FILESYSTEMTYPE"
			abort
		fi
		elif [ "$ANSWER" == "no" ]; then
			break
		fi
	done
	mount -t ${FILESYSTEMTYPE} ${ROOTPART} ${TARGET_MOUNT}
	cd ${TARGET_MOUNT}
	echo "Installing packages on ${ROOTPART}"
	for f in /System/Installation/Packages_${ARCH}/files-*.tar.bz2 \
		 /System/Installation/Packages_${ARCH}/*-*.tar.bz2 \
		 /System/Installation/BinaryDrivers_${ARCH}/*-*.tar.bz2 ; do
		echo "Uncompressing $(basename $f)"
		tar xjpf $f 2>/dev/null
		if [ "$?" != "0" ]; then
			echo "warning: error during extraction"
		fi
	done

	cd /
}

main() {

	if [ -f "/Release Notes.txt" ]; then
		echo ""
		echo "Welcome to the installation of" `grep 'Darwin [0-9.-]*' /Release\ Notes.txt | head -1 | awk '{print $1" "$2}'`
		echo ""
	fi
	if [ -f "/Important Notice.txt" ]; then
		cat "/Important Notice.txt"
	fi

	# Get the device the user wants to install onto.
	INSTALLDEV="novalue"
	until [[ ${INSTALLDEV} != "" && -b ${INSTALLDEV} ]]
	do
		echo "The following devices are available for installation:"
		until [[ ! -z "${FOO}" ]]
		do
			FOO=`iofindwholemedia`
		done
		iofindwholemedia
		echo "Enter 'shell' to drop into a shell"
		echo -n "Which device would you like to install Darwin onto? "
		read INSTALLDEV
	
		if [ "${INSTALLDEV}" == "shell" ]; then
			exec /bin/sh
		fi
	
		INSTALLDEV=`iofindwholemedia ${INSTALLDEV}`

		if [ ! -b "${INSTALLDEV}" ]; then
			echo ""
			echo "${INSTALLDEV} doesn't exist, please enter one of the listed devices."
			echo ""
		fi
	done
	
	RAWINSTDEV=`echo ${INSTALLDEV} | sed 's/disk/rdisk/'`

	
	if [ "${ARCH}" == "i386" ]; then 
		if fdisk -t ${RAWINSTDEV} ; then
			echo ""
			echo "For partitioning the disk, you have the following choices:"
			until [ ! : ]
			do
				echo "1) Auto-partition the disk (Destroys all disk contents)"
				echo "2) Manually partition the disk using fdisk"
				echo "3) Use existing partitions"
				echo -n "Choice: "
				read ANSWER
				case ${ANSWER} in
					1) choose_filesystem_type
					partition_disk
				   	# Don't ask which to use, since we already know.
				   	ROOTPART="${INSTALLDEV}s1"
				   	break
				   	;;
					2) run_fdisk
				   	use_partitions
					choose_filesystem_type
				   	break
				   	;;
					3) use_partitions
					choose_filesystem_type
				   	break
				   	;;
				esac
			done
		else
			echo ""
			echo "For partitioning the disk, you have the following choices:"
			until [ ! : ]
			do
				echo "1) Auto-partition the disk (Destroys all disk contents)"
				echo "2) Manually partition the disk using fdisk"
				echo -n "Choice: "
				read ANSWER
				case ${ANSWER} in
					1) partition_disk
				   	# Don't ask which to use, since we already know.
				   	ROOTPART="${INSTALLDEV}s1"
				   	break
				   	;;
					2) run_fdisk
				   	use_partitions
				   	break
				   	;;
				esac
			done
		fi
	elif [ "${ARCH}" == "ppc" ]; then
		until [ ! : ]
		do
			FILESYSTEMTYPE="hfs"
			echo "Which (Apple_HFS) partition would you like to install into: "
			pdisk --list ${INSTALLDEV} 2> /dev/null
			slice=""
			until [[ "$slice" != "" && -b ${INSTALLDEV}s${slice} ]]
			do
				echo -n "Your choice: "
				read slice
			done
			ROOTPART="${INSTALLDEV}s${slice}"
			break
		done
	fi
	install_packages
	install_booter
	echo 'LANGUAGE=English' > ${TARGET_MOUNT}/var/log/CDIS.custom
	echo "Updating mkext cache"
	export TMPDIR=${TARGET_MOUNT}/private/tmp
	kextcache -K ${TARGET_MOUNT}/mach_kernel -a ${ARCH} -m ${TARGET_MOUNT}/System/Library/Extensions.mkext ${TARGET_MOUNT}/System/Library/Extensions 2>/dev/null
	export -n TMPDIR

	echo "Creating root user"
	
	# loop until password was entered the same twice
	while [ 1 ]; do
	ROOT_PW=`openssl passwd`
	if [ ${?} == "0" ]; then
		break
        fi
    	done

   	nicl -raw ${TARGET_MOUNT}/var/db/netinfo/local.nidb -create /users/root passwd ${ROOT_PW}

	echo -n "Set computer name (Bonjour hostname): "
	read BONJOUR
	configd
	echo "$BONJOUR" | chroot ${TARGET_MOUNT} scutil --set ComputerName
	echo "$BONJOUR" | tr A-Z a-z | sed -e 's/[^a-z0-9_-][^a-z0-9_-]*/-/g' | chroot ${TARGET_MOUNT} scutil --set LocalHostName
	
	echo "Configuring emacs"
	chroot ${TARGET_MOUNT} /usr/libexec/dumpemacs > /dev/null 2>&1

	finishup
}
	
# Set the erase character properly
# This is only for telnet consoles...
#stty erase �

# Ignore ^C
#trap "" 2

main

exit

Priority questions

If you know the answer to any of these, please post it here.

  • What is required (step-by-step) to get the latest published kernel running on a darwinx86_801.iso based system?
  • Will the open source kernels continue to run on, e.g., Celeron 400 MHz machines (as the kernel from darwinx86_801.iso does? (This is very important e.g., for embedded devices development. Think AMD Geode)
  • Is there a way to patch the kernel on darwinx86_801.iso so that it is compatible with the Mach-O header specification of Mac OS X (Intel), enabling it to run Mac CLI applications?

Bug reporting

Please do not flood Apple with bug reports. It is more likely that Darwin bugs get addressed properly if bug reports are well-written and thorougly documented. Let's provide Apple with high-quality bug reports in their preferred format through their official channels, then it is most likely that they will be considered.

Apple mailing lists