FreeBSD Bugzilla – Attachment 224662 Details for
Bug 255594
efirt: add ESRT table support
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
ESRT table patch
0001-efirt-add-ESRT-table-support.patch (text/plain), 7.12 KB, created by
Pavel Balaev
on 2021-05-04 15:14:09 UTC
(
hide
)
Description:
ESRT table patch
Filename:
MIME Type:
Creator:
Pavel Balaev
Created:
2021-05-04 15:14:09 UTC
Size:
7.12 KB
patch
obsolete
>From cd756c48ceb8a1375c083d10cb18a5141e25e6f4 Mon Sep 17 00:00:00 2001 >From: Pavel Balaev <pavel.balaev@3mdeb.com> >Date: Tue, 4 May 2021 18:09:26 +0300 >Subject: [PATCH] efirt: add ESRT table support > >This patch enables publishing ESRT table to user space. >This is usefull for firmware update tools such as fwupd. > >ESRT table represent via read-only sysctl variables. >User can disable ESRT representing via variable >"efi.esrt.disable=1" in loader.conf. > >Signed-off-by: Pavel Balaev <pavel.balaev@3mdeb.com> >--- > stand/man/loader.8 | 3 + > sys/dev/efidev/efirt.c | 135 ++++++++++++++++++++++++++++++++++++++++- > sys/sys/efi.h | 2 + > 3 files changed, 139 insertions(+), 1 deletion(-) > >diff --git a/stand/man/loader.8 b/stand/man/loader.8 >index 4555f9962..6731fe9c0 100644 >--- a/stand/man/loader.8 >+++ b/stand/man/loader.8 >@@ -561,6 +561,9 @@ The following tunables are available: > Disable UEFI runtime services in the kernel, if applicable. > Runtime services are only available and used if the kernel is booted in a UEFI > environment. >+.It Va efi.esrt.disabled >+Disable publishing ESRT table to user space, if applicable. >+Depends on UEFI runtime services in the kernel. > .It Va hw.physmem > Limit the amount of physical memory the system will use. > By default the size is in bytes, but the >diff --git a/sys/dev/efidev/efirt.c b/sys/dev/efidev/efirt.c >index f28b99819..600d4853b 100644 >--- a/sys/dev/efidev/efirt.c >+++ b/sys/dev/efidev/efirt.c >@@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); > #include <sys/sysctl.h> > #include <sys/systm.h> > #include <sys/vmmeter.h> >+#include <sys/malloc.h> > > #include <machine/fpu.h> > #include <machine/efi.h> >@@ -96,8 +97,16 @@ static int efi_status2err[25] = { > EPROTO /* EFI_PROTOCOL_ERROR */ > }; > >+#define ESRT_UUID_LEN 36 >+ >+static struct esrt_ctx { >+ struct sysctl_ctx_list clist; >+ char uuid_name[ESRT_UUID_LEN + 1]; >+} esrt_ctx; >+ > static int efi_enter(void); > static void efi_leave(void); >+static void represent_esrt_table(struct esrt_ctx *ctx); > > int > efi_status_to_errno(efi_status status) >@@ -155,9 +164,10 @@ efi_init(void) > struct efi_rt *rtdm; > caddr_t kmdp; > size_t efisz; >- int ndesc, rt_disabled; >+ int ndesc, rt_disabled, esrt_disabled; > > rt_disabled = 0; >+ esrt_disabled = 0; > TUNABLE_INT_FETCH("efi.rt.disabled", &rt_disabled); > if (rt_disabled == 1) > return (0); >@@ -241,6 +251,11 @@ efi_init(void) > efi_shutdown_tag = EVENTHANDLER_REGISTER(shutdown_final, > efi_shutdown_final, NULL, SHUTDOWN_PRI_LAST - 1); > >+ TUNABLE_INT_FETCH("efi.esrt.disabled", &esrt_disabled); >+ if (esrt_disabled == 0) { >+ represent_esrt_table(&esrt_ctx); >+ } >+ > return (0); > } > >@@ -259,6 +274,8 @@ efi_uninit(void) > efi_cfgtbl = NULL; > efi_runtime = NULL; > >+ sysctl_ctx_free(&esrt_ctx.clist); >+ > mtx_destroy(&efi_lock); > } > >@@ -336,6 +353,122 @@ get_table(struct uuid *uuid, void **ptr) > return (ENOENT); > } > >+static void >+represent_esrt_table(struct esrt_ctx *ctx) >+{ >+ struct uuid esrt_uuid = EFI_TABLE_ESRT; >+ struct sysctl_oid *root; >+ >+ struct esrt_entry_v1 { >+ struct uuid fw_class; >+ uint32_t fw_type; >+ uint32_t fw_version; >+ uint32_t lowest_supported_fw_version; >+ uint32_t capsule_flags; >+ uint32_t last_attempt_version; >+ uint32_t last_attempt_status; >+ }; >+ >+ struct esrt_table { >+ uint32_t fw_resource_count; >+ uint32_t fw_resource_count_max; >+ uint64_t fw_resource_version; >+ uint8_t entries[]; >+ }; >+ >+ struct esrt_table *esrt_ptr = NULL; >+ struct esrt_entry_v1 *entries_v1; >+ void *ptr = NULL; >+ >+ if (efi_get_table(&esrt_uuid, &ptr) != 0) { >+ return; >+ } >+ >+ esrt_ptr = (struct esrt_table *) efi_phys_to_kva((uintptr_t) ptr); >+ >+ /* check for fw_resource_version, must be 1 */ >+ if (!esrt_ptr || esrt_ptr->fw_resource_version != 1) { >+ return; >+ } >+ >+ sysctl_ctx_init(&ctx->clist); >+ >+ root = SYSCTL_ADD_NODE(&ctx->clist, SYSCTL_STATIC_CHILDREN(_hw_efi), >+ OID_AUTO, "esrt", CTLFLAG_RD, NULL, "ESRT table"); >+ >+ if (root == NULL) { >+ printf("%s: unable to allocate sysctl tree\n", __func__); >+ return; >+ } >+ >+ SYSCTL_ADD_U32(&ctx->clist, SYSCTL_CHILDREN(root), OID_AUTO, >+ "fw_resource_count", CTLFLAG_RD, >+ &esrt_ptr->fw_resource_count, 0, >+ "The number of firmware resources in the table"); >+ SYSCTL_ADD_U32(&ctx->clist, SYSCTL_CHILDREN(root), OID_AUTO, >+ "fw_resource_count_max", CTLFLAG_RD, >+ &esrt_ptr->fw_resource_count_max, 0, ""); >+ SYSCTL_ADD_U64(&ctx->clist, SYSCTL_CHILDREN(root), OID_AUTO, >+ "fw_resource_version", CTLFLAG_RD, >+ &esrt_ptr->fw_resource_version, 0, >+ "The version of the ESRT entities"); >+ >+ entries_v1 = (void *) esrt_ptr->entries; >+ >+ for (uint32_t i = 0; i < esrt_ptr->fw_resource_count; i++) { >+ >+ struct esrt_entry_v1 *e = &entries_v1[i]; >+ struct sysctl_oid *oid; >+ int n, num_dec; >+ char *entry_name; >+ >+ /* Count the number of decimal digits */ >+ for (n = 0, num_dec = i; num_dec != 0; n++) >+ num_dec /= 10; >+ entry_name = malloc(strlen("entry") + n + 1, M_TEMP, M_ZERO | M_WAITOK); >+ if (!entry_name) { >+ printf("%s: unable to allocate entry name\n", __func__); >+ return; >+ } >+ sprintf(entry_name, "%s%d", "entry", i); >+ >+ oid = SYSCTL_ADD_NODE(&ctx->clist, SYSCTL_CHILDREN(root), OID_AUTO, >+ entry_name, CTLFLAG_RD, NULL, ""); >+ if (oid == NULL) { >+ printf("%s: unable to allocate sysctl tree\n", __func__); >+ return; >+ } >+ >+ snprintf_uuid(ctx->uuid_name, ESRT_UUID_LEN + 1, &e->fw_class); >+ >+ SYSCTL_ADD_CONST_STRING(&ctx->clist, SYSCTL_CHILDREN(oid), OID_AUTO, >+ "fw_class", CTLFLAG_RD, ctx->uuid_name, >+ "GUID that identifies a firmware component"); >+ SYSCTL_ADD_U32(&ctx->clist, SYSCTL_CHILDREN(oid), OID_AUTO, >+ "fw_type", CTLFLAG_RD, &e->fw_type, 0, >+ "Type of firmware resource"); >+ SYSCTL_ADD_U32(&ctx->clist, SYSCTL_CHILDREN(oid), OID_AUTO, >+ "fw_version", CTLFLAG_RD, &e->fw_version, 0, >+ "The current version of the firmware resource"); >+ SYSCTL_ADD_U32(&ctx->clist, SYSCTL_CHILDREN(oid), OID_AUTO, >+ "lowest_supported_fw_version", CTLFLAG_RD, >+ &e->lowest_supported_fw_version, 0, >+ "The lowest firmware resource version to which a firmware"); >+ SYSCTL_ADD_U32(&ctx->clist, SYSCTL_CHILDREN(oid), OID_AUTO, >+ "capsule_flags", CTLFLAG_RD, &e->capsule_flags, 0, >+ "The capsule flags field in decimal"); >+ SYSCTL_ADD_U32(&ctx->clist, SYSCTL_CHILDREN(oid), OID_AUTO, >+ "last_attempt_version", CTLFLAG_RD, &e->last_attempt_version, 0, >+ "The last firmware version for which an update was attempted"); >+ SYSCTL_ADD_U32(&ctx->clist, SYSCTL_CHILDREN(oid), OID_AUTO, >+ "last_attempt_status", CTLFLAG_RD, &e->last_attempt_status, 0, >+ "The result of the last firmware update attempt"); >+ >+ free(entry_name, M_TEMP); >+ } >+} >+ >+ > static int efi_rt_handle_faults = EFI_RT_HANDLE_FAULTS_DEFAULT; > SYSCTL_INT(_machdep, OID_AUTO, efi_rt_handle_faults, CTLFLAG_RWTUN, > &efi_rt_handle_faults, 0, >diff --git a/sys/sys/efi.h b/sys/sys/efi.h >index 0c0b52afc..531f60e29 100644 >--- a/sys/sys/efi.h >+++ b/sys/sys/efi.h >@@ -40,6 +40,8 @@ > {0xeb9d2d31,0x2d88,0x11d3,0x9a,0x16,{0x00,0x90,0x27,0x3f,0xc1,0x4d}} > #define EFI_TABLE_SMBIOS3 \ > {0xf2fd1544,0x9794,0x4a2c,0x99,0x2e,{0xe5,0xbb,0xcf,0x20,0xe3,0x94}} >+#define EFI_TABLE_ESRT \ >+ {0xb122a263,0x3661,0x4f68,0x99,0x29,{0x78,0xf8,0xb0,0xd6,0x21,0x80}} > > enum efi_reset { > EFI_RESET_COLD = 0, >-- >2.26.2 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 255594
: 224662