This commit is contained in:
2025-12-24 17:21:08 +09:00
parent a96323de19
commit 96dc62d8dc
2302 changed files with 455822 additions and 0 deletions

View File

@@ -0,0 +1,309 @@
// SPDX-License-Identifier: BSD-2-Clause
/*
* Copyright (C) 2017 The Android Open Source Project
*/
#include <android_ab.h>
#include <android_bootloader_message.h>
#include <log.h>
#include <string.h>
#include <errno.h>
#ifndef ENODATA
#define ENODATA 61
#endif
#include <crc.h>
#include <dma.h>
#include <mem_io.h>
#include <rpc.h>
#include <rpcqspidrv.h>
#include <spiflash2drv.h>
#include <image_load_flash.h>
typedef unsigned long int ulong;
typedef uint32_t u32;
#define typeof(x) __typeof__(x)
#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#define QSPI_MISC_START (FLASH_BASE + 0x00740000U)
#define QSPI_AB_OFFSET (2048)
#define QSPI_AB_CONTROL (QSPI_MISC_START + QSPI_AB_OFFSET)
#define QSPI_AB_SIZE (1024U)
#include <remap.h>
#undef DISK_BUFFER_ADDR
#define DISK_BUFFER_ADDR (BASE_RTSRAM_ADDR + (0x0002E000U)) // 0xEB22E000U
volatile uint8_t *_disk_buffer = 0;
#undef AB_INFO_FLAG_ADDR
#define AB_INFO_FLAG_ADDR (BASE_RTSRAM_ADDR + (0x0002FFFCU)) // 0xEB22FFFCU
#define TMP_BUFFER_ADDR (BASE_RTSRAM_ADDR + (0x0002D000U)) // 0xEB22D000U
/**
* Compute the CRC-32 of the bootloader control struct.
*
* Only the bytes up to the crc32_le field are considered for the CRC-32
* calculation.
*
* @param[in] abc bootloader control block
*
* @return crc32 sum
*/
static uint32_t ab_control_compute_crc(struct bootloader_control *abc)
{
return crc32(0, (void *)abc, offsetof(typeof(*abc), crc32_le));
}
/**
* Initialize bootloader_control to the default value.
*
* It allows us to boot all slots in order from the first one. This value
* should be used when the bootloader message is corrupted, but not when
* a valid message indicates that all slots are unbootable.
*
* @param[in] abc bootloader control block
*
* @return 0 on success and a negative on error
*/
static int ab_control_default(struct bootloader_control *abc)
{
int i;
const struct slot_metadata metadata = {
.priority = 15,
.tries_remaining = 7,
.successful_boot = 0,
.verity_corrupted = 0,
.reserved = 0
};
if (!abc)
return -EFAULT;
memcpy(abc->slot_suffix, "a\0\0\0", 4);
abc->magic = BOOT_CTRL_MAGIC;
abc->version = BOOT_CTRL_VERSION;
abc->nb_slot = NUM_SLOTS;
memset(abc->reserved0, 0, sizeof(abc->reserved0));
for (i = 0; i < abc->nb_slot; ++i)
abc->slot_info[i] = metadata;
memset(abc->reserved1, 0, sizeof(abc->reserved1));
abc->crc32_le = ab_control_compute_crc(abc);
return 0;
}
/**
* Load the boot_control struct from disk into newly allocated memory.
*
* This function allocates and returns an integer number of disk blocks,
* based on the block size of the passed device to help performing a
* read-modify-write operation on the boot_control struct.
* The boot_control struct offset (2 KiB) must be a multiple of the device
* block size, for simplicity.
*
* @param[out] pointer to pointer to bootloader_control data
* @return 0 on success and a negative on error
*/
static int ab_control_create_from_disk(struct bootloader_control **abc)
{
uint32_t phys_dst = remap_get_phys_addr(DISK_BUFFER_ADDR); // 0xEB22E000U
uint32_t phys_src = QSPI_AB_CONTROL;
uint32_t size = QSPI_AB_SIZE;
/* Load content */
dma_trans_start(phys_dst, phys_src, size);
/* End loading */
load_end();
*abc = (struct bootloader_control *)_disk_buffer;
return 0;
}
/**
* Store the loaded boot_control block.
*
* Store back to the same location it was read from with
* ab_control_create_from_misc().
*
* @return 0 on success and a negative on error
*/
static int ab_control_store(struct bootloader_control *abc)
{
uint32_t phys_dst = QSPI_AB_CONTROL;
uint32_t phys_src = remap_get_phys_addr((uint32_t)abc);
uint32_t size = sizeof(struct bootloader_control);
init_rpc_qspi_flash();
qspi_flash_rw_init();
NOTICE("we're storing bootloader control block.(%d)\n", size);
phys_dst -= FLASH_BASE;
/* Sector Erase */
sector_erase_qspi_flash(phys_dst, phys_dst + 4096 - 1);
clear_bp_qspi_flash();
save_data_with_buf_qspi_flash(phys_src, phys_dst, size);
/* set read mode, it's slower than before */
init_rpc_qspi_flash_4fastread_ext_mode();
return 0;
}
/**
* Compare two slots.
*
* The function determines slot which is should we boot from among the two.
*
* @param[in] a The first bootable slot metadata
* @param[in] b The second bootable slot metadata
* @return Negative if the slot "a" is better, positive of the slot "b" is
* better or 0 if they are equally good.
*/
static int ab_compare_slots(const struct slot_metadata *a,
const struct slot_metadata *b)
{
/* Higher priority is better */
if (a->priority != b->priority)
return b->priority - a->priority;
/* Higher successful_boot value is better, in case of same priority */
if (a->successful_boot != b->successful_boot)
return b->successful_boot - a->successful_boot;
/* Higher tries_remaining is better to ensure round-robin */
if (a->tries_remaining != b->tries_remaining)
return b->tries_remaining - a->tries_remaining;
return 0;
}
int ab_select_slot(void)
{
struct bootloader_control *abc = NULL;
u32 crc32_le;
int slot, i, ret;
bool store_needed = false;
char slot_suffix[4];
// uint32_t ab_info_addr = remap_get_phys_addr(AB_INFO_FLAG_ADDR); // 0xEB22FFFCU
_disk_buffer = (uint8_t *)(DISK_BUFFER_ADDR); // 0xEB22E000U
mem_write32(AB_INFO_FLAG_ADDR, AB_INFO_FLAG_INIT);
ret = ab_control_create_from_disk(&abc);
if (ret < 0) {
/*
* This condition represents an actual problem with the code or
* the board setup, like an invalid partition information.
* Signal a repair mode and do not try to boot from either slot.
*/
return ret;
}
crc32_le = ab_control_compute_crc(abc);
if (abc->crc32_le != crc32_le) {
ERROR("Invalid CRC-32 (expected %.8x, found %.8x),"
"re-initializing A/B metadata.\n", crc32_le, abc->crc32_le);
ret = ab_control_default(abc);
if (ret < 0) {
// free(abc);
return -ENODATA;
}
store_needed = true;
}
if (abc->magic != BOOT_CTRL_MAGIC) {
ERROR("Unknown A/B metadata: %.8x\n", abc->magic);
// free(abc);
return -ENODATA;
}
if (abc->version > BOOT_CTRL_VERSION) {
ERROR("Unsupported A/B metadata version: %.8x\n", abc->version);
// free(abc);
return -ENODATA;
}
/*
* At this point a valid boot control metadata is stored in abc,
* followed by other reserved data in the same block. We select a with
* the higher priority slot that
* - is not marked as corrupted and
* - either has tries_remaining > 0 or successful_boot is true.
* If the selected slot has a false successful_boot, we also decrement
* the tries_remaining until it eventually becomes unbootable because
* tries_remaining reaches 0. This mechanism produces a bootloader
* induced rollback, typically right after a failed update.
*/
/* Safety check: limit the number of slots. */
if (abc->nb_slot > ARRAY_SIZE(abc->slot_info)) {
abc->nb_slot = ARRAY_SIZE(abc->slot_info);
NOTICE("[%s:%d] abc->nb_slot > ARRAY_SIZE(abc->slot_info)\n", __func__, __LINE__);
store_needed = true;
}
slot = -1;
for (i = 0; i < abc->nb_slot; ++i) {
if (abc->slot_info[i].verity_corrupted ||
!abc->slot_info[i].tries_remaining) {
NOTICE("unbootable slot %d tries: %d, corrupt: %d\n",
i, abc->slot_info[i].tries_remaining,
abc->slot_info[i].verity_corrupted);
continue;
}
NOTICE("bootable slot %d pri: %d, tries: %d, "
"corrupt: %d, successful: %d\n",
i, abc->slot_info[i].priority,
abc->slot_info[i].tries_remaining,
abc->slot_info[i].verity_corrupted,
abc->slot_info[i].successful_boot);
if (slot < 0 ||
ab_compare_slots(&abc->slot_info[i],
&abc->slot_info[slot]) < 0) {
slot = i;
}
}
if (slot >= 0 && !abc->slot_info[slot].successful_boot) {
ERROR("Attempting slot %d, tries remaining %d\n",
slot, abc->slot_info[slot].tries_remaining);
abc->slot_info[slot].tries_remaining--;
store_needed = true;
}
if (slot >= 0) {
/*
* Legacy user-space requires this field to be set in the BCB.
* Newer releases load this slot suffix from the command line
* or the device tree.
*/
memset(slot_suffix, 0, sizeof(slot_suffix));
slot_suffix[0] = BOOT_SLOT_NAME(slot);
if (memcmp(abc->slot_suffix, slot_suffix, sizeof(slot_suffix))) {
NOTICE("slot_suffix is differ(%s:%s)\n",
abc->slot_suffix, slot_suffix);
memcpy(abc->slot_suffix, slot_suffix, sizeof(slot_suffix));
store_needed = true;
}
}
if (store_needed) {
abc->crc32_le = ab_control_compute_crc(abc);
ab_control_store(abc);
crc32_le = AB_INFO_FLAG_STORE;
}
else
crc32_le = AB_INFO_FLAG_OK;
// free(abc);
if (slot == 1)
crc32_le |= AB_INFO_SELECT_2nd;
mem_write32(AB_INFO_FLAG_ADDR, crc32_le);
if (slot < 0)
return -EINVAL;
return slot;
}

View File

@@ -0,0 +1,535 @@
/*******************************************************************************
* DISCLAIMER
* This software is supplied by Renesas Electronics Corporation and is only
* intended for use with Renesas products. No other uses are authorized. This
* software is owned by Renesas Electronics Corporation and is protected under
* all applicable laws, including copyright laws.
* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT
* LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.
* TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS
* ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE
* FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR
* ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE
* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* Renesas reserves the right, without notice, to make changes to this software
* and to discontinue the availability of this software. By using this software,
* you agree to the additional terms and conditions found by accessing the
* following link:
* http://www.renesas.com/disclaimer
* Copyright 2021-2025 Renesas Electronics Corporation All rights reserved.
*******************************************************************************/
/*******************************************************************************
* DESCRIPTION : Image load function
******************************************************************************/
/******************************************************************************
* @file image_load.c
* - Version : 0.14
* @brief Loading image driver.
* .
*****************************************************************************/
/******************************************************************************
* History : DD.MM.YYYY Version Description
* : 28.07.2021 0.01 First Release
* : 03.09.2021 0.02 Modify macro definition name.
* : 30.09.2021 0.03 Support of eMMC boot.
* : 15.10.2021 0.04 Fix a problem with overwriting the load area
* information in RTOS.
* modify Error log of check_load_area.
* Modify the process of outputting load
* information of Optionbyte to function.
* : 03.12.2021 0.05 Modify function "check_load_area" to check the
* boundary value of RT-VRAM(for virtual buffer).
* Fixed judgment of the top/end of the
* forwarding destination.
* : 06.01.2022 0.06 Support for two-stage boot of G4MH.
* : 23.05.2022 0.07 Support for updating the memory map.
* : 21.06.2022 0.08 Modify some function's arguments and add
* macros.
* : 05.08.2022 0.09 Add TFMV/NTFMV minimum version table
* information to load_init function.
* : 22.09.2022 0.10 Fix address range check for V4H.
* : 21.08.2023 0.11 Add support for V4M.
* : 15.01.2024 0.12 Add image_id initialization to load_init
* function.
* : 19.12.2024 0.13 Add RTOS#1, RTOS#2 image.
* : 26.05.2025 0.14 Change key cert address of [CA_OPTIONAL_ID+2].
*****************************************************************************/
/* indelude */
#include <stdint.h>
#include <image_load.h>
#include <remap.h>
#include <mem_io.h>
#include <log.h>
#include <rom_api.h>
#include <ram_def.h>
#if (RCAR_SA9_TYPE == FLASH_BOOT)
#include <image_load_flash.h>
#include <dma.h>
#elif (RCAR_SA9_TYPE == EMMC_BOOT)
#include <image_load_emmc.h>
#include <emmc_multiboot.h>
#include <emmc_def.h>
#endif
#define KEY_SIZE_FLG_MSK (0x00000003U)
#define KEY_SIZE_4096 (0x00000002U)
#define KEY_SIZE_3072 (0x00000001U)
#define KEY_SIZE_2048 (0x00000000U)
#define WORD_TO_BYTE (4U)
#define ERROR_PARAM (0U)
#define NOT_OVERLAP_FLAG (0U)
#define OVERLAP_FLAG (1U)
#define RAM_RANGE_OK (0U)
#define RAM_RANGE_NG (1U)
#if (BOOT_MCU != 0U)
#define RAM_MAX (5U)
#else
#define RAM_MAX (4U)
#endif /* (BOOT_MCU != 0U) */
/* Load Parameter of Secure data */
#define SRC_ADDR_OF_SECURE_DATA_FOR_ICUMXB (SRC_TOP + 0x00340000U)
#define DST_ADDR_OF_SECURE_DATA_FOR_ICUMXB (0xEB2E0000U)
#if (BOOT_MCU != 0U)
#define SRC_ADDR_OF_SECURE_DATA_FOR_ICUMH (SRC_TOP + 0x00440000U)
/* The destination address of Flash to RAM in the ICUMH Secure data is the top address of RT-VRAM. */
#endif
static void get_info_from_cert(uint32_t cert_addr, uint32_t *size,
uint32_t *dest_addr);
static void check_src_addr_range(uint32_t src, uint32_t len, uint32_t src_end);
static void check_dst_addr_range(uint32_t dst, uint32_t len, uint32_t dst_end);
static void check_overlap_images(uint32_t dst, uint32_t len, uint32_t dst_end);
uint32_t load_content_cert(int slot)
{
uint32_t load_num;
#if (RCAR_SA9_TYPE == FLASH_BOOT)
load_num = load_content_cert_for_flash(slot);
#elif (RCAR_SA9_TYPE == EMMC_BOOT)
load_num = load_content_cert_for_emmc();
#else
/* NoProcess */
#endif
return load_num;
}
/* End of function load_content_cert(void) */
void load_image(LOAD_INFO* li)
{
/* log output of load image for information */
#if (RCAR_SA9_TYPE == FLASH_BOOT)
load_image_info_print_for_flash(li);
#elif (RCAR_SA9_TYPE == EMMC_BOOT)
load_image_info_print_for_emmc(li);
#endif
/* Check transfer range of image. */
check_load_area(li);
/* Image load start. */
load_start(li);
}
/* End of function load_image(LOAD_INFO* li) */
void load_init(LOAD_INFO* li, int slot)
{
uint32_t loop;
uint32_t buf;
const char *image_name[MAX_PLACED] = {
[SECURE_FW_ID] = "Secure FW",
[RTOS_ID] = "RTOS",
[CA_PROGRAM_ID] = "Cx IPL",
[ICUMH_PROGRAM_ID] = "ICUMH",
[G4MH_PROGRAM_ID] = "G4MH(1st)",
[G4MH_PROGRAM_ID + 1] = "G4MH(2nd)",
[CA_OPTIONAL_ID] = "CA Program #1",
[CA_OPTIONAL_ID + 1] = "CA Program #2",
[CA_OPTIONAL_ID + 2] = "CA Program #3",
[CA_OPTIONAL_ID + 3] = "CA Program #4",
[CA_OPTIONAL_ID + 4] = "CA Program #5",
[CA_OPTIONAL_ID + 5] = "CA Program #6",
[CA_OPTIONAL_ID + 6] = "CA Program #7",
[CA_OPTIONAL_ID + 7] = "CA Program #8",
[TFMV_MIN_VER_TBL_ID] = "TFMV minimum version table",
[NTFMV_MIN_VER_TBL_ID] = "NTFMV minimum version table",
#if (RTOS_LOAD_NUM == RTOS_LOAD_NUM_3)
[RTOS1_ID] = "RTOS#1",
[RTOS2_ID] = "RTOS#2"
#endif /* RTOS_LOAD_NUM == RTOS_LOAD_NUM_3 */
};
const uint32_t key_cert[MAX_PLACED] = {
[SECURE_FW_ID] = TFMV_KEY_CERT_ADDR,
[RTOS_ID] = TFMV_KEY_CERT_ADDR,
[CA_PROGRAM_ID] = TFMV_KEY_CERT_ADDR,
[ICUMH_PROGRAM_ID] = TFMV_KEY_CERT_ADDR,
[G4MH_PROGRAM_ID] = TFMV_KEY_CERT_ADDR,
[G4MH_PROGRAM_ID + 1] = TFMV_KEY_CERT_ADDR,
[CA_OPTIONAL_ID] = TFMV_KEY_CERT_ADDR, /* bl31 */
#if (RCAR_LSI == RCAR_S4)
[CA_OPTIONAL_ID + 1] = TFMV_KEY_CERT_ADDR,
#elif ((RCAR_LSI == RCAR_V4H) || (RCAR_LSI == RCAR_V4M))
[CA_OPTIONAL_ID + 1] = NTFMV_KEY_CERT_ADDR, /* u-boot */
#endif
#if (OPTEE_LOAD_ENABLE == OPTEE_DISABLE)
[CA_OPTIONAL_ID + 2] = NTFMV_KEY_CERT_ADDR,
#else
[CA_OPTIONAL_ID + 2] = TFMV_KEY_CERT_ADDR, /* tee-os */
#endif
#if (BL2_LOAD_ENABLE == 0)
[CA_OPTIONAL_ID + 3] = NTFMV_KEY_CERT_ADDR,
#else
[CA_OPTIONAL_ID + 3] = TFMV_KEY_CERT_ADDR, /* ca76-loader */
#endif
[CA_OPTIONAL_ID + 4] = NTFMV_KEY_CERT_ADDR,
[CA_OPTIONAL_ID + 5] = NTFMV_KEY_CERT_ADDR,
[CA_OPTIONAL_ID + 6] = NTFMV_KEY_CERT_ADDR,
[CA_OPTIONAL_ID + 7] = NTFMV_KEY_CERT_ADDR,
[TFMV_MIN_VER_TBL_ID] = TFMV_KEY_CERT_ADDR,
[NTFMV_MIN_VER_TBL_ID] = NTFMV_KEY_CERT_ADDR,
#if (RTOS_LOAD_NUM == RTOS_LOAD_NUM_3)
[RTOS1_ID] = TFMV_KEY_CERT_ADDR,
[RTOS2_ID] = TFMV_KEY_CERT_ADDR
#endif /* RTOS_LOAD_NUM == RTOS_LOAD_NUM_3 */
};
/* Set Load info parameter */
for (loop = 0; loop < MAX_PLACED; loop++)
{
li[loop].name = image_name[loop];
li[loop].key_cert_addr = key_cert[loop];
li[loop].cnt_cert_addr = get_logic_cont_cert_addr(loop);
get_info_from_cert(li[loop].cnt_cert_addr, &li[loop].image_size, &li[loop].boot_addr);
buf = get_src_addr_offset_in_cert(loop);
li[loop].src_addr = (SRC_TOP + mem_read32(buf));
#if (RCAR_SA9_TYPE == FLASH_BOOT)
li[loop].src_addr += (slot * CONTENT_CERT_2nd_OFFSET);
#endif
li[loop].image_id = loop;
#if (RCAR_SA9_TYPE == EMMC_BOOT)
buf = get_part_num_in_cert(loop);
li[loop].part_num = mem_read32(buf);
#endif
}
}/* End of function load_init(LOAD_INFO* li) */
void check_load_area(const LOAD_INFO* li)
{
uint32_t src;
uint32_t dst;
uint32_t len;
uint32_t src_end;
uint32_t dst_end;
src = li->src_addr;
dst = li->boot_addr;
len = li->image_size;
/* Check whether source is overflow. */
check_overflow(src, len, &src_end, __func__);
/* Check whether destination is overflow. */
check_overflow(dst, len, &dst_end, __func__);
/* Check source address range. */
check_src_addr_range(src, len, src_end);
/* Check destination address range. */
check_dst_addr_range(dst, len, dst_end);
/* Check whether overlap destination address and images that have been loaded. */
check_overlap_images(dst, len, dst_end);
}
/* End of function check_load_area(const LOAD_INFO* li) */
static void get_info_from_cert(uint32_t cert_addr, uint32_t *size,
uint32_t *dest_addr)
{
uint32_t val;
uint32_t certInfo1;
uint32_t pSize;
uint32_t pDestL;
/* Get key length of content certificate. */
val = mem_read32(cert_addr + CERT_INFO_FLG_OFFSET);
certInfo1 = (val >> KEY_SIZE_BIT_SHIFT) & KEY_SIZE_FLG_MSK;
/* Get the transfer address and transfer size from
the certificate in accordance with the key length. */
if (KEY_SIZE_4096 == certInfo1) /* key size = 4096 */
{
pSize = cert_addr + CERT_INFO_SIZE_OFFSET2;
*size = mem_read32(pSize) * WORD_TO_BYTE;
pDestL = cert_addr + CERT_INFO_DST_OFFSET2;
*dest_addr = mem_read32(pDestL);
}
else if (KEY_SIZE_3072 == certInfo1) /* key size = 3072 */
{
pSize = cert_addr + CERT_INFO_SIZE_OFFSET1;
*size = mem_read32(pSize) * WORD_TO_BYTE;
pDestL = cert_addr + CERT_INFO_DST_OFFSET1;
*dest_addr = mem_read32(pDestL);
}
else if (KEY_SIZE_2048 == certInfo1) /* key size = 2048 */
{
pSize = cert_addr + CERT_INFO_SIZE_OFFSET;
*size = mem_read32(pSize) * WORD_TO_BYTE;
pDestL = cert_addr + CERT_INFO_DST_OFFSET;
*dest_addr = mem_read32(pDestL);
}
else
{
*size = ERROR_PARAM;
*dest_addr = ERROR_PARAM;
}
}
/* End of function get_info_from_cert(uint32_t cert_addr, uint32_t *size, uint32_t *dest_addr) */
void load_start(const LOAD_INFO* li)
{
#if (RCAR_SA9_TYPE == FLASH_BOOT)
dma_trans_start(li->boot_addr, li->src_addr, li->image_size);
#elif (RCAR_SA9_TYPE == EMMC_BOOT)
uint32_t rtn_val;
uint32_t sector_count;
uint32_t fraction;
/* Converted to number of sectors transferred. */
sector_count = li->image_size >> EMMC_SECTOR_SIZE_SHIFT;
fraction = li->image_size % EMMC_SECTOR_SIZE;
/* Add 1 if there is a fraction */
if(0U != fraction)
{
sector_count += 1U;
}
rtn_val = emmc_trans_data(li->part_num, (li->src_addr >> EMMC_SECTOR_SIZE_SHIFT),
li->boot_addr, sector_count);
if(EMMC_DEV_OK != rtn_val)
{
ERROR("load_start(emmc_trans_data error).\r\n");
panic;
}
#else
/* NoProcess */
#endif
}/* End of function load_start(LOAD_INFO* li) */
void load_end(void)
{
#if (RCAR_SA9_TYPE == FLASH_BOOT)
dma_trans_end_check();
#else
/* NoProcess */
#endif
}/* End of function load_end(void) */
void load_securedata(uint32_t target_id, int slot)
{
LOAD_INFO tmp_li;
if(target_id == SECURE_FW_ID) /* When secure data transfer for ICUMXB FW. */
{
tmp_li.image_size = SECUREDATA_SIZE;
tmp_li.src_addr = SRC_ADDR_OF_SECURE_DATA_FOR_ICUMXB;
#if (RCAR_SA9_TYPE == FLASH_BOOT)
tmp_li.src_addr += (slot * CONTENT_CERT_2nd_OFFSET);
#endif
tmp_li.boot_addr =DST_ADDR_OF_SECURE_DATA_FOR_ICUMXB;
#if (RCAR_SA9_TYPE == EMMC_BOOT)
tmp_li.part_num = EMMC_PARTITION_1;
#endif
}
#if (BOOT_MCU != 0U)
else if(target_id == ICUMH_PROGRAM_ID) /* When secure data transfer for ICUMH FW. */
{
tmp_li.image_size = SECUREDATA_SIZE;
tmp_li.src_addr = SRC_ADDR_OF_SECURE_DATA_FOR_ICUMH;
tmp_li.boot_addr = RTVRAM_BASE;
#if (RCAR_SA9_TYPE == EMMC_BOOT)
tmp_li.part_num = EMMC_PARTITION_1;
#endif
}
#endif
else
{
ERROR("Failed input parameter.\n");
panic;
}
load_start(&tmp_li);
}/* End of function load_securedata(uint32_t target_id) */
void check_overflow(uint32_t addr, uint32_t len, uint32_t *end_addr, const char *func_name)
{
/* Pre confirmation */
if (addr > (UINT32_MAX - len))
{
ERROR("1:overflow is occurred in %s.\n", func_name);
ERROR("1:address = 0x%x size = 0x%x\n", addr, len);
panic;
}
else
{
*end_addr = addr + len - 1U;
}
/* Post confirmation */
if (*end_addr < addr)
{
ERROR("2:overflow is occurred in %s.\n", func_name);
ERROR("2:address = 0x%x size = 0x%x\n", addr, len);
panic;
}
}
/* End of function check_overflow(uint32_t addr, uint32_t len, uint32_t *end_addr, char *func_name) */
static void check_src_addr_range(uint32_t src, uint32_t len, uint32_t src_end)
{
/* Check image size */
if (len == 0U)
{
ERROR("image size error\n");
panic;
}
#if (RCAR_SA9_TYPE == FLASH_BOOT)
if ((src < SRC_TOP) || (SRC_END < src_end))
#elif (RCAR_SA9_TYPE == EMMC_BOOT)
if (SRC_END < src_end)
#endif
{
ERROR("check load area (source address)\n");
ERROR("source address = 0x%x image size = 0x%x\n", src, len);
panic;
}
}
/* End of function check_src_addr_range(uint32_t src, uint32_t len, uint32_t src_end) */
static void check_dst_addr_range(uint32_t dst, uint32_t len, uint32_t dst_end)
{
uint32_t rge_chk_flg;
uint32_t loop;
/* The memory range of destination. */
const ADDRESS_RANGE add_list[RAM_MAX] = {
[TARGET_MEM_DRAM] = {DRAM_BASE, DRAM_END},
[TARGET_MEM_RTSRAM] = {RTSRAM_BASE, RTSRAM_END},
[TARGET_MEM_RTVRAM] = {RTVRAM_VBUF_TOP, RTVRAM_VBUF_END},
[TARGET_MEM_SYSRAM] = {SYSRAM_BASE, SYSRAM_END},
#if (BOOT_MCU != 0U)
[TARGET_MEM_CODESRAM] = {CODESRAM_BASE, CODESRAM_END}
#endif /* (BOOT_MCU != 0U) */
};
/* Check image size */
if (len == 0U)
{
ERROR("image size error\n");
panic;
}
rge_chk_flg = RAM_RANGE_NG;
for(loop = 0; loop < RAM_MAX; loop++)
{
if (add_list[loop].topadd <= dst)
{
if(dst_end <= add_list[loop].endadd)
{
rge_chk_flg = RAM_RANGE_OK;
break;
}
}
}
if(rge_chk_flg != RAM_RANGE_OK)
{
ERROR("check load area (destination address)\n");
ERROR("destination address = 0x%x image size = 0x%x\n", dst, len);
panic;
}
}
/* End of function check_dst_addr_range(uint32_t dst, uint32_t len, uint32_t dst_end) */
static void check_overlap_images(uint32_t dst, uint32_t len, uint32_t dst_end)
{
uint32_t overlap;
uint32_t loop;
static uint32_t s_num = 1U;
static ADDRESS_RANGE s_placed_image[MAX_PLACED + 1] = {
[0] = {IPL_TOP, IPL_END},
[1] = {0U,0U},
[2] = {0U,0U},
[3] = {0U,0U},
[4] = {0U,0U},
[5] = {0U,0U},
[6] = {0U,0U},
[7] = {0U,0U},
[8] = {0U,0U},
[9] = {0U,0U},
[10] = {0U,0U},
[11] = {0U,0U},
[12] = {0U,0U},
[13] = {0U,0U},
[14] = {0U,0U},
[15] = {0U,0U},
[16] = {0U,0U}
};
overlap = NOT_OVERLAP_FLAG;
loop = 0U;
do
{
/* check overlap */
if ((dst >= s_placed_image[loop].topadd) && (dst <= s_placed_image[loop].endadd))
{
overlap = OVERLAP_FLAG;
}
else if ((dst_end >= s_placed_image[loop].topadd) && (dst_end <= s_placed_image[loop].endadd))
{
overlap = OVERLAP_FLAG;
}
else if ((dst < s_placed_image[loop].topadd) && (s_placed_image[loop].endadd < dst_end))
{
overlap = OVERLAP_FLAG;
}
else
{
loop++;
}
} while ((loop < s_num) && (overlap == NOT_OVERLAP_FLAG));
/* Check the overlap flag. *
* Parameters are error if overwrite occurred. *
* Otherwise, add parameters of the image to be loaded into Placed_image. */
if (overlap == NOT_OVERLAP_FLAG)
{
s_placed_image[s_num].topadd = dst;
s_placed_image[s_num].endadd = dst_end;
INFO("[0x%x] topadd = 0x%x endadd = 0x%x\n", s_num,
s_placed_image[s_num].topadd, s_placed_image[s_num].endadd);
s_num++;
}
else
{
ERROR("check load area (overlap)\n");
ERROR("destination address = 0x%x image size = 0x%x\n", dst, len);
ERROR("overlapped image is [%x]\n", loop);
ERROR("top address = 0x%x end address = 0x%x\n",
s_placed_image[loop].topadd, s_placed_image[loop].endadd);
panic;
}
}
/* End of function check_overlap_images(uint32_t dst, uint32_t len, uint32_t dst_end) */

View File

@@ -0,0 +1,145 @@
/*******************************************************************************
* DISCLAIMER
* This software is supplied by Renesas Electronics Corporation and is only
* intended for use with Renesas products. No other uses are authorized. This
* software is owned by Renesas Electronics Corporation and is protected under
* all applicable laws, including copyright laws.
* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT
* LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.
* TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS
* ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE
* FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR
* ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE
* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* Renesas reserves the right, without notice, to make changes to this software
* and to discontinue the availability of this software. By using this software,
* you agree to the additional terms and conditions found by accessing the
* following link:
* http://www.renesas.com/disclaimer
* Copyright 2021-2022 Renesas Electronics Corporation All rights reserved.
*******************************************************************************/
/*******************************************************************************
* DESCRIPTION : Image load for emmc function
******************************************************************************/
/******************************************************************************
* @file image_load_emmc.c
* - Version : 0.04
* @brief Image load for emmc function.
* .
*****************************************************************************/
/******************************************************************************
* History : DD.MM.YYYY Version Description
* : 30.09.2021 0.01 First Release
* : 23.05.2022 0.02 Support for updating the memory map.
* : 05.08.2022 0.03 Add load_ver_tbl_cert_for_emmc function.
* : 30.09.2022 0.04 Modify size output in
* load_ver_tbl_cert_for_emmc function.
*****************************************************************************/
/* indelude */
#include <stdint.h>
#include <image_load.h>
#include <image_load_emmc.h>
#include <remap.h>
#include <log.h>
#include <mem_io.h>
#include <rom_api.h>
#include <emmc_multiboot.h>
#include <emmc_hal.h>
#include <emmc_std.h>
static void load_ver_tbl_cert_for_emmc(void);
uint32_t load_content_cert_for_emmc(void)
{
uint32_t load_num;
uint32_t phys_dst;
uint32_t phys_src;
uint32_t size;
uint32_t part;
/* source address.(0x00240000/sector:0x1200) */
phys_src = EMMC_CONTENT_CERT_SECTOR_NUMBER;
/* Get physical address of transfer destination. */
phys_dst = remap_get_phys_addr(SA9_DEST_ADDR);
/* transfer size(number of secters) */
size = CONTENT_CERT_INFO_SIZE >> EMMC_SECTOR_SIZE_SHIFT;
/* The partition that contains A. */
part = (uint32_t)PARTITION_ID_BOOT_1;
/* Load content cert header */
(void)emmc_trans_data(part, phys_src, phys_dst, size);
NOTICE(
"======== content cert info ========\n"
"destination address:0x%08x\n"
"physical destination address:0x%08x\n"
"source address:(p:%d)0x%08x\n"
"size:0x%08x\n", SA9_DEST_ADDR, phys_dst,
PARTITION_ID_BOOT_1, EMMC_CONTENT_CERT_ADDR, CONTENT_CERT_INFO_SIZE);
load_num = mem_read32(SA9_DEST_ADDR);
/* Check number of image load.
In case of number of image load is 0, error of transfer parameter.
In case of number of image loads is higher than 8,
the transfer parameter error. */
if ((load_num == 0U) || (load_num > CA_MAX_IMAGE))
{
ERROR("Content cert info 'load image num' fault.\n");
ERROR("load image num = %d\n",load_num);
panic;
}
/* Increase forwarding address by the size of cert header */
phys_src += (CONTENT_CERT_INFO_SIZE >> EMMC_SECTOR_SIZE_SHIFT);
phys_dst += CONTENT_CERT_INFO_SIZE;
/* Transfer size calculation for SA9 *
* TFMV key + NTFMV key + minimum version table + (content cert * number of loads) */
size = ((KEY_CERT_SIZE * 2U) + MIN_VER_TBL_SIZE
+ ((NUM_OF_ALWAYS_LOAD_CERT + load_num) * CONTENT_CERT_SIZE));
(void)emmc_trans_data(part, phys_src, phys_dst, size >> EMMC_SECTOR_SIZE_SHIFT);
NOTICE(
"======== content cert ========\n"
"address:0x%08x size:0x%08x\n", phys_dst, size);
/* Load content cert of Software minimum version table */
load_ver_tbl_cert_for_emmc();
return load_num;
}
/* End of function load_content_cert_for_emmc(void) */
static void load_ver_tbl_cert_for_emmc(void)
{
#if (SW_VERSION_CHECK == OPT_VERSION_CHECK_ENABLE)
uint32_t phys_dst;
uint32_t phys_src;
uint32_t size;
uint32_t part;
/* source address.(0x0024D000/sector:0x1268) */
phys_src = EMMC_VER_TBL_CNT_CERT_SEC_NUM;
/* Get physical address of transfer destination. */
phys_dst = remap_get_phys_addr(SA9_DEST_ADDR + EMMC_VER_TBL_OFFSET);
/* transfer size(number of secters) */
size = (CONTENT_CERT_SIZE * 2U) >> EMMC_SECTOR_SIZE_SHIFT;
/* The partition that contains content cert of Software minimum version table. */
part = (uint32_t)PARTITION_ID_BOOT_1;
/* Load content cert of Software minimum version table */
(void)emmc_trans_data(part, phys_src, phys_dst, size);
NOTICE("======== content cert of SW version table ========\n"
"address:0x%08x size:0x%08x\n", phys_dst, (size << EMMC_SECTOR_SIZE_SHIFT));
#endif /* (SW_VERSION_CHECK == OPT_VERSION_CHECK_ENABLE) */
}
/* End of function load_ver_tbl_cert_for_emmc(void) */

View File

@@ -0,0 +1,180 @@
/*******************************************************************************
* DISCLAIMER
* This software is supplied by Renesas Electronics Corporation and is only
* intended for use with Renesas products. No other uses are authorized. This
* software is owned by Renesas Electronics Corporation and is protected under
* all applicable laws, including copyright laws.
* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT
* LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.
* TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS
* ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE
* FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR
* ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE
* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* Renesas reserves the right, without notice, to make changes to this software
* and to discontinue the availability of this software. By using this software,
* you agree to the additional terms and conditions found by accessing the
* following link:
* http://www.renesas.com/disclaimer
* Copyright 2021-2024 Renesas Electronics Corporation All rights reserved.
*******************************************************************************/
/*******************************************************************************
* DESCRIPTION : Image load for Flash function
******************************************************************************/
/******************************************************************************
* @file image_load_flash.c
* - Version : 0.04
* @brief Image load for Flash function.
* .
*****************************************************************************/
/******************************************************************************
* History : DD.MM.YYYY Version Description
* : 30.09.2021 0.01 First Release
* : 23.05.2022 0.02 Support for updating the memory map.
* : 05.08.2022 0.03 Add load_ver_tbl_cert_for_flash function.
* : 20.12.2024 0.04 Add support for booting CR52 3 cores.
*****************************************************************************/
/* indelude */
#include <stdint.h>
#include <image_load_flash.h>
#include <dma.h>
#include <remap.h>
#include <mem_io.h>
#include <rom_api.h>
#include "image_load.h"
#if (RTOS_LOAD_NUM == RTOS_LOAD_NUM_3)
static void load_rtos12_cert_for_flash(void);
#endif /* RTOS_LOAD_NUM == RTOS_LOAD_NUM_3 */
static void load_ver_tbl_cert_for_flash(int slot);
uint32_t load_content_cert_for_flash(int slot)
{
uint32_t load_num;
uint32_t phys_dst;
uint32_t phys_src;
uint32_t size;
/* source address.(0x08240000) */
phys_src = FLASH_CONTENT_CERT_ADDR + (slot * CONTENT_CERT_2nd_OFFSET);
/* Get physical address of transfer destination. */
phys_dst = remap_get_phys_addr(SA9_DEST_ADDR);
/* transfer size */
size = CONTENT_CERT_INFO_SIZE;
/* Load content cert header */
dma_trans_start(phys_dst, phys_src, size);
NOTICE(
"======== content cert info ========\n"
"destination address:0x%08x\n"
"physical destination address:0x%08x\n"
"source address:0x%08x\n"
"size:0x%08x\n", SA9_DEST_ADDR, phys_dst, phys_src, size);
/* End loading cert header */
load_end();
load_num = mem_read32(SA9_DEST_ADDR);
/* Check number of image load.
In case of number of image load is 0, error of transfer parameter.
In case of number of image loads is higher than 8,
the transfer parameter error. */
if ((load_num == 0U) || (load_num > CA_MAX_IMAGE))
{
ERROR("Content cert info 'load image num' fault.\n");
ERROR("load image num = %d\n",load_num);
panic;
}
/* Increase forwarding address by the size of cert header */
phys_src += CONTENT_CERT_INFO_SIZE;
phys_dst += CONTENT_CERT_INFO_SIZE;
/* Transfer size calculation for SA9 *
* TFMV key + NTFMV key + TFMV/NTFMV minimum version table + (content cert * number of loads) */
size = ((KEY_CERT_SIZE * 2U) + MIN_VER_TBL_SIZE
+ ((NUM_OF_ALWAYS_LOAD_CERT + load_num) * CONTENT_CERT_SIZE));
/* Load SA9. */
dma_trans_start(phys_dst, phys_src, size);
/* End loading content cert */
load_end();
NOTICE("======== content of SA9 ========\n"
"address:0x%08x size:0x%08x\n", phys_dst, size);
/* Load content cert of Software minimum version table */
load_ver_tbl_cert_for_flash(slot);
#if (RTOS_LOAD_NUM == RTOS_LOAD_NUM_3)
/* Load content cert of RTOS#1 and RTOS#2 */
load_rtos12_cert_for_flash();
#endif /* RTOS_LOAD_NUM == RTOS_LOAD_NUM_3 */
return load_num;
}
/* End of function load_content_cert_for_flash(void) */
static void load_ver_tbl_cert_for_flash(int slot)
{
#if (SW_VERSION_CHECK == OPT_VERSION_CHECK_ENABLE)
uint32_t phys_dst;
uint32_t phys_src;
uint32_t size;
/* Source address.(0x0824D000) */
phys_src = FLASH_VER_TBL_CNT_CERT_ADDR + (slot * CONTENT_CERT_2nd_OFFSET);
/* Get physical address of transfer destination. */
phys_dst = remap_get_phys_addr(SA9_DEST_ADDR + VER_TBL_CNT_CERT_OFFSET);
/* transfer size */
size = CONTENT_CERT_SIZE * 2U;
/* Load content cert of Software minimum version table. */
dma_trans_start(phys_dst, phys_src, size);
/* End loading content cert */
load_end();
NOTICE("======== content cert of SW version table ========\n"
"address:0x%08x size:0x%08x\n", phys_dst, size);
#endif /* (SW_VERSION_CHECK == OPT_VERSION_CHECK_ENABLE) */
}
/* End of function load_ver_tbl_cert_for_flash(void) */
#if (RTOS_LOAD_NUM == RTOS_LOAD_NUM_3)
static void load_rtos12_cert_for_flash(void)
{
uint32_t phys_dst;
uint32_t phys_src;
uint32_t size;
/* Source address.(0x0824E000) */
phys_src = FLASH_RTOS12_CNT_CERT_ADDR;
/* Get physical address of transfer destination. */
phys_dst = remap_get_phys_addr(SA9_DEST_ADDR + RTOS12_CNT_CERT_OFFSET);
/* transfer size */
size = CONTENT_CERT_SIZE * 2U; /* RTOS#1 and RTOS#2 */
/* Load content cert of Software minimum version table. */
dma_trans_start(phys_dst, phys_src, size);
/* End loading content cert */
load_end();
NOTICE("======== content cert of RTOS#1 and RTOS#2 ========\n"
"address:0x%08x size:0x%08x\n", phys_dst, size);
}
/* End of function load_rtos12_cert_for_flash(void) */
#endif /* RTOS_LOAD_NUM == RTOS_LOAD_NUM_3 */