dboot_printf.c revision 0d928757379972073af9fb22bdc827b74e8ba6ac
ae115bc77f6fcde83175c75b4206dc2e50747966mrj/*
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * CDDL HEADER START
ae115bc77f6fcde83175c75b4206dc2e50747966mrj *
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * The contents of this file are subject to the terms of the
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * Common Development and Distribution License (the "License").
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * You may not use this file except in compliance with the License.
ae115bc77f6fcde83175c75b4206dc2e50747966mrj *
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * or http://www.opensolaris.org/os/licensing.
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * See the License for the specific language governing permissions
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * and limitations under the License.
ae115bc77f6fcde83175c75b4206dc2e50747966mrj *
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * When distributing Covered Code, include this CDDL HEADER in each
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * If applicable, add the following below this CDDL HEADER, with the
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * fields enclosed by brackets "[]" replaced with your own identifying
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * information: Portions Copyright [yyyy] [name of copyright owner]
ae115bc77f6fcde83175c75b4206dc2e50747966mrj *
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * CDDL HEADER END
ae115bc77f6fcde83175c75b4206dc2e50747966mrj */
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj/*
0d928757379972073af9fb22bdc827b74e8ba6acGary Mills * Copyright (c) 2012 Gary Mills
0d928757379972073af9fb22bdc827b74e8ba6acGary Mills *
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * Use is subject to license terms.
ae115bc77f6fcde83175c75b4206dc2e50747966mrj */
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#include <sys/types.h>
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#include <sys/param.h>
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#include <sys/machparam.h>
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#include <sys/archsystm.h>
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#include <sys/boot_console.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/varargs.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include "dboot_asm.h"
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#include "dboot_printf.h"
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#include "dboot_xboot.h"
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#ifdef __xpv
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/hypervisor.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#endif
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj/*
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * This file provides simple output formatting via dboot_printf()
ae115bc77f6fcde83175c75b4206dc2e50747966mrj */
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrjstatic void do_dboot_printf(char *fmt, va_list args);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrjstatic char digits[] = "0123456789abcdef";
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj/*
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * Primitive version of panic, prints a message then resets the system
ae115bc77f6fcde83175c75b4206dc2e50747966mrj */
ae115bc77f6fcde83175c75b4206dc2e50747966mrjvoid
ae115bc77f6fcde83175c75b4206dc2e50747966mrjdboot_panic(char *fmt, ...)
ae115bc77f6fcde83175c75b4206dc2e50747966mrj{
ae115bc77f6fcde83175c75b4206dc2e50747966mrj va_list args;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj va_start(args, fmt);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj do_dboot_printf(fmt, args);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
0d928757379972073af9fb22bdc827b74e8ba6acGary Mills if (boot_console_type(NULL) == CONS_SCREEN_TEXT) {
ae115bc77f6fcde83175c75b4206dc2e50747966mrj dboot_printf("Press any key to reboot\n");
ae115bc77f6fcde83175c75b4206dc2e50747966mrj (void) bcons_getchar();
ae115bc77f6fcde83175c75b4206dc2e50747966mrj }
ae115bc77f6fcde83175c75b4206dc2e50747966mrj outb(0x64, 0xfe); /* this resets the system, see pc_reset() */
ae115bc77f6fcde83175c75b4206dc2e50747966mrj dboot_halt(); /* just in case */
ae115bc77f6fcde83175c75b4206dc2e50747966mrj}
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj/*
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * printf for boot code
ae115bc77f6fcde83175c75b4206dc2e50747966mrj */
ae115bc77f6fcde83175c75b4206dc2e50747966mrjvoid
ae115bc77f6fcde83175c75b4206dc2e50747966mrjdboot_printf(char *fmt, ...)
ae115bc77f6fcde83175c75b4206dc2e50747966mrj{
ae115bc77f6fcde83175c75b4206dc2e50747966mrj va_list args;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj va_start(args, fmt);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj do_dboot_printf(fmt, args);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj}
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj/*
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * output a string
ae115bc77f6fcde83175c75b4206dc2e50747966mrj */
ae115bc77f6fcde83175c75b4206dc2e50747966mrjstatic void
ae115bc77f6fcde83175c75b4206dc2e50747966mrjdboot_puts(char *s)
ae115bc77f6fcde83175c75b4206dc2e50747966mrj{
ae115bc77f6fcde83175c75b4206dc2e50747966mrj while (*s != 0) {
ae115bc77f6fcde83175c75b4206dc2e50747966mrj bcons_putchar(*s);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj ++s;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj }
ae115bc77f6fcde83175c75b4206dc2e50747966mrj}
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrjstatic void
ae115bc77f6fcde83175c75b4206dc2e50747966mrjdboot_putnum(uint64_t x, uint_t is_signed, uint8_t base)
ae115bc77f6fcde83175c75b4206dc2e50747966mrj{
ae115bc77f6fcde83175c75b4206dc2e50747966mrj char buffer[64]; /* digits in reverse order */
ae115bc77f6fcde83175c75b4206dc2e50747966mrj int i;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj if (is_signed && (int64_t)x < 0) {
ae115bc77f6fcde83175c75b4206dc2e50747966mrj bcons_putchar('-');
ae115bc77f6fcde83175c75b4206dc2e50747966mrj x = -x;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj }
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj for (i = -1; x != 0 && i <= 63; x /= base)
ae115bc77f6fcde83175c75b4206dc2e50747966mrj buffer[++i] = digits[x - ((x / base) * base)];
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj if (i < 0)
ae115bc77f6fcde83175c75b4206dc2e50747966mrj buffer[++i] = '0';
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj while (i >= 0)
ae115bc77f6fcde83175c75b4206dc2e50747966mrj bcons_putchar(buffer[i--]);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj}
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj/*
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * very primitive printf - only does %s, %d, %x, %lx, or %%
ae115bc77f6fcde83175c75b4206dc2e50747966mrj */
ae115bc77f6fcde83175c75b4206dc2e50747966mrjstatic void
ae115bc77f6fcde83175c75b4206dc2e50747966mrjdo_dboot_printf(char *fmt, va_list args)
ae115bc77f6fcde83175c75b4206dc2e50747966mrj{
ae115bc77f6fcde83175c75b4206dc2e50747966mrj char *s;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj uint64_t x;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj uint8_t base;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj uint8_t size;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj uint_t is_signed = 1;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj if (fmt == NULL) {
ae115bc77f6fcde83175c75b4206dc2e50747966mrj dboot_puts("dboot_printf(): 1st arg is NULL\n");
ae115bc77f6fcde83175c75b4206dc2e50747966mrj return;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj }
ae115bc77f6fcde83175c75b4206dc2e50747966mrj for (; *fmt; ++fmt) {
ae115bc77f6fcde83175c75b4206dc2e50747966mrj if (*fmt != '%') {
ae115bc77f6fcde83175c75b4206dc2e50747966mrj bcons_putchar(*fmt);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj continue;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj }
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj size = 0;
ae115bc77f6fcde83175c75b4206dc2e50747966mrjagain:
ae115bc77f6fcde83175c75b4206dc2e50747966mrj ++fmt;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj switch (*fmt) {
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj case '%':
ae115bc77f6fcde83175c75b4206dc2e50747966mrj bcons_putchar(*fmt);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj break;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj case 'c':
ae115bc77f6fcde83175c75b4206dc2e50747966mrj x = va_arg(args, int);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj bcons_putchar(x);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj break;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj case 's':
ae115bc77f6fcde83175c75b4206dc2e50747966mrj s = va_arg(args, char *);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj if (s == NULL)
ae115bc77f6fcde83175c75b4206dc2e50747966mrj dboot_puts("*NULL*");
ae115bc77f6fcde83175c75b4206dc2e50747966mrj else
ae115bc77f6fcde83175c75b4206dc2e50747966mrj dboot_puts(s);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj break;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj case 'p':
ae115bc77f6fcde83175c75b4206dc2e50747966mrj x = va_arg(args, ulong_t);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj dboot_putnum(x, !is_signed, 16);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj break;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj case 'l':
ae115bc77f6fcde83175c75b4206dc2e50747966mrj if (size == 0)
ae115bc77f6fcde83175c75b4206dc2e50747966mrj size = sizeof (long);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj else if (size == sizeof (long))
ae115bc77f6fcde83175c75b4206dc2e50747966mrj size = sizeof (long long);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj goto again;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj case 'd':
ae115bc77f6fcde83175c75b4206dc2e50747966mrj if (size == 0)
ae115bc77f6fcde83175c75b4206dc2e50747966mrj x = va_arg(args, int);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj else if (size == sizeof (long))
ae115bc77f6fcde83175c75b4206dc2e50747966mrj x = va_arg(args, long);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj else
ae115bc77f6fcde83175c75b4206dc2e50747966mrj x = va_arg(args, long long);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj dboot_putnum(x, is_signed, 10);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj break;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj case 'b':
ae115bc77f6fcde83175c75b4206dc2e50747966mrj base = 2;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj goto unsigned_num;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj case 'o':
ae115bc77f6fcde83175c75b4206dc2e50747966mrj base = 8;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj goto unsigned_num;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj case 'x':
ae115bc77f6fcde83175c75b4206dc2e50747966mrj base = 16;
ae115bc77f6fcde83175c75b4206dc2e50747966mrjunsigned_num:
ae115bc77f6fcde83175c75b4206dc2e50747966mrj if (size == 0)
ae115bc77f6fcde83175c75b4206dc2e50747966mrj x = va_arg(args, uint_t);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj else if (size == sizeof (long))
ae115bc77f6fcde83175c75b4206dc2e50747966mrj x = va_arg(args, ulong_t);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj else
ae115bc77f6fcde83175c75b4206dc2e50747966mrj x = va_arg(args, unsigned long long);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj dboot_putnum(x, !is_signed, base);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj break;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj default:
ae115bc77f6fcde83175c75b4206dc2e50747966mrj dboot_puts("dboot_printf(): unknown % escape\n");
ae115bc77f6fcde83175c75b4206dc2e50747966mrj }
ae115bc77f6fcde83175c75b4206dc2e50747966mrj }
ae115bc77f6fcde83175c75b4206dc2e50747966mrj}