13446Smrj /*
23446Smrj * CDDL HEADER START
33446Smrj *
43446Smrj * The contents of this file are subject to the terms of the
53446Smrj * Common Development and Distribution License (the "License").
63446Smrj * You may not use this file except in compliance with the License.
73446Smrj *
83446Smrj * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93446Smrj * or http://www.opensolaris.org/os/licensing.
103446Smrj * See the License for the specific language governing permissions
113446Smrj * and limitations under the License.
123446Smrj *
133446Smrj * When distributing Covered Code, include this CDDL HEADER in each
143446Smrj * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153446Smrj * If applicable, add the following below this CDDL HEADER, with the
163446Smrj * fields enclosed by brackets "[]" replaced with your own identifying
173446Smrj * information: Portions Copyright [yyyy] [name of copyright owner]
183446Smrj *
193446Smrj * CDDL HEADER END
203446Smrj */
213446Smrj
223446Smrj /*
233446Smrj * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
243446Smrj * Use is subject to license terms.
253446Smrj */
263446Smrj
273446Smrj #pragma ident "%Z%%M% %I% %E% SMI"
283446Smrj
293446Smrj #include <sys/types.h>
303446Smrj #include <sys/param.h>
313446Smrj #include <sys/machparam.h>
323446Smrj #include <sys/archsystm.h>
333446Smrj #include <sys/boot_console.h>
34*5084Sjohnlev #include <sys/varargs.h>
35*5084Sjohnlev #include "dboot_asm.h"
363446Smrj #include "dboot_printf.h"
37*5084Sjohnlev #include "dboot_xboot.h"
383446Smrj
39*5084Sjohnlev #ifdef __xpv
40*5084Sjohnlev #include <sys/hypervisor.h>
41*5084Sjohnlev #endif
423446Smrj
433446Smrj /*
443446Smrj * This file provides simple output formatting via dboot_printf()
453446Smrj */
463446Smrj
473446Smrj static void do_dboot_printf(char *fmt, va_list args);
483446Smrj
493446Smrj static char digits[] = "0123456789abcdef";
503446Smrj
513446Smrj /*
523446Smrj * Primitive version of panic, prints a message then resets the system
533446Smrj */
543446Smrj void
dboot_panic(char * fmt,...)553446Smrj dboot_panic(char *fmt, ...)
563446Smrj {
573446Smrj va_list args;
583446Smrj
593446Smrj va_start(args, fmt);
603446Smrj do_dboot_printf(fmt, args);
613446Smrj
623446Smrj if (console == CONS_SCREEN_TEXT) {
633446Smrj dboot_printf("Press any key to reboot\n");
643446Smrj (void) bcons_getchar();
653446Smrj }
663446Smrj outb(0x64, 0xfe); /* this resets the system, see pc_reset() */
673446Smrj dboot_halt(); /* just in case */
683446Smrj }
693446Smrj
703446Smrj /*
713446Smrj * printf for boot code
723446Smrj */
733446Smrj void
dboot_printf(char * fmt,...)743446Smrj dboot_printf(char *fmt, ...)
753446Smrj {
763446Smrj va_list args;
773446Smrj
783446Smrj va_start(args, fmt);
793446Smrj do_dboot_printf(fmt, args);
803446Smrj }
813446Smrj
823446Smrj
833446Smrj /*
843446Smrj * output a string
853446Smrj */
863446Smrj static void
dboot_puts(char * s)873446Smrj dboot_puts(char *s)
883446Smrj {
893446Smrj while (*s != 0) {
903446Smrj bcons_putchar(*s);
913446Smrj ++s;
923446Smrj }
933446Smrj }
943446Smrj
953446Smrj static void
dboot_putnum(uint64_t x,uint_t is_signed,uint8_t base)963446Smrj dboot_putnum(uint64_t x, uint_t is_signed, uint8_t base)
973446Smrj {
983446Smrj char buffer[64]; /* digits in reverse order */
993446Smrj int i;
1003446Smrj
1013446Smrj if (is_signed && (int64_t)x < 0) {
1023446Smrj bcons_putchar('-');
1033446Smrj x = -x;
1043446Smrj }
1053446Smrj
1063446Smrj for (i = -1; x != 0 && i <= 63; x /= base)
1073446Smrj buffer[++i] = digits[x - ((x / base) * base)];
1083446Smrj
1093446Smrj if (i < 0)
1103446Smrj buffer[++i] = '0';
1113446Smrj
1123446Smrj while (i >= 0)
1133446Smrj bcons_putchar(buffer[i--]);
1143446Smrj }
1153446Smrj
1163446Smrj /*
1173446Smrj * very primitive printf - only does %s, %d, %x, %lx, or %%
1183446Smrj */
1193446Smrj static void
do_dboot_printf(char * fmt,va_list args)1203446Smrj do_dboot_printf(char *fmt, va_list args)
1213446Smrj {
1223446Smrj char *s;
1233446Smrj uint64_t x;
1243446Smrj uint8_t base;
1253446Smrj uint8_t size;
1263446Smrj uint_t is_signed = 1;
1273446Smrj
1283446Smrj if (fmt == NULL) {
1293446Smrj dboot_puts("dboot_printf(): 1st arg is NULL\n");
1303446Smrj return;
1313446Smrj }
1323446Smrj for (; *fmt; ++fmt) {
1333446Smrj if (*fmt != '%') {
1343446Smrj bcons_putchar(*fmt);
1353446Smrj continue;
1363446Smrj }
1373446Smrj
1383446Smrj size = 0;
1393446Smrj again:
1403446Smrj ++fmt;
1413446Smrj switch (*fmt) {
1423446Smrj
1433446Smrj case '%':
1443446Smrj bcons_putchar(*fmt);
1453446Smrj break;
1463446Smrj
1473446Smrj case 'c':
1483446Smrj x = va_arg(args, int);
1493446Smrj bcons_putchar(x);
1503446Smrj break;
1513446Smrj
1523446Smrj case 's':
1533446Smrj s = va_arg(args, char *);
1543446Smrj if (s == NULL)
1553446Smrj dboot_puts("*NULL*");
1563446Smrj else
1573446Smrj dboot_puts(s);
1583446Smrj break;
1593446Smrj
1603446Smrj case 'p':
1613446Smrj x = va_arg(args, ulong_t);
1623446Smrj dboot_putnum(x, !is_signed, 16);
1633446Smrj break;
1643446Smrj
1653446Smrj case 'l':
1663446Smrj if (size == 0)
1673446Smrj size = sizeof (long);
1683446Smrj else if (size == sizeof (long))
1693446Smrj size = sizeof (long long);
1703446Smrj goto again;
1713446Smrj
1723446Smrj case 'd':
1733446Smrj if (size == 0)
1743446Smrj x = va_arg(args, int);
1753446Smrj else if (size == sizeof (long))
1763446Smrj x = va_arg(args, long);
1773446Smrj else
1783446Smrj x = va_arg(args, long long);
1793446Smrj dboot_putnum(x, is_signed, 10);
1803446Smrj break;
1813446Smrj
1823446Smrj case 'b':
1833446Smrj base = 2;
1843446Smrj goto unsigned_num;
1853446Smrj
1863446Smrj case 'o':
1873446Smrj base = 8;
1883446Smrj goto unsigned_num;
1893446Smrj
1903446Smrj case 'x':
1913446Smrj base = 16;
1923446Smrj unsigned_num:
1933446Smrj if (size == 0)
1943446Smrj x = va_arg(args, uint_t);
1953446Smrj else if (size == sizeof (long))
1963446Smrj x = va_arg(args, ulong_t);
1973446Smrj else
1983446Smrj x = va_arg(args, unsigned long long);
1993446Smrj dboot_putnum(x, !is_signed, base);
2003446Smrj break;
2013446Smrj
2023446Smrj default:
2033446Smrj dboot_puts("dboot_printf(): unknown % escape\n");
2043446Smrj }
2053446Smrj }
2063446Smrj }
207