From 7fbb4c8ef4b0e54a2326b0d9750fd9e27afdf92e Mon Sep 17 00:00:00 2001 From: liqiqi Date: Wed, 22 Jul 2026 16:58:06 -0700 Subject: [PATCH] AdvLoggerPkg/AdvancedFileLogger: Flush logs only once per reset A capsule-armed reset converts a warm reset into a cold reset by issuing a second, nested ResetSystem() call. NvmExpressDxe shuts its controller down on the first reset notification (via the reset notification protocol, which fires after this platform-specific reset filter) and does not re-initialize it, so re-writing the logs on the nested reset issues I/O to a powered-down NVMe controller. This stalls for the full NVMe command timeout (~5 seconds) and logs a fatal NVMe WHEA telemetry record (EFI_IO_BUS_SCSI | EFI_IOB_EC_INTERFACE_ERROR, 0x02070005), and the log write ultimately fails with a timeout. Add a module-static latch so the in-memory log is flushed to media only once per reset sequence. Nested reset notifications early-return instead of re-writing to the already-shut-down controller. The normal ReadyToBoot / ExitBootServices / sync flush paths are unaffected. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: cccd4451-999f-4caf-bdb4-da35fd5bef85 --- .../AdvancedFileLogger/AdvancedFileLogger.c | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/AdvLoggerPkg/AdvancedFileLogger/AdvancedFileLogger.c b/AdvLoggerPkg/AdvancedFileLogger/AdvancedFileLogger.c index 8ec80feab2..07e8f22740 100644 --- a/AdvLoggerPkg/AdvancedFileLogger/AdvancedFileLogger.c +++ b/AdvLoggerPkg/AdvancedFileLogger/AdvancedFileLogger.c @@ -19,6 +19,14 @@ UINT32 mWritingSemaphore = 0; EFI_EVENT mReadyToBootEvent = NULL; EFI_EVENT mExitBootServicesEvent = NULL; +// +// Set once the in-memory log has been flushed to media during a reset +// notification. Prevents re-flushing on a nested reset (for example, a +// capsule-armed warm-to-cold reset conversion) after storage controllers have +// already been shut down. +// +STATIC BOOLEAN mLogsFlushedOnReset = FALSE; + /** WriteLogFiles @@ -88,11 +96,29 @@ OnResetNotification ( { EFI_TPL OldTpl; + // + // A single logical reset can raise the reset notification more than once. For + // example, a capsule-armed reset converts a warm reset into a cold reset by + // issuing a second, nested ResetSystem () call. Storage drivers such as + // NvmExpressDxe shut their controllers down on the first notification (through + // the reset notification protocol, which fires after this platform-specific + // reset filter) and do not re-initialize them. Re-writing the logs on the + // nested reset would then issue I/O to a powered-down NVMe controller, + // stalling for the full command timeout (~5 seconds) and logging a fatal NVMe + // WHEA telemetry record. The logs are already flushed on the first + // notification, so flush only once per reset sequence. + // + if (mLogsFlushedOnReset) { + DEBUG ((DEBUG_INFO, "OnResetNotification: logs already flushed, skipping nested reset.\n")); + return; + } + OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); gBS->RestoreTPL (OldTpl); DEBUG ((DEBUG_INFO, "OnResetNotification\n")); if (OldTpl <= TPL_CALLBACK) { + mLogsFlushedOnReset = TRUE; WriteLogFiles (); } else { DEBUG ((DEBUG_ERROR, "Unable to write log at reset\n"));