Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2170005/?format=api
{ "id": 2170005, "url": "http://patchwork.ozlabs.org/api/patches/2170005/?format=api", "web_url": "http://patchwork.ozlabs.org/project/uboot/patch/20251128163535.2301653-4-raymondmaoca@gmail.com/", "project": { "id": 18, "url": "http://patchwork.ozlabs.org/api/projects/18/?format=api", "name": "U-Boot", "link_name": "uboot", "list_id": "u-boot.lists.denx.de", "list_email": "u-boot@lists.denx.de", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20251128163535.2301653-4-raymondmaoca@gmail.com>", "list_archive_url": null, "date": "2025-11-28T16:35:20", "name": "[v5,3/6] smbios: add support for dynamic generation of Type 16 table", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "3d356747b933828ffcddd4d91e110616ff8b5f10", "submitter": { "id": 91989, "url": "http://patchwork.ozlabs.org/api/people/91989/?format=api", "name": "Raymond Mao", "email": "raymondmaoca@gmail.com" }, "delegate": { "id": 96103, "url": "http://patchwork.ozlabs.org/api/users/96103/?format=api", "username": "apalos", "first_name": "Ilias", "last_name": "Apalodimas", "email": "apalos@gmail.com" }, "mbox": "http://patchwork.ozlabs.org/project/uboot/patch/20251128163535.2301653-4-raymondmaoca@gmail.com/mbox/", "series": [ { "id": 483864, "url": "http://patchwork.ozlabs.org/api/series/483864/?format=api", "web_url": "http://patchwork.ozlabs.org/project/uboot/list/?series=483864", "date": "2025-11-28T16:35:17", "name": "Implement all missing SMBIOS types required by distro tooling", "version": 5, "mbox": "http://patchwork.ozlabs.org/series/483864/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2170005/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2170005/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<u-boot-bounces@lists.denx.de>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@legolas.ozlabs.org", "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20230601 header.b=TwN24xL+;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de\n (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de;\n envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org)", "phobos.denx.de;\n dmarc=pass (p=none dis=none) header.from=gmail.com", "phobos.denx.de;\n spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de", "phobos.denx.de;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.b=\"TwN24xL+\";\n\tdkim-atps=neutral", "phobos.denx.de;\n dmarc=pass (p=none dis=none) header.from=gmail.com", "phobos.denx.de;\n spf=pass smtp.mailfrom=raymondmaoca@gmail.com" ], "Received": [ "from phobos.denx.de (phobos.denx.de\n [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange X25519 server-signature ECDSA (secp384r1))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4dHzSz0L7wz1yDd\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 29 Nov 2025 03:36:19 +1100 (AEDT)", "from h2850616.stratoserver.net (localhost [IPv6:::1])\n\tby phobos.denx.de (Postfix) with ESMTP id 5E52C83AED;\n\tFri, 28 Nov 2025 17:36:11 +0100 (CET)", "by phobos.denx.de (Postfix, from userid 109)\n id AA3E383B03; Fri, 28 Nov 2025 17:36:10 +0100 (CET)", "from mail-qk1-x729.google.com (mail-qk1-x729.google.com\n [IPv6:2607:f8b0:4864:20::729])\n (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits))\n (No client certificate requested)\n by phobos.denx.de (Postfix) with ESMTPS id 1CF5F838FA\n for <u-boot@lists.denx.de>; Fri, 28 Nov 2025 17:36:08 +0100 (CET)", "by mail-qk1-x729.google.com with SMTP id\n af79cd13be357-8b31a665ba5so176175685a.2\n for <u-boot@lists.denx.de>; Fri, 28 Nov 2025 08:36:08 -0800 (PST)", "from ubuntu.localdomain ([216.58.22.99])\n by smtp.gmail.com with ESMTPSA id\n af79cd13be357-8b52a1b75a9sm331227985a.25.2025.11.28.08.36.05\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Fri, 28 Nov 2025 08:36:06 -0800 (PST)" ], "X-Spam-Checker-Version": "SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de", "X-Spam-Level": "", "X-Spam-Status": "No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED,\n DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,\n RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE,SPF_PASS autolearn=ham\n autolearn_force=no version=3.4.2", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20230601; t=1764347767; x=1764952567; darn=lists.denx.de;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=nkf8iSJWvvAhqtMQ94JgJ3+La+bbJr+Yvp2ook6aQxs=;\n b=TwN24xL+TU3cC6ZU+IMqGGypewvPEQ6ungA2jxvIoLnvX927bni+XrJ5YHCd7k8Pwe\n S5TPoiwKQE6uEJml8LOX6OzkJEg1K8oiVf4MvJPeRoDBADIXpi0T2HoAE93BJmPUdxfO\n f7hCEwuYXimy5XaTt6hxyz0v5DL1l8khy7ACvGLAdC/+7x9wqjfYSB+TEQdAXwZqusKR\n jGegDTJU8EaGKC15am7SVNjcO+neELglc/YcjQtSxzegTWHgrDkKXzzYRps6UVCsIr7X\n DpLaTdPh8pcDu/A85mLm4++HlKGlpeIgR8oKzD2/vKjXeZEQB1na9p0UQ75qVI82h769\n i6ZQ==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1764347767; x=1764952567;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=nkf8iSJWvvAhqtMQ94JgJ3+La+bbJr+Yvp2ook6aQxs=;\n b=R0JXu1LcGrUk0mksC16+P0wYppISftY8/Fa9fIU+fXoBHuZgeMO9qwYAqchpLWu6a6\n ttdoUWwyUxyzLG2lCFvlkmRIIV9KLtvH6zi5/WOiSNiXjbTuGXU7hJZKhiKGpwlAVks3\n Sy0LytdTiWVZcRhRM8BMtN/vXwidwCNBkYWn9b1CzOIy6nl7WeOXpFaLEzLcWjkeoxBw\n 1VJWY6Ljzpy+oJJWYIyXeO5hdVAYuU8YFhjw7SifERbYgy7sIO5LKTutkcZZsrSkprut\n bGjvt7jXbwJeRUHCDP/sK84wzPi9bp7OZ/iMRpvLdGIQ7gXNpLMXL+C+JRxIe8wVTwFj\n 3jLg==", "X-Gm-Message-State": "AOJu0Ywh4t1KgPHGUEL23WwUDLCl26vyc+USNIOwxI85IPMEtfX32Xj6\n JOTpMQ6W/d/RpsRvbr4oGzwDa9lrXBRF70yG6z3LZZ8tz4x/59vmVmmD0IpekXI+y1c=", "X-Gm-Gg": "ASbGnct/5eMlXSXMP2j1rKDC8bjHmtJvRYTxfU5Gwji3+K/F5wyeq/LWAjTm68f9/PF\n AGd3Dpnxe0x1JXHr7DS++4oI82JP8eIw1aPCyf/ICpEzkedzuceLcCrN43z/cpM5upd/IpTKevF\n NUoVSKQtnERcm+0WtzcjK45Ra2fwnRKZ/Sfj8aQhk4PXdxB3xM7u6Xv2FEOSCjyTrGOIS3RMsET\n peekzhihDkwy2580EwMpiQhpamAkivGDN/YbyS2zbDhbgERz4n6JyFi4L+ruJrrHyRJ+oeZslxj\n 0HkrlBoeLsfKybxiYkqHK96bYrHTlqb9t06SwS8G+pLICi8f1k/UgTmg26WEoLrgRrpu/dL713f\n aZTn8ZHUMUWi4VeorUtu8GnVj4ayvVybvherkJPP/OjvgrgzQQGEmPt3spnvhm86XVz62M48bRa\n 23khB4jvykZWDb/jEsMHa1lqq43lBD7iA=", "X-Google-Smtp-Source": "\n AGHT+IGFdjTEuDXZQzw6OjiUYH1OBZoLd9O4arsJoXehvjxqWBmZ3s3TFcyu3PQNZIjn37+XUmyIJg==", "X-Received": "by 2002:a05:620a:3188:b0:811:3f8a:24a6 with SMTP id\n af79cd13be357-8b4ebdae723mr2111362385a.53.1764347766595;\n Fri, 28 Nov 2025 08:36:06 -0800 (PST)", "From": "Raymond Mao <raymondmaoca@gmail.com>", "To": "u-boot@lists.denx.de", "Cc": "Raymond Mao <raymondmaoca@gmail.com>, Tom Rini <trini@konsulko.com>,\n Heinrich Schuchardt <xypron.glpk@gmx.de>,\n Mark Kettenis <kettenis@openbsd.org>,\n Baocheng Su <baocheng.su@siemens.com>, Jan Kiszka <jan.kiszka@siemens.com>,\n Li Hua Qian <huaqian.li@siemens.com>,\n Samuel Holland <samuel.holland@sifive.com>,\n Ilias Apalodimas <ilias.apalodimas@linaro.org>, Peng Fan <peng.fan@nxp.com>", "Subject": "[PATCH v5 3/6] smbios: add support for dynamic generation of Type 16\n table", "Date": "Fri, 28 Nov 2025 08:35:20 -0800", "Message-Id": "<20251128163535.2301653-4-raymondmaoca@gmail.com>", "X-Mailer": "git-send-email 2.25.1", "In-Reply-To": "<20251128163535.2301653-1-raymondmaoca@gmail.com>", "References": "<20251128163535.2301653-1-raymondmaoca@gmail.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "X-BeenThere": "u-boot@lists.denx.de", "X-Mailman-Version": "2.1.39", "Precedence": "list", "List-Id": "U-Boot discussion <u-boot.lists.denx.de>", "List-Unsubscribe": "<https://lists.denx.de/options/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=unsubscribe>", "List-Archive": "<https://lists.denx.de/pipermail/u-boot/>", "List-Post": "<mailto:u-boot@lists.denx.de>", "List-Help": "<mailto:u-boot-request@lists.denx.de?subject=help>", "List-Subscribe": "<https://lists.denx.de/listinfo/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=subscribe>", "Errors-To": "u-boot-bounces@lists.denx.de", "Sender": "\"U-Boot\" <u-boot-bounces@lists.denx.de>", "X-Virus-Scanned": "clamav-milter 0.103.8 at phobos.denx.de", "X-Virus-Status": "Clean" }, "content": "This commit implements SMBIOS Type 16 (Physical Memory Array)\ngeneration with a hybrid approach supporting both:\n\n1. Explicit definition via Device Tree 'smbios' node:\n Child node under '/smbios/smbios/memory-array' will be used to\n populate as individual Type 16 structure directly.\n - Properties follow SMBIOS field names with lowercase letters and\n hyphen-separated words (e.g., 'memory-error-correction',\n 'maximum-capacity', 'extended-maximum-capacity', etc.).\n - This method supports precise platform-defined overrides and system\n descriptions.\n\n2. Fallback to automatic DT-based discovery:\n If child node under '/smbios/smbios/memory-array' does not exist,\n the implementation will:\n - Scan all top-level 'memory@' nodes to populate Type 16 structure with\n inferred size and location data.\n - Scan nodes named or marked as 'memory-controller' and parse\n associated 'dimm@' subnodes (if present) to extract DIMM sizes and\n map them accordingly.\n\nThis dual-mode support enables flexible firmware SMBIOS reporting while\naligning with spec-compliant naming and runtime-detected memory topology.\n\nType 16 support is under GENERATE_SMBIOS_TABLE_VERBOSE to avoid\nincreasing rom size for those platforms which only require basic SMBIOS\nsupport.\n\nSigned-off-by: Raymond Mao <raymondmaoca@gmail.com>\n---\nChanges in v4:\n- Initial patch.\nChanges in v5:\n- None.\n\n arch/arm/dts/smbios_generic.dtsi | 3 +\n cmd/smbios.c | 46 +++++\n drivers/sysinfo/smbios.c | 5 +\n include/smbios.h | 18 ++\n include/smbios_def.h | 29 ++++\n include/sysinfo.h | 4 +\n lib/smbios.c | 282 +++++++++++++++++++++++++++++++\n 7 files changed, 387 insertions(+)", "diff": "diff --git a/arch/arm/dts/smbios_generic.dtsi b/arch/arm/dts/smbios_generic.dtsi\nindex 4463dade217..1a9adfaa409 100644\n--- a/arch/arm/dts/smbios_generic.dtsi\n+++ b/arch/arm/dts/smbios_generic.dtsi\n@@ -80,6 +80,9 @@\n \n \t\t\tsystem-slot {\n \t\t\t};\n+\n+\t\t\tmemory-array {\n+\t\t\t};\n \t\t};\n \t};\n };\ndiff --git a/cmd/smbios.c b/cmd/smbios.c\nindex f9b62e66229..3f7dd21f92e 100644\n--- a/cmd/smbios.c\n+++ b/cmd/smbios.c\n@@ -168,6 +168,32 @@ static const struct str_lookup_table slot_length_strings[] = {\n \t{ SMBIOS_SYSSLOT_LENG_3_5INDRV,\t\"3.5 inch drive form factor\" },\n };\n \n+static const struct str_lookup_table ma_location_strings[] = {\n+\t{ SMBIOS_MA_LOCATION_OTHER,\t\t\"Other\" },\n+\t{ SMBIOS_MA_LOCATION_UNKNOWN,\t\t\"Unknown\" },\n+\t{ SMBIOS_MA_LOCATION_MOTHERBOARD,\t\"System board or motherboard\" },\n+};\n+\n+static const struct str_lookup_table ma_use_strings[] = {\n+\t{ SMBIOS_MA_USE_OTHER,\t\t\"Other\" },\n+\t{ SMBIOS_MA_USE_UNKNOWN,\t\"Unknown\" },\n+\t{ SMBIOS_MA_USE_SYSTEM,\t\t\"System memory\" },\n+\t{ SMBIOS_MA_USE_VIDEO,\t\t\"Video memory\" },\n+\t{ SMBIOS_MA_USE_FLASH,\t\t\"Flash memory\" },\n+\t{ SMBIOS_MA_USE_NVRAM,\t\t\"Non-volatile RAM\" },\n+\t{ SMBIOS_MA_USE_CACHE,\t\t\"Cache memory\" },\n+};\n+\n+static const struct str_lookup_table ma_err_corr_strings[] = {\n+\t{ SMBIOS_MA_ERRCORR_OTHER,\t\"Other\" },\n+\t{ SMBIOS_MA_ERRCORR_UNKNOWN,\t\"Unknown\" },\n+\t{ SMBIOS_MA_ERRCORR_NONE,\t\"None\" },\n+\t{ SMBIOS_MA_ERRCORR_PARITY,\t\"Parity\" },\n+\t{ SMBIOS_MA_ERRCORR_SBITECC,\t\"Single-bit ECC\" },\n+\t{ SMBIOS_MA_ERRCORR_MBITECC,\t\"Multi-bit ECC\" },\n+\t{ SMBIOS_MA_ERRCORR_CRC,\t\"CRC\" },\n+};\n+\n /**\n * smbios_get_string() - get SMBIOS string from table\n *\n@@ -514,6 +540,23 @@ static void smbios_print_type9(struct smbios_type9 *table)\n \tprintf(\"\\tSlot Height: 0x%04x\\n\", *addr);\n }\n \n+static void smbios_print_type16(struct smbios_type16 *table)\n+{\n+\tprintf(\"Physical Memory Array:\\n\");\n+\tsmbios_print_lookup_str(ma_location_strings, table->location,\n+\t\t\t\tARRAY_SIZE(ma_location_strings), \"Location\");\n+\tsmbios_print_lookup_str(ma_use_strings, table->use,\n+\t\t\t\tARRAY_SIZE(ma_use_strings), \"Use\");\n+\tsmbios_print_lookup_str(ma_err_corr_strings, table->mem_err_corr,\n+\t\t\t\tARRAY_SIZE(ma_err_corr_strings),\n+\t\t\t\t\"Memory Error Correction\");\n+\tprintf(\"\\tMaximum Capacity: 0x%08x\\n\", table->max_cap);\n+\tprintf(\"\\tMemory Error Information Handle: 0x%04x\\n\",\n+\t table->mem_err_info_hdl);\n+\tprintf(\"\\tNumber of Memory Devices: 0x%04x\\n\", table->num_of_mem_dev);\n+\tprintf(\"\\tExtended Maximum Capacity: 0x%016llx\\n\", table->ext_max_cap);\n+}\n+\n static void smbios_print_type127(struct smbios_type127 *table)\n {\n \tprintf(\"End Of Table\\n\");\n@@ -596,6 +639,9 @@ static int do_smbios(struct cmd_tbl *cmdtp, int flag, int argc,\n \t\tcase SMBIOS_SYSTEM_SLOTS:\n \t\t\tsmbios_print_type9((struct smbios_type9 *)pos);\n \t\t\tbreak;\n+\t\tcase SMBIOS_PHYS_MEMORY_ARRAY:\n+\t\t\tsmbios_print_type16((struct smbios_type16 *)pos);\n+\t\t\tbreak;\n \t\tcase SMBIOS_END_OF_TABLE:\n \t\t\tsmbios_print_type127((struct smbios_type127 *)pos);\n \t\t\tbreak;\ndiff --git a/drivers/sysinfo/smbios.c b/drivers/sysinfo/smbios.c\nindex 99104274f72..ff5873c940e 100644\n--- a/drivers/sysinfo/smbios.c\n+++ b/drivers/sysinfo/smbios.c\n@@ -24,6 +24,7 @@ struct sysinfo_plat_priv {\n \tstruct smbios_type7 t7[SYSINFO_CACHE_LVL_MAX];\n \tu16 cache_handles[SYSINFO_CACHE_LVL_MAX];\n \tu8 cache_level;\n+\tu16 marray_handles[SYSINFO_MEM_HANDLE_MAX];\n };\n \n static void smbios_cache_info_dump(struct smbios_type7 *cache_info)\n@@ -165,6 +166,10 @@ static int sysinfo_plat_get_data(struct udevice *dev, int id, void **buf,\n \t\t*buf = &priv->cache_handles[0];\n \t\t*size = sizeof(priv->cache_handles);\n \t\tbreak;\n+\tcase SYSID_SM_MEMARRAY_HANDLE:\n+\t\t*buf = &priv->marray_handles[0];\n+\t\t*size = sizeof(priv->marray_handles);\n+\t\tbreak;\n \tdefault:\n \t\treturn -EOPNOTSUPP;\n \t}\ndiff --git a/include/smbios.h b/include/smbios.h\nindex d885285ea41..16438c059c7 100644\n--- a/include/smbios.h\n+++ b/include/smbios.h\n@@ -309,6 +309,24 @@ struct __packed smbios_type9 {\n \tchar eos[SMBIOS_STRUCT_EOS_BYTES];\n };\n \n+enum {\n+\tSMBIOS_MEM_NONE = 0,\n+\tSMBIOS_MEM_CUSTOM = 1,\n+\tSMBIOS_MEM_FDT_MEM_NODE = 2,\n+\tSMBIOS_MEM_FDT_MEMCON_NODE = 3\n+};\n+\n+struct __packed smbios_type16 {\n+\tstruct smbios_header hdr;\n+\tu8 location;\n+\tu8 use;\n+\tu8 mem_err_corr;\n+\tu32 max_cap;\n+\tu16 mem_err_info_hdl;\n+\tu16 num_of_mem_dev;\n+\tu64 ext_max_cap;\n+\tchar eos[SMBIOS_STRUCT_EOS_BYTES];\n+};\n struct __packed smbios_type32 {\n \tu8 type;\n \tu8 length;\ndiff --git a/include/smbios_def.h b/include/smbios_def.h\nindex ef9cb02ed25..c6850a5d6f5 100644\n--- a/include/smbios_def.h\n+++ b/include/smbios_def.h\n@@ -280,4 +280,33 @@\n /* Slot segment group number */\n #define SMBIOS_SYSSLOT_SGGNUM_UND\t0\n \n+/* Physical Memory Array */\n+\n+/* Location */\n+#define SMBIOS_MA_LOCATION_OTHER\t1\n+#define SMBIOS_MA_LOCATION_UNKNOWN\t2\n+#define SMBIOS_MA_LOCATION_MOTHERBOARD\t3\n+\n+/* Use */\n+#define SMBIOS_MA_USE_OTHER\t\t1\n+#define SMBIOS_MA_USE_UNKNOWN\t\t2\n+#define SMBIOS_MA_USE_SYSTEM\t\t3\n+#define SMBIOS_MA_USE_VIDEO\t\t4\n+#define SMBIOS_MA_USE_FLASH\t\t5\n+#define SMBIOS_MA_USE_NVRAM\t\t6\n+#define SMBIOS_MA_USE_CACHE\t\t7\n+\n+/* Error Correction Type */\n+#define SMBIOS_MA_ERRCORR_OTHER\t\t1\n+#define SMBIOS_MA_ERRCORR_UNKNOWN\t2\n+#define SMBIOS_MA_ERRCORR_NONE\t\t3\n+#define SMBIOS_MA_ERRCORR_PARITY\t4\n+#define SMBIOS_MA_ERRCORR_SBITECC\t5\n+#define SMBIOS_MA_ERRCORR_MBITECC\t6\n+#define SMBIOS_MA_ERRCORR_CRC\t\t7\n+\n+/* Error Information Handle */\n+#define SMBIOS_MA_ERRINFO_NONE\t\t0xFFFE\n+#define SMBIOS_MA_ERRINFO_NOERR\t\t0xFFFF\n+\n #endif /* _SMBIOS_DEF_H_ */\ndiff --git a/include/sysinfo.h b/include/sysinfo.h\nindex e87cf969fcd..54eb64a204a 100644\n--- a/include/sysinfo.h\n+++ b/include/sysinfo.h\n@@ -12,6 +12,7 @@\n struct udevice;\n \n #define SYSINFO_CACHE_LVL_MAX 3\n+#define SYSINFO_MEM_HANDLE_MAX 8\n \n /*\n * This uclass encapsulates hardware methods to gather information about a\n@@ -149,6 +150,9 @@ enum sysinfo_id {\n \tSYSID_SM_CACHE_INFO_END =\n \t\tSYSID_SM_CACHE_INST_SIZE2 + SYSINFO_CACHE_LVL_MAX - 1,\n \n+\t/* Memory Array (Type 16) */\n+\tSYSID_SM_MEMARRAY_HANDLE,\n+\n \t/* For show_board_info() */\n \tSYSID_BOARD_MODEL,\n \tSYSID_BOARD_MANUFACTURER,\ndiff --git a/lib/smbios.c b/lib/smbios.c\nindex caeb309294d..27c9c975cf2 100644\n--- a/lib/smbios.c\n+++ b/lib/smbios.c\n@@ -290,6 +290,49 @@ static int smbios_get_val_si(struct smbios_ctx * __maybe_unused ctx,\n \treturn val_def;\n }\n \n+#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE)\n+static u64 smbios_get_u64_si(struct smbios_ctx * __maybe_unused ctx,\n+\t\t\t const char * __maybe_unused prop,\n+\t\t\t int __maybe_unused sysinfo_id, u64 val_def)\n+{\n+\tsize_t len;\n+\tvoid *data;\n+\tconst fdt32_t *prop_val;\n+\tint prop_len;\n+\tu64 val = 0;\n+\n+\tif (!ctx->dev)\n+\t\treturn val_def;\n+\n+\tif (!sysinfo_get_data(ctx->dev, sysinfo_id, &data, &len))\n+\t\treturn *((u64 *)data);\n+\n+\tif (!IS_ENABLED(CONFIG_OF_CONTROL) || !prop || !ofnode_valid(ctx->node))\n+\t\treturn val_def;\n+\n+\tprop_val = ofnode_read_prop(ctx->node, prop, &prop_len);\n+\tif (!prop_val || prop_len < sizeof(fdt32_t) ||\n+\t prop_len % sizeof(fdt32_t)) {\n+\t\t/*\n+\t\t * If the node or property is not valid fallback and try the root\n+\t\t */\n+\t\tprop_val = ofnode_read_prop(ofnode_root(), prop, &prop_len);\n+\t\tif (!prop_val || prop_len < sizeof(fdt32_t) ||\n+\t\t prop_len % sizeof(fdt32_t))\n+\t\t\treturn val_def;\n+\t}\n+\n+\t/* 64-bit: <hi lo> or 32-bit */\n+\tif (prop_len >= sizeof(fdt32_t) * 2) {\n+\t\tval = ((u64)fdt32_to_cpu(prop_val[0]) << 32) |\n+\t\t fdt32_to_cpu(prop_val[1]);\n+\t} else {\n+\t\tval = fdt32_to_cpu(prop_val[0]);\n+\t}\n+\treturn val;\n+}\n+#endif\n+\n /**\n * smbios_add_prop_si() - Add a property from the devicetree or sysinfo\n *\n@@ -1151,6 +1194,244 @@ static int smbios_write_type9(ulong *current, int *handle,\n \treturn len;\n }\n \n+static u64 smbios_pop_size_from_memory_node(ofnode node)\n+{\n+\tconst fdt32_t *reg;\n+\tint len;\n+\tu64 size_bytes;\n+\n+\t/* Read property 'reg' from the node */\n+\treg = ofnode_read_prop(node, \"reg\", &len);\n+\tif (!reg || len < sizeof(fdt32_t) * 4 || len % sizeof(fdt32_t))\n+\t\treturn 0;\n+\n+\t/* Combine hi/lo for size (typically 64-bit) */\n+\tsize_bytes = ((u64)fdt32_to_cpu(reg[2]) << 32) | fdt32_to_cpu(reg[3]);\n+\n+\treturn size_bytes;\n+}\n+\n+static int\n+smbios_write_type16_sum_memory_nodes(ulong *current, int handle,\n+\t\t\t\t struct smbios_ctx *ctx, u16 cnt, u64 size)\n+{\n+\tstruct smbios_type16 *t;\n+\tint len = sizeof(*t);\n+\tu8 *eos_addr;\n+\tvoid *hdl;\n+\tsize_t hdl_size;\n+\n+\tt = map_sysmem(*current, len);\n+\tmemset(t, 0, len);\n+\n+\tfill_smbios_header(t, SMBIOS_PHYS_MEMORY_ARRAY, len, handle);\n+\n+\t/* eos is at the end of the structure */\n+\teos_addr = (u8 *)t + len - sizeof(t->eos);\n+\tsmbios_set_eos(ctx, eos_addr);\n+\n+\t/* default attributes */\n+\tt->location = SMBIOS_MA_LOCATION_MOTHERBOARD;\n+\tt->use = SMBIOS_MA_USE_SYSTEM;\n+\tt->mem_err_corr = SMBIOS_MA_ERRCORR_UNKNOWN;\n+\tt->mem_err_info_hdl = SMBIOS_MA_ERRINFO_NONE;\n+\tt->num_of_mem_dev = cnt;\n+\n+\t/* Use extended field */\n+\tt->max_cap = cpu_to_le32(0x80000000);\n+\tt->ext_max_cap = cpu_to_le64(size >> 10); /* In KB */\n+\n+\t/* Save the memory array handles */\n+\tif (!sysinfo_get_data(ctx->dev, SYSID_SM_MEMARRAY_HANDLE, &hdl,\n+\t\t\t &hdl_size) &&\n+\t hdl_size == SYSINFO_MEM_HANDLE_MAX * sizeof(u16))\n+\t\t*((u16 *)hdl) = handle;\n+\n+\tlen = t->hdr.length + smbios_string_table_len(ctx);\n+\t*current += len;\n+\tunmap_sysmem(t);\n+\n+\treturn len;\n+}\n+\n+static void\n+smbios_pop_type16_from_memcontroller_node(ofnode node, struct smbios_type16 *t)\n+{\n+\tofnode child;\n+\tint count = 0;\n+\tu64 total = 0;\n+\n+\t/* default attributes */\n+\tt->location = SMBIOS_MA_LOCATION_MOTHERBOARD;\n+\tt->use = SMBIOS_MA_USE_SYSTEM;\n+\tt->mem_err_info_hdl = SMBIOS_MA_ERRINFO_NONE;\n+\n+\t/* Check custom property 'ecc-enabled' */\n+\tif (ofnode_read_bool(node, \"ecc-enabled\"))\n+\t\tt->mem_err_corr = SMBIOS_MA_ERRCORR_SBITECC;\n+\telse\n+\t\tt->mem_err_corr = SMBIOS_MA_ERRCORR_UNKNOWN;\n+\n+\t/* Read subnodes with 'size' property */\n+\tfor (child = ofnode_first_subnode(node); ofnode_valid(child);\n+\t child = ofnode_next_subnode(child)) {\n+\t\tu64 sz = 0;\n+\t\tconst fdt32_t *size;\n+\t\tint len;\n+\n+\t\tsize = ofnode_read_prop(child, \"size\", &len);\n+\t\tif (!size || len < sizeof(fdt32_t) || len % sizeof(fdt32_t))\n+\t\t\tcontinue;\n+\n+\t\t/* 64-bit size: <hi lo> or 32-bit size */\n+\t\tif (len >= sizeof(fdt32_t) * 2)\n+\t\t\tsz = ((u64)fdt32_to_cpu(size[0]) << 32) |\n+\t\t\t fdt32_to_cpu(size[1]);\n+\t\telse\n+\t\t\tsz = fdt32_to_cpu(size[0]);\n+\n+\t\tcount++;\n+\t\ttotal += sz;\n+\t}\n+\n+\t/*\n+\t * Number of memory devices associated with this array\n+\t * (i.e., how many Type17 entries link to this Type16 array)\n+\t */\n+\tt->num_of_mem_dev = count;\n+\n+\t/* Use extended field */\n+\tt->max_cap = cpu_to_le32(0x80000000);\n+\tt->ext_max_cap = cpu_to_le64(total >> 10); /* In KB */\n+}\n+\n+static void smbios_pop_type16_si(struct smbios_ctx *ctx,\n+\t\t\t\t struct smbios_type16 *t)\n+{\n+\tt->location = smbios_get_val_si(ctx, \"location\", SYSID_NONE,\n+\t\t\t\t\tSMBIOS_MA_LOCATION_UNKNOWN);\n+\tt->use = smbios_get_val_si(ctx, \"use\", SYSID_NONE,\n+\t\t\t\t SMBIOS_MA_USE_UNKNOWN);\n+\tt->mem_err_corr = smbios_get_val_si(ctx, \"memory-error-correction\", SYSID_NONE,\n+\t\t\t\t\t SMBIOS_MA_ERRCORR_UNKNOWN);\n+\tt->max_cap = smbios_get_val_si(ctx, \"maximum-capacity\", SYSID_NONE, 0);\n+\tt->mem_err_info_hdl = smbios_get_val_si(ctx, \"memory-error-information-handle\",\n+\t\t\t\t\t\tSYSID_NONE, SMBIOS_MA_ERRINFO_NONE);\n+\tt->num_of_mem_dev = smbios_get_val_si(ctx, \"number-of-memory-devices\", SYSID_NONE, 1);\n+\tt->ext_max_cap = smbios_get_u64_si(ctx, \"extended-maximum-capacity\", SYSID_NONE, 0);\n+}\n+\n+static int smbios_write_type16_1array(ulong *current, int handle,\n+\t\t\t\t struct smbios_ctx *ctx, int idx,\n+\t\t\t\t int type)\n+{\n+\tstruct smbios_type16 *t;\n+\tint len = sizeof(*t);\n+\tu8 *eos_addr;\n+\tvoid *hdl;\n+\tsize_t hdl_size;\n+\n+\tt = map_sysmem(*current, len);\n+\tmemset(t, 0, len);\n+\n+\tfill_smbios_header(t, SMBIOS_PHYS_MEMORY_ARRAY, len, handle);\n+\n+\t/* eos is at the end of the structure */\n+\teos_addr = (u8 *)t + len - sizeof(t->eos);\n+\tsmbios_set_eos(ctx, eos_addr);\n+\n+\tif (type == SMBIOS_MEM_CUSTOM)\n+\t\tsmbios_pop_type16_si(ctx, t);\n+\telse if (type == SMBIOS_MEM_FDT_MEMCON_NODE)\n+\t\tsmbios_pop_type16_from_memcontroller_node(ctx->node, t);\n+\n+\t/* Save the memory array handles */\n+\tif (!sysinfo_get_data(ctx->dev, SYSID_SM_MEMARRAY_HANDLE, &hdl,\n+\t\t\t &hdl_size) &&\n+\t hdl_size == SYSINFO_MEM_HANDLE_MAX * sizeof(u16))\n+\t\t*((u16 *)hdl + idx) = handle;\n+\n+\tlen = t->hdr.length + smbios_string_table_len(ctx);\n+\t*current += len;\n+\tunmap_sysmem(t);\n+\n+\treturn len;\n+}\n+\n+static int smbios_write_type16(ulong *current, int *handle,\n+\t\t\t struct smbios_ctx *ctx)\n+{\n+\tint len;\n+\tstruct smbios_ctx ctx_bak;\n+\tofnode child;\n+\tint idx;\n+\tu64 total = 0;\n+\tint count = 0;\n+\tint hdl_base = *handle;\n+\n+\tif (!IS_ENABLED(CONFIG_OF_CONTROL))\n+\t\treturn 0;\t/* Error, return 0-length */\n+\n+\t/* Step 1: Scan any subnode exists under 'memory-array' */\n+\tlen = smbios_scan_subnodes(current, ctx, handle,\n+\t\t\t\t smbios_write_type16_1array,\n+\t\t\t\t SMBIOS_MEM_CUSTOM);\n+\tif (len)\n+\t\treturn len;\n+\n+\t/* Step 2: Scan 'memory' node from the entire FDT */\n+\tfor (child = ofnode_first_subnode(ofnode_root());\n+\t ofnode_valid(child); child = ofnode_next_subnode(child)) {\n+\t\tconst char *str;\n+\n+\t\t/* Look up for 'device_type = \"memory\"' */\n+\t\tstr = ofnode_read_string(child, \"device_type\");\n+\t\tif (str && !strcmp(str, \"memory\")) {\n+\t\t\tcount++;\n+\t\t\ttotal += smbios_pop_size_from_memory_node(child);\n+\t\t}\n+\t}\n+\t/*\n+\t * Generate one type16 instance for all 'memory' nodes,\n+\t * use idx=0 implicitly\n+\t */\n+\tif (count)\n+\t\tlen += smbios_write_type16_sum_memory_nodes(current, *handle,\n+\t\t\t\t\t\t\t ctx, count, total);\n+\n+\t/* Step 3: Scan 'memory-controller' node from the entire FDT */\n+\t/* idx starts from 1 */\n+\tmemcpy(&ctx_bak, ctx, sizeof(ctx_bak));\n+\tfor (idx = 1, child = ofnode_first_subnode(ofnode_root());\n+\t ofnode_valid(child); child = ofnode_next_subnode(child)) {\n+\t\tconst char *compat;\n+\t\tconst char *name;\n+\n+\t\t/*\n+\t\t * Look up for node with name or property 'compatible'\n+\t\t * containing 'memory-controller'.\n+\t\t */\n+\t\tname = ofnode_get_name(child);\n+\t\tcompat = ofnode_read_string(child, \"compatible\");\n+\t\tif ((!compat || !strstr(compat, \"memory-controller\")) &&\n+\t\t (!name || !strstr(name, \"memory-controller\")))\n+\t\t\tcontinue;\n+\n+\t\t*handle = hdl_base + idx;\n+\t\tctx->node = child;\n+\t\t/*\n+\t\t * Generate one type16 instance for each 'memory-controller'\n+\t\t * node, sum the 'size' of all subnodes.\n+\t\t */\n+\t\tlen += smbios_write_type16_1array(current, *handle, ctx, idx,\n+\t\t\t\t\t\t SMBIOS_MEM_FDT_MEMCON_NODE);\n+\t\tidx++;\n+\t\tmemcpy(ctx, &ctx_bak, sizeof(*ctx));\n+\t}\n+\n+\treturn len;\n+}\n+\n #endif /* #if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE) */\n \n static int smbios_write_type32(ulong *current, int *handle,\n@@ -1199,6 +1480,7 @@ static struct smbios_write_method smbios_write_funcs[] = {\n \t{ smbios_write_type4, \"processor\"},\n #if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE)\n \t{ smbios_write_type9, \"system-slot\"},\n+\t{ smbios_write_type16, \"memory-array\"},\n #endif\n \t{ smbios_write_type32, },\n \t{ smbios_write_type127 },\n", "prefixes": [ "v5", "3/6" ] }