/****************************************************************************** * * Module Name: osefixf - EFI OSL interfaces * *****************************************************************************/ /* * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * substantially similar to the "NO WARRANTY" disclaimer below * ("Disclaimer") and any redistribution must be conditioned upon * including a substantially similar Disclaimer requirement for further * binary redistribution. * 3. Neither the names of the above-listed copyright holders nor the names * of any contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * Alternatively, this software may be distributed under the terms of the * GNU General Public License ("GPL") version 2 as published by the Free * Software Foundation. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. */ #include "acpi.h" #include "accommon.h" #include "acapps.h" /* Local definitions */ #define ACPI_EFI_PRINT_LENGTH 256 /* Local prototypes */ static ACPI_STATUS AcpiEfiArgify ( char *String, int *ArgcPtr, char ***ArgvPtr); static BOOLEAN AcpiEfiCompareGuid ( EFI_GUID *Guid1, EFI_GUID *Guid2); static ACPI_STATUS AcpiEfiConvertArgcv ( CHAR16 *LoadOpt, UINT32 LoadOptSize, int *ArgcPtr, char ***ArgvPtr, char **BufferPtr); static ACPI_PHYSICAL_ADDRESS AcpiEfiGetRsdpViaGuid ( EFI_GUID *Guid); static CHAR16 * AcpiEfiFlushFile ( ACPI_FILE File, CHAR16 *Begin, CHAR16 *End, CHAR16 *Pos, BOOLEAN FlushAll); /* Local variables */ static EFI_FILE_HANDLE AcpiGbl_EfiCurrentVolume = NULL; /****************************************************************************** * * FUNCTION: AcpiEfiGetRsdpViaGuid * * PARAMETERS: Guid1 - GUID to compare * Guid2 - GUID to compare * * RETURN: TRUE if Guid1 == Guid2 * * DESCRIPTION: Compares two GUIDs * *****************************************************************************/ static BOOLEAN AcpiEfiCompareGuid ( EFI_GUID *Guid1, EFI_GUID *Guid2) { INT32 *g1; INT32 *g2; INT32 r; g1 = (INT32 *) Guid1; g2 = (INT32 *) Guid2; r = g1[0] - g2[0]; r |= g1[1] - g2[1]; r |= g1[2] - g2[2]; r |= g1[3] - g2[3]; return (r ? FALSE : TRUE); } /****************************************************************************** * * FUNCTION: AcpiEfiGetRsdpViaGuid * * PARAMETERS: None * * RETURN: RSDP address if found * * DESCRIPTION: Find RSDP address via EFI using specified GUID. * *****************************************************************************/ static ACPI_PHYSICAL_ADDRESS AcpiEfiGetRsdpViaGuid ( EFI_GUID *Guid) { unsigned long Address = 0; int i; for (i = 0; i < ST->NumberOfTableEntries; i++) { if (AcpiEfiCompareGuid (&ST->ConfigurationTable[i].VendorGuid, Guid)) { Address = (ACPI_PHYSICAL_ADDRESS) ST->ConfigurationTable[i].VendorTable; break; } } return ((ACPI_PHYSICAL_ADDRESS) (Address)); } /****************************************************************************** * * FUNCTION: AcpiOsGetRootPointer * * PARAMETERS: None * * RETURN: RSDP physical address * * DESCRIPTION: Gets the ACPI root pointer (RSDP) * *****************************************************************************/ ACPI_PHYSICAL_ADDRESS AcpiOsGetRootPointer ( void) { ACPI_PHYSICAL_ADDRESS Address; EFI_GUID Guid10 = ACPI_TABLE_GUID; EFI_GUID Guid20 = ACPI_20_TABLE_GUID; Address = AcpiEfiGetRsdpViaGuid (&Guid20); if (!Address) { Address = AcpiEfiGetRsdpViaGuid (&Guid10); } return (Address); } /****************************************************************************** * * FUNCTION: AcpiOsMapMemory * * PARAMETERS: where - Physical address of memory to be mapped * length - How much memory to map * * RETURN: Pointer to mapped memory. Null on error. * * DESCRIPTION: Map physical memory into caller's address space * *****************************************************************************/ void * AcpiOsMapMemory ( ACPI_PHYSICAL_ADDRESS where, ACPI_SIZE length) { return (ACPI_TO_POINTER ((ACPI_SIZE) where)); } /****************************************************************************** * * FUNCTION: AcpiOsUnmapMemory * * PARAMETERS: where - Logical address of memory to be unmapped * length - How much memory to unmap * * RETURN: None * * DESCRIPTION: Delete a previously created mapping. Where and Length must * correspond to a previous mapping exactly. * *****************************************************************************/ void AcpiOsUnmapMemory ( void *where, ACPI_SIZE length) { return; } /****************************************************************************** * * FUNCTION: Spinlock interfaces * * DESCRIPTION: No-op on single threaded BIOS * *****************************************************************************/ ACPI_STATUS AcpiOsCreateLock ( ACPI_SPINLOCK *OutHandle) { return (AE_OK); } void AcpiOsDeleteLock ( ACPI_SPINLOCK Handle) { } ACPI_CPU_FLAGS AcpiOsAcquireLock ( ACPI_SPINLOCK Handle) { return (0); } void AcpiOsReleaseLock ( ACPI_SPINLOCK Handle, ACPI_CPU_FLAGS Flags) { } /****************************************************************************** * * FUNCTION: AcpiOsAllocate * * PARAMETERS: Size - Amount to allocate, in bytes * * RETURN: Pointer to the new allocation. Null on error. * * DESCRIPTION: Allocate memory. Algorithm is dependent on the OS. * *****************************************************************************/ void * AcpiOsAllocate ( ACPI_SIZE Size) { EFI_STATUS EfiStatus; void *Mem; EfiStatus = uefi_call_wrapper (BS->AllocatePool, 3, EfiLoaderData, Size, &Mem); if (EFI_ERROR (EfiStatus)) { AcpiLogError ("EFI_BOOT_SERVICES->AllocatePool(EfiLoaderData) failure.\n"); return (NULL); } return (Mem); } #ifdef USE_NATIVE_ALLOCATE_ZEROED /****************************************************************************** * * FUNCTION: AcpiOsAllocateZeroed * * PARAMETERS: Size - Amount to allocate, in bytes * * RETURN: Pointer to the new allocation. Null on error. * * DESCRIPTION: Allocate and zero memory. Algorithm is dependent on the OS. * *****************************************************************************/ void * AcpiOsAllocateZeroed ( ACPI_SIZE Size) { void *Mem; Mem = AcpiOsAllocate (Size); if (Mem) { ACPI_MEMSET (Mem, 0, Size); } return (Mem); } #endif /****************************************************************************** * * FUNCTION: AcpiOsFree * * PARAMETERS: Mem - Pointer to previously allocated memory * * RETURN: None * * DESCRIPTION: Free memory allocated via AcpiOsAllocate * *****************************************************************************/ void AcpiOsFree ( void *Mem) { uefi_call_wrapper (BS->FreePool, 1, Mem); } /******************************************************************************* * * FUNCTION: AcpiOsOpenFile * * PARAMETERS: Path - File path * Modes - File operation type * * RETURN: File descriptor * * DESCRIPTION: Open a file for reading (ACPI_FILE_READING) or/and writing * (ACPI_FILE_WRITING). * ******************************************************************************/ ACPI_FILE AcpiOsOpenFile ( const char *Path, UINT8 Modes) { EFI_STATUS EfiStatus = EFI_SUCCESS; UINT64 OpenModes; EFI_FILE_HANDLE EfiFile = NULL; CHAR16 *Path16 = NULL; CHAR16 *Pos16; const char *Pos; INTN Count, i; if (!Path) { return (NULL); } /* Convert modes */ OpenModes = EFI_FILE_MODE_READ; if (Modes & ACPI_FILE_WRITING) { OpenModes |= (EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE); } /* Allocate path buffer */ Count = ACPI_STRLEN (Path); Path16 = ACPI_ALLOCATE_ZEROED ((Count + 1) * sizeof (CHAR16)); if (!Path16) { EfiStatus = EFI_BAD_BUFFER_SIZE; goto ErrorExit; } Pos = Path; Pos16 = Path16; while (*Pos == '/' || *Pos == '\\') { Pos++; Count--; } for (i = 0; i < Count; i++) { if (*Pos == '/') { *Pos16++ = '\\'; Pos++; } else { *Pos16++ = *Pos++; } } *Pos16 = '\0'; EfiStatus = uefi_call_wrapper (AcpiGbl_EfiCurrentVolume->Open, 5, AcpiGbl_EfiCurrentVolume, &EfiFile, Path16, OpenModes, 0); if (EFI_ERROR (EfiStatus)) { AcpiLogError ("EFI_FILE_HANDLE->Open() failure.\n"); goto ErrorExit; } ErrorExit: if (Path16) { ACPI_FREE (Path16); } return ((ACPI_FILE) EfiFile); } /******************************************************************************* * * FUNCTION: AcpiOsCloseFile * * PARAMETERS: File - File descriptor * * RETURN: None. * * DESCRIPTION: Close a file. * ******************************************************************************/ void AcpiOsCloseFile ( ACPI_FILE File) { EFI_FILE_HANDLE EfiFile; if (File == ACPI_FILE_OUT || File == ACPI_FILE_ERR) { return; } EfiFile = (EFI_FILE_HANDLE) File; (void) uefi_call_wrapper (AcpiGbl_EfiCurrentVolume->Close, 1, EfiFile); return; } /******************************************************************************* * * FUNCTION: AcpiOsReadFile * * PARAMETERS: File - File descriptor * Buffer - Data buffer * Size - Data block size * Count - Number of data blocks * * RETURN: Size of successfully read buffer * * DESCRIPTION: Read from a file. * ******************************************************************************/ int AcpiOsReadFile ( ACPI_FILE File, void *Buffer, ACPI_SIZE Size, ACPI_SIZE Count) { int Length = -1; EFI_FILE_HANDLE EfiFile; UINTN ReadSize; EFI_STATUS EfiStatus; if (File == ACPI_FILE_OUT || File == ACPI_FILE_ERR) { } else { EfiFile = (EFI_FILE_HANDLE) File; if (!EfiFile) { goto ErrorExit; } ReadSize = Size * Count; EfiStatus = uefi_call_wrapper (AcpiGbl_EfiCurrentVolume->Read, 3, EfiFile, &ReadSize, Buffer); if (EFI_ERROR (EfiStatus)) { AcpiLogError ("EFI_FILE_HANDLE->Read() failure.\n"); goto ErrorExit; } Length = ReadSize; } ErrorExit: return (Length); } /******************************************************************************* * * FUNCTION: AcpiEfiFlushFile * * PARAMETERS: File - File descriptor * Begin - String with boundary * End - Boundary of the string * Pos - Current position * FlushAll - Whether checking boundary before flushing * * RETURN: Updated position * * DESCRIPTION: Flush cached buffer to the file. * ******************************************************************************/ static CHAR16 * AcpiEfiFlushFile ( ACPI_FILE File, CHAR16 *Begin, CHAR16 *End, CHAR16 *Pos, BOOLEAN FlushAll) { if (FlushAll || Pos >= (End - 1)) { *Pos = 0; uefi_call_wrapper (File->OutputString, 2, File, Begin); Pos = Begin; } return (Pos); } /******************************************************************************* * * FUNCTION: AcpiOsWriteFile * * PARAMETERS: File - File descriptor * Buffer - Data buffer * Size - Data block size * Count - Number of data blocks * * RETURN: Size of successfully written buffer * * DESCRIPTION: Write to a file. * ******************************************************************************/ int AcpiOsWriteFile ( ACPI_FILE File, void *Buffer, ACPI_SIZE Size, ACPI_SIZE Count) { int Length = -1; CHAR16 String[ACPI_EFI_PRINT_LENGTH]; const char *Ascii; CHAR16 *End; CHAR16 *Pos; int i, j; EFI_FILE_HANDLE EfiFile; UINTN WriteSize; EFI_STATUS EfiStatus; if (File == ACPI_FILE_OUT || File == ACPI_FILE_ERR) { Pos = String; End = String + ACPI_EFI_PRINT_LENGTH - 1; Ascii = ACPI_CAST_PTR (const char, Buffer); Length = 0; for (j = 0; j < Count; j++) { for (i = 0; i < Size; i++) { if (*Ascii == '\n') { *Pos++ = '\r'; Pos = AcpiEfiFlushFile (File, String, End, Pos, FALSE); } *Pos++ = *Ascii++; Length++; Pos = AcpiEfiFlushFile (File, String, End, Pos, FALSE); } } Pos = AcpiEfiFlushFile (File, String, End, Pos, TRUE); } else { EfiFile = (EFI_FILE_HANDLE) File; if (!EfiFile) { goto ErrorExit; } WriteSize = Size * Count; EfiStatus = uefi_call_wrapper (AcpiGbl_EfiCurrentVolume->Write, 3, EfiFile, &WriteSize, Buffer); if (EFI_ERROR (EfiStatus)) { AcpiLogError ("EFI_FILE_HANDLE->Write() failure.\n"); goto ErrorExit; } Length = WriteSize; } ErrorExit: return (Length); } /******************************************************************************* * * FUNCTION: AcpiOsGetFileOffset * * PARAMETERS: File - File descriptor * * RETURN: Size of current position * * DESCRIPTION: Get current file offset. * ******************************************************************************/ long AcpiOsGetFileOffset ( ACPI_FILE File) { long Offset = -1; return (Offset); } /******************************************************************************* * * FUNCTION: AcpiOsSetFileOffset * * PARAMETERS: File - File descriptor * Offset - File offset * From - From begin/end of file * * RETURN: Status * * DESCRIPTION: Set current file offset. * ******************************************************************************/ ACPI_STATUS AcpiOsSetFileOffset ( ACPI_FILE File, long Offset, UINT8 From) { return (AE_SUPPORT); } /****************************************************************************** * * FUNCTION: AcpiOsPrintf * * PARAMETERS: Format, ... - Standard printf format * * RETURN: None * * DESCRIPTION: Formatted output. * *****************************************************************************/ void ACPI_INTERNAL_VAR_XFACE AcpiOsPrintf ( const char *Format, ...) { va_list Args; va_start (Args, Format); AcpiOsVprintf (Format, Args); va_end (Args); } /****************************************************************************** * * FUNCTION: AcpiOsVprintf * * PARAMETERS: Format - Standard printf format * Args - Argument list * * RETURN: None * * DESCRIPTION: Formatted output with arguments list pointer. * *****************************************************************************/ void AcpiOsVprintf ( const char *Format, va_list Args) { (void) AcpiUtFileVprintf (ACPI_FILE_OUT, Format, Args); } /****************************************************************************** * * FUNCTION: AcpiOsInitialize * * PARAMETERS: None * * RETURN: Status * * DESCRIPTION: Initialize this module. * *****************************************************************************/ ACPI_STATUS AcpiOsInitialize ( void) { return (AE_OK); } /****************************************************************************** * * FUNCTION: AcpiEfiArgify * * PARAMETERS: String - Pointer to command line argument strings * which are seperated with spaces * ArgcPtr - Return number of the arguments * ArgvPtr - Return vector of the arguments * * RETURN: Status * * DESCRIPTION: Convert EFI arguments into C arguments. * *****************************************************************************/ static ACPI_STATUS AcpiEfiArgify ( char *String, int *ArgcPtr, char ***ArgvPtr) { char *CopyBuffer; int MaxArgc = *ArgcPtr; int Argc = 0; char **Argv = *ArgvPtr; char *Arg; BOOLEAN IsSingleQuote = FALSE; BOOLEAN IsDoubleQuote = FALSE; BOOLEAN IsEscape = FALSE; if (String == NULL) { return (AE_BAD_PARAMETER); } CopyBuffer = String; while (*String != '\0') { while (ACPI_IS_SPACE (*String)) { *String++ = '\0'; } Arg = CopyBuffer; while (*String != '\0') { if (ACPI_IS_SPACE (*String) && !IsSingleQuote && !IsDoubleQuote && !IsEscape) { *Arg++ = '\0'; String++; break; } if (IsEscape) { IsEscape = FALSE; *Arg++ = *String; } else if (*String == '\\') { IsEscape = TRUE; } else if (IsSingleQuote) { if (*String == '\'') { IsSingleQuote = FALSE; *Arg++ = '\0'; } else { *Arg++ = *String; } } else if (IsDoubleQuote) { if (*String == '"') { IsDoubleQuote = FALSE; *Arg = '\0'; } else { *Arg++ = *String; } } else { if (*String == '\'') { IsSingleQuote = TRUE; } else if (*String == '"') { IsDoubleQuote = TRUE; } else { *Arg++ = *String; } } String++; } if (Argv && Argc < MaxArgc) { Argv[Argc] = CopyBuffer; } Argc++; CopyBuffer = Arg; } if (Argv && Argc < MaxArgc) { Argv[Argc] = NULL; } *ArgcPtr = Argc; *ArgvPtr = Argv; return ((MaxArgc < Argc) ? AE_NO_MEMORY : AE_OK); } /****************************************************************************** * * FUNCTION: AcpiEfiConvertArgcv * * PARAMETERS: LoadOptions - Pointer to the EFI options buffer, which * is NULL terminated * LoadOptionsSize - Size of the EFI options buffer * ArgcPtr - Return number of the arguments * ArgvPtr - Return vector of the arguments * BufferPtr - Buffer to contain the argument strings * * RETURN: Status * * DESCRIPTION: Convert EFI arguments into C arguments. * *****************************************************************************/ static ACPI_STATUS AcpiEfiConvertArgcv ( CHAR16 *LoadOptions, UINT32 LoadOptionsSize, int *ArgcPtr, char ***ArgvPtr, char **BufferPtr) { ACPI_STATUS Status = AE_OK; UINT32 Count = LoadOptionsSize / sizeof (CHAR16); UINT32 i; CHAR16 *From; char *To; int Argc = 0; char **Argv = NULL; char *Buffer; /* Prepare a buffer to contain the argument strings */ Buffer = ACPI_ALLOCATE_ZEROED (Count); if (!Buffer) { Status = AE_NO_MEMORY; goto ErrorExit; } TryAgain: /* Extend the argument vector */ if (Argv) { ACPI_FREE (Argv); Argv = NULL; } if (Argc > 0) { Argv = ACPI_ALLOCATE_ZEROED (sizeof (char *) * (Argc + 1)); if (!Argv) { Status = AE_NO_MEMORY; goto ErrorExit; } } /* * Note: As AcpiEfiArgify() will modify the content of the buffer, so * we need to restore it each time before invoking * AcpiEfiArgify(). */ From = LoadOptions; To = ACPI_CAST_PTR (char, Buffer); for (i = 0; i < Count; i++) { *To++ = (char) *From++; } /* * The "Buffer" will contain NULL terminated strings after invoking * AcpiEfiArgify(). The number of the strings are saved in Argc and the * pointers of the strings are saved in Argv. */ Status = AcpiEfiArgify (Buffer, &Argc, &Argv); if (ACPI_FAILURE (Status)) { if (Status == AE_NO_MEMORY) { goto TryAgain; } } ErrorExit: if (ACPI_FAILURE (Status)) { ACPI_FREE (Buffer); ACPI_FREE (Argv); } else { *ArgcPtr = Argc; *ArgvPtr = Argv; *BufferPtr = Buffer; } return (Status); } /****************************************************************************** * * FUNCTION: efi_main * * PARAMETERS: Image - EFI image handle * SystemTab - EFI system table * * RETURN: EFI Status * * DESCRIPTION: Entry point of EFI executable * *****************************************************************************/ EFI_STATUS efi_main ( EFI_HANDLE Image, EFI_SYSTEM_TABLE *SystemTab) { EFI_LOADED_IMAGE *Info; EFI_STATUS EfiStatus = EFI_SUCCESS; ACPI_STATUS Status; int argc; char **argv = NULL; char *OptBuffer = NULL; EFI_FILE_IO_INTERFACE *Volume = NULL; /* Initialize EFI library */ InitializeLib (Image, SystemTab); /* Retrieve image information */ EfiStatus = uefi_call_wrapper (BS->HandleProtocol, 3, Image, &LoadedImageProtocol, ACPI_CAST_PTR (VOID, &Info)); if (EFI_ERROR (EfiStatus)) { AcpiLogError ("EFI_BOOT_SERVICES->HandleProtocol(LoadedImageProtocol) failure.\n"); return (EfiStatus); } EfiStatus = uefi_call_wrapper (BS->HandleProtocol, 3, Info->DeviceHandle, &FileSystemProtocol, (void **) &Volume); if (EFI_ERROR (EfiStatus)) { AcpiLogError ("EFI_BOOT_SERVICES->HandleProtocol(FileSystemProtocol) failure.\n"); return (EfiStatus); } EfiStatus = uefi_call_wrapper (Volume->OpenVolume, 2, Volume, &AcpiGbl_EfiCurrentVolume); if (EFI_ERROR (EfiStatus)) { AcpiLogError ("EFI_FILE_IO_INTERFACE->OpenVolume() failure.\n"); return (EfiStatus); } Status = AcpiEfiConvertArgcv (Info->LoadOptions, Info->LoadOptionsSize, &argc, &argv, &OptBuffer); if (ACPI_FAILURE (Status)) { EfiStatus = EFI_DEVICE_ERROR; goto ErrorAlloc; } acpi_main (argc, argv); ErrorAlloc: if (argv) { ACPI_FREE (argv); } if (OptBuffer) { ACPI_FREE (OptBuffer); } return (EfiStatus); }