flat assembler
Message board for the users of flat assembler.
Index
> Tutorials and Examples > UEFI basics tutorial by MrFox |
Author |
|
MrFox 04 Nov 2016, 07:07
Hello. I've been learning UEFI for a few months and I would like to start a series of tutorials to share what I have learned by now. Traditionally, programming in a new environment starts off with a 'Hello world' program.
Here it is (code and some explanations in comments): Code: ; ; Hello.asm ; Hello UEFI in assembly ; Flat Assembler v1.71.54 ; 2016 MrFox ; ; Symbols and structures ; The UEFI favorite data type: Unsigned Integer Native width ; (32-bit width in 32-bit systems, 64-bit in 64-bit systems) ; I use 32-bit width because my EFI is 32-bit (rd) ; Data alignment must be same as width ; (all UEFI data stuff must be native aligned) struc UINTN { align 4 . rd 1 } ; Error codes EFI_SUCCESS = 0 EFIERR = 0x80000000 EFI_LOAD_ERROR = EFIERR or 1 EFI_INVALID_PARAMETER = EFIERR or 2 EFI_UNSUPPORTED = EFIERR or 3 ; Etc (more error codes in EFI spec) ; Our program on entry gets two pointers as arguments: ; ImageHandle and SystemTable (see below at the beginning of code) ; ImageHandle is just like an ID of our running app ; SystemTable is just a table somewhere in memory ; which contains pointers to all functionality of UEFI ; (without it our program is blind and can't contact with UEFI ; functions just because it doesn't know where they are) ; SystemTable structure virtual at 0 EFI_SYSTEM_TABLE: ; Table header .Signature rq 1 .Revision UINTN .HeaderSize UINTN .CRC32 UINTN .Reserved UINTN ; Rest of the table .FirmwareVendor UINTN .FirmwareRevision UINTN .ConsoleInHandle UINTN .ConIn UINTN .ConsoleOutHandle UINTN .ConOut UINTN ; We need this one to handle screen output .StandardErrorHandle UINTN .StdErr UINTN .RuntimeServices UINTN .BootServices UINTN .NumberOfTableEntries UINTN .ConfigurationTable UINTN end virtual ; Simple Text Output is a Protocol (like just a set of functions). ; The ConOut pointer in SystemTable (above) points to the memory address ; where the table described just below is located. ; The table itself contains memory addresses to 'call' ; if we want to use a specific UIFI function virtual at 0 SIMPLE_TEXT_OUTPUT: .Reset UINTN .OutputString UINTN ; Calling this address will run this function .TestString UINTN .QueryMode UINTN .SetMode UINTN .SetAttribute UINTN .ClearScreen UINTN .SetCursorPosition UINTN .EnableCursor UINTN .Mode UINTN end virtual ; Some initial format settings for the linker regarding ; the executable file format used by UEFI format pe dll efi entry main section '.text' code executable readable ; Program entry point main: push ebp ; get args (ImageHandle and SystemTable pointers) mov eax, [esp+8] mov [ImageHandle], eax mov ebx, [esp+12] mov [SystemTable], ebx ; Call OutputString function of SIMPLE_TEXT_OUTPUT protocol ; Function OutputString when entered, looks for two args in the stack: ; 1. The address of the zero-ended UCS2 string to print ; 2. The address of the Simple Text Output interface (aka *This in C language) ; so we 'push' them before calling the function and then ; restore the stack pointer (add esp,8 ) when the function returns ; 8 is the total size of our two args of type UINTN ; More info is in UEFI spec, page 474 (UEFI Specification Version 2.6) ; http://www.uefi.org/specifications ; Pay attention to the reversed order of the arguments pushed on stack lea eax, [Text] push eax ; This is out text address mov eax, [SystemTable] mov ebx, [eax+EFI_SYSTEM_TABLE.ConOut] push ebx ; push ConOut address and call one of its functions call [ebx+SIMPLE_TEXT_OUTPUT.OutputString] add esp, 8 ; restore stack pointer (UEFI uses C calling convention) ; so restoring stack pointer is caller's responsibility ; Exit program mov eax, EFI_SUCCESS pop ebp ret section '.data' data readable writeable ImageHandle dd ? SystemTable dd ? Text du 'Hello UEFI',13,10,0 ; 13 and 10 are Line Feed and Form Feed characters section '.reloc' fixups data discardable To run the program, compile it with fasm and put your .EFI file somewhere on a FAT-32 partition. Then reboot and enter the boot menu of your PC. Either find your file on bootable media via 'Boot from file' option or select 'Internal EFI Shell' and use shell commands to run it. A quick rundown on shell commands: (to run a command or file just type it in command prompt and press enter) map - shows all partitions accessible for UEFI, formatted like 'fs0, fs1, etc'. fs0: - select partition (FileSystem) #0 (fs1:, fs2:, etc) dir - show contents of current directory cd dirname - changes directory yourfilename(.efi) - starts your .EFI file exit - exits Shell and goes back to your boot menu or whatever (implementation specific, I guess). CTRL+ALT+DEL also works unless your app "hung" the PC. Use "anykey" then That's all, report bugs, ask questions, see ya soon...
|
|||||||||||
04 Nov 2016, 07:07 |
|
MrFox 11 Nov 2016, 11:41
Hi again.
Today we'll continue exploring SIMPLE_TEXT_OUTPUT protocol and see what else we can do with it. Today's task is to print a colored line of text in the center of the screeen. To do this, we'll have to get the screen resolution (in characters) and put the cursor to Height/2 and (Width-LenOfString)/2. Then, we'll set up the colors and finally print the text. Here's the code: Code: ; ; Center.asm ; Center colored string in UEFI in assembly ; Flat Assembler v1.71.54 ; 2016 MrFox ; ; Symbols and structures ; The UEFI favorite data type: Unsigned Integer Native width ; (32-bit width in 32-bit systems, 64-bit in 64-bit systems) ; I use 32-bit width because my EFI is 32-bit (rd) ; Data alignment must be same as width ; (all UEFI data stuff must be native aligned) struc UINTN { align 4 . rd 1 } ; Error codes EFI_SUCCESS = 0 EFIERR = 0x80000000 EFI_LOAD_ERROR = EFIERR or 1 EFI_INVALID_PARAMETER = EFIERR or 2 EFI_UNSUPPORTED = EFIERR or 3 ; Etc (more error codes in EFI spec) ; Console Colors EFI_RED = 0x04 EFI_YELLOW = 0x0E EFI_BACKGROUND_BLUE = 0x10 EFI_BACKGROUND_GREEN = 0x20 EFI_BACKGROUND_RED = 0x40 ; more colors in the Specification ; SystemTable structure virtual at 0 EFI_SYSTEM_TABLE: ; Table header .Signature rq 1 .Revision UINTN .HeaderSize UINTN .CRC32 UINTN .Reserved UINTN ; Rest of the table .FirmwareVendor UINTN .FirmwareRevision UINTN .ConsoleInHandle UINTN .ConIn UINTN .ConsoleOutHandle UINTN .ConOut UINTN ; We need this one to handle screen output .StandardErrorHandle UINTN .StdErr UINTN .RuntimeServices UINTN .BootServices UINTN .NumberOfTableEntries UINTN .ConfigurationTable UINTN end virtual ; Simple Text Output is a Protocol (like just a set of functions). ; The ConOut pointer in SystemTable (above) points to the memory address ; where the table described just below is located. ; The table itself contains memory addresses to 'call' ; if we want to use a specific UIFI function virtual at 0 SIMPLE_TEXT_OUTPUT: .Reset UINTN .OutputString UINTN ; Calling this address will run this function .TestString UINTN .QueryMode UINTN .SetMode UINTN .SetAttribute UINTN .ClearScreen UINTN .SetCursorPosition UINTN .EnableCursor UINTN .Mode UINTN end virtual ; This structure is used to get Viewport mode (GetMode function) virtual at 0 SIMPLE_TEXT_OUTPUT_MODE: .MaxMode UINTN .Mode UINTN .Attribute UINTN .CursorColumn UINTN .CursorRow UINTN .CursorVisible rb 1 end virtual ; Some initial format settings for the linker regarding ; the executable file format used by UEFI format pe dll efi entry main section '.text' code executable readable ; Program entry point main: push ebp ; 1. Get arguments that UEFI passed to my program ; 1.1. Get ImageHandle mov eax, [esp+8] mov [ImageHandle], eax ; 1.2. Get SystemTable mov ebx, [esp+12] mov [SystemTable], ebx ; 2. Get screen width and height ; 2.1. Get where ConOut protocol is located mov ebx, [SystemTable] mov ebp, [ebx+EFI_SYSTEM_TABLE.ConOut] ; 2.2. Get Console viewport width and height ; 2.2.1. Get CurrentScreenMode structure location mov eax, [ebp+SIMPLE_TEXT_OUTPUT.Mode] ; 2.2.2. Get Mode Number into ECX mov ecx, [eax+SIMPLE_TEXT_OUTPUT_MODE.Mode] ; 2.2.3. Load variables to receive data lea eax, [ScreenHeight] lea ebx, [ScreenWidth] ; 2.2.4. Send arguments to function push eax ; Height push ebx ; Width push ecx ; Mode number push ebp ; *This call [ebp+SIMPLE_TEXT_OUTPUT.QueryMode] add esp, 16 ; Clean the stack ; 3. Clear screen (to current colors, which are white on black I think) push ebp call [ebp+SIMPLE_TEXT_OUTPUT.ClearScreen] add esp,4 ; 4. Set screen Background and Foreground mov eax,EFI_YELLOW or EFI_BACKGROUND_BLUE push eax push ebp call [ebp+SIMPLE_TEXT_OUTPUT.SetAttribute] add esp,8 ; 5. Set Cursor Position to center ; 5.1. Some math first mov edx,[ScreenHeight] shr edx,1 ; Division by two mov eax,[ScreenWidth] sub eax,10 ; Length of the string shr eax,1 ; Division by two ; 5.2. Sending the coordinates to put the cursor push edx ; Row push eax ; Column push ebp ; *This call [ebp+SIMPLE_TEXT_OUTPUT.SetCursorPosition] add esp,12 ; 6. Now it's time to print the text lea eax, [Text] push eax ; This is our text address push ebp call [ebp+SIMPLE_TEXT_OUTPUT.OutputString] add esp, 8 ; restore stack pointer (UEFI uses C calling convention) ; 7. Set the coordinates back to 0,0 pushd 0 ; Row pushd 0 ; Column push ebp ; *This call [ebp+SIMPLE_TEXT_OUTPUT.SetCursorPosition] add esp,12 ; 8. Set the colors to RED on BLACK pushd EFI_RED push ebp call [ebp+SIMPLE_TEXT_OUTPUT.SetAttribute] add esp,8 ; 8. Exit program mov eax, EFI_SUCCESS pop ebp ret section '.data' data readable writeable ImageHandle dd ? SystemTable dd ? ScreenWidth dd 0 ScreenHeight dd 0 Text du 'Hello UEFI',0 section '.reloc' fixups data discardable
|
|||||||||||
11 Nov 2016, 11:41 |
|
ford 15 Nov 2016, 03:41
I like it. Keep it coming
|
|||
15 Nov 2016, 03:41 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.