Index: i386/multiboot.c =================================================================== RCS file: /home/joerg/repo/netbsd/src/sys/arch/i386/i386/multiboot.c,v retrieving revision 1.16 diff -u -p -r1.16 multiboot.c --- i386/multiboot.c 28 Apr 2008 20:23:24 -0000 1.16 +++ i386/multiboot.c 8 Oct 2008 20:00:40 -0000 @@ -32,6 +32,8 @@ #include __KERNEL_RCSID(0, "$NetBSD: multiboot.c,v 1.16 2008/04/28 20:23:24 martin Exp $"); +#include "opt_multiboot.h" + #include #include #include Index: include/multiboot.h =================================================================== RCS file: /home/joerg/repo/netbsd/src/sys/arch/i386/include/multiboot.h,v retrieving revision 1.6 diff -u -p -r1.6 multiboot.h --- include/multiboot.h 28 Apr 2008 20:23:24 -0000 1.6 +++ include/multiboot.h 8 Oct 2008 20:00:40 -0000 @@ -29,12 +29,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#if defined(_KERNEL) - -#include "opt_multiboot.h" - -#if defined(MULTIBOOT) - /* --------------------------------------------------------------------- */ /* @@ -70,9 +64,9 @@ struct multiboot_header { /* * Symbols defined in locore.S. */ -#if !defined(_LOCORE) +#if !defined(_LOCORE) && defined(_KERNEL) extern struct multiboot_header *Multiboot_Header; -#endif /* !defined(_LOCORE) */ +#endif /* !defined(_LOCORE) && defined(_KERNEL) */ /* --------------------------------------------------------------------- */ @@ -111,8 +105,8 @@ struct multiboot_info { char * mi_cmdline; /* Valid if mi_flags sets MULTIBOOT_INFO_HAS_MODS. */ - uint32_t unused_mi_mods_count; - vaddr_t unused_mi_mods_addr; + uint32_t mi_mods_count; + vaddr_t mi_mods_addr; /* Valid if mi_flags sets MULTIBOOT_INFO_HAS_{AOUT,ELF}_SYMS. */ uint32_t mi_elfshdr_num; @@ -180,6 +174,18 @@ struct multiboot_mmap { uint32_t mm_type; }; +/* + * Modules. This describes an entry in the modules table as pointed + * to by mi_mods_addr. + */ + +struct multiboot_module { + uint32_t mmo_start; + uint32_t mmo_end; + char * mmo_string; + uint32_t mmo_reserved; +}; + #endif /* !defined(_LOCORE) */ /* --------------------------------------------------------------------- */ @@ -187,7 +193,7 @@ struct multiboot_mmap { /* * Prototypes for public functions defined in multiboot.c. */ -#if !defined(_LOCORE) +#if !defined(_LOCORE) && defined(_KERNEL) void multiboot_pre_reloc(struct multiboot_info *); void multiboot_post_reloc(void); void multiboot_print_info(void); @@ -195,7 +201,3 @@ bool multiboot_ksyms_init(void); #endif /* !defined(_LOCORE) */ /* --------------------------------------------------------------------- */ - -#endif /* defined(MULTIBOOT) */ - -#endif /* defined(_KERNEL) */ Index: stand/boot/boot2.c =================================================================== RCS file: /home/joerg/repo/netbsd/src/sys/arch/i386/stand/boot/boot2.c,v retrieving revision 1.37 diff -u -p -r1.37 boot2.c --- stand/boot/boot2.c 26 Sep 2008 18:42:52 -0000 1.37 +++ stand/boot/boot2.c 8 Oct 2008 20:35:07 -0000 @@ -133,6 +133,7 @@ void command_dev(char *); void command_consdev(char *); void command_modules(char *); void command_load(char *); +void command_multiboot(char *); const struct bootblk_command commands[] = { { "help", command_help }, @@ -144,6 +145,7 @@ const struct bootblk_command commands[] { "consdev", command_consdev }, { "modules", command_modules }, { "load", command_load }, + { "multiboot", command_multiboot }, { NULL, NULL }, }; @@ -685,6 +687,7 @@ command_help(char *arg) "consdev {pc|com[0123]|com[0123]kbd|auto}\n" "modules {enabled|disabled}\n" "load {path_to_module}\n" + "multiboot [xdNx:][filename] []\n" "help|?\n" "quit\n"); } @@ -800,6 +803,9 @@ command_load(char *arg) size_t len; char *str; + while (*arg == ' ' || *arg == '\t') + ++arg; + bm = alloc(sizeof(boot_module_t)); len = strlen(arg) + 1; str = alloc(len); @@ -819,3 +825,17 @@ command_load(char *arg) bmp->bm_next = bm; } } + +void +command_multiboot(char *arg) +{ + char *filename; + + filename = arg; + if (exec_multiboot(filename, gettrailer(arg)) < 0) + printf("multiboot: %s: %s\n", sprint_bootsel(filename), + strerror(errno)); + else + printf("boot returned\n"); +} + Index: stand/lib/Makefile =================================================================== RCS file: /home/joerg/repo/netbsd/src/sys/arch/i386/stand/lib/Makefile,v retrieving revision 1.24 diff -u -p -r1.24 Makefile --- stand/lib/Makefile 17 Oct 2007 19:54:59 -0000 1.24 +++ stand/lib/Makefile 8 Oct 2008 20:00:40 -0000 @@ -21,7 +21,7 @@ SRCS+= getsecs.c biosgetrtc.S biosdelay. SRCS+= biosmem.S getextmemx.c biosmemx.S printmemlist.c SRCS+= pread.c menuutils.c parseutils.c SRCS+= bootinfo.c bootinfo_biosgeom.c bootinfo_memmap.c -SRCS+= startprog.S panic.c +SRCS+= startprog.S multiboot.S panic.c SRCS+= biosgetsystime.S cpufunc.S SRCS+= realprot.S message.S dump_eax.S pvcopy.S putstr.S .if (${I386_INCLUDE_DISK} == "yes") Index: stand/lib/exec.c =================================================================== RCS file: /home/joerg/repo/netbsd/src/sys/arch/i386/stand/lib/exec.c,v retrieving revision 1.29 diff -u -p -r1.29 exec.c --- stand/lib/exec.c 26 Sep 2008 14:12:50 -0000 1.29 +++ stand/lib/exec.c 8 Oct 2008 21:57:50 -0000 @@ -103,6 +103,8 @@ #include #include +#include + #include #include @@ -293,13 +295,25 @@ static const char * module_path(boot_module_t *bm) { static char buf[256]; - const char *name; + char name_buf[256]; + const char *name, *name2; name = bm->bm_path; + for (name2 = name; *name2; ++name2) { + if (*name2 == ' ' || *name2 == '\t') { + strlcpy(name_buf, name, sizeof(name_buf)); + if (name2 - name < sizeof(name_buf)) + name_buf[name2 - name] = '\0'; + name = name_buf; + break; + } + } if (name[0] == '/') - return name; - snprintf(buf, sizeof(buf), "%s/%s/%s.kmod", module_base, bm->bm_path, - bm->bm_path); + snprintf(buf, sizeof(buf), "%s", name); + else + snprintf(buf, sizeof(buf), "%s/%s/%s.kmod", + module_base, name, name); + return buf; } @@ -396,3 +410,179 @@ module_init(void) } btinfo_modulelist->endpa = image_end; } + +int +exec_multiboot(const char *file, char *args) +{ + struct multiboot_info *mbi; + struct multiboot_module *mbm; + struct bi_modulelist_entry *bim; + int fd, i, len; + u_long marks[MARK_MAX]; + physaddr_t loadaddr = 0; +#ifdef XMS + u_long xmsmem; + physaddr_t origaddr = 0; +#endif + char *machine, *cmdline; + +#ifdef DEBUG + printf("exec: file=%s\n", file ? file : "NULL"); +#endif + + mbi = alloc(sizeof(struct multiboot_info)); + mbi->mi_flags = MULTIBOOT_INFO_HAS_MEMORY; + mbi->mi_mem_upper = getextmem(); + mbi->mi_mem_lower = getbasemem(); + +#ifdef XMS + if ((getextmem1() == 0) && (xmsmem = checkxms())) { + u_long kernsize; + + /* + * With "CONSERVATIVE_MEMDETECT", extmem is 0 because + * getextmem() is getextmem1(). Without, the "smart" + * methods could fail to report all memory as well. + * xmsmem is a few kB less than the actual size, but + * better than nothing. + */ + if (xmsmem > mbi->mi_mem_upper) + mbi->mi_mem_upper = xmsmem; + /* + * Get the size of the kernel + */ + marks[MARK_START] = loadaddr; + if ((fd = loadfile(file, marks, COUNT_KERNEL)) == -1) + goto out; + close(fd); + + kernsize = marks[MARK_END]; + kernsize = (kernsize + 1023) / 1024; + + loadaddr = xmsalloc(kernsize); + if (!loadaddr) + return ENOMEM; + } +#endif + marks[MARK_START] = loadaddr; + if ((fd = loadfile(file, marks, LOAD_KERNEL)) == -1) + goto out; + + close(fd); + + /* + * Gather some information for the kernel. Do this after the + * "point of no return" to avoid memory leaks. + * (but before DOS might be trashed in the XMS case) + */ +#ifdef PASS_BIOSGEOM + bi_getbiosgeom(); +#endif +#ifdef PASS_MEMMAP + bi_getmemmap(); +#endif + +#ifdef XMS + if (loadaddr != origaddr) { + /* + * We now have done our last DOS IO, so we may + * trash the OS. Copy the data from the temporary + * buffer to its real address. + */ + marks[MARK_START] -= loadaddr; + marks[MARK_END] -= loadaddr; + marks[MARK_SYM] -= loadaddr; + marks[MARK_END] -= loadaddr; + ppbcopy(loadaddr, origaddr, marks[MARK_END]); + } +#endif + marks[MARK_END] = (((u_long) marks[MARK_END] + sizeof(int) - 1)) & + (-sizeof(int)); + image_end = marks[MARK_END]; + kernel_loaded = true; + + if (args) { + size_t file_len; + + mbi->mi_flags |= MULTIBOOT_INFO_HAS_CMDLINE; + file_len = strlen(file); + len = strlen(args) + file_len + 2; + cmdline = alloc(len); + memcpy(cmdline, file, file_len); + cmdline[file_len] = ' '; + memcpy(cmdline + file_len + 1, args, len); + mbi->mi_cmdline = (char *) vtophys(cmdline); + } + + /* pull in any modules if necessary */ + if (boot_modules_enabled) { + switch (netbsd_elf_class) { + case ELFCLASS32: + machine = "i386"; + break; + case ELFCLASS64: + machine = "amd64"; + break; + default: + machine = "generic"; + break; + } + if (netbsd_version / 1000000 % 100 == 99) { + /* -current */ + snprintf(module_base, sizeof(module_base), + "/stand/%s/%d.%d.%d/modules", machine, + netbsd_version / 100000000, + netbsd_version / 1000000 % 100, + netbsd_version / 100 % 100); + } else if (netbsd_version != 0) { + /* release */ + snprintf(module_base, sizeof(module_base), + "/stand/%s/%d.%d/modules", machine, + netbsd_version / 100000000, + netbsd_version / 1000000 % 100); + } + module_init(); + if (btinfo_modulelist) { + mbm = alloc(sizeof(struct multiboot_module) * + btinfo_modulelist->num); + + bim = (struct bi_modulelist_entry *) + (((char *) btinfo_modulelist) + + sizeof(struct btinfo_modulelist)); + for (i = 0; i < btinfo_modulelist->num; i++) { + mbm[i].mmo_start = bim->base; + mbm[i].mmo_end = bim->base + bim->len; + mbm[i].mmo_string = (char *)vtophys(bim->path); + mbm[i].mmo_reserved = 0; + bim++; + } + mbi->mi_flags |= MULTIBOOT_INFO_HAS_MODS; + mbi->mi_mods_count = btinfo_modulelist->num; + mbi->mi_mods_addr = vtophys(mbm); + } + } + +#ifdef DEBUG + printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n", marks[MARK_ENTRY], + marks[MARK_NSYM], marks[MARK_SYM], marks[MARK_END]); +#endif + + +#if 0 + if (btinfo_symtab.nsym) { + mbi->mi_flags |= MULTIBOOT_INFO_HAS_ELF_SYMS; + mbi->mi_elfshdr_addr = marks[MARK_SYM]; + btinfo_symtab.nsym = marks[MARK_NSYM]; + btinfo_symtab.ssym = marks[MARK_SYM]; + btinfo_symtab.esym = marks[MARK_END]; +#endif + + multiboot(marks[MARK_ENTRY], vtophys(mbi), + x86_trunc_page(mbi->mi_mem_lower*1024)); + panic("exec returned"); + +out: + dealloc(mbi, 0); + return -1; +} + Index: stand/lib/libi386.h =================================================================== RCS file: /home/joerg/repo/netbsd/src/sys/arch/i386/stand/lib/libi386.h,v retrieving revision 1.25 diff -u -p -r1.25 libi386.h --- stand/lib/libi386.h 26 Sep 2008 14:12:50 -0000 1.25 +++ stand/lib/libi386.h 8 Oct 2008 20:00:40 -0000 @@ -36,8 +36,10 @@ physaddr_t vtophys(void *); ssize_t pread(int, void *, size_t); void startprog(physaddr_t, int, unsigned long *, physaddr_t); +void multiboot(physaddr_t, physaddr_t, physaddr_t); int exec_netbsd(const char *, physaddr_t, int, int); +int exec_multiboot(const char *, char *); void delay(int); int getbasemem(void); Index: stand/lib/multiboot.S =================================================================== RCS file: stand/lib/multiboot.S diff -N stand/lib/multiboot.S --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ stand/lib/multiboot.S 8 Oct 2008 18:02:39 -0000 @@ -0,0 +1,124 @@ +/* $NetBSD: $ */ + +/* starts program in protected mode / flat space + with given stackframe + needs global variables flatcodeseg and flatdataseg + (gdt offsets) + derived from: NetBSD:sys/arch/i386/stand/lib/startprog.S + */ + +/*- + * Copyright (c) 2008 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. + * + * 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. + */ + +/* + * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 + * + * Mach Operating System + * Copyright (c) 1992, 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +/* + Copyright 1988, 1989, 1990, 1991, 1992 + by Intel Corporation, Santa Clara, California. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appears in all +copies and that both the copyright notice and this permission notice +appear in supporting documentation, and that the name of Intel +not be used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. + +INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, +IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, +NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION +WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#include +#define MULTIBOOT_INFO_MAGIC 0x2BADB002 + +/* + * multiboot(phyaddr,header,stack) + * start the program on protected mode where phyaddr is the entry point + */ +ENTRY(multiboot) + pushl %ebp + movl %esp, %ebp + + # prepare a new stack + movl $flatdataseg, %eax + movw %ax, %es # for arg copy + movl 16(%ebp), %ebx # stack + subl $4,%ebx + movl %ebx, %edi + + movl 12(%ebp), %ebx # header + movl 8(%ebp), %ecx # entry + + # set new stackptr (movsl decd sp 1 more -> dummy return address) + movw %ax, %ss + movl %edi, %esp + + # push on our entry address + movl $flatcodeseg, %eax # segment + pushl %eax + pushl %ecx #entry + + # convert over the other data segs + movl $flatdataseg, %eax + mov %ax, %ds + mov %ax, %es + + movl $MULTIBOOT_INFO_MAGIC, %eax + # convert the PC (and code seg) + lret