Por que meu initrd tem apenas um diretório, a saber, 'kernel'?

23

Estou usando o live-build do Debian para trabalhar em um sistema inicializável. Ao final do processo, recebo os arquivos típicos usados para inicializar um sistema ativo: um arquivo squashfs, alguns módulos e arquivos de configuração do GRUB e um arquivo initrd.img.

Eu posso inicializar muito bem usando esses arquivos, passando o initrd para o kernel via

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

na linha de comando do carregador de inicialização. Mas quando tento examinar o conteúdo da minha imagem initrd, assim:

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

a árvore de arquivos que eu recebo é assim:

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

Onde está a árvore real do sistema de arquivos, com os típicos / bin, / etc, / sbin ... contendo os arquivos reais usados durante a inicialização?

    
por user986730 21.10.2014 / 14:28

4 respostas

23

O método skip do bloco cpio dado não funciona de forma confiável. Isso porque as imagens initrd que eu estava conseguindo não tinham os dois arquivos concatenados em um limite de 512 bytes.

Em vez disso, faça isso:

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

Use o último número (21136) que não está em um limite de 512 bytes para mim:

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
    
por 23.03.2015 / 19:41
14

Acontece que o initrd gerado pelo live-build do Debian (e para minha surpresa, aceito pelo kernel) é na verdade a concatenação de duas imagens:

  • um arquivo CPIO contendo atualizações de microcódigo a serem aplicadas no processador;
  • um arquivo cpio gzip-ed, que na verdade contém a árvore de arquivos initrd (com os diretórios / etc / bin / sbin / dev ... esperados).

Após extrair o initrd.img original, direto da saída ao vivo, obtive esta saída:

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

O que significa que a extração do cpio terminou após a análise de 896 blocos de 512 Bytes cada. Mas o initrd.img original era muito maior que 896 * 512 = 458752B = 448 KB:

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

Assim, a imagem atual do initrd que eu estava procurando foi anexada logo após o primeiro arquivo do cpio (aquele que contém as atualizações do microcódigo) e podia ser acessado usando o dd:

$dd if=initrd.img of=myActualInitrdImage.img.gz bs=512 skip=896
    
por 21.10.2014 / 15:01
11

Se você sabe que seu initrd.img consiste em um arquivo cpio descompactado seguido por um arquivo cpio compactado com gz, você pode usar o seguinte para extrair todos os arquivos (de ambos os arquivos) em seu diretório de trabalho atual (testado no bash):

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

A linha de comando acima transmite o conteúdo de initrd.img como entrada padrão para um subshell que executa os dois comandos cpio -id e zcat | cpio -id sequencialmente. O primeiro comando ( cpio -id ) termina assim que ler todos os dados pertencentes ao primeiro arquivo cpio. O conteúdo restante é então passado para zcat | cpio -id , que descomprime e descompacta o segundo arquivo.

    
por 12.12.2016 / 23:47
0

Se você precisar executar essa tarefa com frequência, talvez queira criar uma pequena função bash como a seguinte (e talvez adicioná-la ao seu .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 $@
}

O código é baseado na resposta de Marc, mas é significativamente mais rápido, já que o binwalk só procura por arquivos gzip. Você pode invocá-lo assim:

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

Você precisará do binwalk instalado para que funcione.

    
por 12.12.2016 / 23:26