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