您的位置:首页 > 移动开发 > Android开发

读取boot.img头(根据Android源码中的bootimg.h读取)将kernel和ramdisk读取出来

2012-12-08 16:41 393 查看
使用bootimg.pl(linux、win7都可以执行)脚本,该脚本可以读取boot.img头(根据Android源码中的bootimg.h读取)将kernel和ramdisk读取出来,此脚本也会输出内核命令行和板子名字。

root@ckt-desktop:/home/ckt/work# ./split_bootimg.pl disc2/R7627USNSKQLYA113023_shared/out/target/product/msm7627a_vicuna/boot.2knand.img

Page size: 2048 (0x00000800)

Kernel size: 3127908 (0x002fba64)

Ramdisk size: 194341 (0x0002f725)

Second size: 0 (0x00000000)

Board name:

Command line: console=ttyMSM0,115200,n8 androidboot.hardware=qcom

Writing boot.2knand.img-kernel ... complete.

Writing boot.2knand.img-ramdisk.gz ... complete.

root@ckt-desktop:/home/ckt/work# ./split_bootimg.pl disc2/R7627USNSKQLYA113023_shared/out/target/product/msm7627a_vicuna/recovery.2knand.img

Page size: 2048 (0x00000800)

Kernel size: 3127908 (0x002fba64)

Ramdisk size: 438761 (0x0006b1e9)

Second size: 0 (0x00000000)

Board name:

Command line: console=ttyMSM0,115200,n8 androidboot.hardware=qcom loglevel=7

Writing recovery.2knand.img-kernel ... complete.

Writing recovery.2knand.img-ramdisk.gz ... complete.

bootimg.pl源码

#!/usr/bin/perl
use strict;
use warnings;

# Turn on print flushing
$|++;

######################################################################
## Global Variables and Constants

my $SCRIPT = __FILE__;
my $IMAGE_FN = undef;

# Constants (from bootimg.h)
use constant BOOT_MAGIC => 'ANDROID!';
use constant BOOT_MAGIC_SIZE => 8;
use constant BOOT_NAME_SIZE => 16;
use constant BOOT_ARGS_SIZE => 512;

# Unsigned integers are 4 bytes
use constant UNSIGNED_SIZE => 4;

# Parsed Values
my $PAGE_SIZE = undef;
my $KERNEL_SIZE = undef;
my $RAMDISK_SIZE = undef;
my $SECOND_SIZE = undef;

######################################################################
## Main Code

&parse_cmdline();
&parse_header($IMAGE_FN);

=format (from bootimg.h)
** +-----------------+
** | boot header     | 1 page
** +-----------------+
** | kernel          | n pages
** +-----------------+
** | ramdisk         | m pages
** +-----------------+
** | second stage    | o pages
** +-----------------+
**
** n = (kernel_size + page_size - 1) / page_size
** m = (ramdisk_size + page_size - 1) / page_size
** o = (second_size + page_size - 1) / page_size
=cut

my $n = int(($KERNEL_SIZE + $PAGE_SIZE - 1) / $PAGE_SIZE);
my $m = int(($RAMDISK_SIZE + $PAGE_SIZE - 1) / $PAGE_SIZE);
my $o = int(($SECOND_SIZE + $PAGE_SIZE - 1) / $PAGE_SIZE);

my $k_offset = $PAGE_SIZE;
my $r_offset = $k_offset + ($n * $PAGE_SIZE);
my $s_offset = $r_offset + ($m * $PAGE_SIZE);

(my $base = $IMAGE_FN) =~ s/.*\/(.*)$/$1/;
my $k_file = $base . "-kernel";
my $r_file = $base . "-ramdisk.gz";
my $s_file = $base . "-second.gz";

# The kernel is always there
print "Writing $k_file ...";
&dump_file($IMAGE_FN, $k_file, $k_offset, $KERNEL_SIZE);
print " complete.\n";

# The ramdisk is always there
print "Writing $r_file ...";
&dump_file($IMAGE_FN, $r_file, $r_offset, $RAMDISK_SIZE);
print " complete.\n";

# The Second stage bootloader is optional
unless ($SECOND_SIZE == 0) {
print "Writing $s_file ...";
&dump_file($IMAGE_FN, $s_file, $s_offset, $SECOND_SIZE);
print " complete.\n";
}

######################################################################
## Supporting Subroutines

=header_format (from bootimg.h)
struct boot_img_hdr
{
unsigned char magic[BOOT_MAGIC_SIZE];

unsigned kernel_size;  /* size in bytes */
unsigned kernel_addr;  /* physical load addr */

unsigned ramdisk_size; /* size in bytes */
unsigned ramdisk_addr; /* physical load addr */

unsigned second_size;  /* size in bytes */
unsigned second_addr;  /* physical load addr */

unsigned tags_addr;    /* physical addr for kernel tags */
unsigned page_size;    /* flash page size we assume */
unsigned unused[2];    /* future expansion: should be 0 */

unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */

unsigned char cmdline[BOOT_ARGS_SIZE];

unsigned id[8]; /* timestamp / checksum / sha1 / etc */
};
=cut
sub parse_header {
my ($fn) = @_;
my $buf = undef;

open INF, $fn or die "Could not open $fn: $!\n";
binmode INF;

# Read the Magic
read(INF, $buf, BOOT_MAGIC_SIZE);
unless ($buf eq BOOT_MAGIC) {
die "Android Magic not found in $fn. Giving up.\n";
}

# Read kernel size and address (assume little-endian)
read(INF, $buf, UNSIGNED_SIZE * 2);
my ($k_size, $k_addr) = unpack("VV", $buf);

# Read ramdisk size and address (assume little-endian)
read(INF, $buf, UNSIGNED_SIZE * 2);
my ($r_size, $r_addr) = unpack("VV", $buf);

# Read second size and address (assume little-endian)
read(INF, $buf, UNSIGNED_SIZE * 2);
my ($s_size, $s_addr) = unpack("VV", $buf);

# Ignore tags_addr
read(INF, $buf, UNSIGNED_SIZE);

# get the page size (assume little-endian)
read(INF, $buf, UNSIGNED_SIZE);
my ($p_size) = unpack("V", $buf);

# Ignore unused
read(INF, $buf, UNSIGNED_SIZE * 2);

# Read the name (board name)
read(INF, $buf, BOOT_NAME_SIZE);
my $name = $buf;

# Read the command line
read(INF, $buf, BOOT_ARGS_SIZE);
my $cmdline = $buf;

# Ignore the id
read(INF, $buf, UNSIGNED_SIZE * 8);

# Close the file
close INF;

# Print important values
printf "Page size: %d (0x%08x)\n", $p_size, $p_size;
printf "Kernel size: %d (0x%08x)\n", $k_size, $k_size;
printf "Ramdisk size: %d (0x%08x)\n", $r_size, $r_size;
printf "Second size: %d (0x%08x)\n", $s_size, $s_size;
printf "Board name: $name\n";
printf "Command line: $cmdline\n";

# Save the values
$PAGE_SIZE = $p_size;
$KERNEL_SIZE = $k_size;
$RAMDISK_SIZE = $r_size;
$SECOND_SIZE = $s_size;
}

sub dump_file {
my ($infn, $outfn, $offset, $size) = @_;
my $buf = undef;

open INF, $infn or die "Could not open $infn: $!\n";
open OUTF, ">$outfn" or die "Could not open $outfn: $!\n";

binmode INF;
binmode OUTF;

seek(INF, $offset, 0) or die "Could not seek in $infn: $!\n";
read(INF, $buf, $size) or die "Could not read $infn: $!\n";
print OUTF $buf or die "Could not write $outfn: $!\n";

close INF;
close OUTF;
}

######################################################################
## Configuration Subroutines

sub parse_cmdline {
unless ($#ARGV == 0) {
die "Usage: $SCRIPT boot.img\n";
}
$IMAGE_FN = $ARGV[0];
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: