flat assembler
Message board for the users of flat assembler.

Index > Tutorials and Examples > UEFI basics tutorial by MrFox

Author
Thread Post new topic Reply to topic
MrFox



Joined: 17 Aug 2016
Posts: 52
Location: Russia
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 Wink

That's all, report bugs, ask questions, see ya soon...


Description: Hello World in UEFI
Download
Filename: Hello.asm
Filesize: 3.79 KB
Downloaded: 911 Time(s)

Post 04 Nov 2016, 07:07
View user's profile Send private message Reply with quote
MrFox



Joined: 17 Aug 2016
Posts: 52
Location: Russia
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
    


Description: Prints colored line of text in the center of the screen
Download
Filename: Center.asm
Filesize: 4.74 KB
Downloaded: 996 Time(s)

Post 11 Nov 2016, 11:41
View user's profile Send private message Reply with quote
ford



Joined: 21 Jan 2010
Posts: 118
Location: Absurdistan
ford 15 Nov 2016, 03:41
I like it. Keep it coming Smile
Post 15 Nov 2016, 03:41
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.