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*9956SWilliam.Roche@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate * Definitions of interfaces that provide services from the secondary
280Sstevel@tonic-gate * boot program to its clients (primarily Solaris, krtld, kmdb and their
290Sstevel@tonic-gate * successors.) This interface replaces the bootops (BOP) implementation
300Sstevel@tonic-gate * as the interface to be called by boot clients.
310Sstevel@tonic-gate *
320Sstevel@tonic-gate */
330Sstevel@tonic-gate
340Sstevel@tonic-gate #include <sys/types.h>
355648Ssetje #include <sys/systm.h>
360Sstevel@tonic-gate #include <sys/reboot.h>
370Sstevel@tonic-gate #include <sys/param.h>
380Sstevel@tonic-gate #include <sys/varargs.h>
390Sstevel@tonic-gate #include <sys/obpdefs.h>
405648Ssetje #include <sys/promimpl.h>
415648Ssetje #include <sys/prom_plat.h>
420Sstevel@tonic-gate #include <sys/bootconf.h>
430Sstevel@tonic-gate #include <sys/bootstat.h>
445648Ssetje #include <sys/kobj_impl.h>
450Sstevel@tonic-gate
465648Ssetje struct bootops *bootops;
475648Ssetje struct bootops kbootops;
485648Ssetje
495648Ssetje pnode_t chosennode;
50*9956SWilliam.Roche@Sun.COM /*
51*9956SWilliam.Roche@Sun.COM * Flag to disable the use of real ramdisks (in the OBP - on Sparc) when
52*9956SWilliam.Roche@Sun.COM * the associated memory is no longer available.
53*9956SWilliam.Roche@Sun.COM */
54*9956SWilliam.Roche@Sun.COM int bootops_obp_ramdisk_disabled = 0;
555648Ssetje
565648Ssetje #define FAKE_ROOT (pnode_t)1
575648Ssetje
585648Ssetje struct fakeprop {
595648Ssetje char *bootname;
605648Ssetje pnode_t promnode;
615648Ssetje char *promname;
625648Ssetje } fakeprops[] = {
635648Ssetje { "mfg-name", FAKE_ROOT, "name" },
645648Ssetje { NULL, 0, NULL }
655648Ssetje };
665648Ssetje
675648Ssetje static void
fakelook_init(void)685648Ssetje fakelook_init(void)
690Sstevel@tonic-gate {
705648Ssetje struct fakeprop *fpp = fakeprops;
715648Ssetje
725648Ssetje while (fpp->bootname != NULL) {
735648Ssetje switch (fpp->promnode) {
745648Ssetje case FAKE_ROOT:
755648Ssetje fpp->promnode = prom_rootnode();
765648Ssetje break;
775648Ssetje }
785648Ssetje fpp++;
795648Ssetje }
800Sstevel@tonic-gate }
810Sstevel@tonic-gate
825648Ssetje static struct fakeprop *
fakelook(const char * prop)835648Ssetje fakelook(const char *prop)
845648Ssetje {
855648Ssetje struct fakeprop *fpp = fakeprops;
865648Ssetje
875648Ssetje while (fpp->bootname != NULL) {
885648Ssetje if (strcmp(prop, fpp->bootname) == 0)
895648Ssetje return (fpp);
905648Ssetje fpp++;
915648Ssetje }
925648Ssetje return (NULL);
935648Ssetje }
945648Ssetje
955648Ssetje ihandle_t bfs_ih = OBP_BADNODE;
965648Ssetje ihandle_t afs_ih = OBP_BADNODE;
975648Ssetje
985648Ssetje void
bop_init(void)995648Ssetje bop_init(void)
1005648Ssetje {
1015648Ssetje chosennode = prom_chosennode();
1025648Ssetje
1035648Ssetje fakelook_init();
1045648Ssetje
1055648Ssetje /* fake bootops - it needs to point to non-NULL */
1065648Ssetje bootops = &kbootops;
1075648Ssetje }
1085648Ssetje
1095648Ssetje #define MAXPROMFD 16
1105648Ssetje
1115648Ssetje static ihandle_t prom_ihs[MAXPROMFD];
1125648Ssetje int filter_etc = 1;
1130Sstevel@tonic-gate
1140Sstevel@tonic-gate /*
1150Sstevel@tonic-gate * Implementation of the "open" boot service.
1160Sstevel@tonic-gate */
1175648Ssetje /*ARGSUSED*/
1180Sstevel@tonic-gate int
bop_open(const char * name,int flags)1195648Ssetje bop_open(const char *name, int flags)
1200Sstevel@tonic-gate {
1215648Ssetje int fd = -1, layered;
1225648Ssetje ihandle_t ih;
1235648Ssetje
1245648Ssetje /*
1255648Ssetje * Only look underneath archive for /etc files
1265648Ssetje */
1275648Ssetje layered = filter_etc ?
1285648Ssetje strncmp(name, "/etc", sizeof ("/etc") - 1) == 0 : 1;
1290Sstevel@tonic-gate
1305648Ssetje if (afs_ih != OBP_BADNODE) {
1315648Ssetje ih = afs_ih;
1325648Ssetje fd = prom_fopen(ih, (char *)name);
1335648Ssetje if (fd == -1 && !layered)
1345648Ssetje return (BOOT_SVC_FAIL);
1355648Ssetje }
1365648Ssetje if (fd == -1 && bfs_ih != OBP_BADNODE) {
1375648Ssetje ih = bfs_ih;
1385648Ssetje fd = prom_fopen(ih, (char *)name);
1395648Ssetje }
1405648Ssetje if (fd == -1)
1415648Ssetje return (BOOT_SVC_FAIL);
1425648Ssetje ASSERT(fd < MAXPROMFD);
1435648Ssetje ASSERT(prom_ihs[fd] == 0);
1445648Ssetje prom_ihs[fd] = ih;
1455648Ssetje return (fd);
1465648Ssetje }
1470Sstevel@tonic-gate
1485648Ssetje static void
spinner(void)1495648Ssetje spinner(void)
1505648Ssetje {
1515648Ssetje static int pos;
1525648Ssetje static char ind[] = "|/-\\"; /* that's entertainment? */
1535648Ssetje static int blks_read;
1545648Ssetje
1555648Ssetje if ((blks_read++ & 0x3) == 0)
1565648Ssetje prom_printf("%c\b", ind[pos++ & 3]);
1570Sstevel@tonic-gate }
1580Sstevel@tonic-gate
1590Sstevel@tonic-gate /*
1600Sstevel@tonic-gate * Implementation of the "read" boot service.
1610Sstevel@tonic-gate */
1620Sstevel@tonic-gate int
bop_read(int fd,caddr_t buf,size_t size)1635648Ssetje bop_read(int fd, caddr_t buf, size_t size)
1640Sstevel@tonic-gate {
1655648Ssetje ASSERT(prom_ihs[fd] != 0);
1665648Ssetje spinner();
1675648Ssetje return (prom_fread(prom_ihs[fd], fd, buf, size));
1680Sstevel@tonic-gate }
1690Sstevel@tonic-gate
1700Sstevel@tonic-gate /*
1710Sstevel@tonic-gate * Implementation of the "seek" boot service.
1720Sstevel@tonic-gate */
1730Sstevel@tonic-gate int
bop_seek(int fd,off_t off)1745648Ssetje bop_seek(int fd, off_t off)
1750Sstevel@tonic-gate {
1765648Ssetje ASSERT(prom_ihs[fd] != 0);
1775648Ssetje return (prom_fseek(prom_ihs[fd], fd, off));
1780Sstevel@tonic-gate }
1790Sstevel@tonic-gate
1800Sstevel@tonic-gate /*
1810Sstevel@tonic-gate * Implementation of the "close" boot service.
1820Sstevel@tonic-gate */
1830Sstevel@tonic-gate int
bop_close(int fd)1845648Ssetje bop_close(int fd)
1850Sstevel@tonic-gate {
1865648Ssetje ASSERT(prom_ihs[fd] != 0);
1875648Ssetje prom_fclose(prom_ihs[fd], fd);
1885648Ssetje prom_ihs[fd] = 0;
1895648Ssetje return (0);
1905648Ssetje }
1915648Ssetje
1925648Ssetje /*
1935648Ssetje * Simple temp memory allocator
1945648Ssetje *
1955648Ssetje * >PAGESIZE allocations are gotten directly from prom at bighand
1965648Ssetje * smaller ones are satisfied from littlehand, which does a
1975648Ssetje * 1 page bighand allocation when it runs out of memory
1985648Ssetje */
1995648Ssetje static caddr_t bighand = (caddr_t)BOOTTMPBASE;
2005648Ssetje static caddr_t littlehand = (caddr_t)BOOTTMPBASE;
2015648Ssetje
2025648Ssetje #define NTMPALLOC 128
2035648Ssetje
2045648Ssetje static caddr_t temp_base[NTMPALLOC];
2055648Ssetje static size_t temp_size[NTMPALLOC];
2065648Ssetje static int temp_indx;
2075648Ssetje
2085648Ssetje #if defined(C_OBP)
2095648Ssetje void cobp_free_mem(caddr_t, size_t);
2105648Ssetje #endif /* C_OBP */
2115648Ssetje
2125648Ssetje
2135648Ssetje /*
2145648Ssetje * temporary memory storage until bop_tmp_freeall is called
2155648Ssetje * (after the kernel heap is initialized)
2165648Ssetje */
2175648Ssetje caddr_t
bop_temp_alloc(size_t size,int align)2185648Ssetje bop_temp_alloc(size_t size, int align)
2195648Ssetje {
2205648Ssetje caddr_t ret;
2210Sstevel@tonic-gate
2225648Ssetje /*
2235648Ssetje * OBP allocs 10MB to boot, which is where virthint = 0
2245648Ssetje * memory was allocated from. Without boot, we allocate
2255648Ssetje * from BOOTTMPBASE and free when we're ready to take
2265648Ssetje * the machine from OBP
2275648Ssetje */
2285648Ssetje if (size < PAGESIZE) {
2295648Ssetje size_t left =
2305648Ssetje ALIGN(littlehand, PAGESIZE) - (uintptr_t)littlehand;
2315648Ssetje
2325648Ssetje size = roundup(size, MAX(align, 8));
2335648Ssetje if (size <= left) {
2345648Ssetje ret = littlehand;
2355648Ssetje littlehand += size;
2365648Ssetje return (ret);
2375648Ssetje }
2385648Ssetje littlehand = bighand + size;
2395648Ssetje }
2405648Ssetje size = roundup(size, PAGESIZE);
2415648Ssetje ret = prom_alloc(bighand, size, align);
2425648Ssetje if (ret == NULL)
2435648Ssetje prom_panic("boot temp overflow");
2445648Ssetje bighand += size;
2450Sstevel@tonic-gate
2465648Ssetje /* log it for bop_fini() */
2475648Ssetje temp_base[temp_indx] = ret;
2485648Ssetje temp_size[temp_indx] = size;
2495648Ssetje if (++temp_indx == NTMPALLOC)
2505648Ssetje prom_panic("out of bop temp space");
2515648Ssetje
2525648Ssetje return (ret);
2530Sstevel@tonic-gate }
2540Sstevel@tonic-gate
2555648Ssetje void
bop_temp_freeall(void)2565648Ssetje bop_temp_freeall(void)
2575648Ssetje {
2585648Ssetje int i;
2595648Ssetje
2605648Ssetje /*
2615648Ssetje * We have to call prom_free() with the same args
2625648Ssetje * as we used in prom_alloc()
2635648Ssetje */
2645648Ssetje for (i = 0; i < NTMPALLOC; i++) {
2655648Ssetje if (temp_base[i] == NULL)
2665648Ssetje break;
2675648Ssetje #if !defined(C_OBP)
2685648Ssetje prom_free(temp_base[i], temp_size[i]);
2695648Ssetje #else /* !C_OBP */
2705648Ssetje cobp_free_mem(temp_base[i], temp_size[i]);
2715648Ssetje #endif /* !C_OBP */
2725648Ssetje }
2735648Ssetje }
2745648Ssetje
2755648Ssetje
2760Sstevel@tonic-gate /*
2770Sstevel@tonic-gate * Implementation of the "alloc" boot service.
2780Sstevel@tonic-gate */
2790Sstevel@tonic-gate caddr_t
bop_alloc(caddr_t virthint,size_t size,int align)2805648Ssetje bop_alloc(caddr_t virthint, size_t size, int align)
2810Sstevel@tonic-gate {
2825648Ssetje if (virthint == NULL)
2835648Ssetje return (bop_temp_alloc(size, align));
2845648Ssetje return (prom_alloc(virthint, size, align));
2850Sstevel@tonic-gate }
2860Sstevel@tonic-gate
2877218Ssvemuri
2887218Ssvemuri /*
2897218Ssvemuri * Similar to bop_alloc functionality except that
2907218Ssvemuri * it will try to breakup into PAGESIZE chunk allocations
2917218Ssvemuri * if the original single chunk request failed.
2927218Ssvemuri * This routine does not guarantee physical contig
2937218Ssvemuri * allocation.
2947218Ssvemuri */
2957218Ssvemuri caddr_t
bop_alloc_chunk(caddr_t virthint,size_t size,int align)2967218Ssvemuri bop_alloc_chunk(caddr_t virthint, size_t size, int align)
2977218Ssvemuri {
2987218Ssvemuri caddr_t ret;
2997218Ssvemuri size_t chunksz;
3007218Ssvemuri
3017218Ssvemuri if (virthint == NULL)
3027218Ssvemuri return (bop_temp_alloc(size, align));
3037218Ssvemuri
3047218Ssvemuri if ((ret = prom_alloc(virthint, size, align)))
3057218Ssvemuri return (ret);
3067218Ssvemuri
3077218Ssvemuri /*
3087218Ssvemuri * Normal request to prom_alloc has failed.
3097218Ssvemuri * We will attempt to satisfy the request by allocating
3107218Ssvemuri * smaller chunks resulting in allocation that
3117218Ssvemuri * will be virtually contiguous but potentially
3127218Ssvemuri * not physically contiguous. There are additional
3137218Ssvemuri * requirements before we want to do this:
3147218Ssvemuri * 1. virthirt must be PAGESIZE aligned.
3157218Ssvemuri * 2. align must not be greater than PAGESIZE
3167218Ssvemuri * 3. size request must be at least PAGESIZE
3177218Ssvemuri * Otherwise, we will revert back to the original
3187218Ssvemuri * bop_alloc behavior i.e. return failure.
3197218Ssvemuri */
3207218Ssvemuri if (P2PHASE_TYPED(virthint, PAGESIZE, size_t) != 0 ||
3217218Ssvemuri align > PAGESIZE || size < PAGESIZE)
3227218Ssvemuri return (ret);
3237218Ssvemuri
3247218Ssvemuri /*
3257218Ssvemuri * Now we will break up the allocation
3267218Ssvemuri * request in smaller chunks that are
3277218Ssvemuri * always PAGESIZE aligned.
3287218Ssvemuri */
3297218Ssvemuri ret = virthint;
3307218Ssvemuri chunksz = P2ALIGN((size >> 1), PAGESIZE);
3317218Ssvemuri chunksz = MAX(chunksz, PAGESIZE);
3327218Ssvemuri
3337218Ssvemuri while (size) {
3347218Ssvemuri do {
3357218Ssvemuri /*LINTED E_FUNC_SET_NOT_USED*/
3367218Ssvemuri caddr_t res;
3377218Ssvemuri if ((res = prom_alloc(virthint, chunksz,
3387218Ssvemuri PAGESIZE))) {
3397218Ssvemuri ASSERT(virthint == res);
3407218Ssvemuri break;
3417218Ssvemuri }
3427218Ssvemuri
3437218Ssvemuri chunksz >>= 1;
3447218Ssvemuri chunksz = P2ALIGN(chunksz, PAGESIZE);
3457218Ssvemuri } while (chunksz >= PAGESIZE);
3467218Ssvemuri
3477218Ssvemuri if (chunksz < PAGESIZE)
3487218Ssvemuri /* Can't really happen.. */
3497218Ssvemuri prom_panic("bop_alloc_chunk failed");
3507218Ssvemuri
3517218Ssvemuri virthint += chunksz;
3527218Ssvemuri size -= chunksz;
3537218Ssvemuri if (size < chunksz)
3547218Ssvemuri chunksz = size;
3557218Ssvemuri }
3567218Ssvemuri return (ret);
3577218Ssvemuri }
3587218Ssvemuri
3597218Ssvemuri
3600Sstevel@tonic-gate /*
3610Sstevel@tonic-gate * Implementation of the "alloc_virt" boot service
3620Sstevel@tonic-gate */
3630Sstevel@tonic-gate caddr_t
bop_alloc_virt(caddr_t virt,size_t size)3645648Ssetje bop_alloc_virt(caddr_t virt, size_t size)
3650Sstevel@tonic-gate {
3665648Ssetje return (prom_claim_virt(size, virt));
3670Sstevel@tonic-gate }
3680Sstevel@tonic-gate
3690Sstevel@tonic-gate /*
3700Sstevel@tonic-gate * Implementation of the "free" boot service.
3710Sstevel@tonic-gate */
3720Sstevel@tonic-gate /*ARGSUSED*/
3730Sstevel@tonic-gate void
bop_free(caddr_t virt,size_t size)3745648Ssetje bop_free(caddr_t virt, size_t size)
3750Sstevel@tonic-gate {
3765648Ssetje prom_free(virt, size);
3770Sstevel@tonic-gate }
3780Sstevel@tonic-gate
3790Sstevel@tonic-gate
3800Sstevel@tonic-gate
3810Sstevel@tonic-gate /*
3820Sstevel@tonic-gate * Implementation of the "getproplen" boot service.
3830Sstevel@tonic-gate */
3840Sstevel@tonic-gate /*ARGSUSED*/
3850Sstevel@tonic-gate int
bop_getproplen(const char * name)3865648Ssetje bop_getproplen(const char *name)
3870Sstevel@tonic-gate {
3885648Ssetje struct fakeprop *fpp;
3895648Ssetje pnode_t node;
3905648Ssetje char *prop;
3910Sstevel@tonic-gate
3925648Ssetje fpp = fakelook(name);
3935648Ssetje if (fpp != NULL) {
3945648Ssetje node = fpp->promnode;
3955648Ssetje prop = fpp->promname;
3965648Ssetje } else {
3975648Ssetje node = chosennode;
3985648Ssetje prop = (char *)name;
3995648Ssetje }
4005648Ssetje return (prom_getproplen(node, prop));
4010Sstevel@tonic-gate }
4020Sstevel@tonic-gate
4030Sstevel@tonic-gate /*
4040Sstevel@tonic-gate * Implementation of the "getprop" boot service.
4050Sstevel@tonic-gate */
4060Sstevel@tonic-gate /*ARGSUSED*/
4070Sstevel@tonic-gate int
bop_getprop(const char * name,void * value)4085648Ssetje bop_getprop(const char *name, void *value)
4090Sstevel@tonic-gate {
4105648Ssetje struct fakeprop *fpp;
4115648Ssetje pnode_t node;
4125648Ssetje char *prop;
4130Sstevel@tonic-gate
4145648Ssetje fpp = fakelook(name);
4155648Ssetje if (fpp != NULL) {
4165648Ssetje node = fpp->promnode;
4175648Ssetje prop = fpp->promname;
4185648Ssetje } else {
4195648Ssetje node = chosennode;
4205648Ssetje prop = (char *)name;
4215648Ssetje }
4225648Ssetje return (prom_getprop(node, prop, value));
4230Sstevel@tonic-gate }
4240Sstevel@tonic-gate
4250Sstevel@tonic-gate /*
4265648Ssetje * Implementation of the "print" boot service.
4270Sstevel@tonic-gate */
4280Sstevel@tonic-gate /*ARGSUSED*/
4290Sstevel@tonic-gate void
bop_printf(void * ops,const char * fmt,...)4305648Ssetje bop_printf(void *ops, const char *fmt, ...)
4310Sstevel@tonic-gate {
4325648Ssetje va_list adx;
4330Sstevel@tonic-gate
4345648Ssetje va_start(adx, fmt);
4355648Ssetje prom_vprintf(fmt, adx);
4365648Ssetje va_end(adx);
4370Sstevel@tonic-gate }
4380Sstevel@tonic-gate
4390Sstevel@tonic-gate /*
4405648Ssetje * Special routine for kmdb
4410Sstevel@tonic-gate */
4420Sstevel@tonic-gate void
bop_putsarg(const char * fmt,char * arg)4435648Ssetje bop_putsarg(const char *fmt, char *arg)
4440Sstevel@tonic-gate {
4455648Ssetje prom_printf(fmt, arg);
4465648Ssetje }
4470Sstevel@tonic-gate
4485648Ssetje /*
4495648Ssetje * panic for krtld only
4505648Ssetje */
4515648Ssetje void
bop_panic(const char * s)4525648Ssetje bop_panic(const char *s)
4535648Ssetje {
4545648Ssetje prom_panic((char *)s);
4550Sstevel@tonic-gate }
4560Sstevel@tonic-gate
4570Sstevel@tonic-gate /*
4580Sstevel@tonic-gate * Implementation of the "mount" boot service.
4590Sstevel@tonic-gate *
4600Sstevel@tonic-gate */
4610Sstevel@tonic-gate /*ARGSUSED*/
4620Sstevel@tonic-gate int
bop_mountroot(void)4635648Ssetje bop_mountroot(void)
4640Sstevel@tonic-gate {
4655648Ssetje (void) prom_getprop(chosennode, "bootfs", (caddr_t)&bfs_ih);
4665648Ssetje (void) prom_getprop(chosennode, "archfs", (caddr_t)&afs_ih);
4675648Ssetje return ((bfs_ih == -1 && afs_ih == -1) ? BOOT_SVC_FAIL : BOOT_SVC_OK);
4680Sstevel@tonic-gate }
4690Sstevel@tonic-gate
4700Sstevel@tonic-gate /*
4710Sstevel@tonic-gate * Implementation of the "unmountroot" boot service.
4720Sstevel@tonic-gate */
4730Sstevel@tonic-gate /*ARGSUSED*/
4740Sstevel@tonic-gate int
bop_unmountroot(void)4755648Ssetje bop_unmountroot(void)
4760Sstevel@tonic-gate {
4770Sstevel@tonic-gate
4785648Ssetje if (bfs_ih != OBP_BADNODE) {
4795648Ssetje (void) prom_close(bfs_ih);
4805648Ssetje bfs_ih = OBP_BADNODE;
4815648Ssetje }
4825648Ssetje if (afs_ih != OBP_BADNODE) {
4835648Ssetje (void) prom_close(afs_ih);
4845648Ssetje afs_ih = OBP_BADNODE;
4855648Ssetje }
4865648Ssetje return (BOOT_SVC_OK);
4870Sstevel@tonic-gate }
4880Sstevel@tonic-gate
4890Sstevel@tonic-gate /*
4900Sstevel@tonic-gate * Implementation of the "fstat" boot service.
4910Sstevel@tonic-gate */
4920Sstevel@tonic-gate int
bop_fstat(int fd,struct bootstat * st)4935648Ssetje bop_fstat(int fd, struct bootstat *st)
4945648Ssetje {
4955648Ssetje ASSERT(prom_ihs[fd] != 0);
4965648Ssetje return (prom_fsize(prom_ihs[fd], fd, (size_t *)&st->st_size));
4975648Ssetje }
4985648Ssetje
4995648Ssetje int
boot_compinfo(int fd,struct compinfo * cb)5005648Ssetje boot_compinfo(int fd, struct compinfo *cb)
5015648Ssetje {
5025648Ssetje ASSERT(prom_ihs[fd] != 0);
5035648Ssetje return (prom_compinfo(prom_ihs[fd], fd,
5045648Ssetje &cb->iscmp, &cb->fsize, &cb->blksize));
5055648Ssetje }
5065648Ssetje
5075648Ssetje void
bop_free_archive(void)5085648Ssetje bop_free_archive(void)
5090Sstevel@tonic-gate {
5105648Ssetje char archive[OBP_MAXPATHLEN];
5115648Ssetje pnode_t arph;
5125648Ssetje uint32_t arbase, arsize, alloc_size;
5135648Ssetje
5145648Ssetje /*
5155648Ssetje * If the ramdisk will eventually be root, or we weren't
5165648Ssetje * booted via the archive, then nothing to do here
5175648Ssetje */
5185648Ssetje if (root_is_ramdisk == B_TRUE ||
5195648Ssetje prom_getprop(chosennode, "bootarchive", archive) == -1)
5205648Ssetje return;
5215648Ssetje arph = prom_finddevice(archive);
5225648Ssetje if (arph == -1 ||
5235648Ssetje prom_getprop(arph, OBP_ALLOCSIZE, (caddr_t)&alloc_size) == -1 ||
5245648Ssetje prom_getprop(arph, OBP_SIZE, (caddr_t)&arsize) == -1 ||
5255648Ssetje prom_getprop(arph, OBP_ADDRESS, (caddr_t)&arbase) == -1)
5265648Ssetje prom_panic("can't free boot archive");
5275648Ssetje
528*9956SWilliam.Roche@Sun.COM bootops_obp_ramdisk_disabled = 1;
529*9956SWilliam.Roche@Sun.COM
5305648Ssetje #if !defined(C_OBP)
5315648Ssetje if (alloc_size == 0)
5325648Ssetje prom_free((caddr_t)(uintptr_t)arbase, arsize);
5335648Ssetje else {
5345648Ssetje uint32_t arend = arbase + arsize;
5350Sstevel@tonic-gate
5365648Ssetje while (arbase < arend) {
5375648Ssetje prom_free((caddr_t)(uintptr_t)arbase,
5385648Ssetje MIN(alloc_size, arend - arbase));
5395648Ssetje arbase += alloc_size;
5405648Ssetje }
5415648Ssetje }
5425648Ssetje #else /* !C_OBP */
5435648Ssetje cobp_free_mem((caddr_t)(uintptr_t)arbase, arsize);
5445648Ssetje #endif /* !C_OBP */
5455648Ssetje }
5465648Ssetje
5475648Ssetje #if defined(C_OBP)
5485648Ssetje /*
5495648Ssetje * Blech. The C proms have a bug when freeing areas that cross
5505648Ssetje * page sizes, so we have to break up the free into sections
5515648Ssetje * bounded by the various pagesizes.
5525648Ssetje */
5535648Ssetje void
cobp_free_mem(caddr_t base,size_t size)5545648Ssetje cobp_free_mem(caddr_t base, size_t size)
5555648Ssetje {
5565648Ssetje int i;
5575648Ssetje size_t len, pgsz;
5585648Ssetje
5595648Ssetje /*
5605648Ssetje * Large pages only used when size > 512k
5615648Ssetje */
5625648Ssetje if (size < MMU_PAGESIZE512K ||
5635648Ssetje ((uintptr_t)base & MMU_PAGEOFFSET512K) != 0) {
5645648Ssetje prom_free(base, size);
5655648Ssetje return;
5665648Ssetje }
5675648Ssetje for (i = 3; i >= 0; i--) {
5685648Ssetje pgsz = page_get_pagesize(i);
5695648Ssetje if (size < pgsz)
5705648Ssetje continue;
5715648Ssetje len = size & ~(pgsz - 1);
5725648Ssetje prom_free(base, len);
5735648Ssetje base += len;
5745648Ssetje size -= len;
5755648Ssetje }
5765648Ssetje }
5775648Ssetje #endif /* C_OBP */
5785648Ssetje
5795648Ssetje
5805648Ssetje /*
5815648Ssetje * Implementation of the "enter_mon" boot service.
5825648Ssetje */
5835648Ssetje void
bop_enter_mon(void)5845648Ssetje bop_enter_mon(void)
5855648Ssetje {
5865648Ssetje prom_enter_mon();
5870Sstevel@tonic-gate }
5880Sstevel@tonic-gate
5890Sstevel@tonic-gate /*
5905648Ssetje * free elf info allocated by booter
5910Sstevel@tonic-gate */
5920Sstevel@tonic-gate void
bop_free_elf(void)5935648Ssetje bop_free_elf(void)
5940Sstevel@tonic-gate {
5955648Ssetje uint32_t eadr;
5965648Ssetje uint32_t esize;
5975648Ssetje extern Addr dynseg;
5985648Ssetje extern size_t dynsize;
5995648Ssetje
6005648Ssetje if (bop_getprop("elfheader-address", (caddr_t)&eadr) == -1 ||
6015648Ssetje bop_getprop("elfheader-length", (caddr_t)&esize) == -1)
6025648Ssetje prom_panic("missing elfheader");
6035648Ssetje prom_free((caddr_t)(uintptr_t)eadr, roundup(esize, PAGESIZE));
6045648Ssetje
6055648Ssetje prom_free((caddr_t)(uintptr_t)dynseg, roundup(dynsize, PAGESIZE));
6065648Ssetje }
6075648Ssetje
6080Sstevel@tonic-gate
6095648Ssetje /* Simple message to indicate that the bootops pointer has been zeroed */
6105648Ssetje #ifdef DEBUG
6115648Ssetje int bootops_gone_on = 0;
6125648Ssetje #define BOOTOPS_GONE() \
6135648Ssetje if (bootops_gone_on) \
6145648Ssetje prom_printf("The bootops vec is zeroed now!\n");
6155648Ssetje #else
6165648Ssetje #define BOOTOPS_GONE()
6175648Ssetje #endif /* DEBUG */
6185648Ssetje
6195648Ssetje void
bop_fini(void)6205648Ssetje bop_fini(void)
6215648Ssetje {
6225648Ssetje bop_free_archive();
6235648Ssetje (void) bop_unmountroot();
6245648Ssetje bop_free_elf();
6255648Ssetje bop_temp_freeall();
6265648Ssetje
6275648Ssetje bootops = (struct bootops *)NULL;
6285648Ssetje BOOTOPS_GONE();
6290Sstevel@tonic-gate }
630