]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Fdt/FdtPciPcdProducerLib/FdtPciPcdProducerLib.c
OvmfPkg: Apply uncrustify changes
[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
ac0a286f
MK
25 UINT32 Type;\r
26 UINT64 ChildBase;\r
27 UINT64 CpuBase;\r
28 UINT64 Size;\r
c8f1a75a
AB
29} DTB_PCI_HOST_RANGE_RECORD;\r
30#pragma pack ()\r
31\r
ac0a286f
MK
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
c8f1a75a
AB
39\r
40STATIC\r
41RETURN_STATUS\r
42GetPciIoTranslation (\r
ac0a286f
MK
43 IN FDT_CLIENT_PROTOCOL *FdtClient,\r
44 IN INT32 Node,\r
45 OUT UINT64 *IoTranslation\r
c8f1a75a
AB
46 )\r
47{\r
ac0a286f
MK
48 UINT32 RecordIdx;\r
49 CONST VOID *Prop;\r
50 UINT32 Len;\r
51 EFI_STATUS Status;\r
52 UINT64 IoBase;\r
c8f1a75a
AB
53\r
54 //\r
55 // Iterate over "ranges".\r
56 //\r
57 Status = FdtClient->GetNodeProperty (FdtClient, Node, "ranges", &Prop, &Len);\r
ac0a286f
MK
58 if (EFI_ERROR (Status) || (Len == 0) ||\r
59 (Len % sizeof (DTB_PCI_HOST_RANGE_RECORD) != 0))\r
60 {\r
47719926 61 DEBUG ((DEBUG_ERROR, "%a: 'ranges' not found or invalid\n", __FUNCTION__));\r
c8f1a75a
AB
62 return RETURN_PROTOCOL_ERROR;\r
63 }\r
64\r
65 for (RecordIdx = 0; RecordIdx < Len / sizeof (DTB_PCI_HOST_RANGE_RECORD);\r
ac0a286f
MK
66 ++RecordIdx)\r
67 {\r
68 CONST DTB_PCI_HOST_RANGE_RECORD *Record;\r
69 UINT32 Type;\r
c8f1a75a
AB
70\r
71 Record = (CONST DTB_PCI_HOST_RANGE_RECORD *)Prop + RecordIdx;\r
ac0a286f 72 Type = SwapBytes32 (Record->Type) & DTB_PCI_HOST_RANGE_TYPEMASK;\r
c8f1a75a 73 if (Type == DTB_PCI_HOST_RANGE_IO) {\r
ac0a286f 74 IoBase = SwapBytes64 (Record->ChildBase);\r
c8f1a75a
AB
75 *IoTranslation = SwapBytes64 (Record->CpuBase) - IoBase;\r
76\r
77 return RETURN_SUCCESS;\r
78 }\r
79 }\r
ac0a286f 80\r
c8f1a75a
AB
81 return RETURN_NOT_FOUND;\r
82}\r
83\r
33ac4566
AB
84RETURN_STATUS\r
85EFIAPI\r
86FdtPciPcdProducerLibConstructor (\r
87 VOID\r
88 )\r
89{\r
ac0a286f
MK
90 UINT64 PciExpressBaseAddress;\r
91 FDT_CLIENT_PROTOCOL *FdtClient;\r
92 CONST UINT64 *Reg;\r
93 UINT32 RegSize;\r
94 EFI_STATUS Status;\r
95 INT32 Node;\r
96 RETURN_STATUS RetStatus;\r
97 UINT64 IoTranslation;\r
98 RETURN_STATUS PcdStatus;\r
33ac4566
AB
99\r
100 PciExpressBaseAddress = PcdGet64 (PcdPciExpressBaseAddress);\r
101 if (PciExpressBaseAddress != MAX_UINT64) {\r
c8f1a75a
AB
102 //\r
103 // Assume that the fact that PciExpressBaseAddress has been changed from\r
104 // its default value of MAX_UINT64 implies that this code has been\r
105 // executed already, in the context of another module. That means we can\r
106 // assume that PcdPciIoTranslation has been discovered from the DT node\r
107 // as well.\r
108 //\r
33ac4566
AB
109 return EFI_SUCCESS;\r
110 }\r
111\r
ac0a286f
MK
112 Status = gBS->LocateProtocol (\r
113 &gFdtClientProtocolGuid,\r
114 NULL,\r
115 (VOID **)&FdtClient\r
116 );\r
33ac4566
AB
117 ASSERT_EFI_ERROR (Status);\r
118\r
c8f1a75a 119 PciExpressBaseAddress = 0;\r
ac0a286f
MK
120 Status = FdtClient->FindCompatibleNode (\r
121 FdtClient,\r
122 "pci-host-ecam-generic",\r
123 &Node\r
124 );\r
c8f1a75a
AB
125\r
126 if (!EFI_ERROR (Status)) {\r
ac0a286f
MK
127 Status = FdtClient->GetNodeProperty (\r
128 FdtClient,\r
129 Node,\r
130 "reg",\r
131 (CONST VOID **)&Reg,\r
132 &RegSize\r
133 );\r
134\r
135 if (!EFI_ERROR (Status) && (RegSize == 2 * sizeof (UINT64))) {\r
c8f1a75a 136 PciExpressBaseAddress = SwapBytes64 (*Reg);\r
33ac4566 137\r
5d1546b4
LE
138 PcdStatus = PcdSetBoolS (PcdPciDisableBusEnumeration, FALSE);\r
139 ASSERT_RETURN_ERROR (PcdStatus);\r
33ac4566 140\r
70c368e2 141 IoTranslation = 0;\r
ac0a286f 142 RetStatus = GetPciIoTranslation (FdtClient, Node, &IoTranslation);\r
c8f1a75a 143 if (!RETURN_ERROR (RetStatus)) {\r
ac0a286f
MK
144 PcdStatus = PcdSet64S (PcdPciIoTranslation, IoTranslation);\r
145 ASSERT_RETURN_ERROR (PcdStatus);\r
c8f1a75a
AB
146 } else {\r
147 //\r
148 // Support for I/O BARs is not mandatory, and so it does not make sense\r
149 // to abort in the general case. So leave it up to the actual driver to\r
150 // complain about this if it wants to, and just issue a warning here.\r
151 //\r
ac0a286f
MK
152 DEBUG ((\r
153 DEBUG_WARN,\r
c8f1a75a 154 "%a: 'pci-host-ecam-generic' device encountered with no I/O range\n",\r
ac0a286f
MK
155 __FUNCTION__\r
156 ));\r
c8f1a75a
AB
157 }\r
158 }\r
33ac4566
AB
159 }\r
160\r
5d1546b4
LE
161 PcdStatus = PcdSet64S (PcdPciExpressBaseAddress, PciExpressBaseAddress);\r
162 ASSERT_RETURN_ERROR (PcdStatus);\r
33ac4566
AB
163\r
164 return RETURN_SUCCESS;\r
165}\r