Я подготовил образ сервера Ubuntu с VirtualBox. Чтобы передать образ на SSD сервера, я сначала dd
отредактировал MBR (512 байт), а затем раздел LVM (PV, содержащий корневой раздел, уменьшился до 3 ГБ). Серверу не удалось загрузиться из-за отсутствия некоторых частей GRUB. Появлялась подсказка о спасении grub.
Как я узнал из документации GRUB, это имеет смысл, потому что ее части (обычно) хранятся в дисковом пространстве между MBR и первым разделом.
Но как узнать где именно?
Я знаю, что могу просто скопировать все пространство перед первым разделом, но мне любопытно, есть ли какая-нибудь команда, которая показывает точное расположение различных частей GRUB.
Разъяснение: Отдельного загрузочного раздела нет. Есть только физический том LVM, содержащий только корневой раздел (с папкой / boot). Проблема с загрузкой также может быть решена с помощью chroot
вставляя в скопированный образ и выполняя grub-install
.
В MBR, созданной GRUB2, начиная со смещения 0x5c, существует 64-битное значение с прямым порядком байтов, указывающее номер следующего блока диска, который будет загружен. Часто это блок 0x00000000 00000001, то есть следующий блок после MBR.
(Согласно древнему соглашению DOS, первый раздел будет начинаться в начале цилиндра №1, поэтому обычно имеется ряд неиспользуемых блоков, доступных на цилиндре №0 после MBR. В современных системах первый раздел обычно выравнивается, начиная с блок # 2048, т.е. ровно 1 МБ от начала диска. Это дает еще больше свободных блоков перед началом первого раздела.)
Этот второй блок содержит еще немного кода ядра GRUB и список блоков, в котором указаны блоки для загрузки остальной части образа ядра GRUB. Черный список находится в самом конце этого блока. Каждая запись в черном списке имеет длину 12 байтов и имеет следующую структуру:
struct __attribute__ ((packed)) g2_blist_entry {
uint64_t start_lba; # the LBA block number of the first block covered by this entry
uint16_t num_blocks; # number of blocks to read
uint16_t startseg; # segment address in memory to write them to
};
Обычно в черном списке есть только одна запись, охватывающая все остальные блоки для чтения, начиная с блока 0x00000000 00000002.
Длина основного образа GRUB зависит от версии GRUB и количества модулей, добавленных к ядру GRUB.
Например, в моей системе Debian 9, которая использует устаревшую загрузку MBR, GRUB включает в общей сложности 103 блока после MBR. На виртуальной машине RHEL 7.4 общая длина после MBR составляет 107 блоков.