From 78ac03b0396795d3502a56c3764605b687da7c30 Mon Sep 17 00:00:00 2001 From: Rafal Kupiec Date: Sun, 3 Dec 2023 00:24:56 +0100 Subject: [PATCH] Add string manipulation support --- xtldr2/CMakeLists.txt | 1 + xtldr2/globals.c | 3 + xtldr2/includes/bootman.h | 86 ++++++++ xtldr2/includes/globals.h | 24 +++ xtldr2/includes/xtbm.h | 35 +-- xtldr2/string.c | 444 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 560 insertions(+), 33 deletions(-) create mode 100644 xtldr2/includes/bootman.h create mode 100644 xtldr2/includes/globals.h create mode 100644 xtldr2/string.c diff --git a/xtldr2/CMakeLists.txt b/xtldr2/CMakeLists.txt index 22258dd..43e1747 100644 --- a/xtldr2/CMakeLists.txt +++ b/xtldr2/CMakeLists.txt @@ -10,6 +10,7 @@ include_directories( list(APPEND XTLDR_SOURCE ${XTLDR_SOURCE_DIR}/console.c ${XTLDR_SOURCE_DIR}/globals.c + ${XTLDR_SOURCE_DIR}/string.c ${XTLDR_SOURCE_DIR}/xtldr.c) # Link static XTLDR library diff --git a/xtldr2/globals.c b/xtldr2/globals.c index dda53f5..10ba127 100644 --- a/xtldr2/globals.c +++ b/xtldr2/globals.c @@ -9,6 +9,9 @@ #include +/* XT Boot Loader hex table */ +STATIC PUINT16 BmpHexTable = L"0123456789ABCDEF"; + /* EFI Image Handle */ EFI_HANDLE EfiImageHandle; diff --git a/xtldr2/includes/bootman.h b/xtldr2/includes/bootman.h new file mode 100644 index 0000000..20c7cdf --- /dev/null +++ b/xtldr2/includes/bootman.h @@ -0,0 +1,86 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/includes/xtbm.h + * DESCRIPTION: XTLDR Boot Manager related structures and routines forward references + * DEVELOPERS: Rafal Kupiec + */ + +#ifndef __XTLDR_BOOTMAN_H +#define __XTLDR_BOOTMAN_H + +#include + + +/* XTLDR routine callbacks */ +typedef VOID (BMPRINTCHAR)(IN USHORT Character); + +/* XTLDR routines forward references */ +XTCDECL +VOID +BmClearScreen(); + +XTCDECL +VOID +BmDisableCursor(); + +XTCDECL +VOID +BmEnableCursor(); + +XTCDECL +VOID +BmInitializeConsole(); + +XTCDECL +VOID +BmPrintChar(IN USHORT Character); + +XTCDECL +VOID +BmPrintString(IN IN BMPRINTCHAR PrintCharRoutine, + IN PUINT16 Format, + IN VA_LIST Arguments); + +XTCDECL +EFI_STATUS +BmStartXtLoader(IN EFI_HANDLE ImageHandle, + IN PEFI_SYSTEM_TABLE SystemTable); + +XTCDECL +VOID +BmpFormatString(IN BMPRINTCHAR PrintCharRoutine, + IN PUINT16 Format, + IN ...); + +XTCDECL +VOID +BmpPrintSigned32String(IN BMPRINTCHAR PrintCharRoutine, + IN INT Number, + IN UINT Base); + +XTCDECL +VOID +BmpPrintSigned64String(IN BMPRINTCHAR PrintCharRoutine, + IN INT_PTR Number, + IN UINT_PTR Base); + +XTCDECL +VOID +BmpPrintUnsigned32String(IN BMPRINTCHAR PrintCharRoutine, + IN UINT Number, + IN UINT Base, + IN UINT Padding); + +XTCDECL +VOID +BmpPrintUnsigned64String(IN BMPRINTCHAR PrintCharRoutine, + IN UINT_PTR Number, + IN UINT_PTR Base, + IN UINT_PTR Padding); + +XTCDECL +UINT64 +BmpReadStringPadding(IN PUINT16 *Format); + +#endif /* __XTLDR_BOOTMAN_H */ diff --git a/xtldr2/includes/globals.h b/xtldr2/includes/globals.h new file mode 100644 index 0000000..ca7dcda --- /dev/null +++ b/xtldr2/includes/globals.h @@ -0,0 +1,24 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/includes/xtbm.h + * DESCRIPTION: XTLDR global variables + * DEVELOPERS: Rafal Kupiec + */ + +#ifndef __XTLDR_GLOBALS_H +#define __XTLDR_GLOBALS_H + +#include + + +/* XT Boot Loader hex table */ +EXTERN PUINT16 BmpHexTable; + +/* EFI Image Handle */ +EXTERN EFI_HANDLE EfiImageHandle; + +/* EFI System Table */ +EXTERN PEFI_SYSTEM_TABLE EfiSystemTable; + +#endif /* __XTLDR_GLOBALS_H */ diff --git a/xtldr2/includes/xtbm.h b/xtldr2/includes/xtbm.h index 53224d7..7a9c9d4 100644 --- a/xtldr2/includes/xtbm.h +++ b/xtldr2/includes/xtbm.h @@ -12,38 +12,7 @@ #include #include - -/* EFI Image Handle */ -EXTERN EFI_HANDLE EfiImageHandle; - -/* EFI System Table */ -EXTERN PEFI_SYSTEM_TABLE EfiSystemTable; - - -/* XTLDR routines forward references */ -XTCDECL -VOID -BmClearScreen(); - -XTCDECL -VOID -BmDisableCursor(); - -XTCDECL -VOID -BmEnableCursor(); - -XTCDECL -VOID -BmInitializeConsole(); - -XTCDECL -VOID -BmPrintChar(IN USHORT Character); - -XTCDECL -EFI_STATUS -BmStartXtLoader(IN EFI_HANDLE ImageHandle, - IN PEFI_SYSTEM_TABLE SystemTable); +#include +#include #endif /* __XTLDR_XTBM_H */ diff --git a/xtldr2/string.c b/xtldr2/string.c new file mode 100644 index 0000000..be812c5 --- /dev/null +++ b/xtldr2/string.c @@ -0,0 +1,444 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/string.c + * DESCRIPTION: EFI string manipulation support + * DEVELOPERS: Rafal Kupiec + */ + +#include + + +/** + * This routine formats the input string and prints it using specified routine. + * + * @param PrintCharRoutine + * Pointer to the routine that writes an input data to specific device. + * + * @param Format + * The formatted string that is to be written to the specified device. + * + * @param Arguments + * A value identifying a variable arguments list initialized with VA_START. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BmPrintString(IN IN BMPRINTCHAR PrintCharRoutine, + IN PUINT16 Format, + IN VA_LIST Arguments) +{ + PEFI_GUID Guid; + PUCHAR String; + PWCHAR WideString; + ULONG PaddingCount; + + /* Read the variable arguments */ + for(; *Format; ++Format) + { + switch(*Format) + { + case L'%': + switch(*++Format) + { + case L'b': + /* Boolean */ + BmpFormatString(PrintCharRoutine, L"%s", VA_ARG(Arguments, INT32) ? "TRUE" : "FALSE"); + break; + case L'c': + /* Character */ + PrintCharRoutine(VA_ARG(Arguments, INT)); + break; + case L'd': + /* Signed 32-bit integer */ + BmpPrintSigned32String(PrintCharRoutine, VA_ARG(Arguments, INT32), 10); + break; + case L'g': + /* EFI GUID */ + Guid = VA_ARG(Arguments, PEFI_GUID); + BmpFormatString(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; + case L'l': + /* 64-bit numbers */ + switch(*++Format) + { + case L'd': + /* Signed 64-bit integer */ + BmpPrintSigned64String(PrintCharRoutine, VA_ARG(Arguments, INT_PTR), 10); + break; + case L'u': + /* Unsigned 64-bit integer */ + BmpPrintUnsigned64String(PrintCharRoutine, VA_ARG(Arguments, UINT_PTR), 10, 0); + break; + case L'x': + /* Unsigned 64-bit hexadecimal integer */ + BmpPrintUnsigned64String(PrintCharRoutine, VA_ARG(Arguments, UINT_PTR), 16, 0); + break; + default: + /* Unknown by default */ + PrintCharRoutine(L'?'); + break; + } + break; + case L'p': + /* Pointer address */ + BmpPrintUnsigned64String(PrintCharRoutine, VA_ARG(Arguments, UINT_PTR), 16, 0); + break; + case L's': + /* String of characters */ + String = VA_ARG(Arguments, PUCHAR); + while(*String) + { + PrintCharRoutine(*String++); + } + break; + case L'S': + WideString = VA_ARG(Arguments, PWCHAR); + while(*WideString) + { + PrintCharRoutine((UCHAR)*WideString++); + } + break; + case L'u': + /* Unsigned 32-bit integer */ + BmpPrintUnsigned32String(PrintCharRoutine, VA_ARG(Arguments, UINT32), 10, 0); + break; + case L'x': + /* Unsigned 32-bit hexadecimal integer */ + BmpPrintUnsigned32String(PrintCharRoutine, VA_ARG(Arguments, UINT32), 16, 0); + break; + case L'0': + /* Zero padded numbers */ + ++Format; + PaddingCount = BmpReadStringPadding(&Format); + switch(*Format) + { + case L'd': + /* Zero-padded, signed 32-bit integer */ + BmpPrintSigned32String(PrintCharRoutine, VA_ARG(Arguments, INT32), 10); + break; + case L'l': + /* 64-bit numbers */ + switch(*++Format) + { + case L'd': + /* Zero-padded, signed 64-bit integer */ + BmpPrintSigned64String(PrintCharRoutine, VA_ARG(Arguments, INT_PTR), 10); + break; + case L'u': + /* Zero-padded, unsigned 64-bit integer */ + BmpPrintUnsigned64String(PrintCharRoutine, VA_ARG(Arguments, UINT_PTR), 10, PaddingCount); + break; + case L'x': + /* Zero-padded, unsigned 64-bit hexadecimal integer */ + BmpPrintUnsigned64String(PrintCharRoutine, VA_ARG(Arguments, UINT_PTR), 16, PaddingCount); + break; + default: + /* Unknown by default */ + PrintCharRoutine(L'?'); + break; + } + break; + case L'u': + /* Zero-padded, unsigned 32-bit integer */ + BmpPrintUnsigned32String(PrintCharRoutine, VA_ARG(Arguments, UINT32), 10, PaddingCount); + break; + case L'x': + /* Zero-padded, unsigned 32-bit hexadecimal integer */ + BmpPrintUnsigned32String(PrintCharRoutine, VA_ARG(Arguments, UINT32), 16, PaddingCount); + break; + default: + /* Unknown by default */ + PrintCharRoutine(L'?'); + break; + } + break; + case L'%': + /* Percent character */ + PrintCharRoutine(L'%'); + break; + default: + /* Unknown by default */ + PrintCharRoutine(L'?'); + break; + } + break; + case L'\r': + /* Carriage return is ignored */ + break; + case L'\n': + /* New line together with carriage return */ + PrintCharRoutine(L'\r'); + PrintCharRoutine(L'\n'); + break; + default: + /* Put character by default */ + PrintCharRoutine(*Format); + break; + } + } +} + +/** + * This routine formats the input string and prints it using specified routine. + * + * @param PrintCharRoutine + * Pointer to the routine that writes an input data to specific device. + * + * @param Format + * The formatted string that is to be written to the specified device. + * + * @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 +BmpFormatString(IN BMPRINTCHAR PrintCharRoutine, + IN PUINT16 Format, + IN ...) +{ + VA_LIST Arguments; + + /* Initialise the va_list */ + VA_START(Arguments, Format); + + /* Format and print the string to the desired output */ + BmPrintString(PrintCharRoutine, Format, Arguments); + + /* Clean up the va_list */ + VA_END(Arguments); +} + +/** + * This routine converts 32-bit integer as string and prints it using specified routine. + * + * @param PrintCharRoutine + * Pointer to the routine that writes an input data to specific device. + * + * @param Number + * 32-bit integer value. + * + * @param Base + * Specifies the number base system representation. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BmpPrintSigned32String(IN BMPRINTCHAR PrintCharRoutine, + IN INT Number, + IN UINT Base) +{ + /* Print - (minus) if this is negative value */ + if(Number < 0) + { + PrintCharRoutine(L'-'); + Number *= -1; + } + + /* Print the integer value */ + BmpPrintUnsigned32String(PrintCharRoutine, Number, Base, 0); +} + +/** + * This routine converts 64-bit integer as string and prints it using specified routine. + * + * @param PrintCharRoutine + * Pointer to the routine that writes an input data to specific device. + * + * @param Number + * 64-bit integer value. + * + * @param Base + * Specifies the number base system representation. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BmpPrintSigned64String(IN BMPRINTCHAR PrintCharRoutine, + IN INT_PTR Number, + IN UINT_PTR Base) +{ + /* Print - (minus) if this is negative value */ + if(Number < 0) + { + PrintCharRoutine(L'-'); + Number *= -1; + } + + /* Print the integer value */ + BmpPrintUnsigned64String(PrintCharRoutine, Number, Base, 0); +} + +/** + * This routine converts 32-bit unsigned integer as string and prints it using specified routine. + * + * @param PrintCharRoutine + * Pointer to the routine that writes an input data to specific device. + * + * @param Number + * 32-bit integer value. + * + * @param Base + * Specifies the number base system representation. + * + * @param Padding + * Specifies the number of leading zeros to complete the field width. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BmpPrintUnsigned32String(IN BMPRINTCHAR PrintCharRoutine, + IN UINT Number, + IN UINT Base, + IN UINT Padding) +{ + 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 = BmpHexTable[Number % Base]; + } while(Pointer >= Buffer && (Number /= Base)); + + /* Calculate number length */ + NumberLength = ARRAY_SIZE(Buffer) - (Pointer - Buffer) - 1; + + /* Check if leading zeros are needed */ + if(NumberLength < Padding) + { + Padding -= NumberLength; + while(Padding--) + { + /* Write leading zeroes */ + PrintCharRoutine(L'0'); + } + } + + /* Print value to the console */ + for(; *Pointer; ++Pointer) + { + PrintCharRoutine(*Pointer); + } +} + +/** + * This routine converts 64-bit unsigned integer as string and prints it using specified routine. + * + * @param PrintCharRoutine + * Pointer to the routine that writes an input data to specific device. + * + * @param Number + * 64-bit integer value. + * + * @param Base + * Specifies the number base system representation. + * + * @param Padding + * Specifies the number of leading zeros to complete the field width. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BmpPrintUnsigned64String(IN BMPRINTCHAR PrintCharRoutine, + IN UINT_PTR Number, + IN UINT_PTR Base, + IN UINT_PTR Padding) +{ + UINT16 Buffer[20]; + 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 = BmpHexTable[Number % Base]; + } while(Pointer >= Buffer && (Number /= Base)); + + /* Calculate number length */ + NumberLength = ARRAY_SIZE(Buffer) - (Pointer - Buffer) - 1; + + /* Check if leading zeros are needed */ + if(NumberLength < Padding) + { + Padding -= NumberLength; + while(Padding--) + { + /* Write leading zeroes */ + PrintCharRoutine(L'0'); + } + } + + /* Print value to the console */ + for(; *Pointer; ++Pointer) + { + PrintCharRoutine(*Pointer); + } +} + +/** + * Reads the number of padding characters from the format string. + * + * @param Format + * The format string. + * + * @return Number of padding characters. + * + * @since XT 1.0 + */ +XTCDECL +UINT64 +BmpReadStringPadding(IN PUINT16 *Format) +{ + ULONG Count = 0; + PUINT16 Fmt = *Format; + + /* Read the padding */ + for(;; ++Fmt) + { + switch(*Fmt) + { + case L'0' ... L'9': + /* Check the number of leading zeroes */ + Count = Count * 10 + *Fmt - L'0'; + break; + default: + /* No padding by default */ + *Format = Fmt; + return Count; + } + } + + /* No padding by default */ + return 0; +}