]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - usr.sbin/boot98cfg/boot98cfg.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / usr.sbin / boot98cfg / boot98cfg.c
1 /*
2  * Copyright (c) KATO Takenori, 2000.
3  * 
4  * All rights reserved.  Unpublished rights reserved under the copyright
5  * laws of Japan.
6  * 
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer as
13  *    the first lines of this file unmodified.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. The name of the author may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission.
19  * 
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 /*
33  * Copyright (c) 1999 Robert Nordier
34  * All rights reserved.
35  *
36  * Redistribution and use in source and binary forms, with or without
37  * modification, are permitted provided that the following conditions
38  * are met:
39  * 1. Redistributions of source code must retain the above copyright
40  *    notice, this list of conditions and the following disclaimer.
41  * 2. Redistributions in binary form must reproduce the above copyright
42  *    notice, this list of conditions and the following disclaimer in the
43  *    documentation and/or other materials provided with the distribution.
44  *
45  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS``AS IS'' AND
46  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
48  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
49  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
50  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
51  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
52  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
53  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
54  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
55  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56  */
57
58 #include <sys/cdefs.h>
59 __FBSDID("$FreeBSD$");
60
61 #include <sys/param.h>
62 #include <sys/diskpc98.h>
63 #include <sys/stat.h>
64
65 #include <err.h>
66 #include <errno.h>
67 #include <fcntl.h>
68 #include <libgeom.h>
69 #include <paths.h>
70 #include <stdio.h>
71 #include <stdlib.h>
72 #include <string.h>
73 #include <unistd.h>
74
75 #define BOOTSIZE                0x2000
76 #define IPLSIZE                 512             /* IPL size */
77 #define BOOTMENUSIZE            7168            /* Max HDD boot menu size */
78 #define BOOTMENUOFF             0x400
79
80 u_char  boot0buf[BOOTSIZE];
81 u_char  ipl[IPLSIZE];
82 u_char  menu[BOOTMENUSIZE];
83
84 static  int read_boot(const char *, u_char *);
85 static  int write_boot(const char *, u_char *);
86 static  char *mkrdev(const char *);
87 static  void usage(void);
88
89 /*
90  * Boot manager installation/configuration utility.
91  */
92 int
93 main(int argc, char *argv[])
94 {
95         char    *endptr;
96         const   char *iplpath = "/boot/boot0", *menupath = "/boot/boot0.5";
97         char    *iplbakpath = NULL, *menubakpath = NULL;
98         char    *disk;
99         int     B_flag = 0;
100         int     c;
101         int     fd1;
102         int     n;
103         int     secsize = 512;
104         int     v_flag = 0, version;
105
106         while ((c = getopt(argc, argv, "BF:f:i:m:s:v:")) != -1) {
107                 switch (c) {
108                 case 'B':
109                         B_flag = 1;
110                         break;
111                 case 'F':
112                         menubakpath = optarg;
113                         break;
114                 case 'f':
115                         iplbakpath = optarg;
116                         break;
117                 case 'i':
118                         iplpath = optarg;
119                         break;
120                 case 'm':
121                         menupath = optarg;
122                         break;
123                 case 's':
124                         secsize = strtol(optarg, &endptr, 0);
125                         if (errno || *optarg == '\0' || *endptr)
126                                 errx(1, "%s: Bad argument to -s option",
127                                     optarg);
128                         switch (secsize) {
129                         case 256:
130                         case 512:
131                         case 1024:
132                         case 2048:
133                                 break;
134                         default:
135                                 errx(1, "%s: unsupported sector size", optarg);
136                                 break;
137                         }
138                         break;
139                 case 'v':
140                         v_flag = 1;
141                         version = strtol(optarg, &endptr, 0);
142                         if (errno || *optarg == '\0' || *endptr ||
143                             version < 0 || version > 255)
144                                 errx(1, "%s: Bad argument to -v option",
145                                     optarg);
146                         break;
147                 default:
148                         usage();
149                         /* NOTREACHED */
150                         break;
151                 }
152         }
153         argc -= optind;
154         argv += optind;
155         if (argc != 1)
156                 usage();
157         disk = mkrdev(*argv);
158
159         read_boot(disk, boot0buf);
160
161         if (iplbakpath != NULL) {
162                 fd1 = open(iplbakpath, O_WRONLY | O_CREAT | O_TRUNC, 0666);
163                 if (fd1 < 0)
164                         err(1, "%s", iplbakpath);
165                 n = write(fd1, boot0buf, IPLSIZE);
166                 if (n == -1)
167                         err(1, "%s", iplbakpath);
168                 if (n != IPLSIZE)
169                         errx(1, "%s: short write", iplbakpath);
170                 close(fd1);
171         }
172
173         if (menubakpath != NULL) {
174                 fd1 = open(menubakpath, O_WRONLY | O_CREAT | O_TRUNC, 0666);
175                 if (fd1 < 0)
176                         err(1, "%s", menubakpath);
177                 n = write(fd1, boot0buf + BOOTMENUOFF, BOOTMENUSIZE);
178                 if (n == -1)
179                         err(1, "%s", menubakpath);
180                 if (n != BOOTMENUSIZE)
181                         errx(1, "%s: short write", menubakpath);
182                 close(fd1);
183         }
184
185         if (B_flag) {
186                 /* Read IPL (boot0). */
187                 fd1 = open(iplpath, O_RDONLY);
188                 if (fd1 < 0)
189                         err(1, "%s", disk);
190                 n = read(fd1, ipl, IPLSIZE);
191                 if (n < 0)
192                         err(1, "%s", iplpath);
193                 if (n != IPLSIZE)
194                         errx(1, "%s: invalid file", iplpath);
195                 close(fd1);
196
197                 /* Read HDD boot menu (boot0.5). */
198                 fd1 = open(menupath, O_RDONLY);
199                 if (fd1 < 0)
200                         err(1, "%s", disk);
201                 n = read(fd1, menu, BOOTMENUSIZE);
202                 if (n < 0)
203                         err(1, "%s", menupath);
204                 if (n != BOOTMENUSIZE)
205                         errx(1, "%s: invalid file", menupath);
206                 close(fd1);
207
208                 memcpy(boot0buf, ipl, IPLSIZE);
209                 memcpy(boot0buf + BOOTMENUOFF, menu, BOOTMENUSIZE);
210         }
211
212         /* Set version number field. */
213         if (v_flag)
214                 *(boot0buf + secsize - 4) = (u_char)version;
215
216         if (B_flag || v_flag)
217                 write_boot(disk, boot0buf);
218
219         return 0;
220 }
221
222 static int
223 read_boot(const char *disk, u_char *boot)
224 {
225         int fd, n;
226
227         /* Read IPL, partition table and HDD boot menu. */
228         fd = open(disk, O_RDONLY);
229         if (fd < 0)
230                 err(1, "%s", disk);
231         n = read(fd, boot, BOOTSIZE);
232         if (n != BOOTSIZE)
233                 errx(1, "%s: short read", disk);
234         close(fd);
235
236         return 0;
237 }
238
239 static int
240 write_boot(const char *disk, u_char *boot)
241 {
242         int fd, n, i;
243         char buf[MAXPATHLEN];
244         const char *q;
245         struct gctl_req *grq;
246
247         fd = open(disk, O_WRONLY, 0666);
248         if (fd != -1) {
249                 if ((n = write(fd, boot, BOOTSIZE)) < 0)
250                         err(1, "%s", disk);
251                 if (n != BOOTSIZE)
252                         errx(1, "%s: short write", disk);
253                 close(fd);
254                 return 0;
255         }
256
257         grq = gctl_get_handle();
258         gctl_ro_param(grq, "verb", -1, "write PC98");
259         gctl_ro_param(grq, "class", -1, "PC98");
260         q = strrchr(disk, '/');
261         if (q == NULL)
262                 q = disk;
263         else
264                 q++;
265         gctl_ro_param(grq, "geom", -1, q);
266         gctl_ro_param(grq, "data", BOOTSIZE, boot);
267         q = gctl_issue(grq);
268         if (q == NULL)
269                 return 0;
270
271         warnx("%s: %s", disk, q);
272         gctl_free(grq);
273
274         for (i = 0; i < PC98_NPARTS; i++) {
275                 snprintf(buf, sizeof(buf), "%ss%d", disk, i + 1);
276                 fd = open(buf, O_RDONLY);
277                 if (fd < 0)
278                         continue;
279                 n = ioctl(fd, DIOCSPC98, boot);
280                 if (n != 0)
281                         err(1, "%s: ioctl DIOCSPC98", disk);
282                 close(fd);
283                 return 0;
284         }
285
286         err(1, "%s", disk);
287 }
288
289 /*
290  * Produce a device path for a "canonical" name, where appropriate.
291  */
292 static char *
293 mkrdev(const char *fname)
294 {
295     char buf[MAXPATHLEN];
296     char *s;
297
298     if (!strchr(fname, '/')) {
299         snprintf(buf, sizeof(buf), "%s%s", _PATH_DEV, fname);
300         s = strdup(buf);
301     } else
302         s = strdup(fname);
303
304     if (s == NULL)
305         errx(1, "No more memory");
306     return s;
307 }
308
309 /*
310  * Display usage information.
311  */
312 static void
313 usage(void)
314 {
315         fprintf(stderr,
316             "boot98cfg [-B][-i boot0][-m boot0.5][-s secsize][-v version]\n"
317             "          [-f ipl.bak][-F menu.bak] disk\n");
318         exit(1);
319 }