mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-12-30 15:03:18 +00:00
37e3a36a54
This patch basically adds two new commands for loadig secure images. 1. zynq rsa adds support to load secure image which can be both authenticated or encrypted or both authenticated and encrypted image in xilinx bootimage(BOOT.bin) format. 2. zynq aes command adds support to decrypt and load encrypted image back to DDR as per destination address. The image has to be encrypted using xilinx bootgen tool and to get only the encrypted image from tool use -split option while invoking bootgen. Signed-off-by: Siva Durga Prasad Paladugu <siva.durga.paladugu@xilinx.com> Signed-off-by: Michal Simek <michal.simek@xilinx.com>
143 lines
3.1 KiB
C
143 lines
3.1 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* Copyright (C) 2018 Xilinx, Inc.
|
|
*/
|
|
|
|
#include <common.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>
|
|
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
#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], 0x10000);
|
|
|
|
if (!memcmp(checksum, calchecksum, MD5_CHECKSUM_SIZE))
|
|
return 0;
|
|
|
|
printf("Error: Partition DataChecksum\n");
|
|
return -1;
|
|
}
|