1 1.3 manu /* $NetBSD: exec_multiboot1.c,v 1.3 2019/10/18 01:09:46 manu Exp $ */ 2 1.1 manu 3 1.1 manu /* 4 1.1 manu * Copyright (c) 2019 The NetBSD Foundation, Inc. 5 1.1 manu * All rights reserved. 6 1.1 manu * 7 1.1 manu * Redistribution and use in source and binary forms, with or without 8 1.1 manu * modification, are permitted provided that the following conditions 9 1.1 manu * are met: 10 1.1 manu * 1. Redistributions of source code must retain the above copyright 11 1.1 manu * notice, this list of conditions and the following disclaimer. 12 1.1 manu * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 manu * notice, this list of conditions and the following disclaimer in the 14 1.1 manu * documentation and/or other materials provided with the distribution. 15 1.1 manu * 16 1.1 manu * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 1.1 manu * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 1.1 manu * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 1.1 manu * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 1.1 manu * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 1.1 manu * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 1.1 manu * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 1.1 manu * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 1.1 manu * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 1.1 manu * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 1.1 manu * POSSIBILITY OF SUCH DAMAGE. 27 1.1 manu */ 28 1.1 manu 29 1.1 manu #include <sys/param.h> 30 1.1 manu #include <sys/reboot.h> 31 1.1 manu 32 1.1 manu #include <i386/multiboot.h> 33 1.1 manu 34 1.1 manu #include <lib/libsa/stand.h> 35 1.1 manu #include <lib/libkern/libkern.h> 36 1.1 manu 37 1.1 manu #include "loadfile.h" 38 1.1 manu #include "libi386.h" 39 1.1 manu #include "bootinfo.h" 40 1.1 manu #include "bootmod.h" 41 1.1 manu #include "vbe.h" 42 1.1 manu 43 1.1 manu extern struct btinfo_modulelist *btinfo_modulelist; 44 1.1 manu 45 1.3 manu void 46 1.3 manu ksyms_addr_set(void *ehdr, void *shdr, void *symbase) 47 1.3 manu { 48 1.3 manu int class; 49 1.3 manu Elf32_Ehdr *ehdr32 = NULL; 50 1.3 manu Elf64_Ehdr *ehdr64 = NULL; 51 1.3 manu uint64_t shnum; 52 1.3 manu int i; 53 1.3 manu 54 1.3 manu class = ((Elf_Ehdr *)ehdr)->e_ident[EI_CLASS]; 55 1.3 manu 56 1.3 manu switch (class) { 57 1.3 manu case ELFCLASS32: 58 1.3 manu ehdr32 = (Elf32_Ehdr *)ehdr; 59 1.3 manu shnum = ehdr32->e_shnum; 60 1.3 manu break; 61 1.3 manu case ELFCLASS64: 62 1.3 manu ehdr64 = (Elf64_Ehdr *)ehdr; 63 1.3 manu shnum = ehdr64->e_shnum; 64 1.3 manu break; 65 1.3 manu default: 66 1.3 manu panic("Unexpected ELF class"); 67 1.3 manu break; 68 1.3 manu } 69 1.3 manu 70 1.3 manu for (i = 0; i < shnum; i++) { 71 1.3 manu Elf64_Shdr *shdrp64 = NULL; 72 1.3 manu Elf32_Shdr *shdrp32 = NULL; 73 1.3 manu uint64_t shtype, shaddr, shsize, shoffset; 74 1.3 manu 75 1.3 manu switch(class) { 76 1.3 manu case ELFCLASS64: 77 1.3 manu shdrp64 = &((Elf64_Shdr *)shdr)[i]; 78 1.3 manu shtype = shdrp64->sh_type; 79 1.3 manu shaddr = shdrp64->sh_addr; 80 1.3 manu shsize = shdrp64->sh_size; 81 1.3 manu shoffset = shdrp64->sh_offset; 82 1.3 manu break; 83 1.3 manu case ELFCLASS32: 84 1.3 manu shdrp32 = &((Elf32_Shdr *)shdr)[i]; 85 1.3 manu shtype = shdrp32->sh_type; 86 1.3 manu shaddr = shdrp32->sh_addr; 87 1.3 manu shsize = shdrp32->sh_size; 88 1.3 manu shoffset = shdrp32->sh_offset; 89 1.3 manu break; 90 1.3 manu default: 91 1.3 manu panic("Unexpected ELF class"); 92 1.3 manu break; 93 1.3 manu } 94 1.3 manu 95 1.3 manu if (shtype != SHT_SYMTAB && shtype != SHT_STRTAB) 96 1.3 manu continue; 97 1.3 manu 98 1.3 manu if (shaddr != 0 || shsize == 0) 99 1.3 manu continue; 100 1.3 manu 101 1.3 manu shaddr = (uint64_t)(uintptr_t)(symbase + shoffset); 102 1.3 manu 103 1.3 manu switch(class) { 104 1.3 manu case ELFCLASS64: 105 1.3 manu shdrp64->sh_addr = shaddr; 106 1.3 manu break; 107 1.3 manu case ELFCLASS32: 108 1.3 manu shdrp32->sh_addr = shaddr; 109 1.3 manu break; 110 1.3 manu default: 111 1.3 manu panic("Unexpected ELF class"); 112 1.3 manu break; 113 1.3 manu } 114 1.3 manu } 115 1.3 manu 116 1.3 manu return; 117 1.3 manu } 118 1.3 manu 119 1.1 manu static int 120 1.1 manu exec_multiboot1(struct multiboot_package *mbp) 121 1.1 manu { 122 1.1 manu struct multiboot_info *mbi; 123 1.1 manu struct multiboot_module *mbm; 124 1.1 manu int i, len; 125 1.1 manu char *cmdline; 126 1.1 manu struct bi_modulelist_entry *bim; 127 1.1 manu 128 1.1 manu mbi = alloc(sizeof(struct multiboot_info)); 129 1.1 manu mbi->mi_flags = MULTIBOOT_INFO_HAS_MEMORY; 130 1.1 manu 131 1.1 manu mbi->mi_mem_upper = mbp->mbp_extmem; 132 1.1 manu mbi->mi_mem_lower = mbp->mbp_basemem; 133 1.1 manu 134 1.1 manu if (mbp->mbp_args) { 135 1.1 manu mbi->mi_flags |= MULTIBOOT_INFO_HAS_CMDLINE; 136 1.1 manu len = strlen(mbp->mbp_file) + 1 + strlen(mbp->mbp_args) + 1; 137 1.1 manu cmdline = alloc(len); 138 1.1 manu snprintf(cmdline, len, "%s %s", mbp->mbp_file, mbp->mbp_args); 139 1.1 manu mbi->mi_cmdline = (char *) vtophys(cmdline); 140 1.1 manu } 141 1.1 manu 142 1.1 manu /* pull in any modules if necessary */ 143 1.1 manu if (btinfo_modulelist) { 144 1.1 manu mbm = alloc(sizeof(struct multiboot_module) * 145 1.1 manu btinfo_modulelist->num); 146 1.1 manu 147 1.1 manu bim = (struct bi_modulelist_entry *) 148 1.1 manu (((char *) btinfo_modulelist) + 149 1.1 manu sizeof(struct btinfo_modulelist)); 150 1.1 manu for (i = 0; i < btinfo_modulelist->num; i++) { 151 1.1 manu mbm[i].mmo_start = bim->base; 152 1.1 manu mbm[i].mmo_end = bim->base + bim->len; 153 1.1 manu mbm[i].mmo_string = (char *)vtophys(bim->path); 154 1.1 manu mbm[i].mmo_reserved = 0; 155 1.1 manu bim++; 156 1.1 manu } 157 1.1 manu mbi->mi_flags |= MULTIBOOT_INFO_HAS_MODS; 158 1.1 manu mbi->mi_mods_count = btinfo_modulelist->num; 159 1.1 manu mbi->mi_mods_addr = vtophys(mbm); 160 1.1 manu } 161 1.1 manu 162 1.3 manu if (mbp->mbp_marks[MARK_SYM] != 0) { 163 1.3 manu Elf32_Ehdr ehdr; 164 1.3 manu void *shbuf; 165 1.3 manu size_t shlen; 166 1.3 manu u_long shaddr; 167 1.3 manu 168 1.3 manu pvbcopy((void *)mbp->mbp_marks[MARK_SYM], &ehdr, sizeof(ehdr)); 169 1.3 manu 170 1.3 manu if (memcmp(&ehdr.e_ident, ELFMAG, SELFMAG) != 0) 171 1.3 manu goto skip_ksyms; 172 1.3 manu 173 1.3 manu shaddr = mbp->mbp_marks[MARK_SYM] + ehdr.e_shoff; 174 1.3 manu 175 1.3 manu shlen = ehdr.e_shnum * ehdr.e_shentsize; 176 1.3 manu shbuf = alloc(shlen); 177 1.3 manu 178 1.3 manu pvbcopy((void *)shaddr, shbuf, shlen); 179 1.3 manu ksyms_addr_set(&ehdr, shbuf, 180 1.3 manu (void *)(KERNBASE + mbp->mbp_marks[MARK_SYM])); 181 1.3 manu vpbcopy(shbuf, (void *)shaddr, shlen); 182 1.3 manu 183 1.3 manu dealloc(shbuf, shlen); 184 1.3 manu 185 1.3 manu mbi->mi_elfshdr_num = ehdr.e_shnum; 186 1.3 manu mbi->mi_elfshdr_size = ehdr.e_shentsize; 187 1.3 manu mbi->mi_elfshdr_addr = shaddr; 188 1.3 manu mbi->mi_elfshdr_shndx = ehdr.e_shstrndx; 189 1.3 manu 190 1.3 manu mbi->mi_flags |= MULTIBOOT_INFO_HAS_ELF_SYMS; 191 1.3 manu } 192 1.3 manu skip_ksyms: 193 1.3 manu 194 1.1 manu #ifdef DEBUG 195 1.1 manu printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n", 196 1.1 manu mbp->mbp_marks[MARK_ENTRY], 197 1.1 manu mbp->mbp_marks[MARK_NSYM], 198 1.1 manu mbp->mbp_marks[MARK_SYM], 199 1.1 manu mbp->mbp_marks[MARK_END]); 200 1.1 manu #endif 201 1.1 manu 202 1.1 manu /* Does not return */ 203 1.1 manu multiboot(mbp->mbp_marks[MARK_ENTRY], vtophys(mbi), 204 1.1 manu x86_trunc_page(mbi->mi_mem_lower * 1024), MULTIBOOT_INFO_MAGIC); 205 1.1 manu 206 1.1 manu return 0; 207 1.1 manu } 208 1.1 manu 209 1.1 manu static void 210 1.1 manu cleanup_multiboot1(struct multiboot_package *mbp) 211 1.1 manu { 212 1.1 manu dealloc(mbp->mbp_header, sizeof(*mbp->mbp_header)); 213 1.1 manu dealloc(mbp, sizeof(*mbp)); 214 1.1 manu 215 1.1 manu return; 216 1.1 manu } 217 1.1 manu 218 1.1 manu 219 1.1 manu struct multiboot_package * 220 1.1 manu probe_multiboot1(const char *path) 221 1.1 manu { 222 1.1 manu int fd = -1; 223 1.1 manu size_t i; 224 1.1 manu char buf[8192 + sizeof(struct multiboot_header)]; 225 1.1 manu ssize_t readen; 226 1.1 manu struct multiboot_package *mbp = NULL; 227 1.1 manu 228 1.1 manu if ((fd = open(path, 0)) == -1) 229 1.1 manu goto out; 230 1.1 manu 231 1.1 manu readen = read(fd, buf, sizeof(buf)); 232 1.1 manu if (readen < sizeof(struct multiboot_header)) 233 1.1 manu goto out; 234 1.1 manu 235 1.2 manu for (i = 0; i < readen; i += 4) { 236 1.1 manu struct multiboot_header *mbh; 237 1.1 manu 238 1.1 manu mbh = (struct multiboot_header *)(buf + i); 239 1.1 manu 240 1.1 manu if (mbh->mh_magic != MULTIBOOT_HEADER_MAGIC) 241 1.1 manu continue; 242 1.1 manu 243 1.1 manu if (mbh->mh_magic + mbh->mh_flags + mbh->mh_checksum) 244 1.1 manu continue; 245 1.1 manu 246 1.1 manu mbp = alloc(sizeof(*mbp)); 247 1.1 manu mbp->mbp_version = 1; 248 1.1 manu mbp->mbp_file = path; 249 1.1 manu mbp->mbp_header = alloc(sizeof(*mbp->mbp_header)); 250 1.1 manu mbp->mbp_probe = *probe_multiboot1; 251 1.1 manu mbp->mbp_exec = *exec_multiboot1; 252 1.1 manu mbp->mbp_cleanup = *cleanup_multiboot1; 253 1.1 manu 254 1.1 manu memcpy(mbp->mbp_header, mbh, sizeof(*mbp->mbp_header)); 255 1.1 manu 256 1.1 manu goto out; 257 1.1 manu 258 1.1 manu } 259 1.1 manu 260 1.1 manu out: 261 1.1 manu if (fd != -1) 262 1.1 manu close(fd); 263 1.1 manu 264 1.1 manu return mbp; 265 1.1 manu } 266