From cc6947172dcced4f7909eb351981b3413bb9a27a Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Tue, 12 Jul 2016 14:37:54 +0800 Subject: Clib/EFI: Add file position seeking/telling support This patch adds file position seeking/telling support. Lv Zheng. Signed-off-by: Lv Zheng --- source/include/platform/acefiex.h | 31 ++++++++ source/os_specific/efi/oseficlib.c | 142 ++++++++++++++++++++++++++++++++++++- 2 files changed, 171 insertions(+), 2 deletions(-) diff --git a/source/include/platform/acefiex.h b/source/include/platform/acefiex.h index 9f5b9208c..e90b89712 100644 --- a/source/include/platform/acefiex.h +++ b/source/include/platform/acefiex.h @@ -167,6 +167,20 @@ typedef struct { UINT8 Data4[8]; } ACPI_EFI_GUID; +typedef struct { + UINT16 Year; /* 1998 - 20XX */ + UINT8 Month; /* 1 - 12 */ + UINT8 Day; /* 1 - 31 */ + UINT8 Hour; /* 0 - 23 */ + UINT8 Minute; /* 0 - 59 */ + UINT8 Second; /* 0 - 59 */ + UINT8 Pad1; + UINT32 Nanosecond; /* 0 - 999,999,999 */ + INT16 TimeZone; /* -1440 to 1440 or 2047 */ + UINT8 Daylight; + UINT8 Pad2; +} ACPI_EFI_TIME; + typedef struct _ACPI_EFI_DEVICE_PATH { UINT8 Type; UINT8 SubType; @@ -447,6 +461,22 @@ ACPI_EFI_STATUS struct _ACPI_EFI_FILE_HANDLE *File, UINT64 *Position); +#define ACPI_EFI_FILE_INFO_ID \ + { 0x9576e92, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } + +typedef struct { + UINT64 Size; + UINT64 FileSize; + UINT64 PhysicalSize; + ACPI_EFI_TIME CreateTime; + ACPI_EFI_TIME LastAccessTime; + ACPI_EFI_TIME ModificationTime; + UINT64 Attribute; + CHAR16 FileName[1]; +} ACPI_EFI_FILE_INFO; + +#define SIZE_OF_ACPI_EFI_FILE_INFO ACPI_OFFSET(ACPI_EFI_FILE_INFO, FileName) + typedef ACPI_EFI_STATUS (ACPI_EFI_API *ACPI_EFI_FILE_GET_INFO) ( @@ -1018,5 +1048,6 @@ extern ACPI_EFI_GUID AcpiGbl_LoadedImageProtocol; extern ACPI_EFI_GUID AcpiGbl_TextInProtocol; extern ACPI_EFI_GUID AcpiGbl_TextOutProtocol; extern ACPI_EFI_GUID AcpiGbl_FileSystemProtocol; +extern ACPI_EFI_GUID AcpiGbl_GenericFileInfo; #endif /* __ACEFIEX_H__ */ diff --git a/source/os_specific/efi/oseficlib.c b/source/os_specific/efi/oseficlib.c index 96b6f9f9c..333031801 100644 --- a/source/os_specific/efi/oseficlib.c +++ b/source/os_specific/efi/oseficlib.c @@ -153,6 +153,11 @@ AcpiEfiConvertArgcv ( char ***ArgvPtr, char **BufferPtr); +static int +AcpiEfiGetFileInfo ( + FILE *File, + ACPI_EFI_FILE_INFO **InfoPtr); + static CHAR16 * AcpiEfiFlushFile ( FILE *File, @@ -172,6 +177,7 @@ ACPI_EFI_GUID AcpiGbl_LoadedImageProtocol = ACPI_EFI_LOADED_IMAGE_ ACPI_EFI_GUID AcpiGbl_TextInProtocol = ACPI_SIMPLE_TEXT_INPUT_PROTOCOL; ACPI_EFI_GUID AcpiGbl_TextOutProtocol = ACPI_SIMPLE_TEXT_OUTPUT_PROTOCOL; ACPI_EFI_GUID AcpiGbl_FileSystemProtocol = ACPI_SIMPLE_FILE_SYSTEM_PROTOCOL; +ACPI_EFI_GUID AcpiGbl_GenericFileInfo = ACPI_EFI_FILE_INFO_ID; int errno = 0; @@ -681,13 +687,70 @@ ErrorExit: } +/******************************************************************************* + * + * FUNCTION: AcpiEfiGetFileInfo + * + * PARAMETERS: File - File descriptor + * InfoPtr - Pointer to contain file information + * + * RETURN: Clibrary error code + * + * DESCRIPTION: Get file information. + * + ******************************************************************************/ + +static int +AcpiEfiGetFileInfo ( + FILE *File, + ACPI_EFI_FILE_INFO **InfoPtr) +{ + ACPI_EFI_STATUS EfiStatus = ACPI_EFI_BUFFER_TOO_SMALL; + ACPI_EFI_FILE_INFO *Buffer = NULL; + UINTN BufferSize = SIZE_OF_ACPI_EFI_FILE_INFO + 200; + ACPI_EFI_FILE_HANDLE EfiFile; + + + if (!InfoPtr) + { + errno = EINVAL; + return (-EINVAL); + } + + while (EfiStatus == ACPI_EFI_BUFFER_TOO_SMALL) + { + EfiFile = (ACPI_EFI_FILE_HANDLE) File; + Buffer = AcpiOsAllocate (BufferSize); + if (!Buffer) + { + errno = ENOMEM; + return (-ENOMEM); + } + EfiStatus = uefi_call_wrapper (EfiFile->GetInfo, 4, EfiFile, + &AcpiGbl_GenericFileInfo, &BufferSize, Buffer); + if (ACPI_EFI_ERROR (EfiStatus)) + { + AcpiOsFree (Buffer); + if (EfiStatus != ACPI_EFI_BUFFER_TOO_SMALL) + { + errno = EIO; + return (-EIO); + } + } + } + + *InfoPtr = Buffer; + return (0); +} + + /******************************************************************************* * * FUNCTION: ftell * * PARAMETERS: File - File descriptor * - * RETURN: Size of current position + * RETURN: current position * * DESCRIPTION: Get current file offset. * @@ -698,8 +761,32 @@ ftell ( FILE *File) { long Offset = -1; + UINT64 Current; + ACPI_EFI_STATUS EfiStatus; + ACPI_EFI_FILE_HANDLE EfiFile; + + if (File == stdin || File == stdout || File == stderr) + { + Offset = 0; + } + else + { + EfiFile = (ACPI_EFI_FILE_HANDLE) File; + + EfiStatus = uefi_call_wrapper (EfiFile->GetPosition, 2, + EfiFile, &Current); + if (ACPI_EFI_ERROR (EfiStatus)) + { + goto ErrorExit; + } + else + { + Offset = (long) Current; + } + } +ErrorExit: return (Offset); } @@ -724,8 +811,59 @@ fseek ( long Offset, int From) { + ACPI_EFI_FILE_INFO *Info; + int Error; + ACPI_SIZE Size; + UINT64 Current; + ACPI_EFI_STATUS EfiStatus; + ACPI_EFI_FILE_HANDLE EfiFile; + + + if (File == stdin || File == stdout || File == stderr) + { + return (0); + } + else + { + EfiFile = (ACPI_EFI_FILE_HANDLE) File; + Error = AcpiEfiGetFileInfo (File, &Info); + if (Error) + { + return (Error); + } + Size = Info->FileSize; + AcpiOsFree (Info); + + if (From == SEEK_CUR) + { + EfiStatus = uefi_call_wrapper (EfiFile->GetPosition, 2, + EfiFile, &Current); + if (ACPI_EFI_ERROR (EfiStatus)) + { + errno = ERANGE; + return (-ERANGE); + } + Current += Offset; + } + else if (From == SEEK_END) + { + Current = Size - Offset; + } + else + { + Current = Offset; + } - return (-1); + EfiStatus = uefi_call_wrapper (EfiFile->SetPosition, 2, + EfiFile, Current); + if (ACPI_EFI_ERROR (EfiStatus)) + { + errno = ERANGE; + return (-ERANGE); + } + } + + return (0); } -- cgit v1.2.1