;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; Copyright (C) KolibriOS team 2020. All rights reserved. ;; ;; Distributed under terms of the GNU General Public License ;; ;; Version 2, or (at your option) any later version. ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; format pe64 efi entry main section '.text' code executable readable include '../../struct.inc' include '../../macros.inc' include '../../const.inc' purge DQ include 'uefi64.inc' MEMORY_MAP_SIZE = 0x10000 GOP_BUFFER_SIZE = 0x100 LIP_BUFFER_SIZE = 0x100 FILE_BUFFER_SIZE = 0x1000 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 load_file: virtual at rsp+8 .root dq ? .name dq ? .buffer dq ? .size dq ? .fatal dq ? end virtual eficall [.root], EFI_FILE_PROTOCOL.Open, [.root], file_handle, \ [.name], EFI_FILE_MODE_READ, 0 test eax, eax jz @f xor eax, eax cmp [.fatal], 1 jnz .done mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ msg_error_open_file mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ [.name] jmp $ @@: lea rax, [.size] eficall [file_handle], EFI_FILE_PROTOCOL.Read, [file_handle], rax, \ [.buffer] eficall [file_handle], EFI_FILE_PROTOCOL.Close, [file_handle] mov rax, [.size] .done: push rax call clearbuf mov rdi, msg call num2dec push rbx mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ msg_file_size pop rbx push rbx mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, msg pop rbx pop rax ret 8*5 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 parse_config: virtual at rsp+8 .buffer dq ? end virtual ; mov rsi, [.buffer] push rbx mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ msg_parsing_config pop rbx mov rsi, KERNEL_BASE .next_line: call parse_line cmp byte[rsi], 0 jnz .next_line ret 1*8 read_options_from_config: mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.BootServices] eficall rbx, EFI_BOOT_SERVICES.HandleProtocol, [efi_handle], lipuuid, \ lip_interface test eax, eax jz @f push rbx mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ msg_error_efi_lip_handle pop rbx jmp $ @@: mov rax, [lip_interface] mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.BootServices] eficall rbx, EFI_BOOT_SERVICES.HandleProtocol, \ [rax+EFI_LOADED_IMAGE_PROTOCOL.DeviceHandle], sfspguid, \ sfsp_interface test eax, eax jz @f push rbx mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ msg_error_lip_dev_sfsp pop rbx jmp $ @@: eficall [sfsp_interface], EFI_SIMPLE_FILE_SYSTEM_PROTOCOL.OpenVolume, \ [sfsp_interface], esp_root test eax, eax jz @f push rbx mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ msg_error_sfsp_openvolume pop rbx jmp $ @@: push 0 ; not fatal, i.e. it's ok to not find this file push FILE_BUFFER_SIZE push KERNEL_BASE ; push file_name mov rax, file_name push rax push [esp_root] call load_file test eax, eax jz @f push KERNEL_BASE call parse_config @@: .error: ret print_vmode: push rax rbx rcx rdx rsi rdi mov rbx, rcx call clearbuf mov eax, [rbx+EFI_GRAPHICS_OUTPUT_MODE_INFORMATION.HorizontalResolution] mov rdi, msg call num2dec mov eax, [rbx+EFI_GRAPHICS_OUTPUT_MODE_INFORMATION.VerticalResolution] mov rdi, msg+8*2 call num2dec mov eax, [rbx+EFI_GRAPHICS_OUTPUT_MODE_INFORMATION.PixelFormat] mov rdi, msg+16*2 call num2dec mov eax, [rbx+EFI_GRAPHICS_OUTPUT_MODE_INFORMATION.PixelsPerScanLine] mov rdi, msg+24*2 call num2dec mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, msg pop rdi rsi rdx rcx rbx rax ret find_vmode_index_by_resolution: mov [cfg_opt_used_resolution], 1 mov [cfg_opt_value_vmode], 0 .next_mode: movzx eax, [cfg_opt_value_vmode] eficall [gop_interface], EFI_GRAPHICS_OUTPUT_PROTOCOL.QueryMode, \ [gop_interface], rax, gop_info_size, gop_info cmp rax, EFI_SUCCESS jnz .error mov rcx, [gop_info] call 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 rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ msg_error_no_such_vmode mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ msg_error jmp $ .error: .done: ret ask_for_params: ret mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.BootServices] eficall rbx, EFI_BOOT_SERVICES.HandleProtocol, [rax], gopuuid, \ msg_ask_for_params jmp $ xor ebx, ebx .next_mode: call clearbuf mov eax, ebx lea rdi, [msg] call num2dec push rbx eficall [gop_interface], EFI_GRAPHICS_OUTPUT_PROTOCOL.QueryMode, \ [gop_interface], rbx, gop_info_size, gop_info cmp rax, EFI_SUCCESS jnz .error mov rcx, [gop_info] ; PixelBlueGreenRedReserved8BitPerColor cmp [rcx+EFI_GRAPHICS_OUTPUT_MODE_INFORMATION.PixelFormat], 1 jnz .skip mov eax, [rcx+EFI_GRAPHICS_OUTPUT_MODE_INFORMATION.HorizontalResolution] lea rdi, [msg+4*2] call num2dec mov eax, [rcx+EFI_GRAPHICS_OUTPUT_MODE_INFORMATION.VerticalResolution] lea rdi, [msg+9*2] call num2dec ; mov eax, [rcx+EFI_GRAPHICS_OUTPUT_MODE_INFORMATION.PixelsPerScanLine] ; lea rdi, [msg+14*2] ; call num2dec .skip: mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, msg cmp rax, EFI_SUCCESS jnz .error pop rbx inc rbx mov rcx, [gop_interface] mov rdx, [rcx+EFI_GRAPHICS_OUTPUT_PROTOCOL.Mode] cmp ebx, [rdx+EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE.MaxMode] jnz .next_mode mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConIn] eficall rbx, SIMPLE_INPUT_INTERFACE.Reset, rbx, 1 cmp rax, EFI_SUCCESS jnz .error xor ecx, ecx @@: push rcx mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConIn] eficall rbx, SIMPLE_INPUT_INTERFACE.ReadKeyStroke, rbx, msg pop rcx mov rdx, EFI_DEVICE_ERROR cmp rax, rdx jz .error mov rdx, EFI_NOT_READY cmp rax, rdx jz @b ; cmp rax, EFI_SUCCESS movzx eax, word[msg+2] ;jmp .key_done cmp al, 0x0D jz .key_done imul ecx, 10 sub eax, '0' add ecx, eax jmp @b .key_done: mov [cfg_opt_value_vmode], cl .error: .done: ret main: mov [efi_handle], rcx mov [efi_table], rdx mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.Reset, rbx, 1 test eax, eax jz @f jmp $ ; what can I do here? @@: mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ msg_u4k_loaded mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ msg_read_options call read_options_from_config ; read kernel file mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ msg_load_kernel push 1 ; fatal push MAX_FILE_SIZE push KERNEL_BASE ; push kernel_name mov rax, kernel_name push rax push [esp_root] call load_file ; read ramdisk image mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ msg_load_ramdisk push 1 ; fatal push MAX_FILE_SIZE push RAMDISK_BASE ; push ramdisk_name mov rax, ramdisk_name push rax push [esp_root] call load_file ; alloc buffer for devices.dat mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ msg_alloc_devicesdat mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.BootServices] eficall rbx, 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 rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ msg_load_devicesdat push 0 ; not fatal push [devicesdat_size] push [devicesdat_data] ; push devicesdat_name mov rax, devicesdat_name push rax push [esp_root] call load_file mov [devicesdat_size], rax mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ msg_locate_gop_handlers mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.BootServices] eficall rbx, EFI_BOOT_SERVICES.LocateHandle, \ EFI_LOCATE_SEARCH_TYPE.ByProtocol, gopuuid, 0, \ gop_buffer_size, gop_buffer mov [status], rax mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ msg_gop_buffer_size call clearbuf mov rax, [gop_buffer_size] mov rdi, msg call num2hex mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, msg mov rax, [status] test eax, eax jz @f call clearbuf mov rdi, msg call num2hex mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ msg_error mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, msg jmp $ @@: mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ msg_look_for_gop_handler mov rbx, gop_buffer .next_gop_handle: mov rax, rbx mov rcx, gop_buffer sub rax, rcx cmp rax, [gop_buffer_size] jb @f push rbx mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ msg_error_out_of_handlers pop rbx push rbx mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, msg_error pop rbx jmp $ @@: push rbx mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ msg_query_handler pop rbx mov rax, rbx push rbx mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.BootServices] eficall rbx, EFI_BOOT_SERVICES.HandleProtocol, [rax], gopuuid, \ gop_interface pop rbx ;mov rax, 0x8000_0000_0000_0003 test eax, eax jz @f call clearbuf mov rdi, msg call num2hex push rbx mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, msg pop rbx add rbx, 8 jmp .next_gop_handle @@: call find_rsdp mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ msg_acpi_tables_done cmp [cfg_opt_used_resolution], 0 jz .not_used_resolution mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ 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 rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, msg call 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 ecx, [cfg_opt_value_vmode] eficall [gop_interface], EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode, \ [gop_interface], rcx test eax, eax jz @f call clearbuf mov rdi, msg call num2hex mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, msg mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ 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 ebx, [rdx+EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE.Mode] eficall [gop_interface], EFI_GRAPHICS_OUTPUT_PROTOCOL.QueryMode, \ [gop_interface], rbx, 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 byte[rdx+BOOT_LO.pci_data+0], 1 ; PCI access mechanism mov byte[rdx+BOOT_LO.pci_data+1], 8 ; last bus, don't know how to count them mov byte[rdx+BOOT_LO.pci_data+2], 0x10 ; PCI version mov byte[rdx+BOOT_LO.pci_data+3], 0x02 mov dword[rdx+BOOT_LO.pci_data+4], 0xe3 ; kernel ; eficall BootServices, AllocatePages, EFI_RESERVED_MEMORY_TYPE, \ ; 450000/0x1000, EFI_ALLOCATE_ADDRESS ; ramdisk ; eficall BootServices, AllocatePages, EFI_RESERVED_MEMORY_TYPE, \ ; 2880*512/0x1000, EFI_ALLOCATE_ADDRESS call calc_memmap ; call dump_memmap mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.BootServices] eficall rbx, EFI_BOOT_SERVICES.ExitBootServices, [efi_handle], \ [memory_map_key] call halt_on_error cli xor edx, edx xor esi, esi mov [esi+BOOT_LO.bpp], 32 mov [esi+BOOT_LO.vesa_mode], dx mov [esi+BOOT_LO.bank_switch], edx mov rdi, [fb_base] mov [esi+BOOT_LO.lfb], edi movzx eax, [cfg_opt_value_mtrr] mov [esi+BOOT_LO.mtrr], al movzx eax, [cfg_opt_value_launcher_start] mov [esi+BOOT_LO.launcher_start], al movzx eax, [cfg_opt_value_debug_print] mov [esi+BOOT_LO.debug_print], al mov [esi+BOOT_LO.dma], dl ; mov qword[esi+BOOT_LO.pci_data], 0 mov [esi+BOOT_LO.apm_entry], edx mov [esi+BOOT_LO.apm_version], dx mov [esi+BOOT_LO.apm_flags], dx mov [esi+BOOT_LO.apm_code_32], dx mov [esi+BOOT_LO.apm_code_16], dx mov [esi+BOOT_LO.apm_data_16], dx mov [esi+BOOT_LO.bios_hd_cnt], dl movzx eax, [cfg_opt_value_imgfrom] mov [esi+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 lgdt [cs:GDTR] mov ax, DATA_32_SELECTOR mov ds, ax mov es, ax mov fs, ax mov gs, ax mov ss, ax push CODE_32_SELECTOR lea rax, [.next] push rax retf use32 align 16 .next: 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 use64 .error: mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ msg_error jmp $ halt_on_error: test eax, eax jz @f call clearbuf mov rdi, msg call num2hex mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ msg_error mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, msg jmp $ @@: ret find_rsdp: push rbx mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ msg_look_for_rsdp pop rbx mov rbx, [efi_table] 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 calc_memmap: mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.BootServices] eficall rbx, EFI_BOOT_SERVICES.AllocatePages, EFI_ALLOCATE_ANY_PAGES, \ EFI_RESERVED_MEMORY_TYPE, MEMORY_MAP_SIZE/0x1000, memory_map call halt_on_error mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.BootServices] eficall rbx, 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 rbx, rsi add rbx, [memory_map_size] .next_descr: call add_uefi_memmap add rsi, [descriptor_size] cmp rsi, rbx jb .next_descr ret dump_memmap: xor eax, eax mov rsi, BOOT_LO.memmap_blocks mov ebx, [rax+BOOT_LO.memmap_block_cnt] call clearbuf mov eax, ebx mov rdi, msg call num2dec push rbx mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, \ msg_memmap pop rbx push rbx mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, msg pop rbx call clearbuf .next_mapping: dec ebx 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 push rbx mov rbx, [efi_table] mov rbx, [rbx+EFI_SYSTEM_TABLE.ConOut] eficall rbx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString, rbx, msg pop rbx add rsi, sizeof.e820entry jmp .next_mapping .done: ret ; linux/arch/x86/platform/efi/efi.c ; do_add_efi_memmap 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 num2dec: push rax rbx rcx rdx rsi 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 rsi rdx rcx rbx rax ret num2hex: push rax rbx rcx rdx rsi rdi xchg rdx, rax mov ecx, 16 .next_tetra: rol rdx, 4 movzx eax, dl and eax, 0x0f movzx eax, byte[hex+eax] stosw loop .next_tetra pop rdi rsi rdx rcx rbx rax ret hex db '0123456789ABCDEF' clearbuf: push rax rbx rcx rdx rsi rdi mov eax, 0x0020 mov ecx, 79 mov rdi, msg rep stosw pop rdi rsi rdx rcx rbx rax ret section '.rodata' data readable 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 gopuuid db EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID lipuuid db EFI_LOADED_IMAGE_PROTOCOL_GUID sfspguid db EFI_SIMPLE_FILE_SYSTEM_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_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_handlers du "Locate GOP handlers",13,10,0 msg_look_for_gop_handler du "Look for GOP 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_gop_buffer_size du "GOP 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 section '.data' data readable writeable efi_handle dq 0 efi_table dq 0 uefi_rsptmp dq 0 fb_base dq 0 gop_buffer_size dq GOP_BUFFER_SIZE gop_handle dq 0 gop_interface dq 0 gop_info_size dq 0 gop_info dq 0 lip_buffer_size dq LIP_BUFFER_SIZE lip_handle dq 0 lip_interface dq 0 sfsp_interface dq 0 esp_root dq ? file_handle dq ? file_buffer_size dq FILE_BUFFER_SIZE-1 ; leave the last byte for \0 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 efi_fs_info EFI_FILE_SYSTEM_INFO memory_map dq ? gop_buffer rq GOP_BUFFER_SIZE/8 devicesdat_data dq 0xffffffff devicesdat_size dq 0x1000 status dq ? section '.reloc' fixups data discardable