linux/arch/powerpc/platforms/powernv/opal-flash.c
<<
>>
Prefs
   1/*
   2 * PowerNV OPAL Firmware Update Interface
   3 *
   4 * Copyright 2013 IBM Corp.
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License
   8 * as published by the Free Software Foundation; either version
   9 * 2 of the License, or (at your option) any later version.
  10 */
  11
  12#define DEBUG
  13
  14#include <linux/kernel.h>
  15#include <linux/reboot.h>
  16#include <linux/init.h>
  17#include <linux/kobject.h>
  18#include <linux/sysfs.h>
  19#include <linux/slab.h>
  20#include <linux/mm.h>
  21#include <linux/vmalloc.h>
  22#include <linux/pagemap.h>
  23#include <linux/delay.h>
  24
  25#include <asm/opal.h>
  26
  27/* FLASH status codes */
  28#define FLASH_NO_OP             -1099   /* No operation initiated by user */
  29#define FLASH_NO_AUTH           -9002   /* Not a service authority partition */
  30
  31/* Validate image status values */
  32#define VALIDATE_IMG_READY      -1001   /* Image ready for validation */
  33#define VALIDATE_IMG_INCOMPLETE -1002   /* User copied < VALIDATE_BUF_SIZE */
  34
  35/* Manage image status values */
  36#define MANAGE_ACTIVE_ERR       -9001   /* Cannot overwrite active img */
  37
  38/* Flash image status values */
  39#define FLASH_IMG_READY         0       /* Img ready for flash on reboot */
  40#define FLASH_INVALID_IMG       -1003   /* Flash image shorter than expected */
  41#define FLASH_IMG_NULL_DATA     -1004   /* Bad data in sg list entry */
  42#define FLASH_IMG_BAD_LEN       -1005   /* Bad length in sg list entry */
  43
  44/* Manage operation tokens */
  45#define FLASH_REJECT_TMP_SIDE   0       /* Reject temporary fw image */
  46#define FLASH_COMMIT_TMP_SIDE   1       /* Commit temporary fw image */
  47
  48/* Update tokens */
  49#define FLASH_UPDATE_CANCEL     0       /* Cancel update request */
  50#define FLASH_UPDATE_INIT       1       /* Initiate update */
  51
  52/* Validate image update result tokens */
  53#define VALIDATE_TMP_UPDATE     0     /* T side will be updated */
  54#define VALIDATE_FLASH_AUTH     1     /* Partition does not have authority */
  55#define VALIDATE_INVALID_IMG    2     /* Candidate image is not valid */
  56#define VALIDATE_CUR_UNKNOWN    3     /* Current fixpack level is unknown */
  57/*
  58 * Current T side will be committed to P side before being replace with new
  59 * image, and the new image is downlevel from current image
  60 */
  61#define VALIDATE_TMP_COMMIT_DL  4
  62/*
  63 * Current T side will be committed to P side before being replaced with new
  64 * image
  65 */
  66#define VALIDATE_TMP_COMMIT     5
  67/*
  68 * T side will be updated with a downlevel image
  69 */
  70#define VALIDATE_TMP_UPDATE_DL  6
  71/*
  72 * The candidate image's release date is later than the system's firmware
  73 * service entitlement date - service warranty period has expired
  74 */
  75#define VALIDATE_OUT_OF_WRNTY   7
  76
  77/* Validate buffer size */
  78#define VALIDATE_BUF_SIZE       4096
  79
  80/* XXX: Assume candidate image size is <= 1GB */
  81#define MAX_IMAGE_SIZE  0x40000000
  82
  83/* Image status */
  84enum {
  85        IMAGE_INVALID,
  86        IMAGE_LOADING,
  87        IMAGE_READY,
  88};
  89
  90/* Candidate image data */
  91struct image_data_t {
  92        int             status;
  93        void            *data;
  94        uint32_t        size;
  95};
  96
  97/* Candidate image header */
  98struct image_header_t {
  99        uint16_t        magic;
 100        uint16_t        version;
 101        uint32_t        size;
 102};
 103
 104struct validate_flash_t {
 105        int             status;         /* Return status */
 106        void            *buf;           /* Candidate image buffer */
 107        uint32_t        buf_size;       /* Image size */
 108        uint32_t        result;         /* Update results token */
 109};
 110
 111struct manage_flash_t {
 112        int status;             /* Return status */
 113};
 114
 115struct update_flash_t {
 116        int status;             /* Return status */
 117};
 118
 119static struct image_header_t    image_header;
 120static struct image_data_t      image_data;
 121static struct validate_flash_t  validate_flash_data;
 122static struct manage_flash_t    manage_flash_data;
 123
 124/* Initialize update_flash_data status to No Operation */
 125static struct update_flash_t    update_flash_data = {
 126        .status = FLASH_NO_OP,
 127};
 128
 129static DEFINE_MUTEX(image_data_mutex);
 130
 131/*
 132 * Validate candidate image
 133 */
 134static inline void opal_flash_validate(void)
 135{
 136        long ret;
 137        void *buf = validate_flash_data.buf;
 138        __be32 size = cpu_to_be32(validate_flash_data.buf_size);
 139        __be32 result;
 140
 141        ret = opal_validate_flash(__pa(buf), &size, &result);
 142
 143        validate_flash_data.status = ret;
 144        validate_flash_data.buf_size = be32_to_cpu(size);
 145        validate_flash_data.result = be32_to_cpu(result);
 146}
 147
 148/*
 149 * Validate output format:
 150 *     validate result token
 151 *     current image version details
 152 *     new image version details
 153 */
 154static ssize_t validate_show(struct kobject *kobj,
 155                             struct kobj_attribute *attr, char *buf)
 156{
 157        struct validate_flash_t *args_buf = &validate_flash_data;
 158        int len;
 159
 160        /* Candidate image is not validated */
 161        if (args_buf->status < VALIDATE_TMP_UPDATE) {
 162                len = sprintf(buf, "%d\n", args_buf->status);
 163                goto out;
 164        }
 165
 166        /* Result token */
 167        len = sprintf(buf, "%d\n", args_buf->result);
 168
 169        /* Current and candidate image version details */
 170        if ((args_buf->result != VALIDATE_TMP_UPDATE) &&
 171            (args_buf->result < VALIDATE_CUR_UNKNOWN))
 172                goto out;
 173
 174        if (args_buf->buf_size > (VALIDATE_BUF_SIZE - len)) {
 175                memcpy(buf + len, args_buf->buf, VALIDATE_BUF_SIZE - len);
 176                len = VALIDATE_BUF_SIZE;
 177        } else {
 178                memcpy(buf + len, args_buf->buf, args_buf->buf_size);
 179                len += args_buf->buf_size;
 180        }
 181out:
 182        /* Set status to default */
 183        args_buf->status = FLASH_NO_OP;
 184        return len;
 185}
 186
 187/*
 188 * Validate candidate firmware image
 189 *
 190 * Note:
 191 *   We are only interested in first 4K bytes of the
 192 *   candidate image.
 193 */
 194static ssize_t validate_store(struct kobject *kobj,
 195                              struct kobj_attribute *attr,
 196                              const char *buf, size_t count)
 197{
 198        struct validate_flash_t *args_buf = &validate_flash_data;
 199
 200        if (buf[0] != '1')
 201                return -EINVAL;
 202
 203        mutex_lock(&image_data_mutex);
 204
 205        if (image_data.status != IMAGE_READY ||
 206            image_data.size < VALIDATE_BUF_SIZE) {
 207                args_buf->result = VALIDATE_INVALID_IMG;
 208                args_buf->status = VALIDATE_IMG_INCOMPLETE;
 209                goto out;
 210        }
 211
 212        /* Copy first 4k bytes of candidate image */
 213        memcpy(args_buf->buf, image_data.data, VALIDATE_BUF_SIZE);
 214
 215        args_buf->status = VALIDATE_IMG_READY;
 216        args_buf->buf_size = VALIDATE_BUF_SIZE;
 217
 218        /* Validate candidate image */
 219        opal_flash_validate();
 220
 221out:
 222        mutex_unlock(&image_data_mutex);
 223        return count;
 224}
 225
 226/*
 227 * Manage flash routine
 228 */
 229static inline void opal_flash_manage(uint8_t op)
 230{
 231        struct manage_flash_t *const args_buf = &manage_flash_data;
 232
 233        args_buf->status = opal_manage_flash(op);
 234}
 235
 236/*
 237 * Show manage flash status
 238 */
 239static ssize_t manage_show(struct kobject *kobj,
 240                           struct kobj_attribute *attr, char *buf)
 241{
 242        struct manage_flash_t *const args_buf = &manage_flash_data;
 243        int rc;
 244
 245        rc = sprintf(buf, "%d\n", args_buf->status);
 246        /* Set status to default*/
 247        args_buf->status = FLASH_NO_OP;
 248        return rc;
 249}
 250
 251/*
 252 * Manage operations:
 253 *   0 - Reject
 254 *   1 - Commit
 255 */
 256static ssize_t manage_store(struct kobject *kobj,
 257                            struct kobj_attribute *attr,
 258                            const char *buf, size_t count)
 259{
 260        uint8_t op;
 261        switch (buf[0]) {
 262        case '0':
 263                op = FLASH_REJECT_TMP_SIDE;
 264                break;
 265        case '1':
 266                op = FLASH_COMMIT_TMP_SIDE;
 267                break;
 268        default:
 269                return -EINVAL;
 270        }
 271
 272        /* commit/reject temporary image */
 273        opal_flash_manage(op);
 274        return count;
 275}
 276
 277/*
 278 * OPAL update flash
 279 */
 280static int opal_flash_update(int op)
 281{
 282        struct opal_sg_list *list;
 283        unsigned long addr;
 284        int64_t rc = OPAL_PARAMETER;
 285
 286        if (op == FLASH_UPDATE_CANCEL) {
 287                pr_alert("FLASH: Image update cancelled\n");
 288                addr = '\0';
 289                goto flash;
 290        }
 291
 292        list = opal_vmalloc_to_sg_list(image_data.data, image_data.size);
 293        if (!list)
 294                goto invalid_img;
 295
 296        /* First entry address */
 297        addr = __pa(list);
 298
 299flash:
 300        rc = opal_update_flash(addr);
 301
 302invalid_img:
 303        return rc;
 304}
 305
 306/* Return CPUs to OPAL before starting FW update */
 307static void flash_return_cpu(void *info)
 308{
 309        int cpu = smp_processor_id();
 310
 311        if (!cpu_online(cpu))
 312                return;
 313
 314        /* Disable IRQ */
 315        hard_irq_disable();
 316
 317        /* Return the CPU to OPAL */
 318        opal_return_cpu();
 319}
 320
 321/* This gets called just before system reboots */
 322void opal_flash_term_callback(void)
 323{
 324        struct cpumask mask;
 325
 326        if (update_flash_data.status != FLASH_IMG_READY)
 327                return;
 328
 329        pr_alert("FLASH: Flashing new firmware\n");
 330        pr_alert("FLASH: Image is %u bytes\n", image_data.size);
 331        pr_alert("FLASH: Performing flash and reboot/shutdown\n");
 332        pr_alert("FLASH: This will take several minutes. Do not power off!\n");
 333
 334        /* Small delay to help getting the above message out */
 335        msleep(500);
 336
 337        /* Return secondary CPUs to firmware */
 338        cpumask_copy(&mask, cpu_online_mask);
 339        cpumask_clear_cpu(smp_processor_id(), &mask);
 340        if (!cpumask_empty(&mask))
 341                smp_call_function_many(&mask,
 342                                       flash_return_cpu, NULL, false);
 343        /* Hard disable interrupts */
 344        hard_irq_disable();
 345}
 346
 347/*
 348 * Show candidate image status
 349 */
 350static ssize_t update_show(struct kobject *kobj,
 351                           struct kobj_attribute *attr, char *buf)
 352{
 353        struct update_flash_t *const args_buf = &update_flash_data;
 354        return sprintf(buf, "%d\n", args_buf->status);
 355}
 356
 357/*
 358 * Set update image flag
 359 *  1 - Flash new image
 360 *  0 - Cancel flash request
 361 */
 362static ssize_t update_store(struct kobject *kobj,
 363                            struct kobj_attribute *attr,
 364                            const char *buf, size_t count)
 365{
 366        struct update_flash_t *const args_buf = &update_flash_data;
 367        int rc = count;
 368
 369        mutex_lock(&image_data_mutex);
 370
 371        switch (buf[0]) {
 372        case '0':
 373                if (args_buf->status == FLASH_IMG_READY)
 374                        opal_flash_update(FLASH_UPDATE_CANCEL);
 375                args_buf->status = FLASH_NO_OP;
 376                break;
 377        case '1':
 378                /* Image is loaded? */
 379                if (image_data.status == IMAGE_READY)
 380                        args_buf->status =
 381                                opal_flash_update(FLASH_UPDATE_INIT);
 382                else
 383                        args_buf->status = FLASH_INVALID_IMG;
 384                break;
 385        default:
 386                rc = -EINVAL;
 387        }
 388
 389        mutex_unlock(&image_data_mutex);
 390        return rc;
 391}
 392
 393/*
 394 * Free image buffer
 395 */
 396static void free_image_buf(void)
 397{
 398        void *addr;
 399        int size;
 400
 401        addr = image_data.data;
 402        size = PAGE_ALIGN(image_data.size);
 403        while (size > 0) {
 404                ClearPageReserved(vmalloc_to_page(addr));
 405                addr += PAGE_SIZE;
 406                size -= PAGE_SIZE;
 407        }
 408        vfree(image_data.data);
 409        image_data.data = NULL;
 410        image_data.status = IMAGE_INVALID;
 411}
 412
 413/*
 414 * Allocate image buffer.
 415 */
 416static int alloc_image_buf(char *buffer, size_t count)
 417{
 418        void *addr;
 419        int size;
 420
 421        if (count < sizeof(struct image_header_t)) {
 422                pr_warn("FLASH: Invalid candidate image\n");
 423                return -EINVAL;
 424        }
 425
 426        memcpy(&image_header, (void *)buffer, sizeof(struct image_header_t));
 427        image_data.size = be32_to_cpu(image_header.size);
 428        pr_debug("FLASH: Candidate image size = %u\n", image_data.size);
 429
 430        if (image_data.size > MAX_IMAGE_SIZE) {
 431                pr_warn("FLASH: Too large image\n");
 432                return -EINVAL;
 433        }
 434        if (image_data.size < VALIDATE_BUF_SIZE) {
 435                pr_warn("FLASH: Image is shorter than expected\n");
 436                return -EINVAL;
 437        }
 438
 439        image_data.data = vzalloc(PAGE_ALIGN(image_data.size));
 440        if (!image_data.data) {
 441                pr_err("%s : Failed to allocate memory\n", __func__);
 442                return -ENOMEM;
 443        }
 444
 445        /* Pin memory */
 446        addr = image_data.data;
 447        size = PAGE_ALIGN(image_data.size);
 448        while (size > 0) {
 449                SetPageReserved(vmalloc_to_page(addr));
 450                addr += PAGE_SIZE;
 451                size -= PAGE_SIZE;
 452        }
 453
 454        image_data.status = IMAGE_LOADING;
 455        return 0;
 456}
 457
 458/*
 459 * Copy candidate image
 460 *
 461 * Parse candidate image header to get total image size
 462 * and pre-allocate required memory.
 463 */
 464static ssize_t image_data_write(struct file *filp, struct kobject *kobj,
 465                                struct bin_attribute *bin_attr,
 466                                char *buffer, loff_t pos, size_t count)
 467{
 468        int rc;
 469
 470        mutex_lock(&image_data_mutex);
 471
 472        /* New image ? */
 473        if (pos == 0) {
 474                /* Free memory, if already allocated */
 475                if (image_data.data)
 476                        free_image_buf();
 477
 478                /* Cancel outstanding image update request */
 479                if (update_flash_data.status == FLASH_IMG_READY)
 480                        opal_flash_update(FLASH_UPDATE_CANCEL);
 481
 482                /* Allocate memory */
 483                rc = alloc_image_buf(buffer, count);
 484                if (rc)
 485                        goto out;
 486        }
 487
 488        if (image_data.status != IMAGE_LOADING) {
 489                rc = -ENOMEM;
 490                goto out;
 491        }
 492
 493        if ((pos + count) > image_data.size) {
 494                rc = -EINVAL;
 495                goto out;
 496        }
 497
 498        memcpy(image_data.data + pos, (void *)buffer, count);
 499        rc = count;
 500
 501        /* Set image status */
 502        if ((pos + count) == image_data.size) {
 503                pr_debug("FLASH: Candidate image loaded....\n");
 504                image_data.status = IMAGE_READY;
 505        }
 506
 507out:
 508        mutex_unlock(&image_data_mutex);
 509        return rc;
 510}
 511
 512/*
 513 * sysfs interface :
 514 *  OPAL uses below sysfs files for code update.
 515 *  We create these files under /sys/firmware/opal.
 516 *
 517 *   image              : Interface to load candidate firmware image
 518 *   validate_flash     : Validate firmware image
 519 *   manage_flash       : Commit/Reject firmware image
 520 *   update_flash       : Flash new firmware image
 521 *
 522 */
 523static struct bin_attribute image_data_attr = {
 524        .attr = {.name = "image", .mode = 0200},
 525        .size = MAX_IMAGE_SIZE, /* Limit image size */
 526        .write = image_data_write,
 527};
 528
 529static struct kobj_attribute validate_attribute =
 530        __ATTR(validate_flash, 0600, validate_show, validate_store);
 531
 532static struct kobj_attribute manage_attribute =
 533        __ATTR(manage_flash, 0600, manage_show, manage_store);
 534
 535static struct kobj_attribute update_attribute =
 536        __ATTR(update_flash, 0600, update_show, update_store);
 537
 538static struct attribute *image_op_attrs[] = {
 539        &validate_attribute.attr,
 540        &manage_attribute.attr,
 541        &update_attribute.attr,
 542        NULL    /* need to NULL terminate the list of attributes */
 543};
 544
 545static struct attribute_group image_op_attr_group = {
 546        .attrs = image_op_attrs,
 547};
 548
 549void __init opal_flash_update_init(void)
 550{
 551        int ret;
 552
 553        /* Allocate validate image buffer */
 554        validate_flash_data.buf = kzalloc(VALIDATE_BUF_SIZE, GFP_KERNEL);
 555        if (!validate_flash_data.buf) {
 556                pr_err("%s : Failed to allocate memory\n", __func__);
 557                return;
 558        }
 559
 560        /* Make sure /sys/firmware/opal directory is created */
 561        if (!opal_kobj) {
 562                pr_warn("FLASH: opal kobject is not available\n");
 563                goto nokobj;
 564        }
 565
 566        /* Create the sysfs files */
 567        ret = sysfs_create_group(opal_kobj, &image_op_attr_group);
 568        if (ret) {
 569                pr_warn("FLASH: Failed to create sysfs files\n");
 570                goto nokobj;
 571        }
 572
 573        ret = sysfs_create_bin_file(opal_kobj, &image_data_attr);
 574        if (ret) {
 575                pr_warn("FLASH: Failed to create sysfs files\n");
 576                goto nosysfs_file;
 577        }
 578
 579        /* Set default status */
 580        validate_flash_data.status = FLASH_NO_OP;
 581        manage_flash_data.status = FLASH_NO_OP;
 582        update_flash_data.status = FLASH_NO_OP;
 583        image_data.status = IMAGE_INVALID;
 584        return;
 585
 586nosysfs_file:
 587        sysfs_remove_group(opal_kobj, &image_op_attr_group);
 588
 589nokobj:
 590        kfree(validate_flash_data.buf);
 591        return;
 592}
 593