如何重新打包initrd.img?

在原始的 /boot/initrd.img-kernel_ver 上,binwalk 显示了以下结构:

enter image description here

从0到22528字节,存在一个CPIO存档,其中只包含特定文件夹层次结构中的GenuineIntel.bin固件。
从22528字节开始,存在一个gzip存档,其中包含适当的文件系统,并且该gzip也被CPIO归档。

解压并修改后,我如何以相同的方式(具有相同的文件夹层次结构)压缩initrd.img?就像这个原始结构一样:

enter image description here

根据评论的建议:
find . | cpio --quiet --dereference -o -H newc | lzma -7 > ../cusotm.initrd.lz

binwalk

enter image description here

这是完全不同的结构。

你将initrd.img解压到一个工作目录中。然后,你按照特定的文件夹层次结构将你的GenuineIntel.bin固件添加到工作目录中。接下来,使用以下命令重新创建存档:find . | cpio --quiet --dereference -o -H newc | lzma -7 > ../cusotm.initrd.lz 如果这个过程不起作用,请说明你运行了哪些命令以及出现了什么问题。 - Panther
你的编辑,加上一张图片,对我理解你的问题几乎没有任何帮助。你需要提取这个图片,将它与你的代码结合起来,并确保正确的文件结构和GenuineIntel.bin固件的位置,然后重新打包成一个新的.img文件。 - Panther
@bodhi.zazen 如我所说,这创建了一个不同的文件... - EdiD
@bodhi.zazen 你终于明白我在问什么了吗? - EdiD
@bodhi.zazen "不"?:) 你怎么了?你的高声誉是虚构的吗?;) 我完全按照你说的做了(现在你又在说)结果是修改后的问题。有时候说“我不知道”比写关于存档和压缩的无用无礼更好 ;) - EdiD
1看起来initramfs文件是CPIO档案的串联。每个CPIO档案可以被压缩(使用gzip、xz等)或者未经压缩。你的输入文件以一个未经压缩的档案开始,偏移量为0,然后在偏移量22528处继续以一个压缩的档案。不幸的是,我不知道有标准工具可以提取可能被压缩的CPIO档案的串联部分。 - pts
4个回答

我弄清楚了如何制作完全相同的initrd.img归档文件。
Bodhi.zazen的答案可能有效,因为这是众所周知的解决方案。
find . | cpio --quiet --dereference -o -H newc | lzma -7 > ../cusotm.initrd.lz

但是问题不同。如果在cpio存档中只有一个gzipped文件系统,这个答案是好的,但在这种情况下,还有特定的文件夹结构中的Intel固件我想保留。

为了保持相同的文件夹层次结构,需要三个步骤:

  1. 使用简单的-o选项创建CPIO文件系统存档,而不使用新的格式,例如在之前创建的基本文件夹中:

    find . | cpio -o | gzip -9 > ../base/file_system.gz

  2. 使用新的格式创建包含kernel/x86/microcode/GenuineIntel.bin的正确存档:

    find kernel/ | cpio -o -H newc > new_initrd.img

  3. 将gzipped文件系统存档添加到正确的new_initrd.img中:

    find base/ | cpio -o >> new_initrd.img


1太棒了!谢谢!+10!但是你要如何解包原始的initrd文件呢? - rth
此外,您的解决方案创建了一个稍微不同的结构。当我首先执行步骤(2),然后执行find . | cpio -o | gzip -9 >> new_initrd.img时,在binwalk中得到了完全相同的结构。 - rth
@EdiD 你怎么解压原始的initrd文件? - ImranRazaKhan
1@ImranRazaKhan 你需要四个步骤:cpio -id < initrd.img-kernel_verdd if=initrd.img-4.4.0-22-generic of=image.gz bs=22528 skip=1 - 根据你的initrd.img文件名和块大小进行匹配;gunzip image.gzcpio -i < image - EdiD

最近我遇到了同样的问题,我的网络搜索导致我进入了这个帖子,所以为了帮助其他人,以下是一个回答关于旧问题的2018年答案...

在“最近”的内核中,initrd.img文件可以包含一个未压缩的cpio存档(即包含微码更新),该存档被附加到包含正常initramfs目录树的(已压缩的)cpio存档之前。

这在Debian Wiki页面中简要讨论:
https://wiki.debian.org/initramfs#How_to_inspect_initramfs
,但对于解析这种initrd.img文件的更精确代码可以在initramfs-tools-core软件包中的unmkinitramfs命令中找到(例如: https://git.launchpad.net/ubuntu/+source/initramfs-tools/tree/unmkinitramfs )。

我自己没有尝试过重新构建这种initrd.img文件,但根据维基页面上的信息,要编辑initramfs引导脚本,就不需要解压GenuineIntel存档。相反,你可以将那个cpio存档保留在另一个地方,然后解压第二个(压缩的)存档,修改目录结构,重新构建压缩的cpio存档,最后将保存的微码存档与新生成的存档连接起来。
(生成这个“预置”存档的代码位于/usr/share/initramfs-tools/hooks/intel_microcode中。)

重新包装
cd your_working_directory_with_modifications
find . | cpio --quiet --dereference -o -H newc | lzma -7 > ../cusotm.initrd.lz

第二个命令是重命名initrd,你在grub中指定了启动时要使用的initrd。
我建议你在移动或重命名之前先测试(启动)自定义的initrd。
从评论中的讨论中获得的额外信息:
首先,我认为你没有理解cpio / tar的作用。cpio和tar都可以将多个文件和/或目录合并成一个文件或存档。
其次,我认为你没有理解压缩的作用,压缩只是使得结果存档更小而已。你可以使用任何你喜欢的压缩工具。
参见

https://wiki.ubuntu.com/CustomizeLiveInitrd

https://wiki.gentoo.org/wiki/Initramfs/Guide

第三,Linux内核使用cpio而不是tar。
请参阅。

https://www.kernel.org/doc/Documentation/filesystems/ramfs-rootfs-initramfs.txt

请查看“为什么选择cpio而不是tar?”部分。

Why cpio rather than tar?

This decision was made back in December, 2001. The discussion started here:

http://www.uwsg.iu.edu/hypermail/linux/kernel/0112.2/1538.html

And spawned a second thread (specifically on tar vs cpio), starting here:

http://www.uwsg.iu.edu/hypermail/linux/kernel/0112.2/1587.html

The quick and dirty summary version (which is no substitute for reading the above threads) is:

1) cpio is a standard. It's decades old (from the AT&T days), and already widely used on Linux (inside RPM, Red Hat's device driver disks). Here's a Linux Journal article about it from 1996:

  http://www.linuxjournal.com/article/1213

It's not as popular as tar because the traditional cpio command line tools require _truly_hideous_ command line arguments. But that says nothing either way about the archive format, and there are alternative tools, such as:

 http://freecode.com/projects/afio

2) The cpio archive format chosen by the kernel is simpler and cleaner (and thus easier to create and parse) than any of the (literally dozens of) various tar archive formats. The complete initramfs archive format is explained in buffer-format.txt, created in usr/gen_init_cpio.c, and extracted in init/initramfs.c. All three together come to less than 26k total of human-readable text.

3) The GNU project standardizing on tar is approximately as relevant as Windows standardizing on zip. Linux is not part of either, and is free to make its own technical decisions.

4) Since this is a kernel internal format, it could easily have been
something brand new. The kernel provides its own tools to create and extract this format anyway. Using an existing standard was preferable, but not essential.

5) Al Viro made the decision (quote: "tar is ugly as hell and not going to be supported on the kernel side"):

  http://www.uwsg.iu.edu/hypermail/linux/kernel/0112.2/1540.html

explained his reasoning:

  http://www.uwsg.iu.edu/hypermail/linux/kernel/0112.2/1550.html
  http://www.uwsg.iu.edu/hypermail/linux/kernel/0112.2/1638.html

and, most importantly, designed and implemented the initramfs code.


这将不会保留文件夹结构。我希望与原始的initrd.img具有相同的结构。意思是,GenuineIntel.bin不压缩,只是在kernel/x86/microcode文件夹的根目录下以cpio方式存档,并且为什么我提到gzip时使用了lzma? - EdiD
如果你想要一个更小的存档文件,可以使用lzma。如果你愿意,也可以使用gzip。我不确定你为什么对压缩有所担心,但使用压缩功能应该能够正常工作,并且在磁盘上会生成一个较小的图像。根据你发布的内容,我并不确定你想要达到什么目的。 - Panther
我想知道最初是如何完成的。可能因为更快的可访问性,英特尔固件没有被压缩。 - EdiD
几乎可以肯定是被压缩过的,你可以检查一下档案。压缩是默认使用的,因为它对性能影响不大。 - Panther
cpio手册中没有关于压缩的内容。请查看被接受的答案:http://superuser.com/questions/343915/tar-vs-cpio-what-is-the-difference - EdiD
我觉得你可能没有理解cpio / tar的作用 - "tar和cpio基本上具有相同的功能,即从多个文件和目录的输入中创建一个连续的单一文件"。然后,生成的文件可以使用gzip、lzma或其他工具进行压缩。请参考https://wiki.ubuntu.com/CustomizeLiveInitrd。 - Panther
cpio被用作内核的一部分(而不是tar),请参阅https://www.kernel.org/doc/Documentation/filesystems/ramfs-rootfs-initramfs.txt中的“为什么选择cpio而不是tar?”部分。 - Panther
不,这是错误的。Tar和cpio只是存档工具,没有任何压缩功能。如果你想要压缩,你必须使用gzip、7zip、lzma等工具(这就是为什么它被管道传输到gzip)。是的,我知道cpio已经内置在内核中。 - EdiD
什么是“错误”? - Panther
在您编辑之后,仍然没有回答我的问题,即如何制作相同的initrd.img文件? - EdiD
创建备份cp old_img old_img.bak创建新的图像find . | cpio --quiet --dereference -o -H newc | lzma -7 > 任意名称的新图像 - Panther
:) 这个有什么不同?与回答相比有什么区别?好的,我会编辑我的问题以便更清楚。 - EdiD
@EdiD - 你有点东拉西扯,从cpio / tar的定义/用法到压缩对内核性能的影响,再到声称答案是“错误”的同时又重申了同样的“错误”信息。也许你需要澄清你的问题,并告诉我们你运行了什么命令以及遇到了什么问题。 - Panther
如果这对你来说有点拐弯抹角,就放下它,走开吧 :) 我觉得我们都在这里为了更多地了解这个系统...不是吗? - EdiD
问题从一开始就很清楚,但是从不同的问题中“复制粘贴”旧解决方案并不能解决这个问题。 - EdiD

在Ubuntu中,initrd.img被压缩为gzip格式,当我编辑它时,我希望保留这个特性。以下是具体操作步骤:
解压缩:
zcat /boot/initrd.img-3.19.0-80-generic | cpio --extract

压缩:
find . 2>/dev/null | cpio --quiet --dereference -o -H newc | gzip -9 > /boot/initrd.img-3.19.0-80-generic

嗯,看起来好像可以工作,但实际上它不再能启动我的机器。我还注意到重新打包的存档比原始存档要大得多,尽管重新打包使用了更高的压缩率(-9)。需要找出问题的根源。 - nisc
从我记忆中来看,那是唯一一个与引导项正常工作的组合。可能缺少文件权限设置,或者在不同的Ubuntu版本之间有所区别(当时我用的是14.04)。 - Jossef Harush Kadouri
不同的文件大小可能是由于--dereference,但尚未确认/测试。 - nisc