]> git.proxmox.com Git - mirror_edk2.git/blob - UnixPkg/Sec/SecMain.c
This checkin addresses the compatibility issue of passing arguments of type VA_LIST...
[mirror_edk2.git] / UnixPkg / Sec / SecMain.c
1 /*++
2
3 Copyright (c) 2006 - 2007 Intel Corporation.
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 SecMain.c
15
16 Abstract:
17 WinNt emulator of SEC phase. It's really a Posix application, but this is
18 Ok since all the other modules for NT32 are NOT Posix applications.
19
20 This program processes host environment variables and figures out
21 what the memory layout will be, how may FD's will be loaded and also
22 what the boot mode is.
23
24 The SEC registers a set of services with the SEC core. gPrivateDispatchTable
25 is a list of PPI's produced by the SEC that are availble for usage in PEI.
26
27 This code produces 128 K of temporary memory for the PEI stack by opening a
28 host file and mapping it directly to memory addresses.
29
30 The system.cmd script is used to set host environment variables that drive
31 the configuration opitons of the SEC.
32
33 --*/
34
35 #include "SecMain.h"
36 #include <sys/mman.h>
37 #include <Ppi/UnixPeiLoadFile.h>
38 #include <Framework/StatusCode.h>
39 #include <Ppi/TemporaryRamSupport.h>
40 #include <dlfcn.h>
41 //
42 // Globals
43 //
44
45 UNIX_PEI_LOAD_FILE_PPI mSecNtLoadFilePpi = { SecWinNtPeiLoadFile };
46
47 PEI_UNIX_AUTOSCAN_PPI mSecNtAutoScanPpi = { SecWinNtPeiAutoScan };
48
49 PEI_UNIX_THUNK_PPI mSecWinNtThunkPpi = { SecWinNtWinNtThunkAddress };
50
51 EFI_PEI_PROGRESS_CODE_PPI mSecStatusCodePpi = { SecPeiReportStatusCode };
52
53 UNIX_FWH_PPI mSecFwhInformationPpi = { SecWinNtFdAddress };
54
55 TEMPORARY_RAM_SUPPORT_PPI mSecTemporaryRamSupportPpi = {SecTemporaryRamSupport};
56
57 EFI_PEI_PPI_DESCRIPTOR gPrivateDispatchTable[] = {
58 {
59 EFI_PEI_PPI_DESCRIPTOR_PPI,
60 &gUnixPeiLoadFilePpiGuid,
61 &mSecNtLoadFilePpi
62 },
63 {
64 EFI_PEI_PPI_DESCRIPTOR_PPI,
65 &gPeiUnixAutoScanPpiGuid,
66 &mSecNtAutoScanPpi
67 },
68 {
69 EFI_PEI_PPI_DESCRIPTOR_PPI,
70 &gPeiUnixThunkPpiGuid,
71 &mSecWinNtThunkPpi
72 },
73 {
74 EFI_PEI_PPI_DESCRIPTOR_PPI,
75 &gEfiPeiStatusCodePpiGuid,
76 &mSecStatusCodePpi
77 },
78 {
79 EFI_PEI_PPI_DESCRIPTOR_PPI,
80 &gEfiTemporaryRamSupportPpiGuid,
81 &mSecTemporaryRamSupportPpi
82 },
83 {
84
85 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
86 &gUnixFwhPpiGuid,
87 &mSecFwhInformationPpi
88 }
89 };
90
91
92 //
93 // Default information about where the FD is located.
94 // This array gets filled in with information from EFI_FIRMWARE_VOLUMES
95 // EFI_FIRMWARE_VOLUMES is a host environment variable set by system.cmd.
96 // The number of array elements is allocated base on parsing
97 // EFI_FIRMWARE_VOLUMES and the memory is never freed.
98 //
99 UINTN gFdInfoCount = 0;
100 UNIX_FD_INFO *gFdInfo;
101
102 //
103 // Array that supports seperate memory rantes.
104 // The memory ranges are set in system.cmd via the EFI_MEMORY_SIZE variable.
105 // The number of array elements is allocated base on parsing
106 // EFI_MEMORY_SIZE and the memory is never freed.
107 //
108 UINTN gSystemMemoryCount = 0;
109 UNIX_SYSTEM_MEMORY *gSystemMemory;
110
111 VOID
112 EFIAPI
113 SecSwitchStack (
114 UINT32 TemporaryMemoryBase,
115 UINT32 PermenentMemoryBase
116 );
117
118 EFI_PHYSICAL_ADDRESS *
119 MapMemory (
120 INTN fd,
121 UINT64 length,
122 INTN prot,
123 INTN flags);
124
125 EFI_STATUS
126 MapFile (
127 IN CHAR8 *FileName,
128 IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
129 OUT UINT64 *Length
130 );
131 EFI_STATUS
132 EFIAPI
133 SecNt32PeCoffRelocateImage (
134 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
135 );
136
137
138 INTN
139 EFIAPI
140 main (
141 IN INTN Argc,
142 IN CHAR8 **Argv,
143 IN CHAR8 **Envp
144 )
145 /*++
146
147 Routine Description:
148 Main entry point to SEC for WinNt. This is a unix program
149
150 Arguments:
151 Argc - Number of command line arguments
152 Argv - Array of command line argument strings
153 Envp - Array of environmemt variable strings
154
155 Returns:
156 0 - Normal exit
157 1 - Abnormal exit
158
159 --*/
160 {
161 EFI_STATUS Status;
162 EFI_PHYSICAL_ADDRESS InitialStackMemory;
163 UINT64 InitialStackMemorySize;
164 UINTN Index;
165 UINTN Index1;
166 UINTN Index2;
167 UINTN PeiIndex;
168 CHAR8 *FileName;
169 BOOLEAN Done;
170 VOID *PeiCoreFile;
171 CHAR16 *MemorySizeStr;
172 CHAR16 *FirmwareVolumesStr;
173 UINTN *StackPointer;
174
175 setbuf(stdout, 0);
176 setbuf(stderr, 0);
177
178 MemorySizeStr = (CHAR16 *) FixedPcdGetPtr (PcdUnixMemorySizeForSecMain);
179 FirmwareVolumesStr = (CHAR16 *) FixedPcdGetPtr (PcdUnixFirmwareVolume);
180
181 printf ("\nEDK SEC Main UNIX Emulation Environment from www.TianoCore.org\n");
182
183 //
184 // Allocate space for gSystemMemory Array
185 //
186 gSystemMemoryCount = CountSeperatorsInString (MemorySizeStr, '!') + 1;
187 gSystemMemory = calloc (gSystemMemoryCount, sizeof (UNIX_SYSTEM_MEMORY));
188 if (gSystemMemory == NULL) {
189 printf ("ERROR : Can not allocate memory for system. Exiting.\n");
190 exit (1);
191 }
192 //
193 // Allocate space for gSystemMemory Array
194 //
195 gFdInfoCount = CountSeperatorsInString (FirmwareVolumesStr, '!') + 1;
196 gFdInfo = calloc (gFdInfoCount, sizeof (UNIX_FD_INFO));
197 if (gFdInfo == NULL) {
198 printf ("ERROR : Can not allocate memory for fd info. Exiting.\n");
199 exit (1);
200 }
201 //
202 // Setup Boot Mode. If BootModeStr == "" then BootMode = 0 (BOOT_WITH_FULL_CONFIGURATION)
203 //
204 printf (" BootMode 0x%02x\n", FixedPcdGet32 (PcdUnixBootMode));
205
206 //
207 // Open up a 128K file to emulate temp memory for PEI.
208 // on a real platform this would be SRAM, or using the cache as RAM.
209 // Set InitialStackMemory to zero so WinNtOpenFile will allocate a new mapping
210 //
211 InitialStackMemorySize = STACK_SIZE;
212 InitialStackMemory = (UINTN)MapMemory(0,
213 (UINT32) InitialStackMemorySize,
214 PROT_READ | PROT_WRITE,
215 MAP_ANONYMOUS | MAP_PRIVATE);
216 if (InitialStackMemory == 0) {
217 printf ("ERROR : Can not open SecStack Exiting\n");
218 exit (1);
219 }
220
221 printf (" SEC passing in %u KB of temp RAM at 0x%08lx to PEI\n",
222 (UINTN)(InitialStackMemorySize / 1024),
223 (unsigned long)InitialStackMemory);
224
225 for (StackPointer = (UINTN*) (UINTN) InitialStackMemory;
226 StackPointer < (UINTN*) ((UINTN) InitialStackMemory + (UINT64) InitialStackMemorySize);
227 StackPointer ++) {
228 *StackPointer = 0x5AA55AA5;
229 }
230
231 //
232 // Open All the firmware volumes and remember the info in the gFdInfo global
233 //
234 FileName = (CHAR8 *)malloc (StrLen (FirmwareVolumesStr) + 1);
235 if (FileName == NULL) {
236 printf ("ERROR : Can not allocate memory for firmware volume string\n");
237 exit (1);
238 }
239
240 Index2 = 0;
241 for (Done = FALSE, Index = 0, PeiIndex = 0, PeiCoreFile = NULL;
242 FirmwareVolumesStr[Index2] != 0;
243 Index++) {
244 for (Index1 = 0; (FirmwareVolumesStr[Index2] != '!') && (FirmwareVolumesStr[Index2] != 0); Index2++)
245 FileName[Index1++] = FirmwareVolumesStr[Index2];
246 if (FirmwareVolumesStr[Index2] == '!')
247 Index2++;
248 FileName[Index1] = '\0';
249
250 //
251 // Open the FD and remmeber where it got mapped into our processes address space
252 //
253 Status = MapFile (
254 FileName,
255 &gFdInfo[Index].Address,
256 &gFdInfo[Index].Size
257 );
258 if (EFI_ERROR (Status)) {
259 printf ("ERROR : Can not open Firmware Device File %s (%x). Exiting.\n", FileName, Status);
260 exit (1);
261 }
262
263 printf (" FD loaded from %s at 0x%08lx",
264 FileName, (unsigned long)gFdInfo[Index].Address);
265
266 if (PeiCoreFile == NULL) {
267 //
268 // Assume the beginning of the FD is an FV and look for the PEI Core.
269 // Load the first one we find.
270 //
271 Status = SecFfsFindPeiCore ((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) gFdInfo[Index].Address, &PeiCoreFile);
272 if (!EFI_ERROR (Status)) {
273 PeiIndex = Index;
274 printf (" contains SEC Core");
275 }
276 }
277
278 printf ("\n");
279 }
280 //
281 // Calculate memory regions and store the information in the gSystemMemory
282 // global for later use. The autosizing code will use this data to
283 // map this memory into the SEC process memory space.
284 //
285 Index1 = 0;
286 Index = 0;
287 while (1) {
288 UINTN val = 0;
289 //
290 // Save the size of the memory.
291 //
292 while (MemorySizeStr[Index1] >= '0' && MemorySizeStr[Index1] <= '9') {
293 val = val * 10 + MemorySizeStr[Index1] - '0';
294 Index1++;
295 }
296 gSystemMemory[Index++].Size = val * 0x100000;
297 if (MemorySizeStr[Index1] == 0)
298 break;
299 Index1++;
300 }
301
302 printf ("\n");
303
304 //
305 // Hand off to PEI Core
306 //
307 SecLoadFromCore ((UINTN) InitialStackMemory, (UINTN) InitialStackMemorySize, (UINTN) gFdInfo[0].Address, PeiCoreFile);
308
309 //
310 // If we get here, then the PEI Core returned. This is an error as PEI should
311 // always hand off to DXE.
312 //
313 printf ("ERROR : PEI Core returned\n");
314 exit (1);
315 }
316
317 EFI_PHYSICAL_ADDRESS *
318 MapMemory (
319 INTN fd,
320 UINT64 length,
321 INTN prot,
322 INTN flags)
323 {
324 STATIC UINTN base = 0x40000000;
325 CONST UINTN align = (1 << 24);
326 VOID *res = NULL;
327 BOOLEAN isAligned = 0;
328
329 //
330 // Try to get an aligned block somewhere in the address space of this
331 // process.
332 //
333 while((!isAligned) && (base != 0)) {
334 res = mmap ((void *)base, length, prot, flags, fd, 0);
335 if (res == MAP_FAILED) {
336 return NULL;
337 }
338 if ((((UINTN)res) & ~(align-1)) == (UINTN)res) {
339 isAligned=1;
340 }
341 else {
342 munmap(res, length);
343 base += align;
344 }
345 }
346 return res;
347 }
348
349 EFI_STATUS
350 MapFile (
351 IN CHAR8 *FileName,
352 IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
353 OUT UINT64 *Length
354 )
355 /*++
356
357 Routine Description:
358 Opens and memory maps a file using WinNt services. If BaseAddress is non zero
359 the process will try and allocate the memory starting at BaseAddress.
360
361 Arguments:
362 FileName - The name of the file to open and map
363 MapSize - The amount of the file to map in bytes
364 CreationDisposition - The flags to pass to CreateFile(). Use to create new files for
365 memory emulation, and exiting files for firmware volume emulation
366 BaseAddress - The base address of the mapped file in the user address space.
367 If passed in as NULL the a new memory region is used.
368 If passed in as non NULL the request memory region is used for
369 the mapping of the file into the process space.
370 Length - The size of the mapped region in bytes
371
372 Returns:
373 EFI_SUCCESS - The file was opened and mapped.
374 EFI_NOT_FOUND - FileName was not found in the current directory
375 EFI_DEVICE_ERROR - An error occured attempting to map the opened file
376
377 --*/
378 {
379 int fd;
380 VOID *res;
381 UINTN FileSize;
382
383 fd = open (FileName, O_RDONLY);
384 if (fd < 0)
385 return EFI_NOT_FOUND;
386 FileSize = lseek (fd, 0, SEEK_END);
387
388 #if 0
389 if (IsMain)
390 {
391 /* Read entry address. */
392 lseek (fd, FileSize - 0x20, SEEK_SET);
393 if (read (fd, &EntryAddress, 4) != 4)
394 {
395 close (fd);
396 return EFI_DEVICE_ERROR;
397 }
398 }
399 #endif
400
401 res = MapMemory(fd, FileSize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
402
403 close (fd);
404
405 if (res == MAP_FAILED)
406 return EFI_DEVICE_ERROR;
407
408 *Length = (UINT64) FileSize;
409 *BaseAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) res;
410
411 return EFI_SUCCESS;
412 }
413
414 #define BYTES_PER_RECORD 512
415
416 EFI_STATUS
417 EFIAPI
418 SecPeiReportStatusCode (
419 IN EFI_PEI_SERVICES **PeiServices,
420 IN EFI_STATUS_CODE_TYPE CodeType,
421 IN EFI_STATUS_CODE_VALUE Value,
422 IN UINT32 Instance,
423 IN EFI_GUID * CallerId,
424 IN EFI_STATUS_CODE_DATA * Data OPTIONAL
425 )
426 /*++
427
428 Routine Description:
429
430 This routine produces the ReportStatusCode PEI service. It's passed
431 up to the PEI Core via a PPI. T
432
433 This code currently uses the UNIX clib printf. This does not work the same way
434 as the EFI Print (), as %t, %g, %s as Unicode are not supported.
435
436 Arguments:
437 (see EFI_PEI_REPORT_STATUS_CODE)
438
439 Returns:
440 EFI_SUCCESS - Always return success
441
442 --*/
443 // TODO: PeiServices - add argument and description to function comment
444 // TODO: CodeType - add argument and description to function comment
445 // TODO: Value - add argument and description to function comment
446 // TODO: Instance - add argument and description to function comment
447 // TODO: CallerId - add argument and description to function comment
448 // TODO: Data - add argument and description to function comment
449 {
450 CHAR8 *Format;
451 BASE_LIST Marker;
452 CHAR8 PrintBuffer[BYTES_PER_RECORD * 2];
453 CHAR8 *Filename;
454 CHAR8 *Description;
455 UINT32 LineNumber;
456 UINT32 ErrorLevel;
457
458
459 if (Data == NULL) {
460 } else if (ReportStatusCodeExtractAssertInfo (CodeType, Value, Data, &Filename, &Description, &LineNumber)) {
461 //
462 // Processes ASSERT ()
463 //
464 printf ("ASSERT %s(%d): %s\n", Filename, LineNumber, Description);
465
466 } else if (ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) {
467 //
468 // Process DEBUG () macro
469 //
470 AsciiBSPrint (PrintBuffer, BYTES_PER_RECORD, Format, Marker);
471 printf (PrintBuffer);
472 }
473
474 return EFI_SUCCESS;
475 }
476
477 /**
478 Transfers control to a function starting with a new stack.
479
480 Transfers control to the function specified by EntryPoint using the new stack
481 specified by NewStack and passing in the parameters specified by Context1 and
482 Context2. Context1 and Context2 are optional and may be NULL. The function
483 EntryPoint must never return.
484
485 If EntryPoint is NULL, then ASSERT().
486 If NewStack is NULL, then ASSERT().
487
488 @param EntryPoint A pointer to function to call with the new stack.
489 @param Context1 A pointer to the context to pass into the EntryPoint
490 function.
491 @param Context2 A pointer to the context to pass into the EntryPoint
492 function.
493 @param NewStack A pointer to the new stack to use for the EntryPoint
494 function.
495 @param NewBsp A pointer to the new BSP for the EntryPoint on IPF. It's
496 Reserved on other architectures.
497
498 **/
499 VOID
500 EFIAPI
501 PeiSwitchStacks (
502 IN SWITCH_STACK_ENTRY_POINT EntryPoint,
503 IN VOID *Context1, OPTIONAL
504 IN VOID *Context2, OPTIONAL
505 IN VOID *Context3, OPTIONAL
506 IN VOID *NewStack
507 )
508 {
509 BASE_LIBRARY_JUMP_BUFFER JumpBuffer;
510
511 ASSERT (EntryPoint != NULL);
512 ASSERT (NewStack != NULL);
513
514 //
515 // Stack should be aligned with CPU_STACK_ALIGNMENT
516 //
517 ASSERT (((UINTN)NewStack & (CPU_STACK_ALIGNMENT - 1)) == 0);
518
519 JumpBuffer.Eip = (UINTN)EntryPoint;
520 JumpBuffer.Esp = (UINTN)NewStack - sizeof (VOID*);
521 JumpBuffer.Esp -= sizeof (Context1) + sizeof (Context2) + sizeof(Context3);
522 ((VOID**)JumpBuffer.Esp)[1] = Context1;
523 ((VOID**)JumpBuffer.Esp)[2] = Context2;
524 ((VOID**)JumpBuffer.Esp)[3] = Context3;
525
526 LongJump (&JumpBuffer, (UINTN)-1);
527
528
529 //
530 // InternalSwitchStack () will never return
531 //
532 ASSERT (FALSE);
533 }
534
535 VOID
536 SecLoadFromCore (
537 IN UINTN LargestRegion,
538 IN UINTN LargestRegionSize,
539 IN UINTN BootFirmwareVolumeBase,
540 IN VOID *PeiCorePe32File
541 )
542 /*++
543
544 Routine Description:
545 This is the service to load the PEI Core from the Firmware Volume
546
547 Arguments:
548 LargestRegion - Memory to use for PEI.
549 LargestRegionSize - Size of Memory to use for PEI
550 BootFirmwareVolumeBase - Start of the Boot FV
551 PeiCorePe32File - PEI Core PE32
552
553 Returns:
554 Success means control is transfered and thus we should never return
555
556 --*/
557 {
558 EFI_STATUS Status;
559 EFI_PHYSICAL_ADDRESS TopOfMemory;
560 VOID *TopOfStack;
561 UINT64 PeiCoreSize;
562 EFI_PHYSICAL_ADDRESS PeiCoreEntryPoint;
563 EFI_PHYSICAL_ADDRESS PeiImageAddress;
564 EFI_SEC_PEI_HAND_OFF *SecCoreData;
565 UINTN PeiStackSize;
566
567 //
568 // Compute Top Of Memory for Stack and PEI Core Allocations
569 //
570 TopOfMemory = LargestRegion + LargestRegionSize;
571 PeiStackSize = (UINTN)RShiftU64((UINT64)STACK_SIZE,1);
572
573 //
574 // |-----------| <---- TemporaryRamBase + TemporaryRamSize
575 // | Heap |
576 // | |
577 // |-----------| <---- StackBase / PeiTemporaryMemoryBase
578 // | |
579 // | Stack |
580 // |-----------| <---- TemporaryRamBase
581 //
582 TopOfStack = (VOID *)(LargestRegion + PeiStackSize);
583 TopOfMemory = LargestRegion + PeiStackSize;
584
585 //
586 // Reservet space for storing PeiCore's parament in stack.
587 //
588 TopOfStack = (VOID *)((UINTN)TopOfStack - sizeof (EFI_SEC_PEI_HAND_OFF) - CPU_STACK_ALIGNMENT);
589 TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);
590
591
592 //
593 // Bind this information into the SEC hand-off state
594 //
595 SecCoreData = (EFI_SEC_PEI_HAND_OFF*)(UINTN) TopOfStack;
596 SecCoreData->DataSize = sizeof(EFI_SEC_PEI_HAND_OFF);
597 SecCoreData->BootFirmwareVolumeBase = (VOID*)BootFirmwareVolumeBase;
598 SecCoreData->BootFirmwareVolumeSize = FixedPcdGet32(PcdUnixFirmwareFdSize);
599 SecCoreData->TemporaryRamBase = (VOID*)(UINTN)LargestRegion;
600 SecCoreData->TemporaryRamSize = STACK_SIZE;
601 SecCoreData->StackBase = SecCoreData->TemporaryRamBase;
602 SecCoreData->StackSize = PeiStackSize;
603 SecCoreData->PeiTemporaryRamBase = (VOID*) ((UINTN) SecCoreData->TemporaryRamBase + PeiStackSize);
604 SecCoreData->PeiTemporaryRamSize = STACK_SIZE - PeiStackSize;
605
606 //
607 // Load the PEI Core from a Firmware Volume
608 //
609 Status = SecWinNtPeiLoadFile (
610 PeiCorePe32File,
611 &PeiImageAddress,
612 &PeiCoreSize,
613 &PeiCoreEntryPoint
614 );
615 if (EFI_ERROR (Status)) {
616 return ;
617 }
618
619 //
620 // Transfer control to the PEI Core
621 //
622 PeiSwitchStacks (
623 (SWITCH_STACK_ENTRY_POINT) (UINTN) PeiCoreEntryPoint,
624 SecCoreData,
625 (VOID *) (UINTN) ((EFI_PEI_PPI_DESCRIPTOR *) &gPrivateDispatchTable),
626 NULL,
627 TopOfStack
628 );
629 //
630 // If we get here, then the PEI Core returned. This is an error
631 //
632 return ;
633 }
634
635 EFI_STATUS
636 EFIAPI
637 SecWinNtPeiAutoScan (
638 IN UINTN Index,
639 OUT EFI_PHYSICAL_ADDRESS *MemoryBase,
640 OUT UINT64 *MemorySize
641 )
642 /*++
643
644 Routine Description:
645 This service is called from Index == 0 until it returns EFI_UNSUPPORTED.
646 It allows discontiguous memory regions to be supported by the emulator.
647 It uses gSystemMemory[] and gSystemMemoryCount that were created by
648 parsing the host environment variable EFI_MEMORY_SIZE.
649 The size comes from the varaible and the address comes from the call to
650 WinNtOpenFile.
651
652 Arguments:
653 Index - Which memory region to use
654 MemoryBase - Return Base address of memory region
655 MemorySize - Return size in bytes of the memory region
656
657 Returns:
658 EFI_SUCCESS - If memory region was mapped
659 EFI_UNSUPPORTED - If Index is not supported
660
661 --*/
662 {
663 void *res;
664
665 if (Index >= gSystemMemoryCount) {
666 return EFI_UNSUPPORTED;
667 }
668
669 *MemoryBase = 0;
670 res = MapMemory(0, gSystemMemory[Index].Size,
671 PROT_READ | PROT_WRITE | PROT_EXEC,
672 MAP_PRIVATE | MAP_ANONYMOUS);
673 if (res == MAP_FAILED)
674 return EFI_DEVICE_ERROR;
675 *MemorySize = gSystemMemory[Index].Size;
676 *MemoryBase = (UINTN)res;
677 gSystemMemory[Index].Memory = *MemoryBase;
678
679 return EFI_SUCCESS;
680 }
681
682 VOID *
683 EFIAPI
684 SecWinNtWinNtThunkAddress (
685 VOID
686 )
687 /*++
688
689 Routine Description:
690 Since the SEC is the only Unix program in stack it must export
691 an interface to do Win API calls. That's what the WinNtThunk address
692 is for. gWinNt is initailized in WinNtThunk.c.
693
694 Arguments:
695 InterfaceSize - sizeof (EFI_WIN_NT_THUNK_PROTOCOL);
696 InterfaceBase - Address of the gWinNt global
697
698 Returns:
699 EFI_SUCCESS - Data returned
700
701 --*/
702 {
703 return gUnix;
704 }
705
706
707 EFI_STATUS
708 EFIAPI
709 SecWinNtPeiLoadFile (
710 IN VOID *Pe32Data,
711 IN EFI_PHYSICAL_ADDRESS *ImageAddress,
712 IN UINT64 *ImageSize,
713 IN EFI_PHYSICAL_ADDRESS *EntryPoint
714 )
715 /*++
716
717 Routine Description:
718 Loads and relocates a PE/COFF image into memory.
719
720 Arguments:
721 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
722 ImageAddress - The base address of the relocated PE/COFF image
723 ImageSize - The size of the relocated PE/COFF image
724 EntryPoint - The entry point of the relocated PE/COFF image
725
726 Returns:
727 EFI_SUCCESS - The file was loaded and relocated
728 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
729
730 --*/
731 {
732 EFI_STATUS Status;
733 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
734
735 ZeroMem (&ImageContext, sizeof (ImageContext));
736 ImageContext.Handle = Pe32Data;
737
738 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) SecImageRead;
739
740 Status = PeCoffLoaderGetImageInfo (&ImageContext);
741 if (EFI_ERROR (Status)) {
742 return Status;
743 }
744 //
745 // Allocate space in UNIX (not emulator) memory. Extra space is for alignment
746 //
747 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) malloc ((UINTN) (ImageContext.ImageSize + (ImageContext.SectionAlignment * 2)));
748 if (ImageContext.ImageAddress == 0) {
749 return EFI_OUT_OF_RESOURCES;
750 }
751 //
752 // Align buffer on section boundry
753 //
754 ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
755 ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);
756
757
758 Status = PeCoffLoaderLoadImage (&ImageContext);
759 if (EFI_ERROR (Status)) {
760 return Status;
761 }
762
763 Status = SecNt32PeCoffRelocateImage(&ImageContext);
764 if (EFI_ERROR (Status)) {
765 return Status;
766 }
767
768 //
769 // BugBug: Flush Instruction Cache Here when CPU Lib is ready
770 //
771
772 *ImageAddress = ImageContext.ImageAddress;
773 *ImageSize = ImageContext.ImageSize;
774 *EntryPoint = ImageContext.EntryPoint;
775
776 return EFI_SUCCESS;
777 }
778
779 EFI_STATUS
780 EFIAPI
781 SecWinNtFdAddress (
782 IN UINTN Index,
783 IN OUT EFI_PHYSICAL_ADDRESS *FdBase,
784 IN OUT UINT64 *FdSize
785 )
786 /*++
787
788 Routine Description:
789 Return the FD Size and base address. Since the FD is loaded from a
790 file into host memory only the SEC will know it's address.
791
792 Arguments:
793 Index - Which FD, starts at zero.
794 FdSize - Size of the FD in bytes
795 FdBase - Start address of the FD. Assume it points to an FV Header
796
797 Returns:
798 EFI_SUCCESS - Return the Base address and size of the FV
799 EFI_UNSUPPORTED - Index does nto map to an FD in the system
800
801 --*/
802 {
803 if (Index >= gFdInfoCount) {
804 return EFI_UNSUPPORTED;
805 }
806
807 *FdBase = gFdInfo[Index].Address;
808 *FdSize = gFdInfo[Index].Size;
809
810 if (*FdBase == 0 && *FdSize == 0) {
811 return EFI_UNSUPPORTED;
812 }
813
814 return EFI_SUCCESS;
815 }
816
817 EFI_STATUS
818 EFIAPI
819 SecImageRead (
820 IN VOID *FileHandle,
821 IN UINTN FileOffset,
822 IN OUT UINTN *ReadSize,
823 OUT VOID *Buffer
824 )
825 /*++
826
827 Routine Description:
828 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
829
830 Arguments:
831 FileHandle - The handle to the PE/COFF file
832 FileOffset - The offset, in bytes, into the file to read
833 ReadSize - The number of bytes to read from the file starting at FileOffset
834 Buffer - A pointer to the buffer to read the data into.
835
836 Returns:
837 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
838
839 --*/
840 {
841 CHAR8 *Destination8;
842 CHAR8 *Source8;
843 UINTN Length;
844
845 Destination8 = Buffer;
846 Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
847 Length = *ReadSize;
848 while (Length--) {
849 *(Destination8++) = *(Source8++);
850 }
851
852 return EFI_SUCCESS;
853 }
854
855 UINTN
856 CountSeperatorsInString (
857 IN const CHAR16 *String,
858 IN CHAR16 Seperator
859 )
860 /*++
861
862 Routine Description:
863 Count the number of seperators in String
864
865 Arguments:
866 String - String to process
867 Seperator - Item to count
868
869 Returns:
870 Number of Seperator in String
871
872 --*/
873 {
874 UINTN Count;
875
876 for (Count = 0; *String != '\0'; String++) {
877 if (*String == Seperator) {
878 Count++;
879 }
880 }
881
882 return Count;
883 }
884
885
886
887 VOID
888 SecUnixLoaderBreak (
889 VOID
890 )
891 {
892 }
893
894 EFI_STATUS
895 EFIAPI
896 SecNt32PeCoffRelocateImage (
897 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
898 )
899 {
900 void * Handle;
901 void * Entry;
902 EFI_STATUS Status;
903
904 Handle = NULL;
905 Entry = NULL;
906 Status = PeCoffLoaderRelocateImage (ImageContext);
907 fprintf (stderr,
908 "Loading %s 0x%08lx - entry point 0x%08lx\n",
909 ImageContext->PdbPointer,
910 (unsigned long)ImageContext->ImageAddress,
911 (unsigned long)ImageContext->EntryPoint);
912
913 Handle = dlopen(ImageContext->PdbPointer, RTLD_NOW);
914
915 if (Handle) {
916 Entry = dlsym(Handle, "_ModuleEntryPoint");
917 } else {
918 printf("%s\n", dlerror());
919 }
920
921 if (Entry != NULL) {
922 ImageContext->EntryPoint = Entry;
923 printf("Change %s Entrypoint to :0x%08lx\n", ImageContext->PdbPointer, Entry);
924 }
925
926 SecUnixLoaderBreak ();
927
928 return Status;
929 }
930
931
932 EFI_STATUS
933 EFIAPI
934 SecNt32PeCoffUnloadimage (
935 IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
936 )
937 {
938 return EFI_SUCCESS;
939 }
940
941 VOID
942 ModuleEntryPoint (
943 VOID
944 )
945 {
946 }
947
948 EFI_STATUS
949 EFIAPI
950 SecTemporaryRamSupport (
951 IN CONST EFI_PEI_SERVICES **PeiServices,
952 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
953 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
954 IN UINTN CopySize
955 )
956 {
957 //
958 // Migrate the whole temporary memory to permenent memory.
959 //
960 CopyMem (
961 (VOID*)(UINTN)PermanentMemoryBase,
962 (VOID*)(UINTN)TemporaryMemoryBase,
963 CopySize
964 );
965
966 //
967 // SecSwitchStack function must be invoked after the memory migration
968 // immediatly, also we need fixup the stack change caused by new call into
969 // permenent memory.
970 //
971 SecSwitchStack (
972 (UINT32) TemporaryMemoryBase,
973 (UINT32) PermanentMemoryBase
974 );
975
976 //
977 // We need *not* fix the return address because currently,
978 // The PeiCore is excuted in flash.
979 //
980
981 //
982 // Simulate to invalid temporary memory, terminate temporary memory
983 //
984 //ZeroMem ((VOID*)(UINTN)TemporaryMemoryBase, CopySize);
985
986 return EFI_SUCCESS;
987 }