source: trunk/minix/commands/ibm/readclock.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 5.9 KB
Line 
1/* setime - set the system time from the real time clock
2 Authors: T. Holm & E. Froese
3 Adapted by: Jorrit .N. Herder */
4
5/************************************************************************/
6/* Readclock was updated for security reasons: openeing /dev/mem no */
7/* longer automatically grants I/O privileges to the calling process */
8/* so that the CMOS' clock could not be read from this program. The */
9/* new approach is to rely on the FS to do the CMOS I/O, via the new */
10/* system call CMOSTIME (which only reads the current clock value and */
11/* cannot update the CMOS clock). */
12/* The original readclock.c is still available under backup.c. */
13/************************************************************************/
14/* */
15/* readclock.c */
16/* */
17/* Read the clock value from the 64 byte CMOS RAM */
18/* area, then set system time. */
19/* */
20/* If the machine ID byte is 0xFC or 0xF8, the device */
21/* /dev/mem exists and can be opened for reading, */
22/* and no errors in the CMOS RAM are reported by the */
23/* RTC, then the time is read from the clock RAM */
24/* area maintained by the RTC. */
25/* */
26/* The clock RAM values are decoded and fed to mktime */
27/* to make a time_t value, then stime(2) is called. */
28/* */
29/* This fails if: */
30/* */
31/* If the machine ID does not match 0xFC or 0xF8 (no */
32/* error message.) */
33/* */
34/* If the machine ID is 0xFC or 0xF8 and /dev/mem */
35/* is missing, or cannot be accessed. */
36/* */
37/* If the RTC reports errors in the CMOS RAM. */
38/* */
39/************************************************************************/
40/* origination 1987-Dec-29 efth */
41/* robustness 1990-Oct-06 C. Sylvain */
42/* incorp. B. Evans ideas 1991-Jul-06 C. Sylvain */
43/* set time & calibrate 1992-Dec-17 Kees J. Bot */
44/* clock timezone 1993-Oct-10 Kees J. Bot */
45/* set CMOS clock 1994-Jun-12 Kees J. Bot */
46/* removed set CMOS 2004-Sep-06 Jorrit N. Herder */
47/************************************************************************/
48
49#include <minix/callnr.h>
50#include <minix/config.h>
51#include <minix/type.h>
52#include <minix/const.h>
53#include <minix/com.h>
54#include <minix/syslib.h>
55
56#include <sys/types.h>
57#include <sys/stat.h>
58#include <sys/ioc_cmos.h>
59#include <stdlib.h>
60#include <unistd.h>
61#include <fcntl.h>
62#include <stdio.h>
63#include <string.h>
64#include <time.h>
65#include <errno.h>
66#include <signal.h>
67#include <ibm/portio.h>
68#include <ibm/cmos.h>
69#include <sys/svrctl.h>
70
71#define MAX_RETRIES 1
72
73int nflag = 0; /* Tell what, but don't do it. */
74int y2kflag = 0; /* Interpret 1980 as 2000 for clock with Y2K bug. */
75
76char clocktz[128]; /* Timezone of the clock. */
77
78#define MACH_ID_ADDR 0xFFFFE /* BIOS Machine ID at FFFF:000E */
79
80#define PC_AT 0xFC /* Machine ID byte for PC/AT,
81 PC/XT286, and PS/2 Models 50, 60 */
82#define PS_386 0xF8 /* Machine ID byte for PS/2 Model 80 */
83
84/* Manufacturers usually use the ID value of the IBM model they emulate.
85 * However some manufacturers, notably HP and COMPAQ, have had different
86 * ideas in the past.
87 *
88 * Machine ID byte information source:
89 * _The Programmer's PC Sourcebook_ by Thom Hogan,
90 * published by Microsoft Press
91 */
92
93void errmsg(char *s);
94int bcd_to_dec(int n);
95int dec_to_bcd(int n);
96void usage(void);
97
98#define CMOS_DEV "/dev/cmos"
99
100PUBLIC int main(int argc, char **argv)
101{
102 int fd;
103 struct tm time1;
104 struct tm time2;
105 struct tm tmnow;
106 char date[64];
107 time_t now, rtc;
108 int i, s, mem;
109 unsigned char mach_id, cmos_state;
110 struct sysgetenv sysgetenv;
111 message m;
112 int request;
113
114
115 /* Process options. */
116 while (argc > 1) {
117 char *p = *++argv;
118
119 if (*p++ != '-') usage();
120
121 while (*p != 0) {
122 switch (*p++) {
123 case 'n': nflag = 1; break;
124 case '2': y2kflag = 1; break;
125 default: usage();
126 }
127 }
128 argc--;
129 }
130
131#if DEAD_CODE
132 /* The hardware clock may run in a different time zone, likely GMT or
133 * winter time. Select that time zone.
134 */
135 strcpy(clocktz, "TZ=");
136 sysgetenv.key = "TZ";
137 sysgetenv.keylen = 2+1;
138 sysgetenv.val = clocktz+3;
139 sysgetenv.vallen = sizeof(clocktz)-3;
140 if (svrctl(SYSGETENV, &sysgetenv) == 0) {
141 putenv(clocktz);
142 tzset();
143 }
144#endif
145
146 /* Read the CMOS real time clock. */
147 for (i = 0; i < MAX_RETRIES; i++) {
148
149 /* sleep, unless first iteration */
150 if (i > 0) sleep(5);
151
152 /* Open the CMOS device to read the system time. */
153 if ((fd = open(CMOS_DEV, O_RDONLY)) < 0) {
154 perror(CMOS_DEV);
155 fprintf(stderr, "Couldn't open CMOS device.\n");
156 exit(1);
157 }
158 request = (y2kflag) ? CIOCGETTIME : CIOCGETTIMEY2K;
159 if ((s=ioctl(fd, request, (void *) &time1)) < 0) {
160 perror("ioctl");
161 fprintf(stderr, "Couldn't do CMOS ioctl.\n");
162 exit(1);
163 }
164 close(fd);
165
166 now = time(NULL);
167
168 time1.tm_isdst = -1; /* Do timezone calculations. */
169 time2 = time1;
170
171 rtc= mktime(&time1); /* Transform to a time_t. */
172 if (rtc != -1) {
173 break;
174 }
175
176 fprintf(stderr,
177"readclock: Invalid time read from CMOS RTC: %d-%02d-%02d %02d:%02d:%02d\n",
178 time2.tm_year+1900, time2.tm_mon+1, time2.tm_mday,
179 time2.tm_hour, time2.tm_min, time2.tm_sec);
180 }
181 if (i >= MAX_RETRIES) exit(1);
182
183 /* Now set system time. */
184 if (nflag) {
185 printf("stime(%lu)\n", (unsigned long) rtc);
186 } else {
187 if (stime(&rtc) < 0) {
188 errmsg( "Not allowed to set time." );
189 exit(1);
190 }
191 }
192 tmnow = *localtime(&rtc);
193 if (strftime(date, sizeof(date),
194 "%a %b %d %H:%M:%S %Z %Y", &tmnow) != 0) {
195 if (date[8] == '0') date[8]= ' ';
196#if 0
197 printf("%s [CMOS read via FS, see command/ibm/readclock.c]\n", date);
198#endif
199 }
200 exit(0);
201}
202
203void errmsg(char *s)
204{
205 static char *prompt = "readclock: ";
206
207 fprintf(stderr, "%s%s\n", prompt, s);
208 prompt = "";
209}
210
211
212int bcd_to_dec(int n)
213{
214 return ((n >> 4) & 0x0F) * 10 + (n & 0x0F);
215}
216
217int dec_to_bcd(int n)
218{
219 return ((n / 10) << 4) | (n % 10);
220}
221
222void usage(void)
223{
224 fprintf(stderr, "Usage: settime [-n2]\n");
225 exit(1);
226}
Note: See TracBrowser for help on using the repository browser.