summaryrefslogtreecommitdiffstats
path: root/sys/boot
diff options
context:
space:
mode:
authoriedowse <iedowse@FreeBSD.org>2004-08-28 14:57:34 +0000
committeriedowse <iedowse@FreeBSD.org>2004-08-28 14:57:34 +0000
commit1057ee343cee3ac0157a20aa450988d1e301c5f5 (patch)
treef9fe9b68204fea3bc9f22c81ede496d28832dd0a /sys/boot
parentd4a1defb3987ee2058cf2db8fae47ee3f74136cb (diff)
downloadFreeBSD-src-1057ee343cee3ac0157a20aa450988d1e301c5f5.zip
FreeBSD-src-1057ee343cee3ac0157a20aa450988d1e301c5f5.tar.gz
Add a few helper functions for zeroing kernel space and reading
from specified file offsets. Make use of these in load_elf.c.
Diffstat (limited to 'sys/boot')
-rw-r--r--sys/boot/common/bootstrap.h3
-rw-r--r--sys/boot/common/load_elf.c48
-rw-r--r--sys/boot/common/misc.c68
3 files changed, 82 insertions, 37 deletions
diff --git a/sys/boot/common/bootstrap.h b/sys/boot/common/bootstrap.h
index 6e17be7..21845ce 100644
--- a/sys/boot/common/bootstrap.h
+++ b/sys/boot/common/bootstrap.h
@@ -76,6 +76,9 @@ char *unargv(int argc, char *argv[]);
void hexdump(caddr_t region, size_t len);
size_t strlenout(vm_offset_t str);
char *strdupout(vm_offset_t str);
+void kern_bzero(vm_offset_t dest, size_t len);
+int kern_pread(int fd, vm_offset_t dest, size_t len, off_t off);
+void *alloc_pread(int fd, off_t off, size_t len);
/* bcache.c */
int bcache_init(u_int nblks, size_t bsize);
diff --git a/sys/boot/common/load_elf.c b/sys/boot/common/load_elf.c
index dd163a8..27cc527 100644
--- a/sys/boot/common/load_elf.c
+++ b/sys/boot/common/load_elf.c
@@ -241,10 +241,8 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off)
int ret;
vm_offset_t firstaddr;
vm_offset_t lastaddr;
- void *buf;
- size_t resid, chunk;
+ size_t chunk;
ssize_t result;
- vm_offset_t dest;
Elf_Addr ssym, esym;
Elf_Dyn *dp;
Elf_Addr adp;
@@ -305,14 +303,10 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off)
phdr[i].p_vaddr + off, fpcopy);
}
if (phdr[i].p_filesz > fpcopy) {
- if (lseek(ef->fd, (off_t)(phdr[i].p_offset + fpcopy),
- SEEK_SET) == -1) {
- printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadexec: cannot seek\n");
- goto out;
- }
- if (archsw.arch_readin(ef->fd, phdr[i].p_vaddr + off + fpcopy,
- phdr[i].p_filesz - fpcopy) != (ssize_t)(phdr[i].p_filesz - fpcopy)) {
- printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadexec: archsw.readin failed\n");
+ if (kern_pread(ef->fd, phdr[i].p_vaddr + off + fpcopy,
+ phdr[i].p_filesz - fpcopy, phdr[i].p_offset + fpcopy) != 0) {
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
+ "_loadimage: read failed\n");
goto out;
}
}
@@ -324,22 +318,8 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off)
(long)(phdr[i].p_vaddr + off + phdr[i].p_memsz - 1));
#endif
- /* no archsw.arch_bzero */
- buf = malloc(PAGE_SIZE);
- if (buf == NULL) {
- printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: malloc() failed\n");
- goto out;
- }
- bzero(buf, PAGE_SIZE);
- resid = phdr[i].p_memsz - phdr[i].p_filesz;
- dest = phdr[i].p_vaddr + off + phdr[i].p_filesz;
- while (resid > 0) {
- chunk = min(PAGE_SIZE, resid);
- archsw.arch_copyin(buf, dest, chunk);
- resid -= chunk;
- dest += chunk;
- }
- free(buf);
+ kern_bzero(phdr[i].p_vaddr + off + phdr[i].p_filesz,
+ phdr[i].p_memsz - phdr[i].p_filesz);
}
#ifdef ELF_VERBOSE
printf("\n");
@@ -361,16 +341,10 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off)
chunk = ehdr->e_shnum * ehdr->e_shentsize;
if (chunk == 0 || ehdr->e_shoff == 0)
goto nosyms;
- shdr = malloc(chunk);
- if (shdr == NULL)
- goto nosyms;
- if (lseek(ef->fd, (off_t)ehdr->e_shoff, SEEK_SET) == -1) {
- printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: cannot lseek() to section headers");
- goto nosyms;
- }
- result = read(ef->fd, shdr, chunk);
- if (result < 0 || (size_t)result != chunk) {
- printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: read section headers failed");
+ shdr = alloc_pread(ef->fd, ehdr->e_shoff, chunk);
+ if (shdr == NULL) {
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
+ "_loadimage: failed to read section headers");
goto nosyms;
}
symtabindex = -1;
diff --git a/sys/boot/common/misc.c b/sys/boot/common/misc.c
index 9f38b60..f1a0491 100644
--- a/sys/boot/common/misc.c
+++ b/sys/boot/common/misc.c
@@ -93,6 +93,74 @@ strdupout(vm_offset_t str)
return(result);
}
+/* Zero a region in kernel space. */
+void
+kern_bzero(vm_offset_t dest, size_t len)
+{
+ char buf[256];
+ size_t chunk, resid;
+
+ bzero(buf, sizeof(buf));
+ resid = len;
+ while (resid > 0) {
+ chunk = min(sizeof(buf), resid);
+ archsw.arch_copyin(buf, dest, chunk);
+ resid -= chunk;
+ dest += chunk;
+ }
+}
+
+/*
+ * Read the specified part of a file to kernel space. Unlike regular
+ * pread, the file pointer is advanced to the end of the read data,
+ * and it just returns 0 if successful.
+ */
+int
+kern_pread(int fd, vm_offset_t dest, size_t len, off_t off)
+{
+ ssize_t nread;
+
+ if (lseek(fd, off, SEEK_SET) == -1) {
+ printf("\nlseek failed\n");
+ return (-1);
+ }
+ nread = archsw.arch_readin(fd, dest, len);
+ if (nread != len) {
+ printf("\nreadin failed\n");
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * Read the specified part of a file to a malloced buffer. The file
+ * pointer is advanced to the end of the read data.
+ */
+void *
+alloc_pread(int fd, off_t off, size_t len)
+{
+ void *buf;
+ ssize_t nread;
+
+ buf = malloc(len);
+ if (buf == NULL) {
+ printf("\nmalloc(%d) failed\n", (int)len);
+ return (NULL);
+ }
+ if (lseek(fd, off, SEEK_SET) == -1) {
+ printf("\nlseek failed\n");
+ free(buf);
+ return (NULL);
+ }
+ nread = read(fd, buf, len);
+ if (nread != len) {
+ printf("\nread failed\n");
+ free(buf);
+ return (NULL);
+ }
+ return (buf);
+}
+
/*
* Display a region in traditional hexdump format.
*/
OpenPOWER on IntegriCloud