/*
 * i386 boot code, based on  qemu-bmibug.
 *
 * Copyright 2019 Doug Gale
 * Copyright 2019, 2024 Linaro
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

        .section .head

        /* Multi-boot header */
multiboot_st:
        .int 0x1BADB002
        .int 0x10000
        .int -(0x10000+0x1BADB002)
        // Load address
        .int __load_st
        .int __load_st
        .int __load_en
        .int __bss_en
        .int _start
        // mode
        .int 0
        // width
        .int 0
        // height
        .int 0
        // depth
        .int 0

        .code32
        .section .text

        /* Kernel Entry Point */
.global _start
_start:
        // Setup stack ASAP
        mov $stack_end,%esp

        // Load GDT ASAP
        lgdt gdtr
        ljmp $0x8,$.Lloadcs
.Lloadcs:
        mov $0x10,%eax
        mov %eax,%ds
        mov %eax,%es
        mov %eax,%fs
        mov %eax,%gs
        mov %eax,%ss

        // Fixup the IDT to the ridiculous i386 layout
        xor %ebx,%ebx
.Lnextidt:
        mov idt_00(,%ebx,8),%eax
        shr $16,%eax
        movw $0x8,idt_00+2(,%ebx,8)
        movw $0x8E00,idt_00+4(,%ebx,8)
        movw %ax,idt_00+6(,%ebx,8)
        add $1,%ebx
        cmp $32,%ebx
        jl .Lnextidt

        // Load IDTR
        push $idt_00
        push $((32 * 8 - 1) << 16)
        lidt 2(%esp)
        add $8,%esp

        /*
         * Don't worry about stack frame, assume everything
         * is garbage when we return, we won't need it.
         */
        call main

_exit:	/* output any non-zero result in eax to isa-debug-exit device */
        test %al, %al
        jz 1f
        out %ax, $0xf4

1:      /* QEMU ACPI poweroff */
        mov $0x604,%edx
        mov $0x2000,%eax
        out %ax,%dx
        hlt
        jmp 1b

        /*
         * Helper Functions
         */

        /* Output a single character to serial port */
        .global __sys_outc
__sys_outc:
        pushl %ebp
        movl %esp, %ebp
        out %al,$0xE9
        movl %ebp, %esp
        popl %ebp
        ret


        /* Interrupt Descriptor Table */

        .section .data
        .align 16

idt_00: .int 0, 0
idt_01: .int 0, 0
idt_02: .int 0, 0
idt_03: .int 0, 0
idt_04: .int 0, 0
idt_05: .int 0, 0
idt_06: .int 0, 0 /* intr_6_opcode, Invalid Opcode */
idt_07: .int 0, 0
idt_08: .int 0, 0
idt_09: .int 0, 0
idt_0A: .int 0, 0
idt_0B: .int 0, 0
idt_0C: .int 0, 0
idt_0D: .int 0, 0
idt_0E: .int 0, 0
idt_0F: .int 0, 0
idt_10: .int 0, 0
idt_11: .int 0, 0
idt_12: .int 0, 0
idt_13: .int 0, 0
idt_14: .int 0, 0
idt_15: .int 0, 0
idt_16: .int 0, 0
idt_17: .int 0, 0
idt_18: .int 0, 0
idt_19: .int 0, 0
idt_1A: .int 0, 0
idt_1B: .int 0, 0
idt_1C: .int 0, 0
idt_1D: .int 0, 0
idt_1E: .int 0, 0
idt_1F: .int 0, 0

gdt:
        .short 0
gdtr:
        .short gdt_en - gdt - 1
        .int gdt

        // Code
        .short 0xFFFF
        .short 0
        .byte 0
        .byte 0x9b
        .byte 0xCF
        .byte 0

        // Data
        .short 0xFFFF
        .short 0
        .byte 0
        .byte 0x93
        .byte 0xCF
        .byte 0

gdt_en:

        .section .bss
        .align 16

stack: .space 65536
stack_end: