summaryrefslogtreecommitdiffstats
path: root/arch/alpha/boot
diff options
context:
space:
mode:
Diffstat (limited to 'arch/alpha/boot')
-rw-r--r--arch/alpha/boot/Makefile91
-rw-r--r--arch/alpha/boot/bootloader.lds50
-rw-r--r--arch/alpha/boot/head.S8
-rw-r--r--arch/alpha/boot/main.c53
-rw-r--r--arch/alpha/boot/tools/build.c173
-rw-r--r--arch/alpha/boot/tools/mkbb.c151
-rw-r--r--arch/alpha/boot/tools/objstrip.c280
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;
+}