1 /* 2 * c 2001 PPC 64 Team, IBM Corp 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 * 9 * /dev/nvram driver for PPC64 10 * 11 * This perhaps should live in drivers/char 12 * 13 * TODO: Split the /dev/nvram part (that one can use 14 * drivers/char/generic_nvram.c) from the arch & partition 15 * parsing code. 16 */ 17 18 #include <linux/module.h> 19 20 #include <linux/types.h> 21 #include <linux/errno.h> 22 #include <linux/fs.h> 23 #include <linux/miscdevice.h> 24 #include <linux/fcntl.h> 25 #include <linux/nvram.h> 26 #include <linux/init.h> 27 #include <linux/slab.h> 28 #include <linux/spinlock.h> 29 #include <asm/uaccess.h> 30 #include <asm/nvram.h> 31 #include <asm/rtas.h> 32 #include <asm/prom.h> 33 #include <asm/machdep.h> 34 35 #undef DEBUG_NVRAM 36 37 static struct nvram_partition * nvram_part; 38 static long nvram_error_log_index = -1; 39 static long nvram_error_log_size = 0; 40 41 struct err_log_info { 42 int error_type; 43 unsigned int seq_num; 44 }; 45 46 static loff_t dev_nvram_llseek(struct file *file, loff_t offset, int origin) 47 { 48 int size; 49 50 if (ppc_md.nvram_size == NULL) 51 return -ENODEV; 52 size = ppc_md.nvram_size(); 53 54 switch (origin) { 55 case 1: 56 offset += file->f_pos; 57 break; 58 case 2: 59 offset += size; 60 break; 61 } 62 if (offset < 0) 63 return -EINVAL; 64 file->f_pos = offset; 65 return file->f_pos; 66 } 67 68 69 static ssize_t dev_nvram_read(struct file *file, char __user *buf, 70 size_t count, loff_t *ppos) 71 { 72 ssize_t ret; 73 char *tmp = NULL; 74 ssize_t size; 75 76 ret = -ENODEV; 77 if (!ppc_md.nvram_size) 78 goto out; 79 80 ret = 0; 81 size = ppc_md.nvram_size(); 82 if (*ppos >= size || size < 0) 83 goto out; 84 85 count = min_t(size_t, count, size - *ppos); 86 count = min(count, PAGE_SIZE); 87 88 ret = -ENOMEM; 89 tmp = kmalloc(count, GFP_KERNEL); 90 if (!tmp) 91 goto out; 92 93 ret = ppc_md.nvram_read(tmp, count, ppos); 94 if (ret <= 0) 95 goto out; 96 97 if (copy_to_user(buf, tmp, ret)) 98 ret = -EFAULT; 99 100 out: 101 kfree(tmp); 102 return ret; 103 104 } 105 106 static ssize_t dev_nvram_write(struct file *file, const char __user *buf, 107 size_t count, loff_t *ppos) 108 { 109 ssize_t ret; 110 char *tmp = NULL; 111 ssize_t size; 112 113 ret = -ENODEV; 114 if (!ppc_md.nvram_size) 115 goto out; 116 117 ret = 0; 118 size = ppc_md.nvram_size(); 119 if (*ppos >= size || size < 0) 120 goto out; 121 122 count = min_t(size_t, count, size - *ppos); 123 count = min(count, PAGE_SIZE); 124 125 ret = -ENOMEM; 126 tmp = kmalloc(count, GFP_KERNEL); 127 if (!tmp) 128 goto out; 129 130 ret = -EFAULT; 131 if (copy_from_user(tmp, buf, count)) 132 goto out; 133 134 ret = ppc_md.nvram_write(tmp, count, ppos); 135 136 out: 137 kfree(tmp); 138 return ret; 139 140 } 141 142 static int dev_nvram_ioctl(struct inode *inode, struct file *file, 143 unsigned int cmd, unsigned long arg) 144 { 145 switch(cmd) { 146 #ifdef CONFIG_PPC_PMAC 147 case OBSOLETE_PMAC_NVRAM_GET_OFFSET: 148 printk(KERN_WARNING "nvram: Using obsolete PMAC_NVRAM_GET_OFFSET ioctl\n"); 149 case IOC_NVRAM_GET_OFFSET: { 150 int part, offset; 151 152 if (!machine_is(powermac)) 153 return -EINVAL; 154 if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0) 155 return -EFAULT; 156 if (part < pmac_nvram_OF || part > pmac_nvram_NR) 157 return -EINVAL; 158 offset = pmac_get_partition(part); 159 if (offset < 0) 160 return offset; 161 if (copy_to_user((void __user*)arg, &offset, sizeof(offset)) != 0) 162 return -EFAULT; 163 return 0; 164 } 165 #endif /* CONFIG_PPC_PMAC */ 166 default: 167 return -EINVAL; 168 } 169 } 170 171 const struct file_operations nvram_fops = { 172 .owner = THIS_MODULE, 173 .llseek = dev_nvram_llseek, 174 .read = dev_nvram_read, 175 .write = dev_nvram_write, 176 .ioctl = dev_nvram_ioctl, 177 }; 178 179 static struct miscdevice nvram_dev = { 180 NVRAM_MINOR, 181 "nvram", 182 &nvram_fops 183 }; 184 185 186 #ifdef DEBUG_NVRAM 187 static void nvram_print_partitions(char * label) 188 { 189 struct list_head * p; 190 struct nvram_partition * tmp_part; 191 192 printk(KERN_WARNING "--------%s---------\n", label); 193 printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n"); 194 list_for_each(p, &nvram_part->partition) { 195 tmp_part = list_entry(p, struct nvram_partition, partition); 196 printk(KERN_WARNING "%4d \t%02x\t%02x\t%d\t%s\n", 197 tmp_part->index, tmp_part->header.signature, 198 tmp_part->header.checksum, tmp_part->header.length, 199 tmp_part->header.name); 200 } 201 } 202 #endif 203 204 205 static int nvram_write_header(struct nvram_partition * part) 206 { 207 loff_t tmp_index; 208 int rc; 209 210 tmp_index = part->index; 211 rc = ppc_md.nvram_write((char *)&part->header, NVRAM_HEADER_LEN, &tmp_index); 212 213 return rc; 214 } 215 216 217 static unsigned char nvram_checksum(struct nvram_header *p) 218 { 219 unsigned int c_sum, c_sum2; 220 unsigned short *sp = (unsigned short *)p->name; /* assume 6 shorts */ 221 c_sum = p->signature + p->length + sp[0] + sp[1] + sp[2] + sp[3] + sp[4] + sp[5]; 222 223 /* The sum may have spilled into the 3rd byte. Fold it back. */ 224 c_sum = ((c_sum & 0xffff) + (c_sum >> 16)) & 0xffff; 225 /* The sum cannot exceed 2 bytes. Fold it into a checksum */ 226 c_sum2 = (c_sum >> 8) + (c_sum << 8); 227 c_sum = ((c_sum + c_sum2) >> 8) & 0xff; 228 return c_sum; 229 } 230 231 232 /* 233 * Find an nvram partition, sig can be 0 for any 234 * partition or name can be NULL for any name, else 235 * tries to match both 236 */ 237 struct nvram_partition *nvram_find_partition(int sig, const char *name) 238 { 239 struct nvram_partition * part; 240 struct list_head * p; 241 242 list_for_each(p, &nvram_part->partition) { 243 part = list_entry(p, struct nvram_partition, partition); 244 245 if (sig && part->header.signature != sig) 246 continue; 247 if (name && 0 != strncmp(name, part->header.name, 12)) 248 continue; 249 return part; 250 } 251 return NULL; 252 } 253 EXPORT_SYMBOL(nvram_find_partition); 254 255 256 static int nvram_remove_os_partition(void) 257 { 258 struct list_head *i; 259 struct list_head *j; 260 struct nvram_partition * part; 261 struct nvram_partition * cur_part; 262 int rc; 263 264 list_for_each(i, &nvram_part->partition) { 265 part = list_entry(i, struct nvram_partition, partition); 266 if (part->header.signature != NVRAM_SIG_OS) 267 continue; 268 269 /* Make os partition a free partition */ 270 part->header.signature = NVRAM_SIG_FREE; 271 sprintf(part->header.name, "wwwwwwwwwwww"); 272 part->header.checksum = nvram_checksum(&part->header); 273 274 /* Merge contiguous free partitions backwards */ 275 list_for_each_prev(j, &part->partition) { 276 cur_part = list_entry(j, struct nvram_partition, partition); 277 if (cur_part == nvram_part || cur_part->header.signature != NVRAM_SIG_FREE) { 278 break; 279 } 280 281 part->header.length += cur_part->header.length; 282 part->header.checksum = nvram_checksum(&part->header); 283 part->index = cur_part->index; 284 285 list_del(&cur_part->partition); 286 kfree(cur_part); 287 j = &part->partition; /* fixup our loop */ 288 } 289 290 /* Merge contiguous free partitions forwards */ 291 list_for_each(j, &part->partition) { 292 cur_part = list_entry(j, struct nvram_partition, partition); 293 if (cur_part == nvram_part || cur_part->header.signature != NVRAM_SIG_FREE) { 294 break; 295 } 296 297 part->header.length += cur_part->header.length; 298 part->header.checksum = nvram_checksum(&part->header); 299 300 list_del(&cur_part->partition); 301 kfree(cur_part); 302 j = &part->partition; /* fixup our loop */ 303 } 304 305 rc = nvram_write_header(part); 306 if (rc <= 0) { 307 printk(KERN_ERR "nvram_remove_os_partition: nvram_write failed (%d)\n", rc); 308 return rc; 309 } 310 311 } 312 313 return 0; 314 } 315 316 /* nvram_create_os_partition 317 * 318 * Create a OS linux partition to buffer error logs. 319 * Will create a partition starting at the first free 320 * space found if space has enough room. 321 */ 322 static int nvram_create_os_partition(void) 323 { 324 struct nvram_partition *part; 325 struct nvram_partition *new_part; 326 struct nvram_partition *free_part = NULL; 327 int seq_init[2] = { 0, 0 }; 328 loff_t tmp_index; 329 long size = 0; 330 int rc; 331 332 /* Find a free partition that will give us the maximum needed size 333 If can't find one that will give us the minimum size needed */ 334 list_for_each_entry(part, &nvram_part->partition, partition) { 335 if (part->header.signature != NVRAM_SIG_FREE) 336 continue; 337 338 if (part->header.length >= NVRAM_MAX_REQ) { 339 size = NVRAM_MAX_REQ; 340 free_part = part; 341 break; 342 } 343 if (!size && part->header.length >= NVRAM_MIN_REQ) { 344 size = NVRAM_MIN_REQ; 345 free_part = part; 346 } 347 } 348 if (!size) 349 return -ENOSPC; 350 351 /* Create our OS partition */ 352 new_part = kmalloc(sizeof(*new_part), GFP_KERNEL); 353 if (!new_part) { 354 printk(KERN_ERR "nvram_create_os_partition: kmalloc failed\n"); 355 return -ENOMEM; 356 } 357 358 new_part->index = free_part->index; 359 new_part->header.signature = NVRAM_SIG_OS; 360 new_part->header.length = size; 361 strcpy(new_part->header.name, "ppc64,linux"); 362 new_part->header.checksum = nvram_checksum(&new_part->header); 363 364 rc = nvram_write_header(new_part); 365 if (rc <= 0) { 366 printk(KERN_ERR "nvram_create_os_partition: nvram_write_header \ 367 failed (%d)\n", rc); 368 return rc; 369 } 370 371 /* make sure and initialize to zero the sequence number and the error 372 type logged */ 373 tmp_index = new_part->index + NVRAM_HEADER_LEN; 374 rc = ppc_md.nvram_write((char *)&seq_init, sizeof(seq_init), &tmp_index); 375 if (rc <= 0) { 376 printk(KERN_ERR "nvram_create_os_partition: nvram_write " 377 "failed (%d)\n", rc); 378 return rc; 379 } 380 381 nvram_error_log_index = new_part->index + NVRAM_HEADER_LEN; 382 nvram_error_log_size = ((part->header.length - 1) * 383 NVRAM_BLOCK_LEN) - sizeof(struct err_log_info); 384 385 list_add_tail(&new_part->partition, &free_part->partition); 386 387 if (free_part->header.length <= size) { 388 list_del(&free_part->partition); 389 kfree(free_part); 390 return 0; 391 } 392 393 /* Adjust the partition we stole the space from */ 394 free_part->index += size * NVRAM_BLOCK_LEN; 395 free_part->header.length -= size; 396 free_part->header.checksum = nvram_checksum(&free_part->header); 397 398 rc = nvram_write_header(free_part); 399 if (rc <= 0) { 400 printk(KERN_ERR "nvram_create_os_partition: nvram_write_header " 401 "failed (%d)\n", rc); 402 return rc; 403 } 404 405 return 0; 406 } 407 408 409 /* nvram_setup_partition 410 * 411 * This will setup the partition we need for buffering the 412 * error logs and cleanup partitions if needed. 413 * 414 * The general strategy is the following: 415 * 1.) If there is ppc64,linux partition large enough then use it. 416 * 2.) If there is not a ppc64,linux partition large enough, search 417 * for a free partition that is large enough. 418 * 3.) If there is not a free partition large enough remove 419 * _all_ OS partitions and consolidate the space. 420 * 4.) Will first try getting a chunk that will satisfy the maximum 421 * error log size (NVRAM_MAX_REQ). 422 * 5.) If the max chunk cannot be allocated then try finding a chunk 423 * that will satisfy the minum needed (NVRAM_MIN_REQ). 424 */ 425 static int nvram_setup_partition(void) 426 { 427 struct list_head * p; 428 struct nvram_partition * part; 429 int rc; 430 431 /* For now, we don't do any of this on pmac, until I 432 * have figured out if it's worth killing some unused stuffs 433 * in our nvram, as Apple defined partitions use pretty much 434 * all of the space 435 */ 436 if (machine_is(powermac)) 437 return -ENOSPC; 438 439 /* see if we have an OS partition that meets our needs. 440 will try getting the max we need. If not we'll delete 441 partitions and try again. */ 442 list_for_each(p, &nvram_part->partition) { 443 part = list_entry(p, struct nvram_partition, partition); 444 if (part->header.signature != NVRAM_SIG_OS) 445 continue; 446 447 if (strcmp(part->header.name, "ppc64,linux")) 448 continue; 449 450 if (part->header.length >= NVRAM_MIN_REQ) { 451 /* found our partition */ 452 nvram_error_log_index = part->index + NVRAM_HEADER_LEN; 453 nvram_error_log_size = ((part->header.length - 1) * 454 NVRAM_BLOCK_LEN) - sizeof(struct err_log_info); 455 return 0; 456 } 457 } 458 459 /* try creating a partition with the free space we have */ 460 rc = nvram_create_os_partition(); 461 if (!rc) { 462 return 0; 463 } 464 465 /* need to free up some space */ 466 rc = nvram_remove_os_partition(); 467 if (rc) { 468 return rc; 469 } 470 471 /* create a partition in this new space */ 472 rc = nvram_create_os_partition(); 473 if (rc) { 474 printk(KERN_ERR "nvram_create_os_partition: Could not find a " 475 "NVRAM partition large enough\n"); 476 return rc; 477 } 478 479 return 0; 480 } 481 482 483 static int nvram_scan_partitions(void) 484 { 485 loff_t cur_index = 0; 486 struct nvram_header phead; 487 struct nvram_partition * tmp_part; 488 unsigned char c_sum; 489 char * header; 490 int total_size; 491 int err; 492 493 if (ppc_md.nvram_size == NULL) 494 return -ENODEV; 495 total_size = ppc_md.nvram_size(); 496 497 header = kmalloc(NVRAM_HEADER_LEN, GFP_KERNEL); 498 if (!header) { 499 printk(KERN_ERR "nvram_scan_partitions: Failed kmalloc\n"); 500 return -ENOMEM; 501 } 502 503 while (cur_index < total_size) { 504 505 err = ppc_md.nvram_read(header, NVRAM_HEADER_LEN, &cur_index); 506 if (err != NVRAM_HEADER_LEN) { 507 printk(KERN_ERR "nvram_scan_partitions: Error parsing " 508 "nvram partitions\n"); 509 goto out; 510 } 511 512 cur_index -= NVRAM_HEADER_LEN; /* nvram_read will advance us */ 513 514 memcpy(&phead, header, NVRAM_HEADER_LEN); 515 516 err = 0; 517 c_sum = nvram_checksum(&phead); 518 if (c_sum != phead.checksum) { 519 printk(KERN_WARNING "WARNING: nvram partition checksum" 520 " was %02x, should be %02x!\n", 521 phead.checksum, c_sum); 522 printk(KERN_WARNING "Terminating nvram partition scan\n"); 523 goto out; 524 } 525 if (!phead.length) { 526 printk(KERN_WARNING "WARNING: nvram corruption " 527 "detected: 0-length partition\n"); 528 goto out; 529 } 530 tmp_part = (struct nvram_partition *) 531 kmalloc(sizeof(struct nvram_partition), GFP_KERNEL); 532 err = -ENOMEM; 533 if (!tmp_part) { 534 printk(KERN_ERR "nvram_scan_partitions: kmalloc failed\n"); 535 goto out; 536 } 537 538 memcpy(&tmp_part->header, &phead, NVRAM_HEADER_LEN); 539 tmp_part->index = cur_index; 540 list_add_tail(&tmp_part->partition, &nvram_part->partition); 541 542 cur_index += phead.length * NVRAM_BLOCK_LEN; 543 } 544 err = 0; 545 546 out: 547 kfree(header); 548 return err; 549 } 550 551 static int __init nvram_init(void) 552 { 553 int error; 554 int rc; 555 556 if (ppc_md.nvram_size == NULL || ppc_md.nvram_size() <= 0) 557 return -ENODEV; 558 559 rc = misc_register(&nvram_dev); 560 if (rc != 0) { 561 printk(KERN_ERR "nvram_init: failed to register device\n"); 562 return rc; 563 } 564 565 /* initialize our anchor for the nvram partition list */ 566 nvram_part = kmalloc(sizeof(struct nvram_partition), GFP_KERNEL); 567 if (!nvram_part) { 568 printk(KERN_ERR "nvram_init: Failed kmalloc\n"); 569 return -ENOMEM; 570 } 571 INIT_LIST_HEAD(&nvram_part->partition); 572 573 /* Get all the NVRAM partitions */ 574 error = nvram_scan_partitions(); 575 if (error) { 576 printk(KERN_ERR "nvram_init: Failed nvram_scan_partitions\n"); 577 return error; 578 } 579 580 if(nvram_setup_partition()) 581 printk(KERN_WARNING "nvram_init: Could not find nvram partition" 582 " for nvram buffered error logging.\n"); 583 584 #ifdef DEBUG_NVRAM 585 nvram_print_partitions("NVRAM Partitions"); 586 #endif 587 588 return rc; 589 } 590 591 void __exit nvram_cleanup(void) 592 { 593 misc_deregister( &nvram_dev ); 594 } 595 596 597 #ifdef CONFIG_PPC_PSERIES 598 599 /* nvram_write_error_log 600 * 601 * We need to buffer the error logs into nvram to ensure that we have 602 * the failure information to decode. If we have a severe error there 603 * is no way to guarantee that the OS or the machine is in a state to 604 * get back to user land and write the error to disk. For example if 605 * the SCSI device driver causes a Machine Check by writing to a bad 606 * IO address, there is no way of guaranteeing that the device driver 607 * is in any state that is would also be able to write the error data 608 * captured to disk, thus we buffer it in NVRAM for analysis on the 609 * next boot. 610 * 611 * In NVRAM the partition containing the error log buffer will looks like: 612 * Header (in bytes): 613 * +-----------+----------+--------+------------+------------------+ 614 * | signature | checksum | length | name | data | 615 * |0 |1 |2 3|4 15|16 length-1| 616 * +-----------+----------+--------+------------+------------------+ 617 * 618 * The 'data' section would look like (in bytes): 619 * +--------------+------------+-----------------------------------+ 620 * | event_logged | sequence # | error log | 621 * |0 3|4 7|8 nvram_error_log_size-1| 622 * +--------------+------------+-----------------------------------+ 623 * 624 * event_logged: 0 if event has not been logged to syslog, 1 if it has 625 * sequence #: The unique sequence # for each event. (until it wraps) 626 * error log: The error log from event_scan 627 */ 628 int nvram_write_error_log(char * buff, int length, 629 unsigned int err_type, unsigned int error_log_cnt) 630 { 631 int rc; 632 loff_t tmp_index; 633 struct err_log_info info; 634 635 if (nvram_error_log_index == -1) { 636 return -ESPIPE; 637 } 638 639 if (length > nvram_error_log_size) { 640 length = nvram_error_log_size; 641 } 642 643 info.error_type = err_type; 644 info.seq_num = error_log_cnt; 645 646 tmp_index = nvram_error_log_index; 647 648 rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info), &tmp_index); 649 if (rc <= 0) { 650 printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc); 651 return rc; 652 } 653 654 rc = ppc_md.nvram_write(buff, length, &tmp_index); 655 if (rc <= 0) { 656 printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc); 657 return rc; 658 } 659 660 return 0; 661 } 662 663 /* nvram_read_error_log 664 * 665 * Reads nvram for error log for at most 'length' 666 */ 667 int nvram_read_error_log(char * buff, int length, 668 unsigned int * err_type, unsigned int * error_log_cnt) 669 { 670 int rc; 671 loff_t tmp_index; 672 struct err_log_info info; 673 674 if (nvram_error_log_index == -1) 675 return -1; 676 677 if (length > nvram_error_log_size) 678 length = nvram_error_log_size; 679 680 tmp_index = nvram_error_log_index; 681 682 rc = ppc_md.nvram_read((char *)&info, sizeof(struct err_log_info), &tmp_index); 683 if (rc <= 0) { 684 printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc); 685 return rc; 686 } 687 688 rc = ppc_md.nvram_read(buff, length, &tmp_index); 689 if (rc <= 0) { 690 printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc); 691 return rc; 692 } 693 694 *error_log_cnt = info.seq_num; 695 *err_type = info.error_type; 696 697 return 0; 698 } 699 700 /* This doesn't actually zero anything, but it sets the event_logged 701 * word to tell that this event is safely in syslog. 702 */ 703 int nvram_clear_error_log(void) 704 { 705 loff_t tmp_index; 706 int clear_word = ERR_FLAG_ALREADY_LOGGED; 707 int rc; 708 709 tmp_index = nvram_error_log_index; 710 711 rc = ppc_md.nvram_write((char *)&clear_word, sizeof(int), &tmp_index); 712 if (rc <= 0) { 713 printk(KERN_ERR "nvram_clear_error_log: Failed nvram_write (%d)\n", rc); 714 return rc; 715 } 716 717 return 0; 718 } 719 720 #endif /* CONFIG_PPC_PSERIES */ 721 722 module_init(nvram_init); 723 module_exit(nvram_cleanup); 724 MODULE_LICENSE("GPL"); 725