mkbootimage.c revision 1.4 1 /* $NetBSD: mkbootimage.c,v 1.4 2007/12/20 17:58:49 garbled Exp $ */
2
3 /*-
4 * Copyright (c) 2007 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Tim Rightnour and NONAKA Kimihiro
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #if HAVE_NBTOOL_CONFIG_H
40 #include "nbtool_config.h"
41 #include "../../sys/sys/bootblock.h"
42 #else
43 #include <sys/bootblock.h>
44 #endif
45
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <fcntl.h>
50 #include <unistd.h>
51 #include <errno.h>
52 #include <zlib.h>
53 #include <err.h>
54 #include <sys/stat.h>
55 #include <sys/types.h>
56 #include <sys/uio.h>
57
58 #ifdef __NetBSD__
59 #include <sys/sysctl.h>
60 #include <sys/utsname.h>
61 #endif
62
63 /* BFD ELF headers */
64 #include <elf/common.h>
65 #include <elf/external.h>
66
67 #include "rs6000_bootrec.h"
68 #include "byteorder.h"
69 #include "magic.h"
70
71 /* Globals */
72
73 int saloneflag = 0;
74 int verboseflag = 0;
75 int lfloppyflag = 0;
76 Elf32_External_Ehdr hdr, khdr;
77 struct stat elf_stat;
78 unsigned char mbr[512];
79
80 /* the boot and config records for rs6000 */
81 rs6000_boot_record_t bootrec;
82 rs6000_config_record_t confrec;
83
84 /* supported platforms */
85 char *sup_plats[] = {
86 "prep",
87 "rs6000",
88 NULL,
89 };
90
91 /*
92 * Macros to get values from multi-byte ELF header fields. These assume
93 * a big-endian image.
94 */
95 #define ELFGET16(x) (((x)[0] << 8) | (x)[1])
96
97 #define ELFGET32(x) (((x)[0] << 24) | ((x)[1] << 16) | \
98 ((x)[2] << 8) | (x)[3])
99
100 static void usage(int);
101 static int open_file(const char *, char *, Elf32_External_Ehdr *,
102 struct stat *);
103 static void check_mbr(int, char *);
104 static int prep_build_image(char *, char *, char *, char *);
105 static void rs6000_build_records(int);
106 static int rs6000_build_image(char *, char *, char *, char *);
107 int main(int, char **);
108
109 static void
110 usage(int extended)
111 {
112 int i;
113
114 if (extended) {
115 fprintf(stderr, "You are not running this program on"
116 " the target machine. You must supply the\n"
117 "machine architecture with the -m flag\n");
118 fprintf(stderr, "Supported architectures: ");
119 for (i=0; sup_plats[i] != NULL; i++)
120 fprintf(stderr, " %s", sup_plats[i]);
121 fprintf(stderr, "\n\n");
122 }
123 #ifdef __NetBSD__
124 fprintf(stderr, "usage: %s [-ls] [-m machine_arch] [-b bootfile] "
125 "[-k kernel] [-r rawdev] bootimage\n", getprogname());
126 #else
127 fprintf(stderr, "usage: %s [-ls] -m machine_arch [-b bootfile] "
128 "[-k kernel] [-r rawdev] bootimage\n", getprogname());
129 #endif
130 exit(1);
131 }
132
133 /* verify the file is ELF and ppc, and open it up */
134 static int
135 open_file(const char *ftype, char *file, Elf32_External_Ehdr *hdr,
136 struct stat *f_stat)
137 {
138 int fd;
139
140 if ((fd = open(file, 0)) < 0)
141 errx(2, "Can't open %s '%s': %s", ftype, file, strerror(errno));
142 fstat(fd, f_stat);
143
144 if (read(fd, hdr, sizeof(Elf32_External_Ehdr)) !=
145 sizeof(Elf32_External_Ehdr))
146 errx(3, "Can't read input '%s': %s", file, strerror(errno));
147
148 if (hdr->e_ident[EI_MAG0] != ELFMAG0 ||
149 hdr->e_ident[EI_MAG1] != ELFMAG1 ||
150 hdr->e_ident[EI_MAG2] != ELFMAG2 ||
151 hdr->e_ident[EI_MAG3] != ELFMAG3 ||
152 hdr->e_ident[EI_CLASS] != ELFCLASS32)
153 errx(3, "input '%s' is not ELF32 format", file);
154
155 if (hdr->e_ident[EI_DATA] != ELFDATA2MSB)
156 errx(3, "input '%s' is not big-endian", file);
157
158 if (ELFGET16(hdr->e_machine) != EM_PPC)
159 errx(3, "input '%s' is not PowerPC exec binary", file);
160
161 return(fd);
162 }
163
164 static void
165 prep_check_mbr(int prep_fd, char *rawdev)
166 {
167 int raw_fd;
168 unsigned long entry, length;
169 struct mbr_partition *mbrp;
170 struct stat raw_stat;
171
172 /* If we are building a standalone image, do not write an MBR, just
173 * set entry point and boot image size skipping over elf header
174 */
175 if (saloneflag) {
176 entry = sa_htole32(0x400);
177 length = sa_htole32(elf_stat.st_size - sizeof(hdr) + 0x400);
178 lseek(prep_fd, sizeof(mbr), SEEK_SET);
179 write(prep_fd, &entry, sizeof(entry));
180 write(prep_fd, &length, sizeof(length));
181 return;
182 }
183
184 /*
185 * if we have a raw device, we need to check to see if it already
186 * has a partition table, and if so, read it in and check for
187 * suitability.
188 */
189 if (rawdev != NULL) {
190 raw_fd = open(rawdev, O_RDONLY, 0);
191 if (raw_fd == -1)
192 errx(3, "couldn't open raw device %s: %s", rawdev,
193 strerror(errno));
194
195 fstat(raw_fd, &raw_stat);
196 if (!S_ISCHR(raw_stat.st_mode))
197 errx(3, "%s is not a raw device", rawdev);
198
199 if (read(raw_fd, mbr, 512) != 512)
200 errx(3, "MBR Read Failed: %s", strerror(errno));
201
202 mbrp = (struct mbr_partition *)&mbr[MBR_PART_OFFSET];
203 if (mbrp->mbrp_type != MBR_PTYPE_PREP)
204 errx(3, "First partition is not of type 0x%x.",
205 MBR_PTYPE_PREP);
206 if (mbrp->mbrp_start != 0)
207 errx(3, "Use of the raw device is intended for"
208 " upgrading of legacy installations. Your"
209 " install does not have a PReP boot partition"
210 " starting at sector 0. Use the -s option"
211 " to build an image instead.");
212
213 /* if we got this far, we are fine, write back the partition
214 * and write the entry points and get outta here */
215 /* Set entry point and boot image size skipping over elf header */
216 lseek(prep_fd, 0, SEEK_SET);
217 entry = sa_htole32(0x400);
218 length = sa_htole32(elf_stat.st_size - sizeof(hdr) + 0x400);
219 write(prep_fd, mbr, sizeof(mbr));
220 write(prep_fd, &entry, sizeof(entry));
221 write(prep_fd, &length, sizeof(length));
222 close(raw_fd);
223 return;
224 }
225
226 /* if we get to here, we want to build a standard floppy or netboot
227 * image to file, so just build it */
228
229 memset(mbr, 0, sizeof(mbr));
230 mbrp = (struct mbr_partition *)&mbr[MBR_PART_OFFSET];
231
232 /* Set entry point and boot image size skipping over elf header */
233 entry = sa_htole32(0x400);
234 length = sa_htole32(elf_stat.st_size - sizeof(hdr) + 0x400);
235
236 /*
237 * Set magic number for msdos partition
238 */
239 *(unsigned short *)&mbr[MBR_MAGIC_OFFSET] = sa_htole16(MBR_MAGIC);
240
241 /*
242 * Build a "PReP" partition table entry in the boot record
243 * - "PReP" may only look at the system_indicator
244 */
245 mbrp->mbrp_flag = MBR_PFLAG_ACTIVE;
246 mbrp->mbrp_type = MBR_PTYPE_PREP;
247
248 /*
249 * The first block of the diskette is used by this "boot record" which
250 * actually contains the partition table. (The first block of the
251 * partition contains the boot image, but I digress...) We'll set up
252 * one partition on the diskette and it shall contain the rest of the
253 * diskette.
254 */
255 mbrp->mbrp_shd = 0; /* zero-based */
256 mbrp->mbrp_ssect = 2; /* one-based */
257 mbrp->mbrp_scyl = 0; /* zero-based */
258 mbrp->mbrp_ehd = 1; /* assumes two heads */
259 if (lfloppyflag)
260 mbrp->mbrp_esect = 36; /* 2.88MB floppy */
261 else
262 mbrp->mbrp_esect = 18; /* assumes 18 sectors/track */
263 mbrp->mbrp_ecyl = 79; /* assumes 80 cylinders/diskette */
264
265 /*
266 * The "PReP" software ignores the above fields and just looks at
267 * the next two.
268 * - size of the diskette is (assumed to be)
269 * (2 tracks/cylinder)(18 sectors/tracks)(80 cylinders/diskette)
270 * - unlike the above sector numbers,
271 * the beginning sector is zero-based!
272 */
273
274 /* This has to be 0 on the PowerStack? */
275 mbrp->mbrp_start = sa_htole32(0);
276 mbrp->mbrp_size = sa_htole32(2 * 18 * 80 - 1);
277
278 write(prep_fd, mbr, sizeof(mbr));
279 write(prep_fd, &entry, sizeof(entry));
280 write(prep_fd, &length, sizeof(length));
281 }
282
283 static int
284 prep_build_image(char *kernel, char *boot, char *rawdev, char *outname)
285 {
286 unsigned char *elf_img = NULL, *kern_img = NULL;
287 int i, ch, tmp, kgzlen, err;
288 int elf_fd, prep_fd, kern_fd, elf_img_len = 0;
289 off_t lenpos, kstart, kend;
290 unsigned long length;
291 long flength;
292 gzFile gzf;
293 struct stat kern_stat;
294 Elf32_External_Phdr phdr;
295
296 elf_fd = open_file("bootloader", boot, &hdr, &elf_stat);
297 kern_fd = open_file("kernel", kernel, &khdr, &kern_stat);
298 kern_len = kern_stat.st_size + PREP_MAGICSIZE + KERNLENSIZE;
299
300 for (i = 0; i < ELFGET16(hdr.e_phnum); i++) {
301 lseek(elf_fd, ELFGET32(hdr.e_phoff) + sizeof(phdr) * i,
302 SEEK_SET);
303 if (read(elf_fd, &phdr, sizeof(phdr)) != sizeof(phdr))
304 errx(3, "Can't read input '%s' phdr : %s", boot,
305 strerror(errno));
306
307 if ((ELFGET32(phdr.p_type) != PT_LOAD) ||
308 !(ELFGET32(phdr.p_flags) & PF_X))
309 continue;
310
311 fstat(elf_fd, &elf_stat);
312 elf_img_len = elf_stat.st_size - ELFGET32(phdr.p_offset);
313 lseek(elf_fd, ELFGET32(phdr.p_offset), SEEK_SET);
314
315 break;
316 }
317 if ((prep_fd = open(outname, O_RDWR|O_TRUNC, 0)) < 0) {
318 /* we couldn't open it, it must be new */
319 prep_fd = creat(outname, 0644);
320 if (prep_fd < 0)
321 errx(2, "Can't open output '%s': %s", outname,
322 strerror(errno));
323 }
324
325 prep_check_mbr(prep_fd, rawdev);
326
327 /* Set file pos. to 2nd sector where image will be written */
328 lseek(prep_fd, 0x400, SEEK_SET);
329
330 /* Copy boot image */
331 elf_img = (unsigned char *)malloc(elf_img_len);
332 if (!elf_img)
333 errx(3, "Can't malloc: %s", strerror(errno));
334 if (read(elf_fd, elf_img, elf_img_len) != elf_img_len)
335 errx(3, "Can't read file '%s' : %s", boot, strerror(errno));
336
337 write(prep_fd, elf_img, elf_img_len);
338 free(elf_img);
339
340 /* Copy kernel */
341 kern_img = (unsigned char *)malloc(kern_stat.st_size);
342
343 if (kern_img == NULL)
344 errx(3, "Can't malloc: %s", strerror(errno));
345
346 /* we need to jump back after having read the headers */
347 lseek(kern_fd, 0, SEEK_SET);
348 if (read(kern_fd, (void *)kern_img, kern_stat.st_size) !=
349 kern_stat.st_size)
350 errx(3, "Can't read kernel '%s' : %s", kernel, strerror(errno));
351
352 gzf = gzdopen(dup(prep_fd), "a");
353 if (gzf == NULL)
354 errx(3, "Can't init compression: %s", strerror(errno));
355 if (gzsetparams(gzf, Z_BEST_COMPRESSION, Z_DEFAULT_STRATEGY) != Z_OK)
356 errx(3, "%s", gzerror(gzf, &err));
357
358 /* write a magic number and size before the kernel */
359 write(prep_fd, (void *)prep_magic, PREP_MAGICSIZE);
360 lenpos = lseek(prep_fd, 0, SEEK_CUR);
361 tmp = sa_htobe32(0);
362 write(prep_fd, (void *)&tmp, KERNLENSIZE);
363
364 /* write in the compressed kernel */
365 kstart = lseek(prep_fd, 0, SEEK_CUR);
366 kgzlen = gzwrite(gzf, kern_img, kern_stat.st_size);
367 gzclose(gzf);
368 kend = lseek(prep_fd, 0, SEEK_CUR);
369
370 /* jump back to the length position now that we know the length */
371 lseek(prep_fd, lenpos, SEEK_SET);
372 kgzlen = kend - kstart;
373 tmp = sa_htobe32(kgzlen);
374 write(prep_fd, (void *)&tmp, KERNLENSIZE);
375
376 length = sa_htole32(0x400 + elf_img_len + 8 + kgzlen);
377 lseek(prep_fd, sizeof(mbr) + 4, SEEK_SET);
378 write(prep_fd, &length, sizeof(length));
379
380 flength = 0x400 + elf_img_len + 8 + kgzlen;
381 if (lfloppyflag)
382 flength -= (5760 * 512);
383 else
384 flength -= (2880 * 512);
385 if (flength > 0 && !saloneflag)
386 fprintf(stderr, "%s: Image %s is %d bytes larger than single"
387 " floppy. Can only be used for netboot.\n", getprogname(),
388 outname, flength);
389
390 free(kern_img);
391 close(kern_fd);
392 close(prep_fd);
393 close(elf_fd);
394
395 return 0;
396 }
397
398 /* Fill in the needed information on the boot and config records. Most of
399 * this is just AIX garbage that we don't really need to boot.
400 */
401 static void
402 rs6000_build_records(int img_len)
403 {
404 int bcl;
405
406 /* zero out all the fields, so we only have to set the ones
407 * we care about, which are rather few.
408 */
409 memset(&bootrec, 0, sizeof(rs6000_boot_record_t));
410 memset(&confrec, 0, sizeof(rs6000_config_record_t));
411
412 bootrec.ipl_record = IPLRECID;
413 bcl = img_len/512;
414 if (img_len%512 != 0)
415 bcl++;
416 bootrec.bootcode_len = bcl;
417 bootrec.bootcode_off = 0; /* XXX */
418 bootrec.bootpart_start = 2; /* skip bootrec and confrec */
419 bootrec.bootprg_start = 2;
420 bootrec.bootpart_len = bcl;
421 bootrec.boot_load_addr = 0x800000; /* XXX? */
422 bootrec.boot_frag = 1;
423 bootrec.boot_emul = 0x02; /* ?? */
424 /* service mode is a repeat of normal mode */
425 bootrec.servcode_len = bootrec.bootcode_len;
426 bootrec.servcode_off = bootrec.bootcode_off;
427 bootrec.servpart_start = bootrec.bootpart_start;
428 bootrec.servprg_start = bootrec.bootprg_start;
429 bootrec.servpart_len = bootrec.bootpart_len;
430 bootrec.serv_load_addr = bootrec.boot_load_addr;
431 bootrec.serv_frag = bootrec.boot_frag;
432 bootrec.serv_emul = bootrec.boot_emul;
433
434 /* now the config record */
435 confrec.conf_rec = CONFRECID;
436 confrec.sector_size = 0x02; /* 512 bytes */
437 confrec.last_cyl = 0x4f; /* 79 cyl, emulates floppy */
438 }
439
440 static int
441 rs6000_build_image(char *kernel, char *boot, char *rawdev, char *outname)
442 {
443 unsigned char *elf_img = NULL, *kern_img = NULL;
444 int i, ch, tmp, kgzlen, err;
445 int elf_fd, rs6000_fd, kern_fd, elf_img_len = 0, elf_pad;
446 uint32_t swapped[128];
447 off_t lenpos, kstart, kend;
448 unsigned long length;
449 long flength;
450 gzFile gzf;
451 struct stat kern_stat;
452 Elf32_External_Phdr phdr;
453
454 elf_fd = open_file("bootloader", boot, &hdr, &elf_stat);
455 kern_fd = open_file("kernel", kernel, &khdr, &kern_stat);
456 kern_len = kern_stat.st_size + RS6000_MAGICSIZE + KERNLENSIZE;
457
458 for (i = 0; i < ELFGET16(hdr.e_phnum); i++) {
459 lseek(elf_fd, ELFGET32(hdr.e_phoff) + sizeof(phdr) * i,
460 SEEK_SET);
461 if (read(elf_fd, &phdr, sizeof(phdr)) != sizeof(phdr))
462 errx(3, "Can't read input '%s' phdr : %s", boot,
463 strerror(errno));
464
465 if ((ELFGET32(phdr.p_type) != PT_LOAD) ||
466 !(ELFGET32(phdr.p_flags) & PF_X))
467 continue;
468
469 fstat(elf_fd, &elf_stat);
470 elf_img_len = elf_stat.st_size - ELFGET32(phdr.p_offset);
471 elf_pad = ELFGET32(phdr.p_memsz) - ELFGET32(phdr.p_filesz);
472 if (verboseflag)
473 printf("Padding %d\n", elf_pad);
474 lseek(elf_fd, ELFGET32(phdr.p_offset), SEEK_SET);
475
476 break;
477 }
478 if ((rs6000_fd = open(outname, O_RDWR|O_TRUNC, 0)) < 0) {
479 /* we couldn't open it, it must be new */
480 rs6000_fd = creat(outname, 0644);
481 if (rs6000_fd < 0)
482 errx(2, "Can't open output '%s': %s", outname,
483 strerror(errno));
484 }
485
486 /* Set file pos. to 2nd sector where image will be written */
487 lseek(rs6000_fd, 0x400, SEEK_SET);
488
489 /* Copy boot image */
490 elf_img = (unsigned char *)malloc(elf_img_len);
491 if (!elf_img)
492 errx(3, "Can't malloc: %s", strerror(errno));
493 if (read(elf_fd, elf_img, elf_img_len) != elf_img_len)
494 errx(3, "Can't read file '%s' : %s", boot, strerror(errno));
495
496 write(rs6000_fd, elf_img, elf_img_len);
497 free(elf_img);
498
499 /* now dump in the padding space for the BSS */
500 elf_pad += 100; /* just a little extra for good luck */
501 lseek(rs6000_fd, elf_pad, SEEK_CUR);
502
503 /* Copy kernel */
504 kern_img = (unsigned char *)malloc(kern_stat.st_size);
505
506 if (kern_img == NULL)
507 errx(3, "Can't malloc: %s", strerror(errno));
508
509 /* we need to jump back after having read the headers */
510 lseek(kern_fd, 0, SEEK_SET);
511 if (read(kern_fd, (void *)kern_img, kern_stat.st_size) !=
512 kern_stat.st_size)
513 errx(3, "Can't read kernel '%s' : %s", kernel, strerror(errno));
514
515 gzf = gzdopen(dup(rs6000_fd), "a");
516 if (gzf == NULL)
517 errx(3, "Can't init compression: %s", strerror(errno));
518 if (gzsetparams(gzf, Z_BEST_COMPRESSION, Z_DEFAULT_STRATEGY) != Z_OK)
519 errx(3, "%s", gzerror(gzf, &err));
520
521 /* write a magic number and size before the kernel */
522 write(rs6000_fd, (void *)rs6000_magic, RS6000_MAGICSIZE);
523 lenpos = lseek(rs6000_fd, 0, SEEK_CUR);
524 if (verboseflag)
525 printf("wrote magic at pos 0x%x\n", lenpos);
526 tmp = sa_htobe32(0);
527 write(rs6000_fd, (void *)&tmp, KERNLENSIZE);
528
529 /* write in the compressed kernel */
530 kstart = lseek(rs6000_fd, 0, SEEK_CUR);
531 if (verboseflag)
532 printf("kernel start at pos 0x%x\n", kstart);
533 kgzlen = gzwrite(gzf, kern_img, kern_stat.st_size);
534 gzclose(gzf);
535 kend = lseek(rs6000_fd, 0, SEEK_CUR);
536 if (verboseflag)
537 printf("kernel end at pos 0x%x\n", kend);
538
539 /* jump back to the length position now that we know the length */
540 lseek(rs6000_fd, lenpos, SEEK_SET);
541 kgzlen = kend - kstart;
542 tmp = sa_htobe32(kgzlen);
543 if (verboseflag)
544 printf("kernel len = 0x%x tmp = 0x%x\n", kgzlen, tmp);
545 write(rs6000_fd, (void *)&tmp, KERNLENSIZE);
546
547 #if 0
548 lseek(rs6000_fd, sizeof(boot_record_t) + sizeof(config_record_t),
549 SEEK_SET);
550 /* set entry and length */
551 length = sa_htole32(0x400);
552 write(rs6000_fd, &length, sizeof(length));
553 length = sa_htole32(0x400 + elf_img_len + 8 + kgzlen);
554 write(rs6000_fd, &length, sizeof(length));
555 #endif
556
557 /* generate the header now that we know the kernel length */
558 if (verboseflag)
559 printf("building records\n");
560 rs6000_build_records(elf_img_len + 8 + kgzlen);
561 lseek(rs6000_fd, 0, SEEK_SET);
562 /* ROM wants it byteswapped in 32bit chunks */
563 if (verboseflag)
564 printf("writing records\n");
565 memcpy(swapped, &bootrec, sizeof(rs6000_boot_record_t));
566 for (i=0; i < 128; i++)
567 swapped[i] = htonl(swapped[i]);
568 write(rs6000_fd, swapped, sizeof(rs6000_boot_record_t));
569 memcpy(swapped, &confrec, sizeof(rs6000_config_record_t));
570 for (i=0; i < 128; i++)
571 swapped[i] = htonl(swapped[i]);
572 write(rs6000_fd, swapped, sizeof(rs6000_config_record_t));
573
574 free(kern_img);
575 close(kern_fd);
576 close(rs6000_fd);
577 close(elf_fd);
578
579 return 0;
580 }
581
582 int
583 main(int argc, char **argv)
584 {
585 int ch, lfloppyflag=0;
586 char *kernel = NULL, *boot = NULL, *rawdev = NULL, *outname = NULL;
587 char *march = NULL;
588 #ifdef __NetBSD__
589 char machine_arch[SYS_NMLN];
590 int mib[2] = { CTL_HW, HW_MACHINE_ARCH };
591 #endif
592
593 setprogname(argv[0]);
594 kern_len = 0;
595
596 while ((ch = getopt(argc, argv, "b:k:lm:r:sv")) != -1)
597 switch (ch) {
598 case 'b':
599 boot = optarg;
600 break;
601 case 'k':
602 kernel = optarg;
603 break;
604 case 'l':
605 lfloppyflag = 1;
606 break;
607 case 'm':
608 march = optarg;
609 break;
610 case 'r':
611 rawdev = optarg;
612 break;
613 case 's':
614 saloneflag = 1;
615 break;
616 case 'v':
617 verboseflag = 1;
618 break;
619 case '?':
620 default:
621 usage(0);
622 /* NOTREACHED */
623 }
624 argc -= optind;
625 argv += optind;
626
627 if (argc < 1)
628 usage(0);
629
630 if (kernel == NULL)
631 kernel = "/netbsd";
632
633 if (boot == NULL)
634 boot = "/usr/mdec/boot";
635
636 if (strcmp(march, "") == 0)
637 march = NULL;
638 if (march == NULL) {
639 int i;
640 #ifdef __NetBSD__
641 size_t len = sizeof(machine_arch);
642
643 if (sysctl(mib, sizeof (mib) / sizeof (mib[0]), machine_arch,
644 &len, NULL, 0) != -1) {
645 for (i=0; sup_plats[i] != NULL; i++) {
646 if (strcmp(sup_plats[i], machine_arch) == 0) {
647 march = strdup(sup_plats[i]);
648 break;
649 }
650 }
651 }
652 if (march == NULL)
653 #endif
654 usage(1);
655 }
656
657 outname = argv[0];
658
659 if (strcmp(march, "prep") == 0)
660 return(prep_build_image(kernel, boot, rawdev, outname));
661 if (strcmp(march, "rs6000") == 0)
662 return(rs6000_build_image(kernel, boot, rawdev, outname));
663
664 usage(1);
665 return(0);
666 }
667