kolibrios/kernel/trunk/bootloader/uefi4kos/uefi64kos.asm
Ivan Baravy e44770ac18 uefi64kos: Fix stack alignment on function calls.
It is a formal requirement of UEFI spec that the stack is to be aligned
on 16 bytes on all calls to service routines. I changed eficall macro to
fstcall one in my previous commit. Due to differences in macro logic
that change broke UEFI boot on some platforms that do care about stack
alignment. This commit should fix the issue.

git-svn-id: svn://kolibrios.org@9253 a494cfbc-eb01-0410-851d-a64ba20cac60
2021-11-05 02:17:31 +00:00

1181 lines
37 KiB
NASM

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2020-2021. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; Version 2, or (at your option) any later version. ;;
;; ;;
;; Written by Ivan Baravy ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
format pe64 efi
entry main
section '.text' code executable readable
include '../../struct.inc'
include '../../macros.inc'
include '../../kglobals.inc'
fastcall fix fstcall
include 'proc64.inc'
include '../../const.inc'
purge DQ
include 'uefi64.inc'
MEMORY_MAP_SIZE = 0x10000
PROTOCOL_HANDLERS_BUFFER_SIZE = 0x100
FILE_BUFFER_SIZE = 0x1000
KERNEL_TRAMPOLINE = 0x8f80 ; just before BOOT_LO
KERNEL_BASE = 0x10000
RAMDISK_BASE = 0x100000
MAX_FILE_SIZE = 0x10000000
CODE_32_SELECTOR = 8
DATA_32_SELECTOR = 16
CODE_64_SELECTOR = 24
; linux/arch/x86/include/uapi/asm/e820.h
E820_RAM = 1
E820_RESERVED = 2
E820_ACPI = 3
E820_NVS = 4
E820_UNUSABLE = 5
E820_PMEM = 7
proc load_file _root, _name, _buffer, _size, _fatal
locals
.status dq ?
endl
mov [_root], rcx
mov [_name], rdx
mov [_buffer], r8
mov [_size], r9
mov r10, [_root]
mov r11, [_name]
fstcall [r10+EFI_FILE_PROTOCOL.Open], r10, file_handle, \
r11, EFI_FILE_MODE_READ, 0
test eax, eax
jz @f
xor eax, eax
cmp [_fatal], 1
jnz .done
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_error_open_file
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
mov rdx, [_name]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, [_name]
jmp $
@@:
lea rdx, [_size]
mov r8, [_buffer]
mov r10, [file_handle]
fstcall [r10+EFI_FILE_PROTOCOL.Read], [file_handle], rdx, r8
mov r10, [file_handle]
fstcall [r10+EFI_FILE_PROTOCOL.Close], [file_handle]
mov rax, [_size]
.done:
mov [.status], rax
call clearbuf
mov rdi, msg
call num2dec
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_file_size
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, msg
mov rax, [.status]
ret
endp
skip_whitespace:
.next_char:
cmp byte[rsi], 0
jz .done
cmp byte[rsi], 0x20 ; ' '
jz .whitespace
cmp byte[rsi], 9 ; '\t'
jz .whitespace
jmp .done
.whitespace:
inc rsi
jmp .next_char
.done:
ret
skip_until_newline:
.next_char:
cmp byte[rsi], 0
jz .done
cmp byte[rsi], 0xd ; '\r'
jz .done
cmp byte[rsi], 0xa ; '\n'
jz .done
inc rsi
jmp .next_char
.done:
ret
skip_newline:
.next_char:
cmp byte[rsi], 0xd ; '\r'
jz .newline
cmp byte[rsi], 0xa ; '\n'
jz .newline
jmp .done
.newline:
inc rsi
jmp .next_char
.done:
ret
skip_line:
call skip_until_newline
call skip_newline
ret
dec2bin:
mov edx, 0
.next_char:
movzx eax, byte[rsi]
test eax, eax
jz .done
sub eax, '0'
jb .done
cmp eax, 9
ja .done
inc rsi
imul edx, 10
add edx, eax
jmp .next_char
.done:
mov eax, edx
ret
parse_option:
mov rbx, config_options-3*8
.try_next_option:
add rbx, 3*8
mov rdi, rsi
mov rdx, [rbx] ; option name
test rdx, rdx
jz .done
.next_char:
cmp byte[rdx], 0
jnz @f
cmp byte[rdi], '='
jz .opt_name_ok
@@:
cmp byte[rdi], 0
jz .done
movzx eax, byte[rdi]
cmp [rdx], al
jnz .try_next_option
inc rdi
inc rdx
jmp .next_char
.opt_name_ok:
inc rdi
mov rsi, rdi
call qword[rbx+8]
.done:
ret
parse_line:
.next_line:
cmp byte[rsi], 0
jz .done
cmp byte[rsi], 0xd ; '\r'
jz .skip
cmp byte[rsi], 0xa ; '\n'
jz .skip
cmp byte[rsi], '#'
jz .skip
call parse_option
call skip_line
jmp .next_line
.skip:
call skip_line
jmp .next_line
.done:
ret
cfg_opt_func_resolution:
call dec2bin
xor edx, edx
mov [rdx+BOOT_LO.x_res], ax
cmp byte[rsi], 'x'
jz @f
cmp byte[rsi], '*'
jz @f
jmp .done
@@:
inc rsi
call dec2bin
xor edx, edx
mov [rdx+BOOT_LO.y_res], ax
mov [cfg_opt_used_resolution], 1
.done:
ret
cfg_opt_func_acpi:
call dec2bin
mov [cfg_opt_used_acpi], 1
mov [cfg_opt_value_acpi], al
ret
cfg_opt_func_debug_print:
call dec2bin
mov [cfg_opt_used_debug_print], 1
mov [cfg_opt_value_debug_print], al
ret
cfg_opt_func_launcher_start:
call dec2bin
mov [cfg_opt_used_launcher_start], 1
mov [cfg_opt_value_launcher_start], al
ret
cfg_opt_func_mtrr:
call dec2bin
mov [cfg_opt_used_mtrr], 1
mov [cfg_opt_value_mtrr], al
ret
cfg_opt_func_ask_params:
call dec2bin
mov [cfg_opt_used_ask_params], 1
mov [cfg_opt_value_ask_params], al
ret
cfg_opt_func_imgfrom:
call dec2bin
mov [cfg_opt_used_imgfrom], 1
mov [cfg_opt_value_imgfrom], al
ret
cfg_opt_func_syspath:
mov rdi, cfg_opt_value_syspath
.next_char:
movzx eax, byte[rsi]
cmp al, 0xd ; \r
jz .done
cmp al, 0xa ; \n
jz .done
inc rsi
stosb
jmp .next_char
.done:
mov byte[rdi], 0
ret
proc parse_config uses rbx rsi rdi, _buffer
mov rsi, rcx
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_parsing_config
.next_line:
call parse_line
cmp byte[rsi], 0
jnz .next_line
ret
endp
proc read_options_from_config
mov r10, [rbx+EFI_SYSTEM_TABLE.BootServices]
fstcall [r10+EFI_BOOT_SERVICES.HandleProtocol], [efi_handle], \
lip_guid, lip_interface
test eax, eax
jz @f
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_error_efi_lip_handle
jmp $
@@:
mov r11, [lip_interface]
mov r10, [rbx+EFI_SYSTEM_TABLE.BootServices]
fstcall [r10+EFI_BOOT_SERVICES.HandleProtocol], \
[r11+EFI_LOADED_IMAGE_PROTOCOL.DeviceHandle], sfsp_guid, \
sfsp_interface
test eax, eax
jz @f
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_error_lip_dev_sfsp
jmp $
@@:
mov r10, [sfsp_interface]
fstcall [r10+EFI_SIMPLE_FILE_SYSTEM_PROTOCOL.OpenVolume], \
[sfsp_interface], esp_root
test eax, eax
jz @f
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_error_sfsp_openvolume
jmp $
@@:
fstcall load_file, [esp_root], file_name, KERNEL_BASE, \
FILE_BUFFER_SIZE, 0 ; not fatal
test eax, eax
jz @f
fstcall parse_config, KERNEL_BASE
@@:
.error:
ret
endp
proc print_vmode uses rax rbx rcx rdx rsi rdi
mov r10, rcx
call clearbuf
mov eax, [r10+EFI_GRAPHICS_OUTPUT_MODE_INFORMATION.HorizontalResolution]
mov rdi, msg
call num2dec
mov eax, [r10+EFI_GRAPHICS_OUTPUT_MODE_INFORMATION.VerticalResolution]
mov rdi, msg+8*2
call num2dec
mov eax, [r10+EFI_GRAPHICS_OUTPUT_MODE_INFORMATION.PixelFormat]
mov rdi, msg+16*2
call num2dec
mov eax, [r10+EFI_GRAPHICS_OUTPUT_MODE_INFORMATION.PixelsPerScanLine]
mov rdi, msg+24*2
call num2dec
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, msg
ret
endp
proc find_vmode_index_by_resolution
mov [cfg_opt_used_resolution], 1
mov [cfg_opt_value_vmode], 0
.next_mode:
movzx edx, [cfg_opt_value_vmode]
mov r10, [gop_interface]
fstcall [r10+EFI_GRAPHICS_OUTPUT_PROTOCOL.QueryMode], [gop_interface], \
rdx, gop_info_size, gop_info
cmp rax, EFI_SUCCESS
jnz .error
mov rcx, [gop_info]
fstcall print_vmode
; PixelBlueGreenRedReserved8BitPerColor
cmp [rcx+EFI_GRAPHICS_OUTPUT_MODE_INFORMATION.PixelFormat], 1
jnz .skip_mode
xor edx, edx
mov eax, [rcx+EFI_GRAPHICS_OUTPUT_MODE_INFORMATION.HorizontalResolution]
cmp ax, [rdx+BOOT_LO.x_res]
jnz .skip_mode
mov eax, [rcx+EFI_GRAPHICS_OUTPUT_MODE_INFORMATION.VerticalResolution]
cmp ax, [rdx+BOOT_LO.y_res]
jnz .skip_mode
jmp .done
.skip_mode:
inc [cfg_opt_value_vmode]
movzx eax, [cfg_opt_value_vmode]
mov rcx, [gop_interface]
mov rdx, [rcx+EFI_GRAPHICS_OUTPUT_PROTOCOL.Mode]
cmp eax, [rdx+EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE.MaxMode]
jnz .next_mode
mov [cfg_opt_used_resolution], 0
mov [cfg_opt_value_ask_params], 1
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_error_no_such_vmode
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_error
jmp $
.error:
.done:
ret
endp
ask_for_params:
jmp $
proc detect_pci_config
fstcall get_protocol_interface, pcirbiop_guid
mov [pcirbiop_interface], rax
mov r10, rax
fstcall [r10+EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.Configuration], r10, \
pcirbiop_resources
; fstcall dump_pci_resources
fstcall get_last_pci_bus
call clearbuf
movzx eax, [pci_last_bus]
mov rdi, msg
call num2hex
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_pci_last_bus
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, msg
ret
endp
proc get_last_pci_bus
mov rsi, [pcirbiop_resources]
.next_resource:
cmp [rsi+EFI_QWORD_ADDRESS_SPACE_DESCRIPTOR.Type], \
EFI_RESOURCE_DESCRIPTOR_TYPE.END_TAG
jz .not_found
mov rax, [rsi+EFI_QWORD_ADDRESS_SPACE_DESCRIPTOR.RangeMaximum]
cmp [rsi+EFI_QWORD_ADDRESS_SPACE_DESCRIPTOR.ResourceType], \
EFI_RESOURCE_TYPE.BUS
jz .found
movzx eax, [rsi+EFI_QWORD_ADDRESS_SPACE_DESCRIPTOR.Length]
lea rsi, [rsi+rax+3]
jmp .next_resource
.found:
mov [pci_last_bus], al
.not_found:
ret
endp
proc main _efi_handle, _efi_table
mov [efi_handle], rcx
mov [efi_table], rdx
mov rbx, rdx
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.Reset], rcx, 1
test eax, eax
jnz $ ; what can I do here?
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_u4k_loaded
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_detect_pci_config
fstcall detect_pci_config
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_read_options
fstcall read_options_from_config
; read kernel file
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_load_kernel
fstcall load_file, [esp_root], kernel_name, KERNEL_BASE, \
MAX_FILE_SIZE, 1 ; fatal
; read ramdisk image
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_load_ramdisk
fstcall load_file, [esp_root], ramdisk_name, RAMDISK_BASE, \
MAX_FILE_SIZE, 1 ; fatal
; alloc buffer for devices.dat
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_alloc_devicesdat
mov r10, [rbx+EFI_SYSTEM_TABLE.BootServices]
fstcall [r10+EFI_BOOT_SERVICES.AllocatePages], \
EFI_ALLOCATE_MAX_ADDRESS, EFI_RESERVED_MEMORY_TYPE, 1, \
devicesdat_data
cmp eax, EFI_SUCCESS
jnz .error
; read devices.dat
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_load_devicesdat
fstcall load_file, [esp_root], devicesdat_name, [devicesdat_data], \
[devicesdat_size], 0 ; not fatal
mov [devicesdat_size], rax
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_locate_gop_interface
fstcall get_protocol_interface, gop_guid
mov [gop_interface], rax
fstcall find_rsdp
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_acpi_tables_done
cmp [cfg_opt_used_resolution], 0
jz .not_used_resolution
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_opt_resolution
call clearbuf
xor edx, edx
movzx eax, [rdx+BOOT_LO.x_res]
mov rdi, msg
call num2dec
xor edx, edx
movzx eax, [rdx+BOOT_LO.y_res]
mov rdi, msg+8*2
call num2dec
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, msg
fstcall find_vmode_index_by_resolution
.not_used_resolution:
cmp [cfg_opt_used_debug_print], 0
jz .not_used_debug_print
movzx eax, [cfg_opt_value_debug_print]
xor edx, edx
mov [rdx+BOOT_LO.debug_print], al
.not_used_debug_print:
cmp [cfg_opt_value_ask_params], 0
jz @f
call ask_for_params
@@:
movzx edx, [cfg_opt_value_vmode]
mov r10, [gop_interface]
fstcall [r10+EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode], [gop_interface], rdx
test eax, eax
jz @f
call clearbuf
mov rdi, msg
call num2hex
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, msg
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_error
jmp $
@@:
mov rcx, [gop_interface]
mov rdx, [rcx+EFI_GRAPHICS_OUTPUT_PROTOCOL.Mode]
mov rdi, [rdx+EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE.FrameBufferBase]
mov [fb_base], rdi
mov edx, [rdx+EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE.Mode]
mov r10, [gop_interface]
fstcall [r10+EFI_GRAPHICS_OUTPUT_PROTOCOL.QueryMode], [gop_interface], \
rdx, gop_info_size, gop_info
test eax, eax
jz @f
jmp .error
@@:
mov rcx, [gop_info]
mov eax, [rcx+EFI_GRAPHICS_OUTPUT_MODE_INFORMATION.HorizontalResolution]
xor rdx, rdx
mov [rdx+BOOT_LO.x_res], ax
mov eax, [rcx+EFI_GRAPHICS_OUTPUT_MODE_INFORMATION.VerticalResolution]
mov [rdx+BOOT_LO.y_res], ax
mov eax, [rcx+EFI_GRAPHICS_OUTPUT_MODE_INFORMATION.PixelsPerScanLine]
shl eax, 2
mov [rdx+BOOT_LO.pitch], ax
mov [rdx+BOOT_LO.pci_data.access_mechanism], 1
movzx eax, [pci_last_bus]
mov [rdx+BOOT_LO.pci_data.last_bus], al
mov [rdx+BOOT_LO.pci_data.version], 0x0300 ; PCI 3.0
mov [rdx+BOOT_LO.pci_data.pm_entry], 0
; kernel
; fstcall BootServices, AllocatePages, EFI_RESERVED_MEMORY_TYPE, \
; 450000/0x1000, EFI_ALLOCATE_ADDRESS
; ramdisk
; fstcall BootServices, AllocatePages, EFI_RESERVED_MEMORY_TYPE, \
; 2880*512/0x1000, EFI_ALLOCATE_ADDRESS
fstcall calc_memmap
; fstcall dump_memmap
mov r10, [rbx+EFI_SYSTEM_TABLE.BootServices]
fstcall [r10+EFI_BOOT_SERVICES.ExitBootServices], [efi_handle], \
[memory_map_key]
fstcall halt_on_error
cli
xor edx, edx
xor esi, esi
mov [rsi+BOOT_LO.bpp], 32
mov [rsi+BOOT_LO.vesa_mode], dx
mov [rsi+BOOT_LO.bank_switch], edx
mov rdi, [fb_base]
mov [rsi+BOOT_LO.lfb], edi
movzx eax, [cfg_opt_value_mtrr]
mov [rsi+BOOT_LO.mtrr], al
movzx eax, [cfg_opt_value_launcher_start]
mov [rsi+BOOT_LO.launcher_start], al
movzx eax, [cfg_opt_value_debug_print]
mov [rsi+BOOT_LO.debug_print], al
mov [rsi+BOOT_LO.dma], dl
mov [rsi+BOOT_LO.apm_entry], edx
mov [rsi+BOOT_LO.apm_version], dx
mov [rsi+BOOT_LO.apm_flags], dx
mov [rsi+BOOT_LO.apm_code_32], dx
mov [rsi+BOOT_LO.apm_code_16], dx
mov [rsi+BOOT_LO.apm_data_16], dx
mov [rsi+BOOT_LO.bios_hd_cnt], dl
movzx eax, [cfg_opt_value_imgfrom]
mov [rsi+BOOT_LO.rd_load_from], al
mov eax, dword[devicesdat_size]
mov [rdx+BOOT_LO.devicesdat_size], eax
mov eax, dword[devicesdat_data]
mov [rdx+BOOT_LO.devicesdat_data], eax
mov rsi, cfg_opt_value_syspath
mov rdi, BOOT_LO.syspath
mov ecx, 0x17
rep movsb
; kernel trampoline
mov rsi, kernel_trampoline
mov rdi, KERNEL_TRAMPOLINE
mov ecx, kernel_trampoline.size
rep movsb
mov rax, GDTR
lgdt [cs:rax]
mov ax, DATA_32_SELECTOR
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
push CODE_32_SELECTOR
mov rax, KERNEL_TRAMPOLINE
push rax
retf
.error:
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_error
jmp $
endp
proc halt_on_error
test eax, eax
jz @f
call clearbuf
mov rdi, msg
call num2hex
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_error
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, msg
jmp $
@@:
ret
endp
proc get_protocol_interface uses rsi rdi, _guid
locals
.status dq ?
endl
mov [_guid], rcx
mov [prot_handlers_buffer_size], PROTOCOL_HANDLERS_BUFFER_SIZE
mov r10, [rbx+EFI_SYSTEM_TABLE.BootServices]
fstcall [r10+EFI_BOOT_SERVICES.LocateHandle], \
EFI_LOCATE_SEARCH_TYPE.ByProtocol, [_guid], 0, \
prot_handlers_buffer_size, prot_handlers_buffer
mov [.status], rax
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_protocol_buffer_size
call clearbuf
mov rax, [prot_handlers_buffer_size]
mov rdi, msg
call num2hex
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, msg
mov rax, [.status]
test eax, eax
jz @f
call clearbuf
mov rdi, msg
call num2hex
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_error
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, msg
jmp $
@@:
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_look_for_handler
mov rsi, prot_handlers_buffer
.try_next_handle:
mov rax, rsi
mov rcx, prot_handlers_buffer
sub rax, rcx
cmp rax, [prot_handlers_buffer_size]
jb @f
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_error_out_of_handlers
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_error
jmp $
@@:
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_query_handler
mov r10, [rbx+EFI_SYSTEM_TABLE.BootServices]
fstcall [r10+EFI_BOOT_SERVICES.HandleProtocol], qword[rsi], [_guid], \
prot_interface
;mov rax, 0x8000_0000_0000_0003
test eax, eax
jz @f
call clearbuf
mov rdi, msg
call num2hex
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, msg
add rsi, 8
jmp .try_next_handle
@@:
mov rax, [prot_interface]
ret
endp
proc find_rsdp uses rsi rdi
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_look_for_rsdp
mov rdi, [rbx+EFI_SYSTEM_TABLE.ConfigurationTable]
mov rcx, [rbx+EFI_SYSTEM_TABLE.NumberOfTableEntries]
mov rax, 0x11d3e4f18868e871
mov rdx, 0x81883cc7800022bc
.next_table:
dec ecx
js .all_tables_done
cmp [rdi+0], rax
jnz .not_acpi20
cmp [rdi+8], rdx
jnz .not_acpi20
mov rax, [rdi+16]
mov rdx, BOOT_LO.acpi_rsdp
mov [rdx], eax
jmp .all_tables_done
.not_acpi20:
add rdi, 24
jmp .next_table
.all_tables_done:
ret
endp
proc dump_pci_resources uses rsi rdi
xor eax, eax
mov rsi, [pcirbiop_resources]
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_dump_pci_resources
.next_resource:
call clearbuf
movzx eax, [rsi+EFI_QWORD_ADDRESS_SPACE_DESCRIPTOR.Type]
cmp eax, EFI_RESOURCE_DESCRIPTOR_TYPE.END_TAG
jz .done
mov rdi, msg
call num2hex
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, msg
call clearbuf
movzx eax, [rsi+EFI_QWORD_ADDRESS_SPACE_DESCRIPTOR.ResourceType]
mov rdi, msg
call num2dec
mov rax, [rsi+EFI_QWORD_ADDRESS_SPACE_DESCRIPTOR.RangeMinimum]
mov rdi, msg+2*2
call num2hex
mov rax, [rsi+EFI_QWORD_ADDRESS_SPACE_DESCRIPTOR.RangeMaximum]
mov rdi, msg+19*2
call num2hex
mov rax, [rsi+EFI_QWORD_ADDRESS_SPACE_DESCRIPTOR.TranslationOffset]
mov rdi, msg+36*2
call num2hex
mov rax, [rsi+EFI_QWORD_ADDRESS_SPACE_DESCRIPTOR.AddressLength]
mov rdi, msg+53*2
call num2hex
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, msg
movzx eax, [rsi+EFI_QWORD_ADDRESS_SPACE_DESCRIPTOR.Length]
add eax, 3
add rsi, rax
jmp .next_resource
.done:
ret
endp
proc calc_memmap uses rsi rdi
mov r10, [rbx+EFI_SYSTEM_TABLE.BootServices]
fstcall [r10+EFI_BOOT_SERVICES.AllocatePages], EFI_ALLOCATE_ANY_PAGES, \
EFI_RESERVED_MEMORY_TYPE, MEMORY_MAP_SIZE/0x1000, memory_map
call halt_on_error
mov r10, [rbx+EFI_SYSTEM_TABLE.BootServices]
fstcall [r10+EFI_BOOT_SERVICES.GetMemoryMap], memory_map_size, \
[memory_map], memory_map_key, descriptor_size, descriptor_ver
call halt_on_error
mov rdi, BOOT_LO.memmap_blocks
mov dword[rdi-4], 0 ; memmap_block_cnt
mov rsi, [memory_map]
mov r10, rsi
add r10, [memory_map_size]
.next_descr:
fstcall add_uefi_memmap
add rsi, [descriptor_size]
cmp rsi, r10
jb .next_descr
ret
endp
proc dump_memmap uses rsi rdi
xor eax, eax
mov rsi, BOOT_LO.memmap_blocks
mov r12, [rax+BOOT_LO.memmap_block_cnt]
call clearbuf
mov eax, ebx
mov rdi, msg
call num2dec
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, \
msg_memmap
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, msg
call clearbuf
.next_mapping:
dec r12d
js .done
mov rax, rsi
mov rcx, BOOT_LO.memmap_blocks
sub rax, rcx
mov ecx, sizeof.e820entry
xor edx, edx
div ecx
mov rdi, msg
call num2dec
mov rax, [rsi+e820entry.addr]
mov rdi, msg+4*2
call num2hex
mov rax, [rsi+e820entry.size]
mov rdi, msg+24*2
call num2hex
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, msg
add rsi, sizeof.e820entry
jmp .next_mapping
.done:
ret
endp
; linux/arch/x86/platform/efi/efi.c
; do_add_efi_memmap
proc add_uefi_memmap
xor eax, eax
cmp [rax+BOOT_LO.memmap_block_cnt], MAX_MEMMAP_BLOCKS
jz .done
mov rax, [rsi+EFI_MEMORY_DESCRIPTOR.PhysicalStart]
mov [rdi+e820entry.addr], rax
mov rax, [rsi+EFI_MEMORY_DESCRIPTOR.NumberOfPages]
shl rax, 12
mov [rdi+e820entry.size], rax
mov ecx, [rsi+EFI_MEMORY_DESCRIPTOR.Type]
cmp ecx, EFI_LOADER_CODE
jz .mem_ram_if_wb
cmp ecx, EFI_LOADER_DATA
jz .mem_ram_if_wb
cmp ecx, EFI_BOOT_SERVICES_CODE
jz .mem_ram_if_wb
cmp ecx, EFI_BOOT_SERVICES_DATA
jz .mem_ram_if_wb
cmp ecx, EFI_CONVENTIONAL_MEMORY
jz .mem_ram_if_wb
cmp ecx, EFI_ACPI_RECLAIM_MEMORY
mov eax, E820_ACPI
jz .type_done
cmp ecx, EFI_ACPI_MEMORY_NVS
mov eax, E820_NVS
jz .type_done
cmp ecx, EFI_UNUSABLE_MEMORY
mov eax, E820_UNUSABLE
jz .type_done
cmp ecx, EFI_PERSISTENT_MEMORY
mov eax, E820_PMEM
jz .type_done
jmp .reserved
.mem_ram_if_wb:
test [rsi+EFI_MEMORY_DESCRIPTOR.Attribute], dword EFI_MEMORY_WB
mov eax, E820_RAM
jnz .type_done
.reserved:
mov eax, E820_RESERVED
.type_done:
mov [rdi+e820entry.type], eax
cmp eax, E820_RAM
jnz @f
xor eax, eax
inc [rax+BOOT_LO.memmap_block_cnt]
add rdi, sizeof.e820entry
@@:
.done:
ret
endp
num2dec:
push rbx rcx rdx rdi
xor ecx, ecx
mov ebx, 10
.next_digit:
xor edx, edx
div ebx
push rdx
inc ecx
test eax, eax
jnz .next_digit
.next_char:
pop rax
add eax, '0'
stosw
loop .next_char
pop rdi rdx rcx rbx
ret
num2hex:
push rbx rcx rdx rdi
xchg rdx, rax
mov ecx, 16
.next_tetra:
rol rdx, 4
movzx eax, dl
and eax, 0x0f
movzx eax, byte[hex_abc+eax]
stosw
loop .next_tetra
pop rdi rdx rcx rbx
ret
clearbuf:
push rcx rdi
mov eax, ' '
mov ecx, 79
mov rdi, msg
rep stosw
pop rdi rcx
ret
use32
kernel_trampoline:
org KERNEL_TRAMPOLINE
mov eax, cr0
and eax, not CR0_PG
mov cr0, eax
mov ecx, MSR_AMD_EFER
rdmsr
btr eax, 8 ; LME
wrmsr
mov eax, cr4
and eax, not CR4_PAE
mov cr4, eax
push KERNEL_BASE
retn
align 16
GDTR:
dw 4*8-1
dq GDT
align 16
GDT:
dw 0, 0, 0, 0
dw 0FFFFh,0,9A00h,0CFh ; 32-bit code
dw 0FFFFh,0,9200h,0CFh ; flat data
dw 0FFFFh,0,9A00h,0AFh ; 64-bit code
assert $ < BOOT_LO
kernel_trampoline.size = $ - KERNEL_TRAMPOLINE
section '.rodata' data readable
gop_guid db EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID
lip_guid db EFI_LOADED_IMAGE_PROTOCOL_GUID
sfsp_guid db EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID
pcirbiop_guid db EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID
file_name du '\EFI\KOLIBRIOS\KOLIBRI.INI',0
kernel_name du '\EFI\KOLIBRIOS\KOLIBRI.KRN',0
ramdisk_name du '\EFI\KOLIBRIOS\KOLIBRI.IMG',0
devicesdat_name du '\EFI\KOLIBRIOS\DEVICES.DAT',0
config_options dq cfg_opt_name_resolution, cfg_opt_func_resolution, \
cfg_opt_cmnt_resolution, \
cfg_opt_name_acpi, cfg_opt_func_acpi, cfg_opt_cmnt_acpi, \
cfg_opt_name_debug_print, cfg_opt_func_debug_print, \
cfg_opt_cmnt_debug_print, \
cfg_opt_name_launcher_start, cfg_opt_func_launcher_start, \
cfg_opt_cmnt_launcher_start, \
cfg_opt_name_mtrr, cfg_opt_func_mtrr, cfg_opt_cmnt_mtrr, \
cfg_opt_name_ask_params, cfg_opt_func_ask_params, \
cfg_opt_cmnt_ask_params, \
cfg_opt_name_imgfrom, cfg_opt_func_imgfrom, \
cfg_opt_cmnt_imgfrom, \
cfg_opt_name_syspath, cfg_opt_func_syspath, \
cfg_opt_cmnt_syspath, \
0
cfg_opt_name_resolution db "resolution",0
cfg_opt_name_acpi db "acpi",0
cfg_opt_name_debug_print db "debug_print",0
cfg_opt_name_launcher_start db "launcher_start",0
cfg_opt_name_mtrr db "mtrr",0
cfg_opt_name_ask_params db "ask_params",0
cfg_opt_name_imgfrom db "imgfrom",0
cfg_opt_name_syspath db "syspath",0
cfg_opt_cmnt_resolution db "# Graphic mode",0
cfg_opt_cmnt_acpi db "# ACPI settings",0xa, \
"# 0: don't use",0xa, \
"# 1: parse ACPI tables",0xa, \
"# 2: + call _PIC method",0xa, \
"# 3: + get APIC interrupts",0xa,0
cfg_opt_cmnt_debug_print db "# Duplicate debug output to the screen",0
cfg_opt_cmnt_launcher_start db "# Start LAUNCHER app after kernel is loaded",0
cfg_opt_cmnt_mtrr db "# Configure MTRR's",0
cfg_opt_cmnt_ask_params db "# Interrupt booting to ask the user for boot", \
" params",0
cfg_opt_cmnt_imgfrom db "# Where to load ramdisk image from",0
cfg_opt_cmnt_syspath db "# Path to /sys directory",0
msg_u4k_loaded du "uefi64kos loaded",13,10,0
msg_detect_pci_config du "Detect PCI configuration",13,10,0
msg_dump_pci_resources du "Dump PCI resources",13,10,0
msg_pci_last_bus du "Last PCI bus",13,10,0
msg_read_options du "Read options from config file",13,10,0
msg_file_size du "File size:",13,10,0
msg_parsing_config du "Parsing config file",13,10,0
msg_load_kernel du "Load kernel",13,10,0
msg_load_ramdisk du "Load ramdisk",13,10,0
msg_load_devicesdat du "Load DEVICES.DAT",13,10,0
msg_alloc_devicesdat du "Allocate memory for DEVICES.DAT",13,10,0
msg_locate_gop_interface du "Locate GOP interface",13,10,0
msg_look_for_handler du "Look for protocol handler",13,10,0
msg_query_handler du "Query handler",13,10,0
msg_query_vmode du "Query vmode",13,10,0
msg_vmode_found du "Video mode found",13,10,0
msg_look_for_rsdp du "Look for RSDP",13,10,0
msg_rsdp_found du "RSDP found",13,10,0
msg_acpi_tables_done du "ACPI tables done",13,10,0
msg_ask_for_params du "Ask for params",13,10,0
msg_set_graphic_mode du "Set graphic mode",13,10,0
msg_success du "Success!",13,10,0
msg_protocol_buffer_size du "Protocol buffer size",13,10,0
msg_opt_resolution du "Option resolution: ",0
msg_memmap du "Memmap",13,10,0
msg_error du "Error!",13,10,0
msg_error_efi_lip_handle du "efi_handle can't handle LIP",13,10,0
msg_error_lip_dev_sfsp du "LIP device handle can't handle SFSP",13,10,0
msg_error_sfsp_openvolume du "SFSP OpenVolume failed",13,10,0
msg_error_no_such_vmode du "No such vmode",13,10,0
msg_error_out_of_handlers du "Out of handlers",13,10,0
msg_error_open_file du "Error: can't open file ",0
msg_error_exit_boot_services du "Error: Exit boot services",13,10,0
msg du 79 dup " ",13,10,0
msg_debug du "Debug ",13,10,0
section '.data' data readable writeable
efi_handle dq 0
efi_table dq 0
fb_base dq 0
gop_interface dq 0
gop_info_size dq 0
gop_info dq 0
lip_interface dq 0
sfsp_interface dq 0
pci_last_bus db 254
cfg_opt_used_resolution db 0
cfg_opt_used_acpi db 0
cfg_opt_used_debug_print db 0
cfg_opt_used_launcher_start db 0
cfg_opt_used_mtrr db 0
cfg_opt_used_ask_params db 0
cfg_opt_used_imgfrom db 0
cfg_opt_used_syspath db 0
cfg_opt_value_vmode db 0
cfg_opt_value_acpi db 0
cfg_opt_value_debug_print db 0
cfg_opt_value_launcher_start db 1
cfg_opt_value_mtrr db 0
cfg_opt_value_ask_params db 0
cfg_opt_value_imgfrom db RD_LOAD_FROM_MEMORY
cfg_opt_value_syspath db "/RD/1",0
rb 20
memory_map_key dq 0
descriptor_size dq 0
descriptor_ver dq 0
memory_map_size dq MEMORY_MAP_SIZE
efi_fs_info_id db EFI_FILE_SYSTEM_INFO_ID
efi_fs_info_size dq sizeof.EFI_FILE_SYSTEM_INFO
devicesdat_data dq 0xffffffff
devicesdat_size dq 0x1000
hex_abc db '0123456789ABCDEF'
section '.bss' data readable writeable discardable
prot_handlers_buffer_size dq ?
prot_interface dq ?
esp_root dq ?
file_handle dq ?
pcirbiop_interface dq ?
pcirbiop_resources dq ?
efi_fs_info EFI_FILE_SYSTEM_INFO
memory_map dq ?
prot_handlers_buffer rq PROTOCOL_HANDLERS_BUFFER_SIZE/8
pcirbio_buffer rq PROTOCOL_HANDLERS_BUFFER_SIZE/8
section '.reloc' fixups data discardable