Неполиткорректный совет

Если вы мэр города, то назначьте на должность начальника Горводоканала человека с еврейской фамилией. Вы дадите новую жизнь старому мему, про евреев, кран и воду.

Передача управления другому загрузчику по MBR ID в Syslinux.

Преамбула

Раз уж в прошлой заметке зашла речь про chainloading, т.е. передачу управления другому загрузчику из Syslinux, был разобран стандартный способ указания загрузчика в виде записи hdX Y, и определен минус этого способа, то можно рассказать и про устранение этого минуса.

Согласно спецификации, управление другому загрузчику можно передать не только указав номер диска и раздела, но и в следующем формате:

mbr:<id> [<partition>]

где:
<id> - уникальный MBR ID
<partition> - номер раздела жесткого диска

Схема нумерации разделов жесткого диска

Эта схема, конечно, для предыдущего случая, но разделы (а не диски), в обоих случаях нумеруются одинаково. А вот вместо hd0 (hd1, hd2…) будет mbr:<id>.

Пример конфига

Вот часть измененного конфига syslinux.cfg, где chainloading используется для загрузки Windows со второго раздела на первом жестком диске, только теперь жесткий диск определяется не по номеру, а по MBR ID:

LABEL windows
   menu label Microsoft Windows 7
   kernel modules/chain.c32
   append mbr:0x31c5dff2 2

Получение номера раздела, MBR ID и формирование записи конфигурации для загрузчика Syslinux

Сделал весь процесс в отдельной функции get_slid(), куда первым параметром передается имя устройства (с номером раздела или без), например, /dev/sda2.

1. Получим имя устройства без пути:

T_BN=`basename $1`

2. Получим номер раздела, удалив из начала имени все латинские буквы:

T_VOLNUM=`echo "$T_BN" | sed 's/^[a-z]*//'`

3. Получим имя устройства, с полным путем, но без номера раздела:

T_DSKNAM=`echo "$1"|sed 's/[0-9]\+$//'`

4. Проверим, не получилась ли пустая строка (может случиться, если в первый параметр что-то не то положили):

if [ -z "$T_DSKNAM" ]; then
    return 1 #error
fi

5. Получаем идентификатор MBR, способ указан в руководстве по chain.c32 [1]:

T_MBRID=`hexdump -s 440 -n 4 -e '"0x%08x\n"' "$T_DSKNAM"`

т.е. hexdump читает из MBR устройства 4 байта идентификатора, и выдает их в виде строки требуемого формата.

6. Формируем строку для конфигурации Syslinux:

SL_ID="mbr:$T_MBRID $T_VOLNUM"

7. Пример вызова функции:

if [ -z "$1" ]; then
    echo "Use "`basename $0` "<device>"
    exit
fi

get_slid "$1"

if [ "$?" -ne 0 ];then
    echo "Error!"
else
    echo "$1: $SL_ID"
fi

Скрипт целиком

На PasteBin
На GitHub

Источники

1. Comboot/chain.c32
2. Syslinux (Русский)

Преобразование имени раздела и устройства в формат SYSLINUX

Преамбула

Меня спрашивают, а где на практике можно применить «номер буквы в алфавите», про получение которого в bash-скрипте было недавно написано. Вот пример такого практического применения. Известно, что в Linux дисковые устройства представлены в виде /dev/sda, /dev/sdb, /dev/sdc и т.д., а разделы диска в виде /dev/sda1, /dev/sda2
SYSLINUX, точнее его модуль chain.c32, который может передавать управление другим загрузчикам, использует другой формат:

hdD P
где:
D — номер устройства (диска) в BIOS
P — номер раздела на диске
Отсчет дисков ведется с 0, разделов — с 1 (0 — главная загрузочная запись диска)
Например, hd0 2 — загрузка должна производиться со 2 раздела первого диска, hd1 1 — с 1 раздела второго жесткого диска, hd3 0 — необходимо передать управление главной загрузочной записи (MBR) четвертого диска.

Вот часть конфига syslinux.cfg, где chainloading используется для загрузки Windows со второго раздела на первом жестком диске:

LABEL windows
   menu label Microsoft Windows 7
   kernel modules/chain.c32
   append hd0 2

Некоторые минусы

— Минус, связанный с BIOS. Если вдруг порядок устройств в BIOS поменяется, то загрузчик SYSLINUX «заблудится» и попытается передать управление не туда.
— Некоторые линуксы меняют порядок именования жестких дисков, т.е. /dev/hda может и не соответствовать первому загрузочному диску. Тут уже зависит от конкретного дистрибутива.

Первый минуса можно избежать, используя вместо номера диска MBR ID, но это уже тема для отдельной заметки.

Получаем ID для chain.c32

Я организовал это в отдельной функции get_sysl_hd(), чтобы было удобно утащить в другой скрипт, буде понадобится. Первый параметр функции — имя устройства, например, /dev/sda1

1. Получаем имя устройства без пути к нему.
T_DN=`basename $1`

2. Можно проверить, соответствует ли имя устройства формату имени дисков, а то вдруг нам CD-ROM подсунули 🙂
Имя диска начинается с первой буквы s или h на некоторых пожилых дистрибутивах, далее следует буква d, далее — латинская буква a-z, потом могут следовать цифры (номера разделов). Можно сообразить вот такое простенькое регулярное выражение:

^[sh]d[a-z][1-9]*$

Далее пропускаем результат работы basename через grep, и проверяем выхлоп в переменной. Если переменная пустая, подсунули что-то не то.

T_DN=`basename $1|grep '^[sh]d[a-z][1-9]*$'`
if [ -z "$T_DN" ]; then
	return 1
fi

Но на самом деле, эта проверка не очень-то и нужна, можно пропустить этот пункт

3. Получаем третью букву в имени диска с помощью команды expr:
expr substr pos len

где:
substr — операция получения подстроки
pos — позиция символа в строке (отсчет ведется с единицы)
len — длина подстроки

T_3LET=`expr substr $T_DN 3 1`

4. Получаем номер буквы в алфавите. Я воспользовался вторым копия из ранее описанных способов.

S_CODE=`printf '%d' \'$T_3LET`
A_CODE=`printf '%d' \'a`
SYSL_ID="hd"`expr $S_CODE - $A_CODE`

5. Получим номер раздела, удалив sed‘ом все латинские буквы с начала имени устройства в переменной $T_DN:

T_VOLNUM=`echo "$T_DN" | sed 's/^[a-z]*//'`
if [ -z "$T_VOLNUM" ]; then
	T_VOLNUM=0
fi

Если переменная окажется пустой, значит нам подсунули устройство, без указания раздела — необходимо сослаться на MBR. Присваиваем T_VOLNUM значение 0.

6. Добавляем полученные данные в переменную SYSL_ID

SYSL_ID="$SYSL_ID $T_VOLNUM"

7. Пример вызова функции:

if [ -z "$1" ]; then
    echo "Use "`basename $0` "<device>"
    exit
fi

get_sysl_hd "$1"

if [ $? -ne 0 ];then
    echo "Bad device name!"
else
    echo "$1: $SYSL_ID"
fi

Скрипт целиком

На PasteBin
На GitHub

Источники

1. Syslinux (Русский)
2. Работа со строками
3. BASH: Получить номер буквы в латинском алфавите, более элегантное решение. Копия

Замечательные опечатки.

В околошкольной крипипасте:

сжечь ему эту погонь

Интересно, кого полагалось сжечь, местного военкома, или даже целого министра обороны?

За «погонью» идет ее сестра «серень», наверное, весьма зловонное растение.

На участке бабушки вовсю цвела серень

И, наконец, финалист нашего сегодняшнего хит-парада, мужыкальный, прям-таки инструмент из теста по музыке — сексофон.