TianoCore EDK2 master
Loading...
Searching...
No Matches
FdtPciPcdProducerLib.c
Go to the documentation of this file.
1
10#include <Uefi.h>
11
12#include <Library/BaseLib.h>
13#include <Library/DebugLib.h>
14#include <Library/PcdLib.h>
16
17#include <Protocol/FdtClient.h>
18
19//
20// We expect the "ranges" property of "pci-host-ecam-generic" to consist of
21// records like this.
22//
23#pragma pack (1)
24typedef struct {
25 UINT32 Type;
26 UINT64 ChildBase;
27 UINT64 CpuBase;
28 UINT64 Size;
30#pragma pack ()
31
32#define DTB_PCI_HOST_RANGE_RELOCATABLE BIT31
33#define DTB_PCI_HOST_RANGE_PREFETCHABLE BIT30
34#define DTB_PCI_HOST_RANGE_ALIASED BIT29
35#define DTB_PCI_HOST_RANGE_MMIO32 BIT25
36#define DTB_PCI_HOST_RANGE_MMIO64 (BIT25 | BIT24)
37#define DTB_PCI_HOST_RANGE_IO BIT24
38#define DTB_PCI_HOST_RANGE_TYPEMASK (BIT31 | BIT30 | BIT29 | BIT25 | BIT24)
39
41RETURN_STATUS
42GetPciIoTranslation (
43 IN FDT_CLIENT_PROTOCOL *FdtClient,
44 IN INT32 Node,
45 OUT UINT64 *IoTranslation
46 )
47{
48 UINT32 RecordIdx;
49 CONST VOID *Prop;
50 UINT32 Len;
51 EFI_STATUS Status;
52 UINT64 IoBase;
53
54 //
55 // Iterate over "ranges".
56 //
57 Status = FdtClient->GetNodeProperty (FdtClient, Node, "ranges", &Prop, &Len);
58 if (EFI_ERROR (Status) || (Len == 0) ||
59 (Len % sizeof (DTB_PCI_HOST_RANGE_RECORD) != 0))
60 {
61 DEBUG ((DEBUG_ERROR, "%a: 'ranges' not found or invalid\n", __func__));
63 }
64
65 for (RecordIdx = 0; RecordIdx < Len / sizeof (DTB_PCI_HOST_RANGE_RECORD);
66 ++RecordIdx)
67 {
69 UINT32 Type;
70
71 Record = (CONST DTB_PCI_HOST_RANGE_RECORD *)Prop + RecordIdx;
72 Type = SwapBytes32 (Record->Type) & DTB_PCI_HOST_RANGE_TYPEMASK;
73 if (Type == DTB_PCI_HOST_RANGE_IO) {
74 IoBase = SwapBytes64 (Record->ChildBase);
75 *IoTranslation = SwapBytes64 (Record->CpuBase) - IoBase;
76
77 return RETURN_SUCCESS;
78 }
79 }
80
81 return RETURN_NOT_FOUND;
82}
83
84RETURN_STATUS
85EFIAPI
86FdtPciPcdProducerLibConstructor (
87 VOID
88 )
89{
90 UINT64 PciExpressBaseAddress;
91 FDT_CLIENT_PROTOCOL *FdtClient;
92 CONST UINT64 *Reg;
93 UINT32 RegSize;
94 EFI_STATUS Status;
95 INT32 Node;
96 RETURN_STATUS RetStatus;
97 UINT64 IoTranslation;
98 RETURN_STATUS PcdStatus;
99
100 PciExpressBaseAddress = PcdGet64 (PcdPciExpressBaseAddress);
101 if (PciExpressBaseAddress != MAX_UINT64) {
102 //
103 // Assume that the fact that PciExpressBaseAddress has been changed from
104 // its default value of MAX_UINT64 implies that this code has been
105 // executed already, in the context of another module. That means we can
106 // assume that PcdPciIoTranslation has been discovered from the DT node
107 // as well.
108 //
109 return EFI_SUCCESS;
110 }
111
112 Status = gBS->LocateProtocol (
113 &gFdtClientProtocolGuid,
114 NULL,
115 (VOID **)&FdtClient
116 );
117 ASSERT_EFI_ERROR (Status);
118
119 PciExpressBaseAddress = 0;
120 Status = FdtClient->FindCompatibleNode (
121 FdtClient,
122 "pci-host-ecam-generic",
123 &Node
124 );
125
126 if (!EFI_ERROR (Status)) {
127 Status = FdtClient->GetNodeProperty (
128 FdtClient,
129 Node,
130 "reg",
131 (CONST VOID **)&Reg,
132 &RegSize
133 );
134
135 if (!EFI_ERROR (Status) && (RegSize == 2 * sizeof (UINT64))) {
136 PciExpressBaseAddress = SwapBytes64 (*Reg);
137
138 PcdStatus = PcdSetBoolS (PcdPciDisableBusEnumeration, FALSE);
139 ASSERT_RETURN_ERROR (PcdStatus);
140
141 IoTranslation = 0;
142 RetStatus = GetPciIoTranslation (FdtClient, Node, &IoTranslation);
143 if (!RETURN_ERROR (RetStatus)) {
144 PcdStatus = PcdSet64S (PcdPciIoTranslation, IoTranslation);
145 ASSERT_RETURN_ERROR (PcdStatus);
146 } else {
147 //
148 // Support for I/O BARs is not mandatory, and so it does not make sense
149 // to abort in the general case. So leave it up to the actual driver to
150 // complain about this if it wants to, and just issue a warning here.
151 //
152 DEBUG ((
153 DEBUG_WARN,
154 "%a: 'pci-host-ecam-generic' device encountered with no I/O range\n",
155 __func__
156 ));
157 }
158 }
159 }
160
161 PcdStatus = PcdSet64S (PcdPciExpressBaseAddress, PciExpressBaseAddress);
162 ASSERT_RETURN_ERROR (PcdStatus);
163
164 return RETURN_SUCCESS;
165}
UINT32 EFIAPI SwapBytes32(IN UINT32 Value)
Definition: SwapBytes32.c:25
UINT64 EFIAPI SwapBytes64(IN UINT64 Value)
Definition: SwapBytes64.c:25
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define RETURN_PROTOCOL_ERROR
Definition: Base.h:1192
#define RETURN_ERROR(StatusCode)
Definition: Base.h:1061
#define RETURN_NOT_FOUND
Definition: Base.h:1142
#define RETURN_SUCCESS
Definition: Base.h:1066
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define ASSERT_RETURN_ERROR(StatusParameter)
Definition: DebugLib.h:493
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define PcdGet64(TokenName)
Definition: PcdLib.h:375
#define PcdSetBoolS(TokenName, Value)
Definition: PcdLib.h:549
#define PcdSet64S(TokenName, Value)
Definition: PcdLib.h:511
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS