LINUX.ORG.RU

initcpio hooks: как добавить устройства в /dev/disk

 


0

1

Покажу фрагмент кода:

run_hook() {
  local os_root="$(find_root)"
  # echo $os_root
  # IFS='=' read -r root_partname root_partid <<< "$os_root"
  local opal_drives="$(list_opal_drives)" drive passphrase
  until [ "$(findfs "$os_root" 2> /dev/null)" ]; do
    printf "Enter Passphrase to Unlock OPAL Drives: "
    read -s passphrase
    echo
    for drive in $(list_opal_drives); do
      if check_opal_locked "$drive"; then
        unlock_opal_drive "$drive" "$passphrase"
      fi
    done
  done
}

В find_root я парсю параметры ядра, извлекаю root. В моем случае это PARTUUID=74ed86c1-539b-d14d-b7d4-38681f4227fb.

Разблокировка диска выглядит так:

unlock_opal_drive() {
  sedutil-cli --setLockingRange 0 rw "$2" "$1" \
    && sedutil-cli --setMBRDone on "$2" "$1" \
    && partprobe "$1"
}

Partprobe повторно сканирует устройство после разблокировки и находит на нем разделы. Но ссылки типа /dev/disk/by-label/%LABEL_NAME% создаются как я понимаю udev, и по этой причине findfs у меня не срабатывает… Вопрос: как эти симлинки создать вручную. И еще один вопрос: а можно ли как-то поймать ошибку монтирования корневой системы, узнать что она не смонтировалась через хуки? Монтировка в filesystems происходит же и дальше хуки не выполняются, если какой-то падает?


Ответ на: комментарий от kostik87

Ничего лучше не придумал…

~
❯ cat /usr/lib/initcpio/hooks/unlock-root-sed
#!/usr/bin/ash

list_sed_drives() {
  sedutil-cli --scan 2> /dev/null \
    | head -n -1 \
    | tail -n+2 \
    | awk '{if ($2 == 2) print ($1 ~ /nvme/) ? $1 "n1" : $1}'
}

is_sed_locked() {
  sedutil-cli --query "$1" | grep 'Locked = Y' > /dev/null
}

unlock_sed() {
  sedutil-cli --setLockingRange 0 rw "$2" "$1" \
    && sedutil-cli --setMBRDone on "$2" "$1" \
    && partprobe "$1"
}

run_hook() {
  root_sed="${root_sed:-$(list_sed_drives | head -1)}"
  local passphrase
  while is_sed_locked "$root_sed"; do
    read -sp "SED Passphrase: " passphrase
    echo
    unlock_sed "$root_sed" "$passphrase"
  done
}

~
❯ sudo -e /etc/mkinitcpio.conf                 
sudo: /etc/mkinitcpio.conf unchanged

~ 14s
❯ cat /usr/lib/initcpio/install/unlock-root-sed
#!/bin/ash

build() {
  add_binary "sedutil-cli"
  add_runscript
}

help() {
  cat <<HELP
This hook unlock root SED TCG Opal 2.0 drive. Use the kernel parameter 'root_sed' to specify a drive.
HELP
}

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

uwuwuu
() автор топика

Partprobe повторно сканирует устройство после разблокировки и находит на нем разделы. Но ссылки типа /dev/disk/by-label/%LABEL_NAME% создаются как я понимаю udev, и по этой причине findfs у меня не срабатывает… Вопрос: как эти симлинки создать вручную.

зачем их создавать вручную? если можно передернуть сам udev, и он пересоздаст.

$ udevadm trigger

только надо не забыть сделать

$ udevadm settle

после этого. иначе есть риск, что пока оно будет процесситься в фоне, твой скрипт отработает раньше, чем они появятся.

n_play
()
Ответ на: комментарий от n_play

Да. Это гиблая идея. У меня корень на самошифрующемся диске, а чтобы узнать на каком нужно все UUID считать с разблокированного диска, чтобы findfs работала как надо… А превопричина в том, что BIOS материнок от ASUS и Acer удаляет Boot записи после отключения устройства, когда диск переходит в залоченное состояние, то для прошивки - это равно его физическому отсоединени, те для неее залоченный и разлоченный диск - два разных устройства. Если нет загрузочных записей, то материнка начинает искать в порядке приоритета загрузчики Windows, а потом грузит BOOTX64.EFI, иными словами при Dualboot ВСЕГДА БУДЕТ ГРУЗИТЬСЯ ВИНДА, с виндой я распрощаться не могу, так wine падает с ошибками при запуске моих игорей. И тут два решения: перенести загрузочный раздел на другой диск, либо оставить на зашифрованном и таким вот костылем подменять загрузчик винды на линуксовый:

#!/bin/bash
systemd_efi=systemd/systemd-bootx64.efi
windows_efi=Microsoft/Boot/bootmgfw.efi

cd /boot/EFI

if cmp --silent -- "$systemd_efi" "$windows_efi"; then
  echo "efi files are same" >&2
  exit 1
fi

# Переим. bootmgfw.efi -> bootmgfw_.efi
mv "$windows_efi" "$(sed 's/\.efi$/_\0/i' <<< "$windows_efi")"

# Подменяем загрузчик Windows
cp "$systemd_efi" "$windows_efi"
uwuwuu
() автор топика
Последнее исправление: uwuwuu (всего исправлений: 1)
Ответ на: комментарий от uwuwuu

Вообще-то нет.

UEFI по-умолчанию, если нет других вариантов, грузит именно BOOTX64.EFI. Поскольку он у тебя от Microsoft Windows логично, что он вызывает bootmgfw.efi (или сам – достоверно этот момент не описан/ я не встречал) для загрузки именно Microsoft Windows.

Тот же grub «помещает» себя по умолчательному пути, как BOOTX64.EFI – иначе «магии не будет».

Если systemd-bootx64.efi умеет в дуалбут или чайнлоадинг, то план такой

  • оригинальный BOOTX64.EFI переименовывается
  • на его «место» копируется systemd-bootx64.efi с именем BOOTX64.EFI
  • конфиг загрузки правится // если это возможно и необходимо

Именно с systemd-boot я дел не имел. Но остальное только в таком варианте наименее проблемное в реализации.

master_0K
()
Ответ на: комментарий от master_0K

Нет. Все именно так как я описал. Windows вообще этот BOOTX64.EFI не трогает, там лежит тож самое что systemd-boot или grub. Там захардкожено это. ОН отыскивает винду, прописывает ее в NVRAM и грузится в нее, если ее не находит, то грузит BOOTX64, я думаю это FREEDOS там по-умолчанию располагается. Те ноуты идут с виндой либо фридосом, а чтобы лишнюю манипуляцию не совершать с прописыванием меню загрузчика, там сделано так

uwuwuu
() автор топика
Ответ на: комментарий от uwuwuu

((

Я «промахнулся»:

  • используется BOOTX64.EFI, именно когда доступных других вариантов (записей о загрузчиках) нет – у тебя остается загрузочная запись Windows
  • в описанном мною варианте манипулирование записями осталось за кадром, а без него обойтись не могло

С фридосом … Здесь промолчу, т.к. реально его не «тыкал».

master_0K
()
Последнее исправление: master_0K (всего исправлений: 1)
Ответ на: комментарий от master_0K

А почему винда в приоритете первой добавлятся… Я думаю есть какие-то модели, где стоят одноврменно Windows и UEFI Shell, который тоже BOOTX64.EFI, а винда по этой же причине этот файл собой не подменяет. Короче, производители ноутов экономят даже на операции добавления загрузочных записей, поэтому в прошивку свою захардкодили автоматический поиск EFI и добавление записей

uwuwuu
() автор топика
Ответ на: комментарий от uwuwuu

В моём текущем ноутбуке не было ничего: при включении он просто грузился в «SETUP».

Добавление записей на лету (в какой-то мере и удаление тоже) необходимо для работы внешних носителей-установщиков ОС (как минимум).

Загрузка /efi/boot/BOOTX64.EFI захоркоджена (при условиях*) в этом все сходятся. Чем он является? Интересный вопрос, ответ я не знаю. Странно даже, что раньше не задался этим вопросом.

UEFI Shell может быть отдельным приложением (как минимум один раз видел). Совет переименовать UEFI Shell в /efi/boot/bootx64.efi содержится ArchWiki – в таком ключе я и написал первое своё сообщение (очень «кривое») в этой теме. Кстати, там же упоминается проект позволявший из Биоса грузится в UEFI (его разработчики удалили в 2018).

Спецификация UEFI ясности не вносит: boot manager (видимо и умолчательный /efi/boot/bootx64.efi также классифицируется) начинает загрузку…

Посмотри раздел 8. Решение проблем, подраздел 8.6 Windows изменяет порядок загрузки. Возможно, что-то из описанных «механик» сочтешь допустимым.

master_0K
()
Ответ на: комментарий от master_0K

ты не понял смысла темы.

  • есть диск с аппаратным шифрованием
  • у диска два состояния: залоченное, когда доступна небольшая область в 128MiB, и обычное тут у нас в доступе весь диск (кроме этих 128 мегабайт)
  • есть какой-то биос/uefi на ноутах/материнках от acer. его особенность в том, что там записи в nvram удаляются сразу же после отключения устройства
  • когда диск переходит в залоченное состояние, то для прошивки материнки он исчезает, словно его вытащили (ну там и по факту два диска на 128 MiB и 500 GB), и она трет все записи, которые ассоциируются с ним
  • когда мы вводим пароль и перегружаемся, то никаких загрузочных записей нет, и прошивка начинает сканировать файловую систему разделов с FAT в поиске bootmgfw.efi либо bootx64.efi, когда она их находит, то добавляет записи в nvram. У винды приоритет выше, поэтому она грузится всегда

Мое решение заключается в замене bootmgfw.efi на линуксовы efi, тогда вместо винды у меня по умолчанию грузится менюшка, где можно выбрать что грузить линукс или винду.

Тут вся проблеме в прошивке, в UEFI или в BIOS (хотя мож и неправильно так называть, но все так говорят). У других производителей запоминаются, например, 10 загрузочных записей, и после переполнения «стека», последние удаляются, а новые в конец вставляются. Еще есть бивисы, где можно тупо прописать из какого файла по умолчанию грузиться, если нет никакиъ записей, например, \EFI\BOOT\BOOTX64.EFI. Это специфическая проблема для конкретной прошивки конкретного производителя. Даже не так, а производителей с Тайваня, которые заказывают свои ноуты где-то в Китае на заводе. Всякие Lenovo, Acer, Asus - это ноуты с одного завода, с одной компоновкой, у них отличается только гравировка и наклейка. И прошивки у них часто одинаковые, а точнее какую там они по лицензии купили, ту и записывают в чип

uwuwuu
() автор топика
Ответ на: комментарий от uwuwuu

Я не знаю мож эту проблемку небольшую можно было бы решить заменой UEFI на Coreboot, если бы он поддерживался…

https://www.coreboot.org/status/board-status.html

А так как у меня программатора нет, то с флешем не поиграешься

uwuwuu
() автор топика
Ответ на: комментарий от uwuwuu

Скорее я просто не смог толком объяснить свои предложения.

Запись и загрузчики Windows присутствуют в описанной тобой ситуации постоянно. Поэтому, «прошивка UEFI» и передаёт управление загрузчику Windows. После чего грузится Windows. (Я так вижу ситуацию).

Поэтому я и предлагал подменить загрузчик Windows на тот, который контролируешь ты. Пока при запуске не будет стартовать «твой» загрузчик «винду» не остановить.

В WikiArch предложили довольно красивое решение: изменить загрузочную запись Windows так, чтобы загрузчик «винды» запускал что-то другое, но не саму ОС Микрософта. Делается это средствами самой «винды». Я бы добавил ещё одну запись для загрузки «винды», активную модифицировал для запуска systemd-bootx64.efi (или любого другого контролируемого тобой загрузчика).

Если вдруг есть в прошивке твоего компьютера UEFI Shell, то это тоже вариант:

  • его можно установить в оболочке Setup firmware (то, что раньше было оболочкой биоса) первым в очереди на загрузку
  • по умолчанию он ищет файл сценария/скрипта с заданным именем по заданному пути
    • отрабатывает его или переходит в интерактивный режим, когда сценария нет
master_0K
()
Ответ на: комментарий от uwuwuu

Старт «своего» загрузчика только первая фаза. Она предотвращает немедленный старт Windows.

Вторая фаза настойка «своего» загрузчика:

  • он должен, дождаться когда «появиться» диск
  • загрузить ОС с этого диска – будут записи в NVRAM или нет в этом случае не влияет на запуск твоей ОС
  • или выполнить, то что ты посчитаеш нужным
master_0K
()
Последнее исправление: master_0K (всего исправлений: 1)
Ответ на: комментарий от master_0K

Ты чет вообще не про то. Тут два решения:

  1. подменяем виндовый загрузчик
  2. перемещаем ESP на другой диск и разблокируем шифрованный через хуки либо linuxpba.img

Я долгое время пользовался первым, потом написал хук, попользовался им одно время, решил переписать по феншую и понял, что оно как-то слишком костыльно -> вернулся к варинту 1

uwuwuu
() автор топика
Ответ на: комментарий от master_0K

На WPower Shell тож скрипт написал, чтобы после обновления когда винда заменяет bootmgfw, двумя кликами фиксить все

# BEGIN RUN SCRIPT AS ADMINISTRATOR
# https://superuser.com/a/532109
param([switch]$elevated)

function Test-Admin {
  $currentUser = New-Object Security.Principal.WindowsPrincipal $([Security.Principal.WindowsIdentity]::GetCurrent())
  $currentUser.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
}

if ((Test-Admin) -eq $false)  {
  if ($elevated) {
    # tried to elevate, did not work, aborting
  } else {
    Start-Process powershell.exe -Verb RunAs -ArgumentList ('-noprofile -noexit -file "{0}" -elevated' -f ($myinvocation.MyCommand.Definition))
  }
  exit
}
# END RUN SCRIPT AS ADMINISTRATOR

function Replace-Windows-Boot-Manager {
  param([string]$letter)
  $source = "${letter}:\efi\boot\bootx64.efi"
  $target = "${letter}:\efi\microsoft\boot\bootmgfw.efi"

  if ((Get-FileHash $source).Hash -eq (Get-FileHash $target).Hash) {
    Write-Output "Boot loaders are same!"
    return 0
  }

  # Save original windows boot manager as _bootmgfw.efi
  Move-Item -Path $target -Destination ($target -replace '[^\\]+$', '_$&') -Force

  # Change windows boot manager
  Copy-Item $source $target

  Write-Output "Windows Boot Manager replaced!"
  return 1
}

# Change ESP letter if necessary
Replace-Windows-Boot-Manager -letter "Z"

uwuwuu
() автор топика
Последнее исправление: uwuwuu (всего исправлений: 1)
Ответ на: комментарий от uwuwuu

подменяем виндовый загрузчик

Мне казалось я только про это и писал. Как вариант «этого же в профиль»: забрать у него право «первого запуска» (может быть на практике это не везде и не всегда возможно сделать).

Спасибо, что выслушал. «Выхожу из треда» )

master_0K
()