patch-2.4.10 linux/arch/mips/boot/mkboot.c

Next file: linux/arch/mips/config.in
Previous file: linux/arch/mips/boot/Makefile
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.9/linux/arch/mips/boot/mkboot.c linux/arch/mips/boot/mkboot.c
@@ -1,658 +0,0 @@
-/*
- * Make a bootable image from a Linux/MIPS kernel.
- *
- * 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.
- *
- * Copyright (C) 1996, 2001 by Ralf Baechle
- *
- * This file is written in plain Kernighan & Ritchie C as it has to run
- * on all crosscompile hosts no matter how braindead.  This code might
- * also become part of Milo.  It's therefore important that we don't use
- * seek because the Seek() call of the Magnum 4000 ARC BIOS is broken.
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-/*
- * Define this for verbose debugging output.
- */
-#undef VERBOSE
-
-/*
- * Don't use the host's elf.h - it might be using incompatible defines
- */
-
-#define EI_NIDENT 16
-
-/*
- * Basic ELF types.
- */
-typedef unsigned short Elf32_Half;
-typedef unsigned short Elf32_Section;
-typedef unsigned int Elf32_Word;
-typedef unsigned int Elf32_Addr;
-typedef unsigned int Elf32_Off;
-
-typedef struct
-{
-  unsigned char e_ident[EI_NIDENT];     /* Magic number and other info */
-  Elf32_Half    e_type;                 /* Object file type */
-  Elf32_Half    e_machine;              /* Architecture */
-  Elf32_Word    e_version;              /* Object file version */
-  Elf32_Addr    e_entry;                /* Entry point virtual address */
-  Elf32_Off     e_phoff;                /* Program header table file offset */
-  Elf32_Off     e_shoff;                /* Section header table file offset */
-  Elf32_Word    e_flags;                /* Processor-specific flags */
-  Elf32_Half    e_ehsize;               /* ELF header size in bytes */
-  Elf32_Half    e_phentsize;            /* Program header table entry size */
-  Elf32_Half    e_phnum;                /* Program header table entry count */
-  Elf32_Half    e_shentsize;            /* Section header table entry size */
-  Elf32_Half    e_shnum;                /* Section header table entry count */
-  Elf32_Half    e_shstrndx;             /* Section header string table index */
-} Elf32_Ehdr;
-
-/*
- * ELF magic number
- */
-#define ELFMAG          "\177ELF"
-#define SELFMAG         4
-
-#define EI_CLASS        4               /* File class byte index */
-#define ELFCLASSNONE    0               /* Invalid class */
-#define ELFCLASS32      1               /* 32-bit objects */
-#define ELFCLASS64      2               /* 64-bit objects */
-
-#define EI_DATA         5               /* Data encoding byte index */
-#define ELFDATA2LSB     1               /* 2's complement, little endian */
-#define ELFDATA2MSB     2               /* 2's complement, big endian */
-
-#define EI_VERSION      6               /* File version byte index */
-#define EV_CURRENT      1               /* Current version */
-
-/*
- * Acceptable machine type in e_machine.
- */
-#define EM_MIPS         8               /* MIPS R3000 big-endian */
-
-/*
- * The type of ELF file we accept.
- */
-#define ET_EXEC         2               /* Executable file */
-
-/*
- * Definition of a single program header structure
- */
-typedef struct
-{
-  Elf32_Word    p_type;                 /* Segment type */
-  Elf32_Off     p_offset;               /* Segment file offset */
-  Elf32_Addr    p_vaddr;                /* Segment virtual address */
-  Elf32_Addr    p_paddr;                /* Segment physical address */
-  Elf32_Word    p_filesz;               /* Segment size in file */
-  Elf32_Word    p_memsz;                /* Segment size in memory */
-  Elf32_Word    p_flags;                /* Segment flags */
-  Elf32_Word    p_align;                /* Segment alignment */
-} Elf32_Phdr;
-
-/*
- * Legal values for p_type
- */
-#define PT_NULL         0               /* Program header table entry unused */
-#define PT_LOAD         1               /* Loadable program segment */
-#define PT_DYNAMIC      2               /* Dynamic linking information */
-#define PT_INTERP       3               /* Program interpreter */
-#define PT_NOTE         4               /* Auxiliary information */
-#define PT_SHLIB        5               /* Reserved */
-#define PT_PHDR         6               /* Entry for header table itself */
-#define PT_NUM          7               /* Number of defined types.  */
-#define PT_LOPROC       0x70000000      /* Start of processor-specific */
-#define PT_HIPROC       0x7fffffff      /* End of processor-specific */
-
-typedef struct
-{
-  Elf32_Word    sh_name;                /* Section name (string tbl index) */
-  Elf32_Word    sh_type;                /* Section type */
-  Elf32_Word    sh_flags;               /* Section flags */
-  Elf32_Addr    sh_addr;                /* Section virtual addr at execution */
-  Elf32_Off     sh_offset;              /* Section file offset */
-  Elf32_Word    sh_size;                /* Section size in bytes */
-  Elf32_Word    sh_link;                /* Link to another section */
-  Elf32_Word    sh_info;                /* Additional section information */
-  Elf32_Word    sh_addralign;           /* Section alignment */
-  Elf32_Word    sh_entsize;             /* Entry size if section holds table */
-} Elf32_Shdr;
-
-typedef struct
-{
-  Elf32_Word    st_name;                /* Symbol name (string tbl index) */
-  Elf32_Addr    st_value;               /* Symbol value */
-  Elf32_Word    st_size;                /* Symbol size */
-  unsigned char st_info;                /* Symbol type and binding */
-  unsigned char st_other;               /* No defined meaning, 0 */
-  Elf32_Section st_shndx;               /* Section index */
-} Elf32_Sym;
-
-/* How to extract and insert information held in the st_info field.  */
-#define ELF32_ST_BIND(val)              (((unsigned char) (val)) >> 4)
-#define ELF32_ST_TYPE(val)              ((val) & 0xf)
-
-/* Legal values for ST_BIND subfield of st_info (symbol binding).  */
-#define STB_GLOBAL      1               /* Global symbol */
-
-/* Legal values for ST_TYPE subfield of st_info (symbol type).  */
-#define STT_NOTYPE      0               /* Symbol type is unspecified */
-#define STT_OBJECT      1               /* Symbol is a data object */
-#define STT_FUNC        2               /* Symbol is a code object */
-
-static unsigned int
-get_Elf32_Half(unsigned char *p)
-{
-	return p[0] | (p[1] << 8);
-}
-#define get_Elf32_Section(p) get_Elf32_Half(p)
-
-static unsigned int
-get_Elf32_Word(unsigned char *p)
-{
-	return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
-}
-#define get_Elf32_Addr(p) get_Elf32_Word(p)
-#define get_Elf32_Off(p) get_Elf32_Word(p)
-
-static void
-put_byte(p, x)
-	unsigned char *p;
-	unsigned char x;
-{
-	p[0] = x;
-}
-
-static void
-put_half(p, x)
-	unsigned char *p;
-	unsigned short x;
-{
-	p[0] = x & 0xff;
-	p[1] = (x >> 8) & 0xff;
-}
-
-static void
-put_word(p, x)
-	unsigned char *p;
-	unsigned long x;
-{
-	p[0] = x & 0xff;
-	p[1] = (x >> 8) & 0xff;
-	p[2] = (x >> 16) & 0xff;
-	p[3] = (x >> 24) & 0xff;
-}
-
-/*
- * Swap a program header in.
- */
-static void
-get_elfph(p, ph)
-	unsigned char *p;
-	Elf32_Phdr *ph;
-{
-	ph->p_type   = get_Elf32_Word(p);
-	ph->p_offset = get_Elf32_Off(p + 4);
-	ph->p_vaddr  = get_Elf32_Addr(p + 8);
-	ph->p_paddr  = get_Elf32_Addr(p + 12);
-	ph->p_filesz = get_Elf32_Word(p + 16);
-	ph->p_memsz  = get_Elf32_Word(p + 20);
-	ph->p_flags  = get_Elf32_Word(p + 24);
-	ph->p_align  = get_Elf32_Word(p + 28);
-}
-
-/*
- * Swap a section header in.
- */
-static void
-get_elfsh(p, sh)
-	unsigned char *p;
-	Elf32_Shdr *sh;
-{
-	sh->sh_name      = get_Elf32_Word(p);
-	sh->sh_type      = get_Elf32_Word(p + 4);
-	sh->sh_flags     = get_Elf32_Word(p + 8);
-	sh->sh_addr      = get_Elf32_Addr(p + 12);
-	sh->sh_offset    = get_Elf32_Off(p + 16);
-	sh->sh_size      = get_Elf32_Word(p + 20);
-	sh->sh_link      = get_Elf32_Word(p + 24);
-	sh->sh_info      = get_Elf32_Word(p + 28);
-	sh->sh_addralign = get_Elf32_Word(p + 32);
-	sh->sh_entsize   = get_Elf32_Word(p + 36);
-}
-
-/*
- * Swap a section header in.
- */
-static void
-get_elfsym(p, sym)
-	unsigned char *p;
-	Elf32_Sym *sym;
-{
-	sym->st_name      = get_Elf32_Word(p);
-	sym->st_value     = get_Elf32_Addr(p + 4);
-	sym->st_size      = get_Elf32_Word(p + 8);
-	sym->st_info      = *(p + 12);
-	sym->st_other     = *(p + 13);
-	sym->st_shndx     = get_Elf32_Section(p + 14);
-}
-
-/*
- * The a.out magic number
- */
-#define OMAGIC 0407	/* Code indicating object file or impure executable. */
-#define M_MIPS1 151	/* MIPS R3000/R3000 binary */
-#define M_MIPS2 152	/* MIPS R6000/R4000 binary */
-
-/*
- * Compute and return an a.out magic number.
- */
-#define AOUT_INFO(magic, type, flags) \
-        (((magic) & 0xffff) | \
-         (((int)(type) & 0xff) << 16) | \
-         (((flags) & 0xff) << 24))
-
-/*
- * a.out symbols
- */
-#define N_UNDF 0
-#define N_ABS 2
-#define N_TEXT 4
-#define N_DATA 6
-#define N_BSS 8
-#define N_FN 15
-#define N_EXT 1
-
-#define min(x,y) (((x)<(y))?(x):(y))
-
-static void
-do_read(fd, buf, size)
-	int fd;
-	char *buf;
-	ssize_t size;
-{
-	ssize_t rd;
-
-	while(size != 0) {
-		rd = read(fd, buf, size);
-		if (rd == -1) {
-			perror("Can't read from file.");
-			exit(1);
-		}
-		size -= rd;
-	}
-}
-
-static void
-writepad(fd, size)
-	int fd;
-	size_t size;
-{
-	static void *zeropage = NULL;
-	ssize_t written;
-
-	if (zeropage == NULL) {
-		zeropage = malloc(4096);
-		if (zeropage == NULL) {
-			fprintf(stderr, "Couldn't allocate zero buffer.\n");
-			exit(1);
-		}
-		memset(zeropage, '\0', 4096);
-	}
-	while(size != 0) {
-		written = write(fd, zeropage, min(4096, size));
-		if (written == -1) {
-			perror("Can't write to boot image");
-			exit(1);
-		}
-		size -= written;
-	}
-}
-
-static void
-do_write(fd, buf, size)
-	int fd;
-	char *buf;
-	ssize_t size;
-{
-	ssize_t written;
-
-	while(size != 0) {
-		written = write(fd, buf, size);
-		if (written == -1) {
-			perror("Can't write to boot image");
-			exit(1);
-		}
-		size -= written;
-	}
-}
-
-static int
-usage(program_name)
-	char *program_name;
-{
-	fprintf(stderr, "Usage: %s infile outfile\n", program_name);
-	exit(0);
-}
-
-int
-main(argc, argv)
-	int argc;
-	char *argv[];
-{
-	char *infile, *outfile;
-	struct stat ifstat;
-	off_t ifsize;
-	char *image;
-	int ifd, ofd, i, symtabix, strtabix;
-	Elf32_Ehdr eh;
-	Elf32_Phdr *ph;
-	Elf32_Shdr *sh;
-	unsigned long vaddr, entry, bss, kernel_entry, kernel_end;
-	unsigned char ahdr[32];
-	Elf32_Sym sym;
-	int	symnum;
-	char *symname;
-
-	/*
-	 * Verify some basic assuptions about type sizes made in this code
-	 */
-	if (sizeof(Elf32_Half) != 2) {
-		fprintf(stderr, "Fix mkboot: sizeof(Elf32_Half) != 2\n");
-		exit(1);
-	}
-	if (sizeof(Elf32_Word) != 4) {
-		fprintf(stderr, "Fix mkboot: sizeof(Elf32_Word) != 4\n");
-		exit(1);
-	}
-	if (sizeof(Elf32_Addr) != 4) {
-		fprintf(stderr, "Fix mkboot: sizeof(Elf32_Addr) != 4\n");
-		exit(1);
-	}
-
-	if (argc != 3)
-		usage(argv[0]);
-
-	infile = argv[1];
-	outfile = argv[2];
-
-	if (stat(infile, &ifstat) < 0) {
-		perror("Can't stat kernel image.");
-		exit(1);
-	}
-
-	if (!S_ISREG(ifstat.st_mode)) {
-		fprintf(stderr, "Input file isn't a regular file.\n");
-		exit(1);
-	}
-	ifsize = ifstat.st_size;
-
-	image = malloc((size_t)ifsize);
-	if (image == NULL) {
-		fprintf(stderr, "Can't allocate memory to read file\n");
-		exit(1);
-	}
-
-	/*
-	 * Read the entire input file in.
-	 */
-	ifd = open(infile, O_RDONLY);
-	if(ifd == 0) {
-		fprintf(stderr, "Can't open input file\n");
-		exit(1);
-	}
-	do_read(ifd, image, ifsize);
-	close(ifd);
-
-	/*
-	 * Now swap the ELF header in.  This is ugly but we the file
-	 * we're reading might have different type sizes, byteorder
-	 * or alignment than the host.
-	 */
-	memcpy(eh.e_ident, (void *)image, sizeof(eh.e_ident));
-	if(memcmp(eh.e_ident, ELFMAG, SELFMAG)) {
-		fprintf(stderr, "Input file isn't a ELF file\n");
-		exit(1);
-	}
-	if(eh.e_ident[EI_CLASS] != ELFCLASS32) {
-		fprintf(stderr, "Input file isn't a 32 bit ELF file\n");
-		exit(1);
-	}
-	if(eh.e_ident[EI_DATA] != ELFDATA2LSB) {
-		fprintf(stderr, "Input file isn't a little endian ELF file\n");
-		exit(1);
-	}
-	if(eh.e_ident[EI_VERSION] != EV_CURRENT) {
-		fprintf(stderr, "Input file isn't a version %d ELF file\n",
-		        EV_CURRENT);
-		exit(1);
-	}
-
-	/*
-	 * Ok, so far the file looks ok.  Now swap the rest of the header in
-	 * and do some more paranoia checks.
-	 */
-	eh.e_type      = get_Elf32_Half(image + 16);
-	eh.e_machine   = get_Elf32_Half(image + 18);
-	eh.e_version   = get_Elf32_Word(image + 20);
-	eh.e_entry     = get_Elf32_Addr(image + 24);
-	eh.e_phoff     = get_Elf32_Off(image + 28);
-	eh.e_shoff     = get_Elf32_Off(image + 32);
-	eh.e_flags     = get_Elf32_Word(image + 36);
-	eh.e_ehsize    = get_Elf32_Half(image + 40);
-	eh.e_phentsize = get_Elf32_Half(image + 42);
-	eh.e_phnum     = get_Elf32_Half(image + 44);
-	eh.e_shentsize = get_Elf32_Half(image + 46);
-	eh.e_shnum     = get_Elf32_Half(image + 48);
-	eh.e_shstrndx  = get_Elf32_Half(image + 50);
-
-	if(eh.e_type != ET_EXEC) {
-		fprintf(stderr, "Input file isn't a executable.\n");
-		exit(1);
-	}
-	if(eh.e_machine != EM_MIPS) {
-		fprintf(stderr, "Input file isn't a MIPS executable.\n");
-		exit(1);
-	}
-
-	/*
-	 * Now read the program headers ...
-	 */
-	ph = malloc(sizeof(Elf32_Phdr) * eh.e_phnum);
-	if (ph == NULL) {
-		fprintf(stderr, "No memory for program header table.\n");
-		exit(1);
-	}
-	for(i = 0;i < eh.e_phnum; i++)
-		get_elfph((void *)(image + eh.e_phoff + i * 32), ph + i);
-
-	/*
-	 * ... and then the section headers.
-	 */
-	sh = malloc(sizeof(Elf32_Shdr) * eh.e_shnum);
-	if (sh == NULL) {
-		fprintf(stderr, "No memory for section header table.\n");
-		exit(1);
-	}
-	for(i = 0;i < eh.e_shnum; i++)
-		get_elfsh((void *)(image + eh.e_shoff + (i * 40)), sh + i);
-
-	/*
-	 * Find the symboltable and the stringtable in the file.
-	 */
-	for(i = 0;i < eh.e_shnum; i++) {
-		if (!strcmp (image + sh [eh.e_shstrndx].sh_offset + sh[i].sh_name,
-		             ".symtab")) {
-			symtabix = i;
-			continue;
-		}
-		if (!strcmp (image + sh [eh.e_shstrndx].sh_offset + sh[i].sh_name,
-		             ".strtab")) {
-			strtabix = i;
-			continue;
-		}
-	}
-
-	if (symtabix == -1) {
-		fprintf(stderr, "The executable doesn't have a symbol table\n");
-		exit(1);
-	}
-	if (strtabix == -1) {
-		fprintf(stderr, "The executable doesn't have a string table\n");
-		exit(1);
-	}
-
-	/*
-	 * Dig for the two required symbols in the symbol table.
-	 */
-	symnum = sh[symtabix].sh_size / 16;
-	for(i = 0;i < symnum;i++) {
-		get_elfsym(image + sh[symtabix].sh_offset + (i * 16), &sym);
-		symname = image + sh[strtabix].sh_offset + sym.st_name;
-		if (ELF32_ST_BIND(sym.st_info) != STB_GLOBAL)
-			continue;
-		if (ELF32_ST_TYPE(sym.st_info) != STT_NOTYPE &&
-		    ELF32_ST_TYPE(sym.st_info) != STT_OBJECT &&
-		    ELF32_ST_TYPE(sym.st_info) != STT_FUNC)
-			continue;
-		if (strcmp("kernel_entry", symname) == 0) {
-			kernel_entry = sym.st_value;
-			continue;
-		}
-		if (strcmp("_end", symname) == 0) {
-			kernel_end = sym.st_value;
-			continue;
-		}
-	}
-
-#ifdef VERBOSE
-	/*
-	 * And print what we will be loaded into memory.
-	 */
-	for(i = 0;i < eh.e_phnum; i++) {
-		if (ph[i].p_type != PT_LOAD) {
-			continue;
-		}
-		printf("  Offset: %08lx\n", ph[i].p_offset);
-		printf("  file size: %08lx\n", ph[i].p_filesz);
-		printf("  mem size: %08lx\n", ph[i].p_memsz);
-		printf("    Loading: %08lx - %08lx\n",
-		       ph[i].p_vaddr, ph[i].p_vaddr + ph[i].p_filesz);
-		printf("    Zero mapping: %08lx - %08lx\n",
-		       ph[i].p_vaddr + ph[i].p_filesz,
-		       ph[i].p_vaddr + ph[i].p_memsz);
-	}
-#endif
-
-	/*
-	 * Time to open the outputfile.
-	 */
-	ofd = open(outfile, O_WRONLY|O_CREAT|O_TRUNC, 0666);
-	if (ofd == -1) {
-		perror("Can't open boot image for output.");
-		exit(1);
-	}
-
-	/*
-	 * First compute the layout of the file.  We need to do this
-	 * first because we can't seek back to the beginning due to the
-	 * broken Seek() call in the Magnum firmware.
-	 */
-	entry = vaddr = 0xffffffff;
-	bss = 0;
-	for(i = 0;i < eh.e_phnum; i++) {
-		if (ph[i].p_type != PT_LOAD)
-			continue;
-		if (vaddr == 0xffffffff)
-			entry = vaddr = ph[i].p_vaddr;
-		vaddr = ph[i].p_vaddr + ph[i].p_filesz;
-		bss = ph[i].p_memsz - ph[i].p_filesz;
-	}
-
-	/*
-	 * In the next step we construct the boot image.  The boot file
-	 * looks essentially like a dump of the loaded kernel with a
-	 * minimal header.  Because Milo supports already a.out image
-	 * we simply dump the image in an a.out image ...  First let's
-	 * write the header.
-	 */
-
-	/*
-	 * Create and write the a.out header.
-	 */
-	put_word(ahdr, AOUT_INFO(OMAGIC, M_MIPS1, 0));
-	put_word(ahdr + 4, vaddr - entry);	/* text size */
-	put_word(ahdr + 8, 0);			/* data size */
-	put_word(ahdr + 12, bss);		/* bss size */
-	put_word(ahdr + 16, 2 * 12);		/* size of symbol table */
-	put_word(ahdr + 20, entry);		/* base address */
-	put_word(ahdr + 24, 0);			/* size of text relocations */
-	put_word(ahdr + 28, 0);			/* size of data relocations */
-	do_write(ofd, ahdr, 32);
-
-	/*
-	 * Write text and data segment combined into the a.out text segment
-	 * and a zero length data segment into the file.
-	 */
-	vaddr = 0xffffffff;
-	bss = 0;
-	for(i = 0;i < eh.e_phnum; i++) {
-		if (ph[i].p_type != PT_LOAD)
-			continue;
-		if (vaddr == 0xffffffff)
-			vaddr = ph[i].p_vaddr;
-		writepad(ofd, ph[i].p_vaddr - vaddr);	/* Write zero pad */
-		do_write(ofd, image + ph[i].p_offset, ph[i].p_filesz);
-		vaddr = ph[i].p_vaddr + ph[i].p_filesz;
-		bss = ph[i].p_memsz - ph[i].p_filesz;
-	}
-
-	/*
-	 * Now write the symbol table.  It has only two symbols,
-	 * kernel_entry and _end which we need for booting.
-	 */
-	put_word(ahdr    , 4);			/* n_un.n_strx */
-	put_byte(ahdr + 4, N_TEXT | N_EXT);	/* n_type */
-	put_byte(ahdr + 5, 0);			/* n_other */
-	put_half(ahdr + 6, 0);			/* n_desc */
-	put_word(ahdr + 8, kernel_entry);	/* n_value */
-	do_write(ofd, ahdr, 12);
-
-	put_word(ahdr    , 4 + 13);		/* n_un.n_strx */
-	put_byte(ahdr + 4, N_ABS | N_EXT);	/* n_type */
-	put_byte(ahdr + 5, 0);			/* n_other */
-	put_half(ahdr + 6, 0);			/* n_desc */
-	put_word(ahdr + 8, kernel_end);		/* n_value */
-	do_write(ofd, ahdr, 12);
-
-	/*
-	 * Now write stringtable size and the strings.
-	 */
-	put_word(ahdr, 4 + 20);
-	do_write(ofd, ahdr, 4);
-	do_write(ofd, "kernel_entry\0_end\0\0", 20);
-
-	/*
-	 * That's is all ...
-	 */
-	close(ofd);
-
-#ifdef VERBOSE
-	printf("Entry: %08lx\n", entry);
-	printf("Dumped image %08lx - %08lx\n", 0x80000000, vaddr);
-	printf("Extra bss at end: %08lx\n", bss);
-#endif
-
-	return 0;
-}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)