From e7c2a72e2680827d6a733931273a93461c0d8d1b Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 14 Nov 1995 08:00:00 +0000 Subject: Import of Linux/MIPS 1.3.0 --- arch/alpha/boot/tools/build.c | 173 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 arch/alpha/boot/tools/build.c (limited to 'arch/alpha/boot/tools') diff --git a/arch/alpha/boot/tools/build.c b/arch/alpha/boot/tools/build.c new file mode 100644 index 000000000..040655a54 --- /dev/null +++ b/arch/alpha/boot/tools/build.c @@ -0,0 +1,173 @@ +/* + * arch/alpha/boot/tools/build.c + * + * Build a bootable image from the vmlinux binary + */ +#include +#include +#include +#include + +#include + +#include + +#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; +} -- cgit v1.2.3