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*53206Sralph * @(#)mkboottape.c 7.4 (Berkeley) 04/19/92 1153090Sbostic */ 1253090Sbostic 1353090Sbostic #include <sys/param.h> 1453091Sbostic #include <sys/stat.h> 1553090Sbostic #include <sys/exec.h> 1653091Sbostic #include <errno.h> 1753091Sbostic #include <stdio.h> 1853091Sbostic #include <stdlib.h> 1953091Sbostic #include <unistd.h> 2053091Sbostic #include <fcntl.h> 2153091Sbostic #include <string.h> 2253090Sbostic 23*53206Sralph #include "dec_boot.h" 24*53206Sralph 2553091Sbostic void err __P((const char *, ...)); 2653091Sbostic void usage __P((void)); 2753090Sbostic 28*53206Sralph struct Dec_DiskBoot decBootInfo; 29*53206Sralph 3053090Sbostic /* 3153090Sbostic * This program takes a kernel and the name of the special device file that 3253090Sbostic * has the mini-root file system stored on it and creates a boot tape. 3353090Sbostic * The -b option makes a bootfile that can load the kernel and mini-root 3453090Sbostic * over the network using the 'boot 6/tftp/filename -m' PROM command. 3553090Sbostic * 3653090Sbostic * usage: mkboottape [-b] tapedev vmunix minirootdev size 3753090Sbostic */ 3853091Sbostic int 3953090Sbostic main(argc, argv) 4053090Sbostic int argc; 4153090Sbostic char *argv[]; 4253090Sbostic { 4353090Sbostic register int i, n; 4453090Sbostic ProcSectionHeader shdr; 4553090Sbostic struct exec aout; 4653090Sbostic long loadAddr; 4753090Sbostic long execAddr; 4853090Sbostic long textoff; 4953090Sbostic long length; 5053090Sbostic long rootsize; 5153091Sbostic int ifd, ofd, rfd; 5253091Sbostic int makebootfile; 5353091Sbostic int nsectors; 5453091Sbostic char block[DEV_BSIZE]; 5553090Sbostic 5653091Sbostic makebootfile = 0; 5753091Sbostic while ((i = getopt(argc, argv, "b")) != EOF) 5853091Sbostic switch(i) { 5953091Sbostic case 'b': 6053091Sbostic makebootfile = 1; 6153091Sbostic break; 6253091Sbostic case '?': 6353091Sbostic default: 6453091Sbostic usage(); 6553091Sbostic } 6653091Sbostic argc -= optind; 6753091Sbostic argv += optind; 6853091Sbostic 6953092Sbostic if (argc != 4) 7053090Sbostic usage(); 7153091Sbostic 7253090Sbostic if (makebootfile) 73*53206Sralph ofd = open(argv[0], O_CREAT|O_TRUNC|O_WRONLY, DEFFILEMODE); 7453090Sbostic else 75*53206Sralph ofd = open(argv[0], O_RDWR, 0); 7653091Sbostic if (ofd < 0) 77*53206Sralph deverr: err("%s: %s", argv[0], strerror(errno)); 7853090Sbostic 79*53206Sralph if ((ifd = open(argv[1], O_RDONLY, 0)) < 0) 80*53206Sralph bootferr: err("%s: %s", argv[1], strerror(errno)); 8153091Sbostic 82*53206Sralph if ((rfd = open(argv[2], O_RDONLY, 0)) < 0) 83*53206Sralph rooterr: err("%s: %s", argv[2], strerror(errno)); 8453091Sbostic 85*53206Sralph rootsize = atoi(argv[3]); 8653091Sbostic 8753090Sbostic /* 8853090Sbostic * Check for exec header and skip to code segment. 8953090Sbostic */ 9053091Sbostic if (read(ifd, &aout, sizeof(aout)) != sizeof(aout) || 9153091Sbostic aout.ex_fhdr.magic != COFF_MAGIC || aout.a_magic != OMAGIC) 9253091Sbostic err("need impure text format (OMAGIC) file"); 9353091Sbostic 9453090Sbostic loadAddr = aout.ex_aout.codeStart; 9553090Sbostic execAddr = aout.a_entry; 9653090Sbostic length = aout.a_text + aout.a_data; 9753090Sbostic textoff = N_TXTOFF(aout); 9853091Sbostic (void)printf("Input file is COFF format\n"); 9953091Sbostic (void)printf("load %x, start %x, len %d\n", loadAddr, execAddr, length); 10053090Sbostic 10153090Sbostic /* 10253090Sbostic * Compute size of boot program rounded to page size + mini-root size. 10353090Sbostic */ 10453090Sbostic nsectors = (((length + aout.a_bss + NBPG - 1) & ~(NBPG - 1)) >> 105*53206Sralph DEV_BSHIFT) + rootsize; 10653090Sbostic 10753090Sbostic if (makebootfile) { 10853090Sbostic /* 10953090Sbostic * Write modified ECOFF header. 11053090Sbostic */ 11153090Sbostic aout.ex_fhdr.numSections = 1; 11253090Sbostic aout.ex_fhdr.numSyms = 0; 11353090Sbostic aout.ex_fhdr.symPtr = 0; 11453090Sbostic aout.a_text = nsectors << DEV_BSHIFT; 11553090Sbostic aout.a_data = 0; 11653090Sbostic aout.a_bss = 0; 11753090Sbostic aout.ex_aout.heapStart = aout.ex_aout.bssStart = 11853090Sbostic aout.ex_aout.codeStart + aout.a_text; 11953090Sbostic if (write(ofd, (char *)&aout, sizeof(aout)) != sizeof(aout)) 12053090Sbostic goto deverr; 12153090Sbostic strncpy(shdr.name, ".text", sizeof(shdr.name)); 12253090Sbostic shdr.physAddr = shdr.virtAddr = loadAddr; 12353090Sbostic shdr.size = aout.a_text; 12453090Sbostic shdr.sectionPtr = n = (sizeof(aout) + sizeof(shdr) + 15) & ~15; 12553090Sbostic shdr.relocPtr = 0; 12653090Sbostic shdr.lnnoPtr = 0; 12753090Sbostic shdr.numReloc = 0; 12853090Sbostic shdr.numLnno = 0; 12953090Sbostic shdr.flags = 0x20; 13053090Sbostic if (write(ofd, (char *)&shdr, sizeof(shdr)) != sizeof(shdr)) 13153090Sbostic goto deverr; 13253090Sbostic n -= sizeof(aout) + sizeof(shdr); 13353090Sbostic if (write(ofd, block, n) != n) 13453090Sbostic goto deverr; 13553090Sbostic } else { 13653090Sbostic /* 13753090Sbostic * Write the boot information block. 13853090Sbostic */ 13953090Sbostic decBootInfo.magic = DEC_BOOT_MAGIC; 14053090Sbostic decBootInfo.mode = 0; 14153090Sbostic decBootInfo.loadAddr = loadAddr; 14253090Sbostic decBootInfo.execAddr = execAddr; 14353090Sbostic decBootInfo.map[0].numBlocks = nsectors; 14453090Sbostic decBootInfo.map[0].startBlock = 1; 14553090Sbostic decBootInfo.map[1].numBlocks = 0; 14653090Sbostic if (write(ofd, (char *)&decBootInfo, sizeof(decBootInfo)) != 14753090Sbostic sizeof(decBootInfo)) 14853090Sbostic goto deverr; 14953090Sbostic } 15053090Sbostic /* seek to start of text */ 15153091Sbostic if (lseek(ifd, textoff, SEEK_SET) < 0) 15253090Sbostic goto bootferr; 15353090Sbostic 15453090Sbostic /* 15553090Sbostic * Write the remaining code to the correct place on the tape. 15653090Sbostic */ 15753091Sbostic for (i = length; i > 0; i -= n) { 15853090Sbostic n = DEV_BSIZE; 15953090Sbostic if (n > i) 16053090Sbostic n = i; 16153090Sbostic if (read(ifd, block, n) != n) 16253090Sbostic goto bootferr; 163*53206Sralph if (write(ofd, block, DEV_BSIZE) != DEV_BSIZE) 16453090Sbostic goto deverr; 16553090Sbostic } 16653090Sbostic 16753090Sbostic /* 16853090Sbostic * Pad the boot file with zeros to the start of the mini-root. 16953090Sbostic */ 17053090Sbostic bzero(block, DEV_BSIZE); 171*53206Sralph i = ((nsectors - rootsize) << DEV_BSHIFT) - 172*53206Sralph ((length + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1)); 173*53206Sralph n = DEV_BSIZE; 174*53206Sralph for (; i > 0; i -= n) { 17553090Sbostic if (write(ofd, block, n) != n) 17653090Sbostic goto deverr; 17753090Sbostic } 17853090Sbostic 17953090Sbostic /* 18053090Sbostic * Write the mini-root to tape. 18153090Sbostic */ 18253091Sbostic for (i = rootsize; i > 0; i--) { 18353091Sbostic if (read(rfd, block, DEV_BSIZE) != DEV_BSIZE) 18453091Sbostic goto rooterr; 18553090Sbostic if (write(ofd, block, DEV_BSIZE) != DEV_BSIZE) 18653090Sbostic goto deverr; 18753090Sbostic } 18853090Sbostic 18953091Sbostic (void)printf("mkboottape: wrote %d sectors\n", nsectors); 19053090Sbostic exit(0); 19153090Sbostic } 19253090Sbostic 19353091Sbostic void 19453090Sbostic usage() 19553090Sbostic { 19653091Sbostic (void)fprintf(stderr, 19753091Sbostic "usage: mkboottape [-b] tapedev vmunix minirootdev size\n"); 19853090Sbostic exit(1); 19953090Sbostic } 20053091Sbostic 20153091Sbostic #if __STDC__ 20253091Sbostic #include <stdarg.h> 20353091Sbostic #else 20453091Sbostic #include <varargs.h> 20553091Sbostic #endif 20653091Sbostic 20753091Sbostic void 20853091Sbostic #if __STDC__ 20953091Sbostic err(const char *fmt, ...) 21053091Sbostic #else 21153091Sbostic err(fmt, va_alist) 21253091Sbostic char *fmt; 21353091Sbostic va_dcl 21453091Sbostic #endif 21553091Sbostic { 21653091Sbostic va_list ap; 21753091Sbostic #if __STDC__ 21853091Sbostic va_start(ap, fmt); 21953091Sbostic #else 22053091Sbostic va_start(ap); 22153091Sbostic #endif 22253091Sbostic (void)fprintf(stderr, "mkboottape: "); 22353091Sbostic (void)vfprintf(stderr, fmt, ap); 22453091Sbostic va_end(ap); 22553091Sbostic (void)fprintf(stderr, "\n"); 22653091Sbostic exit(1); 22753091Sbostic /* NOTREACHED */ 22853091Sbostic } 229