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 <linux/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
398static int nvram_pstore_write(struct pstore_record *record)
399{
400 int rc;
401 unsigned int err_type = ERR_TYPE_KERNEL_PANIC;
402 struct oops_log_info *oops_hdr = (struct oops_log_info *) oops_buf;
403
404
405 if (record->part > 1 || (record->type != PSTORE_TYPE_DMESG))
406 return -1;
407
408 if (clobbering_unread_rtas_event())
409 return -1;
410
411 oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
412 oops_hdr->report_length = cpu_to_be16(record->size);
413 oops_hdr->timestamp = cpu_to_be64(ktime_get_real_seconds());
414
415 if (record->compressed)
416 err_type = ERR_TYPE_KERNEL_PANIC_GZ;
417
418 rc = nvram_write_os_partition(&oops_log_partition, oops_buf,
419 (int) (sizeof(*oops_hdr) + record->size), err_type,
420 record->count);
421
422 if (rc != 0)
423 return rc;
424
425 record->id = record->part;
426 return 0;
427}
428
429
430
431
432
433
434static ssize_t nvram_pstore_read(struct pstore_record *record)
435{
436 struct oops_log_info *oops_hdr;
437 unsigned int err_type, id_no, size = 0;
438 struct nvram_os_partition *part = NULL;
439 char *buff = NULL;
440 int sig = 0;
441 loff_t p;
442
443 read_type++;
444
445 switch (nvram_type_ids[read_type]) {
446 case PSTORE_TYPE_DMESG:
447 part = &oops_log_partition;
448 record->type = PSTORE_TYPE_DMESG;
449 break;
450 case PSTORE_TYPE_PPC_COMMON:
451 sig = NVRAM_SIG_SYS;
452 part = &common_partition;
453 record->type = PSTORE_TYPE_PPC_COMMON;
454 record->id = PSTORE_TYPE_PPC_COMMON;
455 record->time.tv_sec = 0;
456 record->time.tv_nsec = 0;
457 break;
458#ifdef CONFIG_PPC_PSERIES
459 case PSTORE_TYPE_PPC_RTAS:
460 part = &rtas_log_partition;
461 record->type = PSTORE_TYPE_PPC_RTAS;
462 record->time.tv_sec = last_rtas_event;
463 record->time.tv_nsec = 0;
464 break;
465 case PSTORE_TYPE_PPC_OF:
466 sig = NVRAM_SIG_OF;
467 part = &of_config_partition;
468 record->type = PSTORE_TYPE_PPC_OF;
469 record->id = PSTORE_TYPE_PPC_OF;
470 record->time.tv_sec = 0;
471 record->time.tv_nsec = 0;
472 break;
473#endif
474#ifdef CONFIG_PPC_POWERNV
475 case PSTORE_TYPE_PPC_OPAL:
476 sig = NVRAM_SIG_FW;
477 part = &skiboot_partition;
478 record->type = PSTORE_TYPE_PPC_OPAL;
479 record->id = PSTORE_TYPE_PPC_OPAL;
480 record->time.tv_sec = 0;
481 record->time.tv_nsec = 0;
482 break;
483#endif
484 default:
485 return 0;
486 }
487
488 if (!part->os_partition) {
489 p = nvram_find_partition(part->name, sig, &size);
490 if (p <= 0) {
491 pr_err("nvram: Failed to find partition %s, "
492 "err %d\n", part->name, (int)p);
493 return 0;
494 }
495 part->index = p;
496 part->size = size;
497 }
498
499 buff = kmalloc(part->size, GFP_KERNEL);
500
501 if (!buff)
502 return -ENOMEM;
503
504 if (nvram_read_partition(part, buff, part->size, &err_type, &id_no)) {
505 kfree(buff);
506 return 0;
507 }
508
509 record->count = 0;
510
511 if (part->os_partition)
512 record->id = id_no;
513
514 if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) {
515 size_t length, hdr_size;
516
517 oops_hdr = (struct oops_log_info *)buff;
518 if (be16_to_cpu(oops_hdr->version) < OOPS_HDR_VERSION) {
519
520 hdr_size = sizeof(u16);
521 length = be16_to_cpu(oops_hdr->version);
522 record->time.tv_sec = 0;
523 record->time.tv_nsec = 0;
524 } else {
525 hdr_size = sizeof(*oops_hdr);
526 length = be16_to_cpu(oops_hdr->report_length);
527 record->time.tv_sec = be64_to_cpu(oops_hdr->timestamp);
528 record->time.tv_nsec = 0;
529 }
530 record->buf = kmemdup(buff + hdr_size, length, GFP_KERNEL);
531 kfree(buff);
532 if (record->buf == NULL)
533 return -ENOMEM;
534
535 record->ecc_notice_size = 0;
536 if (err_type == ERR_TYPE_KERNEL_PANIC_GZ)
537 record->compressed = true;
538 else
539 record->compressed = false;
540 return length;
541 }
542
543 record->buf = buff;
544 return part->size;
545}
546
547static struct pstore_info nvram_pstore_info = {
548 .owner = THIS_MODULE,
549 .name = "nvram",
550 .flags = PSTORE_FLAGS_DMESG,
551 .open = nvram_pstore_open,
552 .read = nvram_pstore_read,
553 .write = nvram_pstore_write,
554};
555
556static int nvram_pstore_init(void)
557{
558 int rc = 0;
559
560 if (machine_is(pseries)) {
561 nvram_type_ids[2] = PSTORE_TYPE_PPC_RTAS;
562 nvram_type_ids[3] = PSTORE_TYPE_PPC_OF;
563 } else
564 nvram_type_ids[2] = PSTORE_TYPE_PPC_OPAL;
565
566 nvram_pstore_info.buf = oops_data;
567 nvram_pstore_info.bufsize = oops_data_sz;
568
569 spin_lock_init(&nvram_pstore_info.buf_lock);
570
571 rc = pstore_register(&nvram_pstore_info);
572 if (rc && (rc != -EPERM))
573
574 pr_err("nvram: pstore_register() failed, returned %d. "
575 "Defaults to kmsg_dump\n", rc);
576
577 return rc;
578}
579#else
580static int nvram_pstore_init(void)
581{
582 return -1;
583}
584#endif
585
586void __init nvram_init_oops_partition(int rtas_partition_exists)
587{
588 int rc;
589
590 rc = nvram_init_os_partition(&oops_log_partition);
591 if (rc != 0) {
592#ifdef CONFIG_PPC_PSERIES
593 if (!rtas_partition_exists) {
594 pr_err("nvram: Failed to initialize oops partition!");
595 return;
596 }
597 pr_notice("nvram: Using %s partition to log both"
598 " RTAS errors and oops/panic reports\n",
599 rtas_log_partition.name);
600 memcpy(&oops_log_partition, &rtas_log_partition,
601 sizeof(rtas_log_partition));
602#else
603 pr_err("nvram: Failed to initialize oops partition!");
604 return;
605#endif
606 }
607 oops_buf = kmalloc(oops_log_partition.size, GFP_KERNEL);
608 if (!oops_buf) {
609 pr_err("nvram: No memory for %s partition\n",
610 oops_log_partition.name);
611 return;
612 }
613 oops_data = oops_buf + sizeof(struct oops_log_info);
614 oops_data_sz = oops_log_partition.size - sizeof(struct oops_log_info);
615
616 rc = nvram_pstore_init();
617
618 if (!rc)
619 return;
620
621
622
623
624
625
626 big_oops_buf_sz = (oops_data_sz * 100) / 45;
627 big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
628 if (big_oops_buf) {
629 stream.workspace = kmalloc(zlib_deflate_workspacesize(
630 WINDOW_BITS, MEM_LEVEL), GFP_KERNEL);
631 if (!stream.workspace) {
632 pr_err("nvram: No memory for compression workspace; "
633 "skipping compression of %s partition data\n",
634 oops_log_partition.name);
635 kfree(big_oops_buf);
636 big_oops_buf = NULL;
637 }
638 } else {
639 pr_err("No memory for uncompressed %s data; "
640 "skipping compression\n", oops_log_partition.name);
641 stream.workspace = NULL;
642 }
643
644 rc = kmsg_dump_register(&nvram_kmsg_dumper);
645 if (rc != 0) {
646 pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc);
647 kfree(oops_buf);
648 kfree(big_oops_buf);
649 kfree(stream.workspace);
650 }
651}
652
653
654
655
656
657
658
659
660static void oops_to_nvram(struct kmsg_dumper *dumper,
661 enum kmsg_dump_reason reason)
662{
663 struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
664 static unsigned int oops_count = 0;
665 static bool panicking = false;
666 static DEFINE_SPINLOCK(lock);
667 unsigned long flags;
668 size_t text_len;
669 unsigned int err_type = ERR_TYPE_KERNEL_PANIC_GZ;
670 int rc = -1;
671
672 switch (reason) {
673 case KMSG_DUMP_RESTART:
674 case KMSG_DUMP_HALT:
675 case KMSG_DUMP_POWEROFF:
676
677 return;
678 case KMSG_DUMP_OOPS:
679 break;
680 case KMSG_DUMP_PANIC:
681 panicking = true;
682 break;
683 case KMSG_DUMP_EMERG:
684 if (panicking)
685
686 return;
687 break;
688 default:
689 pr_err("%s: ignoring unrecognized KMSG_DUMP_* reason %d\n",
690 __func__, (int) reason);
691 return;
692 }
693
694 if (clobbering_unread_rtas_event())
695 return;
696
697 if (!spin_trylock_irqsave(&lock, flags))
698 return;
699
700 if (big_oops_buf) {
701 kmsg_dump_get_buffer(dumper, false,
702 big_oops_buf, big_oops_buf_sz, &text_len);
703 rc = zip_oops(text_len);
704 }
705 if (rc != 0) {
706 kmsg_dump_rewind(dumper);
707 kmsg_dump_get_buffer(dumper, false,
708 oops_data, oops_data_sz, &text_len);
709 err_type = ERR_TYPE_KERNEL_PANIC;
710 oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
711 oops_hdr->report_length = cpu_to_be16(text_len);
712 oops_hdr->timestamp = cpu_to_be64(ktime_get_real_seconds());
713 }
714
715 (void) nvram_write_os_partition(&oops_log_partition, oops_buf,
716 (int) (sizeof(*oops_hdr) + text_len), err_type,
717 ++oops_count);
718
719 spin_unlock_irqrestore(&lock, flags);
720}
721
722static loff_t dev_nvram_llseek(struct file *file, loff_t offset, int origin)
723{
724 if (ppc_md.nvram_size == NULL)
725 return -ENODEV;
726 return generic_file_llseek_size(file, offset, origin, MAX_LFS_FILESIZE,
727 ppc_md.nvram_size());
728}
729
730
731static ssize_t dev_nvram_read(struct file *file, char __user *buf,
732 size_t count, loff_t *ppos)
733{
734 ssize_t ret;
735 char *tmp = NULL;
736 ssize_t size;
737
738 if (!ppc_md.nvram_size) {
739 ret = -ENODEV;
740 goto out;
741 }
742
743 size = ppc_md.nvram_size();
744 if (size < 0) {
745 ret = size;
746 goto out;
747 }
748
749 if (*ppos >= size) {
750 ret = 0;
751 goto out;
752 }
753
754 count = min_t(size_t, count, size - *ppos);
755 count = min(count, PAGE_SIZE);
756
757 tmp = kmalloc(count, GFP_KERNEL);
758 if (!tmp) {
759 ret = -ENOMEM;
760 goto out;
761 }
762
763 ret = ppc_md.nvram_read(tmp, count, ppos);
764 if (ret <= 0)
765 goto out;
766
767 if (copy_to_user(buf, tmp, ret))
768 ret = -EFAULT;
769
770out:
771 kfree(tmp);
772 return ret;
773
774}
775
776static ssize_t dev_nvram_write(struct file *file, const char __user *buf,
777 size_t count, loff_t *ppos)
778{
779 ssize_t ret;
780 char *tmp = NULL;
781 ssize_t size;
782
783 ret = -ENODEV;
784 if (!ppc_md.nvram_size)
785 goto out;
786
787 ret = 0;
788 size = ppc_md.nvram_size();
789 if (*ppos >= size || size < 0)
790 goto out;
791
792 count = min_t(size_t, count, size - *ppos);
793 count = min(count, PAGE_SIZE);
794
795 tmp = memdup_user(buf, count);
796 if (IS_ERR(tmp)) {
797 ret = PTR_ERR(tmp);
798 goto out;
799 }
800
801 ret = ppc_md.nvram_write(tmp, count, ppos);
802
803 kfree(tmp);
804out:
805 return ret;
806}
807
808static long dev_nvram_ioctl(struct file *file, unsigned int cmd,
809 unsigned long arg)
810{
811 switch(cmd) {
812#ifdef CONFIG_PPC_PMAC
813 case OBSOLETE_PMAC_NVRAM_GET_OFFSET:
814 printk(KERN_WARNING "nvram: Using obsolete PMAC_NVRAM_GET_OFFSET ioctl\n");
815 case IOC_NVRAM_GET_OFFSET: {
816 int part, offset;
817
818 if (!machine_is(powermac))
819 return -EINVAL;
820 if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0)
821 return -EFAULT;
822 if (part < pmac_nvram_OF || part > pmac_nvram_NR)
823 return -EINVAL;
824 offset = pmac_get_partition(part);
825 if (offset < 0)
826 return offset;
827 if (copy_to_user((void __user*)arg, &offset, sizeof(offset)) != 0)
828 return -EFAULT;
829 return 0;
830 }
831#endif
832 default:
833 return -EINVAL;
834 }
835}
836
837static const struct file_operations nvram_fops = {
838 .owner = THIS_MODULE,
839 .llseek = dev_nvram_llseek,
840 .read = dev_nvram_read,
841 .write = dev_nvram_write,
842 .unlocked_ioctl = dev_nvram_ioctl,
843};
844
845static struct miscdevice nvram_dev = {
846 NVRAM_MINOR,
847 "nvram",
848 &nvram_fops
849};
850
851
852#ifdef DEBUG_NVRAM
853static void __init nvram_print_partitions(char * label)
854{
855 struct nvram_partition * tmp_part;
856
857 printk(KERN_WARNING "--------%s---------\n", label);
858 printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n");
859 list_for_each_entry(tmp_part, &nvram_partitions, partition) {
860 printk(KERN_WARNING "%4d \t%02x\t%02x\t%d\t%12.12s\n",
861 tmp_part->index, tmp_part->header.signature,
862 tmp_part->header.checksum, tmp_part->header.length,
863 tmp_part->header.name);
864 }
865}
866#endif
867
868
869static int __init nvram_write_header(struct nvram_partition * part)
870{
871 loff_t tmp_index;
872 int rc;
873 struct nvram_header phead;
874
875 memcpy(&phead, &part->header, NVRAM_HEADER_LEN);
876 phead.length = cpu_to_be16(phead.length);
877
878 tmp_index = part->index;
879 rc = ppc_md.nvram_write((char *)&phead, NVRAM_HEADER_LEN, &tmp_index);
880
881 return rc;
882}
883
884
885static unsigned char __init nvram_checksum(struct nvram_header *p)
886{
887 unsigned int c_sum, c_sum2;
888 unsigned short *sp = (unsigned short *)p->name;
889 c_sum = p->signature + p->length + sp[0] + sp[1] + sp[2] + sp[3] + sp[4] + sp[5];
890
891
892 c_sum = ((c_sum & 0xffff) + (c_sum >> 16)) & 0xffff;
893
894 c_sum2 = (c_sum >> 8) + (c_sum << 8);
895 c_sum = ((c_sum + c_sum2) >> 8) & 0xff;
896 return c_sum;
897}
898
899
900
901
902
903static int nvram_can_remove_partition(struct nvram_partition *part,
904 const char *name, int sig, const char *exceptions[])
905{
906 if (part->header.signature != sig)
907 return 0;
908 if (name) {
909 if (strncmp(name, part->header.name, 12))
910 return 0;
911 } else if (exceptions) {
912 const char **except;
913 for (except = exceptions; *except; except++) {
914 if (!strncmp(*except, part->header.name, 12))
915 return 0;
916 }
917 }
918 return 1;
919}
920
921
922
923
924
925
926
927
928
929
930int __init nvram_remove_partition(const char *name, int sig,
931 const char *exceptions[])
932{
933 struct nvram_partition *part, *prev, *tmp;
934 int rc;
935
936 list_for_each_entry(part, &nvram_partitions, partition) {
937 if (!nvram_can_remove_partition(part, name, sig, exceptions))
938 continue;
939
940
941 part->header.signature = NVRAM_SIG_FREE;
942 memset(part->header.name, 'w', 12);
943 part->header.checksum = nvram_checksum(&part->header);
944 rc = nvram_write_header(part);
945 if (rc <= 0) {
946 printk(KERN_ERR "nvram_remove_partition: nvram_write failed (%d)\n", rc);
947 return rc;
948 }
949 }
950
951
952 prev = NULL;
953 list_for_each_entry_safe(part, tmp, &nvram_partitions, partition) {
954 if (part->header.signature != NVRAM_SIG_FREE) {
955 prev = NULL;
956 continue;
957 }
958 if (prev) {
959 prev->header.length += part->header.length;
960 prev->header.checksum = nvram_checksum(&prev->header);
961 rc = nvram_write_header(prev);
962 if (rc <= 0) {
963 printk(KERN_ERR "nvram_remove_partition: nvram_write failed (%d)\n", rc);
964 return rc;
965 }
966 list_del(&part->partition);
967 kfree(part);
968 } else
969 prev = part;
970 }
971
972 return 0;
973}
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988loff_t __init nvram_create_partition(const char *name, int sig,
989 int req_size, int min_size)
990{
991 struct nvram_partition *part;
992 struct nvram_partition *new_part;
993 struct nvram_partition *free_part = NULL;
994 static char nv_init_vals[16];
995 loff_t tmp_index;
996 long size = 0;
997 int rc;
998
999
1000 req_size = _ALIGN_UP(req_size, NVRAM_BLOCK_LEN) / NVRAM_BLOCK_LEN;
1001 min_size = _ALIGN_UP(min_size, NVRAM_BLOCK_LEN) / NVRAM_BLOCK_LEN;
1002
1003
1004
1005
1006 if (min_size == 0)
1007 min_size = req_size;
1008 if (min_size > req_size)
1009 return -EINVAL;
1010
1011
1012 req_size += 1;
1013 min_size += 1;
1014
1015
1016
1017 list_for_each_entry(part, &nvram_partitions, partition) {
1018 if (part->header.signature != NVRAM_SIG_FREE)
1019 continue;
1020
1021 if (part->header.length >= req_size) {
1022 size = req_size;
1023 free_part = part;
1024 break;
1025 }
1026 if (part->header.length > size &&
1027 part->header.length >= min_size) {
1028 size = part->header.length;
1029 free_part = part;
1030 }
1031 }
1032 if (!size)
1033 return -ENOSPC;
1034
1035
1036 new_part = kmalloc(sizeof(*new_part), GFP_KERNEL);
1037 if (!new_part) {
1038 pr_err("%s: kmalloc failed\n", __func__);
1039 return -ENOMEM;
1040 }
1041
1042 new_part->index = free_part->index;
1043 new_part->header.signature = sig;
1044 new_part->header.length = size;
1045 strncpy(new_part->header.name, name, 12);
1046 new_part->header.checksum = nvram_checksum(&new_part->header);
1047
1048 rc = nvram_write_header(new_part);
1049 if (rc <= 0) {
1050 pr_err("%s: nvram_write_header failed (%d)\n", __func__, rc);
1051 kfree(new_part);
1052 return rc;
1053 }
1054 list_add_tail(&new_part->partition, &free_part->partition);
1055
1056
1057 if (free_part->header.length > size) {
1058 free_part->index += size * NVRAM_BLOCK_LEN;
1059 free_part->header.length -= size;
1060 free_part->header.checksum = nvram_checksum(&free_part->header);
1061 rc = nvram_write_header(free_part);
1062 if (rc <= 0) {
1063 pr_err("%s: nvram_write_header failed (%d)\n",
1064 __func__, rc);
1065 return rc;
1066 }
1067 } else {
1068 list_del(&free_part->partition);
1069 kfree(free_part);
1070 }
1071
1072
1073 for (tmp_index = new_part->index + NVRAM_HEADER_LEN;
1074 tmp_index < ((size - 1) * NVRAM_BLOCK_LEN);
1075 tmp_index += NVRAM_BLOCK_LEN) {
1076 rc = ppc_md.nvram_write(nv_init_vals, NVRAM_BLOCK_LEN, &tmp_index);
1077 if (rc <= 0) {
1078 pr_err("%s: nvram_write failed (%d)\n",
1079 __func__, rc);
1080 return rc;
1081 }
1082 }
1083
1084 return new_part->index + NVRAM_HEADER_LEN;
1085}
1086
1087
1088
1089
1090
1091
1092
1093int nvram_get_partition_size(loff_t data_index)
1094{
1095 struct nvram_partition *part;
1096
1097 list_for_each_entry(part, &nvram_partitions, partition) {
1098 if (part->index + NVRAM_HEADER_LEN == data_index)
1099 return (part->header.length - 1) * NVRAM_BLOCK_LEN;
1100 }
1101 return -1;
1102}
1103
1104
1105
1106
1107
1108
1109
1110
1111loff_t nvram_find_partition(const char *name, int sig, int *out_size)
1112{
1113 struct nvram_partition *p;
1114
1115 list_for_each_entry(p, &nvram_partitions, partition) {
1116 if (p->header.signature == sig &&
1117 (!name || !strncmp(p->header.name, name, 12))) {
1118 if (out_size)
1119 *out_size = (p->header.length - 1) *
1120 NVRAM_BLOCK_LEN;
1121 return p->index + NVRAM_HEADER_LEN;
1122 }
1123 }
1124 return 0;
1125}
1126
1127int __init nvram_scan_partitions(void)
1128{
1129 loff_t cur_index = 0;
1130 struct nvram_header phead;
1131 struct nvram_partition * tmp_part;
1132 unsigned char c_sum;
1133 char * header;
1134 int total_size;
1135 int err;
1136
1137 if (ppc_md.nvram_size == NULL || ppc_md.nvram_size() <= 0)
1138 return -ENODEV;
1139 total_size = ppc_md.nvram_size();
1140
1141 header = kmalloc(NVRAM_HEADER_LEN, GFP_KERNEL);
1142 if (!header) {
1143 printk(KERN_ERR "nvram_scan_partitions: Failed kmalloc\n");
1144 return -ENOMEM;
1145 }
1146
1147 while (cur_index < total_size) {
1148
1149 err = ppc_md.nvram_read(header, NVRAM_HEADER_LEN, &cur_index);
1150 if (err != NVRAM_HEADER_LEN) {
1151 printk(KERN_ERR "nvram_scan_partitions: Error parsing "
1152 "nvram partitions\n");
1153 goto out;
1154 }
1155
1156 cur_index -= NVRAM_HEADER_LEN;
1157
1158 memcpy(&phead, header, NVRAM_HEADER_LEN);
1159
1160 phead.length = be16_to_cpu(phead.length);
1161
1162 err = 0;
1163 c_sum = nvram_checksum(&phead);
1164 if (c_sum != phead.checksum) {
1165 printk(KERN_WARNING "WARNING: nvram partition checksum"
1166 " was %02x, should be %02x!\n",
1167 phead.checksum, c_sum);
1168 printk(KERN_WARNING "Terminating nvram partition scan\n");
1169 goto out;
1170 }
1171 if (!phead.length) {
1172 printk(KERN_WARNING "WARNING: nvram corruption "
1173 "detected: 0-length partition\n");
1174 goto out;
1175 }
1176 tmp_part = kmalloc(sizeof(struct nvram_partition), GFP_KERNEL);
1177 err = -ENOMEM;
1178 if (!tmp_part) {
1179 printk(KERN_ERR "nvram_scan_partitions: kmalloc failed\n");
1180 goto out;
1181 }
1182
1183 memcpy(&tmp_part->header, &phead, NVRAM_HEADER_LEN);
1184 tmp_part->index = cur_index;
1185 list_add_tail(&tmp_part->partition, &nvram_partitions);
1186
1187 cur_index += phead.length * NVRAM_BLOCK_LEN;
1188 }
1189 err = 0;
1190
1191#ifdef DEBUG_NVRAM
1192 nvram_print_partitions("NVRAM Partitions");
1193#endif
1194
1195 out:
1196 kfree(header);
1197 return err;
1198}
1199
1200static int __init nvram_init(void)
1201{
1202 int rc;
1203
1204 BUILD_BUG_ON(NVRAM_BLOCK_LEN != 16);
1205
1206 if (ppc_md.nvram_size == NULL || ppc_md.nvram_size() <= 0)
1207 return -ENODEV;
1208
1209 rc = misc_register(&nvram_dev);
1210 if (rc != 0) {
1211 printk(KERN_ERR "nvram_init: failed to register device\n");
1212 return rc;
1213 }
1214
1215 return rc;
1216}
1217device_initcall(nvram_init);
1218