|
|
/*++
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; 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 = BS->LocateDevicePath (&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 = LastHandle->Open ( LastHandle, &FileHandle, FilePathNode->PathName, EFI_FILE_MODE_READ, 0 ); /*
* Close the last node */ LastHandle->Close (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) { FileHandle->Close (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)) {
/*
* Determine the size of buffer needed to hold the file */
SourceSize = 0; Status = LoadFile->LoadFile ( 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 = LoadFile->LoadFile ( LoadFile, *FilePath, BootPolicy, &SourceSize, SourceBuffer ); } }
/*
* If success, return FHand */
if (!EFI_ERROR(Status)) { 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)) { 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 = FHand->FileHandle->SetPosition (FHand->FileHandle, Offset);
if (!EFI_ERROR(Status)) { Status = FHand->FileHandle->Read (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) { FHand->FileHandle->Close (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); }
|