Home | History | Annotate | Line # | Download | only in lib
      1  1.2  jmcneill /*	$NetBSD: sread.c,v 1.2 2021/10/23 15:20:26 jmcneill Exp $	*/
      2  1.1  jakllsch 
      3  1.1  jakllsch /*++
      4  1.1  jakllsch 
      5  1.1  jakllsch Copyright (c) 1998  Intel Corporation
      6  1.1  jakllsch 
      7  1.1  jakllsch Module Name:
      8  1.1  jakllsch 
      9  1.1  jakllsch     sread.c
     10  1.1  jakllsch 
     11  1.1  jakllsch Abstract:
     12  1.1  jakllsch 
     13  1.1  jakllsch     Simple read file access
     14  1.1  jakllsch 
     15  1.1  jakllsch 
     16  1.1  jakllsch 
     17  1.1  jakllsch Revision History
     18  1.1  jakllsch 
     19  1.1  jakllsch --*/
     20  1.1  jakllsch 
     21  1.1  jakllsch #include "lib.h"
     22  1.1  jakllsch 
     23  1.1  jakllsch #define SIMPLE_READ_SIGNATURE       EFI_SIGNATURE_32('s','r','d','r')
     24  1.1  jakllsch typedef struct _SIMPLE_READ_FILE {
     25  1.1  jakllsch     UINTN               Signature;
     26  1.1  jakllsch     BOOLEAN             FreeBuffer;
     27  1.1  jakllsch     VOID                *Source;
     28  1.1  jakllsch     UINTN               SourceSize;
     29  1.1  jakllsch     EFI_FILE_HANDLE     FileHandle;
     30  1.1  jakllsch } SIMPLE_READ_HANDLE;
     31  1.1  jakllsch 
     32  1.1  jakllsch 
     33  1.1  jakllsch 
     34  1.1  jakllsch EFI_STATUS
     35  1.1  jakllsch OpenSimpleReadFile (
     36  1.1  jakllsch     IN BOOLEAN                  BootPolicy,
     37  1.1  jakllsch     IN VOID                     *SourceBuffer   OPTIONAL,
     38  1.1  jakllsch     IN UINTN                    SourceSize,
     39  1.1  jakllsch     IN OUT EFI_DEVICE_PATH      **FilePath,
     40  1.1  jakllsch     OUT EFI_HANDLE              *DeviceHandle,
     41  1.1  jakllsch     OUT SIMPLE_READ_FILE        *SimpleReadHandle
     42  1.1  jakllsch     )
     43  1.1  jakllsch /*++
     44  1.1  jakllsch 
     45  1.1  jakllsch Routine Description:
     46  1.1  jakllsch 
     47  1.1  jakllsch     Opens a file for (simple) reading.  The simple read abstraction
     48  1.1  jakllsch     will access the file either from a memory copy, from a file
     49  1.1  jakllsch     system interface, or from the load file interface.
     50  1.1  jakllsch 
     51  1.1  jakllsch Arguments:
     52  1.1  jakllsch 
     53  1.1  jakllsch Returns:
     54  1.1  jakllsch 
     55  1.1  jakllsch     A handle to access the file
     56  1.1  jakllsch 
     57  1.1  jakllsch --*/
     58  1.1  jakllsch {
     59  1.1  jakllsch     SIMPLE_READ_HANDLE          *FHand;
     60  1.1  jakllsch     EFI_DEVICE_PATH             *UserFilePath;
     61  1.1  jakllsch     EFI_DEVICE_PATH             *TempFilePath;
     62  1.1  jakllsch     EFI_DEVICE_PATH             *TempFilePathPtr;
     63  1.1  jakllsch     FILEPATH_DEVICE_PATH        *FilePathNode;
     64  1.2  jmcneill     EFI_DEVICE_PATH_PROTOCOL    *AlignedFilePath;
     65  1.1  jakllsch     EFI_FILE_HANDLE             FileHandle, LastHandle;
     66  1.1  jakllsch     EFI_STATUS                  Status;
     67  1.1  jakllsch     EFI_LOAD_FILE_INTERFACE     *LoadFile;
     68  1.1  jakllsch 
     69  1.1  jakllsch     FHand = NULL;
     70  1.2  jmcneill     AlignedFilePath = NULL;
     71  1.1  jakllsch     UserFilePath = *FilePath;
     72  1.1  jakllsch 
     73  1.1  jakllsch     //
     74  1.1  jakllsch     // Allocate a new simple read handle structure
     75  1.1  jakllsch     //
     76  1.1  jakllsch 
     77  1.1  jakllsch     FHand = AllocateZeroPool (sizeof(SIMPLE_READ_HANDLE));
     78  1.1  jakllsch     if (!FHand) {
     79  1.1  jakllsch         Status = EFI_OUT_OF_RESOURCES;
     80  1.1  jakllsch         goto Done;
     81  1.1  jakllsch     }
     82  1.1  jakllsch 
     83  1.1  jakllsch     *SimpleReadHandle = (SIMPLE_READ_FILE) FHand;
     84  1.1  jakllsch     FHand->Signature = SIMPLE_READ_SIGNATURE;
     85  1.1  jakllsch 
     86  1.1  jakllsch     //
     87  1.1  jakllsch     // If the caller passed a copy of the file, then just use it
     88  1.1  jakllsch     //
     89  1.1  jakllsch 
     90  1.1  jakllsch     if (SourceBuffer) {
     91  1.1  jakllsch         FHand->Source = SourceBuffer;
     92  1.1  jakllsch         FHand->SourceSize = SourceSize;
     93  1.1  jakllsch         *DeviceHandle = NULL;
     94  1.1  jakllsch         Status = EFI_SUCCESS;
     95  1.1  jakllsch         goto Done;
     96  1.1  jakllsch     }
     97  1.1  jakllsch 
     98  1.1  jakllsch     //
     99  1.1  jakllsch     // Attempt to access the file via a file system interface
    100  1.1  jakllsch     //
    101  1.1  jakllsch 
    102  1.1  jakllsch     FileHandle = NULL;
    103  1.1  jakllsch     Status = uefi_call_wrapper(BS->LocateDevicePath, 3, &FileSystemProtocol, FilePath, DeviceHandle);
    104  1.1  jakllsch     if (!EFI_ERROR(Status)) {
    105  1.1  jakllsch         FileHandle = LibOpenRoot (*DeviceHandle);
    106  1.1  jakllsch     }
    107  1.1  jakllsch 
    108  1.1  jakllsch     Status = FileHandle ? EFI_SUCCESS : EFI_UNSUPPORTED;
    109  1.1  jakllsch 
    110  1.1  jakllsch     //
    111  1.2  jmcneill     // Duplicate FilePath to make sure it is aligned so that
    112  1.2  jmcneill     // FilePathNode->PathName below is 16-bit aligned.
    113  1.2  jmcneill     //
    114  1.2  jmcneill     AlignedFilePath = DuplicateDevicePath(*FilePath);
    115  1.2  jmcneill     if (AlignedFilePath == NULL) {
    116  1.2  jmcneill         if (FileHandle != NULL) {
    117  1.2  jmcneill             uefi_call_wrapper(FileHandle->Close, 1, FileHandle);
    118  1.2  jmcneill         }
    119  1.2  jmcneill         return EFI_OUT_OF_RESOURCES;
    120  1.2  jmcneill     }
    121  1.2  jmcneill 
    122  1.2  jmcneill     //
    123  1.1  jakllsch     // To access as a filesystem, the filepath should only
    124  1.1  jakllsch     // contain filepath components.  Follow the filepath nodes
    125  1.1  jakllsch     // and find the target file
    126  1.1  jakllsch     //
    127  1.1  jakllsch 
    128  1.2  jmcneill     FilePathNode = (FILEPATH_DEVICE_PATH *)AlignedFilePath;
    129  1.1  jakllsch     while (!IsDevicePathEnd(&FilePathNode->Header)) {
    130  1.1  jakllsch 
    131  1.1  jakllsch         //
    132  1.1  jakllsch         // For filesystem access each node should be a filepath component
    133  1.1  jakllsch         //
    134  1.1  jakllsch 
    135  1.1  jakllsch         if (DevicePathType(&FilePathNode->Header) != MEDIA_DEVICE_PATH ||
    136  1.1  jakllsch             DevicePathSubType(&FilePathNode->Header) != MEDIA_FILEPATH_DP) {
    137  1.1  jakllsch             Status = EFI_UNSUPPORTED;
    138  1.1  jakllsch         }
    139  1.1  jakllsch 
    140  1.1  jakllsch         //
    141  1.1  jakllsch         // If there's been an error, stop
    142  1.1  jakllsch         //
    143  1.1  jakllsch 
    144  1.1  jakllsch         if (EFI_ERROR(Status)) {
    145  1.1  jakllsch             break;
    146  1.1  jakllsch         }
    147  1.1  jakllsch 
    148  1.1  jakllsch         //
    149  1.1  jakllsch         // Open this file path node
    150  1.1  jakllsch         //
    151  1.1  jakllsch 
    152  1.1  jakllsch         LastHandle = FileHandle;
    153  1.1  jakllsch         FileHandle = NULL;
    154  1.1  jakllsch 
    155  1.1  jakllsch         Status = uefi_call_wrapper(
    156  1.1  jakllsch 			LastHandle->Open,
    157  1.1  jakllsch 			5,
    158  1.1  jakllsch                         LastHandle,
    159  1.1  jakllsch                         &FileHandle,
    160  1.1  jakllsch                         FilePathNode->PathName,
    161  1.1  jakllsch                         EFI_FILE_MODE_READ,
    162  1.1  jakllsch                         0
    163  1.1  jakllsch                         );
    164  1.1  jakllsch 
    165  1.1  jakllsch         //
    166  1.1  jakllsch         // Close the last node
    167  1.1  jakllsch         //
    168  1.1  jakllsch 
    169  1.1  jakllsch         uefi_call_wrapper(LastHandle->Close, 1, LastHandle);
    170  1.1  jakllsch 
    171  1.1  jakllsch         //
    172  1.1  jakllsch         // Get the next node
    173  1.1  jakllsch         //
    174  1.1  jakllsch 
    175  1.1  jakllsch         FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode(&FilePathNode->Header);
    176  1.1  jakllsch     }
    177  1.1  jakllsch 
    178  1.1  jakllsch     //
    179  1.1  jakllsch     // If success, return the FHand
    180  1.1  jakllsch     //
    181  1.1  jakllsch 
    182  1.1  jakllsch     if (!EFI_ERROR(Status)) {
    183  1.1  jakllsch         ASSERT(FileHandle);
    184  1.1  jakllsch         FHand->FileHandle = FileHandle;
    185  1.1  jakllsch         goto Done;
    186  1.1  jakllsch     }
    187  1.1  jakllsch 
    188  1.1  jakllsch     //
    189  1.1  jakllsch     // Cleanup from filesystem access
    190  1.1  jakllsch     //
    191  1.1  jakllsch 
    192  1.1  jakllsch     if (FileHandle) {
    193  1.1  jakllsch         uefi_call_wrapper(FileHandle->Close, 1, FileHandle);
    194  1.1  jakllsch         FileHandle = NULL;
    195  1.1  jakllsch         *FilePath = UserFilePath;
    196  1.1  jakllsch     }
    197  1.1  jakllsch 
    198  1.1  jakllsch     //
    199  1.1  jakllsch     // If the error is something other then unsupported, return it
    200  1.1  jakllsch     //
    201  1.1  jakllsch 
    202  1.1  jakllsch     if (Status != EFI_UNSUPPORTED) {
    203  1.1  jakllsch         goto Done;
    204  1.1  jakllsch     }
    205  1.1  jakllsch 
    206  1.1  jakllsch     //
    207  1.1  jakllsch     // Attempt to access the file via the load file protocol
    208  1.1  jakllsch     //
    209  1.1  jakllsch 
    210  1.1  jakllsch     Status = LibDevicePathToInterface (&LoadFileProtocol, *FilePath, (VOID*)&LoadFile);
    211  1.1  jakllsch     if (!EFI_ERROR(Status)) {
    212  1.1  jakllsch 
    213  1.1  jakllsch         TempFilePath = DuplicateDevicePath (*FilePath);
    214  1.1  jakllsch 
    215  1.1  jakllsch         TempFilePathPtr = TempFilePath;
    216  1.1  jakllsch 
    217  1.1  jakllsch         Status = uefi_call_wrapper(BS->LocateDevicePath, 3, &LoadFileProtocol, &TempFilePath, DeviceHandle);
    218  1.1  jakllsch 
    219  1.1  jakllsch         FreePool (TempFilePathPtr);
    220  1.1  jakllsch 
    221  1.1  jakllsch         //
    222  1.1  jakllsch         // Determine the size of buffer needed to hold the file
    223  1.1  jakllsch         //
    224  1.1  jakllsch 
    225  1.1  jakllsch         SourceSize = 0;
    226  1.1  jakllsch         Status = uefi_call_wrapper(
    227  1.1  jakllsch 		    LoadFile->LoadFile,
    228  1.1  jakllsch 			5,
    229  1.1  jakllsch                     LoadFile,
    230  1.1  jakllsch                     *FilePath,
    231  1.1  jakllsch                     BootPolicy,
    232  1.1  jakllsch                     &SourceSize,
    233  1.1  jakllsch                     NULL
    234  1.1  jakllsch                     );
    235  1.1  jakllsch 
    236  1.1  jakllsch         //
    237  1.1  jakllsch         // We expect a buffer too small error to inform us
    238  1.1  jakllsch         // of the buffer size needed
    239  1.1  jakllsch         //
    240  1.1  jakllsch 
    241  1.1  jakllsch         if (Status == EFI_BUFFER_TOO_SMALL) {
    242  1.1  jakllsch             SourceBuffer = AllocatePool (SourceSize);
    243  1.1  jakllsch 
    244  1.1  jakllsch             if (SourceBuffer) {
    245  1.1  jakllsch                 FHand->FreeBuffer = TRUE;
    246  1.1  jakllsch                 FHand->Source = SourceBuffer;
    247  1.1  jakllsch                 FHand->SourceSize = SourceSize;
    248  1.1  jakllsch 
    249  1.1  jakllsch                 Status = uefi_call_wrapper(
    250  1.1  jakllsch 			    LoadFile->LoadFile,
    251  1.1  jakllsch 				5,
    252  1.1  jakllsch                             LoadFile,
    253  1.1  jakllsch                             *FilePath,
    254  1.1  jakllsch                             BootPolicy,
    255  1.1  jakllsch                             &SourceSize,
    256  1.1  jakllsch                             SourceBuffer
    257  1.1  jakllsch                             );
    258  1.1  jakllsch             }
    259  1.1  jakllsch         }
    260  1.1  jakllsch 
    261  1.1  jakllsch         //
    262  1.1  jakllsch         // If success, return FHand
    263  1.1  jakllsch         //
    264  1.1  jakllsch 
    265  1.1  jakllsch         if (!EFI_ERROR(Status) || Status == EFI_ALREADY_STARTED) {
    266  1.1  jakllsch             goto Done;
    267  1.1  jakllsch         }
    268  1.1  jakllsch     }
    269  1.1  jakllsch 
    270  1.1  jakllsch     //
    271  1.1  jakllsch     // Nothing else to try
    272  1.1  jakllsch     //
    273  1.1  jakllsch 
    274  1.1  jakllsch     DEBUG ((D_LOAD|D_WARN, "OpenSimpleReadFile: Device did not support a known load protocol\n"));
    275  1.1  jakllsch     Status = EFI_UNSUPPORTED;
    276  1.1  jakllsch 
    277  1.1  jakllsch Done:
    278  1.1  jakllsch 
    279  1.2  jmcneill     if (AlignedFilePath) {
    280  1.2  jmcneill         FreePool (AlignedFilePath);
    281  1.2  jmcneill     }
    282  1.2  jmcneill 
    283  1.1  jakllsch     //
    284  1.1  jakllsch     // If the file was not accessed, clean up
    285  1.1  jakllsch     //
    286  1.1  jakllsch     if (EFI_ERROR(Status) && (Status != EFI_ALREADY_STARTED)) {
    287  1.1  jakllsch         if (FHand) {
    288  1.1  jakllsch             if (FHand->FreeBuffer) {
    289  1.1  jakllsch                 FreePool (FHand->Source);
    290  1.1  jakllsch             }
    291  1.1  jakllsch 
    292  1.1  jakllsch             FreePool (FHand);
    293  1.1  jakllsch         }
    294  1.1  jakllsch     }
    295  1.1  jakllsch 
    296  1.1  jakllsch     return Status;
    297  1.1  jakllsch }
    298  1.1  jakllsch 
    299  1.1  jakllsch EFI_STATUS
    300  1.1  jakllsch ReadSimpleReadFile (
    301  1.1  jakllsch     IN SIMPLE_READ_FILE     UserHandle,
    302  1.1  jakllsch     IN UINTN                Offset,
    303  1.1  jakllsch     IN OUT UINTN            *ReadSize,
    304  1.1  jakllsch     OUT VOID                *Buffer
    305  1.1  jakllsch     )
    306  1.1  jakllsch {
    307  1.1  jakllsch     UINTN                   EndPos;
    308  1.1  jakllsch     SIMPLE_READ_HANDLE      *FHand;
    309  1.1  jakllsch     EFI_STATUS              Status;
    310  1.1  jakllsch 
    311  1.1  jakllsch     FHand = UserHandle;
    312  1.1  jakllsch     ASSERT (FHand->Signature == SIMPLE_READ_SIGNATURE);
    313  1.1  jakllsch     if (FHand->Source) {
    314  1.1  jakllsch 
    315  1.1  jakllsch         //
    316  1.1  jakllsch         // Move data from our local copy of the file
    317  1.1  jakllsch         //
    318  1.1  jakllsch 
    319  1.1  jakllsch         EndPos = Offset + *ReadSize;
    320  1.1  jakllsch         if (EndPos > FHand->SourceSize) {
    321  1.1  jakllsch             *ReadSize = FHand->SourceSize - Offset;
    322  1.1  jakllsch             if (Offset >= FHand->SourceSize) {
    323  1.1  jakllsch                 *ReadSize = 0;
    324  1.1  jakllsch             }
    325  1.1  jakllsch         }
    326  1.1  jakllsch 
    327  1.1  jakllsch         CopyMem (Buffer, (CHAR8 *) FHand->Source + Offset, *ReadSize);
    328  1.1  jakllsch         Status = EFI_SUCCESS;
    329  1.1  jakllsch 
    330  1.1  jakllsch     } else {
    331  1.1  jakllsch 
    332  1.1  jakllsch         //
    333  1.1  jakllsch         // Read data from the file
    334  1.1  jakllsch         //
    335  1.1  jakllsch 
    336  1.1  jakllsch         Status = uefi_call_wrapper(FHand->FileHandle->SetPosition, 2, FHand->FileHandle, Offset);
    337  1.1  jakllsch 
    338  1.1  jakllsch         if (!EFI_ERROR(Status)) {
    339  1.1  jakllsch             Status = uefi_call_wrapper(FHand->FileHandle->Read, 3, FHand->FileHandle, ReadSize, Buffer);
    340  1.1  jakllsch         }
    341  1.1  jakllsch     }
    342  1.1  jakllsch 
    343  1.1  jakllsch     return Status;
    344  1.1  jakllsch }
    345  1.1  jakllsch 
    346  1.1  jakllsch 
    347  1.1  jakllsch VOID
    348  1.1  jakllsch CloseSimpleReadFile (
    349  1.1  jakllsch     IN SIMPLE_READ_FILE     UserHandle
    350  1.1  jakllsch     )
    351  1.1  jakllsch {
    352  1.1  jakllsch     SIMPLE_READ_HANDLE      *FHand;
    353  1.1  jakllsch 
    354  1.1  jakllsch     FHand = UserHandle;
    355  1.1  jakllsch     ASSERT (FHand->Signature == SIMPLE_READ_SIGNATURE);
    356  1.1  jakllsch 
    357  1.1  jakllsch     //
    358  1.1  jakllsch     // Free any file handle we opened
    359  1.1  jakllsch     //
    360  1.1  jakllsch 
    361  1.1  jakllsch     if (FHand->FileHandle) {
    362  1.1  jakllsch         uefi_call_wrapper(FHand->FileHandle->Close, 1, FHand->FileHandle);
    363  1.1  jakllsch     }
    364  1.1  jakllsch 
    365  1.1  jakllsch     //
    366  1.1  jakllsch     // If we allocated the Source buffer, free it
    367  1.1  jakllsch     //
    368  1.1  jakllsch 
    369  1.1  jakllsch     if (FHand->FreeBuffer) {
    370  1.1  jakllsch         FreePool (FHand->Source);
    371  1.1  jakllsch     }
    372  1.1  jakllsch 
    373  1.1  jakllsch     //
    374  1.1  jakllsch     // Done with this simple read file handle
    375  1.1  jakllsch     //
    376  1.1  jakllsch 
    377  1.1  jakllsch     FreePool (FHand);
    378  1.1  jakllsch }
    379