]> git.proxmox.com Git - mirror_edk2.git/blame - EmulatorPkg/Win/Host/WinHost.c
EmulatorPkg: Record Argc, Argv and Envp in EmuThunk 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
4e17aba4
RN
229 UINTN Index;\r
230\r
7bee2498
RN
231 ASSERT (ResetType <= EfiResetPlatformSpecific);\r
232 SecPrint (" Emu ResetSystem is called: ResetType = %s\n", mResetTypeStr[ResetType]);\r
233\r
234 if (ResetType == EfiResetShutdown) {\r
235 exit (0);\r
236 } else {\r
4e17aba4
RN
237 //\r
238 // Unload all DLLs\r
239 //\r
240 for (Index = 0; Index < mPdbNameModHandleArraySize; Index++) {\r
241 if (mPdbNameModHandleArray[Index].PdbPointer != NULL) {\r
242 SecPrint (" Emu Unload DLL: %s\n", mPdbNameModHandleArray[Index].PdbPointer);\r
243 FreeLibrary (mPdbNameModHandleArray[Index].ModHandle);\r
244 HeapFree (GetProcessHeap (), 0, mPdbNameModHandleArray[Index].PdbPointer);\r
245 mPdbNameModHandleArray[Index].PdbPointer = NULL;\r
246 }\r
247 }\r
248\r
7bee2498
RN
249 //\r
250 // Jump back to SetJump with jump code = ResetType + 1\r
251 //\r
252 LongJump (&mResetJumpBuffer, ResetType + 1);\r
253 }\r
254}\r
255\r
256EFI_PEI_RESET2_PPI mEmuReset2Ppi = {\r
257 WinReset\r
258};\r
259\r
3c859dfe
RN
260/*++\r
261\r
262Routine Description:\r
263 Check to see if an address range is in the EFI GCD memory map.\r
264\r
265 This is all of GCD for system memory passed to DXE Core. FV\r
266 mapping and other device mapped into system memory are not\r
267 inlcuded in the check.\r
268\r
269Arguments:\r
270 Index - Which memory region to use\r
271 MemoryBase - Return Base address of memory region\r
272 MemorySize - Return size in bytes of the memory region\r
273\r
274Returns:\r
275 TRUE - Address is in the EFI GCD memory map\r
276 FALSE - Address is NOT in memory map\r
277\r
278**/\r
279BOOLEAN\r
280EfiSystemMemoryRange (\r
a550d468 281 IN VOID *MemoryAddress\r
3c859dfe
RN
282 )\r
283{\r
284 UINTN Index;\r
285 EFI_PHYSICAL_ADDRESS MemoryBase;\r
286\r
287 MemoryBase = (EFI_PHYSICAL_ADDRESS)(UINTN)MemoryAddress;\r
288 for (Index = 0; Index < gSystemMemoryCount; Index++) {\r
289 if ((MemoryBase >= gSystemMemory[Index].Memory) &&\r
a550d468
MK
290 (MemoryBase < (gSystemMemory[Index].Memory + gSystemMemory[Index].Size)))\r
291 {\r
3c859dfe
RN
292 return TRUE;\r
293 }\r
294 }\r
295\r
296 return FALSE;\r
297}\r
298\r
3c859dfe
RN
299EFI_STATUS\r
300WinNtOpenFile (\r
a550d468
MK
301 IN CHAR16 *FileName OPTIONAL,\r
302 IN UINT32 MapSize,\r
303 IN DWORD CreationDisposition,\r
304 IN OUT VOID **BaseAddress,\r
305 OUT UINTN *Length\r
3c859dfe 306 )\r
a550d468 307\r
3c859dfe
RN
308/*++\r
309\r
310Routine Description:\r
311 Opens and memory maps a file using WinNt services. If *BaseAddress is non zero\r
312 the process will try and allocate the memory starting at BaseAddress.\r
313\r
314Arguments:\r
315 FileName - The name of the file to open and map\r
316 MapSize - The amount of the file to map in bytes\r
317 CreationDisposition - The flags to pass to CreateFile(). Use to create new files for\r
318 memory emulation, and exiting files for firmware volume emulation\r
319 BaseAddress - The base address of the mapped file in the user address space.\r
320 If *BaseAddress is 0, the new memory region is used.\r
321 If *BaseAddress is not 0, the request memory region is used for\r
322 the mapping of the file into the process space.\r
323 Length - The size of the mapped region in bytes\r
324\r
325Returns:\r
326 EFI_SUCCESS - The file was opened and mapped.\r
327 EFI_NOT_FOUND - FileName was not found in the current directory\r
3d6b7fd3 328 EFI_DEVICE_ERROR - An error occurred attempting to map the opened file\r
3c859dfe
RN
329\r
330--*/\r
331{\r
332 HANDLE NtFileHandle;\r
333 HANDLE NtMapHandle;\r
334 VOID *VirtualAddress;\r
335 UINTN FileSize;\r
336\r
337 //\r
338 // Use Win API to open/create a file\r
339 //\r
340 NtFileHandle = INVALID_HANDLE_VALUE;\r
341 if (FileName != NULL) {\r
342 NtFileHandle = CreateFile (\r
343 FileName,\r
344 GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE,\r
345 FILE_SHARE_READ,\r
346 NULL,\r
347 CreationDisposition,\r
348 FILE_ATTRIBUTE_NORMAL,\r
349 NULL\r
350 );\r
351 if (NtFileHandle == INVALID_HANDLE_VALUE) {\r
352 return EFI_NOT_FOUND;\r
353 }\r
354 }\r
a550d468 355\r
3c859dfe
RN
356 //\r
357 // Map the open file into a memory range\r
358 //\r
359 NtMapHandle = CreateFileMapping (\r
360 NtFileHandle,\r
361 NULL,\r
362 PAGE_EXECUTE_READWRITE,\r
363 0,\r
364 MapSize,\r
365 NULL\r
366 );\r
367 if (NtMapHandle == NULL) {\r
368 return EFI_DEVICE_ERROR;\r
369 }\r
a550d468 370\r
3c859dfe
RN
371 //\r
372 // Get the virtual address (address in the emulator) of the mapped file\r
373 //\r
374 VirtualAddress = MapViewOfFileEx (\r
a550d468
MK
375 NtMapHandle,\r
376 FILE_MAP_EXECUTE | FILE_MAP_ALL_ACCESS,\r
377 0,\r
378 0,\r
379 MapSize,\r
380 *BaseAddress\r
381 );\r
3c859dfe
RN
382 if (VirtualAddress == NULL) {\r
383 return EFI_DEVICE_ERROR;\r
384 }\r
385\r
386 if (MapSize == 0) {\r
387 //\r
388 // Seek to the end of the file to figure out the true file size.\r
389 //\r
390 FileSize = SetFilePointer (\r
a550d468
MK
391 NtFileHandle,\r
392 0,\r
393 NULL,\r
394 FILE_END\r
395 );\r
3c859dfe
RN
396 if (FileSize == -1) {\r
397 return EFI_DEVICE_ERROR;\r
398 }\r
399\r
400 *Length = FileSize;\r
401 } else {\r
402 *Length = MapSize;\r
403 }\r
404\r
405 *BaseAddress = VirtualAddress;\r
406\r
407 return EFI_SUCCESS;\r
408}\r
409\r
410INTN\r
411EFIAPI\r
412main (\r
a550d468
MK
413 IN INT Argc,\r
414 IN CHAR8 **Argv,\r
415 IN CHAR8 **Envp\r
3c859dfe 416 )\r
a550d468 417\r
3c859dfe
RN
418/*++\r
419\r
420Routine Description:\r
421 Main entry point to SEC for WinNt. This is a Windows program\r
422\r
423Arguments:\r
424 Argc - Number of command line arguments\r
425 Argv - Array of command line argument strings\r
426 Envp - Array of environment variable strings\r
427\r
428Returns:\r
429 0 - Normal exit\r
430 1 - Abnormal exit\r
431\r
432--*/\r
433{\r
a550d468
MK
434 EFI_STATUS Status;\r
435 HANDLE Token;\r
436 TOKEN_PRIVILEGES TokenPrivileges;\r
437 VOID *TemporaryRam;\r
438 UINT32 TemporaryRamSize;\r
439 VOID *EmuMagicPage;\r
440 UINTN Index;\r
441 UINTN Index1;\r
442 CHAR16 *FileName;\r
443 CHAR16 *FileNamePtr;\r
444 BOOLEAN Done;\r
445 EFI_PEI_FILE_HANDLE FileHandle;\r
446 VOID *SecFile;\r
447 CHAR16 *MemorySizeStr;\r
448 CHAR16 *FirmwareVolumesStr;\r
449 UINTN ProcessAffinityMask;\r
450 UINTN SystemAffinityMask;\r
451 INT32 LowBit;\r
7bee2498 452 UINTN ResetJumpCode;\r
22f73b6d 453 EMU_THUNK_PPI *SecEmuThunkPpi;\r
3c859dfe
RN
454\r
455 //\r
456 // Enable the privilege so that RTC driver can successfully run SetTime()\r
457 //\r
a550d468
MK
458 OpenProcessToken (GetCurrentProcess (), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &Token);\r
459 if (LookupPrivilegeValue (NULL, SE_TIME_ZONE_NAME, &TokenPrivileges.Privileges[0].Luid)) {\r
460 TokenPrivileges.PrivilegeCount = 1;\r
3c859dfe 461 TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;\r
a550d468 462 AdjustTokenPrivileges (Token, FALSE, &TokenPrivileges, 0, (PTOKEN_PRIVILEGES)NULL, 0);\r
3c859dfe
RN
463 }\r
464\r
a550d468
MK
465 MemorySizeStr = (CHAR16 *)PcdGetPtr (PcdEmuMemorySize);\r
466 FirmwareVolumesStr = (CHAR16 *)PcdGetPtr (PcdEmuFirmwareVolume);\r
3c859dfe 467\r
30b4abc6 468 SecPrint ("\n\rEDK II WIN Host Emulation Environment from http://www.tianocore.org/edk2/\n\r");\r
3c859dfe
RN
469\r
470 //\r
471 // Determine the first thread available to this process.\r
472 //\r
473 if (GetProcessAffinityMask (GetCurrentProcess (), &ProcessAffinityMask, &SystemAffinityMask)) {\r
2737037a 474 LowBit = (INT32)LowBitSet32 ((UINT32)ProcessAffinityMask);\r
3c859dfe
RN
475 if (LowBit != -1) {\r
476 //\r
477 // Force the system to bind the process to a single thread to work\r
478 // around odd semaphore type crashes.\r
479 //\r
480 SetProcessAffinityMask (GetCurrentProcess (), (INTN)(BIT0 << LowBit));\r
481 }\r
482 }\r
483\r
484 //\r
485 // Make some Windows calls to Set the process to the highest priority in the\r
486 // idle class. We need this to have good performance.\r
487 //\r
488 SetPriorityClass (GetCurrentProcess (), IDLE_PRIORITY_CLASS);\r
489 SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);\r
490\r
491 SecInitializeThunk ();\r
492 //\r
493 // PPIs pased into PEI_CORE\r
494 //\r
22f73b6d
ZL
495 SecEmuThunkPpi = AllocateZeroPool (sizeof (EMU_THUNK_PPI) + FixedPcdGet32 (PcdPersistentMemorySize));\r
496 if (SecEmuThunkPpi == NULL) {\r
497 SecPrint ("ERROR : Can not allocate memory for SecEmuThunkPpi. Exiting.\n");\r
498 exit (1);\r
499 }\r
500\r
501 CopyMem (SecEmuThunkPpi, &mSecEmuThunkPpi, sizeof (EMU_THUNK_PPI));\r
8a485e4b
ZL
502 SecEmuThunkPpi->Argc = Argc;\r
503 SecEmuThunkPpi->Argv = Argv;\r
504 SecEmuThunkPpi->Envp = Envp;\r
22f73b6d
ZL
505 SecEmuThunkPpi->PersistentMemorySize = FixedPcdGet32 (PcdPersistentMemorySize);\r
506 AddThunkPpi (EFI_PEI_PPI_DESCRIPTOR_PPI, &gEmuThunkPpiGuid, SecEmuThunkPpi);\r
7bee2498 507 AddThunkPpi (EFI_PEI_PPI_DESCRIPTOR_PPI, &gEfiPeiReset2PpiGuid, &mEmuReset2Ppi);\r
3c859dfe 508\r
7a465451
RN
509 //\r
510 // Emulator Bus Driver Thunks\r
511 //\r
512 AddThunkProtocol (&mWinNtWndThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuGop), TRUE);\r
56502bf1 513 AddThunkProtocol (&mWinNtFileSystemThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuFileSystem), TRUE);\r
8f819697 514 AddThunkProtocol (&mWinNtBlockIoThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuVirtualDisk), TRUE);\r
bb78cfbe 515 AddThunkProtocol (&mWinNtSnpThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuNetworkInterface), TRUE);\r
7a465451 516\r
3c859dfe
RN
517 //\r
518 // Allocate space for gSystemMemory Array\r
519 //\r
a550d468
MK
520 gSystemMemoryCount = CountSeparatorsInString (MemorySizeStr, '!') + 1;\r
521 gSystemMemory = calloc (gSystemMemoryCount, sizeof (NT_SYSTEM_MEMORY));\r
3c859dfe 522 if (gSystemMemory == NULL) {\r
30b4abc6 523 SecPrint ("ERROR : Can not allocate memory for %S. Exiting.\n\r", MemorySizeStr);\r
3c859dfe
RN
524 exit (1);\r
525 }\r
526\r
d2842bb6
RN
527 //\r
528 // Allocate "physical" memory space for emulator. It will be reported out later throuth MemoryAutoScan()\r
529 //\r
530 for (Index = 0, Done = FALSE; !Done; Index++) {\r
531 ASSERT (Index < gSystemMemoryCount);\r
532 gSystemMemory[Index].Size = ((UINT64)_wtoi (MemorySizeStr)) * ((UINT64)SIZE_1MB);\r
533 gSystemMemory[Index].Memory = (EFI_PHYSICAL_ADDRESS)(UINTN)VirtualAlloc (NULL, (SIZE_T)(gSystemMemory[Index].Size), MEM_COMMIT, PAGE_EXECUTE_READWRITE);\r
534 if (gSystemMemory[Index].Memory == 0) {\r
535 return EFI_OUT_OF_RESOURCES;\r
536 }\r
537\r
538 //\r
539 // Find the next region\r
540 //\r
541 for (Index1 = 0; MemorySizeStr[Index1] != '!' && MemorySizeStr[Index1] != 0; Index1++) {\r
542 }\r
543\r
544 if (MemorySizeStr[Index1] == 0) {\r
545 Done = TRUE;\r
546 }\r
547\r
548 MemorySizeStr = MemorySizeStr + Index1 + 1;\r
549 }\r
550\r
3c859dfe
RN
551 //\r
552 // Allocate space for gSystemMemory Array\r
553 //\r
a550d468
MK
554 gFdInfoCount = CountSeparatorsInString (FirmwareVolumesStr, '!') + 1;\r
555 gFdInfo = calloc (gFdInfoCount, sizeof (NT_FD_INFO));\r
3c859dfe 556 if (gFdInfo == NULL) {\r
30b4abc6 557 SecPrint ("ERROR : Can not allocate memory for %S. Exiting.\n\r", FirmwareVolumesStr);\r
3c859dfe
RN
558 exit (1);\r
559 }\r
a550d468 560\r
3c859dfe
RN
561 //\r
562 // Setup Boot Mode.\r
563 //\r
30b4abc6 564 SecPrint (" BootMode 0x%02x\n\r", PcdGet32 (PcdEmuBootMode));\r
3c859dfe
RN
565\r
566 //\r
567 // Allocate 128K memory to emulate temp memory for PEI.\r
568 // on a real platform this would be SRAM, or using the cache as RAM.\r
569 // Set TemporaryRam to zero so WinNtOpenFile will allocate a new mapping\r
570 //\r
571 TemporaryRamSize = TEMPORARY_RAM_SIZE;\r
a550d468 572 TemporaryRam = VirtualAlloc (NULL, (SIZE_T)(TemporaryRamSize), MEM_COMMIT, PAGE_EXECUTE_READWRITE);\r
3c859dfe 573 if (TemporaryRam == NULL) {\r
30b4abc6 574 SecPrint ("ERROR : Can not allocate enough space for SecStack\n\r");\r
3c859dfe
RN
575 exit (1);\r
576 }\r
a550d468 577\r
3c859dfe
RN
578 //\r
579 // If enabled use the magic page to communicate between modules\r
580 // This replaces the PI PeiServicesTable pointer mechanism that\r
581 // deos not work in the emulator. It also allows the removal of\r
582 // writable globals from SEC, PEI_CORE (libraries), PEIMs\r
583 //\r
584 EmuMagicPage = (VOID *)(UINTN)(FixedPcdGet64 (PcdPeiServicesTablePage) & MAX_UINTN);\r
585 if (EmuMagicPage != NULL) {\r
586 UINT64 Size;\r
587 Status = WinNtOpenFile (\r
a550d468
MK
588 NULL,\r
589 SIZE_4KB,\r
590 0,\r
591 &EmuMagicPage,\r
592 &Size\r
593 );\r
3c859dfe 594 if (EFI_ERROR (Status)) {\r
30b4abc6 595 SecPrint ("ERROR : Could not allocate PeiServicesTablePage @ %p\n\r", EmuMagicPage);\r
3c859dfe
RN
596 return EFI_DEVICE_ERROR;\r
597 }\r
598 }\r
599\r
600 //\r
601 // Open All the firmware volumes and remember the info in the gFdInfo global\r
602 // Meanwhile, find the SEC Core.\r
603 //\r
604 FileNamePtr = AllocateCopyPool (StrSize (FirmwareVolumesStr), FirmwareVolumesStr);\r
605 if (FileNamePtr == NULL) {\r
30b4abc6 606 SecPrint ("ERROR : Can not allocate memory for firmware volume string\n\r");\r
3c859dfe
RN
607 exit (1);\r
608 }\r
609\r
610 for (Done = FALSE, Index = 0, SecFile = NULL; !Done; Index++) {\r
611 FileName = FileNamePtr;\r
a550d468
MK
612 for (Index1 = 0; (FileNamePtr[Index1] != '!') && (FileNamePtr[Index1] != 0); Index1++) {\r
613 }\r
614\r
3c859dfe
RN
615 if (FileNamePtr[Index1] == 0) {\r
616 Done = TRUE;\r
617 } else {\r
a550d468
MK
618 FileNamePtr[Index1] = '\0';\r
619 FileNamePtr = &FileNamePtr[Index1 + 1];\r
3c859dfe
RN
620 }\r
621\r
622 //\r
623 // Open the FD and remember where it got mapped into our processes address space\r
624 //\r
625 Status = WinNtOpenFile (\r
a550d468
MK
626 FileName,\r
627 0,\r
628 OPEN_EXISTING,\r
629 &gFdInfo[Index].Address,\r
630 &gFdInfo[Index].Size\r
631 );\r
3c859dfe 632 if (EFI_ERROR (Status)) {\r
30b4abc6 633 SecPrint ("ERROR : Can not open Firmware Device File %S (0x%X). Exiting.\n\r", FileName, Status);\r
3c859dfe
RN
634 exit (1);\r
635 }\r
636\r
30b4abc6 637 SecPrint (" FD loaded from %S", FileName);\r
3c859dfe
RN
638\r
639 if (SecFile == NULL) {\r
640 //\r
641 // Assume the beginning of the FD is an FV and look for the SEC Core.\r
642 // Load the first one we find.\r
643 //\r
644 FileHandle = NULL;\r
a550d468
MK
645 Status = PeiServicesFfsFindNextFile (\r
646 EFI_FV_FILETYPE_SECURITY_CORE,\r
647 (EFI_PEI_FV_HANDLE)gFdInfo[Index].Address,\r
648 &FileHandle\r
649 );\r
3c859dfe
RN
650 if (!EFI_ERROR (Status)) {\r
651 Status = PeiServicesFfsFindSectionData (EFI_SECTION_PE32, FileHandle, &SecFile);\r
652 if (!EFI_ERROR (Status)) {\r
653 SecPrint (" contains SEC Core");\r
654 }\r
655 }\r
656 }\r
657\r
30b4abc6 658 SecPrint ("\n\r");\r
3c859dfe 659 }\r
a550d468 660\r
7bee2498
RN
661 ResetJumpCode = SetJump (&mResetJumpBuffer);\r
662\r
663 //\r
664 // Do not clear memory content for warm reset.\r
665 //\r
666 if (ResetJumpCode != EfiResetWarm + 1) {\r
667 SecPrint (" OS Emulator clearing temp RAM and physical RAM (to be discovered later)......\n\r");\r
668 SetMem32 (TemporaryRam, TemporaryRamSize, PcdGet32 (PcdInitValueInTempStack));\r
669 for (Index = 0; Index < gSystemMemoryCount; Index++) {\r
670 SetMem32 ((VOID *)(UINTN)gSystemMemory[Index].Memory, (UINTN)gSystemMemory[Index].Size, PcdGet32 (PcdInitValueInTempStack));\r
671 }\r
672 }\r
673\r
674 SecPrint (\r
675 " OS Emulator passing in %u KB of temp RAM at 0x%08lx to SEC\n\r",\r
676 TemporaryRamSize / SIZE_1KB,\r
677 TemporaryRam\r
678 );\r
3c859dfe
RN
679 //\r
680 // Hand off to SEC Core\r
681 //\r
682 SecLoadSecCore ((UINTN)TemporaryRam, TemporaryRamSize, gFdInfo[0].Address, gFdInfo[0].Size, SecFile);\r
683\r
684 //\r
685 // If we get here, then the SEC Core returned. This is an error as SEC should\r
686 // always hand off to PEI Core and then on to DXE Core.\r
687 //\r
30b4abc6 688 SecPrint ("ERROR : SEC returned\n\r");\r
3c859dfe
RN
689 exit (1);\r
690}\r
691\r
692VOID\r
693SecLoadSecCore (\r
a550d468
MK
694 IN UINTN TemporaryRam,\r
695 IN UINTN TemporaryRamSize,\r
696 IN VOID *BootFirmwareVolumeBase,\r
697 IN UINTN BootFirmwareVolumeSize,\r
698 IN VOID *SecCorePe32File\r
3c859dfe 699 )\r
a550d468 700\r
3c859dfe
RN
701/*++\r
702\r
703Routine Description:\r
704 This is the service to load the SEC Core from the Firmware Volume\r
705\r
706Arguments:\r
707 TemporaryRam - Memory to use for SEC.\r
708 TemporaryRamSize - Size of Memory to use for SEC\r
709 BootFirmwareVolumeBase - Start of the Boot FV\r
710 SecCorePe32File - SEC Core PE32\r
711\r
712Returns:\r
3d6b7fd3 713 Success means control is transferred and thus we should never return\r
3c859dfe
RN
714\r
715--*/\r
716{\r
a550d468
MK
717 EFI_STATUS Status;\r
718 VOID *TopOfStack;\r
719 VOID *SecCoreEntryPoint;\r
720 EFI_SEC_PEI_HAND_OFF *SecCoreData;\r
721 UINTN SecStackSize;\r
3c859dfe
RN
722\r
723 //\r
724 // Compute Top Of Memory for Stack and PEI Core Allocations\r
725 //\r
726 SecStackSize = TemporaryRamSize >> 1;\r
727\r
728 //\r
729 // |-----------| <---- TemporaryRamBase + TemporaryRamSize\r
730 // | Heap |\r
731 // | |\r
732 // |-----------| <---- StackBase / PeiTemporaryMemoryBase\r
733 // | |\r
734 // | Stack |\r
735 // |-----------| <---- TemporaryRamBase\r
736 //\r
a550d468 737 TopOfStack = (VOID *)(TemporaryRam + SecStackSize);\r
3c859dfe
RN
738\r
739 //\r
740 // Reservet space for storing PeiCore's parament in stack.\r
741 //\r
a550d468
MK
742 TopOfStack = (VOID *)((UINTN)TopOfStack - sizeof (EFI_SEC_PEI_HAND_OFF) - CPU_STACK_ALIGNMENT);\r
743 TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);\r
3c859dfe
RN
744\r
745 //\r
746 // Bind this information into the SEC hand-off state\r
747 //\r
a550d468 748 SecCoreData = (EFI_SEC_PEI_HAND_OFF *)(UINTN)TopOfStack;\r
3c859dfe
RN
749 SecCoreData->DataSize = sizeof (EFI_SEC_PEI_HAND_OFF);\r
750 SecCoreData->BootFirmwareVolumeBase = BootFirmwareVolumeBase;\r
751 SecCoreData->BootFirmwareVolumeSize = BootFirmwareVolumeSize;\r
a550d468 752 SecCoreData->TemporaryRamBase = (VOID *)TemporaryRam;\r
3c859dfe
RN
753 SecCoreData->TemporaryRamSize = TemporaryRamSize;\r
754 SecCoreData->StackBase = SecCoreData->TemporaryRamBase;\r
755 SecCoreData->StackSize = SecStackSize;\r
a550d468 756 SecCoreData->PeiTemporaryRamBase = (VOID *)((UINTN)SecCoreData->TemporaryRamBase + SecStackSize);\r
3c859dfe
RN
757 SecCoreData->PeiTemporaryRamSize = TemporaryRamSize - SecStackSize;\r
758\r
759 //\r
760 // Load the PEI Core from a Firmware Volume\r
761 //\r
762 Status = SecPeCoffGetEntryPoint (\r
a550d468
MK
763 SecCorePe32File,\r
764 &SecCoreEntryPoint\r
765 );\r
3c859dfe 766 if (EFI_ERROR (Status)) {\r
a550d468 767 return;\r
3c859dfe
RN
768 }\r
769\r
770 //\r
771 // Transfer control to the SEC Core\r
772 //\r
773 SwitchStack (\r
f4eaaf1a 774 (SWITCH_STACK_ENTRY_POINT)(UINTN)SecCoreEntryPoint,\r
3c859dfe
RN
775 SecCoreData,\r
776 GetThunkPpiList (),\r
777 TopOfStack\r
778 );\r
779 //\r
780 // If we get here, then the SEC Core returned. This is an error\r
781 //\r
a550d468 782 return;\r
3c859dfe
RN
783}\r
784\r
785RETURN_STATUS\r
786EFIAPI\r
787SecPeCoffGetEntryPoint (\r
788 IN VOID *Pe32Data,\r
789 IN OUT VOID **EntryPoint\r
790 )\r
791{\r
a550d468
MK
792 EFI_STATUS Status;\r
793 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
3c859dfe
RN
794\r
795 ZeroMem (&ImageContext, sizeof (ImageContext));\r
a550d468 796 ImageContext.Handle = Pe32Data;\r
3c859dfe 797\r
a550d468 798 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)SecImageRead;\r
3c859dfe 799\r
a550d468 800 Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
3c859dfe
RN
801 if (EFI_ERROR (Status)) {\r
802 return Status;\r
803 }\r
a550d468 804\r
3c859dfe 805 //\r
a121165e 806 // XIP for SEC and PEI_CORE\r
3c859dfe 807 //\r
a121165e 808 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Pe32Data;\r
3c859dfe
RN
809\r
810 Status = PeCoffLoaderLoadImage (&ImageContext);\r
811 if (EFI_ERROR (Status)) {\r
812 return Status;\r
813 }\r
814\r
815 Status = PeCoffLoaderRelocateImage (&ImageContext);\r
816 if (EFI_ERROR (Status)) {\r
817 return Status;\r
818 }\r
819\r
a550d468 820 *EntryPoint = (VOID *)(UINTN)ImageContext.EntryPoint;\r
3c859dfe
RN
821\r
822 return EFI_SUCCESS;\r
823}\r
824\r
825EFI_STATUS\r
826EFIAPI\r
827SecImageRead (\r
a550d468
MK
828 IN VOID *FileHandle,\r
829 IN UINTN FileOffset,\r
830 IN OUT UINTN *ReadSize,\r
831 OUT VOID *Buffer\r
3c859dfe 832 )\r
a550d468 833\r
3c859dfe
RN
834/*++\r
835\r
836Routine Description:\r
837 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file\r
838\r
839Arguments:\r
840 FileHandle - The handle to the PE/COFF file\r
841 FileOffset - The offset, in bytes, into the file to read\r
842 ReadSize - The number of bytes to read from the file starting at FileOffset\r
843 Buffer - A pointer to the buffer to read the data into.\r
844\r
845Returns:\r
846 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset\r
847\r
848--*/\r
849{\r
a550d468
MK
850 CHAR8 *Destination8;\r
851 CHAR8 *Source8;\r
852 UINTN Length;\r
3c859dfe 853\r
a550d468
MK
854 Destination8 = Buffer;\r
855 Source8 = (CHAR8 *)((UINTN)FileHandle + FileOffset);\r
856 Length = *ReadSize;\r
3c859dfe
RN
857 while (Length--) {\r
858 *(Destination8++) = *(Source8++);\r
859 }\r
860\r
861 return EFI_SUCCESS;\r
862}\r
863\r
864CHAR16 *\r
865AsciiToUnicode (\r
a550d468
MK
866 IN CHAR8 *Ascii,\r
867 IN UINTN *StrLen OPTIONAL\r
3c859dfe 868 )\r
a550d468 869\r
3c859dfe
RN
870/*++\r
871\r
872Routine Description:\r
873 Convert the passed in Ascii string to Unicode.\r
874 Optionally return the length of the strings.\r
875\r
876Arguments:\r
877 Ascii - Ascii string to convert\r
878 StrLen - Length of string\r
879\r
880Returns:\r
881 Pointer to malloc'ed Unicode version of Ascii\r
882\r
883--*/\r
884{\r
885 UINTN Index;\r
886 CHAR16 *Unicode;\r
887\r
888 //\r
889 // Allocate a buffer for unicode string\r
890 //\r
a550d468
MK
891 for (Index = 0; Ascii[Index] != '\0'; Index++) {\r
892 }\r
893\r
3c859dfe
RN
894 Unicode = malloc ((Index + 1) * sizeof (CHAR16));\r
895 if (Unicode == NULL) {\r
896 return NULL;\r
897 }\r
898\r
899 for (Index = 0; Ascii[Index] != '\0'; Index++) {\r
a550d468 900 Unicode[Index] = (CHAR16)Ascii[Index];\r
3c859dfe
RN
901 }\r
902\r
903 Unicode[Index] = '\0';\r
904\r
905 if (StrLen != NULL) {\r
906 *StrLen = Index;\r
907 }\r
908\r
909 return Unicode;\r
910}\r
911\r
912UINTN\r
913CountSeparatorsInString (\r
a550d468
MK
914 IN CONST CHAR16 *String,\r
915 IN CHAR16 Separator\r
3c859dfe 916 )\r
a550d468 917\r
3c859dfe
RN
918/*++\r
919\r
920Routine Description:\r
921 Count the number of separators in String\r
922\r
923Arguments:\r
924 String - String to process\r
925 Separator - Item to count\r
926\r
927Returns:\r
928 Number of Separator in String\r
929\r
930--*/\r
931{\r
a550d468 932 UINTN Count;\r
3c859dfe
RN
933\r
934 for (Count = 0; *String != '\0'; String++) {\r
935 if (*String == Separator) {\r
936 Count++;\r
937 }\r
938 }\r
939\r
940 return Count;\r
941}\r
942\r
10ccc27c
MK
943/**\r
944 Store the ModHandle in an array indexed by the Pdb File name.\r
945 The ModHandle is needed to unload the image.\r
946 @param ImageContext - Input data returned from PE Laoder Library. Used to find the\r
947 .PDB file name of the PE Image.\r
948 @param ModHandle - Returned from LoadLibraryEx() and stored for call to\r
949 FreeLibrary().\r
950 @return return EFI_SUCCESS when ModHandle was stored.\r
951--*/\r
952EFI_STATUS\r
953AddModHandle (\r
a550d468
MK
954 IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,\r
955 IN VOID *ModHandle\r
10ccc27c
MK
956 )\r
957\r
958{\r
959 UINTN Index;\r
960 PDB_NAME_TO_MOD_HANDLE *Array;\r
961 UINTN PreviousSize;\r
962 PDB_NAME_TO_MOD_HANDLE *TempArray;\r
963 HANDLE Handle;\r
964 UINTN Size;\r
965\r
966 //\r
967 // Return EFI_ALREADY_STARTED if this DLL has already been loaded\r
968 //\r
969 Array = mPdbNameModHandleArray;\r
970 for (Index = 0; Index < mPdbNameModHandleArraySize; Index++, Array++) {\r
a550d468 971 if ((Array->PdbPointer != NULL) && (Array->ModHandle == ModHandle)) {\r
10ccc27c
MK
972 return EFI_ALREADY_STARTED;\r
973 }\r
974 }\r
975\r
976 Array = mPdbNameModHandleArray;\r
977 for (Index = 0; Index < mPdbNameModHandleArraySize; Index++, Array++) {\r
978 if (Array->PdbPointer == NULL) {\r
979 //\r
980 // Make a copy of the stirng and store the ModHandle\r
981 //\r
a550d468
MK
982 Handle = GetProcessHeap ();\r
983 Size = AsciiStrLen (ImageContext->PdbPointer) + 1;\r
984 Array->PdbPointer = HeapAlloc (Handle, HEAP_ZERO_MEMORY, Size);\r
10ccc27c
MK
985 ASSERT (Array->PdbPointer != NULL);\r
986\r
987 AsciiStrCpyS (Array->PdbPointer, Size, ImageContext->PdbPointer);\r
988 Array->ModHandle = ModHandle;\r
989 return EFI_SUCCESS;\r
990 }\r
991 }\r
992\r
993 //\r
994 // No free space in mPdbNameModHandleArray so grow it by\r
995 // MAX_PDB_NAME_TO_MOD_HANDLE_ARRAY_SIZE entires.\r
996 //\r
a550d468 997 PreviousSize = mPdbNameModHandleArraySize * sizeof (PDB_NAME_TO_MOD_HANDLE);\r
10ccc27c
MK
998 mPdbNameModHandleArraySize += MAX_PDB_NAME_TO_MOD_HANDLE_ARRAY_SIZE;\r
999 //\r
1000 // re-allocate a new buffer and copy the old values to the new locaiton.\r
1001 //\r
a550d468
MK
1002 TempArray = HeapAlloc (\r
1003 GetProcessHeap (),\r
1004 HEAP_ZERO_MEMORY,\r
1005 mPdbNameModHandleArraySize * sizeof (PDB_NAME_TO_MOD_HANDLE)\r
1006 );\r
10ccc27c 1007\r
a550d468 1008 CopyMem ((VOID *)(UINTN)TempArray, (VOID *)(UINTN)mPdbNameModHandleArray, PreviousSize);\r
10ccc27c
MK
1009\r
1010 HeapFree (GetProcessHeap (), 0, mPdbNameModHandleArray);\r
1011\r
1012 mPdbNameModHandleArray = TempArray;\r
1013 if (mPdbNameModHandleArray == NULL) {\r
1014 ASSERT (FALSE);\r
1015 return EFI_OUT_OF_RESOURCES;\r
1016 }\r
1017\r
1018 return AddModHandle (ImageContext, ModHandle);\r
1019}\r
1020\r
1021/**\r
1022 Return the ModHandle and delete the entry in the array.\r
1023 @param ImageContext - Input data returned from PE Laoder Library. Used to find the\r
1024 .PDB file name of the PE Image.\r
1025 @return\r
1026 ModHandle - ModHandle assoicated with ImageContext is returned\r
1027 NULL - No ModHandle associated with ImageContext\r
1028**/\r
1029VOID *\r
1030RemoveModHandle (\r
a550d468 1031 IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
10ccc27c
MK
1032 )\r
1033{\r
1034 UINTN Index;\r
1035 PDB_NAME_TO_MOD_HANDLE *Array;\r
1036\r
1037 if (ImageContext->PdbPointer == NULL) {\r
1038 //\r
1039 // If no PDB pointer there is no ModHandle so return NULL\r
1040 //\r
1041 return NULL;\r
1042 }\r
1043\r
1044 Array = mPdbNameModHandleArray;\r
1045 for (Index = 0; Index < mPdbNameModHandleArraySize; Index++, Array++) {\r
a550d468 1046 if ((Array->PdbPointer != NULL) && (AsciiStrCmp (Array->PdbPointer, ImageContext->PdbPointer) == 0)) {\r
10ccc27c
MK
1047 //\r
1048 // If you find a match return it and delete the entry\r
1049 //\r
1050 HeapFree (GetProcessHeap (), 0, Array->PdbPointer);\r
1051 Array->PdbPointer = NULL;\r
1052 return Array->ModHandle;\r
1053 }\r
1054 }\r
1055\r
1056 return NULL;\r
1057}\r
3c859dfe
RN
1058\r
1059VOID\r
1060EFIAPI\r
1061PeCoffLoaderRelocateImageExtraAction (\r
a550d468 1062 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
3c859dfe
RN
1063 )\r
1064{\r
a550d468
MK
1065 EFI_STATUS Status;\r
1066 VOID *DllEntryPoint;\r
1067 CHAR16 *DllFileName;\r
1068 HMODULE Library;\r
1069 UINTN Index;\r
3c859dfe
RN
1070\r
1071 ASSERT (ImageContext != NULL);\r
1072 //\r
1073 // If we load our own PE COFF images the Windows debugger can not source\r
10ccc27c 1074 // level debug our code. If a valid PDB pointer exists use it to load\r
3c859dfe
RN
1075 // the *.dll file as a library using Windows* APIs. This allows\r
1076 // source level debug. The image is still loaded and relocated\r
1077 // in the Framework memory space like on a real system (by the code above),\r
3d6b7fd3 1078 // but the entry point points into the DLL loaded by the code below.\r
3c859dfe
RN
1079 //\r
1080\r
1081 DllEntryPoint = NULL;\r
1082\r
1083 //\r
1084 // Load the DLL if it's not an EBC image.\r
1085 //\r
1086 if ((ImageContext->PdbPointer != NULL) &&\r
a550d468
MK
1087 (ImageContext->Machine != EFI_IMAGE_MACHINE_EBC))\r
1088 {\r
3c859dfe
RN
1089 //\r
1090 // Convert filename from ASCII to Unicode\r
1091 //\r
1092 DllFileName = AsciiToUnicode (ImageContext->PdbPointer, &Index);\r
1093\r
1094 //\r
1095 // Check that we have a valid filename\r
1096 //\r
a550d468 1097 if ((Index < 5) || (DllFileName[Index - 4] != '.')) {\r
3c859dfe
RN
1098 free (DllFileName);\r
1099\r
1100 //\r
1101 // Never return an error if PeCoffLoaderRelocateImage() succeeded.\r
1102 // The image will run, but we just can't source level debug. If we\r
1103 // return an error the image will not run.\r
1104 //\r
1105 return;\r
1106 }\r
a550d468 1107\r
3c859dfe
RN
1108 //\r
1109 // Replace .PDB with .DLL on the filename\r
1110 //\r
a550d468
MK
1111 DllFileName[Index - 3] = 'D';\r
1112 DllFileName[Index - 2] = 'L';\r
1113 DllFileName[Index - 1] = 'L';\r
3c859dfe
RN
1114\r
1115 //\r
1116 // Load the .DLL file into the user process's address space for source\r
1117 // level debug\r
1118 //\r
1119 Library = LoadLibraryEx (DllFileName, NULL, DONT_RESOLVE_DLL_REFERENCES);\r
1120 if (Library != NULL) {\r
1121 //\r
1122 // InitializeDriver is the entry point we put in all our EFI DLL's. The\r
1123 // DONT_RESOLVE_DLL_REFERENCES argument to LoadLIbraryEx() suppresses the\r
1124 // normal DLL entry point of DllMain, and prevents other modules that are\r
1125 // referenced in side the DllFileName from being loaded. There is no error\r
1126 // checking as the we can point to the PE32 image loaded by Tiano. This\r
1127 // step is only needed for source level debugging\r
1128 //\r
a550d468 1129 DllEntryPoint = (VOID *)(UINTN)GetProcAddress (Library, "InitializeDriver");\r
3c859dfe
RN
1130 }\r
1131\r
1132 if ((Library != NULL) && (DllEntryPoint != NULL)) {\r
10ccc27c
MK
1133 Status = AddModHandle (ImageContext, Library);\r
1134 if (Status == EFI_ALREADY_STARTED) {\r
1135 //\r
1136 // If the DLL has already been loaded before, then this instance of the DLL can not be debugged.\r
1137 //\r
1138 ImageContext->PdbPointer = NULL;\r
1139 SecPrint ("WARNING: DLL already loaded. No source level debug %S.\n\r", DllFileName);\r
1140 } else {\r
1141 //\r
1142 // This DLL is not already loaded, so source level debugging is supported.\r
1143 //\r
a550d468 1144 ImageContext->EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)DllEntryPoint;\r
10ccc27c
MK
1145 SecPrint ("LoadLibraryEx (\n\r %S,\n\r NULL, DONT_RESOLVE_DLL_REFERENCES)\n\r", DllFileName);\r
1146 }\r
3c859dfe 1147 } else {\r
10ccc27c 1148 SecPrint ("WARNING: No source level debug %S. \n\r", DllFileName);\r
3c859dfe
RN
1149 }\r
1150\r
1151 free (DllFileName);\r
1152 }\r
1153}\r
1154\r
1155VOID\r
1156EFIAPI\r
1157PeCoffLoaderUnloadImageExtraAction (\r
10ccc27c 1158 IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
a550d468 1159 )\r
3c859dfe 1160{\r
10ccc27c
MK
1161 VOID *ModHandle;\r
1162\r
3c859dfe 1163 ASSERT (ImageContext != NULL);\r
3c859dfe 1164\r
10ccc27c
MK
1165 ModHandle = RemoveModHandle (ImageContext);\r
1166 if (ModHandle != NULL) {\r
1167 FreeLibrary (ModHandle);\r
1168 SecPrint ("FreeLibrary (\n\r %s)\n\r", ImageContext->PdbPointer);\r
1169 } else {\r
1170 SecPrint ("WARNING: Unload image without source level debug\n\r");\r
1171 }\r
1172}\r
3c859dfe
RN
1173\r
1174VOID\r
1175_ModuleEntryPoint (\r
1176 VOID\r
1177 )\r
1178{\r
1179}\r