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