]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Library/LockBoxLib/LockBoxLib.c
OvmfPkg/Virtio: take RingBaseShift in SetQueueAddress()
[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
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
227 @retval RETURN_BUFFER_TOO_SMALL the original buffer to too small to hold\r
228 new information.\r
229 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface\r
230 @retval RETURN_NOT_STARTED it is too early to invoke this interface\r
231 @retval RETURN_UNSUPPORTED the service is not supported by\r
232 implementaion.\r
233**/\r
234RETURN_STATUS\r
235EFIAPI\r
236UpdateLockBox (\r
237 IN GUID *Guid,\r
238 IN UINTN Offset,\r
239 IN VOID *Buffer,\r
240 IN UINTN Length\r
241 )\r
242{\r
243 LOCK_BOX_ENTRY *Header;\r
244\r
245 DEBUG ((DEBUG_VERBOSE, "%a: Guid=%g Offset=0x%x Length=0x%x\n", __FUNCTION__,\r
246 Guid, (UINT32) Offset, (UINT32) Length));\r
247\r
248 if (Guid == NULL || Buffer == NULL || Length == 0) {\r
249 return RETURN_INVALID_PARAMETER;\r
250 }\r
251\r
252 Header = FindHeaderByGuid (Guid);\r
253 if (!Header || Header->Size == 0) {\r
254 return RETURN_NOT_FOUND;\r
255 }\r
256\r
257 if (Header->Size < Offset ||\r
258 Length > Header->Size - Offset) {\r
259 return RETURN_BUFFER_TOO_SMALL;\r
260 }\r
261\r
262 CopyMem ((UINT8 *)(UINTN) (Header->CopyAddress) + Offset, Buffer, Length);\r
263\r
264 return RETURN_SUCCESS;\r
265}\r
266\r
267\r
268/**\r
269 This function will restore confidential information from lockbox.\r
270\r
271 @param Guid the guid to identify the confidential information\r
272 @param Buffer the address of the restored confidential information\r
273 NULL means restored to original address, Length MUST be NULL at\r
274 same time.\r
275 @param Length the length of the restored confidential information\r
276\r
277 @retval RETURN_SUCCESS the information is restored successfully.\r
278 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or one of Buffer and\r
279 Length is NULL.\r
280 @retval RETURN_WRITE_PROTECTED Buffer and Length are NULL, but the LockBox\r
281 has no LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE\r
282 attribute.\r
283 @retval RETURN_BUFFER_TOO_SMALL the Length is too small to hold the\r
284 confidential information.\r
285 @retval RETURN_NOT_FOUND the requested GUID not found.\r
286 @retval RETURN_NOT_STARTED it is too early to invoke this interface\r
287 @retval RETURN_ACCESS_DENIED not allow to restore to the address\r
288 @retval RETURN_UNSUPPORTED the service is not supported by\r
289 implementaion.\r
290**/\r
291RETURN_STATUS\r
292EFIAPI\r
293RestoreLockBox (\r
294 IN GUID *Guid,\r
295 IN VOID *Buffer, OPTIONAL\r
296 IN OUT UINTN *Length OPTIONAL\r
297 )\r
298{\r
299 LOCK_BOX_ENTRY *Header;\r
300\r
301 DEBUG ((DEBUG_VERBOSE, "%a: Guid=%g Buffer=%p\n", __FUNCTION__, Guid,\r
302 Buffer));\r
303\r
304 if ((Guid == NULL) ||\r
305 ((Buffer == NULL) && (Length != NULL)) ||\r
306 ((Buffer != NULL) && (Length == NULL))) {\r
307 return EFI_INVALID_PARAMETER;\r
308 }\r
309\r
310 Header = FindHeaderByGuid (Guid);\r
311 if (!Header || Header->Size == 0) {\r
312 return RETURN_NOT_FOUND;\r
313 }\r
314\r
315 if (Buffer == NULL) {\r
316 if (!(Header->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE)) {\r
317 return RETURN_WRITE_PROTECTED;\r
318 }\r
319 if (Header->OrigAddress + (Header->Size - 1) > MAX_ADDRESS) {\r
320 return RETURN_UNSUPPORTED;\r
321 }\r
322 Buffer = (VOID *)(UINTN) Header->OrigAddress;\r
323 }\r
324\r
325 //\r
326 // Set RestoreLength\r
327 //\r
328 if (Length != NULL) {\r
329 if (Header->Size > *Length) {\r
330 //\r
331 // Input buffer is too small to hold all data.\r
332 //\r
333 *Length = Header->Size;\r
334 return EFI_BUFFER_TOO_SMALL;\r
335 }\r
336 *Length = Header->Size;\r
337 }\r
338\r
339 CopyMem (Buffer, (VOID*)(UINTN) Header->CopyAddress, Header->Size);\r
340\r
341 return RETURN_SUCCESS;\r
342}\r
343\r
344\r
345/**\r
346 This function will restore confidential information from all lockbox which\r
347 have RestoreInPlace attribute.\r
348\r
349 @retval RETURN_SUCCESS the information is restored successfully.\r
350 @retval RETURN_NOT_STARTED it is too early to invoke this interface\r
351 @retval RETURN_UNSUPPORTED the service is not supported by\r
352 implementaion.\r
353**/\r
354RETURN_STATUS\r
355EFIAPI\r
356RestoreAllLockBoxInPlace (\r
357 VOID\r
358 )\r
359{\r
360 LOCK_BOX_ENTRY *Header;\r
361\r
362 for (Header = StartOfEntries;\r
363 Header < EndOfEntries && Header->Size > 0;\r
364 Header++) {\r
365 if (Header->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) {\r
366 VOID *Buffer;\r
367\r
368 if (Header->OrigAddress + (Header->Size - 1) > MAX_ADDRESS) {\r
369 return RETURN_UNSUPPORTED;\r
370 }\r
371 Buffer = (VOID *)(UINTN) Header->OrigAddress;\r
372 CopyMem (Buffer, (VOID*)(UINTN)Header->CopyAddress, Header->Size);\r
373 DEBUG ((DEBUG_VERBOSE, "%a: Guid=%g Buffer=%p\n", __FUNCTION__,\r
6394c35a 374 &Header->Guid, Buffer));\r
6a7cba79
LE
375 }\r
376 }\r
377 return RETURN_SUCCESS;\r
378}\r