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/slab.h> 45 #include <linux/spinlock.h> 46 #include <linux/io.h> 47 #include <linux/uaccess.h> 48 #include <linux/mutex.h> 49 #include <linux/pagemap.h> 50 51 #ifdef CONFIG_PPC 52 #include <asm/nvram.h> 53 #endif 54 55 static DEFINE_MUTEX(nvram_mutex); 56 static DEFINE_SPINLOCK(nvram_state_lock); 57 static int nvram_open_cnt; /* #times opened */ 58 static int nvram_open_mode; /* special open modes */ 59 static ssize_t nvram_size; 60 #define NVRAM_WRITE 1 /* opened for writing (exclusive) */ 61 #define NVRAM_EXCL 2 /* opened with O_EXCL */ 62 63 #ifdef CONFIG_X86 64 /* 65 * These functions are provided to be called internally or by other parts of 66 * the kernel. It's up to the caller to ensure correct checksum before reading 67 * or after writing (needs to be done only once). 68 * 69 * It is worth noting that these functions all access bytes of general 70 * purpose memory in the NVRAM - that is to say, they all add the 71 * NVRAM_FIRST_BYTE offset. Pass them offsets into NVRAM as if you did not 72 * know about the RTC cruft. 73 */ 74 75 #define NVRAM_BYTES (128 - NVRAM_FIRST_BYTE) 76 77 /* Note that *all* calls to CMOS_READ and CMOS_WRITE must be done with 78 * rtc_lock held. Due to the index-port/data-port design of the RTC, we 79 * don't want two different things trying to get to it at once. (e.g. the 80 * periodic 11 min sync from kernel/time/ntp.c vs. this driver.) 81 */ 82 83 static unsigned char __nvram_read_byte(int i) 84 { 85 return CMOS_READ(NVRAM_FIRST_BYTE + i); 86 } 87 88 static unsigned char pc_nvram_read_byte(int i) 89 { 90 unsigned long flags; 91 unsigned char c; 92 93 spin_lock_irqsave(&rtc_lock, flags); 94 c = __nvram_read_byte(i); 95 spin_unlock_irqrestore(&rtc_lock, flags); 96 return c; 97 } 98 99 /* This races nicely with trying to read with checksum checking (nvram_read) */ 100 static void __nvram_write_byte(unsigned char c, int i) 101 { 102 CMOS_WRITE(c, NVRAM_FIRST_BYTE + i); 103 } 104 105 static void pc_nvram_write_byte(unsigned char c, int i) 106 { 107 unsigned long flags; 108 109 spin_lock_irqsave(&rtc_lock, flags); 110 __nvram_write_byte(c, i); 111 spin_unlock_irqrestore(&rtc_lock, flags); 112 } 113 114 /* On PCs, the checksum is built only over bytes 2..31 */ 115 #define PC_CKS_RANGE_START 2 116 #define PC_CKS_RANGE_END 31 117 #define PC_CKS_LOC 32 118 119 static int __nvram_check_checksum(void) 120 { 121 int i; 122 unsigned short sum = 0; 123 unsigned short expect; 124 125 for (i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; ++i) 126 sum += __nvram_read_byte(i); 127 expect = __nvram_read_byte(PC_CKS_LOC)<<8 | 128 __nvram_read_byte(PC_CKS_LOC+1); 129 return (sum & 0xffff) == expect; 130 } 131 132 static void __nvram_set_checksum(void) 133 { 134 int i; 135 unsigned short sum = 0; 136 137 for (i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; ++i) 138 sum += __nvram_read_byte(i); 139 __nvram_write_byte(sum >> 8, PC_CKS_LOC); 140 __nvram_write_byte(sum & 0xff, PC_CKS_LOC + 1); 141 } 142 143 static long pc_nvram_set_checksum(void) 144 { 145 spin_lock_irq(&rtc_lock); 146 __nvram_set_checksum(); 147 spin_unlock_irq(&rtc_lock); 148 return 0; 149 } 150 151 static long pc_nvram_initialize(void) 152 { 153 ssize_t i; 154 155 spin_lock_irq(&rtc_lock); 156 for (i = 0; i < NVRAM_BYTES; ++i) 157 __nvram_write_byte(0, i); 158 __nvram_set_checksum(); 159 spin_unlock_irq(&rtc_lock); 160 return 0; 161 } 162 163 static ssize_t pc_nvram_get_size(void) 164 { 165 return NVRAM_BYTES; 166 } 167 168 static ssize_t pc_nvram_read(char *buf, size_t count, loff_t *ppos) 169 { 170 char *p = buf; 171 loff_t i; 172 173 spin_lock_irq(&rtc_lock); 174 if (!__nvram_check_checksum()) { 175 spin_unlock_irq(&rtc_lock); 176 return -EIO; 177 } 178 for (i = *ppos; count > 0 && i < NVRAM_BYTES; --count, ++i, ++p) 179 *p = __nvram_read_byte(i); 180 spin_unlock_irq(&rtc_lock); 181 182 *ppos = i; 183 return p - buf; 184 } 185 186 static ssize_t pc_nvram_write(char *buf, size_t count, loff_t *ppos) 187 { 188 char *p = buf; 189 loff_t i; 190 191 spin_lock_irq(&rtc_lock); 192 if (!__nvram_check_checksum()) { 193 spin_unlock_irq(&rtc_lock); 194 return -EIO; 195 } 196 for (i = *ppos; count > 0 && i < NVRAM_BYTES; --count, ++i, ++p) 197 __nvram_write_byte(*p, i); 198 __nvram_set_checksum(); 199 spin_unlock_irq(&rtc_lock); 200 201 *ppos = i; 202 return p - buf; 203 } 204 205 const struct nvram_ops arch_nvram_ops = { 206 .read = pc_nvram_read, 207 .write = pc_nvram_write, 208 .read_byte = pc_nvram_read_byte, 209 .write_byte = pc_nvram_write_byte, 210 .get_size = pc_nvram_get_size, 211 .set_checksum = pc_nvram_set_checksum, 212 .initialize = pc_nvram_initialize, 213 }; 214 EXPORT_SYMBOL(arch_nvram_ops); 215 #endif /* CONFIG_X86 */ 216 217 /* 218 * The are the file operation function for user access to /dev/nvram 219 */ 220 221 static loff_t nvram_misc_llseek(struct file *file, loff_t offset, int origin) 222 { 223 return generic_file_llseek_size(file, offset, origin, MAX_LFS_FILESIZE, 224 nvram_size); 225 } 226 227 static ssize_t nvram_misc_read(struct file *file, char __user *buf, 228 size_t count, loff_t *ppos) 229 { 230 char *tmp; 231 ssize_t ret; 232 233 234 if (!access_ok(buf, count)) 235 return -EFAULT; 236 if (*ppos >= nvram_size) 237 return 0; 238 239 count = min_t(size_t, count, nvram_size - *ppos); 240 count = min_t(size_t, count, PAGE_SIZE); 241 242 tmp = kmalloc(count, GFP_KERNEL); 243 if (!tmp) 244 return -ENOMEM; 245 246 ret = nvram_read(tmp, count, ppos); 247 if (ret <= 0) 248 goto out; 249 250 if (copy_to_user(buf, tmp, ret)) { 251 *ppos -= ret; 252 ret = -EFAULT; 253 } 254 255 out: 256 kfree(tmp); 257 return ret; 258 } 259 260 static ssize_t nvram_misc_write(struct file *file, const char __user *buf, 261 size_t count, loff_t *ppos) 262 { 263 char *tmp; 264 ssize_t ret; 265 266 if (!access_ok(buf, count)) 267 return -EFAULT; 268 if (*ppos >= nvram_size) 269 return 0; 270 271 count = min_t(size_t, count, nvram_size - *ppos); 272 count = min_t(size_t, count, PAGE_SIZE); 273 274 tmp = memdup_user(buf, count); 275 if (IS_ERR(tmp)) 276 return PTR_ERR(tmp); 277 278 ret = nvram_write(tmp, count, ppos); 279 kfree(tmp); 280 return ret; 281 } 282 283 static long nvram_misc_ioctl(struct file *file, unsigned int cmd, 284 unsigned long arg) 285 { 286 long ret = -ENOTTY; 287 288 switch (cmd) { 289 #ifdef CONFIG_PPC 290 case OBSOLETE_PMAC_NVRAM_GET_OFFSET: 291 pr_warn("nvram: Using obsolete PMAC_NVRAM_GET_OFFSET ioctl\n"); 292 /* fall through */ 293 case IOC_NVRAM_GET_OFFSET: 294 ret = -EINVAL; 295 #ifdef CONFIG_PPC_PMAC 296 if (machine_is(powermac)) { 297 int part, offset; 298 299 if (copy_from_user(&part, (void __user *)arg, 300 sizeof(part)) != 0) 301 return -EFAULT; 302 if (part < pmac_nvram_OF || part > pmac_nvram_NR) 303 return -EINVAL; 304 offset = pmac_get_partition(part); 305 if (offset < 0) 306 return -EINVAL; 307 if (copy_to_user((void __user *)arg, 308 &offset, sizeof(offset)) != 0) 309 return -EFAULT; 310 ret = 0; 311 } 312 #endif 313 break; 314 #ifdef CONFIG_PPC32 315 case IOC_NVRAM_SYNC: 316 if (ppc_md.nvram_sync != NULL) { 317 mutex_lock(&nvram_mutex); 318 ppc_md.nvram_sync(); 319 mutex_unlock(&nvram_mutex); 320 } 321 ret = 0; 322 break; 323 #endif 324 #elif defined(CONFIG_X86) || defined(CONFIG_M68K) 325 case NVRAM_INIT: 326 /* initialize NVRAM contents and checksum */ 327 if (!capable(CAP_SYS_ADMIN)) 328 return -EACCES; 329 330 if (arch_nvram_ops.initialize != NULL) { 331 mutex_lock(&nvram_mutex); 332 ret = arch_nvram_ops.initialize(); 333 mutex_unlock(&nvram_mutex); 334 } 335 break; 336 case NVRAM_SETCKS: 337 /* just set checksum, contents unchanged (maybe useful after 338 * checksum garbaged somehow...) */ 339 if (!capable(CAP_SYS_ADMIN)) 340 return -EACCES; 341 342 if (arch_nvram_ops.set_checksum != NULL) { 343 mutex_lock(&nvram_mutex); 344 ret = arch_nvram_ops.set_checksum(); 345 mutex_unlock(&nvram_mutex); 346 } 347 break; 348 #endif /* CONFIG_X86 || CONFIG_M68K */ 349 } 350 return ret; 351 } 352 353 static int nvram_misc_open(struct inode *inode, struct file *file) 354 { 355 spin_lock(&nvram_state_lock); 356 357 /* Prevent multiple readers/writers if desired. */ 358 if ((nvram_open_cnt && (file->f_flags & O_EXCL)) || 359 (nvram_open_mode & NVRAM_EXCL)) { 360 spin_unlock(&nvram_state_lock); 361 return -EBUSY; 362 } 363 364 #if defined(CONFIG_X86) || defined(CONFIG_M68K) 365 /* Prevent multiple writers if the set_checksum ioctl is implemented. */ 366 if ((arch_nvram_ops.set_checksum != NULL) && 367 (file->f_mode & FMODE_WRITE) && (nvram_open_mode & NVRAM_WRITE)) { 368 spin_unlock(&nvram_state_lock); 369 return -EBUSY; 370 } 371 #endif 372 373 if (file->f_flags & O_EXCL) 374 nvram_open_mode |= NVRAM_EXCL; 375 if (file->f_mode & FMODE_WRITE) 376 nvram_open_mode |= NVRAM_WRITE; 377 nvram_open_cnt++; 378 379 spin_unlock(&nvram_state_lock); 380 381 return 0; 382 } 383 384 static int nvram_misc_release(struct inode *inode, struct file *file) 385 { 386 spin_lock(&nvram_state_lock); 387 388 nvram_open_cnt--; 389 390 /* if only one instance is open, clear the EXCL bit */ 391 if (nvram_open_mode & NVRAM_EXCL) 392 nvram_open_mode &= ~NVRAM_EXCL; 393 if (file->f_mode & FMODE_WRITE) 394 nvram_open_mode &= ~NVRAM_WRITE; 395 396 spin_unlock(&nvram_state_lock); 397 398 return 0; 399 } 400 401 #if defined(CONFIG_X86) && defined(CONFIG_PROC_FS) 402 static const char * const floppy_types[] = { 403 "none", "5.25'' 360k", "5.25'' 1.2M", "3.5'' 720k", "3.5'' 1.44M", 404 "3.5'' 2.88M", "3.5'' 2.88M" 405 }; 406 407 static const char * const gfx_types[] = { 408 "EGA, VGA, ... (with BIOS)", 409 "CGA (40 cols)", 410 "CGA (80 cols)", 411 "monochrome", 412 }; 413 414 static void pc_nvram_proc_read(unsigned char *nvram, struct seq_file *seq, 415 void *offset) 416 { 417 int checksum; 418 int type; 419 420 spin_lock_irq(&rtc_lock); 421 checksum = __nvram_check_checksum(); 422 spin_unlock_irq(&rtc_lock); 423 424 seq_printf(seq, "Checksum status: %svalid\n", checksum ? "" : "not "); 425 426 seq_printf(seq, "# floppies : %d\n", 427 (nvram[6] & 1) ? (nvram[6] >> 6) + 1 : 0); 428 seq_printf(seq, "Floppy 0 type : "); 429 type = nvram[2] >> 4; 430 if (type < ARRAY_SIZE(floppy_types)) 431 seq_printf(seq, "%s\n", floppy_types[type]); 432 else 433 seq_printf(seq, "%d (unknown)\n", type); 434 seq_printf(seq, "Floppy 1 type : "); 435 type = nvram[2] & 0x0f; 436 if (type < ARRAY_SIZE(floppy_types)) 437 seq_printf(seq, "%s\n", floppy_types[type]); 438 else 439 seq_printf(seq, "%d (unknown)\n", type); 440 441 seq_printf(seq, "HD 0 type : "); 442 type = nvram[4] >> 4; 443 if (type) 444 seq_printf(seq, "%02x\n", type == 0x0f ? nvram[11] : type); 445 else 446 seq_printf(seq, "none\n"); 447 448 seq_printf(seq, "HD 1 type : "); 449 type = nvram[4] & 0x0f; 450 if (type) 451 seq_printf(seq, "%02x\n", type == 0x0f ? nvram[12] : type); 452 else 453 seq_printf(seq, "none\n"); 454 455 seq_printf(seq, "HD type 48 data: %d/%d/%d C/H/S, precomp %d, lz %d\n", 456 nvram[18] | (nvram[19] << 8), 457 nvram[20], nvram[25], 458 nvram[21] | (nvram[22] << 8), nvram[23] | (nvram[24] << 8)); 459 seq_printf(seq, "HD type 49 data: %d/%d/%d C/H/S, precomp %d, lz %d\n", 460 nvram[39] | (nvram[40] << 8), 461 nvram[41], nvram[46], 462 nvram[42] | (nvram[43] << 8), nvram[44] | (nvram[45] << 8)); 463 464 seq_printf(seq, "DOS base memory: %d kB\n", nvram[7] | (nvram[8] << 8)); 465 seq_printf(seq, "Extended memory: %d kB (configured), %d kB (tested)\n", 466 nvram[9] | (nvram[10] << 8), nvram[34] | (nvram[35] << 8)); 467 468 seq_printf(seq, "Gfx adapter : %s\n", 469 gfx_types[(nvram[6] >> 4) & 3]); 470 471 seq_printf(seq, "FPU : %sinstalled\n", 472 (nvram[6] & 2) ? "" : "not "); 473 474 return; 475 } 476 477 static int nvram_proc_read(struct seq_file *seq, void *offset) 478 { 479 unsigned char contents[NVRAM_BYTES]; 480 int i = 0; 481 482 spin_lock_irq(&rtc_lock); 483 for (i = 0; i < NVRAM_BYTES; ++i) 484 contents[i] = __nvram_read_byte(i); 485 spin_unlock_irq(&rtc_lock); 486 487 pc_nvram_proc_read(contents, seq, offset); 488 489 return 0; 490 } 491 #endif /* CONFIG_X86 && CONFIG_PROC_FS */ 492 493 static const struct file_operations nvram_misc_fops = { 494 .owner = THIS_MODULE, 495 .llseek = nvram_misc_llseek, 496 .read = nvram_misc_read, 497 .write = nvram_misc_write, 498 .unlocked_ioctl = nvram_misc_ioctl, 499 .open = nvram_misc_open, 500 .release = nvram_misc_release, 501 }; 502 503 static struct miscdevice nvram_misc = { 504 NVRAM_MINOR, 505 "nvram", 506 &nvram_misc_fops, 507 }; 508 509 static int __init nvram_module_init(void) 510 { 511 int ret; 512 513 nvram_size = nvram_get_size(); 514 if (nvram_size < 0) 515 return nvram_size; 516 517 ret = misc_register(&nvram_misc); 518 if (ret) { 519 pr_err("nvram: can't misc_register on minor=%d\n", NVRAM_MINOR); 520 return ret; 521 } 522 523 #if defined(CONFIG_X86) && defined(CONFIG_PROC_FS) 524 if (!proc_create_single("driver/nvram", 0, NULL, nvram_proc_read)) { 525 pr_err("nvram: can't create /proc/driver/nvram\n"); 526 misc_deregister(&nvram_misc); 527 return -ENOMEM; 528 } 529 #endif 530 531 pr_info("Non-volatile memory driver v" NVRAM_VERSION "\n"); 532 return 0; 533 } 534 535 static void __exit nvram_module_exit(void) 536 { 537 #if defined(CONFIG_X86) && defined(CONFIG_PROC_FS) 538 remove_proc_entry("driver/nvram", NULL); 539 #endif 540 misc_deregister(&nvram_misc); 541 } 542 543 module_init(nvram_module_init); 544 module_exit(nvram_module_exit); 545 546 MODULE_LICENSE("GPL"); 547 MODULE_ALIAS_MISCDEV(NVRAM_MINOR); 548 MODULE_ALIAS("devname:nvram"); 549