Commit 926cd70a authored by Manish Pandey's avatar Manish Pandey Committed by TrustedFirmware Code Review
Browse files

Merge changes from topic "brcm_initial_support" into integration

* changes:
  doc: brcm: Add documentation file for brcm stingray platform
  drivers: Add SPI Nor flash support
  drivers: Add iproc spi driver
  drivers: Add emmc driver for Broadcom platforms
  Add BL31 support for Broadcom stingray platform
  Add BL2 support for Broadcom stingray platform
  Add bl31 support common across Broadcom platforms
  Add bl2 setup code common across Broadcom platforms
  drivers: Add support to retrieve plat_toc_flags
parents 33f1dd9c fd1017b1
/*
* Copyright (c) 2019-2020, Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PLAT_BRCM_H
#define PLAT_BRCM_H
#include <stdint.h>
#include <lib/cassert.h>
#include <lib/utils_def.h>
#include <lib/xlat_tables/xlat_tables.h>
#include <platform_def.h>
struct image_info;
/* Global variables */
extern const mmap_region_t plat_brcm_mmap[];
uint32_t brcm_get_spsr_for_bl32_entry(void);
uint32_t brcm_get_spsr_for_bl33_entry(void);
const mmap_region_t *plat_brcm_get_mmap(void);
int bcm_bl2_handle_scp_bl2(struct image_info *image_info);
unsigned int plat_brcm_calc_core_pos(u_register_t mpidr);
void plat_brcm_gic_driver_init(void);
void plat_brcm_gic_init(void);
void plat_brcm_gic_cpuif_enable(void);
void plat_brcm_gic_cpuif_disable(void);
void plat_brcm_gic_pcpu_init(void);
void plat_brcm_gic_redistif_on(void);
void plat_brcm_gic_redistif_off(void);
void plat_brcm_interconnect_init(void);
void plat_brcm_interconnect_enter_coherency(void);
void plat_brcm_interconnect_exit_coherency(void);
void plat_brcm_io_setup(void);
void plat_brcm_process_flags(uint16_t plat_toc_flags);
#endif /* PLAT_BRCM_H */
/*
* 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)
{
(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)
{
(void)console_flush();
(void)console_unregister(&bcm_runtime_console);
}
/*
* 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);
}
/*
* 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");
}
/*
* 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 */
/*
* Copyright 2015 - 2020 Broadcom
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.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%llx\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);
}
/*
* 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);
#
# Copyright (c) 2015 - 2020, 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
# 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
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 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_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 '${MBEDTLS_DIR}')
ifneq (${MBEDTLS_CHECK},)
$(info Found mbedTLS at ${MBEDTLS_DIR})
PLAT_INCLUDES += -I${MBEDTLS_DIR}/include/mbedtls
# Specify mbedTLS configuration file
MBEDTLS_CONFIG_FILE := "<brcm_mbedtls_config.h>"
# 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.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
/*
* 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);
}
/*
* 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
/*
* 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>
#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)
/* Print file and line number on assert */
#define PLAT_LOG_LEVEL_ASSERT LOG_LEVEL_INFO
/*
* 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
/*
* 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
/*
* 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);
}
/*
* 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
/*
* 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();
}
}
/*
* 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];
}
/*
* 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) {
;
}
}
/*
* 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;
}
/*
* 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 */
/*
* 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);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment