<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<oembed><type>rich</type><version>1.0</version><provider_name>phorkie</provider_name><provider_url>https://p.cweiske.de/</provider_url><title>split_bootimg.pl</title><author_name>Christian Weiske</author_name><cache_age>86400</cache_age><width>900</width><height>900</height><html>&lt;!-- embedding all files of https://p.cweiske.de/197 --&gt;
&lt;link rel="stylesheet" href="https://p.cweiske.de/css/embed.css"/&gt;
&lt;div class="phork" id="197"&gt;
    &lt;div class="phork-file"&gt;
 &lt;div class="phork-content"&gt;
  &lt;div class="code"&gt;&lt;pre class="txt"&gt;copied from http://www.enck.org/tools/split_bootimg_pl.txt&lt;/pre&gt;&lt;/div&gt;

 &lt;/div&gt;
 &lt;div class="phork-meta"&gt;
  &lt;a href="https://p.cweiske.de/197/rev-raw/2a3db1f76d8d99ed8eeadbad4fbd7e8987387213/README.txt" style="float: right"&gt;view raw source&lt;/a&gt;
  &lt;a href="https://p.cweiske.de/197#README.txt"&gt;README.txt&lt;/a&gt;
 &lt;/div&gt;
&lt;/div&gt;
    &lt;div class="phork-file"&gt;
 &lt;div class="phork-content"&gt;
  &lt;div class="code"&gt;&lt;pre class="txt"&gt;#!/usr/bin/perl&#13;
######################################################################&#13;
#&#13;
#   File          : split_bootimg.pl&#13;
#   Author(s)     : William Enck &amp;lt;enck@cse.psu.edu&amp;gt;&#13;
#   Description   : Split appart an Android boot image created &#13;
#                   with mkbootimg. The format can be found in&#13;
#                   android-src/system/core/mkbootimg/bootimg.h&#13;
#&#13;
#                   Thanks to alansj on xda-developers.com for &#13;
#                   identifying the format in bootimg.h and &#13;
#                   describing initial instructions for splitting&#13;
#                   the boot.img file.&#13;
#&#13;
#   Last Modified : Tue Dec  2 23:36:25 EST 2008&#13;
#   By            : William Enck &amp;lt;enck@cse.psu.edu&amp;gt;&#13;
#&#13;
#   Copyright (c) 2008 The Pennsylvania State University&#13;
#   Systems and Internet Infrastructure Security Laboratory&#13;
#&#13;
#   Licensed under the Apache License, Version 2.0 (the &amp;quot;License&amp;quot;); &#13;
#   you may not use this file except in compliance with the License. &#13;
#   You may obtain a copy of the License at &#13;
#&#13;
#       http://www.apache.org/licenses/LICENSE-2.0 &#13;
#&#13;
#   Unless required by applicable law or agreed to in writing, software &#13;
#   distributed under the License is distributed on an &amp;quot;AS IS&amp;quot; BASIS,&#13;
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#13;
#   See the License for the specific language governing permissions and&#13;
#   limitations under the License. &#13;
#&#13;
######################################################################&#13;
&#13;
use strict;&#13;
use warnings;&#13;
&#13;
# Turn on print flushing&#13;
$|++;&#13;
&#13;
######################################################################&#13;
## Global Variables and Constants&#13;
&#13;
my $SCRIPT = __FILE__;&#13;
my $IMAGE_FN = undef;&#13;
&#13;
# Constants (from bootimg.h)&#13;
use constant BOOT_MAGIC =&amp;gt; 'ANDROID!';&#13;
use constant BOOT_MAGIC_SIZE =&amp;gt; 8;&#13;
use constant BOOT_NAME_SIZE =&amp;gt; 16;&#13;
use constant BOOT_ARGS_SIZE =&amp;gt; 512;&#13;
&#13;
# Unsigned integers are 4 bytes&#13;
use constant UNSIGNED_SIZE =&amp;gt; 4;&#13;
&#13;
# Parsed Values&#13;
my $PAGE_SIZE = undef;&#13;
my $KERNEL_SIZE = undef;&#13;
my $RAMDISK_SIZE = undef;&#13;
my $SECOND_SIZE = undef;&#13;
&#13;
######################################################################&#13;
## Main Code&#13;
&#13;
&amp;amp;parse_cmdline();&#13;
&amp;amp;parse_header($IMAGE_FN);&#13;
&#13;
=format (from bootimg.h)&#13;
** +-----------------+&#13;
** | boot header     | 1 page&#13;
** +-----------------+&#13;
** | kernel          | n pages&#13;
** +-----------------+&#13;
** | ramdisk         | m pages&#13;
** +-----------------+&#13;
** | second stage    | o pages&#13;
** +-----------------+&#13;
**&#13;
** n = (kernel_size + page_size - 1) / page_size&#13;
** m = (ramdisk_size + page_size - 1) / page_size&#13;
** o = (second_size + page_size - 1) / page_size&#13;
=cut&#13;
&#13;
my $n = int(($KERNEL_SIZE + $PAGE_SIZE - 1) / $PAGE_SIZE);&#13;
my $m = int(($RAMDISK_SIZE + $PAGE_SIZE - 1) / $PAGE_SIZE);&#13;
my $o = int(($SECOND_SIZE + $PAGE_SIZE - 1) / $PAGE_SIZE);&#13;
&#13;
my $k_offset = $PAGE_SIZE;&#13;
my $r_offset = $k_offset + ($n * $PAGE_SIZE);&#13;
my $s_offset = $r_offset + ($m * $PAGE_SIZE);&#13;
&#13;
(my $base = $IMAGE_FN) =~ s/.*\/(.*)$/$1/;&#13;
my $k_file = $base . &amp;quot;-kernel&amp;quot;;&#13;
my $r_file = $base . &amp;quot;-ramdisk.gz&amp;quot;;&#13;
my $s_file = $base . &amp;quot;-second.gz&amp;quot;;&#13;
&#13;
# The kernel is always there&#13;
print &amp;quot;Writing $k_file ...&amp;quot;;&#13;
&amp;amp;dump_file($IMAGE_FN, $k_file, $k_offset, $KERNEL_SIZE);&#13;
print &amp;quot; complete.\n&amp;quot;;&#13;
&#13;
# The ramdisk is always there&#13;
print &amp;quot;Writing $r_file ...&amp;quot;;&#13;
&amp;amp;dump_file($IMAGE_FN, $r_file, $r_offset, $RAMDISK_SIZE);&#13;
print &amp;quot; complete.\n&amp;quot;;&#13;
&#13;
# The Second stage bootloader is optional&#13;
unless ($SECOND_SIZE == 0) {&#13;
    print &amp;quot;Writing $s_file ...&amp;quot;;&#13;
    &amp;amp;dump_file($IMAGE_FN, $s_file, $s_offset, $SECOND_SIZE);&#13;
    print &amp;quot; complete.\n&amp;quot;;&#13;
}&#13;
    &#13;
######################################################################&#13;
## Supporting Subroutines&#13;
&#13;
=header_format (from bootimg.h)&#13;
struct boot_img_hdr&#13;
{&#13;
    unsigned char magic[BOOT_MAGIC_SIZE];&#13;
&#13;
    unsigned kernel_size;  /* size in bytes */&#13;
    unsigned kernel_addr;  /* physical load addr */&#13;
&#13;
    unsigned ramdisk_size; /* size in bytes */&#13;
    unsigned ramdisk_addr; /* physical load addr */&#13;
&#13;
    unsigned second_size;  /* size in bytes */&#13;
    unsigned second_addr;  /* physical load addr */&#13;
&#13;
    unsigned tags_addr;    /* physical addr for kernel tags */&#13;
    unsigned page_size;    /* flash page size we assume */&#13;
    unsigned unused[2];    /* future expansion: should be 0 */&#13;
&#13;
    unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */&#13;
&#13;
    unsigned char cmdline[BOOT_ARGS_SIZE];&#13;
&#13;
    unsigned id[8]; /* timestamp / checksum / sha1 / etc */&#13;
};&#13;
=cut&#13;
sub parse_header {&#13;
    my ($fn) = @_;&#13;
    my $buf = undef;&#13;
&#13;
    open INF, $fn or die &amp;quot;Could not open $fn: $!\n&amp;quot;;&#13;
    binmode INF;&#13;
&#13;
    # Read the Magic&#13;
    read(INF, $buf, BOOT_MAGIC_SIZE);&#13;
    unless ($buf eq BOOT_MAGIC) {&#13;
	die &amp;quot;Android Magic not found in $fn. Giving up.\n&amp;quot;;&#13;
    }&#13;
&#13;
    # Read kernel size and address (assume little-endian)&#13;
    read(INF, $buf, UNSIGNED_SIZE * 2);&#13;
    my ($k_size, $k_addr) = unpack(&amp;quot;VV&amp;quot;, $buf);&#13;
&#13;
    # Read ramdisk size and address (assume little-endian)&#13;
    read(INF, $buf, UNSIGNED_SIZE * 2);&#13;
    my ($r_size, $r_addr) = unpack(&amp;quot;VV&amp;quot;, $buf);&#13;
&#13;
    # Read second size and address (assume little-endian)&#13;
    read(INF, $buf, UNSIGNED_SIZE * 2);&#13;
    my ($s_size, $s_addr) = unpack(&amp;quot;VV&amp;quot;, $buf);&#13;
&#13;
    # Ignore tags_addr&#13;
    read(INF, $buf, UNSIGNED_SIZE);&#13;
&#13;
    # get the page size (assume little-endian)&#13;
    read(INF, $buf, UNSIGNED_SIZE);&#13;
    my ($p_size) = unpack(&amp;quot;V&amp;quot;, $buf);&#13;
&#13;
    # Ignore unused&#13;
    read(INF, $buf, UNSIGNED_SIZE * 2);&#13;
&#13;
    # Read the name (board name)&#13;
    read(INF, $buf, BOOT_NAME_SIZE);&#13;
    my $name = $buf;&#13;
&#13;
    # Read the command line&#13;
    read(INF, $buf, BOOT_ARGS_SIZE);&#13;
    my $cmdline = $buf;&#13;
&#13;
    # Ignore the id&#13;
    read(INF, $buf, UNSIGNED_SIZE * 8);&#13;
&#13;
    # Close the file&#13;
    close INF;&#13;
&#13;
    # Print important values&#13;
    printf &amp;quot;Page size: %d (0x%08x)\n&amp;quot;, $p_size, $p_size;&#13;
    printf &amp;quot;Kernel size: %d (0x%08x)\n&amp;quot;, $k_size, $k_size;&#13;
    printf &amp;quot;Ramdisk size: %d (0x%08x)\n&amp;quot;, $r_size, $r_size;&#13;
    printf &amp;quot;Second size: %d (0x%08x)\n&amp;quot;, $s_size, $s_size;&#13;
    printf &amp;quot;Board name: $name\n&amp;quot;;&#13;
    printf &amp;quot;Command line: $cmdline\n&amp;quot;;&#13;
&#13;
    # Save the values&#13;
    $PAGE_SIZE = $p_size;&#13;
    $KERNEL_SIZE = $k_size;&#13;
    $RAMDISK_SIZE = $r_size;&#13;
    $SECOND_SIZE = $s_size;&#13;
}&#13;
&#13;
sub dump_file {&#13;
    my ($infn, $outfn, $offset, $size) = @_;&#13;
    my $buf = undef;&#13;
&#13;
    open INF, $infn or die &amp;quot;Could not open $infn: $!\n&amp;quot;;&#13;
    open OUTF, &amp;quot;&amp;gt;$outfn&amp;quot; or die &amp;quot;Could not open $outfn: $!\n&amp;quot;;&#13;
&#13;
    binmode INF;&#13;
    binmode OUTF;&#13;
&#13;
    seek(INF, $offset, 0) or die &amp;quot;Could not seek in $infn: $!\n&amp;quot;;&#13;
    read(INF, $buf, $size) or die &amp;quot;Could not read $infn: $!\n&amp;quot;;&#13;
    print OUTF $buf or die &amp;quot;Could not write $outfn: $!\n&amp;quot;;&#13;
&#13;
    close INF;&#13;
    close OUTF;&#13;
}&#13;
&#13;
######################################################################&#13;
## Configuration Subroutines&#13;
&#13;
sub parse_cmdline {&#13;
    unless ($#ARGV == 0) {&#13;
	die &amp;quot;Usage: $SCRIPT boot.img\n&amp;quot;;&#13;
    }&#13;
    $IMAGE_FN = $ARGV[0];&#13;
}&#13;
&#13;
&#13;
&lt;/pre&gt;&lt;/div&gt;

 &lt;/div&gt;
 &lt;div class="phork-meta"&gt;
  &lt;a href="https://p.cweiske.de/197/rev-raw/2a3db1f76d8d99ed8eeadbad4fbd7e8987387213/split_bootimg.pl.txt" style="float: right"&gt;view raw source&lt;/a&gt;
  &lt;a href="https://p.cweiske.de/197#split_bootimg.pl.txt"&gt;split_bootimg.pl.txt&lt;/a&gt;
 &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</html></oembed>
