Добрый вечер, Habrahabr!
Сегодня мы научимся перезагружаться из Linux прямиком в Windows и обратно всего за один (двойной) клик.
Дано:
- Два диска с GPT с разными ОС
- Материнская плата с UEFI и отключеным Legacy Mode
- Windows, которую бережно поставили с полной поддержкой UEFI
- Linux (у меня Manjaro), который бережно поставили, выпилив любое упоминание GRUB и прочих старомодных вещей
- rEFInd — красивый менеджер загрузки (нет, не загрузчик)
Надо:
- Написать два скрипта на *sh и cmd (bat), которые позволят перезагрузиться в нужную ОС
Примечания:
- Рабочие варианты обозначены, как Решение, остальное — мои рассуждения и описание пути к цели.
- Я сознательно опускаю описание тех деталей, которые не относятся к сути настройки, либо легко варьируются. Упоминаются же эти детали потому, что для меня они не были очевидны на момент настройки, поэтому статья становится более понятной для неискушенных читателей, которые не будут видеть в ней инструкцию по рисованию совы.
Linux:
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:
Началось всё с поиска аналога 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=DeviceHarddiskVolume2
path EFIMicrosoftBootbootmgfw.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=DeviceHarddiskVolume2
path EFIREFINDREFIND_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=DeviceHarddiskVolume2
path EFIMicrosoftBootbootmgfw.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=DeviceHarddiskVolume2
path EFIREFINDREFIND_X64.EFI
description rEFInd Boot Manager
Firmware Application (101fffff)
-------------------------------
identifier {ff0bc716-c088-11e7-bf74-000acd2dac7d}
device partition=DeviceHarddiskVolume2
path EFISYSTEMDSYSTEMD-BOOTX64.EFI
description Linux Boot Manager
Firmware Application (101fffff)
-------------------------------
identifier {ff0bc717-c088-11e7-bf74-000acd2dac7d}
device partition=DeviceHarddiskVolume1
path EFImanjarovmlinuz-4.13-x86_64
description Manjaro
Тут стоит упомянуть, что проблему мне помогали решать пользователи reddit. Именно благодаря им мы имеем следующий шаг:
bcdedit /bootsequence {ff0bc716-c088-11e7-bf74-000acd2dac7d}
Где аргументом является identifier необходимого варианта — Linux Boot Manager.
Powershell не даёт нормально выполнить эту команду, ругаясь на
The entry list data is not valid as specified.
Всё из-за того, что Microsoft периодически любит что-нибудь сломать. Решение просто и элегантно — вызываем классический CMD и работаем в нём. Это можно сделать командой
cmd
Перезагружаемся и видим, что порядок загрузки не изменился, а мы оказались в первом элементе в BootOrder (у меня это был rEFInd), выбираем Windows и видим страшный привет из времен DOS, который говорит нам, что EFISYSTEMDSYSTEMD-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
Выставляем запуск из-под администратора и готово!
Спасибо за внимание! Буду крайне рад замечаниям по технической части в комментариях, замечаниям по оформлению — в ЛС.
Автор: Иван Пискунов