win: Add -mno-ms-bitfields
[profile/ivi/syslinux.git] / libinstaller / syslxopt.c
1 /* ----------------------------------------------------------------------- *
2  *
3  *   Copyright 2010 Intel Corp. - All Rights Reserved
4  *
5  *   This program is free software; you can redistribute it and/or modify
6  *   it under the terms of the GNU General Public License as published by
7  *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
8  *   Boston MA 02111-1307, USA; either version 2 of the License, or
9  *   (at your option) any later version; incorporated herein by reference.
10  *
11  * ----------------------------------------------------------------------- */
12
13 /*
14  * syslxopt.c
15  *
16  * parse cmdline for extlinux and syslinux installer
17  *
18  */
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <stddef.h>
22 #include <stdint.h>
23 #include <string.h>
24 #include <getopt.h>
25 #include <sysexits.h>
26 #include "../version.h"
27 #include "syslxcom.h"
28 #include "syslxfs.h"
29 #include "syslxopt.h"
30
31 /* These are the options we can set their values */
32 struct sys_options opt = {
33     .sectors = 0,
34     .heads = 0,
35     .raid_mode = 0,
36     .stupid_mode = 0,
37     .reset_adv = 0,
38     .set_once = NULL,
39     .update_only = -1,
40     .directory = NULL,
41     .device = NULL,
42     .offset = 0,
43     .menu_save = NULL,
44     .install_mbr = 0,
45     .activate_partition = 0,
46     .force = 0,
47     .bootsecfile = NULL,
48 };
49
50 const struct option long_options[] = {
51     {"force", 0, NULL, 'f'},    /* DOS/Win32/mtools only */
52     {"install", 0, NULL, 'i'},
53     {"directory", 1, NULL, 'd'},
54     {"offset", 1, NULL, 't'},
55     {"update", 0, NULL, 'U'},
56     {"zipdrive", 0, NULL, 'z'},
57     {"sectors", 1, NULL, 'S'},
58     {"stupid", 0, NULL, 's'},
59     {"heads", 1, NULL, 'H'},
60     {"raid-mode", 0, NULL, 'r'},
61     {"version", 0, NULL, 'v'},
62     {"help", 0, NULL, 'h'},
63     {"once", 1, NULL, OPT_ONCE},
64     {"clear-once", 0, NULL, 'O'},
65     {"reset-adv", 0, NULL, OPT_RESET_ADV},
66     {"menu-save", 1, NULL, 'M'},
67     {"mbr", 0, NULL, 'm'},      /* DOS/Win32 only */
68     {"active", 0, NULL, 'a'},   /* DOS/Win32 only */
69     {"device", 1, NULL, OPT_DEVICE},
70     {0, 0, 0, 0}
71 };
72
73 const char short_options[] = "t:fid:UuzsS:H:rvho:OM:ma";
74
75 void __attribute__ ((noreturn)) usage(int rv, enum syslinux_mode mode)
76 {
77     switch (mode) {
78     case MODE_SYSLINUX:
79         /* For unmounted fs installation (syslinux) */
80         fprintf(stderr,
81             "Usage: %s [options] device\n"
82             "  --offset     -t  Offset of the file system on the device \n"
83             "  --directory  -d  Directory for installation target\n",
84             program);
85         break;
86
87     case MODE_EXTLINUX:
88         /* Mounted fs installation (extlinux) */
89         /* Actually extlinux can also use -d to provide a directory too... */
90         fprintf(stderr,
91             "Usage: %s [options] directory\n"
92             "  --device         Force use of a specific block device (experts only)\n",
93             program);
94         break;
95
96     case MODE_SYSLINUX_DOSWIN:
97         /* For fs installation under Windows (syslinux.exe) */
98         fprintf(stderr,
99             "Usage: %s [options] <drive>: [bootsecfile]\n"
100             "  --directory  -d  Directory for installation target\n",
101             program);
102         break;
103     }
104
105     fprintf(stderr,
106             "  --install    -i  Install over the current bootsector\n"
107             "  --update     -U  Update a previous installation\n"
108             "  --zip        -z  Force zipdrive geometry (-H 64 -S 32)\n"
109             "  --sectors=#  -S  Force the number of sectors per track\n"
110             "  --heads=#    -H  Force number of heads\n"
111             "  --stupid     -s  Slow, safe and stupid mode\n"
112             "  --raid       -r  Fall back to the next device on boot failure\n"
113             "  --once=...   %s  Execute a command once upon boot\n"
114             "  --clear-once -O  Clear the boot-once command\n"
115             "  --reset-adv      Reset auxilliary data\n",
116             mode == MODE_SYSLINUX  ? "  " : "-o");
117     /*
118      * Have to chop this roughly in half for the DOS installer due
119      * to limited output buffer size
120      */
121     fprintf(stderr,
122             "  --menu-save= -M  Set the label to select as default on the next boot\n");
123     if (mode == MODE_SYSLINUX_DOSWIN)
124         fprintf(stderr,
125                 "  --mbr        -m  Install an MBR\n"
126                 "  --active     -a  Mark partition as active\n");
127
128     if (mode == MODE_SYSLINUX_DOSWIN || mode == MODE_SYSLINUX)
129         fprintf(stderr,
130                 "  --force      -f  Ignore precautions\n");
131
132     exit(rv);
133 }
134
135 void parse_options(int argc, char *argv[], enum syslinux_mode mode)
136 {
137     int o;
138
139     program = argv[0];
140     while ((o = getopt_long(argc, argv, short_options,
141                             long_options, NULL)) != EOF) {
142         switch (o) {
143         case 'f':
144             opt.force = 1;
145             break;
146         case 'z':
147             opt.heads = 64;
148             opt.sectors = 32;
149             break;
150         case 'S':
151             opt.sectors = strtoul(optarg, NULL, 0);
152             if (opt.sectors < 1 || opt.sectors > 63) {
153                 fprintf(stderr,
154                         "%s: invalid number of sectors: %u (must be 1-63)\n",
155                         program, opt.sectors);
156                 exit(EX_USAGE);
157             }
158             break;
159         case 'H':
160             opt.heads = strtoul(optarg, NULL, 0);
161             if (opt.heads < 1 || opt.heads > 256) {
162                 fprintf(stderr,
163                         "%s: invalid number of heads: %u (must be 1-256)\n",
164                         program, opt.heads);
165                 exit(EX_USAGE);
166             }
167             break;
168         case 'r':
169             opt.raid_mode = 1;
170             break;
171         case 's':
172             opt.stupid_mode = 1;
173             break;
174         case 'i':
175             opt.update_only = 0;
176             break;
177         case 'u':
178         case 'U':
179             opt.update_only = 1;
180             break;
181         case 'h':
182             usage(0, mode);
183             break;
184         case 'o':
185             if (mode == MODE_SYSLINUX) {
186                 fprintf(stderr, "%s: -o will change meaning in a future version, use -t or --offset\n", program);
187                 goto opt_offset;
188             }
189             /* else fall through */
190         case OPT_ONCE:
191             opt.set_once = optarg;
192             break;
193         case 't':
194         opt_offset:
195             opt.offset = strtoul(optarg, NULL, 0);
196             break;
197         case 'O':
198             opt.set_once = "";
199             break;
200         case 'd':
201             opt.directory = optarg;
202             break;
203         case OPT_RESET_ADV:
204             opt.reset_adv = 1;
205             break;
206         case 'M':
207             opt.menu_save = optarg;
208             break;
209         case 'm':
210             opt.install_mbr = 1;
211             break;
212         case 'a':
213             opt.activate_partition = 1;
214             break;
215         case OPT_DEVICE:
216             if (mode != MODE_EXTLINUX)
217                 usage(EX_USAGE, mode);
218             opt.device = optarg;
219             break;
220         case 'v':
221             fprintf(stderr,
222                     "%s " VERSION_STR "  Copyright 1994-" YEAR_STR
223                     " H. Peter Anvin et al\n", program);
224             exit(0);
225         default:
226             fprintf(stderr, "%s: Unknown option: -%c\n", program, optopt);
227             usage(EX_USAGE, mode);
228         }
229     }
230
231     switch (mode) {
232     case MODE_SYSLINUX:
233     case MODE_SYSLINUX_DOSWIN:
234         opt.device = argv[optind++];
235         break;
236     case MODE_EXTLINUX:
237         if (!opt.directory)
238             opt.directory = argv[optind++];
239         break;
240     }
241
242     if (argv[optind] && (mode == MODE_SYSLINUX_DOSWIN))
243         /* Allow for the boot-sector argument */
244         opt.bootsecfile = argv[optind++];
245     if (argv[optind])
246         usage(EX_USAGE, mode);  /* Excess arguments */
247 }
248
249 /*
250  * Make any user-specified ADV modifications in memory
251  */
252 int modify_adv(void)
253 {
254     int rv = 0;
255
256     if (opt.reset_adv)
257         syslinux_reset_adv(syslinux_adv);
258
259     if (opt.set_once) {
260         if (syslinux_setadv(ADV_BOOTONCE, strlen(opt.set_once), opt.set_once)) {
261             fprintf(stderr, "%s: not enough space for boot-once command\n",
262                     program);
263             rv = -1;
264         }
265     }
266     if (opt.menu_save) {
267         if (syslinux_setadv(ADV_MENUSAVE, strlen(opt.menu_save), opt.menu_save)) {
268             fprintf(stderr, "%s: not enough space for menu-save label\n",
269                     program);
270             rv = -1;
271         }
272     }
273
274     return rv;
275 }