10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*5648Ssetje * Common Development and Distribution License (the "License"). 6*5648Ssetje * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*5648Ssetje * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate /* 290Sstevel@tonic-gate * Definitions of interfaces that provide services from the secondary 300Sstevel@tonic-gate * boot program to its clients (primarily Solaris, krtld, kmdb and their 310Sstevel@tonic-gate * successors.) This interface replaces the bootops (BOP) implementation 320Sstevel@tonic-gate * as the interface to be called by boot clients. 330Sstevel@tonic-gate * 340Sstevel@tonic-gate */ 350Sstevel@tonic-gate 360Sstevel@tonic-gate #include <sys/types.h> 37*5648Ssetje #include <sys/systm.h> 380Sstevel@tonic-gate #include <sys/reboot.h> 390Sstevel@tonic-gate #include <sys/param.h> 400Sstevel@tonic-gate #include <sys/varargs.h> 410Sstevel@tonic-gate #include <sys/obpdefs.h> 42*5648Ssetje #include <sys/promimpl.h> 43*5648Ssetje #include <sys/prom_plat.h> 440Sstevel@tonic-gate #include <sys/bootconf.h> 450Sstevel@tonic-gate #include <sys/bootstat.h> 46*5648Ssetje #include <sys/kobj_impl.h> 470Sstevel@tonic-gate 48*5648Ssetje struct bootops *bootops; 49*5648Ssetje struct bootops kbootops; 50*5648Ssetje 51*5648Ssetje pnode_t chosennode; 52*5648Ssetje 53*5648Ssetje #define FAKE_ROOT (pnode_t)1 54*5648Ssetje 55*5648Ssetje struct fakeprop { 56*5648Ssetje char *bootname; 57*5648Ssetje pnode_t promnode; 58*5648Ssetje char *promname; 59*5648Ssetje } fakeprops[] = { 60*5648Ssetje { "mfg-name", FAKE_ROOT, "name" }, 61*5648Ssetje { NULL, 0, NULL } 62*5648Ssetje }; 63*5648Ssetje 64*5648Ssetje static void 65*5648Ssetje fakelook_init(void) 660Sstevel@tonic-gate { 67*5648Ssetje struct fakeprop *fpp = fakeprops; 68*5648Ssetje 69*5648Ssetje while (fpp->bootname != NULL) { 70*5648Ssetje switch (fpp->promnode) { 71*5648Ssetje case FAKE_ROOT: 72*5648Ssetje fpp->promnode = prom_rootnode(); 73*5648Ssetje break; 74*5648Ssetje } 75*5648Ssetje fpp++; 76*5648Ssetje } 770Sstevel@tonic-gate } 780Sstevel@tonic-gate 79*5648Ssetje static struct fakeprop * 80*5648Ssetje fakelook(const char *prop) 81*5648Ssetje { 82*5648Ssetje struct fakeprop *fpp = fakeprops; 83*5648Ssetje 84*5648Ssetje while (fpp->bootname != NULL) { 85*5648Ssetje if (strcmp(prop, fpp->bootname) == 0) 86*5648Ssetje return (fpp); 87*5648Ssetje fpp++; 88*5648Ssetje } 89*5648Ssetje return (NULL); 90*5648Ssetje } 91*5648Ssetje 92*5648Ssetje ihandle_t bfs_ih = OBP_BADNODE; 93*5648Ssetje ihandle_t afs_ih = OBP_BADNODE; 94*5648Ssetje 95*5648Ssetje void 96*5648Ssetje bop_init(void) 97*5648Ssetje { 98*5648Ssetje chosennode = prom_chosennode(); 99*5648Ssetje 100*5648Ssetje fakelook_init(); 101*5648Ssetje 102*5648Ssetje /* fake bootops - it needs to point to non-NULL */ 103*5648Ssetje bootops = &kbootops; 104*5648Ssetje } 105*5648Ssetje 106*5648Ssetje #define MAXPROMFD 16 107*5648Ssetje 108*5648Ssetje static ihandle_t prom_ihs[MAXPROMFD]; 109*5648Ssetje int filter_etc = 1; 1100Sstevel@tonic-gate 1110Sstevel@tonic-gate /* 1120Sstevel@tonic-gate * Implementation of the "open" boot service. 1130Sstevel@tonic-gate */ 114*5648Ssetje /*ARGSUSED*/ 1150Sstevel@tonic-gate int 116*5648Ssetje bop_open(const char *name, int flags) 1170Sstevel@tonic-gate { 118*5648Ssetje int fd = -1, layered; 119*5648Ssetje ihandle_t ih; 120*5648Ssetje 121*5648Ssetje /* 122*5648Ssetje * Only look underneath archive for /etc files 123*5648Ssetje */ 124*5648Ssetje layered = filter_etc ? 125*5648Ssetje strncmp(name, "/etc", sizeof ("/etc") - 1) == 0 : 1; 1260Sstevel@tonic-gate 127*5648Ssetje if (afs_ih != OBP_BADNODE) { 128*5648Ssetje ih = afs_ih; 129*5648Ssetje fd = prom_fopen(ih, (char *)name); 130*5648Ssetje if (fd == -1 && !layered) 131*5648Ssetje return (BOOT_SVC_FAIL); 132*5648Ssetje } 133*5648Ssetje if (fd == -1 && bfs_ih != OBP_BADNODE) { 134*5648Ssetje ih = bfs_ih; 135*5648Ssetje fd = prom_fopen(ih, (char *)name); 136*5648Ssetje } 137*5648Ssetje if (fd == -1) 138*5648Ssetje return (BOOT_SVC_FAIL); 139*5648Ssetje ASSERT(fd < MAXPROMFD); 140*5648Ssetje ASSERT(prom_ihs[fd] == 0); 141*5648Ssetje prom_ihs[fd] = ih; 142*5648Ssetje return (fd); 143*5648Ssetje } 1440Sstevel@tonic-gate 145*5648Ssetje static void 146*5648Ssetje spinner(void) 147*5648Ssetje { 148*5648Ssetje static int pos; 149*5648Ssetje static char ind[] = "|/-\\"; /* that's entertainment? */ 150*5648Ssetje static int blks_read; 151*5648Ssetje 152*5648Ssetje if ((blks_read++ & 0x3) == 0) 153*5648Ssetje prom_printf("%c\b", ind[pos++ & 3]); 1540Sstevel@tonic-gate } 1550Sstevel@tonic-gate 1560Sstevel@tonic-gate /* 1570Sstevel@tonic-gate * Implementation of the "read" boot service. 1580Sstevel@tonic-gate */ 1590Sstevel@tonic-gate int 160*5648Ssetje bop_read(int fd, caddr_t buf, size_t size) 1610Sstevel@tonic-gate { 162*5648Ssetje ASSERT(prom_ihs[fd] != 0); 163*5648Ssetje spinner(); 164*5648Ssetje return (prom_fread(prom_ihs[fd], fd, buf, size)); 1650Sstevel@tonic-gate } 1660Sstevel@tonic-gate 1670Sstevel@tonic-gate /* 1680Sstevel@tonic-gate * Implementation of the "seek" boot service. 1690Sstevel@tonic-gate */ 1700Sstevel@tonic-gate int 171*5648Ssetje bop_seek(int fd, off_t off) 1720Sstevel@tonic-gate { 173*5648Ssetje ASSERT(prom_ihs[fd] != 0); 174*5648Ssetje return (prom_fseek(prom_ihs[fd], fd, off)); 1750Sstevel@tonic-gate } 1760Sstevel@tonic-gate 1770Sstevel@tonic-gate /* 1780Sstevel@tonic-gate * Implementation of the "close" boot service. 1790Sstevel@tonic-gate */ 1800Sstevel@tonic-gate int 181*5648Ssetje bop_close(int fd) 1820Sstevel@tonic-gate { 183*5648Ssetje ASSERT(prom_ihs[fd] != 0); 184*5648Ssetje prom_fclose(prom_ihs[fd], fd); 185*5648Ssetje prom_ihs[fd] = 0; 186*5648Ssetje return (0); 187*5648Ssetje } 188*5648Ssetje 189*5648Ssetje /* 190*5648Ssetje * Simple temp memory allocator 191*5648Ssetje * 192*5648Ssetje * >PAGESIZE allocations are gotten directly from prom at bighand 193*5648Ssetje * smaller ones are satisfied from littlehand, which does a 194*5648Ssetje * 1 page bighand allocation when it runs out of memory 195*5648Ssetje */ 196*5648Ssetje static caddr_t bighand = (caddr_t)BOOTTMPBASE; 197*5648Ssetje static caddr_t littlehand = (caddr_t)BOOTTMPBASE; 198*5648Ssetje 199*5648Ssetje #define NTMPALLOC 128 200*5648Ssetje 201*5648Ssetje static caddr_t temp_base[NTMPALLOC]; 202*5648Ssetje static size_t temp_size[NTMPALLOC]; 203*5648Ssetje static int temp_indx; 204*5648Ssetje 205*5648Ssetje #if defined(C_OBP) 206*5648Ssetje void cobp_free_mem(caddr_t, size_t); 207*5648Ssetje #endif /* C_OBP */ 208*5648Ssetje 209*5648Ssetje 210*5648Ssetje /* 211*5648Ssetje * temporary memory storage until bop_tmp_freeall is called 212*5648Ssetje * (after the kernel heap is initialized) 213*5648Ssetje */ 214*5648Ssetje caddr_t 215*5648Ssetje bop_temp_alloc(size_t size, int align) 216*5648Ssetje { 217*5648Ssetje caddr_t ret; 2180Sstevel@tonic-gate 219*5648Ssetje /* 220*5648Ssetje * OBP allocs 10MB to boot, which is where virthint = 0 221*5648Ssetje * memory was allocated from. Without boot, we allocate 222*5648Ssetje * from BOOTTMPBASE and free when we're ready to take 223*5648Ssetje * the machine from OBP 224*5648Ssetje */ 225*5648Ssetje if (size < PAGESIZE) { 226*5648Ssetje size_t left = 227*5648Ssetje ALIGN(littlehand, PAGESIZE) - (uintptr_t)littlehand; 228*5648Ssetje 229*5648Ssetje size = roundup(size, MAX(align, 8)); 230*5648Ssetje if (size <= left) { 231*5648Ssetje ret = littlehand; 232*5648Ssetje littlehand += size; 233*5648Ssetje return (ret); 234*5648Ssetje } 235*5648Ssetje littlehand = bighand + size; 236*5648Ssetje } 237*5648Ssetje size = roundup(size, PAGESIZE); 238*5648Ssetje ret = prom_alloc(bighand, size, align); 239*5648Ssetje if (ret == NULL) 240*5648Ssetje prom_panic("boot temp overflow"); 241*5648Ssetje bighand += size; 2420Sstevel@tonic-gate 243*5648Ssetje /* log it for bop_fini() */ 244*5648Ssetje temp_base[temp_indx] = ret; 245*5648Ssetje temp_size[temp_indx] = size; 246*5648Ssetje if (++temp_indx == NTMPALLOC) 247*5648Ssetje prom_panic("out of bop temp space"); 248*5648Ssetje 249*5648Ssetje return (ret); 2500Sstevel@tonic-gate } 2510Sstevel@tonic-gate 252*5648Ssetje void 253*5648Ssetje bop_temp_freeall(void) 254*5648Ssetje { 255*5648Ssetje int i; 256*5648Ssetje 257*5648Ssetje /* 258*5648Ssetje * We have to call prom_free() with the same args 259*5648Ssetje * as we used in prom_alloc() 260*5648Ssetje */ 261*5648Ssetje for (i = 0; i < NTMPALLOC; i++) { 262*5648Ssetje if (temp_base[i] == NULL) 263*5648Ssetje break; 264*5648Ssetje #if !defined(C_OBP) 265*5648Ssetje prom_free(temp_base[i], temp_size[i]); 266*5648Ssetje #else /* !C_OBP */ 267*5648Ssetje cobp_free_mem(temp_base[i], temp_size[i]); 268*5648Ssetje #endif /* !C_OBP */ 269*5648Ssetje } 270*5648Ssetje } 271*5648Ssetje 272*5648Ssetje 2730Sstevel@tonic-gate /* 2740Sstevel@tonic-gate * Implementation of the "alloc" boot service. 2750Sstevel@tonic-gate */ 2760Sstevel@tonic-gate caddr_t 277*5648Ssetje bop_alloc(caddr_t virthint, size_t size, int align) 2780Sstevel@tonic-gate { 279*5648Ssetje if (virthint == NULL) 280*5648Ssetje return (bop_temp_alloc(size, align)); 281*5648Ssetje return (prom_alloc(virthint, size, align)); 2820Sstevel@tonic-gate } 2830Sstevel@tonic-gate 2840Sstevel@tonic-gate /* 2850Sstevel@tonic-gate * Implementation of the "alloc_virt" boot service 2860Sstevel@tonic-gate */ 2870Sstevel@tonic-gate caddr_t 288*5648Ssetje bop_alloc_virt(caddr_t virt, size_t size) 2890Sstevel@tonic-gate { 290*5648Ssetje return (prom_claim_virt(size, virt)); 2910Sstevel@tonic-gate } 2920Sstevel@tonic-gate 2930Sstevel@tonic-gate /* 2940Sstevel@tonic-gate * Implementation of the "free" boot service. 2950Sstevel@tonic-gate */ 2960Sstevel@tonic-gate /*ARGSUSED*/ 2970Sstevel@tonic-gate void 298*5648Ssetje bop_free(caddr_t virt, size_t size) 2990Sstevel@tonic-gate { 300*5648Ssetje prom_free(virt, size); 3010Sstevel@tonic-gate } 3020Sstevel@tonic-gate 3030Sstevel@tonic-gate 3040Sstevel@tonic-gate 3050Sstevel@tonic-gate /* 3060Sstevel@tonic-gate * Implementation of the "getproplen" boot service. 3070Sstevel@tonic-gate */ 3080Sstevel@tonic-gate /*ARGSUSED*/ 3090Sstevel@tonic-gate int 310*5648Ssetje bop_getproplen(const char *name) 3110Sstevel@tonic-gate { 312*5648Ssetje struct fakeprop *fpp; 313*5648Ssetje pnode_t node; 314*5648Ssetje char *prop; 3150Sstevel@tonic-gate 316*5648Ssetje fpp = fakelook(name); 317*5648Ssetje if (fpp != NULL) { 318*5648Ssetje node = fpp->promnode; 319*5648Ssetje prop = fpp->promname; 320*5648Ssetje } else { 321*5648Ssetje node = chosennode; 322*5648Ssetje prop = (char *)name; 323*5648Ssetje } 324*5648Ssetje return (prom_getproplen(node, prop)); 3250Sstevel@tonic-gate } 3260Sstevel@tonic-gate 3270Sstevel@tonic-gate /* 3280Sstevel@tonic-gate * Implementation of the "getprop" boot service. 3290Sstevel@tonic-gate */ 3300Sstevel@tonic-gate /*ARGSUSED*/ 3310Sstevel@tonic-gate int 332*5648Ssetje bop_getprop(const char *name, void *value) 3330Sstevel@tonic-gate { 334*5648Ssetje struct fakeprop *fpp; 335*5648Ssetje pnode_t node; 336*5648Ssetje char *prop; 3370Sstevel@tonic-gate 338*5648Ssetje fpp = fakelook(name); 339*5648Ssetje if (fpp != NULL) { 340*5648Ssetje node = fpp->promnode; 341*5648Ssetje prop = fpp->promname; 342*5648Ssetje } else { 343*5648Ssetje node = chosennode; 344*5648Ssetje prop = (char *)name; 345*5648Ssetje } 346*5648Ssetje return (prom_getprop(node, prop, value)); 3470Sstevel@tonic-gate } 3480Sstevel@tonic-gate 3490Sstevel@tonic-gate /* 350*5648Ssetje * Implementation of the "print" boot service. 3510Sstevel@tonic-gate */ 3520Sstevel@tonic-gate /*ARGSUSED*/ 3530Sstevel@tonic-gate void 354*5648Ssetje bop_printf(void *ops, const char *fmt, ...) 3550Sstevel@tonic-gate { 356*5648Ssetje va_list adx; 3570Sstevel@tonic-gate 358*5648Ssetje va_start(adx, fmt); 359*5648Ssetje prom_vprintf(fmt, adx); 360*5648Ssetje va_end(adx); 3610Sstevel@tonic-gate } 3620Sstevel@tonic-gate 3630Sstevel@tonic-gate /* 364*5648Ssetje * Special routine for kmdb 3650Sstevel@tonic-gate */ 3660Sstevel@tonic-gate void 367*5648Ssetje bop_putsarg(const char *fmt, char *arg) 3680Sstevel@tonic-gate { 369*5648Ssetje prom_printf(fmt, arg); 370*5648Ssetje } 3710Sstevel@tonic-gate 372*5648Ssetje /* 373*5648Ssetje * panic for krtld only 374*5648Ssetje */ 375*5648Ssetje void 376*5648Ssetje bop_panic(const char *s) 377*5648Ssetje { 378*5648Ssetje prom_panic((char *)s); 3790Sstevel@tonic-gate } 3800Sstevel@tonic-gate 3810Sstevel@tonic-gate /* 3820Sstevel@tonic-gate * Implementation of the "mount" boot service. 3830Sstevel@tonic-gate * 3840Sstevel@tonic-gate */ 3850Sstevel@tonic-gate /*ARGSUSED*/ 3860Sstevel@tonic-gate int 387*5648Ssetje bop_mountroot(void) 3880Sstevel@tonic-gate { 389*5648Ssetje (void) prom_getprop(chosennode, "bootfs", (caddr_t)&bfs_ih); 390*5648Ssetje (void) prom_getprop(chosennode, "archfs", (caddr_t)&afs_ih); 391*5648Ssetje return ((bfs_ih == -1 && afs_ih == -1) ? BOOT_SVC_FAIL : BOOT_SVC_OK); 3920Sstevel@tonic-gate } 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate /* 3950Sstevel@tonic-gate * Implementation of the "unmountroot" boot service. 3960Sstevel@tonic-gate */ 3970Sstevel@tonic-gate /*ARGSUSED*/ 3980Sstevel@tonic-gate int 399*5648Ssetje bop_unmountroot(void) 4000Sstevel@tonic-gate { 4010Sstevel@tonic-gate 402*5648Ssetje if (bfs_ih != OBP_BADNODE) { 403*5648Ssetje (void) prom_close(bfs_ih); 404*5648Ssetje bfs_ih = OBP_BADNODE; 405*5648Ssetje } 406*5648Ssetje if (afs_ih != OBP_BADNODE) { 407*5648Ssetje (void) prom_close(afs_ih); 408*5648Ssetje afs_ih = OBP_BADNODE; 409*5648Ssetje } 410*5648Ssetje return (BOOT_SVC_OK); 4110Sstevel@tonic-gate } 4120Sstevel@tonic-gate 4130Sstevel@tonic-gate /* 4140Sstevel@tonic-gate * Implementation of the "fstat" boot service. 4150Sstevel@tonic-gate */ 4160Sstevel@tonic-gate int 417*5648Ssetje bop_fstat(int fd, struct bootstat *st) 418*5648Ssetje { 419*5648Ssetje ASSERT(prom_ihs[fd] != 0); 420*5648Ssetje return (prom_fsize(prom_ihs[fd], fd, (size_t *)&st->st_size)); 421*5648Ssetje } 422*5648Ssetje 423*5648Ssetje int 424*5648Ssetje boot_compinfo(int fd, struct compinfo *cb) 425*5648Ssetje { 426*5648Ssetje ASSERT(prom_ihs[fd] != 0); 427*5648Ssetje return (prom_compinfo(prom_ihs[fd], fd, 428*5648Ssetje &cb->iscmp, &cb->fsize, &cb->blksize)); 429*5648Ssetje } 430*5648Ssetje 431*5648Ssetje void 432*5648Ssetje bop_free_archive(void) 4330Sstevel@tonic-gate { 434*5648Ssetje char archive[OBP_MAXPATHLEN]; 435*5648Ssetje pnode_t arph; 436*5648Ssetje uint32_t arbase, arsize, alloc_size; 437*5648Ssetje 438*5648Ssetje /* 439*5648Ssetje * If the ramdisk will eventually be root, or we weren't 440*5648Ssetje * booted via the archive, then nothing to do here 441*5648Ssetje */ 442*5648Ssetje if (root_is_ramdisk == B_TRUE || 443*5648Ssetje prom_getprop(chosennode, "bootarchive", archive) == -1) 444*5648Ssetje return; 445*5648Ssetje arph = prom_finddevice(archive); 446*5648Ssetje if (arph == -1 || 447*5648Ssetje prom_getprop(arph, OBP_ALLOCSIZE, (caddr_t)&alloc_size) == -1 || 448*5648Ssetje prom_getprop(arph, OBP_SIZE, (caddr_t)&arsize) == -1 || 449*5648Ssetje prom_getprop(arph, OBP_ADDRESS, (caddr_t)&arbase) == -1) 450*5648Ssetje prom_panic("can't free boot archive"); 451*5648Ssetje 452*5648Ssetje #if !defined(C_OBP) 453*5648Ssetje if (alloc_size == 0) 454*5648Ssetje prom_free((caddr_t)(uintptr_t)arbase, arsize); 455*5648Ssetje else { 456*5648Ssetje uint32_t arend = arbase + arsize; 4570Sstevel@tonic-gate 458*5648Ssetje while (arbase < arend) { 459*5648Ssetje prom_free((caddr_t)(uintptr_t)arbase, 460*5648Ssetje MIN(alloc_size, arend - arbase)); 461*5648Ssetje arbase += alloc_size; 462*5648Ssetje } 463*5648Ssetje } 464*5648Ssetje #else /* !C_OBP */ 465*5648Ssetje cobp_free_mem((caddr_t)(uintptr_t)arbase, arsize); 466*5648Ssetje #endif /* !C_OBP */ 467*5648Ssetje } 468*5648Ssetje 469*5648Ssetje #if defined(C_OBP) 470*5648Ssetje /* 471*5648Ssetje * Blech. The C proms have a bug when freeing areas that cross 472*5648Ssetje * page sizes, so we have to break up the free into sections 473*5648Ssetje * bounded by the various pagesizes. 474*5648Ssetje */ 475*5648Ssetje void 476*5648Ssetje cobp_free_mem(caddr_t base, size_t size) 477*5648Ssetje { 478*5648Ssetje int i; 479*5648Ssetje size_t len, pgsz; 480*5648Ssetje 481*5648Ssetje /* 482*5648Ssetje * Large pages only used when size > 512k 483*5648Ssetje */ 484*5648Ssetje if (size < MMU_PAGESIZE512K || 485*5648Ssetje ((uintptr_t)base & MMU_PAGEOFFSET512K) != 0) { 486*5648Ssetje prom_free(base, size); 487*5648Ssetje return; 488*5648Ssetje } 489*5648Ssetje for (i = 3; i >= 0; i--) { 490*5648Ssetje pgsz = page_get_pagesize(i); 491*5648Ssetje if (size < pgsz) 492*5648Ssetje continue; 493*5648Ssetje len = size & ~(pgsz - 1); 494*5648Ssetje prom_free(base, len); 495*5648Ssetje base += len; 496*5648Ssetje size -= len; 497*5648Ssetje } 498*5648Ssetje } 499*5648Ssetje #endif /* C_OBP */ 500*5648Ssetje 501*5648Ssetje 502*5648Ssetje /* 503*5648Ssetje * Implementation of the "enter_mon" boot service. 504*5648Ssetje */ 505*5648Ssetje void 506*5648Ssetje bop_enter_mon(void) 507*5648Ssetje { 508*5648Ssetje prom_enter_mon(); 5090Sstevel@tonic-gate } 5100Sstevel@tonic-gate 5110Sstevel@tonic-gate /* 512*5648Ssetje * free elf info allocated by booter 5130Sstevel@tonic-gate */ 5140Sstevel@tonic-gate void 515*5648Ssetje bop_free_elf(void) 5160Sstevel@tonic-gate { 517*5648Ssetje uint32_t eadr; 518*5648Ssetje uint32_t esize; 519*5648Ssetje extern Addr dynseg; 520*5648Ssetje extern size_t dynsize; 521*5648Ssetje 522*5648Ssetje if (bop_getprop("elfheader-address", (caddr_t)&eadr) == -1 || 523*5648Ssetje bop_getprop("elfheader-length", (caddr_t)&esize) == -1) 524*5648Ssetje prom_panic("missing elfheader"); 525*5648Ssetje prom_free((caddr_t)(uintptr_t)eadr, roundup(esize, PAGESIZE)); 526*5648Ssetje 527*5648Ssetje prom_free((caddr_t)(uintptr_t)dynseg, roundup(dynsize, PAGESIZE)); 528*5648Ssetje } 529*5648Ssetje 5300Sstevel@tonic-gate 531*5648Ssetje /* Simple message to indicate that the bootops pointer has been zeroed */ 532*5648Ssetje #ifdef DEBUG 533*5648Ssetje int bootops_gone_on = 0; 534*5648Ssetje #define BOOTOPS_GONE() \ 535*5648Ssetje if (bootops_gone_on) \ 536*5648Ssetje prom_printf("The bootops vec is zeroed now!\n"); 537*5648Ssetje #else 538*5648Ssetje #define BOOTOPS_GONE() 539*5648Ssetje #endif /* DEBUG */ 540*5648Ssetje 541*5648Ssetje void 542*5648Ssetje bop_fini(void) 543*5648Ssetje { 544*5648Ssetje bop_free_archive(); 545*5648Ssetje (void) bop_unmountroot(); 546*5648Ssetje bop_free_elf(); 547*5648Ssetje bop_temp_freeall(); 548*5648Ssetje 549*5648Ssetje bootops = (struct bootops *)NULL; 550*5648Ssetje BOOTOPS_GONE(); 5510Sstevel@tonic-gate } 552