2 * Makes a prep bootable image which can be dd'd onto
3 * a disk device to make a bootdisk. Will take
4 * as input a elf executable, strip off the header
5 * and write out a boot image as:
6 * 1) default - strips elf header
7 * suitable as a network boot image
8 * 2) -pbp - strips elf header and writes out prep boot partition image
9 * cat or dd onto disk for booting
10 * 3) -asm - strips elf header and writes out as asm data
11 * useful for generating data for a compressed image
14 * Modified for x86 hosted builds by Matt Porter <porter@neta.com>
15 * Modified for Sparc hosted builds by Peter Wahl <PeterWahl@web.de>
22 /* size of read buffer */
26 * Partition table entry
27 * - from the PReP spec
29 typedef struct partition_entry
{
30 unsigned char boot_indicator
;
31 unsigned char starting_head
;
32 unsigned char starting_sector
;
33 unsigned char starting_cylinder
;
35 unsigned char system_indicator
;
36 unsigned char ending_head
;
37 unsigned char ending_sector
;
38 unsigned char ending_cylinder
;
40 unsigned char beginning_sector
[4];
41 unsigned char number_of_sectors
[4];
44 #define BootActive 0x80
45 #define SystemPrep 0x41
47 void copy_image(FILE *, FILE *);
48 void write_prep_partition(FILE *, FILE *);
49 void write_asm_data(FILE *, FILE *);
51 unsigned int elfhdr_size
= 65536;
53 int main(int argc
, char *argv
[])
60 if (argc
< 3 || argc
> 4) {
61 fprintf(stderr
, "usage: %s [-pbp] [-asm] <boot-file> <image>\n",
66 /* needs to handle args more elegantly -- but this is a small/simple program */
69 if (!strcmp(argv
[argptr
], "-pbp")) {
75 if (!strcmp(argv
[argptr
], "-asm")) {
81 if (!strcmp(argv
[argptr
], "-"))
83 else if (!(in
= fopen(argv
[argptr
], "r")))
88 if (!strcmp(argv
[argptr
], "-"))
90 else if (!(out
= fopen(argv
[argptr
], "w")))
94 /* skip elf header in input file */
96 fseek(in
, elfhdr_size
, SEEK_SET
);
98 /* write prep partition if necessary */
100 write_prep_partition(in
, out
);
102 /* write input image to bootimage */
104 write_asm_data(in
, out
);
111 void store_le32(unsigned int v
, unsigned char *p
)
119 void write_prep_partition(FILE *in
, FILE *out
)
121 unsigned char block
[512];
122 partition_entry_t pe
;
123 unsigned char *entry
= block
;
124 unsigned char *length
= block
+ 4;
125 long pos
= ftell(in
), size
;
127 if (fseek(in
, 0, SEEK_END
) < 0) {
128 fprintf(stderr
,"info failed\n");
132 if (fseek(in
, pos
, SEEK_SET
) < 0) {
133 fprintf(stderr
,"info failed\n");
137 memset(block
, '\0', sizeof(block
));
139 /* set entry point and boot image size skipping over elf header */
140 store_le32(0x400/*+65536*/, entry
);
141 store_le32(size
-elfhdr_size
+0x400, length
);
143 /* sets magic number for msdos partition (used by linux) */
148 * Build a "PReP" partition table entry in the boot record
149 * - "PReP" may only look at the system_indicator
151 pe
.boot_indicator
= BootActive
;
152 pe
.system_indicator
= SystemPrep
;
154 * The first block of the diskette is used by this "boot record" which
155 * actually contains the partition table. (The first block of the
156 * partition contains the boot image, but I digress...) We'll set up
157 * one partition on the diskette and it shall contain the rest of the
160 pe
.starting_head
= 0; /* zero-based */
161 pe
.starting_sector
= 2; /* one-based */
162 pe
.starting_cylinder
= 0; /* zero-based */
163 pe
.ending_head
= 1; /* assumes two heads */
164 pe
.ending_sector
= 18; /* assumes 18 sectors/track */
165 pe
.ending_cylinder
= 79; /* assumes 80 cylinders/diskette */
168 * The "PReP" software ignores the above fields and just looks at
170 * - size of the diskette is (assumed to be)
171 * (2 tracks/cylinder)(18 sectors/tracks)(80 cylinders/diskette)
172 * - unlike the above sector numbers, the beginning sector is zero-based!
175 store_le32(1, pe
.beginning_sector
);
177 /* This has to be 0 on the PowerStack? */
178 store_le32(0, pe
.beginning_sector
);
181 store_le32(2*18*80-1, pe
.number_of_sectors
);
183 memcpy(&block
[0x1BE], &pe
, sizeof(pe
));
185 fwrite(block
, sizeof(block
), 1, out
);
186 fwrite(entry
, 4, 1, out
);
187 fwrite(length
, 4, 1, out
);
188 /* set file position to 2nd sector where image will be written */
189 fseek( out
, 0x400, SEEK_SET
);
194 void copy_image(FILE *in
, FILE *out
)
199 while ( (n
= fread(buf
, 1, SIZE
, in
)) > 0 )
200 fwrite(buf
, 1, n
, out
);
205 write_asm_data(FILE *in
, FILE *out
)
208 unsigned int cksum
= 0, val
;
210 unsigned char buf
[SIZE
];
213 fputs("\t.data\n\t.globl input_data\ninput_data:\n", out
);
214 while ((len
= fread(buf
, 1, sizeof(buf
), in
)) > 0) {
217 /* Round up to longwords */
220 for (i
= 0; i
< len
; i
+= 4) {
222 fputs("\t.long\t", out
);
223 fprintf(out
, "0x%02X%02X%02X%02X",
224 lp
[0], lp
[1], lp
[2], lp
[3]);
225 val
= *(unsigned long *)lp
;
230 fprintf(out
, " # %x \n", pos
+i
-12);
239 fprintf(out
, "\t.globl input_len\ninput_len:\t.long\t0x%x\n", pos
);
240 fprintf(stderr
, "cksum = %x\n", cksum
);