1*53090Sbostic /*- 2*53090Sbostic * Copyright (c) 1992 The Regents of the University of California. 3*53090Sbostic * All rights reserved. 4*53090Sbostic * 5*53090Sbostic * This code is derived from software contributed to Berkeley by 6*53090Sbostic * Ralph Campbell. 7*53090Sbostic * 8*53090Sbostic * %sccs.include.redist.c% 9*53090Sbostic * 10*53090Sbostic * @(#)mkboottape.c 7.1 (Berkeley) 03/30/92 11*53090Sbostic */ 12*53090Sbostic 13*53090Sbostic #include <stdio.h> 14*53090Sbostic #include <sys/param.h> 15*53090Sbostic #include <sys/exec.h> 16*53090Sbostic #include "../dev/devDiskLabel.h" 17*53090Sbostic 18*53090Sbostic char block[DEV_BSIZE]; 19*53090Sbostic char *tapedev, *rootdev, *bootfname; 20*53090Sbostic 21*53090Sbostic /* 22*53090Sbostic * This program takes a kernel and the name of the special device file that 23*53090Sbostic * has the mini-root file system stored on it and creates a boot tape. 24*53090Sbostic * The -b option makes a bootfile that can load the kernel and mini-root 25*53090Sbostic * over the network using the 'boot 6/tftp/filename -m' PROM command. 26*53090Sbostic * 27*53090Sbostic * usage: mkboottape [-b] tapedev vmunix minirootdev size 28*53090Sbostic */ 29*53090Sbostic main(argc, argv) 30*53090Sbostic int argc; 31*53090Sbostic char *argv[]; 32*53090Sbostic { 33*53090Sbostic register int i, n; 34*53090Sbostic int ifd, ofd, rfd; 35*53090Sbostic Dec_DiskBoot decBootInfo; 36*53090Sbostic ProcSectionHeader shdr; 37*53090Sbostic struct exec aout; 38*53090Sbostic int nsectors; 39*53090Sbostic long loadAddr; 40*53090Sbostic long execAddr; 41*53090Sbostic long textoff; 42*53090Sbostic long length; 43*53090Sbostic long rootsize; 44*53090Sbostic int makebootfile = 0; 45*53090Sbostic 46*53090Sbostic if (argc > 1 && strcmp(argv[1], "-b") == 0) { 47*53090Sbostic argc--; 48*53090Sbostic argv++; 49*53090Sbostic makebootfile = 1; 50*53090Sbostic } 51*53090Sbostic if (argc != 5) 52*53090Sbostic usage(); 53*53090Sbostic tapedev = argv[1]; 54*53090Sbostic bootfname = argv[2]; 55*53090Sbostic rootdev = argv[3]; 56*53090Sbostic rootsize = atoi(argv[4]); 57*53090Sbostic ifd = open(bootfname, 0, 0); 58*53090Sbostic if (ifd < 0) { 59*53090Sbostic bootferr: 60*53090Sbostic perror(bootfname); 61*53090Sbostic exit(1); 62*53090Sbostic } 63*53090Sbostic rfd = open(rootdev, 0, 0); 64*53090Sbostic if (rfd < 0) { 65*53090Sbostic perror(rootdev); 66*53090Sbostic exit(1); 67*53090Sbostic } 68*53090Sbostic if (makebootfile) 69*53090Sbostic ofd = creat(tapedev, 0666); 70*53090Sbostic else 71*53090Sbostic ofd = open(tapedev, 2, 0); 72*53090Sbostic if (ofd < 0) { 73*53090Sbostic deverr: 74*53090Sbostic perror(tapedev); 75*53090Sbostic exit(1); 76*53090Sbostic } 77*53090Sbostic 78*53090Sbostic /* 79*53090Sbostic * Check for exec header and skip to code segment. 80*53090Sbostic */ 81*53090Sbostic i = read(ifd, (char *)&aout, sizeof(aout)); 82*53090Sbostic if (i != sizeof(aout) || aout.ex_fhdr.magic != COFF_MAGIC || 83*53090Sbostic aout.a_magic != OMAGIC) { 84*53090Sbostic fprintf(stderr, "Need impure text format (OMAGIC) file\n"); 85*53090Sbostic exit(1); 86*53090Sbostic } 87*53090Sbostic loadAddr = aout.ex_aout.codeStart; 88*53090Sbostic execAddr = aout.a_entry; 89*53090Sbostic length = aout.a_text + aout.a_data; 90*53090Sbostic textoff = N_TXTOFF(aout); 91*53090Sbostic printf("Input file is COFF format\n"); 92*53090Sbostic printf("load %x, start %x, len %d\n", loadAddr, execAddr, length); 93*53090Sbostic 94*53090Sbostic /* 95*53090Sbostic * Compute size of boot program rounded to page size + mini-root size. 96*53090Sbostic */ 97*53090Sbostic nsectors = (((length + aout.a_bss + NBPG - 1) & ~(NBPG - 1)) >> 98*53090Sbostic DEV_BSHIFT) + rootsize; 99*53090Sbostic 100*53090Sbostic if (makebootfile) { 101*53090Sbostic /* 102*53090Sbostic * Write modified ECOFF header. 103*53090Sbostic */ 104*53090Sbostic aout.ex_fhdr.numSections = 1; 105*53090Sbostic aout.ex_fhdr.numSyms = 0; 106*53090Sbostic aout.ex_fhdr.symPtr = 0; 107*53090Sbostic aout.a_text = nsectors << DEV_BSHIFT; 108*53090Sbostic aout.a_data = 0; 109*53090Sbostic aout.a_bss = 0; 110*53090Sbostic aout.ex_aout.heapStart = aout.ex_aout.bssStart = 111*53090Sbostic aout.ex_aout.codeStart + aout.a_text; 112*53090Sbostic if (write(ofd, (char *)&aout, sizeof(aout)) != sizeof(aout)) 113*53090Sbostic goto deverr; 114*53090Sbostic strncpy(shdr.name, ".text", sizeof(shdr.name)); 115*53090Sbostic shdr.physAddr = shdr.virtAddr = loadAddr; 116*53090Sbostic shdr.size = aout.a_text; 117*53090Sbostic shdr.sectionPtr = n = (sizeof(aout) + sizeof(shdr) + 15) & ~15; 118*53090Sbostic shdr.relocPtr = 0; 119*53090Sbostic shdr.lnnoPtr = 0; 120*53090Sbostic shdr.numReloc = 0; 121*53090Sbostic shdr.numLnno = 0; 122*53090Sbostic shdr.flags = 0x20; 123*53090Sbostic if (write(ofd, (char *)&shdr, sizeof(shdr)) != sizeof(shdr)) 124*53090Sbostic goto deverr; 125*53090Sbostic n -= sizeof(aout) + sizeof(shdr); 126*53090Sbostic if (write(ofd, block, n) != n) 127*53090Sbostic goto deverr; 128*53090Sbostic } else { 129*53090Sbostic /* 130*53090Sbostic * Write the boot information block. 131*53090Sbostic */ 132*53090Sbostic decBootInfo.magic = DEC_BOOT_MAGIC; 133*53090Sbostic decBootInfo.mode = 0; 134*53090Sbostic decBootInfo.loadAddr = loadAddr; 135*53090Sbostic decBootInfo.execAddr = execAddr; 136*53090Sbostic decBootInfo.map[0].numBlocks = nsectors; 137*53090Sbostic decBootInfo.map[0].startBlock = 1; 138*53090Sbostic decBootInfo.map[1].numBlocks = 0; 139*53090Sbostic if (write(ofd, (char *)&decBootInfo, sizeof(decBootInfo)) != 140*53090Sbostic sizeof(decBootInfo)) 141*53090Sbostic goto deverr; 142*53090Sbostic } 143*53090Sbostic /* seek to start of text */ 144*53090Sbostic if (lseek(ifd, textoff, 0) < 0) 145*53090Sbostic goto bootferr; 146*53090Sbostic 147*53090Sbostic /* 148*53090Sbostic * Write the remaining code to the correct place on the tape. 149*53090Sbostic */ 150*53090Sbostic i = length; 151*53090Sbostic while (i > 0) { 152*53090Sbostic n = DEV_BSIZE; 153*53090Sbostic if (n > i) 154*53090Sbostic n = i; 155*53090Sbostic if (read(ifd, block, n) != n) 156*53090Sbostic goto bootferr; 157*53090Sbostic if (write(ofd, block, n) != n) 158*53090Sbostic goto deverr; 159*53090Sbostic i -= n; 160*53090Sbostic } 161*53090Sbostic 162*53090Sbostic /* 163*53090Sbostic * Pad the boot file with zeros to the start of the mini-root. 164*53090Sbostic */ 165*53090Sbostic bzero(block, DEV_BSIZE); 166*53090Sbostic i = ((nsectors - rootsize) << DEV_BSHIFT) - length; 167*53090Sbostic while (i > 0) { 168*53090Sbostic n = DEV_BSIZE; 169*53090Sbostic if (n > i) 170*53090Sbostic n = i; 171*53090Sbostic if (write(ofd, block, n) != n) 172*53090Sbostic goto deverr; 173*53090Sbostic i -= n; 174*53090Sbostic } 175*53090Sbostic 176*53090Sbostic /* 177*53090Sbostic * Write the mini-root to tape. 178*53090Sbostic */ 179*53090Sbostic i = rootsize; 180*53090Sbostic while (i > 0) { 181*53090Sbostic if (read(rfd, block, DEV_BSIZE) != DEV_BSIZE) { 182*53090Sbostic perror(rootdev); 183*53090Sbostic break; 184*53090Sbostic } 185*53090Sbostic if (write(ofd, block, DEV_BSIZE) != DEV_BSIZE) 186*53090Sbostic goto deverr; 187*53090Sbostic i--; 188*53090Sbostic } 189*53090Sbostic 190*53090Sbostic printf("Wrote %d sectors\n", nsectors); 191*53090Sbostic exit(0); 192*53090Sbostic } 193*53090Sbostic 194*53090Sbostic usage() 195*53090Sbostic { 196*53090Sbostic printf("Usage: mkboottape [-b] tapedev vmunix minirootdev size\n"); 197*53090Sbostic printf("where:\n"); 198*53090Sbostic printf("\t\"tapedev\" is the tape drive device\n"); 199*53090Sbostic printf("\t\"vmunix\" is a -N format file\n"); 200*53090Sbostic printf("\t\"minitrootdev\" is the character device of a mini-root file system disk\n"); 201*53090Sbostic printf("\t\"size\" is the number of 512 byte blocks in the file system\n"); 202*53090Sbostic exit(1); 203*53090Sbostic } 204