1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 28 #include <sys/types.h> 29 #include <sys/param.h> 30 #include <sys/segments.h> 31 #include <sys/sysmacros.h> 32 #include <sys/vm.h> 33 34 #include <sys/proc.h> 35 #include <sys/buf.h> 36 #include <sys/kmem.h> 37 38 #include <sys/reboot.h> 39 #include <sys/uadmin.h> 40 41 #include <sys/cred.h> 42 #include <sys/vnode.h> 43 #include <sys/file.h> 44 45 #include <sys/cmn_err.h> 46 #include <sys/dumphdr.h> 47 #include <sys/bootconf.h> 48 #include <sys/ddidmareq.h> 49 #include <sys/varargs.h> 50 #include <sys/promif.h> 51 #include <sys/modctl.h> 52 53 #include <vm/hat.h> 54 #include <vm/as.h> 55 #include <vm/page.h> 56 #include <vm/seg.h> 57 #include <vm/hat_i86.h> 58 #include <sys/vm_machparam.h> 59 #include <sys/archsystm.h> 60 #include <sys/machsystm.h> 61 #include <sys/mman.h> 62 #include <sys/x86_archext.h> 63 64 #include <sys/fastboot.h> 65 #include <sys/machelf.h> 66 #include <sys/kobj.h> 67 #include <sys/multiboot.h> 68 69 fastboot_info_t newkernel = { 0 }; 70 static char fastboot_filename[2][OBP_MAXPATHLEN] = { { 0 }, { 0 }}; 71 static x86pte_t ptp_bits = PT_VALID | PT_REF | PT_USER | PT_WRITABLE; 72 static x86pte_t pte_bits = 73 PT_VALID | PT_REF | PT_MOD | PT_NOCONSIST | PT_WRITABLE; 74 static uint_t fastboot_shift_amt_pae[] = {12, 21, 30, 39}; 75 76 77 int fastboot_debug = 0; 78 int fastboot_contig = 0; 79 80 /* 81 * Fake starting va for new kernel and boot archive. 82 */ 83 static uintptr_t fake_va = FASTBOOT_FAKE_VA; 84 85 /* 86 * Below 1G for page tables as we are using 2G as the fake virtual address for 87 * the new kernel and boot archive. 88 */ 89 static ddi_dma_attr_t fastboot_below_1G_dma_attr = { 90 DMA_ATTR_V0, 91 0x0000000008000000ULL, /* dma_attr_addr_lo: 128MB */ 92 0x000000003FFFFFFFULL, /* dma_attr_addr_hi: 1G */ 93 0x00000000FFFFFFFFULL, /* dma_attr_count_max */ 94 0x0000000000001000ULL, /* dma_attr_align: 4KB */ 95 1, /* dma_attr_burstsize */ 96 1, /* dma_attr_minxfer */ 97 0x00000000FFFFFFFFULL, /* dma_attr_maxxfer */ 98 0x00000000FFFFFFFFULL, /* dma_attr_seg */ 99 1, /* dma_attr_sgllen */ 100 0x1000ULL, /* dma_attr_granular */ 101 0, /* dma_attr_flags */ 102 }; 103 104 static ddi_dma_attr_t fastboot_dma_attr = { 105 DMA_ATTR_V0, 106 0x0000000008000000ULL, /* dma_attr_addr_lo: 128MB */ 107 0x0000000FFFFFFFFFULL, /* dma_attr_addr_hi: 64GB */ 108 0x00000000FFFFFFFFULL, /* dma_attr_count_max */ 109 0x0000000000001000ULL, /* dma_attr_align: 4KB */ 110 1, /* dma_attr_burstsize */ 111 1, /* dma_attr_minxfer */ 112 0x00000000FFFFFFFFULL, /* dma_attr_maxxfer */ 113 0x00000000FFFFFFFFULL, /* dma_attr_seg */ 114 1, /* dma_attr_sgllen */ 115 0x1000ULL, /* dma_attr_granular */ 116 0, /* dma_attr_flags */ 117 }; 118 119 /* 120 * Various information saved from the previous boot to reconstruct 121 * multiboot_info. 122 */ 123 extern multiboot_info_t saved_mbi; 124 extern mb_memory_map_t saved_mmap[FASTBOOT_SAVED_MMAP_COUNT]; 125 extern struct sol_netinfo saved_drives[FASTBOOT_SAVED_DRIVES_COUNT]; 126 extern char saved_cmdline[FASTBOOT_SAVED_CMDLINE_LEN]; 127 extern int saved_cmdline_len; 128 129 extern void* contig_alloc(size_t size, ddi_dma_attr_t *attr, 130 uintptr_t align, int cansleep); 131 132 /* PRINTLIKE */ 133 extern void vprintf(const char *, va_list); 134 135 136 /* 137 * Need to be able to get boot_archives from other places 138 */ 139 #define BOOTARCHIVE64 "/platform/i86pc/amd64/boot_archive" 140 #define BOOTARCHIVE32 "/platform/i86pc/boot_archive" 141 #define BOOTARCHIVE_FAILSAFE "/boot/x86.miniroot-safe" 142 #define FAILSAFE_BOOTFILE "/boot/platform/i86pc/kernel/unix" 143 144 static uint_t fastboot_vatoindex(fastboot_info_t *, uintptr_t, int); 145 static void fastboot_map_with_size(fastboot_info_t *, uintptr_t, 146 paddr_t, size_t, int); 147 static void fastboot_build_pagetables(fastboot_info_t *); 148 static int fastboot_build_mbi(char *, fastboot_info_t *); 149 150 static const char fastboot_enomem_msg[] = "Fastboot: Couldn't allocate 0x%" 151 PRIx64" bytes below %s to do fast reboot"; 152 153 static void 154 dprintf(char *fmt, ...) 155 { 156 va_list adx; 157 158 if (!fastboot_debug) 159 return; 160 161 va_start(adx, fmt); 162 vprintf(fmt, adx); 163 va_end(adx); 164 } 165 166 167 /* 168 * Return the index corresponding to a virt address at a given page table level. 169 */ 170 static uint_t 171 fastboot_vatoindex(fastboot_info_t *nk, uintptr_t va, int level) 172 { 173 return ((va >> nk->fi_shift_amt[level]) & (nk->fi_ptes_per_table - 1)); 174 } 175 176 177 /* 178 * Add mapping from vstart to pstart for the specified size. 179 * Only handles 2 level. Must use 2M pages. vstart, pstart 180 * and size should all have been aligned at 2M boundaries. 181 */ 182 static void 183 fastboot_map_with_size(fastboot_info_t *nk, uintptr_t vstart, paddr_t pstart, 184 size_t size, int level) 185 { 186 x86pte_t pteval, *table; 187 uintptr_t vaddr; 188 paddr_t paddr; 189 int index, l; 190 191 table = (x86pte_t *)(nk->fi_pagetable_va); 192 193 for (l = nk->fi_top_level; l >= level; l--) { 194 195 index = fastboot_vatoindex(nk, vstart, l); 196 197 if (l == level) { 198 /* 199 * Last level. Program the page table entries. 200 */ 201 for (vaddr = vstart, paddr = pstart; 202 vaddr < vstart + size; 203 vaddr += (1ULL << nk->fi_shift_amt[l]), 204 paddr += (1ULL << nk->fi_shift_amt[l])) { 205 206 uint_t index = fastboot_vatoindex(nk, vaddr, l); 207 208 if (l > 0) 209 pteval = paddr | pte_bits | PT_PAGESIZE; 210 else 211 pteval = paddr | pte_bits; 212 213 table[index] = pteval; 214 } 215 } else if (table[index] & PT_VALID) { 216 if (l == level) 217 break; 218 219 table = (x86pte_t *) 220 ((uintptr_t)(((paddr_t)table[index] & MMU_PAGEMASK) 221 - nk->fi_pagetable_pa) + nk->fi_pagetable_va); 222 } else { 223 /* 224 * Intermediate levels. Program with either valid 225 * bit or PTP bits. 226 */ 227 if (l == nk->fi_top_level) { 228 table[index] = nk->fi_next_table_pa | PT_VALID; 229 } else { 230 table[index] = nk->fi_next_table_pa | ptp_bits; 231 } 232 table = (x86pte_t *)(nk->fi_next_table_va); 233 nk->fi_next_table_va += MMU_PAGESIZE; 234 nk->fi_next_table_pa += MMU_PAGESIZE; 235 } 236 } 237 } 238 239 /* 240 * Build page tables for the lower 1G of physical memory using 2M 241 * pages, and prepare page tables for mapping new kernel and boot 242 * archive pages using 4K pages. 243 */ 244 static void 245 fastboot_build_pagetables(fastboot_info_t *nk) 246 { 247 /* 248 * Map lower 1G physical memory. Use large pages. 249 */ 250 fastboot_map_with_size(nk, 0, 0, ONE_GIG, 1); 251 252 /* 253 * Map one 4K page to get the middle page tables set up. 254 */ 255 fake_va = P2ALIGN_TYPED(fake_va, nk->fi_lpagesize, uintptr_t); 256 fastboot_map_with_size(nk, fake_va, 257 nk->fi_files[0].fb_pte_list_va[0] & MMU_PAGEMASK, PAGESIZE, 0); 258 } 259 260 261 /* 262 * Sanity check. Look for dboot offset. 263 */ 264 static int 265 fastboot_elf64_find_dboot_load_offset(void *img, off_t imgsz, uint32_t *offp) 266 { 267 Elf64_Ehdr *ehdr = (Elf64_Ehdr *)img; 268 Elf64_Phdr *phdr; 269 uint8_t *phdrbase; 270 int i; 271 272 if ((ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize) >= imgsz) 273 return (-1); 274 275 phdrbase = (uint8_t *)img + ehdr->e_phoff; 276 277 for (i = 0; i < ehdr->e_phnum; i++) { 278 phdr = (Elf64_Phdr *)(phdrbase + ehdr->e_phentsize * i); 279 280 if (phdr->p_type == PT_LOAD) { 281 if (phdr->p_vaddr == phdr->p_paddr && 282 phdr->p_vaddr == DBOOT_ENTRY_ADDRESS) { 283 ASSERT(phdr->p_offset <= UINT32_MAX); 284 *offp = (uint32_t)phdr->p_offset; 285 return (0); 286 } 287 } 288 } 289 290 return (-1); 291 } 292 293 294 /* 295 * Initialize text and data section information for 32-bit kernel. 296 */ 297 static int 298 fastboot_elf32_find_loadables(void *img, off_t imgsz, fastboot_section_t *sectp, 299 int *sectcntp, uint32_t *offp) 300 { 301 Elf32_Ehdr *ehdr = (Elf32_Ehdr *)img; 302 Elf32_Phdr *phdr; 303 uint8_t *phdrbase; 304 int i; 305 int used_sections = 0; 306 307 308 if ((ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize) >= imgsz) 309 return (-1); 310 311 phdrbase = (uint8_t *)img + ehdr->e_phoff; 312 313 for (i = 0; i < ehdr->e_phnum; i++) { 314 phdr = (Elf32_Phdr *)(phdrbase + ehdr->e_phentsize * i); 315 316 if (phdr->p_type == PT_INTERP) 317 return (-1); 318 319 if (phdr->p_type != PT_LOAD) 320 continue; 321 322 if (phdr->p_vaddr == phdr->p_paddr && 323 phdr->p_paddr == DBOOT_ENTRY_ADDRESS) { 324 *offp = (uint32_t)phdr->p_offset; 325 } else { 326 sectp[used_sections].fb_sec_offset = phdr->p_offset; 327 sectp[used_sections].fb_sec_paddr = phdr->p_paddr; 328 sectp[used_sections].fb_sec_size = phdr->p_filesz; 329 sectp[used_sections].fb_sec_bss_size = 330 (phdr->p_filesz < phdr->p_memsz) ? 331 (phdr->p_memsz - phdr->p_filesz) : 0; 332 333 used_sections++; 334 } 335 336 } 337 338 *sectcntp = used_sections; 339 return (0); 340 } 341 342 /* 343 * Create multiboot info structure 344 */ 345 static int 346 fastboot_build_mbi(char *mdep, fastboot_info_t *nk) 347 { 348 mb_module_t *mbp; 349 uintptr_t next_addr; 350 uintptr_t new_mbi_pa; 351 size_t size; 352 void *buf = NULL; 353 size_t arglen; 354 char bootargs[OBP_MAXPATHLEN]; 355 356 bzero(bootargs, OBP_MAXPATHLEN); 357 358 if (mdep != NULL) { 359 arglen = strlen(mdep) + 1; 360 } else { 361 arglen = saved_cmdline_len; 362 } 363 364 size = PAGESIZE + P2ROUNDUP(arglen, PAGESIZE); 365 buf = contig_alloc(size, &fastboot_below_1G_dma_attr, PAGESIZE, 0); 366 if (buf == NULL) { 367 cmn_err(CE_WARN, fastboot_enomem_msg, (uint64_t)size, "1G"); 368 return (-1); 369 } 370 371 bzero(buf, size); 372 373 new_mbi_pa = mmu_ptob((uint64_t)hat_getpfnum(kas.a_hat, (caddr_t)buf)); 374 375 hat_devload(kas.a_hat, (caddr_t)new_mbi_pa, size, 376 mmu_btop(new_mbi_pa), PROT_READ | PROT_WRITE, HAT_LOAD_NOCONSIST); 377 378 nk->fi_new_mbi_pa = (paddr_t)new_mbi_pa; 379 380 bcopy(&saved_mbi, (void *)new_mbi_pa, sizeof (multiboot_info_t)); 381 382 next_addr = new_mbi_pa + sizeof (multiboot_info_t); 383 ((multiboot_info_t *)new_mbi_pa)->mods_addr = next_addr; 384 mbp = (mb_module_t *)(uintptr_t)next_addr; 385 mbp->mod_start = newkernel.fi_files[FASTBOOT_BOOTARCHIVE].fb_dest_pa; 386 mbp->mod_end = newkernel.fi_files[FASTBOOT_BOOTARCHIVE].fb_next_pa; 387 388 next_addr += sizeof (mb_module_t); 389 bcopy(fastboot_filename[FASTBOOT_NAME_BOOTARCHIVE], (void *)next_addr, 390 strlen(fastboot_filename[FASTBOOT_NAME_BOOTARCHIVE])); 391 392 mbp->mod_name = next_addr; 393 mbp->reserved = 0; 394 next_addr += strlen(fastboot_filename[FASTBOOT_NAME_BOOTARCHIVE]); 395 *(char *)next_addr = '\0'; 396 next_addr++; 397 next_addr = P2ROUNDUP_TYPED(next_addr, 16, uintptr_t); 398 399 ((multiboot_info_t *)new_mbi_pa)->mmap_addr = next_addr; 400 bcopy((void *)(uintptr_t)saved_mmap, (void *)next_addr, 401 saved_mbi.mmap_length); 402 next_addr += saved_mbi.mmap_length; 403 404 ((multiboot_info_t *)new_mbi_pa)->drives_addr = next_addr; 405 bcopy((void *)(uintptr_t)saved_drives, (void *)next_addr, 406 saved_mbi.drives_length); 407 next_addr += saved_mbi.drives_length; 408 409 ((multiboot_info_t *)new_mbi_pa)->cmdline = next_addr; 410 411 if (mdep != NULL) { 412 bcopy(mdep, (void *)(uintptr_t) 413 (((multiboot_info_t *)new_mbi_pa)->cmdline), (arglen - 1)); 414 } else { 415 bcopy((void *)saved_cmdline, (void *)next_addr, (arglen - 1)); 416 } 417 /* Terminate the string */ 418 ((char *)(intptr_t)next_addr)[arglen - 1] = '\0'; 419 420 return (0); 421 } 422 423 424 void 425 load_kernel(char *mdep) 426 { 427 struct _buf *file; 428 void *buf = NULL; 429 uintptr_t va; 430 int i, j; 431 fastboot_file_t *fb; 432 uint32_t dboot_start_offset; 433 Ehdr *ehdr; 434 char kern_bootpath[OBP_MAXPATHLEN]; 435 char bootargs[OBP_MAXPATHLEN]; 436 extern uintptr_t postbootkernelbase; 437 extern char fb_swtch_image[]; 438 int bootpath_len = 0; 439 int is_failsafe = 0; 440 uintptr_t next_pa = 0; /* next available physical addr */ 441 442 ASSERT(fastreboot_capable); 443 444 postbootkernelbase = 0; 445 446 if (x86_feature & X86_PAE) { 447 newkernel.fi_has_pae = 1; 448 newkernel.fi_shift_amt = fastboot_shift_amt_pae; 449 newkernel.fi_ptes_per_table = 512; 450 newkernel.fi_lpagesize = (2 << 20); /* 2M */ 451 newkernel.fi_top_level = 2; 452 } 453 454 bzero(kern_bootpath, OBP_MAXPATHLEN); 455 bzero(bootargs, OBP_MAXPATHLEN); 456 457 /* 458 * If mdep is not NULL, it comes in the format of 459 * mountpoint unix args 460 */ 461 if (mdep != NULL) { 462 if (mdep[0] != '-') { 463 /* First get the root argument */ 464 i = 0; 465 while (mdep[i] != '\0' && mdep[i] != ' ') { 466 i++; 467 } 468 469 if (i < 4 || strncmp(&mdep[i-4], "unix", 4) != 0) { 470 /* mount point */ 471 bcopy(mdep, kern_bootpath, i); 472 kern_bootpath[i] = '\0'; 473 bootpath_len = i; 474 475 /* 476 * Get the next argument. It should be unix as 477 * we have validated in in halt.c. 478 */ 479 if (strlen(mdep) > i) { 480 mdep += (i + 1); 481 i = 0; 482 while (mdep[i] != '\0' && 483 mdep[i] != ' ') { 484 i++; 485 } 486 } 487 488 } 489 bcopy(mdep, kern_bootfile, i); 490 kern_bootfile[i] = '\0'; 491 } else { 492 int off = strlen(kern_bootfile); 493 bcopy(kern_bootfile, bootargs, off); 494 bcopy(" ", &bootargs[off++], 1); 495 bcopy(mdep, &bootargs[off], strlen(mdep)); 496 off += strlen(mdep); 497 bootargs[off] = '\0'; 498 mdep = bootargs; 499 } 500 } 501 502 /* 503 * Make sure we get the null character 504 */ 505 bcopy(kern_bootpath, fastboot_filename[FASTBOOT_NAME_UNIX], 506 bootpath_len); 507 bcopy(kern_bootfile, 508 &fastboot_filename[FASTBOOT_NAME_UNIX][bootpath_len], 509 strlen(kern_bootfile) + 1); 510 511 bcopy(kern_bootpath, fastboot_filename[FASTBOOT_NAME_BOOTARCHIVE], 512 bootpath_len); 513 514 if (bcmp(kern_bootfile, FAILSAFE_BOOTFILE, 515 (sizeof (FAILSAFE_BOOTFILE) - 1)) == 0) { 516 is_failsafe = 1; 517 } 518 519 /* 520 * Read in unix and boot_archive 521 */ 522 for (i = 0; i < FASTBOOT_MAX_FILES_MAP; i++) { 523 uint64_t fsize; 524 size_t fsize_roundup, pt_size; 525 int page_index; 526 uintptr_t offset; 527 int pt_entry_count; 528 ddi_dma_attr_t dma_attr = fastboot_dma_attr; 529 530 dprintf("fastboot_filename[%d] = %s\n", 531 i, fastboot_filename[i]); 532 533 if ((file = kobj_open_file(fastboot_filename[i])) == 534 (struct _buf *)-1) { 535 cmn_err(CE_WARN, "Fastboot: Couldn't open %s", 536 fastboot_filename[i]); 537 goto err_out; 538 } 539 540 if (kobj_get_filesize(file, &fsize) != 0) { 541 cmn_err(CE_WARN, 542 "Fastboot: Couldn't get filesize for %s", 543 fastboot_filename[i]); 544 goto err_out; 545 } 546 547 if (i == FASTBOOT_BOOTARCHIVE && is_failsafe) { 548 /* Adjust low memory for failsafe mode */ 549 fastboot_below_1G_dma_attr.dma_attr_addr_lo = 550 dma_attr.dma_attr_addr_lo = 551 P2ROUNDUP_TYPED(fsize, PAGESIZE, uint64_t) + 552 next_pa; 553 } 554 555 if (!fastboot_contig) 556 dma_attr.dma_attr_sgllen = (fsize / PAGESIZE) + 557 (((fsize % PAGESIZE) == 0) ? 0 : 1); 558 559 if ((buf = contig_alloc(fsize, &dma_attr, PAGESIZE, 0)) 560 == NULL) { 561 cmn_err(CE_WARN, fastboot_enomem_msg, fsize, 562 "64G"); 563 goto err_out; 564 } 565 566 va = P2ROUNDUP_TYPED((uintptr_t)buf, PAGESIZE, uintptr_t); 567 568 if (kobj_read_file(file, (char *)va, fsize, 0) < 0) { 569 cmn_err(CE_WARN, "Fastboot: Couldn't read %s", 570 fastboot_filename[i]); 571 goto err_out; 572 } 573 574 fb = &newkernel.fi_files[i]; 575 fb->fb_va = va; 576 fb->fb_size = fsize; 577 fb->fb_sectcnt = 0; 578 579 fsize_roundup = P2ROUNDUP_TYPED(fb->fb_size, PAGESIZE, size_t); 580 581 /* 582 * Allocate one extra page table entry for terminating 583 * the list. 584 */ 585 pt_entry_count = (fsize_roundup >> PAGESHIFT) + 1; 586 pt_size = P2ROUNDUP(pt_entry_count * 8, PAGESIZE); 587 588 if ((fb->fb_pte_list_va = 589 (x86pte_t *)contig_alloc(pt_size, 590 &fastboot_below_1G_dma_attr, PAGESIZE, 0)) == NULL) { 591 cmn_err(CE_WARN, fastboot_enomem_msg, 592 (uint64_t)pt_size, "1G"); 593 goto err_out; 594 } 595 596 bzero((void *)(fb->fb_pte_list_va), pt_size); 597 598 fb->fb_pte_list_pa = mmu_ptob((uint64_t)hat_getpfnum(kas.a_hat, 599 (caddr_t)fb->fb_pte_list_va)); 600 601 for (page_index = 0, offset = 0; offset < fb->fb_size; 602 offset += PAGESIZE) { 603 uint64_t paddr; 604 605 paddr = mmu_ptob((uint64_t)hat_getpfnum(kas.a_hat, 606 (caddr_t)fb->fb_va + offset)); 607 608 ASSERT(paddr >= fastboot_dma_attr.dma_attr_addr_lo); 609 610 /* 611 * Include the pte_bits so we don't have to make 612 * it in assembly. 613 */ 614 fb->fb_pte_list_va[page_index++] = (x86pte_t) 615 (paddr | pte_bits); 616 } 617 618 fb->fb_pte_list_va[page_index] = FASTBOOT_TERMINATE; 619 620 if (i == FASTBOOT_UNIX) { 621 ehdr = (Ehdr *)va; 622 623 /* 624 * Sanity checks: 625 */ 626 for (j = 0; j < SELFMAG; j++) { 627 if (ehdr->e_ident[j] != ELFMAG[j]) { 628 cmn_err(CE_WARN, "Fastboot: Bad ELF " 629 "signature"); 630 goto err_out; 631 } 632 } 633 634 if (ehdr->e_ident[EI_CLASS] == ELFCLASS32 && 635 ehdr->e_ident[EI_DATA] == ELFDATA2LSB && 636 ehdr->e_machine == EM_386) { 637 638 if (fastboot_elf32_find_loadables((void *)va, 639 fsize, &fb->fb_sections[0], 640 &fb->fb_sectcnt, &dboot_start_offset) < 0) { 641 cmn_err(CE_WARN, "Fastboot: ELF32 " 642 "program section failure"); 643 goto err_out; 644 } 645 646 if (fb->fb_sectcnt == 0) { 647 cmn_err(CE_WARN, "Fastboot: No ELF32 " 648 "program sections found"); 649 goto err_out; 650 } 651 652 if (is_failsafe) { 653 /* Failsafe boot_archive */ 654 bcopy(BOOTARCHIVE_FAILSAFE, 655 &fastboot_filename 656 [FASTBOOT_NAME_BOOTARCHIVE] 657 [bootpath_len], 658 sizeof (BOOTARCHIVE_FAILSAFE)); 659 } else { 660 bcopy(BOOTARCHIVE32, 661 &fastboot_filename 662 [FASTBOOT_NAME_BOOTARCHIVE] 663 [bootpath_len], 664 sizeof (BOOTARCHIVE32)); 665 } 666 667 } else if (ehdr->e_ident[EI_CLASS] == ELFCLASS64 && 668 ehdr->e_ident[EI_DATA] == ELFDATA2LSB && 669 ehdr->e_machine == EM_AMD64) { 670 671 if (fastboot_elf64_find_dboot_load_offset( 672 (void *)va, fsize, &dboot_start_offset) 673 != 0) { 674 cmn_err(CE_WARN, "Fastboot: Couldn't " 675 "find ELF64 dboot entry offset"); 676 goto err_out; 677 } 678 679 if ((x86_feature & X86_64) == 0 || 680 newkernel.fi_has_pae == 0) { 681 cmn_err(CE_WARN, "Fastboot: Cannot " 682 "reboot to %s: " 683 "not a 64-bit capable system", 684 kern_bootfile); 685 goto err_out; 686 } 687 688 bcopy(BOOTARCHIVE64, 689 &fastboot_filename 690 [FASTBOOT_NAME_BOOTARCHIVE][bootpath_len], 691 sizeof (BOOTARCHIVE64)); 692 } else { 693 cmn_err(CE_WARN, "Fastboot: Unknown ELF type"); 694 goto err_out; 695 } 696 697 fb->fb_dest_pa = DBOOT_ENTRY_ADDRESS - 698 dboot_start_offset; 699 700 fb->fb_next_pa = DBOOT_ENTRY_ADDRESS + fsize_roundup; 701 } else { 702 fb->fb_dest_pa = newkernel.fi_files[i - 1].fb_next_pa; 703 fb->fb_next_pa = fb->fb_dest_pa + fsize_roundup; 704 } 705 706 next_pa = fb->fb_next_pa; 707 708 kobj_close_file(file); 709 710 /* 711 * Set fb_va to fake_va 712 */ 713 fb->fb_va = fake_va; 714 } 715 716 717 /* 718 * Add the function that will switch us to 32-bit protected mode 719 */ 720 fb = &newkernel.fi_files[FASTBOOT_SWTCH]; 721 fb->fb_va = fb->fb_dest_pa = FASTBOOT_SWTCH_PA; 722 fb->fb_size = PAGESIZE; 723 724 /* 725 * Map in FASTBOOT_SWTCH_PA 726 */ 727 hat_devload(kas.a_hat, (caddr_t)fb->fb_va, MMU_PAGESIZE, 728 mmu_btop(fb->fb_dest_pa), 729 PROT_READ | PROT_WRITE | PROT_EXEC, HAT_LOAD_NOCONSIST); 730 731 bcopy((void *)fb_swtch_image, (void *)fb->fb_va, fb->fb_size); 732 733 /* 734 * Build the new multiboot_info structure 735 */ 736 if (fastboot_build_mbi(mdep, &newkernel) != 0) { 737 goto err_out; 738 } 739 740 /* 741 * Build page table for low 1G physical memory. Use big pages. 742 * Allocate 4 pages for the page tables. 743 * 1 page for Page-Directory-Pointer Table 744 * 2 page for Page Directory 745 * 1 page for Page Table. 746 * The page table entry will be rewritten to map the physical 747 * address as we do the copying. 748 */ 749 if (newkernel.fi_has_pae) { 750 size_t size = MMU_PAGESIZE * 4; 751 752 if ((newkernel.fi_pagetable_va = (uintptr_t) 753 contig_alloc(size, &fastboot_below_1G_dma_attr, 754 PAGESIZE, 0)) == NULL) { 755 cmn_err(CE_WARN, fastboot_enomem_msg, 756 (uint64_t)size, "1G"); 757 goto err_out; 758 } 759 760 bzero((void *)(newkernel.fi_pagetable_va), size); 761 762 newkernel.fi_pagetable_pa = 763 mmu_ptob((uint64_t)hat_getpfnum(kas.a_hat, 764 (caddr_t)newkernel.fi_pagetable_va)); 765 766 newkernel.fi_last_table_pa = newkernel.fi_pagetable_pa + 767 MMU_PAGESIZE * 3; 768 769 newkernel.fi_next_table_va = newkernel.fi_pagetable_va + 770 MMU_PAGESIZE; 771 newkernel.fi_next_table_pa = newkernel.fi_pagetable_pa + 772 MMU_PAGESIZE; 773 774 fastboot_build_pagetables(&newkernel); 775 } 776 777 778 /* Mark it as valid */ 779 newkernel.fi_valid = 1; 780 newkernel.fi_magic = FASTBOOT_MAGIC; 781 782 return; 783 784 err_out: 785 /* XXX Do we need to free up the memory we allocated? */ 786 787 newkernel.fi_valid = 0; 788 } 789 790 791 void 792 fast_reboot() 793 { 794 void (*fastboot_func)(fastboot_info_t *); 795 796 fastboot_func = (void (*)())(newkernel.fi_files[FASTBOOT_SWTCH].fb_va); 797 (*fastboot_func)(&newkernel); 798 } 799