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