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 rc = pstore_register(&nvram_pstore_info);
567 if (rc && (rc != -EPERM))
568
569 pr_err("nvram: pstore_register() failed, returned %d. "
570 "Defaults to kmsg_dump\n", rc);
571
572 return rc;
573}
574#else
575static int nvram_pstore_init(void)
576{
577 return -1;
578}
579#endif
580
581void __init nvram_init_oops_partition(int rtas_partition_exists)
582{
583 int rc;
584
585 rc = nvram_init_os_partition(&oops_log_partition);
586 if (rc != 0) {
587#ifdef CONFIG_PPC_PSERIES
588 if (!rtas_partition_exists) {
589 pr_err("nvram: Failed to initialize oops partition!");
590 return;
591 }
592 pr_notice("nvram: Using %s partition to log both"
593 " RTAS errors and oops/panic reports\n",
594 rtas_log_partition.name);
595 memcpy(&oops_log_partition, &rtas_log_partition,
596 sizeof(rtas_log_partition));
597#else
598 pr_err("nvram: Failed to initialize oops partition!");
599 return;
600#endif
601 }
602 oops_buf = kmalloc(oops_log_partition.size, GFP_KERNEL);
603 if (!oops_buf) {
604 pr_err("nvram: No memory for %s partition\n",
605 oops_log_partition.name);
606 return;
607 }
608 oops_data = oops_buf + sizeof(struct oops_log_info);
609 oops_data_sz = oops_log_partition.size - sizeof(struct oops_log_info);
610
611 rc = nvram_pstore_init();
612
613 if (!rc)
614 return;
615
616
617
618
619
620
621 big_oops_buf_sz = (oops_data_sz * 100) / 45;
622 big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
623 if (big_oops_buf) {
624 stream.workspace = kmalloc(zlib_deflate_workspacesize(
625 WINDOW_BITS, MEM_LEVEL), GFP_KERNEL);
626 if (!stream.workspace) {
627 pr_err("nvram: No memory for compression workspace; "
628 "skipping compression of %s partition data\n",
629 oops_log_partition.name);
630 kfree(big_oops_buf);
631 big_oops_buf = NULL;
632 }
633 } else {
634 pr_err("No memory for uncompressed %s data; "
635 "skipping compression\n", oops_log_partition.name);
636 stream.workspace = NULL;
637 }
638
639 rc = kmsg_dump_register(&nvram_kmsg_dumper);
640 if (rc != 0) {
641 pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc);
642 kfree(oops_buf);
643 kfree(big_oops_buf);
644 kfree(stream.workspace);
645 }
646}
647
648
649
650
651
652
653
654
655static void oops_to_nvram(struct kmsg_dumper *dumper,
656 enum kmsg_dump_reason reason)
657{
658 struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
659 static unsigned int oops_count = 0;
660 static struct kmsg_dump_iter iter;
661 static bool panicking = false;
662 static DEFINE_SPINLOCK(lock);
663 unsigned long flags;
664 size_t text_len;
665 unsigned int err_type = ERR_TYPE_KERNEL_PANIC_GZ;
666 int rc = -1;
667
668 switch (reason) {
669 case KMSG_DUMP_RESTART:
670 case KMSG_DUMP_HALT:
671 case KMSG_DUMP_POWEROFF:
672
673 return;
674 case KMSG_DUMP_OOPS:
675 break;
676 case KMSG_DUMP_PANIC:
677 panicking = true;
678 break;
679 case KMSG_DUMP_EMERG:
680 if (panicking)
681
682 return;
683 break;
684 default:
685 pr_err("%s: ignoring unrecognized KMSG_DUMP_* reason %d\n",
686 __func__, (int) reason);
687 return;
688 }
689
690 if (clobbering_unread_rtas_event())
691 return;
692
693 if (!spin_trylock_irqsave(&lock, flags))
694 return;
695
696 if (big_oops_buf) {
697 kmsg_dump_rewind(&iter);
698 kmsg_dump_get_buffer(&iter, 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(&iter);
704 kmsg_dump_get_buffer(&iter, 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(req_size, NVRAM_BLOCK_LEN) / NVRAM_BLOCK_LEN;
998 min_size = ALIGN(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