Почему мой initrd имеет только один каталог, а именно, «ядро»?


29

Я использую live-сборку Debian для работы на загрузочной системе. К концу процесса я получаю типичные файлы, используемые для загрузки работающей системы: файл squashfs, некоторые модули GRUB и файлы конфигурации, а также файл initrd.img.

Я могу нормально загружаться, используя эти файлы, передавая initrd ядру через

initrd=/path/to/my/initrd.img

в командной строке загрузчика. Но когда я пытаюсь проверить содержимое моего образа initrd, вот так:

$file initrd.img
initrd.img: ASCII cpio archive (SVR4 with no CRC)
$mkdir initTree && cd initTree
$cpio -idv < ../initrd.img

дерево файлов, которое я получаю, выглядит так:

$tree --charset=ASCII
.
`-- kernel
    `-- x86
        `-- microcode
            `-- GenuineIntel.bin

Где находится фактическое дерево файловой системы, с типичными / bin, / etc, / sbin ..., содержащими фактические файлы, используемые во время загрузки?


1
Команда 'lsinitramfs' была разработана для этого.
Earlgrey

Ответы:


32

Данный метод пропуска блока cpio не работает надежно. Это потому, что образы initrd, которые я получал сам, не объединяли оба архива на границе 512 байт.

Вместо этого сделайте это:

apt-get install binwalk
legolas [mc]# binwalk initrd.img 
DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             ASCII cpio archive (SVR4 with no CRC), file name: "kernel", file name length: "0x00000007", file size: "0x00000000"
120           0x78            ASCII cpio archive (SVR4 with no CRC), file name: "kernel/x86", file name length: "0x0000000B", file size: "0x00000000"
244           0xF4            ASCII cpio archive (SVR4 with no CRC), file name: "kernel/x86/microcode", file name length: "0x00000015", file size: "0x00000000"
376           0x178           ASCII cpio archive (SVR4 with no CRC), file name: "kernel/x86/microcode/GenuineIntel.bin", file name length: "0x00000026", file size: "0x00005000"
21004         0x520C          ASCII cpio archive (SVR4 with no CRC), file name: "TRAILER!!!", file name length: "0x0000000B", file size: "0x00000000"
21136         0x5290          gzip compressed data, from Unix, last modified: Sat Feb 28 09:46:24 2015

Используйте последнее число (21136), которое не находится на границе 512 байт для меня:

legolas [mc]# dd if=initrd.img bs=21136 skip=1 | gunzip | cpio -tdv | head
drwxr-xr-x   1 root     root            0 Feb 28 09:46 .
drwxr-xr-x   1 root     root            0 Feb 28 09:46 bin
-rwxr-xr-x   1 root     root       554424 Dec 17  2011 bin/busybox
lrwxrwxrwx   1 root     root            7 Feb 28 09:46 bin/sh -> busybox
-rwxr-xr-x   1 root     root       111288 Sep 23  2011 bin/loadkeys
-rwxr-xr-x   1 root     root         2800 Aug 19  2013 bin/cat
-rwxr-xr-x   1 root     root          856 Aug 19  2013 bin/chroot
-rwxr-xr-x   1 root     root         5224 Aug 19  2013 bin/cpio
-rwxr-xr-x   1 root     root         3936 Aug 19  2013 bin/dd
-rwxr-xr-x   1 root     root          984 Aug 19  2013 bin/dmesg

Действительно, ваш ответ превосходит мой. Я никогда не думал, что выравнивание будет проблемой. Интересно, однако, если бы cpio дал более интересные результаты, если бы первое изображение, содержащееся в файле мультиизображений, не было 512B-выровненным.
user986730

Как вернуть его обратно (перепаковать в исходное состояние) после изменения, с той же иерархией папок?
EdiD

2
Просто cdв директорию , куда вы распаковали свой архив CPIO, бег find | cpio -H newc -o > /tmp/my_archive.cpio, затем GZIP его gzip /tmp/my_archive.cpioи , наконец, сцепить его с с микрокода изображением, если у вас один: cat my_microcode_image.cpio /tmp/my_archive.cpio.gz > mynewinitrd.img. Если у вас не было изображения микрокода, то вы можете просто использовать файл gzip, который есть в вашем загрузчике
user986730

При прочтении этого ответа кажется очевидным, что это сработает только в том случае, если содержимое файла gzipped находится в середине файла. В противном случае вы должны изменить размер блока на 1 и установить пропуск на количество байтов для пропуска. Есть ли причина не всегда делать это?
TamaMcGlinn

во-вторых, чтобы на самом деле записывать файлы, а не просто перечислять некоторые из них, измените последнюю команду в конвейере на cpio -iвместо cpio -tdv | head.
TamaMcGlinn

22

Если вы знаете, что вы initrd.imgсостоите из несжатого архива cpio, за которым следует gp-сжатый архив cpio, вы можете использовать следующее для извлечения всех файлов (из обоих архивов) в текущий рабочий каталог (протестировано в bash):

(cpio -id; zcat | cpio -id) < /path/to/initrd.img

Приведенная выше командная строка передает содержимое initrd.imgстандартного ввода в подоболочку, которая выполняет две команды cpio -idи zcat | cpio -idпоследовательно. Первая команда ( cpio -id) завершается, как только она прочитает все данные, принадлежащие первому архиву cpio. Оставшийся контент затем передается zcat | cpio -id, который распаковывает и распаковывает второй архив.


1
Это выглядит как самое чистое решение на сегодняшний день
velis

1
Работает прекрасно
TurboHz

Таинственным образом, точный ответ @ woolpool - единственный ответ, который когда-либо размещал пользователь. Это стиль. Если вы собирались опубликовать только один ответ в течение всей своей карьеры в StackExchange, то вряд ли вы могли бы сделать лучше, чем опубликовать такой, как этот. ОП может рассмотреть вопрос об изменении принятого ответа на этот.
THB

16

Оказывается, initrd, сгенерированный live-сборкой Debian (и, к моему удивлению, принятый ядром), на самом деле является объединением двух образов:

  • архив CPIO, содержащий обновления микрокода, которые должны быть применены к процессору;
  • cpio-архив gzip-ed, который фактически содержит дерево файлов initrd (с ожидаемыми ожидаемыми каталогами / etc / bin / sbin / dev ...).

После извлечения исходного initrd.img прямо из вывода live-build я получил следующий вывод:

$cpio -idv ../initrd.img
kernel
kernel/x86
kernel/x86/microcode
kernel/x86/microcode/GenuineIntel.bin
896 blocks

Это означает, что извлечение cpio закончилось после анализа 896 блоков по 512 байт каждый. Но исходный файл initrd.img был больше, чем 896 * 512 = 458752B = 448 КБ:

$ls -liah initrd.img
3933924 -r--r--r-- 1 root root 21M Oct 21 10:05 initrd.img

Таким образом, фактическое изображение initrd, которое я искал, было добавлено сразу после первого архива cpio (содержащего обновления микрокода), и к нему можно было получить доступ с помощью dd:

$dd if=initrd.img of=myActualInitrdImage.img.gz bs=512 skip=896


1

Основываясь на идее, приведенной в ответе @ woolpool, я написал рекурсивную функцию, которая будет работать для любого архива cpio независимо от расположения объединенных данных и не требует специальных инструментов, таких как binwalk. Например, мой mkinitramfs создавал файл cpio; cpio; gzip. Он работает, извлекая каждую часть объединенного файла initrd, сохраняя оставшуюся часть в временный файл и затем используя программу «file», чтобы решить, что делать со следующей частью.

uncpio(){
if [[ $(wc -c $1 | cut -d ' ' -f1) -eq 0 ]]; then
    return
fi

type=$(cat $1 | file -)
local tmpfile=$(date +%s.%N)
echo -e "\n$type"
if [[ $type =~ .*cpio.* ]]; then
    cat $1 | (cpio -id; cat >$tmpfile)
elif [[ $type =~ .*gzip.* ]]; then
    zcat $1 | (cpio -id; cat >$tmpfile)
else
    return
fi
uncpio $tmpfile 
rm $tmpfile
}

Чтобы использовать тип: uncpio initrdfilename


0

Если вам нужно часто выполнять эту задачу, вы можете создать небольшую функцию bash, подобную следующей (и, возможно, добавить ее в ваш .bashrc):

initramfs-extract() {
    local target=$1
    local offset=$(binwalk -y gzip $1 | awk '$3 ~ /gzip/ { print $1; exit }')
    shift
    dd if=$target bs=$offset skip=1 | zcat | cpio -id --no-absolute-filenames $@
}

Код основан на ответе Марка, но он значительно быстрее, так как binwalk будет искать только файлы gzip. Вы можете вызвать это, как это:

$ initramfs-extract /boot/initrd.img -v

Вам нужно будет binwalkустановить, чтобы он работал.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.