Hi
Post by Martin SchlemmerPost by Martin SchlemmerI had a bit of an accident, and wondered if somebody already had to try to
extract the initramfs image from an existing vmlinuz?
Post by Martin SchlemmerI did try google, but either my search terms was not right, or nobody
really touched on the subject before, because all the results mostly dealt
with an external image.
Post by Martin SchlemmerAny advice will be appreciated.
yes, it happens to me from time to time.
You first have to extract and uncompress the ELF image from vmlinuz. For
this, look for the gzip signature 1F 8B 08 in your vmlinuz, and feed all
data starting from this point to zcat. Either you do the same on the
resulting file -and you may find several compressed images- or you simply
pass it through "objdump -h". It will show you a .init.ramfs section. Use
the fourth field as the file offset, and dump from that position. You'll
find your initramfs, likely starting with 1F 8B 08 since it's supposed
to be compressed with gzip.
You need an hex editor, dd, zcat and objdump for this. It's not much
complicated once you have the tools, but it might require a few attempts
before finding the right image (I tend to find config.gz before initramfs).
Not sure if the previous post got through due to mail scanner, but it was also an older version.
Anyhow, below is a simple Perl script to do above if anybody ever have the same need in the future.
M
-------------------------------
#!/usr/bin/perl
#
# extract_initramfs.pl: extracts the initramfs out of a packed kernel image
#
# Copyright (C) Martin Schlemmer <***@nosferatu.za.org>
#
# Released under the terms of the GNU GPL
#
use strict;
use warnings;
use Cwd;
use Encode;
use IO::File;
use IO::Pipe;
use IO::Uncompress::Gunzip qw (gunzip $GunzipError);
my ($input,$vm_output,$rfs_output) = @ARGV;
$vm_output = cwd . '/vmlinux',
if (! defined ($vm_output) || $vm_output eq '');
$rfs_output = cwd . '/initramfs.cpio.gz',
if (! defined ($rfs_output) || $rfs_output eq '');
if (! defined ($input)) {
print "usage: $0 VMLINUZ [VMLINUX] [INITRAMFS_IMAGE]\n";
exit (1);
}
if (! -f $input) {
print "'$input' does not exist!\n";
exit (1);
}
eval {
my $fh = IO::File->new;
$fh->open ($input) or die ($!);
$fh->binmode;
my $data;
my $count = 0;
do {
$data = '';
$fh->seek ($count++, 0) or die ($!);
$fh->read ($data, 3) or die ($!);
} until ($data eq "\x1F\x8B\x08" || $fh->eof);
if ($data ne "\x1F\x8B\x08" || $fh->eof) {
print STDERR "Could not find GZIP marker!\n";
exit (1);
}
$fh->seek (--$count, 0) or die ($!);
$data = '';
while (! $fh->eof) {
my $buffer;
$fh->read ($buffer, 2048) or die ($!);
$data .= $buffer;
}
$fh->close;
my $image_data;
gunzip \$data => \$image_data,
or die ("Gunzip failed: $GunzipError\n");
$fh->open ($vm_output, '>') or die ($!);
$fh->binmode;
$fh->write ($image_data) or die ($!);
$fh->close;
my $have_ramfs = 0;
my $pipe = IO::Pipe->new or die ($!);
$pipe->reader ('objdump', '-h', $vm_output) or die ($!);
while (my $line = $pipe->getline) {
if ($line =~ /^\s+\d+\s+(\S+)\s+(\S+)\s+\S+\s+\S+\s+(\S+)\s+/) {
my ($section,$size,$offset) = ($1,$2,$3);
next if ($section ne '.init.ramfs');
$fh->open ($rfs_output, '>') or die ($!);
$fh->write ($image_data, hex ($size), hex ($offset)) or die ($!);
$fh->close;
$have_ramfs = 1;
last;
}
}
$pipe->close;
die ('No \'.init.ramfs\' section found!') if (! $have_ramfs);
};
if ($@) {
printf STDERR "$@\n";
exit (1);
}
exit (0);
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/