aboutsummaryrefslogtreecommitdiff
path: root/gnu-efi/gnu-efi-3.0/lib/sread.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu-efi/gnu-efi-3.0/lib/sread.c')
-rw-r--r--gnu-efi/gnu-efi-3.0/lib/sread.c358
1 files changed, 358 insertions, 0 deletions
diff --git a/gnu-efi/gnu-efi-3.0/lib/sread.c b/gnu-efi/gnu-efi-3.0/lib/sread.c
new file mode 100644
index 0000000..888f954
--- /dev/null
+++ b/gnu-efi/gnu-efi-3.0/lib/sread.c
@@ -0,0 +1,358 @@
+/*++
+
+Copyright (c) 1998 Intel Corporation
+
+Module Name:
+
+ sread.c
+
+Abstract:
+
+ Simple read file access
+
+
+
+Revision History
+
+--*/
+
+#include "lib.h"
+
+#define SIMPLE_READ_SIGNATURE EFI_SIGNATURE_32('s','r','d','r')
+typedef struct _SIMPLE_READ_FILE {
+ UINTN Signature;
+ BOOLEAN FreeBuffer;
+ VOID *Source;
+ UINTN SourceSize;
+ EFI_FILE_HANDLE FileHandle;
+} SIMPLE_READ_HANDLE;
+
+
+
+EFI_STATUS
+OpenSimpleReadFile (
+ IN BOOLEAN BootPolicy,
+ IN VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ IN OUT EFI_DEVICE_PATH **FilePath,
+ OUT EFI_HANDLE *DeviceHandle,
+ OUT SIMPLE_READ_FILE *SimpleReadHandle
+ )
+/*++
+
+Routine Description:
+
+ Opens a file for (simple) reading. The simple read abstraction
+ will access the file either from a memory copy, from a file
+ system interface, or from the load file interface.
+
+Arguments:
+
+Returns:
+
+ A handle to access the file
+
+--*/
+{
+ SIMPLE_READ_HANDLE *FHand;
+ EFI_DEVICE_PATH *UserFilePath;
+ EFI_DEVICE_PATH *TempFilePath;
+ EFI_DEVICE_PATH *TempFilePathPtr;
+ FILEPATH_DEVICE_PATH *FilePathNode;
+ EFI_FILE_HANDLE FileHandle, LastHandle;
+ EFI_STATUS Status;
+ EFI_LOAD_FILE_INTERFACE *LoadFile;
+
+ FHand = NULL;
+ UserFilePath = *FilePath;
+
+ //
+ // Allocate a new simple read handle structure
+ //
+
+ FHand = AllocateZeroPool (sizeof(SIMPLE_READ_HANDLE));
+ if (!FHand) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ *SimpleReadHandle = (SIMPLE_READ_FILE) FHand;
+ FHand->Signature = SIMPLE_READ_SIGNATURE;
+
+ //
+ // If the caller passed a copy of the file, then just use it
+ //
+
+ if (SourceBuffer) {
+ FHand->Source = SourceBuffer;
+ FHand->SourceSize = SourceSize;
+ *DeviceHandle = NULL;
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ //
+ // Attempt to access the file via a file system interface
+ //
+
+ FileHandle = NULL;
+ Status = uefi_call_wrapper(BS->LocateDevicePath, 3, &FileSystemProtocol, FilePath, DeviceHandle);
+ if (!EFI_ERROR(Status)) {
+ FileHandle = LibOpenRoot (*DeviceHandle);
+ }
+
+ Status = FileHandle ? EFI_SUCCESS : EFI_UNSUPPORTED;
+
+ //
+ // To access as a filesystem, the filepath should only
+ // contain filepath components. Follow the filepath nodes
+ // and find the target file
+ //
+
+ FilePathNode = (FILEPATH_DEVICE_PATH *) *FilePath;
+ while (!IsDevicePathEnd(&FilePathNode->Header)) {
+
+ //
+ // For filesystem access each node should be a filepath component
+ //
+
+ if (DevicePathType(&FilePathNode->Header) != MEDIA_DEVICE_PATH ||
+ DevicePathSubType(&FilePathNode->Header) != MEDIA_FILEPATH_DP) {
+ Status = EFI_UNSUPPORTED;
+ }
+
+ //
+ // If there's been an error, stop
+ //
+
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+
+ //
+ // Open this file path node
+ //
+
+ LastHandle = FileHandle;
+ FileHandle = NULL;
+
+ Status = uefi_call_wrapper(
+ LastHandle->Open,
+ 5,
+ LastHandle,
+ &FileHandle,
+ FilePathNode->PathName,
+ EFI_FILE_MODE_READ,
+ 0
+ );
+
+ //
+ // Close the last node
+ //
+
+ uefi_call_wrapper(LastHandle->Close, 1, LastHandle);
+
+ //
+ // Get the next node
+ //
+
+ FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode(&FilePathNode->Header);
+ }
+
+ //
+ // If success, return the FHand
+ //
+
+ if (!EFI_ERROR(Status)) {
+ ASSERT(FileHandle);
+ FHand->FileHandle = FileHandle;
+ goto Done;
+ }
+
+ //
+ // Cleanup from filesystem access
+ //
+
+ if (FileHandle) {
+ uefi_call_wrapper(FileHandle->Close, 1, FileHandle);
+ FileHandle = NULL;
+ *FilePath = UserFilePath;
+ }
+
+ //
+ // If the error is something other then unsupported, return it
+ //
+
+ if (Status != EFI_UNSUPPORTED) {
+ goto Done;
+ }
+
+ //
+ // Attempt to access the file via the load file protocol
+ //
+
+ Status = LibDevicePathToInterface (&LoadFileProtocol, *FilePath, (VOID*)&LoadFile);
+ if (!EFI_ERROR(Status)) {
+
+ TempFilePath = DuplicateDevicePath (*FilePath);
+
+ TempFilePathPtr = TempFilePath;
+
+ Status = uefi_call_wrapper(BS->LocateDevicePath, 3, &LoadFileProtocol, &TempFilePath, DeviceHandle);
+
+ FreePool (TempFilePathPtr);
+
+ //
+ // Determine the size of buffer needed to hold the file
+ //
+
+ SourceSize = 0;
+ Status = uefi_call_wrapper(
+ LoadFile->LoadFile,
+ 5,
+ LoadFile,
+ *FilePath,
+ BootPolicy,
+ &SourceSize,
+ NULL
+ );
+
+ //
+ // We expect a buffer too small error to inform us
+ // of the buffer size needed
+ //
+
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ SourceBuffer = AllocatePool (SourceSize);
+
+ if (SourceBuffer) {
+ FHand->FreeBuffer = TRUE;
+ FHand->Source = SourceBuffer;
+ FHand->SourceSize = SourceSize;
+
+ Status = uefi_call_wrapper(
+ LoadFile->LoadFile,
+ 5,
+ LoadFile,
+ *FilePath,
+ BootPolicy,
+ &SourceSize,
+ SourceBuffer
+ );
+ }
+ }
+
+ //
+ // If success, return FHand
+ //
+
+ if (!EFI_ERROR(Status) || Status == EFI_ALREADY_STARTED) {
+ goto Done;
+ }
+ }
+
+ //
+ // Nothing else to try
+ //
+
+ DEBUG ((D_LOAD|D_WARN, "OpenSimpleReadFile: Device did not support a known load protocol\n"));
+ Status = EFI_UNSUPPORTED;
+
+Done:
+
+ //
+ // If the file was not accessed, clean up
+ //
+ if (EFI_ERROR(Status) && (Status != EFI_ALREADY_STARTED)) {
+ if (FHand) {
+ if (FHand->FreeBuffer) {
+ FreePool (FHand->Source);
+ }
+
+ FreePool (FHand);
+ }
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+ReadSimpleReadFile (
+ IN SIMPLE_READ_FILE UserHandle,
+ IN UINTN Offset,
+ IN OUT UINTN *ReadSize,
+ OUT VOID *Buffer
+ )
+{
+ UINTN EndPos;
+ SIMPLE_READ_HANDLE *FHand;
+ EFI_STATUS Status;
+
+ FHand = UserHandle;
+ ASSERT (FHand->Signature == SIMPLE_READ_SIGNATURE);
+ if (FHand->Source) {
+
+ //
+ // Move data from our local copy of the file
+ //
+
+ EndPos = Offset + *ReadSize;
+ if (EndPos > FHand->SourceSize) {
+ *ReadSize = FHand->SourceSize - Offset;
+ if (Offset >= FHand->SourceSize) {
+ *ReadSize = 0;
+ }
+ }
+
+ CopyMem (Buffer, (CHAR8 *) FHand->Source + Offset, *ReadSize);
+ Status = EFI_SUCCESS;
+
+ } else {
+
+ //
+ // Read data from the file
+ //
+
+ Status = uefi_call_wrapper(FHand->FileHandle->SetPosition, 2, FHand->FileHandle, Offset);
+
+ if (!EFI_ERROR(Status)) {
+ Status = uefi_call_wrapper(FHand->FileHandle->Read, 3, FHand->FileHandle, ReadSize, Buffer);
+ }
+ }
+
+ return Status;
+}
+
+
+VOID
+CloseSimpleReadFile (
+ IN SIMPLE_READ_FILE UserHandle
+ )
+{
+ SIMPLE_READ_HANDLE *FHand;
+
+ FHand = UserHandle;
+ ASSERT (FHand->Signature == SIMPLE_READ_SIGNATURE);
+
+ //
+ // Free any file handle we opened
+ //
+
+ if (FHand->FileHandle) {
+ uefi_call_wrapper(FHand->FileHandle->Close, 1, FHand->FileHandle);
+ }
+
+ //
+ // If we allocated the Source buffer, free it
+ //
+
+ if (FHand->FreeBuffer) {
+ FreePool (FHand->Source);
+ }
+
+ //
+ // Done with this simple read file handle
+ //
+
+ FreePool (FHand);
+}