TianoCore EDK2 master
Loading...
Searching...
No Matches
QemuFwCfgMmioPei.c
Go to the documentation of this file.
1
13#include <Uefi.h>
14
15#include <Library/BaseLib.h>
16#include <Library/DebugLib.h>
17#include <Library/IoLib.h>
20
21#include <libfdt.h>
22
24
33EFIAPI
35 VOID
36 )
37{
38 QEMU_FW_CFG_RESOURCE *FwCfgResource;
39
40 FwCfgResource = QemuGetFwCfgResourceHob ();
41 ASSERT (FwCfgResource != NULL);
42
43 return FwCfgResource->FwCfgSelectorAddress;
44}
45
54EFIAPI
56 VOID
57 )
58{
59 QEMU_FW_CFG_RESOURCE *FwCfgResource;
60
61 FwCfgResource = QemuGetFwCfgResourceHob ();
62 ASSERT (FwCfgResource != NULL);
63
64 return FwCfgResource->FwCfgDataAddress;
65}
66
75EFIAPI
77 VOID
78 )
79{
80 QEMU_FW_CFG_RESOURCE *FwCfgResource;
81
82 FwCfgResource = QemuGetFwCfgResourceHob ();
83 ASSERT (FwCfgResource != NULL);
84
85 return FwCfgResource->FwCfgDmaAddress;
86}
87
88RETURN_STATUS
89EFIAPI
90QemuFwCfgInitialize (
91 VOID
92 )
93{
94 VOID *DeviceTreeBase;
95 INT32 Node;
96 INT32 Prev;
97 UINT32 Signature;
98 CONST CHAR8 *Type;
99 INT32 Len;
100 CONST UINT64 *Reg;
101 UINT64 FwCfgSelectorAddress;
102 UINT64 FwCfgSelectorSize;
103 UINT64 FwCfgDataAddress;
104 UINT64 FwCfgDataSize;
105 UINT64 FwCfgDmaAddress;
106 UINT64 FwCfgDmaSize;
107 QEMU_FW_CFG_RESOURCE *FwCfgResource;
108
109 //
110 // Check whether the Qemu firmware configure resources HOB has been created,
111 // if so use the resources in the HOB.
112 //
113 FwCfgResource = QemuGetFwCfgResourceHob ();
114 if (FwCfgResource != NULL) {
115 return RETURN_SUCCESS;
116 }
117
118 DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);
119 ASSERT (DeviceTreeBase != NULL);
120 //
121 // Make sure we have a valid device tree blob
122 //
123 ASSERT (fdt_check_header (DeviceTreeBase) == 0);
124
125 //
126 // Create resouce memory
127 //
128 FwCfgResource = AllocateZeroPool (sizeof (QEMU_FW_CFG_RESOURCE));
129 ASSERT (FwCfgResource != NULL);
130
131 for (Prev = 0; ; Prev = Node) {
132 Node = fdt_next_node (DeviceTreeBase, Prev, NULL);
133 if (Node < 0) {
134 break;
135 }
136
137 //
138 // Check for memory node
139 //
140 Type = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len);
141 if ((Type != NULL) &&
142 (AsciiStrnCmp (Type, "qemu,fw-cfg-mmio", Len) == 0))
143 {
144 //
145 // Get the 'reg' property of this node. For now, we will assume
146 // two 8 byte quantities for base and size, respectively.
147 //
148 Reg = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);
149 if ((Reg != 0) && (Len == (2 * sizeof (UINT64)))) {
150 FwCfgDataAddress = SwapBytes64 (Reg[0]);
151 FwCfgDataSize = 8;
152 FwCfgSelectorAddress = FwCfgDataAddress + FwCfgDataSize;
153 FwCfgSelectorSize = 2;
154
155 //
156 // The following ASSERT()s express
157 //
158 // Address + Size - 1 <= MAX_UINTN
159 //
160 // for both registers, that is, that the last byte in each MMIO range is
161 // expressible as a MAX_UINTN. The form below is mathematically
162 // equivalent, and it also prevents any unsigned overflow before the
163 // comparison.
164 //
165 ASSERT (FwCfgSelectorAddress <= MAX_UINTN - FwCfgSelectorSize + 1);
166 ASSERT (FwCfgDataAddress <= MAX_UINTN - FwCfgDataSize + 1);
167
168 FwCfgResource->FwCfgSelectorAddress = FwCfgSelectorAddress;
169 FwCfgResource->FwCfgDataAddress = FwCfgDataAddress;
170
171 DEBUG ((
172 DEBUG_INFO,
173 "Found FwCfg @ 0x%Lx/0x%Lx\n",
174 FwCfgSelectorAddress,
175 FwCfgDataAddress
176 ));
177
178 if (SwapBytes64 (Reg[1]) >= 0x18) {
179 FwCfgDmaAddress = FwCfgDataAddress + 0x10;
180 FwCfgDmaSize = 0x08;
181
182 //
183 // See explanation above.
184 //
185 ASSERT (FwCfgDmaAddress <= MAX_UINTN - FwCfgDmaSize + 1);
186
187 DEBUG ((DEBUG_INFO, "Found FwCfg DMA @ 0x%Lx\n", FwCfgDmaAddress));
188 FwCfgResource->FwCfgDmaAddress = FwCfgDmaAddress;
189 } else {
190 FwCfgDmaAddress = 0;
191 }
192
193 if ((FwCfgSelectorAddress != 0) && (FwCfgDataAddress != 0)) {
194 //
195 // Select Item Signature
196 //
197 MmioWrite16 (FwCfgSelectorAddress, SwapBytes16 ((UINT16)QemuFwCfgItemSignature));
198
199 //
200 // Readout the Signature.
201 //
202 Signature = MmioRead32 (FwCfgDataAddress);
203
204 if (Signature == SIGNATURE_32 ('Q', 'E', 'M', 'U')) {
205 //
206 // Build the firmware configure resource HOB.
207 //
208 QemuBuildFwCfgResourceHob (FwCfgResource);
209 } else {
210 FwCfgResource->FwCfgDataAddress = 0;
211 FwCfgResource->FwCfgSelectorAddress = 0;
212 FwCfgResource->FwCfgDmaAddress = 0;
213
214 DEBUG ((
215 DEBUG_ERROR,
216 "%a: Signature dose not match QEMU!\n",
217 __func__
218 ));
219 break;
220 }
221 }
222
223 break;
224 } else {
225 DEBUG ((
226 DEBUG_ERROR,
227 "%a: Failed to parse FDT QemuCfg node\n",
228 __func__
229 ));
230 break;
231 }
232 }
233 }
234
235 return RETURN_SUCCESS;
236}
UINT64 UINTN
UINT16 EFIAPI SwapBytes16(IN UINT16 Value)
Definition: SwapBytes16.c:25
INTN EFIAPI AsciiStrnCmp(IN CONST CHAR8 *FirstString, IN CONST CHAR8 *SecondString, IN UINTN Length)
Definition: String.c:872
UINT64 EFIAPI SwapBytes64(IN UINT64 Value)
Definition: SwapBytes64.c:25
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
UINT32 EFIAPI MmioRead32(IN UINTN Address)
Definition: IoLib.c:262
UINT16 EFIAPI MmioWrite16(IN UINTN Address, IN UINT16 Value)
Definition: IoLib.c:216
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define RETURN_SUCCESS
Definition: Base.h:1066
#define SIGNATURE_32(A, B, C, D)
Definition: Base.h:1310
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define PcdGet64(TokenName)
Definition: PcdLib.h:375
QEMU_FW_CFG_RESOURCE * QemuGetFwCfgResourceHob(VOID)
VOID QemuBuildFwCfgResourceHob(IN QEMU_FW_CFG_RESOURCE *FwCfgResource)
UINTN EFIAPI QemuGetFwCfgDmaAddress(VOID)
UINTN EFIAPI QemuGetFwCfgDataAddress(VOID)
UINTN EFIAPI QemuGetFwCfgSelectorAddress(VOID)