11 static int soi_s2n(char *ptr
, unsigned int *seg
,
16 unsigned int segval
= 0, offval
, ipval
, val
;
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");
35 val
= (segval
<< 4) + ipval
;
37 if (ipval
> 0xFFFE || val
< ADDRMIN
|| val
> ADDRMAX
) {
38 error("Invalid seg:*:ip address specified.\n");
54 static void usage(void)
57 static const char key
[] = "Press any key...\n";
58 static const char *const usage
[] = {
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\
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\
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
++) {
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";
135 int opt_parse_args(int argc
, char *argv
[])
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")) {
146 } else if (!strncmp(argv
[i
], "seg=", 4)) {
147 if (soi_s2n(argv
[i
] + 4, &opt
.fseg
, &opt
.foff
, &opt
.fip
, 0))
149 } else if (!strncmp(argv
[i
], "bss=", 4)) {
150 opt
.file
= argv
[i
] + 4;
154 /* opt.save = true; */
155 } else if (!strncmp(argv
[i
], "bs=", 3)) {
156 opt
.file
= argv
[i
] + 3;
159 } else if (!strncmp(argv
[i
], "isolinux=", 9)) {
160 opt
.file
= argv
[i
] + 9;
164 } else if (!strncmp(argv
[i
], "ntldr=", 6)) {
165 opt
.fseg
= 0x2000; /* NTLDR wants this address */
168 opt
.file
= argv
[i
] + 6;
170 /* opt.save = true; */
172 } else if (!strncmp(argv
[i
], "cmldr=", 6)) {
173 opt
.fseg
= 0x2000; /* CMLDR wants this address */
176 opt
.file
= argv
[i
] + 6;
179 /* opt.save = true; */
181 } else if (!strncmp(argv
[i
], "freedos=", 8)) {
182 opt
.fseg
= 0x60; /* FREEDOS wants this address */
186 opt
.file
= argv
[i
] + 8;
188 /* opt.save = true; */
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 */
195 opt
.fip
= v
== 7 ? 0x200 : 0; /* MS-DOS 7.0+ wants this ip */
197 opt
.file
= argv
[i
] + v
;
199 /* opt.save = true; */
201 } else if (!strncmp(argv
[i
], "drmk=", 5)) {
202 opt
.fseg
= 0x70; /* DRMK wants this address */
208 opt
.file
= argv
[i
] + 5;
209 /* opt.drmk = true; */
211 /* opt.save = true; */
213 } else if (!strncmp(argv
[i
], "grub=", 5)) {
214 opt
.fseg
= 0x800; /* stage2 wants this address */
217 opt
.file
= argv
[i
] + 5;
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;
228 } else if (!strcmp(argv
[i
], "keeppxe")) {
230 } else if (!strcmp(argv
[i
], "nokeeppxe")) {
232 } else if (!strcmp(argv
[i
], "maps")) {
234 } else if (!strcmp(argv
[i
], "nomaps")) {
236 } else if (!strcmp(argv
[i
], "hand")) {
238 } else if (!strcmp(argv
[i
], "nohand")) {
240 } else if (!strcmp(argv
[i
], "hptr")) {
242 } else if (!strcmp(argv
[i
], "nohptr")) {
244 } else if (!strcmp(argv
[i
], "swap")) {
246 } else if (!strcmp(argv
[i
], "noswap")) {
248 } else if (!strcmp(argv
[i
], "nohide")) {
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")) {
260 } else if (!strcmp(argv
[i
], "nosetbpb")) {
262 } else if (!strcmp(argv
[i
], "filebpb")) {
264 } else if (!strcmp(argv
[i
], "nofilebpb")) {
266 } else if (!strncmp(argv
[i
], "sect=", 5) ||
267 !strcmp(argv
[i
], "sect")) {
269 if (soi_s2n(argv
[i
] + 5, &opt
.sseg
, &opt
.soff
, &opt
.sip
, 0))
273 } else if (!strcmp(argv
[i
], "nosect")) {
276 } else if (!strcmp(argv
[i
], "save")) {
278 } else if (!strcmp(argv
[i
], "nosave")) {
280 } else if (!strcmp(argv
[i
], "fixchs")) {
282 } else if (!strcmp(argv
[i
], "nofixchs")) {
284 } else if (!strcmp(argv
[i
], "warn")) {
286 } else if (!strcmp(argv
[i
], "nowarn")) {
288 } else if (!strcmp(argv
[i
], "chain")) {
290 } else if (!strcmp(argv
[i
], "nochain")) {
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
, ',');
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
];
324 if (opt
.grubcfg
&& !opt
.grub
) {
325 error("grubcfg=<filename> must be used together with grub=<loader>.\n");
330 if ((!opt
.maps
|| !opt
.sect
) && !opt
.file
) {
331 error("You have to load something.\n");
336 if (opt
.filebpb
&& !opt
.file
) {
337 error("Option 'filebpb' requires a file.\n");
341 if (opt
.save
&& !opt
.sect
) {
342 error("Option 'save' requires a sector.\n");
346 if (opt
.setbpb
&& !opt
.sect
) {
347 error("Option 'setbpb' requires a sector.\n");
351 if (opt
.maps
&& !opt
.sect
) {
352 error("Option 'maps' requires a sector.\n");
361 /* vim: set ts=8 sts=4 sw=4 noet: */