1 /* $NetBSD: next68k.c,v 1.6 2009/04/05 11:55:39 lukem Exp $ */
4 * Copyright (c) 2003 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by David Laight and Christian Limpach.
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"
36 #include <sys/cdefs.h>
38 __RCSID("$NetBSD: next68k.c,v 1.6 2009/04/05 11:55:39 lukem Exp $");
41 #include <sys/param.h>
52 #include "installboot.h"
54 static uint16_t nextstep_checksum(const void *, const void *);
55 static int next68k_setboot(ib_params
*);
57 struct ib_mach ib_mach_next68k
=
58 { "next68k", next68k_setboot
, no_clearboot
, no_editboot
, 0};
61 nextstep_checksum(const void *vbuf
, const void *vlimit
)
63 const uint16_t *buf
= vbuf
;
64 const uint16_t *limit
= vlimit
;
68 sum
+= be16toh(*buf
++);
71 return (sum
& 0xffff);
75 next68k_setboot(ib_params
*params
)
77 int retval
, labelupdated
;
83 struct next68k_disklabel
*next68klabel
;
87 assert(params
!= NULL
);
88 assert(params
->fsfd
!= -1);
89 assert(params
->filesystem
!= NULL
);
90 assert(params
->s1fd
!= -1);
91 assert(params
->stage1
!= NULL
);
97 next68klabel
= malloc(NEXT68K_LABEL_SIZE
);
98 if (next68klabel
== NULL
) {
99 warn("Allocating %lu bytes", (unsigned long)NEXT68K_LABEL_SIZE
);
104 * Read in the next68k disklabel
106 rv
= pread(params
->fsfd
, next68klabel
, NEXT68K_LABEL_SIZE
,
107 NEXT68K_LABEL_SECTOR
* params
->sectorsize
+ NEXT68K_LABEL_OFFSET
);
109 warn("Reading `%s'", params
->filesystem
);
112 if (rv
!= NEXT68K_LABEL_SIZE
) {
113 warnx("Reading `%s': short read", params
->filesystem
);
116 if (be32toh(next68klabel
->cd_version
) == NEXT68K_LABEL_CD_V3
) {
117 checksum
= &next68klabel
->NEXT68K_LABEL_cd_v3_checksum
;
119 checksum
= &next68klabel
->cd_checksum
;
121 if (nextstep_checksum (next68klabel
, checksum
) !=
122 be16toh(*checksum
)) {
123 warn("Disklabel checksum invalid on `%s'",
128 cd_secsize
= be32toh(next68klabel
->cd_secsize
);
129 sec_netonb_mult
= (cd_secsize
/ params
->sectorsize
);
132 * Allocate a buffer, with space to round up the input file
133 * to the next block size boundary, and with space for the boot
136 bootsize
= roundup(params
->s1stat
.st_size
, cd_secsize
);
138 bootbuf
= malloc(bootsize
);
139 if (bootbuf
== NULL
) {
140 warn("Allocating %zu bytes", bootsize
);
143 memset(bootbuf
, 0, bootsize
);
146 * Read the file into the buffer.
148 rv
= pread(params
->s1fd
, bootbuf
, params
->s1stat
.st_size
, 0);
150 warn("Reading `%s'", params
->stage1
);
152 } else if (rv
!= params
->s1stat
.st_size
) {
153 warnx("Reading `%s': short read", params
->stage1
);
157 if (bootsize
> be16toh(next68klabel
->cd_front
) * cd_secsize
-
158 NEXT68K_LABEL_SIZE
) {
159 warnx("Boot program is larger than front porch space");
163 fp
= be16toh(next68klabel
->cd_front
);
164 b0
= be32toh(next68klabel
->cd_boot_blkno
[0]);
165 b1
= be32toh(next68klabel
->cd_boot_blkno
[1]);
171 if (((bootsize
/ cd_secsize
) > b1
- b0
) ||
172 ((bootsize
/ cd_secsize
) > fp
- b1
)) {
173 if (2 * bootsize
> (fp
* cd_secsize
- NEXT68K_LABEL_SIZE
))
174 /* can only fit one copy */
175 b0
= b1
= NEXT68K_LABEL_SIZE
/ cd_secsize
;
177 if (2 * bootsize
> (fp
* cd_secsize
-
178 NEXT68K_LABEL_DEFAULTBOOT0_1
*
180 /* can fit two copies starting after label */
181 b0
= NEXT68K_LABEL_SIZE
/ cd_secsize
;
183 /* can fit two copies starting at default 1 */
184 b0
= NEXT68K_LABEL_DEFAULTBOOT0_1
/
186 /* try to fit 2nd copy at default 2 */
187 b1
= NEXT68K_LABEL_DEFAULTBOOT0_2
/ sec_netonb_mult
;
190 if (bootsize
/ cd_secsize
> (fp
- b1
))
191 /* fit 2nd copy before front porch */
192 b1
= fp
- bootsize
/ cd_secsize
;
195 if (next68klabel
->cd_boot_blkno
[0] != (int32_t)htobe32(b0
)) {
196 next68klabel
->cd_boot_blkno
[0] = htobe32(b0
);
199 if (next68klabel
->cd_boot_blkno
[1] != (int32_t)htobe32(b1
)) {
200 next68klabel
->cd_boot_blkno
[1] = htobe32(b1
);
203 if (params
->flags
& IB_VERBOSE
)
204 printf("Boot programm locations%s: %d %d\n",
205 labelupdated
? " updated" : "", b0
* sec_netonb_mult
,
206 b1
* sec_netonb_mult
);
208 if (params
->flags
& IB_NOWRITE
) {
214 * Write the updated next68k disklabel
217 if (params
->flags
& IB_VERBOSE
)
218 printf ("Writing updated label\n");
219 *checksum
= htobe16(nextstep_checksum (next68klabel
,
221 rv
= pwrite(params
->fsfd
, next68klabel
, NEXT68K_LABEL_SIZE
,
222 NEXT68K_LABEL_SECTOR
* params
->sectorsize
+
223 NEXT68K_LABEL_OFFSET
);
225 warn("Writing `%s'", params
->filesystem
);
228 if (rv
!= NEXT68K_LABEL_SIZE
) {
229 warnx("Writing `%s': short write", params
->filesystem
);
234 b0
*= sec_netonb_mult
;
235 b1
*= sec_netonb_mult
;
238 * Write boot program to locations b0 and b1 (if different).
241 if (params
->flags
& IB_VERBOSE
)
242 printf ("Writing boot program at %d\n", b0
);
243 rv
= pwrite(params
->fsfd
, bootbuf
, bootsize
,
244 b0
* params
->sectorsize
);
246 warn("Writing `%s' at %d", params
->filesystem
, b0
);
249 if ((size_t)rv
!= bootsize
) {
250 warnx("Writing `%s' at %d: short write",
251 params
->filesystem
, b0
);