xref: /original-bsd/sys/hp300/stand/mkboot.c (revision a6d8c59f)
1 /*
2  * Copyright (c) 1990 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)mkboot.c	7.4 (Berkeley) 10/11/92
8  */
9 
10 #ifndef lint
11 char copyright[] =
12 "@(#) Copyright (c) 1990 The Regents of the University of California.\n\
13  All rights reserved.\n";
14 #endif /* not lint */
15 
16 #ifndef lint
17 static char sccsid[] = "@(#)mkboot.c	7.2 (Berkeley) 12/16/90";
18 #endif /* not lint */
19 
20 #include <sys/param.h>
21 #include <sys/exec.h>
22 #include <sys/file.h>
23 
24 #include <hp300/stand/volhdr.h>
25 
26 #include <stdio.h>
27 #include <ctype.h>
28 
29 int lpflag;
30 int loadpoint;
31 struct load ld;
32 struct lifvol lifv;
33 struct lifdir lifd[8];
34 struct exec ex;
35 char buf[10240];
36 
37 main(argc, argv)
38 	char **argv;
39 {
40 	int ac;
41 	char **av;
42 	int from1, from2, to;
43 	register int n;
44 	char *n1, *n2, *lifname();
45 
46 	ac = --argc;
47 	av = ++argv;
48 	if (ac == 0)
49 		usage();
50 	if (!strcmp(av[0], "-l")) {
51 		av++;
52 		ac--;
53 		if (ac == 0)
54 			usage();
55 		sscanf(av[0], "0x%x", &loadpoint);
56 		lpflag++;
57 		av++;
58 		ac--;
59 	}
60 	if (ac == 0)
61 		usage();
62 	from1 = open(av[0], O_RDONLY, 0);
63 	if (from1 < 0) {
64 		perror("open");
65 		exit(1);
66 	}
67 	n1 = av[0];
68 	av++;
69 	ac--;
70 	if (ac == 0)
71 		usage();
72 	if (ac == 2) {
73 		from2 = open(av[0], O_RDONLY, 0);
74 		if (from2 < 0) {
75 			perror("open");
76 			exit(1);
77 		}
78 		n2 = av[0];
79 		av++;
80 		ac--;
81 	} else
82 		from2 = -1;
83 	to = open(av[0], O_WRONLY | O_TRUNC | O_CREAT, 0644);
84 	if (to < 0) {
85 		perror("open");
86 		exit(1);
87 	}
88 	/* clear possibly unused directory entries */
89 	strncpy(lifd[1].dir_name, "          ", 10);
90 	lifd[1].dir_type = -1;
91 	lifd[1].dir_addr = 0;
92 	lifd[1].dir_length = 0;
93 	lifd[1].dir_flag = 0xFF;
94 	lifd[1].dir_exec = 0;
95 	lifd[7] = lifd[6] = lifd[5] = lifd[4] = lifd[3] = lifd[2] = lifd[1];
96 	/* record volume info */
97 	lifv.vol_id = VOL_ID;
98 	strncpy(lifv.vol_label, "BOOT43", 6);
99 	lifv.vol_addr = 2;
100 	lifv.vol_oct = VOL_OCT;
101 	lifv.vol_dirsize = 1;
102 	lifv.vol_version = 1;
103 	/* output bootfile one */
104 	lseek(to, 3 * SECTSIZE, 0);
105 	putfile(from1, to);
106 	n = (ld.count + sizeof(ld) + (SECTSIZE - 1)) / SECTSIZE;
107 	strcpy(lifd[0].dir_name, lifname(n1));
108 	lifd[0].dir_type = DIR_TYPE;
109 	lifd[0].dir_addr = 3;
110 	lifd[0].dir_length = n;
111 	bcddate(from1, lifd[0].dir_toc);
112 	lifd[0].dir_flag = DIR_FLAG;
113 	lifd[0].dir_exec = lpflag? loadpoint + ex.a_entry : ex.a_entry;
114 	lifv.vol_length = lifd[0].dir_addr + lifd[0].dir_length;
115 	/* if there is an optional second boot program, output it */
116 	if (from2 >= 0) {
117 		lseek(to, (3 + n) * SECTSIZE, 0);
118 		putfile(from2, to);
119 		n = (ld.count + sizeof(ld) + (SECTSIZE - 1)) / SECTSIZE;
120 		strcpy(lifd[1].dir_name, lifname(n2));
121 		lifd[1].dir_type = DIR_TYPE;
122 		lifd[1].dir_addr = 3 + lifd[0].dir_length;
123 		lifd[1].dir_length = n;
124 		bcddate(from2, lifd[1].dir_toc);
125 		lifd[1].dir_flag = DIR_FLAG;
126 		lifd[1].dir_exec = lpflag? loadpoint + ex.a_entry : ex.a_entry;
127 		lifv.vol_length = lifd[1].dir_addr + lifd[1].dir_length;
128 	}
129 	/* output volume/directory header info */
130 	lseek(to, 0 * SECTSIZE, 0);
131 	write(to, &lifv, sizeof(lifv));
132 	lseek(to, 2 * SECTSIZE, 0);
133 	write(to, lifd, sizeof(lifd));
134 	exit(0);
135 }
136 
137 putfile(from, to)
138 {
139 	register int n, tcnt, dcnt;
140 
141 	n = read(from, &ex, sizeof(ex));
142 	if (n != sizeof(ex)) {
143 		fprintf(stderr, "error reading file header\n");
144 		exit(1);
145 	}
146 	if (ex.a_magic == OMAGIC) {
147 		tcnt = ex.a_text;
148 		dcnt = ex.a_data;
149 	}
150 	else if (ex.a_magic == NMAGIC) {
151 		tcnt = (ex.a_text + PGOFSET) & ~PGOFSET;
152 		dcnt = ex.a_data;
153 	}
154 	else {
155 		fprintf(stderr, "bad magic number\n");
156 		exit(1);
157 	}
158 	ld.address = lpflag ? loadpoint : ex.a_entry;
159 	ld.count = tcnt + dcnt;
160 	write(to, &ld, sizeof(ld));
161 	while (tcnt) {
162 		n = sizeof(buf);
163 		if (n > tcnt)
164 			n = tcnt;
165 		n = read(from, buf, n);
166 		if (n < 0) {
167 			perror("read");
168 			exit(1);
169 		}
170 		if (n == 0) {
171 			fprintf(stderr, "short read\n");
172 			exit(1);
173 		}
174 		if (write(to, buf, n) < 0) {
175 			perror("write");
176 			exit(1);
177 		}
178 		tcnt -= n;
179 	}
180 	while (dcnt) {
181 		n = sizeof(buf);
182 		if (n > dcnt)
183 			n = dcnt;
184 		n = read(from, buf, n);
185 		if (n < 0) {
186 			perror("read");
187 			exit(1);
188 		}
189 		if (n == 0) {
190 			fprintf(stderr, "short read\n");
191 			exit(1);
192 		}
193 		if (write(to, buf, n) < 0) {
194 			perror("write");
195 			exit(1);
196 		}
197 		dcnt -= n;
198 	}
199 }
200 
201 usage()
202 {
203 	fprintf(stderr,
204 		"usage:  mkboot [-l loadpoint] prog1 [ prog2 ] outfile\n");
205 	exit(1);
206 }
207 
208 char *
209 lifname(str)
210  char *str;
211 {
212 	static char lname[10] = "SYS_XXXXX";
213 	register int i;
214 
215 	for (i = 4; i < 9; i++) {
216 		if (islower(*str))
217 			lname[i] = toupper(*str);
218 		else if (isalnum(*str) || *str == '_')
219 			lname[i] = *str;
220 		else
221 			break;
222 		str++;
223 	}
224 	for ( ; i < 10; i++)
225 		lname[i] = '\0';
226 	return(lname);
227 }
228 
229 #include <sys/stat.h>
230 #include <time.h>	/* XXX */
231 
232 bcddate(fd, toc)
233 	int fd;
234 	char *toc;
235 {
236 	struct stat statb;
237 	struct tm *tm;
238 
239 	fstat(fd, &statb);
240 	tm = localtime(&statb.st_ctime);
241 	*toc = ((tm->tm_mon+1) / 10) << 4;
242 	*toc++ |= (tm->tm_mon+1) % 10;
243 	*toc = (tm->tm_mday / 10) << 4;
244 	*toc++ |= tm->tm_mday % 10;
245 	*toc = (tm->tm_year / 10) << 4;
246 	*toc++ |= tm->tm_year % 10;
247 	*toc = (tm->tm_hour / 10) << 4;
248 	*toc++ |= tm->tm_hour % 10;
249 	*toc = (tm->tm_min / 10) << 4;
250 	*toc++ |= tm->tm_min % 10;
251 	*toc = (tm->tm_sec / 10) << 4;
252 	*toc |= tm->tm_sec % 10;
253 }
254