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