diff --git a/common/cmdline.c b/common/cmdline.c new file mode 100644 index 00000000..0f64de19 --- /dev/null +++ b/common/cmdline.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2021 Amazon.com, Inc. or its affiliates. + * All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +bool opt_debug = false; +bool_cmd("debug", opt_debug); + +bool opt_keyboard = true; +bool_cmd("keyboard", opt_keyboard); + +bool opt_pit = false; +bool_cmd("pit", opt_pit); + +bool opt_apic_timer = false; +bool_cmd("apic_timer", opt_apic_timer); + +bool opt_hpet = false; +bool_cmd("hpet", opt_hpet); + +bool opt_fpu = false; +bool_cmd("fpu", opt_fpu); + +const char *kernel_cmdline; + +void __text_init cmdline_parse(const char *cmdline) { + static __bss_init char opt[PAGE_SIZE]; + char *optval, *optkey, *q; + const char *p = cmdline; + struct ktf_param *param; + + if (cmdline == NULL) + return; + + for (;;) { + p = string_trim_whitspace(p); + + if (iseostr(*p)) + break; + + q = optkey = opt; + while ((!isspace(*p)) && (!iseostr(*p))) { + ASSERT(_ul(q - opt) < sizeof(opt) - 1); + *q++ = *p++; + } + *q = '\0'; + + /* split on '=' */ + optval = strchr(opt, '='); + if (optval != NULL) + *optval++ = '\0'; + else + /* assume a bool later */ + optval = opt; + + for (param = __start_cmdline; param < __end_cmdline; param++) { + if (strcmp(param->name, optkey)) + continue; + + switch (param->type) { + case STRING: + strncpy(param->var, optval, param->varlen); + if (strlen(optval) >= param->varlen) { + ((char *) param->var)[param->varlen - 1] = '\0'; + printk("WARNING: The commandline parameter value for %s does not fit " + "into the preallocated buffer (size %lu >= %u)\n", + param->name, strlen(optval), param->varlen); + } + break; + case ULONG: + *(unsigned long *) param->var = strtoul(optval, NULL, 0); + break; + case BOOL: + *(bool *) param->var = + !!parse_bool(!strcmp(optval, optkey) ? "1" : optval); + break; + default: + panic("Unkown cmdline type detected..."); + break; + } + } + } +} diff --git a/common/setup.c b/common/setup.c index e9daef18..fd615200 100644 --- a/common/setup.c +++ b/common/setup.c @@ -60,107 +60,17 @@ #include #endif -bool opt_debug = false; -bool_cmd("debug", opt_debug); - -bool opt_keyboard = true; -bool_cmd("keyboard", opt_keyboard); - -bool opt_pit = false; -bool_cmd("pit", opt_pit); - -bool opt_apic_timer = false; -bool_cmd("apic_timer", opt_apic_timer); - -bool opt_hpet = false; -bool_cmd("hpet", opt_hpet); - -bool opt_fpu = false; -bool_cmd("fpu", opt_fpu); - io_port_t __data_rmode com_ports[2] = {COM1_PORT, COM2_PORT}; boot_flags_t boot_flags; static unsigned bsp_cpu_id = 0; -const char *kernel_cmdline; char cpu_identifier[49]; unsigned get_bsp_cpu_id(void) { return bsp_cpu_id; } void set_bsp_cpu_id(unsigned cpu_id) { bsp_cpu_id = cpu_id; } -static __text_init int parse_bool(const char *s) { - if (!strcmp("no", s) || !strcmp("off", s) || !strcmp("false", s) || - !strcmp("disable", s) || !strcmp("0", s)) - return 0; - - if (!strcmp("yes", s) || !strcmp("on", s) || !strcmp("true", s) || - !strcmp("enable", s) || !strcmp("1", s)) - return 1; - - return -1; -} - -void __text_init cmdline_parse(const char *cmdline) { - static __bss_init char opt[PAGE_SIZE]; - char *optval, *optkey, *q; - const char *p = cmdline; - struct ktf_param *param; - - if (cmdline == NULL) - return; - - for (;;) { - p = string_trim_whitspace(p); - - if (iseostr(*p)) - break; - - q = optkey = opt; - while ((!isspace(*p)) && (!iseostr(*p))) { - ASSERT(_ul(q - opt) < sizeof(opt) - 1); - *q++ = *p++; - } - *q = '\0'; - - /* split on '=' */ - optval = strchr(opt, '='); - if (optval != NULL) - *optval++ = '\0'; - else - /* assume a bool later */ - optval = opt; - - for (param = __start_cmdline; param < __end_cmdline; param++) { - if (strcmp(param->name, optkey)) - continue; - - switch (param->type) { - case STRING: - strncpy(param->var, optval, param->varlen); - if (strlen(optval) >= param->varlen) { - ((char *) param->var)[param->varlen - 1] = '\0'; - printk("WARNING: The commandline parameter value for %s does not fit " - "into the preallocated buffer (size %lu >= %u)\n", - param->name, strlen(optval), param->varlen); - } - break; - case ULONG: - *(unsigned long *) param->var = strtoul(optval, NULL, 0); - break; - case BOOL: - *(bool *) param->var = - !!parse_bool(!strcmp(optval, optkey) ? "1" : optval); - break; - default: - panic("Unkown cmdline type detected..."); - break; - } - } - } -} - static void __text_init init_console(void) { get_com_ports(); @@ -216,6 +126,14 @@ void __noreturn __text_init kernel_start(uint32_t multiboot_magic, /* Zero-out BSS sections */ zero_bss(); + if (multiboot_magic == MULTIBOOT_BOOTLOADER_MAGIC) { + /* Indentity mapping is still on, so fill in multiboot structures */ + init_multiboot(mbi, &kernel_cmdline); + } + + /* Parse commandline parameters */ + cmdline_parse(kernel_cmdline); + /* Initialize console early */ init_console(); @@ -237,14 +155,6 @@ void __noreturn __text_init kernel_start(uint32_t multiboot_magic, /* PIC is initialized - enable local interrupts */ sti(); - if (multiboot_magic == MULTIBOOT_BOOTLOADER_MAGIC) { - /* Indentity mapping is still on, so fill in multiboot structures */ - init_multiboot(mbi, &kernel_cmdline); - } - - /* Parse commandline parameters */ - cmdline_parse(kernel_cmdline); - /* Initialize Physical Memory Manager */ init_regions(); init_pmm(); diff --git a/include/cmdline.h b/include/cmdline.h index f7473807..5b18b632 100644 --- a/include/cmdline.h +++ b/include/cmdline.h @@ -27,6 +27,8 @@ #ifndef __ASSEMBLY__ #include +#include +#include #define PARAM_MAX_LENGTH 32 @@ -53,4 +55,30 @@ struct __packed ktf_param { #endif /* __ASSEMBLY__ */ +/* External declarations */ + +extern bool opt_debug; +extern bool opt_keyboard; +extern bool opt_pit; +extern bool opt_apic_timer; +extern bool opt_hpet; +extern bool opt_fpu; +extern const char *kernel_cmdline; + +extern void cmdline_parse(const char *cmdline); + +/* Static declarations */ + +static inline int parse_bool(const char *s) { + if (!strcmp("no", s) || !strcmp("off", s) || !strcmp("false", s) || + !strcmp("disable", s) || !strcmp("0", s)) + return 0; + + if (!strcmp("yes", s) || !strcmp("on", s) || !strcmp("true", s) || + !strcmp("enable", s) || !strcmp("1", s)) + return 1; + + return -1; +} + #endif /* KTF_CMDLINE_H */ diff --git a/include/setup.h b/include/setup.h index 721931e3..23b480cf 100644 --- a/include/setup.h +++ b/include/setup.h @@ -43,7 +43,6 @@ typedef struct boot_flags boot_flags_t; extern io_port_t com_ports[2]; -extern const char *kernel_cmdline; extern char cpu_identifier[49]; extern boot_flags_t boot_flags; diff --git a/tests/unittests.c b/tests/unittests.c index d804e550..04bc2afa 100644 --- a/tests/unittests.c +++ b/tests/unittests.c @@ -31,7 +31,6 @@ #include #include -extern char *kernel_cmdline; #include static char opt_string[4];