3 # Copyright (c) 1998-1999 TiVo, Inc.
4 # Original ELF parsing code.
6 # Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
7 # Original code from 'mkevimg'.
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
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
33 # This routine prints out the proper command line usage for this program
36 # status - Flag determining what usage information will be printed and what
37 # the exit status of the program will be after the information is
44 # This subroutine does not return.
51 printf("Usage: %s [-hvV] <ELF input file> <Evaluation board output file> <irSectStart.txt file>\n",
55 printf("Try `%s -h' for more information.\n", $program);
59 print(" -h Print out this message and exit.\n");
60 print(" -v Verbose. Print out lots of ELF information.\n");
61 print(" -V Print out version information and exit.\n");
71 # This routine prints out program version information
80 # This subroutine does not return.
84 print("mkirimg Version 1.1.0\n");
85 print("Copyright (c) 1998-1999 TiVo, Inc.\n");
86 print("Copyright (c) 1999 Grant Erickson <grant\@lcse.umn.edu>\n");
95 # This routine checks an input file to ensure that it exists, is a
96 # regular file, and is readable.
99 # file - Input file to be checked.
105 # 0 if the file exists, is a regular file, and is readable, otherwise -1.
113 printf("The file \"%s\" does not exist.\n", $file);
115 } elsif (!(-f $file)) {
116 printf("The file \"%s\" is not a regular file.\n", $file);
118 } elsif (!(-r $file)) {
119 printf("The file \"%s\" is not readable.\n", $file);
130 # This routine steps through the command-line arguments, parsing out
131 # recognzied options.
145 if (!getopts("hvV")) {
162 if (!($ElfFile = shift(@ARGV))) {
166 if (!($OutputFile = shift(@ARGV))) {
170 if (!($IrFile = shift(@ARGV))) {
174 if (file_check($ElfFile)) {
178 if (file_check($IrFile)) {
184 # ELF file and section header field numbers
194 $program = basename($0);
197 open(ELF, "<$ElfFile") || die "Cannot open input file";
198 open(OUTPUT, ">$OutputFile") || die "Cannot open output file";
199 open(IR, "$IrFile") || die "Cannot open input file";
201 $ElfFilesize = (-s $ElfFile);
203 if (read(ELF, $ibuf, $ElfFilesize) != $ElfFilesize) {
204 print("Failed to read ELF input file!\n");
208 if (read(IR, $irbuf, 8) != 8) {
209 print("Failed to read Ir input file!\n");
217 @eh = unpack("a16n2N5n6", $ibuf);
220 # Make sure this is actually a PowerPC ELF file.
223 if (substr($eh[$e_ident], 0, 4) ne "\177ELF") {
224 printf("The file \"%s\" is not an ELF file.\n", $ElfFile);
226 } elsif ($eh[$e_machine] != 20) {
227 printf("The file \"%s\" is not a PowerPC ELF file.\n", $ElfFile);
232 # Find the section header for the string table.
235 $strtable_section_offset = $eh[$e_shoff] +
237 $eh[$e_shstrndx] * $eh[$e_shentsize];
240 printf("String table section header offset: 0x%x\n",
241 $strtable_section_offset);
245 # Find the start of the string table.
248 @strh = unpack("N10", substr($ibuf, $strtable_section_offset,
252 printf("Section name strings start at: 0x%x, %d bytes.\n",
253 $strh[$sh_offset], $strh[$sh_size]);
256 $names = substr($ibuf, $strh[$sh_offset], $strh[$sh_size]);
258 # Grab each section header and find '.data', 'image', and
259 # 'initrd' sections in particular.
261 $off = $eh[$e_shoff];
265 for($i = 0; $i < $eh[$e_shnum]; $i++, $off += $eh[$e_shentsize]) {
266 @sh = unpack("N10", substr($ibuf, $off, $eh[$e_shentsize]));
268 # Take the first section name from the array returned by split.
270 ($name) = split(/\000/, substr($names, $sh[$sh_name]));
272 # Attempt to find the .data, image, and initrd sections
274 if ($name =~ /^\image$/) {
275 ($image_addr, $image_offset, $image_size) =
276 ($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
279 } elsif ($name =~ /^\initrd$/) {
280 ($initrd_addr, $initrd_offset, $initrd_size) =
281 ($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
284 } elsif ($name =~ /^\.data$/) {
285 ($data_addr, $data_offset, $data_size) =
286 ($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
288 } elsif ($name =~ /^\.bss$/) {
289 ($bss_addr, $bss_offset, $bss_size) =
290 ($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
296 printf("Data section - Address: 0x%08x, Size: 0x%08x, File Offset 0x%08x\n",
297 $data_addr, $data_size, $data_offset);
298 printf("Bss section - Address: 0x%08x, Size: 0x%08x, File Offset 0x%08x\n",
299 $bss_addr, $bss_size, $bss_offset);
304 printf("Image section - Address: 0x%08x, Size: 0x%08x\n",
305 $image_addr, $image_size);
307 printf("Image section not found in file: $ElfFile\n");
311 printf("Initrd section - Address: 0x%08x, Size: 0x%08x\n",
312 $initrd_addr, $initrd_size);
314 printf("Initrd section not found in file: $ElfFile\n");
318 # get file offset of irSectStart
320 $irSectStartoffset = hex ($irbuf);
323 printf("irSectStartOffset Address: 0x%08x\n", $irSectStartoffset);
326 # get the offset of global variables
328 $initialOffset = ($irSectStartoffset - $data_addr) + $data_offset + 4;
330 # write modified values to OUTPUT file
332 syswrite(OUTPUT, $ibuf, $initialOffset);
335 $testN = pack ("N2", $bss_addr + $bss_size, $image_size);
336 syswrite(OUTPUT, $testN, length($testN));
337 printf("Updated symbol \"imageSect_start\" to 0x%08x\n",
338 $bss_addr + $bss_size);
339 printf("Updated symbol \"imageSect_size\" to 0x%08x\n", $image_size);
341 syswrite(OUTPUT, $ibuf, 8, $initialOffset);
345 $testN = pack ("N2", $bss_addr + $bss_size + $image_size, $initrd_size);
346 syswrite(OUTPUT, $testN, length($testN));
347 printf("Updated symbol \"initrdSect_start\" to 0x%08x\n",
348 $bss_addr + $bss_size + $image_size);
349 printf("Updated symbol \"initrdSect_size\" to 0x%08x\n", $initrd_size);
351 syswrite(OUTPUT, $ibuf,8, $initialOffset + 8);
354 syswrite(OUTPUT, $ibuf, $ElfFilesize - ($initialOffset + 16),
355 $initialOffset + 16);