--- /dev/null
+/** @file\r
+ Dir for EBL (Embedded Boot Loader)\r
+\r
+ Copyright (c) 2007, Intel Corporation<BR>\r
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved.\r
+\r
+\r
+ All rights reserved. This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+ Module Name: CmdTemplate.c\r
+\r
+ Search/Replace Dir with the name of your new command\r
+\r
+**/\r
+\r
+#include "Ebl.h"\r
+\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 *gFvFileType[] = {\r
+ "All",\r
+ "Raw",\r
+ "Freeform",\r
+ "SEC",\r
+ "PeiCore",\r
+ "DxeCore",\r
+ "PEIM",\r
+ "Driver",\r
+ "Combo Driver",\r
+ "Application",\r
+ "NULL",\r
+ "FV"\r
+};\r
+\r
+\r
+/**\r
+ Perform a dir on a device. The device must support Simple File System Protocol\r
+ or the FV protocol. \r
+\r
+ Argv[0] - "dir"\r
+ Argv[1] - Device Name:path. Path is optional \r
+ Argv[2] - Optional filename to match on. A leading * means match substring\r
+ Argv[3] - Optional FV file type\r
+\r
+ dir fs1:\efi ; perform a dir on fs1: device in the efi directory\r
+ dir fs1:\efi *.efi; perform a dir on fs1: device in the efi directory but \r
+ only print out files that contain the string *.efi\r
+ dir fv1:\ ; perform a dir on fv1: device in the efi directory \r
+ NOTE: fv devices do not contian subdirs \r
+ dir fv1:\ * PEIM ; will match all files of type SEC\r
+\r
+ @param Argc Number of command arguments in Argv\r
+ @param Argv Array of strings that represent the parsed command line. \r
+ Argv[0] is the comamnd name\r
+\r
+ @return EFI_SUCCESS\r
+\r
+**/\r
+EFI_STATUS\r
+EblDirCmd (\r
+ IN UINTN Argc,\r
+ IN CHAR8 **Argv\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_OPEN_FILE *File;\r
+ EFI_FILE_INFO *DirInfo;\r
+ UINTN ReadSize;\r
+ UINTN CurrentRow; \r
+ CHAR16 *MatchSubString;\r
+ EFI_STATUS GetNextFileStatus;\r
+ UINTN Key;\r
+ EFI_FV_FILETYPE SearchType;\r
+ EFI_FV_FILETYPE Type;\r
+ EFI_FV_FILE_ATTRIBUTES Attributes;\r
+ UINTN Size;\r
+ EFI_GUID NameGuid;\r
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r
+ UINT32 AuthenticationStatus;\r
+ VOID *Section;\r
+ UINTN SectionSize;\r
+ EFI_FV_FILETYPE Index;\r
+ UINTN Length;\r
+ UINTN BestMatchCount;\r
+ CHAR16 UnicodeFileName[MAX_CMD_LINE];\r
+\r
+\r
+ if (Argc <= 1) {\r
+ // CWD not currently supported \r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0);\r
+ if (File == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (File->Type == EfiOpenFirmwareVolume) {\r
+ // FV Dir\r
+\r
+ SearchType = EFI_FV_FILETYPE_ALL;\r
+ UnicodeFileName[0] = '\0';\r
+ MatchSubString = &UnicodeFileName[0];\r
+ if (Argc > 2) {\r
+ AsciiStrToUnicodeStr (Argv[2], UnicodeFileName);\r
+ if (UnicodeFileName[0] == '*') {\r
+ // Handle *Name substring matching\r
+ MatchSubString = &UnicodeFileName[1];\r
+ }\r
+\r
+ // Handle file type matchs\r
+ if (Argc > 3) {\r
+ // match a specific file type, always last argument\r
+ Length = AsciiStrLen (Argv[3]);\r
+ for (Index = 1, BestMatchCount = 0; Index < sizeof (gFvFileType)/sizeof (CHAR8 *); Index++) {\r
+ if (AsciiStriCmp (gFvFileType[Index], Argv[3]) == 0) {\r
+ // exact match\r
+ SearchType = Index;\r
+ break;\r
+ }\r
+\r
+ if (AsciiStrniCmp (Argv[3], gFvFileType[Index], Length) == 0) {\r
+ // partial match, so keep looking to make sure there is only one partial match\r
+ BestMatchCount++;\r
+ SearchType = Index;\r
+ }\r
+ }\r
+\r
+ if (BestMatchCount > 1) {\r
+ SearchType = EFI_FV_FILETYPE_ALL;\r
+ }\r
+ }\r
+ }\r
+\r
+ Fv = File->Fv;\r
+ Key = 0;\r
+ CurrentRow = 0;\r
+ do {\r
+ Type = SearchType;\r
+ GetNextFileStatus = Fv->GetNextFile (\r
+ Fv, \r
+ &Key,\r
+ &Type, \r
+ &NameGuid, \r
+ &Attributes, \r
+ &Size\r
+ );\r
+ if (!EFI_ERROR (GetNextFileStatus)) {\r
+ // Calculate size of entire file\r
+ Section = NULL;\r
+ Size = 0;\r
+ Status = Fv->ReadFile (\r
+ Fv,\r
+ &NameGuid, \r
+ Section,\r
+ &Size,\r
+ &Type,\r
+ &Attributes,\r
+ &AuthenticationStatus\r
+ );\r
+ if (!((Status == EFI_BUFFER_TOO_SMALL) || !EFI_ERROR (Status))) {\r
+ // EFI_SUCCESS or EFI_BUFFER_TOO_SMALL mean size is valid \r
+ Size = 0;\r
+ }\r
+\r
+ // read the UI seciton to do a name match.\r
+ Section = NULL;\r
+ Status = Fv->ReadSection (\r
+ Fv,\r
+ &NameGuid,\r
+ EFI_SECTION_USER_INTERFACE,\r
+ 0,\r
+ &Section,\r
+ &SectionSize,\r
+ &AuthenticationStatus\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ if (StrStr (Section, MatchSubString) != NULL) {\r
+ AsciiPrint (" %g %s %a %,d\n", &NameGuid, Section, gFvFileType[Type], Size);\r
+ if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {\r
+ break;\r
+ }\r
+ }\r
+ FreePool (Section);\r
+ } else {\r
+ if (*MatchSubString == '\0') {\r
+ AsciiPrint (" %g %a %,d\n", &NameGuid, gFvFileType[Type], Size);\r
+ if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ } while (!EFI_ERROR (GetNextFileStatus));\r
+ \r
+ } else if ((File->Type == EfiOpenFileSystem) || (File->Type == EfiOpenBlockIo)) {\r
+ // Simple File System DIR\r
+\r
+ if (File->FsFileInfo == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (!(File->FsFileInfo->Attribute & EFI_FILE_DIRECTORY)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ // Handle *Name substring matching\r
+ MatchSubString = NULL;\r
+ UnicodeFileName[0] = '\0';\r
+ if (Argc > 2) {\r
+ AsciiStrToUnicodeStr (Argv[2], UnicodeFileName);\r
+ if (UnicodeFileName[0] == '*') {\r
+ MatchSubString = &UnicodeFileName[1];\r
+ }\r
+ } \r
+\r
+ File->FsFileHandle->SetPosition (File->FsFileHandle, 0);\r
+ for (CurrentRow = 0;;) {\r
+ // First read gets the size\r
+ DirInfo = NULL;\r
+ ReadSize = 0;\r
+ Status = File->FsFileHandle->Read (File->FsFileHandle, &ReadSize, DirInfo);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ // Allocate the buffer for the real read\r
+ DirInfo = AllocatePool (ReadSize);\r
+ if (DirInfo == NULL) {\r
+ goto Done;\r
+ }\r
+ \r
+ // Read the data\r
+ Status = File->FsFileHandle->Read (File->FsFileHandle, &ReadSize, DirInfo);\r
+ if ((EFI_ERROR (Status)) || (ReadSize == 0)) {\r
+ break;\r
+ }\r
+ } else {\r
+ break;\r
+ }\r
+ \r
+ if (MatchSubString != NULL) {\r
+ if (StrStr (&DirInfo->FileName[0], MatchSubString) == NULL) {\r
+ // does not match *name argument, so skip\r
+ continue;\r
+ }\r
+ } else if (UnicodeFileName[0] != '\0') {\r
+ // is not an exact match for name argument, so skip\r
+ if (StrCmp (&DirInfo->FileName[0], UnicodeFileName) != 0) {\r
+ continue;\r
+ }\r
+ }\r
+\r
+ if (DirInfo->Attribute & EFI_FILE_DIRECTORY) {\r
+ AsciiPrint (" <DIR> %s\n", &DirInfo->FileName[0]);\r
+ } else {\r
+ AsciiPrint ("%,14ld %s\n", DirInfo->FileSize, &DirInfo->FileName[0]);\r
+ }\r
+\r
+ if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {\r
+ break;\r
+ }\r
+ \r
+ FreePool (DirInfo);\r
+ }\r
+\r
+Done:\r
+ if (DirInfo != NULL) {\r
+ FreePool (DirInfo);\r
+ }\r
+ }\r
+\r
+ EfiClose (File);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdDirTemplate[] =\r
+{\r
+ {\r
+ "dir",\r
+ " dirdev [*match]; directory listing of dirdev. opt match a substring",\r
+ NULL,\r
+ EblDirCmd\r
+ }\r
+};\r
+\r
+\r
+/**\r
+ Initialize the commands in this in this file\r
+**/\r
+VOID\r
+EblInitializeDirCmd (\r
+ VOID\r
+ )\r
+{ \r
+ if (FeaturePcdGet (PcdEmbeddedDirCmd)) {\r
+ EblAddCommands (mCmdDirTemplate, sizeof (mCmdDirTemplate)/sizeof (EBL_COMMAND_TABLE));\r
+ }\r
+}\r
+\r