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