From bb89ec1a7ec2f8d35033df9e47b3604925da3bd3 Mon Sep 17 00:00:00 2001 From: jljusten Date: Tue, 28 Jun 2011 16:47:23 +0000 Subject: InOsEmuPkg: Rename package to EmulatorPkg & Sec to Host * Rename InOsEmuPkg to EmulatorPkg * Rename Unix/Sec to Unix/Host Signed-off-by: jljusten Reviewed-by: andrewfish Reviewed-by: geekboy15a git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11918 6f19259b-4bc3-4df7-8a09-765794883524 --- EmulatorPkg/Unix/.gdbinit | 8 + EmulatorPkg/Unix/GdbRun | 79 + EmulatorPkg/Unix/Host/BerkeleyPacketFilter.c | 1111 +++++++++++++ EmulatorPkg/Unix/Host/BlockIo.c | 706 +++++++++ EmulatorPkg/Unix/Host/EmuThunk.c | 432 ++++++ EmulatorPkg/Unix/Host/Gasket.h | 651 ++++++++ EmulatorPkg/Unix/Host/Ia32/Gasket.S | 1492 ++++++++++++++++++ EmulatorPkg/Unix/Host/Ia32/SwitchStack.c | 74 + EmulatorPkg/Unix/Host/LinuxPacketFilter.c | 604 ++++++++ EmulatorPkg/Unix/Host/MemoryAllocationLib.c | 145 ++ EmulatorPkg/Unix/Host/PosixFileSystem.c | 1556 +++++++++++++++++++ EmulatorPkg/Unix/Host/Pthreads.c | 235 +++ EmulatorPkg/Unix/Host/SecMain.c | 1226 +++++++++++++++ EmulatorPkg/Unix/Host/SecMain.h | 356 +++++ EmulatorPkg/Unix/Host/SecMain.inf | 140 ++ EmulatorPkg/Unix/Host/X11GraphicsWindow.c | 1028 ++++++++++++ EmulatorPkg/Unix/Host/X64/Gasket.S | 1631 ++++++++++++++++++++ EmulatorPkg/Unix/Host/X64/SwitchStack.S | 53 + EmulatorPkg/Unix/UnixX64.dsc | 455 ++++++ EmulatorPkg/Unix/UnixX64.fdf | 395 +++++ .../Unix/Xcode/xcode_project32/XcodeBuild.sh | 24 + .../xcode_project.xcodeproj/default.pbxuser | 191 +++ .../xcode_project.xcodeproj/project.pbxproj | 124 ++ .../Unix/Xcode/xcode_project64/XcodeBuild.sh | 24 + .../xcode_project.xcodeproj/default.pbxuser | 191 +++ .../xcode_project.xcodeproj/project.pbxproj | 124 ++ EmulatorPkg/Unix/build.sh | 137 ++ EmulatorPkg/Unix/build64.sh | 138 ++ 28 files changed, 13330 insertions(+) create mode 100644 EmulatorPkg/Unix/.gdbinit create mode 100644 EmulatorPkg/Unix/GdbRun create mode 100644 EmulatorPkg/Unix/Host/BerkeleyPacketFilter.c create mode 100644 EmulatorPkg/Unix/Host/BlockIo.c create mode 100644 EmulatorPkg/Unix/Host/EmuThunk.c create mode 100644 EmulatorPkg/Unix/Host/Gasket.h create mode 100644 EmulatorPkg/Unix/Host/Ia32/Gasket.S create mode 100644 EmulatorPkg/Unix/Host/Ia32/SwitchStack.c create mode 100644 EmulatorPkg/Unix/Host/LinuxPacketFilter.c create mode 100644 EmulatorPkg/Unix/Host/MemoryAllocationLib.c create mode 100644 EmulatorPkg/Unix/Host/PosixFileSystem.c create mode 100644 EmulatorPkg/Unix/Host/Pthreads.c create mode 100644 EmulatorPkg/Unix/Host/SecMain.c create mode 100644 EmulatorPkg/Unix/Host/SecMain.h create mode 100644 EmulatorPkg/Unix/Host/SecMain.inf create mode 100644 EmulatorPkg/Unix/Host/X11GraphicsWindow.c create mode 100644 EmulatorPkg/Unix/Host/X64/Gasket.S create mode 100644 EmulatorPkg/Unix/Host/X64/SwitchStack.S create mode 100644 EmulatorPkg/Unix/UnixX64.dsc create mode 100644 EmulatorPkg/Unix/UnixX64.fdf create mode 100755 EmulatorPkg/Unix/Xcode/xcode_project32/XcodeBuild.sh create mode 100644 EmulatorPkg/Unix/Xcode/xcode_project32/xcode_project.xcodeproj/default.pbxuser create mode 100644 EmulatorPkg/Unix/Xcode/xcode_project32/xcode_project.xcodeproj/project.pbxproj create mode 100755 EmulatorPkg/Unix/Xcode/xcode_project64/XcodeBuild.sh create mode 100644 EmulatorPkg/Unix/Xcode/xcode_project64/xcode_project.xcodeproj/default.pbxuser create mode 100644 EmulatorPkg/Unix/Xcode/xcode_project64/xcode_project.xcodeproj/project.pbxproj create mode 100755 EmulatorPkg/Unix/build.sh create mode 100755 EmulatorPkg/Unix/build64.sh (limited to 'EmulatorPkg/Unix') diff --git a/EmulatorPkg/Unix/.gdbinit b/EmulatorPkg/Unix/.gdbinit new file mode 100644 index 0000000000..173818c0e7 --- /dev/null +++ b/EmulatorPkg/Unix/.gdbinit @@ -0,0 +1,8 @@ +set confirm off +set output-radix 16 +b SecGdbScriptBreak +command +silent +source SecMain.gdb +c +end diff --git a/EmulatorPkg/Unix/GdbRun b/EmulatorPkg/Unix/GdbRun new file mode 100644 index 0000000000..428e655631 --- /dev/null +++ b/EmulatorPkg/Unix/GdbRun @@ -0,0 +1,79 @@ +## @file +# GDB startup script +# +# Copyright (c) 2011, Intel Corporation. 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. +# +## + +# +# Gdb will set $_exitcode when the program exits. Pre-init it to an unlikely +# return value. +# +set $_exitcode = 42 + +# +# Gdb will call hook-stop on each break. Check to see if $_exitcode was +# changed from the value we pre-initialized it to. If so, the program +# had exited, so gdb should now quit. +# +define hook-stop + if $_exitcode != 42 + quit + else + source SecMain.gdb + end +end + +# +# We keep track of the number of symbol files we have loaded via gdb +# scripts in the $SymbolFilesAdded variable +# +set $SymbolFileChangesCount = 0 + +# +# This macro adds a symbols file for gdb +# +# @param $arg0 - Symbol file changes number +# @param $arg1 - Symbol file name +# @param $arg2 - Image address +# +define AddFirmwareSymbolFile + if $SymbolFileChangesCount < $arg0 + add-symbol-file $arg1 $arg2 + set $SymbolFileChangesCount = $arg0 + end +end + +# +# This macro removes a symbols file for gdb +# +# @param $arg0 - Symbol file changes number +# @param $arg1 - Symbol file name +# +define RemoveFirmwareSymbolFile + if $SymbolFileChangesCount < $arg0 + # + # Currently there is not a method to remove a single symbol file + # + set $SymbolFileChangesCount = $arg0 + end +end + +if gInXcode == 1 + # in Xcode the program is already runing. Issuing a run command + # will cause a fatal debugger error. The break point sciprt that + # is used to source this script sets gInCode to 1. +else + # + # Start the program running + # + run +end diff --git a/EmulatorPkg/Unix/Host/BerkeleyPacketFilter.c b/EmulatorPkg/Unix/Host/BerkeleyPacketFilter.c new file mode 100644 index 0000000000..519d394e37 --- /dev/null +++ b/EmulatorPkg/Unix/Host/BerkeleyPacketFilter.c @@ -0,0 +1,1111 @@ +/**@file + Berkeley Packet Filter implementation of the EMU_SNP_PROTOCOL that allows the + emulator to get on real networks. + + Tested on Mac OS X. + +Copyright (c) 2004 - 2009, Intel Corporation. All rights reserved.
+Portitions copyright (c) 2011, 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. + +**/ + + +#include "SecMain.h" + +#ifdef __APPLE__ + + +#include + + +#define EMU_SNP_PRIVATE_SIGNATURE SIGNATURE_32('E', 'M', 's', 'n') +typedef struct { + UINTN Signature; + + EMU_IO_THUNK_PROTOCOL *Thunk; + EMU_SNP_PROTOCOL EmuSnp; + EFI_SIMPLE_NETWORK_MODE *Mode; + + int BpfFd; + char *InterfaceName; + EFI_MAC_ADDRESS MacAddress; + u_int ReadBufferSize; + VOID *ReadBuffer; + + // + // Two walking pointers to manage the multiple packets that can be returned + // in a single read. + // + VOID *CurrentReadPointer; + VOID *EndReadPointer; + + UINT32 ReceivedPackets; + UINT32 DroppedPackets; + +} EMU_SNP_PRIVATE; + +#define EMU_SNP_PRIVATE_DATA_FROM_THIS(a) \ + CR(a, EMU_SNP_PRIVATE, EmuSnp, EMU_SNP_PRIVATE_SIGNATURE) + + +// +// Strange, but there doesn't appear to be any structure for the Ethernet header in edk2... +// + +typedef struct { + UINT8 DstAddr[NET_ETHER_ADDR_LEN]; + UINT8 SrcAddr[NET_ETHER_ADDR_LEN]; + UINT16 Type; +} ETHERNET_HEADER; + +/** + Register storage for SNP Mode. + + @param This Protocol instance pointer. + @param Mode SimpleNetworkProtocol Mode structure passed into driver. + + @retval EFI_SUCCESS The network interface was started. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + +**/ +EFI_STATUS +EmuSnpCreateMapping ( + IN EMU_SNP_PROTOCOL *This, + IN EFI_SIMPLE_NETWORK_MODE *Mode + ) +{ + EMU_SNP_PRIVATE *Private; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + Private->Mode = Mode; + + // + // Set the broadcast address. + // + SetMem (&Mode->BroadcastAddress, sizeof (EFI_MAC_ADDRESS), 0xFF); + + CopyMem (&Mode->CurrentAddress, &Private->MacAddress, sizeof (EFI_MAC_ADDRESS)); + CopyMem (&Mode->PermanentAddress, &Private->MacAddress, sizeof (EFI_MAC_ADDRESS)); + + // + // Since the fake SNP is based on a real NIC, to avoid conflict with the host NIC + // network stack, we use a different MAC address. + // So just change the last byte of the MAC address for the real NIC. + // + Mode->CurrentAddress.Addr[NET_ETHER_ADDR_LEN - 1]++; + + return EFI_SUCCESS; +} + + +static struct bpf_insn mFilterInstructionTemplate[] = { + // Load 4 bytes from the destination MAC address. + BPF_STMT (BPF_LD + BPF_W + BPF_ABS, OFFSET_OF (ETHERNET_HEADER, DstAddr[0])), + + // Compare to first 4 bytes of fake MAC address. + BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 0x12345678, 0, 3 ), + + // Load remaining 2 bytes from the destination MAC address. + BPF_STMT (BPF_LD + BPF_H + BPF_ABS, OFFSET_OF( ETHERNET_HEADER, DstAddr[4])), + + // Compare to remaining 2 bytes of fake MAC address. + BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 0x9ABC, 5, 0 ), + + // Load 4 bytes from the destination MAC address. + BPF_STMT (BPF_LD + BPF_W + BPF_ABS, OFFSET_OF (ETHERNET_HEADER, DstAddr[0])), + + // Compare to first 4 bytes of broadcast MAC address. + BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 0xFFFFFFFF, 0, 2), + + // Load remaining 2 bytes from the destination MAC address. + BPF_STMT (BPF_LD + BPF_H + BPF_ABS, OFFSET_OF( ETHERNET_HEADER, DstAddr[4])), + + // Compare to remaining 2 bytes of broadcast MAC address. + BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 0xFFFF, 1, 0), + + // Reject packet. + BPF_STMT (BPF_RET + BPF_K, 0), + + // Receive entire packet. + BPF_STMT (BPF_RET + BPF_K, -1) +}; + + +EFI_STATUS +OpenBpfFileDescriptor ( + IN EMU_SNP_PRIVATE *Private, + OUT int *Fd + ) +{ + char BfpDeviceName[256]; + int Index; + + // + // Open a Berkeley Packet Filter device. This must be done as root, so this is probably + // the place which is most likely to fail... + // + for (Index = 0; TRUE; Index++ ) { + snprintf (BfpDeviceName, sizeof (BfpDeviceName), "/dev/bpf%d", Index); + + *Fd = open (BfpDeviceName, O_RDWR, 0); + if ( *Fd >= 0 ) { + return EFI_SUCCESS; + } + + if (errno == EACCES) { + printf ( + "SNP: Permissions on '%s' are incorrect. Fix with 'sudo chmod 666 %s'.\n", + BfpDeviceName, + BfpDeviceName + ); + } + + if (errno != EBUSY) { + break; + } + } + + return EFI_OUT_OF_RESOURCES; +} + + +/** + Changes the state of a network interface from "stopped" to "started". + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The network interface was started. + @retval EFI_ALREADY_STARTED The network interface is already in the started state. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EmuSnpStart ( + IN EMU_SNP_PROTOCOL *This + ) +{ + EFI_STATUS Status; + EMU_SNP_PRIVATE *Private; + struct ifreq BoundIf; + struct bpf_program BpfProgram; + struct bpf_insn *FilterProgram; + u_int Value; + u_int ReadBufferSize; + UINT16 Temp16; + UINT32 Temp32; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + switch (Private->Mode->State) { + case EfiSimpleNetworkStopped: + break; + + case EfiSimpleNetworkStarted: + case EfiSimpleNetworkInitialized: + return EFI_ALREADY_STARTED; + break; + + default: + return EFI_DEVICE_ERROR; + break; + } + + Status = EFI_SUCCESS; + if (Private->BpfFd == 0) { + Status = OpenBpfFileDescriptor (Private, &Private->BpfFd); + if (EFI_ERROR (Status)) { + goto DeviceErrorExit; + } + + // + // Get the read buffer size. + // + if (ioctl (Private->BpfFd, BIOCGBLEN, &ReadBufferSize) < 0) { + goto DeviceErrorExit; + } + + // + // Default value from BIOCGBLEN is usually too small, so use a much larger size, if necessary. + // + if (ReadBufferSize < FixedPcdGet32 (PcdNetworkPacketFilterSize)) { + ReadBufferSize = FixedPcdGet32 (PcdNetworkPacketFilterSize); + if (ioctl (Private->BpfFd, BIOCSBLEN, &ReadBufferSize) < 0) { + goto DeviceErrorExit; + } + } + + // + // Associate our interface with this BPF file descriptor. + // + AsciiStrCpy (BoundIf.ifr_name, Private->InterfaceName); + if (ioctl (Private->BpfFd, BIOCSETIF, &BoundIf) < 0) { + goto DeviceErrorExit; + } + + // + // Enable immediate mode. + // + Value = 1; + if (ioctl (Private->BpfFd, BIOCIMMEDIATE, &Value) < 0) { + goto DeviceErrorExit; + } + + // + // Enable non-blocking I/O. + // + if (fcntl (Private->BpfFd, F_GETFL, 0) == -1) { + goto DeviceErrorExit; + } + + Value |= O_NONBLOCK; + + if (fcntl (Private->BpfFd, F_SETFL, Value) == -1) { + goto DeviceErrorExit; + } + + // + // Disable "header complete" flag. This means the supplied source MAC address is + // what goes on the wire. + // + Value = 1; + if (ioctl (Private->BpfFd, BIOCSHDRCMPLT, &Value) < 0) { + goto DeviceErrorExit; + } + + // + // Allocate read buffer. + // + Private->ReadBufferSize = ReadBufferSize; + Private->ReadBuffer = malloc (Private->ReadBufferSize); + if (Private->ReadBuffer == NULL) { + goto ErrorExit; + } + + Private->CurrentReadPointer = Private->EndReadPointer = Private->ReadBuffer; + + // + // Install our packet filter: successful reads should only produce broadcast or unicast + // packets directed to our fake MAC address. + // + FilterProgram = malloc (sizeof (mFilterInstructionTemplate)) ; + if ( FilterProgram == NULL ) { + goto ErrorExit; + } + + CopyMem (FilterProgram, &mFilterInstructionTemplate, sizeof (mFilterInstructionTemplate)); + + // + // Insert out fake MAC address into the filter. The data has to be host endian. + // + CopyMem (&Temp32, &Private->Mode->CurrentAddress.Addr[0], sizeof (UINT32)); + FilterProgram[1].k = NTOHL (Temp32); + CopyMem (&Temp16, &Private->Mode->CurrentAddress.Addr[4], sizeof (UINT16)); + FilterProgram[3].k = NTOHS (Temp16); + + BpfProgram.bf_len = sizeof (mFilterInstructionTemplate) / sizeof (struct bpf_insn); + BpfProgram.bf_insns = FilterProgram; + + if (ioctl (Private->BpfFd, BIOCSETF, &BpfProgram) < 0) { + goto DeviceErrorExit; + } + + free (FilterProgram); + + // + // Enable promiscuous mode. + // + if (ioctl (Private->BpfFd, BIOCPROMISC, 0) < 0) { + goto DeviceErrorExit; + } + + + Private->Mode->State = EfiSimpleNetworkStarted; + } + + return Status; + +DeviceErrorExit: + Status = EFI_DEVICE_ERROR; +ErrorExit: + if (Private->ReadBuffer != NULL) { + free (Private->ReadBuffer); + Private->ReadBuffer = NULL; + } + return Status; +} + + +/** + Changes the state of a network interface from "started" to "stopped". + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The network interface was stopped. + @retval EFI_ALREADY_STARTED The network interface is already in the stopped state. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EmuSnpStop ( + IN EMU_SNP_PROTOCOL *This + ) +{ + EMU_SNP_PRIVATE *Private; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + switch ( Private->Mode->State ) { + case EfiSimpleNetworkStarted: + break; + + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + break; + + default: + return EFI_DEVICE_ERROR; + break; + } + + if (Private->BpfFd != 0) { + close (Private->BpfFd); + Private->BpfFd = 0; + } + + if (Private->ReadBuffer != NULL) { + free (Private->ReadBuffer ); + Private->CurrentReadPointer = Private->EndReadPointer = Private->ReadBuffer = NULL; + } + + Private->Mode->State = EfiSimpleNetworkStopped; + + return EFI_SUCCESS; +} + + +/** + Resets a network adapter and allocates the transmit and receive buffers + required by the network interface; optionally, also requests allocation + of additional transmit and receive buffers. + + @param This The protocol instance pointer. + @param ExtraRxBufferSize The size, in bytes, of the extra receive buffer space + that the driver should allocate for the network interface. + Some network interfaces will not be able to use the extra + buffer, and the caller will not know if it is actually + being used. + @param ExtraTxBufferSize The size, in bytes, of the extra transmit buffer space + that the driver should allocate for the network interface. + Some network interfaces will not be able to use the extra + buffer, and the caller will not know if it is actually + being used. + + @retval EFI_SUCCESS The network interface was initialized. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_OUT_OF_RESOURCES There was not enough memory for the transmit and + receive buffers. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EmuSnpInitialize ( + IN EMU_SNP_PROTOCOL *This, + IN UINTN ExtraRxBufferSize OPTIONAL, + IN UINTN ExtraTxBufferSize OPTIONAL + ) +{ + EMU_SNP_PRIVATE *Private; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + switch ( Private->Mode->State ) { + case EfiSimpleNetworkStarted: + break; + + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + break; + + default: + return EFI_DEVICE_ERROR; + break; + } + + Private->Mode->MCastFilterCount = 0; + Private->Mode->ReceiveFilterSetting = 0; + ZeroMem (Private->Mode->MCastFilter, sizeof (Private->Mode->MCastFilter)); + + Private->Mode->State = EfiSimpleNetworkInitialized; + + return EFI_SUCCESS; +} + + +/** + Resets a network adapter and re-initializes it with the parameters that were + provided in the previous call to Initialize(). + + @param This The protocol instance pointer. + @param ExtendedVerification Indicates that the driver may perform a more + exhaustive verification operation of the device + during reset. + + @retval EFI_SUCCESS The network interface was reset. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EmuSnpReset ( + IN EMU_SNP_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + EMU_SNP_PRIVATE *Private; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + switch ( Private->Mode->State ) { + case EfiSimpleNetworkInitialized: + break; + + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + break; + + default: + return EFI_DEVICE_ERROR; + break; + } + + return EFI_SUCCESS; +} + + +/** + Resets a network adapter and leaves it in a state that is safe for + another driver to initialize. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The network interface was shutdown. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EmuSnpShutdown ( + IN EMU_SNP_PROTOCOL *This + ) +{ + EMU_SNP_PRIVATE *Private; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + switch ( Private->Mode->State ) { + case EfiSimpleNetworkInitialized: + break; + + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + break; + + default: + return EFI_DEVICE_ERROR; + break; + } + + Private->Mode->State = EfiSimpleNetworkStarted; + + Private->Mode->ReceiveFilterSetting = 0; + Private->Mode->MCastFilterCount = 0; + ZeroMem (Private->Mode->MCastFilter, sizeof (Private->Mode->MCastFilter)); + + if (Private->BpfFd != 0) { + close (Private->BpfFd); + Private->BpfFd = 0; + } + + if (Private->ReadBuffer != NULL) { + free (Private->ReadBuffer); + Private->CurrentReadPointer = Private->EndReadPointer = Private->ReadBuffer = NULL; + } + + return EFI_SUCCESS; +} + +/** + Manages the multicast receive filters of a network interface. + + @param This The protocol instance pointer. + @param Enable A bit mask of receive filters to enable on the network interface. + @param Disable A bit mask of receive filters to disable on the network interface. + @param ResetMCastFilter Set to TRUE to reset the contents of the multicast receive + filters on the network interface to their default values. + @param McastFilterCnt Number of multicast HW MAC addresses in the new + MCastFilter list. This value must be less than or equal to + the MCastFilterCnt field of EMU_SNP_MODE. This + field is optional if ResetMCastFilter is TRUE. + @param MCastFilter A pointer to a list of new multicast receive filter HW MAC + addresses. This list will replace any existing multicast + HW MAC address list. This field is optional if + ResetMCastFilter is TRUE. + + @retval EFI_SUCCESS The multicast receive filter list was updated. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EmuSnpReceiveFilters ( + IN EMU_SNP_PROTOCOL *This, + IN UINT32 Enable, + IN UINT32 Disable, + IN BOOLEAN ResetMCastFilter, + IN UINTN MCastFilterCnt OPTIONAL, + IN EFI_MAC_ADDRESS *MCastFilter OPTIONAL + ) +{ + EMU_SNP_PRIVATE *Private; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + // For now, just succeed... + return EFI_SUCCESS; +} + + +/** + Modifies or resets the current station address, if supported. + + @param This The protocol instance pointer. + @param Reset Flag used to reset the station address to the network interfaces + permanent address. + @param New The new station address to be used for the network interface. + + @retval EFI_SUCCESS The network interfaces station address was updated. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EmuSnpStationAddress ( + IN EMU_SNP_PROTOCOL *This, + IN BOOLEAN Reset, + IN EFI_MAC_ADDRESS *New OPTIONAL + ) +{ + EMU_SNP_PRIVATE *Private; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + return EFI_UNSUPPORTED; +} + + +/** + Resets or collects the statistics on a network interface. + + @param This Protocol instance pointer. + @param Reset Set to TRUE to reset the statistics for the network interface. + @param StatisticsSize On input the size, in bytes, of StatisticsTable. On + output the size, in bytes, of the resulting table of + statistics. + @param StatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that + contains the statistics. + + @retval EFI_SUCCESS The statistics were collected from the network interface. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_BUFFER_TOO_SMALL The Statistics buffer was too small. The current buffer + size needed to hold the statistics is returned in + StatisticsSize. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EmuSnpStatistics ( + IN EMU_SNP_PROTOCOL *This, + IN BOOLEAN Reset, + IN OUT UINTN *StatisticsSize OPTIONAL, + OUT EFI_NETWORK_STATISTICS *StatisticsTable OPTIONAL + ) +{ + EMU_SNP_PRIVATE *Private; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + return EFI_UNSUPPORTED; +} + + +/** + Converts a multicast IP address to a multicast HW MAC address. + + @param This The protocol instance pointer. + @param IPv6 Set to TRUE if the multicast IP address is IPv6 [RFC 2460]. Set + to FALSE if the multicast IP address is IPv4 [RFC 791]. + @param IP The multicast IP address that is to be converted to a multicast + HW MAC address. + @param MAC The multicast HW MAC address that is to be generated from IP. + + @retval EFI_SUCCESS The multicast IP address was mapped to the multicast + HW MAC address. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_BUFFER_TOO_SMALL The Statistics buffer was too small. The current buffer + size needed to hold the statistics is returned in + StatisticsSize. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EmuSnpMCastIpToMac ( + IN EMU_SNP_PROTOCOL *This, + IN BOOLEAN IPv6, + IN EFI_IP_ADDRESS *IP, + OUT EFI_MAC_ADDRESS *MAC + ) +{ + EMU_SNP_PRIVATE *Private; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + return EFI_UNSUPPORTED; +} + + +/** + Performs read and write operations on the NVRAM device attached to a + network interface. + + @param This The protocol instance pointer. + @param ReadWrite TRUE for read operations, FALSE for write operations. + @param Offset Byte offset in the NVRAM device at which to start the read or + write operation. This must be a multiple of NvRamAccessSize and + less than NvRamSize. + @param BufferSize The number of bytes to read or write from the NVRAM device. + This must also be a multiple of NvramAccessSize. + @param Buffer A pointer to the data buffer. + + @retval EFI_SUCCESS The NVRAM access was performed. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EmuSnpNvData ( + IN EMU_SNP_PROTOCOL *This, + IN BOOLEAN ReadWrite, + IN UINTN Offset, + IN UINTN BufferSize, + IN OUT VOID *Buffer + ) +{ + EMU_SNP_PRIVATE *Private; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + return EFI_UNSUPPORTED; +} + +/** + Reads the current interrupt status and recycled transmit buffer status from + a network interface. + + @param This The protocol instance pointer. + @param InterruptStatus A pointer to the bit mask of the currently active interrupts + If this is NULL, the interrupt status will not be read from + the device. If this is not NULL, the interrupt status will + be read from the device. When the interrupt status is read, + it will also be cleared. Clearing the transmit interrupt + does not empty the recycled transmit buffer array. + @param TxBuf Recycled transmit buffer address. The network interface will + not transmit if its internal recycled transmit buffer array + is full. Reading the transmit buffer does not clear the + transmit interrupt. If this is NULL, then the transmit buffer + status will not be read. If there are no transmit buffers to + recycle and TxBuf is not NULL, * TxBuf will be set to NULL. + + @retval EFI_SUCCESS The status of the network interface was retrieved. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EmuSnpGetStatus ( + IN EMU_SNP_PROTOCOL *This, + OUT UINT32 *InterruptStatus OPTIONAL, + OUT VOID **TxBuf OPTIONAL + ) +{ + EMU_SNP_PRIVATE *Private; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + if (TxBuf != NULL) { + *((UINT8 **)TxBuf) = (UINT8 *)1; + } + + if ( InterruptStatus != NULL ) { + *InterruptStatus = EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT; + } + + return EFI_SUCCESS; +} + + +/** + Places a packet in the transmit queue of a network interface. + + @param This The protocol instance pointer. + @param HeaderSize The size, in bytes, of the media header to be filled in by + the Transmit() function. If HeaderSize is non-zero, then it + must be equal to This->Mode->MediaHeaderSize and the DestAddr + and Protocol parameters must not be NULL. + @param BufferSize The size, in bytes, of the entire packet (media header and + data) to be transmitted through the network interface. + @param Buffer A pointer to the packet (media header followed by data) to be + transmitted. This parameter cannot be NULL. If HeaderSize is zero, + then the media header in Buffer must already be filled in by the + caller. If HeaderSize is non-zero, then the media header will be + filled in by the Transmit() function. + @param SrcAddr The source HW MAC address. If HeaderSize is zero, then this parameter + is ignored. If HeaderSize is non-zero and SrcAddr is NULL, then + This->Mode->CurrentAddress is used for the source HW MAC address. + @param DestAddr The destination HW MAC address. If HeaderSize is zero, then this + parameter is ignored. + @param Protocol The type of header to build. If HeaderSize is zero, then this + parameter is ignored. See RFC 1700, section "Ether Types", for + examples. + + @retval EFI_SUCCESS The packet was placed on the transmit queue. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_NOT_READY The network interface is too busy to accept this transmit request. + @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EmuSnpTransmit ( + IN EMU_SNP_PROTOCOL *This, + IN UINTN HeaderSize, + IN UINTN BufferSize, + IN VOID *Buffer, + IN EFI_MAC_ADDRESS *SrcAddr OPTIONAL, + IN EFI_MAC_ADDRESS *DestAddr OPTIONAL, + IN UINT16 *Protocol OPTIONAL + ) +{ + EMU_SNP_PRIVATE *Private; + ETHERNET_HEADER *EnetHeader; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + if (Private->Mode->State < EfiSimpleNetworkStarted) { + return EFI_NOT_STARTED; + } + + if ( HeaderSize != 0 ) { + if ((DestAddr == NULL) || (Protocol == NULL) || (HeaderSize != Private->Mode->MediaHeaderSize)) { + return EFI_INVALID_PARAMETER; + } + + if (SrcAddr == NULL) { + SrcAddr = &Private->Mode->CurrentAddress; + } + + EnetHeader = (ETHERNET_HEADER *) Buffer; + + CopyMem (EnetHeader->DstAddr, DestAddr, NET_ETHER_ADDR_LEN); + CopyMem (EnetHeader->SrcAddr, SrcAddr, NET_ETHER_ADDR_LEN); + + EnetHeader->Type = HTONS(*Protocol); + } + + if (write (Private->BpfFd, Buffer, BufferSize) < 0) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** + Receives a packet from a network interface. + + @param This The protocol instance pointer. + @param HeaderSize The size, in bytes, of the media header received on the network + interface. If this parameter is NULL, then the media header size + will not be returned. + @param BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in + bytes, of the packet that was received on the network interface. + @param Buffer A pointer to the data buffer to receive both the media header and + the data. + @param SrcAddr The source HW MAC address. If this parameter is NULL, the + HW MAC source address will not be extracted from the media + header. + @param DestAddr The destination HW MAC address. If this parameter is NULL, + the HW MAC destination address will not be extracted from the + media header. + @param Protocol The media header type. If this parameter is NULL, then the + protocol will not be extracted from the media header. See + RFC 1700 section "Ether Types" for examples. + + @retval EFI_SUCCESS The received data was stored in Buffer, and BufferSize has + been updated to the number of bytes received. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_NOT_READY The network interface is too busy to accept this transmit + request. + @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EmuSnpReceive ( + IN EMU_SNP_PROTOCOL *This, + OUT UINTN *HeaderSize OPTIONAL, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer, + OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL, + OUT EFI_MAC_ADDRESS *DestAddr OPTIONAL, + OUT UINT16 *Protocol OPTIONAL + ) +{ + EMU_SNP_PRIVATE *Private; + struct bpf_hdr *BpfHeader; + struct bpf_stat BpfStats; + ETHERNET_HEADER *EnetHeader; + ssize_t Result; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + if (Private->Mode->State < EfiSimpleNetworkStarted) { + return EFI_NOT_STARTED; + } + + ZeroMem (&BpfStats, sizeof( BpfStats)); + + if (ioctl (Private->BpfFd, BIOCGSTATS, &BpfStats) == 0) { + Private->ReceivedPackets += BpfStats.bs_recv; + if (BpfStats.bs_drop > Private->DroppedPackets) { + printf ( + "SNP: STATS: RCVD = %d DROPPED = %d. Probably need to increase BPF PcdNetworkPacketFilterSize?\n", + BpfStats.bs_recv, + BpfStats.bs_drop - Private->DroppedPackets + ); + Private->DroppedPackets = BpfStats.bs_drop; + } + } + + // + // Do we have any remaining packets from the previous read? + // + if (Private->CurrentReadPointer >= Private->EndReadPointer) { + Result = read (Private->BpfFd, Private->ReadBuffer, Private->ReadBufferSize); + if (Result < 0) { + // EAGAIN means that there's no I/O outstanding against this file descriptor. + return (errno == EAGAIN) ? EFI_NOT_READY : EFI_DEVICE_ERROR; + } + + if (Result == 0) { + return EFI_NOT_READY; + } + + Private->CurrentReadPointer = Private->ReadBuffer; + Private->EndReadPointer = Private->CurrentReadPointer + Result; + } + + BpfHeader = Private->CurrentReadPointer; + EnetHeader = Private->CurrentReadPointer + BpfHeader->bh_hdrlen; + + if (BpfHeader->bh_caplen > *BufferSize) { + *BufferSize = BpfHeader->bh_caplen; + return EFI_BUFFER_TOO_SMALL; + } + + CopyMem (Buffer, EnetHeader, BpfHeader->bh_caplen); + *BufferSize = BpfHeader->bh_caplen; + + if (HeaderSize != NULL) { + *HeaderSize = sizeof (ETHERNET_HEADER); + } + + if (DestAddr != NULL) { + ZeroMem (DestAddr, sizeof (EFI_MAC_ADDRESS)); + CopyMem (DestAddr, EnetHeader->DstAddr, NET_ETHER_ADDR_LEN); + } + + if (SrcAddr != NULL) { + ZeroMem (SrcAddr, sizeof (EFI_MAC_ADDRESS)); + CopyMem (SrcAddr, EnetHeader->SrcAddr, NET_ETHER_ADDR_LEN); + } + + if (Protocol != NULL) { + *Protocol = NTOHS (EnetHeader->Type); + } + + Private->CurrentReadPointer += BPF_WORDALIGN (BpfHeader->bh_hdrlen + BpfHeader->bh_caplen); + return EFI_SUCCESS; +} + + +EMU_SNP_PROTOCOL gEmuSnpProtocol = { + GasketSnpCreateMapping, + GasketSnpStart, + GasketSnpStop, + GasketSnpInitialize, + GasketSnpReset, + GasketSnpShutdown, + GasketSnpReceiveFilters, + GasketSnpStationAddress, + GasketSnpStatistics, + GasketSnpMCastIpToMac, + GasketSnpNvData, + GasketSnpGetStatus, + GasketSnpTransmit, + GasketSnpReceive +}; + +EFI_STATUS +GetInterfaceMacAddr ( + EMU_SNP_PRIVATE *Private + ) +{ + EFI_STATUS Status; + struct ifaddrs *IfAddrs; + struct ifaddrs *If; + struct sockaddr_dl *IfSdl; + + if (getifaddrs (&IfAddrs) != 0) { + return EFI_UNSUPPORTED; + } + + // + // Convert the interface name to ASCII so we can find it. + // + Private->InterfaceName = malloc (StrSize (Private->Thunk->ConfigString)); + if (Private->InterfaceName == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + UnicodeStrToAsciiStr (Private->Thunk->ConfigString, Private->InterfaceName); + + Status = EFI_NOT_FOUND; + If = IfAddrs; + while (If != NULL) { + IfSdl = (struct sockaddr_dl *)If->ifa_addr; + + if (IfSdl->sdl_family == AF_LINK) { + if (!AsciiStrCmp( Private->InterfaceName, If->ifa_name)) { + CopyMem (&Private->MacAddress, LLADDR (IfSdl), NET_ETHER_ADDR_LEN); + + Status = EFI_SUCCESS; + break; + } + } + + If = If->ifa_next; + } + +Exit: + freeifaddrs (IfAddrs); + return Status; +} + + +EFI_STATUS +EmuSnpThunkOpen ( + IN EMU_IO_THUNK_PROTOCOL *This + ) +{ + EMU_SNP_PRIVATE *Private; + + if (This->Private != NULL) { + return EFI_ALREADY_STARTED; + } + + if (!CompareGuid (This->Protocol, &gEmuSnpProtocolGuid)) { + return EFI_UNSUPPORTED; + } + + Private = malloc (sizeof (EMU_SNP_PRIVATE)); + if (Private == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + + Private->Signature = EMU_SNP_PRIVATE_SIGNATURE; + Private->Thunk = This; + CopyMem (&Private->EmuSnp, &gEmuSnpProtocol, sizeof (gEmuSnpProtocol)); + GetInterfaceMacAddr (Private); + + This->Interface = &Private->EmuSnp; + This->Private = Private; + return EFI_SUCCESS; +} + + +EFI_STATUS +EmuSnpThunkClose ( + IN EMU_IO_THUNK_PROTOCOL *This + ) +{ + EMU_SNP_PRIVATE *Private; + + if (!CompareGuid (This->Protocol, &gEmuSnpProtocolGuid)) { + return EFI_UNSUPPORTED; + } + + Private = This->Private; + free (Private); + + return EFI_SUCCESS; +} + + + +EMU_IO_THUNK_PROTOCOL gSnpThunkIo = { + &gEmuSnpProtocolGuid, + NULL, + NULL, + 0, + GasketSnpThunkOpen, + GasketSnpThunkClose, + NULL +}; + +#endif diff --git a/EmulatorPkg/Unix/Host/BlockIo.c b/EmulatorPkg/Unix/Host/BlockIo.c new file mode 100644 index 0000000000..bb2da24d85 --- /dev/null +++ b/EmulatorPkg/Unix/Host/BlockIo.c @@ -0,0 +1,706 @@ +/**@file + +Copyright (c) 2004 - 2009, Intel Corporation. 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 "SecMain.h" + +#define EMU_BLOCK_IO_PRIVATE_SIGNATURE SIGNATURE_32 ('E', 'M', 'b', 'k') +typedef struct { + UINTN Signature; + + EMU_IO_THUNK_PROTOCOL *Thunk; + + char *Filename; + UINTN ReadMode; + UINTN Mode; + + int fd; + + BOOLEAN RemovableMedia; + BOOLEAN WriteProtected; + + UINT64 NumberOfBlocks; + UINT32 BlockSize; + + EMU_BLOCK_IO_PROTOCOL EmuBlockIo; + EFI_BLOCK_IO_MEDIA *Media; + +} EMU_BLOCK_IO_PRIVATE; + +#define EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS(a) \ + CR(a, EMU_BLOCK_IO_PRIVATE, EmuBlockIo, EMU_BLOCK_IO_PRIVATE_SIGNATURE) + + + +EFI_STATUS +EmuBlockIoReset ( + IN EMU_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + + +/*++ + +This function extends the capability of SetFilePointer to accept 64 bit parameters + +**/ +EFI_STATUS +SetFilePointer64 ( + IN EMU_BLOCK_IO_PRIVATE *Private, + IN INT64 DistanceToMove, + OUT UINT64 *NewFilePointer, + IN INT32 MoveMethod + ) +{ + EFI_STATUS Status; + off_t res; + off_t offset = DistanceToMove; + + Status = EFI_SUCCESS; + res = lseek (Private->fd, offset, (int)MoveMethod); + if (res == -1) { + Status = EFI_INVALID_PARAMETER; + } + + if (NewFilePointer != NULL) { + *NewFilePointer = res; + } + + return Status; +} + + +EFI_STATUS +EmuBlockIoOpenDevice ( + IN EMU_BLOCK_IO_PRIVATE *Private + ) +{ + EFI_STATUS Status; + UINT64 FileSize; + struct statfs buf; + + + // + // If the device is already opened, close it + // + if (Private->fd >= 0) { + EmuBlockIoReset (&Private->EmuBlockIo, FALSE); + } + + // + // Open the device + // + Private->fd = open (Private->Filename, Private->Mode, 0644); + if (Private->fd < 0) { + printf ("EmuOpenBlock: Could not open %s: %s\n", Private->Filename, strerror(errno)); + Private->Media->MediaPresent = FALSE; + Status = EFI_NO_MEDIA; + goto Done; + } + + if (!Private->Media->MediaPresent) { + // + // BugBug: try to emulate if a CD appears - notify drivers to check it out + // + Private->Media->MediaPresent = TRUE; + } + + // + // get the size of the file + // + Status = SetFilePointer64 (Private, 0, &FileSize, SEEK_END); + if (EFI_ERROR (Status)) { + printf ("EmuOpenBlock: Could not get filesize of %s\n", Private->Filename); + Status = EFI_UNSUPPORTED; + goto Done; + } + + if (FileSize == 0) { + // lseek fails on a real device. ioctl calls are OS specific +#if __APPLE__ + { + UINT32 BlockSize; + + if (ioctl (Private->fd, DKIOCGETBLOCKSIZE, &BlockSize) == 0) { + Private->Media->BlockSize = BlockSize; + } + if (ioctl (Private->fd, DKIOCGETBLOCKCOUNT, &Private->NumberOfBlocks) == 0) { + if ((Private->NumberOfBlocks == 0) && (BlockSize == 0x800)) { + // A DVD is ~ 4.37 GB so make up a number + Private->Media->LastBlock = (0x100000000ULL/0x800) - 1; + } else { + Private->Media->LastBlock = Private->NumberOfBlocks - 1; + } + } + ioctl (Private->fd, DKIOCGETMAXBLOCKCOUNTWRITE, &Private->Media->OptimalTransferLengthGranularity); + } +#else + { + size_t BlockSize; + UINT64 DiskSize; + + if (ioctl (Private->fd, BLKSSZGET, &BlockSize) == 0) { + Private->Media->BlockSize = BlockSize; + } + if (ioctl (Private->fd, BLKGETSIZE64, &DiskSize) == 0) { + Private->NumberOfBlocks = DivU64x32 (DiskSize, (UINT32)BlockSize); + Private->Media->LastBlock = Private->NumberOfBlocks - 1; + } + } +#endif + + } else { + Private->Media->BlockSize = Private->BlockSize; + Private->NumberOfBlocks = DivU64x32 (FileSize, Private->Media->BlockSize); + Private->Media->LastBlock = Private->NumberOfBlocks - 1; + + if (fstatfs (Private->fd, &buf) == 0) { +#if __APPLE__ + Private->Media->OptimalTransferLengthGranularity = buf.f_iosize/buf.f_bsize; +#else + Private->Media->OptimalTransferLengthGranularity = buf.f_bsize/buf.f_bsize; +#endif + } + } + + DEBUG ((EFI_D_INIT, "%HEmuOpenBlock: opened %a%N\n", Private->Filename)); + Status = EFI_SUCCESS; + +Done: + if (EFI_ERROR (Status)) { + if (Private->fd >= 0) { + EmuBlockIoReset (&Private->EmuBlockIo, FALSE); + } + } + + return Status; +} + + +EFI_STATUS +EmuBlockIoCreateMapping ( + IN EMU_BLOCK_IO_PROTOCOL *This, + IN EFI_BLOCK_IO_MEDIA *Media + ) +{ + EFI_STATUS Status; + EMU_BLOCK_IO_PRIVATE *Private; + + Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This); + + Private->Media = Media; + + Media->MediaId = 0; + Media->RemovableMedia = Private->RemovableMedia; + Media->MediaPresent = TRUE; + Media->LogicalPartition = FALSE; + Media->ReadOnly = Private->WriteProtected; + Media->WriteCaching = FALSE; + Media->IoAlign = 1; + Media->LastBlock = 0; // Filled in by OpenDevice + + // EFI_BLOCK_IO_PROTOCOL_REVISION2 + Media->LowestAlignedLba = 0; + Media->LogicalBlocksPerPhysicalBlock = 0; + + + // EFI_BLOCK_IO_PROTOCOL_REVISION3 + Media->OptimalTransferLengthGranularity = 0; + + Status = EmuBlockIoOpenDevice (Private); + + + return Status; +} + + +EFI_STATUS +EmuBlockIoError ( + IN EMU_BLOCK_IO_PRIVATE *Private + ) +{ + EFI_STATUS Status; + BOOLEAN ReinstallBlockIoFlag; + + + switch (errno) { + + case EAGAIN: + Status = EFI_NO_MEDIA; + Private->Media->ReadOnly = FALSE; + Private->Media->MediaPresent = FALSE; + ReinstallBlockIoFlag = FALSE; + break; + + case EACCES: + Private->Media->ReadOnly = FALSE; + Private->Media->MediaPresent = TRUE; + Private->Media->MediaId += 1; + ReinstallBlockIoFlag = TRUE; + Status = EFI_MEDIA_CHANGED; + break; + + case EROFS: + Private->Media->ReadOnly = TRUE; + ReinstallBlockIoFlag = FALSE; + Status = EFI_WRITE_PROTECTED; + break; + + default: + ReinstallBlockIoFlag = FALSE; + Status = EFI_DEVICE_ERROR; + break; + } + return Status; +} + + +EFI_STATUS +EmuBlockIoReadWriteCommon ( + IN EMU_BLOCK_IO_PRIVATE *Private, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer, + IN CHAR8 *CallerName + ) +{ + EFI_STATUS Status; + UINTN BlockSize; + UINT64 LastBlock; + INT64 DistanceToMove; + UINT64 DistanceMoved; + + if (Private->fd < 0) { + Status = EmuBlockIoOpenDevice (Private); + if (EFI_ERROR (Status)) { + return Status; + } + } + + if (!Private->Media->MediaPresent) { + DEBUG ((EFI_D_INIT, "%s: No Media\n", CallerName)); + return EFI_NO_MEDIA; + } + + if (Private->Media->MediaId != MediaId) { + return EFI_MEDIA_CHANGED; + } + + if ((UINTN) Buffer % Private->Media->IoAlign != 0) { + return EFI_INVALID_PARAMETER; + } + + // + // Verify buffer size + // + BlockSize = Private->Media->BlockSize; + if (BufferSize == 0) { + DEBUG ((EFI_D_INIT, "%s: Zero length read\n", CallerName)); + return EFI_SUCCESS; + } + + if ((BufferSize % BlockSize) != 0) { + DEBUG ((EFI_D_INIT, "%s: Invalid read size\n", CallerName)); + return EFI_BAD_BUFFER_SIZE; + } + + LastBlock = Lba + (BufferSize / BlockSize) - 1; + if (LastBlock > Private->Media->LastBlock) { + DEBUG ((EFI_D_INIT, "ReadBlocks: Attempted to read off end of device\n")); + return EFI_INVALID_PARAMETER; + } + // + // Seek to End of File + // + DistanceToMove = MultU64x32 (Lba, BlockSize); + Status = SetFilePointer64 (Private, DistanceToMove, &DistanceMoved, SEEK_SET); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_INIT, "WriteBlocks: SetFilePointer failed\n")); + return EmuBlockIoError (Private); + } + + return EFI_SUCCESS; +} + + +/** + Read BufferSize bytes from Lba into Buffer. + + This function reads the requested number of blocks from the device. All the + blocks are read, or an error is returned. + If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_or EFI_MEDIA_CHANGED is returned and + non-blocking I/O is being used, the Event associated with this request will + not be signaled. + + @param[in] This Indicates a pointer to the calling context. + @param[in] MediaId Id of the media, changes every time the media is + replaced. + @param[in] Lba The starting Logical Block Address to read from. + @param[in, out] Token A pointer to the token associated with the transaction. + @param[in] BufferSize Size of Buffer, must be a multiple of device block size. + @param[out] Buffer A pointer to the destination buffer for the data. The + caller is responsible for either having implicit or + explicit ownership of the buffer. + + @retval EFI_SUCCESS The read request was queued if Token->Event is + not NULL.The data was read correctly from the + device if the Token->Event is NULL. + @retval EFI_DEVICE_ERROR The device reported an error while performing + the read. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the + intrinsic block size of the device. + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, + or the buffer is not on proper alignment. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack + of resources. +**/ +EFI_STATUS +EmuBlockIoReadBlocks ( + IN EMU_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN OUT EFI_BLOCK_IO2_TOKEN *Token, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + EMU_BLOCK_IO_PRIVATE *Private; + ssize_t len; + + Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This); + + Status = EmuBlockIoReadWriteCommon (Private, MediaId, LBA, BufferSize, Buffer, "UnixReadBlocks"); + if (EFI_ERROR (Status)) { + goto Done; + } + + len = read (Private->fd, Buffer, BufferSize); + if (len != BufferSize) { + DEBUG ((EFI_D_INIT, "ReadBlocks: ReadFile failed.\n")); + Status = EmuBlockIoError (Private); + goto Done; + } + + // + // If we read then media is present. + // + Private->Media->MediaPresent = TRUE; + Status = EFI_SUCCESS; + +Done: + if (Token != NULL) { + if (Token->Event != NULL) { + // Caller is responcible for signaling EFI Event + Token->TransactionStatus = Status; + return EFI_SUCCESS; + } + } + return Status; +} + + +/** + Write BufferSize bytes from Lba into Buffer. + + This function writes the requested number of blocks to the device. All blocks + are written, or an error is returned.If EFI_DEVICE_ERROR, EFI_NO_MEDIA, + EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED is returned and non-blocking I/O is + being used, the Event associated with this request will not be signaled. + + @param[in] This Indicates a pointer to the calling context. + @param[in] MediaId The media ID that the write request is for. + @param[in] Lba The starting logical block address to be written. The + caller is responsible for writing to only legitimate + locations. + @param[in, out] Token A pointer to the token associated with the transaction. + @param[in] BufferSize Size of Buffer, must be a multiple of device block size. + @param[in] Buffer A pointer to the source buffer for the data. + + @retval EFI_SUCCESS The write request was queued if Event is not NULL. + The data was written correctly to the device if + the Event is NULL. + @retval EFI_WRITE_PROTECTED The device can not be written to. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device. + @retval EFI_DEVICE_ERROR The device reported an error while performing the write. + @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device. + @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, + or the buffer is not on proper alignment. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack + of resources. + +**/ +EFI_STATUS +EmuBlockIoWriteBlocks ( + IN EMU_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN OUT EFI_BLOCK_IO2_TOKEN *Token, + IN UINTN BufferSize, + IN VOID *Buffer + ) +{ + EMU_BLOCK_IO_PRIVATE *Private; + ssize_t len; + EFI_STATUS Status; + + + Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This); + + Status = EmuBlockIoReadWriteCommon (Private, MediaId, LBA, BufferSize, Buffer, "UnixWriteBlocks"); + if (EFI_ERROR (Status)) { + goto Done; + } + + len = write (Private->fd, Buffer, BufferSize); + if (len != BufferSize) { + DEBUG ((EFI_D_INIT, "ReadBlocks: WriteFile failed.\n")); + Status = EmuBlockIoError (Private); + goto Done; + } + + // + // If the write succeeded, we are not write protected and media is present. + // + Private->Media->MediaPresent = TRUE; + Private->Media->ReadOnly = FALSE; + Status = EFI_SUCCESS; + +Done: + if (Token != NULL) { + if (Token->Event != NULL) { + // Caller is responcible for signaling EFI Event + Token->TransactionStatus = Status; + return EFI_SUCCESS; + } + } + + return Status; +} + + +/** + Flush the Block Device. + + If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED + is returned and non-blocking I/O is being used, the Event associated with + this request will not be signaled. + + @param[in] This Indicates a pointer to the calling context. + @param[in,out] Token A pointer to the token associated with the transaction + + @retval EFI_SUCCESS The flush request was queued if Event is not NULL. + All outstanding data was written correctly to the + device if the Event is NULL. + @retval EFI_DEVICE_ERROR The device reported an error while writting back + the data. + @retval EFI_WRITE_PROTECTED The device cannot be written to. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack + of resources. + +**/ +EFI_STATUS +EmuBlockIoFlushBlocks ( + IN EMU_BLOCK_IO_PROTOCOL *This, + IN OUT EFI_BLOCK_IO2_TOKEN *Token + ) +{ + EMU_BLOCK_IO_PRIVATE *Private; + + Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This); + + if (Private->fd >= 0) { + fsync (Private->fd); +#if __APPLE__ + fcntl (Private->fd, F_FULLFSYNC); +#endif + } + + + if (Token != NULL) { + if (Token->Event != NULL) { + // Caller is responcible for signaling EFI Event + Token->TransactionStatus = EFI_SUCCESS; + return EFI_SUCCESS; + } + } + + return EFI_SUCCESS; +} + + +/** + Reset the block device hardware. + + @param[in] This Indicates a pointer to the calling context. + @param[in] ExtendedVerification Indicates that the driver may perform a more + exhausive verfication operation of the device + during reset. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The device is not functioning properly and could + not be reset. + +**/ +EFI_STATUS +EmuBlockIoReset ( + IN EMU_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + EMU_BLOCK_IO_PRIVATE *Private; + + Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This); + + if (Private->fd >= 0) { + close (Private->fd); + Private->fd = -1; + } + + return EFI_SUCCESS; +} + + +char * +StdDupUnicodeToAscii ( + IN CHAR16 *Str + ) +{ + UINTN Size; + char *Ascii; + char *Ptr; + + Size = StrLen (Str) + 1; + Ascii = malloc (Size); + if (Ascii == NULL) { + return NULL; + } + + for (Ptr = Ascii; *Str != '\0'; Ptr++, Str++) { + *Ptr = *Str; + } + *Ptr = 0; + + return Ascii; +} + + +EMU_BLOCK_IO_PROTOCOL gEmuBlockIoProtocol = { + GasketEmuBlockIoReset, + GasketEmuBlockIoReadBlocks, + GasketEmuBlockIoWriteBlocks, + GasketEmuBlockIoFlushBlocks, + GasketEmuBlockIoCreateMapping +}; + +EFI_STATUS +EmuBlockIoThunkOpen ( + IN EMU_IO_THUNK_PROTOCOL *This + ) +{ + EMU_BLOCK_IO_PRIVATE *Private; + char *Str; + + if (This->Private != NULL) { + return EFI_ALREADY_STARTED; + } + + if (!CompareGuid (This->Protocol, &gEmuBlockIoProtocolGuid)) { + return EFI_UNSUPPORTED; + } + + Private = malloc (sizeof (EMU_BLOCK_IO_PRIVATE)); + if (Private == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + + Private->Signature = EMU_BLOCK_IO_PRIVATE_SIGNATURE; + Private->Thunk = This; + CopyMem (&Private->EmuBlockIo, &gEmuBlockIoProtocol, sizeof (gEmuBlockIoProtocol)); + Private->fd = -1; + Private->BlockSize = 512; + + Private->Filename = StdDupUnicodeToAscii (This->ConfigString); + if (Private->Filename == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Str = strstr (Private->Filename, ":"); + if (Str == NULL) { + Private->RemovableMedia = FALSE; + Private->WriteProtected = FALSE; + } else { + for (*Str++ = '\0'; *Str != 0; Str++) { + if (*Str == 'R' || *Str == 'F') { + Private->RemovableMedia = (BOOLEAN) (*Str == 'R'); + } + if (*Str == 'O' || *Str == 'W') { + Private->WriteProtected = (BOOLEAN) (*Str == 'O'); + } + if (*Str == ':') { + Private->BlockSize = strtol (++Str, NULL, 0); + break; + } + } + } + + This->Interface = &Private->EmuBlockIo; + This->Private = Private; + return EFI_SUCCESS; +} + + +EFI_STATUS +EmuBlockIoThunkClose ( + IN EMU_IO_THUNK_PROTOCOL *This + ) +{ + EMU_BLOCK_IO_PRIVATE *Private; + + if (!CompareGuid (This->Protocol, &gEmuBlockIoProtocolGuid)) { + return EFI_UNSUPPORTED; + } + + Private = This->Private; + + if (This->Private != NULL) { + if (Private->Filename != NULL) { + free (Private->Filename); + } + free (This->Private); + This->Private = NULL; + } + + return EFI_SUCCESS; +} + + + +EMU_IO_THUNK_PROTOCOL gBlockIoThunkIo = { + &gEmuBlockIoProtocolGuid, + NULL, + NULL, + 0, + GasketBlockIoThunkOpen, + GasketBlockIoThunkClose, + NULL +}; + + diff --git a/EmulatorPkg/Unix/Host/EmuThunk.c b/EmulatorPkg/Unix/Host/EmuThunk.c new file mode 100644 index 0000000000..fe68603d3f --- /dev/null +++ b/EmulatorPkg/Unix/Host/EmuThunk.c @@ -0,0 +1,432 @@ +/*++ @file + Since the SEC is the only program in our emulation we + must use a UEFI/PI mechanism to export APIs to other modules. + This is the role of the EFI_EMU_THUNK_PROTOCOL. + + The mUnixThunkTable exists so that a change to EFI_EMU_THUNK_PROTOCOL + will cause an error in initializing the array if all the member functions + are not added. It looks like adding a element to end and not initializing + it may cause the table to be initaliized with the members at the end being + set to zero. This is bad as jumping to zero will crash. + +Copyright (c) 2004 - 2009, Intel Corporation. All rights reserved.
+Portions copyright (c) 2008 - 2011, 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. + +**/ + +#include "SecMain.h" + +#ifdef __APPLE__ +#define DebugAssert _Mangle__DebugAssert + +#include +#include +#include +#include + +#undef DebugAssert +#endif + +int settimer_initialized; +struct timeval settimer_timeval; +void (*settimer_callback)(UINT64 delta); + +BOOLEAN gEmulatorInterruptEnabled = FALSE; + + +UINTN +SecWriteStdErr ( + IN UINT8 *Buffer, + IN UINTN NumberOfBytes + ) +{ + ssize_t Return; + + Return = write (STDERR_FILENO, (const void *)Buffer, (size_t)NumberOfBytes); + + return (Return == -1) ? 0 : Return; +} + + +EFI_STATUS +SecConfigStdIn ( + VOID + ) +{ + struct termios tty; + + // + // Need to turn off line buffering, ECHO, and make it unbuffered. + // + tcgetattr (STDIN_FILENO, &tty); + tty.c_lflag &= ~(ICANON | ECHO); + tcsetattr (STDIN_FILENO, TCSANOW, &tty); + +// setvbuf (STDIN_FILENO, NULL, _IONBF, 0); + + // now ioctl FIONREAD will do what we need + return EFI_SUCCESS; +} + +UINTN +SecWriteStdOut ( + IN UINT8 *Buffer, + IN UINTN NumberOfBytes + ) +{ + ssize_t Return; + + Return = write (STDOUT_FILENO, (const void *)Buffer, (size_t)NumberOfBytes); + + return (Return == -1) ? 0 : Return; +} + +UINTN +SecReadStdIn ( + IN UINT8 *Buffer, + IN UINTN NumberOfBytes + ) +{ + ssize_t Return; + + Return = read (STDIN_FILENO, Buffer, (size_t)NumberOfBytes); + + return (Return == -1) ? 0 : Return; +} + +BOOLEAN +SecPollStdIn ( + VOID + ) +{ + int Result; + int Bytes; + + Result = ioctl (STDIN_FILENO, FIONREAD, &Bytes); + if (Result == -1) { + return FALSE; + } + + return (BOOLEAN)(Bytes > 0); +} + + +VOID * +SecMalloc ( + IN UINTN Size + ) +{ + return malloc ((size_t)Size); +} + +VOID * +SecValloc ( + IN UINTN Size + ) +{ + return valloc ((size_t)Size); +} + +BOOLEAN +SecFree ( + IN VOID *Ptr + ) +{ + if (EfiSystemMemoryRange (Ptr)) { + // If an address range is in the EFI memory map it was alloced via EFI. + // So don't free those ranges and let the caller know. + return FALSE; + } + + free (Ptr); + return TRUE; +} + + +void +settimer_handler (int sig) +{ + struct timeval timeval; + UINT64 delta; + + gettimeofday (&timeval, NULL); + delta = ((UINT64)timeval.tv_sec * 1000) + (timeval.tv_usec / 1000) + - ((UINT64)settimer_timeval.tv_sec * 1000) + - (settimer_timeval.tv_usec / 1000); + settimer_timeval = timeval; + + if (settimer_callback) { + ReverseGasketUint64 (settimer_callback, delta); + } +} + +VOID +SecSetTimer ( + IN UINT64 PeriodMs, + IN EMU_SET_TIMER_CALLBACK CallBack + ) +{ + struct itimerval timerval; + UINT32 remainder; + + if (!settimer_initialized) { + struct sigaction act; + + settimer_initialized = 1; + act.sa_handler = settimer_handler; + act.sa_flags = 0; + sigemptyset (&act.sa_mask); + gEmulatorInterruptEnabled = TRUE; + if (sigaction (SIGALRM, &act, NULL) != 0) { + printf ("SetTimer: sigaction error %s\n", strerror (errno)); + } + if (gettimeofday (&settimer_timeval, NULL) != 0) { + printf ("SetTimer: gettimeofday error %s\n", strerror (errno)); + } + } + timerval.it_value.tv_sec = DivU64x32(PeriodMs, 1000); + DivU64x32Remainder(PeriodMs, 1000, &remainder); + timerval.it_value.tv_usec = remainder * 1000; + timerval.it_value.tv_sec = DivU64x32(PeriodMs, 1000); + timerval.it_interval = timerval.it_value; + + if (setitimer (ITIMER_REAL, &timerval, NULL) != 0) { + printf ("SetTimer: setitimer error %s\n", strerror (errno)); + } + settimer_callback = CallBack; +} + + +VOID +SecEnableInterrupt ( + VOID + ) +{ + sigset_t sigset; + + gEmulatorInterruptEnabled = TRUE; + // Since SetTimer() uses SIGALRM we emulate turning on and off interrupts + // by enabling/disabling SIGALRM. + sigemptyset (&sigset); + sigaddset (&sigset, SIGALRM); + pthread_sigmask (SIG_UNBLOCK, &sigset, NULL); +} + + +VOID +SecDisableInterrupt ( + VOID + ) +{ + sigset_t sigset; + + // Since SetTimer() uses SIGALRM we emulate turning on and off interrupts + // by enabling/disabling SIGALRM. + sigemptyset (&sigset); + sigaddset (&sigset, SIGALRM); + pthread_sigmask (SIG_BLOCK, &sigset, NULL); + gEmulatorInterruptEnabled = FALSE; +} + + +BOOLEAN +SecInterruptEanbled (void) +{ + return gEmulatorInterruptEnabled; +} + + +UINT64 +QueryPerformanceFrequency ( + VOID + ) +{ + // Hard code to nanoseconds + return 1000000000ULL; +} + +UINT64 +QueryPerformanceCounter ( + VOID + ) +{ +#if __APPLE__ + UINT64 Start; + Nanoseconds elapsedNano; + + Start = mach_absolute_time (); + + // Convert to nanoseconds. + + // Have to do some pointer fun because AbsoluteToNanoseconds + // works in terms of UnsignedWide, which is a structure rather + // than a proper 64-bit integer. + elapsedNano = AbsoluteToNanoseconds (*(AbsoluteTime *) &Start); + + return *(uint64_t *) &elapsedNano; +#else + // Need to figure out what to do for Linux? + return 0; +#endif +} + + + +VOID +SecSleep ( + IN UINT64 Nanoseconds + ) +{ + struct timespec rq, rm; + struct timeval start, end; + unsigned long MicroSec; + + rq.tv_sec = DivU64x32 (Nanoseconds, 1000000000); + rq.tv_nsec = ModU64x32 (Nanoseconds, 1000000000); + + // + // nanosleep gets interrupted by our timer tic. + // we need to track wall clock time or we will stall for way too long + // + gettimeofday (&start, NULL); + end.tv_sec = start.tv_sec + rq.tv_sec; + MicroSec = (start.tv_usec + rq.tv_nsec/1000); + end.tv_usec = MicroSec % 1000000; + if (MicroSec > 1000000) { + end.tv_sec++; + } + + while (nanosleep (&rq, &rm) == -1) { + if (errno != EINTR) { + break; + } + gettimeofday (&start, NULL); + if (start.tv_sec > end.tv_sec) { + break; + } if ((start.tv_sec == end.tv_sec) && (start.tv_usec > end.tv_usec)) { + break; + } + rq = rm; + } +} + + +VOID +SecCpuSleep ( + VOID + ) +{ + struct timespec rq, rm; + + // nanosleep gets interrupted by the timer tic + rq.tv_sec = 1; + rq.tv_nsec = 0; + + nanosleep (&rq, &rm); +} + + +VOID +SecExit ( + UINTN Status + ) +{ + exit (Status); +} + + +VOID +SecGetTime ( + OUT EFI_TIME *Time, + OUT EFI_TIME_CAPABILITIES *Capabilities OPTIONAL + ) +{ + struct tm *tm; + time_t t; + + t = time (NULL); + tm = localtime (&t); + + Time->Year = 1900 + tm->tm_year; + Time->Month = tm->tm_mon + 1; + Time->Day = tm->tm_mday; + Time->Hour = tm->tm_hour; + Time->Minute = tm->tm_min; + Time->Second = tm->tm_sec; + Time->Nanosecond = 0; + Time->TimeZone = timezone; + Time->Daylight = (daylight ? EFI_TIME_ADJUST_DAYLIGHT : 0) + | (tm->tm_isdst > 0 ? EFI_TIME_IN_DAYLIGHT : 0); + + if (Capabilities != NULL) { + Capabilities->Resolution = 1; + Capabilities->Accuracy = 50000000; + Capabilities->SetsToZero = FALSE; + } +} + + + +VOID +SecSetTime ( + IN EFI_TIME *Time + ) +{ + // Don't change the time on the system + // We could save delta to localtime() and have SecGetTime adjust return values? + return; +} + + +EFI_STATUS +SecGetNextProtocol ( + IN BOOLEAN EmuBusDriver, + OUT EMU_IO_THUNK_PROTOCOL **Instance OPTIONAL + ) +{ + return GetNextThunkProtocol (EmuBusDriver, Instance); +} + + +EMU_THUNK_PROTOCOL gEmuThunkProtocol = { + GasketSecWriteStdErr, + GasketSecConfigStdIn, + GasketSecWriteStdOut, + GasketSecReadStdIn, + GasketSecPollStdIn, + GasketSecMalloc, + GasketSecValloc, + GasketSecFree, + GasketSecPeCoffGetEntryPoint, + GasketSecPeCoffRelocateImageExtraAction, + GasketSecPeCoffUnloadImageExtraAction, + GasketSecEnableInterrupt, + GasketSecDisableInterrupt, + GasketQueryPerformanceFrequency, + GasketQueryPerformanceCounter, + GasketSecSleep, + GasketSecCpuSleep, + GasketSecExit, + GasketSecGetTime, + GasketSecSetTime, + GasketSecSetTimer, + GasketSecGetNextProtocol +}; + + +VOID +SecInitThunkProtocol ( + VOID + ) +{ + // timezone and daylight lib globals depend on tzset be called 1st. + tzset (); +} + diff --git a/EmulatorPkg/Unix/Host/Gasket.h b/EmulatorPkg/Unix/Host/Gasket.h new file mode 100644 index 0000000000..2c59a562e6 --- /dev/null +++ b/EmulatorPkg/Unix/Host/Gasket.h @@ -0,0 +1,651 @@ +/** @file + + Copyright (c) 2008 - 2011, Apple Inc. All rights reserved.
+ Copyright (c) 2011, Intel Corporation. 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. + +**/ + +#ifndef _GASKET_H_ +#define _GASKET_H_ + +// +// EMU_THUNK_PROTOCOL gaskets (EFIAPI to UNIX ABI) +// + +UINTN +EFIAPI +GasketSecWriteStdErr ( + IN UINT8 *Buffer, + IN UINTN NumberOfBytes + ); + +EFI_STATUS +EFIAPI +GasketSecConfigStdIn ( + VOID + ); + +UINTN +EFIAPI +GasketSecWriteStdOut ( + IN UINT8 *Buffer, + IN UINTN NumberOfBytes + ); + +UINTN +EFIAPI +GasketSecReadStdIn ( + IN UINT8 *Buffer, + IN UINTN NumberOfBytes + ); + +BOOLEAN +EFIAPI +GasketSecPollStdIn ( + VOID + ); + +VOID * +EFIAPI +GasketSecMalloc ( + IN UINTN Size + ); + +VOID * +EFIAPI +GasketSecValloc ( + IN UINTN Size + ); + +BOOLEAN +EFIAPI +GasketSecFree ( + IN VOID *Ptr + ); + + +RETURN_STATUS +EFIAPI +GasketSecPeCoffGetEntryPoint ( + IN VOID *Pe32Data, + IN OUT VOID **EntryPoint + ); + +VOID +EFIAPI +GasketSecPeCoffRelocateImageExtraAction ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ); + +VOID +EFIAPI +GasketSecPeCoffUnloadImageExtraAction ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ); + +VOID +EFIAPI +GasketSecSetTimer ( + IN UINT64 PeriodMs, + IN EMU_SET_TIMER_CALLBACK CallBack + ); + +VOID +EFIAPI +GasketSecEnableInterrupt ( + VOID + ); + +VOID +EFIAPI +GasketSecDisableInterrupt ( + VOID + ); + +UINT64 +EFIAPI +GasketQueryPerformanceFrequency ( + VOID + ); + +UINT64 +EFIAPI +GasketQueryPerformanceCounter ( + VOID + ); + + +VOID +EFIAPI +GasketSecSleep ( + IN UINT64 Nanoseconds + ); + +VOID +EFIAPI +GasketSecCpuSleep ( + VOID + ); + +VOID +EFIAPI +GasketSecExit ( + UINTN Status + ); + +VOID +EFIAPI +GasketSecGetTime ( + OUT EFI_TIME *Time, + OUT EFI_TIME_CAPABILITIES *Capabilities OPTIONAL + ); + +VOID +EFIAPI +GasketSecSetTime ( + IN EFI_TIME *Time + ); + +EFI_STATUS +EFIAPI +GasketSecGetNextProtocol ( + IN BOOLEAN EmuBusDriver, + OUT EMU_IO_THUNK_PROTOCOL **Instance OPTIONAL + ); + + +// PPIs produced by SEC + + +EFI_STATUS +EFIAPI +GasketSecUnixPeiAutoScan ( + IN UINTN Index, + OUT EFI_PHYSICAL_ADDRESS *MemoryBase, + OUT UINT64 *MemorySize + ); + +VOID * +EFIAPI +GasketSecEmuThunkAddress ( + VOID + ); + + +EFI_STATUS +EFIAPI +GasketSecUnixUnixFwhAddress ( + IN OUT UINT64 *FwhSize, + IN OUT EFI_PHYSICAL_ADDRESS *FwhBase + ); + + + +// +// Reverse (UNIX to EFIAPI) gaskets +// + +typedef +void +(EFIAPI *CALL_BACK) ( + UINT64 Delta + ); + +UINTN +ReverseGasketUint64 ( + CALL_BACK CallBack, + UINT64 a + ); + +UINTN +ReverseGasketUint64Uint64 ( + VOID *CallBack, + VOID *Context, + VOID *Key + ); + +// +// Gasket functions for EFI_EMU_UGA_IO_PROTOCOL +// + + +EFI_STATUS +EFIAPI +GasketX11Size ( + EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsWindowsIo, + UINT32 Width, + UINT32 Height + ); + +EFI_STATUS +EFIAPI +GasketX11CheckKey ( + EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsWindowsIo + ); + +EFI_STATUS +EFIAPI +GasketX11GetKey ( + EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsWindowsIo, + EFI_KEY_DATA *key + ); + +EFI_STATUS +EFIAPI +GasketX11KeySetState ( + EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsWindowsIo, + EFI_KEY_TOGGLE_STATE *KeyToggleState + ); + +EFI_STATUS +EFIAPI +GasketX11RegisterKeyNotify ( + IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsWindowsIo, + IN EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK MakeCallBack, + IN EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK BreakCallBack, + IN VOID *Context + ); + + +EFI_STATUS +EFIAPI +GasketX11Blt ( + IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsWindows, + IN EFI_UGA_PIXEL *BltBuffer OPTIONAL, + IN EFI_UGA_BLT_OPERATION BltOperation, + IN EMU_GRAPHICS_WINDOWS__BLT_ARGS *Args + ); + +EFI_STATUS +EFIAPI +GasketX11CheckPointer ( + EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsWindowsIo + ); + +EFI_STATUS +EFIAPI +GasketX11GetPointerState ( + EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsWindowsIo, + EFI_SIMPLE_POINTER_STATE *state + ); + +EFI_STATUS +EFIAPI +GasketX11GraphicsWindowOpen ( + IN EMU_IO_THUNK_PROTOCOL *This + ); + +EFI_STATUS +EFIAPI +GasketX11GraphicsWindowClose ( + IN EMU_IO_THUNK_PROTOCOL *This + ); + +// Pthreads + +UINTN +EFIAPI +GasketPthreadMutexLock ( + IN VOID *Mutex + ); + + + +UINTN +EFIAPI +GasketPthreadMutexUnLock ( + IN VOID *Mutex + ); + + +UINTN +EFIAPI +GasketPthreadMutexTryLock ( + IN VOID *Mutex + ); + + +VOID * +EFIAPI +GasketPthreadMutexInit ( + IN VOID + ); + + +UINTN +EFIAPI +GasketPthreadMutexDestroy ( + IN VOID *Mutex + ); + + +UINTN +EFIAPI +GasketPthreadCreate ( + IN VOID *Thread, + IN VOID *Attribute, + IN THREAD_THUNK_THREAD_ENTRY Start, + IN VOID *Context + ); + +VOID +EFIAPI +GasketPthreadExit ( + IN VOID *ValuePtr + ); + + +UINTN +EFIAPI +GasketPthreadSelf ( + VOID + ); + +EFI_STATUS +EFIAPI +GasketPthreadOpen ( + IN EMU_IO_THUNK_PROTOCOL *This + ); + +EFI_STATUS +EFIAPI +GasketPthreadClose ( + IN EMU_IO_THUNK_PROTOCOL *This + ); + + +// PosixFileSystem + +EFI_STATUS +EFIAPI +GasketPosixOpenVolume ( + IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, + OUT EFI_FILE_PROTOCOL **Root + ); + +EFI_STATUS +EFIAPI +GasketPosixFileOpen ( + IN EFI_FILE_PROTOCOL *This, + OUT EFI_FILE_PROTOCOL **NewHandle, + IN CHAR16 *FileName, + IN UINT64 OpenMode, + IN UINT64 Attributes + ); + +EFI_STATUS +EFIAPI +GasketPosixFileCLose ( + IN EFI_FILE_PROTOCOL *This + ); + +EFI_STATUS +EFIAPI +GasketPosixFileDelete ( + IN EFI_FILE_PROTOCOL *This + ); + +EFI_STATUS +EFIAPI +GasketPosixFileRead ( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + +EFI_STATUS +EFIAPI +GasketPosixFileWrite ( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ); + +EFI_STATUS +EFIAPI +GasketPosixFileSetPossition ( + IN EFI_FILE_PROTOCOL *This, + IN UINT64 Position + ); + +EFI_STATUS +EFIAPI +GasketPosixFileGetPossition ( + IN EFI_FILE_PROTOCOL *This, + OUT UINT64 *Position + ); + +EFI_STATUS +EFIAPI +GasketPosixFileGetInfo ( + IN EFI_FILE_PROTOCOL *This, + IN EFI_GUID *InformationType, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + +EFI_STATUS +EFIAPI +GasketPosixFileSetInfo ( + IN EFI_FILE_PROTOCOL *This, + IN EFI_GUID *InformationType, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +EFI_STATUS +EFIAPI +GasketPosixFileFlush ( + IN EFI_FILE_PROTOCOL *This + ); + +EFI_STATUS +EFIAPI +GasketPosixFileSystmeThunkOpen ( + IN EMU_IO_THUNK_PROTOCOL *This + ); + +EFI_STATUS +EFIAPI +GasketPosixFileSystmeThunkClose ( + IN EMU_IO_THUNK_PROTOCOL *This + ); + +EFI_STATUS +EFIAPI +GasketEmuBlockIoReset ( + IN EMU_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +EFI_STATUS +EFIAPI +GasketEmuBlockIoReadBlocks ( + IN EMU_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN OUT EFI_BLOCK_IO2_TOKEN *Token, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +EFI_STATUS +EFIAPI +GasketEmuBlockIoWriteBlocks ( + IN EMU_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN OUT EFI_BLOCK_IO2_TOKEN *Token, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +EFI_STATUS +EFIAPI +GasketEmuBlockIoFlushBlocks ( + IN EMU_BLOCK_IO_PROTOCOL *This, + IN OUT EFI_BLOCK_IO2_TOKEN *Token + ); + +EFI_STATUS +EFIAPI +GasketEmuBlockIoCreateMapping ( + IN EMU_BLOCK_IO_PROTOCOL *This, + IN EFI_BLOCK_IO_MEDIA *Media + ); + +EFI_STATUS +EFIAPI +GasketBlockIoThunkOpen ( + IN EMU_IO_THUNK_PROTOCOL *This + ); + +EFI_STATUS +EFIAPI +GasketBlockIoThunkClose ( + IN EMU_IO_THUNK_PROTOCOL *This + ); + +EFI_STATUS +EFIAPI +GasketSnpThunkOpen ( + IN EMU_IO_THUNK_PROTOCOL *This + ); + +EFI_STATUS +EFIAPI +GasketSnpThunkClose ( + IN EMU_IO_THUNK_PROTOCOL *This + ); + +EFI_STATUS +EFIAPI +GasketSnpCreateMapping ( + IN EMU_SNP_PROTOCOL *This, + IN EFI_SIMPLE_NETWORK_MODE *Media + ); + +EFI_STATUS +EFIAPI +GasketSnpStart ( + IN EMU_SNP_PROTOCOL *This + ); + +EFI_STATUS +EFIAPI +GasketSnpStop ( + IN EMU_SNP_PROTOCOL *This + ); + +EFI_STATUS +EFIAPI +GasketSnpInitialize ( + IN EMU_SNP_PROTOCOL *This, + IN UINTN ExtraRxBufferSize OPTIONAL, + IN UINTN ExtraTxBufferSize OPTIONAL + ); + +EFI_STATUS +EFIAPI +GasketSnpReset ( + IN EMU_SNP_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +EFI_STATUS +EFIAPI +GasketSnpShutdown ( + IN EMU_SNP_PROTOCOL *This + ); + +EFI_STATUS +EFIAPI +GasketSnpReceiveFilters ( + IN EMU_SNP_PROTOCOL *This, + IN UINT32 Enable, + IN UINT32 Disable, + IN BOOLEAN ResetMCastFilter, + IN UINTN MCastFilterCnt OPTIONAL, + IN EFI_MAC_ADDRESS *MCastFilter OPTIONAL + ); + +EFI_STATUS +EFIAPI +GasketSnpStationAddress ( + IN EMU_SNP_PROTOCOL *This, + IN BOOLEAN Reset, + IN EFI_MAC_ADDRESS *New OPTIONAL + ); + +EFI_STATUS +EFIAPI +GasketSnpStatistics ( + IN EMU_SNP_PROTOCOL *This, + IN BOOLEAN Reset, + IN OUT UINTN *StatisticsSize OPTIONAL, + OUT EFI_NETWORK_STATISTICS *StatisticsTable OPTIONAL + ); + +EFI_STATUS +EFIAPI +GasketSnpMCastIpToMac ( + IN EMU_SNP_PROTOCOL *This, + IN BOOLEAN IPv6, + IN EFI_IP_ADDRESS *IP, + OUT EFI_MAC_ADDRESS *MAC + ); + +EFI_STATUS +EFIAPI +GasketSnpNvData ( + IN EMU_SNP_PROTOCOL *This, + IN BOOLEAN ReadWrite, + IN UINTN Offset, + IN UINTN BufferSize, + IN OUT VOID *Buffer + ); + +EFI_STATUS +EFIAPI +GasketSnpGetStatus ( + IN EMU_SNP_PROTOCOL *This, + OUT UINT32 *InterruptStatus OPTIONAL, + OUT VOID **TxBuf OPTIONAL + ); + +EFI_STATUS +EFIAPI +GasketSnpTransmit ( + IN EMU_SNP_PROTOCOL *This, + IN UINTN HeaderSize, + IN UINTN BufferSize, + IN VOID *Buffer, + IN EFI_MAC_ADDRESS *SrcAddr OPTIONAL, + IN EFI_MAC_ADDRESS *DestAddr OPTIONAL, + IN UINT16 *Protocol OPTIONAL + ); + +EFI_STATUS +EFIAPI +GasketSnpReceive ( + IN EMU_SNP_PROTOCOL *This, + OUT UINTN *HeaderSize OPTIONAL, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer, + OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL, + OUT EFI_MAC_ADDRESS *DestAddr OPTIONAL, + OUT UINT16 *Protocol OPTIONAL + ); + + +#endif + + diff --git a/EmulatorPkg/Unix/Host/Ia32/Gasket.S b/EmulatorPkg/Unix/Host/Ia32/Gasket.S new file mode 100644 index 0000000000..aa031ecece --- /dev/null +++ b/EmulatorPkg/Unix/Host/Ia32/Gasket.S @@ -0,0 +1,1492 @@ +#------------------------------------------------------------------------------ +# +# Manage differenced between UNIX ABI and EFI/Windows ABI +# +# For IA-32 the only difference is Mac OS X requires a 16-byte aligned stack. +# For Linux this stack adjustment is a no-op, but we may as well make the +# the code common. +# +# Copyright (c) 2008 - 2011, 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. +# +#------------------------------------------------------------------------------ + + + + .text + +// +// EMU_THUNK_PROTOCOL gaskets (EFIAPI to UNIX ABI) +// + + +ASM_GLOBAL ASM_PFX(GasketSecWriteStdErr) +ASM_PFX(GasketSecWriteStdErr): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(SecWriteStdErr) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketSecConfigStdIn) +ASM_PFX(GasketSecConfigStdIn): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(SecConfigStdIn) + + leave + ret + +ASM_GLOBAL ASM_PFX(GasketSecWriteStdOut) +ASM_PFX(GasketSecWriteStdOut): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(SecWriteStdOut) + + leave + ret + +ASM_GLOBAL ASM_PFX(GasketSecReadStdIn) +ASM_PFX(GasketSecReadStdIn): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(SecReadStdIn) + + leave + ret + +ASM_GLOBAL ASM_PFX(GasketSecPollStdIn) +ASM_PFX(GasketSecPollStdIn): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(SecPollStdIn) + + leave + ret + +ASM_GLOBAL ASM_PFX(GasketSecMalloc) +ASM_PFX(GasketSecMalloc): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(SecMalloc) + + leave + ret + +ASM_GLOBAL ASM_PFX(GasketSecValloc) +ASM_PFX(GasketSecValloc): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(SecValloc) + + leave + ret + +ASM_GLOBAL ASM_PFX(GasketSecFree) +ASM_PFX(GasketSecFree): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(SecFree) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketSecSetTimer) +ASM_PFX(GasketSecSetTimer): + pushl %ebp + movl %esp, %ebp + subl $40, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 16(%ebp), %eax + movl %eax, 8(%esp) + movl 8(%ebp), %eax + movl 12(%ebp), %edx + movl %edx, 4(%esp) + movl %eax, (%esp) + + call ASM_PFX(SecSetTimer) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketSecEnableInterrupt) +ASM_PFX(GasketSecEnableInterrupt): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + + call ASM_PFX(SecEnableInterrupt) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketSecDisableInterrupt) +ASM_PFX(GasketSecDisableInterrupt): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + + call ASM_PFX(SecDisableInterrupt) + + leave + ret + +ASM_GLOBAL ASM_PFX(GasketQueryPerformanceFrequency) +ASM_PFX(GasketQueryPerformanceFrequency): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + + call ASM_PFX(QueryPerformanceFrequency) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketQueryPerformanceCounter) +ASM_PFX(GasketQueryPerformanceCounter): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + + call ASM_PFX(QueryPerformanceCounter) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketSecSleep) +ASM_PFX(GasketSecSleep): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl 12(%ebp), %ecx + movl %ecx, 4(%esp) + movl %eax, (%esp) + + call ASM_PFX(SecSleep) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketSecCpuSleep) +ASM_PFX(GasketSecCpuSleep): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + + call ASM_PFX(SecCpuSleep) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketSecExit) +ASM_PFX(GasketSecExit): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(SecExit) // Less to do as we will never return to EFI ABI world +LDEAD_LOOP: + jmp LDEAD_LOOP // _exit should never return + + +ASM_GLOBAL ASM_PFX(GasketSecGetTime) +ASM_PFX(GasketSecGetTime): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(SecGetTime) + + leave + ret + +ASM_GLOBAL ASM_PFX(GasketSecSetTime) +ASM_PFX(GasketSecSetTime): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(SecSetTime) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketSecGetNextProtocol) +ASM_PFX(GasketSecGetNextProtocol): + pushl %ebp + movl %esp, %ebp + subl $40, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 20(%ebp), %eax + movl %eax, 12(%esp) + movl 16(%ebp), %eax + movl %eax, 8(%esp) + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(SecGetNextProtocol) + + leave + ret + +// PPIs produced by SEC + +ASM_GLOBAL ASM_PFX(GasketSecPeCoffGetEntryPoint) +ASM_PFX(GasketSecPeCoffGetEntryPoint): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(SecPeCoffGetEntryPoint) + + leave + ret + +ASM_GLOBAL ASM_PFX(GasketSecPeCoffRelocateImageExtraAction) +ASM_PFX(GasketSecPeCoffRelocateImageExtraAction): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(SecPeCoffRelocateImageExtraAction) + + leave + ret + +ASM_GLOBAL ASM_PFX(GasketSecPeCoffUnloadImageExtraAction) +ASM_PFX(GasketSecPeCoffUnloadImageExtraAction): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(SecPeCoffUnloadImageExtraAction) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketSecEmuThunkAddress) +ASM_PFX(GasketSecEmuThunkAddress): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + + call ASM_PFX(SecEmuThunkAddress) + + leave + ret + +// +// Gasket functions for EFI_EMU_UGA_IO_PROTOCOL +// + +ASM_GLOBAL ASM_PFX(GasketX11Size) +ASM_PFX(GasketX11Size): + pushl %ebp + movl %esp, %ebp + subl $40, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 20(%ebp), %eax + movl %eax, 12(%esp) + movl 16(%ebp), %eax + movl %eax, 8(%esp) + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(X11Size) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketX11CheckKey) +ASM_PFX(GasketX11CheckKey): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(X11CheckKey) + + leave + ret + +ASM_GLOBAL ASM_PFX(GasketX11GetKey) +ASM_PFX(GasketX11GetKey): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(X11GetKey) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketX11KeySetState) +ASM_PFX(GasketX11KeySetState): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(X11KeySetState) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketX11RegisterKeyNotify) +ASM_PFX(GasketX11RegisterKeyNotify): + pushl %ebp + movl %esp, %ebp + subl $40, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 20(%ebp), %eax + movl %eax, 12(%esp) + movl 16(%ebp), %eax + movl %eax, 8(%esp) + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(X11RegisterKeyNotify) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketX11Blt) +ASM_PFX(GasketX11Blt): + pushl %ebp + movl %esp, %ebp + subl $40, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 20(%ebp), %eax + movl %eax, 12(%esp) + movl 16(%ebp), %eax + movl %eax, 8(%esp) + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(X11Blt) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketX11CheckPointer) +ASM_PFX(GasketX11CheckPointer): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(X11CheckPointer) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketX11GetPointerState) +ASM_PFX(GasketX11GetPointerState): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(X11GetPointerState) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketX11GraphicsWindowOpen) +ASM_PFX(GasketX11GraphicsWindowOpen): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(X11GraphicsWindowOpen) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketX11GraphicsWindowClose) +ASM_PFX(GasketX11GraphicsWindowClose): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(X11GraphicsWindowClose) + + leave + ret + + +// Pthreads + +ASM_GLOBAL ASM_PFX(GasketPthreadMutexLock) +ASM_PFX(GasketPthreadMutexLock): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(PthreadMutexLock) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketPthreadMutexUnLock) +ASM_PFX(GasketPthreadMutexUnLock): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(PthreadMutexUnLock) + + leave + ret + +ASM_GLOBAL ASM_PFX(GasketPthreadMutexTryLock) +ASM_PFX(GasketPthreadMutexTryLock): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(PthreadMutexTryLock) + + leave + ret + +ASM_GLOBAL ASM_PFX(GasketPthreadMutexInit) +ASM_PFX(GasketPthreadMutexInit): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + + call ASM_PFX(PthreadMutexInit) + + leave + ret + + + +ASM_GLOBAL ASM_PFX(GasketPthreadMutexDestroy) +ASM_PFX(GasketPthreadMutexDestroy): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(PthreadMutexDestroy) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketPthreadCreate) +ASM_PFX(GasketPthreadCreate): + pushl %ebp + movl %esp, %ebp + subl $40, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 20(%ebp), %eax + movl %eax, 12(%esp) + movl 16(%ebp), %eax + movl %eax, 8(%esp) + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(PthreadCreate) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketPthreadExit) +ASM_PFX(GasketPthreadExit): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(PthreadExit) + + leave + ret + + + +ASM_GLOBAL ASM_PFX(GasketPthreadSelf) +ASM_PFX(GasketPthreadSelf): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + + call ASM_PFX(PthreadSelf) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketPthreadOpen) +ASM_PFX(GasketPthreadOpen): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(PthreadOpen) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketPthreadClose) +ASM_PFX(GasketPthreadClose): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(PthreadClose) + + leave + ret + + + + +// +// UNIX ABI to EFI ABI call +// +// UINTN +// ReverseGasketUint64 ( +// void *Api, +// UINTN Arg1 +// ); +ASM_GLOBAL ASM_PFX(ReverseGasketUint64) +ASM_PFX(ReverseGasketUint64): + pushl %ebp + movl %esp, %ebp + subl $8, %esp + movl 16(%ebp), %eax + movl %eax, 4(%esp) + movl 12(%ebp), %eax + movl %eax, (%esp) + calll *8(%ebp) + addl $8, %esp + popl %ebp + ret + + + +// +// UNIX ABI to EFI ABI call +// +// UINTN +// ReverseGasketUint64Uint64 ( +// void *Api, +// UINTN Arg1 +// UINTN Arg2 +// ); +ASM_GLOBAL ASM_PFX(ReverseGasketUint64Uint64) +ASM_PFX(ReverseGasketUint64Uint64): + pushl %ebp + movl %esp, %ebp + subl $24, %esp + movl 24(%ebp), %eax + movl %eax, 12(%esp) + movl 20(%ebp), %eax + movl %eax, 8(%esp) + movl 16(%ebp), %eax + movl %eax, 4(%esp) + movl 12(%ebp), %eax + movl %eax, (%esp) + calll *8(%ebp) + addl $24, %esp + popl %ebp + ret + + +ASM_GLOBAL ASM_PFX(GasketSecUnixPeiAutoScan) +ASM_PFX(GasketSecUnixPeiAutoScan): + pushl %ebp + movl %esp, %ebp + subl $40, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 16(%ebp), %eax + movl %eax, 8(%esp) + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(SecUnixPeiAutoScan) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketSecUnixFdAddress) +ASM_PFX(GasketSecUnixFdAddress): + pushl %ebp + movl %esp, %ebp + subl $40, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 20(%ebp), %eax + movl %eax, 12(%esp) + movl 16(%ebp), %eax + movl %eax, 8(%esp) + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(SecUnixFdAddress) + + leave + ret + + +// EmuIoThunk SimpleFileSystem + +ASM_GLOBAL ASM_PFX(GasketPosixOpenVolume) +ASM_PFX(GasketPosixOpenVolume): + pushl %ebp + movl %esp, %ebp + subl $40, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 20(%ebp), %eax + movl %eax, 12(%esp) + movl 16(%ebp), %eax + movl %eax, 8(%esp) + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(PosixOpenVolume) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketPosixFileOpen) +ASM_PFX(GasketPosixFileOpen): + pushl %ebp + movl %esp, %ebp + subl $56, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 28(%ebp), %eax + movl 32(%ebp), %ecx + movl %ecx, 24(%esp) + movl %eax, 20(%esp) + movl 20(%ebp), %eax + movl 24(%ebp), %ecx + movl %ecx, 16(%esp) + movl %eax, 12(%esp) + movl 16(%ebp), %eax + movl %eax, 8(%esp) + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(PosixFileOpen) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketPosixFileCLose) +ASM_PFX(GasketPosixFileCLose): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(PosixFileCLose) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketPosixFileDelete) +ASM_PFX(GasketPosixFileDelete): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(PosixFileDelete) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketPosixFileRead) +ASM_PFX(GasketPosixFileRead): + pushl %ebp + movl %esp, %ebp + subl $40, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 16(%ebp), %eax + movl %eax, 8(%esp) + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(PosixFileRead) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketPosixFileWrite) +ASM_PFX(GasketPosixFileWrite): + pushl %ebp + movl %esp, %ebp + subl $40, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 16(%ebp), %eax + movl %eax, 8(%esp) + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(PosixFileWrite) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketPosixFileSetPossition) +ASM_PFX(GasketPosixFileSetPossition): + pushl %ebp + movl %esp, %ebp + subl $40, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 12(%ebp), %eax + movl 16(%ebp), %ecx + movl %ecx, 8(%esp) + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(PosixFileSetPossition) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketPosixFileGetPossition) +ASM_PFX(GasketPosixFileGetPossition): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(PosixFileGetPossition) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketPosixFileGetInfo) +ASM_PFX(GasketPosixFileGetInfo): + pushl %ebp + movl %esp, %ebp + subl $40, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 20(%ebp), %eax + movl %eax, 12(%esp) + movl 16(%ebp), %eax + movl %eax, 8(%esp) + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(PosixFileGetInfo) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketPosixFileSetInfo) +ASM_PFX(GasketPosixFileSetInfo): + pushl %ebp + movl %esp, %ebp + subl $40, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 20(%ebp), %eax + movl %eax, 12(%esp) + movl 16(%ebp), %eax + movl %eax, 8(%esp) + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(PosixFileSetInfo) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketPosixFileFlush) +ASM_PFX(GasketPosixFileFlush): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(PosixFileFlush) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketPosixFileSystmeThunkOpen) +ASM_PFX(GasketPosixFileSystmeThunkOpen): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(PosixFileSystmeThunkOpen) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketPosixFileSystmeThunkClose) +ASM_PFX(GasketPosixFileSystmeThunkClose): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(PosixFileSystmeThunkClose) + + leave + ret + +ASM_GLOBAL ASM_PFX(GasketEmuBlockIoReset) +ASM_PFX(GasketEmuBlockIoReset): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(EmuBlockIoReset) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketEmuBlockIoReadBlocks) +ASM_PFX(GasketEmuBlockIoReadBlocks): + pushl %ebp + movl %esp, %ebp + subl $56, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 32(%ebp), %eax + movl %eax, 24(%esp) + movl 28(%ebp), %eax + movl %eax, 20(%esp) + movl 24(%ebp), %eax + movl %eax, 16(%esp) + movl 16(%ebp), %eax + movl 20(%ebp), %edx + movl %edx, 12(%esp) + movl %eax, 8(%esp) + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(EmuBlockIoReadBlocks) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketEmuBlockIoWriteBlocks) +ASM_PFX(GasketEmuBlockIoWriteBlocks): + pushl %ebp + movl %esp, %ebp + subl $56, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 32(%ebp), %eax + movl %eax, 24(%esp) + movl 28(%ebp), %eax + movl %eax, 20(%esp) + movl 24(%ebp), %eax + movl %eax, 16(%esp) + movl 16(%ebp), %eax + movl 20(%ebp), %edx + movl %edx, 12(%esp) + movl %eax, 8(%esp) + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(EmuBlockIoWriteBlocks) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketEmuBlockIoFlushBlocks) +ASM_PFX(GasketEmuBlockIoFlushBlocks): pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + + call ASM_PFX(EmuBlockIoFlushBlocks) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketEmuBlockIoCreateMapping) +ASM_PFX(GasketEmuBlockIoCreateMapping): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(EmuBlockIoCreateMapping) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketBlockIoThunkOpen) +ASM_PFX(GasketBlockIoThunkOpen): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(EmuBlockIoThunkOpen) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketBlockIoThunkClose) +ASM_PFX(GasketBlockIoThunkClose): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(EmuBlockIoThunkClose) + + leave + ret + + + +ASM_GLOBAL ASM_PFX(GasketSnpCreateMapping) +ASM_PFX(GasketSnpCreateMapping): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(EmuSnpCreateMapping) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketSnpStart) +ASM_PFX(GasketSnpStart): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(EmuSnpStart) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketSnpStop) +ASM_PFX(GasketSnpStop): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(EmuSnpStop) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketSnpInitialize) +ASM_PFX(GasketSnpInitialize): + pushl %ebp + movl %esp, %ebp + subl $40, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 16(%ebp), %eax + movl %eax, 8(%esp) + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(EmuSnpInitialize) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketSnpReset) +ASM_PFX(GasketSnpReset): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(EmuSnpReset) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketSnpShutdown) +ASM_PFX(GasketSnpShutdown): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(EmuSnpShutdown) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketSnpReceiveFilters) +ASM_PFX(GasketSnpReceiveFilters): + pushl %ebp + movl %esp, %ebp + subl $40, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 28(%ebp), %eax + movl %eax, 20(%esp) + movl 24(%ebp), %eax + movl %eax, 16(%esp) + movl 20(%ebp), %eax + movl %eax, 12(%esp) + movl 16(%ebp), %eax + movl %eax, 8(%esp) + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(EmuSnpReceiveFilters) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketSnpStationAddress) +ASM_PFX(GasketSnpStationAddress): + pushl %ebp + movl %esp, %ebp + subl $40, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 16(%ebp), %eax + movl %eax, 8(%esp) + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + leave + ret + + + +ASM_GLOBAL ASM_PFX(GasketSnpStatistics) +ASM_PFX(GasketSnpStatistics): + pushl %ebp + movl %esp, %ebp + subl $40, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 20(%ebp), %eax + movl %eax, 12(%esp) + movl 16(%ebp), %eax + movl %eax, 8(%esp) + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(EmuSnpStatistics) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketSnpMCastIpToMac) +ASM_PFX(GasketSnpMCastIpToMac): + pushl %ebp + movl %esp, %ebp + subl $40, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 20(%ebp), %eax + movl %eax, 12(%esp) + movl 16(%ebp), %eax + movl %eax, 8(%esp) + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(EmuSnpMCastIpToMac) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketSnpNvData) +ASM_PFX(GasketSnpNvData): + pushl %ebp + movl %esp, %ebp + subl $40, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 24(%ebp), %eax + movl %eax, 16(%esp) + movl 20(%ebp), %eax + movl %eax, 12(%esp) + movl 16(%ebp), %eax + movl %eax, 8(%esp) + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(EmuSnpNvData) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketSnpGetStatus) +ASM_PFX(GasketSnpGetStatus): + pushl %ebp + movl %esp, %ebp + subl $40, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 16(%ebp), %eax + movl %eax, 8(%esp) + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(EmuSnpGetStatus) + + leave + ret + + + +ASM_GLOBAL ASM_PFX(GasketSnpTransmit) +ASM_PFX(GasketSnpTransmit): + pushl %ebp + movl %esp, %ebp + subl $56, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 32(%ebp), %eax + movl %eax, 24(%esp) + movl 28(%ebp), %eax + movl %eax, 20(%esp) + movl 24(%ebp), %eax + movl %eax, 16(%esp) + movl 20(%ebp), %eax + movl %eax, 12(%esp) + movl 16(%ebp), %eax + movl %eax, 8(%esp) + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(EmuSnpTransmit) + + leave + ret + + + +ASM_GLOBAL ASM_PFX(GasketSnpReceive) +ASM_PFX(GasketSnpReceive): + pushl %ebp + movl %esp, %ebp + subl $56, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 32(%ebp), %eax + movl %eax, 24(%esp) + movl 28(%ebp), %eax + movl %eax, 20(%esp) + movl 24(%ebp), %eax + movl %eax, 16(%esp) + movl 20(%ebp), %eax + movl %eax, 12(%esp) + movl 16(%ebp), %eax + movl %eax, 8(%esp) + movl 12(%ebp), %eax + movl %eax, 4(%esp) + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(EmuSnpReceive) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketSnpThunkOpen) +ASM_PFX(GasketSnpThunkOpen): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(EmuSnpThunkOpen) + + leave + ret + + +ASM_GLOBAL ASM_PFX(GasketSnpThunkClose) +ASM_PFX(GasketSnpThunkClose): + pushl %ebp + movl %esp, %ebp + subl $24, %esp // sub extra 16 from the stack for alignment + and $-16, %esp // stack needs to end in 0xFFFFFFF0 before call + movl 8(%ebp), %eax + movl %eax, (%esp) + + call ASM_PFX(EmuSnpThunkClose) + + leave + ret + + diff --git a/EmulatorPkg/Unix/Host/Ia32/SwitchStack.c b/EmulatorPkg/Unix/Host/Ia32/SwitchStack.c new file mode 100644 index 0000000000..c75073ac2e --- /dev/null +++ b/EmulatorPkg/Unix/Host/Ia32/SwitchStack.c @@ -0,0 +1,74 @@ +/*++ + +Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+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. + + +--*/ + +#include "SecMain.h" + + +/** + Transfers control to a function starting with a new stack. + + Transfers control to the function specified by EntryPoint using the new stack + specified by NewStack and passing in the parameters specified by Context1 and + Context2. Context1 and Context2 are optional and may be NULL. The function + EntryPoint must never return. + + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + @param EntryPoint A pointer to function to call with the new stack. + @param Context1 A pointer to the context to pass into the EntryPoint + function. + @param Context2 A pointer to the context to pass into the EntryPoint + function. + @param NewStack A pointer to the new stack to use for the EntryPoint + function. + +**/ +VOID +EFIAPI +PeiSwitchStacks ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ) +{ + BASE_LIBRARY_JUMP_BUFFER JumpBuffer; + + ASSERT (EntryPoint != NULL); + ASSERT (NewStack != NULL); + + // + // Stack should be aligned with CPU_STACK_ALIGNMENT + // + ASSERT (((UINTN)NewStack & (CPU_STACK_ALIGNMENT - 1)) == 0); + + JumpBuffer.Eip = (UINTN)EntryPoint; + JumpBuffer.Esp = (UINTN)NewStack - sizeof (VOID*); + JumpBuffer.Esp -= sizeof (Context1) + sizeof (Context2); + ((VOID**)JumpBuffer.Esp)[1] = Context1; + ((VOID**)JumpBuffer.Esp)[2] = Context2; + + LongJump (&JumpBuffer, (UINTN)-1); + + + // + // PeiSwitchStacks () will never return + // + ASSERT (FALSE); +} + + + diff --git a/EmulatorPkg/Unix/Host/LinuxPacketFilter.c b/EmulatorPkg/Unix/Host/LinuxPacketFilter.c new file mode 100644 index 0000000000..20a08c9059 --- /dev/null +++ b/EmulatorPkg/Unix/Host/LinuxPacketFilter.c @@ -0,0 +1,604 @@ +/**@file + Linux Packet Filter implementation of the EMU_SNP_PROTOCOL that allows the + emulator to get on real networks. + + Currently only the Berkeley Packet Filter is fully implemented and this file + is just a template that needs to get filled in. + +Copyright (c) 2004 - 2009, Intel Corporation. All rights reserved.
+Portitions copyright (c) 2011, 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. + +**/ + + +#include "SecMain.h" + +#ifndef __APPLE__ + +#define EMU_SNP_PRIVATE_SIGNATURE SIGNATURE_32('E', 'M', 's', 'n') +typedef struct { + UINTN Signature; + + EMU_IO_THUNK_PROTOCOL *Thunk; + + + EMU_SNP_PROTOCOL EmuSnp; + EFI_SIMPLE_NETWORK_MODE *Mode; + +} EMU_SNP_PRIVATE; + +#define EMU_SNP_PRIVATE_DATA_FROM_THIS(a) \ + CR(a, EMU_SNP_PRIVATE, EmuSnp, EMU_SNP_PRIVATE_SIGNATURE) + +/** + Register storage for SNP Mode. + + @param This Protocol instance pointer. + @param Mode SimpleNetworkProtocol Mode structure passed into driver. + + @retval EFI_SUCCESS The network interface was started. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + +**/ +EFI_STATUS +EmuSnpCreateMapping ( + IN EMU_SNP_PROTOCOL *This, + IN EFI_SIMPLE_NETWORK_MODE *Mode + ) +{ + EMU_SNP_PRIVATE *Private; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + Private->Mode = Mode; + + return EFI_SUCCESS; +} + +/** + Changes the state of a network interface from "stopped" to "started". + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The network interface was started. + @retval EFI_ALREADY_STARTED The network interface is already in the started state. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EmuSnpStart ( + IN EMU_SNP_PROTOCOL *This + ) +{ + EMU_SNP_PRIVATE *Private; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + return EFI_UNSUPPORTED; +} + +/** + Changes the state of a network interface from "started" to "stopped". + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The network interface was stopped. + @retval EFI_ALREADY_STARTED The network interface is already in the stopped state. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EmuSnpStop ( + IN EMU_SNP_PROTOCOL *This + ) +{ + EMU_SNP_PRIVATE *Private; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + return EFI_UNSUPPORTED; +} + +/** + Resets a network adapter and allocates the transmit and receive buffers + required by the network interface; optionally, also requests allocation + of additional transmit and receive buffers. + + @param This The protocol instance pointer. + @param ExtraRxBufferSize The size, in bytes, of the extra receive buffer space + that the driver should allocate for the network interface. + Some network interfaces will not be able to use the extra + buffer, and the caller will not know if it is actually + being used. + @param ExtraTxBufferSize The size, in bytes, of the extra transmit buffer space + that the driver should allocate for the network interface. + Some network interfaces will not be able to use the extra + buffer, and the caller will not know if it is actually + being used. + + @retval EFI_SUCCESS The network interface was initialized. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_OUT_OF_RESOURCES There was not enough memory for the transmit and + receive buffers. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EmuSnpInitialize ( + IN EMU_SNP_PROTOCOL *This, + IN UINTN ExtraRxBufferSize OPTIONAL, + IN UINTN ExtraTxBufferSize OPTIONAL + ) +{ + EMU_SNP_PRIVATE *Private; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + return EFI_UNSUPPORTED; +} + +/** + Resets a network adapter and re-initializes it with the parameters that were + provided in the previous call to Initialize(). + + @param This The protocol instance pointer. + @param ExtendedVerification Indicates that the driver may perform a more + exhaustive verification operation of the device + during reset. + + @retval EFI_SUCCESS The network interface was reset. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EmuSnpReset ( + IN EMU_SNP_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + EMU_SNP_PRIVATE *Private; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + return EFI_UNSUPPORTED; +} + +/** + Resets a network adapter and leaves it in a state that is safe for + another driver to initialize. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The network interface was shutdown. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EmuSnpShutdown ( + IN EMU_SNP_PROTOCOL *This + ) +{ + EMU_SNP_PRIVATE *Private; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + return EFI_UNSUPPORTED; +} + +/** + Manages the multicast receive filters of a network interface. + + @param This The protocol instance pointer. + @param Enable A bit mask of receive filters to enable on the network interface. + @param Disable A bit mask of receive filters to disable on the network interface. + @param ResetMCastFilter Set to TRUE to reset the contents of the multicast receive + filters on the network interface to their default values. + @param McastFilterCnt Number of multicast HW MAC addresses in the new + MCastFilter list. This value must be less than or equal to + the MCastFilterCnt field of EMU_SNP_MODE. This + field is optional if ResetMCastFilter is TRUE. + @param MCastFilter A pointer to a list of new multicast receive filter HW MAC + addresses. This list will replace any existing multicast + HW MAC address list. This field is optional if + ResetMCastFilter is TRUE. + + @retval EFI_SUCCESS The multicast receive filter list was updated. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EmuSnpReceiveFilters ( + IN EMU_SNP_PROTOCOL *This, + IN UINT32 Enable, + IN UINT32 Disable, + IN BOOLEAN ResetMCastFilter, + IN UINTN MCastFilterCnt OPTIONAL, + IN EFI_MAC_ADDRESS *MCastFilter OPTIONAL + ) +{ + EMU_SNP_PRIVATE *Private; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + return EFI_UNSUPPORTED; +} + +/** + Modifies or resets the current station address, if supported. + + @param This The protocol instance pointer. + @param Reset Flag used to reset the station address to the network interfaces + permanent address. + @param New The new station address to be used for the network interface. + + @retval EFI_SUCCESS The network interfaces station address was updated. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EmuSnpStationAddress ( + IN EMU_SNP_PROTOCOL *This, + IN BOOLEAN Reset, + IN EFI_MAC_ADDRESS *New OPTIONAL + ) +{ + EMU_SNP_PRIVATE *Private; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + return EFI_UNSUPPORTED; +} + +/** + Resets or collects the statistics on a network interface. + + @param This Protocol instance pointer. + @param Reset Set to TRUE to reset the statistics for the network interface. + @param StatisticsSize On input the size, in bytes, of StatisticsTable. On + output the size, in bytes, of the resulting table of + statistics. + @param StatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that + contains the statistics. + + @retval EFI_SUCCESS The statistics were collected from the network interface. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_BUFFER_TOO_SMALL The Statistics buffer was too small. The current buffer + size needed to hold the statistics is returned in + StatisticsSize. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EmuSnpStatistics ( + IN EMU_SNP_PROTOCOL *This, + IN BOOLEAN Reset, + IN OUT UINTN *StatisticsSize OPTIONAL, + OUT EFI_NETWORK_STATISTICS *StatisticsTable OPTIONAL + ) +{ + EMU_SNP_PRIVATE *Private; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + return EFI_UNSUPPORTED; +} + +/** + Converts a multicast IP address to a multicast HW MAC address. + + @param This The protocol instance pointer. + @param IPv6 Set to TRUE if the multicast IP address is IPv6 [RFC 2460]. Set + to FALSE if the multicast IP address is IPv4 [RFC 791]. + @param IP The multicast IP address that is to be converted to a multicast + HW MAC address. + @param MAC The multicast HW MAC address that is to be generated from IP. + + @retval EFI_SUCCESS The multicast IP address was mapped to the multicast + HW MAC address. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_BUFFER_TOO_SMALL The Statistics buffer was too small. The current buffer + size needed to hold the statistics is returned in + StatisticsSize. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EmuSnpMCastIpToMac ( + IN EMU_SNP_PROTOCOL *This, + IN BOOLEAN IPv6, + IN EFI_IP_ADDRESS *IP, + OUT EFI_MAC_ADDRESS *MAC + ) +{ + EMU_SNP_PRIVATE *Private; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + return EFI_UNSUPPORTED; +} + +/** + Performs read and write operations on the NVRAM device attached to a + network interface. + + @param This The protocol instance pointer. + @param ReadWrite TRUE for read operations, FALSE for write operations. + @param Offset Byte offset in the NVRAM device at which to start the read or + write operation. This must be a multiple of NvRamAccessSize and + less than NvRamSize. + @param BufferSize The number of bytes to read or write from the NVRAM device. + This must also be a multiple of NvramAccessSize. + @param Buffer A pointer to the data buffer. + + @retval EFI_SUCCESS The NVRAM access was performed. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EmuSnpNvData ( + IN EMU_SNP_PROTOCOL *This, + IN BOOLEAN ReadWrite, + IN UINTN Offset, + IN UINTN BufferSize, + IN OUT VOID *Buffer + ) +{ + EMU_SNP_PRIVATE *Private; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + return EFI_UNSUPPORTED; +} + +/** + Reads the current interrupt status and recycled transmit buffer status from + a network interface. + + @param This The protocol instance pointer. + @param InterruptStatus A pointer to the bit mask of the currently active interrupts + If this is NULL, the interrupt status will not be read from + the device. If this is not NULL, the interrupt status will + be read from the device. When the interrupt status is read, + it will also be cleared. Clearing the transmit interrupt + does not empty the recycled transmit buffer array. + @param TxBuf Recycled transmit buffer address. The network interface will + not transmit if its internal recycled transmit buffer array + is full. Reading the transmit buffer does not clear the + transmit interrupt. If this is NULL, then the transmit buffer + status will not be read. If there are no transmit buffers to + recycle and TxBuf is not NULL, * TxBuf will be set to NULL. + + @retval EFI_SUCCESS The status of the network interface was retrieved. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EmuSnpGetStatus ( + IN EMU_SNP_PROTOCOL *This, + OUT UINT32 *InterruptStatus OPTIONAL, + OUT VOID **TxBuf OPTIONAL + ) +{ + EMU_SNP_PRIVATE *Private; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + return EFI_UNSUPPORTED; +} + +/** + Places a packet in the transmit queue of a network interface. + + @param This The protocol instance pointer. + @param HeaderSize The size, in bytes, of the media header to be filled in by + the Transmit() function. If HeaderSize is non-zero, then it + must be equal to This->Mode->MediaHeaderSize and the DestAddr + and Protocol parameters must not be NULL. + @param BufferSize The size, in bytes, of the entire packet (media header and + data) to be transmitted through the network interface. + @param Buffer A pointer to the packet (media header followed by data) to be + transmitted. This parameter cannot be NULL. If HeaderSize is zero, + then the media header in Buffer must already be filled in by the + caller. If HeaderSize is non-zero, then the media header will be + filled in by the Transmit() function. + @param SrcAddr The source HW MAC address. If HeaderSize is zero, then this parameter + is ignored. If HeaderSize is non-zero and SrcAddr is NULL, then + This->Mode->CurrentAddress is used for the source HW MAC address. + @param DestAddr The destination HW MAC address. If HeaderSize is zero, then this + parameter is ignored. + @param Protocol The type of header to build. If HeaderSize is zero, then this + parameter is ignored. See RFC 1700, section "Ether Types", for + examples. + + @retval EFI_SUCCESS The packet was placed on the transmit queue. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_NOT_READY The network interface is too busy to accept this transmit request. + @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EmuSnpTransmit ( + IN EMU_SNP_PROTOCOL *This, + IN UINTN HeaderSize, + IN UINTN BufferSize, + IN VOID *Buffer, + IN EFI_MAC_ADDRESS *SrcAddr OPTIONAL, + IN EFI_MAC_ADDRESS *DestAddr OPTIONAL, + IN UINT16 *Protocol OPTIONAL + ) +{ + EMU_SNP_PRIVATE *Private; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + return EFI_UNSUPPORTED; +} + +/** + Receives a packet from a network interface. + + @param This The protocol instance pointer. + @param HeaderSize The size, in bytes, of the media header received on the network + interface. If this parameter is NULL, then the media header size + will not be returned. + @param BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in + bytes, of the packet that was received on the network interface. + @param Buffer A pointer to the data buffer to receive both the media header and + the data. + @param SrcAddr The source HW MAC address. If this parameter is NULL, the + HW MAC source address will not be extracted from the media + header. + @param DestAddr The destination HW MAC address. If this parameter is NULL, + the HW MAC destination address will not be extracted from the + media header. + @param Protocol The media header type. If this parameter is NULL, then the + protocol will not be extracted from the media header. See + RFC 1700 section "Ether Types" for examples. + + @retval EFI_SUCCESS The received data was stored in Buffer, and BufferSize has + been updated to the number of bytes received. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_NOT_READY The network interface is too busy to accept this transmit + request. + @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +EFI_STATUS +EmuSnpReceive ( + IN EMU_SNP_PROTOCOL *This, + OUT UINTN *HeaderSize OPTIONAL, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer, + OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL, + OUT EFI_MAC_ADDRESS *DestAddr OPTIONAL, + OUT UINT16 *Protocol OPTIONAL + ) +{ + EMU_SNP_PRIVATE *Private; + + Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This); + + return EFI_UNSUPPORTED; +} + + +EMU_SNP_PROTOCOL gEmuSnpProtocol = { + GasketSnpCreateMapping, + GasketSnpStart, + GasketSnpStop, + GasketSnpInitialize, + GasketSnpReset, + GasketSnpShutdown, + GasketSnpReceiveFilters, + GasketSnpStationAddress, + GasketSnpStatistics, + GasketSnpMCastIpToMac, + GasketSnpNvData, + GasketSnpGetStatus, + GasketSnpTransmit, + GasketSnpReceive +}; + +EFI_STATUS +EmuSnpThunkOpen ( + IN EMU_IO_THUNK_PROTOCOL *This + ) +{ + EMU_SNP_PRIVATE *Private; + + if (This->Private != NULL) { + return EFI_ALREADY_STARTED; + } + + if (!CompareGuid (This->Protocol, &gEmuSnpProtocolGuid)) { + return EFI_UNSUPPORTED; + } + + Private = malloc (sizeof (EMU_SNP_PRIVATE)); + if (Private == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + + Private->Signature = EMU_SNP_PRIVATE_SIGNATURE; + Private->Thunk = This; + CopyMem (&Private->EmuSnp, &gEmuSnpProtocol, sizeof (gEmuSnpProtocol)); + + This->Interface = &Private->EmuSnp; + This->Private = Private; + return EFI_SUCCESS; +} + + +EFI_STATUS +EmuSnpThunkClose ( + IN EMU_IO_THUNK_PROTOCOL *This + ) +{ + EMU_SNP_PRIVATE *Private; + + if (!CompareGuid (This->Protocol, &gEmuSnpProtocolGuid)) { + return EFI_UNSUPPORTED; + } + + Private = This->Private; + free (Private); + + return EFI_SUCCESS; +} + + + +EMU_IO_THUNK_PROTOCOL gSnpThunkIo = { + &gEmuSnpProtocolGuid, + NULL, + NULL, + 0, + GasketSnpThunkOpen, + GasketSnpThunkClose, + NULL +}; + +#endif diff --git a/EmulatorPkg/Unix/Host/MemoryAllocationLib.c b/EmulatorPkg/Unix/Host/MemoryAllocationLib.c new file mode 100644 index 0000000000..76b7271872 --- /dev/null +++ b/EmulatorPkg/Unix/Host/MemoryAllocationLib.c @@ -0,0 +1,145 @@ +/*++ @file + + Copyright (c) 2011, Intel Corporation. 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 "Base.h" +#include "Library/BaseMemoryLib.h" +#include "Library/MemoryAllocationLib.h" + +#include + +/** + Allocates a buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a + pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is + returned. If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocatePool ( + IN UINTN AllocationSize + ) +{ + return (VOID*) malloc (AllocationSize); +} + + +/** + Allocates and zeros a buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the + buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the + request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateZeroPool ( + IN UINTN AllocationSize + ) +{ + VOID *Buffer; + + Buffer = AllocatePool (AllocationSize); + if (Buffer == NULL) { + return NULL; + } + + ZeroMem (Buffer, AllocationSize); + + return Buffer; +} + + +/** + Reallocates a buffer of type EfiBootServicesData. + + Allocates and zeros the number bytes specified by NewSize from memory of type + EfiBootServicesData. If OldBuffer is not NULL, then the smaller of OldSize and + NewSize bytes are copied from OldBuffer to the newly allocated buffer, and + OldBuffer is freed. A pointer to the newly allocated buffer is returned. + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not + enough memory remaining to satisfy the request, then NULL is returned. + + If the allocation of the new buffer is successful and the smaller of NewSize and OldSize + is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). + + @param OldSize The size, in bytes, of OldBuffer. + @param NewSize The size, in bytes, of the buffer to reallocate. + @param OldBuffer The buffer to copy to the allocated buffer. This is an optional + parameter that may be NULL. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +ReallocatePool ( + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + VOID *NewBuffer; + + NewBuffer = AllocatePool (NewSize); + if (NewBuffer == NULL) { + return NULL; + } + + if (OldBuffer != NULL) { + if (OldSize > 0) { + CopyMem (NewBuffer, OldBuffer, OldSize); + } + + FreePool (OldBuffer); + } + + return NewBuffer; +} + + +/** + Frees a buffer that was previously allocated with one of the pool allocation functions in the + Memory Allocation Library. + + Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the + pool allocation services of the Memory Allocation Library. If it is not possible to free pool + resources, then this function will perform no actions. + + If Buffer was not allocated with a pool allocation function in the Memory Allocation Library, + then ASSERT(). + + @param Buffer Pointer to the buffer to free. + +**/ +VOID +EFIAPI +FreePool ( + IN VOID *Buffer + ) +{ + free ((void *) Buffer); +} + diff --git a/EmulatorPkg/Unix/Host/PosixFileSystem.c b/EmulatorPkg/Unix/Host/PosixFileSystem.c new file mode 100644 index 0000000000..3141a3cf1a --- /dev/null +++ b/EmulatorPkg/Unix/Host/PosixFileSystem.c @@ -0,0 +1,1556 @@ +/*++ @file + POSIX Pthreads to emulate APs and implement threads + +Copyright (c) 2011, 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. + + +**/ + +#include "SecMain.h" + + +#define EMU_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE SIGNATURE_32 ('E', 'P', 'f', 's') + +typedef struct { + UINTN Signature; + EMU_IO_THUNK_PROTOCOL *Thunk; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL SimpleFileSystem; + CHAR8 *FilePath; + CHAR16 *VolumeLabel; + BOOLEAN FileHandlesOpen; +} EMU_SIMPLE_FILE_SYSTEM_PRIVATE; + +#define EMU_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS(a) \ + CR (a, \ + EMU_SIMPLE_FILE_SYSTEM_PRIVATE, \ + SimpleFileSystem, \ + EMU_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE \ + ) + + +#define EMU_EFI_FILE_PRIVATE_SIGNATURE SIGNATURE_32 ('E', 'P', 'f', 'i') + +typedef struct { + UINTN Signature; + EMU_IO_THUNK_PROTOCOL *Thunk; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem; + EFI_FILE_PROTOCOL EfiFile; + int fd; + DIR *Dir; + BOOLEAN IsRootDirectory; + BOOLEAN IsDirectoryPath; + BOOLEAN IsOpenedByRead; + char *FileName; + struct dirent *Dirent; +} EMU_EFI_FILE_PRIVATE; + +#define EMU_EFI_FILE_PRIVATE_DATA_FROM_THIS(a) \ + CR (a, \ + EMU_EFI_FILE_PRIVATE, \ + EfiFile, \ + EMU_EFI_FILE_PRIVATE_SIGNATURE \ + ) + +EFI_STATUS +PosixFileGetInfo ( + IN EFI_FILE_PROTOCOL *This, + IN EFI_GUID *InformationType, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + +EFI_STATUS +PosixFileSetInfo ( + IN EFI_FILE_PROTOCOL *This, + IN EFI_GUID *InformationType, + IN UINTN BufferSize, + IN VOID *Buffer + ); + + +EFI_FILE_PROTOCOL gPosixFileProtocol = { + EFI_FILE_REVISION, + GasketPosixFileOpen, + GasketPosixFileCLose, + GasketPosixFileDelete, + GasketPosixFileRead, + GasketPosixFileWrite, + GasketPosixFileGetPossition, + GasketPosixFileSetPossition, + GasketPosixFileGetInfo, + GasketPosixFileSetInfo, + GasketPosixFileFlush +}; + +EFI_SIMPLE_FILE_SYSTEM_PROTOCOL gPosixFileSystemProtocol = { + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION, + GasketPosixOpenVolume, +}; + + +/** + Open the root directory on a volume. + + @param This Protocol instance pointer. + @param Root Returns an Open file handle for the root directory + + @retval EFI_SUCCESS The device was opened. + @retval EFI_UNSUPPORTED This volume does not support the file system. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_ACCESS_DENIED The service denied access to the file. + @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources. + +**/ +EFI_STATUS +PosixOpenVolume ( + IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, + OUT EFI_FILE_PROTOCOL **Root + ) +{ + EFI_STATUS Status; + EMU_SIMPLE_FILE_SYSTEM_PRIVATE *Private; + EMU_EFI_FILE_PRIVATE *PrivateFile; + + Private = EMU_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (This); + + Status = EFI_OUT_OF_RESOURCES; + PrivateFile = malloc (sizeof (EMU_EFI_FILE_PRIVATE)); + if (PrivateFile == NULL) { + goto Done; + } + + PrivateFile->FileName = malloc (AsciiStrSize (Private->FilePath)); + if (PrivateFile->FileName == NULL) { + goto Done; + } + AsciiStrCpy (PrivateFile->FileName, Private->FilePath); + + PrivateFile->Signature = EMU_EFI_FILE_PRIVATE_SIGNATURE; + PrivateFile->Thunk = Private->Thunk; + PrivateFile->SimpleFileSystem = This; + PrivateFile->IsRootDirectory = TRUE; + PrivateFile->IsDirectoryPath = TRUE; + PrivateFile->IsOpenedByRead = TRUE; + + CopyMem (&PrivateFile->EfiFile, &gPosixFileProtocol, sizeof (EFI_FILE_PROTOCOL)); + + PrivateFile->fd = -1; + PrivateFile->Dir = NULL; + PrivateFile->Dirent = NULL; + + *Root = &PrivateFile->EfiFile; + + PrivateFile->Dir = opendir (PrivateFile->FileName); + if (PrivateFile->Dir == NULL) { + Status = EFI_ACCESS_DENIED; + } else { + Status = EFI_SUCCESS; + } + +Done: + if (EFI_ERROR (Status)) { + if (PrivateFile != NULL) { + if (PrivateFile->FileName != NULL) { + free (PrivateFile->FileName); + } + + free (PrivateFile); + } + + *Root = NULL; + } + + return Status; +} + + +EFI_STATUS +ErrnoToEfiStatus () +{ + switch (errno) { + case EACCES: + return EFI_ACCESS_DENIED; + + case EDQUOT: + case ENOSPC: + return EFI_VOLUME_FULL; + + default: + return EFI_DEVICE_ERROR; + } +} + +VOID +CutPrefix ( + IN CHAR8 *Str, + IN UINTN Count + ) +{ + CHAR8 *Pointer; + + if (AsciiStrLen (Str) < Count) { + ASSERT (0); + } + + for (Pointer = Str; *(Pointer + Count); Pointer++) { + *Pointer = *(Pointer + Count); + } + + *Pointer = *(Pointer + Count); +} + + +VOID +PosixSystemTimeToEfiTime ( + IN time_t SystemTime, + OUT EFI_TIME *Time + ) +{ + struct tm *tm; + + tm = gmtime (&SystemTime); + Time->Year = tm->tm_year; + Time->Month = tm->tm_mon + 1; + Time->Day = tm->tm_mday; + Time->Hour = tm->tm_hour; + Time->Minute = tm->tm_min; + Time->Second = tm->tm_sec; + Time->Nanosecond = 0; + + Time->TimeZone = timezone; + Time->Daylight = (daylight ? EFI_TIME_ADJUST_DAYLIGHT : 0) | (tm->tm_isdst > 0 ? EFI_TIME_IN_DAYLIGHT : 0); +} + + +EFI_STATUS +UnixSimpleFileSystemFileInfo ( + EMU_EFI_FILE_PRIVATE *PrivateFile, + IN CHAR8 *FileName, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + UINTN Size; + UINTN NameSize; + UINTN ResultSize; + EFI_FILE_INFO *Info; + CHAR8 *RealFileName; + CHAR8 *TempPointer; + CHAR16 *BufferFileName; + struct stat buf; + + if (FileName != NULL) { + RealFileName = FileName; + } else if (PrivateFile->IsRootDirectory) { + RealFileName = ""; + } else { + RealFileName = PrivateFile->FileName; + } + + TempPointer = RealFileName; + while (*TempPointer) { + if (*TempPointer == '/') { + RealFileName = TempPointer + 1; + } + + TempPointer++; + } + + Size = SIZE_OF_EFI_FILE_INFO; + NameSize = AsciiStrSize (RealFileName) * 2; + ResultSize = Size + NameSize; + + if (*BufferSize < ResultSize) { + *BufferSize = ResultSize; + return EFI_BUFFER_TOO_SMALL; + } + if (stat (FileName == NULL ? PrivateFile->FileName : FileName, &buf) < 0) { + return EFI_DEVICE_ERROR; + } + + Status = EFI_SUCCESS; + + Info = Buffer; + ZeroMem (Info, ResultSize); + + Info->Size = ResultSize; + Info->FileSize = buf.st_size; + Info->PhysicalSize = MultU64x32 (buf.st_blocks, buf.st_blksize); + + PosixSystemTimeToEfiTime (buf.st_ctime, &Info->CreateTime); + PosixSystemTimeToEfiTime (buf.st_atime, &Info->LastAccessTime); + PosixSystemTimeToEfiTime (buf.st_mtime, &Info->ModificationTime); + + if (!(buf.st_mode & S_IWUSR)) { + Info->Attribute |= EFI_FILE_READ_ONLY; + } + + if (S_ISDIR(buf.st_mode)) { + Info->Attribute |= EFI_FILE_DIRECTORY; + } + + + BufferFileName = (CHAR16 *)((CHAR8 *) Buffer + Size); + while (*RealFileName) { + *BufferFileName++ = *RealFileName++; + } + *BufferFileName = 0; + + *BufferSize = ResultSize; + return Status; +} + +BOOLEAN +IsZero ( + IN VOID *Buffer, + IN UINTN Length + ) +{ + if (Buffer == NULL || Length == 0) { + return FALSE; + } + + if (*(UINT8 *) Buffer != 0) { + return FALSE; + } + + if (Length > 1) { + if (!CompareMem (Buffer, (UINT8 *) Buffer + 1, Length - 1)) { + return FALSE; + } + } + + return TRUE; +} + + + +/** + Opens a new file relative to the source file's location. + + @param This The protocol instance pointer. + @param NewHandle Returns File Handle for FileName. + @param FileName Null terminated string. "\", ".", and ".." are supported. + @param OpenMode Open mode for file. + @param Attributes Only used for EFI_FILE_MODE_CREATE. + + @retval EFI_SUCCESS The device was opened. + @retval EFI_NOT_FOUND The specified file could not be found on the device. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_MEDIA_CHANGED The media has changed. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_ACCESS_DENIED The service denied access to the file. + @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources. + @retval EFI_VOLUME_FULL The volume is full. + +**/ +EFI_STATUS +PosixFileOpen ( + IN EFI_FILE_PROTOCOL *This, + OUT EFI_FILE_PROTOCOL **NewHandle, + IN CHAR16 *FileName, + IN UINT64 OpenMode, + IN UINT64 Attributes + ) +{ + EFI_FILE_PROTOCOL *Root; + EMU_EFI_FILE_PRIVATE *PrivateFile; + EMU_EFI_FILE_PRIVATE *NewPrivateFile; + EMU_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot; + EFI_STATUS Status; + CHAR16 *Src; + char *Dst; + CHAR8 *RealFileName; + char *ParseFileName; + char *GuardPointer; + CHAR8 TempChar; + UINTN Count; + BOOLEAN TrailingDash; + BOOLEAN LoopFinish; + UINTN InfoSize; + EFI_FILE_INFO *Info; + struct stat finfo; + int res; + + + PrivateFile = EMU_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + PrivateRoot = EMU_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem); + NewPrivateFile = NULL; + Status = EFI_OUT_OF_RESOURCES; + + // + // BUGBUG: assume an open of root + // if current location, return current data + // + if ((StrCmp (FileName, L"\\") == 0) || + (StrCmp (FileName, L".") == 0 && PrivateFile->IsRootDirectory)) { +OpenRoot: + Status = PosixOpenVolume (PrivateFile->SimpleFileSystem, &Root); + NewPrivateFile = EMU_EFI_FILE_PRIVATE_DATA_FROM_THIS (Root); + goto Done; + } + + TrailingDash = FALSE; + if (FileName[StrLen (FileName) - 1] == L'\\') { + TrailingDash = TRUE; + FileName[StrLen (FileName) - 1] = 0; + } + + // + // Attempt to open the file + // + NewPrivateFile = malloc (sizeof (EMU_EFI_FILE_PRIVATE)); + if (NewPrivateFile == NULL) { + goto Done; + } + + CopyMem (NewPrivateFile, PrivateFile, sizeof (EMU_EFI_FILE_PRIVATE)); + + NewPrivateFile->FileName = malloc (AsciiStrSize (PrivateFile->FileName) + 1 + StrLen (FileName) + 1); + if (NewPrivateFile->FileName == NULL) { + goto Done; + } + + if (*FileName == L'\\') { + AsciiStrCpy (NewPrivateFile->FileName, PrivateRoot->FilePath); + // Skip first '\'. + Src = FileName + 1; + } else { + AsciiStrCpy (NewPrivateFile->FileName, PrivateFile->FileName); + Src = FileName; + } + Dst = NewPrivateFile->FileName + AsciiStrLen (NewPrivateFile->FileName); + GuardPointer = NewPrivateFile->FileName + AsciiStrLen (PrivateRoot->FilePath); + *Dst++ = '/'; + // Convert unicode to ascii and '\' to '/' + while (*Src) { + if (*Src == '\\') { + *Dst++ = '/'; + } else { + *Dst++ = *Src; + } + Src++; + } + *Dst = 0; + + + // + // Get rid of . and .., except leading . or .. + // + + // + // GuardPointer protect simplefilesystem root path not be destroyed + // + + LoopFinish = FALSE; + while (!LoopFinish) { + LoopFinish = TRUE; + + for (ParseFileName = GuardPointer; *ParseFileName; ParseFileName++) { + if (*ParseFileName == '.' && + (*(ParseFileName + 1) == 0 || *(ParseFileName + 1) == '/') && + *(ParseFileName - 1) == '/' + ) { + + // + // cut /. + // + CutPrefix (ParseFileName - 1, 2); + LoopFinish = FALSE; + break; + } + + if (*ParseFileName == '.' && + *(ParseFileName + 1) == '.' && + (*(ParseFileName + 2) == 0 || *(ParseFileName + 2) == '/') && + *(ParseFileName - 1) == '/' + ) { + + ParseFileName--; + Count = 3; + + while (ParseFileName != GuardPointer) { + ParseFileName--; + Count++; + if (*ParseFileName == '/') { + break; + } + } + + // + // cut /.. and its left directory + // + CutPrefix (ParseFileName, Count); + LoopFinish = FALSE; + break; + } + } + } + + if (AsciiStrCmp (NewPrivateFile->FileName, PrivateRoot->FilePath) == 0) { + NewPrivateFile->IsRootDirectory = TRUE; + free (NewPrivateFile->FileName); + free (NewPrivateFile); + goto OpenRoot; + } + + RealFileName = NewPrivateFile->FileName + AsciiStrLen(NewPrivateFile->FileName) - 1; + while (RealFileName > NewPrivateFile->FileName && *RealFileName != '/') { + RealFileName--; + } + + TempChar = *(RealFileName - 1); + *(RealFileName - 1) = 0; + *(RealFileName - 1) = TempChar; + + + // + // Test whether file or directory + // + NewPrivateFile->IsRootDirectory = FALSE; + NewPrivateFile->fd = -1; + NewPrivateFile->Dir = NULL; + if (OpenMode & EFI_FILE_MODE_CREATE) { + if (Attributes & EFI_FILE_DIRECTORY) { + NewPrivateFile->IsDirectoryPath = TRUE; + } else { + NewPrivateFile->IsDirectoryPath = FALSE; + } + } else { + res = stat (NewPrivateFile->FileName, &finfo); + if (res == 0 && S_ISDIR(finfo.st_mode)) { + NewPrivateFile->IsDirectoryPath = TRUE; + } else { + NewPrivateFile->IsDirectoryPath = FALSE; + } + } + + if (OpenMode & EFI_FILE_MODE_WRITE) { + NewPrivateFile->IsOpenedByRead = FALSE; + } else { + NewPrivateFile->IsOpenedByRead = TRUE; + } + + Status = EFI_SUCCESS; + + // + // deal with directory + // + if (NewPrivateFile->IsDirectoryPath) { + if ((OpenMode & EFI_FILE_MODE_CREATE)) { + // + // Create a directory + // + if (mkdir (NewPrivateFile->FileName, 0777) != 0) { + if (errno != EEXIST) { + //free (TempFileName); + Status = EFI_ACCESS_DENIED; + goto Done; + } + } + } + + NewPrivateFile->Dir = opendir (NewPrivateFile->FileName); + if (NewPrivateFile->Dir == NULL) { + if (errno == EACCES) { + Status = EFI_ACCESS_DENIED; + } else { + Status = EFI_NOT_FOUND; + } + + goto Done; + } + + } else { + // + // deal with file + // + NewPrivateFile->fd = open ( + NewPrivateFile->FileName, + ((OpenMode & EFI_FILE_MODE_CREATE) ? O_CREAT : 0) | (NewPrivateFile->IsOpenedByRead ? O_RDONLY : O_RDWR), + 0666 + ); + if (NewPrivateFile->fd < 0) { + if (errno == ENOENT) { + Status = EFI_NOT_FOUND; + } else { + Status = EFI_ACCESS_DENIED; + } + } + } + + if ((OpenMode & EFI_FILE_MODE_CREATE) && Status == EFI_SUCCESS) { + // + // Set the attribute + // + InfoSize = 0; + Info = NULL; + Status = PosixFileGetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, &InfoSize, Info); + if (Status != EFI_BUFFER_TOO_SMALL) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + + Info = malloc (InfoSize); + if (Info == NULL) { + goto Done; + } + + Status = PosixFileGetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, &InfoSize, Info); + if (EFI_ERROR (Status)) { + goto Done; + } + + Info->Attribute = Attributes; + PosixFileSetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, InfoSize, Info); + + free (Info); + } + +Done: ; + if (TrailingDash) { + FileName[StrLen (FileName) + 1] = 0; + FileName[StrLen (FileName)] = L'\\'; + } + + if (EFI_ERROR (Status)) { + if (NewPrivateFile) { + if (NewPrivateFile->FileName) { + free (NewPrivateFile->FileName); + } + + free (NewPrivateFile); + } + } else { + *NewHandle = &NewPrivateFile->EfiFile; + } + + return Status; +} + + + +/** + Close the file handle + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The device was opened. + +**/ +EFI_STATUS +PosixFileCLose ( + IN EFI_FILE_PROTOCOL *This + ) +{ + EMU_EFI_FILE_PRIVATE *PrivateFile; + + PrivateFile = EMU_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + + if (PrivateFile->fd >= 0) { + close (PrivateFile->fd); + } + if (PrivateFile->Dir != NULL) { + closedir (PrivateFile->Dir); + } + + PrivateFile->fd = -1; + PrivateFile->Dir = NULL; + + if (PrivateFile->FileName) { + free (PrivateFile->FileName); + } + + free (PrivateFile); + + return EFI_SUCCESS; +} + + +/** + Close and delete the file handle. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The device was opened. + @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted. + +**/ +EFI_STATUS +PosixFileDelete ( + IN EFI_FILE_PROTOCOL *This + ) +{ + EFI_STATUS Status; + EMU_EFI_FILE_PRIVATE *PrivateFile; + + PrivateFile = EMU_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + Status = EFI_WARN_DELETE_FAILURE; + + if (PrivateFile->IsDirectoryPath) { + if (PrivateFile->Dir != NULL) { + closedir (PrivateFile->Dir); + PrivateFile->Dir = NULL; + } + + if (rmdir (PrivateFile->FileName) == 0) { + Status = EFI_SUCCESS; + } + } else { + close (PrivateFile->fd); + PrivateFile->fd = -1; + + if (!PrivateFile->IsOpenedByRead) { + if (!unlink (PrivateFile->FileName)) { + Status = EFI_SUCCESS; + } + } + } + + free (PrivateFile->FileName); + free (PrivateFile); + + return Status; +} + + +/** + Read data from the file. + + @param This Protocol instance pointer. + @param BufferSize On input size of buffer, on output amount of data in buffer. + @param Buffer The buffer in which data is read. + + @retval EFI_SUCCESS Data was read. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_BUFFER_TO_SMALL BufferSize is too small. BufferSize contains required size. + +**/ +EFI_STATUS +PosixFileRead ( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + EMU_EFI_FILE_PRIVATE *PrivateFile; + EFI_STATUS Status; + int Res; + UINTN Size; + UINTN NameSize; + UINTN ResultSize; + CHAR8 *FullFileName; + + + PrivateFile = EMU_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + + if (!PrivateFile->IsDirectoryPath) { + if (PrivateFile->fd < 0) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + + Res = read (PrivateFile->fd, Buffer, *BufferSize); + if (Res < 0) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + *BufferSize = Res; + Status = EFI_SUCCESS; + goto Done; + } + + // + // Read on a directory. + // + if (PrivateFile->Dir == NULL) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + + if (PrivateFile->Dirent == NULL) { + PrivateFile->Dirent = readdir (PrivateFile->Dir); + if (PrivateFile->Dirent == NULL) { + *BufferSize = 0; + Status = EFI_SUCCESS; + goto Done; + } + } + + Size = SIZE_OF_EFI_FILE_INFO; + NameSize = AsciiStrLen (PrivateFile->Dirent->d_name) + 1; + ResultSize = Size + 2 * NameSize; + + if (*BufferSize < ResultSize) { + *BufferSize = ResultSize; + Status = EFI_BUFFER_TOO_SMALL; + goto Done; + } + Status = EFI_SUCCESS; + + *BufferSize = ResultSize; + + FullFileName = malloc (AsciiStrLen(PrivateFile->FileName) + 1 + NameSize); + if (FullFileName == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + AsciiStrCpy (FullFileName, PrivateFile->FileName); + AsciiStrCat (FullFileName, "/"); + AsciiStrCat (FullFileName, PrivateFile->Dirent->d_name); + Status = UnixSimpleFileSystemFileInfo ( + PrivateFile, + FullFileName, + BufferSize, + Buffer + ); + free (FullFileName); + + PrivateFile->Dirent = NULL; + +Done: + return Status; +} + + + +/** + Write data to a file. + + @param This Protocol instance pointer. + @param BufferSize On input size of buffer, on output amount of data in buffer. + @param Buffer The buffer in which data to write. + + @retval EFI_SUCCESS Data was written. + @retval EFI_UNSUPPORTED Writes to Open directory are not supported. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_DEVICE_ERROR An attempt was made to write to a deleted file. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The device is write protected. + @retval EFI_ACCESS_DENIED The file was open for read only. + @retval EFI_VOLUME_FULL The volume is full. + +**/ +EFI_STATUS +PosixFileWrite ( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + EMU_EFI_FILE_PRIVATE *PrivateFile; + int Res; + + + PrivateFile = EMU_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + + if (PrivateFile->fd < 0) { + return EFI_DEVICE_ERROR; + } + + if (PrivateFile->IsDirectoryPath) { + return EFI_UNSUPPORTED; + } + + if (PrivateFile->IsOpenedByRead) { + return EFI_ACCESS_DENIED; + } + + Res = write (PrivateFile->fd, Buffer, *BufferSize); + if (Res == (UINTN)-1) { + return ErrnoToEfiStatus (); + } + + *BufferSize = Res; + return EFI_SUCCESS; +} + + + +/** + Set a files current position + + @param This Protocol instance pointer. + @param Position Byte position from the start of the file. + + @retval EFI_SUCCESS Data was written. + @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open. + +**/ +EFI_STATUS +PosixFileSetPossition ( + IN EFI_FILE_PROTOCOL *This, + IN UINT64 Position + ) +{ + EMU_EFI_FILE_PRIVATE *PrivateFile; + off_t Pos; + + PrivateFile = EMU_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + + if (PrivateFile->IsDirectoryPath) { + if (Position != 0) { + return EFI_UNSUPPORTED; + } + + if (PrivateFile->Dir == NULL) { + return EFI_DEVICE_ERROR; + } + rewinddir (PrivateFile->Dir); + return EFI_SUCCESS; + } else { + if (Position == (UINT64) -1) { + Pos = lseek (PrivateFile->fd, 0, SEEK_END); + } else { + Pos = lseek (PrivateFile->fd, Position, SEEK_SET); + } + if (Pos == (off_t)-1) { + return ErrnoToEfiStatus (); + } + return EFI_SUCCESS; + } +} + + + +/** + Get a file's current position + + @param This Protocol instance pointer. + @param Position Byte position from the start of the file. + + @retval EFI_SUCCESS Data was written. + @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.. + +**/ +EFI_STATUS +PosixFileGetPossition ( + IN EFI_FILE_PROTOCOL *This, + OUT UINT64 *Position + ) +{ + EFI_STATUS Status; + EMU_EFI_FILE_PRIVATE *PrivateFile; + + PrivateFile = EMU_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + + if (PrivateFile->IsDirectoryPath) { + Status = EFI_UNSUPPORTED; + } else { + *Position = (UINT64)lseek (PrivateFile->fd, 0, SEEK_CUR); + Status = (*Position == (UINT64) -1) ? ErrnoToEfiStatus () : EFI_SUCCESS; + } + + return Status; +} + + +/** + Get information about a file. + + @param This Protocol instance pointer. + @param InformationType Type of information to return in Buffer. + @param BufferSize On input size of buffer, on output amount of data in buffer. + @param Buffer The buffer to return data. + + @retval EFI_SUCCESS Data was returned. + @retval EFI_UNSUPPORTED InformationType is not supported. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The device is write protected. + @retval EFI_ACCESS_DENIED The file was open for read only. + @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in BufferSize. + +**/ +EFI_STATUS +PosixFileGetInfo ( + IN EFI_FILE_PROTOCOL *This, + IN EFI_GUID *InformationType, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + EMU_EFI_FILE_PRIVATE *PrivateFile; + EFI_FILE_SYSTEM_INFO *FileSystemInfoBuffer; + int UnixStatus; + EMU_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot; + struct statfs buf; + + PrivateFile = EMU_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + PrivateRoot = EMU_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem); + + Status = EFI_SUCCESS; + if (CompareGuid (InformationType, &gEfiFileInfoGuid)) { + Status = UnixSimpleFileSystemFileInfo (PrivateFile, NULL, BufferSize, Buffer); + } else if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) { + if (*BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel)) { + *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel); + return EFI_BUFFER_TOO_SMALL; + } + + UnixStatus = statfs (PrivateFile->FileName, &buf); + if (UnixStatus < 0) { + return EFI_DEVICE_ERROR; + } + + FileSystemInfoBuffer = (EFI_FILE_SYSTEM_INFO *) Buffer; + FileSystemInfoBuffer->Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel); + FileSystemInfoBuffer->ReadOnly = FALSE; + + // + // Succeeded + // + FileSystemInfoBuffer->VolumeSize = MultU64x32 (buf.f_blocks, buf.f_bsize); + FileSystemInfoBuffer->FreeSpace = MultU64x32 (buf.f_bavail, buf.f_bsize); + FileSystemInfoBuffer->BlockSize = buf.f_bsize; + + + StrCpy ((CHAR16 *) FileSystemInfoBuffer->VolumeLabel, PrivateRoot->VolumeLabel); + *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel); + + } else if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) { + if (*BufferSize < StrSize (PrivateRoot->VolumeLabel)) { + *BufferSize = StrSize (PrivateRoot->VolumeLabel); + return EFI_BUFFER_TOO_SMALL; + } + + StrCpy ((CHAR16 *) Buffer, PrivateRoot->VolumeLabel); + *BufferSize = StrSize (PrivateRoot->VolumeLabel); + + } + + return Status; +} + + +/** + Set information about a file + + @param File Protocol instance pointer. + @param InformationType Type of information in Buffer. + @param BufferSize Size of buffer. + @param Buffer The data to write. + + @retval EFI_SUCCESS Data was returned. + @retval EFI_UNSUPPORTED InformationType is not supported. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The device is write protected. + @retval EFI_ACCESS_DENIED The file was open for read only. + +**/ +EFI_STATUS +PosixFileSetInfo ( + IN EFI_FILE_PROTOCOL *This, + IN EFI_GUID *InformationType, + IN UINTN BufferSize, + IN VOID *Buffer + ) +{ + EMU_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot; + EMU_EFI_FILE_PRIVATE *PrivateFile; + EFI_FILE_INFO *OldFileInfo; + EFI_FILE_INFO *NewFileInfo; + EFI_STATUS Status; + UINTN OldInfoSize; + mode_t NewAttr; + struct stat OldAttr; + CHAR8 *OldFileName; + CHAR8 *NewFileName; + CHAR8 *CharPointer; + BOOLEAN AttrChangeFlag; + BOOLEAN NameChangeFlag; + BOOLEAN SizeChangeFlag; + BOOLEAN TimeChangeFlag; + struct tm NewLastAccessSystemTime; + struct tm NewLastWriteSystemTime; + EFI_FILE_SYSTEM_INFO *NewFileSystemInfo; + CHAR8 *AsciiFilePtr; + CHAR16 *UnicodeFilePtr; + int UnixStatus; + struct utimbuf Utime; + + + PrivateFile = EMU_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + PrivateRoot = EMU_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem); + errno = 0; + Status = EFI_UNSUPPORTED; + OldFileInfo = NewFileInfo = NULL; + OldFileName = NewFileName = NULL; + AttrChangeFlag = NameChangeFlag = SizeChangeFlag = TimeChangeFlag = FALSE; + + // + // Set file system information. + // + if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) { + if (BufferSize < (SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel))) { + Status = EFI_BAD_BUFFER_SIZE; + goto Done; + } + + NewFileSystemInfo = (EFI_FILE_SYSTEM_INFO *) Buffer; + + free (PrivateRoot->VolumeLabel); + + PrivateRoot->VolumeLabel = malloc (StrSize (NewFileSystemInfo->VolumeLabel)); + if (PrivateRoot->VolumeLabel == NULL) { + goto Done; + } + + StrCpy (PrivateRoot->VolumeLabel, NewFileSystemInfo->VolumeLabel); + + Status = EFI_SUCCESS; + goto Done; + } + + // + // Set volume label information. + // + if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) { + if (BufferSize < StrSize (PrivateRoot->VolumeLabel)) { + Status = EFI_BAD_BUFFER_SIZE; + goto Done; + } + + StrCpy (PrivateRoot->VolumeLabel, (CHAR16 *) Buffer); + + Status = EFI_SUCCESS; + goto Done; + } + + if (!CompareGuid (InformationType, &gEfiFileInfoGuid)) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + if (BufferSize < SIZE_OF_EFI_FILE_INFO) { + Status = EFI_BAD_BUFFER_SIZE; + goto Done; + } + + // + // Set file/directory information. + // + + // + // Check for invalid set file information parameters. + // + NewFileInfo = (EFI_FILE_INFO *) Buffer; + if (NewFileInfo->Size <= sizeof (EFI_FILE_INFO) || + (NewFileInfo->Attribute &~(EFI_FILE_VALID_ATTR)) || + (sizeof (UINTN) == 4 && NewFileInfo->Size > 0xFFFFFFFF) + ) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + // + // Get current file information so we can determine what kind + // of change request this is. + // + OldInfoSize = 0; + Status = UnixSimpleFileSystemFileInfo (PrivateFile, NULL, &OldInfoSize, NULL); + if (Status != EFI_BUFFER_TOO_SMALL) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + + OldFileInfo = malloc (OldInfoSize); + if (OldFileInfo == NULL) { + goto Done; + } + + Status = UnixSimpleFileSystemFileInfo (PrivateFile, NULL, &OldInfoSize, OldFileInfo); + if (EFI_ERROR (Status)) { + goto Done; + } + + OldFileName = malloc (AsciiStrSize (PrivateFile->FileName)); + if (OldFileInfo == NULL) { + goto Done; + } + + AsciiStrCpy (OldFileName, PrivateFile->FileName); + + // + // Make full pathname from new filename and rootpath. + // + if (NewFileInfo->FileName[0] == '\\') { + NewFileName = malloc (AsciiStrLen (PrivateRoot->FilePath) + 1 + StrLen (NewFileInfo->FileName) + 1); + if (NewFileName == NULL) { + goto Done; + } + + AsciiStrCpy (NewFileName, PrivateRoot->FilePath); + AsciiFilePtr = NewFileName + AsciiStrLen(NewFileName); + UnicodeFilePtr = NewFileInfo->FileName + 1; + *AsciiFilePtr++ ='/'; + } else { + NewFileName = malloc (AsciiStrLen (PrivateFile->FileName) + 2 + StrLen (NewFileInfo->FileName) + 1); + if (NewFileName == NULL) { + goto Done; + } + + AsciiStrCpy (NewFileName, PrivateRoot->FilePath); + AsciiFilePtr = NewFileName + AsciiStrLen(NewFileName); + if ((AsciiFilePtr[-1] != '/') && (NewFileInfo->FileName[0] != '/')) { + // make sure there is a / between Root FilePath and NewFileInfo Filename + AsciiFilePtr[0] = '/'; + AsciiFilePtr[1] = '\0'; + AsciiFilePtr++; + } + UnicodeFilePtr = NewFileInfo->FileName; + } + // Convert to ascii. + while (*UnicodeFilePtr) { + *AsciiFilePtr++ = *UnicodeFilePtr++; + } + *AsciiFilePtr = 0; + + // + // Is there an attribute change request? + // + if (NewFileInfo->Attribute != OldFileInfo->Attribute) { + if ((NewFileInfo->Attribute & EFI_FILE_DIRECTORY) != (OldFileInfo->Attribute & EFI_FILE_DIRECTORY)) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + AttrChangeFlag = TRUE; + } + + // + // Is there a name change request? + // bugbug: - Should really use EFI_UNICODE_COLLATION_PROTOCOL + // + if (StrCmp (NewFileInfo->FileName, OldFileInfo->FileName)) { + NameChangeFlag = TRUE; + } + + // + // Is there a size change request? + // + if (NewFileInfo->FileSize != OldFileInfo->FileSize) { + SizeChangeFlag = TRUE; + } + + // + // Is there a time stamp change request? + // + if (!IsZero (&NewFileInfo->CreateTime, sizeof (EFI_TIME)) && + CompareMem (&NewFileInfo->CreateTime, &OldFileInfo->CreateTime, sizeof (EFI_TIME)) + ) { + TimeChangeFlag = TRUE; + } else if (!IsZero (&NewFileInfo->LastAccessTime, sizeof (EFI_TIME)) && + CompareMem (&NewFileInfo->LastAccessTime, &OldFileInfo->LastAccessTime, sizeof (EFI_TIME)) + ) { + TimeChangeFlag = TRUE; + } else if (!IsZero (&NewFileInfo->ModificationTime, sizeof (EFI_TIME)) && + CompareMem (&NewFileInfo->ModificationTime, &OldFileInfo->ModificationTime, sizeof (EFI_TIME)) + ) { + TimeChangeFlag = TRUE; + } + + // + // All done if there are no change requests being made. + // + if (!(AttrChangeFlag || NameChangeFlag || SizeChangeFlag || TimeChangeFlag)) { + Status = EFI_SUCCESS; + goto Done; + } + + // + // Set file or directory information. + // + if (stat (OldFileName, &OldAttr) != 0) { + Status = ErrnoToEfiStatus (); + goto Done; + } + + // + // Name change. + // + if (NameChangeFlag) { + // + // Close the handles first + // + if (PrivateFile->IsOpenedByRead) { + Status = EFI_ACCESS_DENIED; + goto Done; + } + + for (CharPointer = NewFileName; *CharPointer != 0 && *CharPointer != L'/'; CharPointer++) { + } + + if (*CharPointer != 0) { + Status = EFI_ACCESS_DENIED; + goto Done; + } + + UnixStatus = rename (OldFileName, NewFileName); + if (UnixStatus == 0) { + // + // modify file name + // + free (PrivateFile->FileName); + + PrivateFile->FileName = malloc (AsciiStrSize (NewFileName)); + if (PrivateFile->FileName == NULL) { + goto Done; + } + + AsciiStrCpy (PrivateFile->FileName, NewFileName); + } else { + Status = EFI_DEVICE_ERROR; + goto Done; + } + } + + // + // Size change + // + if (SizeChangeFlag) { + if (PrivateFile->IsDirectoryPath) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + if (PrivateFile->IsOpenedByRead || OldFileInfo->Attribute & EFI_FILE_READ_ONLY) { + Status = EFI_ACCESS_DENIED; + goto Done; + } + + if (ftruncate (PrivateFile->fd, NewFileInfo->FileSize) != 0) { + Status = ErrnoToEfiStatus (); + goto Done; + } + + } + + // + // Time change + // + if (TimeChangeFlag) { + NewLastAccessSystemTime.tm_year = NewFileInfo->LastAccessTime.Year; + NewLastAccessSystemTime.tm_mon = NewFileInfo->LastAccessTime.Month; + NewLastAccessSystemTime.tm_mday = NewFileInfo->LastAccessTime.Day; + NewLastAccessSystemTime.tm_hour = NewFileInfo->LastAccessTime.Hour; + NewLastAccessSystemTime.tm_min = NewFileInfo->LastAccessTime.Minute; + NewLastAccessSystemTime.tm_sec = NewFileInfo->LastAccessTime.Second; + NewLastAccessSystemTime.tm_isdst = 0; + + Utime.actime = mktime (&NewLastAccessSystemTime); + + NewLastWriteSystemTime.tm_year = NewFileInfo->ModificationTime.Year; + NewLastWriteSystemTime.tm_mon = NewFileInfo->ModificationTime.Month; + NewLastWriteSystemTime.tm_mday = NewFileInfo->ModificationTime.Day; + NewLastWriteSystemTime.tm_hour = NewFileInfo->ModificationTime.Hour; + NewLastWriteSystemTime.tm_min = NewFileInfo->ModificationTime.Minute; + NewLastWriteSystemTime.tm_sec = NewFileInfo->ModificationTime.Second; + NewLastWriteSystemTime.tm_isdst = 0; + + Utime.modtime = mktime (&NewLastWriteSystemTime); + + if (Utime.actime == (time_t)-1 || Utime.modtime == (time_t)-1) { + goto Done; + } + + if (utime (PrivateFile->FileName, &Utime) == -1) { + Status = ErrnoToEfiStatus (); + goto Done; + } + } + + // + // No matter about AttrChangeFlag, Attribute must be set. + // Because operation before may cause attribute change. + // + NewAttr = OldAttr.st_mode; + + if (NewFileInfo->Attribute & EFI_FILE_READ_ONLY) { + NewAttr &= ~(S_IRUSR | S_IRGRP | S_IROTH); + } else { + NewAttr |= S_IRUSR; + } + + if (chmod (NewFileName, NewAttr) != 0) { + Status = ErrnoToEfiStatus (); + } + +Done: + if (OldFileInfo != NULL) { + free (OldFileInfo); + } + + if (OldFileName != NULL) { + free (OldFileName); + } + + if (NewFileName != NULL) { + free (NewFileName); + } + + return Status; +} + + +/** + Flush data back for the file handle. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS Data was written. + @retval EFI_UNSUPPORTED Writes to Open directory are not supported. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The device is write protected. + @retval EFI_ACCESS_DENIED The file was open for read only. + @retval EFI_VOLUME_FULL The volume is full. + +**/ +EFI_STATUS +PosixFileFlush ( + IN EFI_FILE_PROTOCOL *This + ) +{ + EMU_EFI_FILE_PRIVATE *PrivateFile; + + + PrivateFile = EMU_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + + if (PrivateFile->IsDirectoryPath) { + return EFI_UNSUPPORTED; + } + + if (PrivateFile->IsOpenedByRead) { + return EFI_ACCESS_DENIED; + } + + if (PrivateFile->fd < 0) { + return EFI_DEVICE_ERROR; + } + + if (fsync (PrivateFile->fd) != 0) { + return ErrnoToEfiStatus (); + } + + return EFI_SUCCESS; +} + + + +EFI_STATUS +PosixFileSystmeThunkOpen ( + IN EMU_IO_THUNK_PROTOCOL *This + ) +{ + EMU_SIMPLE_FILE_SYSTEM_PRIVATE *Private; + UINTN i; + + if (This->Private != NULL) { + return EFI_ALREADY_STARTED; + } + + if (!CompareGuid (This->Protocol, &gEfiSimpleFileSystemProtocolGuid)) { + return EFI_UNSUPPORTED; + } + + Private = malloc (sizeof (EMU_SIMPLE_FILE_SYSTEM_PRIVATE)); + if (Private == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Private->FilePath = malloc (StrLen (This->ConfigString) + 1); + if (Private->FilePath == NULL) { + free (Private); + return EFI_OUT_OF_RESOURCES; + } + + // Convert Unicode to Ascii + for (i = 0; This->ConfigString[i] != 0; i++) { + Private->FilePath[i] = This->ConfigString[i]; + } + Private->FilePath[i] = 0; + + + Private->VolumeLabel = malloc (StrSize (L"EFI_EMULATED")); + if (Private->VolumeLabel == NULL) { + free (Private->FilePath); + free (Private); + return EFI_OUT_OF_RESOURCES; + } + StrCpy (Private->VolumeLabel, L"EFI_EMULATED"); + + Private->Signature = EMU_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE; + Private->Thunk = This; + CopyMem (&Private->SimpleFileSystem, &gPosixFileSystemProtocol, sizeof (Private->SimpleFileSystem)); + Private->FileHandlesOpen = FALSE; + + This->Interface = &Private->SimpleFileSystem; + This->Private = Private; + return EFI_SUCCESS; +} + + +EFI_STATUS +PosixFileSystmeThunkClose ( + IN EMU_IO_THUNK_PROTOCOL *This + ) +{ + EMU_SIMPLE_FILE_SYSTEM_PRIVATE *Private; + + if (!CompareGuid (This->Protocol, &gEfiSimpleFileSystemProtocolGuid)) { + return EFI_UNSUPPORTED; + } + + Private = This->Private; + + if (Private->FileHandlesOpen) { + // + // Close only supported if all the EFI_FILE_HANDLEs have been closed. + // + return EFI_NOT_READY; + } + + if (This->Private != NULL) { + if (Private->VolumeLabel != NULL) { + free (Private->VolumeLabel); + } + free (This->Private); + This->Private = NULL; + } + + return EFI_SUCCESS; +} + + +EMU_IO_THUNK_PROTOCOL gPosixFileSystemThunkIo = { + &gEfiSimpleFileSystemProtocolGuid, + NULL, + NULL, + 0, + GasketPosixFileSystmeThunkOpen, + GasketPosixFileSystmeThunkClose, + NULL +}; + + diff --git a/EmulatorPkg/Unix/Host/Pthreads.c b/EmulatorPkg/Unix/Host/Pthreads.c new file mode 100644 index 0000000000..b6b6ae8ef5 --- /dev/null +++ b/EmulatorPkg/Unix/Host/Pthreads.c @@ -0,0 +1,235 @@ +/*++ @file + POSIX Pthreads to emulate APs and implement threads + +Copyright (c) 2011, Apple Inc. All rights reserved. +Copyright (c) 2011, Intel Corporation. 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 "SecMain.h" +#include + + +UINTN +EFIAPI +PthreadMutexLock ( + IN VOID *Mutex + ) +{ + return (UINTN)pthread_mutex_lock ((pthread_mutex_t *)Mutex); +} + + + +UINTN +EFIAPI +PthreadMutexUnLock ( + IN VOID *Mutex + ) +{ + return (UINTN)pthread_mutex_unlock ((pthread_mutex_t *)Mutex); +} + + +UINTN +EFIAPI +PthreadMutexTryLock ( + IN VOID *Mutex + ) +{ + return (UINTN)pthread_mutex_trylock ((pthread_mutex_t *)Mutex); +} + + +VOID * +PthreadMutexInit ( + IN VOID + ) +{ + pthread_mutex_t *Mutex; + int err; + + Mutex = malloc (sizeof (pthread_mutex_t)); + err = pthread_mutex_init (Mutex, NULL); + if (err == 0) { + return Mutex; + } + + return NULL; +} + + +UINTN +PthreadMutexDestroy ( + IN VOID *Mutex + ) +{ + if (Mutex != NULL) { + return pthread_mutex_destroy ((pthread_mutex_t *)Mutex); + } + + return -1; +} + +// Can't store this data on PthreadCreate stack so we need a global +typedef struct { + pthread_mutex_t Mutex; + THREAD_THUNK_THREAD_ENTRY Start; +} THREAD_MANGLE; + +THREAD_MANGLE mThreadMangle = { + PTHREAD_MUTEX_INITIALIZER, + NULL +}; + +VOID * +SecFakePthreadStart ( + VOID *Context + ) +{ + THREAD_THUNK_THREAD_ENTRY Start; + sigset_t SigMask; + + // Save global on the stack before we unlock + Start = mThreadMangle.Start; + pthread_mutex_unlock (&mThreadMangle.Mutex); + + // Mask all signals to the APs + sigfillset (&SigMask); + pthread_sigmask (SIG_BLOCK, &SigMask, NULL); + + // + // We have to start the thread in SEC as we need to follow + // OS X calling conventions. We can then call back into + // to the callers Start. + // + // This is a great example of how all problems in computer + // science can be solved by adding another level of indirection + // + return (VOID *)ReverseGasketUint64 ((CALL_BACK)Start, (UINTN)Context); +} + +UINTN +PthreadCreate ( + IN VOID *Thread, + IN VOID *Attribute, + IN THREAD_THUNK_THREAD_ENTRY Start, + IN VOID *Context + ) +{ + int err; + BOOLEAN EnabledOnEntry; + + // + // Threads inherit interrupt state so disable interrupts before we start thread + // + if (SecInterruptEanbled ()) { + SecDisableInterrupt (); + EnabledOnEntry = TRUE; + } else { + EnabledOnEntry = FALSE; + } + + // Aquire lock for global, SecFakePthreadStart runs in a different thread. + pthread_mutex_lock (&mThreadMangle.Mutex); + mThreadMangle.Start = Start; + + err = pthread_create (Thread, Attribute, SecFakePthreadStart, Context); + if (err != 0) { + // Thread failed to launch so release the lock; + pthread_mutex_unlock (&mThreadMangle.Mutex); + } + + if (EnabledOnEntry) { + // Restore interrupt state + SecEnableInterrupt (); + } + + return err; +} + + +VOID +PthreadExit ( + IN VOID *ValuePtr + ) +{ + pthread_exit (ValuePtr); + return; +} + + +UINTN +PthreadSelf ( + VOID + ) +{ + // POSIX currently allows pthread_t to be a structure or arithmetic type. + // Check out sys/types.h to make sure this will work if you are porting. + // On OS X (Darwin) pthread_t is a pointer to a structure so this code works. + return (UINTN)pthread_self (); +} + + +EMU_THREAD_THUNK_PROTOCOL gPthreadThunk = { + GasketPthreadMutexLock, + GasketPthreadMutexUnLock, + GasketPthreadMutexTryLock, + GasketPthreadMutexInit, + GasketPthreadMutexDestroy, + GasketPthreadCreate, + GasketPthreadExit, + GasketPthreadSelf +}; + + +EFI_STATUS +PthreadOpen ( + IN EMU_IO_THUNK_PROTOCOL *This + ) +{ + if (This->Instance != 0) { + // Only single instance is supported + return EFI_NOT_FOUND; + } + + if (This->ConfigString[0] == L'0') { + // If AP count is zero no need for threads + return EFI_NOT_FOUND; + } + + This->Interface = &gPthreadThunk; + + return EFI_SUCCESS; +} + + +EFI_STATUS +PthreadClose ( + IN EMU_IO_THUNK_PROTOCOL *This + ) +{ + return EFI_SUCCESS; +} + + +EMU_IO_THUNK_PROTOCOL gPthreadThunkIo = { + &gEmuThreadThunkProtocolGuid, + NULL, + NULL, + 0, + GasketPthreadOpen, + GasketPthreadClose, + NULL +}; + + diff --git a/EmulatorPkg/Unix/Host/SecMain.c b/EmulatorPkg/Unix/Host/SecMain.c new file mode 100644 index 0000000000..2806347941 --- /dev/null +++ b/EmulatorPkg/Unix/Host/SecMain.c @@ -0,0 +1,1226 @@ +/*++ @file + +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+Portions copyright (c) 2008 - 2011, 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. + +**/ + +#include "SecMain.h" + +#ifdef __APPLE__ +#define MAP_ANONYMOUS MAP_ANON +#endif + + +// +// Globals +// + +EMU_THUNK_PPI mSecEmuThunkPpi = { + GasketSecUnixPeiAutoScan, + GasketSecUnixFdAddress, + GasketSecEmuThunkAddress +}; + +char *gGdbWorkingFileName = NULL; +unsigned int mScriptSymbolChangesCount = 0; + + +// +// Default information about where the FD is located. +// This array gets filled in with information from EFI_FIRMWARE_VOLUMES +// EFI_FIRMWARE_VOLUMES is a host environment variable set by system.cmd. +// The number of array elements is allocated base on parsing +// EFI_FIRMWARE_VOLUMES and the memory is never freed. +// +UINTN gFdInfoCount = 0; +EMU_FD_INFO *gFdInfo; + +// +// Array that supports seperate memory rantes. +// The memory ranges are set in system.cmd via the EFI_MEMORY_SIZE variable. +// The number of array elements is allocated base on parsing +// EFI_MEMORY_SIZE and the memory is never freed. +// +UINTN gSystemMemoryCount = 0; +EMU_SYSTEM_MEMORY *gSystemMemory; + + + +UINTN mImageContextModHandleArraySize = 0; +IMAGE_CONTEXT_TO_MOD_HANDLE *mImageContextModHandleArray = NULL; + +EFI_PEI_PPI_DESCRIPTOR *gPpiList; + + +int gInXcode = 0; + + +/*++ + Breakpoint target for Xcode project. Set in the Xcode XML + + Xcode breakpoint will 'source SecMain.gdb' + gGdbWorkingFileName is set to SecMain.gdb + +**/ +VOID +SecGdbConfigBreak ( + VOID + ) +{ +} + + + +/*++ + +Routine Description: + Main entry point to SEC for Unix. This is a unix program + +Arguments: + Argc - Number of command line arguments + Argv - Array of command line argument strings + Envp - Array of environmemt variable strings + +Returns: + 0 - Normal exit + 1 - Abnormal exit + +**/ +int +main ( + IN int Argc, + IN char **Argv, + IN char **Envp + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS InitialStackMemory; + UINT64 InitialStackMemorySize; + UINTN Index; + UINTN Index1; + UINTN Index2; + UINTN PeiIndex; + CHAR8 *FileName; + BOOLEAN Done; + EFI_PEI_FILE_HANDLE FileHandle; + VOID *SecFile; + CHAR16 *MemorySizeStr; + CHAR16 *FirmwareVolumesStr; + UINTN *StackPointer; + FILE *GdbTempFile; + + // + // Xcode does not support sourcing gdb scripts directly, so the Xcode XML + // has a break point script to source the GdbRun script. + // + SecGdbConfigBreak (); + + // + // If dlopen doesn't work, then we build a gdb script to allow the + // symbols to be loaded. + // + Index = strlen (*Argv); + gGdbWorkingFileName = AllocatePool (Index + strlen(".gdb") + 1); + strcpy (gGdbWorkingFileName, *Argv); + strcat (gGdbWorkingFileName, ".gdb"); + + // + // Empty out the gdb symbols script file. + // + GdbTempFile = fopen (gGdbWorkingFileName, "w"); + if (GdbTempFile != NULL) { + fclose (GdbTempFile); + } + + printf ("\nEDK II UNIX Host Emulation Environment from edk2.sourceforge.net\n"); + + setbuf (stdout, 0); + setbuf (stderr, 0); + + MemorySizeStr = (CHAR16 *) PcdGetPtr (PcdEmuMemorySize); + FirmwareVolumesStr = (CHAR16 *) PcdGetPtr (PcdEmuFirmwareVolume); + + // + // PPIs pased into PEI_CORE + // + AddThunkPpi (EFI_PEI_PPI_DESCRIPTOR_PPI, &gEmuThunkPpiGuid, &mSecEmuThunkPpi); + + SecInitThunkProtocol (); + + // + // Emulator Bus Driver Thunks + // + AddThunkProtocol (&gX11ThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuGop), TRUE); + AddThunkProtocol (&gPosixFileSystemThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuFileSystem), TRUE); + AddThunkProtocol (&gBlockIoThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuVirtualDisk), TRUE); + AddThunkProtocol (&gSnpThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuNetworkInterface), TRUE); + + // + // Emulator other Thunks + // + AddThunkProtocol (&gPthreadThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuApCount), FALSE); + + // EmuSecLibConstructor (); + + gPpiList = GetThunkPpiList (); + + // + // Allocate space for gSystemMemory Array + // + gSystemMemoryCount = CountSeperatorsInString (MemorySizeStr, '!') + 1; + gSystemMemory = AllocateZeroPool (gSystemMemoryCount * sizeof (EMU_SYSTEM_MEMORY)); + if (gSystemMemory == NULL) { + printf ("ERROR : Can not allocate memory for system. Exiting.\n"); + exit (1); + } + // + // Allocate space for gSystemMemory Array + // + gFdInfoCount = CountSeperatorsInString (FirmwareVolumesStr, '!') + 1; + gFdInfo = AllocateZeroPool (gFdInfoCount * sizeof (EMU_FD_INFO)); + if (gFdInfo == NULL) { + printf ("ERROR : Can not allocate memory for fd info. Exiting.\n"); + exit (1); + } + + printf (" BootMode 0x%02x\n", (unsigned int)PcdGet32 (PcdEmuBootMode)); + + // + // Open up a 128K file to emulate temp memory for SEC. + // on a real platform this would be SRAM, or using the cache as RAM. + // Set InitialStackMemory to zero so UnixOpenFile will allocate a new mapping + // + InitialStackMemorySize = STACK_SIZE; + InitialStackMemory = (UINTN)MapMemory ( + 0, (UINT32) InitialStackMemorySize, + PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE + ); + if (InitialStackMemory == 0) { + printf ("ERROR : Can not open SecStack Exiting\n"); + exit (1); + } + + printf (" OS Emulator passing in %u KB of temp RAM at 0x%08lx to SEC\n", + (unsigned int)(InitialStackMemorySize / 1024), + (unsigned long)InitialStackMemory + ); + + for (StackPointer = (UINTN*) (UINTN) InitialStackMemory; + StackPointer < (UINTN*)(UINTN)((UINTN) InitialStackMemory + (UINT64) InitialStackMemorySize); + StackPointer ++) { + *StackPointer = 0x5AA55AA5; + } + + // + // Open All the firmware volumes and remember the info in the gFdInfo global + // + FileName = (CHAR8 *) AllocatePool (StrLen (FirmwareVolumesStr) + 1); + if (FileName == NULL) { + printf ("ERROR : Can not allocate memory for firmware volume string\n"); + exit (1); + } + + Index2 = 0; + for (Done = FALSE, Index = 0, PeiIndex = 0, SecFile = NULL; + FirmwareVolumesStr[Index2] != 0; + Index++) { + for (Index1 = 0; (FirmwareVolumesStr[Index2] != '!') && (FirmwareVolumesStr[Index2] != 0); Index2++) { + FileName[Index1++] = FirmwareVolumesStr[Index2]; + } + if (FirmwareVolumesStr[Index2] == '!') { + Index2++; + } + FileName[Index1] = '\0'; + + if (Index == 0) { + // Map FV Recovery Read Only and other areas Read/Write + Status = MapFd0 ( + FileName, + &gFdInfo[0].Address, + &gFdInfo[0].Size + ); + } else { + // + // Open the FD and remmeber where it got mapped into our processes address space + // Maps Read Only + // + Status = MapFile ( + FileName, + &gFdInfo[Index].Address, + &gFdInfo[Index].Size + ); + } + if (EFI_ERROR (Status)) { + printf ("ERROR : Can not open Firmware Device File %s (%x). Exiting.\n", FileName, (unsigned int)Status); + exit (1); + } + + printf (" FD loaded from %s at 0x%08lx",FileName, (unsigned long)gFdInfo[Index].Address); + + if (SecFile == NULL) { + // + // Assume the beginning of the FD is an FV and look for the SEC Core. + // Load the first one we find. + // + FileHandle = NULL; + Status = PeiServicesFfsFindNextFile ( + EFI_FV_FILETYPE_SECURITY_CORE, + (EFI_PEI_FV_HANDLE)(UINTN)gFdInfo[Index].Address, + &FileHandle + ); + if (!EFI_ERROR (Status)) { + Status = PeiServicesFfsFindSectionData (EFI_SECTION_PE32, FileHandle, &SecFile); + if (!EFI_ERROR (Status)) { + PeiIndex = Index; + printf (" contains SEC Core"); + } + } + } + + printf ("\n"); + } + // + // Calculate memory regions and store the information in the gSystemMemory + // global for later use. The autosizing code will use this data to + // map this memory into the SEC process memory space. + // + Index1 = 0; + Index = 0; + while (1) { + UINTN val = 0; + // + // Save the size of the memory. + // + while (MemorySizeStr[Index1] >= '0' && MemorySizeStr[Index1] <= '9') { + val = val * 10 + MemorySizeStr[Index1] - '0'; + Index1++; + } + gSystemMemory[Index++].Size = val * 0x100000; + if (MemorySizeStr[Index1] == 0) { + break; + } + Index1++; + } + + printf ("\n"); + + // + // Hand off to SEC + // + SecLoadFromCore ((UINTN) InitialStackMemory, (UINTN) InitialStackMemorySize, (UINTN) gFdInfo[0].Address, SecFile); + + // + // If we get here, then the SEC Core returned. This is an error as SEC should + // always hand off to PEI Core and then on to DXE Core. + // + printf ("ERROR : SEC returned\n"); + exit (1); +} + + +EFI_PHYSICAL_ADDRESS * +MapMemory ( + IN INTN fd, + IN UINT64 length, + IN INTN prot, + IN INTN flags + ) +{ + STATIC UINTN base = 0x40000000; + CONST UINTN align = (1 << 24); + VOID *res = NULL; + BOOLEAN isAligned = 0; + + // + // Try to get an aligned block somewhere in the address space of this + // process. + // + while((!isAligned) && (base != 0)) { + res = mmap ((void *)base, length, prot, flags, fd, 0); + if (res == MAP_FAILED) { + return NULL; + } + if ((((UINTN)res) & ~(align-1)) == (UINTN)res) { + isAligned=1; + } else { + munmap(res, length); + base += align; + } + } + return res; +} + + +/*++ + +Routine Description: + 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: + FileName - The name of the file to open and map + MapSize - The amount of the file to map in bytes + CreationDisposition - The flags to pass to CreateFile(). Use to create new files for + memory emulation, and exiting files for firmware volume emulation + BaseAddress - The base address of the mapped file in the user address space. + If passed in as NULL the a new memory region is used. + If passed in as non NULL the request memory region is used for + the mapping of the file into the process space. + Length - The size of the mapped region in bytes + +Returns: + EFI_SUCCESS - The file was opened and mapped. + EFI_NOT_FOUND - FileName was not found in the current directory + EFI_DEVICE_ERROR - An error occured attempting to map the opened file + +**/ +EFI_STATUS +MapFile ( + IN CHAR8 *FileName, + IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress, + OUT UINT64 *Length + ) +{ + int fd; + VOID *res; + UINTN FileSize; + + fd = open (FileName, O_RDWR); + if (fd < 0) { + return EFI_NOT_FOUND; + } + FileSize = lseek (fd, 0, SEEK_END); + + + res = MapMemory (fd, FileSize, PROT_READ | PROT_EXEC, MAP_PRIVATE); + + close (fd); + + if (res == NULL) { + perror ("MapFile() Failed"); + return EFI_DEVICE_ERROR; + } + + *Length = (UINT64) FileSize; + *BaseAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) res; + + return EFI_SUCCESS; +} + +EFI_STATUS +MapFd0 ( + IN CHAR8 *FileName, + IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress, + OUT UINT64 *Length + ) +{ + int fd; + void *res, *res2, *res3; + UINTN FileSize; + UINTN FvSize; + void *EmuMagicPage; + + fd = open (FileName, O_RDWR); + if (fd < 0) { + return EFI_NOT_FOUND; + } + FileSize = lseek (fd, 0, SEEK_END); + + FvSize = FixedPcdGet64 (PcdEmuFlashFvRecoverySize); + + // Assume start of FD is Recovery FV, and make it write protected + res = mmap ( + (void *)(UINTN)FixedPcdGet64 (PcdEmuFlashFvRecoveryBase), + FvSize, + PROT_READ | PROT_EXEC, + MAP_PRIVATE, + fd, + 0 + ); + if (res == MAP_FAILED) { + perror ("MapFd0() Failed res ="); + close (fd); + return EFI_DEVICE_ERROR; + } else if (res != (void *)(UINTN)FixedPcdGet64 (PcdEmuFlashFvRecoveryBase)) { + // We could not load at the build address, so we need to allow writes + munmap (res, FvSize); + res = mmap ( + (void *)(UINTN)FixedPcdGet64 (PcdEmuFlashFvRecoveryBase), + FvSize, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE, + fd, + 0 + ); + if (res == MAP_FAILED) { + perror ("MapFd0() Failed res ="); + close (fd); + return EFI_DEVICE_ERROR; + } + } + + // Map the rest of the FD as read/write + res2 = mmap ( + (void *)(UINTN)(FixedPcdGet64 (PcdEmuFlashFvRecoveryBase) + FvSize), + FileSize - FvSize, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_SHARED, + fd, + FvSize + ); + close (fd); + if (res2 == MAP_FAILED) { + perror ("MapFd0() Failed res2 ="); + return EFI_DEVICE_ERROR; + } + + // + // If enabled use the magic page to communicate between modules + // This replaces the PI PeiServicesTable pointer mechanism that + // deos not work in the emulator. It also allows the removal of + // writable globals from SEC, PEI_CORE (libraries), PEIMs + // + EmuMagicPage = (void *)(UINTN)FixedPcdGet64 (PcdPeiServicesTablePage); + if (EmuMagicPage != NULL) { + res3 = mmap ( + (void *)EmuMagicPage, + 4096, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, + 0, + 0 + ); + if (res3 != EmuMagicPage) { + printf ("MapFd0(): Could not allocate PeiServicesTablePage @ %lx\n", (long unsigned int)EmuMagicPage); + return EFI_DEVICE_ERROR; + } + } + + *Length = (UINT64) FileSize; + *BaseAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) res; + + return EFI_SUCCESS; +} + + +/*++ + +Routine Description: + This is the service to load the SEC Core from the Firmware Volume + +Arguments: + LargestRegion - Memory to use for SEC. + LargestRegionSize - Size of Memory to use for PEI + BootFirmwareVolumeBase - Start of the Boot FV + PeiCorePe32File - SEC PE32 + +Returns: + Success means control is transfered and thus we should never return + +**/ +VOID +SecLoadFromCore ( + IN UINTN LargestRegion, + IN UINTN LargestRegionSize, + IN UINTN BootFirmwareVolumeBase, + IN VOID *PeiCorePe32File + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS TopOfMemory; + VOID *TopOfStack; + EFI_PHYSICAL_ADDRESS PeiCoreEntryPoint; + EFI_SEC_PEI_HAND_OFF *SecCoreData; + UINTN PeiStackSize; + + // + // Compute Top Of Memory for Stack and PEI Core Allocations + // + TopOfMemory = LargestRegion + LargestRegionSize; + PeiStackSize = (UINTN)RShiftU64((UINT64)STACK_SIZE,1); + + // + // |-----------| <---- TemporaryRamBase + TemporaryRamSize + // | Heap | + // | | + // |-----------| <---- StackBase / PeiTemporaryMemoryBase + // | | + // | Stack | + // |-----------| <---- TemporaryRamBase + // + TopOfStack = (VOID *)(LargestRegion + PeiStackSize); + TopOfMemory = LargestRegion + PeiStackSize; + + // + // Reservet space for storing PeiCore's parament in stack. + // + TopOfStack = (VOID *)((UINTN)TopOfStack - sizeof (EFI_SEC_PEI_HAND_OFF) - CPU_STACK_ALIGNMENT); + TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT); + + + // + // Bind this information into the SEC hand-off state + // + SecCoreData = (EFI_SEC_PEI_HAND_OFF*)(UINTN) TopOfStack; + SecCoreData->DataSize = sizeof(EFI_SEC_PEI_HAND_OFF); + SecCoreData->BootFirmwareVolumeBase = (VOID*)BootFirmwareVolumeBase; + SecCoreData->BootFirmwareVolumeSize = PcdGet32 (PcdEmuFirmwareFdSize); + SecCoreData->TemporaryRamBase = (VOID*)(UINTN)LargestRegion; + SecCoreData->TemporaryRamSize = STACK_SIZE; + SecCoreData->StackBase = SecCoreData->TemporaryRamBase; + SecCoreData->StackSize = PeiStackSize; + SecCoreData->PeiTemporaryRamBase = (VOID*) ((UINTN) SecCoreData->TemporaryRamBase + PeiStackSize); + SecCoreData->PeiTemporaryRamSize = STACK_SIZE - PeiStackSize; + + // + // Find the SEC Core Entry Point + // + Status = SecPeCoffGetEntryPoint (PeiCorePe32File, (VOID **)&PeiCoreEntryPoint); + if (EFI_ERROR (Status)) { + return ; + } + + // + // Transfer control to the SEC Core + // + PeiSwitchStacks ( + (SWITCH_STACK_ENTRY_POINT) (UINTN) PeiCoreEntryPoint, + SecCoreData, + (VOID *)gPpiList, + TopOfStack + ); + // + // If we get here, then the SEC Core returned. This is an error + // + return ; +} + + +/*++ + +Routine Description: + This service is called from Index == 0 until it returns EFI_UNSUPPORTED. + It allows discontiguous memory regions to be supported by the emulator. + 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 + UnixOpenFile. + +Arguments: + Index - Which memory region to use + MemoryBase - Return Base address of memory region + MemorySize - Return size in bytes of the memory region + +Returns: + EFI_SUCCESS - If memory region was mapped + EFI_UNSUPPORTED - If Index is not supported + +**/ +EFI_STATUS +SecUnixPeiAutoScan ( + IN UINTN Index, + OUT EFI_PHYSICAL_ADDRESS *MemoryBase, + OUT UINT64 *MemorySize + ) +{ + void *res; + + if (Index >= gSystemMemoryCount) { + return EFI_UNSUPPORTED; + } + + *MemoryBase = 0; + res = MapMemory ( + 0, gSystemMemory[Index].Size, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS + ); + if (res == MAP_FAILED) { + return EFI_DEVICE_ERROR; + } + *MemorySize = gSystemMemory[Index].Size; + *MemoryBase = (UINTN)res; + gSystemMemory[Index].Memory = *MemoryBase; + + return EFI_SUCCESS; +} + + +/*++ + +Routine Description: + Check to see if an address range is in the EFI GCD memory map. + + This is all of GCD for system memory passed to DXE Core. FV + mapping and other device mapped into system memory are not + inlcuded in the check. + +Arguments: + Index - Which memory region to use + MemoryBase - Return Base address of memory region + MemorySize - Return size in bytes of the memory region + +Returns: + TRUE - Address is in the EFI GCD memory map + FALSE - Address is NOT in memory map + +**/ +BOOLEAN +EfiSystemMemoryRange ( + IN VOID *MemoryAddress + ) +{ + UINTN Index; + EFI_PHYSICAL_ADDRESS MemoryBase; + + MemoryBase = (EFI_PHYSICAL_ADDRESS)(UINTN)MemoryAddress; + for (Index = 0; Index < gSystemMemoryCount; Index++) { + if ((MemoryBase >= gSystemMemory[Index].Memory) && + (MemoryBase < (gSystemMemory[Index].Memory + gSystemMemory[Index].Size)) ) { + return TRUE; + } + } + + return FALSE; +} + + +/*++ + +Routine Description: + Since the SEC is the only Unix program in stack it must export + an interface to do POSIX calls. gUnix is initailized in UnixThunk.c. + +Arguments: + InterfaceSize - sizeof (EFI_WIN_NT_THUNK_PROTOCOL); + InterfaceBase - Address of the gUnix global + +Returns: + EFI_SUCCESS - Data returned + +**/ +VOID * +SecEmuThunkAddress ( + VOID + ) +{ + return &gEmuThunkProtocol; +} + + + +RETURN_STATUS +EFIAPI +SecPeCoffGetEntryPoint ( + IN VOID *Pe32Data, + IN OUT VOID **EntryPoint + ) +{ + EFI_STATUS Status; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + + ZeroMem (&ImageContext, sizeof (ImageContext)); + ImageContext.Handle = Pe32Data; + ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) SecImageRead; + + Status = PeCoffLoaderGetImageInfo (&ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + + if (ImageContext.ImageAddress != (UINTN)Pe32Data) { + // + // Relocate image to match the address where it resides + // + ImageContext.ImageAddress = (UINTN)Pe32Data; + Status = PeCoffLoaderLoadImage (&ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = PeCoffLoaderRelocateImage (&ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + } else { + // + // Or just return image entry point + // + ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer (Pe32Data); + Status = PeCoffLoaderGetEntryPoint (Pe32Data, EntryPoint); + if (EFI_ERROR (Status)) { + return Status; + } + ImageContext.EntryPoint = (UINTN)*EntryPoint; + } + + // On Unix a dlopen is done that will change the entry point + SecPeCoffRelocateImageExtraAction (&ImageContext); + *EntryPoint = (VOID *)(UINTN)ImageContext.EntryPoint; + + return Status; +} + + + +/*++ + +Routine Description: + Return the FD Size and base address. Since the FD is loaded from a + file into host memory only the SEC will know it's address. + +Arguments: + Index - Which FD, starts at zero. + FdSize - Size of the FD in bytes + FdBase - Start address of the FD. Assume it points to an FV Header + FixUp - Difference between actual FD address and build address + +Returns: + EFI_SUCCESS - Return the Base address and size of the FV + EFI_UNSUPPORTED - Index does nto map to an FD in the system + +**/ +EFI_STATUS +SecUnixFdAddress ( + IN UINTN Index, + IN OUT EFI_PHYSICAL_ADDRESS *FdBase, + IN OUT UINT64 *FdSize, + IN OUT EFI_PHYSICAL_ADDRESS *FixUp + ) +{ + if (Index >= gFdInfoCount) { + return EFI_UNSUPPORTED; + } + + *FdBase = gFdInfo[Index].Address; + *FdSize = gFdInfo[Index].Size; + *FixUp = 0; + + if (*FdBase == 0 && *FdSize == 0) { + return EFI_UNSUPPORTED; + } + + if (Index == 0) { + // + // FD 0 has XIP code and well known PCD values + // If the memory buffer could not be allocated at the FD build address + // the Fixup is the difference. + // + *FixUp = *FdBase - PcdGet64 (PcdEmuFdBaseAddress); + } + + return EFI_SUCCESS; +} + + +/*++ + +Routine Description: + Count the number of seperators in String + +Arguments: + String - String to process + Seperator - Item to count + +Returns: + Number of Seperator in String + +**/ +UINTN +CountSeperatorsInString ( + IN const CHAR16 *String, + IN CHAR16 Seperator + ) +{ + UINTN Count; + + for (Count = 0; *String != '\0'; String++) { + if (*String == Seperator) { + Count++; + } + } + + return Count; +} + + +EFI_STATUS +EFIAPI +SecImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file + +Arguments: + FileHandle - The handle to the PE/COFF file + FileOffset - The offset, in bytes, into the file to read + ReadSize - The number of bytes to read from the file starting at FileOffset + Buffer - A pointer to the buffer to read the data into. + +Returns: + EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset + +**/ +{ + CHAR8 *Destination8; + CHAR8 *Source8; + UINTN Length; + + Destination8 = Buffer; + Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset); + Length = *ReadSize; + while (Length--) { + *(Destination8++) = *(Source8++); + } + + return EFI_SUCCESS; +} + + +/*++ + +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. + +**/ +EFI_STATUS +AddHandle ( + IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN VOID *ModHandle + ) +{ + 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 = ReallocatePool ( + (mImageContextModHandleArraySize - 1) * sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE), + mImageContextModHandleArraySize * sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE), + mImageContextModHandleArray + ); + 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); +} + + +/*++ + +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 + +**/ +VOID * +RemoveHandle ( + IN PE_COFF_LOADER_IMAGE_CONTEXT *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; +} + + + +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 + ) +{ + if (ImageContext->PdbPointer == NULL) { + fprintf (stderr, + "0x%08lx Loading NO DEBUG with entry point 0x%08lx\n", + (unsigned long)(ImageContext->ImageAddress), + (unsigned long)ImageContext->EntryPoint + ); + } else { + 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); +} + + +/** + Loads the image using dlopen so symbols will be automatically + loaded by gdb. + + @param ImageContext The PE/COFF image context + + @retval TRUE - The image was successfully loaded + @retval FALSE - The image was successfully loaded + +**/ +BOOLEAN +DlLoadImage ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + +#ifdef __APPLE__ + + return FALSE; + +#else + + void *Handle = NULL; + void *Entry = NULL; + + if (ImageContext->PdbPointer == NULL) { + return FALSE; + } + + if (!IsPdbFile (ImageContext->PdbPointer)) { + return FALSE; + } + + fprintf ( + stderr, + "Loading %s 0x%08lx - entry point 0x%08lx\n", + ImageContext->PdbPointer, + (unsigned long)ImageContext->ImageAddress, + (unsigned long)ImageContext->EntryPoint + ); + + Handle = dlopen (ImageContext->PdbPointer, RTLD_NOW); + if (Handle != NULL) { + Entry = dlsym (Handle, "_ModuleEntryPoint"); + AddHandle (ImageContext, Handle); + } else { + printf("%s\n", dlerror()); + } + + if (Entry != NULL) { + ImageContext->EntryPoint = (UINTN)Entry; + printf ("Change %s Entrypoint to :0x%08lx\n", ImageContext->PdbPointer, (unsigned long)Entry); + return TRUE; + } else { + return FALSE; + } + +#endif +} + + +/** + Adds the image to a gdb script so it's symbols can be loaded. + The AddFirmwareSymbolFile helper macro is used. + + @param ImageContext The PE/COFF image context + +**/ +VOID +GdbScriptAddImage ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + + PrintLoadAddress (ImageContext); + + if (ImageContext->PdbPointer != NULL && !IsPdbFile (ImageContext->PdbPointer)) { + FILE *GdbTempFile; + GdbTempFile = fopen (gGdbWorkingFileName, "a"); + if (GdbTempFile != NULL) { + long unsigned int SymbolsAddr = (long unsigned int)(ImageContext->ImageAddress + ImageContext->SizeOfHeaders); + mScriptSymbolChangesCount++; + fprintf ( + GdbTempFile, + "AddFirmwareSymbolFile 0x%x %s 0x%08lx\n", + mScriptSymbolChangesCount, + ImageContext->PdbPointer, + SymbolsAddr + ); + fclose (GdbTempFile); + } else { + ASSERT (FALSE); + } + } +} + + +VOID +EFIAPI +SecPeCoffRelocateImageExtraAction ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + if (!DlLoadImage (ImageContext)) { + GdbScriptAddImage (ImageContext); + } +} + + +/** + Adds the image to a gdb script so it's symbols can be unloaded. + The RemoveFirmwareSymbolFile helper macro is used. + + @param ImageContext The PE/COFF image context + +**/ +VOID +GdbScriptRemoveImage ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + FILE *GdbTempFile; + + // + // Need to skip .PDB files created from VC++ + // + if (IsPdbFile (ImageContext->PdbPointer)) { + return; + } + + // + // Write the file we need for the gdb script + // + GdbTempFile = fopen (gGdbWorkingFileName, "a"); + if (GdbTempFile != NULL) { + mScriptSymbolChangesCount++; + fprintf ( + GdbTempFile, + "RemoveFirmwareSymbolFile 0x%x %s\n", + mScriptSymbolChangesCount, + ImageContext->PdbPointer + ); + fclose (GdbTempFile); + } else { + ASSERT (FALSE); + } +} + + +VOID +EFIAPI +SecPeCoffUnloadImageExtraAction ( + IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + VOID *Handle; + + // + // Check to see if the image symbols were loaded with gdb script, or dlopen + // + Handle = RemoveHandle (ImageContext); + if (Handle != NULL) { +#ifndef __APPLE__ + dlclose (Handle); +#endif + return; + } + + GdbScriptRemoveImage (ImageContext); +} + + diff --git a/EmulatorPkg/Unix/Host/SecMain.h b/EmulatorPkg/Unix/Host/SecMain.h new file mode 100644 index 0000000000..5cd717818e --- /dev/null +++ b/EmulatorPkg/Unix/Host/SecMain.h @@ -0,0 +1,356 @@ +/*++ @file + +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+Portions copyright (c) 2008 - 2011, 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. + +**/ + +#ifndef _SEC_MAIN_H__ +#define _SEC_MAIN_H__ + +// +// Name mangle to prevent build errors. I.e conflicts between EFI and OS +// +#define NTOHL _UNIX_EFI_NAME_MANGLE_NTOHL_ +#define HTONL _UNIX_EFI_NAME_MANGLE_HTONL_ +#define NTOHS _UNIX_EFI_NAME_MANGLE_NTOHS_ +#define HTONS _UNIX_EFI_NAME_MANGLE_HTOHS_ +#define B0 _UNIX_EFI_NAME_MANGLE_B0_ + +#include +#include + +#include +#include +#include +#include + +#if __CYGWIN__ +#include +#else +#include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef __APPLE__ +#include +#include +#include +#include +#include +#define _XOPEN_SOURCE +#ifndef _Bool + #define _Bool char // for clang debug +#endif +#else +#include +#include +#include +#endif + +#include + +#undef NTOHL +#undef HTONL +#undef NTOHS +#undef HTONS +#undef B0 + + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +#include "Gasket.h" + + +#define STACK_SIZE 0x20000 + +typedef struct { + EFI_PHYSICAL_ADDRESS Address; + UINT64 Size; +} EMU_FD_INFO; + +typedef struct { + EFI_PHYSICAL_ADDRESS Memory; + UINT64 Size; +} EMU_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 +SecUnixPeiLoadFile ( + VOID *Pe32Data, + EFI_PHYSICAL_ADDRESS *ImageAddress, + UINT64 *ImageSize, + EFI_PHYSICAL_ADDRESS *EntryPoint + ); + +int +main ( + IN int Argc, + IN char **Argv, + IN char **Envp + ); + +VOID +SecLoadFromCore ( + IN UINTN LargestRegion, + IN UINTN LargestRegionSize, + IN UINTN BootFirmwareVolumeBase, + IN VOID *PeiCoreFile + ); + +EFI_STATUS +SecLoadFile ( + IN VOID *Pe32Data, + IN EFI_PHYSICAL_ADDRESS *ImageAddress, + IN UINT64 *ImageSize, + IN EFI_PHYSICAL_ADDRESS *EntryPoint + ); + +EFI_STATUS +SecFfsFindPeiCore ( + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader, + OUT VOID **Pe32Data + ); + +EFI_STATUS +SecFfsFindNextFile ( + IN EFI_FV_FILETYPE SearchType, + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader, + IN OUT EFI_FFS_FILE_HEADER **FileHeader + ); + +EFI_STATUS +SecFfsFindSectionData ( + IN EFI_SECTION_TYPE SectionType, + IN EFI_FFS_FILE_HEADER *FfsFileHeader, + IN OUT VOID **SectionData + ); + +EFI_STATUS +EFIAPI +SecUnixPeCoffLoaderLoadAsDll ( + IN CHAR8 *PdbFileName, + IN VOID **ImageEntryPoint, + OUT VOID **ModHandle + ); + +EFI_STATUS +EFIAPI +SecUnixPeCoffLoaderFreeLibrary ( + OUT VOID *ModHandle + ); + +EFI_STATUS +SecUnixFdAddress ( + IN UINTN Index, + IN OUT EFI_PHYSICAL_ADDRESS *FdBase, + IN OUT UINT64 *FdSize, + IN OUT EFI_PHYSICAL_ADDRESS *FixUp + ) +; + +EFI_STATUS +EFIAPI +GasketSecUnixFdAddress ( + IN UINTN Index, + IN OUT EFI_PHYSICAL_ADDRESS *FdBase, + IN OUT UINT64 *FdSize, + IN OUT EFI_PHYSICAL_ADDRESS *FixUp + ) +; + + +EFI_STATUS +GetImageReadFunction ( + IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN EFI_PHYSICAL_ADDRESS *TopOfMemory + ); + +EFI_STATUS +EFIAPI +SecImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ); + +CHAR16 * +AsciiToUnicode ( + IN CHAR8 *Ascii, + IN UINTN *StrLen OPTIONAL + ); + +UINTN +CountSeperatorsInString ( + IN const CHAR16 *String, + IN CHAR16 Seperator + ); + +EFI_STATUS +EFIAPI +SecTemporaryRamSupport ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase, + IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase, + IN UINTN CopySize + ); + +EFI_STATUS +EFIAPI +GasketSecTemporaryRamSupport ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase, + IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase, + 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 + ); + + +VOID +PeiSwitchStacks ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ); + +VOID +SecInitThunkProtocol ( + VOID + ); + + +EFI_PHYSICAL_ADDRESS * +MapMemory ( + INTN fd, + UINT64 length, + INTN prot, + INTN flags); + +EFI_STATUS +MapFile ( + IN CHAR8 *FileName, + IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress, + OUT UINT64 *Length + ); + +EFI_STATUS +MapFd0 ( + IN CHAR8 *FileName, + IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress, + OUT UINT64 *Length + ); + +BOOLEAN +EfiSystemMemoryRange ( + IN VOID *MemoryAddress + ); + + +VOID SecSleep (UINT64 Nanoseconds); +VOID SecEnableInterrupt (VOID); +VOID SecDisableInterrupt (VOID); +BOOLEAN SecInterruptEanbled (VOID); + + +extern EMU_THUNK_PROTOCOL gEmuThunkProtocol; +extern EMU_IO_THUNK_PROTOCOL gX11ThunkIo; +extern EMU_IO_THUNK_PROTOCOL gPosixFileSystemThunkIo; +extern EMU_IO_THUNK_PROTOCOL gPthreadThunkIo; +extern EMU_IO_THUNK_PROTOCOL gBlockIoThunkIo; +extern EMU_IO_THUNK_PROTOCOL gSnpThunkIo; + +#endif diff --git a/EmulatorPkg/Unix/Host/SecMain.inf b/EmulatorPkg/Unix/Host/SecMain.inf new file mode 100644 index 0000000000..9bda6f8d31 --- /dev/null +++ b/EmulatorPkg/Unix/Host/SecMain.inf @@ -0,0 +1,140 @@ +## @file +# Entry Point of Emu Emulator +# +# Main executable file of Unix Emulator that loads PEI core after initialization finished. +# Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2011, 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. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SecMain + FILE_GUID = 8863C0AD-7724-C84B-88E5-A33B116D1485 + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + SecMain.c + EmuThunk.c + X11GraphicsWindow.c + Pthreads.c + PosixFileSystem.c + BlockIo.c + LinuxPacketFilter.c + BerkeleyPacketFilter.c + MemoryAllocationLib.c + +[Sources.X64] + X64/Gasket.S # convert between Emu x86_64 ABI and EFI X64 ABI + X64/SwitchStack.S + +[Sources.IA32] + Ia32/Gasket.S # enforce 16-byte stack alignment for Mac OS X + Ia32/SwitchStack.c + + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmulatorPkg/EmulatorPkg.dec + +[LibraryClasses] + DebugLib + PcdLib + PrintLib + BaseMemoryLib + BaseLib + PeCoffLib + ThunkPpiList + ThunkProtocolList + PpiListLib + PeiServicesLib + PeCoffGetEntryPointLib + +[Ppis] + gEfiPeiStatusCodePpiGuid # PPI ALWAYS_PRODUCED + gEmuThunkPpiGuid + +[Protocols] + gEmuIoThunkProtocolGuid + gEmuIoThunkProtocolGuid + gEmuGraphicsWindowProtocolGuid + gEmuThreadThunkProtocolGuid + gEmuBlockIoProtocolGuid + gEmuSnpProtocolGuid + gEfiSimpleFileSystemProtocolGuid + +[Guids] + gEfiFileSystemVolumeLabelInfoIdGuid # SOMETIMES_CONSUMED + gEfiFileInfoGuid # SOMETIMES_CONSUMED + gEfiFileSystemInfoGuid # SOMETIMES_CONSUMED + +[Pcd] + gEmulatorPkgTokenSpaceGuid.PcdEmuBootMode + gEmulatorPkgTokenSpaceGuid.PcdEmuFirmwareVolume + gEmulatorPkgTokenSpaceGuid.PcdEmuMemorySize + gEmulatorPkgTokenSpaceGuid.PcdEmuFdBaseAddress + gEmulatorPkgTokenSpaceGuid.PcdEmuFirmwareFdSize + gEmulatorPkgTokenSpaceGuid.PcdEmuFirmwareBlockSize + gEmulatorPkgTokenSpaceGuid.PcdEmuApCount + gEmulatorPkgTokenSpaceGuid.PcdEmuVirtualDisk + gEmulatorPkgTokenSpaceGuid.PcdEmuGop|L"GOP Window" + gEmulatorPkgTokenSpaceGuid.PcdEmuFileSystem + gEmulatorPkgTokenSpaceGuid.PcdEmuSerialPort + gEmulatorPkgTokenSpaceGuid.PcdEmuNetworkInterface + gEmulatorPkgTokenSpaceGuid.PcdNetworkPacketFilterSize + + gEmulatorPkgTokenSpaceGuid.PcdEmuFlashFvRecoveryBase + gEmulatorPkgTokenSpaceGuid.PcdEmuFlashFvRecoverySize + gEmulatorPkgTokenSpaceGuid.PcdEmuFlashNvStorageVariableBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize + gEmulatorPkgTokenSpaceGuid.PcdEmuFlashNvStorageEventLogBase + gEmulatorPkgTokenSpaceGuid.PcdEmuFlashNvStorageEventLogSize + gEmulatorPkgTokenSpaceGuid.PcdEmuFlashNvStorageFtwWorkingBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize + gEmulatorPkgTokenSpaceGuid.PcdEmuFlashNvStorageFtwSpareBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize + gEmulatorPkgTokenSpaceGuid.PcdPeiServicesTablePage + + +[BuildOptions] + GCC:*_*_IA32_DLINK_FLAGS == -o $(BIN_DIR)/SecMain -m elf_i386 -dynamic-linker /lib$(LIB_ARCH_SFX)/ld-linux.so.2 /usr/lib$(LIB_ARCH_SFX)/crt1.o /usr/lib$(LIB_ARCH_SFX)/crti.o -L/usr/X11R6/lib -lXext -lX11 /usr/lib$(LIB_ARCH_SFX)/crtn.o + GCC:*_*_*_DLINK2_FLAGS == -lpthread -lc + 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 == -m32 -c -x assembler -imacros $(DEST_DIR_DEBUG)/AutoGen.h + + GCC:*_*_X64_DLINK_FLAGS == -o $(BIN_DIR)/SecMain -m elf_x86_64 -dynamic-linker /lib$(LIB_ARCH_SFX)/ld-linux-x86-64.so.2 /usr/lib$(LIB_ARCH_SFX)/crt1.o /usr/lib$(LIB_ARCH_SFX)/crti.o -L/usr/X11R6/lib -lXext -lX11 /usr/lib$(LIB_ARCH_SFX)/crtn.o + GCC:*_*_X64_CC_FLAGS == -m64 -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:*_GCC44_X64_CC_FLAGS = "-DEFIAPI=__attribute__((ms_abi))" + GCC:*_GCC45_X64_CC_FLAGS = "-DEFIAPI=__attribute__((ms_abi))" + GCC:*_*_X64_PP_FLAGS == -m64 -E -x assembler-with-cpp -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_*_X64_ASM_FLAGS == -m64 -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_CC_FLAGS == -arch i386 -O0 -g -include $(DEST_DIR_DEBUG)/AutoGen.h -c -fshort-wchar -fno-strict-aliasing + XCODE:*_*_IA32_DLINK_FLAGS == -arch i386 -o $(BIN_DIR)/SecMain -L/usr/X11R6/lib -lXext -lX11 -framework Carbon + XCODE:*_*_IA32_ASM_FLAGS == -arch i386 -g + + XCODE:*_*_X64_DLINK_PATH == gcc + XCODE:*_*_X64_DLINK_FLAGS == -o $(BIN_DIR)/SecMain -L/usr/X11R6/lib -lXext -lX11 -framework Carbon + XCODE:*_*_X64_ASM_FLAGS == -g + diff --git a/EmulatorPkg/Unix/Host/X11GraphicsWindow.c b/EmulatorPkg/Unix/Host/X11GraphicsWindow.c new file mode 100644 index 0000000000..ddcf1e7675 --- /dev/null +++ b/EmulatorPkg/Unix/Host/X11GraphicsWindow.c @@ -0,0 +1,1028 @@ +/*++ @file + +Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.
+Portions copyright (c) 2008 - 2011, 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. + +**/ + +#include "SecMain.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#define KEYSYM_LOWER 0 +#define KEYSYM_UPPER 1 + + +struct uga_drv_shift_mask { + unsigned char shift; + unsigned char size; + unsigned char csize; +}; + +#define NBR_KEYS 32 +typedef struct { + EMU_GRAPHICS_WINDOW_PROTOCOL GraphicsIo; + + Display *display; + int screen; // values for window_size in main + Window win; + GC gc; + Visual *visual; + + int depth; + unsigned int width; + unsigned int height; + unsigned int line_bytes; + unsigned int pixel_shift; + unsigned char *image_data; + + struct uga_drv_shift_mask r, g, b; + + int use_shm; + XShmSegmentInfo xshm_info; + XImage *image; + char *Title; + + unsigned int key_rd; + unsigned int key_wr; + unsigned int key_count; + EFI_KEY_DATA keys[NBR_KEYS]; + + EFI_KEY_STATE KeyState; + + EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK MakeRegisterdKeyCallback; + EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK BreakRegisterdKeyCallback; + VOID *RegisterdKeyCallbackContext; + + int previous_x; + int previous_y; + EFI_SIMPLE_POINTER_STATE pointer_state; + int pointer_state_changed; +} GRAPHICS_IO_PRIVATE; + +void +HandleEvents( + IN GRAPHICS_IO_PRIVATE *Drv + ); + +void +fill_shift_mask ( + IN struct uga_drv_shift_mask *sm, + IN unsigned long mask + ) +{ + sm->shift = 0; + sm->size = 0; + while ((mask & 1) == 0) { + mask >>= 1; + sm->shift++; + } + while (mask & 1) { + sm->size++; + mask >>= 1; + } + sm->csize = 8 - sm->size; +} + +int +TryCreateShmImage ( + IN GRAPHICS_IO_PRIVATE *Drv + ) +{ + Drv->image = XShmCreateImage ( + Drv->display, Drv->visual, + Drv->depth, ZPixmap, NULL, &Drv->xshm_info, + Drv->width, Drv->height + ); + if (Drv->image == NULL) { + return 0; + } + + switch (Drv->image->bitmap_unit) { + case 32: + Drv->pixel_shift = 2; + break; + case 16: + Drv->pixel_shift = 1; + break; + case 8: + Drv->pixel_shift = 0; + break; + } + + Drv->xshm_info.shmid = shmget ( + IPC_PRIVATE, Drv->image->bytes_per_line * Drv->image->height, + IPC_CREAT | 0777 + ); + if (Drv->xshm_info.shmid < 0) { + XDestroyImage(Drv->image); + return 0; + } + + Drv->image_data = shmat (Drv->xshm_info.shmid, NULL, 0); + if(!Drv->image_data) { + shmctl (Drv->xshm_info.shmid, IPC_RMID, NULL); + 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. + // + shmctl (Drv->xshm_info.shmid, IPC_RMID, NULL); +#endif + + Drv->xshm_info.shmaddr = (char*)Drv->image_data; + Drv->image->data = (char*)Drv->image_data; + + if (!XShmAttach (Drv->display, &Drv->xshm_info)) { + shmdt (Drv->image_data); + XDestroyImage(Drv->image); + return 0; + } + return 1; +} + + +EFI_STATUS +X11Size ( + IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo, + IN UINT32 Width, + IN UINT32 Height + ) +{ + GRAPHICS_IO_PRIVATE *Drv; + XSizeHints size_hints; + + // Destroy current buffer if created. + Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo; + if (Drv->image != NULL) { + // Before destroy buffer, need to make sure the buffer available for access. + XDestroyImage (Drv->image); + + if (Drv->use_shm) { + shmdt (Drv->image_data); + } + + Drv->image_data = NULL; + Drv->image = NULL; + } + + Drv->width = Width; + Drv->height = Height; + XResizeWindow (Drv->display, Drv->win, Width, Height); + + // Allocate image. + if (XShmQueryExtension(Drv->display) && TryCreateShmImage(Drv)) { + Drv->use_shm = 1; + } else { + Drv->use_shm = 0; + if (Drv->depth > 16) { + Drv->pixel_shift = 2; + } else if (Drv->depth > 8) { + Drv->pixel_shift = 1; + } else { + Drv->pixel_shift = 0; + } + + Drv->image_data = malloc ((Drv->width * Drv->height) << Drv->pixel_shift); + Drv->image = XCreateImage ( + Drv->display, Drv->visual, Drv->depth, + ZPixmap, 0, (char *)Drv->image_data, + Drv->width, Drv->height, + 8 << Drv->pixel_shift, 0 + ); + } + + Drv->line_bytes = Drv->image->bytes_per_line; + + fill_shift_mask (&Drv->r, Drv->image->red_mask); + fill_shift_mask (&Drv->g, Drv->image->green_mask); + fill_shift_mask (&Drv->b, Drv->image->blue_mask); + + // Set WM hints. + size_hints.flags = PSize | PMinSize | PMaxSize; + size_hints.min_width = size_hints.max_width = size_hints.base_width = Width; + size_hints.min_height = size_hints.max_height = size_hints.base_height = Height; + XSetWMNormalHints (Drv->display, Drv->win, &size_hints); + + XMapWindow (Drv->display, Drv->win); + HandleEvents (Drv); + return EFI_SUCCESS; +} + +void +handleKeyEvent ( + IN GRAPHICS_IO_PRIVATE *Drv, + IN XEvent *ev, + IN BOOLEAN Make + ) +{ + KeySym *KeySym; + EFI_KEY_DATA KeyData; + int KeySymArraySize; + + if (Make) { + if (Drv->key_count == NBR_KEYS) { + return; + } + } + + // keycode is a physical key on the keyboard + // KeySym is a mapping of a physical key + // KeyboardMapping is the array of KeySym for a given keycode. key, shifted key, option key, command key, ... + // + // Returns an array of KeySymArraySize of KeySym for the keycode. [0] is lower case, [1] is upper case, + // [2] and [3] are based on option and command modifiers. The problem we have is command V + // could be mapped to a crazy Unicode character so the old scheme of returning a string. + // + KeySym = XGetKeyboardMapping (Drv->display, ev->xkey.keycode, 1, &KeySymArraySize); + + KeyData.Key.ScanCode = 0; + KeyData.Key.UnicodeChar = 0; + KeyData.KeyState.KeyShiftState = 0; + + // + // Skipping EFI_SCROLL_LOCK_ACTIVE & EFI_NUM_LOCK_ACTIVE since they are not on Macs + // + if ((ev->xkey.state & LockMask) == 0) { + Drv->KeyState.KeyToggleState &= ~EFI_CAPS_LOCK_ACTIVE; + } else { + if (Make) { + Drv->KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE; + } + } + + // Skipping EFI_MENU_KEY_PRESSED and EFI_SYS_REQ_PRESSED + + switch (*KeySym) { + case XK_Control_R: + if (Make) { + Drv->KeyState.KeyShiftState |= EFI_RIGHT_CONTROL_PRESSED; + } else { + Drv->KeyState.KeyShiftState &= ~EFI_RIGHT_CONTROL_PRESSED; + } + break; + case XK_Control_L: + if (Make) { + Drv->KeyState.KeyShiftState |= EFI_LEFT_CONTROL_PRESSED; + } else { + Drv->KeyState.KeyShiftState &= ~EFI_LEFT_CONTROL_PRESSED; + } + break; + + case XK_Shift_R: + if (Make) { + Drv->KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED; + } else { + Drv->KeyState.KeyShiftState &= ~EFI_RIGHT_SHIFT_PRESSED; + } + break; + case XK_Shift_L: + if (Make) { + Drv->KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED; + } else { + Drv->KeyState.KeyShiftState &= ~EFI_LEFT_SHIFT_PRESSED; + } + break; + + case XK_Mode_switch: + if (Make) { + Drv->KeyState.KeyShiftState |= EFI_LEFT_ALT_PRESSED; + } else { + Drv->KeyState.KeyShiftState &= ~EFI_LEFT_ALT_PRESSED; + } + break; + + case XK_Meta_R: + if (Make) { + Drv->KeyState.KeyShiftState |= EFI_RIGHT_LOGO_PRESSED; + } else { + Drv->KeyState.KeyShiftState &= ~EFI_RIGHT_LOGO_PRESSED; + } + break; + case XK_Meta_L: + if (Make) { + Drv->KeyState.KeyShiftState |= EFI_LEFT_LOGO_PRESSED; + } else { + Drv->KeyState.KeyShiftState &= ~EFI_LEFT_LOGO_PRESSED; + } + break; + + case XK_KP_Home: + case XK_Home: KeyData.Key.ScanCode = SCAN_HOME; break; + + case XK_KP_End: + case XK_End: KeyData.Key.ScanCode = SCAN_END; break; + + case XK_KP_Left: + case XK_Left: KeyData.Key.ScanCode = SCAN_LEFT; break; + + case XK_KP_Right: + case XK_Right: KeyData.Key.ScanCode = SCAN_RIGHT; break; + + case XK_KP_Up: + case XK_Up: KeyData.Key.ScanCode = SCAN_UP; break; + + case XK_KP_Down: + case XK_Down: KeyData.Key.ScanCode = SCAN_DOWN; break; + + case XK_KP_Delete: + case XK_Delete: KeyData.Key.ScanCode = SCAN_DELETE; break; + + case XK_KP_Insert: + case XK_Insert: KeyData.Key.ScanCode = SCAN_INSERT; break; + + case XK_KP_Page_Up: + case XK_Page_Up: KeyData.Key.ScanCode = SCAN_PAGE_UP; break; + + case XK_KP_Page_Down: + case XK_Page_Down: KeyData.Key.ScanCode = SCAN_PAGE_DOWN; break; + + case XK_Escape: KeyData.Key.ScanCode = SCAN_ESC; break; + + case XK_Pause: KeyData.Key.ScanCode = SCAN_PAUSE; break; + + case XK_KP_F1: + case XK_F1: KeyData.Key.ScanCode = SCAN_F1; break; + + case XK_KP_F2: + case XK_F2: KeyData.Key.ScanCode = SCAN_F2; break; + + case XK_KP_F3: + case XK_F3: KeyData.Key.ScanCode = SCAN_F3; break; + + case XK_KP_F4: + case XK_F4: KeyData.Key.ScanCode = SCAN_F4; break; + + case XK_F5: KeyData.Key.ScanCode = SCAN_F5; break; + case XK_F6: KeyData.Key.ScanCode = SCAN_F6; break; + case XK_F7: KeyData.Key.ScanCode = SCAN_F7; break; + + // Don't map into X11 by default on a Mac + // System Preferences->Keyboard->Keyboard Shortcuts can be configured + // to not use higher function keys as shortcuts and the will show up + // in X11. + case XK_F8: KeyData.Key.ScanCode = SCAN_F8; break; + case XK_F9: KeyData.Key.ScanCode = SCAN_F9; break; + case XK_F10: KeyData.Key.ScanCode = SCAN_F10; break; + + case XK_F11: KeyData.Key.ScanCode = SCAN_F11; break; + case XK_F12: KeyData.Key.ScanCode = SCAN_F12; break; + + case XK_F13: KeyData.Key.ScanCode = SCAN_F13; break; + case XK_F14: KeyData.Key.ScanCode = SCAN_F14; break; + case XK_F15: KeyData.Key.ScanCode = SCAN_F15; break; + case XK_F16: KeyData.Key.ScanCode = SCAN_F16; break; + case XK_F17: KeyData.Key.ScanCode = SCAN_F17; break; + case XK_F18: KeyData.Key.ScanCode = SCAN_F18; break; + case XK_F19: KeyData.Key.ScanCode = SCAN_F19; break; + case XK_F20: KeyData.Key.ScanCode = SCAN_F20; break; + case XK_F21: KeyData.Key.ScanCode = SCAN_F21; break; + case XK_F22: KeyData.Key.ScanCode = SCAN_F22; break; + case XK_F23: KeyData.Key.ScanCode = SCAN_F23; break; + case XK_F24: KeyData.Key.ScanCode = SCAN_F24; break; + + // No mapping in X11 + //case XK_: KeyData.Key.ScanCode = SCAN_MUTE; break; + //case XK_: KeyData.Key.ScanCode = SCAN_VOLUME_UP; break; + //case XK_: KeyData.Key.ScanCode = SCAN_VOLUME_DOWN; break; + //case XK_: KeyData.Key.ScanCode = SCAN_BRIGHTNESS_UP; break; + //case XK_: KeyData.Key.ScanCode = SCAN_BRIGHTNESS_DOWN; break; + //case XK_: KeyData.Key.ScanCode = SCAN_SUSPEND; break; + //case XK_: KeyData.Key.ScanCode = SCAN_HIBERNATE; break; + //case XK_: KeyData.Key.ScanCode = SCAN_TOGGLE_DISPLAY; break; + //case XK_: KeyData.Key.ScanCode = SCAN_RECOVERY; break; + //case XK_: KeyData.Key.ScanCode = SCAN_EJECT; break; + + case XK_BackSpace: KeyData.Key.UnicodeChar = 0x0008; break; + + case XK_KP_Tab: + case XK_Tab: KeyData.Key.UnicodeChar = 0x0009; break; + + case XK_Linefeed: KeyData.Key.UnicodeChar = 0x000a; break; + + case XK_KP_Enter: + case XK_Return: KeyData.Key.UnicodeChar = 0x000d; break; + + case XK_KP_Equal : KeyData.Key.UnicodeChar = L'='; break; + case XK_KP_Multiply : KeyData.Key.UnicodeChar = L'*'; break; + case XK_KP_Add : KeyData.Key.UnicodeChar = L'+'; break; + case XK_KP_Separator : KeyData.Key.UnicodeChar = L'~'; break; + case XK_KP_Subtract : KeyData.Key.UnicodeChar = L'-'; break; + case XK_KP_Decimal : KeyData.Key.UnicodeChar = L'.'; break; + case XK_KP_Divide : KeyData.Key.UnicodeChar = L'/'; break; + + case XK_KP_0 : KeyData.Key.UnicodeChar = L'0'; break; + case XK_KP_1 : KeyData.Key.UnicodeChar = L'1'; break; + case XK_KP_2 : KeyData.Key.UnicodeChar = L'2'; break; + case XK_KP_3 : KeyData.Key.UnicodeChar = L'3'; break; + case XK_KP_4 : KeyData.Key.UnicodeChar = L'4'; break; + case XK_KP_5 : KeyData.Key.UnicodeChar = L'5'; break; + case XK_KP_6 : KeyData.Key.UnicodeChar = L'6'; break; + case XK_KP_7 : KeyData.Key.UnicodeChar = L'7'; break; + case XK_KP_8 : KeyData.Key.UnicodeChar = L'8'; break; + case XK_KP_9 : KeyData.Key.UnicodeChar = L'9'; break; + + default: + ; + } + + // The global state is our state + KeyData.KeyState.KeyShiftState = Drv->KeyState.KeyShiftState; + KeyData.KeyState.KeyToggleState = Drv->KeyState.KeyToggleState; + + if (*KeySym < XK_BackSpace) { + if (((Drv->KeyState.KeyShiftState & (EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED)) != 0) || + ((Drv->KeyState.KeyToggleState & EFI_CAPS_LOCK_ACTIVE) != 0) ) { + + KeyData.Key.UnicodeChar = (CHAR16)KeySym[KEYSYM_UPPER]; + + // Per UEFI spec since we converted the Unicode clear the shift bits we pass up + KeyData.KeyState.KeyShiftState &= ~(EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED); + } else { + KeyData.Key.UnicodeChar = (CHAR16)KeySym[KEYSYM_LOWER]; + } + } else { + // XK_BackSpace is the start of XK_MISCELLANY. These are the XK_? keys we process in this file + ; + } + + if (Make) { + memcpy (&Drv->keys[Drv->key_wr], &KeyData, sizeof (EFI_KEY_DATA)); + Drv->key_wr = (Drv->key_wr + 1) % NBR_KEYS; + Drv->key_count++; + if (Drv->MakeRegisterdKeyCallback != NULL) { + ReverseGasketUint64Uint64 (Drv->MakeRegisterdKeyCallback ,Drv->RegisterdKeyCallbackContext, &KeyData); + } + } else { + if (Drv->BreakRegisterdKeyCallback != NULL) { + ReverseGasketUint64Uint64 (Drv->BreakRegisterdKeyCallback ,Drv->RegisterdKeyCallbackContext, &KeyData); + } + } +} + + +void +handleMouseMoved( + IN GRAPHICS_IO_PRIVATE *Drv, + IN XEvent *ev + ) +{ + if (ev->xmotion.x != Drv->previous_x) { + Drv->pointer_state.RelativeMovementX += ( ev->xmotion.x - Drv->previous_x ); + Drv->previous_x = ev->xmotion.x; + Drv->pointer_state_changed = 1; + } + + if (ev->xmotion.y != Drv->previous_y) { + Drv->pointer_state.RelativeMovementY += ( ev->xmotion.y - Drv->previous_y ); + Drv->previous_y = ev->xmotion.y; + Drv->pointer_state_changed = 1; + } + + Drv->pointer_state.RelativeMovementZ = 0; +} + +void +handleMouseDown ( + IN GRAPHICS_IO_PRIVATE *Drv, + IN XEvent *ev, + IN BOOLEAN Pressed + ) +{ + if (ev->xbutton.button == Button1) { + Drv->pointer_state_changed = (Drv->pointer_state.LeftButton != Pressed); + Drv->pointer_state.LeftButton = Pressed; + } + if ( ev->xbutton.button == Button2 ) { + Drv->pointer_state_changed = (Drv->pointer_state.RightButton != Pressed); + Drv->pointer_state.RightButton = Pressed; + } +} + +void +Redraw ( + IN GRAPHICS_IO_PRIVATE *Drv, + IN UINTN X, + IN UINTN Y, + IN UINTN Width, + IN UINTN Height + ) +{ + if (Drv->use_shm) { + XShmPutImage ( + Drv->display, Drv->win, Drv->gc, Drv->image, X, Y, X, Y, Width, Height, False + ); + } else { + XPutImage ( + Drv->display, Drv->win, Drv->gc, Drv->image, X, Y, X, Y, Width, Height + ); + } + XFlush(Drv->display); +} + +void +HandleEvent(GRAPHICS_IO_PRIVATE *Drv, XEvent *ev) +{ + switch (ev->type) { + case Expose: + Redraw (Drv, ev->xexpose.x, ev->xexpose.y, + ev->xexpose.width, ev->xexpose.height); + break; + case GraphicsExpose: + Redraw (Drv, ev->xgraphicsexpose.x, ev->xgraphicsexpose.y, + ev->xgraphicsexpose.width, ev->xgraphicsexpose.height); + break; + case KeyPress: + handleKeyEvent (Drv, ev, TRUE); + break; + case KeyRelease: + handleKeyEvent (Drv, ev, FALSE); + break; + case MappingNotify: + XRefreshKeyboardMapping (&ev->xmapping); + break; + case MotionNotify: + handleMouseMoved (Drv, ev); + break; + case ButtonPress: + handleMouseDown (Drv, ev, TRUE); + break; + case ButtonRelease: + handleMouseDown (Drv, ev, FALSE); + break; +#if 0 + case DestroyNotify: + XCloseDisplay (Drv->display); + exit (1); + break; +#endif + case NoExpose: + default: + break; + } +} + +void +HandleEvents ( + IN GRAPHICS_IO_PRIVATE *Drv + ) +{ + XEvent ev; + + while (XPending (Drv->display) != 0) { + XNextEvent (Drv->display, &ev); + HandleEvent (Drv, &ev); + } +} + +unsigned long +X11PixelToColor ( + IN GRAPHICS_IO_PRIVATE *Drv, + IN EFI_UGA_PIXEL pixel + ) +{ + return ((pixel.Red >> Drv->r.csize) << Drv->r.shift) + | ((pixel.Green >> Drv->g.csize) << Drv->g.shift) + | ((pixel.Blue >> Drv->b.csize) << Drv->b.shift); +} + +EFI_UGA_PIXEL +X11ColorToPixel ( + IN GRAPHICS_IO_PRIVATE *Drv, + IN unsigned long val + ) +{ + EFI_UGA_PIXEL Pixel; + + memset (&Pixel, 0, sizeof (EFI_UGA_PIXEL)); + + // Truncation not an issue since X11 and EFI are both using 8 bits per color + Pixel.Red = (val >> Drv->r.shift) << Drv->r.csize; + Pixel.Green = (val >> Drv->g.shift) << Drv->g.csize; + Pixel.Blue = (val >> Drv->b.shift) << Drv->b.csize; + + return Pixel; +} + + +EFI_STATUS +X11CheckKey ( + IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo + ) +{ + GRAPHICS_IO_PRIVATE *Drv; + + Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo; + + HandleEvents (Drv); + + if (Drv->key_count != 0) { + return EFI_SUCCESS; + } + + return EFI_NOT_READY; +} + +EFI_STATUS +X11GetKey ( + IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo, + IN EFI_KEY_DATA *KeyData + ) +{ + EFI_STATUS EfiStatus; + GRAPHICS_IO_PRIVATE *Drv; + + Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo; + + EfiStatus = X11CheckKey (GraphicsIo); + if (EFI_ERROR (EfiStatus)) { + return EfiStatus; + } + + CopyMem (KeyData, &Drv->keys[Drv->key_rd], sizeof (EFI_KEY_DATA)); + Drv->key_rd = (Drv->key_rd + 1) % NBR_KEYS; + Drv->key_count--; + + return EFI_SUCCESS; +} + + +EFI_STATUS +X11KeySetState ( + IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo, + IN EFI_KEY_TOGGLE_STATE *KeyToggleState + ) +{ + GRAPHICS_IO_PRIVATE *Drv; + + Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo; + + if (*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) { + if ((Drv->KeyState.KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == 0) { + // + // We could create an XKeyEvent and send a XK_Caps_Lock to + // the UGA/GOP Window + // + } + } + + Drv->KeyState.KeyToggleState = *KeyToggleState; + return EFI_SUCCESS; +} + + +EFI_STATUS +X11RegisterKeyNotify ( + IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo, + IN EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK MakeCallBack, + IN EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK BreakCallBack, + IN VOID *Context + ) +{ + GRAPHICS_IO_PRIVATE *Drv; + + Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo; + + Drv->MakeRegisterdKeyCallback = MakeCallBack; + Drv->BreakRegisterdKeyCallback = BreakCallBack; + Drv->RegisterdKeyCallbackContext = Context; + + return EFI_SUCCESS; +} + + +EFI_STATUS +X11Blt ( + IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo, + IN EFI_UGA_PIXEL *BltBuffer OPTIONAL, + IN EFI_UGA_BLT_OPERATION BltOperation, + IN EMU_GRAPHICS_WINDOWS__BLT_ARGS *Args + ) +{ + GRAPHICS_IO_PRIVATE *Private; + UINTN DstY; + UINTN SrcY; + UINTN DstX; + UINTN SrcX; + UINTN Index; + EFI_UGA_PIXEL *Blt; + UINT8 *Dst; + UINT8 *Src; + UINTN Nbr; + unsigned long Color; + XEvent ev; + + Private = (GRAPHICS_IO_PRIVATE *)GraphicsIo; + + + // + // Check bounds + // + if (BltOperation == EfiUgaVideoToBltBuffer + || BltOperation == EfiUgaVideoToVideo) { + // + // Source is Video. + // + if (Args->SourceY + Args->Height > Private->height) { + return EFI_INVALID_PARAMETER; + } + + if (Args->SourceX + Args->Width > Private->width) { + return EFI_INVALID_PARAMETER; + } + } + + if (BltOperation == EfiUgaBltBufferToVideo + || BltOperation == EfiUgaVideoToVideo + || BltOperation == EfiUgaVideoFill) { + // + // Destination is Video + // + if (Args->DestinationY + Args->Height > Private->height) { + return EFI_INVALID_PARAMETER; + } + + if (Args->DestinationX + Args->Width > Private->width) { + return EFI_INVALID_PARAMETER; + } + } + + switch (BltOperation) { + case EfiUgaVideoToBltBuffer: + Blt = (EFI_UGA_PIXEL *)((UINT8 *)BltBuffer + (Args->DestinationY * Args->Delta) + Args->DestinationX * sizeof (EFI_UGA_PIXEL)); + Args->Delta -= Args->Width * sizeof (EFI_UGA_PIXEL); + for (SrcY = Args->SourceY; SrcY < (Args->Height + Args->SourceY); SrcY++) { + for (SrcX = Args->SourceX; SrcX < (Args->Width + Args->SourceX); SrcX++) { + *Blt++ = X11ColorToPixel (Private, XGetPixel (Private->image, SrcX, SrcY)); + } + Blt = (EFI_UGA_PIXEL *) ((UINT8 *) Blt + Args->Delta); + } + break; + case EfiUgaBltBufferToVideo: + Blt = (EFI_UGA_PIXEL *)((UINT8 *)BltBuffer + (Args->SourceY * Args->Delta) + Args->SourceX * sizeof (EFI_UGA_PIXEL)); + Args->Delta -= Args->Width * sizeof (EFI_UGA_PIXEL); + for (DstY = Args->DestinationY; DstY < (Args->Height + Args->DestinationY); DstY++) { + for (DstX = Args->DestinationX; DstX < (Args->Width + Args->DestinationX); DstX++) { + XPutPixel(Private->image, DstX, DstY, X11PixelToColor(Private, *Blt)); + Blt++; + } + Blt = (EFI_UGA_PIXEL *) ((UINT8 *) Blt + Args->Delta); + } + break; + case EfiUgaVideoToVideo: + Dst = Private->image_data + (Args->DestinationX << Private->pixel_shift) + + Args->DestinationY * Private->line_bytes; + Src = Private->image_data + (Args->SourceX << Private->pixel_shift) + + Args->SourceY * Private->line_bytes; + Nbr = Args->Width << Private->pixel_shift; + if (Args->DestinationY < Args->SourceY) { + for (Index = 0; Index < Args->Height; Index++) { + memcpy (Dst, Src, Nbr); + Dst += Private->line_bytes; + Src += Private->line_bytes; + } + } else { + Dst += (Args->Height - 1) * Private->line_bytes; + Src += (Args->Height - 1) * Private->line_bytes; + for (Index = 0; Index < Args->Height; Index++) { + // + // Source and Destination Y may be equal, therefore Dst and Src may + // overlap. + // + memmove (Dst, Src, Nbr); + Dst -= Private->line_bytes; + Src -= Private->line_bytes; + } + } + break; + case EfiUgaVideoFill: + Color = X11PixelToColor(Private, *BltBuffer); + for (DstY = Args->DestinationY; DstY < (Args->Height + Args->DestinationY); DstY++) { + for (DstX = Args->DestinationX; DstX < (Args->Width + Args->DestinationX); DstX++) { + XPutPixel(Private->image, DstX, DstY, Color); + } + } + break; + default: + return EFI_INVALID_PARAMETER; + } + + // + // Refresh screen. + // + switch (BltOperation) { + case EfiUgaVideoToVideo: + XCopyArea( + Private->display, Private->win, Private->win, Private->gc, + Args->SourceX, Args->SourceY, Args->Width, Args->Height, + Args->DestinationX, Args->DestinationY + ); + + while (1) { + XNextEvent (Private->display, &ev); + HandleEvent (Private, &ev); + if (ev.type == NoExpose || ev.type == GraphicsExpose) { + break; + } + } + break; + case EfiUgaVideoFill: + Color = X11PixelToColor (Private, *BltBuffer); + XSetForeground (Private->display, Private->gc, Color); + XFillRectangle ( + Private->display, Private->win, Private->gc, + Args->DestinationX, Args->DestinationY, Args->Width, Args->Height + ); + XFlush (Private->display); + break; + case EfiUgaBltBufferToVideo: + Redraw (Private, Args->DestinationX, Args->DestinationY, Args->Width, Args->Height); + break; + default: + break; + } + return EFI_SUCCESS; +} + + +EFI_STATUS +X11CheckPointer ( + IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo + ) +{ + GRAPHICS_IO_PRIVATE *Drv; + + Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo; + + HandleEvents (Drv); + if (Drv->pointer_state_changed != 0) { + return EFI_SUCCESS; + } + + return EFI_NOT_READY; +} + + +EFI_STATUS +X11GetPointerState ( + IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo, + IN EFI_SIMPLE_POINTER_STATE *State + ) +{ + EFI_STATUS EfiStatus; + GRAPHICS_IO_PRIVATE *Drv; + + Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo; + + EfiStatus = X11CheckPointer (GraphicsIo); + if (EfiStatus != EFI_SUCCESS) { + return EfiStatus; + } + + memcpy (State, &Drv->pointer_state, sizeof (EFI_SIMPLE_POINTER_STATE)); + + Drv->pointer_state.RelativeMovementX = 0; + Drv->pointer_state.RelativeMovementY = 0; + Drv->pointer_state.RelativeMovementZ = 0; + Drv->pointer_state_changed = 0; + return EFI_SUCCESS; +} + + + +EFI_STATUS +X11GraphicsWindowOpen ( + IN EMU_IO_THUNK_PROTOCOL *This + ) +{ + GRAPHICS_IO_PRIVATE *Drv; + unsigned int border_width = 0; + char *display_name = NULL; + + Drv = (GRAPHICS_IO_PRIVATE *)calloc (1, sizeof (GRAPHICS_IO_PRIVATE)); + if (Drv == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Drv->GraphicsIo.Size = GasketX11Size; + Drv->GraphicsIo.CheckKey = GasketX11CheckKey; + Drv->GraphicsIo.GetKey = GasketX11GetKey; + Drv->GraphicsIo.KeySetState = GasketX11KeySetState; + Drv->GraphicsIo.RegisterKeyNotify = GasketX11RegisterKeyNotify; + Drv->GraphicsIo.Blt = GasketX11Blt; + Drv->GraphicsIo.CheckPointer = GasketX11CheckPointer; + Drv->GraphicsIo.GetPointerState = GasketX11GetPointerState; + + + Drv->key_count = 0; + Drv->key_rd = 0; + Drv->key_wr = 0; + Drv->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID; + Drv->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID; + Drv->MakeRegisterdKeyCallback = NULL; + Drv->BreakRegisterdKeyCallback = NULL; + Drv->RegisterdKeyCallbackContext = NULL; + + + Drv->display = XOpenDisplay (display_name); + if (Drv->display == NULL) { + fprintf (stderr, "uga: cannot connect to X server %s\n", XDisplayName (display_name)); + free (Drv); + return EFI_DEVICE_ERROR; + } + Drv->screen = DefaultScreen (Drv->display); + Drv->visual = DefaultVisual (Drv->display, Drv->screen); + Drv->win = XCreateSimpleWindow ( + Drv->display, RootWindow (Drv->display, Drv->screen), + 0, 0, 4, 4, border_width, + WhitePixel (Drv->display, Drv->screen), + BlackPixel (Drv->display, Drv->screen) + ); + + Drv->depth = DefaultDepth (Drv->display, Drv->screen); + XDefineCursor (Drv->display, Drv->win, XCreateFontCursor (Drv->display, XC_pirate)); + + Drv->Title = malloc (StrSize (This->ConfigString)); + UnicodeStrToAsciiStr (This->ConfigString, Drv->Title); + XStoreName (Drv->display, Drv->win, Drv->Title); + +// XAutoRepeatOff (Drv->display); + XSelectInput ( + Drv->display, Drv->win, + ExposureMask | KeyPressMask | KeyReleaseMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask + ); + Drv->gc = DefaultGC (Drv->display, Drv->screen); + + This->Private = (VOID *)Drv; + This->Interface = (VOID *)Drv; + return EFI_SUCCESS; +} + + +EFI_STATUS +X11GraphicsWindowClose ( + IN EMU_IO_THUNK_PROTOCOL *This + ) +{ + GRAPHICS_IO_PRIVATE *Drv; + + Drv = (GRAPHICS_IO_PRIVATE *)This->Private; + + if (Drv == NULL) { + return EFI_SUCCESS; + } + + if (Drv->image != NULL) { + XDestroyImage(Drv->image); + + if (Drv->use_shm) { + shmdt (Drv->image_data); + } + + Drv->image_data = NULL; + Drv->image = NULL; + } + 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; +} + + +EMU_IO_THUNK_PROTOCOL gX11ThunkIo = { + &gEmuGraphicsWindowProtocolGuid, + NULL, + NULL, + 0, + GasketX11GraphicsWindowOpen, + GasketX11GraphicsWindowClose, + NULL +}; + + diff --git a/EmulatorPkg/Unix/Host/X64/Gasket.S b/EmulatorPkg/Unix/Host/X64/Gasket.S new file mode 100644 index 0000000000..7ea49bb422 --- /dev/null +++ b/EmulatorPkg/Unix/Host/X64/Gasket.S @@ -0,0 +1,1631 @@ +#------------------------------------------------------------------------------ +# +# Manage differenced between UNIX ABI and EFI/Windows ABI +# +# EFI Arg passing: RCX, RDX, R8, R9 +# Callee allocates 32 bytes on stack to spill registers +# UNIX Arg passing: RDI, RSI, RDX, RCX, R8, R9 +# RSI, RDI calle-save on EFI, scatch on UNIX callign +# +# Copyright (c) 2008 - 2011, 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. +# +#------------------------------------------------------------------------------ + +// +// Gaskets are EFI ABI to UNIX ABI calls +// EFI ABI code will sub 40 (0x28) from %rsp before calling a function +// This is the 32 (0x20) byte to spill registers and 8 bytes to align stack on 16 byte boundry. +// + .text + +// 32 byte shadow to spill rcx-r9, 8 bytes to align stack on 16 byte boundry +// Any call with 0 - 4 arguments allocates 40 bytes on the stack. +// For more than 4 args you always have to increase in quanta of 16 so 5 or 6 args is 56, +// 7 or 8 args is 72, and 9 or 10 args is 88 + + + + .text + +// +// EMU_THUNK_PROTOCOL gaskets (EFIAPI to UNIX ABI) +// + + + + +ASM_GLOBAL ASM_PFX(GasketSecWriteStdErr) +ASM_PFX(GasketSecWriteStdErr): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + + call ASM_PFX(SecWriteStdErr) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketSecConfigStdIn) +ASM_PFX(GasketSecConfigStdIn): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + call ASM_PFX(SecConfigStdIn) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + +ASM_GLOBAL ASM_PFX(GasketSecWriteStdOut) +ASM_PFX(GasketSecWriteStdOut): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + + call ASM_PFX(SecWriteStdOut) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + +ASM_GLOBAL ASM_PFX(GasketSecReadStdIn) +ASM_PFX(GasketSecReadStdIn): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + + call ASM_PFX(SecReadStdIn) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + +ASM_GLOBAL ASM_PFX(GasketSecPollStdIn) +ASM_PFX(GasketSecPollStdIn): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + call ASM_PFX(SecPollStdIn) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + +ASM_GLOBAL ASM_PFX(GasketSecMalloc) +ASM_PFX(GasketSecMalloc): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(SecMalloc) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + +ASM_GLOBAL ASM_PFX(GasketSecValloc) +ASM_PFX(GasketSecValloc): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(SecValloc) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + +ASM_GLOBAL ASM_PFX(GasketSecFree) +ASM_PFX(GasketSecFree): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(SecFree) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketSecSetTimer) +ASM_PFX(GasketSecSetTimer): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + + call ASM_PFX(SecSetTimer) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketSecEnableInterrupt) +ASM_PFX(GasketSecEnableInterrupt): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + call ASM_PFX(SecEnableInterrupt) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketSecDisableInterrupt) +ASM_PFX(GasketSecDisableInterrupt): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + call ASM_PFX(SecDisableInterrupt) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + +ASM_GLOBAL ASM_PFX(GasketQueryPerformanceFrequency) +ASM_PFX(GasketQueryPerformanceFrequency): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + call ASM_PFX(QueryPerformanceFrequency) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketQueryPerformanceCounter) +ASM_PFX(GasketQueryPerformanceCounter): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + call ASM_PFX(QueryPerformanceCounter) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketSecSleep) +ASM_PFX(GasketSecSleep): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(SecSleep) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketSecCpuSleep) +ASM_PFX(GasketSecCpuSleep): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + call ASM_PFX(SecCpuSleep) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketSecExit) +ASM_PFX(GasketSecExit): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + movq %rcx, %rdi // Swizzle args + call ASM_PFX(SecExit) // Less to do as we will never return to EFI ABI world +LDEAD_LOOP: + jmp LDEAD_LOOP // _exit should never return + + +ASM_GLOBAL ASM_PFX(GasketSecGetTime) +ASM_PFX(GasketSecGetTime): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + + call ASM_PFX(SecGetTime) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + +ASM_GLOBAL ASM_PFX(GasketSecSetTime) +ASM_PFX(GasketSecSetTime): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + + call ASM_PFX(SecSetTime) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketSecGetNextProtocol) +ASM_PFX(GasketSecGetNextProtocol): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + movq %r8, %rdx + movq %r9, %rcx + + call ASM_PFX(SecGetNextProtocol) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + +// PPIs produced by SEC + +ASM_GLOBAL ASM_PFX(GasketSecPeCoffGetEntryPoint) +ASM_PFX(GasketSecPeCoffGetEntryPoint): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + + call ASM_PFX(SecPeCoffGetEntryPoint) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + +ASM_GLOBAL ASM_PFX(GasketSecPeCoffRelocateImageExtraAction) +ASM_PFX(GasketSecPeCoffRelocateImageExtraAction): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(SecPeCoffRelocateImageExtraAction) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + +ASM_GLOBAL ASM_PFX(GasketSecPeCoffUnloadImageExtraAction) +ASM_PFX(GasketSecPeCoffUnloadImageExtraAction): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(SecPeCoffUnloadImageExtraAction) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketSecEmuThunkAddress) +ASM_PFX(GasketSecEmuThunkAddress): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + call ASM_PFX(SecEmuThunkAddress) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + +// +// Gasket functions for EFI_EMU_UGA_IO_PROTOCOL +// + +ASM_GLOBAL ASM_PFX(GasketX11Size) +ASM_PFX(GasketX11Size): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + movq %r8, %rdx + movq %r9, %rcx + + call ASM_PFX(X11Size) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketX11CheckKey) +ASM_PFX(GasketX11CheckKey): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(X11CheckKey) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + +ASM_GLOBAL ASM_PFX(GasketX11GetKey) +ASM_PFX(GasketX11GetKey): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + + call ASM_PFX(X11GetKey) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketX11KeySetState) +ASM_PFX(GasketX11KeySetState): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + + call ASM_PFX(X11KeySetState) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketX11RegisterKeyNotify) +ASM_PFX(GasketX11RegisterKeyNotify): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + movq %r8, %rdx + movq %r9, %rcx + + call ASM_PFX(X11RegisterKeyNotify) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketX11Blt) +ASM_PFX(GasketX11Blt): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + movq %r8, %rdx + movq %r9, %rcx + + call ASM_PFX(X11Blt) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketX11CheckPointer) +ASM_PFX(GasketX11CheckPointer): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(X11CheckPointer) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketX11GetPointerState) +ASM_PFX(GasketX11GetPointerState): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + + call ASM_PFX(X11GetPointerState) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketX11GraphicsWindowOpen) +ASM_PFX(GasketX11GraphicsWindowOpen): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(X11GraphicsWindowOpen) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketX11GraphicsWindowClose) +ASM_PFX(GasketX11GraphicsWindowClose): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %r9, %rcx + + call ASM_PFX(X11GraphicsWindowClose) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +// Pthreads + +ASM_GLOBAL ASM_PFX(GasketPthreadMutexLock) +ASM_PFX(GasketPthreadMutexLock): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(PthreadMutexLock) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketPthreadMutexUnLock) +ASM_PFX(GasketPthreadMutexUnLock): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(PthreadMutexUnLock) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + +ASM_GLOBAL ASM_PFX(GasketPthreadMutexTryLock) +ASM_PFX(GasketPthreadMutexTryLock): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(PthreadMutexTryLock) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + +ASM_GLOBAL ASM_PFX(GasketPthreadMutexInit) +ASM_PFX(GasketPthreadMutexInit): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + + call ASM_PFX(PthreadMutexInit) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + + +ASM_GLOBAL ASM_PFX(GasketPthreadMutexDestroy) +ASM_PFX(GasketPthreadMutexDestroy): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(PthreadMutexDestroy) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketPthreadCreate) +ASM_PFX(GasketPthreadCreate): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + movq %r8, %rdx + movq %r9, %rcx + + call ASM_PFX(PthreadCreate) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketPthreadExit) +ASM_PFX(GasketPthreadExit): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(PthreadExit) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + + +ASM_GLOBAL ASM_PFX(GasketPthreadSelf) +ASM_PFX(GasketPthreadSelf): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + + call ASM_PFX(PthreadSelf) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketPthreadOpen) +ASM_PFX(GasketPthreadOpen): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(PthreadOpen) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketPthreadClose) +ASM_PFX(GasketPthreadClose): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(PthreadClose) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + + + +// +// UNIX ABI to EFI ABI call +// +// UINTN +// ReverseGasketUint64 ( +// void *Api, +// UINTN Arg1 +// ); +ASM_GLOBAL ASM_PFX(ReverseGasketUint64) +ASM_PFX(ReverseGasketUint64): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + movq %rdi, %rax // Swizzle args + movq %rsi, %rcx + + subq $32, %rsp // 32-byte shadow space + call *%rax + addq $32, %rsp + + popq %rbp + ret + +// +// UNIX ABI to EFI ABI call +// +// UINTN +// ReverseGasketUint64Uint64 ( +// void *Api, +// UINTN Arg1 +// UINTN Arg2 +// ); +ASM_GLOBAL ASM_PFX(ReverseGasketUint64Uint64) +ASM_PFX(ReverseGasketUint64Uint64): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + movq %rdi, %rax // Swizzle args + movq %rsi, %rcx + + subq $32, %rsp // 32-byte shadow space + call *%rax + addq $32, %rsp + + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketSecUnixPeiAutoScan) +ASM_PFX(GasketSecUnixPeiAutoScan): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + movq %r8, %rdx + + call ASM_PFX(SecUnixPeiAutoScan) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketSecUnixFdAddress) +ASM_PFX(GasketSecUnixFdAddress): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + movq %r8, %rdx + movq %r9, %rcx + + call ASM_PFX(SecUnixFdAddress) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +// EmuIoThunk SimpleFileSystem + +ASM_GLOBAL ASM_PFX(GasketPosixOpenVolume) +ASM_PFX(GasketPosixOpenVolume): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + movq %r8, %rdx + movq %r9, %rcx + + call ASM_PFX(PosixOpenVolume) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketPosixFileOpen) +ASM_PFX(GasketPosixFileOpen): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + movq %r8, %rdx + movq %r9, %rcx + movq 48(%rbp), %r8 + + call ASM_PFX(PosixFileOpen) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketPosixFileCLose) +ASM_PFX(GasketPosixFileCLose): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(PosixFileCLose) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketPosixFileDelete) +ASM_PFX(GasketPosixFileDelete): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(PosixFileDelete) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketPosixFileRead) +ASM_PFX(GasketPosixFileRead): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + movq %r8, %rdx + + call ASM_PFX(PosixFileRead) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketPosixFileWrite) +ASM_PFX(GasketPosixFileWrite): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + movq %r8, %rdx + + call ASM_PFX(PosixFileWrite) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketPosixFileSetPossition) +ASM_PFX(GasketPosixFileSetPossition): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + + call ASM_PFX(PosixFileSetPossition) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketPosixFileGetPossition) +ASM_PFX(GasketPosixFileGetPossition): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + + call ASM_PFX(PosixFileGetPossition) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketPosixFileGetInfo) +ASM_PFX(GasketPosixFileGetInfo): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + movq %r8, %rdx + movq %r9, %rcx + + call ASM_PFX(PosixFileGetInfo) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketPosixFileSetInfo) +ASM_PFX(GasketPosixFileSetInfo): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + movq %r8, %rdx + movq %r9, %rcx + + call ASM_PFX(PosixFileSetInfo) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketPosixFileFlush) +ASM_PFX(GasketPosixFileFlush): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(PosixFileFlush) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketPosixFileSystmeThunkOpen) +ASM_PFX(GasketPosixFileSystmeThunkOpen): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(PosixFileSystmeThunkOpen) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketPosixFileSystmeThunkClose) +ASM_PFX(GasketPosixFileSystmeThunkClose): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(PosixFileSystmeThunkClose) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + +ASM_GLOBAL ASM_PFX(GasketEmuBlockIoReset) +ASM_PFX(GasketEmuBlockIoReset): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + + call ASM_PFX(EmuBlockIoReset) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketEmuBlockIoReadBlocks) +ASM_PFX(GasketEmuBlockIoReadBlocks): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + movq %r8, %rdx + movq %r9, %rcx + movq 48(%rbp), %r8 + movq 56(%rbp), %r9 + + call ASM_PFX(EmuBlockIoReadBlocks) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketEmuBlockIoWriteBlocks) +ASM_PFX(GasketEmuBlockIoWriteBlocks): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + movq %r8, %rdx + movq %r9, %rcx + movq 48(%rbp), %r8 + movq 56(%rbp), %r9 + + call ASM_PFX(EmuBlockIoWriteBlocks) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketEmuBlockIoFlushBlocks) +ASM_PFX(GasketEmuBlockIoFlushBlocks): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + + call ASM_PFX(EmuBlockIoFlushBlocks) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketEmuBlockIoCreateMapping) +ASM_PFX(GasketEmuBlockIoCreateMapping): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + + call ASM_PFX(EmuBlockIoCreateMapping) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketBlockIoThunkOpen) +ASM_PFX(GasketBlockIoThunkOpen): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(EmuBlockIoThunkOpen) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketBlockIoThunkClose) +ASM_PFX(GasketBlockIoThunkClose): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(EmuBlockIoThunkClose) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + + +ASM_GLOBAL ASM_PFX(GasketSnpCreateMapping) +ASM_PFX(GasketSnpCreateMapping): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + + call ASM_PFX(EmuSnpCreateMapping) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketSnpStart) +ASM_PFX(GasketSnpStart): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(EmuSnpStart) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketSnpStop) +ASM_PFX(GasketSnpStop): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(EmuSnpStop) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketSnpInitialize) +ASM_PFX(GasketSnpInitialize): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + movq %r8, %rdx + + call ASM_PFX(EmuSnpInitialize) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + + +ASM_GLOBAL ASM_PFX(GasketSnpReset) +ASM_PFX(GasketSnpReset): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + + call ASM_PFX(EmuSnpReset) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketSnpShutdown) +ASM_PFX(GasketSnpShutdown): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(EmuSnpShutdown) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketSnpReceiveFilters) +ASM_PFX(GasketSnpReceiveFilters): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + movq %r8, %rdx + movq %r9, %rcx + movq 48(%rbp), %r8 + movq 56(%rbp), %r9 + + call ASM_PFX(EmuSnpReceiveFilters) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketSnpStationAddress) +ASM_PFX(GasketSnpStationAddress): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + movq %r8, %rdx + + call ASM_PFX(EmuSnpStationAddress) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + + +ASM_GLOBAL ASM_PFX(GasketSnpStatistics) +ASM_PFX(GasketSnpStatistics): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + movq %r8, %rdx + movq %r9, %rcx + + call ASM_PFX(EmuSnpStatistics) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketSnpMCastIpToMac) +ASM_PFX(GasketSnpMCastIpToMac): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + movq %r8, %rdx + movq %r9, %rcx + + call ASM_PFX(EmuSnpMCastIpToMac) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketSnpNvData) +ASM_PFX(GasketSnpNvData): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + movq %r8, %rdx + movq %r9, %rcx + movq 48(%rbp), %r8 + + call ASM_PFX(EmuSnpNvData) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketSnpGetStatus) +ASM_PFX(GasketSnpGetStatus): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + movq %r8, %rdx + + call ASM_PFX(EmuSnpGetStatus) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + + +ASM_GLOBAL ASM_PFX(GasketSnpTransmit) +ASM_PFX(GasketSnpTransmit): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + subq $16, %rsp // Allocate space for args on the stack + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + movq %r8, %rdx + movq %r9, %rcx + movq 48(%rbp), %r8 + movq 56(%rbp), %r9 + movq 64(%rbp), %rax + movq %rax, (%rsp) + + call ASM_PFX(EmuSnpTransmit) + addq $16, %rsp + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + + +ASM_GLOBAL ASM_PFX(GasketSnpReceive) +ASM_PFX(GasketSnpReceive): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + subq $16, %rsp // Allocate space for args on the stack + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + movq %rdx, %rsi + movq %r8, %rdx + movq %r9, %rcx + movq 48(%rbp), %r8 + movq 56(%rbp), %r9 + movq 64(%rbp), %rax + movq %rax, (%rsp) + + call ASM_PFX(EmuSnpReceive) + addq $16, %rsp + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketSnpThunkOpen) +ASM_PFX(GasketSnpThunkOpen): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(EmuSnpThunkOpen) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + +ASM_GLOBAL ASM_PFX(GasketSnpThunkClose) +ASM_PFX(GasketSnpThunkClose): + pushq %rbp // stack frame is for the debugger + movq %rsp, %rbp + + pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI + pushq %rdi + + movq %rcx, %rdi // Swizzle args + + call ASM_PFX(EmuSnpThunkClose) + + popq %rdi // restore state + popq %rsi + popq %rbp + ret + + diff --git a/EmulatorPkg/Unix/Host/X64/SwitchStack.S b/EmulatorPkg/Unix/Host/X64/SwitchStack.S new file mode 100644 index 0000000000..8a57b781b5 --- /dev/null +++ b/EmulatorPkg/Unix/Host/X64/SwitchStack.S @@ -0,0 +1,53 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# Portitions copyright (c) 2011, 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. +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# Routine Description: +# +# Routine for switching stacks with 2 parameters EFI ABI +# Convert UNIX to EFI ABI +# +# Arguments: +# +# (rdi) EntryPoint - Entry point with new stack. +# (rsi) Context1 - Parameter1 for entry point. (rcx) +# (rdx) Context2 - Parameter2 for entry point. (rdx) +# (rcx) NewStack - The pointer to new stack. +# +# Returns: +# +# None +# +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(PeiSwitchStacks) +ASM_PFX(PeiSwitchStacks): + pushq $0 // tells gdb to stop unwinding frame + movq %rsp, %rbp + + movq %rcx, %rsp // update stack pointer + + movq %rdi, %rax // entry point to %rax + movq %rsi, %rcx // Adjust Context1 + // Context2 already in the rigth spot + + # + # Reserve space for register parameters (rcx, rdx, r8 & r9) on the stack, + # in case the callee wishes to spill them. + # + subq $32, %rsp // 32-byte shadow space plus alignment pad + call *%rax + + + diff --git a/EmulatorPkg/Unix/UnixX64.dsc b/EmulatorPkg/Unix/UnixX64.dsc new file mode 100644 index 0000000000..922df012fa --- /dev/null +++ b/EmulatorPkg/Unix/UnixX64.dsc @@ -0,0 +1,455 @@ +## @file +# +# UEFI/PI Emulation Platform with UEFI HII interface supported. +# +# The Emulation Platform can be used to debug individual modules, prior to creating +# a real platform. This also provides an example for how an DSC is created. +# Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2010 - 2011, 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. +# +## + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + PLATFORM_NAME = EmuUnix + PLATFORM_GUID = 05FD064D-1073-E844-936C-A0E16317107D + PLATFORM_VERSION = 0.3 + DSC_ SPECIFICATION = 0x00010005 +!if $(BUILD_32) + OUTPUT_DIRECTORY = Build/EmuUnixIa32 +!else + OUTPUT_DIRECTORY = Build/EmuUnixX64 +!endif + + SUPPORTED_ARCHITECTURES = X64|IA32 + BUILD_TARGETS = DEBUG|RELEASE + SKUID_IDENTIFIER = DEFAULT + FLASH_DEFINITION = EmulatorPkg/Unix/UnixX64.fdf + +################################################################################ +# +# SKU Identification section - list of all SKU IDs supported by this Platform. +# +################################################################################ +[SkuIds] + 0|DEFAULT + +################################################################################ +# +# Library Class section - list of all Library Classes needed by this Platform. +# +################################################################################ +[LibraryClasses] + # + # Entry point + # + PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf + PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf + DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf + # + # Basic + # + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf + PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf + + # + # UEFI & PI + # + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf + HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + UefiDecompressLib|IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf + + PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf + # + # Generic Modules + # + UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf + NetLib|MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf + IpIoLib|MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.inf + UdpIoLib|MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf + DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf + OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf + GenericBdsLib|IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf + SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf + TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf + SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf + # + # Platform + # + PlatformBdsLib|EmulatorPkg/Library/EmuBdsLib/EmuBdsLib.inf + KeyMapLib|EmulatorPkg/Library/KeyMapLibNull/KeyMapLibNull.inf + + # + # Misc + # + DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf + PeiServicesTablePointerLib|EmulatorPkg/Library/PeiServicesTablePointerLibMagicPage/PeiServicesTablePointerLibMagicPage.inf + DebugLib|IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf + + +[LibraryClasses.common.SEC] + PeiServicesLib|EmulatorPkg/Library/SecPeiServicesLib/SecPeiServicesLib.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + PeCoffGetEntryPointLib|EmulatorPkg/Library/PeiEmuPeCoffGetEntryPointLib/PeiEmuPeCoffGetEntryPointLib.inf + PeCoffExtraActionLib|EmulatorPkg/Library/PeiEmuPeCoffExtraActionLib/PeiEmuPeCoffExtraActionLib.inf + SerialPortLib|EmulatorPkg/Library/PeiEmuSerialPortLib/PeiEmuSerialPortLib.inf + PpiListLib|EmulatorPkg/Library/SecPpiListLib/SecPpiListLib.inf + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + TimerLib|EmulatorPkg/Library/PeiTimerLib/PeiTimerLib.inf + +[LibraryClasses.common.USER_DEFINED, LibraryClasses.common.BASE] + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + PpiListLib|EmulatorPkg/Library/SecPpiListLib/SecPpiListLib.inf + ThunkPpiList|EmulatorPkg/Library/ThunkPpiList/ThunkPpiList.inf + ThunkProtocolList|EmulatorPkg/Library/ThunkProtocolList/ThunkProtocolList.inf + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + PpiListLib|EmulatorPkg/Library/SecPpiListLib/SecPpiListLib.inf + PeiServicesLib|EmulatorPkg/Library/SecPeiServicesLib/SecPeiServicesLib.inf + + +[LibraryClasses.common.PEIM, LibraryClasses.common.PEI_CORE] + HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf + MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf + PeCoffGetEntryPointLib|EmulatorPkg/Library/PeiEmuPeCoffGetEntryPointLib/PeiEmuPeCoffGetEntryPointLib.inf + PeCoffExtraActionLib|EmulatorPkg/Library/PeiEmuPeCoffExtraActionLib/PeiEmuPeCoffExtraActionLib.inf + ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf + SerialPortLib|EmulatorPkg/Library/PeiEmuSerialPortLib/PeiEmuSerialPortLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf + TimerLib|EmulatorPkg/Library/PeiTimerLib/PeiTimerLib.inf + +[LibraryClasses.common.PEI_CORE] + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + +[LibraryClasses.common.PEIM] + PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf + +[LibraryClasses.common.DXE_CORE] + HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf + MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf + PeCoffExtraActionLib|EmulatorPkg/Library/DxeEmuPeCoffExtraActionLib/DxeEmuPeCoffExtraActionLib.inf + ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + TimerLib|EmulatorPkg/Library/DxeCoreTimerLib/DxeCoreTimerLib.inf + EmuThunkLib|EmulatorPkg/Library/DxeEmuLib/DxeEmuLib.inf + +[LibraryClasses.common.DXE_RUNTIME_DRIVER, LibraryClasses.common.UEFI_DRIVER, LibraryClasses.common.DXE_DRIVER, LibraryClasses.common.UEFI_APPLICATION] + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf + EmuThunkLib|EmulatorPkg/Library/DxeEmuLib/DxeEmuLib.inf + PeCoffExtraActionLib|EmulatorPkg/Library/DxeEmuPeCoffExtraActionLib/DxeEmuPeCoffExtraActionLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf + TimerLib|EmulatorPkg/Library/DxeTimerLib/DxeTimerLib.inf + +[LibraryClasses.common.UEFI_DRIVER] + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + +[LibraryClasses.common.UEFI_APPLICATION] + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + + +################################################################################ +# +# Pcd Section - list of all EDK II PCD Entries defined by this Platform. +# +################################################################################ +[PcdsFeatureFlag] + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreImageLoaderSearchTeSectionFirst|FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE + +[PcdsFixedAtBuild] + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000040 + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x0f + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x1f + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizeNonPopulateCapsule|0x0 + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizePopulateCapsule|0x0 + + gEmulatorPkgTokenSpaceGuid.PcdEmuFirmwareFdSize|0x002a0000 + gEmulatorPkgTokenSpaceGuid.PcdEmuFirmwareBlockSize|0x10000 + gEmulatorPkgTokenSpaceGuid.PcdEmuFirmwareVolume|L"../FV/FV_RECOVERY.fd" + + gEmulatorPkgTokenSpaceGuid.PcdEmuMemorySizeForSecMain|L"64!64" + +!if $(BUILD_NEW_SHELL) + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile|{ 0x83, 0xA5, 0x04, 0x7C, 0x3E, 0x9E, 0x1C, 0x4F, 0xAD, 0x65, 0xE0, 0x52, 0x68, 0xD0, 0xB4, 0xD1 } +!else +!if $(USE_NEW_SHELL) + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile|{ 0x83, 0xA5, 0x04, 0x7C, 0x3E, 0x9E, 0x1C, 0x4F, 0xAD, 0x65, 0xE0, 0x52, 0x68, 0xD0, 0xB4, 0xD1 } +!endif +!endif + +#define BOOT_WITH_FULL_CONFIGURATION 0x00 +#define BOOT_WITH_MINIMAL_CONFIGURATION 0x01 +#define BOOT_ASSUMING_NO_CONFIGURATION_CHANGES 0x02 +#define BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS 0x03 +#define BOOT_WITH_DEFAULT_SETTINGS 0x04 +#define BOOT_ON_S4_RESUME 0x05 +#define BOOT_ON_S5_RESUME 0x06 +#define BOOT_ON_S2_RESUME 0x10 +#define BOOT_ON_S3_RESUME 0x11 +#define BOOT_ON_FLASH_UPDATE 0x12 +#define BOOT_IN_RECOVERY_MODE 0x20 + gEmulatorPkgTokenSpaceGuid.PcdEmuBootMode|0 + + gEmulatorPkgTokenSpaceGuid.PcdEmuApCount|L"1" + + # For a CD-ROM/DVD use L"diag.dmg:RO:2048" + gEmulatorPkgTokenSpaceGuid.PcdEmuVirtualDisk|L"disk.dmg:FW" + gEmulatorPkgTokenSpaceGuid.PcdEmuGop|L"GOP Window" + gEmulatorPkgTokenSpaceGuid.PcdEmuFileSystem|L".!../../../../EdkShellBinPkg/Bin" + gEmulatorPkgTokenSpaceGuid.PcdEmuSerialPort|L"/dev/ttyS0" + gEmulatorPkgTokenSpaceGuid.PcdEmuNetworkInterface|L"en0" + + gEmulatorPkgTokenSpaceGuid.PcdEmuCpuModel|L"Intel(R) Processor Model" + gEmulatorPkgTokenSpaceGuid.PcdEmuCpuSpeed|L"3000" + + # 0-PCANSI, 1-VT100, 2-VT00+, 3-UTF8 + gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType|1 + +################################################################################ +# +# Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Platform +# +################################################################################ + +[PcdsDynamicDefault.common.DEFAULT] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|0 + +[PcdsDynamicHii.common.DEFAULT] + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn|L"Setup"|gEmuSystemConfigGuid|0x0|80 + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|L"Setup"|gEmuSystemConfigGuid|0x4|25 + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPlatformBootTimeOut|L"Timeout"|gEfiGlobalVariableGuid|0x0|10 + + +################################################################################################### +# +# Components Section - list of the modules and components that will be processed by compilation +# tools and the EDK II tools to generate PE32/PE32+/Coff image files. +# +# Note: The EDK II DSC file is not used to specify how compiled binary images get placed +# into firmware volume images. This section is just a list of modules to compile from +# source into UEFI-compliant binaries. +# It is the FDF file that contains information on combining binary files into firmware +# volume images, whose concept is beyond UEFI and is described in PI specification. +# Binary modules do not need to be listed in this section, as they should be +# specified in the FDF file. For example: Shell binary (Shell_Full.efi), FAT binary (Fat.efi), +# Logo (Logo.bmp), and etc. +# There may also be modules listed in this section that are not required in the FDF file, +# When a module listed here is excluded from FDF file, then UEFI-compliant binary will be +# generated for it, but the binary will not be put into any firmware volume. +# +################################################################################################### + +!ifndef $(SKIP_MAIN_BUILD) +[Components.X64] + MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf { + + # turn off CR3 write so that DXE IPL will not crash emulator + BaseLib|UnixPkg/Library/UnixBaseLib/UnixBaseLib.inf + } + +[Components.IA32] + MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf +!endif + +[Components] +!ifdef $(UNIX_SEC_BUILD) + ## + # Emulator, OS POSIX application + ## + EmulatorPkg/Unix/Host/SecMain.inf +!endif + +!ifndef $(SKIP_MAIN_BUILD) + # + # Generic SEC + # + EmulatorPkg/Sec/Sec.inf + + ## + # PEI Phase modules + ## + MdeModulePkg/Core/Pei/PeiMain.inf + MdeModulePkg/Universal/PCD/Pei/Pcd.inf { + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + } + MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf + MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf + + IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.inf + EmulatorPkg/BootModePei/BootModePei.inf + MdeModulePkg/Universal/Variable/Pei/VariablePei.inf + EmulatorPkg/AutoScanPei/AutoScanPei.inf + EmulatorPkg/FirmwareVolumePei/FirmwareVolumePei.inf + EmulatorPkg/FlashMapPei/FlashMapPei.inf + EmulatorPkg/ThunkPpiToProtocolPei/ThunkPpiToProtocolPei.inf + + ## + # DXE Phase modules + ## + MdeModulePkg/Core/Dxe/DxeMain.inf { + + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + NULL|MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32GuidedSectionExtractLib.inf + NULL|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf + } + MdeModulePkg/Universal/PCD/Dxe/Pcd.inf { + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + } + + MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf + MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf { + + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + SerialPortLib|EmulatorPkg/Library/DxeEmuStdErrSerialPortLib/DxeEmuStdErrSerialPortLib.inf + } + + MdeModulePkg/Universal/Metronome/Metronome.inf + EmulatorPkg/RealTimeClockRuntimeDxe/RealTimeClock.inf + EmulatorPkg/ResetRuntimeDxe/Reset.inf + MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf + EmulatorPkg/FvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf + MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf + MdeModulePkg/Universal/EbcDxe/EbcDxe.inf + MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf + EmulatorPkg/EmuThunkDxe/EmuThunk.inf + EmulatorPkg/CpuRuntimeDxe/Cpu.inf + MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf + EmulatorPkg/MiscSubClassPlatformDxe/MiscSubClassDriver.inf + EmulatorPkg/TimerDxe/Timer.inf + + + MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf + MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf + MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf + MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf + MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf + MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf + MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf + EmbeddedPkg/SerialDxe/SerialDxe.inf { + + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + SerialPortLib|EmulatorPkg/Library/DxeEmuSerialPortLib/DxeEmuSerialPortLib.inf + } + + MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf + IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf + MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf + #{ + # + # NULL|EmulatorPkg/Library/DevicePathTextLib/DevicePathTextLib.inf + #} + + MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf + MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf + MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf + MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf + MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf + MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf + IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf + + EmulatorPkg/EmuBusDriverDxe/EmuBusDriverDxe.inf + EmulatorPkg/EmuGopDxe/EmuGopDxe.inf + EmulatorPkg/EmuSimpleFileSystemDxe/EmuSimpleFileSystemDxe.inf + EmulatorPkg/EmuBlockIoDxe/EmuBlockIoDxe.inf + EmulatorPkg/EmuSnpDxe/EmuSnpDxe.inf + + MdeModulePkg/Application/HelloWorld/HelloWorld.inf + + # + # Network stack drivers + # + MdeModulePkg/Universal/Network/DpcDxe/DpcDxe.inf + MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf + MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Dxe.inf + MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf + MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.inf + MdeModulePkg/Universal/Network/MnpDxe/MnpDxe.inf + MdeModulePkg/Universal/Network/VlanConfigDxe/VlanConfigDxe.inf + MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Dxe.inf + MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dxe.inf + MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Dxe.inf + + MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf + MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf + MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf + MdeModulePkg/Universal/PrintDxe/PrintDxe.inf + MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf { + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + } + +!if $(BUILD_FAT) + FatPkg/EnhancedFatDxe/Fat.inf +!endif + +!if $(BUILD_NEW_SHELL) + ShellPkg/Application/Shell/Shell.inf { + + ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf + NULL|ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf + NULL|ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf + NULL|ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf + NULL|ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf + NULL|ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf + NULL|ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf + NULL|ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf + HandleParsingLib|ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf + FileHandleLib|ShellPkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf + ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf + SortLib|ShellPkg/Library/UefiSortLib/UefiSortLib.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + MemoryAllocationLib|EmulatorPkg/Library/GuardUefiMemoryAllocationLib/GuardUefiMemoryAllocationLib.inf + SafeBlockIoLib|ShellPkg/Library/SafeBlockIoLib/SafeBlockIoLib.inf + SafeOpenProtocolLib|ShellPkg/Library/SafeOpenProtocolLib/SafeOpenProtocolLib.inf + + + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0xFF + gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE + gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|8000 + } +!endif + +!endif + diff --git a/EmulatorPkg/Unix/UnixX64.fdf b/EmulatorPkg/Unix/UnixX64.fdf new file mode 100644 index 0000000000..2977a9ff7b --- /dev/null +++ b/EmulatorPkg/Unix/UnixX64.fdf @@ -0,0 +1,395 @@ +## @file +# This is Unix FDF file with UEFI HII features enabled +# +# Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2009 - 2011, 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. +# + +################################################################################ +# +# FD Section +# The [FD] Section is made up of the definition statements and a +# description of what goes into the Flash Device Image. Each FD section +# defines one flash "device" image. A flash device image may be one of +# the following: Removable media bootable image (like a boot floppy +# image,) an Option ROM image (that would be "flashed" into an add-in +# card,) a System "Flash" image (that would be burned into a system's +# flash) or an Update ("Capsule") image that will be used to update and +# existing system flash. +# +################################################################################ +[FD.Fv_Recovery] +# +# In OS X PEIMs are really XIP, so we need to make this address match the malloced +# buffer for the FD (0x41000000). If this address does not match the FV will get +# relocated in place (works, but not a great idea). +# +BaseAddress = 0x102000000|gEmulatorPkgTokenSpaceGuid.PcdEmuFdBaseAddress #The base address of the FLASH Device. +Size = 0x005a0000|gEmulatorPkgTokenSpaceGuid.PcdEmuFirmwareFdSize #The size in bytes of the FLASH Device +ErasePolarity = 1 +BlockSize = 0x10000 +NumBlocks = 0x5a + +################################################################################ +# +# Following are lists of FD Region layout which correspond to the locations of different +# images within the flash device. +# +# Regions must be defined in ascending order and may not overlap. +# +# A Layout Region start with a eight digit hex offset (leading "0x" required) followed by +# the pipe "|" character, followed by the size of the region, also in hex with the leading +# "0x" characters. Like: +# Offset|Size +# PcdOffsetCName|PcdSizeCName +# RegionType +# +################################################################################ +0x00000000|0x00580000 +gEmulatorPkgTokenSpaceGuid.PcdEmuFlashFvRecoveryBase|gEmulatorPkgTokenSpaceGuid.PcdEmuFlashFvRecoverySize +FV = FvRecovery + +0x00580000|0x0000c000 +gEmulatorPkgTokenSpaceGuid.PcdEmuFlashNvStorageVariableBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize +#NV_VARIABLE_STORE +DATA = { + ## This is the EFI_FIRMWARE_VOLUME_HEADER + # ZeroVector [] + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + # FileSystemGuid: gEfiSystemNvDataFvGuid = + # { 0xFFF12B8D, 0x7696, 0x4C8B, { 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50 }} + 0x8D, 0x2B, 0xF1, 0xFF, 0x96, 0x76, 0x8B, 0x4C, + 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50, + # FvLength: 0x20000 + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + # Signature "_FVH" #Attributes + 0x5f, 0x46, 0x56, 0x48, 0xff, 0xfe, 0x04, 0x00, + # HeaderLength #CheckSum #ExtHeaderOffset #Reserved #Revision + 0x48, 0x00, 0x36, 0x09, 0x00, 0x00, 0x00, 0x02, + # Blockmap[0]: 2 Blocks * 0x10000 Bytes / Block + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + # Blockmap[1]: End + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ## This is the VARIABLE_STORE_HEADER + #Signature: gEfiVariableGuid = + # { 0xddcf3616, 0x3275, 0x4164, { 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d }} + 0x16, 0x36, 0xcf, 0xdd, 0x75, 0x32, 0x64, 0x41, + 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d, + #Size: 0xc000 (gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize) - 0x48 (size of EFI_FIRMWARE_VOLUME_HEADER) = 0xBFB8 + # This can speed up the Variable Dispatch a bit. + 0xB8, 0xBF, 0x00, 0x00, + #FORMATTED: 0x5A #HEALTHY: 0xFE #Reserved: UINT16 #Reserved1: UINT32 + 0x5A, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +} + +0x0058c000|0x00002000 +#NV_EVENT_LOG +gEmulatorPkgTokenSpaceGuid.PcdEmuFlashNvStorageEventLogBase|gEmulatorPkgTokenSpaceGuid.PcdEmuFlashNvStorageEventLogSize + +0x0058e000|0x00002000 +gEmulatorPkgTokenSpaceGuid.PcdEmuFlashNvStorageFtwWorkingBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize +#NV_FTW_WORKING +DATA = { + # EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER->Signature = gEfiSystemNvDataFvGuid = + # { 0xFFF12B8D, 0x7696, 0x4C8B, { 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50 }} + 0x8D, 0x2B, 0xF1, 0xFF, 0x96, 0x76, 0x8B, 0x4C, + 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50, + # Crc:UINT32 #WorkingBlockValid:1, WorkingBlockInvalid:1, Reserved + 0x77, 0x13, 0x9B, 0xD7, 0xFE, 0xFF, 0xFF, 0xFF, + # WriteQueueSize: UINT64 + 0xE0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +} + +0x00590000|0x00010000 +#NV_FTW_SPARE +gEmulatorPkgTokenSpaceGuid.PcdEmuFlashNvStorageFtwSpareBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize + +################################################################################ +# +# FV Section +# +# [FV] section is used to define what components or modules are placed within a flash +# device file. This section also defines order the components and modules are positioned +# within the image. The [FV] section consists of define statements, set statements and +# module statements. +# +################################################################################ +[FV.FvRecovery] +FvAlignment = 16 #FV alignment and FV attributes setting. +ERASE_POLARITY = 1 +MEMORY_MAPPED = TRUE +STICKY_WRITE = TRUE +LOCK_CAP = TRUE +LOCK_STATUS = TRUE +WRITE_DISABLED_CAP = TRUE +WRITE_ENABLED_CAP = TRUE +WRITE_STATUS = TRUE +WRITE_LOCK_CAP = TRUE +WRITE_LOCK_STATUS = TRUE +READ_DISABLED_CAP = TRUE +READ_ENABLED_CAP = TRUE +READ_STATUS = TRUE +READ_LOCK_CAP = TRUE +READ_LOCK_STATUS = TRUE + +################################################################################ +# +# The INF statements point to EDK component and EDK II module INF files, which will be placed into this FV image. +# Parsing tools will scan the INF file to determine the type of component or module. +# The component or module type is used to reference the standard rules +# defined elsewhere in the FDF file. +# +# The format for INF statements is: +# INF $(PathAndInfFileName) +# +################################################################################ +## +# PEI Phase modules +## +## +# PEI Apriori file example, more PEIM module added later. +## +APRIORI PEI { + INF MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf + INF MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf + INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf + } +APRIORI DXE { + INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf + INF MdeModulePkg/Universal/Metronome/Metronome.inf + } +INF EmulatorPkg/Sec/Sec.inf +INF MdeModulePkg/Core/Pei/PeiMain.inf +INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf +INF MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf +INF MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf +INF EmulatorPkg/BootModePei/BootModePei.inf +INF EmulatorPkg/AutoScanPei/AutoScanPei.inf +INF EmulatorPkg/FirmwareVolumePei/FirmwareVolumePei.inf +INF EmulatorPkg/FlashMapPei/FlashMapPei.inf +INF EmulatorPkg/ThunkPpiToProtocolPei/ThunkPpiToProtocolPei.inf +INF MdeModulePkg/Universal/Variable/Pei/VariablePei.inf +INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf + +## +# DXE Phase modules +## +INF MdeModulePkg/Core/Dxe/DxeMain.inf +INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf +INF MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf +INF MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf +INF MdeModulePkg/Universal/Metronome/Metronome.inf +INF EmulatorPkg/RealTimeClockRuntimeDxe/RealTimeClock.inf +INF EmulatorPkg/ResetRuntimeDxe/Reset.inf +INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf +INF EmulatorPkg/FvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf +INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf +INF MdeModulePkg/Universal/EbcDxe/EbcDxe.inf +INF MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf +INF EmulatorPkg/EmuThunkDxe/EmuThunk.inf +INF EmulatorPkg/CpuRuntimeDxe/Cpu.inf +INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf +INF EmulatorPkg/MiscSubClassPlatformDxe/MiscSubClassDriver.inf +INF EmulatorPkg/TimerDxe/Timer.inf +INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf +INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf +INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf +INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf +INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf +INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf +INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf + +INF EmbeddedPkg/SerialDxe/SerialDxe.inf +INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf +INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf +INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf +INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf +INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf +INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf +INF MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf +INF MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf +INF IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf +INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf + +INF EmulatorPkg/EmuBusDriverDxe/EmuBusDriverDxe.inf +INF EmulatorPkg/EmuGopDxe/EmuGopDxe.inf +INF EmulatorPkg/EmuSimpleFileSystemDxe/EmuSimpleFileSystemDxe.inf +INF EmulatorPkg/EmuBlockIoDxe/EmuBlockIoDxe.inf +INF EmulatorPkg/EmuSnpDxe/EmuSnpDxe.inf + +INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf +INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf +INF MdeModulePkg/Universal/PrintDxe/PrintDxe.inf +INF IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf +INF MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf +INF MdeModulePkg/Application/HelloWorld/HelloWorld.inf + +# +# Network stack drivers +# +!if $(NETWORK_SUPPORT) +INF EmulatorPkg/EmuSnpDxe/EmuSnpDxe.inf +!endif +INF MdeModulePkg/Universal/Network/DpcDxe/DpcDxe.inf +INF MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf +INF MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Dxe.inf +INF MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf +INF MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.inf +INF MdeModulePkg/Universal/Network/MnpDxe/MnpDxe.inf +INF MdeModulePkg/Universal/Network/VlanConfigDxe/VlanConfigDxe.inf +INF MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Dxe.inf +INF MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dxe.inf +INF MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Dxe.inf + + +!if $(BUILD_FAT) +INF FatPkg/EnhancedFatDxe/Fat.inf +!else +INF RuleOverride = BINARY FatBinPkg/EnhancedFatDxe/Fat.inf +!endif + +!if $(BUILD_NEW_SHELL) +INF ShellPkg/Application/Shell/Shell.inf +!else +!if $(USE_NEW_SHELL) +INF RuleOverride = BINARY ShellBinPkg/UefiShell/UefiShell.inf +!else +INF RuleOverride = BINARY EdkShellBinPkg/FullShell/FullShell.inf +!endif +!endif + +FILE FREEFORM = PCD(gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLogoFile) { + SECTION RAW = MdeModulePkg/Logo/Logo.bmp +} + + +################################################################################ +# +# Rules are use with the [FV] section's module INF type to define +# how an FFS file is created for a given INF file. The following Rule are the default +# rules for the different module type. User can add the customized rules to define the +# content of the FFS file. +# +################################################################################ + + +############################################################################ +# Example of a DXE_DRIVER FFS file with a Checksum encapsulation section # +############################################################################ +# +#[Rule.Common.DXE_DRIVER] +# FILE DRIVER = $(NAMED_GUID) { +# DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex +# COMPRESS PI_STD { +# GUIDED { +# PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi +# UI STRING="$(MODULE_NAME)" Optional +# VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) +# } +# } +# } +# +############################################################################ +[Rule.Common.SEC] + FILE SEC = $(NAMED_GUID) { + PE32 PE32 Align=32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING ="$(MODULE_NAME)" Optional + VERSION STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + + +[Rule.Common.PEI_CORE] + FILE PEI_CORE = $(NAMED_GUID) { + PE32 PE32 Align=32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING ="$(MODULE_NAME)" Optional + VERSION STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.PEIM] + FILE PEIM = $(NAMED_GUID) { + PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 Align=32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.DXE_CORE] + FILE DXE_CORE = $(NAMED_GUID) { + COMPRESS PI_STD { + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + } + +[Rule.Common.UEFI_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + COMPRESS PI_STD { + GUIDED { + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + } + } + +[Rule.Common.DXE_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + COMPRESS PI_STD { + GUIDED { + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + } + } + +[Rule.Common.DXE_RUNTIME_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + COMPRESS PI_STD { + GUIDED { + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + } + } + +[Rule.Common.UEFI_APPLICATION] + FILE APPLICATION = $(NAMED_GUID) { + COMPRESS PI_STD { + GUIDED { + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + } + } + +[Rule.Common.UEFI_DRIVER.BINARY] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.UEFI_APPLICATION.BINARY] + FILE APPLICATION = $(NAMED_GUID) { + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + diff --git a/EmulatorPkg/Unix/Xcode/xcode_project32/XcodeBuild.sh b/EmulatorPkg/Unix/Xcode/xcode_project32/XcodeBuild.sh new file mode 100755 index 0000000000..09d1a280d9 --- /dev/null +++ b/EmulatorPkg/Unix/Xcode/xcode_project32/XcodeBuild.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# +# External makefile Xcode project project uses this script to build and clean from the Xcode GUI +# +# Copyright (c) 2008 - 2011, 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. +# + +# force exit on error +set -e + +# +# Source the workspace and set up the environment variables we need +# +cd ../.. +echo `pwd` +./build.sh $1 $2 $3 $4 $5 $6 $8 diff --git a/EmulatorPkg/Unix/Xcode/xcode_project32/xcode_project.xcodeproj/default.pbxuser b/EmulatorPkg/Unix/Xcode/xcode_project32/xcode_project.xcodeproj/default.pbxuser new file mode 100644 index 0000000000..e2dfcb9f29 --- /dev/null +++ b/EmulatorPkg/Unix/Xcode/xcode_project32/xcode_project.xcodeproj/default.pbxuser @@ -0,0 +1,191 @@ +// !$*UTF8*$! +{ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + activeBuildConfigurationName = Debug; + activeExecutable = BA11A1010FB10BCE00D06FEC /* SecMain.dll */; + activeTarget = D28A88AD04BDD90700651E21 /* xcode_project */; + breakpoints = ( + BA11A11A0FB10E0700D06FEC /* SecGdbConfigBreak */, + ); + codeSenseManager = BA11A0FE0FB10B4800D06FEC /* Code sense */; + executables = ( + BA11A1010FB10BCE00D06FEC /* SecMain.dll */, + ); + perUserDictionary = { + "PBXConfiguration.PBXBreakpointsDataSource.v1:1CA1AED706398EBD00589147" = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXBreakpointsDataSource_BreakpointID; + PBXFileTableDataSourceColumnWidthsKey = ( + 20, + 20, + 198, + 20, + 99, + 99, + 29, + 20, + ); + PBXFileTableDataSourceColumnsKey = ( + PBXBreakpointsDataSource_ActionID, + PBXBreakpointsDataSource_TypeID, + PBXBreakpointsDataSource_BreakpointID, + PBXBreakpointsDataSource_UseID, + PBXBreakpointsDataSource_LocationID, + PBXBreakpointsDataSource_ConditionID, + PBXBreakpointsDataSource_IgnoreCountID, + PBXBreakpointsDataSource_ContinueID, + ); + }; + PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID; + PBXFileTableDataSourceColumnWidthsKey = ( + 22, + 300, + 229, + ); + PBXFileTableDataSourceColumnsKey = ( + PBXExecutablesDataSource_ActiveFlagID, + PBXExecutablesDataSource_NameID, + PBXExecutablesDataSource_CommentsID, + ); + }; + PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; + PBXFileTableDataSourceColumnWidthsKey = ( + 20, + 341, + 20, + 48, + 43, + 43, + 20, + ); + PBXFileTableDataSourceColumnsKey = ( + PBXFileDataSource_FiletypeID, + PBXFileDataSource_Filename_ColumnID, + PBXFileDataSource_Built_ColumnID, + PBXFileDataSource_ObjectSize_ColumnID, + PBXFileDataSource_Errors_ColumnID, + PBXFileDataSource_Warnings_ColumnID, + PBXFileDataSource_Target_ColumnID, + ); + }; + PBXPerProjectTemplateStateSaveDate = 263260969; + PBXWorkspaceStateSaveDate = 263260969; + }; + sourceControlManager = BA11A0FD0FB10B4800D06FEC /* Source Control */; + userBuildSettings = { + }; + }; + BA11A0FD0FB10B4800D06FEC /* Source Control */ = { + isa = PBXSourceControlManager; + fallbackIsa = XCSourceControlManager; + isSCMEnabled = 0; + repositoryNamesForRoots = { + }; + scmConfiguration = { + }; + }; + BA11A0FE0FB10B4800D06FEC /* Code sense */ = { + isa = PBXCodeSenseManager; + indexTemplatePath = ""; + }; + BA11A1010FB10BCE00D06FEC /* SecMain.dll */ = { + isa = PBXExecutable; + activeArgIndices = ( + ); + argumentStrings = ( + ); + autoAttachOnCrash = 1; + breakpointsEnabled = 1; + configStateDict = { + "PBXLSLaunchAction-0" = { + PBXLSLaunchAction = 0; + PBXLSLaunchStartAction = 1; + PBXLSLaunchStdioStyle = 2; + PBXLSLaunchStyle = 0; + class = PBXLSRunLaunchConfig; + commandLineArgs = ( + ); + displayName = "Executable Runner"; + environment = { + }; + identifier = com.apple.Xcode.launch.runConfig; + remoteHostInfo = ""; + startActionInfo = ""; + }; + "PBXLSLaunchAction-1" = { + PBXLSLaunchAction = 1; + PBXLSLaunchStartAction = 1; + PBXLSLaunchStdioStyle = 2; + PBXLSLaunchStyle = 0; + class = PBXGDB_LaunchConfig; + commandLineArgs = ( + ); + displayName = GDB; + environment = { + }; + identifier = com.apple.Xcode.launch.GDBMI_Config; + remoteHostInfo = ""; + startActionInfo = ""; + }; + }; + customDataFormattersEnabled = 0; + dataTipCustomDataFormattersEnabled = 1; + dataTipShowTypeColumn = 1; + dataTipSortType = 0; + debuggerPlugin = GDBDebugging; + disassemblyDisplayState = 0; + dylibVariantSuffix = ""; + enableDebugStr = 1; + environmentEntries = ( + ); + executableSystemSymbolLevel = 0; + executableUserSymbolLevel = 0; + launchableReference = BA11A1020FB10BCE00D06FEC /* SecMain.dll */; + libgmallocEnabled = 0; + name = SecMain.dll; + savedGlobals = { + }; + showTypeColumn = 0; + sourceDirectories = ( + ); + startupPath = ../../../../Build/EmuUnixIa32/DEBUG_XCLANG/IA32; + }; + BA11A1020FB10BCE00D06FEC /* SecMain.dll */ = { + isa = PBXFileReference; + lastKnownFileType = "compiled.mach-o.executable"; + name = SecMain.dll; + path = ../../../../Build/EmuUnixIa32/DEBUG_XCLANG/IA32/SecMain; + sourceTree = SOURCE_ROOT; + }; + BA11A11A0FB10E0700D06FEC /* SecGdbConfigBreak */ = { + isa = PBXSymbolicBreakpoint; + actions = ( + BA11A11E0FB10E2200D06FEC /* XCBreakpointCommandAction */, + ); + breakpointStyle = 1; + continueAfterActions = 1; + countType = 0; + delayBeforeContinue = 0; + hitCount = 0; + ignoreCount = 0; + location = SecMain; + modificationTime = 263261853.260195; + originalNumberOfMultipleMatches = 1; + state = 1; + symbolName = SecGdbConfigBreak; + }; + BA11A11E0FB10E2200D06FEC /* XCBreakpointCommandAction */ = { + isa = XCBreakpointCommandAction; + command = "set gInXcode=1\nsource ../../../../EmulatorPkg/Unix/GdbRun"; + fallbackIsa = XCBreakpointAction; + logCommand = 0; + useDebuggerSideImplementation = 1; + }; + D28A88AD04BDD90700651E21 /* xcode_project */ = { + activeExec = 0; + }; +} diff --git a/EmulatorPkg/Unix/Xcode/xcode_project32/xcode_project.xcodeproj/project.pbxproj b/EmulatorPkg/Unix/Xcode/xcode_project32/xcode_project.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..8ff531ef6c --- /dev/null +++ b/EmulatorPkg/Unix/Xcode/xcode_project32/xcode_project.xcodeproj/project.pbxproj @@ -0,0 +1,124 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 45; + objects = { + +/* Begin PBXGroup section */ + 08FB7794FE84155DC02AAC07 /* xcode_project */ = { + isa = PBXGroup; + children = ( + ); + name = xcode_project; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXLegacyTarget section */ + D28A88AD04BDD90700651E21 /* xcode_project */ = { + isa = PBXLegacyTarget; + buildArgumentsString = "$(ACTION)"; + buildConfigurationList = 1DEB918F08733D9F0010E9CD /* Build configuration list for PBXLegacyTarget "xcode_project" */; + buildPhases = ( + ); + buildToolPath = ./XcodeBuild.sh; + buildWorkingDirectory = ""; + dependencies = ( + ); + name = xcode_project; + passBuildSettingsInEnvironment = 1; + productName = xcode_project; + }; +/* End PBXLegacyTarget section */ + +/* Begin PBXProject section */ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = 1DEB919308733D9F0010E9CD /* Build configuration list for PBXProject "xcode_project" */; + compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 08FB7794FE84155DC02AAC07 /* xcode_project */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + D28A88AD04BDD90700651E21 /* xcode_project */, + ); + }; +/* End PBXProject section */ + +/* Begin XCBuildConfiguration section */ + 1DEB919008733D9F0010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = xcode_project; + }; + name = Debug; + }; + 1DEB919108733D9F0010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + PRODUCT_NAME = xcode_project; + }; + name = Release; + }; + 1DEB919408733D9F0010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + ONLY_ACTIVE_ARCH = YES; + PREBINDING = NO; + SDKROOT = macosx10.6; + }; + name = Debug; + }; + 1DEB919508733D9F0010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOT = macosx10.6; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB918F08733D9F0010E9CD /* Build configuration list for PBXLegacyTarget "xcode_project" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB919008733D9F0010E9CD /* Debug */, + 1DEB919108733D9F0010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB919308733D9F0010E9CD /* Build configuration list for PBXProject "xcode_project" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB919408733D9F0010E9CD /* Debug */, + 1DEB919508733D9F0010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; +} diff --git a/EmulatorPkg/Unix/Xcode/xcode_project64/XcodeBuild.sh b/EmulatorPkg/Unix/Xcode/xcode_project64/XcodeBuild.sh new file mode 100755 index 0000000000..634b1b025c --- /dev/null +++ b/EmulatorPkg/Unix/Xcode/xcode_project64/XcodeBuild.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# +# External makefile Xcode project project uses this script to build and clean from the Xcode GUI +# +# Copyright (c) 2008 - 2011, 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. +# + +# force exit on error +set -e + +# +# Source the workspace and set up the environment variables we need +# +cd ../.. +echo `pwd` +./build64.sh $1 $2 $3 $4 $5 $6 $8 diff --git a/EmulatorPkg/Unix/Xcode/xcode_project64/xcode_project.xcodeproj/default.pbxuser b/EmulatorPkg/Unix/Xcode/xcode_project64/xcode_project.xcodeproj/default.pbxuser new file mode 100644 index 0000000000..55c869f9fd --- /dev/null +++ b/EmulatorPkg/Unix/Xcode/xcode_project64/xcode_project.xcodeproj/default.pbxuser @@ -0,0 +1,191 @@ +// !$*UTF8*$! +{ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + activeBuildConfigurationName = Debug; + activeExecutable = BA11A1010FB10BCE00D06FEC /* SecMain.dll */; + activeTarget = D28A88AD04BDD90700651E21 /* xcode_project */; + breakpoints = ( + BA11A11A0FB10E0700D06FEC /* SecGdbConfigBreak */, + ); + codeSenseManager = BA11A0FE0FB10B4800D06FEC /* Code sense */; + executables = ( + BA11A1010FB10BCE00D06FEC /* SecMain.dll */, + ); + perUserDictionary = { + "PBXConfiguration.PBXBreakpointsDataSource.v1:1CA1AED706398EBD00589147" = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXBreakpointsDataSource_BreakpointID; + PBXFileTableDataSourceColumnWidthsKey = ( + 20, + 20, + 198, + 20, + 99, + 99, + 29, + 20, + ); + PBXFileTableDataSourceColumnsKey = ( + PBXBreakpointsDataSource_ActionID, + PBXBreakpointsDataSource_TypeID, + PBXBreakpointsDataSource_BreakpointID, + PBXBreakpointsDataSource_UseID, + PBXBreakpointsDataSource_LocationID, + PBXBreakpointsDataSource_ConditionID, + PBXBreakpointsDataSource_IgnoreCountID, + PBXBreakpointsDataSource_ContinueID, + ); + }; + PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID; + PBXFileTableDataSourceColumnWidthsKey = ( + 22, + 300, + 229, + ); + PBXFileTableDataSourceColumnsKey = ( + PBXExecutablesDataSource_ActiveFlagID, + PBXExecutablesDataSource_NameID, + PBXExecutablesDataSource_CommentsID, + ); + }; + PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; + PBXFileTableDataSourceColumnWidthsKey = ( + 20, + 341, + 20, + 48, + 43, + 43, + 20, + ); + PBXFileTableDataSourceColumnsKey = ( + PBXFileDataSource_FiletypeID, + PBXFileDataSource_Filename_ColumnID, + PBXFileDataSource_Built_ColumnID, + PBXFileDataSource_ObjectSize_ColumnID, + PBXFileDataSource_Errors_ColumnID, + PBXFileDataSource_Warnings_ColumnID, + PBXFileDataSource_Target_ColumnID, + ); + }; + PBXPerProjectTemplateStateSaveDate = 263260969; + PBXWorkspaceStateSaveDate = 263260969; + }; + sourceControlManager = BA11A0FD0FB10B4800D06FEC /* Source Control */; + userBuildSettings = { + }; + }; + BA11A0FD0FB10B4800D06FEC /* Source Control */ = { + isa = PBXSourceControlManager; + fallbackIsa = XCSourceControlManager; + isSCMEnabled = 0; + repositoryNamesForRoots = { + }; + scmConfiguration = { + }; + }; + BA11A0FE0FB10B4800D06FEC /* Code sense */ = { + isa = PBXCodeSenseManager; + indexTemplatePath = ""; + }; + BA11A1010FB10BCE00D06FEC /* SecMain.dll */ = { + isa = PBXExecutable; + activeArgIndices = ( + ); + argumentStrings = ( + ); + autoAttachOnCrash = 1; + breakpointsEnabled = 1; + configStateDict = { + "PBXLSLaunchAction-0" = { + PBXLSLaunchAction = 0; + PBXLSLaunchStartAction = 1; + PBXLSLaunchStdioStyle = 2; + PBXLSLaunchStyle = 0; + class = PBXLSRunLaunchConfig; + commandLineArgs = ( + ); + displayName = "Executable Runner"; + environment = { + }; + identifier = com.apple.Xcode.launch.runConfig; + remoteHostInfo = ""; + startActionInfo = ""; + }; + "PBXLSLaunchAction-1" = { + PBXLSLaunchAction = 1; + PBXLSLaunchStartAction = 1; + PBXLSLaunchStdioStyle = 2; + PBXLSLaunchStyle = 0; + class = PBXGDB_LaunchConfig; + commandLineArgs = ( + ); + displayName = GDB; + environment = { + }; + identifier = com.apple.Xcode.launch.GDBMI_Config; + remoteHostInfo = ""; + startActionInfo = ""; + }; + }; + customDataFormattersEnabled = 0; + dataTipCustomDataFormattersEnabled = 1; + dataTipShowTypeColumn = 1; + dataTipSortType = 0; + debuggerPlugin = GDBDebugging; + disassemblyDisplayState = 0; + dylibVariantSuffix = ""; + enableDebugStr = 1; + environmentEntries = ( + ); + executableSystemSymbolLevel = 0; + executableUserSymbolLevel = 0; + launchableReference = BA11A1020FB10BCE00D06FEC /* SecMain.dll */; + libgmallocEnabled = 0; + name = SecMain.dll; + savedGlobals = { + }; + showTypeColumn = 0; + sourceDirectories = ( + ); + startupPath = ../../../../Build/EmuUnixX64/DEBUG_XCLANG/X64; + }; + BA11A1020FB10BCE00D06FEC /* SecMain.dll */ = { + isa = PBXFileReference; + lastKnownFileType = "compiled.mach-o.executable"; + name = SecMain.dll; + path = ../../../../Build/EmuUnixX64/DEBUG_XCLANG/X64/SecMain; + sourceTree = SOURCE_ROOT; + }; + BA11A11A0FB10E0700D06FEC /* SecGdbConfigBreak */ = { + isa = PBXSymbolicBreakpoint; + actions = ( + BA11A11E0FB10E2200D06FEC /* XCBreakpointCommandAction */, + ); + breakpointStyle = 1; + continueAfterActions = 1; + countType = 0; + delayBeforeContinue = 0; + hitCount = 0; + ignoreCount = 0; + location = SecMain; + modificationTime = 263261853.260195; + originalNumberOfMultipleMatches = 1; + state = 1; + symbolName = SecGdbConfigBreak; + }; + BA11A11E0FB10E2200D06FEC /* XCBreakpointCommandAction */ = { + isa = XCBreakpointCommandAction; + command = "set gInXcode=1\nsource ../../../../EmulatorPkg/Unix/GdbRun"; + fallbackIsa = XCBreakpointAction; + logCommand = 0; + useDebuggerSideImplementation = 1; + }; + D28A88AD04BDD90700651E21 /* xcode_project */ = { + activeExec = 0; + }; +} diff --git a/EmulatorPkg/Unix/Xcode/xcode_project64/xcode_project.xcodeproj/project.pbxproj b/EmulatorPkg/Unix/Xcode/xcode_project64/xcode_project.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..9bd13bd63f --- /dev/null +++ b/EmulatorPkg/Unix/Xcode/xcode_project64/xcode_project.xcodeproj/project.pbxproj @@ -0,0 +1,124 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 45; + objects = { + +/* Begin PBXGroup section */ + 08FB7794FE84155DC02AAC07 /* xcode_project */ = { + isa = PBXGroup; + children = ( + ); + name = xcode_project; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXLegacyTarget section */ + D28A88AD04BDD90700651E21 /* xcode_project */ = { + isa = PBXLegacyTarget; + buildArgumentsString = "$(ACTION)"; + buildConfigurationList = 1DEB918F08733D9F0010E9CD /* Build configuration list for PBXLegacyTarget "xcode_project" */; + buildPhases = ( + ); + buildToolPath = ./XcodeBuild.sh; + buildWorkingDirectory = ""; + dependencies = ( + ); + name = xcode_project; + passBuildSettingsInEnvironment = 1; + productName = xcode_project; + }; +/* End PBXLegacyTarget section */ + +/* Begin PBXProject section */ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = 1DEB919308733D9F0010E9CD /* Build configuration list for PBXProject "xcode_project" */; + compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 08FB7794FE84155DC02AAC07 /* xcode_project */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + D28A88AD04BDD90700651E21 /* xcode_project */, + ); + }; +/* End PBXProject section */ + +/* Begin XCBuildConfiguration section */ + 1DEB919008733D9F0010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = xcode_project; + }; + name = Debug; + }; + 1DEB919108733D9F0010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + PRODUCT_NAME = xcode_project; + }; + name = Release; + }; + 1DEB919408733D9F0010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + ONLY_ACTIVE_ARCH = YES; + PREBINDING = NO; + SDKROOT = macosx10.6; + }; + name = Debug; + }; + 1DEB919508733D9F0010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOT = macosx10.6; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB918F08733D9F0010E9CD /* Build configuration list for PBXLegacyTarget "xcode_project" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB919008733D9F0010E9CD /* Debug */, + 1DEB919108733D9F0010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB919308733D9F0010E9CD /* Build configuration list for PBXProject "xcode_project" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB919408733D9F0010E9CD /* Debug */, + 1DEB919508733D9F0010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; +} diff --git a/EmulatorPkg/Unix/build.sh b/EmulatorPkg/Unix/build.sh new file mode 100755 index 0000000000..b7dc0bb109 --- /dev/null +++ b/EmulatorPkg/Unix/build.sh @@ -0,0 +1,137 @@ +#!/bin/bash +# +# Copyright (c) 2008 - 2011, Apple Inc. All rights reserved.
+# Copyright (c) 2010, Intel Corporation. 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. +# + +set -e +shopt -s nocasematch + + +# +# Setup workspace if it is not set +# +if [ -z "$WORKSPACE" ] +then + echo Initializing workspace + if [ ! -e `pwd`/edksetup.sh ] + then + cd ../.. + fi +# This version is for the tools in the BaseTools project. +# this assumes svn pulls have the same root dir +# export EDK_TOOLS_PATH=`pwd`/../BaseTools +# This version is for the tools source in edk2 + export EDK_TOOLS_PATH=`pwd`/BaseTools + echo $EDK_TOOLS_PATH + source edksetup.sh BaseTools +else + echo Building from: $WORKSPACE +fi + +# +# Pick a default tool type for a given OS +# +UNIXPKG_TOOLS=GCC44 +NETWORK_SUPPORT= +BUILD_NEW_SHELL= +BUILD_FAT= +case `uname` in + CYGWIN*) echo Cygwin not fully supported yet. ;; + Darwin*) + Major=$(uname -r | cut -f 1 -d '.') + if [[ $Major == 9 ]] + then + echo UnixPkg requires Snow Leopard or later OS + exit 1 + else + TARGET_TOOLS=XCODE32 + UNIXPKG_TOOLS=XCLANG + fi + BUILD_NEW_SHELL="-D BUILD_NEW_SHELL" + BUILD_FAT="-D BUILD_FAT" + ;; +esac + +if [ -d /lib32 ] +then + export LIB_ARCH_SFX=32 +fi + +if [ -z "$TARGET_TOOLS" ] +then + TARGET_TOOLS=$UNIXPKG_TOOLS +fi + +BUILD_ROOT_ARCH=$WORKSPACE/Build/EmuUnixIa32/DEBUG_"$UNIXPKG_TOOLS"/IA32 + +if [[ ! -f `which build` || ! -f `which GenFv` ]]; +then + # build the tools if they don't yet exist. Bin scheme + echo Building tools as they are not in the path + make -C $WORKSPACE/BaseTools +elif [[ ( -f `which build` || -f `which GenFv` ) && ! -d $EDK_TOOLS_PATH/Source/C/bin ]]; +then + # build the tools if they don't yet exist. BinWrapper scheme + echo Building tools no $EDK_TOOLS_PATH/Source/C/bin directory + make -C $WORKSPACE/BaseTools +else + echo using prebuilt tools +fi + + +for arg in "$@" +do + if [[ $arg == run ]]; then + case `uname` in + Darwin*) + # + # On Darwin we can't use dlopen, so we have to load the real PE/COFF images. + # This .gdbinit script sets a breakpoint that loads symbols for the PE/COFFEE + # images that get loaded in SecMain + # + cp $WORKSPACE/EmulatorPkg/Unix/.gdbinit $WORKSPACE/Build/EmuUnixIa32/DEBUG_"$UNIXPKG_TOOLS"/IA32 + ;; + esac + + /usr/bin/gdb $BUILD_ROOT_ARCH/SecMain -q -cd=$BUILD_ROOT_ARCH -x $WORKSPACE/EmulatorPkg/Unix/GdbRun + exit + fi + + if [[ $arg == cleanall ]]; then + make -C $WORKSPACE/BaseTools clean + build -p $WORKSPACE/EmulatorPkg/Unix/UnixX64.dsc -a IA32 -t $TARGET_TOOLS -D SEC_ONLY -n 3 clean + build -p $WORKSPACE/EmulatorPkg/Unix/UnixX64.dsc -a IA32 -t $UNIXPKG_TOOLS -n 3 clean + build -p $WORKSPACE/ShellPkg/ShellPkg.dsc -a IA32 -t $UNIXPKG_TOOLS -n 3 clean + exit $? + fi + + if [[ $arg == clean ]]; then + build -p $WORKSPACE/EmulatorPkg/Unix/UnixX64.dsc -a IA32 -t $TARGET_TOOLS -D SEC_ONLY -n 3 clean + build -p $WORKSPACE/EmulatorPkg/Unix/UnixX64.dsc -a IA32 -t $UNIXPKG_TOOLS -n 3 clean + exit $? + fi + +done + + +# +# Build the edk2 UnixPkg +# +if [[ $TARGET_TOOLS == $UNIXPKG_TOOLS ]]; then + build -p $WORKSPACE/EmulatorPkg/Unix/UnixX64.dsc -a IA32 -t $UNIXPKG_TOOLS -D BUILD_32 -D UNIX_SEC_BUILD $NETWORK_SUPPORT $BUILD_NEW_SHELL $BUILD_FAT -n 3 $1 $2 $3 $4 $5 $6 $7 $8 +else + build -p $WORKSPACE/EmulatorPkg/Unix/UnixX64.dsc -a IA32 -t $TARGET_TOOLS -D BUILD_32 -D UNIX_SEC_BUILD -D SKIP_MAIN_BUILD -n 3 $1 $2 $3 $4 $5 $6 $7 $8 modules + build -p $WORKSPACE/EmulatorPkg/Unix/UnixX64.dsc -a IA32 -t $UNIXPKG_TOOLS -D BUILD_32 $NETWORK_SUPPORT $BUILD_NEW_SHELL $BUILD_FAT -n 3 $1 $2 $3 $4 $5 $6 $7 $8 + cp $WORKSPACE/Build/EmuUnixIa32/DEBUG_"$TARGET_TOOLS"/IA32/SecMain $WORKSPACE/Build/EmuUnixIa32/DEBUG_"$UNIXPKG_TOOLS"/IA32 +fi +exit $? + diff --git a/EmulatorPkg/Unix/build64.sh b/EmulatorPkg/Unix/build64.sh new file mode 100755 index 0000000000..25d14dfc67 --- /dev/null +++ b/EmulatorPkg/Unix/build64.sh @@ -0,0 +1,138 @@ +#!/bin/bash +# +# Copyright (c) 2008 - 2011, Apple Inc. All rights reserved.
+# Copyright (c) 2010 - 2011, Intel Corporation. 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. +# + +set -e +shopt -s nocasematch + + +# +# Setup workspace if it is not set +# +if [ -z "$WORKSPACE" ] +then + echo Initializing workspace + if [ ! -e `pwd`/edksetup.sh ] + then + cd ../.. + fi +# This version is for the tools in the BaseTools project. +# this assumes svn pulls have the same root dir +# export EDK_TOOLS_PATH=`pwd`/../BaseTools +# This version is for the tools source in edk2 + export EDK_TOOLS_PATH=`pwd`/BaseTools + echo $EDK_TOOLS_PATH + source edksetup.sh BaseTools +else + echo Building from: $WORKSPACE +fi + +# +# Pick a default tool type for a given OS +# +UNIXPKG_TOOLS=GCC44 +NETWORK_SUPPORT= +BUILD_NEW_SHELL= +BUILD_FAT= +case `uname` in + CYGWIN*) echo Cygwin not fully supported yet. ;; + Darwin*) + Major=$(uname -r | cut -f 1 -d '.') + if [[ $Major == 9 ]] + then + echo UnixPkg requires Snow Leopard or later OS + exit 1 + else + TARGET_TOOLS=XCODE32 + UNIXPKG_TOOLS=XCLANG + fi +# NETWORK_SUPPORT="-D NETWORK_SUPPORT" + BUILD_NEW_SHELL="-D BUILD_NEW_SHELL" + BUILD_FAT="-D BUILD_FAT" + ;; +esac + +if [ -d /lib64 ] +then + export LIB_ARCH_SFX=64 +fi + +if [ -z "$TARGET_TOOLS" ] +then + TARGET_TOOLS=$UNIXPKG_TOOLS +fi + +BUILD_ROOT_ARCH=$WORKSPACE/Build/EmuUnixX64/DEBUG_"$UNIXPKG_TOOLS"/X64 + +if [[ ! -f `which build` || ! -f `which GenFv` ]]; +then + # build the tools if they don't yet exist. Bin scheme + echo Building tools as they are not in the path + make -C $WORKSPACE/BaseTools +elif [[ ( -f `which build` || -f `which GenFv` ) && ! -d $EDK_TOOLS_PATH/Source/C/bin ]]; +then + # build the tools if they don't yet exist. BinWrapper scheme + echo Building tools no $EDK_TOOLS_PATH/Source/C/bin directory + make -C $WORKSPACE/BaseTools +else + echo using prebuilt tools +fi + + +for arg in "$@" +do + if [[ $arg == run ]]; then + case `uname` in + Darwin*) + # + # On Darwin we can't use dlopen, so we have to load the real PE/COFF images. + # This .gdbinit script sets a breakpoint that loads symbols for the PE/COFFEE + # images that get loaded in SecMain + # + cp $WORKSPACE/EmulatorPkg/Unix/.gdbinit $WORKSPACE/Build/EmuUnixX64/DEBUG_"$UNIXPKG_TOOLS"/X64 + ;; + esac + + /usr/bin/gdb $BUILD_ROOT_ARCH/SecMain -q -cd=$BUILD_ROOT_ARCH -x $WORKSPACE/EmulatorPkg/Unix/GdbRun + exit + fi + + if [[ $arg == cleanall ]]; then + make -C $WORKSPACE/BaseTools clean + build -p $WORKSPACE/EmulatorPkg/Unix/UnixX64.dsc -a X64 -t $TARGET_TOOLS -D SEC_ONLY -n 3 clean + build -p $WORKSPACE/EmulatorPkg/Unix/UnixX64.dsc -a X64 -t $UNIXPKG_TOOLS -n 3 clean + build -p $WORKSPACE/ShellPkg/ShellPkg.dsc -a X64 -t $UNIXPKG_TOOLS -n 3 clean + exit $? + fi + + if [[ $arg == clean ]]; then + build -p $WORKSPACE/EmulatorPkg/Unix/UnixX64.dsc -a X64 -t $TARGET_TOOLS -D SEC_ONLY -n 3 clean + build -p $WORKSPACE/EmulatorPkg/Unix/UnixX64.dsc -a X64 -t $UNIXPKG_TOOLS -n 3 clean + exit $? + fi + +done + + +# +# Build the edk2 UnixPkg +# +if [[ $TARGET_TOOLS == $UNIXPKG_TOOLS ]]; then + build -p $WORKSPACE/EmulatorPkg/Unix/UnixX64.dsc -a X64 -t $UNIXPKG_TOOLS -D UNIX_SEC_BUILD $NETWORK_SUPPORT $BUILD_NEW_SHELL $BUILD_FAT -n 3 $1 $2 $3 $4 $5 $6 $7 $8 +else + build -p $WORKSPACE/EmulatorPkg/Unix/UnixX64.dsc -a X64 -t $TARGET_TOOLS -D UNIX_SEC_BUILD -D SKIP_MAIN_BUILD -n 3 $1 $2 $3 $4 $5 $6 $7 $8 modules + build -p $WORKSPACE/EmulatorPkg/Unix/UnixX64.dsc -a X64 -t $UNIXPKG_TOOLS $NETWORK_SUPPORT $BUILD_NEW_SHELL $BUILD_FAT -n 3 $1 $2 $3 $4 $5 $6 $7 $8 + cp $WORKSPACE/Build/EmuUnixX64/DEBUG_"$TARGET_TOOLS"/X64/SecMain $WORKSPACE/Build/EmuUnixX64/DEBUG_"$UNIXPKG_TOOLS"/X64 +fi +exit $? + -- cgit v1.2.3