git: f840492b5b0d - main - efidev: add support for memory attribute
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 22 Jul 2025 04:45:52 UTC
The branch main has been updated by aokblast:
URL: https://cgit.FreeBSD.org/src/commit/?id=f840492b5b0d5c9e7d6d7d7dc25c260bc4d63ba2
commit f840492b5b0d5c9e7d6d7d7dc25c260bc4d63ba2
Author: ShengYi Hung <aokblast@FreeBSD.org>
AuthorDate: 2025-07-19 17:07:27 +0000
Commit: ShengYi Hung <aokblast@FreeBSD.org>
CommitDate: 2025-07-22 04:45:29 +0000
efidev: add support for memory attribute
The EFI_PROPERTIES_TABLE has been deprecated in the UEFI specification.
It is now replaced by the EFI_MEMORY_ATTRIBUTES_TABLE, which provides
a new header and data format for describing memory region attributes.
Reviewed by: imp
Approved by: markj (mentor)
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D49998
---
sys/dev/efidev/efirt.c | 42 +++++++++++++++++++++++++++++++++++--
sys/modules/efirt/Makefile | 2 +-
sys/sys/efi.h | 18 ++++++++++++++++
usr.sbin/efitable/efitable.8 | 2 ++
usr.sbin/efitable/efitable.c | 50 +++++++++++++++++++++++++++++++++++++++++++-
5 files changed, 110 insertions(+), 4 deletions(-)
diff --git a/sys/dev/efidev/efirt.c b/sys/dev/efidev/efirt.c
index b0fa33daeca7..b55c1c191077 100644
--- a/sys/dev/efidev/efirt.c
+++ b/sys/dev/efidev/efirt.c
@@ -107,7 +107,8 @@ static int efi_status2err[25] = {
enum efi_table_type {
TYPE_ESRT = 0,
- TYPE_PROP
+ TYPE_PROP,
+ TYPE_MEMORY_ATTR
};
static int efi_enter(void);
@@ -445,6 +446,42 @@ get_table_length(enum efi_table_type type, size_t *table_len, void **taddr)
free(buf, M_TEMP);
return (0);
}
+ case TYPE_MEMORY_ATTR:
+ {
+ efi_guid_t guid = EFI_MEMORY_ATTRIBUTES_TABLE;
+ struct efi_memory_attribute_table *tbl_addr, *mem_addr;
+ int error;
+ void *buf;
+ size_t len = sizeof(struct efi_memory_attribute_table);
+
+ error = efi_get_table(&guid, (void **)&tbl_addr);
+ if (error)
+ return (error);
+
+ buf = malloc(len, M_TEMP, M_WAITOK);
+ error = physcopyout((vm_paddr_t)tbl_addr, buf, len);
+ if (error) {
+ free(buf, M_TEMP);
+ return (error);
+ }
+
+ mem_addr = (struct efi_memory_attribute_table *)buf;
+ if (mem_addr->version != 2) {
+ free(buf, M_TEMP);
+ return (EINVAL);
+ }
+ len += mem_addr->descriptor_size * mem_addr->num_ents;
+ if (len > EFI_TABLE_ALLOC_MAX) {
+ free(buf, M_TEMP);
+ return (ENOMEM);
+ }
+
+ *table_len = len;
+ if (taddr != NULL)
+ *taddr = tbl_addr;
+ free(buf, M_TEMP);
+ return (0);
+ }
}
return (ENOENT);
}
@@ -457,7 +494,8 @@ copy_table(efi_guid_t *guid, void **buf, size_t buf_len, size_t *table_len)
enum efi_table_type type;
} tables[] = {
{ EFI_TABLE_ESRT, TYPE_ESRT },
- { EFI_PROPERTIES_TABLE, TYPE_PROP }
+ { EFI_PROPERTIES_TABLE, TYPE_PROP },
+ { EFI_MEMORY_ATTRIBUTES_TABLE, TYPE_MEMORY_ATTR }
};
size_t table_idx;
void *taddr;
diff --git a/sys/modules/efirt/Makefile b/sys/modules/efirt/Makefile
index 4738996fd4e6..c46484465b68 100644
--- a/sys/modules/efirt/Makefile
+++ b/sys/modules/efirt/Makefile
@@ -9,7 +9,7 @@ SRCS+= device_if.h bus_if.h clock_if.h
DPSRCS+= assym.inc
.if ${MACHINE_CPUARCH} == "amd64"
-SRCS+= opt_hwpmc_hooks.h opt_kstack_pages.h
+SRCS+= opt_acpi.h opt_hwpmc_hooks.h opt_kstack_pages.h
.endif
efirt_support.o: efirt_support.S assym.inc
diff --git a/sys/sys/efi.h b/sys/sys/efi.h
index 95a433a950db..89c8b15519de 100644
--- a/sys/sys/efi.h
+++ b/sys/sys/efi.h
@@ -42,6 +42,8 @@
{0xb122a263,0x3661,0x4f68,{0x99,0x29,0x78,0xf8,0xb0,0xd6,0x21,0x80}}
#define EFI_PROPERTIES_TABLE \
{0x880aaca3,0x4adc,0x4a04,{0x90,0x79,0xb7,0x47,0x34,0x08,0x25,0xe5}}
+#define EFI_MEMORY_ATTRIBUTES_TABLE \
+ {0xdcfa911d,0x26eb,0x469f,{0xa2,0x20,0x38,0xb7,0xdc,0x46,0x12,0x20}}
#define LINUX_EFI_MEMRESERVE_TABLE \
{0x888eb0c6,0x8ede,0x4ff5,{0xa8,0xf0,0x9a,0xee,0x5c,0xb9,0x77,0xc2}}
@@ -166,6 +168,22 @@ struct efi_prop_table {
uint64_t memory_protection_attribute;
};
+struct efi_memory_descriptor {
+ uint32_t type;
+ caddr_t phy_addr;
+ caddr_t virt_addr;
+ uint64_t pages;
+ uint64_t attrs;
+};
+
+struct efi_memory_attribute_table {
+ uint32_t version;
+ uint32_t num_ents;
+ uint32_t descriptor_size;
+ uint32_t flags;
+ struct efi_memory_descriptor tables[];
+};
+
#ifdef _KERNEL
#ifdef EFIABI_ATTR
diff --git a/usr.sbin/efitable/efitable.8 b/usr.sbin/efitable/efitable.8
index bb8a9cc3d0e1..4d174b7d9514 100644
--- a/usr.sbin/efitable/efitable.8
+++ b/usr.sbin/efitable/efitable.8
@@ -54,6 +54,8 @@ Currently supported tables:
.Bl -tag -width indent -compact
.It Cm esrt
EFI System Resource Table
+.It Cm memory
+EFI Memory Attributes Table
.It Cm prop
EFI Properties Table
.El
diff --git a/usr.sbin/efitable/efitable.c b/usr.sbin/efitable/efitable.c
index 0eee72801592..a506b4dea311 100644
--- a/usr.sbin/efitable/efitable.c
+++ b/usr.sbin/efitable/efitable.c
@@ -44,6 +44,7 @@
static void efi_table_print_esrt(const void *data);
static void efi_table_print_prop(const void *data);
+static void efi_table_print_memory(const void *data);
static void usage(void) __dead2;
struct efi_table_op {
@@ -56,7 +57,9 @@ static const struct efi_table_op efi_table_ops[] = {
{ .name = "esrt", .parse = efi_table_print_esrt,
.guid = EFI_TABLE_ESRT },
{ .name = "prop", .parse = efi_table_print_prop,
- .guid = EFI_PROPERTIES_TABLE }
+ .guid = EFI_PROPERTIES_TABLE },
+ { .name = "memory", .parse = efi_table_print_memory,
+ .guid = EFI_MEMORY_ATTRIBUTES_TABLE }
};
int
@@ -239,6 +242,51 @@ efi_table_print_prop(const void *data)
xo_err(EX_IOERR, "stdout");
}
+static void
+efi_table_print_memory(const void *data)
+{
+ const struct efi_memory_attribute_table *attr =
+ (const struct efi_memory_attribute_table *)data;
+ const struct efi_memory_descriptor *desc;
+ int i, nentries;
+
+ nentries = attr->num_ents;
+ desc = attr->tables;
+
+ xo_set_version(EFITABLE_XO_VERSION);
+
+ xo_open_container("memory");
+ xo_emit("{Lwc:Version}{:version/%#x}\n", attr->version);
+ xo_emit("{Lwc:Length}{:length/%u}\n", attr->descriptor_size);
+ xo_emit("{Lwc:Entries}{:entries/%u}\n", attr->num_ents);
+
+ xo_open_container("attributes");
+
+ /*
+ * According to https://forum.osdev.org/viewtopic.php?t=32953, the size
+ * of records into the attribute table never equals to
+ * sizeof(efi_memory_descriptor). The correct one for indexing the array
+ * resides in the attributet table.
+ */
+ for (i = 0; i < nentries; i++) {
+ xo_emit("{Lwc:ID}{:id/%#x}\n", i);
+ xo_emit("{Lwc:Attributes}{:attributes/%#x}\n", desc->attrs);
+ xo_emit("{Lwc:Type}{:type/%#x}\n", desc->type);
+ xo_emit("{Lwc:Pages}{:pages/%#x}\n", desc->pages);
+ xo_emit("{Lwc:Phyaddr}{:phyaddr/%#p}\n", desc->phy_addr);
+ xo_emit("{Lwc:Virtaddr}{:virtaddr/%#p}\n", desc->virt_addr);
+ desc = (const struct efi_memory_descriptor *)(const void *)
+ ((const char *)desc + attr->descriptor_size);
+ }
+
+ xo_close_container("attributes");
+
+ xo_close_container("memory");
+
+ if (xo_finish() < 0)
+ xo_err(EX_IOERR, "stdout");
+}
+
static void usage(void)
{
xo_error("usage: efitable [-g guid | -t name] [--libxo]\n");