blob: 6f5f08870e3bf31912eca538fbc336bffc0ddedf [file] [log] [blame] [edit]
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
#include <common.h>
#include <amlogic/cpu_id.h>
#include <amlogic/nocs_seb.h>
#include <asm/io.h>
#include <asm/arch/cpu_config.h>
#ifndef DEBUG_NOCS_SEB
#define DEBUG_NOCS_SEB 0
#endif
#define debug_print(fmt, args...) \
debug_cond(DEBUG_NOCS_SEB, fmt, ##args)
#ifdef CONFIG_UPDATE_UBOOT_NOCS
static unsigned int array_to_uint32_little(unsigned char *array)
{
return ((array)[3] << 24 | (array)[2] << 16 | (array)[1] << 8 | (array)[0]);
}
#endif
nocs_seb_status get_nocs_inf(nocs_chip_type *chip_type, nocs_scs_status *scs_status)
{
#ifdef CONFIG_UPDATE_UBOOT_NOCS
unsigned int reg_value = 0;
int soc_family_id = 0;
soc_family_id = get_cpu_id().family_id;
debug_print("family_id:0x%x\n", soc_family_id);
if (soc_family_id != MESON_CPU_MAJOR_ID_SC2) {
*chip_type = NOCS_UNDEFINE;
*scs_status = NOCS_SCS_DISABLE;
return SEB_NO_ERROR;
}
reg_value = readl(CA_NOCS_MODE_REG);
debug_print("reg_value0:0x%x\n", reg_value);
if ((reg_value & 0x0f) == CA_NOCS_MODE) {
*chip_type = NOCS_S905C2_TYPE1;
reg_value = readl(CA_NOCS_SCS_STATUS);
debug_print("reg_value1:0x%x\n", reg_value);
if ((reg_value & CA_NOCS_SCS) != 0)
*scs_status = NOCS_SCS_ENABLE;
else
*scs_status = NOCS_SCS_DISABLE;
} else {
*chip_type = NOCS_UNDEFINE;
*scs_status = NOCS_SCS_DISABLE;
}
debug_print("chiptype:%d scs_status:%d\n", *chip_type, *scs_status);
#else
*chip_type = NOCS_UNDEFINE;
*scs_status = NOCS_SCS_DISABLE;
debug_print("UnConfig chiptype:%d scs_status:%d\n", *chip_type, *scs_status);
#endif
return SEB_NO_ERROR;
}
nocs_seb_status nocs_secure_boot_modify(nocs_chip_type chip_type,
unsigned char *flash_boot, unsigned int flash_boot_size,
unsigned char *update_boot, unsigned int update_boot_size,
nocs_boot_replace *nocs_replace)
{
int ret = SEB_NO_ERROR;
#ifdef CONFIG_UPDATE_UBOOT_NOCS
unsigned int i;
switch (chip_type) {
case NOCS_S905C2_TYPE1:
{
for (i = 0; i < CMP_SIZE; i++)
if (flash_boot[CMP_OFFSET_TYPE1 + i] != update_boot[CMP_OFFSET_TYPE1 + i]) {
ret = SEB_UNSUPPORT;
break;
}
nocs_replace->area_num = 2;
nocs_replace->offset[0] = REPLACE_INFO_OFFSET;
nocs_replace->size[0] = REPLACE_INFO_SIZE;
nocs_replace->offset[1] = array_to_uint32_little(&update_boot[INFO_OFFSET]);
nocs_replace->size[1] = array_to_uint32_little(&update_boot[INFO_OFFSET + 4]);
} break;
default:
{
printf("Unsupport chip type!\n");
ret = SEB_ERROR;
} break;
}
#else
nocs_replace->area_num = 0;
#endif
return ret;
}
#if DEBUG_NOCS_SEB
static int do_test(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
nocs_chip_type chip_type;
nocs_scs_status scs_status;
nocs_seb_status ret;
ret = get_nocs_inf(&chip_type, &scs_status);
debug_print("test chiptype:%d scs_status:%d ret:%d\n", chip_type, scs_status, ret);
return 0;
}
U_BOOT_CMD(dnocs, 1, 0, do_test,
"determines whether NOCS are included",
"read chip id and cas mode to determines whether NOCS are included\n"
);
#endif