diff options
Diffstat (limited to 'ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c')
| -rw-r--r-- | ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c | 2742 |
1 files changed, 1371 insertions, 1371 deletions
diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c index 1e7168364d..4f0a8bb5d0 100644 --- a/ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c +++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c @@ -1,1371 +1,1371 @@ -/** @file
- Main file for map shell level 2 command.
-
- Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
- (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
- (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
-
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "UefiShellLevel2CommandsLib.h"
-#include <Protocol/SimpleFileSystem.h>
-#include <Protocol/BlockIo.h>
-#include <Library/DevicePathLib.h>
-#include <Library/HandleParsingLib.h>
-#include <Library/SortLib.h>
-
-/**
- Determine if a string has only numbers and letters.
-
- This is useful for such things as Map names which can only be letters and numbers.
-
- @param[in] String pointer to the string to analyze,
- @param[in] Len Number of characters to analyze.
-
- @retval TRUE String has only numbers and letters
- @retval FALSE String has at least one other character.
-**/
-BOOLEAN
-IsNumberLetterOnly (
- IN CONST CHAR16 *String,
- IN CONST UINTN Len
- )
-{
- UINTN Count;
-
- for (Count = 0; Count < Len && String != NULL && *String != CHAR_NULL; String++, Count++) {
- if (!(((*String >= L'a') && (*String <= L'z')) ||
- ((*String >= L'A') && (*String <= L'Z')) ||
- ((*String >= L'0') && (*String <= L'9')))
- )
- {
- return (FALSE);
- }
- }
-
- return (TRUE);
-}
-
-/**
- Do a search in the Target delimited list.
-
- @param[in] List The list to seatch in.
- @param[in] MetaTarget The item to search for. MetaMatching supported.
- @param[out] FullName Optional pointer to an allocated buffer containing
- the match.
- @param[in] Meta TRUE to use MetaMatching.
- @param[in] SkipTrailingNumbers TRUE to allow for numbers after the MetaTarget.
- @param[in] Target The single character that delimits list
- items (";" normally).
-**/
-BOOLEAN
-SearchList (
- IN CONST CHAR16 *List,
- IN CONST CHAR16 *MetaTarget,
- OUT CHAR16 **FullName OPTIONAL,
- IN CONST BOOLEAN Meta,
- IN CONST BOOLEAN SkipTrailingNumbers,
- IN CONST CHAR16 *Target
-
- )
-{
- CHAR16 *TempList;
- CONST CHAR16 *ListWalker;
- BOOLEAN Result;
- CHAR16 *TempSpot;
-
- for (ListWalker = List, TempList = NULL
- ; ListWalker != NULL && *ListWalker != CHAR_NULL
- ;
- )
- {
- TempList = StrnCatGrow (&TempList, NULL, ListWalker, 0);
- ASSERT (TempList != NULL);
- TempSpot = StrStr (TempList, Target);
- if (TempSpot != NULL) {
- *TempSpot = CHAR_NULL;
- }
-
- while (SkipTrailingNumbers && (ShellIsDecimalDigitCharacter (TempList[StrLen (TempList)-1]) || TempList[StrLen (TempList)-1] == L':')) {
- TempList[StrLen (TempList)-1] = CHAR_NULL;
- }
-
- ListWalker = StrStr (ListWalker, Target);
- while (ListWalker != NULL && *ListWalker == *Target) {
- ListWalker++;
- }
-
- if (Meta) {
- Result = gUnicodeCollation->MetaiMatch (gUnicodeCollation, (CHAR16 *)TempList, (CHAR16 *)MetaTarget);
- } else {
- Result = (BOOLEAN)(StrCmp (TempList, MetaTarget) == 0);
- }
-
- if (Result) {
- if (FullName != NULL) {
- *FullName = TempList;
- } else {
- FreePool (TempList);
- }
-
- return (TRUE);
- }
-
- FreePool (TempList);
- TempList = NULL;
- }
-
- return (FALSE);
-}
-
-/**
- Determine what type of device is represented and return it's string. The
- string is in allocated memory and must be callee freed. The HII is is listed below.
- The actual string cannot be determined.
-
- @param[in] DevicePath The device to analyze.
-
- @retval STR_MAP_MEDIA_UNKNOWN The media type is unknown.
- @retval STR_MAP_MEDIA_HARDDISK The media is a hard drive.
- @retval STR_MAP_MEDIA_CDROM The media is a CD ROM.
- @retval STR_MAP_MEDIA_FLOPPY The media is a floppy drive.
-**/
-CHAR16 *
-GetDeviceMediaType (
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
- )
-{
- ACPI_HID_DEVICE_PATH *Acpi;
-
- //
- // Parse the device path:
- // Devicepath sub type mediatype
- // MEDIA_HANRDDRIVE_DP -> Hard Disk
- // MEDIA_CDROM_DP -> CD Rom
- // Acpi.HID = 0X0604 -> Floppy
- //
- if (NULL == DevicePath) {
- return HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_MAP_MEDIA_UNKNOWN), NULL);
- }
-
- for ( ; !IsDevicePathEndType (DevicePath); DevicePath = NextDevicePathNode (DevicePath)) {
- if (DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) {
- switch (DevicePathSubType (DevicePath)) {
- case MEDIA_HARDDRIVE_DP:
- return HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_MAP_MEDIA_HARDDISK), NULL);
- case MEDIA_CDROM_DP:
- return HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_MAP_MEDIA_CDROM), NULL);
- }
- } else if (DevicePathType (DevicePath) == ACPI_DEVICE_PATH) {
- Acpi = (ACPI_HID_DEVICE_PATH *)DevicePath;
- if (EISA_ID_TO_NUM (Acpi->HID) == 0x0604) {
- return HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_MAP_MEDIA_FLOPPY), NULL);
- }
- }
- }
-
- return HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_MAP_MEDIA_UNKNOWN), NULL);
-}
-
-/**
- Function to detemine if a handle has removable storage.
-
- @param[in] DevicePath DevicePath to test.
-
- @retval TRUE The handle has removable storage.
- @retval FALSE The handle does not have removable storage.
-**/
-BOOLEAN
-IsRemoveableDevice (
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
- )
-{
- if (NULL == DevicePath) {
- return FALSE;
- }
-
- while (!IsDevicePathEndType (DevicePath)) {
- if (DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) {
- switch (DevicePathSubType (DevicePath)) {
- case MSG_USB_DP:
- case MSG_SCSI_DP:
- return TRUE;
- default:
- return FALSE;
- }
- }
-
- DevicePath = NextDevicePathNode (DevicePath);
- }
-
- return FALSE;
-}
-
-/**
- Function to detemine if a something on the map list matches.
-
- @param[in] MapList The pointer to the list to test.
- @param[in] Specific The pointer to a specific name to test for.
- @param[in] TypeString The pointer to the list of types.
- @param[in] Normal Always show normal mappings.
- @param[in] Consist Always show consistent mappings.
-
- @retval TRUE The map should be displayed.
- @retval FALSE The map should not be displayed.
-**/
-BOOLEAN
-MappingListHasType (
- IN CONST CHAR16 *MapList,
- IN CONST CHAR16 *Specific,
- IN CONST CHAR16 *TypeString,
- IN CONST BOOLEAN Normal,
- IN CONST BOOLEAN Consist
- )
-{
- CHAR16 *NewSpecific;
- RETURN_STATUS Status;
- UINTN Length;
-
- //
- // specific has priority
- //
- if (Specific != NULL) {
- Length = StrLen (Specific);
- //
- // Allocate enough buffer for Specific and potential ":"
- //
- NewSpecific = AllocatePool ((Length + 2) * sizeof (CHAR16));
- if (NewSpecific == NULL) {
- return FALSE;
- }
-
- StrCpyS (NewSpecific, Length + 2, Specific);
- if (Specific[Length - 1] != L':') {
- Status = StrnCatS (NewSpecific, Length + 2, L":", StrLen (L":"));
- if (EFI_ERROR (Status)) {
- FreePool (NewSpecific);
- return FALSE;
- }
- }
-
- if (SearchList (MapList, NewSpecific, NULL, TRUE, FALSE, L";")) {
- FreePool (NewSpecific);
- return (TRUE);
- }
-
- FreePool (NewSpecific);
- }
-
- if ( Consist
- && (Specific == NULL)
- && ( SearchList (MapList, L"HD*", NULL, TRUE, TRUE, L";")
- || SearchList (MapList, L"CD*", NULL, TRUE, TRUE, L";")
- || SearchList (MapList, L"F*", NULL, TRUE, TRUE, L";")
- || SearchList (MapList, L"FP*", NULL, TRUE, TRUE, L";")))
- {
- return (TRUE);
- }
-
- if ( Normal
- && (Specific == NULL)
- && ( SearchList (MapList, L"FS", NULL, FALSE, TRUE, L";")
- || SearchList (MapList, L"BLK", NULL, FALSE, TRUE, L";")))
- {
- return (TRUE);
- }
-
- if ((TypeString != NULL) && SearchList (MapList, TypeString, NULL, TRUE, TRUE, L";")) {
- return (TRUE);
- }
-
- return (FALSE);
-}
-
-/**
- Display a single map line for device Handle if conditions are met.
-
- @param[in] Verbose TRUE to display (extra) verbose information.
- @param[in] Consist TRUE to display consistent mappings.
- @param[in] Normal TRUE to display normal (not consist) mappings.
- @param[in] TypeString pointer to string of filter types.
- @param[in] SFO TRUE to display output in Standard Output Format.
- @param[in] Specific pointer to string for specific map to display.
- @param[in] Handle The handle to display from.
-
- @retval EFI_SUCCESS The mapping was displayed.
-**/
-EFI_STATUS
-PerformSingleMappingDisplay (
- IN CONST BOOLEAN Verbose,
- IN CONST BOOLEAN Consist,
- IN CONST BOOLEAN Normal,
- IN CONST CHAR16 *TypeString,
- IN CONST BOOLEAN SFO,
- IN CONST CHAR16 *Specific OPTIONAL,
- IN CONST EFI_HANDLE Handle
- )
-{
- EFI_DEVICE_PATH_PROTOCOL *DevPath;
- EFI_DEVICE_PATH_PROTOCOL *DevPathCopy;
- CONST CHAR16 *MapList;
- CHAR16 *CurrentName;
- CHAR16 *MediaType;
- CHAR16 *DevPathString;
- CHAR16 *TempSpot;
- CHAR16 *Alias;
- UINTN TempLen;
- BOOLEAN Removable;
- CONST CHAR16 *TempSpot2;
-
- Alias = NULL;
- TempSpot2 = NULL;
- CurrentName = NULL;
- DevPath = DevicePathFromHandle (Handle);
- DevPathCopy = DevPath;
- MapList = gEfiShellProtocol->GetMapFromDevicePath (&DevPathCopy);
- if (MapList == NULL) {
- return EFI_NOT_FOUND;
- }
-
- if (!MappingListHasType (MapList, Specific, TypeString, Normal, Consist)) {
- return EFI_NOT_FOUND;
- }
-
- if (Normal || !Consist) {
- //
- // need the Normal here since people can use both on command line. otherwise unused.
- //
-
- //
- // Allocate a name
- //
- CurrentName = NULL;
- CurrentName = StrnCatGrow (&CurrentName, 0, MapList, 0);
- if (CurrentName == NULL) {
- return (EFI_OUT_OF_RESOURCES);
- }
-
- //
- // Chop off the other names that become "Alias(s)"
- // leaving just the normal name
- //
- TempSpot = StrStr (CurrentName, L";");
- if (TempSpot != NULL) {
- *TempSpot = CHAR_NULL;
- }
- } else {
- CurrentName = NULL;
-
- //
- // Skip the first name. This is the standard name.
- //
- TempSpot = StrStr (MapList, L";");
- if (TempSpot != NULL) {
- TempSpot++;
- }
-
- SearchList (TempSpot, L"HD*", &CurrentName, TRUE, FALSE, L";");
- if (CurrentName == NULL) {
- SearchList (TempSpot, L"CD*", &CurrentName, TRUE, FALSE, L";");
- }
-
- if (CurrentName == NULL) {
- SearchList (TempSpot, L"FP*", &CurrentName, TRUE, FALSE, L";");
- }
-
- if (CurrentName == NULL) {
- SearchList (TempSpot, L"F*", &CurrentName, TRUE, FALSE, L";");
- }
-
- if (CurrentName == NULL) {
- //
- // We didnt find anything, so just the first one in the list...
- //
- CurrentName = StrnCatGrow (&CurrentName, 0, MapList, 0);
- if (CurrentName == NULL) {
- return (EFI_OUT_OF_RESOURCES);
- }
-
- TempSpot = StrStr (CurrentName, L";");
- if (TempSpot != NULL) {
- *TempSpot = CHAR_NULL;
- }
- } else {
- Alias = StrnCatGrow (&Alias, 0, MapList, 0);
- if (Alias == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- TempSpot = StrStr (Alias, CurrentName);
- if (TempSpot != NULL) {
- TempSpot2 = StrStr (TempSpot, L";");
- if (TempSpot2 != NULL) {
- TempSpot2++; // Move past ";" from CurrentName
- CopyMem (TempSpot, TempSpot2, StrSize (TempSpot2));
- } else {
- *TempSpot = CHAR_NULL;
- }
- }
-
- if (Alias[StrLen (Alias)-1] == L';') {
- Alias[StrLen (Alias)-1] = CHAR_NULL;
- }
- }
- }
-
- DevPathString = ConvertDevicePathToText (DevPath, TRUE, FALSE);
- TempLen = StrLen (CurrentName);
- if (!SFO) {
- ShellPrintHiiEx (
- -1,
- -1,
- NULL,
- STRING_TOKEN (STR_MAP_ENTRY),
- gShellLevel2HiiHandle,
- CurrentName,
- Alias != NULL ? Alias : (TempLen < StrLen (MapList) ? MapList + TempLen+1 : L""),
- DevPathString
- );
- if (Verbose) {
- //
- // also print handle, media type, removable (y/n), and current directory
- //
- MediaType = GetDeviceMediaType (DevPath);
- if (((TypeString != NULL) && (MediaType != NULL) && (StrStr (TypeString, MediaType) != NULL)) || (TypeString == NULL)) {
- Removable = IsRemoveableDevice (DevPath);
- TempSpot2 = ShellGetCurrentDir (CurrentName);
- ShellPrintHiiEx (
- -1,
- -1,
- NULL,
- STRING_TOKEN (STR_MAP_ENTRY_VERBOSE),
- gShellLevel2HiiHandle,
- ConvertHandleToHandleIndex (Handle),
- MediaType,
- Removable ? L"Yes" : L"No",
- TempSpot2
- );
- }
-
- SHELL_FREE_NON_NULL (MediaType);
- }
- } else {
- ShellPrintHiiEx (
- -1,
- -1,
- NULL,
- STRING_TOKEN (STR_MAP_SFO_MAPPINGS),
- gShellLevel2HiiHandle,
- CurrentName,
- DevPathString,
- Consist ? L"" : (TempLen < StrLen (MapList) ? MapList + TempLen+1 : L"")
- );
- }
-
- SHELL_FREE_NON_NULL (DevPathString);
- SHELL_FREE_NON_NULL (CurrentName);
- SHELL_FREE_NON_NULL (Alias);
- return EFI_SUCCESS;
-}
-
-/**
- Delete Specific from the list of maps for device Handle.
-
- @param[in] Specific The name to delete.
- @param[in] Handle The device to look on.
-
- @retval EFI_SUCCESS The delete was successful.
- @retval EFI_NOT_FOUND Name was not a map on Handle.
-**/
-EFI_STATUS
-PerformSingleMappingDelete (
- IN CONST CHAR16 *Specific,
- IN CONST EFI_HANDLE Handle
- )
-{
- EFI_DEVICE_PATH_PROTOCOL *DevPath;
- EFI_DEVICE_PATH_PROTOCOL *DevPathCopy;
- CONST CHAR16 *MapList;
- CHAR16 *CurrentName;
-
- DevPath = DevicePathFromHandle (Handle);
- DevPathCopy = DevPath;
- MapList = gEfiShellProtocol->GetMapFromDevicePath (&DevPathCopy);
- CurrentName = NULL;
-
- if (MapList == NULL) {
- return (EFI_NOT_FOUND);
- }
-
- //
- // if there is a specific and its not on the list...
- //
- if (!SearchList (MapList, Specific, &CurrentName, TRUE, FALSE, L";")) {
- return (EFI_NOT_FOUND);
- }
-
- return (gEfiShellProtocol->SetMap (NULL, CurrentName));
-}
-
-CONST CHAR16 Cd[] = L"cd*";
-CONST CHAR16 Hd[] = L"hd*";
-CONST CHAR16 Fp[] = L"fp*";
-CONST CHAR16 AnyF[] = L"F*";
-
-/**
- Function to display mapping information to the user.
-
- If Specific is specified then Consist and Normal will be ignored since information will
- be printed for the specific item only.
-
- @param[in] Verbose TRUE to display (extra) verbose information.
- @param[in] Consist TRUE to display consistent mappings.
- @param[in] Normal TRUE to display normal (not consist) mappings.
- @param[in] TypeString Pointer to string of filter types.
- @param[in] SFO TRUE to display output in Standard Output Format.
- @param[in] Specific Pointer to string for specific map to display.
- @param[in] Header TRUE to print the header block.
-
- @retval SHELL_SUCCESS The display was printed.
- @retval SHELL_INVALID_PARAMETER One of Consist or Normal must be TRUE if no Specific.
-
-**/
-SHELL_STATUS
-PerformMappingDisplay (
- IN CONST BOOLEAN Verbose,
- IN CONST BOOLEAN Consist,
- IN CONST BOOLEAN Normal,
- IN CONST CHAR16 *TypeString,
- IN CONST BOOLEAN SFO,
- IN CONST CHAR16 *Specific OPTIONAL,
- IN CONST BOOLEAN Header
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE *HandleBuffer;
- UINTN BufferSize;
- UINTN LoopVar;
- CHAR16 *Test;
- BOOLEAN Found;
-
- if (!Consist && !Normal && (Specific == NULL) && (TypeString == NULL)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"map");
- return (SHELL_INVALID_PARAMETER);
- }
-
- if (TypeString != NULL) {
- Test = (CHAR16 *)Cd;
- if (StrnCmp (TypeString, Test, StrLen (Test)-1) != 0) {
- Test = (CHAR16 *)Hd;
- if (StrnCmp (TypeString, Test, StrLen (Test)-1) != 0) {
- Test = (CHAR16 *)Fp;
- if (StrnCmp (TypeString, Test, StrLen (Test)-1) != 0) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"map", TypeString);
- return (SHELL_INVALID_PARAMETER);
- }
- } else if (Test == NULL) {
- Test = (CHAR16 *)AnyF;
- }
- }
- } else {
- Test = NULL;
- }
-
- if (Header) {
- //
- // Print the header
- //
- if (!SFO) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MAP_HEADER), gShellLevel2HiiHandle);
- } else {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_SFO_HEADER), gShellLevel2HiiHandle, L"map");
- }
- }
-
- BufferSize = 0;
- HandleBuffer = NULL;
-
- //
- // Look up all SimpleFileSystems in the platform
- //
- Status = gBS->LocateHandle (
- ByProtocol,
- &gEfiSimpleFileSystemProtocolGuid,
- NULL,
- &BufferSize,
- HandleBuffer
- );
- if (Status == EFI_BUFFER_TOO_SMALL) {
- HandleBuffer = AllocateZeroPool (BufferSize);
- if (HandleBuffer == NULL) {
- return (SHELL_OUT_OF_RESOURCES);
- }
-
- Status = gBS->LocateHandle (
- ByProtocol,
- &gEfiSimpleFileSystemProtocolGuid,
- NULL,
- &BufferSize,
- HandleBuffer
- );
- }
-
- //
- // Get the map name(s) for each one.
- //
- for ( LoopVar = 0, Found = FALSE
- ; LoopVar < (BufferSize / sizeof (EFI_HANDLE)) && HandleBuffer != NULL
- ; LoopVar++
- )
- {
- Status = PerformSingleMappingDisplay (
- Verbose,
- Consist,
- Normal,
- Test,
- SFO,
- Specific,
- HandleBuffer[LoopVar]
- );
- if (!EFI_ERROR (Status)) {
- Found = TRUE;
- }
- }
-
- //
- // Look up all BlockIo in the platform
- //
- Status = gBS->LocateHandle (
- ByProtocol,
- &gEfiBlockIoProtocolGuid,
- NULL,
- &BufferSize,
- HandleBuffer
- );
- if (Status == EFI_BUFFER_TOO_SMALL) {
- SHELL_FREE_NON_NULL (HandleBuffer);
- HandleBuffer = AllocateZeroPool (BufferSize);
- if (HandleBuffer == NULL) {
- return (SHELL_OUT_OF_RESOURCES);
- }
-
- Status = gBS->LocateHandle (
- ByProtocol,
- &gEfiBlockIoProtocolGuid,
- NULL,
- &BufferSize,
- HandleBuffer
- );
- }
-
- if (!EFI_ERROR (Status) && (HandleBuffer != NULL)) {
- //
- // Get the map name(s) for each one.
- //
- for ( LoopVar = 0
- ; LoopVar < BufferSize / sizeof (EFI_HANDLE)
- ; LoopVar++
- )
- {
- //
- // Skip any that were already done...
- //
- if (gBS->OpenProtocol (
- HandleBuffer[LoopVar],
- &gEfiSimpleFileSystemProtocolGuid,
- NULL,
- gImageHandle,
- NULL,
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL
- ) == EFI_SUCCESS)
- {
- continue;
- }
-
- Status = PerformSingleMappingDisplay (
- Verbose,
- Consist,
- Normal,
- Test,
- SFO,
- Specific,
- HandleBuffer[LoopVar]
- );
- if (!EFI_ERROR (Status)) {
- Found = TRUE;
- }
- }
-
- FreePool (HandleBuffer);
- }
-
- if (!Found) {
- if (Specific != NULL) {
- ShellPrintHiiEx (gST->ConOut->Mode->CursorColumn, gST->ConOut->Mode->CursorRow-1, NULL, STRING_TOKEN (STR_MAP_NF), gShellLevel2HiiHandle, L"map", Specific);
- } else {
- ShellPrintHiiEx (gST->ConOut->Mode->CursorColumn, gST->ConOut->Mode->CursorRow-1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"map");
- }
- }
-
- return (SHELL_SUCCESS);
-}
-
-/**
- Perform a mapping display and parse for multiple types in the TypeString.
-
- @param[in] Verbose TRUE to use verbose output.
- @param[in] Consist TRUE to display consistent names.
- @param[in] Normal TRUE to display normal names.
- @param[in] TypeString An optional comma-delimited list of types.
- @param[in] SFO TRUE to display in SFO format. See Spec.
- @param[in] Specific An optional specific map name to display alone.
-
- @retval SHELL_INVALID_PARAMETER A parameter was invalid.
- @retval SHELL_SUCCESS The display was successful.
- @sa PerformMappingDisplay
-**/
-SHELL_STATUS
-PerformMappingDisplay2 (
- IN CONST BOOLEAN Verbose,
- IN CONST BOOLEAN Consist,
- IN CONST BOOLEAN Normal,
- IN CONST CHAR16 *TypeString,
- IN CONST BOOLEAN SFO,
- IN CONST CHAR16 *Specific OPTIONAL
- )
-{
- CONST CHAR16 *TypeWalker;
- SHELL_STATUS ShellStatus;
- CHAR16 *Comma;
-
- if (TypeString == NULL) {
- return (PerformMappingDisplay (Verbose, Consist, Normal, NULL, SFO, Specific, TRUE));
- }
-
- ShellStatus = SHELL_SUCCESS;
- for (TypeWalker = TypeString; TypeWalker != NULL && *TypeWalker != CHAR_NULL;) {
- Comma = StrStr (TypeWalker, L",");
- if (Comma == NULL) {
- if (ShellStatus == SHELL_SUCCESS) {
- ShellStatus = PerformMappingDisplay (Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString));
- } else {
- PerformMappingDisplay (Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString));
- }
-
- break;
- } else {
- *Comma = CHAR_NULL;
- if (ShellStatus == SHELL_SUCCESS) {
- ShellStatus = PerformMappingDisplay (Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString));
- } else {
- PerformMappingDisplay (Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString));
- }
-
- *Comma = L',';
- TypeWalker = Comma + 1;
- }
- }
-
- return (ShellStatus);
-}
-
-/**
- Delete a specific map.
-
- @param[in] Specific The pointer to the name of the map to delete.
-
- @retval EFI_INVALID_PARAMETER Specific was NULL.
- @retval EFI_SUCCESS The operation was successful.
- @retval EFI_NOT_FOUND Specific could not be found.
-**/
-EFI_STATUS
-PerformMappingDelete (
- IN CONST CHAR16 *Specific
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE *HandleBuffer;
- UINTN BufferSize;
- UINTN LoopVar;
- BOOLEAN Deleted;
-
- if (Specific == NULL) {
- return (EFI_INVALID_PARAMETER);
- }
-
- BufferSize = 0;
- HandleBuffer = NULL;
- Deleted = FALSE;
-
- //
- // Look up all SimpleFileSystems in the platform
- //
- Status = gBS->LocateHandle (
- ByProtocol,
- &gEfiDevicePathProtocolGuid,
- NULL,
- &BufferSize,
- HandleBuffer
- );
- if (Status == EFI_BUFFER_TOO_SMALL) {
- HandleBuffer = AllocateZeroPool (BufferSize);
- if (HandleBuffer == NULL) {
- return (EFI_OUT_OF_RESOURCES);
- }
-
- Status = gBS->LocateHandle (
- ByProtocol,
- &gEfiDevicePathProtocolGuid,
- NULL,
- &BufferSize,
- HandleBuffer
- );
- }
-
- if (EFI_ERROR (Status)) {
- SHELL_FREE_NON_NULL (HandleBuffer);
- return (Status);
- }
-
- if (HandleBuffer != NULL) {
- //
- // Get the map name(s) for each one.
- //
- for ( LoopVar = 0
- ; LoopVar < BufferSize / sizeof (EFI_HANDLE)
- ; LoopVar++
- )
- {
- if (PerformSingleMappingDelete (Specific, HandleBuffer[LoopVar]) == SHELL_SUCCESS) {
- Deleted = TRUE;
- }
- }
- }
-
- //
- // Look up all BlockIo in the platform
- //
- Status = gBS->LocateHandle (
- ByProtocol,
- &gEfiBlockIoProtocolGuid,
- NULL,
- &BufferSize,
- HandleBuffer
- );
- if (Status == EFI_BUFFER_TOO_SMALL) {
- FreePool (HandleBuffer);
- HandleBuffer = AllocateZeroPool (BufferSize);
- if (HandleBuffer == NULL) {
- return (EFI_OUT_OF_RESOURCES);
- }
-
- Status = gBS->LocateHandle (
- ByProtocol,
- &gEfiBlockIoProtocolGuid,
- NULL,
- &BufferSize,
- HandleBuffer
- );
- }
-
- if (EFI_ERROR (Status)) {
- SHELL_FREE_NON_NULL (HandleBuffer);
- return (Status);
- }
-
- if (HandleBuffer != NULL) {
- //
- // Get the map name(s) for each one.
- //
- for ( LoopVar = 0
- ; LoopVar < BufferSize / sizeof (EFI_HANDLE)
- ; LoopVar++
- )
- {
- //
- // Skip any that were already done...
- //
- if (gBS->OpenProtocol (
- HandleBuffer[LoopVar],
- &gEfiDevicePathProtocolGuid,
- NULL,
- gImageHandle,
- NULL,
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL
- ) == EFI_SUCCESS)
- {
- continue;
- }
-
- if (PerformSingleMappingDelete (Specific, HandleBuffer[LoopVar]) == SHELL_SUCCESS) {
- Deleted = TRUE;
- }
- }
- }
-
- SHELL_FREE_NON_NULL (HandleBuffer);
- if (!Deleted) {
- return (EFI_NOT_FOUND);
- }
-
- return (EFI_SUCCESS);
-}
-
-/**
- function to add a mapping from mapping.
-
- This function will get the device path associated with the mapping and call SetMap.
-
- @param[in] Map The Map to add a mapping for
- @param[in] SName The name of the new mapping
-
- @retval SHELL_SUCCESS the mapping was added
- @retval SHELL_INVALID_PARAMETER the device path for Map could not be retrieved.
- @return Shell version of a return value from EfiShellProtocol->SetMap
-
-**/
-SHELL_STATUS
-AddMappingFromMapping (
- IN CONST CHAR16 *Map,
- IN CONST CHAR16 *SName
- )
-{
- CONST EFI_DEVICE_PATH_PROTOCOL *DevPath;
- EFI_STATUS Status;
- CHAR16 *NewSName;
- RETURN_STATUS StrRetStatus;
-
- NewSName = AllocateCopyPool (StrSize (SName) + sizeof (CHAR16), SName);
- if (NewSName == NULL) {
- return (SHELL_OUT_OF_RESOURCES);
- }
-
- if (NewSName[StrLen (NewSName)-1] != L':') {
- StrRetStatus = StrnCatS (NewSName, (StrSize (SName) + sizeof (CHAR16))/sizeof (CHAR16), L":", StrLen (L":"));
- if (EFI_ERROR (StrRetStatus)) {
- FreePool (NewSName);
- return ((SHELL_STATUS)(StrRetStatus & (~MAX_BIT)));
- }
- }
-
- if (!IsNumberLetterOnly (NewSName, StrLen (NewSName)-1)) {
- FreePool (NewSName);
- return (SHELL_INVALID_PARAMETER);
- }
-
- DevPath = gEfiShellProtocol->GetDevicePathFromMap (Map);
- if (DevPath == NULL) {
- FreePool (NewSName);
- return (SHELL_INVALID_PARAMETER);
- }
-
- Status = gEfiShellProtocol->SetMap (DevPath, NewSName);
- FreePool (NewSName);
- if (EFI_ERROR (Status)) {
- return (SHELL_DEVICE_ERROR);
- }
-
- return (SHELL_SUCCESS);
-}
-
-/**
- function to add a mapping from an EFI_HANDLE.
-
- This function will get the device path associated with the Handle and call SetMap.
-
- @param[in] Handle The handle to add a mapping for
- @param[in] SName The name of the new mapping
-
- @retval SHELL_SUCCESS the mapping was added
- @retval SHELL_INVALID_PARAMETER SName was not valid for a map name.
- @return Shell version of a return value from either
- gBS->OpenProtocol or EfiShellProtocol->SetMap
-
-**/
-SHELL_STATUS
-AddMappingFromHandle (
- IN CONST EFI_HANDLE Handle,
- IN CONST CHAR16 *SName
- )
-{
- EFI_DEVICE_PATH_PROTOCOL *DevPath;
- EFI_STATUS Status;
- CHAR16 *NewSName;
- RETURN_STATUS StrRetStatus;
-
- NewSName = AllocateCopyPool (StrSize (SName) + sizeof (CHAR16), SName);
- if (NewSName == NULL) {
- return (SHELL_OUT_OF_RESOURCES);
- }
-
- if (NewSName[StrLen (NewSName)-1] != L':') {
- StrRetStatus = StrnCatS (NewSName, (StrSize (SName) + sizeof (CHAR16))/sizeof (CHAR16), L":", StrLen (L":"));
- if (EFI_ERROR (StrRetStatus)) {
- FreePool (NewSName);
- return ((SHELL_STATUS)(StrRetStatus & (~MAX_BIT)));
- }
- }
-
- if (!IsNumberLetterOnly (NewSName, StrLen (NewSName)-1)) {
- FreePool (NewSName);
- return (SHELL_INVALID_PARAMETER);
- }
-
- Status = gBS->OpenProtocol (
- Handle,
- &gEfiDevicePathProtocolGuid,
- (VOID **)&DevPath,
- gImageHandle,
- NULL,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (EFI_ERROR (Status)) {
- FreePool (NewSName);
- return (SHELL_DEVICE_ERROR);
- }
-
- Status = gEfiShellProtocol->SetMap (DevPath, NewSName);
- FreePool (NewSName);
- if (EFI_ERROR (Status)) {
- return (SHELL_DEVICE_ERROR);
- }
-
- return (SHELL_SUCCESS);
-}
-
-STATIC CONST SHELL_PARAM_ITEM MapParamList[] = {
- { L"-d", TypeValue },
- { L"-r", TypeFlag },
- { L"-v", TypeFlag },
- { L"-c", TypeFlag },
- { L"-f", TypeFlag },
- { L"-u", TypeFlag },
- { L"-t", TypeValue },
- { L"-sfo", TypeValue },
- { NULL, TypeMax }
-};
-
-/**
- The routine issues dummy read for every physical block device to cause
- the BlockIo re-installed if media change happened.
-**/
-VOID
-ProbeForMediaChange (
- VOID
- )
-{
- EFI_STATUS Status;
- UINTN HandleCount;
- EFI_HANDLE *Handles;
- EFI_BLOCK_IO_PROTOCOL *BlockIo;
- UINTN Index;
-
- gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiBlockIoProtocolGuid,
- NULL,
- &HandleCount,
- &Handles
- );
- //
- // Probe for media change for every physical block io
- //
- for (Index = 0; Index < HandleCount; Index++) {
- Status = gBS->HandleProtocol (
- Handles[Index],
- &gEfiBlockIoProtocolGuid,
- (VOID **)&BlockIo
- );
- if (!EFI_ERROR (Status)) {
- if (!BlockIo->Media->LogicalPartition) {
- //
- // Per spec:
- // The function (ReadBlocks) must return EFI_NO_MEDIA or
- // EFI_MEDIA_CHANGED even if LBA, BufferSize, or Buffer are invalid so the caller can probe
- // for changes in media state.
- //
- BlockIo->ReadBlocks (
- BlockIo,
- BlockIo->Media->MediaId,
- 0,
- 0,
- NULL
- );
- }
- }
- }
-}
-
-/**
- Function for 'map' 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
-ShellCommandRunMap (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- EFI_STATUS Status;
- LIST_ENTRY *Package;
- CHAR16 *ProblemParam;
- CONST CHAR16 *SName;
- CONST CHAR16 *Mapping;
- EFI_HANDLE MapAsHandle;
- SHELL_STATUS ShellStatus;
- BOOLEAN SfoMode;
- BOOLEAN ConstMode;
- BOOLEAN NormlMode;
- CONST CHAR16 *Param1;
- CONST CHAR16 *TypeString;
- UINTN TempStringLength;
-
- ProblemParam = NULL;
- Mapping = NULL;
- SName = NULL;
- ShellStatus = SHELL_SUCCESS;
- MapAsHandle = 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 (MapParamList, &Package, &ProblemParam, TRUE);
- if (EFI_ERROR (Status)) {
- if ((Status == EFI_VOLUME_CORRUPTED) && (ProblemParam != NULL)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"map", ProblemParam);
- FreePool (ProblemParam);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- ASSERT (FALSE);
- }
- } else {
- //
- // check for "-?"
- //
- SfoMode = ShellCommandLineGetFlag (Package, L"-sfo");
- ConstMode = ShellCommandLineGetFlag (Package, L"-c");
- NormlMode = ShellCommandLineGetFlag (Package, L"-f");
- if (ShellCommandLineGetFlag (Package, L"-?")) {
- ASSERT (FALSE);
- } else if (ShellCommandLineGetRawValue (Package, 3) != NULL) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"map");
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- //
- // Deleting a map name...
- //
- if (ShellCommandLineGetFlag (Package, L"-d")) {
- if ( ShellCommandLineGetFlag (Package, L"-r")
- || ShellCommandLineGetFlag (Package, L"-v")
- || ConstMode
- || NormlMode
- || ShellCommandLineGetFlag (Package, L"-u")
- || ShellCommandLineGetFlag (Package, L"-t")
- )
- {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellLevel2HiiHandle, L"map");
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- SName = ShellCommandLineGetValue (Package, L"-d");
- if (SName != NULL) {
- Status = PerformMappingDelete (SName);
- if (EFI_ERROR (Status)) {
- if (Status == EFI_ACCESS_DENIED) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel2HiiHandle, L"map");
- ShellStatus = SHELL_ACCESS_DENIED;
- } else if (Status == EFI_NOT_FOUND) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MAP_NF), gShellLevel2HiiHandle, L"map", SName);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, L"map", Status);
- ShellStatus = SHELL_UNSUPPORTED;
- }
- }
- } else {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"map");
- ShellStatus = SHELL_INVALID_PARAMETER;
- }
- }
- } else if ( ShellCommandLineGetFlag (Package, L"-r")
- // || ShellCommandLineGetFlag(Package, L"-v")
- || ConstMode
- || NormlMode
- || ShellCommandLineGetFlag (Package, L"-u")
- || ShellCommandLineGetFlag (Package, L"-t")
- )
- {
- ProbeForMediaChange ();
- if ( ShellCommandLineGetFlag (Package, L"-r")) {
- //
- // Do the reset
- //
- Status = ShellCommandCreateInitialMappingsAndPaths ();
- if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, L"map", Status);
- ShellStatus = SHELL_UNSUPPORTED;
- }
- }
-
- if ((ShellStatus == SHELL_SUCCESS) && ShellCommandLineGetFlag (Package, L"-u")) {
- //
- // Do the Update
- //
- Status = ShellCommandUpdateMapping ();
- if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, L"map", Status);
- ShellStatus = SHELL_UNSUPPORTED;
- }
- }
-
- if (ShellStatus == SHELL_SUCCESS) {
- Param1 = ShellCommandLineGetRawValue (Package, 1);
- TypeString = ShellCommandLineGetValue (Package, L"-t");
- if ( !ConstMode
- && !NormlMode
- && (TypeString == NULL)
- )
- {
- //
- // now do the display...
- //
- ShellStatus = PerformMappingDisplay (
- ShellCommandLineGetFlag (Package, L"-v"),
- TRUE,
- TRUE,
- NULL,
- SfoMode,
- Param1,
- TRUE
- );
- } else {
- //
- // now do the display...
- //
- ShellStatus = PerformMappingDisplay2 (
- ShellCommandLineGetFlag (Package, L"-v"),
- ConstMode,
- NormlMode,
- TypeString,
- SfoMode,
- Param1
- );
- }
- }
- } else {
- //
- // adding or displaying (there were no flags)
- //
- SName = ShellCommandLineGetRawValue (Package, 1);
- Mapping = ShellCommandLineGetRawValue (Package, 2);
- if ( (SName == NULL)
- && (Mapping == NULL)
- )
- {
- //
- // display only since no flags
- //
- ShellStatus = PerformMappingDisplay (
- ShellCommandLineGetFlag (Package, L"-v"),
- TRUE,
- TRUE,
- NULL,
- SfoMode,
- NULL,
- TRUE
- );
- } else if ( (SName == NULL)
- || (Mapping == NULL)
- )
- {
- //
- // Display only the one specified
- //
- ShellStatus = PerformMappingDisplay (
- FALSE,
- FALSE,
- FALSE,
- NULL,
- SfoMode,
- SName, // note the variable here...
- TRUE
- );
- } else {
- if (ShellIsHexOrDecimalNumber (Mapping, TRUE, FALSE)) {
- MapAsHandle = ConvertHandleIndexToHandle (ShellStrToUintn (Mapping));
- } else {
- MapAsHandle = NULL;
- }
-
- if ((MapAsHandle == NULL) && (Mapping[StrLen (Mapping)-1] != L':')) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"map", Mapping);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- TempStringLength = StrLen (SName);
- if (!IsNumberLetterOnly (SName, TempStringLength-((SName[TempStringLength-1] == L':') ? 1 : 0))) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"map", SName);
- ShellStatus = SHELL_INVALID_PARAMETER;
- }
-
- if (ShellStatus == SHELL_SUCCESS) {
- if (MapAsHandle != NULL) {
- ShellStatus = AddMappingFromHandle (MapAsHandle, SName);
- } else {
- ShellStatus = AddMappingFromMapping (Mapping, SName);
- }
-
- if (ShellStatus != SHELL_SUCCESS) {
- switch (ShellStatus) {
- case SHELL_ACCESS_DENIED:
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel2HiiHandle, L"map");
- break;
- case SHELL_INVALID_PARAMETER:
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"map", Mapping);
- break;
- case SHELL_DEVICE_ERROR:
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MAP_NOF), gShellLevel2HiiHandle, L"map", Mapping);
- break;
- default:
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, L"map", ShellStatus|MAX_BIT);
- }
- } else {
- //
- // now do the display...
- //
- ShellStatus = PerformMappingDisplay (
- FALSE,
- FALSE,
- FALSE,
- NULL,
- SfoMode,
- SName,
- TRUE
- );
- } // we were successful so do an output
- }
- } // got a valid map target
- } // got 2 variables
- } // we are adding a mapping
- } // got valid parameters
- }
-
- //
- // free the command line package
- //
- ShellCommandLineFreeVarList (Package);
-
- return (ShellStatus);
-}
+/** @file + Main file for map shell level 2 command. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR> + (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR> + (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "UefiShellLevel2CommandsLib.h" +#include <Protocol/SimpleFileSystem.h> +#include <Protocol/BlockIo.h> +#include <Library/DevicePathLib.h> +#include <Library/HandleParsingLib.h> +#include <Library/SortLib.h> + +/** + Determine if a string has only numbers and letters. + + This is useful for such things as Map names which can only be letters and numbers. + + @param[in] String pointer to the string to analyze, + @param[in] Len Number of characters to analyze. + + @retval TRUE String has only numbers and letters + @retval FALSE String has at least one other character. +**/ +BOOLEAN +IsNumberLetterOnly ( + IN CONST CHAR16 *String, + IN CONST UINTN Len + ) +{ + UINTN Count; + + for (Count = 0; Count < Len && String != NULL && *String != CHAR_NULL; String++, Count++) { + if (!(((*String >= L'a') && (*String <= L'z')) || + ((*String >= L'A') && (*String <= L'Z')) || + ((*String >= L'0') && (*String <= L'9'))) + ) + { + return (FALSE); + } + } + + return (TRUE); +} + +/** + Do a search in the Target delimited list. + + @param[in] List The list to seatch in. + @param[in] MetaTarget The item to search for. MetaMatching supported. + @param[out] FullName Optional pointer to an allocated buffer containing + the match. + @param[in] Meta TRUE to use MetaMatching. + @param[in] SkipTrailingNumbers TRUE to allow for numbers after the MetaTarget. + @param[in] Target The single character that delimits list + items (";" normally). +**/ +BOOLEAN +SearchList ( + IN CONST CHAR16 *List, + IN CONST CHAR16 *MetaTarget, + OUT CHAR16 **FullName OPTIONAL, + IN CONST BOOLEAN Meta, + IN CONST BOOLEAN SkipTrailingNumbers, + IN CONST CHAR16 *Target + + ) +{ + CHAR16 *TempList; + CONST CHAR16 *ListWalker; + BOOLEAN Result; + CHAR16 *TempSpot; + + for (ListWalker = List, TempList = NULL + ; ListWalker != NULL && *ListWalker != CHAR_NULL + ; + ) + { + TempList = StrnCatGrow (&TempList, NULL, ListWalker, 0); + ASSERT (TempList != NULL); + TempSpot = StrStr (TempList, Target); + if (TempSpot != NULL) { + *TempSpot = CHAR_NULL; + } + + while (SkipTrailingNumbers && (ShellIsDecimalDigitCharacter (TempList[StrLen (TempList)-1]) || TempList[StrLen (TempList)-1] == L':')) { + TempList[StrLen (TempList)-1] = CHAR_NULL; + } + + ListWalker = StrStr (ListWalker, Target); + while (ListWalker != NULL && *ListWalker == *Target) { + ListWalker++; + } + + if (Meta) { + Result = gUnicodeCollation->MetaiMatch (gUnicodeCollation, (CHAR16 *)TempList, (CHAR16 *)MetaTarget); + } else { + Result = (BOOLEAN)(StrCmp (TempList, MetaTarget) == 0); + } + + if (Result) { + if (FullName != NULL) { + *FullName = TempList; + } else { + FreePool (TempList); + } + + return (TRUE); + } + + FreePool (TempList); + TempList = NULL; + } + + return (FALSE); +} + +/** + Determine what type of device is represented and return it's string. The + string is in allocated memory and must be callee freed. The HII is is listed below. + The actual string cannot be determined. + + @param[in] DevicePath The device to analyze. + + @retval STR_MAP_MEDIA_UNKNOWN The media type is unknown. + @retval STR_MAP_MEDIA_HARDDISK The media is a hard drive. + @retval STR_MAP_MEDIA_CDROM The media is a CD ROM. + @retval STR_MAP_MEDIA_FLOPPY The media is a floppy drive. +**/ +CHAR16 * +GetDeviceMediaType ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + ACPI_HID_DEVICE_PATH *Acpi; + + // + // Parse the device path: + // Devicepath sub type mediatype + // MEDIA_HANRDDRIVE_DP -> Hard Disk + // MEDIA_CDROM_DP -> CD Rom + // Acpi.HID = 0X0604 -> Floppy + // + if (NULL == DevicePath) { + return HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_MAP_MEDIA_UNKNOWN), NULL); + } + + for ( ; !IsDevicePathEndType (DevicePath); DevicePath = NextDevicePathNode (DevicePath)) { + if (DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) { + switch (DevicePathSubType (DevicePath)) { + case MEDIA_HARDDRIVE_DP: + return HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_MAP_MEDIA_HARDDISK), NULL); + case MEDIA_CDROM_DP: + return HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_MAP_MEDIA_CDROM), NULL); + } + } else if (DevicePathType (DevicePath) == ACPI_DEVICE_PATH) { + Acpi = (ACPI_HID_DEVICE_PATH *)DevicePath; + if (EISA_ID_TO_NUM (Acpi->HID) == 0x0604) { + return HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_MAP_MEDIA_FLOPPY), NULL); + } + } + } + + return HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_MAP_MEDIA_UNKNOWN), NULL); +} + +/** + Function to detemine if a handle has removable storage. + + @param[in] DevicePath DevicePath to test. + + @retval TRUE The handle has removable storage. + @retval FALSE The handle does not have removable storage. +**/ +BOOLEAN +IsRemoveableDevice ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + if (NULL == DevicePath) { + return FALSE; + } + + while (!IsDevicePathEndType (DevicePath)) { + if (DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) { + switch (DevicePathSubType (DevicePath)) { + case MSG_USB_DP: + case MSG_SCSI_DP: + return TRUE; + default: + return FALSE; + } + } + + DevicePath = NextDevicePathNode (DevicePath); + } + + return FALSE; +} + +/** + Function to detemine if a something on the map list matches. + + @param[in] MapList The pointer to the list to test. + @param[in] Specific The pointer to a specific name to test for. + @param[in] TypeString The pointer to the list of types. + @param[in] Normal Always show normal mappings. + @param[in] Consist Always show consistent mappings. + + @retval TRUE The map should be displayed. + @retval FALSE The map should not be displayed. +**/ +BOOLEAN +MappingListHasType ( + IN CONST CHAR16 *MapList, + IN CONST CHAR16 *Specific, + IN CONST CHAR16 *TypeString, + IN CONST BOOLEAN Normal, + IN CONST BOOLEAN Consist + ) +{ + CHAR16 *NewSpecific; + RETURN_STATUS Status; + UINTN Length; + + // + // specific has priority + // + if (Specific != NULL) { + Length = StrLen (Specific); + // + // Allocate enough buffer for Specific and potential ":" + // + NewSpecific = AllocatePool ((Length + 2) * sizeof (CHAR16)); + if (NewSpecific == NULL) { + return FALSE; + } + + StrCpyS (NewSpecific, Length + 2, Specific); + if (Specific[Length - 1] != L':') { + Status = StrnCatS (NewSpecific, Length + 2, L":", StrLen (L":")); + if (EFI_ERROR (Status)) { + FreePool (NewSpecific); + return FALSE; + } + } + + if (SearchList (MapList, NewSpecific, NULL, TRUE, FALSE, L";")) { + FreePool (NewSpecific); + return (TRUE); + } + + FreePool (NewSpecific); + } + + if ( Consist + && (Specific == NULL) + && ( SearchList (MapList, L"HD*", NULL, TRUE, TRUE, L";") + || SearchList (MapList, L"CD*", NULL, TRUE, TRUE, L";") + || SearchList (MapList, L"F*", NULL, TRUE, TRUE, L";") + || SearchList (MapList, L"FP*", NULL, TRUE, TRUE, L";"))) + { + return (TRUE); + } + + if ( Normal + && (Specific == NULL) + && ( SearchList (MapList, L"FS", NULL, FALSE, TRUE, L";") + || SearchList (MapList, L"BLK", NULL, FALSE, TRUE, L";"))) + { + return (TRUE); + } + + if ((TypeString != NULL) && SearchList (MapList, TypeString, NULL, TRUE, TRUE, L";")) { + return (TRUE); + } + + return (FALSE); +} + +/** + Display a single map line for device Handle if conditions are met. + + @param[in] Verbose TRUE to display (extra) verbose information. + @param[in] Consist TRUE to display consistent mappings. + @param[in] Normal TRUE to display normal (not consist) mappings. + @param[in] TypeString pointer to string of filter types. + @param[in] SFO TRUE to display output in Standard Output Format. + @param[in] Specific pointer to string for specific map to display. + @param[in] Handle The handle to display from. + + @retval EFI_SUCCESS The mapping was displayed. +**/ +EFI_STATUS +PerformSingleMappingDisplay ( + IN CONST BOOLEAN Verbose, + IN CONST BOOLEAN Consist, + IN CONST BOOLEAN Normal, + IN CONST CHAR16 *TypeString, + IN CONST BOOLEAN SFO, + IN CONST CHAR16 *Specific OPTIONAL, + IN CONST EFI_HANDLE Handle + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevPath; + EFI_DEVICE_PATH_PROTOCOL *DevPathCopy; + CONST CHAR16 *MapList; + CHAR16 *CurrentName; + CHAR16 *MediaType; + CHAR16 *DevPathString; + CHAR16 *TempSpot; + CHAR16 *Alias; + UINTN TempLen; + BOOLEAN Removable; + CONST CHAR16 *TempSpot2; + + Alias = NULL; + TempSpot2 = NULL; + CurrentName = NULL; + DevPath = DevicePathFromHandle (Handle); + DevPathCopy = DevPath; + MapList = gEfiShellProtocol->GetMapFromDevicePath (&DevPathCopy); + if (MapList == NULL) { + return EFI_NOT_FOUND; + } + + if (!MappingListHasType (MapList, Specific, TypeString, Normal, Consist)) { + return EFI_NOT_FOUND; + } + + if (Normal || !Consist) { + // + // need the Normal here since people can use both on command line. otherwise unused. + // + + // + // Allocate a name + // + CurrentName = NULL; + CurrentName = StrnCatGrow (&CurrentName, 0, MapList, 0); + if (CurrentName == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + + // + // Chop off the other names that become "Alias(s)" + // leaving just the normal name + // + TempSpot = StrStr (CurrentName, L";"); + if (TempSpot != NULL) { + *TempSpot = CHAR_NULL; + } + } else { + CurrentName = NULL; + + // + // Skip the first name. This is the standard name. + // + TempSpot = StrStr (MapList, L";"); + if (TempSpot != NULL) { + TempSpot++; + } + + SearchList (TempSpot, L"HD*", &CurrentName, TRUE, FALSE, L";"); + if (CurrentName == NULL) { + SearchList (TempSpot, L"CD*", &CurrentName, TRUE, FALSE, L";"); + } + + if (CurrentName == NULL) { + SearchList (TempSpot, L"FP*", &CurrentName, TRUE, FALSE, L";"); + } + + if (CurrentName == NULL) { + SearchList (TempSpot, L"F*", &CurrentName, TRUE, FALSE, L";"); + } + + if (CurrentName == NULL) { + // + // We didnt find anything, so just the first one in the list... + // + CurrentName = StrnCatGrow (&CurrentName, 0, MapList, 0); + if (CurrentName == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + + TempSpot = StrStr (CurrentName, L";"); + if (TempSpot != NULL) { + *TempSpot = CHAR_NULL; + } + } else { + Alias = StrnCatGrow (&Alias, 0, MapList, 0); + if (Alias == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + TempSpot = StrStr (Alias, CurrentName); + if (TempSpot != NULL) { + TempSpot2 = StrStr (TempSpot, L";"); + if (TempSpot2 != NULL) { + TempSpot2++; // Move past ";" from CurrentName + CopyMem (TempSpot, TempSpot2, StrSize (TempSpot2)); + } else { + *TempSpot = CHAR_NULL; + } + } + + if (Alias[StrLen (Alias)-1] == L';') { + Alias[StrLen (Alias)-1] = CHAR_NULL; + } + } + } + + DevPathString = ConvertDevicePathToText (DevPath, TRUE, FALSE); + TempLen = StrLen (CurrentName); + if (!SFO) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_MAP_ENTRY), + gShellLevel2HiiHandle, + CurrentName, + Alias != NULL ? Alias : (TempLen < StrLen (MapList) ? MapList + TempLen+1 : L""), + DevPathString + ); + if (Verbose) { + // + // also print handle, media type, removable (y/n), and current directory + // + MediaType = GetDeviceMediaType (DevPath); + if (((TypeString != NULL) && (MediaType != NULL) && (StrStr (TypeString, MediaType) != NULL)) || (TypeString == NULL)) { + Removable = IsRemoveableDevice (DevPath); + TempSpot2 = ShellGetCurrentDir (CurrentName); + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_MAP_ENTRY_VERBOSE), + gShellLevel2HiiHandle, + ConvertHandleToHandleIndex (Handle), + MediaType, + Removable ? L"Yes" : L"No", + TempSpot2 + ); + } + + SHELL_FREE_NON_NULL (MediaType); + } + } else { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_MAP_SFO_MAPPINGS), + gShellLevel2HiiHandle, + CurrentName, + DevPathString, + Consist ? L"" : (TempLen < StrLen (MapList) ? MapList + TempLen+1 : L"") + ); + } + + SHELL_FREE_NON_NULL (DevPathString); + SHELL_FREE_NON_NULL (CurrentName); + SHELL_FREE_NON_NULL (Alias); + return EFI_SUCCESS; +} + +/** + Delete Specific from the list of maps for device Handle. + + @param[in] Specific The name to delete. + @param[in] Handle The device to look on. + + @retval EFI_SUCCESS The delete was successful. + @retval EFI_NOT_FOUND Name was not a map on Handle. +**/ +EFI_STATUS +PerformSingleMappingDelete ( + IN CONST CHAR16 *Specific, + IN CONST EFI_HANDLE Handle + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevPath; + EFI_DEVICE_PATH_PROTOCOL *DevPathCopy; + CONST CHAR16 *MapList; + CHAR16 *CurrentName; + + DevPath = DevicePathFromHandle (Handle); + DevPathCopy = DevPath; + MapList = gEfiShellProtocol->GetMapFromDevicePath (&DevPathCopy); + CurrentName = NULL; + + if (MapList == NULL) { + return (EFI_NOT_FOUND); + } + + // + // if there is a specific and its not on the list... + // + if (!SearchList (MapList, Specific, &CurrentName, TRUE, FALSE, L";")) { + return (EFI_NOT_FOUND); + } + + return (gEfiShellProtocol->SetMap (NULL, CurrentName)); +} + +CONST CHAR16 Cd[] = L"cd*"; +CONST CHAR16 Hd[] = L"hd*"; +CONST CHAR16 Fp[] = L"fp*"; +CONST CHAR16 AnyF[] = L"F*"; + +/** + Function to display mapping information to the user. + + If Specific is specified then Consist and Normal will be ignored since information will + be printed for the specific item only. + + @param[in] Verbose TRUE to display (extra) verbose information. + @param[in] Consist TRUE to display consistent mappings. + @param[in] Normal TRUE to display normal (not consist) mappings. + @param[in] TypeString Pointer to string of filter types. + @param[in] SFO TRUE to display output in Standard Output Format. + @param[in] Specific Pointer to string for specific map to display. + @param[in] Header TRUE to print the header block. + + @retval SHELL_SUCCESS The display was printed. + @retval SHELL_INVALID_PARAMETER One of Consist or Normal must be TRUE if no Specific. + +**/ +SHELL_STATUS +PerformMappingDisplay ( + IN CONST BOOLEAN Verbose, + IN CONST BOOLEAN Consist, + IN CONST BOOLEAN Normal, + IN CONST CHAR16 *TypeString, + IN CONST BOOLEAN SFO, + IN CONST CHAR16 *Specific OPTIONAL, + IN CONST BOOLEAN Header + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN BufferSize; + UINTN LoopVar; + CHAR16 *Test; + BOOLEAN Found; + + if (!Consist && !Normal && (Specific == NULL) && (TypeString == NULL)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"map"); + return (SHELL_INVALID_PARAMETER); + } + + if (TypeString != NULL) { + Test = (CHAR16 *)Cd; + if (StrnCmp (TypeString, Test, StrLen (Test)-1) != 0) { + Test = (CHAR16 *)Hd; + if (StrnCmp (TypeString, Test, StrLen (Test)-1) != 0) { + Test = (CHAR16 *)Fp; + if (StrnCmp (TypeString, Test, StrLen (Test)-1) != 0) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"map", TypeString); + return (SHELL_INVALID_PARAMETER); + } + } else if (Test == NULL) { + Test = (CHAR16 *)AnyF; + } + } + } else { + Test = NULL; + } + + if (Header) { + // + // Print the header + // + if (!SFO) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MAP_HEADER), gShellLevel2HiiHandle); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_SFO_HEADER), gShellLevel2HiiHandle, L"map"); + } + } + + BufferSize = 0; + HandleBuffer = NULL; + + // + // Look up all SimpleFileSystems in the platform + // + Status = gBS->LocateHandle ( + ByProtocol, + &gEfiSimpleFileSystemProtocolGuid, + NULL, + &BufferSize, + HandleBuffer + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + HandleBuffer = AllocateZeroPool (BufferSize); + if (HandleBuffer == NULL) { + return (SHELL_OUT_OF_RESOURCES); + } + + Status = gBS->LocateHandle ( + ByProtocol, + &gEfiSimpleFileSystemProtocolGuid, + NULL, + &BufferSize, + HandleBuffer + ); + } + + // + // Get the map name(s) for each one. + // + for ( LoopVar = 0, Found = FALSE + ; LoopVar < (BufferSize / sizeof (EFI_HANDLE)) && HandleBuffer != NULL + ; LoopVar++ + ) + { + Status = PerformSingleMappingDisplay ( + Verbose, + Consist, + Normal, + Test, + SFO, + Specific, + HandleBuffer[LoopVar] + ); + if (!EFI_ERROR (Status)) { + Found = TRUE; + } + } + + // + // Look up all BlockIo in the platform + // + Status = gBS->LocateHandle ( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &BufferSize, + HandleBuffer + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + SHELL_FREE_NON_NULL (HandleBuffer); + HandleBuffer = AllocateZeroPool (BufferSize); + if (HandleBuffer == NULL) { + return (SHELL_OUT_OF_RESOURCES); + } + + Status = gBS->LocateHandle ( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &BufferSize, + HandleBuffer + ); + } + + if (!EFI_ERROR (Status) && (HandleBuffer != NULL)) { + // + // Get the map name(s) for each one. + // + for ( LoopVar = 0 + ; LoopVar < BufferSize / sizeof (EFI_HANDLE) + ; LoopVar++ + ) + { + // + // Skip any that were already done... + // + if (gBS->OpenProtocol ( + HandleBuffer[LoopVar], + &gEfiSimpleFileSystemProtocolGuid, + NULL, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ) == EFI_SUCCESS) + { + continue; + } + + Status = PerformSingleMappingDisplay ( + Verbose, + Consist, + Normal, + Test, + SFO, + Specific, + HandleBuffer[LoopVar] + ); + if (!EFI_ERROR (Status)) { + Found = TRUE; + } + } + + FreePool (HandleBuffer); + } + + if (!Found) { + if (Specific != NULL) { + ShellPrintHiiEx (gST->ConOut->Mode->CursorColumn, gST->ConOut->Mode->CursorRow-1, NULL, STRING_TOKEN (STR_MAP_NF), gShellLevel2HiiHandle, L"map", Specific); + } else { + ShellPrintHiiEx (gST->ConOut->Mode->CursorColumn, gST->ConOut->Mode->CursorRow-1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"map"); + } + } + + return (SHELL_SUCCESS); +} + +/** + Perform a mapping display and parse for multiple types in the TypeString. + + @param[in] Verbose TRUE to use verbose output. + @param[in] Consist TRUE to display consistent names. + @param[in] Normal TRUE to display normal names. + @param[in] TypeString An optional comma-delimited list of types. + @param[in] SFO TRUE to display in SFO format. See Spec. + @param[in] Specific An optional specific map name to display alone. + + @retval SHELL_INVALID_PARAMETER A parameter was invalid. + @retval SHELL_SUCCESS The display was successful. + @sa PerformMappingDisplay +**/ +SHELL_STATUS +PerformMappingDisplay2 ( + IN CONST BOOLEAN Verbose, + IN CONST BOOLEAN Consist, + IN CONST BOOLEAN Normal, + IN CONST CHAR16 *TypeString, + IN CONST BOOLEAN SFO, + IN CONST CHAR16 *Specific OPTIONAL + ) +{ + CONST CHAR16 *TypeWalker; + SHELL_STATUS ShellStatus; + CHAR16 *Comma; + + if (TypeString == NULL) { + return (PerformMappingDisplay (Verbose, Consist, Normal, NULL, SFO, Specific, TRUE)); + } + + ShellStatus = SHELL_SUCCESS; + for (TypeWalker = TypeString; TypeWalker != NULL && *TypeWalker != CHAR_NULL;) { + Comma = StrStr (TypeWalker, L","); + if (Comma == NULL) { + if (ShellStatus == SHELL_SUCCESS) { + ShellStatus = PerformMappingDisplay (Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString)); + } else { + PerformMappingDisplay (Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString)); + } + + break; + } else { + *Comma = CHAR_NULL; + if (ShellStatus == SHELL_SUCCESS) { + ShellStatus = PerformMappingDisplay (Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString)); + } else { + PerformMappingDisplay (Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString)); + } + + *Comma = L','; + TypeWalker = Comma + 1; + } + } + + return (ShellStatus); +} + +/** + Delete a specific map. + + @param[in] Specific The pointer to the name of the map to delete. + + @retval EFI_INVALID_PARAMETER Specific was NULL. + @retval EFI_SUCCESS The operation was successful. + @retval EFI_NOT_FOUND Specific could not be found. +**/ +EFI_STATUS +PerformMappingDelete ( + IN CONST CHAR16 *Specific + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN BufferSize; + UINTN LoopVar; + BOOLEAN Deleted; + + if (Specific == NULL) { + return (EFI_INVALID_PARAMETER); + } + + BufferSize = 0; + HandleBuffer = NULL; + Deleted = FALSE; + + // + // Look up all SimpleFileSystems in the platform + // + Status = gBS->LocateHandle ( + ByProtocol, + &gEfiDevicePathProtocolGuid, + NULL, + &BufferSize, + HandleBuffer + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + HandleBuffer = AllocateZeroPool (BufferSize); + if (HandleBuffer == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + + Status = gBS->LocateHandle ( + ByProtocol, + &gEfiDevicePathProtocolGuid, + NULL, + &BufferSize, + HandleBuffer + ); + } + + if (EFI_ERROR (Status)) { + SHELL_FREE_NON_NULL (HandleBuffer); + return (Status); + } + + if (HandleBuffer != NULL) { + // + // Get the map name(s) for each one. + // + for ( LoopVar = 0 + ; LoopVar < BufferSize / sizeof (EFI_HANDLE) + ; LoopVar++ + ) + { + if (PerformSingleMappingDelete (Specific, HandleBuffer[LoopVar]) == SHELL_SUCCESS) { + Deleted = TRUE; + } + } + } + + // + // Look up all BlockIo in the platform + // + Status = gBS->LocateHandle ( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &BufferSize, + HandleBuffer + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + FreePool (HandleBuffer); + HandleBuffer = AllocateZeroPool (BufferSize); + if (HandleBuffer == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + + Status = gBS->LocateHandle ( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &BufferSize, + HandleBuffer + ); + } + + if (EFI_ERROR (Status)) { + SHELL_FREE_NON_NULL (HandleBuffer); + return (Status); + } + + if (HandleBuffer != NULL) { + // + // Get the map name(s) for each one. + // + for ( LoopVar = 0 + ; LoopVar < BufferSize / sizeof (EFI_HANDLE) + ; LoopVar++ + ) + { + // + // Skip any that were already done... + // + if (gBS->OpenProtocol ( + HandleBuffer[LoopVar], + &gEfiDevicePathProtocolGuid, + NULL, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ) == EFI_SUCCESS) + { + continue; + } + + if (PerformSingleMappingDelete (Specific, HandleBuffer[LoopVar]) == SHELL_SUCCESS) { + Deleted = TRUE; + } + } + } + + SHELL_FREE_NON_NULL (HandleBuffer); + if (!Deleted) { + return (EFI_NOT_FOUND); + } + + return (EFI_SUCCESS); +} + +/** + function to add a mapping from mapping. + + This function will get the device path associated with the mapping and call SetMap. + + @param[in] Map The Map to add a mapping for + @param[in] SName The name of the new mapping + + @retval SHELL_SUCCESS the mapping was added + @retval SHELL_INVALID_PARAMETER the device path for Map could not be retrieved. + @return Shell version of a return value from EfiShellProtocol->SetMap + +**/ +SHELL_STATUS +AddMappingFromMapping ( + IN CONST CHAR16 *Map, + IN CONST CHAR16 *SName + ) +{ + CONST EFI_DEVICE_PATH_PROTOCOL *DevPath; + EFI_STATUS Status; + CHAR16 *NewSName; + RETURN_STATUS StrRetStatus; + + NewSName = AllocateCopyPool (StrSize (SName) + sizeof (CHAR16), SName); + if (NewSName == NULL) { + return (SHELL_OUT_OF_RESOURCES); + } + + if (NewSName[StrLen (NewSName)-1] != L':') { + StrRetStatus = StrnCatS (NewSName, (StrSize (SName) + sizeof (CHAR16))/sizeof (CHAR16), L":", StrLen (L":")); + if (EFI_ERROR (StrRetStatus)) { + FreePool (NewSName); + return ((SHELL_STATUS)(StrRetStatus & (~MAX_BIT))); + } + } + + if (!IsNumberLetterOnly (NewSName, StrLen (NewSName)-1)) { + FreePool (NewSName); + return (SHELL_INVALID_PARAMETER); + } + + DevPath = gEfiShellProtocol->GetDevicePathFromMap (Map); + if (DevPath == NULL) { + FreePool (NewSName); + return (SHELL_INVALID_PARAMETER); + } + + Status = gEfiShellProtocol->SetMap (DevPath, NewSName); + FreePool (NewSName); + if (EFI_ERROR (Status)) { + return (SHELL_DEVICE_ERROR); + } + + return (SHELL_SUCCESS); +} + +/** + function to add a mapping from an EFI_HANDLE. + + This function will get the device path associated with the Handle and call SetMap. + + @param[in] Handle The handle to add a mapping for + @param[in] SName The name of the new mapping + + @retval SHELL_SUCCESS the mapping was added + @retval SHELL_INVALID_PARAMETER SName was not valid for a map name. + @return Shell version of a return value from either + gBS->OpenProtocol or EfiShellProtocol->SetMap + +**/ +SHELL_STATUS +AddMappingFromHandle ( + IN CONST EFI_HANDLE Handle, + IN CONST CHAR16 *SName + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevPath; + EFI_STATUS Status; + CHAR16 *NewSName; + RETURN_STATUS StrRetStatus; + + NewSName = AllocateCopyPool (StrSize (SName) + sizeof (CHAR16), SName); + if (NewSName == NULL) { + return (SHELL_OUT_OF_RESOURCES); + } + + if (NewSName[StrLen (NewSName)-1] != L':') { + StrRetStatus = StrnCatS (NewSName, (StrSize (SName) + sizeof (CHAR16))/sizeof (CHAR16), L":", StrLen (L":")); + if (EFI_ERROR (StrRetStatus)) { + FreePool (NewSName); + return ((SHELL_STATUS)(StrRetStatus & (~MAX_BIT))); + } + } + + if (!IsNumberLetterOnly (NewSName, StrLen (NewSName)-1)) { + FreePool (NewSName); + return (SHELL_INVALID_PARAMETER); + } + + Status = gBS->OpenProtocol ( + Handle, + &gEfiDevicePathProtocolGuid, + (VOID **)&DevPath, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + FreePool (NewSName); + return (SHELL_DEVICE_ERROR); + } + + Status = gEfiShellProtocol->SetMap (DevPath, NewSName); + FreePool (NewSName); + if (EFI_ERROR (Status)) { + return (SHELL_DEVICE_ERROR); + } + + return (SHELL_SUCCESS); +} + +STATIC CONST SHELL_PARAM_ITEM MapParamList[] = { + { L"-d", TypeValue }, + { L"-r", TypeFlag }, + { L"-v", TypeFlag }, + { L"-c", TypeFlag }, + { L"-f", TypeFlag }, + { L"-u", TypeFlag }, + { L"-t", TypeValue }, + { L"-sfo", TypeValue }, + { NULL, TypeMax } +}; + +/** + The routine issues dummy read for every physical block device to cause + the BlockIo re-installed if media change happened. +**/ +VOID +ProbeForMediaChange ( + VOID + ) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *Handles; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + UINTN Index; + + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &HandleCount, + &Handles + ); + // + // Probe for media change for every physical block io + // + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol ( + Handles[Index], + &gEfiBlockIoProtocolGuid, + (VOID **)&BlockIo + ); + if (!EFI_ERROR (Status)) { + if (!BlockIo->Media->LogicalPartition) { + // + // Per spec: + // The function (ReadBlocks) must return EFI_NO_MEDIA or + // EFI_MEDIA_CHANGED even if LBA, BufferSize, or Buffer are invalid so the caller can probe + // for changes in media state. + // + BlockIo->ReadBlocks ( + BlockIo, + BlockIo->Media->MediaId, + 0, + 0, + NULL + ); + } + } + } +} + +/** + Function for 'map' 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 +ShellCommandRunMap ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + CONST CHAR16 *SName; + CONST CHAR16 *Mapping; + EFI_HANDLE MapAsHandle; + SHELL_STATUS ShellStatus; + BOOLEAN SfoMode; + BOOLEAN ConstMode; + BOOLEAN NormlMode; + CONST CHAR16 *Param1; + CONST CHAR16 *TypeString; + UINTN TempStringLength; + + ProblemParam = NULL; + Mapping = NULL; + SName = NULL; + ShellStatus = SHELL_SUCCESS; + MapAsHandle = 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 (MapParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR (Status)) { + if ((Status == EFI_VOLUME_CORRUPTED) && (ProblemParam != NULL)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"map", ProblemParam); + FreePool (ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT (FALSE); + } + } else { + // + // check for "-?" + // + SfoMode = ShellCommandLineGetFlag (Package, L"-sfo"); + ConstMode = ShellCommandLineGetFlag (Package, L"-c"); + NormlMode = ShellCommandLineGetFlag (Package, L"-f"); + if (ShellCommandLineGetFlag (Package, L"-?")) { + ASSERT (FALSE); + } else if (ShellCommandLineGetRawValue (Package, 3) != NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"map"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // Deleting a map name... + // + if (ShellCommandLineGetFlag (Package, L"-d")) { + if ( ShellCommandLineGetFlag (Package, L"-r") + || ShellCommandLineGetFlag (Package, L"-v") + || ConstMode + || NormlMode + || ShellCommandLineGetFlag (Package, L"-u") + || ShellCommandLineGetFlag (Package, L"-t") + ) + { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellLevel2HiiHandle, L"map"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + SName = ShellCommandLineGetValue (Package, L"-d"); + if (SName != NULL) { + Status = PerformMappingDelete (SName); + if (EFI_ERROR (Status)) { + if (Status == EFI_ACCESS_DENIED) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel2HiiHandle, L"map"); + ShellStatus = SHELL_ACCESS_DENIED; + } else if (Status == EFI_NOT_FOUND) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MAP_NF), gShellLevel2HiiHandle, L"map", SName); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, L"map", Status); + ShellStatus = SHELL_UNSUPPORTED; + } + } + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"map"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + } else if ( ShellCommandLineGetFlag (Package, L"-r") + // || ShellCommandLineGetFlag(Package, L"-v") + || ConstMode + || NormlMode + || ShellCommandLineGetFlag (Package, L"-u") + || ShellCommandLineGetFlag (Package, L"-t") + ) + { + ProbeForMediaChange (); + if ( ShellCommandLineGetFlag (Package, L"-r")) { + // + // Do the reset + // + Status = ShellCommandCreateInitialMappingsAndPaths (); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, L"map", Status); + ShellStatus = SHELL_UNSUPPORTED; + } + } + + if ((ShellStatus == SHELL_SUCCESS) && ShellCommandLineGetFlag (Package, L"-u")) { + // + // Do the Update + // + Status = ShellCommandUpdateMapping (); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, L"map", Status); + ShellStatus = SHELL_UNSUPPORTED; + } + } + + if (ShellStatus == SHELL_SUCCESS) { + Param1 = ShellCommandLineGetRawValue (Package, 1); + TypeString = ShellCommandLineGetValue (Package, L"-t"); + if ( !ConstMode + && !NormlMode + && (TypeString == NULL) + ) + { + // + // now do the display... + // + ShellStatus = PerformMappingDisplay ( + ShellCommandLineGetFlag (Package, L"-v"), + TRUE, + TRUE, + NULL, + SfoMode, + Param1, + TRUE + ); + } else { + // + // now do the display... + // + ShellStatus = PerformMappingDisplay2 ( + ShellCommandLineGetFlag (Package, L"-v"), + ConstMode, + NormlMode, + TypeString, + SfoMode, + Param1 + ); + } + } + } else { + // + // adding or displaying (there were no flags) + // + SName = ShellCommandLineGetRawValue (Package, 1); + Mapping = ShellCommandLineGetRawValue (Package, 2); + if ( (SName == NULL) + && (Mapping == NULL) + ) + { + // + // display only since no flags + // + ShellStatus = PerformMappingDisplay ( + ShellCommandLineGetFlag (Package, L"-v"), + TRUE, + TRUE, + NULL, + SfoMode, + NULL, + TRUE + ); + } else if ( (SName == NULL) + || (Mapping == NULL) + ) + { + // + // Display only the one specified + // + ShellStatus = PerformMappingDisplay ( + FALSE, + FALSE, + FALSE, + NULL, + SfoMode, + SName, // note the variable here... + TRUE + ); + } else { + if (ShellIsHexOrDecimalNumber (Mapping, TRUE, FALSE)) { + MapAsHandle = ConvertHandleIndexToHandle (ShellStrToUintn (Mapping)); + } else { + MapAsHandle = NULL; + } + + if ((MapAsHandle == NULL) && (Mapping[StrLen (Mapping)-1] != L':')) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"map", Mapping); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + TempStringLength = StrLen (SName); + if (!IsNumberLetterOnly (SName, TempStringLength-((SName[TempStringLength-1] == L':') ? 1 : 0))) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"map", SName); + ShellStatus = SHELL_INVALID_PARAMETER; + } + + if (ShellStatus == SHELL_SUCCESS) { + if (MapAsHandle != NULL) { + ShellStatus = AddMappingFromHandle (MapAsHandle, SName); + } else { + ShellStatus = AddMappingFromMapping (Mapping, SName); + } + + if (ShellStatus != SHELL_SUCCESS) { + switch (ShellStatus) { + case SHELL_ACCESS_DENIED: + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel2HiiHandle, L"map"); + break; + case SHELL_INVALID_PARAMETER: + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"map", Mapping); + break; + case SHELL_DEVICE_ERROR: + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MAP_NOF), gShellLevel2HiiHandle, L"map", Mapping); + break; + default: + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, L"map", ShellStatus|MAX_BIT); + } + } else { + // + // now do the display... + // + ShellStatus = PerformMappingDisplay ( + FALSE, + FALSE, + FALSE, + NULL, + SfoMode, + SName, + TRUE + ); + } // we were successful so do an output + } + } // got a valid map target + } // got 2 variables + } // we are adding a mapping + } // got valid parameters + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + return (ShellStatus); +} |
