diff options
Diffstat (limited to 'arch/x86/cpu')
-rw-r--r-- | arch/x86/cpu/Makefile | 7 | ||||
-rw-r--r-- | arch/x86/cpu/baytrail/Kconfig | 2 | ||||
-rw-r--r-- | arch/x86/cpu/baytrail/cpu.c | 2 | ||||
-rw-r--r-- | arch/x86/cpu/baytrail/valleyview.c | 10 | ||||
-rw-r--r-- | arch/x86/cpu/call32.S | 64 | ||||
-rw-r--r-- | arch/x86/cpu/call64.S | 4 | ||||
-rw-r--r-- | arch/x86/cpu/cpu.c | 23 | ||||
-rw-r--r-- | arch/x86/cpu/efi/Makefile | 8 | ||||
-rw-r--r-- | arch/x86/cpu/efi/efi.c | 42 | ||||
-rw-r--r-- | arch/x86/cpu/efi/elf_ia32_efi.lds | 94 | ||||
-rw-r--r-- | arch/x86/cpu/efi/elf_x86_64_efi.lds | 83 | ||||
-rw-r--r-- | arch/x86/cpu/efi/sdram.c | 29 | ||||
-rw-r--r-- | arch/x86/cpu/interrupts.c | 25 | ||||
-rw-r--r-- | arch/x86/cpu/mp_init.c | 2 | ||||
-rw-r--r-- | arch/x86/cpu/qemu/Makefile | 5 | ||||
-rw-r--r-- | arch/x86/cpu/qemu/qemu.c | 2 | ||||
-rw-r--r-- | arch/x86/cpu/start.S | 73 |
17 files changed, 432 insertions, 43 deletions
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile index 8a8e63e1d3..e7979254db 100644 --- a/arch/x86/cpu/Makefile +++ b/arch/x86/cpu/Makefile @@ -12,8 +12,15 @@ extra-y = start.o obj-$(CONFIG_X86_RESET_VECTOR) += resetvec.o start16.o obj-y += interrupts.o cpu.o cpu_x86.o call64.o +AFLAGS_REMOVE_call32.o := -mregparm=3 \ + $(if $(CONFIG_EFI_STUB_64BIT),-march=i386 -m32) +AFLAGS_call32.o := -fpic -fshort-wchar + +extra-y += call32.o + obj-$(CONFIG_INTEL_BAYTRAIL) += baytrail/ obj-$(CONFIG_SYS_COREBOOT) += coreboot/ +obj-$(CONFIG_EFI_APP) += efi/ obj-$(CONFIG_QEMU) += qemu/ obj-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += ivybridge/ obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/ diff --git a/arch/x86/cpu/baytrail/Kconfig b/arch/x86/cpu/baytrail/Kconfig index e86cc01115..407feb214b 100644 --- a/arch/x86/cpu/baytrail/Kconfig +++ b/arch/x86/cpu/baytrail/Kconfig @@ -6,4 +6,4 @@ config INTEL_BAYTRAIL bool - select HAVE_FSP + select HAVE_FSP if !EFI diff --git a/arch/x86/cpu/baytrail/cpu.c b/arch/x86/cpu/baytrail/cpu.c index a0117308ae..b1faf8ca32 100644 --- a/arch/x86/cpu/baytrail/cpu.c +++ b/arch/x86/cpu/baytrail/cpu.c @@ -45,6 +45,8 @@ static void set_max_freq(void) static int cpu_x86_baytrail_probe(struct udevice *dev) { + if (!ll_boot_init()) + return 0; debug("Init BayTrail core\n"); /* diff --git a/arch/x86/cpu/baytrail/valleyview.c b/arch/x86/cpu/baytrail/valleyview.c index 9915da5bd7..610e9d9b1d 100644 --- a/arch/x86/cpu/baytrail/valleyview.c +++ b/arch/x86/cpu/baytrail/valleyview.c @@ -7,6 +7,7 @@ #include <common.h> #include <mmc.h> #include <pci_ids.h> +#include <asm/irq.h> #include <asm/post.h> static struct pci_device_id mmc_supported[] = { @@ -20,6 +21,7 @@ int cpu_mmc_init(bd_t *bis) ARRAY_SIZE(mmc_supported)); } +#ifndef CONFIG_EFI_APP int arch_cpu_init(void) { int ret; @@ -35,3 +37,11 @@ int arch_cpu_init(void) return 0; } + +int arch_misc_init(void) +{ + pirq_init(); + + return 0; +} +#endif diff --git a/arch/x86/cpu/call32.S b/arch/x86/cpu/call32.S new file mode 100644 index 0000000000..c517e4a89f --- /dev/null +++ b/arch/x86/cpu/call32.S @@ -0,0 +1,64 @@ +/* + * (C) Copyright 2015 Google, Inc + * Written by Simon Glass <sjg@chromium.org> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm/global_data.h> +#include <asm/msr-index.h> +#include <asm/processor-flags.h> + + /* + * rdi - 32-bit code segment selector + * rsi - target address + * rdx - table address (0 if none) + */ +.code64 +.globl cpu_call32 +cpu_call32: + cli + + /* Save table pointer */ + mov %edx, %ebx + + /* + * Debugging option, this outputs characters to the console UART + * mov $0x3f8,%edx + * mov $'a',%al + * out %al,(%dx) + */ + + pushf + push %rdi /* 32-bit code segment */ + lea compat(%rip), %rax + push %rax + .byte 0x48 /* REX prefix to force 64-bit far return */ + retf +.code32 +compat: + /* + * We are now in compatibility mode with a default operand size of + * 32 bits. First disable paging. + */ + movl %cr0, %eax + andl $~X86_CR0_PG, %eax + movl %eax, %cr0 + + /* Invalidate TLB */ + xorl %eax, %eax + movl %eax, %cr3 + + /* Disable Long mode in EFER (Extended Feature Enable Register) */ + movl $MSR_EFER, %ecx + rdmsr + btr $_EFER_LME, %eax + wrmsr + + /* Set up table pointer for _x86boot_start */ + mov %ebx, %ecx + + /* Jump to the required target */ + pushl %edi /* 32-bit code segment */ + pushl %esi /* 32-bit target address */ + retf diff --git a/arch/x86/cpu/call64.S b/arch/x86/cpu/call64.S index 74dd5a89dc..08dc473d6a 100644 --- a/arch/x86/cpu/call64.S +++ b/arch/x86/cpu/call64.S @@ -82,8 +82,8 @@ lret_target: .data gdt: - .word gdt_end - gdt - .long gdt + .word gdt_end - gdt - 1 + .long gdt /* Fixed up by code above */ .word 0 .quad 0x0000000000000000 /* NULL descriptor */ .quad 0x00af9a000000ffff /* __KERNEL_CS */ diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index b9134cfef3..129777c717 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -330,13 +330,15 @@ int x86_cpu_init_f(void) const u32 em_rst = ~X86_CR0_EM; const u32 mp_ne_set = X86_CR0_MP | X86_CR0_NE; - /* initialize FPU, reset EM, set MP and NE */ - asm ("fninit\n" \ - "movl %%cr0, %%eax\n" \ - "andl %0, %%eax\n" \ - "orl %1, %%eax\n" \ - "movl %%eax, %%cr0\n" \ - : : "i" (em_rst), "i" (mp_ne_set) : "eax"); + if (ll_boot_init()) { + /* initialize FPU, reset EM, set MP and NE */ + asm ("fninit\n" \ + "movl %%cr0, %%eax\n" \ + "andl %0, %%eax\n" \ + "orl %1, %%eax\n" \ + "movl %%eax, %%cr0\n" \ + : : "i" (em_rst), "i" (mp_ne_set) : "eax"); + } /* identify CPU via cpuid and store the decoded info into gd->arch */ if (has_cpuid()) { @@ -456,7 +458,7 @@ void x86_full_reset(void) int dcache_status(void) { - return !(read_cr0() & 0x40000000); + return !(read_cr0() & X86_CR0_CD); } /* Define these functions to allow ehch-hcd to function */ @@ -712,5 +714,8 @@ __weak int x86_init_cpus(void) int cpu_init_r(void) { - return x86_init_cpus(); + if (ll_boot_init()) + return x86_init_cpus(); + + return 0; } diff --git a/arch/x86/cpu/efi/Makefile b/arch/x86/cpu/efi/Makefile new file mode 100644 index 0000000000..e09163715d --- /dev/null +++ b/arch/x86/cpu/efi/Makefile @@ -0,0 +1,8 @@ +# +# Copyright (c) 2015 Google, Inc +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += efi.o +obj-y += sdram.o diff --git a/arch/x86/cpu/efi/efi.c b/arch/x86/cpu/efi/efi.c new file mode 100644 index 0000000000..75ba0d4844 --- /dev/null +++ b/arch/x86/cpu/efi/efi.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2015 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <fdtdec.h> +#include <netdev.h> + +int arch_cpu_init(void) +{ +#ifdef CONFIG_SYS_X86_TSC_TIMER + timer_set_base(rdtsc()); +#endif + + return 0; +} + +int board_early_init_f(void) +{ + return 0; +} + +int print_cpuinfo(void) +{ + return default_print_cpuinfo(); +} + +void board_final_cleanup(void) +{ +} + +int misc_init_r(void) +{ + return 0; +} + +int arch_misc_init(void) +{ + return 0; +} diff --git a/arch/x86/cpu/efi/elf_ia32_efi.lds b/arch/x86/cpu/efi/elf_ia32_efi.lds new file mode 100644 index 0000000000..cd3b0a982d --- /dev/null +++ b/arch/x86/cpu/efi/elf_ia32_efi.lds @@ -0,0 +1,94 @@ +/* + * U-Boot EFI linker script + * + * SPDX-License-Identifier: BSD-2-Clause + * + * Modified from usr/lib32/elf_ia32_efi.lds in gnu-efi + */ + +#include <config.h> + +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) +ENTRY(_start) +SECTIONS +{ + image_base = .; + .hash : { *(.hash) } /* this MUST come first, EFI expects it */ + . = ALIGN(4096); + .text : + { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + . = ALIGN(4096); + .sdata : + { + *(.got.plt) + *(.got) + *(.srodata) + *(.sdata) + *(.sbss) + *(.scommon) + } + . = ALIGN(4096); + .data : + { + *(.rodata*) + *(.data) + *(.data1) + *(.data.*) + *(.sdata) + *(.got.plt) + *(.got) + /* + * the EFI loader doesn't seem to like a .bss section, so we + * stick it all into .data: + */ + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + + /* U-Boot lists and device tree */ + . = ALIGN(8); + *(SORT(.u_boot_list*)); + . = ALIGN(8); + *(.dtb*); + } + + . = ALIGN(4096); + .dynamic : { *(.dynamic) } + . = ALIGN(4096); + .rel : + { + *(.rel.data) + *(.rel.data.*) + *(.rel.got) + *(.rel.stab) + *(.data.rel.ro.local) + *(.data.rel.local) + *(.data.rel.ro) + *(.data.rel*) + *(.rel.u_boot_list*) + } + . = ALIGN(4096); + .reloc : /* This is the PECOFF .reloc section! */ + { + *(.reloc) + } + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } + . = ALIGN(4096); + /DISCARD/ : + { + *(.rel.reloc) + *(.eh_frame) + *(.note.GNU-stack) + } + .comment 0 : { *(.comment) } +} diff --git a/arch/x86/cpu/efi/elf_x86_64_efi.lds b/arch/x86/cpu/efi/elf_x86_64_efi.lds new file mode 100644 index 0000000000..9d9f05774a --- /dev/null +++ b/arch/x86/cpu/efi/elf_x86_64_efi.lds @@ -0,0 +1,83 @@ +/* + * U-Boot EFI linker script + * + * SPDX-License-Identifier: BSD-2-Clause + * + * Modified from usr/lib32/elf_x86_64_efi.lds in gnu-efi + */ + +#include <config.h> + +OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") +OUTPUT_ARCH(i386:x86-64) +ENTRY(_start) +SECTIONS +{ + image_base = .; + .hash : { *(.hash) } /* this MUST come first, EFI expects it */ + . = ALIGN(4096); + .eh_frame : { + *(.eh_frame) + } + + . = ALIGN(4096); + + .text : { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + . = ALIGN(4096); + + .reloc : { + *(.reloc) + } + + . = ALIGN(4096); + + .data : { + *(.rodata*) + *(.got.plt) + *(.got) + *(.data*) + *(.sdata) + /* the EFI loader doesn't seem to like a .bss section, so we stick + * it all into .data: */ + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + *(.rel.local) + + /* U-Boot lists and device tree */ + . = ALIGN(8); + *(SORT(.u_boot_list*)); + . = ALIGN(8); + *(.dtb*); + } + + . = ALIGN(4096); + .dynamic : { *(.dynamic) } + . = ALIGN(4096); + + .rela : { + *(.rela.data*) + *(.rela.got) + *(.rela.stab) + } + + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } + . = ALIGN(4096); + .ignored.reloc : { + *(.rela.reloc) + *(.eh_frame) + *(.note.GNU-stack) + } + + .comment 0 : { *(.comment) } +} diff --git a/arch/x86/cpu/efi/sdram.c b/arch/x86/cpu/efi/sdram.c new file mode 100644 index 0000000000..51599445ab --- /dev/null +++ b/arch/x86/cpu/efi/sdram.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2015 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <efi.h> +#include <asm/u-boot-x86.h> + +DECLARE_GLOBAL_DATA_PTR; + +ulong board_get_usable_ram_top(ulong total_size) +{ + return (ulong)efi_get_ram_base() + gd->ram_size; +} + +int dram_init(void) +{ + /* gd->ram_size is set as part of EFI init */ + + return 0; +} + +void dram_init_banksize(void) +{ + gd->bd->bi_dram[0].start = efi_get_ram_base(); + gd->bd->bi_dram[0].size = CONFIG_EFI_RAM_SIZE; +} diff --git a/arch/x86/cpu/interrupts.c b/arch/x86/cpu/interrupts.c index 853c82f5a7..9217307e4a 100644 --- a/arch/x86/cpu/interrupts.c +++ b/arch/x86/cpu/interrupts.c @@ -19,6 +19,7 @@ #include <asm/processor-flags.h> #include <linux/compiler.h> #include <asm/msr.h> +#include <asm/processor.h> #include <asm/u-boot-x86.h> #include <asm/i8259.h> @@ -46,7 +47,7 @@ static char *exceptions[] = { "Invalid TSS", "Segment Not Present", "Stack Segment Fault", - "Gerneral Protection", + "General Protection", "Page Fault", "Reserved", "x87 FPU Floating-Point Error", @@ -165,7 +166,6 @@ struct idt_entry { struct desc_ptr { unsigned short size; unsigned long address; - unsigned short segment; } __packed; struct idt_entry idt[256] __aligned(16); @@ -202,14 +202,13 @@ int cpu_init_interrupts(void) for (i = 0; i < 256; i++) { idt[i].access = 0x8e; idt[i].res = 0; - idt[i].selector = 0x10; + idt[i].selector = X86_GDT_ENTRY_32BIT_CS * X86_GDT_ENTRY_SIZE; set_vector(i, irq_entry); irq_entry += irq_entry_size; } - idt_ptr.size = 256 * 8; + idt_ptr.size = 256 * 8 - 1; idt_ptr.address = (unsigned long) idt; - idt_ptr.segment = 0x18; load_idt(&idt_ptr); @@ -243,6 +242,11 @@ int disable_interrupts(void) int interrupt_init(void) { + /* + * When running as an EFI application we are not in control of + * interrupts and should leave them alone. + */ +#ifndef CONFIG_EFI_APP /* Just in case... */ disable_interrupts(); @@ -254,8 +258,15 @@ int interrupt_init(void) /* Initialize core interrupt and exception functionality of CPU */ cpu_init_interrupts(); - /* It is now safe to enable interrupts */ - enable_interrupts(); + /* + * It is now safe to enable interrupts. + * + * TODO(sjg@chromium.org): But we don't handle these correctly when + * booted from EFI. + */ + if (ll_boot_init()) + enable_interrupts(); +#endif return 0; } diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c index e686b28c9c..3294a50b76 100644 --- a/arch/x86/cpu/mp_init.c +++ b/arch/x86/cpu/mp_init.c @@ -24,6 +24,8 @@ #include <dm/uclass-internal.h> #include <linux/linkage.h> +DECLARE_GLOBAL_DATA_PTR; + /* Total CPUs include BSP */ static int num_cpus; diff --git a/arch/x86/cpu/qemu/Makefile b/arch/x86/cpu/qemu/Makefile index be79723a67..9a66b166fe 100644 --- a/arch/x86/cpu/qemu/Makefile +++ b/arch/x86/cpu/qemu/Makefile @@ -4,5 +4,8 @@ # SPDX-License-Identifier: GPL-2.0+ # -obj-y += car.o dram.o qemu.o +ifndef CONFIG_EFI_STUB +obj-y += car.o dram.o +endif +obj-y += qemu.o obj-$(CONFIG_PCI) += pci.o diff --git a/arch/x86/cpu/qemu/qemu.c b/arch/x86/cpu/qemu/qemu.c index 930d2b6c9d..64634a9229 100644 --- a/arch/x86/cpu/qemu/qemu.c +++ b/arch/x86/cpu/qemu/qemu.c @@ -25,11 +25,13 @@ int arch_cpu_init(void) return 0; } +#ifndef CONFIG_EFI_STUB int print_cpuinfo(void) { post_code(POST_CPU_INFO); return default_print_cpuinfo(); } +#endif void reset_cpu(ulong addr) { diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S index 00e585e19b..e5c1733e59 100644 --- a/arch/x86/cpu/start.S +++ b/arch/x86/cpu/start.S @@ -25,11 +25,11 @@ .globl _x86boot_start _x86boot_start: /* - * This is the fail safe 32-bit bootstrap entry point. The - * following code is not executed from a cold-reset (actually, a - * lot of it is, but from real-mode after cold reset. It is - * repeated here to put the board into a state as close to cold - * reset as necessary) + * This is the fail-safe 32-bit bootstrap entry point. + * + * This code is used when booting from another boot loader like + * coreboot or EFI. So we repeat some of the same init found in + * start16. */ cli cld @@ -41,19 +41,34 @@ _x86boot_start: wbinvd /* Tell 32-bit code it is being entered from an in-RAM copy */ - movw $GD_FLG_WARM_BOOT, %bx + movl $GD_FLG_WARM_BOOT, %ebx + + /* + * Zero the BIST (Built-In Self Test) value since we don't have it. + * It must be 0 or the previous loader would have reported an error. + */ + movl $0, %ebp + jmp 1f + + /* Add a way for tools to discover the _start entry point */ + .align 4 + .long 0x12345678 _start: /* - * This is the 32-bit cold-reset entry point. Initialize %bx to 0 - * in case we're preceeded by some sort of boot stub. + * This is the 32-bit cold-reset entry point, coming from start16. + * Set %ebx to GD_FLG_COLD_BOOT to indicate this. */ - movw $GD_FLG_COLD_BOOT, %bx -1: + movl $GD_FLG_COLD_BOOT, %ebx + /* Save BIST */ movl %eax, %ebp +1: + + /* Save table pointer */ + movl %ecx, %esi - /* Load the segement registes to match the gdt loaded in start16.S */ + /* Load the segement registers to match the GDT loaded in start16.S */ movl $(X86_GDT_ENTRY_32BIT_DS * X86_GDT_ENTRY_SIZE), %eax movw %ax, %fs movw %ax, %ds @@ -64,7 +79,11 @@ _start: /* Clear the interrupt vectors */ lidt blank_idt_ptr - /* Early platform init (setup gpio, etc ) */ + /* + * Critical early platform init - generally not used, we prefer init + * to happen later when we have a console, in case something goes + * wrong. + */ jmp early_board_init .globl early_board_init_ret early_board_init_ret: @@ -79,7 +98,7 @@ car_init_ret: * We now have CONFIG_SYS_CAR_SIZE bytes of Cache-As-RAM (or SRAM, * or fully initialised SDRAM - we really don't care which) * starting at CONFIG_SYS_CAR_ADDR to be used as a temporary stack - * and early malloc area. The MRC requires some space at the top. + * and early malloc() area. The MRC requires some space at the top. * * Stack grows down from top of CAR. We have: * @@ -97,7 +116,7 @@ car_init_ret: #endif #else /* - * When we get here after car_init, esp points to a temporary stack + * When we get here after car_init(), esp points to a temporary stack * and esi holds the HOB list address returned by the FSP. */ #endif @@ -125,7 +144,13 @@ car_init_ret: movl %esi, (%edx) skip_hob: +#else + /* Store table pointer */ + movl %esp, %edx + addl $GD_TABLE, %edx + movl %esi, (%edx) #endif + /* Setup first parameter to setup_gdt, pointer to global_data */ movl %esp, %eax @@ -137,17 +162,18 @@ skip_hob: movl %esp, %ecx #if defined(CONFIG_SYS_MALLOC_F_LEN) + /* Set up the pre-relocation malloc pool */ subl $CONFIG_SYS_MALLOC_F_LEN, %esp movl %eax, %edx addl $GD_MALLOC_BASE, %edx movl %esp, (%edx) #endif - /* Store BIST */ + /* Store BIST into global_data */ movl %eax, %edx addl $GD_BIST, %edx movl %ebp, (%edx) - /* Set second parameter to setup_gdt */ + /* Set second parameter to setup_gdt() */ movl %ecx, %edx /* Setup global descriptor table so gd->xyz works */ @@ -157,7 +183,7 @@ skip_hob: post_code(POST_START_DONE) xorl %eax, %eax - /* Enter, U-boot! */ + /* Enter, U-Boot! */ call board_init_f /* indicate (lack of) progress */ @@ -184,13 +210,13 @@ board_init_f_r_trampoline: /* Align global data to 16-byte boundary */ andl $0xfffffff0, %esp - /* Setup first parameter to memcpy (and setup_gdt) */ + /* Setup first parameter to memcpy() and setup_gdt() */ movl %esp, %eax - /* Setup second parameter to memcpy */ + /* Setup second parameter to memcpy() */ fs movl 0, %edx - /* Set third parameter to memcpy */ + /* Set third parameter to memcpy() */ movl $GENERATED_GBL_DATA_SIZE, %ecx /* Copy global data from CAR to SDRAM stack */ @@ -202,7 +228,7 @@ board_init_f_r_trampoline: /* Align global descriptor table to 16-byte boundary */ andl $0xfffffff0, %esp - /* Set second parameter to setup_gdt */ + /* Set second parameter to setup_gdt() */ movl %esp, %edx /* Setup global descriptor table so gd->xyz works */ @@ -216,7 +242,7 @@ board_init_f_r_trampoline: call car_uninit 1: - /* Re-enter U-Boot by calling board_init_f_r */ + /* Re-enter U-Boot by calling board_init_f_r() */ call board_init_f_r die: @@ -230,9 +256,10 @@ blank_idt_ptr: .p2align 2 /* force 4-byte alignment */ + /* Add a multiboot header so U-Boot can be loaded by GRUB2 */ multiboot_header: /* magic */ - .long 0x1BADB002 + .long 0x1badb002 /* flags */ .long (1 << 16) /* checksum */ |