Home | History | Annotate | Download | only in SmmLockBoxLib
      1 /** @file
      2 
      3 Copyright (c) 2010 - 2015, 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 <PiSmm.h>
     17 #include <Library/SmmServicesTableLib.h>
     18 #include <Library/BaseLib.h>
     19 #include <Library/BaseMemoryLib.h>
     20 #include <Library/LockBoxLib.h>
     21 #include <Library/DebugLib.h>
     22 #include <Guid/SmmLockBox.h>
     23 
     24 #include "SmmLockBoxLibPrivate.h"
     25 
     26 /**
     27   We need handle this library carefully. Only one library instance will construct the environment.
     28   Below 2 global variable can only be used in constructor. They should NOT be used in any other library functions.
     29 **/
     30 SMM_LOCK_BOX_CONTEXT mSmmLockBoxContext;
     31 LIST_ENTRY           mLockBoxQueue = INITIALIZE_LIST_HEAD_VARIABLE (mLockBoxQueue);
     32 
     33 /**
     34   This function return SmmLockBox context from SMST.
     35 
     36   @return SmmLockBox context from SMST.
     37 **/
     38 SMM_LOCK_BOX_CONTEXT *
     39 InternalGetSmmLockBoxContext (
     40   VOID
     41   )
     42 {
     43   UINTN   Index;
     44 
     45   //
     46   // Check if gEfiSmmLockBoxCommunicationGuid is installed by someone
     47   //
     48   for (Index = 0; Index < gSmst->NumberOfTableEntries; Index++) {
     49     if (CompareGuid (&gSmst->SmmConfigurationTable[Index].VendorGuid, &gEfiSmmLockBoxCommunicationGuid)) {
     50       //
     51       // Found. That means some other library instance is already run.
     52       // No need to install again, just return.
     53       //
     54       return (SMM_LOCK_BOX_CONTEXT *)gSmst->SmmConfigurationTable[Index].VendorTable;
     55     }
     56   }
     57 
     58   //
     59   // Not found.
     60   //
     61   return NULL;
     62 }
     63 
     64 /**
     65   Constructor for SmmLockBox library.
     66   This is used to set SmmLockBox context, which will be used in PEI phase in S3 boot path later.
     67 
     68   @param[in] ImageHandle  Image handle of this driver.
     69   @param[in] SystemTable  A Pointer to the EFI System Table.
     70 
     71   @retval EFI_SUCEESS
     72   @return Others          Some error occurs.
     73 **/
     74 EFI_STATUS
     75 EFIAPI
     76 SmmLockBoxSmmConstructuor (
     77   IN EFI_HANDLE        ImageHandle,
     78   IN EFI_SYSTEM_TABLE  *SystemTable
     79   )
     80 {
     81   EFI_STATUS           Status;
     82   SMM_LOCK_BOX_CONTEXT *SmmLockBoxContext;
     83 
     84   DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SmmLockBoxSmmConstructuor - Enter\n"));
     85 
     86   //
     87   // Check if gEfiSmmLockBoxCommunicationGuid is installed by someone
     88   //
     89   SmmLockBoxContext = InternalGetSmmLockBoxContext ();
     90   if (SmmLockBoxContext != NULL) {
     91     //
     92     // Find it. That means some other library instance is already run.
     93     // No need to install again, just return.
     94     //
     95     DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SmmLockBoxContext - already installed\n"));
     96     DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SmmLockBoxSmmConstructuor - Exit\n"));
     97     return EFI_SUCCESS;
     98   }
     99 
    100   //
    101   // If no one install this, it means this is first instance. Install it.
    102   //
    103   if (sizeof(UINTN) == sizeof(UINT64)) {
    104     mSmmLockBoxContext.Signature = SMM_LOCK_BOX_SIGNATURE_64;
    105   } else {
    106     mSmmLockBoxContext.Signature = SMM_LOCK_BOX_SIGNATURE_32;
    107   }
    108   mSmmLockBoxContext.LockBoxDataAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)&mLockBoxQueue;
    109 
    110   Status = gSmst->SmmInstallConfigurationTable (
    111                     gSmst,
    112                     &gEfiSmmLockBoxCommunicationGuid,
    113                     &mSmmLockBoxContext,
    114                     sizeof(mSmmLockBoxContext)
    115                     );
    116   ASSERT_EFI_ERROR (Status);
    117 
    118   DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SmmLockBoxContext - %x\n", (UINTN)&mSmmLockBoxContext));
    119   DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib LockBoxDataAddress - %x\n", (UINTN)&mLockBoxQueue));
    120   DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SmmLockBoxSmmConstructuor - Exit\n"));
    121 
    122   return Status;
    123 }
    124 
    125 /**
    126   This function return SmmLockBox queue address.
    127 
    128   @return SmmLockBox queue address.
    129 **/
    130 LIST_ENTRY *
    131 InternalGetLockBoxQueue (
    132   VOID
    133   )
    134 {
    135   SMM_LOCK_BOX_CONTEXT        *SmmLockBoxContext;
    136 
    137   SmmLockBoxContext = InternalGetSmmLockBoxContext ();
    138   ASSERT (SmmLockBoxContext != NULL);
    139   if (SmmLockBoxContext == NULL) {
    140     return NULL;
    141   }
    142   return (LIST_ENTRY *)(UINTN)SmmLockBoxContext->LockBoxDataAddress;
    143 }
    144 
    145 /**
    146   This function find LockBox by GUID.
    147 
    148   @param Guid The guid to indentify the LockBox
    149 
    150   @return LockBoxData
    151 **/
    152 SMM_LOCK_BOX_DATA *
    153 InternalFindLockBoxByGuid (
    154   IN EFI_GUID   *Guid
    155   )
    156 {
    157   LIST_ENTRY                    *Link;
    158   SMM_LOCK_BOX_DATA             *LockBox;
    159   LIST_ENTRY                    *LockBoxQueue;
    160 
    161   LockBoxQueue = InternalGetLockBoxQueue ();
    162   ASSERT (LockBoxQueue != NULL);
    163 
    164   for (Link = LockBoxQueue->ForwardLink;
    165        Link != LockBoxQueue;
    166        Link = Link->ForwardLink) {
    167     LockBox = BASE_CR (
    168                 Link,
    169                 SMM_LOCK_BOX_DATA,
    170                 Link
    171                 );
    172     if (CompareGuid (&LockBox->Guid, Guid)) {
    173       return LockBox;
    174     }
    175   }
    176   return NULL;
    177 }
    178 
    179 /**
    180   This function will save confidential information to lockbox.
    181 
    182   @param Guid       the guid to identify the confidential information
    183   @param Buffer     the address of the confidential information
    184   @param Length     the length of the confidential information
    185 
    186   @retval RETURN_SUCCESS            the information is saved successfully.
    187   @retval RETURN_INVALID_PARAMETER  the Guid is NULL, or Buffer is NULL, or Length is 0
    188   @retval RETURN_ALREADY_STARTED    the requested GUID already exist.
    189   @retval RETURN_OUT_OF_RESOURCES   no enough resource to save the information.
    190   @retval RETURN_ACCESS_DENIED      it is too late to invoke this interface
    191   @retval RETURN_NOT_STARTED        it is too early to invoke this interface
    192   @retval RETURN_UNSUPPORTED        the service is not supported by implementaion.
    193 **/
    194 RETURN_STATUS
    195 EFIAPI
    196 SaveLockBox (
    197   IN  GUID                        *Guid,
    198   IN  VOID                        *Buffer,
    199   IN  UINTN                       Length
    200   )
    201 {
    202   SMM_LOCK_BOX_DATA           *LockBox;
    203   EFI_PHYSICAL_ADDRESS        SmramBuffer;
    204   EFI_STATUS                  Status;
    205   LIST_ENTRY                  *LockBoxQueue;
    206 
    207   DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SaveLockBox - Enter\n"));
    208 
    209   //
    210   // Basic check
    211   //
    212   if ((Guid == NULL) || (Buffer == NULL) || (Length == 0)) {
    213     DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_INVALID_PARAMETER));
    214     return EFI_INVALID_PARAMETER;
    215   }
    216 
    217   //
    218   // Find LockBox
    219   //
    220   LockBox = InternalFindLockBoxByGuid (Guid);
    221   if (LockBox != NULL) {
    222     DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_ALREADY_STARTED));
    223     return EFI_ALREADY_STARTED;
    224   }
    225 
    226   //
    227   // Allocate SMRAM buffer
    228   //
    229   Status = gSmst->SmmAllocatePages (
    230                     AllocateAnyPages,
    231                     EfiRuntimeServicesData,
    232                     EFI_SIZE_TO_PAGES (Length),
    233                     &SmramBuffer
    234                     );
    235   ASSERT_EFI_ERROR (Status);
    236   if (EFI_ERROR (Status)) {
    237     DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_OUT_OF_RESOURCES));
    238     return EFI_OUT_OF_RESOURCES;
    239   }
    240 
    241   //
    242   // Allocate LockBox
    243   //
    244   Status = gSmst->SmmAllocatePool (
    245                     EfiRuntimeServicesData,
    246                     sizeof(*LockBox),
    247                     (VOID **)&LockBox
    248                     );
    249   ASSERT_EFI_ERROR (Status);
    250   if (EFI_ERROR (Status)) {
    251     gSmst->SmmFreePages (SmramBuffer, EFI_SIZE_TO_PAGES (Length));
    252     DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_OUT_OF_RESOURCES));
    253     return EFI_OUT_OF_RESOURCES;
    254   }
    255 
    256   //
    257   // Save data
    258   //
    259   CopyMem ((VOID *)(UINTN)SmramBuffer, (VOID *)(UINTN)Buffer, Length);
    260 
    261   //
    262   // Insert LockBox to queue
    263   //
    264   LockBox->Signature   = SMM_LOCK_BOX_DATA_SIGNATURE;
    265   CopyMem (&LockBox->Guid, Guid, sizeof(EFI_GUID));
    266   LockBox->Buffer      = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer;
    267   LockBox->Length      = (UINT64)Length;
    268   LockBox->Attributes  = 0;
    269   LockBox->SmramBuffer = SmramBuffer;
    270 
    271   DEBUG ((
    272     EFI_D_INFO,
    273     "LockBoxGuid - %g, SmramBuffer - 0x%lx, Length - 0x%lx\n",
    274     &LockBox->Guid,
    275     LockBox->SmramBuffer,
    276     LockBox->Length
    277     ));
    278 
    279   LockBoxQueue = InternalGetLockBoxQueue ();
    280   ASSERT (LockBoxQueue != NULL);
    281   InsertTailList (LockBoxQueue, &LockBox->Link);
    282 
    283   //
    284   // Done
    285   //
    286   DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_SUCCESS));
    287   return EFI_SUCCESS;
    288 }
    289 
    290 /**
    291   This function will set lockbox attributes.
    292 
    293   @param Guid       the guid to identify the confidential information
    294   @param Attributes the attributes of the lockbox
    295 
    296   @retval RETURN_SUCCESS            the information is saved successfully.
    297   @retval RETURN_INVALID_PARAMETER  attributes is invalid.
    298   @retval RETURN_NOT_FOUND          the requested GUID not found.
    299   @retval RETURN_ACCESS_DENIED      it is too late to invoke this interface
    300   @retval RETURN_NOT_STARTED        it is too early to invoke this interface
    301   @retval RETURN_UNSUPPORTED        the service is not supported by implementaion.
    302 **/
    303 RETURN_STATUS
    304 EFIAPI
    305 SetLockBoxAttributes (
    306   IN  GUID                        *Guid,
    307   IN  UINT64                      Attributes
    308   )
    309 {
    310   SMM_LOCK_BOX_DATA              *LockBox;
    311 
    312   DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes - Enter\n"));
    313 
    314   //
    315   // Basic check
    316   //
    317   if ((Guid == NULL) ||
    318       ((Attributes & ~LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) != 0)) {
    319     DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_INVALID_PARAMETER));
    320     return EFI_INVALID_PARAMETER;
    321   }
    322 
    323   //
    324   // Find LockBox
    325   //
    326   LockBox = InternalFindLockBoxByGuid (Guid);
    327   if (LockBox == NULL) {
    328     DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_NOT_FOUND));
    329     return EFI_NOT_FOUND;
    330   }
    331 
    332   //
    333   // Update data
    334   //
    335   LockBox->Attributes = Attributes;
    336 
    337   //
    338   // Done
    339   //
    340   DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_SUCCESS));
    341   return EFI_SUCCESS;
    342 }
    343 
    344 /**
    345   This function will update confidential information to lockbox.
    346 
    347   @param Guid   the guid to identify the original confidential information
    348   @param Offset the offset of the original confidential information
    349   @param Buffer the address of the updated confidential information
    350   @param Length the length of the updated confidential information
    351 
    352   @retval RETURN_SUCCESS            the information is saved successfully.
    353   @retval RETURN_INVALID_PARAMETER  the Guid is NULL, or Buffer is NULL, or Length is 0.
    354   @retval RETURN_NOT_FOUND          the requested GUID not found.
    355   @retval RETURN_BUFFER_TOO_SMALL   the original buffer to too small to hold new information.
    356   @retval RETURN_ACCESS_DENIED      it is too late to invoke this interface
    357   @retval RETURN_NOT_STARTED        it is too early to invoke this interface
    358   @retval RETURN_UNSUPPORTED        the service is not supported by implementaion.
    359 **/
    360 RETURN_STATUS
    361 EFIAPI
    362 UpdateLockBox (
    363   IN  GUID                        *Guid,
    364   IN  UINTN                       Offset,
    365   IN  VOID                        *Buffer,
    366   IN  UINTN                       Length
    367   )
    368 {
    369   SMM_LOCK_BOX_DATA             *LockBox;
    370 
    371   DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib UpdateLockBox - Enter\n"));
    372 
    373   //
    374   // Basic check
    375   //
    376   if ((Guid == NULL) || (Buffer == NULL) || (Length == 0)) {
    377     DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_INVALID_PARAMETER));
    378     return EFI_INVALID_PARAMETER;
    379   }
    380 
    381   //
    382   // Find LockBox
    383   //
    384   LockBox = InternalFindLockBoxByGuid (Guid);
    385   if (LockBox == NULL) {
    386     DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_NOT_FOUND));
    387     return EFI_NOT_FOUND;
    388   }
    389 
    390   //
    391   // Update data
    392   //
    393   if (LockBox->Length < Offset + Length) {
    394     DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_BUFFER_TOO_SMALL));
    395     return EFI_BUFFER_TOO_SMALL;
    396   }
    397   ASSERT ((UINTN)LockBox->SmramBuffer <= (MAX_ADDRESS - Offset));
    398   CopyMem ((VOID *)((UINTN)LockBox->SmramBuffer + Offset), Buffer, Length);
    399 
    400   //
    401   // Done
    402   //
    403   DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_SUCCESS));
    404   return EFI_SUCCESS;
    405 }
    406 
    407 /**
    408   This function will restore confidential information from lockbox.
    409 
    410   @param Guid   the guid to identify the confidential information
    411   @param Buffer the address of the restored confidential information
    412                 NULL means restored to original address, Length MUST be NULL at same time.
    413   @param Length the length of the restored confidential information
    414 
    415   @retval RETURN_SUCCESS            the information is restored successfully.
    416   @retval RETURN_INVALID_PARAMETER  the Guid is NULL, or one of Buffer and Length is NULL.
    417   @retval RETURN_WRITE_PROTECTED    Buffer and Length are NULL, but the LockBox has no
    418                                     LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE attribute.
    419   @retval RETURN_BUFFER_TOO_SMALL   the Length is too small to hold the confidential information.
    420   @retval RETURN_NOT_FOUND          the requested GUID not found.
    421   @retval RETURN_NOT_STARTED        it is too early to invoke this interface
    422   @retval RETURN_ACCESS_DENIED      not allow to restore to the address
    423   @retval RETURN_UNSUPPORTED        the service is not supported by implementaion.
    424 **/
    425 RETURN_STATUS
    426 EFIAPI
    427 RestoreLockBox (
    428   IN  GUID                        *Guid,
    429   IN  VOID                        *Buffer, OPTIONAL
    430   IN  OUT UINTN                   *Length  OPTIONAL
    431   )
    432 {
    433   SMM_LOCK_BOX_DATA              *LockBox;
    434   VOID                           *RestoreBuffer;
    435 
    436   DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib RestoreLockBox - Enter\n"));
    437 
    438   //
    439   // Restore this, Buffer and Length MUST be both NULL or both non-NULL
    440   //
    441   if ((Guid == NULL) ||
    442       ((Buffer == NULL) && (Length != NULL)) ||
    443       ((Buffer != NULL) && (Length == NULL))) {
    444     DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_INVALID_PARAMETER));
    445     return EFI_INVALID_PARAMETER;
    446   }
    447 
    448   //
    449   // Find LockBox
    450   //
    451   LockBox = InternalFindLockBoxByGuid (Guid);
    452   if (LockBox == NULL) {
    453     //
    454     // Not found
    455     //
    456     DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_NOT_FOUND));
    457     return EFI_NOT_FOUND;
    458   }
    459 
    460   //
    461   // Set RestoreBuffer
    462   //
    463   if (Buffer != NULL) {
    464     //
    465     // restore to new buffer
    466     //
    467     RestoreBuffer = Buffer;
    468   } else {
    469     //
    470     // restore to original buffer
    471     //
    472     if ((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) == 0) {
    473       DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_WRITE_PROTECTED));
    474       return EFI_WRITE_PROTECTED;
    475     }
    476     RestoreBuffer = (VOID *)(UINTN)LockBox->Buffer;
    477   }
    478 
    479   //
    480   // Set RestoreLength
    481   //
    482   if (Length != NULL) {
    483     if (*Length < (UINTN)LockBox->Length) {
    484       //
    485       // Input buffer is too small to hold all data.
    486       //
    487       *Length = (UINTN)LockBox->Length;
    488       DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_BUFFER_TOO_SMALL));
    489       return EFI_BUFFER_TOO_SMALL;
    490     }
    491     *Length = (UINTN)LockBox->Length;
    492   }
    493 
    494   //
    495   // Restore data
    496   //
    497   CopyMem (RestoreBuffer, (VOID *)(UINTN)LockBox->SmramBuffer, (UINTN)LockBox->Length);
    498 
    499   //
    500   // Done
    501   //
    502   DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_SUCCESS));
    503   return EFI_SUCCESS;
    504 }
    505 
    506 /**
    507   This function will restore confidential information from all lockbox which have RestoreInPlace attribute.
    508 
    509   @retval RETURN_SUCCESS            the information is restored successfully.
    510   @retval RETURN_NOT_STARTED        it is too early to invoke this interface
    511   @retval RETURN_UNSUPPORTED        the service is not supported by implementaion.
    512 **/
    513 RETURN_STATUS
    514 EFIAPI
    515 RestoreAllLockBoxInPlace (
    516   VOID
    517   )
    518 {
    519   SMM_LOCK_BOX_DATA             *LockBox;
    520   LIST_ENTRY                    *Link;
    521   LIST_ENTRY                    *LockBoxQueue;
    522 
    523   DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib RestoreAllLockBoxInPlace - Enter\n"));
    524 
    525   LockBoxQueue = InternalGetLockBoxQueue ();
    526   ASSERT (LockBoxQueue != NULL);
    527 
    528   //
    529   // Restore all, Buffer and Length MUST be NULL
    530   //
    531   for (Link = LockBoxQueue->ForwardLink;
    532        Link != LockBoxQueue;
    533        Link = Link->ForwardLink) {
    534     LockBox = BASE_CR (
    535                 Link,
    536                 SMM_LOCK_BOX_DATA,
    537                 Link
    538                 );
    539     if ((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) != 0) {
    540       //
    541       // Restore data
    542       //
    543       CopyMem ((VOID *)(UINTN)LockBox->Buffer, (VOID *)(UINTN)LockBox->SmramBuffer, (UINTN)LockBox->Length);
    544     }
    545   }
    546   //
    547   // Done
    548   //
    549   DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib RestoreAllLockBoxInPlace - Exit (%r)\n", EFI_SUCCESS));
    550   return EFI_SUCCESS;
    551 }
    552 
    553