From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DD3E53D5226 for ; Tue, 20 Jan 2026 21:55:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768946155; cv=none; b=kmk0XOv2Nym/qyqlqraevcBV4nxYDOp/Ljl38rdDRYc0oktnJ1jdmw3NOdQKuQkiTRsF1tfbF3QS1WHgJZY2KG9Z0NQjqeOFuTROm7rOQYjyqxkA25jebv/qMMzBKOtTHyuptQzWCXTYPfbtXx0yg4JaDc/wwZAGogwdi7CpuGE= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768946155; c=relaxed/simple; bh=hLiXf1GCL39VL0t91DzHAn49p8vLMoYkttzWAPXH1uM=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=XznuKAiXBY2f233UIRVt79Oe/mjbmTdecN893CDrZO2mdz82kMrxjA9hzQXv95HB2NUdpf1XdMZ3rSnwY1HH9pRySOvzsATCQOG88OwhBUyUp+UDUO4OX9jzKwbE9FVsbeO4oGxEs9oZ79YIFGnZ3Q4SYQkYZv05Gpt0qwA6mUA= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=p3ls9YTg; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="p3ls9YTg" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EA596C16AAE; Tue, 20 Jan 2026 21:55:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768946155; bh=hLiXf1GCL39VL0t91DzHAn49p8vLMoYkttzWAPXH1uM=; h=Date:Subject:To:Cc:References:From:In-Reply-To:From; b=p3ls9YTgXmTRnIfTtS73jxwNnq313h6qCORPnNe8CID6te64HlUg3O/B5zlK7r5Wk Mw9kGvaGMDZLMG9nrztWLqXBdxgZXHh5i1mPZP0qjoQ8ENTDEHCio6aa3TEU+1HQNt nI2MVejVHHHewt3kxAAxQrLWEcXJKuixO0zjbWgSDaKO/rhBMi2ZrYUH9Ag6+XhWmj RUQqQi0fg0tNgHrbWExirjKKytUtQjfmXkVqxJ1erU1QoktlxNC2tzPb649ReaFKSo CZeESAnGM1sRCoVIFGh4ezV1tSzmmzk8+sDngZbX10DMKyHVY99gBv2A3GjeogUSg1 RGvNCQ21Chs5A== Message-ID: <3f427986-1d7a-49b1-b661-e5004f1c7f0d@kernel.org> Date: Tue, 20 Jan 2026 15:55:54 -0600 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH v3 5/5] firmware: dmi: Read additional information when decoding DMI table To: Yazen Ghannam Cc: Jean Delvare , linux-kernel@vger.kernel.org, Borislav Petkov References: <20260110134835.1296600-1-superm1@kernel.org> <20260110134835.1296600-6-superm1@kernel.org> <20260116213032.GC471170@yaz-khff2.amd.com> <20260120214520.GA1753876@yaz-khff2.amd.com> Content-Language: en-US From: Mario Limonciello In-Reply-To: <20260120214520.GA1753876@yaz-khff2.amd.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit On 1/20/26 3:45 PM, Yazen Ghannam wrote: > On Fri, Jan 16, 2026 at 04:30:32PM -0500, Yazen Ghannam wrote: >> On Sat, Jan 10, 2026 at 07:48:34AM -0600, Mario Limonciello (AMD) wrote: >> > > [...] > >> ACPI tables do this a lot. So there are examples of iterating over >> variable length entries. > > Here's another implementation. What do you think? Oh you beat me to it, been busy this week. I do like that we can localize the printing code to amd.c. I'll test it and let you know if it works. If it does; I'll roll it into the series. > > Thanks, > Yazen > > > From c76f27e5d55570bb25bcefc3365fb3a1852bcad3 Mon Sep 17 00:00:00 2001 > From: Yazen Ghannam > Date: Mon, 19 Jan 2026 18:33:09 +0000 > Subject: [PATCH] x86/CPU/AMD: Print AGESA string from DMI additional > information entry > > Type 40 entries (Additional Information) are summarized in section 7.41 > as part of the SMBIOS specification. Generally, these entries aren't > interesting to save. > > However on some AMD Zen systems, the AGESA version is stored here. This > is useful to save to the kernel message logs for debugging. It can be > used to cross-reference issues. > > Implement an iterator for the Additional Information entries. Use this > to find and print the AGESA string. Do so in AMD code, since the use > case is AMD-specific. > > Originally-by: "Mario Limonciello (AMD)" > Signed-off-by: Yazen Ghannam > --- > arch/x86/kernel/cpu/amd.c | 53 +++++++++++++++++++++++++++++++++++++ > drivers/firmware/dmi_scan.c | 3 ++- > include/linux/dmi.h | 18 +++++++++++++ > 3 files changed, 73 insertions(+), 1 deletion(-) > > diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c > index bc94ff1e250a..aa04a27aeb10 100644 > --- a/arch/x86/kernel/cpu/amd.c > +++ b/arch/x86/kernel/cpu/amd.c > @@ -1,6 +1,7 @@ > // SPDX-License-Identifier: GPL-2.0-only > #include > #include > +#include > #include > #include > #include > @@ -1404,3 +1405,55 @@ static __init int print_s5_reset_status_mmio(void) > return 0; > } > late_initcall(print_s5_reset_status_mmio); > + > +static void __init amd_dmi_scan_additional(const struct dmi_header *d, void *p) > +{ > + struct dmi_a_info *info = (struct dmi_a_info *)d; > + void *next, *end; > + > + /* > + * DMI Additional Info table has a 'count' field. But it's not very > + * helpful since the entries are variable length. So don't use it. > + */ > + if (info->header.type != DMI_ENTRY_ADDITIONAL || > + info->header.length < DMI_A_INFO_MIN_SIZE) > + return; > + > + /* > + * Get the first entry. > + * The minimum table size guarantees at least one entry is present. > + */ > + next = (void *)(info + 1); > + end = (void *)info + info->header.length; > + > + do { > + struct dmi_a_info_entry *entry; > + const char *string_ptr; > + > + entry = (struct dmi_a_info_entry *)next; > + > + /* > + * Not much can be done to validate data. At least the entry > + * length shouldn't be 0. > + */ > + if (!entry->length) > + return; > + > + string_ptr = dmi_string_nosave(&info->header, entry->str_num); > + > + /* Only one AGESA string is expected. */ > + if (!strncmp(string_ptr, "AGESA", 5)) { > + pr_info("%s\n", string_ptr); > + break; > + } > + > + next += entry->length; > + } while (end - next >= DMI_A_INFO_ENT_MIN_SIZE); > +} > + > +static __init int print_dmi_agesa(void) > +{ > + dmi_walk(amd_dmi_scan_additional, NULL); > + return 0; > +} > +late_initcall(print_dmi_agesa); > diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c > index caa09ddf0dfa..8b196992618d 100644 > --- a/drivers/firmware/dmi_scan.c > +++ b/drivers/firmware/dmi_scan.c > @@ -47,7 +47,7 @@ static struct dmi_memdev_info { > static int dmi_memdev_nr; > static int dmi_memdev_populated_nr __initdata; > > -static const char * __init dmi_string_nosave(const struct dmi_header *dm, u8 s) > +const char *dmi_string_nosave(const struct dmi_header *dm, u8 s) > { > const u8 *bp = ((u8 *) dm) + dm->length; > const u8 *nsp; > @@ -66,6 +66,7 @@ static const char * __init dmi_string_nosave(const struct dmi_header *dm, u8 s) > > return dmi_empty_string; > } > +EXPORT_SYMBOL_GPL(dmi_string_nosave); > > static const char * __init dmi_string(const struct dmi_header *dm, u8 s) > { > diff --git a/include/linux/dmi.h b/include/linux/dmi.h > index 2eedf44e6801..48691d589b88 100644 > --- a/include/linux/dmi.h > +++ b/include/linux/dmi.h > @@ -91,6 +91,21 @@ struct dmi_device { > void *device_data; /* Type specific data */ > }; > > +#define DMI_A_INFO_ENT_MIN_SIZE 0x6 > +struct dmi_a_info_entry { > + u8 length; > + u16 handle; > + u8 offset; > + u8 str_num; > + u8 value[]; > +} __packed; > + > +#define DMI_A_INFO_MIN_SIZE 0xB > +struct dmi_a_info { > + struct dmi_header header; > + u8 count; > +} __packed; > + > #ifdef CONFIG_DMI > > struct dmi_dev_onboard { > @@ -120,6 +135,7 @@ extern void dmi_memdev_name(u16 handle, const char **bank, const char **device); > extern u64 dmi_memdev_size(u16 handle); > extern u8 dmi_memdev_type(u16 handle); > extern u16 dmi_memdev_handle(int slot); > +const char *dmi_string_nosave(const struct dmi_header *dm, u8 s); > > #else > > @@ -153,6 +169,8 @@ static inline u8 dmi_memdev_type(u16 handle) { return 0x0; } > static inline u16 dmi_memdev_handle(int slot) { return 0xffff; } > static inline const struct dmi_system_id * > dmi_first_match(const struct dmi_system_id *list) { return NULL; } > +static inline const char * > + dmi_string_nosave(const struct dmi_header *dm, u8 s) { return NULL; } > > #endif >