From 6a6589b1eee864b913ab1f1a8bf82350698afbf5 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Wed, 28 Feb 2024 17:01:49 +0000 Subject: [PATCH] Run as much of the progress report as we can in test mode, so it can be stress tested * Instead of simply exiting the progress calls, we now perform the progress bar computations and run the various ASSERTS, so we can stress test them in some new progress tests * Also apply minor additional code improvements. --- src/boot.c | 6 ++---- src/boot.h | 7 ++++++- src/console.c | 46 +++++++++++++++++++++++++-------------------- tests/test_list.txt | 30 +++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 25 deletions(-) diff --git a/src/boot.c b/src/boot.c index 508e597..b4f0a59 100644 --- a/src/boot.c +++ b/src/boot.c @@ -277,10 +277,8 @@ EFI_STATUS EFIAPI efi_main( if (EFI_ERROR(Status)) goto out; - if (IsTestMode) { - // Print any extra data we want to validate - Print(L"[TEST] TotalBytes = 0x%lX\n", HashList.TotalBytes); - } + // Print any extra data we want to validate + PrintTest(L"TotalBytes = 0x%lX", HashList.TotalBytes); // Set up the progress bar data Progress.Type = (HashList.TotalBytes == 0) ? PROGRESS_TYPE_FILE : PROGRESS_TYPE_BYTE; diff --git a/src/boot.h b/src/boot.h index 0bc4437..95b2d44 100644 --- a/src/boot.h +++ b/src/boot.h @@ -136,11 +136,15 @@ typedef UINT32 CHAR32; #define ARRAY_SIZE(Array) (sizeof(Array) / sizeof((Array)[0])) #endif -/* Standard MIN() macro */ +/* Standard MIN/MAX macro */ #ifndef MIN #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) #endif +#ifndef MAX +#define MAX(X, Y) (((X) > (Y)) ? (X) : (Y)) +#endif + /* FreePool() replacement, that NULLs the freed pointer. */ #define SafeFree(p) do { FreePool(p); p = NULL;} while(0) @@ -192,6 +196,7 @@ typedef struct { #define PrintError(fmt, ...) do { SetTextPosition(MARGIN_H, AlertYPos++); \ SetText(TEXT_RED); Print(L"[FAIL]"); DefText(); \ Print(L" " fmt L": [%d] %r\n", ##__VA_ARGS__, (Status&0x7FFFFFFF), Status); } while (0) +#define PrintTest(fmt, ...) do { if (IsTestMode) Print(L"[TEST] " fmt L"\n", ##__VA_ARGS__); } while(0) /* Convenience macro to position text on screen (when not running in test mode). */ #define SetTextPosition(x, y) do { if (!IsTestMode) gST->ConOut->SetCursorPosition(gST->ConOut, x, y);} while (0) diff --git a/src/console.c b/src/console.c index 094537d..4ec681b 100644 --- a/src/console.c +++ b/src/console.c @@ -75,9 +75,9 @@ VOID PrintCentered( { UINTN MessagePos; + MessagePos = Console.Cols / 2 - SafeStrLen(Message) / 2; + V_ASSERT(MessagePos > MARGIN_H); if (!IsTestMode) { - MessagePos = Console.Cols / 2 - SafeStrLen(Message) / 2; - V_ASSERT(MessagePos > MARGIN_H); SetTextPosition(0, YPos); Print(EmptyLine); SetTextPosition(MessagePos, YPos); @@ -103,7 +103,6 @@ VOID PrintFailedEntry( return; // Truncate the path in case it's very long. - // TODO: Ideally we'd want long path reduction similar to what Windows does. if (SafeStrLen(Path) > 80) Path[80] = L'\0'; if (!IsTestMode) { @@ -116,7 +115,7 @@ VOID PrintFailedEntry( Print(L"[FAIL]"); DefText(); // Display a more explicit message (than "CRC Error") for files that fail MD5 - if ((Status & 0x7FFFFFFF) == 27) + if (Status == EFI_CRC_ERROR) Print(L" File '%s': [27] MD5 Checksum Error\n", Path); else Print(L" File '%s': [%d] %r\n", Path, (Status & 0x7FFFFFFF), Status); @@ -135,8 +134,8 @@ VOID InitProgress( Progress->Active = FALSE; - if (Console.Cols < COLS_MIN || Console.Rows < ROWS_MIN || Console.Cols >= STRING_MAX || - Progress->Message == NULL || IsTestMode) + if (Console.Cols < COLS_MIN || Console.Rows < ROWS_MIN || + Console.Cols >= STRING_MAX || Progress->Message == NULL) return; if (SafeStrLen(Progress->Message) > Console.Cols - MARGIN_H * 2 - 8) @@ -152,12 +151,14 @@ VOID InitProgress( Progress->LastCol = 0; Progress->PPos = MessagePos + SafeStrLen(Progress->Message) + 2; - SetTextPosition(MessagePos, Progress->YPos); - Print(L"%s: 0.0%%", Progress->Message); + if (!IsTestMode) { + SetTextPosition(MessagePos, Progress->YPos); + Print(L"%s: 0.0%%", Progress->Message); - SetTextPosition(MARGIN_H, Progress->YPos + 1); - for (i = 0; i < Console.Cols - MARGIN_H * 2; i++) - Print(L"░"); + SetTextPosition(MARGIN_H, Progress->YPos + 1); + for (i = 0; i < Console.Cols - MARGIN_H * 2; i++) + Print(L"░"); + } Progress->Active = TRUE; } @@ -174,7 +175,7 @@ VOID UpdateProgress( UINTN CurCol, PerMille; if (Progress == NULL || !Progress->Active || Progress->Maximum == 0 || - Console.Cols < COLS_MIN || Console.Cols >= STRING_MAX || IsTestMode) + Console.Cols < COLS_MIN || Console.Cols >= STRING_MAX) return; if (Progress->Current > Progress->Maximum) @@ -182,14 +183,18 @@ VOID UpdateProgress( // Update the percentage figure PerMille = (UINTN)((Progress->Current * 1000) / Progress->Maximum); - SetTextPosition(Progress->PPos, Progress->YPos); - Print(L"%d.%d%%", PerMille / 10, PerMille % 10); + if (!IsTestMode) { + SetTextPosition(Progress->PPos, Progress->YPos); + Print(L"%d.%d%%", PerMille / 10, PerMille % 10); + } // Update the progress bar CurCol = (UINTN)((Progress->Current * (Console.Cols - MARGIN_H * 2)) / Progress->Maximum); - for (; CurCol > Progress->LastCol && Progress->LastCol < Console.Cols; Progress->LastCol++) { - SetTextPosition(MARGIN_H + Progress->LastCol, Progress->YPos + 1); - Print(L"%c", BLOCKELEMENT_FULL_BLOCK); + if (!IsTestMode) { + for (; CurCol > Progress->LastCol && Progress->LastCol < Console.Cols; Progress->LastCol++) { + SetTextPosition(MARGIN_H + Progress->LastCol, Progress->YPos + 1); + Print(L"%c", BLOCKELEMENT_FULL_BLOCK); + } } if (Progress->Current == Progress->Maximum) @@ -210,12 +215,13 @@ VOID CountDown( UINTN MessagePos, CounterPos; INTN i; - if (IsTestMode) - return; - MessagePos = Console.Cols / 2 - SafeStrLen(Message) / 2 - 1; CounterPos = MessagePos + SafeStrLen(Message) + 2; V_ASSERT(MessagePos > MARGIN_H); + + if (IsTestMode) + return; + SetTextPosition(0, Console.Rows - 2); Print(EmptyLine); SetTextPosition(MessagePos, Console.Rows - 2); diff --git a/tests/test_list.txt b/tests/test_list.txt index b69ca50..05d601d 100644 --- a/tests/test_list.txt +++ b/tests/test_list.txt @@ -278,3 +278,33 @@ Test bootloader < rm -f image/efi/boot/*_original.efi < rm image/file* + +# Chainload original bootloader without md5sum +> 7z x ./tests/chainload.7z -y -o./image/efi/boot +> rm -f md5sum.txt +Test bootloader +< rm -f image/efi/boot/*_original.efi + +# Progress with TotalBytes too small +> echo "# md5sum_totalbytes = 0x1" > image/md5sum.txt +> for i in {64..1024..64}; do dd if=/dev/urandom of=image/file$i bs=1k count=$i; done +> (cd image; md5sum file* >> md5sum.txt) +[TEST] TotalBytes = 0x1 +16/16 files processed [0 failed] +< rm image/file* + +# Progress with TotalBytes exact +> echo "# md5sum_totalbytes = 0x880000" > image/md5sum.txt +> for i in {64..1024..64}; do dd if=/dev/urandom of=image/file$i bs=1k count=$i; done +> (cd image; md5sum file* >> md5sum.txt) +[TEST] TotalBytes = 0x880000 +16/16 files processed [0 failed] +< rm image/file* + +# Progress with TotalBytes too large +> echo "# md5sum_totalbytes = 0x1234567890abcdef" > image/md5sum.txt +> for i in {64..1024..64}; do dd if=/dev/urandom of=image/file$i bs=1k count=$i; done +> (cd image; md5sum file* >> md5sum.txt) +[TEST] TotalBytes = 0x1234567890ABCDEF +16/16 files processed [0 failed] +< rm image/file*