1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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 <linux/kmsg_dump.h>
30#include <linux/pstore.h>
31#include <linux/zlib.h>
32#include <asm/uaccess.h>
33#include <asm/nvram.h>
34#include <asm/rtas.h>
35#include <asm/prom.h>
36#include <asm/machdep.h>
37
38#undef DEBUG_NVRAM
39
40#define NVRAM_HEADER_LEN sizeof(struct nvram_header)
41#define NVRAM_BLOCK_LEN NVRAM_HEADER_LEN
42
43
44struct nvram_header {
45 unsigned char signature;
46 unsigned char checksum;
47 unsigned short length;
48
49 char name[12];
50};
51
52struct nvram_partition {
53 struct list_head partition;
54 struct nvram_header header;
55 unsigned int index;
56};
57
58static LIST_HEAD(nvram_partitions);
59
60#ifdef CONFIG_PPC_PSERIES
61struct nvram_os_partition rtas_log_partition = {
62 .name = "ibm,rtas-log",
63 .req_size = 2079,
64 .min_size = 1055,
65 .index = -1,
66 .os_partition = true
67};
68#endif
69
70struct nvram_os_partition oops_log_partition = {
71 .name = "lnx,oops-log",
72 .req_size = 4000,
73 .min_size = 2000,
74 .index = -1,
75 .os_partition = true
76};
77
78static const char *nvram_os_partitions[] = {
79#ifdef CONFIG_PPC_PSERIES
80 "ibm,rtas-log",
81#endif
82 "lnx,oops-log",
83 NULL
84};
85
86static void oops_to_nvram(struct kmsg_dumper *dumper,
87 enum kmsg_dump_reason reason);
88
89static struct kmsg_dumper nvram_kmsg_dumper = {
90 .dump = oops_to_nvram
91};
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118static size_t big_oops_buf_sz;
119static char *big_oops_buf, *oops_buf;
120static char *oops_data;
121static size_t oops_data_sz;
122
123
124#define COMPR_LEVEL 6
125#define WINDOW_BITS 12
126#define MEM_LEVEL 4
127static struct z_stream_s stream;
128
129#ifdef CONFIG_PSTORE
130#ifdef CONFIG_PPC_POWERNV
131static struct nvram_os_partition skiboot_partition = {
132 .name = "ibm,skiboot",
133 .index = -1,
134 .os_partition = false
135};
136#endif
137
138#ifdef CONFIG_PPC_PSERIES
139static struct nvram_os_partition of_config_partition = {
140 .name = "of-config",
141 .index = -1,
142 .os_partition = false
143};
144#endif
145
146static struct nvram_os_partition common_partition = {
147 .name = "common",
148 .index = -1,
149 .os_partition = false
150};
151
152static enum pstore_type_id nvram_type_ids[] = {
153 PSTORE_TYPE_DMESG,
154 PSTORE_TYPE_PPC_COMMON,
155 -1,
156 -1,
157 -1
158};
159static int read_type;
160#endif
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191int nvram_write_os_partition(struct nvram_os_partition *part,
192 char *buff, int length,
193 unsigned int err_type,
194 unsigned int error_log_cnt)
195{
196 int rc;
197 loff_t tmp_index;
198 struct err_log_info info;
199
200 if (part->index == -1)
201 return -ESPIPE;
202
203 if (length > part->size)
204 length = part->size;
205
206 info.error_type = cpu_to_be32(err_type);
207 info.seq_num = cpu_to_be32(error_log_cnt);
208
209 tmp_index = part->index;
210
211 rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info),
212 &tmp_index);
213 if (rc <= 0) {
214 pr_err("%s: Failed nvram_write (%d)\n", __func__, rc);
215 return rc;
216 }
217
218 rc = ppc_md.nvram_write(buff, length, &tmp_index);
219 if (rc <= 0) {
220 pr_err("%s: Failed nvram_write (%d)\n", __func__, rc);
221 return rc;
222 }
223
224 return 0;
225}
226
227
228
229
230
231int nvram_read_partition(struct nvram_os_partition *part, char *buff,
232 int length, unsigned int *err_type,
233 unsigned int *error_log_cnt)
234{
235 int rc;
236 loff_t tmp_index;
237 struct err_log_info info;
238
239 if (part->index == -1)
240 return -1;
241
242 if (length > part->size)
243 length = part->size;
244
245 tmp_index = part->index;
246
247 if (part->os_partition) {
248 rc = ppc_md.nvram_read((char *)&info,
249 sizeof(struct err_log_info),
250 &tmp_index);
251 if (rc <= 0) {
252 pr_err("%s: Failed nvram_read (%d)\n", __func__, rc);
253 return rc;
254 }
255 }
256
257 rc = ppc_md.nvram_read(buff, length, &tmp_index);
258 if (rc <= 0) {
259 pr_err("%s: Failed nvram_read (%d)\n", __func__, rc);
260 return rc;
261 }
262
263 if (part->os_partition) {
264 *error_log_cnt = be32_to_cpu(info.seq_num);
265 *err_type = be32_to_cpu(info.error_type);
266 }
267
268 return 0;
269}
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288int __init nvram_init_os_partition(struct nvram_os_partition *part)
289{
290 loff_t p;
291 int size;
292
293
294 p = nvram_find_partition(part->name, NVRAM_SIG_OS, &size);
295
296
297 if (p && size < part->min_size) {
298 pr_info("nvram: Found too small %s partition,"
299 " removing it...\n", part->name);
300 nvram_remove_partition(part->name, NVRAM_SIG_OS, NULL);
301 p = 0;
302 }
303
304
305 if (!p) {
306 p = nvram_create_partition(part->name, NVRAM_SIG_OS,
307 part->req_size, part->min_size);
308 if (p == -ENOSPC) {
309 pr_info("nvram: No room to create %s partition, "
310 "deleting any obsolete OS partitions...\n",
311 part->name);
312 nvram_remove_partition(NULL, NVRAM_SIG_OS,
313 nvram_os_partitions);
314 p = nvram_create_partition(part->name, NVRAM_SIG_OS,
315 part->req_size, part->min_size);
316 }
317 }
318
319 if (p <= 0) {
320 pr_err("nvram: Failed to find or create %s"
321 " partition, err %d\n", part->name, (int)p);
322 return -1;
323 }
324
325 part->index = p;
326 part->size = nvram_get_partition_size(p) - sizeof(struct err_log_info);
327
328 return 0;
329}
330
331
332static int nvram_compress(const void *in, void *out, size_t inlen,
333 size_t outlen)
334{
335 int err, ret;
336
337 ret = -EIO;
338 err = zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS,
339 MEM_LEVEL, Z_DEFAULT_STRATEGY);
340 if (err != Z_OK)
341 goto error;
342
343 stream.next_in = in;
344 stream.avail_in = inlen;
345 stream.total_in = 0;
346 stream.next_out = out;
347 stream.avail_out = outlen;
348 stream.total_out = 0;
349
350 err = zlib_deflate(&stream, Z_FINISH);
351 if (err != Z_STREAM_END)
352 goto error;
353
354 err = zlib_deflateEnd(&stream);
355 if (err != Z_OK)
356 goto error;
357
358 if (stream.total_out >= stream.total_in)
359 goto error;
360
361 ret = stream.total_out;
362error:
363 return ret;
364}
365
366
367static int zip_oops(size_t text_len)
368{
369 struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
370 int zipped_len = nvram_compress(big_oops_buf, oops_data, text_len,
371 oops_data_sz);
372 if (zipped_len < 0) {
373 pr_err("nvram: compression failed; returned %d\n", zipped_len);
374 pr_err("nvram: logging uncompressed oops/panic report\n");
375 return -1;
376 }
377 oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
378 oops_hdr->report_length = cpu_to_be16(zipped_len);
379 oops_hdr->timestamp = cpu_to_be64(get_seconds());
380 return 0;
381}
382
383#ifdef CONFIG_PSTORE
384static int nvram_pstore_open(struct pstore_info *psi)
385{
386
387 read_type = -1;
388 return 0;
389}
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407static int nvram_pstore_write(enum pstore_type_id type,
408 enum kmsg_dump_reason reason,
409 u64 *id, unsigned int part, int count,
410 bool compressed, size_t size,
411 struct pstore_info *psi)
412{
413 int rc;
414 unsigned int err_type = ERR_TYPE_KERNEL_PANIC;
415 struct oops_log_info *oops_hdr = (struct oops_log_info *) oops_buf;
416
417
418 if (part > 1 || (type != PSTORE_TYPE_DMESG))
419 return -1;
420
421 if (clobbering_unread_rtas_event())
422 return -1;
423
424 oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
425 oops_hdr->report_length = cpu_to_be16(size);
426 oops_hdr->timestamp = cpu_to_be64(get_seconds());
427
428 if (compressed)
429 err_type = ERR_TYPE_KERNEL_PANIC_GZ;
430
431 rc = nvram_write_os_partition(&oops_log_partition, oops_buf,
432 (int) (sizeof(*oops_hdr) + size), err_type, count);
433
434 if (rc != 0)
435 return rc;
436
437 *id = part;
438 return 0;
439}
440
441
442
443
444
445
446static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type,
447 int *count, struct timespec *time, char **buf,
448 bool *compressed, struct pstore_info *psi)
449{
450 struct oops_log_info *oops_hdr;
451 unsigned int err_type, id_no, size = 0;
452 struct nvram_os_partition *part = NULL;
453 char *buff = NULL;
454 int sig = 0;
455 loff_t p;
456
457 read_type++;
458
459 switch (nvram_type_ids[read_type]) {
460 case PSTORE_TYPE_DMESG:
461 part = &oops_log_partition;
462 *type = PSTORE_TYPE_DMESG;
463 break;
464 case PSTORE_TYPE_PPC_COMMON:
465 sig = NVRAM_SIG_SYS;
466 part = &common_partition;
467 *type = PSTORE_TYPE_PPC_COMMON;
468 *id = PSTORE_TYPE_PPC_COMMON;
469 time->tv_sec = 0;
470 time->tv_nsec = 0;
471 break;
472#ifdef CONFIG_PPC_PSERIES
473 case PSTORE_TYPE_PPC_RTAS:
474 part = &rtas_log_partition;
475 *type = PSTORE_TYPE_PPC_RTAS;
476 time->tv_sec = last_rtas_event;
477 time->tv_nsec = 0;
478 break;
479 case PSTORE_TYPE_PPC_OF:
480 sig = NVRAM_SIG_OF;
481 part = &of_config_partition;
482 *type = PSTORE_TYPE_PPC_OF;
483 *id = PSTORE_TYPE_PPC_OF;
484 time->tv_sec = 0;
485 time->tv_nsec = 0;
486 break;
487#endif
488#ifdef CONFIG_PPC_POWERNV
489 case PSTORE_TYPE_PPC_OPAL:
490 sig = NVRAM_SIG_FW;
491 part = &skiboot_partition;
492 *type = PSTORE_TYPE_PPC_OPAL;
493 *id = PSTORE_TYPE_PPC_OPAL;
494 time->tv_sec = 0;
495 time->tv_nsec = 0;
496 break;
497#endif
498 default:
499 return 0;
500 }
501
502 if (!part->os_partition) {
503 p = nvram_find_partition(part->name, sig, &size);
504 if (p <= 0) {
505 pr_err("nvram: Failed to find partition %s, "
506 "err %d\n", part->name, (int)p);
507 return 0;
508 }
509 part->index = p;
510 part->size = size;
511 }
512
513 buff = kmalloc(part->size, GFP_KERNEL);
514
515 if (!buff)
516 return -ENOMEM;
517
518 if (nvram_read_partition(part, buff, part->size, &err_type, &id_no)) {
519 kfree(buff);
520 return 0;
521 }
522
523 *count = 0;
524
525 if (part->os_partition)
526 *id = id_no;
527
528 if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) {
529 size_t length, hdr_size;
530
531 oops_hdr = (struct oops_log_info *)buff;
532 if (be16_to_cpu(oops_hdr->version) < OOPS_HDR_VERSION) {
533
534 hdr_size = sizeof(u16);
535 length = be16_to_cpu(oops_hdr->version);
536 time->tv_sec = 0;
537 time->tv_nsec = 0;
538 } else {
539 hdr_size = sizeof(*oops_hdr);
540 length = be16_to_cpu(oops_hdr->report_length);
541 time->tv_sec = be64_to_cpu(oops_hdr->timestamp);
542 time->tv_nsec = 0;
543 }
544 *buf = kmalloc(length, GFP_KERNEL);
545 if (*buf == NULL)
546 return -ENOMEM;
547 memcpy(*buf, buff + hdr_size, length);
548 kfree(buff);
549
550 if (err_type == ERR_TYPE_KERNEL_PANIC_GZ)
551 *compressed = true;
552 else
553 *compressed = false;
554 return length;
555 }
556
557 *buf = buff;
558 return part->size;
559}
560
561static struct pstore_info nvram_pstore_info = {
562 .owner = THIS_MODULE,
563 .name = "nvram",
564 .open = nvram_pstore_open,
565 .read = nvram_pstore_read,
566 .write = nvram_pstore_write,
567};
568
569static int nvram_pstore_init(void)
570{
571 int rc = 0;
572
573 if (machine_is(pseries)) {
574 nvram_type_ids[2] = PSTORE_TYPE_PPC_RTAS;
575 nvram_type_ids[3] = PSTORE_TYPE_PPC_OF;
576 } else
577 nvram_type_ids[2] = PSTORE_TYPE_PPC_OPAL;
578
579 nvram_pstore_info.buf = oops_data;
580 nvram_pstore_info.bufsize = oops_data_sz;
581
582 spin_lock_init(&nvram_pstore_info.buf_lock);
583
584 rc = pstore_register(&nvram_pstore_info);
585 if (rc != 0)
586 pr_err("nvram: pstore_register() failed, defaults to "
587 "kmsg_dump; returned %d\n", rc);
588
589 return rc;
590}
591#else
592static int nvram_pstore_init(void)
593{
594 return -1;
595}
596#endif
597
598void __init nvram_init_oops_partition(int rtas_partition_exists)
599{
600 int rc;
601
602 rc = nvram_init_os_partition(&oops_log_partition);
603 if (rc != 0) {
604#ifdef CONFIG_PPC_PSERIES
605 if (!rtas_partition_exists) {
606 pr_err("nvram: Failed to initialize oops partition!");
607 return;
608 }
609 pr_notice("nvram: Using %s partition to log both"
610 " RTAS errors and oops/panic reports\n",
611 rtas_log_partition.name);
612 memcpy(&oops_log_partition, &rtas_log_partition,
613 sizeof(rtas_log_partition));
614#else
615 pr_err("nvram: Failed to initialize oops partition!");
616 return;
617#endif
618 }
619 oops_buf = kmalloc(oops_log_partition.size, GFP_KERNEL);
620 if (!oops_buf) {
621 pr_err("nvram: No memory for %s partition\n",
622 oops_log_partition.name);
623 return;
624 }
625 oops_data = oops_buf + sizeof(struct oops_log_info);
626 oops_data_sz = oops_log_partition.size - sizeof(struct oops_log_info);
627
628 rc = nvram_pstore_init();
629
630 if (!rc)
631 return;
632
633
634
635
636
637
638 big_oops_buf_sz = (oops_data_sz * 100) / 45;
639 big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
640 if (big_oops_buf) {
641 stream.workspace = kmalloc(zlib_deflate_workspacesize(
642 WINDOW_BITS, MEM_LEVEL), GFP_KERNEL);
643 if (!stream.workspace) {
644 pr_err("nvram: No memory for compression workspace; "
645 "skipping compression of %s partition data\n",
646 oops_log_partition.name);
647 kfree(big_oops_buf);
648 big_oops_buf = NULL;
649 }
650 } else {
651 pr_err("No memory for uncompressed %s data; "
652 "skipping compression\n", oops_log_partition.name);
653 stream.workspace = NULL;
654 }
655
656 rc = kmsg_dump_register(&nvram_kmsg_dumper);
657 if (rc != 0) {
658 pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc);
659 kfree(oops_buf);
660 kfree(big_oops_buf);
661 kfree(stream.workspace);
662 }
663}
664
665
666
667
668
669
670
671
672static void oops_to_nvram(struct kmsg_dumper *dumper,
673 enum kmsg_dump_reason reason)
674{
675 struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
676 static unsigned int oops_count = 0;
677 static bool panicking = false;
678 static DEFINE_SPINLOCK(lock);
679 unsigned long flags;
680 size_t text_len;
681 unsigned int err_type = ERR_TYPE_KERNEL_PANIC_GZ;
682 int rc = -1;
683
684 switch (reason) {
685 case KMSG_DUMP_RESTART:
686 case KMSG_DUMP_HALT:
687 case KMSG_DUMP_POWEROFF:
688
689 return;
690 case KMSG_DUMP_OOPS:
691 break;
692 case KMSG_DUMP_PANIC:
693 panicking = true;
694 break;
695 case KMSG_DUMP_EMERG:
696 if (panicking)
697
698 return;
699 break;
700 default:
701 pr_err("%s: ignoring unrecognized KMSG_DUMP_* reason %d\n",
702 __func__, (int) reason);
703 return;
704 }
705
706 if (clobbering_unread_rtas_event())
707 return;
708
709 if (!spin_trylock_irqsave(&lock, flags))
710 return;
711
712 if (big_oops_buf) {
713 kmsg_dump_get_buffer(dumper, false,
714 big_oops_buf, big_oops_buf_sz, &text_len);
715 rc = zip_oops(text_len);
716 }
717 if (rc != 0) {
718 kmsg_dump_rewind(dumper);
719 kmsg_dump_get_buffer(dumper, false,
720 oops_data, oops_data_sz, &text_len);
721 err_type = ERR_TYPE_KERNEL_PANIC;
722 oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
723 oops_hdr->report_length = cpu_to_be16(text_len);
724 oops_hdr->timestamp = cpu_to_be64(get_seconds());
725 }
726
727 (void) nvram_write_os_partition(&oops_log_partition, oops_buf,
728 (int) (sizeof(*oops_hdr) + text_len), err_type,
729 ++oops_count);
730
731 spin_unlock_irqrestore(&lock, flags);
732}
733
734static loff_t dev_nvram_llseek(struct file *file, loff_t offset, int origin)
735{
736 int size;
737
738 if (ppc_md.nvram_size == NULL)
739 return -ENODEV;
740 size = ppc_md.nvram_size();
741
742 switch (origin) {
743 case 1:
744 offset += file->f_pos;
745 break;
746 case 2:
747 offset += size;
748 break;
749 }
750 if (offset < 0)
751 return -EINVAL;
752 file->f_pos = offset;
753 return file->f_pos;
754}
755
756
757static ssize_t dev_nvram_read(struct file *file, char __user *buf,
758 size_t count, loff_t *ppos)
759{
760 ssize_t ret;
761 char *tmp = NULL;
762 ssize_t size;
763
764 if (!ppc_md.nvram_size) {
765 ret = -ENODEV;
766 goto out;
767 }
768
769 size = ppc_md.nvram_size();
770 if (size < 0) {
771 ret = size;
772 goto out;
773 }
774
775 if (*ppos >= size) {
776 ret = 0;
777 goto out;
778 }
779
780 count = min_t(size_t, count, size - *ppos);
781 count = min(count, PAGE_SIZE);
782
783 tmp = kmalloc(count, GFP_KERNEL);
784 if (!tmp) {
785 ret = -ENOMEM;
786 goto out;
787 }
788
789 ret = ppc_md.nvram_read(tmp, count, ppos);
790 if (ret <= 0)
791 goto out;
792
793 if (copy_to_user(buf, tmp, ret))
794 ret = -EFAULT;
795
796out:
797 kfree(tmp);
798 return ret;
799
800}
801
802static ssize_t dev_nvram_write(struct file *file, const char __user *buf,
803 size_t count, loff_t *ppos)
804{
805 ssize_t ret;
806 char *tmp = NULL;
807 ssize_t size;
808
809 ret = -ENODEV;
810 if (!ppc_md.nvram_size)
811 goto out;
812
813 ret = 0;
814 size = ppc_md.nvram_size();
815 if (*ppos >= size || size < 0)
816 goto out;
817
818 count = min_t(size_t, count, size - *ppos);
819 count = min(count, PAGE_SIZE);
820
821 ret = -ENOMEM;
822 tmp = kmalloc(count, GFP_KERNEL);
823 if (!tmp)
824 goto out;
825
826 ret = -EFAULT;
827 if (copy_from_user(tmp, buf, count))
828 goto out;
829
830 ret = ppc_md.nvram_write(tmp, count, ppos);
831
832out:
833 kfree(tmp);
834 return ret;
835
836}
837
838static long dev_nvram_ioctl(struct file *file, unsigned int cmd,
839 unsigned long arg)
840{
841 switch(cmd) {
842#ifdef CONFIG_PPC_PMAC
843 case OBSOLETE_PMAC_NVRAM_GET_OFFSET:
844 printk(KERN_WARNING "nvram: Using obsolete PMAC_NVRAM_GET_OFFSET ioctl\n");
845 case IOC_NVRAM_GET_OFFSET: {
846 int part, offset;
847
848 if (!machine_is(powermac))
849 return -EINVAL;
850 if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0)
851 return -EFAULT;
852 if (part < pmac_nvram_OF || part > pmac_nvram_NR)
853 return -EINVAL;
854 offset = pmac_get_partition(part);
855 if (offset < 0)
856 return offset;
857 if (copy_to_user((void __user*)arg, &offset, sizeof(offset)) != 0)
858 return -EFAULT;
859 return 0;
860 }
861#endif
862 default:
863 return -EINVAL;
864 }
865}
866
867static const struct file_operations nvram_fops = {
868 .owner = THIS_MODULE,
869 .llseek = dev_nvram_llseek,
870 .read = dev_nvram_read,
871 .write = dev_nvram_write,
872 .unlocked_ioctl = dev_nvram_ioctl,
873};
874
875static struct miscdevice nvram_dev = {
876 NVRAM_MINOR,
877 "nvram",
878 &nvram_fops
879};
880
881
882#ifdef DEBUG_NVRAM
883static void __init nvram_print_partitions(char * label)
884{
885 struct nvram_partition * tmp_part;
886
887 printk(KERN_WARNING "--------%s---------\n", label);
888 printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n");
889 list_for_each_entry(tmp_part, &nvram_partitions, partition) {
890 printk(KERN_WARNING "%4d \t%02x\t%02x\t%d\t%12.12s\n",
891 tmp_part->index, tmp_part->header.signature,
892 tmp_part->header.checksum, tmp_part->header.length,
893 tmp_part->header.name);
894 }
895}
896#endif
897
898
899static int __init nvram_write_header(struct nvram_partition * part)
900{
901 loff_t tmp_index;
902 int rc;
903 struct nvram_header phead;
904
905 memcpy(&phead, &part->header, NVRAM_HEADER_LEN);
906 phead.length = cpu_to_be16(phead.length);
907
908 tmp_index = part->index;
909 rc = ppc_md.nvram_write((char *)&phead, NVRAM_HEADER_LEN, &tmp_index);
910
911 return rc;
912}
913
914
915static unsigned char __init nvram_checksum(struct nvram_header *p)
916{
917 unsigned int c_sum, c_sum2;
918 unsigned short *sp = (unsigned short *)p->name;
919 c_sum = p->signature + p->length + sp[0] + sp[1] + sp[2] + sp[3] + sp[4] + sp[5];
920
921
922 c_sum = ((c_sum & 0xffff) + (c_sum >> 16)) & 0xffff;
923
924 c_sum2 = (c_sum >> 8) + (c_sum << 8);
925 c_sum = ((c_sum + c_sum2) >> 8) & 0xff;
926 return c_sum;
927}
928
929
930
931
932
933static int nvram_can_remove_partition(struct nvram_partition *part,
934 const char *name, int sig, const char *exceptions[])
935{
936 if (part->header.signature != sig)
937 return 0;
938 if (name) {
939 if (strncmp(name, part->header.name, 12))
940 return 0;
941 } else if (exceptions) {
942 const char **except;
943 for (except = exceptions; *except; except++) {
944 if (!strncmp(*except, part->header.name, 12))
945 return 0;
946 }
947 }
948 return 1;
949}
950
951
952
953
954
955
956
957
958
959
960int __init nvram_remove_partition(const char *name, int sig,
961 const char *exceptions[])
962{
963 struct nvram_partition *part, *prev, *tmp;
964 int rc;
965
966 list_for_each_entry(part, &nvram_partitions, partition) {
967 if (!nvram_can_remove_partition(part, name, sig, exceptions))
968 continue;
969
970
971 part->header.signature = NVRAM_SIG_FREE;
972 strncpy(part->header.name, "wwwwwwwwwwww", 12);
973 part->header.checksum = nvram_checksum(&part->header);
974 rc = nvram_write_header(part);
975 if (rc <= 0) {
976 printk(KERN_ERR "nvram_remove_partition: nvram_write failed (%d)\n", rc);
977 return rc;
978 }
979 }
980
981
982 prev = NULL;
983 list_for_each_entry_safe(part, tmp, &nvram_partitions, partition) {
984 if (part->header.signature != NVRAM_SIG_FREE) {
985 prev = NULL;
986 continue;
987 }
988 if (prev) {
989 prev->header.length += part->header.length;
990 prev->header.checksum = nvram_checksum(&part->header);
991 rc = nvram_write_header(part);
992 if (rc <= 0) {
993 printk(KERN_ERR "nvram_remove_partition: nvram_write failed (%d)\n", rc);
994 return rc;
995 }
996 list_del(&part->partition);
997 kfree(part);
998 } else
999 prev = part;
1000 }
1001
1002 return 0;
1003}
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018loff_t __init nvram_create_partition(const char *name, int sig,
1019 int req_size, int min_size)
1020{
1021 struct nvram_partition *part;
1022 struct nvram_partition *new_part;
1023 struct nvram_partition *free_part = NULL;
1024 static char nv_init_vals[16];
1025 loff_t tmp_index;
1026 long size = 0;
1027 int rc;
1028
1029
1030 req_size = _ALIGN_UP(req_size, NVRAM_BLOCK_LEN) / NVRAM_BLOCK_LEN;
1031 min_size = _ALIGN_UP(min_size, NVRAM_BLOCK_LEN) / NVRAM_BLOCK_LEN;
1032
1033
1034
1035
1036 if (min_size == 0)
1037 min_size = req_size;
1038 if (min_size > req_size)
1039 return -EINVAL;
1040
1041
1042 req_size += 1;
1043 min_size += 1;
1044
1045
1046
1047 list_for_each_entry(part, &nvram_partitions, partition) {
1048 if (part->header.signature != NVRAM_SIG_FREE)
1049 continue;
1050
1051 if (part->header.length >= req_size) {
1052 size = req_size;
1053 free_part = part;
1054 break;
1055 }
1056 if (part->header.length > size &&
1057 part->header.length >= min_size) {
1058 size = part->header.length;
1059 free_part = part;
1060 }
1061 }
1062 if (!size)
1063 return -ENOSPC;
1064
1065
1066 new_part = kmalloc(sizeof(*new_part), GFP_KERNEL);
1067 if (!new_part) {
1068 pr_err("nvram_create_os_partition: kmalloc failed\n");
1069 return -ENOMEM;
1070 }
1071
1072 new_part->index = free_part->index;
1073 new_part->header.signature = sig;
1074 new_part->header.length = size;
1075 strncpy(new_part->header.name, name, 12);
1076 new_part->header.checksum = nvram_checksum(&new_part->header);
1077
1078 rc = nvram_write_header(new_part);
1079 if (rc <= 0) {
1080 pr_err("nvram_create_os_partition: nvram_write_header "
1081 "failed (%d)\n", rc);
1082 return rc;
1083 }
1084 list_add_tail(&new_part->partition, &free_part->partition);
1085
1086
1087 if (free_part->header.length > size) {
1088 free_part->index += size * NVRAM_BLOCK_LEN;
1089 free_part->header.length -= size;
1090 free_part->header.checksum = nvram_checksum(&free_part->header);
1091 rc = nvram_write_header(free_part);
1092 if (rc <= 0) {
1093 pr_err("nvram_create_os_partition: nvram_write_header "
1094 "failed (%d)\n", rc);
1095 return rc;
1096 }
1097 } else {
1098 list_del(&free_part->partition);
1099 kfree(free_part);
1100 }
1101
1102
1103 for (tmp_index = new_part->index + NVRAM_HEADER_LEN;
1104 tmp_index < ((size - 1) * NVRAM_BLOCK_LEN);
1105 tmp_index += NVRAM_BLOCK_LEN) {
1106 rc = ppc_md.nvram_write(nv_init_vals, NVRAM_BLOCK_LEN, &tmp_index);
1107 if (rc <= 0) {
1108 pr_err("nvram_create_partition: nvram_write failed (%d)\n", rc);
1109 return rc;
1110 }
1111 }
1112
1113 return new_part->index + NVRAM_HEADER_LEN;
1114}
1115
1116
1117
1118
1119
1120
1121
1122int nvram_get_partition_size(loff_t data_index)
1123{
1124 struct nvram_partition *part;
1125
1126 list_for_each_entry(part, &nvram_partitions, partition) {
1127 if (part->index + NVRAM_HEADER_LEN == data_index)
1128 return (part->header.length - 1) * NVRAM_BLOCK_LEN;
1129 }
1130 return -1;
1131}
1132
1133
1134
1135
1136
1137
1138
1139
1140loff_t nvram_find_partition(const char *name, int sig, int *out_size)
1141{
1142 struct nvram_partition *p;
1143
1144 list_for_each_entry(p, &nvram_partitions, partition) {
1145 if (p->header.signature == sig &&
1146 (!name || !strncmp(p->header.name, name, 12))) {
1147 if (out_size)
1148 *out_size = (p->header.length - 1) *
1149 NVRAM_BLOCK_LEN;
1150 return p->index + NVRAM_HEADER_LEN;
1151 }
1152 }
1153 return 0;
1154}
1155
1156int __init nvram_scan_partitions(void)
1157{
1158 loff_t cur_index = 0;
1159 struct nvram_header phead;
1160 struct nvram_partition * tmp_part;
1161 unsigned char c_sum;
1162 char * header;
1163 int total_size;
1164 int err;
1165
1166 if (ppc_md.nvram_size == NULL || ppc_md.nvram_size() <= 0)
1167 return -ENODEV;
1168 total_size = ppc_md.nvram_size();
1169
1170 header = kmalloc(NVRAM_HEADER_LEN, GFP_KERNEL);
1171 if (!header) {
1172 printk(KERN_ERR "nvram_scan_partitions: Failed kmalloc\n");
1173 return -ENOMEM;
1174 }
1175
1176 while (cur_index < total_size) {
1177
1178 err = ppc_md.nvram_read(header, NVRAM_HEADER_LEN, &cur_index);
1179 if (err != NVRAM_HEADER_LEN) {
1180 printk(KERN_ERR "nvram_scan_partitions: Error parsing "
1181 "nvram partitions\n");
1182 goto out;
1183 }
1184
1185 cur_index -= NVRAM_HEADER_LEN;
1186
1187 memcpy(&phead, header, NVRAM_HEADER_LEN);
1188
1189 phead.length = be16_to_cpu(phead.length);
1190
1191 err = 0;
1192 c_sum = nvram_checksum(&phead);
1193 if (c_sum != phead.checksum) {
1194 printk(KERN_WARNING "WARNING: nvram partition checksum"
1195 " was %02x, should be %02x!\n",
1196 phead.checksum, c_sum);
1197 printk(KERN_WARNING "Terminating nvram partition scan\n");
1198 goto out;
1199 }
1200 if (!phead.length) {
1201 printk(KERN_WARNING "WARNING: nvram corruption "
1202 "detected: 0-length partition\n");
1203 goto out;
1204 }
1205 tmp_part = kmalloc(sizeof(struct nvram_partition), GFP_KERNEL);
1206 err = -ENOMEM;
1207 if (!tmp_part) {
1208 printk(KERN_ERR "nvram_scan_partitions: kmalloc failed\n");
1209 goto out;
1210 }
1211
1212 memcpy(&tmp_part->header, &phead, NVRAM_HEADER_LEN);
1213 tmp_part->index = cur_index;
1214 list_add_tail(&tmp_part->partition, &nvram_partitions);
1215
1216 cur_index += phead.length * NVRAM_BLOCK_LEN;
1217 }
1218 err = 0;
1219
1220#ifdef DEBUG_NVRAM
1221 nvram_print_partitions("NVRAM Partitions");
1222#endif
1223
1224 out:
1225 kfree(header);
1226 return err;
1227}
1228
1229static int __init nvram_init(void)
1230{
1231 int rc;
1232
1233 BUILD_BUG_ON(NVRAM_BLOCK_LEN != 16);
1234
1235 if (ppc_md.nvram_size == NULL || ppc_md.nvram_size() <= 0)
1236 return -ENODEV;
1237
1238 rc = misc_register(&nvram_dev);
1239 if (rc != 0) {
1240 printk(KERN_ERR "nvram_init: failed to register device\n");
1241 return rc;
1242 }
1243
1244 return rc;
1245}
1246
1247void __exit nvram_cleanup(void)
1248{
1249 misc_deregister( &nvram_dev );
1250}
1251
1252module_init(nvram_init);
1253module_exit(nvram_cleanup);
1254MODULE_LICENSE("GPL");
1255