Change UI for dir of FV to make it less confusing.
[mirror_edk2.git] / EmbeddedPkg / Ebl / Dir.c
CommitLineData
2ef2b01e
A
1/** @file\r
2 Dir for EBL (Embedded Boot Loader)\r
3\r
4 Copyright (c) 2007, Intel Corporation<BR>\r
5 Portions copyright (c) 2008-2009, Apple Inc. All rights reserved.\r
6\r
7\r
8 All rights reserved. This program and the accompanying materials\r
9 are licensed and made available under the terms and conditions of the BSD License\r
10 which accompanies this distribution. The full text of the license may be found at\r
11 http://opensource.org/licenses/bsd-license.php\r
12\r
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
15\r
16 Module Name: CmdTemplate.c\r
17\r
18 Search/Replace Dir with the name of your new command\r
19\r
20**/\r
21\r
22#include "Ebl.h"\r
23\r
24\r
25GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 *gFvFileType[] = {\r
26 "All",\r
3575301c 27 "Bin",\r
28 "section",\r
2ef2b01e
A
29 "SEC",\r
30 "PeiCore",\r
31 "DxeCore",\r
32 "PEIM",\r
33 "Driver",\r
3575301c 34 "Combo",\r
35 "App",\r
2ef2b01e
A
36 "NULL",\r
37 "FV"\r
38};\r
39\r
40\r
41/**\r
42 Perform a dir on a device. The device must support Simple File System Protocol\r
43 or the FV protocol. \r
44\r
45 Argv[0] - "dir"\r
46 Argv[1] - Device Name:path. Path is optional \r
47 Argv[2] - Optional filename to match on. A leading * means match substring\r
48 Argv[3] - Optional FV file type\r
49\r
50 dir fs1:\efi ; perform a dir on fs1: device in the efi directory\r
51 dir fs1:\efi *.efi; perform a dir on fs1: device in the efi directory but \r
52 only print out files that contain the string *.efi\r
53 dir fv1:\ ; perform a dir on fv1: device in the efi directory \r
54 NOTE: fv devices do not contian subdirs \r
16ccac42 55 dir fv1:\ * PEIM ; will match all files of type PEIM\r
2ef2b01e
A
56\r
57 @param Argc Number of command arguments in Argv\r
58 @param Argv Array of strings that represent the parsed command line. \r
59 Argv[0] is the comamnd name\r
60\r
61 @return EFI_SUCCESS\r
62\r
63**/\r
64EFI_STATUS\r
65EblDirCmd (\r
66 IN UINTN Argc,\r
67 IN CHAR8 **Argv\r
68 )\r
69{\r
70 EFI_STATUS Status;\r
71 EFI_OPEN_FILE *File;\r
72 EFI_FILE_INFO *DirInfo;\r
73 UINTN ReadSize;\r
74 UINTN CurrentRow; \r
75 CHAR16 *MatchSubString;\r
76 EFI_STATUS GetNextFileStatus;\r
77 UINTN Key;\r
78 EFI_FV_FILETYPE SearchType;\r
79 EFI_FV_FILETYPE Type;\r
80 EFI_FV_FILE_ATTRIBUTES Attributes;\r
81 UINTN Size;\r
82 EFI_GUID NameGuid;\r
83 EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r
84 UINT32 AuthenticationStatus;\r
85 VOID *Section;\r
86 UINTN SectionSize;\r
87 EFI_FV_FILETYPE Index;\r
88 UINTN Length;\r
89 UINTN BestMatchCount;\r
90 CHAR16 UnicodeFileName[MAX_CMD_LINE];\r
16ccac42 91 CHAR8 *Path;\r
3575301c 92 CHAR8 *TypeStr;\r
2ef2b01e
A
93\r
94\r
95 if (Argc <= 1) {\r
16ccac42 96 Path = EfiGetCwd ();\r
97 if (Path == NULL) {\r
98 return EFI_SUCCESS;\r
99 }\r
100 } else {\r
101 Path = Argv[1];\r
2ef2b01e
A
102 }\r
103\r
16ccac42 104 File = EfiOpen (Path, EFI_FILE_MODE_READ, 0);\r
2ef2b01e
A
105 if (File == NULL) {\r
106 return EFI_SUCCESS;\r
107 }\r
108\r
109 if (File->Type == EfiOpenFirmwareVolume) {\r
110 // FV Dir\r
111\r
112 SearchType = EFI_FV_FILETYPE_ALL;\r
113 UnicodeFileName[0] = '\0';\r
114 MatchSubString = &UnicodeFileName[0];\r
115 if (Argc > 2) {\r
116 AsciiStrToUnicodeStr (Argv[2], UnicodeFileName);\r
117 if (UnicodeFileName[0] == '*') {\r
118 // Handle *Name substring matching\r
119 MatchSubString = &UnicodeFileName[1];\r
120 }\r
121\r
122 // Handle file type matchs\r
123 if (Argc > 3) {\r
124 // match a specific file type, always last argument\r
125 Length = AsciiStrLen (Argv[3]);\r
126 for (Index = 1, BestMatchCount = 0; Index < sizeof (gFvFileType)/sizeof (CHAR8 *); Index++) {\r
127 if (AsciiStriCmp (gFvFileType[Index], Argv[3]) == 0) {\r
128 // exact match\r
129 SearchType = Index;\r
130 break;\r
131 }\r
132\r
133 if (AsciiStrniCmp (Argv[3], gFvFileType[Index], Length) == 0) {\r
134 // partial match, so keep looking to make sure there is only one partial match\r
135 BestMatchCount++;\r
136 SearchType = Index;\r
137 }\r
138 }\r
139\r
140 if (BestMatchCount > 1) {\r
141 SearchType = EFI_FV_FILETYPE_ALL;\r
142 }\r
143 }\r
144 }\r
145\r
146 Fv = File->Fv;\r
147 Key = 0;\r
148 CurrentRow = 0;\r
149 do {\r
150 Type = SearchType;\r
151 GetNextFileStatus = Fv->GetNextFile (\r
152 Fv, \r
153 &Key,\r
154 &Type, \r
155 &NameGuid, \r
156 &Attributes, \r
157 &Size\r
158 );\r
159 if (!EFI_ERROR (GetNextFileStatus)) {\r
3575301c 160 // Calculate size of entire file\r
161 Section = NULL;\r
162 Size = 0;\r
163 Status = Fv->ReadFile (\r
2ef2b01e
A
164 Fv,\r
165 &NameGuid, \r
166 Section,\r
167 &Size,\r
168 &Type,\r
169 &Attributes,\r
170 &AuthenticationStatus\r
171 );\r
3575301c 172 if (!((Status == EFI_BUFFER_TOO_SMALL) || !EFI_ERROR (Status))) {\r
173 // EFI_SUCCESS or EFI_BUFFER_TOO_SMALL mean size is valid \r
174 Size = 0;\r
175 }\r
176 \r
177 TypeStr = (Type <= EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) ? gFvFileType[Type] : "UNKNOWN";\r
2ef2b01e
A
178\r
179 // read the UI seciton to do a name match.\r
180 Section = NULL;\r
181 Status = Fv->ReadSection (\r
182 Fv,\r
183 &NameGuid,\r
184 EFI_SECTION_USER_INTERFACE,\r
185 0,\r
186 &Section,\r
187 &SectionSize,\r
188 &AuthenticationStatus\r
189 );\r
190 if (!EFI_ERROR (Status)) {\r
191 if (StrStr (Section, MatchSubString) != NULL) {\r
3575301c 192 AsciiPrint ("%,6d %7a %g %s\n", Size, TypeStr, &NameGuid, Section);\r
2ef2b01e
A
193 if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {\r
194 break;\r
195 }\r
196 }\r
197 FreePool (Section);\r
198 } else {\r
199 if (*MatchSubString == '\0') {\r
3575301c 200 AsciiPrint ("%,6d %7a %g\n", Size, TypeStr, &NameGuid);\r
2ef2b01e
A
201 if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {\r
202 break;\r
203 }\r
204 }\r
205 }\r
206 }\r
207 } while (!EFI_ERROR (GetNextFileStatus));\r
208 \r
209 } else if ((File->Type == EfiOpenFileSystem) || (File->Type == EfiOpenBlockIo)) {\r
210 // Simple File System DIR\r
211\r
212 if (File->FsFileInfo == NULL) {\r
213 return EFI_SUCCESS;\r
214 }\r
215\r
216 if (!(File->FsFileInfo->Attribute & EFI_FILE_DIRECTORY)) {\r
217 return EFI_SUCCESS;\r
218 }\r
219\r
220 // Handle *Name substring matching\r
221 MatchSubString = NULL;\r
222 UnicodeFileName[0] = '\0';\r
223 if (Argc > 2) {\r
224 AsciiStrToUnicodeStr (Argv[2], UnicodeFileName);\r
225 if (UnicodeFileName[0] == '*') {\r
226 MatchSubString = &UnicodeFileName[1];\r
227 }\r
228 } \r
229\r
230 File->FsFileHandle->SetPosition (File->FsFileHandle, 0);\r
231 for (CurrentRow = 0;;) {\r
232 // First read gets the size\r
233 DirInfo = NULL;\r
234 ReadSize = 0;\r
235 Status = File->FsFileHandle->Read (File->FsFileHandle, &ReadSize, DirInfo);\r
236 if (Status == EFI_BUFFER_TOO_SMALL) {\r
237 // Allocate the buffer for the real read\r
238 DirInfo = AllocatePool (ReadSize);\r
239 if (DirInfo == NULL) {\r
240 goto Done;\r
241 }\r
242 \r
243 // Read the data\r
244 Status = File->FsFileHandle->Read (File->FsFileHandle, &ReadSize, DirInfo);\r
245 if ((EFI_ERROR (Status)) || (ReadSize == 0)) {\r
246 break;\r
247 }\r
248 } else {\r
249 break;\r
250 }\r
251 \r
252 if (MatchSubString != NULL) {\r
253 if (StrStr (&DirInfo->FileName[0], MatchSubString) == NULL) {\r
254 // does not match *name argument, so skip\r
255 continue;\r
256 }\r
257 } else if (UnicodeFileName[0] != '\0') {\r
258 // is not an exact match for name argument, so skip\r
259 if (StrCmp (&DirInfo->FileName[0], UnicodeFileName) != 0) {\r
260 continue;\r
261 }\r
262 }\r
263\r
264 if (DirInfo->Attribute & EFI_FILE_DIRECTORY) {\r
265 AsciiPrint (" <DIR> %s\n", &DirInfo->FileName[0]);\r
266 } else {\r
267 AsciiPrint ("%,14ld %s\n", DirInfo->FileSize, &DirInfo->FileName[0]);\r
268 }\r
269\r
270 if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {\r
271 break;\r
272 }\r
273 \r
274 FreePool (DirInfo);\r
275 }\r
276\r
277Done:\r
278 if (DirInfo != NULL) {\r
279 FreePool (DirInfo);\r
280 }\r
281 }\r
282\r
283 EfiClose (File);\r
284\r
285 return EFI_SUCCESS;\r
286}\r
287\r
16ccac42 288/**\r
289 Change the Current Working Directory\r
290\r
291 Argv[0] - "cd"\r
292 Argv[1] - Device Name:path. Path is optional \r
293\r
294 @param Argc Number of command arguments in Argv\r
295 @param Argv Array of strings that represent the parsed command line. \r
296 Argv[0] is the comamnd name\r
297\r
298 @return EFI_SUCCESS\r
299\r
300**/\r
301EFI_STATUS\r
302EblCdCmd (\r
303 IN UINTN Argc,\r
304 IN CHAR8 **Argv\r
305 )\r
306{\r
307 if (Argc <= 1) {\r
308 return EFI_SUCCESS;\r
309 } \r
310 \r
311 return EfiSetCwd (Argv[1]);\r
312}\r
313\r
2ef2b01e
A
314\r
315\r
316GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdDirTemplate[] =\r
317{\r
318 {\r
319 "dir",\r
320 " dirdev [*match]; directory listing of dirdev. opt match a substring",\r
321 NULL,\r
322 EblDirCmd\r
16ccac42 323 },\r
324 {\r
325 "cd",\r
326 " device - set the current working directory",\r
327 NULL,\r
328 EblCdCmd\r
2ef2b01e
A
329 }\r
330};\r
331\r
332\r
333/**\r
334 Initialize the commands in this in this file\r
335**/\r
336VOID\r
337EblInitializeDirCmd (\r
338 VOID\r
339 )\r
340{ \r
341 if (FeaturePcdGet (PcdEmbeddedDirCmd)) {\r
342 EblAddCommands (mCmdDirTemplate, sizeof (mCmdDirTemplate)/sizeof (EBL_COMMAND_TABLE));\r
343 }\r
344}\r
345\r