From a405b86d274d32b92f69842bfb9a1ab143128f57 Mon Sep 17 00:00:00 2001 From: jcarsey Date: Tue, 14 Sep 2010 05:18:09 +0000 Subject: udk2010.up2.shell initial release. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10874 6f19259b-4bc3-4df7-8a09-765794883524 --- ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c | 1116 +++++++++++++++++++++ 1 file changed, 1116 insertions(+) create mode 100644 ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c (limited to 'ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c') diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c new file mode 100644 index 0000000000..5d6a200c19 --- /dev/null +++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c @@ -0,0 +1,1116 @@ +/** @file + Main file for map shell level 2 command. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" +#include +#include +#include +#include +#include + +BOOLEAN +EFIAPI +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); +} + +EFI_STATUS +EFIAPI +UpdateMapping ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleList; + UINTN Count; + EFI_DEVICE_PATH_PROTOCOL **DevicePathList; + CHAR16 *NewDefaultName; + CHAR16 *NewConsistName; + EFI_DEVICE_PATH_PROTOCOL **ConsistMappingTable; + + HandleList = NULL; + Status = EFI_SUCCESS; + + // + // remove mappings that represent removed devices. + // + + // + // Find each handle with Simple File System + // + HandleList = GetHandleListByPotocol(&gEfiSimpleFileSystemProtocolGuid); + if (HandleList != NULL) { + // + // Do a count of the handles + // + for (Count = 0 ; HandleList[Count] != NULL ; Count++); + + // + // Get all Device Paths + // + DevicePathList = AllocatePool(sizeof(EFI_DEVICE_PATH_PROTOCOL*) * Count); + ASSERT(DevicePathList != NULL); + + for (Count = 0 ; HandleList[Count] != NULL ; Count++) { + DevicePathList[Count] = DevicePathFromHandle(HandleList[Count]); + } + + // + // Sort all DevicePaths + // + PerformQuickSort(DevicePathList, Count, sizeof(EFI_DEVICE_PATH_PROTOCOL*), DevicePathCompare); + + ShellCommandConsistMappingInitialize(&ConsistMappingTable); + + // + // Assign new Mappings to remainders + // + for (Count = 0 ; HandleList[Count] != NULL && !EFI_ERROR(Status); Count++) { + // + // Skip ones that already have + // + if (gEfiShellProtocol->GetMapFromDevicePath(&DevicePathList[Count]) != NULL) { + continue; + } + // + // Get default name + // + NewDefaultName = ShellCommandCreateNewMappingName(MappingTypeFileSystem); + ASSERT(NewDefaultName != NULL); + + // + // Call shell protocol SetMap function now... + // + Status = gEfiShellProtocol->SetMap(DevicePathList[Count], NewDefaultName); + + if (!EFI_ERROR(Status)) { + // + // Now do consistent name + // + NewConsistName = ShellCommandConsistMappingGenMappingName(DevicePathList[Count], ConsistMappingTable); + if (NewConsistName != NULL) { + Status = gEfiShellProtocol->SetMap(DevicePathList[Count], NewConsistName); + FreePool(NewConsistName); + } + } + + FreePool(NewDefaultName); + } + ShellCommandConsistMappingUnInitialize(ConsistMappingTable); + SHELL_FREE_NON_NULL(HandleList); + SHELL_FREE_NON_NULL(DevicePathList); + + HandleList = NULL; + } else { + Count = (UINTN)-1; + } + // + // Do it all over again for gEfiBlockIoProtocolGuid + // + + return (Status); +} + +CHAR16* +EFIAPI +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 +EFIAPI +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 +EFIAPI +MappingListHasType( + IN CONST CHAR16 *MapList, + IN CONST CHAR16 *Specific, + IN CONST CHAR16 *TypeString, + IN CONST BOOLEAN Normal, + IN CONST BOOLEAN Consist + ) +{ + // + // specific has priority + // + if ( Specific != NULL + && SearchList(MapList, Specific, NULL, TRUE, FALSE, L";")) { + return (TRUE); + } + + if ( Consist + && (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 + && (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); +} + + +VOID +EFIAPI +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; + UINTN TempLen; + BOOLEAN Removable; + CONST CHAR16 *TempSpot2; + + DevPath = DevicePathFromHandle(Handle); + DevPathCopy = DevPath; + MapList = gEfiShellProtocol->GetMapFromDevicePath(&DevPathCopy); + if (MapList == NULL) { + return; + } + + if (!MappingListHasType(MapList, Specific, TypeString, Normal, Consist)){ + return; + } + + CurrentName = NULL; + CurrentName = StrnCatGrow(&CurrentName, 0, MapList, 0); + TempSpot = StrStr(CurrentName, L";"); + if (TempSpot != NULL) { + *TempSpot = CHAR_NULL; + } + DevPathString = gDevPathToText->ConvertDevicePathToText(DevPath, TRUE, FALSE); + if (!SFO) { + TempLen = StrLen(CurrentName); + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_MAP_ENTRY), + gShellLevel2HiiHandle, + CurrentName, + 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 + ); + } + FreePool(MediaType); + } + } else { + TempLen = StrLen(CurrentName); + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_MAP_SFO_MAPPINGS), + gShellLevel2HiiHandle, + CurrentName, + DevPathString, + TempLen < StrLen(MapList)?MapList + TempLen+1:L"" + ); + } + FreePool(DevPathString); + FreePool(CurrentName); + return; +} + +EFI_STATUS +EFIAPI +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)); +} + +/** + 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 + + @retval SHELL_SUCCESS the display was printed + @retval SHELL_INVALID_PARAMETER one of Consist or Normal must be TRUE if no Specific + +**/ +CONST CHAR16 Cd[] = L"cd*"; +CONST CHAR16 Hd[] = L"hd*"; +CONST CHAR16 Fp[] = L"fp*"; +CONST CHAR16 F[] = L"F*"; +SHELL_STATUS +EFIAPI +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; + + if (!Consist && !Normal && Specific == NULL && TypeString == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle); + 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_PROBLEM), gShellLevel2HiiHandle, TypeString); + return (SHELL_INVALID_PARAMETER); + } + } else if (Test == NULL) { + Test = (CHAR16*)F; + } + } + } 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, + &gEfiDevicePathProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + HandleBuffer = AllocatePool(BufferSize); + Status = gBS->LocateHandle( + ByProtocol, + &gEfiDevicePathProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + } + ASSERT_EFI_ERROR(Status); + ASSERT(HandleBuffer != NULL); + + // + // Get the map name(s) for each one. + // + for ( LoopVar = 0 + ; LoopVar < (BufferSize / sizeof(EFI_HANDLE)) + ; LoopVar ++ + ){ + PerformSingleMappingDisplay( + Verbose, + Consist, + Normal, + Test, + SFO, + Specific, + HandleBuffer[LoopVar]); + } + + // + // Look up all BlockIo in the platform + // + Status = gBS->LocateHandle( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + FreePool(HandleBuffer); + HandleBuffer = AllocatePool(BufferSize); + Status = gBS->LocateHandle( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + } + ASSERT_EFI_ERROR(Status); + + // + // 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; + } + PerformSingleMappingDisplay( + Verbose, + Consist, + Normal, + Test, + SFO, + Specific, + HandleBuffer[LoopVar]); + } + FreePool(HandleBuffer); + return (SHELL_SUCCESS); +} + +SHELL_STATUS +EFIAPI +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); +} + +EFI_STATUS +EFIAPI +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 = AllocatePool(BufferSize); + Status = gBS->LocateHandle( + ByProtocol, + &gEfiDevicePathProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + } + ASSERT_EFI_ERROR(Status); + ASSERT(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 = AllocatePool(BufferSize); + Status = gBS->LocateHandle( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + } + ASSERT_EFI_ERROR(Status); + + // + // 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; + } + } + FreePool(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 +EFIAPI +AddMappingFromMapping( + IN CONST CHAR16 *Map, + IN CONST CHAR16 *SName + ) +{ + CONST EFI_DEVICE_PATH_PROTOCOL *DevPath; + EFI_STATUS Status; + + if (StrStr(SName, L"*") != NULL + ||StrStr(SName, L"?") != NULL + ||StrStr(SName, L"[") != NULL + ||StrStr(SName, L"]") != NULL) { + return (SHELL_INVALID_PARAMETER); + } + + DevPath = gEfiShellProtocol->GetDevicePathFromMap(Map); + if (DevPath == NULL) { + return (SHELL_INVALID_PARAMETER); + } + + Status = gEfiShellProtocol->SetMap(DevPath, SName); + if (EFI_ERROR(Status)) { + return (SHELL_DEVICE_ERROR); + } + return (SHELL_SUCCESS); +} + +/** + function to 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 + + @retval TRUE String has only numbers and letters + @retval FALSE String has at least one other character. +**/ +BOOLEAN +EFIAPI +IsNumberLetterOnly( + IN CONST CHAR16 *String + ) +{ + while(String != NULL && *String != CHAR_NULL) { + if (! ( *String >= L'a' && *String <= L'z' + || *String >= L'A' && *String <= L'Z' + || *String >= L'0' && *String <= L'9') + ){ + return (FALSE); + } + String++; + } + return (TRUE); +} + +/** + 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 +EFIAPI +AddMappingFromHandle( + IN CONST EFI_HANDLE Handle, + IN CONST CHAR16 *SName + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevPath; + EFI_STATUS Status; + + if (!IsNumberLetterOnly(SName)) { + return (SHELL_INVALID_PARAMETER); + } + + Status = gBS->OpenProtocol( + Handle, + &gEfiDevicePathProtocolGuid, + (VOID**)&DevPath, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR(Status)) { + return (SHELL_DEVICE_ERROR); + } + Status = gEfiShellProtocol->SetMap(DevPath, SName); + 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} + }; + +/** + 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 MappingAsHandle; + CONST EFI_DEVICE_PATH_PROTOCOL *DevPath; + SHELL_STATUS ShellStatus; + BOOLEAN SfoMode; + BOOLEAN ConstMode; + BOOLEAN NormlMode; + CONST CHAR16 *Param1; + CONST CHAR16 *TypeString; + + ProblemParam = NULL; + Mapping = NULL; + SName = NULL; + DevPath = NULL; + ShellStatus = SHELL_SUCCESS; + MappingAsHandle = 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, 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); + 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); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + SName = ShellCommandLineGetValue(Package, L"-d"); + if (SName != NULL) { + Status = PerformMappingDelete(SName); + if (EFI_ERROR(Status)) { + switch (Status) { + case EFI_ACCESS_DENIED: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel2HiiHandle); + ShellStatus = SHELL_ACCESS_DENIED; + break; + case EFI_NOT_FOUND: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MAP_NF), gShellLevel2HiiHandle, SName); + ShellStatus = SHELL_INVALID_PARAMETER; + break; + default: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, Status); + ShellStatus = SHELL_UNSUPPORTED; + } + } + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + } else if ( ShellCommandLineGetFlag(Package, L"-r") +// || ShellCommandLineGetFlag(Package, L"-v") + || ConstMode + || NormlMode + || ShellCommandLineGetFlag(Package, L"-u") + || ShellCommandLineGetFlag(Package, L"-t") + ){ + 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, Status); + ShellStatus = SHELL_UNSUPPORTED; + } + } + if ( ShellStatus == SHELL_SUCCESS && ShellCommandLineGetFlag(Package, L"-u")) { + // + // Do the Update + // + Status = UpdateMapping(); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, 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)) { + MappingAsHandle = ConvertHandleIndexToHandle(StrHexToUintn(Mapping)); + } else { + MappingAsHandle = NULL; + } + if (MappingAsHandle == NULL && Mapping[StrLen(Mapping)-1] != L':') { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, Mapping); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + if (MappingAsHandle != NULL) { + ShellStatus = AddMappingFromHandle(MappingAsHandle, 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); + break; + case SHELL_INVALID_PARAMETER: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle); + break; + default: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, ShellStatus|MAX_BIT); + } + } else { + // + // now do the display... + // + ShellStatus = PerformMappingDisplay( + FALSE, + FALSE, + FALSE, + NULL, + SfoMode, + SName, + TRUE + ); + } // we were sucessful 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); +} + -- cgit v1.2.3