orphan
[debian/elilo] / config.c
index e24c0c0198613c2338215e4302ed12428e7c4295..d144c9f0a9b1620a0f10b2ac98edce55f790ceb7 100644 (file)
--- a/config.c
+++ b/config.c
@@ -1,6 +1,9 @@
 /*
  *  Copyright (C) 2001-2003 Hewlett-Packard Co.
  *     Contributed by Stephane Eranian <eranian@hpl.hp.com>
+ *     Contributed by Fenghua Yu <fenghua.yu@intel.com>
+ *     Contributed by Bibo Mao <bibo.mao@intel.com>
+ *     Contributed by Chandramouli Narayanan <mouli@linux.intel.com>
  *
  * This file is part of the ELILO, the EFI Linux boot loader.
  *
@@ -42,6 +45,8 @@
 #define ELILO_ARCH_DEFAULT_CONFIG      L"elilo-ia64.conf"
 #elif defined (CONFIG_ia32)
 #define ELILO_ARCH_DEFAULT_CONFIG      L"elilo-ia32.conf"
+#elif defined (CONFIG_x86_64)
+#define ELILO_ARCH_DEFAULT_CONFIG       L"elilo-x86_64.conf"
 #else
 #error "You need to specfy your default arch config file"
 #endif
@@ -51,7 +56,7 @@
  */
 #define ELILO_DEFAULT_CONFIG   L"elilo.conf"
 
-#define MAX_STRING     CMDLINE_MAXLEN
+#define MAX_STRING     512
 #define CONFIG_BUFSIZE 512     /* input buffer size */
 
 /*
@@ -66,7 +71,7 @@ typedef struct boot_image {
        struct boot_image *next;
        CHAR16  label[MAX_STRING];
        CHAR16  kname[FILENAME_MAXLEN];
-       CHAR16  options[MAX_STRING];
+       CHAR16  options[CMDLINE_MAXLEN];
        CHAR16  initrd[FILENAME_MAXLEN];
        CHAR16  vmcode[FILENAME_MAXLEN];
        CHAR16  root[FILENAME_MAXLEN];
@@ -95,7 +100,7 @@ typedef struct {
        CHAR16          root[FILENAME_MAXLEN];  /* globally defined root fs */
        CHAR16          initrd[FILENAME_MAXLEN];/* globally defined initrd  */
        CHAR16          vmcode[FILENAME_MAXLEN];/* globally defined boot-time module  */
-       CHAR16          options[MAX_STRING];
+       CHAR16          options[CMDLINE_MAXLEN];
        CHAR16          default_image_name[MAX_STRING];
        CHAR16          message_file[MAX_MESSAGES][FILENAME_MAXLEN]; 
        CHAR16          chooser[FILENAME_MAXLEN];/* which image chooser to use */
@@ -204,14 +209,8 @@ static fops_fd_t config_fd;
 static VOID 
 config_error(CHAR16 *msg,...)
 {
-    va_list ap;
-    extern UINTN _IPrint (UINTN, UINTN, SIMPLE_TEXT_OUTPUT_INTERFACE *, CHAR16 *, CHAR8 *, va_list);
-
     Print(L"near line %d: ",line_num);
-
-    va_start(ap,msg);
-    _IPrint((UINTN)-1, (UINTN)-1, systab->ConOut, msg, NULL, ap);
-    va_end(ap);
+    IPrint(systab->ConOut, msg);
     Print(L"\n");
 }
 
@@ -256,7 +255,16 @@ next(VOID)
        back = 0;
        return ch;
     }
-    return getc();
+/*
+ * config files served from pxe/tftpboot windows servers can contain
+ * extraneous '\r' characters, often the first char in the file, and
+ * we need to simply skip over those and continue on
+ */
+   ch = getc();
+   if(ch == '\r')
+       ch = getc();
+
+   return ch;
 }
 
 /*
@@ -305,23 +313,23 @@ find_option(config_option_group_t *grp, CHAR16 *str)
  *     - TOK_ERR: in case of (parsing) error
  */
 static token_t
-get_token(CHAR16 *str, UINTN maxlen)
+get_token_core(CHAR16 *str, UINTN maxlen, BOOLEAN rhs)
 {
     INTN ch, escaped;
     CHAR16 *here;
 
     for (;;) {
-       while ((ch = next()), ch == ' ' || ch == '\t' || ch == '\n') if (ch == '\n') line_num++;
+       while ((ch = next()), ch == ' ' || ch == '\t' || ch == '\n') if (ch == '\n' ) line_num++;
 
        if (ch == CHAR_EOF) return TOK_EOF;
 
+       /* skip comment line */
        if (ch != '#') break;
 
-       /* skip comment line */
        while ((ch = next()), ch != '\n') if (ch == CHAR_EOF) return TOK_EOF;
        line_num++;
     }
-    if (ch == '=') return TOK_EQUAL;
+    if (ch == '=' && !rhs) return TOK_EQUAL;
 
     if (ch == '"') {
        here = str;
@@ -374,7 +382,7 @@ get_token(CHAR16 *str, UINTN maxlen)
        }
        else {
            if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '#' ||
-             ch == '=' || ch == CHAR_EOF) {
+             ch == CHAR_EOF || (ch == '=' && !rhs)) {
                again(ch);
                *here = 0;
                return TOK_STR;
@@ -387,6 +395,18 @@ get_token(CHAR16 *str, UINTN maxlen)
     return TOK_ERR;
 }
 
+static token_t
+get_token(CHAR16 *str, UINTN maxlen)
+{
+    return get_token_core(str, maxlen, FALSE);
+}
+
+static token_t
+get_token_rhs(CHAR16 *str, UINTN maxlen)
+{
+    return get_token_core(str, maxlen, TRUE);
+}
+
 static INTN
 image_check(boot_image_t *img)
 {
@@ -680,7 +700,7 @@ do_string_core(config_option_t *p, CHAR16 *str, UINTN maxlen, CHAR16 *msg)
        /*
         * now get the value
         */
-       tok = get_token(str, maxlen);
+       tok = get_token_rhs(str, maxlen);
        if (tok != TOK_STR) {
                config_error(L"Option %s expects %s", p->name, msg);
                return -1;
@@ -751,7 +771,10 @@ config_parse(VOID)
 
                if (tok == TOK_EOF) break;
 
-               if (tok == TOK_ERR) return -1;
+               if (tok == TOK_ERR) {
+                       Print(L"Bad Token from elilo config file, parser read: %s\n elilo exiting\n", str);
+                       return -1;
+               }
 
                if ( (p = find_option(current_options, str)) == NULL) {
                        config_error(L"Unkown option %s", str);
@@ -886,10 +909,10 @@ print_label_list(VOID)
 {
        boot_image_t *img, *dfl = global_config.default_image;
 
-       if (dfl) Print(L"\t%s\n", dfl->label);
+       if (dfl) Print(L"    %s\n", dfl->label);
 
        for (img = image_list; img; img = img->next) {
-               if (img != dfl) Print(L"\t%s\n", img->label);
+               if (img != dfl) Print(L"    %s\n", img->label);
        }
 }
 
@@ -936,6 +959,37 @@ find_description(CHAR16 *label)
        return NULL;
 }
 
+static void
+add_root_to_options(CHAR16 *options, CHAR16 *root, CHAR16 *vmcode)
+{
+       CHAR16 *o, ko[CMDLINE_MAXLEN];
+
+       if (vmcode[0]) {
+               for (o = options; *o; o++) {
+                       if (*o == '-' && *(o+1) == '-')
+                               break;
+               }
+               if (! *o) {
+                       /* no separator found, add one */
+                       StrCpy(o, L" -- ");
+                       o++;
+               }
+
+               /* advance past separator and whitespace */
+               o += 2;
+               while (*o == ' ') o++;
+       } else {
+               o = options;
+       }
+
+       /* insert root param at this point */
+       StrCpy(ko, o);
+       StrCpy(o, L"root=");
+       StrCat(o, root);
+       StrCat(o, L" ");
+       StrCat(o, ko);
+}
+
 INTN
 find_label(CHAR16 *label, CHAR16 *kname, CHAR16 *options, CHAR16 *initrd, CHAR16 *vmcode)
 {
@@ -958,15 +1012,12 @@ find_label(CHAR16 *label, CHAR16 *kname, CHAR16 *options, CHAR16 *initrd, CHAR16
        /*
         * when the label does not exist, we still propagate the global options
         */
-       if (global_config.root[0]) {
-               StrCpy(options, L" root=");
-               StrCat(options, global_config.root);
-       }
-
        if (global_config.options[0]) {
                StrCat(options, L" ");
                StrCat(options, global_config.options);
        }
+       if (global_config.root[0])
+               add_root_to_options(options, global_config.root, global_config.vmcode);
        if (global_config.readonly) StrCat(options, L" ro");
 
        if (global_config.initrd[0]) StrCpy(initrd, global_config.initrd);
@@ -979,21 +1030,33 @@ find_label(CHAR16 *label, CHAR16 *kname, CHAR16 *options, CHAR16 *initrd, CHAR16
 found:
        StrCpy(kname, img->kname);
 
+       /* per image initrd has precedence over global initrd */
+       if (img->initrd[0]) 
+               StrCpy(initrd, img->initrd);
+       else
+               StrCpy(initrd, global_config.initrd);
+
+       /* per image vmcode has precedence over global vmcode */
+       if (img->vmcode[0]) 
+               StrCpy(vmcode, img->vmcode);
+       else
+               StrCpy(vmcode, global_config.vmcode);
+
        /*
         * literal option overrides any other image-based or global option
         *
         * In any case, the image option has priority over the global option
         */
        if (img->literal == 0) {
-               if (img->root[0] || global_config.root[0]) {
-                       StrCat(options, L"root=");
-                       StrCat(options, img->root[0] ? img->root : global_config.root);
-               }
                /* XXX: check max length */
                if (img->options[0] || global_config.options[0]) {
                        StrCat(options, L" ");
                        StrCat(options, img->options[0] ? img->options: global_config.options);
                }
+               if (img->root[0] || global_config.root[0]) {
+                       add_root_to_options(options, img->root[0] 
+                                           ? img->root : global_config.root, vmcode);
+               }
                if (img->readonly || global_config.readonly) {
                        StrCat(options, L" ro");
                }
@@ -1002,17 +1065,6 @@ found:
                StrCpy(options, img->options);
        }
 
-       /* per image initrd has precedence over global initrd */
-       if (img->initrd[0]) 
-               StrCpy(initrd, img->initrd);
-       else if (global_config.initrd[0])
-               StrCpy(initrd, global_config.initrd);
-
-       if (img->vmcode[0]) 
-               StrCpy(vmcode, img->vmcode);
-       else if (global_config.vmcode[0])
-               StrCpy(vmcode, global_config.vmcode);
-
        /*
         * point to architecture dependent options for this image
         */