summaryrefslogtreecommitdiffstats
path: root/arch/ppc/treeboot/mkirimg
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-04 07:40:19 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-04 07:40:19 +0000
commit33263fc5f9ac8e8cb2b22d06af3ce5ac1dd815e4 (patch)
tree2d1b86a40bef0958a68cf1a2eafbeb0667a70543 /arch/ppc/treeboot/mkirimg
parent216f5f51aa02f8b113aa620ebc14a9631a217a00 (diff)
Merge with Linux 2.3.32.
Diffstat (limited to 'arch/ppc/treeboot/mkirimg')
-rw-r--r--arch/ppc/treeboot/mkirimg367
1 files changed, 367 insertions, 0 deletions
diff --git a/arch/ppc/treeboot/mkirimg b/arch/ppc/treeboot/mkirimg
new file mode 100644
index 000000000..e8aa24e3d
--- /dev/null
+++ b/arch/ppc/treeboot/mkirimg
@@ -0,0 +1,367 @@
+#!/usr/local/bin/perl
+#
+# Copyright (c) 1998-1999 TiVo, Inc.
+# Original ELF parsing code.
+#
+# Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+# Original code from 'mkevimg'.
+#
+# Module name: mkirimg
+#
+# Description:
+# Reads an ELF file and assigns global variables 'imageSect_start',
+# 'imageSect_size', 'initrdSect_start', and 'initrdSect_size' from
+# the "image" and "initrd" section header information. It then
+# rewrites the input ELF file with assigned globals to an output
+# file.
+#
+# An input file, "irSectStart.txt" has the memory address of
+# 'irSectStart'. The irSectStart memory address is used to find
+# the global variables in the ".data" section of the ELF file.
+# The 'irSectStart' and the above global variables are defined
+# in "irSect.c".
+#
+#
+
+use File::Basename;
+use Getopt::Std;
+
+#
+# usage()
+#
+# Description:
+# This routine prints out the proper command line usage for this program
+#
+# Input(s):
+# status - Flag determining what usage information will be printed and what
+# the exit status of the program will be after the information is
+# printed.
+#
+# Output(s):
+# N/A
+#
+# Returns:
+# This subroutine does not return.
+#
+
+sub usage {
+ my($status);
+ $status = $_[0];
+
+ printf("Usage: %s [-hvV] <ELF input file> <Evaluation board output file> <irSectStart.txt file>\n",
+ $program);
+
+ if ($status != 0) {
+ printf("Try `%s -h' for more information.\n", $program);
+ }
+
+ if ($status != 1) {
+ print(" -h Print out this message and exit.\n");
+ print(" -v Verbose. Print out lots of ELF information.\n");
+ print(" -V Print out version information and exit.\n");
+ }
+
+ exit($status);
+}
+
+#
+# version()
+#
+# Description:
+# This routine prints out program version information
+#
+# Input(s):
+# N/A
+#
+# Output(s):
+# N/A
+#
+# Returns:
+# This subroutine does not return.
+#
+
+sub version {
+ print("mkirimg Version 1.1.0\n");
+ print("Copyright (c) 1998-1999 TiVo, Inc.\n");
+ print("Copyright (c) 1999 Grant Erickson <grant\@lcse.umn.edu>\n");
+
+ exit (0);
+}
+
+#
+# file_check()
+#
+# Description:
+# This routine checks an input file to ensure that it exists, is a
+# regular file, and is readable.
+#
+# Input(s):
+# file - Input file to be checked.
+#
+# Output(s):
+# N/A
+#
+# Returns:
+# 0 if the file exists, is a regular file, and is readable, otherwise -1.
+#
+
+sub file_check {
+ my($file);
+ $file = $_[0];
+
+ if (!(-e $file)) {
+ printf("The file \"%s\" does not exist.\n", $file);
+ return (-1);
+ } elsif (!(-f $file)) {
+ printf("The file \"%s\" is not a regular file.\n", $file);
+ return (-1);
+ } elsif (!(-r $file)) {
+ printf("The file \"%s\" is not readable.\n", $file);
+ return (-1);
+ }
+
+ return (0);
+}
+
+#
+# decode_options()
+#
+# Description:
+# This routine steps through the command-line arguments, parsing out
+# recognzied options.
+#
+# Input(s):
+# N/A
+#
+# Output(s):
+# N/A
+#
+# Returns:
+# N/A
+#
+
+sub decode_options {
+
+ if (!getopts("hvV")) {
+ usage(1);
+ }
+
+ if ($opt_h) {
+ usage(0);
+ }
+
+ if ($opt_V) {
+ version();
+ exit (0);
+ }
+
+ if ($opt_v) {
+ $verbose = 1;
+ }
+
+ if (!($ElfFile = shift(@ARGV))) {
+ usage(1);
+ }
+
+ if (!($OutputFile = shift(@ARGV))) {
+ usage (1);
+ }
+
+ if (!($IrFile = shift(@ARGV))) {
+ usage (1);
+ }
+
+ if (file_check($ElfFile)) {
+ exit(1);
+ }
+
+ if (file_check($IrFile)) {
+ exit(1);
+ }
+}
+
+#
+# ELF file and section header field numbers
+#
+
+require 'elf.pl';
+
+#
+# Main program body
+#
+
+{
+ $program = basename($0);
+ decode_options();
+
+ open(ELF, "<$ElfFile") || die "Cannot open input file";
+ open(OUTPUT, ">$OutputFile") || die "Cannot open output file";
+ open(IR, "$IrFile") || die "Cannot open input file";
+
+ $ElfFilesize = (-s $ElfFile);
+
+ if (read(ELF, $ibuf, $ElfFilesize) != $ElfFilesize) {
+ print("Failed to read ELF input file!\n");
+ exit(1);
+ }
+
+ if (read(IR, $irbuf, 8) != 8) {
+ print("Failed to read Ir input file!\n");
+ exit(1);
+ }
+
+ #
+ # Parse ELF header
+ #
+
+ @eh = unpack("a16n2N5n6", $ibuf);
+
+ #
+ # Make sure this is actually a PowerPC ELF file.
+ #
+
+ if (substr($eh[$e_ident], 0, 4) ne "\177ELF") {
+ printf("The file \"%s\" is not an ELF file.\n", $ElfFile);
+ exit (1);
+ } elsif ($eh[$e_machine] != 20) {
+ printf("The file \"%s\" is not a PowerPC ELF file.\n", $ElfFile);
+ exit (1);
+ }
+
+ #
+ # Find the section header for the string table.
+ #
+
+ $strtable_section_offset = $eh[$e_shoff] +
+
+ $eh[$e_shstrndx] * $eh[$e_shentsize];
+
+ if ($verbose) {
+ printf("String table section header offset: 0x%x\n",
+ $strtable_section_offset);
+ }
+
+ #
+ # Find the start of the string table.
+ #
+
+ @strh = unpack("N10", substr($ibuf, $strtable_section_offset,
+ $eh[$e_shentsize]));
+
+ if ($verbose) {
+ printf("Section name strings start at: 0x%x, %d bytes.\n",
+ $strh[$sh_offset], $strh[$sh_size]);
+ }
+
+ $names = substr($ibuf, $strh[$sh_offset], $strh[$sh_size]);
+
+ # Grab each section header and find '.data', 'image', and
+ # 'initrd' sections in particular.
+
+ $off = $eh[$e_shoff];
+ $imageFound = 0;
+ $initrdFound = 0;
+
+ for($i = 0; $i < $eh[$e_shnum]; $i++, $off += $eh[$e_shentsize]) {
+ @sh = unpack("N10", substr($ibuf, $off, $eh[$e_shentsize]));
+
+ # Take the first section name from the array returned by split.
+
+ ($name) = split(/\000/, substr($names, $sh[$sh_name]));
+
+ # Attempt to find the .data, image, and initrd sections
+
+ if ($name =~ /^\image$/) {
+ ($image_addr, $image_offset, $image_size) =
+ ($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
+ $imageFound = 1;
+
+ } elsif ($name =~ /^\initrd$/) {
+ ($initrd_addr, $initrd_offset, $initrd_size) =
+ ($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
+ $initrdFound = 1;
+
+ } elsif ($name =~ /^\.data$/) {
+ ($data_addr, $data_offset, $data_size) =
+ ($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
+
+ } elsif ($name =~ /^\.bss$/) {
+ ($bss_addr, $bss_offset, $bss_size) =
+ ($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
+
+ }
+ }
+
+ if ($verbose) {
+ printf("Data section - Address: 0x%08x, Size: 0x%08x, File Offset 0x%08x\n",
+ $data_addr, $data_size, $data_offset);
+ printf("Bss section - Address: 0x%08x, Size: 0x%08x, File Offset 0x%08x\n",
+ $bss_addr, $bss_size, $bss_offset);
+ }
+
+ if ($verbose) {
+ if ($imageFound) {
+ printf("Image section - Address: 0x%08x, Size: 0x%08x\n",
+ $image_addr, $image_size);
+ } else {
+ printf("Image section not found in file: $ElfFile\n");
+ }
+
+ if ($initrdFound) {
+ printf("Initrd section - Address: 0x%08x, Size: 0x%08x\n",
+ $initrd_addr, $initrd_size);
+ } else {
+ printf("Initrd section not found in file: $ElfFile\n");
+ }
+ }
+
+ # get file offset of irSectStart
+
+ $irSectStartoffset = hex ($irbuf);
+
+ if ($verbose) {
+ printf("irSectStartOffset Address: 0x%08x\n", $irSectStartoffset);
+ }
+
+ # get the offset of global variables
+
+ $initialOffset = ($irSectStartoffset - $data_addr) + $data_offset + 4;
+
+ # write modified values to OUTPUT file
+
+ syswrite(OUTPUT, $ibuf, $initialOffset);
+
+ if ($imageFound) {
+ $testN = pack ("I2", $bss_addr + $bss_size, $image_size);
+ syswrite(OUTPUT, $testN, length($testN));
+ printf("Updated symbol \"imageSect_start\" to 0x%08x\n",
+ $bss_addr + $bss_size);
+ printf("Updated symbol \"imageSect_size\" to 0x%08x\n", $image_size);
+ } else {
+ syswrite(OUTPUT, $ibuf, 8, $initialOffset);
+ }
+
+ if ($initrdFound) {
+ $testN = pack ("I2", $bss_addr + $bss_size + $image_size, $initrd_size);
+ syswrite(OUTPUT, $testN, length($testN));
+ printf("Updated symbol \"initrdSect_start\" to 0x%08x\n",
+ $bss_addr + $bss_size + $image_size);
+ printf("Updated symbol \"initrdSect_size\" to 0x%08x\n", $initrd_size);
+ } else {
+ syswrite(OUTPUT, $ibuf,8, $initialOffset + 8);
+ }
+
+ syswrite(OUTPUT, $ibuf, $ElfFilesize - ($initialOffset + 16),
+ $initialOffset + 16);
+
+ #
+ # Clean-up and leave
+ #
+
+ close (ELF);
+ close (OUTPUT);
+ close (IR);
+
+ exit (0);
+}
+