3 Copyright (c) 1998 Intel Corporation
11 Simple read file access
21 #define SIMPLE_READ_SIGNATURE EFI_SIGNATURE_32('s','r','d','r')
22 typedef struct _SIMPLE_READ_FILE {
27 EFI_FILE_HANDLE FileHandle;
34 IN BOOLEAN BootPolicy,
35 IN VOID *SourceBuffer OPTIONAL,
37 IN OUT EFI_DEVICE_PATH **FilePath,
38 OUT EFI_HANDLE *DeviceHandle,
39 OUT SIMPLE_READ_FILE *SimpleReadHandle
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.
53 A handle to access the file
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;
64 EFI_LOAD_FILE_INTERFACE *LoadFile;
67 UserFilePath = *FilePath;
70 // Allocate a new simple read handle structure
73 FHand = AllocateZeroPool (sizeof(SIMPLE_READ_HANDLE));
75 Status = EFI_OUT_OF_RESOURCES;
79 *SimpleReadHandle = (SIMPLE_READ_FILE) FHand;
80 FHand->Signature = SIMPLE_READ_SIGNATURE;
83 // If the caller passed a copy of the file, then just use it
87 FHand->Source = SourceBuffer;
88 FHand->SourceSize = SourceSize;
95 // Attempt to access the file via a file system interface
99 Status = uefi_call_wrapper(BS->LocateDevicePath, 3, &FileSystemProtocol, FilePath, DeviceHandle);
100 if (!EFI_ERROR(Status)) {
101 FileHandle = LibOpenRoot (*DeviceHandle);
104 Status = FileHandle ? EFI_SUCCESS : EFI_UNSUPPORTED;
107 // To access as a filesystem, the filepath should only
108 // contain filepath components. Follow the filepath nodes
109 // and find the target file
112 FilePathNode = (FILEPATH_DEVICE_PATH *) *FilePath;
113 while (!IsDevicePathEnd(&FilePathNode->Header)) {
116 // For filesystem access each node should be a filepath component
119 if (DevicePathType(&FilePathNode->Header) != MEDIA_DEVICE_PATH ||
120 DevicePathSubType(&FilePathNode->Header) != MEDIA_FILEPATH_DP) {
121 Status = EFI_UNSUPPORTED;
125 // If there's been an error, stop
128 if (EFI_ERROR(Status)) {
133 // Open this file path node
136 LastHandle = FileHandle;
139 Status = uefi_call_wrapper(
144 FilePathNode->PathName,
150 // Close the last node
153 uefi_call_wrapper(LastHandle->Close, 1, LastHandle);
159 FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode(&FilePathNode->Header);
163 // If success, return the FHand
166 if (!EFI_ERROR(Status)) {
168 FHand->FileHandle = FileHandle;
173 // Cleanup from filesystem access
177 uefi_call_wrapper(FileHandle->Close, 1, FileHandle);
179 *FilePath = UserFilePath;
183 // If the error is something other then unsupported, return it
186 if (Status != EFI_UNSUPPORTED) {
191 // Attempt to access the file via the load file protocol
194 Status = LibDevicePathToInterface (&LoadFileProtocol, *FilePath, (VOID*)&LoadFile);
195 if (!EFI_ERROR(Status)) {
197 TempFilePath = DuplicateDevicePath (*FilePath);
199 TempFilePathPtr = TempFilePath;
201 Status = uefi_call_wrapper(BS->LocateDevicePath, 3, &LoadFileProtocol, &TempFilePath, DeviceHandle);
203 FreePool (TempFilePathPtr);
206 // Determine the size of buffer needed to hold the file
210 Status = uefi_call_wrapper(
221 // We expect a buffer too small error to inform us
222 // of the buffer size needed
225 if (Status == EFI_BUFFER_TOO_SMALL) {
226 SourceBuffer = AllocatePool (SourceSize);
229 FHand->FreeBuffer = TRUE;
230 FHand->Source = SourceBuffer;
231 FHand->SourceSize = SourceSize;
233 Status = uefi_call_wrapper(
246 // If success, return FHand
249 if (!EFI_ERROR(Status) || Status == EFI_ALREADY_STARTED) {
255 // Nothing else to try
258 DEBUG ((D_LOAD|D_WARN, "OpenSimpleReadFile: Device did not support a known load protocol\n"));
259 Status = EFI_UNSUPPORTED;
264 // If the file was not accessed, clean up
266 if (EFI_ERROR(Status) && (Status != EFI_ALREADY_STARTED)) {
268 if (FHand->FreeBuffer) {
269 FreePool (FHand->Source);
281 IN SIMPLE_READ_FILE UserHandle,
283 IN OUT UINTN *ReadSize,
288 SIMPLE_READ_HANDLE *FHand;
292 ASSERT (FHand->Signature == SIMPLE_READ_SIGNATURE);
296 // Move data from our local copy of the file
299 EndPos = Offset + *ReadSize;
300 if (EndPos > FHand->SourceSize) {
301 *ReadSize = FHand->SourceSize - Offset;
302 if (Offset >= FHand->SourceSize) {
307 CopyMem (Buffer, (CHAR8 *) FHand->Source + Offset, *ReadSize);
308 Status = EFI_SUCCESS;
313 // Read data from the file
316 Status = uefi_call_wrapper(FHand->FileHandle->SetPosition, 2, FHand->FileHandle, Offset);
318 if (!EFI_ERROR(Status)) {
319 Status = uefi_call_wrapper(FHand->FileHandle->Read, 3, FHand->FileHandle, ReadSize, Buffer);
328 CloseSimpleReadFile (
329 IN SIMPLE_READ_FILE UserHandle
332 SIMPLE_READ_HANDLE *FHand;
335 ASSERT (FHand->Signature == SIMPLE_READ_SIGNATURE);
338 // Free any file handle we opened
341 if (FHand->FileHandle) {
342 uefi_call_wrapper(FHand->FileHandle->Close, 1, FHand->FileHandle);
346 // If we allocated the Source buffer, free it
349 if (FHand->FreeBuffer) {
350 FreePool (FHand->Source);
354 // Done with this simple read file handle