Home | History | Annotate | Download | only in BaseExtractGuidedSectionLib
      1 /** @file
      2   Provide generic extract guided section functions.
      3 
      4   Copyright (c) 2007 - 2011, 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 <PiPei.h>
     16 
     17 #include <Library/DebugLib.h>
     18 #include <Library/PcdLib.h>
     19 #include <Library/BaseMemoryLib.h>
     20 #include <Library/ExtractGuidedSectionLib.h>
     21 
     22 #define EXTRACT_HANDLER_INFO_SIGNATURE SIGNATURE_32 ('E', 'G', 'S', 'I')
     23 
     24 typedef struct {
     25   UINT32                                  Signature;
     26   UINT32                                  NumberOfExtractHandler;
     27   GUID                                    *ExtractHandlerGuidTable;
     28   EXTRACT_GUIDED_SECTION_DECODE_HANDLER   *ExtractDecodeHandlerTable;
     29   EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER *ExtractGetInfoHandlerTable;
     30 } EXTRACT_GUIDED_SECTION_HANDLER_INFO;
     31 
     32 /**
     33   HandlerInfo table address is set by PcdGuidedExtractHandlerTableAddress, which is used to store
     34   the registered guid and Handler list. When it is initialized, it will be directly returned.
     35   Or, HandlerInfo table will be initialized in this function.
     36 
     37   @param[in, out]  InfoPointer   The pointer to the handler information structure.
     38 
     39   @retval  RETURN_SUCCESS            HandlerInfo table can be used to store guid and function tables.
     40   @retval  RETURN_OUT_OF_RESOURCES   HandlerInfo table address is not writable.
     41 **/
     42 RETURN_STATUS
     43 GetExtractGuidedSectionHandlerInfo (
     44   IN OUT EXTRACT_GUIDED_SECTION_HANDLER_INFO **InfoPointer
     45   )
     46 {
     47   EXTRACT_GUIDED_SECTION_HANDLER_INFO *HandlerInfo;
     48 
     49   //
     50   // Set the available memory address to handler info.
     51   //
     52   HandlerInfo = (EXTRACT_GUIDED_SECTION_HANDLER_INFO*)(VOID*)(UINTN) PcdGet64 (PcdGuidedExtractHandlerTableAddress);
     53   if (HandlerInfo == NULL) {
     54     *InfoPointer = NULL;
     55     return EFI_OUT_OF_RESOURCES;
     56   }
     57 
     58   //
     59   // First check whether the handler information structure is initialized.
     60   //
     61   if (HandlerInfo->Signature == EXTRACT_HANDLER_INFO_SIGNATURE) {
     62     //
     63     // The handler information has been initialized and is returned.
     64     //
     65     *InfoPointer = HandlerInfo;
     66     return RETURN_SUCCESS;
     67   }
     68 
     69   //
     70   // Try to initialize the handler information structure
     71   //
     72   HandlerInfo->Signature = EXTRACT_HANDLER_INFO_SIGNATURE;
     73   if (HandlerInfo->Signature != EXTRACT_HANDLER_INFO_SIGNATURE) {
     74     //
     75     // The handler information structure was not writeable because the memory is not ready.
     76     //
     77     *InfoPointer = NULL;
     78     return RETURN_OUT_OF_RESOURCES;
     79   }
     80 
     81   //
     82   // Init HandlerInfo structure
     83   //
     84   HandlerInfo->NumberOfExtractHandler     = 0;
     85   HandlerInfo->ExtractHandlerGuidTable    = (GUID *) (HandlerInfo + 1);
     86   HandlerInfo->ExtractDecodeHandlerTable  = (EXTRACT_GUIDED_SECTION_DECODE_HANDLER *) (
     87                                               (UINT8 *)HandlerInfo->ExtractHandlerGuidTable +
     88                                               PcdGet32 (PcdMaximumGuidedExtractHandler) * sizeof (GUID)
     89                                              );
     90   HandlerInfo->ExtractGetInfoHandlerTable = (EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER *) (
     91                                               (UINT8 *)HandlerInfo->ExtractDecodeHandlerTable +
     92                                               PcdGet32 (PcdMaximumGuidedExtractHandler) *
     93                                               sizeof (EXTRACT_GUIDED_SECTION_DECODE_HANDLER)
     94                                              );
     95   *InfoPointer = HandlerInfo;
     96   return RETURN_SUCCESS;
     97 }
     98 
     99 /**
    100   Retrieve the list GUIDs that have been registered through ExtractGuidedSectionRegisterHandlers().
    101 
    102   Sets ExtractHandlerGuidTable so it points at a callee allocated array of registered GUIDs.
    103   The total number of GUIDs in the array are returned. Since the array of GUIDs is callee allocated
    104   and caller must treat this array of GUIDs as read-only data.
    105   If ExtractHandlerGuidTable is NULL, then ASSERT().
    106 
    107   @param[out]  ExtractHandlerGuidTable  A pointer to the array of GUIDs that have been registered through
    108                                         ExtractGuidedSectionRegisterHandlers().
    109 
    110   @return The number of the supported extract guided Handler.
    111 
    112 **/
    113 UINTN
    114 EFIAPI
    115 ExtractGuidedSectionGetGuidList (
    116   OUT  GUID  **ExtractHandlerGuidTable
    117   )
    118 {
    119   RETURN_STATUS                       Status;
    120   EXTRACT_GUIDED_SECTION_HANDLER_INFO *HandlerInfo;
    121 
    122   ASSERT (ExtractHandlerGuidTable != NULL);
    123 
    124   //
    125   // Get all registered handler information
    126   //
    127   Status = GetExtractGuidedSectionHandlerInfo (&HandlerInfo);
    128   if (RETURN_ERROR (Status)) {
    129     *ExtractHandlerGuidTable = NULL;
    130     return 0;
    131   }
    132 
    133   //
    134   // Get GuidTable and Table Number
    135   //
    136   ASSERT (HandlerInfo != NULL);
    137   *ExtractHandlerGuidTable = HandlerInfo->ExtractHandlerGuidTable;
    138   return HandlerInfo->NumberOfExtractHandler;
    139 }
    140 
    141 /**
    142   Registers handlers of type EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER and EXTRACT_GUIDED_SECTION_DECODE_HANDLER
    143   for a specific GUID section type.
    144 
    145   Registers the handlers specified by GetInfoHandler and DecodeHandler with the GUID specified by SectionGuid.
    146   If the GUID value specified by SectionGuid has already been registered, then return RETURN_ALREADY_STARTED.
    147   If there are not enough resources available to register the handlers  then RETURN_OUT_OF_RESOURCES is returned.
    148 
    149   If SectionGuid is NULL, then ASSERT().
    150   If GetInfoHandler is NULL, then ASSERT().
    151   If DecodeHandler is NULL, then ASSERT().
    152 
    153   @param[in]  SectionGuid    A pointer to the GUID associated with the the handlers
    154                              of the GUIDed section type being registered.
    155   @param[in]  GetInfoHandler The pointer to a function that examines a GUIDed section and returns the
    156                              size of the decoded buffer and the size of an optional scratch buffer
    157                              required to actually decode the data in a GUIDed section.
    158   @param[in]  DecodeHandler  The pointer to a function that decodes a GUIDed section into a caller
    159                              allocated output buffer.
    160 
    161   @retval  RETURN_SUCCESS           The handlers were registered.
    162   @retval  RETURN_OUT_OF_RESOURCES  There are not enough resources available to register the handlers.
    163 
    164 **/
    165 RETURN_STATUS
    166 EFIAPI
    167 ExtractGuidedSectionRegisterHandlers (
    168   IN CONST  GUID                                     *SectionGuid,
    169   IN        EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER  GetInfoHandler,
    170   IN        EXTRACT_GUIDED_SECTION_DECODE_HANDLER    DecodeHandler
    171   )
    172 {
    173   UINT32                              Index;
    174   RETURN_STATUS                       Status;
    175   EXTRACT_GUIDED_SECTION_HANDLER_INFO *HandlerInfo;
    176 
    177   //
    178   // Check input paramter
    179   //
    180   ASSERT (SectionGuid != NULL);
    181   ASSERT (GetInfoHandler != NULL);
    182   ASSERT (DecodeHandler != NULL);
    183 
    184   //
    185   // Get the registered handler information
    186   //
    187   Status = GetExtractGuidedSectionHandlerInfo (&HandlerInfo);
    188   if (RETURN_ERROR (Status)) {
    189     return Status;
    190   }
    191 
    192   //
    193   // Search the match registered GetInfo handler for the input guided section.
    194   //
    195   ASSERT (HandlerInfo != NULL);
    196   for (Index = 0; Index < HandlerInfo->NumberOfExtractHandler; Index ++) {
    197     if (CompareGuid (HandlerInfo->ExtractHandlerGuidTable + Index, SectionGuid)) {
    198       //
    199       // If the guided handler has been registered before, only update its handler.
    200       //
    201       HandlerInfo->ExtractDecodeHandlerTable [Index] = DecodeHandler;
    202       HandlerInfo->ExtractGetInfoHandlerTable [Index] = GetInfoHandler;
    203       return RETURN_SUCCESS;
    204     }
    205   }
    206 
    207   //
    208   // Check the global table is enough to contain new Handler.
    209   //
    210   if (HandlerInfo->NumberOfExtractHandler >= PcdGet32 (PcdMaximumGuidedExtractHandler)) {
    211     return RETURN_OUT_OF_RESOURCES;
    212   }
    213 
    214   //
    215   // Register new Handler and guid value.
    216   //
    217   CopyGuid (HandlerInfo->ExtractHandlerGuidTable + HandlerInfo->NumberOfExtractHandler, SectionGuid);
    218   HandlerInfo->ExtractDecodeHandlerTable [HandlerInfo->NumberOfExtractHandler] = DecodeHandler;
    219   HandlerInfo->ExtractGetInfoHandlerTable [HandlerInfo->NumberOfExtractHandler++] = GetInfoHandler;
    220 
    221   return RETURN_SUCCESS;
    222 }
    223 
    224 /**
    225   Retrieves a GUID from a GUIDed section and uses that GUID to select an associated handler of type
    226   EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER that was registered with ExtractGuidedSectionRegisterHandlers().
    227   The selected handler is used to retrieve and return the size of the decoded buffer and the size of an
    228   optional scratch buffer required to actually decode the data in a GUIDed section.
    229 
    230   Examines a GUIDed section specified by InputSection.
    231   If GUID for InputSection does not match any of the GUIDs registered through ExtractGuidedSectionRegisterHandlers(),
    232   then RETURN_UNSUPPORTED is returned.
    233   If the GUID of InputSection does match the GUID that this handler supports, then the the associated handler
    234   of type EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER that was registered with ExtractGuidedSectionRegisterHandlers()
    235   is used to retrieve the OututBufferSize, ScratchSize, and Attributes values. The return status from the handler of
    236   type EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER is returned.
    237 
    238   If InputSection is NULL, then ASSERT().
    239   If OutputBufferSize is NULL, then ASSERT().
    240   If ScratchBufferSize is NULL, then ASSERT().
    241   If SectionAttribute is NULL, then ASSERT().
    242 
    243   @param[in]  InputSection       A pointer to a GUIDed section of an FFS formatted file.
    244   @param[out] OutputBufferSize   A pointer to the size, in bytes, of an output buffer required if the buffer
    245                                  specified by InputSection were decoded.
    246   @param[out] ScratchBufferSize  A pointer to the size, in bytes, required as scratch space if the buffer specified by
    247                                  InputSection were decoded.
    248   @param[out] SectionAttribute   A pointer to the attributes of the GUIDed section.  See the Attributes field of
    249                                  EFI_GUID_DEFINED_SECTION in the PI Specification.
    250 
    251   @retval  RETURN_SUCCESS      Successfully retrieved the required information.
    252   @retval  RETURN_UNSUPPORTED  The GUID from the section specified by InputSection does not match any of
    253                                the GUIDs registered with ExtractGuidedSectionRegisterHandlers().
    254   @retval  Others              The return status from the handler associated with the GUID retrieved from
    255                                the section specified by InputSection.
    256 
    257 **/
    258 RETURN_STATUS
    259 EFIAPI
    260 ExtractGuidedSectionGetInfo (
    261   IN  CONST VOID    *InputSection,
    262   OUT       UINT32  *OutputBufferSize,
    263   OUT       UINT32  *ScratchBufferSize,
    264   OUT       UINT16  *SectionAttribute
    265   )
    266 {
    267   UINT32                              Index;
    268   RETURN_STATUS                       Status;
    269   EXTRACT_GUIDED_SECTION_HANDLER_INFO *HandlerInfo;
    270   EFI_GUID                            *SectionDefinitionGuid;
    271 
    272   //
    273   // Check input paramter
    274   //
    275   ASSERT (InputSection != NULL);
    276   ASSERT (OutputBufferSize != NULL);
    277   ASSERT (ScratchBufferSize != NULL);
    278   ASSERT (SectionAttribute != NULL);
    279 
    280   //
    281   // Get all registered handler information.
    282   //
    283   Status = GetExtractGuidedSectionHandlerInfo (&HandlerInfo);
    284   if (RETURN_ERROR (Status)) {
    285     return Status;
    286   }
    287 
    288   if (IS_SECTION2 (InputSection)) {
    289     SectionDefinitionGuid = &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid);
    290   } else {
    291     SectionDefinitionGuid = &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid);
    292   }
    293 
    294   //
    295   // Search the match registered GetInfo handler for the input guided section.
    296   //
    297   ASSERT (HandlerInfo != NULL);
    298   for (Index = 0; Index < HandlerInfo->NumberOfExtractHandler; Index ++) {
    299     if (CompareGuid (HandlerInfo->ExtractHandlerGuidTable + Index, SectionDefinitionGuid)) {
    300       //
    301       // Call the match handler to get information for the input section data.
    302       //
    303       return HandlerInfo->ExtractGetInfoHandlerTable [Index] (
    304                 InputSection,
    305                 OutputBufferSize,
    306                 ScratchBufferSize,
    307                 SectionAttribute
    308               );
    309     }
    310   }
    311 
    312   //
    313   // Not found, the input guided section is not supported.
    314   //
    315   return RETURN_UNSUPPORTED;
    316 }
    317 
    318 /**
    319   Retrieves the GUID from a GUIDed section and uses that GUID to select an associated handler of type
    320   EXTRACT_GUIDED_SECTION_DECODE_HANDLER that was registered with ExtractGuidedSectionRegisterHandlers().
    321   The selected handler is used to decode the data in a GUIDed section and return the result in a caller
    322   allocated output buffer.
    323 
    324   Decodes the GUIDed section specified by InputSection.
    325   If GUID for InputSection does not match any of the GUIDs registered through ExtractGuidedSectionRegisterHandlers(),
    326   then RETURN_UNSUPPORTED is returned.
    327   If the GUID of InputSection does match the GUID that this handler supports, then the the associated handler
    328   of type EXTRACT_GUIDED_SECTION_DECODE_HANDLER that was registered with ExtractGuidedSectionRegisterHandlers()
    329   is used to decode InputSection into the buffer specified by OutputBuffer and the authentication status of this
    330   decode operation is returned in AuthenticationStatus.  If the decoded buffer is identical to the data in InputSection,
    331   then OutputBuffer is set to point at the data in InputSection.  Otherwise, the decoded data will be placed in a caller
    332   allocated buffer specified by OutputBuffer.    This function is responsible for computing the  EFI_AUTH_STATUS_PLATFORM_OVERRIDE
    333   bit of in AuthenticationStatus.  The return status from the handler of type EXTRACT_GUIDED_SECTION_DECODE_HANDLER is returned.
    334 
    335   If InputSection is NULL, then ASSERT().
    336   If OutputBuffer is NULL, then ASSERT().
    337   If ScratchBuffer is NULL and this decode operation requires a scratch buffer, then ASSERT().
    338   If AuthenticationStatus is NULL, then ASSERT().
    339 
    340   @param[in]  InputSection   A pointer to a GUIDed section of an FFS formatted file.
    341   @param[out] OutputBuffer   A pointer to a buffer that contains the result of a decode operation.
    342   @param[in]  ScratchBuffer  A caller allocated buffer that may be required by this function as a scratch buffer to perform the decode operation.
    343   @param[out] AuthenticationStatus
    344                              A pointer to the authentication status of the decoded output buffer. See the definition
    345                              of authentication status in the EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI section of the PI
    346                              Specification.
    347 
    348   @retval  RETURN_SUCCESS           The buffer specified by InputSection was decoded.
    349   @retval  RETURN_UNSUPPORTED       The section specified by InputSection does not match the GUID this handler supports.
    350   @retval  RETURN_INVALID_PARAMETER The section specified by InputSection can not be decoded.
    351 
    352 **/
    353 RETURN_STATUS
    354 EFIAPI
    355 ExtractGuidedSectionDecode (
    356   IN  CONST VOID    *InputSection,
    357   OUT       VOID    **OutputBuffer,
    358   IN        VOID    *ScratchBuffer,        OPTIONAL
    359   OUT       UINT32  *AuthenticationStatus
    360   )
    361 {
    362   UINT32                              Index;
    363   RETURN_STATUS                       Status;
    364   EXTRACT_GUIDED_SECTION_HANDLER_INFO *HandlerInfo;
    365   EFI_GUID                            *SectionDefinitionGuid;
    366 
    367   //
    368   // Check input parameter
    369   //
    370   ASSERT (InputSection != NULL);
    371   ASSERT (OutputBuffer != NULL);
    372   ASSERT (AuthenticationStatus != NULL);
    373 
    374   //
    375   // Get all registered handler information.
    376   //
    377   Status = GetExtractGuidedSectionHandlerInfo (&HandlerInfo);
    378   if (RETURN_ERROR (Status)) {
    379     return Status;
    380   }
    381 
    382   if (IS_SECTION2 (InputSection)) {
    383     SectionDefinitionGuid = &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid);
    384   } else {
    385     SectionDefinitionGuid = &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid);
    386   }
    387 
    388   //
    389   // Search the match registered Extract handler for the input guided section.
    390   //
    391   ASSERT (HandlerInfo != NULL);
    392   for (Index = 0; Index < HandlerInfo->NumberOfExtractHandler; Index ++) {
    393     if (CompareGuid (HandlerInfo->ExtractHandlerGuidTable + Index, SectionDefinitionGuid)) {
    394       //
    395       // Call the match handler to extract raw data for the input guided section.
    396       //
    397       return HandlerInfo->ExtractDecodeHandlerTable [Index] (
    398                 InputSection,
    399                 OutputBuffer,
    400                 ScratchBuffer,
    401                 AuthenticationStatus
    402               );
    403     }
    404   }
    405 
    406   //
    407   // Not found, the input guided section is not supported.
    408   //
    409   return RETURN_UNSUPPORTED;
    410 }
    411 
    412 /**
    413   Retrieves handlers of type EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER and
    414   EXTRACT_GUIDED_SECTION_DECODE_HANDLER for a specific GUID section type.
    415 
    416   Retrieves the handlers associated with SectionGuid and returns them in
    417   GetInfoHandler and DecodeHandler.
    418 
    419   If the GUID value specified by SectionGuid has not been registered, then
    420   return RETURN_NOT_FOUND.
    421 
    422   If SectionGuid is NULL, then ASSERT().
    423 
    424   @param[in]  SectionGuid    A pointer to the GUID associated with the handlersof the GUIDed
    425                              section type being retrieved.
    426   @param[out] GetInfoHandler Pointer to a function that examines a GUIDed section and returns
    427                              the size of the decoded buffer and the size of an optional scratch
    428                              buffer required to actually decode the data in a GUIDed section.
    429                              This is an optional parameter that may be NULL. If it is NULL, then
    430                              the previously registered handler is not returned.
    431   @param[out] DecodeHandler  Pointer to a function that decodes a GUIDed section into a caller
    432                              allocated output buffer. This is an optional parameter that may be NULL.
    433                              If it is NULL, then the previously registered handler is not returned.
    434 
    435   @retval  RETURN_SUCCESS     The handlers were retrieved.
    436   @retval  RETURN_NOT_FOUND   No handlers have been registered with the specified GUID.
    437 
    438 **/
    439 RETURN_STATUS
    440 EFIAPI
    441 ExtractGuidedSectionGetHandlers (
    442   IN CONST   GUID                                     *SectionGuid,
    443   OUT        EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER  *GetInfoHandler,  OPTIONAL
    444   OUT        EXTRACT_GUIDED_SECTION_DECODE_HANDLER    *DecodeHandler    OPTIONAL
    445   )
    446 {
    447   UINT32                              Index;
    448   RETURN_STATUS                       Status;
    449   EXTRACT_GUIDED_SECTION_HANDLER_INFO *HandlerInfo;
    450 
    451   //
    452   // Check input paramter
    453   //
    454   ASSERT (SectionGuid != NULL);
    455 
    456   //
    457   // Get the registered handler information
    458   //
    459   Status = GetExtractGuidedSectionHandlerInfo (&HandlerInfo);
    460   if (RETURN_ERROR (Status)) {
    461     return Status;
    462   }
    463 
    464   //
    465   // Search the match registered GetInfo handler for the input guided section.
    466   //
    467   ASSERT (HandlerInfo != NULL);
    468   for (Index = 0; Index < HandlerInfo->NumberOfExtractHandler; Index ++) {
    469     if (CompareGuid (HandlerInfo->ExtractHandlerGuidTable + Index, SectionGuid)) {
    470 
    471       //
    472       // If the guided handler has been registered before, then return the registered handlers.
    473       //
    474       if (GetInfoHandler != NULL) {
    475         *GetInfoHandler = HandlerInfo->ExtractGetInfoHandlerTable[Index];
    476       }
    477       if (DecodeHandler != NULL) {
    478         *DecodeHandler = HandlerInfo->ExtractDecodeHandlerTable[Index];
    479       }
    480       return RETURN_SUCCESS;
    481     }
    482   }
    483   return RETURN_NOT_FOUND;
    484 }
    485