***************************************************************************** * BOOTING FROM DISK * * * * * * Copyright (c) 2001 Daniel P. Bovet, Marco Cesati, and Cosimo Comella * * Permission is granted to copy, distribute and/or modify this document * * under the terms of the GNU Free Documentation License, Version 1.1, * * published by the Free Software Foundation; with no Invariant Sections, * * with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the * * license is included in the file named LICENSE. * * * * (version 1.0) * ***************************************************************************** We have just seen how to create a boot floppy disk that can be used in an emergency situation if the file system becomes corrupted and the system is unable to boot from disk. In these cases, the only thing to do is to insert the boot floppy into the driver and restart the PC. Once the kernel is running, a filesystem repairing utility such as e2fsck can be invoked to fix things up. However, booting from floppy is somehow cumbersome and if you plan to use Linux quite often, it is preferrable to boot the kernel from the hard disk. In fact, if you are a kernel hacker, you might want to select at boot time which kernel version to boot. All this is possible, of course, and we are going to describe how to do it. Our workplan is the following: a) discuss disk partitions b) introduce the Master Boot Record c) discuss how to personalize the booting options according to your needs d) explain the role of the lilo loader ***************************************************************************** * DISK PARTITIONS * ***************************************************************************** The disk blocks of a disk are partitioned into groups of contiguous blocks called partitions. In Linux: - each disk is viewed as a device file characterized by a proper name: /dev/hda is the name of the first EIDE disk, /dev/sdb is the name of the second SCSI disk, etc. - each partition on a disk is viewed as a device file characterized by a proper name: /dev/hda1 is the first partition of the /dev/hda EIDE disk, /dev/sda3 is the third partition of the /dev/sda SCSI disk, and so forth. Disk partitions are an important feature of Linux. Splitting a disk into several partitions has several advantages: a) several OS can co-exist without interfering with each other, each in its own set of partitions b) the disk space required by Linux can be splitted into several physically isolated partitions. The standard Linux partitions include: - a large ext2 partition containing the filesystem - a small (100-400 MB) swap partition containing the swap area (virtual memory) - a very small (2-4 MB) boot partition containing a set of bootable kernel images If you plan to become a kernel hacker, it is strongly suggested to include a boot partition while installing Linux. This partition will include all the kernel images produced by you. If anything goes wrong during booting, your root file system stored in another partition won't be affected and you will always be able to reboot from floppy and clean up the mess. ***************************************************************************** * PLAYING WITH PARTITIONS * ***************************************************************************** Suppose you have an EIDE disk (/dev/hda device file) and you want to change its partitions. Then you issue the command: fdisk /dev/hda and you get the following prompt: Command (m for help): If you type p (print) you get a report of your current partitions. On my computer, this is the outcome: Disk /dev/hda: 255 heads, 63 sectors, 1245 cylinders Units = cylinders of 16065 * 512 bytes Device Boot Start End Blocks Id System /dev/hda1 1 1 8001 83 Linux /dev/hda2 * 2 396 3172837+ b Win95 FAT32 /dev/hda3 397 1214 6570585 83 Linux /dev/hda4 1215 1245 249007+ 82 Linux swap Be careful. If you modify the disk partitions, you will loose all data contained in the disk, so if you really want to change them, remember to do a disk backup before. After having changed the partitions, you will need to perform a few extra steps so that Linux is able to recognize the re-partitioned disk. In fact, we don't like at all the idea of repartitioning a disk. If you plan things ahead carefully, you should have chosen an appropriate set of partitions when you installed Linux. Let's then discuss another case where you really need to define new partitions. Let's assume you are short of disk space and you decide to install a second EIDE internal hard disk in your PC. In this case, you must do the following things: 1) Partition the new disk by issuing: fdisk /dev/hdb because /dev/hdb is the device file name associated with the second EIDE disk. 2) If you created a single partition in /dev/hdb, insert the following new entry in the /etc/fstab table: /dev/hdb1 /ext2 defaults 1 1 Otherwise, insert one entry for each partition. 3) If you created a single partition in /dev/hdb, run the ext2 utility that makes the partition an ext2 partition: mke2fs /dev/hdb1 Otherwise, run mke2fs on each partition. That's all. When Linux starts, the default fstab entry option specifies automatic mounting so the second disk will be mounted automatically and you are all set. ***************************************************************************** * THE MASTER BOOT RECORD * ***************************************************************************** Booting from the first PCs was done in a primitive way as a two step process: - read the first sector of the boot disk in RAM, starting from a fixed address; - set the CPU's program counter to the RAM fixed address. The few instructions that can be packed in a single sector are sufficient to read additional sectors: as a result of this bootstrapping activity, the whole kernel image is loaded in memory. This rudimentary approach is still used when booting from a floppy disk. Booting from a hard disk is done differently. The first sector of the hard disk, named the Master Boot Record (MBR), includes: - the partition table: each partition table entry typically includes the starting and ending sectors of a partition, and the kind of operating system that handles it - a small program, which loads the first sector of the partition containing the operating system to be started. Some operating systems such as Microsoft Windows~98 identifies this partition by means of an ``active flag'' included in the partition table (the active flag may be set through programs like MS-DOS's FDISK). Following this approach, only the operating system whose kernel image is stored in the active partition can be booted. ***************************************************************************** * THE LILO loader * ***************************************************************************** Linux uses the MBR in a rather clever way and treats all partitions in the same way. The rudimentary program included in the MBR is replaced by a sophisticated program called LILO that allows users to select the operating system to be booted. The LILO program, in turn, makes use of a script file and of a message file. As we shall see next, these two ASCII files can be easily edited by the user. The /sbin/lilo program reads the script contained in the /etc/lilo.conf file (and the data contained in the /etc/lilo.message file) and writes in the MBR (and in another sector) a machine language program capable of accomplishing any of the actions described in the script. Since lilo records not only the initial address of a kernel image but also its length in bytes, YOU MUST RUN LILO WHENEVER YOU REPLACE A KERNEL IMAGE IN THE BOOT PARTITION WITH A NEW ONE WITH THE SAME NAME. As a kernel hacker, this means that, whenever you recompile linux-2.4.5khx and put the kernel image in the boot partiton, you MUST execute lilo before rebooting the system, otherwise lilo will continue to boot the old kernel image! ***************************************************************************** * THE lilo.conf SCRIPT * ***************************************************************************** The /etc/lilo.conf file contains the script that is interpreted by lilo. As an example, the following script offers a choice of three possible OSs to be booted: - linux (digit l) - development linux (digit d) - windows 98 (digit w) # Start LILO global section lba32 # Allow booting past 1024th cylinder with a recent BIOS boot = /dev/hda message = /etc/lilo.message prompt # delay 50 # delay in tenths of sec for default OS if prompt is not chosen # Normal VGA console vga = normal # Linux bootable partition config begins image = /boot/vmlinuz root = /dev/hda3 label = Linux alias = l read-only # Linux bootable partition config ends # Linux bootable partition config begins image = /boot/vmlinuz_dvlp root = /dev/hda3 label = dvlp_Linux alias = d read-only # Linux bootable partition config ends # DOS bootable partition config begins other = /dev/hda2 label = Win98 alias = w table = /dev/hda # DOS bootable partition config ends Please notice that the root filesystem of Linux is stored in the /dev/hda3 partition while the Windows filesystem is stored in the /dev/hda2 partition. This script thus agrees with the partition table shwon in the "Playing with partitions" section. The /etc/lilo.message file must be prepared correspondingly. In our example, it should look like: Type 'l' to start Linux Type 'd' to start development version of Linux Type 'w' to start Windows 98 The three letters 'l', 'd', and 'w' are those chosen as alias in the lilo.conf script. According to such setup, two distinct Linux kernel images may be loaded: /boot/vmlinuz or /boot/vmlinuz_dvlp. Both of them are stored in the small boot Linux partition associated with the /dev/hda1 device file. HINT: as kernel hackers, we are going to produce several versions of Linux development kernel images, say vmlinuz-2.4.12kh1, vmlinuz-2.4.12kh2, vmlinuz-2.4.12kh3, etc. Each time we switch from a development version to the next one, say from vmlinuz-2.4.12kh2 to vmlinuz-2.4.12kh3, we must recall to modify the /etc/lilo.conf file and replace the line: image = /boot/vmlinuz-2.4.12kh2 with: image = /boot/vmlinuz-2.4.12kh3 This annoying step can be avoided in we make use, once for all, of a symbolic link in the boot partition to identify the current name of the development linux kernel image. Something like: ln -s /boot/vmlinuz-2.4.12kh2 /boot/vmlinuz_devlp In this way, if we switch from a development version to the next one, we'll only have to remove the existing vmlinuz_devlp symbolic link and replace it with another one but we don't need to edit /etc/lilo.conf (always a risky operation). As stated before, after changing the symbolic link you MUST run lilo to update the MBR. in the opposite case (this is a frequent error among fresh kernel hackers) the system will continue to boot the old kernel image!!!