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