aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Pau Monné <royger@FreeBSD.org>2021-02-12 11:11:58 +0000
committerRoger Pau Monné <royger@FreeBSD.org>2021-02-16 14:26:11 +0000
commit27d3902679cd6df6404cd402ffc85a9763c449b1 (patch)
tree2e59a985f5b2d5e0f78e156aa6edf3fd8b35da79
parenta2495c36678cb16597758ce150da5456cdd90331 (diff)
downloadsrc-27d3902679cd6df6404cd402ffc85a9763c449b1.tar.gz
src-27d3902679cd6df6404cd402ffc85a9763c449b1.zip
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
-rw-r--r--sys/dev/efidev/efirt.c51
-rw-r--r--sys/sys/efi.h106
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 */