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