Home | History | Annotate | Download | only in RuntimeDxe
      1 /** @file
      2   Status code driver for IA32/X64/EBC architecture.
      3 
      4   Copyright (c) 2006 - 2010, 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 "StatusCodeRuntimeDxe.h"
     16 
     17 EFI_EVENT    mVirtualAddressChangeEvent = NULL;
     18 EFI_HANDLE   mHandle = NULL;
     19 
     20 //
     21 // Declaration of status code protocol.
     22 //
     23 EFI_STATUS_CODE_PROTOCOL  mEfiStatusCodeProtocol  = {
     24   ReportDispatcher
     25 };
     26 
     27 //
     28 // Report operation nest status.
     29 // If it is set, then the report operation has nested.
     30 //
     31 UINT32  mStatusCodeNestStatus = 0;
     32 
     33 /**
     34   Entry point of DXE Status Code Driver.
     35 
     36   This function is the entry point of this DXE Status Code Driver.
     37   It installs Status Code Runtime Protocol, and registers event for EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
     38 
     39   @param  ImageHandle       The firmware allocated handle for the EFI image.
     40   @param  SystemTable       A pointer to the EFI System Table.
     41 
     42   @retval EFI_SUCCESS       The entry point is executed successfully.
     43 
     44 **/
     45 EFI_STATUS
     46 EFIAPI
     47 StatusCodeRuntimeDxeEntry (
     48   IN EFI_HANDLE         ImageHandle,
     49   IN EFI_SYSTEM_TABLE   *SystemTable
     50   )
     51 {
     52   EFI_STATUS  Status;
     53 
     54   //
     55   // Dispatch initialization request to supported devices
     56   //
     57   InitializationDispatcherWorker ();
     58 
     59   //
     60   // Install Status Code Runtime Protocol implementation as defined in PI Specification.
     61   //
     62   Status = gBS->InstallMultipleProtocolInterfaces (
     63                   &mHandle,
     64                   &gEfiStatusCodeRuntimeProtocolGuid,
     65                   &mEfiStatusCodeProtocol,
     66                   NULL
     67                   );
     68   ASSERT_EFI_ERROR (Status);
     69 
     70   Status = gBS->CreateEventEx (
     71                   EVT_NOTIFY_SIGNAL,
     72                   TPL_NOTIFY,
     73                   VirtualAddressChangeCallBack,
     74                   NULL,
     75                   &gEfiEventVirtualAddressChangeGuid,
     76                   &mVirtualAddressChangeEvent
     77                   );
     78   ASSERT_EFI_ERROR (Status);
     79 
     80   return EFI_SUCCESS;
     81 }
     82 
     83 /**
     84   Report status code to all supported device.
     85 
     86   This function implements EFI_STATUS_CODE_PROTOCOL.ReportStatusCode().
     87   It calls into the workers which dispatches the platform specific listeners.
     88 
     89   @param  CodeType         Indicates the type of status code being reported.
     90   @param  Value            Describes the current status of a hardware or software entity.
     91                            This included information about the class and subclass that is used to
     92                            classify the entity as well as an operation.
     93   @param  Instance         The enumeration of a hardware or software entity within
     94                            the system. Valid instance numbers start with 1.
     95   @param  CallerId         This optional parameter may be used to identify the caller.
     96                            This parameter allows the status code driver to apply different rules to
     97                            different callers.
     98   @param  Data             This optional parameter may be used to pass additional data.
     99 
    100   @retval EFI_SUCCESS      The function completed successfully
    101   @retval EFI_DEVICE_ERROR The function should not be completed due to a device error.
    102 
    103 **/
    104 EFI_STATUS
    105 EFIAPI
    106 ReportDispatcher (
    107   IN EFI_STATUS_CODE_TYPE     CodeType,
    108   IN EFI_STATUS_CODE_VALUE    Value,
    109   IN UINT32                   Instance,
    110   IN EFI_GUID                 *CallerId  OPTIONAL,
    111   IN EFI_STATUS_CODE_DATA     *Data      OPTIONAL
    112   )
    113 {
    114   //
    115   // Use atom operation to avoid the reentant of report.
    116   // If current status is not zero, then the function is reentrancy.
    117   //
    118   if (InterlockedCompareExchange32 (&mStatusCodeNestStatus, 0, 1) == 1) {
    119     return EFI_DEVICE_ERROR;
    120   }
    121 
    122   if (FeaturePcdGet (PcdStatusCodeUseSerial)) {
    123     SerialStatusCodeReportWorker (
    124       CodeType,
    125       Value,
    126       Instance,
    127       CallerId,
    128       Data
    129       );
    130   }
    131   if (FeaturePcdGet (PcdStatusCodeUseMemory)) {
    132     RtMemoryStatusCodeReportWorker (
    133       CodeType,
    134       Value,
    135       Instance
    136       );
    137   }
    138   if (FeaturePcdGet (PcdStatusCodeUseDataHub)) {
    139     DataHubStatusCodeReportWorker (
    140       CodeType,
    141       Value,
    142       Instance,
    143       CallerId,
    144       Data
    145       );
    146   }
    147   if (FeaturePcdGet (PcdStatusCodeUseOEM)) {
    148     //
    149     // Call OEM hook status code library API to report status code to OEM device
    150     //
    151     OemHookStatusCodeReport (
    152       CodeType,
    153       Value,
    154       Instance,
    155       CallerId,
    156       Data
    157       );
    158   }
    159 
    160   //
    161   // Restore the nest status of report
    162   //
    163   InterlockedCompareExchange32 (&mStatusCodeNestStatus, 1, 0);
    164 
    165   return EFI_SUCCESS;
    166 }
    167 
    168 
    169 /**
    170   Virtual address change notification call back. It converts global pointer
    171   to virtual address.
    172 
    173   @param  Event         Event whose notification function is being invoked.
    174   @param  Context       Pointer to the notification function's context, which is
    175                         always zero in current implementation.
    176 
    177 **/
    178 VOID
    179 EFIAPI
    180 VirtualAddressChangeCallBack (
    181   IN EFI_EVENT        Event,
    182   IN VOID             *Context
    183   )
    184 {
    185   //
    186   // Convert memory status code table to virtual address;
    187   //
    188   EfiConvertPointer (
    189     0,
    190     (VOID **) &mRtMemoryStatusCodeTable
    191     );
    192 }
    193 
    194 /**
    195   Dispatch initialization request to sub status code devices based on
    196   customized feature flags.
    197 
    198 **/
    199 VOID
    200 InitializationDispatcherWorker (
    201   VOID
    202   )
    203 {
    204   EFI_PEI_HOB_POINTERS              Hob;
    205   EFI_STATUS                        Status;
    206   MEMORY_STATUSCODE_PACKET_HEADER   *PacketHeader;
    207   MEMORY_STATUSCODE_RECORD          *Record;
    208   UINTN                             Index;
    209   UINTN                             MaxRecordNumber;
    210 
    211   //
    212   // If enable UseSerial, then initialize serial port.
    213   // if enable UseRuntimeMemory, then initialize runtime memory status code worker.
    214   // if enable UseDataHub, then initialize data hub status code worker.
    215   //
    216   if (FeaturePcdGet (PcdStatusCodeUseSerial)) {
    217     //
    218     // Call Serial Port Lib API to initialize serial port.
    219     //
    220     Status = SerialPortInitialize ();
    221     ASSERT_EFI_ERROR (Status);
    222   }
    223   if (FeaturePcdGet (PcdStatusCodeUseMemory)) {
    224     Status = RtMemoryStatusCodeInitializeWorker ();
    225     ASSERT_EFI_ERROR (Status);
    226   }
    227   if (FeaturePcdGet (PcdStatusCodeUseDataHub)) {
    228     DataHubStatusCodeInitializeWorker ();
    229   }
    230   if (FeaturePcdGet (PcdStatusCodeUseOEM)) {
    231     //
    232     // Call OEM hook status code library API to initialize OEM device for status code.
    233     //
    234     Status = OemHookStatusCodeInitialize ();
    235     ASSERT_EFI_ERROR (Status);
    236   }
    237 
    238   //
    239   // Replay Status code which saved in GUID'ed HOB to all supported devices.
    240   //
    241   if (FeaturePcdGet (PcdStatusCodeReplayIn)) {
    242     //
    243     // Journal GUID'ed HOBs to find all record entry, if found,
    244     // then output record to support replay device.
    245     //
    246     Hob.Raw   = GetFirstGuidHob (&gMemoryStatusCodeRecordGuid);
    247     if (Hob.Raw != NULL) {
    248       PacketHeader = (MEMORY_STATUSCODE_PACKET_HEADER *) GET_GUID_HOB_DATA (Hob.Guid);
    249       Record = (MEMORY_STATUSCODE_RECORD *) (PacketHeader + 1);
    250       MaxRecordNumber = (UINTN) PacketHeader->RecordIndex;
    251       if (PacketHeader->PacketIndex > 0) {
    252         //
    253         // Record has been wrapped around. So, record number has arrived at max number.
    254         //
    255         MaxRecordNumber = (UINTN) PacketHeader->MaxRecordsNumber;
    256       }
    257       for (Index = 0; Index < MaxRecordNumber; Index++) {
    258         //
    259         // Dispatch records to devices based on feature flag.
    260         //
    261         if (FeaturePcdGet (PcdStatusCodeUseSerial)) {
    262           SerialStatusCodeReportWorker (
    263             Record[Index].CodeType,
    264             Record[Index].Value,
    265             Record[Index].Instance,
    266             NULL,
    267             NULL
    268             );
    269         }
    270         if (FeaturePcdGet (PcdStatusCodeUseMemory)) {
    271           RtMemoryStatusCodeReportWorker (
    272             Record[Index].CodeType,
    273             Record[Index].Value,
    274             Record[Index].Instance
    275             );
    276         }
    277         if (FeaturePcdGet (PcdStatusCodeUseDataHub)) {
    278           DataHubStatusCodeReportWorker (
    279             Record[Index].CodeType,
    280             Record[Index].Value,
    281             Record[Index].Instance,
    282             NULL,
    283             NULL
    284             );
    285         }
    286         if (FeaturePcdGet (PcdStatusCodeUseOEM)) {
    287           //
    288           // Call OEM hook status code library API to report status code to OEM device
    289           //
    290           OemHookStatusCodeReport (
    291             Record[Index].CodeType,
    292             Record[Index].Value,
    293             Record[Index].Instance,
    294             NULL,
    295             NULL
    296             );
    297         }
    298       }
    299     }
    300   }
    301 }
    302