From 94a228b2782d97f408071906a7c9fc3670c1936c Mon Sep 17 00:00:00 2001 From: Eric-Paul Ickhorn Date: Sun, 16 Jun 2024 23:02:55 +0200 Subject: [PATCH] Add A20 line check This commit adds a check for whether the A20 line is usable; checking whether more than one megabyte of RAM can be used. If it isn't usable, it currently isn't activated, but rather, the boot process is stopped. --- i386/loader/src-asm/memory/a20.asm | 95 ++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100755 i386/loader/src-asm/memory/a20.asm diff --git a/i386/loader/src-asm/memory/a20.asm b/i386/loader/src-asm/memory/a20.asm new file mode 100755 index 0000000..a160493 --- /dev/null +++ b/i386/loader/src-asm/memory/a20.asm @@ -0,0 +1,95 @@ + +check_a20_wraparound: +.prolog: + push dword esi + sub esp, 64 + mov esi, esp + + ; EAX is used for the return value, + ; so it doesn't have to be preserved. + mov [esi + (64 - 8)], ebx + mov [esi + (64 - 12)], edi + +.test_a20: + ; Save the values which are going to be overwritten + mov edi, 0x0800 + mov eax, [edi] + mov edi, 0x00100800 + mov ebx, [edi] + + ; Write to two locations which, if A20 wraps around, + ; will both be written to by the second statement. + ; Write 0 to 0x08000 to avoid the unlikely case that + ; those bytes are there coincidentally and A20 is on. + mov edi, 0x0800 + mov [edi], dword 0x00000000 + mov edi, 0x00100800 + mov [edi], dword 0xffaa00dd + + ; Check the lower address (which should NOT contain) + ; this value for the value. If it does contain it, the + ; memory space wraps around to 0 every 2^19 bytes. + cmp [0x0800], dword 0xffaa00dd + je .return_a20_not_enabled ; If the value at 0x0800 + ; was written to instead + ; (or at the same time) of + ; writing to 0x100800, + ; the A20 wasn't enabled. + ; Reset the values at the addresses to which the test + ; values were written znd return that A20 is enabled. + mov edi, 0x0800 + mov [edi], eax + mov edi, 0x00100800 + mov [edi], ebx + +.return_a20_enabled: + + mov eax, 1 + + ; Restore the one used register which + ; doesn't contain the return value. + mov ebx, [esi + (64 - 8)] + + add esp, 64 + pop dword esi + ret + +.return_a20_not_enabled: + ; It's only necessary to write to one of the addresses + ; as both of them are equal either way. + mov edi, 0x0800 + mov [edi], eax + + mov eax, 0 + + ; Restore the one used register which + ; doesn't contain the return value. + mov ebx, [esi + (64 - 12)] + mov edi, [esi + (64 - 8)] + + add esp, 64 + pop dword esi + ret + + + +enable_a20_through_keyboard_controller: +.prolog: + push dword esi + sub esp, 64 + mov esi, esp + + mov [esi + (64 - 8)], ebx + mov [esi + (64 - 12)], ecx + mov [esi + (64 - 16)], edx + mov [esi + (64 - 20)], edi + +.epilog: + mov ebx, [esi + (64 - 8)] + mov ecx, [esi + (64 - 12)] + mov edx, [esi + (64 - 16)] + mov edi, [esi + (64 - 20)] + + add esp, 64 + pop dword esi + ret