/*++ @file

Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
Portions copyright (c) 2008 - 2011, Apple Inc. All rights reserved.<BR>

SPDX-License-Identifier: BSD-2-Clause-Patent

**/

#pragma once

//
// Name mangle to prevent build errors. I.e conflicts between EFI and OS
//
#define NTOHL   _UNIX_EFI_NAME_MANGLE_NTOHL_
#define NTOHLL  _UNIX_EFI_NAME_MANGLE_NTOHLL_
#define HTONL   _UNIX_EFI_NAME_MANGLE_HTONL_
#define HTONLL  _UNIX_EFI_NAME_MANGLE_HTONLL_
#define NTOHS   _UNIX_EFI_NAME_MANGLE_NTOHS_
#define HTONS   _UNIX_EFI_NAME_MANGLE_HTOHS_
#define B0      _UNIX_EFI_NAME_MANGLE_B0_

#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/termios.h>
#include <sys/time.h>

#if __CYGWIN__
  #include <sys/dirent.h>
#else
  #include <sys/dir.h>
#endif

#include <sys/mman.h>
#include <dlfcn.h>

#include <unistd.h>
#include <poll.h>
#include <fcntl.h>
#include <time.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/statvfs.h>

#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <net/if.h>
#include <ifaddrs.h>

#ifdef __APPLE__
  #include <net/if_dl.h>
  #include <net/bpf.h>
  #include <sys/param.h>
  #include <sys/mount.h>
  #include <sys/disk.h>
#define _XOPEN_SOURCE
  #ifndef _Bool
#define _Bool  char  // for clang debug
  #endif
#else
  #include <sys/vfs.h>
  #include <linux/fs.h>
#endif

#include <utime.h>

#undef NTOHL
#undef NTOHLL
#undef HTONL
#undef HTONLL
#undef NTOHS
#undef HTONS
#undef B0
#undef CR3

#include <PiPei.h>
#include <Uefi.h>

#include <Library/PeCoffLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/PrintLib.h>
#include <Library/PcdLib.h>
#include <Library/DebugLib.h>
#include <Library/ReportStatusCodeLib.h>

#include <Library/ThunkPpiList.h>
#include <Library/ThunkProtocolList.h>
#include <Library/PeiServicesLib.h>
#include <Library/PeCoffGetEntryPointLib.h>
#include <Library/EmuMagicPageLib.h>

#include <Ppi/EmuThunk.h>
#include <Ppi/StatusCode.h>

#include <Protocol/SimplePointer.h>
#include <Protocol/SimpleTextIn.h>
#include <Protocol/SimpleTextInEx.h>
#include <Protocol/SimpleFileSystem.h>

#include <Protocol/EmuThunk.h>
#include <Protocol/EmuIoThunk.h>
#include <Protocol/EmuGraphicsWindow.h>
#include <Protocol/EmuThread.h>
#include <Protocol/EmuBlockIo.h>
#include <Protocol/EmuSnp.h>

#include <Guid/FileInfo.h>
#include <Guid/FileSystemInfo.h>
#include <Guid/FileSystemVolumeLabelInfo.h>

#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
CountSeparatorsInString (
  IN  const CHAR16  *String,
  IN  CHAR16        Separator
  );

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;
