a4eeb3383838d3ff29a9d6f284ee1dd18be3ab09
[mirror_edk2.git] / EdkModulePkg / Library / EdkUefiRuntimeLib / Ipf / RuntimeLib.c
1 /*++
2
3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. 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 Module Name:
13
14 RuntimeLib.c
15
16 Abstract:
17
18 Light weight lib to support Tiano drivers.
19
20 --*/
21
22 #include <SalApi.h>
23 #include <RuntimeLibInternal.h>
24
25 //
26 // Driver Lib Module Globals
27 //
28
29 STATIC EFI_EVENT mRuntimeNotifyEvent;
30 STATIC EFI_EVENT mEfiVirtualNotifyEvent;
31
32 STATIC EFI_PLABEL mPlabel;
33 STATIC EXTENDED_SAL_BOOT_SERVICE_PROTOCOL *mEsalBootService;
34
35 EFI_RUNTIME_SERVICES *mRT = NULL;
36
37 STATIC
38 VOID
39 EFIAPI
40 RuntimeDriverExitBootServices (
41 IN EFI_EVENT Event,
42 IN VOID *Context
43 )
44 /*++
45
46 Routine Description:
47
48 Set AtRuntime flag as TRUE after ExitBootServices
49
50 Arguments:
51
52 Event - The Event that is being processed
53
54 Context - Event Context
55
56 Returns:
57
58 None
59
60 --*/
61 {
62 EFI_EVENT_NOTIFY ChildNotifyEventHandler;
63 UINTN Index;
64
65 for (Index = 0; _gDriverExitBootServicesEvent[Index] != NULL; Index++) {
66 ChildNotifyEventHandler = _gDriverExitBootServicesEvent[Index];
67 ChildNotifyEventHandler (Event, NULL);
68 }
69 }
70
71 STATIC
72 VOID
73 EFIAPI
74 RuntimeLibVirtualNotifyEvent (
75 IN EFI_EVENT Event,
76 IN VOID *Context
77 )
78 /*++
79
80 Routine Description:
81
82 Fixup internal data so that EFI can be call in virtual mode.
83 Call the passed in Child Notify event and convert any pointers in
84 lib to virtual mode.
85
86 Arguments:
87
88 Event - The Event that is being processed
89
90 Context - Event Context
91
92 Returns:
93
94 None
95
96 --*/
97 {
98 UINTN Index;
99 EFI_EVENT_NOTIFY ChildNotifyEventHandler;
100
101 for (Index = 0; _gDriverSetVirtualAddressMapEvent[Index] != NULL; Index++) {
102 ChildNotifyEventHandler = _gDriverSetVirtualAddressMapEvent[Index];
103 ChildNotifyEventHandler (Event, NULL);
104 }
105
106 mRT->ConvertPointer (0x0, (VOID **) &mPlabel.EntryPoint);
107 mRT->ConvertPointer (EFI_IPF_GP_POINTER, (VOID **) &mPlabel.GP);
108
109 SetEsalVirtualEntryPoint (mPlabel.EntryPoint, mPlabel.GP);
110
111 //
112 // Clear out BootService globals
113 //
114 gBS = NULL;
115 gST = NULL;
116 mRT = NULL;
117 }
118
119 EFI_STATUS
120 RuntimeDriverLibConstruct (
121 IN EFI_HANDLE ImageHandle,
122 IN EFI_SYSTEM_TABLE *SystemTable
123 )
124 /*++
125
126 Routine Description:
127
128 Intialize runtime Driver Lib if it has not yet been initialized.
129
130 Arguments:
131
132 ImageHandle - The firmware allocated handle for the EFI image.
133
134 SystemTable - A pointer to the EFI System Table.
135
136 GoVirtualChildEvent - Caller can register a virtual notification event.
137
138 Returns:
139
140 EFI_STATUS always returns EFI_SUCCESS except EFI_ALREADY_STARTED if already started.
141
142 --*/
143 {
144 EFI_PLABEL *Plabel;
145 EFI_STATUS Status;
146
147 mRT = SystemTable->RuntimeServices;
148
149 //
150 // The protocol contains a function pointer, which is an indirect procedure call.
151 // An indirect procedure call goes through a plabel, and pointer to a function is
152 // a pointer to a plabel. To implement indirect procedure calls that can work in
153 // both physical and virtual mode, two plabels are required (one physical and one
154 // virtual). So lets grap the physical PLABEL for the EsalEntryPoint and store it
155 // away. We cache it in a module global, so we can register the vitrual version.
156 //
157 Status = gBS->LocateProtocol (&gEfiExtendedSalBootServiceProtocolGuid, NULL, &mEsalBootService);
158 ASSERT_EFI_ERROR (Status);
159
160 Plabel = (EFI_PLABEL *) (UINTN) mEsalBootService->ExtendedSalProc;
161
162 mPlabel.EntryPoint = Plabel->EntryPoint;
163 mPlabel.GP = Plabel->GP;
164
165 SetEsalPhysicalEntryPoint (mPlabel.EntryPoint, mPlabel.GP);
166
167 //
168 // Register our ExitBootServices () notify function
169 //
170
171 Status = gBS->CreateEvent (
172 EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES,
173 EFI_TPL_NOTIFY,
174 RuntimeDriverExitBootServices,
175 NULL,
176 &mRuntimeNotifyEvent
177 );
178 ASSERT_EFI_ERROR (Status);
179
180 //
181 // Register SetVirtualAddressMap () notify function
182 //
183
184 Status = gBS->CreateEvent (
185 EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
186 EFI_TPL_NOTIFY,
187 RuntimeLibVirtualNotifyEvent,
188 NULL,
189 mEfiVirtualNotifyEvent
190 );
191 ASSERT_EFI_ERROR (Status);
192
193 return EFI_SUCCESS;
194 }
195
196 EFI_STATUS
197 RuntimeDriverLibDeconstruct (
198 VOID
199 )
200 /*++
201
202 Routine Description:
203
204 This routine will free some resources which have been allocated in
205 EfiInitializeRuntimeDriverLib(). If a runtime driver exits with an error,
206 it must call this routine to free the allocated resource before the exiting.
207
208 Arguments:
209
210 None
211
212 Returns:
213
214 EFI_SUCCESS - Shotdown the Runtime Driver Lib successfully
215 EFI_UNSUPPORTED - Runtime Driver lib was not initialized at all
216
217 --*/
218 {
219 EFI_STATUS Status;
220
221 //
222 // Close our ExitBootServices () notify function
223 //
224 Status = gBS->CloseEvent (mRuntimeNotifyEvent);
225 ASSERT_EFI_ERROR (Status);
226
227 //
228 // Close SetVirtualAddressMap () notify function
229 //
230 Status = gBS->CloseEvent (mEfiVirtualNotifyEvent);
231 ASSERT_EFI_ERROR (Status);
232
233 return EFI_SUCCESS;
234 }
235
236 BOOLEAN
237 EfiAtRuntime (
238 VOID
239 )
240 /*++
241
242 Routine Description:
243 Return TRUE if ExitBootService () has been called
244
245 Arguments:
246 NONE
247
248 Returns:
249 TRUE - If ExitBootService () has been called
250
251 --*/
252 {
253 EFI_GUID Guid = EFI_EXTENDED_SAL_VIRTUAL_SERVICES_PROTOCOL_GUID;
254 SAL_RETURN_REGS ReturnReg;
255
256 ReturnReg = EfiCallEsalService (&Guid, IsEfiRuntime, 0, 0, 0, 0, 0, 0, 0);
257
258 return (BOOLEAN) (ReturnReg.r9 == 1);
259 }
260
261 BOOLEAN
262 EfiGoneVirtual (
263 VOID
264 )
265 /*++
266
267 Routine Description:
268 Return TRUE if SetVirtualAddressMap () has been called
269
270 Arguments:
271 NONE
272
273 Returns:
274 TRUE - If SetVirtualAddressMap () has been called
275
276 --*/
277 {
278 EFI_GUID Guid = EFI_EXTENDED_SAL_VIRTUAL_SERVICES_PROTOCOL_GUID;
279 SAL_RETURN_REGS ReturnReg;
280
281 ReturnReg = EfiCallEsalService (&Guid, IsVirtual, 0, 0, 0, 0, 0, 0, 0);
282
283 return (BOOLEAN) (ReturnReg.r9 == 1);
284 }