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