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