1 /** @file
2
3 Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12
13 **/
14
15 #include "Edb.h"
16
17 /**
18 Read a file.
19
20 @param Vol - File System Volume
21 @param FileName - The file to be read.
22 @param BufferSize - The file buffer size
23 @param Buffer - The file buffer
24
25 @retval EFI_SUCCESS - read file successfully
26 @retval EFI_NOT_FOUND - file not found
27
28 **/
29 EFI_STATUS
30 EFIAPI
ReadFileFromVol(IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL * Vol,IN CHAR16 * FileName,OUT UINTN * BufferSize,OUT VOID ** Buffer)31 ReadFileFromVol (
32 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol,
33 IN CHAR16 *FileName,
34 OUT UINTN *BufferSize,
35 OUT VOID **Buffer
36 )
37 {
38 EFI_STATUS Status;
39 EFI_FILE_HANDLE RootDir;
40 EFI_FILE_HANDLE Handle;
41 UINTN FileInfoSize;
42 EFI_FILE_INFO *FileInfo;
43 UINTN TempBufferSize;
44 VOID *TempBuffer;
45
46 //
47 // Open the root directory
48 //
49 Status = Vol->OpenVolume (Vol, &RootDir);
50 if (EFI_ERROR (Status)) {
51 return Status;
52 }
53
54 //
55 // Open the file
56 //
57 Status = RootDir->Open (
58 RootDir,
59 &Handle,
60 FileName,
61 EFI_FILE_MODE_READ,
62 0
63 );
64 if (EFI_ERROR (Status)) {
65 RootDir->Close (RootDir);
66 return Status;
67 }
68
69 RootDir->Close (RootDir);
70
71 //
72 // Get the file information
73 //
74 FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;
75
76 FileInfo = AllocateZeroPool (FileInfoSize);
77 if (FileInfo == NULL) {
78 Handle->Close (Handle);
79 return Status;
80 }
81
82 Status = Handle->GetInfo (
83 Handle,
84 &gEfiFileInfoGuid,
85 &FileInfoSize,
86 FileInfo
87 );
88 if (EFI_ERROR (Status)) {
89 Handle->Close (Handle);
90 gBS->FreePool (FileInfo);
91 return Status;
92 }
93
94 //
95 // Allocate buffer for the file data. The last CHAR16 is for L'\0'
96 //
97 TempBufferSize = (UINTN) FileInfo->FileSize + sizeof(CHAR16);
98 TempBuffer = AllocateZeroPool (TempBufferSize);
99 if (TempBuffer == NULL) {
100 Handle->Close (Handle);
101 gBS->FreePool (FileInfo);
102 return Status;
103 }
104
105 gBS->FreePool (FileInfo);
106
107 //
108 // Read the file data to the buffer
109 //
110 Status = Handle->Read (
111 Handle,
112 &TempBufferSize,
113 TempBuffer
114 );
115 if (EFI_ERROR (Status)) {
116 Handle->Close (Handle);
117 gBS->FreePool (TempBuffer);
118 return Status;
119 }
120
121 Handle->Close (Handle);
122
123 *BufferSize = TempBufferSize;
124 *Buffer = TempBuffer;
125 return EFI_SUCCESS;
126 }
127
128 /**
129
130 Read a file.
131 If ScanFs is FLASE, it will use DebuggerPrivate->Vol as default Fs.
132 If ScanFs is TRUE, it will scan all FS and check the file.
133 If there is only one file match the name, it will be read.
134 If there is more than one file match the name, it will return Error.
135
136 @param DebuggerPrivate - EBC Debugger private data structure
137 @param FileName - The file to be read.
138 @param BufferSize - The file buffer size
139 @param Buffer - The file buffer
140 @param ScanFs - Need Scan all FS
141
142 @retval EFI_SUCCESS - read file successfully
143 @retval EFI_NOT_FOUND - file not found
144 @retval EFI_NO_MAPPING - there is duplicated files found
145
146 **/
147 EFI_STATUS
148 EFIAPI
ReadFileToBuffer(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN CHAR16 * FileName,OUT UINTN * BufferSize,OUT VOID ** Buffer,IN BOOLEAN ScanFs)149 ReadFileToBuffer (
150 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
151 IN CHAR16 *FileName,
152 OUT UINTN *BufferSize,
153 OUT VOID **Buffer,
154 IN BOOLEAN ScanFs
155 )
156 {
157 EFI_STATUS Status;
158 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol;
159 UINTN TempBufferSize;
160 VOID *TempBuffer;
161 UINTN NoHandles;
162 EFI_HANDLE *HandleBuffer;
163 UINTN Index;
164
165 //
166 // Check parameters
167 //
168 if ((FileName == NULL) || (Buffer == NULL)) {
169 return EFI_INVALID_PARAMETER;
170 }
171
172 //
173 // not scan fs
174 //
175 if (!ScanFs) {
176 if (DebuggerPrivate->Vol == NULL) {
177 return EFI_INVALID_PARAMETER;
178 }
179 //
180 // Read file directly from Vol
181 //
182 return ReadFileFromVol (DebuggerPrivate->Vol, FileName, BufferSize, Buffer);
183 }
184
185 //
186 // need scan fs
187 //
188
189 //
190 // Get all Vol handle
191 //
192 Status = gBS->LocateHandleBuffer (
193 ByProtocol,
194 &gEfiSimpleFileSystemProtocolGuid,
195 NULL,
196 &NoHandles,
197 &HandleBuffer
198 );
199 if (EFI_ERROR (Status) && (NoHandles == 0)) {
200 return EFI_NOT_FOUND;
201 }
202
203 //
204 // Walk through each Vol
205 //
206 DebuggerPrivate->Vol = NULL;
207 *BufferSize = 0;
208 *Buffer = NULL;
209 for (Index = 0; Index < NoHandles; Index++) {
210 Status = gBS->HandleProtocol (
211 HandleBuffer[Index],
212 &gEfiSimpleFileSystemProtocolGuid,
213 (VOID**) &Vol
214 );
215 if (EFI_ERROR(Status)) {
216 continue;
217 }
218
219 Status = ReadFileFromVol (Vol, FileName, &TempBufferSize, &TempBuffer);
220 if (!EFI_ERROR (Status)) {
221 //
222 // Read file OK, check duplication
223 //
224 if (DebuggerPrivate->Vol != NULL) {
225 //
226 // Find the duplicated file
227 //
228 gBS->FreePool (TempBuffer);
229 gBS->FreePool (*Buffer);
230 EDBPrint (L"Duplicated FileName found!\n");
231 return EFI_NO_MAPPING;
232 } else {
233 //
234 // Record value
235 //
236 DebuggerPrivate->Vol = Vol;
237 *BufferSize = TempBufferSize;
238 *Buffer = TempBuffer;
239 }
240 }
241 }
242
243 //
244 // Scan Fs done
245 //
246 if (DebuggerPrivate->Vol == NULL) {
247 return EFI_NOT_FOUND;
248 }
249
250 //
251 // Done
252 //
253 return EFI_SUCCESS;
254 }
255
256 /**
257
258 Get file name under this dir with index
259
260 @param DebuggerPrivate - EBC Debugger private data structure
261 @param DirName - The dir to be read.
262 @param FileName - The file name pattern under this dir
263 @param Index - The file index under this dir
264
265 @return File Name which match the pattern and index.
266
267 **/
268 CHAR16 *
269 EFIAPI
GetFileNameUnderDir(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN CHAR16 * DirName,IN CHAR16 * FileName,IN OUT UINTN * Index)270 GetFileNameUnderDir (
271 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
272 IN CHAR16 *DirName,
273 IN CHAR16 *FileName,
274 IN OUT UINTN *Index
275 )
276 {
277 EFI_STATUS Status;
278 EFI_FILE_HANDLE RootDir;
279 EFI_FILE_HANDLE Handle;
280 UINTN FileInfoSize;
281 EFI_FILE_INFO *FileInfo;
282 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol;
283 VOID *TempName;
284 UINTN FileIndex;
285
286 if (DebuggerPrivate->Vol == NULL) {
287 Status = gBS->LocateProtocol (
288 &gEfiSimpleFileSystemProtocolGuid,
289 NULL,
290 (VOID**) &DebuggerPrivate->Vol
291 );
292 if (EFI_ERROR(Status)) {
293 return NULL;
294 }
295 }
296 Vol = DebuggerPrivate->Vol;
297
298 //
299 // Open the root directory
300 //
301 Status = Vol->OpenVolume (Vol, &RootDir);
302 if (EFI_ERROR (Status)) {
303 return NULL;
304 }
305
306 //
307 // Open the file
308 //
309 Status = RootDir->Open (
310 RootDir,
311 &Handle,
312 DirName,
313 EFI_FILE_MODE_READ,
314 EFI_FILE_DIRECTORY
315 );
316 if (EFI_ERROR (Status)) {
317 RootDir->Close (RootDir);
318 return NULL;
319 }
320 RootDir->Close (RootDir);
321
322 //
323 // Set Dir Position
324 //
325 Status = Handle->SetPosition (Handle, 0);
326 if (EFI_ERROR (Status)) {
327 Handle->Close (Handle);
328 return NULL;
329 }
330
331 //
332 // Get the file information
333 //
334 FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;
335
336 FileInfo = AllocateZeroPool (FileInfoSize);
337 if (FileInfo == NULL) {
338 Handle->Close (Handle);
339 return NULL;
340 }
341
342 //
343 // Walk through each file in the directory
344 //
345 FileIndex = 0;
346 TempName = NULL;
347 while (TRUE) {
348 //
349 // Read a file entry
350 //
351 FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;
352
353 Status = Handle->Read (
354 Handle,
355 &FileInfoSize,
356 FileInfo
357 );
358 if (EFI_ERROR (Status) || (FileInfoSize == 0)) {
359 break;
360 }
361
362 if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) == 0) {
363 //
364 // This is a file
365 //
366
367 //
368 // Only deal with the EFI key file
369 //
370 if (!StrEndWith (FileInfo->FileName, FileName)) {
371 continue;
372 }
373
374 if (FileIndex == *Index) {
375 TempName = StrDuplicate (FileInfo->FileName);
376 *Index = *Index + 1;
377 break;
378 }
379 FileIndex ++;
380 }
381 }
382
383 //
384 // Free resources
385 //
386 gBS->FreePool (FileInfo);
387 Handle->Close (Handle);
388
389 return TempName;
390 }
391