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
5986fd29aSsetje * Common Development and Distribution License (the "License").
6986fd29aSsetje * 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 /*
223f9058a8SWilliam Roche * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate * Definitions of interfaces that provide services from the secondary
287c478bd9Sstevel@tonic-gate * boot program to its clients (primarily Solaris, krtld, kmdb and their
297c478bd9Sstevel@tonic-gate * successors.) This interface replaces the bootops (BOP) implementation
307c478bd9Sstevel@tonic-gate * as the interface to be called by boot clients.
317c478bd9Sstevel@tonic-gate *
327c478bd9Sstevel@tonic-gate */
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gate #include <sys/types.h>
35986fd29aSsetje #include <sys/systm.h>
367c478bd9Sstevel@tonic-gate #include <sys/reboot.h>
377c478bd9Sstevel@tonic-gate #include <sys/param.h>
387c478bd9Sstevel@tonic-gate #include <sys/varargs.h>
397c478bd9Sstevel@tonic-gate #include <sys/obpdefs.h>
40986fd29aSsetje #include <sys/promimpl.h>
41986fd29aSsetje #include <sys/prom_plat.h>
427c478bd9Sstevel@tonic-gate #include <sys/bootconf.h>
437c478bd9Sstevel@tonic-gate #include <sys/bootstat.h>
44986fd29aSsetje #include <sys/kobj_impl.h>
457c478bd9Sstevel@tonic-gate
46986fd29aSsetje struct bootops *bootops;
47986fd29aSsetje struct bootops kbootops;
48986fd29aSsetje
49986fd29aSsetje pnode_t chosennode;
503f9058a8SWilliam Roche /*
513f9058a8SWilliam Roche * Flag to disable the use of real ramdisks (in the OBP - on Sparc) when
523f9058a8SWilliam Roche * the associated memory is no longer available.
533f9058a8SWilliam Roche */
543f9058a8SWilliam Roche int bootops_obp_ramdisk_disabled = 0;
55986fd29aSsetje
56986fd29aSsetje #define FAKE_ROOT (pnode_t)1
57986fd29aSsetje
58986fd29aSsetje struct fakeprop {
59986fd29aSsetje char *bootname;
60986fd29aSsetje pnode_t promnode;
61986fd29aSsetje char *promname;
62986fd29aSsetje } fakeprops[] = {
63986fd29aSsetje { "mfg-name", FAKE_ROOT, "name" },
64986fd29aSsetje { NULL, 0, NULL }
65986fd29aSsetje };
66986fd29aSsetje
67986fd29aSsetje static void
fakelook_init(void)68986fd29aSsetje fakelook_init(void)
697c478bd9Sstevel@tonic-gate {
70986fd29aSsetje struct fakeprop *fpp = fakeprops;
71986fd29aSsetje
72986fd29aSsetje while (fpp->bootname != NULL) {
73986fd29aSsetje switch (fpp->promnode) {
74986fd29aSsetje case FAKE_ROOT:
75986fd29aSsetje fpp->promnode = prom_rootnode();
76986fd29aSsetje break;
77986fd29aSsetje }
78986fd29aSsetje fpp++;
79986fd29aSsetje }
80986fd29aSsetje }
81986fd29aSsetje
82986fd29aSsetje static struct fakeprop *
fakelook(const char * prop)83986fd29aSsetje fakelook(const char *prop)
84986fd29aSsetje {
85986fd29aSsetje struct fakeprop *fpp = fakeprops;
86986fd29aSsetje
87986fd29aSsetje while (fpp->bootname != NULL) {
88986fd29aSsetje if (strcmp(prop, fpp->bootname) == 0)
89986fd29aSsetje return (fpp);
90986fd29aSsetje fpp++;
91986fd29aSsetje }
92986fd29aSsetje return (NULL);
937c478bd9Sstevel@tonic-gate }
947c478bd9Sstevel@tonic-gate
95986fd29aSsetje ihandle_t bfs_ih = OBP_BADNODE;
96986fd29aSsetje ihandle_t afs_ih = OBP_BADNODE;
97986fd29aSsetje
98986fd29aSsetje void
bop_init(void)99986fd29aSsetje bop_init(void)
100986fd29aSsetje {
101986fd29aSsetje chosennode = prom_chosennode();
102986fd29aSsetje
103986fd29aSsetje fakelook_init();
104986fd29aSsetje
105986fd29aSsetje /* fake bootops - it needs to point to non-NULL */
106986fd29aSsetje bootops = &kbootops;
107986fd29aSsetje }
108986fd29aSsetje
109986fd29aSsetje #define MAXPROMFD 16
110986fd29aSsetje
111986fd29aSsetje static ihandle_t prom_ihs[MAXPROMFD];
112986fd29aSsetje int filter_etc = 1;
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate /*
1157c478bd9Sstevel@tonic-gate * Implementation of the "open" boot service.
1167c478bd9Sstevel@tonic-gate */
117986fd29aSsetje /*ARGSUSED*/
1187c478bd9Sstevel@tonic-gate int
bop_open(const char * name,int flags)119986fd29aSsetje bop_open(const char *name, int flags)
120986fd29aSsetje {
121986fd29aSsetje int fd = -1, layered;
122986fd29aSsetje ihandle_t ih;
123986fd29aSsetje
124986fd29aSsetje /*
125986fd29aSsetje * Only look underneath archive for /etc files
126986fd29aSsetje */
127986fd29aSsetje layered = filter_etc ?
128986fd29aSsetje strncmp(name, "/etc", sizeof ("/etc") - 1) == 0 : 1;
129986fd29aSsetje
130986fd29aSsetje if (afs_ih != OBP_BADNODE) {
131986fd29aSsetje ih = afs_ih;
132986fd29aSsetje fd = prom_fopen(ih, (char *)name);
133986fd29aSsetje if (fd == -1 && !layered)
134986fd29aSsetje return (BOOT_SVC_FAIL);
135986fd29aSsetje }
136986fd29aSsetje if (fd == -1 && bfs_ih != OBP_BADNODE) {
137986fd29aSsetje ih = bfs_ih;
138986fd29aSsetje fd = prom_fopen(ih, (char *)name);
139986fd29aSsetje }
140986fd29aSsetje if (fd == -1)
141986fd29aSsetje return (BOOT_SVC_FAIL);
142986fd29aSsetje ASSERT(fd < MAXPROMFD);
143986fd29aSsetje ASSERT(prom_ihs[fd] == 0);
144986fd29aSsetje prom_ihs[fd] = ih;
145986fd29aSsetje return (fd);
146986fd29aSsetje }
147986fd29aSsetje
148986fd29aSsetje static void
spinner(void)149986fd29aSsetje spinner(void)
1507c478bd9Sstevel@tonic-gate {
151986fd29aSsetje static int pos;
152986fd29aSsetje static char ind[] = "|/-\\"; /* that's entertainment? */
153986fd29aSsetje static int blks_read;
154986fd29aSsetje
155986fd29aSsetje if ((blks_read++ & 0x3) == 0)
156986fd29aSsetje prom_printf("%c\b", ind[pos++ & 3]);
1577c478bd9Sstevel@tonic-gate }
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate /*
1607c478bd9Sstevel@tonic-gate * Implementation of the "read" boot service.
1617c478bd9Sstevel@tonic-gate */
1627c478bd9Sstevel@tonic-gate int
bop_read(int fd,caddr_t buf,size_t size)163986fd29aSsetje bop_read(int fd, caddr_t buf, size_t size)
1647c478bd9Sstevel@tonic-gate {
165986fd29aSsetje ASSERT(prom_ihs[fd] != 0);
166986fd29aSsetje spinner();
167986fd29aSsetje return (prom_fread(prom_ihs[fd], fd, buf, size));
1687c478bd9Sstevel@tonic-gate }
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate /*
1717c478bd9Sstevel@tonic-gate * Implementation of the "seek" boot service.
1727c478bd9Sstevel@tonic-gate */
1737c478bd9Sstevel@tonic-gate int
bop_seek(int fd,off_t off)174986fd29aSsetje bop_seek(int fd, off_t off)
1757c478bd9Sstevel@tonic-gate {
176986fd29aSsetje ASSERT(prom_ihs[fd] != 0);
177986fd29aSsetje return (prom_fseek(prom_ihs[fd], fd, off));
1787c478bd9Sstevel@tonic-gate }
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate /*
1817c478bd9Sstevel@tonic-gate * Implementation of the "close" boot service.
1827c478bd9Sstevel@tonic-gate */
1837c478bd9Sstevel@tonic-gate int
bop_close(int fd)184986fd29aSsetje bop_close(int fd)
1857c478bd9Sstevel@tonic-gate {
186986fd29aSsetje ASSERT(prom_ihs[fd] != 0);
187986fd29aSsetje prom_fclose(prom_ihs[fd], fd);
188986fd29aSsetje prom_ihs[fd] = 0;
189986fd29aSsetje return (0);
1907c478bd9Sstevel@tonic-gate }
1917c478bd9Sstevel@tonic-gate
1927c478bd9Sstevel@tonic-gate /*
193986fd29aSsetje * Simple temp memory allocator
1947c478bd9Sstevel@tonic-gate *
195986fd29aSsetje * >PAGESIZE allocations are gotten directly from prom at bighand
196986fd29aSsetje * smaller ones are satisfied from littlehand, which does a
197986fd29aSsetje * 1 page bighand allocation when it runs out of memory
1987c478bd9Sstevel@tonic-gate */
199986fd29aSsetje static caddr_t bighand = (caddr_t)BOOTTMPBASE;
200986fd29aSsetje static caddr_t littlehand = (caddr_t)BOOTTMPBASE;
201986fd29aSsetje
202986fd29aSsetje #define NTMPALLOC 128
203986fd29aSsetje
204986fd29aSsetje static caddr_t temp_base[NTMPALLOC];
205986fd29aSsetje static size_t temp_size[NTMPALLOC];
206986fd29aSsetje static int temp_indx;
207986fd29aSsetje
208986fd29aSsetje #if defined(C_OBP)
209986fd29aSsetje void cobp_free_mem(caddr_t, size_t);
210986fd29aSsetje #endif /* C_OBP */
211986fd29aSsetje
2127c478bd9Sstevel@tonic-gate
2137c478bd9Sstevel@tonic-gate /*
214986fd29aSsetje * temporary memory storage until bop_tmp_freeall is called
215986fd29aSsetje * (after the kernel heap is initialized)
2167c478bd9Sstevel@tonic-gate */
2177c478bd9Sstevel@tonic-gate caddr_t
bop_temp_alloc(size_t size,int align)218986fd29aSsetje bop_temp_alloc(size_t size, int align)
2197c478bd9Sstevel@tonic-gate {
220986fd29aSsetje caddr_t ret;
221986fd29aSsetje
222986fd29aSsetje /*
223986fd29aSsetje * OBP allocs 10MB to boot, which is where virthint = 0
224986fd29aSsetje * memory was allocated from. Without boot, we allocate
225986fd29aSsetje * from BOOTTMPBASE and free when we're ready to take
226986fd29aSsetje * the machine from OBP
227986fd29aSsetje */
228986fd29aSsetje if (size < PAGESIZE) {
229986fd29aSsetje size_t left =
230986fd29aSsetje ALIGN(littlehand, PAGESIZE) - (uintptr_t)littlehand;
231986fd29aSsetje
232986fd29aSsetje size = roundup(size, MAX(align, 8));
233986fd29aSsetje if (size <= left) {
234986fd29aSsetje ret = littlehand;
235986fd29aSsetje littlehand += size;
236986fd29aSsetje return (ret);
237986fd29aSsetje }
238986fd29aSsetje littlehand = bighand + size;
239986fd29aSsetje }
240986fd29aSsetje size = roundup(size, PAGESIZE);
241986fd29aSsetje ret = prom_alloc(bighand, size, align);
242986fd29aSsetje if (ret == NULL)
243986fd29aSsetje prom_panic("boot temp overflow");
244986fd29aSsetje bighand += size;
245986fd29aSsetje
246986fd29aSsetje /* log it for bop_fini() */
247986fd29aSsetje temp_base[temp_indx] = ret;
248986fd29aSsetje temp_size[temp_indx] = size;
249986fd29aSsetje if (++temp_indx == NTMPALLOC)
250986fd29aSsetje prom_panic("out of bop temp space");
251986fd29aSsetje
252986fd29aSsetje return (ret);
2537c478bd9Sstevel@tonic-gate }
2547c478bd9Sstevel@tonic-gate
2557c478bd9Sstevel@tonic-gate void
bop_temp_freeall(void)256986fd29aSsetje bop_temp_freeall(void)
2577c478bd9Sstevel@tonic-gate {
258986fd29aSsetje int i;
259986fd29aSsetje
260986fd29aSsetje /*
261986fd29aSsetje * We have to call prom_free() with the same args
262986fd29aSsetje * as we used in prom_alloc()
263986fd29aSsetje */
264986fd29aSsetje for (i = 0; i < NTMPALLOC; i++) {
265986fd29aSsetje if (temp_base[i] == NULL)
266986fd29aSsetje break;
267986fd29aSsetje #if !defined(C_OBP)
268986fd29aSsetje prom_free(temp_base[i], temp_size[i]);
269986fd29aSsetje #else /* !C_OBP */
270986fd29aSsetje cobp_free_mem(temp_base[i], temp_size[i]);
271986fd29aSsetje #endif /* !C_OBP */
272986fd29aSsetje }
2737c478bd9Sstevel@tonic-gate }
2747c478bd9Sstevel@tonic-gate
275986fd29aSsetje
2767c478bd9Sstevel@tonic-gate /*
277986fd29aSsetje * Implementation of the "alloc" boot service.
2787c478bd9Sstevel@tonic-gate */
2797c478bd9Sstevel@tonic-gate caddr_t
bop_alloc(caddr_t virthint,size_t size,int align)280986fd29aSsetje bop_alloc(caddr_t virthint, size_t size, int align)
2817c478bd9Sstevel@tonic-gate {
282986fd29aSsetje if (virthint == NULL)
283986fd29aSsetje return (bop_temp_alloc(size, align));
284986fd29aSsetje return (prom_alloc(virthint, size, align));
2857c478bd9Sstevel@tonic-gate }
2867c478bd9Sstevel@tonic-gate
287ca622e3aSsvemuri
288ca622e3aSsvemuri /*
289ca622e3aSsvemuri * Similar to bop_alloc functionality except that
290ca622e3aSsvemuri * it will try to breakup into PAGESIZE chunk allocations
291ca622e3aSsvemuri * if the original single chunk request failed.
292ca622e3aSsvemuri * This routine does not guarantee physical contig
293ca622e3aSsvemuri * allocation.
294ca622e3aSsvemuri */
295ca622e3aSsvemuri caddr_t
bop_alloc_chunk(caddr_t virthint,size_t size,int align)296ca622e3aSsvemuri bop_alloc_chunk(caddr_t virthint, size_t size, int align)
297ca622e3aSsvemuri {
298ca622e3aSsvemuri caddr_t ret;
299ca622e3aSsvemuri size_t chunksz;
300ca622e3aSsvemuri
301ca622e3aSsvemuri if (virthint == NULL)
302ca622e3aSsvemuri return (bop_temp_alloc(size, align));
303ca622e3aSsvemuri
304ca622e3aSsvemuri if ((ret = prom_alloc(virthint, size, align)))
305ca622e3aSsvemuri return (ret);
306ca622e3aSsvemuri
307ca622e3aSsvemuri /*
308ca622e3aSsvemuri * Normal request to prom_alloc has failed.
309ca622e3aSsvemuri * We will attempt to satisfy the request by allocating
310ca622e3aSsvemuri * smaller chunks resulting in allocation that
311ca622e3aSsvemuri * will be virtually contiguous but potentially
312ca622e3aSsvemuri * not physically contiguous. There are additional
313ca622e3aSsvemuri * requirements before we want to do this:
314ca622e3aSsvemuri * 1. virthirt must be PAGESIZE aligned.
315ca622e3aSsvemuri * 2. align must not be greater than PAGESIZE
316ca622e3aSsvemuri * 3. size request must be at least PAGESIZE
317ca622e3aSsvemuri * Otherwise, we will revert back to the original
318ca622e3aSsvemuri * bop_alloc behavior i.e. return failure.
319ca622e3aSsvemuri */
320ca622e3aSsvemuri if (P2PHASE_TYPED(virthint, PAGESIZE, size_t) != 0 ||
321ca622e3aSsvemuri align > PAGESIZE || size < PAGESIZE)
322ca622e3aSsvemuri return (ret);
323ca622e3aSsvemuri
324ca622e3aSsvemuri /*
325ca622e3aSsvemuri * Now we will break up the allocation
326ca622e3aSsvemuri * request in smaller chunks that are
327ca622e3aSsvemuri * always PAGESIZE aligned.
328ca622e3aSsvemuri */
329ca622e3aSsvemuri ret = virthint;
330ca622e3aSsvemuri chunksz = P2ALIGN((size >> 1), PAGESIZE);
331ca622e3aSsvemuri chunksz = MAX(chunksz, PAGESIZE);
332ca622e3aSsvemuri
333ca622e3aSsvemuri while (size) {
334ca622e3aSsvemuri do {
335ca622e3aSsvemuri /*LINTED E_FUNC_SET_NOT_USED*/
336ca622e3aSsvemuri caddr_t res;
337ca622e3aSsvemuri if ((res = prom_alloc(virthint, chunksz,
338ca622e3aSsvemuri PAGESIZE))) {
339ca622e3aSsvemuri ASSERT(virthint == res);
340ca622e3aSsvemuri break;
341ca622e3aSsvemuri }
342ca622e3aSsvemuri
343ca622e3aSsvemuri chunksz >>= 1;
344ca622e3aSsvemuri chunksz = P2ALIGN(chunksz, PAGESIZE);
345ca622e3aSsvemuri } while (chunksz >= PAGESIZE);
346ca622e3aSsvemuri
347ca622e3aSsvemuri if (chunksz < PAGESIZE)
348ca622e3aSsvemuri /* Can't really happen.. */
349ca622e3aSsvemuri prom_panic("bop_alloc_chunk failed");
350ca622e3aSsvemuri
351ca622e3aSsvemuri virthint += chunksz;
352ca622e3aSsvemuri size -= chunksz;
353ca622e3aSsvemuri if (size < chunksz)
354ca622e3aSsvemuri chunksz = size;
355ca622e3aSsvemuri }
356ca622e3aSsvemuri return (ret);
357ca622e3aSsvemuri }
358ca622e3aSsvemuri
359ca622e3aSsvemuri
3607c478bd9Sstevel@tonic-gate /*
361986fd29aSsetje * Implementation of the "alloc_virt" boot service
3627c478bd9Sstevel@tonic-gate */
363986fd29aSsetje caddr_t
bop_alloc_virt(caddr_t virt,size_t size)364986fd29aSsetje bop_alloc_virt(caddr_t virt, size_t size)
3657c478bd9Sstevel@tonic-gate {
366986fd29aSsetje return (prom_claim_virt(size, virt));
3677c478bd9Sstevel@tonic-gate }
3687c478bd9Sstevel@tonic-gate
3697c478bd9Sstevel@tonic-gate /*
370986fd29aSsetje * Implementation of the "free" boot service.
3717c478bd9Sstevel@tonic-gate */
3727c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3737c478bd9Sstevel@tonic-gate void
bop_free(caddr_t virt,size_t size)374986fd29aSsetje bop_free(caddr_t virt, size_t size)
3757c478bd9Sstevel@tonic-gate {
376986fd29aSsetje prom_free(virt, size);
377986fd29aSsetje }
3787c478bd9Sstevel@tonic-gate
3797c478bd9Sstevel@tonic-gate
3807c478bd9Sstevel@tonic-gate
3817c478bd9Sstevel@tonic-gate /*
3827c478bd9Sstevel@tonic-gate * Implementation of the "getproplen" boot service.
3837c478bd9Sstevel@tonic-gate */
3847c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3857c478bd9Sstevel@tonic-gate int
bop_getproplen(const char * name)386986fd29aSsetje bop_getproplen(const char *name)
3877c478bd9Sstevel@tonic-gate {
388986fd29aSsetje struct fakeprop *fpp;
389986fd29aSsetje pnode_t node;
390986fd29aSsetje char *prop;
391986fd29aSsetje
392986fd29aSsetje fpp = fakelook(name);
393986fd29aSsetje if (fpp != NULL) {
394986fd29aSsetje node = fpp->promnode;
395986fd29aSsetje prop = fpp->promname;
396986fd29aSsetje } else {
397986fd29aSsetje node = chosennode;
398986fd29aSsetje prop = (char *)name;
399986fd29aSsetje }
400986fd29aSsetje return (prom_getproplen(node, prop));
4017c478bd9Sstevel@tonic-gate }
4027c478bd9Sstevel@tonic-gate
4037c478bd9Sstevel@tonic-gate /*
4047c478bd9Sstevel@tonic-gate * Implementation of the "getprop" boot service.
4057c478bd9Sstevel@tonic-gate */
4067c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4077c478bd9Sstevel@tonic-gate int
bop_getprop(const char * name,void * value)408986fd29aSsetje bop_getprop(const char *name, void *value)
4097c478bd9Sstevel@tonic-gate {
410986fd29aSsetje struct fakeprop *fpp;
411986fd29aSsetje pnode_t node;
412986fd29aSsetje char *prop;
413986fd29aSsetje
414986fd29aSsetje fpp = fakelook(name);
415986fd29aSsetje if (fpp != NULL) {
416986fd29aSsetje node = fpp->promnode;
417986fd29aSsetje prop = fpp->promname;
418986fd29aSsetje } else {
419986fd29aSsetje node = chosennode;
420986fd29aSsetje prop = (char *)name;
421986fd29aSsetje }
422986fd29aSsetje return (prom_getprop(node, prop, value));
4237c478bd9Sstevel@tonic-gate }
4247c478bd9Sstevel@tonic-gate
4257c478bd9Sstevel@tonic-gate /*
426986fd29aSsetje * Implementation of the "print" boot service.
4277c478bd9Sstevel@tonic-gate */
4287c478bd9Sstevel@tonic-gate /*ARGSUSED*/
429*508de9f3SToomas Soome void
vbop_printf(void * ptr,const char * fmt,va_list ap)430*508de9f3SToomas Soome vbop_printf(void *ptr, const char *fmt, va_list ap)
431*508de9f3SToomas Soome {
432*508de9f3SToomas Soome prom_vprintf(fmt, ap);
433*508de9f3SToomas Soome }
434*508de9f3SToomas Soome
435986fd29aSsetje void
bop_printf(void * ops,const char * fmt,...)436986fd29aSsetje bop_printf(void *ops, const char *fmt, ...)
4377c478bd9Sstevel@tonic-gate {
438986fd29aSsetje va_list adx;
439986fd29aSsetje
440986fd29aSsetje va_start(adx, fmt);
441*508de9f3SToomas Soome vbop_printf(ops, fmt, adx);
442986fd29aSsetje va_end(adx);
4437c478bd9Sstevel@tonic-gate }
4447c478bd9Sstevel@tonic-gate
4457c478bd9Sstevel@tonic-gate /*
446986fd29aSsetje * Special routine for kmdb
4477c478bd9Sstevel@tonic-gate */
4487c478bd9Sstevel@tonic-gate void
bop_putsarg(const char * fmt,char * arg)449986fd29aSsetje bop_putsarg(const char *fmt, char *arg)
4507c478bd9Sstevel@tonic-gate {
451986fd29aSsetje prom_printf(fmt, arg);
4527c478bd9Sstevel@tonic-gate }
4537c478bd9Sstevel@tonic-gate
4547c478bd9Sstevel@tonic-gate /*
455986fd29aSsetje * panic for krtld only
4567c478bd9Sstevel@tonic-gate */
4577c478bd9Sstevel@tonic-gate void
bop_panic(const char * s)458986fd29aSsetje bop_panic(const char *s)
4597c478bd9Sstevel@tonic-gate {
460986fd29aSsetje prom_panic((char *)s);
4617c478bd9Sstevel@tonic-gate }
4627c478bd9Sstevel@tonic-gate
4637c478bd9Sstevel@tonic-gate /*
4647c478bd9Sstevel@tonic-gate * Implementation of the "mount" boot service.
4657c478bd9Sstevel@tonic-gate *
4667c478bd9Sstevel@tonic-gate */
4677c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4687c478bd9Sstevel@tonic-gate int
bop_mountroot(void)469986fd29aSsetje bop_mountroot(void)
4707c478bd9Sstevel@tonic-gate {
471986fd29aSsetje (void) prom_getprop(chosennode, "bootfs", (caddr_t)&bfs_ih);
472986fd29aSsetje (void) prom_getprop(chosennode, "archfs", (caddr_t)&afs_ih);
473986fd29aSsetje return ((bfs_ih == -1 && afs_ih == -1) ? BOOT_SVC_FAIL : BOOT_SVC_OK);
4747c478bd9Sstevel@tonic-gate }
4757c478bd9Sstevel@tonic-gate
4767c478bd9Sstevel@tonic-gate /*
4777c478bd9Sstevel@tonic-gate * Implementation of the "unmountroot" boot service.
4787c478bd9Sstevel@tonic-gate */
4797c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4807c478bd9Sstevel@tonic-gate int
bop_unmountroot(void)481986fd29aSsetje bop_unmountroot(void)
4827c478bd9Sstevel@tonic-gate {
4837c478bd9Sstevel@tonic-gate
484986fd29aSsetje if (bfs_ih != OBP_BADNODE) {
485986fd29aSsetje (void) prom_close(bfs_ih);
486986fd29aSsetje bfs_ih = OBP_BADNODE;
487986fd29aSsetje }
488986fd29aSsetje if (afs_ih != OBP_BADNODE) {
489986fd29aSsetje (void) prom_close(afs_ih);
490986fd29aSsetje afs_ih = OBP_BADNODE;
491986fd29aSsetje }
492986fd29aSsetje return (BOOT_SVC_OK);
4937c478bd9Sstevel@tonic-gate }
4947c478bd9Sstevel@tonic-gate
4957c478bd9Sstevel@tonic-gate /*
496986fd29aSsetje * Implementation of the "fstat" boot service.
4977c478bd9Sstevel@tonic-gate */
4987c478bd9Sstevel@tonic-gate int
bop_fstat(int fd,struct bootstat * st)499986fd29aSsetje bop_fstat(int fd, struct bootstat *st)
5007c478bd9Sstevel@tonic-gate {
501986fd29aSsetje ASSERT(prom_ihs[fd] != 0);
502986fd29aSsetje return (prom_fsize(prom_ihs[fd], fd, (size_t *)&st->st_size));
5037c478bd9Sstevel@tonic-gate }
5047c478bd9Sstevel@tonic-gate
505986fd29aSsetje int
boot_compinfo(int fd,struct compinfo * cb)506986fd29aSsetje boot_compinfo(int fd, struct compinfo *cb)
507986fd29aSsetje {
508986fd29aSsetje ASSERT(prom_ihs[fd] != 0);
509986fd29aSsetje return (prom_compinfo(prom_ihs[fd], fd,
510986fd29aSsetje &cb->iscmp, &cb->fsize, &cb->blksize));
511986fd29aSsetje }
512986fd29aSsetje
513986fd29aSsetje void
bop_free_archive(void)514986fd29aSsetje bop_free_archive(void)
515986fd29aSsetje {
516986fd29aSsetje char archive[OBP_MAXPATHLEN];
517986fd29aSsetje pnode_t arph;
518986fd29aSsetje uint32_t arbase, arsize, alloc_size;
519986fd29aSsetje
520986fd29aSsetje /*
521986fd29aSsetje * If the ramdisk will eventually be root, or we weren't
522986fd29aSsetje * booted via the archive, then nothing to do here
523986fd29aSsetje */
524986fd29aSsetje if (root_is_ramdisk == B_TRUE ||
525986fd29aSsetje prom_getprop(chosennode, "bootarchive", archive) == -1)
526986fd29aSsetje return;
527986fd29aSsetje arph = prom_finddevice(archive);
528986fd29aSsetje if (arph == -1 ||
529986fd29aSsetje prom_getprop(arph, OBP_ALLOCSIZE, (caddr_t)&alloc_size) == -1 ||
530986fd29aSsetje prom_getprop(arph, OBP_SIZE, (caddr_t)&arsize) == -1 ||
531986fd29aSsetje prom_getprop(arph, OBP_ADDRESS, (caddr_t)&arbase) == -1)
532986fd29aSsetje prom_panic("can't free boot archive");
533986fd29aSsetje
5343f9058a8SWilliam Roche bootops_obp_ramdisk_disabled = 1;
5353f9058a8SWilliam Roche
536986fd29aSsetje #if !defined(C_OBP)
537986fd29aSsetje if (alloc_size == 0)
538986fd29aSsetje prom_free((caddr_t)(uintptr_t)arbase, arsize);
539986fd29aSsetje else {
540986fd29aSsetje uint32_t arend = arbase + arsize;
541986fd29aSsetje
542986fd29aSsetje while (arbase < arend) {
543986fd29aSsetje prom_free((caddr_t)(uintptr_t)arbase,
544986fd29aSsetje MIN(alloc_size, arend - arbase));
545986fd29aSsetje arbase += alloc_size;
546986fd29aSsetje }
547986fd29aSsetje }
548986fd29aSsetje #else /* !C_OBP */
549986fd29aSsetje cobp_free_mem((caddr_t)(uintptr_t)arbase, arsize);
550986fd29aSsetje #endif /* !C_OBP */
551986fd29aSsetje }
552986fd29aSsetje
553986fd29aSsetje #if defined(C_OBP)
5547c478bd9Sstevel@tonic-gate /*
555986fd29aSsetje * Blech. The C proms have a bug when freeing areas that cross
556986fd29aSsetje * page sizes, so we have to break up the free into sections
557986fd29aSsetje * bounded by the various pagesizes.
5587c478bd9Sstevel@tonic-gate */
559986fd29aSsetje void
cobp_free_mem(caddr_t base,size_t size)560986fd29aSsetje cobp_free_mem(caddr_t base, size_t size)
5617c478bd9Sstevel@tonic-gate {
562986fd29aSsetje int i;
563986fd29aSsetje size_t len, pgsz;
564986fd29aSsetje
565986fd29aSsetje /*
566986fd29aSsetje * Large pages only used when size > 512k
567986fd29aSsetje */
568986fd29aSsetje if (size < MMU_PAGESIZE512K ||
569986fd29aSsetje ((uintptr_t)base & MMU_PAGEOFFSET512K) != 0) {
570986fd29aSsetje prom_free(base, size);
571986fd29aSsetje return;
572986fd29aSsetje }
573986fd29aSsetje for (i = 3; i >= 0; i--) {
574986fd29aSsetje pgsz = page_get_pagesize(i);
575986fd29aSsetje if (size < pgsz)
576986fd29aSsetje continue;
577986fd29aSsetje len = size & ~(pgsz - 1);
578986fd29aSsetje prom_free(base, len);
579986fd29aSsetje base += len;
580986fd29aSsetje size -= len;
581986fd29aSsetje }
5827c478bd9Sstevel@tonic-gate }
583986fd29aSsetje #endif /* C_OBP */
584986fd29aSsetje
5857c478bd9Sstevel@tonic-gate
5867c478bd9Sstevel@tonic-gate /*
5877c478bd9Sstevel@tonic-gate * Implementation of the "enter_mon" boot service.
5887c478bd9Sstevel@tonic-gate */
5897c478bd9Sstevel@tonic-gate void
bop_enter_mon(void)590986fd29aSsetje bop_enter_mon(void)
591986fd29aSsetje {
592986fd29aSsetje prom_enter_mon();
593986fd29aSsetje }
594986fd29aSsetje
595986fd29aSsetje /*
596986fd29aSsetje * free elf info allocated by booter
597986fd29aSsetje */
598986fd29aSsetje void
bop_free_elf(void)599986fd29aSsetje bop_free_elf(void)
600986fd29aSsetje {
601986fd29aSsetje uint32_t eadr;
602986fd29aSsetje uint32_t esize;
603986fd29aSsetje extern Addr dynseg;
604986fd29aSsetje extern size_t dynsize;
605986fd29aSsetje
606986fd29aSsetje if (bop_getprop("elfheader-address", (caddr_t)&eadr) == -1 ||
607986fd29aSsetje bop_getprop("elfheader-length", (caddr_t)&esize) == -1)
608986fd29aSsetje prom_panic("missing elfheader");
609986fd29aSsetje prom_free((caddr_t)(uintptr_t)eadr, roundup(esize, PAGESIZE));
610986fd29aSsetje
611986fd29aSsetje prom_free((caddr_t)(uintptr_t)dynseg, roundup(dynsize, PAGESIZE));
612986fd29aSsetje }
613986fd29aSsetje
614986fd29aSsetje
615986fd29aSsetje /* Simple message to indicate that the bootops pointer has been zeroed */
616986fd29aSsetje #ifdef DEBUG
617986fd29aSsetje int bootops_gone_on = 0;
618986fd29aSsetje #define BOOTOPS_GONE() \
619986fd29aSsetje if (bootops_gone_on) \
620986fd29aSsetje prom_printf("The bootops vec is zeroed now!\n");
621986fd29aSsetje #else
622986fd29aSsetje #define BOOTOPS_GONE()
623986fd29aSsetje #endif /* DEBUG */
624986fd29aSsetje
625986fd29aSsetje void
bop_fini(void)626986fd29aSsetje bop_fini(void)
6277c478bd9Sstevel@tonic-gate {
628986fd29aSsetje bop_free_archive();
629986fd29aSsetje (void) bop_unmountroot();
630986fd29aSsetje bop_free_elf();
631986fd29aSsetje bop_temp_freeall();
632986fd29aSsetje
633986fd29aSsetje bootops = (struct bootops *)NULL;
634986fd29aSsetje BOOTOPS_GONE();
6357c478bd9Sstevel@tonic-gate }
636