summaryrefslogtreecommitdiffstats
path: root/ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c
diff options
context:
space:
mode:
authorjcarsey <jcarsey@6f19259b-4bc3-4df7-8a09-765794883524>2010-09-14 05:18:09 +0000
committerjcarsey <jcarsey@6f19259b-4bc3-4df7-8a09-765794883524>2010-09-14 05:18:09 +0000
commita405b86d274d32b92f69842bfb9a1ab143128f57 (patch)
treeb6fb97d9a65152d2b6527d6cd226a5b48c675dd8 /ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c
parent52fb4d3d133883c6e0e8b8ee8a7af590a920f5eb (diff)
downloadedk2-a405b86d274d32b92f69842bfb9a1ab143128f57.tar.gz
edk2-a405b86d274d32b92f69842bfb9a1ab143128f57.tar.bz2
edk2-a405b86d274d32b92f69842bfb9a1ab143128f57.zip
udk2010.up2.shell initial release.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10874 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c')
-rw-r--r--ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c1116
1 files changed, 1116 insertions, 0 deletions
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.<BR>
+ 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 <Protocol/SimpleFileSystem.h>
+#include <Protocol/BlockIo.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HandleParsingLib.h>
+#include <Library/SortLib.h>
+
+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);
+}
+