xref: /illumos-gate/usr/src/uts/sparc/os/bootops.c (revision 355b4669e025ff377602b6fc7caaf30dbc218371)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * Definitions of interfaces that provide services from the secondary
31  * boot program to its clients (primarily Solaris, krtld, kmdb and their
32  * successors.) This interface replaces the bootops (BOP) implementation
33  * as the interface to be called by boot clients.
34  *
35  */
36 
37 #include <sys/types.h>
38 #include <sys/reboot.h>
39 #include <sys/param.h>
40 #include <sys/varargs.h>
41 #include <sys/obpdefs.h>
42 #include <sys/promif.h>
43 #include <sys/bootconf.h>
44 #include <sys/bootstat.h>
45 
46 /*
47  * Implementation of the "version" boot service.
48  * Return the compiled version number of this implementation.
49  *
50  * Note: An individual service can be tested for and versioned with
51  * bop_serviceavail();
52  *
53  * Calling spec:
54  * args[0] Service name string
55  * args[1] #argument cells
56  * args[2] #result cells
57  * args[3] Res0: returned version number
58  */
59 uint_t
60 bop_getversion(struct bootops *bop)
61 {
62 	return (bop->bsys_version);
63 }
64 
65 
66 /*
67  * Implementation of the "open" boot service.
68  *
69  * Calling spec:
70  * args[0] Service name string
71  * args[1] #argument cells
72  * args[2] #result cells
73  * args[3] filename string
74  * args[4] flags
75  * args[5] Res0: returned result
76  *
77  */
78 int
79 bop_open(struct bootops *bop, char *name, int flags)
80 {
81 	boot_cell_t args[6];
82 	int	(*bsys_1275_call)(void *);
83 
84 	/* use uintptr_t to suppress the gcc warning */
85 	bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call;
86 	args[0] = boot_ptr2cell("open");
87 	args[1] = 2;
88 	args[2] = 1;
89 
90 	args[3] = boot_ptr2cell(name);
91 	args[4] = boot_int2cell(flags);
92 	(void) (bsys_1275_call)(args);
93 	return (boot_cell2int(args[5]));
94 }
95 
96 /*
97  * Implementation of the "read" boot service.
98  *
99  * Calling spec:
100  * args[0] Service name string
101  * args[1] #argument cells
102  * args[2] #result cells
103  * args[3] boot-opened file descriptor
104  * args[4] client's buffer
105  * args[5] size of read request
106  * args[6] Res0: returned result
107  *
108  */
109 int
110 bop_read(struct bootops *bop, int fd, caddr_t buf, size_t size)
111 {
112 	boot_cell_t args[7];
113 	int	(*bsys_1275_call)(void *);
114 
115 	/* use uintptr_t to suppress the gcc warning */
116 	bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call;
117 	args[0] = boot_ptr2cell("read");
118 	args[1] = 3;
119 	args[2] = 1;
120 
121 	args[3] = boot_int2cell(fd);
122 	args[4] = boot_ptr2cell(buf);
123 	args[5] = boot_uint2cell(size);
124 	(void) (bsys_1275_call)(args);
125 	return (boot_cell2int(args[6]));
126 }
127 
128 /*
129  * Implementation of the "seek" boot service.
130  *
131  * Calling spec:
132  * args[0] Service name string
133  * args[1] #argument cells
134  * args[2] #result cells
135  * args[3] boot-opened file descriptor
136  * args[4] offset hi		XXX just use one cell for offset?
137  * args[5] offset lo
138  * args[6] Res0: returned result
139  */
140 int
141 bop_seek(struct bootops *bop, int fd, off_t hi, off_t lo)
142 {
143 	boot_cell_t args[7];
144 	int	(*bsys_1275_call)(void *);
145 
146 	/* use uintptr_t to suppress the gcc warning */
147 	bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call;
148 	args[0] = boot_ptr2cell("seek");
149 	args[1] = 3;
150 	args[2] = 1;
151 
152 	args[3] = boot_int2cell(fd);
153 	args[4] = boot_offt2cell(hi);
154 	args[5] = boot_offt2cell(lo);
155 	(void) (bsys_1275_call)(args);
156 	return (boot_cell2int(args[6]));
157 }
158 
159 /*
160  * Implementation of the "close" boot service.
161  *
162  * Calling spec:
163  * args[0] Service name string
164  * args[1] #argument cells
165  * args[2] #result cells
166  * args[3] boot-opened file descriptor
167  * args[4] Res0: returned result
168  */
169 int
170 bop_close(struct bootops *bop, int fd)
171 {
172 	boot_cell_t args[5];
173 	int	(*bsys_1275_call)(void *);
174 
175 	/* use uintptr_t to suppress the gcc warning */
176 	bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call;
177 	args[0] = boot_ptr2cell("close");
178 	args[1] = 1;
179 	args[2] = 1;
180 
181 	args[3] = boot_int2cell(fd);
182 	(void) (bsys_1275_call)(args);
183 	return (boot_cell2int(args[4]));
184 }
185 
186 /*
187  * Implementation of the "alloc" boot service.
188  *
189  * Calling spec:
190  * args[0] Service name string
191  * args[1] #argument cells
192  * args[2] #result cells
193  * args[3] virtual hint
194  * args[4] size to allocate
195  * args[5] alignment
196  * args[6] Res0: returned result
197  */
198 caddr_t
199 bop_alloc(struct bootops *bop, caddr_t virthint, size_t size, int align)
200 {
201 	boot_cell_t args[7];
202 	int	(*bsys_1275_call)(void *);
203 
204 	/* use uintptr_t to suppress the gcc warning */
205 	bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call;
206 	args[0] = boot_ptr2cell("alloc");
207 	args[1] = 3;
208 	args[2] = 1;
209 
210 	args[3] = boot_ptr2cell(virthint);
211 	args[4] = boot_size2cell(size);
212 	args[5] = boot_int2cell(align);
213 	(void) (bsys_1275_call)(args);
214 	return ((caddr_t)(uintptr_t)boot_ptr2cell((uintptr_t)args[6]));
215 }
216 
217 /*
218  * Implementation of the "alloc_virt" boot service
219  *
220  * Calling spec:
221  * args[0] Service name string
222  * args[1] #argument cells
223  * args[2] #result cells
224  * args[3] virtual address
225  * args[4] size to allocate
226  * args[5] Resi: returned result
227  */
228 caddr_t
229 bop_alloc_virt(struct bootops *bop, caddr_t virt, size_t size)
230 {
231 	boot_cell_t args[6];
232 	int	(*bsys_1275_call)(void *);
233 
234 	/* use uintptr_t to suppress the gcc warning */
235 	bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call;
236 	args[0] = boot_ptr2cell("alloc_virt");
237 	args[1] = 2;
238 	args[2] = 1;
239 
240 	args[3] = boot_ptr2cell(virt);
241 	args[4] = boot_size2cell(size);
242 	(void) (bsys_1275_call)(args);
243 	return ((caddr_t)(uintptr_t)boot_ptr2cell((uintptr_t)args[5]));
244 }
245 
246 /*
247  * Implementation of the "free" boot service.
248  *
249  * Calling spec:
250  * args[0] Service name string
251  * args[1] #argument cells
252  * args[2] #result cells
253  * args[3] virtual hint
254  * args[4] size to free
255  * args[5] Res0: returned result
256  */
257 /*ARGSUSED*/
258 void
259 bop_free(struct bootops *bop, caddr_t virt, size_t size)
260 {
261 	boot_cell_t args[6];
262 	int	(*bsys_1275_call)(void *);
263 
264 	/* use uintptr_t to suppress the gcc warning */
265 	bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call;
266 	args[0] = boot_ptr2cell("free");
267 	args[1] = 2;
268 	args[2] = 1;
269 
270 	args[3] = boot_ptr2cell(virt);
271 	args[4] = boot_size2cell(size);
272 	(void) (bsys_1275_call)(args);
273 }
274 
275 /*
276  * Implementation of the "map" boot service.
277  *
278  * Calling spec:
279  * args[0] Service name string
280  * args[1] #argument cells
281  * args[2] #result cells
282  * args[3] virtual address
283  * args[4] space of phys addr
284  * args[5] phys addr
285  * args[6] size
286  * args[7] Res0: returned result
287  */
288 /*ARGSUSED*/
289 caddr_t
290 bop_map(struct bootops *bop, caddr_t virt, int space,
291 	caddr_t phys, size_t size)
292 {
293 	boot_cell_t args[8];
294 	int	(*bsys_1275_call)(void *);
295 
296 	/* use uintptr_t to suppress the gcc warning */
297 	bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call;
298 	args[0] = boot_ptr2cell("map");
299 	args[1] = 3;
300 	args[2] = 1;
301 
302 	args[3] = boot_ptr2cell(virt);
303 	args[4] = boot_int2cell(space);
304 	args[5] = boot_ptr2cell(phys);
305 	args[6] = boot_size2cell(size);
306 	(void) (bsys_1275_call)(args);
307 	return ((caddr_t)boot_cell2ptr(args[7]));
308 }
309 
310 /*
311  * Implementation of the "unmap" boot service.
312  *
313  * Calling spec:
314  * args[0] Service name string
315  * args[1] #argument cells
316  * args[2] #result cells
317  * args[3] virtual address
318  * args[4] size of chunk
319  * args[5] Res0: returned result
320  */
321 /*ARGSUSED*/
322 void
323 bop_unmap(struct bootops *bop, caddr_t virt, size_t size)
324 {
325 	boot_cell_t args[6];
326 	int	(*bsys_1275_call)(void *);
327 
328 	/* use uintptr_t to suppress the gcc warning */
329 	bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call;
330 	args[0] = boot_ptr2cell("unmap");
331 	args[1] = 2;
332 	args[2] = 1;
333 
334 	args[3] = boot_ptr2cell(virt);
335 	args[4] = boot_size2cell(size);
336 	(void) (bsys_1275_call)(args);
337 }
338 
339 /*
340  * Implementation of the "quiesce" boot service.
341  *
342  * Calling spec:
343  * args[0] Service name string
344  * args[1] #argument cells
345  * args[2] #result cells
346  * args[3] Res0: returned result
347  */
348 /*ARGSUSED*/
349 void
350 bop_quiesce_io(struct bootops *bop)
351 {
352 	boot_cell_t args[4];
353 	int	(*bsys_1275_call)(void *);
354 
355 	/* use uintptr_t to suppress the gcc warning */
356 	bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call;
357 	args[0] = boot_ptr2cell("quiesce");
358 	args[1] = 0;
359 	args[2] = 1;
360 
361 	(void) (bsys_1275_call)(args);
362 }
363 
364 /*
365  * Implementation of the "getproplen" boot service.
366  *
367  * Calling spec:
368  * args[0] Service name string
369  * args[1] #argument cells
370  * args[2] #result cells
371  * args[3] property name string
372  * args[4] Res0: returned result
373  */
374 /*ARGSUSED*/
375 int
376 bop_getproplen(struct bootops *bop, char *name)
377 {
378 	boot_cell_t args[7];
379 	int	(*bsys_1275_call)(void *);
380 
381 	/* use uintptr_t to suppress the gcc warning */
382 	bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call;
383 	args[0] = boot_ptr2cell("getproplen");
384 	args[1] = 1;
385 	args[2] = 1;
386 
387 	args[3] = boot_ptr2cell(name);
388 	(void) (bsys_1275_call)(args);
389 	return (boot_cell2int(args[4]));
390 }
391 
392 /*
393  * Implementation of the "getprop" boot service.
394  *
395  * Calling spec:
396  * args[0] Service name string
397  * args[1] #argument cells
398  * args[2] #result cells
399  * args[3] property name string
400  * args[4] buffer pointer to hold value of the property
401  * args[5] Res0: returned result
402  */
403 /*ARGSUSED*/
404 int
405 bop_getprop(struct bootops *bop, char *name, void *value)
406 {
407 	boot_cell_t args[6];
408 	int	(*bsys_1275_call)(void *);
409 
410 	/* use uintptr_t to suppress the gcc warning */
411 	bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call;
412 	args[0] = boot_ptr2cell("getprop");
413 	args[1] = 2;
414 	args[2] = 1;
415 
416 	args[3] = boot_ptr2cell(name);
417 	args[4] = boot_ptr2cell(value);
418 	(void) (bsys_1275_call)(args);
419 	return (boot_cell2int(args[5]));
420 }
421 
422 /*
423  * Implementation of the "nextprop" boot service.
424  *
425  * Calling spec:
426  * args[0] Service name string
427  * args[1] #argument cells
428  * args[2] #result cells
429  * args[3] previous property name string
430  * args[4] Res0: returned result
431  */
432 /*ARGSUSED*/
433 char *
434 bop_nextprop(struct bootops *bop, char *prevprop)
435 {
436 	boot_cell_t args[5];
437 	int	(*bsys_1275_call)(void *);
438 
439 	/* use uintptr_t to suppress the gcc warning */
440 	bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call;
441 	args[0] = boot_ptr2cell("nextprop");
442 	args[1] = 1;
443 	args[2] = 1;
444 
445 	args[3] = boot_ptr2cell(prevprop);
446 	(void) (bsys_1275_call)(args);
447 	return ((char *)boot_cell2ptr(args[4]));
448 }
449 
450 /*
451  * Implementation of the "puts" boot service.
452  *
453  * Calling spec:
454  * args[0] Service name string
455  * args[1] #argument cells
456  * args[2] #result cells
457  * args[3] string to print
458  */
459 /*ARGSUSED*/
460 void
461 bop_puts(struct bootops *bop, char *string)
462 {
463 	boot_cell_t	args[6];
464 	int	(*bsys_1275_call)(void *);
465 	void	(*bsys_printf)(struct bootops *, char *, ...);
466 
467 	/* so new kernel, old boot can print a message before dying */
468 	if (!BOOTOPS_ARE_1275(bop)) {
469 		/* use uintptr_t to suppress the gcc warning */
470 		bsys_printf = (void (*)(struct bootops *, char *, ...))
471 		    (uintptr_t)bop->bsys_printf;
472 		(*bsys_printf)(bop, string);
473 		return;
474 	}
475 
476 	bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call;
477 	args[0] = boot_ptr2cell("puts");
478 	args[1] = 1;
479 	args[2] = 0;
480 
481 	args[3] = boot_ptr2cell(string);
482 	(void) (bsys_1275_call)(args);
483 
484 }
485 
486 /*
487  * Implementation of the "putsarg" boot service.
488  *
489  * Calling spec:
490  * args[0] Service name string
491  * args[1] #argument cells
492  * args[2] #result cells
493  * args[3] string to print (with '%*' format)
494  * args[4] 64-bit thing to print
495  */
496 /*ARGSUSED*/
497 void
498 bop_putsarg(struct bootops *bop, const char *string, ...)
499 {
500 	boot_cell_t	args[6];
501 	int	(*bsys_1275_call)(void *);
502 	void	(*bsys_printf)(struct bootops *, char *, ...);
503 	va_list		ap;
504 	const char	*fmt = string;
505 	int		ells = 0;
506 	uint64_t	arg;
507 
508 	/*
509 	 * We need to do the minimum printf-like stuff here to figure
510 	 * out the size of argument, if present.
511 	 */
512 	while (*fmt) {
513 		if (*fmt++ != '%')
514 			continue;
515 		if (*fmt == '%') {
516 			fmt++;
517 			continue;
518 		}
519 
520 		while (*fmt >= '0' && *fmt <= '9')
521 			fmt++;
522 		for (ells = 0; *fmt == 'l'; fmt++)
523 			ells++;
524 		va_start(ap, string);
525 		switch (*fmt) {
526 		case 's':
527 			/* use uintptr_t to suppress the gcc warning */
528 			arg = (uint64_t)(uintptr_t)va_arg(ap, char *);
529 			break;
530 		case 'p':
531 			arg = (uint64_t)(uintptr_t)va_arg(ap, void *);
532 			break;
533 		case 'd':
534 		case 'D':
535 		case 'x':
536 		case 'X':
537 		case 'u':
538 		case 'U':
539 		case 'o':
540 		case 'O':
541 			if (ells == 0)
542 				arg = (uint64_t)va_arg(ap, uint_t);
543 			else if (ells == 1)
544 				arg = (uint64_t)va_arg(ap, ulong_t);
545 			else
546 				arg = (uint64_t)va_arg(ap, uint64_t);
547 			break;
548 		default:
549 			arg = (uint64_t)va_arg(ap, uint_t);
550 			break;
551 		}
552 		va_end(ap);
553 		break;
554 	}
555 
556 	/* so new kernel, old boot can print a message before dying */
557 	if (!BOOTOPS_ARE_1275(bop)) {
558 		/* use uintptr_t to suppress the gcc warning */
559 		bsys_printf = (void (*)(struct bootops *, char *, ...))
560 		    (uintptr_t)bop->bsys_printf;
561 		(*bsys_printf)(bop, (char *)string, arg);
562 		return;
563 	}
564 
565 	bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call;
566 	args[0] = boot_ptr2cell("putsarg");
567 	args[1] = 2;
568 	args[2] = 0;
569 	args[3] = boot_ptr2cell(string);
570 	args[4] = boot_uint642cell(arg);
571 
572 	(void) (bsys_1275_call)(args);
573 }
574 
575 /*
576  * Implementation of the "mount" boot service.
577  *
578  * Calling spec:
579  * args[0] Service name string
580  * args[1] #argument cells
581  * args[2] #result cells
582  * args[3] pathname string
583  * args[4] Res0: returned result
584  */
585 /*ARGSUSED*/
586 int
587 bop_mountroot(struct bootops *bop, char *path)
588 {
589 	boot_cell_t args[5];
590 	int	(*bsys_1275_call)(void *);
591 
592 	/* use uintptr_t to suppress the gcc warning */
593 	bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call;
594 	args[0] = boot_ptr2cell("mountroot");
595 	args[1] = 2;
596 	args[2] = 1;
597 
598 	args[3] = boot_ptr2cell(path);
599 	(void) (bsys_1275_call)(args);
600 	return (boot_cell2int(args[4]));
601 }
602 
603 /*
604  * Implementation of the "unmountroot" boot service.
605  *
606  * Calling spec:
607  * args[0] Service name string
608  * args[1] #argument cells
609  * args[2] #result cells
610  * args[3] Res0: returned result
611  */
612 /*ARGSUSED*/
613 int
614 bop_unmountroot(struct bootops *bop)
615 {
616 	boot_cell_t args[4];
617 	int	(*bsys_1275_call)(void *);
618 
619 	/* use uintptr_t to suppress the gcc warning */
620 	bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call;
621 	args[0] = boot_ptr2cell("unmountroot");
622 	args[1] = 0;
623 	args[2] = 1;
624 
625 	(void) (bsys_1275_call)(args);
626 	return (boot_cell2int(args[3]));
627 }
628 
629 /*
630  * Implementation of the "serviceavail" boot service.
631  *
632  * Calling spec:
633  * args[0] Service name string
634  * args[1] #argument cells
635  * args[2] #result cells
636  * args[3] name string of service to be tested for
637  * args[4] Res0: returned version number or 0
638  */
639 /*ARGSUSED*/
640 int
641 bop_serviceavail(struct bootops *bop, char *name)
642 {
643 	/* use uintptr_t to suppress the gcc warning */
644 	boot_cell_t args[5];
645 	int	(*bsys_1275_call)(void *) =
646 	    (int (*)(void *))(uintptr_t)bop->bsys_1275_call;
647 
648 	args[0] = boot_ptr2cell("serviceavail");
649 	args[1] = 1;
650 	args[2] = 1;
651 
652 	args[3] = boot_ptr2cell(name);
653 	(void) (bsys_1275_call)(args);
654 	return (boot_cell2int(args[4]));
655 }
656 
657 /*
658  * Implementation of the "fstat" boot service.
659  *
660  * Calling spec:
661  * args[0] Service name string
662  * args[1] #argument cells
663  * args[2] #result cells
664  * args[3] fd
665  * args[4] client's stat structure
666  */
667 int
668 bop_fstat(struct bootops *bop, int fd, struct bootstat *st)
669 {
670 	boot_cell_t args[6];
671 	int	(*bsys_1275_call)(void *);
672 
673 	/* use uintptr_t to suppress the gcc warning */
674 	bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call;
675 	args[0] = boot_ptr2cell("fstat");
676 	args[1] = 2;
677 	args[2] = 1;
678 	args[3] = boot_int2cell(fd);
679 	args[4] = boot_ptr2cell(st);
680 	(void) (bsys_1275_call)(args);
681 	return (boot_cell2int(args[5]));
682 }
683 
684 /*
685  * Implementation of the "enter_mon" boot service.
686  *
687  * Calling spec:
688  * args[0] Service name string
689  * args[1] #argument cells (0)
690  * args[2] #result cells (0)
691  */
692 void
693 bop_enter_mon(struct bootops *bop)
694 {
695 	boot_cell_t args[4];
696 	int (*bsys_1275_call)(void *);
697 
698 	/* use uintptr_t to suppress the gcc warning */
699 	bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call;
700 	args[0] = boot_ptr2cell("enter_mon");
701 	args[1] = 0;
702 	args[2] = 0;
703 	(void) (bsys_1275_call)(args);
704 }
705