From 4412d4fc988e6585439c546690d6476b0bfc8fe8 Mon Sep 17 00:00:00 2001 From: Rafal Kupiec Date: Tue, 9 Jan 2024 18:51:04 +0100 Subject: [PATCH] Rewrite core of the XTLDR boot loader Reviewed-on: https://git.codingworkshop.eu.org/xt-sys/exectos/pulls/7 Reviewed-by: Piotr Likoski Co-authored-by: Rafal Kupiec Co-committed-by: Rafal Kupiec --- KNOWN_ISSUES.md | 3 - bootdata/xtldr/CMakeLists.txt | 2 +- bootdata/xtldr/xtldr.ini | 16 +- sdk/cmake/version.cmake | 4 + sdk/cmake/version/xtver.h.cmake | 3 + sdk/xtdk/blfuncs.h | 23 + sdk/xtdk/bltypes.h | 289 ++++ sdk/xtdk/xtblapi.h | 50 + sdk/xtdk/xtstruct.h | 12 + xtldr/CMakeLists.txt | 21 +- xtldr/README.md | 2 +- xtldr/blproto.c | 96 -- xtldr/config.c | 595 ++++++++ xtldr/console.c | 253 +++- xtldr/debug.c | 263 ++++ xtldr/efiutil.c | 364 ----- xtldr/efiutils.c | 120 ++ xtldr/globals.c | 38 +- xtldr/hardware.c | 112 ++ xtldr/includes/bldefs.h | 22 - xtldr/includes/blmod.h | 94 -- xtldr/includes/blproto.h | 62 - xtldr/includes/globals.h | 48 + xtldr/includes/xtbl.h | 264 ---- xtldr/includes/xtldr.h | 422 ++++++ xtldr/library/modproto.c | 80 + xtldr/memory.c | 495 +------ xtldr/modules/CMakeLists.txt | 8 +- xtldr/modules/beep/CMakeLists.txt | 27 + xtldr/modules/beep/beep.c | 209 +++ xtldr/modules/beep/globals.c | 13 + xtldr/modules/beep/includes/beep.h | 38 + xtldr/modules/beep/includes/globals.h | 18 + xtldr/modules/dummy/CMakeLists.txt | 27 + xtldr/modules/dummy/dummy.c | 69 + xtldr/modules/dummy/globals.c | 16 + xtldr/modules/dummy/includes/dummy.h | 26 + xtldr/modules/dummy/includes/globals.h | 21 + xtldr/modules/fb_o/CMakeLists.txt | 27 + xtldr/modules/{framebuf => fb_o}/framebuf.c | 97 +- xtldr/modules/{framebuf => fb_o}/gop.c | 2 +- xtldr/modules/fb_o/includes/framebuf.h | 79 + xtldr/modules/framebuf/CMakeLists.txt | 28 - xtldr/modules/framebuf/includes/framebuf.h | 44 - xtldr/modules/pecoff/CMakeLists.txt | 27 - xtldr/modules/pecoff_o/CMakeLists.txt | 26 + .../{pecoff => pecoff_o}/includes/pecoff.h | 20 +- xtldr/modules/{pecoff => pecoff_o}/pecoff.c | 115 +- xtldr/modules/xtos/CMakeLists.txt | 27 - xtldr/modules/xtos/includes/xtos.h | 54 - xtldr/modules/xtos_o/CMakeLists.txt | 28 + xtldr/{ => modules/xtos_o}/amd64/memory.c | 90 +- xtldr/{ => modules/xtos_o}/i686/memory.c | 83 +- xtldr/modules/xtos_o/includes/xtos.h | 107 ++ xtldr/modules/xtos_o/memory.c | 385 +++++ xtldr/modules/{xtos => xtos_o}/xtos.c | 161 ++- xtldr/protocol.c | 601 ++++++++ xtldr/shell.c | 50 + xtldr/string.c | 190 +-- xtldr/system.c | 77 - xtldr/textui.c | 1288 +++++++++++++++++ xtldr/volume.c | 239 ++- xtldr/xtldr.c | 583 ++++---- 63 files changed, 6282 insertions(+), 2371 deletions(-) create mode 100644 sdk/xtdk/blfuncs.h create mode 100644 sdk/xtdk/bltypes.h create mode 100644 sdk/xtdk/xtblapi.h delete mode 100644 xtldr/blproto.c create mode 100644 xtldr/config.c create mode 100644 xtldr/debug.c delete mode 100644 xtldr/efiutil.c create mode 100644 xtldr/efiutils.c create mode 100644 xtldr/hardware.c delete mode 100644 xtldr/includes/bldefs.h delete mode 100644 xtldr/includes/blmod.h delete mode 100644 xtldr/includes/blproto.h create mode 100644 xtldr/includes/globals.h delete mode 100644 xtldr/includes/xtbl.h create mode 100644 xtldr/includes/xtldr.h create mode 100644 xtldr/library/modproto.c create mode 100644 xtldr/modules/beep/CMakeLists.txt create mode 100644 xtldr/modules/beep/beep.c create mode 100644 xtldr/modules/beep/globals.c create mode 100644 xtldr/modules/beep/includes/beep.h create mode 100644 xtldr/modules/beep/includes/globals.h create mode 100644 xtldr/modules/dummy/CMakeLists.txt create mode 100644 xtldr/modules/dummy/dummy.c create mode 100644 xtldr/modules/dummy/globals.c create mode 100644 xtldr/modules/dummy/includes/dummy.h create mode 100644 xtldr/modules/dummy/includes/globals.h create mode 100644 xtldr/modules/fb_o/CMakeLists.txt rename xtldr/modules/{framebuf => fb_o}/framebuf.c (69%) rename xtldr/modules/{framebuf => fb_o}/gop.c (96%) create mode 100644 xtldr/modules/fb_o/includes/framebuf.h delete mode 100644 xtldr/modules/framebuf/CMakeLists.txt delete mode 100644 xtldr/modules/framebuf/includes/framebuf.h delete mode 100644 xtldr/modules/pecoff/CMakeLists.txt create mode 100644 xtldr/modules/pecoff_o/CMakeLists.txt rename xtldr/modules/{pecoff => pecoff_o}/includes/pecoff.h (71%) rename xtldr/modules/{pecoff => pecoff_o}/pecoff.c (82%) delete mode 100644 xtldr/modules/xtos/CMakeLists.txt delete mode 100644 xtldr/modules/xtos/includes/xtos.h create mode 100644 xtldr/modules/xtos_o/CMakeLists.txt rename xtldr/{ => modules/xtos_o}/amd64/memory.c (78%) rename xtldr/{ => modules/xtos_o}/i686/memory.c (78%) create mode 100644 xtldr/modules/xtos_o/includes/xtos.h create mode 100644 xtldr/modules/xtos_o/memory.c rename xtldr/modules/{xtos => xtos_o}/xtos.c (73%) create mode 100644 xtldr/protocol.c create mode 100644 xtldr/shell.c delete mode 100644 xtldr/system.c create mode 100644 xtldr/textui.c diff --git a/KNOWN_ISSUES.md b/KNOWN_ISSUES.md index a13844a..f008157 100644 --- a/KNOWN_ISSUES.md +++ b/KNOWN_ISSUES.md @@ -2,8 +2,5 @@ This is a list of well known bugs that exists in all master branch builds. ### XTLDR - - [ ] In some specific scenarios (most probably EFI by Insyde) XTLDR cannot load modules. Calling the EFI's - BootServices->LoadImage() fails with STATUS_EFI_NOT_FOUND (0x800000000000000E) status code. Possibly this is - a bug in BlFindVolumeDevicePath() routine. - [ ] EFI Runtime Services are not mapped properly into higher half. They are mapped itself, but all pointers inside that structure point to some physical address that is unavailable after paging is enabled. diff --git a/bootdata/xtldr/CMakeLists.txt b/bootdata/xtldr/CMakeLists.txt index 3bf097a..9dcfcfb 100644 --- a/bootdata/xtldr/CMakeLists.txt +++ b/bootdata/xtldr/CMakeLists.txt @@ -1 +1 @@ -set_install_file(xtldr.ini efi/boot) +set_install_file(xtldr.ini efi/boot/xtldr) diff --git a/bootdata/xtldr/xtldr.ini b/bootdata/xtldr/xtldr.ini index 4537da4..31dfdfd 100644 --- a/bootdata/xtldr/xtldr.ini +++ b/bootdata/xtldr/xtldr.ini @@ -6,13 +6,14 @@ # Debug - enables the debugging port and consists of two comma-separated parameters: com port and baud rate; # it is also possible to specify custom port address with: COM0:[address],[baud_rate] # Default - specifies which operating system listen in config file will be started if no choice is made -# Theme - allows to set a custom theme to personalize XTLDR's look'n'feel +# Modules - supplies a list of modules that will be loaded in orded to extend XTLDR functionality # Timeout - sets the countdown timer (in seconds) before the default OS get started automatically -# Tune - plays a tune on the pcspeaker right before the XTLDR loads +# Tune - plays a tune on the pcspeaker right before the XTLDR boot menu shows up # # Another type of section is [OS-Section] which adds a new position (operating system) to the boot menu. Each type # of the operating system provides a set of available parameters. If unsupported option is added, it is being ignored # by the XT Boot Loader. The available options are: +# BootModules - supplies a list of additional modules that will be loaded just before invoking the boot protocol # SystemName - sets a long operating system name that will be shown on the boot menu # SystemType - specifies an OS type from a predefined list of supported boot protocols # SystemPath - the ARC path, eg. multi(0)disk(0)rdisk(0)partition(1) @@ -22,22 +23,24 @@ # Parameters - specifies extra boot options for the kernel [XTLDR] -Tune=400 880 2 988 2 783 2 392 2 587 3 Debug=COM1,115200 -Timeout=30 -Theme=Fancy Default=ExectOS +Modules=beep +Timeout=30 +Tune=400 880 2 988 2 783 2 392 2 587 3 [ExectOS] SystemName="ExectOS Operating System" SystemType=XTOS +BootModules=xtos_o SystemPath=multi(0)disk(0)rdisk(0)partition(1)/ExectOS KernelFile=xtoskrnl.exe -Parameters=DEBUG DEBUGPORT=COM1,115200 +Parameters=DEBUG=COM1,115200 [Windows] SystemName="Microsoft Windows 2000" SystemType=NT50 +BootModules=ntos SystemPath=multi(0)disk(0)rdisk(0)partition(2)/Windows KernelFile=ntoskrnl.exe HalFile=hal.dll @@ -46,6 +49,7 @@ Parameters=/NOGUIBOOT /MININT [Linux] SystemName="GNU/Linux" SystemType=LINUX +BootModules=linux SystemPath=multi(0)disk(0)rdisk(0)partition(3)/boot KernelFile=vmlinuz InitrdFile=initramfs.cpio.gz diff --git a/sdk/cmake/version.cmake b/sdk/cmake/version.cmake index 141814a..9d57776 100644 --- a/sdk/cmake/version.cmake +++ b/sdk/cmake/version.cmake @@ -9,6 +9,10 @@ set(XTOS_COMPATIBLE_MINOR "3") set(XTOS_COMPATIBLE_VERSION "0x0603") set(XTOS_COMPATIBLE_BUILD "9600") +# Set XTLDR version +set(XTLDR_VERSION_MAJOR "0") +set(XTLDR_VERSION_MINOR "1") + # Set common XTOS version variables string(TIMESTAMP XTOS_VERSION_YEAR %Y) string(TIMESTAMP XTOS_VERSION_DATE "%Y%m%d") diff --git a/sdk/cmake/version/xtver.h.cmake b/sdk/cmake/version/xtver.h.cmake index 3172604..1e34126 100644 --- a/sdk/cmake/version/xtver.h.cmake +++ b/sdk/cmake/version/xtver.h.cmake @@ -29,4 +29,7 @@ #define XTOS_COMPILER_NAME "@CMAKE_C_COMPILER_ID@" #define XTOS_COMPILER_VERSION "@CMAKE_C_COMPILER_VERSION@" +#define XTLDR_VERSION_MAJOR @XTLDR_VERSION_MAJOR@ +#define XTLDR_VERSION_MINOR @XTLDR_VERSION_MINOR@ + #endif /* __XTGEN_XTVER_H */ diff --git a/sdk/xtdk/blfuncs.h b/sdk/xtdk/blfuncs.h new file mode 100644 index 0000000..77e0bf1 --- /dev/null +++ b/sdk/xtdk/blfuncs.h @@ -0,0 +1,23 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: sdk/xtdk/blfuncs.h + * DESCRIPTION: XT Boot Manager routines + * DEVELOPERS: Rafal Kupiec + */ + +#ifndef __XTDK_BLFUNCS_H +#define __XTDK_BLFUNCS_H + +#include +#include + + +/* XT BootLoader routines forward references */ +XTCDECL +EFI_STATUS +BlGetXtLdrProtocol(IN PEFI_SYSTEM_TABLE SystemTable, + IN EFI_HANDLE ImageHandle, + OUT PXTBL_LOADER_PROTOCOL *ProtocolHandler); + +#endif /* __XTDK_BLFUNCS_H */ diff --git a/sdk/xtdk/bltypes.h b/sdk/xtdk/bltypes.h new file mode 100644 index 0000000..25a5127 --- /dev/null +++ b/sdk/xtdk/bltypes.h @@ -0,0 +1,289 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: sdk/xtdk/bltypes.h + * DESCRIPTION: XT Boot Manager structures definitions + * DEVELOPERS: Rafal Kupiec + */ + +#ifndef __XTDK_BLTYPES_H +#define __XTDK_BLTYPES_H + +#include +#include +#include + + +/* Architecture specific definitions */ +#if defined(__i386__) || defined(__i686__) + #define XTBL_ARCH_LOADER_DIRECTORY_PATH L"\\EFI\\BOOT\\XTLDR32\\" + #define XTBL_ARCH_MODULES_DIRECTORY_PATH L"\\EFI\\BOOT\\XTLDR32\\MODULES\\" + #define XTBL_ARCH_THEMES_DIRECTORY_PATH L"\\EFI\\BOOT\\XTLDR32\\THEMES\\" +#elif defined(__amd64__) || defined(__x86_64__) + #define XTBL_ARCH_LOADER_DIRECTORY_PATH L"\\EFI\\BOOT\\XTLDR64\\" + #define XTBL_ARCH_MODULES_DIRECTORY_PATH L"\\EFI\\BOOT\\XTLDR64\\MODULES\\" + #define XTBL_ARCH_THEMES_DIRECTORY_PATH L"\\EFI\\BOOT\\XTLDR64\\THEMES\\" +#else + #error Unknown architecture +#endif + +/* XTLDR directories */ +#define XTBL_LOADER_DIRECTORY_PATH L"\\EFI\\BOOT\\XTLDR\\" +#define XTBL_MODULES_DIRECTORY_PATH L"\\EFI\\BOOT\\XTLDR\\MODULES\\" +#define XTBL_THEMES_DIRECTORY_PATH L"\\EFI\\BOOT\\XTLDR\\THEMES\\" + +/* XTLDR module segment macros */ +#define XTBL_MODDEPS SEGMENT(".moddeps") CONST WCHAR XtBlpDeps[][8] +#define XTBL_MODINFO SEGMENT(".modinfo") CONST WCHAR XtBlpInfo[] + +/* EFI XT boot devices */ +#define XTBL_BOOT_DEVICE_UNKNOWN 0x00 +#define XTBL_BOOT_DEVICE_CDROM 0x01 +#define XTBL_BOOT_DEVICE_FLOPPY 0x02 +#define XTBL_BOOT_DEVICE_HARDDISK 0x03 +#define XTBL_BOOT_DEVICE_RAMDISK 0x04 + +/* XTLDR Debug Port type definitions */ +#define XTBL_DEBUGPORT_SCREEN 1 +#define XTBL_DEBUGPORT_SERIAL 2 + +/* TUI dialog box attributes */ +#define XTBL_TUI_DIALOG_GENERIC_BOX 1 +#define XTBL_TUI_DIALOG_ERROR_BOX 2 +#define XTBL_TUI_DIALOG_ACTIVE_BUTTON 4 +#define XTBL_TUI_DIALOG_INACTIVE_BUTTON 8 +#define XTBL_TUI_DIALOG_ACTIVE_INPUT 16 +#define XTBL_TUI_DIALOG_INACTIVE_INPUT 32 +#define XTBL_TUI_DIALOG_PROGRESS_BAR 64 + +/* TUI dialog box maximum width */ +#define XTBL_TUI_MAX_DIALOG_WIDTH 100 + +/* Boot Loader protocol routine pointers */ +typedef EFI_STATUS (*PBL_ALLOCATE_PAGES)(IN UINT64 Size, OUT PEFI_PHYSICAL_ADDRESS Memory); +typedef EFI_STATUS (*PBL_ALLOCATE_POOL)(IN UINT_PTR Size, OUT PVOID *Memory); +typedef VOID (*PBL_BOOTMENU_INITIALIZE_OS_LIST)(OUT PXTBL_BOOTMENU_ITEM MenuEntries, OUT PULONG EntriesCount, OUT PULONG DefaultId); +typedef EFI_STATUS (*PBL_BOOTPROTO_BOOT_SYSTEM)(IN PXTBL_BOOT_PARAMETERS Parameters); +typedef EFI_STATUS (*PBL_CLOSE_VOLUME)(IN PEFI_HANDLE VolumeHandle); +typedef VOID (*PBL_CLEAR_CONSOLE_LINE)(IN ULONGLONG LineNo); +typedef EFI_STATUS (*PBL_CLOSE_XT_PROTOCOL)(IN PEFI_HANDLE Handle, IN PEFI_GUID ProtocolGuid); +typedef PWCHAR (*PBL_CONFIG_GET_VALUE)(IN CONST PWCHAR ConfigName); +typedef VOID (*PBL_CONSOLE_CLEAR_SCREEN)(); +typedef VOID (*PBL_CONSOLE_DISABLE_CURSOR)(); +typedef VOID (*PBL_CONSOLE_ENABLE_CURSOR)(); +typedef VOID (*PBL_CONSOLE_PRINT)(IN PUINT16 Format, IN ...); +typedef VOID (*PBL_CONSOLE_QUERY_MODE)(OUT PUINT_PTR ResX, OUT PUINT_PTR ResY); +typedef VOID (*PBL_CONSOLE_READ_KEY_STROKE)(OUT PEFI_INPUT_KEY Key); +typedef VOID (*PBL_CONSOLE_RESET_INPUT_BUFFER)(); +typedef VOID (*PBL_CONSOLE_SET_ATTRIBUTES)(IN ULONGLONG Attributes); +typedef VOID (*PBL_CONSOLE_SET_CURSOR_POSITION)(IN ULONGLONG PosX, IN ULONGLONG PosY); +typedef VOID (*PBL_CONSOLE_WRITE)(IN PUSHORT String); +typedef VOID (*PBL_DEBUG_PRINT)(IN PUINT16 Format, IN ...); +typedef EFI_STATUS (*PBL_EXECIMAGE_GET_ENTRY_POINT)(IN PVOID ImagePointer, OUT PVOID *EntryPoint); +typedef EFI_STATUS (*PBL_EXECIMAGE_GET_MACHINE_TYPE)(IN PVOID ImagePointer, OUT PUSHORT MachineType); +typedef EFI_STATUS (*PBL_EXECIMAGE_GET_SUBSYSTEM)(IN PVOID ImagePointer, OUT PUSHORT SubSystem); +typedef EFI_STATUS (*PBL_EXECIMAGE_LOAD_IMAGE)(IN PEFI_FILE_HANDLE FileHandle, IN LOADER_MEMORY_TYPE MemoryType, IN PVOID VirtualAddress, OUT PVOID *ImagePointer); +typedef EFI_STATUS (*PBL_EXECIMAGE_RELOCATE_IMAGE)(IN PVOID ImagePointer, IN EFI_VIRTUAL_ADDRESS Address); +typedef EFI_STATUS (*PBL_EXIT_BOOT_SERVICES)(IN UINT_PTR MapKey); +typedef EFI_STATUS (*PBL_FIND_BOOT_PROTOCOL)(IN PWCHAR SystemType, OUT PEFI_GUID BootProtocolGuid); +typedef EFI_STATUS (*PBL_FREE_PAGES)(IN UINT64 Size, IN EFI_PHYSICAL_ADDRESS Memory); +typedef EFI_STATUS (*PBL_FREE_POOL)(IN PVOID Memory); +typedef EFI_STATUS (*PBL_GET_MEMORY_MAP)(OUT PEFI_MEMORY_MAP MemoryMap); +typedef PLIST_ENTRY (*PBL_GET_MODULES_LIST)(); +typedef INT_PTR (*PBL_GET_SECURE_BOOT_STATUS)(); +typedef EFI_STATUS (*PBL_INSTALL_XT_PROTOCOL)(IN PVOID Interface, IN PEFI_GUID Guid); +typedef EFI_STATUS (*PBL_INVOKE_BOOT_PROTOCOL)(IN PLIST_ENTRY OptionsList); +typedef EFI_STATUS (*PBL_OPEN_VOLUME)(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, OUT PEFI_HANDLE DiskHandle, OUT PEFI_FILE_HANDLE *FsHandle); +typedef EFI_STATUS (*PBL_OPEN_XT_PROTOCOL)(OUT PEFI_HANDLE Handle, OUT PVOID *ProtocolHandler, IN PEFI_GUID ProtocolGuid); +typedef EFI_STATUS (*PBL_READ_FILE)(IN PEFI_FILE_HANDLE DirHandle, IN CONST PWCHAR FileName, OUT PVOID *FileData, OUT PSIZE_T FileSize); +typedef EFI_STATUS (*PBL_REGISTER_BOOT_PROTOCOL)(IN PWCHAR SystemType, IN PEFI_GUID BootProtocolGuid); +typedef VOID (*PBL_REGISTER_XT_BOOT_MENU)(PVOID BootMenuRoutine); +typedef VOID (*PBL_SLEEP_EXECUTION)(IN ULONG_PTR Milliseconds); +typedef VOID (*PBL_TUI_DISPLAY_ERROR_DIALOG)(IN PWCHAR Caption, IN PWCHAR Message); +typedef VOID (*PBL_TUI_DISPLAY_INFO_DIALOG)(IN PWCHAR Caption, IN PWCHAR Message); +typedef VOID (*PBL_TUI_DISPLAY_INPUT_DIALOG)(IN PWCHAR Caption, IN PWCHAR Message, IN PWCHAR *InputFieldText); +typedef XTBL_DIALOG_HANDLE (*PBL_TUI_DISPLAY_PROGRESS_DIALOG)(IN PWCHAR Caption, IN PWCHAR Message, IN UCHAR Percentage); +typedef VOID (*PBL_TUI_UPDATE_PROGRESS_BAR)(IN PXTBL_DIALOG_HANDLE Handle, IN PWCHAR Message, IN UCHAR Percentage); +typedef EFI_STATUS (*PBL_WAIT_FOR_EFI_EVENT)(IN UINT_PTR NumberOfEvents, IN PEFI_EVENT Event, OUT PUINT_PTR Index); +typedef VOID (*PBL_XT_BOOT_MENU)(); + +/* Boot parameters structure */ +typedef struct _XTBL_BOOT_PARAMETERS +{ + PEFI_DEVICE_PATH_PROTOCOL DevicePath; + PWCHAR ArcName; + PWCHAR SystemPath; + PWCHAR SystemType; + PWCHAR KernelFile; + PWCHAR InitrdFile; + PWCHAR HalFile; + PWCHAR Parameters; +} XTBL_BOOT_PARAMETERS, *PXTBL_BOOT_PARAMETERS; + +/* Boot menu list structure */ +typedef struct _XTBL_BOOTMENU_ITEM +{ + PWCHAR EntryName; + PLIST_ENTRY Options; +} XTBL_BOOTMENU_ITEM, *PXTBL_BOOTMENU_ITEM; + +/* XTLDR Configuration data */ +typedef struct _XTBL_CONFIG_ENTRY +{ + LIST_ENTRY Flink; + PWCHAR Name; + PWCHAR Value; +} XTBL_CONFIG_ENTRY, *PXTBL_CONFIG_ENTRY; + +/* XTLDR Configuration section */ +typedef struct _XTBL_CONFIG_SECTION +{ + LIST_ENTRY Flink; + LIST_ENTRY Options; + PWCHAR SectionName; +} XTBL_CONFIG_SECTION, *PXTBL_CONFIG_SECTION; + +/* XTLDR Dialog handle data */ +typedef struct _XTBL_DIALOG_HANDLE +{ + UCHAR Attributes; + UCHAR DialogColor; + UCHAR TextColor; + UINT_PTR ResX; + UINT_PTR ResY; + UINT_PTR PosX; + UINT_PTR PosY; + UINT_PTR Width; + UINT_PTR Height; +} XTBL_DIALOG_HANDLE, *PXTBL_DIALOG_HANDLE; + +/* Registered boot protocol structure */ +typedef struct _XTBL_KNOWN_BOOT_PROTOCOL +{ + LIST_ENTRY Flink; + PWCHAR SystemType; + EFI_GUID Guid; +} XTBL_KNOWN_BOOT_PROTOCOL, *PXTBL_KNOWN_BOOT_PROTOCOL; + +/* XTLDR Module dependencies data */ +typedef struct _XTBL_MODULE_DEPS +{ + LIST_ENTRY Flink; + PWCHAR ModuleName; +} XTBL_MODULE_DEPS, *PXTBL_MODULE_DEPS; + +/* XTLDR Module information data */ +typedef struct _XTBL_MODULE_INFO +{ + LIST_ENTRY Flink; + PWCHAR ModuleName; + PWCHAR ModuleDescription; + LIST_ENTRY Dependencies; + PVOID ModuleBase; + UINT64 ModuleSize; + UINT32 Revision; + PEFI_IMAGE_UNLOAD UnloadModule; +} XTBL_MODULE_INFO, *PXTBL_MODULE_INFO; + +/* XTLDR Status data */ +typedef struct _XTBL_STATUS +{ + PBL_XT_BOOT_MENU BootMenu; + BOOLEAN BootServices; + ULONG DebugPort; + INT_PTR SecureBoot; + CPPORT SerialPort; +} XTBL_STATUS, *PXTBL_STATUS; + +/* XTLDR Boot protocol structure */ +typedef struct _XTBL_BOOT_PROTOCOL +{ + PBL_BOOTPROTO_BOOT_SYSTEM BootSystem; +} XTBL_BOOT_PROTOCOL, *PXTBL_BOOT_PROTOCOL; + +/* XTLDR Executable image protocol structure */ +typedef struct _XTBL_EXECUTABLE_IMAGE_PROTOCOL +{ + PBL_EXECIMAGE_GET_ENTRY_POINT GetEntryPoint; + PBL_EXECIMAGE_GET_MACHINE_TYPE GetMachineType; + // PBL_EXECIMAGE_GET_SECTION GetSection; + PBL_EXECIMAGE_GET_SUBSYSTEM GetSubSystem; + // PBL_EXECIMAGE_GET_VERSION GetVersion; + PBL_EXECIMAGE_LOAD_IMAGE LoadImage; + // PBL_EXECIMAGE_PRINT_INFO PrintDebugInfo; + PBL_EXECIMAGE_RELOCATE_IMAGE RelocateImage; + // PBL_EXECUTABLE_VERIFY_IMAGE VerifyImage; +} XTBL_EXECUTABLE_IMAGE_PROTOCOL, *PXTBL_EXECUTABLE_IMAGE_PROTOCOL; + +/* XTLDR Loader protocol */ +typedef struct _XTBL_LOADER_PROTOCOL +{ + struct + { + PBL_FIND_BOOT_PROTOCOL FindProtocol; + PBL_BOOTMENU_INITIALIZE_OS_LIST InitializeMenuList; + PBL_INVOKE_BOOT_PROTOCOL InvokeProtocol; + PBL_REGISTER_XT_BOOT_MENU RegisterMenu; + PBL_REGISTER_BOOT_PROTOCOL RegisterProtocol; + } Boot; + struct + { + PBL_CONFIG_GET_VALUE GetValue; + } Config; + struct + { + PBL_CLEAR_CONSOLE_LINE ClearLine; + PBL_CONSOLE_CLEAR_SCREEN ClearScreen; + PBL_CONSOLE_DISABLE_CURSOR DisableCursor; + PBL_CONSOLE_ENABLE_CURSOR EnableCursor; + PBL_CONSOLE_PRINT Print; + PBL_CONSOLE_QUERY_MODE QueryMode; + PBL_CONSOLE_READ_KEY_STROKE ReadKeyStroke; + PBL_CONSOLE_RESET_INPUT_BUFFER ResetInputBuffer; + PBL_CONSOLE_SET_ATTRIBUTES SetAttributes; + PBL_CONSOLE_SET_CURSOR_POSITION SetCursorPosition; + PBL_CONSOLE_WRITE Write; + } Console; + struct + { + PBL_DEBUG_PRINT Print; + } Debug; + struct + { + PBL_CLOSE_VOLUME CloseVolume; + PBL_OPEN_VOLUME OpenVolume; + PBL_READ_FILE ReadFile; + } Disk; + struct + { + PBL_ALLOCATE_PAGES AllocatePages; + PBL_ALLOCATE_POOL AllocatePool; + PBL_FREE_PAGES FreePages; + PBL_FREE_POOL FreePool; + PBL_GET_MEMORY_MAP GetMemoryMap; + } Memory; + struct + { + PBL_CLOSE_XT_PROTOCOL Close; + PBL_GET_MODULES_LIST GetModulesList; + PBL_INSTALL_XT_PROTOCOL Install; + PBL_OPEN_XT_PROTOCOL Open; + } Protocol; + struct + { + PBL_TUI_DISPLAY_ERROR_DIALOG DisplayErrorDialog; + PBL_TUI_DISPLAY_INFO_DIALOG DisplayInfoDialog; + PBL_TUI_DISPLAY_INPUT_DIALOG DisplayInputDialog; + PBL_TUI_DISPLAY_PROGRESS_DIALOG DisplayProgressDialog; + PBL_TUI_UPDATE_PROGRESS_BAR UpdateProgressBar; + } Tui; + struct + { + PBL_EXIT_BOOT_SERVICES ExitBootServices; + PBL_GET_SECURE_BOOT_STATUS GetSecureBootStatus; + PBL_SLEEP_EXECUTION SleepExecution; + PBL_WAIT_FOR_EFI_EVENT WaitForEfiEvent; + } Util; +} XTBL_LOADER_PROTOCOL, *PXTBL_LOADER_PROTOCOL; + +#endif /* __XTDK_BLTYPES_H */ diff --git a/sdk/xtdk/xtblapi.h b/sdk/xtdk/xtblapi.h new file mode 100644 index 0000000..e13f9c4 --- /dev/null +++ b/sdk/xtdk/xtblapi.h @@ -0,0 +1,50 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: sdk/xtdk/xtblapi.h + * DESCRIPTION: Top level header for the XT Boot Loader API + * DEVELOPERS: Rafal Kupiec + */ + +/* Base XT headers */ +#include +#include +#include +#include + +/* XT forward references */ +#include + +/* Architecture-specific XT forward references */ +#include ARCH_HEADER(xtstruct.h) + +/* Architecture-independent XT API */ +#include +#include +#include +#include +#include +#include + +/* Architecture independent XT kernel data types */ +#include +#include +#include + +/* Architecture dependent XT kernel data types */ +#include ARCH_HEADER(artypes.h) +#include ARCH_HEADER(hltypes.h) +#include ARCH_HEADER(ketypes.h) +#include ARCH_HEADER(mmtypes.h) + +/* XT Kernel runtime routines */ +#include +#include + +/* Architecture specific XT kernel routines */ +#include ARCH_HEADER(arfuncs.h) +#include ARCH_HEADER(hlfuncs.h) + +/* Boot Manager specific structures */ +#include +#include diff --git a/sdk/xtdk/xtstruct.h b/sdk/xtdk/xtstruct.h index e60aa84..dcc19ab 100644 --- a/sdk/xtdk/xtstruct.h +++ b/sdk/xtdk/xtstruct.h @@ -264,6 +264,18 @@ typedef struct _UEFI_FIRMWARE_INFORMATION UEFI_FIRMWARE_INFORMATION, *PUEFI_FIRM typedef struct _UNICODE_STRING UNICODE_STRING, *PUNICODE_STRING; typedef struct _UNICODE_STRING32 UNICODE_STRING32, *PUNICODE_STRING32; typedef struct _UNICODE_STRING64 UNICODE_STRING64, *PUNICODE_STRING64; +typedef struct _XTBL_BOOT_PARAMETERS XTBL_BOOT_PARAMETERS, *PXTBL_BOOT_PARAMETERS; +typedef struct _XTBL_BOOT_PROTOCOL XTBL_BOOT_PROTOCOL, *PXTBL_BOOT_PROTOCOL; +typedef struct _XTBL_BOOTMENU_ITEM XTBL_BOOTMENU_ITEM, *PXTBL_BOOTMENU_ITEM; +typedef struct _XTBL_CONFIG_ENTRY XTBL_CONFIG_ENTRY, *PXTBL_CONFIG_ENTRY; +typedef struct _XTBL_CONFIG_SECTION XTBL_CONFIG_SECTION, *PXTBL_CONFIG_SECTION; +typedef struct _XTBL_DIALOG_HANDLE XTBL_DIALOG_HANDLE, *PXTBL_DIALOG_HANDLE; +typedef struct _XTBL_EXECUTABLE_IMAGE_PROTOCOL XTBL_EXECUTABLE_IMAGE_PROTOCOL, *PXTBL_EXECUTABLE_IMAGE_PROTOCOL; +typedef struct _XTBL_KNOWN_BOOT_PROTOCOL XTBL_KNOWN_BOOT_PROTOCOL, *PXTBL_KNOWN_BOOT_PROTOCOL; +typedef struct _XTBL_LOADER_PROTOCOL XTBL_LOADER_PROTOCOL, *PXTBL_LOADER_PROTOCOL; +typedef struct _XTBL_MODULE_DEPS XTBL_MODULE_DEPS, *PXTBL_MODULE_DEPS; +typedef struct _XTBL_MODULE_INFO XTBL_MODULE_INFO, *PXTBL_MODULE_INFO; +typedef struct _XTBL_STATUS XTBL_STATUS, *PXTBL_STATUS; /* Unions forward references */ typedef union _EFI_DEV_PATH EFI_DEV_PATH, *PEFI_DEV_PATH; diff --git a/xtldr/CMakeLists.txt b/xtldr/CMakeLists.txt index 17184ba..680f6fe 100644 --- a/xtldr/CMakeLists.txt +++ b/xtldr/CMakeLists.txt @@ -9,19 +9,29 @@ include_directories( ${EXECTOS_SOURCE_DIR}/sdk/xtdk ${XTLDR_SOURCE_DIR}/includes) +# Specify list of library source code files +list(APPEND LIBXTLDR_SOURCE + ${XTLDR_SOURCE_DIR}/library/modproto.c) + # Specify list of source code files list(APPEND XTLDR_SOURCE - ${XTLDR_SOURCE_DIR}/${ARCH}/memory.c - ${XTLDR_SOURCE_DIR}/blproto.c + ${XTLDR_SOURCE_DIR}/config.c ${XTLDR_SOURCE_DIR}/console.c - ${XTLDR_SOURCE_DIR}/efiutil.c + ${XTLDR_SOURCE_DIR}/debug.c + ${XTLDR_SOURCE_DIR}/efiutils.c ${XTLDR_SOURCE_DIR}/globals.c + ${XTLDR_SOURCE_DIR}/hardware.c ${XTLDR_SOURCE_DIR}/memory.c + ${XTLDR_SOURCE_DIR}/protocol.c + ${XTLDR_SOURCE_DIR}/shell.c ${XTLDR_SOURCE_DIR}/string.c - ${XTLDR_SOURCE_DIR}/system.c + ${XTLDR_SOURCE_DIR}/textui.c ${XTLDR_SOURCE_DIR}/volume.c ${XTLDR_SOURCE_DIR}/xtldr.c) +# Link static XTLDR library +add_library(libxtldr ${LIBXTLDR_SOURCE}) + # Link bootloader executable add_executable(xtldr ${XTLDR_SOURCE}) @@ -38,6 +48,7 @@ set_target_properties(xtldr PROPERTIES OUTPUT_NAME ${BINARY_NAME} SUFFIX .efi) set_install_target(xtldr efi/boot) # Set loader entrypoint and subsystem -set_imagebase(xtldr ${BASEADDRESS_XTLDR}) set_entrypoint(xtldr "BlStartXtLoader") +set_imagebase(xtldr ${BASEADDRESS_XTLDR}) +set_linker_map(xtldr TRUE) set_subsystem(xtldr efi_application) diff --git a/xtldr/README.md b/xtldr/README.md index 3d0b51b..38cefcd 100644 --- a/xtldr/README.md +++ b/xtldr/README.md @@ -1,4 +1,4 @@ -## XT Loader (XTLDR) +## XT Boot Loader (XTLDR) The XTLDR, or XTOS Boot Loader, is an EFI (Extensible Firmware Interface) boot loader specifically designed for XTOS. As an EFI boot loader, XTLDR operates exclusively with EFI-based hardware and is not compatible with non-EFI systems, like old and deprecated BIOS. diff --git a/xtldr/blproto.c b/xtldr/blproto.c deleted file mode 100644 index 9d27404..0000000 --- a/xtldr/blproto.c +++ /dev/null @@ -1,96 +0,0 @@ -/** - * PROJECT: ExectOS - * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtldr/blproto.c - * DESCRIPTION: EFI XTLDR protocol API - * DEVELOPERS: Rafal Kupiec - */ - -#include -#include - - -/** - * This routine locates and opens the XT boot loader protocol. - * - * @param LdrProtocol - * Supplies the address where a pointer to the loader protocol is returned. - * - * @return This routine returns status code. - * - * @since XT 1.0 - */ -XTCDECL -EFI_STATUS -BlGetXtLoaderProtocol(OUT PXT_BOOT_LOADER_PROTOCOL *LdrProtocol) -{ - EFI_GUID Guid = XT_BOOT_LOADER_PROTOCOL_GUID; - - /* Load XTLDR protocol */ - return BlLoadXtProtocol((PVOID *)LdrProtocol, &Guid); -} - -/** - * This routine locates and opens the requested XT protocol. - * - * @param ProtocolHandler - * Supplies the address where a pointer to the opened protocol is returned. - * - * @param ProtocolGuid - * Supplies a pointer to the unique protocol GUID. - * - * @return This routine returns status code. - * - * @since XT 1.0 - */ -XTCDECL -EFI_STATUS -BlLoadXtProtocol(OUT PVOID *ProtocolHandler, - IN PEFI_GUID ProtocolGuid) -{ - PEFI_HANDLE Handles = NULL; - EFI_STATUS Status; - UINT_PTR Count; - UINT Index; - - /* Try to locate the handles */ - Status = EfiSystemTable->BootServices->LocateHandleBuffer(ByProtocol, ProtocolGuid, NULL, &Count, &Handles); - if(Status != STATUS_EFI_SUCCESS) - { - /* Unable to get handles */ - return Status; - } - - /* Check if any handles returned */ - if(Count > 0) - { - /* Iterate through all given handles */ - for(Index = 0; Index < Count; Index++) - { - /* Try to open protocol */ - Status = EfiSystemTable->BootServices->OpenProtocol(Handles[Index], ProtocolGuid, - ProtocolHandler, EfiImageHandle, NULL, - EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL); - - /* Check if successfully opened the loader protocol */ - if(Status == STATUS_EFI_SUCCESS) - { - /* Protocol found and successfully opened */ - break; - } - } - } - - /* Free handles */ - EfiSystemTable->BootServices->FreePool(Handles); - - /* Make sure the loaded protocol has been found */ - if(*ProtocolHandler == NULL) - { - /* Protocol not found */ - return STATUS_EFI_NOT_FOUND; - } - - /* Return success */ - return STATUS_EFI_SUCCESS; -} diff --git a/xtldr/config.c b/xtldr/config.c new file mode 100644 index 0000000..c2e8569 --- /dev/null +++ b/xtldr/config.c @@ -0,0 +1,595 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/config.c + * DESCRIPTION: XT Boot Loader Configuration + * DEVELOPERS: Rafal Kupiec + */ + +#include + + +/** + * Returns a value of the specified configuration key. + * + * @param ConfigName + * Specifies the configuration key to return its value. + * + * @return This routine returns a pointer to the configuration value, or NULL if key was not found. + * + * @since XT 1.0 + */ +XTCDECL +PWCHAR +BlGetConfigValue(IN CONST PWCHAR ConfigName) +{ + PXTBL_CONFIG_ENTRY ConfigEntry; + PLIST_ENTRY ConfigListEntry; + SIZE_T KeyLength, ValueLength; + EFI_STATUS Status; + PWCHAR Value; + + /* Get config entry name length */ + KeyLength = RtlWideStringLength(ConfigName, 0); + + /* Iterate through config entries */ + ConfigListEntry = BlpConfig.Flink; + while(ConfigListEntry != &BlpConfig) + { + /* Get config entry */ + ConfigEntry = CONTAIN_RECORD(ConfigListEntry, XTBL_CONFIG_ENTRY, Flink); + + /* Check if requested configuration found */ + if(RtlCompareWideStringInsensitive(ConfigEntry->Name, ConfigName, KeyLength) == 0) + { + /* Get value length */ + ValueLength = RtlWideStringLength(ConfigEntry->Value, 0); + + /* Allocate memory for value */ + Status = BlMemoryAllocatePool(ValueLength * sizeof(WCHAR), (PVOID *)&Value); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory allocation failure, return NULL */ + BlDebugPrint(L"ERROR: Memory allocation failure (Status Code: 0x%lx)\n", Status); + return NULL; + } + + /* Copy value and return it */ + RtlCopyMemory(Value, ConfigEntry->Value, ValueLength * sizeof(WCHAR)); + Value[ValueLength] = 0; + return Value; + } + + /* Move to the next config entry */ + ConfigListEntry = ConfigListEntry->Flink; + } + + /* Config entry not found, return NULL */ + return NULL; +} + +/** + * Updates existing configuration value. + * + * @param ConfigName + * Specifies the configuration key to update. + * + * @param ConfigValue + * Specifies the new configuration value. + * + * @return This routine returns status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlSetConfigValue(IN CONST PWCHAR ConfigName, + IN CONST PWCHAR ConfigValue) +{ + PXTBL_CONFIG_ENTRY ConfigEntry; + PLIST_ENTRY ConfigListEntry; + SIZE_T Length; + + /* Get config entry name length */ + Length = RtlWideStringLength(ConfigName, 0); + + /* Iterate through config entries */ + ConfigListEntry = BlpConfig.Flink; + while(ConfigListEntry != &BlpConfig) + { + /* Get config entry */ + ConfigEntry = CONTAIN_RECORD(ConfigListEntry, XTBL_CONFIG_ENTRY, Flink); + + /* Check if requested configuration found */ + if(RtlCompareWideStringInsensitive(ConfigEntry->Name, ConfigName, Length) == 0) + { + /* Update config value */ + ConfigEntry->Value = ConfigValue; + + /* Return success */ + return STATUS_EFI_SUCCESS; + } + + /* Move to the next config entry */ + ConfigListEntry = ConfigListEntry->Flink; + } + + /* Config entry not found */ + return STATUS_EFI_NOT_FOUND; +} + +/** + * Loads and parses XTLDR configuration file. + * + * @return This routine returns status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlpLoadConfiguration() +{ + PLIST_ENTRY SectionListEntry; + EFI_STATUS Status; + PCHAR ConfigData; + + /* Initialize configuration pointer */ + RtlInitializeListHead(&BlpConfigSections); + + /* Read data from configuration file */ + Status = BlpReadConfigFile(XTBL_LOADER_DIRECTORY_PATH, L"XTLDR.INI", &ConfigData); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to read config file, try with architecture specific directory */ + Status = BlpReadConfigFile(XTBL_ARCH_LOADER_DIRECTORY_PATH, L"XTLDR.INI", &ConfigData); + } + + /* Check if configuration was read successfully */ + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to load configuration */ + BlDebugPrint(L"Failed to load FS0:/EFI/BOOT/XTLDR.INI configuration file (Status Code: 0x%lx)\n", Status); + return Status; + } + + /* Parse configuration data */ + Status = BlpParseConfigFile(ConfigData, &BlpConfigSections); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to parse configuration */ + BlDebugPrint(L"Failed to parse FS0:/EFI/BOOT/XTLDR.INI configuration file (Status Code: 0x%lx)\n", Status); + return Status; + } + + /* Iterate through config sections */ + SectionListEntry = BlpConfigSections.Flink; + while(SectionListEntry != &BlpConfigSections) + { + /* Get config section */ + PXTBL_CONFIG_SECTION Section = CONTAIN_RECORD(SectionListEntry, XTBL_CONFIG_SECTION, Flink); + + /* Look for global XTLDR configuration section */ + if(RtlCompareWideStringInsensitive(Section->SectionName, L"XTLDR", 5) == 0) + { + /* Update global configuration */ + BlpUpdateConfiguration(&Section->Options); + + /* Remove XTLDR section from the list */ + RtlRemoveEntryList(SectionListEntry); + break; + } + + /* Move to the next section */ + SectionListEntry = SectionListEntry->Flink; + } + + /* Update boot menu OS list */ + BlpMenuList = &BlpConfigSections; + + /* Return success */ + return STATUS_EFI_SUCCESS; +} + +/** + * Parses command line arguments and updates global configuration. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlpParseCommandLine(VOID) +{ + EFI_GUID LIPGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID; + PEFI_LOADED_IMAGE_PROTOCOL LoadedImage; + PWCHAR Argument, Key, LastArg, Value; + PXTBL_CONFIG_ENTRY Option; + EFI_STATUS Status; + SIZE_T KeyLength, ValueLength; + LIST_ENTRY Config; + + /* Initialize configuration list */ + RtlInitializeListHead(&Config); + + /* Handle loaded image protocol */ + Status = EfiSystemTable->BootServices->HandleProtocol(EfiImageHandle, &LIPGuid, (PVOID *)&LoadedImage); + if(Status == STATUS_EFI_SUCCESS) + { + /* Check if launched from UEFI shell */ + if(LoadedImage && LoadedImage->LoadOptions) + { + /* Tokenize provided options */ + Argument = RtlTokenizeWideString(LoadedImage->LoadOptions, L" ", &LastArg); + + /* Iterate over all arguments passed to boot loader */ + while(Argument != NULL) + { + /* Store key name */ + Key = Argument; + + /* Find end of the key */ + while(*Argument != '=' && *Argument != 0 && *Argument != '\n') + { + /* Advance to the next character */ + Argument++; + } + + /* Mark end of the key and advance to the next character */ + *Argument = 0; + Argument++; + + /* Store value */ + Value = Argument; + + /* Find end of the value */ + while(*Argument != 0 && *Argument != '\n') + { + /* Advance to the next character */ + Argument++; + } + + /* Mark end of the value and advance to the next character */ + *Argument = 0; + Argument++; + + /* Get length of the key and its value */ + KeyLength = RtlWideStringLength(Key, 0); + ValueLength = RtlWideStringLength(Value, 0); + + /* Check if argument is valid */ + if(KeyLength == 0 || ValueLength == 0) + { + /* Invalid argument, skip to the next one */ + continue; + } + + /* Allocate memory for new option */ + Status = BlMemoryAllocatePool(sizeof(XTBL_CONFIG_ENTRY), (PVOID*)&Option); + if(Status == STATUS_EFI_SUCCESS) + { + /* Allocate more memory for option name */ + Status = BlMemoryAllocatePool(sizeof(PWCHAR) * (KeyLength + 1), (PVOID*)&Option->Name); + if(Status == STATUS_EFI_SUCCESS) + { + /* Allocate even more memory for option value */ + Status = BlMemoryAllocatePool(sizeof(PWCHAR) * (ValueLength + 1), (PVOID*)&Option->Value); + } + } + if(Status != STATUS_EFI_SUCCESS) + { + /* Some memory allocation failed */ + return Status; + } + + /* Set entry name and value */ + RtlCopyMemory(Option->Name, Key, (KeyLength * sizeof(WCHAR))); + RtlCopyMemory(Option->Value, Value, (ValueLength * sizeof(WCHAR))); + Option->Name[KeyLength] = 0; + Option->Value[ValueLength] = 0; + + /* Add entry to the list */ + RtlInsertTailList(&Config, &Option->Flink); + + /* Take next argument */ + Argument = RtlTokenizeWideString(NULL, L" ", &LastArg); + } + + /* Update global configuration */ + BlpUpdateConfiguration(&Config); + } + } + + /* Return success */ + return STATUS_EFI_SUCCESS; +} + +/** + * Parses configuration INI file. + * + * @param RawConfig + * Suplies a pointer to configuration INI file to be parsed. + * + * @param Configuration + * Supplies a pointer to memory region where parsed configuration will be stored. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlpParseConfigFile(IN CONST PCHAR RawConfig, + OUT PLIST_ENTRY Configuration) +{ + SIZE_T SectionLength, KeyLength, ValueLength; + PCHAR InputData, Key, SectionName, Value; + PXTBL_CONFIG_SECTION Section; + PXTBL_CONFIG_ENTRY Option; + EFI_STATUS Status; + + /* Initialize pointers */ + InputData = RawConfig; + Section = NULL; + Option = NULL; + SectionName = NULL; + Key = NULL; + Value = NULL; + + /* Analyze configuration data until end of file is reached */ + while(*InputData != 0) + { + if(*InputData == ';' || *InputData == '#') + { + /* Skip comment until end of the line */ + while(*InputData != 0 && *InputData != '\n') + { + /* Advance to the next character */ + InputData++; + } + } + else if(*InputData == ' ' || *InputData == '\t' || *InputData == '\r' || *InputData == '\n') + { + /* Skip whitespaces */ + InputData++; + } + else if(*InputData == '[') + { + /* Skip leading bracket */ + InputData++; + + /* Store section name */ + SectionName = InputData; + + /* Find end of the section name */ + while(*InputData != ']' && *InputData != 0 && *InputData != '\n') + { + /* Advance to the next character */ + InputData++; + } + + /* Check if end of the section name is reached */ + if(*InputData != ']') + { + /* Section name does not end */ + return STATUS_EFI_INVALID_PARAMETER; + } + + /* Mark end of the section name and advance to the next character */ + *InputData = 0; + InputData++; + + /* Remove leading and trailing spaces from section name */ + SectionName = RtlTrimString(SectionName); + + /* Find length of the section name */ + SectionLength = RtlStringLength(SectionName, 0); + + /* Allocate memory for new section */ + Status = BlMemoryAllocatePool(sizeof(XTBL_CONFIG_SECTION), (PVOID*)&Section); + if(Status == STATUS_EFI_SUCCESS) + { + /* Allocate more memory for section name */ + Status = BlMemoryAllocatePool(sizeof(PWCHAR) * (SectionLength + 1), (PVOID*)&Section->SectionName); + } + if(Status != STATUS_EFI_SUCCESS) + { + /* Some memory allocation failed */ + return Status; + } + + /* Initialize new section and add it to the list */ + RtlInitializeListHead(&Section->Options); + RtlStringToWideString(Section->SectionName, &SectionName, SectionLength + 1); + RtlInsertTailList(Configuration, &Section->Flink); + } + else + { + /* Store key */ + Key = InputData; + + /* Find end of the key */ + while(*InputData != '=' && *InputData != 0 && *InputData != '\n') + { + /* Advance to the next character */ + InputData++; + } + + /* Check if end of the key is reached */ + if(*InputData != '=') + { + /* Key name does not end */ + return STATUS_EFI_INVALID_PARAMETER; + } + + /* Mark end of the key and advance to the next character */ + *InputData = 0; + InputData++; + + /* Skip all leading spaces in the value */ + while(*InputData == ' ') + { + /* Advance to the next character */ + InputData++; + } + + /* Store value */ + Value = InputData; + + /* Find end of the value */ + while(*InputData != 0 && *InputData != '\n') + { + /* Advance to the next character */ + InputData++; + } + + /* Mark end of the value and advance to the next character */ + *InputData = 0; + InputData++; + + /* Remove leading and trailing spaces from key and value */ + Key = RtlTrimString(Key); + Value = RtlTrimString(Value); + + /* Find length of the key and its value */ + KeyLength = RtlStringLength(Key, 0); + ValueLength = RtlStringLength(Value, 0); + + /* Allocate memory for new option */ + Status = BlMemoryAllocatePool(sizeof(XTBL_CONFIG_ENTRY), (PVOID*)&Option); + if(Status == STATUS_EFI_SUCCESS) + { + /* Allocate more memory for option name */ + Status = BlMemoryAllocatePool(sizeof(PWCHAR) * (KeyLength + 1), (PVOID*)&Option->Name); + if(Status == STATUS_EFI_SUCCESS) + { + /* Allocate even more memory for option value */ + Status = BlMemoryAllocatePool(sizeof(PWCHAR) * (ValueLength + 1), (PVOID*)&Option->Value); + } + } + if(Status != STATUS_EFI_SUCCESS) + { + /* Some memory allocation failed */ + return Status; + } + + /* Remove leading quotes from the value */ + if(*Value == '"' || *Value == '\'') + { + Value++; + } + + /* Remove trailing quotes from the value */ + if(Value[ValueLength - 2] == '"' || Value[ValueLength - 2] == '\'') + { + Value[ValueLength - 2] = 0; + } + + /* Initialize new option and add it to the list */ + RtlStringToWideString(Option->Name, &Key, RtlStringLength(Key, 0) + 1); + RtlStringToWideString(Option->Value, &Value, RtlStringLength(Value, 0) + 1); + RtlInsertTailList(&Section->Options, &Option->Flink); + } + } + + /* Return success */ + return STATUS_EFI_SUCCESS; +} + +/** + * Loads configuration file from the specified directory on the FS0:/ drive. + * + * @param ConfigDirectory + * Specifies a path to the directory containing the configuration file. + * + * @param ConfigFile + * Specifies the name of the configuration file. + * + * @param ConfigData + * Provides a buffer to store the data read from the configuration file. + * + * @return This routine returns status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlpReadConfigFile(IN CONST PWCHAR ConfigDirectory, + IN CONST PWCHAR ConfigFile, + OUT PCHAR *ConfigData) +{ + PEFI_FILE_HANDLE DirHandle, FsHandle; + EFI_HANDLE DiskHandle; + EFI_STATUS Status; + SIZE_T FileSize; + + /* Open EFI volume */ + Status = BlOpenVolume(NULL, &DiskHandle, &FsHandle); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to open a volume */ + return Status; + } + + /* Open specified directory, containing the configuration file and close the FS immediately */ + Status = FsHandle->Open(FsHandle, &DirHandle, ConfigDirectory, EFI_FILE_MODE_READ, 0); + FsHandle->Close(FsHandle); + + /* Check if directory opened successfully */ + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to open directory */ + BlCloseVolume(DiskHandle); + return Status; + } + + /* Read configuration file and close directory */ + Status = BlReadFile(DirHandle, ConfigFile, (PVOID *)ConfigData, &FileSize); + DirHandle->Close(DirHandle); + + /* Close EFI volume */ + BlCloseVolume(DiskHandle); + + /* Return read status */ + return Status; +} + +/** + * Adds new XTLDR configuration entries to the global configuration list. Existing entries are not overwritten. + * + * @param NewConfig + * Supplies a pointer to a linked list containing new configuration entries. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlpUpdateConfiguration(IN PLIST_ENTRY NewConfig) +{ + PXTBL_CONFIG_ENTRY ConfigEntry; + PLIST_ENTRY ConfigListEntry, NextListEntry; + + /* Iterate through new config entries */ + ConfigListEntry = NewConfig->Flink; + while(ConfigListEntry != NewConfig) + { + /* Get new config entry */ + ConfigEntry = CONTAIN_RECORD(ConfigListEntry, XTBL_CONFIG_ENTRY, Flink); + + /* Get next config entry */ + NextListEntry = ConfigListEntry->Flink; + + /* Make sure config entry does not exist yet */ + if(BlGetConfigValue(ConfigEntry->Name) == NULL) + { + /* Remove new config entry from input list and put it into global config list */ + RtlRemoveEntryList(&ConfigEntry->Flink); + RtlInsertTailList(&BlpConfig, &ConfigEntry->Flink); + } + + /* Move to the next new config entry */ + ConfigListEntry = NextListEntry; + } +} diff --git a/xtldr/console.c b/xtldr/console.c index 52fc096..8d7bca3 100644 --- a/xtldr/console.c +++ b/xtldr/console.c @@ -6,9 +6,37 @@ * DEVELOPERS: Rafal Kupiec */ -#include +#include +/** + * Clears a specified line on the UEFI text console. + * + * @param LineNo + * Supplies a line number to clear. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlClearConsoleLine(IN ULONGLONG LineNo) +{ + UINT_PTR Index, ResX, ResY; + + /* Query console mode */ + BlQueryConsoleMode(&ResX, &ResY); + + /* Set cursor position and clear line */ + BlSetCursorPosition(0, LineNo); + for(Index = 0; Index < ResX; Index++) + { + /* Clear line */ + BlConsoleWrite(L" "); + } +} + /** * This routine clears the UEFI console screen. * @@ -18,32 +46,233 @@ */ XTCDECL VOID -BlConsoleClearScreen() +BlClearConsoleScreen() { + /* Clear screen */ EfiSystemTable->ConOut->ClearScreen(EfiSystemTable->ConOut); } /** - * This routine initializes the EFI console. - * - * @return This routine returns status code. - * + * Disables the cursor on the UEFI console. + * + * @return This routine does not return any value. + * * @since XT 1.0 */ XTCDECL VOID -BlConsoleInitialize() +BlDisableConsoleCursor() +{ + EfiSystemTable->ConOut->EnableCursor(EfiSystemTable->ConOut, FALSE); +} + +/** + * Enables the cursor on the UEFI console. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlEnableConsoleCursor() +{ + EfiSystemTable->ConOut->EnableCursor(EfiSystemTable->ConOut, TRUE); +} + +/** + * This routine formats the input string and prints it out to the stdout and serial console. + * + * @param Format + * The formatted string that is to be written to the output. + * + * @param ... + * Depending on the format string, this routine might expect a sequence of additional arguments. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlConsolePrint(IN PUINT16 Format, + IN ...) +{ + VA_LIST Arguments; + + /* Initialise the va_list */ + VA_START(Arguments, Format); + + /* Format and print the string to the stdout */ + BlpStringPrint(BlpConsolePrintChar, Format, Arguments); + + /* Print to serial console only if not running under OVMF */ + if(RtlCompareWideString(EfiSystemTable->FirmwareVendor, L"EDK II", 6) != 0) + { + /* Check if debugging enabled and if EFI serial port is fully initialized */ + if(DEBUG && (BlpStatus.SerialPort.Flags & COMPORT_FLAG_INIT)) + { + /* Format and print the string to the serial console */ + BlpStringPrint(BlpDebugPutChar, Format, Arguments); + } + } + + /* Clean up the va_list */ + VA_END(Arguments); +} + +/** + * Displays the string on the device at the current cursor location. + * + * @param String + * The string to be displayed. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlConsoleWrite(IN PUSHORT String) +{ + EfiSystemTable->ConOut->OutputString(EfiSystemTable->ConOut, String); +} + +/** + * This routine initializes the EFI console. + * + * @return This routine returns status code. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlInitializeConsole() { /* Clear console buffers */ EfiSystemTable->ConIn->Reset(EfiSystemTable->ConIn, TRUE); EfiSystemTable->ConOut->Reset(EfiSystemTable->ConOut, TRUE); EfiSystemTable->StdErr->Reset(EfiSystemTable->StdErr, TRUE); - /* Clear screen */ - BlConsoleClearScreen(); + /* Make sure that current console mode is 80x25 characters, as some broken EFI implementations might + * set different mode that do not fit on the screen, causing a text to be displayed offscreen */ + if(EfiSystemTable->ConOut->Mode->Mode != 0) + { + /* Set console mode to 0, which is standard, 80x25 text mode */ + BlSetConsoleMode(0); + } - /* Enable cursor */ - EfiSystemTable->ConOut->EnableCursor(EfiSystemTable->ConOut, TRUE); + /* Clear screen and enable cursor */ + BlSetConsoleAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_LIGHTGRAY); + BlClearConsoleScreen(); + BlEnableConsoleCursor(); +} + +/** + * Queries information concerning the output device’s supported text mode. + * + * @param ResX + * Supplies a buffer to receive the horizontal resolution. + * + * @param ResY + * Supplies a buffer to receive the vertical resolution. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlQueryConsoleMode(OUT PUINT_PTR ResX, + OUT PUINT_PTR ResY) +{ + EfiSystemTable->ConOut->QueryMode(EfiSystemTable->ConOut, EfiSystemTable->ConOut->Mode->Mode, ResX, ResY); +} + +/** + * Reads a keystroke from the input device. + * + * @param Key + * Supplies a pointer to the EFI_INPUT_KEY structure that will receive the keystroke. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlReadKeyStroke(OUT PEFI_INPUT_KEY Key) +{ + EfiSystemTable->ConIn->ReadKeyStroke(EfiSystemTable->ConIn, Key); +} + +/** + * Resets the console input device and clears its input buffer. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlResetConsoleInputBuffer() +{ + EfiSystemTable->ConIn->Reset(EfiSystemTable->ConIn, FALSE); +} + +/** + * Sets the foreground and background colors. + * + * @param Attribute + * Specifies the foreground and background colors (bits 0..3 are fg, and bits 4..6 are bg color). + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlSetConsoleAttributes(IN ULONGLONG Attributes) +{ + EfiSystemTable->ConOut->SetAttribute(EfiSystemTable->ConOut, Attributes); +} + +/** + * Sets the output console device to the requested mode. + * + * @param Mode + * Supplies a text mode number to set. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlSetConsoleMode(IN ULONGLONG Mode) +{ + return EfiSystemTable->ConOut->SetMode(EfiSystemTable->ConOut, Mode); +} + +/** + * Sets new coordinates of the console cursor position. + * + * @param PosX + * Specifies the new X coordinate of the cursor. + * + * @param PosY + * Specifies the new Y coordinate of the cursor. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlSetCursorPosition(IN ULONGLONG PosX, + IN ULONGLONG PosY) +{ + EfiSystemTable->ConOut->SetCursorPosition(EfiSystemTable->ConOut, PosX, PosY); } /** @@ -58,7 +287,7 @@ BlConsoleInitialize() */ XTCDECL VOID -BlConsolePutChar(IN USHORT Character) +BlpConsolePrintChar(IN USHORT Character) { USHORT Buffer[2]; diff --git a/xtldr/debug.c b/xtldr/debug.c new file mode 100644 index 0000000..221c649 --- /dev/null +++ b/xtldr/debug.c @@ -0,0 +1,263 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/debug.c + * DESCRIPTION: XT Boot Loader debugging support + * DEVELOPERS: Rafal Kupiec + */ + +#include + + +/** + * This routine formats the input string and prints it out to the debug ports. + * + * @param Format + * The formatted string that is to be written to the output. + * + * @param ... + * Depending on the format string, this routine might expect a sequence of additional arguments. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlDebugPrint(IN PUINT16 Format, + IN ...) +{ + VA_LIST Arguments; + + /* Check if debugging enabled and if EFI serial port is fully initialized */ + if(DEBUG) + { + /* Initialise the va_list */ + VA_START(Arguments, Format); + + /* Check if serial debug port is enabled */ + if((BlpStatus.DebugPort & XTBL_DEBUGPORT_SERIAL) && (BlpStatus.SerialPort.Flags & COMPORT_FLAG_INIT)) + { + /* Format and print the string to the serial console */ + BlpStringPrint(BlpDebugPutChar, Format, Arguments); + } + + /* Check if screen debug port is enabled and Boot Services are still available */ + if((BlpStatus.DebugPort & XTBL_DEBUGPORT_SCREEN) && (BlpStatus.BootServices == TRUE)) + { + /* Format and print the string to the screen */ + BlpStringPrint(BlpConsolePrintChar, Format, Arguments); + } + + /* Clean up the va_list */ + VA_END(Arguments); + } +} + +/** + * This routine initializes the XTLDR debug console. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlpInitializeDebugConsole() +{ + ULONG PortAddress, PortNumber, BaudRate; + PWCHAR DebugConfiguration, DebugPort, LastPort; + EFI_STATUS Status; + + /* Set default serial port options */ + PortAddress = 0; + PortNumber = 0; + BaudRate = 0; + + /* Get debug configuration */ + DebugConfiguration = BlGetConfigValue(L"DEBUG"); + + /* Make sure any debug options are provided and debug console is not initialized yet */ + if(DebugConfiguration && BlpStatus.DebugPort == 0) + { + /* Find all debug ports */ + DebugPort = RtlTokenizeWideString(DebugConfiguration, L";", &LastPort); + + /* Iterate over all debug ports */ + while(DebugPort != NULL) + { + /* Check what port is set for debugging */ + if(RtlCompareWideStringInsensitive(DebugPort, L"COM", 3) == 0) + { + /* Read COM port number */ + DebugPort += 3; + while(*DebugPort >= '0' && *DebugPort <= '9') + { + /* Get port number */ + PortNumber *= 10; + PortNumber += *DebugPort - '0'; + DebugPort++; + } + + /* Check if custom COM port address supplied */ + if(PortNumber == 0 && RtlCompareWideStringInsensitive(DebugPort, L":0x", 3) == 0) + { + /* COM port address provided */ + DebugPort += 3; + while((*DebugPort >= '0' && *DebugPort <= '9') || + (*DebugPort >= 'A' && *DebugPort <= 'F') || + (*DebugPort >= 'a' && *DebugPort <= 'f')) + { + /* Get port address */ + PortAddress *= 16; + if(*DebugPort >= '0' && *DebugPort <= '9') + { + PortAddress += *DebugPort - '0'; + } + else if(*DebugPort >= 'A' && *DebugPort <= 'F') + { + PortAddress += *DebugPort - 'A' + 10; + } + else if(*DebugPort >= 'a' && *DebugPort <= 'f') + { + PortAddress += *DebugPort - 'a' + 10; + } + DebugPort++; + } + } + + /* Look for additional COM port parameters */ + if(*DebugPort == ',') + { + /* Baud rate provided */ + DebugPort++; + while(*DebugPort >= '0' && *DebugPort <= '9') + { + /* Get baud rate */ + BaudRate *= 10; + BaudRate += *DebugPort - '0'; + DebugPort++; + } + } + + /* Enable debug port */ + BlpStatus.DebugPort |= XTBL_DEBUGPORT_SERIAL; + } + else if(RtlCompareWideStringInsensitive(DebugPort, L"SCREEN", 5) == 0) + { + /* Enable debug port */ + BlpStatus.DebugPort |= XTBL_DEBUGPORT_SCREEN; + } + else + { + /* Unsupported debug port specified */ + BlConsolePrint(L"ERROR: Unsupported debug port ('%S') specified\n", DebugPort); + BlSleepExecution(3000); + } + + /* Take next debug port */ + DebugPort = RtlTokenizeWideString(NULL, L";", &LastPort); + } + + /* Check if serial debug port is enabled */ + if(BlpStatus.DebugPort & XTBL_DEBUGPORT_SERIAL) + { + /* Try to initialize COM port */ + Status = BlpInitializeSerialPort(PortNumber, PortAddress, BaudRate); + if(Status != STATUS_EFI_SUCCESS) + { + /* Remove serial debug port, as COM port initialization failed and return */ + BlpStatus.DebugPort &= ~XTBL_DEBUGPORT_SERIAL; + return Status; + } + } + } + + /* Return success */ + return STATUS_EFI_SUCCESS; +} + +/** + * This routine initializes the serial debug console. + * + * @param PortNumber + * Supplies a port number. + * + * @param PortAddress + * Supplies an address of the COM port. + * + * @param BaudRate + * Supplies an optional port baud rate. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlpInitializeSerialPort(IN ULONG PortNumber, + IN ULONG PortAddress, + IN ULONG BaudRate) +{ + EFI_STATUS EfiStatus; + XTSTATUS Status; + + /* Print debug message depending on port settings */ + if(PortAddress) + { + BlConsolePrint(L"Initializing serial console at COM port address: 0x%lx\n", PortAddress); + } + else + { + BlConsolePrint(L"Initializing serial console at port COM%d\n", PortNumber); + } + + /* Initialize COM port */ + Status = HlInitializeComPort(&BlpStatus.SerialPort, PortNumber, UlongToPtr(PortAddress), BaudRate); + + /* Port not found under supplied address */ + if(Status == STATUS_NOT_FOUND && PortAddress) + { + /* This might be PCI(E) serial controller, try to activate I/O space access first */ + EfiStatus = BlpActivateSerialIOController(); + if(EfiStatus == STATUS_EFI_SUCCESS) + { + /* Try to reinitialize COM port */ + BlConsolePrint(L"Enabled I/O space access for all PCI(E) serial controllers found\n"); + Status = HlInitializeComPort(&BlpStatus.SerialPort, PortNumber, UlongToPtr(PortAddress), BaudRate); + } + } + + /* Check COM port initialization status code */ + if(Status != STATUS_SUCCESS) + { + /* Serial port initialization failed, mark as not ready */ + return STATUS_EFI_NOT_READY; + } + + /* Return success */ + return STATUS_EFI_SUCCESS; +} + +/** + * Writes a character to the serial console. + * + * @param Character + * The integer promotion of the character to be written. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlpDebugPutChar(IN USHORT Character) +{ + USHORT Buffer[2]; + + /* Write character to the serial console */ + Buffer[0] = Character; + Buffer[1] = 0; + + HlComPortPutByte(&BlpStatus.SerialPort, Buffer[0]); +} diff --git a/xtldr/efiutil.c b/xtldr/efiutil.c deleted file mode 100644 index 39d01a3..0000000 --- a/xtldr/efiutil.c +++ /dev/null @@ -1,364 +0,0 @@ -/** - * PROJECT: ExectOS - * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtldr/efiutil.c - * DESCRIPTION: EFI utilities - * DEVELOPERS: Rafal Kupiec - */ - -#include - - -/** - * Enables I/O space access to all serial controllers found on the PCI(E) root bridge. - * - * @return This routine returns a status code. - * - * @since XT 1.0 - */ -XTCDECL -EFI_STATUS -BlActivateSerialControllerIO() -{ - EFI_GUID PciGuid = EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID; - PEFI_PCI_ROOT_BRIDGE_IO_PROTOCOL PciDev; - USHORT Bus, Device, Function, Command; - UINT_PTR Index, PciHandleSize; - PEFI_HANDLE PciHandle = NULL; - PCI_COMMON_HEADER PciHeader; - EFI_STATUS Status; - UINT64 Address; - - /* Allocate memory for single EFI_HANDLE, what should be enough in most cases */ - PciHandleSize = sizeof(EFI_HANDLE); - Status = BlEfiMemoryAllocatePool(PciHandleSize, (PVOID*)&PciHandle); - if(Status != STATUS_EFI_SUCCESS) - { - /* Memory allocation failure */ - return Status; - } - - /* Get all instances of PciRootBridgeIo */ - Status = EfiSystemTable->BootServices->LocateHandle(ByProtocol, &PciGuid, NULL, &PciHandleSize, PciHandle); - if(Status == STATUS_EFI_BUFFER_TOO_SMALL) - { - /* Reallocate more memory as requested by UEFI */ - BlEfiMemoryFreePool(PciHandle); - Status = BlEfiMemoryAllocatePool(PciHandleSize, (PVOID*)&PciHandle); - if(Status != STATUS_EFI_SUCCESS) - { - /* Memory reallocation failure */ - return Status; - } - - /* Second attempt to get instances of PciRootBridgeIo */ - Status = EfiSystemTable->BootServices->LocateHandle(ByProtocol, &PciGuid, NULL, &PciHandleSize, PciHandle); - } - - /* Make sure successfully obtained PciRootBridgeIo instances */ - if(Status != STATUS_EFI_SUCCESS) - { - /* Failed to get PciRootBridgeIo instances */ - return Status; - } - - /* Enumerate all devices for each handle, which decides a segment and a bus number range */ - for(Index = 0; Index < (PciHandleSize / sizeof(EFI_HANDLE)); Index++) - { - /* Get inferface from the protocol */ - Status = EfiSystemTable->BootServices->HandleProtocol(PciHandle[Index], &PciGuid, (PVOID*)&PciDev); - if(Status != STATUS_EFI_SUCCESS) - { - /* Failed to get interface */ - return Status; - } - - /* Enumerate whole PCI bridge */ - for(Bus = 0; Bus <= PCI_MAX_BRIDGE_NUMBER; Bus++) - { - /* Enumerate all devices for each bus */ - for(Device = 0; Device < PCI_MAX_DEVICES; Device++) - { - /* Enumerate all functions for each devices */ - for(Function = 0; Function < PCI_MAX_FUNCTION; Function++) - { - /* Read configuration space */ - Address = ((UINT64)((((UINT_PTR) Bus) << 24) + (((UINT_PTR) Device) << 16) + - (((UINT_PTR) Function) << 8) + ((UINT_PTR) 0))); - PciDev->Pci.Read(PciDev, 2, Address, sizeof (PciHeader) / sizeof (UINT32), &PciHeader); - - /* Check if device exists */ - if(PciHeader.VendorId == PCI_INVALID_VENDORID) - { - /* Skip non-existen device */ - continue; - } - - /* Check if device is serial controller or multiport serial controller */ - if(PciHeader.BaseClass == 0x07 && (PciHeader.SubClass == 0x00 || PciHeader.SubClass == 0x02)) - { - /* Enable I/O space access */ - Address |= 0x4; - Command = PCI_ENABLE_IO_SPACE; - Status = PciDev->Pci.Write(PciDev, 1, Address, 1, &Command); - } - } - } - } - } - - /* Return SUCCESS */ - return STATUS_EFI_SUCCESS; -} - -/** - * This routine initializes the COM port debug console. - * - * @return This routine returns a status code. - * - * @since XT 1.0 - */ -XTCDECL -EFI_STATUS -BlComPortInitialize() -{ - EFI_GUID LIPGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID; - PEFI_LOADED_IMAGE_PROTOCOL LoadedImage; - ULONG PortAddress, PortNumber, BaudRate; - PWCHAR Argument, CommandLine, LastArg; - EFI_STATUS EfiStatus; - XTSTATUS Status; - - /* Set default serial port options */ - PortAddress = 0; - PortNumber = 0; - BaudRate = 0; - - /* Handle loaded image protocol */ - EfiStatus = EfiSystemTable->BootServices->HandleProtocol(EfiImageHandle, &LIPGuid, (PVOID *)&LoadedImage); - if(EfiStatus == STATUS_EFI_SUCCESS) - { - - /* Check if launched from UEFI shell */ - if(LoadedImage && LoadedImage->LoadOptions) - { - /* Store arguments passed from UEFI shell */ - CommandLine = (PWCHAR)LoadedImage->LoadOptions; - - /* Find command in command line */ - Argument = RtlTokenizeWideString(CommandLine, L" ", &LastArg); - - /* Iterate over all arguments passed to boot loader */ - while(Argument != NULL) - { - /* Check if this is DEBUG parameter */ - if(RtlCompareWideString(Argument, L"DEBUG=", 6) == 0) - { - /* Skip to the argument value */ - Argument += 6; - - /* Make sure COM port is being used */ - if(RtlCompareWideString(Argument, L"COM", 3)) - { - /* Invalid debug port specified */ - BlEfiPrint(L"ERROR: Invalid debug port specified, falling back to defaults\n"); - break; - } - - /* Read COM port number */ - Argument += 3; - while(*Argument >= '0' && *Argument <= '9') - { - /* Get port number */ - PortNumber *= 10; - PortNumber += *Argument - '0'; - Argument++; - } - - /* Check if custom COM port address supplied */ - if(PortNumber == 0 && RtlCompareWideString(Argument, L":0x", 3) == 0) - { - /* COM port address provided */ - Argument += 3; - while((*Argument >= '0' && *Argument <= '9') || - (*Argument >= 'A' && *Argument <= 'F') || - (*Argument >= 'a' && *Argument <= 'f')) - { - /* Get port address */ - PortAddress *= 16; - if(*Argument >= '0' && *Argument <= '9') - { - PortAddress += *Argument - '0'; - } - else if(*Argument >= 'A' && *Argument <= 'F') - { - PortAddress += *Argument - 'A' + 10; - } - else if(*Argument >= 'a' && *Argument <= 'f') - { - PortAddress += *Argument - 'a' + 10; - } - Argument++; - } - } - - /* Look for additional COM port parameters */ - if(*Argument == ',') - { - /* Baud rate provided */ - Argument++; - while(*Argument >= '0' && *Argument <= '9') - { - /* Get baud rate */ - BaudRate *= 10; - BaudRate += *Argument - '0'; - Argument++; - } - } - - /* No need to check next arguments */ - break; - } - - /* Take next argument */ - Argument = RtlTokenizeWideString(NULL, L" ", &LastArg); - } - } - } - - /* Print debug message depending on port settings */ - if(PortAddress) - { - BlEfiPrint(L"Initializing serial console at COM port address: 0x%lx\n", PortAddress); - } - else - { - BlEfiPrint(L"Initializing serial console at port COM%d\n", PortNumber); - } - - /* Initialize COM port */ - Status = HlInitializeComPort(&EfiSerialPort, PortNumber, UlongToPtr(PortAddress), BaudRate); - - /* Port not found under supplied address */ - if(Status == STATUS_NOT_FOUND && PortAddress) - { - /* This might be PCI(E) serial controller, try to activate I/O space access first */ - EfiStatus = BlActivateSerialControllerIO(); - if(EfiStatus == STATUS_EFI_SUCCESS) - { - /* Try to reinitialize COM port */ - BlEfiPrint(L"Enabled I/O space access for all PCI(E) serial controllers found\n"); - Status = HlInitializeComPort(&EfiSerialPort, PortNumber, UlongToPtr(PortAddress), BaudRate); - } - } - - /* Check COM port initialization status code */ - if(Status != STATUS_SUCCESS) - { - /* Serial port initialization failed, mark as not ready */ - return STATUS_EFI_NOT_READY; - } - - /* Return success */ - return STATUS_EFI_SUCCESS; -} - -/** - * Writes a character to the serial console. - * - * @param Character - * The integer promotion of the character to be written. - * - * @return This routine does not return any value. - * - * @since XT 1.0 - */ -XTCDECL -VOID -BlComPortPutChar(IN USHORT Character) -{ - USHORT Buffer[2]; - - /* Write character to the serial console */ - Buffer[0] = Character; - Buffer[1] = 0; - - HlComPortPutByte(&EfiSerialPort, Buffer[0]); -} - -/** - * This routine formats the input string and prints it out to the serial console. - * - * @param Format - * The formatted string that is to be written to the output. - * - * @param ... - * Depending on the format string, this routine might expect a sequence of additional arguments. - * - * @return This routine does not return any value. - * - * @since XT 1.0 - */ -XTCDECL -VOID -BlDbgPrint(IN PUINT16 Format, - IN ...) -{ - VA_LIST Arguments; - - /* Check if debugging enabled and if EFI serial port is fully initialized */ - if(DEBUG && (EfiSerialPort.Flags & COMPORT_FLAG_INIT)) - { - /* Initialise the va_list */ - VA_START(Arguments, Format); - - /* Format and print the string to the serial console */ - BlStringPrint(BlComPortPutChar, Format, Arguments); - - /* Clean up the va_list */ - VA_END(Arguments); - } -} - -/** - * This routine formats the input string and prints it out to the stdout and serial console. - * - * @param Format - * The formatted string that is to be written to the output. - * - * @param ... - * Depending on the format string, this routine might expect a sequence of additional arguments. - * - * @return This routine does not return any value. - * - * @since XT 1.0 - * - * @todo Check if GOP is active and use it instead of default conout protocol - */ -XTCDECL -VOID -BlEfiPrint(IN PUINT16 Format, - IN ...) -{ - VA_LIST Arguments; - - /* Initialise the va_list */ - VA_START(Arguments, Format); - - /* Format and print the string to the stdout */ - BlStringPrint(BlConsolePutChar, Format, Arguments); - - /* Print to serial console only if not running under OVMF */ - if(RtlCompareWideString(EfiSystemTable->FirmwareVendor, L"EDK II", 6) != 0) - { - /* Check if debugging enabled and if EFI serial port is fully initialized */ - if(DEBUG && (EfiSerialPort.Flags & COMPORT_FLAG_INIT)) - { - /* Format and print the string to the serial console */ - BlStringPrint(BlComPortPutChar, Format, Arguments); - } - } - - /* Clean up the va_list */ - VA_END(Arguments); -} diff --git a/xtldr/efiutils.c b/xtldr/efiutils.c new file mode 100644 index 0000000..34dac18 --- /dev/null +++ b/xtldr/efiutils.c @@ -0,0 +1,120 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/efiutils.c + * DESCRIPTION: EFI related routines for XT Boot Loader + * DEVELOPERS: Rafal Kupiec + */ + +#include + + +/** + * Exits EFI boot services. + * + * @param MapKey + * Identifies the current memory map of the system. + * + * @return This routine returns status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlExitBootServices(IN UINT_PTR MapKey) +{ + EFI_STATUS Status; + + /* Attempt to exit boot services */ + Status = EfiSystemTable->BootServices->ExitBootServices(EfiImageHandle, MapKey); + if(Status != STATUS_EFI_SUCCESS) + { + /* Retry as UEFI spec says to do it twice */ + Status = EfiSystemTable->BootServices->ExitBootServices(EfiImageHandle, MapKey); + } + + /* Make sure boot services were successfully exited */ + if(Status == STATUS_EFI_SUCCESS) + { + /* Mark EFI Boot Services as no longer available */ + BlpStatus.BootServices = FALSE; + } + + /* Return EFI status code */ + return Status; +} + +/** + * Checks whether SecureBoot is enabled or not. + * + * @return Numeric representation of SecureBoot status (0 = Disabled, >0 = Enabled, <0 SetupMode). + * + * @since XT 1.0 + */ +XTCDECL +INT_PTR +BlGetSecureBootStatus() +{ + EFI_GUID VarGuid = EFI_GLOBAL_VARIABLE_GUID; + INT_PTR SecureBootStatus = 0; + UCHAR VarValue = 0; + UINT_PTR Size; + + Size = sizeof(VarValue); + if(EfiSystemTable->RuntimeServices->GetVariable(L"SecureBoot", &VarGuid, + NULL, &Size, &VarValue) == STATUS_EFI_SUCCESS) + { + SecureBootStatus = (INT_PTR)VarValue; + + if((EfiSystemTable->RuntimeServices->GetVariable(L"SetupMode", &VarGuid, + NULL, &Size, &VarValue) == STATUS_EFI_SUCCESS) && VarValue != 0) + { + SecureBootStatus = -1; + } + } + + /* Return SecureBoot status */ + return SecureBootStatus; +} + +/** + * Puts the system to sleep for the specified number of milliseconds. + * + * @param Milliseconds + * Supplies the number of milliseconds to sleep. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlSleepExecution(IN ULONG_PTR Milliseconds) +{ + EfiSystemTable->BootServices->Stall(Milliseconds * 1000); +} + +/** + * Waits for one or more EFI events. + * + * @param NumberOfEvents + * Supplies the number of events to wait for. + * + * @param Event + * Supplies the array of events to wait for. + * + * @param Index + * Receives the index of the event that was signaled. + * + * @return This routine returns status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlWaitForEfiEvent(IN UINT_PTR NumberOfEvents, + IN PEFI_EVENT Event, + OUT PUINT_PTR Index) +{ + return EfiSystemTable->BootServices->WaitForEvent(NumberOfEvents, Event, Index); +} diff --git a/xtldr/globals.c b/xtldr/globals.c index 04d0740..4a6a286 100644 --- a/xtldr/globals.c +++ b/xtldr/globals.c @@ -6,26 +6,38 @@ * DEVELOPERS: Rafal Kupiec */ -#include +#include +/* XT Boot Loader registered boot protocol list */ +LIST_ENTRY BlpBootProtocols; + +/* XT Boot Loader configuration list */ +LIST_ENTRY BlpConfig; + +/* XT Boot Loader loaded configuration */ +LIST_ENTRY BlpConfigSections; + +/* XT Boot Loader hex table */ +STATIC PUINT16 BlpHexTable = L"0123456789ABCDEF"; + +/* XT Boot Loader protocol */ +XTBL_LOADER_PROTOCOL BlpLdrProtocol; + +/* XT Boot Loader loaded modules list */ +LIST_ENTRY BlpLoadedModules; + +/* XT Boot Loader menu list */ +PLIST_ENTRY BlpMenuList = NULL; + +/* XT Boot Loader status data */ +XTBL_STATUS BlpStatus = {0}; + /* List of available block devices */ LIST_ENTRY EfiBlockDevices; -/* XT Boot Loader hex table */ -STATIC PUINT16 EfiHexTable = L"0123456789ABCDEF"; - /* EFI Image Handle */ EFI_HANDLE EfiImageHandle; -/* XT Boot Loader protocol */ -XT_BOOT_LOADER_PROTOCOL EfiLdrProtocol; - /* EFI System Table */ PEFI_SYSTEM_TABLE EfiSystemTable; - -/* EFI Secure Boot status */ -INT_PTR EfiSecureBoot; - -/* Serial port configuration */ -CPPORT EfiSerialPort; diff --git a/xtldr/hardware.c b/xtldr/hardware.c new file mode 100644 index 0000000..4b6e6b7 --- /dev/null +++ b/xtldr/hardware.c @@ -0,0 +1,112 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/hardware.c + * DESCRIPTION: EFI hardware support for XT Boot Loader + * DEVELOPERS: Rafal Kupiec + */ + +#include + + +/** + * Enables I/O space access to all serial controllers found on the PCI(E) root bridge. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlpActivateSerialIOController() +{ + EFI_GUID PciGuid = EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID; + PEFI_PCI_ROOT_BRIDGE_IO_PROTOCOL PciDev; + USHORT Bus, Device, Function, Command; + UINT_PTR Index, PciHandleSize; + PEFI_HANDLE PciHandle = NULL; + PCI_COMMON_HEADER PciHeader; + EFI_STATUS Status; + UINT64 Address; + + /* Allocate memory for single EFI_HANDLE, what should be enough in most cases */ + PciHandleSize = sizeof(EFI_HANDLE); + Status = BlMemoryAllocatePool(PciHandleSize, (PVOID*)&PciHandle); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory allocation failure */ + return Status; + } + + /* Get all instances of PciRootBridgeIo */ + Status = EfiSystemTable->BootServices->LocateHandle(ByProtocol, &PciGuid, NULL, &PciHandleSize, PciHandle); + if(Status == STATUS_EFI_BUFFER_TOO_SMALL) + { + /* Reallocate more memory as requested by UEFI */ + BlMemoryFreePool(PciHandle); + Status = BlMemoryAllocatePool(PciHandleSize, (PVOID*)&PciHandle); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory reallocation failure */ + return Status; + } + + /* Second attempt to get instances of PciRootBridgeIo */ + Status = EfiSystemTable->BootServices->LocateHandle(ByProtocol, &PciGuid, NULL, &PciHandleSize, PciHandle); + } + + /* Make sure successfully obtained PciRootBridgeIo instances */ + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to get PciRootBridgeIo instances */ + return Status; + } + + /* Enumerate all devices for each handle, which decides a segment and a bus number range */ + for(Index = 0; Index < (PciHandleSize / sizeof(EFI_HANDLE)); Index++) + { + /* Get inferface from the protocol */ + Status = EfiSystemTable->BootServices->HandleProtocol(PciHandle[Index], &PciGuid, (PVOID*)&PciDev); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to get interface */ + return Status; + } + + /* Enumerate whole PCI bridge */ + for(Bus = 0; Bus <= PCI_MAX_BRIDGE_NUMBER; Bus++) + { + /* Enumerate all devices for each bus */ + for(Device = 0; Device < PCI_MAX_DEVICES; Device++) + { + /* Enumerate all functions for each devices */ + for(Function = 0; Function < PCI_MAX_FUNCTION; Function++) + { + /* Read configuration space */ + Address = ((UINT64)((((UINT_PTR) Bus) << 24) + (((UINT_PTR) Device) << 16) + + (((UINT_PTR) Function) << 8) + ((UINT_PTR) 0))); + PciDev->Pci.Read(PciDev, 2, Address, sizeof (PciHeader) / sizeof (UINT32), &PciHeader); + + /* Check if device exists */ + if(PciHeader.VendorId == PCI_INVALID_VENDORID) + { + /* Skip non-existen device */ + continue; + } + + /* Check if device is serial controller or multiport serial controller */ + if(PciHeader.BaseClass == 0x07 && (PciHeader.SubClass == 0x00 || PciHeader.SubClass == 0x02)) + { + /* Enable I/O space access */ + Address |= 0x4; + Command = PCI_ENABLE_IO_SPACE; + Status = PciDev->Pci.Write(PciDev, 1, Address, 1, &Command); + } + } + } + } + } + + /* Return SUCCESS */ + return STATUS_EFI_SUCCESS; +} diff --git a/xtldr/includes/bldefs.h b/xtldr/includes/bldefs.h deleted file mode 100644 index 2ff44cb..0000000 --- a/xtldr/includes/bldefs.h +++ /dev/null @@ -1,22 +0,0 @@ -/** - * PROJECT: ExectOS - * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtldr/includes/bldefs.h - * DESCRIPTION: Definitions for the XT boot loader - * DEVELOPERS: Rafal Kupiec - */ - -#ifndef __XTLDR_BLDEFS_H -#define __XTLDR_BLDEFS_H - -#include - - -/* EFI XT boot devices */ -#define XT_BOOT_DEVICE_UNKNOWN 0x00 -#define XT_BOOT_DEVICE_CDROM 0x01 -#define XT_BOOT_DEVICE_FLOPPY 0x02 -#define XT_BOOT_DEVICE_HARDDISK 0x03 -#define XT_BOOT_DEVICE_RAMDISK 0x04 - -#endif /* __XTLDR_BLDEFS_H */ diff --git a/xtldr/includes/blmod.h b/xtldr/includes/blmod.h deleted file mode 100644 index 4138dba..0000000 --- a/xtldr/includes/blmod.h +++ /dev/null @@ -1,94 +0,0 @@ -/** - * PROJECT: ExectOS - * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtldr/includes/blmod.h - * DESCRIPTION: Top level header for XTLDR modules support - * DEVELOPERS: Rafal Kupiec - */ - -#ifndef __XTLDR_BLMOD_H -#define __XTLDR_BLMOD_H - -#include -#include -#include - - -/* Structures forward declarations */ -typedef struct _XT_BOOT_PROTOCOL XT_BOOT_PROTOCOL, *PXT_BOOT_PROTOCOL; -typedef struct _XT_BOOT_PROTOCOL_PARAMETERS XT_BOOT_PROTOCOL_PARAMETERS, *PXT_BOOT_PROTOCOL_PARAMETERS; -typedef struct _XT_PECOFFF_IMAGE_PROTOCOL XT_PECOFF_IMAGE_PROTOCOL, *PXT_PECOFF_IMAGE_PROTOCOL; - -/* Pointers to the routines provided by the modules */ -typedef EFI_STATUS (*PXT_BOOTPROTO_BOOT_SYSTEM)(IN PXT_BOOT_PROTOCOL_PARAMETERS Parameters); -typedef VOID (*PXT_FRAMEBUFFER_GET_DISPLAY_DRIVER)(OUT PWCHAR *DriverName); -typedef VOID (*PXT_FRAMEBUFFER_GET_DISPLAY_INFORMATION)(OUT PLOADER_GRAPHICS_INFORMATION_BLOCK InformationBlock); -typedef EFI_STATUS (*PXT_FRAMEBUFFER_INITIALIZE)(); -typedef VOID (*PXT_FRAMEBUFFER_PRINT_DISPLAY_INFORMATION)(); -typedef EFI_STATUS (*PXT_PECOFF_GET_ENTRY_POINT)(IN PPECOFF_IMAGE_CONTEXT Image, OUT PVOID *EntryPoint); -typedef EFI_STATUS (*PXT_PECOFF_GET_MACHINE_TYPE)(IN PPECOFF_IMAGE_CONTEXT Image, OUT PUSHORT MachineType); -typedef EFI_STATUS (*PXT_PECOFF_GET_SUBSYSTEM)(IN PPECOFF_IMAGE_CONTEXT Image, OUT PUSHORT SubSystem); -typedef EFI_STATUS (*PXT_PECOFF_LOAD_IMAGE)(IN PEFI_FILE_HANDLE FileHandle, IN LOADER_MEMORY_TYPE MemoryType, - IN PVOID VirtualAddress, OUT PPECOFF_IMAGE_CONTEXT *Image); -typedef EFI_STATUS (*PXT_PECOFF_RELOCATE_IMAGE)(IN PPECOFF_IMAGE_CONTEXT Image, IN EFI_VIRTUAL_ADDRESS Address); - - -/* XT common boot protocols */ -typedef struct _XT_BOOT_PROTOCOL -{ - PXT_BOOTPROTO_BOOT_SYSTEM BootSystem; -} XT_BOOT_PROTOCOL, *PXT_BOOT_PROTOCOL; - -/* XT common boot protocol parameters */ -typedef struct _XT_BOOT_PROTOCOL_PARAMETERS -{ - PEFI_DEVICE_PATH_PROTOCOL DevicePath; - PWCHAR ArcName; - PWCHAR SystemPath; - PWCHAR KernelFile; - PWCHAR InitrdFile; - PWCHAR HalFile; - PWCHAR Arguments; -} XT_BOOT_PROTOCOL_PARAMETERS, *PXT_BOOT_PROTOCOL_PARAMETERS; - -/* XT framebuffer support protocol */ -typedef struct _XT_FRAMEBUFFER_PROTOCOL -{ - PXT_FRAMEBUFFER_GET_DISPLAY_DRIVER GetDisplayDriver; - PXT_FRAMEBUFFER_GET_DISPLAY_INFORMATION GetDisplayInformation; - PXT_FRAMEBUFFER_INITIALIZE Initialize; - PXT_FRAMEBUFFER_PRINT_DISPLAY_INFORMATION PrintDisplayInformation; -} XT_FRAMEBUFFER_PROTOCOL, *PXT_FRAMEBUFFER_PROTOCOL; - -/* XT framebuffer information structure definition */ -typedef struct _XT_FRAMEBUFFER_INFORMATION -{ - BOOLEAN Initialized; - EFI_GRAPHICS_PROTOCOL Protocol; - union - { - PEFI_GRAPHICS_OUTPUT_PROTOCOL GOP; - PEFI_UNIVERSAL_GRAPHICS_ADAPTER_PROTOCOL UGA; - } Adapter; - UINT HorizontalResolution; - UINT VerticalResolution; - UINT BitsPerPixel; - UINT BytesPerPixel; - UINT PixelsPerScanLine; - UINT Pitch; - EFI_GRAPHICS_PIXEL_FORMAT PixelFormat; - EFI_PHYSICAL_ADDRESS FrameBufferBase; - ULONG_PTR FrameBufferSize; -} XT_FRAMEBUFFER_INFORMATION, *PXT_FRAMEBUFFER_INFORMATION; - -/* EFI XT PE/COFF Image Protocol */ -typedef struct _XT_PECOFFF_IMAGE_PROTOCOL -{ - PXT_PECOFF_GET_ENTRY_POINT GetEntryPoint; - PXT_PECOFF_GET_MACHINE_TYPE GetMachineType; - PXT_PECOFF_GET_SUBSYSTEM GetSubSystem; - PXT_PECOFF_LOAD_IMAGE Load; - PXT_PECOFF_RELOCATE_IMAGE Relocate; -} XT_PECOFF_IMAGE_PROTOCOL, *PXT_PECOFF_IMAGE_PROTOCOL; - -#endif /* __XTLDR_BLMOD_H */ diff --git a/xtldr/includes/blproto.h b/xtldr/includes/blproto.h deleted file mode 100644 index 8b82e8c..0000000 --- a/xtldr/includes/blproto.h +++ /dev/null @@ -1,62 +0,0 @@ -/** - * PROJECT: ExectOS - * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtldr/includes/blproto.h - * DESCRIPTION: XTLDR boot loader protocol support - * DEVELOPERS: Rafal Kupiec - */ - -#ifndef __XTLDR_BLPROTO_H -#define __XTLDR_BLPROTO_H - -#include -#include - - -/* Loader protocol routine pointers */ -typedef EFI_STATUS (*PBL_ADD_VIRTUAL_MEMORY_MAPPING)(IN PLIST_ENTRY MemoryMappings, IN PVOID VirtualAddress, IN PVOID PhysicalAddress, IN UINT NumberOfPages, IN LOADER_MEMORY_TYPE MemoryType); -typedef EFI_STATUS (*PBL_ALLOCATE_PAGES)(IN UINT64 Size, OUT PEFI_PHYSICAL_ADDRESS Memory); -typedef EFI_STATUS (*PBL_ALLOCATE_POOL)(IN UINT_PTR Size, OUT PVOID *Memory); -typedef EFI_STATUS (*PBL_ENABLE_PAGING)(IN PLIST_ENTRY MemoryMappings, IN PVOID VirtualAddress, IN PEFI_LOADED_IMAGE_PROTOCOL ImageProtocol, IN PVOID *PtePointer); -typedef EFI_STATUS (*PBL_FREE_PAGES)(IN UINT64 Size, IN EFI_PHYSICAL_ADDRESS Memory); -typedef EFI_STATUS (*PBL_FREE_POOL)(IN PVOID Memory); -typedef EFI_STATUS (*PBL_GET_MEMORY_MAP)(OUT PEFI_MEMORY_MAP MemoryMap); -typedef EFI_STATUS (*PBL_GET_VIRTUAL_ADDRESS)(IN PLIST_ENTRY MemoryMappings, IN PVOID PhysicalAddress, OUT PVOID *VirtualAddress); -typedef EFI_STATUS (*PBL_INIT_VIRTUAL_MEMORY)(IN OUT PLIST_ENTRY MemoryMappings, IN OUT PVOID *MemoryMapAddress); -typedef EFI_STATUS (*PBL_MAP_VIRTUAL_MEMORY)(IN PLIST_ENTRY MemoryMappings, IN UINT_PTR VirtualAddress, IN UINT_PTR PhysicalAddress, IN UINT NumberOfPages, IN OUT PVOID *PtePointer); -typedef VOID (*PBL_GET_STACK)(OUT PVOID *Stack); -typedef VOID (*PBL_DBG_PRINT)(IN PUINT16 Format, IN ...); -typedef VOID (*PBL_EFI_PRINT)(IN PUINT16 Format, IN ...); -typedef EFI_STATUS (*PBL_CLOSE_VOLUME)(IN PEFI_HANDLE VolumeHandle); -typedef EFI_STATUS (*PBL_OPEN_VOLUME)(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, OUT PEFI_HANDLE DiskHandle, OUT PEFI_FILE_HANDLE *FsHandle); - -/* EFI XT Boot Loader Protocol */ -typedef struct _XT_BOOT_LOADER_PROTOCOL -{ - PBL_ADD_VIRTUAL_MEMORY_MAPPING AddVirtualMemoryMapping; - PBL_ALLOCATE_PAGES AllocatePages; - PBL_ALLOCATE_POOL AllocatePool; - PBL_FREE_PAGES FreePages; - PBL_FREE_POOL FreePool; - PBL_ENABLE_PAGING EnablePaging; - PBL_GET_MEMORY_MAP GetMemoryMap; - PBL_GET_VIRTUAL_ADDRESS GetVirtualAddress; - PBL_INIT_VIRTUAL_MEMORY InitializeVirtualMemory; - PBL_MAP_VIRTUAL_MEMORY MapVirtualMemory; - PBL_DBG_PRINT DbgPrint; - PBL_EFI_PRINT EfiPrint; - PBL_CLOSE_VOLUME CloseVolume; - PBL_OPEN_VOLUME OpenVolume; -} XT_BOOT_LOADER_PROTOCOL, *PXT_BOOT_LOADER_PROTOCOL; - -/* Loader protocol related routines forward references */ -XTCDECL -EFI_STATUS -BlGetXtLoaderProtocol(OUT PXT_BOOT_LOADER_PROTOCOL *LdrProtocol); - -XTCDECL -EFI_STATUS -BlLoadXtProtocol(OUT PVOID *ProtocolHandler, - IN PEFI_GUID ProtocolGuid); - -#endif /* __XTLDR_BLPROTO_H */ diff --git a/xtldr/includes/globals.h b/xtldr/includes/globals.h new file mode 100644 index 0000000..172ec21 --- /dev/null +++ b/xtldr/includes/globals.h @@ -0,0 +1,48 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/includes/globals.h + * DESCRIPTION: XTLDR global variables + * DEVELOPERS: Rafal Kupiec + */ + +#ifndef __XTLDR_GLOBALS_H +#define __XTLDR_GLOBALS_H + +#include + + +/* XT Boot Loader registered boot protocol list */ +EXTERN LIST_ENTRY BlpBootProtocols; + +/* XT Boot Loader configuration list */ +EXTERN LIST_ENTRY BlpConfig; + +/* XT Boot Loader loaded configuration */ +EXTERN LIST_ENTRY BlpConfigSections; + +/* XT Boot Loader hex table */ +EXTERN PUINT16 BlpHexTable; + +/* XT Boot Loader protocol */ +EXTERN XTBL_LOADER_PROTOCOL BlpLdrProtocol; + +/* XT Boot Loader loaded modules list */ +EXTERN LIST_ENTRY BlpLoadedModules; + +/* XT Boot Loader menu list */ +EXTERN PLIST_ENTRY BlpMenuList; + +/* XT Boot Loader status data */ +EXTERN XTBL_STATUS BlpStatus; + +/* List of available block devices */ +EXTERN LIST_ENTRY EfiBlockDevices; + +/* EFI Image Handle */ +EXTERN EFI_HANDLE EfiImageHandle; + +/* EFI System Table */ +EXTERN PEFI_SYSTEM_TABLE EfiSystemTable; + +#endif /* __XTLDR_GLOBALS_H */ diff --git a/xtldr/includes/xtbl.h b/xtldr/includes/xtbl.h deleted file mode 100644 index 40ccc62..0000000 --- a/xtldr/includes/xtbl.h +++ /dev/null @@ -1,264 +0,0 @@ -/** - * PROJECT: ExectOS - * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtldr/includes/xtbl.h - * DESCRIPTION: Top level header for XTLDR - * DEVELOPERS: Rafal Kupiec - */ - -#ifndef __XTLDR_XTBL_H -#define __XTLDR_XTBL_H - -#include -#include -#include - - -/* List of available block devices */ -EXTERN LIST_ENTRY EfiBlockDevices; - -/* XT Boot Loader hex table */ -EXTERN PUINT16 EfiHexTable; - -/* EFI Image Handle */ -EXTERN EFI_HANDLE EfiImageHandle; - -/* XT Boot Loader protocol */ -EXTERN XT_BOOT_LOADER_PROTOCOL EfiLdrProtocol; - -/* EFI System Table */ -EXTERN PEFI_SYSTEM_TABLE EfiSystemTable; - -/* EFI Secure Boot status */ -EXTERN INT_PTR EfiSecureBoot; - -/* New bootloader stack */ -EXTERN PVOID EfiLoaderStack; - -/* Serial port configuration */ -EXTERN CPPORT EfiSerialPort; - -XTCDECL -EFI_STATUS -BlActivateSerialControllerIO(); - -XTCDECL -EFI_STATUS -BlAddVirtualMemoryMapping(IN PLIST_ENTRY MemoryMappings, - IN PVOID VirtualAddress, - IN PVOID PhysicalAddress, - IN UINT NumberOfPages, - IN LOADER_MEMORY_TYPE MemoryType); - -XTCDECL -EFI_STATUS -BlCloseVolume(IN PEFI_HANDLE VolumeHandle); - -XTCDECL -EFI_STATUS -BlComPortInitialize(); - -XTCDECL -VOID -BlComPortPutChar(IN USHORT Character); - -XTCDECL -VOID -BlConsoleClearScreen(); - -XTCDECL -VOID -BlConsoleInitialize(); - -XTCDECL -VOID -BlConsolePutChar(IN USHORT Character); - -XTCDECL -LOADER_MEMORY_TYPE -BlConvertEfiMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType); - -XTCDECL -VOID -BlDbgPrint(IN PUINT16 Format, - IN ...); - -XTCDECL -INT_PTR -BlEfiGetSecureBootStatus(); - -XTCDECL -EFI_STATUS -BlEfiGetSystemConfigurationTable(IN PEFI_GUID TableGuid, - OUT PVOID *Table); - -XTCDECL -EFI_STATUS -BlEfiMemoryAllocatePages(IN UINT64 Size, - OUT PEFI_PHYSICAL_ADDRESS Memory); - -XTCDECL -EFI_STATUS -BlEfiMemoryAllocatePool(IN UINT_PTR Size, - OUT PVOID *Memory); - -XTCDECL -EFI_STATUS -BlEfiMemoryFreePages(IN UINT64 Size, - IN EFI_PHYSICAL_ADDRESS Memory); - -XTCDECL -EFI_STATUS -BlEfiMemoryFreePool(IN PVOID Memory); - -XTCDECL -VOID -BlEfiPrint(IN PUINT16 Format, - IN ...); - -XTCDECL -EFI_STATUS -BlEnablePaging(IN PLIST_ENTRY MemoryMappings, - IN PVOID VirtualAddress, - IN PEFI_LOADED_IMAGE_PROTOCOL ImageProtocol, - IN PVOID *PtePointer); - -XTCDECL -EFI_STATUS -BlEnumerateEfiBlockDevices(); - -XTCDECL -EFI_STATUS -BlFindVolumeDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL FsHandle, - IN CONST PWCHAR FileSystemPath, - OUT PEFI_DEVICE_PATH_PROTOCOL* DevicePath); - -XTCDECL -EFI_STATUS -BlGetMemoryMap(OUT PEFI_MEMORY_MAP MemoryMap); - -XTCDECL -EFI_STATUS -BlGetVirtualAddress(IN PLIST_ENTRY MemoryMappings, - IN PVOID PhysicalAddress, - OUT PVOID *VirtualAddress); - -XTCDECL -EFI_STATUS -BlGetVolumeDevicePath(IN PUCHAR SystemPath, - OUT PEFI_DEVICE_PATH_PROTOCOL *DevicePath, - OUT PUCHAR *ArcName, - OUT PUCHAR *Path); - -XTCDECL -EFI_STATUS -BlInitializeVirtualMemory(IN OUT PLIST_ENTRY MemoryMappings, - IN OUT PVOID *MemoryMapAddress); - -XTCDECL -EFI_STATUS -BlLoadEfiModules(); - -XTCDECL -EFI_STATUS -BlLoadXtSystem(); - -XTCDECL -EFI_STATUS -BlMapVirtualMemory(IN PLIST_ENTRY MemoryMappings, - IN UINT_PTR VirtualAddress, - IN UINT_PTR PhysicalAddress, - IN UINT NumberOfPages, - IN OUT PVOID *PtePointer); - -XTCDECL -EFI_STATUS -BlOpenVolume(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, - OUT PEFI_HANDLE DiskHandle, - OUT PEFI_FILE_HANDLE *FsHandle); - -XTCDECL -EFI_STATUS -BlRegisterXtLoaderProtocol(); - -XTCDECL -EFI_STATUS -BlStartXtLoader(IN EFI_HANDLE ImageHandle, - IN PEFI_SYSTEM_TABLE SystemTable); - -XTCDECL -INT -BlStringCompareInsensitive(IN PUCHAR String1, - IN PUCHAR String2); - -XTCDECL -VOID -BlStringPrint(IN VOID PutChar(IN USHORT Character), - IN PUINT16 Format, - IN VA_LIST Arguments); - -XTCDECL -EFI_STATUS -BlpDiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices); - -XTCDECL -EFI_STATUS -BlpDissectVolumeArcPath(IN PUCHAR SystemPath, - OUT PUCHAR *ArcName, - OUT PUCHAR *Path, - OUT PUSHORT DriveType, - OUT PULONG DriveNumber, - OUT PULONG PartNumber); - -XTCDECL -PEFI_DEVICE_PATH_PROTOCOL -BlpDuplicateDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath); - -XTCDECL -EFI_STATUS -BlpFindLastEfiBlockDeviceNode(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, - OUT PEFI_DEVICE_PATH_PROTOCOL *LastNode); - -XTCDECL -BOOLEAN -BlpFindParentEfiBlockDevice(IN PLIST_ENTRY BlockDevices, - IN PEFI_BLOCK_DEVICE_DATA ChildNode, - OUT PEFI_BLOCK_DEVICE_DATA ParentNode); - -XTCDECL -VOID -BlpStringFormat(IN VOID PutChar(IN USHORT Character), - IN PUINT16 Format, - IN ...); - -XTCDECL -VOID -BlpStringPrintSigned32(IN VOID PutChar(IN USHORT Character), - IN INT32 Number, - IN UINT32 Base); - -XTCDECL -VOID -BlpStringPrintSigned64(IN VOID PutChar(IN USHORT Character), - IN INT_PTR Number, - IN UINT_PTR Base); - -XTCDECL -VOID -BlpStringPrintUnsigned32(IN VOID PutChar(IN USHORT Character), - IN UINT32 Number, - IN UINT32 Base, - IN UINT32 Padding); - -XTCDECL -VOID -BlpStringPrintUnsigned64(IN VOID PutChar(IN USHORT Character), - IN UINT_PTR Number, - IN UINT_PTR Base, - IN UINT_PTR Padding); - -XTCDECL -UINT64 -BlpStringReadPadding(IN PUINT16 *Format); - -#endif /* __XTLDR_XTBL_H */ diff --git a/xtldr/includes/xtldr.h b/xtldr/includes/xtldr.h new file mode 100644 index 0000000..bcb9a49 --- /dev/null +++ b/xtldr/includes/xtldr.h @@ -0,0 +1,422 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/includes/xtldr.h + * DESCRIPTION: Top level header for XTLDR + * DEVELOPERS: Rafal Kupiec + */ + +#ifndef __XTLDR_XTLDR_H +#define __XTLDR_XTLDR_H + +#include +#include + +#include + + +/* XTLDR routine callbacks */ +typedef VOID (BLPRINTCHAR)(IN USHORT Character); + +/* XTLDR routines forward references */ +XTCDECL +VOID +BlClearConsoleLine(IN ULONGLONG LineNo); + +XTCDECL +VOID +BlClearConsoleScreen(); + +XTCDECL +EFI_STATUS +BlCloseVolume(IN PEFI_HANDLE VolumeHandle); + +XTCDECL +VOID +BlConsolePrint(IN PUINT16 Format, + IN ...); + +XTCDECL +VOID +BlConsoleWrite(IN PUSHORT String); + +XTCDECL +VOID +BlDebugPrint(IN PUINT16 Format, + IN ...); + +XTCDECL +VOID +BlDisableConsoleCursor(); + +XTCDECL +VOID +BlDisplayBootMenu(); + +XTCDECL +VOID +BlDisplayErrorDialog(IN PWCHAR Caption, + IN PWCHAR Message); + +XTCDECL +VOID +BlDisplayInfoDialog(IN PWCHAR Caption, + IN PWCHAR Message); + +XTCDECL +VOID +BlDisplayInputDialog(IN PWCHAR Caption, + IN PWCHAR Message, + IN OUT PWCHAR *InputFieldText); + +XTCDECL +XTBL_DIALOG_HANDLE +BlDisplayProgressDialog(IN PWCHAR Caption, + IN PWCHAR Message, + IN UCHAR Percentage); + +XTCDECL +VOID +BlEnableConsoleCursor(); + +XTCDECL +EFI_STATUS +BlEnumerateBlockDevices(); + +XTCDECL +EFI_STATUS +BlExitBootServices(IN UINT_PTR MapKey); + +XTCDECL +EFI_STATUS +BlFindBootProtocol(IN PWCHAR SystemType, + OUT PEFI_GUID BootProtocolGuid); + +XTCDECL +EFI_STATUS +BlFindVolumeDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL FsHandle, + IN CONST PWCHAR FileSystemPath, + OUT PEFI_DEVICE_PATH_PROTOCOL* DevicePath); + +XTCDECL +PWCHAR +BlGetConfigValue(IN CONST PWCHAR ConfigName); + +XTCDECL +EFI_STATUS +BlGetMemoryMap(OUT PEFI_MEMORY_MAP MemoryMap); + +XTCDECL +PLIST_ENTRY +BlGetModulesList(); + +XTCDECL +INT_PTR +BlGetSecureBootStatus(); + +XTCDECL +EFI_STATUS +BlGetVolumeDevicePath(IN PWCHAR SystemPath, + OUT PEFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT PWCHAR *ArcName, + OUT PWCHAR *Path); + +XTCDECL +VOID +BlInitializeBootLoader(); + +XTCDECL +VOID +BlInitializeBootMenuList(OUT PXTBL_BOOTMENU_ITEM MenuEntries, + OUT PULONG EntriesCount, + OUT PULONG DefaultId); + +XTCDECL +VOID +BlInitializeConsole(); + +XTCDECL +EFI_STATUS +BlInvokeBootProtocol(IN PLIST_ENTRY OptionsList); + +XTCDECL +EFI_STATUS +BlLoadModule(IN PWCHAR ModuleName); + +XTCDECL +EFI_STATUS +BlLoadModules(IN PWCHAR ModulesList); + +XTCDECL +EFI_STATUS +BlMemoryAllocatePages(IN UINT64 Pages, + OUT PEFI_PHYSICAL_ADDRESS Memory); + +XTCDECL +EFI_STATUS +BlMemoryAllocatePool(IN UINT_PTR Size, + OUT PVOID *Memory); + +XTCDECL +EFI_STATUS +BlMemoryFreePages(IN UINT64 Pages, + IN EFI_PHYSICAL_ADDRESS Memory); + +XTCDECL +EFI_STATUS +BlMemoryFreePool(IN PVOID Memory); + +XTCDECL +EFI_STATUS +BlOpenVolume(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, + OUT PEFI_HANDLE DiskHandle, + OUT PEFI_FILE_HANDLE *FsHandle); + +XTCDECL +EFI_STATUS +BlOpenProtocol(OUT PEFI_HANDLE Handle, + OUT PVOID *ProtocolHandler, + IN PEFI_GUID ProtocolGuid); + +XTCDECL +VOID +BlQueryConsoleMode(OUT PUINT_PTR ResX, + OUT PUINT_PTR ResY); + +XTCDECL +EFI_STATUS +BlReadFile(IN PEFI_FILE_HANDLE DirHandle, + IN CONST PWCHAR FileName, + OUT PVOID *FileData, + OUT PSIZE_T FileSize); + +XTCDECL +VOID +BlReadKeyStroke(OUT PEFI_INPUT_KEY Key); + +XTCDECL +VOID +BlRegisterBootMenu(PVOID BootMenuRoutine); + +XTCDECL +EFI_STATUS +BlRegisterBootProtocol(IN PWCHAR SystemType, + IN PEFI_GUID BootProtocolGuid); + +XTCDECL +EFI_STATUS +BlInstallProtocol(IN PVOID Interface, + IN PEFI_GUID Guid); + +XTCDECL +VOID +BlResetConsoleInputBuffer(); + +XTCDECL +EFI_STATUS +BlSetConfigValue(IN CONST PWCHAR ConfigName, + IN CONST PWCHAR ConfigValue); + +XTCDECL +VOID +BlSetConsoleAttributes(IN ULONGLONG Attributes); + +XTCDECL +EFI_STATUS +BlSetConsoleMode(IN ULONGLONG Mode); + +XTCDECL +VOID +BlSetCursorPosition(IN ULONGLONG PosX, + IN ULONGLONG PosY); + +XTCDECL +VOID +BlSleepExecution(IN ULONG_PTR Milliseconds); + +XTCDECL +VOID +BlStartLoaderShell(); + +XTCDECL +EFI_STATUS +BlStartXtLoader(IN EFI_HANDLE ImageHandle, + IN PEFI_SYSTEM_TABLE SystemTable); + +XTCDECL +VOID +BlUpdateProgressBar(IN PXTBL_DIALOG_HANDLE Handle, + IN PWCHAR Message, + IN UCHAR Percentage); + +XTCDECL +EFI_STATUS +BlWaitForEfiEvent(IN UINT_PTR NumberOfEvents, + IN PEFI_EVENT Event, + OUT PUINT_PTR Index); + +XTCDECL +EFI_STATUS +BlpActivateSerialIOController(); + +XTCDECL +VOID +BlpConsolePrintChar(IN USHORT Character); + +XTCDECL +VOID +BlpDebugPutChar(IN USHORT Character); + +XTCDECL +VOID +BlpDetermineDialogBoxSize(IN OUT PXTBL_DIALOG_HANDLE Handle, + IN PWCHAR Message); + +XTCDECL +EFI_STATUS +BlpDiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices); + +XTCDECL +EFI_STATUS +BlpDissectVolumeArcPath(IN PWCHAR SystemPath, + OUT PWCHAR *ArcName, + OUT PWCHAR *Path, + OUT PUSHORT DriveType, + OUT PULONG DriveNumber, + OUT PULONG PartNumber); + +XTCDECL +VOID +BlpDrawBootMenu(OUT PXTBL_DIALOG_HANDLE Handle); + +XTCDECL +VOID +BlpDrawBootMenuEntry(IN PXTBL_DIALOG_HANDLE Handle, + IN PWCHAR MenuEntry, + IN UINT Position, + IN BOOLEAN Highlighted); + +XTCDECL +VOID +BlpDrawDialogBox(IN OUT PXTBL_DIALOG_HANDLE Handle, + IN PWCHAR Caption, + IN PWCHAR Message); + +XTCDECL +VOID +BlpDrawDialogButton(IN PXTBL_DIALOG_HANDLE Handle); + +XTCDECL +VOID +BlpDrawDialogInputField(IN PXTBL_DIALOG_HANDLE Handle, + IN PWCHAR InputFieldText); + +XTCDECL +VOID +BlpDrawDialogMessage(IN PXTBL_DIALOG_HANDLE Handle, + IN PWCHAR Message); + +XTCDECL +VOID +BlpDrawDialogProgressBar(IN PXTBL_DIALOG_HANDLE Handle, + IN UCHAR Percentage); + +XTCDECL +PEFI_DEVICE_PATH_PROTOCOL +BlpDuplicateDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath); + +XTCDECL +EFI_STATUS +BlpFindLastBlockDeviceNode(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, + OUT PEFI_DEVICE_PATH_PROTOCOL *LastNode); + +XTCDECL +BOOLEAN +BlpFindParentBlockDevice(IN PLIST_ENTRY BlockDevices, + IN PEFI_BLOCK_DEVICE_DATA ChildNode, + OUT PEFI_BLOCK_DEVICE_DATA ParentNode); + +XTCDECL +EFI_STATUS +BlpInitializeDebugConsole(); + +XTCDECL +EFI_STATUS +BlpInitializeSerialPort(IN ULONG PortNumber, + IN ULONG PortAddress, + IN ULONG BaudRate); + +XTCDECL +EFI_STATUS +BlpInstallXtLoaderProtocol(); + +XTCDECL +EFI_STATUS +BlpLoadConfiguration(); + +XTCDECL +EFI_STATUS +BlpParseCommandLine(VOID); + +XTCDECL +EFI_STATUS +BlpParseConfigFile(IN CONST PCHAR RawConfig, + OUT PLIST_ENTRY Configuration); + +XTCDECL +VOID +BlpPrintShellPrompt(); + +XTCDECL +EFI_STATUS +BlpReadConfigFile(IN CONST PWCHAR ConfigDirectory, + IN CONST PWCHAR ConfigFile, + OUT PCHAR *ConfigData); + +XTCDECL +VOID +BlpStringFormat(IN BLPRINTCHAR PrintCharRoutine, + IN PUINT16 Format, + IN ...); + +XTCDECL +VOID +BlpStringPrint(IN IN BLPRINTCHAR PrintCharRoutine, + IN PUINT16 Format, + IN VA_LIST Arguments); + +XTCDECL +VOID +BlpStringPrintSigned32(IN BLPRINTCHAR PrintCharRoutine, + IN INT Number, + IN UINT Base); + +XTCDECL +VOID +BlpStringPrintSigned64(IN BLPRINTCHAR PrintCharRoutine, + IN INT_PTR Number, + IN UINT_PTR Base); + +XTCDECL +VOID +BlpStringPrintUnsigned32(IN BLPRINTCHAR PrintCharRoutine, + IN UINT Number, + IN UINT Base, + IN UINT Padding); + +XTCDECL +VOID +BlpStringPrintUnsigned64(IN BLPRINTCHAR PrintCharRoutine, + IN UINT_PTR Number, + IN UINT_PTR Base, + IN UINT_PTR Padding); + +XTCDECL +UINT64 +BlpStringReadPadding(IN PUINT16 *Format); + +XTCDECL +VOID +BlpUpdateConfiguration(IN PLIST_ENTRY NewConfig); + +#endif /* __XTLDR_XTLDR_H */ diff --git a/xtldr/library/modproto.c b/xtldr/library/modproto.c new file mode 100644 index 0000000..7bf441d --- /dev/null +++ b/xtldr/library/modproto.c @@ -0,0 +1,80 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/library/modproto.c + * DESCRIPTION: XT Boot Loader protocol support for XTLDR modules + * DEVELOPERS: Rafal Kupiec + */ + +#include + + +/** + * Finds and opens the XT Boot Loader protocol. This routine should be called by module to access XTLDR protocol. + * + * @param SystemTable + * Provides the EFI system table. + * + * @param ImageHandle + * Firmware-allocated handle that identifies the image. + * + * @param ProtocolHandler + * Receives the pointer to the XT Boot Loader protocol. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlGetXtLdrProtocol(IN PEFI_SYSTEM_TABLE SystemTable, + IN EFI_HANDLE ImageHandle, + OUT PXTBL_LOADER_PROTOCOL *ProtocolHandler) +{ + EFI_GUID ProtocolGuid = XT_BOOT_LOADER_PROTOCOL_GUID; + PEFI_HANDLE Handles = NULL; + EFI_STATUS Status; + UINT_PTR Count; + UINT Index; + + /* Try to locate the handles */ + Status = SystemTable->BootServices->LocateHandleBuffer(ByProtocol, &ProtocolGuid, NULL, &Count, &Handles); + if(Status != STATUS_EFI_SUCCESS) + { + /* Unable to get handles */ + return Status; + } + + /* Check if any handles returned */ + if(Count > 0) + { + /* Iterate through all given handles */ + for(Index = 0; Index < Count; Index++) + { + /* Try to open protocol */ + Status = SystemTable->BootServices->OpenProtocol(Handles[Index], &ProtocolGuid, + (PVOID*)ProtocolHandler, ImageHandle, NULL, + EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL); + + /* Check if successfully opened the loader protocol */ + if(Status == STATUS_EFI_SUCCESS) + { + /* Protocol found and successfully opened */ + break; + } + } + } + + /* Free handles */ + SystemTable->BootServices->FreePool(Handles); + + /* Make sure the loaded protocol has been found */ + if(*ProtocolHandler == NULL) + { + /* Protocol not found */ + return STATUS_EFI_NOT_FOUND; + } + + /* Return success */ + return STATUS_EFI_SUCCESS; +} diff --git a/xtldr/memory.c b/xtldr/memory.c index 6a09dd9..8df0448 100644 --- a/xtldr/memory.c +++ b/xtldr/memory.c @@ -2,315 +2,13 @@ * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/memory.c - * DESCRIPTION: EFI memory management + * DESCRIPTION: XT Boot Loader memory management * DEVELOPERS: Rafal Kupiec */ -#include +#include -/** - * Adds a physical to virtual address mapping to the linked list for future processing. - * - * @param MemoryMapping - * Supplies the head of the memory mapping list. - * - * @param VirtualAddress - * Supplies a virtual address where the physical address should be mapped. - * - * @param PhysicalAddress - * Supplies a physical address which will be mapped. - * - * @param NumberOfPages - * Supplies a number of pages which will be mapped. - * - * @param MemoryType - * Supplies the type of memory that will be assigned to the memory descriptor. - * - * @return This routine returns a status code. - * - * @since XT 1.0 - */ -XTCDECL -EFI_STATUS -BlAddVirtualMemoryMapping(IN PLIST_ENTRY MemoryMappings, - IN PVOID VirtualAddress, - IN PVOID PhysicalAddress, - IN UINT NumberOfPages, - IN LOADER_MEMORY_TYPE MemoryType) -{ - PLOADER_MEMORY_MAPPING Mapping1, Mapping2, Mapping3; - PVOID PhysicalAddressEnd, PhysicalAddress2End; - PLIST_ENTRY ListEntry, MappingListEntry; - SIZE_T NumberOfMappedPages; - EFI_STATUS Status; - - /* Allocate memory for new mapping */ - Status = BlEfiMemoryAllocatePool(sizeof(LOADER_MEMORY_MAPPING), (PVOID *)&Mapping1); - if(Status != STATUS_EFI_SUCCESS) - { - /* Memory allocation failure */ - return Status; - } - - /* Set mapping fields */ - Mapping1->PhysicalAddress = PhysicalAddress; - Mapping1->VirtualAddress = VirtualAddress; - Mapping1->NumberOfPages = NumberOfPages; - Mapping1->MemoryType = MemoryType; - - /* Calculate the end of the physical address */ - PhysicalAddressEnd = (PUINT8)PhysicalAddress + (NumberOfPages * EFI_PAGE_SIZE) - 1; - - /* Iterate through all the mappings already set to insert new mapping at the correct place */ - ListEntry = MemoryMappings->Flink; - while(ListEntry != MemoryMappings) - { - /* Take a mapping from the list and calculate its end of physical address */ - Mapping2 = CONTAIN_RECORD(ListEntry, LOADER_MEMORY_MAPPING, ListEntry); - PhysicalAddress2End = (PUINT8)Mapping2->PhysicalAddress + (Mapping2->NumberOfPages * EFI_PAGE_SIZE) - 1 ; - - /* Check if they overlap */ - if(PhysicalAddressEnd > Mapping2->PhysicalAddress && PhysicalAddressEnd <= PhysicalAddress2End) - { - /* Make sure it's memory type is LoaderFree */ - if(Mapping2->MemoryType != LoaderFree) - { - /* LoaderFree memory type is strictly expected */ - return STATUS_EFI_INVALID_PARAMETER; - } - - /* Calculate number of pages for this mapping */ - NumberOfMappedPages = ((PUINT8)PhysicalAddress2End - (PUINT8)PhysicalAddressEnd) / EFI_PAGE_SIZE; - if(NumberOfMappedPages > 0) - { - /* Pages associated to the mapping, allocate memory for it */ - Status = BlEfiMemoryAllocatePool(sizeof(LOADER_MEMORY_MAPPING), (PVOID*)&Mapping3); - if(Status != STATUS_EFI_SUCCESS) - { - /* Memory allocation failure */ - return Status; - } - - /* Set mapping fields and insert it on the top */ - Mapping3->PhysicalAddress = (PUINT8)PhysicalAddressEnd + 1; - Mapping3->VirtualAddress = NULL; - Mapping3->NumberOfPages = NumberOfMappedPages; - Mapping3->MemoryType = Mapping2->MemoryType; - RtlInsertHeadList(&Mapping2->ListEntry, &Mapping3->ListEntry); - } - - /* Calculate number of pages and the end of the physical address */ - Mapping2->NumberOfPages = ((PUINT8)PhysicalAddressEnd + 1 - - (PUINT8)Mapping2->PhysicalAddress) / EFI_PAGE_SIZE; - PhysicalAddress2End = (PUINT8)Mapping2->PhysicalAddress + (Mapping2->NumberOfPages * EFI_PAGE_SIZE) - 1; - } - - /* Check if they overlap */ - if(Mapping1->PhysicalAddress > Mapping2->PhysicalAddress && Mapping1->PhysicalAddress < PhysicalAddress2End) - { - /* Make sure it's memory type is LoaderFree */ - if(Mapping2->MemoryType != LoaderFree) - { - /* LoaderFree memory type is strictly expected */ - return STATUS_EFI_INVALID_PARAMETER; - } - - /* Calculate number of pages for this mapping */ - NumberOfMappedPages = ((PUINT8)PhysicalAddress2End + 1 - (PUINT8)Mapping1->PhysicalAddress) / EFI_PAGE_SIZE; - if(NumberOfMappedPages > 0) - { - /* Pages associated to the mapping, allocate memory for it */ - Status = BlEfiMemoryAllocatePool(sizeof(LOADER_MEMORY_MAPPING), (PVOID*)&Mapping3); - if(Status != STATUS_EFI_SUCCESS) - { - /* Memory allocation failure */ - return Status; - } - - /* Set mapping fields and insert it on the top */ - Mapping3->PhysicalAddress = Mapping1->PhysicalAddress; - Mapping3->VirtualAddress = NULL; - Mapping3->NumberOfPages = NumberOfMappedPages; - Mapping3->MemoryType = Mapping2->MemoryType; - RtlInsertHeadList(&Mapping2->ListEntry, &Mapping3->ListEntry); - } - - /* Calculate number of pages and the end of the physical address */ - Mapping2->NumberOfPages = ((PUINT8)Mapping1->PhysicalAddress - - (PUINT8)Mapping2->PhysicalAddress) / EFI_PAGE_SIZE; - PhysicalAddress2End = (PUINT8)Mapping2->PhysicalAddress + (Mapping2->NumberOfPages * EFI_PAGE_SIZE) - 1; - } - - /* Check if mapping is really needed */ - if((Mapping2->PhysicalAddress >= Mapping1->PhysicalAddress && PhysicalAddress2End <= PhysicalAddressEnd) || - (Mapping2->NumberOfPages == 0)) - { - /* Make sure it's memory type is LoaderFree */ - if(Mapping2->MemoryType != LoaderFree) - { - /* LoaderFree memory type is strictly expected */ - return STATUS_EFI_INVALID_PARAMETER; - } - - /* Store address of the next mapping */ - MappingListEntry = ListEntry->Flink; - - /* Remove mapping from the list and free up it's memory */ - RtlRemoveEntryList(&Mapping2->ListEntry); - BlEfiMemoryFreePool(Mapping2); - ListEntry = MappingListEntry; - - /* Go to the next mapping */ - continue; - } - - /* Determine phsical address order */ - if(Mapping2->PhysicalAddress > Mapping1->PhysicalAddress) - { - /* Insert new mapping in front */ - RtlInsertHeadList(Mapping2->ListEntry.Blink, &Mapping1->ListEntry); - return STATUS_EFI_SUCCESS; - } - - /* Get next mapping from the list */ - ListEntry = ListEntry->Flink; - } - - /* Insert new mapping to the end of the list and return success */ - RtlInsertTailList(MemoryMappings, &Mapping1->ListEntry); - return STATUS_EFI_SUCCESS; -} - -/** - * Converts an EFI memory type into an XTOS memory type. - * - * @param EfiMemoryType - * Supplies the EFI memory type. - * - * @return Returns a conversion of the memory type. - * - * @since XT 1.0 - */ -XTCDECL -LOADER_MEMORY_TYPE -BlConvertEfiMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType) -{ - LOADER_MEMORY_TYPE MemoryType; - - /* Check EFI memory type and convert to XTOS memory type */ - switch(EfiMemoryType) - { - case EfiACPIMemoryNVS: - case EfiACPIReclaimMemory: - case EfiPalCode: - MemoryType = LoaderSpecialMemory; - break; - case EfiRuntimeServicesCode: - case EfiRuntimeServicesData: - case EfiMemoryMappedIO: - case EfiMemoryMappedIOPortSpace: - MemoryType = LoaderFirmwarePermanent; - break; - case EfiBootServicesData: - case EfiLoaderCode: - case EfiLoaderData: - MemoryType = LoaderFirmwareTemporary; - break; - case EfiUnusableMemory: - MemoryType = LoaderBad; - break; - default: - MemoryType = LoaderFree; - break; - } - - /* Return XTOS memory type */ - return MemoryType; -} - -/** - * This routine allocates one or more 4KB pages. - * - * @param Pages - * The number of contiguous 4KB pages to allocate. - * - * @param Memory - * The pointer to a physical address. - * - * @return This routine returns a status code. - * - * @since XT 1.0 - */ -XTCDECL -EFI_STATUS -BlEfiMemoryAllocatePages(IN UINT64 Pages, - OUT PEFI_PHYSICAL_ADDRESS Memory) -{ - return EfiSystemTable->BootServices->AllocatePages(AllocateAnyPages, EfiLoaderData, Pages, Memory); -} - -/** - * This routine allocates a pool memory. - * - * @param Size - * The number of bytes to allocate from the pool. - * - * @param Memory - * The pointer to a physical address. - * - * @return This routine returns a status code. - * - * @since XT 1.0 - */ -XTCDECL -EFI_STATUS -BlEfiMemoryAllocatePool(IN UINT_PTR Size, - OUT PVOID *Memory) -{ - /* Allocate pool */ - return EfiSystemTable->BootServices->AllocatePool(EfiLoaderData, Size, Memory); -} - -/** - * This routine frees memory pages. - * - * @param Pages - * The number of contiguous 4 KB pages to free. - * - * @param Memory - * The base physical address of the pages to be freed. - * - * @return This routine returns a status code. - * - * @since XT 1.0 - */ -XTCDECL -EFI_STATUS -BlEfiMemoryFreePages(IN UINT64 Pages, - IN EFI_PHYSICAL_ADDRESS Memory) -{ - return EfiSystemTable->BootServices->FreePages(Memory, Pages); -} - -/** - * Returns pool memory to the system. - * - * @param Memory - * The pointer to the buffer to free. - * - * @return This routine returns a status code. - * - * @since XT 1.0 - */ -XTCDECL -EFI_STATUS -BlEfiMemoryFreePool(IN PVOID Memory) -{ - /* Free pool */ - return EfiSystemTable->BootServices->FreePool(Memory); -} - /** * Returns the memory descriptors which define a memory map of all the physical memory ranges reserved by the UEFI. * @@ -352,14 +50,14 @@ BlGetMemoryMap(OUT PEFI_MEMORY_MAP MemoryMap) if(MemoryMap->Map) { /* Free allocated memory */ - BlEfiMemoryFreePool(MemoryMap->Map); + BlMemoryFreePool(MemoryMap->Map); } return Status; } /* Allocate the desired amount of memory */ MemoryMap->MapSize += 2 * MemoryMap->DescriptorSize; - BlEfiMemoryAllocatePool(MemoryMap->MapSize, (PVOID *)&MemoryMap->Map); + BlMemoryAllocatePool(MemoryMap->MapSize, (PVOID *)&MemoryMap->Map); } while(Status == STATUS_EFI_BUFFER_TOO_SMALL); @@ -375,16 +73,13 @@ BlGetMemoryMap(OUT PEFI_MEMORY_MAP MemoryMap) } /** - * Attempts to find a virtual address of the specified physical address in memory mappings. + * This routine allocates one or more 4KB pages. * - * @param MemoryMappings - * Supplies a pointer to linked list containing all memory mappings. + * @param Pages + * The number of contiguous 4KB pages to allocate. * - * @param PhysicalAddress - * Supplies a physical address to search for in the mappings. - * - * @param VirtualAddress - * Supplies a buffer, where mapped virtual address of the found mapping will be stored. + * @param Memory + * The pointer to a physical address. * * @return This routine returns a status code. * @@ -392,58 +87,20 @@ BlGetMemoryMap(OUT PEFI_MEMORY_MAP MemoryMap) */ XTCDECL EFI_STATUS -BlGetVirtualAddress(IN PLIST_ENTRY MemoryMappings, - IN PVOID PhysicalAddress, - OUT PVOID *VirtualAddress) +BlMemoryAllocatePages(IN UINT64 Pages, + OUT PEFI_PHYSICAL_ADDRESS Memory) { - PLOADER_MEMORY_MAPPING Mapping; - PLIST_ENTRY ListEntry; - - /* NULLify virtual address */ - *VirtualAddress = NULL; - - /* Iterate over memory mappings in order to find descriptor containing a physical address */ - ListEntry = MemoryMappings->Flink; - while(ListEntry != MemoryMappings) - { - /* Get mapping from linked list */ - Mapping = CONTAIN_RECORD(ListEntry, LOADER_MEMORY_MAPPING, ListEntry); - - /* Make sure any virtual address is set */ - if(Mapping->VirtualAddress) - { - /* Check if provided physical address is in range of this mapping */ - if((PhysicalAddress >= Mapping->PhysicalAddress) && - (PhysicalAddress < Mapping->PhysicalAddress + (Mapping->NumberOfPages * EFI_PAGE_SIZE))) - { - /* Calculate virtual address based on the mapping */ - *VirtualAddress = PhysicalAddress - Mapping->PhysicalAddress + Mapping->VirtualAddress; - } - } - - /* Get next element from the list */ - ListEntry = ListEntry->Flink; - } - - /* If virtual address is still NULL, then mapping was not found */ - if(*VirtualAddress == NULL) - { - /* Mapping not found */ - return STATUS_EFI_NOT_FOUND; - } - - /* Mapping found, return success */ - return STATUS_EFI_SUCCESS; + return EfiSystemTable->BootServices->AllocatePages(AllocateAnyPages, EfiLoaderData, Pages, Memory); } /** - * Initializes virtual memory by adding known and general mappings. + * This routine allocates a pool memory. * - * @param MemoryMappings - * Supplies a pointer to linked list containing all memory mappings. + * @param Size + * The number of bytes to allocate from the pool. * - * @param MemoryMapAddress - * Supplies an address of the mapped virtual memory area. + * @param Memory + * The pointer to a physical address. * * @return This routine returns a status code. * @@ -451,80 +108,48 @@ BlGetVirtualAddress(IN PLIST_ENTRY MemoryMappings, */ XTCDECL EFI_STATUS -BlInitializeVirtualMemory(IN OUT PLIST_ENTRY MemoryMappings, - IN OUT PVOID *MemoryMapAddress) +BlMemoryAllocatePool(IN UINT_PTR Size, + OUT PVOID *Memory) { - PEFI_MEMORY_DESCRIPTOR Descriptor; - LOADER_MEMORY_TYPE MemoryType; - PEFI_MEMORY_MAP MemoryMap; - SIZE_T DescriptorCount; - PUCHAR VirtualAddress; - EFI_STATUS Status; - SIZE_T Index; - - /* Set initial virtual address */ - VirtualAddress = *MemoryMapAddress; - - /* Allocate and zero-fill buffer for EFI memory map */ - BlEfiMemoryAllocatePool(sizeof(EFI_MEMORY_MAP), (PVOID*)&MemoryMap); - RtlZeroMemory(MemoryMap, sizeof(EFI_MEMORY_MAP)); - - /* Get EFI memory map */ - Status = BlGetMemoryMap(MemoryMap); - if(Status != STATUS_EFI_SUCCESS) - { - return Status; - } - - /* Calculate descriptors count and get first one */ - Descriptor = MemoryMap->Map; - DescriptorCount = MemoryMap->MapSize / MemoryMap->DescriptorSize; - - /* Iterate through all descriptors from the memory map */ - for(Index = 0; Index < DescriptorCount; Index++) - { - /* Make sure descriptor does not go beyond lowest physical page */ - if((Descriptor->PhysicalStart + (Descriptor->NumberOfPages * EFI_PAGE_SIZE)) <= (UINT_PTR)-1) - { - /* Convert EFI memory type into XTOS memory type */ - MemoryType = BlConvertEfiMemoryType(Descriptor->Type); - - /* Do memory mappings depending on memory type */ - if(MemoryType == LoaderFirmwareTemporary) - { - /* Map EFI firmware code */ - Status = BlAddVirtualMemoryMapping(MemoryMappings, (PVOID)Descriptor->PhysicalStart, - (PVOID)Descriptor->PhysicalStart, Descriptor->NumberOfPages, MemoryType); - } - else if(MemoryType != LoaderFree) - { - /* Add any non-free memory mapping */ - Status = BlAddVirtualMemoryMapping(MemoryMappings, VirtualAddress, (PVOID)Descriptor->PhysicalStart, - Descriptor->NumberOfPages, MemoryType); - - /* Calculate next valid virtual address */ - VirtualAddress += Descriptor->NumberOfPages * EFI_PAGE_SIZE; - } - else - { - /* Map all other memory as loader free */ - Status = BlAddVirtualMemoryMapping(MemoryMappings, NULL, (PVOID)Descriptor->PhysicalStart, - Descriptor->NumberOfPages, LoaderFree); - } - - /* Make sure memory mapping succeeded */ - if(Status != STATUS_EFI_SUCCESS) - { - /* Mapping failed */ - return Status; - } - - /* Grab next descriptor */ - Descriptor = (PEFI_MEMORY_DESCRIPTOR)((PUCHAR)Descriptor + MemoryMap->DescriptorSize); - } - } - - /* Store next valid virtual address and return success */ - *MemoryMapAddress = VirtualAddress; - return STATUS_EFI_SUCCESS; + /* Allocate pool */ + return EfiSystemTable->BootServices->AllocatePool(EfiLoaderData, Size, Memory); +} + +/** + * This routine frees memory pages. + * + * @param Pages + * The number of contiguous 4 KB pages to free. + * + * @param Memory + * The base physical address of the pages to be freed. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlMemoryFreePages(IN UINT64 Pages, + IN EFI_PHYSICAL_ADDRESS Memory) +{ + return EfiSystemTable->BootServices->FreePages(Memory, Pages); +} + +/** + * Returns pool memory to the system. + * + * @param Memory + * The pointer to the buffer to free. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlMemoryFreePool(IN PVOID Memory) +{ + /* Free pool */ + return EfiSystemTable->BootServices->FreePool(Memory); } diff --git a/xtldr/modules/CMakeLists.txt b/xtldr/modules/CMakeLists.txt index c898f2e..375c1d7 100644 --- a/xtldr/modules/CMakeLists.txt +++ b/xtldr/modules/CMakeLists.txt @@ -1,3 +1,5 @@ -add_subdirectory(framebuf) -add_subdirectory(pecoff) -add_subdirectory(xtos) +add_subdirectory(beep) +add_subdirectory(dummy) +add_subdirectory(fb_o) +add_subdirectory(pecoff_o) +add_subdirectory(xtos_o) diff --git a/xtldr/modules/beep/CMakeLists.txt b/xtldr/modules/beep/CMakeLists.txt new file mode 100644 index 0000000..fb81272 --- /dev/null +++ b/xtldr/modules/beep/CMakeLists.txt @@ -0,0 +1,27 @@ +# XT Boot Loader Beep Module +PROJECT(XTLDR_BEEP) + +# Specify include directories +include_directories( + ${EXECTOS_SOURCE_DIR}/sdk/xtdk + ${XTLDR_BEEP_SOURCE_DIR}/includes) + +# Specify list of source code files +list(APPEND XTLDR_BEEP_SOURCE + ${XTLDR_BEEP_SOURCE_DIR}/beep.c + ${XTLDR_BEEP_SOURCE_DIR}/globals.c) + +# Link bootloader executable +add_executable(beep ${XTLDR_BEEP_SOURCE}) + +# Add linker libraries +target_link_libraries(beep libxtldr libxtos) + +# Set proper binary name and install target +set_target_properties(beep PROPERTIES SUFFIX .efi) +set_install_target(beep efi/boot/xtldr/modules) + +# Set module entrypoint and subsystem +set_entrypoint(beep "XtLdrModuleMain") +set_linker_map(beep TRUE) +set_subsystem(beep efi_boot_service_driver) diff --git a/xtldr/modules/beep/beep.c b/xtldr/modules/beep/beep.c new file mode 100644 index 0000000..1eab7b0 --- /dev/null +++ b/xtldr/modules/beep/beep.c @@ -0,0 +1,209 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/modules/beep/beep.c + * DESCRIPTION: XTLDR Beep Module + * DEVELOPERS: Rafal Kupiec + */ + +#include + + +/* Dummy module information */ +XTBL_MODINFO = L"Plays a GRUB compatible tune via PC speaker"; + +/** + * Disables the PC speaker. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BpDisableToneBeep() +{ + UCHAR Status; + + /* Stop the PC speaker */ + Status = HlIoPortInByte(0x61); + HlIoPortOutByte(0x61, Status & 0xFC); +} + +/** + * Enables the PC speaker and plays a sound. + * + * @param Pitch + * Specifies a pitch (in Hz) of the sound. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BpEnableToneBeep(IN UINT Pitch) +{ + UINT Counter; + UCHAR Status; + + /* Pitch only in range of 20..20000 */ + if(Pitch < 20) + { + Pitch = 20; + } + else if(Pitch > 20000) + { + Pitch = 20000; + } + + /* Set the desired frequency of the PIT clock */ + Counter = 0x1234DD / Pitch; + HlIoPortOutByte(0x43, 0xB6); + HlIoPortOutByte(0x43, 0xB6); + HlIoPortOutByte(0x42, (UCHAR) Counter & 0xFF); + HlIoPortOutByte(0x42, (UCHAR) (Counter >> 8) & 0xFF); + + /* Start the PC speaker */ + Status = HlIoPortInByte(0x61); + HlIoPortOutByte(0x61, Status | 0x03); +} + +/** + * This routine plays a tune. + * + * @param Arguments + * Optional list of parameters provided with the command. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BpPlayTune(IN PWCHAR Arguments) +{ + LONG Pitch, Duration, Tempo; + PWCHAR Argument, LastArgument; + + /* Reset pitch and duration */ + Duration = -1; + Pitch = -1; + Tempo = -1; + + /* Tokenize provided list of arguments */ + Argument = RtlTokenizeWideString(Arguments, L" ", &LastArgument); + + /* Iterate over all arguments */ + while(Argument != NULL) + { + /* Check if tempo, pitch and duration are set */ + if(Tempo < 0) + { + /* Set the tempo */ + Tempo = BpWideStringToNumber(Argument); + } + else if(Pitch < 0) + { + /* Set the pitch */ + Pitch = BpWideStringToNumber(Argument); + } + else + { + /* Set the duration */ + Duration = BpWideStringToNumber(Argument); + + /* Check pitch value */ + if(Pitch > 0) + { + /* Emit the beep tone */ + BpEnableToneBeep(Pitch); + } + else + { + /* Stop emitting beep tone */ + BpDisableToneBeep(); + } + + /* Wait for duration time */ + XtLdrProto->Util.SleepExecution(60000 * Duration / Tempo); + + /* Reset pitch and duration */ + Pitch = -1; + Duration = -1; + } + + /* Get next argument */ + Argument = RtlTokenizeWideString(NULL, L" ", &LastArgument); + } + + /* Stop emitting beep tone */ + BpDisableToneBeep(); +} + +/** + * Converts a wide string into a number. + * + * @param String + * Supplies an input wide string. + * + * @return This routine returns the number that was converted from the wide string. + * + * @since XT 1.0 + */ +XTCDECL +UINT +BpWideStringToNumber(IN PWCHAR String) +{ + ULONG Number = 0; + + /* Iterate over all characters until '\0' found */ + do + { + /* Check if this is a digit */ + if(*String - '0' < 10) + { + /* Add another digit to the number */ + Number *= 10; + Number += *String - '0'; + } + } + while(*++String != L'\0'); + + /* Return number */ + return Number; +} + +/** + * This routine is the entry point of the XT EFI boot loader module. + * + * @param ImageHandle + * Firmware-allocated handle that identifies the image. + * + * @param SystemTable + * Provides the EFI system table. + * + * @return This routine returns status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +XtLdrModuleMain(IN EFI_HANDLE ImageHandle, + IN PEFI_SYSTEM_TABLE SystemTable) +{ + EFI_STATUS Status; + + /* Open the XTLDR protocol */ + Status = BlGetXtLdrProtocol(SystemTable, ImageHandle, &XtLdrProto); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to open the protocol, return error */ + return STATUS_EFI_PROTOCOL_ERROR; + } + + /* Play the tune set in the configuration */ + BpPlayTune(XtLdrProto->Config.GetValue(L"TUNE")); + + return STATUS_EFI_SUCCESS; +} diff --git a/xtldr/modules/beep/globals.c b/xtldr/modules/beep/globals.c new file mode 100644 index 0000000..eb8e3cc --- /dev/null +++ b/xtldr/modules/beep/globals.c @@ -0,0 +1,13 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/modules/beep/globals.c + * DESCRIPTION: Dummy XTLDR module global variables + * DEVELOPERS: Rafal Kupiec + */ + +#include + + +/* XTLDR protocol handler */ +PXTBL_LOADER_PROTOCOL XtLdrProto; diff --git a/xtldr/modules/beep/includes/beep.h b/xtldr/modules/beep/includes/beep.h new file mode 100644 index 0000000..db0af8f --- /dev/null +++ b/xtldr/modules/beep/includes/beep.h @@ -0,0 +1,38 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/modules/beep/includes/beep.h + * DESCRIPTION: XTLDR Beep Module header file + * DEVELOPERS: Rafal Kupiec + */ + +#ifndef __XTLDR_BEEP_BEEP_H +#define __XTLDR_BEEP_BEEP_H + +#include +#include + + +/* Beep module routines forward references */ +XTCDECL +VOID +BpDisableToneBeep(); + +XTCDECL +VOID +BpEnableToneBeep(IN UINT Pitch); + +XTCDECL +VOID +BpPlayTune(IN PWCHAR Arguments); + +XTCDECL +UINT +BpWideStringToNumber(IN PWCHAR String); + +XTCDECL +EFI_STATUS +XtLdrModuleMain(IN EFI_HANDLE ImageHandle, + IN PEFI_SYSTEM_TABLE SystemTable); + +#endif/* __XTLDR_BEEP_BEEP_H */ diff --git a/xtldr/modules/beep/includes/globals.h b/xtldr/modules/beep/includes/globals.h new file mode 100644 index 0000000..ee5bff0 --- /dev/null +++ b/xtldr/modules/beep/includes/globals.h @@ -0,0 +1,18 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/modules/beep/includes/globals.h + * DESCRIPTION: XTLDR Beep Module global variables + * DEVELOPERS: Rafal Kupiec + */ + +#ifndef __XTLDR_BEEP_GLOBALS_H +#define __XTLDR_BEEP_GLOBALS_H + +#include + + +/* XTLDR protocol handler */ +EXTERN PXTBL_LOADER_PROTOCOL XtLdrProto; + +#endif/* __XTLDR_BEEP_GLOBALS_H */ diff --git a/xtldr/modules/dummy/CMakeLists.txt b/xtldr/modules/dummy/CMakeLists.txt new file mode 100644 index 0000000..801ad83 --- /dev/null +++ b/xtldr/modules/dummy/CMakeLists.txt @@ -0,0 +1,27 @@ +# XT Boot Loader Dummy Module +PROJECT(XTLDR_DUMMY) + +# Specify include directories +include_directories( + ${EXECTOS_SOURCE_DIR}/sdk/xtdk + ${XTLDR_DUMMY_SOURCE_DIR}/includes) + +# Specify list of source code files +list(APPEND XTLDR_DUMMY_SOURCE + ${XTLDR_DUMMY_SOURCE_DIR}/dummy.c + ${XTLDR_DUMMY_SOURCE_DIR}/globals.c) + +# Link bootloader executable +add_executable(dummy ${XTLDR_DUMMY_SOURCE}) + +# Add linker libraries +target_link_libraries(dummy libxtldr) + +# Set proper binary name and install target +set_target_properties(dummy PROPERTIES SUFFIX .efi) +set_install_target(dummy efi/boot/xtldr/modules) + +# Set module entrypoint and subsystem +set_entrypoint(dummy "XtLdrModuleMain") +set_linker_map(dummy TRUE) +set_subsystem(dummy efi_boot_service_driver) diff --git a/xtldr/modules/dummy/dummy.c b/xtldr/modules/dummy/dummy.c new file mode 100644 index 0000000..0628827 --- /dev/null +++ b/xtldr/modules/dummy/dummy.c @@ -0,0 +1,69 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/modules/dummy/dummy.c + * DESCRIPTION: XTLDR Dummy Module + * DEVELOPERS: Rafal Kupiec + */ + +#include + + +/* Dummy module information */ +XTBL_MODINFO = L"XTLDR Dummy Module"; + +/** + * Stub boot routine. + * + * @param Parameters + * Supplies all parameters associated with the chosen boot menu entry. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlBootDummyOS(IN PXTBL_BOOT_PARAMETERS Parameters) +{ + return STATUS_EFI_SUCCESS; +} + +/** + * This routine is the entry point of the XT EFI boot loader module. + * + * @param ImageHandle + * Firmware-allocated handle that identifies the image. + * + * @param SystemTable + * Provides the EFI system table. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +XtLdrModuleMain(IN EFI_HANDLE ImageHandle, + IN PEFI_SYSTEM_TABLE SystemTable) +{ + EFI_GUID DummyGuid = XT_XTOS_BOOT_PROTOCOL_GUID; + EFI_STATUS Status; + + /* Open the XTLDR protocol */ + Status = BlGetXtLdrProtocol(SystemTable, ImageHandle, &XtLdrProto); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to open the protocol, return error */ + return STATUS_EFI_PROTOCOL_ERROR; + } + + /* Set boot protocol routines */ + BlpDummyProtocol.BootSystem = BlBootDummyOS; + + /* Register XTOS boot protocol */ + XtLdrProto->Boot.RegisterProtocol(L"XTOS", &DummyGuid); + + /* Register DUMMY protocol as XTOS boot protocol */ + return XtLdrProto->Protocol.Install(&BlpDummyProtocol, &DummyGuid); +} diff --git a/xtldr/modules/dummy/globals.c b/xtldr/modules/dummy/globals.c new file mode 100644 index 0000000..595be67 --- /dev/null +++ b/xtldr/modules/dummy/globals.c @@ -0,0 +1,16 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/modules/dummy/globals.c + * DESCRIPTION: Dummy XTLDR module global variables + * DEVELOPERS: Rafal Kupiec + */ + +#include + + +/* XTLDR protocol handler */ +PXTBL_LOADER_PROTOCOL XtLdrProto; + +/* Dummy Boot Protocol handler */ +XTBL_BOOT_PROTOCOL BlpDummyProtocol; diff --git a/xtldr/modules/dummy/includes/dummy.h b/xtldr/modules/dummy/includes/dummy.h new file mode 100644 index 0000000..675bdbc --- /dev/null +++ b/xtldr/modules/dummy/includes/dummy.h @@ -0,0 +1,26 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/modules/dummy/includes/dummy.h + * DESCRIPTION: XTLDR Dummy Module header file + * DEVELOPERS: Rafal Kupiec + */ + +#ifndef __XTLDR_DUMMY_DUMMY_H +#define __XTLDR_DUMMY_DUMMY_H + +#include +#include + + +/* Dummy module routines forward references */ +XTCDECL +EFI_STATUS +BlBootDummyOS(IN PXTBL_BOOT_PARAMETERS Parameters); + +XTCDECL +EFI_STATUS +XtLdrModuleMain(IN EFI_HANDLE ImageHandle, + IN PEFI_SYSTEM_TABLE SystemTable); + +#endif/* __XTLDR_DUMMY_DUMMY_H */ diff --git a/xtldr/modules/dummy/includes/globals.h b/xtldr/modules/dummy/includes/globals.h new file mode 100644 index 0000000..8fd8446 --- /dev/null +++ b/xtldr/modules/dummy/includes/globals.h @@ -0,0 +1,21 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/modules/dummy/includes/globals.h + * DESCRIPTION: XTLDR Dummy Module global variables + * DEVELOPERS: Rafal Kupiec + */ + +#ifndef __XTLDR_DUMMY_GLOBALS_H +#define __XTLDR_DUMMY_GLOBALS_H + +#include + + +/* XTLDR protocol handler */ +EXTERN PXTBL_LOADER_PROTOCOL XtLdrProto; + +/* Dummy Boot Protocol handler */ +EXTERN XTBL_BOOT_PROTOCOL BlpDummyProtocol; + +#endif/* __XTLDR_DUMMY_GLOBALS_H */ diff --git a/xtldr/modules/fb_o/CMakeLists.txt b/xtldr/modules/fb_o/CMakeLists.txt new file mode 100644 index 0000000..f8d811b --- /dev/null +++ b/xtldr/modules/fb_o/CMakeLists.txt @@ -0,0 +1,27 @@ +# XT Boot Loader +PROJECT(XTLDR_FB_O) + +# Specify include directories +include_directories( + ${EXECTOS_SOURCE_DIR}/sdk/xtdk + ${XTLDR_FB_O_SOURCE_DIR}/includes) + +# Specify list of source code files +list(APPEND XTLDR_FB_O_SOURCE + ${XTLDR_FB_O_SOURCE_DIR}/framebuf.c + ${XTLDR_FB_O_SOURCE_DIR}/gop.c) + +# Link bootloader executable +add_executable(fb_o ${XTLDR_FB_O_SOURCE}) + +# Add linker libraries +target_link_libraries(fb_o libxtos libxtldr) + +# Set proper binary name and install target +set_target_properties(fb_o PROPERTIES SUFFIX .efi) +set_install_target(fb_o efi/boot/xtldr/modules) + +# Set module entrypoint and subsystem +set_entrypoint(fb_o "XtLdrModuleMain") +set_linker_map(fb_o TRUE) +set_subsystem(fb_o efi_boot_service_driver) diff --git a/xtldr/modules/framebuf/framebuf.c b/xtldr/modules/fb_o/framebuf.c similarity index 69% rename from xtldr/modules/framebuf/framebuf.c rename to xtldr/modules/fb_o/framebuf.c index 71b764f..703e56e 100644 --- a/xtldr/modules/framebuf/framebuf.c +++ b/xtldr/modules/fb_o/framebuf.c @@ -9,14 +9,11 @@ #include -/* EFI Image Handle */ -EFI_HANDLE EfiImageHandle; - -/* EFI System Table */ -PEFI_SYSTEM_TABLE EfiSystemTable; +/* PE/COFF_O module information */ +XTBL_MODINFO = L"EFI FB (FrameBuffer) support"; /* EFI XT Loader Protocol */ -PXT_BOOT_LOADER_PROTOCOL XtLdrProtocol; +PXTBL_LOADER_PROTOCOL XtLdrProtocol; /* XT FrameBuffer Information */ XT_FRAMEBUFFER_INFORMATION FrameBufferInfo; @@ -36,18 +33,18 @@ XT_FRAMEBUFFER_PROTOCOL XtFramebufferProtocol; */ XTCDECL VOID -FbGetDisplayDriver(OUT PWCHAR *DriverName) +FbGetDisplayDriver(OUT PWCHAR DriverName) { switch(FrameBufferInfo.Protocol) { case GOP: - *DriverName = L"GOP"; + DriverName = L"GOP"; break; case UGA: - *DriverName = L"UGA"; + DriverName = L"UGA"; break; default: - *DriverName = L"NONE"; + DriverName = L"NONE"; break; } } @@ -91,30 +88,25 @@ FbInitializeDisplay() EFI_GUID GopGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; EFI_GUID UgaGuid = EFI_UNIVERSAL_GRAPHICS_ADAPTER_PROTOCOL_GUID; UINT32 Parameter1, Parameter2; + EFI_HANDLE Handle; EFI_STATUS Status; /* Check if framebuffer already initialized */ if(!FrameBufferInfo.Initialized) { /* Initialize framebuffer */ - XtLdrProtocol->DbgPrint(L"Initializing framebuffer device\n"); + XtLdrProtocol->Debug.Print(L"Initializing framebuffer device\n"); FrameBufferInfo.Protocol = NONE; FrameBufferInfo.Initialized = FALSE; - /* Check if GOP already in use */ - Status = EfiSystemTable->BootServices->HandleProtocol(EfiSystemTable->ConsoleOutHandle, &GopGuid, - (PVOID*)&FrameBufferInfo.Adapter.GOP); - if(Status != STATUS_EFI_SUCCESS) - { - /* Locate GOP protocol */ - Status = EfiSystemTable->BootServices->LocateProtocol(&GopGuid, NULL, (PVOID *)&FrameBufferInfo.Adapter.GOP); - } + /* Attempt to open GOP protocol */ + Status = XtLdrProtocol->Protocol.Open(&Handle, (PVOID*)&FrameBufferInfo.Adapter.GOP, &GopGuid); /* Check if Graphics Output Protocol is available */ if(Status == STATUS_EFI_SUCCESS) { /* Found GOP */ - XtLdrProtocol->DbgPrint(L"Found GOP compatible display adapter\n"); + XtLdrProtocol->Debug.Print(L"Found GOP compatible display adapter\n"); /* Set framebuffer parameters */ FrameBufferInfo.HorizontalResolution = FrameBufferInfo.Adapter.GOP->Mode->Info->HorizontalResolution; @@ -128,27 +120,23 @@ FbInitializeDisplay() FrameBufferInfo.FrameBufferSize = FrameBufferInfo.Adapter.GOP->Mode->FrameBufferSize; FrameBufferInfo.Protocol = GOP; FrameBufferInfo.Initialized = TRUE; + + /* Close GOP protocol */ + Status = XtLdrProtocol->Protocol.Close(Handle, &GopGuid); } else { /* GOP is unavailable */ FrameBufferInfo.Adapter.GOP = NULL; - /* Check if UGA already in use */ - Status = EfiSystemTable->BootServices->HandleProtocol(EfiSystemTable->ConsoleOutHandle, &UgaGuid, - (PVOID*)&FrameBufferInfo.Adapter.UGA); - if(Status != STATUS_EFI_SUCCESS) - { - /* Locate UGA protocol */ - Status = EfiSystemTable->BootServices->LocateProtocol(&UgaGuid, NULL, - (PVOID*)&FrameBufferInfo.Adapter.UGA); - } + /* Attempt to open UGA protocol */ + Status = XtLdrProtocol->Protocol.Open(&Handle, (PVOID*)&FrameBufferInfo.Adapter.UGA, &UgaGuid); /* Check if Universal Graphics Adapter is available */ if(Status == STATUS_EFI_SUCCESS) { /* Found UGA */ - XtLdrProtocol->DbgPrint(L"Found UGA compatible display adapter\n"); + XtLdrProtocol->Debug.Print(L"Found UGA compatible display adapter\n"); /* Get current mode */ Status = FrameBufferInfo.Adapter.UGA->GetMode(FrameBufferInfo.Adapter.UGA, @@ -158,7 +146,7 @@ FbInitializeDisplay() if(Status != STATUS_EFI_SUCCESS) { /* Unable to get current UGA mode */ - XtLdrProtocol->DbgPrint(L"Failed to get current UGA mode (Status code: %lx)\n", Status); + XtLdrProtocol->Debug.Print(L"Failed to get current UGA mode (Status code: %lx)\n", Status); FrameBufferInfo.Adapter.UGA = NULL; } else @@ -178,6 +166,9 @@ FbInitializeDisplay() /* Temporarily set this to FALSE, as we don't set FB base and we cannot use it anyway */ FrameBufferInfo.Initialized = FALSE; } + + /* Close UGA protocol */ + XtLdrProtocol->Protocol.Close(Handle, &UgaGuid); } } @@ -185,7 +176,7 @@ FbInitializeDisplay() if(!FrameBufferInfo.Initialized) { /* GOP and UGA unavailable */ - XtLdrProtocol->DbgPrint(L"No display adapter found\n"); + XtLdrProtocol->Debug.Print(L"No display adapter found\n"); return STATUS_EFI_NOT_FOUND; } } @@ -205,31 +196,31 @@ XTCDECL VOID FbPrintDisplayInformation() { - PWCHAR DriverName; + PWCHAR DriverName = NULL; /* Make sure frame buffer is initialized */ if(!FrameBufferInfo.Initialized) { /* No FrameBuffer */ - XtLdrProtocol->DbgPrint(L"No display adapters initialized, unable to print video information\n"); + XtLdrProtocol->Debug.Print(L"No display adapters initialized, unable to print video information\n"); return; } /* Get display driver name */ - FbGetDisplayDriver(&DriverName); + FbGetDisplayDriver(DriverName); /* Print video information */ - XtLdrProtocol->DbgPrint(L"XTLDR Framebuffer information:\n" - L" FrameBuffer Address: 0x%lx\n" - L" FrameBuffer Size: %lu\n" - L" FrameBuffer Driver: %S\n" - L" Current Resolution: %ux%ux%u\n" - L" Pixel Format: %u\n" - L" Pixels Per ScanLine: %u\n", - FrameBufferInfo.FrameBufferBase, FrameBufferInfo.FrameBufferSize, DriverName, - FrameBufferInfo.HorizontalResolution, FrameBufferInfo.VerticalResolution, - FrameBufferInfo.BitsPerPixel, FrameBufferInfo.PixelFormat, - FrameBufferInfo.PixelsPerScanLine); + XtLdrProtocol->Debug.Print(L"XTLDR Framebuffer information:\n" + L" FrameBuffer Address: 0x%lx\n" + L" FrameBuffer Size: %lu\n" + L" FrameBuffer Driver: %S\n", + FrameBufferInfo.FrameBufferBase, FrameBufferInfo.FrameBufferSize, DriverName); + XtLdrProtocol->Debug.Print(L" Current Resolution: %dx%dx%d\n" + L" Pixel Format: %u\n" + L" Pixels Per ScanLine: %u\n", + FrameBufferInfo.HorizontalResolution, FrameBufferInfo.VerticalResolution, + FrameBufferInfo.BitsPerPixel, FrameBufferInfo.PixelFormat, + FrameBufferInfo.PixelsPerScanLine); } /** @@ -247,19 +238,14 @@ FbPrintDisplayInformation() */ XTCDECL EFI_STATUS -BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle, - IN PEFI_SYSTEM_TABLE SystemTable) +XtLdrModuleMain(IN EFI_HANDLE ImageHandle, + IN PEFI_SYSTEM_TABLE SystemTable) { EFI_GUID Guid = XT_FRAMEBUFFER_PROTOCOL_GUID; - EFI_HANDLE Handle = NULL; EFI_STATUS Status; - /* Set the system table and image handle */ - EfiImageHandle = ImageHandle; - EfiSystemTable = SystemTable; - /* Open the XTLDR protocol */ - Status = BlGetXtLoaderProtocol(&XtLdrProtocol); + Status = BlGetXtLdrProtocol(SystemTable, ImageHandle, &XtLdrProtocol); if(Status != STATUS_EFI_SUCCESS) { /* Failed to open loader protocol */ @@ -272,6 +258,5 @@ BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle, XtFramebufferProtocol.PrintDisplayInformation = FbPrintDisplayInformation; /* Register XTOS boot protocol */ - return EfiSystemTable->BootServices->InstallProtocolInterface(&Handle, &Guid, EFI_NATIVE_INTERFACE, - &XtFramebufferProtocol); + return XtLdrProtocol->Protocol.Install(&XtFramebufferProtocol, &Guid); } diff --git a/xtldr/modules/framebuf/gop.c b/xtldr/modules/fb_o/gop.c similarity index 96% rename from xtldr/modules/framebuf/gop.c rename to xtldr/modules/fb_o/gop.c index ea9c732..baa746f 100644 --- a/xtldr/modules/framebuf/gop.c +++ b/xtldr/modules/fb_o/gop.c @@ -1,7 +1,7 @@ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtldr/modules/framebuf/gop.c + * FILE: xtldr/modules/fb_o/gop.c * DESCRIPTION: Graphical Output Protocol (GOP) support * DEVELOPERS: Rafal Kupiec */ diff --git a/xtldr/modules/fb_o/includes/framebuf.h b/xtldr/modules/fb_o/includes/framebuf.h new file mode 100644 index 0000000..164eae4 --- /dev/null +++ b/xtldr/modules/fb_o/includes/framebuf.h @@ -0,0 +1,79 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/modules/fb_o/includes/framebuf.h + * DESCRIPTION: Framebuffer support module header file + * DEVELOPERS: Rafal Kupiec + */ + +#ifndef __XTLDR_MODULES_FRAMEBUF_H +#define __XTLDR_MODULES_FRAMEBUF_H + +#include + + +typedef VOID (*PXT_FRAMEBUFFER_GET_DISPLAY_DRIVER)(OUT PWCHAR DriverName); +typedef VOID (*PXT_FRAMEBUFFER_GET_DISPLAY_INFORMATION)(OUT PLOADER_GRAPHICS_INFORMATION_BLOCK InformationBlock); +typedef EFI_STATUS (*PXT_FRAMEBUFFER_INITIALIZE)(); +typedef VOID (*PXT_FRAMEBUFFER_PRINT_DISPLAY_INFORMATION)(); + +/* XT framebuffer support protocol */ +typedef struct _XT_FRAMEBUFFER_PROTOCOL +{ + PXT_FRAMEBUFFER_GET_DISPLAY_DRIVER GetDisplayDriver; + PXT_FRAMEBUFFER_GET_DISPLAY_INFORMATION GetDisplayInformation; + PXT_FRAMEBUFFER_INITIALIZE Initialize; + PXT_FRAMEBUFFER_PRINT_DISPLAY_INFORMATION PrintDisplayInformation; +} XT_FRAMEBUFFER_PROTOCOL, *PXT_FRAMEBUFFER_PROTOCOL; + +/* XT framebuffer information structure definition */ +typedef struct _XT_FRAMEBUFFER_INFORMATION +{ + BOOLEAN Initialized; + EFI_GRAPHICS_PROTOCOL Protocol; + union + { + PEFI_GRAPHICS_OUTPUT_PROTOCOL GOP; + PEFI_UNIVERSAL_GRAPHICS_ADAPTER_PROTOCOL UGA; + } Adapter; + UINT HorizontalResolution; + UINT VerticalResolution; + UINT BitsPerPixel; + UINT BytesPerPixel; + UINT PixelsPerScanLine; + UINT Pitch; + EFI_GRAPHICS_PIXEL_FORMAT PixelFormat; + EFI_PHYSICAL_ADDRESS FrameBufferBase; + ULONG_PTR FrameBufferSize; +} XT_FRAMEBUFFER_INFORMATION, *PXT_FRAMEBUFFER_INFORMATION; + +/* XT FrameBuffer Information */ +EXTERN XT_FRAMEBUFFER_INFORMATION FrameBufferInfo; + +/* FrameBuffer support protocol related routines forward references */ +XTCDECL +VOID +FbGetDisplayDriver(OUT PWCHAR DriverName); + +XTCDECL +VOID +FbGetDisplayInformation(OUT PLOADER_GRAPHICS_INFORMATION_BLOCK InformationBlock); + +XTCDECL +EFI_STATUS +FbInitializeDisplay(); + +XTCDECL +VOID +FbPrintDisplayInformation(); + +XTCDECL +UINT32 +GoppGetBitsPerPixel(); + +XTCDECL +EFI_STATUS +BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle, + IN PEFI_SYSTEM_TABLE SystemTable); + +#endif /* __XTLDR_MODULES_FRAMEBUF_H */ diff --git a/xtldr/modules/framebuf/CMakeLists.txt b/xtldr/modules/framebuf/CMakeLists.txt deleted file mode 100644 index 41ebc4c..0000000 --- a/xtldr/modules/framebuf/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -# XT Boot Loader -PROJECT(XTLDR_FRAMEBUF) - -# Specify include directories -include_directories( - ${EXECTOS_SOURCE_DIR}/sdk/xtdk - ${XTLDR_SOURCE_DIR}/includes - ${XTLDR_FRAMEBUF_SOURCE_DIR}/includes) - -# Specify list of source code files -list(APPEND XTLDR_FRAMEBUF_SOURCE - ${XTLDR_SOURCE_DIR}/blproto.c - ${XTLDR_FRAMEBUF_SOURCE_DIR}/framebuf.c - ${XTLDR_FRAMEBUF_SOURCE_DIR}/gop.c) - -# Link bootloader executable -add_executable(framebuf ${XTLDR_FRAMEBUF_SOURCE}) - -# Add linker libraries -target_link_libraries(framebuf libxtos) - -# Set proper binary name and install target -set_target_properties(framebuf PROPERTIES SUFFIX .efi) -set_install_target(framebuf efi/boot/xtldr) - -# Set module entrypoint and subsystem -set_entrypoint(framebuf "BlXtLdrModuleMain") -set_subsystem(framebuf efi_boot_service_driver) diff --git a/xtldr/modules/framebuf/includes/framebuf.h b/xtldr/modules/framebuf/includes/framebuf.h deleted file mode 100644 index 12f54c3..0000000 --- a/xtldr/modules/framebuf/includes/framebuf.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - * PROJECT: ExectOS - * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtldr/modules/framebuf/includes/framebuf.h - * DESCRIPTION: Framebuffer support module header file - * DEVELOPERS: Rafal Kupiec - */ - -#ifndef __XTLDR_MODULES_FRAMEBUF_H -#define __XTLDR_MODULES_FRAMEBUF_H - -#include - - -/* XT FrameBuffer Information */ -EXTERN XT_FRAMEBUFFER_INFORMATION FrameBufferInfo; - -/* FrameBuffer support protocol related routines forward references */ -XTCDECL -VOID -FbGetDisplayDriver(OUT PWCHAR *DriverName); - -XTCDECL -VOID -FbGetDisplayInformation(OUT PLOADER_GRAPHICS_INFORMATION_BLOCK InformationBlock); - -XTCDECL -EFI_STATUS -FbInitializeDisplay(); - -XTCDECL -VOID -FbPrintDisplayInformation(); - -XTCDECL -UINT32 -GoppGetBitsPerPixel(); - -XTCDECL -EFI_STATUS -BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle, - IN PEFI_SYSTEM_TABLE SystemTable); - -#endif /* __XTLDR_MODULES_FRAMEBUF_H */ diff --git a/xtldr/modules/pecoff/CMakeLists.txt b/xtldr/modules/pecoff/CMakeLists.txt deleted file mode 100644 index c556bc8..0000000 --- a/xtldr/modules/pecoff/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -# XT Boot Loader -PROJECT(XTLDR_PECOFF) - -# Specify include directories -include_directories( - ${EXECTOS_SOURCE_DIR}/sdk/xtdk - ${XTLDR_SOURCE_DIR}/includes - ${XTLDR_PECOFF_SOURCE_DIR}/includes) - -# Specify list of source code files -list(APPEND XTLDR_PECOFF_SOURCE - ${XTLDR_SOURCE_DIR}/blproto.c - ${XTLDR_PECOFF_SOURCE_DIR}/pecoff.c) - -# Link bootloader executable -add_executable(pecoff ${XTLDR_PECOFF_SOURCE}) - -# Add linker libraries -target_link_libraries(pecoff libxtos) - -# Set proper binary name and install target -set_target_properties(pecoff PROPERTIES SUFFIX .efi) -set_install_target(pecoff efi/boot/xtldr) - -# Set module entrypoint and subsystem -set_entrypoint(pecoff "BlXtLdrModuleMain") -set_subsystem(pecoff efi_boot_service_driver) diff --git a/xtldr/modules/pecoff_o/CMakeLists.txt b/xtldr/modules/pecoff_o/CMakeLists.txt new file mode 100644 index 0000000..12e137f --- /dev/null +++ b/xtldr/modules/pecoff_o/CMakeLists.txt @@ -0,0 +1,26 @@ +# XT Boot Loader +PROJECT(XTLDR_PECOFF_O) + +# Specify include directories +include_directories( + ${EXECTOS_SOURCE_DIR}/sdk/xtdk + ${XTLDR_PECOFF_O_SOURCE_DIR}/includes) + +# Specify list of source code files +list(APPEND XTLDR_PECOFF_O_SOURCE + ${XTLDR_PECOFF_O_SOURCE_DIR}/pecoff.c) + +# Link bootloader executable +add_executable(pecoff_o ${XTLDR_PECOFF_O_SOURCE}) + +# Add linker libraries +target_link_libraries(pecoff_o libxtos libxtldr) + +# Set proper binary name and install target +set_target_properties(pecoff_o PROPERTIES SUFFIX .efi) +set_install_target(pecoff_o efi/boot/xtldr/modules) + +# Set module entrypoint and subsystem +set_entrypoint(pecoff_o "XtLdrModuleMain") +set_linker_map(pecoff_o TRUE) +set_subsystem(pecoff_o efi_boot_service_driver) diff --git a/xtldr/modules/pecoff/includes/pecoff.h b/xtldr/modules/pecoff_o/includes/pecoff.h similarity index 71% rename from xtldr/modules/pecoff/includes/pecoff.h rename to xtldr/modules/pecoff_o/includes/pecoff.h index b026fc0..af30bf9 100644 --- a/xtldr/modules/pecoff/includes/pecoff.h +++ b/xtldr/modules/pecoff_o/includes/pecoff.h @@ -1,31 +1,31 @@ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtldr/modules/pecoff/includes/pecoff.h + * FILE: xtldr/modules/pecoff_o/includes/pecoff.h * DESCRIPTION: PE/COFF executable file format support header * DEVELOPERS: Rafal Kupiec */ -#ifndef __XTLDR_MODULES_PECOFF_H -#define __XTLDR_MODULES_PECOFF_H +#ifndef __XTLDR_MODULES_PECOFF_O_H +#define __XTLDR_MODULES_PECOFF_O_H -#include +#include /* PE/COFF image protocol related routines forward references */ XTCDECL EFI_STATUS -PeGetEntryPoint(IN PPECOFF_IMAGE_CONTEXT Image, +PeGetEntryPoint(IN PVOID ImagePointer, OUT PVOID *EntryPoint); XTCDECL EFI_STATUS -PeGetMachineType(IN PPECOFF_IMAGE_CONTEXT Image, +PeGetMachineType(IN PVOID ImagePointer, OUT PUSHORT MachineType); XTCDECL EFI_STATUS -PeGetSubSystem(IN PPECOFF_IMAGE_CONTEXT Image, +PeGetSubSystem(IN PVOID ImagePointer, OUT PUSHORT SubSystem); XTCDECL @@ -33,11 +33,11 @@ EFI_STATUS PeLoadImage(IN PEFI_FILE_HANDLE FileHandle, IN LOADER_MEMORY_TYPE MemoryType, IN PVOID VirtualAddress, - OUT PPECOFF_IMAGE_CONTEXT *Image); + OUT PVOID *ImagePointer); XTCDECL EFI_STATUS -PeRelocateImage(IN PPECOFF_IMAGE_CONTEXT Image, +PeRelocateImage(IN PVOID ImagePointer, IN EFI_VIRTUAL_ADDRESS Address); XTCDECL @@ -55,4 +55,4 @@ EFI_STATUS BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable); -#endif /* __XTLDR_MODULES_PECOFF_H */ +#endif /* __XTLDR_MODULES_PECOFF_O_H */ diff --git a/xtldr/modules/pecoff/pecoff.c b/xtldr/modules/pecoff_o/pecoff.c similarity index 82% rename from xtldr/modules/pecoff/pecoff.c rename to xtldr/modules/pecoff_o/pecoff.c index 8ec7bfb..36ff2f4 100644 --- a/xtldr/modules/pecoff/pecoff.c +++ b/xtldr/modules/pecoff_o/pecoff.c @@ -1,25 +1,22 @@ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtldr/modules/pecoff/pecoff.c - * DESCRIPTION: PE/COFF executable file format support + * FILE: xtldr/modules/pecoff_o/pecoff.c + * DESCRIPTION: OLD and deprecated PE/COFF executable file format support module * DEVELOPERS: Rafal Kupiec */ #include -/* EFI Image Handle */ -EFI_HANDLE EfiImageHandle; - -/* EFI System Table */ -PEFI_SYSTEM_TABLE EfiSystemTable; +/* PE/COFF_O module information */ +XTBL_MODINFO = L"PE/COFF executable file format support"; /* EFI XT Loader Protocol */ -PXT_BOOT_LOADER_PROTOCOL XtLdrProtocol; +PXTBL_LOADER_PROTOCOL XtLdrProtocol; /* XTOS PE/COFF Image Protocol */ -XT_PECOFF_IMAGE_PROTOCOL XtPeCoffProtocol; +XTBL_EXECUTABLE_IMAGE_PROTOCOL XtPeCoffProtocol; /** * Returns the address of the entry point. @@ -36,9 +33,11 @@ XT_PECOFF_IMAGE_PROTOCOL XtPeCoffProtocol; */ XTCDECL EFI_STATUS -PeGetEntryPoint(IN PPECOFF_IMAGE_CONTEXT Image, +PeGetEntryPoint(IN PVOID ImagePointer, OUT PVOID *EntryPoint) { + PPECOFF_IMAGE_CONTEXT Image = ImagePointer; + /* Validate input data */ if(!Image || !Image->PeHeader) { @@ -66,9 +65,11 @@ PeGetEntryPoint(IN PPECOFF_IMAGE_CONTEXT Image, */ XTCDECL EFI_STATUS -PeGetMachineType(IN PPECOFF_IMAGE_CONTEXT Image, +PeGetMachineType(IN PVOID ImagePointer, OUT PUSHORT MachineType) { + PPECOFF_IMAGE_CONTEXT Image = ImagePointer; + /* Validate input data */ if(!Image || !Image->PeHeader) { @@ -96,9 +97,11 @@ PeGetMachineType(IN PPECOFF_IMAGE_CONTEXT Image, */ XTCDECL EFI_STATUS -PeGetSubSystem(IN PPECOFF_IMAGE_CONTEXT Image, +PeGetSubSystem(IN PVOID ImagePointer, OUT PUSHORT SubSystem) { + PPECOFF_IMAGE_CONTEXT Image = ImagePointer; + /* Validate input data */ if(!Image || !Image->PeHeader) { @@ -135,7 +138,7 @@ EFI_STATUS PeLoadImage(IN PEFI_FILE_HANDLE FileHandle, IN LOADER_MEMORY_TYPE MemoryType, IN PVOID VirtualAddress, - OUT PPECOFF_IMAGE_CONTEXT *Image) + OUT PVOID *ImagePointer) { EFI_GUID FileInfoGuid = EFI_FILE_INFO_PROTOCOL_GUID; PPECOFF_IMAGE_SECTION_HEADER SectionHeader; @@ -153,11 +156,11 @@ PeLoadImage(IN PEFI_FILE_HANDLE FileHandle, ReadSize = sizeof(EFI_FILE_INFO) + 32; /* Allocate necessary amount of memory */ - Status = XtLdrProtocol->AllocatePool(ReadSize, (PVOID *)&FileInfo); + Status = XtLdrProtocol->Memory.AllocatePool(ReadSize, (PVOID *)&FileInfo); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ - XtLdrProtocol->DbgPrint(L"ERROR: Memory pool allocation failure\n"); + XtLdrProtocol->Debug.Print(L"ERROR: Memory pool allocation failure\n"); return Status; } @@ -166,12 +169,12 @@ PeLoadImage(IN PEFI_FILE_HANDLE FileHandle, if(Status == STATUS_EFI_BUFFER_TOO_SMALL) { /* Buffer it too small, but EFI tells the required size, let's reallocate */ - XtLdrProtocol->FreePool(&FileInfo); - Status = XtLdrProtocol->AllocatePool(ReadSize, (PVOID *)&FileInfo); + XtLdrProtocol->Memory.FreePool(&FileInfo); + Status = XtLdrProtocol->Memory.AllocatePool(ReadSize, (PVOID *)&FileInfo); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ - XtLdrProtocol->DbgPrint(L"ERROR: Memory pool allocation failure\n"); + XtLdrProtocol->Debug.Print(L"ERROR: Memory pool allocation failure\n"); return Status; } @@ -181,16 +184,16 @@ PeLoadImage(IN PEFI_FILE_HANDLE FileHandle, if(Status != STATUS_EFI_SUCCESS) { /* Unable to get file information */ - XtLdrProtocol->DbgPrint(L"ERROR: Failed to get file information\n"); + XtLdrProtocol->Debug.Print(L"ERROR: Failed to get file information\n"); return Status; } /* Allocate memory for storing image data */ - Status = XtLdrProtocol->AllocatePool(sizeof(PECOFF_IMAGE_CONTEXT), (PVOID *)&ImageData); + Status = XtLdrProtocol->Memory.AllocatePool(sizeof(PECOFF_IMAGE_CONTEXT), (PVOID *)&ImageData); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ - XtLdrProtocol->DbgPrint(L"ERROR: Memory pool allocation failure\n"); + XtLdrProtocol->Debug.Print(L"ERROR: Memory pool allocation failure\n"); return Status; } @@ -198,18 +201,18 @@ PeLoadImage(IN PEFI_FILE_HANDLE FileHandle, ImageData->Data = NULL; ImageData->FileSize = FileInfo->FileSize; ImageData->MemoryType = MemoryType; - XtLdrProtocol->FreePool(FileInfo); + XtLdrProtocol->Memory.FreePool(FileInfo); /* Calculate number of pages */ Pages = EFI_SIZE_TO_PAGES(ImageData->FileSize); /* Allocate pages */ - Status = XtLdrProtocol->AllocatePages(Pages, &Address); + Status = XtLdrProtocol->Memory.AllocatePages(Pages, &Address); if(Status != STATUS_EFI_SUCCESS) { /* Pages allocation failure */ - XtLdrProtocol->DbgPrint(L"ERROR: Pages allocation failure\n"); - XtLdrProtocol->FreePool(ImageData); + XtLdrProtocol->Debug.Print(L"ERROR: Pages allocation failure\n"); + XtLdrProtocol->Memory.FreePool(ImageData); return Status; } @@ -220,9 +223,9 @@ PeLoadImage(IN PEFI_FILE_HANDLE FileHandle, if(Status != STATUS_EFI_SUCCESS) { /* Failed to read data */ - XtLdrProtocol->DbgPrint(L"ERROR: Unable to read PE/COFF image file\n"); - XtLdrProtocol->FreePages(Pages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)Data); - XtLdrProtocol->FreePool(ImageData); + XtLdrProtocol->Debug.Print(L"ERROR: Unable to read PE/COFF image file\n"); + XtLdrProtocol->Memory.FreePages(Pages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)Data); + XtLdrProtocol->Memory.FreePool(ImageData); return Status; } @@ -235,9 +238,9 @@ PeLoadImage(IN PEFI_FILE_HANDLE FileHandle, if(Status != STATUS_EFI_SUCCESS) { /* Header validation failed, probably broken or invalid PE/COFF image */ - XtLdrProtocol->DbgPrint(L"ERROR: Invalid PE/COFF image headers\n"); - XtLdrProtocol->FreePages(Pages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)Data); - XtLdrProtocol->FreePool(ImageData); + XtLdrProtocol->Debug.Print(L"ERROR: Invalid PE/COFF image headers\n"); + XtLdrProtocol->Memory.FreePages(Pages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)Data); + XtLdrProtocol->Memory.FreePool(ImageData); return Status; } @@ -245,9 +248,9 @@ PeLoadImage(IN PEFI_FILE_HANDLE FileHandle, if (!(ImageData->PeHeader->FileHeader.Characteristics & PECOFF_IMAGE_FILE_EXECUTABLE_IMAGE)) { /* Loaded image is not executable */ - XtLdrProtocol->DbgPrint(L"ERROR: Non-executable PE/COFF image loaded\n"); - XtLdrProtocol->FreePages(Pages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)Data); - XtLdrProtocol->FreePool(ImageData); + XtLdrProtocol->Debug.Print(L"ERROR: Non-executable PE/COFF image loaded\n"); + XtLdrProtocol->Memory.FreePages(Pages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)Data); + XtLdrProtocol->Memory.FreePool(ImageData); return STATUS_EFI_LOAD_ERROR; } @@ -256,12 +259,12 @@ PeLoadImage(IN PEFI_FILE_HANDLE FileHandle, ImageData->ImagePages = EFI_SIZE_TO_PAGES(ImageData->ImageSize); /* Allocate image pages */ - Status = XtLdrProtocol->AllocatePages(ImageData->ImagePages, &Address); + Status = XtLdrProtocol->Memory.AllocatePages(ImageData->ImagePages, &Address); if(Status != STATUS_EFI_SUCCESS) { /* Pages reallocation failure */ - XtLdrProtocol->DbgPrint(L"ERROR: Pages reallocation failure\n"); - XtLdrProtocol->FreePool(ImageData); + XtLdrProtocol->Debug.Print(L"ERROR: Pages reallocation failure\n"); + XtLdrProtocol->Memory.FreePool(ImageData); return Status; } @@ -319,19 +322,19 @@ PeLoadImage(IN PEFI_FILE_HANDLE FileHandle, } /* Free pages */ - XtLdrProtocol->FreePages((EFI_PHYSICAL_ADDRESS)(UINT_PTR)Data, Pages); + XtLdrProtocol->Memory.FreePages((EFI_PHYSICAL_ADDRESS)(UINT_PTR)Data, Pages); /* Perform relocation fixups */ Status = PepRelocateLoadedImage(ImageData); if(Status != STATUS_EFI_SUCCESS) { /* Failed to relocate image */ - XtLdrProtocol->DbgPrint(L"ERROR: PE/COFF image relocation failed\n"); + XtLdrProtocol->Debug.Print(L"ERROR: PE/COFF image relocation failed\n"); return Status; } /* Store image data */ - *Image = ImageData; + *ImagePointer = ImageData; /* Return SUCCESS */ return STATUS_EFI_SUCCESS; @@ -352,9 +355,11 @@ PeLoadImage(IN PEFI_FILE_HANDLE FileHandle, */ XTCDECL EFI_STATUS -PeRelocateImage(IN PPECOFF_IMAGE_CONTEXT Image, +PeRelocateImage(IN PVOID ImagePointer, IN EFI_VIRTUAL_ADDRESS Address) { + PPECOFF_IMAGE_CONTEXT Image = ImagePointer; + UINT64 ImageBase, OldVirtualAddress; EFI_STATUS Status; @@ -416,7 +421,7 @@ PepRelocateLoadedImage(IN PPECOFF_IMAGE_CONTEXT Image) if(Image->PeHeader->FileHeader.Characteristics & PECOFF_IMAGE_FILE_RELOCS_STRIPPED) { /* No relocation information found */ - XtLdrProtocol->DbgPrint(L"WARNING: PE/COFF image is stripped and contains no information about relocations\n"); + XtLdrProtocol->Debug.Print(L"WARNING: PE/COFF image is stripped and contains no information about relocations\n"); return STATUS_EFI_SUCCESS; } @@ -531,21 +536,21 @@ PepValidateImageHeaders(IN PPECOFF_IMAGE_DOS_HEADER DosHeader, /* Validate file size */ if(FileSize < sizeof(PECOFF_IMAGE_DOS_HEADER)) { - XtLdrProtocol->DbgPrint(L"WARNING: PE/COFF image shorter than DOS header\n"); + XtLdrProtocol->Debug.Print(L"WARNING: PE/COFF image shorter than DOS header\n"); return STATUS_EFI_END_OF_FILE; } /* Validate DOS header */ if(DosHeader->e_magic != PECOFF_IMAGE_DOS_SIGNATURE) { - XtLdrProtocol->DbgPrint(L"WARNING: Invalid DOS signature found\n"); + XtLdrProtocol->Debug.Print(L"WARNING: Invalid DOS signature found\n"); return STATUS_EFI_INCOMPATIBLE_VERSION; } /* Validate PE header */ if(PeHeader->Signature != PECOFF_IMAGE_NT_SIGNATURE && PeHeader->Signature != PECOFF_IMAGE_XT_SIGNATURE) { - XtLdrProtocol->DbgPrint(L"WARNING: Invalid NT/XT signature found\n"); + XtLdrProtocol->Debug.Print(L"WARNING: Invalid NT/XT signature found\n"); return STATUS_EFI_INCOMPATIBLE_VERSION; } @@ -553,7 +558,7 @@ PepValidateImageHeaders(IN PPECOFF_IMAGE_DOS_HEADER DosHeader, if(PeHeader->OptionalHeader.Magic != PECOFF_IMAGE_PE_OPTIONAL_HDR32_MAGIC && PeHeader->OptionalHeader.Magic != PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC) { - XtLdrProtocol->DbgPrint(L"WARNING: Invalid optional header signature found\n"); + XtLdrProtocol->Debug.Print(L"WARNING: Invalid optional header signature found\n"); return STATUS_EFI_INCOMPATIBLE_VERSION; } @@ -576,19 +581,14 @@ PepValidateImageHeaders(IN PPECOFF_IMAGE_DOS_HEADER DosHeader, */ XTCDECL EFI_STATUS -BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle, - IN PEFI_SYSTEM_TABLE SystemTable) +XtLdrModuleMain(IN EFI_HANDLE ImageHandle, + IN PEFI_SYSTEM_TABLE SystemTable) { EFI_GUID Guid = XT_PECOFF_IMAGE_PROTOCOL_GUID; - EFI_HANDLE Handle = NULL; EFI_STATUS Status; - /* Set the system table and image handle */ - EfiImageHandle = ImageHandle; - EfiSystemTable = SystemTable; - /* Open the XTLDR protocol */ - Status = BlGetXtLoaderProtocol(&XtLdrProtocol); + Status = BlGetXtLdrProtocol(SystemTable, ImageHandle, &XtLdrProtocol); if(Status != STATUS_EFI_SUCCESS) { /* Failed to open loader protocol */ @@ -599,10 +599,9 @@ BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle, XtPeCoffProtocol.GetEntryPoint = PeGetEntryPoint; XtPeCoffProtocol.GetMachineType = PeGetMachineType; XtPeCoffProtocol.GetSubSystem = PeGetSubSystem; - XtPeCoffProtocol.Load = PeLoadImage; - XtPeCoffProtocol.Relocate = PeRelocateImage; + XtPeCoffProtocol.LoadImage = PeLoadImage; + XtPeCoffProtocol.RelocateImage = PeRelocateImage; /* Register PE/COFF protocol */ - return EfiSystemTable->BootServices->InstallProtocolInterface(&Handle, &Guid, EFI_NATIVE_INTERFACE, - &XtPeCoffProtocol); + return XtLdrProtocol->Protocol.Install(&XtPeCoffProtocol, &Guid); } diff --git a/xtldr/modules/xtos/CMakeLists.txt b/xtldr/modules/xtos/CMakeLists.txt deleted file mode 100644 index 695c2b6..0000000 --- a/xtldr/modules/xtos/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -# XT Boot Loader -PROJECT(XTLDR_XTOS) - -# Specify include directories -include_directories( - ${EXECTOS_SOURCE_DIR}/sdk/xtdk - ${XTLDR_SOURCE_DIR}/includes - ${XTLDR_XTOS_SOURCE_DIR}/includes) - -# Specify list of source code files -list(APPEND XTLDR_XTOS_SOURCE - ${XTLDR_SOURCE_DIR}/blproto.c - ${XTLDR_XTOS_SOURCE_DIR}/xtos.c) - -# Link bootloader executable -add_executable(xtos ${XTLDR_XTOS_SOURCE}) - -# Add linker libraries -target_link_libraries(xtos libxtos) - -# Set proper binary name and install target -set_target_properties(xtos PROPERTIES SUFFIX .efi) -set_install_target(xtos efi/boot/xtldr) - -# Set module entrypoint and subsystem -set_entrypoint(xtos "BlXtLdrModuleMain") -set_subsystem(xtos efi_boot_service_driver) diff --git a/xtldr/modules/xtos/includes/xtos.h b/xtldr/modules/xtos/includes/xtos.h deleted file mode 100644 index 272b93f..0000000 --- a/xtldr/modules/xtos/includes/xtos.h +++ /dev/null @@ -1,54 +0,0 @@ -/** - * PROJECT: ExectOS - * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtldr/modules/xtos/includes/xtos.h - * DESCRIPTION: XTOS boot protocol support header - * DEVELOPERS: Rafal Kupiec - */ - -#ifndef __XTLDR_MODULES_XTOS_H -#define __XTLDR_MODULES_XTOS_H - -#include - - -/* EFI XT Loader Protocol */ -EXTERN PXT_BOOT_LOADER_PROTOCOL XtLdrProtocol; - -/* XTOS kernel entry point */ -typedef VOID (XTAPI *PXT_ENTRY_POINT)(IN PKERNEL_INITIALIZATION_BLOCK BootParameters); - -/* XTOS boot protocol related routines forward references */ -XTCDECL -EFI_STATUS -XtBootSystem(IN PXT_BOOT_PROTOCOL_PARAMETERS Parameters); - -XTCDECL -EFI_STATUS -XtpBootSequence(IN PEFI_FILE_HANDLE BootDir, - IN PXT_BOOT_PROTOCOL_PARAMETERS Parameters); - - -XTCDECL -EFI_STATUS -XtpInitializeApicBase(IN PLIST_ENTRY MemoryMappings); - -XTCDECL -EFI_STATUS -XtpInitializeLoaderBlock(IN PLIST_ENTRY MemoryMappings, - IN PVOID *VirtualAddress); - -XTCDECL -EFI_STATUS -XtpLoadModule(IN PEFI_FILE_HANDLE BootDir, - IN PWCHAR FileName, - IN PVOID VirtualAddress, - IN LOADER_MEMORY_TYPE MemoryType, - OUT PPECOFF_IMAGE_CONTEXT *ImageContext); - -XTCDECL -EFI_STATUS -BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle, - IN PEFI_SYSTEM_TABLE SystemTable); - -#endif /* __XTLDR_MODULES_XTOS_H */ diff --git a/xtldr/modules/xtos_o/CMakeLists.txt b/xtldr/modules/xtos_o/CMakeLists.txt new file mode 100644 index 0000000..f157240 --- /dev/null +++ b/xtldr/modules/xtos_o/CMakeLists.txt @@ -0,0 +1,28 @@ +# XT Boot Loader +PROJECT(XTLDR_XTOS_O) + +# Specify include directories +include_directories( + ${EXECTOS_SOURCE_DIR}/sdk/xtdk + ${XTLDR_XTOS_O_SOURCE_DIR}/includes) + +# Specify list of source code files +list(APPEND XTLDR_XTOS_O_SOURCE + ${XTLDR_XTOS_O_SOURCE_DIR}/${ARCH}/memory.c + ${XTLDR_XTOS_O_SOURCE_DIR}/memory.c + ${XTLDR_XTOS_O_SOURCE_DIR}/xtos.c) + +# Link bootloader executable +add_executable(xtos_o ${XTLDR_XTOS_O_SOURCE}) + +# Add linker libraries +target_link_libraries(xtos_o libxtos libxtldr) + +# Set proper binary name and install target +set_target_properties(xtos_o PROPERTIES SUFFIX .efi) +set_install_target(xtos_o efi/boot/xtldr/modules) + +# Set module entrypoint and subsystem +set_entrypoint(xtos_o "XtLdrModuleMain") +set_linker_map(xtos_o TRUE) +set_subsystem(xtos_o efi_boot_service_driver) diff --git a/xtldr/amd64/memory.c b/xtldr/modules/xtos_o/amd64/memory.c similarity index 78% rename from xtldr/amd64/memory.c rename to xtldr/modules/xtos_o/amd64/memory.c index ee29723..e227867 100644 --- a/xtldr/amd64/memory.c +++ b/xtldr/modules/xtos_o/amd64/memory.c @@ -6,7 +6,7 @@ * DEVELOPERS: Rafal Kupiec */ -#include +#include /** @@ -30,7 +30,7 @@ */ XTCDECL EFI_STATUS -BlEnablePaging(IN PLIST_ENTRY MemoryMappings, +XtEnablePaging(IN PLIST_ENTRY MemoryMappings, IN PVOID VirtualAddress, IN PEFI_LOADED_IMAGE_PROTOCOL ImageProtocol, IN PVOID *PtePointer) @@ -38,11 +38,12 @@ BlEnablePaging(IN PLIST_ENTRY MemoryMappings, PLOADER_MEMORY_MAPPING Mapping; EFI_PHYSICAL_ADDRESS Address; PEFI_MEMORY_MAP MemoryMap; - PLIST_ENTRY ListEntry; + PLIST_ENTRY ListEntry, ModulesList, ModulesListEntry; + PXTBL_MODULE_INFO ModuleInfo; EFI_STATUS Status; /* Allocate pages for PML4 */ - Status = BlEfiMemoryAllocatePages(1, &Address); + Status = XtLdrProtocol->Memory.AllocatePages(1, &Address); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ @@ -53,17 +54,34 @@ BlEnablePaging(IN PLIST_ENTRY MemoryMappings, *PtePointer = (PVOID)(UINT_PTR)Address; RtlZeroMemory(*PtePointer, EFI_PAGE_SIZE); - /* Map XTLDR code */ - Status = BlAddVirtualMemoryMapping(MemoryMappings, ImageProtocol->ImageBase, ImageProtocol->ImageBase, - EFI_SIZE_TO_PAGES(ImageProtocol->ImageSize), LoaderFirmwareTemporary); - if(Status != STATUS_EFI_SUCCESS) + /* Get list of XTLDR modules */ + ModulesList = XtLdrProtocol->Protocol.GetModulesList(); + ModulesListEntry = ModulesList->Flink; + while(ModulesListEntry != ModulesList) { - /* Mapping the boot loader code failed */ - return Status; + /* Get module info */ + ModuleInfo = CONTAIN_RECORD(ModulesListEntry, XTBL_MODULE_INFO, Flink); + + /* Map module code */ + Status = XtAddVirtualMemoryMapping(MemoryMappings, ModuleInfo->ModuleBase, ModuleInfo->ModuleBase, + EFI_SIZE_TO_PAGES(ModuleInfo->ModuleSize), LoaderFirmwareTemporary); + + if(Status != STATUS_EFI_SUCCESS) + { + /* Mapping module code failed */ + return Status; + } + + /* Get next module */ + ModulesListEntry = ModulesListEntry->Flink; } + /* Map XTLDR code */ + XtAddVirtualMemoryMapping(MemoryMappings, ImageProtocol->ImageBase, ImageProtocol->ImageBase, + EFI_SIZE_TO_PAGES(ImageProtocol->ImageSize), LoaderFirmwareTemporary); + /* Add page mapping itself to memory mapping */ - Status = BlAddVirtualMemoryMapping(MemoryMappings, NULL, *PtePointer, 1, LoaderMemoryData); + Status = XtAddVirtualMemoryMapping(MemoryMappings, NULL, *PtePointer, 1, LoaderMemoryData); if(Status != STATUS_EFI_SUCCESS) { /* Mapping PML4 failed */ @@ -71,7 +89,7 @@ BlEnablePaging(IN PLIST_ENTRY MemoryMappings, } /* Iterate through and map all the mappings*/ - BlDbgPrint(L"Mapping and dumping EFI memory:\n"); + XtLdrProtocol->Debug.Print(L"Mapping and dumping EFI memory:\n"); ListEntry = MemoryMappings->Flink; while(ListEntry != MemoryMappings) { @@ -82,11 +100,11 @@ BlEnablePaging(IN PLIST_ENTRY MemoryMappings, if(Mapping->VirtualAddress) { /* Dump memory mapping */ - BlDbgPrint(L" Type=%02lu, PhysicalBase=0x%016lx, VirtualBase=0x%016lx, Pages=%lu\n", Mapping->MemoryType, + XtLdrProtocol->Debug.Print(L" Type=%02lu, PhysicalBase=0x%016lx, VirtualBase=0x%016lx, Pages=%lu\n", Mapping->MemoryType, Mapping->PhysicalAddress, Mapping->VirtualAddress, Mapping->NumberOfPages); /* Map memory */ - Status = BlMapVirtualMemory(MemoryMappings, (UINT_PTR)Mapping->VirtualAddress, + Status = XtMapVirtualMemory(MemoryMappings, (UINT_PTR)Mapping->VirtualAddress, (UINT_PTR)Mapping->PhysicalAddress, Mapping->NumberOfPages, PtePointer); if(Status != STATUS_EFI_SUCCESS) { @@ -100,15 +118,15 @@ BlEnablePaging(IN PLIST_ENTRY MemoryMappings, } /* Map zero page as well */ - BlMapVirtualMemory(MemoryMappings, 0, 0, 1, PtePointer); + XtMapVirtualMemory(MemoryMappings, 0, 0, 1, PtePointer); /* Allocate and zero-fill buffer for EFI memory map */ - BlEfiMemoryAllocatePool(sizeof(EFI_MEMORY_MAP), (PVOID*)&MemoryMap); + XtLdrProtocol->Memory.AllocatePool(sizeof(EFI_MEMORY_MAP), (PVOID*)&MemoryMap); RtlZeroMemory(MemoryMap, sizeof(EFI_MEMORY_MAP)); /* Get EFI memory map and prepare for exiting boot services */ - BlDbgPrint(L"Exiting EFI boot services\n"); - Status = BlGetMemoryMap(MemoryMap); + XtLdrProtocol->Debug.Print(L"Exiting EFI boot services\n"); + Status = XtLdrProtocol->Memory.GetMemoryMap(MemoryMap); if(Status != STATUS_EFI_SUCCESS) { /* Unable to get memory map */ @@ -116,18 +134,26 @@ BlEnablePaging(IN PLIST_ENTRY MemoryMappings, } /* Exit EFI Boot Services */ - Status = EfiSystemTable->BootServices->ExitBootServices(EfiImageHandle, MemoryMap->MapKey); - if(Status != STATUS_EFI_SUCCESS) - { - /* Retry as UEFI spec says to do it twice */ - Status = EfiSystemTable->BootServices->ExitBootServices(EfiImageHandle, MemoryMap->MapKey); - } + Status = XtLdrProtocol->Util.ExitBootServices(MemoryMap->MapKey); /* Check if exitted boot services successfully */ if(Status != STATUS_EFI_SUCCESS) { /* Failed to exit boot services */ - BlDbgPrint(L"Failed to exit boot services (Status code: %lx)\n", Status); + Status = XtLdrProtocol->Memory.GetMemoryMap(MemoryMap); + if(Status != STATUS_EFI_SUCCESS) + { + /* Unable to get memory map */ + return Status; + } + + Status = XtLdrProtocol->Util.ExitBootServices(MemoryMap->MapKey); + } + + /* Check if exitted boot services successfully */ + if(Status != STATUS_EFI_SUCCESS) + { + XtLdrProtocol->Console.Print(L"Failed to exit boot services (Status code: %lx)\n", Status); return STATUS_EFI_ABORTED; } @@ -165,7 +191,7 @@ BlEnablePaging(IN PLIST_ENTRY MemoryMappings, */ XTCDECL EFI_STATUS -BlMapVirtualMemory(IN PLIST_ENTRY MemoryMappings, +XtMapVirtualMemory(IN PLIST_ENTRY MemoryMappings, IN UINT_PTR VirtualAddress, IN UINT_PTR PhysicalAddress, IN UINT NumberOfPages, @@ -194,14 +220,14 @@ BlMapVirtualMemory(IN PLIST_ENTRY MemoryMappings, if(!((PHARDWARE_PTE)(*PtePointer))[Pml4Index].Valid) { /* Allocate pages for the PDPT */ - Status = BlEfiMemoryAllocatePages(1, &Address); + Status = XtLdrProtocol->Memory.AllocatePages(1, &Address); if (Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ return Status; } /* Add new memory mapping */ - Status = BlAddVirtualMemoryMapping(MemoryMappings, NULL, (PVOID)(UINT_PTR)Address, 1, LoaderMemoryData); + Status = XtAddVirtualMemoryMapping(MemoryMappings, NULL, (PVOID)(UINT_PTR)Address, 1, LoaderMemoryData); if(Status != STATUS_EFI_SUCCESS) { /* Memory mapping failed */ return Status; @@ -228,14 +254,14 @@ BlMapVirtualMemory(IN PLIST_ENTRY MemoryMappings, if(!PageDirectoryPointTable[PdpIndex].Valid) { /* Allocate pages for the PD */ - Status = BlEfiMemoryAllocatePages(1, &Address); + Status = XtLdrProtocol->Memory.AllocatePages(1, &Address); if (Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ return Status; } /* Add new memory mapping */ - Status = BlAddVirtualMemoryMapping(MemoryMappings, NULL, (PVOID)(UINT_PTR)Address, 1, LoaderMemoryData); + Status = XtAddVirtualMemoryMapping(MemoryMappings, NULL, (PVOID)(UINT_PTR)Address, 1, LoaderMemoryData); if (Status != STATUS_EFI_SUCCESS) { /* Memory mapping failed */ return Status; @@ -262,14 +288,14 @@ BlMapVirtualMemory(IN PLIST_ENTRY MemoryMappings, if(!PageDirectory[PdIndex].Valid) { /* Allocate pages for the PT */ - Status = BlEfiMemoryAllocatePages(1, &Address); + Status = XtLdrProtocol->Memory.AllocatePages(1, &Address); if (Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ return Status; } /* Add new memory mapping */ - Status = BlAddVirtualMemoryMapping(MemoryMappings, NULL, (PVOID)(UINT_PTR)Address, 1, LoaderMemoryData); + Status = XtAddVirtualMemoryMapping(MemoryMappings, NULL, (PVOID)(UINT_PTR)Address, 1, LoaderMemoryData); if (Status != STATUS_EFI_SUCCESS) { /* Memory mapping failed */ return Status; diff --git a/xtldr/i686/memory.c b/xtldr/modules/xtos_o/i686/memory.c similarity index 78% rename from xtldr/i686/memory.c rename to xtldr/modules/xtos_o/i686/memory.c index ae99f4c..3ccf644 100644 --- a/xtldr/i686/memory.c +++ b/xtldr/modules/xtos_o/i686/memory.c @@ -6,7 +6,7 @@ * DEVELOPERS: Rafal Kupiec */ -#include +#include /** @@ -30,7 +30,7 @@ */ XTCDECL EFI_STATUS -BlEnablePaging(IN PLIST_ENTRY MemoryMappings, +XtEnablePaging(IN PLIST_ENTRY MemoryMappings, IN PVOID VirtualAddress, IN PEFI_LOADED_IMAGE_PROTOCOL ImageProtocol, IN PVOID *PtePointer) @@ -41,7 +41,8 @@ BlEnablePaging(IN PLIST_ENTRY MemoryMappings, PEFI_MEMORY_DESCRIPTOR Descriptor; PLOADER_MEMORY_MAPPING Mapping; PEFI_MEMORY_MAP MemoryMap; - PLIST_ENTRY ListEntry; + PLIST_ENTRY ListEntry, ModulesList, ModulesListEntry; + PXTBL_MODULE_INFO ModuleInfo; EFI_STATUS Status; UINT Index; @@ -60,16 +61,16 @@ BlEnablePaging(IN PLIST_ENTRY MemoryMappings, if(!(CpuRegisters->Edx & CPUID_FEATURES_EDX_PAE)) { /* No PAE support */ - BlDbgPrint(L"ERROR: PAE extension not supported by the CPU\n"); + XtLdrProtocol->Debug.Print(L"ERROR: PAE extension not supported by the CPU\n"); return STATUS_EFI_UNSUPPORTED; } /* Allocate and zero-fill buffer for EFI memory map */ - BlEfiMemoryAllocatePool(sizeof(EFI_MEMORY_MAP), (PVOID*)&MemoryMap); + XtLdrProtocol->Memory.AllocatePool(sizeof(EFI_MEMORY_MAP), (PVOID*)&MemoryMap); RtlZeroMemory(MemoryMap, sizeof(EFI_MEMORY_MAP)); /* Get EFI memory map */ - Status = BlGetMemoryMap(MemoryMap); + Status = XtLdrProtocol->Memory.GetMemoryMap(MemoryMap); if(Status != STATUS_EFI_SUCCESS) { /* Unable to get memory map */ @@ -103,7 +104,7 @@ BlEnablePaging(IN PLIST_ENTRY MemoryMappings, } /* Allocate pages for the PDPT address */ - Status = BlEfiMemoryAllocatePages(1, &PDPTAddress); + Status = XtLdrProtocol->Memory.AllocatePages(1, &PDPTAddress); if(Status != STATUS_EFI_SUCCESS) { return Status; } @@ -128,7 +129,7 @@ BlEnablePaging(IN PLIST_ENTRY MemoryMappings, Address = 0x100000; /* Allocate pages for the PFN */ - Status = BlEfiMemoryAllocatePages(4, &Address); + Status = XtLdrProtocol->Memory.AllocatePages(4, &Address); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ @@ -151,17 +152,34 @@ BlEnablePaging(IN PLIST_ENTRY MemoryMappings, Address += EFI_PAGE_SIZE; } - /* Map XTLDR code */ - Status = BlAddVirtualMemoryMapping(MemoryMappings, ImageProtocol->ImageBase, ImageProtocol->ImageBase, - EFI_SIZE_TO_PAGES(ImageProtocol->ImageSize), LoaderFirmwareTemporary); - if(Status != STATUS_EFI_SUCCESS) + /* Get list of XTLDR modules */ + ModulesList = XtLdrProtocol->Protocol.GetModulesList(); + ModulesListEntry = ModulesList->Flink; + while(ModulesListEntry != ModulesList) { - /* Mapping the boot loader code failed */ - return Status; + /* Get module info */ + ModuleInfo = CONTAIN_RECORD(ModulesListEntry, XTBL_MODULE_INFO, Flink); + + /* Map module code */ + XtAddVirtualMemoryMapping(MemoryMappings, ModuleInfo->ModuleBase, ModuleInfo->ModuleBase, + EFI_SIZE_TO_PAGES(ModuleInfo->ModuleSize), LoaderFirmwareTemporary); + + if(Status != STATUS_EFI_SUCCESS) + { + /* Mapping module code failed */ + return Status; + } + + /* Get next module */ + ModulesListEntry = ModulesListEntry->Flink; } + /* Map XTLDR code */ + XtAddVirtualMemoryMapping(MemoryMappings, ImageProtocol->ImageBase, ImageProtocol->ImageBase, + EFI_SIZE_TO_PAGES(ImageProtocol->ImageSize), LoaderFirmwareTemporary); + /* Add page mapping itself to memory mapping */ - Status = BlAddVirtualMemoryMapping(MemoryMappings, NULL, *PtePointer, 1, LoaderMemoryData); + Status = XtAddVirtualMemoryMapping(MemoryMappings, NULL, *PtePointer, 1, LoaderMemoryData); if(Status != STATUS_EFI_SUCCESS) { /* Mapping PD failed */ @@ -169,7 +187,7 @@ BlEnablePaging(IN PLIST_ENTRY MemoryMappings, } /* Iterate through and map all the mappings */ - BlDbgPrint(L"Mapping and dumping EFI memory:\n"); + XtLdrProtocol->Debug.Print(L"Mapping and dumping EFI memory:\n"); ListEntry = MemoryMappings->Flink; while(ListEntry != MemoryMappings) { @@ -180,11 +198,11 @@ BlEnablePaging(IN PLIST_ENTRY MemoryMappings, if(Mapping->VirtualAddress) { /* Dump memory mapping */ - BlDbgPrint(L" Type=%02lu, PhysicalBase=0x%08lx, VirtualBase=0x%08lx, Pages=%lu\n", Mapping->MemoryType, - Mapping->PhysicalAddress, Mapping->VirtualAddress, Mapping->NumberOfPages); + XtLdrProtocol->Debug.Print(L" Type=%02lu, PhysicalBase=0x%08lx, VirtualBase=0x%08lx, Pages=%lu\n", Mapping->MemoryType, + Mapping->PhysicalAddress, Mapping->VirtualAddress, Mapping->NumberOfPages); /* Map memory */ - Status = BlMapVirtualMemory(MemoryMappings, (UINT_PTR)Mapping->VirtualAddress, + Status = XtMapVirtualMemory(MemoryMappings, (UINT_PTR)Mapping->VirtualAddress, (UINT_PTR)Mapping->PhysicalAddress, Mapping->NumberOfPages, PtePointer); if(Status != STATUS_EFI_SUCCESS) { @@ -198,14 +216,14 @@ BlEnablePaging(IN PLIST_ENTRY MemoryMappings, } /* Map zero page as well */ - BlMapVirtualMemory(MemoryMappings, 0, 0, 1, PtePointer); + XtMapVirtualMemory(MemoryMappings, 0, 0, 1, PtePointer); /* Zero-fill buffer for EFI memory map */ RtlZeroMemory(MemoryMap, sizeof(EFI_MEMORY_MAP)); /* Get EFI memory map and prepare for exiting boot services */ - BlDbgPrint(L"Exiting EFI boot services\n"); - Status = BlGetMemoryMap(MemoryMap); + XtLdrProtocol->Debug.Print(L"Exiting EFI boot services\n"); + Status = XtLdrProtocol->Memory.GetMemoryMap(MemoryMap); if(Status != STATUS_EFI_SUCCESS) { /* Unable to get memory map */ @@ -213,18 +231,27 @@ BlEnablePaging(IN PLIST_ENTRY MemoryMappings, } /* Exit EFI Boot Services */ - Status = EfiSystemTable->BootServices->ExitBootServices(EfiImageHandle, MemoryMap->MapKey); + Status = XtLdrProtocol->Util.ExitBootServices(MemoryMap->MapKey); + + /* Check if exitted boot services successfully */ if(Status != STATUS_EFI_SUCCESS) { - /* Retry as UEFI spec says to do it twice */ - Status = EfiSystemTable->BootServices->ExitBootServices(EfiImageHandle, MemoryMap->MapKey); + /* Failed to exit boot services */ + Status = XtLdrProtocol->Memory.GetMemoryMap(MemoryMap); + if(Status != STATUS_EFI_SUCCESS) + { + /* Unable to get memory map */ + return Status; + } + + Status = XtLdrProtocol->Util.ExitBootServices(MemoryMap->MapKey); } /* Check if exitted boot services successfully */ if(Status != STATUS_EFI_SUCCESS) { /* Failed to exit boot services */ - BlDbgPrint(L"Failed to exit boot services (Status code: %lx)\n", Status); + XtLdrProtocol->Debug.Print(L"Failed to exit boot services (Status code: %lx)\n", Status); return STATUS_EFI_ABORTED; } @@ -268,7 +295,7 @@ BlEnablePaging(IN PLIST_ENTRY MemoryMappings, */ XTCDECL EFI_STATUS -BlMapVirtualMemory(IN PLIST_ENTRY MemoryMappings, +XtMapVirtualMemory(IN PLIST_ENTRY MemoryMappings, IN UINT_PTR VirtualAddress, IN UINT_PTR PhysicalAddress, IN UINT NumberOfPages, @@ -294,7 +321,7 @@ BlMapVirtualMemory(IN PLIST_ENTRY MemoryMappings, /* Validate Page Directory */ if(!PageDirectory[PdIndex].Valid) { /* Allocate pages for new page table */ - Status = BlEfiMemoryAllocatePages(1, &Address); + Status = XtLdrProtocol->Memory.AllocatePages(1, &Address); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ return Status; diff --git a/xtldr/modules/xtos_o/includes/xtos.h b/xtldr/modules/xtos_o/includes/xtos.h new file mode 100644 index 0000000..34695c5 --- /dev/null +++ b/xtldr/modules/xtos_o/includes/xtos.h @@ -0,0 +1,107 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/modules/xtos/includes/xtos.h + * DESCRIPTION: XTOS boot protocol support header + * DEVELOPERS: Rafal Kupiec + */ + +#ifndef __XTLDR_MODULES_XTOS_H +#define __XTLDR_MODULES_XTOS_H + +#include + + +typedef VOID (*PXT_FRAMEBUFFER_GET_DISPLAY_DRIVER)(OUT PWCHAR DriverName); +typedef VOID (*PXT_FRAMEBUFFER_GET_DISPLAY_INFORMATION)(OUT PLOADER_GRAPHICS_INFORMATION_BLOCK InformationBlock); +typedef EFI_STATUS (*PXT_FRAMEBUFFER_INITIALIZE)(); +typedef VOID (*PXT_FRAMEBUFFER_PRINT_DISPLAY_INFORMATION)(); + +/* XT framebuffer support protocol */ +typedef struct _XT_FRAMEBUFFER_PROTOCOL +{ + PXT_FRAMEBUFFER_GET_DISPLAY_DRIVER GetDisplayDriver; + PXT_FRAMEBUFFER_GET_DISPLAY_INFORMATION GetDisplayInformation; + PXT_FRAMEBUFFER_INITIALIZE Initialize; + PXT_FRAMEBUFFER_PRINT_DISPLAY_INFORMATION PrintDisplayInformation; +} XT_FRAMEBUFFER_PROTOCOL, *PXT_FRAMEBUFFER_PROTOCOL; + +/* EFI XT Loader Protocol */ +EXTERN PXTBL_LOADER_PROTOCOL XtLdrProtocol; + +/* XTOS kernel entry point */ +typedef VOID (XTAPI *PXT_ENTRY_POINT)(IN PKERNEL_INITIALIZATION_BLOCK BootParameters); + +/* XTOS boot protocol related routines forward references */ +XTCDECL +EFI_STATUS +XtAddVirtualMemoryMapping(IN PLIST_ENTRY MemoryMappings, + IN PVOID VirtualAddress, + IN PVOID PhysicalAddress, + IN UINT NumberOfPages, + IN LOADER_MEMORY_TYPE MemoryType); + +XTCDECL +EFI_STATUS +XtBootSystem(IN PXTBL_BOOT_PARAMETERS Parameters); + +XTCDECL +LOADER_MEMORY_TYPE +XtConvertEfiMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType); + +XTCDECL +EFI_STATUS +XtEnablePaging(IN PLIST_ENTRY MemoryMappings, + IN PVOID VirtualAddress, + IN PEFI_LOADED_IMAGE_PROTOCOL ImageProtocol, + IN PVOID *PtePointer); + +XTCDECL +EFI_STATUS +XtGetVirtualAddress(IN PLIST_ENTRY MemoryMappings, + IN PVOID PhysicalAddress, + OUT PVOID *VirtualAddress); + +XTCDECL +EFI_STATUS +XtInitializeVirtualMemory(IN OUT PLIST_ENTRY MemoryMappings, + IN OUT PVOID *MemoryMapAddress); + +XTCDECL +EFI_STATUS +XtMapVirtualMemory(IN PLIST_ENTRY MemoryMappings, + IN UINT_PTR VirtualAddress, + IN UINT_PTR PhysicalAddress, + IN UINT NumberOfPages, + IN OUT PVOID *PtePointer); + +XTCDECL +EFI_STATUS +XtpBootSequence(IN PEFI_FILE_HANDLE BootDir, + IN PXTBL_BOOT_PARAMETERS Parameters); + + +XTCDECL +EFI_STATUS +XtpInitializeApicBase(IN PLIST_ENTRY MemoryMappings); + +XTCDECL +EFI_STATUS +XtpInitializeLoaderBlock(IN PLIST_ENTRY MemoryMappings, + IN PVOID *VirtualAddress, + IN PXTBL_BOOT_PARAMETERS Parameters); + +XTCDECL +EFI_STATUS +XtpLoadModule(IN PEFI_FILE_HANDLE BootDir, + IN PWCHAR FileName, + IN PVOID VirtualAddress, + IN LOADER_MEMORY_TYPE MemoryType, + OUT PPECOFF_IMAGE_CONTEXT *ImageContext); + +XTCDECL +EFI_STATUS +BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle, + IN PEFI_SYSTEM_TABLE SystemTable); + +#endif /* __XTLDR_MODULES_XTOS_H */ diff --git a/xtldr/modules/xtos_o/memory.c b/xtldr/modules/xtos_o/memory.c new file mode 100644 index 0000000..c64a9cc --- /dev/null +++ b/xtldr/modules/xtos_o/memory.c @@ -0,0 +1,385 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/memory.c + * DESCRIPTION: EFI memory management + * DEVELOPERS: Rafal Kupiec + */ + +#include + + +/** + * Adds a physical to virtual address mapping to the linked list for future processing. + * + * @param MemoryMapping + * Supplies the head of the memory mapping list. + * + * @param VirtualAddress + * Supplies a virtual address where the physical address should be mapped. + * + * @param PhysicalAddress + * Supplies a physical address which will be mapped. + * + * @param NumberOfPages + * Supplies a number of pages which will be mapped. + * + * @param MemoryType + * Supplies the type of memory that will be assigned to the memory descriptor. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +XtAddVirtualMemoryMapping(IN PLIST_ENTRY MemoryMappings, + IN PVOID VirtualAddress, + IN PVOID PhysicalAddress, + IN UINT NumberOfPages, + IN LOADER_MEMORY_TYPE MemoryType) +{ + PLOADER_MEMORY_MAPPING Mapping1, Mapping2, Mapping3; + PVOID PhysicalAddressEnd, PhysicalAddress2End; + PLIST_ENTRY ListEntry, MappingListEntry; + SIZE_T NumberOfMappedPages; + EFI_STATUS Status; + + /* Allocate memory for new mapping */ + Status = XtLdrProtocol->Memory.AllocatePool(sizeof(LOADER_MEMORY_MAPPING), (PVOID *)&Mapping1); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory allocation failure */ + return Status; + } + + /* Set mapping fields */ + Mapping1->PhysicalAddress = PhysicalAddress; + Mapping1->VirtualAddress = VirtualAddress; + Mapping1->NumberOfPages = NumberOfPages; + Mapping1->MemoryType = MemoryType; + + /* Calculate the end of the physical address */ + PhysicalAddressEnd = (PUINT8)PhysicalAddress + (NumberOfPages * EFI_PAGE_SIZE) - 1; + + /* Iterate through all the mappings already set to insert new mapping at the correct place */ + ListEntry = MemoryMappings->Flink; + while(ListEntry != MemoryMappings) + { + /* Take a mapping from the list and calculate its end of physical address */ + Mapping2 = CONTAIN_RECORD(ListEntry, LOADER_MEMORY_MAPPING, ListEntry); + PhysicalAddress2End = (PUINT8)Mapping2->PhysicalAddress + (Mapping2->NumberOfPages * EFI_PAGE_SIZE) - 1 ; + + /* Check if they overlap */ + if(PhysicalAddressEnd > Mapping2->PhysicalAddress && PhysicalAddressEnd <= PhysicalAddress2End) + { + /* Make sure it's memory type is LoaderFree */ + if(Mapping2->MemoryType != LoaderFree) + { + /* LoaderFree memory type is strictly expected */ + return STATUS_EFI_INVALID_PARAMETER; + } + + /* Calculate number of pages for this mapping */ + NumberOfMappedPages = ((PUINT8)PhysicalAddress2End - (PUINT8)PhysicalAddressEnd) / EFI_PAGE_SIZE; + if(NumberOfMappedPages > 0) + { + /* Pages associated to the mapping, allocate memory for it */ + Status = XtLdrProtocol->Memory.AllocatePool(sizeof(LOADER_MEMORY_MAPPING), (PVOID*)&Mapping3); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory allocation failure */ + return Status; + } + + /* Set mapping fields and insert it on the top */ + Mapping3->PhysicalAddress = (PUINT8)PhysicalAddressEnd + 1; + Mapping3->VirtualAddress = NULL; + Mapping3->NumberOfPages = NumberOfMappedPages; + Mapping3->MemoryType = Mapping2->MemoryType; + RtlInsertHeadList(&Mapping2->ListEntry, &Mapping3->ListEntry); + } + + /* Calculate number of pages and the end of the physical address */ + Mapping2->NumberOfPages = ((PUINT8)PhysicalAddressEnd + 1 - + (PUINT8)Mapping2->PhysicalAddress) / EFI_PAGE_SIZE; + PhysicalAddress2End = (PUINT8)Mapping2->PhysicalAddress + (Mapping2->NumberOfPages * EFI_PAGE_SIZE) - 1; + } + + /* Check if they overlap */ + if(Mapping1->PhysicalAddress > Mapping2->PhysicalAddress && Mapping1->PhysicalAddress < PhysicalAddress2End) + { + /* Make sure it's memory type is LoaderFree */ + if(Mapping2->MemoryType != LoaderFree) + { + /* LoaderFree memory type is strictly expected */ + return STATUS_EFI_INVALID_PARAMETER; + } + + /* Calculate number of pages for this mapping */ + NumberOfMappedPages = ((PUINT8)PhysicalAddress2End + 1 - (PUINT8)Mapping1->PhysicalAddress) / EFI_PAGE_SIZE; + if(NumberOfMappedPages > 0) + { + /* Pages associated to the mapping, allocate memory for it */ + Status = XtLdrProtocol->Memory.AllocatePool(sizeof(LOADER_MEMORY_MAPPING), (PVOID*)&Mapping3); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory allocation failure */ + return Status; + } + + /* Set mapping fields and insert it on the top */ + Mapping3->PhysicalAddress = Mapping1->PhysicalAddress; + Mapping3->VirtualAddress = NULL; + Mapping3->NumberOfPages = NumberOfMappedPages; + Mapping3->MemoryType = Mapping2->MemoryType; + RtlInsertHeadList(&Mapping2->ListEntry, &Mapping3->ListEntry); + } + + /* Calculate number of pages and the end of the physical address */ + Mapping2->NumberOfPages = ((PUINT8)Mapping1->PhysicalAddress - + (PUINT8)Mapping2->PhysicalAddress) / EFI_PAGE_SIZE; + PhysicalAddress2End = (PUINT8)Mapping2->PhysicalAddress + (Mapping2->NumberOfPages * EFI_PAGE_SIZE) - 1; + } + + /* Check if mapping is really needed */ + if((Mapping2->PhysicalAddress >= Mapping1->PhysicalAddress && PhysicalAddress2End <= PhysicalAddressEnd) || + (Mapping2->NumberOfPages == 0)) + { + /* Make sure it's memory type is LoaderFree */ + if(Mapping2->MemoryType != LoaderFree) + { + /* LoaderFree memory type is strictly expected */ + return STATUS_EFI_INVALID_PARAMETER; + } + + /* Store address of the next mapping */ + MappingListEntry = ListEntry->Flink; + + /* Remove mapping from the list and free up it's memory */ + RtlRemoveEntryList(&Mapping2->ListEntry); + Status = XtLdrProtocol->Memory.FreePool(Mapping2); + ListEntry = MappingListEntry; + + /* Go to the next mapping */ + continue; + } + + /* Determine phsical address order */ + if(Mapping2->PhysicalAddress > Mapping1->PhysicalAddress) + { + /* Insert new mapping in front */ + RtlInsertHeadList(Mapping2->ListEntry.Blink, &Mapping1->ListEntry); + return STATUS_EFI_SUCCESS; + } + + /* Get next mapping from the list */ + ListEntry = ListEntry->Flink; + } + + /* Insert new mapping to the end of the list and return success */ + RtlInsertTailList(MemoryMappings, &Mapping1->ListEntry); + return STATUS_EFI_SUCCESS; +} + +/** + * Converts an EFI memory type into an XTOS memory type. + * + * @param EfiMemoryType + * Supplies the EFI memory type. + * + * @return Returns a conversion of the memory type. + * + * @since XT 1.0 + */ +XTCDECL +LOADER_MEMORY_TYPE +XtConvertEfiMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType) +{ + LOADER_MEMORY_TYPE MemoryType; + + /* Check EFI memory type and convert to XTOS memory type */ + switch(EfiMemoryType) + { + case EfiACPIMemoryNVS: + case EfiACPIReclaimMemory: + case EfiPalCode: + MemoryType = LoaderSpecialMemory; + break; + case EfiRuntimeServicesCode: + case EfiRuntimeServicesData: + case EfiMemoryMappedIO: + case EfiMemoryMappedIOPortSpace: + MemoryType = LoaderFirmwarePermanent; + break; + case EfiBootServicesData: + case EfiLoaderCode: + case EfiLoaderData: + MemoryType = LoaderFirmwareTemporary; + break; + case EfiUnusableMemory: + MemoryType = LoaderBad; + break; + default: + MemoryType = LoaderFree; + break; + } + + /* Return XTOS memory type */ + return MemoryType; +} + +/** + * Attempts to find a virtual address of the specified physical address in memory mappings. + * + * @param MemoryMappings + * Supplies a pointer to linked list containing all memory mappings. + * + * @param PhysicalAddress + * Supplies a physical address to search for in the mappings. + * + * @param VirtualAddress + * Supplies a buffer, where mapped virtual address of the found mapping will be stored. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +XtGetVirtualAddress(IN PLIST_ENTRY MemoryMappings, + IN PVOID PhysicalAddress, + OUT PVOID *VirtualAddress) +{ + PLOADER_MEMORY_MAPPING Mapping; + PLIST_ENTRY ListEntry; + + /* NULLify virtual address */ + *VirtualAddress = NULL; + + /* Iterate over memory mappings in order to find descriptor containing a physical address */ + ListEntry = MemoryMappings->Flink; + while(ListEntry != MemoryMappings) + { + /* Get mapping from linked list */ + Mapping = CONTAIN_RECORD(ListEntry, LOADER_MEMORY_MAPPING, ListEntry); + + /* Make sure any virtual address is set */ + if(Mapping->VirtualAddress) + { + /* Check if provided physical address is in range of this mapping */ + if((PhysicalAddress >= Mapping->PhysicalAddress) && + (PhysicalAddress < Mapping->PhysicalAddress + (Mapping->NumberOfPages * EFI_PAGE_SIZE))) + { + /* Calculate virtual address based on the mapping */ + *VirtualAddress = PhysicalAddress - Mapping->PhysicalAddress + Mapping->VirtualAddress; + } + } + + /* Get next element from the list */ + ListEntry = ListEntry->Flink; + } + + /* If virtual address is still NULL, then mapping was not found */ + if(*VirtualAddress == NULL) + { + /* Mapping not found */ + return STATUS_EFI_NOT_FOUND; + } + + /* Mapping found, return success */ + return STATUS_EFI_SUCCESS; +} + +/** + * Initializes virtual memory by adding known and general mappings. + * + * @param MemoryMappings + * Supplies a pointer to linked list containing all memory mappings. + * + * @param MemoryMapAddress + * Supplies an address of the mapped virtual memory area. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +XtInitializeVirtualMemory(IN OUT PLIST_ENTRY MemoryMappings, + IN OUT PVOID *MemoryMapAddress) +{ + PEFI_MEMORY_DESCRIPTOR Descriptor; + LOADER_MEMORY_TYPE MemoryType; + PEFI_MEMORY_MAP MemoryMap; + SIZE_T DescriptorCount; + PUCHAR VirtualAddress; + EFI_STATUS Status; + SIZE_T Index; + + /* Set initial virtual address */ + VirtualAddress = *MemoryMapAddress; + + /* Allocate and zero-fill buffer for EFI memory map */ + XtLdrProtocol->Memory.AllocatePool(sizeof(EFI_MEMORY_MAP), (PVOID*)&MemoryMap); + RtlZeroMemory(MemoryMap, sizeof(EFI_MEMORY_MAP)); + + /* Get EFI memory map */ + Status = XtLdrProtocol->Memory.GetMemoryMap(MemoryMap); + if(Status != STATUS_EFI_SUCCESS) + { + return Status; + } + + /* Calculate descriptors count and get first one */ + Descriptor = MemoryMap->Map; + DescriptorCount = MemoryMap->MapSize / MemoryMap->DescriptorSize; + + /* Iterate through all descriptors from the memory map */ + for(Index = 0; Index < DescriptorCount; Index++) + { + /* Make sure descriptor does not go beyond lowest physical page */ + if((Descriptor->PhysicalStart + (Descriptor->NumberOfPages * EFI_PAGE_SIZE)) <= (UINT_PTR)-1) + { + /* Convert EFI memory type into XTOS memory type */ + MemoryType = XtConvertEfiMemoryType(Descriptor->Type); + + /* Do memory mappings depending on memory type */ + if(MemoryType == LoaderFirmwareTemporary) + { + /* Map EFI firmware code */ + Status = XtAddVirtualMemoryMapping(MemoryMappings, (PVOID)Descriptor->PhysicalStart, + (PVOID)Descriptor->PhysicalStart, Descriptor->NumberOfPages, MemoryType); + } + else if(MemoryType != LoaderFree) + { + /* Add any non-free memory mapping */ + Status = XtAddVirtualMemoryMapping(MemoryMappings, VirtualAddress, (PVOID)Descriptor->PhysicalStart, + Descriptor->NumberOfPages, MemoryType); + + /* Calculate next valid virtual address */ + VirtualAddress += Descriptor->NumberOfPages * EFI_PAGE_SIZE; + } + else + { + /* Map all other memory as loader free */ + Status = XtAddVirtualMemoryMapping(MemoryMappings, NULL, (PVOID)Descriptor->PhysicalStart, + Descriptor->NumberOfPages, LoaderFree); + } + + /* Make sure memory mapping succeeded */ + if(Status != STATUS_EFI_SUCCESS) + { + /* Mapping failed */ + return Status; + } + + /* Grab next descriptor */ + Descriptor = (PEFI_MEMORY_DESCRIPTOR)((PUCHAR)Descriptor + MemoryMap->DescriptorSize); + } + } + + /* Store next valid virtual address and return success */ + *MemoryMapAddress = VirtualAddress; + return STATUS_EFI_SUCCESS; +} diff --git a/xtldr/modules/xtos/xtos.c b/xtldr/modules/xtos_o/xtos.c similarity index 73% rename from xtldr/modules/xtos/xtos.c rename to xtldr/modules/xtos_o/xtos.c index c663e6a..3393367 100644 --- a/xtldr/modules/xtos/xtos.c +++ b/xtldr/modules/xtos_o/xtos.c @@ -9,20 +9,18 @@ #include -/* EFI Image Handle */ -EFI_HANDLE EfiImageHandle; - -/* EFI System Table */ -PEFI_SYSTEM_TABLE EfiSystemTable; +/* XTOS module information */ +XTBL_MODINFO = L"XTOS boot protocol support"; +XTBL_MODDEPS = {L"fb_o", L"pecoff_o"}; /* EFI XT Loader Protocol */ -PXT_BOOT_LOADER_PROTOCOL XtLdrProtocol; +PXTBL_LOADER_PROTOCOL XtLdrProtocol; /* XTOS PE/COFF Image Protocol */ -PXT_PECOFF_IMAGE_PROTOCOL XtPeCoffProtocol; +PXTBL_EXECUTABLE_IMAGE_PROTOCOL XtPeCoffProtocol; /* XTOS Boot Protocol */ -XT_BOOT_PROTOCOL XtBootProtocol; +XTBL_BOOT_PROTOCOL XtBootProtocol; /* XTOS Page Map */ PVOID XtPageMap; @@ -39,23 +37,23 @@ PVOID XtPageMap; */ XTCDECL EFI_STATUS -XtBootSystem(IN PXT_BOOT_PROTOCOL_PARAMETERS Parameters) +XtBootSystem(IN PXTBL_BOOT_PARAMETERS Parameters) { EFI_GUID PeCoffProtocolGuid = XT_PECOFF_IMAGE_PROTOCOL_GUID; - EFI_HANDLE DiskHandle; + EFI_HANDLE DiskHandle, ProtocolHandle; PEFI_FILE_HANDLE FsHandle, BootDir; PWCHAR SystemPath; EFI_STATUS Status; /* Print debug message */ - XtLdrProtocol->DbgPrint(L"XTOS boot protocol activated\n"); + XtLdrProtocol->Debug.Print(L"XTOS boot protocol activated\n"); /* Open the XT PE/COFF protocol */ - Status = BlLoadXtProtocol((PVOID *)&XtPeCoffProtocol, &PeCoffProtocolGuid); + Status = XtLdrProtocol->Protocol.Open(&ProtocolHandle, (PVOID *)&XtPeCoffProtocol, &PeCoffProtocolGuid); if(Status != STATUS_EFI_SUCCESS) { /* Failed to open loader protocol */ - XtLdrProtocol->DbgPrint(L"ERROR: Unable to load PE/COFF image protocol\n"); + XtLdrProtocol->Debug.Print(L"ERROR: Unable to load PE/COFF image protocol\n"); return STATUS_EFI_PROTOCOL_ERROR; } @@ -63,7 +61,7 @@ XtBootSystem(IN PXT_BOOT_PROTOCOL_PARAMETERS Parameters) if(Parameters->DevicePath == NULL) { /* No device path set */ - XtLdrProtocol->DbgPrint(L"ERROR: No device path provided, unable to boot system\n"); + XtLdrProtocol->Debug.Print(L"ERROR: No device path provided, unable to boot system\n"); return STATUS_EFI_INVALID_PARAMETER; } @@ -85,7 +83,7 @@ XtBootSystem(IN PXT_BOOT_PROTOCOL_PARAMETERS Parameters) if(((*SystemPath | 32) - 'a' >= 26) && ((*SystemPath - '0') >= 10)) { /* Invalid path specified */ - XtLdrProtocol->DbgPrint(L"ERROR: System path does not point to the valid XTOS installation\n"); + XtLdrProtocol->Debug.Print(L"ERROR: System path does not point to the valid XTOS installation\n"); return STATUS_EFI_INVALID_PARAMETER; } /* Check next character in the path */ @@ -95,7 +93,7 @@ XtBootSystem(IN PXT_BOOT_PROTOCOL_PARAMETERS Parameters) else { /* Fallback to '/ExectOS' by default */ - XtLdrProtocol->DbgPrint(L"WARNING: No system path set, falling back to defaults\n"); + XtLdrProtocol->Debug.Print(L"WARNING: No system path set, falling back to defaults\n"); Parameters->SystemPath = L"\\ExectOS"; } @@ -103,31 +101,31 @@ XtBootSystem(IN PXT_BOOT_PROTOCOL_PARAMETERS Parameters) if(Parameters->KernelFile == NULL) { /* No kernel filename set, fallback to default */ - XtLdrProtocol->DbgPrint(L"WARNING: No kernel file specified, falling back to defaults\n"); + XtLdrProtocol->Debug.Print(L"WARNING: No kernel file specified, falling back to defaults\n"); Parameters->KernelFile = L"xtoskrnl.exe"; } /* Check if provided any kernel boot arguments */ - if(Parameters->Arguments == NULL) + if(Parameters->Parameters == NULL) { /* No argument supplied */ - Parameters->Arguments = L""; + Parameters->Parameters = L""; } /* Print a debug message */ - XtLdrProtocol->DbgPrint(L"[XTOS] ARC Path: %S\n" - L"[XTOS] System Path: %S\n" - L"[XTOS] Kernel File: %S\n" - L"[XTOS] Boot Arguments: %S\n", + XtLdrProtocol->Debug.Print(L"[XTOS] ARC Path: %S\n" + L"[XTOS] System Path: %S\n" + L"[XTOS] Kernel File: %S\n" + L"[XTOS] Boot Arguments: %S\n", Parameters->ArcName, Parameters->SystemPath, - Parameters->KernelFile, Parameters->Arguments); + Parameters->KernelFile, Parameters->Parameters); /* Open EFI volume */ - Status = XtLdrProtocol->OpenVolume(NULL, &DiskHandle, &FsHandle); + Status = XtLdrProtocol->Disk.OpenVolume(NULL, &DiskHandle, &FsHandle); if(Status != STATUS_EFI_SUCCESS) { /* Failed to open a volume */ - XtLdrProtocol->DbgPrint(L"ERROR: Unable to open boot volume\n"); + XtLdrProtocol->Debug.Print(L"ERROR: Unable to open boot volume\n"); return Status; } @@ -142,17 +140,17 @@ XtBootSystem(IN PXT_BOOT_PROTOCOL_PARAMETERS Parameters) if(Status == STATUS_EFI_NOT_FOUND) { /* Directory not found, nothing to load */ - XtLdrProtocol->DbgPrint(L"ERROR: System boot directory not found\n"); + XtLdrProtocol->Debug.Print(L"ERROR: System boot directory not found\n"); /* Close volume */ - XtLdrProtocol->CloseVolume(DiskHandle); + XtLdrProtocol->Disk.CloseVolume(DiskHandle); return Status; } else if(Status != STATUS_EFI_SUCCESS) { /* Failed to open directory */ - XtLdrProtocol->DbgPrint(L"ERROR: Unable to open system boot directory\n"); - XtLdrProtocol->CloseVolume(DiskHandle); + XtLdrProtocol->Debug.Print(L"ERROR: Unable to open system boot directory\n"); + XtLdrProtocol->Disk.CloseVolume(DiskHandle); return Status; } @@ -176,7 +174,7 @@ XtBootSystem(IN PXT_BOOT_PROTOCOL_PARAMETERS Parameters) XTCDECL EFI_STATUS XtpBootSequence(IN PEFI_FILE_HANDLE BootDir, - IN PXT_BOOT_PROTOCOL_PARAMETERS Parameters) + IN PXTBL_BOOT_PARAMETERS Parameters) { EFI_GUID LoadedImageGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID; PKERNEL_INITIALIZATION_BLOCK KernelParameters; @@ -185,10 +183,11 @@ XtpBootSequence(IN PEFI_FILE_HANDLE BootDir, PVOID VirtualAddress, VirtualMemoryArea; PXT_ENTRY_POINT KernelEntryPoint; LIST_ENTRY MemoryMappings; + EFI_HANDLE ProtocolHandle; EFI_STATUS Status; /* Initialize XTOS startup sequence */ - XtLdrProtocol->DbgPrint(L"Initializing XTOS startup sequence\n"); + XtLdrProtocol->Debug.Print(L"Initializing XTOS startup sequence\n"); /* Set base virtual memory area for the kernel mappings */ VirtualMemoryArea = (PVOID)KSEG0_BASE; @@ -198,7 +197,7 @@ XtpBootSequence(IN PEFI_FILE_HANDLE BootDir, RtlInitializeListHead(&MemoryMappings); /* Initialize virtual memory mappings */ - Status = XtLdrProtocol->InitializeVirtualMemory(&MemoryMappings, &VirtualMemoryArea); + Status = XtInitializeVirtualMemory(&MemoryMappings, &VirtualMemoryArea); if(Status != STATUS_EFI_SUCCESS) { /* Failed to initialize virtual memory */ @@ -214,7 +213,7 @@ XtpBootSequence(IN PEFI_FILE_HANDLE BootDir, } /* Add kernel image memory mapping */ - Status = XtLdrProtocol->AddVirtualMemoryMapping(&MemoryMappings, ImageContext->VirtualAddress, + Status = XtAddVirtualMemoryMapping(&MemoryMappings, ImageContext->VirtualAddress, ImageContext->PhysicalAddress, ImageContext->ImagePages, 0); if(Status != STATUS_EFI_SUCCESS) { @@ -228,11 +227,11 @@ XtpBootSequence(IN PEFI_FILE_HANDLE BootDir, KernelParameters = (PKERNEL_INITIALIZATION_BLOCK)VirtualAddress; /* Setup and map kernel initialization block */ - Status = XtpInitializeLoaderBlock(&MemoryMappings, &VirtualAddress); + Status = XtpInitializeLoaderBlock(&MemoryMappings, &VirtualAddress, Parameters); if(Status != STATUS_EFI_SUCCESS) { /* Failed to setup kernel initialization block */ - XtLdrProtocol->DbgPrint(L"Failed to setup kernel initialization block (Status Code: %lx)\n", Status); + XtLdrProtocol->Debug.Print(L"Failed to setup kernel initialization block (Status Code: %lx)\n", Status); return Status; } @@ -241,7 +240,7 @@ XtpBootSequence(IN PEFI_FILE_HANDLE BootDir, if(Status != STATUS_EFI_SUCCESS) { /* Failed to setup kernel initialization block */ - XtLdrProtocol->DbgPrint(L"Failed to initialize APIC (Status Code: %lx)\n", Status); + XtLdrProtocol->Debug.Print(L"Failed to initialize APIC (Status Code: %lx)\n", Status); return Status; } @@ -252,17 +251,17 @@ XtpBootSequence(IN PEFI_FILE_HANDLE BootDir, BootDir->Close(BootDir); /* Enable paging */ - EfiSystemTable->BootServices->HandleProtocol(EfiImageHandle, &LoadedImageGuid, (PVOID*)&ImageProtocol); - Status = XtLdrProtocol->EnablePaging(&MemoryMappings, VirtualAddress, ImageProtocol, &XtPageMap); + XtLdrProtocol->Protocol.Open(&ProtocolHandle, (PVOID*)&ImageProtocol, &LoadedImageGuid); + Status = XtEnablePaging(&MemoryMappings, VirtualAddress, ImageProtocol, &XtPageMap); if(Status != STATUS_EFI_SUCCESS) { /* Failed to enable paging */ - XtLdrProtocol->DbgPrint(L"Failed to enable paging (Status Code: %lx)\n", Status); + XtLdrProtocol->Debug.Print(L"Failed to enable paging (Status Code: %lx)\n", Status); return Status; } /* Call XTOS kernel */ - XtLdrProtocol->DbgPrint(L"Booting the XTOS kernel\n"); + XtLdrProtocol->Debug.Print(L"Booting the XTOS kernel\n"); KernelEntryPoint(KernelParameters); /* Return success */ @@ -306,7 +305,7 @@ XtpInitializeApicBase(IN PLIST_ENTRY MemoryMappings) ApicBaseAddress = (PVOID)((UINT_PTR)ArReadModelSpecificRegister(0x1B) & 0xFFFFF000); /* Map APIC base address */ - XtLdrProtocol->AddVirtualMemoryMapping(MemoryMappings, (PVOID)APIC_BASE, ApicBaseAddress, 1, LoaderFirmwarePermanent); + XtAddVirtualMemoryMapping(MemoryMappings, (PVOID)APIC_BASE, ApicBaseAddress, 1, LoaderFirmwarePermanent); return STATUS_EFI_SUCCESS; } @@ -326,21 +325,23 @@ XtpInitializeApicBase(IN PLIST_ENTRY MemoryMappings) XTCDECL EFI_STATUS XtpInitializeLoaderBlock(IN PLIST_ENTRY MemoryMappings, - IN PVOID *VirtualAddress) + IN PVOID *VirtualAddress, + IN PXTBL_BOOT_PARAMETERS Parameters) { EFI_GUID FrameBufGuid = XT_FRAMEBUFFER_PROTOCOL_GUID; PXT_FRAMEBUFFER_PROTOCOL FrameBufProtocol; PKERNEL_INITIALIZATION_BLOCK LoaderBlock; EFI_PHYSICAL_ADDRESS Address; - PVOID RuntimeServices; + // PVOID RuntimeServices; EFI_STATUS Status; + EFI_HANDLE ProtocolHandle; UINT BlockPages, FrameBufferPages; /* Calculate number of pages needed for initialization block */ BlockPages = EFI_SIZE_TO_PAGES(sizeof(KERNEL_INITIALIZATION_BLOCK)); /* Allocate memory for kernel initialization block */ - Status = XtLdrProtocol->AllocatePages(BlockPages, &Address); + Status = XtLdrProtocol->Memory.AllocatePages(BlockPages, &Address); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ @@ -357,15 +358,14 @@ XtpInitializeLoaderBlock(IN PLIST_ENTRY MemoryMappings, LoaderBlock->ProtocolVersion = BOOT_PROTOCOL_VERSION; /* Set LoaderInformation block properties */ - LoaderBlock->LoaderInformation.DbgPrint = XtLdrProtocol->DbgPrint; + LoaderBlock->LoaderInformation.DbgPrint = XtLdrProtocol->Debug.Print; /* Load FrameBuffer protocol */ - Status = BlLoadXtProtocol((PVOID *)&FrameBufProtocol, &FrameBufGuid); + Status = XtLdrProtocol->Protocol.Open(&ProtocolHandle, (PVOID*)&FrameBufProtocol, &FrameBufGuid); if(Status == STATUS_EFI_SUCCESS) { /* Make sure FrameBuffer is initialized */ FrameBufProtocol->Initialize(); - FrameBufProtocol->PrintDisplayInformation(); /* Store information about FrameBuffer device */ FrameBufProtocol->GetDisplayInformation(&LoaderBlock->LoaderInformation.FrameBuffer); @@ -377,23 +377,29 @@ XtpInitializeLoaderBlock(IN PLIST_ENTRY MemoryMappings, LoaderBlock->LoaderInformation.FrameBuffer.Protocol = NONE; } + /* Close FrameBuffer protocol */ + XtLdrProtocol->Protocol.Close(ProtocolHandle, &FrameBufGuid); + /* Attempt to find virtual address of the EFI Runtime Services */ - Status = XtLdrProtocol->GetVirtualAddress(MemoryMappings, &EfiSystemTable->RuntimeServices->Hdr, &RuntimeServices); - if(Status == STATUS_EFI_SUCCESS) - { + // Status = XtLdrProtocol->GetVirtualAddress(MemoryMappings, &EfiSystemTable->RuntimeServices->Hdr, &RuntimeServices); + // if(Status == STATUS_EFI_SUCCESS) + // { /* Set FirmwareInformation block properties */ LoaderBlock->FirmwareInformation.FirmwareType = SystemFirmwareEfi; - LoaderBlock->FirmwareInformation.EfiFirmware.EfiVersion = EfiSystemTable->Hdr.Revision; - LoaderBlock->FirmwareInformation.EfiFirmware.EfiRuntimeServices = RuntimeServices; - } - else - { - /* Set invalid firmware type to indicate that kernel cannot rely on FirmwareInformation block */ - LoaderBlock->FirmwareInformation.FirmwareType = SystemFirmwareInvalid; - } + LoaderBlock->FirmwareInformation.EfiFirmware.EfiVersion = 0; //EfiSystemTable->Hdr.Revision; + LoaderBlock->FirmwareInformation.EfiFirmware.EfiRuntimeServices = NULL; + // } + // else + // { + // /* Set invalid firmware type to indicate that kernel cannot rely on FirmwareInformation block */ + // LoaderBlock->FirmwareInformation.FirmwareType = SystemFirmwareInvalid; + // } + + /* Copy parameters to kernel initialization block */ + RtlCopyMemory(&LoaderBlock->KernelParameters, Parameters->Parameters, RtlWideStringLength(Parameters->Parameters, 0)); /* Map kernel initialization block */ - XtLdrProtocol->AddVirtualMemoryMapping(MemoryMappings, *VirtualAddress, (PVOID)LoaderBlock, + XtAddVirtualMemoryMapping(MemoryMappings, *VirtualAddress, (PVOID)LoaderBlock, BlockPages, LoaderSystemBlock); /* Calculate next valid virtual address */ @@ -406,7 +412,7 @@ XtpInitializeLoaderBlock(IN PLIST_ENTRY MemoryMappings, FrameBufferPages = EFI_SIZE_TO_PAGES(LoaderBlock->LoaderInformation.FrameBuffer.BufferSize); /* Map frame buffer memory */ - XtLdrProtocol->AddVirtualMemoryMapping(MemoryMappings, *VirtualAddress, + XtAddVirtualMemoryMapping(MemoryMappings, *VirtualAddress, LoaderBlock->LoaderInformation.FrameBuffer.Address, FrameBufferPages, LoaderFirmwarePermanent); @@ -456,23 +462,23 @@ XtpLoadModule(IN PEFI_FILE_HANDLE SystemDir, EFI_STATUS Status; /* Print debug message */ - XtLdrProtocol->DbgPrint(L"Loading %S ... \n", FileName); + XtLdrProtocol->Debug.Print(L"Loading %S ... \n", FileName); /* Open module file */ Status = SystemDir->Open(SystemDir, &ModuleHandle, FileName, EFI_FILE_MODE_READ, 0); if(Status != STATUS_EFI_SUCCESS) { /* Unable to open the file */ - XtLdrProtocol->DbgPrint(L"ERROR: Failed to open '%S'\n", FileName); + XtLdrProtocol->Debug.Print(L"ERROR: Failed to open '%S'\n", FileName); return Status; } /* Load the PE/COFF image file */ - Status = XtPeCoffProtocol->Load(ModuleHandle, MemoryType, VirtualAddress, ImageContext); + Status = XtPeCoffProtocol->LoadImage(ModuleHandle, MemoryType, VirtualAddress, (PVOID)ImageContext); if(Status != STATUS_EFI_SUCCESS) { /* Unable to load the file */ - XtLdrProtocol->DbgPrint(L"ERROR: Failed to load '%S'\n", FileName); + XtLdrProtocol->Debug.Print(L"ERROR: Failed to load '%S'\n", FileName); return Status; } @@ -484,7 +490,7 @@ XtpLoadModule(IN PEFI_FILE_HANDLE SystemDir, if(MachineType != _ARCH_IMAGE_MACHINE_TYPE) { /* Machine type mismatch */ - XtLdrProtocol->DbgPrint(L"ERROR: Loaded incompatible PE/COFF image (machine type mismatch)\n"); + XtLdrProtocol->Debug.Print(L"ERROR: Loaded incompatible PE/COFF image (machine type mismatch)\n"); return STATUS_EFI_INCOMPATIBLE_VERSION; } @@ -494,12 +500,12 @@ XtpLoadModule(IN PEFI_FILE_HANDLE SystemDir, SubSystem != PECOFF_IMAGE_SUBSYSTEM_XT_NATIVE_APPLICATION && SubSystem != PECOFF_IMAGE_SUBSYSTEM_XT_NATIVE_DRIVER) { - XtLdrProtocol->DbgPrint(L"WARNING: Loaded PE/COFF image with non-XT subsystem set\n"); + XtLdrProtocol->Debug.Print(L"WARNING: Loaded PE/COFF image with non-XT subsystem set\n"); } /* Print debug message */ - XtLdrProtocol->DbgPrint(L"Loaded %S at PA: 0x%lx, VA: 0x%lx\n", FileName, - (*ImageContext)->PhysicalAddress, (*ImageContext)->VirtualAddress); + XtLdrProtocol->Debug.Print(L"Loaded %S at PA: 0x%lx, VA: 0x%lx\n", FileName, + (*ImageContext)->PhysicalAddress, (*ImageContext)->VirtualAddress); /* Return success */ return STATUS_EFI_SUCCESS; @@ -520,19 +526,14 @@ XtpLoadModule(IN PEFI_FILE_HANDLE SystemDir, */ XTCDECL EFI_STATUS -BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle, - IN PEFI_SYSTEM_TABLE SystemTable) +XtLdrModuleMain(IN EFI_HANDLE ImageHandle, + IN PEFI_SYSTEM_TABLE SystemTable) { EFI_GUID Guid = XT_XTOS_BOOT_PROTOCOL_GUID; - EFI_HANDLE Handle = NULL; EFI_STATUS Status; - /* Set the system table and image handle */ - EfiImageHandle = ImageHandle; - EfiSystemTable = SystemTable; - /* Open the XTLDR protocol */ - Status = BlGetXtLoaderProtocol(&XtLdrProtocol); + Status = BlGetXtLdrProtocol(SystemTable, ImageHandle, &XtLdrProtocol); if(Status != STATUS_EFI_SUCCESS) { /* Failed to open loader protocol */ @@ -543,6 +544,8 @@ BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle, XtBootProtocol.BootSystem = XtBootSystem; /* Register XTOS boot protocol */ - return EfiSystemTable->BootServices->InstallProtocolInterface(&Handle, &Guid, EFI_NATIVE_INTERFACE, - &XtBootProtocol); + XtLdrProtocol->Boot.RegisterProtocol(L"XTOS", &Guid); + + /* Install XTOS protocol */ + return XtLdrProtocol->Protocol.Install(&XtBootProtocol, &Guid); } diff --git a/xtldr/protocol.c b/xtldr/protocol.c new file mode 100644 index 0000000..5cefb67 --- /dev/null +++ b/xtldr/protocol.c @@ -0,0 +1,601 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/protocol.c + * DESCRIPTION: XT Boot Loader protocol support + * DEVELOPERS: Rafal Kupiec + */ + +#include + + +/** + * Closes a protocol on a provided handle. + * + * @param Handle + * Supplies a handle for the protocol interface that was previously opened. + * + * @param ProtocolGuid + * Supplies a unique protocol GUID. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlCloseProtocol(IN PEFI_HANDLE Handle, + IN PEFI_GUID ProtocolGuid) +{ + return EfiSystemTable->BootServices->CloseProtocol(Handle, ProtocolGuid, EfiImageHandle, NULL); +} + +/** + * Finds a boot protocol for specified system type. + * + * @param SystemType + * Specifies the system type to search for. + * + * @param BootProtocolGuid + * Receives the GUID of the registered boot protocol, that supports specified system. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlFindBootProtocol(IN PWCHAR SystemType, + OUT PEFI_GUID BootProtocolGuid) +{ + PXTBL_KNOWN_BOOT_PROTOCOL ProtocolEntry; + PLIST_ENTRY ProtocolListEntry; + + ProtocolListEntry = BlpBootProtocols.Flink; + while(ProtocolListEntry != &BlpBootProtocols) + { + /* Get boot protocol entry */ + ProtocolEntry = CONTAIN_RECORD(ProtocolListEntry, XTBL_KNOWN_BOOT_PROTOCOL, Flink); + + /* Check if this boot protocol supports specified system */ + if(RtlCompareWideStringInsensitive(ProtocolEntry->SystemType, SystemType, 0) == 0) + { + /* Boot protocol matched, return success */ + *BootProtocolGuid = ProtocolEntry->Guid; + return STATUS_EFI_SUCCESS; + } + + /* Move to the next registered boot protocol */ + ProtocolListEntry = ProtocolListEntry->Flink; + } + + /* Boot protocol not found, return error */ + return STATUS_EFI_NOT_FOUND; +} + +/** + * Returns a linked list of all loaded modules. + * + * @return This routine returns a pointer to a linked list of all loaded modules. + * + * @since XT 1.0 + * + * @todo This is a temporary solution and it should be replaced by a complex API allowing to map modules. + */ +XTCDECL +PLIST_ENTRY +BlGetModulesList() +{ + /* Return a pointer to a list of all loaded modules */ + return &BlpLoadedModules; +} + +/** + * Installs XTLDR protocol interface. + * + * @param Guid + * Specifies a unique protocol GUID. + * + * @param Interface + * Supplies a pointer to the protocol interface, or NULL if there is no structure associated. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlInstallProtocol(IN PVOID Interface, + IN PEFI_GUID Guid) +{ + EFI_HANDLE Handle = NULL; + + /* Install protocol interface */ + return EfiSystemTable->BootServices->InstallProtocolInterface(&Handle, Guid, EFI_NATIVE_INTERFACE, Interface); +} + +/** + * Loads a specified XTLDR module from disk. + * + * @param ModuleName + * Specifies the name of the module to load. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlLoadModule(IN PWCHAR ModuleName) +{ + EFI_GUID LIPGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID; + EFI_MEMMAP_DEVICE_PATH ModuleDevicePath[2]; + PEFI_LOADED_IMAGE_PROTOCOL LoadedImage; + PEFI_FILE_HANDLE DirHandle, FsHandle; + EFI_HANDLE DiskHandle, ModuleHandle; + PPECOFF_IMAGE_SECTION_HEADER SectionHeader; + PPECOFF_IMAGE_DOS_HEADER DosHeader; + PPECOFF_IMAGE_PE_HEADER PeHeader; + PXTBL_MODULE_DEPS ModuleDependencies; + PXTBL_MODULE_INFO ModuleInfo; + PLIST_ENTRY ModuleListEntry; + WCHAR ModuleFileName[24]; + USHORT SectionIndex; + SIZE_T ModuleSize; + EFI_STATUS Status; + PVOID ModuleData; + PWCHAR DepsData; + + ModuleListEntry = BlpLoadedModules.Flink; + while(ModuleListEntry != &BlpLoadedModules) + { + /* Get module information */ + ModuleInfo = CONTAIN_RECORD(ModuleListEntry, XTBL_MODULE_INFO, Flink); + + if(RtlCompareWideStringInsensitive(ModuleInfo->ModuleName, ModuleName, 0) == 0) + { + /* Module already loaded */ + BlDebugPrint(L"WARNING: Module '%S' already loaded!\n", ModuleName); + return STATUS_EFI_SUCCESS; + } + + /* Move to the module */ + ModuleListEntry = ModuleListEntry->Flink; + } + + /* Print debug message */ + BlDebugPrint(L"Loading module '%S' ...\n", ModuleName); + + /* Set module path */ + RtlCopyMemory(ModuleFileName, ModuleName, sizeof(ModuleFileName) / sizeof(WCHAR)); + RtlConcatenateWideString(ModuleFileName, L".EFI", 0); + + /* Open EFI volume */ + Status = BlOpenVolume(NULL, &DiskHandle, &FsHandle); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to open a volume */ + return Status; + } + + /* Open XTLDR modules common directory */ + Status = FsHandle->Open(FsHandle, &DirHandle, XTBL_MODULES_DIRECTORY_PATH, EFI_FILE_MODE_READ, 0); + if(Status != STATUS_EFI_SUCCESS) + { + /* Modules directory not found, attempt to open XTLDR architecture specific modules directory */ + Status = FsHandle->Open(FsHandle, &DirHandle, XTBL_ARCH_MODULES_DIRECTORY_PATH, EFI_FILE_MODE_READ, 0); + } + + /* Close FS handle */ + FsHandle->Close(FsHandle); + + /* Check if modules directory opened successfully */ + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to open directory */ + BlCloseVolume(DiskHandle); + return Status; + } + + /* Read module file from disk and close directory and EFI volume */ + Status = BlReadFile(DirHandle, ModuleFileName, &ModuleData, &ModuleSize); + DirHandle->Close(DirHandle); + BlCloseVolume(DiskHandle); + + /* Make sure module file was read successfully */ + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to read file */ + return Status; + } + + /* Allocate memory for module information block */ + Status = BlMemoryAllocatePool(sizeof(XTBL_MODULE_INFO), (PVOID*)&ModuleInfo); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to allocate memory */ + return Status; + } + + /* Zero module information block and initialize dependencies list */ + RtlZeroMemory(ModuleInfo, sizeof(XTBL_MODULE_INFO)); + RtlInitializeListHead(&ModuleInfo->Dependencies); + + /* Setup PE/COFF EFI image headers */ + DosHeader = (PPECOFF_IMAGE_DOS_HEADER)ModuleData; + PeHeader = (PPECOFF_IMAGE_PE_HEADER)(ModuleData + DosHeader->e_lfanew); + SectionHeader = (PPECOFF_IMAGE_SECTION_HEADER)((PUCHAR)&PeHeader->OptionalHeader + + PeHeader->FileHeader.SizeOfOptionalHeader); + + /* Look for .moddeps and .modinfo sections */ + for(SectionIndex = 0; SectionIndex < PeHeader->FileHeader.NumberOfSections; SectionIndex++) + { + /* Check section name */ + if(RtlCompareString((PCHAR)SectionHeader[SectionIndex].Name, ".moddeps", 8) == 0) + { + /* Store address of .moddeps data segment */ + DepsData = ModuleData + SectionHeader[SectionIndex].PointerToRawData; + + /* Iterate over all dependencies stored */ + while(*DepsData != 0) + { + /* Load dependency module */ + BlDebugPrint(L"Module '%S' requires '%S' ...\n", ModuleName, DepsData); + Status = BlLoadModule(DepsData); + + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to load module, print error message and return status code */ + BlDebugPrint(L"Failed to load dependency module '%S', (Status Code: 0x%lx)\n", DepsData, Status); + return STATUS_EFI_UNSUPPORTED; + } + + /* Allocate memory for module dependency */ + Status = BlMemoryAllocatePool(sizeof(XTBL_MODULE_DEPS), (PVOID*)&ModuleDependencies); + if(Status == STATUS_EFI_SUCCESS) + { + /* Memory allocated successfully, store module's dependency */ + ModuleDependencies->ModuleName = DepsData; + RtlInsertTailList(&ModuleInfo->Dependencies, &ModuleDependencies->Flink); + } + + /* Get next dependency module name */ + DepsData += 8; + } + } + else if(RtlCompareString((PCHAR)SectionHeader[SectionIndex].Name, ".modinfo", 8) == 0) + { + /* Store module description */ + ModuleInfo->ModuleDescription = ModuleData + SectionHeader[SectionIndex].PointerToRawData; + } + } + + /* Finally, store module name */ + ModuleInfo->ModuleName = ModuleName; + + /* Setup module device path */ + ModuleDevicePath[0].Header.Length[0] = sizeof(EFI_MEMMAP_DEVICE_PATH); + ModuleDevicePath[0].Header.Length[1] = sizeof(EFI_MEMMAP_DEVICE_PATH) >> 8; + ModuleDevicePath[0].Header.Type = EFI_HARDWARE_DEVICE_PATH; + ModuleDevicePath[0].Header.SubType = EFI_HARDWARE_MEMMAP_DP; + ModuleDevicePath[0].MemoryType = EfiLoaderData; + ModuleDevicePath[0].StartingAddress = (UINT_PTR)ModuleData; + ModuleDevicePath[0].EndingAddress = (UINT_PTR)ModuleData + ModuleSize; + ModuleDevicePath[1].Header.Length[0] = sizeof(EFI_DEVICE_PATH_PROTOCOL); + ModuleDevicePath[1].Header.Length[1] = sizeof(EFI_DEVICE_PATH_PROTOCOL) >> 8; + ModuleDevicePath[1].Header.Type = EFI_END_DEVICE_PATH; + ModuleDevicePath[1].Header.SubType = EFI_END_ENTIRE_DP; + + /* Load EFI image */ + Status = EfiSystemTable->BootServices->LoadImage(FALSE, EfiImageHandle, (PEFI_DEVICE_PATH_PROTOCOL)ModuleDevicePath, + ModuleData, ModuleSize, &ModuleHandle); + if(Status != STATUS_EFI_SUCCESS) + { + /* Check if caused by secure boot */ + if(Status == STATUS_EFI_ACCESS_DENIED && BlpStatus.SecureBoot >= 1) + { + /* SecureBoot signature validation failed */ + BlDebugPrint(L"ERROR: SecureBoot signature validation failed, module '%S' will not be loaded\n", ModuleName); + } + else + { + /* Failed to load module */ + BlDebugPrint(L"ERROR: Unable to load module '%S' (Status Code: 0x%lx)\n", ModuleName, Status); + } + + /* Return error status code */ + return Status; + } + + /* Access module interface for further module type check */ + Status = EfiSystemTable->BootServices->OpenProtocol(ModuleHandle, &LIPGuid, (PVOID *)&LoadedImage, + EfiImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to open LoadedImage protocol */ + BlDebugPrint(L"ERROR: Unable to access module interface (Status Code: 0x%lx)\n", Status); + return Status; + } + + /* Some firmwares do not allow to start drivers which are not of 'boot system driver' type, so check it */ + if(LoadedImage->ImageCodeType != EfiBootServicesCode) + { + /* Different type set, probably 'runtime driver', refuse to load it */ + BlDebugPrint(L"ERROR: Loaded module is not a boot system driver\n"); + + /* Close protocol and skip module */ + EfiSystemTable->BootServices->CloseProtocol(LoadedImage, &LIPGuid, LoadedImage, NULL); + } + + /* Save module information */ + ModuleInfo->ModuleBase = LoadedImage->ImageBase; + ModuleInfo->ModuleSize = LoadedImage->ImageSize; + ModuleInfo->Revision = LoadedImage->Revision; + ModuleInfo->UnloadModule = LoadedImage->Unload; + + /* Close loaded image protocol */ + EfiSystemTable->BootServices->CloseProtocol(LoadedImage, &LIPGuid, LoadedImage, NULL); + + /* Start EFI image */ + Status = EfiSystemTable->BootServices->StartImage(ModuleHandle, NULL, NULL); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to start module image */ + BlDebugPrint(L"ERROR: Failed to start module '%S' (Status Code: 0x%lx)\n", ModuleName, Status); + return Status; + } + + /* Add module to the list of loaded modules */ + RtlInsertTailList(&BlpLoadedModules, &ModuleInfo->Flink); + + /* Return success */ + return STATUS_EFI_SUCCESS; +} + +/** + * Helper routine to load all modules supplied in the configuration file. + * + * @param ModulesList + * Supplies a space separated list of XTLDR modules to load (mostly read from configuration file). + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlLoadModules(IN PWCHAR ModulesList) +{ + PWCHAR LastModule, Module; + EFI_STATUS ReturnStatus, Status; + + /* Set default return value */ + ReturnStatus = STATUS_EFI_SUCCESS; + + if(ModulesList != NULL) + { + /* Tokenize provided list of modules */ + Module = RtlTokenizeWideString(ModulesList, L" ", &LastModule); + + /* Iterate over all arguments passed to boot loader */ + while(Module != NULL) + { + Status = BlLoadModule(Module); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to load module, print error message and set new return value */ + BlDebugPrint(L"ERROR: Failed to load module '%S', (Status Code: 0x%lx)\n", Module, Status); + ReturnStatus = STATUS_EFI_LOAD_ERROR; + } + + /* Take next module from the list */ + Module = RtlTokenizeWideString(NULL, L" ", &LastModule); + } + } + + /* Return success */ + return ReturnStatus; +} + +/** + * This routine locates and opens the requested XT Boot Loader or EFI protocol. + * + * @param Handle + * Supplies the address where a pointer to the handle for the protocol interface. + * + * @param ProtocolHandler + * Supplies the address where a pointer to the opened protocol is returned. + * + * @param ProtocolGuid + * Supplies a pointer to the unique protocol GUID. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlOpenProtocol(OUT PEFI_HANDLE Handle, + OUT PVOID *ProtocolHandler, + IN PEFI_GUID ProtocolGuid) +{ + PEFI_HANDLE Handles = NULL; + EFI_STATUS Status; + UINT_PTR Count; + UINT Index; + + /* Try to locate the handles */ + Status = EfiSystemTable->BootServices->LocateHandleBuffer(ByProtocol, ProtocolGuid, NULL, &Count, &Handles); + if(Status != STATUS_EFI_SUCCESS) + { + /* Unable to get handles */ + return Status; + } + + /* Check if any handles returned */ + if(Count > 0) + { + /* Iterate through all given handles */ + for(Index = 0; Index < Count; Index++) + { + /* Try to open protocol */ + Status = EfiSystemTable->BootServices->OpenProtocol(Handles[Index], ProtocolGuid, + ProtocolHandler, EfiImageHandle, NULL, + EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL); + + /* Check if successfully opened the loader protocol */ + if(Status == STATUS_EFI_SUCCESS) + { + /* Protocol found and successfully opened */ + *Handle = Handles[Index]; + break; + } + } + } + + /* Free handles */ + EfiSystemTable->BootServices->FreePool(Handles); + + /* Make sure the loaded protocol has been found */ + if(*ProtocolHandler == NULL) + { + /* Protocol not found */ + return STATUS_EFI_NOT_FOUND; + } + + /* Return success */ + return STATUS_EFI_SUCCESS; +} + +/** + * Registers a boot menu callback routine, that will be used to display alternative boot menu. + * + * @param BootMenuRoutine + * Supplies a pointer to the boot menu callback routine. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlRegisterBootMenu(IN PVOID BootMenuRoutine) +{ + /* Set boot menu routine */ + BlpStatus.BootMenu = BootMenuRoutine; +} + +/** + * Registers a known boot protocol for a specified OS. + * + * @param SystemType + * Supplies the type of the OS, such as "LINUX", "XTOS", etc. that is supported by the boot protocol. + * + * @param BootProtocolGuid + * Supplies a pointer to the unique protocol GUID. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlRegisterBootProtocol(IN PWCHAR SystemType, + IN PEFI_GUID BootProtocolGuid) +{ + PXTBL_KNOWN_BOOT_PROTOCOL ProtocolEntry; + PLIST_ENTRY ProtocolListEntry; + EFI_STATUS Status; + + ProtocolListEntry = BlpBootProtocols.Flink; + while(ProtocolListEntry != &BlpBootProtocols) + { + /* Get boot protocol entry */ + ProtocolEntry = CONTAIN_RECORD(ProtocolListEntry, XTBL_KNOWN_BOOT_PROTOCOL, Flink); + + /* Check if boot protocol already registered for specified system */ + if(RtlCompareWideStringInsensitive(ProtocolEntry->SystemType, SystemType, 0) == 0) + { + /* Boot protocol already registered */ + return STATUS_EFI_ABORTED; + } + + /* Move to the next registered boot protocol */ + ProtocolListEntry = ProtocolListEntry->Flink; + } + + /* Create new boot protocol entry */ + Status = BlMemoryAllocatePool(sizeof(XTBL_BOOT_PROTOCOL), (PVOID *)&ProtocolEntry); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory allocation failure */ + return STATUS_EFI_OUT_OF_RESOURCES; + } + + /* Set protocol properties and add it to the list */ + ProtocolEntry->SystemType = SystemType; + ProtocolEntry->Guid = *BootProtocolGuid; + RtlInsertTailList(&BlpBootProtocols, &ProtocolEntry->Flink); + + /* Return success */ + return STATUS_EFI_SUCCESS; +} + +/** + * This routine installs XTLDR protocol for further usage by modules. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlpInstallXtLoaderProtocol() +{ + EFI_GUID Guid = XT_BOOT_LOADER_PROTOCOL_GUID; + + /* Set all routines available via loader protocol */ + BlpLdrProtocol.Boot.FindProtocol = BlFindBootProtocol; + BlpLdrProtocol.Boot.InitializeMenuList = BlInitializeBootMenuList; + BlpLdrProtocol.Boot.InvokeProtocol = BlInvokeBootProtocol; + BlpLdrProtocol.Boot.RegisterMenu = BlRegisterBootMenu; + BlpLdrProtocol.Boot.RegisterProtocol = BlRegisterBootProtocol; + BlpLdrProtocol.Config.GetValue = BlGetConfigValue; + BlpLdrProtocol.Console.ClearLine = BlClearConsoleLine; + BlpLdrProtocol.Console.ClearScreen = BlClearConsoleScreen; + BlpLdrProtocol.Console.DisableCursor = BlDisableConsoleCursor; + BlpLdrProtocol.Console.EnableCursor = BlEnableConsoleCursor; + BlpLdrProtocol.Console.Print = BlConsolePrint; + BlpLdrProtocol.Console.QueryMode = BlQueryConsoleMode; + BlpLdrProtocol.Console.ReadKeyStroke = BlReadKeyStroke; + BlpLdrProtocol.Console.ResetInputBuffer = BlResetConsoleInputBuffer; + BlpLdrProtocol.Console.SetAttributes = BlSetConsoleAttributes; + BlpLdrProtocol.Console.SetCursorPosition = BlSetCursorPosition; + BlpLdrProtocol.Console.Write = BlConsoleWrite; + BlpLdrProtocol.Debug.Print = BlDebugPrint; + BlpLdrProtocol.Disk.CloseVolume = BlCloseVolume; + BlpLdrProtocol.Disk.OpenVolume = BlOpenVolume; + BlpLdrProtocol.Disk.ReadFile = BlReadFile; + BlpLdrProtocol.Memory.AllocatePages = BlMemoryAllocatePages; + BlpLdrProtocol.Memory.AllocatePool = BlMemoryAllocatePool; + BlpLdrProtocol.Memory.FreePages = BlMemoryFreePages; + BlpLdrProtocol.Memory.FreePool = BlMemoryFreePool; + BlpLdrProtocol.Memory.GetMemoryMap = BlGetMemoryMap; + BlpLdrProtocol.Protocol.Close = BlCloseProtocol; + BlpLdrProtocol.Protocol.GetModulesList = BlGetModulesList; + BlpLdrProtocol.Protocol.Open = BlOpenProtocol; + BlpLdrProtocol.Protocol.Install = BlInstallProtocol; + BlpLdrProtocol.Tui.DisplayErrorDialog = BlDisplayErrorDialog; + BlpLdrProtocol.Tui.DisplayInfoDialog = BlDisplayInfoDialog; + BlpLdrProtocol.Tui.DisplayInputDialog = BlDisplayInputDialog; + BlpLdrProtocol.Tui.DisplayProgressDialog = BlDisplayProgressDialog; + BlpLdrProtocol.Tui.UpdateProgressBar = BlUpdateProgressBar; + BlpLdrProtocol.Util.ExitBootServices = BlExitBootServices; + BlpLdrProtocol.Util.GetSecureBootStatus = BlGetSecureBootStatus; + BlpLdrProtocol.Util.SleepExecution = BlSleepExecution; + BlpLdrProtocol.Util.WaitForEfiEvent = BlWaitForEfiEvent; + + /* Register XTLDR loader protocol */ + BlDebugPrint(L"Registering XT loader protocol\n"); + return BlInstallProtocol(&BlpLdrProtocol, &Guid); +} diff --git a/xtldr/shell.c b/xtldr/shell.c new file mode 100644 index 0000000..bd1d159 --- /dev/null +++ b/xtldr/shell.c @@ -0,0 +1,50 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/shell.c + * DESCRIPTION: XT Boot Loader shell + * DEVELOPERS: Rafal Kupiec + */ + +#include + + +/** + * Starts XTLDR shell. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlStartLoaderShell() +{ + /* Initialize console */ + BlInitializeConsole(); + + /* Print prompt */ + BlpPrintShellPrompt(); + for(;;); +} + +/** + * Prints XTLDR shell prompt. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlpPrintShellPrompt() +{ + /* Set prompt color */ + BlSetConsoleAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_YELLOW); + + /* Print prompt */ + BlConsolePrint(L"XTLDR> "); + + /* Reset standard shell colors */ + BlSetConsoleAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_LIGHTGRAY); +} diff --git a/xtldr/string.c b/xtldr/string.c index c555999..f082232 100644 --- a/xtldr/string.c +++ b/xtldr/string.c @@ -2,73 +2,17 @@ * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/string.c - * DESCRIPTION: EFI string operations support + * DESCRIPTION: EFI string manipulation support * DEVELOPERS: Rafal Kupiec */ -#include +#include -/** - * Compares two strings without sensitivity to case. - * - * @param String1 - * First string to be compared. - * - * @param String2 - * Second string to be compared. - * - * @return This routine returns a value indicating the relationship between the two strings. - * - * @since XT 1.0 - */ -XTCDECL -INT -BlStringCompareInsensitive(IN PUCHAR String1, - IN PUCHAR String2) -{ - UCHAR Character1; - UCHAR Character2; - ULONG Index = 0; - - /* Iterate through the strings */ - while(String1[Index] != '\0' && String2[Index] != '\0') - { - /* Get the characters */ - Character1 = String1[Index]; - Character2 = String2[Index]; - - /* Lowercase string1 character if needed */ - if(String1[Index] >= 'A' && String1[Index] <= 'Z') - { - Character1 = String1[Index] - 'A' + 'a'; - } - - /* Lowercase string2 character if needed */ - if(String2[Index] >= 'A' && String2[Index] <= 'Z') - { - Character2 = String2[Index] - 'A' + 'a'; - } - - /* Compare the characters */ - if(Character1 != Character2) - { - /* Strings are not equal */ - return Character1 > Character2 ? 1 : -1; - } - - /* Get next character */ - Index++; - } - - /* Strings are equal */ - return 0; -} - /** * This routine formats the input string and prints it using specified routine. * - * @param PutChar + * @param PrintCharRoutine * Pointer to the routine that writes an input data to specific device. * * @param Format @@ -83,9 +27,9 @@ BlStringCompareInsensitive(IN PUCHAR String1, */ XTCDECL VOID -BlStringPrint(IN VOID PutChar(IN USHORT Character), - IN PUINT16 Format, - IN VA_LIST Arguments) +BlpStringPrint(IN IN BLPRINTCHAR PrintCharRoutine, + IN PUINT16 Format, + IN VA_LIST Arguments) { PEFI_GUID Guid; PUCHAR String; @@ -102,20 +46,20 @@ BlStringPrint(IN VOID PutChar(IN USHORT Character), { case L'b': /* Boolean */ - BlpStringFormat(PutChar, L"%s", VA_ARG(Arguments, INT32) ? "TRUE" : "FALSE"); + BlpStringFormat(PrintCharRoutine, L"%s", VA_ARG(Arguments, INT32) ? "TRUE" : "FALSE"); break; case L'c': /* Character */ - PutChar(VA_ARG(Arguments, INT)); + PrintCharRoutine(VA_ARG(Arguments, INT)); break; case L'd': /* Signed 32-bit integer */ - BlpStringPrintSigned32(PutChar, VA_ARG(Arguments, INT32), 10); + BlpStringPrintSigned32(PrintCharRoutine, VA_ARG(Arguments, INT32), 10); break; case L'g': /* EFI GUID */ Guid = VA_ARG(Arguments, PEFI_GUID); - BlpStringFormat(PutChar, L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", Guid->Data1, + BlpStringFormat(PrintCharRoutine, L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", Guid->Data1, Guid->Data2, Guid->Data3, Guid->Data4[0], Guid->Data4[1], Guid->Data4[2], Guid->Data4[3], Guid->Data4[4], Guid->Data4[5], Guid->Data4[6], Guid->Data4[7]); break; @@ -125,48 +69,48 @@ BlStringPrint(IN VOID PutChar(IN USHORT Character), { case L'd': /* Signed 64-bit integer */ - BlpStringPrintSigned64(PutChar, VA_ARG(Arguments, INT_PTR), 10); + BlpStringPrintSigned64(PrintCharRoutine, VA_ARG(Arguments, INT_PTR), 10); break; case L'u': /* Unsigned 64-bit integer */ - BlpStringPrintUnsigned64(PutChar, VA_ARG(Arguments, UINT_PTR), 10, 0); + BlpStringPrintUnsigned64(PrintCharRoutine, VA_ARG(Arguments, UINT_PTR), 10, 0); break; case L'x': /* Unsigned 64-bit hexadecimal integer */ - BlpStringPrintUnsigned64(PutChar, VA_ARG(Arguments, UINT_PTR), 16, 0); + BlpStringPrintUnsigned64(PrintCharRoutine, VA_ARG(Arguments, UINT_PTR), 16, 0); break; default: /* Unknown by default */ - PutChar(L'?'); + PrintCharRoutine(L'?'); break; } break; case L'p': /* Pointer address */ - BlpStringPrintUnsigned64(PutChar, VA_ARG(Arguments, UINT_PTR), 16, 0); + BlpStringPrintUnsigned64(PrintCharRoutine, VA_ARG(Arguments, UINT_PTR), 16, 0); break; case L's': /* String of characters */ String = VA_ARG(Arguments, PUCHAR); while(*String) { - PutChar(*String++); + PrintCharRoutine(*String++); } break; case L'S': WideString = VA_ARG(Arguments, PWCHAR); while(*WideString) { - PutChar((UCHAR)*WideString++); + PrintCharRoutine((UCHAR)*WideString++); } break; case L'u': /* Unsigned 32-bit integer */ - BlpStringPrintUnsigned32(PutChar, VA_ARG(Arguments, UINT32), 10, 0); + BlpStringPrintUnsigned32(PrintCharRoutine, VA_ARG(Arguments, UINT32), 10, 0); break; case L'x': /* Unsigned 32-bit hexadecimal integer */ - BlpStringPrintUnsigned32(PutChar, VA_ARG(Arguments, UINT32), 16, 0); + BlpStringPrintUnsigned32(PrintCharRoutine, VA_ARG(Arguments, UINT32), 16, 0); break; case L'0': /* Zero padded numbers */ @@ -176,7 +120,7 @@ BlStringPrint(IN VOID PutChar(IN USHORT Character), { case L'd': /* Zero-padded, signed 32-bit integer */ - BlpStringPrintSigned32(PutChar, VA_ARG(Arguments, INT32), 10); + BlpStringPrintSigned32(PrintCharRoutine, VA_ARG(Arguments, INT32), 10); break; case L'l': /* 64-bit numbers */ @@ -184,43 +128,43 @@ BlStringPrint(IN VOID PutChar(IN USHORT Character), { case L'd': /* Zero-padded, signed 64-bit integer */ - BlpStringPrintSigned64(PutChar, VA_ARG(Arguments, INT_PTR), 10); + BlpStringPrintSigned64(PrintCharRoutine, VA_ARG(Arguments, INT_PTR), 10); break; case L'u': /* Zero-padded, unsigned 64-bit integer */ - BlpStringPrintUnsigned64(PutChar, VA_ARG(Arguments, UINT_PTR), 10, PaddingCount); + BlpStringPrintUnsigned64(PrintCharRoutine, VA_ARG(Arguments, UINT_PTR), 10, PaddingCount); break; case L'x': /* Zero-padded, unsigned 64-bit hexadecimal integer */ - BlpStringPrintUnsigned64(PutChar, VA_ARG(Arguments, UINT_PTR), 16, PaddingCount); + BlpStringPrintUnsigned64(PrintCharRoutine, VA_ARG(Arguments, UINT_PTR), 16, PaddingCount); break; default: /* Unknown by default */ - PutChar(L'?'); + PrintCharRoutine(L'?'); break; } break; case L'u': /* Zero-padded, unsigned 32-bit integer */ - BlpStringPrintUnsigned32(PutChar, VA_ARG(Arguments, UINT32), 10, PaddingCount); + BlpStringPrintUnsigned32(PrintCharRoutine, VA_ARG(Arguments, UINT32), 10, PaddingCount); break; case L'x': /* Zero-padded, unsigned 32-bit hexadecimal integer */ - BlpStringPrintUnsigned32(PutChar, VA_ARG(Arguments, UINT32), 16, PaddingCount); + BlpStringPrintUnsigned32(PrintCharRoutine, VA_ARG(Arguments, UINT32), 16, PaddingCount); break; default: /* Unknown by default */ - PutChar(L'?'); + PrintCharRoutine(L'?'); break; } break; case L'%': /* Percent character */ - PutChar(L'%'); + PrintCharRoutine(L'%'); break; default: /* Unknown by default */ - PutChar(L'?'); + PrintCharRoutine(L'?'); break; } break; @@ -229,12 +173,12 @@ BlStringPrint(IN VOID PutChar(IN USHORT Character), break; case L'\n': /* New line together with carriage return */ - PutChar(L'\r'); - PutChar(L'\n'); + PrintCharRoutine(L'\r'); + PrintCharRoutine(L'\n'); break; default: /* Put character by default */ - PutChar(*Format); + PrintCharRoutine(*Format); break; } } @@ -243,7 +187,7 @@ BlStringPrint(IN VOID PutChar(IN USHORT Character), /** * This routine formats the input string and prints it using specified routine. * - * @param PutChar + * @param PrintCharRoutine * Pointer to the routine that writes an input data to specific device. * * @param Format @@ -258,7 +202,7 @@ BlStringPrint(IN VOID PutChar(IN USHORT Character), */ XTCDECL VOID -BlpStringFormat(IN VOID PutChar(IN USHORT Character), +BlpStringFormat(IN BLPRINTCHAR PrintCharRoutine, IN PUINT16 Format, IN ...) { @@ -268,7 +212,7 @@ BlpStringFormat(IN VOID PutChar(IN USHORT Character), VA_START(Arguments, Format); /* Format and print the string to the desired output */ - BlStringPrint(PutChar, Format, Arguments); + BlpStringPrint(PrintCharRoutine, Format, Arguments); /* Clean up the va_list */ VA_END(Arguments); @@ -277,7 +221,7 @@ BlpStringFormat(IN VOID PutChar(IN USHORT Character), /** * This routine converts 32-bit integer as string and prints it using specified routine. * - * @param PutChar + * @param PrintCharRoutine * Pointer to the routine that writes an input data to specific device. * * @param Number @@ -292,25 +236,25 @@ BlpStringFormat(IN VOID PutChar(IN USHORT Character), */ XTCDECL VOID -BlpStringPrintSigned32(IN VOID PutChar(IN USHORT Character), - IN INT32 Number, - IN UINT32 Base) +BlpStringPrintSigned32(IN BLPRINTCHAR PrintCharRoutine, + IN INT Number, + IN UINT Base) { /* Print - (minus) if this is negative value */ if(Number < 0) { - PutChar(L'-'); + PrintCharRoutine(L'-'); Number *= -1; } /* Print the integer value */ - BlpStringPrintUnsigned32(PutChar, Number, Base, 0); + BlpStringPrintUnsigned32(PrintCharRoutine, Number, Base, 0); } /** * This routine converts 64-bit integer as string and prints it using specified routine. * - * @param PutChar + * @param PrintCharRoutine * Pointer to the routine that writes an input data to specific device. * * @param Number @@ -325,25 +269,25 @@ BlpStringPrintSigned32(IN VOID PutChar(IN USHORT Character), */ XTCDECL VOID -BlpStringPrintSigned64(IN VOID PutChar(IN USHORT Character), +BlpStringPrintSigned64(IN BLPRINTCHAR PrintCharRoutine, IN INT_PTR Number, IN UINT_PTR Base) { /* Print - (minus) if this is negative value */ if(Number < 0) { - PutChar(L'-'); + PrintCharRoutine(L'-'); Number *= -1; } /* Print the integer value */ - BlpStringPrintUnsigned64(PutChar, Number, Base, 0); + BlpStringPrintUnsigned64(PrintCharRoutine, Number, Base, 0); } /** * This routine converts 32-bit unsigned integer as string and prints it using specified routine. * - * @param PutChar + * @param PrintCharRoutine * Pointer to the routine that writes an input data to specific device. * * @param Number @@ -361,23 +305,27 @@ BlpStringPrintSigned64(IN VOID PutChar(IN USHORT Character), */ XTCDECL VOID -BlpStringPrintUnsigned32(IN VOID PutChar(IN USHORT Character), - IN UINT32 Number, - IN UINT32 Base, - IN UINT32 Padding) +BlpStringPrintUnsigned32(IN BLPRINTCHAR PrintCharRoutine, + IN UINT Number, + IN UINT Base, + IN UINT Padding) { - UINT32 Buffer[20]; - PUINT32 Pointer = Buffer + ARRAY_SIZE(Buffer); + UINT Buffer[20]; + UINT NumberLength; + PUINT Pointer; + + /* Set pointer to the end of buffer */ + Pointer = Buffer + ARRAY_SIZE(Buffer); /* Convert value to specified base system */ *--Pointer = 0; do { - *--Pointer = EfiHexTable[Number % Base]; + *--Pointer = BlpHexTable[Number % Base]; } while(Pointer >= Buffer && (Number /= Base)); /* Calculate number length */ - UINT32 NumberLength = ARRAY_SIZE(Buffer) - (Pointer - Buffer) - 1; + NumberLength = ARRAY_SIZE(Buffer) - (Pointer - Buffer) - 1; /* Check if leading zeros are needed */ if(NumberLength < Padding) @@ -386,21 +334,21 @@ BlpStringPrintUnsigned32(IN VOID PutChar(IN USHORT Character), while(Padding--) { /* Write leading zeroes */ - PutChar(L'0'); + PrintCharRoutine(L'0'); } } /* Print value to the console */ for(; *Pointer; ++Pointer) { - PutChar(*Pointer); + PrintCharRoutine(*Pointer); } } /** * This routine converts 64-bit unsigned integer as string and prints it using specified routine. * - * @param PutChar + * @param PrintCharRoutine * Pointer to the routine that writes an input data to specific device. * * @param Number @@ -418,23 +366,27 @@ BlpStringPrintUnsigned32(IN VOID PutChar(IN USHORT Character), */ XTCDECL VOID -BlpStringPrintUnsigned64(IN VOID PutChar(IN USHORT Character), +BlpStringPrintUnsigned64(IN BLPRINTCHAR PrintCharRoutine, IN UINT_PTR Number, IN UINT_PTR Base, IN UINT_PTR Padding) { UINT16 Buffer[20]; - PUINT16 Pointer = Buffer + ARRAY_SIZE(Buffer); + UINT_PTR NumberLength; + PUINT16 Pointer; + + /* Set pointer to the end of buffer */ + Pointer = Buffer + ARRAY_SIZE(Buffer); /* Convert value to specified base system */ *--Pointer = 0; do { - *--Pointer = EfiHexTable[Number % Base]; + *--Pointer = BlpHexTable[Number % Base]; } while(Pointer >= Buffer && (Number /= Base)); /* Calculate number length */ - UINT_PTR NumberLength = ARRAY_SIZE(Buffer) - (Pointer - Buffer) - 1; + NumberLength = ARRAY_SIZE(Buffer) - (Pointer - Buffer) - 1; /* Check if leading zeros are needed */ if(NumberLength < Padding) @@ -443,14 +395,14 @@ BlpStringPrintUnsigned64(IN VOID PutChar(IN USHORT Character), while(Padding--) { /* Write leading zeroes */ - PutChar(L'0'); + PrintCharRoutine(L'0'); } } /* Print value to the console */ for(; *Pointer; ++Pointer) { - PutChar(*Pointer); + PrintCharRoutine(*Pointer); } } diff --git a/xtldr/system.c b/xtldr/system.c deleted file mode 100644 index 52b83da..0000000 --- a/xtldr/system.c +++ /dev/null @@ -1,77 +0,0 @@ -/** - * PROJECT: ExectOS - * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtldr/system.c - * DESCRIPTION: EFI system information - * DEVELOPERS: Rafal Kupiec - */ - -#include - - -/** - * This routine checks whether SecureBoot is enabled or not. - * - * @return Numeric representation of SecureBoot status (0 = Disabled, >0 = Enabled, <0 SetupMode). - * - * @since XT 1.0 - */ -XTCDECL -INT_PTR -BlEfiGetSecureBootStatus() -{ - EFI_GUID VarGuid = EFI_GLOBAL_VARIABLE_GUID; - INT_PTR SecureBootStatus = 0; - UCHAR VarValue = 0; - UINT_PTR Size; - - Size = sizeof(VarValue); - if(EfiSystemTable->RuntimeServices->GetVariable(L"SecureBoot", &VarGuid, - NULL, &Size, &VarValue) == STATUS_EFI_SUCCESS) - { - SecureBootStatus = (INT_PTR)VarValue; - - if((EfiSystemTable->RuntimeServices->GetVariable(L"SetupMode", &VarGuid, - NULL, &Size, &VarValue) == STATUS_EFI_SUCCESS) && VarValue != 0) - { - SecureBootStatus = -1; - } - } - - /* Return SecureBoot status */ - return SecureBootStatus; -} - -/** - * Read system configuration from a specified table. - * - * @param TableGuid - * Supplies a pointer to the GUID to search for. - * - * @param Table - * Supplies a pointer that will point to the configuration table. - * - * @return This routine returns a status code. - * - * @since XT 1.0 - */ -XTCDECL -EFI_STATUS -BlEfiGetSystemConfigurationTable(IN PEFI_GUID TableGuid, - OUT PVOID *Table) -{ - SIZE_T Size = sizeof(EFI_GUID); - UINT_PTR Index; - - for(Index = 0; Index < EfiSystemTable->NumberOfTableEntries; Index++) - { - if(RtlCompareMemory((PVOID)&EfiSystemTable->ConfigurationTable[Index].VendorGuid, TableGuid, Size) == Size) - { - *Table = EfiSystemTable->ConfigurationTable[Index].VendorTable; - return STATUS_EFI_SUCCESS; - } - } - - /* Table not found */ - return STATUS_EFI_NOT_FOUND; -} diff --git a/xtldr/textui.c b/xtldr/textui.c new file mode 100644 index 0000000..c9aacef --- /dev/null +++ b/xtldr/textui.c @@ -0,0 +1,1288 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/textui.c + * DESCRIPTION: Text console User Interface (TUI) support for XT Boot Loader + * DEVELOPERS: Rafal Kupiec + */ + +#include + + +/** + * Displays a simple TUI-based boot menu. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlDisplayBootMenu() +{ + XTBL_DIALOG_HANDLE Handle; + PXTBL_BOOTMENU_ITEM MenuEntries = NULL; + ULONG Index, NumberOfEntries, HighligtedEntryId; + UINT_PTR EventIndex; + EFI_EVENT Events[2]; + EFI_INPUT_KEY Key; + EFI_EVENT TimerEvent; + EFI_STATUS Status; + LONG TimeOut; + PWCHAR TimeOutString; + + /* Initialize boot menu list */ + BlInitializeBootMenuList(MenuEntries, &NumberOfEntries, &HighligtedEntryId); + + /* Get timeout from the configuration */ + TimeOutString = BlGetConfigValue(L"TIMEOUT"); + TimeOut = -1; + + /* Check if timeout is specified */ + if(TimeOutString != NULL) + { + /* Convert timeout string to number */ + TimeOut = 0; + while(*TimeOutString >= '0' && *TimeOutString <= '9') + { + TimeOut *= 10; + TimeOut += *TimeOutString - '0'; + TimeOutString++; + } + } + + /* Infinite boot menu loop */ + while(TRUE) + { + /* Draw boot menu */ + BlpDrawBootMenu(&Handle); + + /* Check if there is anything to show in the boot menu */ + if(NumberOfEntries > 0) { + /* Check if all menu entries will fit into the menu box */ + if(NumberOfEntries > Handle.Height - 2) + { + /* Too many menu entries, limit entries to match box height (-2 for upper and bottom borders) */ + NumberOfEntries = Handle.Height - 2; + } + + /* Iterate through all menu entries */ + for(Index = 0; Index < NumberOfEntries; Index++) + { + /* Draw menu entry */ + BlpDrawBootMenuEntry(&Handle, MenuEntries[Index].EntryName, Index, Index == HighligtedEntryId); + } + } + else + { + /* No menu entries found, show error message */ + BlDisplayErrorDialog(L"XTLDR", L"No boot menu entries found in the configuration. Falling back to shell."); + + /* Exit into XTLDR shell */ + return; + } + + /* Create a timer event for controlling the timeout of the boot menu */ + Status = EfiSystemTable->BootServices->CreateEvent(EFI_EVENT_TIMER, EFI_TPL_CALLBACK, NULL, NULL, &TimerEvent); + if(Status == STATUS_EFI_SUCCESS) + { + /* Setup new EFI timer */ + Status = EfiSystemTable->BootServices->SetTimer(TimerEvent, TimerPeriodic, 10000000); + } + + /* Check is EFI timer was successfully created */ + if(Status != STATUS_EFI_SUCCESS) + { + /* Timer creation failed, disable the timer */ + TimeOut = -1; + } + + /* Initialize EFI events */ + Events[0] = EfiSystemTable->ConIn->WaitForKey; + Events[1] = TimerEvent; + + /* Infinite boot menu event loop */ + while(TRUE) + { + /* Wait for EFI event */ + BlWaitForEfiEvent(2, Events, &EventIndex); + + /* Check which event was received */ + if(EventIndex == 0) + { + /* Key pressed, check if timer is still active */ + if(TimeOut != -1) + { + /* Disable the timer */ + TimeOut = -1; + + /* Cancel timer event */ + EfiSystemTable->BootServices->SetTimer(TimerEvent, TimerCancel, 0); + + /* Remove the timer message */ + BlClearConsoleLine(Handle.PosY + Handle.Height + 4); + } + + /* Read key stroke */ + BlReadKeyStroke(&Key); + + if(Key.ScanCode == 0x03 || Key.UnicodeChar == 0x0D) + { + /* ENTER or RightArrow key pressed, boot the highlighted OS */ + BlSetConsoleAttributes(Handle.DialogColor | Handle.TextColor); + BlClearConsoleLine(Handle.PosY + Handle.Height + 4); + BlSetCursorPosition(4, Handle.PosY + Handle.Height + 4); + BlConsolePrint(L"Booting '%S' now...\n", MenuEntries[HighligtedEntryId].EntryName); + + /* Boot the highlighted (chosen) OS */ + Status = BlInvokeBootProtocol(MenuEntries[HighligtedEntryId].Options); + if(Status != STATUS_SUCCESS) + { + /* Failed to boot OS */ + BlDebugPrint(L"ERROR: Failed to boot OS '%S' (Status Code: 0x%lx)\n", + MenuEntries[HighligtedEntryId].EntryName, Status); + BlDisplayErrorDialog(L"XTLDR", L"Failed to startup the selected Operating System."); + } + + /* Break from boot menu event loop to redraw whole boot menu */ + break; + } + else if(Key.ScanCode == 0x01) + { + /* UpArrow key pressed, go to previous entry if possible */ + if(HighligtedEntryId > 0) + { + /* Highlight previous entry */ + HighligtedEntryId--; + BlpDrawBootMenuEntry(&Handle, MenuEntries[HighligtedEntryId + 1].EntryName, + HighligtedEntryId + 1, FALSE); + BlpDrawBootMenuEntry(&Handle, MenuEntries[HighligtedEntryId].EntryName, + HighligtedEntryId, TRUE); + } + } + else if(Key.ScanCode == 0x02) + { + /* DownArrow key pressed, go to next entry if possible */ + if(HighligtedEntryId < NumberOfEntries - 1) + { + /* Highlight next entry */ + HighligtedEntryId++; + BlpDrawBootMenuEntry(&Handle, MenuEntries[HighligtedEntryId - 1].EntryName, + HighligtedEntryId - 1, FALSE); + BlpDrawBootMenuEntry(&Handle, MenuEntries[HighligtedEntryId].EntryName, + HighligtedEntryId, TRUE); + } + } + else if(Key.ScanCode == 0x09) + { + /* PageUp key pressed, go to top entry */ + if(HighligtedEntryId != 0) + { + /* Highlight first entry */ + BlpDrawBootMenuEntry(&Handle, MenuEntries[HighligtedEntryId].EntryName, + HighligtedEntryId, FALSE); + BlpDrawBootMenuEntry(&Handle, MenuEntries[0].EntryName, 0, TRUE); + + /* Update highlighted entry ID */ + HighligtedEntryId = 0; + } + } + else if(Key.ScanCode == 0x0A) + { + /* PageDown key pressed, go to bottom entry */ + if(HighligtedEntryId != NumberOfEntries - 1) + { + /* Highlight last entry */ + BlpDrawBootMenuEntry(&Handle, MenuEntries[HighligtedEntryId].EntryName, + HighligtedEntryId, FALSE); + BlpDrawBootMenuEntry(&Handle, MenuEntries[NumberOfEntries - 1].EntryName, + NumberOfEntries - 1, TRUE); + + /* Update highlighted entry ID */ + HighligtedEntryId = NumberOfEntries - 1; + } + } + else if(Key.ScanCode == 0x0B) + { + /* F1 key pressed, show help */ + BlDisplayInfoDialog(L"XTLDR", L"XTLDR, the XTOS Boot Loader for UEFI and EFI-based machines.\n" + L" \n" + L"Use arrow keys (Up/Down) to change the highlighted entry and\n" + L"PgUp/PgDown keys to jump to the first/last position.\n" + L" \n" + L"Press ENTER key to boot the highlighted boot menu entry.\n" + L"Press 'e' key to edit the highlighted menu entry.\n" + L"Press 's' key to exit into XTLDR shell (advanced mode).\n"); + + /* Break from boot menu event loop to redraw whole boot menu */ + break; + } + else if(Key.UnicodeChar == 0x65) + { + /* 'e' key pressed, edit the highlighted entry */ + BlDisplayErrorDialog(L"XTLDR", L"Editing boot menu entries is not implemented yet!"); + + /* Break from boot menu event loop to redraw whole boot menu */ + break; + } + else if(Key.UnicodeChar == 0x73) + { + /* 's' key pressed, exit into XTLDR shell */ + return; + } + } + else + { + /* Timer tick, check if time out expired */ + if(TimeOut > 0) + { + /* Update a message and decrease timeout value */ + BlSetConsoleAttributes(Handle.DialogColor | Handle.TextColor); + BlClearConsoleLine(Handle.PosY + Handle.Height + 4); + BlSetCursorPosition(4, Handle.PosY + Handle.Height + 4); + BlConsolePrint(L"The highlighted position will be booted automatically in %ld seconds.", TimeOut); + TimeOut--; + } + else if(TimeOut == 0) + { + /* Time out expired, update a message */ + BlSetConsoleAttributes(Handle.DialogColor | Handle.TextColor); + BlClearConsoleLine(Handle.PosY + Handle.Height + 4); + BlSetCursorPosition(4, Handle.PosY + Handle.Height + 4); + BlConsolePrint(L"Booting '%S' now...\n", MenuEntries[HighligtedEntryId].EntryName); + + /* Disable the timer just in case booting OS fails */ + TimeOut = -1; + + /* Boot the highlighted (default) OS */ + Status = BlInvokeBootProtocol(MenuEntries[HighligtedEntryId].Options); + if(Status != STATUS_SUCCESS) + { + /* Failed to boot OS */ + BlDebugPrint(L"ERROR: Failed to boot OS '%S' (Status Code: 0x%lx)\n", + MenuEntries[HighligtedEntryId].EntryName, Status); + BlDisplayErrorDialog(L"XTLDR", L"Failed to startup the selected Operating System."); + } + break; + } + } + } + } +} + +/** + * Displays a red error dialog box with the specified caption and message. + * + * @param Caption + * Supplies a caption string put on the dialog box. + * + * @param Message + * Supplies a message string put on the dialog box. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlDisplayErrorDialog(IN PWCHAR Caption, + IN PWCHAR Message) +{ + XTBL_DIALOG_HANDLE Handle; + EFI_INPUT_KEY Key; + UINT_PTR Index; + + /* Set dialog window attributes */ + Handle.Attributes = XTBL_TUI_DIALOG_ERROR_BOX | XTBL_TUI_DIALOG_ACTIVE_BUTTON; + + /* Determine dialog window size and position */ + BlpDetermineDialogBoxSize(&Handle, Message); + + /* Disable cursor and draw dialog box */ + BlDisableConsoleCursor(); + BlpDrawDialogBox(&Handle, Caption, Message); + + /* Draw active button */ + BlpDrawDialogButton(&Handle); + + /* Initialize key stroke */ + Key.ScanCode = 0; + Key.UnicodeChar = 0; + + /* Wait until ENTER or ESC key is pressed */ + while(Key.ScanCode != 0x17 && Key.UnicodeChar != 0x0D) + { + /* Wait for key press and read key stroke */ + BlWaitForEfiEvent(1, &EfiSystemTable->ConIn->WaitForKey, &Index); + BlReadKeyStroke(&Key); + BlResetConsoleInputBuffer(); + } + + /* Clear screen to remove dialog box */ + BlSetConsoleAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_LIGHTGRAY); + BlClearConsoleScreen(); +} + +/** + * Displays a blue informational dialog box with the specified caption and message. + * + * @param Caption + * Supplies a caption string put on the dialog box. + * + * @param Message + * Supplies a message string put on the dialog box. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlDisplayInfoDialog(IN PWCHAR Caption, + IN PWCHAR Message) +{ + XTBL_DIALOG_HANDLE Handle; + EFI_INPUT_KEY Key; + UINT_PTR Index; + + /* Set dialog window attributes */ + Handle.Attributes = XTBL_TUI_DIALOG_GENERIC_BOX | XTBL_TUI_DIALOG_ACTIVE_BUTTON; + + /* Determine dialog window size and position */ + BlpDetermineDialogBoxSize(&Handle, Message); + + /* Disable cursor and draw dialog box */ + BlDisableConsoleCursor(); + BlpDrawDialogBox(&Handle, Caption, Message); + + /* Draw active button */ + BlpDrawDialogButton(&Handle); + + /* Initialize key stroke */ + Key.ScanCode = 0; + Key.UnicodeChar = 0; + + /* Wait until ENTER or ESC key is pressed */ + while(Key.ScanCode != 0x17 && Key.UnicodeChar != 0x0D) + { + /* Wait for key press and read key stroke */ + BlWaitForEfiEvent(1, &EfiSystemTable->ConIn->WaitForKey, &Index); + BlReadKeyStroke(&Key); + BlResetConsoleInputBuffer(); + } + + /* Clear screen to remove dialog box */ + BlSetConsoleAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_LIGHTGRAY); + BlClearConsoleScreen(); +} + +/** + * Displays a blue informational dialog box with the specified caption and message and an input field. + * + * @param Caption + * Specifies a caption string put on the dialog box. + * + * @param Message + * Specifies a message string put on the dialog box. + * + * @param InputFieldText + * Specifies a pointer to the input field text that will be edited. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlDisplayInputDialog(IN PWCHAR Caption, + IN PWCHAR Message, + IN PWCHAR *InputFieldText) +{ + SIZE_T InputFieldLength, TextCursorPosition, TextIndex, TextPosition; + XTBL_DIALOG_HANDLE Handle; + PWCHAR InputFieldBuffer; + SIZE_T BufferLength; + EFI_INPUT_KEY Key; + EFI_STATUS Status; + UINT_PTR Index; + + /* Set dialog window attributes */ + Handle.Attributes = XTBL_TUI_DIALOG_GENERIC_BOX | XTBL_TUI_DIALOG_ACTIVE_INPUT | XTBL_TUI_DIALOG_INACTIVE_BUTTON; + + /* Determine dialog window size and position */ + BlpDetermineDialogBoxSize(&Handle, Message); + + /* Disable cursor and draw dialog box */ + BlDisableConsoleCursor(); + BlpDrawDialogBox(&Handle, Caption, Message); + + /* Draw inactive button */ + BlpDrawDialogButton(&Handle); + + /* Draw active input field */ + BlpDrawDialogInputField(&Handle, *InputFieldText); + + /* Initialize key stroke */ + Key.ScanCode = 0; + Key.UnicodeChar = 0; + + /* Get initial input text length and allocate a buffer */ + BufferLength = RtlWideStringLength(*InputFieldText, 0); + Status = BlMemoryAllocatePool(BufferLength * sizeof(WCHAR), (PVOID *)&InputFieldBuffer); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory allocation failure, print error message and return */ + BlDebugPrint(L"ERROR: Memory allocation failure (Status Code: 0x%lx)\n", Status); + BlDisplayErrorDialog(L"XTLDR", L"Failed to allocate memory for input field buffer."); + return; + } + + /* Copy input text into edit buffer */ + RtlCopyMemory(InputFieldBuffer, *InputFieldText, BufferLength * sizeof(WCHAR)); + InputFieldBuffer[BufferLength] = L'\0'; + + /* Determine input field length */ + InputFieldLength = BufferLength; + if(InputFieldLength > Handle.Width - 8) + { + InputFieldLength = Handle.Width - 8; + } + + /* Start at first character */ + TextPosition = 0; + BlSetCursorPosition(Handle.PosX + 4 + TextPosition, Handle.PosY + Handle.Height - 4); + + /* Wait until ENTER or ESC key is pressed */ + while(TRUE) + { + /* Wait for key press and read key stroke */ + BlWaitForEfiEvent(1, &EfiSystemTable->ConIn->WaitForKey, &Index); + BlReadKeyStroke(&Key); + BlResetConsoleInputBuffer(); + + /* Check key press scan code */ + if(Key.ScanCode == 0x17) + { + /* ESC key pressed, return */ + break; + } + else if(Key.UnicodeChar == 0x09) + { + /* TAB key pressed, toggle input field and button */ + Handle.Attributes ^= (XTBL_TUI_DIALOG_ACTIVE_INPUT | XTBL_TUI_DIALOG_INACTIVE_INPUT); + Handle.Attributes ^= (XTBL_TUI_DIALOG_ACTIVE_BUTTON | XTBL_TUI_DIALOG_INACTIVE_BUTTON); + } + else if(Key.ScanCode == 0x03) + { + /* RIGHT key pressed, move cursor forward */ + if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT && TextPosition < InputFieldLength) + { + TextPosition++; + } + } + else if(Key.ScanCode == 0x04) + { + /* LEFT key pressed, move cursor back */ + if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT && TextPosition > 0) + { + TextPosition--; + } + } + else if(Key.ScanCode == 0x05) + { + /* HOME key pressed, move cursor to the beginning */ + if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT) + { + TextPosition = 0; + } + } + else if(Key.ScanCode == 0x06) + { + /* END key pressed, move cursor to the end */ + if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT) + { + TextPosition = InputFieldLength; + } + } + else if(Key.ScanCode == 0x08) + { + /* DELETE key pressed, delete character */ + if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT) + { + if(InputFieldLength > 0 && TextPosition < InputFieldLength) + { + RtlMoveMemory(InputFieldBuffer + TextPosition, InputFieldBuffer + TextPosition + 1, + (InputFieldLength - TextPosition) * sizeof(WCHAR)); + InputFieldLength--; + InputFieldBuffer[InputFieldLength] = 0; + } + } + } + else if(Key.UnicodeChar == 0x08) + { + /* BACKSPACE key pressed, delete character */ + if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT) + { + if(InputFieldLength > 0 && TextPosition > 0 && TextPosition <= InputFieldLength) + { + TextPosition--; + RtlMoveMemory(InputFieldBuffer + TextPosition, InputFieldBuffer + TextPosition + 1, + (InputFieldLength - TextPosition) * sizeof(WCHAR)); + InputFieldLength--; + InputFieldBuffer[InputFieldLength] = 0; + } + } + } + else if(Key.UnicodeChar == 0x0D) + { + /* ENTER key pressed, update input buffer */ + *InputFieldText = InputFieldBuffer; + break; + } + else + { + /* Other key pressed, add character to the buffer */ + if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT && Key.UnicodeChar != 0) + { + RtlMoveMemory(InputFieldBuffer + TextPosition + 1, InputFieldBuffer + TextPosition, + (InputFieldLength - TextPosition) * sizeof(WCHAR)); + InputFieldBuffer[TextPosition] = Key.UnicodeChar; + TextPosition++; + InputFieldLength++; + InputFieldBuffer[InputFieldLength] = 0; + } + } + + if(TextPosition > (Handle.Width - 9)) + { + TextIndex = TextPosition - (Handle.Width - 9); + TextCursorPosition = Handle.Width - 9; + } + else + { + TextIndex = 0; + TextCursorPosition = TextPosition; + } + + /* Redraw input field and button */ + BlpDrawDialogButton(&Handle); + BlpDrawDialogInputField(&Handle, &InputFieldBuffer[TextIndex]); + + if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT) + { + BlSetCursorPosition(Handle.PosX + 4 + TextCursorPosition, Handle.PosY + Handle.Height - 4); + } + } + + /* Clear screen to remove dialog box */ + BlSetConsoleAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_LIGHTGRAY); + BlClearConsoleScreen(); +} + +/** + * Displays a blue informational dialog box with the specified caption and message and a progress bar. + * + * @param Caption + * Supplies a caption string put on the dialog box. + * + * @param Message + * Supplies a message string put on the dialog box. + * + * @param Percentage + * Specifies the percentage progress of the progress bar. + * + * @return This routine returns a dialog box handle needed to update the progress bar. + * + * @since XT 1.0 + */ +XTCDECL +XTBL_DIALOG_HANDLE +BlDisplayProgressDialog(IN PWCHAR Caption, + IN PWCHAR Message, + IN UCHAR Percentage) +{ + XTBL_DIALOG_HANDLE Handle; + + /* Set dialog window attributes */ + Handle.Attributes = XTBL_TUI_DIALOG_GENERIC_BOX | XTBL_TUI_DIALOG_PROGRESS_BAR; + + /* Determine dialog window size and position */ + BlpDetermineDialogBoxSize(&Handle, Message); + + /* Disable cursor and draw dialog box */ + BlDisableConsoleCursor(); + BlpDrawDialogBox(&Handle, Caption, Message); + + /* Draw active button */ + BlpDrawDialogProgressBar(&Handle, Percentage); + + /* Return dialog handle */ + return Handle; +} + +/** + * Updates the progress bar on the dialog box. + * + * @param Handle + * Supplies a pointer to the dialog box handle. + * + * @param Message + * Supplies a new message that will be put on the dialog box, while updating the progress bar. + * + * @param Percentage + * Specifies the new percentage progress of the progress bar. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlUpdateProgressBar(IN PXTBL_DIALOG_HANDLE Handle, + IN PWCHAR Message, + IN UCHAR Percentage) +{ + /* Check if message needs an update */ + if(Message != NULL) + { + /* Update a message on the dialog box */ + BlpDrawDialogMessage(Handle, Message); + } + + /* Update progress bar */ + BlpDrawDialogProgressBar(Handle, Percentage); +} + +/** + * Determines dialog box size based on enabled components and message length. + * + * @param Handle + * Supplies a pointer to the dialog box handle. + * + * @param Message + * Supplies a pointer to the message string put on the dialog box. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlpDetermineDialogBoxSize(IN OUT PXTBL_DIALOG_HANDLE Handle, + IN PWCHAR Message) +{ + UINT_PTR Width, Height, LineLength; + SIZE_T Index, MessageLength; + UCHAR Attributes; + ULONG Mask; + + /* Set minimum dialog window size */ + Height = 4; + Width = 36; + + /* Zero line length */ + LineLength = 0; + + /* Adjust window height according to enabled components */ + Mask = 1; + Attributes = Handle->Attributes; + while(Mask) + { + /* Check enabled components that affect dialog window size */ + switch(Attributes & Mask) + { + case XTBL_TUI_DIALOG_ACTIVE_BUTTON: + case XTBL_TUI_DIALOG_INACTIVE_BUTTON: + Height += 1; + break; + case XTBL_TUI_DIALOG_ACTIVE_INPUT: + case XTBL_TUI_DIALOG_INACTIVE_INPUT: + case XTBL_TUI_DIALOG_PROGRESS_BAR: + Height += 2; + break; + } + + /* Update component attributes mask */ + Attributes &= ~Mask; + Mask <<= 1; + } + + /* Check if input field is active */ + if(Handle->Attributes & (XTBL_TUI_DIALOG_ACTIVE_INPUT | XTBL_TUI_DIALOG_INACTIVE_INPUT)) + { + /* Set maximum dialog window width to fit input field */ + Width = XTBL_TUI_MAX_DIALOG_WIDTH; + } + + /* Get message length and count dialog window dimensions */ + MessageLength = RtlWideStringLength(Message, 0); + for(Index = 0; Index < MessageLength; Index++) + { + /* Check if this is multiline message */ + if(Message[Index] == L'\n' || Index == MessageLength - 1) + { + /* Check if this line exceeds current dialog window width */ + if(LineLength > Width) + { + /* Update dialog window width */ + Width = LineLength; + } + + /* Increase dialog window height to fit next line */ + Height++; + LineLength = 0; + } + else + { + /* Increase dialog window width to fit next character */ + LineLength++; + } + } + + /* Add more space to dialog window to fit side borders */ + Width += 4; + + /* Get console resolution */ + BlQueryConsoleMode(&Handle->ResX, &Handle->ResY); + + /* Make sure dialog window fits in the buffer */ + if(Width > XTBL_TUI_MAX_DIALOG_WIDTH) + { + /* Set maximum dialog window width */ + Width = XTBL_TUI_MAX_DIALOG_WIDTH; + } + + /* Make sure dialog window fits on the screen (X axis) and it is not too small for input field */ + if(Width > (Handle->ResX - 2)) + { + /* Set maximum dialog window width */ + Width = Handle->ResX - 2; + } + + /* Make sure dialog window fits on the screen (Y axis)*/ + if(Height > (Handle->ResY - 2)) + { + /* Set maximum dialog window height */ + Height = Handle->ResY - 2; + } + + /* Set dialog window final dimensions */ + Handle->PosX = (Handle->ResX - Width) / 2; + Handle->PosY = (Handle->ResY - Height) / 2; + Handle->Width = Width; + Handle->Height = Height; +} + +/** + * Draws a text UI-based boot menu. + * + * @param Handle + * Supplies a pointer to the boot menu handle. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlpDrawBootMenu(OUT PXTBL_DIALOG_HANDLE Handle) +{ + /* Query console screen resolution */ + BlQueryConsoleMode(&Handle->ResX, &Handle->ResY); + + /* Set boot menu parameters */ + Handle->Attributes = 0; + Handle->DialogColor = EFI_TEXT_BGCOLOR_BLACK; + Handle->TextColor = EFI_TEXT_FGCOLOR_LIGHTGRAY; + Handle->PosX = 3; + Handle->PosY = 3; + Handle->Width = Handle->ResX - 6; + Handle->Height = Handle->ResY - 10; + + /* Clear screen and disable cursor */ + BlSetConsoleAttributes(Handle->DialogColor | Handle->TextColor); + BlClearConsoleScreen(); + BlDisableConsoleCursor(); + + /* Check if debugging enabled */ + if(DEBUG) + { + /* Print debug version of XTLDR banner */ + BlSetCursorPosition((Handle->ResX - 44) / 2, 1); + BlConsolePrint(L"XTLDR Boot Loader v%d.%d (%s-%s)\n", + XTLDR_VERSION_MAJOR, XTLDR_VERSION_MINOR, XTOS_VERSION_DATE, XTOS_VERSION_HASH); + } + else + { + /* Print standard XTLDR banner */ + BlSetCursorPosition((Handle->ResX - 22) / 2, 1); + BlConsolePrint(L"XTLDR Boot Loader v%d.%d\n", XTLDR_VERSION_MAJOR, XTLDR_VERSION_MINOR); + } + + /* Draw empty dialog box for boot menu */ + BlpDrawDialogBox(Handle, NULL, NULL); + + /* Print help message below the boot menu */ + BlSetCursorPosition(0, Handle->PosY + Handle->Height); + BlSetConsoleAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_LIGHTGRAY); + BlConsolePrint(L" Use cursors to change the selection. Press ENTER key to boot the chosen\n" + " Operating System, 'e' to edit it before booting or 's' for XTLDR shell.\n" + " Additional help available after pressing F1 key."); +} + +/** + * Draws boot menu entry at the specified position. + * + * @param Handle + * Supplies a pointer to the boot menu handle. + * + * @param MenuEntry + * Supplies a pointer to the buffer containing a menu entry name. + * + * @param Position + * Specifies entry position on the list in the boot menu. + * + * @param Highlighted + * Specifies whether this entry should be highlighted or not. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlpDrawBootMenuEntry(IN PXTBL_DIALOG_HANDLE Handle, + IN PWCHAR MenuEntry, + IN UINT Position, + IN BOOLEAN Highlighted) +{ + UINT Index; + + /* Check whether this entry should be highlighted */ + if(Highlighted) + { + /* Highlight this entry */ + BlSetConsoleAttributes(EFI_TEXT_BGCOLOR_LIGHTGRAY | EFI_TEXT_FGCOLOR_BLACK); + } + else + { + /* Set default colors */ + BlSetConsoleAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_LIGHTGRAY); + } + + /* Move cursor to the right position */ + BlSetCursorPosition(5, 4 + Position); + + /* Clear menu entry */ + for(Index = 0; Index < Handle->Width - 4; Index++) + { + BlConsolePrint(L" "); + } + + /* Print menu entry */ + BlSetCursorPosition(5, 4 + Position); + BlConsolePrint(L"%S\n", MenuEntry); +} + +/** + * Draws dialog box with caption and message. + * + * @param Handle + * Supplies a pointer to the dialog box handle. + * + * @param Caption + * Specifies a caption string put on the dialog box. + * + * @param Message + * Specifies a message string put on the dialog box. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlpDrawDialogBox(IN OUT PXTBL_DIALOG_HANDLE Handle, + IN PWCHAR Caption, + IN PWCHAR Message) +{ + WCHAR BoxLine[XTBL_TUI_MAX_DIALOG_WIDTH]; + SIZE_T CaptionLength; + UINT_PTR PosX, PosY; + + /* Set dialog colors */ + if(Handle->Attributes & XTBL_TUI_DIALOG_ERROR_BOX) + { + /* Error dialog with red background and brown button */ + Handle->DialogColor = EFI_TEXT_BGCOLOR_RED; + Handle->TextColor = EFI_TEXT_FGCOLOR_WHITE; + } + else if(Handle->Attributes & XTBL_TUI_DIALOG_GENERIC_BOX) + { + /* Generic dialog with blue background and cyan button */ + Handle->DialogColor = EFI_TEXT_BGCOLOR_BLUE; + Handle->TextColor = EFI_TEXT_FGCOLOR_WHITE; + } + + /* Set dialog box colors */ + BlSetConsoleAttributes(Handle->DialogColor | 0x0F); + + /* Iterate through dialog box lines */ + for(PosY = Handle->PosY; PosY < Handle->PosY + Handle->Height; PosY++) + { + /* Set cursor position in the appropriate place */ + BlSetCursorPosition(Handle->PosX, PosY); + + /* Draw dialog box */ + if(PosY == Handle->PosY) + { + /* Draw top line of the dialog box, starting from the left corner */ + BoxLine[0] = EFI_TEXT_BOX_DOWN_RIGHT; + + /* Check if there is a caption for this dialog */ + if(Caption != NULL) + { + /* Get caption length */ + CaptionLength = RtlWideStringLength(Caption, 0); + + /* Start caption area with vertical line */ + BoxLine[1] = EFI_TEXT_BOX_VERTICAL_LEFT; + + /* Fill caption area with spaces */ + for(PosX = 2; PosX < CaptionLength + 4; PosX++) + { + BoxLine[PosX] = ' '; + } + + /* End caption area with vertical line */ + BoxLine[CaptionLength + 4] = EFI_TEXT_BOX_VERTICAL_RIGHT; + } + else + { + /* No caption, -4 because of left and right vertical lines and corresponding spaces */ + CaptionLength = -4; + } + + /* Draw bottom line */ + for(PosX = CaptionLength + 5; PosX < Handle->Width - 1; PosX++) + { + BoxLine[PosX] = EFI_TEXT_BOX_HORIZONTAL; + } + + /* End with top right corner */ + BoxLine[Handle->Width - 1] = EFI_TEXT_BOX_DOWN_LEFT; + } + else if(PosY == Handle->PosY + Handle->Height - 1) + { + /* Draw bottom line of the dialog box, starting from the left corner */ + BoxLine[0] = EFI_TEXT_BOX_UP_LEFT; + + /* Fill bottom with horizontal line */ + for(PosX = 1; PosX < Handle->Width - 1; PosX++) + { + BoxLine[PosX] = EFI_TEXT_BOX_HORIZONTAL; + } + + /* End with bottom right corner */ + BoxLine[Handle->Width - 1] = EFI_TEXT_BOX_UP_RIGHT; + } + else + { + /* Draw the middle of the dialog box */ + BoxLine[0] = EFI_TEXT_BOX_VERTICAL; + + /* Fill dialog box with spaces */ + for(PosX = 1; PosX < Handle->Width - 1; PosX++) + { + BoxLine[PosX] = ' '; + } + + /* End with vertical line */ + BoxLine[Handle->Width - 1] = EFI_TEXT_BOX_VERTICAL; + } + + /* Add null terminator to the end of the line */ + BoxLine[Handle->Width] = 0; + + /* Write the line to the console */ + BlConsoleWrite(BoxLine); + } + + /* Make sure there is a caption to print */ + if(Caption != NULL) + { + /* Write dialog box caption */ + BlSetCursorPosition(Handle->PosX + 3, Handle->PosY); + BlConsolePrint(L"%S", Caption); + } + + /* Make sure there is a message to print */ + if(Message != NULL) + { + /* Write a message on the dialog box */ + BlpDrawDialogMessage(Handle, Message); + } +} + +/** + * Draws an active or inactive button in the dialog box, depending on the attributes. + * + * @param Handle + * Supplies a pointer to the dialog box handle. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlpDrawDialogButton(IN PXTBL_DIALOG_HANDLE Handle) +{ + ULONG ButtonColor, TextColor; + + /* Set dialog button colors */ + if(Handle->Attributes & XTBL_TUI_DIALOG_ACTIVE_BUTTON) + { + /* This is an active button */ + if(Handle->Attributes & XTBL_TUI_DIALOG_ERROR_BOX) + { + /* This is an error dialog box */ + ButtonColor = EFI_TEXT_BGCOLOR_BROWN; + TextColor = EFI_TEXT_FGCOLOR_WHITE; + } + else + { + /* This is a generic dialog box */ + ButtonColor = EFI_TEXT_BGCOLOR_CYAN; + TextColor = EFI_TEXT_FGCOLOR_WHITE; + } + } + else + { + /* This is an inactive button */ + ButtonColor = EFI_TEXT_BGCOLOR_LIGHTGRAY; + TextColor = EFI_TEXT_FGCOLOR_BLACK; + } + + /* Disable cursor and draw dialog button */ + BlDisableConsoleCursor(); + BlSetConsoleAttributes(ButtonColor | TextColor); + BlSetCursorPosition(Handle->ResX / 2 - 4, Handle->PosY + Handle->Height - 2); + BlConsolePrint(L"[ OK ]"); +} + +/** + * Draws an active or inactive input field in the dialog box, depending on the attributes. + * + * @param Handle + * Supplies a pointer to the dialog box handle. + * + * @param InputFieldText + * Supplies a pointer to the wide char string that will be displayed in the input field. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlpDrawDialogInputField(IN PXTBL_DIALOG_HANDLE Handle, + IN PWCHAR InputFieldText) +{ + WCHAR InputField[XTBL_TUI_MAX_DIALOG_WIDTH]; + ULONG InputColor, TextColor; + UINT_PTR Index, Position; + SIZE_T Length; + + /* Set dialog button colors */ + if(Handle->Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT) + { + /* This is an active input field */ + if(Handle->Attributes & XTBL_TUI_DIALOG_ERROR_BOX) + { + /* This is an error dialog box */ + InputColor = EFI_TEXT_BGCOLOR_BROWN; + TextColor = EFI_TEXT_FGCOLOR_WHITE; + } + else + { + /* This is a generic dialog box */ + InputColor = EFI_TEXT_BGCOLOR_CYAN; + TextColor = EFI_TEXT_FGCOLOR_WHITE; + } + } + else + { + /* This is an inactive input field */ + InputColor = EFI_TEXT_BGCOLOR_LIGHTGRAY; + TextColor = EFI_TEXT_FGCOLOR_BLACK; + } + + /* Set progress bar color and position */ + BlSetConsoleAttributes(InputColor | TextColor); + Position = (Handle->Attributes & (XTBL_TUI_DIALOG_ACTIVE_BUTTON | XTBL_TUI_DIALOG_INACTIVE_BUTTON)) ? 4 : 3; + BlSetCursorPosition(Handle->PosX + 4, Handle->PosY + Handle->Height - Position); + + /* Draw input field */ + for(Index = 0; Index < Handle->Width - 8; Index++) + { + /* Fill input field with spaces */ + InputField[Index] = L' '; + } + + /* Disable cursor and write input field to console */ + BlDisableConsoleCursor(); + BlConsoleWrite(InputField); + + /* Check input field text length */ + Length = RtlWideStringLength(InputFieldText, 0); + if(Length > (Handle->Width - 9)) + { + /* Text longer than input field width, display only part of it */ + Length = Handle->Width - 9; + } + + /* Copy a part of input field text to input field */ + for(Index = 0; Index < Length; Index++) + { + /* Write input field text */ + InputField[Index] = InputFieldText[Index]; + } + + /* Add null terminator to the end of the line */ + InputField[Handle->Width] = 0; + + /* Write input field text */ + BlSetCursorPosition(Handle->PosX + 4, Handle->PosY + Handle->Height - Position); + BlConsoleWrite(InputField); + + /* Check if this is an active input field */ + if(Handle->Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT) + { + /* Enable cursor for active input field */ + BlEnableConsoleCursor(); + } +} + +/** + * Draws a message on the dialog box specified by the handle. + * + * @param Handle + * Supplies a pointer to the dialog box handle. + * + * @param Message + * Supplies a message that will be displayed on the dialog box. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlpDrawDialogMessage(IN PXTBL_DIALOG_HANDLE Handle, + IN PWCHAR Message) +{ + PWCHAR Msg, MsgLine, LastMsgLine; + SIZE_T Index, Length, LineLength; + EFI_STATUS Status; + ULONG Line; + + /* Allocate memory for dialog box message */ + Length = RtlWideStringLength(Message, 0); + Status = BlMemoryAllocatePool(Length * sizeof(WCHAR), (PVOID *)&Msg); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory allocation failure, print debug message and return */ + BlDebugPrint(L"ERROR: Memory allocation failure (Status Code: 0x%lx)\n", Status); + return; + } + + /* Make a copy of dialog box message */ + RtlCopyMemory(Msg, Message, Length * sizeof(WCHAR)); + Msg[Length] = 0; + + /* Tokenize dialog box message */ + MsgLine = RtlTokenizeWideString(Msg, L"\n", &LastMsgLine); + + /* Iterate through message lines */ + Line = 0; + while(MsgLine) + { + /* Determine line length */ + LineLength = RtlWideStringLength(MsgLine, 0); + + /* Write line in the dialog box */ + BlSetCursorPosition(Handle->PosX + 2, Handle->PosY + 2 + Line); + BlSetConsoleAttributes(Handle->DialogColor | Handle->TextColor); + BlConsolePrint(L"%S", MsgLine); + + /* Check if message line is shorter than the dialog box working area */ + if(LineLength < Handle->Width - 4) + { + /* Fill the rest of the line with spaces */ + for(Index = LineLength; Index < Handle->Width - 4; Index++) + { + BlConsolePrint(L" "); + } + } + + /* Get next line */ + MsgLine = RtlTokenizeWideString(NULL, L"\n", &LastMsgLine); + Line++; + } +} + +/** + * Draws a progress bar component in the dialog box. + * + * @param Handle + * Supplies a pointer to the dialog box handle. + * + * @param Percentage + * Specifies the percentage progress of the progress bar. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlpDrawDialogProgressBar(IN PXTBL_DIALOG_HANDLE Handle, + IN UCHAR Percentage) +{ + UINT_PTR Index, ProgressLength, ProgressBarLength; + WCHAR ProgressBar[XTBL_TUI_MAX_DIALOG_WIDTH]; + UINT_PTR Position; + + /* Determine progress bar length and calculate progress */ + ProgressBarLength = Handle->Width - 8; + ProgressLength = (ProgressBarLength * Percentage) / 100; + + /* Set progress bar color and position */ + BlSetConsoleAttributes(EFI_TEXT_FGCOLOR_YELLOW); + Position = (Handle->Attributes & (XTBL_TUI_DIALOG_ACTIVE_BUTTON | XTBL_TUI_DIALOG_INACTIVE_BUTTON)) ? 4 : 3; + BlSetCursorPosition(Handle->PosX + 4, Handle->PosY + Handle->Height - Position); + + /* Draw progress bar */ + for(Index = 0; Index < ProgressBarLength; Index++) + { + /* Fill progress bar */ + if(Index < ProgressLength) + { + /* Fill with full block */ + ProgressBar[Index] = EFI_TEXT_BOX_FULL_BLOCK; + } + else + { + /* Fill with light block */ + ProgressBar[Index] = EFI_TEXT_BOX_LIGHT_BLOCK; + } + } + + /* Terminate progress bar string */ + ProgressBar[Index] = 0; + + /* Disable cursor and write progress bar to console */ + BlDisableConsoleCursor(); + BlConsoleWrite(ProgressBar); +} diff --git a/xtldr/volume.c b/xtldr/volume.c index c6609cf..fdfca08 100644 --- a/xtldr/volume.c +++ b/xtldr/volume.c @@ -6,7 +6,7 @@ * DEVELOPERS: Rafal Kupiec */ -#include +#include /** @@ -45,7 +45,7 @@ BlCloseVolume(IN PEFI_HANDLE VolumeHandle) */ XTCDECL EFI_STATUS -BlEnumerateEfiBlockDevices() +BlEnumerateBlockDevices() { PEFI_DEVICE_PATH_PROTOCOL LastNode = NULL; PEFI_BLOCK_DEVICE_DATA ParentNode = NULL; @@ -70,7 +70,7 @@ BlEnumerateEfiBlockDevices() Status = BlpDiscoverEfiBlockDevices(&BlockDevices); if(Status != STATUS_EFI_SUCCESS) { - BlDbgPrint(L"ERROR: Failed to discover EFI block devices (status code: %lx)\n", Status); + BlDebugPrint(L"ERROR: Failed to discover EFI block devices (Status Code: 0x%lx)\n", Status); return Status; } @@ -82,16 +82,16 @@ BlEnumerateEfiBlockDevices() BlockDeviceData = CONTAIN_RECORD(ListEntry, EFI_BLOCK_DEVICE_DATA, ListEntry); /* Find last node */ - Status = BlpFindLastEfiBlockDeviceNode(BlockDeviceData->DevicePath, &LastNode); + Status = BlpFindLastBlockDeviceNode(BlockDeviceData->DevicePath, &LastNode); if(Status != STATUS_EFI_SUCCESS) { - BlDbgPrint(L"WARNING: Block device last node not found\n"); + BlDebugPrint(L"WARNING: Block device last node not found\n"); ListEntry = ListEntry->Flink; continue; } /* Set drive type to 'unknown' by default */ - DriveType = XT_BOOT_DEVICE_UNKNOWN; + DriveType = XTBL_BOOT_DEVICE_UNKNOWN; /* Check last node type */ if(LastNode->Type == EFI_ACPI_DEVICE_PATH && LastNode->SubType == EFI_ACPI_DP) @@ -102,12 +102,12 @@ BlEnumerateEfiBlockDevices() { /* Floppy drive found */ Media = BlockDeviceData->BlockIo->Media; - DriveType = XT_BOOT_DEVICE_FLOPPY; + DriveType = XTBL_BOOT_DEVICE_FLOPPY; DriveNumber = FDCount++; PartitionNumber = 0; /* Print debug message */ - BlDbgPrint(L"Found Floppy Disk (DiskNumber: %lu, MediaPresent: %u, RO: %u)\n", + BlDebugPrint(L"Found Floppy Disk (DiskNumber: %lu, MediaPresent: %u, RO: %u)\n", DriveNumber, Media->MediaPresent, Media->ReadOnly); } } @@ -118,12 +118,12 @@ BlEnumerateEfiBlockDevices() { /* Optical drive found */ Media = BlockDeviceData->BlockIo->Media; - DriveType = XT_BOOT_DEVICE_CDROM; + DriveType = XTBL_BOOT_DEVICE_CDROM; DriveNumber = CDCount++; PartitionNumber = 0; /* Print debug message */ - BlDbgPrint(L"Found CD-ROM drive (DriveNumber: %lu, MediaPresent: %u, RemovableMedia: %u, RO: %u)\n", + BlDebugPrint(L"Found CD-ROM drive (DriveNumber: %lu, MediaPresent: %u, RemovableMedia: %u, RO: %u)\n", DriveNumber, Media->MediaPresent, Media->RemovableMedia, Media->ReadOnly); } else if(LastNode->SubType == EFI_MEDIA_HARDDRIVE_DP) @@ -131,13 +131,13 @@ BlEnumerateEfiBlockDevices() /* Hard disk partition found */ Media = BlockDeviceData->BlockIo->Media; HDPath = (PEFI_HARDDRIVE_DEVICE_PATH)LastNode; - DriveType = XT_BOOT_DEVICE_HARDDISK; + DriveType = XTBL_BOOT_DEVICE_HARDDISK; DriveNumber = (HDPath->PartitionNumber == 1) ? HDCount++ : HDCount - 1; PartitionNumber = HDPath->PartitionNumber; PartitionGuid = (PEFI_GUID)HDPath->Signature; /* Print debug message */ - BlDbgPrint(L"Found Hard Disk partition (DiskNumber: %lu, PartNumber: %lu, " + BlDebugPrint(L"Found Hard Disk partition (DiskNumber: %lu, PartNumber: %lu, " L"MBRType: %u, GUID: {%g}, PartSize: %luB)\n", DriveNumber, PartitionNumber, HDPath->MBRType, PartitionGuid, HDPath->PartitionSize * Media->BlockSize); @@ -146,30 +146,30 @@ BlEnumerateEfiBlockDevices() { /* RAM disk found */ Media = BlockDeviceData->BlockIo->Media; - DriveType = XT_BOOT_DEVICE_RAMDISK; + DriveType = XTBL_BOOT_DEVICE_RAMDISK; DriveNumber = RDCount++; PartitionNumber = 0; /* Print debug message */ - BlDbgPrint(L"Found RAM Disk (DiskNumber: %lu, MediaPresent: %u)\n", + BlDebugPrint(L"Found RAM Disk (DiskNumber: %lu, MediaPresent: %u)\n", DriveNumber, Media->MediaPresent); } - if(!BlpFindParentEfiBlockDevice(&BlockDevices, BlockDeviceData, ParentNode)) + if(!BlpFindParentBlockDevice(&BlockDevices, BlockDeviceData, ParentNode)) { - BlDbgPrint(L"WARNING: No parent device found, skipping orphaned media device path\n"); + BlDebugPrint(L"WARNING: No parent device found, skipping orphaned media device path\n"); continue; } } /* Make sure the device found has valid type set */ - if(DriveType != XT_BOOT_DEVICE_UNKNOWN) + if(DriveType != XTBL_BOOT_DEVICE_UNKNOWN) { /* Allocate memory for block device */ - Status = BlEfiMemoryAllocatePool(sizeof(EFI_BLOCK_DEVICE), (PVOID *)&BlockDevice); + Status = BlMemoryAllocatePool(sizeof(EFI_BLOCK_DEVICE), (PVOID *)&BlockDevice); if(Status != STATUS_EFI_SUCCESS) { - BlDbgPrint(L"ERROR: Unable to allocate memory pool for block device (status code: %lx)\n", Status); + BlDebugPrint(L"ERROR: Failed to allocate memory pool for block device (Status Code: 0x%lx)\n", Status); return STATUS_EFI_OUT_OF_RESOURCES; } @@ -248,7 +248,7 @@ BlFindVolumeDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL FsHandle, FsPathLength = RtlWideStringLength(FileSystemPath, 0) * sizeof(WCHAR); /* Allocate memory pool for device path */ - Status = BlEfiMemoryAllocatePool(FsPathLength + DevicePathLength + sizeof(EFI_DEVICE_PATH_PROTOCOL), + Status = BlMemoryAllocatePool(FsPathLength + DevicePathLength + sizeof(EFI_DEVICE_PATH_PROTOCOL), (PVOID *)DevicePath); if(Status != STATUS_EFI_SUCCESS) { @@ -294,16 +294,16 @@ BlFindVolumeDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL FsHandle, */ XTCDECL EFI_STATUS -BlGetVolumeDevicePath(IN PUCHAR SystemPath, +BlGetVolumeDevicePath(IN PWCHAR SystemPath, OUT PEFI_DEVICE_PATH_PROTOCOL *DevicePath, - OUT PUCHAR *ArcName, - OUT PUCHAR *Path) + OUT PWCHAR *ArcName, + OUT PWCHAR *Path) { PEFI_BLOCK_DEVICE Device; USHORT DriveType; ULONG DriveNumber; ULONG PartNumber; - PUCHAR Volume; + PWCHAR Volume; ULONG PathLength; PLIST_ENTRY ListEntry; EFI_STATUS Status; @@ -333,13 +333,13 @@ BlGetVolumeDevicePath(IN PUCHAR SystemPath, if(PathLength == GUID_STRING_LENGTH) { /* This is EFI GUID */ - BlDbgPrint(L"EFI/GPT GUID in system path is not supported yet\n"); + BlDebugPrint(L"WARNING: EFI/GPT GUID in system path is not supported\n"); return STATUS_EFI_UNSUPPORTED; } else if(PathLength == PARTUUID_STRING_LENGTH) { /* This is MBR UUID */ - BlDbgPrint(L"MBR partition UUID in system path is not supported yet\n"); + BlDebugPrint(L"WARNING: MBR partition UUID in system path is not supported\n"); return STATUS_EFI_UNSUPPORTED; } else @@ -358,7 +358,7 @@ BlGetVolumeDevicePath(IN PUCHAR SystemPath, if(Status != STATUS_EFI_SUCCESS) { /* Failed to parse system path */ - BlDbgPrint(L"Failed to parse system path: '%s' with status code: %lx\n", SystemPath, Status); + BlDebugPrint(L"ERROR: Failed to parse system path: '%s' (Status Code: 0x%lx)\n", SystemPath, Status); return Status; } @@ -382,7 +382,7 @@ BlGetVolumeDevicePath(IN PUCHAR SystemPath, if(*DevicePath == NULL) { /* Failed to find volume */ - BlDbgPrint(L"Volume (DriveType: %u, DriveNumber: %lu, PartNumber: %lu) not found\n", + BlDebugPrint(L"ERROR: Volume (DriveType: %u, DriveNumber: %lu, PartNumber: %lu) not found\n", DriveType, DriveNumber, PartNumber); return STATUS_EFI_NOT_FOUND; } @@ -470,6 +470,125 @@ BlOpenVolume(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, return STATUS_EFI_SUCCESS; } +/** + * Reads data from the file. + * + * @param DirHandle + * Supplies a handle of the opened filesystem directory. + * + * @param FileName + * Supplies the name of the file to read. + * + * @param FileData + * Provides a buffer to store the data read from the file. + * + * @param FileSize + * Provides a pointer to the variable to store a size of the buffer. + * + * @return This routine returns status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlReadFile(IN PEFI_FILE_HANDLE DirHandle, + IN CONST PWCHAR FileName, + OUT PVOID *FileData, + OUT PSIZE_T FileSize) +{ + EFI_GUID FileInfoGuid = EFI_FILE_INFO_PROTOCOL_GUID; + EFI_PHYSICAL_ADDRESS Address; + PEFI_FILE_HANDLE FileHandle; + PEFI_FILE_INFO FileInfo; + EFI_STATUS Status; + UINT_PTR ReadSize; + SIZE_T Pages; + + Status = DirHandle->Open(DirHandle, &FileHandle, FileName, EFI_FILE_MODE_READ, + EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to open file */ + return Status; + } + + /* Set required size for getting file information */ + ReadSize = sizeof(EFI_FILE_INFO) + 32; + + /* Allocate necessary amount of memory */ + Status = BlMemoryAllocatePool(ReadSize, (PVOID *)&FileInfo); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory allocation failure */ + FileHandle->Close(FileHandle); + return Status; + } + + /* First attempt to get file information */ + FileHandle->GetInfo(FileHandle, &FileInfoGuid, &ReadSize, FileInfo); + if(Status == STATUS_EFI_BUFFER_TOO_SMALL) + { + /* Buffer is too small, but EFI tells the required size, so reallocate */ + BlMemoryFreePool(&FileInfo); + Status = BlMemoryAllocatePool(ReadSize, (PVOID *)&FileInfo); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory allocation failure */ + FileHandle->Close(FileHandle); + return Status; + } + + /* Second attempt to get file information */ + Status = FileHandle->GetInfo(FileHandle, &FileInfoGuid, &ReadSize, FileInfo); + } + + /* Check if file information got successfully */ + if(Status != STATUS_EFI_SUCCESS) + { + /* Unable to get file information */ + FileHandle->Close(FileHandle); + BlMemoryFreePool(&FileInfo); + return Status; + } + + /* Store file size and calculate number of pages */ + *FileSize = FileInfo->FileSize; + Pages = EFI_SIZE_TO_PAGES(FileInfo->FileSize); + + /* Allocate pages */ + Status = BlMemoryAllocatePages(Pages, &Address); + if(Status != STATUS_EFI_SUCCESS) + { + /* Pages allocation failure */ + FileHandle->Close(FileHandle); + BlMemoryFreePool(&FileInfo); + return Status; + } + + /* Calculate number of bytes to read and zero memory*/ + ReadSize = Pages * EFI_PAGE_SIZE; + *FileData = (PCHAR)(UINT_PTR)Address; + RtlZeroMemory(*FileData, ReadSize); + + /* Read data from the file */ + Status = FileHandle->Read(FileHandle, &ReadSize, *FileData); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to read data */ + FileHandle->Close(FileHandle); + BlMemoryFreePool(&FileInfo); + BlMemoryFreePages(Pages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)*FileData); + return Status; + } + + /* Close handle and free memory */ + FileHandle->Close(FileHandle); + BlMemoryFreePool(&FileInfo); + + /* Return success */ + return STATUS_EFI_SUCCESS; +} + /** * Gets a list of block devices from an EFI enabled BIOS. * @@ -498,7 +617,7 @@ BlpDiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices) if(Status != STATUS_EFI_SUCCESS) { /* Failed to locate handles */ - BlDbgPrint(L"ERROR: Failed to locate block devices handles (status code: %lx)\n", Status); + BlDebugPrint(L"ERROR: Failed to locate block devices handles (Status Code: 0x%lx)\n", Status); return Status; } @@ -506,7 +625,7 @@ BlpDiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices) for(Index = 0; Index < HandlesCount; Index++) { /* Print debug message */ - BlDbgPrint(L"Opening %lu block device from %lu discovered\n", Index + 1, HandlesCount); + BlDebugPrint(L"Opening %lu block device from %lu discovered\n", Index + 1, HandlesCount); /* Open I/O protocol for given handle */ Io = NULL; @@ -515,7 +634,7 @@ BlpDiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices) if(Status != STATUS_EFI_SUCCESS || Io == NULL) { /* Failed to open I/O protocol, skip it */ - BlDbgPrint(L"WARNING: Failed to open EFI Block I/O protocol (status code: %lx)\n", Status); + BlDebugPrint(L"WARNING: Failed to open EFI Block I/O protocol (Status Code: 0x%lx)\n", Status); continue; } @@ -523,7 +642,7 @@ BlpDiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices) if(Io->Media && Io->Media->BlockSize == 1 && Io->Media->MediaId == 0x69505845U) { /* Skip stub as it is non-functional */ - BlDbgPrint(L"WARNING: iPXE stub block I/O protocol"); + BlDebugPrint(L"WARNING: Skipping iPXE stub block I/O protocol"); continue; } @@ -533,17 +652,17 @@ BlpDiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices) if(Status != STATUS_EFI_SUCCESS || DevicePath == NULL) { /* Device failed to handle DP protocol */ - BlDbgPrint(L"WARNING: Unable to open DevicePath protocol (status code: %lx)\n", Status); + BlDebugPrint(L"WARNING: Unable to open DevicePath protocol (Status Code: 0x%lx)\n", Status); EfiSystemTable->BootServices->CloseProtocol(Handles[Index], &IoGuid, EfiImageHandle, NULL); continue; } /* Allocate memory for block device */ - Status = BlEfiMemoryAllocatePool(sizeof(*BlockDevice), (PVOID *)&BlockDevice); + Status = BlMemoryAllocatePool(sizeof(*BlockDevice), (PVOID *)&BlockDevice); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ - BlDbgPrint(L"ERROR: Unable to allocate memory pool for block device (status code: %lx)\n", Status); + BlDebugPrint(L"ERROR: Failed to allocate memory pool for block device (Status Code: 0x%lx)\n", Status); EfiSystemTable->BootServices->CloseProtocol(Handles[Index], &DevicePathGuid, EfiImageHandle, NULL); EfiSystemTable->BootServices->CloseProtocol(Handles[Index], &IoGuid, EfiImageHandle, NULL); return Status; @@ -556,7 +675,7 @@ BlpDiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices) } /* Free handles buffer */ - BlEfiMemoryFreePool(Handles); + BlMemoryFreePool(Handles); /* Return success */ return STATUS_EFI_SUCCESS; @@ -586,36 +705,36 @@ BlpDiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices) */ XTCDECL EFI_STATUS -BlpDissectVolumeArcPath(IN PUCHAR SystemPath, - OUT PUCHAR *ArcName, - OUT PUCHAR *Path, +BlpDissectVolumeArcPath(IN PWCHAR SystemPath, + OUT PWCHAR *ArcName, + OUT PWCHAR *Path, OUT PUSHORT DriveType, OUT PULONG DriveNumber, OUT PULONG PartNumber) { - PUCHAR ArcPath, LocalArcName; + PWCHAR ArcPath, LocalArcName; ULONG ArcLength = 0; /* Set default values */ - *DriveType = XT_BOOT_DEVICE_UNKNOWN; + *DriveType = XTBL_BOOT_DEVICE_UNKNOWN; *DriveNumber = 0; *PartNumber = 0; /* Look for the ARC path */ - if(BlStringCompareInsensitive(SystemPath, (PUCHAR)"ramdisk(0)") == 0) + if(RtlCompareWideStringInsensitive(SystemPath, L"ramdisk(0)", 0) == 0) { /* This is RAM disk */ ArcLength = 10; - *DriveType = XT_BOOT_DEVICE_RAMDISK; + *DriveType = XTBL_BOOT_DEVICE_RAMDISK; } - else if(BlStringCompareInsensitive(SystemPath, (PUCHAR)"multi(0)disk(0)") == 0) + else if(RtlCompareWideStringInsensitive(SystemPath, L"multi(0)disk(0)", 0) == 0) { /* This is a multi-disk port */ ArcLength = 15; ArcPath = SystemPath + ArcLength; /* Check for disk type */ - if(BlStringCompareInsensitive(ArcPath, (PUCHAR)"cdrom(") == 0) + if(RtlCompareWideStringInsensitive(ArcPath, L"cdrom(", 0) == 0) { /* This is an optical drive */ ArcLength += 6; @@ -633,10 +752,10 @@ BlpDissectVolumeArcPath(IN PUCHAR SystemPath, } /* Set proper drive type */ - *DriveType = XT_BOOT_DEVICE_CDROM; + *DriveType = XTBL_BOOT_DEVICE_CDROM; ArcLength++; } - else if(BlStringCompareInsensitive(ArcPath, (PUCHAR)"fdisk(") == 0) + else if(RtlCompareWideStringInsensitive(ArcPath, L"fdisk(", 0) == 0) { /* This is a floppy drive */ ArcLength += 6; @@ -654,10 +773,10 @@ BlpDissectVolumeArcPath(IN PUCHAR SystemPath, } /* Set proper drive type */ - *DriveType = XT_BOOT_DEVICE_FLOPPY; + *DriveType = XTBL_BOOT_DEVICE_FLOPPY; ArcLength++; } - else if(BlStringCompareInsensitive(ArcPath, (PUCHAR)"rdisk(") == 0) + else if(RtlCompareWideStringInsensitive(ArcPath, L"rdisk(", 0) == 0) { /* This is a hard disk */ ArcLength += 6; @@ -675,12 +794,12 @@ BlpDissectVolumeArcPath(IN PUCHAR SystemPath, } /* Set proper drive type */ - *DriveType = XT_BOOT_DEVICE_HARDDISK; + *DriveType = XTBL_BOOT_DEVICE_HARDDISK; ArcLength++; ArcPath = SystemPath + ArcLength; /* Look for a partition */ - if(BlStringCompareInsensitive(ArcPath, (PUCHAR)"partition(") == 0) + if(RtlCompareWideStringInsensitive(ArcPath, L"partition(", 0) == 0) { /* Partition information found */ ArcLength += 10; @@ -720,8 +839,8 @@ BlpDissectVolumeArcPath(IN PUCHAR SystemPath, /* Store ARC name if possible */ if(ArcName) { - BlEfiMemoryAllocatePool(ArcLength, (PVOID *)&LocalArcName); - RtlCopyMemory(LocalArcName, SystemPath, ArcLength); + BlMemoryAllocatePool(ArcLength * sizeof(WCHAR), (PVOID *)&LocalArcName); + RtlCopyMemory(LocalArcName, SystemPath, ArcLength * sizeof(WCHAR)); LocalArcName[ArcLength] = '\0'; *ArcName = LocalArcName; } @@ -770,11 +889,11 @@ BlpDuplicateDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath) } /* Allocate memory for the new device path */ - Status = BlEfiMemoryAllocatePool(Length, (PVOID *)&DevicePathClone); + Status = BlMemoryAllocatePool(Length, (PVOID *)&DevicePathClone); if(Status != STATUS_EFI_SUCCESS) { /* Failed to allocate memory */ - BlDbgPrint(L"ERROR: Unable to allocate memory pool for device path duplicate\n"); + BlDebugPrint(L"ERROR: Failed to allocate memory pool for device path duplicate (Status Code: 0x%lx)\n", Status); return NULL; } @@ -800,8 +919,8 @@ BlpDuplicateDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath) */ XTCDECL EFI_STATUS -BlpFindLastEfiBlockDeviceNode(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, - OUT PEFI_DEVICE_PATH_PROTOCOL *LastNode) +BlpFindLastBlockDeviceNode(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, + OUT PEFI_DEVICE_PATH_PROTOCOL *LastNode) { PEFI_DEVICE_PATH_PROTOCOL EndNode, NextNode; @@ -846,9 +965,9 @@ BlpFindLastEfiBlockDeviceNode(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, */ XTCDECL BOOLEAN -BlpFindParentEfiBlockDevice(IN PLIST_ENTRY BlockDevices, - IN PEFI_BLOCK_DEVICE_DATA ChildNode, - OUT PEFI_BLOCK_DEVICE_DATA ParentNode) +BlpFindParentBlockDevice(IN PLIST_ENTRY BlockDevices, + IN PEFI_BLOCK_DEVICE_DATA ChildNode, + OUT PEFI_BLOCK_DEVICE_DATA ParentNode) { PEFI_DEVICE_PATH_PROTOCOL ChildDevicePath, ParentDevicePath; PEFI_BLOCK_DEVICE_DATA BlockDeviceData; diff --git a/xtldr/xtldr.c b/xtldr/xtldr.c index dd9abee..33cd8bf 100644 --- a/xtldr/xtldr.c +++ b/xtldr/xtldr.c @@ -2,216 +2,161 @@ * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtldr/xtldr.c - * DESCRIPTION: UEFI XT Bootloader + * DESCRIPTION: XTOS UEFI Boot Loader * DEVELOPERS: Rafal Kupiec */ -#include +#include /** - * This routine loads XTLDR EFI modules. + * Initializes EFI Boot Loader (XTLDR). * - * @return This routine returns status code. + * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL -EFI_STATUS -BlLoadEfiModules() +VOID +BlInitializeBootLoader() { - CONST PWCHAR ModulesDirPath = L"\\EFI\\BOOT\\XTLDR\\"; - EFI_GUID DevicePathGuid = EFI_DEVICE_PATH_PROTOCOL_GUID; - EFI_GUID LIPGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID; - PEFI_DEVICE_PATH_PROTOCOL VolumeDevicePath, DevicePath; + EFI_GUID LipGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID; PEFI_LOADED_IMAGE_PROTOCOL LoadedImage; - PEFI_FILE_HANDLE FsHandle, ModulesDir; - EFI_HANDLE DiskHandle, ModuleHandle; - SIZE_T Length; + EFI_HANDLE Handle; EFI_STATUS Status; - UINT_PTR DirSize; - CHAR Buffer[1024]; - WCHAR ModulePath[1024]; - PWCHAR ModuleName; - /* Open EFI volume */ - Status = BlOpenVolume(NULL, &DiskHandle, &FsHandle); - if(Status != STATUS_EFI_SUCCESS) + /* Set current XTLDR's EFI BootServices status */ + BlpStatus.BootServices = TRUE; + + /* Initialize console */ + BlInitializeConsole(); + + /* Print XTLDR version */ + BlConsolePrint(L"XTLDR boot loader v%s\n", XTOS_VERSION); + + /* Initialize XTLDR configuration linked lists */ + RtlInitializeListHead(&BlpBootProtocols); + RtlInitializeListHead(&BlpConfig); + RtlInitializeListHead(&BlpLoadedModules); + + /* Store SecureBoot status */ + BlpStatus.SecureBoot = BlGetSecureBootStatus(); + + /* Check if debug is enabled */ + if(DEBUG) { - /* Failed to open a volume */ - return Status; + /* Attempt to open EFI LoadedImage protocol */ + Status = BlOpenProtocol(&Handle, (PVOID *)&LoadedImage, &LipGuid); + if(Status == STATUS_EFI_SUCCESS) + { + /* Protocol opened successfully, print useful debug information */ + BlConsolePrint(L"\n---------- BOOTLOADER DEBUG ----------\n" + L"Pointer Size : %d\n" + L"Image Base Address: 0x%lx\n" + L"Image Base Size : 0x%lx\n" + L"Image Revision : 0x%lx\n" + L"--------------------------------------\n", + sizeof(PVOID), + LoadedImage->ImageBase, + LoadedImage->ImageSize, + LoadedImage->Revision); + BlSleepExecution(3000); + } } - - /* Open EFI/BOOT/XTLDR directory, which contains all the modules and close the FS immediately */ - Status = FsHandle->Open(FsHandle, &ModulesDir, ModulesDirPath, EFI_FILE_MODE_READ, 0); - FsHandle->Close(FsHandle); - - /* Check if modules directory opened successfully */ - if(Status == STATUS_EFI_NOT_FOUND) - { - /* Directory not found, nothing to load */ - BlDbgPrint(L"WARNING: Boot loader directory (EFI/BOOT/XTLDR) not found\n"); - - /* Close volume */ - BlCloseVolume(DiskHandle); - return STATUS_EFI_SUCCESS; - } - else if(Status != STATUS_EFI_SUCCESS) - { - /* Failed to open directory */ - BlDbgPrint(L"ERROR: Unable to open XTLDR directory (EFI/BOOT/XTLDR)\n"); - BlCloseVolume(DiskHandle); - return Status; - } - - /* Open EFI device path protocol */ - Status = EfiSystemTable->BootServices->HandleProtocol(DiskHandle, &DevicePathGuid, (PVOID *)&DevicePath); - if(Status != STATUS_EFI_SUCCESS) - { - /* Close volume */ - BlCloseVolume(DiskHandle); - return Status; - } - - /* Iterate through files inside XTLDR directory */ - while(TRUE) - { - /* Read directory */ - DirSize = sizeof(Buffer); - Status = ModulesDir->Read(ModulesDir, &DirSize, Buffer); - if(Status != STATUS_EFI_SUCCESS) - { - /* Failed to read directory */ - BlDbgPrint(L"\n"); - - /* Close directory and volume */ - ModulesDir->Close(ModulesDir); - BlCloseVolume(DiskHandle); - return Status; - } - - /* Check if read anything */ - if(DirSize == 0) - { - /* Already read all contents, break loop execution */ - break; - } - - /* Take filename and its length */ - ModuleName = ((PEFI_FILE_INFO)Buffer)->FileName; - Length = RtlWideStringLength(ModuleName, 0); - - /* Make sure we deal with .EFI executable file */ - if(Length < 4 || ModuleName[Length - 4] != '.' || - (ModuleName[Length - 3] != 'E' && ModuleName[Length - 3] != 'e') || - (ModuleName[Length - 2] != 'F' && ModuleName[Length - 2] != 'f') || - (ModuleName[Length - 1] != 'I' && ModuleName[Length - 1] != 'i')) - { - /* Skip non .EFI file */ - continue; - } - - /* Print debug message */ - BlDbgPrint(L"Loading module '%S' ... ", ModuleName); - - /* Set correct path to the module file */ - RtlCopyMemory(ModulePath, ModulesDirPath, sizeof(ModulePath) / sizeof(WCHAR)); - RtlConcatenateWideString(ModulePath, ModuleName, 0); - - /* Find valid device path */ - Status = BlFindVolumeDevicePath(DevicePath, ModulePath, &VolumeDevicePath); - if(Status != STATUS_EFI_SUCCESS) - { - /* Failed to set path */ - BlDbgPrint(L"FAIL\n"); - BlDbgPrint(L"ERROR: Unable to set valid device path\n"); - - /* Close directory and volume */ - ModulesDir->Close(ModulesDir); - BlCloseVolume(DiskHandle); - return Status; - } - - /* Load the module into memory */ - Status = EfiSystemTable->BootServices->LoadImage(FALSE, EfiImageHandle, VolumeDevicePath, - NULL, 0, &ModuleHandle); - if(Status != STATUS_EFI_SUCCESS) - { - /* Module failed */ - BlDbgPrint(L"FAIL\n"); - - /* Check if caused by secure boot */ - if(Status == STATUS_EFI_ACCESS_DENIED && EfiSecureBoot >= 1) - { - BlDbgPrint(L"ERROR: SecureBoot signature validation failed\n"); - } - else - { - BlDbgPrint(L"ERROR: Unable to load module (Status code: %lx)\n", Status); - } - - /* Free memory and skip module */ - BlEfiMemoryFreePool(VolumeDevicePath); - continue; - } - - /* Free memory */ - BlEfiMemoryFreePool(VolumeDevicePath); - - /* Access module interface for further module type check */ - Status = EfiSystemTable->BootServices->OpenProtocol(ModuleHandle, &LIPGuid, (PVOID *)&LoadedImage, - EfiImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); - if(Status != STATUS_EFI_SUCCESS) - { - /* Failed to open protocol */ - BlDbgPrint(L"FAIL\n"); - BlDbgPrint(L"ERROR: Unable to access module interface\n"); - - /* Skip to the next module */ - continue; - } - - /* Some firmwares do not allow to start drivers which are not of 'boot system driver' type, so check it */ - if(LoadedImage->ImageCodeType != EfiBootServicesCode) - { - /* Different type set, probably 'runtime driver', refuse to load it */ - BlDbgPrint(L"FAIL\n"); - BlDbgPrint(L"ERROR: Loaded module is not a boot system driver\n"); - - /* Close protocol and skip module */ - EfiSystemTable->BootServices->CloseProtocol(LoadedImage, &LIPGuid, LoadedImage, NULL); - continue; - } - - /* Close loaded image protocol */ - EfiSystemTable->BootServices->CloseProtocol(LoadedImage, &LIPGuid, LoadedImage, NULL); - - /* Start the module */ - Status = EfiSystemTable->BootServices->StartImage(ModuleHandle, NULL, NULL); - if(Status != STATUS_EFI_SUCCESS) - { - /* Module failed */ - BlDbgPrint(L"FAIL\n"); - BlDbgPrint(L"ERROR: Unable to start module\n"); - - /* Skip module */ - continue; - } - - /* Module loaded successfully */ - BlDbgPrint(L"OK\n"); - } - - /* Close directory and volume */ - ModulesDir->Close(ModulesDir); - BlCloseVolume(DiskHandle); - - /* Return success */ - return STATUS_EFI_SUCCESS; } /** - * This routine attempts to start XT Operating System. + * Initializes a list of operating systems for XTLDR boot menu. + * + * @param MenuEntries + * Supplies a pointer to memory area where operating systems list will be stored. + * + * @param EntriesCount + * Supplies a pointer to memory area where number of menu entries will be stored. + * + * @param DefaultId + * Supplies a pointer to memory area where ID of default menu entry will be stored. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlInitializeBootMenuList(OUT PXTBL_BOOTMENU_ITEM MenuEntries, + OUT PULONG EntriesCount, + OUT PULONG DefaultId) +{ + PWCHAR DefaultMenuEntry, MenuEntryName; + PLIST_ENTRY MenuEntrySectionList, MenuEntryList; + PXTBL_CONFIG_SECTION MenuEntrySection; + PXTBL_CONFIG_ENTRY MenuEntryOption; + PXTBL_BOOTMENU_ITEM OsList; + ULONG DefaultOS, NumberOfEntries; + + /* Set default values */ + DefaultOS = 0; + NumberOfEntries = 0; + OsList = NULL; + + /* Get default menu entry from configuration */ + DefaultMenuEntry = BlGetConfigValue(L"DEFAULT"); + + /* Iterate through all menu sections */ + MenuEntrySectionList = BlpMenuList->Flink; + while(MenuEntrySectionList != BlpMenuList) + { + /* NULLify menu entry name */ + MenuEntryName = NULL; + + /* Get menu section */ + MenuEntrySection = CONTAIN_RECORD(MenuEntrySectionList, XTBL_CONFIG_SECTION, Flink); + + /* Check if this is the default menu entry */ + if(RtlCompareWideStringInsensitive(MenuEntrySection->SectionName, DefaultMenuEntry, 0) == 0) + { + /* Set default OS ID */ + DefaultOS = NumberOfEntries; + } + + /* Iterate through all entry parameters */ + MenuEntryList = MenuEntrySection->Options.Flink; + while(MenuEntryList != &MenuEntrySection->Options) + { + /* Get menu entry parameter */ + MenuEntryOption = CONTAIN_RECORD(MenuEntryList, XTBL_CONFIG_ENTRY, Flink); + + /* Check if this is the menu entry display name */ + if(RtlCompareWideStringInsensitive(MenuEntryOption->Name, L"SYSTEMNAME", 0) == 0) + { + /* Set menu entry display name */ + MenuEntryName = MenuEntryOption->Value; + } + + /* Get next parameter for this menu entry */ + MenuEntryList = MenuEntryList->Flink; + } + + /* Add OS to the boot menu list */ + OsList[NumberOfEntries].EntryName = MenuEntryName; + OsList[NumberOfEntries].Options = &MenuEntrySection->Options; + + /* Get next menu entry */ + MenuEntrySectionList = MenuEntrySectionList->Flink; + NumberOfEntries++; + } + + /* Set return values */ + *DefaultId = DefaultOS; + *EntriesCount = NumberOfEntries; + MenuEntries = OsList; +} + +/** + * Loads all necessary modules and invokes boot protocol. + * + * @param OptionsList + * Supplies a pointer to list of options associated with chosen boot menu entry. * * @return This routine returns a status code. * @@ -219,90 +164,118 @@ BlLoadEfiModules() */ XTCDECL EFI_STATUS -BlLoadXtSystem() +BlInvokeBootProtocol(IN PLIST_ENTRY OptionsList) { - EFI_GUID ProtocolGuid = XT_XTOS_BOOT_PROTOCOL_GUID; - XT_BOOT_PROTOCOL_PARAMETERS BootParameters; - PXT_BOOT_PROTOCOL BootProtocol; - PUCHAR ArcName, SystemPath; + XTBL_BOOT_PARAMETERS BootParameters; + PXTBL_BOOT_PROTOCOL BootProtocol; + PLIST_ENTRY OptionsListEntry; + PXTBL_CONFIG_ENTRY Option; + EFI_GUID BootProtocolGuid; + SIZE_T ModuleListLength; + PWCHAR ModulesList; + EFI_HANDLE Handle; EFI_STATUS Status; - PCHAR ArcPath; - SIZE_T Length; - /* Set ARC path */ - ArcPath = "multi(0)disk(0)rdisk(0)partition(1)/ExectOS"; + /* Initialize boot parameters and a list of modules */ + RtlZeroMemory(&BootParameters, sizeof(XTBL_BOOT_PARAMETERS)); + ModulesList = NULL; - /* Zero boot parameters structure to NULLify all pointers */ - RtlZeroMemory(&BootParameters, sizeof(XT_BOOT_PROTOCOL_PARAMETERS)); - - /* Get boot volume path */ - Status = BlGetVolumeDevicePath((PUCHAR)ArcPath, &BootParameters.DevicePath, &ArcName, &SystemPath); - if(Status != STATUS_EFI_SUCCESS) + /* Iterate through all options provided by boot menu entry and propagate boot parameters */ + OptionsListEntry = OptionsList->Flink; + while(OptionsListEntry != OptionsList) { - /* Failed to find volume */ - BlDbgPrint(L"ERROR: Unable to find volume device path\n"); - return Status; + /* Get option */ + Option = CONTAIN_RECORD(OptionsListEntry, XTBL_CONFIG_ENTRY, Flink); + + /* Look for boot protocol and modules list */ + if(RtlCompareWideStringInsensitive(Option->Name, L"BOOTMODULES", 0) == 0) + { + /* Check a length of modules list */ + ModuleListLength = RtlWideStringLength(Option->Value, 0); + + Status = BlMemoryAllocatePool(sizeof(PWCHAR) * ModuleListLength, (PVOID *)&ModulesList); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to allocate memory, print error message and return status code */ + BlDebugPrint(L"ERROR: Memory allocation failure (Status Code: 0x%lx)\n", Status); + return STATUS_EFI_OUT_OF_RESOURCES; + } + + /* Make a copy of modules list */ + RtlCopyMemory(ModulesList, Option->Value, sizeof(PWCHAR) * ModuleListLength); + } + else if(RtlCompareWideStringInsensitive(Option->Name, L"SYSTEMTYPE", 0) == 0) + { + /* Boot protocol found */ + BootParameters.SystemType = Option->Value; + } + else if(RtlCompareWideStringInsensitive(Option->Name, L"SYSTEMPATH", 0) == 0) + { + /* System path found, get volume device path */ + Status = BlGetVolumeDevicePath((PWCHAR)Option->Value, &BootParameters.DevicePath, &BootParameters.ArcName, &BootParameters.SystemPath); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to find volume */ + BlDebugPrint(L"ERROR: Failed to find volume device path (Status Code: 0x%lx)\n", Status); + return Status; + } + } + else if(RtlCompareWideStringInsensitive(Option->Name, L"KERNELFILE", 0) == 0) + { + /* Kernel file name found */ + BootParameters.KernelFile = Option->Value; + } + else if(RtlCompareWideStringInsensitive(Option->Name, L"INITRDFILE", 0) == 0) + { + /* Initrd file name found */ + BootParameters.InitrdFile = Option->Value; + } + else if(RtlCompareWideStringInsensitive(Option->Name, L"HALFILE", 0) == 0) + { + /* Hal file name found */ + BootParameters.HalFile = Option->Value; + } + else if(RtlCompareWideStringInsensitive(Option->Name, L"PARAMETERS", 0) == 0) + { + /* Kernel parameters found */ + BootParameters.Parameters = Option->Value; + } + + /* Move to the next option entry */ + OptionsListEntry = OptionsListEntry->Flink; } - /* Store ARC name in boot parameters */ - Length = RtlStringLength(ArcName, 0); - BlEfiMemoryAllocatePool(Length + 1, (PVOID *)&BootParameters.ArcName); - RtlStringToWideString(BootParameters.ArcName, &ArcName, Length * 2); + /* Load all necessary modules */ + Status = BlLoadModules(ModulesList); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to load modules, print error message and return status code */ + BlDebugPrint(L"ERROR: Failed to load XTLDR modules (Status Code: 0x%lx)\n", Status); + return STATUS_EFI_NOT_READY; + } - /* Store system path in boot parameters */ - Length = RtlStringLength(SystemPath, 0); - BlEfiMemoryAllocatePool(Length + 1, (PVOID *)&BootParameters.SystemPath); - RtlStringToWideString(BootParameters.SystemPath, &SystemPath, Length + 1); + /* Attempt to get boot protocol GUID */ + Status = BlFindBootProtocol(BootParameters.SystemType, &BootProtocolGuid); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to get boot protocol GUID */ + BlDebugPrint(L"ERROR: Unable to find appropriate boot protocol (Status Code: 0x%lx)\n", Status); + return STATUS_EFI_UNSUPPORTED; + } - /* Open the XT boot protocol */ - Status = BlLoadXtProtocol((PVOID *)&BootProtocol, &ProtocolGuid); + /* Open boot protocol */ + Status = BlOpenProtocol(&Handle, (PVOID *)&BootProtocol, &BootProtocolGuid); if(Status != STATUS_EFI_SUCCESS) { /* Failed to open boot protocol */ - BlDbgPrint(L"ERROR: Unable to load boot protocol\n"); - return STATUS_EFI_PROTOCOL_ERROR; + BlDebugPrint(L"ERROR: Failed to open boot protocol (Status Code: 0x%lx)\n", Status); + return Status; } - /* Boot operating system */ + /* Boot Operating System */ return BootProtocol->BootSystem(&BootParameters); } -/** - * This routine registers XTLDR protocol for further usage by modules. - * - * @return This routine returns status code. - * - * @since XT 1.0 - */ -XTCDECL -EFI_STATUS -BlRegisterXtLoaderProtocol() -{ - EFI_GUID Guid = XT_BOOT_LOADER_PROTOCOL_GUID; - EFI_HANDLE Handle = NULL; - - /* Set all routines available via loader protocol */ - EfiLdrProtocol.AddVirtualMemoryMapping = BlAddVirtualMemoryMapping; - EfiLdrProtocol.AllocatePages = BlEfiMemoryAllocatePages; - EfiLdrProtocol.AllocatePool = BlEfiMemoryAllocatePool; - EfiLdrProtocol.FreePages = BlEfiMemoryFreePages; - EfiLdrProtocol.FreePool = BlEfiMemoryFreePool; - EfiLdrProtocol.EnablePaging = BlEnablePaging; - EfiLdrProtocol.GetMemoryMap = BlGetMemoryMap; - EfiLdrProtocol.GetVirtualAddress = BlGetVirtualAddress; - EfiLdrProtocol.InitializeVirtualMemory = BlInitializeVirtualMemory; - EfiLdrProtocol.MapVirtualMemory = BlMapVirtualMemory; - EfiLdrProtocol.DbgPrint = BlDbgPrint; - EfiLdrProtocol.EfiPrint = BlEfiPrint; - EfiLdrProtocol.CloseVolume = BlCloseVolume; - EfiLdrProtocol.OpenVolume = BlOpenVolume; - - /* Register loader protocol */ - BlDbgPrint(L"Registering XT loader protocol\n"); - return EfiSystemTable->BootServices->InstallProtocolInterface(&Handle, &Guid, EFI_NATIVE_INTERFACE, - &EfiLdrProtocol); -} - /** * This routine is the entry point of the XT EFI boot loader. * @@ -327,71 +300,101 @@ BlStartXtLoader(IN EFI_HANDLE ImageHandle, EfiImageHandle = ImageHandle; EfiSystemTable = SystemTable; - /* Initialize EFI console */ - BlConsoleInitialize(); - BlEfiPrint(L"XTLDR boot loader v%s\n", XTOS_VERSION); + /* Initialize XTLDR and */ + BlInitializeBootLoader(); - /* Early initialize COM port for debugging */ + /* Parse configuration options passed from UEFI shell */ + Status = BlpParseCommandLine(); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to parse command line options */ + BlDisplayErrorDialog(L"XTLDR", L"Failed to parse command line parameters."); + } + + /* Attempt to early initialize debug console */ if(DEBUG) { - Status = BlComPortInitialize(); + Status = BlpInitializeDebugConsole(); if(Status != STATUS_EFI_SUCCESS) { - /* Initialization failed, try printing error to stdout and serial console */ - BlEfiPrint(L"ERROR: Failed to initialize serial console\n"); + /* Initialization failed, notify user on stdout */ + BlDisplayErrorDialog(L"XTLDR", L"Failed to initialize debug console."); } } - /* Check SecureBoot status */ - EfiSecureBoot = BlEfiGetSecureBootStatus(); + /* Load XTLDR configuration file */ + Status = BlpLoadConfiguration(); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to load/parse config file */ + BlDisplayErrorDialog(L"XTLDR", L"Failed to load and parse configuration file "); + } - /* Print firmware information */ - BlDbgPrint(L"UEFI v%d.%d (%S 0x%08x), SecureBoot %S\n", EfiSystemTable->Hdr.Revision >> 16, - EfiSystemTable->Hdr.Revision & 0xFFFF, EfiSystemTable->FirmwareVendor, EfiSystemTable->FirmwareRevision, - EfiSecureBoot == 0 ? L"DISABLED" : EfiSecureBoot > 0 ? L"ENABLED" : L"SETUP"); + /* Reinitialize debug console if it was not initialized earlier */ + if(DEBUG) + { + Status = BlpInitializeDebugConsole(); + if(Status != STATUS_EFI_SUCCESS) + { + /* Initialization failed, notify user on stdout */ + BlDisplayErrorDialog(L"XTLDR", L"Failed to initialize debug console."); + } + } /* Disable watchdog timer */ Status = EfiSystemTable->BootServices->SetWatchdogTimer(0, 0x10000, 0, NULL); if(Status != STATUS_EFI_SUCCESS) { /* Failed to disable the timer, print message */ - BlDbgPrint(L"WARNING: Failed to disable watchdog timer\n"); + BlDebugPrint(L"WARNING: Failed to disable watchdog timer (Status Code: 0x%lx)\n", Status); } - /* Register loader protocol */ - Status = BlRegisterXtLoaderProtocol(); + /* Install loader protocol */ + Status = BlpInstallXtLoaderProtocol(); if(Status != STATUS_EFI_SUCCESS) { /* Failed to register loader protocol */ - BlDbgPrint(L"ERROR: Failed to register XTLDR loader protocol\n"); + BlDebugPrint(L"ERROR: Failed to register XTLDR loader protocol (Status Code: 0x%lx)\n", Status); + return Status; } - /* Load XTLDR modules */ - Status = BlLoadEfiModules(); + /* Load boot loader modules */ + Status = BlLoadModules(BlGetConfigValue(L"MODULES")); if(Status != STATUS_EFI_SUCCESS) { - BlDbgPrint(L"ERROR: Failed to load XTLDR modules\n"); + /* Failed to load modules */ + BlDebugPrint(L"ERROR: Failed to load XTLDR modules (Status Code: 0x%lx)\n", Status); + BlDisplayErrorDialog(L"XTLDR", L"Failed to load some XTLDR modules."); } /* Discover and enumerate EFI block devices */ - BlEnumerateEfiBlockDevices(); - - /* Boot XTOS */ - Status = BlLoadXtSystem(); + Status = BlEnumerateBlockDevices(); if(Status != STATUS_EFI_SUCCESS) { - /* Boot process failed */ - BlEfiPrint(L"Failed to start XT OS (Status code: %lx)!\n", Status); + /* Failed to enumerate block devices */ + BlDebugPrint(L"ERROR: Failed to discover and enumerate block devices (Status Code: 0x%lx)\n", Status); + return Status; } - /* Infinite bootloader loop */ - BlEfiPrint(L"System halted!"); - for(;;) + /* Main boot loader loop */ + while(TRUE) { - ArClearInterruptFlag(); - ArHalt(); + /* Check if custom boot menu registered */ + if(BlpStatus.BootMenu != NULL) + { + /* Display alternative boot menu */ + BlpStatus.BootMenu(); + } + else + { + /* Display default boot menu */ + BlDisplayBootMenu(); + } + + /* Fallback to shell, if boot menu returned */ + BlStartLoaderShell(); } - /* Return success */ - return STATUS_EFI_SUCCESS; + /* This point should be never reached, if this happen return error code */ + return STATUS_EFI_LOAD_ERROR; }