Home | History | Annotate | Download | only in FvOnFv2Thunk
      1 /** @file
      2 UEFI PI specification supersedes Inte's Framework Specification.
      3 EFI_FIRMWARE_VOLUME_PROTOCOL defined in Intel Framework Pkg is replaced by
      4 EFI_FIRMWARE_VOLUME2_PROTOCOL in MdePkg.
      5 This module produces FV on top of FV2. This module is used on platform when both of
      6 these two conditions are true:
      7 1) Framework module consuming FV is present
      8 2) And the platform only produces FV2
      9 
     10 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
     11 This program and the accompanying materials
     12 are licensed and made available under the terms and conditions of the BSD License
     13 which accompanies this distribution.  The full text of the license may be found at
     14 http://opensource.org/licenses/bsd-license.php
     15 
     16 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     17 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     18 Module Name:
     19 
     20 **/
     21 
     22 #include <PiDxe.h>
     23 #include <Protocol/FirmwareVolume2.h>
     24 #include <Protocol/FirmwareVolume.h>
     25 #include <Library/BaseLib.h>
     26 #include <Library/DebugLib.h>
     27 #include <Library/UefiBootServicesTableLib.h>
     28 #include <Library/UefiDriverEntryPoint.h>
     29 #include <Library/UefiLib.h>
     30 #include <Library/MemoryAllocationLib.h>
     31 
     32 #define FIRMWARE_VOLUME_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('f', 'v', 't', 'h')
     33 
     34 typedef struct {
     35   UINTN                          Signature;
     36   EFI_FIRMWARE_VOLUME_PROTOCOL   FirmwareVolume;
     37   EFI_FIRMWARE_VOLUME2_PROTOCOL  *FirmwareVolume2;
     38 } FIRMWARE_VOLUME_PRIVATE_DATA;
     39 
     40 #define FIRMWARE_VOLUME_PRIVATE_DATA_FROM_THIS(a) CR (a, FIRMWARE_VOLUME_PRIVATE_DATA, FirmwareVolume, FIRMWARE_VOLUME_PRIVATE_DATA_SIGNATURE)
     41 
     42 /**
     43   Convert FV attrbiutes to FV2 attributes.
     44 
     45   @param Fv2Attributes FV2 attributes.
     46 
     47   @return FV attributes.
     48 
     49 **/
     50 FRAMEWORK_EFI_FV_ATTRIBUTES
     51 Fv2AttributesToFvAttributes (
     52   IN  EFI_FV_ATTRIBUTES Fv2Attributes
     53   )
     54 {
     55   //
     56   // Clear those filed that is not defined in Framework FV spec and Alignment conversion.
     57   //
     58   return (Fv2Attributes & 0x1ff) | ((UINTN) EFI_FV_ALIGNMENT_2 << RShiftU64((Fv2Attributes & EFI_FV2_ALIGNMENT), 16));
     59 }
     60 
     61 /**
     62   Retrieves attributes, insures positive polarity of attribute bits, returns
     63   resulting attributes in output parameter.
     64 
     65   @param  This                  Calling context
     66   @param  Attributes            output buffer which contains attributes
     67 
     68   @retval EFI_SUCCESS           The firmware volume attributes were returned.
     69 
     70 **/
     71 EFI_STATUS
     72 EFIAPI
     73 FvGetVolumeAttributes (
     74   IN  EFI_FIRMWARE_VOLUME_PROTOCOL  *This,
     75   OUT FRAMEWORK_EFI_FV_ATTRIBUTES   *Attributes
     76   )
     77 {
     78   EFI_STATUS                     Status;
     79   FIRMWARE_VOLUME_PRIVATE_DATA   *Private;
     80   EFI_FIRMWARE_VOLUME2_PROTOCOL  *FirmwareVolume2;
     81 
     82   Private = FIRMWARE_VOLUME_PRIVATE_DATA_FROM_THIS (This);
     83   FirmwareVolume2 = Private->FirmwareVolume2;
     84 
     85   Status = FirmwareVolume2->GetVolumeAttributes (
     86                               FirmwareVolume2,
     87                               Attributes
     88                               );
     89   if (!EFI_ERROR (Status)) {
     90     *Attributes = Fv2AttributesToFvAttributes (*Attributes);
     91   }
     92   return Status;
     93 }
     94 
     95 /**
     96   Sets volume attributes.
     97 
     98   @param  This                  Calling context
     99   @param  Attributes            Buffer which contains attributes
    100 
    101   @retval EFI_INVALID_PARAMETER A bit in Attributes was invalid
    102   @retval EFI_SUCCESS           The requested firmware volume attributes were set
    103                                 and the resulting EFI_FV_ATTRIBUTES is returned in
    104                                 Attributes.
    105   @retval EFI_ACCESS_DENIED     The Device is locked and does not permit modification.
    106 
    107 **/
    108 EFI_STATUS
    109 EFIAPI
    110 FvSetVolumeAttributes (
    111   IN EFI_FIRMWARE_VOLUME_PROTOCOL     *This,
    112   IN OUT FRAMEWORK_EFI_FV_ATTRIBUTES  *Attributes
    113   )
    114 {
    115   FIRMWARE_VOLUME_PRIVATE_DATA   *Private;
    116   EFI_FIRMWARE_VOLUME2_PROTOCOL  *FirmwareVolume2;
    117   EFI_FV_ATTRIBUTES              Fv2Attributes;
    118   EFI_STATUS                     Status;
    119 
    120   Private = FIRMWARE_VOLUME_PRIVATE_DATA_FROM_THIS (This);
    121   FirmwareVolume2 = Private->FirmwareVolume2;
    122 
    123   Fv2Attributes = (*Attributes & 0x1ff);
    124   Status = FirmwareVolume2->SetVolumeAttributes (
    125                             FirmwareVolume2,
    126                             &Fv2Attributes
    127                             );
    128 
    129   *Attributes = Fv2AttributesToFvAttributes (Fv2Attributes);
    130 
    131   return Status;
    132 }
    133 
    134 /**
    135   Read the requested file (NameGuid) and returns data in Buffer.
    136 
    137   @param  This                  Calling context
    138   @param  NameGuid              Filename identifying which file to read
    139   @param  Buffer                Pointer to pointer to buffer in which contents of file are returned.
    140                                 <br>
    141                                 If Buffer is NULL, only type, attributes, and size are returned as
    142                                 there is no output buffer.
    143                                 <br>
    144                                 If Buffer != NULL and *Buffer == NULL, the output buffer is allocated
    145                                 from BS pool by ReadFile
    146                                 <br>
    147                                 If Buffer != NULL and *Buffer != NULL, the output buffer has been
    148                                 allocated by the caller and is being passed in.
    149   @param  BufferSize            Indicates the buffer size passed in, and on output the size
    150                                 required to complete the read
    151   @param  FoundType             Indicates the type of the file who's data is returned
    152   @param  FileAttributes        Indicates the attributes of the file who's data is resturned
    153   @param  AuthenticationStatus  Indicates the authentication status of the data
    154 
    155   @retval EFI_SUCCESS               The call completed successfully
    156   @retval EFI_WARN_BUFFER_TOO_SMALL The buffer is too small to contain the requested output.
    157                                     The buffer is filled and the output is truncated.
    158   @retval EFI_NOT_FOUND             NameGuid was not found in the firmware volume.
    159   @retval EFI_DEVICE_ERROR          A hardware error occurred when attempting to access the firmware volume.
    160   @retval EFI_ACCESS_DENIED         The firmware volume is configured to disallow reads.
    161   @retval EFI_OUT_OF_RESOURCES      An allocation failure occurred.
    162 
    163 **/
    164 EFI_STATUS
    165 EFIAPI
    166 FvReadFile (
    167   IN EFI_FIRMWARE_VOLUME_PROTOCOL   *This,
    168   IN EFI_GUID                       *NameGuid,
    169   IN OUT VOID                       **Buffer,
    170   IN OUT UINTN                      *BufferSize,
    171   OUT EFI_FV_FILETYPE               *FoundType,
    172   OUT EFI_FV_FILE_ATTRIBUTES        *FileAttributes,
    173   OUT UINT32                        *AuthenticationStatus
    174   )
    175 {
    176   FIRMWARE_VOLUME_PRIVATE_DATA   *Private;
    177   EFI_FIRMWARE_VOLUME2_PROTOCOL  *FirmwareVolume2;
    178   EFI_STATUS                     Status;
    179 
    180   Private = FIRMWARE_VOLUME_PRIVATE_DATA_FROM_THIS (This);
    181   FirmwareVolume2 = Private->FirmwareVolume2;
    182 
    183   Status = FirmwareVolume2->ReadFile (
    184                             FirmwareVolume2,
    185                             NameGuid,
    186                             Buffer,
    187                             BufferSize,
    188                             FoundType,
    189                             FileAttributes,
    190                             AuthenticationStatus
    191                             );
    192 
    193   //
    194   // For Framework FV attrbutes, only alignment fields are valid.
    195   //
    196   *FileAttributes = *FileAttributes & EFI_FV_FILE_ATTRIB_ALIGNMENT;
    197 
    198   return Status;
    199 }
    200 
    201 /**
    202   Read the requested section from the specified file and returns data in Buffer.
    203 
    204   @param  This                  Calling context
    205   @param  NameGuid              Filename identifying the file from which to read
    206   @param  SectionType           Indicates what section type to retrieve
    207   @param  SectionInstance       Indicates which instance of SectionType to retrieve
    208   @param  Buffer                Pointer to pointer to buffer in which contents of file are returned.
    209                                 <br>
    210                                 If Buffer is NULL, only type, attributes, and size are returned as
    211                                 there is no output buffer.
    212                                 <br>
    213                                 If Buffer != NULL and *Buffer == NULL, the output buffer is allocated
    214                                 from BS pool by ReadFile
    215                                 <br>
    216                                 If Buffer != NULL and *Buffer != NULL, the output buffer has been
    217                                 allocated by the caller and is being passed in.
    218   @param  BufferSize            Indicates the buffer size passed in, and on output the size
    219                                 required to complete the read
    220   @param  AuthenticationStatus  Indicates the authentication status of the data
    221 
    222   @retval EFI_SUCCESS                The call completed successfully.
    223   @retval EFI_WARN_BUFFER_TOO_SMALL  The buffer is too small to contain the requested output.
    224                                      The buffer is filled and the output is truncated.
    225   @retval EFI_OUT_OF_RESOURCES       An allocation failure occurred.
    226   @retval EFI_NOT_FOUND              Name was not found in the firmware volume.
    227   @retval EFI_DEVICE_ERROR           A hardware error occurred when attempting to access the firmware volume.
    228   @retval EFI_ACCESS_DENIED          The firmware volume is configured to disallow reads.
    229 
    230 **/
    231 EFI_STATUS
    232 EFIAPI
    233 FvReadSection (
    234   IN EFI_FIRMWARE_VOLUME_PROTOCOL   *This,
    235   IN EFI_GUID                       *NameGuid,
    236   IN EFI_SECTION_TYPE               SectionType,
    237   IN UINTN                          SectionInstance,
    238   IN OUT VOID                       **Buffer,
    239   IN OUT UINTN                      *BufferSize,
    240   OUT UINT32                        *AuthenticationStatus
    241   )
    242 {
    243   FIRMWARE_VOLUME_PRIVATE_DATA   *Private;
    244   EFI_FIRMWARE_VOLUME2_PROTOCOL  *FirmwareVolume2;
    245 
    246   Private = FIRMWARE_VOLUME_PRIVATE_DATA_FROM_THIS (This);
    247   FirmwareVolume2 = Private->FirmwareVolume2;
    248 
    249   return FirmwareVolume2->ReadSection (
    250                             FirmwareVolume2,
    251                             NameGuid,
    252                             SectionType,
    253                             SectionInstance,
    254                             Buffer,
    255                             BufferSize,
    256                             AuthenticationStatus
    257                             );
    258 }
    259 
    260 /**
    261   Write the supplied file (NameGuid) to the FV.
    262 
    263   @param  This                  Calling context
    264   @param  NumberOfFiles         Indicates the number of file records pointed to by FileData
    265   @param  WritePolicy           Indicates the level of reliability of the write with respect to
    266                                 things like power failure events.
    267   @param  FileData              A pointer to an array of EFI_FV_WRITE_FILE_DATA structures. Each
    268                                 element in the array indicates a file to write, and there are
    269                                 NumberOfFiles elements in the input array.
    270 
    271   @retval EFI_SUCCESS           The write completed successfully.
    272   @retval EFI_OUT_OF_RESOURCES  The firmware volume does not have enough free space to store file(s).
    273   @retval EFI_DEVICE_ERROR      A hardware error occurred when attempting to access the firmware volume.
    274   @retval EFI_WRITE_PROTECTED   The firmware volume is configured to disallow writes.
    275   @retval EFI_NOT_FOUND         A delete was requested, but the requested file was not
    276                                 found in the firmware volume.
    277   @retval EFI_INVALID_PARAMETER A delete was requested with a multiple file write.
    278                                 An unsupported WritePolicy was requested.
    279                                 An unknown file type was specified.
    280                                 A file system specific error has occurred.
    281 
    282 **/
    283 EFI_STATUS
    284 EFIAPI
    285 FvWriteFile (
    286   IN EFI_FIRMWARE_VOLUME_PROTOCOL      *This,
    287   IN UINT32                            NumberOfFiles,
    288   IN FRAMEWORK_EFI_FV_WRITE_POLICY     WritePolicy,
    289   IN FRAMEWORK_EFI_FV_WRITE_FILE_DATA  *FileData
    290   )
    291 {
    292   FIRMWARE_VOLUME_PRIVATE_DATA   *Private;
    293   EFI_FIRMWARE_VOLUME2_PROTOCOL  *FirmwareVolume2;
    294   EFI_FV_WRITE_FILE_DATA         *PiFileData;
    295   EFI_STATUS                     Status;
    296   UINTN                          Index;
    297 
    298   Private = FIRMWARE_VOLUME_PRIVATE_DATA_FROM_THIS (This);
    299   FirmwareVolume2 = Private->FirmwareVolume2;
    300 
    301   PiFileData = AllocateCopyPool (sizeof (EFI_FV_WRITE_FILE_DATA), FileData);
    302   ASSERT (PiFileData != NULL);
    303 
    304   //
    305   // Framework Spec assume firmware files are Memory-Mapped.
    306   //
    307   for (Index = 0; Index < NumberOfFiles; Index++) {
    308     PiFileData[Index].FileAttributes |= EFI_FV_FILE_ATTRIB_MEMORY_MAPPED;
    309   }
    310 
    311   Status = FirmwareVolume2->WriteFile (
    312                             FirmwareVolume2,
    313                             NumberOfFiles,
    314                             WritePolicy,
    315                             (EFI_FV_WRITE_FILE_DATA *)FileData
    316                             );
    317 
    318   FreePool (PiFileData);
    319   return Status;
    320 }
    321 
    322 /**
    323   Given the input key, search for the next matching file in the volume.
    324 
    325   @param  This                  Calling context
    326   @param  Key                   Pointer to a caller allocated buffer that contains an implementation
    327                                 specific key that is used to track where to begin searching on
    328                                 successive calls.
    329   @param  FileType              Indicates the file type to filter for
    330   @param  NameGuid              Guid filename of the file found
    331   @param  Attributes            Attributes of the file found
    332   @param  Size                  Size in bytes of the file found
    333 
    334   @retval EFI_SUCCESS           The output parameters are filled with data obtained from
    335                                 the first matching file that was found.
    336   @retval EFI_NOT_FOUND         No files of type FileType were found.
    337   @retval EFI_DEVICE_ERROR      A hardware error occurred when attempting to access
    338                                 the firmware volume.
    339   @retval EFI_ACCESS_DENIED     The firmware volume is configured to disallow reads.
    340 
    341 **/
    342 EFI_STATUS
    343 EFIAPI
    344 FvGetNextFile (
    345   IN EFI_FIRMWARE_VOLUME_PROTOCOL   *This,
    346   IN OUT VOID                       *Key,
    347   IN OUT EFI_FV_FILETYPE            *FileType,
    348   OUT EFI_GUID                      *NameGuid,
    349   OUT EFI_FV_FILE_ATTRIBUTES        *Attributes,
    350   OUT UINTN                         *Size
    351   )
    352 {
    353   FIRMWARE_VOLUME_PRIVATE_DATA   *Private;
    354   EFI_FIRMWARE_VOLUME2_PROTOCOL  *FirmwareVolume2;
    355   EFI_STATUS                     Status;
    356 
    357   Private = FIRMWARE_VOLUME_PRIVATE_DATA_FROM_THIS (This);
    358   FirmwareVolume2 = Private->FirmwareVolume2;
    359 
    360   Status = FirmwareVolume2->GetNextFile (
    361                             FirmwareVolume2,
    362                             Key,
    363                             FileType,
    364                             NameGuid,
    365                             Attributes,
    366                             Size
    367                             );
    368 
    369   //
    370   // For Framework FV attrbutes, only alignment fields are valid.
    371   //
    372   *Attributes = *Attributes & EFI_FV_FILE_ATTRIB_ALIGNMENT;
    373 
    374   return Status;
    375 }
    376 
    377 //
    378 // Firmware Volume Protocol template
    379 //
    380 EFI_EVENT  mFvRegistration;
    381 
    382 FIRMWARE_VOLUME_PRIVATE_DATA gFirmwareVolumePrivateDataTemplate = {
    383   FIRMWARE_VOLUME_PRIVATE_DATA_SIGNATURE,
    384   {
    385     FvGetVolumeAttributes,
    386     FvSetVolumeAttributes,
    387     FvReadFile,
    388     FvReadSection,
    389     FvWriteFile,
    390     FvGetNextFile,
    391     0,
    392     NULL
    393   },
    394   NULL
    395 };
    396 
    397 //
    398 // Module globals
    399 //
    400 /**
    401   This notification function is invoked when an instance of the
    402   EFI_FIRMWARE_VOLUME2_PROTOCOL is produced. It installs another instance of the
    403   EFI_FIRMWARE_VOLUME_PROTOCOL on the same handle.
    404 
    405   @param  Event                 The event that occured
    406   @param  Context               Context of event. Not used in this nofication function.
    407 
    408 **/
    409 VOID
    410 EFIAPI
    411 FvNotificationEvent (
    412   IN  EFI_EVENT       Event,
    413   IN  VOID            *Context
    414   )
    415 {
    416   EFI_STATUS                    Status;
    417   UINTN                         BufferSize;
    418   EFI_HANDLE                    Handle;
    419   FIRMWARE_VOLUME_PRIVATE_DATA  *Private;
    420   EFI_FIRMWARE_VOLUME_PROTOCOL  *FirmwareVolume;
    421 
    422   while (TRUE) {
    423     BufferSize = sizeof (Handle);
    424     Status = gBS->LocateHandle (
    425                     ByRegisterNotify,
    426                     &gEfiFirmwareVolume2ProtocolGuid,
    427                     mFvRegistration,
    428                     &BufferSize,
    429                     &Handle
    430                     );
    431     if (EFI_ERROR (Status)) {
    432       //
    433       // Exit Path of While Loop....
    434       //
    435       break;
    436     }
    437 
    438     //
    439     // Skip this handle if the Firmware Volume Protocol is already installed
    440     //
    441     Status = gBS->HandleProtocol (
    442                     Handle,
    443                     &gEfiFirmwareVolumeProtocolGuid,
    444                     (VOID **)&FirmwareVolume
    445                     );
    446     if (!EFI_ERROR (Status)) {
    447       continue;
    448     }
    449 
    450     //
    451     // Allocate private data structure
    452     //
    453     Private = AllocateCopyPool (sizeof (FIRMWARE_VOLUME_PRIVATE_DATA), &gFirmwareVolumePrivateDataTemplate);
    454     if (Private == NULL) {
    455       continue;
    456     }
    457 
    458     //
    459     // Retrieve the Firmware Volume2 Protocol
    460     //
    461     Status = gBS->HandleProtocol (
    462                     Handle,
    463                     &gEfiFirmwareVolume2ProtocolGuid,
    464                     (VOID **)&Private->FirmwareVolume2
    465                     );
    466     ASSERT_EFI_ERROR (Status);
    467 
    468     //
    469     // Fill in rest of private data structure
    470     //
    471     Private->FirmwareVolume.KeySize      = Private->FirmwareVolume2->KeySize;
    472     Private->FirmwareVolume.ParentHandle = Private->FirmwareVolume2->ParentHandle;
    473 
    474     //
    475     // Install Firmware Volume Protocol onto same handle
    476     //
    477     Status = gBS->InstallMultipleProtocolInterfaces (
    478                     &Handle,
    479                     &gEfiFirmwareVolumeProtocolGuid,
    480                     &Private->FirmwareVolume,
    481                     NULL
    482                     );
    483     ASSERT_EFI_ERROR (Status);
    484   }
    485 }
    486 
    487 
    488 /**
    489   The user Entry Point for DXE driver. The user code starts with this function
    490   as the real entry point for the image goes into a library that calls this
    491   function.
    492 
    493   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
    494   @param[in] SystemTable    A pointer to the EFI System Table.
    495 
    496   @retval EFI_SUCCESS       The entry point is executed successfully.
    497   @retval other             Some error occurs when executing this entry point.
    498 
    499 **/
    500 EFI_STATUS
    501 EFIAPI
    502 InitializeFirmwareVolume2 (
    503   IN EFI_HANDLE        ImageHandle,
    504   IN EFI_SYSTEM_TABLE  *SystemTable
    505   )
    506 {
    507   EfiCreateProtocolNotifyEvent (
    508     &gEfiFirmwareVolume2ProtocolGuid,
    509     TPL_CALLBACK,
    510     FvNotificationEvent,
    511     NULL,
    512     &mFvRegistration
    513     );
    514   return EFI_SUCCESS;
    515 }
    516