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