]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Library/EdkDxeSalLib/Ipf/EsalServiceLib.c
Remove use of global variable at runtime in this lib
[mirror_edk2.git] / EdkModulePkg / Library / EdkDxeSalLib / Ipf / EsalServiceLib.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 EsalServiceLib.c
15
16 Abstract:
17
18 --*/
19
20 #include <Ipf/IpfDefines.h>
21
22 EXTENDED_SAL_BOOT_SERVICE_PROTOCOL *mEsalBootService = NULL;
23 EFI_PLABEL mPlabel;
24
25 EFI_STATUS
26 EFIAPI
27 DxeSalLibInitialize (
28 VOID
29 )
30 {
31 EFI_PLABEL *Plabel;
32 EFI_STATUS Status;
33
34 if (mEsalBootService != NULL) {
35 return EFI_SUCCESS;
36 }
37
38 //
39 // The protocol contains a function pointer, which is an indirect procedure call.
40 // An indirect procedure call goes through a plabel, and pointer to a function is
41 // a pointer to a plabel. To implement indirect procedure calls that can work in
42 // both physical and virtual mode, two plabels are required (one physical and one
43 // virtual). So lets grap the physical PLABEL for the EsalEntryPoint and store it
44 // away. We cache it in a module global, so we can register the vitrual version.
45 //
46 Status = gBS->LocateProtocol (&gEfiExtendedSalBootServiceProtocolGuid, NULL, &mEsalBootService);
47 if (EFI_ERROR (Status)) {
48 mEsalBootService = NULL;
49 return EFI_SUCCESS;
50 }
51
52 Plabel = (EFI_PLABEL *) (UINTN) mEsalBootService->ExtendedSalProc;
53
54 mPlabel.EntryPoint = Plabel->EntryPoint;
55 mPlabel.GP = Plabel->GP;
56 SetEsalPhysicalEntryPoint (mPlabel.EntryPoint, mPlabel.GP);
57
58 return EFI_SUCCESS;
59 }
60
61 EFI_STATUS
62 EFIAPI
63 DxeSalLibConstructor (
64 IN EFI_HANDLE ImageHandle,
65 IN EFI_SYSTEM_TABLE *SystemTable
66 )
67 {
68 return DxeSalLibInitialize ();
69 }
70
71 VOID
72 EFIAPI
73 DxeSalVirtualNotifyEvent (
74 IN EFI_EVENT Event,
75 IN VOID *Context
76 )
77 /*++
78
79 Routine Description:
80
81 Fixup virtual address pointer of label.
82
83 Arguments:
84
85 Event - The Event that is being processed
86
87 Context - Event Context
88
89 Returns:
90
91 None
92
93 --*/
94 {
95 EfiConvertPointer (0x0, (VOID **) &mPlabel.EntryPoint);
96 EfiConvertPointer (EFI_IPF_GP_POINTER, (VOID **) &mPlabel.GP);
97
98 SetEsalVirtualEntryPoint (mPlabel.EntryPoint, mPlabel.GP);
99 }
100
101 EFI_STATUS
102 EFIAPI
103 RegisterEsalFunction (
104 IN UINT64 FunctionId,
105 IN EFI_GUID *ClassGuid,
106 IN SAL_INTERNAL_EXTENDED_SAL_PROC Function,
107 IN VOID *ModuleGlobal
108 )
109 /*++
110
111 Routine Description:
112
113 Register ESAL Class Function and it's asociated global.
114 This function is boot service only!
115
116 Arguments:
117 FunctionId - ID of function to register
118 ClassGuid - GUID of function class
119 Function - Function to register under ClassGuid/FunctionId pair
120 ModuleGlobal - Module global for Function.
121
122 Returns:
123 EFI_SUCCESS - If ClassGuid/FunctionId Function was registered.
124
125 --*/
126 {
127 DxeSalLibInitialize ();
128 return mEsalBootService->AddExtendedSalProc (
129 mEsalBootService,
130 ClassGuid,
131 FunctionId,
132 Function,
133 ModuleGlobal
134 );
135 }
136
137 EFI_STATUS
138 EFIAPI
139 RegisterEsalClass (
140 IN EFI_GUID *ClassGuid,
141 IN VOID *ModuleGlobal,
142 ...
143 )
144 /*++
145
146 Routine Description:
147
148 Register ESAL Class and it's asociated global.
149 This function is boot service only!
150
151 Arguments:
152 ClassGuid - GUID of function class
153 ModuleGlobal - Module global for Function.
154 ... - SAL_INTERNAL_EXTENDED_SAL_PROC and FunctionId pairs. NULL
155 indicates the end of the list.
156
157 Returns:
158 EFI_SUCCESS - All members of ClassGuid registered
159
160 --*/
161 {
162 VA_LIST Args;
163 EFI_STATUS Status;
164 SAL_INTERNAL_EXTENDED_SAL_PROC Function;
165 UINT64 FunctionId;
166 EFI_HANDLE NewHandle;
167
168 VA_START (Args, ModuleGlobal);
169
170 Status = EFI_SUCCESS;
171 while (!EFI_ERROR (Status)) {
172 Function = (SAL_INTERNAL_EXTENDED_SAL_PROC) VA_ARG (Args, SAL_INTERNAL_EXTENDED_SAL_PROC);
173 if (Function == NULL) {
174 break;
175 }
176
177 FunctionId = VA_ARG (Args, UINT64);
178
179 Status = RegisterEsalFunction (FunctionId, ClassGuid, Function, ModuleGlobal);
180 }
181
182 if (EFI_ERROR (Status)) {
183 return Status;
184 }
185
186 NewHandle = NULL;
187 return gBS->InstallProtocolInterface (
188 &NewHandle,
189 ClassGuid,
190 EFI_NATIVE_INTERFACE,
191 NULL
192 );
193 }
194
195 SAL_RETURN_REGS
196 EFIAPI
197 EfiCallEsalService (
198 IN EFI_GUID *ClassGuid,
199 IN UINT64 FunctionId,
200 IN UINT64 Arg2,
201 IN UINT64 Arg3,
202 IN UINT64 Arg4,
203 IN UINT64 Arg5,
204 IN UINT64 Arg6,
205 IN UINT64 Arg7,
206 IN UINT64 Arg8
207 )
208 /*++
209
210 Routine Description:
211
212 Call module that is not linked direclty to this module. This code is IP
213 relative and hides the binding issues of virtual or physical calling. The
214 function that gets dispatched has extra arguments that include the registered
215 module global and a boolean flag to indicate if the system is in virutal mode.
216
217 Arguments:
218 ClassGuid - GUID of function
219 FunctionId - Function in ClassGuid to call
220 Arg2 - Argument 2 ClassGuid/FunctionId defined
221 Arg3 - Argument 3 ClassGuid/FunctionId defined
222 Arg4 - Argument 4 ClassGuid/FunctionId defined
223 Arg5 - Argument 5 ClassGuid/FunctionId defined
224 Arg6 - Argument 6 ClassGuid/FunctionId defined
225 Arg7 - Argument 7 ClassGuid/FunctionId defined
226 Arg8 - Argument 8 ClassGuid/FunctionId defined
227
228 Returns:
229 Status of ClassGuid/FuncitonId
230
231 --*/
232 {
233 SAL_RETURN_REGS ReturnReg;
234 SAL_EXTENDED_SAL_PROC EsalProc;
235
236 ReturnReg = GetEsalEntryPoint ();
237 if (ReturnReg.Status != EFI_SAL_SUCCESS) {
238 return ReturnReg;
239 }
240
241 //
242 // Look at the physical mode ESAL entry point to determine of the ESAL entry point has been initialized
243 //
244 if (*(UINT64 *)ReturnReg.r9 == 0 && *(UINT64 *)(ReturnReg.r9 + 8) == 0) {
245 //
246 // Both the function ponter and the GP value are zero, so attempt to initialize the ESAL Entry Point
247 //
248 DxeSalLibInitialize ();
249 ReturnReg = GetEsalEntryPoint ();
250 if (ReturnReg.Status != EFI_SAL_SUCCESS) {
251 return ReturnReg;
252 }
253 if (*(UINT64 *)ReturnReg.r9 == 0 && *(UINT64 *)(ReturnReg.r9 + 8) == 0) {
254 //
255 // The ESAL Entry Point could not be initialized
256 //
257 ReturnReg.Status = EFI_SAL_ERROR;
258 return ReturnReg;
259 }
260 }
261
262 if (ReturnReg.r11 & PSR_IT_MASK) {
263 //
264 // Virtual mode plabel to entry point
265 //
266 EsalProc = (SAL_EXTENDED_SAL_PROC) ReturnReg.r10;
267 } else {
268 //
269 // Physical mode plabel to entry point
270 //
271 EsalProc = (SAL_EXTENDED_SAL_PROC) ReturnReg.r9;
272 }
273
274 return EsalProc (
275 ClassGuid,
276 FunctionId,
277 Arg2,
278 Arg3,
279 Arg4,
280 Arg5,
281 Arg6,
282 Arg7,
283 Arg8
284 );
285 }