Guest User

split_bootimg.pl

a guest
Nov 4th, 2015
140
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.19 KB | None | 0 0
  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.  
  22. use strict;
  23. use warnings;
  24.  
  25. # Turn on print flushing
  26. $|++;
  27.  
  28. ######################################################################
  29. ## Global Variables and Constants
  30.  
  31. my $SCRIPT = __FILE__;
  32. my $IMAGE_FN = undef;
  33.  
  34. # Constants (from bootimg.h)
  35. use constant BOOT_MAGIC => 'ANDROID!';
  36. use constant BOOT_MAGIC_SIZE => 8;
  37. use constant BOOT_NAME_SIZE => 16;
  38. use constant BOOT_ARGS_SIZE => 512;
  39.  
  40. # Unsigned integers are 4 bytes
  41. use constant UNSIGNED_SIZE => 4;
  42.  
  43. # Parsed Values
  44. my $PAGE_SIZE = undef;
  45. my $KERNEL_SIZE = undef;
  46. my $RAMDISK_SIZE = undef;
  47. my $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.  
  71. my $n = int(($KERNEL_SIZE + $PAGE_SIZE - 1) / $PAGE_SIZE);
  72. my $m = int(($RAMDISK_SIZE + $PAGE_SIZE - 1) / $PAGE_SIZE);
  73. my $o = int(($SECOND_SIZE + $PAGE_SIZE - 1) / $PAGE_SIZE);
  74.  
  75. my $k_offset = $PAGE_SIZE;
  76. my $r_offset = $k_offset + ($n * $PAGE_SIZE);
  77. my $s_offset = $r_offset + ($m * $PAGE_SIZE);
  78.  
  79. (my $base = $IMAGE_FN) =~ s/.*\/(.*)$/$1/;
  80. my $k_file = $base . "-kernel";
  81. my $r_file = $base . "-ramdisk.gz";
  82. my $s_file = $base . "-second.gz";
  83.  
  84. # The kernel is always there
  85. print "Writing $k_file ...";
  86. &dump_file($IMAGE_FN, $k_file, $k_offset, $KERNEL_SIZE);
  87. print " complete.\n";
  88.  
  89. # The ramdisk is always there
  90. print "Writing $r_file ...";
  91. &dump_file($IMAGE_FN, $r_file, $r_offset, $RAMDISK_SIZE);
  92. print " complete.\n";
  93.  
  94. # The Second stage bootloader is optional
  95. unless ($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)
  105. struct 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
  129. sub 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 "Ramdisk size: %d (0x%08x)\n", $r_size, $r_size;
  182. printf "Second size: %d (0x%08x)\n", $s_size, $s_size;
  183. printf "Board name: $name\n";
  184. printf "Command line: $cmdline\n";
  185.  
  186. # Save the values
  187. $PAGE_SIZE = $p_size;
  188. $KERNEL_SIZE = $k_size;
  189. $RAMDISK_SIZE = $r_size;
  190. $SECOND_SIZE = $s_size;
  191. }
  192.  
  193. sub dump_file {
  194. my ($infn, $outfn, $offset, $size) = @_;
  195. my $buf = undef;
  196.  
  197. open INF, $infn or die "Could not open $infn: $!\n";
  198. open OUTF, ">$outfn" or die "Could not open $outfn: $!\n";
  199.  
  200. binmode INF;
  201. binmode OUTF;
  202.  
  203. seek(INF, $offset, 0) or die "Could not seek in $infn: $!\n";
  204. read(INF, $buf, $size) or die "Could not read $infn: $!\n";
  205. print OUTF $buf or die "Could not write $outfn: $!\n";
  206.  
  207. close INF;
  208. close OUTF;
  209. }
  210.  
  211. ######################################################################
  212. ## Configuration Subroutines
  213.  
  214. sub parse_cmdline {
  215. unless ($#ARGV == 0) {
  216. die "Usage: $SCRIPT boot.img\n";
  217. }
  218. $IMAGE_FN = $ARGV[0];
  219. }
Add Comment
Please, Sign In to add comment