add IPL
This commit is contained in:
309
IPL/Customer/Mobis/Gen4_ICUMX_Loader/image_load/android_ab.c
Normal file
309
IPL/Customer/Mobis/Gen4_ICUMX_Loader/image_load/android_ab.c
Normal 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;
|
||||
}
|
||||
535
IPL/Customer/Mobis/Gen4_ICUMX_Loader/image_load/image_load.c
Normal file
535
IPL/Customer/Mobis/Gen4_ICUMX_Loader/image_load/image_load.c
Normal 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) */
|
||||
|
||||
@@ -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) */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user