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