aboutsummaryrefslogtreecommitdiff
path: root/sys/sys
diff options
context:
space:
mode:
authorPavel Balaev <pavel.balaev@3mdeb.com>2021-07-01 16:27:25 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2021-07-03 17:06:48 +0000
commitd12d651f8692cfcaf6fd0a6e8264c29547f644c9 (patch)
tree90a276a61982ddd26e690970e793603f53a13dfc /sys/sys
parent2f514e6f13de41aa9ad5f563ed0decc66e91f99c (diff)
downloadsrc-d12d651f8692cfcaf6fd0a6e8264c29547f644c9.tar.gz
src-d12d651f8692cfcaf6fd0a6e8264c29547f644c9.zip
EFI RT: resurrect EFIIOC_GET_TABLE
Make it work, but change the interface to be safe for non-root users. In particular, right now interface only works for the tables which can be minimally parsed by kernel to determine the table size. Then, userspace can query the table size, after that it provides a buffer of needed size and kernel copies out just table to userspace. Main advantage is that user no longer need to be able to read /dev/mem, the disadvantage is the need to have minimal parsers aware of the table types. Right now the parsers are implemented for ESRT and PROP tables. Future extension of the present interface might be a return of only the table physical address, in case kernel does not have suitable parser yet. Then, a privileged user could read the table from /dev/mem. This extension, which logically equivalent to the old (non-worked) EFIIOC_GET_TABLE variant, is not implemented until needed. Submitted by: Pavel Balaev <pavel.balaev@3mdeb.com> MFC after: 2 weeks Differential revision: https://reviews.freebsd.org/D30104
Diffstat (limited to 'sys/sys')
-rw-r--r--sys/sys/efi.h39
-rw-r--r--sys/sys/efiio.h9
2 files changed, 48 insertions, 0 deletions
diff --git a/sys/sys/efi.h b/sys/sys/efi.h
index 7f9408d19b39..6ace7dd6e523 100644
--- a/sys/sys/efi.h
+++ b/sys/sys/efi.h
@@ -40,6 +40,10 @@
{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}}
+#define EFI_PROPERTIES_TABLE \
+ {0x880aaca3,0x4adc,0x4a04,0x90,0x79,{0xb7,0x47,0x34,0x08,0x25,0xe5}}
enum efi_reset {
EFI_RESET_COLD = 0,
@@ -123,6 +127,31 @@ struct efi_tblhdr {
uint32_t __res;
};
+#define ESRT_FIRMWARE_RESOURCE_VERSION 1
+
+struct efi_esrt_table {
+ uint32_t fw_resource_count;
+ uint32_t fw_resource_count_max;
+ uint64_t fw_resource_version;
+ uint8_t entries[];
+};
+
+struct efi_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 efi_prop_table {
+ uint32_t version;
+ uint32_t length;
+ uint64_t memory_protection_attribute;
+};
+
#ifdef _KERNEL
#ifdef EFIABI_ATTR
@@ -188,6 +217,7 @@ struct efi_ops {
*/
int (*rt_ok)(void);
int (*get_table)(struct uuid *, void **);
+ int (*copy_table)(struct uuid *, void **, size_t, size_t *);
int (*get_time)(struct efi_tm *);
int (*get_time_capabilities)(struct efi_tmcap *);
int (*reset_system)(enum efi_reset);
@@ -216,6 +246,15 @@ static inline int efi_get_table(struct uuid *uuid, void **ptr)
return (active_efi_ops->get_table(uuid, ptr));
}
+static inline int efi_copy_table(struct uuid *uuid, void **buf,
+ size_t buf_len, size_t *table_len)
+{
+
+ if (active_efi_ops->copy_table == NULL)
+ return (ENXIO);
+ return (active_efi_ops->copy_table(uuid, buf, buf_len, table_len));
+}
+
static inline int efi_get_time(struct efi_tm *tm)
{
diff --git a/sys/sys/efiio.h b/sys/sys/efiio.h
index e5a0763536a3..803aed6a965e 100644
--- a/sys/sys/efiio.h
+++ b/sys/sys/efiio.h
@@ -32,6 +32,14 @@
#include <sys/uuid.h>
#include <sys/efi.h>
+struct efi_get_table_ioc
+{
+ void *buf; /* Pointer to userspace buffer */
+ struct uuid uuid; /* UUID to look up */
+ size_t table_len; /* Table size */
+ size_t buf_len; /* Size of the buffer */
+};
+
struct efi_var_ioc
{
efi_char *name; /* User pointer to name, in wide chars */
@@ -42,6 +50,7 @@ struct efi_var_ioc
size_t datasize; /* Number of *bytes* in the data */
};
+#define EFIIOC_GET_TABLE _IOWR('E', 1, struct efi_get_table_ioc)
#define EFIIOC_GET_TIME _IOR('E', 2, struct efi_tm)
#define EFIIOC_SET_TIME _IOW('E', 3, struct efi_tm)
#define EFIIOC_VAR_GET _IOWR('E', 4, struct efi_var_ioc)