Upload files to "/"
This commit is contained in:
parent
48b640d2cb
commit
9d42dc2ef2
1 changed files with 152 additions and 0 deletions
152
hellowrld.asm
Normal file
152
hellowrld.asm
Normal 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
|
Loading…
Add table
Add a link
Reference in a new issue