Files
stevia/include/BIOS/func/E820_memory_map.nasm

114 lines
3.9 KiB
NASM

; Copyright (C) 2025 Elaina Claus
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <https://www.gnu.org/licenses/>.
%ifndef __INC_E820MEMORY_MAP
; Address Range Descriptor Structure
;
; Offset in Bytes Name Description
; 0 BaseAddrLow u32 - Low 32 Bits of Base Address
; 4 BaseAddrHigh u32 - High 32 Bits of Base Address
; 8 LengthLow u32 - Low 32 Bits of Length in Bytes
; 12 LengthHigh u32 - High 32 Bits of Length in Bytes
; 16 Type u32 - Address type of this range.
; 20 ExtType u32 - ACPI 3.0 extended type
struc AddressRangeDescStruct_t
.BaseAddrLow resd 1
.BaseAddrHigh resd 1
.LengthLow resd 1
.LengthHigh resd 1
.Type resd 1
.ExtType resd 1
endstruc
; !!! this procedure changes ES !!!
ALIGN 4, db 0x90
GetMemoryMap:
__CDECL16_PROC_ENTRY
push es ; save segment register
.func:
mov word [SteviaInfo + SteviaInfoStruct_t.u16_E820MMapEntryCount], 0
xor ebx, ebx ; Continuation value, 0 for the first call
mov di, BIOSMemoryMap ; destination is es:di, es should == ds
mov ecx, AddressRangeDescStruct_t_size ; hard request ACPI 3.0 table versions (24 bytes)
.loop_L1:
mov eax, 0x0000E820 ; select 0xE820 function
mov edx, 0x534D4150 ; 'SMAP' magic
clc ; clear carry
int 0x15 ; data will be stored at es:di by e820 call
jc GetMemoryMap.error
cmp eax, 0x534D4150
jne GetMemoryMap.no_smap_returned
.no_error:
inc word [SteviaInfo + SteviaInfoStruct_t.u16_E820MMapEntryCount]
cmp ecx, 20 ; TODO: maybe this could be handled better than just panicing
jb GetMemoryMap.nonstandard_e820 ; non-standard entry found
cmp ebx, 0
je GetMemoryMap.endp ; 0 in ebx means we have reached the end of memory ranges
; setup for next loop, ebx is our next index and has already been set.
xor ecx, ecx
mov ecx, AddressRangeDescStruct_t_size ; set ecx (requested_size) to 24 bytes
add di, cx ; increment di to next descriptor so es:di points to the next free space
jmp GetMemoryMap.loop_L1
.error:
ERROR STAGE2_MM_E820_MISC_ERR
.nonstandard_e820:
ERROR STAGE2_MM_E820_NONSTANDARD
.no_smap_returned:
ERROR STAGE2_MM_E820_NO_SMAP
.endp:
pop es
__CDECL16_PROC_EXIT
ret
PrintMemoryMap:
__CDECL16_PROC_ENTRY
.func:
mov eax, dword [SteviaInfo + SteviaInfoStruct_t.u16_E820MMapEntryCount]
cmp eax, 0
je PrintMemoryMap.endp ; if entries == 0, exit
mov ecx, eax ; store # of entries in counter
mov eax, BIOSMemoryMap ; address to start of e820 mmap
push dword ecx
push dword eax
call FormatMemoryMapEntry
add sp, 0x8
; ax contains segment offset to string after call
; TODO: going to need an allocator for strings and stuff...
; print_string strformat_buffer
.endp:
__CDECL16_PROC_EXIT
ret
FormatMemoryMapEntry:
__CDECL16_PROC_ENTRY
.func:
; create a string buffer somewhere and return address to result string in ax
.endp:
__CDECL16_PROC_EXIT
ret
%endif
%define __INC_E820MEMORY_MAP