summaryrefslogtreecommitdiffstats
path: root/documentation/UEFI general/UEFI Programming with FASM
blob: 472b757a61a5b22e9aceea0bebf69e8afc1829f3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
UEFI Programming with FASM

As an extra, I will also demonstrate same Hello World example in assembly (using FASM, that currently has experimental UEFI support since version 1.67.28):

First we need some to create simple UEFI headers (efi.inc):

;for 32/64 portability and automatic natural align in structure definitions

struc int8 {
  . db ?
}
struc int16 {
  align 2
  . dw ?
}
struc int32 {
  align 4
  . dd ?
}
struc int64 {
  align 8
  . dq ?
}
struc intn {
  align 8
  . dq ?
}
struc dptr {
  align 8
  . dq ?
}

;symbols

EFIERR = 0x8000000000000000
EFI_SUCCESS			= 0
EFI_LOAD_ERROR			= EFIERR or 1
EFI_INVALID_PARAMETER		= EFIERR or 2
EFI_UNSUPPORTED 		= EFIERR or 3
EFI_BAD_BUFFER_SIZE		= EFIERR or 4
EFI_BUFFER_TOO_SMALL		= EFIERR or 5
EFI_NOT_READY			= EFIERR or 6
EFI_DEVICE_ERROR		= EFIERR or 7
EFI_WRITE_PROTECTED		= EFIERR or 8
EFI_OUT_OF_RESOURCES		= EFIERR or 9
EFI_VOLUME_CORRUPTED		= EFIERR or 10
EFI_VOLUME_FULL 		= EFIERR or 11
EFI_NO_MEDIA			= EFIERR or 12
EFI_MEDIA_CHANGED		= EFIERR or 13
EFI_NOT_FOUND			= EFIERR or 14
EFI_ACCESS_DENIED		= EFIERR or 15
EFI_NO_RESPONSE 		= EFIERR or 16
EFI_NO_MAPPING			= EFIERR or 17
EFI_TIMEOUT			= EFIERR or 18
EFI_NOT_STARTED 		= EFIERR or 19
EFI_ALREADY_STARTED		= EFIERR or 20
EFI_ABORTED			= EFIERR or 21
EFI_ICMP_ERROR			= EFIERR or 22
EFI_TFTP_ERROR			= EFIERR or 23
EFI_PROTOCOL_ERROR		= EFIERR or 24

;helper macro for definition of relative structure member offsets

macro struct name
{
  virtual at 0
    name name
  end virtual
}

;structures

struc EFI_TABLE_HEADER {
 .Signature    int64
 .Revision     int32
 .HeaderSize   int32
 .CRC32        int32
 .Reserved     int32
}
struct EFI_TABLE_HEADER

struc EFI_SYSTEM_TABLE {
 .Hdr		       EFI_TABLE_HEADER
 .FirmwareVendor       dptr
 .FirmwareRevision     int32
 .ConsoleInHandle      dptr
 .ConIn 	       dptr
 .ConsoleOutHandle     dptr
 .ConOut	       dptr
 .StandardErrorHandle  dptr
 .StdErr	       dptr
 .RuntimeServices      dptr
 .BootServices	       dptr
 .NumberOfTableEntries intn
 .ConfigurationTable   dptr
}
struct EFI_SYSTEM_TABLE

struc SIMPLE_TEXT_OUTPUT_INTERFACE {
 .Reset 	    dptr
 .OutputString	    dptr
 .TestString	    dptr
 .QueryMode	    dptr
 .SetMode	    dptr
 .SetAttribute	    dptr
 .ClearScreen	    dptr
 .SetCursorPosition dptr
 .EnableCursor	    dptr
 .Mode		    dptr
}
struct SIMPLE_TEXT_OUTPUT_INTERFACE

And here is the assembly code itself (hello.asm):

format pe64 dll efi
entry main

section '.text' code executable readable

include 'efi.inc'

main:
 sub rsp, 4*8              ; reserve space for 4 arguments

 mov [Handle], rcx         ; ImageHandle
 mov [SystemTable], rdx    ; pointer to SystemTable

 lea rdx, [_hello]
 mov rcx, [SystemTable]
 mov rcx, [rcx + EFI_SYSTEM_TABLE.ConOut]
 call [rcx + SIMPLE_TEXT_OUTPUT_INTERFACE.OutputString]

 add rsp, 4*8
 mov eax, EFI_SUCCESS
 retn


section '.data' data readable writeable

Handle      dq ?
SystemTable dq ?
_hello      du 'Hello World',13,10,'(From EFI app written in FASM)',13,10,0

section '.reloc' fixups data discardable

Compile and link it with fasm.exe hello_world.asm.