/** @file Main file for DevTree shell Driver1 function. (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "UefiShellDriver1CommandsLib.h" STATIC CONST SHELL_PARAM_ITEM ParamList[] = { {L"-d", TypeFlag}, {L"-l", TypeValue}, {NULL, TypeMax} }; /** Display a tree starting from this handle. @param[in] TheHandle The handle to start with. @param[in] Lang Optionally, a UEFI defined language code. @param[in] UseDevPaths TRUE to display info from DevPath as identifiers. FALSE will use component name protocol instead. @param[in] IndentCharCount How many characters to indent (allows for recursion). @param[in] HiiString The string from HII to use for output. @retval SHELL_SUCCESS The operation was successful. **/ SHELL_STATUS DoDevTreeForHandle( IN CONST EFI_HANDLE TheHandle, IN CONST CHAR8 *Lang OPTIONAL, IN CONST BOOLEAN UseDevPaths, IN CONST UINTN IndentCharCount, IN CONST CHAR16 *HiiString ) { SHELL_STATUS ShellStatus; EFI_STATUS Status; CHAR16 *FormatString; CHAR16 *Name; EFI_HANDLE *ChildHandleBuffer; UINTN ChildCount; UINTN LoopVar; Status = EFI_SUCCESS; ShellStatus = SHELL_SUCCESS; Name = NULL; ChildHandleBuffer = NULL; ChildCount = 0; ASSERT (TheHandle != NULL); ASSERT (HiiString != NULL); if (ShellGetExecutionBreakFlag()) { ShellStatus = SHELL_ABORTED; return ShellStatus; } // // We want controller handles. they will not have LoadedImage or DriverBinding (or others...) // Status = gBS->OpenProtocol ( TheHandle, &gEfiDriverBindingProtocolGuid, NULL, NULL, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL ); if (!EFI_ERROR (Status)) { return SHELL_SUCCESS; } Status = gBS->OpenProtocol ( TheHandle, &gEfiLoadedImageProtocolGuid, NULL, NULL, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL ); if (!EFI_ERROR (Status)) { return SHELL_SUCCESS; } FormatString = AllocateZeroPool(StrSize(HiiString) + (10)*sizeof(FormatString[0])); if (FormatString == NULL) { return SHELL_OUT_OF_RESOURCES; } // // we generate the format string on the fly so that we can control the // number of space characters that the first (empty) string has. this // handles the indenting. // UnicodeSPrint(FormatString, StrSize(HiiString) + (10)*sizeof(FormatString[0]), L"%%%ds %s", IndentCharCount, HiiString); gEfiShellProtocol->GetDeviceName((EFI_HANDLE)TheHandle, !UseDevPaths?EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH:EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Lang, &Name); // // print out the information for ourselves // ShellPrintEx( -1, -1, FormatString, L"", ConvertHandleToHandleIndex(TheHandle), Name==NULL?L"Unknown":Name); FreePool(FormatString); if (Name != NULL) { FreePool(Name); } // // recurse on each child handle with IndentCharCount + 2 // ParseHandleDatabaseForChildControllers(TheHandle, &ChildCount, &ChildHandleBuffer); for (LoopVar = 0 ; LoopVar < ChildCount && ShellStatus == SHELL_SUCCESS; LoopVar++){ ShellStatus = DoDevTreeForHandle(ChildHandleBuffer[LoopVar], Lang, UseDevPaths, IndentCharCount+2, HiiString); if (ShellStatus == SHELL_ABORTED) { break; } } if (ChildHandleBuffer != NULL) { FreePool(ChildHandleBuffer); } return (ShellStatus); } /** Function for 'devtree' command. @param[in] ImageHandle Handle to the Image (NULL if Internal). @param[in] SystemTable Pointer to the System Table (NULL if Internal). **/ SHELL_STATUS EFIAPI ShellCommandRunDevTree ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; LIST_ENTRY *Package; CHAR16 *ProblemParam; SHELL_STATUS ShellStatus; CHAR8 *Language; CONST CHAR16 *Lang; CHAR16 *HiiString; UINTN LoopVar; EFI_HANDLE TheHandle; BOOLEAN FlagD; UINT64 Intermediate; UINTN ParentControllerHandleCount; EFI_HANDLE *ParentControllerHandleBuffer; ShellStatus = SHELL_SUCCESS; Status = EFI_SUCCESS; Language = NULL; // // initialize the shell lib (we must be in non-auto-init...) // Status = ShellInitialize(); ASSERT_EFI_ERROR(Status); Status = CommandInit(); ASSERT_EFI_ERROR(Status); // // parse the command line // Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); if (EFI_ERROR(Status)) { if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"devtree", ProblemParam); FreePool(ProblemParam); ShellStatus = SHELL_INVALID_PARAMETER; } else { ASSERT(FALSE); } } else { if (ShellCommandLineGetCount(Package) > 2) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"devtree"); ShellCommandLineFreeVarList (Package); return (SHELL_INVALID_PARAMETER); } Lang = ShellCommandLineGetValue(Package, L"-l"); if (Lang != NULL) { Language = AllocateZeroPool(StrSize(Lang)); AsciiSPrint(Language, StrSize(Lang), "%S", Lang); } else if (!ShellCommandLineGetFlag(Package, L"-l")){ ASSERT(Language == NULL); // Language = AllocateZeroPool(10); // AsciiSPrint(Language, 10, "en-us"); } else { ASSERT(Language == NULL); ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"devtree", L"-l"); ShellCommandLineFreeVarList (Package); return (SHELL_INVALID_PARAMETER); } FlagD = ShellCommandLineGetFlag(Package, L"-d"); Lang = ShellCommandLineGetRawValue(Package, 1); HiiString = HiiGetString(gShellDriver1HiiHandle, STRING_TOKEN (STR_DEV_TREE_OUTPUT), Language); if (Lang == NULL) { for (LoopVar = 1 ; ; LoopVar++){ TheHandle = ConvertHandleIndexToHandle(LoopVar); if (TheHandle == NULL){ break; } // // Skip handles that do not have device path protocol // Status = gBS->OpenProtocol ( TheHandle, &gEfiDevicePathProtocolGuid, NULL, NULL, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL ); if (EFI_ERROR (Status)) { continue; } // // Skip handles that do have parents // ParentControllerHandleBuffer = NULL; Status = PARSE_HANDLE_DATABASE_PARENTS ( TheHandle, &ParentControllerHandleCount, &ParentControllerHandleBuffer ); SHELL_FREE_NON_NULL (ParentControllerHandleBuffer); if (ParentControllerHandleCount > 0) { continue; } // // Start a devtree from TheHandle that has a device path and no parents // ShellStatus = DoDevTreeForHandle(TheHandle, Language, FlagD, 0, HiiString); } } else { Status = ShellConvertStringToUint64(Lang, &Intermediate, TRUE, FALSE); if (EFI_ERROR(Status) || ConvertHandleIndexToHandle((UINTN)Intermediate) == NULL) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"devtree", Lang); ShellStatus = SHELL_INVALID_PARAMETER; } else { ShellStatus = DoDevTreeForHandle(ConvertHandleIndexToHandle((UINTN)Intermediate), Language, FlagD, 0, HiiString); } } if (HiiString != NULL) { FreePool(HiiString); } SHELL_FREE_NON_NULL(Language); ShellCommandLineFreeVarList (Package); } return (ShellStatus); }