xref: /openbmc/linux/drivers/char/nvram.c (revision d5bbb502)
1 /*
2  * CMOS/NV-RAM driver for Linux
3  *
4  * Copyright (C) 1997 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
5  * idea by and with help from Richard Jelinek <rj@suse.de>
6  * Portions copyright (c) 2001,2002 Sun Microsystems (thockin@sun.com)
7  *
8  * This driver allows you to access the contents of the non-volatile memory in
9  * the mc146818rtc.h real-time clock. This chip is built into all PCs and into
10  * many Atari machines. In the former it's called "CMOS-RAM", in the latter
11  * "NVRAM" (NV stands for non-volatile).
12  *
13  * The data are supplied as a (seekable) character device, /dev/nvram. The
14  * size of this file is dependent on the controller.  The usual size is 114,
15  * the number of freely available bytes in the memory (i.e., not used by the
16  * RTC itself).
17  *
18  * Checksums over the NVRAM contents are managed by this driver. In case of a
19  * bad checksum, reads and writes return -EIO. The checksum can be initialized
20  * to a sane state either by ioctl(NVRAM_INIT) (clear whole NVRAM) or
21  * ioctl(NVRAM_SETCKS) (doesn't change contents, just makes checksum valid
22  * again; use with care!)
23  *
24  * 	1.1	Cesar Barros: SMP locking fixes
25  * 		added changelog
26  * 	1.2	Erik Gilling: Cobalt Networks support
27  * 		Tim Hockin: general cleanup, Cobalt support
28  * 	1.3	Wim Van Sebroeck: convert PRINT_PROC to seq_file
29  */
30 
31 #define NVRAM_VERSION	"1.3"
32 
33 #include <linux/module.h>
34 #include <linux/nvram.h>
35 #include <linux/types.h>
36 #include <linux/errno.h>
37 #include <linux/miscdevice.h>
38 #include <linux/ioport.h>
39 #include <linux/fcntl.h>
40 #include <linux/mc146818rtc.h>
41 #include <linux/init.h>
42 #include <linux/proc_fs.h>
43 #include <linux/seq_file.h>
44 #include <linux/spinlock.h>
45 #include <linux/io.h>
46 #include <linux/uaccess.h>
47 #include <linux/mutex.h>
48 #include <linux/pagemap.h>
49 
50 
51 static DEFINE_MUTEX(nvram_mutex);
52 static DEFINE_SPINLOCK(nvram_state_lock);
53 static int nvram_open_cnt;	/* #times opened */
54 static int nvram_open_mode;	/* special open modes */
55 static ssize_t nvram_size;
56 #define NVRAM_WRITE		1 /* opened for writing (exclusive) */
57 #define NVRAM_EXCL		2 /* opened with O_EXCL */
58 
59 #ifdef CONFIG_X86
60 /*
61  * These functions are provided to be called internally or by other parts of
62  * the kernel. It's up to the caller to ensure correct checksum before reading
63  * or after writing (needs to be done only once).
64  *
65  * It is worth noting that these functions all access bytes of general
66  * purpose memory in the NVRAM - that is to say, they all add the
67  * NVRAM_FIRST_BYTE offset.  Pass them offsets into NVRAM as if you did not
68  * know about the RTC cruft.
69  */
70 
71 #define NVRAM_BYTES		(128 - NVRAM_FIRST_BYTE)
72 
73 /* Note that *all* calls to CMOS_READ and CMOS_WRITE must be done with
74  * rtc_lock held. Due to the index-port/data-port design of the RTC, we
75  * don't want two different things trying to get to it at once. (e.g. the
76  * periodic 11 min sync from kernel/time/ntp.c vs. this driver.)
77  */
78 
79 static unsigned char __nvram_read_byte(int i)
80 {
81 	return CMOS_READ(NVRAM_FIRST_BYTE + i);
82 }
83 
84 static unsigned char pc_nvram_read_byte(int i)
85 {
86 	unsigned long flags;
87 	unsigned char c;
88 
89 	spin_lock_irqsave(&rtc_lock, flags);
90 	c = __nvram_read_byte(i);
91 	spin_unlock_irqrestore(&rtc_lock, flags);
92 	return c;
93 }
94 
95 /* This races nicely with trying to read with checksum checking (nvram_read) */
96 static void __nvram_write_byte(unsigned char c, int i)
97 {
98 	CMOS_WRITE(c, NVRAM_FIRST_BYTE + i);
99 }
100 
101 static void pc_nvram_write_byte(unsigned char c, int i)
102 {
103 	unsigned long flags;
104 
105 	spin_lock_irqsave(&rtc_lock, flags);
106 	__nvram_write_byte(c, i);
107 	spin_unlock_irqrestore(&rtc_lock, flags);
108 }
109 
110 /* On PCs, the checksum is built only over bytes 2..31 */
111 #define PC_CKS_RANGE_START	2
112 #define PC_CKS_RANGE_END	31
113 #define PC_CKS_LOC		32
114 
115 static int __nvram_check_checksum(void)
116 {
117 	int i;
118 	unsigned short sum = 0;
119 	unsigned short expect;
120 
121 	for (i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; ++i)
122 		sum += __nvram_read_byte(i);
123 	expect = __nvram_read_byte(PC_CKS_LOC)<<8 |
124 	    __nvram_read_byte(PC_CKS_LOC+1);
125 	return (sum & 0xffff) == expect;
126 }
127 
128 static void __nvram_set_checksum(void)
129 {
130 	int i;
131 	unsigned short sum = 0;
132 
133 	for (i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; ++i)
134 		sum += __nvram_read_byte(i);
135 	__nvram_write_byte(sum >> 8, PC_CKS_LOC);
136 	__nvram_write_byte(sum & 0xff, PC_CKS_LOC + 1);
137 }
138 
139 #if 0
140 void nvram_set_checksum(void)
141 {
142 	unsigned long flags;
143 
144 	spin_lock_irqsave(&rtc_lock, flags);
145 	__nvram_set_checksum();
146 	spin_unlock_irqrestore(&rtc_lock, flags);
147 }
148 #endif  /*  0  */
149 
150 static ssize_t pc_nvram_get_size(void)
151 {
152 	return NVRAM_BYTES;
153 }
154 
155 const struct nvram_ops arch_nvram_ops = {
156 	.read_byte      = pc_nvram_read_byte,
157 	.write_byte     = pc_nvram_write_byte,
158 	.get_size       = pc_nvram_get_size,
159 };
160 EXPORT_SYMBOL(arch_nvram_ops);
161 #endif /* CONFIG_X86 */
162 
163 /*
164  * The are the file operation function for user access to /dev/nvram
165  */
166 
167 static loff_t nvram_misc_llseek(struct file *file, loff_t offset, int origin)
168 {
169 	return generic_file_llseek_size(file, offset, origin, MAX_LFS_FILESIZE,
170 					nvram_size);
171 }
172 
173 static ssize_t nvram_misc_read(struct file *file, char __user *buf,
174 			       size_t count, loff_t *ppos)
175 {
176 	unsigned char contents[NVRAM_BYTES];
177 	unsigned i = *ppos;
178 	unsigned char *tmp;
179 
180 	spin_lock_irq(&rtc_lock);
181 
182 	if (!__nvram_check_checksum())
183 		goto checksum_err;
184 
185 	for (tmp = contents; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp)
186 		*tmp = __nvram_read_byte(i);
187 
188 	spin_unlock_irq(&rtc_lock);
189 
190 	if (copy_to_user(buf, contents, tmp - contents))
191 		return -EFAULT;
192 
193 	*ppos = i;
194 
195 	return tmp - contents;
196 
197 checksum_err:
198 	spin_unlock_irq(&rtc_lock);
199 	return -EIO;
200 }
201 
202 static ssize_t nvram_misc_write(struct file *file, const char __user *buf,
203 				size_t count, loff_t *ppos)
204 {
205 	unsigned char contents[NVRAM_BYTES];
206 	unsigned i = *ppos;
207 	unsigned char *tmp;
208 
209 	if (i >= NVRAM_BYTES)
210 		return 0;	/* Past EOF */
211 
212 	if (count > NVRAM_BYTES - i)
213 		count = NVRAM_BYTES - i;
214 	if (count > NVRAM_BYTES)
215 		return -EFAULT;	/* Can't happen, but prove it to gcc */
216 
217 	if (copy_from_user(contents, buf, count))
218 		return -EFAULT;
219 
220 	spin_lock_irq(&rtc_lock);
221 
222 	if (!__nvram_check_checksum())
223 		goto checksum_err;
224 
225 	for (tmp = contents; count--; ++i, ++tmp)
226 		__nvram_write_byte(*tmp, i);
227 
228 	__nvram_set_checksum();
229 
230 	spin_unlock_irq(&rtc_lock);
231 
232 	*ppos = i;
233 
234 	return tmp - contents;
235 
236 checksum_err:
237 	spin_unlock_irq(&rtc_lock);
238 	return -EIO;
239 }
240 
241 static long nvram_misc_ioctl(struct file *file, unsigned int cmd,
242 			     unsigned long arg)
243 {
244 	int i;
245 
246 	switch (cmd) {
247 
248 	case NVRAM_INIT:
249 		/* initialize NVRAM contents and checksum */
250 		if (!capable(CAP_SYS_ADMIN))
251 			return -EACCES;
252 
253 		mutex_lock(&nvram_mutex);
254 		spin_lock_irq(&rtc_lock);
255 
256 		for (i = 0; i < NVRAM_BYTES; ++i)
257 			__nvram_write_byte(0, i);
258 		__nvram_set_checksum();
259 
260 		spin_unlock_irq(&rtc_lock);
261 		mutex_unlock(&nvram_mutex);
262 		return 0;
263 
264 	case NVRAM_SETCKS:
265 		/* just set checksum, contents unchanged (maybe useful after
266 		 * checksum garbaged somehow...) */
267 		if (!capable(CAP_SYS_ADMIN))
268 			return -EACCES;
269 
270 		mutex_lock(&nvram_mutex);
271 		spin_lock_irq(&rtc_lock);
272 		__nvram_set_checksum();
273 		spin_unlock_irq(&rtc_lock);
274 		mutex_unlock(&nvram_mutex);
275 		return 0;
276 
277 	default:
278 		return -ENOTTY;
279 	}
280 }
281 
282 static int nvram_misc_open(struct inode *inode, struct file *file)
283 {
284 	spin_lock(&nvram_state_lock);
285 
286 	if ((nvram_open_cnt && (file->f_flags & O_EXCL)) ||
287 	    (nvram_open_mode & NVRAM_EXCL) ||
288 	    ((file->f_mode & FMODE_WRITE) && (nvram_open_mode & NVRAM_WRITE))) {
289 		spin_unlock(&nvram_state_lock);
290 		return -EBUSY;
291 	}
292 
293 	if (file->f_flags & O_EXCL)
294 		nvram_open_mode |= NVRAM_EXCL;
295 	if (file->f_mode & FMODE_WRITE)
296 		nvram_open_mode |= NVRAM_WRITE;
297 	nvram_open_cnt++;
298 
299 	spin_unlock(&nvram_state_lock);
300 
301 	return 0;
302 }
303 
304 static int nvram_misc_release(struct inode *inode, struct file *file)
305 {
306 	spin_lock(&nvram_state_lock);
307 
308 	nvram_open_cnt--;
309 
310 	/* if only one instance is open, clear the EXCL bit */
311 	if (nvram_open_mode & NVRAM_EXCL)
312 		nvram_open_mode &= ~NVRAM_EXCL;
313 	if (file->f_mode & FMODE_WRITE)
314 		nvram_open_mode &= ~NVRAM_WRITE;
315 
316 	spin_unlock(&nvram_state_lock);
317 
318 	return 0;
319 }
320 
321 #if defined(CONFIG_X86) && defined(CONFIG_PROC_FS)
322 static const char * const floppy_types[] = {
323 	"none", "5.25'' 360k", "5.25'' 1.2M", "3.5'' 720k", "3.5'' 1.44M",
324 	"3.5'' 2.88M", "3.5'' 2.88M"
325 };
326 
327 static const char * const gfx_types[] = {
328 	"EGA, VGA, ... (with BIOS)",
329 	"CGA (40 cols)",
330 	"CGA (80 cols)",
331 	"monochrome",
332 };
333 
334 static void pc_nvram_proc_read(unsigned char *nvram, struct seq_file *seq,
335 			       void *offset)
336 {
337 	int checksum;
338 	int type;
339 
340 	spin_lock_irq(&rtc_lock);
341 	checksum = __nvram_check_checksum();
342 	spin_unlock_irq(&rtc_lock);
343 
344 	seq_printf(seq, "Checksum status: %svalid\n", checksum ? "" : "not ");
345 
346 	seq_printf(seq, "# floppies     : %d\n",
347 	    (nvram[6] & 1) ? (nvram[6] >> 6) + 1 : 0);
348 	seq_printf(seq, "Floppy 0 type  : ");
349 	type = nvram[2] >> 4;
350 	if (type < ARRAY_SIZE(floppy_types))
351 		seq_printf(seq, "%s\n", floppy_types[type]);
352 	else
353 		seq_printf(seq, "%d (unknown)\n", type);
354 	seq_printf(seq, "Floppy 1 type  : ");
355 	type = nvram[2] & 0x0f;
356 	if (type < ARRAY_SIZE(floppy_types))
357 		seq_printf(seq, "%s\n", floppy_types[type]);
358 	else
359 		seq_printf(seq, "%d (unknown)\n", type);
360 
361 	seq_printf(seq, "HD 0 type      : ");
362 	type = nvram[4] >> 4;
363 	if (type)
364 		seq_printf(seq, "%02x\n", type == 0x0f ? nvram[11] : type);
365 	else
366 		seq_printf(seq, "none\n");
367 
368 	seq_printf(seq, "HD 1 type      : ");
369 	type = nvram[4] & 0x0f;
370 	if (type)
371 		seq_printf(seq, "%02x\n", type == 0x0f ? nvram[12] : type);
372 	else
373 		seq_printf(seq, "none\n");
374 
375 	seq_printf(seq, "HD type 48 data: %d/%d/%d C/H/S, precomp %d, lz %d\n",
376 	    nvram[18] | (nvram[19] << 8),
377 	    nvram[20], nvram[25],
378 	    nvram[21] | (nvram[22] << 8), nvram[23] | (nvram[24] << 8));
379 	seq_printf(seq, "HD type 49 data: %d/%d/%d C/H/S, precomp %d, lz %d\n",
380 	    nvram[39] | (nvram[40] << 8),
381 	    nvram[41], nvram[46],
382 	    nvram[42] | (nvram[43] << 8), nvram[44] | (nvram[45] << 8));
383 
384 	seq_printf(seq, "DOS base memory: %d kB\n", nvram[7] | (nvram[8] << 8));
385 	seq_printf(seq, "Extended memory: %d kB (configured), %d kB (tested)\n",
386 	    nvram[9] | (nvram[10] << 8), nvram[34] | (nvram[35] << 8));
387 
388 	seq_printf(seq, "Gfx adapter    : %s\n",
389 	    gfx_types[(nvram[6] >> 4) & 3]);
390 
391 	seq_printf(seq, "FPU            : %sinstalled\n",
392 	    (nvram[6] & 2) ? "" : "not ");
393 
394 	return;
395 }
396 
397 static int nvram_proc_read(struct seq_file *seq, void *offset)
398 {
399 	unsigned char contents[NVRAM_BYTES];
400 	int i = 0;
401 
402 	spin_lock_irq(&rtc_lock);
403 	for (i = 0; i < NVRAM_BYTES; ++i)
404 		contents[i] = __nvram_read_byte(i);
405 	spin_unlock_irq(&rtc_lock);
406 
407 	pc_nvram_proc_read(contents, seq, offset);
408 
409 	return 0;
410 }
411 #endif /* CONFIG_X86 && CONFIG_PROC_FS */
412 
413 static const struct file_operations nvram_misc_fops = {
414 	.owner		= THIS_MODULE,
415 	.llseek		= nvram_misc_llseek,
416 	.read		= nvram_misc_read,
417 	.write		= nvram_misc_write,
418 	.unlocked_ioctl	= nvram_misc_ioctl,
419 	.open		= nvram_misc_open,
420 	.release	= nvram_misc_release,
421 };
422 
423 static struct miscdevice nvram_misc = {
424 	NVRAM_MINOR,
425 	"nvram",
426 	&nvram_misc_fops,
427 };
428 
429 static int __init nvram_module_init(void)
430 {
431 	int ret;
432 
433 	nvram_size = nvram_get_size();
434 	if (nvram_size < 0)
435 		return nvram_size;
436 
437 	ret = misc_register(&nvram_misc);
438 	if (ret) {
439 		pr_err("nvram: can't misc_register on minor=%d\n", NVRAM_MINOR);
440 		return ret;
441 	}
442 
443 #if defined(CONFIG_X86) && defined(CONFIG_PROC_FS)
444 	if (!proc_create_single("driver/nvram", 0, NULL, nvram_proc_read)) {
445 		pr_err("nvram: can't create /proc/driver/nvram\n");
446 		misc_deregister(&nvram_misc);
447 		return -ENOMEM;
448 	}
449 #endif
450 
451 	pr_info("Non-volatile memory driver v" NVRAM_VERSION "\n");
452 	return 0;
453 }
454 
455 static void __exit nvram_module_exit(void)
456 {
457 #if defined(CONFIG_X86) && defined(CONFIG_PROC_FS)
458 	remove_proc_entry("driver/nvram", NULL);
459 #endif
460 	misc_deregister(&nvram_misc);
461 }
462 
463 module_init(nvram_module_init);
464 module_exit(nvram_module_exit);
465 
466 MODULE_LICENSE("GPL");
467 MODULE_ALIAS_MISCDEV(NVRAM_MINOR);
468