xref: /illumos-gate/usr/src/uts/sparc/os/bootops.c (revision 49218d4f8e4d84d1c08aeb267bcf6e451f2056dc)
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 	bsys_1275_call = (int (*)(void *))bop->bsys_1275_call;
85 	args[0] = boot_ptr2cell("open");
86 	args[1] = 2;
87 	args[2] = 1;
88 
89 	args[3] = boot_ptr2cell(name);
90 	args[4] = boot_int2cell(flags);
91 	(void) (bsys_1275_call)(args);
92 	return (boot_cell2int(args[5]));
93 }
94 
95 /*
96  * Implementation of the "read" boot service.
97  *
98  * Calling spec:
99  * args[0] Service name string
100  * args[1] #argument cells
101  * args[2] #result cells
102  * args[3] boot-opened file descriptor
103  * args[4] client's buffer
104  * args[5] size of read request
105  * args[6] Res0: returned result
106  *
107  */
108 int
109 bop_read(struct bootops *bop, int fd, caddr_t buf, size_t size)
110 {
111 	boot_cell_t args[7];
112 	int	(*bsys_1275_call)(void *);
113 
114 	bsys_1275_call = (int (*)(void *))bop->bsys_1275_call;
115 	args[0] = boot_ptr2cell("read");
116 	args[1] = 3;
117 	args[2] = 1;
118 
119 	args[3] = boot_int2cell(fd);
120 	args[4] = boot_ptr2cell(buf);
121 	args[5] = boot_uint2cell(size);
122 	(void) (bsys_1275_call)(args);
123 	return (boot_cell2int(args[6]));
124 }
125 
126 /*
127  * Implementation of the "seek" boot service.
128  *
129  * Calling spec:
130  * args[0] Service name string
131  * args[1] #argument cells
132  * args[2] #result cells
133  * args[3] boot-opened file descriptor
134  * args[4] offset hi		XXX just use one cell for offset?
135  * args[5] offset lo
136  * args[6] Res0: returned result
137  */
138 int
139 bop_seek(struct bootops *bop, int fd, off_t hi, off_t lo)
140 {
141 	boot_cell_t args[7];
142 	int	(*bsys_1275_call)(void *);
143 
144 	bsys_1275_call = (int (*)(void *))bop->bsys_1275_call;
145 	args[0] = boot_ptr2cell("seek");
146 	args[1] = 3;
147 	args[2] = 1;
148 
149 	args[3] = boot_int2cell(fd);
150 	args[4] = boot_offt2cell(hi);
151 	args[5] = boot_offt2cell(lo);
152 	(void) (bsys_1275_call)(args);
153 	return (boot_cell2int(args[6]));
154 }
155 
156 /*
157  * Implementation of the "close" boot service.
158  *
159  * Calling spec:
160  * args[0] Service name string
161  * args[1] #argument cells
162  * args[2] #result cells
163  * args[3] boot-opened file descriptor
164  * args[4] Res0: returned result
165  */
166 int
167 bop_close(struct bootops *bop, int fd)
168 {
169 	boot_cell_t args[5];
170 	int	(*bsys_1275_call)(void *);
171 
172 	bsys_1275_call = (int (*)(void *))bop->bsys_1275_call;
173 	args[0] = boot_ptr2cell("close");
174 	args[1] = 1;
175 	args[2] = 1;
176 
177 	args[3] = boot_int2cell(fd);
178 	(void) (bsys_1275_call)(args);
179 	return (boot_cell2int(args[4]));
180 }
181 
182 /*
183  * Implementation of the "alloc" boot service.
184  *
185  * Calling spec:
186  * args[0] Service name string
187  * args[1] #argument cells
188  * args[2] #result cells
189  * args[3] virtual hint
190  * args[4] size to allocate
191  * args[5] alignment
192  * args[6] Res0: returned result
193  */
194 caddr_t
195 bop_alloc(struct bootops *bop, caddr_t virthint, size_t size, int align)
196 {
197 	boot_cell_t args[7];
198 	int	(*bsys_1275_call)(void *);
199 
200 	bsys_1275_call = (int (*)(void *))bop->bsys_1275_call;
201 	args[0] = boot_ptr2cell("alloc");
202 	args[1] = 3;
203 	args[2] = 1;
204 
205 	args[3] = boot_ptr2cell(virthint);
206 	args[4] = boot_size2cell(size);
207 	args[5] = boot_int2cell(align);
208 	(void) (bsys_1275_call)(args);
209 	return ((caddr_t)boot_ptr2cell(args[6]));
210 }
211 
212 /*
213  * Implementation of the "alloc_virt" boot service
214  *
215  * Calling spec:
216  * args[0] Service name string
217  * args[1] #argument cells
218  * args[2] #result cells
219  * args[3] virtual address
220  * args[4] size to allocate
221  * args[5] Resi: returned result
222  */
223 caddr_t
224 bop_alloc_virt(struct bootops *bop, caddr_t virt, size_t size)
225 {
226 	boot_cell_t args[6];
227 	int	(*bsys_1275_call)(void *);
228 
229 	bsys_1275_call = (int (*)(void *))bop->bsys_1275_call;
230 	args[0] = boot_ptr2cell("alloc_virt");
231 	args[1] = 2;
232 	args[2] = 1;
233 
234 	args[3] = boot_ptr2cell(virt);
235 	args[4] = boot_size2cell(size);
236 	(void) (bsys_1275_call)(args);
237 	return ((caddr_t)boot_ptr2cell(args[5]));
238 }
239 
240 /*
241  * Implementation of the "free" boot service.
242  *
243  * Calling spec:
244  * args[0] Service name string
245  * args[1] #argument cells
246  * args[2] #result cells
247  * args[3] virtual hint
248  * args[4] size to free
249  * args[5] Res0: returned result
250  */
251 /*ARGSUSED*/
252 void
253 bop_free(struct bootops *bop, caddr_t virt, size_t size)
254 {
255 	boot_cell_t args[6];
256 	int	(*bsys_1275_call)(void *);
257 
258 	bsys_1275_call = (int (*)(void *))bop->bsys_1275_call;
259 	args[0] = boot_ptr2cell("free");
260 	args[1] = 2;
261 	args[2] = 1;
262 
263 	args[3] = boot_ptr2cell(virt);
264 	args[4] = boot_size2cell(size);
265 	(void) (bsys_1275_call)(args);
266 }
267 
268 /*
269  * Implementation of the "map" boot service.
270  *
271  * Calling spec:
272  * args[0] Service name string
273  * args[1] #argument cells
274  * args[2] #result cells
275  * args[3] virtual address
276  * args[4] space of phys addr
277  * args[5] phys addr
278  * args[6] size
279  * args[7] Res0: returned result
280  */
281 /*ARGSUSED*/
282 caddr_t
283 bop_map(struct bootops *bop, caddr_t virt, int space,
284 	caddr_t phys, size_t size)
285 {
286 	boot_cell_t args[8];
287 	int	(*bsys_1275_call)(void *);
288 
289 	bsys_1275_call = (int (*)(void *))bop->bsys_1275_call;
290 	args[0] = boot_ptr2cell("map");
291 	args[1] = 3;
292 	args[2] = 1;
293 
294 	args[3] = boot_ptr2cell(virt);
295 	args[4] = boot_int2cell(space);
296 	args[5] = boot_ptr2cell(phys);
297 	args[6] = boot_size2cell(size);
298 	(void) (bsys_1275_call)(args);
299 	return ((caddr_t)boot_cell2ptr(args[7]));
300 }
301 
302 /*
303  * Implementation of the "unmap" boot service.
304  *
305  * Calling spec:
306  * args[0] Service name string
307  * args[1] #argument cells
308  * args[2] #result cells
309  * args[3] virtual address
310  * args[4] size of chunk
311  * args[5] Res0: returned result
312  */
313 /*ARGSUSED*/
314 void
315 bop_unmap(struct bootops *bop, caddr_t virt, size_t size)
316 {
317 	boot_cell_t args[6];
318 	int	(*bsys_1275_call)(void *);
319 
320 	bsys_1275_call = (int (*)(void *))bop->bsys_1275_call;
321 	args[0] = boot_ptr2cell("unmap");
322 	args[1] = 2;
323 	args[2] = 1;
324 
325 	args[3] = boot_ptr2cell(virt);
326 	args[4] = boot_size2cell(size);
327 	(void) (bsys_1275_call)(args);
328 }
329 
330 /*
331  * Implementation of the "quiesce" boot service.
332  *
333  * Calling spec:
334  * args[0] Service name string
335  * args[1] #argument cells
336  * args[2] #result cells
337  * args[3] Res0: returned result
338  */
339 /*ARGSUSED*/
340 void
341 bop_quiesce_io(struct bootops *bop)
342 {
343 	boot_cell_t args[4];
344 	int	(*bsys_1275_call)(void *);
345 
346 	bsys_1275_call = (int (*)(void *))bop->bsys_1275_call;
347 	args[0] = boot_ptr2cell("quiesce");
348 	args[1] = 0;
349 	args[2] = 1;
350 
351 	(void) (bsys_1275_call)(args);
352 }
353 
354 /*
355  * Implementation of the "getproplen" boot service.
356  *
357  * Calling spec:
358  * args[0] Service name string
359  * args[1] #argument cells
360  * args[2] #result cells
361  * args[3] property name string
362  * args[4] Res0: returned result
363  */
364 /*ARGSUSED*/
365 int
366 bop_getproplen(struct bootops *bop, char *name)
367 {
368 	boot_cell_t args[7];
369 	int	(*bsys_1275_call)(void *);
370 
371 	bsys_1275_call = (int (*)(void *))bop->bsys_1275_call;
372 	args[0] = boot_ptr2cell("getproplen");
373 	args[1] = 1;
374 	args[2] = 1;
375 
376 	args[3] = boot_ptr2cell(name);
377 	(void) (bsys_1275_call)(args);
378 	return (boot_cell2int(args[4]));
379 }
380 
381 /*
382  * Implementation of the "getprop" boot service.
383  *
384  * Calling spec:
385  * args[0] Service name string
386  * args[1] #argument cells
387  * args[2] #result cells
388  * args[3] property name string
389  * args[4] buffer pointer to hold value of the property
390  * args[5] Res0: returned result
391  */
392 /*ARGSUSED*/
393 int
394 bop_getprop(struct bootops *bop, char *name, void *value)
395 {
396 	boot_cell_t args[6];
397 	int	(*bsys_1275_call)(void *);
398 
399 	bsys_1275_call = (int (*)(void *))bop->bsys_1275_call;
400 	args[0] = boot_ptr2cell("getprop");
401 	args[1] = 2;
402 	args[2] = 1;
403 
404 	args[3] = boot_ptr2cell(name);
405 	args[4] = boot_ptr2cell(value);
406 	(void) (bsys_1275_call)(args);
407 	return (boot_cell2int(args[5]));
408 }
409 
410 /*
411  * Implementation of the "nextprop" boot service.
412  *
413  * Calling spec:
414  * args[0] Service name string
415  * args[1] #argument cells
416  * args[2] #result cells
417  * args[3] previous property name string
418  * args[4] Res0: returned result
419  */
420 /*ARGSUSED*/
421 char *
422 bop_nextprop(struct bootops *bop, char *prevprop)
423 {
424 	boot_cell_t args[5];
425 	int	(*bsys_1275_call)(void *);
426 
427 	bsys_1275_call = (int (*)(void *))bop->bsys_1275_call;
428 	args[0] = boot_ptr2cell("nextprop");
429 	args[1] = 1;
430 	args[2] = 1;
431 
432 	args[3] = boot_ptr2cell(prevprop);
433 	(void) (bsys_1275_call)(args);
434 	return ((char *)boot_cell2ptr(args[4]));
435 }
436 
437 /*
438  * Implementation of the "puts" boot service.
439  *
440  * Calling spec:
441  * args[0] Service name string
442  * args[1] #argument cells
443  * args[2] #result cells
444  * args[3] string to print
445  */
446 /*ARGSUSED*/
447 void
448 bop_puts(struct bootops *bop, char *string)
449 {
450 	boot_cell_t	args[6];
451 	int	(*bsys_1275_call)(void *);
452 	void	(*bsys_printf)(struct bootops *, char *, ...);
453 
454 	/* so new kernel, old boot can print a message before dying */
455 	if (!BOOTOPS_ARE_1275(bop)) {
456 		/* use uintptr_t to suppress the gcc warning */
457 		bsys_printf = (void (*)(struct bootops *, char *, ...))
458 		    (uintptr_t)bop->bsys_printf;
459 		(*bsys_printf)(bop, string);
460 		return;
461 	}
462 	bsys_1275_call = (int (*)(void *))bop->bsys_1275_call;
463 	args[0] = boot_ptr2cell("puts");
464 	args[1] = 1;
465 	args[2] = 0;
466 
467 	args[3] = boot_ptr2cell(string);
468 	(void) (bsys_1275_call)(args);
469 
470 }
471 
472 /*
473  * Implementation of the "putsarg" boot service.
474  *
475  * Calling spec:
476  * args[0] Service name string
477  * args[1] #argument cells
478  * args[2] #result cells
479  * args[3] string to print (with '%*' format)
480  * args[4] 64-bit thing to print
481  */
482 /*ARGSUSED*/
483 void
484 bop_putsarg(struct bootops *bop, const char *string, ...)
485 {
486 	boot_cell_t	args[6];
487 	int	(*bsys_1275_call)(void *);
488 	void	(*bsys_printf)(struct bootops *, char *, ...);
489 	va_list		ap;
490 	const char	*fmt = string;
491 	int		ells = 0;
492 	uint64_t	arg;
493 
494 	/*
495 	 * We need to do the minimum printf-like stuff here to figure
496 	 * out the size of argument, if present.
497 	 */
498 	while (*fmt) {
499 		if (*fmt++ != '%')
500 			continue;
501 		if (*fmt == '%') {
502 			fmt++;
503 			continue;
504 		}
505 
506 		while (*fmt >= '0' && *fmt <= '9')
507 			fmt++;
508 		for (ells = 0; *fmt == 'l'; fmt++)
509 			ells++;
510 		va_start(ap, string);
511 		switch (*fmt) {
512 		case 's':
513 			arg = (uint64_t)va_arg(ap, char *);
514 			break;
515 		case 'p':
516 			arg = (uint64_t)va_arg(ap, void *);
517 			break;
518 		case 'd':
519 		case 'D':
520 		case 'x':
521 		case 'X':
522 		case 'u':
523 		case 'U':
524 		case 'o':
525 		case 'O':
526 			if (ells == 0)
527 				arg = (uint64_t)va_arg(ap, uint_t);
528 			else if (ells == 1)
529 				arg = (uint64_t)va_arg(ap, ulong_t);
530 			else
531 				arg = (uint64_t)va_arg(ap, uint64_t);
532 			break;
533 		default:
534 			arg = (uint64_t)va_arg(ap, uint_t);
535 			break;
536 		}
537 		va_end(ap);
538 		break;
539 	}
540 
541 	/* so new kernel, old boot can print a message before dying */
542 	if (!BOOTOPS_ARE_1275(bop)) {
543 		/* use uintptr_t to suppress the gcc warning */
544 		bsys_printf = (void (*)(struct bootops *, char *, ...))
545 		    (uintptr_t)bop->bsys_printf;
546 		(*bsys_printf)(bop, (char *)string, arg);
547 		return;
548 	}
549 
550 	bsys_1275_call = (int (*)(void *))bop->bsys_1275_call;
551 	args[0] = boot_ptr2cell("putsarg");
552 	args[1] = 2;
553 	args[2] = 0;
554 	args[3] = boot_ptr2cell(string);
555 	args[4] = boot_uint642cell(arg);
556 
557 	(void) (bsys_1275_call)(args);
558 }
559 
560 /*
561  * Implementation of the "mount" boot service.
562  *
563  * Calling spec:
564  * args[0] Service name string
565  * args[1] #argument cells
566  * args[2] #result cells
567  * args[3] pathname string
568  * args[4] Res0: returned result
569  */
570 /*ARGSUSED*/
571 int
572 bop_mountroot(struct bootops *bop, char *path)
573 {
574 	boot_cell_t args[5];
575 	int	(*bsys_1275_call)(void *);
576 
577 	bsys_1275_call = (int (*)(void *))bop->bsys_1275_call;
578 	args[0] = boot_ptr2cell("mountroot");
579 	args[1] = 2;
580 	args[2] = 1;
581 
582 	args[3] = boot_ptr2cell(path);
583 	(void) (bsys_1275_call)(args);
584 	return (boot_cell2int(args[4]));
585 }
586 
587 /*
588  * Implementation of the "unmountroot" boot service.
589  *
590  * Calling spec:
591  * args[0] Service name string
592  * args[1] #argument cells
593  * args[2] #result cells
594  * args[3] Res0: returned result
595  */
596 /*ARGSUSED*/
597 int
598 bop_unmountroot(struct bootops *bop)
599 {
600 	boot_cell_t args[4];
601 	int	(*bsys_1275_call)(void *);
602 
603 	bsys_1275_call = (int (*)(void *))bop->bsys_1275_call;
604 	args[0] = boot_ptr2cell("unmountroot");
605 	args[1] = 0;
606 	args[2] = 1;
607 
608 	(void) (bsys_1275_call)(args);
609 	return (boot_cell2int(args[3]));
610 }
611 
612 /*
613  * Implementation of the "serviceavail" boot service.
614  *
615  * Calling spec:
616  * args[0] Service name string
617  * args[1] #argument cells
618  * args[2] #result cells
619  * args[3] name string of service to be tested for
620  * args[4] Res0: returned version number or 0
621  */
622 /*ARGSUSED*/
623 int
624 bop_serviceavail(struct bootops *bop, char *name)
625 {
626 	boot_cell_t args[5];
627 	int	(*bsys_1275_call)(void *) =
628 	    (int (*)(void *))bop->bsys_1275_call;
629 
630 	args[0] = boot_ptr2cell("serviceavail");
631 	args[1] = 1;
632 	args[2] = 1;
633 
634 	args[3] = boot_ptr2cell(name);
635 	(void) (bsys_1275_call)(args);
636 	return (boot_cell2int(args[4]));
637 }
638 
639 /*
640  * Implementation of the "fstat" boot service.
641  *
642  * Calling spec:
643  * args[0] Service name string
644  * args[1] #argument cells
645  * args[2] #result cells
646  * args[3] fd
647  * args[4] client's stat structure
648  */
649 int
650 bop_fstat(struct bootops *bop, int fd, struct bootstat *st)
651 {
652 	boot_cell_t args[6];
653 	int	(*bsys_1275_call)(void *);
654 
655 	bsys_1275_call = (int (*)(void *))bop->bsys_1275_call;
656 	args[0] = boot_ptr2cell("fstat");
657 	args[1] = 2;
658 	args[2] = 1;
659 	args[3] = boot_int2cell(fd);
660 	args[4] = boot_ptr2cell(st);
661 	(void) (bsys_1275_call)(args);
662 	return (boot_cell2int(args[5]));
663 }
664 
665 /*
666  * Implementation of the "enter_mon" boot service.
667  *
668  * Calling spec:
669  * args[0] Service name string
670  * args[1] #argument cells (0)
671  * args[2] #result cells (0)
672  */
673 void
674 bop_enter_mon(struct bootops *bop)
675 {
676 	boot_cell_t args[4];
677 	int (*bsys_1275_call)(void *);
678 
679 	bsys_1275_call = (int (*)(void *))bop->bsys_1275_call;
680 	args[0] = boot_ptr2cell("enter_mon");
681 	args[1] = 0;
682 	args[2] = 0;
683 	(void) (bsys_1275_call)(args);
684 }
685