| /** @file | |
| Main file for support of shell consist mapping. | |
| Copyright (c) 2005 - 2016, 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 "UefiShellCommandLib.h" | |
| #include <Library/DevicePathLib.h> | |
| #include <Library/SortLib.h> | |
| #include <Library/UefiLib.h> | |
| #include <Protocol/UsbIo.h> | |
| #include <Protocol/BlockIo.h> | |
| #include <Protocol/SimpleFileSystem.h> | |
| typedef enum { | |
| MTDTypeUnknown, | |
| MTDTypeFloppy, | |
| MTDTypeHardDisk, | |
| MTDTypeCDRom, | |
| MTDTypeEnd | |
| } MTD_TYPE; | |
| typedef struct { | |
| CHAR16 *Str; | |
| UINTN Len; | |
| } POOL_PRINT; | |
| typedef struct { | |
| UINTN Hi; | |
| MTD_TYPE Mtd; | |
| POOL_PRINT Csd; | |
| BOOLEAN Digital; | |
| } DEVICE_CONSIST_MAPPING_INFO; | |
| typedef struct { | |
| MTD_TYPE MTDType; | |
| CHAR16 *Name; | |
| } MTD_NAME; | |
| /** | |
| Serial Decode function. | |
| @param DevPath The Device path info. | |
| @param MapInfo The map info. | |
| @param OrigDevPath The original device path protocol. | |
| @retval EFI_OUT_OF_RESOURCES Out of resources. | |
| @retval EFI_SUCCESS The appending was successful. | |
| **/ | |
| typedef | |
| EFI_STATUS | |
| (*SERIAL_DECODE_FUNCTION) ( | |
| EFI_DEVICE_PATH_PROTOCOL *DevPath, | |
| DEVICE_CONSIST_MAPPING_INFO *MapInfo, | |
| EFI_DEVICE_PATH_PROTOCOL *OrigDevPath | |
| ); | |
| typedef struct { | |
| UINT8 Type; | |
| UINT8 SubType; | |
| SERIAL_DECODE_FUNCTION SerialFun; | |
| INTN (EFIAPI *CompareFun) (EFI_DEVICE_PATH_PROTOCOL *DevPath, EFI_DEVICE_PATH_PROTOCOL *DevPath2); | |
| } DEV_PATH_CONSIST_MAPPING_TABLE; | |
| /** | |
| Concatenates a formatted unicode string to allocated pool. | |
| The caller must free the resulting buffer. | |
| @param Str Tracks the allocated pool, size in use, and amount of pool allocated. | |
| @param Fmt The format string | |
| @param ... The data will be printed. | |
| @retval EFI_SUCCESS The string is concatenated successfully. | |
| @retval EFI_OUT_OF_RESOURCES Out of resources. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| CatPrint ( | |
| IN OUT POOL_PRINT *Str, | |
| IN CHAR16 *Fmt, | |
| ... | |
| ) | |
| { | |
| UINT16 *AppendStr; | |
| VA_LIST Args; | |
| UINTN StringSize; | |
| CHAR16 *NewStr; | |
| AppendStr = AllocateZeroPool (0x1000); | |
| if (AppendStr == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| VA_START (Args, Fmt); | |
| UnicodeVSPrint (AppendStr, 0x1000, Fmt, Args); | |
| VA_END (Args); | |
| if (NULL == Str->Str) { | |
| StringSize = StrSize (AppendStr); | |
| NewStr = AllocateZeroPool (StringSize); | |
| } else { | |
| StringSize = StrSize (AppendStr); | |
| StringSize += (StrSize (Str->Str) - sizeof (UINT16)); | |
| NewStr = ReallocatePool ( | |
| StrSize (Str->Str), | |
| StringSize, | |
| Str->Str | |
| ); | |
| } | |
| if (NewStr == NULL) { | |
| FreePool (AppendStr); | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| Str->Str = NewStr; | |
| StrCatS (Str->Str, StringSize/sizeof(CHAR16), AppendStr); | |
| Str->Len = StringSize; | |
| FreePool (AppendStr); | |
| return EFI_SUCCESS; | |
| } | |
| MTD_NAME mMTDName[] = { | |
| { | |
| MTDTypeUnknown, | |
| L"F" | |
| }, | |
| { | |
| MTDTypeFloppy, | |
| L"FP" | |
| }, | |
| { | |
| MTDTypeHardDisk, | |
| L"HD" | |
| }, | |
| { | |
| MTDTypeCDRom, | |
| L"CD" | |
| }, | |
| { | |
| MTDTypeEnd, | |
| NULL | |
| } | |
| }; | |
| /** | |
| Function to append a 64 bit number / 25 onto the string. | |
| @param[in, out] Str The string so append onto. | |
| @param[in] Num The number to divide and append. | |
| @retval EFI_OUT_OF_RESOURCES Out of resources. | |
| @retval EFI_SUCCESS The appending was successful. | |
| **/ | |
| EFI_STATUS | |
| AppendCSDNum2 ( | |
| IN OUT POOL_PRINT *Str, | |
| IN UINT64 Num | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| UINT64 Result; | |
| UINT32 Rem; | |
| ASSERT (Str != NULL); | |
| Result = DivU64x32Remainder (Num, 25, &Rem); | |
| if (Result > 0) { | |
| Status = AppendCSDNum2 (Str, Result); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| } | |
| return CatPrint (Str, L"%c", Rem + 'a'); | |
| } | |
| /** | |
| Function to append a 64 bit number onto the mapping info. | |
| @param[in, out] MappingItem The mapping info object to append onto. | |
| @param[in] Num The info to append. | |
| @retval EFI_OUT_OF_RESOURCES Out of resources. | |
| @retval EFI_SUCCESS The appending was successful. | |
| **/ | |
| EFI_STATUS | |
| AppendCSDNum ( | |
| IN OUT DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
| IN UINT64 Num | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| ASSERT (MappingItem != NULL); | |
| if (MappingItem->Digital) { | |
| Status = CatPrint (&MappingItem->Csd, L"%ld", Num); | |
| } else { | |
| Status = AppendCSDNum2 (&MappingItem->Csd, Num); | |
| } | |
| if (!EFI_ERROR (Status)) { | |
| MappingItem->Digital = (BOOLEAN) !(MappingItem->Digital); | |
| } | |
| return Status; | |
| } | |
| /** | |
| Function to append string into the mapping info. | |
| @param[in, out] MappingItem The mapping info object to append onto. | |
| @param[in] Str The info to append. | |
| @retval EFI_OUT_OF_RESOURCES Out of resources. | |
| @retval EFI_SUCCESS The appending was successful. | |
| **/ | |
| EFI_STATUS | |
| AppendCSDStr ( | |
| IN OUT DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
| IN CHAR16 *Str | |
| ) | |
| { | |
| CHAR16 *Index; | |
| EFI_STATUS Status; | |
| ASSERT (Str != NULL && MappingItem != NULL); | |
| Status = EFI_SUCCESS; | |
| if (MappingItem->Digital) { | |
| // | |
| // To aVOID mult-meaning, the mapping is: | |
| // 0 1 2 3 4 5 6 7 8 9 a b c d e f | |
| // 0 16 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
| // | |
| for (Index = Str; *Index != 0; Index++) { | |
| switch (*Index) { | |
| case '0': | |
| case '2': | |
| case '3': | |
| case '4': | |
| case '5': | |
| case '6': | |
| case '7': | |
| case '8': | |
| case '9': | |
| Status = CatPrint (&MappingItem->Csd, L"%c", *Index); | |
| break; | |
| case '1': | |
| Status = CatPrint (&MappingItem->Csd, L"16"); | |
| break; | |
| case 'a': | |
| case 'b': | |
| case 'c': | |
| case 'd': | |
| case 'e': | |
| case 'f': | |
| Status = CatPrint (&MappingItem->Csd, L"1%c", *Index - 'a' + '0'); | |
| break; | |
| case 'A': | |
| case 'B': | |
| case 'C': | |
| case 'D': | |
| case 'E': | |
| case 'F': | |
| Status = CatPrint (&MappingItem->Csd, L"1%c", *Index - 'A' + '0'); | |
| break; | |
| } | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| } | |
| } else { | |
| for (Index = Str; *Index != 0; Index++) { | |
| // | |
| // The mapping is: | |
| // 0 1 2 3 4 5 6 7 8 9 a b c d e f | |
| // a b c d e f g h i j k l m n o p | |
| // | |
| if (*Index >= '0' && *Index <= '9') { | |
| Status = CatPrint (&MappingItem->Csd, L"%c", *Index - '0' + 'a'); | |
| } else if (*Index >= 'a' && *Index <= 'f') { | |
| Status = CatPrint (&MappingItem->Csd, L"%c", *Index - 'a' + 'k'); | |
| } else if (*Index >= 'A' && *Index <= 'F') { | |
| Status = CatPrint (&MappingItem->Csd, L"%c", *Index - 'A' + 'k'); | |
| } | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| } | |
| } | |
| MappingItem->Digital = (BOOLEAN)!(MappingItem->Digital); | |
| return (EFI_SUCCESS); | |
| } | |
| /** | |
| Function to append a Guid to the mapping item. | |
| @param[in, out] MappingItem The item to append onto. | |
| @param[in] Guid The guid to append. | |
| @retval EFI_OUT_OF_RESOURCES Out of resources. | |
| @retval EFI_SUCCESS The appending was successful. | |
| **/ | |
| EFI_STATUS | |
| AppendCSDGuid ( | |
| DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
| EFI_GUID *Guid | |
| ) | |
| { | |
| CHAR16 Buffer[64]; | |
| ASSERT (Guid != NULL && MappingItem != NULL); | |
| UnicodeSPrint ( | |
| Buffer, | |
| 0, | |
| L"%g", | |
| Guid | |
| ); | |
| return AppendCSDStr (MappingItem, Buffer); | |
| } | |
| /** | |
| Function to compare 2 APCI device paths. | |
| @param[in] DevicePath1 The first device path to compare. | |
| @param[in] DevicePath2 The second device path to compare. | |
| @retval 0 The device paths represent the same device. | |
| @return Non zero if the devices are different, zero otherwise. | |
| **/ | |
| INTN | |
| EFIAPI | |
| DevPathCompareAcpi ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1, | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2 | |
| ) | |
| { | |
| ACPI_HID_DEVICE_PATH *Acpi1; | |
| ACPI_HID_DEVICE_PATH *Acpi2; | |
| if (DevicePath1 == NULL || DevicePath2 == NULL) { | |
| return (-2); | |
| } | |
| Acpi1 = (ACPI_HID_DEVICE_PATH *) DevicePath1; | |
| Acpi2 = (ACPI_HID_DEVICE_PATH *) DevicePath2; | |
| if (Acpi1->HID > Acpi2->HID || (Acpi1->HID == Acpi2->HID && Acpi1->UID > Acpi2->UID)) { | |
| return 1; | |
| } | |
| if (Acpi1->HID == Acpi2->HID && Acpi1->UID == Acpi2->UID) { | |
| return 0; | |
| } | |
| return -1; | |
| } | |
| /** | |
| Function to compare 2 PCI device paths. | |
| @param[in] DevicePath1 The first device path to compare. | |
| @param[in] DevicePath2 The second device path to compare. | |
| @retval 0 The device paths represent the same device. | |
| @return Non zero if the devices are different, zero otherwise. | |
| **/ | |
| INTN | |
| EFIAPI | |
| DevPathComparePci ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1, | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2 | |
| ) | |
| { | |
| PCI_DEVICE_PATH *Pci1; | |
| PCI_DEVICE_PATH *Pci2; | |
| ASSERT(DevicePath1 != NULL); | |
| ASSERT(DevicePath2 != NULL); | |
| Pci1 = (PCI_DEVICE_PATH *) DevicePath1; | |
| Pci2 = (PCI_DEVICE_PATH *) DevicePath2; | |
| if (Pci1->Device > Pci2->Device || (Pci1->Device == Pci2->Device && Pci1->Function > Pci2->Function)) { | |
| return 1; | |
| } | |
| if (Pci1->Device == Pci2->Device && Pci1->Function == Pci2->Function) { | |
| return 0; | |
| } | |
| return -1; | |
| } | |
| /** | |
| Do a comparison on 2 device paths. | |
| @param[in] DevicePath1 The first device path. | |
| @param[in] DevicePath2 The second device path. | |
| @retval 0 The 2 device paths are the same. | |
| @retval <0 DevicePath2 is greater than DevicePath1. | |
| @retval >0 DevicePath1 is greater than DevicePath2. | |
| **/ | |
| INTN | |
| EFIAPI | |
| DevPathCompareDefault ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1, | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2 | |
| ) | |
| { | |
| UINTN DevPathSize1; | |
| UINTN DevPathSize2; | |
| ASSERT(DevicePath1 != NULL); | |
| ASSERT(DevicePath2 != NULL); | |
| DevPathSize1 = DevicePathNodeLength (DevicePath1); | |
| DevPathSize2 = DevicePathNodeLength (DevicePath2); | |
| if (DevPathSize1 > DevPathSize2) { | |
| return 1; | |
| } else if (DevPathSize1 < DevPathSize2) { | |
| return -1; | |
| } else { | |
| return CompareMem (DevicePath1, DevicePath2, DevPathSize1); | |
| } | |
| } | |
| /** | |
| DevicePathNode must be SerialHDD Channel type and this will populate the MappingItem. | |
| @param[in] DevicePathNode The node to get info on. | |
| @param[in] MappingItem The info item to populate. | |
| @param[in] DevicePath Ignored. | |
| @retval EFI_OUT_OF_RESOURCES Out of resources. | |
| @retval EFI_SUCCESS The appending was successful. | |
| **/ | |
| EFI_STATUS | |
| DevPathSerialHardDrive ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
| IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
| ) | |
| { | |
| HARDDRIVE_DEVICE_PATH *Hd; | |
| ASSERT(DevicePathNode != NULL); | |
| ASSERT(MappingItem != NULL); | |
| Hd = (HARDDRIVE_DEVICE_PATH *) DevicePathNode; | |
| if (MappingItem->Mtd == MTDTypeUnknown) { | |
| MappingItem->Mtd = MTDTypeHardDisk; | |
| } | |
| return AppendCSDNum (MappingItem, Hd->PartitionNumber); | |
| } | |
| /** | |
| DevicePathNode must be SerialAtapi Channel type and this will populate the MappingItem. | |
| @param[in] DevicePathNode The node to get info on. | |
| @param[in] MappingItem The info item to populate. | |
| @param[in] DevicePath Ignored. | |
| @retval EFI_OUT_OF_RESOURCES Out of resources. | |
| @retval EFI_SUCCESS The appending was successful. | |
| **/ | |
| EFI_STATUS | |
| DevPathSerialAtapi ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
| IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
| ) | |
| { | |
| ATAPI_DEVICE_PATH *Atapi; | |
| ASSERT(DevicePathNode != NULL); | |
| ASSERT(MappingItem != NULL); | |
| Atapi = (ATAPI_DEVICE_PATH *) DevicePathNode; | |
| return AppendCSDNum (MappingItem, (Atapi->PrimarySecondary * 2 + Atapi->SlaveMaster)); | |
| } | |
| /** | |
| DevicePathNode must be SerialCDROM Channel type and this will populate the MappingItem. | |
| @param[in] DevicePathNode The node to get info on. | |
| @param[in] MappingItem The info item to populate. | |
| @param[in] DevicePath Ignored. | |
| @retval EFI_OUT_OF_RESOURCES Out of resources. | |
| @retval EFI_SUCCESS The appending was successful. | |
| **/ | |
| EFI_STATUS | |
| DevPathSerialCdRom ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
| IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
| ) | |
| { | |
| CDROM_DEVICE_PATH *Cd; | |
| ASSERT(DevicePathNode != NULL); | |
| ASSERT(MappingItem != NULL); | |
| Cd = (CDROM_DEVICE_PATH *) DevicePathNode; | |
| MappingItem->Mtd = MTDTypeCDRom; | |
| return AppendCSDNum (MappingItem, Cd->BootEntry); | |
| } | |
| /** | |
| DevicePathNode must be SerialFibre Channel type and this will populate the MappingItem. | |
| @param[in] DevicePathNode The node to get info on. | |
| @param[in] MappingItem The info item to populate. | |
| @param[in] DevicePath Ignored. | |
| @retval EFI_OUT_OF_RESOURCES Out of resources. | |
| @retval EFI_SUCCESS The appending was successful. | |
| **/ | |
| EFI_STATUS | |
| DevPathSerialFibre ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
| IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| FIBRECHANNEL_DEVICE_PATH *Fibre; | |
| ASSERT(DevicePathNode != NULL); | |
| ASSERT(MappingItem != NULL); | |
| Fibre = (FIBRECHANNEL_DEVICE_PATH *) DevicePathNode; | |
| Status = AppendCSDNum (MappingItem, Fibre->WWN); | |
| if (!EFI_ERROR (Status)) { | |
| Status = AppendCSDNum (MappingItem, Fibre->Lun); | |
| } | |
| return Status; | |
| } | |
| /** | |
| DevicePathNode must be SerialUart type and this will populate the MappingItem. | |
| @param[in] DevicePathNode The node to get info on. | |
| @param[in] MappingItem The info item to populate. | |
| @param[in] DevicePath Ignored. | |
| @retval EFI_OUT_OF_RESOURCES Out of resources. | |
| @retval EFI_SUCCESS The appending was successful. | |
| **/ | |
| EFI_STATUS | |
| DevPathSerialUart ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
| IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| UART_DEVICE_PATH *Uart; | |
| ASSERT(DevicePathNode != NULL); | |
| ASSERT(MappingItem != NULL); | |
| Uart = (UART_DEVICE_PATH *) DevicePathNode; | |
| Status = AppendCSDNum (MappingItem, Uart->BaudRate); | |
| if (!EFI_ERROR (Status)) { | |
| Status = AppendCSDNum (MappingItem, Uart->DataBits); | |
| } | |
| if (!EFI_ERROR (Status)) { | |
| Status = AppendCSDNum (MappingItem, Uart->Parity); | |
| } | |
| if (!EFI_ERROR (Status)) { | |
| Status = AppendCSDNum (MappingItem, Uart->StopBits); | |
| } | |
| return Status; | |
| } | |
| /** | |
| DevicePathNode must be SerialUSB type and this will populate the MappingItem. | |
| @param[in] DevicePathNode The node to get info on. | |
| @param[in] MappingItem The info item to populate. | |
| @param[in] DevicePath Ignored. | |
| @retval EFI_OUT_OF_RESOURCES Out of resources. | |
| @retval EFI_SUCCESS The appending was successful. | |
| **/ | |
| EFI_STATUS | |
| DevPathSerialUsb ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
| IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
| ) | |
| { | |
| USB_DEVICE_PATH *Usb; | |
| EFI_USB_IO_PROTOCOL *UsbIo; | |
| EFI_HANDLE TempHandle; | |
| EFI_STATUS Status; | |
| USB_INTERFACE_DESCRIPTOR InterfaceDesc; | |
| ASSERT(DevicePathNode != NULL); | |
| ASSERT(MappingItem != NULL); | |
| Usb = (USB_DEVICE_PATH *) DevicePathNode; | |
| Status = AppendCSDNum (MappingItem, Usb->ParentPortNumber); | |
| if (!EFI_ERROR (Status)) { | |
| Status = AppendCSDNum (MappingItem, Usb->InterfaceNumber); | |
| } | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| if (PcdGetBool(PcdUsbExtendedDecode)) { | |
| Status = gBS->LocateDevicePath( &gEfiUsbIoProtocolGuid, &DevicePath, &TempHandle ); | |
| UsbIo = NULL; | |
| if (!EFI_ERROR(Status)) { | |
| Status = gBS->OpenProtocol(TempHandle, &gEfiUsbIoProtocolGuid, (VOID**)&UsbIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); | |
| } | |
| if (!EFI_ERROR(Status)) { | |
| ASSERT(UsbIo != NULL); | |
| Status = UsbIo->UsbGetInterfaceDescriptor(UsbIo, &InterfaceDesc); | |
| if (!EFI_ERROR(Status)) { | |
| if (InterfaceDesc.InterfaceClass == USB_MASS_STORE_CLASS && MappingItem->Mtd == MTDTypeUnknown) { | |
| switch (InterfaceDesc.InterfaceSubClass){ | |
| case USB_MASS_STORE_SCSI: | |
| MappingItem->Mtd = MTDTypeHardDisk; | |
| break; | |
| case USB_MASS_STORE_8070I: | |
| case USB_MASS_STORE_UFI: | |
| MappingItem->Mtd = MTDTypeFloppy; | |
| break; | |
| case USB_MASS_STORE_8020I: | |
| MappingItem->Mtd = MTDTypeCDRom; | |
| break; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| return Status; | |
| } | |
| /** | |
| DevicePathNode must be SerialVendor type and this will populate the MappingItem. | |
| @param[in] DevicePathNode The node to get info on. | |
| @param[in] MappingItem The info item to populate. | |
| @param[in] DevicePath Ignored. | |
| @retval EFI_OUT_OF_RESOURCES Out of resources. | |
| @retval EFI_SUCCESS The appending was successful. | |
| **/ | |
| EFI_STATUS | |
| DevPathSerialVendor ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
| IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| VENDOR_DEVICE_PATH *Vendor; | |
| SAS_DEVICE_PATH *Sas; | |
| UINTN TargetNameLength; | |
| UINTN Index; | |
| CHAR16 *Buffer; | |
| CHAR16 *NewBuffer; | |
| ASSERT(DevicePathNode != NULL); | |
| ASSERT(MappingItem != NULL); | |
| Vendor = (VENDOR_DEVICE_PATH *) DevicePathNode; | |
| Status = AppendCSDGuid (MappingItem, &Vendor->Guid); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| if (CompareGuid (&gEfiSasDevicePathGuid, &Vendor->Guid)) { | |
| Sas = (SAS_DEVICE_PATH *) Vendor; | |
| Status = AppendCSDNum (MappingItem, Sas->SasAddress); | |
| if (!EFI_ERROR (Status)) { | |
| Status = AppendCSDNum (MappingItem, Sas->Lun); | |
| } | |
| if (!EFI_ERROR (Status)) { | |
| Status = AppendCSDNum (MappingItem, Sas->DeviceTopology); | |
| } | |
| if (!EFI_ERROR (Status)) { | |
| Status = AppendCSDNum (MappingItem, Sas->RelativeTargetPort); | |
| } | |
| } else { | |
| TargetNameLength = MIN(DevicePathNodeLength (DevicePathNode) - sizeof (VENDOR_DEVICE_PATH), PcdGet32(PcdShellVendorExtendedDecode)); | |
| if (TargetNameLength != 0) { | |
| // | |
| // String is 2 chars per data byte, plus NULL terminator | |
| // | |
| Buffer = AllocateZeroPool (((TargetNameLength * 2) + 1) * sizeof(CHAR16)); | |
| if (Buffer == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| // | |
| // Build the string data | |
| // | |
| for (Index = 0; Index < TargetNameLength; Index++) { | |
| NewBuffer = CatSPrint (Buffer, L"%02x", *((UINT8*)Vendor + sizeof (VENDOR_DEVICE_PATH) + Index)); | |
| if (NewBuffer == NULL) { | |
| Status = EFI_OUT_OF_RESOURCES; | |
| break; | |
| } | |
| Buffer = NewBuffer; | |
| } | |
| // | |
| // Append the new data block | |
| // | |
| if (!EFI_ERROR (Status)) { | |
| Status = AppendCSDStr (MappingItem, Buffer); | |
| } | |
| FreePool(Buffer); | |
| } | |
| } | |
| return Status; | |
| } | |
| /** | |
| DevicePathNode must be SerialLun type and this will populate the MappingItem. | |
| @param[in] DevicePathNode The node to get info on. | |
| @param[in] MappingItem The info item to populate. | |
| @param[in] DevicePath Ignored. | |
| @retval EFI_OUT_OF_RESOURCES Out of resources. | |
| @retval EFI_SUCCESS The appending was successful. | |
| **/ | |
| EFI_STATUS | |
| DevPathSerialLun ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
| IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
| ) | |
| { | |
| DEVICE_LOGICAL_UNIT_DEVICE_PATH *Lun; | |
| ASSERT(DevicePathNode != NULL); | |
| ASSERT(MappingItem != NULL); | |
| Lun = (DEVICE_LOGICAL_UNIT_DEVICE_PATH *) DevicePathNode; | |
| return AppendCSDNum (MappingItem, Lun->Lun); | |
| } | |
| /** | |
| DevicePathNode must be SerialSata type and this will populate the MappingItem. | |
| @param[in] DevicePathNode The node to get info on. | |
| @param[in] MappingItem The info item to populate. | |
| @param[in] DevicePath Ignored. | |
| @retval EFI_OUT_OF_RESOURCES Out of resources. | |
| @retval EFI_SUCCESS The appending was successful. | |
| **/ | |
| EFI_STATUS | |
| DevPathSerialSata ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
| IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| SATA_DEVICE_PATH *Sata; | |
| ASSERT(DevicePathNode != NULL); | |
| ASSERT(MappingItem != NULL); | |
| Sata = (SATA_DEVICE_PATH *) DevicePathNode; | |
| Status = AppendCSDNum (MappingItem, Sata->HBAPortNumber); | |
| if (!EFI_ERROR (Status)) { | |
| Status = AppendCSDNum (MappingItem, Sata->PortMultiplierPortNumber); | |
| } | |
| if (!EFI_ERROR (Status)) { | |
| Status = AppendCSDNum (MappingItem, Sata->Lun); | |
| } | |
| return Status; | |
| } | |
| /** | |
| DevicePathNode must be SerialSCSI type and this will populate the MappingItem. | |
| @param[in] DevicePathNode The node to get info on. | |
| @param[in] MappingItem The info item to populate. | |
| @param[in] DevicePath Ignored. | |
| @retval EFI_OUT_OF_RESOURCES Out of resources. | |
| @retval EFI_SUCCESS The appending was successful. | |
| **/ | |
| EFI_STATUS | |
| DevPathSerialIScsi ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
| IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| ISCSI_DEVICE_PATH *IScsi; | |
| UINT8 *IScsiTargetName; | |
| CHAR16 *TargetName; | |
| UINTN TargetNameLength; | |
| UINTN Index; | |
| ASSERT(DevicePathNode != NULL); | |
| ASSERT(MappingItem != NULL); | |
| Status = EFI_SUCCESS; | |
| if (PcdGetBool(PcdShellDecodeIScsiMapNames)) { | |
| IScsi = (ISCSI_DEVICE_PATH *) DevicePathNode; | |
| Status = AppendCSDNum (MappingItem, IScsi->NetworkProtocol); | |
| if (!EFI_ERROR (Status)) { | |
| Status = AppendCSDNum (MappingItem, IScsi->LoginOption); | |
| } | |
| if (!EFI_ERROR (Status)) { | |
| Status = AppendCSDNum (MappingItem, IScsi->Lun); | |
| } | |
| if (!EFI_ERROR (Status)) { | |
| Status = AppendCSDNum (MappingItem, IScsi->TargetPortalGroupTag); | |
| } | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| TargetNameLength = DevicePathNodeLength (DevicePathNode) - sizeof (ISCSI_DEVICE_PATH); | |
| if (TargetNameLength > 0) { | |
| TargetName = AllocateZeroPool ((TargetNameLength + 1) * sizeof (CHAR16)); | |
| if (TargetName == NULL) { | |
| Status = EFI_OUT_OF_RESOURCES; | |
| } else { | |
| IScsiTargetName = (UINT8 *) (IScsi + 1); | |
| for (Index = 0; Index < TargetNameLength; Index++) { | |
| TargetName[Index] = (CHAR16) IScsiTargetName[Index]; | |
| } | |
| Status = AppendCSDStr (MappingItem, TargetName); | |
| FreePool (TargetName); | |
| } | |
| } | |
| } | |
| return Status; | |
| } | |
| /** | |
| DevicePathNode must be SerialI20 type and this will populate the MappingItem. | |
| @param[in] DevicePathNode The node to get info on. | |
| @param[in] MappingItem The info item to populate. | |
| @param[in] DevicePath Ignored. | |
| @retval EFI_OUT_OF_RESOURCES Out of resources. | |
| @retval EFI_SUCCESS The appending was successful. | |
| **/ | |
| EFI_STATUS | |
| DevPathSerialI2O ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
| IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
| ) | |
| { | |
| I2O_DEVICE_PATH *DevicePath_I20; | |
| ASSERT(DevicePathNode != NULL); | |
| ASSERT(MappingItem != NULL); | |
| DevicePath_I20 = (I2O_DEVICE_PATH *) DevicePathNode; | |
| return AppendCSDNum (MappingItem, DevicePath_I20->Tid); | |
| } | |
| /** | |
| DevicePathNode must be Mac Address type and this will populate the MappingItem. | |
| @param[in] DevicePathNode The node to get info on. | |
| @param[in] MappingItem The info item to populate. | |
| @param[in] DevicePath Ignored. | |
| @retval EFI_OUT_OF_RESOURCES Out of resources. | |
| @retval EFI_SUCCESS The appending was successful. | |
| **/ | |
| EFI_STATUS | |
| DevPathSerialMacAddr ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
| IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
| ) | |
| { | |
| MAC_ADDR_DEVICE_PATH *Mac; | |
| UINTN HwAddressSize; | |
| UINTN Index; | |
| CHAR16 Buffer[64]; | |
| CHAR16 *PBuffer; | |
| ASSERT(DevicePathNode != NULL); | |
| ASSERT(MappingItem != NULL); | |
| Mac = (MAC_ADDR_DEVICE_PATH *) DevicePathNode; | |
| HwAddressSize = sizeof (EFI_MAC_ADDRESS); | |
| if (Mac->IfType == 0x01 || Mac->IfType == 0x00) { | |
| HwAddressSize = 6; | |
| } | |
| for (Index = 0, PBuffer = Buffer; Index < HwAddressSize; Index++, PBuffer += 2) { | |
| UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) Mac->MacAddress.Addr[Index]); | |
| } | |
| return AppendCSDStr (MappingItem, Buffer); | |
| } | |
| /** | |
| DevicePathNode must be InfiniBand type and this will populate the MappingItem. | |
| @param[in] DevicePathNode The node to get info on. | |
| @param[in] MappingItem The info item to populate. | |
| @param[in] DevicePath Ignored. | |
| @retval EFI_OUT_OF_RESOURCES Out of resources. | |
| @retval EFI_SUCCESS The appending was successful. | |
| **/ | |
| EFI_STATUS | |
| DevPathSerialInfiniBand ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
| IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| INFINIBAND_DEVICE_PATH *InfiniBand; | |
| UINTN Index; | |
| CHAR16 Buffer[64]; | |
| CHAR16 *PBuffer; | |
| ASSERT(DevicePathNode != NULL); | |
| ASSERT(MappingItem != NULL); | |
| InfiniBand = (INFINIBAND_DEVICE_PATH *) DevicePathNode; | |
| for (Index = 0, PBuffer = Buffer; Index < 16; Index++, PBuffer += 2) { | |
| UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) InfiniBand->PortGid[Index]); | |
| } | |
| Status = AppendCSDStr (MappingItem, Buffer); | |
| if (!EFI_ERROR (Status)) { | |
| Status = AppendCSDNum (MappingItem, InfiniBand->ServiceId); | |
| } | |
| if (!EFI_ERROR (Status)) { | |
| Status = AppendCSDNum (MappingItem, InfiniBand->TargetPortId); | |
| } | |
| if (!EFI_ERROR (Status)) { | |
| Status = AppendCSDNum (MappingItem, InfiniBand->DeviceId); | |
| } | |
| return Status; | |
| } | |
| /** | |
| DevicePathNode must be IPv4 type and this will populate the MappingItem. | |
| @param[in] DevicePathNode The node to get info on. | |
| @param[in] MappingItem The info item to populate. | |
| @param[in] DevicePath Ignored. | |
| @retval EFI_OUT_OF_RESOURCES Out of resources. | |
| @retval EFI_SUCCESS The appending was successful. | |
| **/ | |
| EFI_STATUS | |
| DevPathSerialIPv4 ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
| IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| IPv4_DEVICE_PATH *Ip; | |
| CHAR16 Buffer[10]; | |
| ASSERT(DevicePathNode != NULL); | |
| ASSERT(MappingItem != NULL); | |
| Ip = (IPv4_DEVICE_PATH *) DevicePathNode; | |
| UnicodeSPrint ( | |
| Buffer, | |
| 0, | |
| L"%02x%02x%02x%02x", | |
| (UINTN) Ip->LocalIpAddress.Addr[0], | |
| (UINTN) Ip->LocalIpAddress.Addr[1], | |
| (UINTN) Ip->LocalIpAddress.Addr[2], | |
| (UINTN) Ip->LocalIpAddress.Addr[3] | |
| ); | |
| Status = AppendCSDStr (MappingItem, Buffer); | |
| if (!EFI_ERROR (Status)) { | |
| Status = AppendCSDNum (MappingItem, Ip->LocalPort); | |
| } | |
| if (!EFI_ERROR (Status)) { | |
| UnicodeSPrint ( | |
| Buffer, | |
| 0, | |
| L"%02x%02x%02x%02x", | |
| (UINTN) Ip->RemoteIpAddress.Addr[0], | |
| (UINTN) Ip->RemoteIpAddress.Addr[1], | |
| (UINTN) Ip->RemoteIpAddress.Addr[2], | |
| (UINTN) Ip->RemoteIpAddress.Addr[3] | |
| ); | |
| Status = AppendCSDStr (MappingItem, Buffer); | |
| } | |
| if (!EFI_ERROR (Status)) { | |
| Status = AppendCSDNum (MappingItem, Ip->RemotePort); | |
| } | |
| return Status; | |
| } | |
| /** | |
| DevicePathNode must be IPv6 type and this will populate the MappingItem. | |
| @param[in] DevicePathNode The node to get info on. | |
| @param[in] MappingItem The info item to populate. | |
| @param[in] DevicePath Ignored. | |
| @retval EFI_OUT_OF_RESOURCES Out of resources. | |
| @retval EFI_SUCCESS The appending was successful. | |
| **/ | |
| EFI_STATUS | |
| DevPathSerialIPv6 ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
| IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| IPv6_DEVICE_PATH *Ip; | |
| UINTN Index; | |
| CHAR16 Buffer[64]; | |
| CHAR16 *PBuffer; | |
| ASSERT(DevicePathNode != NULL); | |
| ASSERT(MappingItem != NULL); | |
| Ip = (IPv6_DEVICE_PATH *) DevicePathNode; | |
| for (Index = 0, PBuffer = Buffer; Index < 16; Index++, PBuffer += 2) { | |
| UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) Ip->LocalIpAddress.Addr[Index]); | |
| } | |
| Status = AppendCSDStr (MappingItem, Buffer); | |
| if (!EFI_ERROR (Status)) { | |
| Status = AppendCSDNum (MappingItem, Ip->LocalPort); | |
| } | |
| if (!EFI_ERROR (Status)) { | |
| for (Index = 0, PBuffer = Buffer; Index < 16; Index++, PBuffer += 2) { | |
| UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) Ip->RemoteIpAddress.Addr[Index]); | |
| } | |
| Status = AppendCSDStr (MappingItem, Buffer); | |
| } | |
| if (!EFI_ERROR (Status)) { | |
| Status = AppendCSDNum (MappingItem, Ip->RemotePort); | |
| } | |
| return Status; | |
| } | |
| /** | |
| DevicePathNode must be SCSI type and this will populate the MappingItem. | |
| @param[in] DevicePathNode The node to get info on. | |
| @param[in] MappingItem The info item to populate. | |
| @param[in] DevicePath Ignored. | |
| @retval EFI_OUT_OF_RESOURCES Out of resources. | |
| @retval EFI_SUCCESS The appending was successful. | |
| **/ | |
| EFI_STATUS | |
| DevPathSerialScsi ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
| IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| SCSI_DEVICE_PATH *Scsi; | |
| ASSERT(DevicePathNode != NULL); | |
| ASSERT(MappingItem != NULL); | |
| Scsi = (SCSI_DEVICE_PATH *) DevicePathNode; | |
| Status = AppendCSDNum (MappingItem, Scsi->Pun); | |
| if (!EFI_ERROR (Status)) { | |
| Status = AppendCSDNum (MappingItem, Scsi->Lun); | |
| } | |
| return Status; | |
| } | |
| /** | |
| DevicePathNode must be 1394 type and this will populate the MappingItem. | |
| @param[in] DevicePathNode The node to get info on. | |
| @param[in] MappingItem The info item to populate. | |
| @param[in] DevicePath Ignored. | |
| @retval EFI_OUT_OF_RESOURCES Out of resources. | |
| @retval EFI_SUCCESS The appending was successful. | |
| **/ | |
| EFI_STATUS | |
| DevPathSerial1394 ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
| IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
| ) | |
| { | |
| F1394_DEVICE_PATH *DevicePath_F1394; | |
| CHAR16 Buffer[20]; | |
| ASSERT(DevicePathNode != NULL); | |
| ASSERT(MappingItem != NULL); | |
| DevicePath_F1394 = (F1394_DEVICE_PATH *) DevicePathNode; | |
| UnicodeSPrint (Buffer, 0, L"%lx", DevicePath_F1394->Guid); | |
| return AppendCSDStr (MappingItem, Buffer); | |
| } | |
| /** | |
| If the node is floppy type then populate the MappingItem. | |
| @param[in] DevicePathNode The node to get info on. | |
| @param[in] MappingItem The info item to populate. | |
| @param[in] DevicePath Ignored. | |
| @retval EFI_OUT_OF_RESOURCES Out of resources. | |
| @retval EFI_SUCCESS The appending was successful. | |
| **/ | |
| EFI_STATUS | |
| DevPathSerialAcpi ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
| IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
| ) | |
| { | |
| ACPI_HID_DEVICE_PATH *Acpi; | |
| ASSERT(DevicePathNode != NULL); | |
| ASSERT(MappingItem != NULL); | |
| Acpi = (ACPI_HID_DEVICE_PATH *) DevicePathNode; | |
| if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { | |
| if (EISA_ID_TO_NUM (Acpi->HID) == 0x0604) { | |
| MappingItem->Mtd = MTDTypeFloppy; | |
| return AppendCSDNum (MappingItem, Acpi->UID); | |
| } | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Empty function used for unknown devices. | |
| @param[in] DevicePathNode Ignored. | |
| @param[in] MappingItem Ignored. | |
| @param[in] DevicePath Ignored. | |
| @retval EFI_OUT_OF_RESOURCES Out of resources. | |
| @retval EFI_SUCCESS The appending was successful. | |
| **/ | |
| EFI_STATUS | |
| DevPathSerialDefault ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, | |
| IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
| ) | |
| { | |
| return EFI_SUCCESS; | |
| } | |
| DEV_PATH_CONSIST_MAPPING_TABLE DevPathConsistMappingTable[] = { | |
| { | |
| HARDWARE_DEVICE_PATH, | |
| HW_PCI_DP, | |
| DevPathSerialDefault, | |
| DevPathComparePci | |
| }, | |
| { | |
| ACPI_DEVICE_PATH, | |
| ACPI_DP, | |
| DevPathSerialAcpi, | |
| DevPathCompareAcpi | |
| }, | |
| { | |
| MESSAGING_DEVICE_PATH, | |
| MSG_ATAPI_DP, | |
| DevPathSerialAtapi, | |
| DevPathCompareDefault | |
| }, | |
| { | |
| MESSAGING_DEVICE_PATH, | |
| MSG_SCSI_DP, | |
| DevPathSerialScsi, | |
| DevPathCompareDefault | |
| }, | |
| { | |
| MESSAGING_DEVICE_PATH, | |
| MSG_FIBRECHANNEL_DP, | |
| DevPathSerialFibre, | |
| DevPathCompareDefault | |
| }, | |
| { | |
| MESSAGING_DEVICE_PATH, | |
| MSG_1394_DP, | |
| DevPathSerial1394, | |
| DevPathCompareDefault | |
| }, | |
| { | |
| MESSAGING_DEVICE_PATH, | |
| MSG_USB_DP, | |
| DevPathSerialUsb, | |
| DevPathCompareDefault | |
| }, | |
| { | |
| MESSAGING_DEVICE_PATH, | |
| MSG_I2O_DP, | |
| DevPathSerialI2O, | |
| DevPathCompareDefault | |
| }, | |
| { | |
| MESSAGING_DEVICE_PATH, | |
| MSG_MAC_ADDR_DP, | |
| DevPathSerialMacAddr, | |
| DevPathCompareDefault | |
| }, | |
| { | |
| MESSAGING_DEVICE_PATH, | |
| MSG_IPv4_DP, | |
| DevPathSerialIPv4, | |
| DevPathCompareDefault | |
| }, | |
| { | |
| MESSAGING_DEVICE_PATH, | |
| MSG_IPv6_DP, | |
| DevPathSerialIPv6, | |
| DevPathCompareDefault | |
| }, | |
| { | |
| MESSAGING_DEVICE_PATH, | |
| MSG_INFINIBAND_DP, | |
| DevPathSerialInfiniBand, | |
| DevPathCompareDefault | |
| }, | |
| { | |
| MESSAGING_DEVICE_PATH, | |
| MSG_UART_DP, | |
| DevPathSerialUart, | |
| DevPathCompareDefault | |
| }, | |
| { | |
| MESSAGING_DEVICE_PATH, | |
| MSG_VENDOR_DP, | |
| DevPathSerialVendor, | |
| DevPathCompareDefault | |
| }, | |
| { | |
| MESSAGING_DEVICE_PATH, | |
| MSG_DEVICE_LOGICAL_UNIT_DP, | |
| DevPathSerialLun, | |
| DevPathCompareDefault | |
| }, | |
| { | |
| MESSAGING_DEVICE_PATH, | |
| MSG_SATA_DP, | |
| DevPathSerialSata, | |
| DevPathCompareDefault | |
| }, | |
| { | |
| MESSAGING_DEVICE_PATH, | |
| MSG_ISCSI_DP, | |
| DevPathSerialIScsi, | |
| DevPathCompareDefault | |
| }, | |
| { | |
| MEDIA_DEVICE_PATH, | |
| MEDIA_HARDDRIVE_DP, | |
| DevPathSerialHardDrive, | |
| DevPathCompareDefault | |
| }, | |
| { | |
| MEDIA_DEVICE_PATH, | |
| MEDIA_CDROM_DP, | |
| DevPathSerialCdRom, | |
| DevPathCompareDefault | |
| }, | |
| { | |
| MEDIA_DEVICE_PATH, | |
| MEDIA_VENDOR_DP, | |
| DevPathSerialVendor, | |
| DevPathCompareDefault | |
| }, | |
| { | |
| 0, | |
| 0, | |
| NULL, | |
| NULL | |
| } | |
| }; | |
| /** | |
| Function to determine if a device path node is Hi or not. | |
| @param[in] DevicePathNode The node to check. | |
| @retval TRUE The node is Hi. | |
| @retval FALSE The node is not Hi. | |
| **/ | |
| BOOLEAN | |
| IsHIDevicePathNode ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode | |
| ) | |
| { | |
| ACPI_HID_DEVICE_PATH *Acpi; | |
| ASSERT(DevicePathNode != NULL); | |
| if (DevicePathNode->Type == HARDWARE_DEVICE_PATH) { | |
| return TRUE; | |
| } | |
| if (DevicePathNode->Type == ACPI_DEVICE_PATH) { | |
| Acpi = (ACPI_HID_DEVICE_PATH *) DevicePathNode; | |
| switch (EISA_ID_TO_NUM (Acpi->HID)) { | |
| case 0x0301: | |
| case 0x0401: | |
| case 0x0501: | |
| case 0x0604: | |
| return FALSE; | |
| } | |
| return TRUE; | |
| } | |
| return FALSE; | |
| } | |
| /** | |
| Function to convert a standard device path structure into a Hi version. | |
| @param[in] DevicePath The device path to convert. | |
| @return the device path portion that is Hi. | |
| **/ | |
| EFI_DEVICE_PATH_PROTOCOL * | |
| GetHIDevicePath ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
| ) | |
| { | |
| UINTN NonHIDevicePathNodeCount; | |
| UINTN Index; | |
| EFI_DEV_PATH Node; | |
| EFI_DEVICE_PATH_PROTOCOL *HIDevicePath; | |
| EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; | |
| ASSERT(DevicePath != NULL); | |
| NonHIDevicePathNodeCount = 0; | |
| HIDevicePath = AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL)); | |
| SetDevicePathEndNode (HIDevicePath); | |
| Node.DevPath.Type = END_DEVICE_PATH_TYPE; | |
| Node.DevPath.SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE; | |
| Node.DevPath.Length[0] = (UINT8)sizeof (EFI_DEVICE_PATH_PROTOCOL); | |
| Node.DevPath.Length[1] = 0; | |
| while (!IsDevicePathEnd (DevicePath)) { | |
| if (IsHIDevicePathNode (DevicePath)) { | |
| for (Index = 0; Index < NonHIDevicePathNodeCount; Index++) { | |
| TempDevicePath = AppendDevicePathNode (HIDevicePath, &Node.DevPath); | |
| FreePool (HIDevicePath); | |
| HIDevicePath = TempDevicePath; | |
| } | |
| TempDevicePath = AppendDevicePathNode (HIDevicePath, DevicePath); | |
| FreePool (HIDevicePath); | |
| HIDevicePath = TempDevicePath; | |
| } else { | |
| NonHIDevicePathNodeCount++; | |
| } | |
| // | |
| // Next device path node | |
| // | |
| DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (DevicePath); | |
| } | |
| return HIDevicePath; | |
| } | |
| /** | |
| Function to walk the device path looking for a dumpable node. | |
| @param[in] MappingItem The Item to fill with data. | |
| @param[in] DevicePath The path of the item to get data on. | |
| @return EFI_SUCCESS Always returns success. | |
| **/ | |
| EFI_STATUS | |
| GetDeviceConsistMappingInfo ( | |
| IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| SERIAL_DECODE_FUNCTION SerialFun; | |
| UINTN Index; | |
| EFI_DEVICE_PATH_PROTOCOL *OriginalDevicePath; | |
| ASSERT(DevicePath != NULL); | |
| ASSERT(MappingItem != NULL); | |
| SetMem (&MappingItem->Csd, sizeof (POOL_PRINT), 0); | |
| OriginalDevicePath = DevicePath; | |
| while (!IsDevicePathEnd (DevicePath)) { | |
| // | |
| // Find the handler to dump this device path node and | |
| // initialize with generic function in case nothing is found | |
| // | |
| for (SerialFun = DevPathSerialDefault, Index = 0; DevPathConsistMappingTable[Index].SerialFun != NULL; Index += 1) { | |
| if (DevicePathType (DevicePath) == DevPathConsistMappingTable[Index].Type && | |
| DevicePathSubType (DevicePath) == DevPathConsistMappingTable[Index].SubType | |
| ) { | |
| SerialFun = DevPathConsistMappingTable[Index].SerialFun; | |
| break; | |
| } | |
| } | |
| Status = SerialFun (DevicePath, MappingItem, OriginalDevicePath); | |
| if (EFI_ERROR (Status)) { | |
| SHELL_FREE_NON_NULL (MappingItem->Csd.Str); | |
| return Status; | |
| } | |
| // | |
| // Next device path node | |
| // | |
| DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (DevicePath); | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Function to initialize the table for creating consistent map names. | |
| @param[out] Table The pointer to pointer to pointer to DevicePathProtocol object. | |
| @retval EFI_SUCCESS The table was created successfully. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| ShellCommandConsistMappingInitialize ( | |
| OUT EFI_DEVICE_PATH_PROTOCOL ***Table | |
| ) | |
| { | |
| EFI_HANDLE *HandleBuffer; | |
| UINTN HandleNum; | |
| UINTN HandleLoop; | |
| EFI_DEVICE_PATH_PROTOCOL **TempTable; | |
| EFI_DEVICE_PATH_PROTOCOL *DevicePath; | |
| EFI_DEVICE_PATH_PROTOCOL *HIDevicePath; | |
| EFI_BLOCK_IO_PROTOCOL *BlockIo; | |
| EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem; | |
| UINTN Index; | |
| EFI_STATUS Status; | |
| HandleBuffer = NULL; | |
| Status = gBS->LocateHandleBuffer ( | |
| ByProtocol, | |
| &gEfiDevicePathProtocolGuid, | |
| NULL, | |
| &HandleNum, | |
| &HandleBuffer | |
| ); | |
| ASSERT_EFI_ERROR(Status); | |
| TempTable = AllocateZeroPool ((HandleNum + 1) * sizeof (EFI_DEVICE_PATH_PROTOCOL *)); | |
| if (TempTable == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| for (HandleLoop = 0 ; HandleLoop < HandleNum ; HandleLoop++) { | |
| DevicePath = DevicePathFromHandle (HandleBuffer[HandleLoop]); | |
| if (DevicePath == NULL) { | |
| continue; | |
| } | |
| HIDevicePath = GetHIDevicePath (DevicePath); | |
| if (HIDevicePath == NULL) { | |
| continue; | |
| } | |
| Status = gBS->HandleProtocol( HandleBuffer[HandleLoop], | |
| &gEfiBlockIoProtocolGuid, | |
| (VOID **)&BlockIo | |
| ); | |
| if (EFI_ERROR(Status)) { | |
| Status = gBS->HandleProtocol( HandleBuffer[HandleLoop], | |
| &gEfiSimpleFileSystemProtocolGuid, | |
| (VOID **)&SimpleFileSystem | |
| ); | |
| if (EFI_ERROR(Status)) { | |
| FreePool (HIDevicePath); | |
| continue; | |
| } | |
| } | |
| for (Index = 0; TempTable[Index] != NULL; Index++) { | |
| if (DevicePathCompare (&TempTable[Index], &HIDevicePath) == 0) { | |
| FreePool (HIDevicePath); | |
| break; | |
| } | |
| } | |
| if (TempTable[Index] == NULL) { | |
| TempTable[Index] = HIDevicePath; | |
| } | |
| } | |
| for (Index = 0; TempTable[Index] != NULL; Index++); | |
| PerformQuickSort(TempTable, Index, sizeof(EFI_DEVICE_PATH_PROTOCOL*), DevicePathCompare); | |
| *Table = TempTable; | |
| if (HandleBuffer != NULL) { | |
| FreePool (HandleBuffer); | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Function to uninitialize the table for creating consistent map names. | |
| The parameter must have been received from ShellCommandConsistMappingInitialize. | |
| @param[out] Table The pointer to pointer to DevicePathProtocol object. | |
| @retval EFI_SUCCESS The table was deleted successfully. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| ShellCommandConsistMappingUnInitialize ( | |
| EFI_DEVICE_PATH_PROTOCOL **Table | |
| ) | |
| { | |
| UINTN Index; | |
| ASSERT(Table != NULL); | |
| for (Index = 0; Table[Index] != NULL; Index++) { | |
| FreePool (Table[Index]); | |
| } | |
| FreePool (Table); | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Create a consistent mapped name for the device specified by DevicePath | |
| based on the Table. | |
| This must be called after ShellCommandConsistMappingInitialize() and | |
| before ShellCommandConsistMappingUnInitialize() is called. | |
| @param[in] DevicePath The pointer to the dev path for the device. | |
| @param[in] Table The Table of mapping information. | |
| @retval NULL A consistent mapped name could not be created. | |
| @return A pointer to a string allocated from pool with the device name. | |
| **/ | |
| CHAR16 * | |
| EFIAPI | |
| ShellCommandConsistMappingGenMappingName ( | |
| IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, | |
| IN EFI_DEVICE_PATH_PROTOCOL **Table | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| POOL_PRINT Str; | |
| DEVICE_CONSIST_MAPPING_INFO MappingInfo; | |
| EFI_DEVICE_PATH_PROTOCOL *HIDevicePath; | |
| UINTN Index; | |
| CHAR16 *NewStr; | |
| ASSERT(DevicePath != NULL); | |
| ASSERT(Table != NULL); | |
| HIDevicePath = GetHIDevicePath (DevicePath); | |
| if (HIDevicePath == NULL) { | |
| return NULL; | |
| } | |
| for (Index = 0; Table[Index] != NULL; Index++) { | |
| if (DevicePathCompare (&Table[Index], &HIDevicePath) == 0) { | |
| break; | |
| } | |
| } | |
| FreePool (HIDevicePath); | |
| if (Table[Index] == NULL) { | |
| return NULL; | |
| } | |
| MappingInfo.Hi = Index; | |
| MappingInfo.Mtd = MTDTypeUnknown; | |
| MappingInfo.Digital = FALSE; | |
| Status = GetDeviceConsistMappingInfo (&MappingInfo, DevicePath); | |
| if (EFI_ERROR (Status)) { | |
| return NULL; | |
| } | |
| SetMem (&Str, sizeof (Str), 0); | |
| for (Index = 0; mMTDName[Index].MTDType != MTDTypeEnd; Index++) { | |
| if (MappingInfo.Mtd == mMTDName[Index].MTDType) { | |
| break; | |
| } | |
| } | |
| if (mMTDName[Index].MTDType != MTDTypeEnd) { | |
| Status = CatPrint (&Str, L"%s", mMTDName[Index].Name); | |
| } | |
| if (!EFI_ERROR (Status)) { | |
| Status = CatPrint (&Str, L"%d", (UINTN) MappingInfo.Hi); | |
| } | |
| if (!EFI_ERROR (Status) && MappingInfo.Csd.Str != NULL) { | |
| Status = CatPrint (&Str, L"%s", MappingInfo.Csd.Str); | |
| FreePool (MappingInfo.Csd.Str); | |
| } | |
| if (!EFI_ERROR (Status) && Str.Str != NULL) { | |
| Status = CatPrint (&Str, L":"); | |
| } | |
| if (EFI_ERROR (Status)) { | |
| SHELL_FREE_NON_NULL (Str.Str); | |
| return NULL; | |
| } | |
| NewStr = ReallocatePool (Str.Len * sizeof (CHAR16), (Str.Len + 1) * sizeof (CHAR16), Str.Str); | |
| if (NewStr == NULL) { | |
| SHELL_FREE_NON_NULL (Str.Str); | |
| return (NULL); | |
| } | |
| NewStr[Str.Len] = CHAR_NULL; | |
| return NewStr; | |
| } | |
| /** | |
| Function to search the list of mappings for the node on the list based on the key. | |
| @param[in] MapKey String Key to search for on the map | |
| @return the node on the list. | |
| **/ | |
| SHELL_MAP_LIST * | |
| EFIAPI | |
| ShellCommandFindMapItem ( | |
| IN CONST CHAR16 *MapKey | |
| ) | |
| { | |
| SHELL_MAP_LIST *MapListItem; | |
| for ( MapListItem = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link) | |
| ; !IsNull(&gShellMapList.Link, &MapListItem->Link) | |
| ; MapListItem = (SHELL_MAP_LIST *)GetNextNode(&gShellMapList.Link, &MapListItem->Link) | |
| ){ | |
| if (gUnicodeCollation->StriColl(gUnicodeCollation,MapListItem->MapName,(CHAR16*)MapKey) == 0) { | |
| return (MapListItem); | |
| } | |
| } | |
| return (NULL); | |
| } | |