com32/chain: option rename: mbrchs -> fixchs
[syslinux.git] / com32 / chain / options.c
blob7d850619d82465b5169e4bea48eb9160facfd7c8
1 #include <stdint.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include "common.h"
5 #include "chain.h"
6 #include "utility.h"
7 #include "options.h"
9 struct options opt;
11 static int soi_s2n(char *ptr, unsigned int *seg,
12 unsigned int *off,
13 unsigned int *ip,
14 unsigned int def)
16 unsigned int segval = 0, offval, ipval, val;
17 char *p;
19 offval = def;
20 ipval = def;
22 segval = strtoul(ptr, &p, 0);
23 if (p[0] == ':' && p[1] && p[1] != ':')
24 offval = strtoul(p+1, &p, 0);
25 if (p[0] == ':' && p[1] && p[1] != ':')
26 ipval = strtoul(p+1, NULL, 0);
28 val = (segval << 4) + offval;
30 if (val < ADDRMIN || val > ADDRMAX) {
31 error("Invalid seg:off:* address specified..\n");
32 goto bail;
35 val = (segval << 4) + ipval;
37 if (ipval > 0xFFFE || val < ADDRMIN || val > ADDRMAX) {
38 error("Invalid seg:*:ip address specified.\n");
39 goto bail;
42 if (seg)
43 *seg = segval;
44 if (off)
45 *off = offval;
46 if (ip)
47 *ip = ipval;
49 return 0;
50 bail:
51 return -1;
54 static void usage(void)
56 unsigned int i;
57 static const char key[] = "Press any key...\n";
58 static const char *const usage[] = {
60 Usage:\n\
61 chain.c32 [options]\n\
62 chain.c32 {fd|hd}<disk#>{,| }[<part#>] [options]\n\
63 chain.c32 mbr{:|=}<id>{,| }[<part#>] [options]\n\
64 chain.c32 guid{:|=}<guid>{,| }[<part#>] [options]\n\
65 chain.c32 label{:|=}<label> [<part#>] [options]\n\
66 chain.c32 boot{,| }[<part#>] [options]\n\
67 chain.c32 fs [options]\n\
68 ", "\
69 \nOptions ('no' prefix specifies default value):\n\
70 sect[=<s[:o[:i]]>] Load sector at <s:o>, jump to <s:i>\n\
71 - defaults to 0:0x7C00:0x7C00\n\
72 - ommited o/i values default to 0\n\
73 maps Map loaded sector into real memory\n\
74 nosetbpb Fix BPB fields in loaded sector\n\
75 nofilebpb Apply 'setbpb' to loaded file\n\
76 nosave Write adjusted sector back to disk\n\
77 hand Prepare handover area\n\
78 nohptr Force ds:si and ds:bp to point to handover area\n\
79 noswap Swap drive numbers, if bootdisk is not fd0/hd0\n\
80 nohide Disable all hide variations (also the default)\n\
81 hide Hide primary partitions, unhide selected partition\n\
82 hideall Hide *all* partitions, unhide selected partition\n\
83 unhide Unhide primary partitions\n\
84 unhideall Unhide *all* partitions\n\
85 nofixchs Walk *all* partitions and fix E/MBRs' chs values\n\
86 nokeeppxe Keep the PXE and UNDI stacks in memory (PXELINUX)\n\
87 nowarn Wait for a keypress to continue chainloading\n\
88 - useful to see emited warnings\n\
89 chain Actually perform the chainloading\n\
90 ", "\
91 \nOptions continued ...\n\
92 file=<file> Load and execute <file>\n\
93 seg=<s[:o[:i]]> Load file at <s:o>, jump to <s:i>\n\
94 - defaults to 0:0x7C00:0x7C00\n\
95 - ommited o/i values default to 0\n\
96 isolinux=<loader> Load another version of ISOLINUX\n\
97 ntldr=<loader> Load Windows NTLDR, SETUPLDR.BIN or BOOTMGR\n\
98 cmldr=<loader> Load Recovery Console of Windows NT/2K/XP/2003\n\
99 freedos=<loader> Load FreeDOS KERNEL.SYS\n\
100 msdos=<loader> Load MS-DOS 2.xx - 6.xx IO.SYS\n\
101 msdos7=<loader> Load MS-DOS 7+ IO.SYS\n\
102 pcdos=<loader> Load PC-DOS IBMBIO.COM\n\
103 drmk=<loader> Load DRMK DELLBIO.BIN\n\
104 grub=<loader> Load GRUB Legacy stage2\n\
105 grubcfg=<filename> Set alternative config filename for GRUB Legacy\n\
106 grldr=<loader> Load GRUB4DOS grldr\n\
107 bss=<filename> Emulate syslinux's BSS\n\
108 bs=<filename> Emulate syslinux's BS\n\
109 \nPlease see doc/chain.txt for the detailed documentation.\n\
112 for (i = 0; i < sizeof(usage)/sizeof(usage[0]); i++) {
113 if (i) {
114 error(key);
115 wait_key();
117 error(usage[i]);
121 void opt_set_defs(void)
123 memset(&opt, 0, sizeof(opt));
124 opt.sect = true; /* by def. load sector */
125 opt.maps = true; /* by def. map sector */
126 opt.hand = true; /* by def. prepare handover */
127 opt.chain = true; /* by def. do chainload */
128 opt.foff = opt.soff = opt.fip = opt.sip = 0x7C00;
129 opt.drivename = "boot";
130 #ifdef DEBUG
131 opt.warn = true;
132 #endif
135 int opt_parse_args(int argc, char *argv[])
137 int i;
138 unsigned int v;
139 char *p;
141 for (i = 1; i < argc; i++) {
142 if (!strncmp(argv[i], "file=", 5)) {
143 opt.file = argv[i] + 5;
144 } else if (!strcmp(argv[i], "nofile")) {
145 opt.file = NULL;
146 } else if (!strncmp(argv[i], "seg=", 4)) {
147 if (soi_s2n(argv[i] + 4, &opt.fseg, &opt.foff, &opt.fip, 0))
148 goto bail;
149 } else if (!strncmp(argv[i], "bss=", 4)) {
150 opt.file = argv[i] + 4;
151 opt.bss = true;
152 opt.maps = false;
153 opt.setbpb = true;
154 /* opt.save = true; */
155 } else if (!strncmp(argv[i], "bs=", 3)) {
156 opt.file = argv[i] + 3;
157 opt.sect = false;
158 opt.filebpb = true;
159 } else if (!strncmp(argv[i], "isolinux=", 9)) {
160 opt.file = argv[i] + 9;
161 opt.isolinux = true;
162 opt.hand = false;
163 opt.sect = false;
164 } else if (!strncmp(argv[i], "ntldr=", 6)) {
165 opt.fseg = 0x2000; /* NTLDR wants this address */
166 opt.foff = 0;
167 opt.fip = 0;
168 opt.file = argv[i] + 6;
169 opt.setbpb = true;
170 /* opt.save = true; */
171 opt.hand = false;
172 } else if (!strncmp(argv[i], "cmldr=", 6)) {
173 opt.fseg = 0x2000; /* CMLDR wants this address */
174 opt.foff = 0;
175 opt.fip = 0;
176 opt.file = argv[i] + 6;
177 opt.cmldr = true;
178 opt.setbpb = true;
179 /* opt.save = true; */
180 opt.hand = false;
181 } else if (!strncmp(argv[i], "freedos=", 8)) {
182 opt.fseg = 0x60; /* FREEDOS wants this address */
183 opt.foff = 0;
184 opt.fip = 0;
185 opt.sseg = 0x1FE0;
186 opt.file = argv[i] + 8;
187 opt.setbpb = true;
188 /* opt.save = true; */
189 opt.hand = false;
190 } else if ( (v = 6, !strncmp(argv[i], "msdos=", v) ||
191 !strncmp(argv[i], "pcdos=", v)) ||
192 (v = 7, !strncmp(argv[i], "msdos7=", v)) ) {
193 opt.fseg = 0x70; /* MS-DOS 2.00 .. 6.xx wants this address */
194 opt.foff = 0;
195 opt.fip = v == 7 ? 0x200 : 0; /* MS-DOS 7.0+ wants this ip */
196 opt.sseg = 0x8000;
197 opt.file = argv[i] + v;
198 opt.setbpb = true;
199 /* opt.save = true; */
200 opt.hand = false;
201 } else if (!strncmp(argv[i], "drmk=", 5)) {
202 opt.fseg = 0x70; /* DRMK wants this address */
203 opt.foff = 0;
204 opt.fip = 0;
205 opt.sseg = 0x2000;
206 opt.soff = 0;
207 opt.sip = 0;
208 opt.file = argv[i] + 5;
209 /* opt.drmk = true; */
210 opt.setbpb = true;
211 /* opt.save = true; */
212 opt.hand = false;
213 } else if (!strncmp(argv[i], "grub=", 5)) {
214 opt.fseg = 0x800; /* stage2 wants this address */
215 opt.foff = 0;
216 opt.fip = 0x200;
217 opt.file = argv[i] + 5;
218 opt.grub = true;
219 opt.hand = false;
220 opt.sect = false;
221 } else if (!strncmp(argv[i], "grubcfg=", 8)) {
222 opt.grubcfg = argv[i] + 8;
223 } else if (!strncmp(argv[i], "grldr=", 6)) {
224 opt.file = argv[i] + 6;
225 opt.grldr = true;
226 opt.hand = false;
227 opt.sect = false;
228 } else if (!strcmp(argv[i], "keeppxe")) {
229 opt.keeppxe = 3;
230 } else if (!strcmp(argv[i], "nokeeppxe")) {
231 opt.keeppxe = 0;
232 } else if (!strcmp(argv[i], "maps")) {
233 opt.maps = true;
234 } else if (!strcmp(argv[i], "nomaps")) {
235 opt.maps = false;
236 } else if (!strcmp(argv[i], "hand")) {
237 opt.hand = true;
238 } else if (!strcmp(argv[i], "nohand")) {
239 opt.hand = false;
240 } else if (!strcmp(argv[i], "hptr")) {
241 opt.hptr = true;
242 } else if (!strcmp(argv[i], "nohptr")) {
243 opt.hptr = false;
244 } else if (!strcmp(argv[i], "swap")) {
245 opt.swap = true;
246 } else if (!strcmp(argv[i], "noswap")) {
247 opt.swap = false;
248 } else if (!strcmp(argv[i], "nohide")) {
249 opt.hide = 0;
250 } else if (!strcmp(argv[i], "hide")) {
251 opt.hide = 1; /* 001b */
252 } else if (!strcmp(argv[i], "hideall")) {
253 opt.hide = 2; /* 010b */
254 } else if (!strcmp(argv[i], "unhide")) {
255 opt.hide = 5; /* 101b */
256 } else if (!strcmp(argv[i], "unhideall")) {
257 opt.hide = 6; /* 110b */
258 } else if (!strcmp(argv[i], "setbpb")) {
259 opt.setbpb = true;
260 } else if (!strcmp(argv[i], "nosetbpb")) {
261 opt.setbpb = false;
262 } else if (!strcmp(argv[i], "filebpb")) {
263 opt.filebpb = true;
264 } else if (!strcmp(argv[i], "nofilebpb")) {
265 opt.filebpb = false;
266 } else if (!strncmp(argv[i], "sect=", 5) ||
267 !strcmp(argv[i], "sect")) {
268 if (argv[i][4]) {
269 if (soi_s2n(argv[i] + 5, &opt.sseg, &opt.soff, &opt.sip, 0))
270 goto bail;
272 opt.sect = true;
273 } else if (!strcmp(argv[i], "nosect")) {
274 opt.sect = false;
275 opt.maps = false;
276 } else if (!strcmp(argv[i], "save")) {
277 opt.save = true;
278 } else if (!strcmp(argv[i], "nosave")) {
279 opt.save = false;
280 } else if (!strcmp(argv[i], "fixchs")) {
281 opt.fixchs = true;
282 } else if (!strcmp(argv[i], "nofixchs")) {
283 opt.fixchs = false;
284 } else if (!strcmp(argv[i], "warn")) {
285 opt.warn = true;
286 } else if (!strcmp(argv[i], "nowarn")) {
287 opt.warn = false;
288 } else if (!strcmp(argv[i], "chain")) {
289 opt.chain = true;
290 } else if (!strcmp(argv[i], "nochain")) {
291 opt.chain = false;
292 opt.file = NULL;
293 opt.maps = false;
294 opt.hand = false;
295 } else if (((argv[i][0] == 'h' || argv[i][0] == 'f')
296 && argv[i][1] == 'd')
297 || !strncmp(argv[i], "mbr:", 4)
298 || !strncmp(argv[i], "mbr=", 4)
299 || !strncmp(argv[i], "guid:", 5)
300 || !strncmp(argv[i], "guid=", 5)
301 || !strncmp(argv[i], "label:", 6)
302 || !strncmp(argv[i], "label=", 6)
303 || !strcmp(argv[i], "boot")
304 || !strncmp(argv[i], "boot,", 5)
305 || !strcmp(argv[i], "fs")) {
306 opt.drivename = argv[i];
307 if (strncmp(argv[i], "label", 5))
308 p = strchr(opt.drivename, ',');
309 else
310 p = NULL;
311 if (p) {
312 *p = '\0';
313 opt.partition = p + 1;
314 } else if (argv[i + 1] && argv[i + 1][0] >= '0'
315 && argv[i + 1][0] <= '9') {
316 opt.partition = argv[++i];
318 } else {
319 usage();
320 goto bail;
324 if (opt.grubcfg && !opt.grub) {
325 error("grubcfg=<filename> must be used together with grub=<loader>.\n");
326 goto bail;
329 #if 0
330 if ((!opt.maps || !opt.sect) && !opt.file) {
331 error("You have to load something.\n");
332 goto bail;
334 #endif
336 if (opt.filebpb && !opt.file) {
337 error("Option 'filebpb' requires a file.\n");
338 goto bail;
341 if (opt.save && !opt.sect) {
342 error("Option 'save' requires a sector.\n");
343 goto bail;
346 if (opt.setbpb && !opt.sect) {
347 error("Option 'setbpb' requires a sector.\n");
348 goto bail;
351 if (opt.maps && !opt.sect) {
352 error("Option 'maps' requires a sector.\n");
353 goto bail;
356 return 0;
357 bail:
358 return -1;
361 /* vim: set ts=8 sts=4 sw=4 noet: */