TianoCore EDK2 master
Loading...
Searching...
No Matches
Host.c
1/*++ @file
2
3Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.<BR>
4Portions copyright (c) 2008 - 2011, Apple Inc. All rights reserved.<BR>
5SPDX-License-Identifier: BSD-2-Clause-Patent
6
7**/
8
9#include "Host.h"
10
11#ifdef __APPLE__
12#define MAP_ANONYMOUS MAP_ANON
13#endif
14
15//
16// Globals
17//
18
19EMU_THUNK_PPI mSecEmuThunkPpi = {
20 GasketSecUnixPeiAutoScan,
21 GasketSecUnixFdAddress,
22 GasketSecEmuThunkAddress
23};
24
25char *gGdbWorkingFileName = NULL;
26unsigned int mScriptSymbolChangesCount = 0;
27
28//
29// Default information about where the FD is located.
30// This array gets filled in with information from EFI_FIRMWARE_VOLUMES
31// EFI_FIRMWARE_VOLUMES is a host environment variable set by system.cmd.
32// The number of array elements is allocated base on parsing
33// EFI_FIRMWARE_VOLUMES and the memory is never freed.
34//
35UINTN gFdInfoCount = 0;
36EMU_FD_INFO *gFdInfo;
37
38//
39// Array that supports separate memory ranges.
40// The memory ranges are set in system.cmd via the EFI_MEMORY_SIZE variable.
41// The number of array elements is allocated base on parsing
42// EFI_MEMORY_SIZE and the memory is never freed.
43//
44UINTN gSystemMemoryCount = 0;
45EMU_SYSTEM_MEMORY *gSystemMemory;
46
47UINTN mImageContextModHandleArraySize = 0;
48IMAGE_CONTEXT_TO_MOD_HANDLE *mImageContextModHandleArray = NULL;
49
51
52int gInXcode = 0;
53
54/*++
55 Breakpoint target for Xcode project. Set in the Xcode XML
56
57 Xcode breakpoint will 'source Host.gdb'
58 gGdbWorkingFileName is set to Host.gdb
59
60**/
61VOID
62SecGdbConfigBreak (
63 VOID
64 )
65{
66}
67
68/*++
69
70Routine Description:
71 Main entry point to SEC for Unix. This is a unix program
72
73Arguments:
74 Argc - Number of command line arguments
75 Argv - Array of command line argument strings
76 Envp - Array of environment variable strings
77
78Returns:
79 0 - Normal exit
80 1 - Abnormal exit
81
82**/
83int
84main (
85 IN int Argc,
86 IN char **Argv,
87 IN char **Envp
88 )
89{
90 EFI_STATUS Status;
91 EFI_PHYSICAL_ADDRESS InitialStackMemory;
92 UINT64 InitialStackMemorySize;
93 UINTN Index;
94 UINTN Index1;
95 UINTN Index2;
96 UINTN PeiIndex;
97 CHAR8 *FileName;
98 BOOLEAN Done;
99 EFI_PEI_FILE_HANDLE FileHandle;
100 VOID *SecFile;
101 CHAR16 *MemorySizeStr;
102 CHAR16 *FirmwareVolumesStr;
103 UINTN *StackPointer;
104 FILE *GdbTempFile;
105 EMU_THUNK_PPI *SecEmuThunkPpi;
106
107 //
108 // Xcode does not support sourcing gdb scripts directly, so the Xcode XML
109 // has a break point script to source the GdbRun.sh script.
110 //
111 SecGdbConfigBreak ();
112
113 //
114 // If dlopen doesn't work, then we build a gdb script to allow the
115 // symbols to be loaded.
116 //
117 Index = strlen (*Argv);
118 gGdbWorkingFileName = AllocatePool (Index + strlen (".gdb") + 1);
119 strcpy (gGdbWorkingFileName, *Argv);
120 strcat (gGdbWorkingFileName, ".gdb");
121
122 //
123 // Empty out the gdb symbols script file.
124 //
125 GdbTempFile = fopen (gGdbWorkingFileName, "w");
126 if (GdbTempFile != NULL) {
127 fclose (GdbTempFile);
128 }
129
130 printf ("\nEDK II UNIX Host Emulation Environment from http://www.tianocore.org/edk2/\n");
131
132 setbuf (stdout, 0);
133 setbuf (stderr, 0);
134
135 MemorySizeStr = (CHAR16 *)PcdGetPtr (PcdEmuMemorySize);
136 FirmwareVolumesStr = (CHAR16 *)PcdGetPtr (PcdEmuFirmwareVolume);
137
138 //
139 // PPIs pased into PEI_CORE
140 //
141 SecEmuThunkPpi = AllocateZeroPool (sizeof (EMU_THUNK_PPI) + FixedPcdGet32 (PcdPersistentMemorySize));
142 if (SecEmuThunkPpi == NULL) {
143 printf ("ERROR : Can not allocate memory for SecEmuThunkPpi. Exiting.\n");
144 exit (1);
145 }
146
147 CopyMem (SecEmuThunkPpi, &mSecEmuThunkPpi, sizeof (EMU_THUNK_PPI));
148 SecEmuThunkPpi->Argc = Argc;
149 SecEmuThunkPpi->Argv = Argv;
150 SecEmuThunkPpi->Envp = Envp;
151 SecEmuThunkPpi->PersistentMemorySize = FixedPcdGet32 (PcdPersistentMemorySize);
152 AddThunkPpi (EFI_PEI_PPI_DESCRIPTOR_PPI, &gEmuThunkPpiGuid, SecEmuThunkPpi);
153
154 SecInitThunkProtocol ();
155
156 //
157 // Emulator Bus Driver Thunks
158 //
159 AddThunkProtocol (&gX11ThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuGop), TRUE);
160 AddThunkProtocol (&gPosixFileSystemThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuFileSystem), TRUE);
161 AddThunkProtocol (&gBlockIoThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuVirtualDisk), TRUE);
162 AddThunkProtocol (&gSnpThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuNetworkInterface), TRUE);
163
164 //
165 // Emulator other Thunks
166 //
167 AddThunkProtocol (&gPthreadThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuApCount), FALSE);
168
169 // EmuSecLibConstructor ();
170
171 gPpiList = GetThunkPpiList ();
172
173 //
174 // Allocate space for gSystemMemory Array
175 //
176 gSystemMemoryCount = CountSeparatorsInString (MemorySizeStr, '!') + 1;
177 gSystemMemory = AllocateZeroPool (gSystemMemoryCount * sizeof (EMU_SYSTEM_MEMORY));
178 if (gSystemMemory == NULL) {
179 printf ("ERROR : Can not allocate memory for system. Exiting.\n");
180 exit (1);
181 }
182
183 //
184 // Allocate space for gSystemMemory Array
185 //
186 gFdInfoCount = CountSeparatorsInString (FirmwareVolumesStr, '!') + 1;
187 gFdInfo = AllocateZeroPool (gFdInfoCount * sizeof (EMU_FD_INFO));
188 if (gFdInfo == NULL) {
189 printf ("ERROR : Can not allocate memory for fd info. Exiting.\n");
190 exit (1);
191 }
192
193 printf (" BootMode 0x%02x\n", (unsigned int)PcdGet32 (PcdEmuBootMode));
194
195 //
196 // Open up a 128K file to emulate temp memory for SEC.
197 // on a real platform this would be SRAM, or using the cache as RAM.
198 // Set InitialStackMemory to zero so UnixOpenFile will allocate a new mapping
199 //
200 InitialStackMemorySize = STACK_SIZE;
201 InitialStackMemory = (UINTN)MapMemory (
202 0,
203 (UINT32)InitialStackMemorySize,
204 PROT_READ | PROT_WRITE | PROT_EXEC,
205 MAP_ANONYMOUS | MAP_PRIVATE
206 );
207 if (InitialStackMemory == 0) {
208 printf ("ERROR : Can not open SecStack Exiting\n");
209 exit (1);
210 }
211
212 printf (
213 " OS Emulator passing in %u KB of temp RAM at 0x%08lx to SEC\n",
214 (unsigned int)(InitialStackMemorySize / 1024),
215 (unsigned long)InitialStackMemory
216 );
217
218 for (StackPointer = (UINTN *)(UINTN)InitialStackMemory;
219 StackPointer < (UINTN *)(UINTN)((UINTN)InitialStackMemory + (UINT64)InitialStackMemorySize);
220 StackPointer++)
221 {
222 *StackPointer = 0x5AA55AA5;
223 }
224
225 //
226 // Open All the firmware volumes and remember the info in the gFdInfo global
227 //
228 FileName = (CHAR8 *)AllocatePool (StrLen (FirmwareVolumesStr) + 1);
229 if (FileName == NULL) {
230 printf ("ERROR : Can not allocate memory for firmware volume string\n");
231 exit (1);
232 }
233
234 Index2 = 0;
235 for (Done = FALSE, Index = 0, PeiIndex = 0, SecFile = NULL;
236 FirmwareVolumesStr[Index2] != 0;
237 Index++)
238 {
239 for (Index1 = 0; (FirmwareVolumesStr[Index2] != '!') && (FirmwareVolumesStr[Index2] != 0); Index2++) {
240 FileName[Index1++] = FirmwareVolumesStr[Index2];
241 }
242
243 if (FirmwareVolumesStr[Index2] == '!') {
244 Index2++;
245 }
246
247 FileName[Index1] = '\0';
248
249 if (Index == 0) {
250 // Map FV Recovery Read Only and other areas Read/Write
251 Status = MapFd0 (
252 FileName,
253 &gFdInfo[0].Address,
254 &gFdInfo[0].Size
255 );
256 } else {
257 //
258 // Open the FD and remember where it got mapped into our processes address space
259 // Maps Read Only
260 //
261 Status = MapFile (
262 FileName,
263 &gFdInfo[Index].Address,
264 &gFdInfo[Index].Size
265 );
266 }
267
268 if (EFI_ERROR (Status)) {
269 printf ("ERROR : Can not open Firmware Device File %s (%x). Exiting.\n", FileName, (unsigned int)Status);
270 exit (1);
271 }
272
273 printf (" FD loaded from %s at 0x%08lx", FileName, (unsigned long)gFdInfo[Index].Address);
274
275 if (SecFile == NULL) {
276 //
277 // Assume the beginning of the FD is an FV and look for the SEC Core.
278 // Load the first one we find.
279 //
280 FileHandle = NULL;
282 EFI_FV_FILETYPE_SECURITY_CORE,
283 (EFI_PEI_FV_HANDLE)(UINTN)gFdInfo[Index].Address,
284 &FileHandle
285 );
286 if (!EFI_ERROR (Status)) {
287 Status = PeiServicesFfsFindSectionData (EFI_SECTION_PE32, FileHandle, &SecFile);
288 if (!EFI_ERROR (Status)) {
289 PeiIndex = Index;
290 printf (" contains SEC Core");
291 }
292 }
293 }
294
295 printf ("\n");
296 }
297
298 if (SecFile == NULL) {
299 printf ("ERROR : SEC not found!\n");
300 exit (1);
301 }
302
303 //
304 // Calculate memory regions and store the information in the gSystemMemory
305 // global for later use. The autosizing code will use this data to
306 // map this memory into the SEC process memory space.
307 //
308 Index1 = 0;
309 Index = 0;
310 while (1) {
311 UINTN val = 0;
312 //
313 // Save the size of the memory.
314 //
315 while (MemorySizeStr[Index1] >= '0' && MemorySizeStr[Index1] <= '9') {
316 val = val * 10 + MemorySizeStr[Index1] - '0';
317 Index1++;
318 }
319
320 gSystemMemory[Index++].Size = val * 0x100000;
321 if (MemorySizeStr[Index1] == 0) {
322 break;
323 }
324
325 Index1++;
326 }
327
328 printf ("\n");
329
330 //
331 // Hand off to SEC
332 //
333 SecLoadFromCore ((UINTN)InitialStackMemory, (UINTN)InitialStackMemorySize, (UINTN)gFdInfo[0].Address, SecFile);
334
335 //
336 // If we get here, then the SEC Core returned. This is an error as SEC should
337 // always hand off to PEI Core and then on to DXE Core.
338 //
339 printf ("ERROR : SEC returned\n");
340 exit (1);
341}
342
344MapMemory (
345 IN INTN fd,
346 IN UINT64 length,
347 IN INTN prot,
348 IN INTN flags
349 )
350{
351 STATIC UINTN base = 0x40000000;
352 CONST UINTN align = (1 << 24);
353 VOID *res = NULL;
354 BOOLEAN isAligned = 0;
355
356 //
357 // Try to get an aligned block somewhere in the address space of this
358 // process.
359 //
360 while ((!isAligned) && (base != 0)) {
361 res = mmap ((void *)base, length, prot, flags, fd, 0);
362 if (res == MAP_FAILED) {
363 return NULL;
364 }
365
366 if ((((UINTN)res) & ~(align-1)) == (UINTN)res) {
367 isAligned = 1;
368 } else {
369 munmap (res, length);
370 base += align;
371 }
372 }
373
374 return res;
375}
376
377/*++
378
379Routine Description:
380 Opens and memory maps a file using Unix services. If BaseAddress is non zero
381 the process will try and allocate the memory starting at BaseAddress.
382
383Arguments:
384 FileName - The name of the file to open and map
385 MapSize - The amount of the file to map in bytes
386 CreationDisposition - The flags to pass to CreateFile(). Use to create new files for
387 memory emulation, and exiting files for firmware volume emulation
388 BaseAddress - The base address of the mapped file in the user address space.
389 If passed in as NULL the a new memory region is used.
390 If passed in as non NULL the request memory region is used for
391 the mapping of the file into the process space.
392 Length - The size of the mapped region in bytes
393
394Returns:
395 EFI_SUCCESS - The file was opened and mapped.
396 EFI_NOT_FOUND - FileName was not found in the current directory
397 EFI_DEVICE_ERROR - An error occurred attempting to map the opened file
398
399**/
401MapFile (
402 IN CHAR8 *FileName,
403 IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
404 OUT UINT64 *Length
405 )
406{
407 int fd;
408 VOID *res;
409 UINTN FileSize;
410
411 fd = open (FileName, O_RDWR);
412 if (fd < 0) {
413 return EFI_NOT_FOUND;
414 }
415
416 FileSize = lseek (fd, 0, SEEK_END);
417
418 res = MapMemory (fd, FileSize, PROT_READ | PROT_EXEC, MAP_PRIVATE);
419
420 close (fd);
421
422 if (res == NULL) {
423 perror ("MapFile() Failed");
424 return EFI_DEVICE_ERROR;
425 }
426
427 *Length = (UINT64)FileSize;
428 *BaseAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)res;
429
430 return EFI_SUCCESS;
431}
432
434MapFd0 (
435 IN CHAR8 *FileName,
436 IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
437 OUT UINT64 *Length
438 )
439{
440 int fd;
441 void *res, *res2, *res3;
442 UINTN FileSize;
443 UINTN FvSize;
444 void *EmuMagicPage;
445
446 fd = open (FileName, O_RDWR);
447 if (fd < 0) {
448 return EFI_NOT_FOUND;
449 }
450
451 FileSize = lseek (fd, 0, SEEK_END);
452
453 FvSize = FixedPcdGet64 (PcdEmuFlashFvRecoverySize);
454
455 // Assume start of FD is Recovery FV, and make it write protected
456 res = mmap (
457 (void *)(UINTN)FixedPcdGet64 (PcdEmuFlashFvRecoveryBase),
458 FvSize,
459 PROT_READ | PROT_EXEC,
460 MAP_PRIVATE,
461 fd,
462 0
463 );
464 if (res == MAP_FAILED) {
465 perror ("MapFd0() Failed res =");
466 close (fd);
467 return EFI_DEVICE_ERROR;
468 } else if (res != (void *)(UINTN)FixedPcdGet64 (PcdEmuFlashFvRecoveryBase)) {
469 // We could not load at the build address, so we need to allow writes
470 munmap (res, FvSize);
471 res = mmap (
472 (void *)(UINTN)FixedPcdGet64 (PcdEmuFlashFvRecoveryBase),
473 FvSize,
474 PROT_READ | PROT_WRITE | PROT_EXEC,
475 MAP_PRIVATE,
476 fd,
477 0
478 );
479 if (res == MAP_FAILED) {
480 perror ("MapFd0() Failed res =");
481 close (fd);
482 return EFI_DEVICE_ERROR;
483 }
484 }
485
486 // Map the rest of the FD as read/write
487 res2 = mmap (
488 (void *)(UINTN)(FixedPcdGet64 (PcdEmuFlashFvRecoveryBase) + FvSize),
489 FileSize - FvSize,
490 PROT_READ | PROT_WRITE | PROT_EXEC,
491 MAP_SHARED,
492 fd,
493 FvSize
494 );
495 close (fd);
496 if (res2 == MAP_FAILED) {
497 perror ("MapFd0() Failed res2 =");
498 return EFI_DEVICE_ERROR;
499 }
500
501 //
502 // If enabled use the magic page to communicate between modules
503 // This replaces the PI PeiServicesTable pointer mechanism that
504 // deos not work in the emulator. It also allows the removal of
505 // writable globals from SEC, PEI_CORE (libraries), PEIMs
506 //
507 EmuMagicPage = (void *)(UINTN)FixedPcdGet64 (PcdPeiServicesTablePage);
508 if (EmuMagicPage != NULL) {
509 res3 = mmap (
510 (void *)EmuMagicPage,
511 4096,
512 PROT_READ | PROT_WRITE,
513 MAP_PRIVATE | MAP_ANONYMOUS,
514 0,
515 0
516 );
517 if (res3 != EmuMagicPage) {
518 printf ("MapFd0(): Could not allocate PeiServicesTablePage @ %lx\n", (long unsigned int)EmuMagicPage);
519 return EFI_DEVICE_ERROR;
520 }
521 }
522
523 *Length = (UINT64)FileSize;
524 *BaseAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)res;
525
526 return EFI_SUCCESS;
527}
528
529/*++
530
531Routine Description:
532 This is the service to load the SEC Core from the Firmware Volume
533
534Arguments:
535 LargestRegion - Memory to use for SEC.
536 LargestRegionSize - Size of Memory to use for PEI
537 BootFirmwareVolumeBase - Start of the Boot FV
538 PeiCorePe32File - SEC PE32
539
540Returns:
541 Success means control is transferred and thus we should never return
542
543**/
544VOID
545SecLoadFromCore (
546 IN UINTN LargestRegion,
547 IN UINTN LargestRegionSize,
548 IN UINTN BootFirmwareVolumeBase,
549 IN VOID *PeiCorePe32File
550 )
551{
552 EFI_STATUS Status;
553 EFI_PHYSICAL_ADDRESS TopOfMemory;
554 VOID *TopOfStack;
555 EFI_PHYSICAL_ADDRESS PeiCoreEntryPoint;
556 EFI_SEC_PEI_HAND_OFF *SecCoreData;
557 UINTN PeiStackSize;
558
559 //
560 // Compute Top Of Memory for Stack and PEI Core Allocations
561 //
562 TopOfMemory = LargestRegion + LargestRegionSize;
563 PeiStackSize = (UINTN)RShiftU64 ((UINT64)STACK_SIZE, 1);
564
565 //
566 // |-----------| <---- TemporaryRamBase + TemporaryRamSize
567 // | Heap |
568 // | |
569 // |-----------| <---- StackBase / PeiTemporaryMemoryBase
570 // | |
571 // | Stack |
572 // |-----------| <---- TemporaryRamBase
573 //
574 TopOfStack = (VOID *)(LargestRegion + PeiStackSize);
575 TopOfMemory = LargestRegion + PeiStackSize;
576
577 //
578 // Reservet space for storing PeiCore's parament in stack.
579 //
580 TopOfStack = (VOID *)((UINTN)TopOfStack - sizeof (EFI_SEC_PEI_HAND_OFF) - CPU_STACK_ALIGNMENT);
581 TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);
582
583 //
584 // Bind this information into the SEC hand-off state
585 //
586 SecCoreData = (EFI_SEC_PEI_HAND_OFF *)(UINTN)TopOfStack;
587 SecCoreData->DataSize = sizeof (EFI_SEC_PEI_HAND_OFF);
588 SecCoreData->BootFirmwareVolumeBase = (VOID *)BootFirmwareVolumeBase;
589 SecCoreData->BootFirmwareVolumeSize = PcdGet32 (PcdEmuFirmwareFdSize);
590 SecCoreData->TemporaryRamBase = (VOID *)(UINTN)LargestRegion;
591 SecCoreData->TemporaryRamSize = STACK_SIZE;
592 SecCoreData->StackBase = SecCoreData->TemporaryRamBase;
593 SecCoreData->StackSize = PeiStackSize;
594 SecCoreData->PeiTemporaryRamBase = (VOID *)((UINTN)SecCoreData->TemporaryRamBase + PeiStackSize);
595 SecCoreData->PeiTemporaryRamSize = STACK_SIZE - PeiStackSize;
596
597 //
598 // Find the SEC Core Entry Point
599 //
600 Status = SecPeCoffGetEntryPoint (PeiCorePe32File, (VOID **)&PeiCoreEntryPoint);
601 if (EFI_ERROR (Status)) {
602 return;
603 }
604
605 //
606 // Transfer control to the SEC Core
607 //
608 PeiSwitchStacks (
609 (SWITCH_STACK_ENTRY_POINT)(UINTN)PeiCoreEntryPoint,
610 SecCoreData,
611 (VOID *)gPpiList,
612 TopOfStack
613 );
614 //
615 // If we get here, then the SEC Core returned. This is an error
616 //
617 return;
618}
619
620/*++
621
622Routine Description:
623 This service is called from Index == 0 until it returns EFI_UNSUPPORTED.
624 It allows discontinuous memory regions to be supported by the emulator.
625 It uses gSystemMemory[] and gSystemMemoryCount that were created by
626 parsing the host environment variable EFI_MEMORY_SIZE.
627 The size comes from the variable and the address comes from the call to
628 UnixOpenFile.
629
630Arguments:
631 Index - Which memory region to use
632 MemoryBase - Return Base address of memory region
633 MemorySize - Return size in bytes of the memory region
634
635Returns:
636 EFI_SUCCESS - If memory region was mapped
637 EFI_UNSUPPORTED - If Index is not supported
638
639**/
641SecUnixPeiAutoScan (
642 IN UINTN Index,
643 OUT EFI_PHYSICAL_ADDRESS *MemoryBase,
644 OUT UINT64 *MemorySize
645 )
646{
647 void *res;
648
649 if (Index >= gSystemMemoryCount) {
650 return EFI_UNSUPPORTED;
651 }
652
653 *MemoryBase = 0;
654 res = MapMemory (
655 0,
656 gSystemMemory[Index].Size,
657 PROT_READ | PROT_WRITE | PROT_EXEC,
658 MAP_PRIVATE | MAP_ANONYMOUS
659 );
660 if (res == MAP_FAILED) {
661 return EFI_DEVICE_ERROR;
662 }
663
664 *MemorySize = gSystemMemory[Index].Size;
665 *MemoryBase = (UINTN)res;
666 gSystemMemory[Index].Memory = *MemoryBase;
667
668 return EFI_SUCCESS;
669}
670
671/*++
672
673Routine Description:
674 Check to see if an address range is in the EFI GCD memory map.
675
676 This is all of GCD for system memory passed to DXE Core. FV
677 mapping and other device mapped into system memory are not
678 included in the check.
679
680Arguments:
681 Index - Which memory region to use
682 MemoryBase - Return Base address of memory region
683 MemorySize - Return size in bytes of the memory region
684
685Returns:
686 TRUE - Address is in the EFI GCD memory map
687 FALSE - Address is NOT in memory map
688
689**/
690BOOLEAN
691EfiSystemMemoryRange (
692 IN VOID *MemoryAddress
693 )
694{
695 UINTN Index;
696 EFI_PHYSICAL_ADDRESS MemoryBase;
697
698 MemoryBase = (EFI_PHYSICAL_ADDRESS)(UINTN)MemoryAddress;
699 for (Index = 0; Index < gSystemMemoryCount; Index++) {
700 if ((MemoryBase >= gSystemMemory[Index].Memory) &&
701 (MemoryBase < (gSystemMemory[Index].Memory + gSystemMemory[Index].Size)))
702 {
703 return TRUE;
704 }
705 }
706
707 return FALSE;
708}
709
710/*++
711
712Routine Description:
713 Since the SEC is the only Unix program in stack it must export
714 an interface to do POSIX calls. gUnix is initialized in UnixThunk.c.
715
716Arguments:
717 InterfaceSize - sizeof (EFI_WIN_NT_THUNK_PROTOCOL);
718 InterfaceBase - Address of the gUnix global
719
720Returns:
721 EFI_SUCCESS - Data returned
722
723**/
724VOID *
725SecEmuThunkAddress (
726 VOID
727 )
728{
729 return &gEmuThunkProtocol;
730}
731
732RETURN_STATUS
733EFIAPI
734SecPeCoffGetEntryPoint (
735 IN VOID *Pe32Data,
736 IN OUT VOID **EntryPoint
737 )
738{
739 EFI_STATUS Status;
740 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
741
742 ZeroMem (&ImageContext, sizeof (ImageContext));
743 ImageContext.Handle = Pe32Data;
744 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)SecImageRead;
745
746 Status = PeCoffLoaderGetImageInfo (&ImageContext);
747 if (EFI_ERROR (Status)) {
748 return Status;
749 }
750
751 if (ImageContext.ImageAddress != (UINTN)Pe32Data) {
752 //
753 // Relocate image to match the address where it resides
754 //
755 ImageContext.ImageAddress = (UINTN)Pe32Data;
756 Status = PeCoffLoaderLoadImage (&ImageContext);
757 if (EFI_ERROR (Status)) {
758 return Status;
759 }
760
761 Status = PeCoffLoaderRelocateImage (&ImageContext);
762 if (EFI_ERROR (Status)) {
763 return Status;
764 }
765 } else {
766 //
767 // Or just return image entry point
768 //
769 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer (Pe32Data);
770 Status = PeCoffLoaderGetEntryPoint (Pe32Data, EntryPoint);
771 if (EFI_ERROR (Status)) {
772 return Status;
773 }
774
775 ImageContext.EntryPoint = (UINTN)*EntryPoint;
776 }
777
778 // On Unix a dlopen is done that will change the entry point
779 SecPeCoffRelocateImageExtraAction (&ImageContext);
780 *EntryPoint = (VOID *)(UINTN)ImageContext.EntryPoint;
781
782 return Status;
783}
784
785/*++
786
787Routine Description:
788 Return the FD Size and base address. Since the FD is loaded from a
789 file into host memory only the SEC will know its address.
790
791Arguments:
792 Index - Which FD, starts at zero.
793 FdSize - Size of the FD in bytes
794 FdBase - Start address of the FD. Assume it points to an FV Header
795 FixUp - Difference between actual FD address and build address
796
797Returns:
798 EFI_SUCCESS - Return the Base address and size of the FV
799 EFI_UNSUPPORTED - Index does nto map to an FD in the system
800
801**/
803SecUnixFdAddress (
804 IN UINTN Index,
806 IN OUT UINT64 *FdSize,
808 )
809{
810 if (Index >= gFdInfoCount) {
811 return EFI_UNSUPPORTED;
812 }
813
814 *FdBase = gFdInfo[Index].Address;
815 *FdSize = gFdInfo[Index].Size;
816 *FixUp = 0;
817
818 if ((*FdBase == 0) && (*FdSize == 0)) {
819 return EFI_UNSUPPORTED;
820 }
821
822 if (Index == 0) {
823 //
824 // FD 0 has XIP code and well known PCD values
825 // If the memory buffer could not be allocated at the FD build address
826 // the Fixup is the difference.
827 //
828 *FixUp = *FdBase - PcdGet64 (PcdEmuFdBaseAddress);
829 }
830
831 return EFI_SUCCESS;
832}
833
834/*++
835
836Routine Description:
837 Count the number of separators in String
838
839Arguments:
840 String - String to process
841 Separator - Item to count
842
843Returns:
844 Number of Separator in String
845
846**/
847UINTN
848CountSeparatorsInString (
849 IN const CHAR16 *String,
850 IN CHAR16 Separator
851 )
852{
853 UINTN Count;
854
855 for (Count = 0; *String != '\0'; String++) {
856 if (*String == Separator) {
857 Count++;
858 }
859 }
860
861 return Count;
862}
863
865EFIAPI
866SecImageRead (
867 IN VOID *FileHandle,
868 IN UINTN FileOffset,
869 IN OUT UINTN *ReadSize,
870 OUT VOID *Buffer
871 )
872
873/*++
874
875Routine Description:
876 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
877
878Arguments:
879 FileHandle - The handle to the PE/COFF file
880 FileOffset - The offset, in bytes, into the file to read
881 ReadSize - The number of bytes to read from the file starting at FileOffset
882 Buffer - A pointer to the buffer to read the data into.
883
884Returns:
885 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
886
887**/
888{
889 CHAR8 *Destination8;
890 CHAR8 *Source8;
891 UINTN Length;
892
893 Destination8 = Buffer;
894 Source8 = (CHAR8 *)((UINTN)FileHandle + FileOffset);
895 Length = *ReadSize;
896 while (Length--) {
897 *(Destination8++) = *(Source8++);
898 }
899
900 return EFI_SUCCESS;
901}
902
903/*++
904
905Routine Description:
906 Store the ModHandle in an array indexed by the Pdb File name.
907 The ModHandle is needed to unload the image.
908
909Arguments:
910 ImageContext - Input data returned from PE Loader Library. Used to find the
911 .PDB file name of the PE Image.
912 ModHandle - Returned from LoadLibraryEx() and stored for call to
913 FreeLibrary().
914
915Returns:
916 EFI_SUCCESS - ModHandle was stored.
917
918**/
920AddHandle (
921 IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
922 IN VOID *ModHandle
923 )
924{
925 UINTN Index;
927 UINTN PreviousSize;
928
929 Array = mImageContextModHandleArray;
930 for (Index = 0; Index < mImageContextModHandleArraySize; Index++, Array++) {
931 if (Array->ImageContext == NULL) {
932 //
933 // Make a copy of the string and store the ModHandle
934 //
935 Array->ImageContext = ImageContext;
936 Array->ModHandle = ModHandle;
937 return EFI_SUCCESS;
938 }
939 }
940
941 //
942 // No free space in mImageContextModHandleArray so grow it by
943 // IMAGE_CONTEXT_TO_MOD_HANDLE entires. realloc will
944 // copy the old values to the new location. But it does
945 // not zero the new memory area.
946 //
947 PreviousSize = mImageContextModHandleArraySize * sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE);
948 mImageContextModHandleArraySize += MAX_IMAGE_CONTEXT_TO_MOD_HANDLE_ARRAY_SIZE;
949
950 mImageContextModHandleArray = ReallocatePool (
951 (mImageContextModHandleArraySize - 1) * sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE),
952 mImageContextModHandleArraySize * sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE),
953 mImageContextModHandleArray
954 );
955 if (mImageContextModHandleArray == NULL) {
956 ASSERT (FALSE);
957 return EFI_OUT_OF_RESOURCES;
958 }
959
960 memset (mImageContextModHandleArray + PreviousSize, 0, MAX_IMAGE_CONTEXT_TO_MOD_HANDLE_ARRAY_SIZE * sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE));
961
962 return AddHandle (ImageContext, ModHandle);
963}
964
965/*++
966
967Routine Description:
968 Return the ModHandle and delete the entry in the array.
969
970Arguments:
971 ImageContext - Input data returned from PE Loader Library. Used to find the
972 .PDB file name of the PE Image.
973
974Returns:
975 ModHandle - ModHandle associated with ImageContext is returned
976 NULL - No ModHandle associated with ImageContext
977
978**/
979VOID *
980RemoveHandle (
981 IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
982 )
983{
984 UINTN Index;
986
987 if (ImageContext->PdbPointer == NULL) {
988 //
989 // If no PDB pointer there is no ModHandle so return NULL
990 //
991 return NULL;
992 }
993
994 Array = mImageContextModHandleArray;
995 for (Index = 0; Index < mImageContextModHandleArraySize; Index++, Array++) {
996 if (Array->ImageContext == ImageContext) {
997 //
998 // If you find a match return it and delete the entry
999 //
1000 Array->ImageContext = NULL;
1001 return Array->ModHandle;
1002 }
1003 }
1004
1005 return NULL;
1006}
1007
1008BOOLEAN
1009IsPdbFile (
1010 IN CHAR8 *PdbFileName
1011 )
1012{
1013 UINTN Len;
1014
1015 if (PdbFileName == NULL) {
1016 return FALSE;
1017 }
1018
1019 Len = strlen (PdbFileName);
1020 if ((Len < 5) || (PdbFileName[Len - 4] != '.')) {
1021 return FALSE;
1022 }
1023
1024 if (((PdbFileName[Len - 3] == 'P') || (PdbFileName[Len - 3] == 'p')) &&
1025 ((PdbFileName[Len - 2] == 'D') || (PdbFileName[Len - 2] == 'd')) &&
1026 ((PdbFileName[Len - 1] == 'B') || (PdbFileName[Len - 1] == 'b')))
1027 {
1028 return TRUE;
1029 }
1030
1031 return FALSE;
1032}
1033
1034#define MAX_SPRINT_BUFFER_SIZE 0x200
1035
1036void
1037PrintLoadAddress (
1038 IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
1039 )
1040{
1041 if (ImageContext->PdbPointer == NULL) {
1042 fprintf (
1043 stderr,
1044 "0x%08lx Loading NO DEBUG with entry point 0x%08lx\n",
1045 (unsigned long)(ImageContext->ImageAddress),
1046 (unsigned long)ImageContext->EntryPoint
1047 );
1048 } else {
1049 fprintf (
1050 stderr,
1051 "0x%08lx Loading %s with entry point 0x%08lx\n",
1052 (unsigned long)(ImageContext->ImageAddress + ImageContext->SizeOfHeaders),
1053 ImageContext->PdbPointer,
1054 (unsigned long)ImageContext->EntryPoint
1055 );
1056 }
1057
1058 // Keep output synced up
1059 fflush (stderr);
1060}
1061
1072BOOLEAN
1073DlLoadImage (
1074 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
1075 )
1076{
1077 #ifdef __APPLE__
1078
1079 return FALSE;
1080
1081 #else
1082
1083 void *Handle = NULL;
1084 void *Entry = NULL;
1085
1086 if (ImageContext->PdbPointer == NULL) {
1087 return FALSE;
1088 }
1089
1090 if (!IsPdbFile (ImageContext->PdbPointer)) {
1091 return FALSE;
1092 }
1093
1094 fprintf (
1095 stderr,
1096 "Loading %s 0x%08lx - entry point 0x%08lx\n",
1097 ImageContext->PdbPointer,
1098 (unsigned long)ImageContext->ImageAddress,
1099 (unsigned long)ImageContext->EntryPoint
1100 );
1101
1102 Handle = dlopen (ImageContext->PdbPointer, RTLD_NOW);
1103 if (Handle != NULL) {
1104 Entry = dlsym (Handle, "_ModuleEntryPoint");
1105 AddHandle (ImageContext, Handle);
1106 } else {
1107 printf ("%s\n", dlerror ());
1108 }
1109
1110 if (Entry != NULL) {
1111 ImageContext->EntryPoint = (UINTN)Entry;
1112 printf ("Change %s Entrypoint to :0x%08lx\n", ImageContext->PdbPointer, (unsigned long)Entry);
1113 return TRUE;
1114 } else {
1115 return FALSE;
1116 }
1117
1118 #endif
1119}
1120
1121#ifdef __APPLE__
1122__attribute__ ((noinline))
1123#endif
1124VOID
1125SecGdbScriptBreak (
1126 char *FileName,
1127 int FileNameLength,
1128 long unsigned int LoadAddress,
1129 int AddSymbolFlag
1130 )
1131{
1132 return;
1133}
1134
1142VOID
1143GdbScriptAddImage (
1144 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
1145 )
1146{
1147 PrintLoadAddress (ImageContext);
1148
1149 if ((ImageContext->PdbPointer != NULL) && !IsPdbFile (ImageContext->PdbPointer)) {
1150 FILE *GdbTempFile;
1151 if (FeaturePcdGet (PcdEmulatorLazyLoadSymbols)) {
1152 GdbTempFile = fopen (gGdbWorkingFileName, "a");
1153 if (GdbTempFile != NULL) {
1154 long unsigned int SymbolsAddr = (long unsigned int)(ImageContext->ImageAddress + ImageContext->SizeOfHeaders);
1155 mScriptSymbolChangesCount++;
1156 fprintf (
1157 GdbTempFile,
1158 "AddFirmwareSymbolFile 0x%x %s 0x%08lx\n",
1159 mScriptSymbolChangesCount,
1160 ImageContext->PdbPointer,
1161 SymbolsAddr
1162 );
1163 fclose (GdbTempFile);
1164 // This is for the lldb breakpoint only
1165 SecGdbScriptBreak (ImageContext->PdbPointer, strlen (ImageContext->PdbPointer) + 1, (long unsigned int)(ImageContext->ImageAddress + ImageContext->SizeOfHeaders), 1);
1166 } else {
1167 ASSERT (FALSE);
1168 }
1169 } else {
1170 GdbTempFile = fopen (gGdbWorkingFileName, "w");
1171 if (GdbTempFile != NULL) {
1172 fprintf (
1173 GdbTempFile,
1174 "add-symbol-file %s 0x%08lx\n",
1175 ImageContext->PdbPointer,
1176 (long unsigned int)(ImageContext->ImageAddress + ImageContext->SizeOfHeaders)
1177 );
1178 fclose (GdbTempFile);
1179
1180 //
1181 // Target for gdb breakpoint in a script that uses gGdbWorkingFileName to set a breakpoint.
1182 // Hey what can you say scripting in gdb is not that great....
1183 // Also used for the lldb breakpoint script. The lldb breakpoint script does
1184 // not use the file, it uses the arguments.
1185 //
1186 SecGdbScriptBreak (ImageContext->PdbPointer, strlen (ImageContext->PdbPointer) + 1, (long unsigned int)(ImageContext->ImageAddress + ImageContext->SizeOfHeaders), 1);
1187 } else {
1188 ASSERT (FALSE);
1189 }
1190 }
1191 }
1192}
1193
1194VOID
1195EFIAPI
1196SecPeCoffRelocateImageExtraAction (
1197 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
1198 )
1199{
1200 if (!DlLoadImage (ImageContext)) {
1201 GdbScriptAddImage (ImageContext);
1202 }
1203}
1204
1212VOID
1213GdbScriptRemoveImage (
1214 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
1215 )
1216{
1217 FILE *GdbTempFile;
1218
1219 //
1220 // Need to skip .PDB files created from VC++
1221 //
1222 if (IsPdbFile (ImageContext->PdbPointer)) {
1223 return;
1224 }
1225
1226 if (FeaturePcdGet (PcdEmulatorLazyLoadSymbols)) {
1227 //
1228 // Write the file we need for the gdb script
1229 //
1230 GdbTempFile = fopen (gGdbWorkingFileName, "a");
1231 if (GdbTempFile != NULL) {
1232 mScriptSymbolChangesCount++;
1233 fprintf (
1234 GdbTempFile,
1235 "RemoveFirmwareSymbolFile 0x%x %s\n",
1236 mScriptSymbolChangesCount,
1237 ImageContext->PdbPointer
1238 );
1239 fclose (GdbTempFile);
1240 SecGdbScriptBreak (ImageContext->PdbPointer, strlen (ImageContext->PdbPointer) + 1, 0, 0);
1241 } else {
1242 ASSERT (FALSE);
1243 }
1244 } else {
1245 GdbTempFile = fopen (gGdbWorkingFileName, "w");
1246 if (GdbTempFile != NULL) {
1247 fprintf (GdbTempFile, "remove-symbol-file %s\n", ImageContext->PdbPointer);
1248 fclose (GdbTempFile);
1249
1250 //
1251 // Target for gdb breakpoint in a script that uses gGdbWorkingFileName to set a breakpoint.
1252 // Hey what can you say scripting in gdb is not that great....
1253 //
1254 SecGdbScriptBreak (ImageContext->PdbPointer, strlen (ImageContext->PdbPointer) + 1, 0, 0);
1255 } else {
1256 ASSERT (FALSE);
1257 }
1258 }
1259}
1260
1261VOID
1262EFIAPI
1263SecPeCoffUnloadImageExtraAction (
1264 IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
1265 )
1266{
1267 VOID *Handle;
1268
1269 //
1270 // Check to see if the image symbols were loaded with gdb script, or dlopen
1271 //
1272 Handle = RemoveHandle (ImageContext);
1273 if (Handle != NULL) {
1274 #ifndef __APPLE__
1275 dlclose (Handle);
1276 #endif
1277 return;
1278 }
1279
1280 GdbScriptRemoveImage (ImageContext);
1281}
UINT64 UINTN
INT64 INTN
#define CPU_STACK_ALIGNMENT
UINT64 EFIAPI RShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: RShiftU64.c:28
VOID(EFIAPI * SWITCH_STACK_ENTRY_POINT)(IN VOID *Context1 OPTIONAL, IN VOID *Context2 OPTIONAL)
Definition: BaseLib.h:5019
UINTN EFIAPI StrLen(IN CONST CHAR16 *String)
Definition: String.c:30
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
int main()
=== TEST ENGINE ================================================================================
VOID *EFIAPI ReallocatePool(IN UINTN OldSize, IN UINTN NewSize, IN VOID *OldBuffer OPTIONAL)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
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 STATIC
Definition: Base.h:264
#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
#define FeaturePcdGet(TokenName)
Definition: PcdLib.h:50
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
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
unsigned long long UINT64 __attribute__((aligned(8)))
Definition: ProcessorBind.h:28
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
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