153090Sbostic /*- 253090Sbostic * Copyright (c) 1992 The Regents of the University of California. 353090Sbostic * All rights reserved. 453090Sbostic * 553090Sbostic * This code is derived from software contributed to Berkeley by 653090Sbostic * Ralph Campbell. 753090Sbostic * 853090Sbostic * %sccs.include.redist.c% 953090Sbostic * 10*53091Sbostic * @(#)mkboottape.c 7.2 (Berkeley) 03/30/92 1153090Sbostic */ 1253090Sbostic 1353090Sbostic #include <sys/param.h> 14*53091Sbostic #include <sys/stat.h> 1553090Sbostic #include <sys/exec.h> 16*53091Sbostic #include <errno.h> 17*53091Sbostic #include <stdio.h> 18*53091Sbostic #include <stdlib.h> 19*53091Sbostic #include <unistd.h> 20*53091Sbostic #include <fcntl.h> 21*53091Sbostic #include <string.h> 2253090Sbostic #include "../dev/devDiskLabel.h" 2353090Sbostic 24*53091Sbostic void err __P((const char *, ...)); 25*53091Sbostic void usage __P((void)); 2653090Sbostic 2753090Sbostic /* 2853090Sbostic * This program takes a kernel and the name of the special device file that 2953090Sbostic * has the mini-root file system stored on it and creates a boot tape. 3053090Sbostic * The -b option makes a bootfile that can load the kernel and mini-root 3153090Sbostic * over the network using the 'boot 6/tftp/filename -m' PROM command. 3253090Sbostic * 3353090Sbostic * usage: mkboottape [-b] tapedev vmunix minirootdev size 3453090Sbostic */ 35*53091Sbostic int 3653090Sbostic main(argc, argv) 3753090Sbostic int argc; 3853090Sbostic char *argv[]; 3953090Sbostic { 4053090Sbostic register int i, n; 4153090Sbostic Dec_DiskBoot decBootInfo; 4253090Sbostic ProcSectionHeader shdr; 4353090Sbostic struct exec aout; 4453090Sbostic long loadAddr; 4553090Sbostic long execAddr; 4653090Sbostic long textoff; 4753090Sbostic long length; 4853090Sbostic long rootsize; 49*53091Sbostic int ifd, ofd, rfd; 50*53091Sbostic int makebootfile; 51*53091Sbostic int nsectors; 52*53091Sbostic char block[DEV_BSIZE]; 5353090Sbostic 54*53091Sbostic makebootfile = 0; 55*53091Sbostic while ((i = getopt(argc, argv, "b")) != EOF) 56*53091Sbostic switch(i) { 57*53091Sbostic case 'b': 58*53091Sbostic makebootfile = 1; 59*53091Sbostic break; 60*53091Sbostic case '?': 61*53091Sbostic default: 62*53091Sbostic usage(); 63*53091Sbostic } 64*53091Sbostic argc -= optind; 65*53091Sbostic argv += optind; 66*53091Sbostic 6753090Sbostic if (argc != 5) 6853090Sbostic usage(); 6953090Sbostic rootsize = atoi(argv[4]); 70*53091Sbostic 7153090Sbostic if (makebootfile) 72*53091Sbostic ofd = open(argv[1], O_CREAT|O_TRUNC|O_WRONLY, DEFFILEMODE); 7353090Sbostic else 74*53091Sbostic ofd = open(argv[1], O_RDWR, 0); 75*53091Sbostic if (ofd < 0) 76*53091Sbostic deverr: err("%s: %s", argv[1], strerror(errno)); 7753090Sbostic 78*53091Sbostic if ((ifd = open(argv[2], O_RDONLY, 0)) < 0) 79*53091Sbostic bootferr: err("%s: %s", argv[2], strerror(errno)); 80*53091Sbostic 81*53091Sbostic if ((rfd = open(argv[3], 0, 0)) < 0) 82*53091Sbostic rooterr: err("%s: %s", argv[3], strerror(errno)); 83*53091Sbostic 84*53091Sbostic 8553090Sbostic /* 8653090Sbostic * Check for exec header and skip to code segment. 8753090Sbostic */ 88*53091Sbostic if (read(ifd, &aout, sizeof(aout)) != sizeof(aout) || 89*53091Sbostic aout.ex_fhdr.magic != COFF_MAGIC || aout.a_magic != OMAGIC) 90*53091Sbostic err("need impure text format (OMAGIC) file"); 91*53091Sbostic 9253090Sbostic loadAddr = aout.ex_aout.codeStart; 9353090Sbostic execAddr = aout.a_entry; 9453090Sbostic length = aout.a_text + aout.a_data; 9553090Sbostic textoff = N_TXTOFF(aout); 96*53091Sbostic (void)printf("Input file is COFF format\n"); 97*53091Sbostic (void)printf("load %x, start %x, len %d\n", loadAddr, execAddr, length); 9853090Sbostic 9953090Sbostic /* 10053090Sbostic * Compute size of boot program rounded to page size + mini-root size. 10153090Sbostic */ 10253090Sbostic nsectors = (((length + aout.a_bss + NBPG - 1) & ~(NBPG - 1)) >> 103*53091Sbostic DEV_BSHIFT) + rootsize; 10453090Sbostic 10553090Sbostic if (makebootfile) { 10653090Sbostic /* 10753090Sbostic * Write modified ECOFF header. 10853090Sbostic */ 10953090Sbostic aout.ex_fhdr.numSections = 1; 11053090Sbostic aout.ex_fhdr.numSyms = 0; 11153090Sbostic aout.ex_fhdr.symPtr = 0; 11253090Sbostic aout.a_text = nsectors << DEV_BSHIFT; 11353090Sbostic aout.a_data = 0; 11453090Sbostic aout.a_bss = 0; 11553090Sbostic aout.ex_aout.heapStart = aout.ex_aout.bssStart = 11653090Sbostic aout.ex_aout.codeStart + aout.a_text; 11753090Sbostic if (write(ofd, (char *)&aout, sizeof(aout)) != sizeof(aout)) 11853090Sbostic goto deverr; 11953090Sbostic strncpy(shdr.name, ".text", sizeof(shdr.name)); 12053090Sbostic shdr.physAddr = shdr.virtAddr = loadAddr; 12153090Sbostic shdr.size = aout.a_text; 12253090Sbostic shdr.sectionPtr = n = (sizeof(aout) + sizeof(shdr) + 15) & ~15; 12353090Sbostic shdr.relocPtr = 0; 12453090Sbostic shdr.lnnoPtr = 0; 12553090Sbostic shdr.numReloc = 0; 12653090Sbostic shdr.numLnno = 0; 12753090Sbostic shdr.flags = 0x20; 12853090Sbostic if (write(ofd, (char *)&shdr, sizeof(shdr)) != sizeof(shdr)) 12953090Sbostic goto deverr; 13053090Sbostic n -= sizeof(aout) + sizeof(shdr); 13153090Sbostic if (write(ofd, block, n) != n) 13253090Sbostic goto deverr; 13353090Sbostic } else { 13453090Sbostic /* 13553090Sbostic * Write the boot information block. 13653090Sbostic */ 13753090Sbostic decBootInfo.magic = DEC_BOOT_MAGIC; 13853090Sbostic decBootInfo.mode = 0; 13953090Sbostic decBootInfo.loadAddr = loadAddr; 14053090Sbostic decBootInfo.execAddr = execAddr; 14153090Sbostic decBootInfo.map[0].numBlocks = nsectors; 14253090Sbostic decBootInfo.map[0].startBlock = 1; 14353090Sbostic decBootInfo.map[1].numBlocks = 0; 14453090Sbostic if (write(ofd, (char *)&decBootInfo, sizeof(decBootInfo)) != 14553090Sbostic sizeof(decBootInfo)) 14653090Sbostic goto deverr; 14753090Sbostic } 14853090Sbostic /* seek to start of text */ 149*53091Sbostic if (lseek(ifd, textoff, SEEK_SET) < 0) 15053090Sbostic goto bootferr; 15153090Sbostic 15253090Sbostic /* 15353090Sbostic * Write the remaining code to the correct place on the tape. 15453090Sbostic */ 155*53091Sbostic for (i = length; i > 0; i -= n) { 15653090Sbostic n = DEV_BSIZE; 15753090Sbostic if (n > i) 15853090Sbostic n = i; 15953090Sbostic if (read(ifd, block, n) != n) 16053090Sbostic goto bootferr; 16153090Sbostic if (write(ofd, block, n) != n) 16253090Sbostic goto deverr; 16353090Sbostic } 16453090Sbostic 16553090Sbostic /* 16653090Sbostic * Pad the boot file with zeros to the start of the mini-root. 16753090Sbostic */ 16853090Sbostic bzero(block, DEV_BSIZE); 169*53091Sbostic for (i = ((nsectors - rootsize) << DEV_BSHIFT) - length; 170*53091Sbostic i > 0; i -= n) { 17153090Sbostic n = DEV_BSIZE; 17253090Sbostic if (n > i) 17353090Sbostic n = i; 17453090Sbostic if (write(ofd, block, n) != n) 17553090Sbostic goto deverr; 17653090Sbostic } 17753090Sbostic 17853090Sbostic /* 17953090Sbostic * Write the mini-root to tape. 18053090Sbostic */ 181*53091Sbostic for (i = rootsize; i > 0; i--) { 182*53091Sbostic if (read(rfd, block, DEV_BSIZE) != DEV_BSIZE) 183*53091Sbostic goto rooterr; 18453090Sbostic if (write(ofd, block, DEV_BSIZE) != DEV_BSIZE) 18553090Sbostic goto deverr; 18653090Sbostic } 18753090Sbostic 188*53091Sbostic (void)printf("mkboottape: wrote %d sectors\n", nsectors); 18953090Sbostic exit(0); 19053090Sbostic } 19153090Sbostic 192*53091Sbostic void 19353090Sbostic usage() 19453090Sbostic { 195*53091Sbostic (void)fprintf(stderr, 196*53091Sbostic "usage: mkboottape [-b] tapedev vmunix minirootdev size\n"); 19753090Sbostic exit(1); 19853090Sbostic } 199*53091Sbostic 200*53091Sbostic #if __STDC__ 201*53091Sbostic #include <stdarg.h> 202*53091Sbostic #else 203*53091Sbostic #include <varargs.h> 204*53091Sbostic #endif 205*53091Sbostic 206*53091Sbostic void 207*53091Sbostic #if __STDC__ 208*53091Sbostic err(const char *fmt, ...) 209*53091Sbostic #else 210*53091Sbostic err(fmt, va_alist) 211*53091Sbostic char *fmt; 212*53091Sbostic va_dcl 213*53091Sbostic #endif 214*53091Sbostic { 215*53091Sbostic va_list ap; 216*53091Sbostic #if __STDC__ 217*53091Sbostic va_start(ap, fmt); 218*53091Sbostic #else 219*53091Sbostic va_start(ap); 220*53091Sbostic #endif 221*53091Sbostic (void)fprintf(stderr, "mkboottape: "); 222*53091Sbostic (void)vfprintf(stderr, fmt, ap); 223*53091Sbostic va_end(ap); 224*53091Sbostic (void)fprintf(stderr, "\n"); 225*53091Sbostic exit(1); 226*53091Sbostic /* NOTREACHED */ 227*53091Sbostic } 228