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