]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c
OvmfPkg/PciHostBridgeLib: clear PCI aperture vars for (re)init
[mirror_edk2.git] / OvmfPkg / Library / QemuFwCfgLib / QemuFwCfgPei.c
... / ...
CommitLineData
1/** @file\r
2\r
3 Stateful and implicitly initialized fw_cfg library implementation.\r
4\r
5 Copyright (C) 2013, Red Hat, Inc.\r
6 Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>\r
7 Copyright (c) 2017, Advanced Micro Devices. All rights reserved.<BR>\r
8\r
9 This program and the accompanying materials are licensed and made available\r
10 under the terms and conditions of the BSD License which accompanies this\r
11 distribution. The full text of the license may be found at\r
12 http://opensource.org/licenses/bsd-license.php\r
13\r
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
15 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
16**/\r
17\r
18#include <Library/BaseLib.h>\r
19#include <Library/IoLib.h>\r
20#include <Library/DebugLib.h>\r
21#include <Library/QemuFwCfgLib.h>\r
22#include <Library/MemEncryptSevLib.h>\r
23\r
24#include "QemuFwCfgLibInternal.h"\r
25\r
26STATIC BOOLEAN mQemuFwCfgSupported = FALSE;\r
27STATIC BOOLEAN mQemuFwCfgDmaSupported;\r
28\r
29\r
30/**\r
31 Returns a boolean indicating if the firmware configuration interface\r
32 is available or not.\r
33\r
34 This function may change fw_cfg state.\r
35\r
36 @retval TRUE The interface is available\r
37 @retval FALSE The interface is not available\r
38\r
39**/\r
40BOOLEAN\r
41EFIAPI\r
42QemuFwCfgIsAvailable (\r
43 VOID\r
44 )\r
45{\r
46 return InternalQemuFwCfgIsAvailable ();\r
47}\r
48\r
49\r
50RETURN_STATUS\r
51EFIAPI\r
52QemuFwCfgInitialize (\r
53 VOID\r
54 )\r
55{\r
56 UINT32 Signature;\r
57 UINT32 Revision;\r
58\r
59 //\r
60 // Enable the access routines while probing to see if it is supported.\r
61 // For probing we always use the IO Port (IoReadFifo8()) access method.\r
62 //\r
63 mQemuFwCfgSupported = TRUE;\r
64 mQemuFwCfgDmaSupported = FALSE;\r
65\r
66 QemuFwCfgSelectItem (QemuFwCfgItemSignature);\r
67 Signature = QemuFwCfgRead32 ();\r
68 DEBUG ((EFI_D_INFO, "FW CFG Signature: 0x%x\n", Signature));\r
69 QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion);\r
70 Revision = QemuFwCfgRead32 ();\r
71 DEBUG ((EFI_D_INFO, "FW CFG Revision: 0x%x\n", Revision));\r
72 if ((Signature != SIGNATURE_32 ('Q', 'E', 'M', 'U')) ||\r
73 (Revision < 1)\r
74 ) {\r
75 DEBUG ((EFI_D_INFO, "QemuFwCfg interface not supported.\n"));\r
76 mQemuFwCfgSupported = FALSE;\r
77 return RETURN_SUCCESS;\r
78 }\r
79\r
80 if ((Revision & FW_CFG_F_DMA) == 0) {\r
81 DEBUG ((DEBUG_INFO, "QemuFwCfg interface (IO Port) is supported.\n"));\r
82 } else {\r
83 //\r
84 // If SEV is enabled then we do not support DMA operations in PEI phase.\r
85 // This is mainly because DMA in SEV guest requires using bounce buffer\r
86 // (which need to allocate dynamic memory and allocating a PAGE size'd\r
87 // buffer can be challenge in PEI phase)\r
88 //\r
89 if (MemEncryptSevIsEnabled ()) {\r
90 DEBUG ((DEBUG_INFO, "SEV: QemuFwCfg fallback to IO Port interface.\n"));\r
91 } else {\r
92 mQemuFwCfgDmaSupported = TRUE;\r
93 DEBUG ((DEBUG_INFO, "QemuFwCfg interface (DMA) is supported.\n"));\r
94 }\r
95 }\r
96 return RETURN_SUCCESS;\r
97}\r
98\r
99\r
100/**\r
101 Returns a boolean indicating if the firmware configuration interface is\r
102 available for library-internal purposes.\r
103\r
104 This function never changes fw_cfg state.\r
105\r
106 @retval TRUE The interface is available internally.\r
107 @retval FALSE The interface is not available internally.\r
108**/\r
109BOOLEAN\r
110InternalQemuFwCfgIsAvailable (\r
111 VOID\r
112 )\r
113{\r
114 return mQemuFwCfgSupported;\r
115}\r
116\r
117/**\r
118 Returns a boolean indicating whether QEMU provides the DMA-like access method\r
119 for fw_cfg.\r
120\r
121 @retval TRUE The DMA-like access method is available.\r
122 @retval FALSE The DMA-like access method is unavailable.\r
123**/\r
124BOOLEAN\r
125InternalQemuFwCfgDmaIsAvailable (\r
126 VOID\r
127 )\r
128{\r
129 return mQemuFwCfgDmaSupported;\r
130}\r
131\r
132/**\r
133 Transfer an array of bytes, or skip a number of bytes, using the DMA\r
134 interface.\r
135\r
136 @param[in] Size Size in bytes to transfer or skip.\r
137\r
138 @param[in,out] Buffer Buffer to read data into or write data from. Ignored,\r
139 and may be NULL, if Size is zero, or Control is\r
140 FW_CFG_DMA_CTL_SKIP.\r
141\r
142 @param[in] Control One of the following:\r
143 FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buffer.\r
144 FW_CFG_DMA_CTL_READ - read from fw_cfg into Buffer.\r
145 FW_CFG_DMA_CTL_SKIP - skip bytes in fw_cfg.\r
146**/\r
147VOID\r
148InternalQemuFwCfgDmaBytes (\r
149 IN UINT32 Size,\r
150 IN OUT VOID *Buffer OPTIONAL,\r
151 IN UINT32 Control\r
152 )\r
153{\r
154 volatile FW_CFG_DMA_ACCESS Access;\r
155 UINT32 AccessHigh, AccessLow;\r
156 UINT32 Status;\r
157\r
158 ASSERT (Control == FW_CFG_DMA_CTL_WRITE || Control == FW_CFG_DMA_CTL_READ ||\r
159 Control == FW_CFG_DMA_CTL_SKIP);\r
160\r
161 if (Size == 0) {\r
162 return;\r
163 }\r
164\r
165 //\r
166 // SEV does not support DMA operations in PEI stage, we should\r
167 // not have reached here.\r
168 //\r
169 ASSERT (!MemEncryptSevIsEnabled ());\r
170\r
171 Access.Control = SwapBytes32 (Control);\r
172 Access.Length = SwapBytes32 (Size);\r
173 Access.Address = SwapBytes64 ((UINTN)Buffer);\r
174\r
175 //\r
176 // Delimit the transfer from (a) modifications to Access, (b) in case of a\r
177 // write, from writes to Buffer by the caller.\r
178 //\r
179 MemoryFence ();\r
180\r
181 //\r
182 // Start the transfer.\r
183 //\r
184 AccessHigh = (UINT32)RShiftU64 ((UINTN)&Access, 32);\r
185 AccessLow = (UINT32)(UINTN)&Access;\r
186 IoWrite32 (FW_CFG_IO_DMA_ADDRESS, SwapBytes32 (AccessHigh));\r
187 IoWrite32 (FW_CFG_IO_DMA_ADDRESS + 4, SwapBytes32 (AccessLow));\r
188\r
189 //\r
190 // Don't look at Access.Control before starting the transfer.\r
191 //\r
192 MemoryFence ();\r
193\r
194 //\r
195 // Wait for the transfer to complete.\r
196 //\r
197 do {\r
198 Status = SwapBytes32 (Access.Control);\r
199 ASSERT ((Status & FW_CFG_DMA_CTL_ERROR) == 0);\r
200 } while (Status != 0);\r
201\r
202 //\r
203 // After a read, the caller will want to use Buffer.\r
204 //\r
205 MemoryFence ();\r
206}\r
207\r