]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase
[mirror_edk2.git] / OvmfPkg / Library / QemuFwCfgLib / QemuFwCfgDxe.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
09719a01 7 Copyright (c) 2017, Advanced Micro Devices. All rights reserved.<BR>\r
2ce7e221
LE
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
09719a01
BS
18#include <Uefi.h>\r
19\r
20#include <Protocol/IoMmu.h>\r
21\r
22#include <Library/BaseLib.h>\r
2ce7e221
LE
23#include <Library/DebugLib.h>\r
24#include <Library/QemuFwCfgLib.h>\r
09719a01
BS
25#include <Library/UefiBootServicesTableLib.h>\r
26#include <Library/MemEncryptSevLib.h>\r
2ce7e221 27\r
5297c0bf
LE
28#include "QemuFwCfgLibInternal.h"\r
29\r
2ce7e221 30STATIC BOOLEAN mQemuFwCfgSupported = FALSE;\r
2c8dcbc6 31STATIC BOOLEAN mQemuFwCfgDmaSupported;\r
2ce7e221 32\r
09719a01
BS
33STATIC EDKII_IOMMU_PROTOCOL *mIoMmuProtocol;\r
34/**\r
35\r
36 Returns a boolean indicating whether SEV is enabled\r
37\r
38 @retval TRUE SEV is enabled\r
39 @retval FALSE SEV is disabled\r
40**/\r
41BOOLEAN\r
42InternalQemuFwCfgSevIsEnabled (\r
43 VOID\r
44 )\r
45{\r
46 return MemEncryptSevIsEnabled ();\r
47}\r
2ce7e221
LE
48\r
49/**\r
50 Returns a boolean indicating if the firmware configuration interface\r
51 is available or not.\r
52\r
53 This function may change fw_cfg state.\r
54\r
55 @retval TRUE The interface is available\r
56 @retval FALSE The interface is not available\r
57\r
58**/\r
59BOOLEAN\r
60EFIAPI\r
61QemuFwCfgIsAvailable (\r
62 VOID\r
63 )\r
64{\r
65 return InternalQemuFwCfgIsAvailable ();\r
66}\r
67\r
68\r
69RETURN_STATUS\r
70EFIAPI\r
71QemuFwCfgInitialize (\r
72 VOID\r
73 )\r
74{\r
75 UINT32 Signature;\r
76 UINT32 Revision;\r
77\r
78 //\r
79 // Enable the access routines while probing to see if it is supported.\r
2c8dcbc6 80 // For probing we always use the IO Port (IoReadFifo8()) access method.\r
2ce7e221
LE
81 //\r
82 mQemuFwCfgSupported = TRUE;\r
2c8dcbc6 83 mQemuFwCfgDmaSupported = FALSE;\r
2ce7e221
LE
84\r
85 QemuFwCfgSelectItem (QemuFwCfgItemSignature);\r
86 Signature = QemuFwCfgRead32 ();\r
87 DEBUG ((EFI_D_INFO, "FW CFG Signature: 0x%x\n", Signature));\r
88 QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion);\r
89 Revision = QemuFwCfgRead32 ();\r
90 DEBUG ((EFI_D_INFO, "FW CFG Revision: 0x%x\n", Revision));\r
91 if ((Signature != SIGNATURE_32 ('Q', 'E', 'M', 'U')) ||\r
92 (Revision < 1)\r
93 ) {\r
94 DEBUG ((EFI_D_INFO, "QemuFwCfg interface not supported.\n"));\r
95 mQemuFwCfgSupported = FALSE;\r
96 return RETURN_SUCCESS;\r
97 }\r
98\r
2c8dcbc6
LE
99 if ((Revision & FW_CFG_F_DMA) == 0) {\r
100 DEBUG ((DEBUG_INFO, "QemuFwCfg interface (IO Port) is supported.\n"));\r
101 } else {\r
102 mQemuFwCfgDmaSupported = TRUE;\r
103 DEBUG ((DEBUG_INFO, "QemuFwCfg interface (DMA) is supported.\n"));\r
104 }\r
09719a01
BS
105\r
106 if (mQemuFwCfgDmaSupported && MemEncryptSevIsEnabled ()) {\r
107 EFI_STATUS Status;\r
108\r
109 //\r
110 // IoMmuDxe driver must have installed the IOMMU protocol. If we are not\r
111 // able to locate the protocol then something must have gone wrong.\r
112 //\r
113 Status = gBS->LocateProtocol (&gEdkiiIoMmuProtocolGuid, NULL, (VOID **)&mIoMmuProtocol);\r
114 if (EFI_ERROR (Status)) {\r
115 DEBUG ((DEBUG_ERROR,\r
116 "QemuFwCfgSevDma %a:%a Failed to locate IOMMU protocol.\n",\r
117 gEfiCallerBaseName, __FUNCTION__));\r
118 ASSERT (FALSE);\r
119 CpuDeadLoop ();\r
120 }\r
121 }\r
122\r
2ce7e221
LE
123 return RETURN_SUCCESS;\r
124}\r
125\r
126\r
127/**\r
128 Returns a boolean indicating if the firmware configuration interface is\r
129 available for library-internal purposes.\r
130\r
131 This function never changes fw_cfg state.\r
132\r
133 @retval TRUE The interface is available internally.\r
134 @retval FALSE The interface is not available internally.\r
135**/\r
136BOOLEAN\r
2ce7e221
LE
137InternalQemuFwCfgIsAvailable (\r
138 VOID\r
139 )\r
140{\r
141 return mQemuFwCfgSupported;\r
142}\r
2c8dcbc6
LE
143\r
144/**\r
145 Returns a boolean indicating whether QEMU provides the DMA-like access method\r
146 for fw_cfg.\r
147\r
148 @retval TRUE The DMA-like access method is available.\r
149 @retval FALSE The DMA-like access method is unavailable.\r
150**/\r
151BOOLEAN\r
152InternalQemuFwCfgDmaIsAvailable (\r
153 VOID\r
154 )\r
155{\r
156 return mQemuFwCfgDmaSupported;\r
157}\r
09719a01
BS
158\r
159/**\r
160 Allocate a bounce buffer for SEV DMA.\r
161\r
162 @param[in] NumPage Number of pages.\r
163 @param[out] Buffer Allocated DMA Buffer pointer\r
164\r
165**/\r
166VOID\r
167InternalQemuFwCfgSevDmaAllocateBuffer (\r
168 OUT VOID **Buffer,\r
169 IN UINT32 NumPages\r
170 )\r
171{\r
172 EFI_STATUS Status;\r
173\r
174 ASSERT (mIoMmuProtocol != NULL);\r
175\r
176 Status = mIoMmuProtocol->AllocateBuffer (\r
177 mIoMmuProtocol,\r
178 0,\r
179 EfiBootServicesData,\r
180 NumPages,\r
181 Buffer,\r
182 EDKII_IOMMU_ATTRIBUTE_MEMORY_CACHED\r
183 );\r
184 if (EFI_ERROR (Status)) {\r
185 DEBUG ((DEBUG_ERROR,\r
186 "%a:%a failed to allocate %u pages\n", gEfiCallerBaseName, __FUNCTION__,\r
187 NumPages));\r
188 ASSERT (FALSE);\r
189 CpuDeadLoop ();\r
190 }\r
191\r
192 DEBUG ((DEBUG_VERBOSE,\r
193 "%a:%a buffer 0x%Lx Pages %u\n", gEfiCallerBaseName, __FUNCTION__,\r
194 (UINT64)(UINTN)Buffer, NumPages));\r
195}\r
196\r
197/**\r
198 Free the DMA buffer allocated using InternalQemuFwCfgSevDmaAllocateBuffer\r
199\r
200 @param[in] NumPage Number of pages.\r
201 @param[in] Buffer DMA Buffer pointer\r
202\r
203**/\r
204VOID\r
205InternalQemuFwCfgSevDmaFreeBuffer (\r
206 IN VOID *Buffer,\r
207 IN UINT32 NumPages\r
208 )\r
209{\r
210 EFI_STATUS Status;\r
211\r
212 ASSERT (mIoMmuProtocol != NULL);\r
213\r
214 Status = mIoMmuProtocol->FreeBuffer (\r
215 mIoMmuProtocol,\r
216 NumPages,\r
217 Buffer\r
218 );\r
219 if (EFI_ERROR (Status)) {\r
220 DEBUG ((DEBUG_ERROR,\r
221 "%a:%a failed to free buffer 0x%Lx pages %u\n", gEfiCallerBaseName,\r
222 __FUNCTION__, (UINT64)(UINTN)Buffer, NumPages));\r
223 ASSERT (FALSE);\r
224 CpuDeadLoop ();\r
225 }\r
226\r
227 DEBUG ((DEBUG_VERBOSE,\r
228 "%a:%a buffer 0x%Lx Pages %u\n", gEfiCallerBaseName,__FUNCTION__,\r
229 (UINT64)(UINTN)Buffer, NumPages));\r
230}\r