hc
2024-01-04 1543e317f1da31b75942316931e8f491a8920811
kernel/drivers/char/nvram.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * CMOS/NV-RAM driver for Linux
34 *
....@@ -21,13 +22,6 @@
2122 * ioctl(NVRAM_SETCKS) (doesn't change contents, just makes checksum valid
2223 * again; use with care!)
2324 *
24
- * This file also provides some functions for other parts of the kernel that
25
- * want to access the NVRAM: nvram_{read,write,check_checksum,set_checksum}.
26
- * Obviously this can be used only if this driver is always configured into
27
- * the kernel and is not a module. Since the functions are used by some Atari
28
- * drivers, this is the case on the Atari.
29
- *
30
- *
3125 * 1.1 Cesar Barros: SMP locking fixes
3226 * added changelog
3327 * 1.2 Erik Gilling: Cobalt Networks support
....@@ -39,64 +33,6 @@
3933
4034 #include <linux/module.h>
4135 #include <linux/nvram.h>
42
-
43
-#define PC 1
44
-#define ATARI 2
45
-
46
-/* select machine configuration */
47
-#if defined(CONFIG_ATARI)
48
-# define MACH ATARI
49
-#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) /* and ?? */
50
-# define MACH PC
51
-#else
52
-# error Cannot build nvram driver for this machine configuration.
53
-#endif
54
-
55
-#if MACH == PC
56
-
57
-/* RTC in a PC */
58
-#define CHECK_DRIVER_INIT() 1
59
-
60
-/* On PCs, the checksum is built only over bytes 2..31 */
61
-#define PC_CKS_RANGE_START 2
62
-#define PC_CKS_RANGE_END 31
63
-#define PC_CKS_LOC 32
64
-#define NVRAM_BYTES (128-NVRAM_FIRST_BYTE)
65
-
66
-#define mach_check_checksum pc_check_checksum
67
-#define mach_set_checksum pc_set_checksum
68
-#define mach_proc_infos pc_proc_infos
69
-
70
-#endif
71
-
72
-#if MACH == ATARI
73
-
74
-/* Special parameters for RTC in Atari machines */
75
-#include <asm/atarihw.h>
76
-#include <asm/atariints.h>
77
-#define RTC_PORT(x) (TT_RTC_BAS + 2*(x))
78
-#define CHECK_DRIVER_INIT() (MACH_IS_ATARI && ATARIHW_PRESENT(TT_CLK))
79
-
80
-#define NVRAM_BYTES 50
81
-
82
-/* On Ataris, the checksum is over all bytes except the checksum bytes
83
- * themselves; these are at the very end */
84
-#define ATARI_CKS_RANGE_START 0
85
-#define ATARI_CKS_RANGE_END 47
86
-#define ATARI_CKS_LOC 48
87
-
88
-#define mach_check_checksum atari_check_checksum
89
-#define mach_set_checksum atari_set_checksum
90
-#define mach_proc_infos atari_proc_infos
91
-
92
-#endif
93
-
94
-/* Note that *all* calls to CMOS_READ and CMOS_WRITE must be done with
95
- * rtc_lock held. Due to the index-port/data-port design of the RTC, we
96
- * don't want two different things trying to get to it at once. (e.g. the
97
- * periodic 11 min sync from kernel/time/ntp.c vs. this driver.)
98
- */
99
-
10036 #include <linux/types.h>
10137 #include <linux/errno.h>
10238 #include <linux/miscdevice.h>
....@@ -106,28 +42,26 @@
10642 #include <linux/init.h>
10743 #include <linux/proc_fs.h>
10844 #include <linux/seq_file.h>
45
+#include <linux/slab.h>
10946 #include <linux/spinlock.h>
11047 #include <linux/io.h>
11148 #include <linux/uaccess.h>
11249 #include <linux/mutex.h>
11350 #include <linux/pagemap.h>
11451
52
+#ifdef CONFIG_PPC
53
+#include <asm/nvram.h>
54
+#endif
11555
11656 static DEFINE_MUTEX(nvram_mutex);
11757 static DEFINE_SPINLOCK(nvram_state_lock);
11858 static int nvram_open_cnt; /* #times opened */
11959 static int nvram_open_mode; /* special open modes */
60
+static ssize_t nvram_size;
12061 #define NVRAM_WRITE 1 /* opened for writing (exclusive) */
12162 #define NVRAM_EXCL 2 /* opened with O_EXCL */
12263
123
-static int mach_check_checksum(void);
124
-static void mach_set_checksum(void);
125
-
126
-#ifdef CONFIG_PROC_FS
127
-static void mach_proc_infos(unsigned char *contents, struct seq_file *seq,
128
- void *offset);
129
-#endif
130
-
64
+#ifdef CONFIG_X86
13165 /*
13266 * These functions are provided to be called internally or by other parts of
13367 * the kernel. It's up to the caller to ensure correct checksum before reading
....@@ -139,13 +73,20 @@
13973 * know about the RTC cruft.
14074 */
14175
142
-unsigned char __nvram_read_byte(int i)
76
+#define NVRAM_BYTES (128 - NVRAM_FIRST_BYTE)
77
+
78
+/* Note that *all* calls to CMOS_READ and CMOS_WRITE must be done with
79
+ * rtc_lock held. Due to the index-port/data-port design of the RTC, we
80
+ * don't want two different things trying to get to it at once. (e.g. the
81
+ * periodic 11 min sync from kernel/time/ntp.c vs. this driver.)
82
+ */
83
+
84
+static unsigned char __nvram_read_byte(int i)
14385 {
14486 return CMOS_READ(NVRAM_FIRST_BYTE + i);
14587 }
146
-EXPORT_SYMBOL(__nvram_read_byte);
14788
148
-unsigned char nvram_read_byte(int i)
89
+static unsigned char pc_nvram_read_byte(int i)
14990 {
15091 unsigned long flags;
15192 unsigned char c;
....@@ -155,16 +96,14 @@
15596 spin_unlock_irqrestore(&rtc_lock, flags);
15697 return c;
15798 }
158
-EXPORT_SYMBOL(nvram_read_byte);
15999
160100 /* This races nicely with trying to read with checksum checking (nvram_read) */
161
-void __nvram_write_byte(unsigned char c, int i)
101
+static void __nvram_write_byte(unsigned char c, int i)
162102 {
163103 CMOS_WRITE(c, NVRAM_FIRST_BYTE + i);
164104 }
165
-EXPORT_SYMBOL(__nvram_write_byte);
166105
167
-void nvram_write_byte(unsigned char c, int i)
106
+static void pc_nvram_write_byte(unsigned char c, int i)
168107 {
169108 unsigned long flags;
170109
....@@ -172,171 +111,261 @@
172111 __nvram_write_byte(c, i);
173112 spin_unlock_irqrestore(&rtc_lock, flags);
174113 }
175
-EXPORT_SYMBOL(nvram_write_byte);
176114
177
-int __nvram_check_checksum(void)
115
+/* On PCs, the checksum is built only over bytes 2..31 */
116
+#define PC_CKS_RANGE_START 2
117
+#define PC_CKS_RANGE_END 31
118
+#define PC_CKS_LOC 32
119
+
120
+static int __nvram_check_checksum(void)
178121 {
179
- return mach_check_checksum();
180
-}
181
-EXPORT_SYMBOL(__nvram_check_checksum);
122
+ int i;
123
+ unsigned short sum = 0;
124
+ unsigned short expect;
182125
183
-int nvram_check_checksum(void)
184
-{
185
- unsigned long flags;
186
- int rv;
187
-
188
- spin_lock_irqsave(&rtc_lock, flags);
189
- rv = __nvram_check_checksum();
190
- spin_unlock_irqrestore(&rtc_lock, flags);
191
- return rv;
126
+ for (i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; ++i)
127
+ sum += __nvram_read_byte(i);
128
+ expect = __nvram_read_byte(PC_CKS_LOC)<<8 |
129
+ __nvram_read_byte(PC_CKS_LOC+1);
130
+ return (sum & 0xffff) == expect;
192131 }
193
-EXPORT_SYMBOL(nvram_check_checksum);
194132
195133 static void __nvram_set_checksum(void)
196134 {
197
- mach_set_checksum();
135
+ int i;
136
+ unsigned short sum = 0;
137
+
138
+ for (i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; ++i)
139
+ sum += __nvram_read_byte(i);
140
+ __nvram_write_byte(sum >> 8, PC_CKS_LOC);
141
+ __nvram_write_byte(sum & 0xff, PC_CKS_LOC + 1);
198142 }
199143
200
-#if 0
201
-void nvram_set_checksum(void)
144
+static long pc_nvram_set_checksum(void)
202145 {
203
- unsigned long flags;
204
-
205
- spin_lock_irqsave(&rtc_lock, flags);
146
+ spin_lock_irq(&rtc_lock);
206147 __nvram_set_checksum();
207
- spin_unlock_irqrestore(&rtc_lock, flags);
148
+ spin_unlock_irq(&rtc_lock);
149
+ return 0;
208150 }
209
-#endif /* 0 */
151
+
152
+static long pc_nvram_initialize(void)
153
+{
154
+ ssize_t i;
155
+
156
+ spin_lock_irq(&rtc_lock);
157
+ for (i = 0; i < NVRAM_BYTES; ++i)
158
+ __nvram_write_byte(0, i);
159
+ __nvram_set_checksum();
160
+ spin_unlock_irq(&rtc_lock);
161
+ return 0;
162
+}
163
+
164
+static ssize_t pc_nvram_get_size(void)
165
+{
166
+ return NVRAM_BYTES;
167
+}
168
+
169
+static ssize_t pc_nvram_read(char *buf, size_t count, loff_t *ppos)
170
+{
171
+ char *p = buf;
172
+ loff_t i;
173
+
174
+ spin_lock_irq(&rtc_lock);
175
+ if (!__nvram_check_checksum()) {
176
+ spin_unlock_irq(&rtc_lock);
177
+ return -EIO;
178
+ }
179
+ for (i = *ppos; count > 0 && i < NVRAM_BYTES; --count, ++i, ++p)
180
+ *p = __nvram_read_byte(i);
181
+ spin_unlock_irq(&rtc_lock);
182
+
183
+ *ppos = i;
184
+ return p - buf;
185
+}
186
+
187
+static ssize_t pc_nvram_write(char *buf, size_t count, loff_t *ppos)
188
+{
189
+ char *p = buf;
190
+ loff_t i;
191
+
192
+ spin_lock_irq(&rtc_lock);
193
+ if (!__nvram_check_checksum()) {
194
+ spin_unlock_irq(&rtc_lock);
195
+ return -EIO;
196
+ }
197
+ for (i = *ppos; count > 0 && i < NVRAM_BYTES; --count, ++i, ++p)
198
+ __nvram_write_byte(*p, i);
199
+ __nvram_set_checksum();
200
+ spin_unlock_irq(&rtc_lock);
201
+
202
+ *ppos = i;
203
+ return p - buf;
204
+}
205
+
206
+const struct nvram_ops arch_nvram_ops = {
207
+ .read = pc_nvram_read,
208
+ .write = pc_nvram_write,
209
+ .read_byte = pc_nvram_read_byte,
210
+ .write_byte = pc_nvram_write_byte,
211
+ .get_size = pc_nvram_get_size,
212
+ .set_checksum = pc_nvram_set_checksum,
213
+ .initialize = pc_nvram_initialize,
214
+};
215
+EXPORT_SYMBOL(arch_nvram_ops);
216
+#endif /* CONFIG_X86 */
210217
211218 /*
212219 * The are the file operation function for user access to /dev/nvram
213220 */
214221
215
-static loff_t nvram_llseek(struct file *file, loff_t offset, int origin)
222
+static loff_t nvram_misc_llseek(struct file *file, loff_t offset, int origin)
216223 {
217224 return generic_file_llseek_size(file, offset, origin, MAX_LFS_FILESIZE,
218
- NVRAM_BYTES);
225
+ nvram_size);
219226 }
220227
221
-static ssize_t nvram_read(struct file *file, char __user *buf,
222
- size_t count, loff_t *ppos)
228
+static ssize_t nvram_misc_read(struct file *file, char __user *buf,
229
+ size_t count, loff_t *ppos)
223230 {
224
- unsigned char contents[NVRAM_BYTES];
225
- unsigned i = *ppos;
226
- unsigned char *tmp;
231
+ char *tmp;
232
+ ssize_t ret;
227233
228
- spin_lock_irq(&rtc_lock);
229234
230
- if (!__nvram_check_checksum())
231
- goto checksum_err;
235
+ if (*ppos >= nvram_size)
236
+ return 0;
232237
233
- for (tmp = contents; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp)
234
- *tmp = __nvram_read_byte(i);
238
+ count = min_t(size_t, count, nvram_size - *ppos);
239
+ count = min_t(size_t, count, PAGE_SIZE);
235240
236
- spin_unlock_irq(&rtc_lock);
241
+ tmp = kmalloc(count, GFP_KERNEL);
242
+ if (!tmp)
243
+ return -ENOMEM;
237244
238
- if (copy_to_user(buf, contents, tmp - contents))
239
- return -EFAULT;
245
+ ret = nvram_read(tmp, count, ppos);
246
+ if (ret <= 0)
247
+ goto out;
240248
241
- *ppos = i;
249
+ if (copy_to_user(buf, tmp, ret)) {
250
+ *ppos -= ret;
251
+ ret = -EFAULT;
252
+ }
242253
243
- return tmp - contents;
244
-
245
-checksum_err:
246
- spin_unlock_irq(&rtc_lock);
247
- return -EIO;
254
+out:
255
+ kfree(tmp);
256
+ return ret;
248257 }
249258
250
-static ssize_t nvram_write(struct file *file, const char __user *buf,
251
- size_t count, loff_t *ppos)
259
+static ssize_t nvram_misc_write(struct file *file, const char __user *buf,
260
+ size_t count, loff_t *ppos)
252261 {
253
- unsigned char contents[NVRAM_BYTES];
254
- unsigned i = *ppos;
255
- unsigned char *tmp;
262
+ char *tmp;
263
+ ssize_t ret;
256264
257
- if (i >= NVRAM_BYTES)
258
- return 0; /* Past EOF */
265
+ if (*ppos >= nvram_size)
266
+ return 0;
259267
260
- if (count > NVRAM_BYTES - i)
261
- count = NVRAM_BYTES - i;
262
- if (count > NVRAM_BYTES)
263
- return -EFAULT; /* Can't happen, but prove it to gcc */
268
+ count = min_t(size_t, count, nvram_size - *ppos);
269
+ count = min_t(size_t, count, PAGE_SIZE);
264270
265
- if (copy_from_user(contents, buf, count))
266
- return -EFAULT;
271
+ tmp = memdup_user(buf, count);
272
+ if (IS_ERR(tmp))
273
+ return PTR_ERR(tmp);
267274
268
- spin_lock_irq(&rtc_lock);
269
-
270
- if (!__nvram_check_checksum())
271
- goto checksum_err;
272
-
273
- for (tmp = contents; count--; ++i, ++tmp)
274
- __nvram_write_byte(*tmp, i);
275
-
276
- __nvram_set_checksum();
277
-
278
- spin_unlock_irq(&rtc_lock);
279
-
280
- *ppos = i;
281
-
282
- return tmp - contents;
283
-
284
-checksum_err:
285
- spin_unlock_irq(&rtc_lock);
286
- return -EIO;
275
+ ret = nvram_write(tmp, count, ppos);
276
+ kfree(tmp);
277
+ return ret;
287278 }
288279
289
-static long nvram_ioctl(struct file *file, unsigned int cmd,
290
- unsigned long arg)
280
+static long nvram_misc_ioctl(struct file *file, unsigned int cmd,
281
+ unsigned long arg)
291282 {
292
- int i;
283
+ long ret = -ENOTTY;
293284
294285 switch (cmd) {
286
+#ifdef CONFIG_PPC
287
+ case OBSOLETE_PMAC_NVRAM_GET_OFFSET:
288
+ pr_warn("nvram: Using obsolete PMAC_NVRAM_GET_OFFSET ioctl\n");
289
+ fallthrough;
290
+ case IOC_NVRAM_GET_OFFSET:
291
+ ret = -EINVAL;
292
+#ifdef CONFIG_PPC_PMAC
293
+ if (machine_is(powermac)) {
294
+ int part, offset;
295295
296
+ if (copy_from_user(&part, (void __user *)arg,
297
+ sizeof(part)) != 0)
298
+ return -EFAULT;
299
+ if (part < pmac_nvram_OF || part > pmac_nvram_NR)
300
+ return -EINVAL;
301
+ offset = pmac_get_partition(part);
302
+ if (offset < 0)
303
+ return -EINVAL;
304
+ if (copy_to_user((void __user *)arg,
305
+ &offset, sizeof(offset)) != 0)
306
+ return -EFAULT;
307
+ ret = 0;
308
+ }
309
+#endif
310
+ break;
311
+#ifdef CONFIG_PPC32
312
+ case IOC_NVRAM_SYNC:
313
+ if (ppc_md.nvram_sync != NULL) {
314
+ mutex_lock(&nvram_mutex);
315
+ ppc_md.nvram_sync();
316
+ mutex_unlock(&nvram_mutex);
317
+ }
318
+ ret = 0;
319
+ break;
320
+#endif
321
+#elif defined(CONFIG_X86) || defined(CONFIG_M68K)
296322 case NVRAM_INIT:
297323 /* initialize NVRAM contents and checksum */
298324 if (!capable(CAP_SYS_ADMIN))
299325 return -EACCES;
300326
301
- mutex_lock(&nvram_mutex);
302
- spin_lock_irq(&rtc_lock);
303
-
304
- for (i = 0; i < NVRAM_BYTES; ++i)
305
- __nvram_write_byte(0, i);
306
- __nvram_set_checksum();
307
-
308
- spin_unlock_irq(&rtc_lock);
309
- mutex_unlock(&nvram_mutex);
310
- return 0;
311
-
327
+ if (arch_nvram_ops.initialize != NULL) {
328
+ mutex_lock(&nvram_mutex);
329
+ ret = arch_nvram_ops.initialize();
330
+ mutex_unlock(&nvram_mutex);
331
+ }
332
+ break;
312333 case NVRAM_SETCKS:
313334 /* just set checksum, contents unchanged (maybe useful after
314335 * checksum garbaged somehow...) */
315336 if (!capable(CAP_SYS_ADMIN))
316337 return -EACCES;
317338
318
- mutex_lock(&nvram_mutex);
319
- spin_lock_irq(&rtc_lock);
320
- __nvram_set_checksum();
321
- spin_unlock_irq(&rtc_lock);
322
- mutex_unlock(&nvram_mutex);
323
- return 0;
324
-
325
- default:
326
- return -ENOTTY;
339
+ if (arch_nvram_ops.set_checksum != NULL) {
340
+ mutex_lock(&nvram_mutex);
341
+ ret = arch_nvram_ops.set_checksum();
342
+ mutex_unlock(&nvram_mutex);
343
+ }
344
+ break;
345
+#endif /* CONFIG_X86 || CONFIG_M68K */
327346 }
347
+ return ret;
328348 }
329349
330
-static int nvram_open(struct inode *inode, struct file *file)
350
+static int nvram_misc_open(struct inode *inode, struct file *file)
331351 {
332352 spin_lock(&nvram_state_lock);
333353
354
+ /* Prevent multiple readers/writers if desired. */
334355 if ((nvram_open_cnt && (file->f_flags & O_EXCL)) ||
335
- (nvram_open_mode & NVRAM_EXCL) ||
336
- ((file->f_mode & FMODE_WRITE) && (nvram_open_mode & NVRAM_WRITE))) {
356
+ (nvram_open_mode & NVRAM_EXCL)) {
337357 spin_unlock(&nvram_state_lock);
338358 return -EBUSY;
339359 }
360
+
361
+#if defined(CONFIG_X86) || defined(CONFIG_M68K)
362
+ /* Prevent multiple writers if the set_checksum ioctl is implemented. */
363
+ if ((arch_nvram_ops.set_checksum != NULL) &&
364
+ (file->f_mode & FMODE_WRITE) && (nvram_open_mode & NVRAM_WRITE)) {
365
+ spin_unlock(&nvram_state_lock);
366
+ return -EBUSY;
367
+ }
368
+#endif
340369
341370 if (file->f_flags & O_EXCL)
342371 nvram_open_mode |= NVRAM_EXCL;
....@@ -349,7 +378,7 @@
349378 return 0;
350379 }
351380
352
-static int nvram_release(struct inode *inode, struct file *file)
381
+static int nvram_misc_release(struct inode *inode, struct file *file)
353382 {
354383 spin_lock(&nvram_state_lock);
355384
....@@ -366,123 +395,7 @@
366395 return 0;
367396 }
368397
369
-#ifndef CONFIG_PROC_FS
370
-static int nvram_add_proc_fs(void)
371
-{
372
- return 0;
373
-}
374
-
375
-#else
376
-
377
-static int nvram_proc_read(struct seq_file *seq, void *offset)
378
-{
379
- unsigned char contents[NVRAM_BYTES];
380
- int i = 0;
381
-
382
- spin_lock_irq(&rtc_lock);
383
- for (i = 0; i < NVRAM_BYTES; ++i)
384
- contents[i] = __nvram_read_byte(i);
385
- spin_unlock_irq(&rtc_lock);
386
-
387
- mach_proc_infos(contents, seq, offset);
388
-
389
- return 0;
390
-}
391
-
392
-static int nvram_add_proc_fs(void)
393
-{
394
- if (!proc_create_single("driver/nvram", 0, NULL, nvram_proc_read))
395
- return -ENOMEM;
396
- return 0;
397
-}
398
-
399
-#endif /* CONFIG_PROC_FS */
400
-
401
-static const struct file_operations nvram_fops = {
402
- .owner = THIS_MODULE,
403
- .llseek = nvram_llseek,
404
- .read = nvram_read,
405
- .write = nvram_write,
406
- .unlocked_ioctl = nvram_ioctl,
407
- .open = nvram_open,
408
- .release = nvram_release,
409
-};
410
-
411
-static struct miscdevice nvram_dev = {
412
- NVRAM_MINOR,
413
- "nvram",
414
- &nvram_fops
415
-};
416
-
417
-static int __init nvram_init(void)
418
-{
419
- int ret;
420
-
421
- /* First test whether the driver should init at all */
422
- if (!CHECK_DRIVER_INIT())
423
- return -ENODEV;
424
-
425
- ret = misc_register(&nvram_dev);
426
- if (ret) {
427
- printk(KERN_ERR "nvram: can't misc_register on minor=%d\n",
428
- NVRAM_MINOR);
429
- goto out;
430
- }
431
- ret = nvram_add_proc_fs();
432
- if (ret) {
433
- printk(KERN_ERR "nvram: can't create /proc/driver/nvram\n");
434
- goto outmisc;
435
- }
436
- ret = 0;
437
- printk(KERN_INFO "Non-volatile memory driver v" NVRAM_VERSION "\n");
438
-out:
439
- return ret;
440
-outmisc:
441
- misc_deregister(&nvram_dev);
442
- goto out;
443
-}
444
-
445
-static void __exit nvram_cleanup_module(void)
446
-{
447
- remove_proc_entry("driver/nvram", NULL);
448
- misc_deregister(&nvram_dev);
449
-}
450
-
451
-module_init(nvram_init);
452
-module_exit(nvram_cleanup_module);
453
-
454
-/*
455
- * Machine specific functions
456
- */
457
-
458
-#if MACH == PC
459
-
460
-static int pc_check_checksum(void)
461
-{
462
- int i;
463
- unsigned short sum = 0;
464
- unsigned short expect;
465
-
466
- for (i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; ++i)
467
- sum += __nvram_read_byte(i);
468
- expect = __nvram_read_byte(PC_CKS_LOC)<<8 |
469
- __nvram_read_byte(PC_CKS_LOC+1);
470
- return (sum & 0xffff) == expect;
471
-}
472
-
473
-static void pc_set_checksum(void)
474
-{
475
- int i;
476
- unsigned short sum = 0;
477
-
478
- for (i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; ++i)
479
- sum += __nvram_read_byte(i);
480
- __nvram_write_byte(sum >> 8, PC_CKS_LOC);
481
- __nvram_write_byte(sum & 0xff, PC_CKS_LOC + 1);
482
-}
483
-
484
-#ifdef CONFIG_PROC_FS
485
-
398
+#if defined(CONFIG_X86) && defined(CONFIG_PROC_FS)
486399 static const char * const floppy_types[] = {
487400 "none", "5.25'' 360k", "5.25'' 1.2M", "3.5'' 720k", "3.5'' 1.44M",
488401 "3.5'' 2.88M", "3.5'' 2.88M"
....@@ -495,8 +408,8 @@
495408 "monochrome",
496409 };
497410
498
-static void pc_proc_infos(unsigned char *nvram, struct seq_file *seq,
499
- void *offset)
411
+static void pc_nvram_proc_read(unsigned char *nvram, struct seq_file *seq,
412
+ void *offset)
500413 {
501414 int checksum;
502415 int type;
....@@ -557,143 +470,76 @@
557470
558471 return;
559472 }
560
-#endif
561473
562
-#endif /* MACH == PC */
563
-
564
-#if MACH == ATARI
565
-
566
-static int atari_check_checksum(void)
474
+static int nvram_proc_read(struct seq_file *seq, void *offset)
567475 {
568
- int i;
569
- unsigned char sum = 0;
476
+ unsigned char contents[NVRAM_BYTES];
477
+ int i = 0;
570478
571
- for (i = ATARI_CKS_RANGE_START; i <= ATARI_CKS_RANGE_END; ++i)
572
- sum += __nvram_read_byte(i);
573
- return (__nvram_read_byte(ATARI_CKS_LOC) == (~sum & 0xff)) &&
574
- (__nvram_read_byte(ATARI_CKS_LOC + 1) == (sum & 0xff));
479
+ spin_lock_irq(&rtc_lock);
480
+ for (i = 0; i < NVRAM_BYTES; ++i)
481
+ contents[i] = __nvram_read_byte(i);
482
+ spin_unlock_irq(&rtc_lock);
483
+
484
+ pc_nvram_proc_read(contents, seq, offset);
485
+
486
+ return 0;
575487 }
488
+#endif /* CONFIG_X86 && CONFIG_PROC_FS */
576489
577
-static void atari_set_checksum(void)
490
+static const struct file_operations nvram_misc_fops = {
491
+ .owner = THIS_MODULE,
492
+ .llseek = nvram_misc_llseek,
493
+ .read = nvram_misc_read,
494
+ .write = nvram_misc_write,
495
+ .unlocked_ioctl = nvram_misc_ioctl,
496
+ .open = nvram_misc_open,
497
+ .release = nvram_misc_release,
498
+};
499
+
500
+static struct miscdevice nvram_misc = {
501
+ NVRAM_MINOR,
502
+ "nvram",
503
+ &nvram_misc_fops,
504
+};
505
+
506
+static int __init nvram_module_init(void)
578507 {
579
- int i;
580
- unsigned char sum = 0;
508
+ int ret;
581509
582
- for (i = ATARI_CKS_RANGE_START; i <= ATARI_CKS_RANGE_END; ++i)
583
- sum += __nvram_read_byte(i);
584
- __nvram_write_byte(~sum, ATARI_CKS_LOC);
585
- __nvram_write_byte(sum, ATARI_CKS_LOC + 1);
586
-}
510
+ nvram_size = nvram_get_size();
511
+ if (nvram_size < 0)
512
+ return nvram_size;
587513
588
-#ifdef CONFIG_PROC_FS
589
-
590
-static struct {
591
- unsigned char val;
592
- const char *name;
593
-} boot_prefs[] = {
594
- { 0x80, "TOS" },
595
- { 0x40, "ASV" },
596
- { 0x20, "NetBSD (?)" },
597
- { 0x10, "Linux" },
598
- { 0x00, "unspecified" }
599
-};
600
-
601
-static const char * const languages[] = {
602
- "English (US)",
603
- "German",
604
- "French",
605
- "English (UK)",
606
- "Spanish",
607
- "Italian",
608
- "6 (undefined)",
609
- "Swiss (French)",
610
- "Swiss (German)"
611
-};
612
-
613
-static const char * const dateformat[] = {
614
- "MM%cDD%cYY",
615
- "DD%cMM%cYY",
616
- "YY%cMM%cDD",
617
- "YY%cDD%cMM",
618
- "4 (undefined)",
619
- "5 (undefined)",
620
- "6 (undefined)",
621
- "7 (undefined)"
622
-};
623
-
624
-static const char * const colors[] = {
625
- "2", "4", "16", "256", "65536", "??", "??", "??"
626
-};
627
-
628
-static void atari_proc_infos(unsigned char *nvram, struct seq_file *seq,
629
- void *offset)
630
-{
631
- int checksum = nvram_check_checksum();
632
- int i;
633
- unsigned vmode;
634
-
635
- seq_printf(seq, "Checksum status : %svalid\n", checksum ? "" : "not ");
636
-
637
- seq_printf(seq, "Boot preference : ");
638
- for (i = ARRAY_SIZE(boot_prefs) - 1; i >= 0; --i) {
639
- if (nvram[1] == boot_prefs[i].val) {
640
- seq_printf(seq, "%s\n", boot_prefs[i].name);
641
- break;
642
- }
514
+ ret = misc_register(&nvram_misc);
515
+ if (ret) {
516
+ pr_err("nvram: can't misc_register on minor=%d\n", NVRAM_MINOR);
517
+ return ret;
643518 }
644
- if (i < 0)
645
- seq_printf(seq, "0x%02x (undefined)\n", nvram[1]);
646519
647
- seq_printf(seq, "SCSI arbitration : %s\n",
648
- (nvram[16] & 0x80) ? "on" : "off");
649
- seq_printf(seq, "SCSI host ID : ");
650
- if (nvram[16] & 0x80)
651
- seq_printf(seq, "%d\n", nvram[16] & 7);
652
- else
653
- seq_printf(seq, "n/a\n");
654
-
655
- /* the following entries are defined only for the Falcon */
656
- if ((atari_mch_cookie >> 16) != ATARI_MCH_FALCON)
657
- return;
658
-
659
- seq_printf(seq, "OS language : ");
660
- if (nvram[6] < ARRAY_SIZE(languages))
661
- seq_printf(seq, "%s\n", languages[nvram[6]]);
662
- else
663
- seq_printf(seq, "%u (undefined)\n", nvram[6]);
664
- seq_printf(seq, "Keyboard language: ");
665
- if (nvram[7] < ARRAY_SIZE(languages))
666
- seq_printf(seq, "%s\n", languages[nvram[7]]);
667
- else
668
- seq_printf(seq, "%u (undefined)\n", nvram[7]);
669
- seq_printf(seq, "Date format : ");
670
- seq_printf(seq, dateformat[nvram[8] & 7],
671
- nvram[9] ? nvram[9] : '/', nvram[9] ? nvram[9] : '/');
672
- seq_printf(seq, ", %dh clock\n", nvram[8] & 16 ? 24 : 12);
673
- seq_printf(seq, "Boot delay : ");
674
- if (nvram[10] == 0)
675
- seq_printf(seq, "default");
676
- else
677
- seq_printf(seq, "%ds%s\n", nvram[10],
678
- nvram[10] < 8 ? ", no memory test" : "");
679
-
680
- vmode = (nvram[14] << 8) | nvram[15];
681
- seq_printf(seq,
682
- "Video mode : %s colors, %d columns, %s %s monitor\n",
683
- colors[vmode & 7],
684
- vmode & 8 ? 80 : 40,
685
- vmode & 16 ? "VGA" : "TV", vmode & 32 ? "PAL" : "NTSC");
686
- seq_printf(seq, " %soverscan, compat. mode %s%s\n",
687
- vmode & 64 ? "" : "no ",
688
- vmode & 128 ? "on" : "off",
689
- vmode & 256 ?
690
- (vmode & 16 ? ", line doubling" : ", half screen") : "");
691
-
692
- return;
693
-}
520
+#if defined(CONFIG_X86) && defined(CONFIG_PROC_FS)
521
+ if (!proc_create_single("driver/nvram", 0, NULL, nvram_proc_read)) {
522
+ pr_err("nvram: can't create /proc/driver/nvram\n");
523
+ misc_deregister(&nvram_misc);
524
+ return -ENOMEM;
525
+ }
694526 #endif
695527
696
-#endif /* MACH == ATARI */
528
+ pr_info("Non-volatile memory driver v" NVRAM_VERSION "\n");
529
+ return 0;
530
+}
531
+
532
+static void __exit nvram_module_exit(void)
533
+{
534
+#if defined(CONFIG_X86) && defined(CONFIG_PROC_FS)
535
+ remove_proc_entry("driver/nvram", NULL);
536
+#endif
537
+ misc_deregister(&nvram_misc);
538
+}
539
+
540
+module_init(nvram_module_init);
541
+module_exit(nvram_module_exit);
697542
698543 MODULE_LICENSE("GPL");
699544 MODULE_ALIAS_MISCDEV(NVRAM_MINOR);
545
+MODULE_ALIAS("devname:nvram");