4 ;; EFI struct definitions {{{
6 EFI_NOT_READY = 0x8000_0000_0000_0000 or 6
8 ;; Based on https://wiki.osdev.org/Uefi.inc
15 struc EFI_TABLE_HEADER {
23 struc EFI_SYSTEM_TABLE {
25 .FirmwareVendor dq ? ; CHAR16*
26 .FirmwareRevision dd ? ; UINT32
28 .ConsoleInHandle dq ? ; EFI_HANDLE
29 .ConIn dq ? ; EFI_SIMPLE_TEXT_INPUT_PROTOCOL*
30 .ConsoleOutHandle dq ? ; EFI_HANDLE
31 .ConOut dq ? ; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL*
32 .StandardErroHandle dq ? ; EFI_HANDLE
33 .StdErr dq ? ; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL*
34 .RuntimeServices dq ? ; EFI_RUNTIME_SERVICES*
35 .BootServices dq ? ; EFI_BOOT_SERVICES*
36 .NumberOfTableEntries dq ? ; UINTN (native width!!)
37 .ConfigurationTable dq ? ; EFI_CONFIGURATION_TABLE*
39 struct EFI_SYSTEM_TABLE
41 struc EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL {
42 .Reset dq ? ; EFI_TEXT_RESET
43 .OutputString dq ? ; EFI_TEXT_STRING
46 struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
48 struc EFI_SIMPLE_TEXT_INPUT_PROTOCOL {
49 .Reset dq ? ; EFI_INPUT_RESET
50 .ReadKeyStroke dq ? ; EFI_INPUT_READ_KEY
53 struct EFI_SIMPLE_TEXT_INPUT_PROTOCOL
56 .ScanCode dw ? ; UINT16
57 .UnicodeChar dw ? ; CHAR16
64 section '.text' code executable readable
67 ; At program startup, RDX contains an EFI_SYSTEM_TABLE*.
68 mov [system_table], rdx
72 ;; We take an input string of bytes without any terminator. We need
73 ;; to turn this string into a string of words, terminated by a null
76 mov rdi, .output_buffer ; Current location in output string
79 ;; When there are no characters left in the input string, we are
84 ;; Load byte from input string
87 ;; Copy byte to output string
92 ;; It's a newline; replace it with '\r\n' in output string.
104 ;; Not a newline, proceed as normal:
108 ;; The output string has words rather than bytes for charactesr, so
109 ;; we need to add an extra zero:
114 ;; We finished copying character to output string, so pop it from
121 ;; Append a final null-word:
124 ; At this point we have our null-terminated word-string at
125 ; .output_buffer. Now we just need to print it.
127 mov rcx, [system_table] ; EFI_SYSTEM_TABLE* rcx
128 mov rcx, [rcx + EFI_SYSTEM_TABLE.ConOut]
129 ; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL* rcx
130 mov rdx, .output_buffer
131 mov rbx, [rcx + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString]
132 ; EFI_TEXT_STRING rbx
140 mov rcx, [system_table] ; EFI_SYSTEM_TABLE* rcx
141 mov rcx, [rcx + EFI_SYSTEM_TABLE.ConIn]
142 ; EFI_SIMPLE_TEXT_INPUT_PROTOCOL* rcx
143 mov rbx, [rcx + EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke]
144 ; EFI_INPUT_READ_KEY rbx
145 mov rdx, input_key ; EFI_INPUT_KEY* rdx
150 mov r8, EFI_NOT_READY
154 movzx rax, word [input_key.UnicodeChar]
156 ;; Special handling of enter (UEFI gives us '\r', but we want '\n'.)
163 ;; Print the character
164 mov [char_buffer], al
172 ;; Terminate with the given error code.
175 ;; - RCX = Error code
177 mov rcx, terminated_msg
178 mov rdx, terminated_msg.len
182 section '.data' readable writable
184 system_table dq ? ; EFI_SYSTEM_TABLE*
186 terminated_msg db 0xD, 0xA, '(The program has terminated.)', 0xD, 0xA
187 .len = $ - terminated_msg
189 os_print_string.output_buffer rq 0x400
193 input_key EFI_INPUT_KEY