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