1 /* $NetBSD: installboot.c,v 1.3 2008/05/14 13:29:27 tsutsui Exp $ */
4 * Copyright (c) 2005 Izumi Tsutsui. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #if HAVE_NBTOOL_CONFIG_H
28 #include "nbtool_config.h"
38 #include <sys/types.h>
40 #include "installboot.h"
43 #define MAX_SB_SIZE (64 * 1024) /* XXX */
44 #define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
46 static void usage(void);
48 static ib_params installboot_params
;
51 main(int argc
, char **argv
)
55 struct apple_part_map_entry pme
;
57 struct shared_bbinfo
*bbinfop
;
59 uint32_t nblk
, maxblk
, blk_i
;
64 params
= &installboot_params
;
65 memset(params
, 0, sizeof(*params
));
72 params
->filesystem
= argv
[1];
74 if ((params
->fsfd
= open(params
->filesystem
, O_RDWR
, 0600)) == -1)
75 err(1, "Opening file system `%s' read", params
->filesystem
);
76 if (fstat(params
->fsfd
, ¶ms
->fsstat
) == -1)
77 err(1, "Examining file system `%s'", params
->filesystem
);
79 printf("file system: %s, %ld bytes\n",
80 params
->filesystem
, (long)params
->fsstat
.st_size
);
84 * Find space for primary boot from the second (NetBSD_BootBlock)
87 if (pread(params
->fsfd
, &pme
, sizeof pme
, BSIZE
* 2) != sizeof(pme
))
88 err(1, "read pme from file system `%s'", params
->filesystem
);
90 if (strcmp(pme
.pmPartName
, "NetBSD_BootBlock"))
91 err(1, "invalid partition map in file system `%s'",
94 /* pmPyPartStart is written by mkisofs */
95 partoff
= BSIZE
* be32toh(pme
.pmPyPartStart
);
98 printf("NetBSD partition offset = %ld\n", (long)partoff
);
101 params
->stage1
= argv
[2];
103 if ((params
->s1fd
= open(params
->stage1
, O_RDONLY
, 0600)) == -1)
104 err(1, "Opening primary bootstrap `%s'", params
->stage1
);
105 if (fstat(params
->s1fd
, ¶ms
->s1stat
) == -1)
106 err(1, "Examining primary bootstrap `%s'", params
->stage1
);
107 if (!S_ISREG(params
->s1stat
.st_mode
))
108 err(1, "`%s' must be a regular file", params
->stage1
);
110 if (params
->s1stat
.st_size
> MACPPC_BOOT_BLOCK_MAX_SIZE
)
111 err(1, "primary bootrap `%s' too large (%ld bytes)",
112 params
->stage1
, (long)params
->s1stat
.st_size
);
115 printf("primary boot: %s, %ld bytes\n",
116 params
->stage1
, (long)params
->s1stat
.st_size
);
119 params
->stage2
= argv
[3];
121 bb
= malloc(MACPPC_BOOT_BLOCK_MAX_SIZE
);
123 err(1, "Allocating %ul bytes for bbinfo",
124 MACPPC_BOOT_BLOCK_MAX_SIZE
);
126 memset(bb
, 0, sizeof(bb
));
127 rv
= read(params
->s1fd
, bb
, params
->s1stat
.st_size
);
130 err(1, "Reading `%s'", params
->stage1
);
132 if (memcmp(bb
+ 1, "ELF", strlen("ELF")) == 0) {
133 warnx("`%s' is an ELF executable; need raw binary",
137 /* look for the bbinfo structure */
138 for (bbi
= 0; bbi
< MACPPC_BOOT_BLOCK_MAX_SIZE
;
139 bbi
+= sizeof(uint32_t)) {
140 bbinfop
= (void *)(bb
+ bbi
);
141 if (memcmp(bbinfop
->bbi_magic
, MACPPC_BBINFO_MAGIC
,
142 sizeof(bbinfop
->bbi_magic
)) == 0) {
144 printf("magic found: %s\n", bbinfop
->bbi_magic
);
149 if (bbi
>= MACPPC_BOOT_BLOCK_MAX_SIZE
)
150 err(1, "bbinfo structure not found in `%s'", params
->stage1
);
152 maxblk
= be32toh(bbinfop
->bbi_block_count
);
154 maxblk
> (MACPPC_BOOT_BLOCK_MAX_SIZE
/ sizeof(uint32_t)))
155 err(1, "bbinfo structure in `%s' has preposterous size `%u'",
156 params
->stage1
, maxblk
);
158 blocks
= malloc(sizeof(*blocks
) * maxblk
);
159 if (blocks
== NULL
) {
160 err(1, "Allocating %lu bytes for blocks",
161 (unsigned long)sizeof(*blocks
) * maxblk
);
164 if (S_ISREG(params
->fsstat
.st_mode
)) {
165 if (fsync(params
->fsfd
) == -1)
166 err(1, "Synchronising file system `%s'",
171 if (!cd9660_findstage2(params
, &nblk
, blocks
)) {
175 bbinfop
->bbi_block_count
= htobe32(nblk
);
176 bbinfop
->bbi_block_size
= htobe32(blocks
[0].blocksize
);
177 for (blk_i
= 0; blk_i
< nblk
; blk_i
++) {
178 bbinfop
->bbi_block_table
[blk_i
] = htobe32(blocks
[blk_i
].block
);
179 if (blocks
[blk_i
].blocksize
< blocks
[0].blocksize
&&
181 warnx("Secondary bootstrap `%s' blocks do not have "
182 "a uniform size", params
->stage2
);
187 /* XXX no write option */
189 if (pwrite(params
->fsfd
, bb
, MACPPC_BOOT_BLOCK_MAX_SIZE
, partoff
) !=
190 MACPPC_BOOT_BLOCK_MAX_SIZE
)
191 err(1, "write bootblock");
193 if (S_ISREG(params
->fsstat
.st_mode
)) {
194 if (fsync(params
->fsfd
) == -1)
195 err(1, "Synchronising file system `%s'",
201 if (close(params
->fsfd
) == -1)
202 err(1, "Closing file system `%s'", params
->filesystem
);
203 if (close(params
->s1fd
) == -1)
204 err(1, "Closing primary bootstrap `%s'", params
->stage1
);
214 prog
= getprogname();
215 fprintf(stderr
, "usage: %s hybrid-cd-image primary secondary\n", prog
);