The process of booting a Linux® system consists of a number of stages. But whether you're booting a standard x86 desktop or a deeply embedded PowerPC® target, much of the flow is surprisingly similar. This article explores the Linux boot process from the initial bootstrap to the start of the first user-space application. Along the way, you'll learn about various other boot-related topics such as the boot loaders, kernel decompression, the initial RAM disk, and other elements of Linux boot.
In the early days, bootstrapping a computer meant feeding a paper tape containing a boot program or manually loading a boot program using the front panel address/data/control switches. Today's computers are equipped with facilities to simplify the boot process, but that doesn't necessarily make it simple.
Let's start with a high-level view of Linux boot so you can see the entire landscape. Then we'll review what's going on at each of the individual steps. Source references along the way will help you navigate the kernel tree and dig in further.
Overview
Figure 1 gives you the 20,000-foot view.
When a system is first booted, or is reset, the processor executes code at a well-known location. In a personal computer (PC), this location is in the basic input/output system (BIOS), which is stored in flash memory on the motherboard. The central processing unit (CPU) in an embedded system invokes the reset vector to start a program at a known address in flash/ROM. In either case, the result is the same. Because PCs offer so much flexibility, the BIOS must determine which devices are candidates for boot. We'll look at this in more detail later.
When a boot device is found, the first-stage boot loader is loaded into RAM and executed. This boot loader is less than 512 bytes in length (a single sector), and its job is to load the second-stage boot loader.
When the second-stage boot loader is in RAM and executing, a splash screen is commonly displayed, and Linux and an optional initial RAM disk (temporary root file system) are loaded into memory. When the images are loaded, the second-stage boot loader passes control to the kernel image and the kernel is decompressed and initialized. At this stage, the second-stage boot loader checks the system hardware, enumerates the attached hardware devices, mounts the root device, and then loads the necessary kernel modules. When complete, the first user-space program (init) starts, and high-level system initialization is performed.
init
That's Linux boot in a nutshell. Now let's dig in a little further and explore some of the details of the Linux boot process.
System startup
The system startup stage depends on the hardware that Linux is being booted on. On an embedded platform, a bootstrap environment is used when the system is powered on, or reset. Examples include U-Boot, RedBoot, and MicroMonitor from Lucent. Embedded platforms are commonly shipped with a boot monitor. These programs reside in special region of flash memory on the target hardware and provide the means to download a Linux kernel image into flash memory and subsequently execute it. In addition to having the ability to store and boot a Linux image, these boot monitors perform some level of system test and hardware initialization. In an embedded target, these boot monitors commonly cover both the first- and second-stage boot loaders.
To see the contents of your MBR, use this command:
# dd if=/dev/hda of=mbr.bin bs=512 count=1# od -xa mbr.bin
The dd command, which needs to be run from root, reads the first 512 bytes from /dev/hda (the first Integrated Drive Electronics, or IDE drive) and writes them to the mbr.bin file. The od command prints the binary file in hex and ASCII formats.
dd
mbr.bin
od
In a PC, booting Linux begins in the BIOS at address 0xFFFF0. The first step of the BIOS is the power-on self test (POST). The job of the POST is to perform a check of the hardware. The second step of the BIOS is local device enumeration and initialization.
Given the different uses of BIOS functions, the BIOS is made up of two parts: the POST code and runtime services. After the POST is complete, it is flushed from memory, but the BIOS runtime services remain and are available to the target operating system.
To boot an operating system, the BIOS runtime searches for devices that are both active and bootable in the order of preference defined by the complementary metal oxide semiconductor (CMOS) settings. A boot device can be a floppy disk, a CD-ROM, a partition on a hard disk, a device on the network, or even a USB flash memory stick.
Commonly, Linux is booted from a hard disk, where the Master Boot Record (MBR) contains the primary boot loader. The MBR is a 512-byte sector, located in the first sector on the disk (sector 1 of cylinder 0, head 0). After the MBR is loaded into RAM, the BIOS yields control to it.
Stage 1 boot loader
The primary boot loader that resides in the MBR is a 512-byte image containing both program code and a small partition table (see Figure 2). The first 446 bytes are the primary boot loader, which contains both executable code and error message text. The next sixty-four bytes are the partition table, which contains a record for each of four partitions (sixteen bytes each). The MBR ends with two bytes that are defined as the magic number (0xAA55). The magic number serves as a validation check of the MBR.
The job of the primary boot loader is to find and load the secondary boot loader (stage 2). It does this by looking through the partition table for an active partition. When it finds an active partition, it scans the remaining partitions in the table to ensure that they're all inactive. When this is verified, the active partition's boot record is read from the device into RAM and executed.
Stage 2 boot loader
The secondary, or second-stage, boot loader could be more aptly called the kernel loader. The task at this stage is to load the Linux kernel and optional initial RAM disk.
The /boot/grub directory contains the stage1, stage1.5, and stage2 boot loaders, as well as a number of alternate loaders (for example, CR-ROMs use the iso9660_stage_1_5).
/boot/grub
stage1
stage1.5
stage2
iso9660_stage_1_5
The first- and second-stage boot loaders combined are called Linux Loader (LILO) or GRand Unified Bootloader (GRUB) in the x86 PC environment. Because LILO has some disadvantages that were corrected in GRUB, let's look into GRUB. (See many additional resources on GRUB, LILO, and related topics in the Resources section later in this article.)
The great thing about GRUB is that it includes knowledge of Linux file systems. Instead of using raw sectors on the disk, as LILO does, GRUB can load a Linux kernel from an ext2 or ext3 file system. It does this by making the two-stage boot loader into a three-stage boot loader. Stage 1 (MBR) boots a stage 1.5 boot loader that understands the particular file system containing the Linux kernel image. Examples include reiserfs_stage1_5 (to load from a Reiser journaling file system) or e2fs_stage1_5 (to load from an ext2 or ext3 file system). When the stage 1.5 boot loader is loaded and running, the stage 2 boot loader can be loaded.
reiserfs_stage1_5
e2fs_stage1_5
With stage 2 loaded, GRUB can, upon request, display a list of available kernels (defined in /etc/grub.conf, with soft links from /etc/grub/menu.lst and /etc/grub.conf). You can select a kernel and even amend it with additional kernel parameters. Optionally, you can use a command-line shell for greater manual control over the boot process.
/etc/grub.conf
/etc/grub/menu.lst
With the second-stage boot loader in memory, the file system is consulted, and the default kernel image and initrd image are loaded into memory. With the images ready, the stage 2 boot loader invokes the kernel image.
initrd
Kernel
From the GRUB command-line, you can boot a specific kernel with a named initrd image as follows:
grub> kernel /bzImage-2.6.14.2 [Linux-bzImage, setup=0x1400, size=0x29672e]grub> initrd /initrd-2.6.14.2.img [Linux-initrd @ 0x5f13000, 0xcc199 bytes]grub> bootUncompressing Linux... Ok, booting the kernel.
If you don't know the name of the kernel to boot, just type a forward slash (/) and press the Tab key. GRUB will display the list of kernels and initrd images.
With the kernel image in memory and control given from the stage 2 boot loader, the kernel stage begins. The kernel image isn't so much an executable kernel, but a compressed kernel image. Typically this is a zImage (compressed image, less than 512KB) or a bzImage (big compressed image, greater than 512KB), that has been previously compressed with zlib. At the head of this kernel image is a routine that does some minimal amount of hardware setup and then decompresses the kernel contained within the kernel image and places it into high memory. If an initial RAM disk image is present, this routine moves it into memory and notes it for later use. The routine then calls the kernel and the kernel boot begins.
When the bzImage (for an i386 image) is invoked, you begin at ./arch/i386/boot/head.S in the start assembly routine (see Figure 3 for the major flow). This routine does some basic hardware setup and invokes the startup_32 routine in ./arch/i386/boot/compressed/head.S. This routine sets up a basic environment (stack, etc.) and clears the Block Started by Symbol (BSS). The kernel is then decompressed through a call to a C function called decompress_kernel (located in ./arch/i386/boot/compressed/misc.c). When the kernel is decompressed into memory, it is called. This is yet another startup_32 function, but this function is in ./arch/i386/kernel/head.S.
./arch/i386/boot/head.S
start
startup_32
./arch/i386/boot/compressed/head.S
decompress_kernel
./arch/i386/boot/compressed/misc.c
./arch/i386/kernel/head.S.
In the new startup_32 function (also called the swapper or process 0), the page tables are initialized and memory paging is enabled. The type of CPU is detected along with any optional floating-point unit (FPU) and stored away for later use. The start_kernel function is then invoked (init/main.c), which takes you to the non-architecture specific Linux kernel. This is, in essence, the main function for the Linux kernel.
start_kernel
init/main.c
main
With the call to start_kernel, a long list of initialization functions are called to set up interrupts, perform further memory configuration, and load the initial RAM disk. In the end, a call is made to kernel_thread (in arch/i386/kernel/process.c) to start the init function, which is the first user-space process. Finally, the idle task is started and the scheduler can now take control (after the call to cpu_idle). With interrupts enabled, the pre-emptive scheduler periodically takes control to provide multitasking.
kernel_thread
arch/i386/kernel/process.c
cpu_idle
During the boot of the kernel, the initial-RAM disk (initrd) that was loaded into memory by the stage 2 boot loader is copied into RAM and mounted. This initrd serves as a temporary root file system in RAM and allows the kernel to fully boot without having to mount any physical disks. Since the necessary modules needed to interface with peripherals can be part of the initrd, the kernel can be very small, but still support a large number of possible hardware configurations. After the kernel is booted, the root file system is pivoted (via pivot_root) where the initrd root file system is unmounted and the real root file system is mounted.
pivot_root
The decompress_kernel function is where you see the usual decompression messages emitted to the display:
Uncompressing Linux... Ok, booting the kernel.
The initrd function allows you to create a small Linux kernel with drivers compiled as loadable modules. These loadable modules give the kernel the means to access disks and the file systems on those disks, as well as drivers for other hardware assets. Because the root file system is a file system on a disk, the initrd function provides a means of bootstrapping to gain access to the disk and mount the real root file system. In an embedded target without a hard disk, the initrd can be the final root file system, or the final root file system can be mounted via the Network File System (NFS).
Init
After the kernel is booted and initialized, the kernel starts the first user-space application. This is the first program invoked that is compiled with the standard C library. Prior to this point in the process, no standard C applications have been executed.
In a desktop Linux system, the first application started is commonly /sbin/init. But it need not be. Rarely do embedded systems require the extensive initialization provided by init (as configured through /etc/inittab). In many cases, you can invoke a simple shell script that starts the necessary embedded applications.
/sbin/init
/etc/inittab
Much like Linux itself, the Linux boot process is highly flexible, supporting a huge number of processors and hardware platforms. In the beginning, the loadlin boot loader provided a simple way to boot Linux without any frills. The LILO boot loader expanded the boot capabilities, but lacked any file system awareness. The latest generation of boot loaders, such as GRUB, permits Linux to boot from a range of file systems (from Minix to Reiser).
Resources
> Lire la dépêche (49 commentaires, moyenne: 3,8).
Nous souhaitons la bienvenue à Novell dans la communauté temps réel. Nous espérons qu'elle fera des contributions à l'avenir.
Note à Red Hat: C'est de l'open source vous vous souvenez ? Novell propose un Linux testé est renforcé pour les entreprises avec des capacités temps réel. Ce n'est pas parce que Red Hat est une fois de plus en retard sur le marché (voir le desktop Linux pour les entreprises, la virtualisation avec Xen...etc) que cela signifie que notre noyau contient du code de qualité bêta (...) Ce n'est pas plus du code Red Hat que les millions de lignes de code apportées par Novell (...) C'est ça le modèle Open Source.
This is a simple procedure for installing Debian GNU/Linux onto a USB key flash media. It includes several configuration changes but tries to stay as close to a default debian install as possible.http://www.debian-administration.org/articles/179
This is useful for administrators that need to carry sensitive information or people concerned about their privacy.
This was tested on Debian Sid and Knoppix 3.8 with the USB Keys listed below.
Tested Media:
Other reviews of USB Flash media:
Note on Devices: All device names and mappings are as they were detected and I used them on my system. You will need to substitute the correct device as it is detected on your system.
KNOPPIX NOTE: When you see these notes, there are special steps necessary for installing from Knoppix.
Installation Procedure
1. Shred the drive
shred -n 1 -z -v /dev/sdd
(One pass to shred, one pass to zero)
2. Create Partitions
We will create two partitions on the USB key, one for /boot and one for / (root). We do not create a swap partition because that would prematurely age the usb key. You may mount and use swap partitions from the local harddrives ala knoppix but that is up to you.
parted /dev/sdd "mklabel msdos mkpart primary 0 14 mkpart primary 15 -0"
3. Shred rootfs
shred -n 1 -v /dev/sdd2
(zero'd filesystems are bad for encrypted ones.)
4. Load modules if necessary
modprobe dm-cryptmodprobe aes
apt-get updateapt-get install cryptsetup dmsetup libdevmapper1.01
5. Created mapped crypt device for root
cryptsetup -y create rootfs /dev/sdd2
6. Format filesystems:
Since we can't use journaling filesystems on flash media (premature aging again), we fall back to good old ext2.
mkfs.ext2 /dev/mapper/rootfsmkfs.ext2 /dev/sdd1sync ; sync
7. Apply disk labels
We do this so that we can identify our drive when we boot on various systems. Using a strict device mapping often breaks if other usb or flash devices are detected before ours.You may use any label that you like, but you will have to remember to update the initrd (file: /sbin/init)
e2label /dev/sdd1 PRIVDEB_BOOT
8. Make temporary mount points and mount
mkdir /mnt/buildroot/mount /dev/mapper/rootfs /mnt/buildrootmkdir /mnt/buildroot/bootmount /dev/sdd1 /mnt/buildroot/boot
9. Install base files.
debootstrap --arch i386 sid /mnt/buildroot
Note: Installed size is about 160MB at this stage.
cp -ap /dev/ub[a-f]* /mnt/buildroot/dev/
10. Enter chroot jail to work on system.
chroot /mnt/buildroot/ /bin/su -
11. Build fstab and mount everything.
Create /etc/fstab file
#/etc/fstab: static file system information.# LABEL=PRIVDEB_BOOT /boot ext2 defaults,noatime 0 2/dev/mapper/rootfs / ext2 defaults,errors=remount-ro,noatime 0 1proc /proc proc defaults 0 0tmpfs /etc/network/run tmpfs defaults,noatime 0 0tmpfs /tmp tmpfs defaults,noatime 0 0tmpfs /var/lock tmpfs defaults,noatime 0 0tmpfs /var/log tmpfs defaults,noatime 0 0tmpfs /var/run tmpfs defaults,noatime 0 0tmpfs /var/tmp tmpfs defaults,noatime 0 0tmpfs /home//Scratch tmpfs defaults,noatime 0 0#Warning: By mounting /var/log on tmpfs, logs will only be available for the current session.
Mount it all
mount -a
12. Build sources.list
Create /etc/apt/sources.list
deb http://mirrors.kernel.org/debian/ sid main non-free contribdeb-src http://mirrors.kernel.org/debian/ sid main non-free contribdeb http://ftp.uk.debian.org/debian-non-US/ sid non-US/main non-US/non-free non-US/contribdeb-src http://ftp.uk.debian.org/debian-non-US/ sid non-US/main non-US/non-free non-US/contrib# If you are using debian stable (woody) include the security updates.# deb http://security.debian.org/ sid/updates main non-free contrib
Note: You can install and use apt-spy to test for the fastest downloading mirrors in your area.
13. System adjustments
blkid.tab: this file is cached as drives are scanned. Since the scan only takes a few seconds, you dont lose much by not caching or setting the default cache to /dev/null. This file generates an error on boot if the cache file has different device mappings than are currently detected. By removing the cache and forcing a fresh scan every time, the error is eliminated.
rm -f /etc/blkid.tab*ln -s /dev/null /etc/blkid.tab
mtab: This file is written a lot and may prematurely age parts of the flash media and the information can simply be accessed from /proc directly.
rm -f /etc/mtabln -s /proc/mounts /etc/mtab
Set Hostname
vi /etc/hostname
Set /etc/hosts with localhost + hostname
vim /etc/hosts127.0.0.1 localhost.localdoman localhost
14. Install additional required packages
apt-get updateapt-get install cryptsetup dmsetup libdevmapper1.01apt-get install discover1 libdiscover1apt-get install module-init-tools equivs cramfsprogsapt-get clean
15. Install custom mkinitrd script and equiv package
Create mkinitrd.dmcrypt-usb file in /usr/local/sbin
#!/bin/bash# Filename: mkinitrd.dmcrypt-usb# Maintainer: Dave Vehrs # Help: << HELP_STEXTOptions: -c Temporary directory to build image in. -k Keep temporary directory used to build image. -l Use to indenify boot partition. -o Write to outfie -d,-m,-r Included for fake support of default mkinitrd script (anything passed to them is discarded). See http://www.saout.de/tikiwiki/tiki-index.php?page=USBFlashMedia for more info.HELP_STEXTfunction display_shelp { echo; echo "Usage $0 [OPTION]...<-o outfile> [version]" sed --silent -e '/HELP_STEXT$/,/^HELP_STEXT/p' "$0" | sed -e '/HELP_STEXT/d'} # Set defaultsBOOT_LABEL="PRIVDEB_BOOT"CRAMFSDIR=/tmp/cramfskeep_temp=0unset VERSION# Parse command line.# if version + other options not specified, exit.if [ $# -eq 0 ] ; then display_shelp exit 1fiwhile [ $# -ge 1 ] ; do case $1 in -c ) CRAMFSDIR=$2 ; shift ; shift ;; -d ) dir_conf=$2 ; shift ; shift ;; -k ) keep_temp=1 ; shift ;; -l ) BOOT_LABEL=$2 ; shift ; shift ;; -m ) cmd_mkinitrd=$2 ; shift ; shift ;; -o ) outfile_name=$2 ; shift ; shift ;; -r ) initrd_root=$2 ; shift ; shift ;; * ) VERSION=$1 ; shift ;; esacdone# Exit if version not specifiedif [ -z "$VERSION" ] ; then echo "Error: You need to specify a kernel version to build for." exit 1else VERSION=${VERSION##*/}fi# Start build...echo "Build directory tree."install -d $CRAMFSDIR/{bin,dev/mapper,etc,proc,mnt,sbin}echo "Copy binaries from /bin."# Copy /bin binaries over and any require libraries.files_bin="bash grep mount umount mkdir mknod sed sleep uname"for file in $files_bin ; do install /bin/$file $CRAMFSDIR/bin/$file for lib in $( ldd /bin/$file | awk '{print $3}' | grep -v fffe000 ) ; do install -d $CRAMFSDIR/${lib%/*} install $lib $CRAMFSDIR/$lib donedoneecho "Copy binaries from /usr/bin."# Copy /usr/bin binaries over and any require libraries.files_usrbin="find mawk"for file in $files_usrbin ; do install /usr/bin/$file $CRAMFSDIR/bin/$file for lib in $( ldd /usr/bin/$file | awk '{print $3}' | grep -v fffe000 ); do install -d $CRAMFSDIR/${lib%/*} install $lib $CRAMFSDIR/$lib donedoneecho "Copy binaries from /sbin."# Copy /sbin binaries over and any require libraries.files_sbin="cryptsetup e2label modprobe pivot_root"for file in $files_sbin ; do install /sbin/$file $CRAMFSDIR/sbin/$file for lib in $( ldd /sbin/$file | awk '{print $3}' | grep -v fffe000 ) ; do install -d $CRAMFSDIR/${lib%/*} install $lib $CRAMFSDIR/$lib donedone# Add common linksln -s bash /tmp/cramfs/bin/shln -s mawk /tmp/cramfs/bin/awkecho "Copy devices over."# Copy devices overcp -apL /dev/{console,hd,initrd,null,ram,scd,sd}* $CRAMFSDIR/dev/echo "Copy modules over."# Copy modules overmodules="aes-i586 dm-crypt sd_mod sr_mod ehci-hcd uhci-hcd ohci-hcd sl811-hcd usbhid usbkbd usb-storage vesafb fbcon ext2 unix"for mod in $modules; do for ko in $( modprobe --set-version $VERSION --show-depends $mod | cut -b8- ) ; do install -d $CRAMFSDIR/${ko%/*} install $ko $CRAMFSDIR/$ko donedonecp -apL /lib/modules/$VERSION/modules.* $CRAMFSDIR/lib/modules/$VERSION/echo "Copy /etc files over."# Copy required config files overcp -apr /etc/modprobe.d $CRAMFSDIR/etc/echo "Copy custom init over."# Copy custom init file. (see below)cat <$CRAMFSDIR/sbin/init#!/bin/bash# Filename: /sbin/init# Dependencies: awk, bash, cryptsetup, e2label, find, grep, modprobe # mount, pivot_root, sed, sleep and uname.# # This file generated by mkinitrd.dmcrypt-usb by Dave Vehrs.set -e# Set varsunset pass part_boot part_rootfs major minor labeldm_name="device-mapper"dm_dir="mapper"dir="/dev/\$dm_dir"control="\$dir/control"count=0# Mount /proc/bin/mount -n -t proc none /proc# Mount /dev/mapper on tmpfs/bin/mount -o rw -n -t tmpfs none /dev/mapper# Modules to loadCORE_MODULES="unix ide-core scsi_mod sd_mod sr_mod mbcache ext2"DISPLAY_MODULES="vesafb fbcon"CRYPT_MODULES="aes-i586 dm-mod dm-crypt"USB_MODULES="ehci-hcd ohci-hcd uhci-hcd sl811-hcd usbcore usbhid usbkbd usb-storage"# Load Modulesif [ -e /lib/modules/\$(/bin/uname -r) ] ; then echo "initrd: loading modules." for module in \$DISPLAY_MODULES \$CORE_MODULES \$CRYPT_MODULES \$USB_MODULES ; do /bin/find /lib/modules/\$(/bin/uname -r) -name \$module.ko -exec /sbin/modprobe \$module \; donefi# Test to be sure the procfs is mounted, if not exit. if [ ! -e /proc/devices ] ; then echo "initrd: procfs not found: please create \$control manually." exit 1fimajor=\$(/bin/sed -n 's/^ *\\([0-9]\+\\) \+misc$/\1/p' /proc/devices)minor=\$(/bin/sed -n "s/^ *\\([0-9]\+\\) \+\$dm_name\\\$/\1/p" /proc/misc)# Test to be sure dm_mod loadedif [ -z "\$major" -o -z "\$minor" ] ; then echo "initrd: \$dm_name kernel module not loaded: can't create \$control." exit 1fi # Create new control device.echo "initrd: creating \$control character device with major:\$major minor:\$minor."/bin/mknod --mode=600 \$control c \$major \$minor# Sleep to let kernel finish loading. 15 seconds is enough on most systems. echo "initrd: sleeping for 15 seconds so kernel can finish detecting devices."/bin/sleep 5echo "initrd: sleeping for 10 more seconds..."/bin/sleep 5echo "initrd: sleeping for 5 more seconds..."/bin/sleep 5echo "initrd: awake...."# Search for boot partition label. When usb media is detected by the operating# system seems to migrate a little depending on what port you connect to on the# mainboard and what if any other devices are connected and where. To# compensate for that, we search for the label on our boot partition.echo "initrd: searching for boot partition label."for device in \$( /bin/grep sd[a-h]1 /proc/partitions | /bin/awk '{print \$4}' ) ; do label=\$( /sbin/e2label /dev/\$device 2>/dev/null ) if [ ! -z "\$label" ] ; then if [ "\$label" == "$BOOT_LABEL" ] ; then part_boot="/dev/\$device" break fi fi done# Exit if boot partition not found.if [ -z "\$part_boot" ] ; then echo "initrd: error -- boot partition label not found (\$part_boot)." exit 1fi# Assign rootfs variable from boot (i.e. if boot is on /dev/sda1, this will# set part_rootfs to /dev/sda2).part_rootfs=\$( echo \$part_boot | /bin/sed -e 's/1/2/' )# Unmount /proc/bin/umount /proc# Prompt for passwordecho -en "\\nplease enter password for rootfs filesystem: "read -s passecho -e# Attempt mountingecho "initrd: attempting to mount rootfs."echo \$pass | /sbin/cryptsetup create rootfs \$part_rootfs/bin/mount -r -n -t ext2 /dev/mapper/rootfs /mnt# Loop for bad password attemptswhile [ \$? -ne 0 ] ; do # Remove old crypt mount. /sbin/cryptsetup remove rootfs # Test for max tries. if [ \$count -ge 5 ] ; then echo -e "\\ninitrd: too many bad guesses. aborting." exit 1 else count=\$(( \$count + 1 )) fi # Reprompt for password echo -e "\\ninitrd: error -- rootfs mount failed." echo -n "please re-enter password: " read -s pass echo # Reattempt mounting echo \$pass | /sbin/cryptsetup create rootfs \$part_rootfs /bin/mount -r -n -t ext2 /dev/mapper/rootfs /mntdoneunset passecho "initrd: rootfs successfully mounted."# Now that the encrypted media is readable, shift the root to it and continue# the boot cycle by running its init.cd /mnt/sbin/pivot_root . initrdexec /usr/sbin/chroot . /sbin/initEOFchown root:root $CRAMFSDIR/sbin/initchmod 755 $CRAMFSDIR/sbin/init# make cramfs fileif [ -z "$outfile_name" ] ; then mkcramfs $CRAMFSDIR ./initrd-$VERSION.imgelse mkcramfs $CRAMFSDIR $outfile_namefi# Cleanupif [ $keep_temp -eq 0 ] ; then rm -rf $CRAMFSDIRfi
Set permissions, and links.
chown root.root /usr/local/sbin/mkinitrd.dmcrypt-usbchmod 750 /usr/local/sbin/mkinitrd.dmcrypt-usbln -s /usr/local/sbin/mkinitrd.dmcrypt-usb /usr/sbin/mkinitrd
Next we need to install an equivs package to let the package system know that we installed this ourselves and not to install initrd-tools
cd /tmpequivs-control initrd-tools
Edit the generated template so that it looks like:
Section: miscPriority: optionalStandards-Version: Package: initrd-tools
Build equivs package
equivs-build initrd-tools
Install the package
dpkg -i initrd-tools_1.0_all.deb
For more information about equivs, see the APT howto at: APT-Howto: Equivs
16. Remove unwanted locales
Be very careful configuring and running localepurge. It is very easy to delete too many locales.
apt-get install localepurgelocalepurgeapt-get clean
For more information about localepurge, see the APT howto at: APT-Howto: localepurge
17. Install kernel
WARNING: Kernels prior to 2.6.10 had a bug in the dm_crypt modules that potentially could reveal data. Only use 2.6.10 or better.
apt-get install kernel-image-2.6.11-1-686apt-get clean
Note: Install size is approximately 184MB now. If you want to install a kernel built from source you can. After you install it, run /sbin/mkinitrd to build the /boot/initrd file. When you run /sbin/mkinitrd, it may print several FATAL errors regarding modules that it cannot find. If you built these modules into the kernel then you can ignore the error messages. If you omitted the modules, this is your warning to go build them as modules or into the kernel. Required modules: dm_crypt, aes, ide_core, scsi_mod, sd_mod, ehci-hcd, ohci-hcd, uhci-hcd, sl811-hcd, usb-storage, usb-hid, dm_mod, cramfs
18. Install optional packages
apt-get install vim irsii-text mutt fetchmail antiword screenapt-get install exuberant-ctags less procmailapt-get install python2.3 python2.3-pexpect python2.3-fuseapt-get install xserver-common xserver-xfree86 xbase-clients xfree86-commonapt-get install ion3 -or- blackbox -or- fluxbox -or- icewmapt-get install xtermapt-get install memtest86+
Note: All this is approximately 300mb installed (with dependencies).
19. Install grub
apt-get install grubgrub-install /dev/sddmkdir /boot/grubgrub root (hd1,0) setup (hd1) quit
Create /boot/grub/menu.lst file
# default numdefault 0# timeout sectimeout 5# pretty colourscolor green/black black/greentitle Debian GNU/Linux-2.6.11-1-686root (hd0,0)kernel /vmlinuz-2.6.11-1-686 root=/dev/ram0 init=/sbin/init vga=794initrd /initrd.img-2.6.11-1-686savedefaultboottitle Debian GNU/Linux-2.6.11-1-686 (Rescue/Single)root (hd0,0)kernel /vmlinuz-2.6.11-1-686 root=/dev/ram0 init=/sbin/init singleinitrd /initrd.img-2.6.11-1-686boot title Memtest86+root (hd0,0)kernel /memtest86+.binboot
20. Add User accounts
Either: Copy an existing /etc/group, /etc/passwd, and /etc/shadow file over from another system (this has to be done from outside the chroot directory). Or: Add users locally. set root password passwd root add local user useradd passwd repeat step 2 as necessary
Either:
Copy an existing /etc/group, /etc/passwd, and /etc/shadow file over from another system (this has to be done from outside the chroot directory).
Or:
Add users locally.
passwd root
useradd passwd
21. Exit Jail
umount -aumount /procexit
22. Unmount and remove crypt mapping
cdumount /mnt/buildroot/cryptsetup remove rootfs
23. Reboot to test media
shutdown -r now
1. Make sure required modules are loaded.
modprobe dm_cryptmodprobe aes-i586 (or aes)modprobe usb-storage
2. Insert USB key into port
3. Create device mapping and mount
cryptsetup create rootfs /dev/sdd2mount /dev/mapper/rootfs /mnt/buildroot
Why are these adverts here?
[ Parent | Reply to this comment ]
deb http://mirrors.kernel.org/debian/ sid main non-free contribdeb-src http://mirrors.kernel.org/debian/ sid main non-free contrib# If you are using debian stable (woody) include the security updates.# deb http://security.debian.org/ sid/updates main non-free contrib
OK, rebuilding libdevmapper1.01 and dmsetup from the source package fixed my problems.
Easiest/fastest way to rebuild it is with apt-src.
First, install apt-src if you need to and remove prebuilt versions of libdevmapper1.01, dmsetup:
apt-get install apt-srcapt-get remove libdevmapper1.01 dmsetup
Note: cryptsetup will get removed as well because it depends on libdevmapper1.01 and dmsetup.
Second, create a directory to store source files in and use apt-src to download/install the necessary files:
cd $HOMEmkdir SRCapt-src install libdevmapper1.01
Third, build the packages:
apt-src build libdevmapper1.01 dmsetup
Forth, install the packages:
dpkg -i libdevmapper1.01*.deb libdevmapper-dev*.deb dmsetup*.deb
Fifth, put cryptsetup back:
apt-get install cryptsetup
Note: Until the binary distribution of libdevmapper1.01 and dmsetup is fixed, you will also need to run apt-src update/upgrade when you do regular system updates with apt-get update/upgrade.
Small correction.
Change into the SRC directory after you create it, as apt-src will create quite a few directories and files.
cd $HOMEmkdir SRCcd SRCapt-src install libdevmapper1.01
....
I: Extracting libstdc++5... ar: /mnt/buildroot//var/cache/apt/archives/dpkg_1.10.28_i386.deb /var/cache/apt/archives/dpkg_1.13.11_i386.deb: No such file or directory zcat: stdin: unexpected end of file I: Installing core packages... ln: `/mnt/buildroot/usr/bin/awk': File exists umount: /mnt/buildroot/dev/pts: not mounted umount: /mnt/buildroot/dev/shm: not mounted umount: /mnt/buildroot/proc/bus/usb: not mounted
Portatil:/mnt/buildroot# chroot /mnt/buildroot/ /bin/su - Sorry. Portatil:/mnt/buildroot# chroot /mnt/buildroot/ I have no name!@Portatil:/# su Sorry.
I have no name!@Portatil:/# pico /etc/fstab bash: pico: command not found I have no name!@Portatil:/# nano /etc/fstab bash: nano: command not found I have no name!@Portatil:/# vi /etc/fstab bash: vi: command not found
I have no name!@Portatil:/# mount -a warning: can't open /etc/mtab: No such file or directory mount: special device LABEL=PRIVDEB_BOOT does not exist mount: mount point /etc/network/run does not exist mount: mount point /home//Scratch does not exist
I have no name!@Portatil:/# apt-get update bash: apt-get: command not found I have no name!@Portatil:/# aptitude
Almost all of the errors after su failed are related to the fact that your new chroot environment is not setup properly. For example, the applications can't be found cause the PATH variable is not set.
For the mount error, if you created the link to /etc/mtab to /proc/mounts, then the error is that /proc probably isn't mounted yet. Try this:
mount -t proc none /procmount -a
However having said all that, I believe that the root problem is that debootstrap error. While its probably fixable, the quickest solution is to just erase everything and start over with either sarge or sid.
It should still work. Let me look into it.
Off of the top of my head the problem is in step 15, maybe you can retry from there. (no need to erase it all)
Ignore the "FATAL: Module sl811_hcd not found.", thats only a problem if thats your USB controller chipset which obviously isn't a problem for you because you're already accessing usb devices.
Ok, I dunno why sarge isn't working, but I've done most of my testing with sid and it works like clockwork. Try it.
Looks like I may have discovered the bug that was causing this to fail for you. Sorry I didn't catch it sooner.
See post http://www.debian-administration.org/articles/179#comment_28
Just out of curiosity, what brands and sizes of usb media have people been using? Any recommendations or warnings?
[ Parent |
Les installations classiques sont sensibles aux coupures électriques et aux arrêt brutaux qui peuvent conduire à des pertes de donnée voir empêcher un redémarrage normal. Par ailleurs les disques compact flash supportent un nombre limité d'écriture qu'il est important de contrôler dans le cas d'un système sur compact-flash Pour mettre en œuvre facilement un système robuste où les disques ne sont pas montés en écriture il est possible d'utiliser des systèmes de fichier en ram 'fusionnés' avec des partitions sur disque en utilisant le module unionfs. Je décris ici plusieurs approches en sachant que nous voulons à la fois avoir un système read only mais aussi pouvoir sauver les modifications et garantir l'intégrité des données...
Unionfs est un système de fichier permettant de fusionner virtuellement des systèmes de fichier (appelé branches). Chaque branche se voie attribuée une priorité et peut-être read-only ou read-write. Unionfs est largement utilisé sur les live CD car il implémente un mécanisme de copy on write, c'est à dire que quand un fichier d'une union est modifiée, le contenu du fichier est recopié dans la branche read-write est ainsi l'union parait read-write alors qu'une ou plusieurs branches sont read-only.
Il faut utiliser un noyau récent (cad > 2.6.18 pour utiliser unionfs v2) et compiler le module unionfs disponible ici . Malheureusement unionfs n'est pas présent dans le noyau officiel, mais il est dans la branche d'Andrew Morton (-mm). Je ne parle ici que d'unionfs 2.1 qui apporte des amélioration intéressantes par rapport à la précédant, en particulier elle permet d'acceder aux branches "raw" d'une union. Notez que la version dans debian etch est ancienne est à déconseiller!
Pour créer des union on utilise simplement la syntaxe:
mount -t unionfs unionfs /nom_de_lunion -o dirs=/rep1=rw:/rep2=ro:...
Il est possible de fusionner de nombreuses branches, la première apparaissant étant la plus prioritaire.
Sous unix, les répertoires /etc, /var et /tmp doivent être read-write. Pour /tmp, pas de problème, un tmpfs fait l'affaire, pour /var et /etc il faut jouer avec les unions...
On va créer des systèmes de fichier tmpfs qui seront des branches read-write pour /var et /etc. Appelons les /rametc et /ramvar. Ensuite on crée des unions respectivement avec /etc et /var.
Pour ne pas s'embêter avec la gestion de /etc/mtab, on peut faire un lien vers /proc/mounts
/bin/mount -n -t tmpfs tmpfs /rametc -o size=30M /bin/mount -n -t tmpfs tmpfs /ramvar -o size=50M /bin/mount -n -t unionfs unionfs /etc -o dirs=/rametc=rw:/etc=ro /bin/mount -n -t unionfs unionfs /var -o dirs=/ramvar=rw:/var=ro echo "tmpfs /rametc tmpfs rw,size=30M 0 0" >> /etc/mtab echo "tmpfs /ramvar tmpfs rw,size=50M 0 0" >> /etc/mtab echo "unionfs /etc unionfs rw,dirs=/rametc=rw:/etc=ro 0 0" >> /etc/mtab echo "unionfs /var unionfs rw,dirs=/ramvar=rw:/var=ro 0 0" >> /etc/mtab
Dans /etc/fstab on n'oublie pas tmp:
et du coup on peut mettre /,/boot et /var en ro
Cette technique est également décrite: ici
Une autre solution consisterai à créer des unions ou l'on veux et ensuite utiliser la commande pivot_root. Cette commande permet de remplacer le répertoire racine et le répertoire courant de tous les processus en cours d'exécution.
En général on utilise pivot_root à la fin du script d'init présent dans initramfs. Pour se simplifier la vie, on peut le lancer dans rcS (debian)
Dans ce cas on procède ainsi:
- Montage de root dans /n/root
- Montage de tmpfs dans /n/tmpfs
- mount unionfs avec dirs=/n/tmpfs:/n/root=ro dans /mnt/unionfs
- pivot_root dans /mnt/unionfs
- chroot du shell en cours dans l'union
Eventuellement mount --move de /dev/
Attention, chroot doit être accessible dans le système pivoté... une copie en dehors de /usr ne fait pas de mal.
Sur la partition / on crée les répertoires /etc et /var qui resterons read-only.On crée des partitions sur le disque qui serviront à la synchro des repertoires tmpfs (dans l'exemple suivant on les monte dans /rw_etc et /rw_var) On crée des répertoires /varram etc /etcram en tmpfs . On monte dans /etc et /var respectivement les unions de /etcram(rw)+/rw_etc(ro)+/etc(ro) et de /varram+rw_var+/var Dans ce cas on peut remonter quand on veut /rw_etc en rw et faire des rsync
Comme précédemment, pour ne pas s'embêter avec la gestion de /etc/mtab, on peut faire un lien vers /proc/mounts Code pour /etc/init.d/rcS
/bin/mount -n -t tmpfs tmpfs /rametc -o size=30M /bin/mount -n /dev/sdb1 /rw_etc -o ro /bin/mount -n -t unionfs unionfs /etc/ -o dirs=/rametc=rw:/rw_etc=ro:/etc=ro echo "tmpfs /rametc tmpfs rw,size=30M 0 0" >> /etc/mtab echo "/dev/sdb1 /rw_etc ext3 rw 0 0" >> /etc/mtab echo "unionfs /etc/ unionfs rw,dirs=/rametc=rw:rw_etc=ro:/etc=ro 0 0" >> /etc/mtab /bin/mount /dev/sdc1 /rw_var -o ro /bin/mount -t tmpfs tmpfs /ramvar -o size=50M /bin/mount -t unionfs unionfs /var/ -o dirs=/ramvar=rw:/rw_var=ro:/var=ro
Le gros avantage de cette structure à trois branches par union est outre de permettre des copies entre branche pour la synchro, de pouvoir effacer quand on veux les repertoire rw_* et ainsi revenir dans l'état d'instalation (reset to factory).
Il y a plein de façon de faire avec unionfs...
Avec unionfs 2.1 (et contrairement à ce que dit la page de manuel) on peut intervenir directement sur les branches. Il est donc possible de remonter les partitions en rw le temps de faire un rsync.
Un problème qui se pose est alors de purger les partitions tmpfs pour quelles ne continuent pas à remplir la mémoire et de bien effacer de la compact flash les fichiers qui ont été détruit. Pour cela unionfs crée des fichiers "whiteout" (.wh.nomdufichier) dans la branche rw quand un fichier ou un répertoire est détruit. Il est facile de pacourir ces fichiers et de détruire les fichiers originaux.
Voici un exemple de script de syncho (à lancer périodiquement et/ou au reboot)
#On remonte /rw_etc en rw pour copier les modifs dessus. mount -o remount,rw /rw_etc rsync -a --exclude '.wh*' /rametc /rw_etc #Pour être sur de bien flusher les caches mount -o remount,incgen /etc #Il vaut mieux retirer la branche avant d'effacer les fichiers mount -t unionfs -o remount,del=/rametc none /etc find /rametc \( -regex '.*/\.wh\.[^/]*' -type f \) | sed -e 's/\.\///;s/\.wh\.//' | while read N do rm -rf /rw_etc/$N done rm -rf /rametc/* mount -t unionfs -o remount,add=/rametc none /etc mount -o remount,ro /rw_etc
#On remonte /rw_etc en rw pour copier les modifs dessus.
mount -o remount,rw /rw_etc
rsync -a --exclude '.wh*' /rametc /rw_etc #Pour être sur de bien flusher les caches mount -o remount,incgen /etc
#Il vaut mieux retirer la branche avant d'effacer les fichiers mount -t unionfs -o remount,del=/rametc none /etc
find /rametc \( -regex '.*/\.wh\.[^/]*' -type f \) | sed -e 's/\.\///;s/\.wh\.//' | while read N do rm -rf /rw_etc/$N done rm -rf /rametc/* mount -t unionfs -o remount,add=/rametc none /etc mount -o remount,ro /rw_etc
Évidement, faire des copies de fichiers ouverts, éventuellement en écriture, ce n'est pas forcement fiable. Idéalement il faudrai synchroniser lors d'un shutdown, mais la copie à chaud ne marche pas si mal à condition de prendre certaines précautions.
Pour une base de donnée, on peut locker les tables en lecture uniquement. Ca fonctionne correctement avec MySQL avec des tables MyISAM.
L'astuce pour locker les tables pendant le temps le plus court possible consiste à faire un double rsync.
- Un premier rsync crée une première copie
- On lock les table: mysql -p ... -u ... < "FLUSH TABLES WITH READ LOCK"
- Un deuxième rsync qui va être ultra rapide cette fois
- on delock: "UNLOCK TABLES"
Une autre solution élégante serai de faire un snapshot avec LVM, par contre on ne peut pas utiliser LVM avec tmpfs, donc il faudrai utiliser un ramdisk, pas très pratique à mettre en œuvre... Il y a des discussions intéressante à ce propos ici
Site officiel de Unionfs
Unionfs: User- and Community-Oriented Development of a Unification File System: http://www.fsl.cs.sunysb.edu/docs/sipek-ols2006/index.html
Tutorial Gentoo, http://gentoo-wiki.com/HOWTO_Read-only_root_filesystem#Unionfs_Method
Snapshot LVM et MySQL : http://mike.kruckenberg.com/archives/2006/05/mysql_backups_u.html
Aufs, un concurant de unionfs: http://aufs.sourceforge.net/
Author: Mattia Jona [contact developer]
Homepage: http://lcd-linux.sourceforge.net/ Tar/GZ: http://sourceforge.net/project/showfiles.php?group_id=123240