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