[BACK]Return to multiboot.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / i386 / i386

Annotation of src/sys/arch/i386/i386/multiboot.c, Revision 1.9

1.9     ! jmmv        1: /*     $NetBSD: multiboot.c,v 1.8 2006/10/25 13:56:16 jmmv Exp $       */
1.1       jmmv        2:
                      3: /*-
                      4:  * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Julio M. Merino Vidal.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  * 3. All advertising materials mentioning features or use of this software
                     19:  *    must display the following acknowledgement:
                     20:  *     This product includes software developed by the NetBSD
                     21:  *     Foundation, Inc. and its contributors.
                     22:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     23:  *    contributors may be used to endorse or promote products derived
                     24:  *    from this software without specific prior written permission.
                     25:  *
                     26:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     27:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     28:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     29:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     30:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     31:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     32:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     33:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     34:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     35:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     36:  * POSSIBILITY OF SUCH DAMAGE.
                     37:  */
                     38:
                     39: #include <sys/cdefs.h>
1.9     ! jmmv       40: __KERNEL_RCSID(0, "$NetBSD: multiboot.c,v 1.8 2006/10/25 13:56:16 jmmv Exp $");
1.1       jmmv       41:
                     42: #include <sys/param.h>
                     43: #include <sys/systm.h>
                     44: #include <sys/cdefs_elf.h>
                     45: #include <sys/boot_flag.h>
                     46: #include <sys/exec.h>
                     47: #include <sys/exec_elf.h>
                     48: #include <sys/optstr.h>
1.8       jmmv       49: #include <sys/ksyms.h>
1.1       jmmv       50:
                     51: #include <machine/bootinfo.h>
                     52: #include <machine/multiboot.h>
                     53:
                     54: #if !defined(MULTIBOOT)
                     55: #  error "MULTIBOOT not defined; this cannot happen."
                     56: #endif
                     57:
                     58: /* --------------------------------------------------------------------- */
                     59:
                     60: /*
1.8       jmmv       61:  * Symbol and string table for the loaded kernel.
                     62:  */
                     63:
                     64: struct multiboot_symbols {
                     65:        caddr_t         s_symstart;
                     66:        size_t          s_symsize;
                     67:        caddr_t         s_strstart;
                     68:        size_t          s_strsize;
                     69: };
                     70:
                     71: /* --------------------------------------------------------------------- */
                     72:
                     73: /*
1.1       jmmv       74:  * External variables.  All of them, with the exception of 'end', must
                     75:  * be set at some point within this file.
1.6       mrg        76:  *
                     77:  * XXX these should be found in a header file!
1.1       jmmv       78:  */
                     79: extern int             biosbasemem;
                     80: extern int             biosextmem;
1.6       mrg        81: extern int             biosmem_implicit;
1.1       jmmv       82: extern int             boothowto;
                     83: extern struct bootinfo bootinfo;
                     84: extern int             end;
                     85: extern int *           esym;
                     86:
                     87: /* --------------------------------------------------------------------- */
                     88:
                     89: /*
                     90:  * Copy of the Multiboot information structure passed to us by the boot
                     91:  * loader.  The Multiboot_Info structure has some pointers adjusted to the
                     92:  * other variables -- see multiboot_pre_reloc() -- so you oughtn't access
                     93:  * them directly.  In other words, always access them through the
                     94:  * Multiboot_Info variable.
                     95:  */
                     96: static char                    Multiboot_Cmdline[255];
                     97: static uint8_t                 Multiboot_Drives[255];
                     98: static struct multiboot_info   Multiboot_Info;
                     99: static boolean_t               Multiboot_Loader = FALSE;
                    100: static char                    Multiboot_Loader_Name[255];
                    101: static uint8_t                 Multiboot_Mmap[1024];
1.8       jmmv      102: static struct multiboot_symbols        Multiboot_Symbols;
1.1       jmmv      103:
                    104: /* --------------------------------------------------------------------- */
                    105:
                    106: /*
                    107:  * Prototypes for private functions.
                    108:  */
                    109: static void    bootinfo_add(struct btinfo_common *, int, int);
                    110: static void    copy_syms(struct multiboot_info *);
                    111: static void    setup_biosgeom(struct multiboot_info *);
                    112: static void    setup_bootdisk(struct multiboot_info *);
                    113: static void    setup_bootpath(struct multiboot_info *);
                    114: static void    setup_console(struct multiboot_info *);
                    115: static void    setup_howto(struct multiboot_info *);
                    116: static void    setup_memory(struct multiboot_info *);
                    117: static void    setup_memmap(struct multiboot_info *);
                    118:
                    119: /* --------------------------------------------------------------------- */
                    120:
                    121: /*
                    122:  * Sets up the kernel if it was booted by a Multiboot-compliant boot
                    123:  * loader.  This is executed before the kernel has relocated itself.
                    124:  * The main purpose of this function is to copy all the information
                    125:  * passed in by the boot loader to a safe place, so that it is available
                    126:  * after it has been relocated.
                    127:  *
                    128:  * WARNING: Because the kernel has not yet relocated itself to KERNBASE,
                    129:  * special care has to be taken when accessing memory because absolute
                    130:  * addresses (referring to kernel symbols) do not work.  So:
                    131:  *
                    132:  *     1) Avoid jumps to absolute addresses (such as gotos and switches).
                    133:  *     2) To access global variables use their physical address, which
                    134:  *        can be obtained using the RELOC macro.
                    135:  */
                    136: void
                    137: multiboot_pre_reloc(struct multiboot_info *mi)
                    138: {
                    139: #define RELOC(type, x) ((type)((vaddr_t)(x) - KERNBASE))
                    140:        struct multiboot_info *midest =
                    141:            RELOC(struct multiboot_info *, &Multiboot_Info);
                    142:
                    143:        *RELOC(boolean_t *, &Multiboot_Loader) = TRUE;
                    144:        memcpy(midest, mi, sizeof(Multiboot_Info));
                    145:
                    146:        if (mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE) {
                    147:                strncpy(RELOC(void *, Multiboot_Cmdline), mi->mi_cmdline,
                    148:                    sizeof(Multiboot_Cmdline));
                    149:                midest->mi_cmdline = (char *)&Multiboot_Cmdline;
                    150:        }
                    151:
                    152:        if (mi->mi_flags & MULTIBOOT_INFO_HAS_LOADER_NAME) {
                    153:                strncpy(RELOC(void *, Multiboot_Loader_Name),
                    154:                    mi->mi_loader_name, sizeof(Multiboot_Loader_Name));
                    155:                midest->mi_loader_name = (char *)&Multiboot_Loader_Name;
                    156:        }
                    157:
                    158:        if (mi->mi_flags & MULTIBOOT_INFO_HAS_MMAP) {
                    159:                memcpy(RELOC(void *, Multiboot_Mmap),
                    160:                    (void *)mi->mi_mmap_addr, mi->mi_mmap_length);
                    161:                midest->mi_mmap_addr = (vaddr_t)&Multiboot_Mmap;
                    162:        }
                    163:
                    164:        if (mi->mi_flags & MULTIBOOT_INFO_HAS_DRIVES) {
                    165:                memcpy(RELOC(void *, Multiboot_Drives),
                    166:                    (void *)mi->mi_drives_addr, mi->mi_drives_length);
                    167:                midest->mi_drives_addr = (vaddr_t)&Multiboot_Drives;
                    168:        }
                    169:
                    170:        copy_syms(mi);
                    171: #undef RELOC
                    172: }
                    173:
                    174: /* --------------------------------------------------------------------- */
                    175:
                    176: /*
                    177:  * Sets up the kernel if it was booted by a Multiboot-compliant boot
                    178:  * loader.  This is executed just after the kernel has relocated itself.
                    179:  * At this point, executing any kind of code is safe, keeping in mind
                    180:  * that no devices have been initialized yet (not even the console!).
                    181:  */
                    182: void
                    183: multiboot_post_reloc(void)
                    184: {
                    185:        struct multiboot_info *mi;
                    186:
                    187:        if (! Multiboot_Loader)
                    188:                return;
                    189:
                    190:        mi = &Multiboot_Info;
                    191:        bootinfo.bi_nentries = 0;
                    192:
                    193:        setup_memory(mi);
                    194:        setup_console(mi);
                    195:        setup_howto(mi);
                    196:        setup_bootpath(mi);
                    197:        setup_biosgeom(mi);
1.3       jmmv      198:        setup_bootdisk(mi);
1.1       jmmv      199:        setup_memmap(mi);
                    200: }
                    201:
                    202: /* --------------------------------------------------------------------- */
                    203:
                    204: /*
                    205:  * Prints a summary of the information collected in the Multiboot
                    206:  * information header (if present).  Done as a separate function because
                    207:  * the console has to be available.
                    208:  */
                    209: void
                    210: multiboot_print_info(void)
                    211: {
                    212:        struct multiboot_info *mi = &Multiboot_Info;
1.8       jmmv      213:        struct multiboot_symbols *ms = &Multiboot_Symbols;
1.1       jmmv      214:
                    215:        if (! Multiboot_Loader)
                    216:                return;
                    217:
                    218:        printf("multiboot: Information structure flags: 0x%08x\n",
                    219:            mi->mi_flags);
                    220:
                    221:        if (mi->mi_flags & MULTIBOOT_INFO_HAS_LOADER_NAME)
                    222:                printf("multiboot: Boot loader: %s\n", mi->mi_loader_name);
                    223:
                    224:        if (mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE)
                    225:                printf("multiboot: Command line: %s\n", mi->mi_cmdline);
                    226:
                    227:        if (mi->mi_flags & MULTIBOOT_INFO_HAS_MEMORY)
                    228:                printf("multiboot: %u KB lower memory, %u KB upper memory\n",
                    229:                    mi->mi_mem_lower, mi->mi_mem_upper);
                    230:
1.8       jmmv      231:        if (mi->mi_flags & MULTIBOOT_INFO_HAS_ELF_SYMS) {
                    232:                KASSERT(esym != 0);
                    233:                printf("multiboot: Symbol table at %p, length %d bytes\n",
                    234:                    ms->s_symstart, ms->s_symsize);
                    235:                printf("multiboot: String table at %p, length %d bytes\n",
                    236:                    ms->s_strstart, ms->s_strsize);
                    237:        }
1.1       jmmv      238: }
                    239:
                    240: /* --------------------------------------------------------------------- */
                    241:
                    242: /*
                    243:  * Adds the bootinfo entry given in 'item' to the bootinfo tables.
                    244:  * Sets the item type to 'type' and its length to 'len'.
                    245:  */
                    246: static void
                    247: bootinfo_add(struct btinfo_common *item, int type, int len)
                    248: {
                    249:        int i;
                    250:        struct bootinfo *bip = (struct bootinfo *)&bootinfo;
                    251:        vaddr_t data;
                    252:
                    253:        item->type = type;
                    254:        item->len = len;
                    255:
                    256:        data = (vaddr_t)&bip->bi_data;
                    257:        for (i = 0; i < bip->bi_nentries; i++) {
                    258:                struct btinfo_common *tmp;
                    259:
                    260:                tmp = (struct btinfo_common *)data;
                    261:                data += tmp->len;
                    262:        }
                    263:        if (data + len < (vaddr_t)&bip->bi_data + sizeof(bip->bi_data)) {
                    264:                memcpy((void *)data, item, len);
                    265:                bip->bi_nentries++;
                    266:        }
                    267: }
                    268:
                    269: /* --------------------------------------------------------------------- */
                    270:
                    271: /*
                    272:  * Copies the symbol table and the strings table passed in by the boot
                    273:  * loader after the kernel's image, and sets up 'esym' accordingly so
                    274:  * that this data is properly copied into upper memory during relocation.
                    275:  *
                    276:  * WARNING: This code runs before the kernel has relocated itself.  See
                    277:  * the note in multiboot_pre_reloc() for more information.
                    278:  */
                    279: static void
                    280: copy_syms(struct multiboot_info *mi)
                    281: {
                    282: #define RELOC(type, x) ((type)((vaddr_t)(x) - KERNBASE))
                    283:        int i;
                    284:        Elf32_Shdr *symtabp, *strtabp;
1.8       jmmv      285:        struct multiboot_symbols *ms;
                    286:        size_t symsize, strsize;
                    287:        paddr_t symaddr, straddr;
                    288:        paddr_t symstart, strstart;
                    289:
1.1       jmmv      290:
                    291:        /*
                    292:         * Check if the Multiboot information header has symbols or not.
                    293:         */
                    294:        if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_ELF_SYMS))
                    295:                return;
                    296:
1.8       jmmv      297:        ms = RELOC(struct multiboot_symbols *, &Multiboot_Symbols);
                    298:
1.1       jmmv      299:        /*
                    300:         * Locate a symbol table and its matching string table in the
                    301:         * section headers passed in by the boot loader.  Set 'symtabp'
                    302:         * and 'strtabp' with pointers to the matching entries.
                    303:         */
                    304:        symtabp = strtabp = NULL;
                    305:        for (i = 0; i < mi->mi_elfshdr_num && symtabp == NULL &&
                    306:            strtabp == NULL; i++) {
                    307:                Elf32_Shdr *shdrp;
                    308:
                    309:                shdrp = &((Elf32_Shdr *)mi->mi_elfshdr_addr)[i];
                    310:
                    311:                if ((shdrp->sh_type & SHT_SYMTAB) &&
                    312:                    shdrp->sh_link != SHN_UNDEF) {
                    313:                        Elf32_Shdr *shdrp2;
                    314:
                    315:                        shdrp2 = &((Elf32_Shdr *)mi->mi_elfshdr_addr)
                    316:                            [shdrp->sh_link];
                    317:
                    318:                        if (shdrp2->sh_type & SHT_STRTAB) {
                    319:                                symtabp = shdrp;
                    320:                                strtabp = shdrp2;
                    321:                        }
                    322:                }
                    323:        }
                    324:        if (symtabp == NULL || strtabp == NULL)
                    325:                return;
                    326:
1.8       jmmv      327:        symaddr = symtabp->sh_addr;
                    328:        straddr = strtabp->sh_addr;
                    329:        symsize = symtabp->sh_size;
                    330:        strsize = strtabp->sh_size;
1.1       jmmv      331:
                    332:        /*
1.8       jmmv      333:         * Copy the symbol and string tables just after the kernel's
                    334:         * end address, in this order.  Only the contents of these ELF
                    335:         * sections are copied; headers are discarded.  esym is later
                    336:         * updated to point to the lowest "free" address after the tables
                    337:         * so that they are mapped appropriately when enabling paging.
1.1       jmmv      338:         *
1.8       jmmv      339:         * We need to be careful to not overwrite valid data doing the
                    340:         * copies, hence all the different cases below.  We can assume
                    341:         * that if the tables start before the kernel's end address,
                    342:         * they will not grow over this address.
1.1       jmmv      343:         */
1.8       jmmv      344:         if ((paddr_t)symtabp < (paddr_t)&end - KERNBASE &&
                    345:            (paddr_t)strtabp < (paddr_t)&end - KERNBASE) {
                    346:                symstart = (paddr_t)((vaddr_t)&end - KERNBASE);
                    347:                strstart = symstart + symsize;
                    348:                memcpy((void *)symstart, (void *)symaddr, symsize);
                    349:                memcpy((void *)strstart, (void *)straddr, strsize);
                    350:         } else if ((paddr_t)symtabp > (paddr_t)&end - KERNBASE &&
                    351:                   (paddr_t)strtabp < (paddr_t)&end - KERNBASE) {
                    352:                symstart = (paddr_t)((vaddr_t)&end - KERNBASE);
                    353:                strstart = symstart + symsize;
                    354:                memcpy((void *)symstart, (void *)symaddr, symsize);
                    355:                memcpy((void *)strstart, (void *)straddr, strsize);
                    356:         } else if ((paddr_t)symtabp < (paddr_t)&end - KERNBASE &&
                    357:                   (paddr_t)strtabp > (paddr_t)&end - KERNBASE) {
                    358:                strstart = (paddr_t)((vaddr_t)&end - KERNBASE);
                    359:                symstart = strstart + strsize;
                    360:                memcpy((void *)strstart, (void *)straddr, strsize);
                    361:                memcpy((void *)symstart, (void *)symaddr, symsize);
                    362:        } else {
                    363:                /* symtabp and strtabp are both over end */
                    364:                if ((paddr_t)symtabp < (paddr_t)strtabp) {
                    365:                        symstart = (paddr_t)((vaddr_t)&end - KERNBASE);
                    366:                        strstart = symstart + symsize;
                    367:                        memcpy((void *)symstart, (void *)symaddr, symsize);
                    368:                        memcpy((void *)strstart, (void *)straddr, strsize);
                    369:                } else {
                    370:                        strstart = (paddr_t)((vaddr_t)&end - KERNBASE);
                    371:                        symstart = strstart + strsize;
                    372:                        memcpy((void *)strstart, (void *)straddr, strsize);
                    373:                        memcpy((void *)symstart, (void *)symaddr, symsize);
                    374:                }
                    375:        }
                    376:        *RELOC(int *, &esym) = (int)(strstart + strsize + KERNBASE);
1.1       jmmv      377:
1.8       jmmv      378:        ms->s_symstart = (caddr_t)(symstart + KERNBASE);
                    379:        ms->s_symsize  = symsize;
                    380:        ms->s_strstart = (caddr_t)(strstart + KERNBASE);
                    381:        ms->s_strsize  = strsize;
1.1       jmmv      382: #undef RELOC
                    383: }
                    384:
                    385: /* --------------------------------------------------------------------- */
                    386:
                    387: /*
                    388:  * Sets up the biosgeom bootinfo structure if the Multiboot information
                    389:  * structure provides information about disk drives.
                    390:  */
                    391: static void
                    392: setup_biosgeom(struct multiboot_info *mi)
                    393: {
                    394:        size_t pos;
                    395:        uint8_t bidata[1024];
                    396:        struct btinfo_biosgeom *bi;
                    397:
                    398:        if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_DRIVES))
                    399:                return;
                    400:
                    401:        memset(bidata, 0, sizeof(bidata));
                    402:        bi = (struct btinfo_biosgeom *)bidata;
                    403:        pos = 0;
                    404:
                    405:        while (pos < mi->mi_drives_length) {
                    406:                struct multiboot_drive *md;
                    407:                struct bi_biosgeom_entry bbe;
                    408:
                    409:                md = (struct multiboot_drive *)
                    410:                    &((uint8_t *)mi->mi_drives_addr)[pos];
                    411:
                    412:                memset(&bbe, 0, sizeof(bbe));
                    413:                bbe.sec = md->md_sectors;
                    414:                bbe.head = md->md_heads;
                    415:                bbe.cyl = md->md_cylinders;
                    416:                bbe.dev = md->md_number;
                    417:
                    418:                memcpy(&bi->disk[bi->num], &bbe, sizeof(bbe));
                    419:                bi->num++;
                    420:
                    421:                pos += md->md_length;
                    422:        }
                    423:
                    424:        bootinfo_add((struct btinfo_common *)bi, BTINFO_BIOSGEOM,
                    425:            sizeof(struct btinfo_biosgeom) +
                    426:            bi->num * sizeof(struct bi_biosgeom_entry));
                    427: }
                    428:
                    429: /* --------------------------------------------------------------------- */
                    430:
                    431: /*
                    432:  * Sets up the default root device if the Multiboot information
                    433:  * structure provides information about the boot drive (where the kernel
                    434:  * image was loaded from) or if the user gave a 'root' parameter on the
                    435:  * boot command line.
                    436:  */
                    437: static void
                    438: setup_bootdisk(struct multiboot_info *mi)
                    439: {
                    440:        boolean_t found;
                    441:        struct btinfo_rootdevice bi;
                    442:
                    443:        found = FALSE;
                    444:
                    445:        if (mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE)
                    446:                found = optstr_get(mi->mi_cmdline, "root", bi.devname,
                    447:                    sizeof(bi.devname));
                    448:
                    449:        if (!found && (mi->mi_flags & MULTIBOOT_INFO_HAS_BOOT_DEVICE)) {
                    450:                const char *devprefix;
                    451:
1.4       jmmv      452:                /* Attempt to match the BIOS boot disk to a device.  There
                    453:                 * is not much we can do to get it right.  (Well, strictly
                    454:                 * speaking, we could, but it is certainly not worth the
                    455:                 * extra effort.) */
1.3       jmmv      456:                switch (mi->mi_boot_device_drive) {
                    457:                case 0x00:      devprefix = "fd0";      break;
                    458:                case 0x01:      devprefix = "fd1";      break;
                    459:                case 0x80:      devprefix = "wd0";      break;
                    460:                case 0x81:      devprefix = "wd1";      break;
                    461:                case 0x82:      devprefix = "wd2";      break;
                    462:                case 0x83:      devprefix = "wd3";      break;
1.4       jmmv      463:                default:        devprefix = "wd0";
1.1       jmmv      464:                }
                    465:
1.4       jmmv      466:                strcpy(bi.devname, devprefix);
                    467:                if (mi->mi_boot_device_part2 != 0xFF)
                    468:                        bi.devname[3] = mi->mi_boot_device_part2 + 'a';
                    469:                else
                    470:                        bi.devname[3] = 'a';
                    471:                bi.devname[4] = '\0';
1.1       jmmv      472:
1.4       jmmv      473:                found = TRUE;
1.1       jmmv      474:        }
                    475:
                    476:        if (found) {
                    477:                bootinfo_add((struct btinfo_common *)&bi, BTINFO_ROOTDEVICE,
                    478:                    sizeof(struct btinfo_rootdevice));
                    479:        }
                    480: }
                    481:
                    482: /* --------------------------------------------------------------------- */
                    483:
                    484: /*
                    485:  * Sets up the bootpath bootinfo structure with an appropriate kernel
                    486:  * name derived from the boot command line.  The Multiboot information
                    487:  * structure does not provide this detail directly, so we try to derive
                    488:  * it from the command line setting.
                    489:  */
                    490: static void
                    491: setup_bootpath(struct multiboot_info *mi)
                    492: {
                    493:        struct btinfo_bootpath bi;
                    494:        char *cl, *cl2, old;
                    495:        int len;
                    496:
                    497:        if (strncmp(Multiboot_Loader_Name, "GNU GRUB ",
                    498:            sizeof(Multiboot_Loader_Name)) > 0) {
                    499:                cl = mi->mi_cmdline;
                    500:                while (*cl != '\0' && *cl != '/')
                    501:                        cl++;
                    502:                cl2 = cl;
                    503:                len = 0;
                    504:                while (*cl2 != '\0' && *cl2 != ' ') {
                    505:                        len++;
                    506:                        cl2++;
                    507:                }
                    508:
                    509:                old = *cl2;
                    510:                *cl2 = '\0';
                    511:                memcpy(bi.bootpath, cl, MIN(sizeof(bi.bootpath), len));
                    512:                *cl2 = old;
                    513:                bi.bootpath[MIN(sizeof(bi.bootpath), len)] = '\0';
                    514:
                    515:                bootinfo_add((struct btinfo_common *)&bi, BTINFO_BOOTPATH,
                    516:                    sizeof(struct btinfo_bootpath));
                    517:        }
                    518: }
                    519:
                    520: /* --------------------------------------------------------------------- */
                    521:
                    522: /*
                    523:  * Sets up the console bootinfo structure if the user gave a 'console'
                    524:  * argument on the boot command line.  The Multiboot information
                    525:  * structure gives no hint about this, so the only way to know where the
                    526:  * console is is to let the user specify it.
                    527:  *
                    528:  * If there wasn't any 'console' argument, this does not generate any
                    529:  * bootinfo entry, falling back to the kernel's default console.
                    530:  *
                    531:  * If there weren't any of 'console_speed' or 'console_addr' arguments,
                    532:  * this falls back to the default values for the serial port.
                    533:  */
                    534: static void
                    535: setup_console(struct multiboot_info *mi)
                    536: {
                    537:        struct btinfo_console bi;
                    538:        boolean_t found;
                    539:
                    540:        found = FALSE;
                    541:
                    542:        if (mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE)
                    543:                found = optstr_get(mi->mi_cmdline, "console", bi.devname,
                    544:                    sizeof(bi.devname));
                    545:
                    546:        if (found) {
                    547:                if (strncmp(bi.devname, "com", sizeof(bi.devname)) == 0) {
                    548:                        char tmp[10];
                    549:
                    550:                        found = optstr_get(mi->mi_cmdline, "console_speed",
                    551:                            tmp, sizeof(tmp));
                    552:                        if (found)
                    553:                                bi.speed = strtoul(tmp, NULL, 10);
                    554:                        else
                    555:                                bi.speed = 0; /* Use default speed. */
                    556:
                    557:                        found = optstr_get(mi->mi_cmdline, "console_addr",
                    558:                            tmp, sizeof(tmp));
                    559:                        if (found) {
                    560:                                if (tmp[0] == '0' && tmp[1] == 'x')
                    561:                                        bi.addr = strtoul(tmp + 2, NULL, 16);
                    562:                                else
                    563:                                        bi.addr = strtoul(tmp, NULL, 10);
                    564:                        } else
                    565:                                bi.addr = 0; /* Use default address. */
                    566:                }
                    567:
                    568:                bootinfo_add((struct btinfo_common *)&bi, BTINFO_CONSOLE,
                    569:                    sizeof(struct btinfo_console));
                    570:        }
                    571: }
                    572:
                    573: /* --------------------------------------------------------------------- */
                    574:
                    575: /*
                    576:  * Sets up the 'boothowto' variable based on the options given in the
                    577:  * boot command line, if any.
                    578:  */
                    579: static void
                    580: setup_howto(struct multiboot_info *mi)
                    581: {
                    582:        char *cl;
                    583:
                    584:        if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE))
                    585:                return;
                    586:
                    587:        cl = mi->mi_cmdline;
                    588:
                    589:        /* Skip kernel file name. */
                    590:        while (*cl != '\0' && *cl != ' ')
                    591:                cl++;
                    592:        while (*cl != '\0' && *cl == ' ')
                    593:                cl++;
                    594:
                    595:        /* Check if there are flags and set 'howto' accordingly. */
                    596:        if (*cl == '-') {
                    597:                int howto = 0;
                    598:
                    599:                cl++;
                    600:                while (*cl != '\0' && *cl != ' ') {
                    601:                        BOOT_FLAG(*cl, howto);
                    602:                        cl++;
                    603:                }
                    604:                if (*cl == ' ')
                    605:                        cl++;
                    606:
                    607:                boothowto = howto;
                    608:        }
                    609: }
                    610:
                    611: /* --------------------------------------------------------------------- */
                    612:
                    613: /*
                    614:  * Sets up the memmap bootinfo structure to describe available memory as
                    615:  * given by the BIOS.
                    616:  */
                    617: static void
                    618: setup_memmap(struct multiboot_info *mi)
                    619: {
                    620:        char data[1024];
                    621:        size_t i;
                    622:        struct btinfo_memmap *bi;
                    623:
                    624:        if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_MMAP))
                    625:                return;
                    626:
                    627:        bi = (struct btinfo_memmap *)data;
                    628:        bi->num = 0;
                    629:
                    630:        i = 0;
                    631:        while (i < mi->mi_mmap_length) {
                    632:                struct multiboot_mmap *mm;
                    633:                struct bi_memmap_entry *bie;
                    634:
                    635:                bie = &bi->entry[bi->num];
                    636:
                    637:                mm = (struct multiboot_mmap *)(mi->mi_mmap_addr + i);
                    638:                bie->addr = mm->mm_base_addr;
                    639:                bie->size = mm->mm_length;
                    640:                if (mm->mm_type == 1)
                    641:                        bie->type = BIM_Memory;
                    642:                else
                    643:                        bie->type = BIM_Reserved;
                    644:
                    645:                bi->num++;
                    646:                i += mm->mm_size + 4;
                    647:        }
                    648:
                    649:        bootinfo_add((struct btinfo_common *)bi, BTINFO_MEMMAP,
                    650:            sizeof(data));
                    651: }
                    652:
                    653: /* --------------------------------------------------------------------- */
                    654:
                    655: /*
                    656:  * Sets up the 'biosbasemem' and 'biosextmem' variables if the
                    657:  * Multiboot information structure provides information about memory.
                    658:  */
                    659: static void
                    660: setup_memory(struct multiboot_info *mi)
                    661: {
1.6       mrg       662:
1.1       jmmv      663:        if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_MEMORY))
                    664:                return;
                    665:
1.6       mrg       666:        /* Make sure we don't override user-set variables. */
                    667:        if (biosbasemem == 0) {
                    668:                biosbasemem = mi->mi_mem_lower;
                    669:                biosmem_implicit = 1;
                    670:        }
                    671:        if (biosextmem == 0) {
                    672:                biosextmem = mi->mi_mem_upper;
                    673:                biosmem_implicit = 1;
                    674:        }
1.1       jmmv      675: }
                    676:
                    677: /* --------------------------------------------------------------------- */
                    678:
                    679: /*
1.8       jmmv      680:  * Sets up the initial kernel symbol table.  Returns true if this was
                    681:  * passed in by Multiboot; false otherwise.
1.1       jmmv      682:  */
1.8       jmmv      683: boolean_t
                    684: multiboot_ksyms_init(void)
1.1       jmmv      685: {
1.8       jmmv      686:        struct multiboot_info *mi = &Multiboot_Info;
                    687:        struct multiboot_symbols *ms = &Multiboot_Symbols;
1.1       jmmv      688:
1.8       jmmv      689:        if (mi->mi_flags & MULTIBOOT_INFO_HAS_ELF_SYMS) {
1.9     ! jmmv      690:                Elf32_Ehdr ehdr;
        !           691:
1.8       jmmv      692:                KASSERT(esym != 0);
1.1       jmmv      693:
1.9     ! jmmv      694:                memcpy(ehdr.e_ident, ELFMAG, SELFMAG);
        !           695:                ehdr.e_ident[EI_CLASS] = ELFCLASS32;
        !           696:                ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
        !           697:                ehdr.e_ident[EI_VERSION] = EV_CURRENT;
        !           698:                ehdr.e_type = ET_EXEC;
        !           699:                ehdr.e_machine = EM_386;
        !           700:                ehdr.e_version = 1;
        !           701:                ehdr.e_ehsize = sizeof(ehdr);
        !           702:
        !           703:                ksyms_init_explicit((caddr_t)&ehdr,
        !           704:                    ms->s_symstart, ms->s_symsize,
1.8       jmmv      705:                    ms->s_strstart, ms->s_strsize);
                    706:        }
1.1       jmmv      707:
1.8       jmmv      708:        return mi->mi_flags & MULTIBOOT_INFO_HAS_ELF_SYMS;
1.1       jmmv      709: }

CVSweb <webmaster@jp.NetBSD.org>