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