Upload files to "/"

This commit is contained in:
Jezura777 2025-03-31 20:39:54 +02:00
parent 48b640d2cb
commit 9d42dc2ef2

152
hellowrld.asm Normal file
View file

@ -0,0 +1,152 @@
format pe64 dll efi
entry main
; The UEFI calling convention is, as told in the documentation, the same
; as the standard cdecl but for convenience (because it looks like cdecl
; isn't that much standardized) here it is (in C-like notation):
;
; rax func(rcx, rdx, r8, r9, rsp+32, rsp+64, ...)
;
; basically the rest of arguments is passed through the stack with 32bit
; offset as it was designed for variadic functions
; Also important fact about uefi is that uefi apps are called images.
; for further reading I think I recommend the official uefi documentation
; I'm not sure because maybe there might be better source
; macro that saves the most important registers and calls the function
macro call_safe func
{
push rcx
push rbx
call func
pop rbx
pop rcx
}
section '.text' code executable readable
include 'uefi.inc'
main:
; storing the args that the main function is called with
; main(*ImageHandle, *SystemTable)
mov [ImgHdl], rcx
mov [SysTbl], rdx
sub rsp, 6*8+8
; storing the most used structures for faster use
mov rax, [rdx + EFI_SYSTEM_TABLE.BootServices]
mov [BootSrvc], rax
mov rax, [rdx + EFI_SYSTEM_TABLE.ConOut]
mov [Output], rax
; preparing args and calling
; ConOut.SetAttribute(Output, BG_CLR | FG_CLR)
mov rax, EFI_BACKGROUND_BLACK or EFI_GREEN
mov rcx, [Output]
call_safe [rcx + SIMPLE_TEXT_OUTPUT_INTERFACE.SetAttribute]
; clearing the screen
; ConOut.ClearScreen(ConOut)
mov rcx, [Output]
call_safe [rcx + SIMPLE_TEXT_OUTPUT_INTERFACE.ClearScreen]
; printing the initial message to indicate
; that the bootloader started successfully
mov rdx, BootMsg
call print
; TODO: Get and store framebuffer
; Getting the memory map is kind of harder (not in this case), normally
; you would need to call the function two times to get the buffer size
; then allocate it (+ some padding because it will expand because of the
; allocation) and then call it again, but as I'm storing it somewhere
; in memory, I'm not using for now, I can just call it two times without
; the allocation.
; BootServices.GetMemoryMap(
; *MemMapSize,
; *MemMapBuffer,
; *MemMapKey,
; *MemMapDescSize,
; *MemMapDescVer)
.GetMemMap:
lea rcx, [MemMapSize]
mov rdx, [MemMapBuff]
lea r8, [MemMapKey]
lea r9, [MemMapDescSize]
; notice the last argument is moved to r10 and then "pushed" to the stack
; with 32bit offset
lea r10, [MemMapDescVer]
mov [rsp+32], r10
call [BootSrvc + EFI_BOOT_SERVICES_TABLE.GetMemoryMap]
; if it returns buffer too small run the function again as it filled out
; the needed buffer length
cmp al, EFI_BUFFER_TOO_SMALL
je .GetMemMap
; if it returned something else it maybe a problem possible TODO: proper
; error handling for now it just puts out error and exits with non-zero code
cmp rax, EFI_SUCCESS
jne .error
; print a message saying that we didn't f**k up yet...
mov rdx, OKMsg
call print
; preparing args and calling
; BootServices.ExitBootServices(*ImegeHandle, *MemMapKey)
mov rcx, [ImgHdl]
mov rdx, [MemMapKey]
call_safe [BootSrvc + EFI_BOOT_SERVICES_TABLE.ExitBootServices]
cmp rax, EFI_SUCCESS
jne .error
mov eax, EFI_SUCCESS
jmp .exit
.error:
mov rdx, ErrMsg
call print
mov eax, 1
.exit:
ret
; print the string in rdx
print:
mov rcx, [Output]
call_safe [rcx + SIMPLE_TEXT_OUTPUT_INTERFACE.OutputString]
ret
; Should not be reachable
hlt
jmp $
section '.data' data readable writeable
ImgHdl dq ?
SysTbl dq ?
BootSrvc dq ?
Output dq ?
MemMapSize dq 32768
MemMapKey dq ?
MemMapDescSize dq ?
MemMapDescVer dq ?
MemMapBuff dq 0x220000
BootMsg du '[BOOT]: Booting the system...',13,10,0
ErrMsg du '[BOOT]: There was an error :(',13,10,0
OKMsg du '[BOOT]: Everything is OK :), for now...',13,10,0
section '.reloc' fixups data discardable