VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/OvmfPkg/Library/LockBoxLib/LockBoxLib.c@ 85718

Last change on this file since 85718 was 80721, checked in by vboxsync, 6 years ago

Devices/EFI/FirmwareNew: Start upgrade process to edk2-stable201908 (compiles on Windows and works to some extent), bugref:4643

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette