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