Rewrite core of the XTLDR boot loader

Reviewed-on: xt-sys/exectos#7
Reviewed-by: Piotr Likoski <likoski@noreply.codingworkshop.git>
Co-authored-by: Rafal Kupiec <belliash@codingworkshop.eu.org>
Co-committed-by: Rafal Kupiec <belliash@codingworkshop.eu.org>
This commit is contained in:
Rafal Kupiec 2024-01-09 18:51:04 +01:00 committed by CodingWorkshop Signing Team
parent 44905bb71d
commit 4412d4fc98
Signed by: CodingWorkshop Signing Team
GPG Key ID: 6DC88369C82795D2
63 changed files with 6282 additions and 2371 deletions

View File

@ -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.

View File

@ -1 +1 @@
set_install_file(xtldr.ini efi/boot)
set_install_file(xtldr.ini efi/boot/xtldr)

View File

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

View File

@ -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")

View File

@ -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 */

23
sdk/xtdk/blfuncs.h Normal file
View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#ifndef __XTDK_BLFUNCS_H
#define __XTDK_BLFUNCS_H
#include <xttypes.h>
#include <xtuefi.h>
/* 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 */

289
sdk/xtdk/bltypes.h Normal file
View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#ifndef __XTDK_BLTYPES_H
#define __XTDK_BLTYPES_H
#include <xttypes.h>
#include <xtuefi.h>
#include <hltypes.h>
/* 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 */

50
sdk/xtdk/xtblapi.h Normal file
View File

@ -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 <belliash@codingworkshop.eu.org>
*/
/* Base XT headers */
#include <xtdefs.h>
#include <xtstatus.h>
#include <xttarget.h>
#include <xttypes.h>
/* XT forward references */
#include <xtstruct.h>
/* Architecture-specific XT forward references */
#include ARCH_HEADER(xtstruct.h)
/* Architecture-independent XT API */
#include <xtbase.h>
#include <xtfw.h>
#include <xtimage.h>
#include <xtuefi.h>
#include <xtdebug.h>
#include <xtguid.h>
/* Architecture independent XT kernel data types */
#include <hltypes.h>
#include <iotypes.h>
#include <rtltypes.h>
/* 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 <hlfuncs.h>
#include <rtlfuncs.h>
/* Architecture specific XT kernel routines */
#include ARCH_HEADER(arfuncs.h)
#include ARCH_HEADER(hlfuncs.h)
/* Boot Manager specific structures */
#include <bltypes.h>
#include <blfuncs.h>

View File

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

View File

@ -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)

View File

@ -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.

View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#include <xtbl.h>
#include <blproto.h>
/**
* 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;
}

595
xtldr/config.c Normal file
View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#include <xtldr.h>
/**
* 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;
}
}

View File

@ -6,9 +6,37 @@
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include <xtbl.h>
#include <xtldr.h>
/**
* 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 devices 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];

263
xtldr/debug.c Normal file
View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#include <xtldr.h>
/**
* 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]);
}

View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#include <xtbl.h>
/**
* 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);
}

120
xtldr/efiutils.c Normal file
View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#include <xtldr.h>
/**
* 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);
}

View File

@ -6,26 +6,38 @@
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include <xtbl.h>
#include <xtldr.h>
/* 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;

112
xtldr/hardware.c Normal file
View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#include <xtldr.h>
/**
* 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;
}

View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#ifndef __XTLDR_BLDEFS_H
#define __XTLDR_BLDEFS_H
#include <xtkmapi.h>
/* 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 */

View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#ifndef __XTLDR_BLMOD_H
#define __XTLDR_BLMOD_H
#include <xtkmapi.h>
#include <bldefs.h>
#include <blproto.h>
/* 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 */

View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#ifndef __XTLDR_BLPROTO_H
#define __XTLDR_BLPROTO_H
#include <xtkmapi.h>
#include <bldefs.h>
/* 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 */

48
xtldr/includes/globals.h Normal file
View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#ifndef __XTLDR_GLOBALS_H
#define __XTLDR_GLOBALS_H
#include <xtblapi.h>
/* 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 */

View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#ifndef __XTLDR_XTBL_H
#define __XTLDR_XTBL_H
#include <xtkmapi.h>
#include <xtver.h>
#include <blmod.h>
/* 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 */

422
xtldr/includes/xtldr.h Normal file
View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#ifndef __XTLDR_XTLDR_H
#define __XTLDR_XTLDR_H
#include <xtblapi.h>
#include <xtver.h>
#include <globals.h>
/* 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 */

80
xtldr/library/modproto.c Normal file
View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#include <xtldr.h>
/**
* 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;
}

View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#include <xtbl.h>
#include <xtldr.h>
/**
* 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);
}

View File

@ -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)

View File

@ -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)

209
xtldr/modules/beep/beep.c Normal file
View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#include <beep.h>
/* 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;
}

View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#include <xtblapi.h>
/* XTLDR protocol handler */
PXTBL_LOADER_PROTOCOL XtLdrProto;

View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#ifndef __XTLDR_BEEP_BEEP_H
#define __XTLDR_BEEP_BEEP_H
#include <xtblapi.h>
#include <globals.h>
/* 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 */

View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#ifndef __XTLDR_BEEP_GLOBALS_H
#define __XTLDR_BEEP_GLOBALS_H
#include <beep.h>
/* XTLDR protocol handler */
EXTERN PXTBL_LOADER_PROTOCOL XtLdrProto;
#endif/* __XTLDR_BEEP_GLOBALS_H */

View File

@ -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)

View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#include <dummy.h>
/* 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);
}

View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#include <dummy.h>
/* XTLDR protocol handler */
PXTBL_LOADER_PROTOCOL XtLdrProto;
/* Dummy Boot Protocol handler */
XTBL_BOOT_PROTOCOL BlpDummyProtocol;

View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#ifndef __XTLDR_DUMMY_DUMMY_H
#define __XTLDR_DUMMY_DUMMY_H
#include <xtblapi.h>
#include <globals.h>
/* 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 */

View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#ifndef __XTLDR_DUMMY_GLOBALS_H
#define __XTLDR_DUMMY_GLOBALS_H
#include <dummy.h>
/* XTLDR protocol handler */
EXTERN PXTBL_LOADER_PROTOCOL XtLdrProto;
/* Dummy Boot Protocol handler */
EXTERN XTBL_BOOT_PROTOCOL BlpDummyProtocol;
#endif/* __XTLDR_DUMMY_GLOBALS_H */

View File

@ -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)

View File

@ -9,14 +9,11 @@
#include <framebuf.h>
/* 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);
}

View File

@ -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 <belliash@codingworkshop.eu.org>
*/

View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#ifndef __XTLDR_MODULES_FRAMEBUF_H
#define __XTLDR_MODULES_FRAMEBUF_H
#include <xtblapi.h>
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 */

View File

@ -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)

View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#ifndef __XTLDR_MODULES_FRAMEBUF_H
#define __XTLDR_MODULES_FRAMEBUF_H
#include <blmod.h>
/* 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 */

View File

@ -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)

View File

@ -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)

View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#ifndef __XTLDR_MODULES_PECOFF_H
#define __XTLDR_MODULES_PECOFF_H
#ifndef __XTLDR_MODULES_PECOFF_O_H
#define __XTLDR_MODULES_PECOFF_O_H
#include <blmod.h>
#include <xtblapi.h>
/* 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 */

View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#include <pecoff.h>
/* 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);
}

View File

@ -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)

View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#ifndef __XTLDR_MODULES_XTOS_H
#define __XTLDR_MODULES_XTOS_H
#include <blmod.h>
/* 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 */

View File

@ -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)

View File

@ -6,7 +6,7 @@
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include <xtbl.h>
#include <xtos.h>
/**
@ -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;

View File

@ -6,7 +6,7 @@
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include <xtbl.h>
#include <xtos.h>
/**
@ -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;

View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#ifndef __XTLDR_MODULES_XTOS_H
#define __XTLDR_MODULES_XTOS_H
#include <xtblapi.h>
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 */

View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#include <xtos.h>
/**
* 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;
}

View File

@ -9,20 +9,18 @@
#include <xtos.h>
/* 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);
}

601
xtldr/protocol.c Normal file
View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#include <xtldr.h>
/**
* 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);
}

50
xtldr/shell.c Normal file
View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#include <xtldr.h>
/**
* 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);
}

View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#include <xtbl.h>
#include <xtldr.h>
/**
* 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);
}
}

View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#include <xtbl.h>
/**
* 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;
}

1288
xtldr/textui.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include <xtbl.h>
#include <xtldr.h>
/**
@ -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;

View File

@ -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 <belliash@codingworkshop.eu.org>
*/
#include <xtbl.h>
#include <xtldr.h>
/**
* 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;
}