]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Library/LockBoxLib/LockBoxLib.c
OvmfPkg/PlatformPei: Change referenced MSR name.
[mirror_edk2.git] / OvmfPkg / Library / LockBoxLib / LockBoxLib.c
CommitLineData
6a7cba79
LE
1/** @file\r
2\r
3 Library implementing the LockBox interface for OVMF\r
4\r
5 Copyright (C) 2013, Red Hat, Inc.\r
b6de92f7 6 Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>\r
6a7cba79 7\r
b26f0cf9 8 SPDX-License-Identifier: BSD-2-Clause-Patent\r
6a7cba79
LE
9\r
10**/\r
11\r
12#include <Uefi.h>\r
13#include <Library/BaseMemoryLib.h>\r
14#include <Library/DebugLib.h>\r
15#include <Library/LockBoxLib.h>\r
16#include <Library/PcdLib.h>\r
17#include <LockBoxLib.h>\r
18\r
19#pragma pack(1)\r
20typedef struct {\r
21 EFI_GUID Guid;\r
22 EFI_PHYSICAL_ADDRESS OrigAddress;\r
23 EFI_PHYSICAL_ADDRESS CopyAddress;\r
24 UINT32 Size;\r
25 UINT64 Attributes;\r
26} LOCK_BOX_ENTRY;\r
27#pragma pack()\r
28\r
29LOCK_BOX_GLOBAL *mLockBoxGlobal = NULL;\r
30STATIC LOCK_BOX_ENTRY *StartOfEntries = NULL;\r
31STATIC LOCK_BOX_ENTRY *EndOfEntries = NULL;\r
32\r
33RETURN_STATUS\r
34EFIAPI\r
35LockBoxLibInitialize (\r
36 VOID\r
37 )\r
38{\r
39 UINTN NumEntries;\r
40\r
54253445
LE
41 ASSERT (!FeaturePcdGet (PcdSmmSmramRequire));\r
42\r
6a7cba79
LE
43 if (PcdGet32 (PcdOvmfLockBoxStorageSize) < sizeof (LOCK_BOX_GLOBAL)) {\r
44 return RETURN_UNSUPPORTED;\r
45 }\r
46\r
47 mLockBoxGlobal = (LOCK_BOX_GLOBAL *)(UINTN) PcdGet32 (PcdOvmfLockBoxStorageBase);\r
48 StartOfEntries = ((LOCK_BOX_ENTRY *) (mLockBoxGlobal + 1));\r
49 NumEntries = ((PcdGet32 (PcdOvmfLockBoxStorageSize) - sizeof (LOCK_BOX_GLOBAL)) /\r
50 sizeof (LOCK_BOX_ENTRY));\r
51 EndOfEntries = StartOfEntries + NumEntries; \r
52 if (mLockBoxGlobal->Signature != LOCK_BOX_GLOBAL_SIGNATURE) {\r
53 //\r
54 // Note: This code depends on the lock box being cleared in early\r
55 // PEI before usage, so the SubPageBuffer and SubPageRemaining\r
56 // fields don't need to be set to 0.\r
57 //\r
58 mLockBoxGlobal->Signature = LOCK_BOX_GLOBAL_SIGNATURE;\r
59 }\r
60 return RETURN_SUCCESS;\r
61}\r
62\r
63\r
64/**\r
65 Find LockBox entry based on GUID.\r
66\r
67 @param[in] Guid The GUID to search for.\r
68\r
69 @return Address of the LOCK_BOX_ENTRY found.\r
70\r
71 If NULL, then the item was not found, and there is no space\r
72 left to store a new item.\r
73\r
74 If non-NULL and LOCK_BOX_ENTRY.Size == 0, then the item was not\r
75 found, but a new item can be inserted at the returned location.\r
76\r
77 If non-NULL and LOCK_BOX_ENTRY.Size > 0, then the item was found.\r
78**/\r
79STATIC\r
80LOCK_BOX_ENTRY *\r
81EFIAPI\r
82FindHeaderByGuid (\r
83 IN CONST EFI_GUID *Guid\r
84 )\r
85{\r
86 LOCK_BOX_ENTRY *Header;\r
87\r
88 for (Header = StartOfEntries; Header < EndOfEntries; Header++) {\r
89 if (Header->Size == 0 || CompareGuid (Guid, &Header->Guid)) {\r
90 return Header;\r
91 }\r
92 }\r
93\r
94 return NULL;\r
95}\r
96\r
97\r
98/**\r
99 This function will save confidential information to lockbox.\r
100\r
101 @param Guid the guid to identify the confidential information\r
102 @param Buffer the address of the confidential information\r
103 @param Length the length of the confidential information\r
104\r
105 @retval RETURN_SUCCESS the information is saved successfully.\r
106 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or\r
107 Length is 0\r
108 @retval RETURN_ALREADY_STARTED the requested GUID already exist.\r
109 @retval RETURN_OUT_OF_RESOURCES no enough resource to save the information.\r
110 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface\r
111 @retval RETURN_NOT_STARTED it is too early to invoke this interface\r
112 @retval RETURN_UNSUPPORTED the service is not supported by\r
113 implementaion.\r
114**/\r
115RETURN_STATUS\r
116EFIAPI\r
117SaveLockBox (\r
118 IN GUID *Guid,\r
119 IN VOID *Buffer,\r
120 IN UINTN Length\r
121 )\r
122{\r
123 LOCK_BOX_ENTRY *Header;\r
124 VOID *CopyBuffer;\r
125\r
126 DEBUG ((DEBUG_VERBOSE, "%a: Guid=%g Buffer=%p Length=0x%x\n", __FUNCTION__,\r
127 Guid, Buffer, (UINT32) Length));\r
128\r
129 if (Guid == NULL || Buffer == NULL || Length == 0) {\r
130 return RETURN_INVALID_PARAMETER;\r
131 }\r
132\r
133 if (Length > 0xFFFFFFFF) {\r
134 return RETURN_OUT_OF_RESOURCES;\r
135 }\r
136\r
137 Header = FindHeaderByGuid (Guid);\r
138 if (Header == NULL) {\r
139 return RETURN_OUT_OF_RESOURCES;\r
140 }\r
141\r
142 if (Header->Size > 0) {\r
143 return RETURN_ALREADY_STARTED;\r
144 }\r
145\r
146 CopyBuffer = AllocateAcpiNvsPool (Length);\r
147 if (CopyBuffer == NULL) {\r
148 return RETURN_OUT_OF_RESOURCES;\r
149 }\r
150\r
151 //\r
152 // overwrite the current terminator header with new metadata\r
153 //\r
154 CopyGuid (&Header->Guid, Guid);\r
155 Header->OrigAddress = (UINTN) Buffer;\r
156 Header->CopyAddress = (UINTN) CopyBuffer;\r
157 Header->Size = (UINT32) Length;\r
158 Header->Attributes = 0;\r
159\r
160 //\r
161 // copy contents\r
162 //\r
163 CopyMem (CopyBuffer, Buffer, Length);\r
164\r
165 return RETURN_SUCCESS;\r
166}\r
167\r
168\r
169/**\r
170 This function will set lockbox attributes.\r
171\r
172 @param Guid the guid to identify the confidential information\r
173 @param Attributes the attributes of the lockbox\r
174\r
175 @retval RETURN_SUCCESS the information is saved successfully.\r
176 @retval RETURN_INVALID_PARAMETER attributes is invalid.\r
177 @retval RETURN_NOT_FOUND the requested GUID not found.\r
178 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface\r
179 @retval RETURN_NOT_STARTED it is too early to invoke this interface\r
180 @retval RETURN_UNSUPPORTED the service is not supported by\r
181 implementaion.\r
182**/\r
183RETURN_STATUS\r
184EFIAPI\r
185SetLockBoxAttributes (\r
186 IN GUID *Guid,\r
187 IN UINT64 Attributes\r
188 )\r
189{\r
190 LOCK_BOX_ENTRY *Header;\r
191\r
192 DEBUG ((DEBUG_VERBOSE, "%a: Guid=%g Attributes=0x%Lx\n", __FUNCTION__, Guid,\r
193 Attributes));\r
194\r
195 if (Guid == NULL) {\r
196 return RETURN_INVALID_PARAMETER;\r
197 }\r
198\r
199 Header = FindHeaderByGuid (Guid);\r
200 if (!Header || Header->Size == 0) {\r
201 return RETURN_NOT_FOUND;\r
202 }\r
203 Header->Attributes = Attributes;\r
204\r
205 return RETURN_SUCCESS;\r
206}\r
207\r
208\r
209/**\r
210 This function will update confidential information to lockbox.\r
211\r
212 @param Guid the guid to identify the original confidential information\r
213 @param Offset the offset of the original confidential information\r
214 @param Buffer the address of the updated confidential information\r
215 @param Length the length of the updated confidential information\r
216\r
217 @retval RETURN_SUCCESS the information is saved successfully.\r
218 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or\r
219 Length is 0.\r
220 @retval RETURN_NOT_FOUND the requested GUID not found.\r
b6de92f7
HW
221 @retval RETURN_BUFFER_TOO_SMALL for lockbox without attribute\r
222 LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY, the\r
223 original buffer to too small to hold new\r
224 information.\r
225 @retval RETURN_OUT_OF_RESOURCES for lockbox with attribute\r
226 LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY, no\r
227 enough resource to save the information.\r
6a7cba79
LE
228 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface\r
229 @retval RETURN_NOT_STARTED it is too early to invoke this interface\r
230 @retval RETURN_UNSUPPORTED the service is not supported by\r
231 implementaion.\r
232**/\r
233RETURN_STATUS\r
234EFIAPI\r
235UpdateLockBox (\r
236 IN GUID *Guid,\r
237 IN UINTN Offset,\r
238 IN VOID *Buffer,\r
239 IN UINTN Length\r
240 )\r
241{\r
242 LOCK_BOX_ENTRY *Header;\r
243\r
244 DEBUG ((DEBUG_VERBOSE, "%a: Guid=%g Offset=0x%x Length=0x%x\n", __FUNCTION__,\r
245 Guid, (UINT32) Offset, (UINT32) Length));\r
246\r
247 if (Guid == NULL || Buffer == NULL || Length == 0) {\r
248 return RETURN_INVALID_PARAMETER;\r
249 }\r
250\r
251 Header = FindHeaderByGuid (Guid);\r
252 if (!Header || Header->Size == 0) {\r
253 return RETURN_NOT_FOUND;\r
254 }\r
255\r
256 if (Header->Size < Offset ||\r
257 Length > Header->Size - Offset) {\r
258 return RETURN_BUFFER_TOO_SMALL;\r
259 }\r
260\r
261 CopyMem ((UINT8 *)(UINTN) (Header->CopyAddress) + Offset, Buffer, Length);\r
262\r
263 return RETURN_SUCCESS;\r
264}\r
265\r
266\r
267/**\r
268 This function will restore confidential information from lockbox.\r
269\r
270 @param Guid the guid to identify the confidential information\r
271 @param Buffer the address of the restored confidential information\r
272 NULL means restored to original address, Length MUST be NULL at\r
273 same time.\r
274 @param Length the length of the restored confidential information\r
275\r
276 @retval RETURN_SUCCESS the information is restored successfully.\r
277 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or one of Buffer and\r
278 Length is NULL.\r
279 @retval RETURN_WRITE_PROTECTED Buffer and Length are NULL, but the LockBox\r
280 has no LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE\r
281 attribute.\r
282 @retval RETURN_BUFFER_TOO_SMALL the Length is too small to hold the\r
283 confidential information.\r
284 @retval RETURN_NOT_FOUND the requested GUID not found.\r
285 @retval RETURN_NOT_STARTED it is too early to invoke this interface\r
286 @retval RETURN_ACCESS_DENIED not allow to restore to the address\r
287 @retval RETURN_UNSUPPORTED the service is not supported by\r
288 implementaion.\r
289**/\r
290RETURN_STATUS\r
291EFIAPI\r
292RestoreLockBox (\r
293 IN GUID *Guid,\r
294 IN VOID *Buffer, OPTIONAL\r
295 IN OUT UINTN *Length OPTIONAL\r
296 )\r
297{\r
298 LOCK_BOX_ENTRY *Header;\r
299\r
300 DEBUG ((DEBUG_VERBOSE, "%a: Guid=%g Buffer=%p\n", __FUNCTION__, Guid,\r
301 Buffer));\r
302\r
303 if ((Guid == NULL) ||\r
304 ((Buffer == NULL) && (Length != NULL)) ||\r
305 ((Buffer != NULL) && (Length == NULL))) {\r
306 return EFI_INVALID_PARAMETER;\r
307 }\r
308\r
309 Header = FindHeaderByGuid (Guid);\r
310 if (!Header || Header->Size == 0) {\r
311 return RETURN_NOT_FOUND;\r
312 }\r
313\r
314 if (Buffer == NULL) {\r
315 if (!(Header->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE)) {\r
316 return RETURN_WRITE_PROTECTED;\r
317 }\r
318 if (Header->OrigAddress + (Header->Size - 1) > MAX_ADDRESS) {\r
319 return RETURN_UNSUPPORTED;\r
320 }\r
321 Buffer = (VOID *)(UINTN) Header->OrigAddress;\r
322 }\r
323\r
324 //\r
325 // Set RestoreLength\r
326 //\r
327 if (Length != NULL) {\r
328 if (Header->Size > *Length) {\r
329 //\r
330 // Input buffer is too small to hold all data.\r
331 //\r
332 *Length = Header->Size;\r
333 return EFI_BUFFER_TOO_SMALL;\r
334 }\r
335 *Length = Header->Size;\r
336 }\r
337\r
338 CopyMem (Buffer, (VOID*)(UINTN) Header->CopyAddress, Header->Size);\r
339\r
340 return RETURN_SUCCESS;\r
341}\r
342\r
343\r
344/**\r
345 This function will restore confidential information from all lockbox which\r
346 have RestoreInPlace attribute.\r
347\r
348 @retval RETURN_SUCCESS the information is restored successfully.\r
349 @retval RETURN_NOT_STARTED it is too early to invoke this interface\r
350 @retval RETURN_UNSUPPORTED the service is not supported by\r
351 implementaion.\r
352**/\r
353RETURN_STATUS\r
354EFIAPI\r
355RestoreAllLockBoxInPlace (\r
356 VOID\r
357 )\r
358{\r
359 LOCK_BOX_ENTRY *Header;\r
360\r
361 for (Header = StartOfEntries;\r
362 Header < EndOfEntries && Header->Size > 0;\r
363 Header++) {\r
364 if (Header->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) {\r
365 VOID *Buffer;\r
366\r
367 if (Header->OrigAddress + (Header->Size - 1) > MAX_ADDRESS) {\r
368 return RETURN_UNSUPPORTED;\r
369 }\r
370 Buffer = (VOID *)(UINTN) Header->OrigAddress;\r
371 CopyMem (Buffer, (VOID*)(UINTN)Header->CopyAddress, Header->Size);\r
372 DEBUG ((DEBUG_VERBOSE, "%a: Guid=%g Buffer=%p\n", __FUNCTION__,\r
6394c35a 373 &Header->Guid, Buffer));\r
6a7cba79
LE
374 }\r
375 }\r
376 return RETURN_SUCCESS;\r
377}\r