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