source: bootcd/isolinux/syslinux-6.03/gnu-efi/gnu-efi-3.0/lib/sread.c @ e16e8f2

Last change on this file since e16e8f2 was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 8.1 KB
Line 
1/*++
2
3Copyright (c) 1998  Intel Corporation
4
5Module Name:
6   
7    sread.c
8
9Abstract:
10
11    Simple read file access
12
13
14
15Revision History
16
17--*/
18
19#include "lib.h"
20
21#define SIMPLE_READ_SIGNATURE       EFI_SIGNATURE_32('s','r','d','r')
22typedef 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
32EFI_STATUS
33OpenSimpleReadFile (
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
43Routine 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
49Arguments:
50
51Returns:
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 = uefi_call_wrapper(BS->LocateDevicePath, 3, &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 = uefi_call_wrapper(
140                        LastHandle->Open,
141                        5,
142                        LastHandle,
143                        &FileHandle,
144                        FilePathNode->PathName,
145                        EFI_FILE_MODE_READ,
146                        0
147                        );
148       
149        //
150        // Close the last node
151        //
152       
153        uefi_call_wrapper(LastHandle->Close, 1, LastHandle);
154
155        //
156        // Get the next node
157        //
158
159        FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode(&FilePathNode->Header);
160    }
161
162    //
163    // If success, return the FHand
164    //
165
166    if (!EFI_ERROR(Status)) {
167        ASSERT(FileHandle);
168        FHand->FileHandle = FileHandle;
169        goto Done;
170    }
171
172    //
173    // Cleanup from filesystem access
174    //
175
176    if (FileHandle) {
177        uefi_call_wrapper(FileHandle->Close, 1, FileHandle);
178        FileHandle = NULL;
179        *FilePath = UserFilePath;
180    }
181
182    //
183    // If the error is something other then unsupported, return it
184    //
185
186    if (Status != EFI_UNSUPPORTED) {
187        goto Done;
188    }
189
190    //
191    // Attempt to access the file via the load file protocol
192    //
193
194    Status = LibDevicePathToInterface (&LoadFileProtocol, *FilePath, (VOID*)&LoadFile);
195    if (!EFI_ERROR(Status)) {
196
197        TempFilePath = DuplicateDevicePath (*FilePath);
198
199        TempFilePathPtr = TempFilePath;
200
201        Status = uefi_call_wrapper(BS->LocateDevicePath, 3, &LoadFileProtocol, &TempFilePath, DeviceHandle);
202
203        FreePool (TempFilePathPtr);
204
205        //
206        // Determine the size of buffer needed to hold the file
207        //
208
209        SourceSize = 0;
210        Status = uefi_call_wrapper(
211                    LoadFile->LoadFile,
212                        5,
213                    LoadFile,
214                    *FilePath,
215                    BootPolicy,
216                    &SourceSize,
217                    NULL
218                    );
219
220        //
221        // We expect a buffer too small error to inform us
222        // of the buffer size needed
223        //
224
225        if (Status == EFI_BUFFER_TOO_SMALL) {
226            SourceBuffer = AllocatePool (SourceSize);
227           
228            if (SourceBuffer) {
229                FHand->FreeBuffer = TRUE;
230                FHand->Source = SourceBuffer;
231                FHand->SourceSize = SourceSize;
232
233                Status = uefi_call_wrapper(
234                            LoadFile->LoadFile,
235                                5,
236                            LoadFile,
237                            *FilePath,
238                            BootPolicy,
239                            &SourceSize,
240                            SourceBuffer
241                            ); 
242            }
243        }
244
245        //
246        // If success, return FHand
247        //
248
249        if (!EFI_ERROR(Status) || Status == EFI_ALREADY_STARTED) {
250            goto Done;
251        }
252    }
253
254    //
255    // Nothing else to try
256    //
257
258    DEBUG ((D_LOAD|D_WARN, "OpenSimpleReadFile: Device did not support a known load protocol\n"));
259    Status = EFI_UNSUPPORTED;
260
261Done:
262
263    //
264    // If the file was not accessed, clean up
265    //
266    if (EFI_ERROR(Status) && (Status != EFI_ALREADY_STARTED)) {
267        if (FHand) {
268            if (FHand->FreeBuffer) {
269                FreePool (FHand->Source);
270            }
271
272            FreePool (FHand);
273        }
274    }
275
276    return Status;
277}
278
279EFI_STATUS
280ReadSimpleReadFile (
281    IN SIMPLE_READ_FILE     UserHandle,
282    IN UINTN                Offset,
283    IN OUT UINTN            *ReadSize,
284    OUT VOID                *Buffer
285    )
286{
287    UINTN                   EndPos;
288    SIMPLE_READ_HANDLE      *FHand;
289    EFI_STATUS              Status;
290
291    FHand = UserHandle;
292    ASSERT (FHand->Signature == SIMPLE_READ_SIGNATURE);
293    if (FHand->Source) {
294
295        //
296        // Move data from our local copy of the file
297        //
298
299        EndPos = Offset + *ReadSize;
300        if (EndPos > FHand->SourceSize) {
301            *ReadSize = FHand->SourceSize - Offset;
302            if (Offset >= FHand->SourceSize) {
303                *ReadSize = 0;
304            }
305        }
306
307        CopyMem (Buffer, (CHAR8 *) FHand->Source + Offset, *ReadSize);
308        Status = EFI_SUCCESS;
309
310    } else {
311
312        //
313        // Read data from the file
314        //
315
316        Status = uefi_call_wrapper(FHand->FileHandle->SetPosition, 2, FHand->FileHandle, Offset);
317
318        if (!EFI_ERROR(Status)) {
319            Status = uefi_call_wrapper(FHand->FileHandle->Read, 3, FHand->FileHandle, ReadSize, Buffer);
320        }
321    }
322
323    return Status;
324}
325
326
327VOID
328CloseSimpleReadFile (
329    IN SIMPLE_READ_FILE     UserHandle
330    )
331{
332    SIMPLE_READ_HANDLE      *FHand;
333
334    FHand = UserHandle;
335    ASSERT (FHand->Signature == SIMPLE_READ_SIGNATURE);
336
337    //
338    // Free any file handle we opened
339    //
340
341    if (FHand->FileHandle) {
342        uefi_call_wrapper(FHand->FileHandle->Close, 1, FHand->FileHandle);
343    }
344
345    //
346    // If we allocated the Source buffer, free it
347    //
348
349    if (FHand->FreeBuffer) {
350        FreePool (FHand->Source);
351    }
352
353    //
354    // Done with this simple read file handle
355    //
356
357    FreePool (FHand);
358}
Note: See TracBrowser for help on using the repository browser.