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 2005 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 #include <stdio.h> 30 #include <stdlib.h> 31 #include <ctype.h> 32 #include <string.h> 33 #include <sys/param.h> 34 #include <sys/types.h> 35 #include <sys/utsname.h> 36 #include <stdarg.h> 37 #include <syslog.h> 38 #include <sys/openpromio.h> 39 #include <libintl.h> 40 #include "pdevinfo.h" 41 #include "display.h" 42 43 #if !defined(TEXT_DOMAIN) 44 #define TEXT_DOMAIN "SYS_TEST" 45 #endif 46 47 /* 48 * external data 49 */ 50 extern int print_flag; 51 extern int logging; 52 53 /* 54 * The following macros for dealing with raw output from the Mostek 48T02 55 * were borrowed from the kernel. Openboot passes the raw Mostek data 56 * thru the device tree, and there are no library routines to deal with 57 * this data. 58 */ 59 60 /* 61 * Tables to convert a single byte from binary-coded decimal (BCD). 62 */ 63 static uchar_t bcd_to_byte[256] = { /* CSTYLED */ 64 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 65 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 0, 66 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 0, 0, 0, 0, 0, 0, 67 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 0, 0, 0, 0, 0, 0, 68 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 0, 0, 0, 0, 0, 0, 69 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 0, 0, 0, 0, 0, 0, 70 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 0, 0, 0, 0, 0, 0, 71 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 0, 0, 0, 0, 0, 0, 72 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 0, 0, 0, 0, 0, 0, 73 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 74 }; 75 76 #define BCD_TO_BYTE(x) bcd_to_byte[(x) & 0xff] 77 #define YRBASE 68 78 79 static int days_thru_month[64] = { 80 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366, 0, 0, 81 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365, 0, 0, 82 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365, 0, 0, 83 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365, 0, 0, 84 }; 85 86 /* 87 * This function takes the raw Mostek data from the device tree translates 88 * it into UNIXC time (secs since Jan 1, 1970) and returns a string from 89 * ctime(3c). 90 */ 91 char * 92 get_time(uchar_t *mostek) 93 { 94 time_t utc; 95 int sec, min, hour, day, month, year; 96 97 year = BCD_TO_BYTE(mostek[6]) + YRBASE; 98 month = BCD_TO_BYTE(mostek[5] & 0x1f) + ((year & 3) << 4); 99 day = BCD_TO_BYTE(mostek[4] & 0x3f); 100 hour = BCD_TO_BYTE(mostek[2] & 0x3f); 101 min = BCD_TO_BYTE(mostek[1] & 0x7f); 102 sec = BCD_TO_BYTE(mostek[0] & 0x7f); 103 104 utc = (year - 70); /* next 3 lines: utc = 365y + y/4 */ 105 utc += (utc << 3) + (utc << 6); 106 utc += (utc << 2) + ((year - 69) >> 2); 107 utc += days_thru_month[month] + day - 1; 108 utc = (utc << 3) + (utc << 4) + hour; /* 24 * day + hour */ 109 utc = (utc << 6) - (utc << 2) + min; /* 60 * hour + min */ 110 utc = (utc << 6) - (utc << 2) + sec; /* 60 * min + sec */ 111 112 return (ctime((time_t *)&utc)); 113 } 114 115 void 116 disp_powerfail(Prom_node *root) 117 { 118 Prom_node *pnode; 119 char *option_str = "options"; 120 char *pf_str = "powerfail-time"; 121 char *value_str; 122 time_t value; 123 124 pnode = dev_find_node(root, option_str); 125 if (pnode == NULL) { 126 return; 127 } 128 129 value_str = get_prop_val(find_prop(pnode, pf_str)); 130 if (value_str == NULL) { 131 return; 132 } 133 134 value = (time_t)atoi(value_str); 135 if (value == 0) 136 return; 137 138 (void) log_printf( 139 dgettext(TEXT_DOMAIN, 140 "Most recent AC Power Failure:\n")); 141 (void) log_printf("=============================\n"); 142 (void) log_printf("%s", ctime(&value)); 143 (void) log_printf("\n"); 144 } 145 146 147 /*VARARGS1*/ 148 void 149 log_printf(char *fmt, ...) 150 { 151 va_list ap; 152 int len; 153 static char bigbuf[4096]; 154 char buffer[1024]; 155 156 if (print_flag == 0) { 157 return; 158 } 159 160 va_start(ap, fmt); 161 if (logging != 0) { 162 len = vsprintf(buffer, fmt, ap); 163 (void) strcat(bigbuf, buffer); 164 165 /* we only call to syslog when we get the entire line. */ 166 if (buffer[len-1] == '\n') { 167 syslog(LOG_DAEMON|LOG_NOTICE, bigbuf); 168 bigbuf[0] = 0; 169 } 170 171 } else { 172 (void) vprintf(fmt, ap); 173 } 174 va_end(ap); 175 } 176 177 void 178 print_header(int board) 179 { 180 log_printf("\n"); 181 log_printf(dgettext(TEXT_DOMAIN, 182 "Analysis for Board %d\n"), board, 0); 183 log_printf("--------------------\n", 0); 184 } 185