Re: [PATCH v3 07/12] net-lwip: add wget command

2024-06-07 Thread Jerome Forissier



On 6/6/24 17:41, Ilias Apalodimas wrote:
> Hi Jerome,
> 
> Can we split this in 2 patches instead?
> A preparatory one, with split the net-common etc and one that adds wget?

Sure, done in v4.

> Thanks
> /Ilias
> 
> On Thu, 6 Jun 2024 at 16:37, Jerome Forissier
>  wrote:
>>
>> Add support for the wget command with NET_LWIP.
>>
>> About the small change in cmd/efidebug.c: when the wget command based
>> on the lwIP stack is used the wget command has a built-in URL
>> validation function since it needs to parse it anyways (in parse_url()).
>> Therefore wget_validate_uri() doesn't exist. So, guard the call in
>> efidebug.c with CONFIG_CMD_WGET.
>>
>> Based on code initially developed by Maxim U.
>>
>> Signed-off-by: Jerome Forissier 
>> Co-developed-by: Maxim Uvarov 
>> Cc: Maxim Uvarov 
>> ---
>>  cmd/Kconfig|   7 ++
>>  cmd/Makefile   |   5 +-
>>  cmd/efidebug.c |   8 +-
>>  cmd/net-common.c   | 115 +
>>  cmd/net-lwip.c |  12 +++
>>  cmd/net.c  | 115 -
>>  include/net-lwip.h |  51 +
>>  net-lwip/Makefile  |   1 +
>>  net-lwip/wget.c| 180 +
>>  9 files changed, 375 insertions(+), 119 deletions(-)
>>  create mode 100644 cmd/net-common.c
>>  create mode 100644 net-lwip/wget.c

Thanks,
-- 
Jerome


Re: [PATCH v3 00/12] Introduce the lwIP network stack

2024-06-07 Thread Jerome Forissier



On 6/6/24 18:56, Tom Rini wrote:
> On Thu, Jun 06, 2024 at 03:35:55PM +0200, Jerome Forissier wrote:
> 
>> This is a rework of a patch series by Maxim Uvarov: "net/lwip: add lwip
>> library for the network stack" [1]. The goal is to introduce the lwIP TCP/IP
>> stack [2] [3] as an alternative to the current implementation in net/,
>> selectable with Kconfig, and ultimately keep only lwIP if possible. Some
>> reasons for doing so are:
>> - Make the support of HTTPS in the wget command easier. Javier T. (CC'd)
>> has some additional lwIP and Mbed TLS patches to do so. With that it
>> becomes possible to fetch and launch a distro installer such as Debian
>> etc. using a secure, authenticated connection directly from the U-Boot
>> shell. Several use cases:
>>   * Authentication: prevent MITM attack (third party replacing the
>> binary with a different one)
>>   * Confidentiality: prevent third parties from grabbing a copy of the
>> image as it is being downloaded
>>   * Allow connection to servers that do not support plain HTTP anymore
>> (this is becoming more and more common on the Internet these days)
>> - Possibly benefit from additional features implemented in lwIP
>> - Less code to maintain in U-Boot
> 
> Alright, on Pi 3, I think we have more "output changed, test fails"
> problems:
> == FAILURES 
> ===
> _ test_efi_fit_launch 
> _
> test/py/tests/test_efi_fit.py:452: in test_efi_fit_launch
> launch_efi(False, False)
> test/py/tests/test_efi_fit.py:394: in launch_efi
> net_set_up = net_dhcp()
> test/py/tests/test_efi_fit.py:178: in net_dhcp
> assert 'DHCP client bound to address ' in output
> E   AssertionError: assert 'DHCP client bound to address ' in 'Waiting for 
> Ethernet connection... done.\r\neth0: smsc95xx_eth b8:27:eb:fc:64:a6 active'
>  Captured stdout call 
> -
> U-Boot> usb start
> U-Boot> U-Boot> setenv autoload no
> U-Boot> U-Boot> dhcp
> Waiting for Ethernet connection... done.
> eth0: smsc95xx_eth b8:27:eb:fc:64:a6 active
> U-Boot>
> === short test summary info 
> ===
> 
> I'm going to skip that set of tests and see how far we get but I suspect
> it'll keep failing on DHCP output being different.

As discussed offline with Ilias it might be a timeout issue, although 2000 ms
for DHCP_TIMEOUT_MS seems a large value to me, it might not be enough in your
environment. Can you please try to increase it? NET effectively has a timeout
of 28 seconds if we take the retries into account.

Thanks,
-- 
Jerome


Re: [PATCH v3 05/12] net-lwip: add ping command

2024-06-07 Thread Jerome Forissier



On 6/6/24 19:45, Ilias Apalodimas wrote:
> On Thu, 6 Jun 2024 at 20:02, Ilias Apalodimas
>  wrote:
>>
>> On Thu, 6 Jun 2024 at 19:53, Ilias Apalodimas
>>  wrote:
>>>
>>> [...]
>>>
 +static int ping_raw_init(void *recv_arg)
 +{
 +   ping_pcb = raw_new(IP_PROTO_ICMP);
 +   if (!ping_pcb)
 +   return -ENOMEM;
 +
 +   raw_recv(ping_pcb, ping_recv, recv_arg);
 +   raw_bind(ping_pcb, IP_ADDR_ANY);
 +
 +   return 0;
 +}
 +
 +static void ping_raw_stop(void)
 +{
 +   if (ping_pcb != NULL) {
>>>
>>> nits, but we usually do if (!ping_pcb) for NULL pointers and variables
>>> that have a value of 0.
>>> Please change it in other files as well
>>>
>>>
 +   raw_remove(ping_pcb);
 +   ping_pcb = NULL;
 +   }
 +}
 +
 +static void ping_prepare_echo(struct icmp_echo_hdr *iecho)
 +{
 +   ICMPH_TYPE_SET(iecho, ICMP_ECHO);
 +   ICMPH_CODE_SET(iecho, 0);
 +   iecho->chksum = 0;
 +   iecho->id = PING_ID;
 +   iecho->seqno = lwip_htons(++ping_seq_num);
 +
 +   iecho->chksum = inet_chksum(iecho, sizeof(*iecho));
 +}
 +
 +static void ping_send_icmp(struct raw_pcb *raw, const ip_addr_t *addr)
 +{
 +   struct pbuf *p;
 +   struct icmp_echo_hdr *iecho;
 +   size_t ping_size = sizeof(struct icmp_echo_hdr);
 +
 +   p = pbuf_alloc(PBUF_IP, (u16_t)ping_size, PBUF_RAM);
 +   if (!p)
 +   return;
 +
 +   if ((p->len == p->tot_len) && (p->next == NULL)) {
>>>
>>> && !p->next
>>>
 +   iecho = (struct icmp_echo_hdr *)p->payload;
 +   ping_prepare_echo(iecho);
 +   raw_sendto(raw, p, addr);
 +   }
 +
 +   pbuf_free(p);
 +}
 +
 +static void ping_send(void *arg)
 +{
 +   struct raw_pcb *pcb = (struct raw_pcb *)arg;
 +
 +   ping_send_icmp(pcb, ping_target);
 +   sys_timeout(PING_DELAY_MS, ping_send, ping_pcb);
 +}
 +
 +static int ping_loop(const ip_addr_t* addr)
 +{
 +   bool alive;
 +   ulong start;
 +   int ret;
 +
 +   printf("Using %s device\n", eth_get_name());
 +
 +   ret = ping_raw_init();
 +   if (ret < 0)
 +   return ret;
 +   ping_target = addr;
 +   ping_seq_num = 0;
 +
 +   start = get_timer(0);
 +   ping_send(ping_pcb);
 +
 +   do {
 +   eth_rx();
 +   if (alive)
 +   break;
 +   sys_check_timeouts();
 +   if (ctrlc()) {
 +   printf("\nAbort\n");
 +   break;
 +   }
 +   } while (get_timer(start) < PING_TIMEOUT_MS);
>>>
>>> I am a bit confused about what happens here.
>>> ping_send() will send the packet, but it will also schedule itself to
>>> rerun after 1 ms and send another ping?
>>>
 +
 +   sys_untimeout(ping_send, ping_pcb);
>>>
>>> So we need the sys_untimeout() because we queued 2 pings? Because
>>> sys_timeout() is supposed to be an one shot.
>>
>> Ah nvm, I misread that. We always reschedule ping_send_icmp(), that's
>> why we have to delete it here
> 
> Ok so looking at it a bit more. Why do we have to schedule contunuous pings?
> We just have to send one packet and wait for the response no?

We could send just one packet as NET does, but if there's packet loss then
the ping command will report the host is unreachable. I think it is safer
to allow for a few retries for better reliability. The code for one packet
would be marginally simpler anyways. What I can do however is use a send
counter rather than a timeout.

Thanks,
-- 
Jerome



[PATCH v3 03/12] net-lwip: add DHCP support and dhcp commmand

2024-06-06 Thread Jerome Forissier
Add what it takes to enable NETDEVICES with NET_LWIP and enable DHCP as
well as the dhcp command.
- net-lwip/net-lwip.c is mostly empty for now. It will provide functions
similar to net/net.c except based on the lwIP stack
- include/net-lwip.h is a replacement for include/net.h which is unused
when NET_LWIP is enabled. Declarations from the latter will be
transferred to the former as needed when new network commands are ported
on top of lwIP.
- CMD_TFTPBOOT is selected by BOOTMETH_EFI due to this code having
an implicit dependency on do_tftpb().

Signed-off-by: Jerome Forissier 
---
 Makefile|   1 +
 boot/Kconfig|   3 +-
 cmd/Kconfig |  26 +
 cmd/Makefile|   4 +
 cmd/net-lwip.c  |  13 +++
 common/board_r.c|   4 +-
 drivers/net/Kconfig |   2 +-
 include/net-lwip.h  |  85 +++
 include/net.h   |   2 +-
 net-lwip/Makefile   |  15 +++
 net-lwip/dhcp.c | 105 +++
 net-lwip/eth_internal.h |  35 +++
 net-lwip/net-lwip.c | 224 
 net-lwip/tftp.c |  11 ++
 14 files changed, 525 insertions(+), 5 deletions(-)
 create mode 100644 cmd/net-lwip.c
 create mode 100644 include/net-lwip.h
 create mode 100644 net-lwip/Makefile
 create mode 100644 net-lwip/dhcp.c
 create mode 100644 net-lwip/eth_internal.h
 create mode 100644 net-lwip/net-lwip.c
 create mode 100644 net-lwip/tftp.c

diff --git a/Makefile b/Makefile
index ceb99a2698e..d3c9e6775dc 100644
--- a/Makefile
+++ b/Makefile
@@ -860,6 +860,7 @@ libs-y += env/
 libs-y += lib/
 libs-y += fs/
 libs-$(CONFIG_NET) += net/
+libs-$(CONFIG_NET_LWIP) += net-lwip/
 libs-y += disk/
 libs-y += drivers/
 libs-$(CONFIG_SYS_FSL_DDR) += drivers/ddr/fsl/
diff --git a/boot/Kconfig b/boot/Kconfig
index 6f3096c15a6..004e69dd92a 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -378,7 +378,7 @@ config BOOT_DEFAULTS_CMDS
select CMD_FAT
select CMD_FS_GENERIC
select CMD_PART if PARTITIONS
-   select CMD_DHCP if CMD_NET
+   select CMD_DHCP if CMD_NET || CMD_NET_LWIP
select CMD_PING if CMD_NET
select CMD_PXE if CMD_NET
select CMD_BOOTI if ARM64
@@ -540,6 +540,7 @@ config BOOTMETH_EXTLINUX_PXE
 config BOOTMETH_EFILOADER
bool "Bootdev support for EFI boot"
depends on EFI_BINARY_EXEC
+   select CMD_TFTPBOOT if CMD_NET_LWIP
default y
help
  Enables support for EFI boot using bootdevs. This makes the
diff --git a/cmd/Kconfig b/cmd/Kconfig
index b026439c773..1bfa528e945 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2084,6 +2084,32 @@ config CMD_WOL
 
 endif
 
+if NET_LWIP
+
+menuconfig CMD_NET_LWIP
+   bool "Network commands (lwIP)"
+   default y
+
+if CMD_NET_LWIP
+
+config CMD_DHCP
+   bool "dhcp"
+   select PROT_DHCP_LWIP
+   help
+ Boot image via network using DHCP/TFTP protocol
+
+config CMD_TFTPBOOT
+   bool "tftp"
+   select PROT_UDP_LWIP
+   default n
+   help
+ tftpboot - load file via network using TFTP protocol
+ Currently a placeholder (not implemented)
+
+endif
+
+endif
+
 menu "Misc commands"
 
 config CMD_2048
diff --git a/cmd/Makefile b/cmd/Makefile
index 87133cc27a8..535b6838ca5 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -128,6 +128,10 @@ endif
 obj-$(CONFIG_CMD_MUX) += mux.o
 obj-$(CONFIG_CMD_NAND) += nand.o
 obj-$(CONFIG_CMD_NET) += net.o
+obj-$(CONFIG_CMD_NET_LWIP) += net-lwip.o
+ifdef CONFIG_CMD_NET_LWIP
+CFLAGS_net-lwip.o := -I$(srctree)/lib/lwip/lwip/src/include 
-I$(srctree)/lib/lwip/u-boot
+endif
 obj-$(CONFIG_ENV_SUPPORT) += nvedit.o
 obj-$(CONFIG_CMD_NVEDIT_EFI) += nvedit_efi.o
 obj-$(CONFIG_CMD_ONENAND) += onenand.o
diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
new file mode 100644
index 000..966d7226eda
--- /dev/null
+++ b/cmd/net-lwip.c
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2024 Linaro Ltd. */
+
+#include 
+#include 
+
+#if defined(CONFIG_CMD_DHCP)
+U_BOOT_CMD(
+dhcp,   3,  1,  do_dhcp,
+"boot image via network using DHCP/TFTP protocol",
+"[loadAddress] [[hostIPaddr:]bootfilename]"
+);
+#endif
diff --git a/common/board_r.c b/common/board_r.c
index da0b80f24ff..6548eb8fdd5 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -472,7 +472,7 @@ static int initr_status_led(void)
 }
 #endif
 
-#ifdef CONFIG_CMD_NET
+#if defined(CONFIG_CMD_NET) || defined(CONFIG_CMD_NET_LWIP)
 static int initr_net(void)
 {
puts("Net:   ");
@@ -727,7 +727,7 @@ static init_fnc_t init_sequence_r[] = {
 #ifdef CONFIG_PCI_ENDPOINT
pci_ep_init,
 #endif
-#ifdef CONFIG_CMD_NET
+#if defined(CONFIG_CMD_NET) || defined(CONFIG_CMD_NET_LWIP)
INIT_FUNC_WATCHDOG_RESET
initr_net,
 #endif
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index b2d7b499766..4ba09c9d6f8 100

[PATCH v3 01/12] net: introduce alternative implementation as net-lwip/

2024-06-06 Thread Jerome Forissier
Prepare the introduction of the lwIP (lightweight IP) TCP/IP stack by
adding a new net-lwip/ directory and the NET_LWIP symbol. Network
support is either NO_NET, NET (legacy stack) or NET_LWIP. Subsequent
commits will introduce the lwIP code, re-work the NETDEVICE integration
and port some of the NET commands and features to lwIP.

SPL_NET cannot be enabled when NET_LWIP=y. SPL_NET pulls some symbols
that are part of NET (such as arp_init(), arp_timeout_check(),
arp_receive(), net_arp_wait_packet_ip()). lwIP support in SPL may be
added later.

Similarly, DFU_TFTP is not compatible with NET_LWIP because it depends
on net_loop(), tftp_timeout_ms, tftp_timeout_count_max. Let's add a
dependency of DFU_OVER_TFTP on !NET_LWIP for now.

Signed-off-by: Jerome Forissier 
---
 Kconfig| 40 ++
 Makefile   |  2 +-
 common/Kconfig |  2 +-
 common/spl/Kconfig |  1 +
 drivers/dfu/Kconfig|  2 +-
 drivers/fastboot/Kconfig   |  4 ++--
 drivers/net/phy/Kconfig|  2 +-
 drivers/usb/gadget/Kconfig |  2 +-
 net-lwip/Kconfig   | 37 +++
 net/Kconfig| 14 -
 10 files changed, 85 insertions(+), 21 deletions(-)
 create mode 100644 net-lwip/Kconfig

diff --git a/Kconfig b/Kconfig
index 82df59f176e..b7304bd37c5 100644
--- a/Kconfig
+++ b/Kconfig
@@ -745,7 +745,47 @@ source "dts/Kconfig"
 
 source "env/Kconfig"
 
+choice
+   prompt "Networking stack"
+   default NET
+
+config NO_NET
+   bool "No networking support"
+
+config NET
+   bool "Legacy U-Boot networking stack"
+   imply NETDEVICES
+
+config NET_LWIP
+   bool "Use lwIP for networking stack"
+   imply NETDEVICES
+   help
+ Include networking support based on the lwIP (lightweight IP)
+ TCP/IP stack (https://nongnu.org/lwip). This is a replacement for
+ the default U-Boot network stack and applications located in net/
+ and enabled via CONFIG_NET as well as other pieces of code that
+ depend on CONFIG_NET (such as cmd/net.c enabled via CONFIG_CMD_NET).
+ Therefore the two symbols CONFIG_NET and CONFIG_NET_LWIP are mutually
+ exclusive.
+
+endchoice
+
+if NET
 source "net/Kconfig"
+endif
+
+if NET_LWIP
+source "net-lwip/Kconfig"
+endif
+
+config SYS_RX_ETH_BUFFER
+   int "Number of receive packet buffers"
+   default 4
+   help
+ Defines the number of Ethernet receive buffers. On some Ethernet
+ controllers it is recommended to set this value to 8 or even higher,
+ since all buffers can be full shortly after enabling the interface on
+ high Ethernet traffic.
 
 source "drivers/Kconfig"
 
diff --git a/Makefile b/Makefile
index f8206b2e30a..ceb99a2698e 100644
--- a/Makefile
+++ b/Makefile
@@ -859,7 +859,7 @@ libs-$(CONFIG_OF_EMBED) += dts/
 libs-y += env/
 libs-y += lib/
 libs-y += fs/
-libs-y += net/
+libs-$(CONFIG_NET) += net/
 libs-y += disk/
 libs-y += drivers/
 libs-$(CONFIG_SYS_FSL_DDR) += drivers/ddr/fsl/
diff --git a/common/Kconfig b/common/Kconfig
index 5e3070e9253..807b726384d 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -424,7 +424,7 @@ config LOGF_FUNC_PAD
 
 config LOG_SYSLOG
bool "Log output to syslog server"
-   depends on NET
+   depends on NET || NET_LWIP
help
  Enables a log driver which broadcasts log records via UDP port 514
  to syslog servers.
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 6405374bcc1..f67f0a859db 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -1055,6 +1055,7 @@ config SPL_DM_SPI_FLASH
 
 config SPL_NET
bool "Support networking"
+   depends on !NET_LWIP
help
  Enable support for network devices (such as Ethernet) in SPL.
  This permits SPL to load U-Boot over a network link rather than
diff --git a/drivers/dfu/Kconfig b/drivers/dfu/Kconfig
index 0360d9da142..c6bce82eb10 100644
--- a/drivers/dfu/Kconfig
+++ b/drivers/dfu/Kconfig
@@ -11,7 +11,7 @@ config DFU_OVER_USB
 
 config DFU_OVER_TFTP
bool
-   depends on NET
+   depends on NET && !NET_LWIP
 
 if DFU
 config DFU_WRITE_ALT
diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig
index 70207573de2..05e988166fb 100644
--- a/drivers/fastboot/Kconfig
+++ b/drivers/fastboot/Kconfig
@@ -27,7 +27,7 @@ config USB_FUNCTION_FASTBOOT
  This enables the USB part of the fastboot gadget.
 
 config UDP_FUNCTION_FASTBOOT
-   depends on NET
+   depends on NET || NET_LWIP
select FASTBOOT
bool "Enable fastboot protocol over UDP"
help
@@ -41,7 +41,7 @@ config UDP_FUNCTION_FASTBOOT_PORT
  The fastboot protocol requires a UDP port number.
 
 config TCP_FUNCTION_FASTBOOT
-   depends on NET
+   dep

Re: [PATCH v3 06/12] net-lwip: add dns command

2024-06-06 Thread Jerome Forissier



On 6/6/24 18:02, Ilias Apalodimas wrote:
> [...]
> 
 +
 +   if (!ipaddr) {
 +   printf("DNS: host not found\n");
 +   host_ipaddr.addr = 0;
 +   return;
 +   }
 +
 +   if (var)
 +   env_set(var, ipstr);
>>>
>>> Do we need this? Won't this set  == ipaddr?
>>
>> No, the syntax of the dns command is: 'dns hostname [env_var]' so one can
>> pretty much give any variable name to receive the IP address.
>>
>>> If we do not need it repurpose the void *arg and get rid of the global 
>>> 'done'
>>
>> I could probably use a struct to get rid of the globals. Let me see what I 
>> can do.
> 
> Yea just pass a struct with char* and a bool * and you should be fine

Done in v4.

Thanks,
-- 
Jerome


Re: [PATCH v3 06/12] net-lwip: add dns command

2024-06-06 Thread Jerome Forissier



On 6/6/24 17:46, Ilias Apalodimas wrote:
>> @@ -7,6 +7,7 @@ obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth_common.o
>>  obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth-uclass.o
>>  obj-$(CONFIG_$(SPL_)DM_ETH) += net-lwip.o
>>  obj-$(CONFIG_CMD_DHCP) += dhcp.o
>> +obj-$(CONFIG_CMD_DNS) += dns.o
>>  obj-$(CONFIG_CMD_PING) += ping.o
>>  obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
>>
>> diff --git a/net-lwip/dns.c b/net-lwip/dns.c
>> new file mode 100644
>> index 000..24a5149343a
>> --- /dev/null
>> +++ b/net-lwip/dns.c
>> @@ -0,0 +1,107 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/* Copyright (C) 2024 Linaro Ltd. */
>> +
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +
>> +#define DNS_RESEND_MS 1000
>> +#define DNS_TIMEOUT_MS 1
>> +
>> +static ulong start;
>> +static ip_addr_t host_ipaddr;
>> +static bool done;
>> +
>> +static void do_dns_tmr(void *arg)
>> +{
>> +   dns_tmr();
>> +}
>> +
>> +static void dns_cb(const char *name, const ip_addr_t *ipaddr, void *arg)
>> +{
>> +   const char *var = arg;
>> +   char *ipstr = ip4addr_ntoa(ipaddr);
>> +
>> +   done = true;
>> +
>> +   if (!ipaddr) {
>> +   printf("DNS: host not found\n");
>> +   host_ipaddr.addr = 0;
>> +   return;
>> +   }
>> +
>> +   if (var)
>> +   env_set(var, ipstr);
> 
> Do we need this? Won't this set  == ipaddr?

No, the syntax of the dns command is: 'dns hostname [env_var]' so one can
pretty much give any variable name to receive the IP address.

> If we do not need it repurpose the void *arg and get rid of the global 'done'

I could probably use a struct to get rid of the globals. Let me see what I can 
do.
 
>> +
>> +   printf("%s\n", ipstr);
>> +}
>> +
>> +int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
>> +{
>> +   bool has_server = false;
>> +   ip_addr_t ipaddr;
>> +   ip_addr_t ns;
>> +   char *nsenv;
>> +   char *name;
>> +   char *var;
>> +   int ret;
> 
> [...]
> 
> Thanks
> /Ilias


[PATCH v3 12/12] CI: add qemu_arm64_lwip to the test matrix

2024-06-06 Thread Jerome Forissier
Build and run qemu_arm64_lwip_defconfig in CI. This tests the lightweight
IP (lwIP) implementation of the dhcp, tftpboot and ping commands.

Signed-off-by: Jerome Forissier 
---
 .azure-pipelines.yml | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml
index 27f69583c65..4da1bb12fab 100644
--- a/.azure-pipelines.yml
+++ b/.azure-pipelines.yml
@@ -199,6 +199,10 @@ stages:
   cd \${WORK_DIR}
   git config --global --add safe.directory \${WORK_DIR}
   git clone --depth=1 https://source.denx.de/u-boot/u-boot-test-hooks 
/tmp/uboot-test-hooks
+  # qemu_arm64_lwip_defconfig is the same as qemu_arm64 but with 
NET_LWIP enabled.
+  # The test config and the boardenv file from qemu_arm64 can be 
re-used so create symlinks
+  ln -s conf.qemu_arm64_na 
/tmp/uboot-test-hooks/bin/travis-ci/conf.qemu_arm64_lwip_na
+  ln -s u_boot_boardenv_qemu_arm64_na.py 
/tmp/uboot-test-hooks/py/travis-ci/u_boot_boardenv_qemu_arm64_lwip_na.py
   ln -s travis-ci /tmp/uboot-test-hooks/bin/\`hostname\`
   ln -s travis-ci /tmp/uboot-test-hooks/py/\`hostname\`
   grub-mkimage --prefix=\"\" -o ~/grub_x86.efi -O i386-efi normal echo 
lsefimmap lsefi lsefisystab efinet tftp minicmd
@@ -371,6 +375,9 @@ stages:
 qemu_arm64:
   TEST_PY_BD: "qemu_arm64"
   TEST_PY_TEST_SPEC: "not sleep"
+qemu_arm64_lwip:
+  TEST_PY_BD: "qemu_arm64_lwip"
+  TEST_PY_TEST_SPEC: "test_net_dhcp or test_net_ping or 
test_net_tftpboot"
 qemu_m68k:
   TEST_PY_BD: "M5208EVBE"
   TEST_PY_ID: "--id qemu"
-- 
2.40.1



[PATCH v3 11/12] MAINTAINERS: net-lwip: add myself as a maintainer

2024-06-06 Thread Jerome Forissier
Add myself as a maintainer for the lwIP network stack integration code
and network commands. The library code itself (i.e., most files under
lib/lwip/ except README, Makefile and integration files in u-boot) is
unmodified from upstream and therefore does not need a maintainer.

Signed-off-by: Jerome Forissier 
Reviewed-by: Ilias Apalodimas 
---
 MAINTAINERS | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index f8afd7d51e2..11105869304 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1310,6 +1310,17 @@ F:   drivers/net/
 F: include/net.h
 F: net/
 
+NETWORK (LWIP)
+M: Jerome Forissier 
+S: Maintained
+F: cmd/net-lwip.c
+F: configs/qemu_arm64_lwip_defconfig
+F: include/net-lwip.h
+F: lib/lwip/Makefile
+F: lib/lwip/README
+F: lib/lwip/u-boot/
+F: net-lwip/
+
 NIOS
 M: Thomas Chou 
 S: Maintained
-- 
2.40.1



[PATCH v3 10/12] configs: add qemu_arm64_lwip_defconfig

2024-06-06 Thread Jerome Forissier
Add qemu_arm64_lwip_defconfig based on qemu_arm64_defconfig but
with NET_LWIP instead of NET.

Signed-off-by: Jerome Forissier 
---
 configs/qemu_arm64_lwip_defconfig | 3 +++
 1 file changed, 3 insertions(+)
 create mode 100644 configs/qemu_arm64_lwip_defconfig

diff --git a/configs/qemu_arm64_lwip_defconfig 
b/configs/qemu_arm64_lwip_defconfig
new file mode 100644
index 000..050c93ff97b
--- /dev/null
+++ b/configs/qemu_arm64_lwip_defconfig
@@ -0,0 +1,3 @@
+#include 
+CONFIG_NET_LWIP=y
+# CONFIG_DFU_TFTP is not set
-- 
2.40.1



[PATCH v3 09/12] cmd: bdinfo: enable -e when CONFIG_CMD_NET_LWIP=y

2024-06-06 Thread Jerome Forissier
Support "bdinfo -e" when lwIP is selected.

Signed-off-by: Jerome Forissier 
Reviewed-by: Ilias Apalodimas 
Reviewed-by: Tom Rini 
---
 cmd/bdinfo.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c
index 79106caeec2..690fb894bf6 100644
--- a/cmd/bdinfo.c
+++ b/cmd/bdinfo.c
@@ -152,7 +152,7 @@ static int bdinfo_print_all(struct bd_info *bd)
bdinfo_print_num_l("relocaddr", gd->relocaddr);
bdinfo_print_num_l("reloc off", gd->reloc_off);
printf("%-12s= %u-bit\n", "Build", (uint)sizeof(void *) * 8);
-   if (IS_ENABLED(CONFIG_CMD_NET))
+   if (IS_ENABLED(CONFIG_CMD_NET) || IS_ENABLED(CONFIG_CMD_NET_LWIP))
print_eth();
bdinfo_print_num_l("fdt_blob", (ulong)map_to_sysmem(gd->fdt_blob));
bdinfo_print_num_l("new_fdt", (ulong)map_to_sysmem(gd->new_fdt));
@@ -198,7 +198,8 @@ int do_bdinfo(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[])
case 'a':
return bdinfo_print_all(bd);
case 'e':
-   if (!IS_ENABLED(CONFIG_CMD_NET))
+   if (!IS_ENABLED(CONFIG_CMD_NET) &&
+   !IS_ENABLED(CONFIG_CMD_NET_LWIP))
return CMD_RET_USAGE;
print_eth();
return CMD_RET_SUCCESS;
-- 
2.40.1



[PATCH v3 08/12] test: dm: dsa, eth: disable tests when CONFIG_NET_LWIP=y

2024-06-06 Thread Jerome Forissier
Some sandbox tests make strong assumptions on how the network stack is
implemented. For example, the ping tests assume that ARP resolution
occurs upon sending out the ICMP packet. This is not always the case
with the lwIP stack which can cache ARP information.
Therefore, disable these tests when CONFIG_NET_LWIP is enabled.

Signed-off-by: Jerome Forissier 
---
 test/dm/dsa.c | 2 ++
 test/dm/eth.c | 4 
 2 files changed, 6 insertions(+)

diff --git a/test/dm/dsa.c b/test/dm/dsa.c
index c857106eaf4..147e2a4afe2 100644
--- a/test/dm/dsa.c
+++ b/test/dm/dsa.c
@@ -59,6 +59,7 @@ static int dm_test_dsa_probe(struct unit_test_state *uts)
 
 DM_TEST(dm_test_dsa_probe, UT_TESTF_SCAN_FDT);
 
+#if !defined(CONFIG_NET_LWIP)
 /* This test sends ping requests with the local address through each DSA port
  * via the sandbox DSA master Eth.
  */
@@ -80,3 +81,4 @@ static int dm_test_dsa(struct unit_test_state *uts)
 }
 
 DM_TEST(dm_test_dsa, UT_TESTF_SCAN_FDT);
+#endif /* !defined(CONFIG_NET_LWIP) */
diff --git a/test/dm/eth.c b/test/dm/eth.c
index bb3dcc6b954..cf97b1c1ab3 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -170,6 +170,7 @@ static int dm_test_ip6_make_lladdr(struct unit_test_state 
*uts)
 DM_TEST(dm_test_ip6_make_lladdr, UT_TESTF_SCAN_FDT);
 #endif
 
+#if !defined(CONFIG_NET_LWIP)
 static int dm_test_eth(struct unit_test_state *uts)
 {
net_ping_ip = string_to_ip("1.1.2.2");
@@ -298,6 +299,7 @@ static int dm_test_eth_act(struct unit_test_state *uts)
return 0;
 }
 DM_TEST(dm_test_eth_act, UT_TESTF_SCAN_FDT);
+#endif /* !CONFIG_NET_LWIP */
 
 /* Ensure that all addresses are loaded properly */
 static int dm_test_ethaddr(struct unit_test_state *uts)
@@ -332,6 +334,7 @@ static int dm_test_ethaddr(struct unit_test_state *uts)
 }
 DM_TEST(dm_test_ethaddr, UT_TESTF_SCAN_FDT);
 
+#if !defined(CONFIG_NET_LWIP)
 /* The asserts include a return on fail; cleanup in the caller */
 static int _dm_test_eth_rotate1(struct unit_test_state *uts)
 {
@@ -616,6 +619,7 @@ static int dm_test_eth_async_ping_reply(struct 
unit_test_state *uts)
 }
 
 DM_TEST(dm_test_eth_async_ping_reply, UT_TESTF_SCAN_FDT);
+#endif /* !CONFIG_NET_LWIP */
 
 #if IS_ENABLED(CONFIG_IPV6_ROUTER_DISCOVERY)
 
-- 
2.40.1



[PATCH v3 07/12] net-lwip: add wget command

2024-06-06 Thread Jerome Forissier
Add support for the wget command with NET_LWIP.

About the small change in cmd/efidebug.c: when the wget command based
on the lwIP stack is used the wget command has a built-in URL
validation function since it needs to parse it anyways (in parse_url()).
Therefore wget_validate_uri() doesn't exist. So, guard the call in
efidebug.c with CONFIG_CMD_WGET.

Based on code initially developed by Maxim U.

Signed-off-by: Jerome Forissier 
Co-developed-by: Maxim Uvarov 
Cc: Maxim Uvarov 
---
 cmd/Kconfig|   7 ++
 cmd/Makefile   |   5 +-
 cmd/efidebug.c |   8 +-
 cmd/net-common.c   | 115 +
 cmd/net-lwip.c |  12 +++
 cmd/net.c  | 115 -
 include/net-lwip.h |  51 +
 net-lwip/Makefile  |   1 +
 net-lwip/wget.c| 180 +
 9 files changed, 375 insertions(+), 119 deletions(-)
 create mode 100644 cmd/net-common.c
 create mode 100644 net-lwip/wget.c

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 6ef0b52cd34..d9a86540be6 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2117,6 +2117,13 @@ config CMD_TFTPBOOT
help
  tftpboot - load file via network using TFTP protocol
 
+config CMD_WGET
+   bool "wget"
+   select PROT_TCP_LWIP
+   help
+ wget is a simple command to download kernel, or other files,
+ from a http server over TCP.
+
 endif
 
 endif
diff --git a/cmd/Makefile b/cmd/Makefile
index 535b6838ca5..e90f2f68211 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -129,8 +129,11 @@ obj-$(CONFIG_CMD_MUX) += mux.o
 obj-$(CONFIG_CMD_NAND) += nand.o
 obj-$(CONFIG_CMD_NET) += net.o
 obj-$(CONFIG_CMD_NET_LWIP) += net-lwip.o
+obj-$(filter y,$(CONFIG_CMD_NET) $(CONFIG_CMD_NET_LWIP)) += net-common.o
 ifdef CONFIG_CMD_NET_LWIP
-CFLAGS_net-lwip.o := -I$(srctree)/lib/lwip/lwip/src/include 
-I$(srctree)/lib/lwip/u-boot
+lwip-includes := -I$(srctree)/lib/lwip/lwip/src/include 
-I$(srctree)/lib/lwip/u-boot
+CFLAGS_net-lwip.o := $(lwip-includes)
+CFLAGS_net-common.o := $(lwip-includes)
 endif
 obj-$(CONFIG_ENV_SUPPORT) += nvedit.o
 obj-$(CONFIG_CMD_NVEDIT_EFI) += nvedit_efi.o
diff --git a/cmd/efidebug.c b/cmd/efidebug.c
index c2c525f2351..d80e91ecadd 100644
--- a/cmd/efidebug.c
+++ b/cmd/efidebug.c
@@ -741,9 +741,11 @@ static int efi_boot_add_uri(int argc, char *const argv[], 
u16 *var_name16,
if (!label)
return CMD_RET_FAILURE;
 
-   if (!wget_validate_uri(argv[3])) {
-   printf("ERROR: invalid URI\n");
-   return CMD_RET_FAILURE;
+   if (IS_ENABLED(CONFIG_CMD_WGET)) {
+   if (!wget_validate_uri(argv[3])) {
+   printf("ERROR: invalid URI\n");
+   return CMD_RET_FAILURE;
+   }
}
 
efi_create_indexed_name(var_name16, var_name16_size, "Boot", id);
diff --git a/cmd/net-common.c b/cmd/net-common.c
new file mode 100644
index 000..f01d9e63998
--- /dev/null
+++ b/cmd/net-common.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, w...@denx.de.
+ */
+
+#include 
+#include 
+#include 
+#ifdef CONFIG_NET
+#include 
+#elif defined CONFIG_NET_LWIP
+#include 
+#else
+#error Either NET or NET_LWIP must be enabled
+#endif
+#include 
+#include 
+
+static int do_net_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const 
argv[])
+{
+   const struct udevice *current = eth_get_dev();
+   unsigned char env_enetaddr[ARP_HLEN];
+   const struct udevice *dev;
+   struct uclass *uc;
+
+   uclass_id_foreach_dev(UCLASS_ETH, dev, uc) {
+   eth_env_get_enetaddr_by_index("eth", dev_seq(dev), 
env_enetaddr);
+   printf("eth%d : %s %pM %s\n", dev_seq(dev), dev->name, 
env_enetaddr,
+  current == dev ? "active" : "");
+   }
+   return CMD_RET_SUCCESS;
+}
+
+static int do_net_stats(struct cmd_tbl *cmdtp, int flag, int argc, char *const 
argv[])
+{
+   int nstats, err, i, off;
+   struct udevice *dev;
+   u64 *values;
+   u8 *strings;
+
+   if (argc < 2)
+   return CMD_RET_USAGE;
+
+   err = uclass_get_device_by_name(UCLASS_ETH, argv[1], );
+   if (err) {
+   printf("Could not find device %s\n", argv[1]);
+   return CMD_RET_FAILURE;
+   }
+
+   if (!eth_get_ops(dev)->get_sset_count ||
+   !eth_get_ops(dev)->get_strings ||
+   !eth_get_ops(dev)->get_stats) {
+   printf("Driver does not implement stats dump!\n");
+   return CMD_RET_FAILURE;
+   }
+
+   nstats = eth_get_ops(dev)->get_sset_count(dev);
+   strings = kcalloc(nstats, ETH_GSTRING_LEN, GFP_KERNEL);
+   if (!strings)
+   return CMD_RET_FAILURE;
+
+   values = kcalloc(nstats, sizeof(u64)

[PATCH v3 06/12] net-lwip: add dns command

2024-06-06 Thread Jerome Forissier
Add CMD_DNS when NET_LWIP is enabled to provide the dns command using
lwIP.

Signed-off-by: Jerome Forissier 
---
 cmd/Kconfig|   6 +++
 cmd/net-lwip.c |   8 
 include/net-lwip.h |   1 +
 net-lwip/Makefile  |   1 +
 net-lwip/dns.c | 107 +
 5 files changed, 123 insertions(+)
 create mode 100644 net-lwip/dns.c

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 07cfe824e3f..6ef0b52cd34 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2098,6 +2098,12 @@ config CMD_DHCP
help
  Boot image via network using DHCP/TFTP protocol
 
+config CMD_DNS
+   bool "dns"
+   select PROT_DNS_LWIP
+   help
+ Lookup the IP of a hostname
+
 config CMD_PING
bool "ping"
select PROT_RAW_LWIP
diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
index 13856703fcf..3abafdf7969 100644
--- a/cmd/net-lwip.c
+++ b/cmd/net-lwip.c
@@ -27,3 +27,11 @@ U_BOOT_CMD(
"[loadAddress] [[hostIPaddr:]bootfilename]"
 );
 #endif
+
+#if defined(CONFIG_CMD_DNS)
+U_BOOT_CMD(
+   dns,3,  1,  do_dns,
+   "lookup the IP of a hostname",
+   "hostname [envvar]"
+);
+#endif
diff --git a/include/net-lwip.h b/include/net-lwip.h
index 2abaaa3b4e3..0019d1524e5 100644
--- a/include/net-lwip.h
+++ b/include/net-lwip.h
@@ -82,6 +82,7 @@ int net_lwip_init(void);
 struct netif *net_lwip_get_netif(void);
 
 int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 
diff --git a/net-lwip/Makefile b/net-lwip/Makefile
index e68d4e24197..aa247859483 100644
--- a/net-lwip/Makefile
+++ b/net-lwip/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth_common.o
 obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth-uclass.o
 obj-$(CONFIG_$(SPL_)DM_ETH) += net-lwip.o
 obj-$(CONFIG_CMD_DHCP) += dhcp.o
+obj-$(CONFIG_CMD_DNS) += dns.o
 obj-$(CONFIG_CMD_PING) += ping.o
 obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
 
diff --git a/net-lwip/dns.c b/net-lwip/dns.c
new file mode 100644
index 000..24a5149343a
--- /dev/null
+++ b/net-lwip/dns.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2024 Linaro Ltd. */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DNS_RESEND_MS 1000
+#define DNS_TIMEOUT_MS 1
+
+static ulong start;
+static ip_addr_t host_ipaddr;
+static bool done;
+
+static void do_dns_tmr(void *arg)
+{
+   dns_tmr();
+}
+
+static void dns_cb(const char *name, const ip_addr_t *ipaddr, void *arg)
+{
+   const char *var = arg;
+   char *ipstr = ip4addr_ntoa(ipaddr);
+
+   done = true;
+
+   if (!ipaddr) {
+   printf("DNS: host not found\n");
+   host_ipaddr.addr = 0;
+   return;
+   }
+
+   if (var)
+   env_set(var, ipstr);
+
+   printf("%s\n", ipstr);
+}
+
+int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+   bool has_server = false;
+   ip_addr_t ipaddr;
+   ip_addr_t ns;
+   char *nsenv;
+   char *name;
+   char *var;
+   int ret;
+
+   if (argc == 1 || argc > 3)
+   return CMD_RET_USAGE;
+
+   if (argc >= 2)
+   name = argv[1];
+
+   if (argc == 3)
+   var = argv[2];
+
+   dns_init();
+
+   nsenv = env_get("dnsip");
+   if (nsenv && ipaddr_aton(nsenv, )) {
+   dns_setserver(0, );
+   has_server = true;
+   }
+
+   nsenv = env_get("dnsip2");
+   if (nsenv && ipaddr_aton(nsenv, )) {
+   dns_setserver(1, );
+   has_server = true;
+   }
+
+   if (!has_server) {
+   log_err("No valid name server (dnsip/dnsip2)\n");
+   return CMD_RET_FAILURE;
+   }
+
+   done = false;
+
+   ret = dns_gethostbyname(name, , dns_cb, var);
+
+   if (ret == ERR_OK) {
+   dns_cb(name, , var);
+   } else if (ret == ERR_INPROGRESS) {
+   start = get_timer(0);
+   sys_timeout(DNS_RESEND_MS, do_dns_tmr, NULL);
+   do {
+   eth_rx();
+   if (done)
+   break;
+   sys_check_timeouts();
+   if (ctrlc()) {
+   printf("\nAbort\n");
+   break;
+   }
+   } while (get_timer(start) < DNS_TIMEOUT_MS);
+   sys_untimeout(do_dns_tmr, NULL);
+   }
+
+   if (done && host_ipaddr.addr != 0)
+   return CMD_RET_SUCCESS;
+
+   return CMD_RET_FAILURE;
+}
+
-- 
2.40.1



[PATCH v3 05/12] net-lwip: add ping command

2024-06-06 Thread Jerome Forissier
Add support for the the ping command with NET_LWIP. The implementation
is derived from lwIP's contrib/apps/ping/ping.c.

Signed-off-by: Jerome Forissier 
---
 boot/Kconfig   |   2 +-
 cmd/Kconfig|   6 ++
 cmd/net-lwip.c |   8 +++
 include/net-lwip.h |   3 +
 net-lwip/Makefile  |   1 +
 net-lwip/ping.c| 163 +
 6 files changed, 182 insertions(+), 1 deletion(-)
 create mode 100644 net-lwip/ping.c

diff --git a/boot/Kconfig b/boot/Kconfig
index 004e69dd92a..983a284ec52 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -379,7 +379,7 @@ config BOOT_DEFAULTS_CMDS
select CMD_FS_GENERIC
select CMD_PART if PARTITIONS
select CMD_DHCP if CMD_NET || CMD_NET_LWIP
-   select CMD_PING if CMD_NET
+   select CMD_PING if CMD_NET || CMD_NET_LWIP
select CMD_PXE if CMD_NET
select CMD_BOOTI if ARM64
select CMD_BOOTZ if ARM && !ARM64
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 94a8de266f6..07cfe824e3f 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2098,6 +2098,12 @@ config CMD_DHCP
help
  Boot image via network using DHCP/TFTP protocol
 
+config CMD_PING
+   bool "ping"
+   select PROT_RAW_LWIP
+   help
+ Send ICMP ECHO_REQUEST to network host
+
 config CMD_TFTPBOOT
bool "tftp"
select PROT_UDP_LWIP
diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
index 490a2e4ac5c..13856703fcf 100644
--- a/cmd/net-lwip.c
+++ b/cmd/net-lwip.c
@@ -12,6 +12,14 @@ U_BOOT_CMD(
 );
 #endif
 
+#if defined(CONFIG_CMD_PING)
+U_BOOT_CMD(
+   ping,   2,  1,  do_ping,
+   "send ICMP ECHO_REQUEST to network host",
+   "pingAddress"
+);
+#endif
+
 #if defined(CONFIG_CMD_TFTPBOOT)
 U_BOOT_CMD(
tftpboot,   3,  0,  do_tftpb,
diff --git a/include/net-lwip.h b/include/net-lwip.h
index 2308703e46b..2abaaa3b4e3 100644
--- a/include/net-lwip.h
+++ b/include/net-lwip.h
@@ -5,6 +5,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -50,6 +51,7 @@ int eth_env_get_enetaddr_by_index(const char *base_name, int 
index,
 int eth_init(void);/* Initialize the device */
 int eth_send(void *packet, int length);   /* Send a packet */
 int eth_rx(void);
+const char *eth_get_name(void);
 int eth_get_dev_index(void);
 int eth_init_state_only(void); /* Set active state */
 void eth_set_current(void);/* set nterface to ethcur var */
@@ -80,6 +82,7 @@ int net_lwip_init(void);
 struct netif *net_lwip_get_netif(void);
 
 int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 
 #endif /* __NET_LWIP_H__ */
diff --git a/net-lwip/Makefile b/net-lwip/Makefile
index a56c32bfa74..e68d4e24197 100644
--- a/net-lwip/Makefile
+++ b/net-lwip/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth_common.o
 obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth-uclass.o
 obj-$(CONFIG_$(SPL_)DM_ETH) += net-lwip.o
 obj-$(CONFIG_CMD_DHCP) += dhcp.o
+obj-$(CONFIG_CMD_PING) += ping.o
 obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
 
 # Disable this warning as it is triggered by:
diff --git a/net-lwip/ping.c b/net-lwip/ping.c
new file mode 100644
index 000..51947d615ed
--- /dev/null
+++ b/net-lwip/ping.c
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2024 Linaro Ltd. */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define PING_DELAY_MS 1000
+#define PING_TIMEOUT_MS 1
+/* Ping identifier - must fit on a u16_t */
+#define PING_ID 0xAFAF
+
+static const ip_addr_t *ping_target;
+static struct raw_pcb *ping_pcb;
+static uint16_t ping_seq_num;
+
+static u8_t ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p,
+ const ip_addr_t *addr)
+{
+   struct icmp_echo_hdr *iecho;
+   bool *alive = arg;
+
+   if (addr->addr != ping_target->addr)
+   return 0;
+
+   if ((p->tot_len >= (IP_HLEN + sizeof(struct icmp_echo_hdr))) &&
+   pbuf_remove_header(p, IP_HLEN) == 0) {
+   iecho = (struct icmp_echo_hdr *)p->payload;
+
+   if ((iecho->id == PING_ID) &&
+   (iecho->seqno == lwip_htons(ping_seq_num))) {
+   *alive = true;
+   printf("host %s is alive\n", ipaddr_ntoa(addr));
+   pbuf_free(p);
+   return 1; /* eat the packet */
+   }
+   /* not eaten, restore original packet */
+   pbuf_add_header(p, IP_HLEN);
+   }
+
+   return 0; /* don't eat the packet */
+}
+
+static int ping_raw_init(void *recv_arg)
+{
+   ping_pcb = raw_new(IP_PROTO_ICMP);
+   if (!ping_pcb)
+

[PATCH v3 04/12] net-lwip: add TFTP support and tftpboot command

2024-06-06 Thread Jerome Forissier
Implement do_tftpb().

Signed-off-by: Jerome Forissier 
---
 cmd/Kconfig |   3 +-
 cmd/net-lwip.c  |   8 ++
 net-lwip/dhcp.c |  11 ++-
 net-lwip/tftp.c | 202 +++-
 4 files changed, 219 insertions(+), 5 deletions(-)

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 1bfa528e945..94a8de266f6 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2101,10 +2101,9 @@ config CMD_DHCP
 config CMD_TFTPBOOT
bool "tftp"
select PROT_UDP_LWIP
-   default n
+   default y
help
  tftpboot - load file via network using TFTP protocol
- Currently a placeholder (not implemented)
 
 endif
 
diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
index 966d7226eda..490a2e4ac5c 100644
--- a/cmd/net-lwip.c
+++ b/cmd/net-lwip.c
@@ -11,3 +11,11 @@ U_BOOT_CMD(
 "[loadAddress] [[hostIPaddr:]bootfilename]"
 );
 #endif
+
+#if defined(CONFIG_CMD_TFTPBOOT)
+U_BOOT_CMD(
+   tftpboot,   3,  0,  do_tftpb,
+   "boot image via network using TFTP protocol\n",
+   "[loadAddress] [[hostIPaddr:]bootfilename]"
+);
+#endif
diff --git a/net-lwip/dhcp.c b/net-lwip/dhcp.c
index d1d35999b04..7bacc234f1e 100644
--- a/net-lwip/dhcp.c
+++ b/net-lwip/dhcp.c
@@ -94,11 +94,20 @@ int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char 
*const argv[])
 int dhcp_run(ulong addr, const char *fname, bool autoload)
 {
char *dhcp_argv[] = {"dhcp", NULL, };
+#ifdef CONFIG_CMD_TFTPBOOT
+   char *tftp_argv[] = {"tftpboot", boot_file_name, NULL, };
+#endif
struct cmd_tbl cmdtp = {};  /* dummy */
 
if (autoload) {
-   /* Will be supported when TFTP is added */
+#ifdef CONFIG_CMD_TFTPBOOT
+   /* Assume DHCP was already performed */
+   if (boot_file_name[0])
+   return do_tftpb(, 0, 2, tftp_argv);
+   return 0;
+#else
return -EOPNOTSUPP;
+#endif
}
 
return do_dhcp(, 0, 1, dhcp_argv);
diff --git a/net-lwip/tftp.c b/net-lwip/tftp.c
index 1fa246f55d9..02ee4aacca5 100644
--- a/net-lwip/tftp.c
+++ b/net-lwip/tftp.c
@@ -2,10 +2,208 @@
 /* Copyright (C) 2024 Linaro Ltd. */
 
 #include 
+#include 
+#include 
+#include 
+#include 
+#include 
 #include 
+#include 
+
+static ulong daddr;
+static ulong size;
+static ulong prevsize;
+#define PROGRESS_PRINT_STEP_BYTES (100 * 1024)
+static ulong start_time;
+static enum done_state {
+   NOT_DONE = 0,
+   SUCCESS = 1,
+   FAILURE = 2
+} done;
+
+static void *tftp_open(const char *fname, const char *mode, u8_t is_write)
+{
+   return NULL;
+}
+
+static void tftp_close(void *handle)
+{
+   ulong elapsed;
+
+   if (done == FAILURE) {
+   /* Closing after an error */
+   return;
+   }
+
+   elapsed = get_timer(start_time);
+   done = SUCCESS;
+   printf("\nBytes transferred = %lu (%lx hex)\n", size, size);
+
+   if (env_set_hex("filesize", size)) {
+   log_err("filesize not updated\n");
+   return;
+   }
+}
+
+static int tftp_read(void *handle, void *buf, int bytes)
+{
+   return 0;
+}
+
+static int tftp_write(void *handle, struct pbuf *p)
+{
+   struct pbuf *q;
+
+   for (q = p; q != NULL; q = q->next) {
+   memcpy((void *)daddr, q->payload, q->len);
+   daddr += q->len;
+   size += q->len;
+   if (size - prevsize > PROGRESS_PRINT_STEP_BYTES) {
+   printf("#");
+   prevsize = size;
+   }
+   }
+
+   return 0;
+}
+
+static void tftp_error(void *handle, int err, const char *msg, int size)
+{
+   char message[100];
+
+   done = FAILURE;
+   memset(message, 0, sizeof(message));
+   memcpy(message, msg, LWIP_MIN(sizeof(message) - 1, (size_t)size));
+
+   log_info("\nTFTP error: %d (%s)\n", err, message);
+}
+
+static const struct tftp_context tftp_context = {
+   tftp_open,
+   tftp_close,
+   tftp_read,
+   tftp_write,
+   tftp_error
+};
+
+static int tftp_run(ulong addr, char *fname, ip_addr_t srvip)
+{
+   void *f = (void *)0x1; /* unused fake file handle*/
+   err_t err;
+
+   if (!fname || addr == 0)
+   return -1;
+
+   done = NOT_DONE;
+   size = 0;
+   prevsize = 0;
+   daddr = addr;
+
+   log_info("TFTP from server %s; our IP address is %s\n",
+ip4addr_ntoa(), env_get("ipaddr"));
+   log_info("Filename '%s'.\n", fname);
+   log_info("Load address: 0x%lx\n", daddr);
+   log_info("Loading: ");
+
+   err = tftp_init_client(_context);
+   if (!(err == ERR_OK || err == ERR_USE))
+   log_err("tftp_init_client err: %d\n", err);
+
+   start_time = get_timer(0);
+   err = 

[PATCH v3 02/12] net-lwip: build lwIP

2024-06-06 Thread Jerome Forissier
Build the lwIP library when NET_LWIP is enabled. The following files
are adaptation layers written specially for U-Boot:

 lib/lwip/u-boot/arch/cc.h
 lib/lwip/u-boot/arch/sys_arch.h (empty)
 lib/lwip/u-boot/limits.h (empty)
 lib/lwip/u-boot/lwipopts.h

They were initially contributed by Maxim in a previous RFC patch series.

Signed-off-by: Jerome Forissier 
Co-developed-by: Maxim Uvarov 
Cc: Maxim Uvarov 
---
 lib/Makefile|   2 +
 lib/lwip/Makefile   |  57 +
 lib/lwip/u-boot/arch/cc.h   |  43 +++
 lib/lwip/u-boot/arch/sys_arch.h |   0
 lib/lwip/u-boot/limits.h|   0
 lib/lwip/u-boot/lwipopts.h  | 197 
 6 files changed, 299 insertions(+)
 create mode 100644 lib/lwip/Makefile
 create mode 100644 lib/lwip/u-boot/arch/cc.h
 create mode 100644 lib/lwip/u-boot/arch/sys_arch.h
 create mode 100644 lib/lwip/u-boot/limits.h
 create mode 100644 lib/lwip/u-boot/lwipopts.h

diff --git a/lib/Makefile b/lib/Makefile
index 2a76acf100d..c35786a0576 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -94,6 +94,8 @@ obj-$(CONFIG_LIBAVB) += libavb/
 obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += libfdt/
 obj-$(CONFIG_$(SPL_TPL_)OF_REAL) += fdtdec_common.o fdtdec.o
 
+obj-$(CONFIG_NET_LWIP) += lwip/
+
 ifdef CONFIG_SPL_BUILD
 obj-$(CONFIG_SPL_YMODEM_SUPPORT) += crc16-ccitt.o
 obj-$(CONFIG_$(SPL_TPL_)HASH) += crc16-ccitt.o
diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile
new file mode 100644
index 000..158e59b91fc
--- /dev/null
+++ b/lib/lwip/Makefile
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2024 Linaro Ltd.
+
+ccflags-y += -I$(srctree)/lib/lwip/lwip/src/include 
-I$(srctree)/lib/lwip/u-boot
+
+obj-y += \
+   lwip/src/api/api_lib.o \
+   lwip/src/api/api_msg.o \
+   lwip/src/api/err.o \
+   lwip/src/api/if_api.o \
+   lwip/src/api/netbuf.o \
+   lwip/src/api/netdb.o \
+   lwip/src/api/netifapi.o \
+   lwip/src/api/sockets.o \
+   lwip/src/api/tcpip.o \
+   lwip/src/apps/http/http_client.o \
+   lwip/src/apps/tftp/tftp.o \
+   lwip/src/core/altcp_alloc.o \
+   lwip/src/core/altcp.o \
+   lwip/src/core/altcp_tcp.o \
+   lwip/src/core/def.o \
+   lwip/src/core/dns.o \
+   lwip/src/core/inet_chksum.o \
+   lwip/src/core/init.o \
+   lwip/src/core/ip.o \
+   lwip/src/core/ipv4/acd.o \
+   lwip/src/core/ipv4/autoip.o \
+   lwip/src/core/ipv4/dhcp.o \
+   lwip/src/core/ipv4/etharp.o \
+   lwip/src/core/ipv4/icmp.o \
+   lwip/src/core/ipv4/igmp.o \
+   lwip/src/core/ipv4/ip4_addr.o \
+   lwip/src/core/ipv4/ip4.o \
+   lwip/src/core/ipv4/ip4_frag.o \
+   lwip/src/core/ipv6/dhcp6.o \
+   lwip/src/core/ipv6/ethip6.o \
+   lwip/src/core/ipv6/icmp6.o \
+   lwip/src/core/ipv6/inet6.o \
+   lwip/src/core/ipv6/ip6_addr.o \
+   lwip/src/core/ipv6/ip6.o \
+   lwip/src/core/ipv6/ip6_frag.o \
+   lwip/src/core/ipv6/mld6.o \
+   lwip/src/core/ipv6/nd6.o \
+   lwip/src/core/mem.o \
+   lwip/src/core/memp.o \
+   lwip/src/core/netif.o \
+   lwip/src/core/pbuf.o \
+   lwip/src/core/raw.o \
+   lwip/src/core/stats.o \
+   lwip/src/core/sys.o \
+   lwip/src/core/tcp.o \
+   lwip/src/core/tcp_in.o \
+   lwip/src/core/tcp_out.o \
+   lwip/src/core/timeouts.o \
+   lwip/src/core/udp.o \
+   lwip/src/netif/ethernet.o
diff --git a/lib/lwip/u-boot/arch/cc.h b/lib/lwip/u-boot/arch/cc.h
new file mode 100644
index 000..31c036dc0c5
--- /dev/null
+++ b/lib/lwip/u-boot/arch/cc.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2023 Linaro Ltd.  */
+
+#ifndef LWIP_ARCH_CC_H
+#define LWIP_ARCH_CC_H
+
+#include 
+#include 
+#include 
+#include 
+
+#define LWIP_ERRNO_INCLUDE 
+
+#define LWIP_ERRNO_STDINCLUDE  1
+#define LWIP_NO_UNISTD_H 1
+#define LWIP_TIMEVAL_PRIVATE 1
+
+#ifdef CONFIG_LIB_RAND
+#define LWIP_RAND() ((u32_t)rand())
+#endif
+
+/* different handling for unit test, normally not needed */
+#ifdef LWIP_NOASSERT_ON_ERROR
+#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \
+   handler; }} while (0)
+#endif
+
+#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS
+
+#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d 
in %s\n", \
+   x, __LINE__, __FILE__); } while (0)
+
+#define atoi(str) (int)dectoul(str, NULL)
+#define lwip_strnstr(a, b)  strnstr(a, b)
+
+#define LWIP_ERR_T int
+#define LWIP_CONST_CAST(target_type, val) ((target_type)((uintptr_t)val))
+
+#if defined(CONFIG_SYS_BIG_ENDIAN)
+#define BYTE_ORDER BIG_ENDIAN
+#endif
+
+#endif /* LWIP_ARCH_CC_H */
diff --git a/lib/lwip/u-boot/arch/sys_arch.h b/lib/lwip/u-boot/arch/sys_arch.h
new file mode 100644
index 000..e69de29bb2d
diff --git a/lib/lwip/u-boot/limits.h b/lib/lwip/u-boot/limits.h
new file mode 1006

[PATCH v3 00/12] Introduce the lwIP network stack

2024-06-06 Thread Jerome Forissier
ot;). I need some more time
for that and I think running CI on this v2 will help better understand
what is needed for v3.

** Miscellaneous improvements

- "net: introduce alternative implementation as net-lwip/":

* Make DFU_OVER_TFTP not DFU_TFTP incompatible with NET_LWIP. It seems
quite natural to supplement "depends on NET" with "&& !NET_LWIP".
* Make PROT_*_LWIP not visible by removing the Kconfig prompt.

[1] https://lore.kernel.org/all/20231127125726.3735-1-maxim.uva...@linaro.org/
[2] https://www.nongnu.org/lwip/
[3] https://en.wikipedia.org/wiki/LwIP

CC: Javier Tia 

Jerome Forissier (12):
  net: introduce alternative implementation as net-lwip/
  net-lwip: build lwIP
  net-lwip: add DHCP support and dhcp commmand
  net-lwip: add TFTP support and tftpboot command
  net-lwip: add ping command
  net-lwip: add dns command
  net-lwip: add wget command
  test: dm: dsa, eth: disable tests when CONFIG_NET_LWIP=y
  cmd: bdinfo: enable -e when CONFIG_CMD_NET_LWIP=y
  configs: add qemu_arm64_lwip_defconfig
  MAINTAINERS: net-lwip: add myself as a maintainer
  CI: add qemu_arm64_lwip to the test matrix

 .azure-pipelines.yml  |   7 +
 Kconfig   |  40 ++
 MAINTAINERS   |  11 ++
 Makefile  |   3 +-
 boot/Kconfig  |   5 +-
 cmd/Kconfig   |  44 ++
 cmd/Makefile  |   7 +
 cmd/bdinfo.c  |   5 +-
 cmd/efidebug.c|   8 +-
 cmd/net-common.c  | 115 +++
 cmd/net-lwip.c|  49 +++
 cmd/net.c | 115 ---
 common/Kconfig|   2 +-
 common/board_r.c  |   4 +-
 common/spl/Kconfig|   1 +
 configs/qemu_arm64_lwip_defconfig |   3 +
 drivers/dfu/Kconfig   |   2 +-
 drivers/fastboot/Kconfig  |   4 +-
 drivers/net/Kconfig   |   2 +-
 drivers/net/phy/Kconfig   |   2 +-
 drivers/usb/gadget/Kconfig|   2 +-
 include/net-lwip.h| 140 +++
 include/net.h |   2 +-
 lib/Makefile  |   2 +
 lib/lwip/Makefile |  57 
 lib/lwip/u-boot/arch/cc.h |  43 ++
 lib/lwip/u-boot/arch/sys_arch.h   |   0
 lib/lwip/u-boot/limits.h  |   0
 lib/lwip/u-boot/lwipopts.h| 197 ++
 net-lwip/Kconfig  |  37 +
 net-lwip/Makefile |  18 +++
 net-lwip/dhcp.c   | 114 +++
 net-lwip/dns.c| 107 ++
 net-lwip/eth_internal.h   |  35 +
 net-lwip/net-lwip.c   | 224 ++
 net-lwip/ping.c   | 163 ++
 net-lwip/tftp.c   | 209 
 net-lwip/wget.c   | 180 
 net/Kconfig   |  14 --
 test/dm/dsa.c |   2 +
 test/dm/eth.c |   4 +
 41 files changed, 1832 insertions(+), 147 deletions(-)
 create mode 100644 cmd/net-common.c
 create mode 100644 cmd/net-lwip.c
 create mode 100644 configs/qemu_arm64_lwip_defconfig
 create mode 100644 include/net-lwip.h
 create mode 100644 lib/lwip/Makefile
 create mode 100644 lib/lwip/u-boot/arch/cc.h
 create mode 100644 lib/lwip/u-boot/arch/sys_arch.h
 create mode 100644 lib/lwip/u-boot/limits.h
 create mode 100644 lib/lwip/u-boot/lwipopts.h
 create mode 100644 net-lwip/Kconfig
 create mode 100644 net-lwip/Makefile
 create mode 100644 net-lwip/dhcp.c
 create mode 100644 net-lwip/dns.c
 create mode 100644 net-lwip/eth_internal.h
 create mode 100644 net-lwip/net-lwip.c
 create mode 100644 net-lwip/ping.c
 create mode 100644 net-lwip/tftp.c
 create mode 100644 net-lwip/wget.c

-- 
2.40.1



Re: [PATCH v2 07/14] net-lwip: add dns command

2024-06-06 Thread Jerome Forissier



On 6/6/24 08:29, Ilias Apalodimas wrote:
> Hi Jerome,
> 
> [...]
> 
>> +
>> +static ulong start;
>> +static ip_addr_t host_ipaddr;
>> +static bool done;
>> +
>> +static void do_dns_tmr(void *arg)
>> +{
>> + dns_tmr();
>> +}
>> +
>> +static void dns_cb(const char *name, const ip_addr_t *ipaddr, void *arg)
>> +{
>> + char *var = (char *)arg;
> 
> const char *

Fixed in v3.

> 
>> + char *ipstr = ip4addr_ntoa(ipaddr);
>> +
>> + done = true;
>> +
>> + if (!ipaddr) {
>> + printf("DNS: host not found\n");
>> + host_ipaddr.addr = 0;
>> + return;
>> + }
>> +
>> + if (var)
>> + env_set(var, ipstr);
>> +
>> + printf("%s\n", ipstr);
>> +}
>> +
>> +int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
>> +{
>> + bool has_server = false;
>> + ip_addr_t ipaddr;
>> + ip_addr_t ns;
>> + char *nsenv;
>> + char *name;
>> + char *var;
>> + int ret;
>> +
>> + if (argc == 1 || argc > 3)
>> + return CMD_RET_USAGE;
>> +
>> + if (argc >= 2)
>> + name = argv[1];
>> +
>> + if (argc == 3)
>> + var = argv[2];
>> +
>> + dns_init();
>> +
>> + nsenv = env_get("dnsip");
>> + if (nsenv && ipaddr_aton(nsenv, )) {
>> + dns_setserver(0, );
>> + has_server = true;
>> + }
>> +
>> + nsenv = env_get("dnsip2");
>> + if (nsenv && ipaddr_aton(nsenv, )) {
>> + dns_setserver(1, );
>> + has_server = true;
>> + }
>> +
>> + if (!has_server) {
>> + log_err("No valid name server (dnsip/dnsip2)\n");
>> + return CMD_RET_FAILURE;
>> + }
>> +
>> + done = false;
>> +
>> + ret = dns_gethostbyname(name, , dns_cb, var);
>> +
>> + if (ret == ERR_OK) {
>> + dns_cb(name, , var);
>> + } else if (ret == ERR_INPROGRESS) {
>> + start = get_timer(0);
>> + sys_timeout(DNS_RESEND_MS, do_dns_tmr, NULL);
>> + do {
>> + eth_rx();
>> + if (done)
>> + break;
>> + sys_check_timeouts();
>> + if (ctrlc()) {
>> + printf("\nAbort\n");
>> + break;
>> + }
>> + } while (get_timer(start) < DNS_TIMEOUT_MS);
>> + sys_untimeout(do_dns_tmr, NULL);
>> + }
> 
> Looking at the lwip code there are other ret values than just ERR_OK,
> ERR_INPROGRESS. Should we have an 'else' handling the rest?

Not needed, since in this case we will reach the next line
'if (done && host_ipaddr.addr != 0)' which is the true success condition.

Thanks,
-- 
Jerome


Re: [PATCH v2 08/14] net-lwip: add wget command

2024-06-06 Thread Jerome Forissier



On 6/6/24 12:16, Maxim Uvarov wrote:
> чт, 6 июн. 2024 г. в 12:56, Jerome Forissier :

[...]

>>>> diff --git a/net-lwip/wget.c b/net-lwip/wget.c
>>>> new file mode 100644
>>>> index 000..25b75040806
>>>> --- /dev/null
>>>> +++ b/net-lwip/wget.c
>>>> @@ -0,0 +1,180 @@
>>>> +// SPDX-License-Identifier: GPL-2.0+
>>>> +/* Copyright (C) 2024 Linaro Ltd. */
>>>> +
>>>> +#include 
>>>> +#include 
>>>> +#include 
>>>> +#include 
>>>> +#include 
>>>> +#include 
>>>> +#include 
>>>> +#include 
>>>> +
>>
>> [...]
>>>> +
>>>> +static void httpc_result_cb(void *arg, httpc_result_t httpc_result,
>>>> +   u32_t rx_content_len, u32_t srv_res, err_t err)
>>>> +{
>>>> +   ulong elapsed;
>>>> +
>>>> +   if (httpc_result != HTTPC_RESULT_OK) {
>>>> +   log_err("\nHTTP client error %d\n", httpc_result);
>>>> +   done = FAILURE;
>>>> +   return;
>>>> +   }
>>>> +
>>>> +   elapsed = get_timer(start_time);
>>>> +log_info("\n%u bytes transferred in %lu ms (", rx_content_len,
>>>
>>> This print I commented for another patch to match current python tests.
>>
>> What do you mean? Is this text incorrect because some tests expect something
>> else? Which ones?
> 
> You modified the python test to expect this output if LWIP is enabled.

It was in the TFTP test.

> Instead of adding one
> more 'if LWIP' to the python test you can make this log_info() output
> the same as the original code.
> But this is up to you. Somebody sometime later will need to drop 'if
> LWIP' from python code.
I dropped the TFTP message change in v3. I will not change the message
for wget since I don't see any issue with that.

Thanks,
-- 
Jerome

> 
> BR,
> Maxim.


Re: [PATCH v2 06/14] net-lwip: add ping command

2024-06-06 Thread Jerome Forissier



On 6/6/24 11:10, Ilias Apalodimas wrote:
>> +#include 
>> +#include 
>> +
>> +#define PING_DELAY_MS 1000
>> +#define PING_TIMEOUT_MS 1
>> +/* Additional data size to include in the packet */
>> +#define PING_DATA_SIZE 32
>> +/* Ping identifier - must fit on a u16_t */
>> +#define PING_ID 0xAFAF
>> +
>> +static const ip_addr_t *ping_target;
>> +static struct raw_pcb *ping_pcb;
>> +static u16_t ping_seq_num;
> 
> As a general note, u8_t u16_t etc are lwip constructs.
> Can we not use them and instead use the original definition?
> uint8_t etc. I am not sure introducing another define is what we want. Tom?

I think it makes sense to use the more standard type (uint16_t etc.) when
defining variables like here. However I'd rather keep the lwIP types in
the function definitions to reflect the function prototype exactly.

>> +static bool ping_target_alive;
>> +
>> +static u8_t ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p,
>> +  const ip_addr_t *addr)
>> +{
>> +struct icmp_echo_hdr *iecho;
>> +
>> +if (addr->addr != ping_target->addr)
>> +return 0;
>> +
>> +if ((p->tot_len >= (IP_HLEN + sizeof(struct icmp_echo_hdr))) &&
>> +pbuf_remove_header(p, IP_HLEN) == 0) {
>> +iecho = (struct icmp_echo_hdr *)p->payload;
>> +
>> +if ((iecho->id == PING_ID) &&
>> +(iecho->seqno == lwip_htons(ping_seq_num))) {
>> +ping_target_alive = true;
>> +printf("host %s is alive\n", ipaddr_ntoa(addr));
>> +pbuf_free(p);
>> +return 1; /* eat the packet */
>> +}
>> +/* not eaten, restore original packet */
>> +pbuf_add_header(p, IP_HLEN);
>> +}
>> +
>> +return 0; /* don't eat the packet */
>> +}
>> +
>> +static int ping_raw_init(void)
>> +{
>> +ping_pcb = raw_new(IP_PROTO_ICMP);
>> +if (!ping_pcb)
>> +return -ENOMEM;
>> +
>> +raw_recv(ping_pcb, ping_recv, NULL);
> 
> Instead of defining a global variable ping_target_alive can we instead pass
> the ptr of void *recv_arg? We can then fill in that private ptr with the
> status

Sure. Fixed in v3.
 
>> +raw_bind(ping_pcb, IP_ADDR_ANY);
>> +
>> +return 0;
>> +}
>> +
>> +static void ping_raw_stop(void)
>> +{
>> +if (ping_pcb != NULL) {
>> +raw_remove(ping_pcb);
>> +ping_pcb = NULL;
>> +}
>> +}
>> +
>> +static void ping_prepare_echo(struct icmp_echo_hdr *iecho, u16_t len)
>> +{
>> +size_t i;
>> +size_t data_len = len - sizeof(struct icmp_echo_hdr);
>> +
>> +ICMPH_TYPE_SET(iecho, ICMP_ECHO);
>> +ICMPH_CODE_SET(iecho, 0);
>> +iecho->chksum = 0;
>> +iecho->id = PING_ID;
>> +iecho->seqno = lwip_htons(++ping_seq_num);
>> +
>> +/* Fill the additional data buffer with some data */
>> +for(i = 0; i < data_len; i++) {
>> +((char *)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i;
>> +}
> 
> is this additional data used? And if they are shouldn't we care about
> endianess?

It's a random payload for the ICMP packet. TBH it's totally useless here,
I will just remove the additional data in v3.

> 
>> +
>> +iecho->chksum = inet_chksum(iecho, len);
>> +}
>> +
>> +static void ping_send_icmp(struct raw_pcb *raw, const ip_addr_t *addr)
>> +{
>> +struct pbuf *p;
>> +struct icmp_echo_hdr *iecho;
>> +size_t ping_size = sizeof(struct icmp_echo_hdr) + PING_DATA_SIZE;
>> +
>> +p = pbuf_alloc(PBUF_IP, (u16_t)ping_size, PBUF_RAM);
>> +if (!p)
>> +return;
>> +
>> +if ((p->len == p->tot_len) && (p->next == NULL)) {
>> +iecho = (struct icmp_echo_hdr *)p->payload;
>> +ping_prepare_echo(iecho, (u16_t)ping_size);
>> +raw_sendto(raw, p, addr);
>> +}
>> +
>> +pbuf_free(p);
>> +}
>> +
>> +static void ping_send(void *arg)
>> +{
>> +struct raw_pcb *pcb = (struct raw_pcb *)arg;
>> +
>> +ping_send_icmp(pcb, ping_target);
>> +sys_timeout(PING_DELAY_MS, ping_send, ping_pcb);
>> +}
>> +
>> +static int ping_loop(const ip_addr_t* addr)
>> +{
>> +ulong start;
>> +int ret;
>> +
>> +printf("Using %s device\n", eth_get_name());
>> +
>> +ret = ping_raw_init();
>> +if (ret < 0)
>> +return ret;
>> +ping_target = addr;
>> +
>> +start = get_timer(0);
>> +ping_send(ping_pcb);
>> +
>> +do {
>> +eth_rx();
> 
> eth_rx() has a ret value. Don't we have to check it here?

We would not do anything different on error because an error
might be transient, we don't want too much complexity. Letting the
loop run until success (which is determined by the proper ICMP
echo reply being received) or timeout or Ctrl-C is good enough.

BTW net_loop() in net/net.c doesn't check the return status,
either.

> 
>> +if (ping_target_alive)
>> +break;
>> +sys_check_timeouts();
>> +if (ctrlc()) {
>> +

Re: [PATCH v2 08/14] net-lwip: add wget command

2024-06-06 Thread Jerome Forissier



On 5/28/24 15:39, Maxim Uvarov wrote:
> пт, 24 мая 2024 г. в 19:22, Jerome Forissier :
>>
>> Add support for the wget command with NET_LWIP.
>>
>> About the small change in cmd/efidebug.c: when the wget command based
>> on the lwIP stack is used the wget command has a built-in URL
>> validation function since it needs to parse it anyways (in parse_url()).
>> Therefore wget_validate_uri() doesn't exist. So, guard the call in
>> efidebug.c with CONFIG_CMD_WGET.
>>
>> Based on code initially developed by Maxim U.
>>
>> Signed-off-by: Jerome Forissier 
>> Co-developed-by: Maxim Uvarov 
>> Cc: Maxim Uvarov 
>> ---
>>  cmd/Kconfig|   7 ++
>>  cmd/Makefile   |   5 +-
>>  cmd/efidebug.c |   8 +-
>>  cmd/net-common.c   | 112 
>>  cmd/net-lwip.c |  12 +++
>>  cmd/net.c  | 115 -
>>  include/net-lwip.h |  51 +
>>  net-lwip/Makefile  |   1 +
>>  net-lwip/wget.c| 180 +
>>  9 files changed, 372 insertions(+), 119 deletions(-)
>>  create mode 100644 cmd/net-common.c
>>  create mode 100644 net-lwip/wget.c
>>
>> diff --git a/cmd/Kconfig b/cmd/Kconfig
>> index 6ef0b52cd34..d9a86540be6 100644
>> --- a/cmd/Kconfig
>> +++ b/cmd/Kconfig
>> @@ -2117,6 +2117,13 @@ config CMD_TFTPBOOT
>> help
>>   tftpboot - load file via network using TFTP protocol
>>
>> +config CMD_WGET
>> +   bool "wget"
>> +   select PROT_TCP_LWIP
>> +   help
>> + wget is a simple command to download kernel, or other files,
>> + from a http server over TCP.
>> +
>>  endif
>>
>>  endif
>> diff --git a/cmd/Makefile b/cmd/Makefile
>> index 535b6838ca5..e90f2f68211 100644
>> --- a/cmd/Makefile
>> +++ b/cmd/Makefile
>> @@ -129,8 +129,11 @@ obj-$(CONFIG_CMD_MUX) += mux.o
>>  obj-$(CONFIG_CMD_NAND) += nand.o
>>  obj-$(CONFIG_CMD_NET) += net.o
>>  obj-$(CONFIG_CMD_NET_LWIP) += net-lwip.o
>> +obj-$(filter y,$(CONFIG_CMD_NET) $(CONFIG_CMD_NET_LWIP)) += net-common.o
>>  ifdef CONFIG_CMD_NET_LWIP
>> -CFLAGS_net-lwip.o := -I$(srctree)/lib/lwip/lwip/src/include 
>> -I$(srctree)/lib/lwip/u-boot
>> +lwip-includes := -I$(srctree)/lib/lwip/lwip/src/include 
>> -I$(srctree)/lib/lwip/u-boot
>> +CFLAGS_net-lwip.o := $(lwip-includes)
>> +CFLAGS_net-common.o := $(lwip-includes)
>>  endif
>>  obj-$(CONFIG_ENV_SUPPORT) += nvedit.o
>>  obj-$(CONFIG_CMD_NVEDIT_EFI) += nvedit_efi.o
>> diff --git a/cmd/efidebug.c b/cmd/efidebug.c
>> index c2c525f2351..d80e91ecadd 100644
>> --- a/cmd/efidebug.c
>> +++ b/cmd/efidebug.c
>> @@ -741,9 +741,11 @@ static int efi_boot_add_uri(int argc, char *const 
>> argv[], u16 *var_name16,
>> if (!label)
>> return CMD_RET_FAILURE;
>>
>> -   if (!wget_validate_uri(argv[3])) {
>> -   printf("ERROR: invalid URI\n");
>> -   return CMD_RET_FAILURE;
>> +   if (IS_ENABLED(CONFIG_CMD_WGET)) {
>> +   if (!wget_validate_uri(argv[3])) {
>> +   printf("ERROR: invalid URI\n");
>> +   return CMD_RET_FAILURE;
>> +   }
>> }
>>
>> efi_create_indexed_name(var_name16, var_name16_size, "Boot", id);
>> diff --git a/cmd/net-common.c b/cmd/net-common.c
>> new file mode 100644
>> index 000..b5dfd2c8866
>> --- /dev/null
>> +++ b/cmd/net-common.c
>> @@ -0,0 +1,112 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * (C) Copyright 2000
>> + * Wolfgang Denk, DENX Software Engineering, w...@denx.de.
>> + */
>> +
>> +#include 
>> +#include 
>> +#include 
>> +#ifdef CONFIG_NET
>> +#include 
>> +#elif defined CONFIG_NET_LWIP
>> +#include 
>> +#else
>> +#error Either NET or NET_LWIP must be enabled
>> +#endif
>> +#include 
>> +#include 
>> +
>> +static int do_net_list(struct cmd_tbl *cmdtp, int flag, int argc, char 
>> *const argv[])
>> +{
>> +   const struct udevice *current = eth_get_dev();
>> +   unsigned char env_enetaddr[ARP_HLEN];
>> +   const struct udevice *dev;
>> +   struct uclass *uc;
>> +
>> +   uclass_id_foreach_dev(UCLASS_ETH, dev, uc) {
>> +   eth_env_get_enetaddr_by_index("eth", dev_seq(dev), 
>> env_enetaddr);
>> +   printf("

Re: [PATCH v2 12/14] test/py: net: add _lwip variants of dhcp, ping and tftpboot tests

2024-06-06 Thread Jerome Forissier



On 5/30/24 16:22, Maxim Uvarov wrote:
> чт, 30 мая 2024 г. в 17:11, Jerome Forissier :
>>
>>
>>
>> On 5/28/24 11:53, Maxim Uvarov wrote:
>>> пт, 24 мая 2024 г. в 19:22, Jerome Forissier :
>>>>
>>>> WHen NET_LWIP is enabled, the dhcp/ping/tftpboot commands are enabled
>>>> via CMD_DHCP_LWIP, CMD_PING_LWIP and CMD_TFTPBOOT_LWIP, respectively;
>>>> therefore the config annotations in the Python test scripts need to be
>>>> cmd_dhcp_lwip, cmd_ping_lwip and cmd_tftpboot_lwip.
>>>>
>>>> The console output of the tftpboot command with lwIP is slightly
>>>> different from the non-lwIP implementation. This is taken care of in
>>>> test_net_tftpboot().
>>>>
>>>> Signed-off-by: Jerome Forissier 
>>>> ---
>>>>  test/py/tests/test_net.py | 21 +
>>>>  1 file changed, 17 insertions(+), 4 deletions(-)
>>>>
>>>> diff --git a/test/py/tests/test_net.py b/test/py/tests/test_net.py
>>>> index 038a473b239..ba30780903f 100644
>>>> --- a/test/py/tests/test_net.py
>>>> +++ b/test/py/tests/test_net.py
>>>> @@ -127,6 +127,10 @@ def test_net_dhcp(u_boot_console):
>>>>  global net_set_up
>>>>  net_set_up = True
>>>>
>>>> +@pytest.mark.buildconfigspec('cmd_dhcp_lwip')
>>>> +def test_net_dhcp_lwip(u_boot_console):
>>>> +test_net_dhcp(u_boot_console)
>>>> +
>>>>  @pytest.mark.buildconfigspec('cmd_dhcp')
>>>>  @pytest.mark.buildconfigspec('cmd_mii')
>>>>  def test_net_dhcp_abort(u_boot_console):
>>>> @@ -230,6 +234,10 @@ def test_net_ping(u_boot_console):
>>>>  output = u_boot_console.run_command('ping $serverip')
>>>>  assert 'is alive' in output
>>>>
>>>> +@pytest.mark.buildconfigspec('cmd_ping_lwip')
>>>> +def test_net_ping_lwip(u_boot_console):
>>>> +test_net_ping(u_boot_console)
>>>> +
>>>>  @pytest.mark.buildconfigspec('IPV6_ROUTER_DISCOVERY')
>>>>  def test_net_network_discovery(u_boot_console):
>>>>  """Test the network discovery feature of IPv6.
>>>> @@ -255,7 +263,7 @@ def test_net_network_discovery(u_boot_console):
>>>>  assert ':::::::' not in output
>>>>
>>>>  @pytest.mark.buildconfigspec('cmd_net')
>>>> -def test_net_tftpboot(u_boot_console):
>>>> +def test_net_tftpboot(u_boot_console, lwip = False):
>>>>  """Test the tftpboot command.
>>>>
>>>>  A file is downloaded from the TFTP server, its size and optionally its
>>>> @@ -279,10 +287,11 @@ def test_net_tftpboot(u_boot_console):
>>>>  output = u_boot_console.run_command('tftpboot %s' % (fn))
>>>>  else:
>>>>  output = u_boot_console.run_command('tftpboot %x %s' % (addr, fn))
>>>> -expected_text = 'Bytes transferred = '
>>>>  sz = f.get('size', None)
>>>> -if sz:
>>>> -expected_text += '%d' % sz
>>>> +if lwip:
>>>> +expected_text = f'{sz} bytes transferred'
>>>
>>> Why not change patch 5 to print with capital character to match this 
>>> pattern?
>>
>> I thought unifying the messages of wget and tftp would be a good idea. With
>> this series, both commands print hash signs followed by:
>> "xxx bytes transferred (yy MB/s)".
>>
>> Would a patch updating the tftp message when the legacy stack is used be
>> acceptable?
>>
>> --
>> Jerome
>>
> 
> I think yes.

I changed my mind. As I replied to Tom, I will stick with the older message
format for now.

Thanks,
-- 
Jerome


Re: [PATCH v2 00/14] Introduce the lwIP network stack

2024-06-06 Thread Jerome Forissier



On 5/27/24 17:34, Tom Rini wrote:
> On Fri, May 24, 2024 at 06:19:54PM +0200, Jerome Forissier wrote:
> 
>> This is a rework of a patch series by Maxim Uvarov: "net/lwip: add lwip
>> library for the network stack" [1]. The goal is to introduce the lwIP TCP/IP
>> stack [2] [3] as an alternative to the current implementation in net/,
>> selectable with Kconfig, and ultimately keep only lwIP if possible. Some
>> reasons for doing so are:
>> - Make the support of HTTPS in the wget command easier. Javier T. (CC'd)
>> has some additional lwIP and Mbed TLS patches to do so. With that it
>> becomes possible to fetch and launch a distro installer such as Debian
>> etc. directly from the U-Boot shell.
>> - Possibly benefit from additional features implemented in lwIP
>> - Less code to maintain in U-Boot
>>
>> The first patch introduces a new Kconfig symbol: NET_LWIP, which selects
>> the lwIP implementation instead of the current one (NET). Contrary to the
>> approach chosen by Maxim in [1], NET_LWIP and NET cannot be enabled
>> simultaneously. The rationale is we want to start from a clean state and
>> not pull potentially duplicated functionality from both stacks. Note
>> however that a few files are still built in net/, they are the ones
>> related to ethernet device management and the ethernet bootflow.
>>
>> The second patch imports the lwIP code as a Git subtree under
>> lib/lwip/lwip. Some glue code is added under lib/lwip/u-boot.
> 
> For next time, please just make it a pre-req to run the git subtree
> command (and note it in the cover letter).
> 
> In more specific feedback, I tried this on a Pi 3, and:
> U-Boot> tftpboot 20 EFI/arm64/helloworld.efi
> TFTP from server 192.168.1.10; our IP address is 192.168.1.100
> Filename 'EFI/arm64/helloworld.efi'.
> Load address: 0x20
> Loading:
> 
> FAILED test/py/tests/test_efi_loader.py::test_efi_helloworld_net - 
> u_boot_spawn.Timeout
> 
> So some amount of networking is working (that's a reasonable dhcp
> response it got), but tftp'ing a file fails.

Thanks for testing! This fails because I changed the command output. The
legacy command prints "Bytes transferred =" while the newer one prints
"%lu bytes transferred" plus throughput information. I will use the older
message in v3 because several tests as well as documentation would need
updating. We'll do that later if desired.

Thanks,
-- 
Jerome


Re: [PATCH v2 01/14] net: introduce alternative implementation as net-lwip/

2024-06-05 Thread Jerome Forissier
On 5/27/24 17:34, Tom Rini wrote:
> On Fri, May 24, 2024 at 06:19:55PM +0200, Jerome Forissier wrote:
> 
>> Prepare the introduction of the lwIP (lightweight IP) TCP/IP stack by
>> adding a new net-lwip/ directory and the NET_LWIP symbol. At this
>> point, enabling NET_LWIP simply disables NET. Subsequent commits will
>> introduce the lwIP code, re-work the NETDEVICE integration and port
>> some of the NET commands and features to lwIP.
>>
>> SPL_NET cannot be enabled when NET_LWIP=y. SPL_NET pulls some symbols
>> that are part of NET (such as arp_init(), arp_timeout_check(),
>> arp_receive(), net_arp_wait_packet_ip()). lwIP support in SPL may be
>> added later.
>>
>> Similarly, DFU_TFTP is not compatible with NET_LWIP because it depends
>> on net_loop(), tftp_timeout_ms, tftp_timeout_count_max. Let's add a
>> dependency on !NET_LWIP for now.
>>
>> Signed-off-by: Jerome Forissier 
> [snip]
>> diff --git a/Kconfig b/Kconfig
>> index 82df59f176e..758256ab121 100644
>> --- a/Kconfig
>> +++ b/Kconfig
>> @@ -747,6 +747,8 @@ source "env/Kconfig"
>>  
>>  source "net/Kconfig"
>>  
>> +source "net-lwip/Kconfig"
>> +
>>  source "drivers/Kconfig"
>>  
>>  source "fs/Kconfig"
> 
> I think we need to instead rework this to a choice statement instead so
> that in the end we have something like:
> choice "Networking stack"
> config NO_NET
>   bool "No networking support"
> config NET
>   bool "Legacy U-Boot networking stack"
> config NET_LWIP
>   bool "Use lwIP for networking stack"
> 
> if NET_LEGACY
> source "net/Kconfig"
> endif
> 
> if NET_LWIP
> source "net-lwip/Kconfig"
> endif
> 
> And then SPL_NET still depends on !NET_LWIP for now and we sort out the
> problems with different networking stacks in SPL vs full U-Boot later
> on.

Done in v3. Thanks.

-- 
Jerome


Re: [PATCH v2 12/14] test/py: net: add _lwip variants of dhcp, ping and tftpboot tests

2024-05-30 Thread Jerome Forissier



On 5/28/24 11:53, Maxim Uvarov wrote:
> пт, 24 мая 2024 г. в 19:22, Jerome Forissier :
>>
>> WHen NET_LWIP is enabled, the dhcp/ping/tftpboot commands are enabled
>> via CMD_DHCP_LWIP, CMD_PING_LWIP and CMD_TFTPBOOT_LWIP, respectively;
>> therefore the config annotations in the Python test scripts need to be
>> cmd_dhcp_lwip, cmd_ping_lwip and cmd_tftpboot_lwip.
>>
>> The console output of the tftpboot command with lwIP is slightly
>> different from the non-lwIP implementation. This is taken care of in
>> test_net_tftpboot().
>>
>> Signed-off-by: Jerome Forissier 
>> ---
>>  test/py/tests/test_net.py | 21 +
>>  1 file changed, 17 insertions(+), 4 deletions(-)
>>
>> diff --git a/test/py/tests/test_net.py b/test/py/tests/test_net.py
>> index 038a473b239..ba30780903f 100644
>> --- a/test/py/tests/test_net.py
>> +++ b/test/py/tests/test_net.py
>> @@ -127,6 +127,10 @@ def test_net_dhcp(u_boot_console):
>>  global net_set_up
>>  net_set_up = True
>>
>> +@pytest.mark.buildconfigspec('cmd_dhcp_lwip')
>> +def test_net_dhcp_lwip(u_boot_console):
>> +test_net_dhcp(u_boot_console)
>> +
>>  @pytest.mark.buildconfigspec('cmd_dhcp')
>>  @pytest.mark.buildconfigspec('cmd_mii')
>>  def test_net_dhcp_abort(u_boot_console):
>> @@ -230,6 +234,10 @@ def test_net_ping(u_boot_console):
>>  output = u_boot_console.run_command('ping $serverip')
>>  assert 'is alive' in output
>>
>> +@pytest.mark.buildconfigspec('cmd_ping_lwip')
>> +def test_net_ping_lwip(u_boot_console):
>> +test_net_ping(u_boot_console)
>> +
>>  @pytest.mark.buildconfigspec('IPV6_ROUTER_DISCOVERY')
>>  def test_net_network_discovery(u_boot_console):
>>  """Test the network discovery feature of IPv6.
>> @@ -255,7 +263,7 @@ def test_net_network_discovery(u_boot_console):
>>  assert ':::::::' not in output
>>
>>  @pytest.mark.buildconfigspec('cmd_net')
>> -def test_net_tftpboot(u_boot_console):
>> +def test_net_tftpboot(u_boot_console, lwip = False):
>>  """Test the tftpboot command.
>>
>>  A file is downloaded from the TFTP server, its size and optionally its
>> @@ -279,10 +287,11 @@ def test_net_tftpboot(u_boot_console):
>>  output = u_boot_console.run_command('tftpboot %s' % (fn))
>>  else:
>>  output = u_boot_console.run_command('tftpboot %x %s' % (addr, fn))
>> -expected_text = 'Bytes transferred = '
>>  sz = f.get('size', None)
>> -if sz:
>> -expected_text += '%d' % sz
>> +if lwip:
>> +expected_text = f'{sz} bytes transferred'
> 
> Why not change patch 5 to print with capital character to match this pattern?

I thought unifying the messages of wget and tftp would be a good idea. With
this series, both commands print hash signs followed by:
"xxx bytes transferred (yy MB/s)".

Would a patch updating the tftp message when the legacy stack is used be
acceptable?

-- 
Jerome

> BR,
> Maxim.
> 
>> +else:
>> +expected_text = f'Bytes transferred = {sz}'
>>  assert expected_text in output
>>
>>  expected_crc = f.get('crc32', None)
>> @@ -295,6 +304,10 @@ def test_net_tftpboot(u_boot_console):
>>  output = u_boot_console.run_command('crc32 $fileaddr $filesize')
>>  assert expected_crc in output
>>
>> +@pytest.mark.buildconfigspec("cmd_net_lwip")
>> +def test_net_tftpboot_lwip(u_boot_console):
>> +test_net_tftpboot(u_boot_console, True)
>> +
>>  @pytest.mark.buildconfigspec('cmd_nfs')
>>  def test_net_nfs(u_boot_console):
>>  """Test the nfs command.
>> --
>> 2.40.1
>>
> 
> 


Re: [PATCH v2 00/14] Introduce the lwIP network stack

2024-05-27 Thread Jerome Forissier
On 5/27/24 11:45, Martin Husemann wrote:
> On Mon, May 27, 2024 at 11:36:26AM +0200, Jerome Forissier wrote:
>> You're correct. The point I am making is about using a secure
>> (authenticated) connection, and I should have clarified that. While using
>> HTTPS might not be critical on a local network, things are different when
>> downloading from the internet (think man-in-the-middle attacks).
> 
> (Sorry if this sounds like nitpkicking, but I am genuinely curious)

No worries. Well-defined use cases are certainly essential to
proper implementations.

> How is it supposed to work?
> 
> You need not only https but also verify the presented certificate chain,
> and for that you need up-to-date root certificates (e.g. the bundle
> available from mozilla).

Yes. I will let Javier comment further since he's more directly
concerned with that part.

> This sounds a bit outside the scope of u-boot to me

Maybe, maybe not. I would argue it is a matter of deployment policy.
For example assume the device is an IP camera or some other IoT thing
that comes with the bare minimum to boot and fetch its OS on first
power up. No guarantee about what is on the local network -- just
plain internet access. https would be quite helpful in such a case.

> (or you should 
> avoid the man-in-the-middle argument, which leaves the still valid
> "sites stop offering plain http" argument).

As long as there is at least one valid argument then I'm fine :)

> If you really worry about man-in-the-middle you need to download via
> https in an environment that does certificate validation, and then
> even better verify the hash of the downloaded image. After that you
> can offer the image locally - via http, https or tftp - for installations.

That certainly would work but again, isn't it a decision to be made
by the device manufacturer or more generally the one who builds u-boot
for the device?

-- 
Jerome


Re: [PATCH v2 00/14] Introduce the lwIP network stack

2024-05-27 Thread Jerome Forissier
Hi Francesco,


On 5/27/24 11:23, Francesco Dolcini wrote:
> Hello Jerome,
> 
> On Fri, May 24, 2024 at 06:19:54PM +0200, Jerome Forissier wrote:
>> - Make the support of HTTPS in the wget command easier. Javier T. (CC'd)
>> has some additional lwIP and Mbed TLS patches to do so. With that it
>> becomes possible to fetch and launch a distro installer such as Debian
>> etc. directly from the U-Boot shell.
> 
> Why this is enabling this use case? Or it is just that currently,
> without TLS, is not supposed to be something you should do?
> I am a little bit confused reading this sentence, since to me this is
> already possible using tftp.

You're correct. The point I am making is about using a secure
(authenticated) connection, and I should have clarified that. While using
HTTPS might not be critical on a local network, things are different when
downloading from the internet (think man-in-the-middle attacks). Also,
many web sites are switching off HTTP in favor of HTTPS so it could be
that your favorite distro becomes unavailable without it.

Thanks,
-- 
Jerome

> 
> Francesco
> 


[PATCH v2 04/14] net-lwip: add DHCP support and dhcp commmand

2024-05-24 Thread Jerome Forissier
Add what it takes to enable NETDEVICES with NET_LWIP and enable DHCP as
well as the dhcp command.
- net-lwip/net-lwip.c is mostly empty for now. It will provide functions
similar to net/net.c except based on the lwIP stack
- include/net-lwip.h is a replacement for include/net.h which is unused
when NET_LWIP is enabled. Declarations from the latter will be
transferred to the former as needed when new network commands are ported
on top of lwIP.
- CMD_TFTPBOOT is selected by BOOTMETH_EFI due to this code having
an implicit dependency on do_tftpb().

Signed-off-by: Jerome Forissier 
---
 Makefile|   1 +
 boot/Kconfig|   3 +-
 cmd/Kconfig |  26 +
 cmd/Makefile|   4 +
 cmd/net-lwip.c  |  13 +++
 common/board_r.c|   4 +-
 drivers/net/Kconfig |   2 +-
 include/net-lwip.h  |  85 +++
 include/net.h   |   2 +-
 net-lwip/Kconfig|  41 +++-
 net-lwip/Makefile   |  15 +++
 net-lwip/dhcp.c | 105 +++
 net-lwip/eth_internal.h |  35 +++
 net-lwip/net-lwip.c | 224 
 net-lwip/tftp.c |  11 ++
 15 files changed, 564 insertions(+), 7 deletions(-)
 create mode 100644 cmd/net-lwip.c
 create mode 100644 include/net-lwip.h
 create mode 100644 net-lwip/Makefile
 create mode 100644 net-lwip/dhcp.c
 create mode 100644 net-lwip/eth_internal.h
 create mode 100644 net-lwip/net-lwip.c
 create mode 100644 net-lwip/tftp.c

diff --git a/Makefile b/Makefile
index 3df9c45a17c..d59b914071f 100644
--- a/Makefile
+++ b/Makefile
@@ -860,6 +860,7 @@ libs-y += env/
 libs-y += lib/
 libs-y += fs/
 libs-$(CONFIG_NET) += net/
+libs-$(CONFIG_NET_LWIP) += net-lwip/
 libs-y += disk/
 libs-y += drivers/
 libs-$(CONFIG_SYS_FSL_DDR) += drivers/ddr/fsl/
diff --git a/boot/Kconfig b/boot/Kconfig
index 6f3096c15a6..004e69dd92a 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -378,7 +378,7 @@ config BOOT_DEFAULTS_CMDS
select CMD_FAT
select CMD_FS_GENERIC
select CMD_PART if PARTITIONS
-   select CMD_DHCP if CMD_NET
+   select CMD_DHCP if CMD_NET || CMD_NET_LWIP
select CMD_PING if CMD_NET
select CMD_PXE if CMD_NET
select CMD_BOOTI if ARM64
@@ -540,6 +540,7 @@ config BOOTMETH_EXTLINUX_PXE
 config BOOTMETH_EFILOADER
bool "Bootdev support for EFI boot"
depends on EFI_BINARY_EXEC
+   select CMD_TFTPBOOT if CMD_NET_LWIP
default y
help
  Enables support for EFI boot using bootdevs. This makes the
diff --git a/cmd/Kconfig b/cmd/Kconfig
index b026439c773..1bfa528e945 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2084,6 +2084,32 @@ config CMD_WOL
 
 endif
 
+if NET_LWIP
+
+menuconfig CMD_NET_LWIP
+   bool "Network commands (lwIP)"
+   default y
+
+if CMD_NET_LWIP
+
+config CMD_DHCP
+   bool "dhcp"
+   select PROT_DHCP_LWIP
+   help
+ Boot image via network using DHCP/TFTP protocol
+
+config CMD_TFTPBOOT
+   bool "tftp"
+   select PROT_UDP_LWIP
+   default n
+   help
+ tftpboot - load file via network using TFTP protocol
+ Currently a placeholder (not implemented)
+
+endif
+
+endif
+
 menu "Misc commands"
 
 config CMD_2048
diff --git a/cmd/Makefile b/cmd/Makefile
index 87133cc27a8..535b6838ca5 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -128,6 +128,10 @@ endif
 obj-$(CONFIG_CMD_MUX) += mux.o
 obj-$(CONFIG_CMD_NAND) += nand.o
 obj-$(CONFIG_CMD_NET) += net.o
+obj-$(CONFIG_CMD_NET_LWIP) += net-lwip.o
+ifdef CONFIG_CMD_NET_LWIP
+CFLAGS_net-lwip.o := -I$(srctree)/lib/lwip/lwip/src/include 
-I$(srctree)/lib/lwip/u-boot
+endif
 obj-$(CONFIG_ENV_SUPPORT) += nvedit.o
 obj-$(CONFIG_CMD_NVEDIT_EFI) += nvedit_efi.o
 obj-$(CONFIG_CMD_ONENAND) += onenand.o
diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
new file mode 100644
index 000..966d7226eda
--- /dev/null
+++ b/cmd/net-lwip.c
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2024 Linaro Ltd. */
+
+#include 
+#include 
+
+#if defined(CONFIG_CMD_DHCP)
+U_BOOT_CMD(
+dhcp,   3,  1,  do_dhcp,
+"boot image via network using DHCP/TFTP protocol",
+"[loadAddress] [[hostIPaddr:]bootfilename]"
+);
+#endif
diff --git a/common/board_r.c b/common/board_r.c
index da0b80f24ff..6548eb8fdd5 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -472,7 +472,7 @@ static int initr_status_led(void)
 }
 #endif
 
-#ifdef CONFIG_CMD_NET
+#if defined(CONFIG_CMD_NET) || defined(CONFIG_CMD_NET_LWIP)
 static int initr_net(void)
 {
puts("Net:   ");
@@ -727,7 +727,7 @@ static init_fnc_t init_sequence_r[] = {
 #ifdef CONFIG_PCI_ENDPOINT
pci_ep_init,
 #endif
-#ifdef CONFIG_CMD_NET
+#if defined(CONFIG_CMD_NET) || defined(CONFIG_CMD_NET_LWIP)
INIT_FUNC_WATCHDOG_RESET
initr_net,
 #endif
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
i

[PATCH v2 01/14] net: introduce alternative implementation as net-lwip/

2024-05-24 Thread Jerome Forissier
Prepare the introduction of the lwIP (lightweight IP) TCP/IP stack by
adding a new net-lwip/ directory and the NET_LWIP symbol. At this
point, enabling NET_LWIP simply disables NET. Subsequent commits will
introduce the lwIP code, re-work the NETDEVICE integration and port
some of the NET commands and features to lwIP.

SPL_NET cannot be enabled when NET_LWIP=y. SPL_NET pulls some symbols
that are part of NET (such as arp_init(), arp_timeout_check(),
arp_receive(), net_arp_wait_packet_ip()). lwIP support in SPL may be
added later.

Similarly, DFU_TFTP is not compatible with NET_LWIP because it depends
on net_loop(), tftp_timeout_ms, tftp_timeout_count_max. Let's add a
dependency on !NET_LWIP for now.

Signed-off-by: Jerome Forissier 
---
 Kconfig|  2 ++
 Makefile   |  2 +-
 common/Kconfig |  2 +-
 common/spl/Kconfig |  1 +
 drivers/dfu/Kconfig|  2 +-
 drivers/fastboot/Kconfig   |  4 ++--
 drivers/net/phy/Kconfig|  2 +-
 drivers/usb/gadget/Kconfig |  2 +-
 net-lwip/Kconfig   | 15 +++
 net/Kconfig|  1 +
 10 files changed, 26 insertions(+), 7 deletions(-)
 create mode 100644 net-lwip/Kconfig

diff --git a/Kconfig b/Kconfig
index 82df59f176e..758256ab121 100644
--- a/Kconfig
+++ b/Kconfig
@@ -747,6 +747,8 @@ source "env/Kconfig"
 
 source "net/Kconfig"
 
+source "net-lwip/Kconfig"
+
 source "drivers/Kconfig"
 
 source "fs/Kconfig"
diff --git a/Makefile b/Makefile
index 79b28c2d81f..3df9c45a17c 100644
--- a/Makefile
+++ b/Makefile
@@ -859,7 +859,7 @@ libs-$(CONFIG_OF_EMBED) += dts/
 libs-y += env/
 libs-y += lib/
 libs-y += fs/
-libs-y += net/
+libs-$(CONFIG_NET) += net/
 libs-y += disk/
 libs-y += drivers/
 libs-$(CONFIG_SYS_FSL_DDR) += drivers/ddr/fsl/
diff --git a/common/Kconfig b/common/Kconfig
index 5e3070e9253..807b726384d 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -424,7 +424,7 @@ config LOGF_FUNC_PAD
 
 config LOG_SYSLOG
bool "Log output to syslog server"
-   depends on NET
+   depends on NET || NET_LWIP
help
  Enables a log driver which broadcasts log records via UDP port 514
  to syslog servers.
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 6405374bcc1..f67f0a859db 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -1055,6 +1055,7 @@ config SPL_DM_SPI_FLASH
 
 config SPL_NET
bool "Support networking"
+   depends on !NET_LWIP
help
  Enable support for network devices (such as Ethernet) in SPL.
  This permits SPL to load U-Boot over a network link rather than
diff --git a/drivers/dfu/Kconfig b/drivers/dfu/Kconfig
index 0360d9da142..c6bce82eb10 100644
--- a/drivers/dfu/Kconfig
+++ b/drivers/dfu/Kconfig
@@ -11,7 +11,7 @@ config DFU_OVER_USB
 
 config DFU_OVER_TFTP
bool
-   depends on NET
+   depends on NET && !NET_LWIP
 
 if DFU
 config DFU_WRITE_ALT
diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig
index 70207573de2..05e988166fb 100644
--- a/drivers/fastboot/Kconfig
+++ b/drivers/fastboot/Kconfig
@@ -27,7 +27,7 @@ config USB_FUNCTION_FASTBOOT
  This enables the USB part of the fastboot gadget.
 
 config UDP_FUNCTION_FASTBOOT
-   depends on NET
+   depends on NET || NET_LWIP
select FASTBOOT
bool "Enable fastboot protocol over UDP"
help
@@ -41,7 +41,7 @@ config UDP_FUNCTION_FASTBOOT_PORT
  The fastboot protocol requires a UDP port number.
 
 config TCP_FUNCTION_FASTBOOT
-   depends on NET
+   depends on NET || NET_LWIP
select FASTBOOT
bool "Enable fastboot protocol over TCP"
help
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 3d96938eaba..738752d29c2 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -11,7 +11,7 @@ config MV88E6352_SWITCH
 
 menuconfig PHYLIB
bool "Ethernet PHY (physical media interface) support"
-   depends on NET
+   depends on NET || NET_LWIP
help
  Enable Ethernet PHY (physical media interface) support.
 
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 4621a6fd5e6..03fe3bca197 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -224,7 +224,7 @@ endif # USB_GADGET_DOWNLOAD
 
 config USB_ETHER
bool "USB Ethernet Gadget"
-   depends on NET
+   depends on NET || NET_LWIP
default y if ARCH_SUNXI && USB_MUSB_GADGET
help
  Creates an Ethernet network device through a USB peripheral
diff --git a/net-lwip/Kconfig b/net-lwip/Kconfig
new file mode 100644
index 000..f8e0481964f
--- /dev/null
+++ b/net-lwip/Kconfig
@@ -0,0 +1,15 @@
+#
+# Network configuration (with lwIP stack)
+#
+
+menuconfig NET_LWIP
+   bool "Networking support (lwIP stack) -- EXPERIMENTAL&qu

[PATCH v2 14/14] CI: add qemu_arm64_lwip to the test matrix

2024-05-24 Thread Jerome Forissier
Build and run qemu_arm64_lwip_defconfig in CI. This tests the lightweight
IP (lwIP) implementation of the dhcp, tftpboot and ping commands.

Signed-off-by: Jerome Forissier 
---
 .azure-pipelines.yml | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml
index 27f69583c65..b036999210f 100644
--- a/.azure-pipelines.yml
+++ b/.azure-pipelines.yml
@@ -199,6 +199,10 @@ stages:
   cd \${WORK_DIR}
   git config --global --add safe.directory \${WORK_DIR}
   git clone --depth=1 https://source.denx.de/u-boot/u-boot-test-hooks 
/tmp/uboot-test-hooks
+  # qemu_arm64_lwip_defconfig is the same as qemu_arm64 but with 
NET_LWIP enabled.
+  # The test config and the boardenv file from qemu_arm64 can be 
re-used so create symlinks
+  ln -s conf.qemu_arm64_na 
/tmp/uboot-test-hooks/bin/travis-ci/conf.qemu_arm64_lwip_na
+  ln -s u_boot_boardenv_qemu_arm64_na.py 
/tmp/uboot-test-hooks/py/travis-ci/u_boot_boardenv_qemu_arm64_lwip_na.py
   ln -s travis-ci /tmp/uboot-test-hooks/bin/\`hostname\`
   ln -s travis-ci /tmp/uboot-test-hooks/py/\`hostname\`
   grub-mkimage --prefix=\"\" -o ~/grub_x86.efi -O i386-efi normal echo 
lsefimmap lsefi lsefisystab efinet tftp minicmd
@@ -371,6 +375,9 @@ stages:
 qemu_arm64:
   TEST_PY_BD: "qemu_arm64"
   TEST_PY_TEST_SPEC: "not sleep"
+qemu_arm64_lwip:
+  TEST_PY_BD: "qemu_arm64_lwip"
+  TEST_PY_TEST_SPEC: "test_net_dhcp_lwip or test_net_ping_lwip or 
test_net_tftpboot_lwip"
 qemu_m68k:
   TEST_PY_BD: "M5208EVBE"
   TEST_PY_ID: "--id qemu"
-- 
2.40.1



[PATCH v2 13/14] MAINTAINERS: net-lwip: add myself as a maintainer

2024-05-24 Thread Jerome Forissier
Add myself as a maintainer for the lwIP network stack integration code
and network commands. The library code itself (i.e., most files under
lib/lwip/ except README, Makefile and integration files in u-boot) is
unmodified from upstream and therefore does not need a maintainer.

Signed-off-by: Jerome Forissier 
Reviewed-by: Ilias Apalodimas 
---
 MAINTAINERS | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 638b2fdd442..737c73cab34 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1315,6 +1315,17 @@ F:   drivers/net/
 F: include/net.h
 F: net/
 
+NETWORK (LWIP)
+M: Jerome Forissier 
+S: Maintained
+F: cmd/net-lwip.c
+F: configs/qemu_arm64_lwip_defconfig
+F: include/net-lwip.h
+F: lib/lwip/Makefile
+F: lib/lwip/README
+F: lib/lwip/u-boot/
+F: net-lwip/
+
 NIOS
 M: Thomas Chou 
 S: Maintained
-- 
2.40.1



[PATCH v2 12/14] test/py: net: add _lwip variants of dhcp, ping and tftpboot tests

2024-05-24 Thread Jerome Forissier
WHen NET_LWIP is enabled, the dhcp/ping/tftpboot commands are enabled
via CMD_DHCP_LWIP, CMD_PING_LWIP and CMD_TFTPBOOT_LWIP, respectively;
therefore the config annotations in the Python test scripts need to be
cmd_dhcp_lwip, cmd_ping_lwip and cmd_tftpboot_lwip.

The console output of the tftpboot command with lwIP is slightly
different from the non-lwIP implementation. This is taken care of in
test_net_tftpboot().

Signed-off-by: Jerome Forissier 
---
 test/py/tests/test_net.py | 21 +
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/test/py/tests/test_net.py b/test/py/tests/test_net.py
index 038a473b239..ba30780903f 100644
--- a/test/py/tests/test_net.py
+++ b/test/py/tests/test_net.py
@@ -127,6 +127,10 @@ def test_net_dhcp(u_boot_console):
 global net_set_up
 net_set_up = True
 
+@pytest.mark.buildconfigspec('cmd_dhcp_lwip')
+def test_net_dhcp_lwip(u_boot_console):
+test_net_dhcp(u_boot_console)
+
 @pytest.mark.buildconfigspec('cmd_dhcp')
 @pytest.mark.buildconfigspec('cmd_mii')
 def test_net_dhcp_abort(u_boot_console):
@@ -230,6 +234,10 @@ def test_net_ping(u_boot_console):
 output = u_boot_console.run_command('ping $serverip')
 assert 'is alive' in output
 
+@pytest.mark.buildconfigspec('cmd_ping_lwip')
+def test_net_ping_lwip(u_boot_console):
+test_net_ping(u_boot_console)
+
 @pytest.mark.buildconfigspec('IPV6_ROUTER_DISCOVERY')
 def test_net_network_discovery(u_boot_console):
 """Test the network discovery feature of IPv6.
@@ -255,7 +263,7 @@ def test_net_network_discovery(u_boot_console):
 assert ':::::::' not in output
 
 @pytest.mark.buildconfigspec('cmd_net')
-def test_net_tftpboot(u_boot_console):
+def test_net_tftpboot(u_boot_console, lwip = False):
 """Test the tftpboot command.
 
 A file is downloaded from the TFTP server, its size and optionally its
@@ -279,10 +287,11 @@ def test_net_tftpboot(u_boot_console):
 output = u_boot_console.run_command('tftpboot %s' % (fn))
 else:
 output = u_boot_console.run_command('tftpboot %x %s' % (addr, fn))
-expected_text = 'Bytes transferred = '
 sz = f.get('size', None)
-if sz:
-expected_text += '%d' % sz
+if lwip:
+expected_text = f'{sz} bytes transferred'
+else:
+expected_text = f'Bytes transferred = {sz}'
 assert expected_text in output
 
 expected_crc = f.get('crc32', None)
@@ -295,6 +304,10 @@ def test_net_tftpboot(u_boot_console):
 output = u_boot_console.run_command('crc32 $fileaddr $filesize')
 assert expected_crc in output
 
+@pytest.mark.buildconfigspec("cmd_net_lwip")
+def test_net_tftpboot_lwip(u_boot_console):
+test_net_tftpboot(u_boot_console, True)
+
 @pytest.mark.buildconfigspec('cmd_nfs')
 def test_net_nfs(u_boot_console):
 """Test the nfs command.
-- 
2.40.1



[PATCH v2 11/14] configs: add qemu_arm64_lwip_defconfig

2024-05-24 Thread Jerome Forissier
Add qemu_arm64_lwip_defconfig based on qemu_arm64_defconfig but
with NET_LWIP instead of NET. The new file was obtained by doing:

 1. make qemu_arm64_defconfig
 2. make menuconfig
Select NET_LWIP
 3. make savedefconfig
 4. diff -u defconfig configs/qemu_arm64_defconfig
 5. Create configs/qemu_arm64_lwip_defconfig, use #include <> to
inherit from configs/qemu_arm64_defconfig, append
'CONFIG_NET_LWIP=y' and '# CONFIG_DFU_TFTP is not set' to reflect
the diff.

Signed-off-by: Jerome Forissier 
---
 configs/qemu_arm64_lwip_defconfig | 3 +++
 1 file changed, 3 insertions(+)
 create mode 100644 configs/qemu_arm64_lwip_defconfig

diff --git a/configs/qemu_arm64_lwip_defconfig 
b/configs/qemu_arm64_lwip_defconfig
new file mode 100644
index 000..050c93ff97b
--- /dev/null
+++ b/configs/qemu_arm64_lwip_defconfig
@@ -0,0 +1,3 @@
+#include 
+CONFIG_NET_LWIP=y
+# CONFIG_DFU_TFTP is not set
-- 
2.40.1



[PATCH v2 10/14] cmd: bdinfo: enable -e when CONFIG_CMD_NET_LWIP=y

2024-05-24 Thread Jerome Forissier
Support "bdinfo -e" when lwIP is selected.

Signed-off-by: Jerome Forissier 
Reviewed-by: Ilias Apalodimas 
Reviewed-by: Tom Rini 
---
 cmd/bdinfo.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c
index 79106caeec2..690fb894bf6 100644
--- a/cmd/bdinfo.c
+++ b/cmd/bdinfo.c
@@ -152,7 +152,7 @@ static int bdinfo_print_all(struct bd_info *bd)
bdinfo_print_num_l("relocaddr", gd->relocaddr);
bdinfo_print_num_l("reloc off", gd->reloc_off);
printf("%-12s= %u-bit\n", "Build", (uint)sizeof(void *) * 8);
-   if (IS_ENABLED(CONFIG_CMD_NET))
+   if (IS_ENABLED(CONFIG_CMD_NET) || IS_ENABLED(CONFIG_CMD_NET_LWIP))
print_eth();
bdinfo_print_num_l("fdt_blob", (ulong)map_to_sysmem(gd->fdt_blob));
bdinfo_print_num_l("new_fdt", (ulong)map_to_sysmem(gd->new_fdt));
@@ -198,7 +198,8 @@ int do_bdinfo(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[])
case 'a':
return bdinfo_print_all(bd);
case 'e':
-   if (!IS_ENABLED(CONFIG_CMD_NET))
+   if (!IS_ENABLED(CONFIG_CMD_NET) &&
+   !IS_ENABLED(CONFIG_CMD_NET_LWIP))
return CMD_RET_USAGE;
print_eth();
return CMD_RET_SUCCESS;
-- 
2.40.1



[PATCH v2 08/14] net-lwip: add wget command

2024-05-24 Thread Jerome Forissier
Add support for the wget command with NET_LWIP.

About the small change in cmd/efidebug.c: when the wget command based
on the lwIP stack is used the wget command has a built-in URL
validation function since it needs to parse it anyways (in parse_url()).
Therefore wget_validate_uri() doesn't exist. So, guard the call in
efidebug.c with CONFIG_CMD_WGET.

Based on code initially developed by Maxim U.

Signed-off-by: Jerome Forissier 
Co-developed-by: Maxim Uvarov 
Cc: Maxim Uvarov 
---
 cmd/Kconfig|   7 ++
 cmd/Makefile   |   5 +-
 cmd/efidebug.c |   8 +-
 cmd/net-common.c   | 112 
 cmd/net-lwip.c |  12 +++
 cmd/net.c  | 115 -
 include/net-lwip.h |  51 +
 net-lwip/Makefile  |   1 +
 net-lwip/wget.c| 180 +
 9 files changed, 372 insertions(+), 119 deletions(-)
 create mode 100644 cmd/net-common.c
 create mode 100644 net-lwip/wget.c

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 6ef0b52cd34..d9a86540be6 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2117,6 +2117,13 @@ config CMD_TFTPBOOT
help
  tftpboot - load file via network using TFTP protocol
 
+config CMD_WGET
+   bool "wget"
+   select PROT_TCP_LWIP
+   help
+ wget is a simple command to download kernel, or other files,
+ from a http server over TCP.
+
 endif
 
 endif
diff --git a/cmd/Makefile b/cmd/Makefile
index 535b6838ca5..e90f2f68211 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -129,8 +129,11 @@ obj-$(CONFIG_CMD_MUX) += mux.o
 obj-$(CONFIG_CMD_NAND) += nand.o
 obj-$(CONFIG_CMD_NET) += net.o
 obj-$(CONFIG_CMD_NET_LWIP) += net-lwip.o
+obj-$(filter y,$(CONFIG_CMD_NET) $(CONFIG_CMD_NET_LWIP)) += net-common.o
 ifdef CONFIG_CMD_NET_LWIP
-CFLAGS_net-lwip.o := -I$(srctree)/lib/lwip/lwip/src/include 
-I$(srctree)/lib/lwip/u-boot
+lwip-includes := -I$(srctree)/lib/lwip/lwip/src/include 
-I$(srctree)/lib/lwip/u-boot
+CFLAGS_net-lwip.o := $(lwip-includes)
+CFLAGS_net-common.o := $(lwip-includes)
 endif
 obj-$(CONFIG_ENV_SUPPORT) += nvedit.o
 obj-$(CONFIG_CMD_NVEDIT_EFI) += nvedit_efi.o
diff --git a/cmd/efidebug.c b/cmd/efidebug.c
index c2c525f2351..d80e91ecadd 100644
--- a/cmd/efidebug.c
+++ b/cmd/efidebug.c
@@ -741,9 +741,11 @@ static int efi_boot_add_uri(int argc, char *const argv[], 
u16 *var_name16,
if (!label)
return CMD_RET_FAILURE;
 
-   if (!wget_validate_uri(argv[3])) {
-   printf("ERROR: invalid URI\n");
-   return CMD_RET_FAILURE;
+   if (IS_ENABLED(CONFIG_CMD_WGET)) {
+   if (!wget_validate_uri(argv[3])) {
+   printf("ERROR: invalid URI\n");
+   return CMD_RET_FAILURE;
+   }
}
 
efi_create_indexed_name(var_name16, var_name16_size, "Boot", id);
diff --git a/cmd/net-common.c b/cmd/net-common.c
new file mode 100644
index 000..b5dfd2c8866
--- /dev/null
+++ b/cmd/net-common.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, w...@denx.de.
+ */
+
+#include 
+#include 
+#include 
+#ifdef CONFIG_NET
+#include 
+#elif defined CONFIG_NET_LWIP
+#include 
+#else
+#error Either NET or NET_LWIP must be enabled
+#endif
+#include 
+#include 
+
+static int do_net_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const 
argv[])
+{
+   const struct udevice *current = eth_get_dev();
+   unsigned char env_enetaddr[ARP_HLEN];
+   const struct udevice *dev;
+   struct uclass *uc;
+
+   uclass_id_foreach_dev(UCLASS_ETH, dev, uc) {
+   eth_env_get_enetaddr_by_index("eth", dev_seq(dev), 
env_enetaddr);
+   printf("eth%d : %s %pM %s\n", dev_seq(dev), dev->name, 
env_enetaddr,
+  current == dev ? "active" : "");
+   }
+   return CMD_RET_SUCCESS;
+}
+
+static int do_net_stats(struct cmd_tbl *cmdtp, int flag, int argc, char *const 
argv[])
+{
+   int nstats, err, i, off;
+   struct udevice *dev;
+   u64 *values;
+   u8 *strings;
+
+   if (argc < 2)
+   return CMD_RET_USAGE;
+
+   err = uclass_get_device_by_name(UCLASS_ETH, argv[1], );
+   if (err) {
+   printf("Could not find device %s\n", argv[1]);
+   return CMD_RET_FAILURE;
+   }
+
+   if (!eth_get_ops(dev)->get_sset_count ||
+   !eth_get_ops(dev)->get_strings ||
+   !eth_get_ops(dev)->get_stats) {
+   printf("Driver does not implement stats dump!\n");
+   return CMD_RET_FAILURE;
+   }
+
+   nstats = eth_get_ops(dev)->get_sset_count(dev);
+   strings = kcalloc(nstats, ETH_GSTRING_LEN, GFP_KERNEL);
+   if (!strings)
+   return CMD_RET_FAILURE;
+
+   values = kcalloc(nstats, sizeof(u64)

[PATCH v2 09/14] test: dm: dsa, eth: disable tests when CONFIG_NET_LWIP=y

2024-05-24 Thread Jerome Forissier
Some sandbox tests make strong assumptions on how the network stack is
implemented. For example, the ping tests assume that ARP resolution
occurs upon sending out the ICMP packet. This is not always the case
with the lwIP stack which can cache ARP information.
Therefore, disable these tests when CONFIG_NET_LWIP is enabled.

Signed-off-by: Jerome Forissier 
---
 test/dm/dsa.c | 2 ++
 test/dm/eth.c | 4 
 2 files changed, 6 insertions(+)

diff --git a/test/dm/dsa.c b/test/dm/dsa.c
index c857106eaf4..147e2a4afe2 100644
--- a/test/dm/dsa.c
+++ b/test/dm/dsa.c
@@ -59,6 +59,7 @@ static int dm_test_dsa_probe(struct unit_test_state *uts)
 
 DM_TEST(dm_test_dsa_probe, UT_TESTF_SCAN_FDT);
 
+#if !defined(CONFIG_NET_LWIP)
 /* This test sends ping requests with the local address through each DSA port
  * via the sandbox DSA master Eth.
  */
@@ -80,3 +81,4 @@ static int dm_test_dsa(struct unit_test_state *uts)
 }
 
 DM_TEST(dm_test_dsa, UT_TESTF_SCAN_FDT);
+#endif /* !defined(CONFIG_NET_LWIP) */
diff --git a/test/dm/eth.c b/test/dm/eth.c
index bb3dcc6b954..cf97b1c1ab3 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -170,6 +170,7 @@ static int dm_test_ip6_make_lladdr(struct unit_test_state 
*uts)
 DM_TEST(dm_test_ip6_make_lladdr, UT_TESTF_SCAN_FDT);
 #endif
 
+#if !defined(CONFIG_NET_LWIP)
 static int dm_test_eth(struct unit_test_state *uts)
 {
net_ping_ip = string_to_ip("1.1.2.2");
@@ -298,6 +299,7 @@ static int dm_test_eth_act(struct unit_test_state *uts)
return 0;
 }
 DM_TEST(dm_test_eth_act, UT_TESTF_SCAN_FDT);
+#endif /* !CONFIG_NET_LWIP */
 
 /* Ensure that all addresses are loaded properly */
 static int dm_test_ethaddr(struct unit_test_state *uts)
@@ -332,6 +334,7 @@ static int dm_test_ethaddr(struct unit_test_state *uts)
 }
 DM_TEST(dm_test_ethaddr, UT_TESTF_SCAN_FDT);
 
+#if !defined(CONFIG_NET_LWIP)
 /* The asserts include a return on fail; cleanup in the caller */
 static int _dm_test_eth_rotate1(struct unit_test_state *uts)
 {
@@ -616,6 +619,7 @@ static int dm_test_eth_async_ping_reply(struct 
unit_test_state *uts)
 }
 
 DM_TEST(dm_test_eth_async_ping_reply, UT_TESTF_SCAN_FDT);
+#endif /* !CONFIG_NET_LWIP */
 
 #if IS_ENABLED(CONFIG_IPV6_ROUTER_DISCOVERY)
 
-- 
2.40.1



[PATCH v2 07/14] net-lwip: add dns command

2024-05-24 Thread Jerome Forissier
Add CONFIG_CMD_DNS_LWIP depending on CONFIG_NET_LWIP to provide the
dns command using lwIP.

Signed-off-by: Jerome Forissier 
---
 cmd/Kconfig|   6 +++
 cmd/net-lwip.c |   8 
 include/net-lwip.h |   1 +
 net-lwip/Makefile  |   1 +
 net-lwip/dns.c | 107 +
 5 files changed, 123 insertions(+)
 create mode 100644 net-lwip/dns.c

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 07cfe824e3f..6ef0b52cd34 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2098,6 +2098,12 @@ config CMD_DHCP
help
  Boot image via network using DHCP/TFTP protocol
 
+config CMD_DNS
+   bool "dns"
+   select PROT_DNS_LWIP
+   help
+ Lookup the IP of a hostname
+
 config CMD_PING
bool "ping"
select PROT_RAW_LWIP
diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
index 13856703fcf..3abafdf7969 100644
--- a/cmd/net-lwip.c
+++ b/cmd/net-lwip.c
@@ -27,3 +27,11 @@ U_BOOT_CMD(
"[loadAddress] [[hostIPaddr:]bootfilename]"
 );
 #endif
+
+#if defined(CONFIG_CMD_DNS)
+U_BOOT_CMD(
+   dns,3,  1,  do_dns,
+   "lookup the IP of a hostname",
+   "hostname [envvar]"
+);
+#endif
diff --git a/include/net-lwip.h b/include/net-lwip.h
index 2abaaa3b4e3..0019d1524e5 100644
--- a/include/net-lwip.h
+++ b/include/net-lwip.h
@@ -82,6 +82,7 @@ int net_lwip_init(void);
 struct netif *net_lwip_get_netif(void);
 
 int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 
diff --git a/net-lwip/Makefile b/net-lwip/Makefile
index e68d4e24197..aa247859483 100644
--- a/net-lwip/Makefile
+++ b/net-lwip/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth_common.o
 obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth-uclass.o
 obj-$(CONFIG_$(SPL_)DM_ETH) += net-lwip.o
 obj-$(CONFIG_CMD_DHCP) += dhcp.o
+obj-$(CONFIG_CMD_DNS) += dns.o
 obj-$(CONFIG_CMD_PING) += ping.o
 obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
 
diff --git a/net-lwip/dns.c b/net-lwip/dns.c
new file mode 100644
index 000..6ef9d0b510b
--- /dev/null
+++ b/net-lwip/dns.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2024 Linaro Ltd. */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DNS_RESEND_MS 1000
+#define DNS_TIMEOUT_MS 1
+
+static ulong start;
+static ip_addr_t host_ipaddr;
+static bool done;
+
+static void do_dns_tmr(void *arg)
+{
+   dns_tmr();
+}
+
+static void dns_cb(const char *name, const ip_addr_t *ipaddr, void *arg)
+{
+   char *var = (char *)arg;
+   char *ipstr = ip4addr_ntoa(ipaddr);
+
+   done = true;
+
+   if (!ipaddr) {
+   printf("DNS: host not found\n");
+   host_ipaddr.addr = 0;
+   return;
+   }
+
+   if (var)
+   env_set(var, ipstr);
+
+   printf("%s\n", ipstr);
+}
+
+int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+   bool has_server = false;
+   ip_addr_t ipaddr;
+   ip_addr_t ns;
+   char *nsenv;
+   char *name;
+   char *var;
+   int ret;
+
+   if (argc == 1 || argc > 3)
+   return CMD_RET_USAGE;
+
+   if (argc >= 2)
+   name = argv[1];
+
+   if (argc == 3)
+   var = argv[2];
+
+   dns_init();
+
+   nsenv = env_get("dnsip");
+   if (nsenv && ipaddr_aton(nsenv, )) {
+   dns_setserver(0, );
+   has_server = true;
+   }
+
+   nsenv = env_get("dnsip2");
+   if (nsenv && ipaddr_aton(nsenv, )) {
+   dns_setserver(1, );
+   has_server = true;
+   }
+
+   if (!has_server) {
+   log_err("No valid name server (dnsip/dnsip2)\n");
+   return CMD_RET_FAILURE;
+   }
+
+   done = false;
+
+   ret = dns_gethostbyname(name, , dns_cb, var);
+
+   if (ret == ERR_OK) {
+   dns_cb(name, , var);
+   } else if (ret == ERR_INPROGRESS) {
+   start = get_timer(0);
+   sys_timeout(DNS_RESEND_MS, do_dns_tmr, NULL);
+   do {
+   eth_rx();
+   if (done)
+   break;
+   sys_check_timeouts();
+   if (ctrlc()) {
+   printf("\nAbort\n");
+   break;
+   }
+   } while (get_timer(start) < DNS_TIMEOUT_MS);
+   sys_untimeout(do_dns_tmr, NULL);
+   }
+
+   if (done && host_ipaddr.addr != 0)
+   return CMD_RET_SUCCESS;
+
+   return CMD_RET_FAILURE;
+}
+
-- 
2.40.1



[PATCH v2 06/14] net-lwip: add ping command

2024-05-24 Thread Jerome Forissier
Add support for the the ping command with NET_LWIP. The implementation
is derived from lwIP's contrib/apps/ping/ping.c.

Signed-off-by: Jerome Forissier 
---
 boot/Kconfig   |   2 +-
 cmd/Kconfig|   6 ++
 cmd/net-lwip.c |   8 +++
 include/net-lwip.h |   3 +
 net-lwip/Makefile  |   1 +
 net-lwip/ping.c| 171 +
 6 files changed, 190 insertions(+), 1 deletion(-)
 create mode 100644 net-lwip/ping.c

diff --git a/boot/Kconfig b/boot/Kconfig
index 004e69dd92a..983a284ec52 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -379,7 +379,7 @@ config BOOT_DEFAULTS_CMDS
select CMD_FS_GENERIC
select CMD_PART if PARTITIONS
select CMD_DHCP if CMD_NET || CMD_NET_LWIP
-   select CMD_PING if CMD_NET
+   select CMD_PING if CMD_NET || CMD_NET_LWIP
select CMD_PXE if CMD_NET
select CMD_BOOTI if ARM64
select CMD_BOOTZ if ARM && !ARM64
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 94a8de266f6..07cfe824e3f 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2098,6 +2098,12 @@ config CMD_DHCP
help
  Boot image via network using DHCP/TFTP protocol
 
+config CMD_PING
+   bool "ping"
+   select PROT_RAW_LWIP
+   help
+ Send ICMP ECHO_REQUEST to network host
+
 config CMD_TFTPBOOT
bool "tftp"
select PROT_UDP_LWIP
diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
index 490a2e4ac5c..13856703fcf 100644
--- a/cmd/net-lwip.c
+++ b/cmd/net-lwip.c
@@ -12,6 +12,14 @@ U_BOOT_CMD(
 );
 #endif
 
+#if defined(CONFIG_CMD_PING)
+U_BOOT_CMD(
+   ping,   2,  1,  do_ping,
+   "send ICMP ECHO_REQUEST to network host",
+   "pingAddress"
+);
+#endif
+
 #if defined(CONFIG_CMD_TFTPBOOT)
 U_BOOT_CMD(
tftpboot,   3,  0,  do_tftpb,
diff --git a/include/net-lwip.h b/include/net-lwip.h
index 2308703e46b..2abaaa3b4e3 100644
--- a/include/net-lwip.h
+++ b/include/net-lwip.h
@@ -5,6 +5,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -50,6 +51,7 @@ int eth_env_get_enetaddr_by_index(const char *base_name, int 
index,
 int eth_init(void);/* Initialize the device */
 int eth_send(void *packet, int length);   /* Send a packet */
 int eth_rx(void);
+const char *eth_get_name(void);
 int eth_get_dev_index(void);
 int eth_init_state_only(void); /* Set active state */
 void eth_set_current(void);/* set nterface to ethcur var */
@@ -80,6 +82,7 @@ int net_lwip_init(void);
 struct netif *net_lwip_get_netif(void);
 
 int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 
 #endif /* __NET_LWIP_H__ */
diff --git a/net-lwip/Makefile b/net-lwip/Makefile
index a56c32bfa74..e68d4e24197 100644
--- a/net-lwip/Makefile
+++ b/net-lwip/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth_common.o
 obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth-uclass.o
 obj-$(CONFIG_$(SPL_)DM_ETH) += net-lwip.o
 obj-$(CONFIG_CMD_DHCP) += dhcp.o
+obj-$(CONFIG_CMD_PING) += ping.o
 obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
 
 # Disable this warning as it is triggered by:
diff --git a/net-lwip/ping.c b/net-lwip/ping.c
new file mode 100644
index 000..763a9bb1e38
--- /dev/null
+++ b/net-lwip/ping.c
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2024 Linaro Ltd. */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define PING_DELAY_MS 1000
+#define PING_TIMEOUT_MS 1
+/* Additional data size to include in the packet */
+#define PING_DATA_SIZE 32
+/* Ping identifier - must fit on a u16_t */
+#define PING_ID 0xAFAF
+
+static const ip_addr_t *ping_target;
+static struct raw_pcb *ping_pcb;
+static u16_t ping_seq_num;
+static bool ping_target_alive;
+
+static u8_t ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p,
+ const ip_addr_t *addr)
+{
+   struct icmp_echo_hdr *iecho;
+
+   if (addr->addr != ping_target->addr)
+   return 0;
+
+   if ((p->tot_len >= (IP_HLEN + sizeof(struct icmp_echo_hdr))) &&
+   pbuf_remove_header(p, IP_HLEN) == 0) {
+   iecho = (struct icmp_echo_hdr *)p->payload;
+
+   if ((iecho->id == PING_ID) &&
+   (iecho->seqno == lwip_htons(ping_seq_num))) {
+   ping_target_alive = true;
+   printf("host %s is alive\n", ipaddr_ntoa(addr));
+   pbuf_free(p);
+   return 1; /* eat the packet */
+   }
+   /* not eaten, restore original packet */
+   pbuf_add_header(p, IP_HLEN);
+   }
+
+   return 0; /* don't eat the packet */
+}
+
+static int ping_raw_init(vo

[PATCH v2 05/14] net-lwip: add TFTP support and tftpboot command

2024-05-24 Thread Jerome Forissier
Implement do_tftpb().

Signed-off-by: Jerome Forissier 
---
 cmd/Kconfig |   3 +-
 cmd/net-lwip.c  |   8 ++
 net-lwip/dhcp.c |  11 ++-
 net-lwip/tftp.c | 206 +++-
 4 files changed, 223 insertions(+), 5 deletions(-)

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 1bfa528e945..94a8de266f6 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2101,10 +2101,9 @@ config CMD_DHCP
 config CMD_TFTPBOOT
bool "tftp"
select PROT_UDP_LWIP
-   default n
+   default y
help
  tftpboot - load file via network using TFTP protocol
- Currently a placeholder (not implemented)
 
 endif
 
diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
index 966d7226eda..490a2e4ac5c 100644
--- a/cmd/net-lwip.c
+++ b/cmd/net-lwip.c
@@ -11,3 +11,11 @@ U_BOOT_CMD(
 "[loadAddress] [[hostIPaddr:]bootfilename]"
 );
 #endif
+
+#if defined(CONFIG_CMD_TFTPBOOT)
+U_BOOT_CMD(
+   tftpboot,   3,  0,  do_tftpb,
+   "boot image via network using TFTP protocol\n",
+   "[loadAddress] [[hostIPaddr:]bootfilename]"
+);
+#endif
diff --git a/net-lwip/dhcp.c b/net-lwip/dhcp.c
index d1d35999b04..7bacc234f1e 100644
--- a/net-lwip/dhcp.c
+++ b/net-lwip/dhcp.c
@@ -94,11 +94,20 @@ int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char 
*const argv[])
 int dhcp_run(ulong addr, const char *fname, bool autoload)
 {
char *dhcp_argv[] = {"dhcp", NULL, };
+#ifdef CONFIG_CMD_TFTPBOOT
+   char *tftp_argv[] = {"tftpboot", boot_file_name, NULL, };
+#endif
struct cmd_tbl cmdtp = {};  /* dummy */
 
if (autoload) {
-   /* Will be supported when TFTP is added */
+#ifdef CONFIG_CMD_TFTPBOOT
+   /* Assume DHCP was already performed */
+   if (boot_file_name[0])
+   return do_tftpb(, 0, 2, tftp_argv);
+   return 0;
+#else
return -EOPNOTSUPP;
+#endif
}
 
return do_dhcp(, 0, 1, dhcp_argv);
diff --git a/net-lwip/tftp.c b/net-lwip/tftp.c
index 1fa246f55d9..19bf083d995 100644
--- a/net-lwip/tftp.c
+++ b/net-lwip/tftp.c
@@ -2,10 +2,212 @@
 /* Copyright (C) 2024 Linaro Ltd. */
 
 #include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
 #include 
+#include 
+
+static ulong daddr;
+static ulong size;
+static ulong prevsize;
+#define PROGRESS_PRINT_STEP_BYTES (100 * 1024)
+static ulong start_time;
+static enum done_state {
+   NOT_DONE = 0,
+   SUCCESS = 1,
+   FAILURE = 2
+} done;
+
+static void *tftp_open(const char *fname, const char *mode, u8_t is_write)
+{
+   return NULL;
+}
+
+static void tftp_close(void *handle)
+{
+   ulong elapsed;
+
+   if (done == FAILURE) {
+   /* Closing after an error */
+   return;
+   }
+
+   elapsed = get_timer(start_time);
+   done = SUCCESS;
+   log_info("\n%lu bytes transferred in %lu ms (", size,
+get_timer(start_time));
+   print_size(size / elapsed * 1000, "/s)\n");
+
+
+   if (env_set_hex("filesize", size)) {
+   log_err("filesize not updated\n");
+   return;
+   }
+}
+
+static int tftp_read(void *handle, void *buf, int bytes)
+{
+   return 0;
+}
+
+static int tftp_write(void *handle, struct pbuf *p)
+{
+   struct pbuf *q;
+
+   for (q = p; q != NULL; q = q->next) {
+   memcpy((void *)daddr, q->payload, q->len);
+   daddr += q->len;
+   size += q->len;
+   if (size - prevsize > PROGRESS_PRINT_STEP_BYTES) {
+   printf("#");
+   prevsize = size;
+   }
+   }
+
+   return 0;
+}
+
+static void tftp_error(void *handle, int err, const char *msg, int size)
+{
+   char message[100];
+
+   done = FAILURE;
+   memset(message, 0, sizeof(message));
+   memcpy(message, msg, LWIP_MIN(sizeof(message) - 1, (size_t)size));
+
+   log_info("\nTFTP error: %d (%s)\n", err, message);
+}
+
+static const struct tftp_context tftp_context = {
+   tftp_open,
+   tftp_close,
+   tftp_read,
+   tftp_write,
+   tftp_error
+};
+
+static int tftp_run(ulong addr, char *fname, ip_addr_t srvip)
+{
+   void *f = (void *)0x1; /* unused fake file handle*/
+   err_t err;
+
+   if (!fname || addr == 0)
+   return -1;
+
+   done = NOT_DONE;
+   size = 0;
+   prevsize = 0;
+   daddr = addr;
+
+   log_info("TFTP from server %s; our IP address is %s\n",
+ip4addr_ntoa(), env_get("ipaddr"));
+   log_info("Filename '%s'.\n", fname);
+   log_info("Load address: 0x%lx\n", daddr);
+   log_info("Loading: ");
+
+   err = tftp_init_client(_context);
+   if (!(err == ERR_OK || err == ERR_USE))
+

[PATCH v2 03/14] net-lwip: build lwIP

2024-05-24 Thread Jerome Forissier
Build the lwIP library when NET_LWIP is enabled. The following files
are adaptation layers written specially for U-Boot:

 lib/lwip/u-boot/arch/cc.h
 lib/lwip/u-boot/arch/sys_arch.h (empty)
 lib/lwip/u-boot/limits.h (empty)
 lib/lwip/u-boot/lwipopts.h

They were initially contributed by Maxim in a previous RFC patch series.

Signed-off-by: Jerome Forissier 
Co-developed-by: Maxim Uvarov 
Cc: Maxim Uvarov 
---
 lib/Makefile|   2 +
 lib/lwip/Makefile   |  57 +
 lib/lwip/u-boot/arch/cc.h   |  43 +++
 lib/lwip/u-boot/arch/sys_arch.h |   0
 lib/lwip/u-boot/limits.h|   0
 lib/lwip/u-boot/lwipopts.h  | 197 
 net-lwip/Kconfig|   3 +-
 7 files changed, 301 insertions(+), 1 deletion(-)
 create mode 100644 lib/lwip/Makefile
 create mode 100644 lib/lwip/u-boot/arch/cc.h
 create mode 100644 lib/lwip/u-boot/arch/sys_arch.h
 create mode 100644 lib/lwip/u-boot/limits.h
 create mode 100644 lib/lwip/u-boot/lwipopts.h

diff --git a/lib/Makefile b/lib/Makefile
index 2a76acf100d..c35786a0576 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -94,6 +94,8 @@ obj-$(CONFIG_LIBAVB) += libavb/
 obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += libfdt/
 obj-$(CONFIG_$(SPL_TPL_)OF_REAL) += fdtdec_common.o fdtdec.o
 
+obj-$(CONFIG_NET_LWIP) += lwip/
+
 ifdef CONFIG_SPL_BUILD
 obj-$(CONFIG_SPL_YMODEM_SUPPORT) += crc16-ccitt.o
 obj-$(CONFIG_$(SPL_TPL_)HASH) += crc16-ccitt.o
diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile
new file mode 100644
index 000..158e59b91fc
--- /dev/null
+++ b/lib/lwip/Makefile
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2024 Linaro Ltd.
+
+ccflags-y += -I$(srctree)/lib/lwip/lwip/src/include 
-I$(srctree)/lib/lwip/u-boot
+
+obj-y += \
+   lwip/src/api/api_lib.o \
+   lwip/src/api/api_msg.o \
+   lwip/src/api/err.o \
+   lwip/src/api/if_api.o \
+   lwip/src/api/netbuf.o \
+   lwip/src/api/netdb.o \
+   lwip/src/api/netifapi.o \
+   lwip/src/api/sockets.o \
+   lwip/src/api/tcpip.o \
+   lwip/src/apps/http/http_client.o \
+   lwip/src/apps/tftp/tftp.o \
+   lwip/src/core/altcp_alloc.o \
+   lwip/src/core/altcp.o \
+   lwip/src/core/altcp_tcp.o \
+   lwip/src/core/def.o \
+   lwip/src/core/dns.o \
+   lwip/src/core/inet_chksum.o \
+   lwip/src/core/init.o \
+   lwip/src/core/ip.o \
+   lwip/src/core/ipv4/acd.o \
+   lwip/src/core/ipv4/autoip.o \
+   lwip/src/core/ipv4/dhcp.o \
+   lwip/src/core/ipv4/etharp.o \
+   lwip/src/core/ipv4/icmp.o \
+   lwip/src/core/ipv4/igmp.o \
+   lwip/src/core/ipv4/ip4_addr.o \
+   lwip/src/core/ipv4/ip4.o \
+   lwip/src/core/ipv4/ip4_frag.o \
+   lwip/src/core/ipv6/dhcp6.o \
+   lwip/src/core/ipv6/ethip6.o \
+   lwip/src/core/ipv6/icmp6.o \
+   lwip/src/core/ipv6/inet6.o \
+   lwip/src/core/ipv6/ip6_addr.o \
+   lwip/src/core/ipv6/ip6.o \
+   lwip/src/core/ipv6/ip6_frag.o \
+   lwip/src/core/ipv6/mld6.o \
+   lwip/src/core/ipv6/nd6.o \
+   lwip/src/core/mem.o \
+   lwip/src/core/memp.o \
+   lwip/src/core/netif.o \
+   lwip/src/core/pbuf.o \
+   lwip/src/core/raw.o \
+   lwip/src/core/stats.o \
+   lwip/src/core/sys.o \
+   lwip/src/core/tcp.o \
+   lwip/src/core/tcp_in.o \
+   lwip/src/core/tcp_out.o \
+   lwip/src/core/timeouts.o \
+   lwip/src/core/udp.o \
+   lwip/src/netif/ethernet.o
diff --git a/lib/lwip/u-boot/arch/cc.h b/lib/lwip/u-boot/arch/cc.h
new file mode 100644
index 000..31c036dc0c5
--- /dev/null
+++ b/lib/lwip/u-boot/arch/cc.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2023 Linaro Ltd.  */
+
+#ifndef LWIP_ARCH_CC_H
+#define LWIP_ARCH_CC_H
+
+#include 
+#include 
+#include 
+#include 
+
+#define LWIP_ERRNO_INCLUDE 
+
+#define LWIP_ERRNO_STDINCLUDE  1
+#define LWIP_NO_UNISTD_H 1
+#define LWIP_TIMEVAL_PRIVATE 1
+
+#ifdef CONFIG_LIB_RAND
+#define LWIP_RAND() ((u32_t)rand())
+#endif
+
+/* different handling for unit test, normally not needed */
+#ifdef LWIP_NOASSERT_ON_ERROR
+#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \
+   handler; }} while (0)
+#endif
+
+#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS
+
+#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d 
in %s\n", \
+   x, __LINE__, __FILE__); } while (0)
+
+#define atoi(str) (int)dectoul(str, NULL)
+#define lwip_strnstr(a, b)  strnstr(a, b)
+
+#define LWIP_ERR_T int
+#define LWIP_CONST_CAST(target_type, val) ((target_type)((uintptr_t)val))
+
+#if defined(CONFIG_SYS_BIG_ENDIAN)
+#define BYTE_ORDER BIG_ENDIAN
+#endif
+
+#endif /* LWIP_ARCH_CC_H */
diff --git a/lib/lwip/u-boot/arch/sys_arch.h b/lib/lwip/u-boot/arch/sys_arch.h
new file mode 100644
index 000..e69de29bb2d
diff --git a/lib/lwip/u-boot

[PATCH v2 00/14] Introduce the lwIP network stack

2024-05-24 Thread Jerome Forissier
This is a rework of a patch series by Maxim Uvarov: "net/lwip: add lwip
library for the network stack" [1]. The goal is to introduce the lwIP TCP/IP
stack [2] [3] as an alternative to the current implementation in net/,
selectable with Kconfig, and ultimately keep only lwIP if possible. Some
reasons for doing so are:
- Make the support of HTTPS in the wget command easier. Javier T. (CC'd)
has some additional lwIP and Mbed TLS patches to do so. With that it
becomes possible to fetch and launch a distro installer such as Debian
etc. directly from the U-Boot shell.
- Possibly benefit from additional features implemented in lwIP
- Less code to maintain in U-Boot

The first patch introduces a new Kconfig symbol: NET_LWIP, which selects
the lwIP implementation instead of the current one (NET). Contrary to the
approach chosen by Maxim in [1], NET_LWIP and NET cannot be enabled
simultaneously. The rationale is we want to start from a clean state and
not pull potentially duplicated functionality from both stacks. Note
however that a few files are still built in net/, they are the ones
related to ethernet device management and the ethernet bootflow.

The second patch imports the lwIP code as a Git subtree under
lib/lwip/lwip. Some glue code is added under lib/lwip/u-boot.

The third patch introduces the Makefile to build lwIP when
CONFIG_NET_LWIP=y.

The subsequent patches implement various network-oriented commands and
features: dhcp, dns, ping, tftpboot, wget.

NET_LWIP is not enabled by default because it lacks functionality compared
to NET and many CI tests would fail to run or even build.

Some tests (dm dsa/eth) are disabled when NET_LWIP is selected because
they make strong assumptions on how the network stack is implemented and
how the packet flow occurs. For example, an ARP exchange is expected
when an ICMP packet goes out, but with lwIP no exchange will occur if the
host IP is already in the the ARP cache.

Due to the above and in order to provide some level of testing, a new QEMU
configuration is introduced (qemu_arm64_lwip_defconfig) which is the same
as qemu_arm64_lwip_defconfig but with NET_LWIP and CMD_*_LWIP enabled.
Tests are added to test/py/tests/test_net.py for that configuration.

Changes in v2:

** Address comments from Ilias A.

- "net-lwip: add wget command"
Implement the wget_with_dns() function to do most of the wget work and
call it from do_wget(). This allows to simplify patch "net-lwip: add
support for EFI_HTTP_BOOT".

- "net-lwip: import net command from cmd/net.c"
Move a few functions from cmd/net.c to a new file cmd/net-common.c
rather than duplicating then in cmd/net-lwip.c.

- "net-lwip: add support for EFI_HTTP_BOOT"
Since wget_with_dns() is now implemented in "net-lwip: add wget command",
just enable the wget command when the lwIP stack is enabled and
EFI_HTTP_BOOT is requested.

** Address comments from Tom R.

- "net-lwip: add DHCP support and dhcp commmand",
  "net-lwip: add TFTP support and tftpboot command",
  "net-lwip: add ping command",
  "net-lwip: add dns command",
  "net-lwip: add wget command"
Do not introduce new CMD_XXX_LWIP symbols and use existing CMD_XXX
instead.

- "configs: add qemu_arm64_lwip_defconfig"
Use #include .

- "net-lwip: import lwIP library under lib/lwip"
Patch removed and replaced by the introduction of a Git subtree:
"Squashed 'lib/lwip/lwip/' content from commit 0a0452b2c3".

Note that I have not yet addressed your comments on "test: dm: dsa,
eth: disable tests when CONFIG_NET_LWIP=y"). I need some more time
for that and I think running CI on this v2 will help better understand
what is needed for v3.

** Miscellaneous improvements

- "net: introduce alternative implementation as net-lwip/":

* Make DFU_OVER_TFTP not DFU_TFTP incompatible with NET_LWIP. It seems
quite natural to supplement "depends on NET" with "&& !NET_LWIP".
* Make PROT_*_LWIP not visible by removing the Kconfig prompt.


[1] https://lore.kernel.org/all/20231127125726.3735-1-maxim.uva...@linaro.org/
[2] https://www.nongnu.org/lwip/
[3] https://en.wikipedia.org/wiki/LwIP

CC: Javier Tia 

Jerome Forissier (14):
  net: introduce alternative implementation as net-lwip/
  Squashed 'lib/lwip/lwip/' content from commit 0a0452b2c39
  net-lwip: build lwIP
  net-lwip: add DHCP support and dhcp commmand
  net-lwip: add TFTP support and tftpboot command
  net-lwip: add ping command
  net-lwip: add dns command
  net-lwip: add wget command
  test: dm: dsa, eth: disable tests when CONFIG_NET_LWIP=y
  cmd: bdinfo: enable -e when CONFIG_CMD_NET_LWIP=y
  configs: add qemu_arm64_lwip_defconfig
  test/py: net: add _lwip variants of dhcp, ping and tftpboot tests
  MAINTAINERS: net-lwip: add myself as a maintainer
  CI: add qemu_arm64_lwip to the test matrix

-- 
2.40.1


Re: [PATCH 12/15] configs: add qemu_arm64_lwip_defconfig

2024-05-24 Thread Jerome Forissier



On 5/24/24 17:08, Tom Rini wrote:
> On Fri, May 24, 2024 at 12:09:33PM +0200, Jerome Forissier wrote:
>>
>>
>> On 5/23/24 17:02, Tom Rini wrote:
>>> On Wed, May 22, 2024 at 06:00:12PM +0200, Jerome Forissier wrote:
>>>
>>>> Add qemu_arm64_lwip_defconfig which was created from
>>>> qemu_arm64_defconfig with CONFIG_NET_LWIP enabled.
>>>>
>>>> Signed-off-by: Jerome Forissier 
>>>> ---
>>>>  configs/qemu_arm64_lwip_defconfig | 70 +++
>>>>  1 file changed, 70 insertions(+)
>>>>  create mode 100644 configs/qemu_arm64_lwip_defconfig
>>>>
>>>> diff --git a/configs/qemu_arm64_lwip_defconfig 
>>>> b/configs/qemu_arm64_lwip_defconfig
>>>> new file mode 100644
>>>> index 00..c8dadbce37
>>>> --- /dev/null
>>>> +++ b/configs/qemu_arm64_lwip_defconfig
>>>> @@ -0,0 +1,70 @@
>>>> +CONFIG_ARM=y
>>>> +CONFIG_POSITION_INDEPENDENT=y
>>>> +CONFIG_ARCH_QEMU=y
>>>
>>> Setting aside that I would like lwip to default to y, at least in the
>>> first few iterations (so that testing is easier),
>>
>> I could certainly do this. By creating a new defconfig, my goal was to
>> minimize the impacts on existing use cases.
> 
> Yes but then it makes it harder to out of the box see what the deltas
> are.
> 
>>> this should be using
>>> the #include method rather than duplicating the whole config.
>>
>> I've done that for v2. Let me know if you still prefer I change
>> qemu_arm64_defconfig instead.
> 
> This is fine for v2, yeah. Once that's posted I'll grab everything and:
> - Throw it at the small HW lab I have
> - Enable it by default for everyone and throw it at CI

At this point you can expect quite a few failures (unresolved symbols to
begin with) because so many parts of the network-related code peek & poke
various parts of the net implementation without formally depending on NET
(i.e., !NET_LWIP). Some more work is clearly needed to port to lwIP, how
much is probably something the CI run will help understand.

Thanks,
-- 
Jerome

> - Also throw it at my script for world build before/after and using
>   buildman's bloat checker to see what grew how much where.



Re: [PATCH 02/15] net-lwip: import lwIP library under lib/lwip

2024-05-24 Thread Jerome Forissier



On 5/23/24 17:02, Tom Rini wrote:
> On Wed, May 22, 2024 at 06:00:02PM +0200, Jerome Forissier wrote:
> 
>> Import the Lightweight IP (lwIP) library as lib/lwip. The code is built
>> when CONFIG_NET_LWIP=y.
>>
>> The lwIP code was imported with the following commands:
>>
>>  (cd /tmp && git clone https://git.savannah.gnu.org/git/lwip.git -b 
>> STABLE-2_2_0_RELEASE)
>>  mkdir -p lib/lwip
>>  cp -R /tmp/lwip/src/{api,core,include} lib/lwip/
>>  mkdir -p lib/lwip/netif && cp /tmp/lwip/src/netif/ethernet.c lib/lwip/netif/
>>  mkdir -p lib/lwip/apps/tftp && cp /tmp/lwip/src/apps/tftp/tftp.c 
>> lib/lwip/apps/tftp/
>>  mkdir -p lib/lwip/apps/http && cp /tmp/lwip/src/apps/http/http_client.c 
>> lib/lwip/apps/http/
>>
>> The list of object files added to lib/liwip/Makefile was given by:
>>
>>  (cd lib/lwip && find . -name \*.c | sort | sed 's@\./@\t@' | sed 's/\.c$/.o 
>> \\/') >>lib/liwip/Makefile
>>
>> These files are adaptation layers written specially for U-Boot:
>>
>>   lib/lwip/u-boot/arch/cc.h
>>   lib/lwip/u-boot/arch/sys_arch.h (empty)
>>   lib/lwip/u-boot/limits.h (empty)
>>   lib/lwip/u-boot/lwipopts.h
>>
>> They were initially contributed by Maxim in a previous RFC patch series.
>>
>> Signed-off-by: Jerome Forissier 
>> Co-developed-by: Maxim Uvarov 
>> Cc: Maxim Uvarov 
> 
> As I believe I've said before, this needs to be a subtree moving
> forward.
> 

Done in upcoming v2. TBH I don't quite like it because (1) it introduces a merge
commit, (2) interactive rebase becomes difficult (I had to pass --rebase-merges
or the rebase will fail), and (3) I found no way to record the command I
used in the patch description. FYI the command was:
 git subtree add --squash --prefix lib/lwip/lwip \
https://git.savannah.gnu.org/git/lwip.git STABLE-2_2_0_RELEASE

Thanks,
-- 
Jerome



Re: [PATCH 08/15] net-lwip: import net command from cmd/net.c

2024-05-24 Thread Jerome Forissier



On 5/24/24 11:38, Ilias Apalodimas wrote:
> On Wed, 22 May 2024 at 19:04, Jerome Forissier
>  wrote:
>>
>> Add support for "net list" and "net stats" to net-lwip/ by copying the
>> code from cmd/net.c.
>>
>> Signed-off-by: Jerome Forissier 
>> ---
>>  cmd/net-lwip.c | 98 ++
>>  include/net-lwip.h | 50 +++
>>  2 files changed, 148 insertions(+)
>>
>> diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
>> index 2926399bd0..20d0d61176 100644
>> --- a/cmd/net-lwip.c
>> +++ b/cmd/net-lwip.c
>> @@ -2,6 +2,10 @@
>>  /* Copyright (C) 2024 Linaro Ltd. */
>>
>>  #include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>>  #include 
>>
>>  #if defined(CONFIG_CMD_DHCP_LWIP)
>> @@ -43,3 +47,97 @@ U_BOOT_CMD(
>> "[loadAddress] URL"
>>  );
>>  #endif
>> +
>> +static int do_net_list(struct cmd_tbl *cmdtp, int flag, int argc, char 
>> *const argv[])
>> +{
>> +   const struct udevice *current = eth_get_dev();
>> +   unsigned char env_enetaddr[ARP_HLEN];
>> +   const struct udevice *dev;
>> +   struct uclass *uc;
>> +
>> +   uclass_id_foreach_dev(UCLASS_ETH, dev, uc) {
>> +   eth_env_get_enetaddr_by_index("eth", dev_seq(dev), 
>> env_enetaddr);
>> +   printf("eth%d : %s %pM %s\n", dev_seq(dev), dev->name, 
>> env_enetaddr,
>> +  current == dev ? "active" : "");
>> +   }
>> +   return CMD_RET_SUCCESS;
>> +}
>> +
> 
> Some of these functions seem to be a c/p from cmd/net.c
> Carve the common ones out in cmd/net-common.c and reuse them please

Totally makes sense. Done in upcoming v2.

-- 
Jerome

> 
> [...]
> 
> Cheers
> /Ilias


Re: [PATCH 03/15] net-lwip: add DHCP support and dhcp commmand

2024-05-24 Thread Jerome Forissier



On 5/23/24 17:02, Tom Rini wrote:
> On Wed, May 22, 2024 at 06:00:03PM +0200, Jerome Forissier wrote:
> 
>> Add what it takes to enable CONFIG_NETDEVICES with CONFIG_NET_LWIP and
>> enable DHCP as well as the dhcp command (CONFIG_CMD_DHCP_LWIP).
>> - net-lwip/net-lwip.c is mostly empty for now. It will provide functions
>> similar to net/net.c except based on the lwIP stack
>> - include/net-lwip.h is a replacement for include/net.h which is unused
>> when CONFIG_NET_LWIP is enabled. Declarations from the latter will be
>> transferred to the former as needed when new network commands are ported
>> on top of lwIP.
>> - CONFIG_CMD_TFTPBOOT_LWIP is introduced due to CONFIG_BOOTMETH_EFI having
>> an implicit dependency on do_tftpb().
>>
>> Signed-off-by: Jerome Forissier 
> 
> I don't like a new symbol for re-implementing each command. To me, the
> user should pick lwIP or traditional stack, and CMD_DHCP gives the DHCP
> command and so forth, and so the Makefile gets reworked as needed.

Done for v2, thanks.

-- 
Jerome


Re: [PATCH 12/15] configs: add qemu_arm64_lwip_defconfig

2024-05-24 Thread Jerome Forissier



On 5/23/24 17:02, Tom Rini wrote:
> On Wed, May 22, 2024 at 06:00:12PM +0200, Jerome Forissier wrote:
> 
>> Add qemu_arm64_lwip_defconfig which was created from
>> qemu_arm64_defconfig with CONFIG_NET_LWIP enabled.
>>
>> Signed-off-by: Jerome Forissier 
>> ---
>>  configs/qemu_arm64_lwip_defconfig | 70 +++
>>  1 file changed, 70 insertions(+)
>>  create mode 100644 configs/qemu_arm64_lwip_defconfig
>>
>> diff --git a/configs/qemu_arm64_lwip_defconfig 
>> b/configs/qemu_arm64_lwip_defconfig
>> new file mode 100644
>> index 00..c8dadbce37
>> --- /dev/null
>> +++ b/configs/qemu_arm64_lwip_defconfig
>> @@ -0,0 +1,70 @@
>> +CONFIG_ARM=y
>> +CONFIG_POSITION_INDEPENDENT=y
>> +CONFIG_ARCH_QEMU=y
> 
> Setting aside that I would like lwip to default to y, at least in the
> first few iterations (so that testing is easier),

I could certainly do this. By creating a new defconfig, my goal was to
minimize the impacts on existing use cases.

> this should be using
> the #include method rather than duplicating the whole config.

I've done that for v2. Let me know if you still prefer I change
qemu_arm64_defconfig instead.

Thanks,
-- 
Jerome


Re: [PATCH 09/15] net-lwip: add support for EFI_HTTP_BOOT

2024-05-23 Thread Jerome Forissier



On 5/22/24 20:19, Ilias Apalodimas wrote:
> Hi Jerome,
> 
> On Wed, 22 May 2024 at 19:04, Jerome Forissier
>  wrote:
>>
>> Implement the wget_with_dns() function which is needed by
>> CONFIG_EFI_HTTP_BOOT=y. Note that there is no dependency added on
>> CONFIG_CMD_DNS_LWIP because CONFIG_CMD_WGET_LWIP natively supports
>> hostname resolution.
>>
>> Signed-off-by: Jerome Forissier 
>> ---
>>  lib/efi_loader/Kconfig |  5 +++--
>>  net-lwip/wget.c| 16 
>>  2 files changed, 19 insertions(+), 2 deletions(-)
>>
>> diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
>> index 430bb7f0f7..9d8dc8c756 100644
>> --- a/lib/efi_loader/Kconfig
>> +++ b/lib/efi_loader/Kconfig
>> @@ -505,8 +505,9 @@ config EFI_RISCV_BOOT_PROTOCOL
>>
>>  config EFI_HTTP_BOOT
>> bool "EFI HTTP Boot support"
>> -   select CMD_DNS
>> -   select CMD_WGET
>> +   select CMD_DNS if NET
>> +   select CMD_WGET if NET
>> +   select CMD_WGET_LWIP if NET_LWIP
>> select BLKMAP
>> help
>>   Enabling this option adds EFI HTTP Boot support. It allows to
>> diff --git a/net-lwip/wget.c b/net-lwip/wget.c
>> index 0ed8b77c47..a3e65dc80e 100644
>> --- a/net-lwip/wget.c
>> +++ b/net-lwip/wget.c
>> @@ -166,3 +166,19 @@ int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, 
>> char * const argv[])
>>
>> return CMD_RET_FAILURE;
>>  }
>> +
>> +#if defined(CONFIG_EFI_HTTP_BOOT)
>> +int wget_with_dns(ulong dst_addr, char *uri)
>> +{
>> +   char addr_str[11];
>> +   struct cmd_tbl cmdtp = {};
>> +   char *argv[] = { "wget", addr_str, uri };
>> +
>> +   snprintf(addr_str, sizeof(addr_str), "0x%lx", dst_addr);
>> +
>> +   if (do_wget(, 0, ARRAY_SIZE(argv), argv) == CMD_RET_SUCCESS)
>> +   return 0;
>> +
> 
> Calling a command directly feels a bit weird.
> Can we do this instead:
> - Split do_wget in patch #7 and carve out 2 functions. The first will
> prepare the arguments and the second will call httpc_get_file_dns()
> and run the loop
> - Once that's split you can use the newly split function here and
> avoid calling a command

Addressed in next version. I have implemented wget_with_dns() in patch #7
to that #9 doesn't need to add any code. And do_wget() simply calls
wget_with_dns().

Thanks.
-- 
Jerome

> 
> Thanks
> /Ilias
>> +   return -1;
>> +}
>> +#endif
>> --
>> 2.40.1
>>


Re: [PATCH 10/15] test: dm: dsa, eth: disable tests when CONFIG_NET_LWIP=y

2024-05-22 Thread Jerome Forissier



On 5/22/24 20:07, Ilias Apalodimas wrote:
> Hi Jerome,
> 
> On Wed, 22 May 2024 at 19:04, Jerome Forissier
>  wrote:
>>
>> Some sandbox tests make strong assumptions on how the network stack is
>> implemented. For example, the ping tests assume that ARP resolution
>> occurs upon sending out the ICMP packet. This is not always the case
>> with the lwIP stack which can cache ARP information.
>> Therefore, disable these tests when CONFIG_NET_LWIP is enabled.
> 
> Is the ARP Caching the only issue?

No, but I don't recall exactly what was wrong in addition to that.

> U-Boot isn't supposed to use the network stack that much, so it might
> be a better idea to disable arp-caching in LWIP (assuming it's
> doable). We might even get a few size of bytes back

If ARP_TABLE_SIZE is 0, there is no caching but in addition to that the
lwIP stack does not work well. For example when requested to send an
ICMP packet to an unknown IP (unknown as in "not yet resolved at the
ethernet level" i.e., ARP) and assuming ARP_TABLE_SIZE is 1, it will
automatically do the ARP request/response then proceed with ICMP send.
However if ARP_TABLE_SIZE is 0, only the ARP resolution occurs and the
ICMP packet won't go out. So I am not sure that 0 is a valid value.

> 
> Cheers
> /Ilias
>>
>> Signed-off-by: Jerome Forissier 
>> ---
>>  test/dm/dsa.c | 2 ++
>>  test/dm/eth.c | 4 
>>  2 files changed, 6 insertions(+)
>>
>> diff --git a/test/dm/dsa.c b/test/dm/dsa.c
>> index c857106eaf..147e2a4afe 100644
>> --- a/test/dm/dsa.c
>> +++ b/test/dm/dsa.c
>> @@ -59,6 +59,7 @@ static int dm_test_dsa_probe(struct unit_test_state *uts)
>>
>>  DM_TEST(dm_test_dsa_probe, UT_TESTF_SCAN_FDT);
>>
>> +#if !defined(CONFIG_NET_LWIP)
>>  /* This test sends ping requests with the local address through each DSA 
>> port
>>   * via the sandbox DSA master Eth.
>>   */
>> @@ -80,3 +81,4 @@ static int dm_test_dsa(struct unit_test_state *uts)
>>  }
>>
>>  DM_TEST(dm_test_dsa, UT_TESTF_SCAN_FDT);
>> +#endif /* !defined(CONFIG_NET_LWIP) */
>> diff --git a/test/dm/eth.c b/test/dm/eth.c
>> index bb3dcc6b95..cf97b1c1ab 100644
>> --- a/test/dm/eth.c
>> +++ b/test/dm/eth.c
>> @@ -170,6 +170,7 @@ static int dm_test_ip6_make_lladdr(struct 
>> unit_test_state *uts)
>>  DM_TEST(dm_test_ip6_make_lladdr, UT_TESTF_SCAN_FDT);
>>  #endif
>>
>> +#if !defined(CONFIG_NET_LWIP)
>>  static int dm_test_eth(struct unit_test_state *uts)
>>  {
>> net_ping_ip = string_to_ip("1.1.2.2");
>> @@ -298,6 +299,7 @@ static int dm_test_eth_act(struct unit_test_state *uts)
>> return 0;
>>  }
>>  DM_TEST(dm_test_eth_act, UT_TESTF_SCAN_FDT);
>> +#endif /* !CONFIG_NET_LWIP */
>>
>>  /* Ensure that all addresses are loaded properly */
>>  static int dm_test_ethaddr(struct unit_test_state *uts)
>> @@ -332,6 +334,7 @@ static int dm_test_ethaddr(struct unit_test_state *uts)
>>  }
>>  DM_TEST(dm_test_ethaddr, UT_TESTF_SCAN_FDT);
>>
>> +#if !defined(CONFIG_NET_LWIP)
>>  /* The asserts include a return on fail; cleanup in the caller */
>>  static int _dm_test_eth_rotate1(struct unit_test_state *uts)
>>  {
>> @@ -616,6 +619,7 @@ static int dm_test_eth_async_ping_reply(struct 
>> unit_test_state *uts)
>>  }
>>
>>  DM_TEST(dm_test_eth_async_ping_reply, UT_TESTF_SCAN_FDT);
>> +#endif /* !CONFIG_NET_LWIP */
>>
>>  #if IS_ENABLED(CONFIG_IPV6_ROUTER_DISCOVERY)
>>
>> --
>> 2.40.1
>>


[PATCH 03/15] net-lwip: add DHCP support and dhcp commmand

2024-05-22 Thread Jerome Forissier
Add what it takes to enable CONFIG_NETDEVICES with CONFIG_NET_LWIP and
enable DHCP as well as the dhcp command (CONFIG_CMD_DHCP_LWIP).
- net-lwip/net-lwip.c is mostly empty for now. It will provide functions
similar to net/net.c except based on the lwIP stack
- include/net-lwip.h is a replacement for include/net.h which is unused
when CONFIG_NET_LWIP is enabled. Declarations from the latter will be
transferred to the former as needed when new network commands are ported
on top of lwIP.
- CONFIG_CMD_TFTPBOOT_LWIP is introduced due to CONFIG_BOOTMETH_EFI having
an implicit dependency on do_tftpb().

Signed-off-by: Jerome Forissier 
---
 Makefile|   1 +
 boot/Kconfig|   2 +
 boot/bootmeth_efi.c |   3 +-
 cmd/Kconfig |  26 
 cmd/Makefile|   4 +
 cmd/net-lwip.c  |  13 ++
 common/board_r.c|   4 +-
 drivers/dfu/Kconfig |   2 +-
 drivers/net/Kconfig |   2 +-
 include/config_distro_bootcmd.h |   2 +-
 include/net-lwip.h  |  85 
 include/net.h   |   2 +-
 net-lwip/Kconfig|  12 +-
 net-lwip/Makefile   |  15 +++
 net-lwip/dhcp.c | 105 +++
 net-lwip/eth_internal.h |  35 +
 net-lwip/net-lwip.c | 224 
 net-lwip/tftp.c |  11 ++
 net/eth_bootdev.c   |   2 +-
 19 files changed, 540 insertions(+), 10 deletions(-)
 create mode 100644 cmd/net-lwip.c
 create mode 100644 include/net-lwip.h
 create mode 100644 net-lwip/Makefile
 create mode 100644 net-lwip/dhcp.c
 create mode 100644 net-lwip/eth_internal.h
 create mode 100644 net-lwip/net-lwip.c
 create mode 100644 net-lwip/tftp.c

diff --git a/Makefile b/Makefile
index 6296ad6f78..6d0ec35cba 100644
--- a/Makefile
+++ b/Makefile
@@ -860,6 +860,7 @@ libs-y += env/
 libs-y += lib/
 libs-y += fs/
 libs-$(CONFIG_NET) += net/
+libs-$(CONFIG_NET_LWIP) += net-lwip/
 libs-y += disk/
 libs-y += drivers/
 libs-$(CONFIG_SYS_FSL_DDR) += drivers/ddr/fsl/
diff --git a/boot/Kconfig b/boot/Kconfig
index 6f3096c15a..649fd454a2 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -381,6 +381,7 @@ config BOOT_DEFAULTS_CMDS
select CMD_DHCP if CMD_NET
select CMD_PING if CMD_NET
select CMD_PXE if CMD_NET
+   select CMD_DHCP_LWIP if CMD_NET_LWIP
select CMD_BOOTI if ARM64
select CMD_BOOTZ if ARM && !ARM64
imply CMD_MII if NET
@@ -540,6 +541,7 @@ config BOOTMETH_EXTLINUX_PXE
 config BOOTMETH_EFILOADER
bool "Bootdev support for EFI boot"
depends on EFI_BINARY_EXEC
+   select CMD_TFTPBOOT_LWIP if CMD_NET_LWIP
default y
help
  Enables support for EFI boot using bootdevs. This makes the
diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c
index aebc5207fc..b12e01d7de 100644
--- a/boot/bootmeth_efi.c
+++ b/boot/bootmeth_efi.c
@@ -70,7 +70,8 @@ static bool bootmeth_uses_network(struct bootflow *bflow)
 {
const struct udevice *media = dev_get_parent(bflow->dev);
 
-   return IS_ENABLED(CONFIG_CMD_DHCP) &&
+   return (IS_ENABLED(CONFIG_CMD_DHCP) ||
+   IS_ENABLED(CONFIG_CMD_DHCP_LWIP)) &&
device_get_uclass_id(media) == UCLASS_ETH;
 }
 
diff --git a/cmd/Kconfig b/cmd/Kconfig
index b026439c77..0ef3189d8c 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2084,6 +2084,32 @@ config CMD_WOL
 
 endif
 
+if NET_LWIP
+
+menuconfig CMD_NET_LWIP
+   bool "Network commands (lwIP)"
+   default y
+
+if CMD_NET_LWIP
+
+config CMD_DHCP_LWIP
+   bool "dhcp"
+   select PROT_DHCP_LWIP
+   help
+ Boot image via network using DHCP/TFTP protocol
+
+config CMD_TFTPBOOT_LWIP
+   bool "tftp"
+   select PROT_UDP_LWIP
+   default n
+   help
+ tftpboot - load file via network using TFTP protocol
+ Currently a placeholder (not implemented)
+
+endif
+
+endif
+
 menu "Misc commands"
 
 config CMD_2048
diff --git a/cmd/Makefile b/cmd/Makefile
index 87133cc27a..c96afac10f 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -128,6 +128,10 @@ endif
 obj-$(CONFIG_CMD_MUX) += mux.o
 obj-$(CONFIG_CMD_NAND) += nand.o
 obj-$(CONFIG_CMD_NET) += net.o
+obj-$(CONFIG_CMD_NET_LWIP) += net-lwip.o
+ifdef CONFIG_CMD_NET_LWIP
+CFLAGS_net-lwip.o := -I$(srctree)/lib/lwip/include -I$(srctree)/lib/lwip/u-boot
+endif
 obj-$(CONFIG_ENV_SUPPORT) += nvedit.o
 obj-$(CONFIG_CMD_NVEDIT_EFI) += nvedit_efi.o
 obj-$(CONFIG_CMD_ONENAND) += onenand.o
diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
new file mode 100644
index 00..c740461c64
--- /dev/null
+++ b/cmd/net-lwip.c
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2024 Linaro Ltd. */
+
+#include 
+#include 
+
+#if defined(CONFIG_CMD_DHCP_LWIP)
+U_BOOT_CMD(
+dhcp,   3,   

[PATCH 01/15] net: introduce alternative implementation as net-lwip/

2024-05-22 Thread Jerome Forissier
Prepare the introduction of the lwIP (lightweight IP) TCP/IP stack by
adding a new net-lwip/ directory and the CONFIG_NET_LWIP symbol. At this
point, enabling CONFIG_NET_LWIP simply disables CONFIG_NET. Subsequent
commits will introduce the lwIP code, re-work the NETDEVICE integration
and port some of the NET commands and features to lwIP.

CONFIG_SPL_NET cannot be enabled when CONFIG_NET_LWIP=y. SPL_NET pulls
some symbols that are part of NET (such as arp_init(),
arp_timeout_check(), arp_receive(), net_arp_wait_packet_ip()).
lwIP support in SPL may be added later.

Signed-off-by: Jerome Forissier 
---
 Kconfig|  2 ++
 Makefile   |  2 +-
 common/Kconfig |  2 +-
 common/spl/Kconfig |  1 +
 drivers/dfu/Kconfig|  2 +-
 drivers/fastboot/Kconfig   |  4 ++--
 drivers/net/phy/Kconfig|  2 +-
 drivers/usb/gadget/Kconfig |  2 +-
 net-lwip/Kconfig   | 15 +++
 net/Kconfig|  1 +
 10 files changed, 26 insertions(+), 7 deletions(-)
 create mode 100644 net-lwip/Kconfig

diff --git a/Kconfig b/Kconfig
index 82df59f176..758256ab12 100644
--- a/Kconfig
+++ b/Kconfig
@@ -747,6 +747,8 @@ source "env/Kconfig"
 
 source "net/Kconfig"
 
+source "net-lwip/Kconfig"
+
 source "drivers/Kconfig"
 
 source "fs/Kconfig"
diff --git a/Makefile b/Makefile
index 44deb339af..6296ad6f78 100644
--- a/Makefile
+++ b/Makefile
@@ -859,7 +859,7 @@ libs-$(CONFIG_OF_EMBED) += dts/
 libs-y += env/
 libs-y += lib/
 libs-y += fs/
-libs-y += net/
+libs-$(CONFIG_NET) += net/
 libs-y += disk/
 libs-y += drivers/
 libs-$(CONFIG_SYS_FSL_DDR) += drivers/ddr/fsl/
diff --git a/common/Kconfig b/common/Kconfig
index 5e3070e925..807b726384 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -424,7 +424,7 @@ config LOGF_FUNC_PAD
 
 config LOG_SYSLOG
bool "Log output to syslog server"
-   depends on NET
+   depends on NET || NET_LWIP
help
  Enables a log driver which broadcasts log records via UDP port 514
  to syslog servers.
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 6405374bcc..f67f0a859d 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -1055,6 +1055,7 @@ config SPL_DM_SPI_FLASH
 
 config SPL_NET
bool "Support networking"
+   depends on !NET_LWIP
help
  Enable support for network devices (such as Ethernet) in SPL.
  This permits SPL to load U-Boot over a network link rather than
diff --git a/drivers/dfu/Kconfig b/drivers/dfu/Kconfig
index 0360d9da14..d331b05993 100644
--- a/drivers/dfu/Kconfig
+++ b/drivers/dfu/Kconfig
@@ -11,7 +11,7 @@ config DFU_OVER_USB
 
 config DFU_OVER_TFTP
bool
-   depends on NET
+   depends on NET || NET_LWIP
 
 if DFU
 config DFU_WRITE_ALT
diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig
index 70207573de..05e988166f 100644
--- a/drivers/fastboot/Kconfig
+++ b/drivers/fastboot/Kconfig
@@ -27,7 +27,7 @@ config USB_FUNCTION_FASTBOOT
  This enables the USB part of the fastboot gadget.
 
 config UDP_FUNCTION_FASTBOOT
-   depends on NET
+   depends on NET || NET_LWIP
select FASTBOOT
bool "Enable fastboot protocol over UDP"
help
@@ -41,7 +41,7 @@ config UDP_FUNCTION_FASTBOOT_PORT
  The fastboot protocol requires a UDP port number.
 
 config TCP_FUNCTION_FASTBOOT
-   depends on NET
+   depends on NET || NET_LWIP
select FASTBOOT
bool "Enable fastboot protocol over TCP"
help
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 3d96938eab..738752d29c 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -11,7 +11,7 @@ config MV88E6352_SWITCH
 
 menuconfig PHYLIB
bool "Ethernet PHY (physical media interface) support"
-   depends on NET
+   depends on NET || NET_LWIP
help
  Enable Ethernet PHY (physical media interface) support.
 
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 4621a6fd5e..03fe3bca19 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -224,7 +224,7 @@ endif # USB_GADGET_DOWNLOAD
 
 config USB_ETHER
bool "USB Ethernet Gadget"
-   depends on NET
+   depends on NET || NET_LWIP
default y if ARCH_SUNXI && USB_MUSB_GADGET
help
  Creates an Ethernet network device through a USB peripheral
diff --git a/net-lwip/Kconfig b/net-lwip/Kconfig
new file mode 100644
index 00..f8e0481964
--- /dev/null
+++ b/net-lwip/Kconfig
@@ -0,0 +1,15 @@
+#
+# Network configuration (with lwIP stack)
+#
+
+menuconfig NET_LWIP
+   bool "Networking support (lwIP stack) -- EXPERIMENTAL"
+   help
+ Include networking support based on the lwIP (lightweight IP)
+ TCP/IP stack (https://nongnu.org/lwip). This is a replacement for
+ the de

[PATCH 15/15] CI: add qemu_arm64_lwip to the test matrix

2024-05-22 Thread Jerome Forissier
Build and run qemu_arm64_lwip_defconfig in CI. This tests the lightweight
IP (lwIP) implementation of the dhcp, tftpboot and ping commands.

Signed-off-by: Jerome Forissier 
---
 .azure-pipelines.yml | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml
index 27f69583c6..b036999210 100644
--- a/.azure-pipelines.yml
+++ b/.azure-pipelines.yml
@@ -199,6 +199,10 @@ stages:
   cd \${WORK_DIR}
   git config --global --add safe.directory \${WORK_DIR}
   git clone --depth=1 https://source.denx.de/u-boot/u-boot-test-hooks 
/tmp/uboot-test-hooks
+  # qemu_arm64_lwip_defconfig is the same as qemu_arm64 but with 
NET_LWIP enabled.
+  # The test config and the boardenv file from qemu_arm64 can be 
re-used so create symlinks
+  ln -s conf.qemu_arm64_na 
/tmp/uboot-test-hooks/bin/travis-ci/conf.qemu_arm64_lwip_na
+  ln -s u_boot_boardenv_qemu_arm64_na.py 
/tmp/uboot-test-hooks/py/travis-ci/u_boot_boardenv_qemu_arm64_lwip_na.py
   ln -s travis-ci /tmp/uboot-test-hooks/bin/\`hostname\`
   ln -s travis-ci /tmp/uboot-test-hooks/py/\`hostname\`
   grub-mkimage --prefix=\"\" -o ~/grub_x86.efi -O i386-efi normal echo 
lsefimmap lsefi lsefisystab efinet tftp minicmd
@@ -371,6 +375,9 @@ stages:
 qemu_arm64:
   TEST_PY_BD: "qemu_arm64"
   TEST_PY_TEST_SPEC: "not sleep"
+qemu_arm64_lwip:
+  TEST_PY_BD: "qemu_arm64_lwip"
+  TEST_PY_TEST_SPEC: "test_net_dhcp_lwip or test_net_ping_lwip or 
test_net_tftpboot_lwip"
 qemu_m68k:
   TEST_PY_BD: "M5208EVBE"
   TEST_PY_ID: "--id qemu"
-- 
2.40.1



[PATCH 14/15] MAINTAINERS: net-lwip: add myself as a maintainer

2024-05-22 Thread Jerome Forissier
Add myself as a maintainer for the lwIP network stack integration code
and network commands. The library code itself (i.e., most files under
lib/lwip/ except README, Makefile and integration files in u-boot) is
unmodified from upstream and therefore does not need a maintainer.

Signed-off-by: Jerome Forissier 
---
 MAINTAINERS | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 7a3b4d3712..0131f89ae3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1311,6 +1311,17 @@ F:   drivers/net/
 F: include/net.h
 F: net/
 
+NETWORK (LWIP)
+M: Jerome Forissier 
+S: Maintained
+F: cmd/net-lwip.c
+F: configs/qemu_arm64_lwip_defconfig
+F: include/net-lwip.h
+F: lib/lwip/Makefile
+F: lib/lwip/README
+F: lib/lwip/u-boot/
+F: net-lwip/
+
 NIOS
 M: Thomas Chou 
 S: Maintained
-- 
2.40.1



[PATCH 13/15] test/py: net: add _lwip variants of dhcp, ping and tftpboot tests

2024-05-22 Thread Jerome Forissier
WHen NET_LWIP is enabled, the dhcp/ping/tftpboot commands are enabled
via CMD_DHCP_LWIP, CMD_PING_LWIP and CMD_TFTPBOOT_LWIP, respectively;
therefore the config annotations in the Python test scripts need to be
cmd_dhcp_lwip, cmd_ping_lwip and cmd_tftpboot_lwip.

The console output of the tftpboot command with lwIP is slightly
different from the non-lwIP implementation. This is taken care of in
test_net_tftpboot().

Signed-off-by: Jerome Forissier 
---
 test/py/tests/test_net.py | 21 +
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/test/py/tests/test_net.py b/test/py/tests/test_net.py
index 038a473b23..ba30780903 100644
--- a/test/py/tests/test_net.py
+++ b/test/py/tests/test_net.py
@@ -127,6 +127,10 @@ def test_net_dhcp(u_boot_console):
 global net_set_up
 net_set_up = True
 
+@pytest.mark.buildconfigspec('cmd_dhcp_lwip')
+def test_net_dhcp_lwip(u_boot_console):
+test_net_dhcp(u_boot_console)
+
 @pytest.mark.buildconfigspec('cmd_dhcp')
 @pytest.mark.buildconfigspec('cmd_mii')
 def test_net_dhcp_abort(u_boot_console):
@@ -230,6 +234,10 @@ def test_net_ping(u_boot_console):
 output = u_boot_console.run_command('ping $serverip')
 assert 'is alive' in output
 
+@pytest.mark.buildconfigspec('cmd_ping_lwip')
+def test_net_ping_lwip(u_boot_console):
+test_net_ping(u_boot_console)
+
 @pytest.mark.buildconfigspec('IPV6_ROUTER_DISCOVERY')
 def test_net_network_discovery(u_boot_console):
 """Test the network discovery feature of IPv6.
@@ -255,7 +263,7 @@ def test_net_network_discovery(u_boot_console):
 assert ':::::::' not in output
 
 @pytest.mark.buildconfigspec('cmd_net')
-def test_net_tftpboot(u_boot_console):
+def test_net_tftpboot(u_boot_console, lwip = False):
 """Test the tftpboot command.
 
 A file is downloaded from the TFTP server, its size and optionally its
@@ -279,10 +287,11 @@ def test_net_tftpboot(u_boot_console):
 output = u_boot_console.run_command('tftpboot %s' % (fn))
 else:
 output = u_boot_console.run_command('tftpboot %x %s' % (addr, fn))
-expected_text = 'Bytes transferred = '
 sz = f.get('size', None)
-if sz:
-expected_text += '%d' % sz
+if lwip:
+expected_text = f'{sz} bytes transferred'
+else:
+expected_text = f'Bytes transferred = {sz}'
 assert expected_text in output
 
 expected_crc = f.get('crc32', None)
@@ -295,6 +304,10 @@ def test_net_tftpboot(u_boot_console):
 output = u_boot_console.run_command('crc32 $fileaddr $filesize')
 assert expected_crc in output
 
+@pytest.mark.buildconfigspec("cmd_net_lwip")
+def test_net_tftpboot_lwip(u_boot_console):
+test_net_tftpboot(u_boot_console, True)
+
 @pytest.mark.buildconfigspec('cmd_nfs')
 def test_net_nfs(u_boot_console):
 """Test the nfs command.
-- 
2.40.1



[PATCH 12/15] configs: add qemu_arm64_lwip_defconfig

2024-05-22 Thread Jerome Forissier
Add qemu_arm64_lwip_defconfig which was created from
qemu_arm64_defconfig with CONFIG_NET_LWIP enabled.

Signed-off-by: Jerome Forissier 
---
 configs/qemu_arm64_lwip_defconfig | 70 +++
 1 file changed, 70 insertions(+)
 create mode 100644 configs/qemu_arm64_lwip_defconfig

diff --git a/configs/qemu_arm64_lwip_defconfig 
b/configs/qemu_arm64_lwip_defconfig
new file mode 100644
index 00..c8dadbce37
--- /dev/null
+++ b/configs/qemu_arm64_lwip_defconfig
@@ -0,0 +1,70 @@
+CONFIG_ARM=y
+CONFIG_POSITION_INDEPENDENT=y
+CONFIG_ARCH_QEMU=y
+CONFIG_SYS_MALLOC_LEN=0x100
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x4020
+CONFIG_ENV_SIZE=0x4
+CONFIG_ENV_SECT_SIZE=0x4
+CONFIG_DEFAULT_DEVICE_TREE="qemu-arm64"
+CONFIG_DEBUG_UART_BASE=0x900
+CONFIG_DEBUG_UART_CLOCK=0
+CONFIG_ARMV8_CRYPTO=y
+CONFIG_SYS_LOAD_ADDR=0x4020
+CONFIG_ENV_ADDR=0x400
+CONFIG_PCI=y
+CONFIG_DEBUG_UART=y
+CONFIG_AHCI=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_FIT_BEST_MATCH=y
+CONFIG_BOOTSTD_FULL=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
+CONFIG_USE_PREBOOT=y
+# CONFIG_DISPLAY_CPUINFO is not set
+# CONFIG_DISPLAY_BOARDINFO is not set
+CONFIG_PCI_INIT_R=y
+CONFIG_CMD_SMBIOS=y
+CONFIG_CMD_BOOTZ=y
+CONFIG_CMD_BOOTEFI_SELFTEST=y
+CONFIG_CMD_NVEDIT_EFI=y
+CONFIG_CMD_DFU=y
+CONFIG_CMD_MTD=y
+CONFIG_CMD_PCI=y
+CONFIG_CMD_TPM=y
+CONFIG_CMD_MTDPARTS=y
+CONFIG_ENV_IS_IN_FLASH=y
+CONFIG_NET_LWIP=y
+CONFIG_SCSI_AHCI=y
+CONFIG_AHCI_PCI=y
+CONFIG_DFU_MTD=y
+CONFIG_DFU_RAM=y
+# CONFIG_MMC is not set
+CONFIG_MTD=y
+CONFIG_DM_MTD=y
+CONFIG_MTD_NOR_FLASH=y
+CONFIG_FLASH_SHOW_PROGRESS=0
+CONFIG_CFI_FLASH=y
+CONFIG_CFI_FLASH_USE_WEAK_ACCESSORS=y
+CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y
+CONFIG_FLASH_CFI_MTD=y
+CONFIG_SYS_FLASH_CFI=y
+CONFIG_SYS_MAX_FLASH_SECT=256
+CONFIG_SYS_MAX_FLASH_BANKS=2
+CONFIG_SYS_MAX_FLASH_BANKS_DETECT=y
+CONFIG_E1000=y
+CONFIG_NVME_PCI=y
+CONFIG_PCIE_ECAM_GENERIC=y
+CONFIG_SCSI=y
+CONFIG_DEBUG_UART_PL011=y
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYSRESET=y
+CONFIG_SYSRESET_CMD_POWEROFF=y
+CONFIG_SYSRESET_PSCI=y
+CONFIG_TPM2_MMIO=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_PCI=y
+CONFIG_SEMIHOSTING=y
+CONFIG_TPM=y
-- 
2.40.1



[PATCH 11/15] cmd: bdinfo: enable -e when CONFIG_CMD_NET_LWIP=y

2024-05-22 Thread Jerome Forissier
Support "bdinfo -e" when lwIP is selected.

Signed-off-by: Jerome Forissier 
---
 cmd/bdinfo.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c
index 79106caeec..690fb894bf 100644
--- a/cmd/bdinfo.c
+++ b/cmd/bdinfo.c
@@ -152,7 +152,7 @@ static int bdinfo_print_all(struct bd_info *bd)
bdinfo_print_num_l("relocaddr", gd->relocaddr);
bdinfo_print_num_l("reloc off", gd->reloc_off);
printf("%-12s= %u-bit\n", "Build", (uint)sizeof(void *) * 8);
-   if (IS_ENABLED(CONFIG_CMD_NET))
+   if (IS_ENABLED(CONFIG_CMD_NET) || IS_ENABLED(CONFIG_CMD_NET_LWIP))
print_eth();
bdinfo_print_num_l("fdt_blob", (ulong)map_to_sysmem(gd->fdt_blob));
bdinfo_print_num_l("new_fdt", (ulong)map_to_sysmem(gd->new_fdt));
@@ -198,7 +198,8 @@ int do_bdinfo(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[])
case 'a':
return bdinfo_print_all(bd);
case 'e':
-   if (!IS_ENABLED(CONFIG_CMD_NET))
+   if (!IS_ENABLED(CONFIG_CMD_NET) &&
+   !IS_ENABLED(CONFIG_CMD_NET_LWIP))
return CMD_RET_USAGE;
print_eth();
return CMD_RET_SUCCESS;
-- 
2.40.1



[PATCH 10/15] test: dm: dsa, eth: disable tests when CONFIG_NET_LWIP=y

2024-05-22 Thread Jerome Forissier
Some sandbox tests make strong assumptions on how the network stack is
implemented. For example, the ping tests assume that ARP resolution
occurs upon sending out the ICMP packet. This is not always the case
with the lwIP stack which can cache ARP information.
Therefore, disable these tests when CONFIG_NET_LWIP is enabled.

Signed-off-by: Jerome Forissier 
---
 test/dm/dsa.c | 2 ++
 test/dm/eth.c | 4 
 2 files changed, 6 insertions(+)

diff --git a/test/dm/dsa.c b/test/dm/dsa.c
index c857106eaf..147e2a4afe 100644
--- a/test/dm/dsa.c
+++ b/test/dm/dsa.c
@@ -59,6 +59,7 @@ static int dm_test_dsa_probe(struct unit_test_state *uts)
 
 DM_TEST(dm_test_dsa_probe, UT_TESTF_SCAN_FDT);
 
+#if !defined(CONFIG_NET_LWIP)
 /* This test sends ping requests with the local address through each DSA port
  * via the sandbox DSA master Eth.
  */
@@ -80,3 +81,4 @@ static int dm_test_dsa(struct unit_test_state *uts)
 }
 
 DM_TEST(dm_test_dsa, UT_TESTF_SCAN_FDT);
+#endif /* !defined(CONFIG_NET_LWIP) */
diff --git a/test/dm/eth.c b/test/dm/eth.c
index bb3dcc6b95..cf97b1c1ab 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -170,6 +170,7 @@ static int dm_test_ip6_make_lladdr(struct unit_test_state 
*uts)
 DM_TEST(dm_test_ip6_make_lladdr, UT_TESTF_SCAN_FDT);
 #endif
 
+#if !defined(CONFIG_NET_LWIP)
 static int dm_test_eth(struct unit_test_state *uts)
 {
net_ping_ip = string_to_ip("1.1.2.2");
@@ -298,6 +299,7 @@ static int dm_test_eth_act(struct unit_test_state *uts)
return 0;
 }
 DM_TEST(dm_test_eth_act, UT_TESTF_SCAN_FDT);
+#endif /* !CONFIG_NET_LWIP */
 
 /* Ensure that all addresses are loaded properly */
 static int dm_test_ethaddr(struct unit_test_state *uts)
@@ -332,6 +334,7 @@ static int dm_test_ethaddr(struct unit_test_state *uts)
 }
 DM_TEST(dm_test_ethaddr, UT_TESTF_SCAN_FDT);
 
+#if !defined(CONFIG_NET_LWIP)
 /* The asserts include a return on fail; cleanup in the caller */
 static int _dm_test_eth_rotate1(struct unit_test_state *uts)
 {
@@ -616,6 +619,7 @@ static int dm_test_eth_async_ping_reply(struct 
unit_test_state *uts)
 }
 
 DM_TEST(dm_test_eth_async_ping_reply, UT_TESTF_SCAN_FDT);
+#endif /* !CONFIG_NET_LWIP */
 
 #if IS_ENABLED(CONFIG_IPV6_ROUTER_DISCOVERY)
 
-- 
2.40.1



[PATCH 09/15] net-lwip: add support for EFI_HTTP_BOOT

2024-05-22 Thread Jerome Forissier
Implement the wget_with_dns() function which is needed by
CONFIG_EFI_HTTP_BOOT=y. Note that there is no dependency added on
CONFIG_CMD_DNS_LWIP because CONFIG_CMD_WGET_LWIP natively supports
hostname resolution.

Signed-off-by: Jerome Forissier 
---
 lib/efi_loader/Kconfig |  5 +++--
 net-lwip/wget.c| 16 
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index 430bb7f0f7..9d8dc8c756 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -505,8 +505,9 @@ config EFI_RISCV_BOOT_PROTOCOL
 
 config EFI_HTTP_BOOT
bool "EFI HTTP Boot support"
-   select CMD_DNS
-   select CMD_WGET
+   select CMD_DNS if NET
+   select CMD_WGET if NET
+   select CMD_WGET_LWIP if NET_LWIP
select BLKMAP
help
  Enabling this option adds EFI HTTP Boot support. It allows to
diff --git a/net-lwip/wget.c b/net-lwip/wget.c
index 0ed8b77c47..a3e65dc80e 100644
--- a/net-lwip/wget.c
+++ b/net-lwip/wget.c
@@ -166,3 +166,19 @@ int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, 
char * const argv[])
 
return CMD_RET_FAILURE;
 }
+
+#if defined(CONFIG_EFI_HTTP_BOOT)
+int wget_with_dns(ulong dst_addr, char *uri)
+{
+   char addr_str[11];
+   struct cmd_tbl cmdtp = {};
+   char *argv[] = { "wget", addr_str, uri };
+
+   snprintf(addr_str, sizeof(addr_str), "0x%lx", dst_addr);
+
+   if (do_wget(, 0, ARRAY_SIZE(argv), argv) == CMD_RET_SUCCESS)
+   return 0;
+
+   return -1;
+}
+#endif
-- 
2.40.1



[PATCH 08/15] net-lwip: import net command from cmd/net.c

2024-05-22 Thread Jerome Forissier
Add support for "net list" and "net stats" to net-lwip/ by copying the
code from cmd/net.c.

Signed-off-by: Jerome Forissier 
---
 cmd/net-lwip.c | 98 ++
 include/net-lwip.h | 50 +++
 2 files changed, 148 insertions(+)

diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
index 2926399bd0..20d0d61176 100644
--- a/cmd/net-lwip.c
+++ b/cmd/net-lwip.c
@@ -2,6 +2,10 @@
 /* Copyright (C) 2024 Linaro Ltd. */
 
 #include 
+#include 
+#include 
+#include 
+#include 
 #include 
 
 #if defined(CONFIG_CMD_DHCP_LWIP)
@@ -43,3 +47,97 @@ U_BOOT_CMD(
"[loadAddress] URL"
 );
 #endif
+
+static int do_net_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const 
argv[])
+{
+   const struct udevice *current = eth_get_dev();
+   unsigned char env_enetaddr[ARP_HLEN];
+   const struct udevice *dev;
+   struct uclass *uc;
+
+   uclass_id_foreach_dev(UCLASS_ETH, dev, uc) {
+   eth_env_get_enetaddr_by_index("eth", dev_seq(dev), 
env_enetaddr);
+   printf("eth%d : %s %pM %s\n", dev_seq(dev), dev->name, 
env_enetaddr,
+  current == dev ? "active" : "");
+   }
+   return CMD_RET_SUCCESS;
+}
+
+static int do_net_stats(struct cmd_tbl *cmdtp, int flag, int argc, char *const 
argv[])
+{
+   int nstats, err, i, off;
+   struct udevice *dev;
+   u64 *values;
+   u8 *strings;
+
+   if (argc < 2)
+   return CMD_RET_USAGE;
+
+   err = uclass_get_device_by_name(UCLASS_ETH, argv[1], );
+   if (err) {
+   printf("Could not find device %s\n", argv[1]);
+   return CMD_RET_FAILURE;
+   }
+
+   if (!eth_get_ops(dev)->get_sset_count ||
+   !eth_get_ops(dev)->get_strings ||
+   !eth_get_ops(dev)->get_stats) {
+   printf("Driver does not implement stats dump!\n");
+   return CMD_RET_FAILURE;
+   }
+
+   nstats = eth_get_ops(dev)->get_sset_count(dev);
+   strings = kcalloc(nstats, ETH_GSTRING_LEN, GFP_KERNEL);
+   if (!strings)
+   return CMD_RET_FAILURE;
+
+   values = kcalloc(nstats, sizeof(u64), GFP_KERNEL);
+   if (!values)
+   goto err_free_strings;
+
+   eth_get_ops(dev)->get_strings(dev, strings);
+   eth_get_ops(dev)->get_stats(dev, values);
+
+   off = 0;
+   for (i = 0; i < nstats; i++) {
+   printf("  %s: %llu\n", [off], values[i]);
+   off += ETH_GSTRING_LEN;
+   };
+
+   return CMD_RET_SUCCESS;
+
+err_free_strings:
+   kfree(strings);
+
+   return CMD_RET_FAILURE;
+}
+
+static struct cmd_tbl cmd_net[] = {
+   U_BOOT_CMD_MKENT(list, 1, 0, do_net_list, "", ""),
+   U_BOOT_CMD_MKENT(stats, 2, 0, do_net_stats, "", ""),
+};
+
+static int do_net(struct cmd_tbl *cmdtp, int flag, int argc, char *const 
argv[])
+{
+   struct cmd_tbl *cp;
+
+   cp = find_cmd_tbl(argv[1], cmd_net, ARRAY_SIZE(cmd_net));
+
+   /* Drop the net command */
+   argc--;
+   argv++;
+
+   if (!cp || argc > cp->maxargs)
+   return CMD_RET_USAGE;
+   if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
+   return CMD_RET_SUCCESS;
+
+   return cp->cmd(cmdtp, flag, argc, argv);
+}
+
+U_BOOT_CMD(
+   net, 3, 1, do_net,
+   "NET sub-system",
+   "list - list available devices\n"
+   "stats  - dump statistics for specified device\n"
+);
diff --git a/include/net-lwip.h b/include/net-lwip.h
index 23ad70fc09..6fda940fec 100644
--- a/include/net-lwip.h
+++ b/include/net-lwip.h
@@ -51,6 +51,56 @@ int eth_env_get_enetaddr_by_index(const char *base_name, int 
index,
 int eth_init(void);/* Initialize the device */
 int eth_send(void *packet, int length);   /* Send a packet */
 int eth_rx(void);
+
+/**
+ * struct eth_ops - functions of Ethernet MAC controllers
+ *
+ * start: Prepare the hardware to send and receive packets
+ * send: Send the bytes passed in "packet" as a packet on the wire
+ * recv: Check if the hardware received a packet. If so, set the pointer to the
+ *  packet buffer in the packetp parameter. If not, return an error or 0 to
+ *  indicate that the hardware receive FIFO is empty. If 0 is returned, the
+ *  network stack will not process the empty packet, but free_pkt() will be
+ *  called if supplied
+ * free_pkt: Give the driver an opportunity to manage its packet buffer memory
+ *  when the network stack is finished processing it. This will only be
+ *  called when no error was returned from recv - optional
+ * stop: Stop the hardware from looking for packets - may be called even if
+ *  state == PASSIVE
+ * mcast: Join or leave a multicast group (for TFT

[PATCH 07/15] net-lwip: add wget command

2024-05-22 Thread Jerome Forissier
Add CONFIG_CMD_WGET_LWIP depending on CONFIG_NET_LWIP to provide the
wget command using the lightweight IP stack.

About the small change in cmd/efidebug.c: when the wget command based
on the lwIP stack is used (CONFIG_CMD_WGET_LWIP=y) the wget command
has a built-in URL validation function since it needs to parse it
anyways (in parse_url()). Therefore wget_validate_uri() doesn't exist.
So, guard the call in efidebug.c with CONFIG_CMD_WGET.

Based on code initially developed by Maxim U.

Signed-off-by: Jerome Forissier 
Co-developed-by: Maxim Uvarov 
Cc: Maxim Uvarov 
---
 cmd/Kconfig|   7 ++
 cmd/efidebug.c |   8 ++-
 cmd/net-lwip.c |   8 +++
 include/net-lwip.h |   1 +
 net-lwip/Makefile  |   1 +
 net-lwip/wget.c| 168 +
 6 files changed, 190 insertions(+), 3 deletions(-)
 create mode 100644 net-lwip/wget.c

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 1aba10b14c..3c6292654d 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2117,6 +2117,13 @@ config CMD_TFTPBOOT_LWIP
help
  tftpboot - load file via network using TFTP protocol
 
+config CMD_WGET_LWIP
+   bool "wget"
+   select PROT_TCP_LWIP
+   help
+ wget is a simple command to download kernel, or other files,
+ from a http server over TCP.
+
 endif
 
 endif
diff --git a/cmd/efidebug.c b/cmd/efidebug.c
index c2c525f235..d80e91ecad 100644
--- a/cmd/efidebug.c
+++ b/cmd/efidebug.c
@@ -741,9 +741,11 @@ static int efi_boot_add_uri(int argc, char *const argv[], 
u16 *var_name16,
if (!label)
return CMD_RET_FAILURE;
 
-   if (!wget_validate_uri(argv[3])) {
-   printf("ERROR: invalid URI\n");
-   return CMD_RET_FAILURE;
+   if (IS_ENABLED(CONFIG_CMD_WGET)) {
+   if (!wget_validate_uri(argv[3])) {
+   printf("ERROR: invalid URI\n");
+   return CMD_RET_FAILURE;
+   }
}
 
efi_create_indexed_name(var_name16, var_name16_size, "Boot", id);
diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
index 4179861b2d..2926399bd0 100644
--- a/cmd/net-lwip.c
+++ b/cmd/net-lwip.c
@@ -35,3 +35,11 @@ U_BOOT_CMD(
"hostname [envvar]"
 );
 #endif
+
+#if defined(CONFIG_CMD_WGET_LWIP)
+U_BOOT_CMD(
+   wget,   3,  1,  do_wget,
+   "boot image via network using HTTP protocol",
+   "[loadAddress] URL"
+);
+#endif
diff --git a/include/net-lwip.h b/include/net-lwip.h
index 0019d1524e..23ad70fc09 100644
--- a/include/net-lwip.h
+++ b/include/net-lwip.h
@@ -85,5 +85,6 @@ int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char 
*const argv[]);
 int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
 
 #endif /* __NET_LWIP_H__ */
diff --git a/net-lwip/Makefile b/net-lwip/Makefile
index a1f2842855..63fbeaaf04 100644
--- a/net-lwip/Makefile
+++ b/net-lwip/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_CMD_DHCP_LWIP) += dhcp.o
 obj-$(CONFIG_CMD_DNS_LWIP) += dns.o
 obj-$(CONFIG_CMD_PING_LWIP) += ping.o
 obj-$(CONFIG_CMD_TFTPBOOT_LWIP) += tftp.o
+obj-$(CONFIG_CMD_WGET_LWIP) += wget.o
 
 # Disable this warning as it is triggered by:
 # sprintf(buf, index ? "foo%d" : "foo", index)
diff --git a/net-lwip/wget.c b/net-lwip/wget.c
new file mode 100644
index 00..0ed8b77c47
--- /dev/null
+++ b/net-lwip/wget.c
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2024 Linaro Ltd. */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define SERVER_NAME_SIZE 200
+#define HTTP_PORT_DEFAULT 80
+
+static ulong daddr;
+static ulong saved_daddr;
+static ulong size;
+static ulong prevsize;
+#define PROGRESS_PRINT_STEP_BYTES (100 * 1024)
+static ulong start_time;
+static enum done_state {
+NOT_DONE = 0,
+SUCCESS = 1,
+FAILURE = 2
+} done;
+
+static int parse_url(char *url, char *host, u16 *port, char **path)
+{
+   char *p, *pp;
+   long lport;
+
+   p = strstr(url, "http://;);
+   if (!p)
+   return -EINVAL;
+
+   p += strlen("http://;);
+
+   /* Parse hostname */
+   pp = strchr(p, ':');
+   if (!pp)
+   pp = strchr(p, '/');
+   if (!pp)
+   return -EINVAL;
+
+   if (p + SERVER_NAME_SIZE <= pp)
+   return -EINVAL;
+
+   memcpy(host, p, pp - p);
+   host[pp - p + 1] = '\0';
+
+   if (*pp == ':') {
+   /* Parse port number */
+   p = pp + 1;
+   lport = simple_strtol(p, , 10);
+   if (pp && *pp != '/')
+   return -EINVAL;
+ 

[PATCH 06/15] net-lwip: add dns command

2024-05-22 Thread Jerome Forissier
Add CONFIG_CMD_DNS_LWIP depending on CONFIG_NET_LWIP to provide the
dns command using lwIP.

Signed-off-by: Jerome Forissier 
---
 cmd/Kconfig|   6 +++
 cmd/net-lwip.c |   8 
 include/net-lwip.h |   1 +
 net-lwip/Makefile  |   1 +
 net-lwip/dns.c | 107 +
 5 files changed, 123 insertions(+)
 create mode 100644 net-lwip/dns.c

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 6840f7319b..1aba10b14c 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2098,6 +2098,12 @@ config CMD_DHCP_LWIP
help
  Boot image via network using DHCP/TFTP protocol
 
+config CMD_DNS_LWIP
+   bool "dns"
+   select PROT_DNS_LWIP
+   help
+ Lookup the IP of a hostname
+
 config CMD_PING_LWIP
bool "ping"
select PROT_RAW_LWIP
diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
index fbe04048cd..4179861b2d 100644
--- a/cmd/net-lwip.c
+++ b/cmd/net-lwip.c
@@ -27,3 +27,11 @@ U_BOOT_CMD(
"[loadAddress] [[hostIPaddr:]bootfilename]"
 );
 #endif
+
+#if defined(CONFIG_CMD_DNS_LWIP)
+U_BOOT_CMD(
+   dns,3,  1,  do_dns,
+   "lookup the IP of a hostname",
+   "hostname [envvar]"
+);
+#endif
diff --git a/include/net-lwip.h b/include/net-lwip.h
index 2abaaa3b4e..0019d1524e 100644
--- a/include/net-lwip.h
+++ b/include/net-lwip.h
@@ -82,6 +82,7 @@ int net_lwip_init(void);
 struct netif *net_lwip_get_netif(void);
 
 int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 
diff --git a/net-lwip/Makefile b/net-lwip/Makefile
index 676615fe17..a1f2842855 100644
--- a/net-lwip/Makefile
+++ b/net-lwip/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth_common.o
 obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth-uclass.o
 obj-$(CONFIG_$(SPL_)DM_ETH) += net-lwip.o
 obj-$(CONFIG_CMD_DHCP_LWIP) += dhcp.o
+obj-$(CONFIG_CMD_DNS_LWIP) += dns.o
 obj-$(CONFIG_CMD_PING_LWIP) += ping.o
 obj-$(CONFIG_CMD_TFTPBOOT_LWIP) += tftp.o
 
diff --git a/net-lwip/dns.c b/net-lwip/dns.c
new file mode 100644
index 00..6ef9d0b510
--- /dev/null
+++ b/net-lwip/dns.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2024 Linaro Ltd. */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DNS_RESEND_MS 1000
+#define DNS_TIMEOUT_MS 1
+
+static ulong start;
+static ip_addr_t host_ipaddr;
+static bool done;
+
+static void do_dns_tmr(void *arg)
+{
+   dns_tmr();
+}
+
+static void dns_cb(const char *name, const ip_addr_t *ipaddr, void *arg)
+{
+   char *var = (char *)arg;
+   char *ipstr = ip4addr_ntoa(ipaddr);
+
+   done = true;
+
+   if (!ipaddr) {
+   printf("DNS: host not found\n");
+   host_ipaddr.addr = 0;
+   return;
+   }
+
+   if (var)
+   env_set(var, ipstr);
+
+   printf("%s\n", ipstr);
+}
+
+int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+   bool has_server = false;
+   ip_addr_t ipaddr;
+   ip_addr_t ns;
+   char *nsenv;
+   char *name;
+   char *var;
+   int ret;
+
+   if (argc == 1 || argc > 3)
+   return CMD_RET_USAGE;
+
+   if (argc >= 2)
+   name = argv[1];
+
+   if (argc == 3)
+   var = argv[2];
+
+   dns_init();
+
+   nsenv = env_get("dnsip");
+   if (nsenv && ipaddr_aton(nsenv, )) {
+   dns_setserver(0, );
+   has_server = true;
+   }
+
+   nsenv = env_get("dnsip2");
+   if (nsenv && ipaddr_aton(nsenv, )) {
+   dns_setserver(1, );
+   has_server = true;
+   }
+
+   if (!has_server) {
+   log_err("No valid name server (dnsip/dnsip2)\n");
+   return CMD_RET_FAILURE;
+   }
+
+   done = false;
+
+   ret = dns_gethostbyname(name, , dns_cb, var);
+
+   if (ret == ERR_OK) {
+   dns_cb(name, , var);
+   } else if (ret == ERR_INPROGRESS) {
+   start = get_timer(0);
+   sys_timeout(DNS_RESEND_MS, do_dns_tmr, NULL);
+   do {
+   eth_rx();
+   if (done)
+   break;
+   sys_check_timeouts();
+   if (ctrlc()) {
+   printf("\nAbort\n");
+   break;
+   }
+   } while (get_timer(start) < DNS_TIMEOUT_MS);
+   sys_untimeout(do_dns_tmr, NULL);
+   }
+
+   if (done && host_ipaddr.addr != 0)
+   return CMD_RET_SUCCESS;
+
+   return CMD_RET_FAILURE;
+}
+
-- 
2.40.1



[PATCH 05/15] net-lwip: add ping command

2024-05-22 Thread Jerome Forissier
Add CONFIG_CMD_PING_LWIP depending on CONFIG_NET_LWIP to provide the
ping command using lwIP.

The implementation is derived from lwIP's contrib/apps/ping/ping.c.

Signed-off-by: Jerome Forissier 
---
 boot/Kconfig   |   1 +
 cmd/Kconfig|   6 ++
 cmd/net-lwip.c |   8 +++
 include/net-lwip.h |   3 +
 net-lwip/Makefile  |   1 +
 net-lwip/ping.c| 171 +
 6 files changed, 190 insertions(+)
 create mode 100644 net-lwip/ping.c

diff --git a/boot/Kconfig b/boot/Kconfig
index 649fd454a2..9f220fa75c 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -382,6 +382,7 @@ config BOOT_DEFAULTS_CMDS
select CMD_PING if CMD_NET
select CMD_PXE if CMD_NET
select CMD_DHCP_LWIP if CMD_NET_LWIP
+   select CMD_PING_LWIP if CMD_NET_LWIP
select CMD_BOOTI if ARM64
select CMD_BOOTZ if ARM && !ARM64
imply CMD_MII if NET
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 7bb6269b7a..6840f7319b 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2098,6 +2098,12 @@ config CMD_DHCP_LWIP
help
  Boot image via network using DHCP/TFTP protocol
 
+config CMD_PING_LWIP
+   bool "ping"
+   select PROT_RAW_LWIP
+   help
+ Send ICMP ECHO_REQUEST to network host
+
 config CMD_TFTPBOOT_LWIP
bool "tftp"
select PROT_UDP_LWIP
diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
index 30b396f2d0..fbe04048cd 100644
--- a/cmd/net-lwip.c
+++ b/cmd/net-lwip.c
@@ -12,6 +12,14 @@ U_BOOT_CMD(
 );
 #endif
 
+#if defined(CONFIG_CMD_PING_LWIP)
+U_BOOT_CMD(
+   ping,   2,  1,  do_ping,
+   "send ICMP ECHO_REQUEST to network host",
+   "pingAddress"
+);
+#endif
+
 #if defined(CONFIG_CMD_TFTPBOOT_LWIP)
 U_BOOT_CMD(
tftpboot,   3,  0,  do_tftpb,
diff --git a/include/net-lwip.h b/include/net-lwip.h
index 2308703e46..2abaaa3b4e 100644
--- a/include/net-lwip.h
+++ b/include/net-lwip.h
@@ -5,6 +5,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -50,6 +51,7 @@ int eth_env_get_enetaddr_by_index(const char *base_name, int 
index,
 int eth_init(void);/* Initialize the device */
 int eth_send(void *packet, int length);   /* Send a packet */
 int eth_rx(void);
+const char *eth_get_name(void);
 int eth_get_dev_index(void);
 int eth_init_state_only(void); /* Set active state */
 void eth_set_current(void);/* set nterface to ethcur var */
@@ -80,6 +82,7 @@ int net_lwip_init(void);
 struct netif *net_lwip_get_netif(void);
 
 int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 
 #endif /* __NET_LWIP_H__ */
diff --git a/net-lwip/Makefile b/net-lwip/Makefile
index 79bdaecee5..676615fe17 100644
--- a/net-lwip/Makefile
+++ b/net-lwip/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth_common.o
 obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth-uclass.o
 obj-$(CONFIG_$(SPL_)DM_ETH) += net-lwip.o
 obj-$(CONFIG_CMD_DHCP_LWIP) += dhcp.o
+obj-$(CONFIG_CMD_PING_LWIP) += ping.o
 obj-$(CONFIG_CMD_TFTPBOOT_LWIP) += tftp.o
 
 # Disable this warning as it is triggered by:
diff --git a/net-lwip/ping.c b/net-lwip/ping.c
new file mode 100644
index 00..763a9bb1e3
--- /dev/null
+++ b/net-lwip/ping.c
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2024 Linaro Ltd. */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define PING_DELAY_MS 1000
+#define PING_TIMEOUT_MS 1
+/* Additional data size to include in the packet */
+#define PING_DATA_SIZE 32
+/* Ping identifier - must fit on a u16_t */
+#define PING_ID 0xAFAF
+
+static const ip_addr_t *ping_target;
+static struct raw_pcb *ping_pcb;
+static u16_t ping_seq_num;
+static bool ping_target_alive;
+
+static u8_t ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p,
+ const ip_addr_t *addr)
+{
+   struct icmp_echo_hdr *iecho;
+
+   if (addr->addr != ping_target->addr)
+   return 0;
+
+   if ((p->tot_len >= (IP_HLEN + sizeof(struct icmp_echo_hdr))) &&
+   pbuf_remove_header(p, IP_HLEN) == 0) {
+   iecho = (struct icmp_echo_hdr *)p->payload;
+
+   if ((iecho->id == PING_ID) &&
+   (iecho->seqno == lwip_htons(ping_seq_num))) {
+   ping_target_alive = true;
+   printf("host %s is alive\n", ipaddr_ntoa(addr));
+   pbuf_free(p);
+   return 1; /* eat the packet */
+   }
+   /* not eaten, restore original packet */
+   pbuf_add_header(p, IP_HLEN);
+   }
+
+   return 0; /* don't eat the packet */
+}
+
+static int ping_raw_init(vo

[PATCH 04/15] net-lwip: add TFTP support and tftpboot command

2024-05-22 Thread Jerome Forissier
Implement do_tftpb().

Signed-off-by: Jerome Forissier 
---
 cmd/Kconfig |   3 +-
 cmd/net-lwip.c  |   8 ++
 net-lwip/dhcp.c |  11 ++-
 net-lwip/tftp.c | 206 +++-
 4 files changed, 223 insertions(+), 5 deletions(-)

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 0ef3189d8c..7bb6269b7a 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2101,10 +2101,9 @@ config CMD_DHCP_LWIP
 config CMD_TFTPBOOT_LWIP
bool "tftp"
select PROT_UDP_LWIP
-   default n
+   default y
help
  tftpboot - load file via network using TFTP protocol
- Currently a placeholder (not implemented)
 
 endif
 
diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
index c740461c64..30b396f2d0 100644
--- a/cmd/net-lwip.c
+++ b/cmd/net-lwip.c
@@ -11,3 +11,11 @@ U_BOOT_CMD(
 "[loadAddress] [[hostIPaddr:]bootfilename]"
 );
 #endif
+
+#if defined(CONFIG_CMD_TFTPBOOT_LWIP)
+U_BOOT_CMD(
+   tftpboot,   3,  0,  do_tftpb,
+   "boot image via network using TFTP protocol\n",
+   "[loadAddress] [[hostIPaddr:]bootfilename]"
+);
+#endif
diff --git a/net-lwip/dhcp.c b/net-lwip/dhcp.c
index ae2d922cda..f4655162fe 100644
--- a/net-lwip/dhcp.c
+++ b/net-lwip/dhcp.c
@@ -94,11 +94,20 @@ int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char 
*const argv[])
 int dhcp_run(ulong addr, const char *fname, bool autoload)
 {
char *dhcp_argv[] = {"dhcp", NULL, };
+#ifdef CONFIG_CMD_TFTPBOOT_LWIP
+   char *tftp_argv[] = {"tftpboot", boot_file_name, NULL, };
+#endif
struct cmd_tbl cmdtp = {};  /* dummy */
 
if (autoload) {
-   /* Will be supported when TFTP is added */
+#ifdef CONFIG_CMD_TFTPBOOT_LWIP
+   /* Assume DHCP was already performed */
+   if (boot_file_name[0])
+   return do_tftpb(, 0, 2, tftp_argv);
+   return 0;
+#else
return -EOPNOTSUPP;
+#endif
}
 
return do_dhcp(, 0, 1, dhcp_argv);
diff --git a/net-lwip/tftp.c b/net-lwip/tftp.c
index 1fa246f55d..19bf083d99 100644
--- a/net-lwip/tftp.c
+++ b/net-lwip/tftp.c
@@ -2,10 +2,212 @@
 /* Copyright (C) 2024 Linaro Ltd. */
 
 #include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
 #include 
+#include 
+
+static ulong daddr;
+static ulong size;
+static ulong prevsize;
+#define PROGRESS_PRINT_STEP_BYTES (100 * 1024)
+static ulong start_time;
+static enum done_state {
+   NOT_DONE = 0,
+   SUCCESS = 1,
+   FAILURE = 2
+} done;
+
+static void *tftp_open(const char *fname, const char *mode, u8_t is_write)
+{
+   return NULL;
+}
+
+static void tftp_close(void *handle)
+{
+   ulong elapsed;
+
+   if (done == FAILURE) {
+   /* Closing after an error */
+   return;
+   }
+
+   elapsed = get_timer(start_time);
+   done = SUCCESS;
+   log_info("\n%lu bytes transferred in %lu ms (", size,
+get_timer(start_time));
+   print_size(size / elapsed * 1000, "/s)\n");
+
+
+   if (env_set_hex("filesize", size)) {
+   log_err("filesize not updated\n");
+   return;
+   }
+}
+
+static int tftp_read(void *handle, void *buf, int bytes)
+{
+   return 0;
+}
+
+static int tftp_write(void *handle, struct pbuf *p)
+{
+   struct pbuf *q;
+
+   for (q = p; q != NULL; q = q->next) {
+   memcpy((void *)daddr, q->payload, q->len);
+   daddr += q->len;
+   size += q->len;
+   if (size - prevsize > PROGRESS_PRINT_STEP_BYTES) {
+   printf("#");
+   prevsize = size;
+   }
+   }
+
+   return 0;
+}
+
+static void tftp_error(void *handle, int err, const char *msg, int size)
+{
+   char message[100];
+
+   done = FAILURE;
+   memset(message, 0, sizeof(message));
+   memcpy(message, msg, LWIP_MIN(sizeof(message) - 1, (size_t)size));
+
+   log_info("\nTFTP error: %d (%s)\n", err, message);
+}
+
+static const struct tftp_context tftp_context = {
+   tftp_open,
+   tftp_close,
+   tftp_read,
+   tftp_write,
+   tftp_error
+};
+
+static int tftp_run(ulong addr, char *fname, ip_addr_t srvip)
+{
+   void *f = (void *)0x1; /* unused fake file handle*/
+   err_t err;
+
+   if (!fname || addr == 0)
+   return -1;
+
+   done = NOT_DONE;
+   size = 0;
+   prevsize = 0;
+   daddr = addr;
+
+   log_info("TFTP from server %s; our IP address is %s\n",
+ip4addr_ntoa(), env_get("ipaddr"));
+   log_info("Filename '%s'.\n", fname);
+   log_info("Load address: 0x%lx\n", daddr);
+   log_info("Loading: ");
+
+   err = tftp_init_client(_context);
+   if (!(err == ERR_OK || err == ERR_US

[PATCH 00/15] Introduce the lwIP network stack

2024-05-22 Thread Jerome Forissier
This is a rework of a patch series by Maxim Uvarov: "net/lwip: add lwip
library for the network stack" [1]. The goal is to introduce the lwIP TCP/IP
stack [2] [3] as an alternative to the current implementation in net/,
selectable with Kconfig, and ultimately keep only lwIP if possible. Some
reasons for doing so are:
- Make the support of HTTPS in the wget command easier. Javier T. (CC'd)
has some additional lwIP and Mbed TLS patches to do so. With that it
becomes possible to fetch and launch a distro installer such as Debian
etc. directly from the U-Boot shell.
- Possibly benefit from additional features implemented in lwIP
- Less code to maintain in U-Boot

The first patch introduces a new Kconfig symbol: NET_LWIP, which selects
the lwIP implementation instead of the current one (NET). Contrary to the
approach chosen by Maxim in [1], NET_LWIP and NET cannot be enabled
simultaneously. The rationale is we want to start from a clean state and
not pull potentially duplicated functionality from both stacks. Note
however that a few files are still built in net/, they are the ones related
to ethernet device management and the ethernet bootflow.

The second patch imports the lwIP code under lib/lwip. There is no change
made to the code itself so upgrading to newer versions should be trivial.
The code could be imported as a Git subtree if that's preferred.

The subsequent patches implement various network-oriented commands and
features: dhcp, dns, ping, tftpboot, wget. The commands have their own
Kconfig symbol suffixed with _LWIP. For example CMD_PING_LWIP is the
equivalent of CMD_PING but using the lwIP stack. Again this is meant to
avoid pulling any unwanted code.

NET_LWIP is not enabled by default because it lacks functionality compared
to NET and many CI tests would fail to run or even build.

Some tests (dm dsa/eth) are disabled when NET_LWIP is selected because
they make strong assumptions on how the network stack is implemented and
how the packet flow occurs. For example, an ARP exchange is expected
when an ICMP packet goes out, but with lwIP no exchange will occur if the
host IP is already in the the ARP cache.

Due to the above and in order to provide some level of testing, a new QEMU
configuration is introduced (qemu_arm64_lwip_defconfig) which is the same
as qemu_arm64_lwip_defconfig but with NET_LWIP and CMD_*_LWIP enabled.
Tests are added to test/py/tests/test_net.py for that configuration.
The series passes the CI tests on GitHub [4].

Regarding the size of the U-Boot binary, I compared various builds using
the command:

 linux/scripts/bloat-o-meter A/u-boot B/u-boot | \
 grep -E "(add/remove|Total:)"

- Comparing default configs (some features that are enabled by default when
lwIP is not used but not supported with lwIP are disabled manually)
(A) master branch, qemu_arm64_defconfig BOOTP_PXE=n CMD_MII=n DFU_TFTP=n
(B) this series, qemu_arm64_lwip_defconfig 

 add/remove: 167/161 grow/shrink: 5/11 up/down: 22335/-19971 (2364)
 Total: Before=811018, After=813382, chg +0.29%

- With all the supported network commands enabled (dhcp + dns + ping +
tftpboot + wget)
(A) master branch, qemu_arm64_defconfig BOOTP_PXE=n CMD_MII=n DFU_TFTP=n
CMD_DNS=y CMD_WGET=y
(B) this series, qemu_arm64_lwip_defconfig CMD_DNS_LWIP=y CMD_WGET_LWIP=y

 add/remove: 303/218 grow/shrink: 8/11 up/down: 48655/-26686 (21969)
 Total: Before=818017, After=839986, chg +2.69%

[1] https://lore.kernel.org/all/20231127125726.3735-1-maxim.uva...@linaro.org/
[2] https://www.nongnu.org/lwip/
[3] https://en.wikipedia.org/wiki/LwIP
[4] https://github.com/u-boot/u-boot/pull/531

CC: Javier Tia 

Jerome Forissier (15):
  net: introduce alternative implementation as net-lwip/
  net-lwip: import lwIP library under lib/lwip
  net-lwip: add DHCP support and dhcp commmand
  net-lwip: add TFTP support and tftpboot command
  net-lwip: add ping command
  net-lwip: add dns command
  net-lwip: add wget command
  net-lwip: import net command from cmd/net.c
  net-lwip: add support for EFI_HTTP_BOOT
  test: dm: dsa, eth: disable tests when CONFIG_NET_LWIP=y
  cmd: bdinfo: enable -e when CONFIG_CMD_NET_LWIP=y
  configs: add qemu_arm64_lwip_defconfig
  test/py: net: add _lwip variants of dhcp, ping and tftpboot tests
  MAINTAINERS: net-lwip: add myself as a maintainer
  CI: add qemu_arm64_lwip to the test matrix

 .azure-pipelines.yml  |7 +
 Kconfig   |2 +
 MAINTAINERS   |   11 +
 Makefile  |3 +-
 boot/Kconfig  |3 +
 boot/bootmeth_efi.c   |3 +-
 cmd/Kconfig   |   44 +
 cmd/Makefile  |4 +
 cmd/bdinfo.c  |5 +-
 cmd/efidebug.c|

Re: [PATCH 2/2] rockchip: rk3399: Update stack and bss addresses

2024-02-12 Thread Jerome Forissier



On 2/12/24 12:51, Quentin Schulz wrote:
> Hi Jonas,
> 
> On 2/12/24 12:08, Jonas Karlman wrote:
>> Hi Quentin,
>>
>> On 2024-02-12 11:37, Quentin Schulz wrote:
>>> Hi Jonas,
>>>
>>> On 2/12/24 01:59, Jonas Karlman wrote:
 With the stack and text base used by U-Boot SPL and proper on RK3399
 there is a high likelihood of overlapping when U-Boot proper + FDT nears
 1 MiB in size.

 Currently the following memory layout is used:
 - 0x (@0 MiB): U-Boot SPL text base
 - 0x0004 (@256 KiB): TF-A
 - 0x0020 (@2 MiB): U-Boot proper text base
 - 0x0030 (@3 MiB): U-Boot proper init stack
 - 0x0040 (@4 MiB): U-Boot SPL init stack
 - 0x0040 (@4 MiB): U-Boot SPL bss
 - 0x0200 (@64 MiB): U-Boot SPL reloc stack
 - 0x0840 (@132 MiB): optional OPTEE

 SPL load TF-A, U-Boot proper and optional OPTEE after SPL stack has
 relocated, meaning that there is room for close to 2 MiB (@2-4 MiB).
 However, the initial stack used by U-Boot proper is limiting the size
 of U-Boot proper + FDT to below 1 MiB (@2-3 MiB).

 Instead change to use the following memory layout:
 - 0x (@0 MiB): U-Boot SPL text base
 - 0x0004 (@256 KiB): TF-A
 - 0x0020 (@2 MiB): U-Boot proper text base
 - 0x0040 (@4 MiB): U-Boot SPL init stack
 - 0x0080 (@8 MiB): U-Boot proper init stack (changed)
 - 0x0200 (@32 MiB): U-Boot SPL bss (changed)
 - 0x0400 (@64 MiB): U-Boot SPL reloc stack
 - 0x0840 (@132 MiB): optional OPTEE

 This should leave room for loading and running a U-Boot proper close
 to 6 MiB (@2-8 MiB) in size. When U-Boot proper has relocated is should
 be possible to use @2-132 MiB and @164 MiB+ for scripts, kernel etc.

 With the moved SPL reloc stack it is also possible to use a much larger
 malloc area in SPL, e.g. using default SPL_STACK_R_MALLOC_SIMPLE_LEN.

 Signed-off-by: Jonas Karlman 
>>>
>>> Do we not need to update memory addresses in the environment as well?
>>
>> The addresses in environment is to my knowledge only used in U-Boot
>> proper after relocation. And at that time we should be free to use @2+
>> MiB up to somewhere close to gd ram_top/relocaddr. The optional Rockchip
>> OPTEE blobb may occupy @132-164 MiB, but I do not think loading OPTEE
>> blobs works as-is, so that may not be a big issue.
>>
> 
> Upstream OP-TEE OS seems to support RK3399, c.f. 
> https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/plat-rockchip/platform_rk3399.c

It does indeed. I run the quarterly release tests on a RockPi4B. We record which
platforms have been tested in the commit description for each release tag. For
example, see [1].

In the configuration I test, OP-TEE is loaded at 0x3000 and uses 32MB (for
some reason the Linux DT reserves 36MB but I don't think it matters much).

[1] 
https://github.com/OP-TEE/optee_os/commit/18b424c23aa5a798dfe2e4d20b4bde3919dc4e99

-- 
Jerome


Re: [PATCH v4 10/16] arm: dts: Introduce j784s4 u-boot dts files

2023-10-02 Thread Jerome Forissier
Hello Apurva,

On 10/1/23 18:55, Apurva Nandan wrote:
> Introduce the base dts files needed for u-boot or to augment the linux
> dtbs for use in the u-boot-spl and u-boot binaries.
> 
> Signed-off-by: Hari Nagalla 
> [ add binman and ddr dtsi files ]
> Signed-off-by: Neha Malcom Francis 
> Signed-off-by: Apurva Nandan 
> Signed-off-by: Dasnavis Sabiya 
> ---
>  arch/arm/dts/Makefile|2 +
>  arch/arm/dts/k3-j784s4-binman.dtsi   |  505 +
>  arch/arm/dts/k3-j784s4-ddr-evm-lp4-4266.dtsi | 8757 +
>  arch/arm/dts/k3-j784s4-ddr.dtsi  | 8858 ++
>  arch/arm/dts/k3-j784s4-evm-u-boot.dtsi   |   25 +
>  arch/arm/dts/k3-j784s4-r5-evm.dts|  105 +
>  6 files changed, 18252 insertions(+)
>  create mode 100644 arch/arm/dts/k3-j784s4-binman.dtsi
>  create mode 100644 arch/arm/dts/k3-j784s4-ddr-evm-lp4-4266.dtsi
>  create mode 100644 arch/arm/dts/k3-j784s4-ddr.dtsi
>  create mode 100644 arch/arm/dts/k3-j784s4-evm-u-boot.dtsi
>  create mode 100644 arch/arm/dts/k3-j784s4-r5-evm.dts
> 
> diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
> index 85fd5b1157..21cfebff58 100644
> --- a/arch/arm/dts/Makefile
> +++ b/arch/arm/dts/Makefile
> @@ -1327,6 +1327,8 @@ dtb-$(CONFIG_SOC_K3_J721S2) += 
> k3-am68-sk-base-board.dtb\
>  k3-am68-sk-r5-base-board.dtb\
>  k3-j721s2-common-proc-board.dtb\
>  k3-j721s2-r5-common-proc-board.dtb
> +dtb-$(CONFIG_SOC_K3_J784S4) += k3-j784s4-evm.dtb\
> +k3-j784s4-r5-evm.dtb
>  dtb-$(CONFIG_SOC_K3_AM642) += k3-am642-evm.dtb \
> k3-am642-r5-evm.dtb \
> k3-am642-sk.dtb \
> diff --git a/arch/arm/dts/k3-j784s4-binman.dtsi 
> b/arch/arm/dts/k3-j784s4-binman.dtsi
> new file mode 100644
> index 00..f9b191424c
> --- /dev/null
> +++ b/arch/arm/dts/k3-j784s4-binman.dtsi
> @@ -0,0 +1,505 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
> + */



> + {
> + ti-spl_unsigned {
> + filename = "tispl.bin_unsigned";
> + pad-byte = <0xff>;
> +
> + fit {
> + description = "Configuration to load ATF and SPL";
> + #address-cells = <1>;
> +
> + images {
> +
> + atf {
> + description = "ARM Trusted Firmware";
> + type = "firmware";
> + arch = "arm64";
> + compression = "none";
> + os = "arm-trusted-firmware";
> + load = ;
> + entry = ;
> +
> + atf-bl31 {
> + filename = "bl31.bin";
> + };
> + };
> +
> + tee {
> + description = "OPTEE";

The official spelling is "OP-TEE".

> + type = "tee";
> + arch = "arm64";
> + compression = "none";
> + os = "tee";
> + load = <0x9e80>;
> + entry = <0x9e80>;
> +
> + tee-os {
> + filename = "tee-pager_v2.bin";

Since OP-TEE 3.21.0 this could/should be replaced with tee-raw.bin. Although 
tee-pager_v2.bin is still produced unconditionally (even when the "pager" 
feature is disabled in OP-TEE) it might not be the case in the future, and the 
name is somewhat misleading when pager is disabled anyways (which is clearly 
the case here since tee-pageable_v2.bin is not used).

Thanks,
-- 
Jerome


Re: [PATCH v1 4/5] rockchip: evb_rk3229: Update/fix README

2023-07-17 Thread Jerome Forissier



On 7/16/23 10:10, Alex Bee wrote:
> This updates the evb_rk3229's README on howto create / use the FIT image
> created by binman.
> Also fix some wrong paths and update filenames which have changed in recent
> upstream optee-os versions.
> 
> Signed-off-by: Alex Bee 
> ---
>  board/rockchip/evb_rk3229/README | 72 +---
>  1 file changed, 48 insertions(+), 24 deletions(-)
> 
> diff --git a/board/rockchip/evb_rk3229/README 
> b/board/rockchip/evb_rk3229/README
> index 9068225e27..e4c88bac06 100644
> --- a/board/rockchip/evb_rk3229/README
> +++ b/board/rockchip/evb_rk3229/README
> @@ -13,25 +13,23 @@ Compile the OP-TEE
>  
>> cd optee_os
>> make clean
> -  > make CROSS_COMPILE_ta_arm32=arm-none-eabi- PLATFORM=rockchip-rk322x
> -  Get tee.bin in this step, copy it to U-Boot root dir:
> -  > cp out/arm-plat-rockchip/core/tee-pager.bin ../u-boot/tee.bin
> +  > make CROSS_COMPILE=arm-none-eabi- PLATFORM=rockchip-rk322x
> +  Get tee-pager_v2.bin in this step, copy it to U-Boot root dir:
> +  > cp out/arm-plat-rockchip/core/tee-pager_v2.bin ../u-boot/tee.bin

Since OP-TEE 3.21.0, there is a tee-raw.bin file. I recommend using it
instead of tee-pager_v2.bin. Technically they are identical when the OP-TEE
"pager" feature is disabled, but the name makes more sense.

-- 
Jerome


Re: [PATCH v7 00/23] Migration to using binman for bootloader

2023-07-14 Thread Jerome Forissier



On 7/14/23 15:50, Neha Malcom Francis wrote:
> This series aims to eliminate the use of additional custom repositories
> such as k3-image-gen (K3 Image Generation) repo and core-secdev-k3 (K3
> Security Development Tools) that was plumbed into the U-Boot build flow
> to generate boot images for TI K3 platform devices. And instead, we move
> towards using binman that aligns better with the community standard build
> flow.
> 
> This series uses binman for all K3 platforms supported on U-Boot currently;
> both HS (High Security, both SE and FS) and GP (General Purpose) devices.
> 
> Background on using k3-image-gen:
>   * TI K3 devices require a SYSFW (System Firmware) image consisting
>   of a signed system firmware image and board configuration binaries,
>   this is needed to bring up system firmware during U-Boot R5 SPL
>   startup.
>   * Board configuration data contain board-specific information
>   such as resource management, power management and security.
> 
> Background on using core-secdev-k3:
>   * Contains resources to sign x509 certificates for HS devices
> 
> Series intends to use binman to take over the packaging and signing for
> the R5 bootloader images tiboot3.bin (and sysfw.itb, for non-combined
> boot flow) instead of k3-image-gen.
> 
> Series also packages the A72/A53 bootloader images (tispl.bin and
> u-boot.img) using ATF, OPTEE and DM (Device Manager)
> 
> Changes in v7:
>   - corrected Texas Instruments copyright year
>   - k3-am65-iot2050 image fit@0x18 filename retained as
> tispl.bin
> 
> Changes in v6:
>   - addressed whitespace warnings
>   - added testcase for overwriting symlink functionality
>   - %s/Arm Trusted Firmware/Trusted Firmware-A
>   - %s/tee-pager_v2.bin/tee-raw.bin

I can still find quite a few occurrences of tee-pager_v2.bin in the patch
set (and in v7 too). Did you forget to change?

Another note applicable to several patches in v7:
'description = "OPTEE"' should be
'description = "OP-TEE"' (the official spelling has a hyphen). 

-- 
Jerome


Re: [PATCH v5 20/23] doc: board: ti: Update documentation for binman flow

2023-07-07 Thread Jerome Forissier



On 7/7/23 14:34, Neha Malcom Francis wrote:
> Earlier documentation specified builds for generating bootloader images
> using an external TI repository k3-image-gen and core-secdev-k3. Modify
> this to using the binman flow so that user understands how to build the
> final boot images.
> 
> Signed-off-by: Neha Malcom Francis 
> Reviewed-by: Simon Glass 
> ---
>  doc/board/ti/am62x_sk.rst  | 42 -
>  doc/board/ti/j721e_evm.rst | 50 +---
>  doc/board/ti/k3.rst| 95 +-
>  3 files changed, 73 insertions(+), 114 deletions(-)
> 
> diff --git a/doc/board/ti/am62x_sk.rst b/doc/board/ti/am62x_sk.rst
> index 27d7b527c6..e4d58b4958 100644
> --- a/doc/board/ti/am62x_sk.rst
> +++ b/doc/board/ti/am62x_sk.rst
[...]
> @@ -139,35 +135,37 @@ Build procedure:
>  
>  1. ATF:
>  
> -.. code-block:: text
> +.. code-block:: bash
>  
> - $ make CROSS_COMPILE=aarch64-none-linux-gnu- ARCH=aarch64 PLAT=k3 
> TARGET_BOARD=lite SPD=opteed
> + $ make CROSS_COMPILE=aarch64-none-linux-gnu- ARCH=aarch64 PLAT=k3 \
> +TARGET_BOARD=lite SPD=opteed
>  
>  2. OPTEE:
>  
> -.. code-block:: text
> +.. code-block:: bash
>  
> - $ make PLATFORM=k3 CFG_ARM64_core=y CROSS_COMPILE=arm-none-linux-gnueabihf- 
> CROSS_COMPILE64=aarch64-none-linux-gnu-
> + $ make PLATFORM=k3 CFG_ARM64_core=y CROSS_COMPILE=arm-none-linux-gnueabihf- 
> \
> +CROSS_COMPILE64=aarch64-none-linux-gnu-
>  
>  3. U-Boot:
>  
>  * 3.1 R5:
>  
> -.. code-block:: text
> +.. code-block:: bash
>  
> - $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabihf- 
> am62x_evm_r5_defconfig O=/tmp/r5
> - $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabihf- O=/tmp/r5
> - $ cd 
> - $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabihf- SOC=am62x 
> SBL=/tmp/r5/spl/u-boot-spl.bin SYSFW_PATH= ti-linux-firmware>/ti-sysfw/ti-fs-firmware-am62x-gp.bin
> -
> -Use the tiboot3.bin generated from last command
> + $ make ARCH=arm am62x_evm_r5_defconfig
> + $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabihf- \
> +BINMAN_INDIRS=
>  
>  * 3.2 A53:
>  
> -.. code-block:: text
> +.. code-block:: bash
>  
> - $ make ARCH=arm CROSS_COMPILE=aarch64-none-linux-gnu- 
> am62x_evm_a53_defconfig O=/tmp/a53
> - $ make ARCH=arm CROSS_COMPILE=aarch64-none-linux-gnu- ATF= dir>/build/k3/lite/release/bl31.bin TEE= dir>/out/arm-plat-k3/core/tee-pager_v2.bin DM= ti-linux-firmware>/ti-dm/am62xx/ipc_echo_testb_mcu1_0_release_strip.xer5f 
> O=/tmp/a53
> + $ make ARCH=arm am62x_evm_a53_defconfig
> + $ make ARCH=arm CROSS_COMPILE=aarch64-none-linux-gnu- \
> +BL31=/build/k3/lite/release/bl31.bin \
> +TEE=/out/arm-plat-k3/core/tee-pager_v2.bin \

Note that since OP-TEE 3.21.0, tee-raw.bin could/should be used instead of
tee-pager_v2.bin. Indeed when the "pager" feature is not enabled, the two
binaries are identical, and the newer name is hopefully less confusing.

-- 
Jerome


Re: imx8m optee load address?

2023-06-16 Thread Jerome Forissier
Hi,

On 6/16/23 05:31, Peng Fan wrote:
> 
> 
> On 6/16/2023 9:56 AM, Tim Harvey wrote:
>> Greetings,
>>
>> I've seen several IMX8M boards include a firmware/optee node in the
>> U-Boot dt (git grep optee arch/arm/dts/imx8m*.dtsi) yet but none that
>> I see configure binman to actually add the binary in the u-boot.dtsi,
>> do anything to keep U-Boot from accessing the OPTEE memory, or
>> document how to configure and build OPTEE for imx8m. I would like to
>> add such support but I find it odd that OPTEE needs to be built
>> differently depending on the dram size.
>>
>> Prior to switching to binman (v2021.10)
>> arch/arm/mach-imx/mkimage_fit_atf.sh [1] would include tee.bin in the
>> FIT image if it was found in the current directory and it was expected
>> that you provide a proper TEE_LOAD_ADDR via the env (commit
>> a9eed6e1b8d8 ("imx: imx8m: introduce script to generate fit image").
>>
>> According to the IMX OPTEE documentation [2] the size and location of
>> OPTEE is hard coded (CFG_TZDRAM_START and CFG_TZDRAM_SIZE) but looking
>> at the imx-optee source [3] this is calculated based off of
>> CFG_DDR_SIZE (which you can provide via env at build time or just
>> provide CFG_TZDRAM_START and CFG_TZDRAM_SIZE via env directly).
> 
> optee does not support PIE, it could only run at the address that built
> time defined.

PIE was introduced recently [1] but please note the limitation about EL2
SPMC.

[1] https://github.com/OP-TEE/optee_os/commit/0d9286927

Regards,
-- 
Jerome

> 
> And the TZASC needs following it to protect the region properly.
> 
>>
>> This results in the OPTEE location of 0x7e00 for 1GiB systems,
>> 0xbe00 for 2GiB systems, and 0x13e00 for 4GiB systems for
>> example. This dependence on dram size causes a couple of issues:
>>   - OPTEE location depends on build-time configuration and several
>> boards have run-time identification of their memory size
>>   - for 4GiB systems the address 0x13e00 crosses the 32bit address
>> boundary and U-Boot hangs
> 
> imx optee seems has this. But for overlapping with U-Boot, I doubt that.
> 
>>
>> Is there any reason OPTEE can't be located wherever you want and not
>> depend on dram size? 
> 
> You could , just modify the imx *.mk file per my recall.
> 
> I've tried to set it to 0x7e00 (for a 1GiB
>> board) on a 4GiB board and U-Boot hangs near the DRAM banner which is
>> likely due to get_ram_size() stepping on OPTEE's memory range but then
> 
> You may give a try to disable TZASC settings in OP-TEE first.
> And you also need to carve out the memory of OP-TEE from U-Boot MMU
> to avoid prefetch.
> 
>> I'm not clear why that doesn't occur when OPTEE is located at the top
>> of dram on a 1GiB and 2GiB system. How would I go about adding a
>> carevout for this?
> 
> Are u using upstream optee or NXP downstream optee release?
> 
> Regards,
> Peng.
> 
>>
>> Best Regards,
>>
>> Tim
>> [1] 
>> https://elixir.bootlin.com/u-boot/v2021.10/source/arch/arm/mach-imx/mkimage_fit_atf.sh
>> [2] https://www.nxp.com/docs/en/user-guide/IMX_PORTING_GUIDE.pdf
>> [3] https://github.com/nxp-imx/imx-optee-os


Re: [PATCH v8 06/13] binman: Support new op-tee binary format

2023-01-07 Thread Jerome Forissier



On 1/7/23 19:55, Simon Glass wrote:
> Hi Jerome,
> 
> On Thu, 22 Dec 2022 at 15:20, Jerome Forissier
>  wrote:
>>
>>
>>
>> On 12/22/22 21:23, Simon Glass wrote:
>>> (dropping the two bounces from cc)
>>>
>>> On Thu, 22 Dec 2022 at 13:18, Simon Glass  wrote:
>>>>
>>>> Hi Jerome,
>>>>
>>>> On Thu, 22 Dec 2022 at 08:36, Jerome Forissier
>>>>  wrote:
>>>>>
>>>>>
>>>>>
>>>>> On 12/22/22 00:07, Simon Glass wrote:
>>>>>> OP-TEE has a format with a binary header that can be used instead of the
>>>>>> ELF file. With newer versions of OP-TEE this may be required on some
>>>>>> platforms.
>>>>>>
>>>>>> Add support for this in binman. First, add a method to obtain the ELF
>>>>>> sections from an entry, then use that in the FIT support. We then end up
>>>>>> with the ability to support both types of OP-TEE files, depending on 
>>>>>> which
>>>>>> one is passed in with the entry argument (TEE=xxx in the U-Boot build).
>>>>>
>>>>> So, with:
>>>>>
>>>>> BL31=/path/to/bl31.elf TEE=/path/to/tee.bin make -C u-boot \
>>>>>   CROSS_COMPILE=aarch64-linux-gnu- CC=aarch64-linux-gnu-gcc \
>>>>>   HOSTCC=gcc BINMAN_DEBUG=1 BINMAN_VERBOSE=4
>>>>>
>>>>>
>>>>> ...I get:
>>>>>
>>>>> Entry '/binman/simple-bin/fit/images/@tee-SEQ/tee-os' marked absent: uses 
>>>>> v1 format which must be in a FIT
> 
> OK, this is expected. It means that the contents are not provided. I
> will add some more comments.
> 
> We can refine this later, but we are a year into this conversion of
> rk3399 to binman and I really want to land this right away before I
> lose interest and it sits here for another year.

I commented that in my other reply. That would break my use case.

> Do you have an influence on OP-TEE?

I am one of the core maintainers ;)

> I think the way they are adding a
> header here is a really back idea. We should look at packaging these
> blobs in a FIT complete with all the metadata that is needed, with a
> standard schema.

Isn't that what this patch series is trying to accomplish? Using a
different tool (binman instead of a custom python script) to package a
blob into a FIT? As I said in my other reply, tee.bin is the output of
the OP-TEE build, it has to be loaded in memory at a specific address,
that you can discover be reading the binary itself -- no need for
metadata... How infrequent is such a use case for a bootloader? to deal
with? :O 

Thanks,
-- 
Jerome

>>>>>
>>>>>
>>>>> More complete log at https://pastebin.com/UZzZeicQ
>>>>
>>>> Thanks.
>>>>
>>>> Is this file in the v1 binary format (with the custom header),
>>
>> Yes
>>
>>>> or is
>>>> is a plain binary file? At present only the former is supported, as I
>>>> thought that it can only be the elf or the v1 binary format these
>>>> days?
>> Correct
>>
>>>> Actually can you please send me the tee.bin ?
>>
>> Sure, here you go: https://ufile.io/f/ex5oy
>>
>> I have added bl31.elf too, although I suppose it is handled properly
>> being an ELF file.
> 
> It seems to work for me.
> 
> [..]
> 
> Regards,
> Simon


Re: [PATCH v8 06/13] binman: Support new op-tee binary format

2023-01-07 Thread Jerome Forissier



On 1/7/23 19:55, Simon Glass wrote:
> Hi Quentin,
> 
> On Mon, 2 Jan 2023 at 10:54, Quentin Schulz
>  wrote:
>>
>> Hi Simon,
>>
>> On 12/22/22 00:07, Simon Glass wrote:
>>> OP-TEE has a format with a binary header that can be used instead of the
>>> ELF file. With newer versions of OP-TEE this may be required on some
>>> platforms.
>>>
>>> Add support for this in binman. First, add a method to obtain the ELF
>>> sections from an entry, then use that in the FIT support. We then end up
>>> with the ability to support both types of OP-TEE files, depending on which
>>> one is passed in with the entry argument (TEE=xxx in the U-Boot build).
>>>
>>> Signed-off-by: Simon Glass 
>>> ---
>>>
>>> (no changes since v7)
>>>
>>> Changes in v7:
>>> - Correct missing test coverage
>>>
>>> Changes in v6:
>>> - Update op-tee to support new v1 binary header
>>>
>>>   tools/binman/entries.rst | 35 -
>>>   tools/binman/entry.py| 13 +++
>>>   tools/binman/etype/fit.py| 69 +---
>>>   tools/binman/etype/section.py|  9 +++
>>>   tools/binman/etype/tee_os.py | 68 +++-
>>>   tools/binman/ftest.py| 83 
>>>   tools/binman/test/263_tee_os_opt.dts | 22 ++
>>>   tools/binman/test/264_tee_os_opt_fit.dts | 33 
>>>   tools/binman/test/265_tee_os_opt_fit_bad.dts | 40 ++
>>>   9 files changed, 340 insertions(+), 32 deletions(-)
>>>   create mode 100644 tools/binman/test/263_tee_os_opt.dts
>>>   create mode 100644 tools/binman/test/264_tee_os_opt_fit.dts
>>>   create mode 100644 tools/binman/test/265_tee_os_opt_fit_bad.dts
>>>
>>> diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst
>>> index b2ce7960d3b..a3e4493a44f 100644
>>> --- a/tools/binman/entries.rst
>>> +++ b/tools/binman/entries.rst
>>> @@ -1508,12 +1508,45 @@ Entry: tee-os: Entry containing an OP-TEE Trusted 
>>> OS (TEE) blob
>>>
>>>   Properties / Entry arguments:
>>>   - tee-os-path: Filename of file to read into entry. This is typically
>>> -called tee-pager.bin
>>> +called tee.bin or tee.elf
>>>
>>>   This entry holds the run-time firmware, typically started by U-Boot SPL.
>>>   See the U-Boot README for your architecture or board for how to use it. 
>>> See
>>>   
>>> https://urldefense.com/v3/__https://github.com/OP-TEE/optee_os__;!!OOPJP91ZZw!kx6SLv4sPusmg1TyYMw-Ho5G9jxeVMf9HOYx_4yq3ZNl_TpoGJoUyICZMgEiv0Zd6l_Bl8f5OAFYyJxm8wDUevhARIs$
>>>   for more information about OP-TEE.
>>>
>>> +Note that if the file is in ELF format, it must go in a FIT. In that case,
>>> +this entry will mark itself as absent, providing the data only through the
>>> +read_elf_segments() method.
>>> +
>>> +Marking this entry as absent means that it if is used in the wrong context
>>> +it can be automatically dropped. Thus it is possible to add anb OP-TEE 
>>> entry
>>
>> s/anb/an/
>>
>>> +like this::
>>> +
>>> +binman {
>>> +tee-os {
>>> +};
>>> +};
>>> +
>>> +and pass either an ELF or plain binary in with -a tee-os-path 
>>> +and have binman do the right thing:
>>> +
>>> +   - include the entry if tee.bin is provided and it doesn't have the v1
>>> + header
>>> +   - drop it otherwise
>>> +
>>
>> Is there an actual usecase for this? (sorry if this was mentioned in the
>> earlier versions of the patch) Are we expecting to be able to append the
>> content of tee-os to some raw binary instead of putting OP-TEE OS in a
>> u-boot.itb image?
> 
> Yes, that is my understanding. Perhaps it is for some archs or some
> old versions. But in any case, we can always drop it later if not
> needed, refine the warnings, etc. etc. But please let's land this mess
> and move on. If I had pushed a little harder a year ago we would have
> be talking about how to do this properly in binman rather than me
> trying to retrofit everything.
> 
> [..]
> 
>>
>> You can use a reference here since we have a _etype_fit target for "Flat
>> Image Tree / FIT".
>>
>>> +the binary v1 format is provided.
>>> +
>>>
>>
>> I'm a bit worried this is OP-TEE OS specific? We could also point to the
>> documentation here:
>> https://optee.readthedocs.io/en/latest/architecture/core.html#partitioning-of-the-binary?
> 
> Yes it is...I believe there will be other use cases for absent
> entriesin a way it is quite a big hold in binman's functionality.
> Will link to the docs.
> 
>>
>>>
>>>   .. _etype_text:
>>> diff --git a/tools/binman/entry.py b/tools/binman/entry.py
>>> index 637aece3705..de51d295891 100644
>>> --- a/tools/binman/entry.py
>>> +++ b/tools/binman/entry.py
>>> @@ -1290,3 +1290,16 @@ features to produce new behaviours.
>>>   def mark_absent(self, msg):
>>>   tout.info("Entry '%s' marked absent: %s" % (self._node.path, msg))
>>>   self.absent = True
>>> +
>>> +def read_elf_segments(self):
>>> +"""Read segments from an entry that can 

Re: [PATCH v8 06/13] binman: Support new op-tee binary format

2022-12-22 Thread Jerome Forissier



On 12/22/22 21:23, Simon Glass wrote:
> (dropping the two bounces from cc)
> 
> On Thu, 22 Dec 2022 at 13:18, Simon Glass  wrote:
>>
>> Hi Jerome,
>>
>> On Thu, 22 Dec 2022 at 08:36, Jerome Forissier
>>  wrote:
>>>
>>>
>>>
>>> On 12/22/22 00:07, Simon Glass wrote:
>>>> OP-TEE has a format with a binary header that can be used instead of the
>>>> ELF file. With newer versions of OP-TEE this may be required on some
>>>> platforms.
>>>>
>>>> Add support for this in binman. First, add a method to obtain the ELF
>>>> sections from an entry, then use that in the FIT support. We then end up
>>>> with the ability to support both types of OP-TEE files, depending on which
>>>> one is passed in with the entry argument (TEE=xxx in the U-Boot build).
>>>
>>> So, with:
>>>
>>> BL31=/path/to/bl31.elf TEE=/path/to/tee.bin make -C u-boot \
>>>   CROSS_COMPILE=aarch64-linux-gnu- CC=aarch64-linux-gnu-gcc \
>>>   HOSTCC=gcc BINMAN_DEBUG=1 BINMAN_VERBOSE=4
>>>
>>>
>>> ...I get:
>>>
>>> Entry '/binman/simple-bin/fit/images/@tee-SEQ/tee-os' marked absent: uses 
>>> v1 format which must be in a FIT
>>>
>>>
>>> More complete log at https://pastebin.com/UZzZeicQ
>>
>> Thanks.
>>
>> Is this file in the v1 binary format (with the custom header),

Yes

>> or is
>> is a plain binary file? At present only the former is supported, as I
>> thought that it can only be the elf or the v1 binary format these
>> days?
Correct

>> Actually can you please send me the tee.bin ?

Sure, here you go: https://ufile.io/f/ex5oy

I have added bl31.elf too, although I suppose it is handled properly
being an ELF file.

Thanks,
-- 
Jerome

>> Regards,
>> Simon
>>
>>
>>>
>>> Thanks,
>>> --
>>> Jerome
>>>
>>>> Signed-off-by: Simon Glass 
>>>> ---
>>>>
>>>> (no changes since v7)
>>>>
>>>> Changes in v7:
>>>> - Correct missing test coverage
>>>>
>>>> Changes in v6:
>>>> - Update op-tee to support new v1 binary header
>>>>
>>>>  tools/binman/entries.rst | 35 -
>>>>  tools/binman/entry.py| 13 +++
>>>>  tools/binman/etype/fit.py| 69 +---
>>>>  tools/binman/etype/section.py|  9 +++
>>>>  tools/binman/etype/tee_os.py | 68 +++-
>>>>  tools/binman/ftest.py| 83 
>>>>  tools/binman/test/263_tee_os_opt.dts | 22 ++
>>>>  tools/binman/test/264_tee_os_opt_fit.dts | 33 
>>>>  tools/binman/test/265_tee_os_opt_fit_bad.dts | 40 ++
>>>>  9 files changed, 340 insertions(+), 32 deletions(-)
>>>>  create mode 100644 tools/binman/test/263_tee_os_opt.dts
>>>>  create mode 100644 tools/binman/test/264_tee_os_opt_fit.dts
>>>>  create mode 100644 tools/binman/test/265_tee_os_opt_fit_bad.dts
>>>>
>>>> diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst
>>>> index b2ce7960d3b..a3e4493a44f 100644
>>>> --- a/tools/binman/entries.rst
>>>> +++ b/tools/binman/entries.rst
>>>> @@ -1508,12 +1508,45 @@ Entry: tee-os: Entry containing an OP-TEE Trusted 
>>>> OS (TEE) blob
>>>>
>>>>  Properties / Entry arguments:
>>>>  - tee-os-path: Filename of file to read into entry. This is typically
>>>> -called tee-pager.bin
>>>> +called tee.bin or tee.elf
>>>>
>>>>  This entry holds the run-time firmware, typically started by U-Boot SPL.
>>>>  See the U-Boot README for your architecture or board for how to use it. 
>>>> See
>>>>  https://github.com/OP-TEE/optee_os for more information about OP-TEE.
>>>>
>>>> +Note that if the file is in ELF format, it must go in a FIT. In that case,
>>>> +this entry will mark itself as absent, providing the data only through the
>>>> +read_elf_segments() method.
>>>> +
>>>> +Marking this entry as absent means that it if is used in the wrong context
>>>> +it can be automatically dropped. Thus it is possible to add anb OP-TEE 
>>>> entry
>>>> +like this::
>>>> +
>>>> +binman {
>>>> +   

Re: [PATCH v8 06/13] binman: Support new op-tee binary format

2022-12-22 Thread Jerome Forissier



On 12/22/22 00:07, Simon Glass wrote:
> OP-TEE has a format with a binary header that can be used instead of the
> ELF file. With newer versions of OP-TEE this may be required on some
> platforms.
> 
> Add support for this in binman. First, add a method to obtain the ELF
> sections from an entry, then use that in the FIT support. We then end up
> with the ability to support both types of OP-TEE files, depending on which
> one is passed in with the entry argument (TEE=xxx in the U-Boot build).

So, with:

BL31=/path/to/bl31.elf TEE=/path/to/tee.bin make -C u-boot \
  CROSS_COMPILE=aarch64-linux-gnu- CC=aarch64-linux-gnu-gcc \
  HOSTCC=gcc BINMAN_DEBUG=1 BINMAN_VERBOSE=4


...I get:

Entry '/binman/simple-bin/fit/images/@tee-SEQ/tee-os' marked absent: uses v1 
format which must be in a FIT


More complete log at https://pastebin.com/UZzZeicQ

Thanks,
-- 
Jerome

> Signed-off-by: Simon Glass 
> ---
> 
> (no changes since v7)
> 
> Changes in v7:
> - Correct missing test coverage
> 
> Changes in v6:
> - Update op-tee to support new v1 binary header
> 
>  tools/binman/entries.rst | 35 -
>  tools/binman/entry.py| 13 +++
>  tools/binman/etype/fit.py| 69 +---
>  tools/binman/etype/section.py|  9 +++
>  tools/binman/etype/tee_os.py | 68 +++-
>  tools/binman/ftest.py| 83 
>  tools/binman/test/263_tee_os_opt.dts | 22 ++
>  tools/binman/test/264_tee_os_opt_fit.dts | 33 
>  tools/binman/test/265_tee_os_opt_fit_bad.dts | 40 ++
>  9 files changed, 340 insertions(+), 32 deletions(-)
>  create mode 100644 tools/binman/test/263_tee_os_opt.dts
>  create mode 100644 tools/binman/test/264_tee_os_opt_fit.dts
>  create mode 100644 tools/binman/test/265_tee_os_opt_fit_bad.dts
> 
> diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst
> index b2ce7960d3b..a3e4493a44f 100644
> --- a/tools/binman/entries.rst
> +++ b/tools/binman/entries.rst
> @@ -1508,12 +1508,45 @@ Entry: tee-os: Entry containing an OP-TEE Trusted OS 
> (TEE) blob
>  
>  Properties / Entry arguments:
>  - tee-os-path: Filename of file to read into entry. This is typically
> -called tee-pager.bin
> +called tee.bin or tee.elf
>  
>  This entry holds the run-time firmware, typically started by U-Boot SPL.
>  See the U-Boot README for your architecture or board for how to use it. See
>  https://github.com/OP-TEE/optee_os for more information about OP-TEE.
>  
> +Note that if the file is in ELF format, it must go in a FIT. In that case,
> +this entry will mark itself as absent, providing the data only through the
> +read_elf_segments() method.
> +
> +Marking this entry as absent means that it if is used in the wrong context
> +it can be automatically dropped. Thus it is possible to add anb OP-TEE entry
> +like this::
> +
> +binman {
> +tee-os {
> +};
> +};
> +
> +and pass either an ELF or plain binary in with -a tee-os-path 
> +and have binman do the right thing:
> +
> +   - include the entry if tee.bin is provided and it doesn't have the v1
> + header
> +   - drop it otherwise
> +
> +When used within a FIT, we can do::
> +
> +binman {
> +fit {
> +tee-os {
> +};
> +};
> +};
> +
> +which will split the ELF into separate nodes for each segment, if an ELF
> +file is provide (see Flat Image Tree / FIT), or produce a single node if
> +the binary v1 format is provided.
> +
>  
>  
>  .. _etype_text:
> diff --git a/tools/binman/entry.py b/tools/binman/entry.py
> index 637aece3705..de51d295891 100644
> --- a/tools/binman/entry.py
> +++ b/tools/binman/entry.py
> @@ -1290,3 +1290,16 @@ features to produce new behaviours.
>  def mark_absent(self, msg):
>  tout.info("Entry '%s' marked absent: %s" % (self._node.path, msg))
>  self.absent = True
> +
> +def read_elf_segments(self):
> +"""Read segments from an entry that can generate an ELF file
> +
> +Returns:
> +tuple:
> +list of segments, each:
> +int: Segment number (0 = first)
> +int: Start address of segment in memory
> +bytes: Contents of segment
> +int: entry address of ELF file
> +"""
> +return None
> diff --git a/tools/binman/etype/fit.py b/tools/binman/etype/fit.py
> index 8ad4f3a8a83..21c769a1cbe 100644
> --- a/tools/binman/etype/fit.py
> +++ b/tools/binman/etype/fit.py
> @@ -540,41 +540,34 @@ class Entry_fit(Entry_section):
>  else:
>  self.Raise("Generator node requires 'fit,fdt-list' 
> property")
>  
> -def _gen_split_elf(base_node, node, elf_data, missing):
> +def _gen_split_elf(base_node, node, segments, entry_addr):
>  """Add nodes for the ELF file, one per group of contiguous 
> 

Re: [PATCH v7 06/12] binman: Support new op-tee binary format

2022-12-22 Thread Jerome Forissier



On 12/22/22 00:38, Simon Glass wrote:
> Hi Jerome,
> 
> On Wed, 21 Dec 2022 at 07:39, Jerome Forissier
>  wrote:
>>
>> Hi Simon,
>>
>> On 12/17/22 22:28, Simon Glass wrote:
>>> OP-TEE has a format with a binary header that can be used instead of the
>>> ELF file. With newer versions of OP-TEE this may be required on some
>>> platforms.
>>>
>>> Add support for this in binman. First, add a method to obtain the ELF
>>> sections from an entry, then use that in the FIT support. We then end up
>>> with the ability to support both types of OP-TEE files, depending on which
>>> one is passed in with the entry argument (TEE=xxx in the U-Boot build).
>>>
>>> Signed-off-by: Simon Glass 
>>> ---
>>>
>>> Changes in v7:
>>> - Correct missing test coverage
>>>
>>> Changes in v6:
>>> - Update op-tee to support new v1 binary header
>>
>> Thanks for the update. I'm trying to test this. How am I supposed to
>> pass the BL31 and TEE binaries? Currently I build u-boot with:
>>
>>   BL31=/path/to/bl31.elf TEE=/path/to/tee.bin make -C u-boot 
>> CROSS_COMPILE=aarch64-linux-gnu- CC=aarch64-linux-gnu-gcc HOSTCC=gcc
>>
>> I applied the series onto the 'next' branch and built as usual but the board
>> failed to boot so I suspect I am missing something.
> 
> Thanks for testing.
> 
> I seem to be missing setting the U-Boot load address. Also TEE is
> supposed to be optional, I believe.
> 
> I pushed an updated series to u-boot-dm/fit-working so could you try
> that (v8)? Also could you please include your board and console output
> if/when it fails?

OK, I will reply in the v8 thread to avoid ambiguities.


Thanks,
-- 
Jerome


Re: [PATCH v7 06/12] binman: Support new op-tee binary format

2022-12-21 Thread Jerome Forissier
Hi Simon,

On 12/17/22 22:28, Simon Glass wrote:
> OP-TEE has a format with a binary header that can be used instead of the
> ELF file. With newer versions of OP-TEE this may be required on some
> platforms.
> 
> Add support for this in binman. First, add a method to obtain the ELF
> sections from an entry, then use that in the FIT support. We then end up
> with the ability to support both types of OP-TEE files, depending on which
> one is passed in with the entry argument (TEE=xxx in the U-Boot build).
> 
> Signed-off-by: Simon Glass 
> ---
> 
> Changes in v7:
> - Correct missing test coverage
> 
> Changes in v6:
> - Update op-tee to support new v1 binary header

Thanks for the update. I'm trying to test this. How am I supposed to
pass the BL31 and TEE binaries? Currently I build u-boot with:

  BL31=/path/to/bl31.elf TEE=/path/to/tee.bin make -C u-boot 
CROSS_COMPILE=aarch64-linux-gnu- CC=aarch64-linux-gnu-gcc HOSTCC=gcc

I applied the series onto the 'next' branch and built as usual but the board
failed to boot so I suspect I am missing something.

Thanks,
-- 
Jerome


Re: [SPAM] [PATCH v5 4/7] rockchip: Support building the all output files in binman

2022-12-09 Thread Jerome Forissier



On 12/9/22 15:24, Quentin Schulz wrote:
> Hi Simon,
> 
> On 12/8/22 18:32, Simon Glass wrote:
>> Hi Xavier,
>>
>> On Fri, 9 Dec 2022 at 03:25, Xavier Drudis Ferran  wrote:
>>>
>>> El Thu, Dec 08, 2022 at 08:56:57AM +1300, Simon Glass deia:
 + @tee-SEQ {
 + fit,operation = "split-elf";
 + description = "TEE";
 + type = "tee";
 + arch = "arm64";
 + os = "tee";
 + compression = "none";
 + fit,load;
 + fit,entry;
 + fit,data;
 +
 + tee-os {
 + };
 + };
>>>
>>> I don't know, I may likely have missed something here, but are you sure 
>>> you're
>>> taking Jerome into account ?
>>>
>>> https://urldefense.com/v3/__https://lists.denx.de/pipermail/u-boot/2022-July/490069.html__;!!OOPJP91ZZw!ltyK0RA-1Vj1dgI1cBlgG1bJOhuZ4JGxwGBIl-Nt-hFz0eZTXmQKALvE9wCKtquDSpexcMtSVjm7ay_Mn7a5e-N4yIc$
>>> https://urldefense.com/v3/__https://lists.denx.de/pipermail/u-boot/2022-November/499306.html__;!!OOPJP91ZZw!ltyK0RA-1Vj1dgI1cBlgG1bJOhuZ4JGxwGBIl-Nt-hFz0eZTXmQKALvE9wCKtquDSpexcMtSVjm7ay_Mn7a5Y8ANiXk$
>>
>> No, I have not done that. The patches mentioned are additions to a
>> deprecated script!
>>
> 
> I think there's a a possible misunderstanding here. I believe Jerome pointed 
> out that make_fit_atf.py currently supports two formats for the tee binary 
> and is asking if the implementation you're suggesting take care of that.

Yes, and I suspect the answer is no ;)
 
>> It introduces a new binary format which binman needs to decode...

Correct, but this was done to fix an assumption that has never been
true in the first place: that OP-TEE's tee.elf file could be used
by bootloaders as the TEE image. It happened to work in the past and it
may still work depending on config options, but as described in [1],
the introduction of ASLR broke that assumption. Here I am speaking only
for OP-TEE, other TEEs may very well be supplied as ELF files of course.

[1] 348310233dac ("mach-rockchip: make_fit_atf.py: support OP-TEE tee.bin v1
format")

>> that
>> will need to be added as a new type, I think, since it seems to use
>> the filename suffix to decide what format it is in.

The suffix is a quick way to tell formats apart but some more precise
detection code could be used instead if needed (telling if a file is ELF
or is OP-TEE .bin can done by looking at the header). Or perhaps this
information should be provided by the user?
 
> If my aforementioned assumption is correct, that unfortunately would make 
> this patch series a regression, making it a blocker.

Agreed. Unfortunately I am not familiar *at all* with binman (or u-boot
in general), so I am not sure how I can help other than with testing. Or
maybe someone can propose some rough patch and I would insert the missing
bits? (i.e., parsing the OP-TEE header).

Thanks,
-- 
Jerome


Re: [PATCH 2/3] cmd: add maximum boot option index Kconfig option

2022-11-23 Thread Jerome Forissier
Hi,

On 11/23/22 08:17, Masahisa Kojima wrote:
> eficonfig command reads the all possible UEFI boot options
> from 0x to 0x to construct the menu. This takes too much
> time in some environment, especially for the platform using
> OP-TEE and RPMB based secure storage.
> For example, on Socionext Developerbox, it takes more than 30 seconds
> to draw the boot option menu.

How are you configuring the RPMB FS driver in OP-TEE [1]?
CFG_RPMB_FS_RD_ENTRIES and CFG_RPMB_FS_CACHE_ENTRIES affect how OP-TEE
reads and caches the File Allocation Table from RPMB, they have an
impact on the performance of file lookup. The default values are quite
conservative in terms of memory, with no caching and a read buffer
capable of holding entries for 8 files only. This can result is poor
performance but was considered a reasonable default considering
memory-constrained platforms.

Since Developerbox has lots of RAM, I suggest experimenting with larger
values. For the initial file enumeration, I think increasing
CFG_RPMB_FS_RD_ENTRIES should be enough to improve the situation quite
a bit. Subsequent enumerations and access to the file contents could be
improved by also increasing CFG_RPMB_FS_CACHE_ENTRIES. I would recommend
setting both to the same "rather large" value (128?). You might need
to increase the TEE core heap size though (CFG_CORE_HEAP_SIZE).

Then it would be nice to have these values defined as platform defaults
upstream rather than in some downstream fork of OP-TEE (I am saying this
because I suppose you already have custom values as part of some Yocto
build or something).

[1] https://github.com/OP-TEE/optee_os/blob/master/mk/config.mk#L170-L201

Thanks,
-- 
Jerome


Re: [PATCH] rockchip: rk3399: pass platform parameter to TF-A by default

2022-11-15 Thread Jerome Forissier
Hi Qentin,

On 11/15/22 11:05, Quentin Schulz wrote:
> Hi Jerome,
> 
> On 11/14/22 22:13, Jerome Forissier wrote:
>>
>>
>> On 11/14/22 18:37, Quentin Schulz wrote:
>>> From: Quentin Schulz 
>>>
>>> Long are gone the times TF-A couldn't handle the FDT passed by U-Boot.
>>> Specifically, since commit e7b586987c0a ("rockchip: don't crash if we
>>> get an FDT we can't parse") in TF-A, failure to parse the FDT will use
>>> the fallback mechanism. This patch was merged in TF-A v2.4-rc0 from two
>>> years ago.
>>>
>>> Therefore, let's finally pass the FDT to TF-A so that it can get the
>>> serial configuration from U-Boot FDT instead of requiring the user to
>>> patch TF-A hardcoded fallback values.
>>>
>>> Cc: Quentin Schulz 
>>> Signed-off-by: Quentin Schulz 
>>> ---
>>> rockchip: rk3399: pass platform parameter to TF-A
>>>
>>> Finally pass the FDT address to TF-A since it now gracefully fallbacks to
>>> hardcoded defaults if it cannot parse it. This allows us to avoid modifying
>>> hardcoded values in TF-A to enable the console.
>>
>> Does this mean that with this patch TF-A will properly set the baudrate of
>> the console UART to 1.5MBd? I'm asking because I am about to send the
> 
> Yes. I tested on my Puma RK3399 which defaults to 115200 with the following 
> patch:
> diff --git a/arch/arm/dts/rk3399-puma-haikou-u-boot.dtsi 
> b/arch/arm/dts/rk3399-puma-haikou-u-boot.dtsi
> index d2349ae90e..1c8ec97d44 100644
> --- a/arch/arm/dts/rk3399-puma-haikou-u-boot.dtsi
> +++ b/arch/arm/dts/rk3399-puma-haikou-u-boot.dtsi
> @@ -22,7 +22,7 @@
>  };
> 
>  chosen {
> -    stdout-path = "serial0:115200n8";
> +    stdout-path = "serial0:150n8";
>  u-boot,spl-boot-order = \
>  "same-as-spl", , , 
>  };
> diff --git a/configs/puma-rk3399_defconfig b/configs/puma-rk3399_defconfig
> index 91f31b37e8..0aa0c1d911 100644
> --- a/configs/puma-rk3399_defconfig
> +++ b/configs/puma-rk3399_defconfig
> @@ -92,6 +92,7 @@ CONFIG_PWM_ROCKCHIP=y
>  CONFIG_DM_RESET=y
>  CONFIG_DM_RTC=y
>  CONFIG_RTC_ISL1208=y
> +CONFIG_BAUDRATE=150
>  CONFIG_DEBUG_UART_SHIFT=2
>  CONFIG_ROCKCHIP_SPI=y
>  CONFIG_SYSRESET=y
> 
> and TF-A prints at that baudrate after reading it from the DT passed by 
> U-Boot (I added my own debug messages in TF-A to validate this claim).
> 
> This is supported since v2.2, commit 30970e0f2979 ("rockchip: make uart 
> baudrate configurable").

Cool. So your patch would fix Rockpi4 automagically it seems.

> 
>> following patch to TF-A (if I can figure out the Gerrit stuff that is...):
>>
> 
> Since I went through this yesterday:
> Link your GitHub account to the Gerrit instance.
> Add your public ssh key in 
> https://review.trustedfirmware.org/settings/#SSHKeys
> Then git clone the repo locally. For some reason the instructions in 
> https://review.trustedfirmware.org/admin/repos/TF-A/trusted-firmware-a do not 
> work for me, instead I did:
> git clone "https://review.trustedfirmware.org/TF-A/trusted-firmware-a;
> wget https://review.trustedfirmware.org/tools/hooks/commit-msg -O 
> trusted-firmware-a/.git/hooks/commit-msg
> chmod +x trusted-firmware-a/.git/hooks/commit-msg
> then you should be able to push with:
> git push origin HEAD:refs/for/integration -o topic=

Weird, I get a "Permission denied (public key)" error although my SSH key *is*
visible in the settings. Never mind since I don't need to send my patch
anymore ;-)

>
>> =
>>  From 51c1aa9277f6386b3a8055ad8ad582f894ab9230 Mon Sep 17 00:00:00 2001
>> From: Jerome Forissier 
>> Date: Thu, 10 Nov 2022 21:38:30 +0100
>> Subject: [PATCH] rk3399: set console baudrate to 150
>>
>> The default speed for the console UART of the rk3399 SoC is 1.5 MBaud.
>> It is the value used by U-Boot so if TF-A has a different value there
>> is no output when the boot switches from TPL to TF-A BL31 (note that
>> OP-TEE which does not change the speed). The Rockchip loader aka flash
>> helper (rk3399_loader_v1.20.119.bin [1][2]) also uses the same speed.
>> Therefore set the default baudrate to 150.
>>
> 
> This has already been discussed, see discussion there:
> https://developer.trustedfirmware.org/T762, I would suggest to try to revive 
> the discussion there.

Interesting. It looks like there is little hope of getting the default
speed changed. TBH I don't even understand why BL31 resets the console when
it could just use it, assuming a prior stage has set it up already (BL1/BL2
or in my case U-Boot).

Thanks,
-- 
Jerome


Re: [PATCH] rockchip: rk3399: pass platform parameter to TF-A by default

2022-11-14 Thread Jerome Forissier



On 11/14/22 18:37, Quentin Schulz wrote:
> From: Quentin Schulz 
> 
> Long are gone the times TF-A couldn't handle the FDT passed by U-Boot.
> Specifically, since commit e7b586987c0a ("rockchip: don't crash if we
> get an FDT we can't parse") in TF-A, failure to parse the FDT will use
> the fallback mechanism. This patch was merged in TF-A v2.4-rc0 from two
> years ago.
> 
> Therefore, let's finally pass the FDT to TF-A so that it can get the
> serial configuration from U-Boot FDT instead of requiring the user to
> patch TF-A hardcoded fallback values.
> 
> Cc: Quentin Schulz 
> Signed-off-by: Quentin Schulz 
> ---
> rockchip: rk3399: pass platform parameter to TF-A
> 
> Finally pass the FDT address to TF-A since it now gracefully fallbacks to
> hardcoded defaults if it cannot parse it. This allows us to avoid modifying
> hardcoded values in TF-A to enable the console.

Does this mean that with this patch TF-A will properly set the baudrate of
the console UART to 1.5MBd? I'm asking because I am about to send the
following patch to TF-A (if I can figure out the Gerrit stuff that is...):

=
>From 51c1aa9277f6386b3a8055ad8ad582f894ab9230 Mon Sep 17 00:00:00 2001
From: Jerome Forissier 
Date: Thu, 10 Nov 2022 21:38:30 +0100
Subject: [PATCH] rk3399: set console baudrate to 150

The default speed for the console UART of the rk3399 SoC is 1.5 MBaud.
It is the value used by U-Boot so if TF-A has a different value there
is no output when the boot switches from TPL to TF-A BL31 (note that
OP-TEE which does not change the speed). The Rockchip loader aka flash
helper (rk3399_loader_v1.20.119.bin [1][2]) also uses the same speed.
Therefore set the default baudrate to 150.

Link: [1] https://dl.radxa.com/rockpi/images/loader/
Link: [2] https://wiki.radxa.com/Rockpi4/dev/usb-install
Signed-off-by: Jerome Forissier 
---
 plat/rockchip/rk3399/rk3399_def.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/plat/rockchip/rk3399/rk3399_def.h 
b/plat/rockchip/rk3399/rk3399_def.h
index ba83242eb..8d6ecfbe6 100644
--- a/plat/rockchip/rk3399/rk3399_def.h
+++ b/plat/rockchip/rk3399/rk3399_def.h
@@ -17,7 +17,7 @@
 /**
  * UART related constants
  **/
-#define RK3399_BAUDRATE115200
+#define RK3399_BAUDRATE150
 #define RK3399_UART_CLOCK  2400
 
 /**
-- 
2.34.1
=

Thanks,
-- 
Jerome


Re: [PATCH v4 4/7] rockchip: Support building the all output files in binman

2022-11-07 Thread Jerome Forissier
On 11/6/22 23:40, Simon Glass wrote:
> Add the required binman images to replace the Makefile rules which are
> currently used. This includes subsuming:
> 
>- tpl/u-boot-tpl-rockchip.bin if TPL is enabled
>- idbloader.img if either or both of SPL and TPL are enabled
>- u-boot.itb if SPL_FIT is enabled
>- u-boot-rockchip.bin if SPL is used, either using u-boot.itb when
>  SPL_FIT is enabled or u-boot.img when it isn't
> 
> Note that the intermediate files are dropped with binman, since it
> producing everything in one pass. This means that
> tpl/u-boot-tpl-rockchip.bin is not created, for example.
> 
> Note that for some 32-bit rk3288 boards, rockchip-optee.dtsi is included.
> 
> Signed-off-by: Simon Glass 
> ---
> 
> (no changes since v3)
> 
> Changes in v3:
> - Add an offset to the FIT description
> 
> Changes in v2:
> - Rename op-tee to tee-os
> - Drop use of .itb2
> 
>  arch/arm/dts/rockchip-u-boot.dtsi | 73 ---
>  1 file changed, 68 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/arm/dts/rockchip-u-boot.dtsi 
> b/arch/arm/dts/rockchip-u-boot.dtsi
> index 584f21eb5bf..084f72b0bd4 100644
> --- a/arch/arm/dts/rockchip-u-boot.dtsi
> +++ b/arch/arm/dts/rockchip-u-boot.dtsi
> @@ -30,14 +30,77 @@
>   };
>   };
>  
> -#ifdef CONFIG_ARM64
> - blob {
> +#if defined(CONFIG_SPL_FIT) && defined(CONFIG_ARM64)
> + fit: fit {
> + description = "FIT image for U-Boot with bl31 (TF-A)";
> + #address-cells = <1>;
> + fit,fdt-list = "of-list";
>   filename = "u-boot.itb";
> + fit,external-offset = ;
> + offset = ;
> + images {
> + u-boot {
> + description = "U-Boot (64-bit)";
> + type = "standalone";
> + os = "U-Boot";
> + arch = "arm64";
> + compression = "none";
> + load = ;
> + u-boot-nodtb {
> + };
> + };
> +
> + @atf-SEQ {
> + fit,operation = "split-elf";
> + description = "ARM Trusted Firmware";
> + type = "firmware";
> + arch = "arm64";
> + os = "arm-trusted-firmware";
> + compression = "none";
> + fit,load;
> + fit,entry;
> + fit,data;
> +
> + atf-bl31 {
> + };
> + };
> + @tee-SEQ {
> + fit,operation = "split-elf";

Does this imply that the TEE image shall be supplied as an ELF file? That won't
work with OP-TEE, see commit 348310233dac ("mach-rockchip: make_fit_atf.py:
support OP-TEE tee.bin v1 format").

> + description = "TEE";
> + type = "tee";
> + arch = "arm64";
> + os = "tee";
> + compression = "none";
> + fit,load;
> + fit,entry;
> + fit,data;
> +
> + tee-os {
> + };
> + };

Thanks,
-- 
Jerome


Re: [PATCH] mmc: dwmmc: only clear handled interrupts

2022-09-16 Thread Jerome Forissier



On 9/15/22 19:56, John Keeping wrote:
> Unconditionally clearing DTO when RXDR is set leads to spurious timeouts
> in FIFO mode transfers if events occur in the following order:
> 
>   mask = dwmci_readl(host, DWMCI_RINTSTS);
> 
>   // Hardware asserts DWMCI_INTMSK_DTO here
> 
>   dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_DTO);
> 
>   if (mask & DWMCI_INTMSK_DTO) {
>   // Unreachable as DTO is cleared without being handled!
>   return 0;
>   }
> 
> Only clear interrupts that we have seen and are handling so that DTO is
> not missed.
> 
> Signed-off-by: John Keeping 
> ---
>  drivers/mmc/dw_mmc.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
> index 4232c5eb8c..5085a3b491 100644
> --- a/drivers/mmc/dw_mmc.c
> +++ b/drivers/mmc/dw_mmc.c
> @@ -168,7 +168,8 @@ static int dwmci_data_transfer(struct dwmci_host *host, 
> struct mmc_data *data)
>   if (data->flags == MMC_DATA_READ &&
>   (mask & (DWMCI_INTMSK_RXDR | DWMCI_INTMSK_DTO))) {
>   dwmci_writel(host, DWMCI_RINTSTS,
> -  DWMCI_INTMSK_RXDR | 
> DWMCI_INTMSK_DTO);
> +  mask & (DWMCI_INTMSK_RXDR |
> +  DWMCI_INTMSK_DTO));
>   while (size) {
>       ret = dwmci_fifo_ready(host,
>   DWMCI_FIFO_EMPTY,

Tested-by: Jerome Forissier  (Rock PI 4B)

Boot logs:

- 2022.04 without this patch:

[...]
U-Boot SPL 2022.04 (Apr 04 2022 - 14:31:32 +)

Trying to boot from MMC1

## Checking hash(es) for config config_1 ... sha1,rsa2048:dev+ OK

## Checking hash(es) for Image atf_1 ... sha1+ sha1,rsa2048:dev+ OK

## Checking hash(es) for Image uboot ... sha1+ sha1,rsa2048:dev+ OK

## Checking hash(es) for Image fdt_1 ... sha1+ sha1,rsa2048:dev+ OK

spl_load_simple_fit: can't load image loadables index 1 (ret = -5)

mmc_load_image_raw_sector: mmc block read error


[...]

- 2022.04 with this patch:

[...]
U-Boot SPL 2022.04 (Apr 04 2022 - 14:31:32 +)

Trying to boot from MMC1

## Checking hash(es) for config config_1 ... sha1,rsa2048:dev+ OK

## Checking hash(es) for Image atf_1 ... sha1+ sha1,rsa2048:dev+ OK

## Checking hash(es) for Image uboot ... sha1+ sha1,rsa2048:dev+ OK

## Checking hash(es) for Image fdt_1 ... sha1+ sha1,rsa2048:dev+ OK

## Checking hash(es) for Image atf_2 ... sha1+ sha1,rsa2048:dev+ OK

## Checking hash(es) for Image atf_3 ... sha1+ sha1,rsa2048:dev+ OK

## Checking hash(es) for Image atf_4 ... sha1+ sha1,rsa2048:dev+ OK

NOTICE:  BL31: v2.6(debug):v2.6-879-gc3bdd3d3cf-dirty

[...]

Thanks,
-- 
Jerome


Re: Replace make-fit-atf.py with binman. Was: migrate u-boot-rockchip.bin to binman and generate an image for SPI

2022-07-26 Thread Jerome Forissier



On 7/26/22 21:08, Xavier Drudis Ferran wrote:
> El Tue, Jul 26, 2022 at 11:08:21AM +0200, Quentin Schulz deia:
>>
>> You could also have a fit,align = <8>; property instead of hardcoding it.
> 
> I'm not sure the fit entry in binman heeds this property, may have
> overlooked something. I'd have to try it.
> 
>> The issue is that this flag seems to be added only for u-boot.itb and
>> fit-dtb.blob. I assume there are usecases outside of those two binaries
>> where the user does not want the fit header to be aligned (or don't need
>> it).
> 
> The commit message said that the device tree spec requires 4 or 8 byte
> alignment, so maybe all fits want it because all fits are device trees
> ? Not sure.
> 
 +  configurations {
 +  default = "@config_DEFAULT-SEQ";
 +
 +  @config_SEQ {
 +  description = "NAME.dtb";
 +  fdt = "fdt_SEQ";
 +  firmware = "atf_1";
 +  loadables = "uboot","atf_2","atf_3";
>>
>> This section will need some more love with some ifdef for ATF_SPL and TEE.
>>
> 
> I'm sending a patch below that adds a couple of configuration properties to 
> binman so that split-elf can fill the properties. How many segments are 
> in bl31.elf or optee is not something that we have in CONFIGs, I think, 
> so it may be difficult to catch all cases with ifdefs.

Careful with OP-TEE: tee.elf must NOT be used, please see commit
348310233dac ("mach-rockchip: make_fit_atf.py: support OP-TEE tee.bin v1
format").

-- 
Jerome


[PATCH v2 2/2] rockchip: rk3399: enable spl-fifo-mode for sdmmc only when needed

2022-06-29 Thread Jerome Forissier
Commit 5c606ca35c42 ("rockchip: rk3399: enable spl-fifo-mode for sdmmc")
mentions that the RK3399 SoC can't do DMA between SDMMC and SRAM.
According to the TRM "7.3.2 Embedded SRAM access path" [1], only the
8KB SRAM at 0xff3b (INTMEM1) is in this situation. The 192KB SRAM
can be accessed by both DMA controllers.

Assuming the only use case for writing from MMC to INTMEM1 is loading
a FIT image, and with the introduction of a temporary buffer for that
purpose (CONFIG_SPL_LOAD_FIT_IMAGE_BUFFER_SIZE, which is required
anyways to ensure the destination boundaries are enforced), then
spl-fifo-mode is not needed anymore and DMA can be enabled safely.

Link: [1] https://www.rockchip.fr/Rockchip%20RK3399%20TRM%20V1.4%20Part1.pdf
CC: Deepak Das 
Signed-off-by: Jerome Forissier 
---
Changes since v1:
- Fixed conditional (#if ... == 0 instead or #ifndef)
---
 arch/arm/dts/rk3399-u-boot.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/dts/rk3399-u-boot.dtsi b/arch/arm/dts/rk3399-u-boot.dtsi
index 716b9a433a..1be1a40bdb 100644
--- a/arch/arm/dts/rk3399-u-boot.dtsi
+++ b/arch/arm/dts/rk3399-u-boot.dtsi
@@ -124,8 +124,10 @@
  {
u-boot,dm-pre-reloc;
 
+#if (CONFIG_SPL_LOAD_FIT_IMAGE_BUFFER_SIZE == 0)
/* mmc to sram can't do dma, prevent aborts transferring TF-A parts */
u-boot,spl-fifo-mode;
+#endif
 };
 
  {
-- 
2.34.1



[PATCH v2 1/2] spl: fit: add config option for temporary buffer when loading image

2022-06-29 Thread Jerome Forissier
When the load address of a FIT image isn't properly aligned,
spl_load_fit_image() may write past the end of the destination buffer. It
is not an issue in many cases because the memory happens to be writeable
and nothing important is present in the overflow. On RockPi4 however there
is a configuration where a TF-A image (bl31_0xff3b.bin) has to be
loaded into a 8K range of SRAM memory, between 0xff3b and 0xff3b2000.
The end address is a hard limit, because due to the way the hardware is
wired, the addresses wrap and any overflow gets written back to 0xff3b
thus overwriting previous data.

To address this problem, introduce a helper function which loads data using
a temporary buffer allocated on the stack. The size of the buffer is
defined by SPL_LOAD_FIT_IMAGE_BUFFER_SIZE (default 0x0 or disabled).

Co-developed-by: Xavier Drudis Ferran 
Signed-off-by: Xavier Drudis Ferran 
Signed-off-by: Jerome Forissier 
---
 common/spl/Kconfig   | 45 +
 common/spl/spl_fit.c | 79 
 2 files changed, 118 insertions(+), 6 deletions(-)

diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 50ff113cab..d95141a6f6 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -1339,6 +1339,51 @@ config SPL_OPENSBI_LOAD_ADDR
help
  Load address of the OpenSBI binary.
 
+config SPL_LOAD_FIT_IMAGE_BUFFER_SIZE
+   hex "Read unaligned external FIT images to a temporary buffer in SPL"
+   default 0x0
+   depends on SPL_LOAD_FIT
+   help
+ An aligned FIT image is such that it starts at the beginning
+ of a block in media and has a load_addr in its FIT header
+ that is DMA aligned in RAM. These aligned images can be read
+ directly from media to RAM. Unaligned external FIT images
+ are those that need reading some extra data before and/or after
+ the image because they don't occupy fully the blocks they're
+ in in media, or their destination is not DMA aligned and must
+ be read somewhere aligned before copying them to load_addr.
+
+ With this option set to 0x0 full blocks will just be read in
+ the closest DMA aligned address, and the unaligned image
+ inside those read blocks will later be copied to
+ load_addr. Meanwhile memory outside [load_addr,
+ load_addr+length) will have been written. That's no problem
+ when the block length, image size and load_addr have been
+ taken into account when laying out memory.
+
+ But in some cases not all memory is writable, or undesired
+ effects arise when writing outside [load_addr,
+ load_addr+length). For instance, in RK3399, one of the
+ images is ATF2, of size 8KiB which should be loaded into
+ INTMEM1, at address 0xff3b. This address is DMA aligned
+ but tight. It maps to a 8KiB SRAM area. If the image on
+ media is not block aligned some extra bytes get read before
+ and after, and everything extra written in
+ 0xff3b2000-0xff3b corrupts SRAM at
+ 0xff3b-0xff3b1fff before the image is memcpyied in place.
+
+ With this option set to a nonzero value a DMA aligned buffer
+ will be allocated on the stack and the image will be read
+ in chuncks of blocks to this buffer, with each chunk being
+ memcpyied to [load_addr,load_addr+length), so never writing
+ outside the destination area.
+
+ The advantage of enabling this option is safety, and the
+ disadvantage is more stack use and slower image load (one read
+ per chunk instead of just one).
+
+ The default is 0x0 to replicate previous behaviour.
+
 config TPL
bool
depends on SUPPORT_TPL
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index 1bbf824684..56775fd744 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -218,6 +219,64 @@ static int get_aligned_image_size(struct spl_load_info 
*info, int data_size,
return (data_size + info->bl_len - 1) / info->bl_len;
 }
 
+#if (CONFIG_SPL_LOAD_FIT_IMAGE_BUFFER_SIZE != 0x0)
+static int load_with_tmpbuf(struct spl_load_info *info, ulong load_addr,
+   ulong sector, int offs, size_t len)
+{
+   ALLOC_CACHE_ALIGN_BUFFER(u8, buf,
+CONFIG_SPL_LOAD_FIT_IMAGE_BUFFER_SIZE);
+   void *dst = (void *)load_addr;
+   int nsect = (len + offs + info->bl_len - 1) / info->bl_len;
+   int bufsect = (CONFIG_SPL_LOAD_FIT_IMAGE_BUFFER_SIZE) / info->bl_len;
+   size_t sz, tail = 0;
+
+   if (offs) {
+   sz = info->bl_len - offs;
+   if (sz > len)
+   sz = len;
+   if (info->read(info, sector, 1, buf) != 1)
+

[PATCH v2 0/2] spl, rk3399: fix FIT image loading out-of-range

2022-06-29 Thread Jerome Forissier
The patches in this series address an issue I met when trying to enable
FIT signature verification by SPL on a RockPi4B board.

- The first patch avoids a buffer overflow when writing to INTMEM1 SRAM
- The second one addresses reliability issues I had with back-to-back
MMC reads from the microSD card. By allowing DMA operation, the issue is
gone and generally speaking DMA is preferred over FIFO mode anyways.

Jerome Forissier (2):
  spl: fit: add config option for temporary buffer when loading image
  rockchip: rk3399: enable spl-fifo-mode for sdmmc only when needed

 arch/arm/dts/rk3399-u-boot.dtsi |  2 +
 common/spl/Kconfig  | 45 +++
 common/spl/spl_fit.c| 79 ++---
 3 files changed, 120 insertions(+), 6 deletions(-)

-- 
2.34.1



Re: [PATCH 2/2] rockchip: rk3399: enable spl-fifo-mode for sdmmc only when needed

2022-06-29 Thread Jerome Forissier



On 6/29/22 05:01, Kever Yang wrote:
> 
> On 2022/6/9 23:23, Jerome Forissier wrote:
>> Commit 5c606ca35c42 ("rockchip: rk3399: enable spl-fifo-mode for sdmmc")
>> mentions that the RK3399 SoC can't do DMA between SDMMC and SRAM.
>> According to the TRM "7.3.2 Embedded SRAM access path" [1], only the
>> 8KB SRAM at 0xff3b (INTMEM1) is in this situation. The 192KB SRAM
>> can be accessed by both DMA controllers.
>>
>> Assuming the only use case for writing from MMC to INTMEM1 is loading
>> a FIT image, and with the introduction of a temporary buffer for that
>> purpose (CONFIG_SPL_LOAD_FIT_IMAGE_BUFFER_SIZE, which is required
>> anyways to ensure the destination boundaries are enforced), then
>> spl-fifo-mode is not needed anymore and DMA can be enabled safely.
>>
>> Link: [1] https://www.rockchip.fr/Rockchip%20RK3399%20TRM%20V1.4%20Part1.pdf
>> CC: Deepak Das 
>> Signed-off-by: Jerome Forissier 
> 
> Reviewed-by: Kever Yang 

Thanks. I will post a v2 with the corrected conditional [#if (xxx == 0)].

-- 
Jerome
> 
> Thanks,
> 
> - Kever
> 
>> ---
>>   arch/arm/dts/rk3399-u-boot.dtsi | 2 ++
>>   1 file changed, 2 insertions(+)
>>
>> diff --git a/arch/arm/dts/rk3399-u-boot.dtsi 
>> b/arch/arm/dts/rk3399-u-boot.dtsi
>> index 716b9a433a..a1b6d6f007 100644
>> --- a/arch/arm/dts/rk3399-u-boot.dtsi
>> +++ b/arch/arm/dts/rk3399-u-boot.dtsi
>> @@ -124,8 +124,10 @@
>>    {
>>   u-boot,dm-pre-reloc;
>>   +#ifndef CONFIG_SPL_LOAD_FIT_IMAGE_BUFFER_SIZE
>>   /* mmc to sram can't do dma, prevent aborts transferring TF-A parts */
>>   u-boot,spl-fifo-mode;
>> +#endif
>>   };
>>      {


Re: [PATCH] mach-rockchip: make_fit_atf.py: support OP-TEE tee.bin v1 format

2022-06-20 Thread Jerome Forissier
Hi,

On 5/11/22 17:35, Jerome Forissier wrote:
> This commit adds support for the OP-TEE 'tee.bin' v1 format for Rockchip
> platforms.
> 
> Since OP-TEE 3.8.0, tee.bin contains meta-data in a proprietary format
> in addition to the ELF data. They are essential information for proper
> initialization of the TEE core, such as the size of the memory region
> covered by the TEE or a compact representation of runtime relocation
> data when ASLR is enabled.
> 
> With OP-TEE 3.8.0 onwards, 'tee.elf' MUST NOT be used and 'tee.bin'
> MUST be used instead. Ignoring this recommendation can lead to crashes
> as described in [3].
> 
> Link: [1] 
> https://github.com/OP-TEE/optee_os/commit/5dd1570ac5b0f6563b1a9c074533a19107b8222d
> Link: [2] 
> https://github.com/OP-TEE/optee_os/blob/3.17.0/scripts/gen_tee_bin.py#L275-L302
> Link: [3] https://github.com/OP-TEE/optee_os/issues/4542
> Signed-off-by: Jerome Forissier 
> ---
>  arch/arm/mach-rockchip/make_fit_atf.py | 43 +-
>  1 file changed, 35 insertions(+), 8 deletions(-)

I have just seen the v2022.07-rc5 announcement. I'm wondering if this
fix would be suitable for inclusion? Or is it too late in the RC cycle?

Thanks,
-- 
Jerome


Re: [PATCH 2/2] rockchip: rk3399: enable spl-fifo-mode for sdmmc only when needed

2022-06-14 Thread Jerome Forissier



On 6/9/22 08:23, Jerome Forissier wrote:
> Commit 5c606ca35c42 ("rockchip: rk3399: enable spl-fifo-mode for sdmmc")
> mentions that the RK3399 SoC can't do DMA between SDMMC and SRAM.
> According to the TRM "7.3.2 Embedded SRAM access path" [1], only the
> 8KB SRAM at 0xff3b (INTMEM1) is in this situation. The 192KB SRAM
> can be accessed by both DMA controllers.
> 
> Assuming the only use case for writing from MMC to INTMEM1 is loading
> a FIT image, and with the introduction of a temporary buffer for that
> purpose (CONFIG_SPL_LOAD_FIT_IMAGE_BUFFER_SIZE, which is required
> anyways to ensure the destination boundaries are enforced), then
> spl-fifo-mode is not needed anymore and DMA can be enabled safely.
> 
> Link: [1] https://www.rockchip.fr/Rockchip%20RK3399%20TRM%20V1.4%20Part1.pdf
> CC: Deepak Das 
> Signed-off-by: Jerome Forissier 
> ---
>  arch/arm/dts/rk3399-u-boot.dtsi | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/arch/arm/dts/rk3399-u-boot.dtsi b/arch/arm/dts/rk3399-u-boot.dtsi
> index 716b9a433a..a1b6d6f007 100644
> --- a/arch/arm/dts/rk3399-u-boot.dtsi
> +++ b/arch/arm/dts/rk3399-u-boot.dtsi
> @@ -124,8 +124,10 @@
>   {
>   u-boot,dm-pre-reloc;
>  
> +#ifndef CONFIG_SPL_LOAD_FIT_IMAGE_BUFFER_SIZE

Oops, that should rather be:

+#if (CONFIG_SPL_LOAD_FIT_IMAGE_BUFFER_SIZE == 0)

>   /* mmc to sram can't do dma, prevent aborts transferring TF-A parts */
>   u-boot,spl-fifo-mode;
> +#endif
>  };
>  
>   {


[PATCH] rockchip: make_fit_atf: generate signed conf when FIT_SIGN_KEY is set

2022-06-09 Thread Jerome Forissier
Introduce the environment variable FIT_SIGN_KEY which when set is the name
of the key that should be used to sign the binaries and configuration in
the FIT image. Usage example (tested on RockPi4B):

 mkdir keys
 openssl genpkey -algorithm RSA -out keys/dev.key \
-pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537
 openssl req -batch -new -x509 -key keys/dev.key -out keys/dev.crt
 FIT_SIGN_KEY=dev TEE=.../tee.bin BL31=.../bl31.elf \
../../git/arch/arm/mach-rockchip/make_fit_atf.py \
arch/arm/dts/rk3399-rock-pi-4b.dtb > u-boot.its
 cp spl/dts/dt-spl.dtb spl/u-boot-spl.dtb
 ./tools/mkimage -E -B 0x8 -p 0x0 -f u-boot.its -k keys \
-r -K spl/u-boot-spl.dtb u-boot.itb
 cat tpl/u-boot-tpl-rockchip.bin spl/u-boot-spl-nodtb.bin \
spl/u-boot-spl.dtb > idbloader.img

Signed-off-by: Jerome Forissier 
---
 arch/arm/mach-rockchip/make_fit_atf.py | 49 ++
 1 file changed, 34 insertions(+), 15 deletions(-)

diff --git a/arch/arm/mach-rockchip/make_fit_atf.py 
b/arch/arm/mach-rockchip/make_fit_atf.py
index f3224d2555..e587760ccf 100755
--- a/arch/arm/mach-rockchip/make_fit_atf.py
+++ b/arch/arm/mach-rockchip/make_fit_atf.py
@@ -28,19 +28,6 @@ DT_HEADER = """
images {
 """
 
-DT_UBOOT = """
-   uboot {
-   description = "U-Boot (64-bit)";
-   data = /incbin/("u-boot-nodtb.bin");
-   type = "standalone";
-   os = "U-Boot";
-   arch = "arm64";
-   compression = "none";
-   load = <0x%08x>;
-   };
-
-"""
-
 DT_IMAGES_NODE_END = """   };
 
 """
@@ -60,6 +47,7 @@ def append_bl31_node(file, atf_index, phy_addr, elf_entry):
 file.write('\t\t\tload = <0x%08x>;\n' % phy_addr)
 if atf_index == 1:
 file.write('\t\t\tentry = <0x%08x>;\n' % elf_entry)
+append_hash_sig_nodes(file)
 file.write('\t\t};\n')
 file.write('\n')
 
@@ -75,6 +63,7 @@ def append_tee_node(file, atf_index, phy_addr, elf_entry):
 file.write('\t\t\tcompression = "none";\n')
 file.write('\t\t\tload = <0x%08x>;\n' % phy_addr)
 file.write('\t\t\tentry = <0x%08x>;\n' % elf_entry)
+append_hash_sig_nodes(file)
 file.write('\t\t};\n')
 file.write('\n')
 
@@ -88,6 +77,7 @@ def append_fdt_node(file, dtbs):
 file.write('\t\t\tdata = /incbin/("%s");\n' % dtb)
 file.write('\t\t\ttype = "flat_dt";\n')
 file.write('\t\t\tcompression = "none";\n')
+append_hash_sig_nodes(file)
 file.write('\t\t};\n')
 file.write('\n')
 cnt = cnt + 1
@@ -108,6 +98,13 @@ def append_conf_section(file, cnt, dtname, segments):
 if segments <= 1:
 file.write(';\n')
 file.write('\t\t\tfdt = "fdt_%d";\n' % cnt)
+key_name = os.getenv('FIT_SIGN_KEY')
+if key_name:
+file.write('\t\t\tsignature {\n')
+file.write('\t\t\t\tsign-images = "firmware","loadables","fdt";\n')
+file.write('\t\t\t\talgo = "sha1,rsa2048";\n')
+file.write('\t\t\t\tkey-name-hint = "dev";\n')
+file.write('\t\t\t};\n')
 file.write('\t\t};\n')
 file.write('\n')
 
@@ -123,12 +120,34 @@ def append_conf_node(file, dtbs, segments):
 file.write('\t};\n')
 file.write('\n')
 
-def generate_atf_fit_dts_uboot(fit_file, uboot_file_name):
+def generate_atf_fit_dts_uboot(file, uboot_file_name):
 segments = unpack_elf(uboot_file_name)
 if len(segments) != 1:
 raise ValueError("Invalid u-boot ELF image '%s'" % uboot_file_name)
 index, entry, p_paddr, data = segments[0]
-fit_file.write(DT_UBOOT % p_paddr)
+file.write('\n')
+file.write('\t\tuboot {\n')
+file.write('\t\t\tdescription = "U-Boot (64-bit)";\n')
+file.write('\t\t\tdata = /incbin/("u-boot-nodtb.bin");\n')
+file.write('\t\t\ttype = "standalone";\n')
+file.write('\t\t\tos = "U-Boot";\n')
+file.write('\t\t\tarch = "arm64";\n')
+file.write('\t\t\tcompression = "none";\n')
+file.write('\t\t\tload = <0x%08x>;\n' % p_paddr)
+append_hash_sig_nodes(file)
+file.write('\t\t};\n')
+file.write('\n')
+
+def append_hash_sig_nodes(file):
+key_name = os.getenv("FIT_SIGN_KEY")
+if key_name:
+file.write('\t\t\thash-1 {\n')
+file.write('\t\t\t\talgo = "sha1";\n')
+file.write('\t\t\t};\n')
+file.write('\t\t\tsignature-1 {\n')
+file.write('\t\t\t\talgo = "sha1,rsa2048";\n')
+file.write('\t\t\t\tkey-name-hint = "%s";\n' % key_name)
+file.write('\t\t\t};\n')
 
 def generate_atf_fit_dts_bl31(fit_file, bl31_file_name, tee_file_name, 
dtbs_file_name):
 segments = unpack_elf(bl31_file_name)
-- 
2.34.1



[PATCH 1/2] spl: fit: add config option for temporary buffer when loading image

2022-06-09 Thread Jerome Forissier
When the load address of a FIT image isn't properly aligned,
spl_load_fit_image() may write past the end of the destination buffer. It
is not an issue in many cases because the memory happens to be writeable
and nothing important is present in the overflow. On RockPi4 however there
is a configuration where a TF-A image (bl31_0xff3b.bin) has to be
loaded into a 8K range of SRAM memory, between 0xff3b and 0xff3b2000.
The end address is a hard limit, because due to the way the hardware is
wired, the addresses wrap and any overflow gets written back to 0xff3b
thus overwriting previous data.

To address this problem, introduce a helper function which loads data using
a temporary buffer allocated on the stack. The size of the buffer is
defined by SPL_LOAD_FIT_IMAGE_BUFFER_SIZE (default 0x0 or disabled).

Co-developed-by: Xavier Drudis Ferran 
Signed-off-by: Xavier Drudis Ferran 
Signed-off-by: Jerome Forissier 
---
 common/spl/Kconfig   | 45 +
 common/spl/spl_fit.c | 79 
 2 files changed, 118 insertions(+), 6 deletions(-)

diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 50ff113cab..d95141a6f6 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -1339,6 +1339,51 @@ config SPL_OPENSBI_LOAD_ADDR
help
  Load address of the OpenSBI binary.
 
+config SPL_LOAD_FIT_IMAGE_BUFFER_SIZE
+   hex "Read unaligned external FIT images to a temporary buffer in SPL"
+   default 0x0
+   depends on SPL_LOAD_FIT
+   help
+ An aligned FIT image is such that it starts at the beginning
+ of a block in media and has a load_addr in its FIT header
+ that is DMA aligned in RAM. These aligned images can be read
+ directly from media to RAM. Unaligned external FIT images
+ are those that need reading some extra data before and/or after
+ the image because they don't occupy fully the blocks they're
+ in in media, or their destination is not DMA aligned and must
+ be read somewhere aligned before copying them to load_addr.
+
+ With this option set to 0x0 full blocks will just be read in
+ the closest DMA aligned address, and the unaligned image
+ inside those read blocks will later be copied to
+ load_addr. Meanwhile memory outside [load_addr,
+ load_addr+length) will have been written. That's no problem
+ when the block length, image size and load_addr have been
+ taken into account when laying out memory.
+
+ But in some cases not all memory is writable, or undesired
+ effects arise when writing outside [load_addr,
+ load_addr+length). For instance, in RK3399, one of the
+ images is ATF2, of size 8KiB which should be loaded into
+ INTMEM1, at address 0xff3b. This address is DMA aligned
+ but tight. It maps to a 8KiB SRAM area. If the image on
+ media is not block aligned some extra bytes get read before
+ and after, and everything extra written in
+ 0xff3b2000-0xff3b corrupts SRAM at
+ 0xff3b-0xff3b1fff before the image is memcpyied in place.
+
+ With this option set to a nonzero value a DMA aligned buffer
+ will be allocated on the stack and the image will be read
+ in chuncks of blocks to this buffer, with each chunk being
+ memcpyied to [load_addr,load_addr+length), so never writing
+ outside the destination area.
+
+ The advantage of enabling this option is safety, and the
+ disadvantage is more stack use and slower image load (one read
+ per chunk instead of just one).
+
+ The default is 0x0 to replicate previous behaviour.
+
 config TPL
bool
depends on SUPPORT_TPL
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index 1bbf824684..56775fd744 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -218,6 +219,64 @@ static int get_aligned_image_size(struct spl_load_info 
*info, int data_size,
return (data_size + info->bl_len - 1) / info->bl_len;
 }
 
+#if (CONFIG_SPL_LOAD_FIT_IMAGE_BUFFER_SIZE != 0x0)
+static int load_with_tmpbuf(struct spl_load_info *info, ulong load_addr,
+   ulong sector, int offs, size_t len)
+{
+   ALLOC_CACHE_ALIGN_BUFFER(u8, buf,
+CONFIG_SPL_LOAD_FIT_IMAGE_BUFFER_SIZE);
+   void *dst = (void *)load_addr;
+   int nsect = (len + offs + info->bl_len - 1) / info->bl_len;
+   int bufsect = (CONFIG_SPL_LOAD_FIT_IMAGE_BUFFER_SIZE) / info->bl_len;
+   size_t sz, tail = 0;
+
+   if (offs) {
+   sz = info->bl_len - offs;
+   if (sz > len)
+   sz = len;
+   if (info->read(info, sector, 1, buf) != 1)
+

[PATCH 2/2] rockchip: rk3399: enable spl-fifo-mode for sdmmc only when needed

2022-06-09 Thread Jerome Forissier
Commit 5c606ca35c42 ("rockchip: rk3399: enable spl-fifo-mode for sdmmc")
mentions that the RK3399 SoC can't do DMA between SDMMC and SRAM.
According to the TRM "7.3.2 Embedded SRAM access path" [1], only the
8KB SRAM at 0xff3b (INTMEM1) is in this situation. The 192KB SRAM
can be accessed by both DMA controllers.

Assuming the only use case for writing from MMC to INTMEM1 is loading
a FIT image, and with the introduction of a temporary buffer for that
purpose (CONFIG_SPL_LOAD_FIT_IMAGE_BUFFER_SIZE, which is required
anyways to ensure the destination boundaries are enforced), then
spl-fifo-mode is not needed anymore and DMA can be enabled safely.

Link: [1] https://www.rockchip.fr/Rockchip%20RK3399%20TRM%20V1.4%20Part1.pdf
CC: Deepak Das 
Signed-off-by: Jerome Forissier 
---
 arch/arm/dts/rk3399-u-boot.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/dts/rk3399-u-boot.dtsi b/arch/arm/dts/rk3399-u-boot.dtsi
index 716b9a433a..a1b6d6f007 100644
--- a/arch/arm/dts/rk3399-u-boot.dtsi
+++ b/arch/arm/dts/rk3399-u-boot.dtsi
@@ -124,8 +124,10 @@
  {
u-boot,dm-pre-reloc;
 
+#ifndef CONFIG_SPL_LOAD_FIT_IMAGE_BUFFER_SIZE
/* mmc to sram can't do dma, prevent aborts transferring TF-A parts */
u-boot,spl-fifo-mode;
+#endif
 };
 
  {
-- 
2.34.1



[PATCH 0/2] spl, rk3399: fix FIT image loadingg out-of-range

2022-06-09 Thread Jerome Forissier
The patches in this series address an issue I met when trying to enable
FIT signature verification by SPL on a RockPi4B board.

- The first patch avoids a buffer overflow when writing to INTMEM1 SRAM
- The second one addresses reliability issues I had with back-to-back
MMC reads from the microSD card. By allowing DMA operation, the issue is
gone and generally speaking DMA is preferred over FIFO mode anyways.

Jerome Forissier (2):
  spl: fit: add config option for temporary buffer when loading image
  rockchip: rk3399: enable spl-fifo-mode for sdmmc only when needed

 arch/arm/dts/rk3399-u-boot.dtsi |  2 +
 common/spl/Kconfig  | 45 +++
 common/spl/spl_fit.c| 79 ++---
 3 files changed, 120 insertions(+), 6 deletions(-)

-- 
2.34.1



Re: [SPAM] RockPi4B: spl_load_fit_image() writing past end of buffer & MMC errors

2022-06-03 Thread Jerome Forissier
Hi Xavier,

On 6/3/22 16:58, Xavier Drudis Ferran wrote:
> El Fri, Jun 03, 2022 at 03:17:05PM +0200, Jerome Forissier deia:
>> First, I noticed that spl_load_fit_image() may write memory outside the range
>> given in the image node. For example on RockPi 4B I have the following FIT
>> (irrelevant parts omitted):
>>
>> / {
>>  images {
>>  atf_2 {
>>  /* File size is 8024 bytes */
>>  data = /incbin/("bl31_0xff3b.bin");
>>  compression = "none";
>>  load = <0xff3b>
>>  }
>>  }
>> }
>>
>> I expect SPL to load atf_2 into 0xff3b - 0xff3b200b but due to the 
>> alignment
>> of the source data in the MMC, spl_load_fit_image() writes one more block and
>> later moves the data in place with memcpy(). What are the guarantees that it
>> is a safe thing to do?
>>
> 
> In my case bl31_0xff3b.bin is 8020 bytes in size. 
>  
>> In my case, the image starts at offset 308 in the 512-byte MMC block (that
>> offset is called 'overhead' in spl_load_fit_image()). As a result,
>> (8204 + 308) / 512 + 1 = 17 blocks = 8704 bytes are read.
> 
> My overhead is 352, it's reading 17 blocks too.
> 
>>
>> For some reason I can't explain, on my board only the first 8K of the 64K 
>> SRAM
>> range 0xff3b - 0xff3c (INTMEM1) can be safely written to. Any data
>> written after this point corrupt the lower 8K. I found nothing in the rk3399
>> TRM about this [1].
>>
> 
> In my Rock Pi 4B this does not happen. It happily writes the 17 blocks. 
> Or it's just that I'm not noticing the problem ? Does it hang or give you 
> an error, or do you just find it out by reading the SRAM?

I found out when trying to use signed FIT images. The board would boot fine
otherwise.

I am setting CONFIG_SPL_FIT_SIGNATURE=y and I have modified the script
arch/arm/mach-rockchip/make_fit_atf.py so that it generates the required
hash and signature nodes in u-boot.its. Then I am basically following the
instructions in doc/uImage.FIT/signature.txt -- generating a RSA key pair
with OpenSSL and using 'mkimage -k keys -K -r $(other-args...)'.

Please refer to the patches at:

https://git.codelinaro.org/linaro/dependable-boot/meta-ts/-/merge_requests/7/diffs

It is work in progress really but it should give you an idea of what I am doing,
and possibly help reproduce the issue.

I also confirmed the issue with a small test case. Could you please try the
following patch?

---8<---
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index f6ccd837aa..810d5fa6db 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -401,6 +401,12 @@ static int mmc_read_blocks(struct mmc *mmc, void *dst, 
lbaint_t start,
struct mmc_cmd cmd;
struct mmc_data data;
 
+   printf("== 0x%08x\n", *(u32 *)0xff3b0100);
+   *(u32 *)0xff3b0100 = 0;
+   printf("== 0x%08x\n", *(u32 *)0xff3b0100);
+   *(u32 *)0xff3b2100 = 0xdeadbeef;
+   printf("== 0x%08x\n", *(u32 *)0xff3b0100);
+
if (blkcnt > 1)
cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
else
---8<---

Guess what, this **does** print "0xdeadbeef" on the console on my board! :O

> 
> I'm using the patch I sent yesterday: 
> 
> [PATCH 0/3] arm: rockchip: rk3399: rock-pi-4: power domain driver to boot 
> from MMCSD 
> https://lists.denx.de/pipermail/u-boot/2022-June/485498.html
> 
> (instead of the patch you can simply configure
> CONFIG_ROCKCHIP_SPL_RESERVE_IRAM from make nconfig or so) 
> 
> Which reserves 0x0 - 0x14fff bytes in DDRAM for bl31. I found that
> otherwise, SPL memory in that area gets overwritten by
> bl31_0x.bin.  I don't remember exactly what was there, but in
> my tests, bl31_0x gets loaded before
> bl31_0xff3b.bin. Depending on what data or code is overwritten,
> SPL might be doing something funny.

I don't have bl31_0x.bin. The bl31*.bin files come from bl31.elf
which is split by arch/arm/mach-rockchip/make_fit_atf.py.
It could be that we are using different versions of TF-A or different build
parameters, but that seems unrelated I think.
 
>> Anyways, I tried using a temporary buffer allocated on the heap to handle
>> the first and last blocks at least (the load address is properly aligned
>> for info->read() so the middle blocks can be read in one go). It works but
>> not reliably. And that is the second problem. mmc_read_blocks() in 
>> mmc_bread()
>> sometimes returns an error. If I read 

RockPi4B: spl_load_fit_image() writing past end of buffer & MMC errors

2022-06-03 Thread Jerome Forissier
Hi,

I am trying to enable FIT image verification by SPL on Rockchip 4B (U-Boot
v2022.04) and I hit a couple of issues.

First, I noticed that spl_load_fit_image() may write memory outside the range
given in the image node. For example on RockPi 4B I have the following FIT
(irrelevant parts omitted):

/ {
images {
atf_2 {
/* File size is 8024 bytes */
data = /incbin/("bl31_0xff3b.bin");
compression = "none";
load = <0xff3b>
}
}
}

I expect SPL to load atf_2 into 0xff3b - 0xff3b200b but due to the alignment
of the source data in the MMC, spl_load_fit_image() writes one more block and
later moves the data in place with memcpy(). What are the guarantees that it
is a safe thing to do?

In my case, the image starts at offset 308 in the 512-byte MMC block (that
offset is called 'overhead' in spl_load_fit_image()). As a result,
(8204 + 308) / 512 + 1 = 17 blocks = 8704 bytes are read.

For some reason I can't explain, on my board only the first 8K of the 64K SRAM
range 0xff3b - 0xff3c (INTMEM1) can be safely written to. Any data
written after this point corrupt the lower 8K. I found nothing in the rk3399
TRM about this [1].

Anyways, I tried using a temporary buffer allocated on the heap to handle
the first and last blocks at least (the load address is properly aligned
for info->read() so the middle blocks can be read in one go). It works but
not reliably. And that is the second problem. mmc_read_blocks() in mmc_bread()
sometimes returns an error. If I read blocks one by one in a loop THE read
randomly fails after a few blocks only. The error is -110 (-ETIMEDOUT) from
dwmci_send_cmd().

Am I using the MMC read incorrectly?

[1] https://www.rockchip.fr/Rockchip%20RK3399%20TRM%20V1.4%20Part1.pdf


Thanks,
-- 
Jerome


Re: [PATCH] mach-rockchip: make_fit_atf.py: support OP-TEE tee.bin v1 format

2022-06-02 Thread Jerome Forissier



On 5/29/22 18:08, Alper Nebi Yasak wrote:
> On 28/05/2022 01:08, Jerome Forissier wrote:
>> On 5/27/22 21:24, Alper Nebi Yasak wrote:
>>> On 11/05/2022 18:35, Jerome Forissier wrote:
>>>> +if paged_sz != 0:
>>>> +raise ValueError("OP-TEE paged mode not supported")
>>>
>>> Is this not feasible/necessary to do, or just not implemented yet?
>>
>> Just not implemented yet. Pager support is not strictly needed, its use or 
>> not
>> depends on the platform and on the threat model. In other words, whether or 
>> not
>> it is OK to have the TEE and TAs run in DRAM, usually isolated only from 
>> Normal
>> World software by TrustZone or some kind of memory firewall. Pager allows to
>> protect from physical access to the DRAM too. It provides authentication 
>> and/or
>> encryption to anything stored outside the internal SRAM of the SoC.
>> Testing this mode on RockPi4 would require some non trivial work. Here I 
>> simply
>> focused on implementing the current use case properly.
> 
> I assume you mean it would need platform-specific work on the OP-TEE OS
> side. 

Yes.
 > But let me ask in a general sense, would we need to pass
> 'paged_size', 'init_mem_usage', etc. via the FIT to U-Boot? Or, how well
> does the info in the files and headers (v1 and v2) map to FIT images and
> their properties?

Yes, the parameters in the tee.bin header would tell U-Boot if the binary needs 
to
be split in two parts (paged_size != 0) or not. The load address of the "non 
paged"
part is also in the header. And, when a "paged" part is present its load address
has to be passed to OP-TEE via register x1.

> Why I am asking these is that I'm hypothesizing we can put the
> unmodified 'tee.bin' (including header) and 'bl31.elf' (normally split
> into raw binary pieces) into the FIT, and then interpret them at runtime
> on the C side. Trying to figure out if it's a good idea.

Definitely sounds doable. It could help having more common code perhaps, and 
also
simplify the content of the FIT and therefore the verification of hash and
signatures.
 
>>>> +e_entry = (start_hi << 32) + start_lo
>>>> +p_addr = e_entry
>>>> +p_data = bin[0x1c:]
>>>> +if len(p_data) != init_sz:
>>>> +raise ValueError("Invalid file '%s': size mismatch "
>>>> + "(expected %d, have %d)" % (filename, 
>>>> init_sz,
>>>> + len(p_data)))
>>>> +segments.append((0, e_entry, p_addr, p_data))
>>>> +else:
>>>> +raise ValueError("Unknown format for TEE file '%s'" % filename)
>>>
>>> I see an 'output_header_v2' in your link [2], what about that?
>>
>> v2 is useful only when the OP-TEE pager is used, in which case it is a matter
>> of preference whether to use a single binary and have the loader split it as
>> expected (tee.bin) or use separate binaries instead.
>>
>> Historically (Jens please correct me if I'm wrong!), there was a single raw
>> binary for OP-TEE: tee.bin, and no pager support. Then pager was added. The
>> build would then create two separate files: tee-pager.bin and 
>> tee-pageable.bin
>> (the latter would be zero sized with pager disabled). At the same time a 
>> header
>> was introduced in tee.bin to indicate whether or not the file would contain a
>> pageable section (tee.bin consisted in the header + tee-pager.bin +
>> tee-pageable.bin). Later, and for reasons I don't remember exactly (related 
>> to
>> the integration with TF-A IIRC), the header was written to its own file and 
>> the
>> format of that header changed a bit. So we had tee-header_v2.bin,
>> tee-pager_v2.bin, and tee-pageable_v2.bin. The previous tee-pager.bin and
>> tee-pageable.bin were subsequently deprecated; but tee.bin wasn't. It is 
>> still
>> generated today, unchanged with its "v1" header. Note, I'm not sure if
>> tee-pager_v2.bin is different from tee-pager.bin (and same goes for the
>> pageable part), but it doesn't really matter for this discussion.
> 
> Thanks for both explanations. I also kept looking at gen_tee_bin.py and
>  outputs from a few OP-TEE OS builds. If I got things right, I can do:
> 
>   cat tee-header_v2.bin tee-pager_v2.bin tee-pageable_v2.bin >tee_v2.bin
> 
> and that would effectively be the same kind of file/image as tee.bin,
> just with a v2 header instead of v1, right?

Correct.

-- 
Jerome


Re: [PATCH] mach-rockchip: make_fit_atf.py: support OP-TEE tee.bin v1 format

2022-05-27 Thread Jerome Forissier



On 5/27/22 21:24, Alper Nebi Yasak wrote:
> On 11/05/2022 18:35, Jerome Forissier wrote:
>> This commit adds support for the OP-TEE 'tee.bin' v1 format for Rockchip
>> platforms.
>>
>> Since OP-TEE 3.8.0, tee.bin contains meta-data in a proprietary format
>> in addition to the ELF data. They are essential information for proper
>> initialization of the TEE core, such as the size of the memory region
>> covered by the TEE or a compact representation of runtime relocation
>> data when ASLR is enabled.
>>
>> With OP-TEE 3.8.0 onwards, 'tee.elf' MUST NOT be used and 'tee.bin'
>> MUST be used instead. Ignoring this recommendation can lead to crashes
>> as described in [3].
>>
>> Link: [1] 
>> https://github.com/OP-TEE/optee_os/commit/5dd1570ac5b0f6563b1a9c074533a19107b8222d
>> Link: [2] 
>> https://github.com/OP-TEE/optee_os/blob/3.17.0/scripts/gen_tee_bin.py#L275-L302
>> Link: [3] https://github.com/OP-TEE/optee_os/issues/4542
>> Signed-off-by: Jerome Forissier 
>> ---
>>  arch/arm/mach-rockchip/make_fit_atf.py | 43 +-
>>  1 file changed, 35 insertions(+), 8 deletions(-)
> 
> This might make it slightly harder to convert this file to binman, since
> it's not as good at deconstructing things.

Yes it is a bit unfortunate, but nothing we can't fix I'm sure. Well, I
say this knowing absolutely nothing about binman... ;-)

> I can't say I understand
> OP-TEE OS or its files/formats, so:
> 
> Acked-by: Alper Nebi Yasak 

Thanks, answers to your questions below.

 
>> diff --git a/arch/arm/mach-rockchip/make_fit_atf.py 
>> b/arch/arm/mach-rockchip/make_fit_atf.py
>> index f3224d2555..fcea652388 100755
>> --- a/arch/arm/mach-rockchip/make_fit_atf.py
>> +++ b/arch/arm/mach-rockchip/make_fit_atf.py
>> @@ -137,7 +137,7 @@ def generate_atf_fit_dts_bl31(fit_file, bl31_file_name, 
>> tee_file_name, dtbs_file
>>  num_segments = len(segments)
>>  
>>  if tee_file_name:
>> -tee_segments = unpack_elf(tee_file_name)
>> +tee_segments = unpack_tee_file(tee_file_name)
>>  for index, entry, paddr, data in tee_segments:
>>  append_tee_node(fit_file, num_segments + index + 1, paddr, 
>> entry)
>>  num_segments = num_segments + len(tee_segments)
>> @@ -169,7 +169,7 @@ def generate_atf_binary(bl31_file_name):
>>  
>>  def generate_tee_binary(tee_file_name):
>>  if tee_file_name:
>> -for index, entry, paddr, data in unpack_elf(tee_file_name):
>> +for index, entry, paddr, data in unpack_tee_file(tee_file_name):
>>  file_name = 'tee_0x%08x.bin' % paddr
>>  with open(file_name, "wb") as atf:
>>  atf.write(data)
>> @@ -194,6 +194,31 @@ def unpack_elf(filename):
>>  segments.append((index, e_entry, p_paddr, p_data))
>>  return segments
>>  
>> +def unpack_tee_file(filename):
>> +if filename.endswith('.elf'):
>> +return unpack_elf(filename)
>> +with open(filename, 'rb') as file:
>> +bin = file.read()
>> +segments = []
>> +if bin[0:5] == b'OPTE\x01':
>> +# OP-TEE v1 format (tee.bin)
>> +init_sz, start_hi, start_lo, _, paged_sz = struct.unpack_from('<5I',
>> +  bin,
>> +  0x8)
>> +if paged_sz != 0:
>> +raise ValueError("OP-TEE paged mode not supported")
> 
> Is this not feasible/necessary to do, or just not implemented yet?

Just not implemented yet. Pager support is not strictly needed, its use or not
depends on the platform and on the threat model. In other words, whether or not
it is OK to have the TEE and TAs run in DRAM, usually isolated only from Normal
World software by TrustZone or some kind of memory firewall. Pager allows to
protect from physical access to the DRAM too. It provides authentication and/or
encryption to anything stored outside the internal SRAM of the SoC.
Testing this mode on RockPi4 would require some non trivial work. Here I simply
focused on implementing the current use case properly.
 
>> +e_entry = (start_hi << 32) + start_lo
>> +p_addr = e_entry
>> +p_data = bin[0x1c:]
>> +if len(p_data) != init_sz:
>> +raise ValueError("Invalid file '%s': size mismatch "
>> + "(expected %d, have %d)" % (filename, init_sz,
>> + len(p_data)))
>> +

Re: [RFC PATCH v2 0/8] Build Rockchip final images using binman

2022-05-16 Thread Jerome Forissier
Hi Andrew,

On 5/16/22 13:07, Andrew Abbott wrote:
> My original goal was to produce SPI images for Rockchip platforms 
> (specifically
> for me, ROCKPro64, and in the future ROCK64). Looking into it, it seemed nicer
> to just switch the SD/MMC image generation over to binman as well in the
> process.
> 
> This is my attempt to move Rockchip final full image generation to binman,
> adding the option to make full SPI images as well.
> 
> Other questions:
> 
> - I noticed that ATF generation for ARM64 Rockchip is done via a Python script
>   instead of binman. I don't currently know how to change that over to binman,
>   but is that something worth pursuing as part of this?

I use this kind of configuration on ROCKPi 4B (U-Boot with TF-A BL31 and 
OP-TEE),
so I could at least run some tests. Please note that I recently sent a patch to
fix the OP-TEE support in make_fit_atf.py [1]. That would be needed in binman
too for me to able to test.

[1] https://lists.denx.de/pipermail/u-boot/2022-May/483917.html

> 
> Please give me your feedback!
> 
> Changes in v2:
> - Revert u-boot-rockchip-sdmmc.bin name to u-boot-rockchip.bin, to
>   keep the name the same as before.
> - Fix whitespace issues.
> - Remove note from docs about different offsets in SPI flash for
>   different SoCs - this was a bad assumption on my part, it doesn't work
>   this way.
> - Update name of SD/MMC image in the docs from u-boot-rockchip-sdmmc.bin
>   to u-boot-rockchip.bin.
> 
> Andrew Abbott (8):
>   binman: mkimage: Support ':'-separated inputs
>   rockchip: Add binman definitions for final images
>   soc: rockchip: Include common U-Boot dtsi file
>   board: rockchip: Move SPI U-Boot offset to config
>   rockchip: Remove obsolete Makefile targets
>   rockchip: Enable binman for ARM64
>   doc: rockchip: Update for new binman image generation
>   board: rockpro64: Enable building SPI image
> 
>  Kconfig  |  4 +-
>  Makefile | 31 ++--
>  arch/arm/Kconfig |  2 +-
>  arch/arm/dts/rk3308-u-boot.dtsi  |  2 +
>  arch/arm/dts/rk3328-u-boot.dtsi  |  2 +
>  arch/arm/dts/rk3368-lion-haikou-u-boot.dtsi  |  1 -
>  arch/arm/dts/rk3368-u-boot.dtsi  |  1 +
>  arch/arm/dts/rk3399-pinebook-pro-u-boot.dtsi |  4 --
>  arch/arm/dts/rk3399-puma-haikou-u-boot.dtsi  |  1 -
>  arch/arm/dts/rk3399-roc-pc-u-boot.dtsi   |  4 --
>  arch/arm/dts/rk3399-rockpro64-u-boot.dtsi|  4 --
>  arch/arm/dts/rk3568-u-boot.dtsi  |  2 +
>  arch/arm/dts/rockchip-u-boot.dtsi| 53 ++--
>  arch/arm/mach-rockchip/Kconfig   |  7 ++-
>  arch/arm/mach-rockchip/rk3399/Kconfig|  1 +
>  configs/lion-rk3368_defconfig|  1 +
>  configs/pinebook-pro-rk3399_defconfig|  1 +
>  configs/puma-rk3399_defconfig|  2 +-
>  configs/roc-pc-rk3399_defconfig  |  1 +
>  configs/rockpro64-rk3399_defconfig   |  1 +
>  doc/board/rockchip/rockchip.rst  | 29 +++
>  tools/binman/etype/mkimage.py| 33 +++-
>  22 files changed, 100 insertions(+), 87 deletions(-)
> 


Re: [PATCH] RockPi4: Add UEFI capsule update support

2022-05-13 Thread Jerome Forissier
; +++ b/configs/rock-pi-4c-rk3399_defconfig
> @@ -21,6 +21,7 @@ CONFIG_SPL_STACK_R=y
>  CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x1
>  CONFIG_TPL=y
>  CONFIG_CMD_BOOTZ=y
> +CONFIG_CMD_DFU=y
>  CONFIG_CMD_GPT=y
>  CONFIG_CMD_MMC=y
>  CONFIG_CMD_PCI=y
> @@ -31,6 +32,7 @@ CONFIG_SPL_OF_CONTROL=y
>  CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names 
> interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
>  CONFIG_ENV_IS_IN_MMC=y
>  CONFIG_SYS_RELOC_GD_ENV_ADDR=y
> +CONFIG_DFU_MMC=y
>  CONFIG_ROCKCHIP_GPIO=y
>  CONFIG_SYS_I2C_ROCKCHIP=y
>  CONFIG_MISC=y
> @@ -76,3 +78,5 @@ CONFIG_VIDEO_ROCKCHIP=y
>  CONFIG_DISPLAY_ROCKCHIP_HDMI=y
>  CONFIG_SPL_TINY_MEMSET=y
>  CONFIG_ERRNO_STR=y
> +CONFIG_EFI_CAPSULE_ON_DISK=y
> +CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
> diff --git a/include/configs/rk3399_common.h b/include/configs/rk3399_common.h
> index 8e13737666..28b514a4ea 100644
> --- a/include/configs/rk3399_common.h
> +++ b/include/configs/rk3399_common.h
> @@ -38,6 +38,22 @@
>  #define CONFIG_SYS_SDRAM_BASE0
>  #define SDRAM_MAX_SIZE   0xf800
>  
> +#define ROCKPI_4B_IDBLOADER_IMAGE_GUID \
> + EFI_GUID(0x02f4d760, 0xcfd5, 0x43bd, 0x8e, 0x2d, \
> +  0xa4, 0x2a, 0xcb, 0x33, 0xc6, 0x60)
> +
> +#define ROCKPI_4B_UBOOT_IMAGE_GUID \
> + EFI_GUID(0x4ce292da, 0x1dd8, 0x428d, 0xa1, 0xc2, \
> +  0x77, 0x74, 0x3e, 0xf8, 0xb9, 0x6e)
> +
> +#define ROCKPI_4C_IDBLOADER_IMAGE_GUID \
> + EFI_GUID(0xfd68510c, 0x12d3, 0x4f0a, 0xb8, 0xd3, \
> +  0xd8, 0x79, 0xe1, 0xd3, 0xa5, 0x40)
> +
> +#define ROCKPI_4C_UBOOT_IMAGE_GUID \
> + EFI_GUID(0xb81fb4ae, 0xe4f3, 0x471b, 0x99, 0xb4, \
> +  0x0b, 0x3d, 0xa5, 0x49, 0xce, 0x13)
> +
>  #ifndef CONFIG_SPL_BUILD
>  
>  #define ENV_MEM_LAYOUT_SETTINGS \

Tested-by: Jerome Forissier  (RockPi4B)

Thanks,
-- 
Jerome


[PATCH] mach-rockchip: make_fit_atf.py: support OP-TEE tee.bin v1 format

2022-05-11 Thread Jerome Forissier
This commit adds support for the OP-TEE 'tee.bin' v1 format for Rockchip
platforms.

Since OP-TEE 3.8.0, tee.bin contains meta-data in a proprietary format
in addition to the ELF data. They are essential information for proper
initialization of the TEE core, such as the size of the memory region
covered by the TEE or a compact representation of runtime relocation
data when ASLR is enabled.

With OP-TEE 3.8.0 onwards, 'tee.elf' MUST NOT be used and 'tee.bin'
MUST be used instead. Ignoring this recommendation can lead to crashes
as described in [3].

Link: [1] 
https://github.com/OP-TEE/optee_os/commit/5dd1570ac5b0f6563b1a9c074533a19107b8222d
Link: [2] 
https://github.com/OP-TEE/optee_os/blob/3.17.0/scripts/gen_tee_bin.py#L275-L302
Link: [3] https://github.com/OP-TEE/optee_os/issues/4542
Signed-off-by: Jerome Forissier 
---
 arch/arm/mach-rockchip/make_fit_atf.py | 43 +-
 1 file changed, 35 insertions(+), 8 deletions(-)

diff --git a/arch/arm/mach-rockchip/make_fit_atf.py 
b/arch/arm/mach-rockchip/make_fit_atf.py
index f3224d2555..fcea652388 100755
--- a/arch/arm/mach-rockchip/make_fit_atf.py
+++ b/arch/arm/mach-rockchip/make_fit_atf.py
@@ -137,7 +137,7 @@ def generate_atf_fit_dts_bl31(fit_file, bl31_file_name, 
tee_file_name, dtbs_file
 num_segments = len(segments)
 
 if tee_file_name:
-tee_segments = unpack_elf(tee_file_name)
+tee_segments = unpack_tee_file(tee_file_name)
 for index, entry, paddr, data in tee_segments:
 append_tee_node(fit_file, num_segments + index + 1, paddr, entry)
 num_segments = num_segments + len(tee_segments)
@@ -169,7 +169,7 @@ def generate_atf_binary(bl31_file_name):
 
 def generate_tee_binary(tee_file_name):
 if tee_file_name:
-for index, entry, paddr, data in unpack_elf(tee_file_name):
+for index, entry, paddr, data in unpack_tee_file(tee_file_name):
 file_name = 'tee_0x%08x.bin' % paddr
 with open(file_name, "wb") as atf:
 atf.write(data)
@@ -194,6 +194,31 @@ def unpack_elf(filename):
 segments.append((index, e_entry, p_paddr, p_data))
 return segments
 
+def unpack_tee_file(filename):
+if filename.endswith('.elf'):
+return unpack_elf(filename)
+with open(filename, 'rb') as file:
+bin = file.read()
+segments = []
+if bin[0:5] == b'OPTE\x01':
+# OP-TEE v1 format (tee.bin)
+init_sz, start_hi, start_lo, _, paged_sz = struct.unpack_from('<5I',
+  bin,
+  0x8)
+if paged_sz != 0:
+raise ValueError("OP-TEE paged mode not supported")
+e_entry = (start_hi << 32) + start_lo
+p_addr = e_entry
+p_data = bin[0x1c:]
+if len(p_data) != init_sz:
+raise ValueError("Invalid file '%s': size mismatch "
+ "(expected %d, have %d)" % (filename, init_sz,
+ len(p_data)))
+segments.append((0, e_entry, p_addr, p_data))
+else:
+raise ValueError("Unknown format for TEE file '%s'" % filename)
+return segments
+
 def main():
 uboot_elf = "./u-boot"
 fit_its = sys.stdout
@@ -210,11 +235,13 @@ def main():
 logging.warning(' Please read Building section in doc/README.rockchip')
 
 if "TEE" in os.environ:
-tee_elf = os.getenv("TEE")
+tee_file = os.getenv("TEE")
+elif os.path.isfile("./tee.bin"):
+tee_file = "./tee.bin"
 elif os.path.isfile("./tee.elf"):
-tee_elf = "./tee.elf"
+tee_file = "./tee.elf"
 else:
-tee_elf = ""
+tee_file = ""
 
 opts, args = getopt.getopt(sys.argv[1:], "o:u:b:t:h")
 for opt, val in opts:
@@ -225,16 +252,16 @@ def main():
 elif opt == "-b":
 bl31_elf = val
 elif opt == "-t":
-tee_elf = val
+tee_file = val
 elif opt == "-h":
 print(__doc__)
 sys.exit(2)
 
 dtbs = args
 
-generate_atf_fit_dts(fit_its, bl31_elf, tee_elf, uboot_elf, dtbs)
+generate_atf_fit_dts(fit_its, bl31_elf, tee_file, uboot_elf, dtbs)
 generate_atf_binary(bl31_elf)
-generate_tee_binary(tee_elf)
+generate_tee_binary(tee_file)
 
 if __name__ == "__main__":
 main()
-- 
2.17.1



  1   2   >