IntelFsp2Pkg/FspSecCore: Do not hang when bootloader IDT is larger

The current logic in FspSecCore is when the size of IDT created
by the bootloader is larger than the size of IDT that's going to be created
by FSP, CpuDeadLoop() is hit.

Change PcdFspMaxInterruptSupported from 34 to 255 to avoid such case.

Even when the PCD is overriden to a small value, the dead-loop is
not necessary. The patch updates the logic to only copy
the first part of the IDT entries when bootloader's IDT is larger.
A warn is printed in the debug log when such case happens.

The change addresses a boot hang in FSP API mode introduced by
commit 3454d7ab41.

Signed-off-by: Ray Ni <ray.ni@intel.com>
This commit is contained in:
Ray Ni 2026-03-18 13:07:47 +08:00 committed by mergify[bot]
parent 819af4cd11
commit ff25439600
2 changed files with 19 additions and 10 deletions

View file

@ -65,6 +65,7 @@ SecStartup (
FSP_GLOBAL_DATA PeiFspData; FSP_GLOBAL_DATA PeiFspData;
IA32_IDT_GATE_DESCRIPTOR ExceptionHandler; IA32_IDT_GATE_DESCRIPTOR ExceptionHandler;
UINTN IdtSize; UINTN IdtSize;
UINTN BootloaderIdtSize;
// //
// Process all libraries constructor function linked to SecCore. // Process all libraries constructor function linked to SecCore.
@ -114,6 +115,7 @@ SecStartup (
// | | // | |
// | | // | |
// |-------------------|----> TempRamBase // |-------------------|----> TempRamBase
BootloaderIdtSize = 0;
IdtTableInStack.PeiService = 0; IdtTableInStack.PeiService = 0;
AsmReadIdtr (&IdtDescriptor); AsmReadIdtr (&IdtDescriptor);
if (IdtDescriptor.Base == 0) { if (IdtDescriptor.Base == 0) {
@ -124,15 +126,9 @@ SecStartup (
IdtSize = sizeof (IdtTableInStack.IdtTable); IdtSize = sizeof (IdtTableInStack.IdtTable);
} else { } else {
IdtSize = IdtDescriptor.Limit + 1; BootloaderIdtSize = IdtDescriptor.Limit + 1;
if (IdtSize > sizeof (IdtTableInStack.IdtTable)) { IdtSize = MIN (BootloaderIdtSize, sizeof (IdtTableInStack.IdtTable));
// CopyMem ((VOID *)(UINTN)&IdtTableInStack.IdtTable, (VOID *)IdtDescriptor.Base, IdtSize);
// ERROR: IDT table size from boot loader is larger than FSP can support, DeadLoop here!
//
CpuDeadLoop ();
} else {
CopyMem ((VOID *)(UINTN)&IdtTableInStack.IdtTable, (VOID *)IdtDescriptor.Base, IdtSize);
}
} }
IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable; IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable;
@ -145,6 +141,19 @@ SecStartup (
// //
FspGlobalDataInit (&PeiFspData, BootLoaderStack, (UINT8)ApiIdx); FspGlobalDataInit (&PeiFspData, BootLoaderStack, (UINT8)ApiIdx);
if (BootloaderIdtSize > IdtSize) {
DEBUG ((
DEBUG_WARN,
"%a: # of IDT entries setup by bootloader (%d) > (PcdFspMaxInterruptSupported + 1) (%d)!\n"
" Interrupt handlers #%d ~ #%d from bootloader are not inherited.\n",
__func__,
BootloaderIdtSize / sizeof (IA32_IDT_GATE_DESCRIPTOR),
ARRAY_SIZE (IdtTableInStack.IdtTable),
ARRAY_SIZE (IdtTableInStack.IdtTable),
BootloaderIdtSize / sizeof (IA32_IDT_GATE_DESCRIPTOR) - 1
));
}
// //
// Update the base address and length of Pei temporary memory // Update the base address and length of Pei temporary memory
// //

View file

@ -112,7 +112,7 @@
# #
# Maximal Interrupt supported in IDT table. # Maximal Interrupt supported in IDT table.
# #
gIntelFsp2PkgTokenSpaceGuid.PcdFspMaxInterruptSupported | 34| UINT8|0x10000005 gIntelFsp2PkgTokenSpaceGuid.PcdFspMaxInterruptSupported | 255| UINT8|0x10000005
# #
# Allows FSP-M to reserve a section of Temporary RAM for implementation specific use. # Allows FSP-M to reserve a section of Temporary RAM for implementation specific use.
# Reduces the amount of memory available for the PeiCore heap. # Reduces the amount of memory available for the PeiCore heap.