152132Smckusick /* 252132Smckusick * Copyright (c) 1992 Regents of the University of California. 352132Smckusick * All rights reserved. 452132Smckusick * 552132Smckusick * This code is derived from software contributed to Berkeley by 652132Smckusick * Ralph Campbell. 752132Smckusick * 852132Smckusick * %sccs.include.redist.c% 952132Smckusick */ 1052132Smckusick 1152132Smckusick #ifndef lint 1252132Smckusick char copyright[] = 1352132Smckusick "@(#) Copyright (c) 1992 Regents of the University of California.\n\ 1452132Smckusick All rights reserved.\n"; 1552132Smckusick #endif not lint 1652132Smckusick 1752132Smckusick #ifndef lint 18*52868Sralph static char sccsid[] = "@(#)mkboot.c 7.2 (Berkeley) 03/07/92"; 1952132Smckusick #endif not lint 2052132Smckusick 2152132Smckusick #include <stdio.h> 22*52868Sralph #include "sys/param.h" 23*52868Sralph #include "sys/exec.h" 2452132Smckusick #include "../dev/devDiskLabel.h" 2552132Smckusick 2652132Smckusick /* this is the size of the standard ULTRIX boot */ 2752132Smckusick #define MAXBOOTSIZE (15 * DEV_BSIZE) 2852132Smckusick 2952132Smckusick char block[DEV_BSIZE]; 3052132Smckusick char *dev, *bootfname; 3152132Smckusick 3252132Smckusick /* 3352132Smckusick * installboot bootprog device 3452132Smckusick */ 3552132Smckusick main(argc, argv) 3652132Smckusick int argc; 3752132Smckusick char *argv[]; 3852132Smckusick { 3952132Smckusick register int i, n; 4052132Smckusick int ifd, ofd; 4152132Smckusick Dec_DiskBoot decBootInfo; 4252132Smckusick int nsectors; 4352132Smckusick long loadAddr; 4452132Smckusick long execAddr; 4552132Smckusick long length; 4652132Smckusick 4752132Smckusick if (argc != 3) 4852132Smckusick usage(); 4952132Smckusick dev = argv[2]; 5052132Smckusick i = strlen(dev); 5152132Smckusick bootfname = argv[1]; 5252132Smckusick ifd = open(bootfname, 0, 0); 5352132Smckusick if (ifd < 0) { 5452132Smckusick perror(bootfname); 5552132Smckusick exit(1); 5652132Smckusick } 5752132Smckusick ofd = open(dev, 2, 0); 5852132Smckusick if (ofd < 0) { 5952132Smckusick deverr: 6052132Smckusick perror(dev); 6152132Smckusick exit(1); 6252132Smckusick } 6352132Smckusick 6452132Smckusick /* 6552132Smckusick * Check for exec header and skip to code segment. 6652132Smckusick */ 6752132Smckusick if (!DecHeader(ifd, &loadAddr, &execAddr, &length)) { 6852132Smckusick fprintf(stderr, "Need impure text format (OMAGIC) file\n"); 6952132Smckusick exit(1); 7052132Smckusick } 7152132Smckusick if (length > MAXBOOTSIZE) { 7252132Smckusick fprintf(stderr, "boot program is too big (%d > %d)\n", 7352132Smckusick length, MAXBOOTSIZE); 7452132Smckusick exit(1); 7552132Smckusick } 7652132Smckusick 7752132Smckusick /* 7852132Smckusick * Write the boot information block. 7952132Smckusick */ 8052132Smckusick decBootInfo.magic = DEC_BOOT_MAGIC; 8152132Smckusick decBootInfo.mode = 0; 8252132Smckusick decBootInfo.loadAddr = loadAddr; 8352132Smckusick decBootInfo.execAddr = execAddr; 8452132Smckusick decBootInfo.map[0].numBlocks = nsectors = 8552132Smckusick (length + DEV_BSIZE - 1) >> DEV_BSHIFT; 8652132Smckusick decBootInfo.map[0].startBlock = 1; 8752132Smckusick decBootInfo.map[1].numBlocks = 0; 8852132Smckusick if (lseek(ofd, (long)(DEC_BOOT_SECTOR * DEV_BSIZE), 0) < 0 || 8952132Smckusick write(ofd, (char *)&decBootInfo, sizeof(decBootInfo)) != 9052132Smckusick sizeof(decBootInfo)) { 9152132Smckusick perror(dev); 9252132Smckusick fprintf(stderr, "Sector write %d failed: ", DEC_BOOT_SECTOR); 9352132Smckusick exit(1); 9452132Smckusick } 9552132Smckusick if (lseek(ofd, (long)(1 * DEV_BSIZE), 0) < 0) 9652132Smckusick goto deverr; 9752132Smckusick 9852132Smckusick /* 9952132Smckusick * Write the remaining code to the correct place on the disk. 10052132Smckusick */ 10152132Smckusick for (i = 0; i < nsectors && length > 0; i++) { 10252132Smckusick bzero(block, DEV_BSIZE); 10352132Smckusick n = length < DEV_BSIZE ? length : DEV_BSIZE; 10452132Smckusick if (read(ifd, block, n) != n) { 10552132Smckusick perror(bootfname); 10652132Smckusick break; 10752132Smckusick } 10852132Smckusick length -= n; 10952132Smckusick if (write(ofd, block, DEV_BSIZE) != DEV_BSIZE) { 11052132Smckusick perror(dev); 11152132Smckusick break; 11252132Smckusick } 11352132Smckusick } 11452132Smckusick printf("Wrote %d sectors\n", i); 11552132Smckusick if (length > 0) 11652132Smckusick printf("Warning: didn't reach end of boot program!\n"); 11752132Smckusick exit(0); 11852132Smckusick } 11952132Smckusick 12052132Smckusick usage() 12152132Smckusick { 12252132Smckusick printf("Usage: installboot bootprog device\n"); 12352132Smckusick printf("where:\n"); 12452132Smckusick printf("\t\"bootprog\" is a -N format file < %d bytes long\n", 12552132Smckusick MAXBOOTSIZE); 12652132Smckusick printf("\t\"device\" should be the 'a' partition of a bootable disk\n"); 12752132Smckusick printf("WARNING!! If the 'c' partition contains a file system, %s\n", 12852132Smckusick "DON'T RUN THIS!!"); 12952132Smckusick exit(1); 13052132Smckusick } 13152132Smckusick 13252132Smckusick /* 13352132Smckusick *---------------------------------------------------------------------- 13452132Smckusick * 13552132Smckusick * DecHeader - 13652132Smckusick * 137*52868Sralph * Check if the header is a DEC (COFF) file. 13852132Smckusick * 13952132Smckusick * Results: 14052132Smckusick * Return true if all went ok. 14152132Smckusick * 14252132Smckusick * Side effects: 14352132Smckusick * None. 14452132Smckusick * 14552132Smckusick *---------------------------------------------------------------------- 14652132Smckusick */ 14752132Smckusick DecHeader(bootFID, loadAddr, execAddr, length) 14852132Smckusick int bootFID; /* Handle on the boot program */ 14952132Smckusick long *loadAddr; /* Address to start loading boot program. */ 15052132Smckusick long *execAddr; /* Address to start executing boot program. */ 15152132Smckusick long *length; /* Length of the boot program. */ 15252132Smckusick { 15352132Smckusick struct exec aout; 15452132Smckusick int bytesRead; 15552132Smckusick 15652132Smckusick if (lseek(bootFID, 0, 0) < 0) { 15752132Smckusick perror(bootfname); 15852132Smckusick return 0; 15952132Smckusick } 16052132Smckusick bytesRead = read(bootFID, (char *)&aout, sizeof(aout)); 16152132Smckusick if (bytesRead != sizeof(aout) || aout.ex_fhdr.magic != COFF_MAGIC || 16252132Smckusick aout.a_magic != OMAGIC) 16352132Smckusick return 0; 16452132Smckusick *loadAddr = aout.ex_aout.codeStart; 16552132Smckusick *execAddr = aout.a_entry; 16652132Smckusick *length = aout.a_text + aout.a_data; 16752132Smckusick if (lseek(bootFID, N_TXTOFF(aout), 0) < 0) { 16852132Smckusick perror(bootfname); 16952132Smckusick return 0; 17052132Smckusick } 171*52868Sralph printf("Input file is COFF format\n"); 17252132Smckusick printf("load %x, start %x, len %d\n", *loadAddr, *execAddr, *length); 17352132Smckusick return 1; 17452132Smckusick } 175