pcienumerator.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,178 行 · 第 1/4 页
C
2,178 行
UINT64 TempOptionRomSize;
MaxOptionRomSize = 0;
//
// Go through bridges to reach all devices
//
CurrentLink = Bridge->ChildList.ForwardLink;
while (CurrentLink && CurrentLink != &Bridge->ChildList) {
Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
if (!IsListEmpty (&Temp->ChildList)) {
//
// Get max option rom size under this bridge
//
TempOptionRomSize = GetMaxOptionRomSize (Temp);
//
// Compare with the option rom size of the bridge
// Get the larger one
//
if (Temp->RomSize > TempOptionRomSize) {
TempOptionRomSize = Temp->RomSize;
}
} else {
//
// For devices get the rom size directly
//
TempOptionRomSize = Temp->RomSize;
}
//
// Get the largest rom size on this bridge
//
if (TempOptionRomSize > MaxOptionRomSize) {
MaxOptionRomSize = TempOptionRomSize;
}
CurrentLink = CurrentLink->ForwardLink;
}
return MaxOptionRomSize;
}
EFI_STATUS
PciHostBridgeDeviceAttribute (
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
)
/*++
Routine Description:
Process attributes of devices on this host bridge
Arguments:
Returns:
None
--*/
// TODO: PciResAlloc - add argument and description to function comment
// TODO: EFI_NOT_FOUND - add return value to function comment
// TODO: EFI_SUCCESS - add return value to function comment
{
EFI_HANDLE RootBridgeHandle;
PCI_IO_DEVICE *RootBridgeDev;
EFI_STATUS Status;
RootBridgeHandle = NULL;
while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
//
// Get RootBridg Device by handle
//
RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
if (RootBridgeDev == NULL) {
return EFI_NOT_FOUND;
}
//
// Set the attributes for devcies behind the Root Bridge
//
Status = DetermineDeviceAttribute (RootBridgeDev);
if (EFI_ERROR (Status)) {
return Status;
}
}
return EFI_SUCCESS;
}
EFI_STATUS
GetResourceAllocationStatus (
VOID *AcpiConfig,
OUT UINT64 *IoResStatus,
OUT UINT64 *Mem32ResStatus,
OUT UINT64 *PMem32ResStatus,
OUT UINT64 *Mem64ResStatus,
OUT UINT64 *PMem64ResStatus
)
/*++
Routine Description:
Get resource allocation status from the ACPI pointer
Arguments:
Returns:
None
--*/
// TODO: AcpiConfig - add argument and description to function comment
// TODO: IoResStatus - add argument and description to function comment
// TODO: Mem32ResStatus - add argument and description to function comment
// TODO: PMem32ResStatus - add argument and description to function comment
// TODO: Mem64ResStatus - add argument and description to function comment
// TODO: PMem64ResStatus - add argument and description to function comment
// TODO: EFI_SUCCESS - add return value to function comment
{
UINT8 *Temp;
UINT64 ResStatus;
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr;
Temp = (UINT8 *) AcpiConfig;
while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
ResStatus = ptr->AddrTranslationOffset;
switch (ptr->ResType) {
case 0:
if (ptr->AddrSpaceGranularity == 32) {
if (ptr->SpecificFlag == 0x06) {
//
// Pmem32
//
*PMem32ResStatus = ResStatus;
} else {
//
// Mem32
//
*Mem32ResStatus = ResStatus;
}
}
if (ptr->AddrSpaceGranularity == 64) {
if (ptr->SpecificFlag == 0x06) {
//
// PMem64
//
*PMem64ResStatus = ResStatus;
} else {
//
// Mem64
//
*Mem64ResStatus = ResStatus;
}
}
break;
case 1:
//
// Io
//
*IoResStatus = ResStatus;
break;
default:
break;
}
Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
}
return EFI_SUCCESS;
}
EFI_STATUS
RejectPciDevice (
IN PCI_IO_DEVICE *PciDevice
)
/*++
Routine Description:
Remove a PCI device from device pool and mark its bar
Arguments:
Returns:
None
--*/
// TODO: PciDevice - add argument and description to function comment
// TODO: EFI_SUCCESS - add return value to function comment
// TODO: EFI_ABORTED - add return value to function comment
// TODO: EFI_SUCCESS - add return value to function comment
// TODO: EFI_ABORTED - add return value to function comment
{
PCI_IO_DEVICE *Bridge;
PCI_IO_DEVICE *Temp;
EFI_LIST_ENTRY *CurrentLink;
//
// Remove the padding resource from a bridge
//
if ( IS_PCI_BRIDGE(&PciDevice->Pci) && \
PciDevice->ResourcePaddingDescriptors ) {
gBS->FreePool (PciDevice->ResourcePaddingDescriptors);
PciDevice->ResourcePaddingDescriptors = NULL;
return EFI_SUCCESS;
}
//
// Skip RB and PPB
//
if (IS_PCI_BRIDGE (&PciDevice->Pci) || (!PciDevice->Parent)) {
return EFI_ABORTED;
}
if (IS_CARDBUS_BRIDGE (&PciDevice->Pci)) {
//
// Get the root bridge device
//
Bridge = PciDevice;
while (Bridge->Parent) {
Bridge = Bridge->Parent;
}
RemoveAllPciDeviceOnBridge (Bridge->Handle, PciDevice);
//
// Mark its bar
//
InitializeP2C (PciDevice);
}
//
// Remove the device
//
Bridge = PciDevice->Parent;
CurrentLink = Bridge->ChildList.ForwardLink;
while (CurrentLink && CurrentLink != &Bridge->ChildList) {
Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
if (Temp == PciDevice) {
InitializePciDevice (Temp);
RemoveEntryList (CurrentLink);
FreePciDevice (Temp);
return EFI_SUCCESS;
}
CurrentLink = CurrentLink->ForwardLink;
}
return EFI_ABORTED;
}
BOOLEAN
IsRejectiveDevice (
IN PCI_RESOURCE_NODE *PciResNode
)
/*++
Routine Description:
Determine whethter a PCI device can be rejected
Arguments:
Returns:
None
--*/
// TODO: PciResNode - add argument and description to function comment
{
PCI_IO_DEVICE *Temp;
Temp = PciResNode->PciDev;
//
// Ensure the device is present
//
if (!Temp) {
return FALSE;
}
//
// PPB and RB should go ahead
//
if (IS_PCI_BRIDGE (&Temp->Pci) || (!Temp->Parent)) {
return TRUE;
}
//
// Skip device on Bus0
//
if ((Temp->Parent) && (Temp->BusNumber == 0)) {
return FALSE;
}
//
// Skip VGA
//
if (IS_PCI_VGA (&Temp->Pci)) {
return FALSE;
}
return TRUE;
}
PCI_RESOURCE_NODE *
GetLargerConsumerDevice (
IN PCI_RESOURCE_NODE *PciResNode1,
IN PCI_RESOURCE_NODE *PciResNode2
)
/*++
Routine Description:
Get the larger resource consumer
Arguments:
Returns:
None
--*/
// TODO: PciResNode1 - add argument and description to function comment
// TODO: PciResNode2 - add argument and description to function comment
{
if (!PciResNode2) {
return PciResNode1;
}
if ((IS_PCI_BRIDGE(&(PciResNode2->PciDev->Pci)) || !(PciResNode2->PciDev->Parent)) \
&& (PciResNode2->ResourceUsage != PciResUsagePadding) )
{
return PciResNode1;
}
if (!PciResNode1) {
return PciResNode2;
}
if ((PciResNode1->Length) > (PciResNode2->Length)) {
return PciResNode1;
}
return PciResNode2;
}
PCI_RESOURCE_NODE *
GetMaxResourceConsumerDevice (
IN PCI_RESOURCE_NODE *ResPool
)
/*++
Routine Description:
Get the max resource consumer in the host resource pool
Arguments:
Returns:
None
--*/
// TODO: ResPool - add argument and description to function comment
{
PCI_RESOURCE_NODE *Temp;
EFI_LIST_ENTRY *CurrentLink;
PCI_RESOURCE_NODE *PciResNode;
PCI_RESOURCE_NODE *PPBResNode;
PciResNode = NULL;
CurrentLink = ResPool->ChildList.ForwardLink;
while (CurrentLink && CurrentLink != &ResPool->ChildList) {
Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
if (!IsRejectiveDevice (Temp)) {
CurrentLink = CurrentLink->ForwardLink;
continue;
}
if ((IS_PCI_BRIDGE (&(Temp->PciDev->Pci)) || (!Temp->PciDev->Parent)) \
&& (Temp->ResourceUsage != PciResUsagePadding))
{
PPBResNode = GetMaxResourceConsumerDevice (Temp);
PciResNode = GetLargerConsumerDevice (PciResNode, PPBResNode);
} else {
PciResNode = GetLargerConsumerDevice (PciResNode, Temp);
}
CurrentLink = CurrentLink->ForwardLink;
}
return PciResNode;
}
EFI_STATUS
PciHostBridgeAdjustAllocation (
IN PCI_RESOURCE_NODE *IoPool,
IN PCI_RESOURCE_NODE *Mem32Pool,
IN PCI_RESOURCE_NODE *PMem32Pool,
IN PCI_RESOURCE_NODE *Mem64Pool,
IN PCI_RESOURCE_NODE *PMem64Pool,
IN UINT64 IoResStatus,
IN UINT64 Mem32ResStatus,
IN UINT64 PMem32ResStatus,
IN UINT64 Mem64ResStatus,
IN UINT64 PMem64ResStatus
)
/*++
Routine Description:
Adjust host bridge allocation so as to reduce resource requirement
Arguments:
Returns:
None
--*/
// TODO: IoPool - add argument and description to function comment
// TODO: Mem32Pool - add argument and description to function comment
// TODO: PMem32Pool - add argument and description to function comment
// TODO: Mem64Pool - add argument and description to function comment
// TODO: PMem64Pool - add argument and description to function comment
// TODO: IoResStatus - add argument and description to function comment
// TODO: Mem32ResStatus - add argument and description to function comment
// TODO: PMem32ResStatus - add argument and description to function comment
// TODO: Mem64ResStatus - add argument and description to function comment
// TODO: PMem64ResStatus - add argument and description to function comment
// TODO: EFI_ABORTED - add return value to function comment
// TODO: EFI_SUCCESS - add return value to function comment
// TODO: EFI_ABORTED - add return value to function comment
{
BOOLEAN AllocationAjusted;
PCI_RESOURCE_NODE *PciResNode;
PCI_RESOURCE_NODE *ResPool[5];
PCI_IO_DEVICE *RemovedPciDev[5];
UINT64 ResStatus[5];
UINTN RemovedPciDevNum;
UINTN DevIndex;
UINTN ResType;
EFI_STATUS Status;
EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA AllocFailExtendedData;
PciResNode = NULL;
EfiZeroMem (RemovedPciDev, 5 * sizeof (PCI_IO_DEVICE *));
RemovedPciDevNum = 0;
ResPool[0] = IoPool;
ResPool[1] = Mem32Pool;
ResPool[2] = PMem32Pool;
ResPool[3] = Mem64Pool;
ResPool[4] = PMem64Pool;
ResStatus[0] = IoResStatus;
ResStatus[1] = Mem32ResStatus;
ResStatus[2] = PMem32ResStatus;
ResStatus[3] = Mem64ResStatus;
ResStatus[4] = PMem64ResStatus;
AllocationAjusted = FALSE;
for (ResType = 0; ResType < 5; ResType++) {
if (ResStatus[ResType] == EFI_RESOURCE_SATISFIED) {
continue;
}
if (ResStatus[ResType] == EFI_RESOURCE_NONEXISTENT) {
//
// Hostbridge hasn't this resource type
//
return EFI_ABORTED;
}
//
// Hostbridge hasn't enough resource
//
PciResNode = GetMaxResourceConsumerDevice (ResPool[ResType]);
if (!PciResNode) {
continue;
}
//
// Check if the device has been removed before
//
for (DevIndex = 0; DevIndex < RemovedPciDevNum; DevIndex++) {
if (PciResNode->PciDev == RemovedPciDev[DevIndex]) {
continue;
}
}
//
// Remove the device if it isn't in the array
//
Status = RejectPciDevice (PciResNode->PciDev);
if (Status == EFI_SUCCESS) {
//
// Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
//
AllocFailExtendedData.DataHeader.HeaderSize = sizeof (EFI_STATUS_CODE_DATA);
AllocFailExtendedData.DataHeader.Size = sizeof (EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA) -
sizeof (EFI_STATUS_CODE_DATA);
EfiCommonLibCopyMem (
&AllocFailExtendedData.DataHeader.Type,
&gEfiStatusCodeSpecificDataGuid,
sizeof (EFI_GUID)
);
//
// Have no way to get ReqRes, AllocRes & Bar here
//
AllocFailExtendedData.DevicePath = PciResNode->PciDev->DevicePath;
AllocFailExtendedData.Bar = PciResNode->Bar;
AllocFailExtendedData.ReqRes = NULL;
AllocFailExtendedData.AllocRes = NULL;
EfiLibReportStatusCode (
EFI_PROGRESS_CODE,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?