public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [edk2-devel] [PATCH 1/1] MdeModulePkg/UefiBootManagerLib: Build proper SD/MMC boot descriptions
@ 2024-01-04  2:47 Mario Bălănică
  2024-03-15 21:21 ` Mario Bălănică
  0 siblings, 1 reply; 2+ messages in thread
From: Mario Bălănică @ 2024-01-04  2:47 UTC (permalink / raw)
  To: devel; +Cc: gaoliming, ray.ni, zhichao.gao

This generates boot descriptions for SD/MMC devices in the form of:
  - "UEFI SanDisk SC128 2A2B1E4F SD Device"
  - "UEFI Samsung BJTD4R 7AB3A8DE eMMC User Data"

The manufacturer ID tables are a best-effort, collected from various
places and personal testing. They're not complete and may be inaccurate
for rebranded cards.

Signed-off-by: Mario Bălănică <mariobalanica02@gmail.com>
---
 MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c | 244 +++++++++++++++++++-
 MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h        |   2 +
 2 files changed, 244 insertions(+), 2 deletions(-)

diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c b/MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c
index 030b2ee3ec25..70c45f794250 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c
+++ b/MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c
@@ -17,6 +17,69 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 CONST UINT16  mBmUsbLangId    = 0x0409; // English
 CHAR16        mBmUefiPrefix[] = L"UEFI ";
 
+CHAR16  mBootDescGenericManufacturer[] = L"Generic";
+CHAR16  mBootDescSd[]                  = L"SD Device";
+CHAR16  mBootDescEmmc[]                = L"eMMC Device";
+CHAR16  mBootDescEmmcUserData[]        = L"eMMC User Data";
+CHAR16  mBootDescEmmcBoot1[]           = L"eMMC Boot 1";
+CHAR16  mBootDescEmmcBoot2[]           = L"eMMC Boot 2";
+CHAR16  mBootDescEmmcGp1[]             = L"eMMC GP 1";
+CHAR16  mBootDescEmmcGp2[]             = L"eMMC GP 2";
+CHAR16  mBootDescEmmcGp3[]             = L"eMMC GP 3";
+CHAR16  mBootDescEmmcGp4[]             = L"eMMC GP 4";
+
+typedef struct {
+  UINT8     Id;
+  CHAR16    *Name;
+} BM_SDMMC_MANUFACTURER;
+
+//
+// List based on:
+//  - https://www.cameramemoryspeed.com/sd-memory-card-faq/reading-sd-card-cid-serial-psn-internal-numbers/
+//  - https://git.kernel.org/pub/scm/utils/mmc/mmc-utils.git/tree/lsmmc.c
+//
+BM_SDMMC_MANUFACTURER  mSdManufacturers[] = {
+  { 0x01, L"Panasonic"               },
+  { 0x02, L"Toshiba/Kingston/Viking" },
+  { 0x03, L"SanDisk"                 },
+  { 0x08, L"Silicon Power"           },
+  { 0x18, L"Infineon"                },
+  { 0x1b, L"Transcend/Samsung"       },
+  { 0x1c, L"Transcend"               },
+  { 0x1d, L"Corsair/AData"           },
+  { 0x1e, L"Transcend"               },
+  { 0x1f, L"Kingston"                },
+  { 0x27, L"Delkin/Phison"           },
+  { 0x28, L"Lexar"                   },
+  { 0x30, L"SanDisk"                 },
+  { 0x31, L"Silicon Power"           },
+  { 0x33, L"STMicroelectronics"      },
+  { 0x41, L"Kingston"                },
+  { 0x6f, L"STMicroelectronics"      },
+  { 0x74, L"Transcend"               },
+  { 0x76, L"Patriot"                 },
+  { 0x82, L"Gobe/Sony"               },
+  { 0x9c, L"Angelbird/Hoodman"       },
+};
+
+BM_SDMMC_MANUFACTURER  mMmcManufacturers[] = {
+  { 0x00, L"SanDisk"          },
+  { 0x02, L"Kingston/SanDisk" },
+  { 0x03, L"Toshiba"          },
+  { 0x11, L"Toshiba"          },
+  { 0x13, L"Micron"           },
+  { 0x15, L"Samsung"          },
+  { 0x37, L"KingMax"          },
+  { 0x44, L"ATP"              },
+  { 0x45, L"SanDisk"          },
+  { 0x2c, L"Kingston"         },
+  { 0x70, L"Kingston"         },
+  { 0x88, L"Foresee"          },
+  { 0x9b, L"YMTC"             },
+  { 0xd6, L"Foresee"          },
+  { 0xfe, L"Micron"           },
+};
+
 LIST_ENTRY  mPlatformBootDescriptionHandlers = INITIALIZE_LIST_HEAD_VARIABLE (mPlatformBootDescriptionHandlers);
 
 /**
@@ -127,6 +190,150 @@ BmEliminateExtraSpaces (
   Str[ActualIndex] = L'\0';
 }
 
+/**
+  Swap a byte array.
+
+  @param    Source     Input byte array.
+  @param    Length     The size of Source in bytes.
+**/
+VOID
+BmSwapBytes (
+  IN UINT8  *Source,
+  IN UINTN  Length
+  )
+{
+  UINTN  Index;
+  UINT8  Temp;
+  UINTN  Count;
+
+  Count = Length / 2;
+  for (Index = 0; Index < Count; ++Index) {
+    Temp                       = Source[Index];
+    Source[Index]              = Source[Length - 1 - Index];
+    Source[Length - 1 - Index] = Temp;
+  }
+}
+
+/**
+  Get the SD/MMC manufacturer name from an ID.
+
+  @param    Id         Manufacturer ID.
+  @param    IsMmc      Boolean indicating whether the ID is for SD or eMMC.
+
+  @return  The manufacturer string.
+**/
+CHAR16 *
+BmGetSdMmcManufacturerName (
+  IN UINT8    Id,
+  IN BOOLEAN  IsMmc
+  )
+{
+  BM_SDMMC_MANUFACTURER  *List;
+  UINT8                  Count;
+  UINTN                  Index;
+
+  List  = IsMmc ? mMmcManufacturers : mSdManufacturers;
+  Count = IsMmc ? ARRAY_SIZE (mMmcManufacturers)
+                : ARRAY_SIZE (mSdManufacturers);
+
+  for (Index = 0; Index < Count; ++Index) {
+    if (List[Index].Id == Id) {
+      return List[Index].Name;
+    }
+  }
+
+  return mBootDescGenericManufacturer;
+}
+
+/**
+  Get the eMMC partition type from a controller path.
+
+  @param    DevicePath       Pointer to a CONTROLLER_DEVICE_PATH.
+
+  @return  The description string.
+**/
+CHAR16 *
+BmGetEmmcTypeDescription (
+  CONTROLLER_DEVICE_PATH  *DevicePath
+  )
+{
+  switch (DevicePath->ControllerNumber) {
+    case EmmcPartitionUserData:
+      return mBootDescEmmcUserData;
+    case EmmcPartitionBoot1:
+      return mBootDescEmmcBoot1;
+    case EmmcPartitionBoot2:
+      return mBootDescEmmcBoot2;
+    case EmmcPartitionGP1:
+      return mBootDescEmmcGp1;
+    case EmmcPartitionGP2:
+      return mBootDescEmmcGp2;
+    case EmmcPartitionGP3:
+      return mBootDescEmmcGp3;
+    case EmmcPartitionGP4:
+      return mBootDescEmmcGp4;
+    default:
+      break;
+  }
+
+  return mBootDescEmmc;
+}
+
+/**
+  Get an SD/MMC boot description.
+
+  @param    ManufacturerName           Manufacturer name string.
+  @param    ProductName                Product name from CID.
+  @param    ProductNameLength          Length of ProductName.
+  @param    SerialNumber               Serial number from CID.
+  @param    DeviceType                 Device type string (e.g. SD or an eMMC partition).
+
+  @return  The description string.
+**/
+CHAR16 *
+BmGetSdMmcDescription (
+  IN CHAR16  *ManufacturerName,
+  IN UINT8   *ProductName,
+  IN UINT8   ProductNameLength,
+  IN UINT8   SerialNumber[4],
+  IN CHAR16  *DeviceType
+  )
+{
+  CHAR16  *Desc;
+  UINTN   DescSize;
+
+  DescSize = StrSize (ManufacturerName) - sizeof (CHAR16)             // "Samsung"
+             + sizeof (CHAR16)                                        // " "
+             + ProductNameLength * sizeof (CHAR16)                    // "BJTD4R"
+             + sizeof (CHAR16)                                        // " "
+             + sizeof (UINT32) * 2 * sizeof (CHAR16)                  // "00000000"
+             + sizeof (CHAR16)                                        // " "
+             + StrSize (DeviceType);                                  // "eMMC User Data\0"
+
+  Desc = AllocateZeroPool (DescSize);
+  if (Desc == NULL) {
+    return NULL;
+  }
+
+  BmSwapBytes (ProductName, ProductNameLength);
+
+  UnicodeSPrint (
+    Desc,
+    DescSize,
+    L"%s %.*a %02x%02x%02x%02x %s",
+    ManufacturerName,
+    ProductNameLength,
+    ProductName,
+    SerialNumber[0],
+    SerialNumber[1],
+    SerialNumber[2],
+    SerialNumber[3],
+    DeviceType
+    );
+
+  return Desc;
+}
+
 /**
   Try to get the controller's ATA/ATAPI description.
 
@@ -145,6 +352,8 @@ BmGetDescriptionFromDiskInfo (
   UINT32                    BufferSize;
   EFI_ATAPI_IDENTIFY_DATA   IdentifyData;
   EFI_SCSI_INQUIRY_DATA     InquiryData;
+  SD_CID                    SdCid;
+  EMMC_CID                  EmmcCid;
   CHAR16                    *Description;
   UINTN                     Length;
   CONST UINTN               ModelNameLength    = 40;
@@ -245,9 +454,40 @@ BmGetDescriptionFromDiskInfo (
     }
 
     if (DevicePathSubType (DevicePath) == MSG_SD_DP) {
-      Description = L"SD Device";
+      BufferSize = sizeof (SD_CID);
+      Status     = DiskInfo->Inquiry (DiskInfo, &SdCid, &BufferSize);
+      if (EFI_ERROR (Status)) {
+        return NULL;
+      }
+
+      Description = BmGetSdMmcDescription (
+                      BmGetSdMmcManufacturerName (SdCid.ManufacturerId, FALSE),
+                      SdCid.ProductName,
+                      ARRAY_SIZE (SdCid.ProductName),
+                      SdCid.ProductSerialNumber,
+                      mBootDescSd
+                      );
     } else if (DevicePathSubType (DevicePath) == MSG_EMMC_DP) {
-      Description = L"eMMC Device";
+      BufferSize = sizeof (EMMC_CID);
+      Status     = DiskInfo->Inquiry (DiskInfo, &EmmcCid, &BufferSize);
+      if (EFI_ERROR (Status)) {
+        return NULL;
+      }
+
+      Description = mBootDescEmmc;
+
+      DevicePath = NextDevicePathNode (DevicePath);
+      if (DevicePath->SubType == HW_CONTROLLER_DP) {
+        Description = BmGetEmmcTypeDescription ((CONTROLLER_DEVICE_PATH *)DevicePath);
+      }
+
+      Description = BmGetSdMmcDescription (
+                      BmGetSdMmcManufacturerName (EmmcCid.ManufacturerId, TRUE),
+                      EmmcCid.ProductName,
+                      ARRAY_SIZE (EmmcCid.ProductName),
+                      EmmcCid.ProductSerialNumber,
+                      Description
+                      );
     } else {
       return NULL;
     }
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h b/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h
index b7dfe2a7e0bd..76ee0a83bf20 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h
+++ b/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h
@@ -18,6 +18,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <IndustryStandard/Atapi.h>
 #include <IndustryStandard/Scsi.h>
 #include <IndustryStandard/Nvme.h>
+#include <IndustryStandard/Sd.h>
+#include <IndustryStandard/Emmc.h>
 
 #include <Protocol/PciRootBridgeIo.h>
 #include <Protocol/BlockIo.h>
-- 
2.39.1.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#113128): https://edk2.groups.io/g/devel/message/113128
Mute This Topic: https://groups.io/mt/103516251/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [edk2-devel] [PATCH 1/1] MdeModulePkg/UefiBootManagerLib: Build proper SD/MMC boot descriptions
  2024-01-04  2:47 [edk2-devel] [PATCH 1/1] MdeModulePkg/UefiBootManagerLib: Build proper SD/MMC boot descriptions Mario Bălănică
@ 2024-03-15 21:21 ` Mario Bălănică
  0 siblings, 0 replies; 2+ messages in thread
From: Mario Bălănică @ 2024-03-15 21:21 UTC (permalink / raw)
  To: Mario Bălănică, devel

[-- Attachment #1: Type: text/plain, Size: 372 bytes --]

Bump


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#116818): https://edk2.groups.io/g/devel/message/116818
Mute This Topic: https://groups.io/mt/103516251/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



[-- Attachment #2: Type: text/html, Size: 784 bytes --]

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2024-03-15 21:21 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-01-04  2:47 [edk2-devel] [PATCH 1/1] MdeModulePkg/UefiBootManagerLib: Build proper SD/MMC boot descriptions Mario Bălănică
2024-03-15 21:21 ` Mario Bălănică

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox