1331722Seadler// SPDX-License-Identifier: GPL-2.0+ 2341477Svmaffione/* 3341477Svmaffione * Copyright (C) 2018 Xilinx, Inc. 4261909Sluigi */ 5261909Sluigi 6261909Sluigi#include <common.h> 7261909Sluigi#include <command.h> 8261909Sluigi#include <log.h> 9261909Sluigi#include <asm/global_data.h> 10261909Sluigi#include <asm/io.h> 11261909Sluigi#include <asm/arch/hardware.h> 12261909Sluigi#include <asm/arch/sys_proto.h> 13261909Sluigi#include <malloc.h> 14261909Sluigi#include <linux/bitops.h> 15261909Sluigi#include <u-boot/md5.h> 16261909Sluigi#include <u-boot/rsa.h> 17261909Sluigi#include <u-boot/rsa-mod-exp.h> 18261909Sluigi#include <u-boot/sha256.h> 19261909Sluigi#include <zynqpl.h> 20261909Sluigi#include <fpga.h> 21261909Sluigi#include <zynq_bootimg.h> 22261909Sluigi 23261909SluigiDECLARE_GLOBAL_DATA_PTR; 24261909Sluigi 25261909Sluigi#ifdef CONFIG_CMD_ZYNQ_RSA 26261909Sluigi 27261909Sluigi#define ZYNQ_EFUSE_RSA_ENABLE_MASK 0x400 28261909Sluigi#define ZYNQ_ATTRIBUTE_PL_IMAGE_MASK 0x20 29261909Sluigi#define ZYNQ_ATTRIBUTE_CHECKSUM_TYPE_MASK 0x7000 30261909Sluigi#define ZYNQ_ATTRIBUTE_RSA_PRESENT_MASK 0x8000 31261909Sluigi#define ZYNQ_ATTRIBUTE_RSA_PART_OWNER_MASK 0x30000 32261909Sluigi 33261909Sluigi#define ZYNQ_RSA_MODULAR_SIZE 256 34261909Sluigi#define ZYNQ_RSA_MODULAR_EXT_SIZE 256 35261909Sluigi#define ZYNQ_RSA_EXPO_SIZE 64 36261909Sluigi#define ZYNQ_RSA_SPK_SIGNATURE_SIZE 256 37261909Sluigi#define ZYNQ_RSA_PARTITION_SIGNATURE_SIZE 256 38261909Sluigi#define ZYNQ_RSA_SIGNATURE_SIZE 0x6C0 39261909Sluigi#define ZYNQ_RSA_HEADER_SIZE 4 40261909Sluigi#define ZYNQ_RSA_MAGIC_WORD_SIZE 60 41261909Sluigi#define ZYNQ_RSA_PART_OWNER_UBOOT 1 42261909Sluigi#define ZYNQ_RSA_ALIGN_PPK_START 64 43261909Sluigi 44261909Sluigi#define WORD_LENGTH_SHIFT 2 45261909Sluigi 46261909Sluigistatic u8 *ppkmodular; 47261909Sluigistatic u8 *ppkmodularex; 48261909Sluigi 49261909Sluigistruct zynq_rsa_public_key { 50261909Sluigi uint len; /* Length of modulus[] in number of u32 */ 51261909Sluigi u32 n0inv; /* -1 / modulus[0] mod 2^32 */ 52261909Sluigi u32 *modulus; /* modulus as little endian array */ 53261909Sluigi u32 *rr; /* R^2 as little endian array */ 54261909Sluigi}; 55261909Sluigi 56261909Sluigistatic struct zynq_rsa_public_key public_key; 57261909Sluigi 58341477Svmaffionestatic struct partition_hdr part_hdr[ZYNQ_MAX_PARTITION_NUMBER]; 59341477Svmaffione 60341477Svmaffione/* 61261909Sluigi * Extract the primary public key components from already autheticated FSBL 62261909Sluigi */ 63261909Sluigistatic void zynq_extract_ppk(u32 fsbl_len) 64261909Sluigi{ 65261909Sluigi u32 padsize; 66261909Sluigi u8 *ppkptr; 67261909Sluigi 68261909Sluigi debug("%s\n", __func__); 69261909Sluigi 70261909Sluigi /* 71261909Sluigi * Extract the authenticated PPK from OCM i.e at end of the FSBL 72261909Sluigi */ 73261909Sluigi ppkptr = (u8 *)(fsbl_len + ZYNQ_OCM_BASEADDR); 74261909Sluigi padsize = ((u32)ppkptr % ZYNQ_RSA_ALIGN_PPK_START); 75261909Sluigi if (padsize) 76261909Sluigi ppkptr += (ZYNQ_RSA_ALIGN_PPK_START - padsize); 77261909Sluigi 78341477Svmaffione ppkptr += ZYNQ_RSA_HEADER_SIZE; 79261909Sluigi 80341477Svmaffione ppkptr += ZYNQ_RSA_MAGIC_WORD_SIZE; 81341477Svmaffione 82261909Sluigi ppkmodular = (u8 *)ppkptr; 83341477Svmaffione ppkptr += ZYNQ_RSA_MODULAR_SIZE; 84341477Svmaffione ppkmodularex = (u8 *)ppkptr; 85341477Svmaffione ppkptr += ZYNQ_RSA_MODULAR_EXT_SIZE; 86261909Sluigi} 87261909Sluigi 88285349Sluigi/* 89285349Sluigi * Calculate the inverse(-1 / modulus[0] mod 2^32 ) for the PPK 90261909Sluigi */ 91341477Svmaffionestatic u32 zynq_calc_inv(void) 92285349Sluigi{ 93261909Sluigi u32 modulus = public_key.modulus[0]; 94285349Sluigi u32 tmp = BIT(1); 95285349Sluigi u32 inverse; 96261909Sluigi 97341477Svmaffione inverse = modulus & BIT(0); 98285349Sluigi 99285349Sluigi while (tmp) { 100261909Sluigi inverse *= 2 - modulus * inverse; 101341477Svmaffione tmp *= tmp; 102341477Svmaffione } 103341477Svmaffione 104285349Sluigi return ~(inverse - 1); 105261909Sluigi} 106261909Sluigi 107285349Sluigi/* 108261909Sluigi * Recreate the signature by padding the bytes and verify with hash value 109261909Sluigi */ 110261909Sluigistatic int zynq_pad_and_check(u8 *signature, u8 *hash) 111261909Sluigi{ 112261909Sluigi u8 padding[] = {0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 113261909Sluigi 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 114261909Sluigi 0x20}; 115261909Sluigi u8 *pad_ptr = signature + 256; 116261909Sluigi u32 pad = 202; 117261909Sluigi u32 ii; 118285349Sluigi 119285349Sluigi /* 120285349Sluigi * Re-Create PKCS#1v1.5 Padding 121285349Sluigi * MSB ----------------------------------------------------LSB 122341477Svmaffione * 0x0 || 0x1 || 0xFF(for 202 bytes) || 0x0 || T_padding || SHA256 Hash 123261909Sluigi */ 124261909Sluigi if (*--pad_ptr != 0 || *--pad_ptr != 1) 125261909Sluigi return -1; 126261909Sluigi 127261909Sluigi for (ii = 0; ii < pad; ii++) { 128261909Sluigi if (*--pad_ptr != 0xFF) 129261909Sluigi return -1; 130261909Sluigi } 131341477Svmaffione 132261909Sluigi if (*--pad_ptr != 0) 133261909Sluigi return -1; 134261909Sluigi 135261909Sluigi for (ii = 0; ii < sizeof(padding); ii++) { 136261909Sluigi if (*--pad_ptr != padding[ii]) 137341477Svmaffione return -1; 138261909Sluigi } 139341477Svmaffione 140341477Svmaffione for (ii = 0; ii < 32; ii++) { 141341477Svmaffione if (*--pad_ptr != hash[ii]) 142341477Svmaffione return -1; 143341477Svmaffione } 144261909Sluigi return 0; 145261909Sluigi} 146261909Sluigi 147261909Sluigi/* 148261909Sluigi * Verify and extract the hash value from signature using the public key 149261909Sluigi * and compare it with calculated hash value. 150261909Sluigi */ 151261909Sluigistatic int zynq_rsa_verify_key(const struct zynq_rsa_public_key *key, 152261909Sluigi const u8 *sig, const u32 sig_len, const u8 *hash) 153261909Sluigi{ 154261909Sluigi int status; 155285349Sluigi void *buf; 156285349Sluigi 157285349Sluigi if (!key || !sig || !hash) 158285349Sluigi return -1; 159261909Sluigi 160261909Sluigi if (sig_len != (key->len * sizeof(u32))) { 161261909Sluigi printf("Signature is of incorrect length %d\n", sig_len); 162261909Sluigi return -1; 163261909Sluigi } 164261909Sluigi 165261909Sluigi /* Sanity check for stack size */ 166261909Sluigi if (sig_len > ZYNQ_RSA_SPK_SIGNATURE_SIZE) { 167261909Sluigi printf("Signature length %u exceeds maximum %d\n", sig_len, 168261909Sluigi ZYNQ_RSA_SPK_SIGNATURE_SIZE); 169261909Sluigi return -1; 170261909Sluigi } 171261909Sluigi 172261909Sluigi buf = malloc(sig_len); 173261909Sluigi if (!buf) 174285349Sluigi return -1; 175285349Sluigi 176285349Sluigi memcpy(buf, sig, sig_len); 177285349Sluigi 178261909Sluigi status = zynq_pow_mod((u32 *)key, (u32 *)buf); 179261909Sluigi if (status == -1) { 180261909Sluigi free(buf); 181261909Sluigi return status; 182341477Svmaffione } 183270063Sluigi 184261909Sluigi status = zynq_pad_and_check((u8 *)buf, (u8 *)hash); 185341477Svmaffione 186341477Svmaffione free(buf); 187341477Svmaffione return status; 188341477Svmaffione} 189341477Svmaffione 190261909Sluigi/* 191341477Svmaffione * Authenticate the partition 192341477Svmaffione */ 193341477Svmaffionestatic int zynq_authenticate_part(u8 *buffer, u32 size) 194341477Svmaffione{ 195261909Sluigi u8 hash_signature[32]; 196341477Svmaffione u8 *spk_modular; 197341477Svmaffione u8 *spk_modular_ex; 198261909Sluigi u8 *signature_ptr; 199341477Svmaffione u32 status; 200341477Svmaffione 201341477Svmaffione debug("%s\n", __func__); 202341477Svmaffione 203341477Svmaffione signature_ptr = (u8 *)(buffer + size - ZYNQ_RSA_SIGNATURE_SIZE); 204341477Svmaffione 205261909Sluigi signature_ptr += ZYNQ_RSA_HEADER_SIZE; 206261909Sluigi 207261909Sluigi signature_ptr += ZYNQ_RSA_MAGIC_WORD_SIZE; 208341477Svmaffione 209341477Svmaffione ppkmodular = (u8 *)signature_ptr; 210341477Svmaffione signature_ptr += ZYNQ_RSA_MODULAR_SIZE; 211341477Svmaffione ppkmodularex = signature_ptr; 212261909Sluigi signature_ptr += ZYNQ_RSA_MODULAR_EXT_SIZE; 213341477Svmaffione signature_ptr += ZYNQ_RSA_EXPO_SIZE; 214341477Svmaffione 215341477Svmaffione sha256_csum_wd((const unsigned char *)signature_ptr, 216341477Svmaffione (ZYNQ_RSA_MODULAR_EXT_SIZE + ZYNQ_RSA_EXPO_SIZE + 217341477Svmaffione ZYNQ_RSA_MODULAR_SIZE), 218341477Svmaffione (unsigned char *)hash_signature, 0x1000); 219261909Sluigi 220341477Svmaffione spk_modular = (u8 *)signature_ptr; 221261909Sluigi signature_ptr += ZYNQ_RSA_MODULAR_SIZE; 222341477Svmaffione spk_modular_ex = (u8 *)signature_ptr; 223341477Svmaffione signature_ptr += ZYNQ_RSA_MODULAR_EXT_SIZE; 224341477Svmaffione signature_ptr += ZYNQ_RSA_EXPO_SIZE; 225261909Sluigi 226341477Svmaffione public_key.len = ZYNQ_RSA_MODULAR_SIZE / sizeof(u32); 227341477Svmaffione public_key.modulus = (u32 *)ppkmodular; 228341477Svmaffione public_key.rr = (u32 *)ppkmodularex; 229341477Svmaffione public_key.n0inv = zynq_calc_inv(); 230341477Svmaffione 231261909Sluigi status = zynq_rsa_verify_key(&public_key, signature_ptr, 232261909Sluigi ZYNQ_RSA_SPK_SIGNATURE_SIZE, 233261909Sluigi hash_signature); 234261909Sluigi if (status) 235341477Svmaffione return status; 236270063Sluigi 237261909Sluigi signature_ptr += ZYNQ_RSA_SPK_SIGNATURE_SIZE; 238341477Svmaffione 239341477Svmaffione sha256_csum_wd((const unsigned char *)buffer, 240341477Svmaffione (size - ZYNQ_RSA_PARTITION_SIGNATURE_SIZE), 241341477Svmaffione (unsigned char *)hash_signature, 0x1000); 242261909Sluigi 243341477Svmaffione public_key.len = ZYNQ_RSA_MODULAR_SIZE / sizeof(u32); 244341477Svmaffione public_key.modulus = (u32 *)spk_modular; 245341477Svmaffione public_key.rr = (u32 *)spk_modular_ex; 246341477Svmaffione public_key.n0inv = zynq_calc_inv(); 247261909Sluigi 248341477Svmaffione return zynq_rsa_verify_key(&public_key, (u8 *)signature_ptr, 249341477Svmaffione ZYNQ_RSA_PARTITION_SIGNATURE_SIZE, 250341477Svmaffione (u8 *)hash_signature); 251341477Svmaffione} 252341477Svmaffione 253341477Svmaffione/* 254341477Svmaffione * Parses the partition header and verfies the authenticated and 255341477Svmaffione * encrypted image. 256341477Svmaffione */ 257341477Svmaffionestatic int zynq_verify_image(u32 src_ptr) 258261909Sluigi{ 259341477Svmaffione u32 silicon_ver, image_base_addr, status; 260341477Svmaffione u32 partition_num = 0; 261341477Svmaffione u32 efuseval, srcaddr, size, fsbl_len; 262341477Svmaffione struct partition_hdr *hdr_ptr; 263341477Svmaffione u32 part_data_len, part_img_len, part_attr; 264341477Svmaffione u32 part_load_addr, part_dst_addr, part_chksum_offset; 265341477Svmaffione u32 part_start_addr, part_total_size, partitioncount; 266341477Svmaffione bool encrypt_part_flag = false; 267341477Svmaffione bool part_chksum_flag = false; 268341477Svmaffione bool signed_part_flag = false; 269341477Svmaffione 270341477Svmaffione image_base_addr = src_ptr; 271341477Svmaffione 272341477Svmaffione silicon_ver = zynq_get_silicon_version(); 273341477Svmaffione 274341477Svmaffione /* RSA not supported in silicon versions 1.0 and 2.0 */ 275341477Svmaffione if (silicon_ver == 0 || silicon_ver == 1) 276341477Svmaffione return -1; 277341477Svmaffione 278341477Svmaffione zynq_get_partition_info(image_base_addr, &fsbl_len, 279341477Svmaffione &part_hdr[0]); 280341477Svmaffione 281341477Svmaffione /* Extract ppk if efuse was blown Otherwise return error */ 282261909Sluigi efuseval = readl(&efuse_base->status); 283261909Sluigi if (!(efuseval & ZYNQ_EFUSE_RSA_ENABLE_MASK)) 284261909Sluigi return -1; 285261909Sluigi 286261909Sluigi zynq_extract_ppk(fsbl_len); 287261909Sluigi 288261909Sluigi partitioncount = zynq_get_part_count(&part_hdr[0]); 289261909Sluigi 290261909Sluigi /* 291261909Sluigi * As the first two partitions are related to fsbl, 292261909Sluigi * we can ignore those two in bootimage and the below 293261909Sluigi * code doesn't need to validate it as fsbl is already 294261909Sluigi * done by now 295261909Sluigi */ 296261909Sluigi if (partitioncount <= 2 || 297261909Sluigi partitioncount > ZYNQ_MAX_PARTITION_NUMBER) 298261909Sluigi return -1; 299261909Sluigi 300261909Sluigi while (partition_num < partitioncount) { 301261909Sluigi if (((part_hdr[partition_num].partitionattr & 302261909Sluigi ZYNQ_ATTRIBUTE_RSA_PART_OWNER_MASK) >> 16) != 303261909Sluigi ZYNQ_RSA_PART_OWNER_UBOOT) { 304261909Sluigi printf("UBOOT is not Owner for partition %d\n", 305261909Sluigi partition_num); 306261909Sluigi partition_num++; 307261909Sluigi continue; 308261909Sluigi } 309261909Sluigi hdr_ptr = &part_hdr[partition_num]; 310261909Sluigi status = zynq_validate_hdr(hdr_ptr); 311261909Sluigi if (status) 312261909Sluigi return status; 313341477Svmaffione 314261909Sluigi part_data_len = hdr_ptr->datawordlen; 315261909Sluigi part_img_len = hdr_ptr->imagewordlen; 316261909Sluigi part_attr = hdr_ptr->partitionattr; 317261909Sluigi part_load_addr = hdr_ptr->loadaddr; 318261909Sluigi part_chksum_offset = hdr_ptr->checksumoffset; 319261909Sluigi part_start_addr = hdr_ptr->partitionstart; 320261909Sluigi part_total_size = hdr_ptr->partitionwordlen; 321261909Sluigi 322261909Sluigi if (part_data_len != part_img_len) { 323261909Sluigi debug("Encrypted\n"); 324261909Sluigi encrypt_part_flag = true; 325261909Sluigi } 326261909Sluigi 327261909Sluigi if (part_attr & ZYNQ_ATTRIBUTE_CHECKSUM_TYPE_MASK) 328261909Sluigi part_chksum_flag = true; 329341477Svmaffione 330261909Sluigi if (part_attr & ZYNQ_ATTRIBUTE_RSA_PRESENT_MASK) { 331261909Sluigi debug("RSA Signed\n"); 332261909Sluigi signed_part_flag = true; 333261909Sluigi size = part_total_size << WORD_LENGTH_SHIFT; 334261909Sluigi } else { 335261909Sluigi size = part_img_len; 336261909Sluigi } 337261909Sluigi 338285349Sluigi if (!signed_part_flag && !part_chksum_flag) { 339285349Sluigi printf("Partition not signed & no chksum\n"); 340261909Sluigi partition_num++; 341261909Sluigi continue; 342261909Sluigi } 343261909Sluigi 344341477Svmaffione srcaddr = image_base_addr + 345261909Sluigi (part_start_addr << WORD_LENGTH_SHIFT); 346261909Sluigi 347261909Sluigi /* 348261909Sluigi * This validation is just for PS DDR. 349341477Svmaffione * TODO: Update this for PL DDR check as well. 350341477Svmaffione */ 351261909Sluigi if (part_load_addr < gd->bd->bi_dram[0].start && 352261909Sluigi ((part_load_addr + part_data_len) > 353261909Sluigi (gd->bd->bi_dram[0].start + 354341477Svmaffione gd->bd->bi_dram[0].size))) { 355285349Sluigi printf("INVALID_LOAD_ADDRESS_FAIL\n"); 356341477Svmaffione return -1; 357285349Sluigi } 358341477Svmaffione 359341477Svmaffione if (part_attr & ZYNQ_ATTRIBUTE_PL_IMAGE_MASK) 360341477Svmaffione part_load_addr = srcaddr; 361341477Svmaffione else 362341477Svmaffione memcpy((u32 *)part_load_addr, (u32 *)srcaddr, 363341477Svmaffione size); 364341477Svmaffione 365341477Svmaffione if (part_chksum_flag) { 366341477Svmaffione part_chksum_offset = image_base_addr + 367285349Sluigi (part_chksum_offset << 368261909Sluigi WORD_LENGTH_SHIFT); 369341477Svmaffione status = zynq_validate_partition(part_load_addr, 370261909Sluigi (part_total_size << 371261909Sluigi WORD_LENGTH_SHIFT), 372261909Sluigi part_chksum_offset); 373261909Sluigi if (status != 0) { 374261909Sluigi printf("PART_CHKSUM_FAIL\n"); 375261909Sluigi return -1; 376261909Sluigi } 377261909Sluigi debug("Partition Validation Done\n"); 378261909Sluigi } 379261909Sluigi 380261909Sluigi if (signed_part_flag) { 381261909Sluigi status = zynq_authenticate_part((u8 *)part_load_addr, 382267128Sluigi size); 383261909Sluigi if (status != 0) { 384261909Sluigi printf("AUTHENTICATION_FAIL\n"); 385261909Sluigi return -1; 386261909Sluigi } 387341477Svmaffione debug("Authentication Done\n"); 388341477Svmaffione } 389261909Sluigi 390261909Sluigi if (encrypt_part_flag) { 391261909Sluigi debug("DECRYPTION\n"); 392261909Sluigi 393261909Sluigi part_dst_addr = part_load_addr; 394261909Sluigi 395267128Sluigi if (part_attr & ZYNQ_ATTRIBUTE_PL_IMAGE_MASK) { 396261909Sluigi partition_num++; 397261909Sluigi continue; 398261909Sluigi } 399261909Sluigi 400261909Sluigi status = zynq_decrypt_load(part_load_addr, 401261909Sluigi part_img_len, 402261909Sluigi part_dst_addr, 403261909Sluigi part_data_len, 404261909Sluigi BIT_NONE); 405261909Sluigi if (status != 0) { 406261909Sluigi printf("DECRYPTION_FAIL\n"); 407261909Sluigi return -1; 408261909Sluigi } 409261909Sluigi } 410341477Svmaffione partition_num++; 411261909Sluigi } 412261909Sluigi 413261909Sluigi return 0; 414261909Sluigi} 415261909Sluigi 416261909Sluigistatic int do_zynq_rsa(struct cmd_tbl *cmdtp, int flag, int argc, 417341477Svmaffione char *const argv[]) 418341477Svmaffione{ 419285349Sluigi u32 src_ptr; 420285349Sluigi char *endp; 421261909Sluigi 422261909Sluigi if (argc != cmdtp->maxargs) 423341477Svmaffione return CMD_RET_FAILURE; 424341477Svmaffione 425341477Svmaffione src_ptr = hextoul(argv[2], &endp); 426341477Svmaffione if (*argv[2] == 0 || *endp != 0) 427341477Svmaffione return CMD_RET_USAGE; 428341477Svmaffione 429341477Svmaffione if (zynq_verify_image(src_ptr)) 430341477Svmaffione return CMD_RET_FAILURE; 431341477Svmaffione 432341477Svmaffione return CMD_RET_SUCCESS; 433341477Svmaffione} 434341477Svmaffione#endif 435341477Svmaffione 436341477Svmaffione#ifdef CONFIG_CMD_ZYNQ_AES 437341477Svmaffionestatic int zynq_decrypt_image(struct cmd_tbl *cmdtp, int flag, int argc, 438341477Svmaffione char *const argv[]) 439341477Svmaffione{ 440341477Svmaffione char *endp; 441341477Svmaffione u32 srcaddr, srclen, dstaddr, dstlen; 442341477Svmaffione int status; 443341477Svmaffione u8 imgtype = BIT_NONE; 444342033Svmaffione 445341477Svmaffione if (argc < 5 && argc > cmdtp->maxargs) 446341477Svmaffione return CMD_RET_USAGE; 447341477Svmaffione 448341477Svmaffione if (argc == 5) { 449341477Svmaffione if (!strcmp("load", argv[2])) 450341477Svmaffione imgtype = BIT_FULL; 451341477Svmaffione else if (!strcmp("loadp", argv[2])) 452341477Svmaffione imgtype = BIT_PARTIAL; 453341477Svmaffione else 454341477Svmaffione return CMD_RET_USAGE; 455341477Svmaffione 456341477Svmaffione srcaddr = hextoul(argv[3], &endp); 457341477Svmaffione if (*argv[3] == 0 || *endp != 0) 458341477Svmaffione return CMD_RET_USAGE; 459341477Svmaffione srclen = hextoul(argv[4], &endp); 460341477Svmaffione if (*argv[4] == 0 || *endp != 0) 461341477Svmaffione return CMD_RET_USAGE; 462341477Svmaffione 463341477Svmaffione dstaddr = 0xFFFFFFFF; 464341477Svmaffione dstlen = srclen; 465341477Svmaffione } else { 466341477Svmaffione srcaddr = hextoul(argv[2], &endp); 467341477Svmaffione if (*argv[2] == 0 || *endp != 0) 468341477Svmaffione return CMD_RET_USAGE; 469341477Svmaffione srclen = hextoul(argv[3], &endp); 470341477Svmaffione if (*argv[3] == 0 || *endp != 0) 471341477Svmaffione return CMD_RET_USAGE; 472341477Svmaffione dstaddr = hextoul(argv[4], &endp); 473341477Svmaffione if (*argv[4] == 0 || *endp != 0) 474341477Svmaffione return CMD_RET_USAGE; 475341477Svmaffione dstlen = hextoul(argv[5], &endp); 476341477Svmaffione if (*argv[5] == 0 || *endp != 0) 477341477Svmaffione return CMD_RET_USAGE; 478341477Svmaffione } 479341477Svmaffione 480341477Svmaffione /* 481341477Svmaffione * Roundup source and destination lengths to 482341477Svmaffione * word size 483341477Svmaffione */ 484341477Svmaffione if (srclen % 4) 485341477Svmaffione srclen = roundup(srclen, 4); 486341477Svmaffione if (dstlen % 4) 487261909Sluigi dstlen = roundup(dstlen, 4); 488341477Svmaffione 489341477Svmaffione status = zynq_decrypt_load(srcaddr, srclen >> 2, dstaddr, 490341477Svmaffione dstlen >> 2, imgtype); 491342033Svmaffione if (status != 0) 492341477Svmaffione return CMD_RET_FAILURE; 493341477Svmaffione 494341477Svmaffione return CMD_RET_SUCCESS; 495341477Svmaffione} 496341477Svmaffione#endif 497341477Svmaffione 498341477Svmaffionestatic struct cmd_tbl zynq_commands[] = { 499261909Sluigi#ifdef CONFIG_CMD_ZYNQ_RSA 500341477Svmaffione U_BOOT_CMD_MKENT(rsa, 3, 1, do_zynq_rsa, "", ""), 501341477Svmaffione#endif 502341477Svmaffione#ifdef CONFIG_CMD_ZYNQ_AES 503341477Svmaffione U_BOOT_CMD_MKENT(aes, 6, 1, zynq_decrypt_image, "", ""), 504341477Svmaffione#endif 505341477Svmaffione}; 506261909Sluigi 507261909Sluigistatic int do_zynq(struct cmd_tbl *cmdtp, int flag, int argc, 508261909Sluigi char *const argv[]) 509261909Sluigi{ 510261909Sluigi struct cmd_tbl *zynq_cmd; 511261909Sluigi int ret; 512261909Sluigi 513261909Sluigi if (!ARRAY_SIZE(zynq_commands)) { 514261909Sluigi puts("No zynq specific command enabled\n"); 515261909Sluigi return CMD_RET_USAGE; 516261909Sluigi } 517261909Sluigi 518261909Sluigi if (argc < 2) 519341477Svmaffione return CMD_RET_USAGE; 520261909Sluigi zynq_cmd = find_cmd_tbl(argv[1], zynq_commands, 521261909Sluigi ARRAY_SIZE(zynq_commands)); 522261909Sluigi if (!zynq_cmd) 523261909Sluigi return CMD_RET_USAGE; 524261909Sluigi 525261909Sluigi ret = zynq_cmd->cmd(zynq_cmd, flag, argc, argv); 526261909Sluigi 527261909Sluigi return cmd_process_error(zynq_cmd, ret); 528267128Sluigi} 529261909Sluigi 530267128SluigiU_BOOT_LONGHELP(zynq, 531261909Sluigi "" 532261909Sluigi#ifdef CONFIG_CMD_ZYNQ_RSA 533261909Sluigi "rsa <baseaddr> - Verifies the authenticated and encrypted\n" 534261909Sluigi " zynq images and loads them back to load\n" 535267128Sluigi " addresses as specified in BOOT image(BOOT.BIN)\n" 536261909Sluigi#endif 537261909Sluigi#ifdef CONFIG_CMD_ZYNQ_AES 538261909Sluigi "aes <srcaddr> <srclen> <dstaddr> <dstlen>\n" 539261909Sluigi " - Decrypts the encrypted image present in source\n" 540341477Svmaffione " address and places the decrypted image at\n" 541261909Sluigi " destination address\n" 542261909Sluigi "aes load <srcaddr> <srclen>\n" 543261909Sluigi "aes loadp <srcaddr> <srclen>\n" 544261909Sluigi " if operation type is load or loadp, it loads the encrypted\n" 545261909Sluigi " full or partial bitstream on to PL respectively.\n" 546261909Sluigi#endif 547341477Svmaffione ); 548341477Svmaffione 549261909SluigiU_BOOT_CMD(zynq, 6, 0, do_zynq, 550261909Sluigi "Zynq specific commands", zynq_help_text 551261909Sluigi); 552261909Sluigi