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_SHUTDOWN:
659
660 return;
661 case KMSG_DUMP_OOPS:
662 break;
663 case KMSG_DUMP_PANIC:
664 panicking = true;
665 break;
666 case KMSG_DUMP_EMERG:
667 if (panicking)
668
669 return;
670 break;
671 default:
672 pr_err("%s: ignoring unrecognized KMSG_DUMP_* reason %d\n",
673 __func__, (int) reason);
674 return;
675 }
676
677 if (clobbering_unread_rtas_event())
678 return;
679
680 if (!spin_trylock_irqsave(&lock, flags))
681 return;
682
683 if (big_oops_buf) {
684 kmsg_dump_get_buffer(dumper, false,
685 big_oops_buf, big_oops_buf_sz, &text_len);
686 rc = zip_oops(text_len);
687 }
688 if (rc != 0) {
689 kmsg_dump_rewind(dumper);
690 kmsg_dump_get_buffer(dumper, false,
691 oops_data, oops_data_sz, &text_len);
692 err_type = ERR_TYPE_KERNEL_PANIC;
693 oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
694 oops_hdr->report_length = cpu_to_be16(text_len);
695 oops_hdr->timestamp = cpu_to_be64(ktime_get_real_seconds());
696 }
697
698 (void) nvram_write_os_partition(&oops_log_partition, oops_buf,
699 (int) (sizeof(*oops_hdr) + text_len), err_type,
700 ++oops_count);
701
702 spin_unlock_irqrestore(&lock, flags);
703}
704
705#ifdef DEBUG_NVRAM
706static void __init nvram_print_partitions(char * label)
707{
708 struct nvram_partition * tmp_part;
709
710 printk(KERN_WARNING "--------%s---------\n", label);
711 printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n");
712 list_for_each_entry(tmp_part, &nvram_partitions, partition) {
713 printk(KERN_WARNING "%4d \t%02x\t%02x\t%d\t%12.12s\n",
714 tmp_part->index, tmp_part->header.signature,
715 tmp_part->header.checksum, tmp_part->header.length,
716 tmp_part->header.name);
717 }
718}
719#endif
720
721
722static int __init nvram_write_header(struct nvram_partition * part)
723{
724 loff_t tmp_index;
725 int rc;
726 struct nvram_header phead;
727
728 memcpy(&phead, &part->header, NVRAM_HEADER_LEN);
729 phead.length = cpu_to_be16(phead.length);
730
731 tmp_index = part->index;
732 rc = ppc_md.nvram_write((char *)&phead, NVRAM_HEADER_LEN, &tmp_index);
733
734 return rc;
735}
736
737
738static unsigned char __init nvram_checksum(struct nvram_header *p)
739{
740 unsigned int c_sum, c_sum2;
741 unsigned short *sp = (unsigned short *)p->name;
742 c_sum = p->signature + p->length + sp[0] + sp[1] + sp[2] + sp[3] + sp[4] + sp[5];
743
744
745 c_sum = ((c_sum & 0xffff) + (c_sum >> 16)) & 0xffff;
746
747 c_sum2 = (c_sum >> 8) + (c_sum << 8);
748 c_sum = ((c_sum + c_sum2) >> 8) & 0xff;
749 return c_sum;
750}
751
752
753
754
755
756static int nvram_can_remove_partition(struct nvram_partition *part,
757 const char *name, int sig, const char *exceptions[])
758{
759 if (part->header.signature != sig)
760 return 0;
761 if (name) {
762 if (strncmp(name, part->header.name, 12))
763 return 0;
764 } else if (exceptions) {
765 const char **except;
766 for (except = exceptions; *except; except++) {
767 if (!strncmp(*except, part->header.name, 12))
768 return 0;
769 }
770 }
771 return 1;
772}
773
774
775
776
777
778
779
780
781
782
783int __init nvram_remove_partition(const char *name, int sig,
784 const char *exceptions[])
785{
786 struct nvram_partition *part, *prev, *tmp;
787 int rc;
788
789 list_for_each_entry(part, &nvram_partitions, partition) {
790 if (!nvram_can_remove_partition(part, name, sig, exceptions))
791 continue;
792
793
794 part->header.signature = NVRAM_SIG_FREE;
795 memset(part->header.name, 'w', 12);
796 part->header.checksum = nvram_checksum(&part->header);
797 rc = nvram_write_header(part);
798 if (rc <= 0) {
799 printk(KERN_ERR "nvram_remove_partition: nvram_write failed (%d)\n", rc);
800 return rc;
801 }
802 }
803
804
805 prev = NULL;
806 list_for_each_entry_safe(part, tmp, &nvram_partitions, partition) {
807 if (part->header.signature != NVRAM_SIG_FREE) {
808 prev = NULL;
809 continue;
810 }
811 if (prev) {
812 prev->header.length += part->header.length;
813 prev->header.checksum = nvram_checksum(&prev->header);
814 rc = nvram_write_header(prev);
815 if (rc <= 0) {
816 printk(KERN_ERR "nvram_remove_partition: nvram_write failed (%d)\n", rc);
817 return rc;
818 }
819 list_del(&part->partition);
820 kfree(part);
821 } else
822 prev = part;
823 }
824
825 return 0;
826}
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841loff_t __init nvram_create_partition(const char *name, int sig,
842 int req_size, int min_size)
843{
844 struct nvram_partition *part;
845 struct nvram_partition *new_part;
846 struct nvram_partition *free_part = NULL;
847 static char nv_init_vals[16];
848 loff_t tmp_index;
849 long size = 0;
850 int rc;
851
852 BUILD_BUG_ON(NVRAM_BLOCK_LEN != 16);
853
854
855 req_size = ALIGN(req_size, NVRAM_BLOCK_LEN) / NVRAM_BLOCK_LEN;
856 min_size = ALIGN(min_size, NVRAM_BLOCK_LEN) / NVRAM_BLOCK_LEN;
857
858
859
860
861 if (min_size == 0)
862 min_size = req_size;
863 if (min_size > req_size)
864 return -EINVAL;
865
866
867 req_size += 1;
868 min_size += 1;
869
870
871
872 list_for_each_entry(part, &nvram_partitions, partition) {
873 if (part->header.signature != NVRAM_SIG_FREE)
874 continue;
875
876 if (part->header.length >= req_size) {
877 size = req_size;
878 free_part = part;
879 break;
880 }
881 if (part->header.length > size &&
882 part->header.length >= min_size) {
883 size = part->header.length;
884 free_part = part;
885 }
886 }
887 if (!size)
888 return -ENOSPC;
889
890
891 new_part = kzalloc(sizeof(*new_part), GFP_KERNEL);
892 if (!new_part) {
893 pr_err("%s: kmalloc failed\n", __func__);
894 return -ENOMEM;
895 }
896
897 new_part->index = free_part->index;
898 new_part->header.signature = sig;
899 new_part->header.length = size;
900 memcpy(new_part->header.name, name, strnlen(name, sizeof(new_part->header.name)));
901 new_part->header.checksum = nvram_checksum(&new_part->header);
902
903 rc = nvram_write_header(new_part);
904 if (rc <= 0) {
905 pr_err("%s: nvram_write_header failed (%d)\n", __func__, rc);
906 kfree(new_part);
907 return rc;
908 }
909 list_add_tail(&new_part->partition, &free_part->partition);
910
911
912 if (free_part->header.length > size) {
913 free_part->index += size * NVRAM_BLOCK_LEN;
914 free_part->header.length -= size;
915 free_part->header.checksum = nvram_checksum(&free_part->header);
916 rc = nvram_write_header(free_part);
917 if (rc <= 0) {
918 pr_err("%s: nvram_write_header failed (%d)\n",
919 __func__, rc);
920 return rc;
921 }
922 } else {
923 list_del(&free_part->partition);
924 kfree(free_part);
925 }
926
927
928 for (tmp_index = new_part->index + NVRAM_HEADER_LEN;
929 tmp_index < ((size - 1) * NVRAM_BLOCK_LEN);
930 tmp_index += NVRAM_BLOCK_LEN) {
931 rc = ppc_md.nvram_write(nv_init_vals, NVRAM_BLOCK_LEN, &tmp_index);
932 if (rc <= 0) {
933 pr_err("%s: nvram_write failed (%d)\n",
934 __func__, rc);
935 return rc;
936 }
937 }
938
939 return new_part->index + NVRAM_HEADER_LEN;
940}
941
942
943
944
945
946
947
948int nvram_get_partition_size(loff_t data_index)
949{
950 struct nvram_partition *part;
951
952 list_for_each_entry(part, &nvram_partitions, partition) {
953 if (part->index + NVRAM_HEADER_LEN == data_index)
954 return (part->header.length - 1) * NVRAM_BLOCK_LEN;
955 }
956 return -1;
957}
958
959
960
961
962
963
964
965
966loff_t nvram_find_partition(const char *name, int sig, int *out_size)
967{
968 struct nvram_partition *p;
969
970 list_for_each_entry(p, &nvram_partitions, partition) {
971 if (p->header.signature == sig &&
972 (!name || !strncmp(p->header.name, name, 12))) {
973 if (out_size)
974 *out_size = (p->header.length - 1) *
975 NVRAM_BLOCK_LEN;
976 return p->index + NVRAM_HEADER_LEN;
977 }
978 }
979 return 0;
980}
981
982int __init nvram_scan_partitions(void)
983{
984 loff_t cur_index = 0;
985 struct nvram_header phead;
986 struct nvram_partition * tmp_part;
987 unsigned char c_sum;
988 char * header;
989 int total_size;
990 int err;
991
992 if (ppc_md.nvram_size == NULL || ppc_md.nvram_size() <= 0)
993 return -ENODEV;
994 total_size = ppc_md.nvram_size();
995
996 header = kmalloc(NVRAM_HEADER_LEN, GFP_KERNEL);
997 if (!header) {
998 printk(KERN_ERR "nvram_scan_partitions: Failed kmalloc\n");
999 return -ENOMEM;
1000 }
1001
1002 while (cur_index < total_size) {
1003
1004 err = ppc_md.nvram_read(header, NVRAM_HEADER_LEN, &cur_index);
1005 if (err != NVRAM_HEADER_LEN) {
1006 printk(KERN_ERR "nvram_scan_partitions: Error parsing "
1007 "nvram partitions\n");
1008 goto out;
1009 }
1010
1011 cur_index -= NVRAM_HEADER_LEN;
1012
1013 memcpy(&phead, header, NVRAM_HEADER_LEN);
1014
1015 phead.length = be16_to_cpu(phead.length);
1016
1017 err = 0;
1018 c_sum = nvram_checksum(&phead);
1019 if (c_sum != phead.checksum) {
1020 printk(KERN_WARNING "WARNING: nvram partition checksum"
1021 " was %02x, should be %02x!\n",
1022 phead.checksum, c_sum);
1023 printk(KERN_WARNING "Terminating nvram partition scan\n");
1024 goto out;
1025 }
1026 if (!phead.length) {
1027 printk(KERN_WARNING "WARNING: nvram corruption "
1028 "detected: 0-length partition\n");
1029 goto out;
1030 }
1031 tmp_part = kmalloc(sizeof(*tmp_part), GFP_KERNEL);
1032 err = -ENOMEM;
1033 if (!tmp_part) {
1034 printk(KERN_ERR "nvram_scan_partitions: kmalloc failed\n");
1035 goto out;
1036 }
1037
1038 memcpy(&tmp_part->header, &phead, NVRAM_HEADER_LEN);
1039 tmp_part->index = cur_index;
1040 list_add_tail(&tmp_part->partition, &nvram_partitions);
1041
1042 cur_index += phead.length * NVRAM_BLOCK_LEN;
1043 }
1044 err = 0;
1045
1046#ifdef DEBUG_NVRAM
1047 nvram_print_partitions("NVRAM Partitions");
1048#endif
1049
1050 out:
1051 kfree(header);
1052 return err;
1053}
1054