linux/arch/powerpc/kernel/nvram_64.c
<<
>>
Prefs
   1/*
   2 *  c 2001 PPC 64 Team, IBM Corp
   3 *
   4 *      This program is free software; you can redistribute it and/or
   5 *      modify it under the terms of the GNU General Public License
   6 *      as published by the Free Software Foundation; either version
   7 *      2 of the License, or (at your option) any later version.
   8 *
   9 * /dev/nvram driver for PPC64
  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/* If change this size, then change the size of NVNAME_LEN */
  37struct nvram_header {
  38        unsigned char signature;
  39        unsigned char checksum;
  40        unsigned short length;
  41        /* Terminating null required only for names < 12 chars. */
  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 * For capturing and compressing an oops or panic report...
  88
  89 * big_oops_buf[] holds the uncompressed text we're capturing.
  90 *
  91 * oops_buf[] holds the compressed text, preceded by a oops header.
  92 * oops header has u16 holding the version of oops header (to differentiate
  93 * between old and new format header) followed by u16 holding the length of
  94 * the compressed* text (*Or uncompressed, if compression fails.) and u64
  95 * holding the timestamp. oops_buf[] gets written to NVRAM.
  96 *
  97 * oops_log_info points to the header. oops_data points to the compressed text.
  98 *
  99 * +- oops_buf
 100 * |                                   +- oops_data
 101 * v                                   v
 102 * +-----------+-----------+-----------+------------------------+
 103 * | version   | length    | timestamp | text                   |
 104 * | (2 bytes) | (2 bytes) | (8 bytes) | (oops_data_sz bytes)   |
 105 * +-----------+-----------+-----------+------------------------+
 106 * ^
 107 * +- oops_log_info
 108 *
 109 * We preallocate these buffers during init to avoid kmalloc during oops/panic.
 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/* Compression parameters */
 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/* nvram_write_os_partition
 156 *
 157 * We need to buffer the error logs into nvram to ensure that we have
 158 * the failure information to decode.  If we have a severe error there
 159 * is no way to guarantee that the OS or the machine is in a state to
 160 * get back to user land and write the error to disk.  For example if
 161 * the SCSI device driver causes a Machine Check by writing to a bad
 162 * IO address, there is no way of guaranteeing that the device driver
 163 * is in any state that is would also be able to write the error data
 164 * captured to disk, thus we buffer it in NVRAM for analysis on the
 165 * next boot.
 166 *
 167 * In NVRAM the partition containing the error log buffer will looks like:
 168 * Header (in bytes):
 169 * +-----------+----------+--------+------------+------------------+
 170 * | signature | checksum | length | name       | data             |
 171 * |0          |1         |2      3|4         15|16        length-1|
 172 * +-----------+----------+--------+------------+------------------+
 173 *
 174 * The 'data' section would look like (in bytes):
 175 * +--------------+------------+-----------------------------------+
 176 * | event_logged | sequence # | error log                         |
 177 * |0            3|4          7|8                  error_log_size-1|
 178 * +--------------+------------+-----------------------------------+
 179 *
 180 * event_logged: 0 if event has not been logged to syslog, 1 if it has
 181 * sequence #: The unique sequence # for each event. (until it wraps)
 182 * error log: The error log from event_scan
 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/* nvram_read_partition
 220 *
 221 * Reads nvram partition for at most 'length'
 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/* nvram_init_os_partition
 262 *
 263 * This sets up a partition with an "OS" signature.
 264 *
 265 * The general strategy is the following:
 266 * 1.) If a partition with the indicated name already exists...
 267 *      - If it's large enough, use it.
 268 *      - Otherwise, recycle it and keep going.
 269 * 2.) Search for a free partition that is large enough.
 270 * 3.) If there's not a free partition large enough, recycle any obsolete
 271 * OS partitions and try again.
 272 * 4.) Will first try getting a chunk that will satisfy the requested size.
 273 * 5.) If a chunk of the requested size cannot be allocated, then try finding
 274 * a chunk that will satisfy the minum needed.
 275 *
 276 * Returns 0 on success, else -1.
 277 */
 278int __init nvram_init_os_partition(struct nvram_os_partition *part)
 279{
 280        loff_t p;
 281        int size;
 282
 283        /* Look for ours */
 284        p = nvram_find_partition(part->name, NVRAM_SIG_OS, &size);
 285
 286        /* Found one but too small, remove it */
 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        /* Create one if we didn't find */
 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/* Derived from logfs_compress() */
 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/* Compress the text from big_oops_buf into oops_buf. */
 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        /* Reset the iterator to start reading partitions again */
 377        read_type = -1;
 378        return 0;
 379}
 380
 381/**
 382 * nvram_pstore_write - pstore write callback for nvram
 383 * @record:             pstore record to write, with @id to be set
 384 *
 385 * Called by pstore_dump() when an oops or panic report is logged in the
 386 * printk buffer.
 387 * Returns 0 on successful write.
 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        /* part 1 has the recent messages from printk buffer */
 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 * Reads the oops/panic report, rtas, of-config and common partition.
 422 * Returns the length of the data we read from each partition.
 423 * Returns 0 if we've been called before.
 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                        /* Old format oops header had 2-byte record size */
 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                /* Print error only when pstore.backend == nvram */
 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         * Figure compression (preceded by elimination of each line's <n>
 612         * severity prefix) will reduce the oops/panic report to at most
 613         * 45% of its original size.
 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 * This is our kmsg_dump callback, called after an oops or panic report
 644 * has been written to the printk buffer.  We want to capture as much
 645 * of the printk buffer as possible.  First, capture as much as we can
 646 * that we think will compress sufficiently to fit in the lnx,oops-log
 647 * partition.  If that's too much, go back and capture uncompressed text.
 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                /* These are almost always orderly shutdowns. */
 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                        /* Panic report already captured. */
 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; /* assume 6 shorts */
 748        c_sum = p->signature + p->length + sp[0] + sp[1] + sp[2] + sp[3] + sp[4] + sp[5];
 749
 750        /* The sum may have spilled into the 3rd byte.  Fold it back. */
 751        c_sum = ((c_sum & 0xffff) + (c_sum >> 16)) & 0xffff;
 752        /* The sum cannot exceed 2 bytes.  Fold it into a checksum */
 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 * Per the criteria passed via nvram_remove_partition(), should this
 760 * partition be removed?  1=remove, 0=keep
 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 * nvram_remove_partition - Remove one or more partitions in nvram
 782 * @name: name of the partition to remove, or NULL for a
 783 *        signature only match
 784 * @sig: signature of the partition(s) to remove
 785 * @exceptions: When removing all partitions with a matching signature,
 786 *        leave these alone.
 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                /* Make partition a free partition */
 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        /* Merge contiguous ones */
 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 * nvram_create_partition - Create a partition in nvram
 836 * @name: name of the partition to create
 837 * @sig: signature of the partition to create
 838 * @req_size: size of data to allocate in bytes
 839 * @min_size: minimum acceptable size (0 means req_size)
 840 *
 841 * Returns a negative error code or a positive nvram index
 842 * of the beginning of the data area of the newly created
 843 * partition. If you provided a min_size smaller than req_size
 844 * you need to query for the actual size yourself after the
 845 * call using nvram_partition_get_size().
 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        /* Convert sizes from bytes to blocks */
 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        /* If no minimum size specified, make it the same as the
 865         * requested size
 866         */
 867        if (min_size == 0)
 868                min_size = req_size;
 869        if (min_size > req_size)
 870                return -EINVAL;
 871
 872        /* Now add one block to each for the header */
 873        req_size += 1;
 874        min_size += 1;
 875
 876        /* Find a free partition that will give us the maximum needed size 
 877           If can't find one that will give us the minimum size needed */
 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        /* Create our OS partition */
 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        /* Adjust or remove the partition we stole the space from */
 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        /* Clear the new partition */
 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 * nvram_get_partition_size - Get the data size of an nvram partition
 950 * @data_index: This is the offset of the start of the data of
 951 *              the partition. The same value that is returned by
 952 *              nvram_create_partition().
 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 * nvram_find_partition - Find an nvram partition by signature and name
 968 * @name: Name of the partition or NULL for any name
 969 * @sig: Signature to test against
 970 * @out_size: if non-NULL, returns the size of the data part of the partition
 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; /* nvram_read will advance us */
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