/* Copyright (C) 2021,2022 fef . All rights reserved. */ #include #include #include /* * miscellaneous utility routines shared among both i386 and amd64 startup * sequences (these are called before entering long mode) */ .code32 .section .multiboot.text, "ax", @progbits /* void _x86_write_tss_base(u64 *gdt_entry, struct x86_tss *tss) */ ENTRY(_x86_write_tss_base) movl 4(%esp), %edi movl 8(%esp), %eax movw %ax, 2(%edi) shrl $16, %eax movb %al, 4(%edi) movb %ah, 7(%edi) ret END(_x86_write_tss_base) /* __noreturn void print_err_and_hlt(char *message) */ L_ENTRY(print_err_and_hlt) mov $0x000b8000, %edx mov 4(%esp), %ecx movb $0x4f, %ah /* BIOS color code: white text on red background */ 1: movb (%ecx), %al testb %al, %al jz 2f movw %ax, (%edx) addl $2, %edx incl %ecx jmp 1b 2: cli /* interrupts should already be off, but it won't hurt */ hlt jmp 2b L_END(print_err_and_hlt) ENTRY(_x86_check_multiboot) cmpl $MB2_BOOTLOADER_MAGIC, 4(%esp) jne 1f ret 1: pushl $errmsg_no_multiboot jmp print_err_and_hlt END(_x86_check_multiboot) /* * check if the CPU supports the CPUID instruction * this is done by checking whether we can flip bit 21 in EFLAGS (??) */ ENTRY(_x86_check_cpuid) pushf pop %eax movl %eax, %ecx xorl $(1 << 21), %eax push %eax popf pushf pop %eax push %ecx /* restore original flags */ popf cmp %eax, %ecx je 1f ret 1: pushl $errmsg_no_cpuid jmp print_err_and_hlt END(_x86_err_no_cpuid) ENTRY(_x86_check_ext_cpuid) movl $0x80000000, %eax cpuid cmpl $0x80000001, %eax jb 1f ret 1: pushl $errmsg_no_ext_cpuid jmp print_err_and_hlt END(_x86_check_ext_cpuid) ENTRY(_x86_check_ia32e) movl $0x80000001, %eax cpuid test $(1 << 29), %edx jz 1f ret 1: pushl $errmsg_no_ia32e jmp print_err_and_hlt END(_x86_check_ia32e) .section .multiboot.data, "a", @progbits L_DATA(errmsg_no_multiboot) .asciz "Invalid Multiboot 2 magic number in %eax" L_END(errmsg_no_multiboot) L_DATA(errmsg_no_cpuid) .asciz "CPUID instruction not supported" L_END(errmsg_no_cpuid) L_DATA(errmsg_no_ext_cpuid) .asciz "No extended CPUID features available" L_END(errmsg_no_ext_cpuid) L_DATA(errmsg_no_ia32e) .asciz "CPU does not appear to support IA-32e mode" L_END(errmsg_no_ia32e)