Как я научился напрямую перезагружаться в нужную ОС через UEFI

  • Tutorial

Добрый вечер, Habrahabr!


Сегодня мы научимся перезагружаться из Linux прямиком в Windows и обратно всего за один (двойной) клик.


image


Дано:


  • Два диска с GPT с разными ОС
  • Материнская плата с UEFI и отключеным Legacy Mode
  • Windows, которую бережно поставили с полной поддержкой UEFI
  • Linux (у меня Manjaro), который бережно поставили, выпилив любое упоминание GRUB и прочих старомодных вещей
  • rEFInd — красивый менеджер загрузки (нет, не загрузчик)

Надо:


  • Написать два скрипта на *sh и cmd (bat), которые позволят перезагрузиться в нужную ОС

Примечания:


  • Рабочие варианты обозначены, как Решение, остальное — мои рассуждения и описание пути к цели.
  • Я сознательно опускаю описание тех деталей, которые не относятся к сути настройки, либо легко варьируются. Упоминаются же эти детали потому, что для меня они не были очевидны на момент настройки, поэтому статья становится более понятной для неискушенных читателей, которые не будут видеть в ней инструкцию по рисованию совы.
  • Почему стоит быть осторожным при модификации NVRAM

Linux:


Linux is your bro
Linux — прекрасная база для работы с компьютером, поэтому всё, что нам нужно уже есть в репозиториях, а коллективный разум сообщества знает всё и всегда готов помочь. Поэтому, после недолгого изучения интернета, ставим efibootmgr:


У меня это было так
sudo pacman -S efibootmgr

Отлично, теперь запускаем:


sudo efibootmgr

Видим что-то вроде этого
Timeout: 1 seconds
BootOrder: 0001,0000
Boot0000* Windows Boot Manager
Boot0001* rEFInd Boot Manager

Внимательные читатели уже наверняка заметили, что в выводе что-то не так, но тогда я был окрылён мыслью о том, что через 15 минут буду летать между операционками без проблем, и не обратил на это должного внимания.
Ок, 3 минуты на документацию, и мы находим нужный параметр "-n", который выставляет кастомый порядок загрузки ровно на один раз. Пробуем выполнить эту команду:
Решение


sudo efibootmgr -n 0000 && sync && reboot

И оказываемся в Windows, как того и желали. Теперь эту команду записываем в скрипт/alias/*.desktop-файл и радуемся тому, как всё здорово получилось.


Windows:


Typical Windows
Началось всё с поиска аналога efibootmgr для Windows, которого в чистом виде, конечно же, нет. Для успокоения совести я даже попытался использовать Linux Subsystem, но это, конечно же, не сработало.
Беглый поиск по интернетам показал, что схожим функционалом по модификации NVRAM обладает утилита bcdedit. Отлично, думаю я, запускаю PowerShell из-под Администратора и пишу


bcdedit /enum firmware

Вот что я увидел

Firmware Boot Manager
---------------------
identifier              {fwbootmgr}
displayorder            {6893bb38-946b-11e7-b175-9301bd8a88f4}
                        {bootmgr}
timeout                 1

Windows Boot Manager
--------------------
identifier              {bootmgr}
device                  partition=\Device\HarddiskVolume2
path                    \EFI\Microsoft\Boot\bootmgfw.efi
description             Windows Boot Manager
locale                  ru-RU
inherit                 {globalsettings}
default                 {current}
resumeobject            {6893bb40-946b-11e7-b175-9301bd8a88f4}
toolsdisplayorder       {memdiag}
timeout                 30

Firmware Application (101fffff)
-------------------------------
identifier              {6893bb38-946b-11e7-b175-9301bd8a88f4}
device                  partition=\Device\HarddiskVolume2
path                    \EFI\REFIND\REFIND_X64.EFI
description             rEFInd Boot Manager

Где Linux? Куда грузиться? Ненавижу винду
На самом деле оказалось, что виновата не Windows, а я (да-да, тот самый момент для внимательных пользователей), и вот почему: rEFInd — прекрасная утилита, которая обычно, для корректной работы, требует только установить себя. Она умеет подхватывать все .efi файлы, разные дистрибутивы с разными ядрами, сама подставляет иконки. Прелесть, а не инструмент. Но это сыграло со мной злую шутку, так как оказалось, что UEFI ничего не знает про Linux, так как отсутствует соответствующий ему .efi-файл.
Поэтому презагружаемся обратно в Linux, конфигурируем systemd-boot (bootctl). Теперь всё выглядит вот так:


Timeout: 1 seconds
BootOrder: 0001,0003,0000,0002
Boot0000* Windows Boot Manager
Boot0001* rEFInd Boot Manager
Boot0002* Linux Boot Manager
Boot0003* Manjaro

Возвращаемся обратно и снова запускаем.


bcdedit /enum firmware

Вот что я увидел теперь

Firmware Boot Manager
---------------------
identifier              {fwbootmgr}
displayorder            {6893bb38-946b-11e7-b175-9301bd8a88f4}
                        {bootmgr}
                        {ff0bc716-c088-11e7-bf74-000acd2dac7d}
                        {ff0bc716-c088-11e7-bf74-000acd2dac7d}
timeout                 1

Windows Boot Manager
--------------------
identifier              {bootmgr}
device                  partition=\Device\HarddiskVolume2
path                    \EFI\Microsoft\Boot\bootmgfw.efi
description             Windows Boot Manager
locale                  ru-RU
inherit                 {globalsettings}
default                 {current}
resumeobject            {6893bb40-946b-11e7-b175-9301bd8a88f4}
toolsdisplayorder       {memdiag}
timeout                 30

Firmware Application (101fffff)
-------------------------------
identifier              {6893bb38-946b-11e7-b175-9301bd8a88f4}
device                  partition=\Device\HarddiskVolume2
path                    \EFI\REFIND\REFIND_X64.EFI
description             rEFInd Boot Manager

Firmware Application (101fffff)
-------------------------------
identifier              {ff0bc716-c088-11e7-bf74-000acd2dac7d}
device                  partition=\Device\HarddiskVolume2
path                    \EFI\SYSTEMD\SYSTEMD-BOOTX64.EFI
description             Linux Boot Manager

Firmware Application (101fffff)
-------------------------------
identifier              {ff0bc717-c088-11e7-bf74-000acd2dac7d}
device                  partition=\Device\HarddiskVolume1
path                    \EFI\manjaro\vmlinuz-4.13-x86_64
description             Manjaro

Тут стоит упомянуть, что проблему мне помогали решать пользователи reddit. Именно благодаря им мы имеем следующий шаг:


bcdedit /bootsequence {ff0bc716-c088-11e7-bf74-000acd2dac7d}

Где аргументом является identifier необходимого варианта — Linux Boot Manager.


Troubleshooting

Powershell не даёт нормально выполнить эту команду, ругаясь на


The entry list data is not valid as specified.

Всё из-за того, что Microsoft периодически любит что-нибудь сломать. Решение просто и элегантно — вызываем классический CMD и работаем в нём. Это можно сделать командой


cmd

Перезагружаемся и видим, что порядок загрузки не изменился, а мы оказались в первом элементе в BootOrder (у меня это был rEFInd), выбираем Windows и видим страшный привет из времен DOS, который говорит нам, что \EFI\SYSTEMD\SYSTEMD-BOOTX64.EFI не найден. Да, мы изменили параметры загрузчика Windows, но не UEFI.
Борьба с этой ошибкой заняла у меня все праздники, но ничего путного не получалось. Я уже подумывал написать на C++ небольшую программку для этого (то, что это возможно, следует из существования такого софта, как EasyUEFI).
Но тут на очередном сайте я обнаружил вот такую конструкцию


 bcdedit /set {bootmgr} path ....

И тут меня осенило, что можно прямо сказать bcdedit что и куда писать. Дальше стоило только проверить догадку:
Решение


bcdedit.exe /set {fwbootmgr} bootsequence {ff0bc716-c088-11e7-bf74-000acd2dac7d} /addfirst

Тут важно, что мы явно сказали писать не в {bootmgr} (как он, видимо, делает по-умолчанию), а в {fwbootmgr}, что и является нашими настройками UEFI.
Перезагружаемся, и всё работает так, как мы этого хотели. Сохраняем это дело в bat/lnk, дописываем


shutdown /r /t 0

Выставляем запуск из-под администратора и готово!
Спасибо за внимание! Буду крайне рад замечаниям по технической части в комментариях, замечаниям по оформлению — в ЛС.

Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 40
  • 0
    А что у вас будет когда Linux проапгрейдит версию ядра?
    • 0
      Без моего ведома он этого не сделает. А так — поменяю версию в конфиге systemctl-boot. Когда-нибудь напишу для этого pacman hook
    • +4
      Для полноты картины было бы неплохо включить в tutorial Mac OS X, установленную на ПК с UEFI-загрузчиком (Clover). Тогда тема, пожалуй, была бы раскрыта полностью. ;-)
      • 0
        Была такая мысль, но на MacBook, так как macOS тоже не имеет efi-файлов, которые можно легко подцепить (по крайней мере, на самый первый взглял).
        Думаю, что в ближайшее время отпишусь либо тут, либо в новой статье :)
      • +3
        bcdedit /bootsequence {ff0bc717-c088-11e7-bf74-000acd2dac7d}

        Где аргументом является identifier необходимого варианта — Linux Boot Manager.

        Согласно выводу bcedit выше, {ff0bc717-c088-11e7-bf74-000acd2dac7d} — это не Linux Boot Manager, а само ядро. У Linux Boot Manager UID отличается на единичку: {ff0bc716-c088-11e7-bf74-000acd2dac7d}

        Но я не понимаю, зачем вам одновременно Refind, Linux Boot Manager и само ядро, которое тоже efi-enabled. Из этих трех два можно выбросить.
        А учитывая что Refind умеет грузить и загрузчик винды — можно было бы обойтись только им. Не надо трогать NVRAM каждый раз, достаточно править конфиг refind. Я думаю, это можно легко сделать и из линукса и из винды.
        К тому же я, слышал что есть платформы, где использование bcdedit/efibootmgr может привезти к окирпичиванию всей системы.
        • 0
          По поводу зачем я постарался встать на место автора в комментарии соседней ветки.
          Да, nvram дергать конечно такое себе, но refind предлагает только параметр default_selection (при первом приближении, может быть есть что-то еще), но сначала все равно грузится рефинд, считает таймаут и только потом грузится.
          Да и правка скриптом конфига из под винды тоже занятие — примонтируй EFI как диск, еще и возможностью записи, найди параметр, замени его :)
          • 0
            1. Абсолютно согласен, где-то промахнулся с копипастой.
            2. rEFInd — красивое меню для выбора того, что мне нужно загрузить. С Linux Boot Manager и ядром — сложнее. Пожалуй, эта система выглядит избыточно, но я нигде даже и не пытался претендовать на инструкцию по конфигурации системы, я лишь описал способ целевой перезагрузки и решения связанных проблем, более того с Linux Boot Manager я могу не волноваться за наличие ядра с нужным именем в нужном месте.
            3. Вы, видимо, не поняли смысл моих манипуляций. А он в том, чтобы иногда(!) пропускать rEFInd и грузиться туда, куда надо, пока я себе наливаю чай.
            4. Думаю, что эти слухи из разряда баек, появившихся в тёмные времена, когда производители клали на стандарт UEFI
            • +7
              1. Думаю, что эти слухи из разряда баек, появившихся в тёмные времена, когда производители клали на стандарт UEFI

              Эти темные времена — они были всегда и будут всегда, так что это не слухи, а суровая реальность.
              Дело там вот в чем: efibootmgr сам по себе ничего не ломает, особенно если менять только переменную BootOrder, как это описано в статье. А вот если пытаться создавать новые записи для загрузчиков или переписывать уже имеющиеся, придется, кроме всего прочего, конструировать EFI DevicePath, и вот здесь у нас получается бомба, поскольку правильность DevicePath зависит от текущей прошивки, и реакция на неправильный также зависит от прошивки. Иногда угадать формат получается и все проходит хорошо, а в других случаях не получается, и восстановление из такого состояния может быть как безболезненным (у AMI Aptio, к примеру), так и очень неприятным (Phoenix SCT), а иногда и вовсе практически смертельным для прошивки (старые Insyde H2O).
              Короче: доверьте управление загрузочными устройствами самой прошивке, она точно знает, как именно создать правильные записи BootXXXX так, чтобы ничего не сломалось. Да, это баг в реализации, и в последнее время он встречается не очень часто, но лучше не испытывать судьбу.

              • 0
                Спасибо за ликбез, добавил предупреждение в статью.
              • 0
                3. Вы, видимо, не поняли смысл моих манипуляций. А он в том, чтобы иногда(!) пропускать rEFInd и грузиться туда, куда надо, пока я себе наливаю чай.
                Мне помнится, в каком-то из Линуксов в меню завершения работы были варианты перезагрузиться в другие ОС — и оно работало (и это было до UEFI).
                • 0
                  Тоже помню такое. Если не ошибаюсь — где-то в районе Кубунту 13.
                  • 0

                    Существует большая техническая проблема по возвращению состояния железа в первоначальное состояние. ОС которая грузится второй ожидает, что управление пришло из legacy bios или uefi и строит на этом основании необоснованные выводы. Примером может служить отлучение usb контроллера от биоса. Первоначально он сидит на SMI работы с клавой, а после первая ось его забирает на себя, неявно отключая SMI хуки. Вторая ось найдет контроллер в необычном состоянии и может запаниковать. Проблема относится не только к ядру, но и к некоторым внешним драйверам.

                  • 0
                    Если вдруг интересно, вот как автор rEFInd ответил на мой вопрос о том, как выбирать дефолтную ОС при запуске:
                    Yes, you can adjust the PreviousBoot variable with UUID
                    36d08fa7-cf0b-42f5-8f14-68df73ed3740. That's how rEFInd remembers what
                    the previously-booted OS was. You'll need to set the value to a unique
                    substring of the description that's shown in rEFInd — for instance,
                    «Windows» for Windows or «vmlinuz» for Linux (if you're booting a kernel
                    directly).

                    You can adjust this variable in Linux by editing the
                    /sys/firmware/efi/efivars/PreviousBoot-36d08fa7-cf0b-42f5-8f14-68df73ed3740
                    or files under
                    /sys/firmware/efi/vars/PreviousBoot-36d08fa7-cf0b-42f5-8f14-68df73ed3740/.
                    I don't know offhand how you'd do this in Windows, OS X, or any other OS.
                    • 0
                      То есть мы всё равно модифицируем NVRAM, только без специальных утилит? Это решение лучше в плане отсутствия лишних сущностей, но выглядит даже страннее
                • +3
                  Что вообще хотел сказать автор?
                  Ставил TrueOS (FreeBSD + Lumina) и Linux на один ЖД (UEFI + GPT). TrueOS ставит rEFInd в качестве среды загрузки. Обе системы грузятся. Обновлял Linux — всё равно грузятся. Подключал внешний ЖД и флэшку — грузился с них.
                  ЧЯДНТ?

                  Картинка с википедии подсказывает, что и Мак и винда тоже работают.
                  Для настройки загрузки лучше использовать саму rEFInd — там есть соответствующее меню.
                  В предыдущей записи lorc правильно указывает, что игры с NVRAM могут окирпичить устройство.

                  image

                  • +6
                    Полагаю, идея была в том, чтобы скриптом перезагрузиться из одной системы в другую напрямую, пропуская промежуточный шаг в виде rEFInd, а его оставить в качестве меню при первом включении устройства.
                  • 0
                    То есть при загрузке компа с нуля мы сначала загрузимся в rEFInd, который тут же загрузит нам линукс?

                    А как быть с консолью восстановления, если что-то пошло не так? А если еще систему захочется установить?
                    И еще к чему фраза про два gpt-шных диска?
                    • 0
                      Я нигде не пытался избавиться от rEFInd, как сказал выше, «Вы, видимо, не поняли смысл моих манипуляций. А он в том, чтобы иногда(!) пропускать rEFInd и грузиться туда, куда надо, пока я себе наливаю чай.»
                      GPT — для корректной работы с UEFI. Слышал, что сейчас уже это необязательно, но очень желательно.
                    • +1
                      Извиняюсь за оффтопик, но раз уж вы поделились опытом, хочется узнать побольше из первых рук…
                      1. Насколько быстро это все происходит лично у вас? Понимаю, что железо критично, предположим, что у меня 2 быстрых SSD диска. Мне важны не секунды, а личные впечатления, удобно ли прыгать между системами?
                      2. Пробовали ли совместить это с гибернацией?
                      3. Как у вас реализован обмен файлами между ОС? Linux монтирует NTFS, а в обратном направлении как? (Я не пользователь Windows, извините, если вопрос глупый).
                      Я бы и сам все попробовал, но, прежде чем покупать Windows, хочется понять, стоит ли игра свеч… Мне вообще от винды нужны только Photoshop и Illustartor.
                    • 0
                      У меня есть разделение рекреационной Windows и рабочего Linux, поэтому в плане непрерывной работы я Вам не советчик, но, при написании этой статьи, перезагружался несколько раз, что сильного дискомфорта не вызывало, тк рабочая область была в браузере.
                      1. На моём процессоре 7700K, 2 SDD (KINGSTON SV300S37A120G — Windows 10, KINGSTON SA400S37240G — Manjaro Linux с Gnome 3). Проходит примерно 20-25 секунд (без учёта таймаута самого UEFI, который можно выставить в 0) от нажатия Enter до экрана логина второй ОС.
                      Если прыгать во время работы, то, конечно, не так удобно, так как пропадает сессия (ниже пишу про гибернацию) и приходится логиниться.
                      2. Linux не умеет подхватывать NTFS (системный, остальные норм) с гибернированной виндой, с Linux не тестировал
                      3. У каждой ОС по 1Tb HDD + виндовый монтирую в Linux. Под винду есть несколько реализаций ext* дров, 2-3 поддерживается нормально, бесплатных и адекватных для ext4 не нашел. Есть платная утилита от Paragon, но ей я пользовался только в версии для macOS, поэтому из своего опыта ничего не скажу (там работает прекрасно, да и компания, вроде, уважаемая).
                      По Вашему софту — не работаю с ним и не знаю, как он ведет себя под тем же wine, чтобы однозначно посоветовать.
                      В любом случае, у Windows есть trial в 30 дней, а до 2018года есть возможность обновить
                      _
                      крякнутую
                      лицензионную Vista — 7 до 10 с получением лицензии

                      • 0
                        1. Linux не умеет подхватывать NTFS (системный, остальные норм) с гибернированной виндой, с Linux не тестировал

                        Сталкивался с проблемой для восьмерки и десятки при настройках по умолчанию.
                        Если виндовс завершался "выключением", линукс не мог монтировать ни один из NTFS разделов с возможностью записи. Если перезагрузкой, то все нормально.
                        Лечилось отключением в виндовс "быстрой загрузки" (не помню, какие параметры там надо было править.
                        Также пришел к выводу, что системные разделы лучше из другой системы без крайней необходимости не трогать, а завести отдельный раздел для обмена. Я делал его NTFS. FAT, конечно, лучше в плане поддержки разными системами, но лимит в 4Г создает неудобство и потери времени на разделение/сборку больших файлов с копированием данных на раздел с более другой файловой системой.

                        • 0
                          Действительно, в Win8+ система автоматически гибернируется при выключении.
                        • 0

                          Минимум — 7, а не Vista.

                        • 0
                          А как с помощью bcdedit добавить бут запись? Заранее спасибо!!!
                          • 0
                            Тут сказано, почему этого делать не стоит. Там же правильный путь.
                            • 0
                              Мне нужно, что бы именно в винде можно было добавить бутзапись(Я пишу программу, которая это будет делать).
                          • +1
                            В загрузку можно установить EFI Shell и загружать любую ОС стартовым скриптом с помощью одной команды EFI Shell. В некоторых UEFI БИОС EFI Shell присутствует штатно, если нет, то ее можно установить отдельно, как любой другой загрузчик.
                            При этом задачей скрипта в ОС для переключения загрузки станет переименование/копирование нового загрузочного скрипта для EFI Shell, в котором будет прописана загрузка другой ОС — а это обычная файловая операция, которая не грозит никакими последствиями для загружаемой ОС.
                            Остается только смонтировать EFI раздел, чтоб можно было работать с файлами. В Windows это можно сделать с помощью стандартной утилиты diskpart, наверняка и в линуксе есть варианты.
                            • +1

                              Тема интересная, как раз хотел заняться этим, и тут ваша статья.
                              А по поводу обмена файлами между операционками, я как раз статью недавно опубликовал: https://habrahabr.ru/post/341042/

                              • 0
                                Я новичок в использовании linux, хотел бы упростить загрузку/перезагрузку в другие ОС убрав grub, статья и комментарии помогли понять суть и принцип настройки. Но есть вопрос, я использую дополнительные настройки параметров ядра linux, которые пишутся в /etc/default/grub > GRUB_CMDLINE_LINUX_DEFAULT= (включил гибернацию в swap-файл), смогу ли я могу реализовать ту же функцию (или подключать другие стартовые параметры ядра) если выпилю grub и заменю его тем же rEFInd? Развёрнутого ответа или алгоритма решения не прошу, но хотелось бы узнать от старших коллег в какую сторону копать и стоит ли вообще заморачиваться с этим.
                                • 0
                                  Да, конечно. Параметры запуска прописываются как в конфиге rEFInd, так и в конфиге systemctl-bool. Единственное, здесь уже придётся самому писать menuentries.
                                  Из собственного опыта: по подавляющему большинству вопросов стоит копать на англоязычной ArchWiki
                                • 0
                                  Хм, а есть ли возможность сделать переключение между windows — windows?
                                  К примеру у меня вторая система установлена на vhd том.
                                  • 0
                                    По-идее достаточно подставить нужный идентификатор. Главные требования: UEFI, UEFI(non-lagacy) Windows installation
                                  • 0
                                    А Kali Linux и 8.1 будут так работать в переключении?
                                  • –1
                                    А вторую систему из под Linux запустить в VM?
                                    И ничего делать лишнего уже не придётся.
                                    • +1

                                      Часто это является исчерпывающим решением, но случаи бывают разные.
                                      Навскидку: недостаточно ОЗУ и/или ядер процессора, чтобы поднять виртуалку с достаточным количеством ресурсов; прямая работа с устройствами (далеко не все железо корректно пробрасывается в виртуалку).

                                      • 0
                                        Использую Windows исключительно для игр

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