mkirimg
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:8k
- #!/usr/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.0n");
- 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 '../utils/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%xn",
- $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(/ 00/, 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%08xn",
- $data_addr, $data_size, $data_offset);
- printf("Bss section - Address: 0x%08x, Size: 0x%08x, File Offset 0x%08xn",
- $bss_addr, $bss_size, $bss_offset);
- }
- if ($verbose) {
- if ($imageFound) {
- printf("Image section - Address: 0x%08x, Size: 0x%08xn",
- $image_addr, $image_size);
- } else {
- printf("Image section not found in file: $ElfFilen");
- }
- if ($initrdFound) {
- printf("Initrd section - Address: 0x%08x, Size: 0x%08xn",
- $initrd_addr, $initrd_size);
- } else {
- printf("Initrd section not found in file: $ElfFilen");
- }
- }
- # get file offset of irSectStart
- $irSectStartoffset = hex ($irbuf);
- if ($verbose) {
- printf("irSectStartOffset Address: 0x%08xn", $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 ("N2", $bss_addr + $bss_size, $image_size);
- syswrite(OUTPUT, $testN, length($testN));
- printf("Updated symbol "imageSect_start" to 0x%08xn",
- $bss_addr + $bss_size);
- printf("Updated symbol "imageSect_size" to 0x%08xn", $image_size);
- } else {
- syswrite(OUTPUT, $ibuf, 8, $initialOffset);
- }
- if ($initrdFound) {
- $testN = pack ("N2", $bss_addr + $bss_size + $image_size, $initrd_size);
- syswrite(OUTPUT, $testN, length($testN));
- printf("Updated symbol "initrdSect_start" to 0x%08xn",
- $bss_addr + $bss_size + $image_size);
- printf("Updated symbol "initrdSect_size" to 0x%08xn", $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);
- }