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*57876Sralph * @(#)mkboottape.c 7.6 (Berkeley) 02/04/93 1153090Sbostic */ 1253090Sbostic 1353090Sbostic #include <sys/param.h> 1453091Sbostic #include <sys/stat.h> 1553090Sbostic #include <sys/exec.h> 1656526Sbostic 1753091Sbostic #include <errno.h> 1853091Sbostic #include <stdio.h> 1953091Sbostic #include <stdlib.h> 2053091Sbostic #include <unistd.h> 2153091Sbostic #include <fcntl.h> 2253091Sbostic #include <string.h> 2353090Sbostic 2456526Sbostic #include <pmax/stand/dec_boot.h> 25*57876Sralph #include <pmax/stand/dec_exec.h> 2653206Sralph 2753091Sbostic void err __P((const char *, ...)); 2853091Sbostic void usage __P((void)); 2953090Sbostic 3053206Sralph struct Dec_DiskBoot decBootInfo; 31*57876Sralph struct coff_exec dec_exec; 3253206Sralph 3353090Sbostic /* 3453090Sbostic * This program takes a kernel and the name of the special device file that 3553090Sbostic * has the mini-root file system stored on it and creates a boot tape. 3653090Sbostic * The -b option makes a bootfile that can load the kernel and mini-root 3753090Sbostic * over the network using the 'boot 6/tftp/filename -m' PROM command. 3853090Sbostic * 3953090Sbostic * usage: mkboottape [-b] tapedev vmunix minirootdev size 4053090Sbostic */ 4153091Sbostic int 4253090Sbostic main(argc, argv) 4353090Sbostic int argc; 4453090Sbostic char *argv[]; 4553090Sbostic { 4653090Sbostic register int i, n; 4753090Sbostic ProcSectionHeader shdr; 4853090Sbostic struct exec aout; 4953090Sbostic long loadAddr; 5053090Sbostic long execAddr; 5153090Sbostic long textoff; 5253090Sbostic long length; 5353090Sbostic long rootsize; 5453091Sbostic int ifd, ofd, rfd; 5553091Sbostic int makebootfile; 5653091Sbostic int nsectors; 5753091Sbostic char block[DEV_BSIZE]; 5853090Sbostic 5953091Sbostic makebootfile = 0; 6053091Sbostic while ((i = getopt(argc, argv, "b")) != EOF) 6153091Sbostic switch(i) { 6253091Sbostic case 'b': 6353091Sbostic makebootfile = 1; 6453091Sbostic break; 6553091Sbostic case '?': 6653091Sbostic default: 6753091Sbostic usage(); 6853091Sbostic } 6953091Sbostic argc -= optind; 7053091Sbostic argv += optind; 7153091Sbostic 7253092Sbostic if (argc != 4) 7353090Sbostic usage(); 7453091Sbostic 7553090Sbostic if (makebootfile) 7653206Sralph ofd = open(argv[0], O_CREAT|O_TRUNC|O_WRONLY, DEFFILEMODE); 7753090Sbostic else 7853206Sralph ofd = open(argv[0], O_RDWR, 0); 7953091Sbostic if (ofd < 0) 8053206Sralph deverr: err("%s: %s", argv[0], strerror(errno)); 8153090Sbostic 8253206Sralph if ((ifd = open(argv[1], O_RDONLY, 0)) < 0) 8353206Sralph bootferr: err("%s: %s", argv[1], strerror(errno)); 8453091Sbostic 8553206Sralph if ((rfd = open(argv[2], O_RDONLY, 0)) < 0) 8653206Sralph rooterr: err("%s: %s", argv[2], strerror(errno)); 8753091Sbostic 8853206Sralph rootsize = atoi(argv[3]); 8953091Sbostic 9053090Sbostic /* 9153090Sbostic * Check for exec header and skip to code segment. 9253090Sbostic */ 9353091Sbostic if (read(ifd, &aout, sizeof(aout)) != sizeof(aout) || 94*57876Sralph aout.a_magic != OMAGIC) 95*57876Sralph err("%s: need impure text format (OMAGIC) file", argv[1]); 9653091Sbostic 97*57876Sralph loadAddr = aout.a_entry; 9853090Sbostic execAddr = aout.a_entry; 9953090Sbostic length = aout.a_text + aout.a_data; 10053090Sbostic textoff = N_TXTOFF(aout); 101*57876Sralph (void)printf("Input file is a.out format\n"); 10253091Sbostic (void)printf("load %x, start %x, len %d\n", loadAddr, execAddr, length); 10353090Sbostic 10453090Sbostic /* 10553090Sbostic * Compute size of boot program rounded to page size + mini-root size. 10653090Sbostic */ 10753090Sbostic nsectors = (((length + aout.a_bss + NBPG - 1) & ~(NBPG - 1)) >> 10853206Sralph DEV_BSHIFT) + rootsize; 10953090Sbostic 11053090Sbostic if (makebootfile) { 11153090Sbostic /* 112*57876Sralph * Write the ECOFF header. 11353090Sbostic */ 114*57876Sralph dec_exec.magic = COFF_MAGIC; 115*57876Sralph dec_exec.numSections = 1; 116*57876Sralph dec_exec.optHeader = 56; 117*57876Sralph dec_exec.flags = 7; 118*57876Sralph dec_exec.aout_magic = OMAGIC; 119*57876Sralph dec_exec.verStamp = 512; 120*57876Sralph dec_exec.codeSize = nsectors << DEV_BSHIFT; 121*57876Sralph dec_exec.entry = execAddr; 122*57876Sralph dec_exec.codeStart = loadAddr; 123*57876Sralph dec_exec.heapStart = dec_exec.bssStart = 124*57876Sralph dec_exec.codeStart + aout.a_text; 125*57876Sralph if (write(ofd, (char *)&dec_exec, sizeof(dec_exec)) != 126*57876Sralph sizeof(dec_exec)) 12753090Sbostic goto deverr; 12853090Sbostic strncpy(shdr.name, ".text", sizeof(shdr.name)); 12953090Sbostic shdr.physAddr = shdr.virtAddr = loadAddr; 130*57876Sralph shdr.size = dec_exec.codeSize; 131*57876Sralph shdr.sectionPtr = n = 132*57876Sralph (sizeof(dec_exec) + sizeof(shdr) + 15) & ~15; 13353090Sbostic shdr.relocPtr = 0; 13453090Sbostic shdr.lnnoPtr = 0; 13553090Sbostic shdr.numReloc = 0; 13653090Sbostic shdr.numLnno = 0; 13753090Sbostic shdr.flags = 0x20; 13853090Sbostic if (write(ofd, (char *)&shdr, sizeof(shdr)) != sizeof(shdr)) 13953090Sbostic goto deverr; 140*57876Sralph n -= sizeof(dec_exec) + sizeof(shdr); 14153090Sbostic if (write(ofd, block, n) != n) 14253090Sbostic goto deverr; 14353090Sbostic } else { 14453090Sbostic /* 14553090Sbostic * Write the boot information block. 14653090Sbostic */ 14753090Sbostic decBootInfo.magic = DEC_BOOT_MAGIC; 14853090Sbostic decBootInfo.mode = 0; 14953090Sbostic decBootInfo.loadAddr = loadAddr; 15053090Sbostic decBootInfo.execAddr = execAddr; 15153090Sbostic decBootInfo.map[0].numBlocks = nsectors; 15253090Sbostic decBootInfo.map[0].startBlock = 1; 15353090Sbostic decBootInfo.map[1].numBlocks = 0; 15453090Sbostic if (write(ofd, (char *)&decBootInfo, sizeof(decBootInfo)) != 15553090Sbostic sizeof(decBootInfo)) 15653090Sbostic goto deverr; 15753090Sbostic } 15853090Sbostic /* seek to start of text */ 15953091Sbostic if (lseek(ifd, textoff, SEEK_SET) < 0) 16053090Sbostic goto bootferr; 16153090Sbostic 16253090Sbostic /* 16353090Sbostic * Write the remaining code to the correct place on the tape. 16453090Sbostic */ 16553091Sbostic for (i = length; i > 0; i -= n) { 16653090Sbostic n = DEV_BSIZE; 16753090Sbostic if (n > i) 16853090Sbostic n = i; 16953090Sbostic if (read(ifd, block, n) != n) 17053090Sbostic goto bootferr; 17153206Sralph if (write(ofd, block, DEV_BSIZE) != DEV_BSIZE) 17253090Sbostic goto deverr; 17353090Sbostic } 17453090Sbostic 17553090Sbostic /* 17653090Sbostic * Pad the boot file with zeros to the start of the mini-root. 17753090Sbostic */ 17853090Sbostic bzero(block, DEV_BSIZE); 17953206Sralph i = ((nsectors - rootsize) << DEV_BSHIFT) - 18053206Sralph ((length + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1)); 18153206Sralph n = DEV_BSIZE; 18253206Sralph for (; i > 0; i -= n) { 18353090Sbostic if (write(ofd, block, n) != n) 18453090Sbostic goto deverr; 18553090Sbostic } 18653090Sbostic 18753090Sbostic /* 18853090Sbostic * Write the mini-root to tape. 18953090Sbostic */ 19053091Sbostic for (i = rootsize; i > 0; i--) { 19153091Sbostic if (read(rfd, block, DEV_BSIZE) != DEV_BSIZE) 19253091Sbostic goto rooterr; 19353090Sbostic if (write(ofd, block, DEV_BSIZE) != DEV_BSIZE) 19453090Sbostic goto deverr; 19553090Sbostic } 19653090Sbostic 19753091Sbostic (void)printf("mkboottape: wrote %d sectors\n", nsectors); 19853090Sbostic exit(0); 19953090Sbostic } 20053090Sbostic 20153091Sbostic void 20253090Sbostic usage() 20353090Sbostic { 20453091Sbostic (void)fprintf(stderr, 20553091Sbostic "usage: mkboottape [-b] tapedev vmunix minirootdev size\n"); 20653090Sbostic exit(1); 20753090Sbostic } 20853091Sbostic 20953091Sbostic #if __STDC__ 21053091Sbostic #include <stdarg.h> 21153091Sbostic #else 21253091Sbostic #include <varargs.h> 21353091Sbostic #endif 21453091Sbostic 21553091Sbostic void 21653091Sbostic #if __STDC__ 21753091Sbostic err(const char *fmt, ...) 21853091Sbostic #else 21953091Sbostic err(fmt, va_alist) 22053091Sbostic char *fmt; 22153091Sbostic va_dcl 22253091Sbostic #endif 22353091Sbostic { 22453091Sbostic va_list ap; 22553091Sbostic #if __STDC__ 22653091Sbostic va_start(ap, fmt); 22753091Sbostic #else 22853091Sbostic va_start(ap); 22953091Sbostic #endif 23053091Sbostic (void)fprintf(stderr, "mkboottape: "); 23153091Sbostic (void)vfprintf(stderr, fmt, ap); 23253091Sbostic va_end(ap); 23353091Sbostic (void)fprintf(stderr, "\n"); 23453091Sbostic exit(1); 23553091Sbostic /* NOTREACHED */ 23653091Sbostic } 237