手順は http://goo.gl/3kYZb を参照して実行。 以下、linux上の作業と、adb shell上の作業のログ。 吸い出したmtd2のイメージを再構築して書き戻しているだけ。 [rt@localhost is06]$ ls -l 合計 6944 -rwxr-xr-x 1 rt rt 24302 6月 3日 02:25 mkbootfs* -rwxr-xr-x 1 rt rt 23798 6月 3日 02:25 mkbootimg* -rw-r--r-- 1 rt rt 6553600 6月 3日 02:19 mtd2.raw -rw-r--r-- 1 rt rt 479568 6月 4日 07:53 ramdisk-new.gz -rwxr-xr-x 1 rt rt 6202 6月 3日 02:41 split_bootimg.pl* [rt@localhost is06]$ ./split_bootimg.pl mtd2.raw Page size: 2048 (0x00000800) Kernel size: 2842696 (0x002b6048) Ramdisk size: 479585 (0x00075161) Second size: 0 (0x00000000) Board name: Command line: console=ttyHSL1,115200n8 pmem_kernel_ebi1_size=0x200000 androidboot.hardware=qcom Base Address: 0x20000000 Writing mtd2.raw-kernel ... complete. Writing mtd2.raw-ramdisk.gz ... complete. [rt@localhost is06]$ mkdir ramdisk [rt@localhost is06]$ cd ramdisk [rt@localhost ramdisk]$ gzip -dc ../mtd2.raw-ramdisk.gz | cpio -i 1779 blocks [rt@localhost ramdisk]$ cd .. [rt@localhost is06]$ ./mkbootfs ./ramdisk | gzip > ramdisk-new.gz [rt@localhost is06]$ ./mkbootimg --cmdline 'console=ttyHSL1,115200n8 pmem_kernel_ebi1_size=0x200000 androidboot.hardware=qcom' --base 0x20000000 --kernel mtd2.raw-kernel --ramdisk ramdisk-new.gz -o recovery.img [rt@localhost is06]$ ls -l 合計 13464 -rwxr-xr-x 1 rt rt 24302 6月 3日 02:25 mkbootfs* -rwxr-xr-x 1 rt rt 23798 6月 3日 02:25 mkbootimg* -rw-r--r-- 1 rt rt 6553600 6月 3日 02:19 mtd2.raw -rw-r--r-- 1 rt rt 2842696 6月 4日 10:19 mtd2.raw-kernel -rw-r--r-- 1 rt rt 479585 6月 4日 10:19 mtd2.raw-ramdisk.gz drwxr-xr-x 11 rt rt 4096 6月 4日 10:19 ramdisk/ -rw-r--r-- 1 rt rt 479568 6月 4日 10:20 ramdisk-new.gz -rw-r--r-- 1 rt rt 3328000 6月 4日 10:20 recovery.img -rwxr-xr-x 1 rt rt 6202 6月 3日 02:41 split_bootimg.pl* [rt@localhost is06]$ cat split_bootimg.pl #!/usr/bin/perl ###################################################################### # # File : split_bootimg.pl # Author(s) : William Enck # Description : Split appart an Android boot image created # with mkbootimg. The format can be found in # android-src/system/core/mkbootimg/bootimg.h # # Thanks to alansj on xda-developers.com for # identifying the format in bootimg.h and # describing initial instructions for splitting # the boot.img file. # # Last Modified : Tue Dec 2 23:36:25 EST 2008 # By : William Enck # # Copyright (c) 2008 William Enck # ###################################################################### 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"; printf "Base Address: 0x%08x\n", $k_addr - 0x8000 if $k_addr != 0x10008000; # 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]; } # cat /dev/zero > /dev/mtd/mtd2 cat /dev/zero > /dev/mtd/mtd2 # ./flash_image recovery recovery.img ./flash_image recovery recovery.img flashing recovery from recovery.img mtd: successfully wrote block at 0 mtd: successfully wrote block at 20000 mtd: successfully wrote block at 40000 mtd: successfully wrote block at 60000 mtd: successfully wrote block at 80000 mtd: successfully wrote block at a0000 mtd: successfully wrote block at c0000 mtd: successfully wrote block at e0000 mtd: successfully wrote block at 100000 mtd: successfully wrote block at 120000 mtd: successfully wrote block at 140000 mtd: successfully wrote block at 160000 mtd: successfully wrote block at 180000 mtd: successfully wrote block at 1a0000 mtd: successfully wrote block at 1c0000 mtd: successfully wrote block at 1e0000 mtd: successfully wrote block at 200000 mtd: successfully wrote block at 220000 mtd: successfully wrote block at 240000 mtd: successfully wrote block at 260000 mtd: successfully wrote block at 280000 mtd: successfully wrote block at 2a0000 mtd: successfully wrote block at 2c0000 mtd: successfully wrote block at 2e0000 mtd: successfully wrote block at 300000 mtd: successfully wrote block at 320000 mtd: successfully wrote block at 0 # ./flash_image recovery recovery.img ./flash_image recovery recovery.img header is the same, not flashing recovery