VirtualBox

Ignore:
Timestamp:
Mar 31, 2025 11:31:09 AM (2 weeks ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
168237
Message:

Devices/EFI/FirmwareNew: Merge edk2-stable202502 from the vendor branch and make it build for the important platforms, bugref:4643

Location:
trunk/src/VBox/Devices/EFI/FirmwareNew
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/EFI/FirmwareNew

  • trunk/src/VBox/Devices/EFI/FirmwareNew/UefiPayloadPkg/Library/PciSegmentInfoLibAcpiBoardInfo/PciSegmentInfoLibAcpiBoardInfo.c

    r99404 r108794  
    44
    55  Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
     6  Copyright (c) 2024, Rivos Inc. All rights reserved.<BR>
     7
    68  SPDX-License-Identifier: BSD-2-Clause-Patent
    79
     
    1416#include <Library/PciSegmentInfoLib.h>
    1517#include <Library/DebugLib.h>
    16 
    17 STATIC PCI_SEGMENT_INFO  mPciSegment0 = {
    18   0,  // Segment number
    19   0,  // To be fixed later
    20   0,  // Start bus number
    21   255 // End bus number
    22 };
    23 
    24 /**
    25   Return an array of PCI_SEGMENT_INFO holding the segment information.
    26 
    27   Note: The returned array/buffer is owned by callee.
    28 
    29   @param  Count  Return the count of segments.
    30 
    31   @retval A callee owned array holding the segment information.
     18#include <UniversalPayload/PciRootBridges.h>
     19#include <Library/PciLib.h>
     20#include <Library/MemoryAllocationLib.h>
     21#include <Library/PcdLib.h>
     22#include <Library/BaseMemoryLib.h>
     23#include <Guid/PciSegmentInfoGuid.h>
     24
     25static PCI_SEGMENT_INFO  *mPciSegments;
     26static UINTN             mCount;
     27
     28/**
     29  Find segment info from all root bridges
     30
     31  @param[in]  PciRootBridgeInfo    Pointer of Universal Payload PCI Root Bridge Info Hob
     32  @param[in]  UplSegmentInfo       Pointer of Universal UPL Segment Info
     33
     34  @param[out] NumberOfRootBridges  Number of root bridges detected
     35
     36**/
     37VOID
     38RetrieveMultiSegmentInfoFromHob (
     39  IN  UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES  *PciRootBridgeInfo,
     40  IN  UPL_PCI_SEGMENT_INFO_HOB            *UplSegmentInfo,
     41  OUT UINTN                               *NumberOfRootBridges
     42  )
     43{
     44  UINTN             Size;
     45  UINT8             IndexForExistingSegments;
     46  UINT8             NumberOfExistingSegments;
     47  UINT8             IndexForRb;
     48  PCI_SEGMENT_INFO  *pPciSegments;
     49
     50  if (PciRootBridgeInfo == NULL) {
     51    mPciSegments = NULL;
     52    return;
     53  }
     54
     55  IndexForExistingSegments = 0;
     56  NumberOfExistingSegments = 0;
     57  IndexForRb               = 0;
     58  Size                     = PciRootBridgeInfo->Count * sizeof (PCI_SEGMENT_INFO);
     59
     60  *NumberOfRootBridges = PciRootBridgeInfo->Count;
     61
     62  pPciSegments = (PCI_SEGMENT_INFO *)AllocatePool (Size);
     63  if (pPciSegments == NULL) {
     64    ASSERT (pPciSegments != NULL);
     65    return;
     66  }
     67
     68  ZeroMem (pPciSegments, PciRootBridgeInfo->Count * sizeof (PCI_SEGMENT_INFO));
     69
     70  //
     71  // RBs may share the same Segment number, but mPciSegments should not have duplicate segment data.
     72  // 1. if RB Segment is same with existing one, update StartBus and EndBus of existing one
     73  // 2. if RB Segment is different from all existing ones, add it to the existing Segments data buffer.
     74  // pPciSegments is local temporary data buffer that will be freed later (size depends on numbers of RB)
     75  // mPciSegments is global data that will be updated with the pPciSegments for caller to utilize. (size depends on numbers of different PciSegments)
     76  //
     77  NumberOfExistingSegments       = 1;
     78  pPciSegments[0].BaseAddress    = UplSegmentInfo->SegmentInfo[0].BaseAddress;
     79  pPciSegments[0].SegmentNumber  = (UINT16)(PciRootBridgeInfo->RootBridge[0].Segment);
     80  pPciSegments[0].StartBusNumber = (UINT8)PciRootBridgeInfo->RootBridge[0].Bus.Base;
     81  pPciSegments[0].EndBusNumber   = (UINT8)PciRootBridgeInfo->RootBridge[0].Bus.Limit;
     82  for (IndexForRb = 1; IndexForRb < PciRootBridgeInfo->Count; IndexForRb++) {
     83    for (IndexForExistingSegments = 0; IndexForExistingSegments < NumberOfExistingSegments; IndexForExistingSegments++) {
     84      if (pPciSegments[IndexForExistingSegments].SegmentNumber == PciRootBridgeInfo->RootBridge[IndexForRb].Segment) {
     85        if (pPciSegments[IndexForExistingSegments].StartBusNumber > PciRootBridgeInfo->RootBridge[IndexForRb].Bus.Base) {
     86          pPciSegments[IndexForExistingSegments].StartBusNumber = (UINT8)PciRootBridgeInfo->RootBridge[IndexForRb].Bus.Base;
     87        }
     88
     89        if (pPciSegments[IndexForExistingSegments].EndBusNumber < PciRootBridgeInfo->RootBridge[IndexForRb].Bus.Limit) {
     90          pPciSegments[IndexForExistingSegments].EndBusNumber = (UINT8)PciRootBridgeInfo->RootBridge[IndexForRb].Bus.Limit;
     91        }
     92
     93        break;  // breaking after a match found
     94      }
     95    }
     96
     97    if (IndexForExistingSegments >= NumberOfExistingSegments) {
     98      //
     99      // No match found, add it to segments data buffer
     100      //
     101      pPciSegments[NumberOfExistingSegments].BaseAddress    = UplSegmentInfo->SegmentInfo[IndexForRb].BaseAddress;
     102      pPciSegments[NumberOfExistingSegments].SegmentNumber  = (UINT16)(PciRootBridgeInfo->RootBridge[IndexForRb].Segment);
     103      pPciSegments[NumberOfExistingSegments].StartBusNumber = (UINT8)PciRootBridgeInfo->RootBridge[IndexForRb].Bus.Base;
     104      pPciSegments[NumberOfExistingSegments].EndBusNumber   = (UINT8)PciRootBridgeInfo->RootBridge[IndexForRb].Bus.Limit;
     105      NumberOfExistingSegments++;
     106    }
     107  }
     108
     109  //
     110  // Prepare data for returning to caller
     111  //
     112  *NumberOfRootBridges = NumberOfExistingSegments;
     113  Size                 = NumberOfExistingSegments * sizeof (PCI_SEGMENT_INFO);
     114  mPciSegments         = (PCI_SEGMENT_INFO *)AllocatePool (Size);
     115  if (mPciSegments == NULL) {
     116    ASSERT (FALSE);
     117    return;
     118  }
     119
     120  CopyMem (&mPciSegments[0], &pPciSegments[0], Size);
     121  if (pPciSegments != NULL) {
     122    FreePool (pPciSegments);
     123  }
     124
     125  return;
     126}
     127
     128/**
     129  Find segment info from all root bridges for legacy systems
     130
     131  @param[in]  PciRootBridgeInfo    Pointer of Universal Payload PCI Root Bridge Info Hob
     132  @param[out] NumberOfRootBridges  Number of root bridges detected
     133
     134**/
     135VOID
     136RetrieveSegmentInfoFromHob (
     137  OUT UINTN  *NumberOfRootBridges
     138  )
     139{
     140  EFI_HOB_GUID_TYPE  *GuidHob;
     141  ACPI_BOARD_INFO    *AcpiBoardInfo;
     142
     143  *NumberOfRootBridges = 1;
     144  // old model relies on gUefiAcpiBoardInfoGuid and hardcoded values for single segment only.
     145  // This is only for backward compatibility, new platforms should adopt new model even in single segment cases.
     146  //
     147  mPciSegments = (PCI_SEGMENT_INFO *)AllocatePool (sizeof (PCI_SEGMENT_INFO));
     148  ASSERT (mPciSegments != NULL);
     149  GuidHob = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid);
     150  ASSERT (GuidHob != NULL);
     151  if (GuidHob != NULL) {
     152    AcpiBoardInfo                = (ACPI_BOARD_INFO *)GET_GUID_HOB_DATA (GuidHob);
     153    mPciSegments->SegmentNumber  = 0;
     154    mPciSegments->BaseAddress    = AcpiBoardInfo->PcieBaseAddress;
     155    mPciSegments->StartBusNumber = 0;
     156    mPciSegments->EndBusNumber   = 0xFF;
     157  }
     158}
     159
     160/**
     161  Return info for all root bridges
     162
     163  @return All the root bridge info instances in an array.
     164**/
     165UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES *
     166Get_RBInfo (
     167  VOID
     168  )
     169{
     170  UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES  *PciRootBridgeInfo;
     171  EFI_HOB_GUID_TYPE                   *GuidHob;
     172  UNIVERSAL_PAYLOAD_GENERIC_HEADER    *GenericHeader;
     173
     174  //
     175  // Find Universal Payload PCI Root Bridge Info hob
     176  //
     177  GuidHob = GetFirstGuidHob (&gUniversalPayloadPciRootBridgeInfoGuid);
     178  if ((GuidHob == NULL) || (sizeof (UNIVERSAL_PAYLOAD_GENERIC_HEADER) > GET_GUID_HOB_DATA_SIZE (GuidHob))) {
     179    return NULL;
     180  }
     181
     182  GenericHeader = (UNIVERSAL_PAYLOAD_GENERIC_HEADER *)GET_GUID_HOB_DATA (GuidHob);
     183  if (GenericHeader->Length > GET_GUID_HOB_DATA_SIZE (GuidHob)) {
     184    return NULL;
     185  }
     186
     187  if ((GenericHeader->Revision != UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES_REVISION) || (GenericHeader->Length < sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES))) {
     188    return NULL;
     189  }
     190
     191  //
     192  // UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES structure is used when Revision equals to UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES_REVISION
     193  //
     194  PciRootBridgeInfo = (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES *)GET_GUID_HOB_DATA (GuidHob);
     195  if (PciRootBridgeInfo->Count <= (GET_GUID_HOB_DATA_SIZE (GuidHob) - sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES)) / sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE)) {
     196    return PciRootBridgeInfo;
     197  }
     198
     199  return NULL;
     200}
     201
     202/**
     203  Return info for all root bridge segments
     204
     205  @return All the segment info instances in an array.
     206**/
     207UPL_PCI_SEGMENT_INFO_HOB *
     208Get_UPLSegInfo (
     209  VOID
     210  )
     211{
     212  UPL_PCI_SEGMENT_INFO_HOB          *UplSegmentInfo;
     213  EFI_HOB_GUID_TYPE                 *GuidHob;
     214  UNIVERSAL_PAYLOAD_GENERIC_HEADER  *GenericHeader;
     215
     216  //
     217  // Find Universal Payload Segment Info hob
     218  //
     219  GuidHob = GetFirstGuidHob (&gUplPciSegmentInfoHobGuid);
     220  if ((GuidHob == NULL) || (sizeof (UNIVERSAL_PAYLOAD_GENERIC_HEADER) > GET_GUID_HOB_DATA_SIZE (GuidHob))) {
     221    return NULL;
     222  }
     223
     224  GenericHeader = (UNIVERSAL_PAYLOAD_GENERIC_HEADER *)GET_GUID_HOB_DATA (GuidHob);
     225  if (GenericHeader->Length > GET_GUID_HOB_DATA_SIZE (GuidHob)) {
     226    return NULL;
     227  }
     228
     229  if ((GenericHeader->Revision != UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES_REVISION) || (GenericHeader->Length < sizeof (UPL_PCI_SEGMENT_INFO_HOB))) {
     230    return NULL;
     231  }
     232
     233  //
     234  // UPL_PCI_SEGMENT_INFO_HOB structure is used when Revision equals to UPL_PCI_SEGMENT_INFO_HOB_REVISION
     235  //
     236  UplSegmentInfo = (UPL_PCI_SEGMENT_INFO_HOB *)GET_GUID_HOB_DATA (GuidHob);
     237  if (UplSegmentInfo->Count <= (GET_GUID_HOB_DATA_SIZE (GuidHob) - sizeof (UPL_PCI_SEGMENT_INFO_HOB)) / sizeof (UPL_SEGMENT_INFO)) {
     238    return UplSegmentInfo;
     239  }
     240
     241  return NULL;
     242}
     243
     244/**
     245  Return all the root bridge instances in an array.
     246
     247  @param Count  Return the count of root bridge instances.
     248
     249  @return All the root bridge instances in an array.
     250          The array should be passed into PciHostBridgeFreeRootBridges()
     251          when it's not used.
    32252**/
    33253PCI_SEGMENT_INFO *
     
    37257  )
    38258{
    39   EFI_HOB_GUID_TYPE  *GuidHob;
    40   ACPI_BOARD_INFO    *AcpiBoardInfo;
    41 
    42   ASSERT (Count != NULL);
    43   if (Count == NULL) {
    44     return NULL;
    45   }
    46 
    47   if (mPciSegment0.BaseAddress == 0) {
    48     //
    49     // Find the acpi board information guid hob
    50     //
    51     GuidHob = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid);
    52     ASSERT (GuidHob != NULL);
    53 
    54     AcpiBoardInfo            = (ACPI_BOARD_INFO *)GET_GUID_HOB_DATA (GuidHob);
    55     mPciSegment0.BaseAddress = AcpiBoardInfo->PcieBaseAddress;
    56   }
    57 
    58   *Count = 1;
    59   return &mPciSegment0;
    60 }
     259  UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES  *PciRootBridgeInfo;
     260  UPL_PCI_SEGMENT_INFO_HOB            *UplSegmentInfo;
     261
     262  if (mPciSegments != NULL) {
     263    *Count = mCount;
     264    return mPciSegments;
     265  }
     266
     267  UplSegmentInfo = Get_UPLSegInfo ();
     268
     269  if (UplSegmentInfo == NULL) {
     270    RetrieveSegmentInfoFromHob (Count);
     271  } else {
     272    PciRootBridgeInfo = Get_RBInfo ();
     273    if (PciRootBridgeInfo == NULL) {
     274      return 0;
     275    }
     276
     277    RetrieveMultiSegmentInfoFromHob (PciRootBridgeInfo, UplSegmentInfo, Count);
     278  }
     279
     280  mCount = *Count;
     281  return mPciSegments;
     282}
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette