Move modify_adv() into common code
[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 "syslxopt.h"
29
30 /* These are the options we can set their values */
31 struct sys_options opt = {
32     .sectors = 0,
33     .heads = 0,
34     .raid_mode = 0,
35     .stupid_mode = 0,
36     .reset_adv = 0,
37     .set_once = NULL,
38     .update_only = -1,
39     .directory = NULL,
40     .device = NULL,
41     .offset = 0,
42     .menu_save = NULL,
43 };
44
45 const struct option long_options[] = {
46     {"force", 0, NULL, 'f'},    /* dummy option for compatibility */
47     {"install", 0, NULL, 'i'},
48     {"directory", 1, NULL, 'd'},
49     {"offset", 1, NULL, 't'},
50     {"update", 0, NULL, 'U'},
51     {"zipdrive", 0, NULL, 'z'},
52     {"sectors", 1, NULL, 'S'},
53     {"stupid", 0, NULL, 's'},
54     {"heads", 1, NULL, 'H'},
55     {"raid-mode", 0, NULL, 'r'},
56     {"version", 0, NULL, 'v'},
57     {"help", 0, NULL, 'h'},
58     {"once", 1, NULL, OPT_ONCE},
59     {"clear-once", 0, NULL, 'O'},
60     {"reset-adv", 0, NULL, OPT_RESET_ADV},
61     {"menu-save", 1, NULL, 'M'},
62     {0, 0, 0, 0}
63 };
64
65 const char short_options[] = "t:fid:UuzS:H:rvho:OM:";
66
67 void __attribute__ ((noreturn)) usage(int rv, enum syslinux_mode mode)
68 {
69     switch (mode) {
70     case MODE_SYSLINUX:
71         /* For unmounted fs installation (syslinux) */
72         fprintf(stderr,
73             "Usage: %s [options] device\n"
74             "  --offset     -t  Offset of the file system on the device \n"
75             "  --directory  -d  Directory for installation target\n",
76             program);
77         break;
78
79     case MODE_EXTLINUX:
80         /* Mounted fs installation (extlinux) */
81         /* Actually extlinux can also use -d to provide a directory too... */
82         fprintf(stderr,
83             "Usage: %s [options] directory\n",
84             program);
85         break;
86     }
87
88     fprintf(stderr,
89             "  --install    -i  Install over the current bootsector\n"
90             "  --update     -U  Update a previous EXTLINUX installation\n"
91             "  --zip        -z  Force zipdrive geometry (-H 64 -S 32)\n"
92             "  --sectors=#  -S  Force the number of sectors per track\n"
93             "  --heads=#    -H  Force number of heads\n"
94             "  --stupid     -s  Slow, safe and stupid mode\n"
95             "  --raid       -r  Fall back to the next device on boot failure\n"
96             "  --once=...   %s  Execute a command once upon boot\n"
97             "  --clear-once -O  Clear the boot-once command\n"
98             "  --reset-adv      Reset auxilliary data\n"
99             "  --menu-save= -M  Set the label to select as default on the next boot\n"
100             "\n"
101             "  Note: geometry is determined at boot time for devices which\n"
102             "  are considered hard disks by the BIOS.  Unfortunately, this is\n"
103             "  not possible for devices which are considered floppy disks,\n"
104             "  which includes zipdisks and LS-120 superfloppies.\n"
105             "\n"
106             "  The -z option is useful for USB devices which are considered\n"
107             "  hard disks by some BIOSes and zipdrives by other BIOSes.\n",
108             mode == MODE_SYSLINUX ? "  " : "-o");
109
110     exit(rv);
111 }
112
113 void parse_options(int argc, char *argv[], enum syslinux_mode mode)
114 {
115     int o;
116
117     program = argv[0];
118     while ((o = getopt_long(argc, argv, short_options,
119                             long_options, NULL)) != EOF) {
120         switch (o) {
121         case 'f':
122             break;
123         case 'z':
124             opt.heads = 64;
125             opt.sectors = 32;
126             break;
127         case 'S':
128             opt.sectors = strtoul(optarg, NULL, 0);
129             if (opt.sectors < 1 || opt.sectors > 63) {
130                 fprintf(stderr,
131                         "%s: invalid number of sectors: %u (must be 1-63)\n",
132                         program, opt.sectors);
133                 exit(EX_USAGE);
134             }
135             break;
136         case 'H':
137             opt.heads = strtoul(optarg, NULL, 0);
138             if (opt.heads < 1 || opt.heads > 256) {
139                 fprintf(stderr,
140                         "%s: invalid number of heads: %u (must be 1-256)\n",
141                         program, opt.heads);
142                 exit(EX_USAGE);
143             }
144             break;
145         case 'r':
146             opt.raid_mode = 1;
147             break;
148         case 's':
149             opt.stupid_mode = 1;
150             break;
151         case 'i':
152             opt.update_only = 0;
153             break;
154         case 'u':
155         case 'U':
156             opt.update_only = 1;
157             break;
158         case 'h':
159             usage(0, mode);
160             break;
161         case 'o':
162             if (mode == MODE_SYSLINUX) {
163                 fprintf(stderr, "%s: -o will change meaning in a future version, use -t or --offset\n", program);
164                 goto opt_offset;
165             }
166             /* else fall through */
167         case OPT_ONCE:
168             opt.set_once = optarg;
169             break;
170         case 't':
171         opt_offset:
172             opt.offset = strtoul(optarg, NULL, 0);
173             break;
174         case 'O':
175             opt.set_once = "";
176             break;
177         case 'd':
178             opt.directory = optarg;
179             break;
180         case OPT_RESET_ADV:
181             opt.reset_adv = 1;
182             break;
183         case 'M':
184             opt.menu_save = optarg;
185             break;
186         case 'v':
187             fprintf(stderr,
188                     "%s " VERSION_STR "  Copyright 1994-" YEAR_STR
189                     " H. Peter Anvin et al\n", program);
190             exit(0);
191         default:
192             fprintf(stderr, "%s: Unknown option: -%c\n", program, optopt);
193             usage(EX_USAGE, mode);
194         }
195     }
196
197     switch (mode) {
198     case MODE_SYSLINUX:
199         opt.device = argv[optind++];
200         break;
201     case MODE_EXTLINUX:
202         if (!opt.directory)
203             opt.directory = argv[optind++];
204         break;
205     }
206
207     if (argv[optind])
208         usage(EX_USAGE, mode);  /* Excess arguments */
209 }
210
211 /*
212  * Make any user-specified ADV modifications in memory
213  */
214 int modify_adv(void)
215 {
216     int rv = 0;
217
218     if (opt.reset_adv)
219         syslinux_reset_adv(syslinux_adv);
220
221     if (opt.set_once) {
222         if (syslinux_setadv(ADV_BOOTONCE, strlen(opt.set_once), opt.set_once)) {
223             fprintf(stderr, "%s: not enough space for boot-once command\n",
224                     program);
225             rv = -1;
226         }
227     }
228     if (opt.menu_save) {
229         if (syslinux_setadv(ADV_MENUSAVE, strlen(opt.menu_save), opt.menu_save)) {
230             fprintf(stderr, "%s: not enough space for menu-save label\n",
231                     program);
232             rv = -1;
233         }
234     }
235
236     return rv;
237 }