Update library constructor definition.
[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 EFIAPI
121 RuntimeDriverLibConstruct (
122 IN EFI_HANDLE ImageHandle,
123 IN EFI_SYSTEM_TABLE *SystemTable
124 )
125 /*++
126
127 Routine Description:
128
129 Intialize runtime Driver Lib if it has not yet been initialized.
130
131 Arguments:
132
133 ImageHandle - The firmware allocated handle for the EFI image.
134
135 SystemTable - A pointer to the EFI System Table.
136
137 GoVirtualChildEvent - Caller can register a virtual notification event.
138
139 Returns:
140
141 EFI_STATUS always returns EFI_SUCCESS except EFI_ALREADY_STARTED if already started.
142
143 --*/
144 {
145 EFI_PLABEL *Plabel;
146 EFI_STATUS Status;
147
148 mRT = SystemTable->RuntimeServices;
149
150 //
151 // The protocol contains a function pointer, which is an indirect procedure call.
152 // An indirect procedure call goes through a plabel, and pointer to a function is
153 // a pointer to a plabel. To implement indirect procedure calls that can work in
154 // both physical and virtual mode, two plabels are required (one physical and one
155 // virtual). So lets grap the physical PLABEL for the EsalEntryPoint and store it
156 // away. We cache it in a module global, so we can register the vitrual version.
157 //
158 Status = gBS->LocateProtocol (&gEfiExtendedSalBootServiceProtocolGuid, NULL, &mEsalBootService);
159 ASSERT_EFI_ERROR (Status);
160
161 Plabel = (EFI_PLABEL *) (UINTN) mEsalBootService->ExtendedSalProc;
162
163 mPlabel.EntryPoint = Plabel->EntryPoint;
164 mPlabel.GP = Plabel->GP;
165
166 SetEsalPhysicalEntryPoint (mPlabel.EntryPoint, mPlabel.GP);
167
168 //
169 // Register our ExitBootServices () notify function
170 //
171
172 Status = gBS->CreateEvent (
173 EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES,
174 EFI_TPL_NOTIFY,
175 RuntimeDriverExitBootServices,
176 NULL,
177 &mRuntimeNotifyEvent
178 );
179 ASSERT_EFI_ERROR (Status);
180
181 //
182 // Register SetVirtualAddressMap () notify function
183 //
184
185 Status = gBS->CreateEvent (
186 EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
187 EFI_TPL_NOTIFY,
188 RuntimeLibVirtualNotifyEvent,
189 NULL,
190 mEfiVirtualNotifyEvent
191 );
192 ASSERT_EFI_ERROR (Status);
193
194 return EFI_SUCCESS;
195 }
196
197 EFI_STATUS
198 EFIAPI
199 RuntimeDriverLibDeconstruct (
200 VOID
201 )
202 /*++
203
204 Routine Description:
205
206 This routine will free some resources which have been allocated in
207 EfiInitializeRuntimeDriverLib(). If a runtime driver exits with an error,
208 it must call this routine to free the allocated resource before the exiting.
209
210 Arguments:
211
212 None
213
214 Returns:
215
216 EFI_SUCCESS - Shotdown the Runtime Driver Lib successfully
217 EFI_UNSUPPORTED - Runtime Driver lib was not initialized at all
218
219 --*/
220 {
221 EFI_STATUS Status;
222
223 //
224 // Close our ExitBootServices () notify function
225 //
226 Status = gBS->CloseEvent (mRuntimeNotifyEvent);
227 ASSERT_EFI_ERROR (Status);
228
229 //
230 // Close SetVirtualAddressMap () notify function
231 //
232 Status = gBS->CloseEvent (mEfiVirtualNotifyEvent);
233 ASSERT_EFI_ERROR (Status);
234
235 return EFI_SUCCESS;
236 }
237
238 BOOLEAN
239 EfiAtRuntime (
240 VOID
241 )
242 /*++
243
244 Routine Description:
245 Return TRUE if ExitBootService () has been called
246
247 Arguments:
248 NONE
249
250 Returns:
251 TRUE - If ExitBootService () has been called
252
253 --*/
254 {
255 EFI_GUID Guid = EFI_EXTENDED_SAL_VIRTUAL_SERVICES_PROTOCOL_GUID;
256 SAL_RETURN_REGS ReturnReg;
257
258 ReturnReg = EfiCallEsalService (&Guid, IsEfiRuntime, 0, 0, 0, 0, 0, 0, 0);
259
260 return (BOOLEAN) (ReturnReg.r9 == 1);
261 }
262
263 BOOLEAN
264 EfiGoneVirtual (
265 VOID
266 )
267 /*++
268
269 Routine Description:
270 Return TRUE if SetVirtualAddressMap () has been called
271
272 Arguments:
273 NONE
274
275 Returns:
276 TRUE - If SetVirtualAddressMap () has been called
277
278 --*/
279 {
280 EFI_GUID Guid = EFI_EXTENDED_SAL_VIRTUAL_SERVICES_PROTOCOL_GUID;
281 SAL_RETURN_REGS ReturnReg;
282
283 ReturnReg = EfiCallEsalService (&Guid, IsVirtual, 0, 0, 0, 0, 0, 0, 0);
284
285 return (BOOLEAN) (ReturnReg.r9 == 1);
286 }