西西河

主题:【原创】如何解开Ubuntu的initrd.img和Gentoo的initramfs -- wsxx

共:💬13 🌺37 新:
全看树展主题 · 分页
家园 【原创】如何解开Ubuntu的initrd.img和Gentoo的initramfs

你为什么要这么干?因为想DIY自己的Linux的启动过程。

对于我来说,我最近的目的是把Gentoo安装到移动硬盘上,让电脑直接从移动硬盘启动。做成这样的一个Linux之后,我可以拿着硬盘到不同的机器上使用,甚至在不支持USB启动的老机器上使用(当然它得有USB接口)。

如何在移动硬盘上安装我的Gentoo,参见

链接出处

在内核启动之后的几秒钟之内,USB设备可能尚未被系统确认,Linux可能会提示找不到根。我们需要修改启动过程,让内核sleep几秒钟之后再继续引导,就需要修改initrd(Ubuntu是initrd.img-xxxx,Gentoo是initramfs-genkernel-xxxxx)文件中的一个叫做init的脚本(script),在其中适当的地方插入一个sleep 5让它暂停5秒钟。

要编辑init这个文件,需要把压缩的initrd解开,找到其中的init进行修改,然后再把修改好的文件连同一起解开的宋有文件再打包成initrd,更换掉原来的initrd或者使用新的文件名,在启动菜单中增加新的指向。后者是保险的方法,免得万一没搞好,原来的又没了。

现在的问题是initrd文件如何解开。

我看了不少网上的文章,介绍的基本上都是针对Linux 2.4之前的方法,那时的打包方法是把所有文件做成镜像文件,再用gzip压缩。打开那种initrd文件的过程就是先gunzip,把解压的文件挂载到一个目录中,就可以对目录中的任何文件进行阅读和修改了。

但是,我开始学Linux的时候已经是2.6版推出之后了。使用上面的方法完全无法解开initrd文件,第一步gunzip可以,后面的挂载就怎么弄都是错的,修改其中的文件也就无从谈起。

这种情况持续了可能有一个月,每天翻来覆去mount -o loop -t filetype都不行,在网上查来查去也还是这个办法。

昨天,在google的搜索结果的第三页之后随便按了一个很不起眼的链接,看到一篇文章竟然有解决办法。原来2.6版开始,不再用镜像的方法制作initrd了,据分析说是为了简化制作步骤。新的制作方法采用cpio的方式制作。

接下来,我将把Ubuntu和Gentoo的解压发放介绍一下,两者还有不同,这又花了我很长时间才搞个半懂。

(待续)

关键词(Tags): #Ubuntu#Gentoo#initrd#cpio元宝推荐:闲看蚂蚁上树,铁手,
家园 支持diy,送花一朵
家园 这种情况持续了可能有一个月!!!

搞不懂老兄一年到头怎么花那么多时间净琢磨这些东西啊??12万分的佩服!!!

家园 很有兴趣,花催下文
家园 你看,wsxx读起来像不像无所事事啊?

可惜那个ID被人抢注了

家园 (续一)解压Ubuntu的initrd.img的方法

Ubuntu的initrd.img可以在/boot中找到,通常文件名后面还跟有很长的一串版本号。

为了保险起见,不直接操作原文件,而是把它复制到自己的家目(home)录中。如果你是用root帐号登录的,家目录就在/root中,如果是用wsxx登录的,家目录一般就在/home/wsxx中,通常登录之后自动就到了家目中。我们把initrd.img复制但家目中进行解压:

cp /boot/initrd.img-2.6.15-ubuntu-r6 ./initrd.img.gz

上面这个命令把/boot区中的文件复制到当前目录,并更名为initrd.img.gz。一方面改成短文件名好一点好操作,另一方面加上gz的后缀更清楚表明它原本就是一个gzip压缩出来的文件。

然后解压:

gunzip initrd.img.gz

也可以:

gzip -d initrd.img.gz

两者结果是相同的,都是在当前目录得到一个解压后的initrd.img,原来的initrd.img.gz被删除掉了(这也许是linux整洁的优点)。

现在这个更大的initrd.img要用cpio解开,成为一系列目录和文件。为了不与当前目录中现有的文件搞混,我们有必要新建一个目录,把initrd.img解压到新目录中去。将来把里面的文件修改好之后,还要把所有的目录文件再打包起来:

mkdir initrd #建立目录

cd initrd #进入目录

cpio -i -d < ../initrd.img #解开上层目录中的initrd.img

因为已经进入到initrd中,../initrd.img表示上层目录中的initrd.img。

现在就可以看到initrd中各目录中有很多新的目录和文件了。在这里我们可以窥视到ubuntu是如何装配起来的。可以对其中的内容进行修改了。

修改文本文件没有什么好多说的了。

修改之后,就是压缩回去,用它来启动,检验是否可以正常启动,是否达到预期的修改目的。先用cpio打包:

find . | cpio -o -H newc > ../myinitrd.img #打包当前目录中的所有目录和文件,到上层目录中的myinitrd.img

cd .. #回到上层目录

gzip -9 myinitrd.img #gzip的最高级压缩

得到的myinitrd.img.gz就是新的Ubuntu启动文件了。

做到这里,要有必要停下来看看一看,比较一下重新压缩之后的文件,是否和原来的initrd.img.gz差不多大小?都应该是4M多的文件。如果文件大小相差太多,可能就有问题。我用Ubuntu文件解压后在压缩回来,用不同的文件名,最后比较,大小完全一致,心里就踏实了。

再用Gentoo的initramfs文件进行同样方法的操作,2M多的文件解压再压缩回来,只剩下不到1K了,自己也不相信这是对的。

(待续)

关键词(Tags): #Ubuntu
家园 受教了,花催
家园 (续二)解压Gentoo中的initramfs的方法

解压Gentoo的initramfs方法,与遵循常规方法的Ubuntun略有不同。

我们先来看看问题在哪里:

cp /boot/initramfs-genkernel-x86-2.6.17-gentoo-r4 /initramfs.gz # 复制到当前家目录,简化文件名

gunzip initramfs.gz # gunzip解压

mkdir initrd #建立一个新目录

cd initrd #进入新目录

cpio -i -d < ../initramfs #解开上层目录中的initramfs

也可以这样:cat ../initramfs |cpio -id

可是结果是显示5 blocks,也就是说解压出来的内容一共才有5K大小!这显然是有问题的,原始的initramfs.gz有2M多,gunzip解压之后有4M多,可是怎么可能cpio解压之后只有5K呢?Ubuntu解压出来之后有12M多呢。

这个问题不解决,修改init是没有用的。曾经修改之后再打包压缩回去,剩下不到1K的内容。如果拿它去启动,不知道会是什么样子。

被这个问题困扰的人不多也不少,在网上遇到问题求问的不少,有些人似乎找到了答案,但是也不是最终正确的。例如有人觉察到cpio打开initramfs之后遇到TRAILER解包就结束了,所以来了个我称作的“二次解包法”:

cat ../initramfs |(cpio -id;cpio -id)

这样可以解出343 blocks。我第一次以为这样算是可以了,后来才明白 1个block其实只有1K,343K是比5K大了不少,但是距离成千上万K的预期值还相去甚远。

继续在网上翻,在几乎绝望的状态之下,很偶然地点击了google搜索结果第n页的一个不起眼的链接,里面竟然有正解!

外链出处

对于Linux比较熟练的人看了上面的链接就知道自己做了,我是琢磨了一番才搞明白的。新手们可能还需要解释一番,我回头再写一个详细一点的解释和示例。

(待续)

家园 静心学习,花,呵呵,一花双宝,好爽!
家园 (续三)解压Gentoo中的initramfs的详细方法

外链出处这篇文章中说到,Gentoo的initramfs文件中有TRAILER的问题,cpio碰到这些东西就停止了解压。该作者写了一个小小的脚本,用来修理TRAILER:

#!/bin/bash

awk '

BEGIN{RS="07070"}

{

if(/TRAILER\!\!\!/){y=""}else{y=RT}

if(RT!=""){x=x gensub(/^.*TRAILER\!\!\!.*$/,"",1) y}else{x=x $0}

}

END{print x}' $1

这个脚本的正则表达式使用得出神入化,我们恐怕一时难以搞明白,先这么使用着吧,等有空再回来琢磨。

我们使用的时候,可以把以上内容保存为一个文本文件,按照作者的方法,命名为fixcpio,保存在家目录中。要让这个脚本可以被执行,还必须给它加上可执行的属性:

chmod +x fixcpio

然后就可以用它来做为解包过程中的一环:

cat initramfs.gz | gunzip | ./fixcpio >initramfs-fixed # 解压后送到fixcpio处理一下再保存起来

cd initrd #进入工作目录

cpio -id <../initramfs-fixed # 解压上层目录的文件到本目录中

initramfs-fixed就是修理过的cpio格式的文件,最后一步就和普通的cpio解包过程相同了。

总结一下,可以把两步合并成一步,如果已经进入工作目录,只要这样就可以了:

cat ../initramfs.gz | gunzip | ../fixcpio |cpio -id

同理,修改init之后,再打包回去,只要这样一步就可以了:

find .|cpio -oH newc|gzip -9> ../myinitramfs.gz

重新打包当然就没有修理一说了。在上层家目录里将会得到myinitramfs.gz,这是可以用来启动的文件了。

简化的方法也是用于Ubuntu。

(完)

家园 【后记】我们应该养成好习惯

在解压的过程中,我碰到问题的时候,花了很多时间在试验各种命令的选项和参数上了,又花了很多时间去查文献,虽然这些都是值得的,但是回想起来不是很科学的方法,效率很低。

碰到这种情况,首先应该从大局出发,摸清它是什么类型的文件,知道了对手的情况才好下手解压。具体来说,要知道initramfs这个文件是什么类型的文件,不应该上去就解压,除非你已经确定知道它的类型,应该使用file这个命令先做一下火力侦察:

file initramfs.gz

系统报告:

initramfs.gz: gzip compressed data, from Unix, max compression

这是一个gzip压缩文件,用gzip/gunzip解压。

而后

file initramfs

系统报告:

initramfs: ASCII cpio archive (SVR4 with no CRC)

原来这是cpio文档,我们很快就会找到解压的办法,就是用cpio去解压,而不是把它当作镜像文件去解。

也许这是事后诸葛亮了,但愿以后碰到问题不会这么费劲。

(完)

关键词(Tags): #cpio#file
家园 很佩服您的钻研精神

家园 好文,做个极好
全看树展主题 · 分页


有趣有益,互惠互利;开阔视野,博采众长。
虚拟的网络,真实的人。天南地北客,相逢皆朋友

Copyright © cchere 西西河