1ae115bc7Smrj /*
2ae115bc7Smrj * CDDL HEADER START
3ae115bc7Smrj *
4ae115bc7Smrj * The contents of this file are subject to the terms of the
5ae115bc7Smrj * Common Development and Distribution License (the "License").
6ae115bc7Smrj * You may not use this file except in compliance with the License.
7ae115bc7Smrj *
8ae115bc7Smrj * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9ae115bc7Smrj * or http://www.opensolaris.org/os/licensing.
10ae115bc7Smrj * See the License for the specific language governing permissions
11ae115bc7Smrj * and limitations under the License.
12ae115bc7Smrj *
13ae115bc7Smrj * When distributing Covered Code, include this CDDL HEADER in each
14ae115bc7Smrj * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15ae115bc7Smrj * If applicable, add the following below this CDDL HEADER, with the
16ae115bc7Smrj * fields enclosed by brackets "[]" replaced with your own identifying
17ae115bc7Smrj * information: Portions Copyright [yyyy] [name of copyright owner]
18ae115bc7Smrj *
19ae115bc7Smrj * CDDL HEADER END
20ae115bc7Smrj */
21ae115bc7Smrj
22ae115bc7Smrj /*
230d928757SGary Mills * Copyright (c) 2012 Gary Mills
24*101bc1d0SJohn Levon * Copyright 2020 Joyent, Inc.
250d928757SGary Mills *
26ae115bc7Smrj * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
27ae115bc7Smrj * Use is subject to license terms.
28ae115bc7Smrj */
29ae115bc7Smrj
30ae115bc7Smrj #include <sys/types.h>
31ae115bc7Smrj #include <sys/param.h>
32ae115bc7Smrj #include <sys/machparam.h>
33ae115bc7Smrj #include <sys/archsystm.h>
34ae115bc7Smrj #include <sys/boot_console.h>
35843e1988Sjohnlev #include <sys/varargs.h>
36843e1988Sjohnlev #include "dboot_asm.h"
37ae115bc7Smrj #include "dboot_printf.h"
38ae115bc7Smrj #include "dboot_xboot.h"
39843e1988Sjohnlev
40843e1988Sjohnlev #ifdef __xpv
41843e1988Sjohnlev #include <sys/hypervisor.h>
42843e1988Sjohnlev #endif
43ae115bc7Smrj
44ae115bc7Smrj /*
45ae115bc7Smrj * This file provides simple output formatting via dboot_printf()
46ae115bc7Smrj */
47ae115bc7Smrj
48ae115bc7Smrj static void do_dboot_printf(char *fmt, va_list args);
49ae115bc7Smrj
50ae115bc7Smrj static char digits[] = "0123456789abcdef";
51ae115bc7Smrj
52ae115bc7Smrj /*
53ae115bc7Smrj * Primitive version of panic, prints a message then resets the system
54ae115bc7Smrj */
55ae115bc7Smrj void
dboot_panic(char * fmt,...)56ae115bc7Smrj dboot_panic(char *fmt, ...)
57ae115bc7Smrj {
58ae115bc7Smrj va_list args;
59ae115bc7Smrj
60ae115bc7Smrj va_start(args, fmt);
61ae115bc7Smrj do_dboot_printf(fmt, args);
62ae115bc7Smrj
630d928757SGary Mills if (boot_console_type(NULL) == CONS_SCREEN_TEXT) {
64ae115bc7Smrj dboot_printf("Press any key to reboot\n");
65ae115bc7Smrj (void) bcons_getchar();
66ae115bc7Smrj }
67ae115bc7Smrj outb(0x64, 0xfe); /* this resets the system, see pc_reset() */
68ae115bc7Smrj dboot_halt(); /* just in case */
69ae115bc7Smrj }
70ae115bc7Smrj
71ae115bc7Smrj /*
72ae115bc7Smrj * printf for boot code
73ae115bc7Smrj */
74ae115bc7Smrj void
dboot_printf(char * fmt,...)75ae115bc7Smrj dboot_printf(char *fmt, ...)
76ae115bc7Smrj {
77ae115bc7Smrj va_list args;
78ae115bc7Smrj
79ae115bc7Smrj va_start(args, fmt);
80ae115bc7Smrj do_dboot_printf(fmt, args);
81ae115bc7Smrj }
82ae115bc7Smrj
83ae115bc7Smrj
84ae115bc7Smrj /*
85ae115bc7Smrj * output a string
86ae115bc7Smrj */
87ae115bc7Smrj static void
dboot_puts(char * s)88ae115bc7Smrj dboot_puts(char *s)
89ae115bc7Smrj {
90ae115bc7Smrj while (*s != 0) {
91ae115bc7Smrj bcons_putchar(*s);
92ae115bc7Smrj ++s;
93ae115bc7Smrj }
94ae115bc7Smrj }
95ae115bc7Smrj
96ae115bc7Smrj static void
dboot_putnum(uint64_t x,boolean_t is_signed,uint8_t base)97*101bc1d0SJohn Levon dboot_putnum(uint64_t x, boolean_t is_signed, uint8_t base)
98ae115bc7Smrj {
99ae115bc7Smrj char buffer[64]; /* digits in reverse order */
100ae115bc7Smrj int i;
101ae115bc7Smrj
102ae115bc7Smrj if (is_signed && (int64_t)x < 0) {
103ae115bc7Smrj bcons_putchar('-');
104ae115bc7Smrj x = -x;
105ae115bc7Smrj }
106ae115bc7Smrj
107ae115bc7Smrj for (i = -1; x != 0 && i <= 63; x /= base)
108ae115bc7Smrj buffer[++i] = digits[x - ((x / base) * base)];
109ae115bc7Smrj
110ae115bc7Smrj if (i < 0)
111ae115bc7Smrj buffer[++i] = '0';
112ae115bc7Smrj
113ae115bc7Smrj while (i >= 0)
114ae115bc7Smrj bcons_putchar(buffer[i--]);
115ae115bc7Smrj }
116ae115bc7Smrj
117ae115bc7Smrj /*
118*101bc1d0SJohn Levon * Very primitive printf - only does a subset of the standard format characters.
119ae115bc7Smrj */
120ae115bc7Smrj static void
do_dboot_printf(char * fmt,va_list args)121ae115bc7Smrj do_dboot_printf(char *fmt, va_list args)
122ae115bc7Smrj {
123ae115bc7Smrj char *s;
124ae115bc7Smrj uint64_t x;
125ae115bc7Smrj uint8_t base;
126ae115bc7Smrj uint8_t size;
127ae115bc7Smrj
128ae115bc7Smrj if (fmt == NULL) {
129ae115bc7Smrj dboot_puts("dboot_printf(): 1st arg is NULL\n");
130ae115bc7Smrj return;
131ae115bc7Smrj }
132ae115bc7Smrj for (; *fmt; ++fmt) {
133ae115bc7Smrj if (*fmt != '%') {
134ae115bc7Smrj bcons_putchar(*fmt);
135ae115bc7Smrj continue;
136ae115bc7Smrj }
137ae115bc7Smrj
138ae115bc7Smrj size = 0;
139ae115bc7Smrj again:
140ae115bc7Smrj ++fmt;
141ae115bc7Smrj switch (*fmt) {
142ae115bc7Smrj
143ae115bc7Smrj case '%':
144ae115bc7Smrj bcons_putchar(*fmt);
145ae115bc7Smrj break;
146ae115bc7Smrj
147ae115bc7Smrj case 'c':
148ae115bc7Smrj x = va_arg(args, int);
149ae115bc7Smrj bcons_putchar(x);
150ae115bc7Smrj break;
151ae115bc7Smrj
152ae115bc7Smrj case 's':
153ae115bc7Smrj s = va_arg(args, char *);
154ae115bc7Smrj if (s == NULL)
155ae115bc7Smrj dboot_puts("*NULL*");
156ae115bc7Smrj else
157ae115bc7Smrj dboot_puts(s);
158ae115bc7Smrj break;
159ae115bc7Smrj
160ae115bc7Smrj case 'p':
161ae115bc7Smrj x = va_arg(args, ulong_t);
162*101bc1d0SJohn Levon dboot_putnum(x, B_FALSE, 16);
163ae115bc7Smrj break;
164ae115bc7Smrj
165ae115bc7Smrj case 'l':
166ae115bc7Smrj if (size == 0)
167ae115bc7Smrj size = sizeof (long);
168ae115bc7Smrj else if (size == sizeof (long))
169ae115bc7Smrj size = sizeof (long long);
170ae115bc7Smrj goto again;
171ae115bc7Smrj
172ae115bc7Smrj case 'd':
173ae115bc7Smrj if (size == 0)
174ae115bc7Smrj x = va_arg(args, int);
175ae115bc7Smrj else if (size == sizeof (long))
176ae115bc7Smrj x = va_arg(args, long);
177ae115bc7Smrj else
178ae115bc7Smrj x = va_arg(args, long long);
179*101bc1d0SJohn Levon dboot_putnum(x, B_TRUE, 10);
180ae115bc7Smrj break;
181ae115bc7Smrj
182*101bc1d0SJohn Levon case 'u':
183*101bc1d0SJohn Levon base = 10;
184*101bc1d0SJohn Levon goto unsigned_num;
185*101bc1d0SJohn Levon
186ae115bc7Smrj case 'b':
187ae115bc7Smrj base = 2;
188ae115bc7Smrj goto unsigned_num;
189ae115bc7Smrj
190ae115bc7Smrj case 'o':
191ae115bc7Smrj base = 8;
192ae115bc7Smrj goto unsigned_num;
193ae115bc7Smrj
194ae115bc7Smrj case 'x':
195ae115bc7Smrj base = 16;
196ae115bc7Smrj unsigned_num:
197ae115bc7Smrj if (size == 0)
198ae115bc7Smrj x = va_arg(args, uint_t);
199*101bc1d0SJohn Levon else if (size == sizeof (ulong_t))
200ae115bc7Smrj x = va_arg(args, ulong_t);
201ae115bc7Smrj else
202ae115bc7Smrj x = va_arg(args, unsigned long long);
203*101bc1d0SJohn Levon dboot_putnum(x, B_FALSE, base);
204ae115bc7Smrj break;
205ae115bc7Smrj
206ae115bc7Smrj default:
207ae115bc7Smrj dboot_puts("dboot_printf(): unknown % escape\n");
208ae115bc7Smrj }
209ae115bc7Smrj }
210ae115bc7Smrj }
211