Home | History | Annotate | Line # | Download | only in lib
exec_multiboot1.c revision 1.2
      1 /* $NetBSD: exec_multiboot1.c,v 1.2 2019/10/18 01:04:24 manu Exp $ */
      2 
      3 /*
      4  * Copyright (c) 2019 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26  * POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 #include <sys/param.h>
     30 #include <sys/reboot.h>
     31 
     32 #include <i386/multiboot.h>
     33 
     34 #include <lib/libsa/stand.h>
     35 #include <lib/libkern/libkern.h>
     36 
     37 #include "loadfile.h"
     38 #include "libi386.h"
     39 #include "bootinfo.h"
     40 #include "bootmod.h"
     41 #include "vbe.h"
     42 
     43 extern struct btinfo_modulelist *btinfo_modulelist;
     44 
     45 static int
     46 exec_multiboot1(struct multiboot_package *mbp)
     47 {
     48 	struct multiboot_info *mbi;
     49 	struct multiboot_module *mbm;
     50 	int i, len;
     51 	char *cmdline;
     52 	struct bi_modulelist_entry *bim;
     53 
     54 	mbi = alloc(sizeof(struct multiboot_info));
     55 	mbi->mi_flags = MULTIBOOT_INFO_HAS_MEMORY;
     56 
     57 	mbi->mi_mem_upper = mbp->mbp_extmem;
     58 	mbi->mi_mem_lower = mbp->mbp_basemem;
     59 
     60 	if (mbp->mbp_args) {
     61 		mbi->mi_flags |= MULTIBOOT_INFO_HAS_CMDLINE;
     62 		len = strlen(mbp->mbp_file) + 1 + strlen(mbp->mbp_args) + 1;
     63 		cmdline = alloc(len);
     64 		snprintf(cmdline, len, "%s %s", mbp->mbp_file, mbp->mbp_args);
     65 		mbi->mi_cmdline = (char *) vtophys(cmdline);
     66 	}
     67 
     68 	/* pull in any modules if necessary */
     69 	if (btinfo_modulelist) {
     70 		mbm = alloc(sizeof(struct multiboot_module) *
     71 				   btinfo_modulelist->num);
     72 
     73 		bim = (struct bi_modulelist_entry *)
     74 		  (((char *) btinfo_modulelist) +
     75 		   sizeof(struct btinfo_modulelist));
     76 		for (i = 0; i < btinfo_modulelist->num; i++) {
     77 			mbm[i].mmo_start = bim->base;
     78 			mbm[i].mmo_end = bim->base + bim->len;
     79 			mbm[i].mmo_string = (char *)vtophys(bim->path);
     80 			mbm[i].mmo_reserved = 0;
     81 			bim++;
     82 		}
     83 		mbi->mi_flags |= MULTIBOOT_INFO_HAS_MODS;
     84 		mbi->mi_mods_count = btinfo_modulelist->num;
     85 		mbi->mi_mods_addr = vtophys(mbm);
     86 	}
     87 
     88 #ifdef DEBUG
     89 	printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n",
     90 	    mbp->mbp_marks[MARK_ENTRY],
     91 	    mbp->mbp_marks[MARK_NSYM],
     92 	    mbp->mbp_marks[MARK_SYM],
     93 	    mbp->mbp_marks[MARK_END]);
     94 #endif
     95 
     96 	/* Does not return */
     97 	multiboot(mbp->mbp_marks[MARK_ENTRY], vtophys(mbi),
     98 	    x86_trunc_page(mbi->mi_mem_lower * 1024), MULTIBOOT_INFO_MAGIC);
     99 
    100 	return 0;
    101 }
    102 
    103 static void
    104 cleanup_multiboot1(struct multiboot_package *mbp)
    105 {
    106 	dealloc(mbp->mbp_header, sizeof(*mbp->mbp_header));
    107 	dealloc(mbp, sizeof(*mbp));
    108 
    109 	return;
    110 }
    111 
    112 
    113 struct multiboot_package *
    114 probe_multiboot1(const char *path)
    115 {
    116 	int fd = -1;
    117 	size_t i;
    118 	char buf[8192 + sizeof(struct multiboot_header)];
    119 	ssize_t readen;
    120 	struct multiboot_package *mbp = NULL;
    121 
    122 	if ((fd = open(path, 0)) == -1)
    123 		goto out;
    124 
    125 	readen = read(fd, buf, sizeof(buf));
    126 	if (readen < sizeof(struct multiboot_header))
    127 		goto out;
    128 
    129 	for (i = 0; i < readen; i += 4) {
    130 		struct multiboot_header *mbh;
    131 
    132 		mbh = (struct multiboot_header *)(buf + i);
    133 
    134 		if (mbh->mh_magic != MULTIBOOT_HEADER_MAGIC)
    135 			continue;
    136 
    137 		if (mbh->mh_magic + mbh->mh_flags + mbh->mh_checksum)
    138 			continue;
    139 
    140 		mbp = alloc(sizeof(*mbp));
    141 		mbp->mbp_version	= 1;
    142 		mbp->mbp_file		= path;
    143 		mbp->mbp_header		= alloc(sizeof(*mbp->mbp_header));
    144 		mbp->mbp_probe		= *probe_multiboot1;
    145 		mbp->mbp_exec		= *exec_multiboot1;
    146 		mbp->mbp_cleanup	= *cleanup_multiboot1;
    147 
    148 		memcpy(mbp->mbp_header, mbh, sizeof(*mbp->mbp_header));
    149 
    150 		goto out;
    151 
    152 	}
    153 
    154 out:
    155 	if (fd != -1)
    156 		close(fd);
    157 
    158 	return mbp;
    159 }
    160