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
- Lines: 659
- Date:
Wed Dec 31 16:00:00 1969
- Orig file:
v2.4.9/linux/arch/mips/boot/mkboot.c
- Orig date:
Tue Jul 3 17:08:18 2001
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)