Зачем помещать Linux на загрузочный CD? Такое решение позволяет иметь Linux на практически любом компьютере, не теряя времени на его установку и настройку. Ярким примером является дистрибутив Blin Linux 1.3, который позволяет смотреть видео на компьютере и требует наличия 64 MB RAM и CD-драйва. Винт ему не требуется, да и CD-драйв освобождается сразу после загрузки системы. Удобно!
Данная статья описывает создание "основы" для дистрибутива подобного рода, который в дальнейшем можно усовершенствовать до нужного вам состояния.
Стандартом для загрузочного CD является El Torito, смысл которого заключается в том, что BIOS считает CD-драйв дисководом и ищет на нём загрузочный образ. Но есть альтернатива в виде ISOLINUX, данное решение не использует эмуляции дисковода и позволяет работать со всем CD-диском.
Процесс загрузки
Стандартный процесс загрузки Linux выглядит как-то так:
Компьютер запускает LILO или подобный загрузчик.
LILO знает где находится ядро и запускает его.
Запускается ядро, после проведения стандартных тестов, оно монтирует корневую файловую систему.
После этого запускается /sbin/init и операционная система запускается
в соответствии с /etc/inittab и
скриптами rc.d.
Процесс загрузки с CD немного отличается. Нам снова нужен загрузчик, но необязательно знать, каким устройством является наш CD-драйв. Он может быть /dev/hdb, /dev/hdc или /dev/hdd. Даже если мы скажем загрузчику, где находится ядро, нам надо будет указать ядру где находится корневая файловая система. В поиске CD-драйва нам помогает ISOLINUX, но не решает проблемы с поиском корневой файловой системы. Многие загрузочные диски используют так называемый initrd (initial ram disk), который является диском в оперативной памяти с минимальной корневой файловой системой. Идея заключается в том, что ядро загружает минимальную файловую систему, на которой находятся модули, которые позволяют найти и подгрузить основную корневую файловую систему. Теперь рассмотрим процесс загрузки Linux с CD:
Загрузка с CD с ISOLINUX.
ISOLINUX загружает
ядро из каталога /isolinux на
CD-диске.
Затем ISOLINUX
загружает initrd.gz, сжатую ext2
файловую систему. Важно понимать, что initrd.gz загружается не ядром!
Ядро запускается и разжимает initrd.gz в память (обычно в /dev/ram0) и монтирует его в корень. Ядро
должно быть собрано с опциями поддержки initrd и ramdisk.
Ядро пытается запустить linuxrc в новой файловой системе.
Программа linuxrc в
свою очередь пытается примонтировать CD-диск, а затем копирует сжатую основную
файловую систему в память (обычно в /dev/ram1). Новая файловая система
монтируется и в её каталоге /dev
создается символическая ссылка на CD-драйв.
После завершения работы linuxrc, управление возвращается ядру и оно
пытается примонтировать свою сконфигурированную файловую систему. В данном
случае, с помощью команды rdev
указываем ядру использовать /dev/ram1 в
качестве корневой файловой системы, в которой есть /sbin/init и система стартует прямо из
памяти.
Но зачем надо разбивать процесс
загрузки на две фазы? Дело в том, что Linux не знает как грузиться с CD.
Преимущество наличия первой фазы загрузки состоит в том, что файловая система
initrd загружается загрузчиком, а не
ядром. Это означает, что мы сможем загрузиться с любого устройства, с которого
сможет запуститься загрузчик.
Создание ядра
Теперь необходимо создать ядро, которое сможет загружать
initrd файловую систему. Процесс сборки
ядра опищем позднее, а пока предположим, что вы умеете это делать :) Ядро должно
быть собрано с поддержкой initrd и RAM
дисков. Будем использовать размер RAM диска по умолчанию, т.е. 4 MB. Также
следует подключить поддержку файловых систем ISO9660 и EXT2. После сборки ядра
его необходимо настроить на использование конкретного корневого
устройства.
Допустим, вы только что выполнили команду make bzImage rdev
/usr/src/linux/arch/i386/boot/bzImage /dev/ram1 Если у вас нет
устройства /dev/ram1, то его следует
создать mknod -m 640 /dev/ram1 b 1
1
Создание дерева каталогов
Создадим шаблон для нашего дистрибутива.
Ключевые
каталоги:
cdimage/ — этот
каталог будет записываться на CD.
initrd/ — этот каталог содержит файловую систему initrd.
root/ — этот
каталог содержит рабочую файловую систему.
Настройка initrd
Фаза INITRD имеет простую цель — получить рабочую файловую систему в /dev/ram1. Есть несколько способов сделать это. Перечислим их попорядку:
Использовать небольшой shell скрипт (ash) для монтирования CD, разворачивания
(gunzip) файла rootfs.gz в /dev/ram1. Такой подход требует наличия libc, что увеличивает размер initrd.gz до 600 KB. Это самый прямой подход.
[ссылка]
Использовать программу linuxrc написанную на i386 ассемблере
выполняющую аналогичные действия, за исключением использования другого
алгоритма компрессии, т.к. gunzip
слишком сложен для его реализации на ассемблере. Программа будет "весить"
всего 1 KB и не требовать наличия дополнительных библиотек. Файл initrd.gz будет иметь размер около 10 KB. [ссылка]
Использовать программу linuxrc написанную на C и статически
слинкованную, которая использует для декомпрессии gunzip.c, и успешно выполняет задачи shell
скрипта. Будучи статически слинкованной с библиотекой dietlibc, программа будет занимать меньше места, чем в случае динамической линковки с libc-2.1.3. Программа будет "весить" примерно 20 KB, а размер файла initrd.gz будет 15 KB. [ссылка]
Программа на C является оптимальным выбором, т.к. имеет небольшой размер
и использует "стандартный" метод декомпрессии.
Перечислим основные этапы выполняемые программой:
Монтирование /proc.
Открываем файл /proc/ide/ide0/hda/media, если там написано
"cdrom", то значит мы нашли наш CD (хм, а если у меня в машине несколько
CD-драйвов???). В противном случае проверяем /proc/ide/ide0/hdb/media, /proc/ide/ide1/hdc/media и /proc/ide/ide1/hdd/media пока не встретится
первый CD-драйв (о как!). То есть, грузиться мы можем только с этих четырех
IDE CD-драйвов!
Переходим в каталог /dev и создаём символическую ссылку cdrom на найденное устройство.
Монтируем CD-драйв в каталог
/cdrom.
Открываем /cdrom/rootfs.gz и разворачиваем его в /dev/ram1. В rootfs.gz должна находиться EXT2 файловая
система размером в 4 MB.
Монтируем /dev/ram1 в /ram.
Переходим в каталог /ram/dev и создаём символическую ссылку на
устройство с CD-диском.
Размонтируем /ram, /cdrom и /proc.
После
этого ядро должно приняться за работу и примонтировать /dev/ram1 как / и попытаться запустить /sbin/init.
Рабочая корневая файловая система
С одной файловой системой initrd многого не сделаешь. Необходимо создать
полезную корневую файловую систему. А так как мы используем RAM диск объёма 4 MB, он немного сжатый. Почему бы не использовать RAM диск большего размера? Да
просто незачем зря забивать память и надо помнить о пользователях компьютеров с небольшим объёмом оперативной памяти. Возмём библиотеки:
Не все из них нужны для старта операционной
системы. В католеге /bin находятся
необходимые утилиты. Также создан скрипт /sbin/init. В каталоге /etc находятся файлы inittab и termcap, а также каталог rc.d, в котором находится скрипт rc.S используемый для запуска операционной
системы. Приведём ключевую часть файла inittab:
Также присутствует пустой каталог /initrd, который указывает, что фаза INITRD завершена и рабочая корневая файловая
система на /dev/ram1 примонтирована,
файловая система initrd (находящаяся на
/dev/ram0) удалена из /initrd. Это означает, что мы можем
размонтировать её и освободить память используемую RAM диском.
Посмотрим
внутренности скрипта rc.S:
#!/bin/sh PATH=/bin; export PATH echo
"System init" mount -t proc none /proc mount -o remount,rw / echo "Find
the extras on the CD and mount it" if [ -r /dev/cdrom ] ;
then mount -t iso9660 /dev/cdrom
/cdrom mount /dev/hda9 /a fi cd / umount
/initrd freeramdisk /dev/ram0
Сначала мы монтируем /proc, а затем перемонтируем / в режиме записи (мы имеем правильную запись о
/ в /etc/fstab). Проверяем наличие устройства /dev/cdrom (оно должно было быть создано в фазе
INITRD) и монтируем его. В рабочей
файловой системе сделана символическая ссылка из /usr в /cdrom/usr. Таким образом, дополнительное
программное обеспечение можно хранить в этом каталоге на CD-диске. В тестовых
целях был примонтирован раздел жёсткого диска в каталог /a.
Создание CD
Теперь у нас есть ядро, структуры файловых систем initrd и rootfs. Как же их записать на CD-диск?
Рассмотрим простейшую структуру каталогов на CD-диске:
/rootfs.gz /isolinux/ isolinux.cfg
-
конфигурационный файл isolinux.bin
-
загрузчик vmlinuz
- ядро с
поддержкой initrd initrd.gz
-
стартовая файловая система
Рассмотрим файл isolinux.cfg:
label
linux kernel vmlinuz append
initrd=initrd.gz
Очень похоже на конфигурационный файл LILO.
Важными элементами данного файла являются имя ядра и строка с именем стартовой
файловой системы. То, что файл со стартовой файловой системой сжат не имеет
значение, т.к. ядро впоследствии само распакует его.
А что насчёт initrd и rootfs? Обе системы EXT2 размером в 4 MB
являются сжатыми файлами. Ниже приведён скрипт для их
создания:
Файл boot.cat будет создан в результате выполнения
этой команды. Опции -l, -R и -r
нужны для расширения RockRidge (см. CD-Writing HowTo), которое позволяет
использовать на CD-диске символические ссылки и имена со строчными и прописными
буквами. Полученный файл следует записать на CD-диск с помощью cdrecord (оставим это в качестве домашнего
задания :). А продвинутые пользователи могут протестить получившийся дистрибутив
с помощью vmWare.
Основа для дальнейшего усовершенствования
Как же добавить особенную, необходимую только
вам, функциональность к данному дистрибутиву? Как было упомянуто выше, каталог
/usr является символической ссылкой на на
каталог /usr на CD-диске. Используйте эту возможность!
Использование FrameBuffer
Приятно иметь графическую среду
во время загрузки с CD. Для достижения максимальной совместимости следует
активировать режим FrameBuffer для
консоли и использовать X-сервер XF86_FBDev. Следует отметить, что FrameBuffer работает на видеокартах, которые
имеют поддержку VESA 2.0, для более старых следует использовать простую консоль.
Ниже приведены настройки ядра для активации FrameBuffer.
[*] VGA
text console [*] Video mode selection support [*] Support for frame buffer
devices (EXPERIMENTAL) [*] VESA VGA graphics console [*] Advanced low
level driver options <*> 8 bpp packet pixels
support
<*> 16 bpp packet pixels support <*> 24 bpp packet
pixels support <*> 32 bpp packet pixels
support <*> VGA character/attributes support [*]
Select compiled-in fonts [*] VGA 8x8
font [*] VGA 8x16 font
Теперь следует указать правильный графический
режим, который будет использоваться X-сервером. Для этого небходимо указать
специфическую опцию для ядра. Таким образом, необходимо внести изменения в файл
isolinux/isolinux.cfg:
label
linux kernel vmlinux append
initrd=initrd.gz vga=791
Загадочное число "791" обозначает графический
режим 1024x768x16bit. Но такое жёсткое указание видеорежима не подойдет для всех
случаев. Надо позволить пользователю выбирать требуемый графический режим.
Перепишем isolinux/isolinux.cfg: