xref: /illumos-gate/usr/src/uts/sparc/os/bootops.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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 2004 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 		bsys_printf = (void (*)(struct bootops *, char *, ...))
457 		    (bop->bsys_printf);
458 		(*bsys_printf)(bop, string);
459 		return;
460 	}
461 	bsys_1275_call = (int (*)(void *))bop->bsys_1275_call;
462 	args[0] = boot_ptr2cell("puts");
463 	args[1] = 1;
464 	args[2] = 0;
465 
466 	args[3] = boot_ptr2cell(string);
467 	(void) (bsys_1275_call)(args);
468 
469 }
470 
471 /*
472  * Implementation of the "putsarg" boot service.
473  *
474  * Calling spec:
475  * args[0] Service name string
476  * args[1] #argument cells
477  * args[2] #result cells
478  * args[3] string to print (with '%*' format)
479  * args[4] 64-bit thing to print
480  */
481 /*ARGSUSED*/
482 void
483 bop_putsarg(struct bootops *bop, const char *string, ...)
484 {
485 	boot_cell_t	args[6];
486 	int	(*bsys_1275_call)(void *);
487 	void	(*bsys_printf)(struct bootops *, char *, ...);
488 	va_list		ap;
489 	const char	*fmt = string;
490 	int		ells = 0;
491 	uint64_t	arg;
492 
493 	/*
494 	 * We need to do the minimum printf-like stuff here to figure
495 	 * out the size of argument, if present.
496 	 */
497 	while (*fmt) {
498 		if (*fmt++ != '%')
499 			continue;
500 		if (*fmt == '%') {
501 			fmt++;
502 			continue;
503 		}
504 
505 		while (*fmt >= '0' && *fmt <= '9')
506 			fmt++;
507 		for (ells = 0; *fmt == 'l'; fmt++)
508 			ells++;
509 		va_start(ap, string);
510 		switch (*fmt) {
511 		case 's':
512 			arg = (uint64_t)va_arg(ap, char *);
513 			break;
514 		case 'p':
515 			arg = (uint64_t)va_arg(ap, void *);
516 			break;
517 		case 'd':
518 		case 'D':
519 		case 'x':
520 		case 'X':
521 		case 'u':
522 		case 'U':
523 		case 'o':
524 		case 'O':
525 			if (ells == 0)
526 				arg = (uint64_t)va_arg(ap, uint_t);
527 			else if (ells == 1)
528 				arg = (uint64_t)va_arg(ap, ulong_t);
529 			else
530 				arg = (uint64_t)va_arg(ap, uint64_t);
531 			break;
532 		default:
533 			arg = (uint64_t)va_arg(ap, uint_t);
534 			break;
535 		}
536 		va_end(ap);
537 		break;
538 	}
539 
540 	/* so new kernel, old boot can print a message before dying */
541 	if (!BOOTOPS_ARE_1275(bop)) {
542 		bsys_printf = (void (*)(struct bootops *, char *, ...))
543 		    (bop->bsys_printf);
544 		(*bsys_printf)(bop, (char *)string, arg);
545 		return;
546 	}
547 
548 	bsys_1275_call = (int (*)(void *))bop->bsys_1275_call;
549 	args[0] = boot_ptr2cell("putsarg");
550 	args[1] = 2;
551 	args[2] = 0;
552 	args[3] = boot_ptr2cell(string);
553 	args[4] = boot_uint642cell(arg);
554 
555 	(void) (bsys_1275_call)(args);
556 }
557 
558 /*
559  * Implementation of the "mount" boot service.
560  *
561  * Calling spec:
562  * args[0] Service name string
563  * args[1] #argument cells
564  * args[2] #result cells
565  * args[3] pathname string
566  * args[4] Res0: returned result
567  */
568 /*ARGSUSED*/
569 int
570 bop_mountroot(struct bootops *bop, char *path)
571 {
572 	boot_cell_t args[5];
573 	int	(*bsys_1275_call)(void *);
574 
575 	bsys_1275_call = (int (*)(void *))bop->bsys_1275_call;
576 	args[0] = boot_ptr2cell("mountroot");
577 	args[1] = 2;
578 	args[2] = 1;
579 
580 	args[3] = boot_ptr2cell(path);
581 	(void) (bsys_1275_call)(args);
582 	return (boot_cell2int(args[4]));
583 }
584 
585 /*
586  * Implementation of the "unmountroot" boot service.
587  *
588  * Calling spec:
589  * args[0] Service name string
590  * args[1] #argument cells
591  * args[2] #result cells
592  * args[3] Res0: returned result
593  */
594 /*ARGSUSED*/
595 int
596 bop_unmountroot(struct bootops *bop)
597 {
598 	boot_cell_t args[4];
599 	int	(*bsys_1275_call)(void *);
600 
601 	bsys_1275_call = (int (*)(void *))bop->bsys_1275_call;
602 	args[0] = boot_ptr2cell("unmountroot");
603 	args[1] = 0;
604 	args[2] = 1;
605 
606 	(void) (bsys_1275_call)(args);
607 	return (boot_cell2int(args[3]));
608 }
609 
610 /*
611  * Implementation of the "serviceavail" boot service.
612  *
613  * Calling spec:
614  * args[0] Service name string
615  * args[1] #argument cells
616  * args[2] #result cells
617  * args[3] name string of service to be tested for
618  * args[4] Res0: returned version number or 0
619  */
620 /*ARGSUSED*/
621 int
622 bop_serviceavail(struct bootops *bop, char *name)
623 {
624 	boot_cell_t args[5];
625 	int	(*bsys_1275_call)(void *) =
626 	    (int (*)(void *))bop->bsys_1275_call;
627 
628 	args[0] = boot_ptr2cell("serviceavail");
629 	args[1] = 1;
630 	args[2] = 1;
631 
632 	args[3] = boot_ptr2cell(name);
633 	(void) (bsys_1275_call)(args);
634 	return (boot_cell2int(args[4]));
635 }
636 
637 /*
638  * Implementation of the "fstat" boot service.
639  *
640  * Calling spec:
641  * args[0] Service name string
642  * args[1] #argument cells
643  * args[2] #result cells
644  * args[3] fd
645  * args[4] client's stat structure
646  */
647 int
648 bop_fstat(struct bootops *bop, int fd, struct bootstat *st)
649 {
650 	boot_cell_t args[6];
651 	int	(*bsys_1275_call)(void *);
652 
653 	bsys_1275_call = (int (*)(void *))bop->bsys_1275_call;
654 	args[0] = boot_ptr2cell("fstat");
655 	args[1] = 2;
656 	args[2] = 1;
657 	args[3] = boot_int2cell(fd);
658 	args[4] = boot_ptr2cell(st);
659 	(void) (bsys_1275_call)(args);
660 	return (boot_cell2int(args[5]));
661 }
662 
663 /*
664  * Implementation of the "enter_mon" boot service.
665  *
666  * Calling spec:
667  * args[0] Service name string
668  * args[1] #argument cells (0)
669  * args[2] #result cells (0)
670  */
671 void
672 bop_enter_mon(struct bootops *bop)
673 {
674 	boot_cell_t args[4];
675 	int (*bsys_1275_call)(void *);
676 
677 	bsys_1275_call = (int (*)(void *))bop->bsys_1275_call;
678 	args[0] = boot_ptr2cell("enter_mon");
679 	args[1] = 0;
680 	args[2] = 0;
681 	(void) (bsys_1275_call)(args);
682 }
683