]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Library/LockBoxLib/LockBoxLib.c
OvmfPkg: Apply uncrustify changes
[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
ac0a286f
MK
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
6a7cba79
LE
26} LOCK_BOX_ENTRY;\r
27#pragma pack()\r
28\r
ac0a286f
MK
29LOCK_BOX_GLOBAL *mLockBoxGlobal = NULL;\r
30STATIC LOCK_BOX_ENTRY *StartOfEntries = NULL;\r
31STATIC LOCK_BOX_ENTRY *EndOfEntries = NULL;\r
6a7cba79
LE
32\r
33RETURN_STATUS\r
34EFIAPI\r
35LockBoxLibInitialize (\r
36 VOID\r
37 )\r
38{\r
ac0a286f 39 UINTN NumEntries;\r
6a7cba79 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
ac0a286f
MK
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
4040754d 51 EndOfEntries = StartOfEntries + NumEntries;\r
6a7cba79
LE
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
ac0a286f 60\r
6a7cba79
LE
61 return RETURN_SUCCESS;\r
62}\r
63\r
6a7cba79
LE
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
ac0a286f 83 IN CONST EFI_GUID *Guid\r
6a7cba79
LE
84 )\r
85{\r
ac0a286f 86 LOCK_BOX_ENTRY *Header;\r
6a7cba79
LE
87\r
88 for (Header = StartOfEntries; Header < EndOfEntries; Header++) {\r
ac0a286f 89 if ((Header->Size == 0) || CompareGuid (Guid, &Header->Guid)) {\r
6a7cba79
LE
90 return Header;\r
91 }\r
92 }\r
93\r
94 return NULL;\r
95}\r
96\r
6a7cba79
LE
97/**\r
98 This function will save confidential information to lockbox.\r
99\r
100 @param Guid the guid to identify the confidential information\r
101 @param Buffer the address of the confidential information\r
102 @param Length the length of the confidential information\r
103\r
104 @retval RETURN_SUCCESS the information is saved successfully.\r
105 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or\r
106 Length is 0\r
107 @retval RETURN_ALREADY_STARTED the requested GUID already exist.\r
108 @retval RETURN_OUT_OF_RESOURCES no enough resource to save the information.\r
109 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface\r
110 @retval RETURN_NOT_STARTED it is too early to invoke this interface\r
111 @retval RETURN_UNSUPPORTED the service is not supported by\r
112 implementaion.\r
113**/\r
114RETURN_STATUS\r
115EFIAPI\r
116SaveLockBox (\r
ac0a286f
MK
117 IN GUID *Guid,\r
118 IN VOID *Buffer,\r
119 IN UINTN Length\r
6a7cba79
LE
120 )\r
121{\r
ac0a286f 122 LOCK_BOX_ENTRY *Header;\r
6a7cba79
LE
123 VOID *CopyBuffer;\r
124\r
ac0a286f
MK
125 DEBUG ((\r
126 DEBUG_VERBOSE,\r
127 "%a: Guid=%g Buffer=%p Length=0x%x\n",\r
128 __FUNCTION__,\r
129 Guid,\r
130 Buffer,\r
131 (UINT32)Length\r
132 ));\r
6a7cba79 133\r
ac0a286f 134 if ((Guid == NULL) || (Buffer == NULL) || (Length == 0)) {\r
6a7cba79
LE
135 return RETURN_INVALID_PARAMETER;\r
136 }\r
137\r
138 if (Length > 0xFFFFFFFF) {\r
139 return RETURN_OUT_OF_RESOURCES;\r
140 }\r
141\r
142 Header = FindHeaderByGuid (Guid);\r
143 if (Header == NULL) {\r
144 return RETURN_OUT_OF_RESOURCES;\r
145 }\r
146\r
147 if (Header->Size > 0) {\r
148 return RETURN_ALREADY_STARTED;\r
149 }\r
150\r
151 CopyBuffer = AllocateAcpiNvsPool (Length);\r
152 if (CopyBuffer == NULL) {\r
153 return RETURN_OUT_OF_RESOURCES;\r
154 }\r
155\r
156 //\r
157 // overwrite the current terminator header with new metadata\r
158 //\r
159 CopyGuid (&Header->Guid, Guid);\r
ac0a286f
MK
160 Header->OrigAddress = (UINTN)Buffer;\r
161 Header->CopyAddress = (UINTN)CopyBuffer;\r
162 Header->Size = (UINT32)Length;\r
6a7cba79
LE
163 Header->Attributes = 0;\r
164\r
165 //\r
166 // copy contents\r
167 //\r
168 CopyMem (CopyBuffer, Buffer, Length);\r
169\r
170 return RETURN_SUCCESS;\r
171}\r
172\r
6a7cba79
LE
173/**\r
174 This function will set lockbox attributes.\r
175\r
176 @param Guid the guid to identify the confidential information\r
177 @param Attributes the attributes of the lockbox\r
178\r
179 @retval RETURN_SUCCESS the information is saved successfully.\r
180 @retval RETURN_INVALID_PARAMETER attributes is invalid.\r
181 @retval RETURN_NOT_FOUND the requested GUID not found.\r
182 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface\r
183 @retval RETURN_NOT_STARTED it is too early to invoke this interface\r
184 @retval RETURN_UNSUPPORTED the service is not supported by\r
185 implementaion.\r
186**/\r
187RETURN_STATUS\r
188EFIAPI\r
189SetLockBoxAttributes (\r
ac0a286f
MK
190 IN GUID *Guid,\r
191 IN UINT64 Attributes\r
6a7cba79
LE
192 )\r
193{\r
ac0a286f 194 LOCK_BOX_ENTRY *Header;\r
6a7cba79 195\r
ac0a286f
MK
196 DEBUG ((\r
197 DEBUG_VERBOSE,\r
198 "%a: Guid=%g Attributes=0x%Lx\n",\r
199 __FUNCTION__,\r
200 Guid,\r
201 Attributes\r
202 ));\r
6a7cba79
LE
203\r
204 if (Guid == NULL) {\r
205 return RETURN_INVALID_PARAMETER;\r
206 }\r
207\r
208 Header = FindHeaderByGuid (Guid);\r
ac0a286f 209 if (!Header || (Header->Size == 0)) {\r
6a7cba79
LE
210 return RETURN_NOT_FOUND;\r
211 }\r
ac0a286f 212\r
6a7cba79
LE
213 Header->Attributes = Attributes;\r
214\r
215 return RETURN_SUCCESS;\r
216}\r
217\r
6a7cba79
LE
218/**\r
219 This function will update confidential information to lockbox.\r
220\r
221 @param Guid the guid to identify the original confidential information\r
222 @param Offset the offset of the original confidential information\r
223 @param Buffer the address of the updated confidential information\r
224 @param Length the length of the updated confidential information\r
225\r
226 @retval RETURN_SUCCESS the information is saved successfully.\r
227 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or\r
228 Length is 0.\r
229 @retval RETURN_NOT_FOUND the requested GUID not found.\r
b6de92f7
HW
230 @retval RETURN_BUFFER_TOO_SMALL for lockbox without attribute\r
231 LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY, the\r
232 original buffer to too small to hold new\r
233 information.\r
234 @retval RETURN_OUT_OF_RESOURCES for lockbox with attribute\r
235 LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY, no\r
236 enough resource to save the information.\r
6a7cba79
LE
237 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface\r
238 @retval RETURN_NOT_STARTED it is too early to invoke this interface\r
239 @retval RETURN_UNSUPPORTED the service is not supported by\r
240 implementaion.\r
241**/\r
242RETURN_STATUS\r
243EFIAPI\r
244UpdateLockBox (\r
ac0a286f
MK
245 IN GUID *Guid,\r
246 IN UINTN Offset,\r
247 IN VOID *Buffer,\r
248 IN UINTN Length\r
6a7cba79
LE
249 )\r
250{\r
ac0a286f
MK
251 LOCK_BOX_ENTRY *Header;\r
252\r
253 DEBUG ((\r
254 DEBUG_VERBOSE,\r
255 "%a: Guid=%g Offset=0x%x Length=0x%x\n",\r
256 __FUNCTION__,\r
257 Guid,\r
258 (UINT32)Offset,\r
259 (UINT32)Length\r
260 ));\r
261\r
262 if ((Guid == NULL) || (Buffer == NULL) || (Length == 0)) {\r
6a7cba79
LE
263 return RETURN_INVALID_PARAMETER;\r
264 }\r
265\r
266 Header = FindHeaderByGuid (Guid);\r
ac0a286f 267 if (!Header || (Header->Size == 0)) {\r
6a7cba79
LE
268 return RETURN_NOT_FOUND;\r
269 }\r
270\r
ac0a286f
MK
271 if ((Header->Size < Offset) ||\r
272 (Length > Header->Size - Offset))\r
273 {\r
6a7cba79
LE
274 return RETURN_BUFFER_TOO_SMALL;\r
275 }\r
276\r
ac0a286f 277 CopyMem ((UINT8 *)(UINTN)(Header->CopyAddress) + Offset, Buffer, Length);\r
6a7cba79
LE
278\r
279 return RETURN_SUCCESS;\r
280}\r
281\r
6a7cba79
LE
282/**\r
283 This function will restore confidential information from lockbox.\r
284\r
285 @param Guid the guid to identify the confidential information\r
286 @param Buffer the address of the restored confidential information\r
287 NULL means restored to original address, Length MUST be NULL at\r
288 same time.\r
289 @param Length the length of the restored confidential information\r
290\r
291 @retval RETURN_SUCCESS the information is restored successfully.\r
292 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or one of Buffer and\r
293 Length is NULL.\r
294 @retval RETURN_WRITE_PROTECTED Buffer and Length are NULL, but the LockBox\r
295 has no LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE\r
296 attribute.\r
297 @retval RETURN_BUFFER_TOO_SMALL the Length is too small to hold the\r
298 confidential information.\r
299 @retval RETURN_NOT_FOUND the requested GUID not found.\r
300 @retval RETURN_NOT_STARTED it is too early to invoke this interface\r
301 @retval RETURN_ACCESS_DENIED not allow to restore to the address\r
302 @retval RETURN_UNSUPPORTED the service is not supported by\r
303 implementaion.\r
304**/\r
305RETURN_STATUS\r
306EFIAPI\r
307RestoreLockBox (\r
ac0a286f
MK
308 IN GUID *Guid,\r
309 IN VOID *Buffer OPTIONAL,\r
310 IN OUT UINTN *Length OPTIONAL\r
6a7cba79
LE
311 )\r
312{\r
ac0a286f 313 LOCK_BOX_ENTRY *Header;\r
6a7cba79 314\r
ac0a286f
MK
315 DEBUG ((\r
316 DEBUG_VERBOSE,\r
317 "%a: Guid=%g Buffer=%p\n",\r
318 __FUNCTION__,\r
319 Guid,\r
320 Buffer\r
321 ));\r
6a7cba79
LE
322\r
323 if ((Guid == NULL) ||\r
324 ((Buffer == NULL) && (Length != NULL)) ||\r
ac0a286f
MK
325 ((Buffer != NULL) && (Length == NULL)))\r
326 {\r
6a7cba79
LE
327 return EFI_INVALID_PARAMETER;\r
328 }\r
329\r
330 Header = FindHeaderByGuid (Guid);\r
ac0a286f 331 if (!Header || (Header->Size == 0)) {\r
6a7cba79
LE
332 return RETURN_NOT_FOUND;\r
333 }\r
334\r
335 if (Buffer == NULL) {\r
336 if (!(Header->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE)) {\r
337 return RETURN_WRITE_PROTECTED;\r
338 }\r
ac0a286f 339\r
6a7cba79
LE
340 if (Header->OrigAddress + (Header->Size - 1) > MAX_ADDRESS) {\r
341 return RETURN_UNSUPPORTED;\r
342 }\r
ac0a286f
MK
343\r
344 Buffer = (VOID *)(UINTN)Header->OrigAddress;\r
6a7cba79
LE
345 }\r
346\r
347 //\r
348 // Set RestoreLength\r
349 //\r
350 if (Length != NULL) {\r
351 if (Header->Size > *Length) {\r
352 //\r
353 // Input buffer is too small to hold all data.\r
354 //\r
355 *Length = Header->Size;\r
356 return EFI_BUFFER_TOO_SMALL;\r
357 }\r
ac0a286f 358\r
6a7cba79
LE
359 *Length = Header->Size;\r
360 }\r
361\r
ac0a286f 362 CopyMem (Buffer, (VOID *)(UINTN)Header->CopyAddress, Header->Size);\r
6a7cba79
LE
363\r
364 return RETURN_SUCCESS;\r
365}\r
366\r
6a7cba79
LE
367/**\r
368 This function will restore confidential information from all lockbox which\r
369 have RestoreInPlace attribute.\r
370\r
371 @retval RETURN_SUCCESS the information is restored successfully.\r
372 @retval RETURN_NOT_STARTED it is too early to invoke this interface\r
373 @retval RETURN_UNSUPPORTED the service is not supported by\r
374 implementaion.\r
375**/\r
376RETURN_STATUS\r
377EFIAPI\r
378RestoreAllLockBoxInPlace (\r
379 VOID\r
380 )\r
381{\r
ac0a286f 382 LOCK_BOX_ENTRY *Header;\r
6a7cba79
LE
383\r
384 for (Header = StartOfEntries;\r
385 Header < EndOfEntries && Header->Size > 0;\r
ac0a286f
MK
386 Header++)\r
387 {\r
6a7cba79 388 if (Header->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) {\r
ac0a286f 389 VOID *Buffer;\r
6a7cba79
LE
390\r
391 if (Header->OrigAddress + (Header->Size - 1) > MAX_ADDRESS) {\r
392 return RETURN_UNSUPPORTED;\r
393 }\r
ac0a286f
MK
394\r
395 Buffer = (VOID *)(UINTN)Header->OrigAddress;\r
396 CopyMem (Buffer, (VOID *)(UINTN)Header->CopyAddress, Header->Size);\r
397 DEBUG ((\r
398 DEBUG_VERBOSE,\r
399 "%a: Guid=%g Buffer=%p\n",\r
400 __FUNCTION__,\r
401 &Header->Guid,\r
402 Buffer\r
403 ));\r
6a7cba79
LE
404 }\r
405 }\r
ac0a286f 406\r
6a7cba79
LE
407 return RETURN_SUCCESS;\r
408}\r