0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/types.h>
0009 #include <linux/errno.h>
0010 #include <linux/fs.h>
0011 #include <linux/miscdevice.h>
0012 #include <linux/fcntl.h>
0013 #include <linux/nvram.h>
0014 #include <linux/init.h>
0015 #include <linux/slab.h>
0016 #include <linux/spinlock.h>
0017 #include <linux/kmsg_dump.h>
0018 #include <linux/pagemap.h>
0019 #include <linux/pstore.h>
0020 #include <linux/zlib.h>
0021 #include <linux/uaccess.h>
0022 #include <linux/of.h>
0023 #include <asm/nvram.h>
0024 #include <asm/rtas.h>
0025 #include <asm/machdep.h>
0026
0027 #undef DEBUG_NVRAM
0028
0029 #define NVRAM_HEADER_LEN sizeof(struct nvram_header)
0030 #define NVRAM_BLOCK_LEN NVRAM_HEADER_LEN
0031
0032
0033 struct nvram_header {
0034 unsigned char signature;
0035 unsigned char checksum;
0036 unsigned short length;
0037
0038 char name[12];
0039 };
0040
0041 struct nvram_partition {
0042 struct list_head partition;
0043 struct nvram_header header;
0044 unsigned int index;
0045 };
0046
0047 static LIST_HEAD(nvram_partitions);
0048
0049 #ifdef CONFIG_PPC_PSERIES
0050 struct nvram_os_partition rtas_log_partition = {
0051 .name = "ibm,rtas-log",
0052 .req_size = 2079,
0053 .min_size = 1055,
0054 .index = -1,
0055 .os_partition = true
0056 };
0057 #endif
0058
0059 struct nvram_os_partition oops_log_partition = {
0060 .name = "lnx,oops-log",
0061 .req_size = 4000,
0062 .min_size = 2000,
0063 .index = -1,
0064 .os_partition = true
0065 };
0066
0067 static const char *nvram_os_partitions[] = {
0068 #ifdef CONFIG_PPC_PSERIES
0069 "ibm,rtas-log",
0070 #endif
0071 "lnx,oops-log",
0072 NULL
0073 };
0074
0075 static void oops_to_nvram(struct kmsg_dumper *dumper,
0076 enum kmsg_dump_reason reason);
0077
0078 static struct kmsg_dumper nvram_kmsg_dumper = {
0079 .dump = oops_to_nvram
0080 };
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107 static size_t big_oops_buf_sz;
0108 static char *big_oops_buf, *oops_buf;
0109 static char *oops_data;
0110 static size_t oops_data_sz;
0111
0112
0113 #define COMPR_LEVEL 6
0114 #define WINDOW_BITS 12
0115 #define MEM_LEVEL 4
0116 static struct z_stream_s stream;
0117
0118 #ifdef CONFIG_PSTORE
0119 #ifdef CONFIG_PPC_POWERNV
0120 static struct nvram_os_partition skiboot_partition = {
0121 .name = "ibm,skiboot",
0122 .index = -1,
0123 .os_partition = false
0124 };
0125 #endif
0126
0127 #ifdef CONFIG_PPC_PSERIES
0128 static struct nvram_os_partition of_config_partition = {
0129 .name = "of-config",
0130 .index = -1,
0131 .os_partition = false
0132 };
0133 #endif
0134
0135 static struct nvram_os_partition common_partition = {
0136 .name = "common",
0137 .index = -1,
0138 .os_partition = false
0139 };
0140
0141 static enum pstore_type_id nvram_type_ids[] = {
0142 PSTORE_TYPE_DMESG,
0143 PSTORE_TYPE_PPC_COMMON,
0144 -1,
0145 -1,
0146 -1
0147 };
0148 static int read_type;
0149 #endif
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180 int nvram_write_os_partition(struct nvram_os_partition *part,
0181 char *buff, int length,
0182 unsigned int err_type,
0183 unsigned int error_log_cnt)
0184 {
0185 int rc;
0186 loff_t tmp_index;
0187 struct err_log_info info;
0188
0189 if (part->index == -1)
0190 return -ESPIPE;
0191
0192 if (length > part->size)
0193 length = part->size;
0194
0195 info.error_type = cpu_to_be32(err_type);
0196 info.seq_num = cpu_to_be32(error_log_cnt);
0197
0198 tmp_index = part->index;
0199
0200 rc = ppc_md.nvram_write((char *)&info, sizeof(info), &tmp_index);
0201 if (rc <= 0) {
0202 pr_err("%s: Failed nvram_write (%d)\n", __func__, rc);
0203 return rc;
0204 }
0205
0206 rc = ppc_md.nvram_write(buff, length, &tmp_index);
0207 if (rc <= 0) {
0208 pr_err("%s: Failed nvram_write (%d)\n", __func__, rc);
0209 return rc;
0210 }
0211
0212 return 0;
0213 }
0214
0215
0216
0217
0218
0219 int nvram_read_partition(struct nvram_os_partition *part, char *buff,
0220 int length, unsigned int *err_type,
0221 unsigned int *error_log_cnt)
0222 {
0223 int rc;
0224 loff_t tmp_index;
0225 struct err_log_info info;
0226
0227 if (part->index == -1)
0228 return -1;
0229
0230 if (length > part->size)
0231 length = part->size;
0232
0233 tmp_index = part->index;
0234
0235 if (part->os_partition) {
0236 rc = ppc_md.nvram_read((char *)&info, sizeof(info), &tmp_index);
0237 if (rc <= 0) {
0238 pr_err("%s: Failed nvram_read (%d)\n", __func__, rc);
0239 return rc;
0240 }
0241 }
0242
0243 rc = ppc_md.nvram_read(buff, length, &tmp_index);
0244 if (rc <= 0) {
0245 pr_err("%s: Failed nvram_read (%d)\n", __func__, rc);
0246 return rc;
0247 }
0248
0249 if (part->os_partition) {
0250 *error_log_cnt = be32_to_cpu(info.seq_num);
0251 *err_type = be32_to_cpu(info.error_type);
0252 }
0253
0254 return 0;
0255 }
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274 int __init nvram_init_os_partition(struct nvram_os_partition *part)
0275 {
0276 loff_t p;
0277 int size;
0278
0279
0280 p = nvram_find_partition(part->name, NVRAM_SIG_OS, &size);
0281
0282
0283 if (p && size < part->min_size) {
0284 pr_info("nvram: Found too small %s partition,"
0285 " removing it...\n", part->name);
0286 nvram_remove_partition(part->name, NVRAM_SIG_OS, NULL);
0287 p = 0;
0288 }
0289
0290
0291 if (!p) {
0292 p = nvram_create_partition(part->name, NVRAM_SIG_OS,
0293 part->req_size, part->min_size);
0294 if (p == -ENOSPC) {
0295 pr_info("nvram: No room to create %s partition, "
0296 "deleting any obsolete OS partitions...\n",
0297 part->name);
0298 nvram_remove_partition(NULL, NVRAM_SIG_OS,
0299 nvram_os_partitions);
0300 p = nvram_create_partition(part->name, NVRAM_SIG_OS,
0301 part->req_size, part->min_size);
0302 }
0303 }
0304
0305 if (p <= 0) {
0306 pr_err("nvram: Failed to find or create %s"
0307 " partition, err %d\n", part->name, (int)p);
0308 return -1;
0309 }
0310
0311 part->index = p;
0312 part->size = nvram_get_partition_size(p) - sizeof(struct err_log_info);
0313
0314 return 0;
0315 }
0316
0317
0318 static int nvram_compress(const void *in, void *out, size_t inlen,
0319 size_t outlen)
0320 {
0321 int err, ret;
0322
0323 ret = -EIO;
0324 err = zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS,
0325 MEM_LEVEL, Z_DEFAULT_STRATEGY);
0326 if (err != Z_OK)
0327 goto error;
0328
0329 stream.next_in = in;
0330 stream.avail_in = inlen;
0331 stream.total_in = 0;
0332 stream.next_out = out;
0333 stream.avail_out = outlen;
0334 stream.total_out = 0;
0335
0336 err = zlib_deflate(&stream, Z_FINISH);
0337 if (err != Z_STREAM_END)
0338 goto error;
0339
0340 err = zlib_deflateEnd(&stream);
0341 if (err != Z_OK)
0342 goto error;
0343
0344 if (stream.total_out >= stream.total_in)
0345 goto error;
0346
0347 ret = stream.total_out;
0348 error:
0349 return ret;
0350 }
0351
0352
0353 static int zip_oops(size_t text_len)
0354 {
0355 struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
0356 int zipped_len = nvram_compress(big_oops_buf, oops_data, text_len,
0357 oops_data_sz);
0358 if (zipped_len < 0) {
0359 pr_err("nvram: compression failed; returned %d\n", zipped_len);
0360 pr_err("nvram: logging uncompressed oops/panic report\n");
0361 return -1;
0362 }
0363 oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
0364 oops_hdr->report_length = cpu_to_be16(zipped_len);
0365 oops_hdr->timestamp = cpu_to_be64(ktime_get_real_seconds());
0366 return 0;
0367 }
0368
0369 #ifdef CONFIG_PSTORE
0370 static int nvram_pstore_open(struct pstore_info *psi)
0371 {
0372
0373 read_type = -1;
0374 return 0;
0375 }
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385 static int nvram_pstore_write(struct pstore_record *record)
0386 {
0387 int rc;
0388 unsigned int err_type = ERR_TYPE_KERNEL_PANIC;
0389 struct oops_log_info *oops_hdr = (struct oops_log_info *) oops_buf;
0390
0391
0392 if (record->part > 1 || (record->type != PSTORE_TYPE_DMESG))
0393 return -1;
0394
0395 if (clobbering_unread_rtas_event())
0396 return -1;
0397
0398 oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
0399 oops_hdr->report_length = cpu_to_be16(record->size);
0400 oops_hdr->timestamp = cpu_to_be64(ktime_get_real_seconds());
0401
0402 if (record->compressed)
0403 err_type = ERR_TYPE_KERNEL_PANIC_GZ;
0404
0405 rc = nvram_write_os_partition(&oops_log_partition, oops_buf,
0406 (int) (sizeof(*oops_hdr) + record->size), err_type,
0407 record->count);
0408
0409 if (rc != 0)
0410 return rc;
0411
0412 record->id = record->part;
0413 return 0;
0414 }
0415
0416
0417
0418
0419
0420
0421 static ssize_t nvram_pstore_read(struct pstore_record *record)
0422 {
0423 struct oops_log_info *oops_hdr;
0424 unsigned int err_type, id_no, size = 0;
0425 struct nvram_os_partition *part = NULL;
0426 char *buff = NULL;
0427 int sig = 0;
0428 loff_t p;
0429
0430 read_type++;
0431
0432 switch (nvram_type_ids[read_type]) {
0433 case PSTORE_TYPE_DMESG:
0434 part = &oops_log_partition;
0435 record->type = PSTORE_TYPE_DMESG;
0436 break;
0437 case PSTORE_TYPE_PPC_COMMON:
0438 sig = NVRAM_SIG_SYS;
0439 part = &common_partition;
0440 record->type = PSTORE_TYPE_PPC_COMMON;
0441 record->id = PSTORE_TYPE_PPC_COMMON;
0442 record->time.tv_sec = 0;
0443 record->time.tv_nsec = 0;
0444 break;
0445 #ifdef CONFIG_PPC_PSERIES
0446 case PSTORE_TYPE_PPC_RTAS:
0447 part = &rtas_log_partition;
0448 record->type = PSTORE_TYPE_PPC_RTAS;
0449 record->time.tv_sec = last_rtas_event;
0450 record->time.tv_nsec = 0;
0451 break;
0452 case PSTORE_TYPE_PPC_OF:
0453 sig = NVRAM_SIG_OF;
0454 part = &of_config_partition;
0455 record->type = PSTORE_TYPE_PPC_OF;
0456 record->id = PSTORE_TYPE_PPC_OF;
0457 record->time.tv_sec = 0;
0458 record->time.tv_nsec = 0;
0459 break;
0460 #endif
0461 #ifdef CONFIG_PPC_POWERNV
0462 case PSTORE_TYPE_PPC_OPAL:
0463 sig = NVRAM_SIG_FW;
0464 part = &skiboot_partition;
0465 record->type = PSTORE_TYPE_PPC_OPAL;
0466 record->id = PSTORE_TYPE_PPC_OPAL;
0467 record->time.tv_sec = 0;
0468 record->time.tv_nsec = 0;
0469 break;
0470 #endif
0471 default:
0472 return 0;
0473 }
0474
0475 if (!part->os_partition) {
0476 p = nvram_find_partition(part->name, sig, &size);
0477 if (p <= 0) {
0478 pr_err("nvram: Failed to find partition %s, "
0479 "err %d\n", part->name, (int)p);
0480 return 0;
0481 }
0482 part->index = p;
0483 part->size = size;
0484 }
0485
0486 buff = kmalloc(part->size, GFP_KERNEL);
0487
0488 if (!buff)
0489 return -ENOMEM;
0490
0491 if (nvram_read_partition(part, buff, part->size, &err_type, &id_no)) {
0492 kfree(buff);
0493 return 0;
0494 }
0495
0496 record->count = 0;
0497
0498 if (part->os_partition)
0499 record->id = id_no;
0500
0501 if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) {
0502 size_t length, hdr_size;
0503
0504 oops_hdr = (struct oops_log_info *)buff;
0505 if (be16_to_cpu(oops_hdr->version) < OOPS_HDR_VERSION) {
0506
0507 hdr_size = sizeof(u16);
0508 length = be16_to_cpu(oops_hdr->version);
0509 record->time.tv_sec = 0;
0510 record->time.tv_nsec = 0;
0511 } else {
0512 hdr_size = sizeof(*oops_hdr);
0513 length = be16_to_cpu(oops_hdr->report_length);
0514 record->time.tv_sec = be64_to_cpu(oops_hdr->timestamp);
0515 record->time.tv_nsec = 0;
0516 }
0517 record->buf = kmemdup(buff + hdr_size, length, GFP_KERNEL);
0518 kfree(buff);
0519 if (record->buf == NULL)
0520 return -ENOMEM;
0521
0522 record->ecc_notice_size = 0;
0523 if (err_type == ERR_TYPE_KERNEL_PANIC_GZ)
0524 record->compressed = true;
0525 else
0526 record->compressed = false;
0527 return length;
0528 }
0529
0530 record->buf = buff;
0531 return part->size;
0532 }
0533
0534 static struct pstore_info nvram_pstore_info = {
0535 .owner = THIS_MODULE,
0536 .name = "nvram",
0537 .flags = PSTORE_FLAGS_DMESG,
0538 .open = nvram_pstore_open,
0539 .read = nvram_pstore_read,
0540 .write = nvram_pstore_write,
0541 };
0542
0543 static int __init nvram_pstore_init(void)
0544 {
0545 int rc = 0;
0546
0547 if (machine_is(pseries)) {
0548 nvram_type_ids[2] = PSTORE_TYPE_PPC_RTAS;
0549 nvram_type_ids[3] = PSTORE_TYPE_PPC_OF;
0550 } else
0551 nvram_type_ids[2] = PSTORE_TYPE_PPC_OPAL;
0552
0553 nvram_pstore_info.buf = oops_data;
0554 nvram_pstore_info.bufsize = oops_data_sz;
0555
0556 rc = pstore_register(&nvram_pstore_info);
0557 if (rc && (rc != -EPERM))
0558
0559 pr_err("nvram: pstore_register() failed, returned %d. "
0560 "Defaults to kmsg_dump\n", rc);
0561
0562 return rc;
0563 }
0564 #else
0565 static int __init nvram_pstore_init(void)
0566 {
0567 return -1;
0568 }
0569 #endif
0570
0571 void __init nvram_init_oops_partition(int rtas_partition_exists)
0572 {
0573 int rc;
0574
0575 rc = nvram_init_os_partition(&oops_log_partition);
0576 if (rc != 0) {
0577 #ifdef CONFIG_PPC_PSERIES
0578 if (!rtas_partition_exists) {
0579 pr_err("nvram: Failed to initialize oops partition!");
0580 return;
0581 }
0582 pr_notice("nvram: Using %s partition to log both"
0583 " RTAS errors and oops/panic reports\n",
0584 rtas_log_partition.name);
0585 memcpy(&oops_log_partition, &rtas_log_partition,
0586 sizeof(rtas_log_partition));
0587 #else
0588 pr_err("nvram: Failed to initialize oops partition!");
0589 return;
0590 #endif
0591 }
0592 oops_buf = kmalloc(oops_log_partition.size, GFP_KERNEL);
0593 if (!oops_buf) {
0594 pr_err("nvram: No memory for %s partition\n",
0595 oops_log_partition.name);
0596 return;
0597 }
0598 oops_data = oops_buf + sizeof(struct oops_log_info);
0599 oops_data_sz = oops_log_partition.size - sizeof(struct oops_log_info);
0600
0601 rc = nvram_pstore_init();
0602
0603 if (!rc)
0604 return;
0605
0606
0607
0608
0609
0610
0611 big_oops_buf_sz = (oops_data_sz * 100) / 45;
0612 big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
0613 if (big_oops_buf) {
0614 stream.workspace = kmalloc(zlib_deflate_workspacesize(
0615 WINDOW_BITS, MEM_LEVEL), GFP_KERNEL);
0616 if (!stream.workspace) {
0617 pr_err("nvram: No memory for compression workspace; "
0618 "skipping compression of %s partition data\n",
0619 oops_log_partition.name);
0620 kfree(big_oops_buf);
0621 big_oops_buf = NULL;
0622 }
0623 } else {
0624 pr_err("No memory for uncompressed %s data; "
0625 "skipping compression\n", oops_log_partition.name);
0626 stream.workspace = NULL;
0627 }
0628
0629 rc = kmsg_dump_register(&nvram_kmsg_dumper);
0630 if (rc != 0) {
0631 pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc);
0632 kfree(oops_buf);
0633 kfree(big_oops_buf);
0634 kfree(stream.workspace);
0635 }
0636 }
0637
0638
0639
0640
0641
0642
0643
0644
0645 static void oops_to_nvram(struct kmsg_dumper *dumper,
0646 enum kmsg_dump_reason reason)
0647 {
0648 struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
0649 static unsigned int oops_count = 0;
0650 static struct kmsg_dump_iter iter;
0651 static bool panicking = false;
0652 static DEFINE_SPINLOCK(lock);
0653 unsigned long flags;
0654 size_t text_len;
0655 unsigned int err_type = ERR_TYPE_KERNEL_PANIC_GZ;
0656 int rc = -1;
0657
0658 switch (reason) {
0659 case KMSG_DUMP_SHUTDOWN:
0660
0661 return;
0662 case KMSG_DUMP_OOPS:
0663 break;
0664 case KMSG_DUMP_PANIC:
0665 panicking = true;
0666 break;
0667 case KMSG_DUMP_EMERG:
0668 if (panicking)
0669
0670 return;
0671 break;
0672 default:
0673 pr_err("%s: ignoring unrecognized KMSG_DUMP_* reason %d\n",
0674 __func__, (int) reason);
0675 return;
0676 }
0677
0678 if (clobbering_unread_rtas_event())
0679 return;
0680
0681 if (!spin_trylock_irqsave(&lock, flags))
0682 return;
0683
0684 if (big_oops_buf) {
0685 kmsg_dump_rewind(&iter);
0686 kmsg_dump_get_buffer(&iter, false,
0687 big_oops_buf, big_oops_buf_sz, &text_len);
0688 rc = zip_oops(text_len);
0689 }
0690 if (rc != 0) {
0691 kmsg_dump_rewind(&iter);
0692 kmsg_dump_get_buffer(&iter, false,
0693 oops_data, oops_data_sz, &text_len);
0694 err_type = ERR_TYPE_KERNEL_PANIC;
0695 oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
0696 oops_hdr->report_length = cpu_to_be16(text_len);
0697 oops_hdr->timestamp = cpu_to_be64(ktime_get_real_seconds());
0698 }
0699
0700 (void) nvram_write_os_partition(&oops_log_partition, oops_buf,
0701 (int) (sizeof(*oops_hdr) + text_len), err_type,
0702 ++oops_count);
0703
0704 spin_unlock_irqrestore(&lock, flags);
0705 }
0706
0707 #ifdef DEBUG_NVRAM
0708 static void __init nvram_print_partitions(char * label)
0709 {
0710 struct nvram_partition * tmp_part;
0711
0712 printk(KERN_WARNING "--------%s---------\n", label);
0713 printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n");
0714 list_for_each_entry(tmp_part, &nvram_partitions, partition) {
0715 printk(KERN_WARNING "%4d \t%02x\t%02x\t%d\t%12.12s\n",
0716 tmp_part->index, tmp_part->header.signature,
0717 tmp_part->header.checksum, tmp_part->header.length,
0718 tmp_part->header.name);
0719 }
0720 }
0721 #endif
0722
0723
0724 static int __init nvram_write_header(struct nvram_partition * part)
0725 {
0726 loff_t tmp_index;
0727 int rc;
0728 struct nvram_header phead;
0729
0730 memcpy(&phead, &part->header, NVRAM_HEADER_LEN);
0731 phead.length = cpu_to_be16(phead.length);
0732
0733 tmp_index = part->index;
0734 rc = ppc_md.nvram_write((char *)&phead, NVRAM_HEADER_LEN, &tmp_index);
0735
0736 return rc;
0737 }
0738
0739
0740 static unsigned char __init nvram_checksum(struct nvram_header *p)
0741 {
0742 unsigned int c_sum, c_sum2;
0743 unsigned short *sp = (unsigned short *)p->name;
0744 c_sum = p->signature + p->length + sp[0] + sp[1] + sp[2] + sp[3] + sp[4] + sp[5];
0745
0746
0747 c_sum = ((c_sum & 0xffff) + (c_sum >> 16)) & 0xffff;
0748
0749 c_sum2 = (c_sum >> 8) + (c_sum << 8);
0750 c_sum = ((c_sum + c_sum2) >> 8) & 0xff;
0751 return c_sum;
0752 }
0753
0754
0755
0756
0757
0758 static int __init nvram_can_remove_partition(struct nvram_partition *part,
0759 const char *name, int sig, const char *exceptions[])
0760 {
0761 if (part->header.signature != sig)
0762 return 0;
0763 if (name) {
0764 if (strncmp(name, part->header.name, 12))
0765 return 0;
0766 } else if (exceptions) {
0767 const char **except;
0768 for (except = exceptions; *except; except++) {
0769 if (!strncmp(*except, part->header.name, 12))
0770 return 0;
0771 }
0772 }
0773 return 1;
0774 }
0775
0776
0777
0778
0779
0780
0781
0782
0783
0784
0785 int __init nvram_remove_partition(const char *name, int sig,
0786 const char *exceptions[])
0787 {
0788 struct nvram_partition *part, *prev, *tmp;
0789 int rc;
0790
0791 list_for_each_entry(part, &nvram_partitions, partition) {
0792 if (!nvram_can_remove_partition(part, name, sig, exceptions))
0793 continue;
0794
0795
0796 part->header.signature = NVRAM_SIG_FREE;
0797 memset(part->header.name, 'w', 12);
0798 part->header.checksum = nvram_checksum(&part->header);
0799 rc = nvram_write_header(part);
0800 if (rc <= 0) {
0801 printk(KERN_ERR "nvram_remove_partition: nvram_write failed (%d)\n", rc);
0802 return rc;
0803 }
0804 }
0805
0806
0807 prev = NULL;
0808 list_for_each_entry_safe(part, tmp, &nvram_partitions, partition) {
0809 if (part->header.signature != NVRAM_SIG_FREE) {
0810 prev = NULL;
0811 continue;
0812 }
0813 if (prev) {
0814 prev->header.length += part->header.length;
0815 prev->header.checksum = nvram_checksum(&prev->header);
0816 rc = nvram_write_header(prev);
0817 if (rc <= 0) {
0818 printk(KERN_ERR "nvram_remove_partition: nvram_write failed (%d)\n", rc);
0819 return rc;
0820 }
0821 list_del(&part->partition);
0822 kfree(part);
0823 } else
0824 prev = part;
0825 }
0826
0827 return 0;
0828 }
0829
0830
0831
0832
0833
0834
0835
0836
0837
0838
0839
0840
0841
0842
0843 loff_t __init nvram_create_partition(const char *name, int sig,
0844 int req_size, int min_size)
0845 {
0846 struct nvram_partition *part;
0847 struct nvram_partition *new_part;
0848 struct nvram_partition *free_part = NULL;
0849 static char nv_init_vals[16];
0850 loff_t tmp_index;
0851 long size = 0;
0852 int rc;
0853
0854 BUILD_BUG_ON(NVRAM_BLOCK_LEN != 16);
0855
0856
0857 req_size = ALIGN(req_size, NVRAM_BLOCK_LEN) / NVRAM_BLOCK_LEN;
0858 min_size = ALIGN(min_size, NVRAM_BLOCK_LEN) / NVRAM_BLOCK_LEN;
0859
0860
0861
0862
0863 if (min_size == 0)
0864 min_size = req_size;
0865 if (min_size > req_size)
0866 return -EINVAL;
0867
0868
0869 req_size += 1;
0870 min_size += 1;
0871
0872
0873
0874 list_for_each_entry(part, &nvram_partitions, partition) {
0875 if (part->header.signature != NVRAM_SIG_FREE)
0876 continue;
0877
0878 if (part->header.length >= req_size) {
0879 size = req_size;
0880 free_part = part;
0881 break;
0882 }
0883 if (part->header.length > size &&
0884 part->header.length >= min_size) {
0885 size = part->header.length;
0886 free_part = part;
0887 }
0888 }
0889 if (!size)
0890 return -ENOSPC;
0891
0892
0893 new_part = kzalloc(sizeof(*new_part), GFP_KERNEL);
0894 if (!new_part) {
0895 pr_err("%s: kmalloc failed\n", __func__);
0896 return -ENOMEM;
0897 }
0898
0899 new_part->index = free_part->index;
0900 new_part->header.signature = sig;
0901 new_part->header.length = size;
0902 memcpy(new_part->header.name, name, strnlen(name, sizeof(new_part->header.name)));
0903 new_part->header.checksum = nvram_checksum(&new_part->header);
0904
0905 rc = nvram_write_header(new_part);
0906 if (rc <= 0) {
0907 pr_err("%s: nvram_write_header failed (%d)\n", __func__, rc);
0908 kfree(new_part);
0909 return rc;
0910 }
0911 list_add_tail(&new_part->partition, &free_part->partition);
0912
0913
0914 if (free_part->header.length > size) {
0915 free_part->index += size * NVRAM_BLOCK_LEN;
0916 free_part->header.length -= size;
0917 free_part->header.checksum = nvram_checksum(&free_part->header);
0918 rc = nvram_write_header(free_part);
0919 if (rc <= 0) {
0920 pr_err("%s: nvram_write_header failed (%d)\n",
0921 __func__, rc);
0922 return rc;
0923 }
0924 } else {
0925 list_del(&free_part->partition);
0926 kfree(free_part);
0927 }
0928
0929
0930 for (tmp_index = new_part->index + NVRAM_HEADER_LEN;
0931 tmp_index < ((size - 1) * NVRAM_BLOCK_LEN);
0932 tmp_index += NVRAM_BLOCK_LEN) {
0933 rc = ppc_md.nvram_write(nv_init_vals, NVRAM_BLOCK_LEN, &tmp_index);
0934 if (rc <= 0) {
0935 pr_err("%s: nvram_write failed (%d)\n",
0936 __func__, rc);
0937 return rc;
0938 }
0939 }
0940
0941 return new_part->index + NVRAM_HEADER_LEN;
0942 }
0943
0944
0945
0946
0947
0948
0949
0950 int nvram_get_partition_size(loff_t data_index)
0951 {
0952 struct nvram_partition *part;
0953
0954 list_for_each_entry(part, &nvram_partitions, partition) {
0955 if (part->index + NVRAM_HEADER_LEN == data_index)
0956 return (part->header.length - 1) * NVRAM_BLOCK_LEN;
0957 }
0958 return -1;
0959 }
0960
0961
0962
0963
0964
0965
0966
0967
0968 loff_t nvram_find_partition(const char *name, int sig, int *out_size)
0969 {
0970 struct nvram_partition *p;
0971
0972 list_for_each_entry(p, &nvram_partitions, partition) {
0973 if (p->header.signature == sig &&
0974 (!name || !strncmp(p->header.name, name, 12))) {
0975 if (out_size)
0976 *out_size = (p->header.length - 1) *
0977 NVRAM_BLOCK_LEN;
0978 return p->index + NVRAM_HEADER_LEN;
0979 }
0980 }
0981 return 0;
0982 }
0983
0984 int __init nvram_scan_partitions(void)
0985 {
0986 loff_t cur_index = 0;
0987 struct nvram_header phead;
0988 struct nvram_partition * tmp_part;
0989 unsigned char c_sum;
0990 char * header;
0991 int total_size;
0992 int err;
0993
0994 if (ppc_md.nvram_size == NULL || ppc_md.nvram_size() <= 0)
0995 return -ENODEV;
0996 total_size = ppc_md.nvram_size();
0997
0998 header = kmalloc(NVRAM_HEADER_LEN, GFP_KERNEL);
0999 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 }