diff options
Diffstat (limited to 'arch/alpha/boot')
-rw-r--r-- | arch/alpha/boot/Makefile | 91 | ||||
-rw-r--r-- | arch/alpha/boot/bootloader.lds | 50 | ||||
-rw-r--r-- | arch/alpha/boot/head.S | 8 | ||||
-rw-r--r-- | arch/alpha/boot/main.c | 53 | ||||
-rw-r--r-- | arch/alpha/boot/tools/build.c | 173 | ||||
-rw-r--r-- | arch/alpha/boot/tools/mkbb.c | 151 | ||||
-rw-r--r-- | arch/alpha/boot/tools/objstrip.c | 280 |
7 files changed, 599 insertions, 207 deletions
diff --git a/arch/alpha/boot/Makefile b/arch/alpha/boot/Makefile index b05047c2a..b3d888a92 100644 --- a/arch/alpha/boot/Makefile +++ b/arch/alpha/boot/Makefile @@ -8,46 +8,95 @@ # Copyright (C) 1994 by Linus Torvalds # -.c.s: - $(CC) $(CFLAGS) -S -o $*.s $< -.s.o: - $(AS) -o $*.o $< -.c.o: - $(CC) $(CFLAGS) -c -o $*.o $< +ifdef CONFIG_CROSSCOMPILE +# enable this for linking under OSF/1: +LINKFLAGS = -non_shared -T 0x20000000 -N +else + elf=$(shell if $(LD) --help | grep elf64alpha >/dev/null; then echo yes; fi) + ifeq ($(elf),yes) + LINKFLAGS = -static -Ttext 0x20000000 -N + else + LINKFLAGS = -static -T bootloader.lds -N + endif +endif + .S.s: $(CC) -D__ASSEMBLY__ -traditional -E -o $*.o $< .S.o: $(CC) -D__ASSEMBLY__ -traditional -c -o $*.o $< OBJECTS = head.o main.o +TARGETS = vmlinux.gz tools/objstrip # also needed by aboot & milo +VMLINUX = $(TOPDIR)/vmlinux +OBJSTRIP = tools/objstrip + +all: $(TARGETS) + @echo Ready to install kernel in $(shell pwd)/vmlinux.gz -all: tools/lxboot tools/bootlx vmlinux - @echo run mkfloppy on machine with floppy drive +# normally no need to build these: +rawboot: vmlinux.nh tools/lxboot tools/bootlx -msb: tools/lxboot tools/bootlx vmlinux - ( cat tools/lxboot tools/bootlx vmlinux ) > /dev/rz0a +msb: tools/lxboot tools/bootlx vmlinux.nh + ( cat tools/lxboot tools/bootlx vmlinux.nh ) > /dev/rz0a disklabel -rw rz0 'linux' tools/lxboot tools/bootlx -vmlinux: tools/build $(TOPDIR)/vmlinux - tools/build -v $(TOPDIR)/vmlinux > vmlinux +bootimage: tools/mkbb tools/lxboot tools/bootlx vmlinux.nh + ( cat tools/lxboot tools/bootlx vmlinux.nh ) > bootimage + tools/mkbb bootimage tools/lxboot + +srmboot: bootdevice bootimage + dd if=bootimage of=$(BOOTDEV) bs=512 seek=1 skip=1 + tools/mkbb $(BOOTDEV) tools/lxboot + +bootdevice: + @test "$(BOOTDEV)" != "" || (echo You must specify BOOTDEV ; exit -1) + +vmlinux.gz: vmlinux + gzip -fv vmlinux + +# +# A raw binary without header. Used by raw boot. +# +main.o: ksize.h + +ksize.h: $(OBJSTRIP) vmlinux.nh + echo "#define KERNEL_SIZE `$(OBJSTRIP) -p vmlinux.nh /dev/null`" > $@ + +vmlinux.nh: $(VMLINUX) $(OBJSTRIP) +ifeq ($(elf),yes) + cp $(VMLINUX) vmlinux.stripped + strip vmlinux.stripped # work around ELF binutils bug... + $(OBJSTRIP) -v vmlinux.stripped vmlinux.nh + rm -f vmlinux.stripped +else + $(OBJSTRIP) -v $(VMLINUX) vmlinux.nh +endif + +vmlinux: $(TOPDIR)/vmlinux + cp $(TOPDIR)/vmlinux vmlinux + strip vmlinux + +tools/lxboot: $(OBJSTRIP) bootloader + $(OBJSTRIP) -p bootloader tools/lxboot -tools/lxboot: tools/build - tools/build > tools/lxboot +tools/bootlx: bootloader $(OBJSTRIP) + $(OBJSTRIP) -vb bootloader tools/bootlx -tools/bootlx: bootloader tools/build - tools/build -vb bootloader > tools/bootlx +$(OBJSTRIP): $(OBJSTRIP).c + $(HOSTCC) $(OBJSTRIP).c -o $(OBJSTRIP) -tools/build: tools/build.c - $(HOSTCC) tools/build.c -o tools/build +tools/mkbb: tools/mkbb.c + $(HOSTCC) tools/mkbb.c -o tools/mkbb bootloader: $(OBJECTS) - $(LD) -non_shared -T 0x20000000 -N \ + $(LD) $(LINKFLAGS) \ $(OBJECTS) \ $(LIBS) \ - -o bootloader || \ + -o bootloader && strip bootloader || \ (rm -f bootloader && exit 1) clean: - rm -f vmlinux bootloader tools/build tools/bootlx tools/lxboot + rm -f $(TARGETS) bootloader bootimage vmlinux.nh \ + tools/mkbb tools/bootlx tools/lxboot dep: diff --git a/arch/alpha/boot/bootloader.lds b/arch/alpha/boot/bootloader.lds new file mode 100644 index 000000000..77806e69f --- /dev/null +++ b/arch/alpha/boot/bootloader.lds @@ -0,0 +1,50 @@ +OUTPUT_FORMAT("ecoff-littlealpha") +ENTRY(__start) +SECTIONS +{ + .text 0x20000000: { + _ftext = . ; + __istart = . ; + eprol = .; + *(.text) + __fstart = . ; + _etext = .; + } + .rdata : { + *(.rdata) + } + .pdata : { + _fpdata = .; + *(.pdata) + } + .data : { + _fdata = .; + *(.data) + CONSTRUCTORS + } + .xdata : { + *(.xdata) + } + _gp = ALIGN (16) + 0x8000; + .lit8 : { + *(.lit8) + } + .lita : { + *(.lita) + } + .sdata : { + *(.sdata) + } + _EDATA = .; + _FBSS = .; + .sbss : { + *(.sbss) + *(.scommon) + . = ALIGN(16); + } + .bss : { + *(.bss) + *(COMMON) + } + _end = .; +} diff --git a/arch/alpha/boot/head.S b/arch/alpha/boot/head.S index efca165e6..9fae5301a 100644 --- a/arch/alpha/boot/head.S +++ b/arch/alpha/boot/head.S @@ -129,3 +129,11 @@ dispatch: ret $31,($26) .end dispatch + .align 3 + .globl tbi + .ent tbi +tbi: + .long PAL_tbi + ret ($26) + .end tbi + diff --git a/arch/alpha/boot/main.c b/arch/alpha/boot/main.c index d122eb6f6..c2d4e657e 100644 --- a/arch/alpha/boot/main.c +++ b/arch/alpha/boot/main.c @@ -13,9 +13,12 @@ #include <asm/system.h> #include <asm/console.h> #include <asm/hwrpb.h> +#include <asm/pgtable.h> #include <stdarg.h> +#include "ksize.h" + extern int vsprintf(char *, const char *, va_list); extern unsigned long switch_to_osf_pal(unsigned long nr, struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa, @@ -24,13 +27,36 @@ extern unsigned long switch_to_osf_pal(unsigned long nr, int printk(const char * fmt, ...) { va_list args; - int i; + int i, j, written, remaining, num_nl; static char buf[1024]; + char * str; va_start(args, fmt); i = vsprintf(buf, fmt, args); va_end(args); - puts(buf,i); + + /* expand \n into \r\n: */ + + num_nl = 0; + for (j = 0; j < i; ++j) { + if (buf[j] == '\n') + ++num_nl; + } + remaining = i + num_nl; + for (j = i - 1; j >= 0; --j) { + buf[j + num_nl] = buf[j]; + if (buf[j] == '\n') { + --num_nl; + buf[j + num_nl] = '\r'; + } + } + + str = buf; + do { + written = puts(str, remaining); + remaining -= written; + str += written; + } while (remaining > 0); return i; } @@ -125,11 +151,9 @@ void pal_init(void) printk("Ok (rev %lx)\n", rev); /* remove the old virtual page-table mapping */ L1[1] = 0; - invalidate_all(); + flush_tlb_all(); } -extern int _end; - static inline long openboot(void) { char bootdev[256]; @@ -149,7 +173,8 @@ static inline long close(long dev) static inline long load(long dev, unsigned long addr, unsigned long count) { char bootfile[256]; - long result; + extern char _end; + long result, boot_size = &_end - (char *) BOOT_ADDR; result = dispatch(CCB_GET_ENV, ENV_BOOTED_FILE, bootfile, 255); if (result < 0) @@ -157,8 +182,9 @@ static inline long load(long dev, unsigned long addr, unsigned long count) result &= 255; bootfile[result] = '\0'; if (result) - printk("Boot file specification (%s) not implemented\n", bootfile); - return dispatch(CCB_READ, dev, count, addr, BOOT_SIZE/512 + 1); + printk("Boot file specification (%s) not implemented\n", + bootfile); + return dispatch(CCB_READ, dev, count, addr, boot_size/512 + 1); } /* @@ -195,19 +221,20 @@ void start_kernel(void) } dev &= 0xffffffff; printk("Loading vmlinux ..."); - i = load(dev, START_ADDR, START_SIZE); + i = load(dev, START_ADDR, KERNEL_SIZE); close(dev); - if (i != START_SIZE) { + if (i != KERNEL_SIZE) { printk("Failed (%lx)\n", i); return; } nbytes = dispatch(CCB_GET_ENV, ENV_BOOTED_OSFLAGS, envval, sizeof(envval)); - if (nbytes > 0) { - envval[nbytes] = '\0'; - strcpy((char*)ZERO_PGE, envval); + if (nbytes < 0) { + nbytes = 0; } + envval[nbytes] = '\0'; + strcpy((char*)ZERO_PAGE, envval); printk(" Ok\nNow booting the kernel\n"); runkernel(); diff --git a/arch/alpha/boot/tools/build.c b/arch/alpha/boot/tools/build.c deleted file mode 100644 index 040655a54..000000000 --- a/arch/alpha/boot/tools/build.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * arch/alpha/boot/tools/build.c - * - * Build a bootable image from the vmlinux binary - */ -#include <string.h> -#include <stdio.h> -#include <unistd.h> -#include <fcntl.h> - -#include <a.out.h> - -#include <asm/system.h> - -#define MAXSECT 10 -#define MAXBUF 8192 - -int verbose = 0; -int pad = 0; -char * program = "tools/build"; -char buffer[MAXBUF]; -unsigned long bootblock[64]; -struct filehdr fhdr; -struct aouthdr ahdr; -struct scnhdr shdr[MAXSECT]; - -char * usage = "'build [-b] system > secondary' or 'build > primary'"; - -static void die(char * str) -{ - fprintf(stderr,"%s: %s\n", program, str); - exit(1); -} - -static int comp(struct scnhdr * a, struct scnhdr * b) -{ - return a->s_vaddr - b->s_vaddr; -} - -int main(int argc, char ** argv) -{ - int fd, i; - unsigned long tmp, start; - unsigned long system_start, system_size; - char * infile = NULL; - - system_start = START_ADDR; - system_size = START_SIZE; - if (argc) { - program = *(argv++); - argc--; - } - while (argc > 0) { - if (**argv == '-') { - while (*++*argv) { - switch (**argv) { - case 'b': - system_start = BOOT_ADDR; - system_size = BOOT_SIZE; - pad = 1; - break; - case 'v': - verbose++; - break; - default: - die(usage); - } - } - } else if (infile) - die(usage); - else - infile = *argv; - argv++; - argc--; - } - if (!infile) { - memcpy(bootblock, "Linux Test", 10); - bootblock[60] = BOOT_SIZE / 512; /* count */ - bootblock[61] = 1; /* starting LBM */ - bootblock[62] = 0; /* flags */ - tmp = 0; - for (i = 0 ; i < 63 ; i++) - tmp += bootblock[i]; - bootblock[63] = tmp; - if (write(1, (char *) bootblock, 512) != 512) { - perror("bbwrite"); - exit(1); - } - return 0; - } - fd = open(infile, O_RDONLY); - if (fd < 0) { - perror(infile); - exit(1); - } - if (read(fd, &fhdr, sizeof(struct filehdr)) != sizeof(struct filehdr)) - die("unable to read file header"); - if (fhdr.f_nscns > MAXSECT) - die("Too many sections"); - if (fhdr.f_opthdr != AOUTHSZ) - die("optional header doesn't look like a.out"); - if (read(fd, &ahdr, sizeof(struct aouthdr)) != sizeof(struct aouthdr)) - die("unable to read a.out header"); - for (i = 0 ; i < fhdr.f_nscns ; i++) { - if (read(fd, i+shdr, sizeof(struct scnhdr)) != sizeof(struct scnhdr)) - die("unable to read section header"); - if (shdr[i].s_paddr != shdr[i].s_vaddr) - die("unable to handle different phys/virt addresses"); - if (shdr[i].s_relptr) - die("Unable to handle relocation info"); - if (verbose) { - fprintf(stderr, "section %d (%.8s):\t%lx - %lx (at %x)\n", - i, shdr[i].s_name, - shdr[i].s_vaddr, - shdr[i].s_vaddr + shdr[i].s_size, - shdr[i].s_scnptr); - } - } - qsort(shdr, fhdr.f_nscns, sizeof(shdr[1]), comp); - start = system_start; - for (i = 0 ; i < fhdr.f_nscns ; i++) { - unsigned long size, offset; - memset(buffer, 0, MAXBUF); - if (!strcmp(shdr[i].s_name, ".comment")) - continue; - if (shdr[i].s_vaddr != start) - die("Unordered or badly placed segments"); - size = shdr[i].s_size; - start += size; - offset = shdr[i].s_scnptr; - if (lseek(fd, offset, SEEK_SET) != offset) - die("Unable to seek in in-file"); - while (size > 0) { - unsigned long num = size; - if (num > MAXBUF) - num = MAXBUF; - if (offset) - if (read(fd, buffer, num) != num) - die("partial read"); - if (write(1, buffer, num) != num) - die("partial write"); - size -= num; - } - if (verbose) { - fprintf(stderr, "section %d (%.8s):\t%lx - %lx (at %x)\n", - i, shdr[i].s_name, - shdr[i].s_vaddr, - shdr[i].s_vaddr + shdr[i].s_size, - shdr[i].s_scnptr); - } - } - if (start > system_start + system_size) { - fprintf(stderr, "Boot image too large\n"); - exit(1); - } - if (pad) { - unsigned long count = (system_start + system_size) - start; - memset(buffer, 0, MAXBUF); - while (count > 0) { - int i = MAXBUF; - if (i > count) - i = count; - i = write(1, buffer, i); - if (i <= 0) { - perror("pad write"); - exit(1); - } - count -= i; - } - } - - return 0; -} diff --git a/arch/alpha/boot/tools/mkbb.c b/arch/alpha/boot/tools/mkbb.c new file mode 100644 index 000000000..23c7190b0 --- /dev/null +++ b/arch/alpha/boot/tools/mkbb.c @@ -0,0 +1,151 @@ +/* This utility makes a bootblock suitable for the SRM console/miniloader */ + +/* Usage: + * mkbb <device> <lxboot> + * + * Where <device> is the name of the device to install the bootblock on, + * and <lxboot> is the name of a bootblock to merge in. This bootblock + * contains the offset and size of the bootloader. It must be exactly + * 512 bytes long. + */ + +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> + +/* Minimal definition of disklabel, so we don't have to include + * asm/disklabel.h (confuses make) + */ +#ifndef MAXPARTITIONS +#define MAXPARTITIONS 8 /* max. # of partitions */ +#endif + +#ifndef u8 +#define u8 unsigned char +#endif + +#ifndef u16 +#define u16 unsigned short +#endif + +#ifndef u32 +#define u32 unsigned int +#endif + +struct disklabel { + u32 d_magic; /* must be DISKLABELMAGIC */ + u16 d_type, d_subtype; + u8 d_typename[16]; + u8 d_packname[16]; + u32 d_secsize; + u32 d_nsectors; + u32 d_ntracks; + u32 d_ncylinders; + u32 d_secpercyl; + u32 d_secprtunit; + u16 d_sparespertrack; + u16 d_sparespercyl; + u32 d_acylinders; + u16 d_rpm, d_interleave, d_trackskew, d_cylskew; + u32 d_headswitch, d_trkseek, d_flags; + u32 d_drivedata[5]; + u32 d_spare[5]; + u32 d_magic2; /* must be DISKLABELMAGIC */ + u16 d_checksum; + u16 d_npartitions; + u32 d_bbsize, d_sbsize; + struct d_partition { + u32 p_size; + u32 p_offset; + u32 p_fsize; + u8 p_fstype; + u8 p_frag; + u16 p_cpg; + } d_partitions[MAXPARTITIONS]; +}; + + +typedef union __bootblock { + struct { + char __pad1[64]; + struct disklabel __label; + } __u1; + struct { + unsigned long __pad2[63]; + unsigned long __checksum; + } __u2; + char bootblock_bytes[512]; + unsigned long bootblock_quadwords[64]; +} bootblock; + +#define bootblock_label __u1.__label +#define bootblock_checksum __u2.__checksum + +main(int argc, char ** argv) +{ + bootblock bootblock_from_disk; + bootblock bootloader_image; + int dev, fd; + int i; + int nread; + + /* Make sure of the arg count */ + if(argc != 3) { + fprintf(stderr, "Usage: %s device lxboot\n", argv[0]); + exit(0); + } + + /* First, open the device and make sure it's accessible */ + dev = open(argv[1], O_RDWR); + if(dev < 0) { + perror(argv[1]); + exit(0); + } + + /* Now open the lxboot and make sure it's reasonable */ + fd = open(argv[2], O_RDONLY); + if(fd < 0) { + perror(argv[2]); + close(dev); + exit(0); + } + + /* Read in the lxboot */ + nread = read(fd, &bootloader_image, sizeof(bootblock)); + if(nread != sizeof(bootblock)) { + perror("lxboot read"); + fprintf(stderr, "expected %d, got %d\n", sizeof(bootblock), nread); + exit(0); + } + + /* Read in the bootblock from disk. */ + nread = read(dev, &bootblock_from_disk, sizeof(bootblock)); + if(nread != sizeof(bootblock)) { + perror("bootblock read"); + fprintf(stderr, "expected %d, got %d\n", sizeof(bootblock), nread); + exit(0); + } + + /* Swap the bootblock's disklabel into the bootloader */ + bootloader_image.bootblock_label = bootblock_from_disk.bootblock_label; + + /* Calculate the bootblock checksum */ + bootloader_image.bootblock_checksum = 0; + for(i = 0; i < 63; i++) { + bootloader_image.bootblock_checksum += + bootloader_image.bootblock_quadwords[i]; + } + + /* Write the whole thing out! */ + lseek(dev, 0L, SEEK_SET); + if(write(dev, &bootloader_image, sizeof(bootblock)) != sizeof(bootblock)) { + perror("bootblock write"); + exit(0); + } + + close(fd); + close(dev); + exit(0); +} + + diff --git a/arch/alpha/boot/tools/objstrip.c b/arch/alpha/boot/tools/objstrip.c new file mode 100644 index 000000000..765e68f2e --- /dev/null +++ b/arch/alpha/boot/tools/objstrip.c @@ -0,0 +1,280 @@ +/* + * arch/alpha/boot/tools/objstrip.c + * + * Strip the object file headers/trailers from an executable (ELF or ECOFF). + * + * Copyright (C) 1996 David Mosberger-Tang. + */ +/* + * Converts an ECOFF or ELF object file into a bootable file. The + * object file must be a OMAGIC file (i.e., data and bss follow immediatly + * behind the text). See DEC "Assembly Language Programmer's Guide" + * documentation for details. The SRM boot process is documented in + * the Alpha AXP Architecture Reference Manual, Second Edition by + * Richard L. Sites and Richard T. Witek. + */ +#include <stdio.h> +#include <unistd.h> + +#include <sys/fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include <linux/a.out.h> +#include <linux/coff.h> +#include <linux/param.h> +#include <linux/string.h> +#ifdef __ELF__ +# include <asm/elf.h> +# include <linux/elf.h> +#endif + +/* bootfile size must be multiple of BLOCK_SIZE: */ +#define BLOCK_SIZE 512 + +const char * prog_name; + + +void +usage (void) +{ + fprintf(stderr, + "usage: %s [-v] -p file primary\n" + " %s [-vb] file [secondary]\n", prog_name, prog_name); + exit(1); +} + + +int +main (int argc, char *argv[]) +{ + size_t nwritten, tocopy, n, mem_size, fil_size, pad = 0; + int fd, ofd, i, j, verbose = 0, primary = 0; + char buf[8192], *inname; + struct exec * aout; /* includes file & aout header */ + long offset; +#ifdef __ELF__ + struct elfhdr *elf; + struct elf_phdr *elf_phdr; /* program header */ + unsigned long long e_entry; +#endif + + prog_name = argv[0]; + + for (i = 1; i < argc && argv[i][0] == '-'; ++i) { + for (j = 1; argv[i][j]; ++j) { + switch (argv[i][j]) { + case 'v': + verbose = ~verbose; + break; + + case 'b': + pad = BLOCK_SIZE; + break; + + case 'p': + primary = 1; /* make primary bootblock */ + break; + } + } + } + + if (i >= argc) { + usage(); + } + inname = argv[i++]; + + fd = open(inname, O_RDONLY); + if (fd == -1) { + perror("open"); + exit(1); + } + + ofd = 1; + if (i < argc) { + ofd = open(argv[i++], O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (fd == -1) { + perror("open"); + exit(1); + } + } + + if (primary) { + /* generate bootblock for primary loader */ + + unsigned long bb[64], sum = 0; + struct stat st; + off_t size; + int i; + + if (ofd == 1) { + usage(); + } + + if (fstat(fd, &st) == -1) { + perror("fstat"); + exit(1); + } + + size = (st.st_size + BLOCK_SIZE - 1) & ~(BLOCK_SIZE - 1); + memset(bb, 0, sizeof(bb)); + strcpy((char *) bb, "Linux SRM bootblock"); + bb[60] = size / BLOCK_SIZE; /* count */ + bb[61] = 1; /* starting sector # */ + bb[62] = 0; /* flags---must be 0 */ + for (i = 0; i < 63; ++i) { + sum += bb[i]; + } + bb[63] = sum; + if (write(ofd, bb, sizeof(bb)) != sizeof(bb)) { + perror("boot-block write"); + exit(1); + } + printf("%lu\n", size); + return 0; + } + + /* read and inspect exec header: */ + + if (read(fd, buf, sizeof(buf)) < 0) { + perror("read"); + exit(1); + } + +#ifdef __ELF__ + elf = (struct elfhdr *) buf; + + if (elf->e_ident[0] == 0x7f && strncmp(elf->e_ident + 1, "ELF", 3) == 0) { + if (elf->e_type != ET_EXEC) { + fprintf(stderr, "%s: %s is not an ELF executable\n", + prog_name, inname); + exit(1); + } + if (!elf_check_arch(elf->e_machine)) { + fprintf(stderr, "%s: is not for this processor (e_machine=%d)\n", + prog_name, elf->e_machine); + exit(1); + } + if (elf->e_phnum != 1) { + fprintf(stderr, + "%s: %d program headers (forgot to link with -N?)\n", + prog_name, elf->e_phnum); + } + + e_entry = elf->e_entry; + + lseek(fd, elf->e_phoff, SEEK_SET); + if (read(fd, buf, sizeof(*elf_phdr)) != sizeof(*elf_phdr)) { + perror("read"); + exit(1); + } + + elf_phdr = (struct elf_phdr *) buf; + offset = elf_phdr->p_offset; + mem_size = elf_phdr->p_memsz; + fil_size = elf_phdr->p_filesz; + + /* work around ELF bug: */ + if (elf_phdr->p_vaddr < e_entry) { + unsigned long delta = e_entry - elf_phdr->p_vaddr; + offset += delta; + mem_size -= delta; + fil_size -= delta; + elf_phdr->p_vaddr += delta; + } + + if (verbose) { + fprintf(stderr, "%s: extracting %#016lx-%#016lx (at %lx)\n", + prog_name, (long) elf_phdr->p_vaddr, + elf_phdr->p_vaddr + fil_size, offset); + } + } else +#endif + { + aout = (struct exec *) buf; + + if (!(aout->fh.f_flags & COFF_F_EXEC)) { + fprintf(stderr, "%s: %s is not in executable format\n", + prog_name, inname); + exit(1); + } + + if (aout->fh.f_opthdr != sizeof(aout->ah)) { + fprintf(stderr, "%s: %s has unexpected optional header size\n", + prog_name, inname); + exit(1); + } + + if (N_MAGIC(*aout) != OMAGIC) { + fprintf(stderr, "%s: %s is not an OMAGIC file\n", + prog_name, inname); + exit(1); + } + offset = N_TXTOFF(*aout); + fil_size = aout->ah.tsize + aout->ah.dsize; + mem_size = fil_size + aout->ah.bsize; + + if (verbose) { + fprintf(stderr, "%s: extracting %#016lx-%#016lx (at %lx)\n", + prog_name, aout->ah.text_start, + aout->ah.text_start + fil_size, offset); + } + } + + if (lseek(fd, offset, SEEK_SET) != offset) { + perror("lseek"); + exit(1); + } + + if (verbose) { + fprintf(stderr, "%s: copying %lu byte from %s\n", + prog_name, (unsigned long) fil_size, inname); + } + + tocopy = fil_size; + while (tocopy > 0) { + n = tocopy; + if (n > sizeof(buf)) { + n = sizeof(buf); + } + tocopy -= n; + if ((size_t) read(fd, buf, n) != n) { + perror("read"); + exit(1); + } + do { + nwritten = write(ofd, buf, n); + if ((ssize_t) nwritten == -1) { + perror("write"); + exit(1); + } + n -= nwritten; + } while (n > 0); + } + + if (pad) { + mem_size = ((mem_size + pad - 1) / pad) * pad; + } + + tocopy = mem_size - fil_size; + if (tocopy > 0) { + fprintf(stderr, + "%s: zero-filling bss and aligning to %lu with %lu bytes\n", + prog_name, pad, (unsigned long) tocopy); + + memset(buf, 0x00, sizeof(buf)); + do { + n = tocopy; + if (n > sizeof(buf)) { + n = sizeof(buf); + } + nwritten = write(ofd, buf, n); + if ((ssize_t) nwritten == -1) { + perror("write"); + exit(1); + } + tocopy -= nwritten; + } while (tocopy > 0); + } + return 0; +} |