diff options
Diffstat (limited to 'UnixPkg/Sec')
-rw-r--r-- | UnixPkg/Sec/Ia32/Stack.S | 95 | ||||
-rw-r--r-- | UnixPkg/Sec/SecMain.c | 425 | ||||
-rw-r--r-- | UnixPkg/Sec/SecMain.h | 61 | ||||
-rw-r--r-- | UnixPkg/Sec/SecMain.inf | 15 | ||||
-rw-r--r-- | UnixPkg/Sec/UgaX11.c | 61 | ||||
-rw-r--r-- | UnixPkg/Sec/UnixThunk.c | 138 |
6 files changed, 716 insertions, 79 deletions
diff --git a/UnixPkg/Sec/Ia32/Stack.S b/UnixPkg/Sec/Ia32/Stack.S new file mode 100644 index 0000000..4716af9 --- /dev/null +++ b/UnixPkg/Sec/Ia32/Stack.S @@ -0,0 +1,95 @@ +#------------------------------------------------------------------------------
+#
+# Copyright (c) 2008 - 2009, Intel Corporation
+# Portions copyright (c) 2008-2009 Apple Inc.
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+# Module Name:
+#
+# Stack.asm
+#
+# Abstract:
+#
+# Switch the stack from temporary memory to permenent memory.
+#
+#------------------------------------------------------------------------------
+
+#------------------------------------------------------------------------------
+# VOID
+# EFIAPI
+# SecSwitchStack (
+# UINT32 TemporaryMemoryBase,
+# UINT32 PermenentMemoryBase
+# );
+#------------------------------------------------------------------------------
+
+#include <ProcessorBind.h>
+
+ASM_GLOBAL ASM_PFX(SecSwitchStack)
+ASM_PFX(SecSwitchStack):
+#
+# Save three register: eax, ebx, ecx
+#
+ push %eax
+ push %ebx
+ push %ecx
+ push %edx
+
+#
+# !!CAUTION!! this function address's is pushed into stack after
+# migration of whole temporary memory, so need save it to permenent
+# memory at first!
+#
+
+ movl 20(%esp), %ebx # Save the first parameter
+ movl 24(%esp), %ecx # Save the second parameter
+
+#
+# Save this function's return address into permenent memory at first.
+# Then, Fixup the esp point to permenent memory
+#
+
+ movl %esp, %eax
+ subl %ebx, %eax
+ addl %ecx, %eax
+ movl (%esp), %edx # copy pushed register's value to permenent memory
+ movl %edx, (%eax)
+ movl 4(%esp), %edx
+ movl %edx, 4(%eax)
+ movl 8(%esp), %edx
+ movl %edx, 8(%eax)
+ movl 12(%esp), %edx
+ movl %edx, 12(%eax)
+ movl 16(%esp), %edx
+ movl %edx, 16(%eax)
+ movl %eax, %esp # From now, esp is pointed to permenent memory
+
+#
+# Fixup the ebp point to permenent memory
+#
+#ifndef __APPLE__
+ movl %ebp, %eax
+ subl %ebx, %eax
+ addl %ecx, %eax
+ movl %eax, %ebp # From now, ebp is pointed to permenent memory
+
+#
+# Fixup callee's ebp point for PeiDispatch
+#
+ movl (%ebp), %eax
+ subl %ebx, %eax
+ addl %ecx, %eax
+ movl %eax, (%ebp) # From now, Temporary's PPI caller's stack is in permenent memory
+#endif
+
+ pop %edx
+ pop %ecx
+ pop %ebx
+ pop %eax
+ ret
diff --git a/UnixPkg/Sec/SecMain.c b/UnixPkg/Sec/SecMain.c index 4e09ddc..b1490ae 100644 --- a/UnixPkg/Sec/SecMain.c +++ b/UnixPkg/Sec/SecMain.c @@ -1,6 +1,7 @@ /*++ -Copyright (c) 2006 - 2007 Intel Corporation. +Copyright (c) 2006 - 2009 Intel Corporation. +Portions copyright (c) 2008-2009 Apple Inc. All rights reserved. This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -14,7 +15,7 @@ Module Name: SecMain.c Abstract: - WinNt emulator of SEC phase. It's really a Posix application, but this is + Unix emulator of SEC phase. It's really a Posix application, but this is Ok since all the other modules for NT32 are NOT Posix applications. This program processes host environment variables and figures out @@ -35,21 +36,29 @@ Abstract: #include "SecMain.h" #include <sys/mman.h> #include <Ppi/UnixPeiLoadFile.h> +#include <Framework/StatusCode.h> #include <Ppi/TemporaryRamSupport.h> #include <dlfcn.h> + +#ifdef __APPLE__ +#define MAP_ANONYMOUS MAP_ANON +char *gGdbWorkingFileName = NULL; +#endif + + // // Globals // -UNIX_PEI_LOAD_FILE_PPI mSecNtLoadFilePpi = { SecWinNtPeiLoadFile }; +UNIX_PEI_LOAD_FILE_PPI mSecUnixLoadFilePpi = { SecUnixPeiLoadFile }; -PEI_UNIX_AUTOSCAN_PPI mSecNtAutoScanPpi = { SecWinNtPeiAutoScan }; +PEI_UNIX_AUTOSCAN_PPI mSecUnixAutoScanPpi = { SecUnixPeiAutoScan }; -PEI_UNIX_THUNK_PPI mSecWinNtThunkPpi = { SecWinNtWinNtThunkAddress }; +PEI_UNIX_THUNK_PPI mSecUnixThunkPpi = { SecUnixUnixThunkAddress }; EFI_PEI_PROGRESS_CODE_PPI mSecStatusCodePpi = { SecPeiReportStatusCode }; -UNIX_FWH_PPI mSecFwhInformationPpi = { SecWinNtFdAddress }; +UNIX_FWH_PPI mSecFwhInformationPpi = { SecUnixFdAddress }; TEMPORARY_RAM_SUPPORT_PPI mSecTemporaryRamSupportPpi = {SecTemporaryRamSupport}; @@ -57,17 +66,17 @@ EFI_PEI_PPI_DESCRIPTOR gPrivateDispatchTable[] = { { EFI_PEI_PPI_DESCRIPTOR_PPI, &gUnixPeiLoadFilePpiGuid, - &mSecNtLoadFilePpi + &mSecUnixLoadFilePpi }, { EFI_PEI_PPI_DESCRIPTOR_PPI, &gPeiUnixAutoScanPpiGuid, - &mSecNtAutoScanPpi + &mSecUnixAutoScanPpi }, { EFI_PEI_PPI_DESCRIPTOR_PPI, &gPeiUnixThunkPpiGuid, - &mSecWinNtThunkPpi + &mSecUnixThunkPpi }, { EFI_PEI_PPI_DESCRIPTOR_PPI, @@ -107,6 +116,12 @@ UNIX_FD_INFO *gFdInfo; UINTN gSystemMemoryCount = 0; UNIX_SYSTEM_MEMORY *gSystemMemory; + + +UINTN mImageContextModHandleArraySize = 0; +IMAGE_CONTEXT_TO_MOD_HANDLE *mImageContextModHandleArray = NULL; + + VOID EFIAPI SecSwitchStack ( @@ -134,17 +149,16 @@ SecNt32PeCoffRelocateImage ( ); -INTN -EFIAPI +int main ( - IN INTN Argc, - IN CHAR8 **Argv, - IN CHAR8 **Envp + IN int Argc, + IN char **Argv, + IN char **Envp ) /*++ Routine Description: - Main entry point to SEC for WinNt. This is a unix program + Main entry point to SEC for Unix. This is a unix program Arguments: Argc - Number of command line arguments @@ -179,6 +193,19 @@ Returns: printf ("\nEDK SEC Main UNIX Emulation Environment from www.TianoCore.org\n"); +#ifdef __APPLE__ + // + // We can't use dlopen on OS X, so we need a scheme to get symboles into gdb + // We need to create a temp file that contains gdb commands so we can load + // symbols when we load every PE/COFF image. + // + Index = strlen (*Argv); + gGdbWorkingFileName = malloc (Index + strlen(".gdb")); + strcpy (gGdbWorkingFileName, *Argv); + strcat (gGdbWorkingFileName, ".gdb"); +#endif + + // // Allocate space for gSystemMemory Array // @@ -200,12 +227,12 @@ Returns: // // Setup Boot Mode. If BootModeStr == "" then BootMode = 0 (BOOT_WITH_FULL_CONFIGURATION) // - printf (" BootMode 0x%02x\n", FixedPcdGet32 (PcdUnixBootMode)); + printf (" BootMode 0x%02x\n", (unsigned int)FixedPcdGet32 (PcdUnixBootMode)); // // Open up a 128K file to emulate temp memory for PEI. // on a real platform this would be SRAM, or using the cache as RAM. - // Set InitialStackMemory to zero so WinNtOpenFile will allocate a new mapping + // Set InitialStackMemory to zero so UnixOpenFile will allocate a new mapping // InitialStackMemorySize = STACK_SIZE; InitialStackMemory = (UINTN)MapMemory(0, @@ -218,11 +245,11 @@ Returns: } printf (" SEC passing in %u KB of temp RAM at 0x%08lx to PEI\n", - (UINTN)(InitialStackMemorySize / 1024), + (unsigned int)(InitialStackMemorySize / 1024), (unsigned long)InitialStackMemory); for (StackPointer = (UINTN*) (UINTN) InitialStackMemory; - StackPointer < (UINTN*) ((UINTN) InitialStackMemory + (UINT64) InitialStackMemorySize); + StackPointer < (UINTN*)(UINTN)((UINTN) InitialStackMemory + (UINT64) InitialStackMemorySize); StackPointer ++) { *StackPointer = 0x5AA55AA5; } @@ -255,7 +282,7 @@ Returns: &gFdInfo[Index].Size ); if (EFI_ERROR (Status)) { - printf ("ERROR : Can not open Firmware Device File %s (%x). Exiting.\n", FileName, Status); + printf ("ERROR : Can not open Firmware Device File %s (%x). Exiting.\n", FileName, (unsigned int)Status); exit (1); } @@ -354,7 +381,7 @@ MapFile ( /*++ Routine Description: - Opens and memory maps a file using WinNt services. If BaseAddress is non zero + Opens and memory maps a file using Unix services. If BaseAddress is non zero the process will try and allocate the memory starting at BaseAddress. Arguments: @@ -415,12 +442,12 @@ Returns: EFI_STATUS EFIAPI SecPeiReportStatusCode ( - IN EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_SERVICES **PeiServices, IN EFI_STATUS_CODE_TYPE CodeType, IN EFI_STATUS_CODE_VALUE Value, IN UINT32 Instance, - IN EFI_GUID * CallerId, - IN EFI_STATUS_CODE_DATA * Data OPTIONAL + IN CONST EFI_GUID *CallerId, + IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL ) /*++ @@ -460,7 +487,7 @@ Returns: // // Processes ASSERT () // - printf ("ASSERT %s(%d): %s\n", Filename, LineNumber, Description); + printf ("ASSERT %s(%d): %s\n", Filename, (int)LineNumber, Description); } else if (ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) { // @@ -605,7 +632,7 @@ Returns: // // Load the PEI Core from a Firmware Volume // - Status = SecWinNtPeiLoadFile ( + Status = SecUnixPeiLoadFile ( PeiCorePe32File, &PeiImageAddress, &PeiCoreSize, @@ -633,7 +660,7 @@ Returns: EFI_STATUS EFIAPI -SecWinNtPeiAutoScan ( +SecUnixPeiAutoScan ( IN UINTN Index, OUT EFI_PHYSICAL_ADDRESS *MemoryBase, OUT UINT64 *MemorySize @@ -646,7 +673,7 @@ Routine Description: It uses gSystemMemory[] and gSystemMemoryCount that were created by parsing the host environment variable EFI_MEMORY_SIZE. The size comes from the varaible and the address comes from the call to - WinNtOpenFile. + UnixOpenFile. Arguments: Index - Which memory region to use @@ -680,19 +707,18 @@ Returns: VOID * EFIAPI -SecWinNtWinNtThunkAddress ( +SecUnixUnixThunkAddress ( VOID ) /*++ Routine Description: Since the SEC is the only Unix program in stack it must export - an interface to do Win API calls. That's what the WinNtThunk address - is for. gWinNt is initailized in WinNtThunk.c. + an interface to do POSIX calls. gUnix is initailized in UnixThunk.c. Arguments: InterfaceSize - sizeof (EFI_WIN_NT_THUNK_PROTOCOL); - InterfaceBase - Address of the gWinNt global + InterfaceBase - Address of the gUnix global Returns: EFI_SUCCESS - Data returned @@ -704,12 +730,11 @@ Returns: EFI_STATUS -EFIAPI -SecWinNtPeiLoadFile ( +SecUnixPeiLoadFile ( IN VOID *Pe32Data, - IN EFI_PHYSICAL_ADDRESS *ImageAddress, - IN UINT64 *ImageSize, - IN EFI_PHYSICAL_ADDRESS *EntryPoint + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint ) /*++ @@ -759,10 +784,7 @@ Returns: return Status; } - Status = SecNt32PeCoffRelocateImage(&ImageContext); - if (EFI_ERROR (Status)) { - return Status; - } + SecPeCoffRelocateImageExtraAction (&ImageContext); // // BugBug: Flush Instruction Cache Here when CPU Lib is ready @@ -775,9 +797,30 @@ Returns: return EFI_SUCCESS; } + +RETURN_STATUS +EFIAPI +SecPeCoffGetEntryPoint ( + IN VOID *Pe32Data, + IN OUT VOID **EntryPoint + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS ImageAddress; + UINT64 ImageSize; + EFI_PHYSICAL_ADDRESS PhysEntryPoint; + + Status = SecUnixPeiLoadFile (Pe32Data, &ImageAddress, &ImageSize, &PhysEntryPoint); + + *EntryPoint = (VOID *)(UINTN)PhysEntryPoint; + return Status; +} + + + EFI_STATUS EFIAPI -SecWinNtFdAddress ( +SecUnixFdAddress ( IN UINTN Index, IN OUT EFI_PHYSICAL_ADDRESS *FdBase, IN OUT UINT64 *FdSize @@ -882,6 +925,131 @@ Returns: } +EFI_STATUS +AddHandle ( + IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN VOID *ModHandle + ) +/*++ + +Routine Description: + Store the ModHandle in an array indexed by the Pdb File name. + The ModHandle is needed to unload the image. + +Arguments: + ImageContext - Input data returned from PE Laoder Library. Used to find the + .PDB file name of the PE Image. + ModHandle - Returned from LoadLibraryEx() and stored for call to + FreeLibrary(). + +Returns: + EFI_SUCCESS - ModHandle was stored. + +--*/ +{ + UINTN Index; + IMAGE_CONTEXT_TO_MOD_HANDLE *Array; + UINTN PreviousSize; + + + Array = mImageContextModHandleArray; + for (Index = 0; Index < mImageContextModHandleArraySize; Index++, Array++) { + if (Array->ImageContext == NULL) { + // + // Make a copy of the stirng and store the ModHandle + // + Array->ImageContext = ImageContext; + Array->ModHandle = ModHandle; + return EFI_SUCCESS; + } + } + + // + // No free space in mImageContextModHandleArray so grow it by + // IMAGE_CONTEXT_TO_MOD_HANDLE entires. realloc will + // copy the old values to the new locaiton. But it does + // not zero the new memory area. + // + PreviousSize = mImageContextModHandleArraySize * sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE); + mImageContextModHandleArraySize += MAX_IMAGE_CONTEXT_TO_MOD_HANDLE_ARRAY_SIZE; + + mImageContextModHandleArray = realloc (mImageContextModHandleArray, mImageContextModHandleArraySize * sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE)); + if (mImageContextModHandleArray == NULL) { + ASSERT (FALSE); + return EFI_OUT_OF_RESOURCES; + } + + memset (mImageContextModHandleArray + PreviousSize, 0, MAX_IMAGE_CONTEXT_TO_MOD_HANDLE_ARRAY_SIZE * sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE)); + + return AddHandle (ImageContext, ModHandle); +} + + +VOID * +RemoveHandle ( + IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + Return the ModHandle and delete the entry in the array. + +Arguments: + ImageContext - Input data returned from PE Laoder Library. Used to find the + .PDB file name of the PE Image. + +Returns: + ModHandle - ModHandle assoicated with ImageContext is returned + NULL - No ModHandle associated with ImageContext + +--*/ +{ + UINTN Index; + IMAGE_CONTEXT_TO_MOD_HANDLE *Array; + + if (ImageContext->PdbPointer == NULL) { + // + // If no PDB pointer there is no ModHandle so return NULL + // + return NULL; + } + + Array = mImageContextModHandleArray; + for (Index = 0; Index < mImageContextModHandleArraySize; Index++, Array++) { + if ((Array->ImageContext == ImageContext)) { + // + // If you find a match return it and delete the entry + // + Array->ImageContext = NULL; + return Array->ModHandle; + } + } + + return NULL; +} + + + +// +// Target for gdb breakpoint in a script that uses gGdbWorkingFileName to source a +// add-symbol-file command. Hey what can you say scripting in gdb is not that great.... +// +// Put .gdbinit in the CWD where you do gdb SecMain.dll for source level debug +// +// cat .gdbinit +// b SecGdbScriptBreak +// command +// silent +// source SecMain.dll.gdb +// c +// end +// +VOID +SecGdbScriptBreak ( + VOID + ) +{ +} VOID SecUnixLoaderBreak ( @@ -890,19 +1058,128 @@ SecUnixLoaderBreak ( { } -EFI_STATUS +BOOLEAN +IsPdbFile ( + IN CHAR8 *PdbFileName + ) +{ + UINTN Len; + + if (PdbFileName == NULL) { + return FALSE; + } + + Len = strlen (PdbFileName); + if ((Len < 5)|| (PdbFileName[Len - 4] != '.')) { + return FALSE; + } + + if ((PdbFileName[Len - 3] == 'P' || PdbFileName[Len - 3] == 'p') && + (PdbFileName[Len - 2] == 'D' || PdbFileName[Len - 2] == 'd') && + (PdbFileName[Len - 1] == 'B' || PdbFileName[Len - 1] == 'b')) { + return TRUE; + } + + return FALSE; +} + + +#define MAX_SPRINT_BUFFER_SIZE 0x200 + +void +PrintLoadAddress ( + IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + fprintf (stderr, + "0x%08lx Loading %s with entry point 0x%08lx\n", + (unsigned long)ImageContext->ImageAddress + ImageContext->SizeOfHeaders, + ImageContext->PdbPointer, + (unsigned long)ImageContext->EntryPoint + ); + + // Keep output synced up + fflush (stderr); +} + + +VOID EFIAPI -SecNt32PeCoffRelocateImage ( +SecPeCoffRelocateImageExtraAction ( IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext ) { - void * Handle; - void * Entry; EFI_STATUS Status; - Handle = NULL; - Entry = NULL; Status = PeCoffLoaderRelocateImage (ImageContext); + if (EFI_ERROR (Status)) { + PrintLoadAddress (ImageContext); + return; + } + +#ifdef __APPLE__ + PrintLoadAddress (ImageContext); + + // + // In mach-o (OS X executable) dlopen() can only load files in the MH_DYLIB of MH_BUNDLE format. + // To convert to PE/COFF we need to construct a mach-o with the MH_PRELOAD format. We create + // .dSYM files for the PE/COFF images that can be used by gdb for source level debugging. + // + FILE *GdbTempFile; + + // + // In the Mach-O to PE/COFF conversion the size of the PE/COFF headers is not accounted for. + // Thus we need to skip over the PE/COFF header when giving load addresses for our symbol table. + // + if (ImageContext->PdbPointer != NULL && !IsPdbFile (ImageContext->PdbPointer)) { + // + // Now we have a database of the images that are currently loaded + // + + // + // 'symbol-file' will clear out currnet symbol mappings in gdb. + // you can do a 'add-symbol-file filename address' for every image we loaded to get source + // level debug in gdb. Note Sec, being a true application will work differently. + // + // We add the PE/COFF header size into the image as the mach-O does not have a header in + // loaded into system memory. + // + // This gives us a data base of gdb commands and after something is unloaded that entry will be + // removed. We don't yet have the scheme of how to comunicate with gdb, but we have the + // data base of info ready to roll. + // + // We could use qXfer:libraries:read, but OS X GDB does not currently support it. + // <library-list> + // <library name="/lib/libc.so.6"> // ImageContext->PdbPointer + // <segment address="0x10000000"/> // ImageContext->ImageAddress + ImageContext->SizeOfHeaders + // </library> + // </library-list> + // + + // + // Write the file we need for the gdb script + // + GdbTempFile = fopen (gGdbWorkingFileName, "w"); + if (GdbTempFile != NULL) { + fprintf (GdbTempFile, "add-symbol-file %s 0x%x\n", ImageContext->PdbPointer, (UINTN)(ImageContext->ImageAddress + ImageContext->SizeOfHeaders)); + fclose (GdbTempFile); + + // + // Target for gdb breakpoint in a script that uses gGdbWorkingFileName to set a breakpoint. + // Hey what can you say scripting in gdb is not that great.... + // + SecGdbScriptBreak (); + } + + AddHandle (ImageContext, ImageContext->PdbPointer); + + } + +#else + + void *Handle = NULL; + void *Entry = NULL; + fprintf (stderr, "Loading %s 0x%08lx - entry point 0x%08lx\n", ImageContext->PdbPointer, @@ -918,23 +1195,63 @@ SecNt32PeCoffRelocateImage ( } if (Entry != NULL) { - ImageContext->EntryPoint = Entry; - printf("Change %s Entrypoint to :0x%08lx\n", ImageContext->PdbPointer, Entry); + ImageContext->EntryPoint = (UINTN)Entry; + printf("Change %s Entrypoint to :0x%08lx\n", ImageContext->PdbPointer, (unsigned long)Entry); } SecUnixLoaderBreak (); - return Status; +#endif + + return; } -EFI_STATUS +VOID EFIAPI -SecNt32PeCoffUnloadimage ( +SecPeCoffLoaderUnloadImageExtraAction ( IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext ) { - return EFI_SUCCESS; + VOID *Handle; + + Handle = RemoveHandle (ImageContext); + +#ifdef __APPLE__ + FILE *GdbTempFile; + + if (Handle != NULL) { + // + // Need to skip .PDB files created from VC++ + // + if (!IsPdbFile (ImageContext->PdbPointer)) { + // + // Write the file we need for the gdb script + // + GdbTempFile = fopen (gGdbWorkingFileName, "w"); + if (GdbTempFile != NULL) { + fprintf (GdbTempFile, "remove-symbol-file %s\n", ImageContext->PdbPointer); + fclose (GdbTempFile); + + // + // Target for gdb breakpoint in a script that uses gGdbWorkingFileName to set a breakpoint. + // Hey what can you say scripting in gdb is not that great.... + // + SecGdbScriptBreak (); + } + } + } + +#else + // + // Don't want to confuse gdb with symbols for something that got unloaded + // + if (Handle != NULL) { + dlclose (Handle); + } + +#endif + return; } VOID diff --git a/UnixPkg/Sec/SecMain.h b/UnixPkg/Sec/SecMain.h index 236a50e..c7a72c9 100644 --- a/UnixPkg/Sec/SecMain.h +++ b/UnixPkg/Sec/SecMain.h @@ -1,6 +1,7 @@ /*++
-Copyright (c) 2006 - 2008, Intel Corporation
+Copyright (c) 2006 - 2009, Intel Corporation
+Portions copyright (c) 2008-2009 Apple Inc.
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@@ -28,6 +29,7 @@ Abstract: #include <Library/PrintLib.h>
#include <Library/PcdLib.h>
#include <Library/DebugLib.h>
+#include <Library/ReportStatusCodeLib.h>
#define STACK_SIZE 0x20000
@@ -42,10 +44,17 @@ typedef struct { } UNIX_SYSTEM_MEMORY;
+#define MAX_IMAGE_CONTEXT_TO_MOD_HANDLE_ARRAY_SIZE 0x100
+
+typedef struct {
+ PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext;
+ VOID *ModHandle;
+} IMAGE_CONTEXT_TO_MOD_HANDLE;
+
EFI_STATUS
EFIAPI
-SecWinNtPeiLoadFile (
+SecUnixPeiLoadFile (
VOID *Pe32Data, // TODO: add IN/OUT modifier to Pe32Data
EFI_PHYSICAL_ADDRESS *ImageAddress, // TODO: add IN/OUT modifier to ImageAddress
UINT64 *ImageSize, // TODO: add IN/OUT modifier to ImageSize
@@ -73,7 +82,7 @@ Returns: EFI_STATUS
EFIAPI
-SecWinNtPeiAutoScan (
+SecUnixPeiAutoScan (
IN UINTN Index,
OUT EFI_PHYSICAL_ADDRESS *MemoryBase,
OUT UINT64 *MemorySize
@@ -99,7 +108,7 @@ Returns: VOID *
EFIAPI
-SecWinNtWinNtThunkAddress (
+SecUnixUnixThunkAddress (
VOID
)
/*++
@@ -122,7 +131,7 @@ Returns: EFI_STATUS
EFIAPI
-SecWinNtWinNtFwhAddress (
+SecUnixUnixFwhAddress (
IN OUT UINT64 *FwhSize,
IN OUT EFI_PHYSICAL_ADDRESS *FwhBase
)
@@ -147,12 +156,12 @@ Returns: EFI_STATUS
EFIAPI
SecPeiReportStatusCode (
- IN EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_SERVICES **PeiServices,
IN EFI_STATUS_CODE_TYPE CodeType,
IN EFI_STATUS_CODE_VALUE Value,
IN UINT32 Instance,
- IN EFI_GUID * CallerId,
- IN EFI_STATUS_CODE_DATA * Data OPTIONAL
+ IN CONST EFI_GUID *CallerId,
+ IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL
)
/*++
@@ -176,12 +185,11 @@ Returns: --*/
;
-INTN
-EFIAPI
+int
main (
- IN INTN Argc,
- IN CHAR8 **Argv,
- IN CHAR8 **Envp
+ IN int Argc,
+ IN char **Argv,
+ IN char **Envp
)
/*++
@@ -331,7 +339,7 @@ Returns: EFI_STATUS
EFIAPI
-SecWinNtPeCoffLoaderLoadAsDll (
+SecUnixPeCoffLoaderLoadAsDll (
IN CHAR8 *PdbFileName,
IN VOID **ImageEntryPoint,
OUT VOID **ModHandle
@@ -357,7 +365,7 @@ Returns: EFI_STATUS
EFIAPI
-SecWinNtPeCoffLoaderFreeLibrary (
+SecUnixPeCoffLoaderFreeLibrary (
OUT VOID *ModHandle
)
/*++
@@ -379,7 +387,7 @@ Returns: EFI_STATUS
EFIAPI
-SecWinNtFdAddress (
+SecUnixFdAddress (
IN UINTN Index,
IN OUT EFI_PHYSICAL_ADDRESS *FdBase,
IN OUT UINT64 *FdSize
@@ -509,4 +517,25 @@ SecTemporaryRamSupport ( IN UINTN CopySize
);
+
+RETURN_STATUS
+EFIAPI
+SecPeCoffGetEntryPoint (
+ IN VOID *Pe32Data,
+ IN OUT VOID **EntryPoint
+ );
+
+VOID
+EFIAPI
+SecPeCoffRelocateImageExtraAction (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ );
+
+VOID
+EFIAPI
+SecPeCoffLoaderUnloadImageExtraAction (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ );
+
+
extern EFI_UNIX_THUNK_PROTOCOL *gUnix;
diff --git a/UnixPkg/Sec/SecMain.inf b/UnixPkg/Sec/SecMain.inf index a0c9268..c7a9b40 100644 --- a/UnixPkg/Sec/SecMain.inf +++ b/UnixPkg/Sec/SecMain.inf @@ -2,7 +2,8 @@ # Entry Point of Unix Emulator
#
# Main executable file of Unix Emulator that loads PEI core after initialization finished.
-# Copyright (c) 2008, Intel Corporation
+# Copyright (c) 2008 - 2009, Intel Corporation
+# Portions copyright (c) 2008-2009 Apple Inc.
#
# All rights reserved. This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
@@ -35,7 +36,10 @@ UnixThunk.c
FwVol.c
SecMain.c
- Stack.S
+
+[Sources.Ia32]
+ Ia32/Gasket.S
+ Ia32/Stack.S
[Packages]
MdePkg/MdePkg.dec
@@ -74,3 +78,10 @@ GCC:*_*_IA32_CC_FLAGS == -m32 -g -fshort-wchar -fno-strict-aliasing -Wall -malign-double -idirafter/usr/include -c -include $(DEST_DIR_DEBUG)/AutoGen.h -DSTRING_ARRAY_NAME=$(BASE_NAME)Strings
GCC:*_*_IA32_PP_FLAGS == -m32 -E -x assembler-with-cpp -include $(DEST_DIR_DEBUG)/AutoGen.h
GCC:*_*_IA32_ASM_FLAGS == -c -x assembler -imacros $(DEST_DIR_DEBUG)/AutoGen.h
+
+#
+# Need to do this link via gcc and not ld as the pathing to libraries changes from OS version to OS version
+#
+ XCODE:*_*_IA32_DLINK_PATH == gcc
+ XCODE:*_*_IA32_DLINK_FLAGS == -arch i386 -L/usr/X11R6/lib -lXext -lX11 -lIOKit -framework Carbon
+ XCODE:*_*_IA32_ASM_FLAGS == -arch i386 -g
diff --git a/UnixPkg/Sec/UgaX11.c b/UnixPkg/Sec/UgaX11.c index 1c68b32..386e0bc 100644 --- a/UnixPkg/Sec/UgaX11.c +++ b/UnixPkg/Sec/UgaX11.c @@ -1,6 +1,19 @@ +/*++ + +Copyright (c) 2004 - 2009, Intel Corporation +Portions copyright (c) 2008-2009 Apple Inc. All rights reserved. +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +--*/ + #include <sys/ipc.h> #include <sys/shm.h> -#include <sys/dir.h> #include <stdio.h> #include <stdlib.h> @@ -123,8 +136,15 @@ TryCreateShmImage(UGA_IO_PRIVATE *drv) XDestroyImage(drv->image); return 0; } + +#ifndef __APPLE__ + // + // This closes shared memory in real time on OS X. Only closes after folks quit using + // it on Linux. + // /* Can this fail ? */ shmctl (drv->xshm_info.shmid, IPC_RMID, NULL); +#endif drv->xshm_info.shmaddr = (char*)drv->image_data; drv->image->data = (char*)drv->image_data; @@ -157,6 +177,12 @@ UgaClose (EFI_UNIX_UGA_IO_PROTOCOL *UgaIo) } XDestroyWindow(drv->display, drv->win); XCloseDisplay(drv->display); + +#ifdef __APPLE__ + // Free up the shared memory + shmctl (drv->xshm_info.shmid, IPC_RMID, NULL); +#endif + free(drv); return EFI_SUCCESS; } @@ -534,16 +560,45 @@ UgaCreate (EFI_UNIX_UGA_IO_PROTOCOL **Uga, CONST CHAR16 *Title) char *display_name = NULL; int title_len; - drv = (UGA_IO_PRIVATE *) - calloc (1, sizeof (UGA_IO_PRIVATE)); + drv = (UGA_IO_PRIVATE *)calloc (1, sizeof (UGA_IO_PRIVATE)); if (drv == NULL) return EFI_OUT_OF_RESOURCES; +#ifdef __APPLE__ +// +// +// +EFI_STATUS EFIAPI GasketUgaClose (EFI_UNIX_UGA_IO_PROTOCOL *UgaIo); +EFI_STATUS EFIAPI GasketUgaSize (EFI_UNIX_UGA_IO_PROTOCOL *UgaIo, UINT32 Width, UINT32 Height); +EFI_STATUS EFIAPI GasketUgaCheckKey (EFI_UNIX_UGA_IO_PROTOCOL *UgaIo); +EFI_STATUS EFIAPI GasketUgaGetKey (EFI_UNIX_UGA_IO_PROTOCOL *UgaIo, EFI_INPUT_KEY *key); +EFI_STATUS EFIAPI GasketUgaBlt ( + EFI_UNIX_UGA_IO_PROTOCOL *UgaIo, + IN EFI_UGA_PIXEL *BltBuffer OPTIONAL, + IN EFI_UGA_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ); + + drv->UgaIo.UgaClose = GasketUgaClose; + drv->UgaIo.UgaSize = GasketUgaSize; + drv->UgaIo.UgaCheckKey = GasketUgaCheckKey; + drv->UgaIo.UgaGetKey = GasketUgaGetKey; + drv->UgaIo.UgaBlt = GasketUgaBlt; +#else drv->UgaIo.UgaClose = UgaClose; drv->UgaIo.UgaSize = UgaSize; drv->UgaIo.UgaCheckKey = UgaCheckKey; drv->UgaIo.UgaGetKey = UgaGetKey; drv->UgaIo.UgaBlt = UgaBlt; +#endif + + drv->key_count = 0; drv->key_rd = 0; diff --git a/UnixPkg/Sec/UnixThunk.c b/UnixPkg/Sec/UnixThunk.c index 8cf64b9..5dfba7a 100644 --- a/UnixPkg/Sec/UnixThunk.c +++ b/UnixPkg/Sec/UnixThunk.c @@ -1,6 +1,7 @@ /*++ -Copyright (c) 2004 - 2006, Intel Corporation +Copyright (c) 2004 - 2009, Intel Corporation +Portions copyright (c) 2008-2009 Apple Inc. All rights reserved. All rights reserved. This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -149,11 +150,136 @@ GetErrno(void) return errno; } +#if __APPLE__ +void GasketmsSleep (unsigned long Milliseconds); +void Gasketexit (int status); +void GasketSetTimer (UINT64 PeriodMs, VOID (*CallBack)(UINT64 DeltaMs)); +void GasketGetLocalTime (EFI_TIME *Time); +struct tm *Gasketgmtime (const time_t *clock); +long GasketGetTimeZone (void); +int GasketGetDayLight (void); +int Gasketpoll (struct pollfd *pfd, int nfds, int timeout); +int Gasketread (int fd, void *buf, int count); +int Gasketwrite (int fd, const void *buf, int count); +char *Gasketgetenv (const char *name); +int Gasketopen (const char *name, int flags, int mode); +off_t Gasketlseek (int fd, off_t off, int whence); +int Gasketftruncate (int fd, long int len); +int Gasketclose (int fd); +int Gasketmkdir (const char *pathname, mode_t mode); +int Gasketrmdir (const char *pathname); +int Gasketunlink (const char *pathname); +int GasketGetErrno (void); +DIR *Gasketopendir (const char *pathname); +void *Gasketrewinddir (DIR *dir); +struct dirent *Gasketreaddir (DIR *dir); +int Gasketclosedir (DIR *dir); +int Gasketstat (const char *path, struct stat *buf); +int Gasketstatfs (const char *path, struct statfs *buf); +int Gasketrename (const char *oldpath, const char *newpath); +time_t Gasketmktime (struct tm *tm); +int Gasketfsync (int fd); +int Gasketchmod (const char *path, mode_t mode); +int Gasketutime (const char *filename, const struct utimbuf *buf); +int Gaskettcflush (int fildes, int queue_selector); +EFI_STATUS GasketUgaCreate(struct _EFI_UNIX_UGA_IO_PROTOCOL **UgaIo, CONST CHAR16 *Title); +void Gasketperror (__const char *__s); + +// +// ... is always an int or pointer to device specific data structure +// +int Gasketioctl (int fd, unsigned long int __request, ...); +int Gasketfcntl (int __fd, int __cmd, ...); + +int Gasketcfsetispeed (struct termios *__termios_p, speed_t __speed); +int Gasketcfsetospeed (struct termios *__termios_p, speed_t __speed); +int Gaskettcgetattr (int __fd, struct termios *__termios_p); +int Gaskettcsetattr (int __fd, int __optional_actions, __const struct termios *__termios_p); +int Gasketsigaction (int sig, const struct sigaction *act, struct sigaction *oact); +int Gasketsetcontext (const ucontext_t *ucp); +int Gasketgetcontext (ucontext_t *ucp); +int Gasketsigemptyset (sigset_t *set); +int Gasketsigaltstack (const stack_t *ss, stack_t *oss); + +RETURN_STATUS +GasketUnixPeCoffGetEntryPoint ( + IN VOID *Pe32Data, + IN OUT VOID **EntryPoint + ); + +VOID +GasketUnixPeCoffRelocateImageExtraAction ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ); + +VOID +GasketPeCoffLoaderUnloadImageExtraAction ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ); + +#endif + extern EFI_STATUS UgaCreate(struct _EFI_UNIX_UGA_IO_PROTOCOL **UgaIo, CONST CHAR16 *Title); EFI_UNIX_THUNK_PROTOCOL mUnixThunkTable = { EFI_UNIX_THUNK_PROTOCOL_SIGNATURE, +#ifdef __APPLE__ +// +// Mac OS X requires the stack to be 16-byte aligned for IA-32. So on an OS X build +// we add an assembly wrapper that makes sure the stack ges aligned. +// This has the nice benfit of being able to run EFI ABI code, like the EFI shell +// that is checked in to source control in the OS X version of the emulator +// + GasketmsSleep, /* Sleep */ + Gasketexit, /* Exit */ + GasketSetTimer, + GasketGetLocalTime, + Gasketgmtime, + GasketGetTimeZone, + GasketGetDayLight, + (UnixPoll)Gasketpoll, + (UnixRead)Gasketread, + (UnixWrite)Gasketwrite, + Gasketgetenv, + (UnixOpen)Gasketopen, + (UnixSeek)Gasketlseek, + (UnixFtruncate)Gasketftruncate, + Gasketclose, + Gasketmkdir, + Gasketrmdir, + Gasketunlink, + GasketGetErrno, + Gasketopendir, + (UnixRewindDir)Gasketrewinddir, + Gasketreaddir, + Gasketclosedir, + Gasketstat, + Gasketstatfs, + Gasketrename, + Gasketmktime, + Gasketfsync, + Gasketchmod, + Gasketutime, + Gaskettcflush, + GasketUgaCreate, + Gasketperror, + Gasketioctl, + Gasketfcntl, + Gasketcfsetispeed, + Gasketcfsetospeed, + Gaskettcgetattr, + Gaskettcsetattr, + + dlopen, // Update me with a gasket + dlerror, // Update me with a gasket + dlsym, // Update me with a gasket + + SecPeCoffGetEntryPoint, // Update me with a gasket + SecPeCoffRelocateImageExtraAction, // Update me with a gasket + SecPeCoffLoaderUnloadImageExtraAction // Update me with a gasket + +#else msSleep, /* Sleep */ exit, /* Exit */ SetTimer, @@ -166,8 +292,8 @@ EFI_UNIX_THUNK_PROTOCOL mUnixThunkTable = { (UnixWrite)write, getenv, (UnixOpen)open, - lseek, - ftruncate, + (UnixSeek)lseek, + (UnixFtruncate)ftruncate, close, mkdir, rmdir, @@ -195,7 +321,11 @@ EFI_UNIX_THUNK_PROTOCOL mUnixThunkTable = { tcsetattr, dlopen, dlerror, - dlsym + dlsym, + SecPeCoffGetEntryPoint, + SecPeCoffRelocateImageExtraAction, + SecPeCoffLoaderUnloadImageExtraAction +#endif }; |