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