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