1// SPDX-License-Identifier: GPL-2.0 2/* 3 * (C) Copyright 2015 - 2016, Xilinx, Inc, 4 * Michal Simek <michal.simek@amd.com> 5 * Siva Durga Prasad Paladugu <siva.durga.prasad.paladugu@amd.com> 6 */ 7 8#include <console.h> 9#include <common.h> 10#include <compiler.h> 11#include <cpu_func.h> 12#include <fpga.h> 13#include <log.h> 14#include <zynqmppl.h> 15#include <zynqmp_firmware.h> 16#include <asm/cache.h> 17#include <linux/bitops.h> 18#include <linux/sizes.h> 19#include <asm/arch/sys_proto.h> 20#include <memalign.h> 21 22#define DUMMY_WORD 0xffffffff 23 24/* Xilinx binary format header */ 25static const u32 bin_format[] = { 26 DUMMY_WORD, /* Dummy words */ 27 DUMMY_WORD, 28 DUMMY_WORD, 29 DUMMY_WORD, 30 DUMMY_WORD, 31 DUMMY_WORD, 32 DUMMY_WORD, 33 DUMMY_WORD, 34 DUMMY_WORD, 35 DUMMY_WORD, 36 DUMMY_WORD, 37 DUMMY_WORD, 38 DUMMY_WORD, 39 DUMMY_WORD, 40 DUMMY_WORD, 41 DUMMY_WORD, 42 0x000000bb, /* Sync word */ 43 0x11220044, /* Sync word */ 44 DUMMY_WORD, 45 DUMMY_WORD, 46 0xaa995566, /* Sync word */ 47}; 48 49#define SWAP_NO 1 50#define SWAP_DONE 2 51 52/* 53 * Load the whole word from unaligned buffer 54 * Keep in your mind that it is byte loading on little-endian system 55 */ 56static u32 load_word(const void *buf, u32 swap) 57{ 58 u32 word = 0; 59 u8 *bitc = (u8 *)buf; 60 int p; 61 62 if (swap == SWAP_NO) { 63 for (p = 0; p < 4; p++) { 64 word <<= 8; 65 word |= bitc[p]; 66 } 67 } else { 68 for (p = 3; p >= 0; p--) { 69 word <<= 8; 70 word |= bitc[p]; 71 } 72 } 73 74 return word; 75} 76 77static u32 check_header(const void *buf) 78{ 79 u32 i, pattern; 80 int swap = SWAP_NO; 81 u32 *test = (u32 *)buf; 82 83 debug("%s: Let's check bitstream header\n", __func__); 84 85 /* Checking that passing bin is not a bitstream */ 86 for (i = 0; i < ARRAY_SIZE(bin_format); i++) { 87 pattern = load_word(&test[i], swap); 88 89 /* 90 * Bitstreams in binary format are swapped 91 * compare to regular bistream. 92 * Do not swap dummy word but if swap is done assume 93 * that parsing buffer is binary format 94 */ 95 if ((__swab32(pattern) != DUMMY_WORD) && 96 (__swab32(pattern) == bin_format[i])) { 97 swap = SWAP_DONE; 98 debug("%s: data swapped - let's swap\n", __func__); 99 } 100 101 debug("%s: %d/%px: pattern %x/%x bin_format\n", __func__, i, 102 &test[i], pattern, bin_format[i]); 103 } 104 debug("%s: Found bitstream header at %px %s swapinng\n", __func__, 105 buf, swap == SWAP_NO ? "without" : "with"); 106 107 return swap; 108} 109 110static void *check_data(u8 *buf, size_t bsize, u32 *swap) 111{ 112 u32 word, p = 0; /* possition */ 113 114 /* Because buf doesn't need to be aligned let's read it by chars */ 115 for (p = 0; p < bsize; p++) { 116 word = load_word(&buf[p], SWAP_NO); 117 debug("%s: word %x %x/%px\n", __func__, word, p, &buf[p]); 118 119 /* Find the first bitstream dummy word */ 120 if (word == DUMMY_WORD) { 121 debug("%s: Found dummy word at position %x/%px\n", 122 __func__, p, &buf[p]); 123 *swap = check_header(&buf[p]); 124 if (*swap) { 125 /* FIXME add full bitstream checking here */ 126 return &buf[p]; 127 } 128 } 129 /* Loop can be huge - support CTRL + C */ 130 if (ctrlc()) 131 return NULL; 132 } 133 return NULL; 134} 135 136static ulong zynqmp_align_dma_buffer(u32 *buf, u32 len, u32 swap) 137{ 138 u32 *new_buf; 139 u32 i; 140 141 if ((ulong)buf != ALIGN((ulong)buf, ARCH_DMA_MINALIGN)) { 142 new_buf = (u32 *)ALIGN((ulong)buf, ARCH_DMA_MINALIGN); 143 144 /* 145 * This might be dangerous but permits to flash if 146 * ARCH_DMA_MINALIGN is greater than header size 147 */ 148 if (new_buf > (u32 *)buf) { 149 debug("%s: Aligned buffer is after buffer start\n", 150 __func__); 151 new_buf -= ARCH_DMA_MINALIGN; 152 } 153 printf("%s: Align buffer at %px to %px(swap %d)\n", __func__, 154 buf, new_buf, swap); 155 156 for (i = 0; i < (len/4); i++) 157 new_buf[i] = load_word(&buf[i], swap); 158 159 buf = new_buf; 160 } else if ((swap != SWAP_DONE) && 161 (zynqmp_firmware_version() <= PMUFW_V1_0)) { 162 /* For bitstream which are aligned */ 163 new_buf = buf; 164 165 printf("%s: Bitstream is not swapped(%d) - swap it\n", __func__, 166 swap); 167 168 for (i = 0; i < (len/4); i++) 169 new_buf[i] = load_word(&buf[i], swap); 170 } 171 172 return (ulong)buf; 173} 174 175static int zynqmp_validate_bitstream(xilinx_desc *desc, const void *buf, 176 size_t bsize, u32 blocksize, u32 *swap) 177{ 178 ulong *buf_start; 179 ulong diff; 180 181 buf_start = check_data((u8 *)buf, blocksize, swap); 182 183 if (!buf_start) 184 return FPGA_FAIL; 185 186 /* Check if data is postpone from start */ 187 diff = (ulong)buf_start - (ulong)buf; 188 if (diff) { 189 printf("%s: Bitstream is not validated yet (diff %lx)\n", 190 __func__, diff); 191 return FPGA_FAIL; 192 } 193 194 if ((ulong)buf < SZ_1M) { 195 printf("%s: Bitstream has to be placed up to 1MB (%px)\n", 196 __func__, buf); 197 return FPGA_FAIL; 198 } 199 200 return 0; 201} 202 203#if CONFIG_IS_ENABLED(FPGA_LOAD_SECURE) 204static int zynqmp_check_compatible(xilinx_desc *desc, int flags) 205{ 206 /* 207 * If no flags set, the image may be legacy, but we need to 208 * signal caller this situation with specific error code. 209 */ 210 if (!flags) 211 return -ENODATA; 212 213 /* For legacy bitstream images no need for other methods exist */ 214 if ((flags & desc->flags) && flags == FPGA_LEGACY) 215 return 0; 216 217 /* 218 * Other images are handled in secure callback loads(). Check 219 * callback existence besides image type support. 220 */ 221 if (desc->operations->loads && (flags & desc->flags)) 222 return 0; 223 224 return -ENODEV; 225} 226#endif 227 228static int zynqmp_load(xilinx_desc *desc, const void *buf, size_t bsize, 229 bitstream_type bstype, int flags) 230{ 231 ALLOC_CACHE_ALIGN_BUFFER(u32, bsizeptr, 1); 232 u32 swap = 0; 233 ulong bin_buf; 234 int ret; 235 u32 buf_lo, buf_hi; 236 u32 bsize_req = (u32)bsize; 237 u32 ret_payload[PAYLOAD_ARG_CNT]; 238#if CONFIG_IS_ENABLED(FPGA_LOAD_SECURE) 239 struct fpga_secure_info info = { 0 }; 240 241 ret = zynqmp_check_compatible(desc, flags); 242 if (ret) { 243 if (ret != -ENODATA) { 244 puts("Missing loads() operation or unsupported bitstream type\n"); 245 return FPGA_FAIL; 246 } 247 /* If flags is not set, the image treats as legacy */ 248 flags = FPGA_LEGACY; 249 } 250 251 switch (flags) { 252 case FPGA_LEGACY: 253 break; /* Handle the legacy image later in this function */ 254#if CONFIG_IS_ENABLED(FPGA_LOAD_SECURE) 255 case FPGA_XILINX_ZYNQMP_DDRAUTH: 256 /* DDR authentication */ 257 info.authflag = ZYNQMP_FPGA_AUTH_DDR; 258 info.encflag = FPGA_NO_ENC_OR_NO_AUTH; 259 return desc->operations->loads(desc, buf, bsize, &info); 260 case FPGA_XILINX_ZYNQMP_ENC: 261 /* Encryption using device key */ 262 info.authflag = FPGA_NO_ENC_OR_NO_AUTH; 263 info.encflag = FPGA_ENC_DEV_KEY; 264 return desc->operations->loads(desc, buf, bsize, &info); 265#endif 266 default: 267 printf("Unsupported bitstream type %d\n", flags); 268 return FPGA_FAIL; 269 } 270#endif 271 272 if (zynqmp_firmware_version() <= PMUFW_V1_0) { 273 puts("WARN: PMUFW v1.0 or less is detected\n"); 274 puts("WARN: Not all bitstream formats are supported\n"); 275 puts("WARN: Please upgrade PMUFW\n"); 276 if (zynqmp_validate_bitstream(desc, buf, bsize, bsize, &swap)) 277 return FPGA_FAIL; 278 bsizeptr = (u32 *)&bsize; 279 flush_dcache_range((ulong)bsizeptr, 280 (ulong)bsizeptr + sizeof(size_t)); 281 bsize_req = (u32)(uintptr_t)bsizeptr; 282 bstype |= BIT(ZYNQMP_FPGA_BIT_NS); 283 } else { 284 bstype = 0; 285 } 286 287 bin_buf = zynqmp_align_dma_buffer((u32 *)buf, bsize, swap); 288 289 flush_dcache_range(bin_buf, bin_buf + bsize); 290 291 buf_lo = (u32)bin_buf; 292 buf_hi = upper_32_bits(bin_buf); 293 294 ret = xilinx_pm_request(PM_FPGA_LOAD, buf_lo, buf_hi, 295 bsize_req, bstype, ret_payload); 296 if (ret) 297 printf("PL FPGA LOAD failed with err: 0x%08x\n", ret); 298 299 return ret; 300} 301 302#if CONFIG_IS_ENABLED(FPGA_LOAD_SECURE) 303static int zynqmp_loads(xilinx_desc *desc, const void *buf, size_t bsize, 304 struct fpga_secure_info *fpga_sec_info) 305{ 306 int ret; 307 u32 buf_lo, buf_hi; 308 u32 ret_payload[PAYLOAD_ARG_CNT]; 309 u8 flag = 0; 310 311 flush_dcache_range((ulong)buf, (ulong)buf + 312 ALIGN(bsize, CONFIG_SYS_CACHELINE_SIZE)); 313 314 if (!fpga_sec_info->encflag) 315 flag |= BIT(ZYNQMP_FPGA_BIT_ENC_DEV_KEY); 316 317 if (fpga_sec_info->userkey_addr && 318 fpga_sec_info->encflag == FPGA_ENC_USR_KEY) { 319 flush_dcache_range((ulong)fpga_sec_info->userkey_addr, 320 (ulong)fpga_sec_info->userkey_addr + 321 ALIGN(KEY_PTR_LEN, 322 CONFIG_SYS_CACHELINE_SIZE)); 323 flag |= BIT(ZYNQMP_FPGA_BIT_ENC_USR_KEY); 324 } 325 326 if (!fpga_sec_info->authflag) 327 flag |= BIT(ZYNQMP_FPGA_BIT_AUTH_OCM); 328 329 if (fpga_sec_info->authflag == ZYNQMP_FPGA_AUTH_DDR) 330 flag |= BIT(ZYNQMP_FPGA_BIT_AUTH_DDR); 331 332 buf_lo = lower_32_bits((ulong)buf); 333 buf_hi = upper_32_bits((ulong)buf); 334 335 if ((u32)(uintptr_t)fpga_sec_info->userkey_addr) 336 ret = xilinx_pm_request(PM_FPGA_LOAD, buf_lo, 337 buf_hi, 338 (u32)(uintptr_t)fpga_sec_info->userkey_addr, 339 flag, ret_payload); 340 else 341 ret = xilinx_pm_request(PM_FPGA_LOAD, buf_lo, 342 buf_hi, (u32)bsize, 343 flag, ret_payload); 344 345 if (ret) 346 puts("PL FPGA LOAD fail\n"); 347 else 348 puts("Bitstream successfully loaded\n"); 349 350 return ret; 351} 352#endif 353 354static int zynqmp_pcap_info(xilinx_desc *desc) 355{ 356 int ret; 357 u32 ret_payload[PAYLOAD_ARG_CNT]; 358 359 ret = xilinx_pm_request(PM_FPGA_GET_STATUS, 0, 0, 0, 360 0, ret_payload); 361 if (!ret) 362 printf("PCAP status\t0x%x\n", ret_payload[1]); 363 364 return ret; 365} 366 367static int __maybe_unused zynqmp_str2flag(xilinx_desc *desc, const char *str) 368{ 369 if (!strncmp(str, "u-boot,fpga-legacy", 18)) 370 return FPGA_LEGACY; 371#if CONFIG_IS_ENABLED(FPGA_LOAD_SECURE) 372 if (!strncmp(str, "u-boot,zynqmp-fpga-ddrauth", 26)) 373 return FPGA_XILINX_ZYNQMP_DDRAUTH; 374 375 if (!strncmp(str, "u-boot,zynqmp-fpga-enc", 22)) 376 return FPGA_XILINX_ZYNQMP_ENC; 377#endif 378 return 0; 379} 380 381struct xilinx_fpga_op zynqmp_op = { 382 .load = zynqmp_load, 383 .info = zynqmp_pcap_info, 384#if CONFIG_IS_ENABLED(FPGA_LOAD_SECURE) 385 .loads = zynqmp_loads, 386 .str2flag = zynqmp_str2flag, 387#endif 388}; 389