Added support for multiboot protocol command line extraction
authorDavide Libenzi <dlibenzi@google.com>
Tue, 3 Nov 2015 03:14:32 +0000 (19:14 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 10 Nov 2015 16:37:23 +0000 (11:37 -0500)
Added support for multiboot protocol command line extraction.
Added API to fetch kernel boot command line parameters.

Signed-off-by: Davide Libenzi <dlibenzi@google.com>
[removed unnecessary null-termiate after strlcpy]
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/include/init.h [new file with mode: 0644]
kern/include/string.h
kern/src/init.c
kern/src/strstr.c

diff --git a/kern/include/init.h b/kern/include/init.h
new file mode 100644 (file)
index 0000000..f2b827c
--- /dev/null
@@ -0,0 +1,34 @@
+/* Copyright (c) 2015 Google Inc
+ * Davide Libenzi <dlibenzi@google.com>
+ * See LICENSE for details.
+ */
+
+#pragma once
+
+/**
+ * @brief Fetches a given boot commond line parameter.
+ *
+ * @param base The base pointer from which to start the search. Should be set
+ *             to NULL the first time is being called, and, for command line
+ *             parameters with multiple instances, should be set to the value
+ *             returned by the previous successful call to this API.
+ * @param option The name of the option to retrieve. By convention, options
+ *               should start with the '-' character.
+ * @param param The pointer to the buffer where to store the eventual value of
+ *              the parameter (in a "-option=value" format). Can be NULL if the
+ *              caller is not interested in the parameter value (because of a
+ *              value-less parameter (example "-enable-acpi").
+ * @param max_param Maximum length of the @a param buffer, or 0 if @a param is
+ *              NULL.
+ *
+ * @return Returns a pointer different from NULL if the given @a option has been
+ *         successfully parsed, or NULL otherwise. The returned pointer should
+ *         be treated as opaque value by the caller, and used only for the
+ *         following calls to this API, in case of multiple instance parameters
+ *         (example "-map=0x12345678,0x1000 -map=0x987654321,0x2000").
+ */
+const char *get_boot_option(const char *base, const char *option, char *param,
+                                                       size_t max_param);
+
+void _panic(const char *file, int line, const char *fmt, ...);
+void _warn(const char *file, int line, const char *fmt, ...);
index efcc890..4005907 100644 (file)
@@ -5,7 +5,7 @@
 
 int    strlen(const char *s);
 int    strnlen(const char *s, size_t size);
-char *strstr(char *s1, char *s2);
+char *strstr(const char *s1, const char *s2);
 
 /* zra : These aren't being used, and they are dangerous, so I'm rm'ing them
 STRING strcpy(STRING dst, const STRING src);
index ba88555..67502c6 100644 (file)
 #include <acpi.h>
 #include <coreboot_tables.h>
 
+#define MAX_BOOT_CMDLINE_SIZE 4096
+
+#define ASSIGN_PTRVAL(prm, top, val)                   \
+       do {                                                                            \
+               if (prm && (prm < top)) {                               \
+                       *prm = val;                                                     \
+                       prm++;                                                          \
+               }                                                                               \
+       } while (0)
+
 int booting = 1;
 struct sysinfo_t sysinfo;
+static char boot_cmdline[MAX_BOOT_CMDLINE_SIZE];
+
 static void run_linker_funcs(void);
 static int run_init_script(void);
 
+const char *get_boot_option(const char *base, const char *option, char *param,
+                                                       size_t max_param)
+{
+       size_t optlen = strlen(option);
+       char *ptop = param + max_param - 1;
+       const char *opt, *arg;
+
+       if (!base)
+               base = boot_cmdline;
+       for (;;) {
+               opt = strstr(base, option);
+               if (!opt)
+                       return NULL;
+               if (((opt == base) || (opt[-1] == ' ')) &&
+                       ((opt[optlen] == 0) || (opt[optlen] == '=') ||
+                        (opt[optlen] == ' ')))
+                       break;
+               base = opt + optlen;
+       }
+       arg = opt + optlen;
+       if (*arg == '=') {
+               arg++;
+               if (*arg == '\'') {
+                       arg++;
+                       for (; *arg; arg++) {
+                               if (*arg == '\\')
+                                       arg++;
+                               else if (*arg == '\'')
+                                       break;
+                               ASSIGN_PTRVAL(param, ptop, *arg);
+                       }
+               } else {
+                       for (; *arg && (*arg != ' '); arg++)
+                               ASSIGN_PTRVAL(param, ptop, *arg);
+               }
+       }
+       ASSIGN_PTRVAL(param, ptop, 0);
+
+       return arg;
+}
+
+static void extract_multiboot_cmdline(struct multiboot_info *mbi)
+{
+       if (mbi && (mbi->flags & MULTIBOOT_INFO_CMDLINE) && mbi->cmdline) {
+               const char *cmdln = (const char *) KADDR(mbi->cmdline);
+
+               /* We need to copy the command line in a permanent buffer, since the
+                * multiboot memory where it is currently residing will be part of the
+                * free boot memory later on in the boot process.
+                */
+               strlcpy(boot_cmdline, cmdln, sizeof(boot_cmdline));
+       }
+}
+
 void kernel_init(multiboot_info_t *mboot_info)
 {
        extern char edata[], end[];
@@ -62,9 +128,13 @@ void kernel_init(multiboot_info_t *mboot_info)
         * memory, we may clobber it. */
        multiboot_kaddr = (struct multiboot_info*)((physaddr_t)mboot_info
                                                + KERNBASE);
+       extract_multiboot_cmdline(multiboot_kaddr);
+
        cons_init();
        print_cpuinfo();
 
+       printk("Boot Command Line: '%s'\n", boot_cmdline);
+
        exception_table_init();
        cache_init();                                   // Determine systems's cache properties
        pmem_init(multiboot_kaddr);
index 10fbf3a..0e81568 100644 (file)
  * Return pointer to first occurrence of s2 in s1,
  * 0 if none
  */
-char *strstr(char *s1, char *s2)
+char *strstr(const char *s1, const char *s2)
 {
-       char *p;
+       const char *p;
        int f, n;
 
        f = s2[0];
        if (f == 0)
-               return s1;
+               return (char *) s1;
        n = strlen(s2);
        for (p = strchr(s1, f); p; p = strchr(p + 1, f))
                if (strncmp(p, s2, n) == 0)
-                       return p;
-       return 0;
+                       return (char *) p;
+       return NULL;
 }
 
 /* Case insensitive strcmp */