@ Карта сайта News Автора!

Bog BOS: GRUB - универсальный загрузчик для PC

Последние изменения:
2024.11.22: sysadmin: systemd-journald (централизованное хранение)
2024.11.11: sysadmin: Linux: пространства имён
2024.11.06: sysadmin: настройка TCP/IP в Linux: виртуальный интерфейс и виртуальный мост
2024.10.25: sysadmin: Linux VFS, атрибуты, расширенные атрибуты, ACL

Последнее изменение файла: 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

GRUB 0.97 состоит из 3 частей:

Настройки хранятся в файле 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 0.97

GRUB переходит после загрузки в режим командного интерфейса, если не находит конфигурационный файл или если пользователь переводит его явно (команда c в режиме меню). Режим ввода команды напоминает bash, те же клавиши редактирования строки (включая историю команд и автодополнение команд и имён дисков и файлов), немедленное исполнение после нажатия клавиши "Enter". Команды:

GRUB может самостоятельно загрузить ядро ОС или загружить вторичный загрузчик и передать ему управление. В первом случае типовой набор команд выглядит так:

root (hd0,0)
kernel /vmlinuz root=/dev/hda1 ...
inird /initrd.img
boot

Во втором так:

rootnoverify (hd0,0)
map ...
hide ...
unhide ...
makeactive ...
chainloader +1
boot

Команды управления интерфейсом и процессом:

"Исследовательские" команды:

Команды для установки GRUB:

Команды для загрузки по сети (после определения сетевых параметров можно использовать сетевой диск - (nd) - для загрузки файлов по TFTP; интересно GRUB знает про все на свете сетевые карточки?):

Команды для работы с терминалом по RS-232:

Описание меню GRUB 0.97

GRUB переходит после загрузки в режим работы с меню, если находит конфигурационный файл. Команды работы с меню описаны на экране (перемещение по меню, выбор текущей секции, переход в командный режим, редактирование меню).

Меню создаётся из конфигурационного файла grub.conf в загрузочном каталоге (/grub или /boot/grub) в момент загрузки. Конфигурационный файл может содержать любые команды командного интерфейса GRUB и некоторые дополнительные. Комментарии начинаются с символа '#'. Файл делится на секции, разделяемые командой title. Секция до первой команды title задаёт общие параметры, в частности секцию по умолчанию и описание интерфейса. Каждая команда title задаёт имя секции, которое будет высвечиваться на экране в момент загрузки. При выборе данной секции выполняются составляющие её команды. Указывать команду boot в конце секции необязательно - она подразумевается.

Команды, задающие общие параметры:

Команды, которые могут входить в секцию:

Установка GRUB 0.97

Скорее всего, что 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.

GRUB 2

Этой ОС не нужны другие ОС! Шутка (почти).

Пакеты:

Составные части:

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 может загружать ОС:

Дополнительные ключи grub2-install:

В качестве корневого устройства может использовать диск в памяти (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/).

Изменения

Настройка GRUB 2

Настройки 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 в виде значений переменных окружения (перечислил не все):

Процедура настройки задаётся скриптами в /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}). Встроенные переменные (некоторые):

Простые команды состоят из слова имени команды и параметров через пробел до ';' или конца строки. Символ '!' инвертирует код возврата. Составные команды (см. bash):

Встроенные команды:

Внешний вид меню задаётся с помощью тем. Элементами темы являются: цвет (#RRGGBB), шрифт (растровый PFF2), индикатор выполнения (progress bar), круговой индикатор выполнения, метки (цвет, шрифт, выравнивание), меню загрузки (заголовки, иконки) и др. Тема описывается в отдельном текстовом файле. Корнем конструкции является canvas, в котором размещается всё остальное.

Если файл настроек не найден или в нём нет меню или вместо выбора из меню оператор нажал C, то GRUB переходит в командный режим (ESC - возврат в меню). Нажатие E в меню позволяет отредактировать и выполнить раздел меню (ESC - возврат в меню без изменений, ^X - выполнение отредактированных команд раздела). Нажатие P - ввод пароля, ^L - перерисовка меню. Введённая в командном режиме команда немедленно исполняется (следите за изменениями GRUB 2!). В командном режиме доступны клавиши управления курсором и команды редактирования строки, похожие на Bash:

Некоторые команды (распределение команд по модулям в файле command.lst):

  • 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)

    Особенности GRUB 2 при загрузке UEFI PXE

    При загрузке с использованием 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:

    Команды GRUB 2

    Особенности загрузки установщика RHEL/CentOS для случая UEFI PXE.

    Ссылки

    @ Карта сайта News Автора!

    Bog BOS: GRUB - универсальный загрузчик для PC

    Последние изменения:
    2024.11.22: sysadmin: systemd-journald (централизованное хранение)
    2024.11.11: sysadmin: Linux: пространства имён
    2024.11.06: sysadmin: настройка TCP/IP в Linux: виртуальный интерфейс и виртуальный мост
    2024.10.25: sysadmin: Linux VFS, атрибуты, расширенные атрибуты, ACL



    Copyright © 1996-2024 Sergey E. Bogomolov; www.bog.pp.ru