[PATCH v2 2/2] efi_loader: expand disk device names with drive details

Padmarao Begari <[email protected]>
Newsgroups org.u-boot-project.lists.u-boot
Message-ID <[email protected]>
Increase the boot menu device name buffer so that extra metadata can
be appended. Append the disk capacity and trimmed vendor/product
strings to the device name so users can differentiate drives in the
EFI boot menu. Also pull in linux/string.h for the strl* helpers.

For example, the U-Boot boot menu now shows entries such as:

    usb 0 (29.7 GiB, Generic Ultra HS-COMBO)
    usb 1 (28.6 GiB, USB SanDisk 3.2Gen1)
    scsi 0 (1 GiB, MICRON MT064GBCAV1U31AA)

The menus are drawn with absolute cursor positioning starting at
column 7, see bootmenu_print_entry() and eficonfig_print_entry(), and
the titles are not truncated. A title which does not fit into a line
would wrap and thereby corrupt the menu layout. The name is therefore
limited to 64 characters, which leaves the longest description above
at 46 columns. Should the identification strings not fit, the
capacity is shown alone rather than a string cut in the middle:

    usb 0 (1023.9 GiB)

Note the limitation of this approach: the description is built from
what struct blk_desc carries, so devices reporting the same capacity
and the same identification strings still get the same description.
Two identical USB sticks, several namespaces of one NVMe drive, or
several sandbox host devices remain indistinguishable:

    nvme 0 (953.9 GiB, SKHynix_HFS001TEM4X169N)
    nvme 1 (953.9 GiB, SKHynix_HFS001TEM4X169N)

    host 0 (64 MiB, U-Boot hostfile)
    host 1 (64 MiB, U-Boot hostfile)

Signed-off-by: Padmarao Begari <[email protected]>
Reviewed-by: Simon Glass <[email protected]>
---
Changes in v2:
- Reuse the print_size() formatting through the new snprint_size()
  helper instead of open-coding the unit selection.
- Build the suffix with a single snprintf() instead of a chain of
  strlcat() calls into an intermediate buffer.
- Limit the device name to 64 instead of 128 characters and fall back to
  the capacity alone when the identification strings do not fit, so that
  the entries stay within an 80 column terminal.
- Document the limitation of the approach in the commit message.
---
 include/efi_loader.h      | 12 +++++--
 lib/efi_loader/efi_disk.c | 66 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 75 insertions(+), 3 deletions(-)

diff --git a/include/efi_loader.h b/include/efi_loader.h
index 3a4d502631c..2bf48d2e169 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -289,8 +289,16 @@ const char *__efi_nesting_dec(void);
 #define EFI_CACHELINE_SIZE 128
 #endif
 
-/* max bootmenu title size for volume selection */
-#define BOOTMENU_DEVICE_NAME_MAX 16
+/*
+ * Max bootmenu title size for volume selection.
+ *
+ * The menu entries are drawn with absolute cursor positioning starting at
+ * column 7, see bootmenu_print_entry() and eficonfig_print_entry(), and are
+ * not truncated. A title which does not fit into a line wraps and thereby
+ * corrupts the menu layout, so keep it short enough for a terminal with
+ * 80 columns.
+ */
+#define BOOTMENU_DEVICE_NAME_MAX 64
 
 /* Key identifying current memory map */
 extern efi_uintn_t efi_memory_map_key;
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index 4a3ace3a304..a9913ad33c4 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -8,6 +8,7 @@
 #define LOG_CATEGORY LOGC_EFI
 
 #include <blk.h>
+#include <display_options.h>
 #include <dm.h>
 #include <dm/device-internal.h>
 #include <dm/tag.h>
@@ -20,6 +21,8 @@
 #include <part.h>
 #include <malloc.h>
 
+#include <linux/string.h>
+
 struct efi_system_partition efi_system_partition = {
 	.uclass_id = UCLASS_INVALID,
 };
@@ -814,9 +817,68 @@ int efi_disk_remove(void *ctx, struct event *event)
 
 }
 
+/**
+ * efi_disk_append_detail() - append capacity and vendor info to a device label
+ *
+ * Appends a " (size, vendor product)" suffix to @buf when the block
+ * descriptor carries readable capacity or identification strings.
+ *
+ * @desc:	block device descriptor
+ * @buf:	label buffer to append to (already contains base name)
+ * @size:	total size of @buf in bytes
+ */
+static void efi_disk_append_detail(const struct blk_desc *desc,
+				   char *buf, int size)
+{
+	u64 capacity = (u64)desc->lba * desc->blksz;
+	char capacity_str[SIZE_STR_LEN];
+	char vendor_buf[BLK_VEN_SIZE + 1];
+	char product_buf[BLK_PRD_SIZE + 1];
+	char *vendor, *product;
+	int len = strlen(buf);
+	int ret;
+
+	capacity_str[0] = '\0';
+
+	if (capacity)
+		snprint_size(capacity_str, sizeof(capacity_str), capacity);
+
+	/*
+	 * Some drivers, e.g. usb_storage and nvme, do not strip the blanks the
+	 * identification strings are padded with. Use copies as strim()
+	 * modifies the string.
+	 */
+	strlcpy(vendor_buf, desc->vendor, sizeof(vendor_buf));
+	strlcpy(product_buf, desc->product, sizeof(product_buf));
+	vendor = strim(vendor_buf);
+	product = strim(product_buf);
+
+	if (!capacity_str[0] && !vendor[0] && !product[0])
+		return;
+
+	ret = snprintf(buf + len, size - len, " (%s%s%s%s%s)", capacity_str,
+		       capacity_str[0] && (vendor[0] || product[0]) ? ", " : "",
+		       vendor, vendor[0] && product[0] ? " " : "",
+		       product);
+	if (ret >= size - len) {
+		/*
+		 * The identification strings are too long to be shown in a
+		 * menu entry. Fall back to the capacity instead of displaying
+		 * a string cut in the middle.
+		 */
+		buf[len] = '\0';
+		if (capacity_str[0])
+			snprintf(buf + len, size - len, " (%s)", capacity_str);
+	}
+}
+
 /**
  * efi_disk_get_device_name() - get U-Boot device name associated with EFI handle
  *
+ * Fills @buf with a human-readable label such as "mmc 0 (7.5 GiB, SanDisk
+ * AJTD4R)". Capacity and trimmed vendor/product strings are appended when
+ * available.
+ *
  * @handle:	pointer to the EFI handle
  * @buf:	pointer to the buffer to store the string
  * @size:	size of buffer
@@ -834,7 +896,7 @@ efi_status_t efi_disk_get_device_name(const efi_handle_t handle, char *buf, int
 	bool is_partition = false;
 	struct disk_part *part_data;
 
-	if (!handle || !buf || !size)
+	if (!handle || !buf || size <= 0)
 		return EFI_INVALID_PARAMETER;
 
 	dev = handle->dev;
@@ -862,6 +924,8 @@ efi_status_t efi_disk_get_device_name(const efi_handle_t handle, char *buf, int
 	if (count < 0 || (count + 1) > size)
 		return EFI_INVALID_PARAMETER;
 
+	efi_disk_append_detail(desc, buf, size);
+
 	return EFI_SUCCESS;
 }
 
-- 
2.34.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.