Uefi.inc: Difference between revisions

[unchecked revision][unchecked revision]
Content deleted Content added
m Bot: Replace deprecated source tag with syntaxhighlight
 
(14 intermediate revisions by 7 users not shown)
Line 1:
{{TutorialTone}}
== uefi.inc ==
Is<tt>uefi.inc</tt> a library for [[UEFI]] written in assembly for fasm[[FASM]]. It's main goal was small code, and to achieve that it gives only limited access to UEFI. It was designed to fulfill all the needs of a boot loader, namely
 
* provideProvide user input interface.
* exactlyExactly one way to load and save sectors.
* framebufferFramebuffer services for output.
 
It is not intend to be an universal UEFI library, because you won't need all UEFI functionality in a bootloader, just the ones listed above.
 
=== Hello World from UEFI ===
This shows how to import and use the library.
This shows how to import and use the library. The macro hides UEFI ABI from the programmer, so you don't have to worry about number of arguments, stack alignment and in which registers to pass arguments etc.
<sourcesyntaxhighlight lang="asm">
format pe64 dll efi
entry main
Line 30 ⟶ 31:
section '.data' data readable writeable
 
_hello dbdu 'Hello World',13,10,0
 
section '.reloc' fixups data discardable
</syntaxhighlight>
</source>
 
=== Case studies: usage in a boot loader ===
== Description ==
 
There's only two functions, as you can see in the Hello World example. The names came from the original [[GNU-EFI]] SDK.
 
* InitializeLib - initializes the library, you should call this as soon as possible.
* uefi_call_wrapper - provides a way to call an UEFI function with it's ABI
 
Other than these, you need structure definitions (like ConIn) to figure out the actual function addresses. These are also defined in the include file. As said earlier, those definitions are limited to Console, Framebuffer and Storage to keep the include file small.
 
If you want, you can add more structure definitions any time in a separate include file. The uefi_call_wrapper macro allows you to call those, but it also specifies shortcuts for the most common functions, so that you don't have to use BootServices or RuntimeServices prefixes.
 
=== Case studies: usage in a boot loader ===
Please note that these are only tutorials. They focus on a specific topic only. They do not allocate buffers they use for example. You'll have to write that part on your own.
They were written for those who wants to roll their own UEFI boot loader in assembly. I hope it will save them some sleepless nights and headaches.
==== Reading a character from keyboard ====
<sourcesyntaxhighlight lang="asm">
@@: uefi_call_wrapper ConIn, ReadKeyStroke, ConIn, key
cmp dword [key.scancode], 0
Line 47 ⟶ 60:
key.scancode: dw 0
key.unicode: du 0
</syntaxhighlight>
</source>
 
==== Iterating on disks ====
=== Detecting Memory Map ===
<sourcesyntaxhighlight lang="asm">
mov dword [memmapdescsize], 48
uefi_call_wrapper BootServices, GetMemoryMap, memmapsize, memmapbuff, memmapkey, memmapdescsize, memmapdescver
cmp dword [memmapdescsize], 0
jnz @f
mov dword [memmapdescsize], 48
@@: clc
cmp rax, EFI_SUCCESS
je @f
stc
@@:
 
;data
memmapsize: dq MEMMAP_BUFFSIZE
memmapkey: dq 0
memmapdescsize: dq 0
memmapdescver: dq 0
memmapbuff: rb MEMMAP_BUFFSIZE
</syntaxhighlight>
Note that memmapkey is needed for ExitBootServices. If you use memory allocation or free, you'll have to query again map to get a valid key.
 
==== Iterating on disks ====
<sourcesyntaxhighlight lang="asm">
; query device handles
mov dword [tmp], DEVICEHANDLE_BUFFSIZE
Line 97 ⟶ 133:
blkiouuid: db EFI_BLOCK_IO_PROTOCOL_UUID
bootdiskblkio: dq 0
</syntaxhighlight>
</source>
 
==== Loading a sector from device ====
<source lang="asm">
<sourcesyntaxhighlight lang="asm">
mov rax, qword [bootdiskblkio]
stc
Line 113 ⟶ 150:
jz @f
xor rax, rax
uefi_call_wrapper rbx, EFI_BLOCK_IO_PROTOCOL.ReadBlocks, rcx, rdx, qword [lba], qword [sizesizeinbytes], bufferdiskbuff
stc
cmp rax, EFI_SUCCESS
Line 119 ⟶ 156:
clc
@@:
 
</source>
;data
==== Get sorted list of available video modes ====
lba: dq 0
<source lang="asm">
sizeinbytes: dq 0
diskbuff: rb DISK_BUFFSIZE
</syntaxhighlight>
 
==== Get sorted list of available video modes ====
For a detailed description, see the [[GOP]] article.
<syntaxhighlight lang="asm">
; installation check on GOP. This must return buffer too small if GOP supported
xor rax, rax
Line 149 ⟶ 193:
jne .error
; iterate on each mode for a handle
; get number of modes
mov rcx, qword [gopinterface]
mov r10, qword [rcx + EFI_GRAPHICS_OUTPUT_PROTOCOL.Mode]
Line 171 ⟶ 216:
cmp rax, EFI_SUCCESS
jne .error
; save info to gopmodes
mov r9, qword [gopinfo]
mov eax, dword [r9+EFI_GRAPHICS_OUTPUT_MODE_INFORMATION.HorizontalResolution]
Line 183 ⟶ 229:
;bubble up mode
mov rbx, rdi
.bubble: mov ax, word [rdi+16]
cmp word [rdi+16-32], ax
ja .ok2
Line 189 ⟶ 235:
mov ax, word [rdi+18]
cmp word [rdi+18-32], ax
jae .ok2@f
.switch: mov rax, qword [rdi]
xchg qword [rdi-32], rax
mov qword [rdi], rax
Line 205 ⟶ 251:
cmp rdi, gopmodes
jae .bubble
.ok2@@: mov rdi, rbx
add rdi, 32
.loop: inc rdx
Line 214 ⟶ 260:
mov qword [gopinterface], rax
stc
jmp .nomore
.nomore:
 
Line 233 ⟶ 278:
; 8 bytes mode number
gopmodes: rb MODE_BUFFSIZE
</syntaxhighlight>
</source>
To access framebuffer, you'll have to get it's address. This code returns it in rbx, and buffer's size in rcx:
<sourcesyntaxhighlight lang="asm">
mov rax, qword [gopinterface]
mov rax, qword [rax + EFI_GRAPHICS_OUTPUT_PROTOCOL.Mode]
mov rbx, qword [rax + EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE.FrameBufferBase]
mov rcx, qword [rax + EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE.FrameBufferSize]
</syntaxhighlight>
</source>
 
=== The include file ===
And finally the library that makes the magic alive:
<sourcesyntaxhighlight lang="asm">
;*********************************************************************
;* *
Line 700 ⟶ 745:
uefi_rsptmp: dq 0
 
</syntaxhighlight>
</source>
[[Category:UEFI]][[Category:X86]]