fpga: zynqmp: Add secure bitstream loading for ZynqMP
This patch adds support for loading secure bitstreams on ZynqMP platforms. The secure bitstream images has to be generated using Xilinx bootgen tool. Signed-off-by: Siva Durga Prasad Paladugu <siva.durga.paladugu@xilinx.com> Signed-off-by: Michal Simek <michal.simek@xilinx.com>
This commit is contained in:
		
							parent
							
								
									cedd48e2cd
								
							
						
					
					
						commit
						a18d09ea38
					
				|  | @ -13,8 +13,14 @@ | ||||||
| #define ZYNQMP_SIP_SVC_PM_SECURE_IMG_LOAD	0xC200002D | #define ZYNQMP_SIP_SVC_PM_SECURE_IMG_LOAD	0xC200002D | ||||||
| #define KEY_PTR_LEN	32 | #define KEY_PTR_LEN	32 | ||||||
| 
 | 
 | ||||||
|  | #define ZYNQMP_FPGA_BIT_AUTH_DDR	1 | ||||||
|  | #define ZYNQMP_FPGA_BIT_AUTH_OCM	2 | ||||||
|  | #define ZYNQMP_FPGA_BIT_ENC_USR_KEY	3 | ||||||
|  | #define ZYNQMP_FPGA_BIT_ENC_DEV_KEY	4 | ||||||
| #define ZYNQMP_FPGA_BIT_NS		5 | #define ZYNQMP_FPGA_BIT_NS		5 | ||||||
| 
 | 
 | ||||||
|  | #define ZYNQMP_FPGA_AUTH_DDR	1 | ||||||
|  | 
 | ||||||
| enum { | enum { | ||||||
| 	IDCODE, | 	IDCODE, | ||||||
| 	VERSION, | 	VERSION, | ||||||
|  |  | ||||||
|  | @ -31,6 +31,7 @@ CONFIG_CMD_DFU=y | ||||||
| # CONFIG_CMD_FLASH is not set | # CONFIG_CMD_FLASH is not set | ||||||
| CONFIG_CMD_FPGA_LOADBP=y | CONFIG_CMD_FPGA_LOADBP=y | ||||||
| CONFIG_CMD_FPGA_LOADP=y | CONFIG_CMD_FPGA_LOADP=y | ||||||
|  | CONFIG_CMD_FPGA_LOAD_SECURE=y | ||||||
| CONFIG_CMD_GPIO=y | CONFIG_CMD_GPIO=y | ||||||
| CONFIG_CMD_GPT=y | CONFIG_CMD_GPT=y | ||||||
| CONFIG_CMD_I2C=y | CONFIG_CMD_I2C=y | ||||||
|  |  | ||||||
|  | @ -171,6 +171,24 @@ int xilinx_loadfs(xilinx_desc *desc, const void *buf, size_t bsize, | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | #if defined(CONFIG_CMD_FPGA_LOAD_SECURE) | ||||||
|  | int xilinx_loads(xilinx_desc *desc, const void *buf, size_t bsize, | ||||||
|  | 		 struct fpga_secure_info *fpga_sec_info) | ||||||
|  | { | ||||||
|  | 	if (!xilinx_validate(desc, (char *)__func__)) { | ||||||
|  | 		printf("%s: Invalid device descriptor\n", __func__); | ||||||
|  | 		return FPGA_FAIL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!desc->operations || !desc->operations->loads) { | ||||||
|  | 		printf("%s: Missing loads operation\n", __func__); | ||||||
|  | 		return FPGA_FAIL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return desc->operations->loads(desc, buf, bsize, fpga_sec_info); | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| int xilinx_dump(xilinx_desc *desc, const void *buf, size_t bsize) | int xilinx_dump(xilinx_desc *desc, const void *buf, size_t bsize) | ||||||
| { | { | ||||||
| 	if (!xilinx_validate (desc, (char *)__FUNCTION__)) { | 	if (!xilinx_validate (desc, (char *)__FUNCTION__)) { | ||||||
|  |  | ||||||
|  | @ -223,6 +223,51 @@ static int zynqmp_load(xilinx_desc *desc, const void *buf, size_t bsize, | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #if defined(CONFIG_CMD_FPGA_LOAD_SECURE) && !defined(CONFIG_SPL_BUILD) | ||||||
|  | static int zynqmp_loads(xilinx_desc *desc, const void *buf, size_t bsize, | ||||||
|  | 			struct fpga_secure_info *fpga_sec_info) | ||||||
|  | { | ||||||
|  | 	int ret; | ||||||
|  | 	u32 buf_lo, buf_hi; | ||||||
|  | 	u32 ret_payload[PAYLOAD_ARG_CNT]; | ||||||
|  | 	u8 flag = 0; | ||||||
|  | 
 | ||||||
|  | 	flush_dcache_range((ulong)buf, (ulong)buf + | ||||||
|  | 			   ALIGN(bsize, CONFIG_SYS_CACHELINE_SIZE)); | ||||||
|  | 
 | ||||||
|  | 	if (!fpga_sec_info->encflag) | ||||||
|  | 		flag |= BIT(ZYNQMP_FPGA_BIT_ENC_DEV_KEY); | ||||||
|  | 
 | ||||||
|  | 	if (fpga_sec_info->userkey_addr && | ||||||
|  | 	    fpga_sec_info->encflag == FPGA_ENC_USR_KEY) { | ||||||
|  | 		flush_dcache_range((ulong)fpga_sec_info->userkey_addr, | ||||||
|  | 				   (ulong)fpga_sec_info->userkey_addr + | ||||||
|  | 				   ALIGN(KEY_PTR_LEN, | ||||||
|  | 					 CONFIG_SYS_CACHELINE_SIZE)); | ||||||
|  | 		flag |= BIT(ZYNQMP_FPGA_BIT_ENC_USR_KEY); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!fpga_sec_info->authflag) | ||||||
|  | 		flag |= BIT(ZYNQMP_FPGA_BIT_AUTH_OCM); | ||||||
|  | 
 | ||||||
|  | 	if (fpga_sec_info->authflag == ZYNQMP_FPGA_AUTH_DDR) | ||||||
|  | 		flag |= BIT(ZYNQMP_FPGA_BIT_AUTH_DDR); | ||||||
|  | 
 | ||||||
|  | 	buf_lo = lower_32_bits((ulong)buf); | ||||||
|  | 	buf_hi = upper_32_bits((ulong)buf); | ||||||
|  | 
 | ||||||
|  | 	ret = invoke_smc(ZYNQMP_SIP_SVC_PM_FPGA_LOAD, buf_lo, buf_hi, | ||||||
|  | 			 (u32)(uintptr_t)fpga_sec_info->userkey_addr, | ||||||
|  | 			 flag, ret_payload); | ||||||
|  | 	if (ret) | ||||||
|  | 		puts("PL FPGA LOAD fail\n"); | ||||||
|  | 	else | ||||||
|  | 		puts("Bitstream successfully loaded\n"); | ||||||
|  | 
 | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| static int zynqmp_pcap_info(xilinx_desc *desc) | static int zynqmp_pcap_info(xilinx_desc *desc) | ||||||
| { | { | ||||||
| 	int ret; | 	int ret; | ||||||
|  | @ -238,5 +283,8 @@ static int zynqmp_pcap_info(xilinx_desc *desc) | ||||||
| 
 | 
 | ||||||
| struct xilinx_fpga_op zynqmp_op = { | struct xilinx_fpga_op zynqmp_op = { | ||||||
| 	.load = zynqmp_load, | 	.load = zynqmp_load, | ||||||
|  | #if defined CONFIG_CMD_FPGA_LOAD_SECURE | ||||||
|  | 	.loads = zynqmp_loads, | ||||||
|  | #endif | ||||||
| 	.info = zynqmp_pcap_info, | 	.info = zynqmp_pcap_info, | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -48,6 +48,8 @@ typedef struct {		/* typedef xilinx_desc */ | ||||||
| struct xilinx_fpga_op { | struct xilinx_fpga_op { | ||||||
| 	int (*load)(xilinx_desc *, const void *, size_t, bitstream_type); | 	int (*load)(xilinx_desc *, const void *, size_t, bitstream_type); | ||||||
| 	int (*loadfs)(xilinx_desc *, const void *, size_t, fpga_fs_info *); | 	int (*loadfs)(xilinx_desc *, const void *, size_t, fpga_fs_info *); | ||||||
|  | 	int (*loads)(xilinx_desc *desc, const void *buf, size_t bsize, | ||||||
|  | 		     struct fpga_secure_info *fpga_sec_info); | ||||||
| 	int (*dump)(xilinx_desc *, const void *, size_t); | 	int (*dump)(xilinx_desc *, const void *, size_t); | ||||||
| 	int (*info)(xilinx_desc *); | 	int (*info)(xilinx_desc *); | ||||||
| }; | }; | ||||||
|  | @ -60,6 +62,8 @@ int xilinx_dump(xilinx_desc *desc, const void *buf, size_t bsize); | ||||||
| int xilinx_info(xilinx_desc *desc); | int xilinx_info(xilinx_desc *desc); | ||||||
| int xilinx_loadfs(xilinx_desc *desc, const void *buf, size_t bsize, | int xilinx_loadfs(xilinx_desc *desc, const void *buf, size_t bsize, | ||||||
| 		  fpga_fs_info *fpga_fsinfo); | 		  fpga_fs_info *fpga_fsinfo); | ||||||
|  | int xilinx_loads(xilinx_desc *desc, const void *buf, size_t bsize, | ||||||
|  | 		 struct fpga_secure_info *fpga_sec_info); | ||||||
| 
 | 
 | ||||||
| /* Board specific implementation specific function types
 | /* Board specific implementation specific function types
 | ||||||
|  *********************************************************************/ |  *********************************************************************/ | ||||||
|  |  | ||||||
|  | @ -16,6 +16,9 @@ | ||||||
| #define ZYNQMP_FPGA_OP_LOAD			(1 << 1) | #define ZYNQMP_FPGA_OP_LOAD			(1 << 1) | ||||||
| #define ZYNQMP_FPGA_OP_DONE			(1 << 2) | #define ZYNQMP_FPGA_OP_DONE			(1 << 2) | ||||||
| 
 | 
 | ||||||
|  | #define ZYNQMP_FPGA_FLAG_AUTHENTICATED		BIT(2) | ||||||
|  | #define ZYNQMP_FPGA_FLAG_ENCRYPTED		BIT(3) | ||||||
|  | 
 | ||||||
| #define ZYNQMP_CSU_IDCODE_DEVICE_CODE_SHIFT	15 | #define ZYNQMP_CSU_IDCODE_DEVICE_CODE_SHIFT	15 | ||||||
| #define ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK	(0xf << \ | #define ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK	(0xf << \ | ||||||
| 					ZYNQMP_CSU_IDCODE_DEVICE_CODE_SHIFT) | 					ZYNQMP_CSU_IDCODE_DEVICE_CODE_SHIFT) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue