1 /* $NetBSD: pmax.c,v 1.14 2009/04/05 11:55:39 lukem Exp $ */
4 * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * This code is derived from software contributed to The NetBSD Foundation
11 * by Luke Mewburn of Wasabi Systems.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
22 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
36 * Copyright (c) 1999 Ross Harvey. All rights reserved.
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement:
48 * This product includes software developed by Ross Harvey
49 * for the NetBSD Project.
50 * 4. The name of the author may not be used to endorse or promote products
51 * derived from this software without specific prior written permission
53 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
54 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
55 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
56 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
57 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
58 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
59 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
60 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
61 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
62 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
66 * Copyright (c) 1999 Christopher G. Demetriou. All rights reserved.
68 * Redistribution and use in source and binary forms, with or without
69 * modification, are permitted provided that the following conditions
71 * 1. Redistributions of source code must retain the above copyright
72 * notice, this list of conditions and the following disclaimer.
73 * 2. Redistributions in binary form must reproduce the above copyright
74 * notice, this list of conditions and the following disclaimer in the
75 * documentation and/or other materials provided with the distribution.
76 * 3. All advertising materials mentioning features or use of this software
77 * must display the following acknowledgement:
78 * This product includes software developed by Christopher G. Demetriou
79 * for the NetBSD Project.
80 * 4. The name of the author may not be used to endorse or promote products
81 * derived from this software without specific prior written permission
83 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
84 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
85 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
86 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
87 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
88 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
89 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
90 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
91 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
92 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
95 #if HAVE_NBTOOL_CONFIG_H
96 #include "nbtool_config.h"
99 #include <sys/cdefs.h>
101 __RCSID("$NetBSD: pmax.c,v 1.14 2009/04/05 11:55:39 lukem Exp $");
104 #include <sys/param.h>
114 #include <sys/exec_elf.h>
116 #include "installboot.h"
118 static int load_bootstrap(ib_params
*, char **,
119 uint32_t *, uint32_t *, size_t *);
121 static int pmax_clearboot(ib_params
*);
122 static int pmax_setboot(ib_params
*);
124 struct ib_mach ib_mach_pmax
=
125 { "pmax", pmax_setboot
, pmax_clearboot
, no_editboot
,
126 IB_STAGE1START
| IB_APPEND
| IB_SUNSUM
};
130 pmax_clearboot(ib_params
*params
)
132 struct pmax_boot_block bb
;
135 assert(params
!= NULL
);
136 assert(params
->fsfd
!= -1);
137 assert(params
->filesystem
!= NULL
);
138 assert(sizeof(struct pmax_boot_block
) == PMAX_BOOT_BLOCK_BLOCKSIZE
);
140 rv
= pread(params
->fsfd
, &bb
, sizeof(bb
), PMAX_BOOT_BLOCK_OFFSET
);
142 warn("Reading `%s'", params
->filesystem
);
144 } else if (rv
!= sizeof(bb
)) {
145 warnx("Reading `%s': short read", params
->filesystem
);
149 if (le32toh(bb
.magic
) != PMAX_BOOT_MAGIC
) {
151 "Old boot block magic number invalid; boot block invalid");
155 bb
.map
[0].num_blocks
= bb
.map
[0].start_block
= bb
.mode
= 0;
156 bb
.magic
= htole32(PMAX_BOOT_MAGIC
);
158 if (params
->flags
& IB_SUNSUM
) {
161 sum
= compute_sunsum((uint16_t *)&bb
);
162 if (! set_sunsum(params
, (uint16_t *)&bb
, sum
))
166 if (params
->flags
& IB_VERBOSE
)
167 printf("%slearing boot block\n",
168 (params
->flags
& IB_NOWRITE
) ? "Not c" : "C");
169 if (params
->flags
& IB_NOWRITE
)
172 rv
= pwrite(params
->fsfd
, &bb
, sizeof(bb
), PMAX_BOOT_BLOCK_OFFSET
);
174 warn("Writing `%s'", params
->filesystem
);
176 } else if (rv
!= sizeof(bb
)) {
177 warnx("Writing `%s': short write", params
->filesystem
);
185 pmax_setboot(ib_params
*params
)
187 struct pmax_boot_block bb
;
191 size_t bootstrapsize
;
192 uint32_t bootstrapload
, bootstrapexec
;
195 assert(params
!= NULL
);
196 assert(params
->fsfd
!= -1);
197 assert(params
->filesystem
!= NULL
);
198 assert(params
->s1fd
!= -1);
199 assert(params
->stage1
!= NULL
);
200 assert(sizeof(struct pmax_boot_block
) == PMAX_BOOT_BLOCK_BLOCKSIZE
);
205 if (! load_bootstrap(params
, &bootstrapbuf
, &bootstrapload
,
206 &bootstrapexec
, &bootstrapsize
))
209 rv
= pread(params
->fsfd
, &bb
, sizeof(bb
), PMAX_BOOT_BLOCK_OFFSET
);
211 warn("Reading `%s'", params
->filesystem
);
213 } else if (rv
!= sizeof(bb
)) {
214 warnx("Reading `%s': short read", params
->filesystem
);
218 /* fill in the updated boot block fields */
219 if (params
->flags
& IB_APPEND
) {
220 if (! S_ISREG(params
->fsstat
.st_mode
)) {
222 "`%s' must be a regular file to append a bootstrap",
226 startblock
= howmany(params
->fsstat
.st_size
,
227 PMAX_BOOT_BLOCK_BLOCKSIZE
);
228 } else if (params
->flags
& IB_STAGE1START
) {
229 startblock
= params
->s1start
;
231 startblock
= PMAX_BOOT_BLOCK_OFFSET
/ PMAX_BOOT_BLOCK_BLOCKSIZE
235 bb
.map
[0].start_block
= htole32(startblock
);
236 bb
.map
[0].num_blocks
=
237 htole32(howmany(bootstrapsize
, PMAX_BOOT_BLOCK_BLOCKSIZE
));
238 bb
.magic
= htole32(PMAX_BOOT_MAGIC
);
239 bb
.load_addr
= htole32(bootstrapload
);
240 bb
.exec_addr
= htole32(bootstrapexec
);
241 bb
.mode
= htole32(PMAX_BOOTMODE_CONTIGUOUS
);
243 if (params
->flags
& IB_SUNSUM
) {
246 sum
= compute_sunsum((uint16_t *)&bb
);
247 if (! set_sunsum(params
, (uint16_t *)&bb
, sum
))
251 if (params
->flags
& IB_VERBOSE
) {
252 printf("Bootstrap start sector: %u\n",
253 le32toh(bb
.map
[0].start_block
));
254 printf("Bootstrap sector count: %u\n",
255 le32toh(bb
.map
[0].num_blocks
));
256 printf("Bootstrap load address: %#x\n",
257 le32toh(bb
.load_addr
));
258 printf("Bootstrap exec address: %#x\n",
259 le32toh(bb
.exec_addr
));
260 printf("%sriting bootstrap\n",
261 (params
->flags
& IB_NOWRITE
) ? "Not w" : "W");
263 if (params
->flags
& IB_NOWRITE
) {
267 rv
= pwrite(params
->fsfd
, bootstrapbuf
, bootstrapsize
,
268 startblock
* PMAX_BOOT_BLOCK_BLOCKSIZE
);
270 warn("Writing `%s'", params
->filesystem
);
272 } else if ((size_t)rv
!= bootstrapsize
) {
273 warnx("Writing `%s': short write", params
->filesystem
);
277 if (params
->flags
& IB_VERBOSE
)
278 printf("Writing boot block\n");
279 rv
= pwrite(params
->fsfd
, &bb
, sizeof(bb
), PMAX_BOOT_BLOCK_OFFSET
);
281 warn("Writing `%s'", params
->filesystem
);
283 } else if (rv
!= sizeof(bb
)) {
284 warnx("Writing `%s': short write", params
->filesystem
);
297 #define MAX_SEGMENTS 10 /* We can load up to 10 segments */
306 load_bootstrap(ib_params
*params
, char **data
,
307 uint32_t *loadaddr
, uint32_t *execaddr
, size_t *len
)
310 Elf32_Addr lowaddr
, highaddr
;
313 struct seglist seglist
[MAX_SEGMENTS
];
315 if ((pread(params
->s1fd
, &ehdr
, sizeof(ehdr
), 0)) != sizeof(ehdr
)) {
316 warn("Reading `%s'", params
->stage1
);
319 if ((memcmp(ehdr
.e_ident
, ELFMAG
, SELFMAG
) != 0) ||
320 (ehdr
.e_ident
[EI_CLASS
] != ELFCLASS32
)) {
321 warnx("No ELF header in `%s'", params
->stage1
);
325 nsegs
= highaddr
= 0;
326 lowaddr
= (uint32_t) ULONG_MAX
;
328 for (i
= 0; i
< le16toh(ehdr
.e_phnum
); i
++) {
329 if (pread(params
->s1fd
, &phdr
, sizeof(phdr
),
330 (off_t
) le32toh(ehdr
.e_phoff
) + i
* sizeof(phdr
))
332 warn("Reading `%s'", params
->stage1
);
335 if (le32toh(phdr
.p_type
) != PT_LOAD
)
338 seglist
[nsegs
].addr
= le32toh(phdr
.p_paddr
);
339 seglist
[nsegs
].f_offset
= le32toh(phdr
.p_offset
);
340 seglist
[nsegs
].f_size
= le32toh(phdr
.p_filesz
);
343 if (le32toh(phdr
.p_paddr
) < lowaddr
)
344 lowaddr
= le32toh(phdr
.p_paddr
);
345 if (le32toh(phdr
.p_paddr
) + le32toh(phdr
.p_filesz
) > highaddr
)
346 highaddr
= le32toh(phdr
.p_paddr
) +
347 le32toh(phdr
.p_filesz
);
351 *execaddr
= le32toh(ehdr
.e_entry
);
352 *len
= roundup(highaddr
- lowaddr
, PMAX_BOOT_BLOCK_BLOCKSIZE
);
353 if ((*data
= malloc(*len
)) == NULL
) {
354 warn("Allocating %lu bytes", (unsigned long) *len
);
358 /* Now load the bootstrap into memory */
359 for (i
= 0; i
< nsegs
; i
++) {
360 if ((Elf32_Word
)pread(params
->s1fd
,
361 *data
+ seglist
[i
].addr
- lowaddr
,
362 seglist
[i
].f_size
, (off_t
)seglist
[i
].f_offset
)
363 != seglist
[i
].f_size
) {
364 warn("Reading `%s'", params
->stage1
);