xref: /titanic_44/usr/src/uts/sparc/os/bootops.c (revision 986fd29a0dc13f7608ef7f508f6e700bd7bc2720)
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