Subversion Repositories HelenOS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2726 vana 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
 
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
}