17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*986fd29aSsetje * Common Development and Distribution License (the "License"). 6*986fd29aSsetje * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*986fd29aSsetje * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate /* 297c478bd9Sstevel@tonic-gate * Definitions of interfaces that provide services from the secondary 307c478bd9Sstevel@tonic-gate * boot program to its clients (primarily Solaris, krtld, kmdb and their 317c478bd9Sstevel@tonic-gate * successors.) This interface replaces the bootops (BOP) implementation 327c478bd9Sstevel@tonic-gate * as the interface to be called by boot clients. 337c478bd9Sstevel@tonic-gate * 347c478bd9Sstevel@tonic-gate */ 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #include <sys/types.h> 37*986fd29aSsetje #include <sys/systm.h> 387c478bd9Sstevel@tonic-gate #include <sys/reboot.h> 397c478bd9Sstevel@tonic-gate #include <sys/param.h> 407c478bd9Sstevel@tonic-gate #include <sys/varargs.h> 417c478bd9Sstevel@tonic-gate #include <sys/obpdefs.h> 42*986fd29aSsetje #include <sys/promimpl.h> 43*986fd29aSsetje #include <sys/prom_plat.h> 447c478bd9Sstevel@tonic-gate #include <sys/bootconf.h> 457c478bd9Sstevel@tonic-gate #include <sys/bootstat.h> 46*986fd29aSsetje #include <sys/kobj_impl.h> 477c478bd9Sstevel@tonic-gate 48*986fd29aSsetje struct bootops *bootops; 49*986fd29aSsetje struct bootops kbootops; 50*986fd29aSsetje 51*986fd29aSsetje pnode_t chosennode; 52*986fd29aSsetje 53*986fd29aSsetje #define FAKE_ROOT (pnode_t)1 54*986fd29aSsetje 55*986fd29aSsetje struct fakeprop { 56*986fd29aSsetje char *bootname; 57*986fd29aSsetje pnode_t promnode; 58*986fd29aSsetje char *promname; 59*986fd29aSsetje } fakeprops[] = { 60*986fd29aSsetje { "mfg-name", FAKE_ROOT, "name" }, 61*986fd29aSsetje { NULL, 0, NULL } 62*986fd29aSsetje }; 63*986fd29aSsetje 64*986fd29aSsetje static void 65*986fd29aSsetje fakelook_init(void) 667c478bd9Sstevel@tonic-gate { 67*986fd29aSsetje struct fakeprop *fpp = fakeprops; 68*986fd29aSsetje 69*986fd29aSsetje while (fpp->bootname != NULL) { 70*986fd29aSsetje switch (fpp->promnode) { 71*986fd29aSsetje case FAKE_ROOT: 72*986fd29aSsetje fpp->promnode = prom_rootnode(); 73*986fd29aSsetje break; 74*986fd29aSsetje } 75*986fd29aSsetje fpp++; 76*986fd29aSsetje } 777c478bd9Sstevel@tonic-gate } 787c478bd9Sstevel@tonic-gate 79*986fd29aSsetje static struct fakeprop * 80*986fd29aSsetje fakelook(const char *prop) 81*986fd29aSsetje { 82*986fd29aSsetje struct fakeprop *fpp = fakeprops; 83*986fd29aSsetje 84*986fd29aSsetje while (fpp->bootname != NULL) { 85*986fd29aSsetje if (strcmp(prop, fpp->bootname) == 0) 86*986fd29aSsetje return (fpp); 87*986fd29aSsetje fpp++; 88*986fd29aSsetje } 89*986fd29aSsetje return (NULL); 90*986fd29aSsetje } 91*986fd29aSsetje 92*986fd29aSsetje ihandle_t bfs_ih = OBP_BADNODE; 93*986fd29aSsetje ihandle_t afs_ih = OBP_BADNODE; 94*986fd29aSsetje 95*986fd29aSsetje void 96*986fd29aSsetje bop_init(void) 97*986fd29aSsetje { 98*986fd29aSsetje chosennode = prom_chosennode(); 99*986fd29aSsetje 100*986fd29aSsetje fakelook_init(); 101*986fd29aSsetje 102*986fd29aSsetje /* fake bootops - it needs to point to non-NULL */ 103*986fd29aSsetje bootops = &kbootops; 104*986fd29aSsetje } 105*986fd29aSsetje 106*986fd29aSsetje #define MAXPROMFD 16 107*986fd29aSsetje 108*986fd29aSsetje static ihandle_t prom_ihs[MAXPROMFD]; 109*986fd29aSsetje int filter_etc = 1; 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate /* 1127c478bd9Sstevel@tonic-gate * Implementation of the "open" boot service. 1137c478bd9Sstevel@tonic-gate */ 114*986fd29aSsetje /*ARGSUSED*/ 1157c478bd9Sstevel@tonic-gate int 116*986fd29aSsetje bop_open(const char *name, int flags) 1177c478bd9Sstevel@tonic-gate { 118*986fd29aSsetje int fd = -1, layered; 119*986fd29aSsetje ihandle_t ih; 1207c478bd9Sstevel@tonic-gate 121*986fd29aSsetje /* 122*986fd29aSsetje * Only look underneath archive for /etc files 123*986fd29aSsetje */ 124*986fd29aSsetje layered = filter_etc ? 125*986fd29aSsetje strncmp(name, "/etc", sizeof ("/etc") - 1) == 0 : 1; 1267c478bd9Sstevel@tonic-gate 127*986fd29aSsetje if (afs_ih != OBP_BADNODE) { 128*986fd29aSsetje ih = afs_ih; 129*986fd29aSsetje fd = prom_fopen(ih, (char *)name); 130*986fd29aSsetje if (fd == -1 && !layered) 131*986fd29aSsetje return (BOOT_SVC_FAIL); 132*986fd29aSsetje } 133*986fd29aSsetje if (fd == -1 && bfs_ih != OBP_BADNODE) { 134*986fd29aSsetje ih = bfs_ih; 135*986fd29aSsetje fd = prom_fopen(ih, (char *)name); 136*986fd29aSsetje } 137*986fd29aSsetje if (fd == -1) 138*986fd29aSsetje return (BOOT_SVC_FAIL); 139*986fd29aSsetje ASSERT(fd < MAXPROMFD); 140*986fd29aSsetje ASSERT(prom_ihs[fd] == 0); 141*986fd29aSsetje prom_ihs[fd] = ih; 142*986fd29aSsetje return (fd); 143*986fd29aSsetje } 144*986fd29aSsetje 145*986fd29aSsetje static void 146*986fd29aSsetje spinner(void) 147*986fd29aSsetje { 148*986fd29aSsetje static int pos; 149*986fd29aSsetje static char ind[] = "|/-\\"; /* that's entertainment? */ 150*986fd29aSsetje static int blks_read; 151*986fd29aSsetje 152*986fd29aSsetje if ((blks_read++ & 0x3) == 0) 153*986fd29aSsetje prom_printf("%c\b", ind[pos++ & 3]); 1547c478bd9Sstevel@tonic-gate } 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate /* 1577c478bd9Sstevel@tonic-gate * Implementation of the "read" boot service. 1587c478bd9Sstevel@tonic-gate */ 1597c478bd9Sstevel@tonic-gate int 160*986fd29aSsetje bop_read(int fd, caddr_t buf, size_t size) 1617c478bd9Sstevel@tonic-gate { 162*986fd29aSsetje ASSERT(prom_ihs[fd] != 0); 163*986fd29aSsetje spinner(); 164*986fd29aSsetje return (prom_fread(prom_ihs[fd], fd, buf, size)); 1657c478bd9Sstevel@tonic-gate } 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate /* 1687c478bd9Sstevel@tonic-gate * Implementation of the "seek" boot service. 1697c478bd9Sstevel@tonic-gate */ 1707c478bd9Sstevel@tonic-gate int 171*986fd29aSsetje bop_seek(int fd, off_t off) 1727c478bd9Sstevel@tonic-gate { 173*986fd29aSsetje ASSERT(prom_ihs[fd] != 0); 174*986fd29aSsetje return (prom_fseek(prom_ihs[fd], fd, off)); 1757c478bd9Sstevel@tonic-gate } 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate /* 1787c478bd9Sstevel@tonic-gate * Implementation of the "close" boot service. 1797c478bd9Sstevel@tonic-gate */ 1807c478bd9Sstevel@tonic-gate int 181*986fd29aSsetje bop_close(int fd) 1827c478bd9Sstevel@tonic-gate { 183*986fd29aSsetje ASSERT(prom_ihs[fd] != 0); 184*986fd29aSsetje prom_fclose(prom_ihs[fd], fd); 185*986fd29aSsetje prom_ihs[fd] = 0; 186*986fd29aSsetje return (0); 1877c478bd9Sstevel@tonic-gate } 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate /* 190*986fd29aSsetje * Simple temp memory allocator 1917c478bd9Sstevel@tonic-gate * 192*986fd29aSsetje * >PAGESIZE allocations are gotten directly from prom at bighand 193*986fd29aSsetje * smaller ones are satisfied from littlehand, which does a 194*986fd29aSsetje * 1 page bighand allocation when it runs out of memory 195*986fd29aSsetje */ 196*986fd29aSsetje static caddr_t bighand = (caddr_t)BOOTTMPBASE; 197*986fd29aSsetje static caddr_t littlehand = (caddr_t)BOOTTMPBASE; 198*986fd29aSsetje 199*986fd29aSsetje #define NTMPALLOC 128 200*986fd29aSsetje 201*986fd29aSsetje static caddr_t temp_base[NTMPALLOC]; 202*986fd29aSsetje static size_t temp_size[NTMPALLOC]; 203*986fd29aSsetje static int temp_indx; 204*986fd29aSsetje 205*986fd29aSsetje #if defined(C_OBP) 206*986fd29aSsetje void cobp_free_mem(caddr_t, size_t); 207*986fd29aSsetje #endif /* C_OBP */ 208*986fd29aSsetje 209*986fd29aSsetje 210*986fd29aSsetje /* 211*986fd29aSsetje * temporary memory storage until bop_tmp_freeall is called 212*986fd29aSsetje * (after the kernel heap is initialized) 2137c478bd9Sstevel@tonic-gate */ 2147c478bd9Sstevel@tonic-gate caddr_t 215*986fd29aSsetje bop_temp_alloc(size_t size, int align) 2167c478bd9Sstevel@tonic-gate { 217*986fd29aSsetje caddr_t ret; 2187c478bd9Sstevel@tonic-gate 219*986fd29aSsetje /* 220*986fd29aSsetje * OBP allocs 10MB to boot, which is where virthint = 0 221*986fd29aSsetje * memory was allocated from. Without boot, we allocate 222*986fd29aSsetje * from BOOTTMPBASE and free when we're ready to take 223*986fd29aSsetje * the machine from OBP 224*986fd29aSsetje */ 225*986fd29aSsetje if (size < PAGESIZE) { 226*986fd29aSsetje size_t left = 227*986fd29aSsetje ALIGN(littlehand, PAGESIZE) - (uintptr_t)littlehand; 2287c478bd9Sstevel@tonic-gate 229*986fd29aSsetje size = roundup(size, MAX(align, 8)); 230*986fd29aSsetje if (size <= left) { 231*986fd29aSsetje ret = littlehand; 232*986fd29aSsetje littlehand += size; 233*986fd29aSsetje return (ret); 234*986fd29aSsetje } 235*986fd29aSsetje littlehand = bighand + size; 236*986fd29aSsetje } 237*986fd29aSsetje size = roundup(size, PAGESIZE); 238*986fd29aSsetje ret = prom_alloc(bighand, size, align); 239*986fd29aSsetje if (ret == NULL) 240*986fd29aSsetje prom_panic("boot temp overflow"); 241*986fd29aSsetje bighand += size; 242*986fd29aSsetje 243*986fd29aSsetje /* log it for bop_fini() */ 244*986fd29aSsetje temp_base[temp_indx] = ret; 245*986fd29aSsetje temp_size[temp_indx] = size; 246*986fd29aSsetje if (++temp_indx == NTMPALLOC) 247*986fd29aSsetje prom_panic("out of bop temp space"); 248*986fd29aSsetje 249*986fd29aSsetje return (ret); 250*986fd29aSsetje } 251*986fd29aSsetje 252*986fd29aSsetje void 253*986fd29aSsetje bop_temp_freeall(void) 254*986fd29aSsetje { 255*986fd29aSsetje int i; 256*986fd29aSsetje 257*986fd29aSsetje /* 258*986fd29aSsetje * We have to call prom_free() with the same args 259*986fd29aSsetje * as we used in prom_alloc() 260*986fd29aSsetje */ 261*986fd29aSsetje for (i = 0; i < NTMPALLOC; i++) { 262*986fd29aSsetje if (temp_base[i] == NULL) 263*986fd29aSsetje break; 264*986fd29aSsetje #if !defined(C_OBP) 265*986fd29aSsetje prom_free(temp_base[i], temp_size[i]); 266*986fd29aSsetje #else /* !C_OBP */ 267*986fd29aSsetje cobp_free_mem(temp_base[i], temp_size[i]); 268*986fd29aSsetje #endif /* !C_OBP */ 269*986fd29aSsetje } 270*986fd29aSsetje } 271*986fd29aSsetje 272*986fd29aSsetje 273*986fd29aSsetje /* 274*986fd29aSsetje * Implementation of the "alloc" boot service. 275*986fd29aSsetje */ 276*986fd29aSsetje caddr_t 277*986fd29aSsetje bop_alloc(caddr_t virthint, size_t size, int align) 278*986fd29aSsetje { 279*986fd29aSsetje if (virthint == NULL) 280*986fd29aSsetje return (bop_temp_alloc(size, align)); 281*986fd29aSsetje return (prom_alloc(virthint, size, align)); 2827c478bd9Sstevel@tonic-gate } 2837c478bd9Sstevel@tonic-gate 2847c478bd9Sstevel@tonic-gate /* 2857c478bd9Sstevel@tonic-gate * Implementation of the "alloc_virt" boot service 2867c478bd9Sstevel@tonic-gate */ 2877c478bd9Sstevel@tonic-gate caddr_t 288*986fd29aSsetje bop_alloc_virt(caddr_t virt, size_t size) 2897c478bd9Sstevel@tonic-gate { 290*986fd29aSsetje return (prom_claim_virt(size, virt)); 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate /* 2947c478bd9Sstevel@tonic-gate * Implementation of the "free" boot service. 2957c478bd9Sstevel@tonic-gate */ 2967c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2977c478bd9Sstevel@tonic-gate void 298*986fd29aSsetje bop_free(caddr_t virt, size_t size) 2997c478bd9Sstevel@tonic-gate { 300*986fd29aSsetje prom_free(virt, size); 3017c478bd9Sstevel@tonic-gate } 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate /* 3067c478bd9Sstevel@tonic-gate * Implementation of the "getproplen" boot service. 3077c478bd9Sstevel@tonic-gate */ 3087c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3097c478bd9Sstevel@tonic-gate int 310*986fd29aSsetje bop_getproplen(const char *name) 3117c478bd9Sstevel@tonic-gate { 312*986fd29aSsetje struct fakeprop *fpp; 313*986fd29aSsetje pnode_t node; 314*986fd29aSsetje char *prop; 3157c478bd9Sstevel@tonic-gate 316*986fd29aSsetje fpp = fakelook(name); 317*986fd29aSsetje if (fpp != NULL) { 318*986fd29aSsetje node = fpp->promnode; 319*986fd29aSsetje prop = fpp->promname; 320*986fd29aSsetje } else { 321*986fd29aSsetje node = chosennode; 322*986fd29aSsetje prop = (char *)name; 323*986fd29aSsetje } 324*986fd29aSsetje return (prom_getproplen(node, prop)); 3257c478bd9Sstevel@tonic-gate } 3267c478bd9Sstevel@tonic-gate 3277c478bd9Sstevel@tonic-gate /* 3287c478bd9Sstevel@tonic-gate * Implementation of the "getprop" boot service. 3297c478bd9Sstevel@tonic-gate */ 3307c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3317c478bd9Sstevel@tonic-gate int 332*986fd29aSsetje bop_getprop(const char *name, void *value) 3337c478bd9Sstevel@tonic-gate { 334*986fd29aSsetje struct fakeprop *fpp; 335*986fd29aSsetje pnode_t node; 336*986fd29aSsetje char *prop; 3377c478bd9Sstevel@tonic-gate 338*986fd29aSsetje fpp = fakelook(name); 339*986fd29aSsetje if (fpp != NULL) { 340*986fd29aSsetje node = fpp->promnode; 341*986fd29aSsetje prop = fpp->promname; 342*986fd29aSsetje } else { 343*986fd29aSsetje node = chosennode; 344*986fd29aSsetje prop = (char *)name; 345*986fd29aSsetje } 346*986fd29aSsetje return (prom_getprop(node, prop, value)); 3477c478bd9Sstevel@tonic-gate } 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate /* 350*986fd29aSsetje * Implementation of the "print" boot service. 3517c478bd9Sstevel@tonic-gate */ 3527c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3537c478bd9Sstevel@tonic-gate void 354*986fd29aSsetje bop_printf(void *ops, const char *fmt, ...) 3557c478bd9Sstevel@tonic-gate { 356*986fd29aSsetje va_list adx; 3577c478bd9Sstevel@tonic-gate 358*986fd29aSsetje va_start(adx, fmt); 359*986fd29aSsetje prom_vprintf(fmt, adx); 360*986fd29aSsetje va_end(adx); 3617c478bd9Sstevel@tonic-gate } 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate /* 364*986fd29aSsetje * Special routine for kmdb 3657c478bd9Sstevel@tonic-gate */ 3667c478bd9Sstevel@tonic-gate void 367*986fd29aSsetje bop_putsarg(const char *fmt, char *arg) 3687c478bd9Sstevel@tonic-gate { 369*986fd29aSsetje prom_printf(fmt, arg); 370*986fd29aSsetje } 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate /* 373*986fd29aSsetje * panic for krtld only 3747c478bd9Sstevel@tonic-gate */ 375*986fd29aSsetje void 376*986fd29aSsetje bop_panic(const char *s) 377*986fd29aSsetje { 378*986fd29aSsetje prom_panic((char *)s); 3797c478bd9Sstevel@tonic-gate } 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate /* 3827c478bd9Sstevel@tonic-gate * Implementation of the "mount" boot service. 3837c478bd9Sstevel@tonic-gate * 3847c478bd9Sstevel@tonic-gate */ 3857c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3867c478bd9Sstevel@tonic-gate int 387*986fd29aSsetje bop_mountroot(void) 3887c478bd9Sstevel@tonic-gate { 389*986fd29aSsetje (void) prom_getprop(chosennode, "bootfs", (caddr_t)&bfs_ih); 390*986fd29aSsetje (void) prom_getprop(chosennode, "archfs", (caddr_t)&afs_ih); 391*986fd29aSsetje return ((bfs_ih == -1 && afs_ih == -1) ? BOOT_SVC_FAIL : BOOT_SVC_OK); 3927c478bd9Sstevel@tonic-gate } 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate /* 3957c478bd9Sstevel@tonic-gate * Implementation of the "unmountroot" boot service. 3967c478bd9Sstevel@tonic-gate */ 3977c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3987c478bd9Sstevel@tonic-gate int 399*986fd29aSsetje bop_unmountroot(void) 4007c478bd9Sstevel@tonic-gate { 4017c478bd9Sstevel@tonic-gate 402*986fd29aSsetje if (bfs_ih != OBP_BADNODE) { 403*986fd29aSsetje (void) prom_close(bfs_ih); 404*986fd29aSsetje bfs_ih = OBP_BADNODE; 4057c478bd9Sstevel@tonic-gate } 406*986fd29aSsetje if (afs_ih != OBP_BADNODE) { 407*986fd29aSsetje (void) prom_close(afs_ih); 408*986fd29aSsetje afs_ih = OBP_BADNODE; 409*986fd29aSsetje } 410*986fd29aSsetje return (BOOT_SVC_OK); 4117c478bd9Sstevel@tonic-gate } 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate /* 4147c478bd9Sstevel@tonic-gate * Implementation of the "fstat" boot service. 4157c478bd9Sstevel@tonic-gate */ 4167c478bd9Sstevel@tonic-gate int 417*986fd29aSsetje bop_fstat(int fd, struct bootstat *st) 4187c478bd9Sstevel@tonic-gate { 419*986fd29aSsetje ASSERT(prom_ihs[fd] != 0); 420*986fd29aSsetje return (prom_fsize(prom_ihs[fd], fd, (size_t *)&st->st_size)); 4217c478bd9Sstevel@tonic-gate } 4227c478bd9Sstevel@tonic-gate 423*986fd29aSsetje int 424*986fd29aSsetje boot_compinfo(int fd, struct compinfo *cb) 425*986fd29aSsetje { 426*986fd29aSsetje ASSERT(prom_ihs[fd] != 0); 427*986fd29aSsetje return (prom_compinfo(prom_ihs[fd], fd, 428*986fd29aSsetje &cb->iscmp, &cb->fsize, &cb->blksize)); 429*986fd29aSsetje } 430*986fd29aSsetje 431*986fd29aSsetje void 432*986fd29aSsetje bop_free_archive(void) 433*986fd29aSsetje { 434*986fd29aSsetje char archive[OBP_MAXPATHLEN]; 435*986fd29aSsetje pnode_t arph; 436*986fd29aSsetje uint32_t arbase, arsize, alloc_size; 437*986fd29aSsetje 438*986fd29aSsetje /* 439*986fd29aSsetje * If the ramdisk will eventually be root, or we weren't 440*986fd29aSsetje * booted via the archive, then nothing to do here 441*986fd29aSsetje */ 442*986fd29aSsetje if (root_is_ramdisk == B_TRUE || 443*986fd29aSsetje prom_getprop(chosennode, "bootarchive", archive) == -1) 444*986fd29aSsetje return; 445*986fd29aSsetje arph = prom_finddevice(archive); 446*986fd29aSsetje if (arph == -1 || 447*986fd29aSsetje prom_getprop(arph, OBP_ALLOCSIZE, (caddr_t)&alloc_size) == -1 || 448*986fd29aSsetje prom_getprop(arph, OBP_SIZE, (caddr_t)&arsize) == -1 || 449*986fd29aSsetje prom_getprop(arph, OBP_ADDRESS, (caddr_t)&arbase) == -1) 450*986fd29aSsetje prom_panic("can't free boot archive"); 451*986fd29aSsetje 452*986fd29aSsetje #if !defined(C_OBP) 453*986fd29aSsetje if (alloc_size == 0) 454*986fd29aSsetje prom_free((caddr_t)(uintptr_t)arbase, arsize); 455*986fd29aSsetje else { 456*986fd29aSsetje uint32_t arend = arbase + arsize; 457*986fd29aSsetje 458*986fd29aSsetje while (arbase < arend) { 459*986fd29aSsetje prom_free((caddr_t)(uintptr_t)arbase, 460*986fd29aSsetje MIN(alloc_size, arend - arbase)); 461*986fd29aSsetje arbase += alloc_size; 462*986fd29aSsetje } 463*986fd29aSsetje } 464*986fd29aSsetje #else /* !C_OBP */ 465*986fd29aSsetje cobp_free_mem((caddr_t)(uintptr_t)arbase, arsize); 466*986fd29aSsetje #endif /* !C_OBP */ 467*986fd29aSsetje } 468*986fd29aSsetje 469*986fd29aSsetje #if defined(C_OBP) 470*986fd29aSsetje /* 471*986fd29aSsetje * Blech. The C proms have a bug when freeing areas that cross 472*986fd29aSsetje * page sizes, so we have to break up the free into sections 473*986fd29aSsetje * bounded by the various pagesizes. 474*986fd29aSsetje */ 475*986fd29aSsetje void 476*986fd29aSsetje cobp_free_mem(caddr_t base, size_t size) 477*986fd29aSsetje { 478*986fd29aSsetje int i; 479*986fd29aSsetje size_t len, pgsz; 480*986fd29aSsetje 481*986fd29aSsetje /* 482*986fd29aSsetje * Large pages only used when size > 512k 483*986fd29aSsetje */ 484*986fd29aSsetje if (size < MMU_PAGESIZE512K || 485*986fd29aSsetje ((uintptr_t)base & MMU_PAGEOFFSET512K) != 0) { 486*986fd29aSsetje prom_free(base, size); 487*986fd29aSsetje return; 488*986fd29aSsetje } 489*986fd29aSsetje for (i = 3; i >= 0; i--) { 490*986fd29aSsetje pgsz = page_get_pagesize(i); 491*986fd29aSsetje if (size < pgsz) 492*986fd29aSsetje continue; 493*986fd29aSsetje len = size & ~(pgsz - 1); 494*986fd29aSsetje prom_free(base, len); 495*986fd29aSsetje base += len; 496*986fd29aSsetje size -= len; 497*986fd29aSsetje } 498*986fd29aSsetje } 499*986fd29aSsetje #endif /* C_OBP */ 500*986fd29aSsetje 501*986fd29aSsetje 5027c478bd9Sstevel@tonic-gate /* 5037c478bd9Sstevel@tonic-gate * Implementation of the "enter_mon" boot service. 5047c478bd9Sstevel@tonic-gate */ 5057c478bd9Sstevel@tonic-gate void 506*986fd29aSsetje bop_enter_mon(void) 5077c478bd9Sstevel@tonic-gate { 508*986fd29aSsetje prom_enter_mon(); 509*986fd29aSsetje } 5107c478bd9Sstevel@tonic-gate 511*986fd29aSsetje /* 512*986fd29aSsetje * free elf info allocated by booter 513*986fd29aSsetje */ 514*986fd29aSsetje void 515*986fd29aSsetje bop_free_elf(void) 516*986fd29aSsetje { 517*986fd29aSsetje uint32_t eadr; 518*986fd29aSsetje uint32_t esize; 519*986fd29aSsetje extern Addr dynseg; 520*986fd29aSsetje extern size_t dynsize; 521*986fd29aSsetje 522*986fd29aSsetje if (bop_getprop("elfheader-address", (caddr_t)&eadr) == -1 || 523*986fd29aSsetje bop_getprop("elfheader-length", (caddr_t)&esize) == -1) 524*986fd29aSsetje prom_panic("missing elfheader"); 525*986fd29aSsetje prom_free((caddr_t)(uintptr_t)eadr, roundup(esize, PAGESIZE)); 526*986fd29aSsetje 527*986fd29aSsetje prom_free((caddr_t)(uintptr_t)dynseg, roundup(dynsize, PAGESIZE)); 528*986fd29aSsetje } 529*986fd29aSsetje 530*986fd29aSsetje 531*986fd29aSsetje /* Simple message to indicate that the bootops pointer has been zeroed */ 532*986fd29aSsetje #ifdef DEBUG 533*986fd29aSsetje int bootops_gone_on = 0; 534*986fd29aSsetje #define BOOTOPS_GONE() \ 535*986fd29aSsetje if (bootops_gone_on) \ 536*986fd29aSsetje prom_printf("The bootops vec is zeroed now!\n"); 537*986fd29aSsetje #else 538*986fd29aSsetje #define BOOTOPS_GONE() 539*986fd29aSsetje #endif /* DEBUG */ 540*986fd29aSsetje 541*986fd29aSsetje void 542*986fd29aSsetje bop_fini(void) 543*986fd29aSsetje { 544*986fd29aSsetje bop_free_archive(); 545*986fd29aSsetje (void) bop_unmountroot(); 546*986fd29aSsetje bop_free_elf(); 547*986fd29aSsetje bop_temp_freeall(); 548*986fd29aSsetje 549*986fd29aSsetje bootops = (struct bootops *)NULL; 550*986fd29aSsetje BOOTOPS_GONE(); 5517c478bd9Sstevel@tonic-gate } 552