Index: share/man/man4/options.4 =================================================================== RCS file: /cvsroot/src/share/man/man4/options.4,v retrieving revision 1.307 diff -u -p -r1.307 options.4 --- share/man/man4/options.4 2 Feb 2006 17:35:37 -0000 1.307 +++ share/man/man4/options.4 3 Feb 2006 10:10:43 -0000 @@ -30,7 +30,7 @@ .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" .\" -.Dd February 2, 2006 +.Dd February 3, 2006 .Os .Dt OPTIONS 4 .Sh NAME @@ -2420,6 +2420,19 @@ The duration of each beep when .Cd options BEEP_ONHALT is enabled, in milliseconds. Defaults to 250. +.It Cd options MULTIBOOT +Makes the kernel Multiboot-compliant, allowing it to be booted through +a Multiboot-compliant boot manager such as GRUB. +See +.Xr multiboot 8 +for more information. +.It Cd options MULTIBOOT_SYMTAB_SPACE=nbytes +Space (in bytes) reserved in memory to store the kernel's symbol table. +If the symbol table is bigger than this space, it will not be loaded; +if it is smaller, the unused memory will be claimed by the kernel and +used normally. +You shouldn't need to touch this variable. +Defaults to 1048576 bytes (one megabyte). .El .Ss isa-specific Options Options specific to Index: share/man/man8/man8.i386/Makefile =================================================================== RCS file: /cvsroot/src/share/man/man8/man8.i386/Makefile,v retrieving revision 1.17 diff -u -p -r1.17 Makefile --- share/man/man8/man8.i386/Makefile 24 Oct 2003 20:26:58 -0000 1.17 +++ share/man/man8/man8.i386/Makefile 3 Feb 2006 10:10:43 -0000 @@ -1,7 +1,7 @@ # $NetBSD: Makefile,v 1.17 2003/10/24 20:26:58 jdolecek Exp $ # from: @(#)Makefile 8.1 (Berkeley) 6/5/93 -MAN= boot.8 dosboot.8 boot_console.8 w95boot.8 pxeboot.8 mbr.8 +MAN= boot.8 dosboot.8 boot_console.8 multiboot.8 w95boot.8 pxeboot.8 mbr.8 MLINKS= mbr.8 bootselect.8 MANSUBDIR=/i386 Index: share/man/man8/man8.i386/multiboot.8 =================================================================== RCS file: share/man/man8/man8.i386/multiboot.8 diff -N share/man/man8/man8.i386/multiboot.8 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ share/man/man8/man8.i386/multiboot.8 3 Feb 2006 10:10:43 -0000 @@ -0,0 +1,133 @@ +.\" $NetBSD$ +.\" +.\" Copyright (c) 2006 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Julio M. Merino Vidal. +.\" +.\" 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. +.\" +.Dd Februrary 3, 2006 +.Os +.Dt MULTIBOOT 8 i386 +.Sh NAME +.Nm multiboot +.Nd procedure for booting NetBSD/i386 from a Multiboot-compliant boot loader +.Sh DESCRIPTION +Multiboot is a specification that defines a protocol between a boot loader +and a kernel. +This protocol allows passing boot information between the two in a standard +way, allowing any Multiboot-compliant boot loader to boot any +Multiboot-compliant kernel. +The +.Nx +kernel supports Multiboot if it was compiled with +.Cd options MULTIBOOT +(the default in the +.Sq GENERIC +and +.Sq GENERIC_LAPTOP +configurations). +.Pp +Unlike when using the native boot loader, the +.Nx +kernel recognizes a set of command line arguments if booted through a +Multiboot-compliant boot loader. +This is because the Multiboot protocol is not complete enough to completely +configure a +.Nx +kernel. +.Pp +The following arguments are recognized: +.Bl -tag -width consoleXspeedX +.It Va console +Specifies the console device name. +Can be one of +.Sq com +or +.Sq pc . +If the former, +.Va console_addr +and +.Va console_speed +should be given too. +.It Va console_addr +Specifies the serial port address for the console. +Defaults to the value of +.Cd options CONADDR +or +.Sq 0x3f8 +if this was not given. +.It Va console_speed +Specifies the serial port speed for the console. +Defaults to the value of +.Cd options CONSPEED +or +.Sq 9600 +if this was not given. +.It Va root +Specifies the name of the device to be mounted as the root partition. +It should not be needed because the kernel tries its best to guess which +is the root partition (basing the decision on the device from which the +kernel was loaded from). +In cases where the automatic detection fails, this flag comes useful. +Example: +.Sq root=wd0e . +.El +.Ss Booting with GRUB Legacy +GRUB Legacy can load Multiboot-enabled +.Nx +kernels properly, assuming that a patch which fixes an issue with the +Multiboot header parsing is applied. +This patch is not yet merged with the stock sources but is available in +pkgsrc; hence, if you have +.Sq grub-0.97nb4 +or a better version, the bug is fixed. +However, if you are building GRUB Legacy outside pkgsrc, you need to manually +apply the patch located at: +.Pa ftp://ftp.NetBSD.org/pub/NetBSD/misc/jmmv/grub-fix-addresses.diff . +.Pp +With the patch applied, a +.Nx +kernel can be booted using the traditional GRUB Legacy syntax. +For example: +.Bd -literal +kernel (fd0)/netbsd.gz -c console=pc root=wd0e +.Ed +.Sh SEE ALSO +.Xr options 4 +.Sh HISTORY +.Nm +support first appeared in +.Nx 4.0 . +.Sh AUTHORS +.Nm +support was added by +.An Julio M. Merino Vidal Aq jmmv@NetBSD.org . Index: share/man/man9/Makefile =================================================================== RCS file: /cvsroot/src/share/man/man9/Makefile,v retrieving revision 1.189 diff -u -p -r1.189 Makefile --- share/man/man9/Makefile 17 Jan 2006 17:29:28 -0000 1.189 +++ share/man/man9/Makefile 3 Feb 2006 10:10:44 -0000 @@ -27,7 +27,7 @@ MAN= altq.9 arc4random.9 arp.9 audio.9 a kprintf.9 kthread.9 linedisc.9 lock.9 log.9 ltsleep.9 \ malloc.9 mbuf.9 mca.9 memcmp.9 memcpy.9 memmove.9 memset.9 \ microtime.9 mstohz.9 m_tag.9 namecache.9 namei.9 need_resched.9 \ - opencrypto.9 \ + opencrypto.9 optstr.9 \ panic.9 pci.9 pci_configure_bus.9 pci_intr.9 pckbport.9 \ pcmcia.9 pfil.9 physio.9 pmap.9 pmatch.9 pmc.9 \ pool.9 pool_cache.9 powerhook_establish.9 ppsratecheck.9 \ @@ -334,6 +334,7 @@ MLINKS+=opencrypto.9 crypto_get_driverid opencrypto.9 crypto_kdispatch.9 \ opencrypto.9 crypto_getreq.9 \ opencrypto.9 crypto_freereq.9 +MLINKS+=optstr.9 optstr_get.9 MLINKS+=pci.9 pci_conf_read.9 \ pci.9 pci_conf_write.9 \ pci.9 pci_conf_print.9 \ Index: share/man/man9/optstr.9 =================================================================== RCS file: share/man/man9/optstr.9 diff -N share/man/man9/optstr.9 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ share/man/man9/optstr.9 3 Feb 2006 10:10:44 -0000 @@ -0,0 +1,88 @@ +.\" $NetBSD$ +.\" +.\" Copyright (c) 2006 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Julio M. Merino Vidal. +.\" +.\" 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. +.\" +.Dd February 3, 2006 +.Dt OPTSTR 9 +.Os +.Sh NAME +.Nm optstr_get +.Nd Options string management +.Sh SYNOPSIS +.In sys/optstr.h +.Ft boolean_t +.Fn optstr_get "const char *optstr" "const char *key" "char *buf" "size_t bufsize" +.Sh DESCRIPTION +An options string is a list of key/value pairs represented in textual form. +Each pair is expressed as +.Sq 'key=value' +and is separated from other pairs by one or more spaces. +For example: +.Bd -literal +key1=value1 key2=value2 key3=value3 +.Ed +.Pp +Options strings are used to pass information between userland programs and +the kernel in a binary-agnostic way. +This makes them endianness and ABI independent. +.Sh FUNCTIONS +The following functions are provided to manage options strings: +.Bl -tag -width compact +.It Fn optstr_get "optstr" "key" "buf" "bufsize" +Scans the +.Va optstr +options string looking for the key +.Va key +and stores its value in the buffer pointed to by +.Va buf +copying a maximum of +.Va bufsize +bytes. +Returns +.Sq TRUE +if the key was found or +.Sq FALSE +otherwise, in which case +.Va buf +is left unmodified. +.El +.Sh CODE REFERENCES +The options string management functions are implemented within the files +.Pa sys/kern/subr_optstr.c +and +.Pa sys/sys/optstr.h . +.Sh HISTORY +Options strings appeared in +.Nx 4.0 . Index: distrib/sets/lists/comp/md.i386 =================================================================== RCS file: /cvsroot/src/distrib/sets/lists/comp/md.i386,v retrieving revision 1.87 diff -u -p -r1.87 md.i386 --- distrib/sets/lists/comp/md.i386 3 May 2005 08:24:15 -0000 1.87 +++ distrib/sets/lists/comp/md.i386 3 Feb 2006 10:10:44 -0000 @@ -45,6 +45,7 @@ ./usr/include/i386/mcontext.h comp-c-include ./usr/include/i386/mouse.h comp-obsolete obsolete ./usr/include/i386/mtrr.h comp-c-include +./usr/include/i386/multiboot.h comp-c-include ./usr/include/i386/npx.h comp-c-include ./usr/include/i386/param.h comp-c-include ./usr/include/i386/pcb.h comp-c-include Index: distrib/sets/lists/comp/mi =================================================================== RCS file: /cvsroot/src/distrib/sets/lists/comp/mi,v retrieving revision 1.845 diff -u -p -r1.845 mi --- distrib/sets/lists/comp/mi 2 Feb 2006 15:26:34 -0000 1.845 +++ distrib/sets/lists/comp/mi 3 Feb 2006 10:10:46 -0000 @@ -1395,6 +1395,7 @@ ./usr/include/sys/mtio.h comp-c-include ./usr/include/sys/namei.h comp-c-include ./usr/include/sys/null.h comp-c-include +./usr/include/sys/optstr.h comp-c-include ./usr/include/sys/param.h comp-c-include ./usr/include/sys/pipe.h comp-c-include ./usr/include/sys/pmc.h comp-c-include @@ -5432,6 +5433,8 @@ ./usr/share/man/cat9/nextrunqueue.0 comp-sys-catman .cat ./usr/share/man/cat9/old_sysctl.0 comp-sys-catman .cat ./usr/share/man/cat9/opencrypto.0 comp-sys-catman .cat +./usr/share/man/cat9/optstr.0 comp-sys-catman .cat +./usr/share/man/cat9/optstr_get.0 comp-sys-catman .cat ./usr/share/man/cat9/panic.0 comp-sys-catman .cat ./usr/share/man/cat9/pci.0 comp-sys-catman .cat ./usr/share/man/cat9/pci_conf_hook.0 comp-sys-catman .cat @@ -9376,6 +9379,8 @@ ./usr/share/man/man9/nextrunqueue.9 comp-sys-man .man ./usr/share/man/man9/old_sysctl.9 comp-sys-man .man ./usr/share/man/man9/opencrypto.9 comp-sys-man .man +./usr/share/man/man9/optstr.9 comp-sys-man .man +./usr/share/man/man9/optstr_get.9 comp-sys-man .man ./usr/share/man/man9/panic.9 comp-sys-man .man ./usr/share/man/man9/pci.9 comp-sys-man .man ./usr/share/man/man9/pci_conf_hook.9 comp-sys-man .man Index: distrib/sets/lists/man/mi =================================================================== RCS file: /cvsroot/src/distrib/sets/lists/man/mi,v retrieving revision 1.849 diff -u -p -r1.849 mi --- distrib/sets/lists/man/mi 2 Feb 2006 15:26:34 -0000 1.849 +++ distrib/sets/lists/man/mi 3 Feb 2006 10:10:47 -0000 @@ -1848,6 +1848,7 @@ ./usr/share/man/cat8/i386/ispcvt.0 man-obsolete obsolete ./usr/share/man/cat8/i386/kbdio.0 man-obsolete obsolete ./usr/share/man/cat8/i386/makedev.0 man-obsolete obsolete +./usr/share/man/cat8/i386/multiboot.0 man-sys-catman .cat ./usr/share/man/cat8/i386/mbr.0 man-sys-catman .cat ./usr/share/man/cat8/i386/pxeboot.0 man-sys-catman .cat ./usr/share/man/cat8/i386/reboot.0 man-obsolete obsolete @@ -4147,6 +4148,7 @@ ./usr/share/man/man8/i386/ispcvt.8 man-obsolete obsolete ./usr/share/man/man8/i386/kbdio.8 man-obsolete obsolete ./usr/share/man/man8/i386/makedev.8 man-obsolete obsolete +./usr/share/man/man8/i386/multiboot.8 man-sys-man .man ./usr/share/man/man8/i386/mbr.8 man-sys-man .man ./usr/share/man/man8/i386/pxeboot.8 man-sys-man .man ./usr/share/man/man8/i386/reboot.8 man-obsolete obsolete Index: doc/CHANGES =================================================================== RCS file: /cvsroot/src/doc/CHANGES,v retrieving revision 1.570 diff -u -p -r1.570 CHANGES --- doc/CHANGES 3 Feb 2006 08:23:58 -0000 1.570 +++ doc/CHANGES 3 Feb 2006 10:10:47 -0000 @@ -178,3 +178,4 @@ Changes from NetBSD 3.0 to NetBSD 4.0: devices like harddisc partions and vnd's. [reinoud 20060202] binutils: updated to FSF binutils 2.16.1 release. [skrll 20060202] + i386: Add support for the Multiboot Specification. [jmmv 20060203] Index: sys/arch/i386/conf/files.i386 =================================================================== RCS file: /cvsroot/src/sys/arch/i386/conf/files.i386,v retrieving revision 1.276 diff -u -p -r1.276 files.i386 --- sys/arch/i386/conf/files.i386 1 Jan 2006 12:12:43 -0000 1.276 +++ sys/arch/i386/conf/files.i386 3 Feb 2006 10:10:47 -0000 @@ -64,6 +64,11 @@ defparam opt_beep.h BEEP_ONHALT_PITCH B # Enhanced SpeedStep defflag ENHANCED_SPEEDSTEP +# Multiboot support +defflag opt_multiboot.h MULTIBOOT +defparam opt_multiboot.h MULTIBOOT_SYMTAB_SPACE +file arch/i386/i386/multiboot.c multiboot + # PowerNow K7 defflag POWERNOW_K7 Index: sys/arch/i386/conf/GENERIC =================================================================== RCS file: /cvsroot/src/sys/arch/i386/conf/GENERIC,v retrieving revision 1.722 diff -u -p -r1.722 GENERIC --- sys/arch/i386/conf/GENERIC 2 Feb 2006 21:32:09 -0000 1.722 +++ sys/arch/i386/conf/GENERIC 3 Feb 2006 10:10:47 -0000 @@ -50,6 +50,9 @@ options MTRR # memory-type range regis # doesn't work with MP just yet.. #options PERFCTRS # performance-monitoring counters support +options MULTIBOOT # Multiboot support (see multiboot(8)) +#options MULTIBOOT_SYMTAB_SPACE=1048576 + # delay between "rebooting ..." message and hardware reset, in milliseconds #options CPURESET_DELAY=2000 Index: sys/arch/i386/conf/GENERIC_LAPTOP =================================================================== RCS file: /cvsroot/src/sys/arch/i386/conf/GENERIC_LAPTOP,v retrieving revision 1.170 diff -u -p -r1.170 GENERIC_LAPTOP --- sys/arch/i386/conf/GENERIC_LAPTOP 3 Feb 2006 01:09:49 -0000 1.170 +++ sys/arch/i386/conf/GENERIC_LAPTOP 3 Feb 2006 10:10:48 -0000 @@ -33,6 +33,9 @@ options ENHANCED_SPEEDSTEP options MTRR # memory-type range register syscall support #options PERFCTRS # performance-monitoring counters support +options MULTIBOOT # Multiboot support (see multiboot(8)) +#options MULTIBOOT_SYMTAB_SPACE=1048576 + # delay between "rebooting ..." message and hardware reset, in milliseconds #options CPURESET_DELAY=2000 Index: sys/arch/i386/i386/locore.S =================================================================== RCS file: /cvsroot/src/sys/arch/i386/i386/locore.S,v retrieving revision 1.36 diff -u -p -r1.36 locore.S --- sys/arch/i386/i386/locore.S 11 Dec 2005 12:17:41 -0000 1.36 +++ sys/arch/i386/i386/locore.S 3 Feb 2006 10:10:48 -0000 @@ -101,6 +101,8 @@ #include #endif +#include + /* LINTSTUB: include */ /* LINTSTUB: include */ /* LINTSTUB: include */ @@ -224,6 +226,40 @@ tmpstk: .globl start start: movw $0x1234,0x472 # warm boot +#if defined(MULTIBOOT) + jmp 1f + + .align 4 + .globl Multiboot_Header +_C_LABEL(Multiboot_Header): +#define MULTIBOOT_HEADER_FLAGS (MULTIBOOT_HEADER_WANT_MEMORY | \ + MULTIBOOT_HEADER_HAS_ADDR) + .long MULTIBOOT_HEADER_MAGIC + .long MULTIBOOT_HEADER_FLAGS + .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) + .long RELOC(Multiboot_Header) + .long RELOC(start) + .long RELOC(_edata) + .long RELOC(_end) + MULTIBOOT_SYMTAB_SPACE + .long RELOC(start) + +1: + /* Check if we are being executed by a Multiboot-compliant boot + * loader. */ + cmpl $MULTIBOOT_INFO_MAGIC,%eax + jne 1f + + /* Indeed, a multiboot-compliat boot loader executed us. We copy + * the received Multiboot information structure into kernel's data + * space to process it later -- after we are relocated. It will + * be safer to run complex C code than doing it at this point. */ + pushl %ebx # Address of Multiboot information + call _C_LABEL(multiboot_pre_reloc) + addl $4,%esp + jmp 3f +#endif + +1: /* * Load parameters from stack * (howto, [bootdev], bootinfo, esym, basemem, extmem). @@ -284,6 +320,7 @@ start: movw $0x1234,0x472 # warm boot movl %eax,RELOC(biosbasemem) 1: +3: /* First, reset the PSL. */ pushl $PSL_MBO popfl @@ -633,6 +670,14 @@ begin: movl %esi,PCB_CR3(%eax) # pcb->pcb_cr3 xorl %ebp,%ebp # mark end of frames +#if defined(MULTIBOOT) + /* It is now safe to parse the Multiboot information structure + * we saved before from C code. Note that we cannot delay its + * parsing any more because initgdt (called below) needs to make + * use of this information. */ + call _C_LABEL(multiboot_post_reloc) +#endif + subl $NGDT*8, %esp # space for temporary gdt pushl %esp call _C_LABEL(initgdt) Index: sys/arch/i386/i386/machdep.c =================================================================== RCS file: /cvsroot/src/sys/arch/i386/i386/machdep.c,v retrieving revision 1.569 diff -u -p -r1.569 machdep.c --- sys/arch/i386/i386/machdep.c 30 Dec 2005 13:37:57 -0000 1.569 +++ sys/arch/i386/i386/machdep.c 3 Feb 2006 10:10:49 -0000 @@ -143,6 +143,7 @@ __KERNEL_RCSID(0, "$NetBSD: machdep.c,v #include #include #include +#include #include #include @@ -303,6 +304,10 @@ cpu_startup() printf("%s%s", copyright, version); +#ifdef MULTIBOOT + multiboot_print_info(); +#endif + #ifdef TRAPLOG /* * Enable recording of branch from/to in MSR's Index: sys/arch/i386/i386/multiboot.c =================================================================== RCS file: sys/arch/i386/i386/multiboot.c diff -N sys/arch/i386/i386/multiboot.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/arch/i386/i386/multiboot.c 3 Feb 2006 10:10:49 -0000 @@ -0,0 +1,717 @@ +/* $NetBSD$ */ + +/*- + * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Julio M. Merino Vidal. + * + * 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 +__KERNEL_RCSID(0, "$NetBSD$"); + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#if !defined(MULTIBOOT) +# error "MULTIBOOT not defined; this cannot happen." +#endif + +/* --------------------------------------------------------------------- */ + +/* + * External variables. All of them, with the exception of 'end', must + * be set at some point within this file. + */ +extern int biosbasemem; +extern int biosextmem; +extern int boothowto; +extern struct bootinfo bootinfo; +extern int end; +extern int * esym; + +/* --------------------------------------------------------------------- */ + +/* + * Copy of the Multiboot information structure passed to us by the boot + * loader. The Multiboot_Info structure has some pointers adjusted to the + * other variables -- see multiboot_pre_reloc() -- so you oughtn't access + * them directly. In other words, always access them through the + * Multiboot_Info variable. + */ +static char Multiboot_Cmdline[255]; +static uint8_t Multiboot_Drives[255]; +static struct multiboot_info Multiboot_Info; +static boolean_t Multiboot_Loader = FALSE; +static char Multiboot_Loader_Name[255]; +static uint8_t Multiboot_Mmap[1024]; + +/* --------------------------------------------------------------------- */ + +/* + * Simplified ELF image that contains the symbol table for the booted + * kernel. Stuck after the kernel image (in memory). + * + * Must be less than MULTIBOOT_SYMTAB_SPACE in bytes. Otherwise, there + * is no guarantee that it will not overwrite other stuff passed in by + * the boot loader. + */ +struct symbols_image { + Elf32_Ehdr i_ehdr; + Elf32_Shdr i_shdr[4]; + char i_strtab[32]; + char i_data; /* Actually longer. */ +}; + +/* --------------------------------------------------------------------- */ + +/* + * Prototypes for private functions. + */ +static void bootinfo_add(struct btinfo_common *, int, int); +static void copy_syms(struct multiboot_info *); +static void setup_biosgeom(struct multiboot_info *); +static void setup_bootdisk(struct multiboot_info *); +static void setup_bootpath(struct multiboot_info *); +static void setup_console(struct multiboot_info *); +static void setup_howto(struct multiboot_info *); +static void setup_memory(struct multiboot_info *); +static void setup_memmap(struct multiboot_info *); +static void setup_syms(struct multiboot_info *); + +/* --------------------------------------------------------------------- */ + +/* + * Sets up the kernel if it was booted by a Multiboot-compliant boot + * loader. This is executed before the kernel has relocated itself. + * The main purpose of this function is to copy all the information + * passed in by the boot loader to a safe place, so that it is available + * after it has been relocated. + * + * WARNING: Because the kernel has not yet relocated itself to KERNBASE, + * special care has to be taken when accessing memory because absolute + * addresses (referring to kernel symbols) do not work. So: + * + * 1) Avoid jumps to absolute addresses (such as gotos and switches). + * 2) To access global variables use their physical address, which + * can be obtained using the RELOC macro. + */ +void +multiboot_pre_reloc(struct multiboot_info *mi) +{ +#define RELOC(type, x) ((type)((vaddr_t)(x) - KERNBASE)) + struct multiboot_info *midest = + RELOC(struct multiboot_info *, &Multiboot_Info); + + *RELOC(boolean_t *, &Multiboot_Loader) = TRUE; + memcpy(midest, mi, sizeof(Multiboot_Info)); + + if (mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE) { + strncpy(RELOC(void *, Multiboot_Cmdline), mi->mi_cmdline, + sizeof(Multiboot_Cmdline)); + midest->mi_cmdline = (char *)&Multiboot_Cmdline; + } + + if (mi->mi_flags & MULTIBOOT_INFO_HAS_LOADER_NAME) { + strncpy(RELOC(void *, Multiboot_Loader_Name), + mi->mi_loader_name, sizeof(Multiboot_Loader_Name)); + midest->mi_loader_name = (char *)&Multiboot_Loader_Name; + } + + if (mi->mi_flags & MULTIBOOT_INFO_HAS_MMAP) { + memcpy(RELOC(void *, Multiboot_Mmap), + (void *)mi->mi_mmap_addr, mi->mi_mmap_length); + midest->mi_mmap_addr = (vaddr_t)&Multiboot_Mmap; + } + + if (mi->mi_flags & MULTIBOOT_INFO_HAS_DRIVES) { + memcpy(RELOC(void *, Multiboot_Drives), + (void *)mi->mi_drives_addr, mi->mi_drives_length); + midest->mi_drives_addr = (vaddr_t)&Multiboot_Drives; + } + + copy_syms(mi); +#undef RELOC +} + +/* --------------------------------------------------------------------- */ + +/* + * Sets up the kernel if it was booted by a Multiboot-compliant boot + * loader. This is executed just after the kernel has relocated itself. + * At this point, executing any kind of code is safe, keeping in mind + * that no devices have been initialized yet (not even the console!). + */ +void +multiboot_post_reloc(void) +{ + struct multiboot_info *mi; + + if (! Multiboot_Loader) + return; + + mi = &Multiboot_Info; + bootinfo.bi_nentries = 0; + + setup_memory(mi); + setup_console(mi); + setup_howto(mi); + setup_bootpath(mi); + setup_biosgeom(mi); + setup_bootdisk(mi); + setup_memmap(mi); + setup_syms(mi); +} + +/* --------------------------------------------------------------------- */ + +/* + * Prints a summary of the information collected in the Multiboot + * information header (if present). Done as a separate function because + * the console has to be available. + */ +void +multiboot_print_info(void) +{ + struct multiboot_info *mi = &Multiboot_Info; + + if (! Multiboot_Loader) + return; + + printf("multiboot: Information structure flags: 0x%08x\n", + mi->mi_flags); + + if (mi->mi_flags & MULTIBOOT_INFO_HAS_LOADER_NAME) + printf("multiboot: Boot loader: %s\n", mi->mi_loader_name); + + if (mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE) + printf("multiboot: Command line: %s\n", mi->mi_cmdline); + + if (mi->mi_flags & MULTIBOOT_INFO_HAS_MEMORY) + printf("multiboot: %u KB lower memory, %u KB upper memory\n", + mi->mi_mem_lower, mi->mi_mem_upper); + + if (mi->mi_flags & MULTIBOOT_INFO_HAS_ELF_SYMS && esym == 0) + printf("multiboot: Symbol table too big; try increasing " + "MULTIBOOT_SYMTAB_SPACE\n"); +} + +/* --------------------------------------------------------------------- */ + +/* + * Adds the bootinfo entry given in 'item' to the bootinfo tables. + * Sets the item type to 'type' and its length to 'len'. + */ +static void +bootinfo_add(struct btinfo_common *item, int type, int len) +{ + int i; + struct bootinfo *bip = (struct bootinfo *)&bootinfo; + vaddr_t data; + + item->type = type; + item->len = len; + + data = (vaddr_t)&bip->bi_data; + for (i = 0; i < bip->bi_nentries; i++) { + struct btinfo_common *tmp; + + tmp = (struct btinfo_common *)data; + data += tmp->len; + } + if (data + len < (vaddr_t)&bip->bi_data + sizeof(bip->bi_data)) { + memcpy((void *)data, item, len); + bip->bi_nentries++; + } +} + +/* --------------------------------------------------------------------- */ + +/* + * Copies the symbol table and the strings table passed in by the boot + * loader after the kernel's image, and sets up 'esym' accordingly so + * that this data is properly copied into upper memory during relocation. + * + * WARNING: This code runs before the kernel has relocated itself. See + * the note in multiboot_pre_reloc() for more information. + */ +static void +copy_syms(struct multiboot_info *mi) +{ +#define RELOC(type, x) ((type)((vaddr_t)(x) - KERNBASE)) + int i; + Elf32_Shdr *symtabp, *strtabp; + struct symbols_image *si; + + /* + * Check if the Multiboot information header has symbols or not. + */ + if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_ELF_SYMS)) + return; + + /* + * Locate a symbol table and its matching string table in the + * section headers passed in by the boot loader. Set 'symtabp' + * and 'strtabp' with pointers to the matching entries. + */ + symtabp = strtabp = NULL; + for (i = 0; i < mi->mi_elfshdr_num && symtabp == NULL && + strtabp == NULL; i++) { + Elf32_Shdr *shdrp; + + shdrp = &((Elf32_Shdr *)mi->mi_elfshdr_addr)[i]; + + if ((shdrp->sh_type & SHT_SYMTAB) && + shdrp->sh_link != SHN_UNDEF) { + Elf32_Shdr *shdrp2; + + shdrp2 = &((Elf32_Shdr *)mi->mi_elfshdr_addr) + [shdrp->sh_link]; + + if (shdrp2->sh_type & SHT_STRTAB) { + symtabp = shdrp; + strtabp = shdrp2; + } + } + } + if (symtabp == NULL || strtabp == NULL) + return; + + /* + * Check if the symbol table will fit after the kernel image. + * If not, ignore it; there is nothing else we can do (except + * maybe copying only part of the table... but that could be + * as useless as not copying it). + */ + if (sizeof(si) + symtabp->sh_size + strtabp->sh_size > + MULTIBOOT_SYMTAB_SPACE) + return; + + /* + * Prepare space after the kernel to create a simple ELF image + * that holds the symbol table and the string table previously + * found. + * + * This goes just after the BSS section to let the bootstraping + * code relocate it (up to esym's value). + */ + memset(RELOC(char *, &end), 0, MULTIBOOT_SYMTAB_SPACE); + si = RELOC(struct symbols_image *, &end); + + /* + * Create a minimal ELF header (as required by ksyms_init). + */ + memcpy(si->i_ehdr.e_ident, ELFMAG, SELFMAG); + si->i_ehdr.e_ident[EI_CLASS] = ELFCLASS32; + si->i_ehdr.e_type = ET_EXEC; + si->i_ehdr.e_version = 1; + si->i_ehdr.e_shoff = offsetof(struct symbols_image, i_shdr); + si->i_ehdr.e_ehsize = sizeof(si->i_ehdr); + si->i_ehdr.e_shentsize = sizeof(si->i_shdr[0]); + si->i_ehdr.e_shnum = 2; + si->i_ehdr.e_shstrndx = SHN_UNDEF; + + /* + * First section: default empty entry; cleared by the previous + * memset. Explicitly set fields that use symbolic values. + */ + si->i_shdr[0].sh_type = SHT_NULL; + si->i_shdr[0].sh_link = SHN_UNDEF; + + /* + * Second section: the symbol table. + */ + memcpy(&si->i_shdr[1], symtabp, sizeof(si->i_shdr[1])); + si->i_shdr[1].sh_name = 1; + si->i_shdr[1].sh_addr = (vaddr_t)(&end) + + offsetof(struct symbols_image, i_shdr[1]); + si->i_shdr[1].sh_offset = offsetof(struct symbols_image, i_data); + si->i_shdr[1].sh_link = 2; + + memcpy(RELOC(uint8_t *, (vaddr_t)(&end)) + si->i_shdr[1].sh_offset, + (void *)symtabp->sh_addr, symtabp->sh_size); + + /* + * Third section: the strings table. + */ + memcpy(&si->i_shdr[2], strtabp, sizeof(si->i_shdr[2])); + si->i_shdr[1].sh_name = 9; + si->i_shdr[2].sh_addr = (vaddr_t)(&end) + + offsetof(struct symbols_image, i_shdr[2]); + si->i_shdr[2].sh_offset = offsetof(struct symbols_image, i_data) + + si->i_shdr[1].sh_size; + si->i_shdr[2].sh_link = SHN_UNDEF; + + memcpy(RELOC(uint8_t *, (vaddr_t)(&end)) + si->i_shdr[2].sh_offset, + (void *)strtabp->sh_addr, strtabp->sh_size); + + /* + * Fourth section: the section header strings table used by this + * minimal ELF image. + */ + si->i_shdr[3].sh_name = 17; + si->i_shdr[3].sh_type = SHT_STRTAB; + si->i_shdr[3].sh_offset = offsetof(struct symbols_image, i_strtab); + si->i_shdr[3].sh_size = sizeof(si->i_strtab); + si->i_shdr[3].sh_addralign = 1; + si->i_shdr[3].sh_link = SHN_UNDEF; + + strcpy(&si->i_strtab[1], ".symtab"); + strcpy(&si->i_strtab[9], ".strtab"); + strcpy(&si->i_strtab[17], ".shstrtab"); + + /* + * Set up the 'esym' global variable to point to the end of the + * minimal ELF image (end of symbols). + */ + *RELOC(int *, &esym) = ((vaddr_t)&end) + si->i_shdr[2].sh_offset + + si->i_shdr[2].sh_size; +#undef RELOC +} + +/* --------------------------------------------------------------------- */ + +/* + * Sets up the biosgeom bootinfo structure if the Multiboot information + * structure provides information about disk drives. + */ +static void +setup_biosgeom(struct multiboot_info *mi) +{ + size_t pos; + uint8_t bidata[1024]; + struct btinfo_biosgeom *bi; + + if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_DRIVES)) + return; + + memset(bidata, 0, sizeof(bidata)); + bi = (struct btinfo_biosgeom *)bidata; + pos = 0; + + while (pos < mi->mi_drives_length) { + struct multiboot_drive *md; + struct bi_biosgeom_entry bbe; + + md = (struct multiboot_drive *) + &((uint8_t *)mi->mi_drives_addr)[pos]; + + memset(&bbe, 0, sizeof(bbe)); + bbe.sec = md->md_sectors; + bbe.head = md->md_heads; + bbe.cyl = md->md_cylinders; + bbe.dev = md->md_number; + + memcpy(&bi->disk[bi->num], &bbe, sizeof(bbe)); + bi->num++; + + pos += md->md_length; + } + + bootinfo_add((struct btinfo_common *)bi, BTINFO_BIOSGEOM, + sizeof(struct btinfo_biosgeom) + + bi->num * sizeof(struct bi_biosgeom_entry)); +} + +/* --------------------------------------------------------------------- */ + +/* + * Sets up the default root device if the Multiboot information + * structure provides information about the boot drive (where the kernel + * image was loaded from) or if the user gave a 'root' parameter on the + * boot command line. + */ +static void +setup_bootdisk(struct multiboot_info *mi) +{ + boolean_t found; + struct btinfo_rootdevice bi; + + found = FALSE; + + if (mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE) + found = optstr_get(mi->mi_cmdline, "root", bi.devname, + sizeof(bi.devname)); + + if (!found && (mi->mi_flags & MULTIBOOT_INFO_HAS_BOOT_DEVICE)) { + const char *devprefix; + + /* XXX: This should use x86_alldisks to find the correct + * match. But, at this point, neither the drivers nor the + * vector are initialized... */ + switch (mi->mi_boot_device_drive) { + case 0x00: devprefix = "fd0"; break; + case 0x01: devprefix = "fd1"; break; + case 0x80: devprefix = "wd0"; break; + case 0x81: devprefix = "wd1"; break; + case 0x82: devprefix = "wd2"; break; + case 0x83: devprefix = "wd3"; break; + default: devprefix = ""; + } + + if (devprefix[0] != '\0') { + strcpy(bi.devname, devprefix); + if (mi->mi_boot_device_part2 != 0xFF) + bi.devname[3] = mi->mi_boot_device_part2 + 'a'; + else + bi.devname[3] = 'a'; + bi.devname[4] = '\0'; + + found = TRUE; + } + } + + if (found) { + bootinfo_add((struct btinfo_common *)&bi, BTINFO_ROOTDEVICE, + sizeof(struct btinfo_rootdevice)); + } +} + +/* --------------------------------------------------------------------- */ + +/* + * Sets up the bootpath bootinfo structure with an appropriate kernel + * name derived from the boot command line. The Multiboot information + * structure does not provide this detail directly, so we try to derive + * it from the command line setting. + */ +static void +setup_bootpath(struct multiboot_info *mi) +{ + struct btinfo_bootpath bi; + char *cl, *cl2, old; + int len; + + if (strncmp(Multiboot_Loader_Name, "GNU GRUB ", + sizeof(Multiboot_Loader_Name)) > 0) { + cl = mi->mi_cmdline; + while (*cl != '\0' && *cl != '/') + cl++; + cl2 = cl; + len = 0; + while (*cl2 != '\0' && *cl2 != ' ') { + len++; + cl2++; + } + + old = *cl2; + *cl2 = '\0'; + memcpy(bi.bootpath, cl, MIN(sizeof(bi.bootpath), len)); + *cl2 = old; + bi.bootpath[MIN(sizeof(bi.bootpath), len)] = '\0'; + + bootinfo_add((struct btinfo_common *)&bi, BTINFO_BOOTPATH, + sizeof(struct btinfo_bootpath)); + } +} + +/* --------------------------------------------------------------------- */ + +/* + * Sets up the console bootinfo structure if the user gave a 'console' + * argument on the boot command line. The Multiboot information + * structure gives no hint about this, so the only way to know where the + * console is is to let the user specify it. + * + * If there wasn't any 'console' argument, this does not generate any + * bootinfo entry, falling back to the kernel's default console. + * + * If there weren't any of 'console_speed' or 'console_addr' arguments, + * this falls back to the default values for the serial port. + */ +static void +setup_console(struct multiboot_info *mi) +{ + struct btinfo_console bi; + boolean_t found; + + found = FALSE; + + if (mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE) + found = optstr_get(mi->mi_cmdline, "console", bi.devname, + sizeof(bi.devname)); + + if (found) { + if (strncmp(bi.devname, "com", sizeof(bi.devname)) == 0) { + char tmp[10]; + + found = optstr_get(mi->mi_cmdline, "console_speed", + tmp, sizeof(tmp)); + if (found) + bi.speed = strtoul(tmp, NULL, 10); + else + bi.speed = 0; /* Use default speed. */ + + found = optstr_get(mi->mi_cmdline, "console_addr", + tmp, sizeof(tmp)); + if (found) { + if (tmp[0] == '0' && tmp[1] == 'x') + bi.addr = strtoul(tmp + 2, NULL, 16); + else + bi.addr = strtoul(tmp, NULL, 10); + } else + bi.addr = 0; /* Use default address. */ + } + + bootinfo_add((struct btinfo_common *)&bi, BTINFO_CONSOLE, + sizeof(struct btinfo_console)); + } +} + +/* --------------------------------------------------------------------- */ + +/* + * Sets up the 'boothowto' variable based on the options given in the + * boot command line, if any. + */ +static void +setup_howto(struct multiboot_info *mi) +{ + char *cl; + + if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE)) + return; + + cl = mi->mi_cmdline; + + /* Skip kernel file name. */ + while (*cl != '\0' && *cl != ' ') + cl++; + while (*cl != '\0' && *cl == ' ') + cl++; + + /* Check if there are flags and set 'howto' accordingly. */ + if (*cl == '-') { + int howto = 0; + + cl++; + while (*cl != '\0' && *cl != ' ') { + BOOT_FLAG(*cl, howto); + cl++; + } + if (*cl == ' ') + cl++; + + boothowto = howto; + } +} + +/* --------------------------------------------------------------------- */ + +/* + * Sets up the memmap bootinfo structure to describe available memory as + * given by the BIOS. + */ +static void +setup_memmap(struct multiboot_info *mi) +{ + char data[1024]; + size_t i; + struct btinfo_memmap *bi; + + if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_MMAP)) + return; + + bi = (struct btinfo_memmap *)data; + bi->num = 0; + + i = 0; + while (i < mi->mi_mmap_length) { + struct multiboot_mmap *mm; + struct bi_memmap_entry *bie; + + bie = &bi->entry[bi->num]; + + mm = (struct multiboot_mmap *)(mi->mi_mmap_addr + i); + bie->addr = mm->mm_base_addr; + bie->size = mm->mm_length; + if (mm->mm_type == 1) + bie->type = BIM_Memory; + else + bie->type = BIM_Reserved; + + bi->num++; + i += mm->mm_size + 4; + } + + bootinfo_add((struct btinfo_common *)bi, BTINFO_MEMMAP, + sizeof(data)); +} + +/* --------------------------------------------------------------------- */ + +/* + * Sets up the 'biosbasemem' and 'biosextmem' variables if the + * Multiboot information structure provides information about memory. + */ +static void +setup_memory(struct multiboot_info *mi) +{ + if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_MEMORY)) + return; + + biosbasemem = mi->mi_mem_lower; + biosextmem = mi->mi_mem_upper; +} + +/* --------------------------------------------------------------------- */ + +/* + * Sets up the symtab bootinfo structure to describe where the symbols + * are if copy_syms() found them. + */ +static void +setup_syms(struct multiboot_info *mi) +{ + struct btinfo_symtab bi; + struct symbols_image *si; + + if (esym == 0) + return; + + si = (struct symbols_image *)(&end); + + bi.ssym = (int)(&end) - KERNBASE; + bi.esym = (int)esym - KERNBASE; + bi.nsym = si->i_shdr[1].sh_size / sizeof(Elf32_Sym); + + bootinfo_add((struct btinfo_common *)&bi, BTINFO_SYMTAB, + sizeof(struct btinfo_symtab)); +} Index: sys/arch/i386/include/Makefile =================================================================== RCS file: /cvsroot/src/sys/arch/i386/include/Makefile,v retrieving revision 1.29 diff -u -p -r1.29 Makefile --- sys/arch/i386/include/Makefile 11 Dec 2005 12:17:43 -0000 1.29 +++ sys/arch/i386/include/Makefile 3 Feb 2006 10:10:49 -0000 @@ -15,7 +15,7 @@ INCS= ansi.h aout_machdep.h apmvar.h asm joystick.h \ kcore.h \ limits.h lock.h \ - math.h mcontext.h mtrr.h \ + math.h mcontext.h mtrr.h multiboot.h \ npx.h \ param.h pcb.h pccons.h pio.h pmap.h pmc.h proc.h profile.h psl.h \ pte.h ptrace.h \ Index: sys/arch/i386/include/multiboot.h =================================================================== RCS file: sys/arch/i386/include/multiboot.h diff -N sys/arch/i386/include/multiboot.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/arch/i386/include/multiboot.h 3 Feb 2006 10:10:49 -0000 @@ -0,0 +1,218 @@ +/* $NetBSD$ */ + +/*- + * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Julio M. Merino Vidal. + * + * 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. + */ + +#if defined(_KERNEL) + +#include "opt_multiboot.h" + +#if defined(MULTIBOOT) + +/* --------------------------------------------------------------------- */ + +/* + * Space reserved after the kernel image to stick the symbol table. + * The boot loader will leave this memory untouched (it will be treated + * as if it was part of the BSS section). + */ +#if !defined(MULTIBOOT_SYMTAB_SPACE) +# define MULTIBOOT_SYMTAB_SPACE 1048576 +#endif + +/* --------------------------------------------------------------------- */ + +/* + * Multiboot header structure. + */ +#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 +#define MULTIBOOT_HEADER_MODS_ALIGNED 0x00000001 +#define MULTIBOOT_HEADER_WANT_MEMORY 0x00000002 +#define MULTIBOOT_HEADER_HAS_VBE 0x00000004 +#define MULTIBOOT_HEADER_HAS_ADDR 0x00010000 + +#if !defined(_LOCORE) +struct multiboot_header { + uint32_t mh_magic; + uint32_t mh_flags; + uint32_t mh_checksum; + + /* Valid if mh_flags sets MULTIBOOT_HEADER_HAS_ADDR. */ + paddr_t mh_header_addr; + paddr_t mh_load_addr; + paddr_t mh_load_end_addr; + paddr_t mh_bss_end_addr; + paddr_t mh_entry_addr; + + /* Valid if mh_flags sets MULTIBOOT_HEADER_HAS_VBE. */ + uint32_t mh_mode_type; + uint32_t mh_width; + uint32_t mh_height; + uint32_t mh_depth; +}; +#endif /* !defined(_LOCORE) */ + +/* + * Symbols defined in locore.S. + */ +#if !defined(_LOCORE) +extern struct multiboot_header *Multiboot_Header; +#endif /* !defined(_LOCORE) */ + +/* --------------------------------------------------------------------- */ + +/* + * Multiboot information structure. + */ +#define MULTIBOOT_INFO_MAGIC 0x2BADB002 +#define MULTIBOOT_INFO_HAS_MEMORY 0x00000001 +#define MULTIBOOT_INFO_HAS_BOOT_DEVICE 0x00000002 +#define MULTIBOOT_INFO_HAS_CMDLINE 0x00000004 +#define MULTIBOOT_INFO_HAS_MODS 0x00000008 +#define MULTIBOOT_INFO_HAS_AOUT_SYMS 0x00000010 +#define MULTIBOOT_INFO_HAS_ELF_SYMS 0x00000020 +#define MULTIBOOT_INFO_HAS_MMAP 0x00000040 +#define MULTIBOOT_INFO_HAS_DRIVES 0x00000080 +#define MULTIBOOT_INFO_HAS_CONFIG_TABLE 0x00000100 +#define MULTIBOOT_INFO_HAS_LOADER_NAME 0x00000200 +#define MULTIBOOT_INFO_HAS_APM_TABLE 0x00000400 +#define MULTIBOOT_INFO_HAS_VBE 0x00000800 + +#if !defined(_LOCORE) +struct multiboot_info { + uint32_t mi_flags; + + /* Valid if mi_flags sets MULTIBOOT_INFO_HAS_MEMORY. */ + uint32_t mi_mem_lower; + uint32_t mi_mem_upper; + + /* Valid if mi_flags sets MULTIBOOT_INFO_HAS_BOOT_DEVICE. */ + uint8_t mi_boot_device_part3; + uint8_t mi_boot_device_part2; + uint8_t mi_boot_device_part1; + uint8_t mi_boot_device_drive; + + /* Valid if mi_flags sets MULTIBOOT_INFO_HAS_CMDLINE. */ + char * mi_cmdline; + + /* Valid if mi_flags sets MULTIBOOT_INFO_HAS_MODS. */ + uint32_t unused_mi_mods_count; + vaddr_t unused_mi_mods_addr; + + /* Valid if mi_flags sets MULTIBOOT_INFO_HAS_{AOUT,ELF}_SYMS. */ + uint32_t mi_elfshdr_num; + uint32_t mi_elfshdr_size; + vaddr_t mi_elfshdr_addr; + uint32_t mi_elfshdr_shndx; + + /* Valid if mi_flags sets MULTIBOOT_INFO_HAS_MMAP. */ + uint32_t mi_mmap_length; + vaddr_t mi_mmap_addr; + + /* Valid if mi_flags sets MULTIBOOT_INFO_HAS_DRIVES. */ + uint32_t mi_drives_length; + vaddr_t mi_drives_addr; + + /* Valid if mi_flags sets MULTIBOOT_INFO_HAS_CONFIG_TABLE. */ + void * unused_mi_config_table; + + /* Valid if mi_flags sets MULTIBOOT_INFO_HAS_LOADER_NAME. */ + char * mi_loader_name; + + /* Valid if mi_flags sets MULTIBOOT_INFO_HAS_APM. */ + void * unused_mi_apm_table; + + /* Valid if mi_flags sets MULTIBOOT_INFO_HAS_VBE. */ + void * unused_mi_vbe_control_info; + void * unused_mi_vbe_mode_info; + paddr_t unused_mi_vbe_interface_seg; + paddr_t unused_mi_vbe_interface_off; + uint32_t unused_mi_vbe_interface_len; +}; + +/* --------------------------------------------------------------------- */ + +/* + * Drive information. This describes an entry in the drives table as + * pointed to by mi_drives_addr. + */ +struct multiboot_drive { + uint32_t md_length; + uint8_t md_number; + uint8_t md_mode; + uint16_t md_cylinders; + uint8_t md_heads; + uint8_t md_sectors; + + /* The variable-sized 'ports' field comes here, so this structure + * can be longer. */ +}; + +/* --------------------------------------------------------------------- */ + +/* + * Memory mapping. This describes an entry in the memory mappings table + * as pointed to by mi_mmap_addr. + * + * Be aware that mm_size specifies the size of all other fields *except* + * for mm_size. In order to jump between two different entries, you + * have to count mm_size + 4 bytes. + */ +struct multiboot_mmap { + uint32_t mm_size; + uint64_t mm_base_addr; + uint64_t mm_length; + uint32_t mm_type; +}; + +#endif /* !defined(_LOCORE) */ + +/* --------------------------------------------------------------------- */ + +/* + * Prototypes for public functions defined in multiboot.c. + */ +#if !defined(_LOCORE) +void multiboot_pre_reloc(struct multiboot_info *); +void multiboot_post_reloc(void); +void multiboot_print_info(void); +#endif /* !defined(_LOCORE) */ + +/* --------------------------------------------------------------------- */ + +#endif /* defined(MULTIBOOT) */ + +#endif /* defined(_KERNEL) */ Index: sys/arch/x86/include/bootinfo.h =================================================================== RCS file: /cvsroot/src/sys/arch/x86/include/bootinfo.h,v retrieving revision 1.10 diff -u -p -r1.10 bootinfo.h --- sys/arch/x86/include/bootinfo.h 30 Dec 2005 13:37:57 -0000 1.10 +++ sys/arch/x86/include/bootinfo.h 3 Feb 2006 10:10:49 -0000 @@ -34,6 +34,7 @@ struct btinfo_common { }; #define BTINFO_BOOTPATH 0 +#define BTINFO_ROOTDEVICE 1 #define BTINFO_BOOTDISK 3 #define BTINFO_NETIF 4 #define BTINFO_CONSOLE 6 @@ -47,6 +48,11 @@ struct btinfo_bootpath { char bootpath[80]; }; +struct btinfo_rootdevice { + struct btinfo_common common; + char devname[16]; +}; + struct btinfo_bootdisk { struct btinfo_common common; int labelsector; /* label valid if != -1 */ Index: sys/arch/x86/x86/consinit.c =================================================================== RCS file: /cvsroot/src/sys/arch/x86/x86/consinit.c,v retrieving revision 1.8 diff -u -p -r1.8 consinit.c --- sys/arch/x86/x86/consinit.c 11 Dec 2005 12:19:47 -0000 1.8 +++ sys/arch/x86/x86/consinit.c 3 Feb 2006 10:10:49 -0000 @@ -195,8 +195,15 @@ dokbd: #if (NCOM > 0) if (!strcmp(consinfo->devname, "com")) { bus_space_tag_t tag = X86_BUS_SPACE_IO; + int addr = consinfo->addr; + int speed = consinfo->speed; - if (comcnattach(tag, consinfo->addr, consinfo->speed, + if (addr == 0) + addr = CONADDR; + if (speed == 0) + speed = CONSPEED; + + if (comcnattach(tag, addr, speed, COM_FREQ, COM_TYPE_NORMAL, comcnmode)) panic("can't init serial console @%x", consinfo->addr); Index: sys/arch/x86/x86/x86_autoconf.c =================================================================== RCS file: /cvsroot/src/sys/arch/x86/x86/x86_autoconf.c,v retrieving revision 1.5 diff -u -p -r1.5 x86_autoconf.c --- sys/arch/x86/x86/x86_autoconf.c 11 Dec 2005 12:19:47 -0000 1.5 +++ sys/arch/x86/x86/x86_autoconf.c 3 Feb 2006 10:10:49 -0000 @@ -364,6 +364,7 @@ uint32_t bootdev = 0; static void findroot(void) { + struct btinfo_rootdevice *biv; struct btinfo_bootdisk *bid; struct btinfo_bootwedge *biw; struct device *dv; @@ -387,6 +388,27 @@ findroot(void) return; } + if ((biv = lookup_bootinfo(BTINFO_ROOTDEVICE)) != NULL) { + for (dv = TAILQ_FIRST(&alldevs); dv != NULL; + dv = TAILQ_NEXT(dv, dv_list)) { + struct cfdata *cd; + size_t len; + + if (dv->dv_class != DV_DISK) + continue; + + cd = dv->dv_cfdata; + len = strlen(cd->cf_name); + + if (strncmp(cd->cf_name, biv->devname, len) == 0 && + biv->devname[len] - '0' == cd->cf_unit) { + booted_device = dv; + booted_partition = biv->devname[len + 1] - 'a'; + return; + } + } + } + if ((biw = lookup_bootinfo(BTINFO_BOOTWEDGE)) != NULL) { /* * Scan all disk devices for ones that match the passed data. Index: sys/conf/files =================================================================== RCS file: /cvsroot/src/sys/conf/files,v retrieving revision 1.756 diff -u -p -r1.756 files --- sys/conf/files 2 Feb 2006 15:26:35 -0000 1.756 +++ sys/conf/files 3 Feb 2006 10:10:49 -0000 @@ -1250,6 +1250,7 @@ file kern/subr_prf.c file kern/subr_prof.c file kern/subr_prop.c file kern/subr_once.c +file kern/subr_optstr.c file kern/subr_userconf.c userconf file kern/subr_workqueue.c file kern/subr_xxx.c Index: sys/kern/subr_optstr.c =================================================================== RCS file: sys/kern/subr_optstr.c diff -N sys/kern/subr_optstr.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/kern/subr_optstr.c 3 Feb 2006 10:10:50 -0000 @@ -0,0 +1,101 @@ +/* $NetBSD$ */ + +/*- + * Copyright (c) 2006 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Julio M. Merino Vidal. + * + * 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 +__KERNEL_RCSID(0, "$NetBSD$"); + +#include +#include + +/* --------------------------------------------------------------------- */ + +/* + * Given an options string of the form 'a=b c=d ... y=z' and a key, + * looks for the given key's value in the string and returns it in buf + * with a maximum of bufsize bytes. If the key is found, returns TRUE; + * otherwise FALSE. + */ +boolean_t +optstr_get(const char *optstr, const char *key, char *buf, size_t bufsize) +{ + boolean_t found; + const char *keyp; + + found = FALSE; + + /* Skip any initial spaces until we find a word. */ + while (*optstr == ' ' && *optstr != '\0') + optstr++; + + /* Search for the given key within the option string. */ + while (!found && *optstr != '\0') { + /* Check if the next word matches the key. */ + keyp = key; + while (*optstr == *keyp) { + optstr++; + keyp++; + } + + if (*optstr == '=') + found = TRUE; + else { + /* Key not found; skip until next space. */ + while (*optstr != ' ' && *optstr != '\0') + optstr++; + + /* And now skip until next word. */ + while (*optstr == ' ' && *optstr != '\0') + optstr++; + } + } + + /* If the key was found; copy its value to the target buffer. */ + if (found) { + const char *lastbuf; + + lastbuf = buf + (bufsize - 1); + + found = TRUE; + optstr++; /* Skip '='. */ + while (buf != lastbuf && *optstr != ' ' && *optstr != '\0') + *buf++ = *optstr++; + *buf = '\0'; + } + + return found; +} Index: sys/sys/Makefile =================================================================== RCS file: /cvsroot/src/sys/sys/Makefile,v retrieving revision 1.80 diff -u -p -r1.80 Makefile --- sys/sys/Makefile 20 Dec 2005 16:28:55 -0000 1.80 +++ sys/sys/Makefile 3 Feb 2006 10:10:50 -0000 @@ -19,6 +19,7 @@ INCS= acct.h agpio.h ansi.h ataio.h audi malloc.h mallocvar.h mbuf.h md4.h \ md5.h midiio.h mman.h mount.h msg.h msgbuf.h mtio.h \ namei.h null.h \ + optstr.h \ param.h pipe.h pmc.h poll.h pool.h power.h proc.h properties.h \ protosw.h ptrace.h queue.h \ ras.h reboot.h radioio.h resource.h resourcevar.h rnd.h \ Index: sys/sys/optstr.h =================================================================== RCS file: sys/sys/optstr.h diff -N sys/sys/optstr.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/sys/optstr.h 3 Feb 2006 10:10:50 -0000 @@ -0,0 +1,47 @@ +/* $NetBSD$ */ + +/*- + * Copyright (c) 2006 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Julio M. Merino Vidal. + * + * 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. + */ + +#if !defined(_SYS_OPTSTR_H_) +#define _SYS_OPTSTR_H_ + +/* + * Prototypes for functions defined in sys/kern/subr_optstr.c. + */ +boolean_t optstr_get(const char *, const char *, char *, size_t); + +#endif /* !defined(_SYS_OPTSTR_H_) */