Files
Tool/IPL/Customer/Mobis/V4H_Cx_Loader/loader/loader_main.c
2025-12-24 17:21:08 +09:00

576 lines
21 KiB
C

/*******************************************************************************
* 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 2018-2025 Renesas Electronics Corporation All rights reserved.
*******************************************************************************/
/*******************************************************************************
* DESCRIPTION : Loader main function
******************************************************************************/
/******************************************************************************
* @file loader_main.c
* - Version : 0.17
* @brief 1. IP initialization.
* 2. Transfer image.
* 3. Release of used resources.
* .
*****************************************************************************/
/******************************************************************************
* History : DD.MM.YYYY Version Description
* : 30.11.2021 0.01 First Release
* : 14.02.2022 0.02 Changed log output
* Added device version log output
* Removed Include in micro_wait.h
* Removed the parameter setting process to BL31
* Removed LCS judgement
* Memory map change
* : 17.02.2022 0.03 Support AArch32
* : 22.03.2022 0.04 Support for GSCE[5.4a, 5.4b],[10.3b]
* Support for coverity
* cid:3430806, 3307617, 3430797
* Changed comment
* : 10.05.2022 0.05 Integrated processing
* Changed to processing for each device
* Change log output
* Add argument of load_init()
* : 16.06.2022 0.06 Change log output
* Support secure boot for S4
* : 31.10.2022 0.07 License notation change.
* : 07.11.2022 0.08 Added the parameter setting process to BL31
* Added DDR initialization/QOS initialization
* : 07.12.2022 0.09 Warning support when log output is disabled
* : 15.12.2022 0.10 Support RegionID check
* : 04.04.2023 0.11 Removed stdio.h.
* : 21.08.2023 0.12 Add support for V4M.
* : 23.01.2024 0.13 Add calling of ram_protection_check function.
* Move calling of final_hash_cmp function.
* : 10.09.2024 0.14 Updated Region ID and RAM protection setting
* for QNX.
* : 11.10.2024 0.15 Updated Region ID and RAM protection setting
* for QNX for V4M.
* : 19.12.2024 0.16 Add loading RTOS#1 and RTOS#2 process.
* Add calling ecm_error_enable() function.
* : 26.05.2025 0.17 Add argument of OP-TEE boot address to
* smoni_set_param function.
*****************************************************************************/
#include <stdint.h>
#include <loader_main.h>
#include <rst_register.h>
#include <image_load.h>
#include <ip_control.h>
#include <rcar_def.h>
#include <mem_io.h>
#include <log.h>
#include <string.h>
#if ((RCAR_LSI == RCAR_V4H) || (RCAR_LSI == RCAR_V4M))
#include "cpu_on.h"
#include "qos.h"
#include "rtvram.h"
#include "loader_main_common.h"
#include "../ip/ddr/boot_init_dram.h"
#include "access_protection.h"
#if (ECC_ENABLE == 1)
#if (RCAR_LSI == RCAR_V4H)
#include "../ip/ddr/v4h/lpddr5/ecc_enable_v4h.h"
#elif (RCAR_LSI == RCAR_V4M)
#include "../ip/ddr/v4m/lpddr5/ecc_enable_v4m.h"
#endif /* RCAR_LSI == RCAR_V4H */
#endif /* ECC_ENABLE == 1 */
#endif /* RCAR_LSI == RCAR_V4H || RCAR_LSI == RCAR_V4M */
#if (BOOT_MODE == SECURE)
#include "secure_boot.h"
#endif /* BOOT_MODE == SECURE */
/* Time analysis */
#if (1 == (MEASURE_TIME))
#include <scmt.h>
#include <scmt_checkpoint.h>
#else
#define scmt_wait_ticks(x)
#define store_time_checkpoint(x,y)
#define print_time_checkpoints(x)
#endif
#if (ACC_PROT_ENABLE == PROTECTION_ENABLE)
#include "axmm_register.h"
#include "ram_protection.h"
#endif
#if (ECM_ERROR_ENABLE == 1)
#if (RCAR_LSI == RCAR_V4H)
#include "../ip/ddr/v4h/lpddr5/ecm_enable_v4h.h"
#elif (RCAR_LSI == RCAR_V4M)
#include "../ip/ddr/v4m/lpddr5/ecm_enable_v4m.h"
#endif /* RCAR_LSI == RCAR_V4H */
#endif /* ECM_ERROR_ENABLE == 1 */
#include <android_ab.h>
#include <emmc_def.h>
#include <emmc_boot.h>
#if (ACC_PROT_ENABLE == PROTECTION_ENABLE)
#define AXMM_DPTSECCR_NUM (SDRAM_PROTECT_AREA) /* set 0 to 15 */
#if (OPTEE_LOAD_ENABLE == OPTEE_ENABLE)
#define AXMM_DPTSECCR_NUM2 (SDRAM_PROTECT_AREA2) /* set 0 to 15 */
#endif /* OPTEE_LOAD_ENABLE == OPTEE_ENABLE */
#define AXMM_DPTSECCR_SECGRP_MASK (0x00000F00U)
#define AXMM_DPTSECCR_SECGRP_SEC (0x00000400U)
#define AXMM_DPTSECCR_SECGWP_MASK (0x0000000FU)
#define AXMM_DPTSECCR_SECGWP_SEC (0x00000004U)
#if ((RCAR_LSI == RCAR_V4H) || (RCAR_LSI == RCAR_V4M))
#if (OPTEE_LOAD_ENABLE == OPTEE_DISABLE)
#define DPTRGNCR_PROTECT_AREA (3U)
#define DPTRGNCR_LINUX_AREA (6U)
#else
#define DPTRGNCR_PROTECT_AREA (4U)
#define DPTRGNCR_LINUX_AREA (9U)
#endif /* OPTEE_LOAD_ENABLE == OPTEE_DISABLE */
#define SECCTRWD_AREA0 (0U)
#define SECCTRWD_AREA2 (2U)
#define AXMM_DPTRGNCR_RGN0RP_MASK (0x00010000U)
#define AXMM_DPTRGNCR_RGN0RP (0x00010000U)
#define AXMM_DPTRGNCR_RGN0WP_MASK (0x00000001U)
#define AXMM_DPTRGNCR_RGN0WP (0x00000001U)
#define SECCTRWD_SAFG15WP_MASK (0x00000005U)
#define SECCTRWD_SAFG15WP (0x00000005U)
static void remove_rgid0_previlege(void);
#endif /* ((RCAR_LSI == RCAR_V4H) || (RCAR_LSI == RCAR_V4M)) */
static void sdram_protection(uint32_t num);
#endif /* ACC_PROT_ENABLE == PROTECTION_ENABLE */
uint32_t loader_main(void)
{
uint32_t ca_load_num; /* number of load for CA program */
uint32_t loop;
uint32_t reg; /* store register value */
#ifdef MOBIS_PRK3
int slot = 0;
#endif
#if ((RCAR_LSI == RCAR_V4H) || (RCAR_LSI == RCAR_V4M))
int32_t result; /* store result of ddr_init() */
#endif /* RCAR_LSI == RCAR_V4H || RCAR_LSI == RCAR_V4M */
__attribute__((unused))const char *str;
#if (RCAR_LSI == RCAR_S4)
const char *product_s4 = "S4";
#elif (RCAR_LSI == RCAR_V4H)
const char *product_v4h = "V4H";
#elif (RCAR_LSI == RCAR_V4M)
const char *product_v4m = "V4M";
#endif /* RCAR_LSI == RCAR_S4 */
const char *unknown = "unknown";
#if (BOOT_MODE == SECURE)
uint32_t bootmode; /* store boot mode */
#endif /* BOOT_MODE == SECURE */
LOAD_INFO li[MAX_PLACED];
#if (1 == (MEASURE_TIME))
scmt_module_start();
store_time_checkpoint("loader_main", 0);
#endif
/*****************************************************************************
* Initialize Hardware
*****************************************************************************/
/* IP initialize */
ip_init();
/*****************************************************************************
* Output boot message
*****************************************************************************/
#if (RCAR_LSI == RCAR_S4)
NOTICE("CA55 Loader Program Rev.%s\n", IPL_VERSION);
#elif ((RCAR_LSI == RCAR_V4H) || (RCAR_LSI == RCAR_V4M))
NOTICE("CR52 Loader Program Rev.%s\n", IPL_VERSION);
#endif /* RCAR_LSI == RCAR_S4 */
NOTICE("%s\n", build_message);
/* Get PRR */
reg = mem_read32(PRR);
switch (reg & PRR_PRODUCT_MASK)
{
#if (RCAR_LSI == RCAR_S4)
case PRR_PRODUCT_S4:
{
str = product_s4;
break;
}
#elif (RCAR_LSI == RCAR_V4H)
case PRR_PRODUCT_V4H:
{
str = product_v4h;
break;
}
#elif (RCAR_LSI == RCAR_V4M)
case PRR_PRODUCT_V4M:
{
str = product_v4m;
break;
}
#endif /* RCAR_LSI == RCAR_S4 */
default:
{
str = unknown;
break;
}
}
NOTICE("PRR is R-Car %s Ver.%d.%d\n", str,
((int)(reg & PRR_MAJOR_MASK) >> PRR_MAJOR_SHIFT)
+ PRR_MAJOR_OFFSET, (int)(reg & PRR_MINOR_MASK));
#if ((RCAR_LSI == RCAR_V4H) || (RCAR_LSI == RCAR_V4M))
#if (ACC_PROT_ENABLE == PROTECTION_ENABLE)
/* Notice the ecc enable */
NOTICE("Access Protection Enable\n");
#endif /* ACC_PROT_ENABLE == PROTECTION_ENABLE */
#endif /* RCAR_LSI == RCAR_V4H || RCAR_LSI == RCAR_V4M */
store_time_checkpoint("init_done", 0);
/*****************************************************************************
* DDR Initialization
*****************************************************************************/
#if ((RCAR_LSI == RCAR_V4H) || (RCAR_LSI == RCAR_V4M))
/* DDR initialize */
result = R_DRAM_Init();
if (INITDRAM_OK != result)
{
ERROR("Failed to DRAM initialize (%d).\n", (int)result);
panic;
}
#if (ECM_ERROR_ENABLE == 1)
ecm_error_enable();
#endif /* ECM_ERROR_ENABLE == 1 */
#if (ECC_ENABLE == 1)
/* ECC Protection */
ecc_sdram_enable();
#endif /* ECC_ENABLE == 1 */
/* QoS configuration */
qos_init();
/* RT-VRAM Extend mode */
rtvram_extendmode();
/* memory copy */
memcpy((void *)DISK_BUFFER_ADDR, (void *)DISK_BUFFER__IPL, 4096);
memset((void *)DISK_BUFFER__IPL, 0xFF, 4096);
memcpy((void *)AB_INFO_FLAG_ADDR, (void *)AB_INFO_FLAG__IPL, 4);
memset((void *)AB_INFO_FLAG__IPL, 0xFF, 4);
#endif /* RCAR_LSI == RCAR_V4H || RCAR_LSI == RCAR_V4M */
store_time_checkpoint("DDR_and_Bus_init_done", 0);
/*****************************************************************************
* Load Certficate
*****************************************************************************/
/* Load content certificate */
ca_load_num = mem_read32(CONTENT_CERT_DEST_ADDR);
/* Get load information */
load_init(li, ca_load_num);
#if (BOOT_MODE == SECURE)
/*****************************************************************************
* Check SecureBoot
*****************************************************************************/
secureboot_init();
/* LCS judgement for secure boot */
bootmode = judge_bootmode();
if (NORMAL_BOOT != bootmode)
{
/* Content cert certification */
#if (BL2_LOAD_ENABLE == BL2_DISABLE)
secureboot_verify(li, CA_OPTIONAL_ID, CA_OPTIONAL_ID + ca_load_num);
#else
secureboot_verify(li, CA_BL2_ID, CA_BL2_ID + 1);
#endif
store_time_checkpoint("verify_cert_done", 0);
}
#endif /* BOOT_MODE == SECURE */
#if (RTOS_LOAD_NUM == RTOS_LOAD_NUM_3)
/*****************************************************************************
* Load RTOS#2
*****************************************************************************/
/* Start loading RTOS#2 image */
load_image(&li[RTOS2_ID]);
store_time_checkpoint("load_RTOS#2_done", li[RTOS2_ID].image_size);
#if (BOOT_MODE == SECURE)
/* Decryption image and Image cerfification */
if (NORMAL_BOOT != bootmode)
{
secureboot_image(&li[RTOS2_ID], 1);
store_time_checkpoint("verify_RTOS#2_done", 0);
}
#endif /* BOOT_MODE == SECURE */
/* boot CR core2 */
arm_cpu_on(RCAR_PWR_TARGET_CR, li[RTOS2_ID].boot_addr, 2);
store_time_checkpoint("started_RTOS#2", 0);
#endif /* RTOS_LOAD_NUM == RTOS_LOAD_NUM_3 */
#if ((RCAR_LSI == RCAR_V4H) || (RCAR_LSI == RCAR_V4M))
/*****************************************************************************
* Load RTOS#0
*****************************************************************************/
#define _IPL_END (0xEB22FFF4)
#ifdef MOBIS_PRK3
emmc_initialize();
store_time_checkpoint("emmc_initialize", 0);
#if (BL2_LOAD_ENABLE == BL2_ENABLE) /* do not clear eMMC */
export_mmc_drv_obj();
#endif
reg = mem_read32(AB_INFO_FLAG_ADDR);
if (reg & AB_INFO_SELECT_2nd)
slot = 1;
// slot = ab_select_slot();
load_update_part_num(li, ca_load_num, slot);
NOTICE("slot: %d\n", slot);
mem_write32(_IPL_END, 0x0);
#endif
/* Start loading RTOS#0 image */
load_image(&li[RTOS_ID]);
store_time_checkpoint("load_RTOS#0_done", li[RTOS_ID].image_size);
#if (BOOT_MODE == SECURE)
/* Decryption image and Image cerfification */
if (NORMAL_BOOT != bootmode)
{
/* WARNING! WARNING! WARNING! WARNING! */
/* TODO: set 1 to panic! later */
secureboot_image(&li[RTOS_ID], 0);
store_time_checkpoint("verify_RTOS#0_done", 0);
}
#endif /* BOOT_MODE == SECURE */
/* boot CR core0 */
arm_cpu_on(RCAR_PWR_TARGET_CR, li[RTOS_ID].boot_addr, -1);
#ifdef MOBIS_PRK3
/* enable CR-52 Core 2 */
arm_cpu_on(RCAR_PWR_TARGET_CR, li[RTOS_ID].boot_addr, 2);
store_time_checkpoint("started_RTOS#0", 0);
#endif
#if (BOOT_TIME_CHECK != 0)
gpio_N1305(2);
#endif
#endif /* RCAR_LSI == RCAR_V4H || RCAR_LSI == RCAR_V4M */
/*****************************************************************************
* Load CA Program#2--#8
*****************************************************************************/
#if (BL2_LOAD_ENABLE == BL2_DISABLE)
/* Start loading CA Program#n image */
for (loop = 0U; loop < ca_load_num; loop++)
#else
/* load bl2 */
loop = (CA_BL2_ID - CA_OPTIONAL_ID);
#endif
{
/* Loading start */
NOTICE("Loading %s...\n", li[CA_OPTIONAL_ID + loop].name);
load_image(&li[CA_OPTIONAL_ID + loop]);
store_time_checkpoint("load_CA_#_done", li[CA_OPTIONAL_ID + loop].image_size);
#if (BOOT_MODE == SECURE)
/* Decryption image and Image certification */
if (NORMAL_BOOT != bootmode)
{
secureboot_image(&li[CA_OPTIONAL_ID + loop], 1);
store_time_checkpoint("verify_CA_#_done", 0);
}
#endif /* BOOT_MODE == SECURE */
}
#if ((RCAR_LSI == RCAR_V4H) || (RCAR_LSI == RCAR_V4M))
/* Set Secure Monitor parameter */
#if (OPTEE_LOAD_ENABLE == OPTEE_DISABLE)
smoni_set_param(li[CA_OPTIONAL_ID].boot_addr, /* BL31 */
li[CA_OPTIONAL_ID + 1U].boot_addr); /* U-Boot */
#else
#if (BL2_LOAD_ENABLE == BL2_DISABLE) /* BL2 will load these */
smoni_set_param(li[CA_OPTIONAL_ID].boot_addr, /* BL31 */
li[CA_OPTIONAL_ID + 1U].boot_addr, /* U-Boot */
li[CA_OPTIONAL_ID + 2U].boot_addr); /* OP-TEE */
#endif
#endif /* OPTEE_LOAD_ENABLE == OPTEE_DISABLE */
/* Before Boot CPU, Set the division ratio for CPU operating frequency */
adj_ca_variant_freq();
/* boot CA */
#if (BL2_LOAD_ENABLE == BL2_DISABLE)
arm_cpu_on(RCAR_PWR_TARGET_CA, li[CA_OPTIONAL_ID].boot_addr, -1);
#else /* run BL2, not BL31 */
arm_cpu_on(RCAR_PWR_TARGET_CA, li[CA_BL2_ID].boot_addr, -1);
#endif
store_time_checkpoint("started_CA_core", 0);
#if (RTOS_LOAD_NUM == RTOS_LOAD_NUM_3)
/*****************************************************************************
* Load RTOS#1
*****************************************************************************/
/* Start loading RTOS#1 image */
load_image(&li[RTOS1_ID]);
store_time_checkpoint("load_RTOS#1_done", li[RTOS1_ID].image_size);
#if (BOOT_MODE == SECURE)
/* Decryption image and Image cerfification */
if (NORMAL_BOOT != bootmode)
{
secureboot_image(&li[RTOS1_ID], 1);
store_time_checkpoint("verify_RTOS#1_done", 0);
}
#endif /* BOOT_MODE == SECURE */
#endif /* RTOS_LOAD_NUM == RTOS_LOAD_NUM_3 */
#if (ACC_PROT_ENABLE == PROTECTION_ENABLE)
sdram_protection(AXMM_DPTSECCR_NUM);
#if (OPTEE_LOAD_ENABLE == OPTEE_ENABLE)
sdram_protection(AXMM_DPTSECCR_NUM2);
#endif /* OPTEE_LOAD_ENABLE == OPTEE_ENABLE */
remove_rgid0_previlege();
/*
* SAN(Safety Application Note) 6.23.5 Operation
* Checker processor :
* Check RegionID/LifeC & memory area protection settings (including order & content of intermediate updates)
* done by ICUMX.
*/
rgid_protection_check();
ram_protection_check();
#endif /* ACC_PROT_ENABLE == PROTECTION_ENABLE */
#if (BOOT_MODE == SECURE)
if (NORMAL_BOOT != bootmode)
{
/* Compare Hash verified at ICUMX IPL (V4H only). (Target images are Secure FW and Cx 2nd IPL.) */
/*
* SAN(Safety Application Note) 6.23.5 Operation
* Checker processor :
* Re-do comparison of hash in Flash vs hash generated by ICUMX to confirm proper comparison.
*/
final_hash_cmp();
store_time_checkpoint("final_verify_done", 0);
}
#endif /* BOOT_MODE == SECURE */
NOTICE("Load finish.(CR52 Loader)\n");
#elif (RCAR_LSI == RCAR_S4)
#if (ACC_PROT_ENABLE == PROTECTION_ENABLE)
sdram_protection(AXMM_DPTSECCR_NUM);
#endif /* ACC_PROT_ENABLE == PROTECTION_ENABLE */
NOTICE("Load finish.(CA55 Loader)\n");
#endif /* RCAR_LSI == RCAR_V4H || RCAR_LSI == RCAR_V4M */
// ip_release();
store_time_checkpoint("Cx_done_starting_RTOS#1", 0);
// scmt_wait_ticks(SCMT_MS2TICKS(1000));
print_time_checkpoints();
#if (BOOT_TIME_CHECK != 0)
gpio_N1305(2);
#endif
#if (RTOS_LOAD_NUM == RTOS_LOAD_NUM_1)
#ifdef MOBIS_PRK3
return li[RTOS_ID].boot_addr;
#else
return li[CA_OPTIONAL_ID].boot_addr;
#endif
#elif (RTOS_LOAD_NUM == RTOS_LOAD_NUM_3)
return li[RTOS1_ID].boot_addr;
#endif /* RTOS_LOAD_NUM == RTOS_LOAD_NUM_3 */
}
/* End of function loader_main(void) */
#if (ACC_PROT_ENABLE == PROTECTION_ENABLE)
static void sdram_protection(uint32_t num)
{
uint32_t val;
uint32_t addr;
/* Calculation of the address of the DPTSECCR register. */
addr = (AXMM_DPTSECCR + (num * 4U));
val = mem_read32(addr);
val &= ~(AXMM_DPTSECCR_SECGRP_MASK | AXMM_DPTSECCR_SECGWP_MASK);
val |= (AXMM_DPTSECCR_SECGRP_SEC | AXMM_DPTSECCR_SECGWP_SEC);
mem_write32(addr, val);
}/* End of function void sdram_protection(void) */
#if ((RCAR_LSI == RCAR_V4H) || (RCAR_LSI == RCAR_V4M))
static void remove_rgid0_previlege(void)
{
uint32_t val;
uint32_t addr;
/* Calculation of the address of the DPTRGNCR register. */
addr = get_dptrgncr_addr(DPTRGNCR_PROTECT_AREA);
val = mem_read32(addr);
val &= ~(AXMM_DPTRGNCR_RGN0RP_MASK | AXMM_DPTRGNCR_RGN0WP_MASK);
val |= (AXMM_DPTRGNCR_RGN0RP| AXMM_DPTRGNCR_RGN0WP); /* Remove RGID0 read/write previlege on SDRAM Area. */
mem_write32(addr, val);
/* Calculation of the address of the DPTRGNCR register. */
addr = get_dptrgncr_addr(DPTRGNCR_LINUX_AREA);
val = mem_read32(addr);
val &= ~(AXMM_DPTRGNCR_RGN0RP_MASK | AXMM_DPTRGNCR_RGN0WP_MASK);
val |= (AXMM_DPTRGNCR_RGN0RP| AXMM_DPTRGNCR_RGN0WP); /* Remove RGID0 read/write previlege on SDRAM Area. */
mem_write32(addr, val);
/* Calculation of the address of the SECCTRW0D_1 register. */
addr = get_rtvram1_secctrwd_addr(SECCTRWD_AREA0);
val = mem_read32(addr);
val &= ~(SECCTRWD_SAFG15WP_MASK);
val |= SECCTRWD_SAFG15WP; /* Remove RGID0/2 write previlege on RT-VRAM1 Area0. */
mem_write32(addr, val);
/* Calculation of the address of the SECCTRW2D_1 register. */
addr = get_rtvram1_secctrwd_addr(SECCTRWD_AREA2);
val = mem_read32(addr);
val &= ~(SECCTRWD_SAFG15WP_MASK);
val |= SECCTRWD_SAFG15WP; /* Remove RGID0/2 write previlege on RT-VRAM1 Area2. */
mem_write32(addr, val);
}
/* End of function void remove_rgid0_previlege(void) */
#endif /* ((RCAR_LSI == RCAR_V4H) || (RCAR_LSI == RCAR_V4M)) */
#endif /* ACC_PROT_ENABLE == PROTECTION_ENABLE */