svn commit: r202777 - in stable/8/sys/ia64: ia64 include
Marcel Moolenaar
marcel at FreeBSD.org
Fri Jan 22 03:59:05 UTC 2010
Author: marcel
Date: Fri Jan 22 03:59:05 2010
New Revision: 202777
URL: http://svn.freebsd.org/changeset/base/202777
Log:
MFC rev. 202271-202273:
o Add wrappers for the RT Variable Services.
o Add ioctl requests to /dev/io on ia64 for reading and writing
EFI variables.
Modified:
stable/8/sys/ia64/ia64/efi.c
stable/8/sys/ia64/ia64/iodev_machdep.c
stable/8/sys/ia64/include/efi.h
stable/8/sys/ia64/include/iodev.h
Directory Properties:
stable/8/sys/ (props changed)
stable/8/sys/amd64/include/xen/ (props changed)
stable/8/sys/cddl/contrib/opensolaris/ (props changed)
stable/8/sys/contrib/dev/acpica/ (props changed)
stable/8/sys/contrib/pf/ (props changed)
stable/8/sys/dev/xen/xenpci/ (props changed)
Modified: stable/8/sys/ia64/ia64/efi.c
==============================================================================
--- stable/8/sys/ia64/ia64/efi.c Fri Jan 22 03:50:43 2010 (r202776)
+++ stable/8/sys/ia64/ia64/efi.c Fri Jan 22 03:59:05 2010 (r202777)
@@ -41,6 +41,45 @@ static struct efi_systbl *efi_systbl;
static struct efi_cfgtbl *efi_cfgtbl;
static struct efi_rt *efi_runtime;
+static int efi_status2err[25] = {
+ 0, /* EFI_SUCCESS */
+ ENOEXEC, /* EFI_LOAD_ERROR */
+ EINVAL, /* EFI_INVALID_PARAMETER */
+ ENOSYS, /* EFI_UNSUPPORTED */
+ EMSGSIZE, /* EFI_BAD_BUFFER_SIZE */
+ EOVERFLOW, /* EFI_BUFFER_TOO_SMALL */
+ EBUSY, /* EFI_NOT_READY */
+ EIO, /* EFI_DEVICE_ERROR */
+ EROFS, /* EFI_WRITE_PROTECTED */
+ EAGAIN, /* EFI_OUT_OF_RESOURCES */
+ EIO, /* EFI_VOLUME_CORRUPTED */
+ ENOSPC, /* EFI_VOLUME_FULL */
+ ENXIO, /* EFI_NO_MEDIA */
+ ESTALE, /* EFI_MEDIA_CHANGED */
+ ENOENT, /* EFI_NOT_FOUND */
+ EACCES, /* EFI_ACCESS_DENIED */
+ ETIMEDOUT, /* EFI_NO_RESPONSE */
+ EADDRNOTAVAIL, /* EFI_NO_MAPPING */
+ ETIMEDOUT, /* EFI_TIMEOUT */
+ EDOOFUS, /* EFI_NOT_STARTED */
+ EALREADY, /* EFI_ALREADY_STARTED */
+ ECANCELED, /* EFI_ABORTED */
+ EPROTO, /* EFI_ICMP_ERROR */
+ EPROTO, /* EFI_TFTP_ERROR */
+ EPROTO /* EFI_PROTOCOL_ERROR */
+};
+
+static int
+efi_status_to_errno(efi_status status)
+{
+ u_long code;
+ int error;
+
+ code = status & 0x3ffffffffffffffful;
+ error = (code < 25) ? efi_status2err[code] : EDOOFUS;
+ return (error);
+}
+
void
efi_boot_finish(void)
{
@@ -148,9 +187,38 @@ efi_reset_system(void)
panic("%s: unable to reset the machine", __func__);
}
-efi_status
+int
efi_set_time(struct efi_tm *tm)
{
- return (efi_runtime->rt_settime(tm));
+ return (efi_status_to_errno(efi_runtime->rt_settime(tm)));
+}
+
+int
+efi_var_get(efi_char *name, struct uuid *vendor, uint32_t *attrib,
+ size_t *datasize, void *data)
+{
+ efi_status status;
+
+ status = efi_runtime->rt_getvar(name, vendor, attrib, datasize, data);
+ return (efi_status_to_errno(status));
+}
+
+int
+efi_var_nextname(size_t *namesize, efi_char *name, struct uuid *vendor)
+{
+ efi_status status;
+
+ status = efi_runtime->rt_scanvar(namesize, name, vendor);
+ return (efi_status_to_errno(status));
+}
+
+int
+efi_var_set(efi_char *name, struct uuid *vendor, uint32_t attrib,
+ size_t datasize, void *data)
+{
+ efi_status status;
+
+ status = efi_runtime->rt_setvar(name, vendor, attrib, datasize, data);
+ return (efi_status_to_errno(status));
}
Modified: stable/8/sys/ia64/ia64/iodev_machdep.c
==============================================================================
--- stable/8/sys/ia64/ia64/iodev_machdep.c Fri Jan 22 03:50:43 2010 (r202776)
+++ stable/8/sys/ia64/ia64/iodev_machdep.c Fri Jan 22 03:59:05 2010 (r202777)
@@ -31,16 +31,22 @@ __FBSDID("$FreeBSD$");
#include <sys/conf.h>
#include <sys/fcntl.h>
#include <sys/ioccom.h>
+#include <sys/malloc.h>
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/systm.h>
#include <machine/bus.h>
+#include <machine/efi.h>
#include <machine/iodev.h>
static int iodev_pio_read(struct iodev_pio_req *req);
static int iodev_pio_write(struct iodev_pio_req *req);
+static int iodev_efivar_getvar(struct iodev_efivar_req *req);
+static int iodev_efivar_nextname(struct iodev_efivar_req *req);
+static int iodev_efivar_setvar(struct iodev_efivar_req *req);
+
/* ARGSUSED */
int
ioopen(struct cdev *dev __unused, int flags __unused, int fmt __unused,
@@ -69,6 +75,7 @@ int
ioioctl(struct cdev *dev __unused, u_long cmd, caddr_t data,
int fflag __unused, struct thread *td __unused)
{
+ struct iodev_efivar_req *efivar_req;
struct iodev_pio_req *pio_req;
int error;
@@ -88,6 +95,24 @@ ioioctl(struct cdev *dev __unused, u_lon
break;
}
break;
+ case IODEV_EFIVAR:
+ efivar_req = (struct iodev_efivar_req *)data;
+ efivar_req->result = 0; /* So it's well-defined */
+ switch (efivar_req->access) {
+ case IODEV_EFIVAR_GETVAR:
+ error = iodev_efivar_getvar(efivar_req);
+ break;
+ case IODEV_EFIVAR_NEXTNAME:
+ error = iodev_efivar_nextname(efivar_req);
+ break;
+ case IODEV_EFIVAR_SETVAR:
+ error = iodev_efivar_setvar(efivar_req);
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ break;
}
return (error);
@@ -158,3 +183,118 @@ iodev_pio_write(struct iodev_pio_req *re
return (0);
}
+
+static int
+iodev_efivar_getvar(struct iodev_efivar_req *req)
+{
+ void *data;
+ efi_char *name;
+ int error;
+
+ if ((req->namesize & 1) != 0 || req->namesize < 4)
+ return (EINVAL);
+ if (req->datasize == 0)
+ return (EINVAL);
+
+ /*
+ * Pre-zero the allocated memory and don't copy the last 2 bytes
+ * of the name. That should be the closing nul character (ucs-2)
+ * and if not, then we ensured a nul-terminating string. This is
+ * to protect the firmware and thus ourselves.
+ */
+ name = malloc(req->namesize, M_TEMP, M_WAITOK | M_ZERO);
+ error = copyin(req->name, name, req->namesize - 2);
+ if (error) {
+ free(name, M_TEMP);
+ return (error);
+ }
+
+ data = malloc(req->datasize, M_TEMP, M_WAITOK);
+ error = efi_var_get(name, &req->vendor, &req->attrib, &req->datasize,
+ data);
+ if (error == EOVERFLOW || error == ENOENT) {
+ req->result = error;
+ error = 0;
+ }
+ if (!error && !req->result)
+ error = copyout(data, req->data, req->datasize);
+
+ free(data, M_TEMP);
+ free(name, M_TEMP);
+ return (error);
+}
+
+static int
+iodev_efivar_nextname(struct iodev_efivar_req *req)
+{
+ efi_char *name;
+ int error;
+
+ /* Enforce a reasonable minimum size of the name buffer. */
+ if (req->namesize < 4)
+ return (EINVAL);
+
+ name = malloc(req->namesize, M_TEMP, M_WAITOK);
+ error = copyin(req->name, name, req->namesize);
+ if (error) {
+ free(name, M_TEMP);
+ return (error);
+ }
+
+ error = efi_var_nextname(&req->namesize, name, &req->vendor);
+ if (error == EOVERFLOW || error == ENOENT) {
+ req->result = error;
+ error = 0;
+ }
+ if (!error && !req->result)
+ error = copyout(name, req->name, req->namesize);
+
+ free(name, M_TEMP);
+ return (error);
+}
+
+static int
+iodev_efivar_setvar(struct iodev_efivar_req *req)
+{
+ void *data;
+ efi_char *name;
+ int error;
+
+ if ((req->namesize & 1) != 0 || req->namesize < 4)
+ return (EINVAL);
+
+ /*
+ * Pre-zero the allocated memory and don't copy the last 2 bytes
+ * of the name. That should be the closing nul character (ucs-2)
+ * and if not, then we ensured a nul-terminating string. This is
+ * to protect the firmware and thus ourselves.
+ */
+ name = malloc(req->namesize, M_TEMP, M_WAITOK | M_ZERO);
+ error = copyin(req->name, name, req->namesize - 2);
+ if (error) {
+ free(name, M_TEMP);
+ return (error);
+ }
+
+ if (req->datasize) {
+ data = malloc(req->datasize, M_TEMP, M_WAITOK);
+ error = copyin(req->data, data, req->datasize);
+ if (error) {
+ free(data, M_TEMP);
+ free(name, M_TEMP);
+ return (error);
+ }
+ } else
+ data = NULL;
+
+ error = efi_var_set(name, &req->vendor, req->attrib, req->datasize,
+ data);
+ if (error == EAGAIN || error == ENOENT) {
+ req->result = error;
+ error = 0;
+ }
+
+ free(data, M_TEMP);
+ free(name, M_TEMP);
+ return (error);
+}
Modified: stable/8/sys/ia64/include/efi.h
==============================================================================
--- stable/8/sys/ia64/include/efi.h Fri Jan 22 03:50:43 2010 (r202776)
+++ stable/8/sys/ia64/include/efi.h Fri Jan 22 03:59:05 2010 (r202777)
@@ -158,6 +158,9 @@ void efi_get_time(struct efi_tm *);
struct efi_md *efi_md_first(void);
struct efi_md *efi_md_next(struct efi_md *);
void efi_reset_system(void);
-efi_status efi_set_time(struct efi_tm *);
+int efi_set_time(struct efi_tm *);
+int efi_var_get(efi_char *, struct uuid *, uint32_t *, size_t *, void *);
+int efi_var_nextname(size_t *, efi_char *, struct uuid *);
+int efi_var_set(efi_char *, struct uuid *, uint32_t, size_t, void *);
#endif /* _MACHINE_EFI_H_ */
Modified: stable/8/sys/ia64/include/iodev.h
==============================================================================
--- stable/8/sys/ia64/include/iodev.h Fri Jan 22 03:50:43 2010 (r202776)
+++ stable/8/sys/ia64/include/iodev.h Fri Jan 22 03:59:05 2010 (r202777)
@@ -29,6 +29,8 @@
#ifndef _MACHINE_IODEV_H_
#define _MACHINE_IODEV_H_
+#include <sys/uuid.h>
+
struct iodev_pio_req {
u_int access;
#define IODEV_PIO_READ 0
@@ -40,6 +42,22 @@ struct iodev_pio_req {
#define IODEV_PIO _IOWR('I', 0, struct iodev_pio_req)
+struct iodev_efivar_req {
+ u_int access;
+#define IODEV_EFIVAR_GETVAR 0
+#define IODEV_EFIVAR_NEXTNAME 1
+#define IODEV_EFIVAR_SETVAR 2
+ u_int result; /* errno value */
+ size_t namesize;
+ u_short *name; /* UCS-2 */
+ struct uuid vendor;
+ uint32_t attrib;
+ size_t datasize;
+ void *data;
+};
+
+#define IODEV_EFIVAR _IOWR('I', 1, struct iodev_efivar_req)
+
#ifdef _KERNEL
d_open_t ioopen;
More information about the svn-src-all
mailing list