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