root/arch/powerpc/platforms/powernv/opal-flash.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. opal_flash_validate
  2. validate_show
  3. validate_store
  4. opal_flash_manage
  5. manage_show
  6. manage_store
  7. opal_flash_update
  8. opal_flash_update_print_message
  9. update_show
  10. update_store
  11. free_image_buf
  12. alloc_image_buf
  13. image_data_write
  14. opal_flash_update_init

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

/* [<][>][^][v][top][bottom][index][help] */