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