References on the OS X boot sequence
Notes on the OS X boot sequence
Here is the sequence of operations at Mac OS X startup:
(extracted from the above references)
0) Press power button
1) The BootROM firmware is run. It does the following:
1.1) POST (Power-On Self Test) initializes some hardware interfaces
and tests the RAM. If all is well, plays the startup chime.
If some problem is found, gives an indication via beeps:
see http://docs.info.apple.com/article.html?artnum=58442
1.2) Open Firmware initializes the rest of the hardware,
builds the initial device tree (a hierarchical representation
of devices associated with the computer), and selects the
operating system to use.
2) When BootROM (or the user) selects Mac OS X as the operating system
to boot, control passes to the BootX booter
(located in /System/Library/CoreServices).
Here are the main functions called by BootX, with a short explanation
for the parts where I have some understanding
(from looking at the source code):
The entry point is defined in the variable StartTVector to be the function
Start() which calls the function Main() which calls the following sequence
of functions. (StartTVector is defined to be the entry point via the -e
option to 'ld' in the Makefile.)
2.1) InitEverything()
2.2) GetBootPaths()
- find the kernel on the hard disk
2.3) DrawSplashScreen(0)
- draws the grey Apple
- initializes the indicator (that spins to show activity)
2.4) LoadFile(BootFile)
- reads the kernel from disk
- each read operation makes the indicator spin
(this is true of the following two steps as well
- the indicator is made to spin every time the function
'Read()' is called)
2.5) DecodeKernel()
2.6) LoadDrivers(RootDir)
2.7) DrawSplashScreen(1)
- erases the grey apple by drawing a grey rectangle over top of it
2.8) SetUpBootArgs()
- sets up the command-line arguments that will be passed
to the /etc/rc script
2.9) CallKernel()
- starts the kernel running
- verbose mode messages start arriving
3) CallKernel() invokes machine_startup() (xnu/osfmk/ppc/model_dep.c)
which calls setup_main() (xnu/osfmk/kern/startup.c)
which calls start_kernel_threads() (xnu/osfmk/kern/startup.c)
which calls bsd_init() (xnu/bsd/kern/bsd_init.c)
which hand-crafts process #0, naming it 'kernel_task'
and then calls bsd_utaskbootstrap() (xnu/bsd/kern/bsd_init.c)
which creates process #1 (via a call to cloneproc())
and then calls act_set_astbsd() for process #1.
This results in a call to bsd_ast() (xnu/bsd/kern/kern_sig.c)
which calls bsdinit_task() (xnu/bsd/kern/bsd_init.c)
which assigns the name 'init' to process #1
and then calls load_init_program() (xnu/bsd/kern/kern_exec.c)
which does an exec of /sbin/mach_init (without doing a fork).
The code for 'mach_init' is in system_cmds/mach_init.tproj/bootstrap.c
mach_init forks and then the parent process (#1) does an exec
of /sbin/init.
The child process from the fork is process #2 and continues running
as mach_init.
So, process #1 is called 'init' for a short time while it is executing
kernel code, then it is '/sbin/mach_init', then it is '/sbin/init'
after the fork & exec.
Acknowledgements
Thanks to "JavaOSX" on the MacOSXHints forums for useful discussions.