1 /** @file
2 
3 Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
4 
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions
7 of the BSD License which accompanies this distribution.  The
8 full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10 
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 
14 **/
15 
16 #include <PiDxe.h>
17 #include <Library/UefiBootServicesTableLib.h>
18 #include <Library/UefiRuntimeServicesTableLib.h>
19 #include <Library/BaseLib.h>
20 #include <Library/BaseMemoryLib.h>
21 #include <Library/LockBoxLib.h>
22 #include <Library/DebugLib.h>
23 #include <Protocol/SmmCommunication.h>
24 #include <Guid/SmmLockBox.h>
25 
26 #include "SmmLockBoxLibPrivate.h"
27 
28 /**
29   This function will save confidential information to lockbox.
30 
31   @param Guid       the guid to identify the confidential information
32   @param Buffer     the address of the confidential information
33   @param Length     the length of the confidential information
34 
35   @retval RETURN_SUCCESS            the information is saved successfully.
36   @retval RETURN_INVALID_PARAMETER  the Guid is NULL, or Buffer is NULL, or Length is 0
37   @retval RETURN_ALREADY_STARTED    the requested GUID already exist.
38   @retval RETURN_OUT_OF_RESOURCES   no enough resource to save the information.
39   @retval RETURN_ACCESS_DENIED      it is too late to invoke this interface
40   @retval RETURN_NOT_STARTED        it is too early to invoke this interface
41   @retval RETURN_UNSUPPORTED        the service is not supported by implementaion.
42 **/
43 RETURN_STATUS
44 EFIAPI
SaveLockBox(IN GUID * Guid,IN VOID * Buffer,IN UINTN Length)45 SaveLockBox (
46   IN  GUID                        *Guid,
47   IN  VOID                        *Buffer,
48   IN  UINTN                       Length
49   )
50 {
51   EFI_STATUS                      Status;
52   EFI_SMM_COMMUNICATION_PROTOCOL  *SmmCommunication;
53   EFI_SMM_LOCK_BOX_PARAMETER_SAVE *LockBoxParameterSave;
54   EFI_SMM_COMMUNICATE_HEADER      *CommHeader;
55   UINT8                           CommBuffer[sizeof(EFI_GUID) + sizeof(UINTN) + sizeof(EFI_SMM_LOCK_BOX_PARAMETER_SAVE)];
56   UINTN                           CommSize;
57 
58   DEBUG ((EFI_D_INFO, "SmmLockBoxDxeLib SaveLockBox - Enter\n"));
59 
60   //
61   // Basic check
62   //
63   if ((Guid == NULL) || (Buffer == NULL) || (Length == 0)) {
64     return EFI_INVALID_PARAMETER;
65   }
66 
67   //
68   // Get needed resource
69   //
70   Status = gBS->LocateProtocol (
71                   &gEfiSmmCommunicationProtocolGuid,
72                   NULL,
73                   (VOID **)&SmmCommunication
74                   );
75   if (EFI_ERROR (Status)) {
76     return EFI_NOT_STARTED;
77   }
78 
79   //
80   // Prepare parameter
81   //
82   CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0];
83   CopyMem (&CommHeader->HeaderGuid, &gEfiSmmLockBoxCommunicationGuid, sizeof(gEfiSmmLockBoxCommunicationGuid));
84   CommHeader->MessageLength = sizeof(*LockBoxParameterSave);
85 
86   LockBoxParameterSave = (EFI_SMM_LOCK_BOX_PARAMETER_SAVE *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
87   LockBoxParameterSave->Header.Command    = EFI_SMM_LOCK_BOX_COMMAND_SAVE;
88   LockBoxParameterSave->Header.DataLength = sizeof(*LockBoxParameterSave);
89   LockBoxParameterSave->Header.ReturnStatus = (UINT64)-1;
90   CopyMem (&LockBoxParameterSave->Guid, Guid, sizeof(*Guid));
91   LockBoxParameterSave->Buffer     = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer;
92   LockBoxParameterSave->Length     = (UINT64)Length;
93 
94   //
95   // Send command
96   //
97   CommSize = sizeof(CommBuffer);
98   Status = SmmCommunication->Communicate (
99                                SmmCommunication,
100                                &CommBuffer[0],
101                                &CommSize
102                                );
103   ASSERT_EFI_ERROR (Status);
104 
105   Status = (EFI_STATUS)LockBoxParameterSave->Header.ReturnStatus;
106 
107   DEBUG ((EFI_D_INFO, "SmmLockBoxDxeLib SaveLockBox - Exit (%r)\n", Status));
108 
109   //
110   // Done
111   //
112   return Status;
113 }
114 
115 /**
116   This function will set lockbox attributes.
117 
118   @param Guid       the guid to identify the confidential information
119   @param Attributes the attributes of the lockbox
120 
121   @retval RETURN_SUCCESS            the information is saved successfully.
122   @retval RETURN_INVALID_PARAMETER  attributes is invalid.
123   @retval RETURN_NOT_FOUND          the requested GUID not found.
124   @retval RETURN_ACCESS_DENIED      it is too late to invoke this interface
125   @retval RETURN_NOT_STARTED        it is too early to invoke this interface
126   @retval RETURN_UNSUPPORTED        the service is not supported by implementaion.
127 **/
128 RETURN_STATUS
129 EFIAPI
SetLockBoxAttributes(IN GUID * Guid,IN UINT64 Attributes)130 SetLockBoxAttributes (
131   IN  GUID                        *Guid,
132   IN  UINT64                      Attributes
133   )
134 {
135   EFI_STATUS                                Status;
136   EFI_SMM_COMMUNICATION_PROTOCOL            *SmmCommunication;
137   EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES *LockBoxParameterSetAttributes;
138   EFI_SMM_COMMUNICATE_HEADER                *CommHeader;
139   UINT8                                     CommBuffer[sizeof(EFI_GUID) + sizeof(UINTN) + sizeof(EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES)];
140   UINTN                                     CommSize;
141 
142   DEBUG ((EFI_D_INFO, "SmmLockBoxDxeLib SetLockBoxAttributes - Enter\n"));
143 
144   //
145   // Basic check
146   //
147   if ((Guid == NULL) ||
148       ((Attributes & ~LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) != 0)) {
149     return EFI_INVALID_PARAMETER;
150   }
151 
152   //
153   // Get needed resource
154   //
155   Status = gBS->LocateProtocol (
156                   &gEfiSmmCommunicationProtocolGuid,
157                   NULL,
158                   (VOID **)&SmmCommunication
159                   );
160   if (EFI_ERROR (Status)) {
161     return EFI_NOT_STARTED;
162   }
163 
164   //
165   // Prepare parameter
166   //
167   CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0];
168   CopyMem (&CommHeader->HeaderGuid, &gEfiSmmLockBoxCommunicationGuid, sizeof(gEfiSmmLockBoxCommunicationGuid));
169   CommHeader->MessageLength = sizeof(*LockBoxParameterSetAttributes);
170 
171   LockBoxParameterSetAttributes = (EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
172   LockBoxParameterSetAttributes->Header.Command    = EFI_SMM_LOCK_BOX_COMMAND_SET_ATTRIBUTES;
173   LockBoxParameterSetAttributes->Header.DataLength = sizeof(*LockBoxParameterSetAttributes);
174   LockBoxParameterSetAttributes->Header.ReturnStatus = (UINT64)-1;
175   CopyMem (&LockBoxParameterSetAttributes->Guid, Guid, sizeof(*Guid));
176   LockBoxParameterSetAttributes->Attributes = (UINT64)Attributes;
177 
178   //
179   // Send command
180   //
181   CommSize = sizeof(CommBuffer);
182   Status = SmmCommunication->Communicate (
183                                SmmCommunication,
184                                &CommBuffer[0],
185                                &CommSize
186                                );
187   ASSERT_EFI_ERROR (Status);
188 
189   Status = (EFI_STATUS)LockBoxParameterSetAttributes->Header.ReturnStatus;
190 
191   DEBUG ((EFI_D_INFO, "SmmLockBoxDxeLib SetLockBoxAttributes - Exit (%r)\n", Status));
192 
193   //
194   // Done
195   //
196   return Status;
197 }
198 
199 /**
200   This function will update confidential information to lockbox.
201 
202   @param Guid   the guid to identify the original confidential information
203   @param Offset the offset of the original confidential information
204   @param Buffer the address of the updated confidential information
205   @param Length the length of the updated confidential information
206 
207   @retval RETURN_SUCCESS            the information is saved successfully.
208   @retval RETURN_INVALID_PARAMETER  the Guid is NULL, or Buffer is NULL, or Length is 0.
209   @retval RETURN_NOT_FOUND          the requested GUID not found.
210   @retval RETURN_BUFFER_TOO_SMALL   the original buffer to too small to hold new information.
211   @retval RETURN_ACCESS_DENIED      it is too late to invoke this interface
212   @retval RETURN_NOT_STARTED        it is too early to invoke this interface
213   @retval RETURN_UNSUPPORTED        the service is not supported by implementaion.
214 **/
215 RETURN_STATUS
216 EFIAPI
UpdateLockBox(IN GUID * Guid,IN UINTN Offset,IN VOID * Buffer,IN UINTN Length)217 UpdateLockBox (
218   IN  GUID                        *Guid,
219   IN  UINTN                       Offset,
220   IN  VOID                        *Buffer,
221   IN  UINTN                       Length
222   )
223 {
224   EFI_STATUS                        Status;
225   EFI_SMM_COMMUNICATION_PROTOCOL    *SmmCommunication;
226   EFI_SMM_LOCK_BOX_PARAMETER_UPDATE *LockBoxParameterUpdate;
227   EFI_SMM_COMMUNICATE_HEADER        *CommHeader;
228   UINT8                             CommBuffer[sizeof(EFI_GUID) + sizeof(UINTN) + sizeof(EFI_SMM_LOCK_BOX_PARAMETER_UPDATE)];
229   UINTN                             CommSize;
230 
231   DEBUG ((EFI_D_INFO, "SmmLockBoxDxeLib UpdateLockBox - Enter\n"));
232 
233   //
234   // Basic check
235   //
236   if ((Guid == NULL) || (Buffer == NULL) || (Length == 0)) {
237     return EFI_INVALID_PARAMETER;
238   }
239 
240   //
241   // Get needed resource
242   //
243   Status = gBS->LocateProtocol (
244                   &gEfiSmmCommunicationProtocolGuid,
245                   NULL,
246                   (VOID **)&SmmCommunication
247                   );
248   if (EFI_ERROR (Status)) {
249     return EFI_NOT_STARTED;
250   }
251 
252   //
253   // Prepare parameter
254   //
255   CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0];
256   CopyMem (&CommHeader->HeaderGuid, &gEfiSmmLockBoxCommunicationGuid, sizeof(gEfiSmmLockBoxCommunicationGuid));
257   CommHeader->MessageLength = sizeof(*LockBoxParameterUpdate);
258 
259   LockBoxParameterUpdate = (EFI_SMM_LOCK_BOX_PARAMETER_UPDATE *)(UINTN)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
260   LockBoxParameterUpdate->Header.Command    = EFI_SMM_LOCK_BOX_COMMAND_UPDATE;
261   LockBoxParameterUpdate->Header.DataLength = sizeof(*LockBoxParameterUpdate);
262   LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)-1;
263   CopyMem (&LockBoxParameterUpdate->Guid, Guid, sizeof(*Guid));
264   LockBoxParameterUpdate->Offset = (UINT64)Offset;
265   LockBoxParameterUpdate->Buffer = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer;
266   LockBoxParameterUpdate->Length = (UINT64)Length;
267 
268   //
269   // Send command
270   //
271   CommSize = sizeof(CommBuffer);
272   Status = SmmCommunication->Communicate (
273                                SmmCommunication,
274                                &CommBuffer[0],
275                                &CommSize
276                                );
277   ASSERT_EFI_ERROR (Status);
278 
279   Status = (EFI_STATUS)LockBoxParameterUpdate->Header.ReturnStatus;
280 
281   DEBUG ((EFI_D_INFO, "SmmLockBoxDxeLib UpdateLockBox - Exit (%r)\n", Status));
282 
283   //
284   // Done
285   //
286   return Status;
287 }
288 
289 /**
290   This function will restore confidential information from lockbox.
291 
292   @param Guid   the guid to identify the confidential information
293   @param Buffer the address of the restored confidential information
294                 NULL means restored to original address, Length MUST be NULL at same time.
295   @param Length the length of the restored confidential information
296 
297   @retval RETURN_SUCCESS            the information is restored successfully.
298   @retval RETURN_INVALID_PARAMETER  the Guid is NULL, or one of Buffer and Length is NULL.
299   @retval RETURN_WRITE_PROTECTED    Buffer and Length are NULL, but the LockBox has no
300                                     LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE attribute.
301   @retval RETURN_BUFFER_TOO_SMALL   the Length is too small to hold the confidential information.
302   @retval RETURN_NOT_FOUND          the requested GUID not found.
303   @retval RETURN_NOT_STARTED        it is too early to invoke this interface
304   @retval RETURN_ACCESS_DENIED      not allow to restore to the address
305   @retval RETURN_UNSUPPORTED        the service is not supported by implementaion.
306 **/
307 RETURN_STATUS
308 EFIAPI
RestoreLockBox(IN GUID * Guid,IN VOID * Buffer,OPTIONAL IN OUT UINTN * Length OPTIONAL)309 RestoreLockBox (
310   IN  GUID                        *Guid,
311   IN  VOID                        *Buffer, OPTIONAL
312   IN  OUT UINTN                   *Length  OPTIONAL
313   )
314 {
315   EFI_STATUS                         Status;
316   EFI_SMM_COMMUNICATION_PROTOCOL     *SmmCommunication;
317   EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *LockBoxParameterRestore;
318   EFI_SMM_COMMUNICATE_HEADER         *CommHeader;
319   UINT8                              CommBuffer[sizeof(EFI_GUID) + sizeof(UINTN) + sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE)];
320   UINTN                              CommSize;
321 
322   DEBUG ((EFI_D_INFO, "SmmLockBoxDxeLib RestoreLockBox - Enter\n"));
323 
324   //
325   // Basic check
326   //
327   if ((Guid == NULL) ||
328       ((Buffer == NULL) && (Length != NULL)) ||
329       ((Buffer != NULL) && (Length == NULL))) {
330     return EFI_INVALID_PARAMETER;
331   }
332 
333   //
334   // Get needed resource
335   //
336   Status = gBS->LocateProtocol (
337                   &gEfiSmmCommunicationProtocolGuid,
338                   NULL,
339                   (VOID **)&SmmCommunication
340                   );
341   if (EFI_ERROR (Status)) {
342     return EFI_NOT_STARTED;
343   }
344 
345   //
346   // Prepare parameter
347   //
348   CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0];
349   CopyMem (&CommHeader->HeaderGuid, &gEfiSmmLockBoxCommunicationGuid, sizeof(gEfiSmmLockBoxCommunicationGuid));
350   CommHeader->MessageLength = sizeof(*LockBoxParameterRestore);
351 
352   LockBoxParameterRestore = (EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
353   LockBoxParameterRestore->Header.Command    = EFI_SMM_LOCK_BOX_COMMAND_RESTORE;
354   LockBoxParameterRestore->Header.DataLength = sizeof(*LockBoxParameterRestore);
355   LockBoxParameterRestore->Header.ReturnStatus = (UINT64)-1;
356   CopyMem (&LockBoxParameterRestore->Guid, Guid, sizeof(*Guid));
357   LockBoxParameterRestore->Buffer = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer;
358   if (Length != NULL) {
359     LockBoxParameterRestore->Length = (EFI_PHYSICAL_ADDRESS)*Length;
360   } else {
361     LockBoxParameterRestore->Length = 0;
362   }
363 
364   //
365   // Send command
366   //
367   CommSize = sizeof(CommBuffer);
368   Status = SmmCommunication->Communicate (
369                                SmmCommunication,
370                                &CommBuffer[0],
371                                &CommSize
372                                );
373   ASSERT_EFI_ERROR (Status);
374 
375   if (Length != NULL) {
376     *Length = (UINTN)LockBoxParameterRestore->Length;
377   }
378 
379   Status = (EFI_STATUS)LockBoxParameterRestore->Header.ReturnStatus;
380 
381   DEBUG ((EFI_D_INFO, "SmmLockBoxDxeLib RestoreLockBox - Exit (%r)\n", Status));
382 
383   //
384   // Done
385   //
386   return Status;
387 }
388 
389 /**
390   This function will restore confidential information from all lockbox which have RestoreInPlace attribute.
391 
392   @retval RETURN_SUCCESS            the information is restored successfully.
393   @retval RETURN_NOT_STARTED        it is too early to invoke this interface
394   @retval RETURN_UNSUPPORTED        the service is not supported by implementaion.
395 **/
396 RETURN_STATUS
397 EFIAPI
RestoreAllLockBoxInPlace(VOID)398 RestoreAllLockBoxInPlace (
399   VOID
400   )
401 {
402   EFI_STATUS                                      Status;
403   EFI_SMM_COMMUNICATION_PROTOCOL                  *SmmCommunication;
404   EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *LockBoxParameterRestoreAllInPlace;
405   EFI_SMM_COMMUNICATE_HEADER                      *CommHeader;
406   UINT8                                           CommBuffer[sizeof(EFI_GUID) + sizeof(UINTN) + sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE)];
407   UINTN                                           CommSize;
408 
409   DEBUG ((EFI_D_INFO, "SmmLockBoxDxeLib RestoreAllLockBoxInPlace - Enter\n"));
410 
411   //
412   // Get needed resource
413   //
414   Status = gBS->LocateProtocol (
415                   &gEfiSmmCommunicationProtocolGuid,
416                   NULL,
417                   (VOID **)&SmmCommunication
418                   );
419   if (EFI_ERROR (Status)) {
420     return EFI_NOT_STARTED;
421   }
422 
423   //
424   // Prepare parameter
425   //
426   CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0];
427   CopyMem (&CommHeader->HeaderGuid, &gEfiSmmLockBoxCommunicationGuid, sizeof(gEfiSmmLockBoxCommunicationGuid));
428   CommHeader->MessageLength = sizeof(*LockBoxParameterRestoreAllInPlace);
429 
430   LockBoxParameterRestoreAllInPlace = (EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
431   LockBoxParameterRestoreAllInPlace->Header.Command    = EFI_SMM_LOCK_BOX_COMMAND_RESTORE_ALL_IN_PLACE;
432   LockBoxParameterRestoreAllInPlace->Header.DataLength = sizeof(*LockBoxParameterRestoreAllInPlace);
433   LockBoxParameterRestoreAllInPlace->Header.ReturnStatus = (UINT64)-1;
434 
435   //
436   // Send command
437   //
438   CommSize = sizeof(CommBuffer);
439   Status = SmmCommunication->Communicate (
440                                SmmCommunication,
441                                &CommBuffer[0],
442                                &CommSize
443                                );
444   ASSERT_EFI_ERROR (Status);
445 
446   Status = (EFI_STATUS)LockBoxParameterRestoreAllInPlace->Header.ReturnStatus;
447 
448   DEBUG ((EFI_D_INFO, "SmmLockBoxDxeLib RestoreAllLockBoxInPlace - Exit (%r)\n", Status));
449 
450   //
451   // Done
452   //
453   return Status;
454 }
455 
456