Newer
Older
AMI-Aptio-BIOS-Reversed / DpcDxe / DpcDxe.md
@Ajax Dong Ajax Dong 2 days ago 4 KB Init

DpcDxe

Function Table

Address Name Description
DpcInternalIsListValid
DpcInternalIsListEmpty
DpcGetDebugOutputProtocol
DpcDebugAssert
DpcReportAssertError
DpcReadUnaligned64
DpcCompareGuid
DpcHobInit
DpcQueueDpc
DpcDispatchDpc
DpcDriverEntry
ModuleEntryPoint
Global data
Protocol interface instance EFI_DPC_PROTOCOL
EFI_DPC_PROTOCOL gDpcProtocolInterface;
Head of the free DPC_ENTRY pool (at 0x1140)
LIST_ENTRY gDpcFreeListHead;
DPC queue heads one LIST_ENTRY per priority level (0..31)
Array at 0x11C0 .. 0x13AF (32 entries * 16 bytes each)
LIST_ENTRY gDpcQueue[DPC_NUM_QUEUES];
Statistics (at 0x1160, 0x1170)
UINT64 gDpcQueueDepth = 0;
Protocol registration handle (at 0x1168)
EFI_HANDLE gDpcProtocolHandle = NULL;
Debug output protocol (at 0x1198)
EFI_DEBUG_OUTPUT_PROTOCOL *gDpcDebugProtocol = NULL;
HOB list pointer (at 0x11A0)
VOID *gDpcHobList = NULL;
Memory management
Debug output support
Read CMOS status check error reporting level.
Port 0x70 index, port 0x71 data.
CmosIndex = __inbyte (0x70);
Map CMOS value to EFI error severity.
if (CmosValue == 1) {
0x80000004 } else {
0x80000006 }
GUID comparison and HOB list initialization
Validate DpcToken (must be in range 4..0x1F).
if **((DpcToken < 4) (DpcToken > 0x1F)) {**
Raise TPL to serialize access to the DPC free list and queues.
Tpl = gBS->RaiseTPL (TPL_DPC_PROCESSING);
Check if the free list has an entry.
if (DpcInternalIsListEmpty (&gDpcFreeListHead)) {
Free list is empty try to allocate more entries.
if (Tpl <= 16) {
TPL is high but still low enough for AllocatePool.
Loop up to DPC_ALLOCATE_BATCH (64) times, dropping and
raising TPL each iteration.
for (RetryCount = 0; RetryCount < DPC_ALLOCATE_BATCH; RetryCount++) {
Restore TPL so AllocatePool can work.
Allocate a new DPC entry.
Entry = DpcAllocatePool ();
Raise TPL back.
Check again if free list is still empty (another thread
may have freed entries while TPL was lowered).
Free list is still empty add this entry to it.
DpcInternalInsertTailList (&gDpcFreeListHead, &Entry->List);
After the loop, check if we now have an entry.
TPL is too high for pool allocation.
Status = EFI_OUT_OF_RESOURCES;
Take an entry from the free list.
Entry = BASE_CR (gDpcFreeListHead.ForwardLink, DPC_ENTRY, List);
Populate the DPC entry.
Queue to the correct priority-level list.
DpcInternalInsertTailList (&gDpcQueue[DpcToken], &Entry->List);
Update statistics.
Raise TPL to DPC_PROCESSING to serialize.
Process priorities from the raised TPL (31) downwards.
if (Priority <= 31) {
If this priority queue has entries, drain it.
if (!DpcInternalIsListEmpty (&gDpcQueue[Priority])) {
Take the first entry from the queue.
Entry = BASE_CR (gDpcQueue[Priority].ForwardLink
Decrement the queue depth counter.
Drop TPL to the priority level so the callback
can execute at its intended TPL.
Execute the deferred procedure.
Raise TPL back, and return the entry to the free list.
Move to the next lower priority level.
if (Priority == 0) {
Driver initialization
Check if DPC protocol is already installed.
Status = gBS->LocateProtocol (
Protocol already registered this is a bug in the calling driver.
DpcDebugAssert (
Initialize all 32 DPC queue heads.
for (QueueIndex = 0; QueueIndex < DPC_NUM_QUEUES; QueueIndex++) {
Install the DPC protocol.
Status = gBS->InstallProtocolInterface (
Initialize UEFI globals.
gImageHandle = ImageHandle;
Initialize HOB list for DXE phase services.
DpcHobInit ();
return DpcDriverEntry (ImageHandle, SystemTable);

Generated by HR650X BIOS Decompilation Project