source: bootcd/isolinux/syslinux-6.03/com32/chain/options.c @ 7b6b7ba

Last change on this file since 7b6b7ba was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 13.8 KB
Line 
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
40struct options opt;
41
42static 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;
89bail:
90    return -1;
91}
92
93static 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
170void 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
185int 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;
432bail:
433    return -1;
434}
435
436/* vim: set ts=8 sts=4 sw=4 noet: */
Note: See TracBrowser for help on using the repository browser.