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