[U-Boot] [PATCH v3 0/4] AE350 support SMP boot from flash

From: Rick Chen rick@andestech.com
In current RISC-V SMP flow, AE350 will encounter the the write failure problem since hart_lottery and available_harts_lock was not in ram address but in flash address when booing from flash.
This patch can help to fix the failure problem when AE350 was booting from flash by disabling this two features.
Changes in v3: - Modify CONFIG_XIP descriptions - Use #ifdef CONFIG_OF_PRIOR_STAGE to replace # if CONFIG_IS_ENABLED(OF_PRIOR_STAGE) - Recovery some blank lines - Add CONFIG_SF_DEFAULT_MODE=0x0 in ae350_rv32_xip_defconfig and ae350_rv64_xip_defconfig - #ifdef CONFIG_OF_PRIOR_STAGE shall also surround SREG s1, 0(t0) - Modify CONFIG_SYS_FDT_BASE from 0x000f0000 as 0x800f0000 in ax25-ae350.h
Changes in v2: - Fix some typos - Also surround the declaration of prior_stage_fdt_address in arch/riscv/cpu/cpu.c with OF_PRIOR_STAGE - Use CONFIP_XIP to replace CONFIG_HART_LOTTERY and CONFIG_AVAILABLE_HARTS
Rick Chen (4): riscv: Introduce CONFIG_XIP to support booting from flash riscv: configs: Support AE350 SMP booting from flash flow riscv: prior_stage_fdt_address should only be used when OF_PRIOR_STAGE is enabled riscv: configs: AE350 will use CONFIG_OF_PRIOR_STAGE when booting from ram
arch/riscv/Kconfig | 7 ++++++ arch/riscv/cpu/cpu.c | 4 ++++ arch/riscv/cpu/start.S | 8 +++++++ arch/riscv/include/asm/global_data.h | 2 ++ arch/riscv/lib/asm-offsets.c | 2 ++ arch/riscv/lib/smp.c | 2 ++ board/AndesTech/ax25-ae350/ax25-ae350.c | 4 ---- configs/ae350_rv32_defconfig | 2 +- configs/ae350_rv32_xip_defconfig | 37 ++++++++++++++++++++++++++++++++ configs/ae350_rv64_defconfig | 2 +- configs/ae350_rv64_xip_defconfig | 38 +++++++++++++++++++++++++++++++++ include/configs/ax25-ae350.h | 2 +- 12 files changed, 103 insertions(+), 7 deletions(-) create mode 100644 configs/ae350_rv32_xip_defconfig create mode 100644 configs/ae350_rv64_xip_defconfig

From: Rick Chen rick@andestech.com
When U-Boot boots from flash, during the boot process, hart_lottery and available_harts_lock variable addresses point to flash which is not writable. This causes boot failures on AE350. Introduce a config option CONFIG_XIP to support such configuration.
Signed-off-by: Rick Chen rick@andestech.com Cc: Greentime Hu greentime@andestech.com --- arch/riscv/Kconfig | 7 +++++++ arch/riscv/cpu/cpu.c | 2 ++ arch/riscv/cpu/start.S | 6 ++++++ arch/riscv/include/asm/global_data.h | 2 ++ arch/riscv/lib/asm-offsets.c | 2 ++ arch/riscv/lib/smp.c | 2 ++ 6 files changed, 21 insertions(+)
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index ae8ff7b..362f3cd 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -162,6 +162,13 @@ config SBI_IPI default y if RISCV_SMODE depends on SMP
+config XIP + bool "XIP mode" + help + XIP (eXecute In Place) is a method for executing code directly + from a NOR flash memory without copying the code to ram. + Say yes here if U-Boot boots from flash directly. + config STACK_SIZE_SHIFT int default 13 diff --git a/arch/riscv/cpu/cpu.c b/arch/riscv/cpu/cpu.c index c32de8a..0cfd7d6 100644 --- a/arch/riscv/cpu/cpu.c +++ b/arch/riscv/cpu/cpu.c @@ -16,6 +16,7 @@ * before the bss section is available. */ phys_addr_t prior_stage_fdt_address __attribute__((section(".data"))); +#ifndef CONFIG_XIP u32 hart_lottery __attribute__((section(".data"))) = 0;
/* @@ -23,6 +24,7 @@ u32 hart_lottery __attribute__((section(".data"))) = 0; * finished initialization of global data. */ u32 available_harts_lock = 1; +#endif
static inline bool supports_extension(char ext) { diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S index a4433fb..3402d09 100644 --- a/arch/riscv/cpu/start.S +++ b/arch/riscv/cpu/start.S @@ -98,6 +98,7 @@ call_board_init_f_0: mv sp, a0 #endif
+#ifndef CONFIG_XIP /* * Pick hart to initialize global data and run U-Boot. The other harts * wait for initialization to complete. @@ -106,6 +107,9 @@ call_board_init_f_0: li s2, 1 amoswap.w s2, t1, 0(t0) bnez s2, wait_for_gd_init +#else + bnez tp, secondary_hart_loop +#endif
la t0, prior_stage_fdt_address SREG s1, 0(t0) @@ -115,6 +119,7 @@ call_board_init_f_0: /* save the boot hart id to global_data */ SREG tp, GD_BOOT_HART(gp)
+#ifndef CONFIG_XIP la t0, available_harts_lock fence rw, w amoswap.w zero, zero, 0(t0) @@ -141,6 +146,7 @@ wait_for_gd_init: * secondary_hart_loop. */ bnez s2, secondary_hart_loop +#endif
/* Enable cache */ jal icache_enable diff --git a/arch/riscv/include/asm/global_data.h b/arch/riscv/include/asm/global_data.h index dffcd45..b74bd7e 100644 --- a/arch/riscv/include/asm/global_data.h +++ b/arch/riscv/include/asm/global_data.h @@ -27,7 +27,9 @@ struct arch_global_data { #ifdef CONFIG_SMP struct ipi_data ipi[CONFIG_NR_CPUS]; #endif +#ifndef CONFIG_XIP ulong available_harts; +#endif };
#include <asm-generic/global_data.h> diff --git a/arch/riscv/lib/asm-offsets.c b/arch/riscv/lib/asm-offsets.c index f998402..4fa4fd3 100644 --- a/arch/riscv/lib/asm-offsets.c +++ b/arch/riscv/lib/asm-offsets.c @@ -14,7 +14,9 @@ int main(void) { DEFINE(GD_BOOT_HART, offsetof(gd_t, arch.boot_hart)); +#ifndef CONFIG_XIP DEFINE(GD_AVAILABLE_HARTS, offsetof(gd_t, arch.available_harts)); +#endif
return 0; } diff --git a/arch/riscv/lib/smp.c b/arch/riscv/lib/smp.c index caa292c..cc66f15 100644 --- a/arch/riscv/lib/smp.c +++ b/arch/riscv/lib/smp.c @@ -63,9 +63,11 @@ static int send_ipi_many(struct ipi_data *ipi) continue; }
+#ifndef CONFIG_XIP /* skip if hart is not available */ if (!(gd->arch.available_harts & (1 << reg))) continue; +#endif
gd->arch.ipi[reg].addr = ipi->addr; gd->arch.ipi[reg].arg0 = ipi->arg0;

On Mon, 2019-04-29 at 15:44 +0800, Andes wrote:
From: Rick Chen rick@andestech.com
When U-Boot boots from flash, during the boot process, hart_lottery and available_harts_lock variable addresses point to flash which is not writable. This causes boot failures on AE350. Introduce a config option CONFIG_XIP to support such configuration.
Signed-off-by: Rick Chen rick@andestech.com Cc: Greentime Hu greentime@andestech.com
arch/riscv/Kconfig | 7 +++++++ arch/riscv/cpu/cpu.c | 2 ++ arch/riscv/cpu/start.S | 6 ++++++ arch/riscv/include/asm/global_data.h | 2 ++ arch/riscv/lib/asm-offsets.c | 2 ++ arch/riscv/lib/smp.c | 2 ++ 6 files changed, 21 insertions(+)
Reviewed-by: Lukas Auer lukas.auer@aisec.fraunhofer.de

From: Rick Chen rick@andestech.com
Add two defconfigs to support AE350 SMP booting from flash.
Signed-off-by: Rick Chen rick@andestech.com Cc: Greentime Hu greentime@andestech.com Reviewed-by: Bin Meng bmeng.cn@gmail.com Reviewed-by: Lukas Auer lukas.auer@aisec.fraunhofer.de --- configs/ae350_rv32_xip_defconfig | 37 +++++++++++++++++++++++++++++++++++++ configs/ae350_rv64_xip_defconfig | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 configs/ae350_rv32_xip_defconfig create mode 100644 configs/ae350_rv64_xip_defconfig
diff --git a/configs/ae350_rv32_xip_defconfig b/configs/ae350_rv32_xip_defconfig new file mode 100644 index 0000000..76534f2 --- /dev/null +++ b/configs/ae350_rv32_xip_defconfig @@ -0,0 +1,37 @@ +CONFIG_RISCV=y +CONFIG_SYS_TEXT_BASE=0x80000000 +CONFIG_XIP=y +CONFIG_TARGET_AX25_AE350=y +CONFIG_DISTRO_DEFAULTS=y +CONFIG_NR_DRAM_BANKS=2 +CONFIG_FIT=y +CONFIG_BOOTDELAY=3 +CONFIG_BOARD_EARLY_INIT_F=y +CONFIG_SYS_PROMPT="RISC-V # " +CONFIG_CMD_IMLS=y +CONFIG_CMD_MMC=y +CONFIG_CMD_SF=y +CONFIG_CMD_SF_TEST=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_BOOTP_PREFER_SERVERIP=y +CONFIG_CMD_CACHE=y +CONFIG_OF_BOARD=y +CONFIG_DEFAULT_DEVICE_TREE="ae350_32" +CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_MMC=y +CONFIG_FTSDC010=y +CONFIG_FTSDC010_SDIO=y +CONFIG_MTD_NOR_FLASH=y +CONFIG_FLASH_CFI_DRIVER=y +CONFIG_CFI_FLASH=y +CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y +CONFIG_SYS_FLASH_CFI=y +CONFIG_SPI_FLASH=y +CONFIG_SF_DEFAULT_MODE=0x0 +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_FTMAC100=y +CONFIG_BAUDRATE=38400 +CONFIG_SYS_NS16550=y +CONFIG_SPI=y +CONFIG_ATCSPI200_SPI=y diff --git a/configs/ae350_rv64_xip_defconfig b/configs/ae350_rv64_xip_defconfig new file mode 100644 index 0000000..f7f2925 --- /dev/null +++ b/configs/ae350_rv64_xip_defconfig @@ -0,0 +1,38 @@ +CONFIG_RISCV=y +CONFIG_SYS_TEXT_BASE=0x80000000 +CONFIG_XIP=y +CONFIG_TARGET_AX25_AE350=y +CONFIG_ARCH_RV64I=y +CONFIG_DISTRO_DEFAULTS=y +CONFIG_NR_DRAM_BANKS=2 +CONFIG_FIT=y +CONFIG_BOOTDELAY=3 +CONFIG_BOARD_EARLY_INIT_F=y +CONFIG_SYS_PROMPT="RISC-V # " +CONFIG_CMD_IMLS=y +CONFIG_CMD_MMC=y +CONFIG_CMD_SF=y +CONFIG_CMD_SF_TEST=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_BOOTP_PREFER_SERVERIP=y +CONFIG_CMD_CACHE=y +CONFIG_OF_BOARD=y +CONFIG_DEFAULT_DEVICE_TREE="ae350_64" +CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_MMC=y +CONFIG_FTSDC010=y +CONFIG_FTSDC010_SDIO=y +CONFIG_MTD_NOR_FLASH=y +CONFIG_FLASH_CFI_DRIVER=y +CONFIG_CFI_FLASH=y +CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y +CONFIG_SYS_FLASH_CFI=y +CONFIG_SPI_FLASH=y +CONFIG_SF_DEFAULT_MODE=0x0 +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_FTMAC100=y +CONFIG_BAUDRATE=38400 +CONFIG_SYS_NS16550=y +CONFIG_SPI=y +CONFIG_ATCSPI200_SPI=y

From: Rick Chen rick@andestech.com
This patch will fix prior_stage_fdt_address write failure problem, when AE350 boots from flash.
When AE350 boots from flash, prior_stage_fdt_address will be flash address, we shall avoid it to be written.
Signed-off-by: Rick Chen rick@andestech.com Cc: Greentime Hu greentime@andestech.com --- arch/riscv/cpu/cpu.c | 2 ++ arch/riscv/cpu/start.S | 2 ++ board/AndesTech/ax25-ae350/ax25-ae350.c | 4 ---- include/configs/ax25-ae350.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/riscv/cpu/cpu.c b/arch/riscv/cpu/cpu.c index 0cfd7d6..e9a8b43 100644 --- a/arch/riscv/cpu/cpu.c +++ b/arch/riscv/cpu/cpu.c @@ -15,7 +15,9 @@ * The variables here must be stored in the data section since they are used * before the bss section is available. */ +#ifdef CONFIG_OF_PRIOR_STAGE phys_addr_t prior_stage_fdt_address __attribute__((section(".data"))); +#endif #ifndef CONFIG_XIP u32 hart_lottery __attribute__((section(".data"))) = 0;
diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S index 3402d09..60ac8c6 100644 --- a/arch/riscv/cpu/start.S +++ b/arch/riscv/cpu/start.S @@ -111,8 +111,10 @@ call_board_init_f_0: bnez tp, secondary_hart_loop #endif
+#ifdef CONFIG_OF_PRIOR_STAGE la t0, prior_stage_fdt_address SREG s1, 0(t0) +#endif
jal board_init_f_init_reserve
diff --git a/board/AndesTech/ax25-ae350/ax25-ae350.c b/board/AndesTech/ax25-ae350/ax25-ae350.c index d343453..3d65ce7 100644 --- a/board/AndesTech/ax25-ae350/ax25-ae350.c +++ b/board/AndesTech/ax25-ae350/ax25-ae350.c @@ -67,10 +67,6 @@ ulong board_flash_get_legacy(ulong base, int banknum, flash_info_t *info)
void *board_fdt_blob_setup(void) { - void **ptr = (void *)&prior_stage_fdt_address; - if (fdt_magic(*ptr) == FDT_MAGIC) - return (void *)*ptr; - return (void *)CONFIG_SYS_FDT_BASE; }
diff --git a/include/configs/ax25-ae350.h b/include/configs/ax25-ae350.h index 395f3a4..a4037f3 100644 --- a/include/configs/ax25-ae350.h +++ b/include/configs/ax25-ae350.h @@ -40,7 +40,7 @@ #define CONFIG_SYS_MALLOC_LEN (512 << 10)
/* DT blob (fdt) address */ -#define CONFIG_SYS_FDT_BASE 0x000f0000 +#define CONFIG_SYS_FDT_BASE 0x800f0000
/* * Physical Memory Map

Hi Rick,
On Mon, 2019-04-29 at 15:44 +0800, Andes wrote:
From: Rick Chen rick@andestech.com
This patch will fix prior_stage_fdt_address write failure problem, when AE350 boots from flash.
When AE350 boots from flash, prior_stage_fdt_address will be flash address, we shall avoid it to be written.
Signed-off-by: Rick Chen rick@andestech.com Cc: Greentime Hu greentime@andestech.com
arch/riscv/cpu/cpu.c | 2 ++ arch/riscv/cpu/start.S | 2 ++ board/AndesTech/ax25-ae350/ax25-ae350.c | 4 ---- include/configs/ax25-ae350.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/riscv/cpu/cpu.c b/arch/riscv/cpu/cpu.c index 0cfd7d6..e9a8b43 100644 --- a/arch/riscv/cpu/cpu.c +++ b/arch/riscv/cpu/cpu.c @@ -15,7 +15,9 @@
- The variables here must be stored in the data section since they are used
- before the bss section is available.
*/ +#ifdef CONFIG_OF_PRIOR_STAGE phys_addr_t prior_stage_fdt_address __attribute__((section(".data"))); +#endif #ifndef CONFIG_XIP u32 hart_lottery __attribute__((section(".data"))) = 0;
diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S index 3402d09..60ac8c6 100644 --- a/arch/riscv/cpu/start.S +++ b/arch/riscv/cpu/start.S @@ -111,8 +111,10 @@ call_board_init_f_0: bnez tp, secondary_hart_loop #endif
+#ifdef CONFIG_OF_PRIOR_STAGE la t0, prior_stage_fdt_address SREG s1, 0(t0) +#endif
jal board_init_f_init_reserve
diff --git a/board/AndesTech/ax25-ae350/ax25-ae350.c b/board/AndesTech/ax25-ae350/ax25-ae350.c index d343453..3d65ce7 100644 --- a/board/AndesTech/ax25-ae350/ax25-ae350.c +++ b/board/AndesTech/ax25-ae350/ax25-ae350.c @@ -67,10 +67,6 @@ ulong board_flash_get_legacy(ulong base, int banknum, flash_info_t *info)
void *board_fdt_blob_setup(void) {
- void **ptr = (void *)&prior_stage_fdt_address;
- if (fdt_magic(*ptr) == FDT_MAGIC)
return (void *)*ptr;
Please move this change and the following into a separate patch.
You may also try to use CONFIG_OF_SEPARATE instead of CONFIG_OF_BOARD. As far as I know, this is the recommended configuration and with this change, I don't think CONFIG_OF_BOARD is needed anymore.
Thanks, Lukas
return (void *)CONFIG_SYS_FDT_BASE; }
diff --git a/include/configs/ax25-ae350.h b/include/configs/ax25-ae350.h index 395f3a4..a4037f3 100644 --- a/include/configs/ax25-ae350.h +++ b/include/configs/ax25-ae350.h @@ -40,7 +40,7 @@ #define CONFIG_SYS_MALLOC_LEN (512 << 10)
/* DT blob (fdt) address */ -#define CONFIG_SYS_FDT_BASE 0x000f0000 +#define CONFIG_SYS_FDT_BASE 0x800f0000
/*
- Physical Memory Map

Hi lukas
Auer, Lukas lukas.auer@aisec.fraunhofer.de 於 2019年4月29日 週一 下午7:55寫道:
Hi Rick,
On Mon, 2019-04-29 at 15:44 +0800, Andes wrote:
From: Rick Chen rick@andestech.com
This patch will fix prior_stage_fdt_address write failure problem, when AE350 boots from flash.
When AE350 boots from flash, prior_stage_fdt_address will be flash address, we shall avoid it to be written.
Signed-off-by: Rick Chen rick@andestech.com Cc: Greentime Hu greentime@andestech.com
arch/riscv/cpu/cpu.c | 2 ++ arch/riscv/cpu/start.S | 2 ++ board/AndesTech/ax25-ae350/ax25-ae350.c | 4 ---- include/configs/ax25-ae350.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/riscv/cpu/cpu.c b/arch/riscv/cpu/cpu.c index 0cfd7d6..e9a8b43 100644 --- a/arch/riscv/cpu/cpu.c +++ b/arch/riscv/cpu/cpu.c @@ -15,7 +15,9 @@
- The variables here must be stored in the data section since they are used
- before the bss section is available.
*/ +#ifdef CONFIG_OF_PRIOR_STAGE phys_addr_t prior_stage_fdt_address __attribute__((section(".data"))); +#endif #ifndef CONFIG_XIP u32 hart_lottery __attribute__((section(".data"))) = 0;
diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S index 3402d09..60ac8c6 100644 --- a/arch/riscv/cpu/start.S +++ b/arch/riscv/cpu/start.S @@ -111,8 +111,10 @@ call_board_init_f_0: bnez tp, secondary_hart_loop #endif
+#ifdef CONFIG_OF_PRIOR_STAGE la t0, prior_stage_fdt_address SREG s1, 0(t0) +#endif
jal board_init_f_init_reserve
diff --git a/board/AndesTech/ax25-ae350/ax25-ae350.c b/board/AndesTech/ax25-ae350/ax25-ae350.c index d343453..3d65ce7 100644 --- a/board/AndesTech/ax25-ae350/ax25-ae350.c +++ b/board/AndesTech/ax25-ae350/ax25-ae350.c @@ -67,10 +67,6 @@ ulong board_flash_get_legacy(ulong base, int banknum, flash_info_t *info)
void *board_fdt_blob_setup(void) {
void **ptr = (void *)&prior_stage_fdt_address;
if (fdt_magic(*ptr) == FDT_MAGIC)
return (void *)*ptr;
Please move this change and the following into a separate patch.
You may also try to use CONFIG_OF_SEPARATE instead of CONFIG_OF_BOARD. As far as I know, this is the recommended configuration and with this change, I don't think CONFIG_OF_BOARD is needed anymore.
OK. I will move it into a separate patch and use CONFIG_OF_SEPARATE.
Thanks Rick
Thanks, Lukas
return (void *)CONFIG_SYS_FDT_BASE;
}
diff --git a/include/configs/ax25-ae350.h b/include/configs/ax25-ae350.h index 395f3a4..a4037f3 100644 --- a/include/configs/ax25-ae350.h +++ b/include/configs/ax25-ae350.h @@ -40,7 +40,7 @@ #define CONFIG_SYS_MALLOC_LEN (512 << 10)
/* DT blob (fdt) address */ -#define CONFIG_SYS_FDT_BASE 0x000f0000 +#define CONFIG_SYS_FDT_BASE 0x800f0000
/*
- Physical Memory Map

From: Rick Chen rick@andestech.com
When AE350 boots from ram, use CONFIG_OF_PRIOR_STAGE instead of CONFIG_OF_BOARD.
Signed-off-by: Rick Chen rick@andestech.com Cc: Greentime Hu greentime@andestech.com Reviewed-by: Bin Meng bmeng.cn@gmail.com Reviewed-by: Lukas Auer lukas.auer@aisec.fraunhofer.de --- configs/ae350_rv32_defconfig | 2 +- configs/ae350_rv64_defconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/configs/ae350_rv32_defconfig b/configs/ae350_rv32_defconfig index f029455..71d2716 100644 --- a/configs/ae350_rv32_defconfig +++ b/configs/ae350_rv32_defconfig @@ -14,7 +14,7 @@ CONFIG_CMD_SF_TEST=y # CONFIG_CMD_SETEXPR is not set CONFIG_BOOTP_PREFER_SERVERIP=y CONFIG_CMD_CACHE=y -CONFIG_OF_BOARD=y +CONFIG_OF_PRIOR_STAGE=y CONFIG_DEFAULT_DEVICE_TREE="ae350_32" CONFIG_ENV_IS_IN_SPI_FLASH=y CONFIG_NET_RANDOM_ETHADDR=y diff --git a/configs/ae350_rv64_defconfig b/configs/ae350_rv64_defconfig index 98635a2..9bf1737 100644 --- a/configs/ae350_rv64_defconfig +++ b/configs/ae350_rv64_defconfig @@ -15,7 +15,7 @@ CONFIG_CMD_SF_TEST=y # CONFIG_CMD_SETEXPR is not set CONFIG_BOOTP_PREFER_SERVERIP=y CONFIG_CMD_CACHE=y -CONFIG_OF_BOARD=y +CONFIG_OF_PRIOR_STAGE=y CONFIG_DEFAULT_DEVICE_TREE="ae350_64" CONFIG_ENV_IS_IN_SPI_FLASH=y CONFIG_NET_RANDOM_ETHADDR=y
participants (3)
-
Andes
-
Auer, Lukas
-
Rick Chen