Home | History | Annotate | Download | only in SecureBootConfigDxe
      1 /** @file
      2   Internal file explorer functions for SecureBoot configuration module.
      3 
      4 Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "SecureBootConfigImpl.h"
     16 
     17 VOID                  *mStartOpCodeHandle = NULL;
     18 VOID                  *mEndOpCodeHandle = NULL;
     19 EFI_IFR_GUID_LABEL    *mStartLabel = NULL;
     20 EFI_IFR_GUID_LABEL    *mEndLabel = NULL;
     21 
     22 /**
     23   Refresh the global UpdateData structure.
     24 
     25 **/
     26 VOID
     27 RefreshUpdateData (
     28   VOID
     29   )
     30 {
     31   //
     32   // Free current updated date
     33   //
     34   if (mStartOpCodeHandle != NULL) {
     35     HiiFreeOpCodeHandle (mStartOpCodeHandle);
     36   }
     37 
     38   //
     39   // Create new OpCode Handle
     40   //
     41   mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
     42 
     43   //
     44   // Create Hii Extend Label OpCode as the start opcode
     45   //
     46   mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
     47                                          mStartOpCodeHandle,
     48                                          &gEfiIfrTianoGuid,
     49                                          NULL,
     50                                          sizeof (EFI_IFR_GUID_LABEL)
     51                                          );
     52   mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
     53 }
     54 
     55 /**
     56   Clean up the dynamic opcode at label and form specified by both LabelId.
     57 
     58   @param[in] LabelId         It is both the Form ID and Label ID for opcode deletion.
     59   @param[in] PrivateData     Module private data.
     60 
     61 **/
     62 VOID
     63 CleanUpPage (
     64   IN UINT16                           LabelId,
     65   IN SECUREBOOT_CONFIG_PRIVATE_DATA   *PrivateData
     66   )
     67 {
     68   RefreshUpdateData ();
     69 
     70   //
     71   // Remove all op-codes from dynamic page
     72   //
     73   mStartLabel->Number = LabelId;
     74   HiiUpdateForm (
     75     PrivateData->HiiHandle,
     76     &gSecureBootConfigFormSetGuid,
     77     LabelId,
     78     mStartOpCodeHandle, // Label LabelId
     79     mEndOpCodeHandle    // LABEL_END
     80     );
     81 }
     82 
     83 /**
     84   This function will open a file or directory referenced by DevicePath.
     85 
     86   This function opens a file with the open mode according to the file path. The
     87   Attributes is valid only for EFI_FILE_MODE_CREATE.
     88 
     89   @param[in, out]  FilePath        On input, the device path to the file.
     90                                    On output, the remaining device path.
     91   @param[out]      FileHandle      Pointer to the file handle.
     92   @param[in]       OpenMode        The mode to open the file with.
     93   @param[in]       Attributes      The file's file attributes.
     94 
     95   @retval EFI_SUCCESS              The information was set.
     96   @retval EFI_INVALID_PARAMETER    One of the parameters has an invalid value.
     97   @retval EFI_UNSUPPORTED          Could not open the file path.
     98   @retval EFI_NOT_FOUND            The specified file could not be found on the
     99                                    device or the file system could not be found on
    100                                    the device.
    101   @retval EFI_NO_MEDIA             The device has no medium.
    102   @retval EFI_MEDIA_CHANGED        The device has a different medium in it or the
    103                                    medium is no longer supported.
    104   @retval EFI_DEVICE_ERROR         The device reported an error.
    105   @retval EFI_VOLUME_CORRUPTED     The file system structures are corrupted.
    106   @retval EFI_WRITE_PROTECTED      The file or medium is write protected.
    107   @retval EFI_ACCESS_DENIED        The file was opened read only.
    108   @retval EFI_OUT_OF_RESOURCES     Not enough resources were available to open the
    109                                    file.
    110   @retval EFI_VOLUME_FULL          The volume is full.
    111 **/
    112 EFI_STATUS
    113 EFIAPI
    114 OpenFileByDevicePath(
    115   IN OUT EFI_DEVICE_PATH_PROTOCOL     **FilePath,
    116   OUT EFI_FILE_HANDLE                 *FileHandle,
    117   IN UINT64                           OpenMode,
    118   IN UINT64                           Attributes
    119   )
    120 {
    121   EFI_STATUS                      Status;
    122   EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol;
    123   EFI_FILE_PROTOCOL               *Handle1;
    124   EFI_FILE_PROTOCOL               *Handle2;
    125   EFI_HANDLE                      DeviceHandle;
    126 
    127   if ((FilePath == NULL || FileHandle == NULL)) {
    128     return EFI_INVALID_PARAMETER;
    129   }
    130 
    131   Status = gBS->LocateDevicePath (
    132                   &gEfiSimpleFileSystemProtocolGuid,
    133                   FilePath,
    134                   &DeviceHandle
    135                   );
    136   if (EFI_ERROR (Status)) {
    137     return Status;
    138   }
    139 
    140   Status = gBS->OpenProtocol(
    141                   DeviceHandle,
    142                   &gEfiSimpleFileSystemProtocolGuid,
    143                   (VOID**)&EfiSimpleFileSystemProtocol,
    144                   gImageHandle,
    145                   NULL,
    146                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    147                   );
    148   if (EFI_ERROR (Status)) {
    149     return Status;
    150   }
    151 
    152   Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, &Handle1);
    153   if (EFI_ERROR (Status)) {
    154     FileHandle = NULL;
    155     return Status;
    156   }
    157 
    158   //
    159   // go down directories one node at a time.
    160   //
    161   while (!IsDevicePathEnd (*FilePath)) {
    162     //
    163     // For file system access each node should be a file path component
    164     //
    165     if (DevicePathType    (*FilePath) != MEDIA_DEVICE_PATH ||
    166         DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP
    167        ) {
    168       FileHandle = NULL;
    169       return (EFI_INVALID_PARAMETER);
    170     }
    171     //
    172     // Open this file path node
    173     //
    174     Handle2  = Handle1;
    175     Handle1 = NULL;
    176 
    177     //
    178     // Try to test opening an existing file
    179     //
    180     Status = Handle2->Open (
    181                           Handle2,
    182                           &Handle1,
    183                           ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
    184                           OpenMode &~EFI_FILE_MODE_CREATE,
    185                           0
    186                          );
    187 
    188     //
    189     // see if the error was that it needs to be created
    190     //
    191     if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) {
    192       Status = Handle2->Open (
    193                             Handle2,
    194                             &Handle1,
    195                             ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
    196                             OpenMode,
    197                             Attributes
    198                            );
    199     }
    200     //
    201     // Close the last node
    202     //
    203     Handle2->Close (Handle2);
    204 
    205     if (EFI_ERROR(Status)) {
    206       return (Status);
    207     }
    208 
    209     //
    210     // Get the next node
    211     //
    212     *FilePath = NextDevicePathNode (*FilePath);
    213   }
    214 
    215   //
    216   // This is a weak spot since if the undefined SHELL_FILE_HANDLE format changes this must change also!
    217   //
    218   *FileHandle = (VOID*)Handle1;
    219   return EFI_SUCCESS;
    220 }
    221 
    222 
    223 /**
    224   Extract filename from device path. The returned buffer is allocated using AllocateCopyPool.
    225   The caller is responsible for freeing the allocated buffer using FreePool(). If return NULL
    226   means not enough memory resource.
    227 
    228   @param DevicePath       Device path.
    229 
    230   @retval NULL            Not enough memory resourece for AllocateCopyPool.
    231   @retval Other           A new allocated string that represents the file name.
    232 
    233 **/
    234 CHAR16 *
    235 ExtractFileNameFromDevicePath (
    236   IN   EFI_DEVICE_PATH_PROTOCOL *DevicePath
    237   )
    238 {
    239   CHAR16          *String;
    240   CHAR16          *MatchString;
    241   CHAR16          *LastMatch;
    242   CHAR16          *FileName;
    243   UINTN           Length;
    244 
    245   ASSERT(DevicePath != NULL);
    246 
    247   String = DevicePathToStr(DevicePath);
    248   MatchString = String;
    249   LastMatch   = String;
    250   FileName    = NULL;
    251 
    252   while(MatchString != NULL){
    253     LastMatch   = MatchString + 1;
    254     MatchString = StrStr(LastMatch,L"\\");
    255   }
    256 
    257   Length = StrLen(LastMatch);
    258   FileName = AllocateCopyPool ((Length + 1) * sizeof(CHAR16), LastMatch);
    259   if (FileName != NULL) {
    260     *(FileName + Length) = 0;
    261   }
    262 
    263   FreePool(String);
    264 
    265   return FileName;
    266 }
    267 
    268 
    269 /**
    270   Update  the form base on the selected file.
    271 
    272   @param FilePath   Point to the file path.
    273   @param FormId     The form need to display.
    274 
    275   @retval TRUE   Exit caller function.
    276   @retval FALSE  Not exit caller function.
    277 
    278 **/
    279 BOOLEAN
    280 UpdatePage(
    281   IN  EFI_DEVICE_PATH_PROTOCOL  *FilePath,
    282   IN  EFI_FORM_ID               FormId
    283   )
    284 {
    285   CHAR16                *FileName;
    286   EFI_STRING_ID         StringToken;
    287 
    288   FileName = NULL;
    289 
    290   if (FilePath != NULL) {
    291     FileName = ExtractFileNameFromDevicePath(FilePath);
    292   }
    293   if (FileName == NULL) {
    294     //
    295     // FileName = NULL has two case:
    296     // 1. FilePath == NULL, not select file.
    297     // 2. FilePath != NULL, but ExtractFileNameFromDevicePath return NULL not enough memory resource.
    298     // In these two case, no need to update the form, and exit the caller function.
    299     //
    300     return TRUE;
    301   }
    302   StringToken =  HiiSetString (gSecureBootPrivateData->HiiHandle, 0, FileName, NULL);
    303 
    304   gSecureBootPrivateData->FileContext->FileName = FileName;
    305 
    306   OpenFileByDevicePath(
    307     &FilePath,
    308     &gSecureBootPrivateData->FileContext->FHandle,
    309     EFI_FILE_MODE_READ,
    310     0
    311     );
    312   //
    313   // Create Subtitle op-code for the display string of the option.
    314   //
    315   RefreshUpdateData ();
    316   mStartLabel->Number = FormId;
    317 
    318   HiiCreateSubTitleOpCode (
    319     mStartOpCodeHandle,
    320     StringToken,
    321     0,
    322     0,
    323     0
    324    );
    325 
    326   HiiUpdateForm (
    327     gSecureBootPrivateData->HiiHandle,
    328     &gSecureBootConfigFormSetGuid,
    329     FormId,
    330     mStartOpCodeHandle, // Label FormId
    331     mEndOpCodeHandle    // LABEL_END
    332     );
    333 
    334   return TRUE;
    335 }
    336 
    337 /**
    338   Update the PK form base on the input file path info.
    339 
    340   @param FilePath    Point to the file path.
    341 
    342   @retval TRUE   Exit caller function.
    343   @retval FALSE  Not exit caller function.
    344 **/
    345 BOOLEAN
    346 EFIAPI
    347 UpdatePKFromFile (
    348   IN EFI_DEVICE_PATH_PROTOCOL    *FilePath
    349   )
    350 {
    351   return UpdatePage(FilePath, FORMID_ENROLL_PK_FORM);
    352 
    353 }
    354 
    355 /**
    356   Update the KEK form base on the input file path info.
    357 
    358   @param FilePath    Point to the file path.
    359 
    360   @retval TRUE   Exit caller function.
    361   @retval FALSE  Not exit caller function.
    362 **/
    363 BOOLEAN
    364 EFIAPI
    365 UpdateKEKFromFile (
    366   IN EFI_DEVICE_PATH_PROTOCOL    *FilePath
    367   )
    368 {
    369   return UpdatePage(FilePath, FORMID_ENROLL_KEK_FORM);
    370 }
    371 
    372 /**
    373   Update the DB form base on the input file path info.
    374 
    375   @param FilePath    Point to the file path.
    376 
    377   @retval TRUE   Exit caller function.
    378   @retval FALSE  Not exit caller function.
    379 **/
    380 BOOLEAN
    381 EFIAPI
    382 UpdateDBFromFile (
    383   IN EFI_DEVICE_PATH_PROTOCOL    *FilePath
    384   )
    385 {
    386   return UpdatePage(FilePath, SECUREBOOT_ENROLL_SIGNATURE_TO_DB);
    387 }
    388 
    389 /**
    390   Update the DBX form base on the input file path info.
    391 
    392   @param FilePath    Point to the file path.
    393 
    394   @retval TRUE   Exit caller function.
    395   @retval FALSE  Not exit caller function.
    396 **/
    397 BOOLEAN
    398 EFIAPI
    399 UpdateDBXFromFile (
    400   IN EFI_DEVICE_PATH_PROTOCOL    *FilePath
    401   )
    402 {
    403   return UpdatePage(FilePath, SECUREBOOT_ENROLL_SIGNATURE_TO_DBX);
    404 }
    405 
    406 /**
    407   Update the DBT form base on the input file path info.
    408 
    409   @param FilePath    Point to the file path.
    410 
    411   @retval TRUE   Exit caller function.
    412   @retval FALSE  Not exit caller function.
    413 **/
    414 BOOLEAN
    415 EFIAPI
    416 UpdateDBTFromFile (
    417   IN EFI_DEVICE_PATH_PROTOCOL    *FilePath
    418   )
    419 {
    420   return UpdatePage(FilePath, SECUREBOOT_ENROLL_SIGNATURE_TO_DBT);
    421 }
    422 
    423