diff --git a/bootloader/bios/CMakeLists.txt b/bootloader/bios/CMakeLists.txt index 73151fcd..1270569f 100644 --- a/bootloader/bios/CMakeLists.txt +++ b/bootloader/bios/CMakeLists.txt @@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.26) project(bootloader ASM) set(BOOTLOADER_SOURCES + a20_line.S boot.S command_line.S disk.S diff --git a/bootloader/bios/a20_line.S b/bootloader/bios/a20_line.S new file mode 100644 index 00000000..101e57bf --- /dev/null +++ b/bootloader/bios/a20_line.S @@ -0,0 +1,166 @@ +.code16 +.section .stage2 + +# checks whether A20 line is enabled or disabled +# return +# ax: 1 if enabled, 0 otherwise +check_a20: + pushf + pushw %si + pushw %di + pushw %ds + pushw %es + + cli + + xorw %ax, %ax + movw %ax, %es + notw %ax + movw %ax, %ds + + movw $0x0500, %di + movw $0x0510, %si + + movb %es:(%di), %al + pushw %ax + + movb %ds:(%si), %al + pushw %ax + + movb $0x00, %es:(%di) + movb $0xFF, %ds:(%si) + + cmpb $0xFF, %es:(%di) + + pop %ax + movb %al, %ds:(%si) + + pop %ax + movb %al, %es:(%di) + + movw $0, %ax + je .check_a20_done + + movw $1, %ax + + .check_a20_done: + popw %es + popw %ds + popw %di + popw %si + popf + ret + + +# Try to enable A20 using PS2 controller +enable_a20_ps2: + pushf + pushw %ax + + cli + + # disable first port + call .enable_a20_ps2_wait1 + movb $0xAD, %al + outb %al, $0x64 + + # read controller output + call .enable_a20_ps2_wait1 + movb $0xD0, %al + outb %al, $0x64 + + call .enable_a20_ps2_wait2 + inb $0x60, %al + pushw %ax + + # write controller output + call .enable_a20_ps2_wait1 + movb $0xD1, %al + outb %al, $0x64 + + call .enable_a20_ps2_wait1 + popw %ax + orw $2, %ax + outb %al, $0x60 + + # enable first port + call .enable_a20_ps2_wait1 + movb $0xAE, %al + outb %al, $0x64 + + call .enable_a20_ps2_wait1 + + popw %ax + popf + ret + + .enable_a20_ps2_wait1: + inb $0x64, %al + test $2, %al + jnz .enable_a20_ps2_wait1 + ret + + .enable_a20_ps2_wait2: + inb $0x64, %al + test $1, %al + jnz .enable_a20_ps2_wait1 + ret + + +# Check if A20 line is disabled. If it is, try to enable it +.global enable_a20 +enable_a20: + pushw %ax + pushw %si + + call check_a20 + testw %ax, %ax + jnz .enable_a20_done + + movw $a20_line_disabled_msg, %si + call puts; call print_newline + + # Try to enable A20 line using bios interrupt + movw $0x2401, %ax + int $0x15 + call check_a20 + testw %ax, %ax + jnz .enable_a20_done + + # Try to enable A20 line using ps2 controller + call enable_a20_ps2 + call check_a20 + testw %ax, %ax + jnz .enable_a20_done + + # Try to enable A20 line using fast A20 gate + inb $0x92, %al + testb $2, %al + jnz .enable_a20_fast_done + orb $2, %al + outb %al, $0x92 + .enable_a20_fast_done: + + call check_a20 + testw %ax, %ax + jnz .enable_a20_done + + movw $a20_could_not_enable_msg, %si + call print_and_halt + + .enable_a20_done: + movw $a20_line_enabled_msg, %si + call puts; call print_newline + + popw %si + popw %ax + ret + +a20_line_disabled_msg: + .asciz "A20 line disabled. Trying to enable it" + +a20_line_enabled_msg: + .asciz "A20 line enabled" + +a20_could_not_enable_msg: + .asciz "Could not enable A20 line" diff --git a/bootloader/bios/boot.S b/bootloader/bios/boot.S index fdb55dc8..90943117 100644 --- a/bootloader/bios/boot.S +++ b/bootloader/bios/boot.S @@ -57,7 +57,11 @@ stage2_main: movw $unreal_enter_msg, %si call puts; call print_newline + call enable_a20 + call get_memory_map + + call print_newline call read_user_command_line call print_newline @@ -129,7 +133,7 @@ enter_unreal_mode: movw $0x10, %bx movw %bx, %ds - andb 0xFE, %al + andb $0xFE, %al movl %eax, %cr0 ljmpl $0x0, $.enter_unreal_mode_unreal