kolibrios/kernel/trunk/bootloader/uefi4kos/uefi64kos.asm

1181 lines
37 KiB
NASM
Raw Normal View History

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; 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