brintos

brintos / linux-shallow public Read only

0
0
Text · 14.9 KiB · 0f7ec88 Raw
468 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Microchip Polarfire SoC "Auto Update" FPGA reprogramming.4 *5 * Documentation of this functionality is available in the "PolarFire® FPGA and6 * PolarFire SoC FPGA Programming" User Guide.7 *8 * Copyright (c) 2022-2023 Microchip Corporation. All rights reserved.9 *10 * Author: Conor Dooley <conor.dooley@microchip.com>11 */12#include <linux/cleanup.h>13#include <linux/debugfs.h>14#include <linux/firmware.h>15#include <linux/math.h>16#include <linux/module.h>17#include <linux/mtd/mtd.h>18#include <linux/platform_device.h>19#include <linux/sizes.h>20 21#include <soc/microchip/mpfs.h>22 23#define AUTO_UPDATE_DEFAULT_MBOX_OFFSET		0u24#define AUTO_UPDATE_DEFAULT_RESP_OFFSET		0u25 26#define AUTO_UPDATE_FEATURE_CMD_OPCODE		0x05u27#define AUTO_UPDATE_FEATURE_CMD_DATA_SIZE	0u28#define AUTO_UPDATE_FEATURE_RESP_SIZE		33u29#define AUTO_UPDATE_FEATURE_CMD_DATA		NULL30#define AUTO_UPDATE_FEATURE_ENABLED		BIT(5)31 32#define AUTO_UPDATE_AUTHENTICATE_CMD_OPCODE	0x22u33#define AUTO_UPDATE_AUTHENTICATE_CMD_DATA_SIZE	0u34#define AUTO_UPDATE_AUTHENTICATE_RESP_SIZE	1u35#define AUTO_UPDATE_AUTHENTICATE_CMD_DATA	NULL36 37#define AUTO_UPDATE_PROGRAM_CMD_OPCODE		0x46u38#define AUTO_UPDATE_PROGRAM_CMD_DATA_SIZE	0u39#define AUTO_UPDATE_PROGRAM_RESP_SIZE		1u40#define AUTO_UPDATE_PROGRAM_CMD_DATA		NULL41 42/*43 * SPI Flash layout example:44 * |------------------------------| 0x000000045 * | 1 KiB                        |46 * | SPI "directories"            |47 * |------------------------------| 0x000040048 * | 1 MiB                        |49 * | Reserved area                |50 * | Used for bitstream info      |51 * |------------------------------| 0x010040052 * | 20 MiB                       |53 * | Golden Image                 |54 * |------------------------------| 0x150040055 * | 20 MiB                       |56 * | Auto Upgrade Image           |57 * |------------------------------| 0x290040058 * | 20 MiB                       |59 * | Reserved for multi-image IAP |60 * | Unused for Auto Upgrade      |61 * |------------------------------| 0x3D0040062 * | ? B                          |63 * | Unused                       |64 * |------------------------------| 0x?65 */66#define AUTO_UPDATE_DIRECTORY_BASE	0u67#define AUTO_UPDATE_DIRECTORY_WIDTH	4u68#define AUTO_UPDATE_GOLDEN_INDEX	0u69#define AUTO_UPDATE_UPGRADE_INDEX	1u70#define AUTO_UPDATE_BLANK_INDEX		2u71#define AUTO_UPDATE_GOLDEN_DIRECTORY	(AUTO_UPDATE_DIRECTORY_WIDTH * AUTO_UPDATE_GOLDEN_INDEX)72#define AUTO_UPDATE_UPGRADE_DIRECTORY	(AUTO_UPDATE_DIRECTORY_WIDTH * AUTO_UPDATE_UPGRADE_INDEX)73#define AUTO_UPDATE_BLANK_DIRECTORY	(AUTO_UPDATE_DIRECTORY_WIDTH * AUTO_UPDATE_BLANK_INDEX)74#define AUTO_UPDATE_DIRECTORY_SIZE	SZ_1K75#define AUTO_UPDATE_INFO_BASE		AUTO_UPDATE_DIRECTORY_SIZE76#define AUTO_UPDATE_INFO_SIZE		SZ_1M77#define AUTO_UPDATE_BITSTREAM_BASE	(AUTO_UPDATE_DIRECTORY_SIZE + AUTO_UPDATE_INFO_SIZE)78 79struct mpfs_auto_update_priv {80	struct mpfs_sys_controller *sys_controller;81	struct device *dev;82	struct mtd_info *flash;83	struct fw_upload *fw_uploader;84	size_t size_per_bitstream;85	bool cancel_request;86};87 88static bool mpfs_auto_update_is_bitstream_info(const u8 *data, u32 size)89{90	if (size < 4)91		return false;92 93	if (data[0] == 0x4d && data[1] == 0x43 && data[2] == 0x48 && data[3] == 0x50)94		return true;95 96	return false;97}98 99static enum fw_upload_err mpfs_auto_update_prepare(struct fw_upload *fw_uploader, const u8 *data,100						   u32 size)101{102	struct mpfs_auto_update_priv *priv = fw_uploader->dd_handle;103	size_t erase_size = AUTO_UPDATE_DIRECTORY_SIZE;104 105	/*106	 * Verifying the Golden Image is idealistic. It will be evaluated107	 * against the currently programmed image and thus may fail - due to108	 * either rollback protection (if its an older version than that in use)109	 * or if the version is the same as that of the in-use image.110	 * Extracting the information as to why a failure occurred is not111	 * currently possible due to limitations of the system controller112	 * driver. If those are fixed, verification of the Golden Image should113	 * be added here.114	 */115 116	priv->flash = mpfs_sys_controller_get_flash(priv->sys_controller);117	if (!priv->flash)118		return FW_UPLOAD_ERR_HW_ERROR;119 120	erase_size = round_up(erase_size, (u64)priv->flash->erasesize);121 122	/*123	 * We need to calculate if we have enough space in the flash for the124	 * new image.125	 * First, chop off the first 1 KiB as it's reserved for the directory.126	 * The 1 MiB reserved for design info needs to be ignored also.127	 * All that remains is carved into 3 & rounded down to the erasesize.128	 * If this is smaller than the image size, we abort.129	 * There's also no need to consume more than 20 MiB per image.130	 */131	priv->size_per_bitstream = priv->flash->size - SZ_1K - SZ_1M;132	priv->size_per_bitstream = round_down(priv->size_per_bitstream / 3, erase_size);133	if (priv->size_per_bitstream > 20 * SZ_1M)134		priv->size_per_bitstream = 20 * SZ_1M;135 136	if (priv->size_per_bitstream < size) {137		dev_err(priv->dev,138			"flash device has insufficient capacity to store this bitstream\n");139		return FW_UPLOAD_ERR_INVALID_SIZE;140	}141 142	priv->cancel_request = false;143 144	return FW_UPLOAD_ERR_NONE;145}146 147static void mpfs_auto_update_cancel(struct fw_upload *fw_uploader)148{149	struct mpfs_auto_update_priv *priv = fw_uploader->dd_handle;150 151	priv->cancel_request = true;152}153 154static enum fw_upload_err mpfs_auto_update_poll_complete(struct fw_upload *fw_uploader)155{156	return FW_UPLOAD_ERR_NONE;157}158 159static int mpfs_auto_update_verify_image(struct fw_upload *fw_uploader)160{161	struct mpfs_auto_update_priv *priv = fw_uploader->dd_handle;162	u32 *response_msg __free(kfree) =163		kzalloc(AUTO_UPDATE_FEATURE_RESP_SIZE * sizeof(*response_msg), GFP_KERNEL);164	struct mpfs_mss_response *response __free(kfree) =165		kzalloc(sizeof(struct mpfs_mss_response), GFP_KERNEL);166	struct mpfs_mss_msg *message __free(kfree) =167		kzalloc(sizeof(struct mpfs_mss_msg), GFP_KERNEL);168	int ret;169 170	if (!response_msg || !response || !message)171		return -ENOMEM;172 173	/*174	 * The system controller can verify that an image in the flash is valid.175	 * Rather than duplicate the check in this driver, call the relevant176	 * service from the system controller instead.177	 * This service has no command data and no response data. It overloads178	 * mbox_offset with the image index in the flash's SPI directory where179	 * the bitstream is located.180	 */181	response->resp_msg = response_msg;182	response->resp_size = AUTO_UPDATE_AUTHENTICATE_RESP_SIZE;183	message->cmd_opcode = AUTO_UPDATE_AUTHENTICATE_CMD_OPCODE;184	message->cmd_data_size = AUTO_UPDATE_AUTHENTICATE_CMD_DATA_SIZE;185	message->response = response;186	message->cmd_data = AUTO_UPDATE_AUTHENTICATE_CMD_DATA;187	message->mbox_offset = AUTO_UPDATE_UPGRADE_INDEX;188	message->resp_offset = AUTO_UPDATE_DEFAULT_RESP_OFFSET;189 190	dev_info(priv->dev, "Running verification of Upgrade Image\n");191	ret = mpfs_blocking_transaction(priv->sys_controller, message);192	if (ret | response->resp_status) {193		dev_warn(priv->dev, "Verification of Upgrade Image failed!\n");194		return ret ? ret : -EBADMSG;195	}196 197	dev_info(priv->dev, "Verification of Upgrade Image passed!\n");198 199	return 0;200}201 202static int mpfs_auto_update_set_image_address(struct mpfs_auto_update_priv *priv,203					      u32 image_address, loff_t directory_address)204{205	struct erase_info erase;206	size_t erase_size = round_up(AUTO_UPDATE_DIRECTORY_SIZE, (u64)priv->flash->erasesize);207	size_t bytes_written = 0, bytes_read = 0;208	char *buffer __free(kfree) = kzalloc(erase_size, GFP_KERNEL);209	int ret;210 211	if (!buffer)212		return -ENOMEM;213 214	erase.addr = AUTO_UPDATE_DIRECTORY_BASE;215	erase.len = erase_size;216 217	/*218	 * We need to write the "SPI DIRECTORY" to the first 1 KiB, telling219	 * the system controller where to find the actual bitstream. Since220	 * this is spi-nor, we have to read the first eraseblock, erase that221	 * portion of the flash, modify the data and then write it back.222	 * There's no need to do this though if things are already the way they223	 * should be, so check and save the write in that case.224	 */225	ret = mtd_read(priv->flash, AUTO_UPDATE_DIRECTORY_BASE, erase_size, &bytes_read,226		       (u_char *)buffer);227	if (ret)228		return ret;229 230	if (bytes_read != erase_size)231		return -EIO;232 233	if ((*(u32 *)(buffer + AUTO_UPDATE_UPGRADE_DIRECTORY) == image_address) &&234	    !(*(u32 *)(buffer + AUTO_UPDATE_BLANK_DIRECTORY)))235		return 0;236 237	ret = mtd_erase(priv->flash, &erase);238	if (ret)239		return ret;240 241	/*242	 * Populate the image address and then zero out the next directory so243	 * that the system controller doesn't complain if in "Single Image"244	 * mode.245	 */246	memcpy(buffer + AUTO_UPDATE_UPGRADE_DIRECTORY, &image_address,247	       AUTO_UPDATE_DIRECTORY_WIDTH);248	memset(buffer + AUTO_UPDATE_BLANK_DIRECTORY, 0x0, AUTO_UPDATE_DIRECTORY_WIDTH);249 250	dev_info(priv->dev, "Writing the image address (0x%x) to the flash directory (0x%llx)\n",251		 image_address, directory_address);252 253	ret = mtd_write(priv->flash, 0x0, erase_size, &bytes_written, (u_char *)buffer);254	if (ret)255		return ret;256 257	if (bytes_written != erase_size)258		return -EIO;259 260	return 0;261}262 263static int mpfs_auto_update_write_bitstream(struct fw_upload *fw_uploader, const u8 *data,264					    u32 offset, u32 size, u32 *written)265{266	struct mpfs_auto_update_priv *priv = fw_uploader->dd_handle;267	struct erase_info erase;268	loff_t directory_address = AUTO_UPDATE_UPGRADE_DIRECTORY;269	size_t erase_size = AUTO_UPDATE_DIRECTORY_SIZE;270	size_t bytes_written = 0;271	bool is_info = mpfs_auto_update_is_bitstream_info(data, size);272	u32 image_address;273	int ret;274 275	erase_size = round_up(erase_size, (u64)priv->flash->erasesize);276 277	if (is_info)278		image_address = AUTO_UPDATE_INFO_BASE;279	else280		image_address = AUTO_UPDATE_BITSTREAM_BASE +281				AUTO_UPDATE_UPGRADE_INDEX * priv->size_per_bitstream;282 283	/*284	 * For bitstream info, the descriptor is written to a fixed offset,285	 * so there is no need to set the image address.286	 */287	if (!is_info) {288		ret = mpfs_auto_update_set_image_address(priv, image_address, directory_address);289		if (ret) {290			dev_err(priv->dev, "failed to set image address in the SPI directory: %d\n", ret);291			return ret;292		}293	} else {294		if (size > AUTO_UPDATE_INFO_SIZE) {295			dev_err(priv->dev, "bitstream info exceeds permitted size\n");296			return -ENOSPC;297		}298	}299 300	/*301	 * Now the .spi image itself can be written to the flash. Preservation302	 * of contents here is not important here, unlike the spi "directory"303	 * which must be RMWed.304	 */305	erase.len = round_up(size, (size_t)priv->flash->erasesize);306	erase.addr = image_address;307 308	dev_info(priv->dev, "Erasing the flash at address (0x%x)\n", image_address);309	ret = mtd_erase(priv->flash, &erase);310	if (ret)311		return ret;312 313	/*314	 * No parsing etc of the bitstream is required. The system controller315	 * will do all of that itself - including verifying that the bitstream316	 * is valid.317	 */318	dev_info(priv->dev, "Writing the image to the flash at address (0x%x)\n", image_address);319	ret = mtd_write(priv->flash, (loff_t)image_address, size, &bytes_written, data);320	if (ret)321		return ret;322 323	if (bytes_written != size)324		return -EIO;325 326	*written = bytes_written;327	dev_info(priv->dev, "Wrote 0x%zx bytes to the flash\n", bytes_written);328 329	return 0;330}331 332static enum fw_upload_err mpfs_auto_update_write(struct fw_upload *fw_uploader, const u8 *data,333						 u32 offset, u32 size, u32 *written)334{335	struct mpfs_auto_update_priv *priv = fw_uploader->dd_handle;336	int ret;337 338	ret = mpfs_auto_update_write_bitstream(fw_uploader, data, offset, size, written);339	if (ret)340		return FW_UPLOAD_ERR_RW_ERROR;341 342	if (priv->cancel_request)343		return FW_UPLOAD_ERR_CANCELED;344 345	if (mpfs_auto_update_is_bitstream_info(data, size))346		return FW_UPLOAD_ERR_NONE;347 348	ret = mpfs_auto_update_verify_image(fw_uploader);349	if (ret)350		return FW_UPLOAD_ERR_FW_INVALID;351 352	return FW_UPLOAD_ERR_NONE;353}354 355static const struct fw_upload_ops mpfs_auto_update_ops = {356	.prepare = mpfs_auto_update_prepare,357	.write = mpfs_auto_update_write,358	.poll_complete = mpfs_auto_update_poll_complete,359	.cancel = mpfs_auto_update_cancel,360};361 362static int mpfs_auto_update_available(struct mpfs_auto_update_priv *priv)363{364	u32 *response_msg __free(kfree) =365		kzalloc(AUTO_UPDATE_FEATURE_RESP_SIZE * sizeof(*response_msg), GFP_KERNEL);366	struct mpfs_mss_response *response __free(kfree) =367		kzalloc(sizeof(struct mpfs_mss_response), GFP_KERNEL);368	struct mpfs_mss_msg *message __free(kfree) =369		kzalloc(sizeof(struct mpfs_mss_msg), GFP_KERNEL);370	int ret;371 372	if (!response_msg || !response || !message)373		return -ENOMEM;374 375	/*376	 * To verify that Auto Update is possible, the "Query Security Service377	 * Request" is performed.378	 * This service has no command data & does not overload mbox_offset.379	 */380	response->resp_msg = response_msg;381	response->resp_size = AUTO_UPDATE_FEATURE_RESP_SIZE;382	message->cmd_opcode = AUTO_UPDATE_FEATURE_CMD_OPCODE;383	message->cmd_data_size = AUTO_UPDATE_FEATURE_CMD_DATA_SIZE;384	message->response = response;385	message->cmd_data = AUTO_UPDATE_FEATURE_CMD_DATA;386	message->mbox_offset = AUTO_UPDATE_DEFAULT_MBOX_OFFSET;387	message->resp_offset = AUTO_UPDATE_DEFAULT_RESP_OFFSET;388 389	ret = mpfs_blocking_transaction(priv->sys_controller, message);390	if (ret)391		return ret;392 393	/*394	 * Currently, the system controller's firmware does not generate any395	 * interrupts for failed services, so mpfs_blocking_transaction() should396	 * time out & therefore return an error.397	 * Hitting this check is highly unlikely at present, but if the system398	 * controller's behaviour changes so that it does generate interrupts399	 * for failed services, it will be required.400	 */401	if (response->resp_status)402		return -EIO;403 404	/*405	 * Bit 5 of byte 1 is "UL_Auto Update" & if it is set, Auto Update is406	 * not possible.407	 */408	if (response_msg[1] & AUTO_UPDATE_FEATURE_ENABLED)409		return -EPERM;410 411	return 0;412}413 414static int mpfs_auto_update_probe(struct platform_device *pdev)415{416	struct device *dev = &pdev->dev;417	struct mpfs_auto_update_priv *priv;418	struct fw_upload *fw_uploader;419	int ret;420 421	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);422	if (!priv)423		return -ENOMEM;424 425	priv->sys_controller = mpfs_sys_controller_get(dev);426	if (IS_ERR(priv->sys_controller))427		return dev_err_probe(dev, PTR_ERR(priv->sys_controller),428				     "Could not register as a sub device of the system controller\n");429 430	priv->dev = dev;431	platform_set_drvdata(pdev, priv);432 433	ret = mpfs_auto_update_available(priv);434	if (ret)435		return dev_err_probe(dev, ret,436				     "The current bitstream does not support auto-update\n");437 438	fw_uploader = firmware_upload_register(THIS_MODULE, dev, "mpfs-auto-update",439					       &mpfs_auto_update_ops, priv);440	if (IS_ERR(fw_uploader))441		return dev_err_probe(dev, PTR_ERR(fw_uploader),442				     "Failed to register the bitstream uploader\n");443 444	priv->fw_uploader = fw_uploader;445 446	return 0;447}448 449static void mpfs_auto_update_remove(struct platform_device *pdev)450{451	struct mpfs_auto_update_priv *priv = platform_get_drvdata(pdev);452 453	firmware_upload_unregister(priv->fw_uploader);454}455 456static struct platform_driver mpfs_auto_update_driver = {457	.driver = {458		.name = "mpfs-auto-update",459	},460	.probe = mpfs_auto_update_probe,461	.remove_new = mpfs_auto_update_remove,462};463module_platform_driver(mpfs_auto_update_driver);464 465MODULE_LICENSE("GPL");466MODULE_AUTHOR("Conor Dooley <conor.dooley@microchip.com>");467MODULE_DESCRIPTION("PolarFire SoC Auto Update FPGA reprogramming");468