1#!/usr/bin/perl 2# 3# Copyright (C) 2009 Henk Vergonet <Henk.Vergonet@gmail.com> 4# 5# This program is free software; you can redistribute it and/or modify 6# it under the terms of the GNU General Public License as published by 7# the Free Software Foundation; either version 2 of the License, or 8# (at your option) any later version. 9# 10# This program is distributed in the hope that it will be useful, 11# but WITHOUT ANY WARRANTY; without even the implied warranty of 12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13# GNU General Public License for more details. 14# 15# You should have received a copy of the GNU General Public License 16# along with this program; if not, write to the Free Software 17# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18# 19 20# Description: 21# Replacement for brcmImagebuilder 22# 23# Disclaimer: 24# Use this software at your own risk. 25# 26# Changelog: 27# 2009-01-01 Henk.Vergonet at gmail.com 28# 29use strict; 30use Getopt::Std; 31use Compress::Zlib; 32 33my $version = "0.1"; 34my %arg = ( 35 o => 'bcm963xx_fs_kernel', 36 b => 'OpenWrt', 37 c => '6348', 38 s => 64, 39 f => 0xbfc00000, 40 x => 0x00010000, 41 a => 0x80010000, 42 e => 0x80010000, 43 i => 2, 44); 45my $prog = $0; 46$prog =~ s/^.*\///; 47getopts("r:k:o:lc:b:s:f:i:a:e:tpvh", \%arg); 48 49die "usage: $prog ~opts~ 50 51 -r <file> : input rootfs file 52 -k <file> : input kernel file 53 -o <file> : output image file, default $arg{o} 54 -l : littleendian system, default ".($arg{l} ? 'yes' : 'no')." 55 -c <chipid> : default $arg{c} 56 -b <boardid> : default $arg{b} 57 -s <size_kb> : erase sise flash, default $arg{s} 58 -f <baseaddr> : flash base, default ".sprintf('0x%x', $arg{f})." 59 -x <cfelen> : length of cfe, default ".sprintf('0x%x', $arg{x})." 60 -i : 2=dual image, default $arg{i} 61 62 -a <loadaddr> : Kernel load address, default ".sprintf('0x%x', $arg{a})." 63 -e <entryaddr>: Kernel entry address, default ".sprintf('0x%x', $arg{e})." 64 -t : Prefix kernel with load,entry,size 65 66 -p : Add a 'gOtO' partition 67 68 -v : be more verbose 69 -h : help, version $version 70 71EXAMPLES: 72 $prog -k kern -r rootfs 73" if $arg{h} || !$arg{k} || !$arg{r}; 74 75sub Read_Image 76{ 77 open my $fh, $_[0] or die "open $_[0]: $!"; 78 local $/; # Set input to "slurp" mode. 79 my $buf = <$fh>; 80 close $fh; 81 return $buf; 82} 83 84sub Padlen 85{ 86 my $p = $_[0] % $_[1]; 87 return ($p ? $_[1] - $p : 0); 88} 89 90sub Pad 91{ 92 my ($buf, $off, $bs) = @_[0..2]; 93 $buf .= chr(255) x Padlen(length($buf) + $off, $bs); 94 return $buf; 95} 96 97sub bcmImage 98{ 99 my ($k, $f) = @_[0..1]; 100 my $tmp = $arg{x} + 0x100 + $arg{f}; 101 102 # regular: rootfs+kernel 103 my ($img, $fa, $ka) = ( $f.$k, $tmp, $tmp + length($f) ); 104 105 # test: kernel+rootfs 106# my ($img, $fa, $ka) = ( $k.$f, $tmp + length($k), $tmp ); 107 108 $fa = 0 unless length($f); 109 110 my $hdr = pack("a4a20a14a6a16a2a10a12a10a12a10a12a10a2a2a74Na16", 111 '6', 112 'LinuxInside', 113 'ver. 2.0', 114 $arg{c}, 115 $arg{b}, 116 ($arg{l} ? '0' : '1'), 117 length($img), 118 '0', 119 '0', 120 $fa, 121 length($f), 122 $ka, 123 length($k), 124 ($arg{i}==2 ? '1' : '0'), 125 '', # if 1, the image is INACTIVE; if 0, active 126 '', 127 ~crc32($k, crc32($f)), 128 ''); 129 $hdr .= pack('Na16', ~crc32($hdr), ''); 130 131 printf "kernel at 0x%x length 0x%x(%u)\n", $ka, length($k), length($k) 132 if $arg{v}; 133 printf "rootfs at 0x%x length 0x%x(%u)\n", $fa, length($f), length($f) 134 if $arg{v}; 135 136 open(FO, ">$arg{o}"); 137 print FO $hdr; 138 print FO $img; 139 close FO; 140} 141 142# MAIN 143 144my $kern = Read_Image $arg{k}; 145my $root = Read_Image $arg{r}; 146 147$kern = pack('NNN', $arg{a}, $arg{e}, length($kern)).$kern if $arg{t}; 148 149# specific fixup for the CFE that expects rootfs-kernel order 150if ($arg{p}) { 151 $kern = Pad($kern, 0x10c, $arg{s} * 1024); 152 my $dummy_root = pack('a4NN', 153 'gOtO', 154 length($kern)+12, 155 length($root)+Padlen(length($root), $arg{s} * 1024) 156 ); 157 $kern .= $root; 158 $root = $dummy_root; 159} 160 161bcmImage($kern, $root); 162 163