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