add IPL
This commit is contained in:
336
IPL/Customer/Mobis/V4H_Cx_Loader/image_load/android_ab.c
Normal file
336
IPL/Customer/Mobis/V4H_Cx_Loader/image_load/android_ab.c
Normal file
@@ -0,0 +1,336 @@
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*/
|
||||
// #include <common.h>
|
||||
#include <android_ab.h>
|
||||
#include <android_bootloader_message.h>
|
||||
// #include <blk.h>
|
||||
#include <log.h>
|
||||
// #include <malloc.h>
|
||||
#include <string.h>
|
||||
// #include <part.h>
|
||||
// #include <memalign.h>
|
||||
// #include <linux/err.h>
|
||||
#include <errno.h>
|
||||
// #include <u-boot/crc.h>
|
||||
#include <crc.h>
|
||||
|
||||
#include <emmc_multiboot.h>
|
||||
#include <image_load_emmc.h>
|
||||
#include <mem_io.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]))
|
||||
|
||||
volatile uint8_t *_disk_buffer = (volatile uint8_t *)DISK_BUFFER_ADDR;
|
||||
|
||||
/**
|
||||
* 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[in] dev_desc Device where to read the boot_control struct from
|
||||
* @param[in] part_info Partition in 'dev_desc' where to read from, normally
|
||||
* the "misc" partition should be used
|
||||
* @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 blk_desc *dev_desc,
|
||||
// const struct disk_partition *part_info,
|
||||
struct bootloader_control **abc)
|
||||
{
|
||||
// ulong abc_offset, abc_blocks, ret;
|
||||
|
||||
// abc_offset = offsetof(struct bootloader_message_ab, slot_suffix);
|
||||
// if (abc_offset % CX_EMMC_SECTOR_SIZE) {
|
||||
// ERROR("Boot control block not block aligned.\n");
|
||||
// return -EINVAL;
|
||||
// }
|
||||
// abc_offset /= CX_EMMC_SECTOR_SIZE;
|
||||
|
||||
// abc_blocks = DIV_ROUND_UP(sizeof(struct bootloader_control),
|
||||
// CX_EMMC_SECTOR_SIZE);
|
||||
// if (abc_offset + abc_blocks > part_info->size) {
|
||||
// ERROR("boot control partition too small. Need at"
|
||||
// " least %lu blocks but have %lu blocks.\n",
|
||||
// abc_offset + abc_blocks, part_info->size);
|
||||
// return -EINVAL;
|
||||
// }
|
||||
// *abc = malloc_cache_aligned(abc_blocks * CX_EMMC_SECTOR_SIZE);
|
||||
// if (!*abc)
|
||||
// return -ENOMEM;
|
||||
|
||||
// [ab_control_create_from_disk:112] start 0x3f800(260096), abc_offset(0x4,4), blocks 1
|
||||
// ret = blk_dread(dev_desc, part_info->start + abc_offset, abc_blocks,
|
||||
// *abc);
|
||||
uint32_t rtn_val = EMMC_DEV_ERR;
|
||||
|
||||
#define CX_EMMC_MISC_PART 0 // user partition
|
||||
#define CX_EMMC_MISC_START 0x3F800 // 127MB in user partition
|
||||
#define CX_EMMC_AB_CONTROL (CX_EMMC_MISC_START + 4)
|
||||
#define CX_EMMC_AB_SIZE (1)
|
||||
rtn_val = emmc_trans_data(CX_EMMC_MISC_PART, (uintptr_t)(CX_EMMC_AB_CONTROL),
|
||||
(uintptr_t)_disk_buffer, CX_EMMC_AB_SIZE);
|
||||
if(EMMC_DEV_OK != rtn_val)
|
||||
{
|
||||
ERROR("Could not read from boot ctrl partition\n");
|
||||
*abc = NULL;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
*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().
|
||||
*
|
||||
* @param[in] dev_desc Device where we should write the boot_control struct
|
||||
* @param[in] part_info Partition on the 'dev_desc' where to write
|
||||
* @param[in] abc Pointer to the boot control struct and the extra bytes after
|
||||
* it up to the nearest block boundary
|
||||
* @return 0 on success and a negative on error
|
||||
*/
|
||||
// static int ab_control_store(struct blk_desc *dev_desc,
|
||||
// const struct disk_partition *part_info,
|
||||
// struct bootloader_control *abc)
|
||||
// {
|
||||
// ulong abc_offset, abc_blocks, ret;
|
||||
|
||||
// abc_offset = offsetof(struct bootloader_message_ab, slot_suffix) /
|
||||
// part_info->blksz;
|
||||
// abc_blocks = DIV_ROUND_UP(sizeof(struct bootloader_control),
|
||||
// part_info->blksz);
|
||||
// ret = blk_dwrite(dev_desc, part_info->start + abc_offset, abc_blocks,
|
||||
// abc);
|
||||
// if (IS_ERR_VALUE(ret)) {
|
||||
// log_err("ANDROID: Could not write back the misc partition\n");
|
||||
// return -EIO;
|
||||
// }
|
||||
|
||||
// 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(
|
||||
// struct blk_desc *dev_desc, struct disk_partition *part_info
|
||||
void
|
||||
)
|
||||
{
|
||||
struct bootloader_control *abc = NULL;
|
||||
u32 crc32_le;
|
||||
int slot, i, ret;
|
||||
bool store_needed = false;
|
||||
char slot_suffix[4];
|
||||
|
||||
mem_write32(AB_INFO_FLAG_ADDR, AB_INFO_FLAG_INIT);
|
||||
ret = ab_control_create_from_disk(/*dev_desc, part_info,*/ &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))) {
|
||||
memcpy(abc->slot_suffix, slot_suffix,
|
||||
sizeof(slot_suffix));
|
||||
NOTICE("[%s:%d] slot_suffix is differ\n", __func__, __LINE__);
|
||||
store_needed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (store_needed) {
|
||||
abc->crc32_le = ab_control_compute_crc(abc);
|
||||
// ab_control_store(dev_desc, part_info, 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;
|
||||
}
|
||||
494
IPL/Customer/Mobis/V4H_Cx_Loader/image_load/image_load.c
Normal file
494
IPL/Customer/Mobis/V4H_Cx_Loader/image_load/image_load.c
Normal file
@@ -0,0 +1,494 @@
|
||||
/*******************************************************************************
|
||||
* 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 : Image load function
|
||||
******************************************************************************/
|
||||
/******************************************************************************
|
||||
* @file image_load.c
|
||||
* - Version : 0.11
|
||||
* @brief Access protection setting driver.
|
||||
* .
|
||||
*****************************************************************************/
|
||||
/******************************************************************************
|
||||
* History : DD.MM.YYYY Version Description
|
||||
* : 29.11.2021 0.01 First Release
|
||||
* : 10.02.2022 0.02 Updated eMMC driver
|
||||
* Removed the comment
|
||||
* Change the line feed code of log output
|
||||
* Change the number of CA programs
|
||||
* : 17.02.2022 0.03 Support AArch32
|
||||
* : 22.03.2022 0.04 Support for GSCE[3.3b]
|
||||
* : 11.05.2022 0.05 Used the standard library
|
||||
* Integrated LOAD_INFO
|
||||
* Changed image_name table
|
||||
* Changed check_load_area
|
||||
* - Change RAM check process
|
||||
* - Change address check process
|
||||
* - Add Image check process
|
||||
* - Processing integration
|
||||
* Changed to processing for each device
|
||||
* Change structure member name
|
||||
* Added function return value judgment
|
||||
* Changed LOGICAL_CONTENT_CERT_ADDR to
|
||||
* get_logic_cont_cert_addr
|
||||
* Changed uint32_t to uintptr_t
|
||||
* Change log output
|
||||
* Add argument of load_init()
|
||||
* Change to error when key information is invalid
|
||||
* Remove unnecessary type conversion
|
||||
* : 11.07.2022 0.06 Change log output
|
||||
* Support secure boot for S4
|
||||
* Change load start processing other than 512byte align
|
||||
* : 02.09.2022 0.07 Added 512byte boundary check
|
||||
* : 31.10.2022 0.08 License notation change.
|
||||
* : 21.08.2023 0.09 Add support for V4M.
|
||||
* : 19.12.2024 0.10 Add support for RTOS#1 and RTOS#2.
|
||||
* : 26.05.2025 0.11 Change key cert address of [CA_OPTIONAL_ID+2].
|
||||
*****************************************************************************/
|
||||
/* indelude */
|
||||
#include <stdint.h>
|
||||
#include <image_load.h>
|
||||
#include <mem_io.h>
|
||||
#include <log.h>
|
||||
|
||||
#include <image_load_emmc.h>
|
||||
#include <emmc_multiboot.h>
|
||||
|
||||
#define KEY_SIZE_FLG_MSK (0x00000003U)
|
||||
#define KEY_SIZE_BIT_SHIFT (21U)
|
||||
#define CERT_INFO_FLG_OFFSET (0x0000000CU)
|
||||
#define KEY_SIZE_4096 (0x00000002U)
|
||||
#define KEY_SIZE_3072 (0x00000001U)
|
||||
#define KEY_SIZE_2048 (0x00000000U)
|
||||
#define WORD_TO_BYTE (4U)
|
||||
#define NOT_OVERLAP_FLAG (0U)
|
||||
#define OVERLAP_FLAG (1U)
|
||||
#define RAM_RANGE_OK (0U)
|
||||
#define RAM_RANGE_NG (1U)
|
||||
#if (RTOS_LOAD_NUM == RTOS_LOAD_NUM_1)
|
||||
#define RAM_MAX (4U)
|
||||
#elif (RTOS_LOAD_NUM == RTOS_LOAD_NUM_3)
|
||||
#define RAM_MAX (5U) /* ++ SRAM in RT-VRAM (0xE2000000 - 0xE200FFFF) */
|
||||
#endif /* RTOS_LOAD_NUM == RTOS_LOAD_NUM_3 */
|
||||
#define ADDRESS_RANGE_512 (512U)
|
||||
|
||||
static void check_load_area(LOAD_INFO* li);
|
||||
static void get_info_from_cert(uint32_t cert_addr, uint32_t *size,
|
||||
uint32_t *dest_addr);
|
||||
|
||||
void load_image(LOAD_INFO* li)
|
||||
{
|
||||
/* log output of load image for information */
|
||||
load_image_info_print_for_emmc(li);
|
||||
|
||||
/* 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, uint32_t num)
|
||||
{
|
||||
uint32_t loop;
|
||||
uintptr_t buf;
|
||||
|
||||
const char *image_name[MAX_PLACED] = {
|
||||
#if ((RCAR_LSI == RCAR_V4H) || (RCAR_LSI == RCAR_V4M))
|
||||
[RTOS_ID] = "RTOS",
|
||||
#endif /* RCAR_LSI == RCAR_V4H || RCAR_LSI == RCAR_V4M */
|
||||
#ifdef MOBIS_PRK3
|
||||
[CA_OPTIONAL_ID] = "BL31",
|
||||
[CA_OPTIONAL_ID + 1] = "u-boot",
|
||||
[CA_OPTIONAL_ID + 2] = "tee OS",
|
||||
[CA_OPTIONAL_ID + 3] = "BL2",
|
||||
[CA_OPTIONAL_ID + 4] = "QNX OS",
|
||||
#else
|
||||
[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",
|
||||
#endif
|
||||
[CA_OPTIONAL_ID + 5] = "CA Program #6",
|
||||
[CA_OPTIONAL_ID + 6] = "CA Program #7",
|
||||
[CA_OPTIONAL_ID + 7] = "CA Program #8",
|
||||
#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] = {
|
||||
#if ((RCAR_LSI == RCAR_V4H) || (RCAR_LSI == RCAR_V4M))
|
||||
[RTOS_ID] = TFMV_KEY_CERT_ADDR,
|
||||
#endif /* RCAR_LSI == RCAR_V4H || RCAR_LSI == RCAR_V4M */
|
||||
[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 /* OPTEE_LOAD_ENABLE == OPTEE_DISABLE */
|
||||
#if (BL2_LOAD_ENABLE == BL2_DISABLE)
|
||||
[CA_OPTIONAL_ID + 3] = NTFMV_KEY_CERT_ADDR,
|
||||
#else
|
||||
[CA_OPTIONAL_ID + 3] = TFMV_KEY_CERT_ADDR, /* ca76-loader */
|
||||
#endif /* BL2_LOAD_ENABLE == BL2_DISABLE */
|
||||
[CA_OPTIONAL_ID + 4] = NTFMV_KEY_CERT_ADDR, /* qnx OS */
|
||||
[CA_OPTIONAL_ID + 5] = NTFMV_KEY_CERT_ADDR,
|
||||
[CA_OPTIONAL_ID + 6] = NTFMV_KEY_CERT_ADDR,
|
||||
[CA_OPTIONAL_ID + 7] = 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 */
|
||||
};
|
||||
|
||||
|
||||
if (num >= 1U && num <= 8U)
|
||||
{
|
||||
/* Set Load info parameter */
|
||||
for (loop = CA_OPTIONAL_ID; loop < CA_OPTIONAL_ID + num; 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));
|
||||
buf = get_part_num_in_cert(loop);
|
||||
li[loop].part_num = mem_read32(buf);
|
||||
li[loop].load_id = loop;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("load_init(CA program num error).\n");
|
||||
panic;
|
||||
}
|
||||
|
||||
#if ((RCAR_LSI == RCAR_V4H) || (RCAR_LSI == RCAR_V4M))
|
||||
li[RTOS_ID].name = image_name[RTOS_ID];
|
||||
li[RTOS_ID].key_cert_addr = key_cert[RTOS_ID];
|
||||
li[RTOS_ID].cnt_cert_addr = get_logic_cont_cert_addr(RTOS_ID);
|
||||
get_info_from_cert(li[RTOS_ID].cnt_cert_addr, &li[RTOS_ID].image_size, &li[RTOS_ID].boot_addr);
|
||||
buf = get_src_addr_offset_in_cert(RTOS_ID);
|
||||
li[RTOS_ID].src_addr = (SRC_TOP + mem_read32(buf));
|
||||
buf = get_part_num_in_cert(RTOS_ID);
|
||||
li[RTOS_ID].part_num = mem_read32(buf);
|
||||
li[RTOS_ID].load_id = RTOS_ID;
|
||||
|
||||
#if (RTOS_LOAD_NUM == RTOS_LOAD_NUM_3)
|
||||
/* Set Load info parameter for RTOS#1 and RTOS#2 */
|
||||
for (loop = RTOS1_ID; loop <= RTOS2_ID; 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));
|
||||
buf = get_part_num_in_cert(loop);
|
||||
li[loop].part_num = mem_read32(buf);
|
||||
li[loop].load_id = loop;
|
||||
}
|
||||
#endif /* RTOS_LOAD_NUM == RTOS_LOAD_NUM_3 */
|
||||
#endif /* RCAR_LSI == RCAR_V4H || RCAR_LSI == RCAR_V4M */
|
||||
|
||||
}/* End of function load_init(LOAD_INFO* li) */
|
||||
|
||||
void load_update_part_num(LOAD_INFO* li, uint32_t num, int slot)
|
||||
{
|
||||
uint32_t loop;
|
||||
|
||||
/* Set Load info parameter */
|
||||
for (loop = CA_OPTIONAL_ID; loop < CA_OPTIONAL_ID + num; loop++)
|
||||
{
|
||||
li[loop].part_num = (slot == 1) ? 2 : 1;
|
||||
}
|
||||
li[RTOS_ID].part_num = (slot == 1) ? 2 : 1;
|
||||
}
|
||||
|
||||
static void check_load_area(LOAD_INFO* li)
|
||||
{
|
||||
uint32_t src;
|
||||
uint32_t dst;
|
||||
uint32_t len;
|
||||
uint32_t dst_end;
|
||||
uint32_t overlap;
|
||||
uint32_t loop;
|
||||
uint32_t rge_chk_flg;
|
||||
static uint32_t s_num = 1U;
|
||||
|
||||
/* 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 (RTOS_LOAD_NUM == RTOS_LOAD_NUM_3)
|
||||
[TARGET_MEM_SRAM_IN_RTVRAM] = {RTVRAM_SRAM_TOP, RTVRAM_SRAM_END},
|
||||
#endif /* RTOS_LOAD_NUM == RTOS_LOAD_NUM_3 */
|
||||
};
|
||||
|
||||
/* The image range check */
|
||||
const IMAGE_RANGE size_list[CA_IMAGESIZECHK_DEF] = {
|
||||
{ CA_PROGRAM1_ID, CA_PROGRAM1_ADR, CA_PROGRAM1_SIZE},
|
||||
{ CA_PROGRAM2_ID, CA_PROGRAM2_ADR, CA_PROGRAM2_SIZE},
|
||||
#if (OPTEE_LOAD_ENABLE == OPTEE_ENABLE)
|
||||
{ CA_PROGRAM3_ID, CA_PROGRAM3_ADR, CA_PROGRAM3_SIZE},
|
||||
#endif /* OPTEE_LOAD_ENABLE == OPTEE_ENABLE */
|
||||
#if (BL2_LOAD_ENABLE == BL2_ENABLE)
|
||||
{ CA_PROGRAM4_ID, CA_PROGRAM4_ADR, CA_PROGRAM4_SIZE},
|
||||
#endif /* BL2_LOAD_ENABLE == BL2_ENABLE */
|
||||
#if (QNX_OS_LOAD_ENABLE == QNX_OS_ENABLE)
|
||||
{ CA_PROGRAM5_ID, CA_PROGRAM5_ADR, CA_PROGRAM5_SIZE},
|
||||
#endif /* QNX_OS_LOAD_ENABLE == QNX_OS_ENABLE */
|
||||
};
|
||||
|
||||
static ADDRESS_RANGE s_placed_image[MAX_PLACED] = {
|
||||
[0] = {IPL_TOP, IPL_END}
|
||||
};
|
||||
|
||||
|
||||
src = li->src_addr;
|
||||
dst = li->boot_addr;
|
||||
len = li->image_size;
|
||||
|
||||
/* Check image size */
|
||||
if (len == 0U)
|
||||
{
|
||||
ERROR("image size error\n");
|
||||
panic;
|
||||
}
|
||||
|
||||
/* Check whether source is overflow */
|
||||
/* INT30-C Pre confirmation */
|
||||
if (src > (UINT32_MAX - len))
|
||||
{
|
||||
ERROR("1:overflow is occurred at source\n");
|
||||
ERROR("1:source address = 0x%x image size = 0x%x\n", (unsigned int)src, (unsigned int)len);
|
||||
panic;
|
||||
}
|
||||
|
||||
/* Check whether destination is overflow */
|
||||
/* INT30-C Pre confirmation */
|
||||
if (dst > (UINT32_MAX - len))
|
||||
{
|
||||
ERROR("1:overflow is occurred at destination\n");
|
||||
ERROR("1:destination address = 0x%x image size = 0x%x\n", (unsigned int)dst,
|
||||
(unsigned int)len);
|
||||
panic;
|
||||
}
|
||||
else
|
||||
{
|
||||
dst_end = dst + len - 1U;
|
||||
}
|
||||
|
||||
/* Check source address range. */
|
||||
/* No error check is performed because it is detected by the eMMC device */
|
||||
|
||||
/* Check destination address range. */
|
||||
|
||||
/* 512byte boundary check */
|
||||
if (0U != (dst % ADDRESS_RANGE_512))
|
||||
{
|
||||
ERROR("check_load_area (destination address)\n");
|
||||
ERROR("destination address = 0x%x \n", (unsigned int)dst);
|
||||
panic;
|
||||
}
|
||||
|
||||
/* range check */
|
||||
rge_chk_flg = RAM_RANGE_NG;
|
||||
|
||||
for(loop = 0U; loop < RAM_MAX; loop++)
|
||||
{
|
||||
if (add_list[loop].cx_topadd <= dst)
|
||||
{
|
||||
if(dst_end <= add_list[loop].cx_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", (unsigned int)dst,
|
||||
(unsigned int)len);
|
||||
panic;
|
||||
}
|
||||
|
||||
/* Check whether destination is overflow */
|
||||
for (loop = 0U; loop < CA_IMAGESIZECHK_DEF; loop++)
|
||||
{
|
||||
if (li->load_id == size_list[loop].load_id)
|
||||
{
|
||||
if ((size_list[loop].image_adr != 0U) && (dst != size_list[loop].image_adr))
|
||||
{
|
||||
ERROR("check load area.(outside secure area)\n");
|
||||
ERROR("destination address = 0x%x(0x%x) image size = 0x%x\n", (unsigned int)dst,
|
||||
(unsigned int)(size_list[loop].image_adr), (unsigned int)len);
|
||||
panic;
|
||||
}
|
||||
if ((size_list[loop].image_size != 0U) && (len > size_list[loop].image_size))
|
||||
{
|
||||
ERROR("check load area.(outside secure area)\n");
|
||||
ERROR("destination address = 0x%x image size = 0x%x(0x%x)\n", (unsigned int)dst,
|
||||
(unsigned int)len, (unsigned int)(size_list[loop].image_size));
|
||||
panic;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check there are no overlaps the image that will be loaded and
|
||||
the images that have already loaded. */
|
||||
overlap = NOT_OVERLAP_FLAG;
|
||||
loop = 0U;
|
||||
do
|
||||
{
|
||||
/* check overlap */
|
||||
if ((dst >= s_placed_image[loop].cx_topadd)
|
||||
&& (dst <= s_placed_image[loop].cx_endadd))
|
||||
{
|
||||
overlap = OVERLAP_FLAG;
|
||||
}
|
||||
else if ((dst_end >= s_placed_image[loop].cx_topadd)
|
||||
&& (dst_end <= s_placed_image[loop].cx_endadd))
|
||||
{
|
||||
overlap = OVERLAP_FLAG;
|
||||
}
|
||||
else if ((dst < s_placed_image[loop].cx_topadd)
|
||||
&& (s_placed_image[loop].cx_endadd < dst_end))
|
||||
{
|
||||
overlap = OVERLAP_FLAG;
|
||||
}
|
||||
else
|
||||
{
|
||||
loop++;
|
||||
}
|
||||
} while ((loop < s_num) && (overlap == NOT_OVERLAP_FLAG));
|
||||
|
||||
/* Check the overlap flag.
|
||||
Parameter 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].cx_topadd = dst;
|
||||
s_placed_image[s_num].cx_endadd = dst_end;
|
||||
s_num++;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("check load area (overlap)\n");
|
||||
ERROR("destination address = 0x%x image size = 0x%x\n", (unsigned int)dst, (unsigned int)len);
|
||||
ERROR("overlapped image is [%u]\n", (unsigned int)loop);
|
||||
ERROR("top address = 0x%x end address = 0x%x\n",
|
||||
(unsigned int)s_placed_image[loop].cx_topadd, (unsigned int)s_placed_image[loop].cx_endadd);
|
||||
panic;
|
||||
}
|
||||
}
|
||||
/* End of function check_load_area(uint32_t dst, uint32_t src, uint32_t len) */
|
||||
|
||||
static void get_info_from_cert(uint32_t cert_addr, uint32_t *size,
|
||||
uint32_t *dest_addr)
|
||||
{
|
||||
uint32_t val;
|
||||
uint32_t certInfo1;
|
||||
uintptr_t pSize;
|
||||
uintptr_t pDestL;
|
||||
|
||||
/* Get key length of content certificate. */
|
||||
val = mem_read32((uintptr_t)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
|
||||
{
|
||||
ERROR("get_info_from_cert key size error.\n");
|
||||
panic;
|
||||
}
|
||||
}
|
||||
/* End of function get_info_from_cert(uint32_t cert_addr, uint32_t *size, uint32_t *dest_addr) */
|
||||
|
||||
void load_start(LOAD_INFO* li)
|
||||
{
|
||||
uint32_t rtn_val = EMMC_DEV_ERR;
|
||||
uint32_t sector_count;
|
||||
uint32_t fraction;
|
||||
|
||||
/* Converted to number of sectors transferred. */
|
||||
sector_count = li->image_size >> CX_EMMC_SECTOR_SIZE_SHIFT;
|
||||
|
||||
fraction = li->image_size % CX_EMMC_SECTOR_SIZE;
|
||||
/* Add 1 if there is a fraction */
|
||||
if(0U != fraction)
|
||||
{
|
||||
sector_count += 1U;
|
||||
}
|
||||
|
||||
rtn_val = emmc_trans_data(li->part_num, (uintptr_t)(li->src_addr >> CX_EMMC_SECTOR_SIZE_SHIFT),
|
||||
(uintptr_t)li->boot_addr, sector_count);
|
||||
|
||||
if(EMMC_DEV_OK != rtn_val)
|
||||
{
|
||||
ERROR("load_start(emmc_trans_data error).\n");
|
||||
panic;
|
||||
}
|
||||
}
|
||||
/* End of function load_start(LOAD_INFO* li) */
|
||||
|
||||
Reference in New Issue
Block a user