Настройка синхронизации EFI-разделов при использовании RAID1 и Grub
Введение
Прогресс не стоит на месте, инновации рано или поздно догоняют даже тех, кто их не очень ждёт. При установке Debian 12 по умолчанию для разметки дисков используется GPT, а для загрузки - UEFI.
UEFI расшифровывается как Unified Extensible Firmware Interface - унифицированный расширяемый интерфейс прошивок. Это обновлённый вариант BIOS, который умеет работать в 32- или 64-битном режиме процессора и умеет загружать с дисков загрузчики в формате EFI. Для этого на диске должна быть таблица разделов в формате GPT, один из разделов должен иметь тип ESP и отформатирован как файловая система FAT32. ESP расшифровывается как EFI System Partition - системный раздел EFI. Именно в этой файловой системе должны находиться файлы загрузчиков с расширением .efi
, которые можно использовать для загрузки операционных систем. По умолчанию используется файл /EFI/Boot/bootx64.efi
, однако UEFI позволяет прописать в NVRAM меню, позволяющее выбрать один из нескольких загрузчиков.
NVRAM расшифровывается как Non Volatile Random Access Memory - энергонезависимая память. Подобно тому, как UEFI являестся обновлённым вариантом BIOS, NVRAM является обновлённым вариантом CMOS. Настройки UEFI сохраняются в NVRAM, а батарейка на материнской плате теперь используется только в качестве источника питания для часов реального времени.
В NVRAM можно прописать меню, в котором можно указать список всех загрузчиков с расширением .efi
, их текстовые описания и порядок использования.
Если нужно настроить загрузку с массива RAID1, то на каждом из дисков нужно создать раздел ESP, на который при установке будут записаны файлы с расширением .efi
. Проблема в том, что такой раздел нужно не только создать, но и поддерживать актуальным на обоих дисках массива.
Управление NVRAM
Для управления меню, записанным в NVRAM, из Linux можно воспользоваться утилитой efibootmgr
.
Вывести список всех возможных загрузчиков в меню:
# efibootmgr
BootCurrent: 0002
Timeout: 0 seconds
BootOrder: 0002,0000,0005,0001
Boot0000* Hard Drive
Boot0001
Boot0002* debian
Boot0005 Internal EFI Shell
В строке BootCurrent
указан номер строки, которая использовалась для загрузки текущей системы. В строке BootOrder
приведён порядок загрузки. Звёздочками отмечены активные пункты меню.
Для вывода подробностей можно указать команде опцию -v
:
# efibootmgr -v
BootNext: 0002
BootCurrent: 0002
Timeout: 0 seconds
BootOrder: 0004,0002,0000,0005,0001,0003
Boot0000* Hard Drive BBS(HD,,0x0)P0: HGST HUS726T6TALE6L4 .
Boot0001 HD(1,MBR,0x34862533,0x11ac,0x4a20)/File()
Boot0002* debian HD(1,GPT,f5414378-382e-459d-97da-f30daa245d1a,0x800,0xee000)/File(\EFI\debian\shimx64.efi)
Boot0003 default HD(1,GPT,6dbda6de-bb78-4e7e-9bc5-c92ce9a7d2f7,0x800,0xee000)/File(\EFI\Boot\bootx64.efi)
Boot0004* debian HD(1,GPT,6dbda6de-bb78-4e7e-9bc5-c92ce9a7d2f7,0x800,0xee000)/File(\EFI\debian\shimx64.efi)
Boot0005 Internal EFI Shell VenMedia(5023b95c-db26-429b-a648-bd47664c8012)/FvFile(c57ad6b7-0515-40a8-9d21-551652854e37)
Активировать какой-либо пункт меню можно следующим образом:
# efibootmgr -b 0005 -a
BootCurrent: 0002
Timeout: 0 seconds
BootOrder: 0002,0000,0005,0001,0003
Boot0000* Hard Drive
Boot0001
Boot0002* debian
Boot0003* default
Boot0005* Internal EFI Shell
Деактивировать можно вот так:
# efibootmgr -b 0005 -A
BootCurrent: 0002
Timeout: 0 seconds
BootOrder: 0002,0000,0005,0001,0003
Boot0000* Hard Drive
Boot0001
Boot0002* debian
Boot0003* default
Boot0005 Internal EFI Shell
Добавить новый загрузчик и поместить его в начало списка можно следующим образом:
# efibootmgr -c -d /dev/sda -p 1 -L default -l '\EFI\Boot\bootx64.efi'
BootCurrent: 0002
Timeout: 0 seconds
BootOrder: 0003,0002,0000,0005,0001
Boot0000* Hard Drive
Boot0001
Boot0002* debian
Boot0005 Internal EFI Shell
Boot0003* default
В опции -d
указывается диск, в опции -p
указывается номер раздела, в опции -L
- название пункта меню, а в опции -l
путь к используемому загрузчику.
Если нужно только добавить загрузчик, но не помещать его в начало списка загрузки, то опцию -c
нужно заменить на -C
.
К этой команде можно также добавить опцию -u
, в которой указать текстовую строку, которая будет передана ядру операционной системы. В этой строке можно указать опции для настройки ядра при его запуске.
Удалить запись из этого списка можно с помощью следующей команды, указав ей номер удаляемого загрузчика:
# efibootmgr -B -b 0003
Для изменения порядка загрузки можно воспользоваться такой командой:
# efibootmgr -o 00002,0000,0005,0001,00003
BootCurrent: 0002
Timeout: 0 seconds
BootOrder: 0002,0000,0005,0001,0003
Boot0000* Hard Drive
Boot0001
Boot0002* debian
Boot0003* default
Boot0005 Internal EFI Shell
С помощью опции -O
можно вовсе удалить информацию о порядке загрузки. Видимо, в таком случае нужно будет выбрать используемый загрузчик из списка вручную.
Для того, чтобы при следующей загрузке компьютера использовать загрузчик с определённым номером, можно указать номер желаемого загрузчика следующей команде:
# efibootmgr -n 0002
BootNext: 0002
BootCurrent: 0002
Timeout: 0 seconds
Boot Order: 0004,0002,0000,0005,0001,0003
Boot0000* Hard Drive
Boot0001
Boot0002* debian
Boot0003 default
Boot0004* debian
Boot0005 Internal EFI Shell
Как видно, выбранный загрузчик будет отображён в строке BootNext
. Для отмены выбора можно воспользоваться опцией -N
- будет использоваться порядок загрузки по умолчанию.
Чтобы изменить время ожидания ручного выбора загрузчика, можно воспользоваться командой такого вида:
# efibootmgr -t 5
BootNext: 0002
BootCurrent: 0002
Timeout: 5 seconds
BootOrder: 0004,0002,0000,0005,0001,0003
Boot0000* Hard Drive
Boot0001
Boot0002* debian
Boot0003 default
Boot0004* debian
Boot0005 Internal EFI Shell
Для удаления времени ожидания ручного выбора можно воспользоваться опцией -T
. Видимо, в таком случае будет использоваться загрузка в указанном порядке без возможности ручного выбора. Не совсем понятно, что произойдёт, если удалить порядок загрузки и выбранный следующий загрузчик. Видимо будет использоваться загрузка с настройками по умолчанию.
Все настраиваемые утилитой значения прописываются в переменные, доступные через файловый интерфейс:
# ls /sys/firmware/efi/efivars/Boot*
/sys/firmware/efi/efivars/Boot0000-8be4df61-93ca-11d2-aa0d-00e098032b8c /sys/firmware/efi/efivars/Boot0003-8be4df61-93ca-11d2-aa0d-00e098032b8c /sys/firmware/efi/efivars/BootCurrent-8be4df61-93ca-11d2-aa0d-00e098032b8c
/sys/firmware/efi/efivars/Boot0001-8be4df61-93ca-11d2-aa0d-00e098032b8c /sys/firmware/efi/efivars/Boot0004-8be4df61-93ca-11d2-aa0d-00e098032b8c /sys/firmware/efi/efivars/BootNext-8be4df61-93ca-11d2-aa0d-00e098032b8c
/sys/firmware/efi/efivars/Boot0002-8be4df61-93ca-11d2-aa0d-00e098032b8c /sys/firmware/efi/efivars/Boot0005-8be4df61-93ca-11d2-aa0d-00e098032b8c /sys/firmware/efi/efivars/BootOrder-8be4df61-93ca-11d2-aa0d-00e098032b8c
К сожалению, значения этих переменных имеют двоичный формат и их нельзя поменять, не прибегая к помощи утилиты efibootmgr
.
Скрипт
Одно из решений, которое предлагают на просторах интернета - смонтировать раздел на втором диске в точку монитирования /boot/efi2
и обновлять его автоматически при вызове update-grub
с помощью скрипта в каталоге /etc/grub.d/
, который вызывается утилитой update-grub
при каждом её запуске.
Например, можно создать файл /etc/grub.d/90_sync_efi2
со следующим содержимым:
#!/bin/sh
set -e
if mountpoint -q /boot/efi && mountpoint -q /boot/efi2 ; then
efi=`find /boot/efi -type f -printf '%T+ %p\n' | sort | tail -n 1 | cut -d' ' -f2`
efi2=`find /boot/efi2 -type f -printf '%T+ %p\n' | sort | tail -n 1 | cut -d' ' -f2`
if [ -z "$efi" ] ; then
rsync -t --recursive --delete /boot/efi2/ /boot/efi/
elif [ -z "$efi2" ] ; then
rsync -t --recursive --delete /boot/efi/ /boot/efi2/
elif [ "$efi" -nt "$efi2" ] ; then
rsync -t --recursive --delete /boot/efi2/ /boot/efi/
elif [ "$efi2" -nt "$efi" ] ; then
rsync -t --recursive --delete /boot/efi/ /boot/efi2/
fi
fi
exit 0
Нужно дать скрипту права на выполнение:
# chmod +x /etc/grub.d/90_sync_efi2
Не забудьте установить в систему пакет с утилитой rsync
.
Скрипт находит в каждом из разделов самый новый файл. Если в каком-то из двух разделов файлов нет или самый новый файл старше, чем самый новый файл на другмо разделе, то выполняется синхронизация из раздела с более новым файлов в раздел с более старым файлом или без файлов.
RAID1
Другое решение - настроить зеркалирование разделов, не меняя в таблице GPT тип раздела. Для этого можно воспользоваться программным массивом, создаваемым утилитой mdadm
. Для того, чтобы mdadm
не затёрла начало раздела информацией о массиве - метаданными, нужно использовать метаданные версии 1.0, а не версии 1.2, которая используется при создании массивов по умолчанию. Метаданные версии 1.0 помещаются в конце раздела и таким образом не помешают загрузчику UEFI разобраться в структуре файловой системы и найти загрузочные файлы.
Пример команды:
# mdadm --create --verbose --level=1 --metadata=1.0 --raid-devices=2 /dev/md1 /dev/sda1 /dev/sdb1
Как обычно, после изменения массивов RAID нужно обновить содержимое файла /etc/mdadm/mdadm.conf
, чтобы операционная система автоматически собрала массивы в процессе загрузки. Сделать это можно, например, при помощи следующей команды:
# mdadm --detail --scan > /etc/mdadm/mdadm.conf
Этот файл нужно добавить в образ файловой системы, используемой при загрузке ядра:
# update-initramfs -u -k all
Установка/восстановление GRUB
Для установки загрузчика GRUB в раздел ESP можно воспользоваться командой следующего вида:
# grub-install --target=x86_64-efi --efi-directory=/boot/efi/ --bootloader-id=debian
Где:
/boot/efi
- точка монтирования раздела ESP,debian
- имя каталога, в котором будет размещён загрузчик, полный путь к файлам загрузчика на разделе ESP получится таким:\EFI\debian\
.
Для загрузки GRUB принято использовать файл shimx64.efi
- небольшой загрузчик, который был подписан сертификатами Microsoft, прописанными в UEFI всех производителей. При использовании этого файла возможно организовать загрузку в режиме SecureBoot, в котором код загрузчиков и ядра операционной системы проверяются с использованием сертификатов.
Загрузчик EFI из systemd
Вместе с системой systemd
распространяется также пакет systemd-boot
с утилитой, которая умеет устанавливать собственный простой EFI-загрузчик. Установим пакет:
# apt-get install systemd-boot
Если раздел ESP смонтирован в каталог /boot/efi
, то установить в него загрузчик можно следующим образом:
# bootctl install --esp-path=/boot/efi/
bootctl
проверяет, является ли указанный раздел разделом ESP в таблице разделов GPT. Если это не так, то он сообщит об ошибке. Например, в моём случае раздел /boot/efi
находится на программном RAID, созданном средствами mdadm
, как это описано ниже. Поэтому в моём случае при попытке воспользоваться приведённой выше командой я столкнулся с ошибкой:
File system "/dev/md1" is not located on a partitioned block device.
Чтобы отключить проверку типа раздела, нужно задать переменную окружения SYSTEMD_RELAX_ESP_CHECKS
равной единице, вот так:
# SYSTEMD_RELAX_ESP_CHECKS=1 bootctl install --esp-path=/boot/efi/
Утилита добавил в раздел ESP файл \EFI\BOOT\BOOTX64.EFI
и идентичный ему файл \EFI\systemd\systemd-bootx64.efi
, а также создаст файлы с настройками загрузчика в каталоге loader
. Кроме этого будет создан пустой каталог \EFI\Linux
, который, видимо, предназначен для размещения драйверов файловых систем для UEFI.
Загрузчик EFI\systemd\systemd-bootx64.efi
будет автоматически прописан первым загрузчиком в NVRAM. Чтобы утилиты не меняла порядок загрузки и не добавляла свой загрузчик в меню, можно указать ей опцию --no-variables
.
Для удаления загрузчика можно воспользоваться такой командой:
# SYSTEMD_RELAX_ESP_CHECKS=1 bootctl remove --esp-path=/boot/efi/
Утилита также обладает другими возможностями, которые имеются в утилите efibootmgr
: позволяет менять настройки таймаута, выбирать загрузчик, который будет использоваться при следующей загрузке и т.д.
Использованные материалы
- О UEFI - наиболее полное и подробное описание UEFI, которое мне попадалось
- Настройка UEFI-загрузчика. Самое краткое руководство в мире
- How to correctly install GRUB on a soft RAID 1?
- Install Ubuntu 20.04 desktop with RAID 1 and LVM on machine with UEFI BIOS
- EFI system partition / Troubleshooting / ESP on software RAID1
- UEFI booting and RAID1