GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
@@ -0,0 +1,65 @@
/*
* Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <common/debug.h>
#include <drivers/console.h>
#include <drivers/ti/uart/uart_16550.h>
#include <platform_def.h>
/*******************************************************************************
* Functions that set up the console
******************************************************************************/
static console_t bcm_boot_console;
static console_t bcm_runtime_console;
/* Initialize the console to provide early debug support */
void bcm_console_boot_init(void)
{
int rc = console_16550_register(PLAT_BRCM_BOOT_UART_BASE,
PLAT_BRCM_BOOT_UART_CLK_IN_HZ,
BRCM_CONSOLE_BAUDRATE,
&bcm_boot_console);
if (rc == 0) {
/*
* The crash console doesn't use the multi console API, it uses
* the core console functions directly. It is safe to call panic
* and let it print debug information.
*/
panic();
}
console_set_scope(&bcm_boot_console, CONSOLE_FLAG_BOOT);
}
void bcm_console_boot_end(void)
{
console_flush();
(void)console_unregister(&bcm_boot_console);
}
/* Initialize the runtime console */
void bcm_console_runtime_init(void)
{
int rc = console_16550_register(PLAT_BRCM_BL31_RUN_UART_BASE,
PLAT_BRCM_BL31_RUN_UART_CLK_IN_HZ,
BRCM_CONSOLE_BAUDRATE,
&bcm_runtime_console);
if (rc == 0)
panic();
console_set_scope(&bcm_runtime_console, CONSOLE_FLAG_RUNTIME);
}
void bcm_console_runtime_end(void)
{
console_flush();
(void)console_unregister(&bcm_runtime_console);
}
@@ -0,0 +1,268 @@
/*
* Copyright (c) 2018 - 2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdarg.h>
#include <stdint.h>
#include <string.h>
#include <arch_helpers.h>
#include <common/debug.h>
#include <plat/common/platform.h>
#include <bcm_elog.h>
/* error logging signature */
#define BCM_ELOG_SIG_OFFSET 0x0000
#define BCM_ELOG_SIG_VAL 0x75767971
/* current logging offset that points to where new logs should be added */
#define BCM_ELOG_OFF_OFFSET 0x0004
/* current logging length (excluding header) */
#define BCM_ELOG_LEN_OFFSET 0x0008
#define BCM_ELOG_HEADER_LEN 12
/*
* @base: base address of memory where log is saved
* @max_size: max size of memory reserved for logging
* @is_active: indicates logging is currently active
* @level: current logging level
*/
struct bcm_elog {
uintptr_t base;
uint32_t max_size;
unsigned int is_active;
unsigned int level;
};
static struct bcm_elog global_elog;
extern void memcpy16(void *dst, const void *src, unsigned int len);
/*
* Log one character
*/
static void elog_putchar(struct bcm_elog *elog, unsigned char c)
{
uint32_t offset, len;
offset = mmio_read_32(elog->base + BCM_ELOG_OFF_OFFSET);
len = mmio_read_32(elog->base + BCM_ELOG_LEN_OFFSET);
mmio_write_8(elog->base + offset, c);
offset++;
/* log buffer is now full and need to wrap around */
if (offset >= elog->max_size)
offset = BCM_ELOG_HEADER_LEN;
/* only increment length when log buffer is not full */
if (len < elog->max_size - BCM_ELOG_HEADER_LEN)
len++;
mmio_write_32(elog->base + BCM_ELOG_OFF_OFFSET, offset);
mmio_write_32(elog->base + BCM_ELOG_LEN_OFFSET, len);
}
static void elog_unsigned_num(struct bcm_elog *elog, unsigned long unum,
unsigned int radix)
{
/* Just need enough space to store 64 bit decimal integer */
unsigned char num_buf[20];
int i = 0, rem;
do {
rem = unum % radix;
if (rem < 0xa)
num_buf[i++] = '0' + rem;
else
num_buf[i++] = 'a' + (rem - 0xa);
} while (unum /= radix);
while (--i >= 0)
elog_putchar(elog, num_buf[i]);
}
static void elog_string(struct bcm_elog *elog, const char *str)
{
while (*str)
elog_putchar(elog, *str++);
}
/*
* Routine to initialize error logging
*/
int bcm_elog_init(void *base, uint32_t size, unsigned int level)
{
struct bcm_elog *elog = &global_elog;
uint32_t val;
elog->base = (uintptr_t)base;
elog->max_size = size;
elog->is_active = 1;
elog->level = level / 10;
/*
* If a valid signature can be found, it means logs have been copied
* into designated memory by another software. In this case, we should
* not re-initialize the entry header in the designated memory
*/
val = mmio_read_32(elog->base + BCM_ELOG_SIG_OFFSET);
if (val != BCM_ELOG_SIG_VAL) {
mmio_write_32(elog->base + BCM_ELOG_SIG_OFFSET,
BCM_ELOG_SIG_VAL);
mmio_write_32(elog->base + BCM_ELOG_OFF_OFFSET,
BCM_ELOG_HEADER_LEN);
mmio_write_32(elog->base + BCM_ELOG_LEN_OFFSET, 0);
}
return 0;
}
/*
* Routine to disable error logging
*/
void bcm_elog_exit(void)
{
struct bcm_elog *elog = &global_elog;
if (!elog->is_active)
return;
elog->is_active = 0;
flush_dcache_range(elog->base, elog->max_size);
}
/*
* Routine to copy error logs from current memory to 'dst' memory and continue
* logging from the new 'dst' memory.
* dst and base addresses must be 16-bytes aligned.
*/
int bcm_elog_copy_log(void *dst, uint32_t max_size)
{
struct bcm_elog *elog = &global_elog;
uint32_t offset, len;
if (!elog->is_active || ((uintptr_t)dst == elog->base))
return -1;
/* flush cache before copying logs */
flush_dcache_range(elog->base, max_size);
/*
* If current offset exceeds the new max size, then that is considered
* as a buffer overflow situation. In this case, we reset the offset
* back to the beginning
*/
offset = mmio_read_32(elog->base + BCM_ELOG_OFF_OFFSET);
if (offset >= max_size) {
offset = BCM_ELOG_HEADER_LEN;
mmio_write_32(elog->base + BCM_ELOG_OFF_OFFSET, offset);
}
/* note payload length does not include header */
len = mmio_read_32(elog->base + BCM_ELOG_LEN_OFFSET);
if (len > max_size - BCM_ELOG_HEADER_LEN) {
len = max_size - BCM_ELOG_HEADER_LEN;
mmio_write_32(elog->base + BCM_ELOG_LEN_OFFSET, len);
}
/* Need to copy everything including the header. */
memcpy16(dst, (const void *)elog->base, len + BCM_ELOG_HEADER_LEN);
elog->base = (uintptr_t)dst;
elog->max_size = max_size;
return 0;
}
/*
* Main routine to save logs into memory
*/
void bcm_elog(const char *fmt, ...)
{
va_list args;
const char *prefix_str;
int bit64;
int64_t num;
uint64_t unum;
char *str;
struct bcm_elog *elog = &global_elog;
/* We expect the LOG_MARKER_* macro as the first character */
unsigned int level = fmt[0];
if (!elog->is_active || level > elog->level)
return;
prefix_str = plat_log_get_prefix(level);
while (*prefix_str != '\0') {
elog_putchar(elog, *prefix_str);
prefix_str++;
}
va_start(args, fmt);
fmt++;
while (*fmt) {
bit64 = 0;
if (*fmt == '%') {
fmt++;
/* Check the format specifier */
loop:
switch (*fmt) {
case 'i': /* Fall through to next one */
case 'd':
if (bit64)
num = va_arg(args, int64_t);
else
num = va_arg(args, int32_t);
if (num < 0) {
elog_putchar(elog, '-');
unum = (unsigned long)-num;
} else
unum = (unsigned long)num;
elog_unsigned_num(elog, unum, 10);
break;
case 's':
str = va_arg(args, char *);
elog_string(elog, str);
break;
case 'x':
if (bit64)
unum = va_arg(args, uint64_t);
else
unum = va_arg(args, uint32_t);
elog_unsigned_num(elog, unum, 16);
break;
case 'l':
bit64 = 1;
fmt++;
goto loop;
case 'u':
if (bit64)
unum = va_arg(args, uint64_t);
else
unum = va_arg(args, uint32_t);
elog_unsigned_num(elog, unum, 10);
break;
default:
/* Exit on any other format specifier */
goto exit;
}
fmt++;
continue;
}
elog_putchar(elog, *fmt++);
}
exit:
va_end(args);
}
@@ -0,0 +1,133 @@
/*
* Copyright 2019-2020 Broadcom.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <common/debug.h>
#include <ddr_init.h>
#include <scp_cmd.h>
#include <scp_utils.h>
#include <platform_def.h>
#include "bcm_elog_ddr.h"
#include "m0_cfg.h"
#include "m0_ipc.h"
void elog_init_ddr_log(void)
{
struct elog_setup setup = {0};
struct elog_global_header global;
struct elog_meta_record rec;
unsigned int rec_idx = 0;
uint32_t log_offset;
uintptr_t metadata;
char *rec_desc[ELOG_SUPPORTED_REC_CNT] = {"SYSRESET", "THERMAL",
"DDR_ECC", "APBOOTLG",
"IDM"};
/*
* If this is warm boot, return immediately.
* We expect metadata to be initialized already
*/
if (is_warmboot()) {
WARN("Warmboot detected, skip ELOG metadata initialization\n");
return;
}
memset(&global, 0, sizeof(global));
global.sector_size = ELOG_SECTOR_SIZE;
global.signature = ELOG_GLOBAL_META_HDR_SIG;
global.rec_count = ELOG_SUPPORTED_REC_CNT;
/* Start of logging area in DDR memory */
log_offset = ELOG_STORE_OFFSET;
/* Shift to the first RECORD header */
log_offset += 2 * global.sector_size;
/* Temporary place to hold metadata */
metadata = TMP_ELOG_METADATA_BASE;
memcpy((void *)metadata, &global, sizeof(global));
metadata += sizeof(global);
while (rec_idx < global.rec_count) {
memset(&rec, 0, sizeof(rec));
rec.type = rec_idx;
if (rec_idx == ELOG_REC_UART_LOG) {
rec.format = ELOG_REC_FMT_ASCII;
rec.src_mem_type = ELOG_SRC_MEM_TYPE_DDR;
rec.alt_src_mem_type = ELOG_SRC_MEM_TYPE_FS4_SCRATCH;
rec.src_mem_addr = BCM_ELOG_BL31_BASE;
rec.alt_src_mem_addr = BCM_ELOG_BL2_BASE;
rec.rec_size = ELOG_APBOOTLG_REC_SIZE;
} else if (rec_idx == ELOG_REC_IDM_LOG) {
rec.type = IDM_ELOG_REC_TYPE;
rec.format = ELOG_REC_FMT_CUSTOM;
rec.src_mem_type = ELOG_SRC_MEM_TYPE_DDR;
rec.alt_src_mem_type = ELOG_SRC_MEM_TYPE_CRMU_SCRATCH;
rec.src_mem_addr = ELOG_IDM_SRC_MEM_ADDR;
rec.alt_src_mem_addr = 0x0;
rec.rec_size = ELOG_DEFAULT_REC_SIZE;
} else {
rec.format = ELOG_REC_FMT_CUSTOM;
rec.src_mem_type = ELOG_SRC_MEM_TYPE_CRMU_SCRATCH;
rec.alt_src_mem_type = ELOG_SRC_MEM_TYPE_CRMU_SCRATCH;
rec.src_mem_addr = ELOG_USE_DEFAULT_MEM_ADDR;
rec.alt_src_mem_addr = ELOG_USE_DEFAULT_MEM_ADDR;
rec.rec_size = ELOG_DEFAULT_REC_SIZE;
}
rec.nvm_type = LOG_MEDIA_DDR;
rec.sector_size = ELOG_SECTOR_SIZE;
rec.rec_addr = (uint64_t)log_offset;
log_offset += rec.rec_size;
/* Sanity checks */
if (rec.type > ELOG_MAX_REC_COUNT ||
rec.format > ELOG_MAX_REC_FORMAT ||
(rec.nvm_type > ELOG_MAX_NVM_TYPE &&
rec.nvm_type != ELOG_NVM_DEFAULT) ||
!rec.rec_size ||
!rec.sector_size ||
rec_idx >= ELOG_SUPPORTED_REC_CNT) {
ERROR("Invalid ELOG record(%u) detected\n", rec_idx);
return;
}
memset(rec.rec_desc, ' ', sizeof(rec.rec_desc));
memcpy(rec.rec_desc, rec_desc[rec_idx],
strlen(rec_desc[rec_idx]));
memcpy((void *)metadata, &rec, sizeof(rec));
metadata += sizeof(rec);
rec_idx++;
}
setup.params[0] = TMP_ELOG_METADATA_BASE;
setup.params[1] = (sizeof(global) + global.rec_count * sizeof(rec));
setup.cmd = ELOG_SETUP_CMD_WRITE_META;
flush_dcache_range((uintptr_t)&setup, sizeof(struct elog_setup));
flush_dcache_range((uintptr_t)setup.params[0], setup.params[1]);
/* initialize DDR Logging METADATA if this is NOT warmboot */
if (!is_warmboot()) {
if (scp_send_cmd(MCU_IPC_MCU_CMD_ELOG_SETUP,
(uint32_t)(uintptr_t)(&setup),
SCP_CMD_DEFAULT_TIMEOUT_US)) {
ERROR("scp_send_cmd: timeout/error for elog setup\n");
return;
}
}
NOTICE("MCU Error logging initialized\n");
}
@@ -0,0 +1,107 @@
/*
* Copyright 2019-2020 Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef BCM_ELOG_DDR_H
#define BCM_ELOG_DDR_H
#define ELOG_GLOBAL_META_HDR_SIG 0x45524c47
#define ELOG_MAX_REC_COUNT 13
#define ELOG_MAX_REC_FORMAT 1
#define ELOG_MAX_NVM_TYPE 4
/* Use a default NVM, set by m0 configuration */
#define ELOG_NVM_DEFAULT 0xff
/* Max. number of cmd parameters per elog spec */
#define ELOG_PARAM_COUNT 3
/*
* Number of supported RECORD Types-
* SYSRESET, THERMAL, DDR_ECC, APBOOTLG, IDM
*/
#define ELOG_SUPPORTED_REC_CNT 5
#define ELOG_REC_DESC_LENGTH 8
#define ELOG_SECTOR_SIZE 0x1000
/* Default Record size for all record types except APBOOTLOG */
#define ELOG_DEFAULT_REC_SIZE 0x10000
/* Default record size for APBOOTLOG record */
#define ELOG_APBOOTLG_REC_SIZE 0x60000
/* Use default CRMU provided mem address */
#define ELOG_USE_DEFAULT_MEM_ADDR 0x0
/* Temporary place to hold metadata */
#define TMP_ELOG_METADATA_BASE (ELOG_AP_UART_LOG_BASE + \
BCM_ELOG_BL2_SIZE)
/* IDM ELOG source memory address */
#define ELOG_IDM_SRC_MEM_ADDR 0x8f213000
#define IDM_ELOG_REC_TYPE 5
enum elog_record_type {
ELOG_REC_SYS_RESET_EVT = 0,
ELOG_REC_THERMAL_EVT,
ELOG_REC_DDR_ECC,
ELOG_REC_UART_LOG,
ELOG_REC_IDM_LOG,
ELOG_REC_MAX
};
enum elog_record_format {
ELOG_REC_FMT_ASCII = 0,
ELOG_REC_FMT_CUSTOM
};
enum elog_src_memory_type {
ELOG_SRC_MEM_TYPE_CRMU_SCRATCH = 0,
ELOG_SRC_MEM_TYPE_FS4_SCRATCH,
ELOG_SRC_MEM_TYPE_DDR,
ELOG_SRC_MEM_TYPE_CHIMP_SCRATCH
};
enum elog_setup_cmd {
ELOG_SETUP_CMD_VALIDATE_META,
ELOG_SETUP_CMD_WRITE_META,
ELOG_SETUP_CMD_ERASE,
ELOG_SETUP_CMD_READ,
ELOG_SETUP_CMD_CHECK
};
struct elog_setup {
uint32_t cmd;
uint32_t params[ELOG_PARAM_COUNT];
uint32_t result;
uint32_t ret_code;
};
struct elog_meta_record {
uint8_t type;
uint8_t format;
uint8_t src_mem_type;
uint8_t alt_src_mem_type;
uint8_t nvm_type;
char rec_desc[ELOG_REC_DESC_LENGTH];
uint64_t src_mem_addr;
uint64_t alt_src_mem_addr;
uint64_t rec_addr;
uint32_t rec_size;
uint32_t sector_size;
uint8_t padding[3];
} __packed;
struct elog_global_header {
uint32_t signature;
uint32_t sector_size;
uint8_t revision;
uint8_t rec_count;
uint16_t padding;
} __packed;
void elog_init_ddr_log(void);
#endif /* BCM_ELOG_DDR_H */
@@ -0,0 +1,625 @@
/*
* Copyright 2015 - 2020 Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <inttypes.h>
#include <stdint.h>
#include <string.h>
#include <common/debug.h>
#include <lib/mmio.h>
#include <plat/common/platform.h>
#include <tools_share/tbbr_oid.h>
#include <sbl_util.h>
#include <sotp.h>
/* Weak definition may be overridden in specific platform */
#pragma weak plat_match_rotpk
#pragma weak plat_get_nv_ctr
#pragma weak plat_set_nv_ctr
/* SHA256 algorithm */
#define SHA256_BYTES 32
/* ROTPK locations */
#define ARM_ROTPK_REGS_ID 1
#define ARM_ROTPK_DEVEL_RSA_ID 2
#define BRCM_ROTPK_SOTP_RSA_ID 3
#if !ARM_ROTPK_LOCATION_ID
#error "ARM_ROTPK_LOCATION_ID not defined"
#endif
static const unsigned char rotpk_hash_hdr[] =
"\x30\x31\x30\x0D\x06\x09\x60\x86\x48"
"\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20";
static const unsigned int rotpk_hash_hdr_len = sizeof(rotpk_hash_hdr) - 1;
static unsigned char rotpk_hash_der[sizeof(rotpk_hash_hdr) - 1 + SHA256_BYTES];
#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID)
static const unsigned char arm_devel_rotpk_hash[] =
"\xB0\xF3\x82\x09\x12\x97\xD8\x3A"
"\x37\x7A\x72\x47\x1B\xEC\x32\x73"
"\xE9\x92\x32\xE2\x49\x59\xF6\x5E"
"\x8B\x4A\x4A\x46\xD8\x22\x9A\xDA";
#endif
#pragma weak plat_rotpk_hash
const unsigned char plat_rotpk_hash[] =
"\xdb\x06\x67\x95\x4f\x88\x2b\x88"
"\x49\xbf\x70\x3f\xde\x50\x4a\x96"
"\xd8\x17\x69\xd4\xa0\x6c\xba\xee"
"\x66\x3e\x71\x82\x2d\x95\x69\xe4";
#pragma weak rom_slice
const unsigned char rom_slice[] =
"\x77\x06\xbc\x98\x40\xbe\xfd\xab"
"\x60\x4b\x74\x3c\x9a\xb3\x80\x75"
"\x39\xb6\xda\x27\x07\x2e\x5b\xbf"
"\x5c\x47\x91\xc9\x95\x26\x26\x0c";
#if (ARM_ROTPK_LOCATION_ID == BRCM_ROTPK_SOTP_RSA_ID)
static int plat_is_trusted_boot(void)
{
uint64_t section3_row0_data;
section3_row0_data = sotp_mem_read(SOTP_DEVICE_SECURE_CFG0_ROW, 0);
if ((section3_row0_data & SOTP_DEVICE_SECURE_CFG0_AB_MASK) == 0) {
INFO("NOT AB\n");
return 0;
}
INFO("AB\n");
return TRUSTED_BOARD_BOOT;
}
/*
* FAST AUTH is enabled if all following conditions are met:
* - AB part
* - SOTP.DEV != 0
* - SOTP.CID != 0
* - SOTP.ENC_DEV_TYPE = ENC_AB_DEV
* - Manuf_debug strap set high
*/
static int plat_fast_auth_enabled(void)
{
uint32_t chip_state;
uint64_t section3_row0_data;
uint64_t section3_row1_data;
section3_row0_data =
sotp_mem_read(SOTP_DEVICE_SECURE_CFG0_ROW, 0);
section3_row1_data =
sotp_mem_read(SOTP_DEVICE_SECURE_CFG1_ROW, 0);
chip_state = mmio_read_32(SOTP_REGS_SOTP_CHIP_STATES);
if (plat_is_trusted_boot() &&
(section3_row0_data & SOTP_DEVICE_SECURE_CFG0_DEV_MASK) &&
(section3_row0_data & SOTP_DEVICE_SECURE_CFG0_CID_MASK) &&
((section3_row1_data & SOTP_ENC_DEV_TYPE_MASK) ==
SOTP_ENC_DEV_TYPE_AB_DEV) &&
(chip_state & SOTP_CHIP_STATES_MANU_DEBUG_MASK))
return 1;
return 0;
}
#endif
/*
* Return the ROTPK hash in the following ASN.1 structure in DER format:
*
* AlgorithmIdentifier ::= SEQUENCE {
* algorithm OBJECT IDENTIFIER,
* parameters ANY DEFINED BY algorithm OPTIONAL
* }
*
* DigestInfo ::= SEQUENCE {
* digestAlgorithm AlgorithmIdentifier,
* digest OCTET STRING
* }
*/
int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
unsigned int *flags)
{
uint8_t *dst;
assert(key_ptr != NULL);
assert(key_len != NULL);
assert(flags != NULL);
*flags = 0;
/* Copy the DER header */
memcpy(rotpk_hash_der, rotpk_hash_hdr, rotpk_hash_hdr_len);
dst = (uint8_t *)&rotpk_hash_der[rotpk_hash_hdr_len];
#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID)
memcpy(dst, arm_devel_rotpk_hash, SHA256_BYTES);
#elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID)
uint32_t *src, tmp;
unsigned int words, i;
/*
* Append the hash from Trusted Root-Key Storage registers. The hash has
* not been written linearly into the registers, so we have to do a bit
* of byte swapping:
*
* 0x00 0x04 0x08 0x0C 0x10 0x14 0x18 0x1C
* +---------------------------------------------------------------+
* | Reg0 | Reg1 | Reg2 | Reg3 | Reg4 | Reg5 | Reg6 | Reg7 |
* +---------------------------------------------------------------+
* | ... ... | | ... ... |
* | +--------------------+ | +-------+
* | | | |
* +----------------------------+ +----------------------------+
* | | | |
* +-------+ | +--------------------+ |
* | | | |
* v v v v
* +---------------------------------------------------------------+
* | | |
* +---------------------------------------------------------------+
* 0 15 16 31
*
* Additionally, we have to access the registers in 32-bit words
*/
words = SHA256_BYTES >> 3;
/* Swap bytes 0-15 (first four registers) */
src = (uint32_t *)TZ_PUB_KEY_HASH_BASE;
for (i = 0 ; i < words ; i++) {
tmp = src[words - 1 - i];
/* Words are read in little endian */
*dst++ = (uint8_t)((tmp >> 24) & 0xFF);
*dst++ = (uint8_t)((tmp >> 16) & 0xFF);
*dst++ = (uint8_t)((tmp >> 8) & 0xFF);
*dst++ = (uint8_t)(tmp & 0xFF);
}
/* Swap bytes 16-31 (last four registers) */
src = (uint32_t *)(TZ_PUB_KEY_HASH_BASE + SHA256_BYTES / 2);
for (i = 0 ; i < words ; i++) {
tmp = src[words - 1 - i];
*dst++ = (uint8_t)((tmp >> 24) & 0xFF);
*dst++ = (uint8_t)((tmp >> 16) & 0xFF);
*dst++ = (uint8_t)((tmp >> 8) & 0xFF);
*dst++ = (uint8_t)(tmp & 0xFF);
}
#elif (ARM_ROTPK_LOCATION_ID == BRCM_ROTPK_SOTP_RSA_ID)
{
int i;
int ret = -1;
/*
* In non-AB mode, we do not read the key.
* In AB mode:
* - The Dauth is in BL11 if SBL is enabled
* - The Dauth is in SOTP if SBL is disabled.
*/
if (plat_is_trusted_boot() == 0) {
INFO("NON-AB: Do not read DAUTH!\n");
*flags = ROTPK_NOT_DEPLOYED;
ret = 0;
} else if ((sbl_status() == SBL_ENABLED) &&
(mmio_read_32(BL11_DAUTH_BASE) == BL11_DAUTH_ID)) {
/* Read hash from BL11 */
INFO("readKeys (DAUTH) from BL11\n");
memcpy(dst,
(void *)(BL11_DAUTH_BASE + sizeof(uint32_t)),
SHA256_BYTES);
for (i = 0; i < SHA256_BYTES; i++)
if (dst[i] != 0)
break;
if (i >= SHA256_BYTES)
ERROR("Hash not valid from BL11\n");
else
ret = 0;
} else if (sotp_key_erased()) {
memcpy(dst, plat_rotpk_hash, SHA256_BYTES);
INFO("SOTP erased, Use internal key hash.\n");
ret = 0;
} else if (plat_fast_auth_enabled()) {
INFO("AB DEV: FAST AUTH!\n");
*flags = ROTPK_NOT_DEPLOYED;
ret = 0;
} else if (!(mmio_read_32(SOTP_STATUS_1) & SOTP_DAUTH_ECC_ERROR_MASK)) {
/* Read hash from SOTP */
ret = sotp_read_key(dst,
SHA256_BYTES,
SOTP_DAUTH_ROW,
SOTP_K_HMAC_ROW-1);
INFO("sotp_read_key (DAUTH): %i\n", ret);
} else {
uint64_t row_data;
uint32_t k;
for (k = 0; k < (SOTP_K_HMAC_ROW - SOTP_DAUTH_ROW); k++) {
row_data = sotp_mem_read(SOTP_DAUTH_ROW + k,
SOTP_ROW_NO_ECC);
if (row_data != 0)
break;
}
if (k == (SOTP_K_HMAC_ROW - SOTP_DAUTH_ROW)) {
INFO("SOTP NOT PROGRAMMED: Do not use DAUTH!\n");
if (sotp_mem_read(SOTP_ATF2_CFG_ROW_ID,
SOTP_ROW_NO_ECC) & SOTP_ROMKEY_MASK) {
memcpy(dst, plat_rotpk_hash, SHA256_BYTES);
INFO("Use internal key hash.\n");
ret = 0;
} else {
*flags = ROTPK_NOT_DEPLOYED;
ret = 0;
}
} else {
INFO("No hash found in SOTP\n");
}
}
if (ret)
return ret;
}
#endif
*key_ptr = (void *)rotpk_hash_der;
*key_len = (unsigned int)sizeof(rotpk_hash_der);
*flags |= ROTPK_IS_HASH;
return 0;
}
#define SOTP_NUM_BITS_PER_ROW 41
#define SOTP_NVCTR_ROW_ALL_ONES 0x1ffffffffff
#define SOTP_NVCTR_TRUSTED_IN_USE \
((uint64_t)0x3 << (SOTP_NUM_BITS_PER_ROW-2))
#define SOTP_NVCTR_NON_TRUSTED_IN_USE ((uint64_t)0x3)
#define SOTP_NVCTR_TRUSTED_NEAR_END SOTP_NVCTR_NON_TRUSTED_IN_USE
#define SOTP_NVCTR_NON_TRUSTED_NEAR_END SOTP_NVCTR_TRUSTED_IN_USE
#define SOTP_NVCTR_ROW_START 64
#define SOTP_NVCTR_ROW_END 75
/*
* SOTP NVCTR are stored in section 10 of SOTP (rows 64-75).
* Each row of SOTP is 41 bits.
* NVCTR's are stored in a bitstream format.
* We are tolerant to consecutive bit errors.
* Trusted NVCTR starts at the top of row 64 in bitstream format.
* Non Trusted NVCTR starts at the bottom of row 75 in reverse bitstream.
* Each row can only be used by 1 of the 2 counters. This is determined
* by 2 zeros remaining at the beginning or end of the last available row.
* If one counter has already starting using a row, the other will be
* prevent from writing to that row.
*
* Example counter values for SOTP programmed below:
* Trusted Counter (rows64-69) = 5 * 41 + 40 = 245
* NonTrusted Counter (row75-71) = 3 * 41 + 4 = 127
* 40 39 38 37 36 ..... 5 4 3 2 1 0
* row 64 1 1 1 1 1 1 1 1 1 1 1
* row 65 1 1 1 1 1 1 1 1 1 1 1
* row 66 1 1 1 1 1 1 1 1 1 1 1
* row 67 1 1 1 1 1 1 1 1 1 1 1
* row 68 1 1 1 1 1 1 1 1 1 1 1
* row 69 1 1 1 1 1 1 1 1 1 1 0
* row 71 0 0 0 0 0 0 0 0 0 0 0
* row 71 0 0 0 0 0 0 0 0 0 0 0
* row 71 0 0 0 0 0 0 0 1 1 1 1
* row 73 1 1 1 1 1 1 1 1 1 1 1
* row 74 1 1 1 1 1 1 1 1 1 1 1
* row 75 1 1 1 1 1 1 1 1 1 1 1
*
*/
#if (DEBUG == 1)
/*
* Dump sotp rows
*/
void sotp_dump_rows(uint32_t start_row, uint32_t end_row)
{
int32_t rownum;
uint64_t rowdata;
for (rownum = start_row; rownum <= end_row; rownum++) {
rowdata = sotp_mem_read(rownum, SOTP_ROW_NO_ECC);
INFO("%d 0x%" PRIx64 "\n", rownum, rowdata);
}
}
#endif
/*
* Get SOTP Trusted nvctr
*/
unsigned int sotp_get_trusted_nvctr(void)
{
uint64_t rowdata;
uint64_t nextrowdata;
uint32_t rownum;
unsigned int nvctr;
rownum = SOTP_NVCTR_ROW_START;
nvctr = SOTP_NUM_BITS_PER_ROW;
/*
* Determine what row has last valid data for trusted ctr
*/
rowdata = sotp_mem_read(rownum, SOTP_ROW_NO_ECC);
while ((rowdata & SOTP_NVCTR_TRUSTED_IN_USE) &&
(rowdata & SOTP_NVCTR_TRUSTED_NEAR_END) &&
(rownum < SOTP_NVCTR_ROW_END)) {
/*
* Current row in use and has data in last 2 bits as well.
* Check if next row also has data for this counter
*/
nextrowdata = sotp_mem_read(rownum+1, SOTP_ROW_NO_ECC);
if (nextrowdata & SOTP_NVCTR_TRUSTED_IN_USE) {
/* Next row also has data so increment rownum */
rownum++;
nvctr += SOTP_NUM_BITS_PER_ROW;
rowdata = nextrowdata;
} else {
/* Next row does not have data */
break;
}
}
if (rowdata & SOTP_NVCTR_TRUSTED_IN_USE) {
while ((rowdata & 0x1) == 0) {
nvctr--;
rowdata >>= 1;
}
} else
nvctr -= SOTP_NUM_BITS_PER_ROW;
INFO("CTR %i\n", nvctr);
return nvctr;
}
/*
* Get SOTP NonTrusted nvctr
*/
unsigned int sotp_get_nontrusted_nvctr(void)
{
uint64_t rowdata;
uint64_t nextrowdata;
uint32_t rownum;
unsigned int nvctr;
nvctr = SOTP_NUM_BITS_PER_ROW;
rownum = SOTP_NVCTR_ROW_END;
/*
* Determine what row has last valid data for nontrusted ctr
*/
rowdata = sotp_mem_read(rownum, SOTP_ROW_NO_ECC);
while ((rowdata & SOTP_NVCTR_NON_TRUSTED_NEAR_END) &&
(rowdata & SOTP_NVCTR_NON_TRUSTED_IN_USE) &&
(rownum > SOTP_NVCTR_ROW_START)) {
/*
* Current row in use and has data in last 2 bits as well.
* Check if next row also has data for this counter
*/
nextrowdata = sotp_mem_read(rownum-1, SOTP_ROW_NO_ECC);
if (nextrowdata & SOTP_NVCTR_NON_TRUSTED_IN_USE) {
/* Next row also has data so decrement rownum */
rownum--;
nvctr += SOTP_NUM_BITS_PER_ROW;
rowdata = nextrowdata;
} else {
/* Next row does not have data */
break;
}
}
if (rowdata & SOTP_NVCTR_NON_TRUSTED_IN_USE) {
while ((rowdata & ((uint64_t)0x1 << (SOTP_NUM_BITS_PER_ROW-1)))
==
0) {
nvctr--;
rowdata <<= 1;
}
} else
nvctr -= SOTP_NUM_BITS_PER_ROW;
INFO("NCTR %i\n", nvctr);
return nvctr;
}
/*
* Set SOTP Trusted nvctr
*/
int sotp_set_trusted_nvctr(unsigned int nvctr)
{
int numrows_available;
uint32_t nontrusted_rownum;
uint32_t trusted_rownum;
uint64_t rowdata;
unsigned int maxnvctr;
/*
* Read SOTP to find out how many rows are used by the
* NON Trusted nvctr
*/
nontrusted_rownum = SOTP_NVCTR_ROW_END;
do {
rowdata = sotp_mem_read(nontrusted_rownum, SOTP_ROW_NO_ECC);
if (rowdata & SOTP_NVCTR_NON_TRUSTED_IN_USE)
nontrusted_rownum--;
else
break;
} while (nontrusted_rownum >= SOTP_NVCTR_ROW_START);
/*
* Calculate maximum value we can have for nvctr based on
* number of available rows.
*/
numrows_available = nontrusted_rownum - SOTP_NVCTR_ROW_START + 1;
maxnvctr = numrows_available * SOTP_NUM_BITS_PER_ROW;
if (maxnvctr) {
/*
* Last 2 bits of counter can't be written or it will
* overflow with nontrusted counter
*/
maxnvctr -= 2;
}
if (nvctr > maxnvctr) {
/* Error - not enough room */
WARN("tctr not set\n");
return 1;
}
/*
* It is safe to write the nvctr, fill all 1's up to the
* last row and then fill the last row with partial bitstream
*/
trusted_rownum = SOTP_NVCTR_ROW_START;
rowdata = SOTP_NVCTR_ROW_ALL_ONES;
while (nvctr >= SOTP_NUM_BITS_PER_ROW) {
sotp_mem_write(trusted_rownum, SOTP_ROW_NO_ECC, rowdata);
nvctr -= SOTP_NUM_BITS_PER_ROW;
trusted_rownum++;
}
rowdata <<= (SOTP_NUM_BITS_PER_ROW - nvctr);
sotp_mem_write(trusted_rownum, SOTP_ROW_NO_ECC, rowdata);
return 0;
}
/*
* Set SOTP NonTrusted nvctr
*/
int sotp_set_nontrusted_nvctr(unsigned int nvctr)
{
int numrows_available;
uint32_t nontrusted_rownum;
uint32_t trusted_rownum;
uint64_t rowdata;
unsigned int maxnvctr;
/*
* Read SOTP to find out how many rows are used by the
* Trusted nvctr
*/
trusted_rownum = SOTP_NVCTR_ROW_START;
do {
rowdata = sotp_mem_read(trusted_rownum, SOTP_ROW_NO_ECC);
if (rowdata & SOTP_NVCTR_TRUSTED_IN_USE)
trusted_rownum++;
else
break;
} while (trusted_rownum <= SOTP_NVCTR_ROW_END);
/*
* Calculate maximum value we can have for nvctr based on
* number of available rows.
*/
numrows_available = SOTP_NVCTR_ROW_END - trusted_rownum + 1;
maxnvctr = numrows_available * SOTP_NUM_BITS_PER_ROW;
if (maxnvctr) {
/*
* Last 2 bits of counter can't be written or it will
* overflow with nontrusted counter
*/
maxnvctr -= 2;
}
if (nvctr > maxnvctr) {
/* Error - not enough room */
WARN("nctr not set\n");
return 1;
}
/*
* It is safe to write the nvctr, fill all 1's up to the
* last row and then fill the last row with partial bitstream
*/
nontrusted_rownum = SOTP_NVCTR_ROW_END;
rowdata = SOTP_NVCTR_ROW_ALL_ONES;
while (nvctr >= SOTP_NUM_BITS_PER_ROW) {
sotp_mem_write(nontrusted_rownum, SOTP_ROW_NO_ECC, rowdata);
nvctr -= SOTP_NUM_BITS_PER_ROW;
nontrusted_rownum--;
}
rowdata >>= (SOTP_NUM_BITS_PER_ROW - nvctr);
sotp_mem_write(nontrusted_rownum, SOTP_ROW_NO_ECC, rowdata);
return 0;
}
/*
* Return the non-volatile counter value stored in the platform. The cookie
* will contain the OID of the counter in the certificate.
*
* Return: 0 = success, Otherwise = error
*/
int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
{
const char *oid;
assert(cookie != NULL);
assert(nv_ctr != NULL);
*nv_ctr = 0;
if ((sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC) &
SOTP_ATF_NVCOUNTER_ENABLE_MASK)) {
oid = (const char *)cookie;
if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0)
*nv_ctr = sotp_get_trusted_nvctr();
else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0)
*nv_ctr = sotp_get_nontrusted_nvctr();
else
return 1;
}
return 0;
}
/*
* Store a new non-volatile counter value.
*
* Return: 0 = success, Otherwise = error
*/
int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
{
const char *oid;
if (sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC) &
SOTP_ATF_NVCOUNTER_ENABLE_MASK) {
INFO("set CTR %i\n", nv_ctr);
oid = (const char *)cookie;
if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0)
return sotp_set_trusted_nvctr(nv_ctr);
else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0)
return sotp_set_nontrusted_nvctr(nv_ctr);
return 1;
}
return 0;
}
int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
{
return get_mbedtls_heap_helper(heap_addr, heap_size);
}
@@ -0,0 +1,74 @@
/*
* Copyright (c) 2016 - 2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <brcm_def.h>
#include <plat_brcm.h>
#if IMAGE_BL2
const mmap_region_t plat_brcm_mmap[] = {
HSLS_REGION,
BRCM_MAP_SHARED_RAM,
BRCM_MAP_NAND_RO,
BRCM_MAP_QSPI_RO,
#ifdef PERIPH0_REGION
PERIPH0_REGION,
#endif
#ifdef PERIPH1_REGION
PERIPH1_REGION,
#endif
#ifdef USE_DDR
BRCM_MAP_NS_DRAM1,
#if BRCM_BL31_IN_DRAM
BRCM_MAP_BL31_SEC_DRAM,
#endif
#else
#ifdef BRCM_MAP_EXT_SRAM
BRCM_MAP_EXT_SRAM,
#endif
#endif
#if defined(USE_CRMU_SRAM) && defined(CRMU_SRAM_BASE)
CRMU_SRAM_REGION,
#endif
{0}
};
#endif
#if IMAGE_BL31
const mmap_region_t plat_brcm_mmap[] = {
HSLS_REGION,
#ifdef PERIPH0_REGION
PERIPH0_REGION,
#endif
#ifdef PERIPH1_REGION
PERIPH1_REGION,
#endif
#ifdef PERIPH2_REGION
PERIPH2_REGION,
#endif
#ifdef USB_REGION
USB_REGION,
#endif
#ifdef USE_DDR
BRCM_MAP_NS_DRAM1,
#ifdef BRCM_MAP_NS_SHARED_DRAM
BRCM_MAP_NS_SHARED_DRAM,
#endif
#else
#ifdef BRCM_MAP_EXT_SRAM
BRCM_MAP_EXT_SRAM,
#endif
#endif
#if defined(USE_CRMU_SRAM) && defined(CRMU_SRAM_BASE)
CRMU_SRAM_REGION,
#endif
{0}
};
#endif
CASSERT((ARRAY_SIZE(plat_brcm_mmap) - 1) <= PLAT_BRCM_MMAP_ENTRIES,
assert_plat_brcm_mmap_mismatch);
CASSERT((PLAT_BRCM_MMAP_ENTRIES + BRCM_BL_REGIONS) <= MAX_MMAP_REGIONS,
assert_max_mmap_regions);
@@ -0,0 +1,294 @@
#
# Copyright (c) 2015 - 2021, Broadcom
#
# SPDX-License-Identifier: BSD-3-Clause
#
PLAT_BL_COMMON_SOURCES += plat/brcm/board/common/board_common.c
# If no board config makefile, do not include it
ifneq (${BOARD_CFG},)
BOARD_CFG_MAKE := $(shell find plat/brcm/board/${PLAT} -name '${BOARD_CFG}.mk')
$(eval $(call add_define,BOARD_CFG))
ifneq (${BOARD_CFG_MAKE},)
$(info Including ${BOARD_CFG_MAKE})
include ${BOARD_CFG_MAKE}
else
$(error Error: File ${BOARD_CFG}.mk not found in plat/brcm/board/${PLAT})
endif
endif
# To compile with highest log level (VERBOSE) set value to 50
LOG_LEVEL := 40
# Use custom generic timer clock
ifneq (${GENTIMER_ACTUAL_CLOCK},)
$(info Using GENTIMER_ACTUAL_CLOCK=$(GENTIMER_ACTUAL_CLOCK))
SYSCNT_FREQ := $(GENTIMER_ACTUAL_CLOCK)
$(eval $(call add_define,SYSCNT_FREQ))
endif
ifeq (${DRIVER_EMMC_ENABLE},)
DRIVER_EMMC_ENABLE :=1
endif
ifeq (${DRIVER_SPI_ENABLE},)
DRIVER_SPI_ENABLE := 0
endif
ifeq (${DRIVER_I2C_ENABLE},)
DRIVER_I2C_ENABLE := 0
endif
# By default, Trusted Watchdog is always enabled unless SPIN_ON_BL1_EXIT is set
ifeq (${BRCM_DISABLE_TRUSTED_WDOG},)
BRCM_DISABLE_TRUSTED_WDOG := 0
endif
ifeq (${SPIN_ON_BL1_EXIT}, 1)
BRCM_DISABLE_TRUSTED_WDOG := 1
endif
$(eval $(call assert_boolean,BRCM_DISABLE_TRUSTED_WDOG))
$(eval $(call add_define,BRCM_DISABLE_TRUSTED_WDOG))
# Process ARM_BL31_IN_DRAM flag
ifeq (${ARM_BL31_IN_DRAM},)
ARM_BL31_IN_DRAM := 0
endif
$(eval $(call assert_boolean,ARM_BL31_IN_DRAM))
$(eval $(call add_define,ARM_BL31_IN_DRAM))
ifeq (${STANDALONE_BL2},yes)
BL2_LOG_LEVEL := 40
$(eval $(call add_define,MMU_DISABLED))
endif
# BL2 XIP from QSPI
RUN_BL2_FROM_QSPI := 0
ifeq (${RUN_BL2_FROM_QSPI},1)
$(eval $(call add_define,RUN_BL2_FROM_QSPI))
endif
# BL2 XIP from NAND
RUN_BL2_FROM_NAND := 0
ifeq (${RUN_BL2_FROM_NAND},1)
$(eval $(call add_define,RUN_BL2_FROM_NAND))
endif
ifneq (${ELOG_AP_UART_LOG_BASE},)
$(eval $(call add_define,ELOG_AP_UART_LOG_BASE))
endif
ifeq (${ELOG_SUPPORT},1)
ifeq (${ELOG_STORE_MEDIA},DDR)
$(eval $(call add_define,ELOG_STORE_MEDIA_DDR))
ifneq (${ELOG_STORE_OFFSET},)
$(eval $(call add_define,ELOG_STORE_OFFSET))
endif
endif
endif
ifneq (${BL2_LOG_LEVEL},)
$(eval $(call add_define,BL2_LOG_LEVEL))
endif
ifneq (${BL31_LOG_LEVEL},)
$(eval $(call add_define,BL31_LOG_LEVEL))
endif
# Use CRMU SRAM from iHOST
ifneq (${USE_CRMU_SRAM},)
$(eval $(call add_define,USE_CRMU_SRAM))
endif
# Use PIO mode if DDR is not used
ifeq (${USE_DDR},yes)
EMMC_USE_DMA := 1
else
EMMC_USE_DMA := 0
endif
$(eval $(call add_define,EMMC_USE_DMA))
# On BRCM platforms, separate the code and read-only data sections to allow
# mapping the former as executable and the latter as execute-never.
SEPARATE_CODE_AND_RODATA := 1
# Use generic OID definition (tbbr_oid.h)
USE_TBBR_DEFS := 1
PLAT_INCLUDES += -Iplat/brcm/board/common \
-Iinclude/drivers/brcm \
-Iinclude/drivers/brcm/emmc \
-Iinclude/drivers/brcm/mdio
PLAT_BL_COMMON_SOURCES += plat/brcm/common/brcm_common.c \
plat/brcm/board/common/cmn_sec.c \
plat/brcm/board/common/bcm_console.c \
plat/brcm/board/common/brcm_mbedtls.c \
plat/brcm/board/common/plat_setup.c \
plat/brcm/board/common/platform_common.c \
drivers/arm/sp804/sp804_delay_timer.c \
drivers/brcm/sotp.c \
drivers/delay_timer/delay_timer.c \
drivers/io/io_fip.c \
drivers/io/io_memmap.c \
drivers/io/io_storage.c \
plat/brcm/common/brcm_io_storage.c \
plat/brcm/board/common/err.c \
plat/brcm/board/common/sbl_util.c \
drivers/arm/sp805/sp805.c
# Add RNG driver
DRIVER_RNG_ENABLE := 1
ifeq (${DRIVER_RNG_ENABLE},1)
PLAT_BL_COMMON_SOURCES += drivers/brcm/rng.c
endif
# Add eMMC driver
ifeq (${DRIVER_EMMC_ENABLE},1)
$(eval $(call add_define,DRIVER_EMMC_ENABLE))
EMMC_SOURCES += drivers/brcm/emmc/emmc_chal_sd.c \
drivers/brcm/emmc/emmc_csl_sdcard.c \
drivers/brcm/emmc/emmc_csl_sdcmd.c \
drivers/brcm/emmc/emmc_pboot_hal_memory_drv.c
PLAT_BL_COMMON_SOURCES += ${EMMC_SOURCES}
ifeq (${DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT},)
$(eval $(call add_define,DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT))
endif
endif
BL2_SOURCES += plat/brcm/common/brcm_bl2_mem_params_desc.c \
plat/brcm/common/brcm_image_load.c \
common/desc_image_load.c
BL2_SOURCES += plat/brcm/common/brcm_bl2_setup.c
BL31_SOURCES += plat/brcm/common/brcm_bl31_setup.c
ifeq (${BCM_ELOG},yes)
ELOG_SOURCES += plat/brcm/board/common/bcm_elog.c
BL2_SOURCES += ${ELOG_SOURCES}
BL31_SOURCES += ${ELOG_SOURCES}
endif
# Add spi driver
ifeq (${DRIVER_SPI_ENABLE},1)
PLAT_BL_COMMON_SOURCES += drivers/brcm/spi/iproc_spi.c \
drivers/brcm/spi/iproc_qspi.c
endif
# Add spi nor/flash driver
ifeq (${DRIVER_SPI_NOR_ENABLE},1)
PLAT_BL_COMMON_SOURCES += drivers/brcm/spi_sf.c \
drivers/brcm/spi_flash.c
endif
ifeq (${DRIVER_I2C_ENABLE},1)
$(eval $(call add_define,DRIVER_I2C_ENABLE))
BL2_SOURCES += drivers/brcm/i2c/i2c.c
PLAT_INCLUDES += -Iinclude/drivers/brcm/i2c
endif
ifeq (${DRIVER_OCOTP_ENABLE},1)
$(eval $(call add_define,DRIVER_OCOTP_ENABLE))
BL2_SOURCES += drivers/brcm/ocotp.c
endif
# Enable FRU table support
ifeq (${USE_FRU},yes)
$(eval $(call add_define,USE_FRU))
BL2_SOURCES += drivers/brcm/fru.c
endif
# Enable GPIO support
ifeq (${USE_GPIO},yes)
$(eval $(call add_define,USE_GPIO))
BL2_SOURCES += drivers/gpio/gpio.c
BL2_SOURCES += drivers/brcm/iproc_gpio.c
ifeq (${GPIO_SUPPORT_FLOAT_DETECTION},yes)
$(eval $(call add_define,GPIO_SUPPORT_FLOAT_DETECTION))
endif
endif
# Include mbedtls if it can be located
MBEDTLS_DIR ?= mbedtls
MBEDTLS_CHECK := $(shell find ${MBEDTLS_DIR}/include -name '$(notdir ${MBEDTLS_DIR})')
ifneq (${MBEDTLS_CHECK},)
$(info Found mbedTLS at ${MBEDTLS_DIR})
PLAT_INCLUDES += -I${MBEDTLS_DIR}/include/mbedtls
# By default, use RSA keys
KEY_ALG := rsa_1_5
# Include common TBB sources
AUTH_SOURCES += drivers/auth/auth_mod.c \
drivers/auth/crypto_mod.c \
drivers/auth/img_parser_mod.c \
drivers/auth/tbbr/tbbr_cot_common.c \
drivers/auth/tbbr/tbbr_cot_bl2.c
BL2_SOURCES += ${AUTH_SOURCES}
# Use ATF framework for MBEDTLS
TRUSTED_BOARD_BOOT := 1
CRYPTO_LIB_MK := drivers/auth/mbedtls/mbedtls_crypto.mk
IMG_PARSER_LIB_MK := drivers/auth/mbedtls/mbedtls_x509.mk
$(info Including ${CRYPTO_LIB_MK})
include ${CRYPTO_LIB_MK}
$(info Including ${IMG_PARSER_LIB_MK})
include ${IMG_PARSER_LIB_MK}
# Use ATF secure boot functions
# Use Hardcoded hash for devel
ARM_ROTPK_LOCATION=arm_rsa
ifeq (${ARM_ROTPK_LOCATION}, arm_rsa)
ARM_ROTPK_LOCATION_ID=ARM_ROTPK_DEVEL_RSA_ID
ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem
else ifeq (${ARM_ROTPK_LOCATION}, brcm_rsa)
ARM_ROTPK_LOCATION_ID=BRCM_ROTPK_SOTP_RSA_ID
ifeq (${ROT_KEY},)
ROT_KEY=plat/brcm/board/common/rotpk/rsa_dauth2048_key.pem
endif
KEY_FIND := $(shell m="${ROT_KEY}"; [ -f "$$m" ] && echo "$$m")
ifeq (${KEY_FIND},)
$(error Error: No ${ROT_KEY} located)
else
$(info Using ROT_KEY: ${ROT_KEY})
endif
else
$(error "Unsupported ARM_ROTPK_LOCATION value")
endif
$(eval $(call add_define,ARM_ROTPK_LOCATION_ID))
PLAT_BL_COMMON_SOURCES+=plat/brcm/board/common/board_arm_trusted_boot.c
endif
#M0 runtime firmware
ifdef SCP_BL2
$(eval $(call add_define,NEED_SCP_BL2))
SCP_CFG_DIR=$(dir ${SCP_BL2})
PLAT_INCLUDES += -I${SCP_CFG_DIR}
endif
ifneq (${NEED_BL33},yes)
# If there is no BL33, BL31 will jump to this address.
ifeq (${USE_DDR},yes)
PRELOADED_BL33_BASE := 0x80000000
else
PRELOADED_BL33_BASE := 0x74000000
endif
endif
# Use translation tables library v1 by default
ARM_XLAT_TABLES_LIB_V1 := 1
ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1)
$(eval $(call assert_boolean,ARM_XLAT_TABLES_LIB_V1))
$(eval $(call add_define,ARM_XLAT_TABLES_LIB_V1))
PLAT_BL_COMMON_SOURCES += lib/xlat_tables/aarch64/xlat_tables.c \
lib/xlat_tables/xlat_tables_common.c
endif
@@ -0,0 +1,12 @@
/*
* Copyright 2015 - 2020 Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common/debug.h>
void tls_exit(int code)
{
INFO("%s: 0x%x\n", __func__, code);
}
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2017 - 2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef CHIP_ID_H
#define CHIP_ID_H
#include <lib/mmio.h>
#include <platform_def.h>
#define CHIP_REV_MAJOR_MASK 0xF0
#define CHIP_REV_MAJOR_AX 0x00
#define CHIP_REV_MAJOR_BX 0x10
#define CHIP_REV_MAJOR_CX 0x20
#define CHIP_REV_MAJOR_DX 0x30
/* Get Chip ID (product number) of the chip */
static inline unsigned int chip_get_product_id(void)
{
return PLAT_CHIP_ID_GET;
}
/* Get Revision ID (major and minor) number of the chip */
static inline unsigned int chip_get_rev_id(void)
{
return PLAT_CHIP_REV_GET;
}
static inline unsigned int chip_get_rev_id_major(void)
{
return (chip_get_rev_id() & CHIP_REV_MAJOR_MASK);
}
#endif
@@ -0,0 +1,82 @@
/*
* Copyright (c) 2015 - 2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef CMN_PLAT_DEF_H
#define CMN_PLAT_DEF_H
#include <bcm_elog.h>
#include <platform_def.h>
#ifndef GET_LOG_LEVEL
#define GET_LOG_LEVEL() LOG_LEVEL
#endif
#ifndef SET_LOG_LEVEL
#define SET_LOG_LEVEL(x) ((void)(x))
#endif
#define PLAT_LOG_NOTICE(...) \
do { \
if (GET_LOG_LEVEL() >= LOG_LEVEL_NOTICE) { \
bcm_elog(LOG_MARKER_NOTICE __VA_ARGS__); \
tf_log(LOG_MARKER_NOTICE __VA_ARGS__); \
} \
} while (0)
#define PLAT_LOG_ERROR(...) \
do { \
if (GET_LOG_LEVEL() >= LOG_LEVEL_ERROR) { \
bcm_elog(LOG_MARKER_ERROR, __VA_ARGS__); \
tf_log(LOG_MARKER_ERROR __VA_ARGS__); \
} \
} while (0)
#define PLAT_LOG_WARN(...) \
do { \
if (GET_LOG_LEVEL() >= LOG_LEVEL_WARNING) { \
bcm_elog(LOG_MARKER_WARNING, __VA_ARGS__);\
tf_log(LOG_MARKER_WARNING __VA_ARGS__); \
} \
} while (0)
#define PLAT_LOG_INFO(...) \
do { \
if (GET_LOG_LEVEL() >= LOG_LEVEL_INFO) { \
bcm_elog(LOG_MARKER_INFO __VA_ARGS__); \
tf_log(LOG_MARKER_INFO __VA_ARGS__); \
} \
} while (0)
#define PLAT_LOG_VERBOSE(...) \
do { \
if (GET_LOG_LEVEL() >= LOG_LEVEL_VERBOSE) { \
bcm_elog(LOG_MARKER_VERBOSE __VA_ARGS__);\
tf_log(LOG_MARKER_VERBOSE __VA_ARGS__); \
} \
} while (0)
/*
* The number of regions like RO(code), coherent and data required by
* different BL stages which need to be mapped in the MMU.
*/
#if USE_COHERENT_MEM
#define CMN_BL_REGIONS 3
#else
#define CMN_BL_REGIONS 2
#endif
/*
* FIP definitions
*/
#define PLAT_FIP_ATTEMPT_OFFSET 0x20000
#define PLAT_FIP_NUM_ATTEMPTS 128
#define PLAT_BRCM_FIP_QSPI_BASE QSPI_BASE_ADDR
#define PLAT_BRCM_FIP_NAND_BASE NAND_BASE_ADDR
#define PLAT_BRCM_FIP_MAX_SIZE 0x01000000
#define PLAT_BRCM_FIP_BASE PLAT_BRCM_FIP_QSPI_BASE
#endif
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2015 - 2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef CMN_PLAT_UTIL_H
#define CMN_PLAT_UTIL_H
#include <lib/mmio.h>
/* BOOT source */
#define BOOT_SOURCE_MASK 7
#define BOOT_SOURCE_QSPI 0
#define BOOT_SOURCE_NAND 1
#define BOOT_SOURCE_SPI_NAND 2
#define BOOT_SOURCE_UART 3
#define BOOT_SOURCE_RES4 4
#define BOOT_SOURCE_EMMC 5
#define BOOT_SOURCE_ATE 6
#define BOOT_SOURCE_USB 7
#define BOOT_SOURCE_MAX 8
#define BOOT_SOURCE_UNKNOWN (-1)
#define KHMAC_SHA256_KEY_SIZE 32
#define SOFT_PWR_UP_RESET_L0 0
#define SOFT_SYS_RESET_L1 1
#define SOFT_RESET_L3 0x3
#define BOOT_SOURCE_SOFT_DATA_OFFSET 8
#define BOOT_SOURCE_SOFT_ENABLE_OFFSET 14
#define BOOT_SOURCE_SOFT_ENABLE_MASK BIT(BOOT_SOURCE_SOFT_ENABLE_OFFSET)
typedef struct _key {
uint8_t hmac_sha256[KHMAC_SHA256_KEY_SIZE];
} cmn_key_t;
uint32_t boot_source_get(void);
void bl1_platform_wait_events(void);
void plat_soft_reset(uint32_t reset);
#endif
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2015-2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdint.h>
#include <common/debug.h>
#include <lib/mmio.h>
#include <cmn_sec.h>
#pragma weak plat_tz_master_default_cfg
#pragma weak plat_tz_sdio_ns_master_set
#pragma weak plat_tz_usb_ns_master_set
void plat_tz_master_default_cfg(void)
{
/* This function should be implemented in the platform side. */
ERROR("%s: TZ CONFIGURATION NOT SET!!!\n", __func__);
}
void plat_tz_sdio_ns_master_set(uint32_t ns)
{
/* This function should be implemented in the platform side. */
ERROR("%s: TZ CONFIGURATION NOT SET!!!\n", __func__);
}
void plat_tz_usb_ns_master_set(uint32_t ns)
{
/* This function should be implemented in the platform side. */
ERROR("%s: TZ CONFIGURATION NOT SET!!!\n", __func__);
}
void tz_master_default_cfg(void)
{
plat_tz_master_default_cfg();
}
void tz_sdio_ns_master_set(uint32_t ns)
{
plat_tz_sdio_ns_master_set(ns);
}
void tz_usb_ns_master_set(uint32_t ns)
{
plat_tz_usb_ns_master_set(ns);
}
@@ -0,0 +1,19 @@
/*
* Copyright (c) 2015-2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef CMN_SEC_H
#define CMN_SEC_H
#include <stdint.h>
#define SECURE_MASTER 0
#define NS_MASTER 1
void tz_master_default_cfg(void);
void tz_usb_ns_master_set(uint32_t ns);
void tz_sdio_ns_master_set(uint32_t ns);
#endif
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2016 - 2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdint.h>
#include <arch_helpers.h>
#include <common/debug.h>
#include <drivers/console.h>
#include <lib/mmio.h>
#include <platform_def.h>
#define L0_RESET 0x2
/*
* Brcm error handler
*/
void plat_error_handler(int err)
{
INFO("L0 reset...\n");
/* Ensure the characters are flushed out */
console_flush();
mmio_write_32(CRMU_SOFT_RESET_CTRL, L0_RESET);
/*
* In case we get here:
* Loop until the watchdog resets the system
*/
while (1) {
wfi();
}
}
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2015 - 2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <plat/common/platform.h>
#include <platform_def.h>
/*
* This function returns the fixed clock frequency at which private
* timers run. This value will be programmed into CNTFRQ_EL0.
*/
unsigned int plat_get_syscnt_freq2(void)
{
return SYSCNT_FREQ;
}
static const char * const plat_prefix_str[] = {
"E: ", "N: ", "W: ", "I: ", "V: "
};
const char *plat_log_get_prefix(unsigned int log_level)
{
return plat_prefix_str[log_level - 1U];
}
@@ -0,0 +1,94 @@
/*
* Copyright (c) 2015-2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <common/debug.h>
#include <drivers/brcm/sotp.h>
#include <cmn_plat_util.h>
#include <platform_def.h>
uint32_t boot_source_get(void)
{
uint32_t data;
#ifdef FORCE_BOOTSOURCE
data = FORCE_BOOTSOURCE;
#else
/* Read primary boot strap from CRMU persistent registers */
data = mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG1);
if (data & BOOT_SOURCE_SOFT_ENABLE_MASK) {
data >>= BOOT_SOURCE_SOFT_DATA_OFFSET;
} else {
uint64_t sotp_atf_row;
sotp_atf_row =
sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC);
if (sotp_atf_row & SOTP_BOOT_SOURCE_ENABLE_MASK) {
/* Construct the boot source based on SOTP bits */
data = 0;
if (sotp_atf_row & SOTP_BOOT_SOURCE_BITS0)
data |= 0x1;
if (sotp_atf_row & SOTP_BOOT_SOURCE_BITS1)
data |= 0x2;
if (sotp_atf_row & SOTP_BOOT_SOURCE_BITS2)
data |= 0x4;
} else {
/*
* This path is for L0 reset with
* Primary Boot source disabled in SOTP.
* BOOT_SOURCE_FROM_PR_ON_L1 compile flag will allow
* to never come back here so that the
* external straps will not be read on L1 reset.
*/
/* Use the external straps */
data = mmio_read_32(ROM_S0_IDM_IO_STATUS);
#ifdef BOOT_SOURCE_FROM_PR_ON_L1
/* Enable boot source read from PR#1 */
mmio_setbits_32(CRMU_IHOST_SW_PERSISTENT_REG1,
BOOT_SOURCE_SOFT_ENABLE_MASK);
/* set boot source */
data &= BOOT_SOURCE_MASK;
mmio_clrsetbits_32(CRMU_IHOST_SW_PERSISTENT_REG1,
BOOT_SOURCE_MASK << BOOT_SOURCE_SOFT_DATA_OFFSET,
data << BOOT_SOURCE_SOFT_DATA_OFFSET);
#endif
}
}
#endif
return (data & BOOT_SOURCE_MASK);
}
void __dead2 plat_soft_reset(uint32_t reset)
{
if (reset == SOFT_RESET_L3) {
mmio_setbits_32(CRMU_IHOST_SW_PERSISTENT_REG1, reset);
mmio_write_32(CRMU_MAIL_BOX0, 0x0);
mmio_write_32(CRMU_MAIL_BOX1, 0xFFFFFFFF);
}
if (reset != SOFT_SYS_RESET_L1)
reset = SOFT_PWR_UP_RESET_L0;
if (reset == SOFT_PWR_UP_RESET_L0)
INFO("L0 RESET...\n");
if (reset == SOFT_SYS_RESET_L1)
INFO("L1 RESET...\n");
console_flush();
mmio_clrbits_32(CRMU_SOFT_RESET_CTRL, 1 << reset);
while (1) {
;
}
}
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2015 - 2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdint.h>
#include <common/debug.h>
#include <platform_def.h>
#include <sbl_util.h>
#include <sotp.h>
#pragma weak plat_sbl_status
int plat_sbl_status(uint64_t sbl_status)
{
return sbl_status ? 1:0;
}
int sbl_status(void)
{
uint64_t sbl_sotp = 0;
int ret = SBL_DISABLED;
sbl_sotp = sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC);
if (sbl_sotp != SOTP_ECC_ERR_DETECT) {
sbl_sotp &= SOTP_SBL_MASK;
if (plat_sbl_status(sbl_sotp))
ret = SBL_ENABLED;
}
VERBOSE("SBL status: %d\n", ret);
return ret;
}
@@ -0,0 +1,19 @@
/*
* Copyright (c) 2015 - 2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef SBL_UTIL_H
#define SBL_UTIL_H
#include <stdint.h>
#include <sotp.h>
#define SBL_DISABLED 0
#define SBL_ENABLED 1
int sbl_status(void);
#endif /* #ifdef SBL_UTIL_H */
@@ -0,0 +1,71 @@
/*
* Copyright (c) 2015 - 2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <common/debug.h>
#include <lib/mmio.h>
#include <platform_def.h>
#include <timer_sync.h>
/*******************************************************************************
* Defines related to time sync and satelite timers
******************************************************************************/
#define TIME_SYNC_WR_ENA ((uint32_t)0xACCE55 << 8)
#define IHOST_STA_TMR_CTRL 0x1800
#define IHOST_SAT_TMR_INC_L 0x1814
#define IHOST_SAT_TMR_INC_H 0x1818
#define SAT_TMR_CYCLE_DELAY 2
#define SAT_TMR_32BIT_WRAP_VAL (BIT_64(32) - SAT_TMR_CYCLE_DELAY)
void ihost_enable_satellite_timer(unsigned int cluster_id)
{
uintptr_t ihost_base;
uint32_t time_lx, time_h;
uintptr_t ihost_enable;
VERBOSE("Program iHost%u satellite timer\n", cluster_id);
ihost_base = IHOST0_BASE + cluster_id * IHOST_ADDR_SPACE;
/* this read starts the satellite timer counting from 0 */
ihost_enable = CENTRAL_TIMER_GET_IHOST_ENA_BASE + cluster_id * 4;
time_lx = mmio_read_32(ihost_enable);
/*
* Increment the satellite timer by the central timer plus 2
* to accommodate for a 1 cycle delay through NOC
* plus counter starting from 0.
*/
mmio_write_32(ihost_base + IHOST_SAT_TMR_INC_L,
time_lx + SAT_TMR_CYCLE_DELAY);
/*
* Read the latched upper data, if lx will wrap by adding 2 to it
* we need to handle the wrap
*/
time_h = mmio_read_32(CENTRAL_TIMER_GET_H);
if (time_lx >= SAT_TMR_32BIT_WRAP_VAL)
mmio_write_32(ihost_base + IHOST_SAT_TMR_INC_H, time_h + 1);
else
mmio_write_32(ihost_base + IHOST_SAT_TMR_INC_H, time_h);
}
void brcm_timer_sync_init(void)
{
unsigned int cluster_id;
/* Get the Time Sync module out of reset */
mmio_setbits_32(CDRU_MISC_RESET_CONTROL,
BIT(CDRU_MISC_RESET_CONTROL_TS_RESET_N));
/* Deassert the Central Timer TIMER_EN signal for all module */
mmio_write_32(CENTRAL_TIMER_SAT_TMR_ENA, TIME_SYNC_WR_ENA);
/* enables/programs iHost0 satellite timer*/
cluster_id = MPIDR_AFFLVL1_VAL(read_mpidr());
ihost_enable_satellite_timer(cluster_id);
}