2 * Copyright (c) 2010 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 #include "bootstrap.h"
40 static void menu_display(void);
41 static int menu_execute(int);
44 * This is called from common and must reference files to bring
45 * library modules into common during linking.
48 dloader_init_cmds(void)
53 * This intercepts lines of the form 'a=b'
55 COMMAND_SET(local, "local", "List local variables", command_local);
56 COMMAND_SET(lunset, "lunset", "Unset local variables", command_lunset);
57 COMMAND_SET(lunsetif, "lunsetif", "Unset local if envvar set to 1 or YES", command_lunsetif);
58 COMMAND_SET(loadall, "loadall", "Load kernel + modules", command_loadall);
59 COMMAND_SET(menuclear, "menuclear", "Clear all menus", command_menuclear);
60 COMMAND_SET(menuitem, "menuitem", "Add menu bullet", command_menuitem);
61 COMMAND_SET(menuadd, "menuadd", "Add script line for bullet", command_menuadd);
62 COMMAND_SET(menu, "menu", "Run menu system", command_menu);
67 static char *kenv_vars[] = {
89 * Set local variable. Sniff "module_path"
91 * format a=b (one argument) - in av[0]
94 command_local(int ac, char **av)
103 * local command executed directly.
105 if (strcmp(av[0], "local") == 0) {
106 for (dvar = dvar_first(); dvar; dvar = dvar_next(dvar)) {
107 for (j = 1; j < ac; ++j) {
108 if (!strncmp(dvar->name, av[j], strlen(av[j])))
111 if (ac > 1 && j == ac)
114 printf("%s=", dvar->name);
115 for (i = 0; i < dvar->count; ++i) {
118 printf("\"%s\"", dvar->data[i]);
126 * local command intercept for blah=blah
129 data = strchr(name, '=');
131 sprintf(command_errbuf, "Bad variable syntax");
137 dvar_set(name, &data, 1);
142 * Take care of loader tunables and several other variables,
143 * all of which have to mirror to kenv because libstand or
144 * other consumers may have hooks into them.
146 if (strchr(name, '.')) {
147 setenv(name, data, 1);
149 for (i = 0; kenv_vars[i] != NULL; i++) {
150 if (strcmp(name, kenv_vars[i]) == 0) {
151 setenv(name, data, 1);
160 * Unset local variables
163 command_lunset(int ac, char **av)
167 for (i = 1; i < ac; ++i)
173 command_lunsetif(int ac, char **av)
178 sprintf(command_errbuf,
179 "syntax error use lunsetif lname envname");
182 envdata = getenv(av[2]);
183 if (strcmp(envdata, "yes") == 0 ||
184 strcmp(envdata, "YES") == 0 ||
185 strtol(envdata, NULL, 0)) {
192 * Load the kernel + all modules specified with
195 command_loadall(int ac, char **av)
209 (void)perform(1, argv);
215 argv[1] = getenv("kernelname");
216 argv[2] = getenv("kernel_options");
218 argv[1] = strdup("kernel");
219 res = perform((argv[2] == NULL)?2:3, argv);
225 printf("Unable to load %s%s\n", DirBase, argv[1]);
232 for (dvar = dvar_first(); dvar; dvar = dvar_next(dvar)) {
233 len = strlen(dvar->name);
234 if (len <= 5 || strcmp(dvar->name + len - 5, "_load"))
236 if (strcmp(dvar->data[0], "yes") != 0 &&
237 strcmp(dvar->data[0], "YES") != 0) {
241 mod_name = strdup(dvar->name);
242 mod_name[len - 5] = 0;
246 /* Check if there's a matching foo_type */
247 for (dvar2 = dvar_first();
248 dvar2 && (mod_type == NULL);
249 dvar2 = dvar_next(dvar2)) {
250 len = strlen(dvar2->name);
251 if (len <= 5 || strcmp(dvar2->name + len - 5, "_type"))
253 tmp_str = strdup(dvar2->name);
254 tmp_str[len - 5] = 0;
255 if (strcmp(tmp_str, mod_name) == 0)
256 mod_type = dvar2->data[0];
261 /* Check if there's a matching foo_name */
262 for (dvar2 = dvar_first();
263 dvar2 && (mod_fname == NULL);
264 dvar2 = dvar_next(dvar2)) {
265 len = strlen(dvar2->name);
266 if (len <= 5 || strcmp(dvar2->name + len - 5, "_name"))
268 tmp_str = strdup(dvar2->name);
269 tmp_str[len - 5] = 0;
270 if (strcmp(tmp_str, mod_name) == 0) {
271 mod_fname = dvar2->data[0];
273 mod_name = strdup(mod_fname);
289 tmp = perform(argc, argv);
291 time_t t = time(NULL);
292 printf("Unable to load %s%s\n", DirBase, mod_name);
293 while (time(NULL) == t)
295 /* don't kill the boot sequence */
307 command_menuclear(int ac, char **av)
309 dvar_unset("menu_*");
310 dvar_unset("item_*");
320 command_menuitem(int ac, char **av)
326 sprintf(command_errbuf, "Bad menuitem syntax");
329 curitem = (unsigned char)av[1][0];
331 sprintf(command_errbuf, "Bad menuitem syntax");
334 snprintf(namebuf, sizeof(namebuf), "menu_%c", curitem);
335 dvar_set(namebuf, &av[2], 1);
345 command_menuadd(int ac, char **av)
353 sprintf(command_errbuf, "Missing menuitem for menuadd");
356 snprintf(namebuf, sizeof(namebuf), "item_%c_%d", curitem, curadd);
357 dvar_set(namebuf, &av[1], ac - 1);
363 * Execute menu system
366 command_menu(int ac, char **av)
378 if ((cp = getenv("autoboot_delay")) != NULL)
379 timeout = strtol(cp, NULL, 0);
382 if (timeout > 24 * 60 * 60)
383 timeout = 24 * 60 * 60;
385 time_target = time(NULL) + timeout;
391 if (c == '\r' || c == '\n') {
397 printf("\rCountdown halted by "
404 setenv("autoboot_delay", "NO", 1);
407 res = menu_execute(c);
409 setenv("autoboot_delay", "NO", 1);
412 /* else ignore char */
419 printf("\rBooting in %d second%s... ",
420 (int)(time_target - t),
421 ((time_target - t) == 1 ? "" : "s"));
422 if ((int)(time_target - t) <= 0) {
428 res = menu_execute(c);
430 setenv("autoboot_delay", "NO", 1);
439 for (dvar = dvar_first(); dvar; dvar = dvar_next(dvar)) {
440 if (strncmp(dvar->name, "menu_", 5) == 0) {
441 printf("%c. %s\n", dvar->name[5], dvar->data[0]);
456 snprintf(namebuf, sizeof(namebuf), "item_%c_0", c);
459 * Does this menu option exist?
461 if (dvar_get(namebuf) == NULL)
464 snprintf(namebuf, sizeof(namebuf), "item_%c", c);
466 for (dvar = dvar_first(); dvar; dvar = dvar_next(dvar)) {
467 if (strncmp(dvar->name, namebuf, 6) == 0) {
468 res = perform(dvar->count, dvar->data);
471 dvar->data[0], command_errmsg);
472 setenv("autoboot_delay", "NO", 1);