summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/octeon/dev/octboot.c51
-rw-r--r--sys/arch/octeon/include/octboot.h7
-rw-r--r--sys/arch/octeon/stand/rdboot/rdboot.c50
3 files changed, 61 insertions, 47 deletions
diff --git a/sys/arch/octeon/dev/octboot.c b/sys/arch/octeon/dev/octboot.c
index 659b165e632..22779986c27 100644
--- a/sys/arch/octeon/dev/octboot.c
+++ b/sys/arch/octeon/dev/octboot.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: octboot.c,v 1.1 2019/07/17 14:36:32 visa Exp $ */
+/* $OpenBSD: octboot.c,v 1.2 2020/05/26 13:21:58 visa Exp $ */
/*
- * Copyright (c) 2019 Visa Hankala
+ * Copyright (c) 2019-2020 Visa Hankala
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -20,9 +20,7 @@
#include <sys/systm.h>
#include <sys/exec_elf.h>
#include <sys/malloc.h>
-#include <sys/namei.h>
#include <sys/proc.h>
-#include <sys/vnode.h>
#include <uvm/uvm_extern.h>
@@ -36,7 +34,7 @@ typedef void (*kentry)(register_t, register_t, register_t, register_t);
#define PRIMARY 1
int octboot_kexec(struct octboot_kexec_args *, struct proc *);
-int octboot_read(struct proc *, struct vnode *, void *, size_t, off_t);
+int octboot_read(struct octboot_kexec_args *, void *, size_t, off_t);
uint64_t octeon_boot_entry;
uint32_t octeon_boot_ready;
@@ -94,29 +92,12 @@ octboot_kexec(struct octboot_kexec_args *kargs, struct proc *p)
Elf_Ehdr eh;
Elf_Phdr *ph = NULL;
Elf_Shdr *sh = NULL;
- struct nameidata nid;
- struct vattr va;
paddr_t ekern = 0, elfp, maxp = 0, off, pa, shp;
size_t len, phsize, shsize, shstrsize, size;
char *argbuf = NULL, *argptr;
char *shstr = NULL;
int argc = 0, error, havesyms = 0, i, nalloc = 0;
- NDINIT(&nid, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, kargs->path, p);
- error = namei(&nid);
- if (error != 0)
- return error;
- error = VOP_GETATTR(nid.ni_vp, &va, p->p_ucred, p);
- if (error != 0)
- goto fail;
- if (nid.ni_vp->v_type != VREG || va.va_size == 0) {
- error = EINVAL;
- goto fail;
- }
- error = VOP_ACCESS(nid.ni_vp, VREAD, p->p_ucred, p);
- if (error != 0)
- goto fail;
-
/*
* Load kernel arguments into a temporary buffer.
* This also translates the userspace argv pointers to kernel pointers.
@@ -140,7 +121,7 @@ octboot_kexec(struct octboot_kexec_args *kargs, struct proc *p)
/*
* Read the headers and validate them.
*/
- error = octboot_read(p, nid.ni_vp, &eh, sizeof(eh), 0);
+ error = octboot_read(kargs, &eh, sizeof(eh), 0);
if (error != 0)
goto fail;
@@ -151,7 +132,7 @@ octboot_kexec(struct octboot_kexec_args *kargs, struct proc *p)
goto fail;
}
phsize = eh.e_phnum * sizeof(Elf_Phdr);
- error = octboot_read(p, nid.ni_vp, ph, phsize, eh.e_phoff);
+ error = octboot_read(kargs, ph, phsize, eh.e_phoff);
if (error != 0)
goto fail;
@@ -162,7 +143,7 @@ octboot_kexec(struct octboot_kexec_args *kargs, struct proc *p)
goto fail;
}
shsize = eh.e_shnum * sizeof(Elf_Shdr);
- error = octboot_read(p, nid.ni_vp, sh, shsize, eh.e_shoff);
+ error = octboot_read(kargs, sh, shsize, eh.e_shoff);
if (error != 0)
goto fail;
@@ -208,7 +189,7 @@ octboot_kexec(struct octboot_kexec_args *kargs, struct proc *p)
if (ph[i].p_type != PT_LOAD)
continue;
- error = octboot_read(p, nid.ni_vp, (caddr_t)ph[i].p_paddr,
+ error = octboot_read(kargs, (caddr_t)ph[i].p_paddr,
ph[i].p_filesz, ph[i].p_offset);
if (error != 0)
goto fail;
@@ -250,7 +231,7 @@ octboot_kexec(struct octboot_kexec_args *kargs, struct proc *p)
error = ENOMEM;
goto fail;
}
- error = octboot_read(p, nid.ni_vp, shstr, shstrsize,
+ error = octboot_read(kargs, shstr, shstrsize,
sh[eh.e_shstrndx].sh_offset);
if (error != 0)
goto fail;
@@ -269,7 +250,7 @@ octboot_kexec(struct octboot_kexec_args *kargs, struct proc *p)
error = ENOMEM;
goto fail;
}
- error = octboot_read(p, nid.ni_vp,
+ error = octboot_read(kargs,
(caddr_t)PHYS_TO_CKSEG0(maxp),
sh[i].sh_size, sh[i].sh_offset);
maxp += bsize;
@@ -366,22 +347,14 @@ fail:
free(sh, M_TEMP, shsize);
free(ph, M_TEMP, phsize);
free(argbuf, M_TEMP, PAGE_SIZE);
- vput(nid.ni_vp);
return error;
}
int
-octboot_read(struct proc *p, struct vnode *vp, void *buf, size_t size,
+octboot_read(struct octboot_kexec_args *kargs, void *buf, size_t size,
off_t off)
{
- size_t resid;
- int error;
-
- error = vn_rdwr(UIO_READ, vp, buf, size, off, UIO_SYSSPACE, 0,
- p->p_ucred, &resid, p);
- if (error != 0)
- return error;
- if (resid != 0)
+ if (off + size < off || off + size > kargs->klen)
return ENOEXEC;
- return 0;
+ return copyin(kargs->kimg + off, buf, size);
}
diff --git a/sys/arch/octeon/include/octboot.h b/sys/arch/octeon/include/octboot.h
index 60c9f300169..12a62f87354 100644
--- a/sys/arch/octeon/include/octboot.h
+++ b/sys/arch/octeon/include/octboot.h
@@ -1,7 +1,7 @@
-/* $OpenBSD: octboot.h,v 1.1 2019/07/17 14:36:32 visa Exp $ */
+/* $OpenBSD: octboot.h,v 1.2 2020/05/26 13:21:58 visa Exp $ */
/*
- * Copyright (c) 2019 Visa Hankala
+ * Copyright (c) 2019-2020 Visa Hankala
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -24,7 +24,8 @@
#define OCTBOOT_MAX_ARGS 8 /* maximum number of boot arguments */
struct octboot_kexec_args {
- const char *path; /* kernel path */
+ char *kimg; /* kernel image buffer */
+ size_t klen; /* size of kernel image */
char *argv[OCTBOOT_MAX_ARGS];
/* kernel boot arguments */
};
diff --git a/sys/arch/octeon/stand/rdboot/rdboot.c b/sys/arch/octeon/stand/rdboot/rdboot.c
index 2a215eb13f9..540a7a5d20a 100644
--- a/sys/arch/octeon/stand/rdboot/rdboot.c
+++ b/sys/arch/octeon/stand/rdboot/rdboot.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: rdboot.c,v 1.4 2020/05/25 13:04:25 visa Exp $ */
+/* $OpenBSD: rdboot.c,v 1.5 2020/05/26 13:21:58 visa Exp $ */
/*
- * Copyright (c) 2019 Visa Hankala
+ * Copyright (c) 2019-2020 Visa Hankala
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -22,12 +22,14 @@
#include <sys/mount.h>
#include <sys/reboot.h>
#include <sys/select.h>
+#include <sys/stat.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <paths.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
@@ -150,17 +152,47 @@ void
kexec(void)
{
struct octboot_kexec_args kargs;
+ struct stat sb;
char boothowtostr[32];
char rootdev[32];
+ char *kimg = NULL;
const char *path;
- int argc, ret;
+ ssize_t n;
+ off_t pos;
+ int argc, fd = -1, ret;
path = disk_open(cmd.path);
if (path == NULL)
return;
+ fd = open(path, O_RDONLY);
+ if (fd == -1)
+ goto load_failed;
+ if (fstat(fd, &sb) == -1)
+ goto load_failed;
+ if (!S_ISREG(sb.st_mode) || sb.st_size == 0) {
+ errno = ENOEXEC;
+ goto load_failed;
+ }
+
+ kimg = malloc(sb.st_size);
+ if (kimg == NULL)
+ goto load_failed;
+
+ pos = 0;
+ while (pos < sb.st_size) {
+ n = read(fd, kimg + pos, sb.st_size - pos);
+ if (n == -1)
+ goto load_failed;
+ pos += n;
+ }
+
+ close(fd);
+ disk_close();
+
memset(&kargs, 0, sizeof(kargs));
- kargs.path = path;
+ kargs.kimg = kimg;
+ kargs.klen = sb.st_size;
argc = 0;
if (cmd.boothowto != 0) {
snprintf(boothowtostr, sizeof(boothowtostr), "boothowto=%d",
@@ -184,6 +216,14 @@ kexec(void)
cmd.path, strerror(errno));
else
fprintf(stderr, "kexec() returned unexpectedly\n");
-
+ free(kimg);
+ return;
+
+load_failed:
+ fprintf(stderr, "failed to load kernel %s: %s\n",
+ cmd.path, strerror(errno));
+ if (fd != -1)
+ close(fd);
disk_close();
+ free(kimg);
}