summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorJerome Forissier <[email protected]>2025-06-25 15:19:19 +0200
committerJerome Forissier <[email protected]>2025-07-08 11:07:37 +0200
commita2a0c7527eb86e69bc7a78d9250eb5a1068ae5b7 (patch)
tree8bad02b896f50468d1a4fe1010a95aef29d68ce9 /cmd
parent77f0bed326b658fcb57f278bd5228afbe382401a (diff)
lwip: add sntp command
Implement the sntp command when NET_LWIP=y. Signed-off-by: Jerome Forissier <[email protected]>
Diffstat (limited to 'cmd')
-rw-r--r--cmd/Kconfig13
-rw-r--r--cmd/lwip/Makefile1
-rw-r--r--cmd/lwip/sntp.c134
3 files changed, 142 insertions, 6 deletions
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 1ba3cfcb28a..ca7ed58c062 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2074,12 +2074,6 @@ config CMD_CDP
and to retrieve configuration data including the VLAN id using the
proprietary Cisco Discovery Protocol (CDP).
-config CMD_SNTP
- bool "sntp"
- select PROT_UDP
- help
- Synchronize RTC via network
-
config CMD_LINK_LOCAL
bool "linklocal"
depends on (LIB_RAND || LIB_HW_RAND)
@@ -2157,6 +2151,13 @@ config CMD_PING
help
Send ICMP ECHO_REQUEST to network host
+config CMD_SNTP
+ bool "sntp"
+ select PROT_UDP if NET
+ select PROT_UDP_LWIP if NET_LWIP
+ help
+ Synchronize RTC via network
+
config CMD_TFTPBOOT
bool "tftp"
select PROT_UDP_LWIP if NET_LWIP
diff --git a/cmd/lwip/Makefile b/cmd/lwip/Makefile
index 4c28d2b28e5..a7f8976af3f 100644
--- a/cmd/lwip/Makefile
+++ b/cmd/lwip/Makefile
@@ -1,5 +1,6 @@
obj-$(CONFIG_CMD_DHCP) += dhcp.o
obj-$(CONFIG_CMD_DNS) += dns.o
obj-$(CONFIG_CMD_PING) += ping.o
+obj-$(CONFIG_CMD_SNTP) += sntp.o
obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
obj-$(CONFIG_CMD_WGET) += wget.o
diff --git a/cmd/lwip/sntp.c b/cmd/lwip/sntp.c
new file mode 100644
index 00000000000..ae02bb11040
--- /dev/null
+++ b/cmd/lwip/sntp.c
@@ -0,0 +1,134 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2025 Linaro Ltd. */
+
+#include <command.h>
+#include <console.h>
+#include <dm/device.h>
+#include <env.h>
+#include <lwip/apps/sntp.h>
+#include <lwip/timeouts.h>
+#include <net.h>
+
+U_BOOT_CMD(sntp, 2, 1, do_sntp, "synchronize RTC via network",
+ "[NTPServerNameOrIp]");
+
+#define SNTP_TIMEOUT 10000
+
+static enum done_state {
+ NOT_DONE = 0,
+ SUCCESS,
+ ABORTED,
+ TIMED_OUT
+} sntp_state;
+
+static void no_response(void *arg)
+{
+ sntp_state = TIMED_OUT;
+}
+
+/* Called by lwIP via the SNTP_SET_SYSTEM_TIME() macro */
+void sntp_set_system_time(uint32_t seconds)
+{
+ char *toff;
+ int net_ntp_time_offset = 0;
+
+ toff = env_get("timeoffset");
+ if (toff)
+ net_ntp_time_offset = simple_strtol(toff, NULL, 10);
+
+ net_sntp_set_rtc(seconds + net_ntp_time_offset);
+ sntp_state = SUCCESS;
+}
+
+static bool ntp_server_known(void)
+{
+ int i;
+
+ for (i = 0; i < SNTP_MAX_SERVERS; i++) {
+ const ip_addr_t *ip = sntp_getserver(i);
+
+ if (ip && ip->addr)
+ return true;
+ }
+
+ return false;
+}
+
+static int sntp_loop(struct udevice *udev, ip_addr_t *srvip)
+{
+ struct netif *netif;
+
+ netif = net_lwip_new_netif(udev);
+ if (!netif)
+ return -1;
+
+ sntp_state = NOT_DONE;
+
+ sntp_setoperatingmode(SNTP_OPMODE_POLL);
+ sntp_servermode_dhcp(CONFIG_IS_ENABLED(CMD_DHCP));
+ if (srvip) {
+ sntp_setserver(0, srvip);
+ } else {
+ if (!ntp_server_known()) {
+ log_err("error: ntpserverip not set\n");
+ return -1;
+ }
+ }
+ sntp_init();
+
+ sys_timeout(SNTP_TIMEOUT, no_response, NULL);
+ while (sntp_state == NOT_DONE) {
+ net_lwip_rx(udev, netif);
+ sys_check_timeouts();
+ if (ctrlc()) {
+ printf("\nAbort\n");
+ sntp_state = ABORTED;
+ break;
+ }
+ }
+ sys_untimeout(no_response, NULL);
+
+ sntp_stop();
+ net_lwip_remove_netif(netif);
+
+ if (sntp_state == SUCCESS)
+ return 0;
+
+ return -1;
+}
+
+int do_sntp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ ip_addr_t *srvip;
+ char *server;
+ ip_addr_t ipaddr;
+
+ switch (argc) {
+ case 1:
+ srvip = NULL;
+ server = env_get("ntpserverip");
+ if (server) {
+ if (!ipaddr_aton(server, &ipaddr)) {
+ printf("ntpserverip is invalid\n");
+ return CMD_RET_FAILURE;
+ }
+ srvip = &ipaddr;
+ }
+ break;
+ case 2:
+ if (net_lwip_dns_resolve(argv[1], &ipaddr))
+ return CMD_RET_FAILURE;
+ srvip = &ipaddr;
+ break;
+ default:
+ return CMD_RET_USAGE;
+ }
+
+ if (net_lwip_eth_start() < 0)
+ return CMD_RET_FAILURE;
+
+ if (sntp_loop(eth_get_dev(), srvip) < 0)
+ return CMD_RET_FAILURE;
+
+ return CMD_RET_SUCCESS;
+}