]> git.proxmox.com Git - mirror_edk2.git/blame - Nt32Pkg/Sec/SecMain.c
MdePkg/UefiBaseType.h: treat EBC as a non-native machine type
[mirror_edk2.git] / Nt32Pkg / Sec / SecMain.c
CommitLineData
6ae81428 1/**@file\r
2e19fd0f 2\r
16b6347b 3Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
4e502412 4(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
9d2eedba 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
2e19fd0f 6\r
7Module Name:\r
8\r
9 SecMain.c\r
10\r
11Abstract:\r
12 WinNt emulator of SEC phase. It's really a Win32 application, but this is\r
13 Ok since all the other modules for NT32 are NOT Win32 applications.\r
14\r
952261d5
LG
15 This program gets NT32 PCD setting and figures out what the memory layout \r
16 will be, how may FD's will be loaded and also what the boot mode is.\r
2e19fd0f 17\r
18 The SEC registers a set of services with the SEC core. gPrivateDispatchTable\r
8aa9d680 19 is a list of PPI's produced by the SEC that are available for usage in PEI.\r
2e19fd0f 20\r
952261d5
LG
21 This code produces 128 K of temporary memory for the PEI stack by directly\r
22 allocate memory space with ReadWrite and Execute attribute.\r
2e19fd0f 23\r
6ae81428 24**/\r
2e19fd0f 25\r
26#include "SecMain.h"\r
d0dc913e 27\r
24e12917
RN
28#ifndef SE_TIME_ZONE_NAME\r
29#define SE_TIME_ZONE_NAME TEXT("SeTimeZonePrivilege")\r
30#endif\r
2e19fd0f 31\r
32NT_PEI_LOAD_FILE_PPI mSecNtLoadFilePpi = { SecWinNtPeiLoadFile };\r
33\r
34PEI_NT_AUTOSCAN_PPI mSecNtAutoScanPpi = { SecWinNtPeiAutoScan };\r
35\r
36PEI_NT_THUNK_PPI mSecWinNtThunkPpi = { SecWinNtWinNtThunkAddress };\r
37\r
38EFI_PEI_PROGRESS_CODE_PPI mSecStatusCodePpi = { SecPeiReportStatusCode };\r
39\r
40NT_FWH_PPI mSecFwhInformationPpi = { SecWinNtFdAddress };\r
41\r
d0a3ead2 42EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mSecTemporaryRamSupportPpi = {SecTemporaryRamSupport};\r
2e19fd0f 43\r
44EFI_PEI_PPI_DESCRIPTOR gPrivateDispatchTable[] = {\r
2e19fd0f 45 {\r
46 EFI_PEI_PPI_DESCRIPTOR_PPI,\r
47 &gNtPeiLoadFilePpiGuid,\r
48 &mSecNtLoadFilePpi\r
49 },\r
50 {\r
51 EFI_PEI_PPI_DESCRIPTOR_PPI,\r
52 &gPeiNtAutoScanPpiGuid,\r
53 &mSecNtAutoScanPpi\r
54 },\r
55 {\r
56 EFI_PEI_PPI_DESCRIPTOR_PPI,\r
57 &gPeiNtThunkPpiGuid,\r
58 &mSecWinNtThunkPpi\r
59 },\r
60 {\r
61 EFI_PEI_PPI_DESCRIPTOR_PPI,\r
62 &gEfiPeiStatusCodePpiGuid,\r
63 &mSecStatusCodePpi\r
64 },\r
58dcdada 65 {\r
66 EFI_PEI_PPI_DESCRIPTOR_PPI,\r
67 &gEfiTemporaryRamSupportPpiGuid,\r
68 &mSecTemporaryRamSupportPpi\r
69 },\r
2e19fd0f 70 {\r
71 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
72 &gNtFwhPpiGuid,\r
73 &mSecFwhInformationPpi\r
74 }\r
75};\r
76\r
77\r
78//\r
79// Default information about where the FD is located.\r
952261d5 80// This array gets filled in with information from PcdWinNtFirmwareVolume\r
2e19fd0f 81// The number of array elements is allocated base on parsing\r
952261d5 82// PcdWinNtFirmwareVolume and the memory is never freed.\r
2e19fd0f 83//\r
84UINTN gFdInfoCount = 0;\r
85NT_FD_INFO *gFdInfo;\r
86\r
87//\r
88// Array that supports seperate memory rantes.\r
952261d5 89// The memory ranges are set by PcdWinNtMemorySizeForSecMain.\r
2e19fd0f 90// The number of array elements is allocated base on parsing\r
952261d5 91// PcdWinNtMemorySizeForSecMain value and the memory is never freed.\r
2e19fd0f 92//\r
93UINTN gSystemMemoryCount = 0;\r
94NT_SYSTEM_MEMORY *gSystemMemory;\r
95\r
58dcdada 96VOID\r
97EFIAPI\r
98SecSwitchStack (\r
99 UINT32 TemporaryMemoryBase,\r
100 UINT32 PermenentMemoryBase\r
101 );\r
ffdd18bb 102EFI_STATUS\r
103SecNt32PeCoffRelocateImage (\r
104 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
105 );\r
1f53f7bb 106\r
f66a43b2
JM
107VOID\r
108EFIAPI\r
109PeiSwitchStacks (\r
110 IN SWITCH_STACK_ENTRY_POINT EntryPoint,\r
111 IN VOID *Context1, OPTIONAL\r
112 IN VOID *Context2, OPTIONAL\r
113 IN VOID *Context3, OPTIONAL\r
114 IN VOID *NewStack\r
115 );\r
116\r
1f53f7bb 117VOID\r
118SecPrint (\r
119 CHAR8 *Format,\r
120 ...\r
121 )\r
122{\r
123 va_list Marker;\r
124 UINTN CharCount;\r
125 CHAR8 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE];\r
126\r
127 va_start (Marker, Format);\r
128 \r
1f53f7bb 129 _vsnprintf (Buffer, sizeof (Buffer), Format, Marker);\r
130\r
3bbe68a3 131 va_end (Marker);\r
132\r
1f53f7bb 133 CharCount = strlen (Buffer);\r
134 WriteFile (\r
135 GetStdHandle (STD_OUTPUT_HANDLE), \r
136 Buffer,\r
f66a43b2 137 (DWORD)CharCount,\r
1f53f7bb 138 (LPDWORD)&CharCount,\r
139 NULL\r
140 );\r
141}\r
142\r
2e19fd0f 143INTN\r
144EFIAPI\r
145main (\r
146 IN INTN Argc,\r
147 IN CHAR8 **Argv,\r
148 IN CHAR8 **Envp\r
149 )\r
150/*++\r
151\r
152Routine Description:\r
153 Main entry point to SEC for WinNt. This is a Windows program\r
154\r
155Arguments:\r
156 Argc - Number of command line arguments\r
157 Argv - Array of command line argument strings\r
8aa9d680 158 Envp - Array of environment variable strings\r
2e19fd0f 159\r
160Returns:\r
161 0 - Normal exit\r
162 1 - Abnormal exit\r
163\r
164--*/\r
165{\r
166 EFI_STATUS Status;\r
24e12917
RN
167 HANDLE Token;\r
168 TOKEN_PRIVILEGES TokenPrivileges;\r
2e19fd0f 169 EFI_PHYSICAL_ADDRESS InitialStackMemory;\r
170 UINT64 InitialStackMemorySize;\r
171 UINTN Index;\r
172 UINTN Index1;\r
173 UINTN Index2;\r
2e19fd0f 174 CHAR16 *FileName;\r
175 CHAR16 *FileNamePtr;\r
176 BOOLEAN Done;\r
177 VOID *PeiCoreFile;\r
178 CHAR16 *MemorySizeStr;\r
179 CHAR16 *FirmwareVolumesStr;\r
85e43be1 180 UINTN *StackPointer;\r
16b6347b
QS
181 UINT32 ProcessAffinityMask;\r
182 UINT32 SystemAffinityMask;\r
183 INT32 LowBit;\r
184\r
706e7534 185\r
24e12917
RN
186 //\r
187 // Enable the privilege so that RTC driver can successfully run SetTime()\r
188 //\r
189 OpenProcessToken (GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &Token);\r
190 if (LookupPrivilegeValue(NULL, SE_TIME_ZONE_NAME, &TokenPrivileges.Privileges[0].Luid)) {\r
191 TokenPrivileges.PrivilegeCount = 1;\r
192 TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;\r
193 AdjustTokenPrivileges(Token, FALSE, &TokenPrivileges, 0, (PTOKEN_PRIVILEGES) NULL, 0);\r
194 }\r
195\r
f7c58a94 196 MemorySizeStr = (CHAR16 *) PcdGetPtr (PcdWinNtMemorySizeForSecMain);\r
197 FirmwareVolumesStr = (CHAR16 *) PcdGetPtr (PcdWinNtFirmwareVolume);\r
2e19fd0f 198\r
1f53f7bb 199 SecPrint ("\nEDK II SEC Main NT Emulation Environment from www.TianoCore.org\n");\r
2e19fd0f 200\r
16b6347b
QS
201 //\r
202 // Determine the first thread available to this process.\r
203 //\r
204 if (GetProcessAffinityMask (GetCurrentProcess (), &ProcessAffinityMask, &SystemAffinityMask)) {\r
205 LowBit = (INT32)LowBitSet32 (ProcessAffinityMask);\r
206 if (LowBit != -1) {\r
207 //\r
208 // Force the system to bind the process to a single thread to work\r
209 // around odd semaphore type crashes.\r
210 //\r
211 SetProcessAffinityMask (GetCurrentProcess (), (INTN)(BIT0 << LowBit));\r
212 }\r
213 }\r
214\r
2e19fd0f 215 //\r
216 // Make some Windows calls to Set the process to the highest priority in the\r
217 // idle class. We need this to have good performance.\r
218 //\r
219 SetPriorityClass (GetCurrentProcess (), IDLE_PRIORITY_CLASS);\r
220 SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);\r
221\r
222 //\r
223 // Allocate space for gSystemMemory Array\r
224 //\r
8aa9d680 225 gSystemMemoryCount = CountSeparatorsInString (MemorySizeStr, '!') + 1;\r
2e19fd0f 226 gSystemMemory = calloc (gSystemMemoryCount, sizeof (NT_SYSTEM_MEMORY));\r
227 if (gSystemMemory == NULL) {\r
1f53f7bb 228 SecPrint ("ERROR : Can not allocate memory for %S. Exiting.\n", MemorySizeStr);\r
2e19fd0f 229 exit (1);\r
230 }\r
231 //\r
232 // Allocate space for gSystemMemory Array\r
233 //\r
8aa9d680 234 gFdInfoCount = CountSeparatorsInString (FirmwareVolumesStr, '!') + 1;\r
2e19fd0f 235 gFdInfo = calloc (gFdInfoCount, sizeof (NT_FD_INFO));\r
236 if (gFdInfo == NULL) {\r
1f53f7bb 237 SecPrint ("ERROR : Can not allocate memory for %S. Exiting.\n", FirmwareVolumesStr);\r
2e19fd0f 238 exit (1);\r
239 }\r
240 //\r
241 // Setup Boot Mode. If BootModeStr == "" then BootMode = 0 (BOOT_WITH_FULL_CONFIGURATION)\r
242 //\r
f7c58a94 243 SecPrint (" BootMode 0x%02x\n", PcdGet32 (PcdWinNtBootMode));\r
2e19fd0f 244\r
245 //\r
952261d5 246 // Allocate 128K memory to emulate temp memory for PEI.\r
2e19fd0f 247 // on a real platform this would be SRAM, or using the cache as RAM.\r
248 // Set InitialStackMemory to zero so WinNtOpenFile will allocate a new mapping\r
249 //\r
952261d5
LG
250 InitialStackMemorySize = STACK_SIZE;\r
251 InitialStackMemory = (EFI_PHYSICAL_ADDRESS) (UINTN) VirtualAlloc (NULL, (SIZE_T) (InitialStackMemorySize), MEM_COMMIT, PAGE_EXECUTE_READWRITE);\r
252 if (InitialStackMemory == 0) {\r
1f53f7bb 253 SecPrint ("ERROR : Can not allocate enough space for SecStack\n");\r
2e19fd0f 254 exit (1);\r
255 }\r
256\r
85e43be1 257 for (StackPointer = (UINTN*) (UINTN) InitialStackMemory;\r
258 StackPointer < (UINTN*) ((UINTN)InitialStackMemory + (SIZE_T) InitialStackMemorySize);\r
259 StackPointer ++) {\r
5cf45973 260 *StackPointer = PcdGet32 (PcdInitValueInTempStack);\r
85e43be1 261 }\r
262 \r
1f53f7bb 263 SecPrint (" SEC passing in %d bytes of temp RAM to PEI\n", InitialStackMemorySize);\r
2e19fd0f 264\r
265 //\r
266 // Open All the firmware volumes and remember the info in the gFdInfo global\r
267 //\r
268 FileNamePtr = (CHAR16 *)malloc (StrLen ((CHAR16 *)FirmwareVolumesStr) * sizeof(CHAR16));\r
269 if (FileNamePtr == NULL) {\r
1f53f7bb 270 SecPrint ("ERROR : Can not allocate memory for firmware volume string\n");\r
2e19fd0f 271 exit (1);\r
272 }\r
273\r
274 StrCpy (FileNamePtr, (CHAR16*)FirmwareVolumesStr);\r
275\r
0b94e319 276 for (Done = FALSE, Index = 0, PeiCoreFile = NULL; !Done; Index++) {\r
2e19fd0f 277 FileName = FileNamePtr;\r
278 for (Index1 = 0; (FileNamePtr[Index1] != '!') && (FileNamePtr[Index1] != 0); Index1++)\r
279 ;\r
280 if (FileNamePtr[Index1] == 0) {\r
281 Done = TRUE;\r
282 } else {\r
283 FileNamePtr[Index1] = '\0';\r
284 FileNamePtr = FileNamePtr + Index1 + 1;\r
285 }\r
286\r
287 //\r
8aa9d680 288 // Open the FD and remember where it got mapped into our processes address space\r
2e19fd0f 289 //\r
290 Status = WinNtOpenFile (\r
291 FileName,\r
292 0,\r
293 OPEN_EXISTING,\r
294 &gFdInfo[Index].Address,\r
295 &gFdInfo[Index].Size\r
296 );\r
297 if (EFI_ERROR (Status)) {\r
1f53f7bb 298 SecPrint ("ERROR : Can not open Firmware Device File %S (0x%X). Exiting.\n", FileName, Status);\r
2e19fd0f 299 exit (1);\r
300 }\r
301\r
1f53f7bb 302 SecPrint (" FD loaded from");\r
2e19fd0f 303 //\r
8aa9d680 304 // printf can't print filenames directly as the \ gets interpreted as an\r
2e19fd0f 305 // escape character.\r
306 //\r
307 for (Index2 = 0; FileName[Index2] != '\0'; Index2++) {\r
1f53f7bb 308 SecPrint ("%c", FileName[Index2]);\r
2e19fd0f 309 }\r
310\r
311 if (PeiCoreFile == NULL) {\r
312 //\r
313 // Assume the beginning of the FD is an FV and look for the PEI Core.\r
314 // Load the first one we find.\r
315 //\r
316 Status = SecFfsFindPeiCore ((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) gFdInfo[Index].Address, &PeiCoreFile);\r
317 if (!EFI_ERROR (Status)) {\r
1f53f7bb 318 SecPrint (" contains SEC Core");\r
2e19fd0f 319 }\r
320 }\r
321\r
1f53f7bb 322 SecPrint ("\n");\r
2e19fd0f 323 }\r
324 //\r
325 // Calculate memory regions and store the information in the gSystemMemory\r
326 // global for later use. The autosizing code will use this data to\r
327 // map this memory into the SEC process memory space.\r
328 //\r
329 for (Index = 0, Done = FALSE; !Done; Index++) {\r
330 //\r
331 // Save the size of the memory and make a Unicode filename SystemMemory00, ...\r
332 //\r
333 gSystemMemory[Index].Size = _wtoi (MemorySizeStr) * 0x100000;\r
2e19fd0f 334\r
335 //\r
336 // Find the next region\r
337 //\r
338 for (Index1 = 0; MemorySizeStr[Index1] != '!' && MemorySizeStr[Index1] != 0; Index1++)\r
339 ;\r
340 if (MemorySizeStr[Index1] == 0) {\r
341 Done = TRUE;\r
342 }\r
343\r
344 MemorySizeStr = MemorySizeStr + Index1 + 1;\r
345 }\r
346\r
1f53f7bb 347 SecPrint ("\n");\r
2e19fd0f 348\r
349 //\r
350 // Hand off to PEI Core\r
351 //\r
352 SecLoadFromCore ((UINTN) InitialStackMemory, (UINTN) InitialStackMemorySize, (UINTN) gFdInfo[0].Address, PeiCoreFile);\r
353\r
354 //\r
355 // If we get here, then the PEI Core returned. This is an error as PEI should\r
356 // always hand off to DXE.\r
357 //\r
1f53f7bb 358 SecPrint ("ERROR : PEI Core returned\n");\r
2e19fd0f 359 exit (1);\r
360}\r
361\r
362EFI_STATUS\r
363WinNtOpenFile (\r
364 IN CHAR16 *FileName,\r
365 IN UINT32 MapSize,\r
366 IN DWORD CreationDisposition,\r
367 IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,\r
368 OUT UINT64 *Length\r
369 )\r
370/*++\r
371\r
372Routine Description:\r
373 Opens and memory maps a file using WinNt services. If BaseAddress is non zero\r
374 the process will try and allocate the memory starting at BaseAddress.\r
375\r
376Arguments:\r
377 FileName - The name of the file to open and map\r
378 MapSize - The amount of the file to map in bytes\r
379 CreationDisposition - The flags to pass to CreateFile(). Use to create new files for\r
380 memory emulation, and exiting files for firmware volume emulation\r
381 BaseAddress - The base address of the mapped file in the user address space.\r
8aa9d680 382 If passed in as NULL the new memory region is used.\r
2e19fd0f 383 If passed in as non NULL the request memory region is used for\r
384 the mapping of the file into the process space.\r
385 Length - The size of the mapped region in bytes\r
386\r
387Returns:\r
388 EFI_SUCCESS - The file was opened and mapped.\r
389 EFI_NOT_FOUND - FileName was not found in the current directory\r
390 EFI_DEVICE_ERROR - An error occured attempting to map the opened file\r
391\r
392--*/\r
393{\r
394 HANDLE NtFileHandle;\r
395 HANDLE NtMapHandle;\r
396 VOID *VirtualAddress;\r
397 UINTN FileSize;\r
398\r
399 //\r
400 // Use Win API to open/create a file\r
401 //\r
402 NtFileHandle = CreateFile (\r
403 FileName,\r
75e55c54 404 GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE,\r
2e19fd0f 405 FILE_SHARE_READ,\r
406 NULL,\r
407 CreationDisposition,\r
408 FILE_ATTRIBUTE_NORMAL,\r
409 NULL\r
410 );\r
411 if (NtFileHandle == INVALID_HANDLE_VALUE) {\r
412 return EFI_NOT_FOUND;\r
413 }\r
414 //\r
415 // Map the open file into a memory range\r
416 //\r
417 NtMapHandle = CreateFileMapping (\r
418 NtFileHandle,\r
419 NULL,\r
75e55c54 420 PAGE_EXECUTE_READWRITE,\r
2e19fd0f 421 0,\r
422 MapSize,\r
423 NULL\r
424 );\r
425 if (NtMapHandle == NULL) {\r
426 return EFI_DEVICE_ERROR;\r
427 }\r
428 //\r
429 // Get the virtual address (address in the emulator) of the mapped file\r
430 //\r
431 VirtualAddress = MapViewOfFileEx (\r
432 NtMapHandle,\r
75e55c54 433 FILE_MAP_EXECUTE | FILE_MAP_ALL_ACCESS,\r
2e19fd0f 434 0,\r
435 0,\r
436 MapSize,\r
437 (LPVOID) (UINTN) *BaseAddress\r
438 );\r
439 if (VirtualAddress == NULL) {\r
440 return EFI_DEVICE_ERROR;\r
441 }\r
442\r
443 if (MapSize == 0) {\r
444 //\r
445 // Seek to the end of the file to figure out the true file size.\r
446 //\r
447 FileSize = SetFilePointer (\r
448 NtFileHandle,\r
449 0,\r
450 NULL,\r
451 FILE_END\r
452 );\r
453 if (FileSize == -1) {\r
454 return EFI_DEVICE_ERROR;\r
455 }\r
456\r
457 *Length = (UINT64) FileSize;\r
458 } else {\r
459 *Length = (UINT64) MapSize;\r
460 }\r
461\r
462 *BaseAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) VirtualAddress;\r
463\r
464 return EFI_SUCCESS;\r
465}\r
466\r
2e19fd0f 467\r
d0dc913e 468#define BYTES_PER_RECORD 512\r
2e19fd0f 469\r
470EFI_STATUS\r
471EFIAPI\r
472SecPeiReportStatusCode (\r
e1001af1 473 IN CONST EFI_PEI_SERVICES **PeiServices,\r
2e19fd0f 474 IN EFI_STATUS_CODE_TYPE CodeType,\r
475 IN EFI_STATUS_CODE_VALUE Value,\r
476 IN UINT32 Instance,\r
e1001af1 477 IN CONST EFI_GUID *CallerId,\r
478 IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL\r
2e19fd0f 479 )\r
480/*++\r
481\r
482Routine Description:\r
483\r
484 This routine produces the ReportStatusCode PEI service. It's passed\r
485 up to the PEI Core via a PPI. T\r
486\r
487 This code currently uses the NT clib printf. This does not work the same way\r
488 as the EFI Print (), as %t, %g, %s as Unicode are not supported.\r
489\r
490Arguments:\r
491 (see EFI_PEI_REPORT_STATUS_CODE)\r
492\r
493Returns:\r
494 EFI_SUCCESS - Always return success\r
495\r
496--*/\r
497// TODO: PeiServices - add argument and description to function comment\r
498// TODO: CodeType - add argument and description to function comment\r
499// TODO: Value - add argument and description to function comment\r
500// TODO: Instance - add argument and description to function comment\r
501// TODO: CallerId - add argument and description to function comment\r
502// TODO: Data - add argument and description to function comment\r
503{\r
504 CHAR8 *Format;\r
a776476a 505 BASE_LIST Marker;\r
2e19fd0f 506 CHAR8 PrintBuffer[BYTES_PER_RECORD * 2];\r
507 CHAR8 *Filename;\r
508 CHAR8 *Description;\r
509 UINT32 LineNumber;\r
d0dc913e 510 UINT32 ErrorLevel;\r
2e19fd0f 511\r
d0dc913e
A
512\r
513 if (Data == NULL) {\r
514 } else if (ReportStatusCodeExtractAssertInfo (CodeType, Value, Data, &Filename, &Description, &LineNumber)) {\r
2e19fd0f 515 //\r
d0dc913e 516 // Processes ASSERT ()\r
2e19fd0f 517 //\r
1f53f7bb 518 SecPrint ("ASSERT %s(%d): %s\n", Filename, (int)LineNumber, Description);\r
2e19fd0f 519\r
d0dc913e
A
520 } else if (ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) {\r
521 //\r
522 // Process DEBUG () macro \r
523 //\r
a776476a 524 AsciiBSPrint (PrintBuffer, BYTES_PER_RECORD, Format, Marker);\r
1f53f7bb 525 SecPrint (PrintBuffer);\r
2e19fd0f 526 }\r
527\r
528 return EFI_SUCCESS;\r
529}\r
530\r
f66a43b2 531#if defined (MDE_CPU_IA32)\r
5aae0aa7 532/**\r
533 Transfers control to a function starting with a new stack.\r
534\r
535 Transfers control to the function specified by EntryPoint using the new stack\r
536 specified by NewStack and passing in the parameters specified by Context1 and\r
537 Context2. Context1 and Context2 are optional and may be NULL. The function\r
538 EntryPoint must never return.\r
539\r
540 If EntryPoint is NULL, then ASSERT().\r
541 If NewStack is NULL, then ASSERT().\r
542\r
543 @param EntryPoint A pointer to function to call with the new stack.\r
544 @param Context1 A pointer to the context to pass into the EntryPoint\r
545 function.\r
546 @param Context2 A pointer to the context to pass into the EntryPoint\r
547 function.\r
548 @param NewStack A pointer to the new stack to use for the EntryPoint\r
549 function.\r
550 @param NewBsp A pointer to the new BSP for the EntryPoint on IPF. It's\r
551 Reserved on other architectures.\r
552\r
553**/\r
554VOID\r
555EFIAPI\r
556PeiSwitchStacks (\r
557 IN SWITCH_STACK_ENTRY_POINT EntryPoint,\r
558 IN VOID *Context1, OPTIONAL\r
559 IN VOID *Context2, OPTIONAL\r
560 IN VOID *Context3, OPTIONAL\r
561 IN VOID *NewStack\r
562 )\r
563{\r
564 BASE_LIBRARY_JUMP_BUFFER JumpBuffer;\r
565 \r
566 ASSERT (EntryPoint != NULL);\r
567 ASSERT (NewStack != NULL);\r
568\r
569 //\r
570 // Stack should be aligned with CPU_STACK_ALIGNMENT\r
571 //\r
572 ASSERT (((UINTN)NewStack & (CPU_STACK_ALIGNMENT - 1)) == 0);\r
573\r
574 JumpBuffer.Eip = (UINTN)EntryPoint;\r
575 JumpBuffer.Esp = (UINTN)NewStack - sizeof (VOID*);\r
576 JumpBuffer.Esp -= sizeof (Context1) + sizeof (Context2) + sizeof(Context3);\r
577 ((VOID**)JumpBuffer.Esp)[1] = Context1;\r
578 ((VOID**)JumpBuffer.Esp)[2] = Context2;\r
579 ((VOID**)JumpBuffer.Esp)[3] = Context3;\r
580\r
581 LongJump (&JumpBuffer, (UINTN)-1);\r
582 \r
583\r
584 //\r
585 // InternalSwitchStack () will never return\r
586 //\r
587 ASSERT (FALSE); \r
588}\r
f66a43b2 589#endif\r
2e19fd0f 590\r
591VOID\r
592SecLoadFromCore (\r
593 IN UINTN LargestRegion,\r
594 IN UINTN LargestRegionSize,\r
595 IN UINTN BootFirmwareVolumeBase,\r
596 IN VOID *PeiCorePe32File\r
597 )\r
598/*++\r
599\r
600Routine Description:\r
601 This is the service to load the PEI Core from the Firmware Volume\r
602\r
603Arguments:\r
604 LargestRegion - Memory to use for PEI.\r
605 LargestRegionSize - Size of Memory to use for PEI\r
606 BootFirmwareVolumeBase - Start of the Boot FV\r
607 PeiCorePe32File - PEI Core PE32\r
608\r
609Returns:\r
610 Success means control is transfered and thus we should never return\r
611\r
612--*/\r
613{\r
614 EFI_STATUS Status;\r
2e19fd0f 615 VOID *TopOfStack;\r
616 UINT64 PeiCoreSize;\r
617 EFI_PHYSICAL_ADDRESS PeiCoreEntryPoint;\r
618 EFI_PHYSICAL_ADDRESS PeiImageAddress;\r
5aae0aa7 619 EFI_SEC_PEI_HAND_OFF *SecCoreData;\r
58dcdada 620 UINTN PeiStackSize;\r
2e19fd0f 621\r
622 //\r
623 // Compute Top Of Memory for Stack and PEI Core Allocations\r
624 //\r
58dcdada 625 PeiStackSize = (UINTN)RShiftU64((UINT64)STACK_SIZE,1);\r
2e19fd0f 626\r
627 //\r
58dcdada 628 // |-----------| <---- TemporaryRamBase + TemporaryRamSize\r
629 // | Heap |\r
630 // | |\r
631 // |-----------| <---- StackBase / PeiTemporaryMemoryBase\r
632 // | |\r
633 // | Stack |\r
634 // |-----------| <---- TemporaryRamBase\r
635 // \r
636 TopOfStack = (VOID *)(LargestRegion + PeiStackSize);\r
58dcdada 637\r
2e19fd0f 638 //\r
58dcdada 639 // Reservet space for storing PeiCore's parament in stack.\r
640 // \r
641 TopOfStack = (VOID *)((UINTN)TopOfStack - sizeof (EFI_SEC_PEI_HAND_OFF) - CPU_STACK_ALIGNMENT);\r
2e19fd0f 642 TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);\r
2e19fd0f 643\r
2e19fd0f 644 //\r
645 // Bind this information into the SEC hand-off state\r
646 //\r
5aae0aa7 647 SecCoreData = (EFI_SEC_PEI_HAND_OFF*)(UINTN) TopOfStack;\r
648 SecCoreData->DataSize = sizeof(EFI_SEC_PEI_HAND_OFF);\r
649 SecCoreData->BootFirmwareVolumeBase = (VOID*)BootFirmwareVolumeBase;\r
f7c58a94 650 SecCoreData->BootFirmwareVolumeSize = PcdGet32(PcdWinNtFirmwareFdSize);\r
58dcdada 651 SecCoreData->TemporaryRamBase = (VOID*)(UINTN)LargestRegion; \r
5aae0aa7 652 SecCoreData->TemporaryRamSize = STACK_SIZE;\r
ff33b87d 653 SecCoreData->StackBase = SecCoreData->TemporaryRamBase;\r
58dcdada 654 SecCoreData->StackSize = PeiStackSize;\r
ff33b87d 655 SecCoreData->PeiTemporaryRamBase = (VOID*) ((UINTN) SecCoreData->TemporaryRamBase + PeiStackSize);\r
58dcdada 656 SecCoreData->PeiTemporaryRamSize = STACK_SIZE - PeiStackSize;\r
2e19fd0f 657\r
658 //\r
659 // Load the PEI Core from a Firmware Volume\r
660 //\r
661 Status = SecWinNtPeiLoadFile (\r
662 PeiCorePe32File,\r
663 &PeiImageAddress,\r
664 &PeiCoreSize,\r
665 &PeiCoreEntryPoint\r
666 );\r
667 if (EFI_ERROR (Status)) {\r
668 return ;\r
669 }\r
5aae0aa7 670 \r
2e19fd0f 671 //\r
672 // Transfer control to the PEI Core\r
673 //\r
5aae0aa7 674 PeiSwitchStacks (\r
2e19fd0f 675 (SWITCH_STACK_ENTRY_POINT) (UINTN) PeiCoreEntryPoint,\r
5aae0aa7 676 SecCoreData,\r
677 (VOID *) (UINTN) ((EFI_PEI_PPI_DESCRIPTOR *) &gPrivateDispatchTable),\r
2e19fd0f 678 NULL,\r
679 TopOfStack\r
680 );\r
681 //\r
682 // If we get here, then the PEI Core returned. This is an error\r
683 //\r
684 return ;\r
685}\r
686\r
687EFI_STATUS\r
688EFIAPI\r
689SecWinNtPeiAutoScan (\r
690 IN UINTN Index,\r
691 OUT EFI_PHYSICAL_ADDRESS *MemoryBase,\r
692 OUT UINT64 *MemorySize\r
693 )\r
694/*++\r
695\r
696Routine Description:\r
697 This service is called from Index == 0 until it returns EFI_UNSUPPORTED.\r
8aa9d680 698 It allows discontinuous memory regions to be supported by the emulator.\r
2e19fd0f 699 It uses gSystemMemory[] and gSystemMemoryCount that were created by\r
952261d5
LG
700 parsing PcdWinNtMemorySizeForSecMain value.\r
701 The size comes from the Pcd value and the address comes from the memory space \r
702 with ReadWrite and Execute attributes allocated by VirtualAlloc() API.\r
2e19fd0f 703\r
704Arguments:\r
705 Index - Which memory region to use\r
706 MemoryBase - Return Base address of memory region\r
707 MemorySize - Return size in bytes of the memory region\r
708\r
709Returns:\r
710 EFI_SUCCESS - If memory region was mapped\r
711 EFI_UNSUPPORTED - If Index is not supported\r
712\r
713--*/\r
714{\r
2e19fd0f 715 if (Index >= gSystemMemoryCount) {\r
716 return EFI_UNSUPPORTED;\r
717 }\r
952261d5
LG
718 \r
719 //\r
720 // Allocate enough memory space for emulator \r
721 //\r
722 gSystemMemory[Index].Memory = (EFI_PHYSICAL_ADDRESS) (UINTN) VirtualAlloc (NULL, (SIZE_T) (gSystemMemory[Index].Size), MEM_COMMIT, PAGE_EXECUTE_READWRITE);\r
723 if (gSystemMemory[Index].Memory == 0) {\r
724 return EFI_OUT_OF_RESOURCES;\r
725 }\r
726 \r
727 *MemoryBase = gSystemMemory[Index].Memory;\r
728 *MemorySize = gSystemMemory[Index].Size;\r
2e19fd0f 729\r
952261d5 730 return EFI_SUCCESS;\r
2e19fd0f 731}\r
732\r
733VOID *\r
734EFIAPI\r
735SecWinNtWinNtThunkAddress (\r
736 VOID\r
737 )\r
738/*++\r
739\r
740Routine Description:\r
741 Since the SEC is the only Windows program in stack it must export\r
742 an interface to do Win API calls. That's what the WinNtThunk address\r
8aa9d680 743 is for. gWinNt is initialized in WinNtThunk.c.\r
2e19fd0f 744\r
745Arguments:\r
746 InterfaceSize - sizeof (EFI_WIN_NT_THUNK_PROTOCOL);\r
747 InterfaceBase - Address of the gWinNt global\r
748\r
749Returns:\r
750 EFI_SUCCESS - Data returned\r
751\r
752--*/\r
753{\r
754 return gWinNt;\r
755}\r
756\r
757\r
758EFI_STATUS\r
759EFIAPI\r
760SecWinNtPeiLoadFile (\r
761 IN VOID *Pe32Data,\r
762 IN EFI_PHYSICAL_ADDRESS *ImageAddress,\r
763 IN UINT64 *ImageSize,\r
764 IN EFI_PHYSICAL_ADDRESS *EntryPoint\r
765 )\r
766/*++\r
767\r
768Routine Description:\r
769 Loads and relocates a PE/COFF image into memory.\r
770\r
771Arguments:\r
772 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated\r
773 ImageAddress - The base address of the relocated PE/COFF image\r
774 ImageSize - The size of the relocated PE/COFF image\r
775 EntryPoint - The entry point of the relocated PE/COFF image\r
776\r
777Returns:\r
778 EFI_SUCCESS - The file was loaded and relocated\r
779 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file\r
780\r
781--*/\r
782{\r
783 EFI_STATUS Status;\r
784 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
785\r
786 ZeroMem (&ImageContext, sizeof (ImageContext));\r
787 ImageContext.Handle = Pe32Data;\r
788\r
789 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) SecImageRead;\r
790\r
ffdd18bb 791 Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
2e19fd0f 792 if (EFI_ERROR (Status)) {\r
793 return Status;\r
794 }\r
795 //\r
8aa9d680 796 // Allocate space in NT (not emulator) memory with ReadWrite and Execute attribute. \r
952261d5 797 // Extra space is for alignment\r
2e19fd0f 798 //\r
952261d5 799 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) VirtualAlloc (NULL, (SIZE_T) (ImageContext.ImageSize + (ImageContext.SectionAlignment * 2)), MEM_COMMIT, PAGE_EXECUTE_READWRITE);\r
2e19fd0f 800 if (ImageContext.ImageAddress == 0) {\r
801 return EFI_OUT_OF_RESOURCES;\r
802 }\r
803 //\r
8aa9d680 804 // Align buffer on section boundary\r
2e19fd0f 805 //\r
0d10bfc8 806 ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;\r
4e502412 807 ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1);\r
2e19fd0f 808\r
ffdd18bb 809 Status = PeCoffLoaderLoadImage (&ImageContext);\r
2e19fd0f 810 if (EFI_ERROR (Status)) {\r
811 return Status;\r
812 }\r
813\r
ffdd18bb 814 Status = SecNt32PeCoffRelocateImage (&ImageContext);\r
2e19fd0f 815 if (EFI_ERROR (Status)) {\r
816 return Status;\r
817 }\r
818\r
819 //\r
820 // BugBug: Flush Instruction Cache Here when CPU Lib is ready\r
821 //\r
822\r
823 *ImageAddress = ImageContext.ImageAddress;\r
824 *ImageSize = ImageContext.ImageSize;\r
825 *EntryPoint = ImageContext.EntryPoint;\r
826\r
827 return EFI_SUCCESS;\r
828}\r
829\r
830EFI_STATUS\r
831EFIAPI\r
832SecWinNtFdAddress (\r
833 IN UINTN Index,\r
834 IN OUT EFI_PHYSICAL_ADDRESS *FdBase,\r
835 IN OUT UINT64 *FdSize\r
836 )\r
837/*++\r
838\r
839Routine Description:\r
840 Return the FD Size and base address. Since the FD is loaded from a\r
841 file into Windows memory only the SEC will know it's address.\r
842\r
843Arguments:\r
844 Index - Which FD, starts at zero.\r
845 FdSize - Size of the FD in bytes\r
846 FdBase - Start address of the FD. Assume it points to an FV Header\r
847\r
848Returns:\r
849 EFI_SUCCESS - Return the Base address and size of the FV\r
8aa9d680 850 EFI_UNSUPPORTED - Index does not map to an FD in the system\r
2e19fd0f 851\r
852--*/\r
853{\r
854 if (Index >= gFdInfoCount) {\r
855 return EFI_UNSUPPORTED;\r
856 }\r
857\r
858 *FdBase = gFdInfo[Index].Address;\r
859 *FdSize = gFdInfo[Index].Size;\r
860\r
861 if (*FdBase == 0 && *FdSize == 0) {\r
862 return EFI_UNSUPPORTED;\r
863 }\r
864\r
865 return EFI_SUCCESS;\r
866}\r
867\r
868EFI_STATUS\r
869EFIAPI\r
870SecImageRead (\r
871 IN VOID *FileHandle,\r
872 IN UINTN FileOffset,\r
873 IN OUT UINTN *ReadSize,\r
874 OUT VOID *Buffer\r
875 )\r
876/*++\r
877\r
878Routine Description:\r
879 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file\r
880\r
881Arguments:\r
882 FileHandle - The handle to the PE/COFF file\r
883 FileOffset - The offset, in bytes, into the file to read\r
884 ReadSize - The number of bytes to read from the file starting at FileOffset\r
885 Buffer - A pointer to the buffer to read the data into.\r
886\r
887Returns:\r
888 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset\r
889\r
890--*/\r
891{\r
892 CHAR8 *Destination8;\r
893 CHAR8 *Source8;\r
894 UINTN Length;\r
895\r
896 Destination8 = Buffer;\r
897 Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);\r
898 Length = *ReadSize;\r
899 while (Length--) {\r
900 *(Destination8++) = *(Source8++);\r
901 }\r
902\r
903 return EFI_SUCCESS;\r
904}\r
905\r
906CHAR16 *\r
907AsciiToUnicode (\r
908 IN CHAR8 *Ascii,\r
909 IN UINTN *StrLen OPTIONAL\r
910 )\r
911/*++\r
912\r
913Routine Description:\r
914 Convert the passed in Ascii string to Unicode.\r
915 Optionally return the length of the strings.\r
916\r
917Arguments:\r
918 Ascii - Ascii string to convert\r
919 StrLen - Length of string\r
920\r
921Returns:\r
922 Pointer to malloc'ed Unicode version of Ascii\r
923\r
924--*/\r
925{\r
926 UINTN Index;\r
927 CHAR16 *Unicode;\r
928\r
929 //\r
930 // Allocate a buffer for unicode string\r
931 //\r
932 for (Index = 0; Ascii[Index] != '\0'; Index++)\r
933 ;\r
934 Unicode = malloc ((Index + 1) * sizeof (CHAR16));\r
935 if (Unicode == NULL) {\r
936 return NULL;\r
937 }\r
938\r
939 for (Index = 0; Ascii[Index] != '\0'; Index++) {\r
940 Unicode[Index] = (CHAR16) Ascii[Index];\r
941 }\r
942\r
943 Unicode[Index] = '\0';\r
944\r
945 if (StrLen != NULL) {\r
946 *StrLen = Index;\r
947 }\r
948\r
949 return Unicode;\r
950}\r
951\r
952UINTN\r
8aa9d680 953CountSeparatorsInString (\r
03c19e06 954 IN CONST CHAR16 *String,\r
8aa9d680 955 IN CHAR16 Separator\r
2e19fd0f 956 )\r
957/*++\r
958\r
959Routine Description:\r
8aa9d680 960 Count the number of separators in String\r
2e19fd0f 961\r
962Arguments:\r
963 String - String to process\r
8aa9d680 964 Separator - Item to count\r
2e19fd0f 965\r
966Returns:\r
8aa9d680 967 Number of Separator in String\r
2e19fd0f 968\r
969--*/\r
970{\r
971 UINTN Count;\r
972\r
973 for (Count = 0; *String != '\0'; String++) {\r
8aa9d680 974 if (*String == Separator) {\r
2e19fd0f 975 Count++;\r
976 }\r
977 }\r
978\r
979 return Count;\r
980}\r
981\r
982\r
983EFI_STATUS\r
2e19fd0f 984SecNt32PeCoffRelocateImage (\r
2e19fd0f 985 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
986 )\r
987{\r
988 EFI_STATUS Status;\r
989 VOID *DllEntryPoint;\r
990 CHAR16 *DllFileName;\r
991 HMODULE Library;\r
992 UINTN Index;\r
993\r
994\r
995 Status = PeCoffLoaderRelocateImage (ImageContext);\r
996 if (EFI_ERROR (Status)) {\r
997 //\r
998 // We could not relocated the image in memory properly\r
999 //\r
1000 return Status;\r
1001 }\r
1002\r
1003 //\r
1004 // If we load our own PE COFF images the Windows debugger can not source\r
1005 // level debug our code. If a valid PDB pointer exists usw it to load\r
1006 // the *.dll file as a library using Windows* APIs. This allows \r
8aa9d680 1007 // source level debug. The image is still loaded and relocated\r
2e19fd0f 1008 // in the Framework memory space like on a real system (by the code above),\r
1009 // but the entry point points into the DLL loaded by the code bellow. \r
1010 //\r
1011\r
1012 DllEntryPoint = NULL;\r
1013\r
1014 //\r
1015 // Load the DLL if it's not an EBC image.\r
1016 //\r
1017 if ((ImageContext->PdbPointer != NULL) &&\r
1018 (ImageContext->Machine != EFI_IMAGE_MACHINE_EBC)) {\r
1019 //\r
1020 // Convert filename from ASCII to Unicode\r
1021 //\r
1022 DllFileName = AsciiToUnicode (ImageContext->PdbPointer, &Index);\r
1023\r
1024 //\r
1025 // Check that we have a valid filename\r
1026 //\r
1027 if (Index < 5 || DllFileName[Index - 4] != '.') {\r
1028 free (DllFileName);\r
1029\r
1030 //\r
1031 // Never return an error if PeCoffLoaderRelocateImage() succeeded.\r
1032 // The image will run, but we just can't source level debug. If we\r
1033 // return an error the image will not run.\r
1034 //\r
1035 return EFI_SUCCESS;\r
1036 }\r
1037 //\r
1038 // Replace .PDB with .DLL on the filename\r
1039 //\r
1040 DllFileName[Index - 3] = 'D';\r
1041 DllFileName[Index - 2] = 'L';\r
1042 DllFileName[Index - 1] = 'L';\r
1043\r
1044 //\r
1045 // Load the .DLL file into the user process's address space for source \r
1046 // level debug\r
1047 //\r
1048 Library = LoadLibraryEx (DllFileName, NULL, DONT_RESOLVE_DLL_REFERENCES);\r
1049 if (Library != NULL) {\r
1050 //\r
1051 // InitializeDriver is the entry point we put in all our EFI DLL's. The\r
8aa9d680 1052 // DONT_RESOLVE_DLL_REFERENCES argument to LoadLIbraryEx() suppresses the \r
2e19fd0f 1053 // normal DLL entry point of DllMain, and prevents other modules that are\r
1054 // referenced in side the DllFileName from being loaded. There is no error \r
1055 // checking as the we can point to the PE32 image loaded by Tiano. This \r
8aa9d680 1056 // step is only needed for source level debugging\r
2e19fd0f 1057 //\r
1058 DllEntryPoint = (VOID *) (UINTN) GetProcAddress (Library, "InitializeDriver");\r
1059\r
1060 }\r
1061\r
1062 if ((Library != NULL) && (DllEntryPoint != NULL)) {\r
2e19fd0f 1063 ImageContext->EntryPoint = (EFI_PHYSICAL_ADDRESS) (UINTN) DllEntryPoint;\r
1f53f7bb 1064 SecPrint ("LoadLibraryEx (%S,\n NULL, DONT_RESOLVE_DLL_REFERENCES)\n", DllFileName);\r
2e19fd0f 1065 } else {\r
1f53f7bb 1066 SecPrint ("WARNING: No source level debug %S. \n", DllFileName);\r
2e19fd0f 1067 }\r
1068\r
1069 free (DllFileName);\r
1070 }\r
1071\r
1072 //\r
1073 // Never return an error if PeCoffLoaderRelocateImage() succeeded.\r
1074 // The image will run, but we just can't source level debug. If we\r
1075 // return an error the image will not run.\r
1076 //\r
1077 return EFI_SUCCESS;\r
1078}\r
1079\r
1080\r
2e19fd0f 1081\r
2e19fd0f 1082\r
1083VOID\r
1084_ModuleEntryPoint (\r
1085 VOID\r
1086 )\r
1087{\r
1088}\r
1089\r
58dcdada 1090EFI_STATUS\r
1091EFIAPI\r
1092SecTemporaryRamSupport (\r
1093 IN CONST EFI_PEI_SERVICES **PeiServices,\r
1094 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,\r
1095 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,\r
1096 IN UINTN CopySize\r
1097 )\r
1098{\r
1099 //\r
8aa9d680 1100 // Migrate the whole temporary memory to permanent memory.\r
58dcdada 1101 // \r
1102 CopyMem (\r
1103 (VOID*)(UINTN)PermanentMemoryBase, \r
1104 (VOID*)(UINTN)TemporaryMemoryBase, \r
1105 CopySize\r
1106 );\r
1107\r
1108 //\r
1109 // SecSwitchStack function must be invoked after the memory migration\r
8aa9d680
GL
1110 // immediately, also we need fixup the stack change caused by new call into \r
1111 // permanent memory.\r
58dcdada 1112 // \r
1113 SecSwitchStack (\r
1114 (UINT32) TemporaryMemoryBase,\r
1115 (UINT32) PermanentMemoryBase\r
1116 );\r
1117\r
1118 //\r
1119 // We need *not* fix the return address because currently, \r
8aa9d680 1120 // The PeiCore is executed in flash.\r
58dcdada 1121 //\r
1122\r
1123 //\r
84a7fd1e 1124 // Simulate to invalid temporary memory, terminate temporary memory\r
58dcdada 1125 // \r
1126 //ZeroMem ((VOID*)(UINTN)TemporaryMemoryBase, CopySize);\r
1127 \r
1128 return EFI_SUCCESS;\r
1129}\r
1130\r