From 73cf35227ea7ccd85c3eec1dfd8183809b4251cd Mon Sep 17 00:00:00 2001 From: zhouzhiwen2000 Date: Fri, 24 Jul 2026 10:42:26 +0800 Subject: [PATCH] net: fix TFTP behind Qualcomm PPE ACL The Qualcomm NSS driver drops unmatched UDP traffic and only installs its TFTP exception behind the undefined CONFIG_TFTP_PORT symbol. With the lwIP network stack, the client also ignores tftpsrcp and selects an ephemeral port, so TFTP replies never reach EDMA. Install the ACL whenever tftpboot is enabled and teach the lwIP client to bind the tftpsrcp port selected by the NSS driver. Validated with the sbe1v1k_chainloader_defconfig build and chainloader FIT packaging. --- drivers/net/qcom/nss-switch.c | 4 ++-- lib/lwip/lwip/src/apps/tftp/tftp.c | 13 +++++++++++++ lib/lwip/lwip/src/include/lwip/apps/tftp_client.h | 1 + net/lwip/tftp.c | 14 ++++++++++++++ 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/net/qcom/nss-switch.c b/drivers/net/qcom/nss-switch.c index eb3f2e523c7..8a40ea76315 100644 --- a/drivers/net/qcom/nss-switch.c +++ b/drivers/net/qcom/nss-switch.c @@ -2118,7 +2118,7 @@ void ipq_ppe_provision_init(struct ppe_info *info) /* Dropping all the UDP packets */ ipq_ppe_acl_set(&acl_set); - if (IS_ENABLED(CONFIG_TFTP_PORT)) { + if (IS_ENABLED(CONFIG_CMD_TFTPBOOT)) { tftp_acl_our_port = 1024 + (get_timer(0) % 3072); UPDATE_ACL_SET(acl_set, reg_base, 3, 0x4, 0x1, @@ -5946,7 +5946,7 @@ static int ipq_eth_start(struct udevice *dev) if (priv->ppe.bridge_mode) priv->ppe.nbport = 0; - if (IS_ENABLED(CONFIG_TFTP_PORT)) + if (IS_ENABLED(CONFIG_CMD_TFTPBOOT)) env_set_ulong("tftpsrcp", tftp_acl_our_port); /* HTTP recovery sets eth_allow_no_link and does not need link chatter. */ diff --git a/lib/lwip/lwip/src/apps/tftp/tftp.c b/lib/lwip/lwip/src/apps/tftp/tftp.c index e73bea20e63..911b37742ef 100644 --- a/lib/lwip/lwip/src/apps/tftp/tftp.c +++ b/lib/lwip/lwip/src/apps/tftp/tftp.c @@ -678,6 +678,19 @@ tftp_init_client(const struct tftp_context *ctx) return tftp_init_common(LWIP_TFTP_MODE_CLIENT, ctx); } +/** @ingroup tftp + * Bind the TFTP client to a specific local UDP port. + * @param port Local UDP port in host byte order + */ +err_t +tftp_client_bind(u16_t port) +{ + LWIP_ERROR("TFTP client is not enabled (tftp_init)", (tftp_state.tftp_mode & LWIP_TFTP_MODE_CLIENT) != 0, return ERR_VAL); + LWIP_ERROR("TFTP client PCB is not initialized", tftp_state.upcb, return ERR_VAL); + + return udp_bind(tftp_state.upcb, IP_ANY_TYPE, port); +} + /** @ingroup tftp * Get the transfer size used by the TFTP client. The server may * report zero in case this is unsupported. diff --git a/lib/lwip/lwip/src/include/lwip/apps/tftp_client.h b/lib/lwip/lwip/src/include/lwip/apps/tftp_client.h index 78de50f4924..5e089993369 100644 --- a/lib/lwip/lwip/src/include/lwip/apps/tftp_client.h +++ b/lib/lwip/lwip/src/include/lwip/apps/tftp_client.h @@ -44,6 +44,7 @@ enum tftp_transfer_mode { }; err_t tftp_init_client(const struct tftp_context* ctx); +err_t tftp_client_bind(u16_t port); void tftp_client_set_blksize(u16_t blksize); u32_t tftp_client_get_tsize(void); err_t tftp_get(void* handle, const ip_addr_t *addr, u16_t port, const char* fname, enum tftp_transfer_mode mode); diff --git a/net/lwip/tftp.c b/net/lwip/tftp.c index 7f3b28b8507..0949f55979a 100644 --- a/net/lwip/tftp.c +++ b/net/lwip/tftp.c @@ -184,6 +184,7 @@ static int tftp_loop(struct udevice *udev, ulong addr, char *fname, ip_addr_t srvip, uint16_t srvport) { int blksize = CONFIG_TFTP_BLOCKSIZE; + u16_t local_port; struct netif *netif; struct tftp_ctx ctx; const char *ep; @@ -216,6 +217,19 @@ static int tftp_loop(struct udevice *udev, ulong addr, char *fname, if (!(err == ERR_OK || err == ERR_USE)) log_err("tftp_init_client err: %d\n", err); + ep = env_get("tftpsrcp"); + if (ep) { + local_port = dectoul(ep, NULL); + err = tftp_client_bind(local_port); + if (err != ERR_OK) { + log_err("tftp_client_bind(%u) err: %d\n", local_port, + err); + tftp_cleanup(); + net_lwip_remove_netif(netif); + return -1; + } + } + ep = env_get("tftpblocksize"); if (ep) blksize = simple_strtol(ep, NULL, 10);