[e16e8f2] | 1 | /* ----------------------------------------------------------------------- * |
---|
| 2 | * |
---|
| 3 | * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved |
---|
| 4 | * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin |
---|
| 5 | * Copyright 2010 Shao Miller |
---|
| 6 | * Copyright 2010-2012 Michal Soltys |
---|
| 7 | * |
---|
| 8 | * Permission is hereby granted, free of charge, to any person |
---|
| 9 | * obtaining a copy of this software and associated documentation |
---|
| 10 | * files (the "Software"), to deal in the Software without |
---|
| 11 | * restriction, including without limitation the rights to use, |
---|
| 12 | * copy, modify, merge, publish, distribute, sublicense, and/or |
---|
| 13 | * sell copies of the Software, and to permit persons to whom |
---|
| 14 | * the Software is furnished to do so, subject to the following |
---|
| 15 | * conditions: |
---|
| 16 | * |
---|
| 17 | * The above copyright notice and this permission notice shall |
---|
| 18 | * be included in all copies or substantial portions of the Software. |
---|
| 19 | * |
---|
| 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
---|
| 21 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
---|
| 22 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
---|
| 23 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
---|
| 24 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
---|
| 25 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
---|
| 26 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
---|
| 27 | * OTHER DEALINGS IN THE SOFTWARE. |
---|
| 28 | * |
---|
| 29 | * ----------------------------------------------------------------------- */ |
---|
| 30 | |
---|
| 31 | #include <syslinux/movebits.h> |
---|
| 32 | #include <stdint.h> |
---|
| 33 | #include <stdlib.h> |
---|
| 34 | #include <string.h> |
---|
| 35 | #include "chain.h" |
---|
| 36 | #include "partiter.h" |
---|
| 37 | #include "utility.h" |
---|
| 38 | #include "options.h" |
---|
| 39 | |
---|
| 40 | struct options opt; |
---|
| 41 | |
---|
| 42 | static int soi_s2n(char *ptr, |
---|
| 43 | addr_t *seg, |
---|
| 44 | addr_t *off, |
---|
| 45 | addr_t *ip, |
---|
| 46 | addr_t def) |
---|
| 47 | { |
---|
| 48 | addr_t segval, offval, ipval, val; |
---|
| 49 | char *p; |
---|
| 50 | |
---|
| 51 | /* defaults */ |
---|
| 52 | segval = 0; |
---|
| 53 | offval = def; |
---|
| 54 | ipval = def; |
---|
| 55 | |
---|
| 56 | segval = strtoul(ptr, &p, 0); |
---|
| 57 | if (p[0] == ':' && p[1] && p[1] != ':') |
---|
| 58 | offval = strtoul(p+1, &p, 0); |
---|
| 59 | if (p[0] == ':' && p[1] && p[1] != ':') |
---|
| 60 | ipval = strtoul(p+1, NULL, 0); |
---|
| 61 | |
---|
| 62 | /* verify if load address is within [dosmin, dosmax) */ |
---|
| 63 | val = (segval << 4) + offval; |
---|
| 64 | |
---|
| 65 | if (val < dosmin || val >= dosmax) { |
---|
| 66 | error("Invalid seg:off:* address specified."); |
---|
| 67 | goto bail; |
---|
| 68 | } |
---|
| 69 | |
---|
| 70 | /* |
---|
| 71 | * verify if jump address is within [dosmin, dosmax) and offset is 16bit |
---|
| 72 | * sane |
---|
| 73 | */ |
---|
| 74 | val = (segval << 4) + ipval; |
---|
| 75 | |
---|
| 76 | if (ipval > 0xFFFE || val < dosmin || val >= dosmax) { |
---|
| 77 | error("Invalid seg:*:ip address specified."); |
---|
| 78 | goto bail; |
---|
| 79 | } |
---|
| 80 | |
---|
| 81 | if (seg) |
---|
| 82 | *seg = segval; |
---|
| 83 | if (off) |
---|
| 84 | *off = offval; |
---|
| 85 | if (ip) |
---|
| 86 | *ip = ipval; |
---|
| 87 | |
---|
| 88 | return 0; |
---|
| 89 | bail: |
---|
| 90 | return -1; |
---|
| 91 | } |
---|
| 92 | |
---|
| 93 | static void usage(void) |
---|
| 94 | { |
---|
| 95 | size_t i; |
---|
| 96 | static const char *const usage[] = { |
---|
| 97 | "Usage:", |
---|
| 98 | "", |
---|
| 99 | " disk + partition selection:", |
---|
| 100 | " chain.c32 [options]", |
---|
| 101 | " chain.c32 hd#[,#] [options]", |
---|
| 102 | " chain.c32 fd#[,#] [options]", |
---|
| 103 | " chain.c32 mbr=<id>[,#] [options]", |
---|
| 104 | " chain.c32 guid=<guid>[,#] [options]", |
---|
| 105 | " chain.c32 boot[,#] [options]", |
---|
| 106 | "", |
---|
| 107 | " direct partition selection:", |
---|
| 108 | " chain.c32 guid=<guid> [options]", |
---|
| 109 | " chain.c32 label=<label> [options]", |
---|
| 110 | " chain.c32 fs [options]", |
---|
| 111 | "", |
---|
| 112 | "You can use ':' instead of '=' and ' ' instead of ','.", |
---|
| 113 | "The default is 'boot,0'.", |
---|
| 114 | "", |
---|
| 115 | "Options:", |
---|
| 116 | " sect[=<s[:o[:i]]>] Load sector at <s:o>, jump to <s:i>", |
---|
| 117 | " - defaults to 0:0x7C00:0x7C00", |
---|
| 118 | " - omitted o/i values default to 0", |
---|
| 119 | " maps Map loaded sector into real memory", |
---|
| 120 | " setbpb Fix BPB fields in loaded sector", |
---|
| 121 | " filebpb Apply 'setbpb' to loaded file", |
---|
| 122 | " save Write adjusted sector back to disk", |
---|
| 123 | " hand Prepare handover area", |
---|
| 124 | " hptr Force ds:si and ds:bp to point to handover area", |
---|
| 125 | " swap Swap drive numbers, if bootdisk is not fd0/hd0", |
---|
| 126 | " nohide Disable all hide variations (default)", |
---|
| 127 | " hide Hide primary partitions, unhide selected partition", |
---|
| 128 | " hideall Hide *all* partitions, unhide selected partition", |
---|
| 129 | " unhide Unhide primary partitions", |
---|
| 130 | " unhideall Unhide *all* partitions", |
---|
| 131 | " fixchs Walk *all* partitions and fix E/MBRs' CHS values", |
---|
| 132 | " keeppxe Keep the PXE and UNDI stacks in memory (PXELINUX)", |
---|
| 133 | " warn Wait for a keypress to continue chainloading", |
---|
| 134 | " break Don't chainload", |
---|
| 135 | " strict[=<0|1|2>] Set the level of strictness in sanity checks", |
---|
| 136 | " - strict w/o any value is the same as strict=2", |
---|
| 137 | " relax The same as strict=0", |
---|
| 138 | " prefmbr On hybrid MBR/GPT disks, prefer legacy layout", |
---|
| 139 | "", |
---|
| 140 | " file=<file> Load and execute <file>", |
---|
| 141 | " seg=<s[:o[:i]]> Load file at <s:o>, jump to <s:i>", |
---|
| 142 | " - defaults to 0:0x7C00:0x7C00", |
---|
| 143 | " - omitted o/i values default to 0", |
---|
| 144 | " isolinux=<loader> Load another version of ISOLINUX", |
---|
| 145 | " ntldr=<loader> Load Windows NTLDR, SETUPLDR.BIN or BOOTMGR", |
---|
| 146 | " reactos=<loader> Load ReactOS's loader", |
---|
| 147 | " cmldr=<loader> Load Recovery Console of Windows NT/2K/XP/2003", |
---|
| 148 | " freedos=<loader> Load FreeDOS KERNEL.SYS", |
---|
| 149 | " msdos=<loader> Load MS-DOS 2.xx - 6.xx IO.SYS", |
---|
| 150 | " msdos7=<loader> Load MS-DOS 7+ IO.SYS", |
---|
| 151 | " pcdos=<loader> Load PC-DOS IBMBIO.COM", |
---|
| 152 | " drmk=<loader> Load DRMK DELLBIO.BIN", |
---|
| 153 | " grub=<loader> Load GRUB Legacy stage2", |
---|
| 154 | " grubcfg=<config> Set alternative config filename for GRUB Legacy", |
---|
| 155 | " grldr=<loader> Load GRUB4DOS grldr", |
---|
| 156 | " bss=<sectimage> Emulate syslinux's BSS", |
---|
| 157 | " bs=<sectimage> Emulate syslinux's BS", |
---|
| 158 | "", |
---|
| 159 | "Please see doc/chain.txt for the detailed documentation." |
---|
| 160 | }; |
---|
| 161 | for (i = 0; i < sizeof(usage)/sizeof(usage[0]); i++) { |
---|
| 162 | if (i % 20 == 19) { |
---|
| 163 | puts("Press any key..."); |
---|
| 164 | wait_key(); |
---|
| 165 | } |
---|
| 166 | puts(usage[i]); |
---|
| 167 | } |
---|
| 168 | } |
---|
| 169 | |
---|
| 170 | void opt_set_defs(void) |
---|
| 171 | { |
---|
| 172 | memset(&opt, 0, sizeof opt); |
---|
| 173 | opt.sect = true; /* by def. load sector */ |
---|
| 174 | opt.maps = true; /* by def. map sector */ |
---|
| 175 | opt.hand = true; /* by def. prepare handover */ |
---|
| 176 | opt.brkchain = false; /* by def. do chainload */ |
---|
| 177 | opt.piflags = PIF_STRICT; /* by def. be strict, but ignore disk sizes */ |
---|
| 178 | opt.foff = opt.soff = opt.fip = opt.sip = 0x7C00; |
---|
| 179 | opt.drivename = "boot"; |
---|
| 180 | #ifdef DEBUG |
---|
| 181 | opt.warn = true; |
---|
| 182 | #endif |
---|
| 183 | } |
---|
| 184 | |
---|
| 185 | int opt_parse_args(int argc, char *argv[]) |
---|
| 186 | { |
---|
| 187 | int i; |
---|
| 188 | size_t v; |
---|
| 189 | char *p; |
---|
| 190 | |
---|
| 191 | for (i = 1; i < argc; i++) { |
---|
| 192 | if (!strncmp(argv[i], "file=", 5)) { |
---|
| 193 | opt.file = argv[i] + 5; |
---|
| 194 | } else if (!strcmp(argv[i], "nofile")) { |
---|
| 195 | opt.file = NULL; |
---|
| 196 | } else if (!strncmp(argv[i], "seg=", 4)) { |
---|
| 197 | if (soi_s2n(argv[i] + 4, &opt.fseg, &opt.foff, &opt.fip, 0)) |
---|
| 198 | goto bail; |
---|
| 199 | } else if (!strncmp(argv[i], "bss=", 4)) { |
---|
| 200 | opt.file = argv[i] + 4; |
---|
| 201 | opt.bss = true; |
---|
| 202 | opt.maps = false; |
---|
| 203 | opt.setbpb = true; |
---|
| 204 | } else if (!strncmp(argv[i], "bs=", 3)) { |
---|
| 205 | opt.file = argv[i] + 3; |
---|
| 206 | opt.sect = false; |
---|
| 207 | opt.filebpb = true; |
---|
| 208 | } else if (!strncmp(argv[i], "isolinux=", 9)) { |
---|
| 209 | opt.file = argv[i] + 9; |
---|
| 210 | opt.isolinux = true; |
---|
| 211 | opt.hand = false; |
---|
| 212 | opt.sect = false; |
---|
| 213 | } else if (!strncmp(argv[i], "ntldr=", 6)) { |
---|
| 214 | opt.fseg = 0x2000; /* NTLDR wants this address */ |
---|
| 215 | opt.foff = 0; |
---|
| 216 | opt.fip = 0; |
---|
| 217 | opt.file = argv[i] + 6; |
---|
| 218 | opt.setbpb = true; |
---|
| 219 | opt.hand = false; |
---|
| 220 | } else if (!strncmp(argv[i], "reactos=", 8)) { |
---|
| 221 | /* |
---|
| 222 | * settings based on commit |
---|
| 223 | * ad4cf1470977f648ee1dd45e97939589ccb0393c |
---|
| 224 | * note, conflicts with: |
---|
| 225 | * http://reactos.freedoors.org/Reactos%200.3.13/ReactOS-0.3.13-REL-src/boot/freeldr/notes.txt |
---|
| 226 | */ |
---|
| 227 | opt.fseg = 0; |
---|
| 228 | opt.foff = 0x8000; |
---|
| 229 | opt.fip = 0x8100; |
---|
| 230 | opt.file = argv[i] + 8; |
---|
| 231 | opt.setbpb = true; |
---|
| 232 | opt.hand = false; |
---|
| 233 | } else if (!strncmp(argv[i], "cmldr=", 6)) { |
---|
| 234 | opt.fseg = 0x2000; /* CMLDR wants this address */ |
---|
| 235 | opt.foff = 0; |
---|
| 236 | opt.fip = 0; |
---|
| 237 | opt.file = argv[i] + 6; |
---|
| 238 | opt.cmldr = true; |
---|
| 239 | opt.setbpb = true; |
---|
| 240 | opt.hand = false; |
---|
| 241 | } else if (!strncmp(argv[i], "freedos=", 8)) { |
---|
| 242 | opt.fseg = 0x60; /* FREEDOS wants this address */ |
---|
| 243 | opt.foff = 0; |
---|
| 244 | opt.fip = 0; |
---|
| 245 | opt.sseg = 0x1FE0; |
---|
| 246 | opt.file = argv[i] + 8; |
---|
| 247 | opt.setbpb = true; |
---|
| 248 | opt.hand = false; |
---|
| 249 | } else if ( (v = 6, !strncmp(argv[i], "msdos=", v) || |
---|
| 250 | !strncmp(argv[i], "pcdos=", v)) || |
---|
| 251 | (v = 7, !strncmp(argv[i], "msdos7=", v)) ) { |
---|
| 252 | opt.fseg = 0x70; /* MS-DOS 2.00 .. 6.xx wants this address */ |
---|
| 253 | opt.foff = 0; |
---|
| 254 | opt.fip = v == 7 ? 0x200 : 0; /* MS-DOS 7.0+ wants this ip */ |
---|
| 255 | opt.sseg = 0x8000; |
---|
| 256 | opt.file = argv[i] + v; |
---|
| 257 | opt.setbpb = true; |
---|
| 258 | opt.hand = false; |
---|
| 259 | } else if (!strncmp(argv[i], "drmk=", 5)) { |
---|
| 260 | opt.fseg = 0x70; /* DRMK wants this address */ |
---|
| 261 | opt.foff = 0; |
---|
| 262 | opt.fip = 0; |
---|
| 263 | opt.sseg = 0x2000; |
---|
| 264 | opt.soff = 0; |
---|
| 265 | opt.sip = 0; |
---|
| 266 | opt.file = argv[i] + 5; |
---|
| 267 | /* opt.drmk = true; */ |
---|
| 268 | opt.setbpb = true; |
---|
| 269 | opt.hand = false; |
---|
| 270 | } else if (!strncmp(argv[i], "grub=", 5)) { |
---|
| 271 | opt.fseg = 0x800; /* stage2 wants this address */ |
---|
| 272 | opt.foff = 0; |
---|
| 273 | opt.fip = 0x200; |
---|
| 274 | opt.file = argv[i] + 5; |
---|
| 275 | opt.grub = true; |
---|
| 276 | opt.hand = false; |
---|
| 277 | opt.sect = false; |
---|
| 278 | } else if (!strncmp(argv[i], "grubcfg=", 8)) { |
---|
| 279 | opt.grubcfg = argv[i] + 8; |
---|
| 280 | } else if (!strncmp(argv[i], "grldr=", 6)) { |
---|
| 281 | opt.file = argv[i] + 6; |
---|
| 282 | opt.grldr = true; |
---|
| 283 | opt.hand = false; |
---|
| 284 | opt.sect = false; |
---|
| 285 | } else if (!strcmp(argv[i], "keeppxe")) { |
---|
| 286 | opt.keeppxe = 3; |
---|
| 287 | } else if (!strcmp(argv[i], "nokeeppxe")) { |
---|
| 288 | opt.keeppxe = 0; |
---|
| 289 | } else if (!strcmp(argv[i], "maps")) { |
---|
| 290 | opt.maps = true; |
---|
| 291 | } else if (!strcmp(argv[i], "nomaps")) { |
---|
| 292 | opt.maps = false; |
---|
| 293 | } else if (!strcmp(argv[i], "hand")) { |
---|
| 294 | opt.hand = true; |
---|
| 295 | } else if (!strcmp(argv[i], "nohand")) { |
---|
| 296 | opt.hand = false; |
---|
| 297 | } else if (!strcmp(argv[i], "hptr")) { |
---|
| 298 | opt.hptr = true; |
---|
| 299 | } else if (!strcmp(argv[i], "nohptr")) { |
---|
| 300 | opt.hptr = false; |
---|
| 301 | } else if (!strcmp(argv[i], "swap")) { |
---|
| 302 | opt.swap = true; |
---|
| 303 | } else if (!strcmp(argv[i], "noswap")) { |
---|
| 304 | opt.swap = false; |
---|
| 305 | } else if (!strcmp(argv[i], "nohide")) { |
---|
| 306 | opt.hide = HIDE_OFF; |
---|
| 307 | } else if (!strcmp(argv[i], "hide")) { |
---|
| 308 | opt.hide = HIDE_ON; |
---|
| 309 | opt.piflags |= PIF_STRICT | PIF_STRICTER; |
---|
| 310 | } else if (!strcmp(argv[i], "hideall")) { |
---|
| 311 | opt.hide = HIDE_ON | HIDE_EXT; |
---|
| 312 | opt.piflags |= PIF_STRICT | PIF_STRICTER; |
---|
| 313 | } else if (!strcmp(argv[i], "unhide")) { |
---|
| 314 | opt.hide = HIDE_ON | HIDE_REV; |
---|
| 315 | opt.piflags |= PIF_STRICT | PIF_STRICTER; |
---|
| 316 | } else if (!strcmp(argv[i], "unhideall")) { |
---|
| 317 | opt.hide = HIDE_ON | HIDE_EXT | HIDE_REV; |
---|
| 318 | opt.piflags |= PIF_STRICT | PIF_STRICTER; |
---|
| 319 | } else if (!strcmp(argv[i], "setbpb")) { |
---|
| 320 | opt.setbpb = true; |
---|
| 321 | } else if (!strcmp(argv[i], "nosetbpb")) { |
---|
| 322 | opt.setbpb = false; |
---|
| 323 | } else if (!strcmp(argv[i], "filebpb")) { |
---|
| 324 | opt.filebpb = true; |
---|
| 325 | } else if (!strcmp(argv[i], "nofilebpb")) { |
---|
| 326 | opt.filebpb = false; |
---|
| 327 | } else if (!strncmp(argv[i], "sect=", 5) || |
---|
| 328 | !strcmp(argv[i], "sect")) { |
---|
| 329 | if (argv[i][4]) { |
---|
| 330 | if (soi_s2n(argv[i] + 5, &opt.sseg, &opt.soff, &opt.sip, 0)) |
---|
| 331 | goto bail; |
---|
| 332 | } |
---|
| 333 | opt.sect = true; |
---|
| 334 | } else if (!strcmp(argv[i], "nosect")) { |
---|
| 335 | opt.sect = false; |
---|
| 336 | opt.maps = false; |
---|
| 337 | } else if (!strcmp(argv[i], "save")) { |
---|
| 338 | opt.save = true; |
---|
| 339 | opt.piflags |= PIF_STRICT | PIF_STRICTER; |
---|
| 340 | } else if (!strcmp(argv[i], "nosave")) { |
---|
| 341 | opt.save = false; |
---|
| 342 | } else if (!strcmp(argv[i], "fixchs")) { |
---|
| 343 | opt.fixchs = true; |
---|
| 344 | opt.piflags |= PIF_STRICT | PIF_STRICTER; |
---|
| 345 | } else if (!strcmp(argv[i], "nofixchs")) { |
---|
| 346 | opt.fixchs = false; |
---|
| 347 | } else if (!strcmp(argv[i], "relax") || !strcmp(argv[i], "nostrict")) { |
---|
| 348 | opt.piflags &= ~(PIF_STRICT | PIF_STRICTER); |
---|
| 349 | } else if (!strcmp(argv[i], "norelax") || !strcmp(argv[i], "strict")) { |
---|
| 350 | opt.piflags |= PIF_STRICT | PIF_STRICTER; |
---|
| 351 | } else if (!strncmp(argv[i], "strict=", 7)) { |
---|
| 352 | if (argv[i][7] < '0' || argv[i][7] > '2' || !argv[i][8]) { |
---|
| 353 | error("Strict level must be 0, 1 or 2."); |
---|
| 354 | goto bail; |
---|
| 355 | } |
---|
| 356 | opt.piflags &= ~(PIF_STRICT | PIF_STRICTER); |
---|
| 357 | switch (argv[i][7]) { |
---|
| 358 | case '2': opt.piflags |= PIF_STRICTER; |
---|
| 359 | case '1': opt.piflags |= PIF_STRICT; break; |
---|
| 360 | default:; |
---|
| 361 | } |
---|
| 362 | } else if (!strcmp(argv[i], "warn")) { |
---|
| 363 | opt.warn = true; |
---|
| 364 | } else if (!strcmp(argv[i], "nowarn")) { |
---|
| 365 | opt.warn = false; |
---|
| 366 | } else if (!strcmp(argv[i], "prefmbr")) { |
---|
| 367 | opt.piflags |= PIF_PREFMBR; |
---|
| 368 | } else if (!strcmp(argv[i], "noprefmbr")) { |
---|
| 369 | opt.piflags &= ~PIF_PREFMBR; |
---|
| 370 | } else if (!strcmp(argv[i], "nobreak")) { |
---|
| 371 | opt.brkchain = false; |
---|
| 372 | } else if (!strcmp(argv[i], "break")) { |
---|
| 373 | opt.brkchain = true; |
---|
| 374 | opt.file = NULL; |
---|
| 375 | opt.maps = false; |
---|
| 376 | opt.hand = false; |
---|
| 377 | } else if (((argv[i][0] == 'h' || argv[i][0] == 'f') |
---|
| 378 | && argv[i][1] == 'd') |
---|
| 379 | || !strncmp(argv[i], "mbr:", 4) |
---|
| 380 | || !strncmp(argv[i], "mbr=", 4) |
---|
| 381 | || !strncmp(argv[i], "guid:", 5) |
---|
| 382 | || !strncmp(argv[i], "guid=", 5) |
---|
| 383 | || !strncmp(argv[i], "label:", 6) |
---|
| 384 | || !strncmp(argv[i], "label=", 6) |
---|
| 385 | || !strcmp(argv[i], "boot") |
---|
| 386 | || !strncmp(argv[i], "boot,", 5) |
---|
| 387 | || !strcmp(argv[i], "fs")) { |
---|
| 388 | opt.drivename = argv[i]; |
---|
| 389 | if (strncmp(argv[i], "label", 5)) |
---|
| 390 | p = strchr(opt.drivename, ','); |
---|
| 391 | else |
---|
| 392 | p = NULL; |
---|
| 393 | if (p) { |
---|
| 394 | *p = '\0'; |
---|
| 395 | opt.partition = p + 1; |
---|
| 396 | } else if (argv[i + 1] && argv[i + 1][0] >= '0' |
---|
| 397 | && argv[i + 1][0] <= '9') { |
---|
| 398 | opt.partition = argv[++i]; |
---|
| 399 | } |
---|
| 400 | } else { |
---|
| 401 | usage(); |
---|
| 402 | goto bail; |
---|
| 403 | } |
---|
| 404 | } |
---|
| 405 | |
---|
| 406 | if (opt.grubcfg && !opt.grub) { |
---|
| 407 | error("grubcfg=<filename> must be used together with grub=<loader>."); |
---|
| 408 | goto bail; |
---|
| 409 | } |
---|
| 410 | |
---|
| 411 | if (opt.filebpb && !opt.file) { |
---|
| 412 | error("Option 'filebpb' requires a file."); |
---|
| 413 | goto bail; |
---|
| 414 | } |
---|
| 415 | |
---|
| 416 | if (opt.save && !opt.sect) { |
---|
| 417 | error("Option 'save' requires a sector."); |
---|
| 418 | goto bail; |
---|
| 419 | } |
---|
| 420 | |
---|
| 421 | if (opt.setbpb && !opt.sect) { |
---|
| 422 | error("Option 'setbpb' requires a sector."); |
---|
| 423 | goto bail; |
---|
| 424 | } |
---|
| 425 | |
---|
| 426 | if (opt.maps && !opt.sect) { |
---|
| 427 | error("Option 'maps' requires a sector."); |
---|
| 428 | goto bail; |
---|
| 429 | } |
---|
| 430 | |
---|
| 431 | return 0; |
---|
| 432 | bail: |
---|
| 433 | return -1; |
---|
| 434 | } |
---|
| 435 | |
---|
| 436 | /* vim: set ts=8 sts=4 sw=4 noet: */ |
---|