patch-pre2.0.8 linux/arch/ppc/kernel/mkboot.c

Next file: linux/arch/ppc/kernel/mmu.h
Previous file: linux/arch/ppc/kernel/mk_defs.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file pre2.0.7/linux/arch/ppc/kernel/mkboot.c linux/arch/ppc/kernel/mkboot.c
@@ -1,67 +1,269 @@
+/*
+ * mkboot - Make a 'boot' image from a PowerPC (ELF) binary
+ *
+ * usage: mkboot <ELF-file> <Boot-file>
+ *
+ */
+
+#include <stdlib.h>
 #include <stdio.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <fcntl.h>
+#include <errno.h>
+#include <elf/common.h>
+#include <elf/external.h>
+
+#define MAX_SECTIONS 64
+int fd;
+Elf32_External_Ehdr hdr;
+Elf32_External_Shdr sections[MAX_SECTIONS];
+char *symtab;
+
+/* Boolean type definitions */
+
+#define FALSE     0
+#define TRUE      1
+#define bool  short
 
-/* amount to skip */
-#define PLACE 65536
+extern char *strerror();
+extern int errno;
 
-/* size of read buffer */
-#define SIZE 0x200000
+#define ADDR unsigned long
 
+/* Definitions that control the shape of the output */
+#define MAX_ITEMS  32  /* Max # bytes per line */
 
-void main(int argc, char **argv )
+FILE *in_file;  /* Input (binary image) file */
+FILE *out_file; /* Output (boot image) file */
+
+int org = -1;
+
+#ifdef linux
+long
+_LONG(unsigned long *p)
 {
-  int fd, fdo;
-  unsigned char data[SIZE];
-  int i, n, skip;
+  unsigned char *xp = (unsigned char *)p;
+  return ((xp[0]<<24) | (xp[1]<<16) | (xp[2]<<8) | xp[3]);
+}
 
-  if ( argc != 3 )
+unsigned short
+_USHORT(unsigned short *p)
+{
+  unsigned char *xp = (unsigned char *)p;
+  return ((xp[0]<<8) | xp[1]);
+}
+#else
+#define _LONG *
+#define _USHORT *
+#endif
+
+Elf32_External_Shdr *
+find_section(char *section_name)
+{
+  Elf32_External_Shdr *shdr = sections;
+  int i;
+  for (i = 0;  i < MAX_SECTIONS;  i++, shdr++)
   {
-    fprintf(stderr,"%s infile outfile\n", argv[0]);
-    exit(-1);
+    if (strcmp(section_name, &symtab[_LONG((int *)shdr->sh_name)]) == 0)
+    {
+      return (shdr);
+    }
   }
+  return ((Elf32_External_Shdr *)0);
+}
 
+main (argc, argv)
+  int argc;
+  char *argv[];
+{
+  if ((argc == 3) || (argc == 4))
+  {
+    if (argc == 4)
+    {
+      org = strtol(argv[3], NULL, 0);
+    }
+    if (init(argc, argv))
+    {
+      process(argv[2]);
+    }
+    else exit(255);
+  } else
+  { /* Illegal command line */
+    fprintf(stderr, "Syntax: mkboot <bin_file> <out_file>\n");
+    exit(255);
+  }
+  exit(0);
+}
 
-  fd = open(argv[1], O_RDONLY);
-  if ( fd == -1 )
+init(argc, argv)
+  int argc;
+  char *argv[];
+{
+  int sizeof_sections, size;
+  char *fn = argv[1];
+  Elf32_External_Shdr *shdr;
+  if ((out_file = fopen(argv[2], "w")) == (FILE *)NULL)
+  {
+    io_err("creating output file");
+    return (FALSE);
+  }
+  if ((in_file = fopen(fn, "r")) == (FILE *)NULL)
+  {
+    fprintf(stderr, "Can't open '%s': %s\n", fn, strerror(errno));
+    return (FALSE);
+  }
+  if (fread(&hdr, sizeof(hdr), 1, in_file) != 1)
   {
-    fprintf(stderr,"Couldn't open %s\n", argv[1]);
-    perror("open()");
-    exit(-1);
+    fprintf(stderr, "Can't read ELF header: %s\n", strerror(errno));
+    return (FALSE);
   }
-  
-  fdo = open(argv[2], O_WRONLY|O_CREAT);
-  if ( fdo == -1 )
+  /* Make sure this is a file we like */
+  if ((hdr.e_ident[EI_MAG0] != ELFMAG0) || (hdr.e_ident[EI_MAG1] != ELFMAG1) ||
+      (hdr.e_ident[EI_MAG2] != ELFMAG2) || (hdr.e_ident[EI_MAG3] != ELFMAG3))
   {
-    fprintf(stderr,"Couldn't open %s\n", argv[2]);
-    perror("open()");
-    exit(-1);
+    fprintf(stderr, "Invalid binary file (not ELF)\n");
+    return (FALSE);
   }
+  if (hdr.e_ident[EI_CLASS] != ELFCLASS32)
+  {
+    fprintf(stderr, "Invalid binary file (not ELF32)\n");
+    return (FALSE);
+  }
+  if ((_USHORT((unsigned short *)hdr.e_machine) != EM_CYGNUS_POWERPC) &&
+      (_USHORT((unsigned short *)hdr.e_machine) != EM_PPC))
+  {
+    fprintf(stderr, "Invalid binary file (not PowerPC)\n");
+    return (FALSE);
+  }
+  if (_USHORT((unsigned short *)hdr.e_shnum) > MAX_SECTIONS)
+  {
+    fprintf(stderr, "Invalid binary file (too many sections)\n");
+    return (FALSE);
+  }
+  fseek(in_file, _LONG((int *)hdr.e_shoff), 0);
+  sizeof_sections = _USHORT((unsigned short *)hdr.e_shnum) * sizeof(sections[0]);
+  if (fread(sections, sizeof_sections, 1, in_file) != 1)
+  {
+    fprintf(stderr, "Can't read sections: %s\n", strerror(errno));
+    return (FALSE);
+  }
+  /* Read in symbol table */
+  shdr = &sections[_USHORT((unsigned short *)hdr.e_shstrndx)];
+  size = _LONG((int *)shdr->sh_size);
+  if (!(symtab = malloc(256)))
+  {
+    fprintf(stderr, "Can't allocate memory for symbol table.\n");
+    return (FALSE);
+  }
+  fseek(in_file, _LONG((int *)shdr->sh_offset), 0);
+  if (fread(symtab, size, 1, in_file) != 1)
+  {
+    fprintf(stderr, "Can't read symbol table: %s\n", strerror(errno));
+    return (FALSE);
+  }
+  return (TRUE);
+}
 
-#if 0
-  skip = atoi(argv[3]);
-#else
-  skip = PLACE;
-#endif
-  i = lseek(fd, skip, SEEK_SET);
-  printf("lseek'd %d bytes\n", i);
-  if ( i == -1 )
+process(out_name)
+  char *out_name;
+{
+  Elf32_External_Shdr *shdr_text, *shdr_data;
+  long relocated_text_base, text_base, text_offset, text_size;
+  long relocated_data_base, data_base, data_offset, data_size;
+  shdr_text = find_section(".text");
+  shdr_data = find_section(".data");
+  text_base = relocated_text_base = _LONG((int *)shdr_text->sh_addr);
+  text_size = _LONG((int *)shdr_text->sh_size);
+  text_offset = _LONG((int *)shdr_text->sh_offset);
+  data_base = relocated_data_base = _LONG((int *)shdr_data->sh_addr);
+  data_size = _LONG((int *)shdr_data->sh_size);
+  data_offset = _LONG((int *)shdr_data->sh_offset);
+  if (org >= 0)
+  {
+  	relocated_text_base = org;
+  	relocated_data_base = data_base - text_base + org;
+  }
+fprintf(stderr, "TEXT %x bytes at %x[%x]\n", text_size, text_base, relocated_text_base);
+fprintf(stderr, "DATA %x bytes at %x[%x]\n", data_size, data_base, relocated_data_base);
+  if (dump_segment(text_offset, relocated_text_base, text_size) &&
+      dump_segment(data_offset, relocated_data_base, data_size))
+  {
+  } else
   {
-      perror("lseek()");
+    unlink(out_name);
   }
+}
 
-  while ( (n = read(fd, data, SIZE)) > 0 )
+dump_segment(off, base, size)
+  long off;
+  ADDR base;
+  long size;
+{
+  char buf[4096];
+  int len;
+  bool ok = TRUE;
+fprintf(stderr, "Reading %x bytes at %x.%x\n", size, off, base);
+  fseek(in_file, 0, 0);
+  fseek(in_file, off, 0);
+#if 0  
+  if (org >= 0)
+  {
+     fseek(out_file, base+org, 0);
+  } else
   {
-    printf("Read %d bytes\n", n);
-    i = write(fdo, data, n);
-    printf("Wrote %d bytes\n", i);    
+     fseek(out_file, base, 0);
   }
+#else
+  fseek(out_file, base, 0);
+#endif  
+  while (size && ok)
+  {
+    len = size;
+    if (len > sizeof(buf))
+    {
+      len = sizeof(buf);
+    }
+    if (fread(buf, sizeof(char), len, in_file) == len)
+    {
+      fwrite(buf, sizeof(char), len, out_file);
+    } else
+    {
+      fprintf(stderr,"Premature EOF encountered.\n");
+      ok = FALSE;
+    }
+    size -= len;
+  }
+  return (ok);
+}
+
+io_err(what)
+  char *what;
+{
+  fprintf(stderr, "Error %s: %s\n", what, strerror(errno));
+}
 
 
-  close(fdo);
-  close(fd);
-  return(0);
+
+#ifdef sun
+extern int sys_nerr;
+extern char *sys_errlist[];
+
+char *
+strerror(int errno)
+{
+	static char msg[32];
+	if (errno <= sys_nerr)
+	{
+		return (sys_errlist[errno]);
+	} else
+	{
+		sprintf(msg, "<<Unknown error: %d>>", errno);
+		return (msg);
+	}
 }
+
+strtoul(char *str, char **radix, int base)
+{
+	return(strtol(str, radix, base));
+}
+#endif
 
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this