git: 27d3902679cd - main - efirt: add hooks for diverging EFI implementations

Roger Pau Monné royger at FreeBSD.org
Tue Feb 16 14:27:19 UTC 2021


The branch main has been updated by royger:

URL: https://cgit.FreeBSD.org/src/commit/?id=27d3902679cd6df6404cd402ffc85a9763c449b1

commit 27d3902679cd6df6404cd402ffc85a9763c449b1
Author:     Roger Pau Monné <royger at FreeBSD.org>
AuthorDate: 2021-02-12 11:11:58 +0000
Commit:     Roger Pau Monné <royger at FreeBSD.org>
CommitDate: 2021-02-16 14:26:11 +0000

    efirt: add hooks for diverging EFI implementations
    
    Introduce a set of hooks for MI EFI public functions, so that a new
    implementation can be done. This will be used to implement the Xen PV
    EFI interface that's used when running FreeBSD as a Xen dom0 from UEFI
    firmware. Also make the efi_status_to_errno non-static since it will
    be used to evaluate status return values from the PV interface.
    
    No functional change indented.
    
    Sponsored by:           Citrix Systems R&D
    Reviewed by:            kib, imp
    Differential revision:  https://reviews.freebsd.org/D28620
---
 sys/dev/efidev/efirt.c |  51 +++++++++++++++---------
 sys/sys/efi.h          | 106 ++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 127 insertions(+), 30 deletions(-)

diff --git a/sys/dev/efidev/efirt.c b/sys/dev/efidev/efirt.c
index fbb8f605c202..f28b9981919c 100644
--- a/sys/dev/efidev/efirt.c
+++ b/sys/dev/efidev/efirt.c
@@ -99,7 +99,7 @@ static int efi_status2err[25] = {
 static int efi_enter(void);
 static void efi_leave(void);
 
-static int
+int
 efi_status_to_errno(efi_status status)
 {
 	u_long code;
@@ -262,8 +262,8 @@ efi_uninit(void)
 	mtx_destroy(&efi_lock);
 }
 
-int
-efi_rt_ok(void)
+static int
+rt_ok(void)
 {
 
 	if (efi_runtime == NULL)
@@ -309,8 +309,8 @@ efi_leave(void)
 	PMAP_UNLOCK(curpmap);
 }
 
-int
-efi_get_table(struct uuid *uuid, void **ptr)
+static int
+get_table(struct uuid *uuid, void **ptr)
 {
 	struct efi_cfgtbl *ct;
 	u_long count;
@@ -419,8 +419,8 @@ efi_get_time_locked(struct efi_tm *tm, struct efi_tmcap *tmcap)
 	return (efi_call(&ec));
 }
 
-int
-efi_get_time(struct efi_tm *tm)
+static int
+get_time(struct efi_tm *tm)
 {
 	struct efi_tmcap dummy;
 	int error;
@@ -439,8 +439,8 @@ efi_get_time(struct efi_tm *tm)
 	return (error);
 }
 
-int
-efi_get_time_capabilities(struct efi_tmcap *tmcap)
+static int
+get_time_capabilities(struct efi_tmcap *tmcap)
 {
 	struct efi_tm dummy;
 	int error;
@@ -453,8 +453,8 @@ efi_get_time_capabilities(struct efi_tmcap *tmcap)
 	return (error);
 }
 
-int
-efi_reset_system(enum efi_reset type)
+static int
+reset_system(enum efi_reset type)
 {
 	struct efirt_callinfo ec;
 
@@ -495,8 +495,8 @@ efi_set_time_locked(struct efi_tm *tm)
 	return (efi_call(&ec));
 }
 
-int
-efi_set_time(struct efi_tm *tm)
+static int
+set_time(struct efi_tm *tm)
 {
 	int error;
 
@@ -508,8 +508,8 @@ efi_set_time(struct efi_tm *tm)
 	return (error);
 }
 
-int
-efi_var_get(efi_char *name, struct uuid *vendor, uint32_t *attrib,
+static int
+var_get(efi_char *name, struct uuid *vendor, uint32_t *attrib,
     size_t *datasize, void *data)
 {
 	struct efirt_callinfo ec;
@@ -528,8 +528,8 @@ efi_var_get(efi_char *name, struct uuid *vendor, uint32_t *attrib,
 	return (efi_call(&ec));
 }
 
-int
-efi_var_nextname(size_t *namesize, efi_char *name, struct uuid *vendor)
+static int
+var_nextname(size_t *namesize, efi_char *name, struct uuid *vendor)
 {
 	struct efirt_callinfo ec;
 
@@ -545,8 +545,8 @@ efi_var_nextname(size_t *namesize, efi_char *name, struct uuid *vendor)
 	return (efi_call(&ec));
 }
 
-int
-efi_var_set(efi_char *name, struct uuid *vendor, uint32_t attrib,
+static int
+var_set(efi_char *name, struct uuid *vendor, uint32_t attrib,
     size_t datasize, void *data)
 {
 	struct efirt_callinfo ec;
@@ -565,6 +565,19 @@ efi_var_set(efi_char *name, struct uuid *vendor, uint32_t attrib,
 	return (efi_call(&ec));
 }
 
+const static struct efi_ops efi_ops = {
+	.rt_ok = rt_ok,
+	.get_table = get_table,
+	.get_time = get_time,
+	.get_time_capabilities = get_time_capabilities,
+	.reset_system = reset_system,
+	.set_time = set_time,
+	.var_get = var_get,
+	.var_nextname = var_nextname,
+	.var_set = var_set,
+};
+const struct efi_ops *active_efi_ops = &efi_ops;
+
 static int
 efirt_modevents(module_t m, int event, void *arg __unused)
 {
diff --git a/sys/sys/efi.h b/sys/sys/efi.h
index 220509853cb2..f7a1fe790d23 100644
--- a/sys/sys/efi.h
+++ b/sys/sys/efi.h
@@ -180,18 +180,102 @@ int efi_rt_arch_call(struct efirt_callinfo *);
 bool efi_create_1t1_map(struct efi_md *, int, int);
 void efi_destroy_1t1_map(void);
 
+struct efi_ops {
+	/*
+	 * The EFI calls might be virtualized in some environments, requiring
+	 * FreeBSD to use a different interface (ie: hypercalls) in order to
+	 * access them.
+	 */
+	int	(*rt_ok)(void);
+	int 	(*get_table)(struct uuid *, void **);
+	int 	(*get_time)(struct efi_tm *);
+	int 	(*get_time_capabilities)(struct efi_tmcap *);
+	int	(*reset_system)(enum efi_reset);
+	int 	(*set_time)(struct efi_tm *);
+	int 	(*var_get)(uint16_t *, struct uuid *, uint32_t *, size_t *,
+    void *);
+	int 	(*var_nextname)(size_t *, uint16_t *, struct uuid *);
+	int 	(*var_set)(uint16_t *, struct uuid *, uint32_t, size_t, void *);
+};
+extern const struct efi_ops *active_efi_ops;
+
 /* Public MI EFI functions */
-int efi_rt_ok(void);
-int efi_get_table(struct uuid *uuid, void **ptr);
-int efi_get_time(struct efi_tm *tm);
-int efi_get_time_capabilities(struct efi_tmcap *tmcap);
-int efi_reset_system(enum efi_reset type);
-int efi_set_time(struct efi_tm *tm);
-int efi_var_get(uint16_t *name, struct uuid *vendor, uint32_t *attrib,
-    size_t *datasize, void *data);
-int efi_var_nextname(size_t *namesize, uint16_t *name, struct uuid *vendor);
-int efi_var_set(uint16_t *name, struct uuid *vendor, uint32_t attrib,
-    size_t datasize, void *data);
+static inline int efi_rt_ok(void)
+{
+
+	if(active_efi_ops->rt_ok == NULL)
+		return (ENXIO);
+	return (active_efi_ops->rt_ok());
+}
+
+static inline int efi_get_table(struct uuid *uuid, void **ptr)
+{
+
+        if (active_efi_ops->get_table == NULL)
+		return (ENXIO);
+	return (active_efi_ops->get_table(uuid, ptr));
+}
+
+static inline int efi_get_time(struct efi_tm *tm)
+{
+
+	if (active_efi_ops->get_time == NULL)
+		return (ENXIO);
+	return (active_efi_ops->get_time(tm));
+}
+
+static inline int efi_get_time_capabilities(struct efi_tmcap *tmcap)
+{
+
+	if (active_efi_ops->get_time_capabilities == NULL)
+		return (ENXIO);
+	return (active_efi_ops->get_time_capabilities(tmcap));
+}
+
+static inline int efi_reset_system(enum efi_reset type)
+{
+
+	if (active_efi_ops->reset_system == NULL)
+		return (ENXIO);
+	return (active_efi_ops->reset_system(type));
+}
+
+static inline int efi_set_time(struct efi_tm *tm)
+{
+
+	if (active_efi_ops->set_time == NULL)
+		return (ENXIO);
+	return (active_efi_ops->set_time(tm));
+}
+
+static inline int efi_var_get(uint16_t *name, struct uuid *vendor,
+    uint32_t *attrib, size_t *datasize, void *data)
+{
+
+	if (active_efi_ops->var_get == NULL)
+		return (ENXIO);
+	return (active_efi_ops->var_get(name, vendor, attrib, datasize, data));
+}
+
+static inline int efi_var_nextname(size_t *namesize, uint16_t *name,
+    struct uuid *vendor)
+{
+
+	if (active_efi_ops->var_nextname == NULL)
+		return (ENXIO);
+	return (active_efi_ops->var_nextname(namesize, name, vendor));
+}
+
+static inline int efi_var_set(uint16_t *name, struct uuid *vendor,
+    uint32_t attrib, size_t datasize, void *data)
+{
+
+	if (active_efi_ops->var_set == NULL)
+		return (ENXIO);
+	return (active_efi_ops->var_set(name, vendor, attrib, datasize, data));
+}
+
+int efi_status_to_errno(efi_status status);
 
 #endif	/* _KERNEL */
 


More information about the dev-commits-src-all mailing list