- 论坛徽章:
- 0
|
从映像文件引导,使用ramdisk为根目录的freebsd。
呵呵,刚发完贴子就看到这篇文章,献上:
Building Monolithic Kernels and Root Filesystems for FreeBSD
David Yeske <dyeske@yahoo.com>;
This article explains an alternative method of creating a kernel that contains a root file system image within it. This single-file kernel and file system can be used in many ways beyond what usual FreeBSD kernels allow, just as having the root file system loaded along with the kernel enables you to have more flexibility in the boot process.
A utility called write_mfs_in_kernel was once used to create a monolithic kernel and mfsroot (memory resident root file system). However, write_mfs_in_kernel has been removed from FreeBSD. Since the functionality was still important, I needed a replacement.
Here are examples of basic uses of this mechanism:
* Network booting with a preloaded root file system without needing a PXE client or NFS server
* Loading PicoBSD from a TFTP image
* Thin terminals
* Embedded systems
* Data recovery
* Fully automated and unattended FreeBSD installation that works with any network device supported by grub or etherboot
* Any other method where /boot/loader or /boot/pxeboot cannot be used
The flexibility of a monolithic kernel allows FreeBSD to be loaded in many situations. Here are additional examples where this can be used.
* If a floppy disk has grub or etherboot installed, then FreeBSD can be loaded over tftp and is not required to be in the same subnet as the tftp server. This allows any computer with an internet connection to run picobsd or the FreeBSD installer with one floppy disk. The size of the FreeBSD kernel with mfsroot is not limited to the size of the floppy, either.
* An image could be made containing the FreeBSD installer with sshd added. This allows for a remote install using an inbound ssh connection. Access control configuration could be stored on a FAT formatted floppy disk. Users could modify the configuration on a machine that is not running FreeBSD and enter in information provided by a remote administrator.
* A machine can download a monolithic kernel onto a drive formatted with FAT32, ext2, or anything else supported by grub or etherboot. This permits installation onto a machine that does not have a bootable 1.44M floppy drive or a bootable cdrom drive. Some laptops and older machines could benefit from this.
* An average PC could quickly become a router, firewall, mp3 server, or X terminal that would not need to modify or remove the existing operating system.
Comparison
The alternative method uses the objcopy program, which is part of GNU binutils. It is used to convert a mfsroot image into an ELF object that can be linked into the FreeBSD kernel. The md device is modified so that it can reference both the beginning and end of the mfsroot from weak symbols that objcopy adds to the mfsroot image before the kernel is linked. Currently this requires the kernel to be recompiled every time you want to replace the image; once a kernel is compiled using this method, the root file system might be able to be replaced by relinking the kernel rather than recompiling it.
The write_mfs_in_kernel method required padding (options MD_ROOT_SIZE) to be added to a kernel, the kernel compiled, and the root file system inserted into it via write_mfs_in_kernel. This allowed a mfsroot image to be inserted into a kernel as long as it was less than the size of the padding. The mfsroot image could also be replaced without having to recompile or relink the kernel. A mfsroot image larger than the size of the padding would require the kernel to be recompiled with more padding though. NetBSD and OpenBSD currently use a similar technique.
I am also working on adding additional functionality so that an arbitrary file can be linked into the kernel and attached to a vnode backed md device during the kernel load. Another benefit to the objcopy method is that it can be extended to have more than one root file system per kernel, which can be referenced via ufs:/dev/md0c, ufs:/dev/md1c, etc... Further development could lead to a distribution of FreeBSD that can live in a file that is not on a drive formatted with ufs. QNX can live in a file on a FAT32 partition, and BeOS was also able to. There are also Linux distributions that can live in a file via the loopback interface. Novice users might want to initially try out FreeBSD in a symbiotic way that does not require another partition, especially if their drive is already formatted with FAT32.
Kernel Construction Overview
The following steps were used to create a FreeBSD kernel and mfsroot image from the 4.7-RELEASE install sets. There is a link to a usable image here that can be used to install FreeBSD 4.7-RELEASE. First, the following patch must be applied so the kernel and md device will have support for the objcopy method. This patch should apply clean to RELENG_4_7_0_RELEASE and not have any effect on a system when MD_ROOT_IMAGE is not defined. This method also works on FreeBSD current, but the code is slightly different. Next the BOOTMFS kernel config file that is created during a make release was modified by adding these 2 lines:
makeoptions MD_ROOT_IMAGE="/tmp/mdimage.o"
options MD_ROOT_IMAGE
The makeoptions MD_ROOT_IMAGE="/tmp/mdimage.o" line adds the mdimage.o object file to the list of files to be linked into the kernel.
The options MD_ROOT_IMAGE line is needed so the md device will compile with some extra definitions.
The next step is to run the following commands that remove the mfsroot image from the mfsroot.flp floppy image.
# vnconfig -v vn1 mfsroot.flp
/dev/vn1: 0 bytes on mfsroot.flp
# mount /dev/vn1 /mnt
# cp /mnt/mfsroot.gz .
# umount /mnt
# vnconfig -v -u vn1
/dev/vn1: cleared
# gzip -d mfsroot.gz
An ELF object must be created from the mfsroot image and symbols added to it so the kernel can mount it as the root file system. The mfsroot file is copied to a file called mdimage so that the symbols will work properly. Objcopy is then used to create the ELF object file with symbols that can be linked in with the kernel.
# cp mfsroot /tmp/mdimage
# cd /tmp
# objcopy -v -I binary -O elf32-i386 -B i386 --redefine-sym _binary_mdimage_start=__md_root_image_start --redefine-sym _binary_mdimage_end=__md_root_image_end mdimage mdimage.o
copy from mdimage(binary) to mdimage.o(elf32-i386)
The __md_root_image_start and __md_root_image_end arguments redefine the the start and end address of the mdimage.o object file so that the md device can reference the weak symbols.
The mdimage.o file is slightly larger (428 bytes) than the original mfsroot image that was copied to mdimage.
4423680 mdimage compared with 4424108 mdimage.o
Make release was run in order to get the BOOTMFS kernel definition file and test this after 4.7-RELEASE was tagged. A kernel was built as follows without modules because they are already on the mfsroot image file system in /stand/modules.
# cd /usr/src && make buildkernel KERNCONF=BOOTMFS NO_MODULES=yes
The result of applying these steps resulted in a kernel of the following size :
7815765 kernel
Size difference between new kernel compared with original BOOTMFS kernel:
3363818 BOOTMFS
# echo $((7815765 - 336381 ) 4451947
Increase in size of kernel for objcopy method not including mfsroot image:
# echo $((4451947 - 4423680)) 28267
Approximately 28k was lost using this process which is less than the size of the /boot/loader file on the boot.flp image:
84875 Oct 9 11:22 loader
A kernel image created with this method can be loaded using /boot/loader or /boot/pxeboot just like a normal kernel can, but it can also be loaded from grub or etherboot. This method has also been tested after running strip on a kernel.
Acknowledgments
I would like to thank Poul-Henning Kamp and Jerry Hicks for all their effort and input. They made it possible for me to progress this far. I would also like to thank everyone that provided me with technical feedback. |
|