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