Установка GRUB и настройка загрузочных записей

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

После обзора и тестов материнской платы Asus Z9PE-D16/2L, которая стояла в моем домашнем сервере, этот самый сервер перестал загружаться, точнее BIOS в режиме UEFI не видел диски c EFI-разделом с загрузчиком GRUB:

А если включить CSM и режим загрузки дисков UEFI & Legacy (или просто Legacy) то диски появляются в меню загрузки, но загрузится с них не получается:

В чем проблема?

Давайте отойдем значительно назад, во время когда я написал инструкцию как установить Proxmox в RAID через Debian. Так вот, во время переустановки, Debian почему-то отказался устанавливать GRUB в EFI-раздел и мне пришлось самостоятельно устанавливать GRUB на каждый диск (по-русски здесь), и что самое важное, я вручную установил порядок загрузки дисков при помощи efibootmgr (по-русски можно здесь):

sudo efibootmgr -c -d /dev/sdb -p 1 -L "Linux" -l '\EFI\debian\grubx64.efi'

Мы тогда с ребятами на стриме разбирались в чем дело, но не разобрались, позже я доделал эту историю.

А во время тестов я вынул батарейку, питающую NVRAM (энергозависимая оперативная память BIOS) системной прошивки, и все настройки сбросились.

И здесь я допустил 2 ошибки:

Давайте разбираться как быть в этой ситуации.

Загрузка с LiveCD

Чтобы исправить ситуацию нужно загрузиться с LiveCD. Так как у меня Debian, точнее Proxmox поверх Debian, то я скачал Debian Live Standard редакцию, то есть без рабочих столов, только консоль.

Загружаемся и переключамся на root:

sudo su -

Просмотр дисков и содержимого

Выведем список дисков при помощи lsblk:

$ sudo lsblk -o NAME,SIZE,TYPE,FSTYPE,PARTLABEL,PARTUUID,PARTTYPE
NAME          SIZE TYPE  FSTYPE            PARTLABEL PARTUUID                             PARTTYPE
sda         238,5G disk                                                                   
├─sda1        476M part  vfat              ESP       b90ff200-1234-41f6-acd3-43d0860eb321 c12a7328-f81f-11d2-ba4b-00a0c93ec93b
└─sda2        238G part  linux_raid_member           ce4b0a0c-1e4f-4593-9726-55694e8583df a19d880f-05fc-4d3b-a006-743f0f84911e
  └─md1     237,9G raid1 ext4                                                             
sdb         238,5G disk                                                                   
├─sdb1        476M part  vfat              ESP       0956121c-3228-4f89-8fce-7d7de9a1fc1f c12a7328-f81f-11d2-ba4b-00a0c93ec93b
└─sdb2        238G part  linux_raid_member           cc9f8e52-5d88-44d8-82eb-0466a44f395a a19d880f-05fc-4d3b-a006-743f0f84911e
  └─md1     237,9G raid1 ext4                                                             
sdc             0B disk                                                                   
sdd             0B disk                                                                   
sr0          1024M rom                                                                    
nvme0n1     953,9G disk                                                                   
└─nvme0n1p1 953,9G part  ext4                        22af38df-009c-495e-a24b-4a61ee6093c8 0fc63daf-8483-4772-8e79-3d69d8477de4
nvme1n1     953,9G disk                                                                   
└─nvme1n1p1 953,9G part  ext4                        5799b3e6-1022-4fa9-90ec-702ff04646a8 0fc63daf-8483-4772-8e79-3d69d8477de4

Здесь видно, что нам нужны диски sda и sdb. Попробуем просмотреть по ним информацию через parted:

$ sudo parted /dev/sdb print
...
Partition Table: gpt

Number  Start   End    Size   File system  Name  Flags
 1      1049kB  500MB  499MB  fat32        ESP   boot, esp
 2      500MB   256GB  256GB                     raid

Или через fdisk:

$ sudo fdisk -l /dev/sda /dev/sdb
Disk /dev/sda: 238,47 GiB, 256060514304 bytes, 500118192 sectors
...
Disklabel type: gpt
...

Device      Start       End   Sectors  Size Type
/dev/sda1    2000    976895    974896  476M EFI System
/dev/sda2  976896 500117503 499140608  238G Linux RAID


Disk /dev/sdb: 238,47 GiB, 256060514304 bytes, 500118192 sectors
...
Disklabel type: gpt
...

Device      Start       End   Sectors  Size Type
/dev/sdb1    2048    976895    974848  476M EFI System
/dev/sdb2  976896 500117503 499140608  238G Linux RAID

Видно, что оба диска размечены как GPT, и на каждом есть EFI-раздел (примерно такая схема, но без swap):

Если примонтируем любой из EFI-разделов и посмотрим что внутри, то увидим путь /mnt/EFI/debian:

$ sudo /dev/sda1 /mnt
$ ls -la /mnt/EFI/
drwx------ 5 root root 4096 июн  4 21:15 .
drwx------ 3 root root 4096 янв  1  1970 ..
drwx------ 2 root root 4096 окт 18  2024 debian

Запомним и идем дальше.

Как устроена загрузка в UEFI?

В документации Debian по UEFI сказано, что UEFI (она же системная прошивка) по умолчанию пытается загрузить загрузчик операционной системы на EFI-разделе по пути /EFI/Boot/BOOTX64.EFI, это некий fallback. А вендоры (поставщики) операционных систем должны создавать загрузчики по пути /EFI//*.efi и самостоятельно заносить информацию о загрузке системы в NVRAM.

Когда мы записываем загрузочную флешку, то на ней создается EFI-раздел куда копируется загрузчик по дефолтному пути /EFI/Boot/BOOTX64.EFI, чтобы любая UEFI-прошивка ее смогла увидеть без проблем.

А теперь представим ситуацию, что у нас несколько систем, и каждый вендор сделал все по документации, сделал свою директорию с загрузчиком на EFI-разделе, добавил запись в NVRAM, которая питается от батарейки на материнской плате. И внезапно батарейка садится и все данные в памяти NVRAM исчезают. Теперь мы не сможем загрузить ни одну операционную систему.

Но судя по все той же документации Debian про UEFI, можно найти информацию, что не все вендоры операционных систем придерживаются спецификации UEFI и создают свои загрузчики по дефолтному пути /EFI/Boot/BOOTX64.EFI.

Например, вот мой ноутбук купленный в 2022 году, изначально на нем стояла Windows, а позже я поставил Ubuntu 22.04 и она разместила свой загрузчик по дефолтному пути:

Теперь мы знаем как устроена загрузка операционной системы и стало понятно, что теперь нужно либо разместить загрузчик по дефолтному пути /EFI/Boot/BOOTX64.EFI либо вручную добавить записи с порядком загрузки операционных систем в NVRAM.

На своем домашнем сервере я сделал первое, так как у меня только одна ОС, но для полноты мы рассмотрим оба варианта.

Установка GRUB

Для установки загрузчика GRUB есть инструкция в документации Debian, а мы попробуем это повторить, если вы еще не загрузились в LiveCD, то пора это сделать. А потом эти команды::

# может потребоваться установка пакета grub-efi-amd64
# sudo apt update
# sudo apt install grub-efi-amd64

# монтируем корень ОС в /mnt
# у меня корень в рейде, он все-равно смонтируется
sudo mount /dev/md1 /mnt

# создаем директории загрузчиков для обоих дисков
sudo mkdir /mnt/boot/efi/sda1 /mnt/boot/efi/sdb1

# монтируем EFI-разделы в созданные директории
sudo mount /dev/sda1 /mnt/boot/efi/sda1
sudo mount /dev/sdb1 /mnt/boot/efi/sdb1

# монтируем устройства
sudo mount --bind /dev /mnt/dev
sudo mount --bind /proc /mnt/proc
sudo mount --bind /sys /mnt/sys

# меняем корень операционной системы на только что сформированную файловую систему в /mnt
sudo chroot /mnt

# устанавливаем GRUB с флагом --removable это установить его по дефолтному пути на диске
grub-install --target=x86_64-efi --efi-directory=/boot/efi/sda1 --bootloader-id=GRUB_A --removable
grub-install --target=x86_64-efi --efi-directory=/boot/efi/sdb1 --bootloader-id=GRUB_B --removable

# обновляем GRUB
update-grub

# выходим из корня собранной файловой системы, т.е. возвращаемся назад
exit

# отмонтируем устройства
sudo umount /mnt/sys
sudo umount /mnt/proc
sudo umount /mnt/dev

# отмонтируем EFI-разделы
sudo umount /mnt/boot/efi/sdb1
sudo umount /mnt/boot/efi/sda1

# отмонтируем корень файловой системы на рейде
sudo umount /mnt

# перезагрузка
reboot

Теперь в BIOS будут доступны диски для загрузки ОС.

Установка записей загрузки вручную

Раз уж зашла речь про загрузку, то давайте быстренько разберем как при помощи efibootmgr настроить загрузку с дисков:

Так мы можем узнать текущий список загрузки:

$ sudo efibootmgr -v
BootCurrent: 0002
Timeout: 1 seconds
BootOrder: 0001,0002,0003
Boot0001* UEFI: VendorCoProductCode 2.00        PciRoot(0x0)/Pci(0x1a,0x0)/USB(0,0)/USB(1,0)/HD(1,MBR,0x3d78d776,0x19fc,0x2540)AMBO
Boot0002* UEFI OS       HD(1,GPT,b90ff200-1234-41f6-acd3-43d0860eb321,0x7d0,0xee030)/File(\EFI\BOOT\BOOTX64.EFI)
Boot0003* UEFI OS       HD(1,GPT,0956121c-3228-4f89-8fce-7d7de9a1fc1f,0x800,0xee000)/File(\EFI\BOOT\BOOTX64.EFI)

Здесь в списке их 3, первый это загрузочная флешка, а остальные 2 это диски.

А вот так можно добавить новую запись:

# -c создать
# -d диск
# -p номер партиции
# -L метка
# -l путь до загрузчика на диске
sudo efibootmgr -c -d /dev/sdb -p 1 -L debian -l '\EFI\debian\grubx64.efi'

Больше деталей в справке:

sudo efibootmgr --help

За пару вечеров я вспомнил моменты освещенные в статье, что-то узнал нового, и починил загрузку ОС на сервере.

В телеграм канале DevOps от первого лица можно оставить комментарий или почитать интересные истории из практики DevOps