Subversion Repositories HelenOS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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