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