source: mainline/boot/arch/ia64/loader/gefi/lib/sread.c@ 36251c6

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 36251c6 was 7208b6c, checked in by Jakub Vana <jakub.vana@…>, 18 years ago

Basic IA64 boot and kernel suport for real machines

  • Property mode set to 100644
File size: 7.8 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 = 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
255Done:
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
273EFI_STATUS
274ReadSimpleReadFile (
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
321VOID
322CloseSimpleReadFile (
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}
Note: See TracBrowser for help on using the repository browser.