[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: apex-1.4.5



* Marc Singer <elf@buici.com> [2006-08-18 10:07]:
> I posted a new version of apex.  This version boots the test2 image

Thanks a lot!

Below is the patch used to create this image.  Rod, can you please
review?

--- slugimage~	2006-08-04 22:52:24.000000000 +0200
+++ slugimage	2006-08-18 19:17:37.000000000 +0200
@@ -39,12 +39,13 @@
 use strict;
 use warnings;
 
-use Getopt::Long;
+use Getopt::Long qw(:config no_ignore_case);
 use POSIX qw(tmpnam);
 
 my($debug) = 1;
 my($quiet) = 0;
 my($block_size) = 0x00020000;
+my(@cleanup);
 
 # The last 70 bytes of the SercommRedBootTrailer (i.e. excluding MAC
 # address).  Needed to create an image with an empty RedBoot partition
@@ -582,6 +583,16 @@
 	    # Pack and append the binary table entry for this partition.
 	    $partition_data .= createPartitionEntry($_->{'name'}, $_->{'offset'} + $flash_start, $_->{'size'});
 
+	    # Optionally put a skip header into the padding area.
+	    if (defined $_->{'skip'}) {
+		my $i = 1;
+		foreach my $skip (@{$_->{'skip'}}) {
+		    substr($partition_data, -8 - 12*$i, 12) = pack("a4N2", "skip",
+			$skip->{'offset'}, $skip->{'size'});
+		    $i++;
+		}
+	    }
+
 	    # If this is the FIS directory, then write the partition table data into it.
 	    if ($_->{'name'} eq "FIS directory") {
 		# Explicitly terminate the partition data.
@@ -725,9 +736,11 @@
     } @partitions;
 }
 
-sub defaultPartitions {
+sub defaultPartitions($) {
+    my($loader) = @_;
 
-    return ({'name'=>'RedBoot',           'file'=>'RedBoot',
+    my @partitions =
+	    ({'name'=>'RedBoot',          'file'=>'RedBoot',
 	     'offset'=>0x00000000,        'size'=>0x00040000,
 	     'variable'=>0, 'header'=>0,  'pseudo'=>0, 'data'=>undef, 'byteswap'=>0},
 	    {'name'=>'EthAddr',           'file'=>undef,
@@ -735,13 +748,44 @@
 	     'variable'=>0, 'header'=>0,  'pseudo'=>1, 'data'=>undef, 'byteswap'=>0},
 	    {'name'=>'SysConf',           'file'=>'SysConf',
 	     'offset'=>0x00040000,        'size'=>0x00020000,
-	     'variable'=>0, 'header'=>0,  'pseudo'=>0, 'data'=>undef, 'byteswap'=>0},
-	    {'name'=>'Kernel',            'file'=>'vmlinuz',
-	     'offset'=>0x00060000,        'size'=>0x00100000,
+	     'variable'=>0, 'header'=>0,  'pseudo'=>0, 'data'=>undef, 'byteswap'=>0});
+
+    my $loader_size = 0;
+    if ($loader) {
+	$loader_size = 0x00020000;
+	push @partitions,
+	   ({'name'=>'Loader',            'file'=>'loader',
+	     'offset'=>0x00060000,        'size'=>$loader_size,
+	     'variable'=>0, 'header'=>16, 'pseudo'=>0, 'data'=>undef, 'byteswap'=>0});
+    }
+
+    push @partitions,
+	    ({'name'=>'Kernel',           'file'=>'vmlinuz',
+	     'offset'=>(0x00060000+$loader_size),
+	     'variable'=>0, 'header'=>16, 'pseudo'=>0, 'data'=>undef, 'byteswap'=>0});
+
+    if ($loader) {
+	# If a second stage boot loader is defined (APEX), we create two
+	# kernel partitions, one beginning right after APEX and one
+	# beginning where RedBoot expects the ramdisk.  Additionally, we
+	# define a pseudo kernel partition (Kernel) which spans both kernel
+	# partitions (Kernel1 and Kernel2) and which has some information
+	# in the padding area of the FIS partition informing APEX which part
+	# to skip in order to get a good kernel image (i.e. the Sercomm
+	# header that sits between the two parts of the kernel image).
+	push @partitions,
+	   ({'name'=>'Kernel1',           'file'=>'vmlinuz1',
+	     'offset'=>(0x00060000+$loader_size), 'size'=>(0x00160000-0x00060000-$loader_size),
 	     'variable'=>0, 'header'=>16, 'pseudo'=>0, 'data'=>undef, 'byteswap'=>0},
-	    {'name'=>'Ramdisk',           'file'=>'ramdisk.gz',
-	     'offset'=>0x00160000,        'size'=>0x006a0000,
-	     'variable'=>1, 'header'=>16, 'pseudo'=>0, 'data'=>undef, 'byteswap'=>0},
+	    {'name'=>'Kernel2',           'file'=>'vmlinuz2',
+	     'offset'=>0x00160000,
+	     'variable'=>1, 'header'=>16, 'pseudo'=>0, 'data'=>undef, 'byteswap'=>0});
+    }
+
+    push @partitions,
+	   ({'name'=>'Ramdisk',           'file'=>'ramdisk.gz',
+	     'variable'=>1,               'pseudo'=>0, 'data'=>undef, 'byteswap'=>0,
+	     'header'=>($loader ? 0 : 16)},
 	    {'name'=>'FIS directory',     'file'=>undef,
 	     'offset'=>0x007e0000,        'size'=>0x00020000,
 	     'variable'=>0, 'header'=>0,  'pseudo'=>0, 'data'=>undef, 'byteswap'=>0},
@@ -750,17 +794,48 @@
 	     'variable'=>1, 'header'=>16, 'pseudo'=>1, 'data'=>undef, 'byteswap'=>0},
 	    {'name'=>'Trailer',           'file'=>'Trailer',
 	     'offset'=>0x007ffff0,        'size'=>0x00000010,
-	     'variable'=>0, 'header'=>0,  'pseudo'=>1, 'data'=>undef, 'byteswap'=>0},
-	    );
+	     'variable'=>0, 'header'=>0,  'pseudo'=>1, 'data'=>undef, 'byteswap'=>0});
 
+    if (!$loader) {
+	map { ($_->{'name'} eq 'Kernel') && ($_->{'offset'} = 0x00060000); } @partitions;
+	map { ($_->{'name'} eq 'Kernel') && ($_->{'size'} = 0x00100000); } @partitions;
+	map { ($_->{'name'} eq 'Ramdisk') && ($_->{'offset'} = 0x00160000); } @partitions;
+	map { ($_->{'name'} eq 'Ramdisk') && ($_->{'size'} = 0x006a0000); } @partitions;
+    }
+    return @partitions;
 }
 
-# Main routine starts here ...
+# Split a file into two.  Takes the name of the input file and the size
+# wanted for the first output file.
+sub splitFile($$) {
+    my($file, $size) = @_;
+    local $/ = undef;
+    open TMP, $file or die "Can't find file \"$file\": $!\n";
+    binmode(TMP);
+    my $data = <TMP>;
+    close TMP;
+    # Write the first part
+    my $file1 = tmpnam();
+    open TMP, ">$file1" or die "Cannot open file $file1: $!";
+    binmode(TMP);
+    push @cleanup, $file1;
+    print TMP substr($data, 0, $size);
+    close TMP;
+    # ... and the second one
+    my $file2 = tmpnam();
+    open TMP, ">$file2" or die "Cannot open file $file2: $!";
+    binmode(TMP);
+    push @cleanup, $file2;
+    print TMP substr($data, $size);
+    close TMP;
+    return ($file1, $file2);
+}
 
-my(@partitions) = defaultPartitions();
+# Main routine starts here ...
 
-my($unpack, $pack, $little, $input, $output, $redboot, $kernel, $sysconf, $ramdisk, $fisdir, $payload, $trailer, $ethaddr);
-my (@cleanup);
+my($unpack, $pack, $little, $input, $output, $redboot);
+my($kernel, $kernel1, $kernel2, $sysconf, $ramdisk, $fisdir);
+my($payload, $trailer, $ethaddr, $loader);
 
 END {
     # Remove temporary files
@@ -784,6 +859,7 @@
 		"y|payload=s"  => \$payload,
 		"t|trailer=s"  => \$trailer,
 		"e|ethaddr=s"  => \$ethaddr,
+		"L|loader=s"   => \$loader,
 		) or (not defined $pack and not defined $unpack)) {
     print "Usage: slugimage <options>\n";
     print "\n";
@@ -801,6 +877,7 @@
     print "  [-f|--fisdir]   <file>		Input/Output FIS directory filename\n";
     print "  [-y|--payload]  <file>		Input/Output Payload filename\n";
     print "  [-t|--trailer]  <file>		Input/Output Trailer filename\n";
+    print "  [-L|--loader]   <file>		Second stage boot loader filename\n";
     print "  [-e|--ethaddr]  <AABBCCDDEEFF>	Set the Ethernet address\n";
 
     # TODO: document --ramdisk syntax
@@ -808,6 +885,8 @@
     exit 1;
 }
 
+my(@partitions) = defaultPartitions($loader);
+
 if ($pack) {
     die "Output filename must be specified\n" unless defined $output;
 
@@ -849,7 +928,25 @@
 
 # Go through the partition options, and set the names and files in @partitions
 if (defined $redboot) { map { ($_->{'name'} eq 'RedBoot') 	&& ($_->{'file'} = $redboot); } @partitions; }
-if (defined $kernel)  { map { ($_->{'name'} eq 'Kernel')  	&& ($_->{'file'} = $kernel);  } @partitions; }
+if (defined $loader)  { map { ($_->{'name'} eq 'Loader')  	&& ($_->{'file'} = $loader);  } @partitions; }
+if (defined $kernel)  { map { ($_->{'name'} eq 'Kernel') && ($_->{'file'} = $kernel); } @partitions; }
+if ($loader && $pack) {
+    # Split the kernel into two, define files for kernel1 and kernel2 und unset
+    # the original kernel so the pseudo partition doesn't contain any data.
+    map { ($_->{'name'} eq 'Kernel') && ($kernel = $_->{'file'}); } @partitions;
+    map { ($_->{'name'} eq 'Kernel') && ($_->{'file'} = undef); } @partitions;
+    my $size;
+    map { ($_->{'name'} eq 'Kernel1') && ($size = $_->{'size'}); } @partitions;
+    ($kernel1, $kernel2) = splitFile($kernel, $size-16);
+    map { ($_->{'name'} eq 'Kernel1') && ($_->{'file'} = $kernel1); } @partitions;
+    map { ($_->{'name'} eq 'Kernel2') && ($_->{'file'} = $kernel2); } @partitions;
+    # Define skip information which the 2nd stage boot loader can use to
+    # load the kernel.
+    my @skip;
+    push @skip, { 'offset' => 0, 'size' => 16 };
+    push @skip, { 'offset' => $size, 'size' => 16 }; # offset is the size of Kernel1
+    map { ($_->{'name'} eq 'Kernel') && ($_->{'skip'} = \@skip); } @partitions;
+}
 if (defined $sysconf) { map { ($_->{'name'} eq 'SysConf') 	&& ($_->{'file'} = $sysconf); } @partitions; }
 if (defined $fisdir)  { map { ($_->{'name'} eq 'FIS directory') && ($_->{'file'} = $fisdir);  } @partitions; }
 if (defined $payload) { map { ($_->{'name'} eq 'Payload')       && ($_->{'file'} = $payload); } @partitions; }
@@ -857,7 +954,10 @@
 
 if (defined $little)  {
     map {
-	if (($_->{'name'} eq 'Kernel') or
+	if (($_->{'name'} eq 'Loader') or
+	    ($_->{'name'} eq 'Kernel') or
+	    ($_->{'name'} eq 'Kernel1') or
+	    ($_->{'name'} eq 'Kernel2') or
 	    ($_->{'name'} eq 'Ramdisk')) {
 	    $_->{'byteswap'} = 1;
 	}
@@ -946,6 +1046,7 @@
 
 # Read in the firmware image
 if ($input) {
+    map { ($_->{'name'} eq 'Kernel') && ($_->{'variable'} = 1); } @partitions;
     my $result = readInFirmware($input, \@partitions);
 }
 
@@ -981,6 +1082,15 @@
     
     layoutPartitions(@partitions);
 
+    if ($loader) {
+	# The pseudo kernel partitions spans both the kernel1 and kernel2
+	# partition; set its size accordingly.
+	my $size = 0;
+	map { ($_->{'name'} eq 'Kernel1') && ($size += $_->{'size'}); } @partitions;
+	map { ($_->{'name'} eq 'Kernel2') && ($size += $_->{'size'}); } @partitions;
+	map { ($_->{'name'} eq 'Kernel') && ($_->{'size'} = $size); } @partitions;
+    }
+
      if ($debug) {
  	print "after layoutPartitions():\n";
  	printPartitions(@partitions);

-- 
Martin Michlmayr
http://www.cyrius.com/



Reply to: