xref: /original-bsd/sys/pmax/stand/mkboot.c (revision 753853ba)
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