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*53207Sralph static char sccsid[] = "@(#)mkboot.c 7.3 (Berkeley) 04/19/92"; 1952132Smckusick #endif not lint 2052132Smckusick 2152132Smckusick #include <stdio.h> 22*53207Sralph #include "param.h" 23*53207Sralph #include "exec.h" 24*53207Sralph #include "disklabel.h" 2552132Smckusick 26*53207Sralph #include "dec_boot.h" 27*53207Sralph 2852132Smckusick /* this is the size of the standard ULTRIX boot */ 2952132Smckusick #define MAXBOOTSIZE (15 * DEV_BSIZE) 3052132Smckusick 31*53207Sralph struct Dec_DiskBoot decBootInfo; 3252132Smckusick char block[DEV_BSIZE]; 33*53207Sralph char *bootfname, *xxboot, *bootxx; 3452132Smckusick 3552132Smckusick /* 36*53207Sralph * This program takes a boot program and splits it into xxboot and bootxx 37*53207Sralph * files for the disklabel program. The disklabel program should be used to 38*53207Sralph * label and install the boot program onto a new disk. 39*53207Sralph * 40*53207Sralph * mkboot bootprog xxboot bootxx 4152132Smckusick */ 4252132Smckusick main(argc, argv) 4352132Smckusick int argc; 4452132Smckusick char *argv[]; 4552132Smckusick { 4652132Smckusick register int i, n; 47*53207Sralph int ifd, ofd1, ofd2; 4852132Smckusick int nsectors; 4952132Smckusick long loadAddr; 5052132Smckusick long execAddr; 5152132Smckusick long length; 5252132Smckusick 53*53207Sralph if (argc != 4) 5452132Smckusick usage(); 5552132Smckusick bootfname = argv[1]; 56*53207Sralph xxboot = argv[2]; 57*53207Sralph bootxx = argv[3]; 5852132Smckusick ifd = open(bootfname, 0, 0); 5952132Smckusick if (ifd < 0) { 6052132Smckusick perror(bootfname); 6152132Smckusick exit(1); 6252132Smckusick } 63*53207Sralph ofd1 = creat(xxboot, 0666); 64*53207Sralph if (ofd1 < 0) { 65*53207Sralph xxboot_err: 66*53207Sralph perror(xxboot); 6752132Smckusick exit(1); 6852132Smckusick } 69*53207Sralph ofd2 = creat(bootxx, 0666); 70*53207Sralph if (ofd2 < 0) { 71*53207Sralph bootxx_err: 72*53207Sralph perror(bootxx); 73*53207Sralph exit(1); 74*53207Sralph } 7552132Smckusick 7652132Smckusick /* 7752132Smckusick * Check for exec header and skip to code segment. 7852132Smckusick */ 7952132Smckusick if (!DecHeader(ifd, &loadAddr, &execAddr, &length)) { 8052132Smckusick fprintf(stderr, "Need impure text format (OMAGIC) file\n"); 8152132Smckusick exit(1); 8252132Smckusick } 8352132Smckusick if (length > MAXBOOTSIZE) { 8452132Smckusick fprintf(stderr, "boot program is too big (%d > %d)\n", 8552132Smckusick length, MAXBOOTSIZE); 8652132Smckusick exit(1); 8752132Smckusick } 8852132Smckusick 8952132Smckusick /* 9052132Smckusick * Write the boot information block. 9152132Smckusick */ 9252132Smckusick decBootInfo.magic = DEC_BOOT_MAGIC; 9352132Smckusick decBootInfo.mode = 0; 9452132Smckusick decBootInfo.loadAddr = loadAddr; 9552132Smckusick decBootInfo.execAddr = execAddr; 9652132Smckusick decBootInfo.map[0].numBlocks = nsectors = 9752132Smckusick (length + DEV_BSIZE - 1) >> DEV_BSHIFT; 9852132Smckusick decBootInfo.map[0].startBlock = 1; 9952132Smckusick decBootInfo.map[1].numBlocks = 0; 100*53207Sralph if (write(ofd1, (char *)&decBootInfo, sizeof(decBootInfo)) != 101*53207Sralph sizeof(decBootInfo) || close(ofd1) != 0) 102*53207Sralph goto xxboot_err; 10352132Smckusick 10452132Smckusick /* 105*53207Sralph * Write the boot code to the bootxx file. 10652132Smckusick */ 10752132Smckusick for (i = 0; i < nsectors && length > 0; i++) { 108*53207Sralph if (length < DEV_BSIZE) { 109*53207Sralph n = length; 110*53207Sralph bzero(block, DEV_BSIZE); 111*53207Sralph } else 112*53207Sralph n = DEV_BSIZE; 11352132Smckusick if (read(ifd, block, n) != n) { 11452132Smckusick perror(bootfname); 11552132Smckusick break; 11652132Smckusick } 11752132Smckusick length -= n; 118*53207Sralph if (write(ofd2, block, DEV_BSIZE) != DEV_BSIZE) { 119*53207Sralph perror(bootxx); 12052132Smckusick break; 12152132Smckusick } 12252132Smckusick } 12352132Smckusick if (length > 0) 12452132Smckusick printf("Warning: didn't reach end of boot program!\n"); 12552132Smckusick exit(0); 12652132Smckusick } 12752132Smckusick 12852132Smckusick usage() 12952132Smckusick { 130*53207Sralph printf("Usage: mkboot bootprog xxboot bootxx\n"); 13152132Smckusick printf("where:\n"); 13252132Smckusick printf("\t\"bootprog\" is a -N format file < %d bytes long\n", 13352132Smckusick MAXBOOTSIZE); 134*53207Sralph printf("\t\"xxboot\" is the name of the first boot block\n"); 135*53207Sralph printf("\t\"bootxx\" is the name of the remaining boot blocks.\n"); 13652132Smckusick exit(1); 13752132Smckusick } 13852132Smckusick 13952132Smckusick /* 14052132Smckusick *---------------------------------------------------------------------- 14152132Smckusick * 14252132Smckusick * DecHeader - 14352132Smckusick * 14452868Sralph * Check if the header is a DEC (COFF) file. 14552132Smckusick * 14652132Smckusick * Results: 14752132Smckusick * Return true if all went ok. 14852132Smckusick * 14952132Smckusick * Side effects: 15052132Smckusick * None. 15152132Smckusick * 15252132Smckusick *---------------------------------------------------------------------- 15352132Smckusick */ 15452132Smckusick DecHeader(bootFID, loadAddr, execAddr, length) 15552132Smckusick int bootFID; /* Handle on the boot program */ 15652132Smckusick long *loadAddr; /* Address to start loading boot program. */ 15752132Smckusick long *execAddr; /* Address to start executing boot program. */ 15852132Smckusick long *length; /* Length of the boot program. */ 15952132Smckusick { 16052132Smckusick struct exec aout; 16152132Smckusick int bytesRead; 16252132Smckusick 16352132Smckusick if (lseek(bootFID, 0, 0) < 0) { 16452132Smckusick perror(bootfname); 16552132Smckusick return 0; 16652132Smckusick } 16752132Smckusick bytesRead = read(bootFID, (char *)&aout, sizeof(aout)); 16852132Smckusick if (bytesRead != sizeof(aout) || aout.ex_fhdr.magic != COFF_MAGIC || 16952132Smckusick aout.a_magic != OMAGIC) 17052132Smckusick return 0; 17152132Smckusick *loadAddr = aout.ex_aout.codeStart; 17252132Smckusick *execAddr = aout.a_entry; 17352132Smckusick *length = aout.a_text + aout.a_data; 17452132Smckusick if (lseek(bootFID, N_TXTOFF(aout), 0) < 0) { 17552132Smckusick perror(bootfname); 17652132Smckusick return 0; 17752132Smckusick } 17852868Sralph printf("Input file is COFF format\n"); 17952132Smckusick printf("load %x, start %x, len %d\n", *loadAddr, *execAddr, *length); 18052132Smckusick return 1; 18152132Smckusick } 182