1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2018 Xilinx, Inc. 4 */ 5 6 #include <common.h> 7 #include <asm/io.h> 8 #include <asm/arch/hardware.h> 9 #include <asm/arch/sys_proto.h> 10 #include <u-boot/md5.h> 11 #include <zynq_bootimg.h> 12 13 DECLARE_GLOBAL_DATA_PTR; 14 15 #define ZYNQ_IMAGE_PHDR_OFFSET 0x09C 16 #define ZYNQ_IMAGE_FSBL_LEN_OFFSET 0x040 17 #define ZYNQ_PART_HDR_CHKSUM_WORD_COUNT 0x0F 18 #define ZYNQ_PART_HDR_WORD_COUNT 0x10 19 #define ZYNQ_MAXIMUM_IMAGE_WORD_LEN 0x40000000 20 #define MD5_CHECKSUM_SIZE 16 21 22 struct headerarray { 23 u32 fields[16]; 24 }; 25 26 /* 27 * Check whether the given partition is last partition or not 28 */ 29 static int zynq_islastpartition(struct headerarray *head) 30 { 31 int index; 32 33 debug("%s\n", __func__); 34 if (head->fields[ZYNQ_PART_HDR_CHKSUM_WORD_COUNT] != 0xFFFFFFFF) 35 return -1; 36 37 for (index = 0; index < ZYNQ_PART_HDR_WORD_COUNT - 1; index++) { 38 if (head->fields[index] != 0x0) 39 return -1; 40 } 41 42 return 0; 43 } 44 45 /* 46 * Get the partition count from the partition header 47 */ 48 int zynq_get_part_count(struct partition_hdr *part_hdr_info) 49 { 50 u32 count; 51 struct headerarray *hap; 52 53 debug("%s\n", __func__); 54 55 for (count = 0; count < ZYNQ_MAX_PARTITION_NUMBER; count++) { 56 hap = (struct headerarray *)&part_hdr_info[count]; 57 if (zynq_islastpartition(hap) != -1) 58 break; 59 } 60 61 return count; 62 } 63 64 /* 65 * Get the partition info of all the partitions available. 66 */ 67 int zynq_get_partition_info(u32 image_base_addr, u32 *fsbl_len, 68 struct partition_hdr *part_hdr) 69 { 70 u32 parthdroffset; 71 72 *fsbl_len = *((u32 *)(image_base_addr + ZYNQ_IMAGE_FSBL_LEN_OFFSET)); 73 74 parthdroffset = *((u32 *)(image_base_addr + ZYNQ_IMAGE_PHDR_OFFSET)); 75 76 parthdroffset += image_base_addr; 77 78 memcpy(part_hdr, (u32 *)parthdroffset, 79 (sizeof(struct partition_hdr) * ZYNQ_MAX_PARTITION_NUMBER)); 80 81 return 0; 82 } 83 84 /* 85 * Check whether the partition header is valid or not 86 */ 87 int zynq_validate_hdr(struct partition_hdr *header) 88 { 89 struct headerarray *hap; 90 u32 index; 91 u32 checksum; 92 93 debug("%s\n", __func__); 94 95 hap = (struct headerarray *)header; 96 97 for (index = 0; index < ZYNQ_PART_HDR_WORD_COUNT; index++) { 98 if (hap->fields[index]) 99 break; 100 } 101 if (index == ZYNQ_PART_HDR_WORD_COUNT) 102 return -1; 103 104 checksum = 0; 105 for (index = 0; index < ZYNQ_PART_HDR_CHKSUM_WORD_COUNT; index++) 106 checksum += hap->fields[index]; 107 108 checksum ^= 0xFFFFFFFF; 109 110 if (hap->fields[ZYNQ_PART_HDR_CHKSUM_WORD_COUNT] != checksum) { 111 printf("Error: Checksum 0x%8.8x != 0x%8.8x\n", 112 checksum, hap->fields[ZYNQ_PART_HDR_CHKSUM_WORD_COUNT]); 113 return -1; 114 } 115 116 if (header->imagewordlen > ZYNQ_MAXIMUM_IMAGE_WORD_LEN) { 117 printf("INVALID_PARTITION_LENGTH\n"); 118 return -1; 119 } 120 121 return 0; 122 } 123 124 /* 125 * Validate the partition by calculationg the md5 checksum for the 126 * partition and compare with checksum present in checksum offset of 127 * partition 128 */ 129 int zynq_validate_partition(u32 start_addr, u32 len, u32 chksum_off) 130 { 131 u8 checksum[MD5_CHECKSUM_SIZE]; 132 u8 calchecksum[MD5_CHECKSUM_SIZE]; 133 134 memcpy(&checksum[0], (u32 *)chksum_off, MD5_CHECKSUM_SIZE); 135 136 md5_wd((u8 *)start_addr, len, &calchecksum[0], 0x10000); 137 138 if (!memcmp(checksum, calchecksum, MD5_CHECKSUM_SIZE)) 139 return 0; 140 141 printf("Error: Partition DataChecksum\n"); 142 return -1; 143 } 144