Загрузка ОС Linux без загрузчика

Введение


Здесь по возможности я постараюсь как можно проще и детальнее ответить на вопрос:
«Как можно загрузить Linux (на примере ubuntu) без использования загрузчика такого как GRUB 2, iELILO»
Здесь не будет разбираться как запустить/установить Ubuntu в режиме [UEFI only]. Для этого обратитесь сюда help.ubuntu.ru/wiki/установка_дистрибутива_на_компьютер_с_efi
и сюда help.ubuntu.ru/wiki/lubuntu-osinstallation
Все действия будут производиться на уже работающей системе.

Для того, чтобы воспользоваться данной возможностью необходимо соблюсти некоторые требования.

Требования


1. UEFI вместо BIOS (выставить режим [UEFI only]);
2. OS 64-bit;
3. Linux (Kernel >= 3.3);

Входные данные


Установленный дистрибутив lubuntu-13.04-desktop-amd64 с выставленным режимом [UEFI only]. Отключил Fast Boot (После завершения можно включить).

Полученная таблица разделов
user@pc:~$ sudo parted /dev/sda print

Model: ATA mSata Smartbuy 3 (scsi)
Disk /dev/sda: 32,0GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt

Number  Start   End     Size    File system     Name  Flags
 1      1049kB  99,6MB  98,6MB  fat32                 boot
 2      99,6MB  27,8GB  27,7GB  ext4
 3      27,8GB  32,0GB  4182MB  linux-swap(v1)

Необходимо обратить внимание на 1 раздел, с него и будет осуществляться прямая загрузка ядра без участия отдельного загрузчика (например GRUB 2), предъявляемые к нему требования:

  1. Выставленный флаг boot;
  2. Рекомендуемый размер до 512 МБ (встречал разные рекомендации каким он должен быть размером, в основном это 200-300 МБ, от себя замечу, что на деле он будет занят на 5.3 МБ);
  3. Файловая система fat32/fat16/fat12 (UEFI имеет поддержку);

данный раздел не обязательно должен идти первым, главное, соблюсти требования выше (от себя советую поставить первым).

Подготовительные этапы выполнены, мы имеем работающую 64 битную операционную систему с выставленным режимом UEFI only и разделом для ядра (в данный момент там расположен GRUB, рядом мы положим ядро).

Получаем и настраиваем своё ядро


Загружаем ОС, открываем консоль.
Для того, чтобы ядро могло загрузиться без использования загрузчика, ему необходимо указать диск который будет монтироватся в качестве корневого, чтобы это сделать, нужно собрать своё ядро и указать ему опцию
CONFIG_CMDLINE="root=/dev/sda2 ro"

у меня ОС установлена на диске sda2.
Обычно эту строку передаёт загрузчик GRUB вместе со многими другими параметрами

Если у Вас другая версия дистрибутива
Проверьте, чтобы были установлены опции ядра
CONFIG_EFI=y
CONFIG_RELOCATABLE=y
CONFIG_EFI_STUB=y
CONFIG_EFI_PARTITION=y
CONFIG_EFI_VARS=m #or y works too.
CONFIG_FB_EFI=y
CONFIG_FRAMEBUFFER_CONSOLE=y

Замечание
На сайте разработчика Ubuntu написано, что если вы используется не оригинальное ядро, а собрали его сами, то им будет трудно вам оказать поддержку и отчёты об ошибках не присылайте. (https://help.ubuntu.com/community/Kernel/Compile)


Получим необходимые инструменты (может занять продолжительное время)
sudo apt-get install fakeroot build-essential crash kexec-tools makedumpfile kernel-wedge
sudo apt-get install libncurses5 libncurses5-dev libelf-dev asciidoc binutils-dev

Теперь создадим директорию в которой будем совершать все действия, я назову папку v2, что будет символизировать модификацию последнего ядра системы.
user@pc:~$ mkdir v2
user@pc:~$ cd v2

Получить исходники последней версии ядра и подготовить окружение
user@pc:~/v2$ apt-get source linux-image-$(uname -r)
user@pc:~/v2$ sudo apt-get build-dep linux-image-$(uname -r)

Перейдём в папку linux-3.8.0
cd linux-3.8.0

Теперь приступим к модификации конфигурации ядра
chmod a+x debian/scripts/*
chmod a+x debian/scripts/misc/*
fakeroot debian/rules clean
fakeroot debian/rules editconfigs

После выполнения последней команды вначале будет выведено уведомление:
Do you want to edit config: amd64/config.flavour.generic? [Y/n]

Здесь как раз указано, что редактируем конфигурацию для 64 битного ядра, вводим Y, жмём ввод и получим окно


теперь открываем поиск (клавиша '/'), вводим cmdline и жмём ввод и видим то, что на скриншоте


затем жмём цифру 2 и переходим к правке параметра 'Built-in kernel command line', жмём 'y' и в данном поле выставляется звёздочка, символизирующая, что данный режим включен, теперь переходим на поле которое ниже, жмём ввод и вводим в него заветное
root=/dev/sda2 ro

Эта и есть та самая опция, ради которой всё затевалось (Вместо sda2 подставьте свой диск).
Мы получили данный конфиг:


Небольшое отступление (можно пропустить)
На этом этапе я остановился, собрал ядро, порадовался, что всё так просто и при загрузке свежесобранного ядра получил ошибку, что ядро не может найти корневой раздел (собственно это, ради чего весь процесс сборки ядра и затевался). Я долго недоумевал что же к чему и даже попробовал указать диск в формате UUID, но стабильно получал ошибку:
VFS: Cannot open root device "sda2" or unknown-block(0,0) error -6
Please append a correct "root=" boot option; here are the available partitions:
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)

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

Теперь необходимо установить ещё некоторые опции ядра.
Водим в консоль (запустите ещё одну)
lspci -n

и полученный вывод вставляем в окно ввода на сайте
Debian GNU/Linux device driver check page
жмём check, получаем:


из этого списка нам нужно включить драйвер дискового контроллера, в моём случае это ahci (Строка 'Sata Controller', Столбец 'Driver').
Снова жмём '/' для поиска и вводим 'ahci'. Для верности отмечаем все три найденных варианта для встраивания SATA_AHCI_PLATFORM, SATA_ACARD_AHCI и SATA_AHCI.

Теперь выбираем везде 'exit', в конце соглашаемся, сохраняем настройки выбором Yes. После чего в консоле отказываемся от редактирования конфигураций для других платформ, ибо они нам не нужны.

Сборка ядра


user@pc:~/v2/linux-3.8.0$ fakeroot debian/rules clean
user@pc:~/v2/linux-3.8.0$ fakeroot debian/rules binary-headers binary-generic

Теперь остаётся только подождать пока ядро будет собрано. В зависимости от мощности вашего компьютера зависит время сборки ядра, на моей машине процесс сборки занял чуть менее часа.

После сборки копируем полученное ядро на загрузочный раздел в папку 'EFI/boot', т.к раздел примонтирован к папке /boot/efi, в результате имеем путь /boot/efi/EFI/boot/
sudo mkdir -p /boot/efi/EFI/boot/

Теперь необходимо скопировать ядро в эту папку дав ему название bootx64.efi
user@pc:~/v2/linux-3.8.0$ sudo cp ./debian/build/build-generic/arch/x86_64/boot/bzImage /boot/efi/EFI/boot/bootx64.efi

Стоит отметить, что загрузка с использованием загрузчика GRUB всё равно будет доступна, стоит только переключить в UEFI (нажать del или F12 при загрузке). Это может пригодиться, если ядро по каким либо причинам не загрузилось.

Теперь необходимо сообщить UEFI о том, что мы хотим сделать загрузочным наше ядро, для этого нужно установить программу которая умеет редактировать настройки UEFI.
sudo apt-get install efibootmgr

Убедимся, что у Вас есть доступ к UEFI переменным
sudo modprobe efivars

Если отработало без ошибок, делаем последний штрих. Добавим наше ядро в UEFI с приоритетом на загрузку №1, название в кавычках после --label можете ввести своё. Регистр в пути к загрузчику не имеет значения, т.к он не регистро-зависимый.
sudo efibootmgr --create --part 1 --label "Linux" --loader '\efi\boot\bootx64.efi'

Теперь в меню загрузки UEFI добавлена новая строчка с названием 'Linux', которая осуществляет прямую загрузку ядра. На этом всё. Можно перезагрузить компьютер и убедиться, что ядро загружается минуя загрузчик.
sudo reboot

Чтобы убедиться, что ядро загружено вами собранное, введите
cat /proc/cmdline

Вы увидете список параметров, передаваемых ядру при загрузке (мы их сами указали ранее):
root=/dev/sda2 ro


Цель достигнута! Спасибо за внимание!

Статья, имеющая подобную тематику:
Загрузка GNU/Linux без стороннего загрузчика

Источники мудрости знаний:
  1. help.ubuntu.com/community/UEFI
  2. www.ondatechnology.org/wiki/index.php?title=Booting_the_Linux_Kernel_without_a_bootloader
  3. swift.siphos.be/linux_sea/kernelbuilding.html#idm3437981411120
  4. askubuntu.com/questions/71332/kernel-panics-with-cannot-open-root-device-error-where-do-i-append-the-root
  5. help.ubuntu.com/community/Kernel/Compile
  6. wiki.ubuntu.com/Kernel/BuildYourOwnKernel
  7. www.rodsbooks.com/efi-bootloaders


UPD:
Спасибо пользователю ValdikSS за ценное замечание. Достичь поставленную цель можно гораздо проще. Пересобирать ядро в данном случае нет необходимости. Его можно скопировать на FAT раздел вместе с initrd (из дириктории /boot) и указать загрузчику правильные параметры:
sudo efibootmgr --create --disk /dev/sda --part 1 --label "Lubuntu" -u --loader '\efi\boot\vmlinuz.efi' root=/dev/sda2 initrd=/efi/boot/initrd.img rw quiet


Поделиться публикацией
Комментарии 18
    +2
    Хм, а разве EFI здесь не выступает в роли загрузчика? И, кстати, какая мотивация — просто интересно, или в этом есть практический смысл (сэкономить 1 секунду на загрузку GRUB'a, например...)?
      +1
      разве EFI здесь не выступает в роли загрузчика?

      думаю вы правы)
      какая мотивация

      Мне было интересно, на сколько сократится время загрузки системы. После установки lubuntu это время составляло 14 сек, после всех этих манипуляций стало 11, выходит я сэкономил 3 сек, правда потратил ни один час времени чтобы сделать такую экономию)) мерил с секундомером и засекал от момента нажатия кнопки питания до появления рабочего стола (думаю я не большую погрешность в измерениях сделал).
        0
        Для интереса, в основном. А вообще, терять преимущества GRUB не всякий согласится, ради пары секунд.
        +12
        Эцсамое. У efibootmgr есть параметр -u. Через него можно передать нужную командную строку для ядра, что обычно и делают, не устраивая плясок с его пересборкой.
          +1
          Незнал. Эта статья меня подтолкнула к такому решению. Обязательно попробую предложенный Вами метод. Спасибо!
            0
            Строго говоря, ядру всегда передаётся командная строка. А параметр -u нужен только для того, чтобы указать на её уникодность.
            +25
            Ну это вообще пушка! Автор, вы наркоман!
            sudo efibootmgr -c -d /dev/sdb -u -l '\EFI\arch\vmlinuz-linux.efi' -u -L "ArchLinux" root=UUID=b255359d-ca9f-4ee4-a9c6-7c8c13d614d1 initrd=EFI/arch/initramfs-linux.img rw quiet i915.lvds_downclock=1 i915.i915_enable_fbc=1 i915.i915_enable_rc6=7 i915.semaphores=1 pcie_aspm=force intel_pstate=disable

            Опции можно писать любые. И никаких перекомпиляций ядра.
              –1
              Разве не будет так в данном случае:
              UEFI предаст управление на ядро, а оно не сможет продолжит загрузку без драйвера sata контроллера (я об этом писал в статье)
              И тогда придется пересобирать ядро
                +2
                для этого там есть initrd.
                  +2
                  Если ядро уже с поддержкой EFI, то оно сможет прочитать initrd с FAT32-раздела в любом случае. А в initrd, как и сказал rimidal, могут быть любые модули.
                • НЛО прилетело и опубликовало эту надпись здесь
                  +1
                  не в рамках шутки, появился вопрос: можно ли в будущем ждать загрузки без UEFI? Просто к чему вопрос — так получается UEFI при загрузке вынуждена каждый раз дергать EFI-сектора устройств и настраивать I/O и прочее управление. Возможно есть смысл как-то упростить эту операцию и пересобирать не ядро а UEFI чтобы вообще получать полноценную «железяку» которая сама все грузит без UEFI и прочих загрузчиков и не дергать диск ради не нужных для его работы частей ядра(ну да, при условии что само ядро будет не монолитным)?
                    +3
                    Кажется, вы намекаете на CoreBoot?
                    0
                    … мимо…
                      0
                      Пару дополнений:

                      На некоторых патченых ядрах (гентушное к примеру) efi-ключи доступны только для чтения, для их изменения (efibootmgr) необходимо загрузиться с параметром «efi_no_storage_paranoia».

                      Можно загружаться и в SecureBoot, но для этого необходимо использовать подписаный загрузчик shim, подписаное ядро и модули (nvidia пролетает). В федоре всё это имеется. (Можно и без загрузчика, если вы уговорите MS подписать ядро)

                      Зачем пересобирать ядро, если в дебиане ещё с версии 2.6 в ядре по умолчанию включен EFI_STUB? UEFI умеет передавать параметры, почитайте справку по efibootmgr.

                      Лучше бы рассказали, как запустить 32-битное ядро на 64-битном UEFI?
                        0
                        Лучше бы рассказали, как запустить 32-битное ядро на 64-битном UEFI?

                        Никак
                        –1
                        Вот что линуксы делают с людьми…
                          0
                          Ещё один шажок на путь разбирательства с «новыми» технологиями для меня. Про перекомпиляцию — с одной стороны фейл, а с другой пришлось разжевывать и объяснять что и как, получилось что материал усваивается лучше. Хотя я бы дополнил статью информацией из комментариев.

                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                          Самое читаемое