Tại sao initrd của tôi chỉ có một thư mục, cụ thể là 'kernel'?


28

Tôi đang sử dụng debian live-build để hoạt động trên hệ thống có thể khởi động. Đến cuối quá trình tôi nhận được các tệp điển hình được sử dụng để khởi động một hệ thống trực tiếp: tệp squashfs, một số mô-đun GRUB và tệp cấu hình và tệp initrd.img.

Tôi có thể khởi động tốt bằng cách sử dụng các tệp đó, chuyển initrd đến kernel thông qua

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

trên dòng lệnh bootloader. Nhưng khi tôi cố gắng kiểm tra nội dung của hình ảnh initrd của mình, như vậy:

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

cây tập tin tôi nhận được trông như thế này:

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

Cây hệ thống tập tin thực sự ở đâu, với / bin, / etc, / sbin ... điển hình chứa các tệp thực tế được sử dụng trong khi khởi động?


1
Lệnh 'lsinitramfs' được thiết kế cho việc này.
Earlgrey

Câu trả lời:


31

Phương pháp bỏ qua khối cpio được đưa ra không hoạt động đáng tin cậy. Đó là bởi vì những hình ảnh ban đầu tôi nhận được không có cả hai tài liệu lưu trữ được nối trên ranh giới 512 byte.

Thay vào đó, hãy làm điều này:

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

Sử dụng số cuối cùng (21136) không nằm trên ranh giới 512 byte đối với tôi:

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

Thật vậy, câu trả lời của bạn đánh bại tôi. Tôi chưa bao giờ nghĩ rằng sự liên kết sẽ là một vấn đề. Tuy nhiên, tôi tự hỏi, nếu cpio sẽ cung cấp một số đầu ra thú vị hơn nếu hình ảnh đầu tiên chứa trong tệp đa hình ảnh không phải là 512B.
dùng986730

Làm thế nào để hoàn nguyên nó (đóng gói lại trạng thái ban đầu) sau khi sửa đổi, với cùng phân cấp thư mục?
EdiD

2
Chỉ cần cdvào thư mục nơi bạn trích xuất kho lưu trữ cpio của mình, chạy find | cpio -H newc -o > /tmp/my_archive.cpio, sau đó gzip nó gzip /tmp/my_archive.cpiovà cuối cùng, nối nó với hình ảnh vi mã, nếu bạn có : cat my_microcode_image.cpio /tmp/my_archive.cpio.gz > mynewinitrd.img. Nếu bạn không có hình ảnh vi mã, thì bạn chỉ có thể sử dụng tệp được nén của mình như trong bộ tải khởi động của mình
user986730

Khi đọc câu trả lời này, có vẻ như điều này rõ ràng sẽ chỉ hoạt động nếu nội dung được nén được quá nửa trong tệp. Nếu không, bạn nên thay đổi kích thước khối thành 1 và đặt bỏ qua thành số byte cần bỏ qua. Bất kỳ lý do không phải luôn luôn làm điều đó?
TamaMcGlinn

thứ hai, để thực sự viết các tập tin thay vì chỉ liệt kê một số trong số chúng, thay đổi lệnh cuối cùng trong đường ống thành cpio -i, thay vì cpio -tdv | head.
TamaMcGlinn

21

Nếu bạn biết initrd.imgbao gồm một kho lưu trữ cpio không nén, sau đó là kho lưu trữ cpio được nén bằng gz, bạn có thể sử dụng cách sau để trích xuất tất cả các tệp (từ cả hai kho lưu trữ) vào thư mục làm việc hiện tại của bạn (đã kiểm tra trong bash):

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

Dòng lệnh trên chuyển các nội dung initrd.imgdưới dạng đầu vào tiêu chuẩn vào một lớp con thực thi hai lệnh cpio -idzcat | cpio -idtuần tự. Lệnh đầu tiên ( cpio -id) chấm dứt khi nó đã đọc tất cả dữ liệu thuộc về kho lưu trữ cpio đầu tiên. Các nội dung còn lại sau đó được chuyển đến zcat | cpio -id, giải nén và giải nén kho lưu trữ thứ hai.


1
Đây trông giống như các giải pháp sạch cho đến nay
Velis

1
Nó hoạt động rất đẹp
TurboHz

Một cách bí ẩn, câu trả lời hay của @ Woolpool là câu trả lời duy nhất mà người dùng đã từng đăng. Đó là phong cách. Nếu bạn chỉ đăng một câu trả lời trong toàn bộ sự nghiệp StackExchange, thì bạn khó có thể làm tốt hơn là đăng một câu như thế này. OP có thể xem xét thay đổi câu trả lời được chấp nhận cho câu trả lời này.
THB

16

Hóa ra initrd được tạo bởi live-build của Debian (và thật ngạc nhiên, được chấp nhận bởi kernel) thực sự là sự kết hợp của hai hình ảnh:

  • một kho lưu trữ CPIO chứa các cập nhật vi mã sẽ được áp dụng trên bộ xử lý;
  • một kho lưu trữ cpio gzip-ed, thực sự chứa cây tệp initrd (với các thư mục / etc / bin / sbin / dev ... đã được mong đợi).

Khi trích xuất initrd.img ban đầu, ra khỏi đầu ra xây dựng trực tiếp, tôi đã nhận được đầu ra này:

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

Điều đó có nghĩa là quá trình trích xuất cpio đã kết thúc sau khi phân tích 896 khối 512 byte mỗi khối. Nhưng initrd.img ban đầu lớn hơn 896 * 512 = 458752B = 448 KB:

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

Vì vậy, hình ảnh initrd thực tế mà tôi đang tìm kiếm đã được thêm vào ngay sau kho lưu trữ cpio đầu tiên (ảnh chứa các bản cập nhật vi mã) và có thể được truy cập bằng dd:

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

2

Bạn có thể sử dụng unmkinitramfstừ initramfs-tools> = 0.126, được bao gồm từ Debian 9 (kéo dài) và Ubuntu 18.04 (bionic).


1

Dựa trên ý tưởng được đưa ra trong câu trả lời của @ Woolpool, tôi đã viết một hàm đệ quy sẽ hoạt động cho bất kỳ kho lưu trữ cpio nào bất kể việc sắp xếp dữ liệu được nối và không yêu cầu bất kỳ công cụ đặc biệt nào như binwalk. Ví dụ: mkinitramfs của tôi đã tạo ra một tệp cpio; cpio; gzip. Nó hoạt động bằng cách trích xuất từng phần của tệp initrd được nối, lưu phần còn lại vào tempfile và sau đó sử dụng chương trình "tệp" để quyết định làm gì với phần tiếp theo.

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
}

Để sử dụng loại: unspio initrdfilename


0

Nếu bạn cần thực hiện nhiệm vụ này thường xuyên, bạn có thể muốn tạo một hàm bash nhỏ như sau (và có thể thêm nó vào .bashrc của bạn):

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 $@
}

Mã dựa trên câu trả lời của Marc, nhưng nó nhanh hơn đáng kể vì binwalk sẽ chỉ tìm các tệp gzip. Bạn có thể gọi nó, như thế này:

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

Bạn sẽ cần binwalkcài đặt để làm cho nó hoạt động.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.