1 /* $NetBSD: installboot.c,v 1.7 2009/03/14 21:04:13 dsl Exp $ */
4 * Copyright (c) 2000 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
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.
40 #include <sys/param.h>
42 #include <sys/disklabel.h>
45 #define VERBOSE(msg) if (verbose) \
47 #define FATAL(a1,a2) errx(EXIT_FAILURE, a1, a2)
48 #define FATALIO(a1,a2) err(EXIT_FAILURE, a1, a2)
50 #define BOOTBLOCK_NUMBER 2
51 #define BOOTBLOCK_OFFSET BOOTBLOCK_NUMBER*DEV_BSIZE
52 #define DEFAULT_BOOTFILE "boot"
54 static void usage(void);
55 static void do_list(const char *);
56 static void do_remove(const char *, const char *);
57 static void do_install(const char *, const char *, const char *);
58 static int mipsvh_cksum(struct mips_volheader
*);
59 static void read_volheader(const char *, struct mips_volheader
*);
60 static void write_volheader(const char *, struct mips_volheader
*);
61 static struct mips_voldir
*voldir_findfile(struct mips_volheader
*,
70 fprintf(stderr
, "usage:\n");
71 fprintf(stderr
, "\t%s [-nv] disk bootstrap [name]\n", getprogname());
72 fprintf(stderr
, "\t%s -r [-nv] disk [name]\n", getprogname());
73 fprintf(stderr
, "\t%s -l [-nv] disk\n", getprogname());
78 main(int argc
, char *argv
[])
83 rflag
= lflag
= verbose
= nowrite
= 0;
85 while ((c
= getopt(argc
, argv
, "lnrv")) != -1) {
88 /* List volume directory contents */
92 /* Disable write of boot sectors */
96 /* Clear any existing boot block */
111 if ((lflag
&& rflag
) || argc
< 1 || (lflag
&& argc
!= 1) ||
112 (rflag
&& argc
> 3) || argc
> 4)
120 do_remove(disk
, argc
==2?argv
[1]:DEFAULT_BOOTFILE
);
122 do_install(disk
, argv
[1], argc
==3?argv
[2]:DEFAULT_BOOTFILE
);
128 do_list(const char *disk
)
130 struct mips_volheader vh
;
131 struct mips_voldir
*vdp
;
134 read_volheader(disk
, &vh
);
136 printf("Slot\t LBN\tLength\tFilename\n");
137 printf("------------------------------------------\n");
138 for (i
=0, vdp
=vh
.vh_voldir
; i
<MIPS_NVOLDIR
; i
++, vdp
++)
140 printf("%2d:\t%5d\t%6d\t%s\n", i
, vdp
->vd_lba
,
141 vdp
->vd_len
, vdp
->vd_name
);
145 do_remove(const char *disk
, const char *filename
)
147 struct mips_volheader vh
;
148 struct mips_voldir
*vdp
;
150 read_volheader(disk
, &vh
);
151 vdp
= voldir_findfile(&vh
, filename
, 0);
153 FATAL("%s: file not found", disk
);
155 memset(vdp
, 0, sizeof(*vdp
));
157 /* Update volume header */
158 write_volheader(disk
, &vh
);
162 do_install(const char *disk
, const char *bootstrap
, const char *bootname
)
164 struct stat bootstrapsb
;
165 struct mips_volheader vh
;
166 struct mips_voldir
*vdp
;
172 /* Open the input file and check it out */
173 if ((fd
= open(bootstrap
, O_RDONLY
)) == -1)
174 FATALIO("open %s", bootstrap
);
175 if (fstat(fd
, &bootstrapsb
) == -1)
176 FATALIO("fstat %s", bootstrap
);
177 if (!S_ISREG(bootstrapsb
.st_mode
))
178 FATAL("%s must be a regular file", bootstrap
);
180 boot_size
= roundup(bootstrapsb
.st_size
, DEV_BSIZE
);
182 if (boot_size
> 8192-1024)
183 FATAL("bootstrap program too large (%d bytes)", boot_size
);
185 boot_code
= malloc(boot_size
);
186 if (boot_code
== NULL
)
187 FATAL("malloc %d bytes failed", boot_size
);
188 memset(boot_code
, 0, boot_size
);
190 /* read the file into the buffer */
191 len
= read(fd
, boot_code
, bootstrapsb
.st_size
);
193 FATALIO("read %s", bootstrap
);
194 else if (len
!= bootstrapsb
.st_size
)
195 FATAL("read %s: short read", bootstrap
);
198 read_volheader(disk
, &vh
);
200 vdp
= voldir_findfile(&vh
, bootname
, 1);
202 FATAL("%s: volume directory full", disk
);
204 strcpy(vdp
->vd_name
, bootname
);
205 vdp
->vd_lba
= BOOTBLOCK_NUMBER
;
206 vdp
->vd_len
= bootstrapsb
.st_size
;
210 fprintf(stderr
, "not writing\n");
215 fprintf(stderr
, "writing bootstrap (%d bytes at logical block %d)\n",
218 /* Write bootstrap */
219 if ((fd
= open(disk
, O_WRONLY
)) == -1)
220 FATALIO("open %s", bootstrap
);
221 len
= pwrite(fd
, boot_code
, boot_size
, BOOTBLOCK_OFFSET
);
223 FATAL("write %s", disk
);
224 if (len
!= boot_size
)
225 FATAL("write %s: short write", disk
);
228 /* Update volume header */
229 write_volheader(disk
, &vh
);
233 read_volheader(const char *disk
, struct mips_volheader
*vhp
)
238 if ((vfd
= open(disk
, O_RDONLY
)) == -1)
239 FATALIO("open %s", disk
);
241 len
= pread(vfd
, vhp
, sizeof(*vhp
), MIPS_VHSECTOR
*DEV_BSIZE
);
246 FATALIO("read %s", disk
);
247 if (len
!= sizeof(*vhp
))
248 FATAL("read %s: short read", disk
);
250 /* Check volume header magic */
251 if (vhp
->vh_magic
!= MIPS_VHMAGIC
)
252 FATAL("%s: no volume header", disk
);
254 /* check volume header checksum */
255 if (mipsvh_cksum(vhp
))
256 FATAL("%s: volume header corrupted", disk
);
260 write_volheader(const char *disk
, struct mips_volheader
*vhp
)
265 /* update volume header checksum */
267 vhp
->vh_cksum
= -mipsvh_cksum(vhp
);
269 if ((vfd
= open(disk
, O_WRONLY
)) == -1)
270 FATALIO("open %s", disk
);
273 fprintf(stderr
, "%s: writing volume header\n", disk
);
275 len
= pwrite(vfd
, vhp
, sizeof(*vhp
), MIPS_VHSECTOR
*512); /* XXX */
277 FATALIO("write %s", disk
);
278 if (len
!= sizeof(*vhp
))
279 FATAL("write %s: short write", disk
);
285 * Compute checksum for MIPS disk volume header
287 * Mips volume header checksum is the 32bit 2's complement sum
288 * of the entire volume header structure
291 mipsvh_cksum(struct mips_volheader
*vhp
)
297 i
= sizeof(*vhp
) / sizeof(*ptr
);
305 * Locate the volume directory slot that matches a filename
307 * If the file entry cannot be found and create is non-zero the next
308 * empty slot is returned, otherwise return NULL
310 static struct mips_voldir
*
311 voldir_findfile(struct mips_volheader
*vhp
, const char *file
, int create
)
312 /* create: return unused entry if not found */
314 struct mips_voldir
*vdp
= vhp
->vh_voldir
;
317 for (i
=0; i
<MIPS_NVOLDIR
; i
++, vdp
++) {
318 if (strcmp(vdp
->vd_name
, file
) == 0)
322 vdp
= vhp
->vh_voldir
;
323 for (i
=0; i
<MIPS_NVOLDIR
; i
++, vdp
++)
324 if (vdp
->vd_len
== 0)