Re: [RFC PATCH] x86/boot: make ELF kernel multiboot-able

From: hpa
Date: Wed Feb 15 2017 - 13:14:50 EST


On February 15, 2017 6:41:56 AM PST, Chao Peng <chao.p.peng@xxxxxxxxxxxxxxx> wrote:
>Multiboot specification
>(http://git.savannah.gnu.org/cgit/grub.git/tree/doc/multiboot.texi?h=multiboot2)
>is an open standard that provides kernels with a uniform way to be
>booted
>by multiboot-compliant bootloaders (like grub).
>
>This patch is trying to make Linux ELF kernel image to be a
>multiboot-compliant OS so that it can be loaded by a multiboot-comliant
>bootloader. The benefit is eliminating the maintainance for realmode
>and
>decompression code and especially when the kernel is loaded in a
>virtual
>machine, the reducing for these code can greatly cuts down the boot
>time.
>
>However, the current version of multiboot spec doesn't support 64 bit
>well so for 64 bit kernel we need stub code to jump from 32 bit code to
>64 bit code. Besides, there are still some other issues:
> 1). '-z max-page-size=0x1000' is used so the text segment start is in
> multiboot header search scope because GNU LD has default page size of
> 0x00200000 for ELF64, which will fail multiboot test.
>
>2). The bootloader like grub has support for ELF kernel (even for
>ELF64)
> which makes the patch easier. However, the current grub implementaion
>thinks the entry address should be a VA. E.g. for 64 bit kernel, the
>entry
>address (0x1000000) is actually phiscial address, grub refuses to load
>it
> by saying: 'entry point isn't in a segment'.
>
>This patch is sent out as RFC in case you have some ideas.
>
>Signed-off-by: Chao Peng <chao.p.peng@xxxxxxxxxxxxxxx>
>---
> arch/x86/Kconfig | 6 +
> arch/x86/Makefile | 4 +
> arch/x86/kernel/head64.c | 64 ++++++-
> arch/x86/kernel/head_64.S | 175 ++++++++++++++++++
>arch/x86/kernel/multiboot2.h | 417
>+++++++++++++++++++++++++++++++++++++++++++
> 5 files changed, 665 insertions(+), 1 deletion(-)
> create mode 100644 arch/x86/kernel/multiboot2.h
>
>diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
>index bada636..75a9ef2 100644
>--- a/arch/x86/Kconfig
>+++ b/arch/x86/Kconfig
>@@ -585,6 +585,12 @@ config X86_AMD_PLATFORM_DEVICE
> I2C and UART depend on COMMON_CLK to set clock. GPIO driver is
> implemented under PINCTRL subsystem.
>
>+config X86_MULTIBOOT_STUB
>+ bool "Multiboot stub support for ELF kernel image"
>+ default n
>+ ---help---
>+ Set whether multiboot stub is on or off.
>+
> config IOSF_MBI
> tristate "Intel SoC IOSF Sideband support for SoC platforms"
> depends on PCI
>diff --git a/arch/x86/Makefile b/arch/x86/Makefile
>index 2d44933..d945c34 100644
>--- a/arch/x86/Makefile
>+++ b/arch/x86/Makefile
>@@ -39,6 +39,10 @@ ifdef CONFIG_X86_NEED_RELOCS
> LDFLAGS_vmlinux := --emit-relocs
> endif
>
>+ifdef CONFIG_X86_MULTIBOOT_STUB
>+ LDFLAGS_vmlinux += -z max-page-size=0x1000
>+endif
>+
> #
> # Prevent GCC from generating any FP code by mistake.
> #
>diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
>index 54a2372..c0f375a 100644
>--- a/arch/x86/kernel/head64.c
>+++ b/arch/x86/kernel/head64.c
>@@ -29,6 +29,8 @@
> #include <asm/microcode.h>
> #include <asm/kasan.h>
>
>+#include "multiboot2.h"
>+
> /*
> * Manage page tables very early on.
> */
>@@ -36,6 +38,7 @@ extern pgd_t early_level4_pgt[PTRS_PER_PGD];
>extern pmd_t
>early_dynamic_pgts[EARLY_DYNAMIC_PAGE_TABLES][PTRS_PER_PMD];
> static unsigned int __initdata next_early_pgt = 2;
>pmdval_t early_pmd_flags = __PAGE_KERNEL_LARGE & ~(_PAGE_GLOBAL |
>_PAGE_NX);
>+char *multiboot_info = NULL;
>
> /* Wipe all early page tables except for the kernel symbol map */
> static void __init reset_early_page_tables(void)
>@@ -130,6 +133,60 @@ static void __init copy_bootdata(char
>*real_mode_data)
> }
> }
>
>+static void __init copy_multiboot_cmdline(struct multiboot_tag_string
>*tag)
>+{
>+ unsigned int size = tag->size - 8;
>+
>+ if (size > COMMAND_LINE_SIZE)
>+ size = COMMAND_LINE_SIZE;
>+ boot_params.hdr.cmdline_size = size;
>+ memcpy(boot_command_line, tag->string, size);
>+}
>+
>+static void __init copy_multiboot_mmap(struct multiboot_tag_mmap *tag)
>+{
>+ multiboot_memory_map_t *mmap;
>+ int nr = 0;
>+
>+ for (mmap = tag->entries;
>+ (u8 *)mmap < (u8 *)tag + tag->size && nr < E820MAX;
>+ mmap = (multiboot_memory_map_t *)((unsigned long)mmap +
>+ tag->entry_size)) {
>+ boot_params.e820_map[nr].addr = mmap->addr;
>+ boot_params.e820_map[nr].size = mmap->len;
>+ boot_params.e820_map[nr].type = mmap->type;
>+ nr++;
>+ }
>+ boot_params.e820_entries = nr;
>+}
>+
>+static void __init copy_multiboot_info(void)
>+{
>+ struct multiboot_tag *tag;
>+ char *ptr = __va(multiboot_info);
>+
>+ boot_params.hdr.boot_flag = 0xAA55;
>+ boot_params.hdr.header = 0x53726448;
>+ boot_params.hdr.version = 0x202;
>+
>+ for (tag = (struct multiboot_tag *)(ptr + 8);
>+ tag->type != MULTIBOOT_TAG_TYPE_END;
>+ tag = (struct multiboot_tag *)((u8 *) tag +
>+ ((tag->size + 7) & ~7))) {
>+ switch (tag->type) {
>+ case MULTIBOOT_TAG_TYPE_CMDLINE:
>+ copy_multiboot_cmdline(
>+ (struct multiboot_tag_string *)tag);
>+ break;
>+ case MULTIBOOT_TAG_TYPE_MMAP:
>+ copy_multiboot_mmap((struct multiboot_tag_mmap *)tag);
>+ break;
>+ default:
>+ break;
>+ }
>+ }
>+}
>+
>asmlinkage __visible void __init x86_64_start_kernel(char *
>real_mode_data)
> {
> int i;
>@@ -163,7 +220,12 @@ asmlinkage __visible void __init
>x86_64_start_kernel(char * real_mode_data)
> set_intr_gate(i, early_idt_handler_array[i]);
> load_idt((const struct desc_ptr *)&idt_descr);
>
>- copy_bootdata(__va(real_mode_data));
>+ if (multiboot_info) {
>+ copy_multiboot_info();
>+ real_mode_data = (char *) (__pa(&boot_params));
>+ } else {
>+ copy_bootdata(__va(real_mode_data));
>+ }
>
> /*
> * Load microcode early on BSP.
>diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
>index b4421cc..1c944fd 100644
>--- a/arch/x86/kernel/head_64.S
>+++ b/arch/x86/kernel/head_64.S
>@@ -22,6 +22,7 @@
> #include <asm/nops.h>
> #include "../entry/calling.h"
> #include <asm/export.h>
>+#include <asm/boot.h>
>
> #ifdef CONFIG_PARAVIRT
> #include <asm/asm-offsets.h>
>@@ -32,6 +33,8 @@
> #define INTERRUPT_RETURN iretq
> #endif
>
>+#include "multiboot2.h"
>+
>/* we are not able to switch in one step to the final KERNEL ADDRESS
>SPACE
> * because we need identity-mapped pages.
> *
>@@ -66,6 +69,161 @@ startup_64:
> * tables and then reload them.
> */
>
>+#ifdef CONFIG_X86_MULTIBOOT_STUB
>+ jmp multiboot_entry
>+
>+ .align MULTIBOOT_HEADER_ALIGN
>+multiboot_header:
>+ /* magic */
>+ .long MULTIBOOT2_HEADER_MAGIC
>+ /* ISA: i386 */
>+ .long MULTIBOOT_ARCHITECTURE_I386
>+ /* Header length. */
>+ .long multiboot_header_end - multiboot_header
>+ /* checksum */
>+ .long -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE_I386
>+ \
>+ (multiboot_header_end - multiboot_header))
>+
>+ /* information request tag */
>+infomation_request_start:
>+ .short MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST
>+ .short MULTIBOOT_HEADER_TAG_OPTIONAL
>+ .long infomation_request_end - infomation_request_start
>+ .long MULTIBOOT_TAG_TYPE_CMDLINE
>+ .long MULTIBOOT_TAG_TYPE_MMAP
>+infomation_request_end:
>+
>+ .short MULTIBOOT_HEADER_TAG_END
>+ .short 0
>+ .long 8
>+multiboot_header_end:
>+
>+multiboot_entry:
>+ cmpl $MULTIBOOT2_BOOTLOADER_MAGIC, %eax
>+ jne not_multiboot
>+
>+ .code32
>+ /* %ebp contains the address we are loaded at by the boot loader */
>+ movl $_text - __START_KERNEL_map, %ebp
>+
>+ /* Store the Multiboot information structure */
>+ movl %ebx, (multiboot_info - startup_64)(%ebp)
>+
>+ /*
>+ * The Multiboot-compliant bootloader puts the machine in 32-bit mode
>+ * so we need to switch to long mode by ourself. If later version of
>+ * Multiboot protocal supports 64-bit machine state then this part of
>+ * code may be eliminated.
>+ */
>+ cli
>+ movl $(__BOOT_DS), %eax
>+ movl %eax, %ds
>+ movl %eax, %es
>+ movl %eax, %ss
>+
>+ /* Setup a stack and make sure cpu supports long mode. */
>+ movl (__end_init_task - 8 - startup_64)(%ebp), %eax
>+ movl %eax, %esp
>+
>+ call verify_cpu
>+ testl %eax, %eax
>+ jnz no_longmode
>+
>+/*
>+ * Prepare for entering 64 bit mode
>+ */
>+
>+ /* Load new GDT with the 64bit segments using 32bit descriptor */
>+ leal (gdt - startup_64)(%ebp), %eax
>+ movl %eax, (gdt + 2 - startup_64)(%ebp)
>+ lgdt (gdt - startup_64)(%ebp)
>+
>+ /* Enable PAE mode */
>+ movl %cr4, %eax
>+ orl $X86_CR4_PAE, %eax
>+ movl %eax, %cr4
>+
>+ /*
>+ * Build early 4G boot pagetable
>+ */
>+ /* Initialize Page tables to 0 */
>+ /*leal pgtable(%ebp), %edi
>+ xorl %eax, %eax
>+ movl $(BOOT_INIT_PGT_SIZE/4), %ecx
>+ rep stosl*/
>+
>+ /* Build Level 4 */
>+ leal (pgtable - startup_64)(%ebp), %edi
>+ leal 0x1007 (%edi), %eax
>+ movl %eax, 0(%edi)
>+
>+ /* Build Level 3 */
>+ leal (pgtable + 0x1000 - startup_64)(%ebp), %edi
>+ leal 0x1007(%edi), %eax
>+ movl $4, %ecx
>+1: movl %eax, 0x00(%edi)
>+ addl $0x00001000, %eax
>+ addl $8, %edi
>+ decl %ecx
>+ jnz 1b
>+
>+ /* Build Level 2 */
>+ leal (pgtable + 0x2000 - startup_64)(%ebp), %edi
>+ movl $0x00000183, %eax
>+ movl $2048, %ecx
>+1: movl %eax, 0(%edi)
>+ addl $0x00200000, %eax
>+ addl $8, %edi
>+ decl %ecx
>+ jnz 1b
>+
>+ /* Enable the boot page tables */
>+ leal (pgtable - startup_64)(%ebp), %eax
>+ movl %eax, %cr3
>+
>+ /* Enable Long mode in EFER (Extended Feature Enable Register) */
>+ movl $MSR_EFER, %ecx
>+ rdmsr
>+ btsl $_EFER_LME, %eax
>+ wrmsr
>+
>+ /* After gdt is loaded */
>+ xorl %eax, %eax
>+ lldt %ax
>+ movl $__BOOT_TSS, %eax
>+ ltr %ax
>+
>+ /*
>+ * Setup for the jump to 64bit mode
>+ *
>+ * When the jump is performend we will be in long mode but
>+ * in 32bit compatibility mode with EFER.LME = 1, CS.L = 0, CS.D = 1
>+ * (and in turn EFER.LMA = 1). To jump into 64bit mode we use
>+ * the new gdt/idt that has __KERNEL_CS with CS.L = 1.
>+ * We place all of the values on our mini stack so lret can
>+ * used to perform that far jump.
>+ */
>+ pushl $__KERNEL_CS
>+ leal (not_multiboot - startup_64)(%ebp), %eax
>+ pushl %eax
>+
>+ /* Enter paged protected Mode, activating Long Mode */
>+ movl $(X86_CR0_PG | X86_CR0_PE), %eax /* Enable Paging and Protected
>mode */
>+ movl %eax, %cr0
>+
>+ /* Jump from 32bit compatibility mode into 64bit mode. */
>+ lret
>+
>+no_longmode:
>+ /* This isn't an x86-64 CPU so hang */
>+1:
>+ hlt
>+ jmp 1b
>+
>+ .code64
>+not_multiboot:
>+#endif
>+
> /*
> * Setup stack for verify_cpu(). "-8" because initial_stack is defined
> * this way, see below. Our best guess is a NULL ptr for stack
>@@ -489,6 +647,23 @@ ENTRY(phys_base)
> .quad 0x0000000000000000
> EXPORT_SYMBOL(phys_base)
>
>+#ifdef CONFIG_X86_MULTIBOOT_STUB
>+gdt:
>+ .word gdt_end - gdt
>+ .long 0
>+ .word 0
>+ .quad 0x0000000000000000 /* NULL descriptor */
>+ .quad 0x00af9a000000ffff /* __KERNEL_CS */
>+ .quad 0x00cf92000000ffff /* __KERNEL_DS */
>+ .quad 0x0080890000000000 /* TS descriptor */
>+ .quad 0x0000000000000000 /* TS continued */
>+gdt_end:
>+
>+ .balign 4096
>+pgtable:
>+ .fill BOOT_PGT_SIZE, 1, 0
>+#endif
>+
> #include "../../x86/xen/xen-head.S"
>
> __PAGE_ALIGNED_BSS
>diff --git a/arch/x86/kernel/multiboot2.h
>b/arch/x86/kernel/multiboot2.h
>new file mode 100644
>index 0000000..03bb5d2
>--- /dev/null
>+++ b/arch/x86/kernel/multiboot2.h
>@@ -0,0 +1,417 @@
>+/* multiboot2.h - Multiboot 2 header file. */
>+/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software
>Foundation, Inc.
>+ *
>+ * Permission is hereby granted, free of charge, to any person
>obtaining a copy
>+ * of this software and associated documentation files (the
>"Software"), to
>+ * deal in the Software without restriction, including without
>limitation the
>+ * rights to use, copy, modify, merge, publish, distribute,
>sublicense, and/or
>+ * sell copies of the Software, and to permit persons to whom the
>Software is
>+ * furnished to do so, subject to the following conditions:
>+ *
>+ * The above copyright notice and this permission notice shall be
>included in
>+ * all copies or substantial portions of the Software.
>+ *
>+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>EXPRESS OR
>+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>MERCHANTABILITY,
>+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
>SHALL ANY
>+ * DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>LIABILITY,
>+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
>OUT OF OR
>+ * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
>THE SOFTWARE.
>+ */
>+
>+#ifndef _ARCH_X86_KERNEL_MULTIBOOT2
>+#define _ARCH_X86_KERNEL_MULTIBOOT2
>+
>+/* How many bytes from the start of the file we search for the header.
> */
>+#define MULTIBOOT_SEARCH 32768
>+#define MULTIBOOT_HEADER_ALIGN 8
>+
>+/* The magic field should contain this. */
>+#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
>+
>+/* This should be in %eax. */
>+#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289
>+
>+/* Alignment of multiboot modules. */
>+#define MULTIBOOT_MOD_ALIGN 0x00001000
>+
>+/* Alignment of the multiboot info structure. */
>+#define MULTIBOOT_INFO_ALIGN 0x00000008
>+
>+/* Flags set in the 'flags' member of the multiboot header. */
>+
>+#define MULTIBOOT_TAG_ALIGN 8
>+#define MULTIBOOT_TAG_TYPE_END 0
>+#define MULTIBOOT_TAG_TYPE_CMDLINE 1
>+#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2
>+#define MULTIBOOT_TAG_TYPE_MODULE 3
>+#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4
>+#define MULTIBOOT_TAG_TYPE_BOOTDEV 5
>+#define MULTIBOOT_TAG_TYPE_MMAP 6
>+#define MULTIBOOT_TAG_TYPE_VBE 7
>+#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
>+#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9
>+#define MULTIBOOT_TAG_TYPE_APM 10
>+#define MULTIBOOT_TAG_TYPE_EFI32 11
>+#define MULTIBOOT_TAG_TYPE_EFI64 12
>+#define MULTIBOOT_TAG_TYPE_SMBIOS 13
>+#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14
>+#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15
>+#define MULTIBOOT_TAG_TYPE_NETWORK 16
>+#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
>+#define MULTIBOOT_TAG_TYPE_EFI_BS 18
>+#define MULTIBOOT_TAG_TYPE_EFI32_IH 19
>+#define MULTIBOOT_TAG_TYPE_EFI64_IH 20
>+#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21
>+
>+#define MULTIBOOT_HEADER_TAG_END 0
>+#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
>+#define MULTIBOOT_HEADER_TAG_ADDRESS 2
>+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
>+#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
>+#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
>+#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
>+#define MULTIBOOT_HEADER_TAG_EFI_BS 7
>+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8
>+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
>+#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10
>+
>+#define MULTIBOOT_ARCHITECTURE_I386 0
>+#define MULTIBOOT_ARCHITECTURE_MIPS32 4
>+#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
>+
>+#define MULTIBOOT_LOAD_PREFERENCE_NONE 0
>+#define MULTIBOOT_LOAD_PREFERENCE_LOW 1
>+#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
>+
>+#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
>+#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
>+
>+#ifndef __ASSEMBLY__
>+
>+typedef unsigned char multiboot_uint8_t;
>+typedef unsigned short multiboot_uint16_t;
>+typedef unsigned int multiboot_uint32_t;
>+typedef unsigned long long multiboot_uint64_t;
>+
>+struct multiboot_header
>+{
>+ /* Must be MULTIBOOT_MAGIC - see above. */
>+ multiboot_uint32_t magic;
>+
>+ /* ISA */
>+ multiboot_uint32_t architecture;
>+
>+ /* Total header length. */
>+ multiboot_uint32_t header_length;
>+
>+ /* The above fields plus this one must equal 0 mod 2^32. */
>+ multiboot_uint32_t checksum;
>+};
>+
>+struct multiboot_header_tag
>+{
>+ multiboot_uint16_t type;
>+ multiboot_uint16_t flags;
>+ multiboot_uint32_t size;
>+};
>+
>+struct multiboot_header_tag_information_request
>+{
>+ multiboot_uint16_t type;
>+ multiboot_uint16_t flags;
>+ multiboot_uint32_t size;
>+ multiboot_uint32_t requests[0];
>+};
>+
>+struct multiboot_header_tag_address
>+{
>+ multiboot_uint16_t type;
>+ multiboot_uint16_t flags;
>+ multiboot_uint32_t size;
>+ multiboot_uint32_t header_addr;
>+ multiboot_uint32_t load_addr;
>+ multiboot_uint32_t load_end_addr;
>+ multiboot_uint32_t bss_end_addr;
>+};
>+
>+struct multiboot_header_tag_entry_address
>+{
>+ multiboot_uint16_t type;
>+ multiboot_uint16_t flags;
>+ multiboot_uint32_t size;
>+ multiboot_uint32_t entry_addr;
>+};
>+
>+struct multiboot_header_tag_console_flags
>+{
>+ multiboot_uint16_t type;
>+ multiboot_uint16_t flags;
>+ multiboot_uint32_t size;
>+ multiboot_uint32_t console_flags;
>+};
>+
>+struct multiboot_header_tag_framebuffer
>+{
>+ multiboot_uint16_t type;
>+ multiboot_uint16_t flags;
>+ multiboot_uint32_t size;
>+ multiboot_uint32_t width;
>+ multiboot_uint32_t height;
>+ multiboot_uint32_t depth;
>+};
>+
>+struct multiboot_header_tag_module_align
>+{
>+ multiboot_uint16_t type;
>+ multiboot_uint16_t flags;
>+ multiboot_uint32_t size;
>+};
>+
>+struct multiboot_header_tag_relocatable
>+{
>+ multiboot_uint16_t type;
>+ multiboot_uint16_t flags;
>+ multiboot_uint32_t size;
>+ multiboot_uint32_t min_addr;
>+ multiboot_uint32_t max_addr;
>+ multiboot_uint32_t align;
>+ multiboot_uint32_t preference;
>+};
>+
>+struct multiboot_color
>+{
>+ multiboot_uint8_t red;
>+ multiboot_uint8_t green;
>+ multiboot_uint8_t blue;
>+};
>+
>+struct multiboot_mmap_entry
>+{
>+ multiboot_uint64_t addr;
>+ multiboot_uint64_t len;
>+#define MULTIBOOT_MEMORY_AVAILABLE 1
>+#define MULTIBOOT_MEMORY_RESERVED 2
>+#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
>+#define MULTIBOOT_MEMORY_NVS 4
>+#define MULTIBOOT_MEMORY_BADRAM 5
>+ multiboot_uint32_t type;
>+ multiboot_uint32_t zero;
>+};
>+typedef struct multiboot_mmap_entry multiboot_memory_map_t;
>+
>+struct multiboot_tag
>+{
>+ multiboot_uint32_t type;
>+ multiboot_uint32_t size;
>+};
>+
>+struct multiboot_tag_string
>+{
>+ multiboot_uint32_t type;
>+ multiboot_uint32_t size;
>+ char string[0];
>+};
>+
>+struct multiboot_tag_module
>+{
>+ multiboot_uint32_t type;
>+ multiboot_uint32_t size;
>+ multiboot_uint32_t mod_start;
>+ multiboot_uint32_t mod_end;
>+ char cmdline[0];
>+};
>+
>+struct multiboot_tag_basic_meminfo
>+{
>+ multiboot_uint32_t type;
>+ multiboot_uint32_t size;
>+ multiboot_uint32_t mem_lower;
>+ multiboot_uint32_t mem_upper;
>+};
>+
>+struct multiboot_tag_bootdev
>+{
>+ multiboot_uint32_t type;
>+ multiboot_uint32_t size;
>+ multiboot_uint32_t biosdev;
>+ multiboot_uint32_t slice;
>+ multiboot_uint32_t part;
>+};
>+
>+struct multiboot_tag_mmap
>+{
>+ multiboot_uint32_t type;
>+ multiboot_uint32_t size;
>+ multiboot_uint32_t entry_size;
>+ multiboot_uint32_t entry_version;
>+ struct multiboot_mmap_entry entries[0];
>+};
>+
>+struct multiboot_vbe_info_block
>+{
>+ multiboot_uint8_t external_specification[512];
>+};
>+
>+struct multiboot_vbe_mode_info_block
>+{
>+ multiboot_uint8_t external_specification[256];
>+};
>+
>+struct multiboot_tag_vbe
>+{
>+ multiboot_uint32_t type;
>+ multiboot_uint32_t size;
>+
>+ multiboot_uint16_t vbe_mode;
>+ multiboot_uint16_t vbe_interface_seg;
>+ multiboot_uint16_t vbe_interface_off;
>+ multiboot_uint16_t vbe_interface_len;
>+
>+ struct multiboot_vbe_info_block vbe_control_info;
>+ struct multiboot_vbe_mode_info_block vbe_mode_info;
>+};
>+
>+struct multiboot_tag_framebuffer_common
>+{
>+ multiboot_uint32_t type;
>+ multiboot_uint32_t size;
>+
>+ multiboot_uint64_t framebuffer_addr;
>+ multiboot_uint32_t framebuffer_pitch;
>+ multiboot_uint32_t framebuffer_width;
>+ multiboot_uint32_t framebuffer_height;
>+ multiboot_uint8_t framebuffer_bpp;
>+#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
>+#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
>+#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
>+ multiboot_uint8_t framebuffer_type;
>+ multiboot_uint16_t reserved;
>+};
>+
>+struct multiboot_tag_framebuffer
>+{
>+ struct multiboot_tag_framebuffer_common common;
>+
>+ union
>+ {
>+ struct
>+ {
>+ multiboot_uint16_t framebuffer_palette_num_colors;
>+ struct multiboot_color framebuffer_palette[0];
>+ };
>+ struct
>+ {
>+ multiboot_uint8_t framebuffer_red_field_position;
>+ multiboot_uint8_t framebuffer_red_mask_size;
>+ multiboot_uint8_t framebuffer_green_field_position;
>+ multiboot_uint8_t framebuffer_green_mask_size;
>+ multiboot_uint8_t framebuffer_blue_field_position;
>+ multiboot_uint8_t framebuffer_blue_mask_size;
>+ };
>+ };
>+};
>+
>+struct multiboot_tag_elf_sections
>+{
>+ multiboot_uint32_t type;
>+ multiboot_uint32_t size;
>+ multiboot_uint32_t num;
>+ multiboot_uint32_t entsize;
>+ multiboot_uint32_t shndx;
>+ char sections[0];
>+};
>+
>+struct multiboot_tag_apm
>+{
>+ multiboot_uint32_t type;
>+ multiboot_uint32_t size;
>+ multiboot_uint16_t version;
>+ multiboot_uint16_t cseg;
>+ multiboot_uint32_t offset;
>+ multiboot_uint16_t cseg_16;
>+ multiboot_uint16_t dseg;
>+ multiboot_uint16_t flags;
>+ multiboot_uint16_t cseg_len;
>+ multiboot_uint16_t cseg_16_len;
>+ multiboot_uint16_t dseg_len;
>+};
>+
>+struct multiboot_tag_efi32
>+{
>+ multiboot_uint32_t type;
>+ multiboot_uint32_t size;
>+ multiboot_uint32_t pointer;
>+};
>+
>+struct multiboot_tag_efi64
>+{
>+ multiboot_uint32_t type;
>+ multiboot_uint32_t size;
>+ multiboot_uint64_t pointer;
>+};
>+
>+struct multiboot_tag_smbios
>+{
>+ multiboot_uint32_t type;
>+ multiboot_uint32_t size;
>+ multiboot_uint8_t major;
>+ multiboot_uint8_t minor;
>+ multiboot_uint8_t reserved[6];
>+ multiboot_uint8_t tables[0];
>+};
>+
>+struct multiboot_tag_old_acpi
>+{
>+ multiboot_uint32_t type;
>+ multiboot_uint32_t size;
>+ multiboot_uint8_t rsdp[0];
>+};
>+
>+struct multiboot_tag_new_acpi
>+{
>+ multiboot_uint32_t type;
>+ multiboot_uint32_t size;
>+ multiboot_uint8_t rsdp[0];
>+};
>+
>+struct multiboot_tag_network
>+{
>+ multiboot_uint32_t type;
>+ multiboot_uint32_t size;
>+ multiboot_uint8_t dhcpack[0];
>+};
>+
>+struct multiboot_tag_efi_mmap
>+{
>+ multiboot_uint32_t type;
>+ multiboot_uint32_t size;
>+ multiboot_uint32_t descr_size;
>+ multiboot_uint32_t descr_vers;
>+ multiboot_uint8_t efi_mmap[0];
>+};
>+
>+struct multiboot_tag_efi32_ih
>+{
>+ multiboot_uint32_t type;
>+ multiboot_uint32_t size;
>+ multiboot_uint32_t pointer;
>+};
>+
>+struct multiboot_tag_efi64_ih
>+{
>+ multiboot_uint32_t type;
>+ multiboot_uint32_t size;
>+ multiboot_uint64_t pointer;
>+};
>+
>+struct multiboot_tag_load_base_addr
>+{
>+ multiboot_uint32_t type;
>+ multiboot_uint32_t size;
>+ multiboot_uint32_t load_base_addr;
>+};
>+
>+#endif /* __ASSEMBLY__ */
>+
>+#endif /* _ARCH_X86_KERNEL_MULTIBOOT2 */

As has been shown many times before, this is a really bad idea. Unless there is a real-life use case where this matters enormously, this is nacked with extreme prejudice.
--
Sent from my Android device with K-9 Mail. Please excuse my brevity.