[U-Boot] [PATCH u-boot-marvell v3 08/10] board: turris_mox: Read info (and ethaddrs) from OTP
Stefan Roese
sr at denx.de
Thu Nov 29 13:04:18 UTC 2018
On 20.11.18 13:04, Marek Behún wrote:
> Add support for reading One-Time Programmable memory via mailbox, which
> communicates with CZ.NIC's firmware on the Secure Processor (Cortex-M3)
> of Armada 3720.
>
> Display product serial number and additional info, and also set MAC
> addresses.
>
> Signed-off-by: Marek Behún <marek.behun at nic.cz>
Reviewed-by: Stefan Roese <sr at denx.de>
Thanks,
Stefan
> ---
> board/CZ.NIC/turris_mox/Makefile | 2 +-
> board/CZ.NIC/turris_mox/mox_sp.c | 133 +++++++++++++++++++++++++++
> board/CZ.NIC/turris_mox/mox_sp.h | 15 +++
> board/CZ.NIC/turris_mox/turris_mox.c | 54 ++++++++++-
> 4 files changed, 201 insertions(+), 3 deletions(-)
> create mode 100644 board/CZ.NIC/turris_mox/mox_sp.c
> create mode 100644 board/CZ.NIC/turris_mox/mox_sp.h
>
> diff --git a/board/CZ.NIC/turris_mox/Makefile b/board/CZ.NIC/turris_mox/Makefile
> index 619704288b..33a52b63d7 100644
> --- a/board/CZ.NIC/turris_mox/Makefile
> +++ b/board/CZ.NIC/turris_mox/Makefile
> @@ -2,4 +2,4 @@
> #
> # Copyright (C) 2018 Marek Behun <marek.behun at nic.cz>
>
> -obj-y := turris_mox.o
> +obj-y := turris_mox.o mox_sp.o
> diff --git a/board/CZ.NIC/turris_mox/mox_sp.c b/board/CZ.NIC/turris_mox/mox_sp.c
> new file mode 100644
> index 0000000000..78438227dc
> --- /dev/null
> +++ b/board/CZ.NIC/turris_mox/mox_sp.c
> @@ -0,0 +1,133 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2018 Marek Behun <marek.behun at nic.cz>
> + */
> +
> +#include <common.h>
> +#include <asm/io.h>
> +
> +#define RWTM_CMD_PARAM(i) (size_t)(0xd00b0000 + (i) * 4)
> +#define RWTM_CMD 0xd00b0040
> +#define RWTM_CMD_RETSTATUS 0xd00b0080
> +#define RWTM_CMD_STATUS(i) (size_t)(0xd00b0084 + (i) * 4)
> +
> +#define RWTM_HOST_INT_RESET 0xd00b00c8
> +#define RWTM_HOST_INT_MASK 0xd00b00cc
> +#define SP_CMD_COMPLETE BIT(0)
> +
> +#define MBOX_STS_SUCCESS (0x0 << 30)
> +#define MBOX_STS_FAIL (0x1 << 30)
> +#define MBOX_STS_BADCMD (0x2 << 30)
> +#define MBOX_STS_LATER (0x3 << 30)
> +#define MBOX_STS_ERROR(s) ((s) & (3 << 30))
> +#define MBOX_STS_VALUE(s) (((s) >> 10) & 0xfffff)
> +#define MBOX_STS_CMD(s) ((s) & 0x3ff)
> +
> +enum mbox_cmd {
> + MBOX_CMD_GET_RANDOM = 1,
> + MBOX_CMD_BOARD_INFO,
> + MBOX_CMD_ECDSA_PUB_KEY,
> + MBOX_CMD_ECDSA_SIGN,
> +
> + MBOX_CMD_OTP_READ,
> + MBOX_CMD_OTP_WRITE
> +};
> +
> +static int mbox_do_cmd(enum mbox_cmd cmd, u32 *out, int nout)
> +{
> + int i;
> + u32 status;
> +
> + clrbits_le32(RWTM_HOST_INT_MASK, SP_CMD_COMPLETE);
> +
> + writel(cmd, RWTM_CMD);
> +
> + for (i = 0; i < 10; ++i) {
> + mdelay(10);
> + if (readl(RWTM_HOST_INT_RESET) & SP_CMD_COMPLETE)
> + break;
> + }
> +
> + if (i == 10) {
> + /* if timed out, don't read status */
> + setbits_le32(RWTM_HOST_INT_RESET, SP_CMD_COMPLETE);
> + return -ETIMEDOUT;
> + }
> +
> + for (i = 0; i < nout; ++i)
> + out[i] = readl(RWTM_CMD_STATUS(i));
> + status = readl(RWTM_CMD_RETSTATUS);
> +
> + setbits_le32(RWTM_HOST_INT_RESET, SP_CMD_COMPLETE);
> +
> + if (MBOX_STS_CMD(status) != cmd)
> + return -EIO;
> + else if (MBOX_STS_ERROR(status) == MBOX_STS_FAIL)
> + return -(int)MBOX_STS_VALUE(status);
> + else if (MBOX_STS_ERROR(status) != MBOX_STS_SUCCESS)
> + return -EIO;
> + else
> + return MBOX_STS_VALUE(status);
> +}
> +
> +const char *mox_sp_get_ecdsa_public_key(void)
> +{
> + static char public_key[135];
> + u32 out[16];
> + int res;
> +
> + if (public_key[0])
> + return public_key;
> +
> + res = mbox_do_cmd(MBOX_CMD_ECDSA_PUB_KEY, out, 16);
> + if (res < 0)
> + return NULL;
> +
> + sprintf(public_key,
> + "%06x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x",
> + (u32)res, out[0], out[1], out[2], out[3], out[4], out[5],
> + out[6], out[7], out[8], out[9], out[10], out[11], out[12],
> + out[13], out[14], out[15]);
> +
> + return public_key;
> +}
> +
> +static inline void res_to_mac(u8 *mac, u32 t1, u32 t2)
> +{
> + mac[0] = t1 >> 8;
> + mac[1] = t1;
> + mac[2] = t2 >> 24;
> + mac[3] = t2 >> 16;
> + mac[4] = t2 >> 8;
> + mac[5] = t2;
> +}
> +
> +int mbox_sp_get_board_info(u64 *sn, u8 *mac1, u8 *mac2, int *bv, int *ram)
> +{
> + u32 out[8];
> + int res;
> +
> + res = mbox_do_cmd(MBOX_CMD_BOARD_INFO, out, 8);
> + if (res < 0)
> + return res;
> +
> + if (sn) {
> + *sn = out[1];
> + *sn <<= 32;
> + *sn |= out[0];
> + }
> +
> + if (bv)
> + *bv = out[2];
> +
> + if (ram)
> + *ram = out[3];
> +
> + if (mac1)
> + res_to_mac(mac1, out[4], out[5]);
> +
> + if (mac2)
> + res_to_mac(mac2, out[6], out[7]);
> +
> + return 0;
> +}
> diff --git a/board/CZ.NIC/turris_mox/mox_sp.h b/board/CZ.NIC/turris_mox/mox_sp.h
> new file mode 100644
> index 0000000000..49a4ed80ea
> --- /dev/null
> +++ b/board/CZ.NIC/turris_mox/mox_sp.h
> @@ -0,0 +1,15 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (C) 2018 Marek Behun <marek.behun at nic.cz>
> + */
> +
> +#ifndef _BOARD_CZNIC_TURRIS_MOX_MOX_SP_H_
> +#define _BOARD_CZNIC_TURRIS_MOX_MOX_SP_H_
> +
> +#include <common.h>
> +
> +const char *mox_sp_get_ecdsa_public_key(void);
> +int mbox_sp_get_board_info(u64 *sn, u8 *mac1, u8 *mac2, int *bv,
> + int *ram);
> +
> +#endif /* _BOARD_CZNIC_TURRIS_MOX_MOX_SP_H_ */
> diff --git a/board/CZ.NIC/turris_mox/turris_mox.c b/board/CZ.NIC/turris_mox/turris_mox.c
> index 39c26416a7..89b3cd2ce0 100644
> --- a/board/CZ.NIC/turris_mox/turris_mox.c
> +++ b/board/CZ.NIC/turris_mox/turris_mox.c
> @@ -19,6 +19,8 @@
> #include <wdt.h>
> #endif
>
> +#include "mox_sp.h"
> +
> #define MAX_MOX_MODULES 10
>
> #define MOX_MODULE_SFP 0x1
> @@ -366,6 +368,49 @@ static int get_reset_gpio(struct gpio_desc *reset_gpio)
> return 0;
> }
>
> +int misc_init_r(void)
> +{
> + int ret;
> + u8 mac1[6], mac2[6];
> +
> + ret = mbox_sp_get_board_info(NULL, mac1, mac2, NULL, NULL);
> + if (ret < 0) {
> + printf("Cannot read data from OTP!\n");
> + return 0;
> + }
> +
> + if (is_valid_ethaddr(mac1) && !env_get("ethaddr"))
> + eth_env_set_enetaddr("ethaddr", mac1);
> +
> + if (is_valid_ethaddr(mac2) && !env_get("eth1addr"))
> + eth_env_set_enetaddr("eth1addr", mac2);
> +
> + return 0;
> +}
> +
> +static void mox_print_info(void)
> +{
> + int ret, board_version, ram_size;
> + u64 serial_number;
> + const char *pub_key;
> +
> + ret = mbox_sp_get_board_info(&serial_number, NULL, NULL, &board_version,
> + &ram_size);
> + if (ret < 0)
> + return;
> +
> + printf("Turris Mox:\n");
> + printf(" Board version: %i\n", board_version);
> + printf(" RAM size: %i MiB\n", ram_size);
> + printf(" Serial Number: %016llX\n", serial_number);
> +
> + pub_key = mox_sp_get_ecdsa_public_key();
> + if (pub_key)
> + printf(" ECDSA Public Key: %s\n", pub_key);
> + else
> + printf("Cannot read ECDSA Public Key\n");
> +}
> +
> int last_stage_init(void)
> {
> int ret, i;
> @@ -374,14 +419,19 @@ int last_stage_init(void)
> struct mii_dev *bus;
> struct gpio_desc reset_gpio = {};
>
> + mox_print_info();
> +
> ret = mox_get_topology(&topology, &module_count, &is_sd);
> if (ret) {
> printf("Cannot read module topology!\n");
> return 0;
> }
>
> - printf("Found Turris Mox %s version\n", is_sd ? "SD" : "eMMC");
> - printf("Module Topology:\n");
> + printf(" SD/eMMC version: %s\n", is_sd ? "SD" : "eMMC");
> +
> + if (module_count)
> + printf("Module Topology:\n");
> +
> for (i = 0; i < module_count; ++i) {
> switch (topology[i]) {
> case MOX_MODULE_SFP:
>
Viele Grüße,
Stefan
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-51 Fax: (+49)-8142-66989-80 Email: sr at denx.de
More information about the U-Boot
mailing list