TianoCore EDK2 master
Loading...
Searching...
No Matches
QemuFwCfgMmioDxe.c
Go to the documentation of this file.
1
13#include <Uefi.h>
14
15#include <Library/BaseLib.h>
16#include <Library/DebugLib.h>
19
20#include <Protocol/FdtClient.h>
21
23
24STATIC UINTN mFwCfgSelectorAddress;
25STATIC UINTN mFwCfgDataAddress;
26STATIC UINTN mFwCfgDmaAddress;
27
36EFIAPI
38 VOID
39 )
40{
41 return mFwCfgSelectorAddress;
42}
43
52EFIAPI
54 VOID
55 )
56{
57 return mFwCfgDataAddress;
58}
59
68EFIAPI
70 VOID
71 )
72{
73 return mFwCfgDmaAddress;
74}
75
76RETURN_STATUS
77EFIAPI
78QemuFwCfgInitialize (
79 VOID
80 )
81{
82 EFI_STATUS Status;
83 FDT_CLIENT_PROTOCOL *FdtClient;
84 CONST UINT64 *Reg;
85 UINT32 RegSize;
86 UINTN AddressCells, SizeCells;
87 UINT64 FwCfgSelectorAddress;
88 UINT64 FwCfgSelectorSize;
89 UINT64 FwCfgDataAddress;
90 UINT64 FwCfgDataSize;
91 UINT64 FwCfgDmaAddress;
92 UINT64 FwCfgDmaSize;
93 QEMU_FW_CFG_RESOURCE *FwCfgResource;
94
95 //
96 // Check whether the Qemu firmware configure resources HOB has been created,
97 // if so use the resources in the HOB.
98 //
99 FwCfgResource = QemuGetFwCfgResourceHob ();
100 if (FwCfgResource != NULL) {
101 mFwCfgSelectorAddress = FwCfgResource->FwCfgSelectorAddress;
102 mFwCfgDataAddress = FwCfgResource->FwCfgDataAddress;
103 mFwCfgDmaAddress = FwCfgResource->FwCfgDmaAddress;
104
105 if (mFwCfgDmaAddress != 0) {
106 InternalQemuFwCfgReadBytes = DmaReadBytes;
107 InternalQemuFwCfgWriteBytes = DmaWriteBytes;
108 InternalQemuFwCfgSkipBytes = DmaSkipBytes;
109 }
110
111 return RETURN_SUCCESS;
112 }
113
114 Status = gBS->LocateProtocol (
115 &gFdtClientProtocolGuid,
116 NULL,
117 (VOID **)&FdtClient
118 );
119 ASSERT_EFI_ERROR (Status);
120
121 Status = FdtClient->FindCompatibleNodeReg (
122 FdtClient,
123 "qemu,fw-cfg-mmio",
124 (CONST VOID **)&Reg,
125 &AddressCells,
126 &SizeCells,
127 &RegSize
128 );
129 if (EFI_ERROR (Status)) {
130 DEBUG ((
131 DEBUG_WARN,
132 "%a: No 'qemu,fw-cfg-mmio' compatible DT node found (Status == %r)\n",
133 __func__,
134 Status
135 ));
136 return EFI_SUCCESS;
137 }
138
139 ASSERT (AddressCells == 2);
140 ASSERT (SizeCells == 2);
141 ASSERT (RegSize == 2 * sizeof (UINT64));
142
143 FwCfgDataAddress = SwapBytes64 (Reg[0]);
144 FwCfgDataSize = 8;
145 FwCfgSelectorAddress = FwCfgDataAddress + FwCfgDataSize;
146 FwCfgSelectorSize = 2;
147
148 //
149 // The following ASSERT()s express
150 //
151 // Address + Size - 1 <= MAX_UINTN
152 //
153 // for both registers, that is, that the last byte in each MMIO range is
154 // expressible as a MAX_UINTN. The form below is mathematically
155 // equivalent, and it also prevents any unsigned overflow before the
156 // comparison.
157 //
158 ASSERT (FwCfgSelectorAddress <= MAX_UINTN - FwCfgSelectorSize + 1);
159 ASSERT (FwCfgDataAddress <= MAX_UINTN - FwCfgDataSize + 1);
160
161 mFwCfgSelectorAddress = FwCfgSelectorAddress;
162 mFwCfgDataAddress = FwCfgDataAddress;
163
164 DEBUG ((
165 DEBUG_INFO,
166 "Found FwCfg @ 0x%Lx/0x%Lx\n",
167 FwCfgSelectorAddress,
168 FwCfgDataAddress
169 ));
170
171 if (SwapBytes64 (Reg[1]) >= 0x18) {
172 FwCfgDmaAddress = FwCfgDataAddress + 0x10;
173 FwCfgDmaSize = 0x08;
174
175 //
176 // See explanation above.
177 //
178 ASSERT (FwCfgDmaAddress <= MAX_UINTN - FwCfgDmaSize + 1);
179
180 DEBUG ((DEBUG_INFO, "Found FwCfg DMA @ 0x%Lx\n", FwCfgDmaAddress));
181 } else {
182 FwCfgDmaAddress = 0;
183 }
184
185 if (QemuFwCfgIsAvailable ()) {
186 UINT32 Signature;
187
188 QemuFwCfgSelectItem (QemuFwCfgItemSignature);
189 Signature = QemuFwCfgRead32 ();
190 if (Signature == SIGNATURE_32 ('Q', 'E', 'M', 'U')) {
191 //
192 // For DMA support, we require the DTB to advertise the register, and the
193 // feature bitmap (which we read without DMA) to confirm the feature.
194 //
195 if (FwCfgDmaAddress != 0) {
196 UINT32 Features;
197
198 QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion);
199 Features = QemuFwCfgRead32 ();
200 if ((Features & FW_CFG_F_DMA) != 0) {
201 mFwCfgDmaAddress = FwCfgDmaAddress;
202 InternalQemuFwCfgReadBytes = DmaReadBytes;
203 InternalQemuFwCfgWriteBytes = DmaWriteBytes;
204 InternalQemuFwCfgSkipBytes = DmaSkipBytes;
205 }
206 }
207 } else {
208 mFwCfgSelectorAddress = 0;
209 mFwCfgDataAddress = 0;
210 }
211 }
212
213 return RETURN_SUCCESS;
214}
UINT64 UINTN
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_SUCCESS
Definition: Base.h:1066
#define SIGNATURE_32(A, B, C, D)
Definition: Base.h:1310
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
UINT32 EFIAPI QemuFwCfgRead32(VOID)
Definition: QemuFwCfgLib.c:205
VOID EFIAPI QemuFwCfgSelectItem(IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem)
Definition: QemuFwCfgLib.c:33
BOOLEAN EFIAPI QemuFwCfgIsAvailable(VOID)
Definition: QemuFwCfgDxe.c:44
VOID EFIAPI DmaSkipBytes(IN UINTN Size)
QEMU_FW_CFG_RESOURCE * QemuGetFwCfgResourceHob(VOID)
VOID EFIAPI DmaReadBytes(IN UINTN Size, IN VOID *Buffer OPTIONAL)
VOID EFIAPI DmaWriteBytes(IN UINTN Size, IN VOID *Buffer OPTIONAL)
UINTN EFIAPI QemuGetFwCfgDmaAddress(VOID)
UINTN EFIAPI QemuGetFwCfgDataAddress(VOID)
UINTN EFIAPI QemuGetFwCfgSelectorAddress(VOID)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS