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*58573Sralph * @(#)mkboottape.c 7.7 (Berkeley) 03/08/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> 23*58573Sralph #include <err.h> 2453090Sbostic 2556526Sbostic #include <pmax/stand/dec_boot.h> 2657876Sralph #include <pmax/stand/dec_exec.h> 2753206Sralph 2853091Sbostic void usage __P((void)); 2953090Sbostic 3053206Sralph struct Dec_DiskBoot decBootInfo; 3157876Sralph struct coff_exec dec_exec; 32*58573Sralph extern char *__progname; /* Program name, from crt0. */ 3353206Sralph 3453090Sbostic /* 3553090Sbostic * This program takes a kernel and the name of the special device file that 3653090Sbostic * has the mini-root file system stored on it and creates a boot tape. 3753090Sbostic * The -b option makes a bootfile that can load the kernel and mini-root 3853090Sbostic * over the network using the 'boot 6/tftp/filename -m' PROM command. 3953090Sbostic * 4053090Sbostic * usage: mkboottape [-b] tapedev vmunix minirootdev size 4153090Sbostic */ 4253091Sbostic int 4353090Sbostic main(argc, argv) 4453090Sbostic int argc; 4553090Sbostic char *argv[]; 4653090Sbostic { 4753090Sbostic register int i, n; 4853090Sbostic ProcSectionHeader shdr; 4953090Sbostic struct exec aout; 5053090Sbostic long loadAddr; 5153090Sbostic long execAddr; 52*58573Sralph off_t textoff; 5353090Sbostic long length; 5453090Sbostic long rootsize; 5553091Sbostic int ifd, ofd, rfd; 5653091Sbostic int makebootfile; 5753091Sbostic int nsectors; 5853091Sbostic char block[DEV_BSIZE]; 5953090Sbostic 6053091Sbostic makebootfile = 0; 6153091Sbostic while ((i = getopt(argc, argv, "b")) != EOF) 6253091Sbostic switch(i) { 6353091Sbostic case 'b': 6453091Sbostic makebootfile = 1; 6553091Sbostic break; 6653091Sbostic case '?': 6753091Sbostic default: 6853091Sbostic usage(); 6953091Sbostic } 7053091Sbostic argc -= optind; 7153091Sbostic argv += optind; 7253091Sbostic 7353092Sbostic if (argc != 4) 7453090Sbostic usage(); 7553091Sbostic 7653090Sbostic if (makebootfile) 7753206Sralph ofd = open(argv[0], O_CREAT|O_TRUNC|O_WRONLY, DEFFILEMODE); 7853090Sbostic else 7953206Sralph ofd = open(argv[0], O_RDWR, 0); 8053091Sbostic if (ofd < 0) 81*58573Sralph deverr: err(1, "%s", argv[0]); 8253090Sbostic 8353206Sralph if ((ifd = open(argv[1], O_RDONLY, 0)) < 0) 84*58573Sralph bootferr: err(1, "%s", argv[1]); 8553091Sbostic 8653206Sralph if ((rfd = open(argv[2], O_RDONLY, 0)) < 0) 87*58573Sralph rooterr: err(1, "%s", argv[2]); 8853091Sbostic 8953206Sralph rootsize = atoi(argv[3]); 9053091Sbostic 9153090Sbostic /* 9253090Sbostic * Check for exec header and skip to code segment. 9353090Sbostic */ 9453091Sbostic if (read(ifd, &aout, sizeof(aout)) != sizeof(aout) || 95*58573Sralph aout.a_magic != OMAGIC) { 96*58573Sralph fprintf(stderr, "%s: %s: need old text format (OMAGIC) file\n", 97*58573Sralph __progname, argv[1]); 98*58573Sralph exit(1); 99*58573Sralph } 10053091Sbostic 10157876Sralph loadAddr = aout.a_entry; 10253090Sbostic execAddr = aout.a_entry; 10353090Sbostic length = aout.a_text + aout.a_data; 10453090Sbostic textoff = N_TXTOFF(aout); 10557876Sralph (void)printf("Input file is a.out format\n"); 10653091Sbostic (void)printf("load %x, start %x, len %d\n", loadAddr, execAddr, length); 10753090Sbostic 10853090Sbostic /* 10953090Sbostic * Compute size of boot program rounded to page size + mini-root size. 11053090Sbostic */ 11153090Sbostic nsectors = (((length + aout.a_bss + NBPG - 1) & ~(NBPG - 1)) >> 11253206Sralph DEV_BSHIFT) + rootsize; 11353090Sbostic 11453090Sbostic if (makebootfile) { 11553090Sbostic /* 11657876Sralph * Write the ECOFF header. 11753090Sbostic */ 11857876Sralph dec_exec.magic = COFF_MAGIC; 11957876Sralph dec_exec.numSections = 1; 12057876Sralph dec_exec.optHeader = 56; 12157876Sralph dec_exec.flags = 7; 12257876Sralph dec_exec.aout_magic = OMAGIC; 12357876Sralph dec_exec.verStamp = 512; 12457876Sralph dec_exec.codeSize = nsectors << DEV_BSHIFT; 12557876Sralph dec_exec.entry = execAddr; 12657876Sralph dec_exec.codeStart = loadAddr; 12757876Sralph dec_exec.heapStart = dec_exec.bssStart = 12857876Sralph dec_exec.codeStart + aout.a_text; 12957876Sralph if (write(ofd, (char *)&dec_exec, sizeof(dec_exec)) != 13057876Sralph sizeof(dec_exec)) 13153090Sbostic goto deverr; 13253090Sbostic strncpy(shdr.name, ".text", sizeof(shdr.name)); 13353090Sbostic shdr.physAddr = shdr.virtAddr = loadAddr; 13457876Sralph shdr.size = dec_exec.codeSize; 13557876Sralph shdr.sectionPtr = n = 13657876Sralph (sizeof(dec_exec) + sizeof(shdr) + 15) & ~15; 13753090Sbostic shdr.relocPtr = 0; 13853090Sbostic shdr.lnnoPtr = 0; 13953090Sbostic shdr.numReloc = 0; 14053090Sbostic shdr.numLnno = 0; 14153090Sbostic shdr.flags = 0x20; 14253090Sbostic if (write(ofd, (char *)&shdr, sizeof(shdr)) != sizeof(shdr)) 14353090Sbostic goto deverr; 14457876Sralph n -= sizeof(dec_exec) + sizeof(shdr); 14553090Sbostic if (write(ofd, block, n) != n) 14653090Sbostic goto deverr; 14753090Sbostic } else { 14853090Sbostic /* 14953090Sbostic * Write the boot information block. 15053090Sbostic */ 15153090Sbostic decBootInfo.magic = DEC_BOOT_MAGIC; 15253090Sbostic decBootInfo.mode = 0; 15353090Sbostic decBootInfo.loadAddr = loadAddr; 15453090Sbostic decBootInfo.execAddr = execAddr; 15553090Sbostic decBootInfo.map[0].numBlocks = nsectors; 15653090Sbostic decBootInfo.map[0].startBlock = 1; 15753090Sbostic decBootInfo.map[1].numBlocks = 0; 15853090Sbostic if (write(ofd, (char *)&decBootInfo, sizeof(decBootInfo)) != 15953090Sbostic sizeof(decBootInfo)) 16053090Sbostic goto deverr; 16153090Sbostic } 16253090Sbostic /* seek to start of text */ 16353091Sbostic if (lseek(ifd, textoff, SEEK_SET) < 0) 16453090Sbostic goto bootferr; 16553090Sbostic 16653090Sbostic /* 16753090Sbostic * Write the remaining code to the correct place on the tape. 16853090Sbostic */ 16953091Sbostic for (i = length; i > 0; i -= n) { 17053090Sbostic n = DEV_BSIZE; 17153090Sbostic if (n > i) 17253090Sbostic n = i; 17353090Sbostic if (read(ifd, block, n) != n) 17453090Sbostic goto bootferr; 17553206Sralph if (write(ofd, block, DEV_BSIZE) != DEV_BSIZE) 17653090Sbostic goto deverr; 17753090Sbostic } 17853090Sbostic 17953090Sbostic /* 18053090Sbostic * Pad the boot file with zeros to the start of the mini-root. 18153090Sbostic */ 18253090Sbostic bzero(block, DEV_BSIZE); 18353206Sralph i = ((nsectors - rootsize) << DEV_BSHIFT) - 18453206Sralph ((length + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1)); 18553206Sralph n = DEV_BSIZE; 18653206Sralph for (; i > 0; i -= n) { 18753090Sbostic if (write(ofd, block, n) != n) 18853090Sbostic goto deverr; 18953090Sbostic } 19053090Sbostic 19153090Sbostic /* 19253090Sbostic * Write the mini-root to tape. 19353090Sbostic */ 19453091Sbostic for (i = rootsize; i > 0; i--) { 19553091Sbostic if (read(rfd, block, DEV_BSIZE) != DEV_BSIZE) 19653091Sbostic goto rooterr; 19753090Sbostic if (write(ofd, block, DEV_BSIZE) != DEV_BSIZE) 19853090Sbostic goto deverr; 19953090Sbostic } 20053090Sbostic 201*58573Sralph (void)printf("%s: wrote %d sectors\n", __progname, nsectors); 20253090Sbostic exit(0); 20353090Sbostic } 20453090Sbostic 20553091Sbostic void 20653090Sbostic usage() 20753090Sbostic { 20853091Sbostic (void)fprintf(stderr, 209*58573Sralph "usage: %s [-b] tapedev vmunix minirootdev size\n", __progname); 21053090Sbostic exit(1); 21153090Sbostic } 212