В один прекрасный момент после обновления до очередного ядра из Debian backports при перезапуске ПК я получил прекрасную картину: при запуске на свежем ядре GRUB писал
Out of memory on "Loading initial ramdisk"
и сваливался в
Kernel Panic - not syncing: VFS: Unable to mount root fs on unknown block(0,0).
Откат на старое ядро решал проблему, но разобраться с причиной надо было обязательно =)
Загрузка ОС на устройстве с UEFI обычно проходит по следующему сценарию:
-
Инициализация оборудования;
-
Копирование в оперативную память UEFI загрузчика OS (lilo/grub) и передача управления ему;
-
UEFI загрузчик записывает образ ядра OS в оперативную память и дёргает функцию start_kernel;
-
Ядро инициализируется, монтирует корень файловой системы и запускает процесс init, лежащий на корне (/init или /sbin/init). Этим процессом может быть любая система инициализации, например systemd, System V, OpenRC и т.д;
Что такое initramfs?
Initramfs (Initial ram file system) – образ файловой системы, загружаемый в оперативную память вместе с ядром OS. Основные задачи этого образа - монтирование реального корня файловой системы и запуск процесса init лежащего на нем.
При загрузке с initramfs ядро передает управление программе /init, лежащей в этом образе, а не в реальном корне файловой системы.
Внутри initramfs образа могут реализовываться разнообразные сценарии загрузки ОС, например:
-
Вывод приветственной картинки на экран;
-
Проверка целостности корневой файловой системы;
-
Загрузка с нестандартных файловых систем;
-
Загрузка с LVM;
-
Загрузка с RAID;
-
Загрузку с образа корня, лежащего в интернете;
-
Загрузку с зашифрованного LUKS раздела;
Соответственно, было принято решение разбираться, а что случилось с initramfs. В ходе изысканий выяснилось, что по умолчанию Debian в целях совместимости с большинством оборудования старается поместить в initramfs максимальное количество модулей ядра для оборудования. С учётом того, что ядро Linux с каждым следующим релизом прибавляет в размерах, количество этих самых модулей также увеличивается. Таким образом, размер initramfs образа тоже увеличивается и он перестал помещаться в отведенную ему область оперативной памяти UEFI (~50 МБ). В связи с этим было принято решение "облегчить" модуль чтобы он обратно вписался в рамки ему отведённые. Для этого:
1) В файле /etc/initramfs-tools/initramfs.conf
Заменить MODULES=most на MODULES=dep
2) Произвести перегенерацию initramfs: update-initramfs -k all -c
3) Обновить grub после этого: update-grub
На этом всё. После данных манипуляций ОС должна загрузиться штатно, т.к размер initramfs модуля уменьшился и уже помещается в 50 МБ UEFI RAM.