boot98cfg.c revision 78715
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 * $FreeBSD: head/usr.sbin/boot98cfg/boot98cfg.c 78715 2001-06-24 18:51:40Z dd $ 32 */ 33 34/* 35 * Copyright (c) 1999 Robert Nordier 36 * All rights reserved. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 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 * 47 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS``AS IS'' AND 48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 50 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 51 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 52 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 53 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 54 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 55 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 56 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 57 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 58 */ 59 60#include <sys/param.h> 61#include <sys/stat.h> 62 63#include <err.h> 64#include <errno.h> 65#include <fcntl.h> 66#include <paths.h> 67#include <stdio.h> 68#include <stdlib.h> 69#include <string.h> 70#include <unistd.h> 71 72#define IPLSIZE 512 /* IPL size */ 73#define BOOTMENUSIZE 7168 /* Max HDD boot menu size */ 74#define BOOTMENUOFF 0x400 75 76static char *mkrdev(char *); 77static void usage(void); 78 79u_char boot0buf[0x2000]; 80char ipl[IPLSIZE]; 81char menu[BOOTMENUSIZE]; 82 83/* 84 * Produce a device path for a "canonical" name, where appropriate. 85 */ 86static char * 87mkrdev(char *fname) 88{ 89 char buf[MAXPATHLEN]; 90 struct stat sb; 91 char *s; 92 93 s = (char *)fname; 94 if (!strchr(fname, '/')) { 95 snprintf(buf, sizeof(buf), "%sr%s", _PATH_DEV, fname); 96 if (stat(buf, &sb)) 97 snprintf(buf, sizeof(buf), "%s%s", _PATH_DEV, fname); 98 if (!(s = strdup(buf))) 99 err(1, NULL); 100 } 101 return s; 102} 103 104static void 105usage(void) 106{ 107 fprintf(stderr, 108 "boot98cfg [-B][-i boot0][-m boot0.5][-s secsize][-v version]\n" 109 " [-f ipl.bak][-F menu.bak] disk\n"); 110 exit(1); 111} 112 113int 114main(int argc, char *argv[]) 115{ 116 char *endptr; 117 const char *iplpath = "/boot/boot0", *menupath = "/boot/boot0.5"; 118 char *iplbakpath = NULL, *menubakpath = NULL; 119 char *disk; 120 int B_flag = 0; 121 int c; 122 int fd, fd1; 123 int n; 124 int secsize = 512; 125 int v_flag = 0, version; 126 127 while ((c = getopt(argc, argv, "BF:f:i:m:s:v:")) != -1) { 128 switch (c) { 129 case 'B': 130 B_flag = 1; 131 break; 132 case 'F': 133 menubakpath = optarg; 134 break; 135 case 'f': 136 iplbakpath = optarg; 137 break; 138 case 'i': 139 iplpath = optarg; 140 break; 141 case 'm': 142 menupath = optarg; 143 break; 144 case 's': 145 secsize = strtol(optarg, &endptr, 0); 146 if (errno || *optarg == NULL || *endptr) 147 errx(1, "%s: Bad argument to -s option", 148 optarg); 149 switch (secsize) { 150 case 256: 151 case 512: 152 case 1024: 153 case 2048: 154 break; 155 default: 156 errx(1, "%s: unsupported sector size", optarg); 157 break; 158 } 159 break; 160 case 'v': 161 v_flag = 1; 162 version = strtol(optarg, &endptr, 0); 163 if (errno || *optarg == NULL || *endptr || 164 version < 0 || version > 255) 165 errx(1, "%s: Bad argument to -s option", 166 optarg); 167 break; 168 default: 169 usage(); 170 /* NOTREACHED */ 171 break; 172 } 173 } 174 argc -= optind; 175 argv += optind; 176 if (argc != 1) 177 usage(); 178 disk = mkrdev(*argv); 179 180 /* Read IPL, partition table and HDD boot menu. */ 181 fd = open(disk, O_RDWR); 182 if (fd < 0) 183 err(1, "%s", disk); 184 n = read(fd, boot0buf, 0x2000); 185 if (n != 0x2000) 186 errx(1, "%s: short read", disk); 187 if (!B_flag && !v_flag) 188 close(fd); 189 190 if (iplbakpath != NULL) { 191 fd1 = open(iplbakpath, O_WRONLY | O_CREAT | O_TRUNC, 0666); 192 if (fd1 < 0) 193 err(1, "%s", iplbakpath); 194 n = write(fd1, boot0buf, IPLSIZE); 195 if (n == -1) 196 err(1, "%s", iplbakpath); 197 if (n != IPLSIZE) 198 errx(1, "%s: short write", iplbakpath); 199 close(fd1); 200 } 201 202 if (menubakpath != NULL) { 203 fd1 = open(menubakpath, O_WRONLY | O_CREAT | O_TRUNC, 0666); 204 if (fd1 < 0) 205 err(1, "%s", menubakpath); 206 n = write(fd1, boot0buf + BOOTMENUOFF, BOOTMENUSIZE); 207 if (n == -1) 208 err(1, "%s", menubakpath); 209 if (n != BOOTMENUSIZE) 210 errx(1, "%s: short write", menubakpath); 211 close(fd1); 212 } 213 214 if (B_flag) { 215 /* Read IPL (boot0). */ 216 fd1 = open(iplpath, O_RDONLY); 217 if (fd1 < 0) 218 err(1, "%s", disk); 219 n = read(fd1, ipl, IPLSIZE); 220 if (n < 0) 221 err(1, "%s", iplpath); 222 if (n != IPLSIZE) 223 errx(1, "%s: invalid file", iplpath); 224 close(fd1); 225 226 /* Read HDD boot menu (boot0.5). */ 227 fd1 = open(menupath, O_RDONLY); 228 if (fd1 < 0) 229 err(1, "%s", disk); 230 n = read(fd1, menu, BOOTMENUSIZE); 231 if (n < 0) 232 err(1, "%s", menupath); 233 if (n != BOOTMENUSIZE) 234 errx(1, "%s: invalid file", menupath); 235 close(fd1); 236 237 memcpy(boot0buf, ipl, IPLSIZE); 238 memcpy(boot0buf + BOOTMENUOFF, menu, BOOTMENUSIZE); 239 } 240 241 /* Set version number field. */ 242 if (v_flag) 243 *(boot0buf + secsize - 4) = (u_char)version; 244 245 if (B_flag || v_flag) { 246 if (lseek(fd, 0, SEEK_SET) == -1 || 247 (n = write(fd, boot0buf, 0x2000)) < 0 || 248 close(fd)) 249 err(1, "%s", disk); 250 if (n != 0x2000) 251 errx(1, "%s: short write", disk); 252 } 253 254 return 0; 255} 256