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 55648Ssetje * Common Development and Distribution License (the "License"). 65648Ssetje * 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*7218Ssvemuri * Copyright 2008 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> 375648Ssetje #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> 425648Ssetje #include <sys/promimpl.h> 435648Ssetje #include <sys/prom_plat.h> 440Sstevel@tonic-gate #include <sys/bootconf.h> 450Sstevel@tonic-gate #include <sys/bootstat.h> 465648Ssetje #include <sys/kobj_impl.h> 470Sstevel@tonic-gate 485648Ssetje struct bootops *bootops; 495648Ssetje struct bootops kbootops; 505648Ssetje 515648Ssetje pnode_t chosennode; 525648Ssetje 535648Ssetje #define FAKE_ROOT (pnode_t)1 545648Ssetje 555648Ssetje struct fakeprop { 565648Ssetje char *bootname; 575648Ssetje pnode_t promnode; 585648Ssetje char *promname; 595648Ssetje } fakeprops[] = { 605648Ssetje { "mfg-name", FAKE_ROOT, "name" }, 615648Ssetje { NULL, 0, NULL } 625648Ssetje }; 635648Ssetje 645648Ssetje static void 655648Ssetje fakelook_init(void) 660Sstevel@tonic-gate { 675648Ssetje struct fakeprop *fpp = fakeprops; 685648Ssetje 695648Ssetje while (fpp->bootname != NULL) { 705648Ssetje switch (fpp->promnode) { 715648Ssetje case FAKE_ROOT: 725648Ssetje fpp->promnode = prom_rootnode(); 735648Ssetje break; 745648Ssetje } 755648Ssetje fpp++; 765648Ssetje } 770Sstevel@tonic-gate } 780Sstevel@tonic-gate 795648Ssetje static struct fakeprop * 805648Ssetje fakelook(const char *prop) 815648Ssetje { 825648Ssetje struct fakeprop *fpp = fakeprops; 835648Ssetje 845648Ssetje while (fpp->bootname != NULL) { 855648Ssetje if (strcmp(prop, fpp->bootname) == 0) 865648Ssetje return (fpp); 875648Ssetje fpp++; 885648Ssetje } 895648Ssetje return (NULL); 905648Ssetje } 915648Ssetje 925648Ssetje ihandle_t bfs_ih = OBP_BADNODE; 935648Ssetje ihandle_t afs_ih = OBP_BADNODE; 945648Ssetje 955648Ssetje void 965648Ssetje bop_init(void) 975648Ssetje { 985648Ssetje chosennode = prom_chosennode(); 995648Ssetje 1005648Ssetje fakelook_init(); 1015648Ssetje 1025648Ssetje /* fake bootops - it needs to point to non-NULL */ 1035648Ssetje bootops = &kbootops; 1045648Ssetje } 1055648Ssetje 1065648Ssetje #define MAXPROMFD 16 1075648Ssetje 1085648Ssetje static ihandle_t prom_ihs[MAXPROMFD]; 1095648Ssetje int filter_etc = 1; 1100Sstevel@tonic-gate 1110Sstevel@tonic-gate /* 1120Sstevel@tonic-gate * Implementation of the "open" boot service. 1130Sstevel@tonic-gate */ 1145648Ssetje /*ARGSUSED*/ 1150Sstevel@tonic-gate int 1165648Ssetje bop_open(const char *name, int flags) 1170Sstevel@tonic-gate { 1185648Ssetje int fd = -1, layered; 1195648Ssetje ihandle_t ih; 1205648Ssetje 1215648Ssetje /* 1225648Ssetje * Only look underneath archive for /etc files 1235648Ssetje */ 1245648Ssetje layered = filter_etc ? 1255648Ssetje strncmp(name, "/etc", sizeof ("/etc") - 1) == 0 : 1; 1260Sstevel@tonic-gate 1275648Ssetje if (afs_ih != OBP_BADNODE) { 1285648Ssetje ih = afs_ih; 1295648Ssetje fd = prom_fopen(ih, (char *)name); 1305648Ssetje if (fd == -1 && !layered) 1315648Ssetje return (BOOT_SVC_FAIL); 1325648Ssetje } 1335648Ssetje if (fd == -1 && bfs_ih != OBP_BADNODE) { 1345648Ssetje ih = bfs_ih; 1355648Ssetje fd = prom_fopen(ih, (char *)name); 1365648Ssetje } 1375648Ssetje if (fd == -1) 1385648Ssetje return (BOOT_SVC_FAIL); 1395648Ssetje ASSERT(fd < MAXPROMFD); 1405648Ssetje ASSERT(prom_ihs[fd] == 0); 1415648Ssetje prom_ihs[fd] = ih; 1425648Ssetje return (fd); 1435648Ssetje } 1440Sstevel@tonic-gate 1455648Ssetje static void 1465648Ssetje spinner(void) 1475648Ssetje { 1485648Ssetje static int pos; 1495648Ssetje static char ind[] = "|/-\\"; /* that's entertainment? */ 1505648Ssetje static int blks_read; 1515648Ssetje 1525648Ssetje if ((blks_read++ & 0x3) == 0) 1535648Ssetje 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 1605648Ssetje bop_read(int fd, caddr_t buf, size_t size) 1610Sstevel@tonic-gate { 1625648Ssetje ASSERT(prom_ihs[fd] != 0); 1635648Ssetje spinner(); 1645648Ssetje 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 1715648Ssetje bop_seek(int fd, off_t off) 1720Sstevel@tonic-gate { 1735648Ssetje ASSERT(prom_ihs[fd] != 0); 1745648Ssetje 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 1815648Ssetje bop_close(int fd) 1820Sstevel@tonic-gate { 1835648Ssetje ASSERT(prom_ihs[fd] != 0); 1845648Ssetje prom_fclose(prom_ihs[fd], fd); 1855648Ssetje prom_ihs[fd] = 0; 1865648Ssetje return (0); 1875648Ssetje } 1885648Ssetje 1895648Ssetje /* 1905648Ssetje * Simple temp memory allocator 1915648Ssetje * 1925648Ssetje * >PAGESIZE allocations are gotten directly from prom at bighand 1935648Ssetje * smaller ones are satisfied from littlehand, which does a 1945648Ssetje * 1 page bighand allocation when it runs out of memory 1955648Ssetje */ 1965648Ssetje static caddr_t bighand = (caddr_t)BOOTTMPBASE; 1975648Ssetje static caddr_t littlehand = (caddr_t)BOOTTMPBASE; 1985648Ssetje 1995648Ssetje #define NTMPALLOC 128 2005648Ssetje 2015648Ssetje static caddr_t temp_base[NTMPALLOC]; 2025648Ssetje static size_t temp_size[NTMPALLOC]; 2035648Ssetje static int temp_indx; 2045648Ssetje 2055648Ssetje #if defined(C_OBP) 2065648Ssetje void cobp_free_mem(caddr_t, size_t); 2075648Ssetje #endif /* C_OBP */ 2085648Ssetje 2095648Ssetje 2105648Ssetje /* 2115648Ssetje * temporary memory storage until bop_tmp_freeall is called 2125648Ssetje * (after the kernel heap is initialized) 2135648Ssetje */ 2145648Ssetje caddr_t 2155648Ssetje bop_temp_alloc(size_t size, int align) 2165648Ssetje { 2175648Ssetje caddr_t ret; 2180Sstevel@tonic-gate 2195648Ssetje /* 2205648Ssetje * OBP allocs 10MB to boot, which is where virthint = 0 2215648Ssetje * memory was allocated from. Without boot, we allocate 2225648Ssetje * from BOOTTMPBASE and free when we're ready to take 2235648Ssetje * the machine from OBP 2245648Ssetje */ 2255648Ssetje if (size < PAGESIZE) { 2265648Ssetje size_t left = 2275648Ssetje ALIGN(littlehand, PAGESIZE) - (uintptr_t)littlehand; 2285648Ssetje 2295648Ssetje size = roundup(size, MAX(align, 8)); 2305648Ssetje if (size <= left) { 2315648Ssetje ret = littlehand; 2325648Ssetje littlehand += size; 2335648Ssetje return (ret); 2345648Ssetje } 2355648Ssetje littlehand = bighand + size; 2365648Ssetje } 2375648Ssetje size = roundup(size, PAGESIZE); 2385648Ssetje ret = prom_alloc(bighand, size, align); 2395648Ssetje if (ret == NULL) 2405648Ssetje prom_panic("boot temp overflow"); 2415648Ssetje bighand += size; 2420Sstevel@tonic-gate 2435648Ssetje /* log it for bop_fini() */ 2445648Ssetje temp_base[temp_indx] = ret; 2455648Ssetje temp_size[temp_indx] = size; 2465648Ssetje if (++temp_indx == NTMPALLOC) 2475648Ssetje prom_panic("out of bop temp space"); 2485648Ssetje 2495648Ssetje return (ret); 2500Sstevel@tonic-gate } 2510Sstevel@tonic-gate 2525648Ssetje void 2535648Ssetje bop_temp_freeall(void) 2545648Ssetje { 2555648Ssetje int i; 2565648Ssetje 2575648Ssetje /* 2585648Ssetje * We have to call prom_free() with the same args 2595648Ssetje * as we used in prom_alloc() 2605648Ssetje */ 2615648Ssetje for (i = 0; i < NTMPALLOC; i++) { 2625648Ssetje if (temp_base[i] == NULL) 2635648Ssetje break; 2645648Ssetje #if !defined(C_OBP) 2655648Ssetje prom_free(temp_base[i], temp_size[i]); 2665648Ssetje #else /* !C_OBP */ 2675648Ssetje cobp_free_mem(temp_base[i], temp_size[i]); 2685648Ssetje #endif /* !C_OBP */ 2695648Ssetje } 2705648Ssetje } 2715648Ssetje 2725648Ssetje 2730Sstevel@tonic-gate /* 2740Sstevel@tonic-gate * Implementation of the "alloc" boot service. 2750Sstevel@tonic-gate */ 2760Sstevel@tonic-gate caddr_t 2775648Ssetje bop_alloc(caddr_t virthint, size_t size, int align) 2780Sstevel@tonic-gate { 2795648Ssetje if (virthint == NULL) 2805648Ssetje return (bop_temp_alloc(size, align)); 2815648Ssetje return (prom_alloc(virthint, size, align)); 2820Sstevel@tonic-gate } 2830Sstevel@tonic-gate 284*7218Ssvemuri 285*7218Ssvemuri /* 286*7218Ssvemuri * Similar to bop_alloc functionality except that 287*7218Ssvemuri * it will try to breakup into PAGESIZE chunk allocations 288*7218Ssvemuri * if the original single chunk request failed. 289*7218Ssvemuri * This routine does not guarantee physical contig 290*7218Ssvemuri * allocation. 291*7218Ssvemuri */ 292*7218Ssvemuri caddr_t 293*7218Ssvemuri bop_alloc_chunk(caddr_t virthint, size_t size, int align) 294*7218Ssvemuri { 295*7218Ssvemuri caddr_t ret; 296*7218Ssvemuri size_t chunksz; 297*7218Ssvemuri 298*7218Ssvemuri if (virthint == NULL) 299*7218Ssvemuri return (bop_temp_alloc(size, align)); 300*7218Ssvemuri 301*7218Ssvemuri if ((ret = prom_alloc(virthint, size, align))) 302*7218Ssvemuri return (ret); 303*7218Ssvemuri 304*7218Ssvemuri /* 305*7218Ssvemuri * Normal request to prom_alloc has failed. 306*7218Ssvemuri * We will attempt to satisfy the request by allocating 307*7218Ssvemuri * smaller chunks resulting in allocation that 308*7218Ssvemuri * will be virtually contiguous but potentially 309*7218Ssvemuri * not physically contiguous. There are additional 310*7218Ssvemuri * requirements before we want to do this: 311*7218Ssvemuri * 1. virthirt must be PAGESIZE aligned. 312*7218Ssvemuri * 2. align must not be greater than PAGESIZE 313*7218Ssvemuri * 3. size request must be at least PAGESIZE 314*7218Ssvemuri * Otherwise, we will revert back to the original 315*7218Ssvemuri * bop_alloc behavior i.e. return failure. 316*7218Ssvemuri */ 317*7218Ssvemuri if (P2PHASE_TYPED(virthint, PAGESIZE, size_t) != 0 || 318*7218Ssvemuri align > PAGESIZE || size < PAGESIZE) 319*7218Ssvemuri return (ret); 320*7218Ssvemuri 321*7218Ssvemuri /* 322*7218Ssvemuri * Now we will break up the allocation 323*7218Ssvemuri * request in smaller chunks that are 324*7218Ssvemuri * always PAGESIZE aligned. 325*7218Ssvemuri */ 326*7218Ssvemuri ret = virthint; 327*7218Ssvemuri chunksz = P2ALIGN((size >> 1), PAGESIZE); 328*7218Ssvemuri chunksz = MAX(chunksz, PAGESIZE); 329*7218Ssvemuri 330*7218Ssvemuri while (size) { 331*7218Ssvemuri do { 332*7218Ssvemuri /*LINTED E_FUNC_SET_NOT_USED*/ 333*7218Ssvemuri caddr_t res; 334*7218Ssvemuri if ((res = prom_alloc(virthint, chunksz, 335*7218Ssvemuri PAGESIZE))) { 336*7218Ssvemuri ASSERT(virthint == res); 337*7218Ssvemuri break; 338*7218Ssvemuri } 339*7218Ssvemuri 340*7218Ssvemuri chunksz >>= 1; 341*7218Ssvemuri chunksz = P2ALIGN(chunksz, PAGESIZE); 342*7218Ssvemuri } while (chunksz >= PAGESIZE); 343*7218Ssvemuri 344*7218Ssvemuri if (chunksz < PAGESIZE) 345*7218Ssvemuri /* Can't really happen.. */ 346*7218Ssvemuri prom_panic("bop_alloc_chunk failed"); 347*7218Ssvemuri 348*7218Ssvemuri virthint += chunksz; 349*7218Ssvemuri size -= chunksz; 350*7218Ssvemuri if (size < chunksz) 351*7218Ssvemuri chunksz = size; 352*7218Ssvemuri } 353*7218Ssvemuri return (ret); 354*7218Ssvemuri } 355*7218Ssvemuri 356*7218Ssvemuri 3570Sstevel@tonic-gate /* 3580Sstevel@tonic-gate * Implementation of the "alloc_virt" boot service 3590Sstevel@tonic-gate */ 3600Sstevel@tonic-gate caddr_t 3615648Ssetje bop_alloc_virt(caddr_t virt, size_t size) 3620Sstevel@tonic-gate { 3635648Ssetje return (prom_claim_virt(size, virt)); 3640Sstevel@tonic-gate } 3650Sstevel@tonic-gate 3660Sstevel@tonic-gate /* 3670Sstevel@tonic-gate * Implementation of the "free" boot service. 3680Sstevel@tonic-gate */ 3690Sstevel@tonic-gate /*ARGSUSED*/ 3700Sstevel@tonic-gate void 3715648Ssetje bop_free(caddr_t virt, size_t size) 3720Sstevel@tonic-gate { 3735648Ssetje prom_free(virt, size); 3740Sstevel@tonic-gate } 3750Sstevel@tonic-gate 3760Sstevel@tonic-gate 3770Sstevel@tonic-gate 3780Sstevel@tonic-gate /* 3790Sstevel@tonic-gate * Implementation of the "getproplen" boot service. 3800Sstevel@tonic-gate */ 3810Sstevel@tonic-gate /*ARGSUSED*/ 3820Sstevel@tonic-gate int 3835648Ssetje bop_getproplen(const char *name) 3840Sstevel@tonic-gate { 3855648Ssetje struct fakeprop *fpp; 3865648Ssetje pnode_t node; 3875648Ssetje char *prop; 3880Sstevel@tonic-gate 3895648Ssetje fpp = fakelook(name); 3905648Ssetje if (fpp != NULL) { 3915648Ssetje node = fpp->promnode; 3925648Ssetje prop = fpp->promname; 3935648Ssetje } else { 3945648Ssetje node = chosennode; 3955648Ssetje prop = (char *)name; 3965648Ssetje } 3975648Ssetje return (prom_getproplen(node, prop)); 3980Sstevel@tonic-gate } 3990Sstevel@tonic-gate 4000Sstevel@tonic-gate /* 4010Sstevel@tonic-gate * Implementation of the "getprop" boot service. 4020Sstevel@tonic-gate */ 4030Sstevel@tonic-gate /*ARGSUSED*/ 4040Sstevel@tonic-gate int 4055648Ssetje bop_getprop(const char *name, void *value) 4060Sstevel@tonic-gate { 4075648Ssetje struct fakeprop *fpp; 4085648Ssetje pnode_t node; 4095648Ssetje char *prop; 4100Sstevel@tonic-gate 4115648Ssetje fpp = fakelook(name); 4125648Ssetje if (fpp != NULL) { 4135648Ssetje node = fpp->promnode; 4145648Ssetje prop = fpp->promname; 4155648Ssetje } else { 4165648Ssetje node = chosennode; 4175648Ssetje prop = (char *)name; 4185648Ssetje } 4195648Ssetje return (prom_getprop(node, prop, value)); 4200Sstevel@tonic-gate } 4210Sstevel@tonic-gate 4220Sstevel@tonic-gate /* 4235648Ssetje * Implementation of the "print" boot service. 4240Sstevel@tonic-gate */ 4250Sstevel@tonic-gate /*ARGSUSED*/ 4260Sstevel@tonic-gate void 4275648Ssetje bop_printf(void *ops, const char *fmt, ...) 4280Sstevel@tonic-gate { 4295648Ssetje va_list adx; 4300Sstevel@tonic-gate 4315648Ssetje va_start(adx, fmt); 4325648Ssetje prom_vprintf(fmt, adx); 4335648Ssetje va_end(adx); 4340Sstevel@tonic-gate } 4350Sstevel@tonic-gate 4360Sstevel@tonic-gate /* 4375648Ssetje * Special routine for kmdb 4380Sstevel@tonic-gate */ 4390Sstevel@tonic-gate void 4405648Ssetje bop_putsarg(const char *fmt, char *arg) 4410Sstevel@tonic-gate { 4425648Ssetje prom_printf(fmt, arg); 4435648Ssetje } 4440Sstevel@tonic-gate 4455648Ssetje /* 4465648Ssetje * panic for krtld only 4475648Ssetje */ 4485648Ssetje void 4495648Ssetje bop_panic(const char *s) 4505648Ssetje { 4515648Ssetje prom_panic((char *)s); 4520Sstevel@tonic-gate } 4530Sstevel@tonic-gate 4540Sstevel@tonic-gate /* 4550Sstevel@tonic-gate * Implementation of the "mount" boot service. 4560Sstevel@tonic-gate * 4570Sstevel@tonic-gate */ 4580Sstevel@tonic-gate /*ARGSUSED*/ 4590Sstevel@tonic-gate int 4605648Ssetje bop_mountroot(void) 4610Sstevel@tonic-gate { 4625648Ssetje (void) prom_getprop(chosennode, "bootfs", (caddr_t)&bfs_ih); 4635648Ssetje (void) prom_getprop(chosennode, "archfs", (caddr_t)&afs_ih); 4645648Ssetje return ((bfs_ih == -1 && afs_ih == -1) ? BOOT_SVC_FAIL : BOOT_SVC_OK); 4650Sstevel@tonic-gate } 4660Sstevel@tonic-gate 4670Sstevel@tonic-gate /* 4680Sstevel@tonic-gate * Implementation of the "unmountroot" boot service. 4690Sstevel@tonic-gate */ 4700Sstevel@tonic-gate /*ARGSUSED*/ 4710Sstevel@tonic-gate int 4725648Ssetje bop_unmountroot(void) 4730Sstevel@tonic-gate { 4740Sstevel@tonic-gate 4755648Ssetje if (bfs_ih != OBP_BADNODE) { 4765648Ssetje (void) prom_close(bfs_ih); 4775648Ssetje bfs_ih = OBP_BADNODE; 4785648Ssetje } 4795648Ssetje if (afs_ih != OBP_BADNODE) { 4805648Ssetje (void) prom_close(afs_ih); 4815648Ssetje afs_ih = OBP_BADNODE; 4825648Ssetje } 4835648Ssetje return (BOOT_SVC_OK); 4840Sstevel@tonic-gate } 4850Sstevel@tonic-gate 4860Sstevel@tonic-gate /* 4870Sstevel@tonic-gate * Implementation of the "fstat" boot service. 4880Sstevel@tonic-gate */ 4890Sstevel@tonic-gate int 4905648Ssetje bop_fstat(int fd, struct bootstat *st) 4915648Ssetje { 4925648Ssetje ASSERT(prom_ihs[fd] != 0); 4935648Ssetje return (prom_fsize(prom_ihs[fd], fd, (size_t *)&st->st_size)); 4945648Ssetje } 4955648Ssetje 4965648Ssetje int 4975648Ssetje boot_compinfo(int fd, struct compinfo *cb) 4985648Ssetje { 4995648Ssetje ASSERT(prom_ihs[fd] != 0); 5005648Ssetje return (prom_compinfo(prom_ihs[fd], fd, 5015648Ssetje &cb->iscmp, &cb->fsize, &cb->blksize)); 5025648Ssetje } 5035648Ssetje 5045648Ssetje void 5055648Ssetje bop_free_archive(void) 5060Sstevel@tonic-gate { 5075648Ssetje char archive[OBP_MAXPATHLEN]; 5085648Ssetje pnode_t arph; 5095648Ssetje uint32_t arbase, arsize, alloc_size; 5105648Ssetje 5115648Ssetje /* 5125648Ssetje * If the ramdisk will eventually be root, or we weren't 5135648Ssetje * booted via the archive, then nothing to do here 5145648Ssetje */ 5155648Ssetje if (root_is_ramdisk == B_TRUE || 5165648Ssetje prom_getprop(chosennode, "bootarchive", archive) == -1) 5175648Ssetje return; 5185648Ssetje arph = prom_finddevice(archive); 5195648Ssetje if (arph == -1 || 5205648Ssetje prom_getprop(arph, OBP_ALLOCSIZE, (caddr_t)&alloc_size) == -1 || 5215648Ssetje prom_getprop(arph, OBP_SIZE, (caddr_t)&arsize) == -1 || 5225648Ssetje prom_getprop(arph, OBP_ADDRESS, (caddr_t)&arbase) == -1) 5235648Ssetje prom_panic("can't free boot archive"); 5245648Ssetje 5255648Ssetje #if !defined(C_OBP) 5265648Ssetje if (alloc_size == 0) 5275648Ssetje prom_free((caddr_t)(uintptr_t)arbase, arsize); 5285648Ssetje else { 5295648Ssetje uint32_t arend = arbase + arsize; 5300Sstevel@tonic-gate 5315648Ssetje while (arbase < arend) { 5325648Ssetje prom_free((caddr_t)(uintptr_t)arbase, 5335648Ssetje MIN(alloc_size, arend - arbase)); 5345648Ssetje arbase += alloc_size; 5355648Ssetje } 5365648Ssetje } 5375648Ssetje #else /* !C_OBP */ 5385648Ssetje cobp_free_mem((caddr_t)(uintptr_t)arbase, arsize); 5395648Ssetje #endif /* !C_OBP */ 5405648Ssetje } 5415648Ssetje 5425648Ssetje #if defined(C_OBP) 5435648Ssetje /* 5445648Ssetje * Blech. The C proms have a bug when freeing areas that cross 5455648Ssetje * page sizes, so we have to break up the free into sections 5465648Ssetje * bounded by the various pagesizes. 5475648Ssetje */ 5485648Ssetje void 5495648Ssetje cobp_free_mem(caddr_t base, size_t size) 5505648Ssetje { 5515648Ssetje int i; 5525648Ssetje size_t len, pgsz; 5535648Ssetje 5545648Ssetje /* 5555648Ssetje * Large pages only used when size > 512k 5565648Ssetje */ 5575648Ssetje if (size < MMU_PAGESIZE512K || 5585648Ssetje ((uintptr_t)base & MMU_PAGEOFFSET512K) != 0) { 5595648Ssetje prom_free(base, size); 5605648Ssetje return; 5615648Ssetje } 5625648Ssetje for (i = 3; i >= 0; i--) { 5635648Ssetje pgsz = page_get_pagesize(i); 5645648Ssetje if (size < pgsz) 5655648Ssetje continue; 5665648Ssetje len = size & ~(pgsz - 1); 5675648Ssetje prom_free(base, len); 5685648Ssetje base += len; 5695648Ssetje size -= len; 5705648Ssetje } 5715648Ssetje } 5725648Ssetje #endif /* C_OBP */ 5735648Ssetje 5745648Ssetje 5755648Ssetje /* 5765648Ssetje * Implementation of the "enter_mon" boot service. 5775648Ssetje */ 5785648Ssetje void 5795648Ssetje bop_enter_mon(void) 5805648Ssetje { 5815648Ssetje prom_enter_mon(); 5820Sstevel@tonic-gate } 5830Sstevel@tonic-gate 5840Sstevel@tonic-gate /* 5855648Ssetje * free elf info allocated by booter 5860Sstevel@tonic-gate */ 5870Sstevel@tonic-gate void 5885648Ssetje bop_free_elf(void) 5890Sstevel@tonic-gate { 5905648Ssetje uint32_t eadr; 5915648Ssetje uint32_t esize; 5925648Ssetje extern Addr dynseg; 5935648Ssetje extern size_t dynsize; 5945648Ssetje 5955648Ssetje if (bop_getprop("elfheader-address", (caddr_t)&eadr) == -1 || 5965648Ssetje bop_getprop("elfheader-length", (caddr_t)&esize) == -1) 5975648Ssetje prom_panic("missing elfheader"); 5985648Ssetje prom_free((caddr_t)(uintptr_t)eadr, roundup(esize, PAGESIZE)); 5995648Ssetje 6005648Ssetje prom_free((caddr_t)(uintptr_t)dynseg, roundup(dynsize, PAGESIZE)); 6015648Ssetje } 6025648Ssetje 6030Sstevel@tonic-gate 6045648Ssetje /* Simple message to indicate that the bootops pointer has been zeroed */ 6055648Ssetje #ifdef DEBUG 6065648Ssetje int bootops_gone_on = 0; 6075648Ssetje #define BOOTOPS_GONE() \ 6085648Ssetje if (bootops_gone_on) \ 6095648Ssetje prom_printf("The bootops vec is zeroed now!\n"); 6105648Ssetje #else 6115648Ssetje #define BOOTOPS_GONE() 6125648Ssetje #endif /* DEBUG */ 6135648Ssetje 6145648Ssetje void 6155648Ssetje bop_fini(void) 6165648Ssetje { 6175648Ssetje bop_free_archive(); 6185648Ssetje (void) bop_unmountroot(); 6195648Ssetje bop_free_elf(); 6205648Ssetje bop_temp_freeall(); 6215648Ssetje 6225648Ssetje bootops = (struct bootops *)NULL; 6235648Ssetje BOOTOPS_GONE(); 6240Sstevel@tonic-gate } 625