mkirimg
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:8k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. #!/usr/bin/perl
  2. #
  3. #    Copyright (c) 1998-1999 TiVo, Inc.
  4. #      Original ELF parsing code.
  5. #
  6. #    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
  7. #      Original code from 'mkevimg'.
  8. #
  9. #    Module name: mkirimg
  10. #
  11. #    Description:
  12. #      Reads an ELF file and assigns global variables 'imageSect_start',
  13. #      'imageSect_size', 'initrdSect_start', and 'initrdSect_size' from
  14. #      the "image" and "initrd" section header information. It then
  15. #      rewrites the input ELF file with assigned globals to an output
  16. #      file.
  17. #
  18. #      An input file, "irSectStart.txt" has the memory address of
  19. #      'irSectStart'. The irSectStart memory address is used to find
  20. #      the global variables in the ".data" section of the ELF file.
  21. #      The 'irSectStart' and the above global variables are defined
  22. #      in "irSect.c".
  23. #
  24. #
  25. use File::Basename;
  26. use Getopt::Std;
  27. #
  28. # usage()
  29. #
  30. # Description:
  31. #   This routine prints out the proper command line usage for this program
  32. #
  33. # Input(s):
  34. #   status - Flag determining what usage information will be printed and what
  35. #            the exit status of the program will be after the information is
  36. #            printed.
  37. #
  38. # Output(s):
  39. #   N/A
  40. #
  41. # Returns:
  42. #   This subroutine does not return.
  43. #
  44. sub usage {
  45.   my($status);
  46.   $status = $_[0];
  47.   printf("Usage: %s [-hvV] <ELF input file> <Evaluation board output file> <irSectStart.txt file>n",
  48.  $program);
  49.   if ($status != 0) {
  50.     printf("Try `%s -h' for more information.n", $program);
  51.   }
  52.   if ($status != 1) {
  53.     print("  -h             Print out this message and exit.n");
  54.     print("  -v             Verbose. Print out lots of ELF information.n");
  55.     print("  -V             Print out version information and exit.n");
  56.   }
  57.   exit($status);
  58. }
  59. #
  60. # version()
  61. #
  62. # Description:
  63. #   This routine prints out program version information
  64. #
  65. # Input(s):
  66. #   N/A
  67. #
  68. # Output(s):
  69. #   N/A
  70. #
  71. # Returns:
  72. #   This subroutine does not return.
  73. #
  74. sub version {
  75.   print("mkirimg Version 1.1.0n");
  76.   print("Copyright (c) 1998-1999 TiVo, Inc.n");
  77.   print("Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>n");
  78.   exit (0);
  79. }
  80. #
  81. # file_check()
  82. #
  83. # Description:
  84. #   This routine checks an input file to ensure that it exists, is a
  85. #   regular file, and is readable.
  86. #
  87. # Input(s):
  88. #   file - Input file to be checked.
  89. #
  90. # Output(s):
  91. #   N/A
  92. #
  93. # Returns:
  94. #   0 if the file exists, is a regular file, and is readable, otherwise -1.
  95. #
  96. sub file_check {
  97.   my($file);
  98.   $file = $_[0];
  99.   if (!(-e $file)) {
  100.      printf("The file "%s" does not exist.n", $file);
  101.      return (-1);
  102.   } elsif (!(-f $file)) {
  103.      printf("The file "%s" is not a regular file.n", $file);
  104.      return (-1);
  105.   } elsif (!(-r $file)) {
  106.      printf("The file "%s" is not readable.n", $file);
  107.      return (-1);
  108.   }
  109.   return (0);
  110. }
  111. #
  112. # decode_options()
  113. #
  114. # Description:
  115. #   This routine steps through the command-line arguments, parsing out
  116. #   recognzied options.
  117. #
  118. # Input(s):
  119. #   N/A
  120. #
  121. # Output(s):
  122. #   N/A
  123. #
  124. # Returns:
  125. #   N/A
  126. #
  127. sub decode_options {
  128.   if (!getopts("hvV")) {
  129.       usage(1);
  130.   }
  131.   if ($opt_h) {
  132.       usage(0);
  133.   }
  134.   if ($opt_V) {
  135.       version();
  136.       exit (0);
  137.   }
  138.   if ($opt_v) {
  139.       $verbose = 1;
  140.   }
  141.   if (!($ElfFile = shift(@ARGV))) {
  142.       usage(1);
  143.   }
  144.   if (!($OutputFile = shift(@ARGV))) {
  145.       usage (1);
  146.   }
  147.   if (!($IrFile = shift(@ARGV))) {
  148.       usage (1);
  149.   }
  150.   if (file_check($ElfFile)) {
  151.       exit(1);
  152.   }
  153.   if (file_check($IrFile)) {
  154.       exit(1);
  155.   }
  156. }
  157. #
  158. # ELF file and section header field numbers
  159. #
  160. require '../utils/elf.pl';
  161. #
  162. # Main program body
  163. #
  164. {
  165.   $program = basename($0);
  166.   decode_options();
  167.   open(ELF, "<$ElfFile") || die "Cannot open input file";
  168.   open(OUTPUT, ">$OutputFile") || die "Cannot open output file";
  169.   open(IR, "$IrFile") || die "Cannot open input file";
  170.   $ElfFilesize = (-s $ElfFile);
  171.   if (read(ELF, $ibuf, $ElfFilesize) != $ElfFilesize) {
  172.     print("Failed to read ELF input file!n");
  173.     exit(1);
  174.   }
  175.   if (read(IR, $irbuf, 8) != 8) {
  176.       print("Failed to read Ir input file!n");
  177.       exit(1);
  178.   }
  179.   #
  180.   # Parse ELF header
  181.   #
  182.   @eh = unpack("a16n2N5n6", $ibuf);
  183.   #
  184.   # Make sure this is actually a PowerPC ELF file.
  185.   #
  186.   if (substr($eh[$e_ident], 0, 4) ne "177ELF") {
  187.       printf("The file "%s" is not an ELF file.n", $ElfFile);
  188.       exit (1);
  189.   } elsif ($eh[$e_machine] != 20) {
  190.       printf("The file "%s" is not a PowerPC ELF file.n", $ElfFile);
  191.       exit (1);
  192.   }
  193.   #
  194.   # Find the section header for the string table.
  195.   #
  196.   $strtable_section_offset =  $eh[$e_shoff] +
  197.   $eh[$e_shstrndx] * $eh[$e_shentsize];
  198.   if ($verbose) {
  199.      printf("String table section header offset: 0x%xn",
  200.      $strtable_section_offset);
  201.   }
  202.   #
  203.   # Find the start of the string table.
  204.   #
  205.   @strh = unpack("N10", substr($ibuf, $strtable_section_offset,
  206.        $eh[$e_shentsize]));
  207.   if ($verbose) {
  208.      printf("Section name strings start at: 0x%x, %d bytes.n",
  209.      $strh[$sh_offset], $strh[$sh_size]);
  210.   }
  211.   $names = substr($ibuf, $strh[$sh_offset], $strh[$sh_size]);
  212.   # Grab each section header and find '.data', 'image', and 
  213.   # 'initrd' sections in particular.
  214.   $off = $eh[$e_shoff];
  215.   $imageFound = 0;
  216.   $initrdFound = 0;
  217.   
  218.   for($i = 0; $i < $eh[$e_shnum]; $i++, $off += $eh[$e_shentsize]) {
  219.     @sh = unpack("N10", substr($ibuf, $off, $eh[$e_shentsize]));
  220.     # Take the first section name from the array returned by split.
  221.     ($name) = split(/00/, substr($names, $sh[$sh_name]));
  222.     # Attempt to find the .data, image, and initrd sections
  223.     if ($name =~ /^image$/) {
  224.       ($image_addr, $image_offset, $image_size) =
  225. ($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
  226.       $imageFound = 1;
  227.     } elsif ($name =~ /^initrd$/) {
  228.       ($initrd_addr, $initrd_offset, $initrd_size) =
  229. ($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
  230.       $initrdFound = 1;
  231.     } elsif ($name =~ /^.data$/) {
  232.       ($data_addr, $data_offset, $data_size) =
  233. ($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
  234.     } elsif ($name =~ /^.bss$/) {
  235.       ($bss_addr, $bss_offset, $bss_size) =
  236. ($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
  237.     }
  238.    }
  239.   if ($verbose) {
  240.     printf("Data section   - Address: 0x%08x, Size: 0x%08x, File Offset 0x%08xn",
  241.    $data_addr, $data_size, $data_offset);
  242.     printf("Bss  section   - Address: 0x%08x, Size: 0x%08x, File Offset 0x%08xn",
  243.  $bss_addr, $bss_size, $bss_offset);
  244.    }
  245.   if ($verbose) {
  246.     if ($imageFound) {
  247.       printf("Image section  - Address: 0x%08x, Size: 0x%08xn",
  248.      $image_addr, $image_size);
  249.     } else {
  250.       printf("Image section not found in file: $ElfFilen");
  251.     }
  252.     if ($initrdFound) {
  253.       printf("Initrd section - Address: 0x%08x, Size: 0x%08xn",
  254.      $initrd_addr, $initrd_size);
  255.     } else {
  256.       printf("Initrd section not found in file: $ElfFilen");
  257.     }
  258.   }
  259.   # get file offset of irSectStart
  260.   $irSectStartoffset = hex ($irbuf);
  261.   if ($verbose) {
  262.     printf("irSectStartOffset Address: 0x%08xn", $irSectStartoffset);
  263.   }
  264.   # get the offset of global variables 
  265.   $initialOffset = ($irSectStartoffset - $data_addr) + $data_offset + 4;
  266.   # write modified values to OUTPUT file
  267.   syswrite(OUTPUT, $ibuf, $initialOffset);
  268.   if ($imageFound) {
  269.     $testN = pack ("N2", $bss_addr + $bss_size, $image_size);
  270.     syswrite(OUTPUT, $testN, length($testN));
  271.     printf("Updated symbol "imageSect_start" to 0x%08xn",
  272.    $bss_addr + $bss_size);
  273.     printf("Updated symbol "imageSect_size" to 0x%08xn", $image_size);
  274.   } else {
  275.     syswrite(OUTPUT, $ibuf, 8, $initialOffset);
  276.   }
  277.   if ($initrdFound) {
  278.     $testN = pack ("N2", $bss_addr + $bss_size + $image_size, $initrd_size);
  279.     syswrite(OUTPUT, $testN, length($testN));
  280.     printf("Updated symbol "initrdSect_start" to 0x%08xn",
  281.    $bss_addr + $bss_size + $image_size);
  282.     printf("Updated symbol "initrdSect_size" to 0x%08xn", $initrd_size);
  283.   } else {
  284.     syswrite(OUTPUT, $ibuf,8, $initialOffset + 8);
  285.   }
  286.   syswrite(OUTPUT, $ibuf, $ElfFilesize - ($initialOffset + 16),
  287.    $initialOffset + 16);
  288.   #
  289.   # Clean-up and leave
  290.   #
  291.   close (ELF);
  292.   close (OUTPUT);
  293.   close (IR);
  294.   exit (0);
  295. }