1/* 2 * i386 boot code, based on qemu-bmibug. 3 * 4 * Copyright 2019 Doug Gale 5 * Copyright 2019, 2024 Linaro 6 * 7 * This work is licensed under the terms of the GNU GPL, version 2 or later. 8 * See the COPYING file in the top-level directory. 9 * 10 * SPDX-License-Identifier: GPL-2.0-or-later 11 */ 12 13 .section .head 14 15 /* Multi-boot header */ 16multiboot_st: 17 .int 0x1BADB002 18 .int 0x10000 19 .int -(0x10000+0x1BADB002) 20 // Load address 21 .int __load_st 22 .int __load_st 23 .int __load_en 24 .int __bss_en 25 .int _start 26 // mode 27 .int 0 28 // width 29 .int 0 30 // height 31 .int 0 32 // depth 33 .int 0 34 35 .code32 36 .section .text 37 38 /* Kernel Entry Point */ 39.global _start 40_start: 41 // Setup stack ASAP 42 mov $stack_end,%esp 43 44 // Load GDT ASAP 45 lgdt gdtr 46 ljmp $0x8,$.Lloadcs 47.Lloadcs: 48 mov $0x10,%eax 49 mov %eax,%ds 50 mov %eax,%es 51 mov %eax,%fs 52 mov %eax,%gs 53 mov %eax,%ss 54 55 // Fixup the IDT to the ridiculous i386 layout 56 xor %ebx,%ebx 57.Lnextidt: 58 mov idt_00(,%ebx,8),%eax 59 shr $16,%eax 60 movw $0x8,idt_00+2(,%ebx,8) 61 movw $0x8E00,idt_00+4(,%ebx,8) 62 movw %ax,idt_00+6(,%ebx,8) 63 add $1,%ebx 64 cmp $32,%ebx 65 jl .Lnextidt 66 67 // Load IDTR 68 push $idt_00 69 push $((32 * 8 - 1) << 16) 70 lidt 2(%esp) 71 add $8,%esp 72 73 /* 74 * Don't worry about stack frame, assume everything 75 * is garbage when we return, we won't need it. 76 */ 77 call main 78 79_exit: /* output any non-zero result in eax to isa-debug-exit device */ 80 test %al, %al 81 jz 1f 82 out %ax, $0xf4 83 841: /* QEMU ACPI poweroff */ 85 mov $0x604,%edx 86 mov $0x2000,%eax 87 out %ax,%dx 88 hlt 89 jmp 1b 90 91 /* 92 * Helper Functions 93 */ 94 95 /* Output a single character to serial port */ 96 .global __sys_outc 97__sys_outc: 98 pushl %ebp 99 movl %esp, %ebp 100 out %al,$0xE9 101 movl %ebp, %esp 102 popl %ebp 103 ret 104 105 106 /* Interrupt Descriptor Table */ 107 108 .section .data 109 .align 16 110 111idt_00: .int 0, 0 112idt_01: .int 0, 0 113idt_02: .int 0, 0 114idt_03: .int 0, 0 115idt_04: .int 0, 0 116idt_05: .int 0, 0 117idt_06: .int 0, 0 /* intr_6_opcode, Invalid Opcode */ 118idt_07: .int 0, 0 119idt_08: .int 0, 0 120idt_09: .int 0, 0 121idt_0A: .int 0, 0 122idt_0B: .int 0, 0 123idt_0C: .int 0, 0 124idt_0D: .int 0, 0 125idt_0E: .int 0, 0 126idt_0F: .int 0, 0 127idt_10: .int 0, 0 128idt_11: .int 0, 0 129idt_12: .int 0, 0 130idt_13: .int 0, 0 131idt_14: .int 0, 0 132idt_15: .int 0, 0 133idt_16: .int 0, 0 134idt_17: .int 0, 0 135idt_18: .int 0, 0 136idt_19: .int 0, 0 137idt_1A: .int 0, 0 138idt_1B: .int 0, 0 139idt_1C: .int 0, 0 140idt_1D: .int 0, 0 141idt_1E: .int 0, 0 142idt_1F: .int 0, 0 143 144gdt: 145 .short 0 146gdtr: 147 .short gdt_en - gdt - 1 148 .int gdt 149 150 // Code 151 .short 0xFFFF 152 .short 0 153 .byte 0 154 .byte 0x9b 155 .byte 0xCF 156 .byte 0 157 158 // Data 159 .short 0xFFFF 160 .short 0 161 .byte 0 162 .byte 0x93 163 .byte 0xCF 164 .byte 0 165 166gdt_en: 167 168 .section .bss 169 .align 16 170 171stack: .space 65536 172stack_end: 173