/*++ @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

**/

#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 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 <termio.h>
#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/UgaDraw.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;

#endif