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

fw-download.c (12396B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Greybus Firmware Download Protocol Driver.
      4 *
      5 * Copyright 2016 Google Inc.
      6 * Copyright 2016 Linaro Ltd.
      7 */
      8
      9#include <linux/firmware.h>
     10#include <linux/jiffies.h>
     11#include <linux/mutex.h>
     12#include <linux/workqueue.h>
     13#include <linux/greybus.h>
     14#include "firmware.h"
     15
     16/* Estimated minimum buffer size, actual size can be smaller than this */
     17#define MIN_FETCH_SIZE		512
     18/* Timeout, in jiffies, within which fetch or release firmware must be called */
     19#define NEXT_REQ_TIMEOUT_J	msecs_to_jiffies(1000)
     20
     21struct fw_request {
     22	u8			firmware_id;
     23	bool			disabled;
     24	bool			timedout;
     25	char			name[FW_NAME_SIZE];
     26	const struct firmware	*fw;
     27	struct list_head	node;
     28
     29	struct delayed_work	dwork;
     30	/* Timeout, in jiffies, within which the firmware shall download */
     31	unsigned long		release_timeout_j;
     32	struct kref		kref;
     33	struct fw_download	*fw_download;
     34};
     35
     36struct fw_download {
     37	struct device		*parent;
     38	struct gb_connection	*connection;
     39	struct list_head	fw_requests;
     40	struct ida		id_map;
     41	struct mutex		mutex;
     42};
     43
     44static void fw_req_release(struct kref *kref)
     45{
     46	struct fw_request *fw_req = container_of(kref, struct fw_request, kref);
     47
     48	dev_dbg(fw_req->fw_download->parent, "firmware %s released\n",
     49		fw_req->name);
     50
     51	release_firmware(fw_req->fw);
     52
     53	/*
     54	 * The request timed out and the module may send a fetch-fw or
     55	 * release-fw request later. Lets block the id we allocated for this
     56	 * request, so that the AP doesn't refer to a later fw-request (with
     57	 * same firmware_id) for the old timedout fw-request.
     58	 *
     59	 * NOTE:
     60	 *
     61	 * This also means that after 255 timeouts we will fail to service new
     62	 * firmware downloads. But what else can we do in that case anyway? Lets
     63	 * just hope that it never happens.
     64	 */
     65	if (!fw_req->timedout)
     66		ida_simple_remove(&fw_req->fw_download->id_map,
     67				  fw_req->firmware_id);
     68
     69	kfree(fw_req);
     70}
     71
     72/*
     73 * Incoming requests are serialized for a connection, and the only race possible
     74 * is between the timeout handler freeing this and an incoming request.
     75 *
     76 * The operations on the fw-request list are protected by the mutex and
     77 * get_fw_req() increments the reference count before returning a fw_req pointer
     78 * to the users.
     79 *
     80 * free_firmware() also takes the mutex while removing an entry from the list,
     81 * it guarantees that every user of fw_req has taken a kref-reference by now and
     82 * we wouldn't have any new users.
     83 *
     84 * Once the last user drops the reference, the fw_req structure is freed.
     85 */
     86static void put_fw_req(struct fw_request *fw_req)
     87{
     88	kref_put(&fw_req->kref, fw_req_release);
     89}
     90
     91/* Caller must call put_fw_req() after using struct fw_request */
     92static struct fw_request *get_fw_req(struct fw_download *fw_download,
     93				     u8 firmware_id)
     94{
     95	struct fw_request *fw_req;
     96
     97	mutex_lock(&fw_download->mutex);
     98
     99	list_for_each_entry(fw_req, &fw_download->fw_requests, node) {
    100		if (fw_req->firmware_id == firmware_id) {
    101			kref_get(&fw_req->kref);
    102			goto unlock;
    103		}
    104	}
    105
    106	fw_req = NULL;
    107
    108unlock:
    109	mutex_unlock(&fw_download->mutex);
    110
    111	return fw_req;
    112}
    113
    114static void free_firmware(struct fw_download *fw_download,
    115			  struct fw_request *fw_req)
    116{
    117	/* Already disabled from timeout handlers */
    118	if (fw_req->disabled)
    119		return;
    120
    121	mutex_lock(&fw_download->mutex);
    122	list_del(&fw_req->node);
    123	mutex_unlock(&fw_download->mutex);
    124
    125	fw_req->disabled = true;
    126	put_fw_req(fw_req);
    127}
    128
    129static void fw_request_timedout(struct work_struct *work)
    130{
    131	struct delayed_work *dwork = to_delayed_work(work);
    132	struct fw_request *fw_req = container_of(dwork,
    133						 struct fw_request, dwork);
    134	struct fw_download *fw_download = fw_req->fw_download;
    135
    136	dev_err(fw_download->parent,
    137		"Timed out waiting for fetch / release firmware requests: %u\n",
    138		fw_req->firmware_id);
    139
    140	fw_req->timedout = true;
    141	free_firmware(fw_download, fw_req);
    142}
    143
    144static int exceeds_release_timeout(struct fw_request *fw_req)
    145{
    146	struct fw_download *fw_download = fw_req->fw_download;
    147
    148	if (time_before(jiffies, fw_req->release_timeout_j))
    149		return 0;
    150
    151	dev_err(fw_download->parent,
    152		"Firmware download didn't finish in time, abort: %d\n",
    153		fw_req->firmware_id);
    154
    155	fw_req->timedout = true;
    156	free_firmware(fw_download, fw_req);
    157
    158	return -ETIMEDOUT;
    159}
    160
    161/* This returns path of the firmware blob on the disk */
    162static struct fw_request *find_firmware(struct fw_download *fw_download,
    163					const char *tag)
    164{
    165	struct gb_interface *intf = fw_download->connection->bundle->intf;
    166	struct fw_request *fw_req;
    167	int ret, req_count;
    168
    169	fw_req = kzalloc(sizeof(*fw_req), GFP_KERNEL);
    170	if (!fw_req)
    171		return ERR_PTR(-ENOMEM);
    172
    173	/* Allocate ids from 1 to 255 (u8-max), 0 is an invalid id */
    174	ret = ida_simple_get(&fw_download->id_map, 1, 256, GFP_KERNEL);
    175	if (ret < 0) {
    176		dev_err(fw_download->parent,
    177			"failed to allocate firmware id (%d)\n", ret);
    178		goto err_free_req;
    179	}
    180	fw_req->firmware_id = ret;
    181
    182	snprintf(fw_req->name, sizeof(fw_req->name),
    183		 FW_NAME_PREFIX "%08x_%08x_%08x_%08x_%s.tftf",
    184		 intf->ddbl1_manufacturer_id, intf->ddbl1_product_id,
    185		 intf->vendor_id, intf->product_id, tag);
    186
    187	dev_info(fw_download->parent, "Requested firmware package '%s'\n",
    188		 fw_req->name);
    189
    190	ret = request_firmware(&fw_req->fw, fw_req->name, fw_download->parent);
    191	if (ret) {
    192		dev_err(fw_download->parent,
    193			"firmware request failed for %s (%d)\n", fw_req->name,
    194			ret);
    195		goto err_free_id;
    196	}
    197
    198	fw_req->fw_download = fw_download;
    199	kref_init(&fw_req->kref);
    200
    201	mutex_lock(&fw_download->mutex);
    202	list_add(&fw_req->node, &fw_download->fw_requests);
    203	mutex_unlock(&fw_download->mutex);
    204
    205	/* Timeout, in jiffies, within which firmware should get loaded */
    206	req_count = DIV_ROUND_UP(fw_req->fw->size, MIN_FETCH_SIZE);
    207	fw_req->release_timeout_j = jiffies + req_count * NEXT_REQ_TIMEOUT_J;
    208
    209	INIT_DELAYED_WORK(&fw_req->dwork, fw_request_timedout);
    210	schedule_delayed_work(&fw_req->dwork, NEXT_REQ_TIMEOUT_J);
    211
    212	return fw_req;
    213
    214err_free_id:
    215	ida_simple_remove(&fw_download->id_map, fw_req->firmware_id);
    216err_free_req:
    217	kfree(fw_req);
    218
    219	return ERR_PTR(ret);
    220}
    221
    222static int fw_download_find_firmware(struct gb_operation *op)
    223{
    224	struct gb_connection *connection = op->connection;
    225	struct fw_download *fw_download = gb_connection_get_data(connection);
    226	struct gb_fw_download_find_firmware_request *request;
    227	struct gb_fw_download_find_firmware_response *response;
    228	struct fw_request *fw_req;
    229	const char *tag;
    230
    231	if (op->request->payload_size != sizeof(*request)) {
    232		dev_err(fw_download->parent,
    233			"illegal size of find firmware request (%zu != %zu)\n",
    234			op->request->payload_size, sizeof(*request));
    235		return -EINVAL;
    236	}
    237
    238	request = op->request->payload;
    239	tag = (const char *)request->firmware_tag;
    240
    241	/* firmware_tag must be null-terminated */
    242	if (strnlen(tag, GB_FIRMWARE_TAG_MAX_SIZE) ==
    243	    GB_FIRMWARE_TAG_MAX_SIZE) {
    244		dev_err(fw_download->parent,
    245			"firmware-tag is not null-terminated\n");
    246		return -EINVAL;
    247	}
    248
    249	fw_req = find_firmware(fw_download, tag);
    250	if (IS_ERR(fw_req))
    251		return PTR_ERR(fw_req);
    252
    253	if (!gb_operation_response_alloc(op, sizeof(*response), GFP_KERNEL)) {
    254		dev_err(fw_download->parent, "error allocating response\n");
    255		free_firmware(fw_download, fw_req);
    256		return -ENOMEM;
    257	}
    258
    259	response = op->response->payload;
    260	response->firmware_id = fw_req->firmware_id;
    261	response->size = cpu_to_le32(fw_req->fw->size);
    262
    263	dev_dbg(fw_download->parent,
    264		"firmware size is %zu bytes\n", fw_req->fw->size);
    265
    266	return 0;
    267}
    268
    269static int fw_download_fetch_firmware(struct gb_operation *op)
    270{
    271	struct gb_connection *connection = op->connection;
    272	struct fw_download *fw_download = gb_connection_get_data(connection);
    273	struct gb_fw_download_fetch_firmware_request *request;
    274	struct gb_fw_download_fetch_firmware_response *response;
    275	struct fw_request *fw_req;
    276	const struct firmware *fw;
    277	unsigned int offset, size;
    278	u8 firmware_id;
    279	int ret = 0;
    280
    281	if (op->request->payload_size != sizeof(*request)) {
    282		dev_err(fw_download->parent,
    283			"Illegal size of fetch firmware request (%zu %zu)\n",
    284			op->request->payload_size, sizeof(*request));
    285		return -EINVAL;
    286	}
    287
    288	request = op->request->payload;
    289	offset = le32_to_cpu(request->offset);
    290	size = le32_to_cpu(request->size);
    291	firmware_id = request->firmware_id;
    292
    293	fw_req = get_fw_req(fw_download, firmware_id);
    294	if (!fw_req) {
    295		dev_err(fw_download->parent,
    296			"firmware not available for id: %02u\n", firmware_id);
    297		return -EINVAL;
    298	}
    299
    300	/* Make sure work handler isn't running in parallel */
    301	cancel_delayed_work_sync(&fw_req->dwork);
    302
    303	/* We timed-out before reaching here ? */
    304	if (fw_req->disabled) {
    305		ret = -ETIMEDOUT;
    306		goto put_fw;
    307	}
    308
    309	/*
    310	 * Firmware download must finish within a limited time interval. If it
    311	 * doesn't, then we might have a buggy Module on the other side. Abort
    312	 * download.
    313	 */
    314	ret = exceeds_release_timeout(fw_req);
    315	if (ret)
    316		goto put_fw;
    317
    318	fw = fw_req->fw;
    319
    320	if (offset >= fw->size || size > fw->size - offset) {
    321		dev_err(fw_download->parent,
    322			"bad fetch firmware request (offs = %u, size = %u)\n",
    323			offset, size);
    324		ret = -EINVAL;
    325		goto put_fw;
    326	}
    327
    328	if (!gb_operation_response_alloc(op, sizeof(*response) + size,
    329					 GFP_KERNEL)) {
    330		dev_err(fw_download->parent,
    331			"error allocating fetch firmware response\n");
    332		ret = -ENOMEM;
    333		goto put_fw;
    334	}
    335
    336	response = op->response->payload;
    337	memcpy(response->data, fw->data + offset, size);
    338
    339	dev_dbg(fw_download->parent,
    340		"responding with firmware (offs = %u, size = %u)\n", offset,
    341		size);
    342
    343	/* Refresh timeout */
    344	schedule_delayed_work(&fw_req->dwork, NEXT_REQ_TIMEOUT_J);
    345
    346put_fw:
    347	put_fw_req(fw_req);
    348
    349	return ret;
    350}
    351
    352static int fw_download_release_firmware(struct gb_operation *op)
    353{
    354	struct gb_connection *connection = op->connection;
    355	struct fw_download *fw_download = gb_connection_get_data(connection);
    356	struct gb_fw_download_release_firmware_request *request;
    357	struct fw_request *fw_req;
    358	u8 firmware_id;
    359
    360	if (op->request->payload_size != sizeof(*request)) {
    361		dev_err(fw_download->parent,
    362			"Illegal size of release firmware request (%zu %zu)\n",
    363			op->request->payload_size, sizeof(*request));
    364		return -EINVAL;
    365	}
    366
    367	request = op->request->payload;
    368	firmware_id = request->firmware_id;
    369
    370	fw_req = get_fw_req(fw_download, firmware_id);
    371	if (!fw_req) {
    372		dev_err(fw_download->parent,
    373			"firmware not available for id: %02u\n", firmware_id);
    374		return -EINVAL;
    375	}
    376
    377	cancel_delayed_work_sync(&fw_req->dwork);
    378
    379	free_firmware(fw_download, fw_req);
    380	put_fw_req(fw_req);
    381
    382	dev_dbg(fw_download->parent, "release firmware\n");
    383
    384	return 0;
    385}
    386
    387int gb_fw_download_request_handler(struct gb_operation *op)
    388{
    389	u8 type = op->type;
    390
    391	switch (type) {
    392	case GB_FW_DOWNLOAD_TYPE_FIND_FIRMWARE:
    393		return fw_download_find_firmware(op);
    394	case GB_FW_DOWNLOAD_TYPE_FETCH_FIRMWARE:
    395		return fw_download_fetch_firmware(op);
    396	case GB_FW_DOWNLOAD_TYPE_RELEASE_FIRMWARE:
    397		return fw_download_release_firmware(op);
    398	default:
    399		dev_err(&op->connection->bundle->dev,
    400			"unsupported request: %u\n", type);
    401		return -EINVAL;
    402	}
    403}
    404
    405int gb_fw_download_connection_init(struct gb_connection *connection)
    406{
    407	struct fw_download *fw_download;
    408	int ret;
    409
    410	if (!connection)
    411		return 0;
    412
    413	fw_download = kzalloc(sizeof(*fw_download), GFP_KERNEL);
    414	if (!fw_download)
    415		return -ENOMEM;
    416
    417	fw_download->parent = &connection->bundle->dev;
    418	INIT_LIST_HEAD(&fw_download->fw_requests);
    419	ida_init(&fw_download->id_map);
    420	gb_connection_set_data(connection, fw_download);
    421	fw_download->connection = connection;
    422	mutex_init(&fw_download->mutex);
    423
    424	ret = gb_connection_enable(connection);
    425	if (ret)
    426		goto err_destroy_id_map;
    427
    428	return 0;
    429
    430err_destroy_id_map:
    431	ida_destroy(&fw_download->id_map);
    432	kfree(fw_download);
    433
    434	return ret;
    435}
    436
    437void gb_fw_download_connection_exit(struct gb_connection *connection)
    438{
    439	struct fw_download *fw_download;
    440	struct fw_request *fw_req, *tmp;
    441
    442	if (!connection)
    443		return;
    444
    445	fw_download = gb_connection_get_data(connection);
    446	gb_connection_disable(fw_download->connection);
    447
    448	/*
    449	 * Make sure we have a reference to the pending requests, before they
    450	 * are freed from the timeout handler.
    451	 */
    452	mutex_lock(&fw_download->mutex);
    453	list_for_each_entry(fw_req, &fw_download->fw_requests, node)
    454		kref_get(&fw_req->kref);
    455	mutex_unlock(&fw_download->mutex);
    456
    457	/* Release pending firmware packages */
    458	list_for_each_entry_safe(fw_req, tmp, &fw_download->fw_requests, node) {
    459		cancel_delayed_work_sync(&fw_req->dwork);
    460		free_firmware(fw_download, fw_req);
    461		put_fw_req(fw_req);
    462	}
    463
    464	ida_destroy(&fw_download->id_map);
    465	kfree(fw_download);
    466}