|
Bog BOS: GRUB - универсальный загрузчик для PC
|
Последнее изменение файла: 2024.09.24
Скопировано с www.bog.pp.ru: 2024.11.23
Bog BOS: GRUB - универсальный загрузчик для PC
Описывается применение GRUB для загрузки Linux, поэтому
перед чтением статьи полезно ознакомиться с
общей картиной процесса загрузки Linux в режиме BIOS и UEFI.
Загрузчик GNU GRUB разрабатывался для загрузки ОС, соответствующих стандарту
Multiboot (т.е. совместимых с GNU/Hurd ;) с 1995 года. Понятное дело, что уговорить
разработчиков других ОС не удалось, поэтому GRUB был доработан так, чтобы
уметь загружать поделки неразумных: Linux, FreeBSD, OpenBSD, NetBSD и
через вызов вторичного загрузчика - MS DOS, MS Windows NT, OS/2.
В 2002 был переписан заново под именем PUPA, затем переименован в GRUB 2.
Первоначальный GRUB был переимеован в GRUB Legacy 0.97 (так что GRUB 1 не существует!).
Особенностью GRUB [2] является умение работать с разными платформами
(x86-32, ia32 EFI, x86-64, amd64 EFI, ia32 IEEE1275, Itanium, ARM, sparc64, Powerpc, ARC, MIPS, xen, LoongArch, QEMU),
понимание форматов нескольких файловых систем (BSD FFS, FAT16, FAT32, exFAT, NTFS, Minix fs, ext2/3/4, ReiserFS,
ISO9660, nilfs2, UFS, UFS2, UDF, JFS, XFS, Btrfs, ZFS, ROMFS, tar, cpio
и, на всякий случай, номера блоков; LVM, RAID) и ядер (NTLDR, Plan9, Freedos, FreeBSD, 32/64 {kFreeBSD,kNetBSD,kOpenBSD,Linux,EFI}, Multiboot, Multiboot2, Appleloader),
что позволяет записывать в конфигурацию загрузчика
имена файлов вместо номеров блоков.
GRUB 2 имеет модульную структуру, модули грузятся динамически или встраиваются в тело.
Позволяет использовать при загрузке меню
(читается из конфигурационного файла или встраивается в тело загрузчика) или командный интерфейс.
Меню можно редактировать в момент загрузки или переходить в командный режим.
Командный режим позволяет дополнять команды (Tab), имена файлов, разделы.
GRUB 2 имеет графический интерфейс.
Файлы читаются с флоппи, жёсткого диска или CD средствами BIOS со всеми
вытекающими ограничениями и неприятностями типа путаницей со способом
трансляции адресов блоков и нумерацией дисков.
Однако, может переключать диск в режим LBA, если имеется такая возможность.
Имеется возможность загрузки по сети (TFTP,
BOOTP, DHCP,
RARP) и использования терминала (RS-232).
Ещё он умеет пользоваться Etherboot и PXE ROM.
Есть средства парольной защиты (команды password и lock), но в наше время
загрузочных свистков - это ненадёжная защита.
GRUB 0.97 состоит из 3 частей:
- stage1 (boot.img) - 512 (446) байт, обычно размещается в MBR; ничего про файлы не знает,
имеет вшитый адрес первого блока stage1_5 или stage2
(размер и адреса остальных интервалов хранятся в этом первом блоке);
в эти же 512 байт упихиваются таблица разделов, BPB и некоторые константы,
так что размер программы невелик
- stage1_5 (core.img) - отдельный модуль для каждого типа файловой системы;
ищет и загружает stage2; может находиться в файловой системе или
вне её (между MBR и первым разделом или в специально зарезервированном
месте FFS или ReiserFS)
- stage2 - основной модуль GRUB, обеспечивающий работу с меню и командной строкой;
имеет вшитый флажок LBA, имя конфигурационного файла и прямо сюда в момент
загрузки может записываться номер выбранной из меню строки
Настройки хранятся в файле grub.conf (или menu.lst)
Имя устройства заключается в круглые скобки и начинается с
указания типа устройства (fd, hd, cd, nd) за которым идёт номер устройства.
Устройства нумеруются с нуля, порядок определяется BIOS (в частности,
ATA и SCSI диски не различаются). Если устройство разбито
на разделы и необходимо указать конкретный раздел вместо всего диска, то далее
необходимо после запятой указать номер раздела (нумеруются с нуля - в GRUB 2 с 1,
первый расширенный раздел имеет номер 4 - 5 в GRUB 2), например, первый расширенный раздел
первого диска для GRUB 0.97:
(hd0,4)
Перед номером раздела может быть указан тип таблицы разделов: msdos, gpt, bsd, sun и др.
(полный список типов таблиц разделов в /usr/lib/grub/i386-pc/partmap.lst или /usr/lib/grub/x86_64-efi/partmap.lst).
В GRUB 2 добавлены типы: ahci0, ata0, crypto0, usb0, cryptouuid/идентификатор, mduuid/идентификатор, md/имя,
lvm/группа-том, lvmid/идентификатор-группы/идентификатор-тома и др.
Появились подразделы: (hd0,gpt1,bsd3).
Сетевые устройства GRUB 2: ({http|tftp}[,сервер[:порт]]), если имя сервера опущено то используется переменная окружения net_default_server.
Имя файла записывается сразу после имени устройства
(если имя устройства опущено, то подразумевается "корневое" устройство;
задаётся командой root или "set root="), в обычном POSIX синтаксисе, начиная от корневого слеша.
Для ZFS первым компонентом необходимо указать имя-тома@имя-снимка.
Если же GRUB ничего не знает про используемую файловую систему,
то расположение файла можно задать с помощью списка через запятую интервалов
блоков (512 байт) в виде: смещение+число-блоков. Если смещение первого интервала опущено,
то подразумевается число 0. Если имя устройства опущено, то подразумевается
"корневое" устройство. Самое распространнённое использование - загрузка
вторичного загрузчика размером 512 байт:
root (hd0,0)
chainloader +1
Утилита grub-probe (grub2-probe) может помочь установить соответствие
между именами устройств в BIOS и GRUB (а может не помочь).
Файл /boot/grub/device.map может содержать зафиксированное соответствие (оно может устареть).
GRUB переходит после загрузки в режим командного интерфейса,
если не находит конфигурационный файл или если пользователь переводит его явно
(команда c в режиме меню). Режим ввода команды напоминает bash, те же клавиши
редактирования строки (включая историю команд и автодополнение команд и имён
дисков и файлов), немедленное исполнение после нажатия клавиши "Enter".
Команды:
- boot (запустить загруженное ядро или вторичный загрузчик)
- chainloader [--force] имя-файла (загрузить в память вторичный загрузчик)
- help [--all] [шаблон]
- hide имя-раздела (устанавливает флаг "hidden" в таблице раздела, чтобы
не пугать DOS несколькими первичными разделами)
- initrd имя-файла (загрузить initrd - RAM диск для Linux)
- kernel [--type=netbsd|freebsd|openbsd|linux|biglinux|multiboot]
[--no-mem-option] имя-файла параметр ... (загрузить ядро
в память; остальные параметры передаются ядру; --no-mem-option запрещает
передавать ядру параметр mem=..., сгенерированный GRUB)
- makeactive (взвести флаг активности для корневого раздела; требуется для DOS)
- map в из (позволяет отобразить исходное устройство в результирующее;
требуется для работы некоторых вторичных загрузчиков (DOS), умеющих
загружаться только с первого диска)
- module имя-файла параметр ... (загрузить модуль для ядра стандарта Multiboot)
- modulenounzip имя-файла параметр ... (загрузить модуль для ядра
стандарта Multiboot без расширения)
- partnew имя-раздела тип начальный-сектор число-секторов (создать раздел)
- parttype имя-раздела тип (изменить тип раздела)
- root имя-устройства-или-раздела (считать указанное устройство "корневым",
определить размер раздела)
- rootnoverify имя-устройства-или-раздела (считать указанное устройство "корневым",
не пытаться работать с разделом)
- unhide имя-раздела
- uppermem килобайт (принудительно назначить размер верхней памяти)
GRUB может самостоятельно загрузить ядро ОС или загружить
вторичный загрузчик и передать ему управление. В первом случае типовой набор
команд выглядит так:
root (hd0,0)
kernel /vmlinuz root=/dev/hda1 ...
inird /initrd.img
boot
Во втором так:
rootnoverify (hd0,0)
map ...
hide ...
unhide ...
makeactive ...
chainloader +1
boot
Команды управления интерфейсом и процессом:
- color цвет/фон [цвет-выделенного/фон] (имена цветов достались от CGA IMHO ;)
- configfile имя-файла (загрузить конфигурационный файл и интерпретировать его)
- halt [--no-apm] (остановить компьютер)
- pager [on | off] (делать ли паузы между экранами при большом выводе)
- pause текст-сообщения (вывести текст и ждать нажатия кнопки Any)
- reboot
- savedefault (сделанный из меню выбор становится выбором по умолчанию;
прописывается в тело stage2;
интересно - будет ли работать при загрузке с CD ;)
- setkey [в из] (переназначение клавиши)
- splashimage имя-файла (используется в качестве фоновой картинки;
xpm 640x480, 14 цветов, сжатый gzip)
"Исследовательские" команды:
- blocklist имя-файла (выдать список интервалов адресов блоков, занимаемых
файлом)
- cat имя-файла
- cmp имя-файла-1 имя-файла-2
- debug (выводить отладочные сообщения)
- displayapm (вывести информацию об APM BIOS)
- displaymem (вывести карту памяти)
- find имя-файла (искать указанное абсолютное имя файла на всех доступных разделах)
- fstest (включить отладочную печать о файловых операциях)
- geometry имя-устройства [C H S] (посмотреть, что BIOS думает о геометрии диска;
при работе в рамках ОС можно установить геометрию для использования в GRUB)
- impsprobe (попытаться включить процессоры согласно
Intel Multiprocessor Specification 1.1 или 1.4)
- ioprobe имя-устройства (вывести адреса портов ввода/вывода данного устройства)
- read адрес-памяти
- testload имя-файла (файл читается различными способами, чтобы проверить
возможность чтения файлов)
- testvbe режим (переключить видеокарту в указанный режим и запустить мультфильм)
- vbeprobe (вывести список имеющихся видеорежимов VESA BIOS EXTENSION)
Команды для установки GRUB:
- device имя-устройства-GRUB имя-устройства-ОС (только при работе в рамках ОС;
задаёт соответствие между именем устройства в понимании GRUB и ОС
- embed имя-файла устройство-или-раздел (встроить stage1_5 из файла сразу после
MBR или область загрузки файловой системы FFS или ReiserFS)
- install ... (установка GRUB на диск: модификация содержимого stage1 и stage2
в соответсвии с указанными адресами, именами и пр.)
- quit (только при работе в рамках ОС)
- setup [--force-lba] [--stage2=имя-файла] [--prefix=каталог-с-источниками] имя-раздела
[имя-раздела-с-источниками] (оболочка для install; установка GRUB на диск;
по умолчанию источники ищутся на корневом разделе в каталогах /boot/grub и /grub;
при установке на диск пытается встроить stage1_5 вне файловой системы)
Команды для загрузки по сети (после определения сетевых параметров
можно использовать сетевой диск - (nd) - для загрузки файлов по TFTP;
интересно GRUB знает про все на свете сетевые карточки?):
- bootp (запрашивает IP адрес компьютера и прочие параметры у
BOOTP сервера)
- dhcp (запрашивает IP адрес компьютера и прочие параметры у
DHCP сервера)
- rarp (запрашивает IP адрес компьютера и прочие параметры у
RARP сервера)
- ifconfig --address=наш-адрес --server=адрес-TFTF-сервера --gateway=адрес-шлюза
--mask=сетевая-маска (явное задание сетевых параметров)
Команды для работы с терминалом по RS-232:
- serial [--unit=номер-последовательного-порта] [--port=UART-I/O-порт]
[--speed=бод] [--word=число-бит-данных] [--stop=число-стоповых-бит]
[--parity=no|odd|even] (параметры по умолчанию - 0 (т.е. COM1), 9600, 8, 1, no;
вывод на теринал начинается по команде terminal)
- terminal [--dumb] [--no-echo] [--no-edit] [--timeout=секунд] [--lines=число-строк]
[--silent] [console] [serial] (задаёт тип устройства общения - через
PC консоль или последовательный терминал; определяется явно или где первым
нажмут кнопку или первое в списке по истечению времени ожидания;
под последовательным терминалом подразумевается VT100, если не указано --dumb;
--silent запрещает вывод приветствия до первого нажатия кнопки - например,
если у вас вообще нет терминала)
- terminfo ... (позволяет описать особенности терминала;
есть утилита grub-terminfo)
GRUB переходит после загрузки в режим работы с меню,
если находит конфигурационный файл. Команды работы с меню описаны на экране
(перемещение по меню, выбор текущей секции, переход в командный режим,
редактирование меню).
Меню создаётся из конфигурационного файла grub.conf в загрузочном
каталоге (/grub или /boot/grub) в момент загрузки.
Конфигурационный файл может содержать любые команды командного
интерфейса GRUB и некоторые дополнительные. Комментарии начинаются с символа '#'.
Файл делится на секции, разделяемые командой title. Секция до первой команды
title задаёт общие параметры, в частности секцию по умолчанию и описание интерфейса.
Каждая команда title задаёт имя секции, которое будет высвечиваться на экране
в момент загрузки.
При выборе данной секции выполняются составляющие её команды. Указывать команду
boot в конце секции необязательно - она подразумевается.
Команды, задающие общие параметры:
- timeout секунд (по истечению указанного времени выполняется секция,
указанная в default или секция 0, если default не использована)
- default номер-секции (какую секцию выполнять по умолчанию по истечению
интервала времени; нумеруются с нуля; можно указать ключевое слово "saved" -
выполняется секция, номер которой сохранён командой savedefault)
- fallback номер-секции (какую секцию выполнять, если default выполнить
не удалось; нумеруются с нуля)
- hiddenmenu (не выводить меню на экран; его всё же можно вызвать нажав ESC)
- password [-md5] пароль-или-хеш [имя-нового-конфигурационного-файла]
(md5 - такой же алгоритм как в /etc/shadow; есть утилита grub-md5-crypt;
блокирует интерактивное управление до ввода пароля, если указан новый файл
конфигурации, то он загружается и загрузчик начинает с начала)
- команды, общие с командным интерфейсом: bootp, color, device, dhcp, hide,
ifconfig, pager, partnew, parttype, password, rarp, srial, setkey, splashimage,
terminal, terminfo, unhide
Команды, которые могут входить в секцию:
- title текст
- lock (должна идти сразу за title; блокирует использование секции, пока не будет
введён пароль, заданный командой password)
- password [-md5] пароль-или-хеш
(md5 - такой же алгоритм как в /etc/shadow;
определяет пароль для использования секции)
- color цвет/фон [цвет-выделенного/фон] (имена цветов достались от CGA IMHO ;)
- команды командного интерфейса: blocklist, boot, cat, chainloader, cmp,
configfile, debug, displayapm, displaymem, embed, find, fstest, geometry,
halt, help, impsprobe, initrd, install, ioprobe, kernel, makeactive,
map, md5crypt, module, moduleunzip, pause, quit, reboot, reed, root,
rootnoverify, savedefault, setup, testload, testvbe, uppermem, vbeprobe
Скорее всего, что GRUB будет установлен в MBR или в ESP во время установки
Linux, но иногда приходится его восстанавливать (после NTLDR ;) или перемещать на другое место.
Для grub 0.97 необходимо иметь установленным пакет grub (/boot/grub: stage1, *stage1_5, stage2).
stage1 - это 512 байт, помещаемые обычно в MBR.
Кроме программы загрузки stage1_5 или stage2 в них помещается таблица разделов
и прочая информация. Адрес загрузчика следующего этапа "впечатывается" в тело
stage1 в виде адресов блоков, так что о файловых системах он ничего не знает
и после смены адреса stage1_5 и stage2 его надо модифицировать и записывать заново.
Установка GRUB 0.97 на флоппи:
dd if=stage1 of=/dev/fd0 bs=512 count=1
dd if=stage2 of=/dev/fd0 bs=512 seek=1
Установка GRUB 0.97 на диск после загрузки GRUB с флоппи в BIOS
(этот метод гарантирует правильную - совпадающую с мнением BIOS - нумерацию дисков):
# сделать корневым раздел, содержащий каталог boot
grub > root (hd0,0)
# запись stage1 в MBR
grub > setup (hd0)
Можно установить GRUB 0.97 на диск без изготовления флоппи
непосредственно из текущей ОС с помощью скрипта grub-install, но при этом есть
риск ошибиться с номером устройства (см. файл device.map):
grub-install /dev/hda
Утилита grub-probe (grub2-probe) может помочь установить соответствие
между именами устройств в BIOS и GRUB (а может не помочь).
Файл /boot/grub/device.map может содержать зафиксированное соответствие (оно может устареть).
Восстановление загрузчика grub 0.97 (загрузка с CD-ROM в режиме rescue,
корневая файловая система вместе с /boot на /dev/hda1):
mkdir /mnt/hard
mount -t ext3 /dev/hda1 /mnt/hard
chroot /mnt/hard
/sbin/grub --no-floppy
device (hd0) /dev/hda
root (hd0,0)
setup (hd0)
quit
exit
Установка GRUB 0.97 на CD
(создание и запись ISO9660 в Linux,
формат El Torito без эмуляции):
mkdir grubiso
mkdir -p grubiso/boot/grub
cp stage2_eltorito grubiso/boot/grub
mkisofs -R -b boot/grub/stage2_eltorito -no-emul-boot \
-boot-load-size 4 -boot-info-table -o /tmp/grub.iso grubiso
запись /tmp/grub.iso на CD
После загрузки с этого CD мы попадаем в командный режим GRUB.
Файлы, записанные на CD дополнительно доступны с указанием устройства (cd).
Этим можно воспользоваться для записи на CD конфигурационного файла, ядра Linux и initrd.
Например, создадим конфигурационный файл grubiso/boot/grub/grub.conf:
#boot=/dev/hda
default=4
timeout=5
title chainloader hd0
rootnoverify (hd0)
chainloader +1
title chainloader hd0,0
rootnoverify (hd0,0)
chainloader +1
title CD CentOS 4.0 (2.6.9-5.0.3.EL)
root (cd)
kernel /boot/vmlinuz-2.6.9-5.0.3.EL ro root=/dev/hda3
initrd /boot/initrd-2.6.9-5.0.3.EL.img
title CD Fedora Core 3 original (2.6.9-1.667)
root (cd)
kernel /boot/vmlinuz-2.6.9-1.667 ro root=LABEL=/ rhgb quiet
initrd /boot/initrd-2.6.9-1.667.img
title CD Fedora Core 3 upgrade (2.6.10-1.770_FC3)
root (cd)
kernel /boot/vmlinuz-2.6.10-1.770_FC3 ro root=LABEL=/ rhgb quiet
initrd /boot/initrd-2.6.10-1.770_FC3.img
Все упомянутые файлы необходимо скопировать в grubiso/boot/,
создать образ ISO9660 и записать на CD. Получившийся CD (его необходимо дополнить
строчками меню для всех вариантов Linux в сети предприятия) можно использовать
как "универсальный" аварийный загрузчик (или как ключ доступа, если убрать
загрузчик из MBR ;). Например, глючный BIOS моего домашнего компьютера
не умел работать с большими дисками и его приходилось загружать с CD.
Этой ОС не нужны другие ОС! Шутка (почти).
Пакеты:
- grub2 (заглушка)
- grub2-common (каталоги, документация)
- grub2-efi-x64 (/boot/efi/EFI/centos/* и ссылки /boot/grub2/grubenv и /etc/grub2-efi.cfg)
- grub2-efi-x64-modules (модули для сборки своего варианта grub.efi, tftp.mod и http.mod есть, а ftp - нет)
- grub2-pc (/boot/grub2/grub.cfg и /etc/grub2.cfg)
- grub2-pc-modules (модули для сборки своего варианта grub)
- grub2-tools (утилиты для сборки файла конфигурации: /etc/default/grub, /etc/grub.d/*;
для установки: /usr/bin/{grub2-menulst2cfg,grub2-mkrelpath,grub2-render-label,grub2-script-check}
и /usr/sbin/{grub2-bios-setup,grub2-install,grub2-macbless,grub2-mkconfig,grub2-probe,grub2-reboot,grub2-rpm-sort};
файлы шрифтов (/usr/share/grub/unicode.pf2), настройки bash, документация)
- grub2-tools-extra (ссылка /etc/sysconfig/grub на /etc/default/grub;
утилиты /usr/bin/{grub2-fstest,glue-efi,kbdcomp,mkfont,mkimage,mklayout,mknetdir,mkrescue,mkstandalone,syslinux2cfg})
- grub2-tools-minimal (/etc/prelink.conf.d/grub2.conf,
утилиты и документация /usr/bin/{grub2-editenv,grub2-mkpasswd-pbkdf2}, /usr/sbin/{grub2-get-kernel-settings,grub2-set-default,grub2-setpassword})
- grubby (используется при обновлении ядра как инструмент для доступа к настройкам grub, lilo и др.)
- grub-customizer (графическая утилита редактирования файла настроек: /usr/bin/grub-customizer, /etc/grub-customizer/grub.cfg)
- grub2-efi-x64-cdboot (для использования сменяемых носителей в условиях UEFI: /boot/efi/EFI/centos/gcdx64.efi, /boot/efi/EFI/centos/fonts/unicode.pf2)
Составные части:
- boot.img - 512 байт, записывается в MBR или загрузочный сектор раздела формата MBR, загружает первый сектор core.img по непосредственному адресу; аналог stage1
- diskboot.img, cdboot.img, pxeboot.img, lnxboot.img - первый сектор core.img, читает остаток core.img используя список блоков
- kernel.img - набор утилит, встраивается в core.img
- core.img - собирается grub-mkimage из kernel.img и требуемых модулей
- *.mod - модули могут быть встроены в core.img, подгружаться автоматически или вручную
GRUB 2 с поддержкой UEFI, GPT, OpenFirmware, NTFS. Варианты установки:
Для установки GRUB 2 необходимо иметь установленными пакеты grub2, grub2-common, grub2-pc (для случая с BIOS),
grub2-efi-x64 (для случая с UEFI), grub2-tools, grub2-tools-minimal, grub2-tools-extra.
grub2-install использует grub2-mkimage для сборки core.img.
Установка GRUB 2 в MBR и /boot/grub2/ на диске sda:
grub2-install [--boot-directory=/boot] /dev/sda
Если дырка (gap) между MBR и первым разделом недостаточна для размещения
полного GRUB2, то он пытается установить минимальную версию (boot.img), а остальное в /boot.
Необходимо учитывать ограничения на список допустимых файловых систем и LVM/RAID структур для /boot,
а также возможность разрушения цепочки загрузки при fsck и т.д.
Установка GRUB 2 на GPT в ESP раздел для UEFI (/boot/efi/)
или BIOS boot partition (0xef02) (содержимое затирается?):
grub2-install [--efi-directory=/boot/efi] [--boot-directory=/boot]
GRUB 2 может загружать ОС:
- самостоятельно командой boot (multiboot, Linux, FreeBSD, NetBSD, OpenBSD)
- вызывая kexec из загруженной системы
- командой chainloader в реальном режиме (необходимо загрузить модуль chain.mod (insmod chain), модуль файловой системы (insmod ntfs),
определить корневое устройство (set root=...)); только BIOS и UEFI
Дополнительные ключи grub2-install:
- --help
- --verbose
- --compress[=no,xz,gz,lzo]
- --core-compress=xz|none|auto
- --recheck # перепроверить содержимое device.map
- --no-rs-codes # не дописывать контрольные суммы к core.img
- --directory=каталог-образов # /usr/lib/grub/платформа/
- --fonts=unicode
- --install-modules=all
- --pubkey=имя-файла # публичный ключ встраивается в core.img
- --no-bootsector
- --no-nvram # не менять настройки менеджера загрузки UEFI
- --target=x86_64-efi
В качестве корневого устройства может использовать диск в памяти (ramdisk) с помощью команды initrd
(initrd16, kfreebsd_module, kopenbsd_ramdisk и др.).
Перед загрузкой (команда boot) Linux необходимо загрузить ядро командой "linux[16] имя-файла-ядра"
и обеспечить совпадение корневого устройства между GRUB и ядром Linux, например, "search --set=root --file имя-файла-ядра".
Пример использования chainloader: обеспечение загрузки memtest86 от PassMark (free, 7.4, ISO версия) на сервер с UEFI и GRUB2:
(загрузка memtest по PXE в UEFI вырезана преднамеренно: не работает ни впрямую, ни через grub2 chainloader)
/boot/efi/EFI/centos/grubx64.efi берётся из grub2-efi-x64-2.02-0.87.el7.centos.7.x86_64
Внутри везде используется UTF-8, включая файлы настройки.
Однако имена файлов NTFS, FAT, Jouliet, UDF и JFS - в UTF-16.
Консоль BIOS - ASCII, консоль UEFI - UTF-16 (формально), при использовании gfxterm нужны правильные шрифты.
Имеются средства i18n и l10n (gettext, locale/).
Изменения
- от 2.02 (RHEl/CentOS 7) до 2.06:
- поддержка RISC-V
- поддержка Xen PVH
- встроенная поддержка UEFI secure boot (?)
- драйвер UEFI TPM
- Btrfs RAID 5/6
- PARTUUID
- VLAN
- встроенная поддержка DHCP (?)
- SBAT
- LUKS2
- Xen XSM/FLASK
- исправление ошибок
- от 2.06 до 2.12
- унификация загрузчика Linux EFI
- SDL2
- LoongArch
- исправление ошибок
Настройки GRUB 2 хранятся в файле grub.conf (/boot/grub2/grub.cfg и /boot/efi/EFI/centos/grub.cfg),
в большинстве случаев изготавливаются автоматизированно с помощью команды
"grub2-mkconfig -o /boot/grub2/grub.cfg" (или "grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg"),
которая ищет имеющиеся ядра и автоматически создаёт строки меню для них: по 2 на ядро - для нормальной работы и для восстановления.
По умолчанию создаётся вложенное меню для старых версий.
Если файл не найден, то GRUB 2 переходит в командный режим.
Файл настройки может быть встроен в сам GRUB 2 - в core.img ("grub-mkimage -c"), нельзя встраивать меню.
Это полезно, если есть проблемы с поиском файла grub.cfg при загрузке, позволяет определить корень и/или загрузить "настоящий" файл с настройками.
В теории grub2-mkconfig при наличии initrd должен добавлять в строку загрузки ядра параметр "root=UUID=...",
если явно не запрещено, но на практике я наблюдаю "root=/dev/mapper/system-root".
Настройки для команды создания файла настроек хранятся в /etc/default/grub
в виде значений переменных окружения (перечислил не все):
- GRUB_DEFAULT=0 - номер строки меню (от 0), идентификатор строки меню ("menuentry --id идентификатор ..."),
строка "saved" (сохраняется командой grub-set-default или переменной окружения GRUB_SAVEDEFAULT в файле grubenv рядом с grub.cfg)
- GRUB_SAVEDEFAULT=false - при выборе из меню результат записывается в файле grubenv рядом с grub.cfg
- GRUB_TIMEOUT=5 - автоматически выбирать указанное в GRUB_DEFAULT через указанное число секунд; 0 - не ждать; -1 - ждать вечно
- GRUB_TIMEOUT_STYLE=menu - menu: показать меню и начать отсчёт; hidden: ждать, не показывая меню
(показывать после нажатия ESC, F4, SHIFT); countdown: ждать, не показывая меню, но роказывая отсчёт
- GRUB_DISTRIBUTOR - пояснительный текст
- GRUB_TERMINAL_INPUT, GRUB_TERMINAL_OUTPUT, GRUB_TERMINAL - console, serial
- GRUB_CMDLINE_LINUX - параметры ядра общие
- GRUB_CMDLINE_LINUX_DEFAULT - дополнительные параметры ядра для нормальной работы (после общих)
- GRUB_CMDLINE_LINUX_RECOVERY=single - дополнительные параметры ядра для режима восстановления (до общих)
- GRUB_EARLY_INITRD_LINUX_STOCK, GRUB_EARLY_INITRD_LINUX_CUSTOM - начальные initrd
- GRUB_DISABLE_LINUX_UUID=false, GRUB_DISABLE_UUID=false - не генерировать параметр ядра "root=UUID=..."
- GRUB_DISABLE_LINUX_PARTUUID=true - не генерировать параметр ядра "root=PARTUUID=..." при отсутствии "root=UUID=..."
- GRUB_DISABLE_RECOVERY=false - не генерировать строки меню для режима восстановления; первоначальный rescue остаётся?
- GRUB_VIDEO_BACKEND - видеодрайвер вместо автоматически выбранного, список в /usr/lib/grub/*/video.lst
- GRUB_GFXMODE=auto, GRUB_GFXPAYLOAD_LINUX=text - разрешение экрана из списка VBE (VESA BIOS Extensions), Ширина x Высота x Глубина
- GRUB_BACKGROUND, GRUB_THEME - оформление графического режима
- GRUB_DISABLE_OS_PROBER=true, GRUB_OS_PROBER_SKIP_LIST - позволяет использовать os-prober для генерации меню (работает ли он нынче?)
- GRUB_DISABLE_SUBMENU=false - запретить генерируемое по умолчанию вложенное меню
- GRUB_ENABLE_CRYPTODISK=false
- GRUB_INIT_TUNE - играть музыку на спикере (play)
- GRUB_BADRAM - обходить плохую память (badram)
- GRUB_PRELOAD_MODULES - список модулей GRUB 2 через пробел
Процедура настройки задаётся скриптами в /etc/grub.d/.
/etc/grub.d/40_custom можно использовать для добавления строк меню.
Скрипт /etc/grub.d/41_custom добавляет содержимое custom.cfg
При необходимости grub.cfg можно ввести или отредактировать любым текстовым редактором.
Язык grub.cfg похож на Bash.
Текст состоит из слов, разделённых символами пробел, табуляция, новая строка, '{', '}', '|', '&', '$', ';', /</, />'.
При необходимости можно использовать экранирование символов с помощью '\' и
квотирование с помощью '"' (обрабатывается подстановка переменных и частично символы экранирования) и "'" (не обрабатывается ничего).
Комментарий начинается с символа '#' и заканчивается концом строки.
Утилита grub2-script-check позволяет проверить правильность синтаксиса.
Имеются встроенные и пользовательские переменные окружения (как в Bash).
Значение переменной используется в виде '$имя' или '${имя}'.
Позиционный параметр функции указывается как '$число' ('$@' - все позиционные параметры, '$*' - все позиционные параметры без квотирования, '$#' - количество параметров).
Код возврата предыдущей команды указывается как '$?'.
Файл grubenv (1024 байта) рядом может хранить переменные окружения (команды save_anv и load_env, утилита grub-editenv), не работает в RAID, LVM, ZFS и т.п.
Например:
saved_entry=строка меню удачной загрузки
kernelopts=параметры ядра
boot_success=1
boot_indeterminate=0 #
Значение переменной нельзя использовать для генерации имени переменной (${net_${if}_hostname}).
Встроенные переменные (некоторые):
- chosen - идентификатор (--id) выбранного раздела меню
- config_directory - имя каталога файла настроек
- config_file - имя файла настроек, обработанного командами configfile и normal
- debug - включение отладочной печати, all - всей, за подробностями отсылают к исходникам
- default - можно задать заголовок/номер/идентификатор раздела меню, который будет выбран по умолчанию (GRUB_DEFAULT, grub-set-default)
- fallback - можно задать заголовок/номер/идентификатор раздела меню, который будет выбран если загрузиться не удалось
- gfxmode - auto, через запятую ил точку с запятой разрешения экрана из списка VBE (VESA BIOS Extensions), Ширина x Высота [x Глубина]
- gfxpayload - в каком графическом режиме загрузить ядро Linux: text, keep, значения из gfxmode
- grub_cpu
- grub_platform - pc или efi
- lang
- pager - делать паузу при выводе текста
- prefix - имя корневого устройства и имя каталога GRUB
- root - имя корневого устройства GRUB
- timeout - время ожидания выбора из меню 0 - не ждать; -1 - ждать вечно
- timeout style - menu: показать меню и начать отсчёт; hidden: ждать, не показывая меню
(показывать после нажатия ESC, F4, SHIFT); countdown: ждать, не показывая меню, но показывая отсчёт
Простые команды состоят из слова имени команды и параметров через пробел до ';' или конца строки.
Символ '!' инвертирует код возврата.
Составные команды (см. bash):
- for имя in слово ...; do список-команд; done
- if список; then список; [elif список; then список;] ... [else список;] fi # then выполняется, если код возврата последней команды списка равен 0
- while список; do список; done # исполнять пока 0
- until список; do список; done # исполнять до 0
- function имя { команда; ... }
- menuentry заголовок [--class=класс ] [--users=пользователи] [--unrestricted] [--hotkey=символ] [--id=идентификатор-строки-меню] { команда; ... }
Встроенные команды:
- break [количество-уровней] # выход из цикла
- continue [количество-уровней] # перейти к следующей итерации цикла
- return [значение] # выход из функции
- setparams аргументы # заменить позиционные параметры функции аргументами
- shift [число] # сдвиг номеров позиционных параметров влево
Внешний вид меню задаётся с помощью тем.
Элементами темы являются: цвет (#RRGGBB), шрифт (растровый PFF2), индикатор выполнения (progress bar), круговой индикатор выполнения,
метки (цвет, шрифт, выравнивание), меню загрузки (заголовки, иконки) и др.
Тема описывается в отдельном текстовом файле.
Корнем конструкции является canvas, в котором размещается всё остальное.
Если файл настроек не найден или в нём нет меню или вместо выбора из меню оператор нажал C,
то GRUB переходит в командный режим (ESC - возврат в меню).
Нажатие E в меню позволяет отредактировать и выполнить раздел меню (ESC - возврат в меню без изменений, ^X - выполнение отредактированных команд раздела).
Нажатие P - ввод пароля, ^L - перерисовка меню.
Введённая в командном режиме команда немедленно исполняется (следите за изменениями GRUB 2!).
В командном режиме доступны клавиши управления курсором и команды редактирования
строки, похожие на Bash:
- ^F (вперёд)
- ^B (назад)
- ^A (в начало строки)
- ^E (в конец строки)
- ^D (удалить симовл)
- ^H (удалить символ перед курсором)
- ^K (удалить текст до конца строки)
- ^U (удалить текст от начала строки)
- ^Y (вставить удалённый текст)
- ^P (вспомнить предыдущую строку из истории команд)
- ^N (вспомнить следующую строку из истории команд)
- ^I (автодополнение)
Некоторые команды (распределение команд по модулям в файле command.lst):
- help [шаблон]
- menuentry заголовок аргумент2 ... { команда; ... } # описание строки меню; при выборе выполняет указанные команды и при успехе команду boot;
заголовок и аргументы передаются как позиционные параметры; опциональные ключи:
- --unrestricted # все пользователи могут сделать это
- --id идентификатор
- --class имя-класса # можно указывать несколько раз; указание на тему оформления
- --hotkey буква
- --user список-допущенных-пользователей
- submenu заголовок { строки меню } # описание вложенного меню; опциональные ключи те же самые
- chainloader [--force] имя-файла [аргумент1 ...] # аргументы передаются только в случае UEFI
- linux имя-файла командная-строка # загрузить ядро Linux в режиме 32-бит; vga= не работает, используйте команду GRUB set "gfxpayload=1024x768"
- linux16 имя-файла командная-строка # загрузить ядро Linux в реальном режиме
- linuxefi имя-файла командная-строка # загрузить ядро Linux в UEFI
- initrd имя-файла [имя-файла ...] # только после команды linux; загрузить RAM диски по порядку;
можно динамически добавлять или подменять файлы в архиве с помощью оператора newc:
- initrd имя-файла [имя-файла ...] # только после команды linux16; загрузить RAM диски по порядку в реальном режиме;
можно динамически добавлять или подменять файлы в архиве с помощью оператора newc:
- boot # запустить загруженное ядро с загруженным RAM диском
- initrdefi имя-файла [имя-файла ...] # только после команды linuxefi
- terminal_input [ --append | --remove ] [тип ...] # console, serial; вывести, установить, добавить или удалить тип ввода
- terminal_output [ --append | --remove ] [тип ...] # console, serial; вывести, установить, добавить или удалить тип вывода
- badram адрес,маска ... # исключить область памяти, формат аналогичен memtest86+; GRUB передаёт этот список дальше
- blocklist имя-файла # вывести список блоков для файла
- cat [--dos] имя-файла
- clear
- cmp [-v] файл1 файл2
- configfile имя-файла # загрузить и выполнить файл настроек, при завершении значения переменных не сохраняются
- cutmem от до # исключить область памяти; GRUB передаёт этот список дальше
- date [[year-]month-day] [hour:minute[:second]]
- drivemap из в # подмена устройства; -l - вывести список подмен, -s - обратное отображение, -r - сбросить список
- echo строка # -n - не выводить NL, -e - интерпретация последовательностей (см. echo(1))
- efitextmod [колонок строк | min | max | номер-режима] # вывести список или установить текстовый режим UEFI
- eval строка ... # объединить и вычислить строки, выполнить результат как команды GRUB
- export имя-переменной # будут видны после загрузки configfile
- false
- fwsetup [--is-supported] # перезагрузиться в меню BIOS/UEFI SETUP; --is-supported - проверить возможность
- halt [--no-apm] # остановить компьютер; --no-apm - без использования APM
- hashsum тип [--uncompress] {--check имя-файла-со-списком | имя файла ...} # вычислить или проверить хэш
- hexdump [--skip смещение] [--length длина] файл-или-устройство # можно использовать устройство "(mem)"
- insmod имя-модуля # загрузить модуль
- list_env [--file имя-файла] # вывести значения переменных, сохранённых в файле grubenv
- load_env [--file имя-файла] [список-допустимых-переменных] # загрузить значения переменных, сохранённых в файле grubenv
- loopback имя-устройства имя-файла # далее интерпретировать файл как устройство, -d - удалить устройство, -D - декомпрессировать файл
- ls [устройство-или-каталог] # вывести список устройств, имя файловой системы или список файлов
- lsmod # вывести список загруженных модулей
- normal [имя-файла] # автоматическая загрузка модулей, полная интерпретация настроек
- normal_exit # выход из нормального режима в аварийный (rescue), модули надо загружать вручную, не все команды обрабатываются
- probe {--driver | --partmap | --fs | --fs-uuid | --label | --part-uuid} устройство # извлечь информацию об устройстве;
"--set имя-переменной" - записать в переменную окружения
- read [имя-переменной] # -s - не отображать ввод
- reboot
- regexp регулярное-выражение строка # сравнение; "--set [номер:]переменная" - записать подвыражение в переменную, нумерация с 1
- rmmod имя-модуля # выгрузить модуль
- save_env [--file имя-файла] имя-переменной ... # записать переменные в файл grubenv
- search [--file | --label | --fs-uuid] имя # поиск устройства по имени файла, метке или UUID файловой системы;
дополнительные опции:
- --set [имя-переменной] # записать в переменную окружения [root]
- --no-floppy # не искать на флопидисках
- --efidisk-only # искать только на дисках UEFI (GPT?)
- --hint имя-устройства # начать поиск с этого устройства
- --hint-bios имя-устройства
- --hint-efi имя-устройства
- --hint-baremetal имя-устройства
- sendkey имя-клавиши # запихнуть в буфер ввода код указанной клавиши (escape, asterisk, shift, alt и т.п.) для загружаемой ОС;
модификаторы (с аргументом on или off): --num, --caps, --scroll, --left-shift, --right-shift, --sysrq, --left-alt, --right-alt, --left-ctrl, --right-ctrl и др.;
только для i386-pc (BIOS) и если ОС использует буфер ввода BIOS
- set [имя-переменной=значение]
- sleep секунд # --verbose - показывать отсчёт; --interruptible - можно прервать по ESC, F$ или SHIFT
- smbios [--type тип] [--handle указатель] [--match номер-по-порядку] {--get-byte | --get-word | --get-dword | --get-qword | --get-string | --get-uuid} смещение
# извлечь информацию из SMBIOS (можно потренироваться на dmidecode); "--set имя-переменной" - записать в переменную
- source имя-файла # вставить содержимое файла в файл настроек, выполнить без смены контекста
- test выражение # сравнение (можно записывать как "[ выражение ]"), выражения:
- строка1 == строка2
- строка1 != строка2
- строка1 < строка2
- строка1 <= строка2
- строка1 > строка2
- строка1 >= строка2
- число1 -eq число2
- число1 -ge число2
- число1 -gt число2
- число1 -le число2
- число1 -lt число2
- число1 -ne число2
- имя-файла1 -nt имя-файла2 # файл1 новее файла2
- имя-файла1 -ot имя-файла2 # файл1 старее файла2
- -d имя-каталога # каталог существует
- -e имя-файла # файл существует
- -f имя-файла # файл существует и это не каталог
- -s имя-файла # файл существует и не пуст
- -n строка # длина строки больше 0
- строка # длина строки больше 0
- -z строка # длина строки равна 0
- ( выражение )
- ! выражение
- выражение1 -a выражение2 # AND
- выражение1 -o выражение2 # OR
true
unset имя-переменной
videoinfo # вывести список видеорежимов
После принятия стандарта Boot Loader Specification меню генерится командой blscfg из содержимого
каталога /boot/loader/entries/. Каждый файл .conf в нём порождает строку меню, файл grub.cfg лишь задаёт параметры $kerneloptsб $tuned_paramsб $grub_users.
Раздел /boot (XBOOTLDR) определяется значением переменной boot (например, mduuid/уникальный-идентификатор-раздела).
Пример:
title Rocky Linux (4.18.0-553.8.1.el8_10.x86_64) 8.10 (Green Obsidian)
version 4.18.0-553.8.1.el8_10.x86_64
linux /vmlinuz-4.18.0-553.8.1.el8_10.x86_64
initrd /initramfs-4.18.0-553.8.1.el8_10.x86_64.img $tuned_initrd
options $kernelopts $tuned_params
id rocky-20240702172104-4.18.0-553.8.1.el8_10.x86_64
grub_users $grub_users
grub_arg --unrestricted
grub_class kernel
Для предотвращения вечного цикла неудачных загрузок файл grubenv хранит переменные
(в имени файла перед .conf может быть закодировано "+остаток_попыток-сделано_попыток"; /etc/kernel/tries)
- boot_success - 1 после успешной загрузки; успешность определяется systemd (systemd-boot-check-no-failures.service,
systemd-bless-boot.service и boot-complete.target)
- boot_indeterminate - 1 до первой успешной загрузки или исчерпания количества попыток
При загрузке с использованием PXE (PXE клиент, shim, grub) GRUB 2 по очереди ищет настройки в файлах
grub.cfg-UUID_клиента, при неудаче исходя из его MAC-адреса ("grub.cfg-MACадрес", например "grub.cfg-88-99-aa-bb-cc-dd"),
при неудаче исходя из его IP адреса (16-ричная нотация с прописными буквами, например, "grub.cfg-C0A8025B", утилита gethostip позволяет получить имя из IP адреса),
при неудаче из урезанного справа IP-адреса, при полной неудаче берётся файл grub.cfg.
Если его нет, то переходит в командный интерфейс.
Переменные окружения UEFI PXE:
- net_default_interface - имя интерфейса, с которого загрузился grub
- net_default_ip
- net_default_mac
- net_default_server
- net_интерфейс_ip
- net_интерфейс_mac
- net_интерфейс_clientid - обеспечивается сервером DHCP (MAC?)
- net_интерфейс_clientuuid - обеспечивается сервером DHCP
- net_интерфейс_hostname - обеспечивается сервером DHCP
- net_интерфейс_domain - обеспечивается сервером DHCP
- net_интерфейс_rootpath - обеспечивается сервером DHCP
- net_интерфейс_extensionspath - обеспечивается сервером DHCP
- net_интерфейс_boot_file - обеспечивается сервером DHCP
- net_интерфейс_dhcp_server_name
- net_интерфейс_next_server - IP адрес сервера TFTP
- pxe_blksize # ?
- pxe_default_gateway # ?
- pxe_default_server # ?
Команды GRUB 2
- net_add_addr интерфейс сетевая-карта адрес # сконфигурировать интерфейс и локальный маршрут; что такое имя интерфейса (efinet5:dhcp?) и имя карты (efinet5?)
- net_add_dns IP-адрес-DNS
- net_add_route имя IP-адрес[/префикс] {интерфейс | gw IP-адрес} # добавить маршрут
- net_del_addr интерфейс # удалить интерфейс с адресом
- net_del_dns IP-адрес-DNS
- net_del_route имя
- net_dhcp [сетевая-карта] # конфигурировать сетевую карту по DHCP; добавляется интерфейс с именем "имя-карты:dhcp";
обрабатываются опции DHCP (имеются разночтения в именах переменных):
subnet-mask, routers, domain-name-servers, host-name (устанавливается переменная net_имя-карты_dhcp_hostname),
domain-name (устанавливается переменная net_имя-карты_dhcp_domain), root-path (устанавливается переменная net_имя-карты_dhcp_rootpath),
extensions-path (устанавливается переменная net_имя-карты_dhcp_extensionspath),
имя сервера TFTP? (устанавливается переменная net_имя-карты_dhcp_server_name), bootfile-name (устанавливается переменная net_имя-карты_boot_file)
- net_get_dhcp_option имя-переменной интерфейс номер-опции-DHCP { string | integer | hex } # записать в переменную значение опции DHCP
- net_ls_addr
- net_ls_cards
- net_ls_dns
- net_ls_routes
- net_nslookup доменное-имя [IP-адрес-сервера-DNS]
- net_set_vlan интерфейс идентификатор-VLAN # в примере указано имя карты, а не интерфейса
Особенности загрузки установщика RHEL/CentOS для случая UEFI PXE.
|
Bog BOS: GRUB - универсальный загрузчик для PC
|
Copyright © 1996-2024 Sergey E. Bogomolov; www.bog.pp.ru