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