1 /* $NetBSD: mkbootimage.c,v 1.10 2008/05/24 17:34:03 kiyohara Exp $ */
4 * Copyright (c) 2007 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Tim Rightnour and NONAKA Kimihiro
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #if HAVE_NBTOOL_CONFIG_H
33 #include "nbtool_config.h"
34 #include "../../sys/sys/bootblock.h"
36 #include <sys/bootblock.h>
48 #include <sys/types.h>
50 #include <sys/signal.h>
54 #if defined(__NetBSD__) && !defined(HAVE_NBTOOL_CONFIG_H)
56 #include <sys/param.h>
57 #include <sys/sysctl.h>
58 #include <sys/utsname.h>
62 #include <elf/common.h>
63 #include <elf/external.h>
65 #include "bebox_bootrec.h"
66 #include "byteorder.h"
69 #include "rs6000_bootrec.h"
76 Elf32_External_Ehdr hdr
, khdr
;
78 unsigned char mbr
[512];
80 /* the boot and config records for rs6000 */
81 rs6000_boot_record_t bootrec
;
82 rs6000_config_record_t confrec
;
84 /* supported platforms */
93 * Macros to get values from multi-byte ELF header fields. These assume
96 #define ELFGET16(x) (((x)[0] << 8) | (x)[1])
98 #define ELFGET32(x) (((x)[0] << 24) | ((x)[1] << 16) | \
99 ((x)[2] << 8) | (x)[3])
101 #define ULALIGN(x) ((x + 0x0f) & 0xfffffff0)
103 static void usage(int);
104 static int open_file(const char *, char *, Elf32_External_Ehdr
*,
106 static void check_mbr(int, char *);
107 static int prep_build_image(char *, char *, char *, char *);
108 static void rs6000_build_records(int);
109 static int rs6000_build_image(char *, char *, char *, char *);
110 int main(int, char **);
119 fprintf(stderr
, "You are not running this program on"
120 " the target machine. You must supply the\n"
121 "machine architecture with the -m flag\n");
122 fprintf(stderr
, "Supported architectures: ");
123 for (i
=0; sup_plats
[i
] != NULL
; i
++)
124 fprintf(stderr
, " %s", sup_plats
[i
]);
125 fprintf(stderr
, "\n\n");
128 fprintf(stderr
, "usage: %s [-lsv] [-m machine] [-b bootfile] "
129 "[-k kernel] [-r rawdev] bootimage\n", getprogname());
131 fprintf(stderr
, "usage: %s [-lsv] -m machine [-b bootfile] "
132 "[-k kernel] [-r rawdev] bootimage\n", getprogname());
137 /* verify the file is ELF and ppc, and open it up */
139 open_file(const char *ftype
, char *file
, Elf32_External_Ehdr
*hdr
,
144 if ((fd
= open(file
, 0)) < 0)
145 errx(2, "Can't open %s '%s': %s", ftype
, file
, strerror(errno
));
148 if (read(fd
, hdr
, sizeof(Elf32_External_Ehdr
)) !=
149 sizeof(Elf32_External_Ehdr
))
150 errx(3, "Can't read input '%s': %s", file
, strerror(errno
));
152 if (hdr
->e_ident
[EI_MAG0
] != ELFMAG0
||
153 hdr
->e_ident
[EI_MAG1
] != ELFMAG1
||
154 hdr
->e_ident
[EI_MAG2
] != ELFMAG2
||
155 hdr
->e_ident
[EI_MAG3
] != ELFMAG3
||
156 hdr
->e_ident
[EI_CLASS
] != ELFCLASS32
)
157 errx(3, "input '%s' is not ELF32 format", file
);
159 if (hdr
->e_ident
[EI_DATA
] != ELFDATA2MSB
)
160 errx(3, "input '%s' is not big-endian", file
);
162 if (ELFGET16(hdr
->e_machine
) != EM_PPC
)
163 errx(3, "input '%s' is not PowerPC exec binary", file
);
169 prep_check_mbr(int prep_fd
, char *rawdev
)
172 unsigned long entry
, length
;
173 struct mbr_partition
*mbrp
;
174 struct stat raw_stat
;
176 /* If we are building a standalone image, do not write an MBR, just
177 * set entry point and boot image size skipping over elf header
180 entry
= sa_htole32(0x400);
181 length
= sa_htole32(elf_stat
.st_size
- sizeof(hdr
) + 0x400);
182 lseek(prep_fd
, sizeof(mbr
), SEEK_SET
);
183 write(prep_fd
, &entry
, sizeof(entry
));
184 write(prep_fd
, &length
, sizeof(length
));
189 * if we have a raw device, we need to check to see if it already
190 * has a partition table, and if so, read it in and check for
193 if (rawdev
!= NULL
) {
194 raw_fd
= open(rawdev
, O_RDONLY
, 0);
196 errx(3, "couldn't open raw device %s: %s", rawdev
,
199 fstat(raw_fd
, &raw_stat
);
200 if (!S_ISCHR(raw_stat
.st_mode
))
201 errx(3, "%s is not a raw device", rawdev
);
203 if (read(raw_fd
, mbr
, 512) != 512)
204 errx(3, "MBR Read Failed: %s", strerror(errno
));
206 mbrp
= (struct mbr_partition
*)&mbr
[MBR_PART_OFFSET
];
207 if (mbrp
->mbrp_type
!= MBR_PTYPE_PREP
)
208 errx(3, "First partition is not of type 0x%x.",
210 if (mbrp
->mbrp_start
!= 0)
211 errx(3, "Use of the raw device is intended for"
212 " upgrading of legacy installations. Your"
213 " install does not have a PReP boot partition"
214 " starting at sector 0. Use the -s option"
215 " to build an image instead.");
217 /* if we got this far, we are fine, write back the partition
218 * and write the entry points and get outta here */
219 /* Set entry point and boot image size skipping over elf header */
220 lseek(prep_fd
, 0, SEEK_SET
);
221 entry
= sa_htole32(0x400);
222 length
= sa_htole32(elf_stat
.st_size
- sizeof(hdr
) + 0x400);
223 write(prep_fd
, mbr
, sizeof(mbr
));
224 write(prep_fd
, &entry
, sizeof(entry
));
225 write(prep_fd
, &length
, sizeof(length
));
230 /* if we get to here, we want to build a standard floppy or netboot
231 * image to file, so just build it */
233 memset(mbr
, 0, sizeof(mbr
));
234 mbrp
= (struct mbr_partition
*)&mbr
[MBR_PART_OFFSET
];
236 /* Set entry point and boot image size skipping over elf header */
237 entry
= sa_htole32(0x400);
238 length
= sa_htole32(elf_stat
.st_size
- sizeof(hdr
) + 0x400);
241 * Set magic number for msdos partition
243 *(unsigned short *)&mbr
[MBR_MAGIC_OFFSET
] = sa_htole16(MBR_MAGIC
);
246 * Build a "PReP" partition table entry in the boot record
247 * - "PReP" may only look at the system_indicator
249 mbrp
->mbrp_flag
= MBR_PFLAG_ACTIVE
;
250 mbrp
->mbrp_type
= MBR_PTYPE_PREP
;
253 * The first block of the diskette is used by this "boot record" which
254 * actually contains the partition table. (The first block of the
255 * partition contains the boot image, but I digress...) We'll set up
256 * one partition on the diskette and it shall contain the rest of the
259 mbrp
->mbrp_shd
= 0; /* zero-based */
260 mbrp
->mbrp_ssect
= 2; /* one-based */
261 mbrp
->mbrp_scyl
= 0; /* zero-based */
262 mbrp
->mbrp_ehd
= 1; /* assumes two heads */
264 mbrp
->mbrp_esect
= 36; /* 2.88MB floppy */
266 mbrp
->mbrp_esect
= 18; /* assumes 18 sectors/track */
267 mbrp
->mbrp_ecyl
= 79; /* assumes 80 cylinders/diskette */
270 * The "PReP" software ignores the above fields and just looks at
272 * - size of the diskette is (assumed to be)
273 * (2 tracks/cylinder)(18 sectors/tracks)(80 cylinders/diskette)
274 * - unlike the above sector numbers,
275 * the beginning sector is zero-based!
278 /* This has to be 0 on the PowerStack? */
279 mbrp
->mbrp_start
= sa_htole32(0);
280 mbrp
->mbrp_size
= sa_htole32(2 * 18 * 80 - 1);
282 write(prep_fd
, mbr
, sizeof(mbr
));
283 write(prep_fd
, &entry
, sizeof(entry
));
284 write(prep_fd
, &length
, sizeof(length
));
288 prep_build_image(char *kernel
, char *boot
, char *rawdev
, char *outname
)
290 unsigned char *elf_img
= NULL
, *kern_img
= NULL
;
291 int i
, ch
, tmp
, kgzlen
, err
;
292 int elf_fd
, prep_fd
, kern_fd
, elf_img_len
= 0;
293 off_t lenpos
, kstart
, kend
;
294 unsigned long length
;
297 struct stat kern_stat
;
298 Elf32_External_Phdr phdr
;
300 elf_fd
= open_file("bootloader", boot
, &hdr
, &elf_stat
);
301 kern_fd
= open_file("kernel", kernel
, &khdr
, &kern_stat
);
302 kern_len
= kern_stat
.st_size
+ PREP_MAGICSIZE
+ KERNLENSIZE
;
304 for (i
= 0; i
< ELFGET16(hdr
.e_phnum
); i
++) {
305 lseek(elf_fd
, ELFGET32(hdr
.e_phoff
) + sizeof(phdr
) * i
,
307 if (read(elf_fd
, &phdr
, sizeof(phdr
)) != sizeof(phdr
))
308 errx(3, "Can't read input '%s' phdr : %s", boot
,
311 if ((ELFGET32(phdr
.p_type
) != PT_LOAD
) ||
312 !(ELFGET32(phdr
.p_flags
) & PF_X
))
315 fstat(elf_fd
, &elf_stat
);
316 elf_img_len
= elf_stat
.st_size
- ELFGET32(phdr
.p_offset
);
317 lseek(elf_fd
, ELFGET32(phdr
.p_offset
), SEEK_SET
);
321 if ((prep_fd
= open(outname
, O_RDWR
|O_TRUNC
, 0)) < 0) {
322 /* we couldn't open it, it must be new */
323 prep_fd
= creat(outname
, 0644);
325 errx(2, "Can't open output '%s': %s", outname
,
329 prep_check_mbr(prep_fd
, rawdev
);
331 /* Set file pos. to 2nd sector where image will be written */
332 lseek(prep_fd
, 0x400, SEEK_SET
);
334 /* Copy boot image */
335 elf_img
= (unsigned char *)malloc(elf_img_len
);
337 errx(3, "Can't malloc: %s", strerror(errno
));
338 if (read(elf_fd
, elf_img
, elf_img_len
) != elf_img_len
)
339 errx(3, "Can't read file '%s' : %s", boot
, strerror(errno
));
341 write(prep_fd
, elf_img
, elf_img_len
);
345 kern_img
= (unsigned char *)malloc(kern_stat
.st_size
);
347 if (kern_img
== NULL
)
348 errx(3, "Can't malloc: %s", strerror(errno
));
350 /* we need to jump back after having read the headers */
351 lseek(kern_fd
, 0, SEEK_SET
);
352 if (read(kern_fd
, (void *)kern_img
, kern_stat
.st_size
) !=
354 errx(3, "Can't read kernel '%s' : %s", kernel
, strerror(errno
));
356 gzf
= gzdopen(dup(prep_fd
), "a");
358 errx(3, "Can't init compression: %s", strerror(errno
));
359 if (gzsetparams(gzf
, Z_BEST_COMPRESSION
, Z_DEFAULT_STRATEGY
) != Z_OK
)
360 errx(3, "%s", gzerror(gzf
, &err
));
362 /* write a magic number and size before the kernel */
363 write(prep_fd
, (void *)prep_magic
, PREP_MAGICSIZE
);
364 lenpos
= lseek(prep_fd
, 0, SEEK_CUR
);
366 write(prep_fd
, (void *)&tmp
, KERNLENSIZE
);
368 /* write in the compressed kernel */
369 kstart
= lseek(prep_fd
, 0, SEEK_CUR
);
370 kgzlen
= gzwrite(gzf
, kern_img
, kern_stat
.st_size
);
372 kend
= lseek(prep_fd
, 0, SEEK_CUR
);
374 /* jump back to the length position now that we know the length */
375 lseek(prep_fd
, lenpos
, SEEK_SET
);
376 kgzlen
= kend
- kstart
;
377 tmp
= sa_htobe32(kgzlen
);
378 write(prep_fd
, (void *)&tmp
, KERNLENSIZE
);
380 length
= sa_htole32(0x400 + elf_img_len
+ 8 + kgzlen
);
381 lseek(prep_fd
, sizeof(mbr
) + 4, SEEK_SET
);
382 write(prep_fd
, &length
, sizeof(length
));
384 flength
= 0x400 + elf_img_len
+ 8 + kgzlen
;
386 flength
-= (5760 * 512);
388 flength
-= (2880 * 512);
389 if (flength
> 0 && !saloneflag
)
390 fprintf(stderr
, "%s: Image %s is %d bytes larger than single"
391 " floppy. Can only be used for netboot.\n", getprogname(),
402 /* Fill in the needed information on the boot and config records. Most of
403 * this is just AIX garbage that we don't really need to boot.
406 rs6000_build_records(int img_len
)
410 /* zero out all the fields, so we only have to set the ones
411 * we care about, which are rather few.
413 memset(&bootrec
, 0, sizeof(rs6000_boot_record_t
));
414 memset(&confrec
, 0, sizeof(rs6000_config_record_t
));
416 bootrec
.ipl_record
= IPLRECID
;
418 if (img_len
%512 != 0)
420 bootrec
.bootcode_len
= bcl
;
421 bootrec
.bootcode_off
= 0; /* XXX */
422 bootrec
.bootpart_start
= 2; /* skip bootrec and confrec */
423 bootrec
.bootprg_start
= 2;
424 bootrec
.bootpart_len
= bcl
;
425 bootrec
.boot_load_addr
= 0x800000; /* XXX? */
426 bootrec
.boot_frag
= 1;
427 bootrec
.boot_emul
= 0x02; /* ?? */
428 /* service mode is a repeat of normal mode */
429 bootrec
.servcode_len
= bootrec
.bootcode_len
;
430 bootrec
.servcode_off
= bootrec
.bootcode_off
;
431 bootrec
.servpart_start
= bootrec
.bootpart_start
;
432 bootrec
.servprg_start
= bootrec
.bootprg_start
;
433 bootrec
.servpart_len
= bootrec
.bootpart_len
;
434 bootrec
.serv_load_addr
= bootrec
.boot_load_addr
;
435 bootrec
.serv_frag
= bootrec
.boot_frag
;
436 bootrec
.serv_emul
= bootrec
.boot_emul
;
438 /* now the config record */
439 confrec
.conf_rec
= CONFRECID
;
440 confrec
.sector_size
= 0x02; /* 512 bytes */
441 confrec
.last_cyl
= 0x4f; /* 79 cyl, emulates floppy */
445 rs6000_build_image(char *kernel
, char *boot
, char *rawdev
, char *outname
)
447 unsigned char *elf_img
= NULL
, *kern_img
= NULL
;
448 int i
, ch
, tmp
, kgzlen
, err
;
449 int elf_fd
, rs6000_fd
, kern_fd
, elf_img_len
= 0, elf_pad
;
450 uint32_t swapped
[128];
451 off_t lenpos
, kstart
, kend
;
452 unsigned long length
;
455 struct stat kern_stat
;
456 Elf32_External_Phdr phdr
;
458 elf_fd
= open_file("bootloader", boot
, &hdr
, &elf_stat
);
459 kern_fd
= open_file("kernel", kernel
, &khdr
, &kern_stat
);
460 kern_len
= kern_stat
.st_size
+ RS6000_MAGICSIZE
+ KERNLENSIZE
;
462 for (i
= 0; i
< ELFGET16(hdr
.e_phnum
); i
++) {
463 lseek(elf_fd
, ELFGET32(hdr
.e_phoff
) + sizeof(phdr
) * i
,
465 if (read(elf_fd
, &phdr
, sizeof(phdr
)) != sizeof(phdr
))
466 errx(3, "Can't read input '%s' phdr : %s", boot
,
469 if ((ELFGET32(phdr
.p_type
) != PT_LOAD
) ||
470 !(ELFGET32(phdr
.p_flags
) & PF_X
))
473 fstat(elf_fd
, &elf_stat
);
474 elf_img_len
= elf_stat
.st_size
- ELFGET32(phdr
.p_offset
);
475 elf_pad
= ELFGET32(phdr
.p_memsz
) - ELFGET32(phdr
.p_filesz
);
477 printf("Padding %d\n", elf_pad
);
478 lseek(elf_fd
, ELFGET32(phdr
.p_offset
), SEEK_SET
);
482 if ((rs6000_fd
= open(outname
, O_RDWR
|O_TRUNC
, 0)) < 0) {
483 /* we couldn't open it, it must be new */
484 rs6000_fd
= creat(outname
, 0644);
486 errx(2, "Can't open output '%s': %s", outname
,
490 /* Set file pos. to 2nd sector where image will be written */
491 lseek(rs6000_fd
, 0x400, SEEK_SET
);
493 /* Copy boot image */
494 elf_img
= (unsigned char *)malloc(elf_img_len
);
496 errx(3, "Can't malloc: %s", strerror(errno
));
497 if (read(elf_fd
, elf_img
, elf_img_len
) != elf_img_len
)
498 errx(3, "Can't read file '%s' : %s", boot
, strerror(errno
));
500 write(rs6000_fd
, elf_img
, elf_img_len
);
503 /* now dump in the padding space for the BSS */
504 elf_pad
+= 100; /* just a little extra for good luck */
505 lseek(rs6000_fd
, elf_pad
, SEEK_CUR
);
508 kern_img
= (unsigned char *)malloc(kern_stat
.st_size
);
510 if (kern_img
== NULL
)
511 errx(3, "Can't malloc: %s", strerror(errno
));
513 /* we need to jump back after having read the headers */
514 lseek(kern_fd
, 0, SEEK_SET
);
515 if (read(kern_fd
, (void *)kern_img
, kern_stat
.st_size
) !=
517 errx(3, "Can't read kernel '%s' : %s", kernel
, strerror(errno
));
519 gzf
= gzdopen(dup(rs6000_fd
), "a");
521 errx(3, "Can't init compression: %s", strerror(errno
));
522 if (gzsetparams(gzf
, Z_BEST_COMPRESSION
, Z_DEFAULT_STRATEGY
) != Z_OK
)
523 errx(3, "%s", gzerror(gzf
, &err
));
525 /* write a magic number and size before the kernel */
526 write(rs6000_fd
, (void *)rs6000_magic
, RS6000_MAGICSIZE
);
527 lenpos
= lseek(rs6000_fd
, 0, SEEK_CUR
);
529 printf("wrote magic at pos 0x%x\n", lenpos
);
531 write(rs6000_fd
, (void *)&tmp
, KERNLENSIZE
);
533 /* write in the compressed kernel */
534 kstart
= lseek(rs6000_fd
, 0, SEEK_CUR
);
536 printf("kernel start at pos 0x%x\n", kstart
);
537 kgzlen
= gzwrite(gzf
, kern_img
, kern_stat
.st_size
);
539 kend
= lseek(rs6000_fd
, 0, SEEK_CUR
);
541 printf("kernel end at pos 0x%x\n", kend
);
543 /* jump back to the length position now that we know the length */
544 lseek(rs6000_fd
, lenpos
, SEEK_SET
);
545 kgzlen
= kend
- kstart
;
546 tmp
= sa_htobe32(kgzlen
);
548 printf("kernel len = 0x%x tmp = 0x%x\n", kgzlen
, tmp
);
549 write(rs6000_fd
, (void *)&tmp
, KERNLENSIZE
);
552 lseek(rs6000_fd
, sizeof(boot_record_t
) + sizeof(config_record_t
),
554 /* set entry and length */
555 length
= sa_htole32(0x400);
556 write(rs6000_fd
, &length
, sizeof(length
));
557 length
= sa_htole32(0x400 + elf_img_len
+ 8 + kgzlen
);
558 write(rs6000_fd
, &length
, sizeof(length
));
561 /* generate the header now that we know the kernel length */
563 printf("building records\n");
564 rs6000_build_records(elf_img_len
+ 8 + kgzlen
);
565 lseek(rs6000_fd
, 0, SEEK_SET
);
566 /* ROM wants it byteswapped in 32bit chunks */
568 printf("writing records\n");
569 memcpy(swapped
, &bootrec
, sizeof(rs6000_boot_record_t
));
570 for (i
=0; i
< 128; i
++)
571 swapped
[i
] = htonl(swapped
[i
]);
572 write(rs6000_fd
, swapped
, sizeof(rs6000_boot_record_t
));
573 memcpy(swapped
, &confrec
, sizeof(rs6000_config_record_t
));
574 for (i
=0; i
< 128; i
++)
575 swapped
[i
] = htonl(swapped
[i
]);
576 write(rs6000_fd
, swapped
, sizeof(rs6000_config_record_t
));
587 bebox_write_header(int bebox_fd
, int elf_image_len
, int kern_img_len
)
589 int hsize
= BEBOX_HEADER_SIZE
;
590 unsigned long textOffset
, dataOffset
, ldrOffset
;
591 unsigned long entry_vector
[3];
592 struct FileHeader fileHdr
;
593 struct SectionHeader textHdr
, dataHdr
, ldrHdr
;
594 struct LoaderHeader lh
;
599 ldrOffset
= ULALIGN(sizeof (fileHdr
) + sizeof (textHdr
) +
600 sizeof (dataHdr
) + sizeof (ldrHdr
));
601 dataOffset
= ULALIGN(ldrOffset
+ sizeof (lh
));
602 textOffset
= ULALIGN(dataOffset
+ sizeof (entry_vector
) + kern_img_len
);
604 /* Create the File Header */
605 memset(&fileHdr
, 0, sizeof (fileHdr
));
606 fileHdr
.magic
= sa_htobe32(PEF_MAGIC
);
607 fileHdr
.fileTypeID
= sa_htobe32(PEF_FILE
);
608 fileHdr
.archID
= sa_htobe32(PEF_PPC
);
609 fileHdr
.versionNumber
= sa_htobe32(1);
610 fileHdr
.numSections
= sa_htobe16(3);
611 fileHdr
.loadableSections
= sa_htobe16(2);
612 write(bebox_fd
, &fileHdr
, sizeof (fileHdr
));
614 /* Create the Section Header for TEXT */
615 memset(&textHdr
, 0, sizeof (textHdr
));
616 textHdr
.sectionName
= sa_htobe32(-1);
617 textHdr
.sectionAddress
= sa_htobe32(0);
618 textHdr
.execSize
= sa_htobe32(elf_image_len
);
619 textHdr
.initSize
= sa_htobe32(elf_image_len
);
620 textHdr
.rawSize
= sa_htobe32(elf_image_len
);
621 textHdr
.fileOffset
= sa_htobe32(textOffset
);
622 textHdr
.regionKind
= CodeSection
;
623 textHdr
.shareKind
= ContextShare
;
624 textHdr
.alignment
= 4; /* 16 byte alignment */
625 write(bebox_fd
, &textHdr
, sizeof (textHdr
));
627 /* Create the Section Header for DATA */
628 memset(&dataHdr
, 0, sizeof (dataHdr
));
629 dataHdr
.sectionName
= sa_htobe32(-1);
630 dataHdr
.sectionAddress
= sa_htobe32(0);
631 dataHdr
.execSize
= sa_htobe32(sizeof (entry_vector
) + kern_img_len
);
632 dataHdr
.initSize
= sa_htobe32(sizeof (entry_vector
) + kern_img_len
);
633 dataHdr
.rawSize
= sa_htobe32(sizeof (entry_vector
) + kern_img_len
);
634 dataHdr
.fileOffset
= sa_htobe32(dataOffset
);
635 dataHdr
.regionKind
= DataSection
;
636 dataHdr
.shareKind
= ContextShare
;
637 dataHdr
.alignment
= 4; /* 16 byte alignment */
638 write(bebox_fd
, &dataHdr
, sizeof (dataHdr
));
640 /* Create the Section Header for loader stuff */
641 memset(&ldrHdr
, 0, sizeof (ldrHdr
));
642 ldrHdr
.sectionName
= sa_htobe32(-1);
643 ldrHdr
.sectionAddress
= sa_htobe32(0);
644 ldrHdr
.execSize
= sa_htobe32(sizeof (lh
));
645 ldrHdr
.initSize
= sa_htobe32(sizeof (lh
));
646 ldrHdr
.rawSize
= sa_htobe32(sizeof (lh
));
647 ldrHdr
.fileOffset
= sa_htobe32(ldrOffset
);
648 ldrHdr
.regionKind
= LoaderSection
;
649 ldrHdr
.shareKind
= GlobalShare
;
650 ldrHdr
.alignment
= 4; /* 16 byte alignment */
651 write(bebox_fd
, &ldrHdr
, sizeof (ldrHdr
));
653 /* Create the Loader Header */
654 memset(&lh
, 0, sizeof (lh
));
655 lh
.entryPointSection
= sa_htobe32(1); /* Data */
656 lh
.entryPointOffset
= sa_htobe32(0);
657 lh
.initPointSection
= sa_htobe32(-1);
658 lh
.initPointOffset
= sa_htobe32(0);
659 lh
.termPointSection
= sa_htobe32(-1);
660 lh
.termPointOffset
= sa_htobe32(0);
661 lseek(bebox_fd
, ldrOffset
+ hsize
, SEEK_SET
);
662 write(bebox_fd
, &lh
, sizeof (lh
));
664 /* Copy the pseudo-DATA */
665 memset(entry_vector
, 0, sizeof (entry_vector
));
666 entry_vector
[0] = sa_htobe32(BEBOX_ENTRY
); /* Magic */
667 lseek(bebox_fd
, dataOffset
+ hsize
, SEEK_SET
);
668 write(bebox_fd
, entry_vector
, sizeof (entry_vector
));
674 bebox_build_image(char *kernel
, char *boot
, char *rawdev
, char *outname
)
676 unsigned char *elf_img
= NULL
, *kern_img
= NULL
, *header_img
= NULL
;
677 int i
, ch
, tmp
, kgzlen
, err
, hsize
= BEBOX_HEADER_SIZE
;
678 int elf_fd
, bebox_fd
, kern_fd
, elf_img_len
= 0;
679 uint32_t swapped
[128];
680 off_t lenpos
, kstart
, kend
, toff
, endoff
;
681 unsigned long length
;
682 long flength
, *offset
;
684 struct stat kern_stat
;
685 struct bebox_image_block
*p
;
687 Elf32_External_Phdr phdr
;
692 elf_fd
= open_file("bootloader", boot
, &hdr
, &elf_stat
);
693 kern_fd
= open_file("kernel", kernel
, &khdr
, &kern_stat
);
694 kern_len
= kern_stat
.st_size
+ BEBOX_MAGICSIZE
+ KERNLENSIZE
;
696 for (i
= 0; i
< ELFGET16(hdr
.e_phnum
); i
++) {
697 lseek(elf_fd
, ELFGET32(hdr
.e_phoff
) + sizeof(phdr
) * i
,
699 if (read(elf_fd
, &phdr
, sizeof(phdr
)) != sizeof(phdr
))
700 errx(3, "Can't read input '%s' phdr : %s", boot
,
703 if ((ELFGET32(phdr
.p_type
) != PT_LOAD
) ||
704 !(ELFGET32(phdr
.p_flags
) & PF_X
))
707 fstat(elf_fd
, &elf_stat
);
708 elf_img_len
= ELFGET32(phdr
.p_filesz
);
709 lseek(elf_fd
, ELFGET32(phdr
.p_offset
), SEEK_SET
);
713 if ((bebox_fd
= open(outname
, O_RDWR
|O_TRUNC
, 0)) < 0) {
714 /* we couldn't open it, it must be new */
715 bebox_fd
= creat(outname
, 0644);
717 errx(2, "Can't open output '%s': %s", outname
,
720 lseek(bebox_fd
, hsize
, SEEK_SET
);
722 /* write the header with the wrong values to get the offset right */
723 bebox_write_header(bebox_fd
, elf_img_len
, kern_stat
.st_size
);
726 kern_img
= (unsigned char *)malloc(kern_stat
.st_size
);
728 if (kern_img
== NULL
)
729 errx(3, "Can't malloc: %s", strerror(errno
));
731 /* we need to jump back after having read the headers */
732 lseek(kern_fd
, 0, SEEK_SET
);
733 if (read(kern_fd
, (void *)kern_img
, kern_stat
.st_size
) !=
735 errx(3, "Can't read kernel '%s' : %s", kernel
, strerror(errno
));
737 gzf
= gzdopen(dup(bebox_fd
), "a");
739 errx(3, "Can't init compression: %s", strerror(errno
));
740 if (gzsetparams(gzf
, Z_BEST_COMPRESSION
, Z_DEFAULT_STRATEGY
) != Z_OK
)
741 errx(3, "%s", gzerror(gzf
, &err
));
743 /* write a magic number and size before the kernel */
744 write(bebox_fd
, (void *)bebox_magic
, BEBOX_MAGICSIZE
);
745 lenpos
= lseek(bebox_fd
, 0, SEEK_CUR
);
747 write(bebox_fd
, (void *)&tmp
, KERNLENSIZE
);
749 /* write in the compressed kernel */
750 kstart
= lseek(bebox_fd
, 0, SEEK_CUR
);
751 kgzlen
= gzwrite(gzf
, kern_img
, kern_stat
.st_size
);
753 kend
= lseek(bebox_fd
, 0, SEEK_CUR
);
756 /* jump back to the length position now that we know the length */
757 lseek(bebox_fd
, lenpos
, SEEK_SET
);
758 kgzlen
= kend
- kstart
;
759 tmp
= sa_htobe32(kgzlen
);
760 write(bebox_fd
, (void *)&tmp
, KERNLENSIZE
);
762 /* now rewrite the header correctly */
763 lseek(bebox_fd
, hsize
, SEEK_SET
);
764 tmp
= kgzlen
+ BEBOX_MAGICSIZE
+ KERNLENSIZE
;
765 toff
= bebox_write_header(bebox_fd
, elf_img_len
, tmp
);
767 /* Copy boot image */
768 elf_img
= (unsigned char *)malloc(elf_img_len
);
770 errx(3, "Can't malloc: %s", strerror(errno
));
771 if (read(elf_fd
, elf_img
, elf_img_len
) != elf_img_len
)
772 errx(3, "Can't read file '%s' : %s", boot
, strerror(errno
));
773 lseek(bebox_fd
, toff
+ hsize
, SEEK_SET
);
774 write(bebox_fd
, elf_img
, elf_img_len
);
785 /* Now go back and write in the block header */
786 endoff
= lseek(bebox_fd
, 0, SEEK_END
);
787 lseek(bebox_fd
, 0, SEEK_SET
);
788 header_img
= (unsigned char *)malloc(BEBOX_HEADER_SIZE
);
790 errx(3, "Can't malloc: %s", strerror(errno
));
791 memset(header_img
, 0, BEBOX_HEADER_SIZE
);
793 /* copy the boot image into the buffer */
794 for (p
= bebox_image_block
; p
->offset
!= -1; p
++)
795 memcpy(header_img
+ p
->offset
, p
->data
, p
->size
);
797 /* fill used block bitmap */
798 memset(header_img
+ BEBOX_FILE_BLOCK_MAP_START
, 0xff,
799 BEBOX_FILE_BLOCK_MAP_END
- BEBOX_FILE_BLOCK_MAP_START
);
801 /* fix the file size in the header */
802 tmp
= endoff
- BEBOX_HEADER_SIZE
;
803 *(long *)(header_img
+ BEBOX_FILE_SIZE_OFFSET
) =
804 (long)sa_htobe32(tmp
);
805 *(long *)(header_img
+ BEBOX_FILE_SIZE_ALIGN_OFFSET
) =
806 (long)sa_htobe32(roundup(tmp
, BEBOX_FILE_BLOCK_SIZE
));
808 gettimeofday(&tp
, 0);
809 for (offset
= bebox_mtime_offset
; *offset
!= -1; offset
++)
810 *(long *)(header_img
+ *offset
) = (long)sa_htobe32(tp
.tv_sec
);
812 write(bebox_fd
, header_img
, BEBOX_HEADER_SIZE
);
814 /* now pad the end */
815 flength
= roundup(endoff
, BEBOX_BLOCK_SIZE
);
816 /* refill the header_img with zeros */
817 memset(header_img
, 0, BEBOX_BLOCK_SIZE
* 2);
818 lseek(bebox_fd
, 0, SEEK_END
);
819 write(bebox_fd
, header_img
, flength
- endoff
);
827 main(int argc
, char **argv
)
829 int ch
, lfloppyflag
=0;
830 char *kernel
= NULL
, *boot
= NULL
, *rawdev
= NULL
, *outname
= NULL
;
833 char machine
[SYS_NMLN
];
834 int mib
[2] = { CTL_HW
, HW_MACHINE
};
837 setprogname(argv
[0]);
840 while ((ch
= getopt(argc
, argv
, "b:k:lm:r:sv")) != -1)
878 boot
= "/usr/mdec/boot";
880 if (march
!= NULL
&& strcmp(march
, "") == 0)
885 size_t len
= sizeof(machine
);
887 if (sysctl(mib
, sizeof (mib
) / sizeof (mib
[0]), machine
,
888 &len
, NULL
, 0) != -1) {
889 for (i
=0; sup_plats
[i
] != NULL
; i
++) {
890 if (strcmp(sup_plats
[i
], machine
) == 0) {
891 march
= strdup(sup_plats
[i
]);
903 if (strcmp(march
, "prep") == 0)
904 return(prep_build_image(kernel
, boot
, rawdev
, outname
));
905 if (strcmp(march
, "rs6000") == 0)
906 return(rs6000_build_image(kernel
, boot
, rawdev
, outname
));
907 if (strcmp(march
, "bebox") == 0)
908 return(bebox_build_image(kernel
, boot
, rawdev
, outname
));