summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2004-11-17 14:13:00 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2004-11-17 14:13:00 +0000
commit0ec52197d4a1d5b0c49dcb1c4f8df9440b6be477 (patch)
treeaa95c2f8d246ca1f7da93affb72cd4f2768ba507 /sys/dev
parent2affc53bff812ac689af1b416f15b552ced1c4d8 (diff)
firmware loading; ok pedro tedu dlg miod
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/firmload.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/sys/dev/firmload.c b/sys/dev/firmload.c
new file mode 100644
index 00000000000..d6c3a567b83
--- /dev/null
+++ b/sys/dev/firmload.c
@@ -0,0 +1,86 @@
+/* $OpenBSD: firmload.c,v 1.1 2004/11/17 14:12:59 deraadt Exp $ */
+
+/*
+ * Copyright (c) 2004 Theo de Raadt <deraadt@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/syslimits.h>
+#include <sys/time.h>
+#include <sys/namei.h>
+#include <sys/vnode.h>
+#include <sys/mount.h>
+#include <sys/errno.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/device.h>
+
+int
+loadfirmware(const char *name, u_char **bufp, size_t *buflen)
+{
+ struct proc *p = curproc;
+ struct nameidata nid;
+ char path[MAXPATHLEN];
+ struct iovec iov;
+ struct uio uio;
+ struct vattr va;
+ int error;
+ char *ptr;
+
+ if (!rootvp || !vcount(rootvp))
+ return (EIO);
+
+ snprintf(path, sizeof path, "/etc/firmware/%s", name);
+
+ NDINIT(&nid, LOOKUP, NOFOLLOW|LOCKLEAF, UIO_SYSSPACE, path, p);
+ error = namei(&nid);
+ if (error)
+ return error;
+ error = VOP_GETATTR(nid.ni_vp, &va, p->p_ucred, p);
+ if (error)
+ goto fail;
+ if (va.va_size > FIRMWARE_MAX) {
+ error = E2BIG;
+ goto fail;
+ }
+ ptr = malloc(va.va_size, M_DEVBUF, M_NOWAIT);
+ if (ptr == NULL) {
+ error = ENOMEM;
+ goto fail;
+ }
+
+ iov.iov_base = ptr,
+ iov.iov_len = va.va_size;
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+ uio.uio_offset = 0;
+ uio.uio_resid = va.va_size;
+ uio.uio_segflg = UIO_SYSSPACE;
+ uio.uio_rw = UIO_READ;
+ uio.uio_procp = p;
+
+ error = VOP_READ(nid.ni_vp, &uio, 0, NOCRED);
+
+ if (error == 0) {
+ *bufp = ptr;
+ *buflen = va.va_size;
+ } else
+ free(bufp, M_DEVBUF);
+
+fail:
+ vput(nid.ni_vp);
+ return (error);
+}