Глава 3. Начальный загрузчик GRUB

Тот начальный загрузчик, который используют системы Linux в эти дни это GRUB версии 2. Самая первый стабильный выпуск GRUB 2 состоялся в 2012, однако он начал появляться в Linux корпоративного уровня в 2014 с Centod 7 и RHEL 7. После 2015 он наблюдался как широко адаптированный в почти всех популярных дистрибутивах Linux. Обычно, когда пользователи сообщают об ошибках или запрашивают новые функциональные возможности, разработчики прислушиваются к получаемым отзывам, расставляют приоритеты и в конечном счёте запускают некую новую версию кода. Тем не менее, в случае GRUB это работает несколько иным способом. Разработчики GRUB приняли решение изменить всю структуру GRUB 2 в то время, когда пользователи были счастливы с наследуемым GRUB (версии 1).

"Наследуемый GRUB превратился в не поддающийся поддержке из- за неряшливого кода и неудачного проектирования. Мы получили большое число запросов на новые функции и расширили GRUB за рамки первоначальной сферы, при этом не изменяли его конструкцию. Это привело к тому, что больше не возможно было расширять GRUB без переосмысления всего с самого начала."

-GNU GRUB FAQ

Вот некоторые предоставляемые или находящиеся в разработке функциональные возможности GRUB:

  • Полная поддержка USB.

  • Поддержка LUKS (Linux Unified Setup Key, Унифицированного ключа установки Linux). LUKS выступает стандартом для шифрования жёсткого диска Linux.

  • Модная реализация меню, которая обладает анимацией, эффектами, таблицами стилей и т.п.

  • Инструмент "parted" будет добавлен в имеющийся начальный загрузчик. После его добавления пользователи смогут редактировать настройки диска в момент загрузки.

Данная глава рассмотрит следующее:

  • Как GRUB 2 реализуется для встроенного ПО BIOS и UEFI.

  • Относящиеся к встроенному ПО структурные изменения в GRUB 2.

  • Функциональные возможности спецификации начального загрузчика GRUB 2.

  • Функциональная возможность Безопасного запуска UEFI и то как она реализована в GRUB 2.

  • Некоторые относящиеся к начальному загрузчику проблемы и как их можно исправлять.

Реализация GRUB 2

Как мы уже видели, GRUB получает управление от встроенного ПО. Это означает, что ему приходится иметь дело как с UEFI, так и с BIOS. Для начала давайте рассмотрим как GRUB 2 был реализован для систем на основе BIOS.

GRUB 2 в системах на основе BIOS

GRUB 2 в системах на основе BIOS удерживает все свои файлы в трёх различных местоположениях.

  • /boot/grub2/

  • /etc/default/grub

  • /etc/grub.d/

В случае Ubuntu версия 2 не применяется в именовании GRUB, а потому это будет /boot/grub/ вместо /boot/grub2/, grub-install вместо grub2-install и grub-mkconfig вместо grub2-mkconfig.

Давайте обсудим эти местоположения и их содержимое.

/boot/grub2

Это то местоположение, в котором будет установлен GRUB 2. Как вы можете видеть на Рисунке 3-1, этот каталог содержит основные файлы ядра начального загрузчика.

 

Рисунок 3-1


Представленные в /boot/grub2 файлы

Device.map

GRUB не понимает названия дисков такие как sda или vda, так как эти соглашения об именование дисков были созданы драйверами SCSI операционной системы. Очевидно, что GRUB исполняется когда ваша ОС ещё не представлена, а потому он обладает своим собственным соглашением именования дисков. Ниже приводятся соглашения об именовании дисков GRUB:

Таблица 3-1. Соглашения GRUB именования дисков
Версия GRUB Соглашение именования дисков Значение

2

hd0, msdos1

Жёсткий диск номер 0 и раздел номер 1, который обладает разделом таблиц MS-DOS

2

hd1, msdos3

Жёсткий диск номер 2 и раздел номер 3, который обладает разделом таблиц MS-DOS

2

hd2, gpt1

Жёсткий диск номер 3 и раздел номер 1, который обладает разделом таблиц GPT

1

hd0, 0

Жёсткий диск номер 0 и раздел номер 0

В GRUB номер жёсткого диска начинается с 0, а номера его разделов стартуют с 1, в то время как соглашения об именовании дисков и разделов ОС стартуют с 1. Поскольку соглашения об именовании дисков ОС и GRUB различны, следует устанавливать соответствие для пользователей и именно по этой причине был создан файл device.map.


# cat /boot/grub2/device.map
      # this device map was generated by anaconda
      (hd0)      /dev/sda
		

Этот файл device.map будет применяться grub2-install в качестве команд для понимания на каком из дисков установлены файлы ядра GRUB. Вот некий образец такого файла:


# strace -o delete_it.txt grub2-install /dev/sda
Installing for i386-pc platform.
      Installation finished. No error reported.
# cat delete_it.txt | grep -i 'device.map'
      openat(AT_FDCWD, "/boot/grub2/device.map", O_RDONLY) = 3
      read(3, "# this device map was generated "..., 4096) = 64
      openat(AT_FDCWD, "/boot/grub2/device.map", O_RDONLY) = 3
      read(3, "# this device map was generated "..., 4096) = 64
		

Наша команда grub2-install получит ввод в виде соглашений именования дисков ОС, так как пользователи не осведомлены о соглашениях именования дисков GRUB. В процессе своего выполнения grub2-install преобразует соглашения об именовании дисков SCSI в соглашения об именовании дисков GRUB считав файл device.map.

grub.cfg

Это основной файл настрое GRUB. Как вы можете видеть на Рисунке 3-2, это гигантский файл сценария, который вырабатывается по ссылкам на прочие файлы сценариев, которые мы вскоре обсудим. Настоятельно предлагается не вносить изменения в само содержание grub.cfg, поскольку это может превратить вашу версию Linux в не запускаемую. Именно этот файл является тем, из которого Часть 3 GRUB получает такие инструкции как:

  • Местоположение своего ядра и initramfs

    • /boot/vmlinuz-<version>

    • /boot/initramfs-<version>

  • Подобные командам параметры ядра

    • Название корневой файловой системы и её местоположения и т.п.

 

Рисунок 3-2


Файл grub.cfg

Как вы можете увидеть отсюда, GRUB обладает своим собственным набором команд:

Таблица 3-2. Собственные команды GRUB
Команда GRUB Назначение

menuentry

Выводит на печать на экран имеющийся заголовок.

set root

Предоставит названия диска и раздела в которых хранятся необходимое ядро и initramfs

linux

Значение абсолютного пути к самому файлу ядра Linux

initrd

Значение абсолютного пути к самому файлу initramfs Linux

Итак, последовательность запуска GRUB 2 в системе Fedora на основе BIOS следующая:

  1. Включается электропитание: вначале BIOS, далее POST, затем BIOS и после этого самый первый сектор.

  2. Первой идёт самораскрутка (Часть 1 GRUB), затем Часть 2 GRUB и потом Часть 3 GRUB.

  3. Часть 3 GRUB считает только что показанный grub.cfg из /boot/grub2/ (в случае Ubuntu это будет /boot/grub/) и выдаст на печать приветственное окно, как это отображено на Рисунке 3-3.

     

    Рисунок 3-3


    Приветственное окно

  4. В тот момент как пользователь выбирает menuentry, будут запущены команды set root, linux и initrd и стартует загрузка в оперативную память необходимых ядра и initramfs.

  5. В подобных Fedora дистрибутивах Linux вы обнаружите другой подход. Будет иметься файл grub.cfg, однако команды menuentry, set root, linux и initrd будут недоступны в grub.cfg. Тогда это некая новая разработка восходящего проекта GRUB с названием BLS. Мы обсужим её позднее в этом разделе.

i386-pc

Этот каталог имеет в себе модули (драйверы) всех имеющихся сопровождаемых GRUB файловых систем (обратитесь, пожалуйста, к Рисунку 3-4. Все файлы *.mod являются такими модулями. Применяя эти модули GRUB способен загружать необходимые файлы ядра и initramfs в оперативную память. Например, /boot в этой системе обладает файловой системой ext4, а потому, очевидно, при выявлении и загрузке файлов vmlinuz и initramfs из /boot, GRUB требуется модуль ext4, который он и получает из файла ext4.mod. Аналогично для /boot в файловой системе XFS или UFS; следовательно, файлы xfs.mod и ufs.mod представлены в /boot/grub2/i386-pc. В то же самое время вы обнаружите такие файлы как http.mod и pxe.mod. Это означает, что Часть 3 GRUB 2 может загружать необходимые файлы ядра и initramfs с устройств http и pxe. В целом, файлы *.mod добавляют функциональные возможности, а не просто устройства. Эти возможности будут включать в себя поддержку устройства, поддержку файловой системы или сопровождение протокола.

Ранее, /boot под LVM был не возможен и причина этого была простой. GRUB не понимал устройства LVM. Для распознавания и сборки необходимого устройства LVM GRUB потребуется модуль LVM, а также такие исполняемые файлы как vgscan, vgchange, pvs, lvscan и т.п.. Это увеличивало бы размер GRUB как пакета; следовательно, производители основных корпоративных систем Linux всегда избегали /boot на устройствах LVM. Однако после введения UEFI GRUB начал поддерживать /boot и на устройствах LVM.

 

Рисунок 3-4




Файлы .mod* из /boot/grub2/i386-pc

Как вы можете видеть на Рисунке 3-5, помимо таких файлов *.mod, вы обнаружите и пару прочих файлов в рассматриваемом нами местоположении /boot/grub2/i386-pc/ .

 

Рисунок 3-5


Дополнительные к *.mod файлы

Файл core.mod это Часть 3 GRUB 2. Поэтому последовательность запуска Linux становится следующей:


-> Power on -> BIOS -> POST -> BIOS ->
-> Часть 1 GRUB2 -> Часть 2 GRUB2 -> core3.img -> grub.cfg ->
-> if /boot находится в файловой системе xfs -> /boot/grub2/i386-pc/xfs.mod ->
-> загружаем vmlinuz & initramfs в основную оперативную память. 
		

После того как наше ядро в оперативной памяти, задание GRUB 2 выполнено. Об оставшейся части последовательности запуска будет заботиться само ядро, которое мы обсудим в Главе 4.

/etc/default/grub

Другой важный файл, это конечон же /etc/default/grub. Обратите, пожалуйста, внимание на Рисунок 3-6.

 

Рисунок 3-6


Содержимое каталога /etc/default

Этот файл используется GRUB для принятия косметических исправлений и изменений командной строки ядра от своего пользователя.


$ cat /etc/default/grub
GRUB_TIMEOUT=10
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="resume=/dev/mapper/root_vg-swap rd.lvm.lv=root_vg/root rd.lvm.lv=root_vg/swap console=ttyS0,115200 console=tty0"
GRUB_DISABLE_RECOVERY="true"
GRUB_ENABLE_BLSCFG=true
		

Как вы можете видеть, в этом файле мы можем изменять значение таймаута по умолчанию приветственного окна GRUB, значение шрифта, значений подменю и параметры командной строки ядра, такие как название его корневого устройства, название устройства подкачки и т.п..

/etc/grub.d/

Теперь мы дошли до того момента, который представляет реальный интерес относительно GRUB 2.

GRUB 2 обладает командой с названием grub2-mkconfig. Её название подразумевает, что она сделает необходимый файл настроек GRUB grub.cfg, который будет справочным для Части 3 GRUB при отображении своего приветственного окна. Файл grub2-mkconfig вначале получит имеющиеся входные параметры косметических исправлений и командной строки ядра из /etc/default/grub и запустит необходимые файлы сценария, перечисленные на внимание на Рисунке 3-7 из своего каталога /etc/grub.d/.

 

Рисунок 3-7


Содержимое каталога /etc/grub.d/

Как вы можете видеть, эти файлы обладают назначенными им номерами вместе с собой. Это означает, что они будут запускаться по порядку.

Соответствующие файлы сценариев 00_header, 01_users, 08_fallback_counting, 10_reset_boot_success и 12_menu_auto_hide выполнят работу по уборке. Например, файл сценария 00_header grub.cfg отвечает за добавление некого заголовка в собираемый файл. Скажем для примера, чо после выполнения файла grub2-mkconfig в Linux Fedora к grub.cfg будет добавлен такой заголовок:


### BEGIN /etc/grub.d/00_header ###
set pager=1
if [ -f ${config_directory}/grubenv ]; then
  load_env -f ${config_directory}/grubenv
elif [ -s $prefix/grubenv ]; then
  load_env
fi
if [ "${next_entry}" ] ; then
   set default="${next_entry}"
   set next_entry=
   save_env next_entry
   set boot_once=true
else
   set default="${saved_entry}"
fi
if [ x"${feature_menuentry_id}" = xy ]; then
  menuentry_id_option="--id"
else
  menuentry_id_option=""
fi
export menuentry_id_option
if [ "${prev_saved_entry}" ]; then
  set saved_entry="${prev_saved_entry}"
  save_env saved_entry
  set prev_saved_entry=
  save_env prev_saved_entry
  set boot_once=true
fi
function savedefault {
  if [ -z "${boot_once}" ]; then
    saved_entry="${chosen}"
    save_env saved_entry
  fi
}
function load_video {
  if [ x$feature_all_video_module = xy ]; then
    insmod all_video
  else
    insmod efi_gop
    insmod efi_uga
    insmod ieee1275_fb
    insmod vbe
    insmod vga
    insmod video_bochs
    insmod video_cirrus
  fi
}
terminal_output console
if [ x$feature_timeout_style = xy ] ; then
  set timeout_style=menu
  set timeout=5
# Fallback normal timeout code in case the timeout_style feature is
# unavailable.
else
  set timeout=5
fi
### END /etc/grub.d/00_header ###
The 08_fallback_counting script file will add the following contents in grub.cfg:
### BEGIN /etc/grub.d/08_fallback_counting ###
insmod increment
# Check if boot_counter exists and boot_success=0 to activate this behaviour.
if [ -n "${boot_counter}" -a "${boot_success}" = "0" ]; then
  # if countdown has ended, choose to boot rollback deployment,
  # i.e. default=1 on OSTree-based systems.
  if  [ "${boot_counter}" = "0" -o "${boot_counter}" = "-1" ]; then
    set default=1
    set boot_counter=-1
  # otherwise decrement boot_counter
  else
    decrement boot_counter
  fi
  save_env boot_counter
fi
### END /etc/grub.d/08_fallback_counting ###
 	   

Как вы можете видеть, этот файл добавляет тот код, который будет отслеживать устанавливаемое по умолчанию значение таймаута приветственного окна GRUB, точно также все остальные файлы (10_reset_boot_success и 12_menu_auto_hide) выполнят работу по приборке для GRUB. Давайте рассмотрим те файлы сценариев,которые превращают GRUB 2 в один из наилучших начальных загрузчиков для множественной загрузки.

10_linux

Этот файл содержит почти 500 строк файла сценария bash. Всякий раз когда некий пользователь выполняет команду grub2-mkconfig, она запускает этот сценарий. 10_linux обнаружит какие прочие дистрибутивы Linux вы установили в своей системе. Он итеративно пройдёт раздел за разделом и отыщет все прочие версии Linux, которые были установлены в вашей системе. Если существует какая- то ещё, она сделает в grub.cfg некую menuentry. Совместно с menuentry она добавит соответствующие записи ядра и initramfs. Ну не замечательно ди?

Положим, вы установили первой Ubuntu и следом Fedora; теперь вам не придётся добавлять записи Ubuntu вручную в grub.cfg Fedora. Вам всего лишь требуется запустить grub2-mkconfig. Эта команда исполнит для нас 10_linux, а она в конечном счёте обнаружит что установлен Ubuntu и добавит для неё соответствующую запись.

20_linux_xen

После 10_linux этот файл сценария обнаружит имеет ли ваша система установленным ядро XEN. Если это так, он добавит надлежащую запись для него в grub.cfg. Большинство распространителей Linux поставляют XEN как некий отдельный пакет ядра. XEN в основном применяется гипервизорами.

20_ppc_terminfo

Если ваша система обладает архитектурой PPC или PowerPC лт IBM, тогда этот файл сценария обнаружит соответствующее ядро и добавит необходимую надлежащую запись в grub.cfg.

30_os_prober

Когда вы имеете на своём HDD установленными ОС не на основе Linux, тогда этот файл сценария обнаружит такую ОС и сделает соответствующую запись для неё. Иными словами, если у вас имеется установленный в вашей системе Windows, он автоматически обнаружит его и выполнит надлежащую запись в grub.cfg. Именно по этой причине после установки нашей третьей ОС (Fedora 31) в системе UEFI, мы получили полный перечень операционных систем ничего не предпринимая. На Рисунке 3-7 вы можете видеть представляемый Fedora 31 приветственный экран.

 

Рисунок 3-8


Экран приветствия

После установки Fedora, Anaconda запускает grub2-mkconfig в фоновом режиме, который в конечном счёте запустил 30_os_prober и он отыскивает нашу установку и сделает соответствующую запись для него в grub.cfg.

30_uefi-firmware

Этот сценарий успешно запустится только когда вы обладаете системой UEFI. Основная задание этого файла сценария состоит в добавлении всех соответствующих записей встроенного ПО UEFI в grub.cfg. Как вы можете увидеть на Рисунке 3-8, файлом сценария 30_uefi-firmware была добавлена запись System setup.


### BEGIN /etc/grub.d/30_uefi-firmware ###
menuentry 'System setup' $menuentry_id_option 'uefi-firmware' {
        fwsetup
}
### END /etc/grub.d/30_uefi-firmware ###
 	   

Если наш пользователь выбирает предоставленный вариант "System setup", тогда он запустит обратно это встроенное ПО UEFI. На Рисунке 3-9 вы можете видеть интерфейс встроенного ПО UEFI.

 

Рисунок 3-9


Экран приветствия

40_custom и 41_custom

Эти записи предоставляются своему пользователю в случае когда этот пользователь желает добавить некие индивидуальные записи в grub.cfg. Например, когда grub2-mkconfig отказывает в добавлении любой из установленных ОС в качестве записей, тогда пользователь добавить некую индивидуальную запись в эти два индивидуальных файла. Вы можете делать свои собственные индивидуальные файлы, но вам следует убедиться что каждый обладает неким назначенным ему номером и обладает полномочиями на выполнение.

GRUB 2 в системах на основе UEFI

И снова имеются три местоположения в которых GRUB 2 хранит свои файлы. Рисунок 3-10 отображает соответствующие каталоги и их файлы.

 

Рисунок 3-10


Местоположения GRUB 2 в системах на основе UEFI

Файл grub.cfg, который был показан ранее в /boot/grub2/, был передвинут в ESP (/boot/efi/EFI/fedora/). Кроме того, как вы можете видеть, не существует каталога i386-pc. Это из- за того, что EFI предоставляет богатую поддержку устройств и файловых систем. Внутри ESP вы можете обнаружить пару файлов *.efi, в том числе исполняемые файлы shim.efi и grubx64.efi. Файл etc/default/grub, который отвечает за косметические изменения и для параметров командной строки ядра всё ещё пребывает в том же самом местоположении. Файл device.map не доступен, так как команда grub2-install не имеет значения в системах UEFI. Позднее в этой главе мы обсудим эту команду.

BLS

BLS (Boot Loader Specification, Спецификация начального загрузчика) это новая разработка в восходящем проекте GRUB которая пока не была адаптирована для многих дистрибутивов основного потока. В частности, эта схема была адаптирована операционными системами на основании Fedora, таких как RHEL, Fedora, Centos, Oracle Linux, и т.п., но не дистрибутивами на основе Debian, таких как Ubuntu, Mint и т.п..

В системах на основе BIOS, в которых ОС обладающая контролем над самыми первыми 512 байтами обладает контролем над последовательностями запуска всех имеющихся операционных систем, именно по этой причине всякая ОС пытается получить удержание этих самых первых 512 байт. Такая ситуация возникает потому, что наш BIOS всегда запускается в самых первых 512 байтах своего HDD и вызывает Часть 1 своего начального загрузчика (самораскрутку). Переход этой Части 1 к Части 2 и от Части 2 к Части 3 происходит позднее и затем в самом конце Часть 3 считывает особый для своего начального загрузчика файл настроек (bcdedit в случае Windows, grub.cfg при варианте с Linux). Еси такой файл настроек обладает соответствующими записями для прочих установленных ОС, тогда они получат шанс для запуска. Итак, длинная история вкратце: всякий кто обладает контролем над самыми первыми 512 байтами контролирует всю последовательность запуска. Однако в случае с ESP все ОС получают некую равную возможность запуска, так как UEFI проверяет имеющиеся каталоги ESP и перечисляет записи всех доступных ОС. Разработчики стали задаваться вопросом могут ли они получить нечто подобное в системе на основе BIOS и они придумали BLS.

В BLS было введено некое новое местоположение (пятое) для хранения необходимых файлов относящихся к начальному загрузчику, и это /boot/loader/. Итак, у нас теперь имеется пять расположений в которых GRUB будет хранить свои файлы.

  • /boot/grub2/

  • /etc/default/grub

  • /etc/grub.d/

  • boot/efi/EFI/<OS_vendor>/ (только в случае UEFI)

  • /boot/loader/ (здесь будут храниться файлы BLS)

Основная идея состоит в том, что после установки соответствующего нового ядра, это ядро само по себе со своими сценарии по окончанию (post-scripts, нечто подобное пакету kernel-core в случае Fedora) создаст некую запись для какого- то нового ядра в своём каталоге /boot/loader/. К примеру, мы установили такой пакет ядра:


# rpm -q kernel
Kernel-5.3.7-301.fc31.x86_64
		

Это тот же самый пакет, который предоставит соответствующие файлы /boot/vmlinuz и /boot/initramfs. После установки этого ядра будет подготовлен такой файл:


# cat /boot/loader/entries/36543031048348f9965e3e12e48bd2b1-5.3.7-301.fc31.x86_64.conf
title Fedora (5.3.7-301.fc31.x86_64) 31 (Thirty One)
version 5.3.7-301.fc31.x86_64
linux /vmlinuz-5.3.7-301.fc31.x86_64
initrd /initramfs-5.3.7-301.fc31.x86_64.img
options $kernelopts
grub_users $grub_users
grub_arg --unrestricted
grub_class kernel
		

Как вы можете видеть, этот файл обладает четырьмя записями.

  • Соответствующий заголовок, который будет выведен на печать Частью 3 GRUB

  • Значениями местоположения и названия файла своего файла ядра

  • Значениями местоположения и названия файла своего файла initramfs

  • Соответствующей переменной $kernelopts, которая была объявлена в файле /boot/grub2/grubenv

    
    # cat /boot/grub2/grubenv
    # GRUB Environment Block
    saved_entry=2058a9f13f9e489dba29c477a8ae2493-5.3.7-301.fc31.x86_64
    menu_auto_hide=1
    boot_success=0
    kernelopts=root=/dev/mapper/fedora_localhost--live-root ro resume=/dev/mapper/fedora_localhost--live-swap rd.lvm.lv=fedora_localhost-live/root rd.lvm.lv=fedora_localhost-live/swap rhgb quiet
    boot_indeterminate=0
    		

В целом, $kernelopts предоставляет параметры командной строки ядра, такие как название своей корневой файловой системы (/dev/mapper/fedora_localhost--live-root) и в каком режиме её надлежит монтировать (ro - read only, только для чтения).

Итак, имеющаяся последовательность запуска становится подобна такой:

  1. BIOS -> POST -> BIOS

  2. Часть 1 GRUB -> Часть 2 GRUB -> Часть 3 GRUB

  3. Часть 3 GRUB -> считывает grub.cfg

  4. Часть 3 GRUB -> считывает /boot/loader/entries/*

  5. Выводит на печать все заголовки файлов, представленных в /boot/loader/entries

В качестве некого примера, рассмотрим некую установленной новую ОС или некое новое ядро. Это должно выработать свой собственный файл записи и поместить его в каталог /boot/loader/entries/ самого первого раздела. Таким образом, всякий раз когда Часть 3 GRUB ОС из самого первого первичного раздела считывает установленные записи, все прочие ОС будут иметь возможность для запуска. Такой файл записи может быть создан при помощи команды Fedora kernel-install.


#kernel-install add 5.3.7-301.fc31.x86_64 /lib/modules/5.3.7-301.fc31.x86_64/vmlinuz
		

Данная команда создаст надлежащую запись для kernel-5.3.7-301.fc31.x86_64 в /boot/loader/entries/, как это показано здесь:


# ls /boot/loader/entries/ -l
total 8
-rw-r--r--. 1 root root 329 Dec  9 10:18 2058a9f13f9e489dba29c477a8ae2493-0-rescue.conf
-rw-r--r--. 1 root root 249 Oct 22 01:04 2058a9f13f9e489dba29c477a8ae2493-5.3.7-301.fc31.x86_64.conf
		

Значение числа, связанного с файлом *.conf уникально. Такая BLS обладает своими преимуществами и недостатками.

Вот преимущества:

  • Всякая ОС получает равные возможности для запуска.

  • Это срабатывает вне зависимости от наличия встроенным ПО BIOS или UEFI.

  • В случае системы с BIOS, самая последняя установка Linux удалит Части 1 и 2 ранее установленных операционных систем, которые устарели с момента последней установки Linux, сделав свою собственную запись посредством команды kernel-install в более ранних ОС.

А вот недостатки:

  • BLS пока ещё не полностью реализована. Когда имеющаяся вторая ОС желает сделать свою запись в своей первой ОС, тогда /boot этой первой ОС должен иметь разделяемый доступ. Это не является тем вариантом, который представлен сейчас. Поэтому я рассматриваю это как некую половину реализации.

  • BLS усложняет без необходимости имеющуюся последовательность запуска, так как нам приходится обладать двумя файлами настройки для справок: grub.conf и <uniq_no><kernel_version>.conf из /boot/loader/entries/. BLS особенно усложняет жизнь в случае разрешения проблем "can’t boot".

  • За исключением дистрибутивов на основе Fedora ни один прочий пока ещй не адаптировал BLS, что выглядит как имеющее предпосылки стать обшим решением. Походе, что именно Fedora является наиболее заинтересованным в разработке этого проекта; следовательно, BLS была реализована в Fedora.

Распространённые проблемы начальной загрузки

На основании этих знаний давайте попытаемся разрешить некоторые из наиболее распространённых проблем "невозможности запуска", связанных с начальным загрузчиком.

Проблема 1 "Can’t Boot" (начальный загрузчик)

Проблема: после включения вашей системы она проваливается в приглашение на ввод GRUB, как это показано на Рисунке 3-11:

 

Рисунок 3-11


Приглашение на ввод GRUB 2

Это именно то, что вы наблюдаете на своём экране. Вы должны были сталкиваться с этой ошибкой хотя бы раз в своей жизни. Давайте попробуем разрешить её.

  1. Вы будете способны разрешить свою проблему только если вы знаете чем вызвана данная проблема. Прямо сейчас, однако, у нас нет никаких мыслей что это за чертовщина, так как мы только запустили свою систему и получили вот это.

  2. Наш экран имеет приглашение на ввод GRUB. Когда вы получили такое приглашение, это означает, что вы имеете возможность выполнять в нём команды. Помните, что это приглашение на ввод команд GRUB, что означает что вы можете получать доступ только к командам GRUB.

  3. Знакомясь с Рисунком 3-11, какая менно из трёх Частей GRUB какая именно из них предоставила нам это приглашение на ввод GRUB?

  4. Естественно, это должна быть Часть 3, потому как Часть 1 и Часть 2 слишком малы в размере, а потому они не могут обладать такой функциональностью. Итак, мы успешно достигли Части 3 GRUB и, что наиболее важно, не имеет значения будет ли эта система обладать UEFI или BIOS. Поскольку мы достигли Части 3, это означает, что мы покинули среду своего встроенного ПО. Это критически важные исходные сведения. Теперь мы можем сосредоточиться только на Части 3.

  5. В чём состоит основная цель Части 3 GRUB? Она считывает grub.cfg и из него получает местоположения своих ядра и initramfs. Если это система с включённой BLS, тогда она получает названия ядра и initramfs из каталогов /boot/loader/entries/. Например, допустим, наша система не осведомлена о BLS. Часть 3 тогда загружает vmlinuz и initramfs в оперативную память.

  6. Поскольку Часть 3 предоставила нам приглашение на ввод GRUB, но отказала в загрузке самой ОС, это означает, что либо файлы ядра или initramfs не представлены, либо наш файл grub.cfg не указывает правильно на местоположение этих файлов.

  7. Итак, в подобном случае мы можем попытаться запустить Fedora вручную. Вручную означает, что мы предоставим файлы ядра и initramfs с абсолютными путями при помощи приглашения на ввод GRUB. Вот как мы это делаем.

  8. linux это команда GRUB через которую нам требуется предоставить абсолютный путь к своему файлу ядра (vmlinuz). Как мы знаем, файл vmlinuz находится в /boot и GRUB следует своему собственному соглашению об именовании дисков. Таким образом, нашим путём к /boot будет жёсткий диск с номером 0 и раздел номер 1. Конечно, вы можете быть не осведомлены на каком HDD или в каком разделе хранится /boot. В этом случае вы можете получить справку у функциональности автозавершения GRUB. Вы можете нажать Tab дважды и GRUB выведет для вас доступные возможности. Давайте найдём номера HDD и раздела /boot. Обратите внимание на Рисунок 3-12.

     

    Рисунок 3-12


    Доступные разделы на жёстком диске с номером 0

    Самая первая табуляция после hd0 покажет нам что существует два раздела доступных в жёстком диске с номером 0. Второй раздел не читается из GRUB, а потому, естественно, второй раздел не способен быть /boot. Следовательно, мы выбираем раздел msdos1. Затем, как это отображено на Рисунке 3-13, мы начнём поиск необходимого файла vmlinuz там при помощи автозаполнения.

     

    Рисунок 3-13


    Файл vmlinuz

    Как вы можете видеть внутри HDD номер 0 и раздела номер 1 мы обнаружили два файла vmlinuz; один является аварийным ядром, а другой это обычный файл ядра Fedora 31. Как показано на Рисунке 3-14, мы выберем это обычное ядро и предоставим ему название его корневой файловой системы, затем вы сможете запустить эту систему с аварийным или live образом и проверить значение записей /etc/fstab. Мы обсудим аварийный режим в Главе 10.

     

    Рисунок 3-14


    Название корневой файловой системы и установленный флаг ro

    Значением абсолютного пути к файлу vmlinuz является (hd0,msdos1)/vmlinuz-5.3.7-301.fc31.x86_64. Вслед за ним следует параметр командной строки ro является , что является сокращением "read-only". После ro у нас имеется передаваемое нашей системой название файловой системы root, которым выступает /dev/mapper/fedora_localhost--live-root.

    
    grub> linux (hd0,msdos1)/vmlinuz-5.3.7-301.fc31.x86_64 ro root=/dev/mapper/fedora_localhost--live-root 
    		

    После успешного выполнения команды linux нам требуется передать название своей initramfs. Доступными для выполнения этого у нас имеются две команды: initrd и initrd16. Обратите внимание, пожалуйста на Рисунок 3-15.

    
    grub> initrd (hd0,msdos1)/initramfs-5.3.7-301.fc31.x86_64.img
    		
     

    Рисунок 3-15


    Команды linux, initrd и boot в действии

  9. В тот момент как вы исполните свою команду boot, как это отражено на Рисунке 3-16 и Рисунке 3-17, Часть 3 GRUB получит эти входные данные и загрузит /boot/vmlinuz-5.3.7-301.fc31.x86_64 (hd0,msdos1). Затем она загрузит /boot/initramfs-5.3.7-301.fc31.x86_64.img и передаст управление этому ядру. Данное ядро в конечном счёте смонтирует корень (/) файловой системы из /dev/mapper/fedora_locahost--live-root в свой каталог / и отобразит экран входа в систему.

     

    Рисунок 3-16


    Сообщения консоли при запуске

     

    Рисунок 3-17


    Экран входа в систему

  10. В случае Ubuntu 18 эти команды слегка иные. В Fedora 31 мы выдавали адрес своего раздела /boot напрямую самой команде linux, в то время как в Ubuntu нам придётся иметь для этого отдельную команду GRUB с названием set root.

    Как вы можете видеть на Рисунке 3-18, устанавливаемым названием корневой файловой системы в системе Ubuntu 18 является /dev/sda1. Это стандартный раздел, в отличии от устройства lvm Fedora 31.

     

    Рисунок 3-18


    Подход Ubuntu слегка отличается

  11. Как только мы предоставим надлежащие входные сведения GRUB 2, он приведёт нас к экрану входа в систему. Вы можете наблюдать этот экран входа в систему на Рисунке 3-19.

     

    Рисунок 3-19


    Представляемый Ubuntu экран входа в систему

  12. Возвращаясь обратно к нашей системе Fedora, поскольку сейчас она была загружена, мы имеем возможность восстановить свой файл grub.cfg воспользовавшись командой grub2-mkconfig, как это отображено на Рисунке 3-20.

     

    Рисунок 3-20


    Команда grub2-mkconfig

    В случае с Ubuntu мы можем выполнить grub-mkconfig. Взгляните на Рисунок 3-21.

     

    Рисунок 3-21


    Команда grub-mkconfig Ubuntu

    Однако если бы это была бы система UEFI, а вы бы желали восстановить grub.cfg, тогда, как это продемонстрировано на Рисунке 3-22, местоположением grub.cfg был бы ESP.

     

    Рисунок 3-22


    Команда grub2-mkconfig системы на основе UEFI

  13. После того как grub.cfg создан, нам требуется восстановить для Fedora соответствующие записи BLS.

    
    #kernel-install add 5.3.7-301.fc31.x86_64 /lib/modules/5.3.7-301.fc31.x86_64/vmlinuz
    		

    Данная команда сделает соответствующую запись для ядра kernel-5.3.7-301.fc31.x86_64 в /boot/loader/entries/.

    
    # ls /boot/loader/entries/ -l
    total 8
    -rw-r--r--. 1 root root 329 Dec  9 10:18 2058a9f13f9e489dba29c477a8ae2493-0-rescue.conf
    -rw-r--r--. 1 root root 249 Oct 22 01:04 2058a9f13f9e489dba29c477a8ae2493-5.3.7-301.fc31.x86_64.conf
    		
  14. Когда Fedora располагается в системе UEFI , тогда шаг BLS останется тем же самым.

  15. После перезагрузки Fedora способная гладко выполнить запуск и проблема "can’t boot" окажется исправленной.

Проблема 2 "Can’t Boot" (начальный загрузчик)

Проблема: После включения системы она проходит стадию встроенного ПО, однако после этого, как вы можете это видеть на Рисунке 3-23, на вашем экране ничего нет.

 

Рисунок 3-23


Чёрный экран

Решение для систем на основе BIOS

Вот шаги по решению этого:

  1. Так как стадия встроенного ПО BIOS была пройдена, это означает, что что- то пошло не так на уровне имеющегося начального загрузчика.

  2. Поскольку мы не получили ничего на своём экране, это означает, что Часть 1 или Часть 2 GRUB отсутствует, либо, в крайнем случае повреждена (512 байт + 31 кБ). Если бы была достигнута Часть 3, тогда мы по крайней мере получили бы приглашение на ввод GRUB. Итак, проблема была выделена и наш план действий состоит в замене Части 1 и Части 2 GRUB.

  3. Это можно осуществить при помощи команды grub2-install. Прежде всего загрузитесь с носителя live того же самого дистрибутива Linux или, когда это доступно, загрузитесь в аварийном режиме. Пояснения по самим образу live и аварийному режиму мы дадим в Главе 10.

Как вы можете видеть на Рисунке 3-24, grub2-install получает на входе значение названия устройства. Обратите, пожалуйста, внимание что это название устройства не должно быть номером раздела; вместо этого оно должно представлять название диска. Это обусловлено тем, что Часть 1 и Часть 2 GRUB должны быть установлены в самых первых 512 байтах + 31 кБ диска, а не внутри раздела. Вам необходимо заменить sda на название вашего диска.

 

Рисунок 3-24


Команда grub2-install

Помимо файлов Части 1 и Части 2 своего начального загрузчика, grub2-install восстановит или повторно установит свой каталог i386-pc, который обладает всеми модулями своего начального загрузчика GRUB 2. Мы можем перекрёстно проверить это, установив эти модули в некий индивидуальный каталог. Обратитесь, пожалуйста к Рисунку 3-25.

 

Рисунок 3-25


Установка grub2 во временном каталоге

Вы можете видеть, что все файлы GRUB 2 были восстановлены совместно с файлами модулей GRUB.


# ls temp/grub2/
      fonts  grubenv  i386-pc
# ls -l temp/grub2/i386-pc/ | wc -l
      279
		

После перезагрузки Fedora должен запуститься нормально и проблема "can’t boot" должна быть исправленной. Если GRUB выбросит вам своё приглашение на вод команд, тогда вам потребуется пройтись шагами, упомянутыми в Проблема 1 "Can’t Boot" (начальный загрузчик), поскольку grub2-install восстановил необходимые исполняемые файлы, однако не выработал повторно файл grub.cfg.

Но что если мы сталкиваемся с этой проблемой в системе на основе UEFI?

Решение для систем на основе UEFI

Вот наши шаги:

  1. Как вы уже могли догадаться, нам всего лишь придётся изменить название передаваемого для нашей команды grub2-install устройство, как это и показано на Рисунке 3-26. Названием этого устройства должен быть ESP.

     

    Рисунок 3-26


    Команда grub-install в некой системе на основе UEFI

Проблема 3 "Can’t Boot" (начальный загрузчик + ядро)

Проблема: Полное отсутствие /boot.

Решение для систем на основе BIOS

Вот наши шаги:

  1. Восстановление утраченного /boot (или же, по крайней мере, оно выходит за рамки данной книги).

  2. Загрузитесь в аварийном режиме или с носителя live и смонтируйте файловую систему корня нашей "can’t boot" системы. Пояснения по тому как работает аварийный режим мы дадим в Главе 10.

  3. Прежде всего создадим новый каталог /boot и установим для него надлежащие права доступа.

    • #mkdir /boot

    • #chmod 555 /boot

    • #chown root:root /boot

    • Если предполагается, что /boot является обособленным разделом, тогда смонтируйте его в верном разделе.

  4. Как мы знаем, именно в /boot хранятся необходимые файлы нашего начального загрузчика, ядра и initramfs. Поскольку /boot утрачен, нам потребуется создать все эти файлы для него.

    • #dnf reinstall kernel

      • Это верно для системы на основе Fedora. Когда это будет система на основе Debian, тогда вы можете воспользоваться командой apt-get и сможете переустановить своё ядро.

      • Это установит необходимый файл vmlinuz и также повторно сгенерирует для него файл initramfs.

  5. Теперь нам требуется установить GRUB.

    • #grub2-install /dev/<disk_name>

      • В нашем случае это команда #grub2-install /dev/sda.

    • Это восстановит Часть 1, Часть 2 GRUB, а также его каталог i386-pc из каталога /boot/grub2.

    • Для восстановления Части 3 GRUB и для получения некоторых предоставляемых GRUB инструментов нам потребуется в системе на основе Fedora установить два пакета.

      • #dnf reinstall grub2 grub2-tools

      • Как и предполагают их названия, grub2 предоставит Часть 3 GRUB, а grub2-tools снабдит нас некоторыми инструментами, такими как grub2-install.

    • Теперь настало время повторно выработать файл настроек GRUB.

      • #grub2-mkconfig -o /boot/grub2/grub.cfg

    • Наконец, исправляем свою BLS.

      • #kernel-install add 5.3.7-301.fc31.x86_64 /lib/modules/5.3.7-301.fc31.x86_64/vmlinuz

Решение для систем на основе UEFI

Наши шаги следующие:

  • /boot/ и /boot/efi/ это отдельные точки монтирования.

    • # mkdir /boot

    • # chmod 555 /boot

    • # chown root:root /boot

    • # yum reinstall kernel

  • Теперь нам требуется создать некий раздел ESP и, как нам известно, он обязан быть разделом VFAT. Затем мы назначим ему тип раздела ESP.

    • #mkdir /boot/efi

    • #mount /dev/sda2 /boot/efi

      • В нашем случае, тот раздел, который я создал под ESP, это sda2.

    • #grub2-install --efi-directory=/boot/efi

      • Это установит в ESP файл grubx64.efi.

    • Остальные необходимые нам файлы предоставляются пакетами grub2-efi, shim и grub2-tools.

      • #yum reinstall grub2-efi shim grub2-tools

    • Создадим повторно файлы настроек.

      • #grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg

      • #kernel-install add 5.3.7-301.fc31.x86_64 /lib/modules/5.3.7-301.fc31.x86_64/vmlinuz

После перезапуска нашей системы, она способно запускаться без каких бы то ни было проблем.

Теперь настало время пролить побольше света на среду Безопасного запуска UEFI.

Функциональная возможность безопасного запуска UEFI

Безопасный запуск (Secure Boot) это великолепная функциональная возможность UEFI. Он гарантирует что никакой не обладающий доверием исполняемый файл не будет выполнен при запуска До сих пор мы наблюдали следующее:

  • Цифровая подпись это некая уникальная строка.

    • Цифровая подпись всякого файла будет вырабатываться из некого частного (private) ключа.

    • Та же самая цифровая подпись может быть восстановлена по общедоступному (public) ключу.

    • В случае отсутствия изменений в этом файле эти цифровые подписи обязаны совпадать.

  • Microsoft изготовил свою собственную пару ключей (частный и общедоступный ключи).

  • Microsoft цифровым образом подписывает относящиеся к своему начальному загрузчику (BCD) файлы при помощи собственного частного ключа.

  • Общедоступный ключ Microsoft представлен внутри UEFI.

  • При запуске UEFI восстанавливает значение цифровой подписи соответствующего начального загрузчика при помощи имеющегося у него общедоступного ключа {Microsoft}. Если значение цифровой подписи не совпадает, тогда UEFI отклоняет выполнение файлов .efi.

  • Для применения этой функциональности в соответствующей средеLinux был создан некий новый начальный загрузчик с названием shim (Прокладка) и он был подписан частным ключом Microsoft с тем, чтобы UEFI допускал выполнение shim.efi.

  • Задание shim.efi состоит в вызове реального файла GRUB, которым выступает grubx64.efi.

Однако Безопасный запуск не завершается на этом. Поскольку имеется вероятность, что grubx64.efi может быть скомпрометирован сам по себе, или при том факте что может оказаться скомпрометированным всякий запускаемый после соответствующего начального загрузчика код, недостаточно безопасности имеющейся среды запуска лишь на уровне начального запуска; следовательно, в наши дни функциональность Безопасного запуска делает безопасной всю процедуру запуска Linux. Вот как это работает:

  1. Fedora подготовит свою собственную пару ключей и подпишет свои файлы GRUB частным ключом Fedora.

  2. Необходимый общедоступный ключ Fedora будет оставаться внутри основного файла shim.efi.

  3. По мере продолжения этой последовательности запуска цифровая подпись GRUB будет восстанавливаться с применением необходимого общедоступного ключа, находящегося внутри shim.efi.

  4. При соответствии подписи grubx64.efi и прочие файлы начального загрузчика будут разрешены к исполнению из UEFI.

  5. Окончательное задание GRUB состоит в загрузке необходимого ядра (/boot/vmlinuz).

  6. Этот файл vmlinuz также может оказаться скомпрометированным, поэтому, во избежание данной ситуации, само ядро также будет подписано тем же самым частным ключом, который применялся для подписи GRUB.

  7. Цифровая подпись vmlinuz будет восстановлена при помощи находящегося внутри shim.efi соответствующего общедоступного ключа.

  8. Когда полученная цифровая подпись удовлетворяет соответствию, подписанное ядро получает контроль над последовательностью запуска.

  9. Однако это ядро пользуется большим числом модулей/ драйверов, который в конечном счёте вставляются вовнутрь самого ядра. Поэтому такие модули являются теми исполняемыми файлами, который снова могут оказаться скомпрометированными, а следовательно, так как они превратятся в часть ядра/ vmlinuz, в конце концов и само по себе ядро будет скомпрометировано.

  10. Итак, наше ядро в качестве пакета, будет подготовлено собственной парой ключей. Все имеющиеся модули будут подписаны этой парой частных ключей ядра, а соответствующим общедоступным ключом будет снабжён сам пакет этого ядра. Значение частного ключа пакета ядра позднее будет разрушено.

  11. На момент запуска при вставке соответствующих модулей в имеющееся ядро значение цифровой подписи этого модуля будет восстановлено с применением надлежащего общедоступного ключа, которое пребывает в самом ядре.

  12. Следуя перечисленным шагам функциональность Безопасного запуска гарантирует выполнение лишь исполняемых модулей от доверенных сторон.

Показанная на Рисунке 3-27 блок- схема ещё больше упростит эту процедуру запуска.

 

Рисунок 3-27


Процедура безопасного запуска

Проект множественной загрузки 100 ОС

Один из моих студентов задал мне вопрос: сколько операционных систем мы способны установить в одной системе и множественно загружать их из одного начального загрузчика? Я не знаю точного ответа, но я попытался найти его. Я решил, что я воспользуюсь для запуска всех устанавливаемых мною операционных систем начальным загрузчиком GRUB 2. Я устанавливал и множественно запускал эти операционные системы почти два года до настоящего момента. Я установил до сих пор 106 операционных систем. И это наша третья система, которую я назвал Jarvis. Вот аппаратные и программные подробности Jarvis:

  • Встроенное ПО UEFI.

  • Подключены два диска (sda и sdb).

  • Методом запуска выступает UEFI.

  • sda отформатирован с таблицей разделов MS-DOS.

  • sdb отформатирован с таблицей разделов GPT.

  • Все имеющиеся операционные системы идентифицируются и запускаются начальным загрузчиком GRUB 2.

Все установленные на моём диске sda операционные системы устанавливались настройкой метода запуска в UEFI и им обладают все новые операционные системы. Те операционные системы, которые находятся на sdb были установлены при настройке метода запуска встроенного ПО в совместимый режим (legacy). sdb размещает операционные системы старого поколения, или, по крайней мере, те операционные системы, которые на обладают поддержкой UEFI. Вот подробности:

Таблица 3-3. Операционные системы sda
Раздел Операционная система Файловая система Размер

sda-1

ESP (EFI System partition)

Fat32

20 ГБ

sda-2

MSR (Microsoft recovery)

MSR

16 МБ

sda-3

Windows 10

NTFS

9.7 ГБ

sda-4

Swap

Swap

2.01 ГБ

sda-5

openSUSE Linux 13.2

EXT4

10 ГБ

sda-6

Mint Linux 17.2

EXT4

10 ГБ

sda-7

Oracle OpenSolaris 11.2

ZFS

10 ГБ

sda-8

Sabayon Linux 15.06

EXT4

10 ГБ

sda-9

немного случайного свободного пространства

N/A

8.4 ГБ

sda-10

Kali Linux 2.0

EXT4

10 ГБ

sda-11

Arch Linux 2015-8.1

EXT4

10 ГБ

sda-12

Debian Linux 8.1

EXT4

10 ГБ

sda-13

Semplice Linux 7.0.1

EXT4

10 ГБ

sda-14

Slackware 14.1 Linux

EXT4

10 ГБ

sda-15

Openmandriva 2014.2

EXT4

10 ГБ

sda-16

Mate Ubuntu Linux15.04

EXT4

10 ГБ

sda-17

Steam OS beta

EXT4

10 ГБ

sda-18

Manjaro Linux 0.8.13.1

EXT4

10 ГБ

sda-19

Netrunner Linux 16

EXT4

10 ГБ

sda-20

Windows 8

NTFS

10 ГБ

sda-21

Korora Linux 22

EXT4

10 ГБ

sda-22

KaoS Linux 2015.08

EXT4

10 ГБ

sda-23

Lubuntu Linux 15.04

EXT4

10 ГБ

sda-24

Sonar Linux 2015.2

EXT4

10 ГБ

sda-25

Antergos Linux 2015.08.18

EXT4

10 ГБ

sda-26

Mythbuntu Linux 14.04.2

EXT4

10 ГБ

sda-27

Rosa Linux fresh r5

EXT4

10 ГБ

sda-28

SparkyLinux 4.0

EXT4

10 ГБ

sda-29

Vinux Linux 4.0

EXT4

10 ГБ

sda-30

Xubuntu Linux 14.04.3

EXT4

10 ГБ

sda-31

Ubuntu Studio 14.04.3

EXT4

10 ГБ

sda-32

Suse Enterprise 12

EXT4

10 ГБ

sda-33

Ubuntu Linux 14.04

EXT4

10 ГБ

sda-34

Uubuntu Linux 15.04

EXT4

10 ГБ

sda-35

Scientific Linux 7

EXT4

10 ГБ

sda-36

Xubuntu Linux 14.04.3

EXT4

10 ГБ

sda-37

CentoS Linux 7

EXT4

10 ГБ

sda-38

Ubuntu Server 14 Linux

EXT4

10 ГБ

sda-39

Fedora 21 Linux

EXT4

10 ГБ

sda-40

Fedora 22 Linux

EXT4

10 ГБ

sda-41

BlackArch 2015.07.31

EXT4

10 ГБ

sda-42

Gentoo Linux multilib 20140826

EXT4

10 ГБ

sda-43

Calculate Linux 14.16.2

EXT4

10 ГБ

sda-44

Fedora 20 Linux

EXT4

10 ГБ

sda-45

Fedora 23 Linux

EXT4

10 ГБ

sda-46

Manjaro Linux 15-0.9

EXT4

10 ГБ

sda-47

Ubuntu Linux 16.04

EXT4

10 ГБ

sda-48

chapeau Linux 23

EXT4

10 ГБ

sda-49

Arquetype Linux 22

EXT4

10 ГБ

sda-50

Fx64 Linux 22

EXT4

10 ГБ

sda-51

Viperr Linux 7

EXT4

10 ГБ

sda-52

Hanthana Linux 21

EXT4

10 ГБ

sda-53

Qubes r3.1 Linux

EXT4

10 ГБ

sda-54

Fedora 24

EXT4

10 ГБ

sda-55

Fedora 23

EXT4

10 ГБ

sda-56

sabayon-16

EXT4

10 ГБ

sda-57

Korora-24

EXT4

10 ГБ

sda-58

Sonar 16 Linux

EXT4

10 ГБ

sda-59

Viper 9 Linux

EXT4

10 ГБ

sda-60

Arquetype Linux 23

EXT4

10 ГБ

sda-61

Manjaro Linux 16

EXT4

10 ГБ

sda-62

Manjaro Linux Gaming 16

EXT4

10 ГБ

sda-63

Calculate Linux 15

EXT4

10 ГБ

Итак, общее число установок ОС UEFI на диске sda составило 59, так как четыре раздела были зарезервированы под обслуживание ESP- и MSR- подобных разделов. Далее следуют подробности установок диска sdb:

Таблица 3-4. Операционные системы sdb
Раздел Операционная система Файловая система Размер

sdb-1

PCBSD 10.1.2

ZFS

10 ГБ

sdb-2

Magia 2 Linux

EXT4

10 МБ

sdb-3

Magia 3 Linux

EXT4

10 ГБ

sdb-4

Extended/secondary

N/A

примерно 970 ГБ

sdb-5

Q4OS Linux 1.2.8

EXT4

10 ГБ

sdb-6

Qubes R2 Linux

EXT4

10 ГБ

sdb-7

Pardus Linux 2013

EXT4

10 ГБ

sdb-8

GoboLinux 015

EXT4

10 ГБ

sdb-9

Crux Linux 3.1

EXT4

10 ГБ

sdb-10

Point Linux 3.0

EXT4

10 ГБ

sdb-11

Extix Linux 15.3

EXT4

10 ГБ

sdb-12

Bodhi Linux 3.0

EXT4

10 ГБ

sdb-13

Debian Linux 7.0

EXT4

10 ГБ

sdb-14

Debian Linux 6.0

EXT4

10 ГБ

sdb-15

BOSS Linux 6.1

EXT4

10 ГБ

sdb-16

CrunchBang rc1 Linux

EXT4

10 ГБ

sdb-17

Handy Linux 2.1

EXT4

10 ГБ

sdb-18

Lite Linux 2.4

EXT4

10 ГБ

sdb-19

WattOS Linux r9

EXT4

10 ГБ

sdb-20

PinGuy OS 14.04.3 Linux

EXT4

10 ГБ

sdb-21

SuperX 3.0 Linux

EXT4

10 ГБ

sdb-22

JuLinux 10X Rev 3.1 Linux

EXT4

10 ГБ

sdb-23

Black Lab Linux 2015.7

EXT4

10 ГБ

sdb-24

Hamara Linux 1.0.3

EXT4

10 ГБ

sdb-25

Peppermint LInux 20150518

EXT4

10 ГБ

sdb-26

Ubuntu 13.10 Linux

EXT4

10 ГБ

sdb-27

LinuxMint 13 mate

EXT4

10 ГБ

sdb-28

LinuxMint 14.1 cinnamon

EXT4

10 ГБ

sdb-29

LinuxMint 15 xfce

EXT4

10 ГБ

sdb-30

LinuxMint 16 Kde

EXT4

10 ГБ

sdb-31

Peppermint 4 20131113

EXT4

10 ГБ

sdb-32

Peppermint 5 20140623

EXT4

10 ГБ

sdb-33

Fedora 12

EXT4

10 ГБ

sdb-34

Trisquel 7 Linux

EXT4

10 ГБ

sdb-35

Oracle Linux 7.1

EXT4

10 ГБ

sdb-36

Fedora 14 Linux

EXT4

10 ГБ

sdb-37

Fedora 15 Linux

EXT4

10 ГБ

sdb-38

Fedora 17 Linux

EXT4

10 ГБ

sdb-39

Fedora 19 Linux

EXT4

10 ГБ

sdb-40

RHEL 6.5 Linux

EXT4

10 ГБ

sdb-41

SolydX 201506

EXT4

10 ГБ

sdb-42

Oracle Linux 6.7

EXT4

10 ГБ

sdb-43

OpenSuse 11.3

EXT4

10 ГБ

sdb-44

LMDE (Linux Mint 2 Debian edition)

EXT4

10 ГБ

sdb-45

Centrych Linux 12.04

EXT4

10 ГБ

sdb-46

Elementary OS 2013

EXT4

10 ГБ

sdb-47

Elementary OS 2015

EXT4

10 ГБ

sdb-48

Sabayon 13.08 Linux

EXT4

10 ГБ

sdb-49

Deepin 2013 Linux

EXT4

10 ГБ

sdb-50

Deepin 15.1 Linux

EXT4

10 ГБ

Общее число запускаемых способом BIOS операционных систем на диске sdb равно 50 -2 = 48.

Два раздела зарезервированы под подкачку и соответствующий расширенный раздел.

Итак, общее число установок в системе Jarvis составляет 106 и, как вы можете видеть на Рисунке 3-28, все эти ОС допускают множественную загрузку при помощи установленного начального загрузчика GRUB 2. С этим проектом я осознал, что этому нет конца. Сочетание GRUB 2 и UEFI способны обрабатывать число n операционных систем.

 

Рисунок 3-28


106 перечисленных GRUB 2 операционных систем

Как я управлял установкой такого большого числа операционных систем? Элементарно. После установки каждой новой операционной системы я запускал команду grub-mkconfig, которая обнаруживала все имеющиеся операционные системы на всех подключённых дисках.


# time grub-mkconfig -o multiboot_grub.cfg
		

Приведённая выше команда применялась после установки Ubuntu 18, которая оказалась 106 ОС в этом списке.

Как вы можете видеть на Рисунке 3-29, после установки 106-й ОС grub-mkconfig потребовался почти час на завершение и полученный в результате файл настроек GRUB обладал 5 500 строк.

 

Рисунок 3-29


Время, требуемое команде grub-mkconfig

Болванка небольшого начального загрузчика

Мы знаем что наш BIOS выполняет безусловный переход в самые первые 512 байт и вызывает начальный загрузчик GRUB 2. Чтобы разобраться как именно BIOS вызывает наш начальный загрузчик мы сделаем свой собственный начальный загрузчик. Наш начальный загрузчик будет совсем крошечным по сравнению с GRUB 2. Наш начальный загрузчик будет всего лишь ! н нашем экране. Однако при помощи этого примера мы сможем понять как наш BIOS выполняет безусловный переход к таким начальным загрузчикам как GRUB2, как это показывается ниже:


#cat boot.nasm
    ;
    ; Замечание: данный пример написан в синтаксисе Intel Assembly
    ;
     [BITS 16]
     [ORG 0x7c00]
    boot:
        mov al, '!'       <<-- Символ для прерывания
        mov ah, 0x0e      <<-- Отобразить символ
        mov bh, 0x00      <<-- Настройка видео режима
        mov bl, 0x07      <<-- Очистка/прокрутка экранавниз
        int 0x10          <<--- прерывание 10 BIOS который получает входные данные из al, ah, bh, bl
        jmp $
        times 510-($-$$) db 0      <<--- Из 512 байт первые 510 байт заполнены нулями.
                                   В реальном мире они будут заполнены начальной самораскруткой grub.
        db 0x55           <<-- &
        db 0xaa           <<-- | сообщает BIOS что это устройство активно/с подписью fdisk/флагом запуска.
     #nasm -f bin boot.nasm && qemu-system-x86_64 boot
		

Это сделает некий загрузочный диск запуска (образ диска) из файла boot.nasm и он станет некими входными данными для qemu, который и выполнит его. Как вы можете видеть на Рисунке 3-30, вы обнаружите напечатанным на экране !.

 

Рисунок 3-30


Наш небольшой крошечный начальный загрузчик

В целом наша машина qemu рассматривает boot в качестве некого диска и всякий раз когда эта машина qemu завершает свою стадию BIOS, этот BIOS проваливается в самые первые 512 байт нашего диска boot. Здесь мы обнаруживаем, что самые первые 510 байт заполнены 0, а в последних 2 байтах мы имеем ! (наш начальный загрузчик) и он будет выведен на печать на нашем экране.

На данный момент мы получили хороший обзор GRUB; теперь мы намерены пройти в своём следующем разделе дальше, где мы обсудим что на самом деле происходит внутри GRUB 2/

GRUB 2 на нижнем уровне

На момент написания этой книги самым последним доступным исходным кодом GRUB был GRUB 2.04, которым я и воспользовался здесь. Исполняемый файл начальной самораскрутки (когда наша система основана на BIOS) из самых первых 440 байт именуется boot.img, который доступен в /usr/lib/grub/i386-pc/boot.img.


# ls -lh /usr/lib/grub/i386-pc/boot.img
-rw-r--r--. 1 root root 512 Mar 28  2019 /usr/lib/grub/i386-pc/boot.img
# file  /usr/lib/grub/i386-pc/boot.img
/usr/lib/grub/i386-pc/boot.img: DOS/MBR boot sector
		

Этот файл boot.img создан из того исходного кода, который записан в файле /GRUB 2.04/grub-core/boot/i386/pc/boot.S.

Ниже приводится фрагмент его кода:


<snip>
1 /* -*-Asm-*- */
  2 /*
  3  *  GRUB  --  GRand Unified Bootloader
  4  *  Copyright (C) 1999,2000,2001,2002,2005,2006,2007,2008,2009  Free Software Foundation, Inc.
  5  *
  6  *  GRUB is free software: you can redistribute it and/or modify
  7  *  it under the terms of the GNU General Public License as published by
  8  *  the Free Software Foundation, either version 3 of the License, or
  9  *  (at your option) any later version.
 10  *
 11  *  GRUB is distributed in the hope that it will be useful,
 12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14  *  GNU General Public License for more details.
 15  *
 16  *  You should have received a copy of the GNU General Public License
 17  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
 18  */
 19
 20 #include <grub/symbol.h>
 21 #include <grub/machine/boot.h>
 22
 23 /*
 24  *  defines for the code go here
 25  */
 26
 27         /* Print message string */
 28 #define MSG(x)  movw $x, %si; call LOCAL(message)
 29 #define ERR(x)  movw $x, %si; jmp LOCAL(error_message)
 30
 31         .macro floppy
 32 part_start:
 33
 34 LOCAL(probe_values):
 35         .byte   36, 18, 15, 9, 0
 36
 37 LOCAL(floppy_probe):
 38         pushw   %dx
 39 /*
 40  *  Perform floppy probe.
 41  */
 42 #ifdef __APPLE__
 43         LOCAL(probe_values_minus_one) = LOCAL(probe_values) - 1
 44         movw    MACRO_DOLLAR(LOCAL(probe_values_minus_one)), %si
 45 #else
 46         movw    MACRO_DOLLAR(LOCAL(probe_values)) - 1, %si
 47 #endif
 48
 49 LOCAL(probe_loop):
 50         /* reset floppy controller INT 13h AH=0 */
 51         xorw    %ax, %ax
 52         int     MACRO_DOLLAR(0x13)
 </snip>
 	   

Вы можете рассматривать boot.img как некую первую стадию или Часть 1 GRUB. Этот файл boot.img передаёт управление в diskboot.img, который выступает Частью 2 GRUB.


# ls -lh /usr/lib/grub/i386-pc/diskboot.img
-rw-r--r--. 1 root root 512 Mar 28  2019 /usr/lib/grub/i386-pc/diskboot.img
# file /usr/lib/grub/i386-pc/diskboot.img
/usr/lib/grub/i386-pc/diskboot.img: data
		

Этот файл diskboot.img сделан из исходного кода grub-2.04/grub-core/boot/i386/pc/diskboot.S. Ниже приводится некий фрагмент его кода:


<snip>
1 /*
  2  *  GRUB  --  GRand Unified Bootloader
  3  * Copyright (C) 1999,2000,2001,2002,2006,2007,2009,2010 Free Software Foundation, Inc.
  4  *
  5  *  GRUB is free software: you can redistribute it and/or modify
  6  *  it under the terms of the GNU General Public License as published by
  7  *  the Free Software Foundation, either version 3 of the License, or
  8  *  (at your option) any later version.
  9  *
 10  *  GRUB is distributed in the hope that it will be useful,
 11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13  *  GNU General Public License for more details.
 14  *
 15  *  You should have received a copy of the GNU General Public License
 16  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
 17  */
 18
 19 #include <grub/symbol.h>
 20 #include <grub/machine/boot.h>
 21
 22 /*
 23  *  defines for the code go here
 24  */
 25
 26 #define MSG(x)  movw $x, %si; call LOCAL(message)
 27
 28         .file   "diskboot.S"
 29
 30         .text
 31
 32         /* Tell GAS to generate 16-bit instructions so that this code works
 33            in real mode. */
 34         .code16
 35
 36         .globl  start, _start
 37 start:
 38 _start:
 39         /*
 40          * _start is loaded at 0x8000 and is jumped to with
 41          * CS:IP 0:0x8000 in kernel.
 42          */
 </snip>
 	   

Наш файл diskboot.img загружает затем реальную часть ядра GRUB 2, которая составляет Часть 3 GRUB. Вы также можете рассматривать Часть 3 GRUB является неким ядром всего начального загрузчика. На этом этапе GRUB 2 будет способен выполнять чтение из своей файловой системы.


# ls /boot/grub2/i386-pc/core.img -lh
-rw-r--r--. 1 root root 30K Dec  9 10:18 /boot/grub2/i386-pc/core.img
		

В /GRUB 2.00/grub-core/kern/main.c GRUB 2 настраивает значение имени корневого устройства, считывает grub.cfg и его конец показывает имеющийся перечень операционных систем для выбора.

Я надеюсь что теперь вы разобрались как работает GRUB 2. Ниже приводится быстрое краткое изложение того что мы обсуждали на данный момент:

  1. Начальный загрузчик это самый первый код, запускаемый после встроенного ПО.

  2. Начальный загрузчик/ GRUB копирует своё ядро в оперативную память.

  3. Этот начальный загрузчик загружает в оперативную память соответствующий образ initramfs и передаёт своему ядру указатель на него.

  4. Начальный загрузчик отдаёт управление своему ядру.