6 ;; [TODO] We need to provide the following:
7 ;; - [X] Print a string of a given length
8 ;; - [ ] Print a single character
9 ;; - [ ] Terminate the program (? - What should this do?)
10 ;; - [X] Read a single character
11 ;; - This should allow the user to type in a string, and then feed the
12 ;; buffer to us one character at a time.
13 ;; - [ ] We want to show the user's input on the screen while reading
14 ;; - [ ] Read a file that was bundled with the program
15 ;; - It looks like we can use EFI_LOAD_FILE_PROTOCOL.LoadFile() to load
16 ;; a file into a buffer. In order to be able to use this, we need to
17 ;; have some way of interpreting a static buffer instead of reading as
20 ;; EFI struct definitions {{{
22 EFI_NOT_READY = 0x8000_0000_0000_0000 or 6
24 ;; Based on https://wiki.osdev.org/Uefi.inc
31 struc EFI_TABLE_HEADER {
39 struc EFI_SYSTEM_TABLE {
41 .FirmwareVendor dq ? ; CHAR16*
42 .FirmwareRevision dd ? ; UINT32
44 .ConsoleInHandle dq ? ; EFI_HANDLE
45 .ConIn dq ? ; EFI_SIMPLE_TEXT_INPUT_PROTOCOL*
46 .ConsoleOutHandle dq ? ; EFI_HANDLE
47 .ConOut dq ? ; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL*
50 struct EFI_SYSTEM_TABLE
52 struc EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL {
53 .Reset dq ? ; EFI_TEXT_RESET
54 .OutputString dq ? ; EFI_TEXT_STRING
57 struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
59 struc EFI_SIMPLE_TEXT_INPUT_PROTOCOL {
60 .Reset dq ? ; EFI_INPUT_RESET
61 .ReadKeyStroke dq ? ; EFI_INPUT_READ_KEY
64 struct EFI_SIMPLE_TEXT_INPUT_PROTOCOL
67 .ScanCode dw ? ; UINT16
68 .UnicodeChar dw ? ; CHAR16
75 section '.text' code executable readable
78 ; At program startup, RDX contains an EFI_SYSTEM_TABLE*.
79 mov [system_table], rdx
82 mov rdx, hello_string.len
93 mov rdx, hello_string.len
98 ;; Print a string of the given length.
101 ;; - RCX = String buffer
102 ;; - RDX = String length
110 ; We take an input string of bytes without any terminator. We need to turn
111 ; this string into a string of words, terminated by a null character.
118 mov al, byte [r8 + rsi]
119 lea rdx, [.output_buffer + rcx]
124 lea rdx, [.output_buffer + rcx]
130 lea rdx, [.output_buffer + r10]
133 ; At this point we have our null-terminated word-string at .output_buffer. Now
134 ; we just need to print it.
136 mov rcx, [system_table] ; EFI_SYSTEM_TABLE* rcx
137 mov rcx, [rcx + EFI_SYSTEM_TABLE.ConOut] ; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL* rcx
138 mov rdx, .output_buffer
139 mov rbx, [rcx + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString] ; EFI_TEXT_STRING rbx
145 ;; Read a character as an ASCII byte into the given buffer.
148 ;; - RCX = Character buffer (1 byte)
152 mov rcx, [system_table] ; EFI_SYSTEM_TABLE* rcx
153 mov rcx, [rcx + EFI_SYSTEM_TABLE.ConIn] ; EFI_SIMPLE_TEXT_INPUT_PROTOCOL* rcx
154 mov rbx, [rcx + EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke] ; EFI_INPUT_READ_KEY rbx
155 mov rdx, input_key ; EFI_INPUT_KEY* rdx
160 mov r8, EFI_NOT_READY
164 mov ax, [input_key.UnicodeChar]
169 section '.data' readable writable
171 system_table dq ? ; EFI_SYSTEM_TABLE*
173 hello_string db 'Hello, world!', 0xD, 0xA, 'Here is some more text.', 0xD, 0xA
174 .len = $ - hello_string
176 print_string.output_buffer rq 0x400
180 input_key EFI_INPUT_KEY