Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch separate machine-independent part of kloader.
details: https://anonhg.NetBSD.org/src/rev/b517e8f5a102
branches: trunk
changeset: 521384:b517e8f5a102
user: uch <uch%NetBSD.org@localhost>
date: Tue Jan 29 18:44:22 2002 +0000
description:
separate machine-independent part of kloader.
diffstat:
sys/arch/hpc/hpc/kloader.c | 447 +++++++++++++++++++++++++++
sys/arch/hpc/include/kloader.h | 72 ++++
sys/arch/hpcsh/conf/files.hpcsh | 18 +-
sys/arch/hpcsh/hpcsh/kloader.c | 532 ---------------------------------
sys/arch/hpcsh/hpcsh/kloader.h | 50 ---
sys/arch/hpcsh/hpcsh/kloader_machdep.c | 113 +++++++
sys/arch/hpcsh/include/kloader.h | 40 ++
7 files changed, 683 insertions(+), 589 deletions(-)
diffs (truncated from 1325 to 300 lines):
diff -r b9dc33ae9820 -r b517e8f5a102 sys/arch/hpc/hpc/kloader.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/hpc/hpc/kloader.c Tue Jan 29 18:44:22 2002 +0000
@@ -0,0 +1,447 @@
+/* $NetBSD: kloader.c,v 1.1 2002/01/29 18:44:25 uch Exp $ */
+
+/*-
+ * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "debug_kloader.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/vnode.h>
+#include <sys/namei.h>
+#include <sys/fcntl.h>
+#define ELFSIZE 32
+#include <sys/exec_elf.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/kloader.h>
+
+#ifdef KLOADER_DEBUG
+#define DPRINTF_ENABLE
+#define DPRINTF_DEBUG kloader_debug
+#endif
+#define USE_HPC_DPRINTF
+#define __DPRINTF_EXT
+#include <machine/debug.h>
+
+struct kloader {
+ struct pglist pg_head;
+ struct vm_page *cur_pg;
+ struct vnode *vp;
+ struct kloader_page_tag *tagstart;
+ struct kloader_bootinfo *bootinfo;
+ vaddr_t loader_sp;
+ kloader_bootfunc_t *loader;
+ int setuped;
+
+ struct kloader_ops *ops;
+};
+
+#define BUCKET_SIZE (PAGE_SIZE - sizeof(struct kloader_page_tag))
+#define KLOADER_PROC (&proc0)
+STATIC struct kloader kloader;
+
+STATIC int kloader_load(void);
+STATIC int kloader_alloc_memory(size_t);
+STATIC void kloader_load_segment(vaddr_t, vsize_t, off_t, size_t);
+STATIC void kloader_load_segment_end(void);
+STATIC void kloader_load_bucket(vaddr_t, off_t, size_t);
+STATIC struct vnode *kloader_open(const char *);
+STATIC void kloader_close(void);
+STATIC int kloader_read(size_t, size_t, void *);
+
+#ifdef KLOADER_DEBUG
+STATIC void kloader_pagetag_dump(void);
+STATIC void kloader_bootinfo_dump(void);
+#endif
+
+void
+__kloader_reboot_setup(struct kloader_ops *ops, const char *filename)
+{
+
+ if (kloader.bootinfo == NULL) {
+ PRINTF("No bootinfo.\n");
+ return;
+ }
+
+ if (ops == NULL || ops->jump == NULL || ops->boot == NULL) {
+ PRINTF("No boot operations.\n");
+ return;
+ }
+ kloader.ops = ops;
+
+ PRINTF("kernel file name: %s\n", filename);
+ kloader.vp = kloader_open(filename);
+ if (kloader.vp == NULL)
+ return;
+
+ if (kloader_load() != 0)
+ goto end;
+
+ kloader.setuped = 1;
+#ifdef KLOADER_DEBUG
+ kloader_pagetag_dump();
+#endif
+ end:
+ kloader_close();
+}
+
+void
+kloader_reboot()
+{
+
+ if (!kloader.setuped)
+ return;
+
+#ifdef KLOADER_DEBUG
+ kloader_bootinfo_dump();
+#endif
+ PRINTF("Rebooting...\n");
+
+ (*kloader.ops->jump) (kloader.loader, kloader.loader_sp,
+ kloader.bootinfo, kloader.tagstart);
+}
+
+int
+kloader_load()
+{
+ Elf_Ehdr eh;
+ Elf_Phdr ph[16], *p;
+ Elf_Shdr sh[16];
+ vaddr_t kv;
+ size_t sz;
+ int i;
+
+ /* read kernel's ELF header */
+ kloader_read(0, sizeof(Elf_Ehdr), &eh);
+
+ if (eh.e_ident[EI_MAG0] != ELFMAG0 ||
+ eh.e_ident[EI_MAG1] != ELFMAG1 ||
+ eh.e_ident[EI_MAG2] != ELFMAG2 ||
+ eh.e_ident[EI_MAG3] != ELFMAG3) {
+ PRINTF("not a ELF file\n");
+ return (1);
+ }
+
+ /* read section header */
+ kloader_read(eh.e_shoff, eh.e_shentsize * eh.e_shnum, sh);
+
+ /* read program header */
+ kloader_read(eh.e_phoff, eh.e_phentsize * eh.e_phnum, ph);
+
+ /* calcurate memory size */
+ DPRINTF("file size: ");
+ for (sz = 0, i = 0; i < eh.e_phnum; i++) {
+ if (ph[i].p_type == PT_LOAD) {
+ size_t filesz = ph[i].p_filesz;
+ _DPRINTF("+0x%x", filesz);
+ sz += round_page(filesz);
+ }
+ }
+ _DPRINTF(" entry: %08x\n", eh.e_entry);
+
+ /* get memory for new kernel */
+ if (kloader_alloc_memory(sz) != 0)
+ return (1);
+
+ /* copy newkernel to memory */
+ for (i = 0, p = ph; i < eh.e_phnum; i++, p++) {
+ if (p->p_type == PT_LOAD) {
+ size_t filesz = p->p_filesz;
+ size_t memsz = p->p_memsz;
+ off_t fileofs = p->p_offset;
+ kv = p->p_vaddr;
+ DPRINTF("[%d] vaddr 0x%08lx file size 0x%x"
+ " mem size 0x%x\n", i, kv, filesz, memsz);
+ kloader_load_segment(kv, memsz, fileofs, filesz);
+ kv += memsz;
+ }
+ }
+ /* end tag */
+ kloader_load_segment_end();
+
+ /* copy loader code */
+ KDASSERT(kloader.cur_pg);
+ kloader.loader = (void *)PG_VADDR(kloader.cur_pg);
+ memcpy(kloader.loader, kloader.ops->boot, PAGE_SIZE);
+
+ /* loader stack */
+ kloader.loader_sp = (vaddr_t)kloader.loader + PAGE_SIZE;
+
+ /* kernel entry point */
+ kloader.bootinfo->entry = eh.e_entry;
+
+ DPRINTF("[loader] addr=%p sp=0x%08lx [kernel] addr=0x%08lx\n",
+ kloader.loader, kloader.loader_sp, kloader.bootinfo->entry);
+
+ return (0);
+}
+
+int
+kloader_alloc_memory(size_t sz)
+{
+ extern paddr_t avail_start, avail_end;
+ int i, n, error;
+
+ n = (sz + BUCKET_SIZE - 1) / BUCKET_SIZE /* kernel */
+ + 1; /* 2nd loader */
+
+ TAILQ_INIT(&kloader.pg_head);
+
+ for (i = 0; i < n; i++) {
+ error = uvm_pglistalloc(PAGE_SIZE, avail_start, avail_end,
+ PAGE_SIZE, PAGE_SIZE, &kloader.pg_head, 0, 0);
+ if (error) {
+ uvm_pglistfree(&kloader.pg_head);
+ PRINTF("can't allocate memory.\n");
+ return (1);
+ }
+ }
+
+ kloader.cur_pg = TAILQ_FIRST(&kloader.pg_head);
+ kloader.tagstart = (void *)PG_VADDR(kloader.cur_pg);
+
+ return (0);
+}
+
+void kloader_load_segment(vaddr_t kv, vsize_t memsz, off_t fileofs,
+ size_t filesz)
+{
+ int i, n;
+
+ if (filesz == 0)
+ return;
+
+ n = filesz / BUCKET_SIZE;
+ for (i = 0; i < n; i ++) {
+ kloader_load_bucket(kv, fileofs, BUCKET_SIZE);
+ kv += BUCKET_SIZE;
+ fileofs += BUCKET_SIZE;
+ }
+
+ n = filesz % BUCKET_SIZE;
+ if (n) {
+ kloader_load_bucket(kv, fileofs, n);
+ }
+}
+
+void
+kloader_load_segment_end()
+{
+ struct vm_page *pg;
+
+ pg = TAILQ_PREV(kloader.cur_pg, pglist, pageq);
+
+ ((struct kloader_page_tag *)PG_VADDR(pg))->next = 0;
+}
+
+void
+kloader_load_bucket(vaddr_t kv, off_t ofs, size_t sz)
+{
+ struct vm_page *pg = kloader.cur_pg;
+ vaddr_t addr = PG_VADDR(pg);
+ struct kloader_page_tag *tag = (void *)addr;
+
+ KDASSERT(pg != NULL);
+
+ tag->src = addr + sizeof(struct kloader_page_tag);
+ tag->dst = kv;
+ tag->sz = sz;
+
+ kloader_read(ofs, sz, (void *)tag->src);
+
+ pg = TAILQ_NEXT(pg, pageq);
+ tag->next = PG_VADDR(pg);
+ kloader.cur_pg = pg;
+}
+
+/*
+ * file access
+ */
+struct vnode *
+kloader_open(const char *filename)
+{
+ struct proc *p = KLOADER_PROC;
Home |
Main Index |
Thread Index |
Old Index