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