kgdb: split_bootimg.pl

File split_bootimg.pl, 6.2 KB (added by admin, 13 years ago)

4f3109ea7c68303cb698a4933dcf4977 split_bootimg.pl

Line 
1#!/usr/bin/perl
2######################################################################
3#
4#   File          : split_bootimg.pl
5#   Author(s)     : William Enck <enck@cse.psu.edu>
6#   Description   : Split appart an Android boot image created
7#                   with mkbootimg. The format can be found in
8#                   android-src/system/core/mkbootimg/bootimg.h
9#
10#                   Thanks to alansj on xda-developers.com for
11#                   identifying the format in bootimg.h and
12#                   describing initial instructions for splitting
13#                   the boot.img file.
14#
15#   Last Modified : Tue Dec  2 23:36:25 EST 2008
16#   By            : William Enck <enck@cse.psu.edu>
17#
18#   Copyright (c) 2008 William Enck
19#
20######################################################################
21
22use strict;
23use warnings;
24
25# Turn on print flushing
26$|++;
27
28######################################################################
29## Global Variables and Constants
30
31my $SCRIPT = __FILE__;
32my $IMAGE_FN = undef;
33
34# Constants (from bootimg.h)
35use constant BOOT_MAGIC => 'ANDROID!';
36use constant BOOT_MAGIC_SIZE => 8;
37use constant BOOT_NAME_SIZE => 16;
38use constant BOOT_ARGS_SIZE => 512;
39
40# Unsigned integers are 4 bytes
41use constant UNSIGNED_SIZE => 4;
42
43# Parsed Values
44my $PAGE_SIZE = undef;
45my $KERNEL_SIZE = undef;
46my $RAMDISK_SIZE = undef;
47my $SECOND_SIZE = undef;
48
49######################################################################
50## Main Code
51
52&parse_cmdline();
53&parse_header($IMAGE_FN);
54
55=format (from bootimg.h)
56** +-----------------+
57** | boot header     | 1 page
58** +-----------------+
59** | kernel          | n pages
60** +-----------------+
61** | ramdisk         | m pages
62** +-----------------+
63** | second stage    | o pages
64** +-----------------+
65**
66** n = (kernel_size + page_size - 1) / page_size
67** m = (ramdisk_size + page_size - 1) / page_size
68** o = (second_size + page_size - 1) / page_size
69=cut
70
71my $n = int(($KERNEL_SIZE + $PAGE_SIZE - 1) / $PAGE_SIZE);
72my $m = int(($RAMDISK_SIZE + $PAGE_SIZE - 1) / $PAGE_SIZE);
73my $o = int(($SECOND_SIZE + $PAGE_SIZE - 1) / $PAGE_SIZE);
74
75my $k_offset = $PAGE_SIZE;
76my $r_offset = $k_offset + ($n * $PAGE_SIZE);
77my $s_offset = $r_offset + ($m * $PAGE_SIZE);
78
79(my $base = $IMAGE_FN) =~ s/.*\/(.*)$/$1/;
80my $k_file = $base . "-kernel";
81my $r_file = $base . "-ramdisk.gz";
82my $s_file = $base . "-second.gz";
83
84# The kernel is always there
85print "Writing $k_file ...";
86&dump_file($IMAGE_FN, $k_file, $k_offset, $KERNEL_SIZE);
87print " complete.\n";
88
89# The ramdisk is always there
90print "Writing $r_file ...";
91&dump_file($IMAGE_FN, $r_file, $r_offset, $RAMDISK_SIZE);
92print " complete.\n";
93
94# The Second stage bootloader is optional
95unless ($SECOND_SIZE == 0) {
96    print "Writing $s_file ...";
97    &dump_file($IMAGE_FN, $s_file, $s_offset, $SECOND_SIZE);
98    print " complete.\n";
99}
100   
101######################################################################
102## Supporting Subroutines
103
104=header_format (from bootimg.h)
105struct boot_img_hdr
106{
107    unsigned char magic[BOOT_MAGIC_SIZE];
108
109    unsigned kernel_size;  /* size in bytes */
110    unsigned kernel_addr;  /* physical load addr */
111
112    unsigned ramdisk_size; /* size in bytes */
113    unsigned ramdisk_addr; /* physical load addr */
114
115    unsigned second_size;  /* size in bytes */
116    unsigned second_addr;  /* physical load addr */
117
118    unsigned tags_addr;    /* physical addr for kernel tags */
119    unsigned page_size;    /* flash page size we assume */
120    unsigned unused[2];    /* future expansion: should be 0 */
121
122    unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */
123
124    unsigned char cmdline[BOOT_ARGS_SIZE];
125
126    unsigned id[8]; /* timestamp / checksum / sha1 / etc */
127};
128=cut
129sub parse_header {
130    my ($fn) = @_;
131    my $buf = undef;
132
133    open INF, $fn or die "Could not open $fn: $!\n";
134    binmode INF;
135
136    # Read the Magic
137    read(INF, $buf, BOOT_MAGIC_SIZE);
138    unless ($buf eq BOOT_MAGIC) {
139        die "Android Magic not found in $fn. Giving up.\n";
140    }
141
142    # Read kernel size and address (assume little-endian)
143    read(INF, $buf, UNSIGNED_SIZE * 2);
144    my ($k_size, $k_addr) = unpack("VV", $buf);
145
146    # Read ramdisk size and address (assume little-endian)
147    read(INF, $buf, UNSIGNED_SIZE * 2);
148    my ($r_size, $r_addr) = unpack("VV", $buf);
149
150    # Read second size and address (assume little-endian)
151    read(INF, $buf, UNSIGNED_SIZE * 2);
152    my ($s_size, $s_addr) = unpack("VV", $buf);
153
154    # Ignore tags_addr
155    read(INF, $buf, UNSIGNED_SIZE);
156
157    # get the page size (assume little-endian)
158    read(INF, $buf, UNSIGNED_SIZE);
159    my ($p_size) = unpack("V", $buf);
160
161    # Ignore unused
162    read(INF, $buf, UNSIGNED_SIZE * 2);
163
164    # Read the name (board name)
165    read(INF, $buf, BOOT_NAME_SIZE);
166    my $name = $buf;
167
168    # Read the command line
169    read(INF, $buf, BOOT_ARGS_SIZE);
170    my $cmdline = $buf;
171
172    # Ignore the id
173    read(INF, $buf, UNSIGNED_SIZE * 8);
174
175    # Close the file
176    close INF;
177
178    # Print important values
179    printf "Page size: %d (0x%08x)\n", $p_size, $p_size;
180    printf "Kernel size: %d (0x%08x)\n", $k_size, $k_size;
181    printf "Kernel addr: %d (0x%08x)\n", $k_addr, $k_addr;
182    printf "Ramdisk size: %d (0x%08x)\n", $r_size, $r_size;
183    printf "Ramdisk addr: %d (0x%08x)\n", $r_addr, $r_addr;
184    printf "Second size: %d (0x%08x)\n", $s_size, $s_size;
185    printf "Second addr: %d (0x%08x)\n", $s_addr, $s_addr;
186    printf "Board name: $name\n";
187    printf "Command line: $cmdline\n";
188
189    # Save the values
190    $PAGE_SIZE = $p_size;
191    $KERNEL_SIZE = $k_size;
192    $RAMDISK_SIZE = $r_size;
193    $SECOND_SIZE = $s_size;
194}
195
196sub dump_file {
197    my ($infn, $outfn, $offset, $size) = @_;
198    my $buf = undef;
199
200    open INF, $infn or die "Could not open $infn: $!\n";
201    open OUTF, ">$outfn" or die "Could not open $outfn: $!\n";
202
203    binmode INF;
204    binmode OUTF;
205
206    seek(INF, $offset, 0) or die "Could not seek in $infn: $!\n";
207    read(INF, $buf, $size) or die "Could not read $infn: $!\n";
208    print OUTF $buf or die "Could not write $outfn: $!\n";
209
210    close INF;
211    close OUTF;
212}
213
214######################################################################
215## Configuration Subroutines
216
217sub parse_cmdline {
218    unless ($#ARGV == 0) {
219        die "Usage: $SCRIPT boot.img\n";
220    }
221    $IMAGE_FN = $ARGV[0];
222}
223
224