1 /** @file
2   This driver will register two callbacks to call fsp's notifies.
3 
4   Copyright (c) 2014 - 2015, 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 <PiDxe.h>
16 
17 #include <Protocol/PciEnumerationComplete.h>
18 
19 #include <Library/UefiDriverEntryPoint.h>
20 #include <Library/UefiBootServicesTableLib.h>
21 #include <Library/DebugLib.h>
22 #include <Library/BaseMemoryLib.h>
23 #include <Library/UefiLib.h>
24 #include <Library/FspApiLib.h>
25 
26 /**
27   Relocate this image under 4G memory.
28 
29   @param  ImageHandle  Handle of driver image.
30   @param  SystemTable  Pointer to system table.
31 
32   @retval EFI_SUCCESS  Image successfully relocated.
33   @retval EFI_ABORTED  Failed to relocate image.
34 
35 **/
36 EFI_STATUS
37 RelocateImageUnder4GIfNeeded (
38   IN EFI_HANDLE           ImageHandle,
39   IN EFI_SYSTEM_TABLE     *SystemTable
40   );
41 
42 FSP_INFO_HEADER *mFspHeader = NULL;
43 
44 /**
45   PciEnumerationComplete Protocol notification event handler.
46 
47   @param[in] Event    Event whose notification function is being invoked.
48   @param[in] Context  Pointer to the notification function's context.
49 **/
50 VOID
51 EFIAPI
OnPciEnumerationComplete(IN EFI_EVENT Event,IN VOID * Context)52 OnPciEnumerationComplete (
53   IN EFI_EVENT  Event,
54   IN VOID       *Context
55   )
56 {
57   NOTIFY_PHASE_PARAMS NotifyPhaseParams;
58   EFI_STATUS          Status;
59   VOID                *Interface;
60 
61   //
62   // Try to locate it because gEfiPciEnumerationCompleteProtocolGuid will trigger it once when registration.
63   // Just return if it is not found.
64   //
65   Status = gBS->LocateProtocol (
66                   &gEfiPciEnumerationCompleteProtocolGuid,
67                   NULL,
68                   &Interface
69                   );
70   if (EFI_ERROR (Status)) {
71     return ;
72   }
73 
74   NotifyPhaseParams.Phase = EnumInitPhaseAfterPciEnumeration;
75   Status = CallFspNotifyPhase (mFspHeader, &NotifyPhaseParams);
76   if (Status != EFI_SUCCESS) {
77     DEBUG((DEBUG_ERROR, "FSP NotifyPhase AfterPciEnumeration failed, status: 0x%x\n", Status));
78   } else {
79     DEBUG((DEBUG_INFO, "FSP NotifyPhase AfterPciEnumeration Success.\n"));
80   }
81 }
82 
83 /**
84   Notification function of EVT_GROUP_READY_TO_BOOT event group.
85 
86   This is a notification function registered on EVT_GROUP_READY_TO_BOOT event group.
87   When the Boot Manager is about to load and execute a boot option, it reclaims variable
88   storage if free size is below the threshold.
89 
90   @param[in] Event        Event whose notification function is being invoked.
91   @param[in] Context      Pointer to the notification function's context.
92 
93 **/
94 VOID
95 EFIAPI
OnReadyToBoot(IN EFI_EVENT Event,IN VOID * Context)96 OnReadyToBoot (
97   IN EFI_EVENT  Event,
98   IN VOID       *Context
99   )
100 {
101   NOTIFY_PHASE_PARAMS NotifyPhaseParams;
102   EFI_STATUS          Status;
103 
104   gBS->CloseEvent (Event);
105 
106   NotifyPhaseParams.Phase = EnumInitPhaseReadyToBoot;
107   Status = CallFspNotifyPhase (mFspHeader, &NotifyPhaseParams);
108   if (Status != EFI_SUCCESS) {
109     DEBUG((DEBUG_ERROR, "FSP NotifyPhase ReadyToBoot failed, status: 0x%x\n", Status));
110   } else {
111     DEBUG((DEBUG_INFO, "FSP NotifyPhase ReadyToBoot Success.\n"));
112   }
113 }
114 
115 /**
116   Main entry for the FSP DXE module.
117 
118   This routine registers two callbacks to call fsp's notifies.
119 
120   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
121   @param[in] SystemTable    A pointer to the EFI System Table.
122 
123   @retval EFI_SUCCESS       The entry point is executed successfully.
124   @retval other             Some error occurs when executing this entry point.
125 
126 **/
127 EFI_STATUS
128 EFIAPI
FspDxeEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)129 FspDxeEntryPoint (
130   IN EFI_HANDLE         ImageHandle,
131   IN EFI_SYSTEM_TABLE   *SystemTable
132   )
133 {
134   EFI_STATUS Status;
135   EFI_EVENT  ReadyToBootEvent;
136   VOID       *Registration;
137   EFI_EVENT  ProtocolNotifyEvent;
138 
139   //
140   // Load this driver's image to memory
141   //
142   Status = RelocateImageUnder4GIfNeeded (ImageHandle, SystemTable);
143   if (EFI_ERROR (Status)) {
144     return EFI_SUCCESS;
145   }
146 
147   if (PcdGet32 (PcdFlashFvSecondFspBase) == 0) {
148     mFspHeader = FspFindFspHeader (PcdGet32 (PcdFlashFvFspBase));
149   } else {
150     mFspHeader = FspFindFspHeader (PcdGet32 (PcdFlashFvSecondFspBase));
151   }
152   DEBUG ((DEBUG_INFO, "FspHeader - 0x%x\n", mFspHeader));
153   if (mFspHeader == NULL) {
154     return EFI_DEVICE_ERROR;
155   }
156 
157   ProtocolNotifyEvent = EfiCreateProtocolNotifyEvent (
158                           &gEfiPciEnumerationCompleteProtocolGuid,
159                           TPL_CALLBACK,
160                           OnPciEnumerationComplete,
161                           NULL,
162                           &Registration
163                           );
164   ASSERT (ProtocolNotifyEvent != NULL);
165 
166   Status = EfiCreateEventReadyToBootEx (
167              TPL_CALLBACK,
168              OnReadyToBoot,
169              NULL,
170              &ReadyToBootEvent
171              );
172   ASSERT_EFI_ERROR (Status);
173 
174   return EFI_SUCCESS;
175 }
176 
177