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