From 5131a682b87b579553fcc278d6b0df73a5546c17 Mon Sep 17 00:00:00 2001 From: Rafal Kupiec Date: Sun, 3 Dec 2023 23:18:49 +0100 Subject: [PATCH] Refactor part 5; Implement debugging ports --- xtldr2/CMakeLists.txt | 2 + xtldr2/console.c | 53 +++++--- xtldr2/debug.c | 260 ++++++++++++++++++++++++++++++++++++++ xtldr2/efiutils.c | 27 ++++ xtldr2/hardware.c | 2 +- xtldr2/includes/bootman.h | 61 ++++++--- xtldr2/xtldr.c | 17 ++- 7 files changed, 381 insertions(+), 41 deletions(-) create mode 100644 xtldr2/debug.c create mode 100644 xtldr2/efiutils.c diff --git a/xtldr2/CMakeLists.txt b/xtldr2/CMakeLists.txt index 198e406..465b1c7 100644 --- a/xtldr2/CMakeLists.txt +++ b/xtldr2/CMakeLists.txt @@ -10,6 +10,8 @@ include_directories( list(APPEND XTLDR_SOURCE ${XTLDR_SOURCE_DIR}/config.c ${XTLDR_SOURCE_DIR}/console.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 diff --git a/xtldr2/console.c b/xtldr2/console.c index b4d7388..c0911c9 100644 --- a/xtldr2/console.c +++ b/xtldr2/console.c @@ -52,27 +52,6 @@ BlConsoleEnableCursor() EfiSystemTable->ConOut->EnableCursor(EfiSystemTable->ConOut, TRUE); } -/** - * This routine initializes the EFI console. - * - * @return This routine returns status code. - * - * @since XT 1.0 - */ -XTCDECL -VOID -BlConsoleInitialize() -{ - /* Clear console buffers */ - EfiSystemTable->ConIn->Reset(EfiSystemTable->ConIn, TRUE); - EfiSystemTable->ConOut->Reset(EfiSystemTable->ConOut, TRUE); - EfiSystemTable->StdErr->Reset(EfiSystemTable->StdErr, TRUE); - - /* Clear screen and enable cursor */ - BlConsoleClearScreen(); - BlConsoleEnableCursor(); -} - /** * This routine formats the input string and prints it out to the stdout and serial console. * @@ -99,10 +78,42 @@ BlConsolePrint(IN PUINT16 Format, /* Format and print the string to the stdout */ BlpStringPrint(BlpConsolePrintChar, Format, Arguments); + /* Print to serial console only if not running under OVMF */ + if(RtlWideStringCompare(EfiSystemTable->FirmwareVendor, L"EDK II", 6) != 0) + { + /* Check if debugging enabled and if EFI serial port is fully initialized */ + if(DEBUG && (BlpSerialPort.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); } +/** + * This routine initializes the EFI console. + * + * @return This routine returns status code. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlpConsoleInitialize() +{ + /* Clear console buffers */ + EfiSystemTable->ConIn->Reset(EfiSystemTable->ConIn, TRUE); + EfiSystemTable->ConOut->Reset(EfiSystemTable->ConOut, TRUE); + EfiSystemTable->StdErr->Reset(EfiSystemTable->StdErr, TRUE); + + /* Clear screen and enable cursor */ + BlConsoleClearScreen(); + BlConsoleEnableCursor(); +} + /** * Writes a character to the default EFI console. * diff --git a/xtldr2/debug.c b/xtldr2/debug.c new file mode 100644 index 0000000..dcfddc5 --- /dev/null +++ b/xtldr2/debug.c @@ -0,0 +1,260 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/debug.c + * DESCRIPTION: XT Boot Loader debugging support + * DEVELOPERS: Rafal Kupiec + */ + +#include + + +/** + * This routine formats the input string and prints it out to the debug ports. + * + * @param Format + * The formatted string that is to be written to the output. + * + * @param ... + * Depending on the format string, this routine might expect a sequence of additional arguments. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlDebugPrint(IN PUINT16 Format, + IN ...) +{ + VA_LIST Arguments; + + /* Check if debugging enabled and if EFI serial port is fully initialized */ + if(DEBUG) + { + /* Initialise the va_list */ + VA_START(Arguments, Format); + + /* Check if serial debug port is enabled */ + if((BlpConfiguration.DebugPort & XTBL_DEBUGPORT_SERIAL) && (BlpSerialPort.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((BlpConfiguration.DebugPort & XTBL_DEBUGPORT_SCREEN) && (EfiSystemTable->BootServices != 0)) + { + /* Format and print the string to the screen */ + BlpStringPrint(BlpConsolePrintChar, Format, Arguments); + } + + /* Clean up the va_list */ + VA_END(Arguments); + } +} + +/** + * 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 +BlpDebugInitializeComPort(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(&BlpSerialPort, 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(&BlpSerialPort, 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; +} + +/** + * This routine initializes the XTLDR debug console. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlpDebugInitializeConsole() +{ + ULONG PortAddress, PortNumber, BaudRate; + PWCHAR DebugPort, LastPort; + EFI_STATUS Status; + + /* Set default serial port options */ + PortAddress = 0; + PortNumber = 0; + BaudRate = 0; + + /* Make sure any debug options are provided */ + if(BlpConfiguration.Debug) + { + /* Find all debug ports */ + DebugPort = RtlWideStringTokenize(BlpConfiguration.Debug, L";", &LastPort); + + /* Iterate over all debug ports */ + while(DebugPort != NULL) + { + /* Check what port is set for debugging */ + if(RtlWideStringCompare(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 && RtlWideStringCompare(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 */ + BlpConfiguration.DebugPort |= XTBL_DEBUGPORT_SERIAL; + } + else if(RtlWideStringCompare(DebugPort, L"SCREEN", 5) == 0) + { + /* Enable debug port */ + BlpConfiguration.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 = RtlWideStringTokenize(NULL, L";", &LastPort); + } + } + + /* Check if serial debug port is enabled */ + if(BlpConfiguration.DebugPort & XTBL_DEBUGPORT_SERIAL) + { + /* Try to initialize COM port */ + Status = BlpDebugInitializeComPort(PortNumber, PortAddress, BaudRate); + if(Status != STATUS_EFI_SUCCESS) + { + /* Remove serial debug port, as COM port initialization failed and return */ + BlpConfiguration.DebugPort &= ~XTBL_DEBUGPORT_SERIAL; + return Status; + } + } + + /* 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(&BlpSerialPort, Buffer[0]); +} diff --git a/xtldr2/efiutils.c b/xtldr2/efiutils.c new file mode 100644 index 0000000..3cded88 --- /dev/null +++ b/xtldr2/efiutils.c @@ -0,0 +1,27 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/efiutils.c + * DESCRIPTION: EFI related routines for XT Boot Loader + * DEVELOPERS: Rafal Kupiec + */ + +#include + + +/** + * 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); +} diff --git a/xtldr2/hardware.c b/xtldr2/hardware.c index 9824cc2..4b6e6b7 100644 --- a/xtldr2/hardware.c +++ b/xtldr2/hardware.c @@ -18,7 +18,7 @@ */ XTCDECL EFI_STATUS -BlpHwActivateSerialIOController() +BlpActivateSerialIOController() { EFI_GUID PciGuid = EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID; PEFI_PCI_ROOT_BRIDGE_IO_PROTOCOL PciDev; diff --git a/xtldr2/includes/bootman.h b/xtldr2/includes/bootman.h index 73abcb5..3a310ae 100644 --- a/xtldr2/includes/bootman.h +++ b/xtldr2/includes/bootman.h @@ -15,17 +15,17 @@ /* XTLDR routine callbacks */ typedef VOID (BMPRINTCHAR)(IN USHORT Character); +/* XTLDR routines forward references */ XTCDECL EFI_STATUS BlMemoryAllocatePages(IN UINT64 Pages, - OUT PEFI_PHYSICAL_ADDRESS Memory); + OUT PEFI_PHYSICAL_ADDRESS Memory); XTCDECL EFI_STATUS BlMemoryAllocatePool(IN UINT_PTR Size, - OUT PVOID *Memory); + OUT PVOID *Memory); -/* XTLDR routines forward references */ XTCDECL VOID BlConsoleClearScreen(); @@ -38,40 +38,67 @@ XTCDECL VOID BlConsoleEnableCursor(); +XTCDECL +VOID +BlConsolePrint(IN PUINT16 Format, + IN ...); + +XTCDECL +VOID +BlDebugPrint(IN PUINT16 Format, + IN ...); + XTCDECL EFI_STATUS BlMemoreFreePages(IN UINT64 Pages, - IN EFI_PHYSICAL_ADDRESS Memory); + IN EFI_PHYSICAL_ADDRESS Memory); XTCDECL EFI_STATUS BlMemoryFreePool(IN PVOID Memory); +XTCDECL +VOID +BlSleepExecution(IN ULONG_PTR Milliseconds); + +XTCDECL +EFI_STATUS +BlStartXtLoader(IN EFI_HANDLE ImageHandle, + IN PEFI_SYSTEM_TABLE SystemTable); + +XTCDECL +EFI_STATUS +BlpActivateSerialIOController(); XTCDECL VOID -BlConsoleInitialize(); +BlpConfigParseCommandLine(VOID); XTCDECL VOID -BlConsolePrint(IN PUINT16 Format, - IN ...); +BlpConfigUpdateGlobalConfiguration(IN PWCHAR Options); + +XTCDECL +VOID +BlpConsoleInitialize(); XTCDECL VOID BlpConsolePrintChar(IN USHORT Character); XTCDECL -VOID -BlpStringPrint(IN IN BMPRINTCHAR PrintCharRoutine, - IN PUINT16 Format, - IN VA_LIST Arguments); +EFI_STATUS +BlpDebugInitializeComPort(IN ULONG PortNumber, + IN ULONG PortAddress, + IN ULONG BaudRate); XTCDECL EFI_STATUS -BmStartXtLoader(IN EFI_HANDLE ImageHandle, - IN PEFI_SYSTEM_TABLE SystemTable); +BlpDebugInitializeConsole(); +XTCDECL +VOID +BlpDebugPutChar(IN USHORT Character); XTCDECL VOID @@ -81,7 +108,9 @@ BlpStringFormat(IN BMPRINTCHAR PrintCharRoutine, XTCDECL VOID -BlpConfigParseCommandLine(VOID); +BlpStringPrint(IN IN BMPRINTCHAR PrintCharRoutine, + IN PUINT16 Format, + IN VA_LIST Arguments); XTCDECL VOID @@ -113,8 +142,4 @@ XTCDECL UINT64 BlpStringReadPadding(IN PUINT16 *Format); -XTCDECL -VOID -BlpConfigUpdateGlobalConfiguration(IN PWCHAR Options); - #endif /* __XTLDR_BOOTMAN_H */ diff --git a/xtldr2/xtldr.c b/xtldr2/xtldr.c index 9a8eeb5..dfa0a03 100644 --- a/xtldr2/xtldr.c +++ b/xtldr2/xtldr.c @@ -34,9 +34,24 @@ BlStartXtLoader(IN EFI_HANDLE ImageHandle, EfiSystemTable = SystemTable; /* Initialize UEFI console and early print XTLDR version */ - BlConsoleInitialize(); + BlpConsoleInitialize(); BlConsolePrint(L"XTLDR boot loader v%s\n", XTOS_VERSION); + /* Parse configuration options passed from UEFI shell */ + BlpConfigParseCommandLine(); + + /* Attempt to early initialize debug console */ + if(DEBUG) + { + Status = BlpDebugInitializeConsole(); + if(Status != STATUS_EFI_SUCCESS) + { + /* Initialization failed, notify user on stdout */ + BlConsolePrint(L"ERROR: Failed to initialize debug console\n"); + BlSleepExecution(3000); + } + } + /* Temporary infinite loop */ for(;;);