Разработчик
0,1
рейтинг
14 октября 2013 в 18:39

Администрирование → Linux Kernel EFI Boot Stub или «Сам себе загрузчик» из песочницы

UEFI Tux Logo

Введение


Прочитав недавнюю статью Загрузка ОС Linux без загрузчика, понял две вещи: многим интересна «новинка», датируемая аж 2011 годом; автор не описал самого основного, без чего, собственно, и работать ничего не будет в некоторых случаях. Также была ещё одна статья, но либо она уже устарела, либо там опять таки много лишнего и недосказанного одновременно.

А конкретно, был упущен основной момент — сборочная опция ядра CONFIG_EFI_STUB. Так как в последних версиях U(lu/ku/edu/*etc*)buntu эта опция по умолчанию уже включена, никаких подозрений у автора не появилось.
Насколько мне известно, на текущий момент она включена в дистрибутивах указанных версий и выше: Arch Linux, Fedora 17, OpenSUSE 12.2 и Ubuntu 12.10. В комментах ещё упомянули, что Debian с ядром 2.6 умеет, но это не более, чем бэкпорт с последних версий. На этих дистрибутивах пересобирать вообще ничего не нужно! А ведь на других CONFIG_EFI_STUB, скорее всего, либо вообще отсутствует, т. к. опция доступна только с ядра версии 3.3.0 и выше, либо выключена по умолчанию. Соответственно, всё, описанное ниже, справедливо для ядра, собранного с опцией CONFIG_EFI_STUB.

Итак, что же такое Linux Kernel EFI Boot Stub?


Общая информация

А ни что иное, как… «exe-файл»! Да-да, «виндовый» PE/COFF. Ну, а точнее, только закос под него с небольшими модификациями, чтобы угодить загрузчику UEFI. Можно убедиться в этом, прочитав первые 2 байта ядра:
$ od /boot/vmlinuz-linux --address-radix=x --read-bytes=2 -t x1c
0000000  4d  5a
          M   Z
0000002

Знакомо, не правда ли? Как минимум тем, кто хоть раз «для интереса» открывал исполняемый файл MS-DOS или Windows в блокноте, хекс-редакторе или чём-то покруче. Это инициалы Марка Збиковски, который, собственно, и разработал данный формат файлов в MS-DOS. Сигнатура этой заглушки до сих пор висит рудиментом в современных исполнимых файлах Windows, сжирая со своим заголовком целых 64 байта на каждый файл!

DOS-заголовок попадает на legacy-код, который выполняется в случае загрузки ядра как бут-сектора, и ругается на манеру MS-DOS при запуске PE-файлов: «Direct floppy boot is not supported. Use a boot loader program instead. Remove disk and press any key to reboot ...». Поэтому информация из этого заголовка здесь является мусором, кроме, собственно, сигнатуры 'MZ' и адреса смещения следующего заголовка.

Идём дальше.
Спецификация PE/COFF говорит нам, что по смещению 0x3c находится 32-битное смещение второго заголовка с сигнатурой «PE\0\0»:
$ od /boot/vmlinuz-linux --address-radix=x --read-bytes=4 --skip-bytes=0x3c -t x4
00003c 000000b8
000040

итак, смещение равно 0xb8, что справедливо для текущего stable-ядра x86_64 архитектуры, на x86 будет 0xa8. Читаем:
$ od /boot/vmlinuz-linux --address-radix=x --read-bytes=4 --skip-bytes=0xb8 -t x1c
0000b8  50  45  00  00
         P   E  \0  \0
0000bc

А вот и сигнатура второго заголовка! Как можно было догадаться, это аббревиатура от словосочетания Portable Executable, с которой и начинается полезная нагрузка в исполнимых файлах.

Даже загрузчик Windows плевал на половину полей этого заголовка, а уж UEFI они и вовсе не нужны, поэтому некоторые из них прописаны статически, важные же — заполняются во время сборки ядра. Множество «ненужных» полей, всяких таймстемпов, котрольных сумм и пр. просто остаются нулями. Заполняются в основном размеры, смещения, точка входа и т. д. Поэтому, можно с натяжкой назвать данный PE-файл полностью валидным. Однако, классические утилиты LordPE или PETools вполне себе довольствуются сигнатурами и рассказывают о файле всё, что им известно:

PE optional header


imageОсновное отличие от «реальных» исполняемых файлов в Windows — это флаг Subsystem опционального заголовка, который выставляется в IMAGE_SUBSYSTEM_EFI_APPLICATION, а не в IMAGE_SUBSYSTEM_WINDOWS_GUI для графических или IMAGE_SUBSYSTEM_WINDOWS_CUI для символьных (консольных) приложений Windows соответственно.

Структура

В общем же, всё как в обычном PE-файле. На текущий момент стабильной версии 3.11.4 ядра Arch Linux из репозиториев, в нём содержатся 3 секции: '.setup', '.reloc' и '.text'.

  • Секция .setup, содержит в основном legacy-код для инициализации в случае загрузки в режиме совместимости. При загрузке же в UEFI mode, все переключения режимов процессора, начальные инициализации производит прошивка.
  • .reloc секция обязательно требуется загрузчиком, поэтому при сборке ядра создаётся пустая заглушка «чтоб было».
  • Самая интересная секция .code, собственно, содержит EntryPoint и основной код всего остального ядра. После того, как EFI-application найдено, загрузчик выполняет загрузочный сервис LoadImage, тем самым загружая весь образ в память. Тип резидентности зависит от поля Subsystem: EFI_APPLICATION будет выгружаться, когда отработает. EFI_DRIVER же может быть Unloadable и выгрузится только в случае критической ошибки. Далее передаётся управление на точку входа, обычно это функция efi_main() — аналог main() в C.

На самом деле, я немного слукавил, в начале назвав ядро exe-файлом. По сути это простое себе приложение EFI, которое использует формат PE32+.

Основные требования


imageПрежде всего, необходимо активировать режим загрузки EFI-mode. Пункт может называться как вдумается вендору, обычно находится во вкладке Boot Options. Если увидели там что-то вроде Legacy Mode или CSM (Compatibility Support Mode), либо просто BOIS Mode, меняйте на что-то похожее: (U)EFI Mode, Enhanced Mode или Advanced Mode.

Если материнская плата имеет логотип «Windows 8 Ready!», то, скорее всего, режим EFI Boot Mode уже активирован по умолчанию.

В большинстве случаев, для загрузки ядра Linux в EFI-mode необходимо выключить опцию Secure Boot.

Разметка диска

Многие источники указывают, что обязательно нужна разметка диска GPT, а не MBR, но это не так. UEFI вполне себе умеет MBR. Другое дело, например, Windows насильно заставляет разбивать диск новым методом, чтобы грузиться в EFI mode и ругается на древность Master Boot Record'а. И правильно делает! Разметив диск «современно» ничего не потеряем, а только выиграем.
Во-первых, не будет проблем со всякими там Primary/Logical разделами, «туда не ходи — сюда ходи» и прочими рудиментами.
Во-вторых, хоть сейчас и продвигаются массово SolidState-диски, у которых объёмы пока не сильно удивляют, размером же обычной «вертушки» в несколько терабайт сейчас уже никого не удивишь. А ведь под MBR можно разметить раздел максимум около 2ТБ. GPT же, видит ну очень много, можно даже цифру не называть — относительно не скоро появятся диски таких размеров.
Ну и плюс всякие бонусы, типа дублирования GPT-записи в начале и конце диска, контрольные суммы целостности и т. п., добавляют желания не раздумывая размечать диск под GPT.

Статей, как разбить диск с помощью различных утилит в GNU/Linux можно найти огромное количество.

Отдельный раздел

Тип раздела

Спустя nn-цать лет разработки стандартов, инженеры таки решили, что хардкодить — не есть хорошо. Теперь не важно где находится наш загрузочный раздел, загрузчик UEFI делает очень просто: он перебирает все подряд разделы и диски и ищет один особенный. Особенность его заключается в том, что в случае с MBR-разметкой, он имеет тип с кодом 0xEF (как можно догадаться, от EFI). В случае разметки GPT — раздел с GUID равным C12A7328-F81F-11D2-BA4B-00A0C93EC93B.

Здесь существует некоторая неявность. Все утилиты для разметки, например, parted, имеют свойство установки и отображения флага «boot», который применяется к разделу. Так вот, в случае с MBR, такая возможность действительно имеется, т. е. существует реальный байт, который указывает БИОСу на «загрузочность» раздела. Этот флаг можно поставить на любой раздел, MBR которого, мы хотим скормить БИОСу для загрузки. Но, когда мы имеем дело с GPT, никакого флага в действительности нет! Под этим флагом parted понимает как раз GUID равный вышеуказанному. Т. е. по факту GPT boot flag = GPT EFI Partition!
parted
# parted /dev/sda -l
Модель: ATA ST3750330AS (scsi)
Диск /dev/sda: 750GB
Размер сектора (логич./физич.): 512B/512B
Таблица разделов: gpt
Disk Flags:

Номер  Начало  Конец   Размер  Файловая система  Имя               Флаги
 1     1049kB  135MB   134MB   fat32             EFI System        загрузочный
 2     135MB   269MB   134MB   ext2              Linux filesystem
 3     269MB   8859MB  8590MB  linux-swap(v1)    Linux swap
 4     8859MB  30,3GB  21,5GB  ext4              Linux filesystem
 5     30,3GB  46,4GB  16,1GB  ext4              Linux filesystem
 6     46,4GB  67,9GB  21,5GB  ext4              Linux filesystem
 7     67,9GB  750GB   682GB   xfs               Linux filesystem
gdisk же, не страдает этим:
gdisk
# gdisk /dev/sda -l
GPT fdisk (gdisk) version 0.8.7

Partition table scan:
  MBR: protective
  BSD: not present
  APM: not present
  GPT: present

Found valid GPT with protective MBR; using GPT.
Disk /dev/sda: 1465149168 sectors, 698.6 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): 02D11900-D331-4114-A3D7-8493969EF533
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 1465149134
Partitions will be aligned on 2048-sector boundaries
Total free space is 2014 sectors (1007.0 KiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048          264191   128.0 MiB   EF00  EFI System
   2          264192          526335   128.0 MiB   8300  Linux filesystem
   3          526336        17303551   8.0 GiB     8200  Linux swap
   4        17303552        59246591   20.0 GiB    8300  Linux filesystem
   5        59246592        90703871   15.0 GiB    8300  Linux filesystem
   6        90703872       132646911   20.0 GiB    8300  Linux filesystem
   7       132646912      1465149134   635.4 GiB   8300  Linux filesystem


Вывод: если наш EFI-раздел на MBR — ставим тип раздела EFI Partition и boot flag. Если GPT — либо тип EFI Partition, либо boot flag, так как они представляют собой одно и то же.

Есть ещё всякие вещи, типа GPT legacy boot flag, который устанавливается в Protective MBR, и прочее, но всё это костыли, которые используются только в режиме совместимости. В режиме GPT UEFI Boot должны игнорироваться.

Файловая система

В разных источниках пишут по-разному. Кто-то говорит, что FAT16 можно использовать, кто-то даже FAT12 рекомендует. Но, не лучше ли последовать совету официальной спецификации? А она говорит, что системный раздел должен быть в FAT32. Для removable-media (USB HDD, USB Flash) — ещё и FAT12/FAT16 в придачу к FAT32.
Про размер раздела ничего не говорится. Однако, по причине начальных костыльных и баганых реализаций загрузчиков и прошивок, опытным путём народ выяснил, что во избежание различных «внезапностей», рекомендуется размер не менее 520МиБ (546МБ). Здесь как повезёт, проблем может не быть и с 32-мегабайтным разделом.

Структура директорий

После того, как загрузчик нашёл свой «меченый» раздел и убедился, что поддерживает файловую систему, он начинает выполнять все действия с путями, относительно корня раздела. Кроме того, все файлы в данном разделе должны находиться в директории \EFI\, которая, в свою очередь, является единственной в корне раздела. По соглашению, каждому вендору рекомендуется выделить себе папку с уникальным названием и поместить её в \EFI\, например: \EFI\redhat\, \EFI\microsoft\, \EFI\archlinux\. В директории вендора находятся непосредственно исполнимые efi-приложения. Рекомендуется один файл на одну архитектуру. Файлы должны иметь расширение .efi.

Для съёмных устройств предназначена директория \EFI\BOOT\. В ней так же рекомендуется не более одного файла для каждой архитектуры. В дополнение к этому, файл должен называться boot{arch}.efi. Например, \EFI\BOOT\bootx64.efi. Доступные архитектуры: ia32, x64, ia64, arm, aa64.

Доступ к NVRAM

По умолчанию, если ничего не записано в энергонезависимой памяти UEFI, будет загружаться \EFI\BOOT\bootx64.efi. Чтобы записать в NVRAM путь к необходимому приложению, можно воспользоваться утилитой efibootmgr. Попробуем вывести текущие записи:
# efibootmgr -v

В некоторых дистрибутивах для работы этой утилиты требуется включенная опция ядра CONFIG_EFI_VARS.

Приступаем


imageИтак, мы разметили FAT32 EFI System Partition (ESP) размером 550МиБ. Либо, у нас стоит винда второй системой и уже сама создала его. Правда, создаёт она его обычно размером около 100МБ, но лично у меня проблем никогда не возникало.
В /boot уже имеется ядро с поддержкой EFI boot STUB.
Проверить
Чтобы проверить, была ли включена опция при сборке ядра, выполним:
$ zgrep CONFIG_EFI_STUB /proc/config.gz
либо
$ zgrep CONFIG_EFI_STUB /boot/config-`uname -r`

CONFIG_EFI_STUB=y означает, что опция активна.

Далее у нас куча вариантов развития событий:
  • Можно смонтировать ESP\{vendor}\ на /boot через mount --bind, предварительно скопировав содержимое.
    Исключения
    Данный пункт подходит только для дистрибутивов, которые не содержат символические ссылки в каталоге /boot. Например, на openSUSE монтировать не удастся, т. к. он содержит там несколько ссылок, в том числе и на само ядро.
  • Как вариант, при обновлении ядра, каждый раз копировать его и ram-disk в ESP\{vendor}\
  • Можно поставить EFI driver на чтение файловой системы /boot и грузиться напрямую, лишь добавив к ядру расширение '.efi' (а лучше хардлинк).

Теперь нужно как-то добавить загрузочный пункт в NVRAM UEFI. Здесь снова множество вариантов:

Если мы уже загружены в режиме EFI (efibootmgr -v не ругается) с помощью загрузчиков GRUB2, rEFInd и т. п., то всё нормально:
  • Используем efibootmgr, который умеет передавать параметры ядра.
  • Если efibootmgr брыкается, можно воспользоваться UEFI Shell, который, как и наше ядро, является EFI-приложением. Через его команду bcfg возможно редактировать пункты загрузки.
  • Может быть такой вариант: efibootmgr ругается на добавление параметров, значит прошивка не поддерживает их запись (либо просто кривая, что вероятнее). В прошлой статье в комментах упомянули параметр ядра efi_no_storage_paranoia, который может помочь. Но пользоваться им можно только если вы уверены в том, что ваша прошивка реализована полностью в соответствии со спецификацией! Разработчики предупреждают, что если вендор добавил костылей и отсебятины при реализации, есть неиллюзорная вероятность материализовать кирпич на месте материнской платы.
  • Можно также грузиться через UEFI Shell. Для него создаётся скрипт startup.nsh, в котором указывается команда загрузки ядра с нужным command line. А Shell, в свою очередь, добавляется как пункт загрузки.
  • Существует ещё одна проблема: добавление пункта возможно только для одного пути ядра, при этом ram-disk не видится. В большинстве статей рекомендуют при этом пересобирать ядро со встроенным initrd. Точно не знаю — проблема ли ядра это, или загрузчика. Но на текущий момент в 90% случаев всё поддерживается и пересобирать ядро не нужно.
    Вероятная причина заблуждения
    Рекомендации по встраиванию рам-диска в ядро пошли, скорее всего, из-за массового неверного указания пути к нему. В ранних реализациях EFI Boot Stub, ядро не плевалось ошибкой о неверном пути к ram-disk, а молча отказывалось грузиться. Видимо поэтому все начали массово внедрять его в ядро, решив, что он не поддерживается. Хотя поддержка параметра initrd существует с самого появления в ядре фичи Boot Stub.

    ВАЖНО: Путь к ram-диску передаётся абсолютный через обратные слеши " \ ", а не прямые! Например, initrd=\EFI\archlinux\initramfs-linux.img.
    Исключения для анархистов
    На самом деле, ядра, версий выше 3.8.0-rc5 не видят разницы между прямым и обратным слешем — будет работать любой. Но вот с момента появления фичи Boot Stub в версии 3.2.0-rc5, путь, записанный через прямые слеши, ядро просто не видело и молча без ошибок отказывалось грузиться. Ругаться ошибками по этому поводу, оно научилось в версии 3.4.0.

Если же мы только узнали про режим EFI boot и хотим на него перейти, чтобы добавлять пункты загрузки, нужно уже находиться в данном режиме, а мы то всё ещё в режиме совместимости… Есть два основных решения:
  • Скачать первый попавшийся live-cd с поддержкой EFI boot. И из него уже воспользоваться командой efibootmgr.
  • Скачать UEFI Shell. Из него можно, как загрузиться в режиме EFI, просто указав ядро и ram disk, так и редактировать пункты загрузки.

Dualboot без загрузчика


Если у вас установлены 2 системы одновременно, и всё равно не хочется ставить сторонний загрузчик, можно добавить обе в пункты загрузки UEFI и подкорректировать предпочитаемый boot order. Загрузчик Windows обычно располагается в \EFI\Microsoft\BOOT\bootmgfw.efi.

Итого


Если всё сделано правильно, перегружаемся, вызываем Boot Menu, выбираем добавленный нами пункт и смотрим на почти мгновенную загрузку. В случае с SSD, FastBoot, Readahead и Arch Linux — около 3-4 секунд. Домашний сервер уже год загружается без всяких сторонних загрузчиков, используя EFI Boot STUB.
Конечно, выигрыш в скорости тут минимальный, но, как пишут знающие люди типа Roderick Smith, иногда в режиме EFI Boot происходит «более адекватная» инициализация оборудования, чем в режимах совместимости.

Заключение


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

Литература


Официальные спецификации UEFI
Roderick W. Smith's Web Page — творчество автора многих утилит, связанных с EFI, загрузчиками и разметкой диска.
ArchWiki: UEFI Bootloaders — бессменная и одна из лучших и полных вики по GNU/Linux одного из дистрибутивов.
Официальная спецификация PE/COFF
Дмитрий @TrueBers
карма
27,2
рейтинг 0,1
Разработчик
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Администрирование

Комментарии (23)

  • 0
    Полезная ссылка, как раз про настройку ядря для всего этого: wiki.gentoo.org/wiki/EFI_stub_kernel
    • 0
      Спасибо, но именно поэтому я и написал статью.
      Всё зависит от реализации загрузчика. Например, ram-disk отдельным файлом преспокойно поддерживается в настоящее время большинством прошивок, а в статье по вашей ссылке его запихивают в ядро, что в 90% случаев не нужно.

      upd: упомянул в статье об этом.
      • 0
        Например, ram-disk отдельным файлом преспокойно поддерживается в настоящее время большинством прошивок

        Наверное таки не прошивками, но самим ядром

        Сам загружаюсь так:

        efibootmgr --create --label "Gentoo" --loader '\EFI\gentoo\kernel.efi' -u 'root=LABEL=Gentoo initrd=EFI\gentoo\initrd.img init=/usr/lib/systemd/systemd'
        
        • 0
          Уже отписал в статье возможную причину: рекомендации по встраиванию рам-диска в ядро пошли, скорее всего, из-за массового неверного указания пути к нему: в ранних реализациях boot stub, ядро не плевалось ошибкой о неверном пути к ram-disk, а молча отказывалось грузиться. Видимо поэтому, все начали массово внедрять его в ядро, решив, что он не поддерживается. Хотя поддержка параметра initrd существует с момента добавления в ядро Boot Stub.

          Странно, что у вас грузится с относительным путём к initrd. В аннотации к коду по Boot Stub явно указано, что путь должен быть абсолютный.
  • +2
    Отличная статья! Грамотно написано, понятно изложено. Хотел бы, чтобы вы написали про практическое применение Secure Boot в Linux, т.к. я хоть и теоретически подкован, у меня нет устройств, где можно это пощупать.
    Моя статья: Немного про UEFI и Secure Boot
    а я, лентяй, все так и не допишу статью про TPM
  • 0
    У меня несколько вопросов по теме.

    1) Когда-то ставил убунту в ефи режиме, она прописала себя в список ос в ефи( нврам?). После этого несколько раз винчестер полностью переразбивал, менял ос, но убунта висит в меню ефи. как убрать?

    2) Иногда подсоединяю винт с восьмой виндой, gpt разбивка. В меню загрузки ефи появляется «виндоус бут манагер». Вытаскиваю винт — меню пропадает. Значит эта запись (или что-то другое — тогда что?) хранится на винчестере. Можно ли хранить на одном винчестере несколько загрузчиков?

    3) Касательно хакинтошей — есть загрузчик кловер, который умеет на лету править таблицы управления питанием. Есть ли практические варианты его применения для линукс? для windows (кроме подсовывания таблицы слик)?
    • 0
      Когда-то ставил убунту в ефи режиме, она прописала себя в список ос в ефи( нврам?). После этого несколько раз винчестер полностью переразбивал, менял ос, но убунта висит в меню ефи. как убрать?

      Через тот же efibootmgr
    • 0
      1) Когда-то ставил убунту в ефи режиме, она прописала себя в список ос в ефи( нврам?). После этого несколько раз винчестер полностью переразбивал, менял ос, но убунта висит в меню ефи. как убрать?

      Как уже сказали, либо efibootmgr, либо EFI Shell закинуть на флешку как \EFI\BOOT\bootx64.efi. Загрузиться с него, и командой bcfg удалить пункт:
      bcfg boot dump -v
      
      запоминаем его номер и удаляем
      bcfg boot rm N
      
      где N — требуемый номер пункта для удаления.

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

      2) Иногда подсоединяю винт с восьмой виндой, gpt разбивка. В меню загрузки ефи появляется «виндоус бут манагер». Вытаскиваю винт — меню пропадает. Значит эта запись (или что-то другое — тогда что?) хранится на винчестере. Можно ли хранить на одном винчестере несколько загрузчиков?

      Извините, но в статье всё это описано, не хочу повторяться.

      3) Касательно хакинтошей — есть загрузчик кловер, который умеет на лету править таблицы управления питанием. Есть ли практические варианты его применения для линукс? для windows (кроме подсовывания таблицы слик)?

      Точно не знаю, возможно поможет какая магия с написанием скрипта для UEFI Shell. Здесь уже глубже надо копаться.
    • 0
      1)…
      под рутом запускаем efibootmgr без параметров.
      Видим что-то подобное:

      root@ubuntu64:~# efibootmgr
      BootCurrent: 0001
      Timeout: 1 seconds
      BootOrder: 0001,0000,0004,0003,0002
      Boot0000* ubuntu
      Boot0001* Ubuntu EFI
      Boot0002 CD/DVD Drive
      Boot0003* Hard Drive
      Boot0004* ubuntu

      Смотрим идентификатор пункта, который хотим удалить. Допустим, 4-й:
      Пишем:
      root@ubuntu64:~# efibootmgr -b 0004 -B
      BootCurrent: 0001
      Timeout: 1 seconds
      BootOrder: 0001,0000,0003,0002
      Boot0000* ubuntu
      Boot0001* Ubuntu EFI
      Boot0002 CD/DVD Drive
      Boot0003* Hard Drive

      Вуаля!
      (а вообще — man efibootmgr в помощь)
  • 0
    а насколько эта nvram является nvram'ом?
    просто sram с батарейкой (и можно всё сбросить выниманием батарейки)?
    или же пишется во флешку (например, ту же, что и содержит сам uefi)?
    • 0
      Не проверял, но думаю, зависит от производителя.
    • 0
      Чаще всего записывается на саму флешку.
  • 0
    Когда-то потратил много времени на борьбу с efi на ноуте. Через bcdedit и через efibootmgr.
    В результате так и не смог заставить прошивку загружать что-то кроме \EFI\Microsoft\Boot\bootmgfw.efi, поэтому просто переименовал его, а вместо него поставил Shell.efi.
    Потом, как упоминается в статье, скопировал на efi-раздел ядро и initrd и из оболочки загружал любую нужную ОС.
    А пока писал эти строчки — вспомнил, что забыл закинуть новое ядро на efi-раздел после его обновления.
    • 0
      Чтобы не забывать, советую использовать один из вариантов автоматического копирования ядра при обновлении из этой статьи.
  • 0
    Достаточно многие моменты весьма условны и (на самом деле!) неважны.
    Нужно реально щупать, что да как, на конкретной системе.

    Кроме того, все файлы в данном разделе должны находиться в директории \EFI\, которая, в свою очередь, является единственной в корне раздела


    Файлы должны иметь расширение .efi.

    По спецификации — да, возможно.
    По факту — вовсе необязательно! Эти правила, как правило (упс!) нужны только чтобы вендоры не запутались с файлами. А для, собственно, загрузки это неважно!

    ВАЖНО: Путь к ram-диску передаётся абсолютный через обратные слеши " \ ", а не прямые! Например, initrd=\EFI\archlinux\initramfs-linux.img.


    Вообще говоря, не очень важно. Ядро как-то само разбирается со слэшами! (опять же, по факту).
    Я на своей рабочей убунте сделал просто: скопировал ядро и initrd на efi-раздел (создал для порядка папку myubuntu и кинул в него), после чего прописал его в загрузку такой командой:

    efibootmgr -c -d /dev/sda -p 1 -l \\EFI\\myubuntu\\vmlinuz-3.8.0-31-generic -L "Ubuntu EFI" -u "initrd=/EFI/myubuntu/initrd.img-3.8.0-31-generic root=/dev/mapper/ssdsys-root ro quiet splash"

    Тут как раз-таки (почти) всё против описанных правил: путь к ram-диску через прямые слэши, отсутстие .efi расширения у ядра. Но! Всё работает! (по крайней мере на двух моих системах).
    Ровно так же можно игнорировать и требования про путь //EFI//vendor.
    Например, вполне рабочий вариант — монтировать efi-раздел на /boot. И тогда пути можно вообще указывать напрямую:

    efibootmgr -c -d /dev/sda -p 1 -l \\vmlinuz-3.8.0-31-generic -L "Ubuntu EFI" -u "initrd=/initrd.img-3.8.0-31-generic root=/dev/mapper/ssdsys-root ro quiet splash"

    (проверял! Работает!)
    Так получается меньше телодвижений в случае обновления ядра (по сути — обновить пункт меню и всё).

    Да, и ещё: в прошлой статье по теме была путаница по поводу записи параметров ядра в efibootmgr. Мол, это делает опция -u. На самом деле — нет. Параметры — это строка после всех опций. А -u всего лишь указывает, что она должна быть записана в nvram в юникоде (иначе ядро может и не понять).
    • +1
      Я уже писал выше: если бы все так советовали, как советуете вы, был бы хаос, какой сейчас и происходит с EFI.

      Предложу эксперимент: возьмите ванильное ядро версии ниже 3.8.0 и попробуйте там ваши прямые слеши. Думаю, вы удивитесь!
      Теперь возьмите среднестатистического юзера убунты, который ещё не обновился до последнего релиза и сидит на 3.5.0. Он этих тонкостей не знает, в случае проблемы в код ядра не полезет, он не знает существует ли там бэкпорт с этими чёртовыми слешами или нет. Он читает вашу статью, в которой написано, что на слеши — плевать. У него не получается. Не получается ещё у сотни. Из этой сотни появляется ещё один автор, который пишет свою статью с костылями, и так по рекурсии… В итоге «ваши эти интернетики» превращаются в мусорку. Разве это хорошо? Я так не считаю. Для чего тогда нужны стандарты? Чтобы пальцем в небо тыкать?

      То же самое с расширением .efi: вы уверены, что нет таких прошивок, которым плевать на расширение? Я вот не уверен. А сотни и тысячи людей, у которых они потенциально есть, прочитав статью, где все плевали на расширение, останутся в печали, что ничего не работает. И опять из этих кто-то выйдет, напишет статью, найдёт где-то ещё псевдо-причину, как с этими рам-дисками случилось…

      Путь к папке вендора в статье был в разделе общей информации. Там я не писал «должен», я написал «рекомендуется». По-моему, разница очевидна.

      Например, вполне рабочий вариант — монтировать efi-раздел на /boot.
      Верно, если вы не заметили, в статье это упоминается. Но почему не упоминается как единственно верный вариант?
      А проведём второй эксперимент: возьмём юзера с OpenSUSE и предложим ему проделать данную процедуру? Фейл! А почему? А потому что по умолчанию в этом дистрибутиве ядро и ещё пара файлов линкуются через символьную ссылку на /boot, а наш efi-раздел внезапно FAT32, который не поддерживает симлинки. Зачем этот вариант советовать всем, тем самым явно отсекая пользователей openSUSE (и, возможно, ещё каких-то дистрибутивов)?
      • 0
        Если вы чуть внимательнее посмотрите — я ничего не советую. Т.е. ВООБЩЕ ничего!
        Лишь констатирую факты.
        Да, эти факты основаны на «грязных хаках» — и поэтому им место не в статье, а _под_ статьёй, в комментариях. Собственно, там они и есть.

        А проведём второй эксперимент: возьмём юзера с OpenSUSE и предложим ему проделать данную процедуру? Фейл! А почему?


        А потому что — см. вторую строчку комментария!

        Нужно реально щупать, что да как, на конкретной системе.
  • +1
    Спасибо за статью, стало значительно понятнее, как с этим EFI все устроено.
    Еще было бы интересно почитать про Secure Boot и загрузчики :)
  • 0
    Было бы здорово почитать туториал/статью на тему программирования EFI-приложения. Написание тетриса какого-нибудь, например.
  • 0
    загрузчик UEFI делает очень просто: он перебирает все подряд разделы и диски и ищет один особенный.


    Интересно, что происходит, когда на каждом из четырех дисков присутствует первый раздел «EFI boot».
    • 0

      А ничего — например, на серверах Dell это работало так:


      • ставим ОС
      • клонируем раздел с EFI на другие диски
      • для каждого раздела в EFI создаем ссылку на EFI-загрузчик на этом разделе
      • при загрузке EFI выбирает загрузчик из списка согласно заданных приоритетов
      • 0
        На интеловском сервере я сделал так же. Из описанной в статье логике работы EFI следует, что не обязательно делать записи в EFI. Вот мне и интересно, так ли это.
        • 0

          В теории grubx64.efi содержит всё необходимое для нахождения основного загрузчика и его загрузки.
          Я в ближайшее время проверить не смогу (сервера боевые и далеко), но по идее, достаточно просто расклонировать раздел с EFI-загрузчиком, а дальше Grub сам разберется что к чему.

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