diff options
Diffstat (limited to 'EdkUnixPkg/Sec')
-rw-r--r-- | EdkUnixPkg/Sec/FwVol.c | 314 | ||||
-rw-r--r-- | EdkUnixPkg/Sec/SecMain.c | 995 | ||||
-rw-r--r-- | EdkUnixPkg/Sec/SecMain.h | 529 | ||||
-rw-r--r-- | EdkUnixPkg/Sec/SecMain.msa | 113 | ||||
-rw-r--r-- | EdkUnixPkg/Sec/SecMain_build.xml | 143 | ||||
-rw-r--r-- | EdkUnixPkg/Sec/UgaX11.c | 580 | ||||
-rw-r--r-- | EdkUnixPkg/Sec/UnixThunk.c | 189 |
7 files changed, 2863 insertions, 0 deletions
diff --git a/EdkUnixPkg/Sec/FwVol.c b/EdkUnixPkg/Sec/FwVol.c new file mode 100644 index 0000000..25ebe07 --- /dev/null +++ b/EdkUnixPkg/Sec/FwVol.c @@ -0,0 +1,314 @@ +/*++
+
+Copyright (c) 2006, 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.
+
+Module Name:
+ FwVol.c
+
+Abstract:
+ A simple FV stack so the SEC can extract the SEC Core from an
+ FV.
+
+--*/
+
+#include "SecMain.h"
+
+#define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
+ (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))
+
+EFI_FFS_FILE_STATE
+GetFileState (
+ IN UINT8 ErasePolarity,
+ IN EFI_FFS_FILE_HEADER *FfsHeader
+ )
+/*++
+
+Routine Description:
+ Returns the highest bit set of the State field
+
+Arguments:
+ ErasePolarity - Erase Polarity as defined by EFI_FVB_ERASE_POLARITY
+ in the Attributes field.
+ FfsHeader - Pointer to FFS File Header.
+
+Returns:
+ Returns the highest bit in the State field
+
+--*/
+{
+ EFI_FFS_FILE_STATE FileState;
+ EFI_FFS_FILE_STATE HighestBit;
+
+ FileState = FfsHeader->State;
+
+ if (ErasePolarity != 0) {
+ FileState = (EFI_FFS_FILE_STATE)~FileState;
+ }
+
+ HighestBit = 0x80;
+ while (HighestBit != 0 && (HighestBit & FileState) == 0) {
+ HighestBit >>= 1;
+ }
+
+ return HighestBit;
+}
+
+UINT8
+CalculateHeaderChecksum (
+ IN EFI_FFS_FILE_HEADER *FileHeader
+ )
+/*++
+
+Routine Description:
+ Calculates the checksum of the header of a file.
+
+Arguments:
+ FileHeader - Pointer to FFS File Header.
+
+Returns:
+ Checksum of the header.
+
+--*/
+{
+ UINT8 *ptr;
+ UINTN Index;
+ UINT8 Sum;
+
+ Sum = 0;
+ ptr = (UINT8 *) FileHeader;
+
+ for (Index = 0; Index < sizeof (EFI_FFS_FILE_HEADER) - 3; Index += 4) {
+ Sum = (UINT8) (Sum + ptr[Index]);
+ Sum = (UINT8) (Sum + ptr[Index + 1]);
+ Sum = (UINT8) (Sum + ptr[Index + 2]);
+ Sum = (UINT8) (Sum + ptr[Index + 3]);
+ }
+
+ for (; Index < sizeof (EFI_FFS_FILE_HEADER); Index++) {
+ Sum = (UINT8) (Sum + ptr[Index]);
+ }
+ //
+ // State field (since this indicates the different state of file).
+ //
+ Sum = (UINT8) (Sum - FileHeader->State);
+ //
+ // Checksum field of the file is not part of the header checksum.
+ //
+ Sum = (UINT8) (Sum - FileHeader->IntegrityCheck.Checksum.File);
+
+ return Sum;
+}
+
+EFI_STATUS
+SecFfsFindNextFile (
+ IN EFI_FV_FILETYPE SearchType,
+ IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader,
+ IN OUT EFI_FFS_FILE_HEADER **FileHeader
+ )
+/*++
+
+Routine Description:
+ Given the input file pointer, search for the next matching file in the
+ FFS volume as defined by SearchType. The search starts from FileHeader inside
+ the Firmware Volume defined by FwVolHeader.
+
+Arguments:
+ SearchType - Filter to find only files of this type.
+ Type EFI_FV_FILETYPE_ALL causes no filtering to be done.
+ FwVolHeader - Pointer to the FV header of the volume to search.
+ This parameter must point to a valid FFS volume.
+ FileHeader - Pointer to the current file from which to begin searching.
+ This pointer will be updated upon return to reflect the file
+ found.
+
+Returns:
+ EFI_NOT_FOUND - No files matching the search criteria were found
+ EFI_SUCCESS
+
+--*/
+{
+ EFI_FFS_FILE_HEADER *FfsFileHeader;
+ UINT32 FileLength;
+ UINT32 FileOccupiedSize;
+ UINT32 FileOffset;
+ UINT64 FvLength;
+ UINT8 ErasePolarity;
+ UINT8 FileState;
+
+ FvLength = FwVolHeader->FvLength;
+ if (FwVolHeader->Attributes & EFI_FVB_ERASE_POLARITY) {
+ ErasePolarity = 1;
+ } else {
+ ErasePolarity = 0;
+ }
+ //
+ // If FileHeader is not specified (NULL) start with the first file in the
+ // firmware volume. Otherwise, start from the FileHeader.
+ //
+ if (*FileHeader == NULL) {
+ FfsFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FwVolHeader + FwVolHeader->HeaderLength);
+ } else {
+ //
+ // Length is 24 bits wide so mask upper 8 bits
+ // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned.
+ //
+ FileLength = *(UINT32 *) (*FileHeader)->Size & 0x00FFFFFF;
+ FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8);
+ FfsFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) *FileHeader + FileOccupiedSize);
+ }
+
+ FileOffset = (UINT32) ((UINT8 *) FfsFileHeader - (UINT8 *) FwVolHeader);
+
+ while (FileOffset < (FvLength - sizeof (EFI_FFS_FILE_HEADER))) {
+ //
+ // Get FileState which is the highest bit of the State
+ //
+ FileState = GetFileState (ErasePolarity, FfsFileHeader);
+
+ switch (FileState) {
+
+ case EFI_FILE_HEADER_INVALID:
+ FileOffset += sizeof (EFI_FFS_FILE_HEADER);
+ FfsFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER));
+ break;
+
+ case EFI_FILE_DATA_VALID:
+ case EFI_FILE_MARKED_FOR_UPDATE:
+ if (CalculateHeaderChecksum (FfsFileHeader) == 0) {
+ FileLength = *(UINT32 *) (FfsFileHeader->Size) & 0x00FFFFFF;
+ FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8);
+
+ if ((SearchType == FfsFileHeader->Type) || (SearchType == EFI_FV_FILETYPE_ALL)) {
+
+ *FileHeader = FfsFileHeader;
+
+ return EFI_SUCCESS;
+ }
+
+ FileOffset += FileOccupiedSize;
+ FfsFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsFileHeader + FileOccupiedSize);
+ } else {
+ return EFI_NOT_FOUND;
+ }
+ break;
+
+ case EFI_FILE_DELETED:
+ FileLength = *(UINT32 *) (FfsFileHeader->Size) & 0x00FFFFFF;
+ FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8);
+ FileOffset += FileOccupiedSize;
+ FfsFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsFileHeader + FileOccupiedSize);
+ break;
+
+ default:
+ return EFI_NOT_FOUND;
+
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+SecFfsFindSectionData (
+ IN EFI_SECTION_TYPE SectionType,
+ IN EFI_FFS_FILE_HEADER *FfsFileHeader,
+ IN OUT VOID **SectionData
+ )
+/*++
+
+Routine Description:
+ Given the input file pointer, search for the next matching section in the
+ FFS volume.
+
+Arguments:
+ SearchType - Filter to find only sections of this type.
+ FfsFileHeader - Pointer to the current file to search.
+ SectionData - Pointer to the Section matching SectionType in FfsFileHeader.
+ NULL if section not found
+
+Returns:
+ EFI_NOT_FOUND - No files matching the search criteria were found
+ EFI_SUCCESS
+
+--*/
+{
+ UINT32 FileSize;
+ EFI_COMMON_SECTION_HEADER *Section;
+ UINT32 SectionLength;
+ UINT32 ParsedLength;
+
+ //
+ // Size is 24 bits wide so mask upper 8 bits.
+ // Does not include FfsFileHeader header size
+ // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned.
+ //
+ Section = (EFI_COMMON_SECTION_HEADER *) (FfsFileHeader + 1);
+ FileSize = *(UINT32 *) (FfsFileHeader->Size) & 0x00FFFFFF;
+ FileSize -= sizeof (EFI_FFS_FILE_HEADER);
+
+ *SectionData = NULL;
+ ParsedLength = 0;
+ while (ParsedLength < FileSize) {
+ if (Section->Type == SectionType) {
+ *SectionData = (VOID *) (Section + 1);
+ return EFI_SUCCESS;
+ }
+ //
+ // Size is 24 bits wide so mask upper 8 bits.
+ // SectionLength is adjusted it is 4 byte aligned.
+ // Go to the next section
+ //
+ SectionLength = *(UINT32 *) Section->Size & 0x00FFFFFF;
+ SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);
+
+ ParsedLength += SectionLength;
+ Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + SectionLength);
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+SecFfsFindPeiCore (
+ IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader,
+ OUT VOID **Pe32Data
+ )
+/*++
+
+Routine Description:
+ Given the pointer to the Firmware Volume Header find the SEC
+ core and return it's PE32 image.
+
+Arguments:
+ FwVolHeader - Pointer to memory mapped FV
+ Pe32Data - Pointer to SEC PE32 iamge.
+
+Returns:
+ EFI_SUCCESS - Pe32Data is valid
+ other - Failure
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_FFS_FILE_HEADER *FileHeader;
+ EFI_FV_FILETYPE SearchType;
+
+ SearchType = EFI_FV_FILETYPE_PEI_CORE;
+ FileHeader = NULL;
+ do {
+ Status = SecFfsFindNextFile (SearchType, FwVolHeader, &FileHeader);
+ if (!EFI_ERROR (Status)) {
+ Status = SecFfsFindSectionData (EFI_SECTION_PE32, FileHeader, Pe32Data);
+ return Status;
+ }
+ } while (!EFI_ERROR (Status));
+
+ return Status;
+}
diff --git a/EdkUnixPkg/Sec/SecMain.c b/EdkUnixPkg/Sec/SecMain.c new file mode 100644 index 0000000..b2234c4 --- /dev/null +++ b/EdkUnixPkg/Sec/SecMain.c @@ -0,0 +1,995 @@ +/*++
+
+Copyright (c) 2006, 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.
+
+Module Name:
+
+ SecMain.c
+
+Abstract:
+ WinNt emulator of SEC phase. It's really a Win32 application, but this is
+ Ok since all the other modules for NT32 are NOT Win32 applications.
+
+ This program processes Windows environment variables and figures out
+ what the memory layout will be, how may FD's will be loaded and also
+ what the boot mode is.
+
+ The SEC registers a set of services with the SEC core. gPrivateDispatchTable
+ is a list of PPI's produced by the SEC that are availble for usage in PEI.
+
+ This code produces 128 K of temporary memory for the PEI stack by opening a
+ Windows file and mapping it directly to memory addresses.
+
+ The system.cmd script is used to set windows environment variables that drive
+ the configuration opitons of the SEC.
+
+--*/
+
+#include "SecMain.h"
+#include <stdlib.h> +#include <sys/mman.h> +#include <sys/fcntl.h> +#include <unistd.h> +
+//
+// Globals
+//
+EFI_PEI_PE_COFF_LOADER_PROTOCOL_INSTANCE mPeiEfiPeiPeCoffLoaderInstance = {
+ {
+ SecNt32PeCoffGetImageInfo,
+ SecNt32PeCoffLoadImage,
+ SecNt32PeCoffRelocateImage,
+ SecNt32PeCoffUnloadimage
+ },
+ NULL
+};
+
+
+
+EFI_PEI_PE_COFF_LOADER_PROTOCOL *gPeiEfiPeiPeCoffLoader = &mPeiEfiPeiPeCoffLoaderInstance.PeCoff;
+
+UNIX_PEI_LOAD_FILE_PPI mSecNtLoadFilePpi = { SecWinNtPeiLoadFile };
+
+PEI_UNIX_AUTOSCAN_PPI mSecNtAutoScanPpi = { SecWinNtPeiAutoScan };
+
+PEI_UNIX_THUNK_PPI mSecWinNtThunkPpi = { SecWinNtWinNtThunkAddress };
+
+EFI_PEI_PROGRESS_CODE_PPI mSecStatusCodePpi = { SecPeiReportStatusCode };
+
+UNIX_FWH_PPI mSecFwhInformationPpi = { SecWinNtFdAddress };
+
+
+EFI_PEI_PPI_DESCRIPTOR gPrivateDispatchTable[] = {
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI,
+ &gEfiPeiPeCoffLoaderGuid,
+ NULL
+ },
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI,
+ &gUnixPeiLoadFilePpiGuid,
+ &mSecNtLoadFilePpi
+ },
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI,
+ &gPeiUnixAutoScanPpiGuid,
+ &mSecNtAutoScanPpi
+ },
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI,
+ &gPeiUnixThunkPpiGuid,
+ &mSecWinNtThunkPpi
+ },
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI,
+ &gEfiPeiStatusCodePpiGuid,
+ &mSecStatusCodePpi
+ },
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &gUnixFwhPpiGuid,
+ &mSecFwhInformationPpi
+ }
+};
+
+
+//
+// Default information about where the FD is located.
+// This array gets filled in with information from EFI_FIRMWARE_VOLUMES
+// EFI_FIRMWARE_VOLUMES is a Windows 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;
+UNIX_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;
+UNIX_SYSTEM_MEMORY *gSystemMemory;
+
+
+STATIC +EFI_PHYSICAL_ADDRESS * +MapMemory ( + INTN fd, + UINT64 length, + INTN prot, + INTN flags); +
+STATIC +EFI_STATUS +MapFile ( + IN CHAR8 *FileName,
+ IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
+ OUT UINT64 *Length
+ ); +
+
+INTN
+EFIAPI
+main (
+ IN INTN Argc,
+ IN CHAR8 **Argv,
+ IN CHAR8 **Envp
+ )
+/*++
+
+Routine Description:
+ Main entry point to SEC for WinNt. This is a Windows 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
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS InitialStackMemory;
+ UINT64 InitialStackMemorySize;
+ UINTN Index;
+ UINTN Index1;
+ UINTN Index2;
+ UINTN PeiIndex;
+ CHAR8 *FileName;
+ BOOLEAN Done;
+ VOID *PeiCoreFile;
+ CHAR16 *MemorySizeStr;
+ CHAR16 *FirmwareVolumesStr;
+
+ MemorySizeStr = (CHAR16 *)PcdGetPtr (PcdUnixMemorySizeForSecMain);
+ FirmwareVolumesStr = (CHAR16 *)PcdGetPtr (PcdUnixFirmwareVolume);
+
+ printf ("\nEDK SEC Main NT Emulation Environment from www.TianoCore.org\n");
+
+ //
+ // Allocate space for gSystemMemory Array
+ //
+ gSystemMemoryCount = CountSeperatorsInString (MemorySizeStr, '!') + 1;
+ gSystemMemory = calloc (gSystemMemoryCount, sizeof (UNIX_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 = calloc (gFdInfoCount, sizeof (UNIX_FD_INFO));
+ if (gFdInfo == NULL) {
+ printf ("ERROR : Can not allocate memory for fd info. Exiting.\n"); + exit (1);
+ }
+ //
+ // Setup Boot Mode. If BootModeStr == "" then BootMode = 0 (BOOT_WITH_FULL_CONFIGURATION)
+ //
+ printf (" BootMode 0x%02x\n", FixedPcdGet32 (PcdUnixBootMode));
+
+ //
+ // Open up a 128K file to emulate temp memory for PEI.
+ // on a real platform this would be SRAM, or using the cache as RAM.
+ // Set InitialStackMemory to zero so WinNtOpenFile will allocate a new mapping
+ //
+ InitialStackMemorySize = 0x20000;
+ InitialStackMemory = (UINTN)MapMemory(0, + (UINT32) InitialStackMemorySize,
+ PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE); + if (InitialStackMemory == 0) {
+ printf ("ERROR : Can not open SecStack Exiting\n");
+ exit (1);
+ }
+
+ printf (" SEC passing in %u KB of temp RAM at 0x%08lx to PEI\n", + (UINTN)(InitialStackMemorySize / 1024), + (unsigned long)InitialStackMemory);
+
+ //
+ // Open All the firmware volumes and remember the info in the gFdInfo global
+ //
+ FileName = (CHAR8 *)malloc (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, PeiCoreFile = 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';
+
+ //
+ // Open the FD and remmeber where it got mapped into our processes address space
+ //
+ 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, Status);
+ exit (1);
+ }
+
+ printf (" FD loaded from %s at 0x%08lx", + FileName, (unsigned long)gFdInfo[Index].Address);
+ + if (PeiCoreFile == NULL) {
+ //
+ // Assume the beginning of the FD is an FV and look for the PEI Core.
+ // Load the first one we find.
+ //
+ Status = SecFfsFindPeiCore ((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) gFdInfo[Index].Address, &PeiCoreFile);
+ 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 PEI Core
+ //
+ SecLoadFromCore ((UINTN) InitialStackMemory, (UINTN) InitialStackMemorySize, (UINTN) gFdInfo[0].Address, PeiCoreFile);
+
+ //
+ // If we get here, then the PEI Core returned. This is an error as PEI should
+ // always hand off to DXE.
+ //
+ printf ("ERROR : PEI Core returned\n");
+ exit (1);
+}
+
+EFI_PHYSICAL_ADDRESS * +MapMemory ( + INTN fd, + UINT64 length, + INTN prot, + INTN flags) +{ + static UINTN base = 0x40000000; + const UINTN align = (1 << 24); + void *res; + + res = mmap ((void *)base, length, prot, flags, fd, 0); + if (res == MAP_FAILED) + return NULL; + + // Guard page. + base += length + 4096; + base = (base + align - 1) & ~(align - 1); + + return res; +} + +EFI_STATUS +MapFile ( + IN CHAR8 *FileName,
+ IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
+ OUT UINT64 *Length
+ ) +/*++ + +Routine Description: + Opens and memory maps a file using WinNt 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 + +--*/ +{ + int fd; + VOID *res; + UINTN FileSize; + + fd = open (FileName, O_RDONLY); + if (fd < 0) + return EFI_NOT_FOUND; + FileSize = lseek (fd, 0, SEEK_END); + +#if 0 + if (IsMain) + { + /* Read entry address. */ + lseek (fd, FileSize - 0x20, SEEK_SET); + if (read (fd, &EntryAddress, 4) != 4) + { + close (fd); + return EFI_DEVICE_ERROR; + } + } +#endif + + res = MapMemory(fd, FileSize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE); + + close (fd); + + if (res == MAP_FAILED) + return EFI_DEVICE_ERROR; + + *Length = (UINT64) FileSize; + *BaseAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) res; + + return EFI_SUCCESS; +} +
+#define BYTES_PER_RECORD 512
+
+/**
+ Extracts ASSERT() information from a status code structure.
+
+ Converts the status code specified by CodeType, Value, and Data to the ASSERT()
+ arguments specified by Filename, Description, and LineNumber. If CodeType is
+ an EFI_ERROR_CODE, and CodeType has a severity of EFI_ERROR_UNRECOVERED, and
+ Value has an operation mask of EFI_SW_EC_ILLEGAL_SOFTWARE_STATE, extract
+ Filename, Description, and LineNumber from the optional data area of the
+ status code buffer specified by Data. The optional data area of Data contains
+ a Null-terminated ASCII string for the FileName, followed by a Null-terminated
+ ASCII string for the Description, followed by a 32-bit LineNumber. If the
+ ASSERT() information could be extracted from Data, then return TRUE.
+ Otherwise, FALSE is returned.
+
+ If Data is NULL, then ASSERT().
+ If Filename is NULL, then ASSERT().
+ If Description is NULL, then ASSERT().
+ If LineNumber is NULL, then ASSERT().
+
+ @param CodeType The type of status code being converted.
+ @param Value The status code value being converted.
+ @param Data Pointer to status code data buffer.
+ @param Filename Pointer to the source file name that generated the ASSERT().
+ @param Description Pointer to the description of the ASSERT().
+ @param LineNumber Pointer to source line number that generated the ASSERT().
+
+ @retval TRUE The status code specified by CodeType, Value, and Data was
+ converted ASSERT() arguments specified by Filename, Description,
+ and LineNumber.
+ @retval FALSE The status code specified by CodeType, Value, and Data could
+ not be converted to ASSERT() arguments.
+
+**/
+STATIC
+BOOLEAN
+ReportStatusCodeExtractAssertInfo (
+ IN EFI_STATUS_CODE_TYPE CodeType,
+ IN EFI_STATUS_CODE_VALUE Value,
+ IN CONST EFI_STATUS_CODE_DATA *Data,
+ OUT CHAR8 **Filename,
+ OUT CHAR8 **Description,
+ OUT UINT32 *LineNumber
+ )
+{
+ EFI_DEBUG_ASSERT_DATA *AssertData;
+
+ ASSERT (Data != NULL);
+ ASSERT (Filename != NULL);
+ ASSERT (Description != NULL);
+ ASSERT (LineNumber != NULL);
+
+ if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) &&
+ ((CodeType & EFI_STATUS_CODE_SEVERITY_MASK) == EFI_ERROR_UNRECOVERED) &&
+ ((Value & EFI_STATUS_CODE_OPERATION_MASK) == EFI_SW_EC_ILLEGAL_SOFTWARE_STATE)) {
+ AssertData = (EFI_DEBUG_ASSERT_DATA *)(Data + 1);
+ *Filename = (CHAR8 *)(AssertData + 1);
+ *Description = *Filename + AsciiStrLen (*Filename) + 1;
+ *LineNumber = AssertData->LineNumber;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+EFI_STATUS
+EFIAPI
+SecPeiReportStatusCode (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_STATUS_CODE_TYPE CodeType,
+ IN EFI_STATUS_CODE_VALUE Value,
+ IN UINT32 Instance,
+ IN EFI_GUID * CallerId,
+ IN EFI_STATUS_CODE_DATA * Data OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ This routine produces the ReportStatusCode PEI service. It's passed
+ up to the PEI Core via a PPI. T
+
+ This code currently uses the NT clib printf. This does not work the same way
+ as the EFI Print (), as %t, %g, %s as Unicode are not supported.
+
+Arguments:
+ (see EFI_PEI_REPORT_STATUS_CODE)
+
+Returns:
+ EFI_SUCCESS - Always return success
+
+--*/
+// TODO: PeiServices - add argument and description to function comment
+// TODO: CodeType - add argument and description to function comment
+// TODO: Value - add argument and description to function comment
+// TODO: Instance - add argument and description to function comment
+// TODO: CallerId - add argument and description to function comment
+// TODO: Data - add argument and description to function comment
+{
+ CHAR8 *Format;
+ EFI_DEBUG_INFO *DebugInfo;
+ VA_LIST Marker;
+ CHAR8 PrintBuffer[BYTES_PER_RECORD * 2];
+ CHAR8 *Filename;
+ CHAR8 *Description;
+ UINT32 LineNumber;
+
+ if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) {
+ //
+ // This supports DEBUG () marcos
+ // Data format
+ // EFI_STATUS_CODE_DATA
+ // EFI_DEBUG_INFO
+ //
+ // The first 12 * UINT64 bytes of the string are really an
+ // arguement stack to support varargs on the Format string.
+ //
+ if (Data != NULL) {
+ DebugInfo = (EFI_DEBUG_INFO *) (Data + 1);
+ Marker = (VA_LIST) (DebugInfo + 1);
+ Format = (CHAR8 *) (((UINT64 *) Marker) + 12);
+
+ AsciiVSPrint (PrintBuffer, BYTES_PER_RECORD, Format, Marker);
+ printf (PrintBuffer);
+ } else {
+ printf ("DEBUG <null>\n");
+ }
+ }
+
+ if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) &&
+ ((CodeType & EFI_STATUS_CODE_SEVERITY_MASK) == EFI_ERROR_UNRECOVERED)
+ ) {
+ if (Data != NULL && ReportStatusCodeExtractAssertInfo (CodeType, Value, Data, &Filename, &Description, &LineNumber)) {
+ //
+ // Support ASSERT () macro
+ //
+ printf ("ASSERT %s(%d): %s\n", Filename, LineNumber, Description);
+ } else {
+ printf ("ASSERT <null>\n");
+ }
+ CpuBreakpoint ();
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+VOID
+SecLoadFromCore (
+ IN UINTN LargestRegion,
+ IN UINTN LargestRegionSize,
+ IN UINTN BootFirmwareVolumeBase,
+ IN VOID *PeiCorePe32File
+ )
+/*++
+
+Routine Description:
+ This is the service to load the PEI Core from the Firmware Volume
+
+Arguments:
+ LargestRegion - Memory to use for PEI.
+ LargestRegionSize - Size of Memory to use for PEI
+ BootFirmwareVolumeBase - Start of the Boot FV
+ PeiCorePe32File - PEI Core PE32
+
+Returns:
+ Success means control is transfered and thus we should never return
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS TopOfMemory;
+ VOID *TopOfStack;
+ UINT64 PeiCoreSize;
+ EFI_PHYSICAL_ADDRESS PeiCoreEntryPoint;
+ EFI_PHYSICAL_ADDRESS PeiImageAddress;
+ EFI_PEI_STARTUP_DESCRIPTOR *PeiStartup;
+
+ //
+ // Compute Top Of Memory for Stack and PEI Core Allocations
+ //
+ TopOfMemory = LargestRegion + LargestRegionSize;
+
+ //
+ // Allocate 128KB for the Stack
+ //
+ TopOfStack = (VOID *)((UINTN)TopOfMemory - sizeof (EFI_PEI_STARTUP_DESCRIPTOR) - CPU_STACK_ALIGNMENT);
+ TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);
+ TopOfMemory = TopOfMemory - STACK_SIZE;
+
+ //
+ // Patch value in dispatch table values
+ //
+ gPrivateDispatchTable[0].Ppi = gPeiEfiPeiPeCoffLoader;
+
+ //
+ // Bind this information into the SEC hand-off state
+ //
+ PeiStartup = (EFI_PEI_STARTUP_DESCRIPTOR *) (UINTN) TopOfStack;
+ PeiStartup->DispatchTable = (EFI_PEI_PPI_DESCRIPTOR *) &gPrivateDispatchTable;
+ PeiStartup->SizeOfCacheAsRam = STACK_SIZE;
+ PeiStartup->BootFirmwareVolume = BootFirmwareVolumeBase;
+
+ //
+ // Load the PEI Core from a Firmware Volume
+ //
+ Status = SecWinNtPeiLoadFile (
+ PeiCorePe32File,
+ &PeiImageAddress,
+ &PeiCoreSize,
+ &PeiCoreEntryPoint
+ );
+ if (EFI_ERROR (Status)) {
+ return ;
+ }
+ printf ("Jump to 0x%08lx\n", (unsigned long)PeiCoreEntryPoint); + //
+ // Transfer control to the PEI Core
+ //
+ SwitchStack (
+ (SWITCH_STACK_ENTRY_POINT) (UINTN) PeiCoreEntryPoint,
+ PeiStartup,
+ NULL,
+ TopOfStack
+ );
+ //
+ // If we get here, then the PEI Core returned. This is an error
+ //
+ return ;
+}
+
+EFI_STATUS
+EFIAPI
+SecWinNtPeiAutoScan (
+ IN UINTN Index,
+ OUT EFI_PHYSICAL_ADDRESS *MemoryBase,
+ OUT UINT64 *MemorySize
+ )
+/*++
+
+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 Windows environment variable EFI_MEMORY_SIZE.
+ The size comes from the varaible and the address comes from the call to
+ WinNtOpenFile.
+
+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
+
+--*/
+{
+ 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;
+}
+
+VOID *
+EFIAPI
+SecWinNtWinNtThunkAddress (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Since the SEC is the only Windows program in stack it must export
+ an interface to do Win API calls. That's what the WinNtThunk address
+ is for. gWinNt is initailized in WinNtThunk.c.
+
+Arguments:
+ InterfaceSize - sizeof (EFI_WIN_NT_THUNK_PROTOCOL);
+ InterfaceBase - Address of the gWinNt global
+
+Returns:
+ EFI_SUCCESS - Data returned
+
+--*/
+{
+ return gUnix;
+}
+
+
+EFI_STATUS
+EFIAPI
+SecWinNtPeiLoadFile (
+ IN VOID *Pe32Data,
+ IN EFI_PHYSICAL_ADDRESS *ImageAddress,
+ IN UINT64 *ImageSize,
+ IN EFI_PHYSICAL_ADDRESS *EntryPoint
+ )
+/*++
+
+Routine Description:
+ Loads and relocates a PE/COFF image into memory.
+
+Arguments:
+ Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
+ ImageAddress - The base address of the relocated PE/COFF image
+ ImageSize - The size of the relocated PE/COFF image
+ EntryPoint - The entry point of the relocated PE/COFF image
+
+Returns:
+ EFI_SUCCESS - The file was loaded and relocated
+ EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
+
+--*/
+{
+ 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 = gPeiEfiPeiPeCoffLoader->GetImageInfo (gPeiEfiPeiPeCoffLoader, &ImageContext);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Allocate space in NT (not emulator) memory. Extra space is for alignment
+ //
+ ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) malloc ((UINTN) (ImageContext.ImageSize + (ImageContext.SectionAlignment * 2)));
+ if (ImageContext.ImageAddress == 0) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Align buffer on section boundry
+ //
+ ImageContext.ImageAddress += ImageContext.SectionAlignment;
+ ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);
+ +
+ Status = gPeiEfiPeiPeCoffLoader->LoadImage (gPeiEfiPeiPeCoffLoader, &ImageContext);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gPeiEfiPeiPeCoffLoader->RelocateImage (gPeiEfiPeiPeCoffLoader, &ImageContext);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // BugBug: Flush Instruction Cache Here when CPU Lib is ready
+ //
+
+ *ImageAddress = ImageContext.ImageAddress;
+ *ImageSize = ImageContext.ImageSize;
+ *EntryPoint = ImageContext.EntryPoint;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+SecWinNtFdAddress (
+ IN UINTN Index,
+ IN OUT EFI_PHYSICAL_ADDRESS *FdBase,
+ IN OUT UINT64 *FdSize
+ )
+/*++
+
+Routine Description:
+ Return the FD Size and base address. Since the FD is loaded from a
+ file into Windows 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
+
+Returns:
+ EFI_SUCCESS - Return the Base address and size of the FV
+ EFI_UNSUPPORTED - Index does nto map to an FD in the system
+
+--*/
+{
+ if (Index >= gFdInfoCount) {
+ return EFI_UNSUPPORTED;
+ }
+
+ *FdBase = gFdInfo[Index].Address;
+ *FdSize = gFdInfo[Index].Size;
+
+ if (*FdBase == 0 && *FdSize == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+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;
+}
+
+UINTN
+CountSeperatorsInString (
+ IN const CHAR16 *String,
+ IN CHAR16 Seperator
+ )
+/*++
+
+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 Count;
+
+ for (Count = 0; *String != '\0'; String++) {
+ if (*String == Seperator) {
+ Count++;
+ }
+ }
+
+ return Count;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+SecNt32PeCoffGetImageInfo (
+ IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+{
+ EFI_STATUS Status;
+
+ Status = PeCoffLoaderGetImageInfo (ImageContext);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ switch (ImageContext->ImageType) {
+
+ case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:
+ ImageContext->ImageCodeMemoryType = EfiLoaderCode;
+ ImageContext->ImageDataMemoryType = EfiLoaderData;
+ break;
+
+ case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:
+ ImageContext->ImageCodeMemoryType = EfiBootServicesCode;
+ ImageContext->ImageDataMemoryType = EfiBootServicesData;
+ break;
+
+ case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
+ case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER:
+ ImageContext->ImageCodeMemoryType = EfiRuntimeServicesCode;
+ ImageContext->ImageDataMemoryType = EfiRuntimeServicesData;
+ break;
+
+ default:
+ ImageContext->ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM;
+ return RETURN_UNSUPPORTED;
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+SecNt32PeCoffLoadImage (
+ IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+{
+ EFI_STATUS Status;
+
+ Status = PeCoffLoaderLoadImage (ImageContext);
+ return Status;
+}
+
+VOID +SecUnixLoaderBreak ( + VOID + ) +{ +} + +EFI_STATUS
+EFIAPI
+SecNt32PeCoffRelocateImage (
+ IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+{
+
+#if 0 + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; + EFI_IMAGE_SECTION_HEADER *Sec; + INTN i; +#endif + + fprintf (stderr, + "Loading %s 0x%08lx - entry point 0x%08lx\n", + ImageContext->PdbPointer, + (unsigned long)ImageContext->ImageAddress, + (unsigned long)ImageContext->EntryPoint); + +#if 0 + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) + ((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset);
+ Sec = (EFI_IMAGE_SECTION_HEADER*) + ((UINTN)ImageContext->ImageAddress + + ImageContext->PeCoffHeaderOffset + + sizeof(UINT32) + + sizeof(EFI_IMAGE_FILE_HEADER) + + Hdr.Pe32->FileHeader.SizeOfOptionalHeader); + for (i = 0; i < Hdr.Pe32->FileHeader.NumberOfSections; i++) + fprintf (stderr, " %s 0x%08lx\n", + Sec[i].Name, (unsigned long)Sec[i].VirtualAddress); +#endif + + SecUnixLoaderBreak (); + + return PeCoffLoaderRelocateImage (ImageContext);
+}
+
+
+EFI_STATUS
+EFIAPI
+SecNt32PeCoffUnloadimage (
+ IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
+ IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+{
+ return EFI_SUCCESS;
+}
+
+VOID
+_ModuleEntryPoint (
+ VOID
+ )
+{
+}
+
diff --git a/EdkUnixPkg/Sec/SecMain.h b/EdkUnixPkg/Sec/SecMain.h new file mode 100644 index 0000000..815dc79 --- /dev/null +++ b/EdkUnixPkg/Sec/SecMain.h @@ -0,0 +1,529 @@ +/*++
+
+Copyright (c) 2006, 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.
+
+
+Module Name:
+ SecMain.h
+
+Abstract:
+ Include file for Windows API based SEC
+
+--*/
+
+#include <stdio.h>
+
+
+#define STACK_SIZE 0x20000
+
+typedef struct {
+ EFI_PHYSICAL_ADDRESS Address;
+ UINT64 Size;
+} UNIX_FD_INFO;
+
+typedef struct {
+ EFI_PHYSICAL_ADDRESS Memory;
+ UINT64 Size;
+} UNIX_SYSTEM_MEMORY;
+
+
+
+EFI_STATUS
+EFIAPI
+SecWinNtPeiLoadFile (
+ VOID *Pe32Data, // TODO: add IN/OUT modifier to Pe32Data
+ EFI_PHYSICAL_ADDRESS *ImageAddress, // TODO: add IN/OUT modifier to ImageAddress
+ UINT64 *ImageSize, // TODO: add IN/OUT modifier to ImageSize
+ EFI_PHYSICAL_ADDRESS *EntryPoint // TODO: add IN/OUT modifier to EntryPoint
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Pe32Data - TODO: add argument description
+ ImageAddress - TODO: add argument description
+ ImageSize - TODO: add argument description
+ EntryPoint - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+SecWinNtPeiAutoScan (
+ IN UINTN Index,
+ OUT EFI_PHYSICAL_ADDRESS *MemoryBase,
+ OUT UINT64 *MemorySize
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Index - TODO: add argument description
+ MemoryBase - TODO: add argument description
+ MemorySize - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+VOID *
+EFIAPI
+SecWinNtWinNtThunkAddress (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ InterfaceSize - TODO: add argument description
+ InterfaceBase - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+SecWinNtWinNtFwhAddress (
+ IN OUT UINT64 *FwhSize,
+ IN OUT EFI_PHYSICAL_ADDRESS *FwhBase
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ FwhSize - TODO: add argument description
+ FwhBase - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+SecPeiReportStatusCode (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_STATUS_CODE_TYPE CodeType,
+ IN EFI_STATUS_CODE_VALUE Value,
+ IN UINT32 Instance,
+ IN EFI_GUID * CallerId,
+ IN EFI_STATUS_CODE_DATA * Data OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PeiServices - TODO: add argument description
+ CodeType - TODO: add argument description
+ Value - TODO: add argument description
+ Instance - TODO: add argument description
+ CallerId - TODO: add argument description
+ Data - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+INTN
+EFIAPI
+main (
+ IN INTN Argc,
+ IN CHAR8 **Argv,
+ IN CHAR8 **Envp
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Argc - TODO: add argument description
+ Argv - TODO: add argument description
+ Envp - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+VOID
+SecLoadFromCore (
+ IN UINTN LargestRegion,
+ IN UINTN LargestRegionSize,
+ IN UINTN BootFirmwareVolumeBase,
+ IN VOID *PeiCoreFile
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ LargestRegion - TODO: add argument description
+ LargestRegionSize - TODO: add argument description
+ BootFirmwareVolumeBase - TODO: add argument description
+ PeiCoreFile - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+SecLoadFile (
+ IN VOID *Pe32Data,
+ IN EFI_PHYSICAL_ADDRESS *ImageAddress,
+ IN UINT64 *ImageSize,
+ IN EFI_PHYSICAL_ADDRESS *EntryPoint
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Pe32Data - TODO: add argument description
+ ImageAddress - TODO: add argument description
+ ImageSize - TODO: add argument description
+ EntryPoint - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+SecFfsFindPeiCore (
+ IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader,
+ OUT VOID **Pe32Data
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ FwVolHeader - TODO: add argument description
+ Pe32Data - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+SecFfsFindNextFile (
+ IN EFI_FV_FILETYPE SearchType,
+ IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader,
+ IN OUT EFI_FFS_FILE_HEADER **FileHeader
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ SearchType - TODO: add argument description
+ FwVolHeader - TODO: add argument description
+ FileHeader - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+SecFfsFindSectionData (
+ IN EFI_SECTION_TYPE SectionType,
+ IN EFI_FFS_FILE_HEADER *FfsFileHeader,
+ IN OUT VOID **SectionData
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ SectionType - TODO: add argument description
+ FfsFileHeader - TODO: add argument description
+ SectionData - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+SecWinNtPeCoffLoaderLoadAsDll (
+ IN CHAR8 *PdbFileName,
+ IN VOID **ImageEntryPoint,
+ OUT VOID **ModHandle
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PdbFileName - TODO: add argument description
+ ImageEntryPoint - TODO: add argument description
+ ModHandle - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+SecWinNtPeCoffLoaderFreeLibrary (
+ OUT VOID *ModHandle
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ ModHandle - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+SecWinNtFdAddress (
+ IN UINTN Index,
+ IN OUT EFI_PHYSICAL_ADDRESS *FdBase,
+ IN OUT UINT64 *FdSize
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Index - TODO: add argument description
+ FdBase - TODO: add argument description
+ FdSize - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+GetImageReadFunction (
+ IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
+ IN EFI_PHYSICAL_ADDRESS *TopOfMemory
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ ImageContext - TODO: add argument description
+ TopOfMemory - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+SecImageRead (
+ IN VOID *FileHandle,
+ IN UINTN FileOffset,
+ IN OUT UINTN *ReadSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ FileHandle - TODO: add argument description
+ FileOffset - TODO: add argument description
+ ReadSize - TODO: add argument description
+ Buffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+CHAR16 *
+AsciiToUnicode (
+ IN CHAR8 *Ascii,
+ IN UINTN *StrLen OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Ascii - TODO: add argument description
+ StrLen - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+UINTN
+CountSeperatorsInString (
+ IN const CHAR16 *String,
+ IN CHAR16 Seperator
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ String - TODO: add argument description
+ Seperator - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+SecNt32PeCoffGetImageInfo (
+ IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ );
+
+EFI_STATUS
+EFIAPI
+SecNt32PeCoffLoadImage (
+ IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ );
+
+EFI_STATUS
+EFIAPI
+SecNt32PeCoffRelocateImage (
+ IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ );
+
+EFI_STATUS
+EFIAPI
+SecNt32PeCoffUnloadimage (
+ IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
+ IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ );
+
+
+typedef struct {
+ EFI_PEI_PE_COFF_LOADER_PROTOCOL PeCoff;
+ VOID *ModHandle;
+} EFI_PEI_PE_COFF_LOADER_PROTOCOL_INSTANCE;
+
+extern EFI_UNIX_THUNK_PROTOCOL *gUnix;
diff --git a/EdkUnixPkg/Sec/SecMain.msa b/EdkUnixPkg/Sec/SecMain.msa new file mode 100644 index 0000000..335cc5f --- /dev/null +++ b/EdkUnixPkg/Sec/SecMain.msa @@ -0,0 +1,113 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0">
+ <MsaHeader>
+ <ModuleName>SecMain</ModuleName>
+ <ModuleType>USER_DEFINED</ModuleType>
+ <GuidValue>f43be88c-8985-11db-8f78-0040d02b1835</GuidValue>
+ <Version>1.0</Version>
+ <Abstract>Entry Point of Unix Emulator</Abstract>
+ <Description>Main executable file of Unix Emulator that loads PEI core after initialization finished.</Description>
+ <Copyright>Copyright (c) 2006, Intel Corporation</Copyright>
+ <License>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.</License>
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
+ </MsaHeader>
+ <ModuleDefinitions>
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
+ <BinaryModule>false</BinaryModule>
+ <OutputFileBasename>SecMain</OutputFileBasename>
+ </ModuleDefinitions>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>PeCoffLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseMemoryLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>PrintLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>PcdLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DebugLib</Keyword>
+ </LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename ToolCode="DUMMY">SecMain_build.xml</Filename>
+ <Filename>SecMain.c</Filename>
+ <Filename>FwVol.c</Filename>
+ <Filename>UnixThunk.c</Filename>
+ <Filename>UgaX11.c</Filename>
+ <Filename>SecMain.h</Filename>
+ </SourceFiles>
+ <PackageDependencies>
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
+ <Package PackageGuid="f2805c44-8985-11db-9e98-0040d02b1835"/>
+ </PackageDependencies>
+ <PPIs>
+ <Ppi Usage="ALWAYS_PRODUCED">
+ <PpiCName>gPeiUnixThunkPpiGuid</PpiCName>
+ </Ppi>
+ <Ppi Usage="ALWAYS_PRODUCED">
+ <PpiCName>gPeiUnixAutoScanPpiGuid</PpiCName>
+ </Ppi>
+ <Ppi Usage="ALWAYS_PRODUCED">
+ <PpiCName>gUnixFwhPpiGuid</PpiCName>
+ </Ppi>
+ <Ppi Usage="ALWAYS_PRODUCED">
+ <PpiCName>gEfiPeiStatusCodePpiGuid</PpiCName>
+ </Ppi>
+ <Ppi Usage="ALWAYS_PRODUCED">
+ <PpiCName>gUnixPeiLoadFilePpiGuid</PpiCName>
+ </Ppi>
+ </PPIs>
+ <Guids>
+ <GuidCNames Usage="ALWAYS_PRODUCED">
+ <GuidCName>gEfiPeiPeCoffLoaderGuid</GuidCName>
+ </GuidCNames>
+ </Guids>
+ <Externs>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
+ </Externs>
+ <PcdCoded>
+ <PcdEntry PcdItemType="DYNAMIC">
+ <C_Name>PcdUnixMemorySizeForSecMain</C_Name>
+ <TokenSpaceGuidCName>gEfiEdkUnixPkgTokenSpaceGuid</TokenSpaceGuidCName>
+ <HelpText>This PCD defines the memory size of simulated machine. Simulator will allocate
+ the size of PcdUnixMemorySizeForSecMain in windows platform.</HelpText>
+ </PcdEntry>
+ <PcdEntry PcdItemType="DYNAMIC">
+ <C_Name>PcdUnixFirmwareVolume</C_Name>
+ <TokenSpaceGuidCName>gEfiEdkUnixPkgTokenSpaceGuid</TokenSpaceGuidCName>
+ <HelpText>This PCD defines the FD file windows path string. Simulator will load the FD file and execute.</HelpText>
+ </PcdEntry>
+ <PcdEntry PcdItemType="DYNAMIC">
+ <C_Name>PcdUnixBootMode</C_Name>
+ <TokenSpaceGuidCName>gEfiEdkUnixPkgTokenSpaceGuid</TokenSpaceGuidCName>
+ <HelpText>This PCD defines the boot mode for simualtor.
+ The boot mode can be set as following value:
+ 0x0: Boot with full configuration.
+ 0x1: Boot with minimal configuration.
+ 0x2: Boot assume no configuration changes.
+ 0x3: Boot with full configuration plus diagnostics.
+ 0x4: Boot with default settings.
+ 0x5: Boot on S4 resume.
+ 0x6: Boot on S5 resume.
+ 0x10: Boot on S2 resume.
+ 0x11: Boot on S3 resume.
+ 0x12: Boot on flash update.
+ 0x20: Boot in reovery mode.</HelpText>
+ </PcdEntry>
+ </PcdCoded>
+</ModuleSurfaceArea> diff --git a/EdkUnixPkg/Sec/SecMain_build.xml b/EdkUnixPkg/Sec/SecMain_build.xml new file mode 100644 index 0000000..c1a5caf --- /dev/null +++ b/EdkUnixPkg/Sec/SecMain_build.xml @@ -0,0 +1,143 @@ +<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, 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.
+-->
+<project name="SecMain" default="main" basedir="." >
+ <!-- Apply external ANT task -->
+ <taskdef resource="frameworktasks.tasks" />
+ <taskdef resource="cpptasks.tasks" />
+ <typedef resource="cpptasks.types" />
+ <taskdef resource="net/sf/antcontrib/antlib.xml" />
+ <property environment="env" />
+ <!-- All Properties -->
+ <property name="BASE_NAME" value="SecMain" />
+
+ <!-- Default target -->
+ <target name="main" depends="libraries, sourcefiles, sections, output" />
+ <!-- Compile all dependency Library instances. -->
+
+ <target name="libraries">
+ <GenBuild type="build">
+ <property name="ARCH" value="${ARCH}"/>
+ <property name="MODULE_GUID" value="27d67720-ea68-48ae-93da-a3a074c90e30"/>
+ <property name="MODULE_VERSION" value=""/>
+ <property name="PLATFORM" value="${PLATFORM}"/>
+ <property name="PACKAGE_GUID" value="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+ <property name="PACKAGE_VERSION" value=""/>
+ </GenBuild>
+ <GenBuild type="build">
+ <property name="ARCH" value="${ARCH}"/>
+ <property name="MODULE_GUID" value="fd44e603-002a-4b29-9f5f-529e815b6165"/>
+ <property name="MODULE_VERSION" value=""/>
+ <property name="PLATFORM" value="${PLATFORM}"/>
+ <property name="PACKAGE_GUID" value="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+ <property name="PACKAGE_VERSION" value=""/>
+ </GenBuild>
+ <GenBuild type="build">
+ <property name="ARCH" value="${ARCH}"/>
+ <property name="MODULE_GUID" value="a86fbfca-0183-4eeb-aa8a-762e3b7da1f3"/>
+ <property name="MODULE_VERSION" value=""/>
+ <property name="PLATFORM" value="${PLATFORM}"/>
+ <property name="PACKAGE_GUID" value="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+ <property name="PACKAGE_VERSION" value=""/>
+ </GenBuild>
+ <GenBuild type="build">
+ <property name="ARCH" value="${ARCH}"/>
+ <property name="MODULE_GUID" value="556f5d10-7309-4af4-b80a-8196bd60946f"/>
+ <property name="MODULE_VERSION" value=""/>
+ <property name="PLATFORM" value="${PLATFORM}"/>
+ <property name="PACKAGE_GUID" value="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+ <property name="PACKAGE_VERSION" value=""/>
+ </GenBuild>
+ <GenBuild type="build">
+ <property name="ARCH" value="${ARCH}"/>
+ <property name="MODULE_GUID" value="9ba1d976-0624-41a3-8650-28165e8d9ae8"/>
+ <property name="MODULE_VERSION" value=""/>
+ <property name="PLATFORM" value="${PLATFORM}"/>
+ <property name="PACKAGE_GUID" value="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+ <property name="PACKAGE_VERSION" value=""/>
+ </GenBuild>
+ </target>
+ <target name="sourcefiles">
+ <Build_Init>
+ <EXTRA.INC>
+ <includepath path="${INCLUDE_PATHS}"/>
+ </EXTRA.INC>
+ </Build_Init>
+ <Build_AUTOGEN FILEEXT="c" FILENAME="AutoGen" FILEPATH=".">
+ <EXTRA.INC>
+ <includepath path="${INCLUDE_PATHS}"/>
+ </EXTRA.INC>
+ </Build_AUTOGEN>
+ <Build_CCode FILEEXT="c" FILENAME="FwVol" FILEPATH=".">
+ <EXTRA.INC>
+ <includepath path="${INCLUDE_PATHS}"/>
+ </EXTRA.INC>
+ </Build_CCode>
+ <Build_CCode FILEEXT="c" FILENAME="UnixThunk" FILEPATH=".">
+ <EXTRA.INC>
+ <includepath path="${INCLUDE_PATHS}"/>
+ </EXTRA.INC>
+ </Build_CCode>
+ <Build_CCode FILEEXT="c" FILENAME="UgaX11" FILEPATH=".">
+ <EXTRA.INC>
+ <includepath path="${INCLUDE_PATHS}"/>
+ </EXTRA.INC>
+ </Build_CCode>
+ <Build_CCode FILEEXT="c" FILENAME="SecMain" FILEPATH=".">
+ <EXTRA.INC>
+ <includepath path="${INCLUDE_PATHS}"/>
+ </EXTRA.INC>
+ </Build_CCode>
+ </target>
+
+ <target name="sections" />
+
+ <target name="output" >
+ <if>
+ <available type="file" file="${DEST_DIR_OUTPUT}/AutoGen.h.obj"/>
+ <then>
+ <var name="SLINK_FLAGS" value="${SLINK_FLAGS} ${DEST_DIR_OUTPUT}/AutoGen.h.obj"/>
+ </then>
+ </if>
+ <OnDependency>
+ <sourcefiles>
+ <fileset dir="${DEST_DIR_OUTPUT}" includes="${OBJECTS}" />
+ <file list="${LIBS}"/>
+ </sourcefiles>
+ <targetfiles>
+ <file name="${BIN_DIR}/SecMain.exe"/>
+ </targetfiles>
+
+ <sequential>
+ <cc userdefine="on">
+ <command type="SLINK" cmd="${SLINK}" family="${SLINK_FAMILY}"
+ outputFile="${DEST_DIR_OUTPUT}/SecMainLocal.lib" dpath="${SLINK_DPATH}">
+
+ <argument value="${SLINK_FLAGS}"/>
+
+ <fileset dir="${DEST_DIR_OUTPUT}" includes="${OBJECTS}"/>
+ </command>
+ </cc>
+
+ <var name="LIBS" value="${LIBS} ${DEST_DIR_OUTPUT}/SecMainLocal.lib" />
+
+ <shellscript shell="sh" tmpsuffix=".cmd" >
+ set -v + gcc -Wl,--start-group ${LIBS} -Wl,--end-group -o ${BIN_DIR}/SecMain.exe -L/usr/X11R6/lib -lXext -lX11 + </shellscript>
+ </sequential>
+ </OnDependency>
+ </target>
+
+ <target name="clean" ></target>
+
+ <target name="cleanAll"></target>
+</project>
diff --git a/EdkUnixPkg/Sec/UgaX11.c b/EdkUnixPkg/Sec/UgaX11.c new file mode 100644 index 0000000..565689a --- /dev/null +++ b/EdkUnixPkg/Sec/UgaX11.c @@ -0,0 +1,580 @@ +#include "Uefi/UefiSpec.h" +#include "Protocol/UnixThunk.h" +#include "Protocol/SimpleTextIn.h" +#include "Protocol/UgaDraw.h" +#include "Protocol/UnixUgaIo.h" +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xos.h> +#include <X11/extensions/XShm.h> +#include <X11/keysym.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include <stdio.h> +#include <stdlib.h> + +/* XQueryPointer */ + +struct uga_drv_shift_mask +{ + unsigned char shift; + unsigned char size; + unsigned char csize; +}; + +#define NBR_KEYS 32 +typedef struct +{ + EFI_UNIX_UGA_IO_PROTOCOL UgaIo; + + 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; + + unsigned int key_rd; + unsigned int key_wr; + unsigned int key_count; + EFI_INPUT_KEY keys[NBR_KEYS]; +} UGA_IO_PRIVATE; + +static void +HandleEvents(UGA_IO_PRIVATE *drv); + +static void +fill_shift_mask (struct uga_drv_shift_mask *sm, 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; +} + +static int +TryCreateShmImage(UGA_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; + } + /* Can this fail ? */ + shmctl (drv->xshm_info.shmid, IPC_RMID, NULL); + + drv->xshm_info.shmaddr = drv->image_data; + drv->image->data = drv->image_data; + + if (!XShmAttach (drv->display, &drv->xshm_info)) + { + shmdt (drv->image_data); + XDestroyImage(drv->image); + return 0; + } + return 1; +} + +static +EFI_STATUS +UgaClose (EFI_UNIX_UGA_IO_PROTOCOL *UgaIo) +{ + UGA_IO_PRIVATE *drv = (UGA_IO_PRIVATE *)UgaIo; + + 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); + free(drv); + return EFI_SUCCESS; +} + +static +EFI_STATUS +UgaSize(EFI_UNIX_UGA_IO_PROTOCOL *UgaIo, UINT32 Width, UINT32 Height) +{ + UGA_IO_PRIVATE *drv = (UGA_IO_PRIVATE *)UgaIo; + XSizeHints size_hints; + + /* Destroy current buffer if created. */ + if (drv->image != NULL) + { + 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, 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; +} + +static void +handleKeyEvent(UGA_IO_PRIVATE *drv, XEvent *ev) +{ + KeySym keysym; + char str[4]; + EFI_INPUT_KEY Key; + int res; + + if (drv->key_count == NBR_KEYS) + return; + + res = XLookupString(&ev->xkey, str, sizeof(str), &keysym, NULL); + Key.ScanCode = 0;
+ Key.UnicodeChar = 0; + switch (keysym) {
+ case XK_Home: Key.ScanCode = SCAN_HOME; break;
+ case XK_End: Key.ScanCode = SCAN_END; break;
+ case XK_Left: Key.ScanCode = SCAN_LEFT; break;
+ case XK_Right: Key.ScanCode = SCAN_RIGHT; break;
+ case XK_Up: Key.ScanCode = SCAN_UP; break;
+ case XK_Down: Key.ScanCode = SCAN_DOWN; break;
+ case XK_Delete: Key.ScanCode = SCAN_DELETE; break;
+ case XK_Insert: Key.ScanCode = SCAN_INSERT; break;
+ case XK_Page_Up: Key.ScanCode = SCAN_PAGE_UP; break;
+ case XK_Page_Down: Key.ScanCode = SCAN_PAGE_DOWN; break;
+ case XK_Escape: Key.ScanCode = SCAN_ESC; break;
+
+ case XK_F1: Key.ScanCode = SCAN_F1; break;
+ case XK_F2: Key.ScanCode = SCAN_F2; break;
+ case XK_F3: Key.ScanCode = SCAN_F3; break;
+ case XK_F4: Key.ScanCode = SCAN_F4; break;
+ case XK_F5: Key.ScanCode = SCAN_F5; break;
+ case XK_F6: Key.ScanCode = SCAN_F6; break;
+ case XK_F7: Key.ScanCode = SCAN_F7; break;
+ case XK_F8: Key.ScanCode = SCAN_F8; break;
+ case XK_F9: Key.ScanCode = SCAN_F9; break;
+ + default: + if (res == 1) { + Key.UnicodeChar = str[0]; + } else { + return; + } + }
+
+ drv->keys[drv->key_wr] = Key; + drv->key_wr = (drv->key_wr + 1) % NBR_KEYS; + drv->key_count++; +} + +static void +Redraw(UGA_IO_PRIVATE *drv, UINTN X, UINTN Y, UINTN Width, 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); +} + +static void +HandleEvent(UGA_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); + break; + case MappingNotify: + XRefreshKeyboardMapping(&ev->xmapping); + break; +#if 0 + case DestroyNotify: + XCloseDisplay (drv->display); + exit (1); + break; +#endif + case NoExpose: + default: + break; + } +} + +static void +HandleEvents(UGA_IO_PRIVATE *drv) +{ + while (XPending(drv->display) != 0) + { + XEvent ev; + + XNextEvent (drv->display, &ev); + HandleEvent(drv, &ev); + } +} + +static +unsigned long +UgaPixelToColor (UGA_IO_PRIVATE *drv, 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); +} + +static +EFI_UGA_PIXEL +UgaColorToPixel (UGA_IO_PRIVATE *drv, unsigned long val) +{ + EFI_UGA_PIXEL res; + + /* FIXME: should round instead of truncate. */ + res.Red = (val >> drv->r.shift) << drv->r.csize; + res.Green = (val >> drv->g.shift) << drv->g.csize; + res.Blue = (val >> drv->b.shift) << drv->b.csize; + + return res; +} + +static +EFI_STATUS +UgaCheckKey(EFI_UNIX_UGA_IO_PROTOCOL *UgaIo) +{ + UGA_IO_PRIVATE *drv = (UGA_IO_PRIVATE *)UgaIo; + HandleEvents(drv); + if (drv->key_count != 0) + return EFI_SUCCESS; + else { + /* EFI is certainly polling. Be CPU-friendly. */ + usleep (50000); + return EFI_NOT_READY; + } +} + +static +EFI_STATUS +UgaGetKey(EFI_UNIX_UGA_IO_PROTOCOL *UgaIo, EFI_INPUT_KEY *key) +{ + UGA_IO_PRIVATE *drv = (UGA_IO_PRIVATE *)UgaIo; + EFI_STATUS status; + + status = UgaCheckKey(UgaIo); + if (status != EFI_SUCCESS) + return status; + + *key = drv->keys[drv->key_rd]; + drv->key_rd = (drv->key_rd + 1) % NBR_KEYS; + drv->key_count--; + return EFI_SUCCESS; +} + +EFI_STATUS
+UgaBlt(EFI_UNIX_UGA_IO_PROTOCOL *UgaIo, + IN EFI_UGA_PIXEL *BltBuffer OPTIONAL,
+ IN EFI_UGA_BLT_OPERATION BltOperation,
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta OPTIONAL
+ )
+{ + UGA_IO_PRIVATE *Private = (UGA_IO_PRIVATE *)UgaIo; + UINTN DstY;
+ UINTN SrcY;
+ UINTN DstX; + UINTN SrcX; + UINTN Index; + EFI_UGA_PIXEL *Blt;
+ UINT8 *Dst; + UINT8 *Src; + UINTN Nbr; + unsigned long Color; + + // + // Check bounds + // + if (BltOperation == EfiUgaVideoToBltBuffer + || BltOperation == EfiUgaVideoToVideo) {
+ //
+ // Source is Video. + //
+ if (SourceY + Height > Private->height) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (SourceX + Width > Private->width) {
+ return EFI_INVALID_PARAMETER;
+ }
+ } + + if (BltOperation == EfiUgaBltBufferToVideo + || BltOperation == EfiUgaVideoToVideo + || BltOperation == EfiUgaVideoFill) {
+ //
+ // Destination is Video
+ //
+ if (DestinationY + Height > Private->height) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (DestinationX + Width > Private->width) {
+ return EFI_INVALID_PARAMETER;
+ }
+ } + + switch (BltOperation) {
+ case EfiUgaVideoToBltBuffer: + Blt = BltBuffer; + Delta -= Width * sizeof (EFI_UGA_PIXEL); + for (SrcY = SourceY; SrcY < (Height + SourceY); SrcY++) {
+ for (SrcX = SourceX; SrcX < (Width + SourceX); SrcX++) { + *Blt++ = UgaColorToPixel(Private, + XGetPixel(Private->image, SrcX, SrcY)); + } + Blt = (EFI_UGA_PIXEL *) ((UINT8 *) Blt + Delta); + }
+ break; + case EfiUgaBltBufferToVideo:
+ Blt = BltBuffer; + Delta -= Width * sizeof (EFI_UGA_PIXEL); + for (DstY = DestinationY; DstY < (Height + DestinationY); DstY++) {
+ for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {
+ XPutPixel(Private->image, DstX, DstY, UgaPixelToColor(Private, *Blt)); + Blt++; + } + Blt = (EFI_UGA_PIXEL *) ((UINT8 *) Blt + Delta); + } + break; + case EfiUgaVideoToVideo:
+ Dst = Private->image_data + (DestinationX << Private->pixel_shift) + + DestinationY * Private->line_bytes; + Src = Private->image_data + (SourceX << Private->pixel_shift) + + SourceY * Private->line_bytes; + Nbr = Width << Private->pixel_shift; + if (DestinationY < SourceY) {
+ for (Index = 0; Index < Height; Index++) { + memcpy (Dst, Src, Nbr); + Dst += Private->line_bytes; + Src += Private->line_bytes; + } + } + else { + Dst += (Height - 1) * Private->line_bytes; + Src += (Height - 1) * Private->line_bytes; + for (Index = 0; Index < 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 = UgaPixelToColor(Private, *BltBuffer); + for (DstY = DestinationY; DstY < (Height + DestinationY); DstY++) {
+ for (DstX = DestinationX; DstX < (Width + 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, + SourceX, SourceY, Width, Height, DestinationX, DestinationY); + while (1) { + XEvent ev; + + XNextEvent (Private->display, &ev); + HandleEvent(Private, &ev); + if (ev.type == NoExpose || ev.type == GraphicsExpose) + break; + } + break; + case EfiUgaVideoFill: + Color = UgaPixelToColor(Private, *BltBuffer); + XSetForeground(Private->display, Private->gc, Color); + XFillRectangle(Private->display, Private->win, Private->gc, + DestinationX, DestinationY, Width, Height); + break; + case EfiUgaBltBufferToVideo:
+ Redraw(Private, DestinationX, DestinationY, Width, Height); + break; + default: + break; + } + return EFI_SUCCESS; +} + +EFI_STATUS +UgaCreate (EFI_UNIX_UGA_IO_PROTOCOL **Uga, CONST CHAR16 *Title) +{ + UGA_IO_PRIVATE *drv; + unsigned int border_width = 0; + char *display_name = NULL; + int title_len; + + drv = (UGA_IO_PRIVATE *) + malloc (sizeof (UGA_IO_PRIVATE)); + if (drv == NULL) + return EFI_OUT_OF_RESOURCES; + + drv->UgaIo.UgaClose = UgaClose; + drv->UgaIo.UgaSize = UgaSize; + drv->UgaIo.UgaCheckKey = UgaCheckKey; + drv->UgaIo.UgaGetKey = UgaGetKey; + drv->UgaIo.UgaBlt = UgaBlt; + + drv->key_count = 0; + drv->key_rd = 0; + drv->key_wr = 0; + 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, + BlackPixel (drv->display, drv->screen), + WhitePixel (drv->display, drv->screen)); + + drv->depth = DefaultDepth (drv->display, drv->screen); + + /* Compute title len and convert to Ascii. */ + for (title_len = 0; Title[title_len] != 0; title_len++) + ; + { + char title[title_len + 1]; + int i; + for (i = 0; i < title_len; i++) + title[i] = Title[i]; + title[i] = 0; + + XStoreName (drv->display, drv->win, title); + } + + XSelectInput (drv->display, drv->win, + ExposureMask | KeyPressMask); + drv->gc = DefaultGC (drv->display, drv->screen); + + *Uga = (EFI_UNIX_UGA_IO_PROTOCOL *)drv; + return EFI_SUCCESS; +} diff --git a/EdkUnixPkg/Sec/UnixThunk.c b/EdkUnixPkg/Sec/UnixThunk.c new file mode 100644 index 0000000..a94cb38 --- /dev/null +++ b/EdkUnixPkg/Sec/UnixThunk.c @@ -0,0 +1,189 @@ +/*++
+
+Copyright (c) 2004 - 2006, 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.
+
+Module Name:
+
+ UnixThunk.c
+
+Abstract:
+
+ Since the SEC is the only program in our emulation we
+ must use a Tiano mechanism to export APIs to other modules.
+ This is the role of the EFI_UNIX_THUNK_PROTOCOL.
+
+ The mUnixThunkTable exists so that a change to EFI_UNIX_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.
+
+
+ gUnix is a a public exported global that contains the initialized
+ data.
+
+--*/
+
+#include "SecMain.h"
+#include "Library/UnixLib.h" +#include <sys/time.h> +#include <time.h> +#include <signal.h> +#include <string.h> +#include <stdlib.h> + +static int settimer_initialized; +static struct timeval settimer_timeval; +static void (*settimer_callback)(UINT64 delta); + +static 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) + (*settimer_callback)(delta); +} + +static +VOID +SetTimer (UINT64 PeriodMs, VOID (*CallBack)(UINT64 DeltaMs)) +{ + struct itimerval timerval; + + if (!settimer_initialized) { + struct sigaction act; + + settimer_initialized = 1; + act.sa_handler = settimer_handler; + act.sa_flags = 0; + sigemptyset (&act.sa_mask); + 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 = PeriodMs / 1000; + timerval.it_value.tv_usec = (PeriodMs % 1000) * 1000; + timerval.it_value.tv_sec = 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 +GetLocalTime (EFI_TIME *Time) +{ + struct tm *tm; + time_t t; + + t = time (NULL); + tm = localtime (&t); + + Time->Year = 1900 + tm->tm_year; + Time->Month = tm->tm_mon; + 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); +} + +void +msSleep (unsigned long Milliseconds) +{ + usleep (Milliseconds * 1000); +} + +static void +TzSet (void) +{ + static int done = 0; + if (!done) { + tzset (); + done = 1; + } +} + +long +GetTimeZone(void) +{ + TzSet (); + return timezone; +} + +int +GetDayLight(void) +{ + TzSet (); + return daylight; +} + +int +GetErrno(void) +{ + return errno; +} + +extern EFI_STATUS +UgaCreate(struct _EFI_UNIX_UGA_IO_PROTOCOL *UgaIo, CONST CHAR16 *Title); + +EFI_UNIX_THUNK_PROTOCOL mUnixThunkTable = {
+ EFI_UNIX_THUNK_PROTOCOL_SIGNATURE,
+ msSleep, /* Sleep */ + exit, /* Exit */ + SetTimer, + GetLocalTime, + gmtime, + GetTimeZone, + GetDayLight, + (UnixPoll)poll, + (UnixRead)read, + (UnixWrite)write, + getenv, + (UnixOpen)open, + lseek, + ftruncate, + close, + mkdir, + rmdir, + unlink, + GetErrno, + opendir, + rewinddir, + readdir, + closedir, + stat, + statfs, + rename, + mktime, + fsync, + chmod, + utime, + + UgaCreate, +};
+
+
+EFI_UNIX_THUNK_PROTOCOL *gUnix = &mUnixThunkTable;
|