|
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
|