]> git.proxmox.com Git - mirror_edk2.git/blame - EmulatorPkg/Win/Host/WinHost.c
EmulatorPkg/WinHost: Add Reset2 PPI
[mirror_edk2.git] / EmulatorPkg / Win / Host / WinHost.c
CommitLineData
3c859dfe
RN
1/**@file\r
2 WinNt emulator of pre-SEC phase. It's really a Win32 application, but this is\r
3 Ok since all the other modules for NT32 are NOT Win32 applications.\r
4\r
5 This program gets NT32 PCD setting and figures out what the memory layout\r
6 will be, how may FD's will be loaded and also what the boot mode is.\r
7\r
8 This code produces 128 K of temporary memory for the SEC stack by directly\r
9 allocate memory space with ReadWrite and Execute attribute.\r
10\r
d2842bb6 11Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.<BR>\r
bb78cfbe 12(C) Copyright 2016-2020 Hewlett Packard Enterprise Development LP<BR>\r
e3ba31da 13SPDX-License-Identifier: BSD-2-Clause-Patent\r
3c859dfe
RN
14**/\r
15\r
16#include "WinHost.h"\r
17\r
18#ifndef SE_TIME_ZONE_NAME\r
a550d468 19#define SE_TIME_ZONE_NAME TEXT("SeTimeZonePrivilege")\r
3c859dfe
RN
20#endif\r
21\r
10ccc27c
MK
22//\r
23// The growth size for array of module handle entries\r
24//\r
a550d468 25#define MAX_PDB_NAME_TO_MOD_HANDLE_ARRAY_SIZE 0x100\r
10ccc27c
MK
26\r
27//\r
28// Module handle entry structure\r
29//\r
30typedef struct {\r
a550d468
MK
31 CHAR8 *PdbPointer;\r
32 VOID *ModHandle;\r
10ccc27c
MK
33} PDB_NAME_TO_MOD_HANDLE;\r
34\r
35//\r
36// An Array to hold the module handles\r
37//\r
a550d468 38PDB_NAME_TO_MOD_HANDLE *mPdbNameModHandleArray = NULL;\r
10ccc27c
MK
39UINTN mPdbNameModHandleArraySize = 0;\r
40\r
3c859dfe
RN
41//\r
42// Default information about where the FD is located.\r
43// This array gets filled in with information from PcdWinNtFirmwareVolume\r
44// The number of array elements is allocated base on parsing\r
45// PcdWinNtFirmwareVolume and the memory is never freed.\r
46//\r
a550d468
MK
47UINTN gFdInfoCount = 0;\r
48NT_FD_INFO *gFdInfo;\r
3c859dfe
RN
49\r
50//\r
3d6b7fd3 51// Array that supports separate memory ranges.\r
3c859dfe
RN
52// The memory ranges are set by PcdWinNtMemorySizeForSecMain.\r
53// The number of array elements is allocated base on parsing\r
54// PcdWinNtMemorySizeForSecMain value and the memory is never freed.\r
55//\r
a550d468
MK
56UINTN gSystemMemoryCount = 0;\r
57NT_SYSTEM_MEMORY *gSystemMemory;\r
3c859dfe 58\r
7bee2498
RN
59BASE_LIBRARY_JUMP_BUFFER mResetJumpBuffer;\r
60CHAR8 *mResetTypeStr[] = {\r
61 "EfiResetCold",\r
62 "EfiResetWarm",\r
63 "EfiResetShutdown",\r
64 "EfiResetPlatformSpecific"\r
65};\r
66\r
3c859dfe
RN
67/*++\r
68\r
69Routine Description:\r
70 This service is called from Index == 0 until it returns EFI_UNSUPPORTED.\r
71 It allows discontinuous memory regions to be supported by the emulator.\r
72 It uses gSystemMemory[] and gSystemMemoryCount that were created by\r
73 parsing the host environment variable EFI_MEMORY_SIZE.\r
74 The size comes from the varaible and the address comes from the call to\r
75 UnixOpenFile.\r
76\r
77Arguments:\r
78 Index - Which memory region to use\r
79 MemoryBase - Return Base address of memory region\r
80 MemorySize - Return size in bytes of the memory region\r
81\r
82Returns:\r
83 EFI_SUCCESS - If memory region was mapped\r
84 EFI_UNSUPPORTED - If Index is not supported\r
85\r
86**/\r
87EFI_STATUS\r
88WinPeiAutoScan (\r
89 IN UINTN Index,\r
90 OUT EFI_PHYSICAL_ADDRESS *MemoryBase,\r
91 OUT UINT64 *MemorySize\r
92 )\r
93{\r
94 if (Index >= gSystemMemoryCount) {\r
95 return EFI_UNSUPPORTED;\r
96 }\r
97\r
3c859dfe
RN
98 *MemoryBase = gSystemMemory[Index].Memory;\r
99 *MemorySize = gSystemMemory[Index].Size;\r
100\r
101 return EFI_SUCCESS;\r
102}\r
103\r
104/*++\r
105\r
106Routine Description:\r
107 Return the FD Size and base address. Since the FD is loaded from a\r
3d6b7fd3 108 file into host memory only the SEC will know its address.\r
3c859dfe
RN
109\r
110Arguments:\r
111 Index - Which FD, starts at zero.\r
112 FdSize - Size of the FD in bytes\r
113 FdBase - Start address of the FD. Assume it points to an FV Header\r
114 FixUp - Difference between actual FD address and build address\r
115\r
116Returns:\r
117 EFI_SUCCESS - Return the Base address and size of the FV\r
118 EFI_UNSUPPORTED - Index does nto map to an FD in the system\r
119\r
120**/\r
121EFI_STATUS\r
122WinFdAddress (\r
123 IN UINTN Index,\r
124 IN OUT EFI_PHYSICAL_ADDRESS *FdBase,\r
125 IN OUT UINT64 *FdSize,\r
126 IN OUT EFI_PHYSICAL_ADDRESS *FixUp\r
127 )\r
128{\r
129 if (Index >= gFdInfoCount) {\r
130 return EFI_UNSUPPORTED;\r
131 }\r
132\r
3c859dfe
RN
133 *FdBase = (EFI_PHYSICAL_ADDRESS)(UINTN)gFdInfo[Index].Address;\r
134 *FdSize = (UINT64)gFdInfo[Index].Size;\r
135 *FixUp = 0;\r
136\r
a550d468 137 if ((*FdBase == 0) && (*FdSize == 0)) {\r
3c859dfe
RN
138 return EFI_UNSUPPORTED;\r
139 }\r
140\r
141 if (Index == 0) {\r
142 //\r
143 // FD 0 has XIP code and well known PCD values\r
144 // If the memory buffer could not be allocated at the FD build address\r
145 // the Fixup is the difference.\r
146 //\r
147 *FixUp = *FdBase - PcdGet64 (PcdEmuFdBaseAddress);\r
148 }\r
149\r
150 return EFI_SUCCESS;\r
151}\r
152\r
153/*++\r
154\r
155Routine Description:\r
156 Since the SEC is the only Unix program in stack it must export\r
157 an interface to do POSIX calls. gUnix is initialized in UnixThunk.c.\r
158\r
159Arguments:\r
160 InterfaceSize - sizeof (EFI_WIN_NT_THUNK_PROTOCOL);\r
161 InterfaceBase - Address of the gUnix global\r
162\r
163Returns:\r
164 EFI_SUCCESS - Data returned\r
165\r
166**/\r
167VOID *\r
168WinThunk (\r
169 VOID\r
170 )\r
171{\r
172 return &gEmuThunkProtocol;\r
173}\r
174\r
a550d468 175EMU_THUNK_PPI mSecEmuThunkPpi = {\r
3c859dfe
RN
176 WinPeiAutoScan,\r
177 WinFdAddress,\r
178 WinThunk\r
179};\r
180\r
181VOID\r
182SecPrint (\r
183 CHAR8 *Format,\r
184 ...\r
185 )\r
186{\r
187 va_list Marker;\r
188 UINTN CharCount;\r
189 CHAR8 Buffer[0x1000];\r
190\r
191 va_start (Marker, Format);\r
192\r
193 _vsnprintf (Buffer, sizeof (Buffer), Format, Marker);\r
194\r
195 va_end (Marker);\r
196\r
197 CharCount = strlen (Buffer);\r
198 WriteFile (\r
199 GetStdHandle (STD_OUTPUT_HANDLE),\r
200 Buffer,\r
201 (DWORD)CharCount,\r
202 (LPDWORD)&CharCount,\r
203 NULL\r
204 );\r
205}\r
206\r
7bee2498
RN
207/**\r
208 Resets the entire platform.\r
209\r
210 @param[in] ResetType The type of reset to perform.\r
211 @param[in] ResetStatus The status code for the reset.\r
212 @param[in] DataSize The size, in bytes, of ResetData.\r
213 @param[in] ResetData For a ResetType of EfiResetCold, EfiResetWarm, or EfiResetShutdown\r
214 the data buffer starts with a Null-terminated string, optionally\r
215 followed by additional binary data. The string is a description\r
216 that the caller may use to further indicate the reason for the\r
217 system reset.\r
218\r
219**/\r
220VOID\r
221EFIAPI\r
222WinReset (\r
223 IN EFI_RESET_TYPE ResetType,\r
224 IN EFI_STATUS ResetStatus,\r
225 IN UINTN DataSize,\r
226 IN VOID *ResetData OPTIONAL\r
227 )\r
228{\r
229 ASSERT (ResetType <= EfiResetPlatformSpecific);\r
230 SecPrint (" Emu ResetSystem is called: ResetType = %s\n", mResetTypeStr[ResetType]);\r
231\r
232 if (ResetType == EfiResetShutdown) {\r
233 exit (0);\r
234 } else {\r
235 //\r
236 // Jump back to SetJump with jump code = ResetType + 1\r
237 //\r
238 LongJump (&mResetJumpBuffer, ResetType + 1);\r
239 }\r
240}\r
241\r
242EFI_PEI_RESET2_PPI mEmuReset2Ppi = {\r
243 WinReset\r
244};\r
245\r
3c859dfe
RN
246/*++\r
247\r
248Routine Description:\r
249 Check to see if an address range is in the EFI GCD memory map.\r
250\r
251 This is all of GCD for system memory passed to DXE Core. FV\r
252 mapping and other device mapped into system memory are not\r
253 inlcuded in the check.\r
254\r
255Arguments:\r
256 Index - Which memory region to use\r
257 MemoryBase - Return Base address of memory region\r
258 MemorySize - Return size in bytes of the memory region\r
259\r
260Returns:\r
261 TRUE - Address is in the EFI GCD memory map\r
262 FALSE - Address is NOT in memory map\r
263\r
264**/\r
265BOOLEAN\r
266EfiSystemMemoryRange (\r
a550d468 267 IN VOID *MemoryAddress\r
3c859dfe
RN
268 )\r
269{\r
270 UINTN Index;\r
271 EFI_PHYSICAL_ADDRESS MemoryBase;\r
272\r
273 MemoryBase = (EFI_PHYSICAL_ADDRESS)(UINTN)MemoryAddress;\r
274 for (Index = 0; Index < gSystemMemoryCount; Index++) {\r
275 if ((MemoryBase >= gSystemMemory[Index].Memory) &&\r
a550d468
MK
276 (MemoryBase < (gSystemMemory[Index].Memory + gSystemMemory[Index].Size)))\r
277 {\r
3c859dfe
RN
278 return TRUE;\r
279 }\r
280 }\r
281\r
282 return FALSE;\r
283}\r
284\r
3c859dfe
RN
285EFI_STATUS\r
286WinNtOpenFile (\r
a550d468
MK
287 IN CHAR16 *FileName OPTIONAL,\r
288 IN UINT32 MapSize,\r
289 IN DWORD CreationDisposition,\r
290 IN OUT VOID **BaseAddress,\r
291 OUT UINTN *Length\r
3c859dfe 292 )\r
a550d468 293\r
3c859dfe
RN
294/*++\r
295\r
296Routine Description:\r
297 Opens and memory maps a file using WinNt services. If *BaseAddress is non zero\r
298 the process will try and allocate the memory starting at BaseAddress.\r
299\r
300Arguments:\r
301 FileName - The name of the file to open and map\r
302 MapSize - The amount of the file to map in bytes\r
303 CreationDisposition - The flags to pass to CreateFile(). Use to create new files for\r
304 memory emulation, and exiting files for firmware volume emulation\r
305 BaseAddress - The base address of the mapped file in the user address space.\r
306 If *BaseAddress is 0, the new memory region is used.\r
307 If *BaseAddress is not 0, the request memory region is used for\r
308 the mapping of the file into the process space.\r
309 Length - The size of the mapped region in bytes\r
310\r
311Returns:\r
312 EFI_SUCCESS - The file was opened and mapped.\r
313 EFI_NOT_FOUND - FileName was not found in the current directory\r
3d6b7fd3 314 EFI_DEVICE_ERROR - An error occurred attempting to map the opened file\r
3c859dfe
RN
315\r
316--*/\r
317{\r
318 HANDLE NtFileHandle;\r
319 HANDLE NtMapHandle;\r
320 VOID *VirtualAddress;\r
321 UINTN FileSize;\r
322\r
323 //\r
324 // Use Win API to open/create a file\r
325 //\r
326 NtFileHandle = INVALID_HANDLE_VALUE;\r
327 if (FileName != NULL) {\r
328 NtFileHandle = CreateFile (\r
329 FileName,\r
330 GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE,\r
331 FILE_SHARE_READ,\r
332 NULL,\r
333 CreationDisposition,\r
334 FILE_ATTRIBUTE_NORMAL,\r
335 NULL\r
336 );\r
337 if (NtFileHandle == INVALID_HANDLE_VALUE) {\r
338 return EFI_NOT_FOUND;\r
339 }\r
340 }\r
a550d468 341\r
3c859dfe
RN
342 //\r
343 // Map the open file into a memory range\r
344 //\r
345 NtMapHandle = CreateFileMapping (\r
346 NtFileHandle,\r
347 NULL,\r
348 PAGE_EXECUTE_READWRITE,\r
349 0,\r
350 MapSize,\r
351 NULL\r
352 );\r
353 if (NtMapHandle == NULL) {\r
354 return EFI_DEVICE_ERROR;\r
355 }\r
a550d468 356\r
3c859dfe
RN
357 //\r
358 // Get the virtual address (address in the emulator) of the mapped file\r
359 //\r
360 VirtualAddress = MapViewOfFileEx (\r
a550d468
MK
361 NtMapHandle,\r
362 FILE_MAP_EXECUTE | FILE_MAP_ALL_ACCESS,\r
363 0,\r
364 0,\r
365 MapSize,\r
366 *BaseAddress\r
367 );\r
3c859dfe
RN
368 if (VirtualAddress == NULL) {\r
369 return EFI_DEVICE_ERROR;\r
370 }\r
371\r
372 if (MapSize == 0) {\r
373 //\r
374 // Seek to the end of the file to figure out the true file size.\r
375 //\r
376 FileSize = SetFilePointer (\r
a550d468
MK
377 NtFileHandle,\r
378 0,\r
379 NULL,\r
380 FILE_END\r
381 );\r
3c859dfe
RN
382 if (FileSize == -1) {\r
383 return EFI_DEVICE_ERROR;\r
384 }\r
385\r
386 *Length = FileSize;\r
387 } else {\r
388 *Length = MapSize;\r
389 }\r
390\r
391 *BaseAddress = VirtualAddress;\r
392\r
393 return EFI_SUCCESS;\r
394}\r
395\r
396INTN\r
397EFIAPI\r
398main (\r
a550d468
MK
399 IN INT Argc,\r
400 IN CHAR8 **Argv,\r
401 IN CHAR8 **Envp\r
3c859dfe 402 )\r
a550d468 403\r
3c859dfe
RN
404/*++\r
405\r
406Routine Description:\r
407 Main entry point to SEC for WinNt. This is a Windows program\r
408\r
409Arguments:\r
410 Argc - Number of command line arguments\r
411 Argv - Array of command line argument strings\r
412 Envp - Array of environment variable strings\r
413\r
414Returns:\r
415 0 - Normal exit\r
416 1 - Abnormal exit\r
417\r
418--*/\r
419{\r
a550d468
MK
420 EFI_STATUS Status;\r
421 HANDLE Token;\r
422 TOKEN_PRIVILEGES TokenPrivileges;\r
423 VOID *TemporaryRam;\r
424 UINT32 TemporaryRamSize;\r
425 VOID *EmuMagicPage;\r
426 UINTN Index;\r
427 UINTN Index1;\r
428 CHAR16 *FileName;\r
429 CHAR16 *FileNamePtr;\r
430 BOOLEAN Done;\r
431 EFI_PEI_FILE_HANDLE FileHandle;\r
432 VOID *SecFile;\r
433 CHAR16 *MemorySizeStr;\r
434 CHAR16 *FirmwareVolumesStr;\r
435 UINTN ProcessAffinityMask;\r
436 UINTN SystemAffinityMask;\r
437 INT32 LowBit;\r
7bee2498 438 UINTN ResetJumpCode;\r
3c859dfe
RN
439\r
440 //\r
441 // Enable the privilege so that RTC driver can successfully run SetTime()\r
442 //\r
a550d468
MK
443 OpenProcessToken (GetCurrentProcess (), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &Token);\r
444 if (LookupPrivilegeValue (NULL, SE_TIME_ZONE_NAME, &TokenPrivileges.Privileges[0].Luid)) {\r
445 TokenPrivileges.PrivilegeCount = 1;\r
3c859dfe 446 TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;\r
a550d468 447 AdjustTokenPrivileges (Token, FALSE, &TokenPrivileges, 0, (PTOKEN_PRIVILEGES)NULL, 0);\r
3c859dfe
RN
448 }\r
449\r
a550d468
MK
450 MemorySizeStr = (CHAR16 *)PcdGetPtr (PcdEmuMemorySize);\r
451 FirmwareVolumesStr = (CHAR16 *)PcdGetPtr (PcdEmuFirmwareVolume);\r
3c859dfe 452\r
30b4abc6 453 SecPrint ("\n\rEDK II WIN Host Emulation Environment from http://www.tianocore.org/edk2/\n\r");\r
3c859dfe
RN
454\r
455 //\r
456 // Determine the first thread available to this process.\r
457 //\r
458 if (GetProcessAffinityMask (GetCurrentProcess (), &ProcessAffinityMask, &SystemAffinityMask)) {\r
2737037a 459 LowBit = (INT32)LowBitSet32 ((UINT32)ProcessAffinityMask);\r
3c859dfe
RN
460 if (LowBit != -1) {\r
461 //\r
462 // Force the system to bind the process to a single thread to work\r
463 // around odd semaphore type crashes.\r
464 //\r
465 SetProcessAffinityMask (GetCurrentProcess (), (INTN)(BIT0 << LowBit));\r
466 }\r
467 }\r
468\r
469 //\r
470 // Make some Windows calls to Set the process to the highest priority in the\r
471 // idle class. We need this to have good performance.\r
472 //\r
473 SetPriorityClass (GetCurrentProcess (), IDLE_PRIORITY_CLASS);\r
474 SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);\r
475\r
476 SecInitializeThunk ();\r
477 //\r
478 // PPIs pased into PEI_CORE\r
479 //\r
480 AddThunkPpi (EFI_PEI_PPI_DESCRIPTOR_PPI, &gEmuThunkPpiGuid, &mSecEmuThunkPpi);\r
7bee2498 481 AddThunkPpi (EFI_PEI_PPI_DESCRIPTOR_PPI, &gEfiPeiReset2PpiGuid, &mEmuReset2Ppi);\r
3c859dfe 482\r
7a465451
RN
483 //\r
484 // Emulator Bus Driver Thunks\r
485 //\r
486 AddThunkProtocol (&mWinNtWndThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuGop), TRUE);\r
56502bf1 487 AddThunkProtocol (&mWinNtFileSystemThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuFileSystem), TRUE);\r
8f819697 488 AddThunkProtocol (&mWinNtBlockIoThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuVirtualDisk), TRUE);\r
bb78cfbe 489 AddThunkProtocol (&mWinNtSnpThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuNetworkInterface), TRUE);\r
7a465451 490\r
3c859dfe
RN
491 //\r
492 // Allocate space for gSystemMemory Array\r
493 //\r
a550d468
MK
494 gSystemMemoryCount = CountSeparatorsInString (MemorySizeStr, '!') + 1;\r
495 gSystemMemory = calloc (gSystemMemoryCount, sizeof (NT_SYSTEM_MEMORY));\r
3c859dfe 496 if (gSystemMemory == NULL) {\r
30b4abc6 497 SecPrint ("ERROR : Can not allocate memory for %S. Exiting.\n\r", MemorySizeStr);\r
3c859dfe
RN
498 exit (1);\r
499 }\r
500\r
d2842bb6
RN
501 //\r
502 // Allocate "physical" memory space for emulator. It will be reported out later throuth MemoryAutoScan()\r
503 //\r
504 for (Index = 0, Done = FALSE; !Done; Index++) {\r
505 ASSERT (Index < gSystemMemoryCount);\r
506 gSystemMemory[Index].Size = ((UINT64)_wtoi (MemorySizeStr)) * ((UINT64)SIZE_1MB);\r
507 gSystemMemory[Index].Memory = (EFI_PHYSICAL_ADDRESS)(UINTN)VirtualAlloc (NULL, (SIZE_T)(gSystemMemory[Index].Size), MEM_COMMIT, PAGE_EXECUTE_READWRITE);\r
508 if (gSystemMemory[Index].Memory == 0) {\r
509 return EFI_OUT_OF_RESOURCES;\r
510 }\r
511\r
512 //\r
513 // Find the next region\r
514 //\r
515 for (Index1 = 0; MemorySizeStr[Index1] != '!' && MemorySizeStr[Index1] != 0; Index1++) {\r
516 }\r
517\r
518 if (MemorySizeStr[Index1] == 0) {\r
519 Done = TRUE;\r
520 }\r
521\r
522 MemorySizeStr = MemorySizeStr + Index1 + 1;\r
523 }\r
524\r
3c859dfe
RN
525 //\r
526 // Allocate space for gSystemMemory Array\r
527 //\r
a550d468
MK
528 gFdInfoCount = CountSeparatorsInString (FirmwareVolumesStr, '!') + 1;\r
529 gFdInfo = calloc (gFdInfoCount, sizeof (NT_FD_INFO));\r
3c859dfe 530 if (gFdInfo == NULL) {\r
30b4abc6 531 SecPrint ("ERROR : Can not allocate memory for %S. Exiting.\n\r", FirmwareVolumesStr);\r
3c859dfe
RN
532 exit (1);\r
533 }\r
a550d468 534\r
3c859dfe
RN
535 //\r
536 // Setup Boot Mode.\r
537 //\r
30b4abc6 538 SecPrint (" BootMode 0x%02x\n\r", PcdGet32 (PcdEmuBootMode));\r
3c859dfe
RN
539\r
540 //\r
541 // Allocate 128K memory to emulate temp memory for PEI.\r
542 // on a real platform this would be SRAM, or using the cache as RAM.\r
543 // Set TemporaryRam to zero so WinNtOpenFile will allocate a new mapping\r
544 //\r
545 TemporaryRamSize = TEMPORARY_RAM_SIZE;\r
a550d468 546 TemporaryRam = VirtualAlloc (NULL, (SIZE_T)(TemporaryRamSize), MEM_COMMIT, PAGE_EXECUTE_READWRITE);\r
3c859dfe 547 if (TemporaryRam == NULL) {\r
30b4abc6 548 SecPrint ("ERROR : Can not allocate enough space for SecStack\n\r");\r
3c859dfe
RN
549 exit (1);\r
550 }\r
a550d468 551\r
3c859dfe
RN
552 //\r
553 // If enabled use the magic page to communicate between modules\r
554 // This replaces the PI PeiServicesTable pointer mechanism that\r
555 // deos not work in the emulator. It also allows the removal of\r
556 // writable globals from SEC, PEI_CORE (libraries), PEIMs\r
557 //\r
558 EmuMagicPage = (VOID *)(UINTN)(FixedPcdGet64 (PcdPeiServicesTablePage) & MAX_UINTN);\r
559 if (EmuMagicPage != NULL) {\r
560 UINT64 Size;\r
561 Status = WinNtOpenFile (\r
a550d468
MK
562 NULL,\r
563 SIZE_4KB,\r
564 0,\r
565 &EmuMagicPage,\r
566 &Size\r
567 );\r
3c859dfe 568 if (EFI_ERROR (Status)) {\r
30b4abc6 569 SecPrint ("ERROR : Could not allocate PeiServicesTablePage @ %p\n\r", EmuMagicPage);\r
3c859dfe
RN
570 return EFI_DEVICE_ERROR;\r
571 }\r
572 }\r
573\r
574 //\r
575 // Open All the firmware volumes and remember the info in the gFdInfo global\r
576 // Meanwhile, find the SEC Core.\r
577 //\r
578 FileNamePtr = AllocateCopyPool (StrSize (FirmwareVolumesStr), FirmwareVolumesStr);\r
579 if (FileNamePtr == NULL) {\r
30b4abc6 580 SecPrint ("ERROR : Can not allocate memory for firmware volume string\n\r");\r
3c859dfe
RN
581 exit (1);\r
582 }\r
583\r
584 for (Done = FALSE, Index = 0, SecFile = NULL; !Done; Index++) {\r
585 FileName = FileNamePtr;\r
a550d468
MK
586 for (Index1 = 0; (FileNamePtr[Index1] != '!') && (FileNamePtr[Index1] != 0); Index1++) {\r
587 }\r
588\r
3c859dfe
RN
589 if (FileNamePtr[Index1] == 0) {\r
590 Done = TRUE;\r
591 } else {\r
a550d468
MK
592 FileNamePtr[Index1] = '\0';\r
593 FileNamePtr = &FileNamePtr[Index1 + 1];\r
3c859dfe
RN
594 }\r
595\r
596 //\r
597 // Open the FD and remember where it got mapped into our processes address space\r
598 //\r
599 Status = WinNtOpenFile (\r
a550d468
MK
600 FileName,\r
601 0,\r
602 OPEN_EXISTING,\r
603 &gFdInfo[Index].Address,\r
604 &gFdInfo[Index].Size\r
605 );\r
3c859dfe 606 if (EFI_ERROR (Status)) {\r
30b4abc6 607 SecPrint ("ERROR : Can not open Firmware Device File %S (0x%X). Exiting.\n\r", FileName, Status);\r
3c859dfe
RN
608 exit (1);\r
609 }\r
610\r
30b4abc6 611 SecPrint (" FD loaded from %S", FileName);\r
3c859dfe
RN
612\r
613 if (SecFile == NULL) {\r
614 //\r
615 // Assume the beginning of the FD is an FV and look for the SEC Core.\r
616 // Load the first one we find.\r
617 //\r
618 FileHandle = NULL;\r
a550d468
MK
619 Status = PeiServicesFfsFindNextFile (\r
620 EFI_FV_FILETYPE_SECURITY_CORE,\r
621 (EFI_PEI_FV_HANDLE)gFdInfo[Index].Address,\r
622 &FileHandle\r
623 );\r
3c859dfe
RN
624 if (!EFI_ERROR (Status)) {\r
625 Status = PeiServicesFfsFindSectionData (EFI_SECTION_PE32, FileHandle, &SecFile);\r
626 if (!EFI_ERROR (Status)) {\r
627 SecPrint (" contains SEC Core");\r
628 }\r
629 }\r
630 }\r
631\r
30b4abc6 632 SecPrint ("\n\r");\r
3c859dfe 633 }\r
a550d468 634\r
7bee2498
RN
635 ResetJumpCode = SetJump (&mResetJumpBuffer);\r
636\r
637 //\r
638 // Do not clear memory content for warm reset.\r
639 //\r
640 if (ResetJumpCode != EfiResetWarm + 1) {\r
641 SecPrint (" OS Emulator clearing temp RAM and physical RAM (to be discovered later)......\n\r");\r
642 SetMem32 (TemporaryRam, TemporaryRamSize, PcdGet32 (PcdInitValueInTempStack));\r
643 for (Index = 0; Index < gSystemMemoryCount; Index++) {\r
644 SetMem32 ((VOID *)(UINTN)gSystemMemory[Index].Memory, (UINTN)gSystemMemory[Index].Size, PcdGet32 (PcdInitValueInTempStack));\r
645 }\r
646 }\r
647\r
648 SecPrint (\r
649 " OS Emulator passing in %u KB of temp RAM at 0x%08lx to SEC\n\r",\r
650 TemporaryRamSize / SIZE_1KB,\r
651 TemporaryRam\r
652 );\r
3c859dfe
RN
653 //\r
654 // Hand off to SEC Core\r
655 //\r
656 SecLoadSecCore ((UINTN)TemporaryRam, TemporaryRamSize, gFdInfo[0].Address, gFdInfo[0].Size, SecFile);\r
657\r
658 //\r
659 // If we get here, then the SEC Core returned. This is an error as SEC should\r
660 // always hand off to PEI Core and then on to DXE Core.\r
661 //\r
30b4abc6 662 SecPrint ("ERROR : SEC returned\n\r");\r
3c859dfe
RN
663 exit (1);\r
664}\r
665\r
666VOID\r
667SecLoadSecCore (\r
a550d468
MK
668 IN UINTN TemporaryRam,\r
669 IN UINTN TemporaryRamSize,\r
670 IN VOID *BootFirmwareVolumeBase,\r
671 IN UINTN BootFirmwareVolumeSize,\r
672 IN VOID *SecCorePe32File\r
3c859dfe 673 )\r
a550d468 674\r
3c859dfe
RN
675/*++\r
676\r
677Routine Description:\r
678 This is the service to load the SEC Core from the Firmware Volume\r
679\r
680Arguments:\r
681 TemporaryRam - Memory to use for SEC.\r
682 TemporaryRamSize - Size of Memory to use for SEC\r
683 BootFirmwareVolumeBase - Start of the Boot FV\r
684 SecCorePe32File - SEC Core PE32\r
685\r
686Returns:\r
3d6b7fd3 687 Success means control is transferred and thus we should never return\r
3c859dfe
RN
688\r
689--*/\r
690{\r
a550d468
MK
691 EFI_STATUS Status;\r
692 VOID *TopOfStack;\r
693 VOID *SecCoreEntryPoint;\r
694 EFI_SEC_PEI_HAND_OFF *SecCoreData;\r
695 UINTN SecStackSize;\r
3c859dfe
RN
696\r
697 //\r
698 // Compute Top Of Memory for Stack and PEI Core Allocations\r
699 //\r
700 SecStackSize = TemporaryRamSize >> 1;\r
701\r
702 //\r
703 // |-----------| <---- TemporaryRamBase + TemporaryRamSize\r
704 // | Heap |\r
705 // | |\r
706 // |-----------| <---- StackBase / PeiTemporaryMemoryBase\r
707 // | |\r
708 // | Stack |\r
709 // |-----------| <---- TemporaryRamBase\r
710 //\r
a550d468 711 TopOfStack = (VOID *)(TemporaryRam + SecStackSize);\r
3c859dfe
RN
712\r
713 //\r
714 // Reservet space for storing PeiCore's parament in stack.\r
715 //\r
a550d468
MK
716 TopOfStack = (VOID *)((UINTN)TopOfStack - sizeof (EFI_SEC_PEI_HAND_OFF) - CPU_STACK_ALIGNMENT);\r
717 TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);\r
3c859dfe
RN
718\r
719 //\r
720 // Bind this information into the SEC hand-off state\r
721 //\r
a550d468 722 SecCoreData = (EFI_SEC_PEI_HAND_OFF *)(UINTN)TopOfStack;\r
3c859dfe
RN
723 SecCoreData->DataSize = sizeof (EFI_SEC_PEI_HAND_OFF);\r
724 SecCoreData->BootFirmwareVolumeBase = BootFirmwareVolumeBase;\r
725 SecCoreData->BootFirmwareVolumeSize = BootFirmwareVolumeSize;\r
a550d468 726 SecCoreData->TemporaryRamBase = (VOID *)TemporaryRam;\r
3c859dfe
RN
727 SecCoreData->TemporaryRamSize = TemporaryRamSize;\r
728 SecCoreData->StackBase = SecCoreData->TemporaryRamBase;\r
729 SecCoreData->StackSize = SecStackSize;\r
a550d468 730 SecCoreData->PeiTemporaryRamBase = (VOID *)((UINTN)SecCoreData->TemporaryRamBase + SecStackSize);\r
3c859dfe
RN
731 SecCoreData->PeiTemporaryRamSize = TemporaryRamSize - SecStackSize;\r
732\r
733 //\r
734 // Load the PEI Core from a Firmware Volume\r
735 //\r
736 Status = SecPeCoffGetEntryPoint (\r
a550d468
MK
737 SecCorePe32File,\r
738 &SecCoreEntryPoint\r
739 );\r
3c859dfe 740 if (EFI_ERROR (Status)) {\r
a550d468 741 return;\r
3c859dfe
RN
742 }\r
743\r
744 //\r
745 // Transfer control to the SEC Core\r
746 //\r
747 SwitchStack (\r
f4eaaf1a 748 (SWITCH_STACK_ENTRY_POINT)(UINTN)SecCoreEntryPoint,\r
3c859dfe
RN
749 SecCoreData,\r
750 GetThunkPpiList (),\r
751 TopOfStack\r
752 );\r
753 //\r
754 // If we get here, then the SEC Core returned. This is an error\r
755 //\r
a550d468 756 return;\r
3c859dfe
RN
757}\r
758\r
759RETURN_STATUS\r
760EFIAPI\r
761SecPeCoffGetEntryPoint (\r
762 IN VOID *Pe32Data,\r
763 IN OUT VOID **EntryPoint\r
764 )\r
765{\r
a550d468
MK
766 EFI_STATUS Status;\r
767 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
3c859dfe
RN
768\r
769 ZeroMem (&ImageContext, sizeof (ImageContext));\r
a550d468 770 ImageContext.Handle = Pe32Data;\r
3c859dfe 771\r
a550d468 772 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)SecImageRead;\r
3c859dfe 773\r
a550d468 774 Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
3c859dfe
RN
775 if (EFI_ERROR (Status)) {\r
776 return Status;\r
777 }\r
a550d468 778\r
3c859dfe 779 //\r
a121165e 780 // XIP for SEC and PEI_CORE\r
3c859dfe 781 //\r
a121165e 782 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Pe32Data;\r
3c859dfe
RN
783\r
784 Status = PeCoffLoaderLoadImage (&ImageContext);\r
785 if (EFI_ERROR (Status)) {\r
786 return Status;\r
787 }\r
788\r
789 Status = PeCoffLoaderRelocateImage (&ImageContext);\r
790 if (EFI_ERROR (Status)) {\r
791 return Status;\r
792 }\r
793\r
a550d468 794 *EntryPoint = (VOID *)(UINTN)ImageContext.EntryPoint;\r
3c859dfe
RN
795\r
796 return EFI_SUCCESS;\r
797}\r
798\r
799EFI_STATUS\r
800EFIAPI\r
801SecImageRead (\r
a550d468
MK
802 IN VOID *FileHandle,\r
803 IN UINTN FileOffset,\r
804 IN OUT UINTN *ReadSize,\r
805 OUT VOID *Buffer\r
3c859dfe 806 )\r
a550d468 807\r
3c859dfe
RN
808/*++\r
809\r
810Routine Description:\r
811 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file\r
812\r
813Arguments:\r
814 FileHandle - The handle to the PE/COFF file\r
815 FileOffset - The offset, in bytes, into the file to read\r
816 ReadSize - The number of bytes to read from the file starting at FileOffset\r
817 Buffer - A pointer to the buffer to read the data into.\r
818\r
819Returns:\r
820 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset\r
821\r
822--*/\r
823{\r
a550d468
MK
824 CHAR8 *Destination8;\r
825 CHAR8 *Source8;\r
826 UINTN Length;\r
3c859dfe 827\r
a550d468
MK
828 Destination8 = Buffer;\r
829 Source8 = (CHAR8 *)((UINTN)FileHandle + FileOffset);\r
830 Length = *ReadSize;\r
3c859dfe
RN
831 while (Length--) {\r
832 *(Destination8++) = *(Source8++);\r
833 }\r
834\r
835 return EFI_SUCCESS;\r
836}\r
837\r
838CHAR16 *\r
839AsciiToUnicode (\r
a550d468
MK
840 IN CHAR8 *Ascii,\r
841 IN UINTN *StrLen OPTIONAL\r
3c859dfe 842 )\r
a550d468 843\r
3c859dfe
RN
844/*++\r
845\r
846Routine Description:\r
847 Convert the passed in Ascii string to Unicode.\r
848 Optionally return the length of the strings.\r
849\r
850Arguments:\r
851 Ascii - Ascii string to convert\r
852 StrLen - Length of string\r
853\r
854Returns:\r
855 Pointer to malloc'ed Unicode version of Ascii\r
856\r
857--*/\r
858{\r
859 UINTN Index;\r
860 CHAR16 *Unicode;\r
861\r
862 //\r
863 // Allocate a buffer for unicode string\r
864 //\r
a550d468
MK
865 for (Index = 0; Ascii[Index] != '\0'; Index++) {\r
866 }\r
867\r
3c859dfe
RN
868 Unicode = malloc ((Index + 1) * sizeof (CHAR16));\r
869 if (Unicode == NULL) {\r
870 return NULL;\r
871 }\r
872\r
873 for (Index = 0; Ascii[Index] != '\0'; Index++) {\r
a550d468 874 Unicode[Index] = (CHAR16)Ascii[Index];\r
3c859dfe
RN
875 }\r
876\r
877 Unicode[Index] = '\0';\r
878\r
879 if (StrLen != NULL) {\r
880 *StrLen = Index;\r
881 }\r
882\r
883 return Unicode;\r
884}\r
885\r
886UINTN\r
887CountSeparatorsInString (\r
a550d468
MK
888 IN CONST CHAR16 *String,\r
889 IN CHAR16 Separator\r
3c859dfe 890 )\r
a550d468 891\r
3c859dfe
RN
892/*++\r
893\r
894Routine Description:\r
895 Count the number of separators in String\r
896\r
897Arguments:\r
898 String - String to process\r
899 Separator - Item to count\r
900\r
901Returns:\r
902 Number of Separator in String\r
903\r
904--*/\r
905{\r
a550d468 906 UINTN Count;\r
3c859dfe
RN
907\r
908 for (Count = 0; *String != '\0'; String++) {\r
909 if (*String == Separator) {\r
910 Count++;\r
911 }\r
912 }\r
913\r
914 return Count;\r
915}\r
916\r
10ccc27c
MK
917/**\r
918 Store the ModHandle in an array indexed by the Pdb File name.\r
919 The ModHandle is needed to unload the image.\r
920 @param ImageContext - Input data returned from PE Laoder Library. Used to find the\r
921 .PDB file name of the PE Image.\r
922 @param ModHandle - Returned from LoadLibraryEx() and stored for call to\r
923 FreeLibrary().\r
924 @return return EFI_SUCCESS when ModHandle was stored.\r
925--*/\r
926EFI_STATUS\r
927AddModHandle (\r
a550d468
MK
928 IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,\r
929 IN VOID *ModHandle\r
10ccc27c
MK
930 )\r
931\r
932{\r
933 UINTN Index;\r
934 PDB_NAME_TO_MOD_HANDLE *Array;\r
935 UINTN PreviousSize;\r
936 PDB_NAME_TO_MOD_HANDLE *TempArray;\r
937 HANDLE Handle;\r
938 UINTN Size;\r
939\r
940 //\r
941 // Return EFI_ALREADY_STARTED if this DLL has already been loaded\r
942 //\r
943 Array = mPdbNameModHandleArray;\r
944 for (Index = 0; Index < mPdbNameModHandleArraySize; Index++, Array++) {\r
a550d468 945 if ((Array->PdbPointer != NULL) && (Array->ModHandle == ModHandle)) {\r
10ccc27c
MK
946 return EFI_ALREADY_STARTED;\r
947 }\r
948 }\r
949\r
950 Array = mPdbNameModHandleArray;\r
951 for (Index = 0; Index < mPdbNameModHandleArraySize; Index++, Array++) {\r
952 if (Array->PdbPointer == NULL) {\r
953 //\r
954 // Make a copy of the stirng and store the ModHandle\r
955 //\r
a550d468
MK
956 Handle = GetProcessHeap ();\r
957 Size = AsciiStrLen (ImageContext->PdbPointer) + 1;\r
958 Array->PdbPointer = HeapAlloc (Handle, HEAP_ZERO_MEMORY, Size);\r
10ccc27c
MK
959 ASSERT (Array->PdbPointer != NULL);\r
960\r
961 AsciiStrCpyS (Array->PdbPointer, Size, ImageContext->PdbPointer);\r
962 Array->ModHandle = ModHandle;\r
963 return EFI_SUCCESS;\r
964 }\r
965 }\r
966\r
967 //\r
968 // No free space in mPdbNameModHandleArray so grow it by\r
969 // MAX_PDB_NAME_TO_MOD_HANDLE_ARRAY_SIZE entires.\r
970 //\r
a550d468 971 PreviousSize = mPdbNameModHandleArraySize * sizeof (PDB_NAME_TO_MOD_HANDLE);\r
10ccc27c
MK
972 mPdbNameModHandleArraySize += MAX_PDB_NAME_TO_MOD_HANDLE_ARRAY_SIZE;\r
973 //\r
974 // re-allocate a new buffer and copy the old values to the new locaiton.\r
975 //\r
a550d468
MK
976 TempArray = HeapAlloc (\r
977 GetProcessHeap (),\r
978 HEAP_ZERO_MEMORY,\r
979 mPdbNameModHandleArraySize * sizeof (PDB_NAME_TO_MOD_HANDLE)\r
980 );\r
10ccc27c 981\r
a550d468 982 CopyMem ((VOID *)(UINTN)TempArray, (VOID *)(UINTN)mPdbNameModHandleArray, PreviousSize);\r
10ccc27c
MK
983\r
984 HeapFree (GetProcessHeap (), 0, mPdbNameModHandleArray);\r
985\r
986 mPdbNameModHandleArray = TempArray;\r
987 if (mPdbNameModHandleArray == NULL) {\r
988 ASSERT (FALSE);\r
989 return EFI_OUT_OF_RESOURCES;\r
990 }\r
991\r
992 return AddModHandle (ImageContext, ModHandle);\r
993}\r
994\r
995/**\r
996 Return the ModHandle and delete the entry in the array.\r
997 @param ImageContext - Input data returned from PE Laoder Library. Used to find the\r
998 .PDB file name of the PE Image.\r
999 @return\r
1000 ModHandle - ModHandle assoicated with ImageContext is returned\r
1001 NULL - No ModHandle associated with ImageContext\r
1002**/\r
1003VOID *\r
1004RemoveModHandle (\r
a550d468 1005 IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
10ccc27c
MK
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
a550d468 1020 if ((Array->PdbPointer != NULL) && (AsciiStrCmp (Array->PdbPointer, ImageContext->PdbPointer) == 0)) {\r
10ccc27c
MK
1021 //\r
1022 // If you find a match return it and delete the entry\r
1023 //\r
1024 HeapFree (GetProcessHeap (), 0, 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
3c859dfe
RN
1032\r
1033VOID\r
1034EFIAPI\r
1035PeCoffLoaderRelocateImageExtraAction (\r
a550d468 1036 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
3c859dfe
RN
1037 )\r
1038{\r
a550d468
MK
1039 EFI_STATUS Status;\r
1040 VOID *DllEntryPoint;\r
1041 CHAR16 *DllFileName;\r
1042 HMODULE Library;\r
1043 UINTN Index;\r
3c859dfe
RN
1044\r
1045 ASSERT (ImageContext != NULL);\r
1046 //\r
1047 // If we load our own PE COFF images the Windows debugger can not source\r
10ccc27c 1048 // level debug our code. If a valid PDB pointer exists use it to load\r
3c859dfe
RN
1049 // the *.dll file as a library using Windows* APIs. This allows\r
1050 // source level debug. The image is still loaded and relocated\r
1051 // in the Framework memory space like on a real system (by the code above),\r
3d6b7fd3 1052 // but the entry point points into the DLL loaded by the code below.\r
3c859dfe
RN
1053 //\r
1054\r
1055 DllEntryPoint = NULL;\r
1056\r
1057 //\r
1058 // Load the DLL if it's not an EBC image.\r
1059 //\r
1060 if ((ImageContext->PdbPointer != NULL) &&\r
a550d468
MK
1061 (ImageContext->Machine != EFI_IMAGE_MACHINE_EBC))\r
1062 {\r
3c859dfe
RN
1063 //\r
1064 // Convert filename from ASCII to Unicode\r
1065 //\r
1066 DllFileName = AsciiToUnicode (ImageContext->PdbPointer, &Index);\r
1067\r
1068 //\r
1069 // Check that we have a valid filename\r
1070 //\r
a550d468 1071 if ((Index < 5) || (DllFileName[Index - 4] != '.')) {\r
3c859dfe
RN
1072 free (DllFileName);\r
1073\r
1074 //\r
1075 // Never return an error if PeCoffLoaderRelocateImage() succeeded.\r
1076 // The image will run, but we just can't source level debug. If we\r
1077 // return an error the image will not run.\r
1078 //\r
1079 return;\r
1080 }\r
a550d468 1081\r
3c859dfe
RN
1082 //\r
1083 // Replace .PDB with .DLL on the filename\r
1084 //\r
a550d468
MK
1085 DllFileName[Index - 3] = 'D';\r
1086 DllFileName[Index - 2] = 'L';\r
1087 DllFileName[Index - 1] = 'L';\r
3c859dfe
RN
1088\r
1089 //\r
1090 // Load the .DLL file into the user process's address space for source\r
1091 // level debug\r
1092 //\r
1093 Library = LoadLibraryEx (DllFileName, NULL, DONT_RESOLVE_DLL_REFERENCES);\r
1094 if (Library != NULL) {\r
1095 //\r
1096 // InitializeDriver is the entry point we put in all our EFI DLL's. The\r
1097 // DONT_RESOLVE_DLL_REFERENCES argument to LoadLIbraryEx() suppresses the\r
1098 // normal DLL entry point of DllMain, and prevents other modules that are\r
1099 // referenced in side the DllFileName from being loaded. There is no error\r
1100 // checking as the we can point to the PE32 image loaded by Tiano. This\r
1101 // step is only needed for source level debugging\r
1102 //\r
a550d468 1103 DllEntryPoint = (VOID *)(UINTN)GetProcAddress (Library, "InitializeDriver");\r
3c859dfe
RN
1104 }\r
1105\r
1106 if ((Library != NULL) && (DllEntryPoint != NULL)) {\r
10ccc27c
MK
1107 Status = AddModHandle (ImageContext, Library);\r
1108 if (Status == EFI_ALREADY_STARTED) {\r
1109 //\r
1110 // If the DLL has already been loaded before, then this instance of the DLL can not be debugged.\r
1111 //\r
1112 ImageContext->PdbPointer = NULL;\r
1113 SecPrint ("WARNING: DLL already loaded. No source level debug %S.\n\r", DllFileName);\r
1114 } else {\r
1115 //\r
1116 // This DLL is not already loaded, so source level debugging is supported.\r
1117 //\r
a550d468 1118 ImageContext->EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)DllEntryPoint;\r
10ccc27c
MK
1119 SecPrint ("LoadLibraryEx (\n\r %S,\n\r NULL, DONT_RESOLVE_DLL_REFERENCES)\n\r", DllFileName);\r
1120 }\r
3c859dfe 1121 } else {\r
10ccc27c 1122 SecPrint ("WARNING: No source level debug %S. \n\r", DllFileName);\r
3c859dfe
RN
1123 }\r
1124\r
1125 free (DllFileName);\r
1126 }\r
1127}\r
1128\r
1129VOID\r
1130EFIAPI\r
1131PeCoffLoaderUnloadImageExtraAction (\r
10ccc27c 1132 IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
a550d468 1133 )\r
3c859dfe 1134{\r
10ccc27c
MK
1135 VOID *ModHandle;\r
1136\r
3c859dfe 1137 ASSERT (ImageContext != NULL);\r
3c859dfe 1138\r
10ccc27c
MK
1139 ModHandle = RemoveModHandle (ImageContext);\r
1140 if (ModHandle != NULL) {\r
1141 FreeLibrary (ModHandle);\r
1142 SecPrint ("FreeLibrary (\n\r %s)\n\r", ImageContext->PdbPointer);\r
1143 } else {\r
1144 SecPrint ("WARNING: Unload image without source level debug\n\r");\r
1145 }\r
1146}\r
3c859dfe
RN
1147\r
1148VOID\r
1149_ModuleEntryPoint (\r
1150 VOID\r
1151 )\r
1152{\r
1153}\r