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