source: trunk/filo/main/grub/builtins.c

Last change on this file was 121, checked in by stepan, 4 years ago

fix "default"

Signed-off-by: Stefan Reinauer <stepan@…>

File size: 40.8 KB
Line 
1/*
2 * This file is part of FILO.
3 *
4 *  Copyright (C) 1999,2000,2001,2002,2004  Free Software Foundation, Inc.
5 *  Copyright (C) 2005-2010 coresystems GmbH
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19 */
20
21#include <libpayload-config.h>
22#include <libpayload.h>
23#include <getopt.h>
24
25#include <config.h>
26#include <fs.h>
27#include <lib.h>
28#include <grub/shared.h>
29#include <arch/timer.h>
30#ifdef CONFIG_USE_MD5_PASSWORDS
31#include <grub/md5.h>
32#endif
33#include <pci.h>
34
35/* The default entry.  */
36int default_entry = 0;
37
38int current_entryno;
39
40// from disk_io:
41int buf_drive = -1;
42unsigned long current_drive = GRUB_INVALID_DRIVE;
43// from common.c:
44unsigned long saved_drive;
45unsigned long saved_partition;
46unsigned long saved_mem_upper;
47// other..
48unsigned long install_partition = 0x20000;
49unsigned long boot_drive = 0;
50char config_file[128] = "\0";
51
52kernel_t kernel_type;
53
54/* The fallback entry.  */
55int fallback_entryno;
56int fallback_entries[MAX_FALLBACK_ENTRIES];
57
58int grub_timeout = -1;
59
60/* The password.  */
61char *password = NULL;
62/* The password type.  */
63password_t password_type;
64/* The flag for indicating that the user is authoritative.  */
65int auth = 0;
66
67/* -------- FILO logic -------- */
68#define BOOT_LINE_LENGTH 1024
69char boot_line[BOOT_LINE_LENGTH] = { 0 };
70char root_device[16] = { 0 };
71/* ---------------------------- */
72
73/* temporary space for run time checks */
74static char temp_space[BOOT_LINE_LENGTH];
75char initrd_space[BOOT_LINE_LENGTH]="\0";
76
77int show_menu = 1;
78
79static int last_normal_color = -1, last_highlight_color = -1;
80
81/* Initialize the data for builtins.  */
82void init_builtins(void)
83{
84        kernel_type = KERNEL_TYPE_NONE;
85}
86
87/* Initialize the data for the configuration file.  */
88void init_config(void)
89{
90        password = NULL;
91        fallback_entryno = -1;
92        fallback_entries[0] = -1;
93        grub_timeout = -1;
94}
95
96int check_password(char *entered, char *expected, password_t type)
97{
98        switch (type) {
99        case PASSWORD_PLAIN:
100                return strcmp(entered, expected);
101#ifdef CONFIG_USE_MD5_PASSWORDS
102        case PASSWORD_MD5:
103                return check_md5_password(entered, expected);
104#endif
105        default:
106                /* unsupported password type: be secure */
107                return 1;
108        }
109}
110
111/* boot */
112static int boot_func(char *arg, int flags)
113{
114        int boot(const char *line);
115        int ret;
116
117        if(!boot_line[0]) {
118                errnum = ERR_BOOT_COMMAND;
119                return 1;
120        }
121
122        /* Set color back to black and white, or Linux booting will look
123         * very funny.
124         */
125        console_setcolor((COLOR_BLACK << 4) | COLOR_WHITE,
126                         (COLOR_WHITE << 4) | COLOR_BLACK);
127
128        cls();
129
130        if (initrd_space[0]) {
131                strncat(boot_line, " initrd=", BOOT_LINE_LENGTH);
132                strncat(boot_line, initrd_space, BOOT_LINE_LENGTH);
133        }
134
135        grub_printf("\nBooting '%s'\n", boot_line);
136
137        ret = boot(boot_line);
138
139        /* If we regain control, something went wrong. */
140
141        /* The menu color was changed and we failed to boot, so we
142         * need to restore the colors in order to make the menu look as
143         * it did before.
144         */
145        if (last_normal_color != -1) {
146                console_setcolor(last_normal_color, last_highlight_color);
147        }
148
149        /* If no loader felt responsible for this image format, it's
150         * a bad file format, otherwise we don't really know.
151         */
152        if (ret == LOADER_NOT_SUPPORT)
153                errnum = ERR_EXEC_FORMAT;
154        else
155                errnum = ERR_BOOT_FAILURE;
156
157        return 1;
158}
159
160static struct builtin builtin_boot = {
161        "boot",
162        boot_func,
163        BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
164        "boot",
165        "Boot the OS/chain-loader which has been loaded."
166};
167
168
169/* color */
170/* Set new colors used for the menu interface. Support two methods to
171 *    specify a color name: a direct integer representation and a symbolic
172 *       color name. An example of the latter is "blink-light-gray/blue".  */
173static int color_func(char *arg, int flags)
174{
175        char *normal;
176        char *highlight;
177        int new_normal_color;
178        int new_highlight_color;
179        static char *color_list[16] = {
180                "black",
181                "red",
182                "green",
183                "brown",
184                "blue",
185                "magenta",
186                "cyan",
187                "light-gray",
188                "dark-gray",
189                "light-red",
190                "light-green",
191                "yellow",
192                "light-blue",
193                "light-magenta",
194                "light-cyan",
195                "white"
196        };
197
198        auto int color_number(char *str);
199
200        /* Convert the color name STR into a VGA color number.  */
201        auto int color_number(char *str) {
202                char *ptr;
203                int i;
204                int color = 0;
205
206                /* Find the separator.  */
207                for (ptr = str; *ptr && *ptr != '/'; ptr++);
208
209                /* If not found, return -1.  */
210                if (!*ptr)
211                        return -1;
212
213                /* Terminate the string STR.  */
214                *ptr++ = 0;
215
216                /* If STR contains the prefix "blink-", then set the `blink' bit in COLOR.  */
217                if (substring("blink-", str) <= 0) {
218                        color = 0x80;
219                        str += 6;
220                }
221
222                /* Search for the foreground color name.  */
223                for (i = 0; i < 16; i++)
224                        if (strcmp(color_list[i], str) == 0) {
225                                color |= i;
226                                break;
227                        }
228
229                if (i == 16)
230                        return -1;
231
232                str = ptr;
233                nul_terminate(str);
234
235                /* Search for the background color name.  */
236                for (i = 0; i < 8; i++)
237                        if (strcmp(color_list[i], str) == 0) {
238                                color |= (i <<4);
239                                break;
240                        }
241
242                if (i == 8)
243                        return -1;
244
245                return color;
246        }
247
248        normal = arg;
249        highlight = skip_to(0, arg);
250
251        new_normal_color = color_number(normal);
252        if (new_normal_color < 0 && !safe_parse_maxint(&normal, &new_normal_color)) {
253                errnum = ERR_BAD_ARGUMENT;
254                return 1;
255        }
256
257        /* The second argument is optional, so set highlight_color to inverted NORMAL_COLOR.  */
258        if (!*highlight)
259                new_highlight_color = ((new_normal_color >> 4)
260                                       | ((new_normal_color & 0xf) << 4));
261        else {
262                new_highlight_color = color_number(highlight);
263                if (new_highlight_color < 0 && !safe_parse_maxint(&highlight, &new_highlight_color)) {
264                        errnum = ERR_BAD_ARGUMENT;
265                        return 1;
266                }
267        }
268
269        console_setcolor(new_normal_color, new_highlight_color);
270
271        // keep the state so we can restore after a failed boot
272        last_normal_color = new_normal_color;
273        last_highlight_color = new_highlight_color;
274
275        return 0;
276}
277
278static struct builtin builtin_color = {
279        "color",
280        color_func,
281        BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
282        "color NORMAL [HIGHLIGHT]",
283        "Change the menu colors. The color NORMAL is used for most"
284            " lines in the menu, and the color HIGHLIGHT is used to highlight the"
285            " line where the cursor points. If you omit HIGHLIGHT, then the"
286            " inverted color of NORMAL is used for the highlighted line."
287            " The format of a color is \"FG/BG\". FG and BG are symbolic color names."
288            " A symbolic color name must be one of these: black, blue, green,"
289            " cyan, red, magenta, brown, light-gray, dark-gray, light-blue,"
290            " light-green, light-cyan, light-red, light-magenta, yellow and white."
291            " But only the first eight names can be used for BG. You can prefix"
292            " \"blink-\" to FG if you want a blinking foreground color."
293};
294
295static int help_func(char *arg, int flags);
296/* configfile */
297static int configfile_func(char *arg, int flags)
298{
299        extern int is_opened, keep_cmdline_running;
300
301        /* Check if the file ARG is present.  */
302        temp_space[0]=0;
303        copy_path_to_filo_bootline(arg, temp_space, 1);
304        if (temp_space[0]==0) {
305                return help_func("configfile",0);
306        }
307        if (!file_open(temp_space)) {
308                errnum = ERR_FILE_NOT_FOUND;
309                return 1;
310        }
311
312        file_close();
313
314        /* Copy ARG to CONFIG_FILE.  */
315        memset(config_file, 0, 128);
316        copy_path_to_filo_bootline(arg, config_file, 1);
317
318        /* Force to load the configuration file.  */
319        is_opened = 0;
320        keep_cmdline_running = 0;
321
322        /* Make sure that the user will not be authoritative.  */
323        auth = 0;
324
325        return 0;
326}
327
328static struct builtin builtin_configfile = {
329        "configfile",
330        configfile_func,
331        BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
332        "configfile FILE",
333        "Load FILE as the configuration file."
334};
335
336/* default */
337static int default_func(char *arg, int flags)
338{
339        unsigned char buf[1];
340        if (get_option(buf, "boot_default"))
341                buf[0] = 0xff;
342       
343        if ((unsigned char)buf[0] != 0xff) {
344                printf("Default override by CMOS.\n");
345                return 0;
346        }
347
348        if (!safe_parse_maxint(&arg, &default_entry))
349                return 1;
350
351        return 0;
352}
353
354static struct builtin builtin_default = {
355        "default",
356        default_func,
357        BUILTIN_MENU,
358#if 0
359        "default [NUM]",
360        "Set the default entry to entry number NUM (if not specified, it is"
361            " 0, the first entry) or the entry number saved by savedefault."
362#endif
363};
364
365#if CONFIG_DEVELOPER_TOOLS
366/* dumpmem */
367static int dumpmem_func(char *arg, int flags)
368{
369        int ret = string_to_args("dumpmem", arg);
370        unsigned int mem_base, mem_len;
371        void *i;
372
373        if(ret || (string_argc != 3)) {
374                errnum = ERR_BAD_ARGUMENT;
375                return 1;
376        }
377
378        // FIXME
379        if (!safe_parse_maxint(&string_argv[1], &mem_base))
380                return 1;
381        if (!safe_parse_maxint(&string_argv[2], &mem_len))
382                return 1;
383
384        grub_printf("Dumping memory at 0x%08x (0x%x bytes)\n",
385                        mem_base, mem_len);
386
387        for (i=phys_to_virt(mem_base); i<phys_to_virt(mem_base + mem_len); i++) {
388                if (((unsigned long)i & 0x0f) == 0)
389                        grub_printf("\n%08x:", i);
390                unsigned char val = *((unsigned char *)i);
391                grub_printf(" %02x", val);
392        }
393        grub_printf("\n");
394
395        return 0;
396}
397
398static struct builtin builtin_dumpmem = {
399        "dumpmem",
400        dumpmem_func,
401        BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
402        "dumpmem",
403        "Dump memory"
404};
405
406/* dumppm */
407static int dumppm_func(char *arg, int flags)
408{
409        u16 pmbase;
410
411        pmbase = pci_read_config16(PCI_DEV(0,0x1f, 0), 0x40) & 0xfffe;
412
413        grub_printf("pmbase+0x0000: 0x%04x     (PM1_STS)\n", inw(pmbase+0x0000));
414        grub_printf("pmbase+0x0002: 0x%04x     (PM1_EN)\n", inw(pmbase+0x0002));
415        grub_printf("pmbase+0x0004: 0x%08x (PM1_CNT)\n", inl(pmbase+0x0004));
416        grub_printf("pmbase+0x0008: 0x%08x (PM1_TMR)\n", inl(pmbase+0x0008));
417        grub_printf("pmbase+0x0010: 0x%08x (PROC_CNT)\n", inl(pmbase+0x0010));
418        grub_printf("pmbase+0x0020: 0x%08x (PM2_CNT)\n", inl(pmbase+0x0020));
419        grub_printf("pmbase+0x0028: 0x%08x (GPE0_STS)\n", inl(pmbase+0x0028));
420        grub_printf("pmbase+0x002c: 0x%08x (GPE0_EN)\n", inl(pmbase+0x002c));
421        grub_printf("pmbase+0x0030: 0x%08x (SMI_EN)\n", inl(pmbase+0x0030));
422        grub_printf("pmbase+0x0034: 0x%08x (SMI_STS)\n", inl(pmbase+0x0034));
423        grub_printf("pmbase+0x0038: 0x%04x     (ALT_GP_SMI_EN)\n", inw(pmbase+0x0038));
424        grub_printf("pmbase+0x003a: 0x%04x     (ALT_GP_SMI_STS)\n", inw(pmbase+0x003a));
425        grub_printf("pmbase+0x0042: 0x%02x       (GPE_CNTL)\n", inb(pmbase+0x0042));
426        grub_printf("pmbase+0x0044: 0x%04x     (DEVACT_STS)\n", inw(pmbase+0x0044));
427        grub_printf("pmbase+0x0050: 0x%02x       (SS_CNT)\n", inb(pmbase+0x0050));
428        grub_printf("pmbase+0x0054: 0x%08x (C3_RES)\n", inl(pmbase+0x0054));
429#if 0
430        // TCO
431        grub_printf("pmbase+0x0060: 0x%04x     (TCO_RLD)\n", inw(pmbase+0x0060));
432        grub_printf("pmbase+0x0062: 0x%02x       (TCO_DAT_IN)\n", inb(pmbase+0x0062));
433        grub_printf("pmbase+0x0063: 0x%02x       (TCO_DAT_OUT)\n", inb(pmbase+0x0063));
434        grub_printf("pmbase+0x0064: 0x%04x     (TCO1_STS)\n", inw(pmbase+0x0064));
435        grub_printf("pmbase+0x0066: 0x%04x     (TCO2_STS)\n", inw(pmbase+0x0066));
436        grub_printf("pmbase+0x0068: 0x%04x     (TCO1_CNT)\n", inw(pmbase+0x0068));
437        grub_printf("pmbase+0x006a: 0x%04x     (TCO2_CNT)\n", inw(pmbase+0x006a));
438        grub_printf("pmbase+0x006c: 0x%04x     (TCO_MESSAGE)\n", inw(pmbase+0x006c));
439        grub_printf("pmbase+0x006e: 0x%02x       (TCO_WDCNT)\n", inb(pmbase+0x006e));
440        grub_printf("pmbase+0x0070: 0x%02x       (TCO_SW_IRQ_GEN)\n", inb(pmbase+0x0070));
441        grub_printf("pmbase+0x0072: 0x%04x     (TCO_TMR)\n", inw(pmbase+0x0072));
442#endif
443        return 0;
444}
445
446static struct builtin builtin_dumppm = {
447        "dumppm",
448        dumppm_func,
449        BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
450        "dumppm",
451        "Dump Powermanagement registers"
452};
453#endif
454
455#if CONFIG_EXPERIMENTAL
456#warning "FIND not implemented yet."
457/* find */
458/* Search for the filename ARG in all of partitions.  */
459static int find_func(char *arg, int flags)
460{
461        char *filename = arg;
462        int got_file = 0;
463
464        // the grub find works like this:
465        //
466        // for all disks
467        //   for all partitions on disk
468        //     open file
469        //     if file exists
470        //        print partition name
471        //        set got_file to 1
472        //
473        // dont they search all subdirectories? Thats a dumb find then.. :(
474
475        /* We want to ignore any error here.  */
476        errnum = ERR_NONE;
477
478        if (got_file) {
479                errnum = ERR_NONE;
480                return 0;
481        }
482
483        errnum = ERR_FILE_NOT_FOUND;
484        return 1;
485}
486
487static struct builtin builtin_find = {
488        "find",
489        find_func,
490        BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
491        "find FILENAME",
492        "Search for the filename FILENAME in all of partitions and print the list of"
493            " the devices which contain the file."
494};
495#endif
496
497/* help */
498#define MAX_SHORT_DOC_LEN       39
499#define MAX_LONG_DOC_LEN        66
500
501static int help_func(char *arg, int flags)
502{
503        int all = 0;
504
505        if (memcmp(arg, "--all", sizeof("--all") - 1) == 0) {
506                all = 1;
507                arg = skip_to(0, arg);
508        }
509
510        if (!*arg) {
511                /* Invoked with no argument. Print the list of the short docs.  */
512                struct builtin **builtin;
513                int left = 1;
514
515                for (builtin = builtin_table; *builtin != 0; builtin++) {
516                        int len;
517                        int i;
518
519                        /* If this cannot be used in the command-line interface,
520                           skip this.  */
521                        if (!((*builtin)->flags & BUILTIN_CMDLINE))
522                                continue;
523
524                        /* If this doesn't need to be listed automatically and "--all"
525                           is not specified, skip this.  */
526                        if (!all && !((*builtin)->flags & BUILTIN_HELP_LIST))
527                                continue;
528
529                        len = strlen((*builtin)->short_doc);
530                        /* If the length of SHORT_DOC is too long, truncate it.  */
531                        if (len > MAX_SHORT_DOC_LEN - 1)
532                                len = MAX_SHORT_DOC_LEN - 1;
533
534                        for (i = 0; i < len; i++)
535                                grub_putchar((*builtin)->short_doc[i]);
536
537                        for (; i < MAX_SHORT_DOC_LEN; i++)
538                                grub_putchar(' ');
539
540
541                        if (!left)
542                                grub_putchar('\n');
543
544                        left = !left;
545                }
546
547                /* If the last entry was at the left column, no newline was printed
548                   at the end.  */
549                if (!left)
550                        grub_putchar('\n');
551        } else {
552                /* Invoked with one or more patterns.  */
553                do {
554                        struct builtin **builtin;
555                        char *next_arg;
556
557                        /* Get the next argument.  */
558                        next_arg = skip_to(0, arg);
559
560                        /* Terminate ARG.  */
561                        nul_terminate(arg);
562
563                        for (builtin = builtin_table; *builtin; builtin++) {
564                                /* Skip this if this is only for the configuration file.  */
565                                if (!((*builtin)->flags & BUILTIN_CMDLINE))
566                                        continue;
567
568                                if (substring(arg, (*builtin)->name) < 1) {
569                                        char *doc = (*builtin)->long_doc;
570
571                                        /* At first, print the name and the short doc.  */
572                                        grub_printf("%s: %s\n", (*builtin)->name, (*builtin)->short_doc);
573
574                                        /* Print the long doc.  */
575                                        while (*doc) {
576                                                int len = strlen(doc);
577                                                int i;
578
579                                                /* If LEN is too long, fold DOC.  */
580                                                if (len > MAX_LONG_DOC_LEN) {
581                                                        /* Fold this line at the position of a space.  */
582                                                        for (len = MAX_LONG_DOC_LEN; len > 0; len--)
583                                                                if (doc[len - 1] == ' ')
584                                                                        break;
585                                                }
586
587                                                grub_putstr("    ");
588                                                for (i = 0; i < len; i++)
589                                                        grub_putchar(*doc++);
590                                                grub_putchar('\n');
591                                        }
592                                }
593                        }
594
595                        arg = next_arg;
596                }
597                while (*arg);
598        }
599        refresh();
600        return 0;
601}
602
603static struct builtin builtin_help = {
604        "help",
605        help_func,
606        BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
607        "help [--all] [PATTERN ...]",
608        "Display helpful information about builtin commands. Not all commands"
609            " aren't shown without the option `--all'."
610};
611
612/* hiddenmenu */
613static int hiddenmenu_func(char *arg, int flags)
614{
615        show_menu = 0;
616        return 0;
617}
618
619static struct builtin builtin_hiddenmenu = {
620        "hiddenmenu",
621        hiddenmenu_func,
622        BUILTIN_MENU,
623#if 0
624        "hiddenmenu",
625        "Hide the menu."
626#endif
627};
628
629/**
630 * @param arg  source pointer with grub device names
631 * @param path destination pointer (will be filled with filo device names)
632 * @param use_rootdev values other than zero mean the root device set by the "root"
633 * command is taken into regard here. This has to be zero when calling from root_func.
634 */
635
636void copy_path_to_filo_bootline(char *arg, char *path, int use_rootdev)
637{
638        char devicename[16];
639        char drivername[16];
640        int disk, part;
641        int i, len;
642
643
644        /* Clean up */
645        memset(devicename, 0, 16);
646        memset(drivername, 0, 16);
647
648        /* Copy over the driver name: "hd", "ud", "sd" ... */
649        if (arg[0] == '(') {
650                i = 1;
651                /* Read until we encounter a number, a comma or a closing
652                 * bracket
653                 */
654                while ((i <= 16) && (arg[i]) && (!isdigit(arg[i])) && (arg[i] != ',')
655                       && (arg[i] != ')')) {
656                        drivername[i - 1] = arg[i];
657                        i++;
658                }
659        }
660
661        disk = -1;
662        part = -1;
663
664        len = strlen(drivername);
665        if (len) {              /* We have a driver. No idea if it exists though */
666                // The driver should decide this:
667                len++;          // skip driver name + opening bracket
668
669                // XXX put @ handling in here, too for flash@addr and mem@addr
670
671                if (isdigit(arg[len])) {
672                        disk = arg[len] - '0';
673                        len++;
674                        if (isdigit(arg[len])) {        /* More than 9 drives? */
675                                /* ok, get one more number. No more than 99 drives */
676                                disk *= 10;
677                                disk += arg[len] - '0';
678                                len++;
679                        }
680                }
681                if (arg[len] == ',') {
682                        len++;
683                        part = arg[len] - '0';
684                        len++;
685                        if (isdigit(arg[len])) {        /* More than 9 partitions? */
686                                /* ok, get one more number. No more than 99
687                                 * partitions */
688                                part *= 10;
689                                part += arg[len] - '0';
690                                len++;
691                        }
692                }
693                if (arg[len] != ')') {
694                        grub_printf("Drive Error.\n");
695                        // set len = 0 --> just copy the drive name
696                        len = 0;
697                } else {
698                        len++;  // skip closing bracket
699                }
700        }
701
702        if (disk == -1) {
703                int cnt = 0;
704                len = 0;
705                while ((arg[cnt] != 0) && (arg[cnt+1] != 0)) {
706                        if (arg[cnt] == ':' && arg[cnt+1] == '/') {
707                                /* The user did specify a FILO name already */
708                                len = cnt;
709                                break;
710                        }
711                        cnt++;
712                }
713        } else {
714                if (part == -1) {       // No partition
715                        sprintf(devicename, "%s%c:", drivername, disk + 'a');
716                } else {        // both disk and partition
717                        sprintf(devicename, "%s%c%d:", drivername, disk + 'a', part + 1);
718                }
719                strncat(path, devicename, BOOT_LINE_LENGTH);
720                arg += len;     // skip original drive name
721        }
722
723        if (use_rootdev && !len) {      // No drive was explicitly specified
724                if (strlen(root_device)) {      // But someone set a root device
725                        strncat(path, root_device, BOOT_LINE_LENGTH);
726                }
727        }
728
729        /* Copy the rest over */
730        strncat(path, arg, BOOT_LINE_LENGTH);
731}
732
733/* initrd */
734static int initrd_func(char *arg, int flags)
735{
736        initrd_space[0]=0; // Erase string
737        copy_path_to_filo_bootline(arg, initrd_space, 1);
738        if (!file_open(initrd_space)) {
739                initrd_space[0]=0; // Erase string
740                errnum = ERR_FILE_NOT_FOUND;
741                file_close();
742                return 1;
743        }
744
745        file_close();
746        return 0;
747}
748
749static struct builtin builtin_initrd = {
750        "initrd",
751        initrd_func,
752        BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
753        "initrd FILE [ARG ...]",
754        "Load an initial ramdisk FILE for a Linux format boot image and set the"
755            " appropriate parameters in the Linux setup area in memory."
756};
757
758
759#ifdef CONFIG_DEVELOPER_TOOLS
760/* io */
761static int io_func(char *arg, int flags)
762{
763        char *walk = arg;
764        unsigned int port = 0;
765        unsigned int value = 0;
766        unsigned int write_mode = 0;
767        unsigned int maxval=0xff, len=1;
768
769        while ((*walk != 0) && (*walk != '.') && (*walk != '=')) {
770                port *= 16;
771                port += hex2bin(*walk);
772                walk++;
773        }
774        if (port > 0xffff) {
775                grub_printf("port too high\n");
776                errnum = ERR_BAD_ARGUMENT;
777                return 1;
778        }
779
780        if (*walk == '.') {
781                walk++;
782                switch (*walk) {
783                case 'l':
784                case 'L':
785                        len = 4;
786                        maxval = 0xffffffff;
787                        break;
788                case 'w':
789                case 'W':
790                        len=2;
791                        maxval = 0xffff;
792                        break;
793                case 'b':
794                case 'B':
795                        len=1;
796                        maxval = 0xff;
797                        break;
798                default:
799                        grub_printf("width must be b, w, or l\n");
800                        errnum = ERR_BAD_ARGUMENT;
801                        return 1;
802                }
803                walk++;
804        }
805
806        if (*walk == '=') {
807                while (*walk!=0 && *walk != '.') {
808                        value *= 16;
809                        value += hex2bin(*walk);
810                        walk++;
811                }
812
813                if (value > maxval) {
814                        grub_printf("value too big.\n");
815                        errnum = ERR_BAD_ARGUMENT;
816                        return 1;
817                }
818
819                write_mode = 1;
820        }
821
822        if (write_mode) {
823                grub_printf ("out");
824                switch (len) {
825                case 1:
826                        grub_printf("b 0x%02x -> 0x%04x\n", value, port);
827                        outb(value, port);
828                        break;
829                case 2:
830                        grub_printf("w 0x%04x -> 0x%04x\n", value, port);
831                        outw(value, port);
832                        break;
833                case 4:
834                        grub_printf("l 0x%08x -> 0x%04x\n", value, port);
835                        outl(value, port);
836                        break;
837                }
838        } else {
839                grub_printf ("in");
840                switch (len) {
841                case 1:
842                        value = inb(port);
843                        grub_printf("b 0x%04x: 0x%02x\n", port, value);
844                        break;
845                case 2:
846                        value = inw(port);
847                        grub_printf("w 0x%04x: 0x%04x\n", port, value);
848                        break;
849                case 4:
850                        value = inl(port);
851                        grub_printf("l 0x%04x: 0x%08x\n", port, value);
852                        break;
853                }
854        }
855
856        return 0;
857}
858
859static struct builtin builtin_io = {
860        "io",
861        io_func,
862        BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST | BUILTIN_NO_ECHO,
863        "io port[.bwl][=val]",
864        "Read/write IO ports."
865};
866#endif
867
868/* kernel */
869static int kernel_func(char *arg, int flags)
870{
871        int i;
872
873        kernel_type = KERNEL_TYPE_NONE;
874
875        /* clear out boot_line. Kernel is the first thing */
876        boot_line[0] = 0;  // Erase string
877
878        /* Get the real boot line and extract the kernel name */
879        temp_space[0] = 0; // Erase string
880        copy_path_to_filo_bootline(arg, temp_space, 1);
881        i=0; while ((temp_space[i] != 0) && (temp_space[i]!=' ')) i++;
882        temp_space[i] = 0;
883
884        if (!file_open(temp_space)) {
885                errnum = ERR_FILE_NOT_FOUND;
886                file_close();
887                return 1;
888        }
889
890        file_close();
891
892        /* Needed to pass grub checks */
893        kernel_type = KERNEL_TYPE_LINUX;
894
895        copy_path_to_filo_bootline(arg, boot_line, 1);
896
897        return 0;
898}
899
900static struct builtin builtin_kernel = {
901        "kernel",
902        kernel_func,
903        BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
904        "kernel [--no-mem-option] [--type=TYPE] FILE [ARG ...]",
905        "Attempt to load the primary boot image from FILE. The rest of the"
906            " line is passed verbatim as the \"kernel command line\".  Any modules"
907            " must be reloaded after using this command. The option --type is used"
908            " to suggest what type of kernel to be loaded. TYPE must be either of"
909            " \"netbsd\", \"freebsd\", \"openbsd\", \"linux\", \"biglinux\" and"
910            " \"multiboot\". The option --no-mem-option tells GRUB not to pass a" " Linux's mem option automatically."
911};
912
913/* lock */
914static int lock_func(char *arg, int flags)
915{
916        if (!auth && password) {
917                errnum = ERR_PRIVILEGED;
918                return 1;
919        }
920
921        return 0;
922}
923
924static struct builtin builtin_lock = {
925        "lock",
926        lock_func,
927        BUILTIN_CMDLINE,
928        "lock",
929        "Break a command execution unless the user is authenticated."
930};
931
932#ifdef CONFIG_DEVELOPER_TOOLS
933static int lspci_indent = 0;
934static void lspci_scan_bus(int bus)
935{
936        int slot, func;
937        unsigned int val;
938        unsigned char hdr;
939        int i;
940
941        for (slot = 0; slot < 0x20; slot++) {
942                for (func = 0; func < 8; func++) {
943                        pcidev_t dev = PCI_DEV(bus, slot, func);
944
945                        val = pci_read_config32(dev, REG_VENDOR_ID);
946
947                        /* Nobody home. */
948                        if (val == 0xffffffff || val == 0x00000000 ||
949                            val == 0x0000ffff || val == 0xffff0000)
950                                continue;
951
952                        for (i=0; i<lspci_indent; i++)
953                                grub_printf("|  ");
954                        grub_printf("|- %02x:%02x.%x [%04x:%04x]\n", bus, slot, func,
955                                        val & 0xffff, val >> 16);
956
957                        /* If this is a bridge, then follow it. */
958                        hdr = pci_read_config8(dev, REG_HEADER_TYPE);
959                        hdr &= 0x7f;
960                        if (hdr == HEADER_TYPE_BRIDGE ||
961                            hdr == HEADER_TYPE_CARDBUS) {
962                                unsigned int busses;
963
964                                busses = pci_read_config32(dev, REG_PRIMARY_BUS);
965                                lspci_indent++;
966                                lspci_scan_bus((busses >> 8) & 0xff);
967                                lspci_indent--;
968                        }
969                }
970        }
971}
972
973static void lspci_configspace(pcidev_t dev)
974{
975        unsigned char cspace[256];
976        int i, x, y;
977
978        for (i = 0; i < 256; i ++)
979                cspace[i] = pci_read_config8(dev, i);
980
981        for (y = 0; y < 16; y++) {
982                grub_printf("%x0:", y);
983                for (x = 0; x < 16; x++)
984                        grub_printf(" %02x", cspace[(y * 16) + x]);
985                grub_printf("\n");
986        }
987
988        grub_printf("\n");
989}
990
991static int lspci_func(char *arg, int flags)
992{
993        char *walk = arg;
994        int bus, slot, fn;
995
996        if(strlen(walk)) {
997                pcidev_t dev;
998
999                if((walk[1] != ':') && (walk[2] =! ':'))
1000                        goto out;
1001                if(walk[1] == ':') {
1002                        bus = hex2bin(walk[0]);
1003                        walk+=2;
1004                } else {
1005                        bus = (hex2bin(walk[0]) * 16) + hex2bin(walk[1]);
1006                        walk+=3;
1007                }
1008                if((walk[1] != '.') && (walk[2] =! '.'))
1009                        goto out;
1010
1011                if(walk[1] == '.') {
1012                        slot = hex2bin(walk[0]);
1013                        walk+=2;
1014                } else {
1015                        slot = (hex2bin(walk[0]) * 16) + hex2bin(walk[1]);
1016                        walk+=3;
1017                }
1018                if (!walk[0])
1019                        goto out;
1020
1021                fn=hex2bin(walk[0]);
1022
1023                grub_printf("Dumping %x:%x.%x\n", bus, slot, fn);
1024
1025                dev = PCI_DEV(bus, slot, fn);
1026                lspci_configspace(dev);
1027                return 0;
1028        }
1029out:
1030        lspci_scan_bus(0);
1031        return 0;
1032}
1033
1034static struct builtin builtin_lspci = {
1035        "lspci",
1036        lspci_func,
1037        BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST | BUILTIN_NO_ECHO,
1038        "lspci <device>",
1039        "Show PCI devices or dump PCI config space"
1040};
1041#endif
1042
1043#ifdef CONFIG_USE_MD5_PASSWORDS
1044/* md5crypt */
1045static int md5crypt_func(char *arg, int flags)
1046{
1047        char crypted[36];
1048        char key[32];
1049        unsigned int seed;
1050        int i;
1051        const char *const seedchars = "./0123456789ABCDEFGHIJKLMNOPQRST" "UVWXYZabcdefghijklmnopqrstuvwxyz";
1052
1053        /* First create a salt.  */
1054
1055        /* The magical prefix.  */
1056        memset(crypted, 0, sizeof(crypted));
1057        memmove(crypted, "$1$", 3);
1058
1059        /* Create the length of a salt.  */
1060        seed = currticks();
1061
1062        /* Generate a salt.  */
1063        for (i = 0; i < 8 && seed; i++) {
1064                /* FIXME: This should be more random.  */
1065                crypted[3 + i] = seedchars[seed & 0x3f];
1066                seed >>= 6;
1067        }
1068
1069        /* A salt must be terminated with `$', if it is less than 8 chars.  */
1070        crypted[3 + i] = '$';
1071
1072#ifdef CONFIG_DEBUG_MD5CRYPT
1073        grub_printf("salt = %s\n", crypted);
1074#endif
1075
1076        /* Get a password.  */
1077        memset(key, 0, sizeof(key));
1078        get_cmdline("Password: ", key, sizeof(key) - 1, '*', 0);
1079
1080        /* Crypt the key.  */
1081        make_md5_password(key, crypted);
1082
1083        grub_printf("Encrypted: %s\n", crypted);
1084        return 0;
1085}
1086
1087static struct builtin builtin_md5crypt = {
1088        "md5crypt",
1089        md5crypt_func,
1090        BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
1091        "md5crypt",
1092        "Generate a password in MD5 format."
1093};
1094#endif                          /* CONFIG_USE_MD5_PASSWORDS */
1095
1096/* password */
1097static int password_func(char *arg, int flags)
1098{
1099        int len;
1100        password_t type = PASSWORD_PLAIN;
1101
1102#ifdef CONFIG_USE_MD5_PASSWORDS
1103        if (memcmp(arg, "--md5", 5) == 0) {
1104                type = PASSWORD_MD5;
1105                arg = skip_to(0, arg);
1106        }
1107#endif
1108        if (memcmp(arg, "--", 2) == 0) {
1109                type = PASSWORD_UNSUPPORTED;
1110                arg = skip_to(0, arg);
1111        }
1112
1113        if ((flags & (BUILTIN_CMDLINE | BUILTIN_SCRIPT)) != 0) {
1114                /* Do password check! */
1115                char entered[32];
1116
1117                /* Wipe out any previously entered password */
1118                entered[0] = 0;
1119                get_cmdline("Password: ", entered, 31, '*', 0);
1120
1121                nul_terminate(arg);
1122                if (check_password(entered, arg, type) != 0) {
1123                        errnum = ERR_PRIVILEGED;
1124                        return 1;
1125                }
1126        } else {
1127                len = strlen(arg);
1128
1129                /* PASSWORD NUL NUL ... */
1130                if (len + 2 > PASSWORD_BUFLEN) {
1131                        errnum = ERR_WONT_FIT;
1132                        return 1;
1133                }
1134
1135                /* Copy the password and clear the rest of the buffer.  */
1136                password = (char *) PASSWORD_BUF;
1137                memmove(password, arg, len);
1138                memset(password + len, 0, PASSWORD_BUFLEN - len);
1139                password_type = type;
1140        }
1141        return 0;
1142}
1143
1144static struct builtin builtin_password = {
1145        "password",
1146        password_func,
1147        BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_NO_ECHO,
1148        "password [--md5] PASSWD [FILE]",
1149        "If used in the first section of a menu file, disable all"
1150            " interactive editing control (menu entry editor and"
1151            " command line). If the password PASSWD is entered, it loads the"
1152            " FILE as a new config file and restarts the GRUB Stage 2. If you"
1153            " omit the argument FILE, then GRUB just unlocks privileged"
1154            " instructions.  You can also use it in the script section, in"
1155            " which case it will ask for the password, before continueing."
1156            " The option --md5 tells GRUB that PASSWD is encrypted with" " md5crypt."
1157};
1158
1159/* pause */
1160static int pause_func(char *arg, int flags)
1161{
1162        grub_printf("%s\n", arg);
1163
1164        /* If ESC is returned, then abort this entry.  */
1165        if (ASCII_CHAR(getkey()) == 27)
1166                return 1;
1167
1168        return 0;
1169}
1170
1171static struct builtin builtin_pause = {
1172        "pause",
1173        pause_func,
1174        BUILTIN_CMDLINE | BUILTIN_NO_ECHO,
1175        "pause [MESSAGE ...]",
1176        "Print MESSAGE, then wait until a key is pressed."
1177};
1178
1179static int poweroff_func(char *arg, int flags)
1180{
1181        void __attribute__((weak)) platform_poweroff(void);
1182        if (platform_poweroff)
1183                platform_poweroff();
1184        else
1185                grub_printf("Poweroff not supported.\n");
1186
1187        // Will (hopefully) never return;
1188        return 0;
1189}
1190
1191static struct builtin builtin_poweroff = {
1192        "poweroff",
1193        poweroff_func,
1194        BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
1195        "poweroff",
1196        "Power off the system."
1197};
1198
1199#ifdef CONFIG_DEVELOPER_TOOLS
1200static int probe_func(char *arg, int flags)
1201{
1202#if CONFIG_IDE_DISK
1203        int i;
1204
1205        for (i=0; i<8; i++)
1206                ide_probe(i);
1207#elif CONFIG_IDE_NEW_DISK
1208        int i;
1209
1210        for (i=0; i<8; i++)
1211                ide_probe_verbose(i);
1212#else
1213        grub_printf("No IDE driver.\n");
1214#endif
1215
1216        return 0;
1217}
1218
1219static struct builtin builtin_probe = {
1220        "probe",
1221        probe_func,
1222        BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
1223        "probe",
1224        "Probe IDE drives"
1225};
1226#endif
1227
1228static int reboot_func(char *arg, int flags)
1229{
1230        void __attribute__((weak)) platform_reboot(void);
1231
1232        if (platform_reboot)
1233                platform_reboot();
1234        else
1235                grub_printf("Reboot not supported.\n");
1236
1237        // Will (hopefully) never return;
1238        return 0;
1239}
1240
1241static struct builtin builtin_reboot = {
1242        "reboot",
1243        reboot_func,
1244        BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
1245        "reboot",
1246        "Reboot the system."
1247};
1248
1249static int root_func(char *arg, int flags)
1250{
1251        int len;
1252
1253        root_device[0] = 0; /* Clear root device */
1254        copy_path_to_filo_bootline(arg, root_device, 0);
1255
1256        /* The following code handles an extra case
1257         * where the user specifies "root hde1" without
1258         * a trailing colon.
1259         */
1260        len=strlen(root_device);
1261        if(root_device[len - 1] != ':') {
1262                root_device[len] = ':';
1263                root_device[len + 1] = 0;
1264        }
1265
1266        return 0;
1267}
1268
1269static struct builtin builtin_root = {
1270        "root",
1271        root_func,
1272        BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
1273        "root [DEVICE]",
1274        "Set the current \"root device\" to the device DEVICE."
1275};
1276
1277void __attribute__((weak))  serial_hardware_init(int port, int speed, int
1278                word_bits, int parity, int stop_bits);
1279
1280/* serial */
1281static int serial_func(char *arg, int flags)
1282{
1283        unsigned short serial_port[] = {0x3f8, 0x2f8, 0x3e8, 0x2e8 };
1284        unsigned short port = 0x3f8;
1285        unsigned int speed = 9600;
1286        int word_len = 8;
1287        int parity = 0;
1288        int stop_bit_len = 1;
1289
1290        /* Process GNU-style long options.
1291           FIXME: We should implement a getopt-like function, to avoid
1292           duplications.  */
1293        while (1) {
1294                if (memcmp(arg, "--unit=", sizeof("--unit=") - 1) == 0) {
1295                        char *p = arg + sizeof("--unit=") - 1;
1296                        int unit;
1297
1298                        if (!safe_parse_maxint(&p, &unit))
1299                                return 1;
1300
1301                        if (unit < 0 || unit > 3) {
1302                                errnum = ERR_DEV_VALUES;
1303                                return 1;
1304                        }
1305
1306                        port = serial_port[unit];
1307                } else if (memcmp(arg, "--speed=", sizeof("--speed=") - 1) == 0) {
1308                        char *p = arg + sizeof("--speed=") - 1;
1309                        int num;
1310
1311                        if (!safe_parse_maxint(&p, &num))
1312                                return 1;
1313
1314                        speed = (unsigned int) num;
1315                } else if (memcmp(arg, "--port=", sizeof("--port=") - 1)
1316                           == 0) {
1317                        char *p = arg + sizeof("--port=") - 1;
1318                        int num;
1319
1320                        if (!safe_parse_maxint(&p, &num))
1321                                return 1;
1322
1323                        port = (unsigned short) num;
1324                } else if (memcmp(arg, "--word=", sizeof("--word=") - 1)
1325                           == 0) {
1326                        char *p = arg + sizeof("--word=") - 1;
1327                        int len;
1328
1329                        if (!safe_parse_maxint(&p, &len))
1330                                return 1;
1331
1332                        switch (len) {
1333                        case 5 ... 8:
1334                                word_len = len;
1335                                break;
1336                        default:
1337                                errnum = ERR_BAD_ARGUMENT;
1338                                return 1;
1339                        }
1340                } else if (memcmp(arg, "--stop=", sizeof("--stop=") - 1)
1341                           == 0) {
1342                        char *p = arg + sizeof("--stop=") - 1;
1343                        int len;
1344
1345                        if (!safe_parse_maxint(&p, &len))
1346                                return 1;
1347
1348                        switch (len) {
1349                        case 1 ... 2:
1350                                stop_bit_len = len;
1351                                break;
1352                        default:
1353                                errnum = ERR_BAD_ARGUMENT;
1354                                return 1;
1355                        }
1356                } else if (memcmp(arg, "--parity=", sizeof("--parity=") - 1) == 0) {
1357                        char *p = arg + sizeof("--parity=") - 1;
1358
1359                        if (memcmp(p, "no", sizeof("no") - 1) == 0)
1360                                parity = 0;
1361                        else if (memcmp(p, "odd", sizeof("odd") - 1)
1362                                 == 0)
1363                                parity = 1;
1364                        else if (memcmp(p, "even", sizeof("even") - 1)
1365                                 == 0)
1366                                parity = 2;
1367                        else {
1368                                errnum = ERR_BAD_ARGUMENT;
1369                                return 1;
1370                        }
1371                } else
1372                        break;
1373
1374                arg = skip_to(0, arg);
1375        }
1376
1377        /* Initialize the serial unit.  */
1378        if (serial_hardware_init)
1379                serial_hardware_init(port, speed, word_len, parity, stop_bit_len);
1380        else
1381                grub_printf("This version of FILO does not have serial console support.\n");
1382
1383        return 0;
1384}
1385
1386static struct builtin builtin_serial = {
1387        "serial",
1388        serial_func,
1389        BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST | BUILTIN_NO_ECHO,
1390        "serial [--unit=UNIT] [--port=PORT] [--speed=SPEED] [--word=WORD] [--parity=PARITY] [--stop=STOP] [--device=DEV]",
1391        "Initialize a serial device. UNIT is a digit that specifies which serial"
1392            " device is used (e.g. 0 == COM1). If you need to specify the port number,"
1393            " set it by --port. SPEED is the DTE-DTE speed. WORD is the word length,"
1394            " PARITY is the type of parity, which is one of `no', `odd' and `even'."
1395            " STOP is the length of stop bit(s). The option --device can be used only"
1396            " in the grub shell, which specifies the file name of a tty device. The"
1397            " default values are COM1, 9600, 8N1."
1398};
1399
1400#ifdef CONFIG_DEVELOPER_TOOLS
1401static int setpci_func(char *arg, int flags)
1402{
1403        char *walk = arg;
1404        int bus, slot, fn;
1405        pcidev_t dev;
1406        unsigned int reg=0;
1407        unsigned int len=1, maxval=0xff, value=0;
1408        int write_mode = 0;
1409
1410        // setpci bus:dev.fn reg.[bwl][=val]
1411
1412        if(!strlen(arg)) {
1413                errnum = ERR_BAD_ARGUMENT;
1414                return 1;
1415        }
1416
1417        if((walk[1] != ':') && (walk[2] =! ':')) {
1418                errnum = ERR_BAD_ARGUMENT;
1419                return 1;
1420        }
1421
1422        if(walk[1] == ':') {
1423                bus = hex2bin(walk[0]);
1424                walk+=2;
1425        } else {
1426                bus = (hex2bin(walk[0]) * 16) + hex2bin(walk[1]);
1427                walk+=3;
1428        }
1429        if((walk[1] != '.') && (walk[2] =! '.')) {
1430                errnum = ERR_BAD_ARGUMENT;
1431                return 1;
1432        }
1433
1434        if(walk[1] == '.') {
1435                slot = hex2bin(walk[0]);
1436                walk+=2;
1437        } else {
1438                slot = (hex2bin(walk[0]) * 16) + hex2bin(walk[1]);
1439                walk+=3;
1440        }
1441        if (!walk[0]) {
1442                errnum = ERR_BAD_ARGUMENT;
1443                return 1;
1444        }
1445
1446        fn=hex2bin(walk[0]);
1447
1448        dev = PCI_DEV(bus, slot, fn);
1449
1450        walk++;
1451        if (walk[0] != ' ') {
1452                grub_printf("No register specified\n");
1453                errnum = ERR_BAD_ARGUMENT;
1454                return 1;
1455        }
1456
1457        while (*walk!=0 && *walk != '.' && *walk != ':' ) {
1458                reg *= 16;
1459                reg += hex2bin(*walk);
1460                walk++;
1461        }
1462
1463        if (reg > 0xff) {
1464                grub_printf("Only 256 byte config space supported.\n");
1465                errnum = ERR_BAD_ARGUMENT;
1466                return 1;
1467        }
1468
1469        if (*walk == '.') {
1470                walk++;
1471                switch (*walk) {
1472                case 'l':
1473                case 'L':
1474                        len = 4;
1475                        maxval = 0xffffffff;
1476                        break;
1477                case 'w':
1478                case 'W':
1479                        len=2;
1480                        maxval = 0xffff;
1481                        break;
1482                case 'b':
1483                case 'B':
1484                        len=1;
1485                        maxval = 0xff;
1486                        break;
1487                default:
1488                        grub_printf("width must be b, w, or l\n");
1489                        errnum = ERR_BAD_ARGUMENT;
1490                        return 1;
1491                }
1492                walk++;
1493        }
1494
1495        if (*walk == '=') {
1496                while (*walk!=0 && *walk != '.') {
1497                        value *= 16;
1498                        value += hex2bin(*walk);
1499                        walk++;
1500                }
1501
1502                if (value > maxval) {
1503                        grub_printf("value too big.\n");
1504                        errnum = ERR_BAD_ARGUMENT;
1505                        return 1;
1506                }
1507
1508                write_mode = 1;
1509        }
1510
1511        if (write_mode) {
1512                grub_printf ("pci_write_config");
1513                switch (len) {
1514                case 1:
1515                        grub_printf("8 0x%02x -> %x:%x.%x [%02x]\n", value, bus, slot, fn, reg);
1516                        pci_write_config8(dev, reg, value);
1517                        break;
1518                case 2:
1519                        grub_printf("16 0x%04x -> %x:%x.%x [%02x]\n", value, bus, slot, fn, reg);
1520                        pci_write_config16(dev, reg, value);
1521                        break;
1522                case 4:
1523                        grub_printf("32 0x%08x -> %x:%x.%x [%02x]\n", value, bus, slot, fn, reg);
1524                        pci_write_config32(dev, reg, value);
1525                        break;
1526                }
1527        } else {
1528                grub_printf ("pci_read_config");
1529                switch (len) {
1530                case 1:
1531                        value = pci_read_config8(dev, reg);
1532                        grub_printf("8 %x:%x.%x [%02x] -> %02x\n", bus, slot, fn, reg, value);
1533                        break;
1534                case 2:
1535                        value = pci_read_config16(dev, reg);
1536                        grub_printf("16 %x:%x.%x [%02x] -> %04x\n", bus, slot, fn, reg, value);
1537                        break;
1538                case 4:
1539                        value = pci_read_config32(dev, reg);
1540                        grub_printf("32 %x:%x.%x [%02x] -> %08x\n", bus, slot, fn, reg, value);
1541                        break;
1542                }
1543        }
1544
1545        return 0;
1546}
1547
1548static struct builtin builtin_setpci = {
1549        "setpci",
1550        setpci_func,
1551        BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST | BUILTIN_NO_ECHO,
1552        "setpci <device>[.bwl][=value]",
1553        "Show/change PCI config space values"
1554};
1555#endif
1556
1557/* terminal */
1558static int terminal_func(char *arg, int flags)
1559{
1560        int use_serial = 0, use_vga = 0;
1561        int terminal_changed = 0;
1562        /* The index of the default terminal in TERM_TABLE.  */
1563        int lines = 0;
1564        unsigned long term_flags = 0;
1565
1566        /* Get GNU-style long options.  */
1567        while (1) {
1568                if (memcmp(arg, "--no-echo", sizeof("--no-echo") - 1) == 0) {
1569                        /* ``--no-echo'' implies ``--no-edit''.  */
1570                        term_flags |= (TERM_NO_ECHO | TERM_NO_EDIT);
1571                } else if (memcmp(arg, "--no-edit", sizeof("--no-edit") - 1) == 0) {
1572                        term_flags |= TERM_NO_EDIT;
1573                } else if (memcmp(arg, "--lines=", sizeof("--lines=") - 1) == 0) {
1574                        char *val = arg + sizeof("--lines=") - 1;
1575
1576                        if (!safe_parse_maxint(&val, &lines))
1577                                return 1;
1578
1579                        /* Probably less than four is meaningless....  */
1580                        if (lines < 4) {
1581                                errnum = ERR_BAD_ARGUMENT;
1582                                return 1;
1583                        }
1584                } else {
1585                        while (*arg) {
1586                                char *next = skip_to(0, arg);
1587
1588                                nul_terminate(arg);
1589
1590                                /* We also accept "terminal console" as GRUB
1591                                 * heritage.
1592                                 */
1593                                if (strcmp(arg, "serial") == 0) {
1594                                        use_serial = 1;
1595                                        terminal_changed = 1;
1596                                } else if (strcmp(arg, "console") == 0) {
1597                                        use_vga = 1;
1598                                        terminal_changed = 1;
1599                                } else if (strcmp(arg, "vga") == 0) {
1600                                        use_vga = 1;
1601                                        terminal_changed = 1;
1602                                } else {
1603                                        errnum = ERR_BAD_ARGUMENT;
1604                                        return 1;
1605                                }
1606
1607                                arg = next;
1608                                break;
1609                        }
1610                        if (!*arg)
1611                                break;
1612                        continue;
1613                }
1614
1615                arg = skip_to(0, arg);
1616        }
1617
1618        if (terminal_changed) {
1619                curses_enable_serial(use_serial);
1620                curses_enable_vga(use_vga);
1621                terminal_flags = term_flags;
1622        }
1623
1624        if (lines)
1625                max_lines = lines;
1626        else
1627                /* 25 would be a good default value.  */
1628                max_lines = 25;
1629
1630        /* If no argument is specified, show current setting.  */
1631        if (! *arg) {
1632                grub_printf("Serial console terminal %s.\n",
1633                                curses_serial_enabled()?"enabled":"disabled");
1634                grub_printf("VGA console terminal %s.\n",
1635                                curses_vga_enabled()?"enabled":"disabled");
1636                grub_printf("Flags:%s%s\n",
1637                            terminal_flags & TERM_NO_EDIT ? " (no edit)" : "",
1638                            terminal_flags & TERM_NO_ECHO ? " (no echo)" : "");
1639        }
1640
1641        return 0;
1642}
1643
1644static struct builtin builtin_terminal = {
1645        "terminal",
1646        terminal_func,
1647        BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST | BUILTIN_NO_ECHO,
1648        "terminal [--no-echo] [--no-edit] [--timeout=SECS] [--lines=LINES] [--silent] [console] [serial]",
1649        "Select a terminal. When multiple terminals are specified, wait until"
1650            " you push any key to continue. If both console and serial are specified,"
1651            " the terminal to which you input a key first will be selected. If no"
1652            " argument is specified, print current setting. If you specify --no-echo,"
1653            " input characters won't be echoed."
1654            " If you specify --no-edit, the BASH-like editing feature will be disabled."
1655            " If --timeout is present, this command will wait at most for SECS"
1656            " seconds. The option --lines specifies the maximum number of lines."
1657};
1658
1659/* timeout */
1660static int timeout_func(char *arg, int flags)
1661{
1662        if (!safe_parse_maxint(&arg, &grub_timeout))
1663                return 1;
1664
1665        return 0;
1666}
1667
1668static struct builtin builtin_timeout = {
1669        "timeout",
1670        timeout_func,
1671        BUILTIN_MENU,
1672#if 0
1673        "timeout SEC",
1674        "Set a timeout, in SEC seconds, before automatically booting the"
1675            " default entry (normally the first entry defined)."
1676#endif
1677};
1678
1679
1680static int keymap_func(char *arg, int flags)
1681{
1682#ifdef CONFIG_PC_KEYBOARD
1683        if (keyboard_set_layout(arg)) {
1684                errnum = ERR_BAD_ARGUMENT;
1685                return 1;
1686        }
1687        return 0;
1688#else
1689        errnum = ERR_BAD_ARGUMENT;
1690        return 1;
1691#endif
1692}
1693
1694static struct builtin builtin_keymap = {
1695        "keymap",
1696        keymap_func,
1697        BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST | BUILTIN_NO_ECHO,
1698        "keymap LANGCODE",
1699        "Select a keymap to use. Currently only 'us' and 'de' are supported."
1700};
1701
1702static int title_func(char *arg, int flags)
1703{
1704        /* This function is not actually used at least currently.  */
1705        return 0;
1706}
1707
1708static struct builtin builtin_title = {
1709        "title",
1710        title_func,
1711        BUILTIN_TITLE,
1712#if 0
1713        "title [NAME ...]",
1714        "Start a new boot entry, and set its name to the contents of the"
1715            " rest of the line, starting with the first non-space character."
1716#endif
1717};
1718
1719static int cat_func(char *arg, int flags)
1720{
1721        char buf[4096];
1722        int len;
1723
1724        temp_space[0]=0;
1725        copy_path_to_filo_bootline(arg, temp_space, 1);
1726        if (temp_space[0]==0) {
1727                return help_func("cat",0);
1728        }
1729        if (!file_open(temp_space)) {
1730                errnum = ERR_FILE_NOT_FOUND;
1731                return 1;
1732        }
1733
1734        while ((len = file_read(buf, sizeof(buf))) != 0) {
1735                int cnt;
1736                for (cnt = 0; cnt < len; cnt++) {
1737                        grub_putchar(buf[cnt]);
1738                }
1739        }
1740
1741        file_close();
1742
1743        return 0;
1744}
1745
1746static struct builtin builtin_cat = {
1747        "cat",
1748        cat_func,
1749        BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
1750        "cat FILENAME",
1751        "Print the content of FILENAME to the terminal."
1752};
1753
1754/* README !!! XXX !!! This list has to be alphabetically ordered !!! */
1755
1756struct builtin *builtin_table[] = {
1757        &builtin_boot,
1758        &builtin_cat,
1759        &builtin_color,
1760        &builtin_configfile,
1761        &builtin_default,
1762#ifdef CONFIG_DEVELOPER_TOOLS
1763        &builtin_dumpmem,
1764        &builtin_dumppm,
1765#endif
1766#ifdef CONFIG_EXPERIMENTAL
1767        &builtin_find,
1768#endif
1769        &builtin_help,
1770        &builtin_hiddenmenu,
1771        &builtin_initrd,
1772#ifdef CONFIG_DEVELOPER_TOOLS
1773        &builtin_io,
1774#endif
1775        &builtin_kernel,
1776        &builtin_keymap,
1777        &builtin_lock,
1778#ifdef CONFIG_DEVELOPER_TOOLS
1779        &builtin_lspci,
1780#endif
1781#ifdef CONFIG_USE_MD5_PASSWORDS
1782        &builtin_md5crypt,
1783#endif
1784        &builtin_password,
1785        &builtin_pause,
1786        &builtin_poweroff,
1787#ifdef CONFIG_DEVELOPER_TOOLS
1788        &builtin_probe,
1789#endif
1790        &builtin_reboot,
1791        &builtin_root,
1792        &builtin_serial,
1793#ifdef CONFIG_DEVELOPER_TOOLS
1794        &builtin_setpci,
1795#endif
1796        &builtin_terminal,
1797        &builtin_timeout,
1798        &builtin_title,
1799        0
1800};
Note: See TracBrowser for help on using the repository browser.