6 ;; EFI struct definitions {{{
8 EFI_NOT_READY = 0x8000_0000_0000_0000 or 6
10 ;; Based on https://wiki.osdev.org/Uefi.inc
17 struc EFI_TABLE_HEADER {
25 struc EFI_SYSTEM_TABLE {
27 .FirmwareVendor dq ? ; CHAR16*
28 .FirmwareRevision dd ? ; UINT32
30 .ConsoleInHandle dq ? ; EFI_HANDLE
31 .ConIn dq ? ; EFI_SIMPLE_TEXT_INPUT_PROTOCOL*
32 .ConsoleOutHandle dq ? ; EFI_HANDLE
33 .ConOut dq ? ; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL*
36 struct EFI_SYSTEM_TABLE
38 struc EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL {
39 .Reset dq ? ; EFI_TEXT_RESET
40 .OutputString dq ? ; EFI_TEXT_STRING
43 struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
45 struc EFI_SIMPLE_TEXT_INPUT_PROTOCOL {
46 .Reset dq ? ; EFI_INPUT_RESET
47 .ReadKeyStroke dq ? ; EFI_INPUT_READ_KEY
50 struct EFI_SIMPLE_TEXT_INPUT_PROTOCOL
53 .ScanCode dw ? ; UINT16
54 .UnicodeChar dw ? ; CHAR16
61 macro os_code_section {
62 section '.text' code readable executable
65 macro os_data_section {
66 section '.data' readable writable
69 section '.text' code executable readable
72 ; At program startup, RDX contains an EFI_SYSTEM_TABLE*.
73 mov [system_table], rdx
77 ;; We take an input string of bytes without any terminator. We need to turn
78 ;; this string into a string of words, terminated by a null character.
80 mov rdi, .output_buffer ; Current location in output string
83 ;; When there are no characters left in the input string, we are done.
87 ;; Load byte from input string
90 ;; Copy byte to output string
95 ;; It's a newline; replace it with '\r\n' in output string.
107 ;; Not a newline, proceed as normal:
111 ;; The output string has words rather than bytes for charactesr, so we need
112 ;; to add an extra zero:
117 ;; We finished copying character to output string, so pop it from the input
124 ;; Append a final null-word:
127 ; At this point we have our null-terminated word-string at .output_buffer. Now
128 ; we just need to print it.
130 mov rcx, [system_table] ; EFI_SYSTEM_TABLE* rcx
131 mov rcx, [rcx + EFI_SYSTEM_TABLE.ConOut] ; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL* rcx
132 mov rdx, .output_buffer
133 mov rbx, [rcx + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString] ; EFI_TEXT_STRING rbx
141 mov rcx, [system_table] ; EFI_SYSTEM_TABLE* rcx
142 mov rcx, [rcx + EFI_SYSTEM_TABLE.ConIn] ; EFI_SIMPLE_TEXT_INPUT_PROTOCOL* rcx
143 mov rbx, [rcx + EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke] ; EFI_INPUT_READ_KEY rbx
144 mov rdx, input_key ; EFI_INPUT_KEY* rdx
149 mov r8, EFI_NOT_READY
153 movzx rax, word [input_key.UnicodeChar]
155 ;; Special handling of enter (UEFI gives us '\r', but we want '\n'.)
162 ;; Print the character
163 mov [char_buffer], al
171 ;; Terminate with the given error code.
174 ;; - RCX = Error code
176 mov rcx, terminated_msg
177 mov rdx, terminated_msg.len
181 section '.data' readable writable
183 system_table dq ? ; EFI_SYSTEM_TABLE*
185 terminated_msg db 0xD, 0xA, '(The program has terminated.)', 0xD, 0xA
186 .len = $ - terminated_msg
188 os_print_string.output_buffer rq 0x400
192 input_key EFI_INPUT_KEY