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