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[] = {
87 * Set local variable. Sniff "module_path"
89 * format a=b (one argument) - in av[0]
92 command_local(int ac, char **av)
101 * local command executed directly.
103 if (strcmp(av[0], "local") == 0) {
104 for (dvar = dvar_first(); dvar; dvar = dvar_next(dvar)) {
105 for (j = 1; j < ac; ++j) {
106 if (!strncmp(dvar->name, av[j], strlen(av[j])))
109 if (ac > 1 && j == ac)
112 printf("%s=", dvar->name);
113 for (i = 0; i < dvar->count; ++i) {
116 printf("\"%s\"", dvar->data[i]);
124 * local command intercept for blah=blah
127 data = strchr(name, '=');
129 sprintf(command_errbuf, "Bad variable syntax");
135 dvar_set(name, &data, 1);
140 * Take care of loader tunables and several other variables,
141 * all of which have to mirror to kenv because libstand or
142 * other consumers may have hooks into them.
144 if (strchr(name, '.')) {
145 setenv(name, data, 1);
147 for (i = 0; kenv_vars[i] != NULL; i++) {
148 if (strcmp(name, kenv_vars[i]) == 0) {
149 setenv(name, data, 1);
158 * Unset local variables
161 command_lunset(int ac, char **av)
165 for (i = 1; i < ac; ++i)
171 command_lunsetif(int ac, char **av)
176 sprintf(command_errbuf,
177 "syntax error use lunsetif lname envname");
180 envdata = getenv(av[2]);
181 if (strcmp(envdata, "yes") == 0 ||
182 strcmp(envdata, "YES") == 0 ||
183 strtol(envdata, NULL, 0)) {
190 * Load the kernel + all modules specified with
193 command_loadall(int ac, char **av)
203 (void)perform(1, argv);
209 argv[1] = getenv("kernelname");
211 argv[1] = strdup("kernel");
212 res = perform(2, argv);
216 printf("Unable to load %s%s\n", DirBase, argv[1]);
223 for (dvar = dvar_first(); dvar; dvar = dvar_next(dvar)) {
224 len = strlen(dvar->name);
225 if (len <= 5 || strcmp(dvar->name + len - 5, "_load"))
227 if (strcmp(dvar->data[0], "yes") != 0 &&
228 strcmp(dvar->data[0], "YES") != 0) {
232 argv[1] = strdup(dvar->name);
233 argv[1][len - 5] = 0;
234 tmp = perform(2, argv);
237 time_t t = time(NULL);
238 printf("Unable to load %s%s\n", DirBase, argv[1]);
239 while (time(NULL) == t)
241 /* don't kill the boot sequence */
253 command_menuclear(int ac, char **av)
255 dvar_unset("menu_*");
256 dvar_unset("item_*");
266 command_menuitem(int ac, char **av)
272 sprintf(command_errbuf, "Bad menuitem syntax");
275 curitem = (unsigned char)av[1][0];
277 sprintf(command_errbuf, "Bad menuitem syntax");
280 snprintf(namebuf, sizeof(namebuf), "menu_%c", curitem);
281 dvar_set(namebuf, &av[2], 1);
291 command_menuadd(int ac, char **av)
299 sprintf(command_errbuf, "Missing menuitem for menuadd");
302 snprintf(namebuf, sizeof(namebuf), "item_%c_%d", curitem, curadd);
303 dvar_set(namebuf, &av[1], ac - 1);
309 * Execute menu system
312 command_menu(int ac, char **av)
324 if ((cp = getenv("autoboot_delay")) != NULL)
325 timeout = strtol(cp, NULL, 0);
328 if (timeout > 24 * 60 * 60)
329 timeout = 24 * 60 * 60;
331 time_target = time(NULL) + timeout;
337 if (c == '\r' || c == '\n') {
343 printf("\rCountdown halted by "
350 setenv("autoboot_delay", "NO", 1);
353 res = menu_execute(c);
355 setenv("autoboot_delay", "NO", 1);
358 /* else ignore char */
365 printf("\rBooting in %d second%s... ",
366 (int)(time_target - t),
367 ((time_target - t) == 1 ? "" : "s"));
368 if ((int)(time_target - t) <= 0) {
374 res = menu_execute(c);
376 setenv("autoboot_delay", "NO", 1);
385 for (dvar = dvar_first(); dvar; dvar = dvar_next(dvar)) {
386 if (strncmp(dvar->name, "menu_", 5) == 0) {
387 printf("%c. %s\n", dvar->name[5], dvar->data[0]);
402 snprintf(namebuf, sizeof(namebuf), "item_%c_0", c);
405 * Does this menu option exist?
407 if (dvar_get(namebuf) == NULL)
410 snprintf(namebuf, sizeof(namebuf), "item_%c", c);
412 for (dvar = dvar_first(); dvar; dvar = dvar_next(dvar)) {
413 if (strncmp(dvar->name, namebuf, 6) == 0) {
414 res = perform(dvar->count, dvar->data);
417 dvar->data[0], command_errmsg);
418 setenv("autoboot_delay", "NO", 1);