cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

opal-flash.c (13363B)


      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 */
     80enum {
     81	IMAGE_INVALID,
     82	IMAGE_LOADING,
     83	IMAGE_READY,
     84};
     85
     86/* Candidate image data */
     87struct image_data_t {
     88	int		status;
     89	void		*data;
     90	uint32_t	size;
     91};
     92
     93/* Candidate image header */
     94struct image_header_t {
     95	uint16_t	magic;
     96	uint16_t	version;
     97	uint32_t	size;
     98};
     99
    100struct 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
    107struct manage_flash_t {
    108	int status;		/* Return status */
    109};
    110
    111struct update_flash_t {
    112	int status;		/* Return status */
    113};
    114
    115static struct image_header_t	image_header;
    116static struct image_data_t	image_data;
    117static struct validate_flash_t	validate_flash_data;
    118static struct manage_flash_t	manage_flash_data;
    119
    120/* Initialize update_flash_data status to No Operation */
    121static struct update_flash_t	update_flash_data = {
    122	.status = FLASH_NO_OP,
    123};
    124
    125static DEFINE_MUTEX(image_data_mutex);
    126
    127/*
    128 * Validate candidate image
    129 */
    130static 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 */
    150static 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	}
    177out:
    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 */
    190static 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
    217out:
    218	mutex_unlock(&image_data_mutex);
    219	return count;
    220}
    221
    222/*
    223 * Manage flash routine
    224 */
    225static 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 */
    235static 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 */
    252static 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 */
    276static 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
    295flash:
    296	rc = opal_update_flash(addr);
    297
    298invalid_img:
    299	return rc;
    300}
    301
    302/* This gets called just before system reboots */
    303void 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 */
    320static 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 */
    332static 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 */
    366static 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 */
    386static 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 */
    434static 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
    477out:
    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 */
    493static 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
    499static struct kobj_attribute validate_attribute =
    500	__ATTR(validate_flash, 0600, validate_show, validate_store);
    501
    502static struct kobj_attribute manage_attribute =
    503	__ATTR(manage_flash, 0600, manage_show, manage_store);
    504
    505static struct kobj_attribute update_attribute =
    506	__ATTR(update_flash, 0600, update_show, update_store);
    507
    508static 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
    515static const struct attribute_group image_op_attr_group = {
    516	.attrs = image_op_attrs,
    517};
    518
    519void __init opal_flash_update_init(void)
    520{
    521	int ret;
    522
    523	/* Firmware update is not supported by firmware */
    524	if (!opal_check_token(OPAL_FLASH_VALIDATE))
    525		return;
    526
    527	/* Allocate validate image buffer */
    528	validate_flash_data.buf = kzalloc(VALIDATE_BUF_SIZE, GFP_KERNEL);
    529	if (!validate_flash_data.buf) {
    530		pr_err("%s : Failed to allocate memory\n", __func__);
    531		return;
    532	}
    533
    534	/* Make sure /sys/firmware/opal directory is created */
    535	if (!opal_kobj) {
    536		pr_warn("FLASH: opal kobject is not available\n");
    537		goto nokobj;
    538	}
    539
    540	/* Create the sysfs files */
    541	ret = sysfs_create_group(opal_kobj, &image_op_attr_group);
    542	if (ret) {
    543		pr_warn("FLASH: Failed to create sysfs files\n");
    544		goto nokobj;
    545	}
    546
    547	ret = sysfs_create_bin_file(opal_kobj, &image_data_attr);
    548	if (ret) {
    549		pr_warn("FLASH: Failed to create sysfs files\n");
    550		goto nosysfs_file;
    551	}
    552
    553	/* Set default status */
    554	validate_flash_data.status = FLASH_NO_OP;
    555	manage_flash_data.status = FLASH_NO_OP;
    556	update_flash_data.status = FLASH_NO_OP;
    557	image_data.status = IMAGE_INVALID;
    558	return;
    559
    560nosysfs_file:
    561	sysfs_remove_group(opal_kobj, &image_op_attr_group);
    562
    563nokobj:
    564	kfree(validate_flash_data.buf);
    565	return;
    566}