The Loopback Root Filesystem HOWTO by Andrew M. Bishop, amb@gedanken.demon.co.uk v1.1.2, 23 Mar 2000 v1.1.13, 14 May 2004 Kent Robotti This HOWTO explains how to use the Linux loopback device to create a Linux native filesystem format installation that can be run from a DOS partition without re-partitioning. Other uses of this same technique are also discussed. ______________________________________________________________________ Table of Contents 1. Introduction 1.1 Copyright 1.2 Revision History 2. Principles of Loopback Devices and Ramdisks 2.1 Loopback Devices 2.2 Ramdisk Devices 2.3 The Initial Ramdisk Device 2.4 The Root Filesystem 2.5 The Linux Boot Sequence 3. How To Create a Loopback Root Device 3.1 Requirements 3.2 Creating the Linux Kernel 3.3 Creating the Initial Ramdisk Device 3.4 Creating The Root Device 3.5 Creating the Swap File 3.6 Creating the MSDOS Directory 3.7 Creating a DOS boot Floppy 3.8 Booting from DOS hard drive 4. Booting the System 4.1 Possible Problems With Solutions 4.2 Reference Documents 5. Other Loopback Root Device Possibilities 5.1 DOS Hard-disk Only Installation 5.2 LILO Booted Installation 5.3 GRUB Booted Installation 5.4 SYSLINUX Booted Installation 5.5 NTFS Installation 5.6 Installing Linux without Re-partitioning 5.7 Booting From a Non-bootable device 5.8 Resizing a loop linux system 5.9 Loop encrypted filesystem 6.0 LoopLinux and Topologilinux distributions 6.1 Source for linuxrc.c ______________________________________________________________________ 1. Introduction 1.1. Copyright The Loopback Root Filesystem HOWTO Copyright (C) 1998,99 Andrew M. Bishop (amb@gedanken.demon.co.uk). This documentation is free documentation; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. The GNU General Public License is available from http://www.fsf.org/ or, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA 1.2. Revision History Version 1.0.0 Initial Version (June 1998) Version 1.0.1-1.0.3 Slight Modifications, kernel version changes, typos etc. (1998 July 1999) Version 1.1-1.1.1 Added Copyright Information and Re-Submitted (September 1999) Version 1.1.2-1.1.13 Included my experience in creating a loop linux system. Added loop encrypted filesystem info. Added source for a linuxrc 'linuxrc.c'. Updated loop encrypted filesystem info. Added GRUB instructions. Updated NTFS instructions. Added NTFS to 'linuxrc.c'. Updated linuxrc.c. Added mention of Topologilinux distribution. Removed AES, there's encrypted loop support in the v2.6 kernel. Kent Robotti (5-14-2004) 2. Principles of Loopback Devices and Ramdisks First I will describe some of the general principles that are used in the setting up of a loopback filesystem as the root device. 2.1. Loopback Devices A loopback device in Linux is a virtual device that can be used like any other media device. Examples of normal media devices are hard disk partitions like /dev/hda1, /dev/hda2, /dev/sda1, or entire disks like the floppy disk /dev/fd0 etc. They are all devices that can be used to hold a files and directory structures. They can be formatted with the filesystem that is required (ext2fs, msdos, ntfs etc.) and then mounted. The loopback filesystem associates a file on another filesystem as a complete device. This can then be formatted and mounted just like any of the other devices listed above. To do this the device called /dev/loop0 or /dev/loop1 etc is associated with the file and then this new virtual device is mounted. 2.2. Ramdisk Devices In Linux it is also possible to have another type of virtual device mounted as a filesystem, this is the ramdisk device. In this case the device does not refer to any physical hardware, but to a portion of memory that is set aside for the purpose. The memory that is allocated is never swapped out to disk, but remains in the disk cache. A ramdisk can be created at any time by writing to the ramdisk device /dev/ram0 or /dev/ram1 etc. This can then be formatted and mounted in the same way that the loopback device is. When a ramdisk is used to boot from (as is often done on Linux installation disks or rescue disks) then the disk image (the entire contents of the disk as a single file) can be stored on the boot floppy in a compressed form. This is automatically recognised by the kernel when it boots and is uncompressed into the ramdisk before it is mounted. 2.3. The Initial Ramdisk Device The initial ramdisk device in Linux is another important mechanism that we need to be able to use a loopback device as a the root filesystem. When the initial ramdisk is used the filesystem image is copied into memory and mounted so that the files on it can be accessed. A program on this ramdisk (called /linuxrc) is run and when it is finished a different device is mounted as the root filesystem. The old ramdisk is still present though and is mounted on the directory /initrd if present or available through the device /dev/initrd. This is unusual behaviour since the normal boot sequence boots from the designated root partition and keeps on running. With the initial ramdisk option the root partition is allowed to change before the main boot sequence is started. 2.4. The Root Filesystem: The root filesystem is the device that is mounted first so that it appears as the directory called / after booting. There are a number of complications about the root filesystem that are due to the fact that it contains all files. When booting the rc scripts are run, these are either the files in /etc/rc.d or /etc/rc?.d depending on the version of the /etc/init program. When the system has booted it is not possible to unmount the root partition or change it since all programs will be using it to some extent. This is why the initial ramdisk is so useful because it can be used so that the final root partition is not the same as the one that is loaded at boot time. 2.5. The Linux Boot Sequence: To show how the initial ramdisk operates in the boot sequence, the order of events is listed below. 1. The kernel is loaded into memory, this is performed by a boot loader like LILO, LOADLIN, or SYSLINUX. You can see the Loading... message as this happens. 2. The ramdisk image is loaded into memory, again this is performed by LILO, LOADLIN, etc. You can see the Loading... message again as this happens. 3. The kernel is initialised, including parsing the command line options and setting of the ramdisk as the root device. 4. The program /linuxrc is run on the initial ramdisk. 5. The root device is changed to that specified in the kernel parameter 'root=/dev/xxxx'. 6. The init program /sbin/init is run which will perform the user configurable boot sequence. This is just a simplified version of what happens, but is sufficient to explain how the kernel starts up and where the initial ramdisk is used. 3. How To Create a Loopback Root Device: Now that the general principles are explained the method of creating the loopback device can be explained. 3.1. Requirements To create the loopback root device will require a number of things. * A working Linux system. * A way to copy large files onto the target DOS partition. Most important is access to an installed Linux system. This is because the loop device can only be created under Linux. This will mean that it is not possible to bootstrap a working system from nothing. The requirements of the Linux system that you use is that you can compile a kernel on it. Once the loopback device is created it will be a large file. I have used an 80 MB files, but while this was sufficient for an X terminal it may not be enough if you want to use it for much else. This file must be copied onto the DOS partition, so either a network or a lot of floppy disks must be used. The software that you will require includes * LOADLIN version 1.6c or above: http://elserv.ffm.fgan.de/~lermen/ ftp://elserv.ffm.fgan.de/pub/linux/loadlin-1.6/ * A version of mount that supports loopback devices * A version of the kernel that supports the required options. All of these should be standard for recent Linux installations. 3.2. Creating the Linux Kernel: I created the loopback device using Linux kernel version 2.2.14, other versions should also work, but they must have at least the options listed below enabled. The kernel options that you will need to enable are the following: * RAM disk support (CONFIG_BLK_DEV_RAM). * Initial RAM disk (initrd) support (CONFIG_BLK_DEV_INITRD). * Loop device support (CONFIG_BLK_DEV_LOOP). * fat fs support (CONFIG_FAT_FS). * msdos fs support (CONFIG_MSDOS_FS). The first two are for the RAM disk device itself and the initial ram disk device. The next one is the loop back filesystem option. The last two are the msdos filesystem support which is required to mount the DOS partitition. Compiling a kernel without modules is the easiest option, although if you do want modules then it should be possible although I have not tried it. If modules are used then you should make sure that you have the options above compiled in and not as modules themselves. Once the kernel is configured it should be compiled to produce a zImage file (make zImage or make bzImage). This file will be /usr/src/linux/arch/i386/boot/zImage or bzImage when compiled. 3.3. Creating the Initial Ramdisk Device The initial ramdisk is most easily created as a loopback device from the start. You will need to do this as root, the commands that you need to execute are listed below. 1. Create a mount point for the initial ramdisk (an empty directory). # mkdir -p /mnt/initrd 2. Create an empty file of the size required. Here I have used 1200kb, you may need less or more depending on the contents, (the size is the last parameter). # dd if=/dev/zero of=initrd bs=1k count=1200 3. Make an ext2 filesystem on the empty file. # mke2fs -i4096 -m0 -F initrd 4. Mount the file onto the mount point, this uses the loopback device. # mount initrd /mnt/initrd -t ext2 -o loop 5. Change to the mounted loopback device. # cd /mnt/initrd 6. Create the files that are required. See "Contents Of The Initial Ramdisk" below. 7. Move out of the mounted loopback device. # cd .. 8. Unmount the device. # umount /mnt/initrd 9. Compress initrd with gzip. # gzip -9 initrd Contents Of The Initial Ramdisk: The files that you will need on the ramdisk are the minimum requirements to be able to execute any commands. * /linuxrc The script that is run to mount the dos/win partition (see below). * /lib/* The dynamic linker and the libraries that the programs need. * /bin/* A shell interpreter (ash because it is smaller than bash. The mount and losetup programs for handling the DOS disk and setting up the loopback devices. * /dev/* The devices that will be used. You need a /dev/hda[1-15] for IDE hard drives or /dev/sda[1-15] for SCSI, to mount your dos/win system, and a /dev/loop0 for the loopback device. * /mnt An empty directory to mount the dos/win partition on. The initial ramdisk = initrd.gz contents are listed below. drwxr-xr-x root/root 0 2000-09-26 14:34:49 bin/ -rwxr-xr-x root/root 52925 2000-08-06 13:22:55 bin/mount -rwxr-xr-x root/root 14297 2000-03-21 09:08:26 bin/losetup -rwxr-xr-x root/root 86300 2000-08-19 01:54:09 bin/ash drwxr-xr-x root/root 0 2000-09-26 14:22:34 dev/ crw------- root/tty 5,1 2000-09-26 14:22:34 dev/console brw-rw---- root/disk 7,0 2000-09-26 14:22:09 dev/loop0 brw-rw---- root/disk 7,1 2000-09-26 14:22:09 dev/loop1 brw-rw---- root/disk 3,1 2000-09-26 14:22:26 dev/hda1 crw--w--w- root/tty 4,0 2000-09-26 14:22:34 dev/tty0 drwxr-xr-x root/root 0 2000-09-26 14:21:58 lib/ -rwxr-xr-x root/root 73632 2000-05-03 19:20:40 lib/ld-2.1.3.so lrwxrwxrwx root/root 0 2000-09-26 14:21:56 lib/ld-linux.so.2 -> ld-2.1.3.so lrwxrwxrwx root/root 0 2000-09-26 14:21:58 lib/libc.so.6 -> libc-2.1.3.so -rwxr-xr-x root/root 888596 2000-05-03 19:20:41 lib/libc-2.1.3.so -rwxr-xr-x root/root 776 2000-09-26 14:27:08 linuxrc drwxr-xr-x root/root 0 2000-09-26 14:26:44 mnt/ Since my dos/win partition is on /dev/hda1, i only put that hard drive device in /dev above. You can copy the needed devices from your linux system to /mnt/initrd/dev or make them with 'mknod'. # cp -a /dev/{hda1,loop0,loop1,tty0,console} /mnt/initrd/dev The /linuxrc file on the initial ramdisk is required to do all of the preparations so that the loopback device can be used for the root partition when it exits. The example below tries to mount /dev/hda1 as a vfat = Win9x partition and if it succeeds then sets up the files /mnt/looplnx/looplnx.img as /dev/loop0. The above would be c:\looplnx\looplnx.img on your dos/win system. This is the linuxrc shell script... #!/bin/ash echo "INITRD: Trying to mount /dev/hda1 as type vfat..." >/dev/tty0 options="uid=0,gid=0,umask=0022,noexec,quiet" if /bin/mount -n -t vfat -o $options /dev/hda1 /mnt; then echo "INITRD: Mounted OK!" >/dev/tty0 /bin/losetup /dev/loop0 /mnt/looplnx/looplnx.img /bin/losetup /dev/loop1 /mnt/looplnx/swap.img exit 0 else echo "INITRD: Mount failed!" >/dev/tty0 exit 1 fi The above assumes you want to mount a Win9x system, if you want to mount a dos system put -t msdos instead of -t vfat for mount. The device /dev/loop0 will become the root device. If you want to be able to write to the DOS partition as a non-root user when you have finished then you should use options="uid=0,gid=0,umask=000,noexec,quiet" instead. This will map all accesses to the DOS partition to root and set the permissions appropriately. 3.4. Creating The Root Device: The root device that you will be using is the file looplnx.img. You will need to create this in the same way that the initial ramdisk was created, but bigger. You can install any Linux installation that you like onto this disk. You can't have a file larger than 2GB on a DOS FAT16 partition. You can't have a file larger than 4GB on a Win9x FAT32 partition. The file can be almost any size on a WINDOWS NTFS partition. You can't have one on a ext2/3 or reiserfs partition either, unless you're using kernel v2.4 or later or v2.2 that's been patched for large file support. For example, create a 300mb image called looplnx.img and put a ext2 filesystem on it. # dd if=/dev/zero of=looplnx.img bs=1M count=300 # mke2fs -F looplnx.img If you want to put a ext3 filesystem on it. You need mke2fs v1.20 or later for this! # mke2fs -j -F looplnx.img Or if you want to put a reiserfs filesystem on it. # mkreiserfs -f looplnx.img A reiserfs filesystem will require more space than ext2 because it needs to create a journal, you have to figure out what you'll need when you create looplnx.img above with dd. You can then mount looplnx.img under /mnt/loop and put what you want in it. # mkdir -p /mnt/loop # mount -t ext2 -o loop looplnx.img /mnt/loop The easiest way might be to copy an existing Linux installation into it. An alternative is to install a new Linux installation onto it. The looplnx.img image you create above must be big enough to hold whatever you want to put in it. You can see the used size of your linux system like this. # df -h Filesystem Size Used Avail Use% Mounted on /dev/hda2 1.5G 150M 1.3G 16% / To copy the current linux system to the looplnx.img image mounted under the /mnt/loop directory, you can use cp or tar. # cp -x -a / /mnt/loop # tar cvpl / | tar xpf - -C /mnt/loop Assuming that you have done this, there are some minor changes that you must make. The /etc/fstab file must reference the root partition (/dev/loop0). The /mnt/loop/etc/fstab file should have this for the / partition. /dev/loop0 / ext2 defaults 1 1 /dev/loop1 none swap sw 0 0 The above assumes it's a ext2 partition, if it were a 'reiserfs' or 'ext3' partition. /dev/loop0 / reiserfs defaults 0 0 /dev/loop0 / ext3 defaults 0 0 If you want to be able to read the DOS partition after Linux has started then you will need to make a number of extra small changes. Create a directory called /initrd, this is where the initial ramdisk will be mounted once the loopback root filesystem is mounted. # mkdir /mnt/loop/initrd Yow can move the Windows partition that's mounted under /initrd/mnt to /mnt/win, then free the RAM used by the initrd. You can put this in /mnt/loop/etc/rc.d/rc.local etc. if [ -d /initrd/mnt ]; then mkdir -p /mnt/win mount --move -t vfat /initrd/mnt /mnt/win umount -l /initrd blockdev --flushbufs /dev/ram0 fi When done unmount the looplnx.img image that's mounted under /mnt/loop. # umount /mnt/loop There is no need to have a Linux kernel on this root device since that is already loaded earlier. If you are using modules however then you should include them on this device as normal. 3.5. Creating the Swap File: The swap file is very simple to create. Create an empty file as was done for the initial ramdisk and then run mkswap swap.img to intialise it. # dd if=/dev/zero of=swap.img bs=1M count=8 # mkswap swap.img The size of the swap space will depend on what you plan to do with the installed system, but I would recommend between 8MB and the amount of RAM that you have. 3.6. Creating the MSDOS Directory: The files that are going to be used need to be moved onto the DOS partition. * LOOPLNX.IMG The disk image that will become the root device. * SWAP.IMG The swap space. Create a c:\looplnx directory and put looplnx.img and swap.img in it. C:\ mkdir looplnx 3.7. Creating a DOS boot floppy: The boot floppy that is used is just a normal DOS format bootable floppy. This is created like this from DOS. Put a floppy in the drive. C:\ format a: /s Onto this disk you will need to create an AUTOEXEC.BAT file (as below) and copy the kernel, compressed initial ramdisk and LOADLIN executable. * AUTOEXEC.BAT The DOS automatically executed batch file. * LOADLIN.EXE The LOADLIN program executable. * ZIMAGE The Linux kernel. * INITRD.GZ The compressed initial ramdisk image. The AUTOEXEC.BAT file should contain just one line as below. \looplnx\loadlin \looplnx\zImage initrd=\looplnx\initrd.gz root=700 ro This specifies the kernel image to use, the initial ramdisk image, the root device after the initial ramdisk has finished and that the root partition is to be mounted read-only. 3.8. Booting from DOS hard drive: You can boot c:\looplnx\looplnx.img from the hard drive using loadlin. c:\looplnx> loadlin bzimage initrd=initrd.gz root=700 ro You should be able to put root=700 or root=/dev/loop0, they're the same device, but some kernels may not work with /dev/loop0. 4. Booting the System: To boot from this new root device all that is required is that the floppy disk prepared as described above is inserted for the PC to boot from. You will see the following sequence of events. 1. DOS boots 2. AUTOEXEC.BAT starts 3. LOADLIN is run 4. The Linux kernel is copied into memory 5. The initial ramdisk is copied into memory 6. The Linux kernel is started running 7. The /linuxrc file on the initial ramdisk is run 8. The DOS partition is mounted and the root and swap devices set up 9. The boot sequence continues from the loopback device When this is complete you can remove the boot floppy and use the Linux system. 4.1. Possible Problems With Solutions There are a number of stages where this process could fail, I will try to explain what they are and what to check. DOS booting is easy to recognise by the message that it prints MS-DOS Starting ... on the screen. If this is not seen then the floopy disk is either not-bootable or the PC is not bootable from the floppy disk drive. When the AUTOEXEC.BAT file is run the commands in it should be echoed to the screen by default. In this case there is just the single line in the file that starts LOADLIN. When LOADLIN executes it will do two very visible things, firstly it will load the kernel into memory, secondly it will copy the ramdisk into memory. Both of these are indicated by a Loading... message. The kernel starts by uncompressing itself, this can give crc errors if the kernel image is corrupted. Then it will start running the initialisation sequence which is very verbose with diagnostic messages. Loading of the initial ramdisk device is also visible during this phase. When the /linuxrc file is run there is no diagnostic messages, but you can add these yourself as an aid to debugging. If this stage fails to set up the loopback device as the root device then you may see a message that there is no root device and the kernel aborts. The normal boot sequence of the new root device will now continue and this is quite verbose. There may be problems about the root device being mounted read-write, but the LOADLIN command line option 'ro' should stop that. Other problems that can occur are that the boot sequence is confused about where the root device is, this is probably due to a problem with /etc/fstab. When the boot sequence has completed, the remaining problem is that programs are confused about whether the DOS partition is mounted or not. This is why it is a good idea to use the fake mount command described earlier. This makes life a lot easier if you want to access the files on the DOS device. 4.2. Reference Documents The documents that I used to create my first loopback root filesystem were: * The Linux kernel source, in particular init/main.c * The Linux kernel documentation, in particular Documentation/initrd.txt and Documentation/ramdisk.txt. * The LILO documentation. * The LOADLIN documentation 5. Other Loopback Root Device Possibilities Once the principle of booting a filesystem in a file on a DOS partition has been established there are many other things that you can now do. 5.1. DOS Hard-disk Only Installation If it is possible to boot Linux from a file on a DOS harddisk by using a boot floppy then it is obviously also possible to do it using the harddisk itself. A configuration boot menu can be used to give the option of running LOADLIN from within the AUTOEXEC.BAT. This will give a much faster boot sequence, but is otherwise identical. 5.2. LILO Booted Installation Using LOADLIN is only one option for booting a Linux kernel. There is also LILO that does much the same but without needing DOS. In this case the DOS format floppy disk can be replaced by an ext2fs format one. Otherwise the details are very similar, with the kernel and the initial ramdisk being files on that disk. The reason that I chose the LOADLIN method is that the arguments that need to be given to LILO are slightly more complex. Also it is more obvious to a casual observer what the floppy disk is since it can be read under DOS. You can make a lilo boot floppy that will boot a loop linux system, like this. Format a floppy to 1.44mb with fdformat or superformat. # fdformat -n /dev/fd0u1440 # superformat -f /dev/fd0u1440 Create a ext2 filesystem on the floppy. # mke2fs -m0 /dev/fd0u1440 Have lilo the boot loader installed, you should have /boot/boot.b from the lilo package on your system. Create a lilo.conf file with this in it. boot = /dev/fd0 backup = /dev/null prompt compact vga = normal image = /boot/kernel label = linux read-only image = /boot/kernel label = looplinux append="root=700 ro" initrd = /boot/initrd.gz Mount the floppy and do these things below. # mount -t ext2 /dev/fd0 /mnt/floppy # rmdir /mnt/floppy/lost+found # mkdir -p /mnt/floppy/boot # mkdir /mnt/floppy/dev # mkdir /mnt/floppy/etc # mkdir /mnt/floppy/tmp # cp -a /dev/null /mnt/floppy/dev # cp -a /dev/fd0 /mnt/floppy/dev # cp /boot/boot.b /mnt/floppy/boot # cp lilo.conf /mnt/floppy/etc Copy a kernel = zImage or bzImage to the floppy, also copy initrd.gz to the floppy. # cp zImage /mnt/floppy/boot/kernel # cp initrd.gz /mnt/floppy/boot Run lilo on the floppy. # lilo -v -r /mnt/floppy Unmount the floppy, it should be ready to boot now! # umount /mnt/floppy At the LILO boot prompt do this to boot the loop linux system. boot: looplinux If you want to use the kernel on the floppy to boot a linux system that's on it's own partition, tell lilo where it is 'root=/dev/xxxx'. boot: linux root=/dev/hda2 5.3. GRUB Booted Installation You can make a grub boot floppy that will boot a loop linux system, like this. Format a floppy to 1.44mb with fdformat or superformat. # fdformat -n /dev/fd0u1440 # superformat -f /dev/fd0u1440 Create a dos or ext2 filesystem on the floppy. # mkdosfs /dev/fd0u1440 Create a menu.lst file with this in it. title Boot Loop Linux system root (fd0) kernel /boot/kernel root=700 ro initrd /boot/initrd.gz Mount the floppy and do these things below. You may find stage1 and stage2 in /usr/share/grub or /usr/lib/grub. # mount -t msdos /dev/fd0 /mnt/floppy # mkdir -p /mnt/floppy/boot/grub # cp /boot/grub/stage1 /mnt/floppy/boot/grub # cp /boot/grub/stage2 /mnt/floppy/boot/grub # cp menu.lst /mnt/floppy/boot/grub # cp menu.lst /mnt/floppy/boot/grub/grub.conf Copy a kernel = zImage or bzImage to the floppy, also copy initrd.gz to the floppy. # cp zImage /mnt/floppy/boot/kernel # cp initrd.gz /mnt/floppy/boot Unmount and run grub on the floppy. # umount /mnt/floppy # grub grub> root (fd0) grub> setup (fd0) grub> quit It should be ready to boot now! At the GRUB menu choose "Loop Linux" to boot the loop linux system. If you want to use the kernel on the floppy to boot a linux system that's on it's own partition, tell grub where it is. Press the `c' key to get a grub command prompt. For example (hd0,0) = /dev/hda1, (hd0,1) = /dev/hda2, etc. grub> kernel /boot/kernel root=/dev/hda2 ro grub> boot 5.4. SYSLINUX Booted Installation: http://syslinux.zytor.com/ You can make a SYSLINUX boot floppy that will boot a loop linux system, like this. Format a floppy to 1.44mb with fdformat or superformat. # fdformat -n /dev/fd0u1440 # superformat -f /dev/fd0u1440 If you use superformat above it will call mformat to put a dos filesystem on the floppy, so you don't need to use mkdosfs below if you have mformat. Create a dos filesystem on the floppy. # mkdosfs /dev/fd0u1440 Create a syslinux.cfg file with this in it. PROMPT 1 LABEL looplinux KERNEL kernel APPEND vga=normal initrd=initrd.gz root=700 ro LABEL linux KERNEL kernel APPEND vga=normal load_ramdisk=0 ro Mount the floppy. # mount -t msdos /dev/fd0 /mnt/floppy Copy a kernel = zImage or bzImage to the floppy, also copy initrd.gz and syslinux.cfg to the floppy. # cp zImage /mnt/floppy/kernel # cp initrd.gz /mnt/floppy # cp syslinux.cfg /mnt/floppy Unmount the floppy and run syslinux on it. # umount /mnt/floppy # syslinux /dev/fd0u1440 It should be ready to boot now! At the SYSLINUX boot prompt do this to boot the loop linux system. boot: looplinux If you want to use the kernel on the floppy to boot a linux system that's on it's own partition, tell where it is 'root=/dev/xxxx'. boot: linux root=/dev/hda2 You can get syslinux here... ftp://ftp.kernel.org/pub/linux/utils/boot/syslinux 5.5. NTFS Installation The only change for the NTFS option is in the initial ramdisk = initrd.gz, the file /linuxrc needs to mount a file system of type ntfs rather than msdos or vfat. The NTFS write support is dangerous in the current 2.6 kernels. If in a future kernel it becomes more stable you can use it then. You can't boot a kernel using `loadlin.exe' under winNT/2000/XP, you would need to use a boot floppy created by `syslinux' etc. Topologilinux has a method for Installing and booting Linux on a NTFS partition, using GRUB. See 6.0 below. 5.6. Installing Linux without Re-partitioning The process of installing Linux on a PC from a standard distribution requires booting from a floppy disk and re-partitioning the disk. This stage could instead be accomplished by a boot floppy that creates an empty loopback device and swap file. This would allow the installation to proceed as normal, but it would install into the loopback device rather than a partition. This could be used as an alternative to a UMSDOS installation, it would be more efficient in disk usage since the minimum allocation unit in the ext2 filesystem is 1kB instead of up to 32kB on a DOS partition. It can also be used on VFAT and NTFS formatted disks which are otherwise a problem. 5.7. Booting From a Non-bootable device This method can also be used to boot a Linux system from a device that is not normally bootable. * CD-Rom * Zip Disks * Parallel port disk drives Obviously there are many other devices that could be used, NFS root filesystems are already included in the kernel as an option, but the method described here might also be used instead. 5.8. Resizing a loop linux system: You can enlarge or reduce the size of a ext2/3 loop linux image, you would use 'ext2resize' to do this. The loop linux image can't be more than 2040MB on a DOS fat16 partition. The loop linux image can't be more than 4090MB on a Win fat32 partition. For example, if you want to enlarge the loop linux image. First get the size of the loop linux image 'looplnx.img'. # du -m looplnx.img "Show size in megabytes!" 300 looplnx.img It says the size is 300mb, I want to add 100mb to it. # dd if=/dev/zero of=looplnx.img bs=1M seek=300 count=100 seek=300 means find the point that's 300mb into the image, and count=100 means add 100mb to that point, total 400mb. Run resize2fs on the enlarged 400mb image, it will resize the ext2 filesystem on it to fill the image. # resize2fs looplnx.img For example, if you want to reduce the loop linux image. Run resize2fs on the image and have it rezize the 300mb ext2 filesystem on it to 200mb. # resize2fs looplnx.img 200M Run 'dd' on the 300mb image to reduce it to 200mb. # dd if=/dev/zero of=looplnx.img bs=1M seek=200 count=0 seek=200 means find the point that's 200mb into the image, and count=0 means add nothing to that point, total 200mb. Resize2fs is part of the e2fsprogs package. The above is a little confusing, if you make a mistake you'll loose whatever is on the loop linux image. I just mention the above so you'll know it's possible to resize a ext2/3 filesystem, whether it's on a image or a partition. If you wanted to resize a image with a reiserfs filesystem on it, you would use 'resize_reiserfs'. For example, if you want to enlarge the loop linux image. First get the size of the loop linux image 'looplnx.img'. # du -m looplnx.img "Show size in megabytes!" 300 looplnx.img It says the size is 300mb, i want to add 100mb to it. # dd if=/dev/zero of=looplnx.img bs=1M seek=300 count=100 # resize_reiserfs -s+100M -f looplnx.img For example, if you want to reduce the 300mb loop linux image to 200mb. Run resize_reiserfs on the image and have it rezize the 300mb reiserfs filesystem on it to 200mb. # resize_reiserfs -s-100M -f looplnx.img Run 'dd' on the 300mb image to reduce it to 200mb. # dd if=/dev/zero of=looplnx.img bs=1M seek=200 count=0 If you need more space then 4GB on the loop linux system, you could create another loop image file and copy the /usr directory to it, then have it mounted at boot time. The file must be at least large enough to hold the contents of the /usr directory, it can't be more than 4000MB on a FAT32 partition. # du -sm /usr "Show size of /usr directory in megabytes!" 700 Create a 2000MB etc. file and put a filesystem on it. # dd if=/dev/zero of=/initrd/mnt/looplnx/usr.img bs=1M count=2000 # mke2fs -F /initrd/mnt/looplnx/usr.img # mkreiserfs -f /initrd/mnt/looplnx/usr.img "For a reiserfs!" Mount the loop file and copy the contents of /usr to it. # mount -o loop /initrd/mnt/looplnx/usr.img /mnt/loop # cp -x -a /usr/* /mnt/loop # umount /mnt/loop Put this in /etc/fstab. /dev/loop0 / ext2 defaults 1 1 /dev/loop1 none swap sw 0 0 /initrd/mnt/looplnx/usr.img /usr ext2 defaults,loop=/dev/loop2 1 2 If it were a reiserfs filesystem. /dev/loop0 / reiserfs defaults 0 0 /dev/loop1 none swap sw 0 0 /initrd/mnt/looplnx/usr.img /usr reiserfs defaults,loop=/dev/loop2 0 0 Delete the contents of the /usr directory. # rm -rf /usr/* # reboot 5.9. Loop encrypted filesystem: You can encrypt the filesystem on the loop image, so a password is required to mount it. The v2.6 kernel has support builtin. 6.0. LoopLinux and Topologilinux distributions: LoopLinux is a way to install and run a Slackware Linux distribution from a DOS/Win9x system, using the loop device. LoopLinux home site... http://www.tux.org/pub/people/kent-robotti/looplinux/index.html ftp://ftp.tux.org/pub/people/kent-robotti/looplinux There's another distribution called "Topologilinux' that also does this, but it can also install on a Windows NTFS NT/2K/XP partition. http://topologi-linux.sourceforge.net/ 6.1. LINUXRC.C This will do the same thing as the initrd above, except it's smaller. It mounts the dos or win partition and associates the image file \looplnx\looplnx.img with the loop device /dev/loop0. You create the initrd like above, but you only have this on it. drwxr-xr-x root/root 0 2000-09-26 14:22:34 dev/ crw------- root/tty 5,1 2000-09-26 14:22:34 dev/console brw-rw---- root/disk 3,1 2000-09-26 14:22:26 dev/hda1 crw--w--w- root/tty 4,0 2000-09-26 14:22:34 dev/tty0 lrwxrwxrwx root/root 0 2000-09-26 14:21:58 dev/win -> hda1 -rwxr-xr-x root/root 205272 2000-09-26 14:27:08 linuxrc In the above example i have a win9x partition with \looplnx\looplnx.img on /dev/hda1, so i make a link called win to it 'ln -sf hda1 win'. If it were a dos partition it would be 'ln -sf hda1 dos'. If it were a ntfs partition it would be 'ln -sf hda1 winnt'. /* This is the source for linuxrc. * * You can compile it this way. * gcc -Os -march=i386 -D_FILE_OFFSET_BITS=64 -static -s -o linuxrc linuxrc.c * * You could use a smaller static libc, called uClibc. * http://www.uclibc.org/ */ #include #include #include #include #include #include #undef dev_t #define dev_t __kernel_dev_t #include #undef dev_t void die(char *s) { write(2,s,strlen(s)); } int set_loop(const char *device, const char *file, int offset, int loopro) { struct loop_info loopinfo; int fd, ffd, mode, i; char *pass; mode = loopro ? O_RDONLY : O_RDWR; if ((ffd = open (file, mode)) < 0 && !loopro && (errno != EROFS || (ffd = open (file, mode = O_RDONLY)) < 0)) { perror (file); return 0; } if ((fd = open (device, mode)) < 0) { perror (device); return 0; } loopro = (mode == O_RDONLY); memset(&loopinfo, 0, sizeof(loopinfo)); strncpy(loopinfo.lo_name, file, LO_NAME_SIZE); loopinfo.lo_name[LO_NAME_SIZE-1] = 0; loopinfo.lo_offset = offset; loopinfo.lo_encrypt_key_size = 0; if (ioctl(fd, LOOP_SET_FD, ffd) < 0) { perror("ioctl: LOOP_SET_FD"); exit(1); } if (ioctl(fd, LOOP_SET_STATUS, &loopinfo) < 0) { (void) ioctl(fd, LOOP_CLR_FD, 0); perror("ioctl: LOOP_SET_STATUS"); exit(1); } close(fd); close(ffd); return 1; } int main(void) { int i,notmounted; FILE *distfile; distfile=fopen("/dev/dos","r"); if (distfile) { fclose(distfile); mkdir("/dos",0755); notmounted=mount("/dev/dos","/dos","msdos",MS_MGC_VAL | MS_NOEXEC,"quiet,umask=0022",0); if (notmounted) { die("\n\tERROR!\tCould not mount the DOS partition!\n"); die("\n\t\tPress Ctrl-Alt-Del to reboot!\n"); pause(); exit(1); } distfile=fopen("/dos/loopslak/loopslak.img","r"); if (!distfile) { die("\n\tERROR!\tCould not find \\loopslak\\loopslak.img on the DOS system!\n"); die("\n\t\tPress Ctrl-Alt-Del to reboot!\n"); umount("/dos"); pause(); exit(1); } fclose(distfile); umask(0); mknod("/dev/loop0",0660|S_IFBLK,7 * 256 + 0); mknod("/dev/loop1",0660|S_IFBLK,7 * 256 + 1); if(!(set_loop("/dev/loop0","/dos/loopslak/loopslak.img",0,0))) { die("\n\tERROR!\tCan't associate \\loopslak\\loopslak.img\n"); die("\t\twith the loop device /dev/loop0!\n"); die("\n\t\tPress Ctrl-Alt-Del to reboot!\n"); umount("/dos"); pause(); exit(1); } distfile=fopen("/dos/loopslak/swap.img","r"); if (distfile) { if(!(set_loop("/dev/loop1","/dos/loopslak/swap.img",0,0))) { die("WARNING! Can't associate \\loopslak\\swap.img " "with loop device /dev/loop1.\n"); } } fclose(distfile); die("INITRD: Mounted DOS partition under /initrd/dos directory...\n"); exit(0); } else distfile=fopen("/dev/win","r"); if (distfile) { fclose(distfile); mkdir("/win",0755); notmounted=mount("/dev/win","/win","vfat",MS_MGC_VAL | MS_NOEXEC,"quiet,umask=0022",0); if (notmounted) { die("\n\tERROR!\tCould not mount the Windows partition!\n"); die("\n\t\tPress Ctrl-Alt-Del to reboot!\n"); pause(); exit(1); } distfile=fopen("/win/loopslak/loopslak.img","r"); if (!distfile) { die("\n\tERROR!\tCould not find \\loopslak\\loopslak.img on the Windows system!\n"); die("\n\t\tPress Ctrl-Alt-Del to reboot!\n"); umount("/win"); pause(); exit(1); } fclose(distfile); umask(0); mknod("/dev/loop0",0660|S_IFBLK,7 * 256 + 0); mknod("/dev/loop1",0660|S_IFBLK,7 * 256 + 1); if(!(set_loop("/dev/loop0","/win/loopslak/loopslak.img",0,0))) { die("\n\tERROR!\tCan't associate \\loopslak\\loopslak.img\n"); die("t\twith the loop device /dev/loop0!\n"); die("\n\t\tPress Ctrl-Alt-Del to reboot!\n"); umount("/win"); pause(); exit(1); } distfile=fopen("/win/loopslak/swap.img","r"); if (distfile) { if(!(set_loop("/dev/loop1","/win/loopslak/swap.img",0,0))) { die("WARNING! Can't associate \\loopslak\\swap.img " "with loop device /dev/loop1.\n"); } } fclose(distfile); die("INITRD: Mounted Windows partition under /initrd/win directory...\n"); exit(0); } else distfile=fopen("/dev/winnt","r"); if (distfile) { fclose(distfile); mkdir("/win",0755); notmounted=mount("/dev/winnt","/win","ntfs",MS_MGC_VAL | MS_NOEXEC,"fmask=0133,dmask=0022",0); if (notmounted) { die("\n\tERROR!\tCould not mount the Windows NTFS partition!\n"); die("\n\t\tPress Ctrl-Alt-Del to reboot!\n"); pause(); exit(1); } distfile=fopen("/win/loopslak/loopslak.img","r"); if (!distfile) { die("\n\tERROR!\tCould not find \\loopslak\\loopslak.img on the Windows NTFS system!\n"); die("\n\t\tPress Ctrl-Alt-Del to reboot!\n"); umount("/win"); pause(); exit(1); } fclose(distfile); umask(0); mknod("/dev/loop0",0660|S_IFBLK,7 * 256 + 0); mknod("/dev/loop1",0660|S_IFBLK,7 * 256 + 1); if(!(set_loop("/dev/loop0","/win/loopslak/loopslak.img",0,0))) { die("\n\tERROR!\tCan't associate \\loopslak\\loopslak.img\n"); die("t\twith the loop device /dev/loop0!\n"); die("\n\t\tPress Ctrl-Alt-Del to reboot!\n"); umount("/win"); pause(); exit(1); } distfile=fopen("/win/loopslak/swap.img","r"); if (distfile) { if(!(set_loop("/dev/loop1","/win/loopslak/swap.img",0,0))) { die("WARNING! Can't associate \\loopslak\\swap.img " "with loop device /dev/loop1.\n"); } } fclose(distfile); die("INITRD: Mounted Windows NTFS partition under /initrd/win directory...\n"); exit(0); } die("\n\tERROR!\tCould not find a device /dev/dos, /dev/win,\n"); die("\t\tor /dev/winnt to mount!\n"); die("\n\t\tPress Ctrl-Alt-Del to reboot!\n"); pause(); exit(1); } /* End of linuxrc.c */ End! ---------------------------------------------------------------------------