]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/EbcDxe/Ia32/EbcSupport.c
Update the copyright notice format
[mirror_edk2.git] / MdeModulePkg / Universal / EbcDxe / Ia32 / EbcSupport.c
CommitLineData
fb0b259e 1/** @file\r
53c71d09 2 This module contains EBC support routines that are customized based on\r
3 the target processor.\r
4\r
e5eed7d3
HT
5Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
6This program and the accompanying materials\r
fb0b259e 7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
53c71d09 15\r
16#include "EbcInt.h"\r
17#include "EbcExecute.h"\r
18\r
19//\r
20// NOTE: This is the stack size allocated for the interpreter\r
21// when it executes an EBC image. The requirements can change\r
22// based on whether or not a debugger is present, and other\r
23// platform-specific configurations.\r
24//\r
25#define VM_STACK_SIZE (1024 * 4)\r
26#define EBC_THUNK_SIZE 32\r
27\r
28#define STACK_REMAIN_SIZE (1024 * 4)\r
53c71d09 29\r
53c71d09 30\r
fb0b259e 31/**\r
32 This function is called to execute an EBC CALLEX instruction.\r
53c71d09 33 The function check the callee's content to see whether it is common native\r
34 code or a thunk to another piece of EBC code.\r
35 If the callee is common native code, use EbcLLCAllEXASM to manipulate,\r
36 otherwise, set the VM->IP to target EBC code directly to avoid another VM\r
37 be startup which cost time and stack space.\r
53c71d09 38\r
8e3bc754 39 @param VmPtr Pointer to a VM context.\r
40 @param FuncAddr Callee's address\r
41 @param NewStackPointer New stack pointer after the call\r
42 @param FramePtr New frame pointer after the call\r
43 @param Size The size of call instruction\r
53c71d09 44\r
fb0b259e 45**/\r
46VOID\r
47EbcLLCALLEX (\r
48 IN VM_CONTEXT *VmPtr,\r
49 IN UINTN FuncAddr,\r
50 IN UINTN NewStackPointer,\r
51 IN VOID *FramePtr,\r
52 IN UINT8 Size\r
53 )\r
53c71d09 54{\r
55 UINTN IsThunk;\r
56 UINTN TargetEbcAddr;\r
57\r
58 IsThunk = 1;\r
59 TargetEbcAddr = 0;\r
60\r
61 //\r
62 // Processor specific code to check whether the callee is a thunk to EBC.\r
63 //\r
64 if (*((UINT8 *)FuncAddr) != 0xB8) {\r
65 IsThunk = 0;\r
66 goto Action;\r
67 }\r
68 if (*((UINT8 *)FuncAddr + 1) != 0xBC) {\r
69 IsThunk = 0;\r
70 goto Action;\r
71 }\r
72 if (*((UINT8 *)FuncAddr + 2) != 0x2E) {\r
73 IsThunk = 0;\r
74 goto Action;\r
75 }\r
76 if (*((UINT8 *)FuncAddr + 3) != 0x11) {\r
77 IsThunk = 0;\r
78 goto Action;\r
79 }\r
80 if (*((UINT8 *)FuncAddr + 4) != 0xCA) {\r
81 IsThunk = 0;\r
82 goto Action;\r
83 }\r
84 if (*((UINT8 *)FuncAddr + 5) != 0xB8) {\r
85 IsThunk = 0;\r
86 goto Action;\r
87 }\r
88 if (*((UINT8 *)FuncAddr + 10) != 0xB9) {\r
89 IsThunk = 0;\r
90 goto Action;\r
91 }\r
92 if (*((UINT8 *)FuncAddr + 15) != 0xFF) {\r
93 IsThunk = 0;\r
94 goto Action;\r
95 }\r
96 if (*((UINT8 *)FuncAddr + 16) != 0xE1) {\r
97 IsThunk = 0;\r
98 goto Action;\r
99 }\r
100\r
101 TargetEbcAddr = ((UINTN)(*((UINT8 *)FuncAddr + 9)) << 24) + ((UINTN)(*((UINT8 *)FuncAddr + 8)) << 16) +\r
102 ((UINTN)(*((UINT8 *)FuncAddr + 7)) << 8) + ((UINTN)(*((UINT8 *)FuncAddr + 6)));\r
103\r
104Action:\r
105 if (IsThunk == 1){\r
106 //\r
107 // The callee is a thunk to EBC, adjust the stack pointer down 16 bytes and\r
108 // put our return address and frame pointer on the VM stack.\r
109 // Then set the VM's IP to new EBC code.\r
110 //\r
1ccdbf2a 111 VmPtr->Gpr[0] -= 8;\r
112 VmWriteMemN (VmPtr, (UINTN) VmPtr->Gpr[0], (UINTN) FramePtr);\r
113 VmPtr->FramePtr = (VOID *) (UINTN) VmPtr->Gpr[0];\r
114 VmPtr->Gpr[0] -= 8;\r
115 VmWriteMem64 (VmPtr, (UINTN) VmPtr->Gpr[0], (UINT64) (UINTN) (VmPtr->Ip + Size));\r
53c71d09 116\r
117 VmPtr->Ip = (VMIP) (UINTN) TargetEbcAddr;\r
118 } else {\r
119 //\r
120 // The callee is not a thunk to EBC, call native code.\r
121 //\r
122 EbcLLCALLEXNative (FuncAddr, NewStackPointer, FramePtr);\r
fb0b259e 123\r
53c71d09 124 //\r
125 // Get return value and advance the IP.\r
126 //\r
1ccdbf2a 127 VmPtr->Gpr[7] = EbcLLGetReturnValue ();\r
53c71d09 128 VmPtr->Ip += Size;\r
129 }\r
130}\r
131\r
fb0b259e 132\r
133/**\r
134 Begin executing an EBC image. The address of the entry point is passed\r
135 in via a processor register, so we'll need to make a call to get the\r
136 value.\r
137\r
8e3bc754 138 This is a thunk function. Microsoft x64 compiler only provide fast_call\r
139 calling convention, so the first four arguments are passed by rcx, rdx,\r
140 r8, and r9, while other arguments are passed in stack.\r
141\r
142 @param Arg1 The 1st argument.\r
143 @param Arg2 The 2nd argument.\r
144 @param Arg3 The 3rd argument.\r
145 @param Arg4 The 4th argument.\r
146 @param Arg5 The 5th argument.\r
147 @param Arg6 The 6th argument.\r
148 @param Arg7 The 7th argument.\r
149 @param Arg8 The 8th argument.\r
150 @param Arg9 The 9th argument.\r
151 @param Arg10 The 10th argument.\r
152 @param Arg11 The 11th argument.\r
153 @param Arg12 The 12th argument.\r
154 @param Arg13 The 13th argument.\r
155 @param Arg14 The 14th argument.\r
156 @param Arg15 The 15th argument.\r
157 @param Arg16 The 16th argument.\r
fb0b259e 158\r
159 @return The value returned by the EBC application we're going to run.\r
160\r
161**/\r
53c71d09 162UINT64\r
163EbcInterpret (\r
164 IN OUT UINTN Arg1,\r
165 IN OUT UINTN Arg2,\r
166 IN OUT UINTN Arg3,\r
167 IN OUT UINTN Arg4,\r
168 IN OUT UINTN Arg5,\r
169 IN OUT UINTN Arg6,\r
170 IN OUT UINTN Arg7,\r
171 IN OUT UINTN Arg8,\r
172 IN OUT UINTN Arg9,\r
173 IN OUT UINTN Arg10,\r
174 IN OUT UINTN Arg11,\r
175 IN OUT UINTN Arg12,\r
176 IN OUT UINTN Arg13,\r
177 IN OUT UINTN Arg14,\r
178 IN OUT UINTN Arg15,\r
179 IN OUT UINTN Arg16\r
180 )\r
53c71d09 181{\r
182 //\r
183 // Create a new VM context on the stack\r
184 //\r
185 VM_CONTEXT VmContext;\r
186 UINTN Addr;\r
187 EFI_STATUS Status;\r
188 UINTN StackIndex;\r
189\r
190 //\r
191 // Get the EBC entry point from the processor register.\r
192 //\r
193 Addr = EbcLLGetEbcEntryPoint ();\r
194\r
195 //\r
196 // Now clear out our context\r
197 //\r
198 ZeroMem ((VOID *) &VmContext, sizeof (VM_CONTEXT));\r
199\r
200 //\r
201 // Set the VM instruction pointer to the correct location in memory.\r
202 //\r
203 VmContext.Ip = (VMIP) Addr;\r
204 //\r
205 // Initialize the stack pointer for the EBC. Get the current system stack\r
206 // pointer and adjust it down by the max needed for the interpreter.\r
207 //\r
208\r
209 //\r
210 // Align the stack on a natural boundary\r
211 //\r
212\r
213 //\r
214 // Allocate stack pool\r
215 //\r
216 Status = GetEBCStack((EFI_HANDLE)-1, &VmContext.StackPool, &StackIndex);\r
217 if (EFI_ERROR(Status)) {\r
218 return Status;\r
219 }\r
220 VmContext.StackTop = (UINT8*)VmContext.StackPool + (STACK_REMAIN_SIZE);\r
1ccdbf2a 221 VmContext.Gpr[0] = (UINT64)(UINTN) ((UINT8*)VmContext.StackPool + STACK_POOL_SIZE);\r
222 VmContext.HighStackBottom = (UINTN)VmContext.Gpr[0];\r
223 VmContext.Gpr[0] &= ~(sizeof (UINTN) - 1);\r
224 VmContext.Gpr[0] -= sizeof (UINTN);\r
53c71d09 225\r
226 //\r
227 // Put a magic value in the stack gap, then adjust down again\r
228 //\r
1ccdbf2a 229 *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) VM_STACK_KEY_VALUE;\r
230 VmContext.StackMagicPtr = (UINTN *) (UINTN) VmContext.Gpr[0];\r
231 VmContext.LowStackTop = (UINTN) VmContext.Gpr[0];\r
53c71d09 232\r
233 //\r
234 // For IA32, this is where we say our return address is\r
235 //\r
1ccdbf2a 236 VmContext.Gpr[0] -= sizeof (UINTN);\r
237 *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg16;\r
238 VmContext.Gpr[0] -= sizeof (UINTN);\r
239 *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg15;\r
240 VmContext.Gpr[0] -= sizeof (UINTN);\r
241 *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg14;\r
242 VmContext.Gpr[0] -= sizeof (UINTN);\r
243 *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg13;\r
244 VmContext.Gpr[0] -= sizeof (UINTN);\r
245 *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg12;\r
246 VmContext.Gpr[0] -= sizeof (UINTN);\r
247 *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg11;\r
248 VmContext.Gpr[0] -= sizeof (UINTN);\r
249 *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg10;\r
250 VmContext.Gpr[0] -= sizeof (UINTN);\r
251 *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg9;\r
252 VmContext.Gpr[0] -= sizeof (UINTN);\r
253 *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg8;\r
254 VmContext.Gpr[0] -= sizeof (UINTN);\r
255 *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg7;\r
256 VmContext.Gpr[0] -= sizeof (UINTN);\r
257 *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg6;\r
258 VmContext.Gpr[0] -= sizeof (UINTN);\r
259 *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg5;\r
260 VmContext.Gpr[0] -= sizeof (UINTN);\r
261 *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg4;\r
262 VmContext.Gpr[0] -= sizeof (UINTN);\r
263 *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg3;\r
264 VmContext.Gpr[0] -= sizeof (UINTN);\r
265 *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg2;\r
266 VmContext.Gpr[0] -= sizeof (UINTN);\r
267 *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg1;\r
268 VmContext.Gpr[0] -= 16;\r
269 VmContext.StackRetAddr = (UINT64) VmContext.Gpr[0];\r
53c71d09 270\r
271 //\r
272 // We need to keep track of where the EBC stack starts. This way, if the EBC\r
273 // accesses any stack variables above its initial stack setting, then we know\r
274 // it's accessing variables passed into it, which means the data is on the\r
275 // VM's stack.\r
276 // When we're called, on the stack (high to low) we have the parameters, the\r
277 // return address, then the saved ebp. Save the pointer to the return address.\r
278 // EBC code knows that's there, so should look above it for function parameters.\r
279 // The offset is the size of locals (VMContext + Addr + saved ebp).\r
280 // Note that the interpreter assumes there is a 16 bytes of return address on\r
281 // the stack too, so adjust accordingly.\r
282 // VmContext.HighStackBottom = (UINTN)(Addr + sizeof (VmContext) + sizeof (Addr));\r
283 //\r
284\r
285 //\r
286 // Begin executing the EBC code\r
287 //\r
288 EbcExecute (&VmContext);\r
289\r
290 //\r
291 // Return the value in R[7] unless there was an error\r
292 //\r
293 ReturnEBCStack(StackIndex);\r
1ccdbf2a 294 return (UINT64) VmContext.Gpr[7];\r
53c71d09 295}\r
296\r
53c71d09 297\r
fb0b259e 298/**\r
53c71d09 299 Begin executing an EBC image. The address of the entry point is passed\r
300 in via a processor register, so we'll need to make a call to get the\r
301 value.\r
53c71d09 302\r
8e3bc754 303 @param ImageHandle image handle for the EBC application we're executing\r
304 @param SystemTable standard system table passed into an driver's entry\r
305 point\r
53c71d09 306\r
fb0b259e 307 @return The value returned by the EBC application we're going to run.\r
53c71d09 308\r
fb0b259e 309**/\r
fb0b259e 310UINT64\r
311ExecuteEbcImageEntryPoint (\r
312 IN EFI_HANDLE ImageHandle,\r
313 IN EFI_SYSTEM_TABLE *SystemTable\r
314 )\r
53c71d09 315{\r
316 //\r
317 // Create a new VM context on the stack\r
318 //\r
319 VM_CONTEXT VmContext;\r
320 UINTN Addr;\r
321 EFI_STATUS Status;\r
322 UINTN StackIndex;\r
323\r
324 //\r
325 // Get the EBC entry point from the processor register. Make sure you don't\r
326 // call any functions before this or you could mess up the register the\r
327 // entry point is passed in.\r
328 //\r
329 Addr = EbcLLGetEbcEntryPoint ();\r
330\r
331 //\r
332 // Print(L"*** Thunked into EBC entry point - ImageHandle = 0x%X\n", (UINTN)ImageHandle);\r
333 // Print(L"EBC entry point is 0x%X\n", (UINT32)(UINTN)Addr);\r
334 //\r
335 // Now clear out our context\r
336 //\r
337 ZeroMem ((VOID *) &VmContext, sizeof (VM_CONTEXT));\r
338\r
339 //\r
340 // Save the image handle so we can track the thunks created for this image\r
341 //\r
342 VmContext.ImageHandle = ImageHandle;\r
343 VmContext.SystemTable = SystemTable;\r
344\r
345 //\r
346 // Set the VM instruction pointer to the correct location in memory.\r
347 //\r
348 VmContext.Ip = (VMIP) Addr;\r
349\r
350 //\r
351 // Initialize the stack pointer for the EBC. Get the current system stack\r
352 // pointer and adjust it down by the max needed for the interpreter.\r
353 //\r
354\r
355 //\r
356 // Allocate stack pool\r
357 //\r
358 Status = GetEBCStack(ImageHandle, &VmContext.StackPool, &StackIndex);\r
359 if (EFI_ERROR(Status)) {\r
360 return Status;\r
361 }\r
362 VmContext.StackTop = (UINT8*)VmContext.StackPool + (STACK_REMAIN_SIZE);\r
1ccdbf2a 363 VmContext.Gpr[0] = (UINT64)(UINTN) ((UINT8*)VmContext.StackPool + STACK_POOL_SIZE);\r
364 VmContext.HighStackBottom = (UINTN)VmContext.Gpr[0];\r
365 VmContext.Gpr[0] -= sizeof (UINTN);\r
fb0b259e 366\r
53c71d09 367 //\r
368 // Put a magic value in the stack gap, then adjust down again\r
369 //\r
1ccdbf2a 370 *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) VM_STACK_KEY_VALUE;\r
371 VmContext.StackMagicPtr = (UINTN *) (UINTN) VmContext.Gpr[0];\r
53c71d09 372\r
373 //\r
374 // Align the stack on a natural boundary\r
1ccdbf2a 375 // VmContext.Gpr[0] &= ~(sizeof(UINTN) - 1);\r
53c71d09 376 //\r
1ccdbf2a 377 VmContext.LowStackTop = (UINTN) VmContext.Gpr[0];\r
378 VmContext.Gpr[0] -= sizeof (UINTN);\r
379 *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) SystemTable;\r
380 VmContext.Gpr[0] -= sizeof (UINTN);\r
381 *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) ImageHandle;\r
53c71d09 382\r
1ccdbf2a 383 VmContext.Gpr[0] -= 16;\r
384 VmContext.StackRetAddr = (UINT64) VmContext.Gpr[0];\r
53c71d09 385 //\r
386 // VM pushes 16-bytes for return address. Simulate that here.\r
387 //\r
388\r
389 //\r
390 // Begin executing the EBC code\r
391 //\r
392 EbcExecute (&VmContext);\r
393\r
394 //\r
395 // Return the value in R[7] unless there was an error\r
396 //\r
1ccdbf2a 397 return (UINT64) VmContext.Gpr[7];\r
53c71d09 398}\r
399\r
fb0b259e 400\r
401/**\r
8e3bc754 402 Create thunks for an EBC image entry point, or an EBC protocol service.\r
fb0b259e 403\r
8e3bc754 404 @param ImageHandle Image handle for the EBC image. If not null, then\r
405 we're creating a thunk for an image entry point.\r
406 @param EbcEntryPoint Address of the EBC code that the thunk is to call\r
407 @param Thunk Returned thunk we create here\r
408 @param Flags Flags indicating options for creating the thunk\r
fb0b259e 409\r
8e3bc754 410 @retval EFI_SUCCESS The thunk was created successfully.\r
411 @retval EFI_INVALID_PARAMETER The parameter of EbcEntryPoint is not 16-bit\r
412 aligned.\r
413 @retval EFI_OUT_OF_RESOURCES There is not enough memory to created the EBC\r
414 Thunk.\r
415 @retval EFI_BUFFER_TOO_SMALL EBC_THUNK_SIZE is not larger enough.\r
fb0b259e 416\r
417**/\r
53c71d09 418EFI_STATUS\r
419EbcCreateThunks (\r
420 IN EFI_HANDLE ImageHandle,\r
421 IN VOID *EbcEntryPoint,\r
422 OUT VOID **Thunk,\r
423 IN UINT32 Flags\r
424 )\r
53c71d09 425{\r
426 UINT8 *Ptr;\r
427 UINT8 *ThunkBase;\r
8e3bc754 428 UINT32 Index;\r
53c71d09 429 UINT32 Addr;\r
430 INT32 Size;\r
431 INT32 ThunkSize;\r
432\r
433 //\r
434 // Check alignment of pointer to EBC code\r
435 //\r
436 if ((UINT32) (UINTN) EbcEntryPoint & 0x01) {\r
437 return EFI_INVALID_PARAMETER;\r
438 }\r
439\r
440 Size = EBC_THUNK_SIZE;\r
441 ThunkSize = Size;\r
442\r
443 Ptr = AllocatePool (Size);\r
444\r
445 if (Ptr == NULL) {\r
446 return EFI_OUT_OF_RESOURCES;\r
447 }\r
448 //\r
449 // Print(L"Allocate TH: 0x%X\n", (UINT32)Ptr);\r
450 //\r
451 // Save the start address so we can add a pointer to it to a list later.\r
452 //\r
453 ThunkBase = Ptr;\r
454\r
455 //\r
456 // Give them the address of our buffer we're going to fix up\r
457 //\r
458 *Thunk = (VOID *) Ptr;\r
459\r
460 //\r
461 // Add a magic code here to help the VM recognize the thunk..\r
462 // mov eax, 0xca112ebc => B8 BC 2E 11 CA\r
463 //\r
464 *Ptr = 0xB8;\r
465 Ptr++;\r
466 Size--;\r
467 Addr = (UINT32) 0xCA112EBC;\r
8e3bc754 468 for (Index = 0; Index < sizeof (Addr); Index++) {\r
53c71d09 469 *Ptr = (UINT8) (UINTN) Addr;\r
470 Addr >>= 8;\r
471 Ptr++;\r
472 Size--;\r
473 }\r
474\r
475 //\r
476 // Add code bytes to load up a processor register with the EBC entry point.\r
477 // mov eax, 0xaa55aa55 => B8 55 AA 55 AA\r
478 // The first 8 bytes of the thunk entry is the address of the EBC\r
479 // entry point.\r
480 //\r
481 *Ptr = 0xB8;\r
482 Ptr++;\r
483 Size--;\r
484 Addr = (UINT32) EbcEntryPoint;\r
8e3bc754 485 for (Index = 0; Index < sizeof (Addr); Index++) {\r
53c71d09 486 *Ptr = (UINT8) (UINTN) Addr;\r
487 Addr >>= 8;\r
488 Ptr++;\r
489 Size--;\r
490 }\r
491 //\r
492 // Stick in a load of ecx with the address of appropriate VM function.\r
493 // mov ecx 12345678h => 0xB9 0x78 0x56 0x34 0x12\r
494 //\r
366219ab 495 if ((Flags & FLAG_THUNK_ENTRY_POINT) != 0) {\r
53c71d09 496 Addr = (UINT32) (UINTN) ExecuteEbcImageEntryPoint;\r
497 } else {\r
498 Addr = (UINT32) (UINTN) EbcInterpret;\r
499 }\r
500\r
501 //\r
502 // MOV ecx\r
503 //\r
504 *Ptr = 0xB9;\r
505 Ptr++;\r
506 Size--;\r
8e3bc754 507 for (Index = 0; Index < sizeof (Addr); Index++) {\r
53c71d09 508 *Ptr = (UINT8) Addr;\r
509 Addr >>= 8;\r
510 Ptr++;\r
511 Size--;\r
512 }\r
513 //\r
514 // Stick in jump opcode bytes for jmp ecx => 0xFF 0xE1\r
515 //\r
516 *Ptr = 0xFF;\r
517 Ptr++;\r
518 Size--;\r
519 *Ptr = 0xE1;\r
520 Size--;\r
521\r
522 //\r
523 // Double check that our defined size is ok (application error)\r
524 //\r
525 if (Size < 0) {\r
526 ASSERT (FALSE);\r
527 return EFI_BUFFER_TOO_SMALL;\r
528 }\r
529 //\r
530 // Add the thunk to the list for this image. Do this last since the add\r
531 // function flushes the cache for us.\r
532 //\r
533 EbcAddImageThunk (ImageHandle, (VOID *) ThunkBase, ThunkSize);\r
534\r
535 return EFI_SUCCESS;\r
536}\r