blob: 2029e0f05e3ef9b6604a93481d8070454eff748f [file] [log] [blame]
/*
* Copyright (C) 2015 Freescale Semiconductor, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <asm/arch/clock.h>
#include <asm/arch/iomux.h>
#include <asm/arch/imx-regs.h>
#include <asm/arch/crm_regs.h>
#include <asm/arch/mx6-pins.h>
#include <asm/arch/sys_proto.h>
#include <asm/gpio.h>
#include <asm/imx-common/iomux-v3.h>
#include <asm/imx-common/boot_mode.h>
#include <asm/imx-common/mxc_i2c.h>
#include <asm/io.h>
#include <common.h>
#include <environment.h>
#include <fdtdec.h>
#include <fsl_esdhc.h>
#include <i2c.h>
#include <linux/sizes.h>
#include <linux/fb.h>
#include <malloc.h>
#include <miiphy.h>
#include <mmc.h>
#include <mxsfb.h>
#include <netdev.h>
#include <usb.h>
#include <usb/ehci-fsl.h>
#include <fuse.h>
#include <rsa-imx.h>
#include "../fs/ubifs/ubifs.h"
#include <power/pmic.h>
#include <power/pfuze100_pmic.h>
#ifdef CONFIG_FASTBOOT
#include <fastboot.h>
#ifdef CONFIG_ANDROID_RECOVERY
#include <recovery.h>
#endif
#endif /*CONFIG_FASTBOOT*/
DECLARE_GLOBAL_DATA_PTR;
#define UART_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \
PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \
PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS)
#define GPMI_PAD_CTRL0 (PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_100K_UP)
#define GPMI_PAD_CTRL1 (PAD_CTL_DSE_40ohm | PAD_CTL_SPEED_MED | \
PAD_CTL_SRE_FAST)
#define GPMI_PAD_CTRL2 (GPMI_PAD_CTRL0 | GPMI_PAD_CTRL1)
int dram_init(void)
{
extern void dram_fixup(void);
extern char _dram_fixup_start, _dram_fixup_end;
char *src, *dst;
size_t len, start, end;
void (*func)(void);
dst = (void*)DRAM_FIXUP_IRAM_ADDR;
src = &_dram_fixup_start;
len = &_dram_fixup_end - &_dram_fixup_start;
memcpy(dst, src, len);
start = (size_t)dst;
end = roundup(start + len, CONFIG_SYS_CACHELINE_SIZE);
invalidate_icache_all();
invalidate_dcache_range(start, end);
func = (void*)(dst - src + (size_t)dram_fixup);
func();
gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
return 0;
}
static iomux_v3_cfg_t const wdog_pads[] = {
MX6_PAD_GPIO1_IO08__WDOG1_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL),
};
// Debug UART
static iomux_v3_cfg_t const uart1_pads[] = {
MX6_PAD_UART1_TX_DATA__UART1_DCE_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
MX6_PAD_UART1_RX_DATA__UART1_DCE_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
};
static iomux_v3_cfg_t const ok2boot_pads[] = {
MX6_PAD_ENET1_TX_EN__GPIO2_IO05 | MUX_PAD_CTRL(NO_PAD_CTRL)
};
static iomux_v3_cfg_t const ram_pads[] = {
MX6_PAD_ENET2_RX_EN__GPIO2_IO10 | MUX_PAD_CTRL(NO_PAD_CTRL)
};
#ifdef CONFIG_SYS_USE_NAND
static iomux_v3_cfg_t const nand_pads[] = {
MX6_PAD_NAND_DATA00__RAWNAND_DATA00 | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_DATA01__RAWNAND_DATA01 | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_DATA02__RAWNAND_DATA02 | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_DATA03__RAWNAND_DATA03 | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_DATA04__RAWNAND_DATA04 | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_DATA05__RAWNAND_DATA05 | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_DATA06__RAWNAND_DATA06 | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_DATA07__RAWNAND_DATA07 | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_CLE__RAWNAND_CLE | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_ALE__RAWNAND_ALE | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_CE0_B__RAWNAND_CE0_B | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_RE_B__RAWNAND_RE_B | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_WE_B__RAWNAND_WE_B | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_WP_B__RAWNAND_WP_B | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_READY_B__RAWNAND_READY_B | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
MX6_PAD_NAND_DQS__RAWNAND_DQS | MUX_PAD_CTRL(GPMI_PAD_CTRL2),
};
/* Mux out the UART for security */
static iomux_v3_cfg_t const uart1_pads_disabled[] = {
MX6_PAD_UART1_TX_DATA__GPIO1_IO16 | MUX_PAD_CTRL(NO_PAD_CTRL),
MX6_PAD_UART1_RX_DATA__GPIO1_IO17 | MUX_PAD_CTRL(NO_PAD_CTRL),
};
void disable_iomux_uart(void)
{
imx_iomux_v3_setup_multiple_pads(uart1_pads_disabled, ARRAY_SIZE(uart1_pads_disabled));
}
static void setup_gpmi_nand(void)
{
struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
/* config gpmi nand iomux */
imx_iomux_v3_setup_multiple_pads(nand_pads, ARRAY_SIZE(nand_pads));
clrbits_le32(&mxc_ccm->CCGR4,
MXC_CCM_CCGR4_RAWNAND_U_BCH_INPUT_APB_MASK |
MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_BCH_MASK |
MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_MASK |
MXC_CCM_CCGR4_RAWNAND_U_GPMI_INPUT_APB_MASK |
MXC_CCM_CCGR4_PL301_MX6QPER1_BCH_MASK);
/*
* config gpmi and bch clock to 100 MHz
* bch/gpmi select PLL2 PFD2 400M
* 100M = 400M / 4
*/
clrbits_le32(&mxc_ccm->cscmr1,
MXC_CCM_CSCMR1_BCH_CLK_SEL |
MXC_CCM_CSCMR1_GPMI_CLK_SEL);
clrsetbits_le32(&mxc_ccm->cscdr1,
MXC_CCM_CSCDR1_BCH_PODF_MASK |
MXC_CCM_CSCDR1_GPMI_PODF_MASK,
(3 << MXC_CCM_CSCDR1_BCH_PODF_OFFSET) |
(3 << MXC_CCM_CSCDR1_GPMI_PODF_OFFSET));
/* enable gpmi and bch clock gating */
setbits_le32(&mxc_ccm->CCGR4,
MXC_CCM_CCGR4_RAWNAND_U_BCH_INPUT_APB_MASK |
MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_BCH_MASK |
MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_MASK |
MXC_CCM_CCGR4_RAWNAND_U_GPMI_INPUT_APB_MASK |
MXC_CCM_CCGR4_PL301_MX6QPER1_BCH_MASK);
/* enable apbh clock gating */
setbits_le32(&mxc_ccm->CCGR0, MXC_CCM_CCGR0_APBHDMA_MASK);
}
#endif
static void setup_iomux_wdog(void)
{
imx_iomux_v3_setup_multiple_pads(wdog_pads, ARRAY_SIZE(wdog_pads));
}
static void setup_iomux_uart(void)
{
imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
}
static void setup_piezo_enable_gpio(void)
{
imx_iomux_v3_setup_pad(MX6_PAD_ENET1_TX_CLK__GPIO2_IO06 | MUX_PAD_CTRL(NO_PAD_CTRL));
gpio_direction_output(IMX_GPIO_NR(2, 6), 1);
}
static void setup_iomux_6lo(void)
{
/* Hold 6Lo in reset. (Proto and later. No impact on other revisions.) */
imx_iomux_v3_setup_pad(MX6_PAD_SD1_DATA1__GPIO2_IO19 | MUX_PAD_CTRL(NO_PAD_CTRL));
gpio_direction_output(IMX_GPIO_NR(2, 19), 0);
}
static void setup_iomux_ok2boot(void)
{
imx_iomux_v3_setup_multiple_pads(ok2boot_pads, ARRAY_SIZE(ok2boot_pads));
}
static void setup_iomux_ram(void)
{
imx_iomux_v3_setup_multiple_pads(ram_pads, ARRAY_SIZE(ram_pads));
gpio_direction_output(GPIO_RAM_PWR_EN, 0);
}
static void battery_trap(void)
{
extern void suspend(void);
extern char _suspend_start, _suspend_end;
struct gpc *gpc = (struct gpc *)GPC_BASE_ADDR;
struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
struct pgc *pgc_pcie_phy = (struct pgc *)PGC_PCIE_PHY_BASE_ADDR;
struct pgc *pgc_mega = (struct pgc *)PGC_MEGA_BASE_ADDR;
struct pgc *pgc_cpu = (struct pgc *)PGC_CPU_BASE_ADDR;
struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
u32 val;
char *src, *dst;
size_t len, start, end;
void (*func)(void);
printf("Entering Battery Trap...\n");
setup_iomux_ram();
/* Disable All Interrupts */
disable_interrupts();
__raw_writel(~0, &gpc->imr1);
__raw_writel(~0, &gpc->imr2);
__raw_writel(~0, &gpc->imr3);
__raw_writel(~0, &gpc->imr4);
val = __raw_readl(&mxc_ccm->clpcr);
/* Enable STOP Mode on DSM */
val &= ~MXC_CCM_CLPCR_LPM_MASK;
val |= (0x2 << MXC_CCM_CLPCR_LPM_OFFSET) & MXC_CCM_CLPCR_LPM_MASK;
/* Enable Standby Voltage in STOP Mode */
val |= MXC_CCM_CLPCR_VSTBY;
/* Disable On-Chip Oscillator in STOP Mode */
val |= MXC_CCM_CLPCR_SBYOS;
/* Bypass MMDC Handshake for STOP Mode Entry */
val |= MXC_CCM_CLPCR_BYP_MMDC_CH0_LPM_HS;
__raw_writel(val, &mxc_ccm->clpcr);
/* Disable Memory Clock Regardless of Pending Interrups on WFI */
clrbits_le32(&mxc_ccm->cgpr, MXC_CCM_CGPR_INT_MEM_CLK_LPM);
/* Enable Regulator Bypass After Standby Voltage */
setbits_le32(&mxc_ccm->ccr, MXC_CCM_CCR_RBC_EN);
/* Power-Down All Optional Domains in Low-Power Mode */
setbits_le32(&pgc_pcie_phy->ctrl, PGC_CTRL_PDN);
setbits_le32(&pgc_mega->ctrl, PGC_CTRL_PDN);
setbits_le32(&pgc_cpu->ctrl, PGC_CTRL_PDN);
/* Turn Off All Regulators */
__raw_writel(BM_ANADIG_REG_1P1_ENABLE_PULLDOWN, &anatop->reg_1p1_set);
__raw_writel(BM_ANADIG_REG_2P5_ENABLE_PULLDOWN, &anatop->reg_2p5_set);
__raw_writel(BM_ANADIG_REG_CORE_FET_ODRIVE, &anatop->reg_core_set);
__raw_writel(BM_ANADIG_ANA_MISC0_V2_DISCON_HIGH_SNVS, &anatop->ana_misc0_set);
__raw_writel(BM_ANADIG_ANA_MISC0_V3_STOP_MODE_CONFIG, &anatop->ana_misc0_set);
dst = (void*)SUSPEND_IRAM_ADDR;
src = &_suspend_start;
len = &_suspend_end - &_suspend_start;
memcpy(dst, src, len);
start = (size_t)dst;
end = roundup(start + len, CONFIG_SYS_CACHELINE_SIZE);
invalidate_icache_all();
invalidate_dcache_range(start, end);
func = (void*)(dst - src + (size_t)suspend);
func();
}
void battery_check(void)
{
if (gpio_get_value(GPIO_OK2BOOT)) {
battery_trap();
}
}
static void setup_clocks(void)
{
struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
u32 val;
val = __raw_readl(&mxc_ccm->cacrr);
val &= ~MXC_CCM_CACRR_ARM_PODF_MASK;
val |= CLOCK_PODF_ARM << MXC_CCM_CACRR_ARM_PODF_OFFSET;
__raw_writel(val, &mxc_ccm->cacrr);
val = __raw_readl(&mxc_ccm->cbcdr);
val &= ~MXC_CCM_CBCDR_MMDC_CH1_PODF_MASK;
val |= CLOCK_PODF_DDR << MXC_CCM_CBCDR_MMDC_CH1_PODF_OFFSET;
__raw_writel(val, &mxc_ccm->cbcdr);
}
/* RSA unlock token check ******************************************************/
#define OTP_BANK_UID 0
#define OTP_WORD_UID_L 1
#define OTP_WORD_UID_H 2
#define OTP_BANK_SEC_CONFIG 0
#define OTP_WORD_SEC_CONFIG 6
#define SEC_CONFIG_CLOSED 0x00000002
#define UNLOCK_TOKEN_SIZE_BYTES 256
#define UNLOCK_TOKEN_BASE64_LEN 344 // The 256-Byte unlock token should ALWAYS be 344 Bytes long when base64 encoded
#define UNLOCK_TOKEN_ADDRESS 0x82FFF000 // This is the address where the DFU tool needs to stick the unlock token when doing DFU
#define UNLOCK_TOKEN_PARTITION "ubi0:system-config"
#define SHA256_CHUNK_SZ 64
// If CONFIG_UNLOCK_TOKEN_PREFIX is defined (basically all but the D3 legacy devices),
// check that all unlock tokens are prefixed with it.
// This disambiguates tokens accidentally generated for the wrong build product.
#ifndef CONFIG_UNLOCK_TOKEN_PREFIX
#error CONFIG_UNLOCK_TOKEN_PREFIX not defined!
#endif
#define UNLOCK_TOKEN_PREFIX_LEN (strlen(CONFIG_UNLOCK_TOKEN_PREFIX))
/* Lookup the 6-bit value for a base64-encoded character.
* Invalid characters will return 0x7f and '=' end padding characters will always return zero.
*/
static char base64_lookup(char in) {
uint8_t ret = 0x7f;
if ((in >= 'A') && (in <= 'Z')) {
ret = in - 'A';
} else if ((in >= 'a') && (in <= 'z')) {
ret = in - 'a' + 26;
} else if ((in >= '0') && (in <= '9')) {
ret = in - '0' + 52;
} else if (in == '+') {
ret = 62;
} else if (in == '/') {
ret = 63;
} else if (in == '=') {
ret = 0;
}
return ret;
}
/* Decode a base64-encoded string.
* This implementation assumes the lengths have been checked, such that the encoded data will always fit
* The source and destination buffers may be the same, but should not otherwise overlap.
* The destination buffer must be large enough hold the output if the expected input has two '=' padding
* characters and those characters are replaced with other valid base64 words.
*/
static int base64_decode(char *encoded_data, char *decoded_data, bool silent) {
int idx_in, idx_out,
len = strlen(encoded_data),
ret = 0;
if (((len % 4) != 0) || (len == 0)) {
printf("%s: Invalid length: %d\n", __func__, len);
decoded_data[0] = 0;
ret = -1;
} else {
idx_in = idx_out = 0;
while ((!ret) && (idx_in < len)) {
char a = base64_lookup(encoded_data[idx_in++]),
b = base64_lookup(encoded_data[idx_in++]),
c = base64_lookup(encoded_data[idx_in++]),
d = base64_lookup(encoded_data[idx_in++]);
if ((a > 0x3f) || (b > 0x3f) || (c > 0x3f) || (d > 0x3f)) {
if (!silent) {
printf("%s: Invalid character near Byte %i\n", __func__, (idx_in - 3));
}
ret = -1;
} else {
decoded_data[idx_out++] = ((a & 0x3f) << 2) | ((b & 0x30) >> 4);
decoded_data[idx_out++] = ((b & 0x0f) << 4) | ((c & 0x3c) >> 2);
decoded_data[idx_out++] = ((c & 0x03) << 6) | (d & 0x3f);
}
}
}
return ret;
}
/* Check for a valid unlock token, either in RAM or in the filesystem.
* The unlock token is the UID string (ASCII hex encoded, with no CR/LF appended),
* signed with the private unlocking key and base64 encoded.
*
* Tokens can be generated as follows (for UIDs '2a1429d4de730bfc' and '102551d4df669959'):
* > device_UIDs=("2a1429d4de730bfc" "102551d4df669959")
* > unlock_key=/dev/shm/diamond3-unlock.key
* > unlock_token_folder=${BuildRoot}/keys/
* > for device_UID in "${device_UIDs[@]}"; do
* > echo -n "${device_UID}" | openssl dgst -sha256 -passin env:passcode -sign ${unlock_key} | base64 --wrap=0 > ${unlock_token_folder}/${device_UID}
* > done
*
* The token can be loaded at boot time when booting via DFU by loading it to UNLOCK_TOKEN_ADDRESS
* The token can be permanently stored by copying the token file (filename is the UID) to the root of UNLOCK_TOKEN_PARTITION
*/
static bool board_unlock_token_check(char *UID_str)
{
bool unlocked = false;
void *blob = ((void *)gd_fdt_blob());
int sig_node, unlock_node;
uint8_t hash[SHA256_SUM_LEN];
sha256_context ctx;
struct imx_rsa_public_key key;
char *unlock_token_source;
char *unlock_data = ((char *)UNLOCK_TOKEN_ADDRESS);
int ret = 0;
// Stretch the UID ASCII hex string into a SHA-256 hash so that we can
// pad it in a standard way
sha256_starts(&ctx);
sha256_update(&ctx, (uint8_t *)UID_str, strlen(UID_str));
sha256_finish(&ctx, hash);
// Locate the signature DT node
sig_node = fdt_subnode_offset(blob, 0, FIT_SIG_NODENAME);
if (sig_node < 0) {
printf("%s: No signature node found\n", __func__);
ret = -1;
}
if (!ret) {
// Locate the public unlocking key DT node
unlock_node = fdt_subnode_offset(blob, sig_node, "unlock");
if (unlock_node < 0) {
printf("%s: No public unlocking key node found\n", __func__);
ret = -1;
}
}
if (!ret) {
// Read the public key from the DT unlock_node into memory
ret = rsa_imx_get_key(blob, unlock_node, &key);
if (ret) {
printf("%s: RSA failed to load public unlocking key: %d\n", __func__, ret);
}
}
if (!ret) {
// Use the public key to check if there is a valid signature in memory
unlock_data[UNLOCK_TOKEN_PREFIX_LEN + UNLOCK_TOKEN_BASE64_LEN] = 0;
if (strlen(unlock_data) != (UNLOCK_TOKEN_PREFIX_LEN + UNLOCK_TOKEN_BASE64_LEN)) {
ret = -1;
} else if (strncmp(unlock_data, CONFIG_UNLOCK_TOKEN_PREFIX, UNLOCK_TOKEN_PREFIX_LEN)) {
ret = -1;
} else if (base64_decode(&unlock_data[UNLOCK_TOKEN_PREFIX_LEN], unlock_data, true) != 0) {
ret = -1;
} else {
ret = rsa_imx_verify_key(&key, (uint8_t *)unlock_data, UNLOCK_TOKEN_SIZE_BYTES, hash);
unlock_token_source = "RAM";
}
if (ret) {
unlock_data[UNLOCK_TOKEN_PREFIX_LEN + UNLOCK_TOKEN_BASE64_LEN] = 0;
// Init UBIFS
ubifs_init();
// Mount the partition containing the token
if (uboot_ubifs_mount(UNLOCK_TOKEN_PARTITION)) {
printf("Could not mount " UNLOCK_TOKEN_PARTITION "\n");
// Attempt to read a file with a name that matches the UID. This will fail silently if the file is absent.
} else if (ubifs_load(UID_str, (u32) unlock_data, (UNLOCK_TOKEN_PREFIX_LEN + UNLOCK_TOKEN_BASE64_LEN))) {
// Do nothing
} else if (strlen(unlock_data) != (UNLOCK_TOKEN_PREFIX_LEN + UNLOCK_TOKEN_BASE64_LEN)) {
printf("%s: Unlock token length incorrect: %d\n", __func__, strlen(unlock_data));
} else if (strncmp(unlock_data, CONFIG_UNLOCK_TOKEN_PREFIX, UNLOCK_TOKEN_PREFIX_LEN)) {
printf("%s: Unlock token prefix invalid\n", __func__);
} else if (base64_decode(&unlock_data[UNLOCK_TOKEN_PREFIX_LEN], unlock_data, false) != 0) {
printf("%s: Unlock token encoding invalid\n", __func__);
} else {
ret = rsa_imx_verify_key(&key, (uint8_t *)unlock_data, UNLOCK_TOKEN_SIZE_BYTES, hash);
unlock_token_source = "filesystem";
}
}
if (ret) {
printf("Unlocking token not present or invalid (%d)\n", ret);
} else {
printf("Unlocking token verified from %s\n", unlock_token_source);
unlocked = true;
}
}
return unlocked;
}
/* Get the 64-bit unique silicon ID and convert it to ASCII hex so that it can be used to generate an unlock token
* Also get the SOC SEC_CONFIG value burned into OCOTP so that we can determine the SOC's security state
*/
int board_get_UID_sec_config(char *UID_str, int maxlen, uint32_t *sec_config) {
uint32_t UID[2]; // The 64-bit UID
int ret;
memset(UID_str, 0x00, maxlen);
ret = fuse_read(OTP_BANK_UID, OTP_WORD_UID_L, &UID[0]);
if (!ret)
ret = fuse_read(OTP_BANK_UID, OTP_WORD_UID_H, &UID[1]);
if (!ret)
ret = fuse_read(OTP_BANK_SEC_CONFIG, OTP_WORD_SEC_CONFIG, sec_config);
if (!ret)
snprintf(UID_str, maxlen, "%08x%08x", UID[1], UID[0]);
return ret;
}
/* Switch the system into either the fully locked or fully unlocked state */
static void board_update_unlocked(bool unlocked)
{
void *blob = ((void *)gd_fdt_blob());
int sig_node;
int ret = 0;
// Update the system state based on locked/unlocked status
if (unlocked) {
// Update the control FDT's boot config to disable ITB signature checking, by finding all
// subnodes in the control FDT that contain a "required" property and set the value to "none".
sig_node = fdt_subnode_offset(blob, 0, FIT_SIG_NODENAME);
if (sig_node < 0) {
// This will happen on systems that don't have the public
// key tree, so we don't make any noise about it.
debug("%s: Unable to get sig node: %d\n", __func__, ret);
} else {
int noffset = fdt_first_subnode(blob, sig_node);
while ((noffset >= 0) && (!ret)) {
if (fdt_getprop(blob, noffset, "required", NULL)) {
ret = fdt_setprop(blob, noffset, "required", "none", 4);
}
noffset = fdt_next_subnode(blob, noffset);
}
}
// Use the boot delay defined in the environment (via CONFIG_BOOTDELAY)
} else {
// Give any outgoing characters time to clear the UART before we mux it out
udelay(100);
// Override the default env variable 'console', which gets passed to kernel cmdline and point it to /dev/null
setenv("console", "/dev/null");
// Always autoboot with no delay and don't check for an abort
setenv("bootdelay", "-2");
// Mux out the UART
disable_iomux_uart();
// Flush out any data received before the UART was muxed out
while (tstc()) {
getc();
}
}
if (ret) {
printf("%s: Failed updating security config: %d\n", __func__, ret);
}
}
int board_early_init_f(void)
{
setup_iomux_wdog();
setup_iomux_uart();
setup_piezo_enable_gpio();
setup_iomux_6lo();
setup_iomux_ok2boot();
battery_check();
setup_clocks();
return 0;
}
int board_init(void)
{
/* Address of boot parameters */
gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
#ifdef CONFIG_SYS_USE_NAND
setup_gpmi_nand();
#endif
return 0;
}
void env_sanitize(void)
{
ALLOC_CACHE_ALIGN_BUFFER(env_t, export, 1);
char *import = (char *)export;
char *whitelist[] =
{
CONFIG_ENV_WHITELIST
};
char *ptr = NULL;
ssize_t size;
bool sanitize;
#ifdef CONFIG_CMD_SAVEENV
/* env can't be sanitized because saving would clear stored data */
sanitize = false
#else
/* env can't be sanitized unless loading was deferred */
sanitize = !fdtdec_get_config_int(gd->fdt_blob, "load-environment", 1);
#endif
if (sanitize) {
env_export(export);
env_relocate();
size = hexport_r(&env_htab, '\0', H_MATCH_KEY | H_MATCH_IDENT,
&ptr, 0, ARRAY_SIZE(whitelist), whitelist);
env_import(import, 1);
if (ptr != NULL) {
himport_r(&env_htab, ptr, size, '\0', H_NOCLEAR, false, 0, NULL);
free(ptr);
}
} else {
printf("*** Warning - cannot sanitize env!\n");
}
}
int board_late_init(void)
{
char UID_str[SHA256_CHUNK_SZ]; // The UID's ASCII hex string representation. Size needs to be multiple of the SHA-256 chunk size.
uint32_t sec_config;
bool unlocked = false;
set_wdog_reset((struct wdog_regs *)WDOG1_BASE_ADDR);
env_sanitize();
/* Get board UID and SEC_CONFIG so that we can determine system security state */
if (board_get_UID_sec_config(UID_str, SHA256_CHUNK_SZ, &sec_config)) {
printf("%s: Error reading fuses\n", __func__);
} else {
printf("UID: %s\n", UID_str);
if ((sec_config & SEC_CONFIG_CLOSED) == 0) {
/* Always unlock units that are still in open mode (i.e. SEC_CONFIG[1] != 1).
* This enables the release bootloader to be used at the factory without requiring
* unlocking tokens for units that haven't been through the shipping settings station.
* It also enables development on devices that aren't secure, or for which keys have
* not yet been generated.
*/
printf("Secure boot not enabled, device unlocked\n");
unlocked = true;
} else {
/* Check for the presence of the unlock token */
unlocked = board_unlock_token_check(UID_str);
}
}
/* Update state based on locked/unlocked status */
board_update_unlocked(unlocked);
return 0;
}
u32 get_board_rev(void)
{
return get_cpu_rev();
}
int checkboard(void)
{
puts("Board: Onyx\n");
return 0;
}