Skip to contentSkip to conversation

mips: mt7628: Change compatible property of the ethernet DT node

PATCH New Stefan Roese 2 participants 11 messages Nov 28, 2018 – Nov 30, 2018

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/3 mips: mt7628: Change compatible property of the ethernet DT node

As the driver has been changed to be more specific, the DT compatible property also needs to be adapted.

Cc Daniel Schwierzeck <[email protected]>
---
 arch/mips/dts/mt7628a.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/mips/dts/mt7628a.dtsi +1 -1
index 70e34cfdbc..1e7d0a6ec5 100644
@@ -164,7 +164,7 @@
 	};
 
 	eth at 10110000 {
-		compatible = "mediatek,mt7622-eth";
+		compatible = "mediatek,mt7628-eth";
 		reg = <0x10100000 0x10000
 		       0x10110000 0x8000>;
 
Signature · 1 line
2.19.2
#1 lore raw

PATCH 2/3 mips: mt76xx: gardena-smart-gateway: Misc updates to defconfig

The following changes are made:
- Add default bootcmd which can be used for initial start-up
- Setup necessary MTD parts for Linux compatibility

Cc Daniel Schwierzeck <[email protected]>
---
 configs/gardena-smart-gateway-mt7688-ram_defconfig | 6 ++++--
 configs/gardena-smart-gateway-mt7688_defconfig     | 6 ++++--
 2 files changed, 8 insertions(+), 4 deletions(-)
configs/gardena-smart-gateway-mt7688-ram_defconfig +4 -2
index 91359698ab..05e7cf9f88 100644
@@ -10,6 +10,8 @@ CONFIG_FIT=y
 CONFIG_FIT_SIGNATURE=y
 CONFIG_IMAGE_FORMAT_LEGACY=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
+CONFIG_USE_BOOTCOMMAND=y
+CONFIG_BOOTCOMMAND="cp.b 83000000 84000000 10000 && dhcp uEnv.txt && env import -t ${fileaddr} ${filesize} && run do_u_boot_init; reset"
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_BOARD_EARLY_INIT_F=y
@@ -31,8 +33,8 @@ CONFIG_CMD_BOOTCOUNT=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_UUID=y
 CONFIG_CMD_MTDPARTS=y
-CONFIG_MTDIDS_DEFAULT="spi-nand0=spi-nand0"
-CONFIG_MTDPARTS_DEFAULT="mtdparts=spi-nand0:-(nand)"
+CONFIG_MTDIDS_DEFAULT="spi-nand0=gd5f,nor0=spi0.0"
+CONFIG_MTDPARTS_DEFAULT="spi0.0:640k(uboot),64k(uboot_env0),64k(uboot_env1),64k(factory),-(unused);gd5f:-(nand)"
 CONFIG_CMD_UBI=y
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="gardena-smart-gateway-mt7688"
configs/gardena-smart-gateway-mt7688_defconfig +4 -2
index bd8b035dea..a08d1dbc9c 100644
@@ -13,6 +13,8 @@ CONFIG_FIT=y
 CONFIG_FIT_SIGNATURE=y
 CONFIG_IMAGE_FORMAT_LEGACY=y
 CONFIG_OF_STDOUT_VIA_ALIAS=y
+CONFIG_USE_BOOTCOMMAND=y
+CONFIG_BOOTCOMMAND="cp.b 83000000 84000000 10000 && dhcp uEnv.txt && env import -t ${fileaddr} ${filesize} && run do_u_boot_init; reset"
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_BOARD_EARLY_INIT_F=y
@@ -34,8 +36,8 @@ CONFIG_CMD_BOOTCOUNT=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_UUID=y
 CONFIG_CMD_MTDPARTS=y
-CONFIG_MTDIDS_DEFAULT="spi-nand0=spi-nand0"
-CONFIG_MTDPARTS_DEFAULT="mtdparts=spi-nand0:-(nand)"
+CONFIG_MTDIDS_DEFAULT="spi-nand0=gd5f,nor0=spi0.0"
+CONFIG_MTDPARTS_DEFAULT="spi0.0:640k(uboot),64k(uboot_env0),64k(uboot_env1),64k(factory),-(unused);gd5f:-(nand)"
 CONFIG_CMD_UBI=y
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="gardena-smart-gateway-mt7688"
Signature · 1 line
2.19.2
#2 lore raw

PATCH 2/3 mips: mt76xx: gardena-smart-gateway: Misc updates to defconfig

Am 28.11.18 um 08:40 schrieb Stefan Roese:

Quoted 11 lines

The following changes are made:
- Add default bootcmd which can be used for initial start-up
- Setup necessary MTD parts for Linux compatibility

Cc Daniel Schwierzeck <[email protected]>
---
 configs/gardena-smart-gateway-mt7688-ram_defconfig | 6 ++++--
 configs/gardena-smart-gateway-mt7688_defconfig     | 6 ++++--
 2 files changed, 8 insertions(+), 4 deletions(-)

applied to u-boot-mips, thanks.

Signature · 9 lines
- Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20181128/e9b5d572/attachment.sig>
#3 lore raw

PATCH 3/3 mips: mt76xx: gardena-smart-gateway: Add factory data variable handling

In reply to Stefan Roese

Some factory data is stored in the SPI NOR and needs to get extracted from there into U-Boot environment variables.

This patch also includes a board-specific command "fd_write" to provide some dummy / default values for this factory-data in the SPI NOR flash. This should only be necessary for testing purposes though.

Cc Daniel Schwierzeck <[email protected]>
---
 board/gardena/smart-gateway-mt7688/board.c | 266 +++++++++++++++++++++
 1 file changed, 266 insertions(+)
board/gardena/smart-gateway-mt7688/board.c +266 -0
index 3a1838e44a..185bdfb71d 100644
@@ -4,11 +4,44 @@
  */
 
 #include <common.h>
+#include <environment.h>
 #include <led.h>
+#include <net.h>
+#include <spi.h>
+#include <spi_flash.h>
+#include <uuid.h>
+#include <linux/ctype.h>
 #include <linux/io.h>
 
 #define MT76XX_AGPIO_CFG	0x1000003c
 
+#define FACTORY_DATA_OFFS	0xc0000
+#define FACTORY_DATA_SECT_SIZE	0x10000
+#if ((CONFIG_ENV_OFFSET_REDUND + CONFIG_ENV_SIZE_REDUND) > FACTORY_DATA_OFFS)
+#error "U-Boot image with environment too big (overlapping with factory-data)!"
+#endif
+#define FACTORY_DATA_USER_OFFS	0x140
+#define FACTORY_DATA_SIZE	0x1f0
+#define FACTORY_DATA_CRC_LEN	(FACTORY_DATA_SIZE -			\
+				 FACTORY_DATA_USER_OFFS - sizeof(u32))
+
+#define FACTORY_DATA_MAGIC	0xCAFEBABE
+
+struct factory_data_values {
+	u8 pad_1[4];
+	u8 wifi_mac[6];		/* offs: 0x004: binary value */
+	u8 pad_2[30];
+	u8 eth_mac[6];		/* offs: 0x028: binary value */
+	u8 pad_3[FACTORY_DATA_USER_OFFS - 4 - 6 - 30 - 6];
+	/* User values start here at offset 0x140 */
+	u32 crc;
+	u32 magic;
+	u32 version;
+	char ipr_id[UUID_STR_LEN];	/* UUID as string w/o ending \0 */
+	char hqv_id[UUID_STR_LEN];	/* UUID as string w/o ending \0 */
+	char unielec_id[UUID_STR_LEN];	/* UUID as string w/o ending \0 */
+};
+
 int board_early_init_f(void)
 {
 	void __iomem *gpio_mode;
@@ -20,10 +53,243 @@ int board_early_init_f(void)
 	return 0;
 }
 
+static int prepare_uuid_var(char *fd_ptr, char *env_var_name, char errorchar)
+{
+	char str[UUID_STR_LEN + 1];	/* Enough for UUID stuff */
+	bool env_updated = 0;
+	char *env;
+	int i;
+
+	memset(str, 0, sizeof(str));
+	memcpy(str, fd_ptr, UUID_STR_LEN);
+
+	/* Convert non-ascii character to 'X' */
+	for (i = 0; i < UUID_STR_LEN; i++) {
+		if (!(isascii(str[i]) && isprint(str[i])))
+			str[i] = errorchar;
+	}
+
+	env = env_get(env_var_name);
+	if (strcmp(env, str)) {
+		env_set(env_var_name, str);
+		env_updated = 1;
+	}
+
+	return env_updated;
+}
+
+static void factory_data_env_config(void)
+{
+	struct factory_data_values *fd;
+	struct spi_flash *sf;
+	int env_updated = 0;
+	char str[UUID_STR_LEN + 1];	/* Enough for UUID stuff */
+	char *env;
+	u8 *buf;
+	u32 crc;
+	int ret;
+	u8 *ptr;
+
+	buf = malloc(FACTORY_DATA_SIZE);
+	if (!buf) {
+		printf("F-Data:Unable to allocate buffer\n");
+		goto err;
+	}
+
+	/*
+	 * Get values from factory-data area in SPI NOR
+	 */
+	sf = spi_flash_probe(CONFIG_SF_DEFAULT_BUS,
+			     CONFIG_SF_DEFAULT_CS,
+			     CONFIG_SF_DEFAULT_SPEED,
+			     CONFIG_SF_DEFAULT_MODE);
+	if (!sf) {
+		printf("F-Data:Unable to access SPI NOR flash\n");
+		goto err;
+	}
+
+	ret = spi_flash_read(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SIZE,
+			     (void *)buf);
+	if (ret) {
+		printf("F-Data:Unable to read factory-data from SPI NOR\n");
+		goto err;
+	}
+
+	fd = (struct factory_data_values *)buf;
+
+	if (fd->magic != FACTORY_DATA_MAGIC)
+		printf("F-Data:Magic value not correct\n");
+
+	crc = crc32(0, (u8 *)&fd->magic, FACTORY_DATA_CRC_LEN);
+	if (crc != fd->crc)
+		printf("F-Data:CRC not correct\n");
+	else
+		printf("F-Data:factory-data version %x detected\n",
+		       fd->version);
+
+	/* Handle wifi_mac env variable */
+	ptr = fd->wifi_mac;
+	sprintf(str, "%pM", ptr);
+	if (!is_valid_ethaddr(ptr))
+		printf("F-Data:Invalid MAC addr: wifi_mac %s\n", str);
+
+	env = env_get("wifiaddr");
+	if (strcmp(env, str)) {
+		env_set("wifiaddr", str);
+		env_updated = 1;
+	}
+
+	/* Handle eth_mac env variable */
+	ptr = fd->eth_mac;
+	sprintf(str, "%pM", ptr);
+	if (!is_valid_ethaddr(ptr))
+		printf("F-Data:Invalid MAC addr: eth_mac %s\n", str);
+
+	env = env_get("ethaddr");
+	if (strcmp(env, str)) {
+		env_set("ethaddr", str);
+		env_updated = 1;
+	}
+
+	/* Handle UUID env variables */
+	env_updated |= prepare_uuid_var(fd->ipr_id, "linuxmoduleid", 'X');
+	env_updated |= prepare_uuid_var(fd->hqv_id, "linuxmodulehqvid", '\0');
+	env_updated |= prepare_uuid_var(fd->unielec_id,
+					"linuxmoduleunielecid", 'X');
+
+	/* Check if the environment was updated and needs to get stored */
+	if (env_updated != 0) {
+		printf("F-Data:Values don't match env values -> saving\n");
+		env_save();
+	} else {
+		printf("F-Data:Values match current env values\n");
+	}
+
+err:
+	free(buf);
+}
+
 int board_late_init(void)
 {
 	if (IS_ENABLED(CONFIG_LED))
 		led_default_state();
 
+	factory_data_env_config();
+
 	return 0;
 }
+
+static void copy_or_generate_uuid(char *fd_ptr, char *env_var_name)
+{
+	char str[UUID_STR_LEN + 1];	/* Enough for UUID stuff */
+	char *env;
+
+	/* Don't use the UUID dest place, as the \0 char won't fit */
+	env = env_get(env_var_name);
+	if (env) {
+		memcpy(fd_ptr, env, UUID_STR_LEN);
+	} else {
+		gen_rand_uuid_str(str, UUID_STR_FORMAT_STD);
+		memcpy(fd_ptr, str, UUID_STR_LEN);
+	}
+}
+
+/*
+ * Helper function to provide some sane factory-data values for testing
+ * purpose, when these values are not programmed correctly
+ */
+int do_fd_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	struct factory_data_values *fd;
+	struct spi_flash *sf;
+	u8 *buf;
+	int ret = CMD_RET_FAILURE;
+
+	buf = malloc(FACTORY_DATA_SECT_SIZE);
+	if (!buf) {
+		printf("F-Data:Unable to allocate buffer\n");
+		return CMD_RET_FAILURE;
+	}
+
+	sf = spi_flash_probe(CONFIG_SF_DEFAULT_BUS,
+			     CONFIG_SF_DEFAULT_CS,
+			     CONFIG_SF_DEFAULT_SPEED,
+			     CONFIG_SF_DEFAULT_MODE);
+	if (!sf) {
+		printf("F-Data:Unable to access SPI NOR flash\n");
+		goto err;
+	}
+
+	/* Generate the factory-data struct */
+
+	/* Fist read complete sector into buffer */
+	ret = spi_flash_read(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SECT_SIZE,
+			     (void *)buf);
+	if (ret) {
+		printf("F-Data:spi_flash_read failed (%d)\n", ret);
+		goto err;
+	}
+
+	fd = (struct factory_data_values *)buf;
+	fd->magic = FACTORY_DATA_MAGIC;
+	fd->version = 0x1;
+
+	/* Use existing MAC and UUID values or generate some random ones */
+	if (!eth_env_get_enetaddr("wifiaddr", fd->wifi_mac)) {
+		net_random_ethaddr(fd->wifi_mac);
+		/* to get a different seed value for the MAC address */
+		mdelay(10);
+	}
+
+	if (!eth_env_get_enetaddr("ethaddr", fd->eth_mac))
+		net_random_ethaddr(fd->eth_mac);
+
+	copy_or_generate_uuid(fd->ipr_id, "linuxmoduleid");
+	copy_or_generate_uuid(fd->hqv_id, "linuxmodulehqvid");
+	copy_or_generate_uuid(fd->unielec_id, "linuxmoduleunielecid");
+
+	printf("New factory-data values:\n");
+	printf("wifiaddr=%pM\n", fd->wifi_mac);
+	printf("ethaddr=%pM\n", fd->eth_mac);
+
+	/*
+	 * We don't have the \0 char at the end, so we need to specify the
+	 * length in the printf format instead
+	 */
+	printf("linuxmoduleid=%." __stringify(UUID_STR_LEN) "s\n", fd->ipr_id);
+	printf("linuxmodulehqvid=%." __stringify(UUID_STR_LEN) "s\n",
+	       fd->hqv_id);
+	printf("linuxmoduleunielecid=%." __stringify(UUID_STR_LEN) "s\n",
+	       fd->unielec_id);
+
+	fd->crc = crc32(0, (u8 *)&fd->magic, FACTORY_DATA_CRC_LEN);
+
+	ret = spi_flash_erase(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SECT_SIZE);
+	if (ret) {
+		printf("F-Data:spi_flash_erase failed (%d)\n", ret);
+		goto err;
+	}
+
+	ret = spi_flash_write(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SECT_SIZE,
+			      buf);
+	if (ret) {
+		printf("F-Data:spi_flash_write failed (%d)\n", ret);
+		goto err;
+	}
+
+	printf("F-Data:factory-data values written to SPI NOR flash\n");
+	ret = 0;
+
+err:
+	spi_flash_free(sf);
+
+	free(buf);
+
+	return ret;
+}
+
+U_BOOT_CMD(
+	fd_write,	1,	0,	do_fd_write,
+	"Write test factory-data values to SPI NOR",
+	"\n"
+);
Signature · 1 line
2.19.2
#4 lore raw

PATCH 3/3 mips: mt76xx: gardena-smart-gateway: Add factory data variable handling

Am 28.11.18 um 08:40 schrieb Stefan Roese:

Quoted 7 lines

Some factory data is stored in the SPI NOR and needs to get extracted from there into U-Boot environment variables.

This patch also includes a board-specific command "fd_write" to provide some dummy / default values for this factory-data in the SPI NOR flash. This should only be necessary for testing purposes though.

Quoted 5 lines
Cc Daniel Schwierzeck <[email protected]>
---
 board/gardena/smart-gateway-mt7688/board.c | 266 +++++++++++++++++++++
 1 file changed, 266 insertions(+)

please send a v2 only of this patch. I already applied the other two patches. Thanks.

Quoted 51 lines
board/gardena/smart-gateway-mt7688/board.c +33 -0
index 3a1838e44a..185bdfb71d 100644
@@ -4,11 +4,44 @@
  */
 
 #include <common.h>
+#include <environment.h>
 #include <led.h>
+#include <net.h>
+#include <spi.h>
+#include <spi_flash.h>
+#include <uuid.h>
+#include <linux/ctype.h>
 #include <linux/io.h>
 
 #define MT76XX_AGPIO_CFG	0x1000003c
 
+#define FACTORY_DATA_OFFS	0xc0000
+#define FACTORY_DATA_SECT_SIZE	0x10000
+#if ((CONFIG_ENV_OFFSET_REDUND + CONFIG_ENV_SIZE_REDUND) > FACTORY_DATA_OFFS)
+#error "U-Boot image with environment too big (overlapping with factory-data)!"
+#endif
+#define FACTORY_DATA_USER_OFFS	0x140
+#define FACTORY_DATA_SIZE	0x1f0
+#define FACTORY_DATA_CRC_LEN	(FACTORY_DATA_SIZE -			\
+				 FACTORY_DATA_USER_OFFS - sizeof(u32))
+
+#define FACTORY_DATA_MAGIC	0xCAFEBABE
+
+struct factory_data_values {
+	u8 pad_1[4];
+	u8 wifi_mac[6];		/* offs: 0x004: binary value */
+	u8 pad_2[30];
+	u8 eth_mac[6];		/* offs: 0x028: binary value */
+	u8 pad_3[FACTORY_DATA_USER_OFFS - 4 - 6 - 30 - 6];
+	/* User values start here at offset 0x140 */
+	u32 crc;
+	u32 magic;
+	u32 version;
+	char ipr_id[UUID_STR_LEN];	/* UUID as string w/o ending \0 */
+	char hqv_id[UUID_STR_LEN];	/* UUID as string w/o ending \0 */
+	char unielec_id[UUID_STR_LEN];	/* UUID as string w/o ending \0 */
+};
+
 int board_early_init_f(void)
 {
 	void __iomem *gpio_mode;

board/gardena/smart-gateway-mt7688/board.c int board_early_init_f(void) · line 56

Quoted 4 lines
board/gardena/smart-gateway-mt7688/board.c +1 -0
@@ -20,10 +53,243 @@ int board_early_init_f(void)
 	return 0;
 }
 
+static int prepare_uuid_var(char *fd_ptr, char *env_var_name, char errorchar)

const for the char pointers and bool as return value?

board/gardena/smart-gateway-mt7688/board.c int board_early_init_f(void) · line 64

Quoted 8 lines
board/gardena/smart-gateway-mt7688/board.c +8 -0
+{
+	char str[UUID_STR_LEN + 1];	/* Enough for UUID stuff */
+	bool env_updated = 0;
+	char *env;
+	int i;
+
+	memset(str, 0, sizeof(str));
+	memcpy(str, fd_ptr, UUID_STR_LEN);

you can avoid the memset() with str[UUID_STR_LEN] = 0;

board/gardena/smart-gateway-mt7688/board.c int board_early_init_f(void) · line 69

Quoted 5 lines
board/gardena/smart-gateway-mt7688/board.c +5 -0
+
+	/* Convert non-ascii character to 'X' */
+	for (i = 0; i < UUID_STR_LEN; i++) {
+		if (!(isascii(str[i]) && isprint(str[i])))
+			str[i] = errorchar;

can it happen that the string value is shorter than UUID_STR_LEN and is zero-terminated? If yes is it intented to fill the remaining characters with errorchar?

Quoted 17 lines
board/gardena/smart-gateway-mt7688/board.c +17 -0
+	}
+
+	env = env_get(env_var_name);
+	if (strcmp(env, str)) {
+		env_set(env_var_name, str);
+		env_updated = 1;
+	}
+
+	return env_updated;
+}
+
+static void factory_data_env_config(void)
+{
+	struct factory_data_values *fd;
+	struct spi_flash *sf;
+	int env_updated = 0;
+	char str[UUID_STR_LEN + 1];	/* Enough for UUID stuff */

board/gardena/smart-gateway-mt7688/board.c int board_early_init_f(void) · line 96

Quoted 10 lines
board/gardena/smart-gateway-mt7688/board.c +10 -0
+	char *env;
+	u8 *buf;
+	u32 crc;
+	int ret;
+	u8 *ptr;
+
+	buf = malloc(FACTORY_DATA_SIZE);
+	if (!buf) {
+		printf("F-Data:Unable to allocate buffer\n");
+		goto err;

this jump to 'err' is incorrect as you would free a NULL poinzer

Quoted 9 lines
board/gardena/smart-gateway-mt7688/board.c +9 -0
+	}
+
+	/*
+	 * Get values from factory-data area in SPI NOR
+	 */
+	sf = spi_flash_probe(CONFIG_SF_DEFAULT_BUS,
+			     CONFIG_SF_DEFAULT_CS,
+			     CONFIG_SF_DEFAULT_SPEED,
+			     CONFIG_SF_DEFAULT_MODE);

board/gardena/smart-gateway-mt7688/board.c int board_early_init_f(void) · line 115

Quoted 10 lines
board/gardena/smart-gateway-mt7688/board.c +10 -0
+	if (!sf) {
+		printf("F-Data:Unable to access SPI NOR flash\n");
+		goto err;
+	}
+
+	ret = spi_flash_read(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SIZE,
+			     (void *)buf);
+	if (ret) {
+		printf("F-Data:Unable to read factory-data from SPI NOR\n");
+		goto err;

you need another goto label with spi_flash_free(sf) from here on

Quoted 40 lines
board/gardena/smart-gateway-mt7688/board.c +40 -0
+	}
+
+	fd = (struct factory_data_values *)buf;
+
+	if (fd->magic != FACTORY_DATA_MAGIC)
+		printf("F-Data:Magic value not correct\n");
+
+	crc = crc32(0, (u8 *)&fd->magic, FACTORY_DATA_CRC_LEN);
+	if (crc != fd->crc)
+		printf("F-Data:CRC not correct\n");
+	else
+		printf("F-Data:factory-data version %x detected\n",
+		       fd->version);
+
+	/* Handle wifi_mac env variable */
+	ptr = fd->wifi_mac;
+	sprintf(str, "%pM", ptr);
+	if (!is_valid_ethaddr(ptr))
+		printf("F-Data:Invalid MAC addr: wifi_mac %s\n", str);
+
+	env = env_get("wifiaddr");
+	if (strcmp(env, str)) {
+		env_set("wifiaddr", str);
+		env_updated = 1;
+	}
+
+	/* Handle eth_mac env variable */
+	ptr = fd->eth_mac;
+	sprintf(str, "%pM", ptr);
+	if (!is_valid_ethaddr(ptr))
+		printf("F-Data:Invalid MAC addr: eth_mac %s\n", str);
+
+	env = env_get("ethaddr");
+	if (strcmp(env, str)) {
+		env_set("ethaddr", str);
+		env_updated = 1;
+	}
+
+	/* Handle UUID env variables */
+	env_updated |= prepare_uuid_var(fd->ipr_id, "linuxmoduleid", 'X');

board/gardena/smart-gateway-mt7688/board.c int board_early_init_f(void) · line 165

Quoted 10 lines
board/gardena/smart-gateway-mt7688/board.c +10 -0
+	env_updated |= prepare_uuid_var(fd->hqv_id, "linuxmodulehqvid", '\0');
+	env_updated |= prepare_uuid_var(fd->unielec_id,
+					"linuxmoduleunielecid", 'X');
+
+	/* Check if the environment was updated and needs to get stored */
+	if (env_updated != 0) {
+		printf("F-Data:Values don't match env values -> saving\n");
+		env_save();
+	} else {
+		printf("F-Data:Values match current env values\n");

maybe debug() or do you want to see that at each boot?

Quoted 7 lines
board/gardena/smart-gateway-mt7688/board.c +6 -0
+	}
+
+err:
+	free(buf);
+}
+
 int board_late_init(void)

board/gardena/smart-gateway-mt7688/board.c int board_early_init_f(void) · line 182

Quoted 10 lines
board/gardena/smart-gateway-mt7688/board.c +4 -0
 {
 	if (IS_ENABLED(CONFIG_LED))
 		led_default_state();
 
+	factory_data_env_config();
+
 	return 0;
 }
+
+static void copy_or_generate_uuid(char *fd_ptr, char *env_var_name)

const char * ?

Quoted 28 lines
board/gardena/smart-gateway-mt7688/board.c +28 -0
+{
+	char str[UUID_STR_LEN + 1];	/* Enough for UUID stuff */
+	char *env;
+
+	/* Don't use the UUID dest place, as the \0 char won't fit */
+	env = env_get(env_var_name);
+	if (env) {
+		memcpy(fd_ptr, env, UUID_STR_LEN);
+	} else {
+		gen_rand_uuid_str(str, UUID_STR_FORMAT_STD);
+		memcpy(fd_ptr, str, UUID_STR_LEN);
+	}
+}
+
+/*
+ * Helper function to provide some sane factory-data values for testing
+ * purpose, when these values are not programmed correctly
+ */
+int do_fd_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	struct factory_data_values *fd;
+	struct spi_flash *sf;
+	u8 *buf;
+	int ret = CMD_RET_FAILURE;
+
+	buf = malloc(FACTORY_DATA_SECT_SIZE);
+	if (!buf) {
+		printf("F-Data:Unable to allocate buffer\n");

board/gardena/smart-gateway-mt7688/board.c int board_early_init_f(void) · line 220

Quoted 10 lines
board/gardena/smart-gateway-mt7688/board.c +10 -0
+		return CMD_RET_FAILURE;
+	}
+
+	sf = spi_flash_probe(CONFIG_SF_DEFAULT_BUS,
+			     CONFIG_SF_DEFAULT_CS,
+			     CONFIG_SF_DEFAULT_SPEED,
+			     CONFIG_SF_DEFAULT_MODE);
+	if (!sf) {
+		printf("F-Data:Unable to access SPI NOR flash\n");
+		goto err;

you should have two goto labels and you should only jump the free() in this error path otherwise you call sf_flash_free() on a NULL pointer.

Quoted 76 lines
board/gardena/smart-gateway-mt7688/board.c +75 -0
+	}
+
+	/* Generate the factory-data struct */
+
+	/* Fist read complete sector into buffer */
+	ret = spi_flash_read(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SECT_SIZE,
+			     (void *)buf);
+	if (ret) {
+		printf("F-Data:spi_flash_read failed (%d)\n", ret);
+		goto err;
+	}
+
+	fd = (struct factory_data_values *)buf;
+	fd->magic = FACTORY_DATA_MAGIC;
+	fd->version = 0x1;
+
+	/* Use existing MAC and UUID values or generate some random ones */
+	if (!eth_env_get_enetaddr("wifiaddr", fd->wifi_mac)) {
+		net_random_ethaddr(fd->wifi_mac);
+		/* to get a different seed value for the MAC address */
+		mdelay(10);
+	}
+
+	if (!eth_env_get_enetaddr("ethaddr", fd->eth_mac))
+		net_random_ethaddr(fd->eth_mac);
+
+	copy_or_generate_uuid(fd->ipr_id, "linuxmoduleid");
+	copy_or_generate_uuid(fd->hqv_id, "linuxmodulehqvid");
+	copy_or_generate_uuid(fd->unielec_id, "linuxmoduleunielecid");
+
+	printf("New factory-data values:\n");
+	printf("wifiaddr=%pM\n", fd->wifi_mac);
+	printf("ethaddr=%pM\n", fd->eth_mac);
+
+	/*
+	 * We don't have the \0 char at the end, so we need to specify the
+	 * length in the printf format instead
+	 */
+	printf("linuxmoduleid=%." __stringify(UUID_STR_LEN) "s\n", fd->ipr_id);
+	printf("linuxmodulehqvid=%." __stringify(UUID_STR_LEN) "s\n",
+	       fd->hqv_id);
+	printf("linuxmoduleunielecid=%." __stringify(UUID_STR_LEN) "s\n",
+	       fd->unielec_id);
+
+	fd->crc = crc32(0, (u8 *)&fd->magic, FACTORY_DATA_CRC_LEN);
+
+	ret = spi_flash_erase(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SECT_SIZE);
+	if (ret) {
+		printf("F-Data:spi_flash_erase failed (%d)\n", ret);
+		goto err;
+	}
+
+	ret = spi_flash_write(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SECT_SIZE,
+			      buf);
+	if (ret) {
+		printf("F-Data:spi_flash_write failed (%d)\n", ret);
+		goto err;
+	}
+
+	printf("F-Data:factory-data values written to SPI NOR flash\n");
+	ret = 0;
+
+err:
+	spi_flash_free(sf);
+
+	free(buf);
+
+	return ret;
+}
+
+U_BOOT_CMD(
+	fd_write,	1,	0,	do_fd_write,
+	"Write test factory-data values to SPI NOR",
+	"\n"
+);
Signature · 9 lines
- Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20181128/fbbaa8e1/attachment.sig>
#5 lore raw

PATCH 3/3 mips: mt76xx: gardena-smart-gateway: Add factory data variable handling

Quoted 10 lines · Daniel Schwierzeck

Am 28.11.18 um 08:40 schrieb Stefan Roese:

Quoted 7 lines

Some factory data is stored in the SPI NOR and needs to get extracted from there into U-Boot environment variables.

This patch also includes a board-specific command "fd_write" to provide some dummy / default values for this factory-data in the SPI NOR flash. This should only be necessary for testing purposes though.

Quoted 8 lines
Quoted 5 lines
Cc Daniel Schwierzeck <[email protected]>
---
  board/gardena/smart-gateway-mt7688/board.c | 266 +++++++++++++++++++++
  1 file changed, 266 insertions(+)

please send a v2 only of this patch. I already applied the other two patches. Thanks.

v2 will follow shortly.

Quoted 54 lines
Quoted 54 lines
board/gardena/smart-gateway-mt7688/board.c +33 -0
index 3a1838e44a..185bdfb71d 100644
@@ -4,11 +4,44 @@
   */
 
  #include <common.h>
+#include <environment.h>
  #include <led.h>
+#include <net.h>
+#include <spi.h>
+#include <spi_flash.h>
+#include <uuid.h>
+#include <linux/ctype.h>
  #include <linux/io.h>
 
  #define MT76XX_AGPIO_CFG	0x1000003c
 
+#define FACTORY_DATA_OFFS	0xc0000
+#define FACTORY_DATA_SECT_SIZE	0x10000
+#if ((CONFIG_ENV_OFFSET_REDUND + CONFIG_ENV_SIZE_REDUND) > FACTORY_DATA_OFFS)
+#error "U-Boot image with environment too big (overlapping with factory-data)!"
+#endif
+#define FACTORY_DATA_USER_OFFS	0x140
+#define FACTORY_DATA_SIZE	0x1f0
+#define FACTORY_DATA_CRC_LEN	(FACTORY_DATA_SIZE -			\
+				 FACTORY_DATA_USER_OFFS - sizeof(u32))
+
+#define FACTORY_DATA_MAGIC	0xCAFEBABE
+
+struct factory_data_values {
+	u8 pad_1[4];
+	u8 wifi_mac[6];		/* offs: 0x004: binary value */
+	u8 pad_2[30];
+	u8 eth_mac[6];		/* offs: 0x028: binary value */
+	u8 pad_3[FACTORY_DATA_USER_OFFS - 4 - 6 - 30 - 6];
+	/* User values start here at offset 0x140 */
+	u32 crc;
+	u32 magic;
+	u32 version;
+	char ipr_id[UUID_STR_LEN];	/* UUID as string w/o ending \0 */
+	char hqv_id[UUID_STR_LEN];	/* UUID as string w/o ending \0 */
+	char unielec_id[UUID_STR_LEN];	/* UUID as string w/o ending \0 */
+};
+
  int board_early_init_f(void)
  {
  	void __iomem *gpio_mode;
@@ -20,10 +53,243 @@ int board_early_init_f(void)
  	return 0;
  }
 
Quoted 3 lines

board/gardena/smart-gateway-mt7688/board.c int board_early_init_f(void) · line 56

Quoted 1 line
board/gardena/smart-gateway-mt7688/board.c +1 -0
+static int prepare_uuid_var(char *fd_ptr, char *env_var_name, char errorchar)

const for the char pointers and bool as return value?

Ack.

Quoted 10 lines

board/gardena/smart-gateway-mt7688/board.c int board_early_init_f(void) · line 64

Quoted 8 lines
board/gardena/smart-gateway-mt7688/board.c +8 -0
+{
+	char str[UUID_STR_LEN + 1];	/* Enough for UUID stuff */
+	bool env_updated = 0;
+	char *env;
+	int i;
+
+	memset(str, 0, sizeof(str));
+	memcpy(str, fd_ptr, UUID_STR_LEN);

you can avoid the memset() with str[UUID_STR_LEN] = 0;

Ack.

Quoted 9 lines

board/gardena/smart-gateway-mt7688/board.c int board_early_init_f(void) · line 69

Quoted 5 lines
board/gardena/smart-gateway-mt7688/board.c +5 -0
+
+	/* Convert non-ascii character to 'X' */
+	for (i = 0; i < UUID_STR_LEN; i++) {
+		if (!(isascii(str[i]) && isprint(str[i])))
+			str[i] = errorchar;

can it happen that the string value is shorter than UUID_STR_LEN and is zero-terminated? If yes is it intented to fill the remaining characters with errorchar?

The string might be shorter and we intentionally want to fill the string with these chars. This makes not that much sense with '\0', but it simplifies the code this way.

Quoted 21 lines
Quoted 21 lines
board/gardena/smart-gateway-mt7688/board.c +21 -0
+	}
+
+	env = env_get(env_var_name);
+	if (strcmp(env, str)) {
+		env_set(env_var_name, str);
+		env_updated = 1;
+	}
+
+	return env_updated;
+}
+
+static void factory_data_env_config(void)
+{
+	struct factory_data_values *fd;
+	struct spi_flash *sf;
+	int env_updated = 0;
+	char str[UUID_STR_LEN + 1];	/* Enough for UUID stuff */
+	char *env;
+	u8 *buf;
+	u32 crc;
+	int ret;
Quoted 8 lines

board/gardena/smart-gateway-mt7688/board.c int board_early_init_f(void) · line 96

Quoted 6 lines
board/gardena/smart-gateway-mt7688/board.c +6 -0
+	u8 *ptr;
+
+	buf = malloc(FACTORY_DATA_SIZE);
+	if (!buf) {
+		printf("F-Data:Unable to allocate buffer\n");
+		goto err;

this jump to 'err' is incorrect as you would free a NULL poinzer

Ack.

Thanks for the review. I'll change all the other issues as well for v2.

Thanks,
Stefan

#6 lore raw

PATCH v2 3/3 mips: mt76xx: gardena-smart-gateway: Add factory data variable handling

In reply to Stefan Roese

Some factory data is stored in the SPI NOR and needs to get extracted from there into U-Boot environment variables.

This patch also includes a board-specific command "fd_write" to provide some dummy / default values for this factory-data in the SPI NOR flash. This should only be necessary for testing purposes though.

Cc Daniel Schwierzeck <[email protected]>

---
v2:
- Use "const char *" where possible
- Avoid memset() by assigning value in variable declaration
- Fix goto's with correct cleanup (free, spi_flash_free)
- Change one printf to debug to be less verbose

board/gardena/smart-gateway-mt7688/board.c | 270 +++++++++++++++++++++

 1 file changed, 270 insertions(+)
board/gardena/smart-gateway-mt7688/board.c +270 -0
index 3a1838e44a..db677edd85 100644
@@ -4,11 +4,44 @@
  */
 
 #include <common.h>
+#include <environment.h>
 #include <led.h>
+#include <net.h>
+#include <spi.h>
+#include <spi_flash.h>
+#include <uuid.h>
+#include <linux/ctype.h>
 #include <linux/io.h>
 
 #define MT76XX_AGPIO_CFG	0x1000003c
 
+#define FACTORY_DATA_OFFS	0xc0000
+#define FACTORY_DATA_SECT_SIZE	0x10000
+#if ((CONFIG_ENV_OFFSET_REDUND + CONFIG_ENV_SIZE_REDUND) > FACTORY_DATA_OFFS)
+#error "U-Boot image with environment too big (overlapping with factory-data)!"
+#endif
+#define FACTORY_DATA_USER_OFFS	0x140
+#define FACTORY_DATA_SIZE	0x1f0
+#define FACTORY_DATA_CRC_LEN	(FACTORY_DATA_SIZE -			\
+				 FACTORY_DATA_USER_OFFS - sizeof(u32))
+
+#define FACTORY_DATA_MAGIC	0xCAFEBABE
+
+struct factory_data_values {
+	u8 pad_1[4];
+	u8 wifi_mac[6];		/* offs: 0x004: binary value */
+	u8 pad_2[30];
+	u8 eth_mac[6];		/* offs: 0x028: binary value */
+	u8 pad_3[FACTORY_DATA_USER_OFFS - 4 - 6 - 30 - 6];
+	/* User values start here at offset 0x140 */
+	u32 crc;
+	u32 magic;
+	u32 version;
+	char ipr_id[UUID_STR_LEN];	/* UUID as string w/o ending \0 */
+	char hqv_id[UUID_STR_LEN];	/* UUID as string w/o ending \0 */
+	char unielec_id[UUID_STR_LEN];	/* UUID as string w/o ending \0 */
+};
+
 int board_early_init_f(void)
 {
 	void __iomem *gpio_mode;
@@ -20,10 +53,247 @@ int board_early_init_f(void)
 	return 0;
 }
 
+static bool prepare_uuid_var(const char *fd_ptr, const char *env_var_name,
+			     char errorchar)
+{
+	char str[UUID_STR_LEN + 1] = { 0 };	/* Enough for UUID stuff */
+	bool env_updated = false;
+	char *env;
+	int i;
+
+	memcpy(str, fd_ptr, UUID_STR_LEN);
+
+	/* Convert non-ascii character to 'X' */
+	for (i = 0; i < UUID_STR_LEN; i++) {
+		if (!(isascii(str[i]) && isprint(str[i])))
+			str[i] = errorchar;
+	}
+
+	env = env_get(env_var_name);
+	if (strcmp(env, str)) {
+		env_set(env_var_name, str);
+		env_updated = true;
+	}
+
+	return env_updated;
+}
+
+static void factory_data_env_config(void)
+{
+	struct factory_data_values *fd;
+	struct spi_flash *sf;
+	int env_updated = 0;
+	char str[UUID_STR_LEN + 1];	/* Enough for UUID stuff */
+	char *env;
+	u8 *buf;
+	u32 crc;
+	int ret;
+	u8 *ptr;
+
+	buf = malloc(FACTORY_DATA_SIZE);
+	if (!buf) {
+		printf("F-Data:Unable to allocate buffer\n");
+		return;
+	}
+
+	/*
+	 * Get values from factory-data area in SPI NOR
+	 */
+	sf = spi_flash_probe(CONFIG_SF_DEFAULT_BUS,
+			     CONFIG_SF_DEFAULT_CS,
+			     CONFIG_SF_DEFAULT_SPEED,
+			     CONFIG_SF_DEFAULT_MODE);
+	if (!sf) {
+		printf("F-Data:Unable to access SPI NOR flash\n");
+		goto err_free;
+	}
+
+	ret = spi_flash_read(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SIZE,
+			     (void *)buf);
+	if (ret) {
+		printf("F-Data:Unable to read factory-data from SPI NOR\n");
+		goto err_spi_flash;
+	}
+
+	fd = (struct factory_data_values *)buf;
+
+	if (fd->magic != FACTORY_DATA_MAGIC)
+		printf("F-Data:Magic value not correct\n");
+
+	crc = crc32(0, (u8 *)&fd->magic, FACTORY_DATA_CRC_LEN);
+	if (crc != fd->crc)
+		printf("F-Data:CRC not correct\n");
+	else
+		printf("F-Data:factory-data version %x detected\n",
+		       fd->version);
+
+	/* Handle wifi_mac env variable */
+	ptr = fd->wifi_mac;
+	sprintf(str, "%pM", ptr);
+	if (!is_valid_ethaddr(ptr))
+		printf("F-Data:Invalid MAC addr: wifi_mac %s\n", str);
+
+	env = env_get("wifiaddr");
+	if (strcmp(env, str)) {
+		env_set("wifiaddr", str);
+		env_updated = 1;
+	}
+
+	/* Handle eth_mac env variable */
+	ptr = fd->eth_mac;
+	sprintf(str, "%pM", ptr);
+	if (!is_valid_ethaddr(ptr))
+		printf("F-Data:Invalid MAC addr: eth_mac %s\n", str);
+
+	env = env_get("ethaddr");
+	if (strcmp(env, str)) {
+		env_set("ethaddr", str);
+		env_updated = 1;
+	}
+
+	/* Handle UUID env variables */
+	env_updated |= prepare_uuid_var(fd->ipr_id, "linuxmoduleid", 'X');
+	env_updated |= prepare_uuid_var(fd->hqv_id, "linuxmodulehqvid", '\0');
+	env_updated |= prepare_uuid_var(fd->unielec_id,
+					"linuxmoduleunielecid", 'X');
+
+	/* Check if the environment was updated and needs to get stored */
+	if (env_updated != 0) {
+		printf("F-Data:Values don't match env values -> saving\n");
+		env_save();
+	} else {
+		debug("F-Data:Values match current env values\n");
+	}
+
+err_spi_flash:
+	spi_flash_free(sf);
+
+err_free:
+	free(buf);
+}
+
 int board_late_init(void)
 {
 	if (IS_ENABLED(CONFIG_LED))
 		led_default_state();
 
+	factory_data_env_config();
+
 	return 0;
 }
+
+static void copy_or_generate_uuid(char *fd_ptr, const char *env_var_name)
+{
+	char str[UUID_STR_LEN + 1];	/* Enough for UUID stuff */
+	char *env;
+
+	/* Don't use the UUID dest place, as the \0 char won't fit */
+	env = env_get(env_var_name);
+	if (env) {
+		memcpy(fd_ptr, env, UUID_STR_LEN);
+	} else {
+		gen_rand_uuid_str(str, UUID_STR_FORMAT_STD);
+		memcpy(fd_ptr, str, UUID_STR_LEN);
+	}
+}
+
+/*
+ * Helper function to provide some sane factory-data values for testing
+ * purpose, when these values are not programmed correctly
+ */
+int do_fd_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	struct factory_data_values *fd;
+	struct spi_flash *sf;
+	u8 *buf;
+	int ret = CMD_RET_FAILURE;
+
+	buf = malloc(FACTORY_DATA_SECT_SIZE);
+	if (!buf) {
+		printf("F-Data:Unable to allocate buffer\n");
+		return CMD_RET_FAILURE;
+	}
+
+	sf = spi_flash_probe(CONFIG_SF_DEFAULT_BUS,
+			     CONFIG_SF_DEFAULT_CS,
+			     CONFIG_SF_DEFAULT_SPEED,
+			     CONFIG_SF_DEFAULT_MODE);
+	if (!sf) {
+		printf("F-Data:Unable to access SPI NOR flash\n");
+		goto err_free;
+	}
+
+	/* Generate the factory-data struct */
+
+	/* Fist read complete sector into buffer */
+	ret = spi_flash_read(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SECT_SIZE,
+			     (void *)buf);
+	if (ret) {
+		printf("F-Data:spi_flash_read failed (%d)\n", ret);
+		goto err_spi_flash;
+	}
+
+	fd = (struct factory_data_values *)buf;
+	fd->magic = FACTORY_DATA_MAGIC;
+	fd->version = 0x1;
+
+	/* Use existing MAC and UUID values or generate some random ones */
+	if (!eth_env_get_enetaddr("wifiaddr", fd->wifi_mac)) {
+		net_random_ethaddr(fd->wifi_mac);
+		/* to get a different seed value for the MAC address */
+		mdelay(10);
+	}
+
+	if (!eth_env_get_enetaddr("ethaddr", fd->eth_mac))
+		net_random_ethaddr(fd->eth_mac);
+
+	copy_or_generate_uuid(fd->ipr_id, "linuxmoduleid");
+	copy_or_generate_uuid(fd->hqv_id, "linuxmodulehqvid");
+	copy_or_generate_uuid(fd->unielec_id, "linuxmoduleunielecid");
+
+	printf("New factory-data values:\n");
+	printf("wifiaddr=%pM\n", fd->wifi_mac);
+	printf("ethaddr=%pM\n", fd->eth_mac);
+
+	/*
+	 * We don't have the \0 char at the end, so we need to specify the
+	 * length in the printf format instead
+	 */
+	printf("linuxmoduleid=%." __stringify(UUID_STR_LEN) "s\n", fd->ipr_id);
+	printf("linuxmodulehqvid=%." __stringify(UUID_STR_LEN) "s\n",
+	       fd->hqv_id);
+	printf("linuxmoduleunielecid=%." __stringify(UUID_STR_LEN) "s\n",
+	       fd->unielec_id);
+
+	fd->crc = crc32(0, (u8 *)&fd->magic, FACTORY_DATA_CRC_LEN);
+
+	ret = spi_flash_erase(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SECT_SIZE);
+	if (ret) {
+		printf("F-Data:spi_flash_erase failed (%d)\n", ret);
+		goto err_spi_flash;
+	}
+
+	ret = spi_flash_write(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SECT_SIZE,
+			      buf);
+	if (ret) {
+		printf("F-Data:spi_flash_write failed (%d)\n", ret);
+		goto err_spi_flash;
+	}
+
+	printf("F-Data:factory-data values written to SPI NOR flash\n");
+	ret = 0;
+
+err_spi_flash:
+	spi_flash_free(sf);
+
+err_free:
+	free(buf);
+
+	return ret;
+}
+
+U_BOOT_CMD(
+	fd_write,	1,	0,	do_fd_write,
+	"Write test factory-data values to SPI NOR",
+	"\n"
+);
Signature · 1 line
2.19.2
#7 lore raw

PATCH v3 3/3 mips: mt76xx: gardena-smart-gateway: Add factory data variable handling

In reply to Stefan Roese

Some factory data is stored in the SPI NOR and needs to get extracted from there into U-Boot environment variables.

This patch also includes a board-specific command "fd_write" to provide some dummy / default values for this factory-data in the SPI NOR flash. This should only be necessary for testing purposes though.

Cc Daniel Schwierzeck <[email protected]>

---
v3:
- Remove unnecessary ret = 0 assignment in do_fd_write()
- Change copy_or_generate_uuid() to not generate random values after the terminating char

v2:
- Use "const char *" where possible
- Avoid memset() by assigning value in variable declaration
- Fix goto's with correct cleanup (free, spi_flash_free)
- Change one printf to debug to be less verbose

 board/gardena/smart-gateway-mt7688/board.c | 269 +++++++++++++++++++++
 1 file changed, 269 insertions(+)
board/gardena/smart-gateway-mt7688/board.c +269 -0
index 3a1838e44a..476139e1b2 100644
@@ -4,11 +4,44 @@
  */
 
 #include <common.h>
+#include <environment.h>
 #include <led.h>
+#include <net.h>
+#include <spi.h>
+#include <spi_flash.h>
+#include <uuid.h>
+#include <linux/ctype.h>
 #include <linux/io.h>
 
 #define MT76XX_AGPIO_CFG	0x1000003c
 
+#define FACTORY_DATA_OFFS	0xc0000
+#define FACTORY_DATA_SECT_SIZE	0x10000
+#if ((CONFIG_ENV_OFFSET_REDUND + CONFIG_ENV_SIZE_REDUND) > FACTORY_DATA_OFFS)
+#error "U-Boot image with environment too big (overlapping with factory-data)!"
+#endif
+#define FACTORY_DATA_USER_OFFS	0x140
+#define FACTORY_DATA_SIZE	0x1f0
+#define FACTORY_DATA_CRC_LEN	(FACTORY_DATA_SIZE -			\
+				 FACTORY_DATA_USER_OFFS - sizeof(u32))
+
+#define FACTORY_DATA_MAGIC	0xCAFEBABE
+
+struct factory_data_values {
+	u8 pad_1[4];
+	u8 wifi_mac[6];		/* offs: 0x004: binary value */
+	u8 pad_2[30];
+	u8 eth_mac[6];		/* offs: 0x028: binary value */
+	u8 pad_3[FACTORY_DATA_USER_OFFS - 4 - 6 - 30 - 6];
+	/* User values start here at offset 0x140 */
+	u32 crc;
+	u32 magic;
+	u32 version;
+	char ipr_id[UUID_STR_LEN];	/* UUID as string w/o ending \0 */
+	char hqv_id[UUID_STR_LEN];	/* UUID as string w/o ending \0 */
+	char unielec_id[UUID_STR_LEN];	/* UUID as string w/o ending \0 */
+};
+
 int board_early_init_f(void)
 {
 	void __iomem *gpio_mode;
@@ -20,10 +53,246 @@ int board_early_init_f(void)
 	return 0;
 }
 
+static bool prepare_uuid_var(const char *fd_ptr, const char *env_var_name,
+			     char errorchar)
+{
+	char str[UUID_STR_LEN + 1] = { 0 };	/* Enough for UUID stuff */
+	bool env_updated = false;
+	char *env;
+	int i;
+
+	memcpy(str, fd_ptr, UUID_STR_LEN);
+
+	/* Convert non-ascii character to 'X' */
+	for (i = 0; i < UUID_STR_LEN; i++) {
+		if (!(isascii(str[i]) && isprint(str[i])))
+			str[i] = errorchar;
+	}
+
+	env = env_get(env_var_name);
+	if (strcmp(env, str)) {
+		env_set(env_var_name, str);
+		env_updated = true;
+	}
+
+	return env_updated;
+}
+
+static void factory_data_env_config(void)
+{
+	struct factory_data_values *fd;
+	struct spi_flash *sf;
+	int env_updated = 0;
+	char str[UUID_STR_LEN + 1];	/* Enough for UUID stuff */
+	char *env;
+	u8 *buf;
+	u32 crc;
+	int ret;
+	u8 *ptr;
+
+	buf = malloc(FACTORY_DATA_SIZE);
+	if (!buf) {
+		printf("F-Data:Unable to allocate buffer\n");
+		return;
+	}
+
+	/*
+	 * Get values from factory-data area in SPI NOR
+	 */
+	sf = spi_flash_probe(CONFIG_SF_DEFAULT_BUS,
+			     CONFIG_SF_DEFAULT_CS,
+			     CONFIG_SF_DEFAULT_SPEED,
+			     CONFIG_SF_DEFAULT_MODE);
+	if (!sf) {
+		printf("F-Data:Unable to access SPI NOR flash\n");
+		goto err_free;
+	}
+
+	ret = spi_flash_read(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SIZE,
+			     (void *)buf);
+	if (ret) {
+		printf("F-Data:Unable to read factory-data from SPI NOR\n");
+		goto err_spi_flash;
+	}
+
+	fd = (struct factory_data_values *)buf;
+
+	if (fd->magic != FACTORY_DATA_MAGIC)
+		printf("F-Data:Magic value not correct\n");
+
+	crc = crc32(0, (u8 *)&fd->magic, FACTORY_DATA_CRC_LEN);
+	if (crc != fd->crc)
+		printf("F-Data:CRC not correct\n");
+	else
+		printf("F-Data:factory-data version %x detected\n",
+		       fd->version);
+
+	/* Handle wifi_mac env variable */
+	ptr = fd->wifi_mac;
+	sprintf(str, "%pM", ptr);
+	if (!is_valid_ethaddr(ptr))
+		printf("F-Data:Invalid MAC addr: wifi_mac %s\n", str);
+
+	env = env_get("wifiaddr");
+	if (strcmp(env, str)) {
+		env_set("wifiaddr", str);
+		env_updated = 1;
+	}
+
+	/* Handle eth_mac env variable */
+	ptr = fd->eth_mac;
+	sprintf(str, "%pM", ptr);
+	if (!is_valid_ethaddr(ptr))
+		printf("F-Data:Invalid MAC addr: eth_mac %s\n", str);
+
+	env = env_get("ethaddr");
+	if (strcmp(env, str)) {
+		env_set("ethaddr", str);
+		env_updated = 1;
+	}
+
+	/* Handle UUID env variables */
+	env_updated |= prepare_uuid_var(fd->ipr_id, "linuxmoduleid", 'X');
+	env_updated |= prepare_uuid_var(fd->hqv_id, "linuxmodulehqvid", '\0');
+	env_updated |= prepare_uuid_var(fd->unielec_id,
+					"linuxmoduleunielecid", 'X');
+
+	/* Check if the environment was updated and needs to get stored */
+	if (env_updated != 0) {
+		printf("F-Data:Values don't match env values -> saving\n");
+		env_save();
+	} else {
+		debug("F-Data:Values match current env values\n");
+	}
+
+err_spi_flash:
+	spi_flash_free(sf);
+
+err_free:
+	free(buf);
+}
+
 int board_late_init(void)
 {
 	if (IS_ENABLED(CONFIG_LED))
 		led_default_state();
 
+	factory_data_env_config();
+
 	return 0;
 }
+
+static void copy_or_generate_uuid(char *fd_ptr, const char *env_var_name)
+{
+	char str[UUID_STR_LEN + 1] = { 0 };	/* Enough for UUID stuff */
+	char *env;
+
+	/* Don't use the UUID dest place, as the \0 char won't fit */
+	env = env_get(env_var_name);
+	if (env)
+		strncpy(str, env, UUID_STR_LEN);
+	else
+		gen_rand_uuid_str(str, UUID_STR_FORMAT_STD);
+
+	memcpy(fd_ptr, str, UUID_STR_LEN);
+}
+
+/*
+ * Helper function to provide some sane factory-data values for testing
+ * purpose, when these values are not programmed correctly
+ */
+int do_fd_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	struct factory_data_values *fd;
+	struct spi_flash *sf;
+	u8 *buf;
+	int ret = CMD_RET_FAILURE;
+
+	buf = malloc(FACTORY_DATA_SECT_SIZE);
+	if (!buf) {
+		printf("F-Data:Unable to allocate buffer\n");
+		return CMD_RET_FAILURE;
+	}
+
+	sf = spi_flash_probe(CONFIG_SF_DEFAULT_BUS,
+			     CONFIG_SF_DEFAULT_CS,
+			     CONFIG_SF_DEFAULT_SPEED,
+			     CONFIG_SF_DEFAULT_MODE);
+	if (!sf) {
+		printf("F-Data:Unable to access SPI NOR flash\n");
+		goto err_free;
+	}
+
+	/* Generate the factory-data struct */
+
+	/* Fist read complete sector into buffer */
+	ret = spi_flash_read(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SECT_SIZE,
+			     (void *)buf);
+	if (ret) {
+		printf("F-Data:spi_flash_read failed (%d)\n", ret);
+		goto err_spi_flash;
+	}
+
+	fd = (struct factory_data_values *)buf;
+	fd->magic = FACTORY_DATA_MAGIC;
+	fd->version = 0x1;
+
+	/* Use existing MAC and UUID values or generate some random ones */
+	if (!eth_env_get_enetaddr("wifiaddr", fd->wifi_mac)) {
+		net_random_ethaddr(fd->wifi_mac);
+		/* to get a different seed value for the MAC address */
+		mdelay(10);
+	}
+
+	if (!eth_env_get_enetaddr("ethaddr", fd->eth_mac))
+		net_random_ethaddr(fd->eth_mac);
+
+	copy_or_generate_uuid(fd->ipr_id, "linuxmoduleid");
+	copy_or_generate_uuid(fd->hqv_id, "linuxmodulehqvid");
+	copy_or_generate_uuid(fd->unielec_id, "linuxmoduleunielecid");
+
+	printf("New factory-data values:\n");
+	printf("wifiaddr=%pM\n", fd->wifi_mac);
+	printf("ethaddr=%pM\n", fd->eth_mac);
+
+	/*
+	 * We don't have the \0 char at the end, so we need to specify the
+	 * length in the printf format instead
+	 */
+	printf("linuxmoduleid=%." __stringify(UUID_STR_LEN) "s\n", fd->ipr_id);
+	printf("linuxmodulehqvid=%." __stringify(UUID_STR_LEN) "s\n",
+	       fd->hqv_id);
+	printf("linuxmoduleunielecid=%." __stringify(UUID_STR_LEN) "s\n",
+	       fd->unielec_id);
+
+	fd->crc = crc32(0, (u8 *)&fd->magic, FACTORY_DATA_CRC_LEN);
+
+	ret = spi_flash_erase(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SECT_SIZE);
+	if (ret) {
+		printf("F-Data:spi_flash_erase failed (%d)\n", ret);
+		goto err_spi_flash;
+	}
+
+	ret = spi_flash_write(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SECT_SIZE,
+			      buf);
+	if (ret) {
+		printf("F-Data:spi_flash_write failed (%d)\n", ret);
+		goto err_spi_flash;
+	}
+
+	printf("F-Data:factory-data values written to SPI NOR flash\n");
+
+err_spi_flash:
+	spi_flash_free(sf);
+
+err_free:
+	free(buf);
+
+	return ret;
+}
+
+U_BOOT_CMD(
+	fd_write,	1,	0,	do_fd_write,
+	"Write test factory-data values to SPI NOR",
+	"\n"
+);
Signature · 1 line
2.19.2
#8 lore raw

PATCH v4 3/3 mips: mt76xx: gardena-smart-gateway: Add factory data variable handling

In reply to Stefan Roese

Some factory data is stored in the SPI NOR and needs to get extracted from there into U-Boot environment variables.

This patch also includes a board-specific command "fd_write" to provide some dummy / default values for this factory-data in the SPI NOR flash. This should only be necessary for testing purposes though.

Cc Daniel Schwierzeck <[email protected]>

---
v4:
- Change end-char for "linuxmoduleunielecid"

v3:
- Remove unnecessary ret = 0 assignment in do_fd_write()
- Change copy_or_generate_uuid() to not generate random values after the terminating char

v2:
- Use "const char *" where possible
- Avoid memset() by assigning value in variable declaration
- Fix goto's with correct cleanup (free, spi_flash_free)
- Change one printf to debug to be less verbose

Daniel, sorry for all these version. I really hope that this is the last version.

Thanks,
Stefan

 board/gardena/smart-gateway-mt7688/board.c | 269 +++++++++++++++++++++
 1 file changed, 269 insertions(+)
board/gardena/smart-gateway-mt7688/board.c +269 -0
index 3a1838e44a..6e11077977 100644
@@ -4,11 +4,44 @@
  */
 
 #include <common.h>
+#include <environment.h>
 #include <led.h>
+#include <net.h>
+#include <spi.h>
+#include <spi_flash.h>
+#include <uuid.h>
+#include <linux/ctype.h>
 #include <linux/io.h>
 
 #define MT76XX_AGPIO_CFG	0x1000003c
 
+#define FACTORY_DATA_OFFS	0xc0000
+#define FACTORY_DATA_SECT_SIZE	0x10000
+#if ((CONFIG_ENV_OFFSET_REDUND + CONFIG_ENV_SIZE_REDUND) > FACTORY_DATA_OFFS)
+#error "U-Boot image with environment too big (overlapping with factory-data)!"
+#endif
+#define FACTORY_DATA_USER_OFFS	0x140
+#define FACTORY_DATA_SIZE	0x1f0
+#define FACTORY_DATA_CRC_LEN	(FACTORY_DATA_SIZE -			\
+				 FACTORY_DATA_USER_OFFS - sizeof(u32))
+
+#define FACTORY_DATA_MAGIC	0xCAFEBABE
+
+struct factory_data_values {
+	u8 pad_1[4];
+	u8 wifi_mac[6];		/* offs: 0x004: binary value */
+	u8 pad_2[30];
+	u8 eth_mac[6];		/* offs: 0x028: binary value */
+	u8 pad_3[FACTORY_DATA_USER_OFFS - 4 - 6 - 30 - 6];
+	/* User values start here at offset 0x140 */
+	u32 crc;
+	u32 magic;
+	u32 version;
+	char ipr_id[UUID_STR_LEN];	/* UUID as string w/o ending \0 */
+	char hqv_id[UUID_STR_LEN];	/* UUID as string w/o ending \0 */
+	char unielec_id[UUID_STR_LEN];	/* UUID as string w/o ending \0 */
+};
+
 int board_early_init_f(void)
 {
 	void __iomem *gpio_mode;
@@ -20,10 +53,246 @@ int board_early_init_f(void)
 	return 0;
 }
 
+static bool prepare_uuid_var(const char *fd_ptr, const char *env_var_name,
+			     char errorchar)
+{
+	char str[UUID_STR_LEN + 1] = { 0 };	/* Enough for UUID stuff */
+	bool env_updated = false;
+	char *env;
+	int i;
+
+	memcpy(str, fd_ptr, UUID_STR_LEN);
+
+	/* Convert non-ascii character to 'X' */
+	for (i = 0; i < UUID_STR_LEN; i++) {
+		if (!(isascii(str[i]) && isprint(str[i])))
+			str[i] = errorchar;
+	}
+
+	env = env_get(env_var_name);
+	if (strcmp(env, str)) {
+		env_set(env_var_name, str);
+		env_updated = true;
+	}
+
+	return env_updated;
+}
+
+static void factory_data_env_config(void)
+{
+	struct factory_data_values *fd;
+	struct spi_flash *sf;
+	int env_updated = 0;
+	char str[UUID_STR_LEN + 1];	/* Enough for UUID stuff */
+	char *env;
+	u8 *buf;
+	u32 crc;
+	int ret;
+	u8 *ptr;
+
+	buf = malloc(FACTORY_DATA_SIZE);
+	if (!buf) {
+		printf("F-Data:Unable to allocate buffer\n");
+		return;
+	}
+
+	/*
+	 * Get values from factory-data area in SPI NOR
+	 */
+	sf = spi_flash_probe(CONFIG_SF_DEFAULT_BUS,
+			     CONFIG_SF_DEFAULT_CS,
+			     CONFIG_SF_DEFAULT_SPEED,
+			     CONFIG_SF_DEFAULT_MODE);
+	if (!sf) {
+		printf("F-Data:Unable to access SPI NOR flash\n");
+		goto err_free;
+	}
+
+	ret = spi_flash_read(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SIZE,
+			     (void *)buf);
+	if (ret) {
+		printf("F-Data:Unable to read factory-data from SPI NOR\n");
+		goto err_spi_flash;
+	}
+
+	fd = (struct factory_data_values *)buf;
+
+	if (fd->magic != FACTORY_DATA_MAGIC)
+		printf("F-Data:Magic value not correct\n");
+
+	crc = crc32(0, (u8 *)&fd->magic, FACTORY_DATA_CRC_LEN);
+	if (crc != fd->crc)
+		printf("F-Data:CRC not correct\n");
+	else
+		printf("F-Data:factory-data version %x detected\n",
+		       fd->version);
+
+	/* Handle wifi_mac env variable */
+	ptr = fd->wifi_mac;
+	sprintf(str, "%pM", ptr);
+	if (!is_valid_ethaddr(ptr))
+		printf("F-Data:Invalid MAC addr: wifi_mac %s\n", str);
+
+	env = env_get("wifiaddr");
+	if (strcmp(env, str)) {
+		env_set("wifiaddr", str);
+		env_updated = 1;
+	}
+
+	/* Handle eth_mac env variable */
+	ptr = fd->eth_mac;
+	sprintf(str, "%pM", ptr);
+	if (!is_valid_ethaddr(ptr))
+		printf("F-Data:Invalid MAC addr: eth_mac %s\n", str);
+
+	env = env_get("ethaddr");
+	if (strcmp(env, str)) {
+		env_set("ethaddr", str);
+		env_updated = 1;
+	}
+
+	/* Handle UUID env variables */
+	env_updated |= prepare_uuid_var(fd->ipr_id, "linuxmoduleid", 'X');
+	env_updated |= prepare_uuid_var(fd->hqv_id, "linuxmodulehqvid", '\0');
+	env_updated |= prepare_uuid_var(fd->unielec_id,
+					"linuxmoduleunielecid", '\0');
+
+	/* Check if the environment was updated and needs to get stored */
+	if (env_updated != 0) {
+		printf("F-Data:Values don't match env values -> saving\n");
+		env_save();
+	} else {
+		debug("F-Data:Values match current env values\n");
+	}
+
+err_spi_flash:
+	spi_flash_free(sf);
+
+err_free:
+	free(buf);
+}
+
 int board_late_init(void)
 {
 	if (IS_ENABLED(CONFIG_LED))
 		led_default_state();
 
+	factory_data_env_config();
+
 	return 0;
 }
+
+static void copy_or_generate_uuid(char *fd_ptr, const char *env_var_name)
+{
+	char str[UUID_STR_LEN + 1] = { 0 };	/* Enough for UUID stuff */
+	char *env;
+
+	/* Don't use the UUID dest place, as the \0 char won't fit */
+	env = env_get(env_var_name);
+	if (env)
+		strncpy(str, env, UUID_STR_LEN);
+	else
+		gen_rand_uuid_str(str, UUID_STR_FORMAT_STD);
+
+	memcpy(fd_ptr, str, UUID_STR_LEN);
+}
+
+/*
+ * Helper function to provide some sane factory-data values for testing
+ * purpose, when these values are not programmed correctly
+ */
+int do_fd_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	struct factory_data_values *fd;
+	struct spi_flash *sf;
+	u8 *buf;
+	int ret = CMD_RET_FAILURE;
+
+	buf = malloc(FACTORY_DATA_SECT_SIZE);
+	if (!buf) {
+		printf("F-Data:Unable to allocate buffer\n");
+		return CMD_RET_FAILURE;
+	}
+
+	sf = spi_flash_probe(CONFIG_SF_DEFAULT_BUS,
+			     CONFIG_SF_DEFAULT_CS,
+			     CONFIG_SF_DEFAULT_SPEED,
+			     CONFIG_SF_DEFAULT_MODE);
+	if (!sf) {
+		printf("F-Data:Unable to access SPI NOR flash\n");
+		goto err_free;
+	}
+
+	/* Generate the factory-data struct */
+
+	/* Fist read complete sector into buffer */
+	ret = spi_flash_read(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SECT_SIZE,
+			     (void *)buf);
+	if (ret) {
+		printf("F-Data:spi_flash_read failed (%d)\n", ret);
+		goto err_spi_flash;
+	}
+
+	fd = (struct factory_data_values *)buf;
+	fd->magic = FACTORY_DATA_MAGIC;
+	fd->version = 0x1;
+
+	/* Use existing MAC and UUID values or generate some random ones */
+	if (!eth_env_get_enetaddr("wifiaddr", fd->wifi_mac)) {
+		net_random_ethaddr(fd->wifi_mac);
+		/* to get a different seed value for the MAC address */
+		mdelay(10);
+	}
+
+	if (!eth_env_get_enetaddr("ethaddr", fd->eth_mac))
+		net_random_ethaddr(fd->eth_mac);
+
+	copy_or_generate_uuid(fd->ipr_id, "linuxmoduleid");
+	copy_or_generate_uuid(fd->hqv_id, "linuxmodulehqvid");
+	copy_or_generate_uuid(fd->unielec_id, "linuxmoduleunielecid");
+
+	printf("New factory-data values:\n");
+	printf("wifiaddr=%pM\n", fd->wifi_mac);
+	printf("ethaddr=%pM\n", fd->eth_mac);
+
+	/*
+	 * We don't have the \0 char at the end, so we need to specify the
+	 * length in the printf format instead
+	 */
+	printf("linuxmoduleid=%." __stringify(UUID_STR_LEN) "s\n", fd->ipr_id);
+	printf("linuxmodulehqvid=%." __stringify(UUID_STR_LEN) "s\n",
+	       fd->hqv_id);
+	printf("linuxmoduleunielecid=%." __stringify(UUID_STR_LEN) "s\n",
+	       fd->unielec_id);
+
+	fd->crc = crc32(0, (u8 *)&fd->magic, FACTORY_DATA_CRC_LEN);
+
+	ret = spi_flash_erase(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SECT_SIZE);
+	if (ret) {
+		printf("F-Data:spi_flash_erase failed (%d)\n", ret);
+		goto err_spi_flash;
+	}
+
+	ret = spi_flash_write(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SECT_SIZE,
+			      buf);
+	if (ret) {
+		printf("F-Data:spi_flash_write failed (%d)\n", ret);
+		goto err_spi_flash;
+	}
+
+	printf("F-Data:factory-data values written to SPI NOR flash\n");
+
+err_spi_flash:
+	spi_flash_free(sf);
+
+err_free:
+	free(buf);
+
+	return ret;
+}
+
+U_BOOT_CMD(
+	fd_write,	1,	0,	do_fd_write,
+	"Write test factory-data values to SPI NOR",
+	"\n"
+);
Signature · 1 line
2.19.2
#9 lore raw

PATCH v4 3/3 mips: mt76xx: gardena-smart-gateway: Add factory data variable handling

Am 30.11.18 um 07:46 schrieb Stefan Roese:

Quoted 24 lines

Some factory data is stored in the SPI NOR and needs to get extracted from there into U-Boot environment variables.

This patch also includes a board-specific command "fd_write" to provide some dummy / default values for this factory-data in the SPI NOR flash. This should only be necessary for testing purposes though.

Cc Daniel Schwierzeck <[email protected]>

---
v4:
- Change end-char for "linuxmoduleunielecid"

v3:
- Remove unnecessary ret = 0 assignment in do_fd_write()
- Change copy_or_generate_uuid() to not generate random values after the terminating char

v2:
- Use "const char *" where possible
- Avoid memset() by assigning value in variable declaration
- Fix goto's with correct cleanup (free, spi_flash_free)
- Change one printf to debug to be less verbose

Quoted 9 lines

Daniel, sorry for all these version. I really hope that this is the last version.

Thanks,
Stefan

 board/gardena/smart-gateway-mt7688/board.c | 269 +++++++++++++++++++++
 1 file changed, 269 insertions(+)

applied to u-boot-mips, thanks.

Signature · 9 lines
- Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20181130/1e918bcf/attachment.sig>
#10 lore raw

PATCH 1/3 mips: mt7628: Change compatible property of the ethernet DT node

In reply to Stefan Roese

Am 28.11.18 um 08:40 schrieb Stefan Roese:

Quoted 9 lines

As the driver has been changed to be more specific, the DT compatible property also needs to be adapted.

Cc Daniel Schwierzeck <[email protected]>
---
 arch/mips/dts/mt7628a.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

applied to u-boot-mips, thanks.

Signature · 9 lines
- Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20181128/ce8cc154/attachment.sig>