Ключевые слова:freebsd, disk, install, (найти похожие документы)
From: Михаил Захаров <zakharov@ipb.redline.ru>
Subject: UNIX на одной дискете (по следам PicoBSD)
UNIX на одной дискете (по следам PicoBSD)
Михаил Захаров <zakharov@ipb.redline.ru>
Содержание
1. Введение
2. Ядро
3. crunchgen
4. mfsroot
5. Загрузочная дискета
1. Введение
Проблема подготовки загрузочной дискеты во FreeBSD обычно решается при
помощи дистрибутива PicoBSD, который поставляется вместе с пакетом
исходных кодов. Однако, бывают случаи когда такую дискету требуется
подготовить своими руками.
Программные файлы FreeBSD обладают весьма внушительными размерами
(например, во FreeBSD 4.6 файл команды ls занимает чуть менее 300Кб),
поэтому основная проблема при подготовке загрузочной дискеты это
острая нехватка свободного пространства. По этой причине от простого
размещения файлов программ на дискете приходится отказаться, и в таком
случае, возможна организация файловой системы в виртуальной памяти
компьютера (MFS), где и будет храниться львиная доля всех файлов.
Впрочем, это не относится к парадоксальной ситуации с ядром, которое
должно располагаться на дискете в корневой директории, несмотря на то,
что в обычном состоянии его размеры намного превосходят объем
стандартной дискеты. Кроме того, при использовании MFS необходимо
учитывать, что эта файловая система считывается из файла образа и
отображается на оперативную память и, что естественно, любые изменения
в файлах при каждой перезагрузке системы будут уничтожаться. Поэтому,
использовать MFS для хранения конфигурационных файлов очень неудобно.
Подобные обстоятельства делают процесс подготовки загрузочной дискеты
довольно сложным и сильно отличающимся от аналогичной операции в
MS-DOS. Поэтому в двух словах поясню последовательность наших
действий:
1. Для начала, подготовим и сожмем при помощи gzip ядро, с
минимальным набором опций, не забыв, однако, включить в него
поддержку MFS.
2. При помощи crunchgen соберем из исходных кодов один программный
файл, объединяющий в себе основные программы операционной системы.
3. Далее создадим mfsroot - образ файловой системы в виртуальной
памяти, наполним его к файлами устройств и запишем на него
crunch'еный бинарник.
4. Подготовим файлы конфигурации и основные скрипты загрузки системы.
В нашем случае эти файлы придется разделить на две группы:
изменяемые и неизменяемые. Файлы первой группы будут размещены на
файловой системе дискеты в каталоге /etc вне MFS, и,
следовательно, при необходимости, могут быть изменены, файлы
второй группы будут записаны на MFS и соответственно, изменения в
них будут сохраняться до первой перезагрузки системы.
5. Подготовим образ дискеты и запишем на него загрузчики ОС boot1,
boot2 и loader. В loader.rc укажем, что при загрузке необходимо
загрузить ядро kernel и из файла mfsroot организовать файловую
систему в виртуальной памяти компьютера, Далее на образ дискеты
запишем ядро и сжатый gzip'ом mfsroot, в каталог /etc поместим
оставшиеся модифицируемые конфигурационные файлы.
Для наших опытов будем использовать FreeBSD 4.6-Release c полным
наборов установленных исходных кодов.
2. Ядро
Нам нужно ядро, которое на дискете занимало бы как можно меньше места.
Поэтому выбросим из него все лишнее и оставим, только самое
необходимое. Допустим, что наше ядро будет называться SMALL, тогда
создаем в каталоге /usr/src/sys/i386/conf файл SMALL:
machine i386
cpu I586_CPU
cpu I686_CPU
ident SMALL
maxusers 10
options MATH_EMULATE # Support for x87 emulation
options INET # InterNETworking
options FFS # Berkeley Fast Filesystem
options FFS_ROOT # FFS usable as root device [keep this!]
options MFS # Memory Filesystem
options MD_ROOT # MD is a potential root device
options NFS # Network Filesystem
options CD9660 # ISO 9660 Filesystem
options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
device isa
device pci
# Floppy drives
device fdc0 at isa? port IO_FD1 irq 6 drq 2
device fd0 at fdc0 drive 0
# ATA and ATAPI devices
device ata0 at isa? port IO_WD1 irq 14
device ata1 at isa? port IO_WD2 irq 15
device ata
device atadisk # ATA disk drives
device atapicd # ATAPI CDROM drives
options ATA_STATIC_ID # Static device numbering
# atkbdc0 controls both the keyboard and the PS/2 mouse
device atkbdc0 at isa? port IO_KBD
device atkbd0 at atkbdc? irq 1 flags 0x1
device vga0 at isa?
# syscons is the default console driver, resembling an SCO console
device sc0 at isa? flags 0x100
# Floating point support - do not disable.
device npx0 at nexus? port IO_NPX irq 13
# PCI Ethernet NICs that use the common MII bus controller code.
# NOTE: Be sure to keep the 'device miibus' line in order to use these NICs!
device miibus # MII bus support
device xl # 3Com 3c90x (``Boomerang'', ``Cyclone'')
# Pseudo devices - the number indicates how many units to allocate.
pseudo-device loop # Network loopback
pseudo-device ether # Ethernet support
pseudo-device pty # Pseudo-ttys (telnet etc)
pseudo-device md # Memory "disks"
Примеры нескольких подобных ядер можно взять у PicoBSD
(/usr/src/release/picobsd). В принципе, в ядро можно включить любые
опции и драйвера, оптимизированные для каждого конкретного случая,
однако необходимо помнить, что поскольку ядро будет загружать
MFS-файловую систему, следующие строки обязательны:
options MFS # Memory Filesystem
options MD_ROOT # MD is a potential root device
pseudo-device md # Memory "disks"
теперь компилируем ядро:
config SMALL; cd ../../compile/SMALL; make depend; make all
Если все прошло удачно, у нас появится ядро, которое по нашим
представлениям должно быть эталоном миниатюрности. Для справки, на
FreeBSD 4.6 размер такого ядра у меня получился 1705820 байт, что все
равно превышает объем 1,44Мб.
Остается "почистить" скомпилированное ядро:
strip kernel
strip --remove-section=.note --remove-section=.comment kernel
и наконец сжать его:
gzip -v -n --best kernel
В результате компрессии, ядро стало занимать чуть более 600 Кбайт.
Итак, нам удалось сократить размеры ядра более чем в 2 раза! И у нас
остается еще место для корневой файловой системы.
3. Crunchgen
Проблему размещения программных файлов постараемся разрешить при
помощи программы /usr/bin/crunchgen, спасибо James da Silva
(jds@cs.umd.edu). Эта программа собирает один большой бинарный файл
из исходных кодов нескольких программ. Напишем для нее собственный
конфигурационный файл crunch.conf:
buildopts -DNOIPSEC -DRELEASE_CRUNCH -DCRUNCHED_BINARY -DNOSECURE -DNOCRYPT -DNOPAM
srcdirs /usr/src/bin
srcdirs /usr/src/sbin/i386
srcdirs /usr/src/sbin
srcdirs /usr/src/usr.bin
srcdirs /usr/src/gnu/usr.bin
srcdirs /usr/src/usr.sbin
srcdirs /usr/src/libexec
progs sh test echo hostname ln login getty stty
progs inetd telnetd
progs w kget reboot
progs init ifconfig df cat
progs cp rm mknod chmod chown mkdir ls syslogd
progs sysctl route pwd_mkdb dev_mkdb
progs mount umount swapon disklabel vnconfig
progs kill mount_std
progs pwd telnet
progs passwd date
progs mount_cd9660 mount_nfs ping traceroute
ln mount_cd9660 cd9660
ln mount_nfs nfs
ln test [
ln sh -sh
ln mount_std procfs
ln mount_std mount_procfs
ln chown chgrp
libs -lncurses -lmytinfo -lipx -lz -lpcap -lalias -lwrap
libs -ledit -lutil -lmd -lcrypt -lmp -lgmp -lm -lkvm
libs -lgnuregex -ltermcap -lipsec /usr/src/lib/libtelnet/libtelnet.a
По правде говоря, для наших целей, если произвести незначительные
изменения, вполне подойдет один из аналогичных файлов PicoBSD. Далее
запускаем crunchgen на выполнение:
crunchgen crunch.conf
Увидев "Run "make -f crunch.mk" to build crunched binary", выполняем:
make -f crunch.mk
Единственная проблема, с которой мне пришлось столкнуться при
выполнении crunchgen, это ошибки при компиляции telnet. Для их
устранения, мне пришлось вручную компилировать telnet, чтобы получить
/usr/src/lib/libtelnet/libtelnet.a.
В результате, создается долгожданный программный файл crunch, который
при размере чуть более 1Мб выполняет функции более сорока самых
необходимых команд FreeBSD.
4. mfsroot
На самом деле если вычесть размеры сжатого ядра, на дискете у нас
остается не так много свободного места, всего порядка 600 Кб и
следовательно, организовывать корневую файловую систему прямо здесь не
имеет никакого смысла, мы просто не сможем там разметить все наши
файлы, не говоря уже про объемистый crunch'еный бинарник. Поэтому
используем возможность создания файловой в виртуальной памяти
компьютера, для этого создадим файл образа MFS, наполним его всеми
необходимыми файлами, сожмем его при помощи gzip и наконец, поместим
его в корневую директорию дискеты.
Подготовим MFS-образ корневой файловой системы. Пусть он будет
располагаться в файле mfsroot:
dd if=/dev/zero of=mfsroot count=4096 bs=1k # Создадим mfs-образ. Для минимального набора
# файлов, 4-х мегабайтов нам вполне хватит
vnconfig -s labels -c /dev/vn0 mfsroot # Будем работать с mfsroot как с дисковым устройством
disklabel -rw vn0 auto # Разметим и
newfs -i 4096 -m 0 -p 0 -o space /dev/vn0c # организуем на нем файловую систему
mount /dev/vn0c /mnt # и смонтируем ее в каталог /mnt
Теперь осталось воспроизвести на MFS-образе минимальный набор
каталогов и заполнить файловую систему необходимыми файлами. Какие
именно файлы и директории там будут располагаться зависит от
воображения ее автора и целей создаваемой дискеты. В нашем случае,
понадобятся каталоги /etc, /dev, /sbin, /usr, /var, /tmp, /flp:
mkdir /mnt/etc
mkdir /mnt/sbin
mkdir /mnt/dev
mkdir /mnt/usr
mkdir /mnt/var
mkdir /mnt/tmp
mkdir /mnt/flp
Полезно также сделать несколько ссылок:
cd /mnt
ln -s sbin ./bin
ln -s sbin ./stand
ln -s ../sbin ./usr/bin
ln -s ../sbin ./usr/sbin
В каталоге /dev надо создать минимальный набор устройств:
cd /mnt/dev
mknod console c 0 0; chmod 600 console
mknod kmem c 2 1 root:kmem; chmod 640 kmem
mknod mem c 2 0 root:kmem; chmod 640 mem
mknod null c 2 2; chmod 666 null
mknod random c 2 3; chmod 644 random
mknod urandom c 2 4; chmod 644 urandom
mknod zero c 2 12; chmod 666 zero
mknod io c 2 14; chmod 600 io
mknod tty c 1 0; chmod 666 tty
mknod klog c 7 0; chmod 600 klog
mknod stdin c 22 0; chmod 666 stdin
mknod stdout c 22 1; chmod 666 stdout
mknod stderr c 22 2; chmod 666 stderr
mknod pci c 78 0; chmod 644 pci
mknod fd0 c 9 0; chmod 600 fd0
mknod ttyv0 c 12 0; chmod 644 ttyv0
mknod ttyv1 c 12 1; chmod 644 ttyv1
mknod ttyv2 c 12 2; chmod 644 ttyv2
mknod ttyv3 c 12 3; chmod 644 ttyv3
mknod ttyp0 c 5 0; chmod 666 ttyp0
mknod ttyp1 c 5 1; chmod 666 ttyp1
mknod ttyp2 c 5 2; chmod 666 ttyp2
mknod ttyp3 c 5 3; chmod 666 ttyp3
mknod ttyp4 c 5 4; chmod 666 ttyp4
mknod ttyp5 c 5 5; chmod 666 ttyp5
mknod ttyp6 c 5 6; chmod 666 ttyp6
mknod ttyp7 c 5 7; chmod 666 ttyp7
mknod ttyp8 c 5 8; chmod 666 ttyp8
mknod ttyp9 c 5 9; chmod 666 ttyp9
mknod vn0 c 43 2; chmod 644 vn0
mknod vn0a c 43 0; chmod 644 vn0a
mknod vn0b c 43 1; chmod 644 vn0b
mknod vn0c c 43 2; chmod 644 vn0c
Не забудем, также, в /sbin на MFS положить файл crunch и сделать на
него необходимые жесткие ссылки:
#!/bin/sh
сp crunch /mnt/sbin
for i in `crunchgen -l crunch.conf` ; \
do \
ln /mnt/sbin/crunch /mnt/sbin/$i; \
done
Теперь осталось самое сложное - заполнить каталог etc на образе MFS.
Однако своими миниатюризированными конфигурационными файлами нас
выручит PicoBSD. Оттуда мы возьмем, слегка модифицировав, несколько
жизненно необходимых файлов.
ttys:
vga none cons25 off secure
ttyv0 "/sbin/getty Pc" cons25 on secure
# Virtual terminals
ttyv1 "/sbin/getty Pc" cons25 on secure
ttyv2 "/sbin/getty Pc" cons25 on secure
ttyv3 "/sbin/getty Pc" cons25 on secure
# Pseudo terminals
ttyp0 none network secure
ttyp1 none network secure
ttyp2 none network secure
ttyp3 none network secure
ttyp4 none network secure
ttyp5 none network secure
ttyp6 none network secure
ttyp7 none network secure
ttyp8 none network secure
ttyp9 none network secure
gettytab:
default:\
:cb:ce:ck:lc:fd#1000:cl:im=\r\n%s/%m (%h) (%t)\r\n\r\n:sp#1200:
P|Pc|Pc console:\
:ht:np:sp#115200:
# Fixed speed entries
2|std.9600|9600-baud:\
:np:sp#9600:
g|std.19200|19200-baud:\
:np:sp#19200:
std.38400|38400-baud:\
:np:sp#38400:
std.57600|57600-baud:\
:np:sp#57600:
std.115200|115200-baud:\
:np:sp#115200:
local.9600|CLOCAL tty @ 9600 Bd:\
:c0#0x0000c300:c1#0x0000cb00:c2#0x0000cb00:\
:o0#0x00000007:o1#0x00000002:o2#0x00000007:\
:i0#0x00000704:i1#0x00000000:i2#0x00000704:\
:l0#0x000005cf:l1#0x00000000:l2#0x000005cf:\
:sp#9600:
login.conf:
# Authentication methods
auth-defaults:\
:auth=passwd:
auth-root-defaults:\
:auth-login=passwd:\
:auth-rlogin=passwd:\
auth-ftp-defaults:\
:auth=passwd:
default:\
:cputime=infinity:\
:datasize-cur=22M:\
:stacksize-cur=8M:\
:memorylocked-cur=10M:\
:memoryuse-cur=30M:\
:filesize=infinity:\
:coredumpsize=0:\
:maxproc-cur=64:\
:openfiles-cur=64:\
:priority=0:\
:requirehome@:\
:umask=022:\
:tc=auth-defaults:
standard:\
:copyright=/etc/COPYRIGHT:\
:welcome=/etc/motd:\
:setenv=MAIL=/var/mail/$,BLOCKSIZE=K,EDITOR=/usr/bin/ee:\
:path=~/bin /bin /usr/bin:\
:nologin=/var/run/nologin:\
:cputime=1h30m:\
:datasize=8M:\
:stacksize=2M:\
:memorylocked=4M:\
:memoryuse=8M:\
:filesize=8M:\
Поскольку образ MFS смонтирован в директорию /mnt, эти файлы должны
быть записаны в каталог /mnt/etc.
Для загрузки этих 3-х файлов вполне хватит, однако, работать с такой
системой будет практически невозможно. Для более или менее нормального
функционирования, системе потребуется большинство конфигурационных
файлов, наблюдаемых нами, на любой машине FreeBSD в каталоге /etc.
Кроме того, как уже было сказано, изменения в файлах на MFS будут
сохраняться только до перезагрузки системы. Решая эту проблему,
воспользуемся опытом PicoBSD и разделим все конфигурационные файлы из
каталога /etc на две группы. Первые, которые мы не планируем
когда-либо изменять, запишем в каталог /etc на MFS, вторые тоже
поместим в директорию /etc, но уже на файловой системе дискеты.
Как минимум, на MFS нам пригодятся файлы disktab, protocols, services
и termcap, которые в очередной раз можно смело заимствовать у PicoBSD,
поэтому, предполагая, что конфигурационные файлы PicoBSD располагаются
в /usr/srs/release/picobsd/mfs-tree/etc, выполняем:
cp /usr/src/release/picobsd/mfs_tree/etc/disktab /mnt/etc
cp /usr/src/release/picobsd/mfs_tree/etc/protocols /mnt/etc
cp /usr/src/release/picobsd/mfs_tree/etc/services /mnt/etc
cp /usr/src/release/picobsd/mfs_tree/etc/termcap /mnt/etc
Так как остальные конфигурационные файлы будут находится за пределами
MFS, при загрузки системы их придется копировать на MFS в каталог
/etc. Для этого к ttys, gettytab и login.conf в каталог /etc на MFS (в
настоящий момент это /mnt/etc), добавим простой rc-файл:
#!/sbin/sh
PATH=/sbin; export PATH
mount -o rdonly /dev/fd0 /flp
cd /etc
cp /flp/etc/* .
umount /flp
. rc.main
exit 0
Этот скрипт должен будет скопировать все файлы из директории /etc на
дискете в одноименный каталог на образе MFS и затем вызвать
"настоящий" rc-файл (rc.main), однако на этом остановимя немного
позже, а сейчас, поскольку MFS-образ готов, выполняем:
umount /mnt # размонтируем /mnt и
vnconfig -u vn0 # отключим связку mfsroot и /dev/vn0c
Завершив эксперименты с mfsroot, заархивируем его:
gzip --best mfsroot
В результате получается файл mfsroot.gz объемом около 600Кб, при
условии что свободное пространство на MFS-образе заполнено нулями,
таким образом, операции создания и удаления файлов не оставили за
собой мусора в файловой системе. Наилучшие результаты сжатия mfsroot в
этом случае достигаются путем записи заранее подготовленных файлов на
их точные места на образе MFS.
5. Загрузочная дискета
Настало время подготовить образ загрузочной дискеты. В общем случае,
процесс загрузки FreeBSD разделен на 4 этапа, каждому из которых
соответствует определенный файл в файловой системе FreeBSD:
* MBR - /boot/boot0;
* Stage 1 - /boot/boot1;
* Stage 2 - /boot/boot2;
* Stage 3 - /boot/loader.
Разумеется, файлы boot0, boot1 и boot2 являются всего лишь копиями
загрузочных областей дисков, которые, по понятным причинам, находятся
вне файловой системы FreeBSD.
Поскольку мы планирует загружаться с дискеты, boot0 (MBR) нас не
интересует, и в нашем случае, boot-процесс начнется со Stage 1
(/boot/boot1). Во время начальной загрузки BIOS пытается прочитать 1-й
сектор нулевой дорожки нулевой стороны диска в дисководе "a:", это и
должен быть boot1. Boot1 - весьма простая программа, основная цель
которой найти и запустить boot2 (Stage2). В принципе, уже boot2 может
загрузить ядро FreeBSD, однако, он, видимо, не может распознать формат
заархивированного ядра, по крайней мере, мне так и не удалось
заставить его сделать это. Далее, boot2 загружает loader (Stage3),
который находится уже в файловой системе в каталоге /boot. В настоящее
время loader и является основным средством загрузки ядра. Подробности
порядка и особенностях загрузки FreeBSD описаны в handbook.
Таким образом, необходимо чтобы в загрузочных областях дискеты
находились boot1 и boot2, а также, на дискете в каталоге /boot
файловой системы FreeBSD должны быть записаны файлы loader и
loader.rc.
Итак, создадим загрузочный образ дискеты. В командной строке
выполняем:
dd if=/dev/zero of=flpImage count=1440 bs=1k # Создаем файл образа дискеты - flpImage
vnconfig -s labels -c /dev/vn0 flpImage # Будем работать с ним как с устройством
disklabel -Brw -b /boot/boot1 -s /boot/boot2 vn0c fd1440 # Помещаем на него boot1 и boot2
newfs -i 32768 -m 0 -p 0 -o space /dev/vn0с # Создаем на нем файловую систему
vnconfig -u vn0 # Отключаемся от файла как устройства
Здесь flpImage - файл образа дискеты, который в последствии будет
записан на дискету.
Теперь следует подготовить файл loader.rc, который будет выполнен
программой loader, в момент, когда загрузка доберется до этапа Stage3.
Этот простенький скрипт будет содержать следующие строки:
echo Loading kernel... # Выводим на экран сообщение о загрузки ядра
load /kernel # и загружаем его
echo Loading MFS... # Выводим сообщение о загрузки MFS-файловой системы
load -t mfs_root /mfsroot # И загружаем ее
autoboot 0 # Загружаемся сразу, а не ждем обычные 9 секунд.
Далее, полученный образ дискеты остается подмонтировать и записать на
него /boot/loader и loader.rc:
vnconfig vn0 flpImage
mount /dev/vn0c /mnt
mkdir /mnt/boot
cp /boot/loader /mnt/boot
cp loader.rc /mnt/boot
На образе дискеты создадим каталог /etc, поместив в него несколько
конфигурационных файлов:
hosts:
127.0.0.1 localhost localhost.mydomain
192.168.1.1 1f-bsd 1f-bsd.somewere.net
inet.d в нашем случае может состоять всего из одной строки:
telnet stream tcp nowait root /usr/sbin/telnetd telnetd
Файлы passwd, master.passwd и group можно подготовить свои, чтобы
разрешить доступ только ограниченному кругу людей, или же взять с
текущей работающей машины, и, таким образом, перенести на нашу систему
всех пользователей.
Урезанные файлы disktab и services, уже по привычке, позаимствуем у
PicoBSD, но rc.main, для простоты напишем свой:
#!/sbin/sh
# add swap file
dd if=/dev/zero of=/swapfile count=1024 bs=1k
vnconfig /dev/vn0b /swapfile
swapon /dev/vn0b
# make password database
pwd_mkdb -p ./master.passwd
# create device database
dev_mkdb
# setup network
hostname 1f-bsd
ifconfig lo0 inet 127.0.0.1
ifconfig xl0 inet 192.168.1.1 netmask 255.255.255.0
# Start daemons
syslogd
inetd
exit 0
И наконец, поместим в корневом каталоге дискеты сжатые ядро и mfsroot:
cp kernel.gz /mnt
cp mfsroot.gz /mnt
Теперь можно смело размонтировать образ дискеты и отключить его от
устройства vn0:
umount /mnt
vnconfig -u vn0
Почти все готово, единственное, что остается сделать, это вставить
дискету в дисковод и выполнить:
dd if=flpImage of=/dev/fd0
для того, чтобы записать подготовленный образ на дискету. Теперь,
остается лишь загрузиться с нашей дискеты и проверить, действительно
ли она работает.