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