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