Home | History | Annotate | Download | only in DxeMain
      1 /** @file
      2   This file deals with Architecture Protocol (AP) registration in
      3   the Dxe Core. The mArchProtocols[] array represents a list of
      4   events that represent the Architectural Protocols.
      5 
      6 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
      7 This program and the accompanying materials
      8 are licensed and made available under the terms and conditions of the BSD License
      9 which accompanies this distribution.  The full text of the license may be found at
     10 http://opensource.org/licenses/bsd-license.php
     11 
     12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     14 
     15 **/
     16 
     17 #include "DxeMain.h"
     18 
     19 //
     20 // DXE Core Global Variables for all of the Architectural Protocols.
     21 // If a protocol is installed mArchProtocols[].Present will be TRUE.
     22 //
     23 // CoreNotifyOnArchProtocolInstallation () fills in mArchProtocols[].Event
     24 // and mArchProtocols[].Registration as it creates events for every array
     25 // entry.
     26 //
     27 EFI_CORE_PROTOCOL_NOTIFY_ENTRY  mArchProtocols[] = {
     28   { &gEfiSecurityArchProtocolGuid,         (VOID **)&gSecurity,      NULL, NULL, FALSE },
     29   { &gEfiCpuArchProtocolGuid,              (VOID **)&gCpu,           NULL, NULL, FALSE },
     30   { &gEfiMetronomeArchProtocolGuid,        (VOID **)&gMetronome,     NULL, NULL, FALSE },
     31   { &gEfiTimerArchProtocolGuid,            (VOID **)&gTimer,         NULL, NULL, FALSE },
     32   { &gEfiBdsArchProtocolGuid,              (VOID **)&gBds,           NULL, NULL, FALSE },
     33   { &gEfiWatchdogTimerArchProtocolGuid,    (VOID **)&gWatchdogTimer, NULL, NULL, FALSE },
     34   { &gEfiRuntimeArchProtocolGuid,          (VOID **)&gRuntime,       NULL, NULL, FALSE },
     35   { &gEfiVariableArchProtocolGuid,         (VOID **)NULL,            NULL, NULL, FALSE },
     36   { &gEfiVariableWriteArchProtocolGuid,    (VOID **)NULL,            NULL, NULL, FALSE },
     37   { &gEfiCapsuleArchProtocolGuid,          (VOID **)NULL,            NULL, NULL, FALSE },
     38   { &gEfiMonotonicCounterArchProtocolGuid, (VOID **)NULL,            NULL, NULL, FALSE },
     39   { &gEfiResetArchProtocolGuid,            (VOID **)NULL,            NULL, NULL, FALSE },
     40   { &gEfiRealTimeClockArchProtocolGuid,    (VOID **)NULL,            NULL, NULL, FALSE },
     41   { NULL,                                  (VOID **)NULL,            NULL, NULL, FALSE }
     42 };
     43 
     44 //
     45 // Optional protocols that the DXE Core will use if they are present
     46 //
     47 EFI_CORE_PROTOCOL_NOTIFY_ENTRY  mOptionalProtocols[] = {
     48   { &gEfiSecurity2ArchProtocolGuid,        (VOID **)&gSecurity2,     NULL, NULL, FALSE },
     49   { &gEfiSmmBase2ProtocolGuid,             (VOID **)&gSmmBase2,      NULL, NULL, FALSE },
     50   { NULL,                                  (VOID **)NULL,            NULL, NULL, FALSE }
     51 };
     52 
     53 //
     54 // Following is needed to display missing architectural protocols in debug builds
     55 //
     56 typedef struct {
     57   EFI_GUID  *ProtocolGuid;
     58   CHAR8     *GuidString;
     59 } GUID_TO_STRING_PROTOCOL_ENTRY;
     60 
     61 GLOBAL_REMOVE_IF_UNREFERENCED CONST GUID_TO_STRING_PROTOCOL_ENTRY mMissingProtocols[] = {
     62   { &gEfiSecurityArchProtocolGuid,         "Security"           },
     63   { &gEfiCpuArchProtocolGuid,              "CPU"                },
     64   { &gEfiMetronomeArchProtocolGuid,        "Metronome"          },
     65   { &gEfiTimerArchProtocolGuid,            "Timer"              },
     66   { &gEfiBdsArchProtocolGuid,              "Bds"                },
     67   { &gEfiWatchdogTimerArchProtocolGuid,    "Watchdog Timer"     },
     68   { &gEfiRuntimeArchProtocolGuid,          "Runtime"            },
     69   { &gEfiVariableArchProtocolGuid,         "Variable"           },
     70   { &gEfiVariableWriteArchProtocolGuid,    "Variable Write"     },
     71   { &gEfiCapsuleArchProtocolGuid,          "Capsule"            },
     72   { &gEfiMonotonicCounterArchProtocolGuid, "Monotonic Counter"  },
     73   { &gEfiResetArchProtocolGuid,            "Reset"              },
     74   { &gEfiRealTimeClockArchProtocolGuid,    "Real Time Clock"    },
     75   { NULL,                                  ""                   }
     76 };
     77 
     78 /**
     79   Return TRUE if all AP services are availible.
     80 
     81   @retval EFI_SUCCESS    All AP services are available
     82   @retval EFI_NOT_FOUND  At least one AP service is not available
     83 
     84 **/
     85 EFI_STATUS
     86 CoreAllEfiServicesAvailable (
     87   VOID
     88   )
     89 {
     90   EFI_CORE_PROTOCOL_NOTIFY_ENTRY  *Entry;
     91 
     92   for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) {
     93     if (!Entry->Present) {
     94       return EFI_NOT_FOUND;
     95     }
     96   }
     97   return EFI_SUCCESS;
     98 }
     99 
    100 
    101 /**
    102   Notification event handler registered by CoreNotifyOnArchProtocolInstallation ().
    103   This notify function is registered for every architectural protocol. This handler
    104   updates mArchProtocol[] array entry with protocol instance data and sets it's
    105   present flag to TRUE. If any constructor is required it is executed. The EFI
    106   System Table headers are updated.
    107 
    108   @param  Event          The Event that is being processed, not used.
    109   @param  Context        Event Context, not used.
    110 
    111 **/
    112 VOID
    113 EFIAPI
    114 GenericProtocolNotify (
    115   IN  EFI_EVENT  Event,
    116   IN  VOID       *Context
    117   )
    118 {
    119   EFI_STATUS                      Status;
    120   EFI_CORE_PROTOCOL_NOTIFY_ENTRY  *Entry;
    121   VOID                            *Protocol;
    122   LIST_ENTRY                      *Link;
    123   LIST_ENTRY                      TempLinkNode;
    124 
    125   Protocol = NULL;
    126 
    127   //
    128   // Get Entry from Context
    129   //
    130   Entry = (EFI_CORE_PROTOCOL_NOTIFY_ENTRY *)Context;
    131 
    132   //
    133   // See if the expected protocol is present in the handle database
    134   //
    135   Status = CoreLocateProtocol (Entry->ProtocolGuid, Entry->Registration, &Protocol);
    136   if (EFI_ERROR (Status)) {
    137     return;
    138   }
    139 
    140   //
    141   // Mark the protocol as present
    142   //
    143   Entry->Present = TRUE;
    144 
    145   //
    146   // Update protocol global variable if one exists. Entry->Protocol points to a global variable
    147   // if one exists in the DXE core for this Architectural Protocol
    148   //
    149   if (Entry->Protocol != NULL) {
    150     *(Entry->Protocol) = Protocol;
    151   }
    152 
    153   //
    154   // Do special operations for Architectural Protocols
    155   //
    156 
    157   if (CompareGuid (Entry->ProtocolGuid, &gEfiTimerArchProtocolGuid)) {
    158     //
    159     // Register the Core timer tick handler with the Timer AP
    160     //
    161     gTimer->RegisterHandler (gTimer, CoreTimerTick);
    162   }
    163 
    164   if (CompareGuid (Entry->ProtocolGuid, &gEfiRuntimeArchProtocolGuid)) {
    165     //
    166     // When runtime architectural protocol is available, updates CRC32 in the Debug Table
    167     //
    168     CoreUpdateDebugTableCrc32 ();
    169 
    170     //
    171     // Update the Runtime Architectural protocol with the template that the core was
    172     // using so there would not need to be a dependency on the Runtime AP
    173     //
    174 
    175     //
    176     // Copy all the registered Image to new gRuntime protocol
    177     //
    178     for (Link = gRuntimeTemplate.ImageHead.ForwardLink; Link != &gRuntimeTemplate.ImageHead; Link = TempLinkNode.ForwardLink) {
    179       CopyMem (&TempLinkNode, Link, sizeof(LIST_ENTRY));
    180       InsertTailList (&gRuntime->ImageHead, Link);
    181     }
    182     //
    183     // Copy all the registered Event to new gRuntime protocol
    184     //
    185     for (Link = gRuntimeTemplate.EventHead.ForwardLink; Link != &gRuntimeTemplate.EventHead; Link = TempLinkNode.ForwardLink) {
    186       CopyMem (&TempLinkNode, Link, sizeof(LIST_ENTRY));
    187       InsertTailList (&gRuntime->EventHead, Link);
    188     }
    189 
    190     //
    191     // Clean up gRuntimeTemplate
    192     //
    193     gRuntimeTemplate.ImageHead.ForwardLink = &gRuntimeTemplate.ImageHead;
    194     gRuntimeTemplate.ImageHead.BackLink    = &gRuntimeTemplate.ImageHead;
    195     gRuntimeTemplate.EventHead.ForwardLink = &gRuntimeTemplate.EventHead;
    196     gRuntimeTemplate.EventHead.BackLink    = &gRuntimeTemplate.EventHead;
    197   }
    198 
    199   //
    200   // It's over kill to do them all every time, but it saves a lot of code.
    201   //
    202   CalculateEfiHdrCrc (&gDxeCoreRT->Hdr);
    203   CalculateEfiHdrCrc (&gBS->Hdr);
    204   CalculateEfiHdrCrc (&gDxeCoreST->Hdr);
    205   CalculateEfiHdrCrc (&gDxeCoreDS->Hdr);
    206 }
    207 
    208 /**
    209   Creates an event for each entry in a table that is fired everytime a Protocol
    210   of a specific type is installed.
    211 
    212   @param Entry  Pointer to EFI_CORE_PROTOCOL_NOTIFY_ENTRY.
    213 
    214 **/
    215 VOID
    216 CoreNotifyOnProtocolEntryTable (
    217   EFI_CORE_PROTOCOL_NOTIFY_ENTRY  *Entry
    218   )
    219 {
    220   EFI_STATUS  Status;
    221 
    222   for (; Entry->ProtocolGuid != NULL; Entry++) {
    223     //
    224     // Create the event
    225     //
    226     Status = CoreCreateEvent (
    227               EVT_NOTIFY_SIGNAL,
    228               TPL_CALLBACK,
    229               GenericProtocolNotify,
    230               Entry,
    231               &Entry->Event
    232               );
    233     ASSERT_EFI_ERROR(Status);
    234 
    235     //
    236     // Register for protocol notifactions on this event
    237     //
    238     Status = CoreRegisterProtocolNotify (
    239               Entry->ProtocolGuid,
    240               Entry->Event,
    241               &Entry->Registration
    242               );
    243     ASSERT_EFI_ERROR(Status);
    244   }
    245 }
    246 
    247 /**
    248   Creates an events for the Architectural Protocols and the optional protocols
    249   that are fired everytime a Protocol of a specific type is installed.
    250 
    251 **/
    252 VOID
    253 CoreNotifyOnProtocolInstallation (
    254   VOID
    255   )
    256 {
    257   CoreNotifyOnProtocolEntryTable (mArchProtocols);
    258   CoreNotifyOnProtocolEntryTable (mOptionalProtocols);
    259 }
    260 
    261 
    262 /**
    263   Displays Architectural protocols that were not loaded and are required for DXE
    264   core to function.  Only used in Debug Builds.
    265 
    266 **/
    267 VOID
    268 CoreDisplayMissingArchProtocols (
    269   VOID
    270   )
    271 {
    272   EFI_CORE_PROTOCOL_NOTIFY_ENTRY       *Entry;
    273   CONST GUID_TO_STRING_PROTOCOL_ENTRY  *MissingEntry;
    274 
    275   for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) {
    276     if (!Entry->Present) {
    277       for (MissingEntry = mMissingProtocols; MissingEntry->ProtocolGuid != NULL; MissingEntry++) {
    278         if (CompareGuid (Entry->ProtocolGuid, MissingEntry->ProtocolGuid)) {
    279           DEBUG ((DEBUG_ERROR, "\n%a Arch Protocol not present!!\n", MissingEntry->GuidString));
    280           break;
    281         }
    282       }
    283     }
    284   }
    285 }
    286