AcpiMcfg.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /** @file
  2. Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
  3. SPDX-License-Identifier: BSD-2-Clause-Patent
  4. **/
  5. #include <AcpiHeader.h>
  6. #include <Guid/RootComplexInfoHob.h>
  7. #include <IndustryStandard/Acpi30.h>
  8. #include <Library/AcpiLib.h>
  9. #include <Library/BaseMemoryLib.h>
  10. #include <Library/DebugLib.h>
  11. #include <Library/HobLib.h>
  12. #include <Library/MemoryAllocationLib.h>
  13. #include <Library/UefiBootServicesTableLib.h>
  14. #include <Platform/Ac01.h>
  15. #include <Protocol/AcpiTable.h>
  16. // Required to be 1 to match the kernel quirk for ECAM
  17. #define EFI_ACPI_MCFG_OEM_REVISION 1
  18. STATIC AC01_ROOT_COMPLEX *mRootComplexList;
  19. #pragma pack(1)
  20. typedef struct
  21. {
  22. UINT64 BaseAddress;
  23. UINT16 SegGroupNum;
  24. UINT8 StartBusNum;
  25. UINT8 EndBusNum;
  26. UINT32 Reserved2;
  27. } EFI_MCFG_CONFIG_STRUCTURE;
  28. typedef struct
  29. {
  30. EFI_ACPI_DESCRIPTION_HEADER Header;
  31. UINT64 Reserved1;
  32. } EFI_MCFG_TABLE_CONFIG;
  33. #pragma pack()
  34. EFI_MCFG_TABLE_CONFIG mMcfgHeader = {
  35. {
  36. EFI_ACPI_6_1_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
  37. 0, // To be filled
  38. 1,
  39. 0x00, // Checksum will be updated at runtime
  40. EFI_ACPI_OEM_ID,
  41. EFI_ACPI_OEM_TABLE_ID,
  42. EFI_ACPI_MCFG_OEM_REVISION,
  43. EFI_ACPI_CREATOR_ID,
  44. EFI_ACPI_CREATOR_REVISION
  45. },
  46. 0x0000000000000000, // Reserved
  47. };
  48. EFI_MCFG_CONFIG_STRUCTURE mMcfgNodeTemplate = {
  49. .BaseAddress = 0,
  50. .SegGroupNum = 0,
  51. .StartBusNum = 0,
  52. .EndBusNum = 255,
  53. .Reserved2 = 0,
  54. };
  55. STATIC
  56. VOID
  57. ConstructMcfg (
  58. VOID *McfgBuffer,
  59. UINT32 McfgCount,
  60. INT32 *EnabledRCs
  61. )
  62. {
  63. AC01_ROOT_COMPLEX *RootComplex;
  64. UINT32 Idx;
  65. VOID *Iter = McfgBuffer;
  66. mMcfgHeader.Header.Length = McfgCount;
  67. CopyMem (Iter, &mMcfgHeader, sizeof (EFI_MCFG_TABLE_CONFIG));
  68. Iter += sizeof (EFI_MCFG_TABLE_CONFIG);
  69. for (Idx = 0; EnabledRCs[Idx] != -1; Idx++) {
  70. RootComplex = &mRootComplexList[EnabledRCs[Idx]];
  71. mMcfgNodeTemplate.BaseAddress = RootComplex->MmcfgBase;
  72. mMcfgNodeTemplate.SegGroupNum = RootComplex->Logical;
  73. CopyMem (Iter, &mMcfgNodeTemplate, sizeof (EFI_MCFG_CONFIG_STRUCTURE));
  74. Iter += sizeof (EFI_MCFG_CONFIG_STRUCTURE);
  75. }
  76. }
  77. EFI_STATUS
  78. EFIAPI
  79. AcpiInstallMcfg (
  80. VOID
  81. )
  82. {
  83. EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;
  84. EFI_STATUS Status;
  85. INT32 EnabledRCs[AC01_PCIE_MAX_ROOT_COMPLEX];
  86. UINT32 RcCount, McfgCount;
  87. UINT8 Idx;
  88. UINTN TableKey;
  89. VOID *Hob;
  90. VOID *McfgBuffer;
  91. Hob = GetFirstGuidHob (&gRootComplexInfoHobGuid);
  92. if (Hob == NULL) {
  93. return EFI_NOT_FOUND;
  94. }
  95. mRootComplexList = (AC01_ROOT_COMPLEX *)GET_GUID_HOB_DATA (Hob);
  96. for (Idx = 0, RcCount = 0; Idx < AC01_PCIE_MAX_ROOT_COMPLEX; Idx++) {
  97. if (mRootComplexList[Idx].Active) {
  98. EnabledRCs[RcCount++] = Idx;
  99. }
  100. }
  101. EnabledRCs[RcCount] = -1;
  102. Status = gBS->LocateProtocol (
  103. &gEfiAcpiTableProtocolGuid,
  104. NULL,
  105. (VOID **)&AcpiTableProtocol
  106. );
  107. if (EFI_ERROR (Status)) {
  108. DEBUG ((DEBUG_ERROR, "MCFG: Unable to locate ACPI table entry\n"));
  109. return Status;
  110. }
  111. McfgCount = sizeof (EFI_MCFG_TABLE_CONFIG) + sizeof (EFI_MCFG_CONFIG_STRUCTURE) * RcCount;
  112. McfgBuffer = AllocateZeroPool (McfgCount);
  113. if (McfgBuffer == NULL) {
  114. return EFI_OUT_OF_RESOURCES;
  115. }
  116. ConstructMcfg (McfgBuffer, McfgCount, EnabledRCs);
  117. Status = AcpiTableProtocol->InstallAcpiTable (
  118. AcpiTableProtocol,
  119. McfgBuffer,
  120. McfgCount,
  121. &TableKey
  122. );
  123. if (EFI_ERROR (Status)) {
  124. DEBUG ((DEBUG_ERROR, "MCFG: Unable to install MCFG table entry\n"));
  125. }
  126. FreePool (McfgBuffer);
  127. return Status;
  128. }