?? mkevimg
字號(hào):
#!/usr/bin/perl## Copyright (c) 1998-1999 TiVo, Inc.# All rights reserved.## Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu># Major syntactic and usability rework.## Module name: mkevimg## Description:# Converts an ELF output file from the linker into the format used by# the IBM evaluation board ROM Monitor to load programs from a host# onto the evaluation board. The ELF file must be an otherwise execut-# able file (with the text and data addresses bound at link time) and# have space reserved after the entry point for the load information# block:## typedef struct boot_block {# unsigned long magic; 0x0052504F# unsigned long dest; Target address of the image# unsigned long num_512blocks; Size, rounded-up, in 512 byte blocks# unsigned long debug_flag; Run the debugger or image after load# unsigned long entry_point; The image address to jump to after load# unsigned long checksum; 32 bit checksum including header# unsigned long reserved[2];# } boot_block_t;## 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 [-hlvV] <ELF input file> <Evaluation board output file>\n", $program); if ($status != 0) { printf("Try `%s -h' for more information.\n", $program); } if ($status != 1) { print(" -c Put checksum in load information block.\n"); print(" -h Print out this message and exit.\n"); print(" -l Linux mode; if present, copy 'image' and 'initrd' sections.\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("mkevimg 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("chlvV")) { usage(1); } if ($opt_c) { $do_checksum = 1; } if ($opt_h) { usage(0); } if ($opt_l) { $linux = 1; } if ($opt_V) { version(); exit (0); } if ($opt_v) { $verbose = 1; } if (!($ifile = shift(@ARGV))) { usage(1); } if (!($ofile = shift(@ARGV))) { usage (1); } if (file_check($ifile)) { exit(1); }}## ELF file and section header field numbers#require '../utils/elf.pl';## Main program body#{ $program = basename($0); decode_options(); open(ELF, "<$ifile") || die "Cannot open input file"; $ifilesize = (-s $ifile); if ($verbose) { print("Output file: $ofile\n"); print("Input file: $ifile, $ifilesize bytes.\n"); } if (read(ELF, $ibuf, $ifilesize) != $ifilesize) { print("Failed to read 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", $ifile); exit (1); } elsif ($eh[$e_machine] != 20) { printf("The file \"%s\" is not a PowerPC ELF file.\n", $ifile); exit (1); } if ($verbose) { print("File header:\n"); printf(" Identifier: %s\n", $eh[$e_ident]); printf(" Type: %d\n", $eh[$e_type]); printf(" Machine: %d\n", $eh[$e_machine]); printf(" Version: %d\n", $eh[$e_version]); printf(" Entry point: 0x%08x\n", $eh[$e_entry]); printf(" Program header offset: 0x%x\n", $eh[$e_phoff]); printf(" Section header offset: 0x%x\n", $eh[$e_shoff]); printf(" Flags: 0x%08x\n", $eh[$e_flags]); printf(" Header size: %d\n", $eh[$e_ehsize]); printf(" Program entry size: %d\n", $eh[$e_phentsize]); printf(" Program table entries: %d\n", $eh[$e_phnum]); printf(" Section header size: %d\n", $eh[$e_shentsize]); printf(" Section table entries: %d\n", $eh[$e_shnum]); printf(" String table section: %d\n", $eh[$e_shstrndx]); } # # 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 '.text' and '.bss' sections in # particular. if ($verbose) { print("Section headers:\n"); print("Idx Name Size Address File off Algn\n"); print("--- ------------------------ -------- -------- -------- ----\n"); } $off = $eh[$e_shoff]; 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])); if ($verbose) { printf("%3d %-24s %8x %08x %08x %4d\n", $i, $name, $sh[$sh_size], $sh[$sh_addr], $sh[$sh_offset], $sh[$sh_addralign]); } # Attempt to find the .text and .bss sections if ($name =~ /^\.bss$/) { ($bss_addr, $bss_offset, $bss_size) = ($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]); } elsif ($name =~ /^\.text$/) { ($text_addr, $text_offset, $text_size) = ($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]); } elsif ($linux && ($name =~ /^\image$/)) { $image_found = 1; ($image_addr, $image_offset, $image_size) = ($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]); } elsif ($linux && ($name =~ /^\initrd$/)) { $initrd_found = 1; ($initrd_addr, $initrd_offset, $initrd_size) = ($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]); } } printf("Text section - Address: 0x%08x, Size: 0x%08x\n", $text_addr, $text_size); printf("Bss section - Address: 0x%08x, Size: 0x%08x\n", $bss_addr, $bss_size); if ($linux) { if ($image_found) { printf("Image section - Address: 0x%08x, Size: 0x%08x\n", $image_addr, $image_size); } if ($initrd_found) { printf("Initrd section - Address: 0x%08x, Size: 0x%08x\n", $initrd_addr, $initrd_size); } } # # Open output file # open(BOOT, ">$ofile") || die "Cannot open output file"; # # Compute image size # $output_size = $bss_offset - $text_offset + $bss_size; if ($linux && $image_found) { $output_size += $image_size; } if ($linux && $initrd_found) { $output_size += $initrd_size; } # # Compute size with header # $header = pack("H8N7", "0052504f", 0, 0, 0, 0, 0, 0, 0); $num_blocks = ($output_size + length($header) + 511) / 512; # # Write IBM PowerPC evaluation board boot_block_t header # $header = pack("H8N7", "0052504f", $text_addr, $num_blocks, 0, $text_addr, 0, 0, 0); $bytes = length($header); if (($resid = syswrite(BOOT, $header, $bytes)) != $bytes) { die("Could not write boot image header to output file."); } printf("Entry point = 0x%08x\n", $text_addr); printf("Image size = 0x%08x (%d bytes) (%d blocks).\n", $output_size, $output_size, $num_blocks); # # Write image starting after ELF and program headers and # continuing to beginning of bss # $bytes = $bss_offset - $text_offset + $bss_size; if (($resid = syswrite(BOOT, $ibuf, $bytes, $text_offset)) != $bytes) { die("Could not write boot image to output file.\n"); } # # If configured, write out the image and initrd sections as well # if ($linux) { if ($image_found) { $bytes = $image_size; if (($resid = syswrite(BOOT, $ibuf, $bytes, $image_offset)) != $bytes) { die("Could not write boot image to output file.\n"); } } if ($initrd_found) { $bytes = $initrd_size; if (($resid = syswrite(BOOT, $ibuf, $bytes, $initrd_offset)) != $bytes) { die("Could not write boot image to output file.\n"); } } } # # Pad to a multiple of 512 bytes # If the (size of the boot image mod 512) is between 509 and 511 bytes # then the tftp to the Walnut fails. This may be fixed in more recent # Walnut bootrom. # $pad_size = 512 - ((length($header) + $output_size) % 512); if ($pad_size == 512) { $pad_size = 0; } if ($pad_size != 0) { if ($verbose) { print("Padding boot image by an additional $pad_size bytes.\n"); } $pad_string = pack("H8","deadbeef") x 128; syswrite(BOOT, $pad_string, $pad_size) or die "Could not pad boot image in output file.\n"; } # # Compute 32 bit checksum over entire file. # if ($do_checksum) { close(BOOT); open(BOOT, "+<$ofile") || die "Cannot open output file"; undef $/; $temp = unpack("%32N*", <BOOT>); # Solaris and PPC Linux return 0x80000000 for "-$temp" when $temp # is negative. "~($temp - 1)" negates $temp properly. $csum = ~($temp - 1); printf("Checksum = 0x%08x\r\n", $csum); # Rewrite IBM PowerPC evaluation board boot_block_t header, # this time with the checksum included # $header = pack("H8N7", "0052504f", $text_addr, $num_blocks, 0, $text_addr, $csum, 0, 0); seek(BOOT, 0, 0); syswrite(BOOT, $header, length($header)) or die("Could not write boot image header to output file."); } # # Clean-up and leave # close(BOOT); print("\nBoot image file \"$ofile\" built successfully.\n\n"); exit(0);}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -