diff --git a/CODEOWNERS b/CODEOWNERS index 54912360c89..d51782315f3 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -38,6 +38,7 @@ /arch/x86/core/ @andrewboie /arch/x86/core/crt0.S @wentongwu @nashif /arch/x86/core/pcie.c @gnuless +/arch/x86/core/multiboot.c @gnuless /soc/x86/ @andrewboie @wentongwu /soc/x86/intel_quark/quark_d2000/ @nashif /soc/x86/intel_quark/quark_se/ @nashif @@ -206,6 +207,7 @@ /include/arch/x86/ @andrewboie @wentongwu /include/arch/common/ @andrewboie @andyross @nashif /include/arch/x86/arch.h @andrewboie +/include/arch/x86/multiboot.h @gnuless /include/arch/xtensa/ @andrewboie /include/atomic.h @andrewboie @andyross /include/bluetooth/ @joerchan @jhedberg @Vudentz diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 33e7658e525..6f417b2a56e 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -20,6 +20,15 @@ config X86_MULTIBOOT to leave this option on if you're not sure. It only expands the text segment by 12-16 bytes and is typically ignored if not needed. +config X86_MULTIBOOT_INFO + bool "Preserve multiboot information structure" + depends on X86_MULTIBOOT + default n + help + Multiboot passes a pointer to an information structure to the + kernel entry point. Some drivers (e.g., the multiboot framebuffer + display driver) need to refer to information in this structure, + and so set this option to preserve the data in a permanent location. source "arch/x86/core/Kconfig" diff --git a/arch/x86/core/CMakeLists.txt b/arch/x86/core/CMakeLists.txt index 3c4a9f15638..55473dc70ab 100644 --- a/arch/x86/core/CMakeLists.txt +++ b/arch/x86/core/CMakeLists.txt @@ -35,6 +35,7 @@ zephyr_library_sources_if_kconfig( reboot_rst_cnt.c) zephyr_library_sources_if_kconfig( pcie.c) zephyr_library_sources_ifdef(CONFIG_LAZY_FP_SHARING float.c) zephyr_library_sources_ifdef(CONFIG_X86_USERSPACE userspace.S) +zephyr_library_sources_ifdef(CONFIG_X86_MULTIBOOT multiboot.c) # Last since we declare default exception handlers here zephyr_library_sources(fatal.c) diff --git a/arch/x86/core/crt0.S b/arch/x86/core/crt0.S index 71f87c2b636..43964492bd0 100644 --- a/arch/x86/core/crt0.S +++ b/arch/x86/core/crt0.S @@ -14,6 +14,7 @@ #include #include #include +#include /* exports (private APIs) */ @@ -140,6 +141,28 @@ gdt_ptr: SECTION_FUNC(TEXT_START, __start) +#ifdef CONFIG_X86_MULTIBOOT_INFO + /* + * If we were loaded by a multiboot-compliant loader, then EAX + * contains X86_MULTIBOOT_EAX_MAGIC and EBX points to a 'struct + * x86_multiboot_info' somewhere in memory that the kernel load + * image doesn't claim. Since the kernel will consider such memory + * "free", we must copy the contents of the struct before the kernel + * decides to use that RAM for something else. However, we can't + * effect the copy until after the BSS is initialized. + * + * EBX isn't touched until the copy is made; even function calls will + * preserve it (it's callee-save in the SysV ABI). But EAX will be + * clobbered, so we check for the magic now and leave a sentinel in + * EBX (0) if the multiboot data isn't valid. + */ + + cmpl $X86_MULTIBOOT_EAX_MAGIC, %eax + je 1f + xorl %ebx, %ebx +1: +#endif + #ifdef CONFIG_BOOT_TIME_MEASUREMENT /* * Record BootTime from start of Kernel. @@ -375,6 +398,23 @@ __csSet: #endif lidt z_x86_idt /* load 32-bit operand size IDT */ +#if defined(CONFIG_X86_MULTIBOOT_INFO) + /* + * If EBX isn't 0, then it points to a valid boot information + * struct. Copy it to x86_multiboot_info before it's overwritten. + */ + + testl %ebx, %ebx + jz 1f + movl $__X86_MULTIBOOT_INFO_SIZEOF, %ecx + movl %ebx, %esi + movl $x86_multiboot_info, %edi + cld /* to be safe. should still be 0 from BSS clear, though */ + rep + movsb +1: +#endif + /* Jump to C portion of kernel initialization and never return */ jmp z_cstart @@ -477,7 +517,7 @@ z_x86_idt: .balign 4,0x90 - .long 0x1BADB002 /* multiboot magic number */ + .long X86_MULTIBOOT_HEADER_MAGIC /* * Flags = no bits are being set, specifically bit 16 is not being @@ -494,7 +534,7 @@ z_x86_idt: * unsigned sum of zero. */ - .long -(0x1BADB002 + 0) + .long -(X86_MULTIBOOT_HEADER_MAGIC + 0) #endif /* CONFIG_X86_MULTIBOOT */ #ifdef CONFIG_SET_GDT diff --git a/arch/x86/core/multiboot.c b/arch/x86/core/multiboot.c new file mode 100644 index 00000000000..1a35e7a60af --- /dev/null +++ b/arch/x86/core/multiboot.c @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2019 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#ifdef CONFIG_X86_MULTIBOOT_INFO + +struct x86_multiboot_info x86_multiboot_info; + +#endif /* CONFIG_X86_MULTIBOOT_INFO */ diff --git a/arch/x86/core/offsets/offsets.c b/arch/x86/core/offsets/offsets.c index f03b5d3711c..3c06b0e202a 100644 --- a/arch/x86/core/offsets/offsets.c +++ b/arch/x86/core/offsets/offsets.c @@ -29,6 +29,7 @@ #include #include #include +#include #include @@ -82,4 +83,9 @@ GEN_OFFSET_SYM(NANO_ESF, eflags); GEN_ABSOLUTE_SYM(__MMU_REGION_SIZEOF, sizeof(struct mmu_region)); +/* size of struct x86_multiboot_info, used by crt0.S */ + +GEN_ABSOLUTE_SYM(__X86_MULTIBOOT_INFO_SIZEOF, + sizeof(struct x86_multiboot_info)); + GEN_ABS_SYM_END diff --git a/include/arch/x86/multiboot.h b/include/arch/x86/multiboot.h new file mode 100644 index 00000000000..0bcb409066f --- /dev/null +++ b/include/arch/x86/multiboot.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2019 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ARCH_X86_MULTIBOOT_H_ +#define ZEPHYR_INCLUDE_ARCH_X86_MULTIBOOT_H_ + +#ifndef _ASMLANGUAGE + +/* + * Multiboot (version 1) boot information structure. + * + * Only fields/values of interest to Zephyr are enumerated: at + * present, that means only those pertaining to the framebuffer. + */ + +struct x86_multiboot_info { + u32_t flags; + u32_t unused0[21]; + u32_t fb_addr_lo; + u32_t fb_addr_hi; + u32_t fb_pitch; + u32_t fb_width; + u32_t fb_height; + u8_t fb_bpp; + u8_t fb_type; +}; + +extern struct x86_multiboot_info x86_multiboot_info; + +#endif /* _ASMLANGUAGE */ + +/* + * Magic numbers: the kernel multiboot header (see crt0.S) begins with + * X86_MULTIBOOT_HEADER_MAGIC to signal to the booter that it supports + * multiboot. On kernel entry, EAX is set to X86_MULTIBOOT_EAX_MAGIC to + * signal that the boot loader is multiboot compliant. + */ + +#define X86_MULTIBOOT_HEADER_MAGIC 0x1BADB002 +#define X86_MULTIBOOT_EAX_MAGIC 0x2BADB002 + +/* The fb_* fields are valid if X86_MULTIBOOT_INFO_FLAGS_FB is set. */ + +#define X86_MULTIBOOT_INFO_FLAGS_FB (1 << 12) + +/* The only fb_type we support is RGB. No text modes and no color palettes. */ + +#define X86_MULTIBOOT_INFO_FB_TYPE_RGB 1 + +#endif /* ZEPHYR_INCLUDE_ARCH_X86_MULTIBOOT_H_ */