From: Andy P. <at...@us...> - 2002-04-10 18:37:13
|
Update of /cvsroot/linux-vax/kernel-2.4/arch/ppc/boot/utils In directory usw-pr-cvs1:/tmp/cvs-serv25860/ppc/boot/utils Added Files: Makefile addnote.c elf.pl hack-coff.c mkevimg mkirimg mknote.c mkprep.c mksimage.c offset piggyback.c sioffset sisize size Log Message: synch 2.4.15 commit 43 --- NEW FILE --- # # arch/ppc/boot/utils/Makefile # # This file is subject to the terms and conditions of the GNU General Public # License. See the file "COPYING" in the main directory of this archive # for more details. HOSTCFLAGS += -I$(TOPDIR)/arch/$(ARCH)/boot/include all: dummy # Simple programs with 1 file and no extra CFLAGS UTILS = addnote hack-coff mkprep mksimage mknote piggyback mkpmon mkbugboot $(UTILS): $(HOSTCC) $(HOSTCFLAGS) -o $@ $@.c clean: rm -f $(UTILS) include $(TOPDIR)/Rules.make --- NEW FILE --- /* * BK Id: SCCS/s.addnote.c 1.7 05/18/01 15:17:23 cort */ /* * Program to hack in a PT_NOTE program header entry in an ELF file. * This is needed for OF on RS/6000s to load an image correctly. * Note that OF needs a program header entry for the note, not an * ELF section. * * Copyright 2000 Paul Mackerras. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * Usage: addnote zImage */ #include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <string.h> char arch[] = "PowerPC"; #define N_DESCR 6 unsigned int descr[N_DESCR] = { #if 1 /* values for IBM RS/6000 machines */ 0xffffffff, /* real-mode = true */ 0x00c00000, /* real-base, i.e. where we expect OF to be */ 0xffffffff, /* real-size */ 0xffffffff, /* virt-base */ 0xffffffff, /* virt-size */ 0x4000, /* load-base */ #else /* values for longtrail CHRP */ 0, /* real-mode = false */ 0xffffffff, /* real-base */ 0xffffffff, /* real-size */ 0xffffffff, /* virt-base */ 0xffffffff, /* virt-size */ 0x00600000, /* load-base */ #endif }; unsigned char buf[512]; #define GET_16BE(off) ((buf[off] << 8) + (buf[(off)+1])) #define GET_32BE(off) ((GET_16BE(off) << 16) + GET_16BE((off)+2)) #define PUT_16BE(off, v) (buf[off] = ((v) >> 8) & 0xff, \ buf[(off) + 1] = (v) & 0xff) #define PUT_32BE(off, v) (PUT_16BE((off), (v) >> 16), \ PUT_16BE((off) + 2, (v))) /* Structure of an ELF file */ #define E_IDENT 0 /* ELF header */ #define E_PHOFF 28 #define E_PHENTSIZE 42 #define E_PHNUM 44 #define E_HSIZE 52 /* size of ELF header */ #define EI_MAGIC 0 /* offsets in E_IDENT area */ #define EI_CLASS 4 #define EI_DATA 5 #define PH_TYPE 0 /* ELF program header */ #define PH_OFFSET 4 #define PH_FILESZ 16 #define PH_HSIZE 32 /* size of program header */ #define PT_NOTE 4 /* Program header type = note */ #define ELFCLASS32 1 #define ELFDATA2MSB 2 unsigned char elf_magic[4] = { 0x7f, 'E', 'L', 'F' }; int main(int ac, char **av) { int fd, n, i; int ph, ps, np; int nnote, ns; if (ac != 2) { fprintf(stderr, "Usage: %s elf-file\n", av[0]); exit(1); } fd = open(av[1], O_RDWR); if (fd < 0) { perror(av[1]); exit(1); } nnote = strlen(arch) + 1 + (N_DESCR + 3) * 4; n = read(fd, buf, sizeof(buf)); if (n < 0) { perror("read"); exit(1); } if (n < E_HSIZE || memcmp(&buf[E_IDENT+EI_MAGIC], elf_magic, 4) != 0) goto notelf; if (buf[E_IDENT+EI_CLASS] != ELFCLASS32 || buf[E_IDENT+EI_DATA] != ELFDATA2MSB) { fprintf(stderr, "%s is not a big-endian 32-bit ELF image\n", av[1]); exit(1); } ph = GET_32BE(E_PHOFF); ps = GET_16BE(E_PHENTSIZE); np = GET_16BE(E_PHNUM); if (ph < E_HSIZE || ps < PH_HSIZE || np < 1) goto notelf; if (ph + (np + 1) * ps + nnote > n) goto nospace; for (i = 0; i < np; ++i) { if (GET_32BE(ph + PH_TYPE) == PT_NOTE) { fprintf(stderr, "%s already has a note entry\n", av[1]); exit(0); } ph += ps; } /* XXX check that the area we want to use is all zeroes */ for (i = 0; i < ps + nnote; ++i) if (buf[ph + i] != 0) goto nospace; /* fill in the program header entry */ ns = ph + ps; PUT_32BE(ph + PH_TYPE, PT_NOTE); PUT_32BE(ph + PH_OFFSET, ns); PUT_32BE(ph + PH_FILESZ, nnote); /* fill in the note area we point to */ /* XXX we should probably make this a proper section */ PUT_32BE(ns, strlen(arch) + 1); PUT_32BE(ns + 4, N_DESCR * 4); PUT_32BE(ns + 8, 0x1275); strcpy(&buf[ns + 12], arch); ns += 12 + strlen(arch) + 1; for (i = 0; i < N_DESCR; ++i) PUT_32BE(ns + i * 4, descr[i]); /* Update the number of program headers */ PUT_16BE(E_PHNUM, np + 1); /* write back */ lseek(fd, (long) 0, SEEK_SET); i = write(fd, buf, n); if (i < 0) { perror("write"); exit(1); } if (i < n) { fprintf(stderr, "%s: write truncated\n", av[1]); exit(1); } exit(0); notelf: fprintf(stderr, "%s does not appear to be an ELF file\n", av[0]); exit(1); nospace: fprintf(stderr, "sorry, I can't find space in %s to put the note\n", av[0]); exit(1); } --- NEW FILE --- # # ELF header field numbers # $e_ident = 0; # Identification bytes / magic number $e_type = 1; # ELF file type $e_machine = 2; # Target machine type $e_version = 3; # File version $e_entry = 4; # Start address $e_phoff = 5; # Program header file offset $e_shoff = 6; # Section header file offset $e_flags = 7; # File flags $e_ehsize = 8; # Size of ELF header $e_phentsize = 9; # Size of program header $e_phnum = 10; # Number of program header entries $e_shentsize = 11; # Size of section header $e_shnum = 12; # Number of section header entries $e_shstrndx = 13; # Section header table string index # # Section header field numbers # $sh_name = 0; # Section name $sh_type = 1; # Section header type $sh_flags = 2; # Section header flags $sh_addr = 3; # Virtual address $sh_offset = 4; # File offset $sh_size = 5; # Section size $sh_link = 6; # Miscellaneous info $sh_info = 7; # More miscellaneous info $sh_addralign = 8; # Memory alignment $sh_entsize = 9; # Entry size if this is a table --- NEW FILE --- /* * BK Id: SCCS/s.hack-coff.c 1.8 05/18/01 06:20:29 patch */ /* * hack-coff.c - hack the header of an xcoff file to fill in * a few fields needed by the Open Firmware xcoff loader on * Power Macs but not initialized by objcopy. * * Copyright (C) Paul Mackerras 1997. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include "rs6000.h" #define AOUT_MAGIC 0x010b #define get_16be(x) ((((unsigned char *)(x))[0] << 8) \ + ((unsigned char *)(x))[1]) #define put_16be(x, v) (((unsigned char *)(x))[0] = (v) >> 8, \ ((unsigned char *)(x))[1] = (v) & 0xff) #define get_32be(x) ((((unsigned char *)(x))[0] << 24) \ + (((unsigned char *)(x))[1] << 16) \ + (((unsigned char *)(x))[2] << 8) \ + ((unsigned char *)(x))[3]) int main(int ac, char **av) { int fd; int i, nsect; int aoutsz; struct external_filehdr fhdr; AOUTHDR aout; struct external_scnhdr shdr; if (ac != 2) { fprintf(stderr, "Usage: hack-coff coff-file\n"); exit(1); } if ((fd = open(av[1], 2)) == -1) { perror(av[2]); exit(1); } if (read(fd, &fhdr, sizeof(fhdr)) != sizeof(fhdr)) goto readerr; i = get_16be(fhdr.f_magic); if (i != U802TOCMAGIC && i != U802WRMAGIC && i != U802ROMAGIC) { fprintf(stderr, "%s: not an xcoff file\n", av[1]); exit(1); } aoutsz = get_16be(fhdr.f_opthdr); if (read(fd, &aout, aoutsz) != aoutsz) goto readerr; nsect = get_16be(fhdr.f_nscns); for (i = 0; i < nsect; ++i) { if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr)) goto readerr; if (strcmp(shdr.s_name, ".text") == 0) { put_16be(aout.o_snentry, i+1); put_16be(aout.o_sntext, i+1); } else if (strcmp(shdr.s_name, ".data") == 0) { put_16be(aout.o_sndata, i+1); } else if (strcmp(shdr.s_name, ".bss") == 0) { put_16be(aout.o_snbss, i+1); } } put_16be(aout.magic, AOUT_MAGIC); if (lseek(fd, (long) sizeof(struct external_filehdr), 0) == -1 || write(fd, &aout, aoutsz) != aoutsz) { fprintf(stderr, "%s: write error\n", av[1]); exit(1); } close(fd); exit(0); readerr: fprintf(stderr, "%s: read error or file too short\n", av[1]); exit(1); } --- NEW FILE --- #!/usr/bin/perl # # Copyright (c) 1998-1999 TiVo, Inc. # All rights reserved. # # Copyright (c) 1999 Grant Erickson <gr...@lc...> # 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); } --- NEW FILE --- #!/usr/bin/perl # # Copyright (c) 1998-1999 TiVo, Inc. # Original ELF parsing code. # # Copyright (c) 1999 Grant Erickson <gr...@lc...> # 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 '../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%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 ("N2", $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 ("N2", $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); } --- NEW FILE --- /* * BK Id: SCCS/s.mknote.c 1.7 05/18/01 15:17:23 cort */ /* * Copyright (C) Cort Dougan 1999. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * Generate a note section as per the CHRP specification. * */ #include <stdio.h> #define PL(x) printf("%c%c%c%c", ((x)>>24)&0xff, ((x)>>16)&0xff, ((x)>>8)&0xff, (x)&0xff ); int main(void) { /* header */ /* namesz */ PL(strlen("PowerPC")+1); /* descrsz */ PL(6*4); /* type */ PL(0x1275); /* name */ printf("PowerPC"); printf("%c", 0); /* descriptor */ /* real-mode */ PL(0xffffffff); /* real-base */ PL(0x00c00000); /* real-size */ PL(0xffffffff); /* virt-base */ PL(0xffffffff); /* virt-size */ PL(0xffffffff); /* load-base */ PL(0x4000); return 0; } --- NEW FILE --- /* * BK Id: SCCS/s.mkprep.c 1.7 05/18/01 06:20:29 patch */ /* * Makes a prep bootable image which can be dd'd onto * a disk device to make a bootdisk. Will take * as input a elf executable, strip off the header * and write out a boot image as: * 1) default - strips elf header * suitable as a network boot image * 2) -pbp - strips elf header and writes out prep boot partition image * cat or dd onto disk for booting * 3) -asm - strips elf header and writes out as asm data * useful for generating data for a compressed image * -- Cort * * Modified for x86 hosted builds by Matt Porter <po...@ne...> */ #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <unistd.h> #define cpu_to_le32(x) le32_to_cpu((x)) unsigned long le32_to_cpu(unsigned long x) { return (((x & 0x000000ffU) << 24) | ((x & 0x0000ff00U) << 8) | ((x & 0x00ff0000U) >> 8) | ((x & 0xff000000U) >> 24)); } #define cpu_to_le16(x) le16_to_cpu((x)) unsigned short le16_to_cpu(unsigned short x) { return (((x & 0x00ff) << 8) | ((x & 0xff00) >> 8)); } #define cpu_to_be32(x) (x) #define be32_to_cpu(x) (x) #define cpu_to_be16(x) (x) #define be16_to_cpu(x) (x) /* size of read buffer */ #define SIZE 0x1000 typedef unsigned long dword_t; typedef unsigned short word_t; typedef unsigned char byte_t; typedef byte_t block_t[512]; typedef byte_t page_t[4096]; /* * Partition table entry * - from the PReP spec */ typedef struct partition_entry { byte_t boot_indicator; byte_t starting_head; byte_t starting_sector; byte_t starting_cylinder; byte_t system_indicator; byte_t ending_head; byte_t ending_sector; byte_t ending_cylinder; dword_t beginning_sector; dword_t number_of_sectors; } partition_entry_t; #define BootActive 0x80 #define SystemPrep 0x41 void copy_image(int , int); void write_prep_partition(int , int ); void write_asm_data( int in, int out ); unsigned int elfhdr_size = 65536; int main(int argc, char *argv[]) { int in_fd, out_fd; int argptr = 1; unsigned int prep = 0; unsigned int asmoutput = 0; if ( (argc < 3) || (argc > 4) ) { fprintf(stderr, "usage: %s [-pbp] [-asm] <boot-file> <image>\n",argv[0]); exit(-1); } /* needs to handle args more elegantly -- but this is a small/simple program */ /* check for -pbp */ if ( !strcmp( argv[argptr], "-pbp" ) ) { prep = 1; argptr++; } /* check for -asm */ if ( !strcmp( argv[argptr], "-asm" ) ) { asmoutput = 1; argptr++; } /* input file */ if ( !strcmp( argv[argptr], "-" ) ) in_fd = 0; /* stdin */ else if ((in_fd = open( argv[argptr] , 0)) < 0) exit(-1); argptr++; /* output file */ if ( !strcmp( argv[argptr], "-" ) ) out_fd = 1; /* stdout */ else if ((out_fd = creat( argv[argptr] , 0755)) < 0) exit(-1); argptr++; /* skip elf header in input file */ /*if ( !prep )*/ lseek(in_fd, elfhdr_size, SEEK_SET); /* write prep partition if necessary */ if ( prep ) write_prep_partition( in_fd, out_fd ); /* write input image to bootimage */ if ( asmoutput ) write_asm_data( in_fd, out_fd ); else copy_image(in_fd, out_fd); return 0; } void write_prep_partition(int in, int out) { unsigned char block[512]; partition_entry_t *pe = (partition_entry_t *)&block[0x1BE]; dword_t *entry = (dword_t *)&block[0]; dword_t *length = (dword_t *)&block[sizeof(long)]; struct stat info; if (fstat(in, &info) < 0) { fprintf(stderr,"info failed\n"); exit(-1); } bzero( block, sizeof block ); /* set entry point and boot image size skipping over elf header */ #ifdef __i386__ *entry = 0x400/*+65536*/; *length = info.st_size-elfhdr_size+0x400; #else *entry = cpu_to_le32(0x400/*+65536*/); *length = cpu_to_le32(info.st_size-elfhdr_size+0x400); #endif /* __i386__ */ /* sets magic number for msdos partition (used by linux) */ block[510] = 0x55; block[511] = 0xAA; /* * Build a "PReP" partition table entry in the boot record * - "PReP" may only look at the system_indicator */ pe->boot_indicator = BootActive; pe->system_indicator = SystemPrep; /* * The first block of the diskette is used by this "boot record" which * actually contains the partition table. (The first block of the * partition contains the boot image, but I digress...) We'll set up * one partition on the diskette and it shall contain the rest of the * diskette. */ pe->starting_head = 0; /* zero-based */ pe->starting_sector = 2; /* one-based */ pe->starting_cylinder = 0; /* zero-based */ pe->ending_head = 1; /* assumes two heads */ pe->ending_sector = 18; /* assumes 18 sectors/track */ pe->ending_cylinder = 79; /* assumes 80 cylinders/diskette */ /* * The "PReP" software ignores the above fields and just looks at * the next two. * - size of the diskette is (assumed to be) * (2 tracks/cylinder)(18 sectors/tracks)(80 cylinders/diskette) * - unlike the above sector numbers, the beginning sector is zero-based! */ #if 0 pe->beginning_sector = cpu_to_le32(1); #else /* This has to be 0 on the PowerStack? */ #ifdef __i386__ pe->beginning_sector = 0; #else pe->beginning_sector = cpu_to_le32(0); #endif /* __i386__ */ #endif #ifdef __i386__ pe->number_of_sectors = 2*18*80-1; #else pe->number_of_sectors = cpu_to_le32(2*18*80-1); #endif /* __i386__ */ write( out, block, sizeof(block) ); write( out, entry, sizeof(*entry) ); write( out, length, sizeof(*length) ); /* set file position to 2nd sector where image will be written */ lseek( out, 0x400, SEEK_SET ); } void copy_image(int in, int out) { char buf[SIZE]; int n; while ( (n = read(in, buf, SIZE)) > 0 ) write(out, buf, n); } void write_asm_data( int in, int out ) { int i, cnt, pos, len; unsigned int cksum, val; unsigned char *lp; unsigned char buf[SIZE]; unsigned char str[256]; write( out, "\t.data\n\t.globl input_data\ninput_data:\n", strlen( "\t.data\n\t.globl input_data\ninput_data:\n" ) ); pos = 0; cksum = 0; while ((len = read(in, buf, sizeof(buf))) > 0) { cnt = 0; lp = (unsigned char *)buf; len = (len + 3) & ~3; /* Round up to longwords */ for (i = 0; i < len; i += 4) { if (cnt == 0) { write( out, "\t.long\t", strlen( "\t.long\t" ) ); } sprintf( str, "0x%02X%02X%02X%02X", lp[0], lp[1], lp[2], lp[3]); write( out, str, strlen(str) ); val = *(unsigned long *)lp; cksum ^= val; lp += 4; if (++cnt == 4) { cnt = 0; sprintf( str, " # %x \n", pos+i-12); write( out, str, strlen(str) ); } else { write( out, ",", 1 ); } } if (cnt) { write( out, "0\n", 2 ); } pos += len; } sprintf(str, "\t.globl input_len\ninput_len:\t.long\t0x%x\n", pos); write( out, str, strlen(str) ); fprintf(stderr, "cksum = %x\n", cksum); } --- NEW FILE --- /* * BK Id: SCCS/s.mksimage.c 1.6 05/18/01 15:16:42 cort */ /* * * * * */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdarg.h> #include <sys/types.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #define SIZE 1024 #define BLOCK_ALIGN(x) (((x)+SIZE-1)&(~(SIZE-1))) static void die(const char *fmt, ...) { va_list args; va_start(args, fmt); vfprintf(stderr, fmt, args); fputc('\n', stderr); exit(1); } static void usage(void) { printf("Usage: mkbinimg <bootstrap> <kernel> <ramdisk> -o <binary>\n"); exit(1); } static int copy_blocks(int ifd, int ofd, unsigned long *offset, unsigned long *size) { off_t cur; int amt; unsigned long len = 0; char buffer[SIZE]; cur = lseek(ofd, 0, SEEK_CUR); if (cur % SIZE) { cur = BLOCK_ALIGN(cur); cur = lseek(ofd, cur, SEEK_SET); } *offset = (unsigned long) cur; while((amt = read(ifd, buffer, SIZE)) > 0) { write(ofd, buffer, amt); len += amt; } *size = len; return 0; } int main(int argc, char *argv[]) { char *kernel, *loader, *rdimage = NULL; unsigned long ld_off, kern_off, rd_off; unsigned long ld_size, kern_size, rd_size; int fd, ofd, len; char buffer[500]; if (argc < 5 && !strcmp(argv[argc-2], "-o")) usage(); if (argc > 5) rdimage = argv[3]; kernel = argv[2]; loader = argv[1]; ofd = open(argv[argc-1], (O_RDWR|O_CREAT), 0755); if (ofd < 0) { die("can't open %s: %s", argv[5], strerror(errno)); } ld_off = kern_off = rd_off = 0; ld_size = kern_size = rd_size = 0; memset(buffer, 0, 500); len = 0; fd = open(loader, O_RDONLY); if (fd < 0) die("can't open loader: %s", strerror(errno)); copy_blocks(fd, ofd, &ld_off, &ld_size); len = sprintf(buffer, "bootloader: %x %x\n", ld_off, ld_size); close(fd); fd = open(kernel, O_RDONLY); if (fd < 0) die("can't open kernel: %s", strerror(errno)); copy_blocks(fd, ofd, &kern_off, &kern_size); len += sprintf(buffer+len, "zimage: %x %x\n", kern_off, kern_size); close(fd); if (rdimage) { fd = open(rdimage, O_RDONLY); if (fd < 0) die("can't get ramdisk: %s", strerror(errno)); copy_blocks(fd, ofd, &rd_off, &rd_size); close(fd); } len += sprintf(buffer+len, "initrd: %x %x", rd_off, rd_size); close(ofd); printf("%s\n", buffer); return 0; } --- NEW FILE --- #!/bin/bash OFFSET=`$1 -h $2 | grep $3 | grep -v zvmlinux| awk '{print $6}'` echo "0x"$OFFSET --- NEW FILE --- /* * BK Id: SCCS/s.piggyback.c 1.7 05/18/01 15:17:23 cort */ #include <stdio.h> #include <unistd.h> extern long ce_exec_config[]; int main(int argc, char *argv[]) { int i, cnt, pos, len; unsigned int cksum, val; unsigned char *lp; unsigned char buf[8192]; if (argc != 2) { fprintf(stderr, "usage: %s name <in-file >out-file\n", argv[0]); exit(1); } fprintf(stdout, "#\n"); fprintf(stdout, "# Miscellaneous data structures:\n"); fprintf(stdout, "# WARNING - this file is automatically generated!\n"); fprintf(stdout, "#\n"); fprintf(stdout, "\n"); fprintf(stdout, "\t.data\n"); fprintf(stdout, "\t.globl %s_data\n", argv[1]); fprintf(stdout, "%s_data:\n", argv[1]); pos = 0; cksum = 0; while ((len = read(0, buf, sizeof(buf))) > 0) { cnt = 0; lp = (unsigned char *)buf; len = (len + 3) & ~3; /* Round up to longwords */ for (i = 0; i < len; i += 4) { if (cnt == 0) { fprintf(stdout, "\t.long\t"); } fprintf(stdout, "0x%02X%02X%02X%02X", lp[0], lp[1], lp[2], lp[3]); val = *(unsigned long *)lp; cksum ^= val; lp += 4; if (++cnt == 4) { cnt = 0; fprintf(stdout, " # %x \n", pos+i-12); fflush(stdout); } else { fprintf(stdout, ","); } } if (cnt) { fprintf(stdout, "0\n"); } pos += len; } fprintf(stdout, "\t.globl %s_len\n", argv[1]); fprintf(stdout, "%s_len:\t.long\t0x%x\n", argv[1], pos); fflush(stdout); fclose(stdout); fprintf(stderr, "cksum = %x\n", cksum); exit(0); } --- NEW FILE --- #!/bin/bash OFFSET=`grep $1 sImage.map | awk '{print $2}'` echo "0x"$OFFSET --- NEW FILE --- #!/bin/bash OFFSET=`grep $1 sImage.map | awk '{print $3}'` echo "0x"$OFFSET --- NEW FILE --- #!/bin/bash OFFSET=`$1 -h $2 | grep $3 | grep -v zvmlinux | awk '{print $3}'` echo "0x"$OFFSET |