system booting (PC)
Any system administrator worth their weight in silicon, knows that you need to understand how the booting process works. From the moment you press power until you are presented with the login prompt, a number of things will have occurred:
- Hardware Boot (POST)
- OS Loader and Master Boot Record
- Kernel Initialization
- Run Levels & Init Scripts
Note: Most of the information below has been obtained from my cpsc550 (system admin class), researching online, and man pages. For a quick intro on the booting process I would advise a 'man boot'.
Hardware Boot (POST)
When power is turned on or a reset occurs. The cpu has a hardwired address that it begins to load instructions out of nvram (none volitile ram) at address 0xFFF0. This program is referred to in the PC world as the bios ( basic input/output system ) and usually exists in memory space 0xF000 : 0xFFFF. Since there is not much room left on the runway, the first instruction usually consists of a jump back into lower bios memory. This nvram is also called CMOS memory which stands for "Complementary Metal Oxide Semiconductor". The bios program now conducts a POST ( Power on Self Test ) where it makes sure that the memory and other peripherals are there and functioning correctly. If there are errors at this point, your system lets you know this with a series of beep codes. If you check your motherboard manufacturer's website there are details to what these codes mean. A minimal set of instructions now exists in the bios to begin probing a set of system devices for bootable code. This bootable code should begin loading the OS.
OS Loader and Master Boot Record
Once the system has located a bootable device, in most cases your hard disk, it transfers control over to the first sector of that device a.k.a the Master Boot Record (MBR). In a PC this loader has some limitations due to the bios; the most notable is the fact that we need the boot program and partition table to exist in the first 512 bytes. The format of the MBR is as follows:
- 446 byte program code starts at 0x0000
- 64 byte partition table starts at 0x01be ( decimal 446)
- 2 byte signature of ( 0x55aa ) starts at 0x01fe ( decimal 510 )
This all sounds good in theory, but as a programmer I want to know a little more about the mysterious MBR. I remember when I was a youngster that boot sector virus's were prevalent. It makes sense to put one there, seeing as how the OS is not loaded and the system has no protection at this point. I believe that these have all but faded away since the internet has come along, providing a better medium of transport. In order to get a better look at the contents of the boot sector we can run the 'dd' command as root. If we specify 'if='dev/hda' and 'of=mbr_contents' and put a 'count' on it we should get what we are looking for. The 'count' part of the last instruction is important; without it you will attempt to read the whole disk. On a modern system you will generate a very large file in a few seconds. Once we have the these bytes we could make the contents into something that is a little more readable. For this I used the command 'hexdump mbr_contents > mbr_hexdump'. Here are the results from my debian machine.
0000000 ebfa 0120 01b5 494c 4f4c 0516 6b4c 413f
0000010 0000 0000 0fe8 404f b836 b836 8080 5560
0000020 13c0 b800 07c0 d08e 00bc fb08 5352 5606
0000030 8efc 31d8 60ed 00b8 b312 cd36 6110 0db0
0000040 68e8 b001 e80a 0163 4cb0 5ee8 6001 071e
0000050 fa80 75fe 8802 bbf2 0200 768a 891d 80d0
0000060 80e4 e030 0a78 103c 0673 46f6 401c 2c75
0000070 f288 8b66 187e 0966 74ff 5221 08b4 80b2
0000080 13cd 5572 9892 ba91 007f 6642 c031 e840
0000090 0071 3b66 b8bf 7401 e203 5aef 8a53 1e76
00000a0 1fbe e800 004b 99b4 8166 fc7f 494c 4f4c
00000b0 2775 685e 0880 3107 e8db 0035 fb75 06be
00000c0 8900 b9f7 000a a6f3 0d75 02b0 75ae 0608
00000d0 b055 e849 00d5 b4cb b09a e820 00cd bae8
00000e0 fe00 004e 0874 e8bc 6107 e960 ff60 ebf4
00000f0 66fd 66ad c009 0a74 0366 1046 04e8 8000
0000100 02c7 60c3 5555 5066 5306 016a 106a e689
0000110 f653 60c6 5874 c6f6 7420 bb14 55aa 41b4
0000120 13cd 0b72 fb81 aa55 0575 c1f6 7501 524a
0000130 b406 cd08 0713 5872 c051 06e9 e986 cf89
0000140 c159 08ea 4092 e183 f73f 93e1 448b 8b08
0000150 0a54 da39 3873 f3f7 f839 3277 e4c0 8606
0000160 92e0 f1f6 e208 d189 5a41 c688 06eb 5066
0000170 5859 e688 01b8 eb02 b402 5b42 05bd 6000
0000180 13cd 0f73 744d 3109 cdc0 6113 f1eb 40b4
0000190 46e9 88ff 1f64 648d 6110 c1c3 04c0 03e8
00001a0 c100 04c0 0f24 0427 14f0 6040 07bb b400
00001b0 cd0e 6110 00c3 6344 b836 b836 0000 fe00
00001c0 ffff fe05 ffff d222 0704 ca12 0023 0180
00001d0 0001 fe83 ffff 003f 0000 d1e3 0704 0000
00001e0 0000 0000 0000 0000 0000 0000 0000 0000
00001f0 0000 0000 0000 0000 0000 0000 0000 aa55
0000200 0000 0000 0000 0000 0000 0000 0000 0000
There are the aa55 bytes right before the 512 byte boundary ... Sweet! That means we found what we were looking for... but unless your hex op-code reading is better than mine... we still have a problem. My first thought was to take our original file and run it threw gdb (gnu debugger), but this turned out not to work at all. It just complains about it not being an executable file. Next I gave 'ndisasm' the NAS Disassembler a try. This one ate the whole file and spat back the nasm I was looking for. So let's see what the lilo MBR boot loader does:
Click here to have a look at the MBR assembly code.
Kernel Initialization
Once the kernel code has been located and control has been passed over to it, the kernel first initializes the devices through the device drivers on the system. Once this is complete the kernel creates its first process which is the scheduler or the swapper. This process is a kernel process called kswapd. The kernel then mounts the root file system and starts its first user process PID 1 called 'init' ( /sbin/init ). Init is often referred to as the mother of all processes. This can be verified by the reader by typing the command 'pstree'. When init loads it looks in '/etc/initab' for instructions on what to do. The inittab specifies the default run level for the system and calls another script passing that run level as an argument to the script '/etc/init.d/rc 6'. At this point you really should go check out the 'rc' script. It is a small script and the syntax is easy to read. To check what run level your system is in, run the 'runlevel' command. The last thing the inittab does on my system is start up a bunch of virtual consoles that I can access with 'ctr+alt+F1 through F6'.
Run Levels & Init Scripts
The scripts that actually start and stop the services on my system are located in ( /etc/rc[0-6].d ). Once you have looked at the '/etc/init.d/rc' script, you know that it gets past the run level and attempts to call Star and Kill scripts in the appropriate run level directory. My system default runlevel is 6 ( X-graphical mode ), so if I go into '/etc/rc6.d/' and do an 'ls -al' we will see that the files in this directory are nothing more then symbolic links back into ( /etc/init.d ). This is were all the real scripts reside. The run level directories are just there to provide a convenient mechanism to talk to these scripts. The conveniance comes from the way the links are named. They all have an 'S' or 'K' in front of them and then a number. If you go back and look at the ( /etc/init.d/rc ) script you can see that the 'S' starts a service and the 'K' will kill a service. The numbers allow you to specify the order in which the system will execute the scripts. This will allow a service that relies on another service to be started after the service that it requires.
So if we would like to add a new service to be started at runlevel 6 we would do the following things:
- Create an init script using the example provided here.
- Put your new script in ( /etc/init.d/ ) .
- Create a symbolic link from ( /etc/rc6.d/ ) called S[0-99]scriptname that points to your new script .
That is all it takes. Finally, if you need a configuration file that your service is going to need when it starts, the standard place to put one is in the ( /etc/sysconfig ) directory. I hope that you have learned and had as much fun as I did playing around with this stuff..