Expose the UID value to GeneratePciSlots(). This is needed for some cases for example: https://docs.microsoft.com/en-us/windows-hardware/drivers/pci/dsd-for-pcie-root-ports#identifying-externally-exposed-pcie-root-ports Name (_DSD, Package () { ToUUID("EFCC06CC-73AC-4BC3-BFF0-76143807C389"), Package () { Package (2) {"ExternalFacingPort", 1}, Package (2) {"UID", 0}, } }) Signed-off-by: Jeff Brasen <jbrasen@nvidia.com> Reviewed-by: Pierre Gondois <pierre.gondois@arm.com> Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>
		
			
				
	
	
		
			203 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			203 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   SSDT PCIe Support Library.
 | |
| 
 | |
|   Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.<BR>
 | |
| 
 | |
|   SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
|   @par Reference(s):
 | |
|   - PCI Firmware Specification - Revision 3.0
 | |
|   - ACPI 6.4 specification:
 | |
|    - s6.2.13 "_PRT (PCI Routing Table)"
 | |
|    - s6.1.1 "_ADR (Address)"
 | |
|   - linux kernel code
 | |
|   - Arm Base Boot Requirements v1.0
 | |
|   - Arm Base System Architecture v1.0
 | |
| **/
 | |
| 
 | |
| #include <Library/AcpiLib.h>
 | |
| #include <Library/BaseLib.h>
 | |
| #include <Library/BaseMemoryLib.h>
 | |
| #include <Library/DebugLib.h>
 | |
| #include <Library/MemoryAllocationLib.h>
 | |
| #include <Protocol/AcpiTable.h>
 | |
| 
 | |
| // Module specific include files.
 | |
| #include <AcpiTableGenerator.h>
 | |
| #include <ConfigurationManagerObject.h>
 | |
| #include <ConfigurationManagerHelper.h>
 | |
| #include <Library/AcpiHelperLib.h>
 | |
| #include <Library/TableHelperLib.h>
 | |
| #include <Library/AmlLib/AmlLib.h>
 | |
| #include <Library/SsdtPcieSupportLib.h>
 | |
| #include <Protocol/ConfigurationManagerProtocol.h>
 | |
| 
 | |
| #include "SsdtPcieSupportLibPrivate.h"
 | |
| 
 | |
| /** Generate Pci slots devices.
 | |
| 
 | |
|   PCI Firmware Specification - Revision 3.3,
 | |
|   s4.8 "Generic ACPI PCI Slot Description" requests to describe the PCI slot
 | |
|   used. It should be possible to enumerate them, but this is additional
 | |
|   information.
 | |
| 
 | |
|   @param [in]       PciInfo       Pci device information.
 | |
|   @param [in]       MappingTable  The mapping table structure.
 | |
|   @param [in]       Uid           Unique Id of the Pci device.
 | |
|   @param [in, out]  PciNode       Pci node to amend.
 | |
| 
 | |
|   @retval EFI_SUCCESS            Success.
 | |
|   @retval EFI_INVALID_PARAMETER  Invalid parameter.
 | |
|   @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| GeneratePciSlots (
 | |
|   IN      CONST CM_ARM_PCI_CONFIG_SPACE_INFO  *PciInfo,
 | |
|   IN      CONST MAPPING_TABLE                 *MappingTable,
 | |
|   IN            UINT32                        Uid,
 | |
|   IN  OUT       AML_OBJECT_NODE_HANDLE        PciNode
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS              Status;
 | |
|   UINT32                  Index;
 | |
|   UINT32                  LastIndex;
 | |
|   UINT32                  DeviceId;
 | |
|   CHAR8                   AslName[AML_NAME_SEG_SIZE + 1];
 | |
|   AML_OBJECT_NODE_HANDLE  DeviceNode;
 | |
| 
 | |
|   ASSERT (MappingTable != NULL);
 | |
|   ASSERT (PciNode != NULL);
 | |
| 
 | |
|   // Generic device name is "Dxx".
 | |
|   CopyMem (AslName, "Dxx_", AML_NAME_SEG_SIZE + 1);
 | |
| 
 | |
|   LastIndex = MappingTable->LastIndex;
 | |
| 
 | |
|   // There are at most 32 devices on a Pci bus.
 | |
|   if (LastIndex >= 32) {
 | |
|     ASSERT (0);
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   for (Index = 0; Index < LastIndex; Index++) {
 | |
|     DeviceId                       = MappingTable->Table[Index];
 | |
|     AslName[AML_NAME_SEG_SIZE - 3] = AsciiFromHex (DeviceId & 0xF);
 | |
|     AslName[AML_NAME_SEG_SIZE - 2] = AsciiFromHex ((DeviceId >> 4) & 0xF);
 | |
| 
 | |
|     // ASL:
 | |
|     // Device (Dxx) {
 | |
|     //   Name (_ADR, <address value>)
 | |
|     // }
 | |
|     Status = AmlCodeGenDevice (AslName, PciNode, &DeviceNode);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       ASSERT (0);
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     /* ACPI 6.4 specification, Table 6.2: "ADR Object Address Encodings"
 | |
|        High word-Device #, Low word-Function #. (for example, device 3,
 | |
|        function 2 is 0x00030002). To refer to all the functions on a device #,
 | |
|        use a function number of FFFF).
 | |
|     */
 | |
|     Status = AmlCodeGenNameInteger (
 | |
|                "_ADR",
 | |
|                (DeviceId << 16) | 0xFFFF,
 | |
|                DeviceNode,
 | |
|                NULL
 | |
|                );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       ASSERT (0);
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     // _SUN object is not generated as we don't know which slot will be used.
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /** Add an _OSC template method to the PciNode.
 | |
| 
 | |
|   The _OSC method is provided as an AML blob. The blob is
 | |
|   parsed and attached at the end of the PciNode list of variable elements.
 | |
| 
 | |
|   @param [in]       PciInfo     Pci device information.
 | |
|   @param [in, out]  PciNode     Pci node to amend.
 | |
| 
 | |
|   @retval EFI_SUCCESS             The function completed successfully.
 | |
|   @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | |
|   @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| AddOscMethod (
 | |
|   IN      CONST CM_ARM_PCI_CONFIG_SPACE_INFO  *PciInfo,
 | |
|   IN  OUT   AML_OBJECT_NODE_HANDLE            PciNode
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                   Status;
 | |
|   EFI_STATUS                   Status1;
 | |
|   EFI_ACPI_DESCRIPTION_HEADER  *SsdtPcieOscTemplate;
 | |
|   AML_ROOT_NODE_HANDLE         OscTemplateRoot;
 | |
|   AML_OBJECT_NODE_HANDLE       OscNode;
 | |
| 
 | |
|   ASSERT (PciNode != NULL);
 | |
| 
 | |
|   // Parse the Ssdt Pci Osc Template.
 | |
|   SsdtPcieOscTemplate = (EFI_ACPI_DESCRIPTION_HEADER *)
 | |
|                         ssdtpcieosctemplate_aml_code;
 | |
| 
 | |
|   OscNode         = NULL;
 | |
|   OscTemplateRoot = NULL;
 | |
|   Status          = AmlParseDefinitionBlock (
 | |
|                       SsdtPcieOscTemplate,
 | |
|                       &OscTemplateRoot
 | |
|                       );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((
 | |
|       DEBUG_ERROR,
 | |
|       "ERROR: SSDT-PCI-OSC: Failed to parse SSDT PCI OSC Template."
 | |
|       " Status = %r\n",
 | |
|       Status
 | |
|       ));
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Status = AmlFindNode (OscTemplateRoot, "\\_OSC", &OscNode);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto error_handler;
 | |
|   }
 | |
| 
 | |
|   Status = AmlDetachNode (OscNode);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto error_handler;
 | |
|   }
 | |
| 
 | |
|   Status = AmlAttachNode (PciNode, OscNode);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     // Free the detached node.
 | |
|     AmlDeleteTree (OscNode);
 | |
|     goto error_handler;
 | |
|   }
 | |
| 
 | |
| error_handler:
 | |
|   // Cleanup
 | |
|   Status1 = AmlDeleteTree (OscTemplateRoot);
 | |
|   if (EFI_ERROR (Status1)) {
 | |
|     DEBUG ((
 | |
|       DEBUG_ERROR,
 | |
|       "ERROR: SSDT-PCI-OSC: Failed to cleanup AML tree."
 | |
|       " Status = %r\n",
 | |
|       Status1
 | |
|       ));
 | |
|     // If Status was success but we failed to delete the AML Tree
 | |
|     // return Status1 else return the original error code, i.e. Status.
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       return Status1;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 |