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