1 // SPDX-License-Identifier: GPL-2.0+
2 /* Copyright (C) 2024 Linaro Ltd. */
8 #include <linux/delay.h>
9 #include <linux/errno.h>
10 #include <lwip/dhcp.h>
12 #include <lwip/timeouts.h>
16 #define DHCP_TIMEOUT_MS 10000
18 #ifdef CONFIG_CMD_TFTPBOOT
19 /* Boot file obtained from DHCP (if present) */
20 static char boot_file_name
[DHCP_BOOT_FILE_LEN
];
23 static void call_lwip_dhcp_fine_tmr(void *ctx
)
26 sys_timeout(10, call_lwip_dhcp_fine_tmr
, NULL
);
29 static int dhcp_loop(struct udevice
*udev
)
31 char ipstr
[] = "ipaddr\0\0";
32 char maskstr
[] = "netmask\0\0";
33 char gwstr
[] = "gatewayip\0\0";
41 if (idx
< 0 || idx
> 99) {
42 log_err("unexpected idx %d\n", idx
);
43 return CMD_RET_FAILURE
;
46 netif
= net_lwip_new_netif_noip(udev
);
48 return CMD_RET_FAILURE
;
52 if (dhcp_start(netif
))
53 return CMD_RET_FAILURE
;
55 call_lwip_dhcp_fine_tmr(NULL
);
57 /* Wait for DHCP to complete */
59 net_lwip_rx(udev
, netif
);
61 bound
= dhcp_supplied_address(netif
);
69 } while (get_timer(start
) < DHCP_TIMEOUT_MS
);
71 sys_untimeout(call_lwip_dhcp_fine_tmr
, NULL
);
74 net_lwip_remove_netif(netif
);
75 return CMD_RET_FAILURE
;
78 dhcp
= netif_dhcp_data(netif
);
80 env_set("bootfile", dhcp
->boot_file_name
);
83 sprintf(ipstr
, "ipaddr%d", idx
);
84 sprintf(maskstr
, "netmask%d", idx
);
85 sprintf(gwstr
, "gatewayip%d", idx
);
87 net_ip
.s_addr
= dhcp
->offered_ip_addr
.addr
;
90 env_set(ipstr
, ip4addr_ntoa(&dhcp
->offered_ip_addr
));
91 env_set(maskstr
, ip4addr_ntoa(&dhcp
->offered_sn_mask
));
92 env_set("serverip", ip4addr_ntoa(&dhcp
->server_ip_addr
));
93 if (dhcp
->offered_gw_addr
.addr
!= 0)
94 env_set(gwstr
, ip4addr_ntoa(&dhcp
->offered_gw_addr
));
96 #ifdef CONFIG_PROT_DNS_LWIP
97 env_set("dnsip", ip4addr_ntoa(dns_getserver(0)));
98 env_set("dnsip2", ip4addr_ntoa(dns_getserver(1)));
100 #ifdef CONFIG_CMD_TFTPBOOT
101 if (dhcp
->boot_file_name
[0] != '\0')
102 strncpy(boot_file_name
, dhcp
->boot_file_name
,
103 sizeof(boot_file_name
));
106 printf("DHCP client bound to address %pI4 (%lu ms)\n",
107 &dhcp
->offered_ip_addr
, get_timer(start
));
109 net_lwip_remove_netif(netif
);
110 return CMD_RET_SUCCESS
;
113 int do_dhcp(struct cmd_tbl
*cmdtp
, int flag
, int argc
, char *const argv
[])
122 log_err("No network device\n");
123 return CMD_RET_FAILURE
;
126 ret
= dhcp_loop(dev
);
131 struct cmd_tbl cmdtp
= {};
133 return do_tftpb(&cmdtp
, 0, argc
, argv
);
136 return CMD_RET_SUCCESS
;
139 int dhcp_run(ulong addr
, const char *fname
, bool autoload
)
141 char *dhcp_argv
[] = {"dhcp", NULL
, };
142 #ifdef CONFIG_CMD_TFTPBOOT
143 char *tftp_argv
[] = {"tftpboot", boot_file_name
, NULL
, };
145 struct cmd_tbl cmdtp
= {}; /* dummy */
148 #ifdef CONFIG_CMD_TFTPBOOT
149 /* Assume DHCP was already performed */
150 if (boot_file_name
[0])
151 return do_tftpb(&cmdtp
, 0, 2, tftp_argv
);
158 return do_dhcp(&cmdtp
, 0, 1, dhcp_argv
);