]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Fdt/FdtPciPcdProducerLib/FdtPciPcdProducerLib.c
OvmfPkg: Change use of EFI_D_* to DEBUG_*
[mirror_edk2.git] / OvmfPkg / Fdt / FdtPciPcdProducerLib / FdtPciPcdProducerLib.c
CommitLineData
33ac4566
AB
1/** @file\r
2 FDT client library for consumers of PCI related dynamic PCDs\r
3\r
4 Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>\r
5\r
9792fb0e 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
33ac4566
AB
7\r
8**/\r
9\r
10#include <Uefi.h>\r
11\r
12#include <Library/BaseLib.h>\r
13#include <Library/DebugLib.h>\r
14#include <Library/PcdLib.h>\r
15#include <Library/UefiBootServicesTableLib.h>\r
16\r
17#include <Protocol/FdtClient.h>\r
18\r
c8f1a75a
AB
19//\r
20// We expect the "ranges" property of "pci-host-ecam-generic" to consist of\r
21// records like this.\r
22//\r
23#pragma pack (1)\r
24typedef struct {\r
25 UINT32 Type;\r
26 UINT64 ChildBase;\r
27 UINT64 CpuBase;\r
28 UINT64 Size;\r
29} DTB_PCI_HOST_RANGE_RECORD;\r
30#pragma pack ()\r
31\r
32#define DTB_PCI_HOST_RANGE_RELOCATABLE BIT31\r
33#define DTB_PCI_HOST_RANGE_PREFETCHABLE BIT30\r
34#define DTB_PCI_HOST_RANGE_ALIASED BIT29\r
35#define DTB_PCI_HOST_RANGE_MMIO32 BIT25\r
36#define DTB_PCI_HOST_RANGE_MMIO64 (BIT25 | BIT24)\r
37#define DTB_PCI_HOST_RANGE_IO BIT24\r
38#define DTB_PCI_HOST_RANGE_TYPEMASK (BIT31 | BIT30 | BIT29 | BIT25 | BIT24)\r
39\r
40STATIC\r
41RETURN_STATUS\r
42GetPciIoTranslation (\r
43 IN FDT_CLIENT_PROTOCOL *FdtClient,\r
44 IN INT32 Node,\r
45 OUT UINT64 *IoTranslation\r
46 )\r
47{\r
48 UINT32 RecordIdx;\r
49 CONST VOID *Prop;\r
50 UINT32 Len;\r
51 EFI_STATUS Status;\r
52 UINT64 IoBase;\r
53\r
54 //\r
55 // Iterate over "ranges".\r
56 //\r
57 Status = FdtClient->GetNodeProperty (FdtClient, Node, "ranges", &Prop, &Len);\r
58 if (EFI_ERROR (Status) || Len == 0 ||\r
59 Len % sizeof (DTB_PCI_HOST_RANGE_RECORD) != 0) {\r
47719926 60 DEBUG ((DEBUG_ERROR, "%a: 'ranges' not found or invalid\n", __FUNCTION__));\r
c8f1a75a
AB
61 return RETURN_PROTOCOL_ERROR;\r
62 }\r
63\r
64 for (RecordIdx = 0; RecordIdx < Len / sizeof (DTB_PCI_HOST_RANGE_RECORD);\r
65 ++RecordIdx) {\r
66 CONST DTB_PCI_HOST_RANGE_RECORD *Record;\r
67 UINT32 Type;\r
68\r
69 Record = (CONST DTB_PCI_HOST_RANGE_RECORD *)Prop + RecordIdx;\r
70 Type = SwapBytes32 (Record->Type) & DTB_PCI_HOST_RANGE_TYPEMASK;\r
71 if (Type == DTB_PCI_HOST_RANGE_IO) {\r
72 IoBase = SwapBytes64 (Record->ChildBase);\r
73 *IoTranslation = SwapBytes64 (Record->CpuBase) - IoBase;\r
74\r
75 return RETURN_SUCCESS;\r
76 }\r
77 }\r
78 return RETURN_NOT_FOUND;\r
79}\r
80\r
33ac4566
AB
81RETURN_STATUS\r
82EFIAPI\r
83FdtPciPcdProducerLibConstructor (\r
84 VOID\r
85 )\r
86{\r
87 UINT64 PciExpressBaseAddress;\r
88 FDT_CLIENT_PROTOCOL *FdtClient;\r
89 CONST UINT64 *Reg;\r
c8f1a75a 90 UINT32 RegSize;\r
33ac4566 91 EFI_STATUS Status;\r
c8f1a75a
AB
92 INT32 Node;\r
93 RETURN_STATUS RetStatus;\r
94 UINT64 IoTranslation;\r
5d1546b4 95 RETURN_STATUS PcdStatus;\r
33ac4566
AB
96\r
97 PciExpressBaseAddress = PcdGet64 (PcdPciExpressBaseAddress);\r
98 if (PciExpressBaseAddress != MAX_UINT64) {\r
c8f1a75a
AB
99 //\r
100 // Assume that the fact that PciExpressBaseAddress has been changed from\r
101 // its default value of MAX_UINT64 implies that this code has been\r
102 // executed already, in the context of another module. That means we can\r
103 // assume that PcdPciIoTranslation has been discovered from the DT node\r
104 // as well.\r
105 //\r
33ac4566
AB
106 return EFI_SUCCESS;\r
107 }\r
108\r
109 Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,\r
110 (VOID **)&FdtClient);\r
111 ASSERT_EFI_ERROR (Status);\r
112\r
c8f1a75a
AB
113 PciExpressBaseAddress = 0;\r
114 Status = FdtClient->FindCompatibleNode (FdtClient, "pci-host-ecam-generic",\r
115 &Node);\r
116\r
117 if (!EFI_ERROR (Status)) {\r
118 Status = FdtClient->GetNodeProperty (FdtClient, Node, "reg",\r
119 (CONST VOID **)&Reg, &RegSize);\r
120\r
121 if (!EFI_ERROR (Status) && RegSize == 2 * sizeof (UINT64)) {\r
122 PciExpressBaseAddress = SwapBytes64 (*Reg);\r
33ac4566 123\r
5d1546b4
LE
124 PcdStatus = PcdSetBoolS (PcdPciDisableBusEnumeration, FALSE);\r
125 ASSERT_RETURN_ERROR (PcdStatus);\r
33ac4566 126\r
70c368e2 127 IoTranslation = 0;\r
c8f1a75a
AB
128 RetStatus = GetPciIoTranslation (FdtClient, Node, &IoTranslation);\r
129 if (!RETURN_ERROR (RetStatus)) {\r
5d1546b4
LE
130 PcdStatus = PcdSet64S (PcdPciIoTranslation, IoTranslation);\r
131 ASSERT_RETURN_ERROR (PcdStatus);\r
c8f1a75a
AB
132 } else {\r
133 //\r
134 // Support for I/O BARs is not mandatory, and so it does not make sense\r
135 // to abort in the general case. So leave it up to the actual driver to\r
136 // complain about this if it wants to, and just issue a warning here.\r
137 //\r
47719926 138 DEBUG ((DEBUG_WARN,\r
c8f1a75a
AB
139 "%a: 'pci-host-ecam-generic' device encountered with no I/O range\n",\r
140 __FUNCTION__));\r
141 }\r
142 }\r
33ac4566
AB
143 }\r
144\r
5d1546b4
LE
145 PcdStatus = PcdSet64S (PcdPciExpressBaseAddress, PciExpressBaseAddress);\r
146 ASSERT_RETURN_ERROR (PcdStatus);\r
33ac4566
AB
147\r
148 return RETURN_SUCCESS;\r
149}\r