installboot.c revision 1.6.6.2 1 1.6.6.2 nathanw /* $NetBSD: installboot.c,v 1.6.6.2 2002/04/17 00:03:43 nathanw Exp $ */
2 1.6.6.2 nathanw
3 1.6.6.2 nathanw /*-
4 1.6.6.2 nathanw * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 1.6.6.2 nathanw * All rights reserved.
6 1.6.6.2 nathanw *
7 1.6.6.2 nathanw * This code is derived from software contributed to The NetBSD Foundation
8 1.6.6.2 nathanw * by Paul Kranenburg.
9 1.6.6.2 nathanw *
10 1.6.6.2 nathanw * Redistribution and use in source and binary forms, with or without
11 1.6.6.2 nathanw * modification, are permitted provided that the following conditions
12 1.6.6.2 nathanw * are met:
13 1.6.6.2 nathanw * 1. Redistributions of source code must retain the above copyright
14 1.6.6.2 nathanw * notice, this list of conditions and the following disclaimer.
15 1.6.6.2 nathanw * 2. Redistributions in binary form must reproduce the above copyright
16 1.6.6.2 nathanw * notice, this list of conditions and the following disclaimer in the
17 1.6.6.2 nathanw * documentation and/or other materials provided with the distribution.
18 1.6.6.2 nathanw * 3. All advertising materials mentioning features or use of this software
19 1.6.6.2 nathanw * must display the following acknowledgement:
20 1.6.6.2 nathanw * This product includes software developed by the NetBSD
21 1.6.6.2 nathanw * Foundation, Inc. and its contributors.
22 1.6.6.2 nathanw * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.6.6.2 nathanw * contributors may be used to endorse or promote products derived
24 1.6.6.2 nathanw * from this software without specific prior written permission.
25 1.6.6.2 nathanw *
26 1.6.6.2 nathanw * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.6.6.2 nathanw * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.6.6.2 nathanw * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.6.6.2 nathanw * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.6.6.2 nathanw * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.6.6.2 nathanw * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.6.6.2 nathanw * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.6.6.2 nathanw * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.6.6.2 nathanw * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.6.6.2 nathanw * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.6.6.2 nathanw * POSSIBILITY OF SUCH DAMAGE.
37 1.6.6.2 nathanw */
38 1.6.6.2 nathanw
39 1.6.6.2 nathanw #include <sys/param.h>
40 1.6.6.2 nathanw #include <sys/mount.h>
41 1.6.6.2 nathanw #include <sys/time.h>
42 1.6.6.2 nathanw #include <sys/stat.h>
43 1.6.6.2 nathanw #include <sys/sysctl.h>
44 1.6.6.2 nathanw #include <ufs/ufs/dinode.h>
45 1.6.6.2 nathanw #include <ufs/ufs/dir.h>
46 1.6.6.2 nathanw #include <ufs/ffs/fs.h>
47 1.6.6.2 nathanw #include <err.h>
48 1.6.6.2 nathanw #ifdef BOOT_AOUT
49 1.6.6.2 nathanw #include <a.out.h>
50 1.6.6.2 nathanw #endif
51 1.6.6.2 nathanw #include <sys/exec_elf.h>
52 1.6.6.2 nathanw #include <fcntl.h>
53 1.6.6.2 nathanw #include <nlist.h>
54 1.6.6.2 nathanw #include <stdlib.h>
55 1.6.6.2 nathanw #include <stdio.h>
56 1.6.6.2 nathanw #include <string.h>
57 1.6.6.2 nathanw #include <unistd.h>
58 1.6.6.2 nathanw
59 1.6.6.2 nathanw #include "dpme.h"
60 1.6.6.2 nathanw
61 1.6.6.2 nathanw int verbose, nowrite, conblockmode, conblockstart;
62 1.6.6.2 nathanw char *boot, *proto, *dev;
63 1.6.6.2 nathanw
64 1.6.6.2 nathanw #define BOOTSECTOR_OFFSET 2048
65 1.6.6.2 nathanw
66 1.6.6.2 nathanw #ifndef DEFAULT_ENTRY
67 1.6.6.2 nathanw #define DEFAULT_ENTRY 0x600000
68 1.6.6.2 nathanw #endif
69 1.6.6.2 nathanw
70 1.6.6.2 nathanw struct nlist nl[] = {
71 1.6.6.2 nathanw #define X_BLOCKTABLE 0
72 1.6.6.2 nathanw {"_block_table"},
73 1.6.6.2 nathanw #define X_BLOCKCOUNT 1
74 1.6.6.2 nathanw {"_block_count"},
75 1.6.6.2 nathanw #define X_BLOCKSIZE 2
76 1.6.6.2 nathanw {"_block_size"},
77 1.6.6.2 nathanw #define X_ENTRY_POINT 3
78 1.6.6.2 nathanw {"_entry_point"},
79 1.6.6.2 nathanw {NULL}
80 1.6.6.2 nathanw };
81 1.6.6.2 nathanw
82 1.6.6.2 nathanw daddr_t *block_table; /* block number array in prototype image */
83 1.6.6.2 nathanw int32_t *block_count_p; /* size of this array */
84 1.6.6.2 nathanw int32_t *block_size_p; /* filesystem block size */
85 1.6.6.2 nathanw int32_t *entry_point_p; /* entry point */
86 1.6.6.2 nathanw int32_t max_block_count;
87 1.6.6.2 nathanw
88 1.6.6.2 nathanw char *loadprotoblocks __P((char *, long *));
89 1.6.6.2 nathanw int loadblocknums_contig __P((char *, int));
90 1.6.6.2 nathanw int loadblocknums_ffs __P((char *, int));
91 1.6.6.2 nathanw static void devread __P((int, void *, daddr_t, size_t, char *));
92 1.6.6.2 nathanw static void usage __P((void));
93 1.6.6.2 nathanw int main __P((int, char *[]));
94 1.6.6.2 nathanw
95 1.6.6.2 nathanw
96 1.6.6.2 nathanw static void
97 1.6.6.2 nathanw usage()
98 1.6.6.2 nathanw {
99 1.6.6.2 nathanw fprintf(stderr,
100 1.6.6.2 nathanw "usage: installboot [-n] [-v] [-b bno] <boot> <proto> <device>\n");
101 1.6.6.2 nathanw exit(1);
102 1.6.6.2 nathanw }
103 1.6.6.2 nathanw
104 1.6.6.2 nathanw int
105 1.6.6.2 nathanw main(argc, argv)
106 1.6.6.2 nathanw int argc;
107 1.6.6.2 nathanw char *argv[];
108 1.6.6.2 nathanw {
109 1.6.6.2 nathanw int c;
110 1.6.6.2 nathanw int devfd;
111 1.6.6.2 nathanw char *protostore;
112 1.6.6.2 nathanw long protosize;
113 1.6.6.2 nathanw int mib[2];
114 1.6.6.2 nathanw size_t size;
115 1.6.6.2 nathanw int (*loadblocknums_func) __P((char *, int));
116 1.6.6.2 nathanw
117 1.6.6.2 nathanw while ((c = getopt(argc, argv, "vnb:")) != -1) {
118 1.6.6.2 nathanw switch (c) {
119 1.6.6.2 nathanw
120 1.6.6.2 nathanw case 'b':
121 1.6.6.2 nathanw /* generic override, supply starting block # */
122 1.6.6.2 nathanw conblockmode = 1;
123 1.6.6.2 nathanw conblockstart = atoi(optarg);
124 1.6.6.2 nathanw break;
125 1.6.6.2 nathanw case 'n':
126 1.6.6.2 nathanw /* Do not actually write the bootblock to disk */
127 1.6.6.2 nathanw nowrite = 1;
128 1.6.6.2 nathanw break;
129 1.6.6.2 nathanw case 'v':
130 1.6.6.2 nathanw /* Chat */
131 1.6.6.2 nathanw verbose = 1;
132 1.6.6.2 nathanw break;
133 1.6.6.2 nathanw default:
134 1.6.6.2 nathanw usage();
135 1.6.6.2 nathanw }
136 1.6.6.2 nathanw }
137 1.6.6.2 nathanw
138 1.6.6.2 nathanw if (argc - optind < 3) {
139 1.6.6.2 nathanw usage();
140 1.6.6.2 nathanw }
141 1.6.6.2 nathanw
142 1.6.6.2 nathanw boot = argv[optind];
143 1.6.6.2 nathanw proto = argv[optind + 1];
144 1.6.6.2 nathanw dev = argv[optind + 2];
145 1.6.6.2 nathanw
146 1.6.6.2 nathanw if (verbose) {
147 1.6.6.2 nathanw printf("boot: %s\n", boot);
148 1.6.6.2 nathanw printf("proto: %s\n", proto);
149 1.6.6.2 nathanw printf("device: %s\n", dev);
150 1.6.6.2 nathanw }
151 1.6.6.2 nathanw
152 1.6.6.2 nathanw /* Load proto blocks into core */
153 1.6.6.2 nathanw if ((protostore = loadprotoblocks(proto, &protosize)) == NULL)
154 1.6.6.2 nathanw exit(1);
155 1.6.6.2 nathanw
156 1.6.6.2 nathanw /* Open and check raw disk device */
157 1.6.6.2 nathanw if ((devfd = open(dev, O_RDONLY, 0)) < 0)
158 1.6.6.2 nathanw err(1, "open: %s", dev);
159 1.6.6.2 nathanw
160 1.6.6.2 nathanw /* Extract and load block numbers */
161 1.6.6.2 nathanw if (conblockmode)
162 1.6.6.2 nathanw loadblocknums_func = loadblocknums_contig;
163 1.6.6.2 nathanw else
164 1.6.6.2 nathanw loadblocknums_func = loadblocknums_ffs;
165 1.6.6.2 nathanw
166 1.6.6.2 nathanw if ((loadblocknums_func)(boot, devfd) != 0)
167 1.6.6.2 nathanw exit(1);
168 1.6.6.2 nathanw
169 1.6.6.2 nathanw (void)close(devfd);
170 1.6.6.2 nathanw
171 1.6.6.2 nathanw if (nowrite)
172 1.6.6.2 nathanw return 0;
173 1.6.6.2 nathanw
174 1.6.6.2 nathanw /* Write patched proto bootblocks into the superblock */
175 1.6.6.2 nathanw if (protosize > SBSIZE - DEV_BSIZE)
176 1.6.6.2 nathanw errx(1, "proto bootblocks too big");
177 1.6.6.2 nathanw
178 1.6.6.2 nathanw if ((devfd = open(dev, O_RDWR, 0)) < 0)
179 1.6.6.2 nathanw err(1, "open: %s", dev);
180 1.6.6.2 nathanw
181 1.6.6.2 nathanw if (writeapplepartmap(devfd) < 0)
182 1.6.6.2 nathanw err(1, "write apm: %s", dev);
183 1.6.6.2 nathanw
184 1.6.6.2 nathanw if (lseek(devfd, BOOTSECTOR_OFFSET, SEEK_SET) != BOOTSECTOR_OFFSET)
185 1.6.6.2 nathanw err(1, "lseek bootstrap");
186 1.6.6.2 nathanw
187 1.6.6.2 nathanw /* Sync filesystems (to clean in-memory superblock?) */
188 1.6.6.2 nathanw sync();
189 1.6.6.2 nathanw
190 1.6.6.2 nathanw if (write(devfd, protostore, protosize) != protosize)
191 1.6.6.2 nathanw err(1, "write bootstrap");
192 1.6.6.2 nathanw (void)close(devfd);
193 1.6.6.2 nathanw return 0;
194 1.6.6.2 nathanw }
195 1.6.6.2 nathanw
196 1.6.6.2 nathanw char *
197 1.6.6.2 nathanw loadprotoblocks(fname, size)
198 1.6.6.2 nathanw char *fname;
199 1.6.6.2 nathanw long *size;
200 1.6.6.2 nathanw {
201 1.6.6.2 nathanw int fd, sz;
202 1.6.6.2 nathanw char *bp;
203 1.6.6.2 nathanw struct stat statbuf;
204 1.6.6.2 nathanw #ifdef BOOT_AOUT
205 1.6.6.2 nathanw struct exec *hp;
206 1.6.6.2 nathanw #endif
207 1.6.6.2 nathanw long off;
208 1.6.6.2 nathanw Elf32_Ehdr *eh;
209 1.6.6.2 nathanw Elf32_Phdr *ph;
210 1.6.6.2 nathanw
211 1.6.6.2 nathanw /* Locate block number array in proto file */
212 1.6.6.2 nathanw if (nlist(fname, nl) != 0) {
213 1.6.6.2 nathanw warnx("nlist: %s: symbols not found", fname);
214 1.6.6.2 nathanw return NULL;
215 1.6.6.2 nathanw }
216 1.6.6.2 nathanw #ifdef BOOT_AOUT
217 1.6.6.2 nathanw if (nl[X_BLOCKTABLE].n_type != N_DATA + N_EXT) {
218 1.6.6.2 nathanw warnx("nlist: %s: wrong type", nl[X_BLOCKTABLE].n_un.n_name);
219 1.6.6.2 nathanw return NULL;
220 1.6.6.2 nathanw }
221 1.6.6.2 nathanw if (nl[X_BLOCKCOUNT].n_type != N_DATA + N_EXT) {
222 1.6.6.2 nathanw warnx("nlist: %s: wrong type", nl[X_BLOCKCOUNT].n_un.n_name);
223 1.6.6.2 nathanw return NULL;
224 1.6.6.2 nathanw }
225 1.6.6.2 nathanw if (nl[X_BLOCKSIZE].n_type != N_DATA + N_EXT) {
226 1.6.6.2 nathanw warnx("nlist: %s: wrong type", nl[X_BLOCKSIZE].n_un.n_name);
227 1.6.6.2 nathanw return NULL;
228 1.6.6.2 nathanw }
229 1.6.6.2 nathanw #endif
230 1.6.6.2 nathanw
231 1.6.6.2 nathanw if ((fd = open(fname, O_RDONLY)) < 0) {
232 1.6.6.2 nathanw warn("open: %s", fname);
233 1.6.6.2 nathanw return NULL;
234 1.6.6.2 nathanw }
235 1.6.6.2 nathanw if (fstat(fd, &statbuf) != 0) {
236 1.6.6.2 nathanw warn("fstat: %s", fname);
237 1.6.6.2 nathanw close(fd);
238 1.6.6.2 nathanw return NULL;
239 1.6.6.2 nathanw }
240 1.6.6.2 nathanw if ((bp = calloc(roundup(statbuf.st_size, DEV_BSIZE), 1)) == NULL) {
241 1.6.6.2 nathanw warnx("malloc: %s: no memory", fname);
242 1.6.6.2 nathanw close(fd);
243 1.6.6.2 nathanw return NULL;
244 1.6.6.2 nathanw }
245 1.6.6.2 nathanw if (read(fd, bp, statbuf.st_size) != statbuf.st_size) {
246 1.6.6.2 nathanw warn("read: %s", fname);
247 1.6.6.2 nathanw free(bp);
248 1.6.6.2 nathanw close(fd);
249 1.6.6.2 nathanw return NULL;
250 1.6.6.2 nathanw }
251 1.6.6.2 nathanw close(fd);
252 1.6.6.2 nathanw
253 1.6.6.2 nathanw #ifdef BOOT_AOUT
254 1.6.6.2 nathanw hp = (struct exec *)bp;
255 1.6.6.2 nathanw #endif
256 1.6.6.2 nathanw eh = (Elf32_Ehdr *)bp;
257 1.6.6.2 nathanw ph = (Elf32_Phdr *)(bp + eh->e_phoff);
258 1.6.6.2 nathanw sz = 1024;
259 1.6.6.2 nathanw
260 1.6.6.2 nathanw /* Calculate the symbols' location within the proto file */
261 1.6.6.2 nathanw off = ph->p_offset - eh->e_entry;
262 1.6.6.2 nathanw block_table = (daddr_t *)(bp + nl[X_BLOCKTABLE].n_value + off);
263 1.6.6.2 nathanw block_count_p = (int32_t *)(bp + nl[X_BLOCKCOUNT].n_value + off);
264 1.6.6.2 nathanw block_size_p = (int32_t *)(bp + nl[X_BLOCKSIZE].n_value + off);
265 1.6.6.2 nathanw entry_point_p = (int32_t *)(bp + nl[X_ENTRY_POINT].n_value + off);
266 1.6.6.2 nathanw
267 1.6.6.2 nathanw if ((int)block_table & 3) {
268 1.6.6.2 nathanw warn("%s: invalid address: block_table = %x",
269 1.6.6.2 nathanw fname, block_table);
270 1.6.6.2 nathanw free(bp);
271 1.6.6.2 nathanw close(fd);
272 1.6.6.2 nathanw return NULL;
273 1.6.6.2 nathanw }
274 1.6.6.2 nathanw if ((int)block_count_p & 3) {
275 1.6.6.2 nathanw warn("%s: invalid address: block_count_p = %x",
276 1.6.6.2 nathanw fname, block_count_p);
277 1.6.6.2 nathanw free(bp);
278 1.6.6.2 nathanw close(fd);
279 1.6.6.2 nathanw return NULL;
280 1.6.6.2 nathanw }
281 1.6.6.2 nathanw if ((int)block_size_p & 3) {
282 1.6.6.2 nathanw warn("%s: invalid address: block_size_p = %x",
283 1.6.6.2 nathanw fname, block_size_p);
284 1.6.6.2 nathanw free(bp);
285 1.6.6.2 nathanw close(fd);
286 1.6.6.2 nathanw return NULL;
287 1.6.6.2 nathanw }
288 1.6.6.2 nathanw if ((int)entry_point_p & 3) {
289 1.6.6.2 nathanw warn("%s: invalid address: entry_point_p = %x",
290 1.6.6.2 nathanw fname, entry_point_p);
291 1.6.6.2 nathanw free(bp);
292 1.6.6.2 nathanw close(fd);
293 1.6.6.2 nathanw return NULL;
294 1.6.6.2 nathanw }
295 1.6.6.2 nathanw max_block_count = *block_count_p;
296 1.6.6.2 nathanw
297 1.6.6.2 nathanw if (verbose) {
298 1.6.6.2 nathanw printf("proto bootblock size: %ld\n", sz);
299 1.6.6.2 nathanw }
300 1.6.6.2 nathanw
301 1.6.6.2 nathanw /*
302 1.6.6.2 nathanw * We convert the a.out header in-vitro into something that
303 1.6.6.2 nathanw * Sun PROMs understand.
304 1.6.6.2 nathanw * Old-style (sun4) ROMs do not expect a header at all, so
305 1.6.6.2 nathanw * we turn the first two words into code that gets us past
306 1.6.6.2 nathanw * the 32-byte header where the actual code begins. In assembly
307 1.6.6.2 nathanw * speak:
308 1.6.6.2 nathanw * .word MAGIC ! a NOP
309 1.6.6.2 nathanw * ba,a start !
310 1.6.6.2 nathanw * .skip 24 ! pad
311 1.6.6.2 nathanw * start:
312 1.6.6.2 nathanw */
313 1.6.6.2 nathanw
314 1.6.6.2 nathanw *size = sz;
315 1.6.6.2 nathanw return (bp + 0x74);
316 1.6.6.2 nathanw }
317 1.6.6.2 nathanw
318 1.6.6.2 nathanw static void
319 1.6.6.2 nathanw devread(fd, buf, blk, size, msg)
320 1.6.6.2 nathanw int fd;
321 1.6.6.2 nathanw void *buf;
322 1.6.6.2 nathanw daddr_t blk;
323 1.6.6.2 nathanw size_t size;
324 1.6.6.2 nathanw char *msg;
325 1.6.6.2 nathanw {
326 1.6.6.2 nathanw if (lseek(fd, dbtob(blk), SEEK_SET) != dbtob(blk))
327 1.6.6.2 nathanw err(1, "%s: devread: lseek", msg);
328 1.6.6.2 nathanw
329 1.6.6.2 nathanw if (read(fd, buf, size) != size)
330 1.6.6.2 nathanw err(1, "%s: devread: read", msg);
331 1.6.6.2 nathanw }
332 1.6.6.2 nathanw
333 1.6.6.2 nathanw int loadblocknums_contig(boot, devfd)
334 1.6.6.2 nathanw char *boot;
335 1.6.6.2 nathanw int devfd;
336 1.6.6.2 nathanw {
337 1.6.6.2 nathanw int size;
338 1.6.6.2 nathanw struct stat sb;
339 1.6.6.2 nathanw
340 1.6.6.2 nathanw if (stat(boot, &sb) == -1)
341 1.6.6.2 nathanw err(1, "stat: %s", boot);
342 1.6.6.2 nathanw size = sb.st_size;
343 1.6.6.2 nathanw
344 1.6.6.2 nathanw if (verbose) {
345 1.6.6.2 nathanw printf("%s: blockstart %d\n", dev, conblockstart);
346 1.6.6.2 nathanw printf("%s: size %d\n", boot, size);
347 1.6.6.2 nathanw }
348 1.6.6.2 nathanw
349 1.6.6.2 nathanw *block_size_p = roundup(size, 512);
350 1.6.6.2 nathanw *block_count_p = 1;
351 1.6.6.2 nathanw *entry_point_p = DEFAULT_ENTRY;
352 1.6.6.2 nathanw
353 1.6.6.2 nathanw block_table[0] = conblockstart;
354 1.6.6.2 nathanw
355 1.6.6.2 nathanw return 0;
356 1.6.6.2 nathanw }
357 1.6.6.2 nathanw
358 1.6.6.2 nathanw static char sblock[SBSIZE];
359 1.6.6.2 nathanw
360 1.6.6.2 nathanw int
361 1.6.6.2 nathanw loadblocknums_ffs(boot, devfd)
362 1.6.6.2 nathanw char *boot;
363 1.6.6.2 nathanw int devfd;
364 1.6.6.2 nathanw {
365 1.6.6.2 nathanw int i, fd;
366 1.6.6.2 nathanw struct stat statbuf;
367 1.6.6.2 nathanw struct statfs statfsbuf;
368 1.6.6.2 nathanw struct fs *fs;
369 1.6.6.2 nathanw char *buf;
370 1.6.6.2 nathanw daddr_t blk, *ap;
371 1.6.6.2 nathanw struct dinode *ip;
372 1.6.6.2 nathanw int ndb;
373 1.6.6.2 nathanw
374 1.6.6.2 nathanw /*
375 1.6.6.2 nathanw * Open 2nd-level boot program and record the block numbers
376 1.6.6.2 nathanw * it occupies on the filesystem represented by `devfd'.
377 1.6.6.2 nathanw */
378 1.6.6.2 nathanw if ((fd = open(boot, O_RDONLY)) < 0)
379 1.6.6.2 nathanw err(1, "open: %s", boot);
380 1.6.6.2 nathanw
381 1.6.6.2 nathanw if (fstatfs(fd, &statfsbuf) != 0)
382 1.6.6.2 nathanw err(1, "statfs: %s", boot);
383 1.6.6.2 nathanw
384 1.6.6.2 nathanw if (strncmp(statfsbuf.f_fstypename, "ffs", MFSNAMELEN) &&
385 1.6.6.2 nathanw strncmp(statfsbuf.f_fstypename, "ufs", MFSNAMELEN)) {
386 1.6.6.2 nathanw errx(1, "%s: must be on an FFS filesystem", boot);
387 1.6.6.2 nathanw }
388 1.6.6.2 nathanw
389 1.6.6.2 nathanw if (fsync(fd) != 0)
390 1.6.6.2 nathanw err(1, "fsync: %s", boot);
391 1.6.6.2 nathanw
392 1.6.6.2 nathanw if (fstat(fd, &statbuf) != 0)
393 1.6.6.2 nathanw err(1, "fstat: %s", boot);
394 1.6.6.2 nathanw
395 1.6.6.2 nathanw close(fd);
396 1.6.6.2 nathanw
397 1.6.6.2 nathanw /* Read superblock */
398 1.6.6.2 nathanw devread(devfd, sblock, btodb(SBOFF), SBSIZE, "superblock");
399 1.6.6.2 nathanw fs = (struct fs *)sblock;
400 1.6.6.2 nathanw
401 1.6.6.2 nathanw /* Read inode */
402 1.6.6.2 nathanw if ((buf = malloc(fs->fs_bsize)) == NULL)
403 1.6.6.2 nathanw errx(1, "No memory for filesystem block");
404 1.6.6.2 nathanw
405 1.6.6.2 nathanw blk = fsbtodb(fs, ino_to_fsba(fs, statbuf.st_ino));
406 1.6.6.2 nathanw devread(devfd, buf, blk, fs->fs_bsize, "inode");
407 1.6.6.2 nathanw ip = (struct dinode *)(buf) + ino_to_fsbo(fs, statbuf.st_ino);
408 1.6.6.2 nathanw
409 1.6.6.2 nathanw /*
410 1.6.6.2 nathanw * Register filesystem block size.
411 1.6.6.2 nathanw */
412 1.6.6.2 nathanw *block_size_p = fs->fs_bsize;
413 1.6.6.2 nathanw
414 1.6.6.2 nathanw /*
415 1.6.6.2 nathanw * Get the block numbers; we don't handle fragments
416 1.6.6.2 nathanw */
417 1.6.6.2 nathanw ndb = howmany(ip->di_size, fs->fs_bsize);
418 1.6.6.2 nathanw if (ndb > max_block_count)
419 1.6.6.2 nathanw errx(1, "%s: Too many blocks", boot);
420 1.6.6.2 nathanw
421 1.6.6.2 nathanw /*
422 1.6.6.2 nathanw * Register block count.
423 1.6.6.2 nathanw */
424 1.6.6.2 nathanw *block_count_p = ndb;
425 1.6.6.2 nathanw
426 1.6.6.2 nathanw /*
427 1.6.6.2 nathanw * Register entry point.
428 1.6.6.2 nathanw */
429 1.6.6.2 nathanw *entry_point_p = DEFAULT_ENTRY;
430 1.6.6.2 nathanw if (verbose)
431 1.6.6.2 nathanw printf("entry point: 0x%08x\n", *entry_point_p);
432 1.6.6.2 nathanw
433 1.6.6.2 nathanw if (verbose)
434 1.6.6.2 nathanw printf("%s: block numbers: ", boot);
435 1.6.6.2 nathanw ap = ip->di_db;
436 1.6.6.2 nathanw for (i = 0; i < NDADDR && *ap && ndb; i++, ap++, ndb--) {
437 1.6.6.2 nathanw blk = fsbtodb(fs, *ap);
438 1.6.6.2 nathanw block_table[i] = blk;
439 1.6.6.2 nathanw if (verbose)
440 1.6.6.2 nathanw printf("%d ", blk);
441 1.6.6.2 nathanw }
442 1.6.6.2 nathanw if (verbose)
443 1.6.6.2 nathanw printf("\n");
444 1.6.6.2 nathanw
445 1.6.6.2 nathanw if (ndb == 0)
446 1.6.6.2 nathanw return 0;
447 1.6.6.2 nathanw
448 1.6.6.2 nathanw /*
449 1.6.6.2 nathanw * Just one level of indirections; there isn't much room
450 1.6.6.2 nathanw * for more in the 1st-level bootblocks anyway.
451 1.6.6.2 nathanw */
452 1.6.6.2 nathanw if (verbose)
453 1.6.6.2 nathanw printf("%s: block numbers (indirect): ", boot);
454 1.6.6.2 nathanw blk = ip->di_ib[0];
455 1.6.6.2 nathanw devread(devfd, buf, blk, fs->fs_bsize, "indirect block");
456 1.6.6.2 nathanw ap = (daddr_t *)buf;
457 1.6.6.2 nathanw for (; i < NINDIR(fs) && *ap && ndb; i++, ap++, ndb--) {
458 1.6.6.2 nathanw blk = fsbtodb(fs, *ap);
459 1.6.6.2 nathanw block_table[i] = blk;
460 1.6.6.2 nathanw if (verbose)
461 1.6.6.2 nathanw printf("%d ", blk);
462 1.6.6.2 nathanw }
463 1.6.6.2 nathanw if (verbose)
464 1.6.6.2 nathanw printf("\n");
465 1.6.6.2 nathanw
466 1.6.6.2 nathanw if (ndb)
467 1.6.6.2 nathanw errx(1, "%s: Too many blocks", boot);
468 1.6.6.2 nathanw return 0;
469 1.6.6.2 nathanw }
470 1.6.6.2 nathanw
471 1.6.6.2 nathanw int
472 1.6.6.2 nathanw writeapplepartmap(fd)
473 1.6.6.2 nathanw int fd;
474 1.6.6.2 nathanw {
475 1.6.6.2 nathanw struct drvr_map dm;
476 1.6.6.2 nathanw struct partmapentry pme;
477 1.6.6.2 nathanw
478 1.6.6.2 nathanw /* block 0 */
479 1.6.6.2 nathanw if (lseek(fd, 0, SEEK_SET) != 0)
480 1.6.6.2 nathanw return -1;
481 1.6.6.2 nathanw if (read(fd, &dm, 512) != 512) /* read existing disklabel */
482 1.6.6.2 nathanw return -1;
483 1.6.6.2 nathanw if (lseek(fd, 0, SEEK_SET) != 0)
484 1.6.6.2 nathanw return -1;
485 1.6.6.2 nathanw
486 1.6.6.2 nathanw dm.sbSig = DRIVER_MAP_MAGIC;
487 1.6.6.2 nathanw dm.sbBlockSize = 512;
488 1.6.6.2 nathanw dm.sbBlkCount = 0;
489 1.6.6.2 nathanw
490 1.6.6.2 nathanw if (write(fd, &dm, 512) != 512)
491 1.6.6.2 nathanw return -1;
492 1.6.6.2 nathanw
493 1.6.6.2 nathanw /* block 1: Apple Partition Map */
494 1.6.6.2 nathanw memset(&pme, 0, sizeof(pme));
495 1.6.6.2 nathanw pme.pmSig = DPME_MAGIC;
496 1.6.6.2 nathanw pme.pmMapBlkCnt = 2;
497 1.6.6.2 nathanw pme.pmPyPartStart = 1;
498 1.6.6.2 nathanw pme.pmPartBlkCnt = pme.pmDataCnt = 2;
499 1.6.6.2 nathanw strcpy(pme.pmPartName, "Apple");
500 1.6.6.2 nathanw strcpy(pme.pmPartType, "Apple_partition_map");
501 1.6.6.2 nathanw
502 1.6.6.2 nathanw pme.pmPartStatus = 0x37;
503 1.6.6.2 nathanw
504 1.6.6.2 nathanw if (lseek(fd, 512, SEEK_SET) != 512)
505 1.6.6.2 nathanw return -1;
506 1.6.6.2 nathanw if (write(fd, &pme, 512) != 512)
507 1.6.6.2 nathanw return -1;
508 1.6.6.2 nathanw
509 1.6.6.2 nathanw /* block 2: NetBSD partition */
510 1.6.6.2 nathanw memset(&pme, 0, sizeof(pme));
511 1.6.6.2 nathanw pme.pmSig = DPME_MAGIC;
512 1.6.6.2 nathanw pme.pmMapBlkCnt = 2;
513 1.6.6.2 nathanw pme.pmPyPartStart = 4;
514 1.6.6.2 nathanw pme.pmPartBlkCnt = pme.pmDataCnt = 0x7fffffff;
515 1.6.6.2 nathanw strcpy(pme.pmPartName, "NetBSD");
516 1.6.6.2 nathanw strcpy(pme.pmPartType, "NetBSD/macppc");
517 1.6.6.2 nathanw pme.pmPartStatus = 0x3b;
518 1.6.6.2 nathanw pme.pmBootSize = 0x400;
519 1.6.6.2 nathanw pme.pmBootLoad = 0x4000;
520 1.6.6.2 nathanw pme.pmBootEntry = 0x4000;
521 1.6.6.2 nathanw strcpy(pme.pmProcessor, "PowerPC");
522 1.6.6.2 nathanw
523 1.6.6.2 nathanw if (lseek(fd, 1024, SEEK_SET) != 1024)
524 1.6.6.2 nathanw return -1;
525 1.6.6.2 nathanw if (write(fd, &pme, 512) != 512)
526 1.6.6.2 nathanw return -1;
527 1.6.6.2 nathanw
528 1.6.6.2 nathanw return 0;
529 1.6.6.2 nathanw }
530