1 /* 2 * Copyright (c) 1992 Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Ralph Campbell. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 char copyright[] = 13 "@(#) Copyright (c) 1992 Regents of the University of California.\n\ 14 All rights reserved.\n"; 15 #endif not lint 16 17 #ifndef lint 18 static char sccsid[] = "@(#)mkboot.c 7.2 (Berkeley) 03/07/92"; 19 #endif not lint 20 21 #include <stdio.h> 22 #include "sys/param.h" 23 #include "sys/exec.h" 24 #include "../dev/devDiskLabel.h" 25 26 /* this is the size of the standard ULTRIX boot */ 27 #define MAXBOOTSIZE (15 * DEV_BSIZE) 28 29 char block[DEV_BSIZE]; 30 char *dev, *bootfname; 31 32 /* 33 * installboot bootprog device 34 */ 35 main(argc, argv) 36 int argc; 37 char *argv[]; 38 { 39 register int i, n; 40 int ifd, ofd; 41 Dec_DiskBoot decBootInfo; 42 int nsectors; 43 long loadAddr; 44 long execAddr; 45 long length; 46 47 if (argc != 3) 48 usage(); 49 dev = argv[2]; 50 i = strlen(dev); 51 bootfname = argv[1]; 52 ifd = open(bootfname, 0, 0); 53 if (ifd < 0) { 54 perror(bootfname); 55 exit(1); 56 } 57 ofd = open(dev, 2, 0); 58 if (ofd < 0) { 59 deverr: 60 perror(dev); 61 exit(1); 62 } 63 64 /* 65 * Check for exec header and skip to code segment. 66 */ 67 if (!DecHeader(ifd, &loadAddr, &execAddr, &length)) { 68 fprintf(stderr, "Need impure text format (OMAGIC) file\n"); 69 exit(1); 70 } 71 if (length > MAXBOOTSIZE) { 72 fprintf(stderr, "boot program is too big (%d > %d)\n", 73 length, MAXBOOTSIZE); 74 exit(1); 75 } 76 77 /* 78 * Write the boot information block. 79 */ 80 decBootInfo.magic = DEC_BOOT_MAGIC; 81 decBootInfo.mode = 0; 82 decBootInfo.loadAddr = loadAddr; 83 decBootInfo.execAddr = execAddr; 84 decBootInfo.map[0].numBlocks = nsectors = 85 (length + DEV_BSIZE - 1) >> DEV_BSHIFT; 86 decBootInfo.map[0].startBlock = 1; 87 decBootInfo.map[1].numBlocks = 0; 88 if (lseek(ofd, (long)(DEC_BOOT_SECTOR * DEV_BSIZE), 0) < 0 || 89 write(ofd, (char *)&decBootInfo, sizeof(decBootInfo)) != 90 sizeof(decBootInfo)) { 91 perror(dev); 92 fprintf(stderr, "Sector write %d failed: ", DEC_BOOT_SECTOR); 93 exit(1); 94 } 95 if (lseek(ofd, (long)(1 * DEV_BSIZE), 0) < 0) 96 goto deverr; 97 98 /* 99 * Write the remaining code to the correct place on the disk. 100 */ 101 for (i = 0; i < nsectors && length > 0; i++) { 102 bzero(block, DEV_BSIZE); 103 n = length < DEV_BSIZE ? length : DEV_BSIZE; 104 if (read(ifd, block, n) != n) { 105 perror(bootfname); 106 break; 107 } 108 length -= n; 109 if (write(ofd, block, DEV_BSIZE) != DEV_BSIZE) { 110 perror(dev); 111 break; 112 } 113 } 114 printf("Wrote %d sectors\n", i); 115 if (length > 0) 116 printf("Warning: didn't reach end of boot program!\n"); 117 exit(0); 118 } 119 120 usage() 121 { 122 printf("Usage: installboot bootprog device\n"); 123 printf("where:\n"); 124 printf("\t\"bootprog\" is a -N format file < %d bytes long\n", 125 MAXBOOTSIZE); 126 printf("\t\"device\" should be the 'a' partition of a bootable disk\n"); 127 printf("WARNING!! If the 'c' partition contains a file system, %s\n", 128 "DON'T RUN THIS!!"); 129 exit(1); 130 } 131 132 /* 133 *---------------------------------------------------------------------- 134 * 135 * DecHeader - 136 * 137 * Check if the header is a DEC (COFF) file. 138 * 139 * Results: 140 * Return true if all went ok. 141 * 142 * Side effects: 143 * None. 144 * 145 *---------------------------------------------------------------------- 146 */ 147 DecHeader(bootFID, loadAddr, execAddr, length) 148 int bootFID; /* Handle on the boot program */ 149 long *loadAddr; /* Address to start loading boot program. */ 150 long *execAddr; /* Address to start executing boot program. */ 151 long *length; /* Length of the boot program. */ 152 { 153 struct exec aout; 154 int bytesRead; 155 156 if (lseek(bootFID, 0, 0) < 0) { 157 perror(bootfname); 158 return 0; 159 } 160 bytesRead = read(bootFID, (char *)&aout, sizeof(aout)); 161 if (bytesRead != sizeof(aout) || aout.ex_fhdr.magic != COFF_MAGIC || 162 aout.a_magic != OMAGIC) 163 return 0; 164 *loadAddr = aout.ex_aout.codeStart; 165 *execAddr = aout.a_entry; 166 *length = aout.a_text + aout.a_data; 167 if (lseek(bootFID, N_TXTOFF(aout), 0) < 0) { 168 perror(bootfname); 169 return 0; 170 } 171 printf("Input file is COFF format\n"); 172 printf("load %x, start %x, len %d\n", *loadAddr, *execAddr, *length); 173 return 1; 174 } 175