Home | History | Annotate | Download | only in SmmRuntimeDxeReportStatusCodeLib
      1 /*++
      2 
      3 Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>
      4 This program and the accompanying materials
      5 are licensed and made available under the terms and conditions of the BSD License
      6 which accompanies this distribution.  The full text of the license may be found at
      7 http://opensource.org/licenses/bsd-license.php
      8 
      9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 
     12 
     13 Module Name:
     14 
     15   SmmRuntimeDxeSupport.c
     16 
     17 Abstract:
     18 
     19   Report Status Code Library for DXE Phase.
     20 
     21 --*/
     22 
     23 #include "ReportStatusCodeLibInternal.h"
     24 #include EFI_PROTOCOL_DEFINITION (SmmStatusCode)
     25 
     26 EFI_EVENT             mVirtualAddressChangeEvent;
     27 
     28 EFI_EVENT             mExitBootServicesEvent;
     29 
     30 EFI_STATUS_CODE_DATA  *mStatusCodeData;
     31 
     32 BOOLEAN               mInSmm;
     33 
     34 EFI_SMM_BASE_PROTOCOL *mSmmBase;
     35 
     36 EFI_RUNTIME_SERVICES  *mRTSmmRuntimeDxeReportStatusCodeLib;
     37 
     38 BOOLEAN               mHaveExitedBootServices = FALSE;
     39 
     40 EFI_SMM_STATUS_CODE_PROTOCOL  *mSmmStatusCode;
     41 
     42 VOID
     43 SmmStatusCodeInitialize (
     44   VOID
     45   )
     46 {
     47   EFI_STATUS Status;
     48 
     49   Status = gBS->LocateProtocol (&gEfiSmmStatusCodeProtocolGuid, NULL, (VOID **) &mSmmStatusCode);
     50   if (EFI_ERROR (Status)) {
     51     mSmmStatusCode = NULL;
     52   }
     53 }
     54 
     55 EFI_STATUS
     56 SmmStatusCodeReport (
     57   IN EFI_STATUS_CODE_TYPE     Type,
     58   IN EFI_STATUS_CODE_VALUE    Value,
     59   IN UINT32                   Instance,
     60   IN EFI_GUID                 *CallerId OPTIONAL,
     61   IN EFI_STATUS_CODE_DATA     *Data     OPTIONAL
     62   )
     63 {
     64   if (mSmmStatusCode != NULL) {
     65     (mSmmStatusCode->ReportStatusCode) (mSmmStatusCode, Type, Value, Instance, CallerId, Data);
     66   }
     67   return EFI_SUCCESS;
     68 }
     69 
     70 /**
     71   Locate he report status code service.
     72 
     73   @return     EFI_REPORT_STATUS_CODE    function point to
     74               ReportStatusCode.
     75 **/
     76 EFI_REPORT_STATUS_CODE
     77 InternalGetReportStatusCode (
     78   VOID
     79   )
     80 {
     81 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
     82   EFI_STATUS_CODE_PROTOCOL  *StatusCodeProtocol;
     83   EFI_STATUS                Status;
     84 #endif
     85 
     86   if (mInSmm) {
     87     return (EFI_REPORT_STATUS_CODE) SmmStatusCodeReport;
     88 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
     89   } else if (!mHaveExitedBootServices) {
     90   	//
     91   	// Check gBS just in case. ReportStatusCode is called before gBS is initialized.
     92   	//
     93     if (gBS != NULL) {
     94       Status = gBS->LocateProtocol (&gEfiStatusCodeRuntimeProtocolGuid, NULL, (VOID**)&StatusCodeProtocol);
     95       if (!EFI_ERROR (Status) && StatusCodeProtocol != NULL) {
     96         return StatusCodeProtocol->ReportStatusCode;
     97       }
     98     }
     99   }
    100 #elif (TIANO_RELEASE_VERSION != 0)
    101   } else if (mRTSmmRuntimeDxeReportStatusCodeLib != NULL) {
    102     return mRTSmmRuntimeDxeReportStatusCodeLib->ReportStatusCode;
    103   }
    104 #endif
    105 
    106   return NULL;
    107 }
    108 
    109 
    110 /**
    111   Fixup internal report status code protocol interface.
    112 
    113   @param[in]    Event   The Event that is being processed
    114   @param[in]    Context Event Context
    115 **/
    116 VOID
    117 EFIAPI
    118 ReportStatusCodeLibVirtualAddressChange (
    119   IN EFI_EVENT        Event,
    120   IN VOID             *Context
    121   )
    122 {
    123   if (NULL != mReportStatusCode) {
    124     mRTSmmRuntimeDxeReportStatusCodeLib->ConvertPointer (0, (VOID **) &mReportStatusCode);
    125   }
    126   mRTSmmRuntimeDxeReportStatusCodeLib->ConvertPointer (0, (VOID **) &mStatusCodeData);
    127   mRTSmmRuntimeDxeReportStatusCodeLib->ConvertPointer (0, (VOID **) &mRTSmmRuntimeDxeReportStatusCodeLib);
    128 }
    129 
    130 /**
    131   Update the In Runtime Indicator.
    132 
    133   @param[in]    Event   The Event that is being processed
    134   @param[in]    Context Event Context
    135 **/
    136 VOID
    137 EFIAPI
    138 ReportStatusCodeLibExitBootServices (
    139   IN EFI_EVENT        Event,
    140   IN VOID             *Context
    141   )
    142 {
    143   //
    144   // If mReportStatusCode is NULL, then see if a Status Code Protocol instance is present
    145   // in the handle database.
    146   //
    147   if (mReportStatusCode == NULL) {
    148     mReportStatusCode = InternalGetReportStatusCode ();
    149   }
    150 
    151   mHaveExitedBootServices = TRUE;
    152 }
    153 
    154 /**
    155   Intialize Report Status Code Lib.
    156 
    157   @param[in]  ImageHandle   The firmware allocated handle for the EFI image.
    158   @param[in]  SystemTable   A pointer to the EFI System Table.
    159 
    160   @return     EFI_STATUS    always returns EFI_SUCCESS.
    161 **/
    162 EFI_STATUS
    163 EFIAPI
    164 ReportStatusCodeLibConstruct (
    165   IN EFI_HANDLE           ImageHandle,
    166   IN EFI_SYSTEM_TABLE     *SystemTable
    167   )
    168 {
    169   EFI_STATUS            Status;
    170 
    171   //
    172   // SMM driver depends on the SMM BASE protocol.
    173   // the SMM driver must be success to locate protocol.
    174   //
    175   Status = gBS->LocateProtocol (&gEfiSmmBaseProtocolGuid, NULL, (VOID **) &mSmmBase);
    176   if (!EFI_ERROR (Status)) {
    177     mSmmBase->InSmm (mSmmBase, &mInSmm);
    178     if (mInSmm) {
    179       Status = mSmmBase->SmmAllocatePool (
    180                            mSmmBase,
    181                            EfiRuntimeServicesData,
    182                            sizeof (EFI_STATUS_CODE_DATA) + EFI_STATUS_CODE_DATA_MAX_SIZE,
    183                            (VOID **) &mStatusCodeData
    184                            );
    185       ASSERT_EFI_ERROR (Status);
    186       SmmStatusCodeInitialize ();
    187       return EFI_SUCCESS;
    188     }
    189   }
    190 
    191   //
    192   // Library should not use the gRT directly, since it
    193   // may be converted by other library instance.
    194   //
    195   mRTSmmRuntimeDxeReportStatusCodeLib = gRT;
    196   mInSmm  = FALSE;
    197 
    198   (gBS->AllocatePool) (EfiRuntimeServicesData, sizeof (EFI_STATUS_CODE_DATA) + EFI_STATUS_CODE_DATA_MAX_SIZE, (VOID **)&mStatusCodeData);
    199   ASSERT (NULL != mStatusCodeData);
    200   //
    201   // Cache the report status code service
    202   //
    203   mReportStatusCode = InternalGetReportStatusCode ();
    204 
    205   //
    206   // Register the call back of virtual address change
    207   //
    208   Status = gBS->CreateEvent (
    209                   EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
    210                   TPL_NOTIFY,
    211                   ReportStatusCodeLibVirtualAddressChange,
    212                   NULL,
    213                   &mVirtualAddressChangeEvent
    214                   );
    215   ASSERT_EFI_ERROR (Status);
    216 
    217 
    218   //
    219   // Register the call back of exit boot services
    220   //
    221   Status = gBS->CreateEvent (
    222                   EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES,
    223                   TPL_NOTIFY,
    224                   ReportStatusCodeLibExitBootServices,
    225                   NULL,
    226                   &mExitBootServicesEvent
    227                   );
    228   ASSERT_EFI_ERROR (Status);
    229 
    230   return Status;
    231 }
    232 
    233 /**
    234   Desctructor of library will close events.
    235 
    236   @param ImageHandle callder module's image handle
    237   @param SystemTable pointer to EFI system table.
    238   @return the status of close event.
    239 **/
    240 EFI_STATUS
    241 EFIAPI
    242 ReportStatusCodeLibDestruct (
    243   IN EFI_HANDLE        ImageHandle,
    244   IN EFI_SYSTEM_TABLE  *SystemTable
    245   )
    246 {
    247   EFI_STATUS  Status;
    248 
    249   if (!mInSmm) {
    250     //
    251     // Close SetVirtualAddressMap () notify function
    252     //
    253     ASSERT (gBS != NULL);
    254     Status = gBS->CloseEvent (mVirtualAddressChangeEvent);
    255     ASSERT_EFI_ERROR (Status);
    256     Status = gBS->CloseEvent (mExitBootServicesEvent);
    257     ASSERT_EFI_ERROR (Status);
    258 
    259     (gBS->FreePool) (mStatusCodeData);
    260   } else {
    261     mSmmBase->SmmFreePool (mSmmBase, mStatusCodeData);
    262   }
    263 
    264   return EFI_SUCCESS;
    265 }
    266 
    267 /**
    268   Reports a status code with full parameters.
    269 
    270   The function reports a status code.  If ExtendedData is NULL and ExtendedDataSize
    271   is 0, then an extended data buffer is not reported.  If ExtendedData is not
    272   NULL and ExtendedDataSize is not 0, then an extended data buffer is allocated.
    273   ExtendedData is assumed not have the standard status code header, so this function
    274   is responsible for allocating a buffer large enough for the standard header and
    275   the extended data passed into this function.  The standard header is filled in
    276   with a GUID specified by ExtendedDataGuid.  If ExtendedDataGuid is NULL, then a
    277   GUID of gEfiStatusCodeSpecificDatauid is used.  The status code is reported with
    278   an instance specified by Instance and a caller ID specified by CallerId.  If
    279   CallerId is NULL, then a caller ID of gEfiCallerIdGuid is used.
    280 
    281   ReportStatusCodeEx()must actively prevent recursion.  If ReportStatusCodeEx()
    282   is called while processing another any other Report Status Code Library function,
    283   then ReportStatusCodeEx() must return EFI_DEVICE_ERROR immediately.
    284 
    285   If ExtendedData is NULL and ExtendedDataSize is not zero, then ASSERT().
    286   If ExtendedData is not NULL and ExtendedDataSize is zero, then ASSERT().
    287 
    288   @param  Type              Status code type.
    289   @param  Value             Status code value.
    290   @param  Instance          Status code instance number.
    291   @param  CallerId          Pointer to a GUID that identifies the caller of this
    292                             function.  If this parameter is NULL, then a caller
    293                             ID of gEfiCallerIdGuid is used.
    294   @param  ExtendedDataGuid  Pointer to the GUID for the extended data buffer.
    295                             If this parameter is NULL, then a the status code
    296                             standard header is filled in with
    297                             gEfiStatusCodeSpecificDataGuid.
    298   @param  ExtendedData      Pointer to the extended data buffer.  This is an
    299                             optional parameter that may be NULL.
    300   @param  ExtendedDataSize  The size, in bytes, of the extended data buffer.
    301 
    302   @retval  EFI_SUCCESS           The status code was reported.
    303   @retval  EFI_OUT_OF_RESOURCES  There were not enough resources to allocate
    304                                  the extended data section if it was specified.
    305   @retval  EFI_UNSUPPORTED       Report status code is not supported
    306 
    307 **/
    308 EFI_STATUS
    309 EFIAPI
    310 InternalReportStatusCodeEx (
    311   IN EFI_STATUS_CODE_TYPE   Type,
    312   IN EFI_STATUS_CODE_VALUE  Value,
    313   IN UINT32                 Instance,
    314   IN CONST EFI_GUID         *CallerId          OPTIONAL,
    315   IN CONST EFI_GUID         *ExtendedDataGuid  OPTIONAL,
    316   IN CONST VOID             *ExtendedData      OPTIONAL,
    317   IN UINTN                  ExtendedDataSize
    318   )
    319 {
    320   ASSERT (!((ExtendedData == NULL) && (ExtendedDataSize != 0)));
    321   ASSERT (!((ExtendedData != NULL) && (ExtendedDataSize == 0)));
    322 
    323   if (ExtendedDataSize > EFI_STATUS_CODE_DATA_MAX_SIZE) {
    324     return EFI_OUT_OF_RESOURCES;
    325   }
    326 
    327   //
    328   // Fill in the extended data header
    329   //
    330   mStatusCodeData->HeaderSize = (UINT16) sizeof (EFI_STATUS_CODE_DATA);
    331   mStatusCodeData->Size = (UINT16)ExtendedDataSize;
    332   if (ExtendedDataGuid == NULL) {
    333     ExtendedDataGuid = &gEfiStatusCodeSpecificDataGuid;
    334   }
    335   CopyGuid (&mStatusCodeData->Type, ExtendedDataGuid);
    336 
    337   //
    338   // Fill in the extended data buffer
    339   //
    340   CopyMem (mStatusCodeData + 1, ExtendedData, ExtendedDataSize);
    341 
    342   //
    343   // Report the status code
    344   //
    345   if (CallerId == NULL) {
    346     CallerId = &gEfiCallerIdGuid;
    347   }
    348   return  InternalReportStatusCode (Type, Value, Instance, CallerId, mStatusCodeData);
    349 }
    350 
    351