summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'cmd')
-rw-r--r--cmd/Kconfig65
-rw-r--r--cmd/Makefile5
-rw-r--r--cmd/abootimg.c2
-rw-r--r--cmd/booti.c10
-rw-r--r--cmd/bootz.c10
-rw-r--r--cmd/eficonfig.c146
-rw-r--r--cmd/help.c6
-rw-r--r--cmd/load.c9
-rw-r--r--cmd/lwip/Makefile6
-rw-r--r--cmd/lwip/dhcp.c9
-rw-r--r--cmd/lwip/dns.c116
-rw-r--r--cmd/lwip/ping.c182
-rw-r--r--cmd/lwip/sntp.c134
-rw-r--r--cmd/lwip/tftp.c9
-rw-r--r--cmd/lwip/wget.c222
-rw-r--r--cmd/net-lwip.c50
-rw-r--r--cmd/smbios.c2
-rw-r--r--cmd/tpm-v2.c6
18 files changed, 878 insertions, 111 deletions
diff --git a/cmd/Kconfig b/cmd/Kconfig
index ed741d43cea..1e86773a143 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -153,6 +153,7 @@ config CMD_CONFIG
bool "config"
default SANDBOX
select BUILD_BIN2C
+ select GZIP
help
Print ".config" contents.
@@ -189,6 +190,12 @@ config CMD_FWU_METADATA
help
Command to read the metadata and dump it's contents
+config CMD_HELP
+ bool "help"
+ default y
+ help
+ Command to show help information about other commands.
+
config CMD_HISTORY
bool "history"
depends on CMDLINE_EDITING
@@ -1864,12 +1871,6 @@ config CMD_DHCP6
if CMD_DHCP6
-config DHCP6_PXE_CLIENTARCH
- hex
- default 0x16 if ARM64
- default 0x15 if ARM
- default 0xFF
-
config DHCP6_PXE_DHCP_OPTION
bool "Request & store 'pxe_configfile' from DHCP6 server"
@@ -1977,12 +1978,22 @@ config BOOTP_PXE
help
Supported for ARM, ARM64, and x86 for now.
-config BOOTP_PXE_CLIENTARCH
- hex
- depends on BOOTP_PXE
- default 0x16 if ARM64
- default 0x15 if ARM
- default 0x0 if X86
+config DHCP_PXE_CLIENTARCH
+ hex "DCHCP client system architecture type"
+ depends on BOOTP_PXE || CMD_DHCP6
+ default 0x16 if ARM64 # arm 64 uboot
+ default 0x15 if ARM # arm 32 uboot
+ default 0x0 if X86 # x86 BIOS
+ default 0xFF # DHCP option not sent
+ help
+ DHCP option 93 (defined in RFC4578) or DHCPv6 option 61 (defined in
+ RFC 5970) is used to transmit the client system architecture type
+ to the DHCP server. The DHCP server may use this information to
+ choose the boot file. For a complete list of assigned values see
+ https://www.iana.org/assignments/dhcpv6-parameters#processor-architecture.
+
+ If the value is set to the reserved value 0xFF, the DHCP option will
+ not be sent by U-Boot.
config BOOTP_PXE_DHCP_OPTION
bool "Request & store 'pxe_configfile' from BOOTP/DHCP server"
@@ -2004,23 +2015,6 @@ config BOOTP_RANDOM_XID
Selecting this will allow for a random transaction ID to get
selected for each BOOTP/DHCPv4 exchange.
-if CMD_DHCP6
-
-config DHCP6_PXE_CLIENTARCH
- hex
- default 0x16 if ARM64
- default 0x15 if ARM
- default 0xFF
-
-config DHCP6_PXE_DHCP_OPTION
- bool "Request & store 'pxe_configfile' from DHCP6 server"
-
-config DHCP6_ENTERPRISE_ID
- int "Enterprise ID to send in DHCPv6 Vendor Class Option"
- default 0
-
-endif
-
config CMD_TFTPPUT
bool "tftp put"
depends on CMD_TFTPBOOT
@@ -2086,12 +2080,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)
@@ -2169,6 +2157,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/Makefile b/cmd/Makefile
index 80cf70b7fe8..40f6ac4a85e 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -7,7 +7,7 @@ ifndef CONFIG_XPL_BUILD
# core command
obj-y += boot.o
obj-$(CONFIG_CMD_BOOTM) += bootm.o
-obj-y += help.o
+obj-$(CONFIG_CMD_HELP) += help.o
obj-y += panic.o
obj-y += version.o
@@ -133,7 +133,8 @@ obj-$(CONFIG_CMD_NAND) += nand.o
ifdef CONFIG_NET
obj-$(CONFIG_CMD_NET) += net.o net-common.o
else ifdef CONFIG_NET_LWIP
-obj-$(CONFIG_CMD_NET) += net-lwip.o net-common.o
+obj-$(CONFIG_CMD_NET) += net-common.o
+obj-y += lwip/
endif
obj-$(CONFIG_ENV_SUPPORT) += nvedit.o
obj-$(CONFIG_CMD_NVEDIT_EFI) += nvedit_efi.o
diff --git a/cmd/abootimg.c b/cmd/abootimg.c
index 44de00fb9c9..6fb52153786 100644
--- a/cmd/abootimg.c
+++ b/cmd/abootimg.c
@@ -96,7 +96,7 @@ static int abootimg_get_dtb_load_addr(int argc, char *const argv[])
return CMD_RET_USAGE;
struct andr_image_data img_data = {0};
const struct andr_boot_img_hdr_v0 *hdr;
- const struct andr_vnd_boot_img_hdr *vhdr;
+ const struct andr_vnd_boot_img_hdr *vhdr = NULL;
hdr = map_sysmem(abootimg_addr(), sizeof(*hdr));
if (get_avendor_bootimg_addr() != -1)
diff --git a/cmd/booti.c b/cmd/booti.c
index 7e6d9426299..e6f67d6e136 100644
--- a/cmd/booti.c
+++ b/cmd/booti.c
@@ -30,6 +30,7 @@ static int booti_start(struct bootm_info *bmi)
uint8_t *temp;
ulong dest;
ulong dest_end;
+ phys_addr_t ep_addr;
unsigned long comp_len;
unsigned long decomp_len;
int ctype;
@@ -88,7 +89,14 @@ static int booti_start(struct bootm_info *bmi)
images->os.start = relocated_addr;
images->os.end = relocated_addr + image_size;
- lmb_reserve(images->ep, le32_to_cpu(image_size), LMB_NONE);
+ ep_addr = (phys_addr_t)images->ep;
+ ret = lmb_alloc_mem(LMB_MEM_ALLOC_ADDR, 0, &ep_addr,
+ le32_to_cpu(image_size), LMB_NONE);
+ if (ret) {
+ printf("Failed to allocate memory for the image at %#llx\n",
+ (unsigned long long)images->ep);
+ return 1;
+ }
/*
* Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not
diff --git a/cmd/bootz.c b/cmd/bootz.c
index 99318ff213f..44af7d012aa 100644
--- a/cmd/bootz.c
+++ b/cmd/bootz.c
@@ -28,6 +28,7 @@ static int bootz_start(struct cmd_tbl *cmdtp, int flag, int argc,
{
ulong zi_start, zi_end;
struct bootm_info bmi;
+ phys_addr_t ep_addr;
int ret;
bootm_init(&bmi);
@@ -56,7 +57,14 @@ static int bootz_start(struct cmd_tbl *cmdtp, int flag, int argc,
if (ret != 0)
return 1;
- lmb_reserve(images->ep, zi_end - zi_start, LMB_NONE);
+ ep_addr = (phys_addr_t)images->ep;
+ ret = lmb_alloc_mem(LMB_MEM_ALLOC_ADDR, 0, &ep_addr, zi_end - zi_start,
+ LMB_NONE);
+ if (ret) {
+ printf("Failed to allocate memory for the image at %#llx\n",
+ (unsigned long long)images->ep);
+ return 1;
+ }
/*
* Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not
diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c
index 6e14d34a6bd..8ac0fb98e02 100644
--- a/cmd/eficonfig.c
+++ b/cmd/eficonfig.c
@@ -35,6 +35,7 @@ static int avail_row;
#define EFICONFIG_DESCRIPTION_MAX 32
#define EFICONFIG_OPTIONAL_DATA_MAX 64
+#define EFICONFIG_URI_MAX 512
#define EFICONFIG_MENU_HEADER_ROW_NUM 3
#define EFICONFIG_MENU_DESC_ROW_NUM 5
@@ -539,6 +540,40 @@ struct efi_device_path *eficonfig_create_device_path(struct efi_device_path *dp_
}
/**
+ * eficonfig_create_uri_device_path() - Create an URI based device path
+ * @uri_str: URI string to be added to the device path
+ *
+ * Take the u16 string, convert it to a u8 string, and create a URI
+ * device path. This will be used for the EFI HTTP boot.
+ *
+ * Return: pointer to the URI device path on success, NULL on failure
+ */
+static struct efi_device_path *eficonfig_create_uri_device_path(u16 *uri_str)
+{
+ char *pos, *p;
+ u32 len = 0;
+ efi_uintn_t uridp_len;
+ struct efi_device_path_uri *uridp;
+
+ len = utf16_utf8_strlen(uri_str);
+
+ uridp_len = sizeof(struct efi_device_path) + len + 1;
+ uridp = efi_alloc(uridp_len + sizeof(EFI_DP_END));
+ if (!uridp)
+ return NULL;
+
+ uridp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+ uridp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_URI;
+ uridp->dp.length = uridp_len;
+ p = (char *)&uridp->uri;
+ utf16_utf8_strcpy(&p, uri_str);
+ pos = (char *)uridp + uridp_len;
+ memcpy(pos, &EFI_DP_END, sizeof(EFI_DP_END));
+
+ return &uridp->dp;
+}
+
+/**
* eficonfig_file_selected() - handler of file selection
*
* @data: pointer to the data of selected entry
@@ -984,6 +1019,22 @@ static efi_status_t eficonfig_boot_add_optional_data(void *data)
}
/**
+ * eficonfig_boot_add_uri() - handle user input for HTTP Boot URI
+ *
+ * @data: pointer to the internal boot option structure
+ * Return: status code
+ */
+static efi_status_t eficonfig_boot_add_uri(void *data)
+{
+ struct eficonfig_select_file_info *file_info = data;
+
+ return handle_user_input(file_info->uri, EFICONFIG_URI_MAX, 24,
+ "\n ** Edit URI **\n"
+ "\n"
+ " enter HTTP Boot URI:");
+}
+
+/**
* eficonfig_boot_edit_save() - handler to save the boot option
*
* @data: pointer to the internal boot option structure
@@ -998,7 +1049,8 @@ static efi_status_t eficonfig_boot_edit_save(void *data)
bo->edit_completed = false;
return EFI_NOT_READY;
}
- if (u16_strlen(bo->file_info.current_path) == 0) {
+ if (u16_strlen(bo->file_info.current_path) == 0 &&
+ u16_strlen(bo->file_info.uri) == 0) {
eficonfig_print_msg("File is not selected!");
bo->edit_completed = false;
return EFI_NOT_READY;
@@ -1024,9 +1076,19 @@ efi_status_t eficonfig_process_clear_file_selection(void *data)
file_info->current_path[0] = u'\0';
file_info->dp_volume = NULL;
+ if (file_info->uri)
+ file_info->uri[0] = u'\0';
+
return EFI_ABORTED;
}
+static struct eficonfig_item select_boot_file_menu_items[] = {
+ {"Select File", eficonfig_process_select_file},
+ {"Enter URI", eficonfig_boot_add_uri},
+ {"Clear", eficonfig_process_clear_file_selection},
+ {"Quit", eficonfig_process_quit},
+};
+
static struct eficonfig_item select_file_menu_items[] = {
{"Select File", eficonfig_process_select_file},
{"Clear", eficonfig_process_clear_file_selection},
@@ -1042,16 +1104,30 @@ static struct eficonfig_item select_file_menu_items[] = {
efi_status_t eficonfig_process_show_file_option(void *data)
{
efi_status_t ret;
+ unsigned int menu_count;
struct efimenu *efi_menu;
+ struct eficonfig_item *menu_items;
+ struct eficonfig_select_file_info *file_info = data;
+
+ menu_items = file_info->uri ? select_boot_file_menu_items :
+ select_file_menu_items;
+
+ menu_count = file_info->uri ?
+ ARRAY_SIZE(select_boot_file_menu_items) :
+ ARRAY_SIZE(select_file_menu_items);
+
+ menu_items[0].data = data;
+ menu_items[1].data = data;
+ menu_items[2].data = data;
- select_file_menu_items[0].data = data;
- select_file_menu_items[1].data = data;
- efi_menu = eficonfig_create_fixed_menu(select_file_menu_items,
- ARRAY_SIZE(select_file_menu_items));
+ efi_menu = eficonfig_create_fixed_menu(menu_items, menu_count);
if (!efi_menu)
return EFI_OUT_OF_RESOURCES;
- ret = eficonfig_process_common(efi_menu, " ** Update File **",
+ ret = eficonfig_process_common(efi_menu,
+ file_info->uri ?
+ " ** Update File/URI **" :
+ " ** Update File **",
eficonfig_menu_desc,
eficonfig_display_statusline,
eficonfig_print_entry,
@@ -1121,6 +1197,14 @@ out:
file_info->current_path[len] = u'\0';
file_info->current_volume = tmp->current_volume;
file_info->dp_volume = tmp->dp_volume;
+
+ /*
+ * File being selected, set the URI string to
+ * null so that the file gets picked as the
+ * boot image.
+ */
+ if (file_info->uri)
+ file_info->uri[0] = u'\0';
}
list_for_each_safe(pos, n, &tmp->filepath_list) {
@@ -1224,6 +1308,12 @@ static efi_status_t prepare_file_selection_entry(struct efimenu *efi_menu, char
efi_handle_t handle;
char *devname;
+ /* Check for URI based boot file */
+ if (file_info->uri && utf16_utf8_strlen(file_info->uri))
+ return create_boot_option_entry(efi_menu, title, file_info->uri,
+ eficonfig_process_show_file_option,
+ file_info);
+
devname = calloc(1, EFICONFIG_VOLUME_PATH_MAX + 1);
if (!devname)
return EFI_OUT_OF_RESOURCES;
@@ -1341,6 +1431,27 @@ out:
}
/**
+ * fill_dp_uri() - copy the URI string in the device path
+ * @dp: pointer to the URI device path
+ * @uri_str: URI string to be copied
+ *
+ * Copy the passed URI string to the URI device path. This
+ * requires utf8_utf16_strcpy() to copy the u16 string to
+ * the u8 array in the device path structure.
+ *
+ * Return: None
+ */
+static void fill_dp_uri(struct efi_device_path *dp, u16 **uri_str)
+{
+ u16 *p = *uri_str;
+ struct efi_device_path_uri *uridp;
+
+ uridp = (struct efi_device_path_uri *)dp;
+
+ utf8_utf16_strcpy(&p, uridp->uri);
+}
+
+/**
* fill_file_info() - fill the file info from efi_device_path structure
*
* @dp: pointer to the device path
@@ -1392,10 +1503,13 @@ static efi_status_t eficonfig_edit_boot_option(u16 *varname, struct eficonfig_bo
size_t len;
efi_status_t ret;
char *tmp = NULL, *p;
+ u16 *current_path = NULL;
struct efi_load_option lo = {0};
efi_uintn_t dp_size;
struct efi_device_path *dp = NULL;
efi_uintn_t size = load_option_size;
+ struct efi_device_path *dp_volume = NULL;
+ struct efi_device_path *uri_dp = NULL;
struct efi_device_path *device_dp = NULL;
struct efi_device_path *initrd_dp = NULL;
struct efi_device_path *fdt_dp = NULL;
@@ -1464,6 +1578,12 @@ static efi_status_t eficonfig_edit_boot_option(u16 *varname, struct eficonfig_bo
goto out;
}
+ bo->file_info.uri = calloc(1, EFICONFIG_URI_MAX * sizeof(u16));
+ if (!bo->file_info.uri) {
+ ret = EFI_OUT_OF_RESOURCES;
+ goto out;
+ }
+
/* copy the preset value */
if (load_option) {
ret = efi_deserialize_load_option(&lo, load_option, &size);
@@ -1481,7 +1601,10 @@ static efi_status_t eficonfig_edit_boot_option(u16 *varname, struct eficonfig_bo
u16_strcpy(bo->description, lo.label);
/* EFI image file path is a first instance */
- if (lo.file_path)
+ if (lo.file_path && EFI_DP_TYPE(lo.file_path, MESSAGING_DEVICE,
+ MSG_URI))
+ fill_dp_uri(lo.file_path, &bo->file_info.uri);
+ else if (lo.file_path)
fill_file_info(lo.file_path, &bo->file_info, device_dp);
/* Initrd file path (optional) is placed at second instance. */
@@ -1512,6 +1635,9 @@ static efi_status_t eficonfig_edit_boot_option(u16 *varname, struct eficonfig_bo
goto out;
}
+ if (utf16_utf8_strlen(bo->file_info.uri))
+ uri_dp = eficonfig_create_uri_device_path(bo->file_info.uri);
+
if (bo->initrd_info.dp_volume) {
dp = eficonfig_create_device_path(bo->initrd_info.dp_volume,
bo->initrd_info.current_path);
@@ -1536,7 +1662,10 @@ static efi_status_t eficonfig_edit_boot_option(u16 *varname, struct eficonfig_bo
efi_free_pool(dp);
}
- dp = eficonfig_create_device_path(bo->file_info.dp_volume, bo->file_info.current_path);
+ dp_volume = bo->file_info.dp_volume;
+ current_path = bo->file_info.current_path;
+ dp = uri_dp ?
+ uri_dp : eficonfig_create_device_path(dp_volume, current_path);
if (!dp) {
ret = EFI_OUT_OF_RESOURCES;
goto out;
@@ -1560,6 +1689,7 @@ out:
free(tmp);
free(bo->optional_data);
free(bo->description);
+ free(bo->file_info.uri);
free(bo->file_info.current_path);
free(bo->initrd_info.current_path);
free(bo->fdt_info.current_path);
diff --git a/cmd/help.c b/cmd/help.c
index 56579e28d31..1be83ba607d 100644
--- a/cmd/help.c
+++ b/cmd/help.c
@@ -9,13 +9,9 @@
static int do_help(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
-#ifdef CONFIG_CMDLINE
struct cmd_tbl *start = ll_entry_start(struct cmd_tbl, cmd);
const int len = ll_entry_count(struct cmd_tbl, cmd);
return _do_help(start, len, cmdtp, flag, argc, argv);
-#else
- return 0;
-#endif
}
U_BOOT_CMD(
@@ -27,7 +23,6 @@ U_BOOT_CMD(
" - print detailed usage of 'command'"
);
-#ifdef CONFIG_CMDLINE
/*
* This does not use the U_BOOT_CMD macro as ? can't be used in symbol names
* nor can we rely on the CONFIG_SYS_LONGHELP helper macro
@@ -39,4 +34,3 @@ ll_entry_declare(struct cmd_tbl, question_mark, cmd) = {
""
#endif /* CONFIG_SYS_LONGHELP */
};
-#endif
diff --git a/cmd/load.c b/cmd/load.c
index 899bb4f598e..159767aa7f7 100644
--- a/cmd/load.c
+++ b/cmd/load.c
@@ -178,17 +178,20 @@ static ulong load_serial(long offset)
#endif
{
void *dst;
+ phys_addr_t dst_addr;
- ret = lmb_reserve(store_addr, binlen, LMB_NONE);
+ dst_addr = (phys_addr_t)store_addr;
+ ret = lmb_alloc_mem(LMB_MEM_ALLOC_ADDR, 0, &dst_addr,
+ binlen, LMB_NONE);
if (ret) {
printf("\nCannot overwrite reserved area (%08lx..%08lx)\n",
store_addr, store_addr + binlen);
return ret;
}
- dst = map_sysmem(store_addr, binlen);
+ dst = map_sysmem(dst_addr, binlen);
memcpy(dst, binbuf, binlen);
unmap_sysmem(dst);
- lmb_free(store_addr, binlen);
+ lmb_free(dst_addr, binlen, LMB_NONE);
}
if ((store_addr) < start_addr)
start_addr = store_addr;
diff --git a/cmd/lwip/Makefile b/cmd/lwip/Makefile
new file mode 100644
index 00000000000..a7f8976af3f
--- /dev/null
+++ b/cmd/lwip/Makefile
@@ -0,0 +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/dhcp.c b/cmd/lwip/dhcp.c
new file mode 100644
index 00000000000..3894d71f654
--- /dev/null
+++ b/cmd/lwip/dhcp.c
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2024-2025 Linaro Ltd. */
+
+#include <command.h>
+#include <net.h>
+
+U_BOOT_CMD(dhcp, 3, 1, do_dhcp,
+ "boot image via network using DHCP/TFTP protocol",
+ "[loadAddress] [[hostIPaddr:]bootfilename]");
diff --git a/cmd/lwip/dns.c b/cmd/lwip/dns.c
new file mode 100644
index 00000000000..b5fccc7433e
--- /dev/null
+++ b/cmd/lwip/dns.c
@@ -0,0 +1,116 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2024 Linaro Ltd. */
+
+#include <command.h>
+#include <console.h>
+#include <env.h>
+#include <lwip/dns.h>
+#include <lwip/timeouts.h>
+#include <net.h>
+#include <time.h>
+
+U_BOOT_CMD(dns, 3, 1, do_dns, "lookup the IP of a hostname",
+ "hostname [envvar]");
+
+#define DNS_RESEND_MS 1000
+#define DNS_TIMEOUT_MS 10000
+
+struct dns_cb_arg {
+ ip_addr_t host_ipaddr;
+ const char *var;
+ 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)
+{
+ struct dns_cb_arg *dns_cb_arg = arg;
+ char *ipstr = ip4addr_ntoa(ipaddr);
+
+ dns_cb_arg->done = true;
+
+ if (!ipaddr) {
+ printf("DNS: host not found\n");
+ dns_cb_arg->host_ipaddr.addr = 0;
+ return;
+ }
+
+ dns_cb_arg->host_ipaddr.addr = ipaddr->addr;
+
+ if (dns_cb_arg->var)
+ env_set(dns_cb_arg->var, ipstr);
+}
+
+static int dns_loop(struct udevice *udev, const char *name, const char *var)
+{
+ struct dns_cb_arg dns_cb_arg = { };
+ struct netif *netif;
+ ip_addr_t ipaddr;
+ ulong start;
+ int ret;
+
+ dns_cb_arg.var = var;
+
+ netif = net_lwip_new_netif(udev);
+ if (!netif)
+ return CMD_RET_FAILURE;
+
+ if (net_lwip_dns_init()) {
+ net_lwip_remove_netif(netif);
+ return CMD_RET_FAILURE;
+ }
+
+ dns_cb_arg.done = false;
+
+ ret = dns_gethostbyname(name, &ipaddr, dns_cb, &dns_cb_arg);
+
+ if (ret == ERR_OK) {
+ dns_cb(name, &ipaddr, &dns_cb_arg);
+ } else if (ret == ERR_INPROGRESS) {
+ start = get_timer(0);
+ sys_timeout(DNS_RESEND_MS, do_dns_tmr, NULL);
+ do {
+ net_lwip_rx(udev, netif);
+ if (dns_cb_arg.done)
+ break;
+ if (ctrlc()) {
+ printf("\nAbort\n");
+ break;
+ }
+ } while (get_timer(start) < DNS_TIMEOUT_MS);
+ sys_untimeout(do_dns_tmr, NULL);
+ }
+
+ net_lwip_remove_netif(netif);
+
+ if (dns_cb_arg.done && dns_cb_arg.host_ipaddr.addr != 0) {
+ if (!var)
+ printf("%s\n", ipaddr_ntoa(&ipaddr));
+ return CMD_RET_SUCCESS;
+ }
+
+ return CMD_RET_FAILURE;
+}
+
+int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ char *name;
+ char *var = NULL;
+
+ if (argc == 1 || argc > 3)
+ return CMD_RET_USAGE;
+
+ name = argv[1];
+
+ if (argc == 3)
+ var = argv[2];
+
+ if (net_lwip_eth_start() < 0)
+ return CMD_RET_FAILURE;
+
+ return dns_loop(eth_get_dev(), name, var);
+}
diff --git a/cmd/lwip/ping.c b/cmd/lwip/ping.c
new file mode 100644
index 00000000000..87f8e958e48
--- /dev/null
+++ b/cmd/lwip/ping.c
@@ -0,0 +1,182 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2024 Linaro Ltd. */
+
+#include <command.h>
+#include <console.h>
+#include <dm/device.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <lwip/icmp.h>
+#include <lwip/inet_chksum.h>
+#include <lwip/raw.h>
+#include <lwip/timeouts.h>
+#include <net.h>
+#include <time.h>
+
+U_BOOT_CMD(ping, 2, 1, do_ping, "send ICMP ECHO_REQUEST to network host",
+ "pingAddressOrHostName");
+
+#define PING_DELAY_MS 1000
+#define PING_COUNT 5
+/* Ping identifier - must fit on a u16_t */
+#define PING_ID 0xAFAF
+
+struct ping_ctx {
+ ip_addr_t target;
+ struct raw_pcb *pcb;
+ struct icmp_echo_hdr *iecho;
+ uint16_t seq_num;
+ bool alive;
+};
+
+static u8_t ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p,
+ const ip_addr_t *addr)
+{
+ struct ping_ctx *ctx = arg;
+ struct icmp_echo_hdr *iecho = ctx->iecho;
+
+ if (addr->addr != ctx->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(ctx->seq_num)) {
+ ctx->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(struct ping_ctx *ctx)
+{
+ ctx->pcb = raw_new(IP_PROTO_ICMP);
+ if (!ctx->pcb)
+ return -ENOMEM;
+
+ raw_recv(ctx->pcb, ping_recv, ctx);
+ raw_bind(ctx->pcb, IP_ADDR_ANY);
+
+ return 0;
+}
+
+static void ping_raw_stop(struct ping_ctx *ctx)
+{
+ if (ctx->pcb)
+ raw_remove(ctx->pcb);
+}
+
+static void ping_prepare_echo(struct ping_ctx *ctx)
+{
+ struct icmp_echo_hdr *iecho = ctx->iecho;
+
+ ICMPH_TYPE_SET(iecho, ICMP_ECHO);
+ ICMPH_CODE_SET(iecho, 0);
+ iecho->chksum = 0;
+ iecho->id = PING_ID;
+ iecho->seqno = lwip_htons(ctx->seq_num);
+
+ iecho->chksum = inet_chksum(iecho, sizeof(*iecho));
+}
+
+static void ping_send_icmp(struct ping_ctx *ctx)
+{
+ struct pbuf *p;
+ 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) {
+ ctx->iecho = (struct icmp_echo_hdr *)p->payload;
+ ping_prepare_echo(ctx);
+ raw_sendto(ctx->pcb, p, &ctx->target);
+ }
+
+ pbuf_free(p);
+}
+
+static void ping_send(void *arg)
+{
+ struct ping_ctx *ctx = arg;
+
+ ctx->seq_num++;
+ if (ctx->seq_num <= PING_COUNT) {
+ ping_send_icmp(ctx);
+ sys_timeout(PING_DELAY_MS, ping_send, ctx);
+ }
+}
+
+static int ping_loop(struct udevice *udev, const ip_addr_t *addr)
+{
+ struct ping_ctx ctx = {};
+ struct netif *netif;
+ int ret;
+
+ netif = net_lwip_new_netif(udev);
+ if (!netif)
+ return -ENODEV;
+
+ printf("Using %s device\n", udev->name);
+
+ ret = ping_raw_init(&ctx);
+ if (ret < 0) {
+ net_lwip_remove_netif(netif);
+ return ret;
+ }
+
+ ctx.target = *addr;
+
+ ping_send(&ctx);
+
+ do {
+ net_lwip_rx(udev, netif);
+ if (ctx.alive)
+ break;
+ if (ctrlc()) {
+ printf("\nAbort\n");
+ break;
+ }
+ } while (ctx.seq_num <= PING_COUNT);
+
+ sys_untimeout(ping_send, &ctx);
+ ping_raw_stop(&ctx);
+
+ net_lwip_remove_netif(netif);
+
+ if (ctx.alive)
+ return 0;
+
+ printf("ping failed; host %s is not alive\n", ipaddr_ntoa(addr));
+ return -1;
+}
+
+int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ ip_addr_t addr;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ if (net_lwip_dns_resolve(argv[1], &addr))
+ return CMD_RET_USAGE;
+
+restart:
+ if (net_lwip_eth_start() < 0 || ping_loop(eth_get_dev(), &addr) < 0) {
+ if (net_start_again() == 0)
+ goto restart;
+ else
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
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;
+}
diff --git a/cmd/lwip/tftp.c b/cmd/lwip/tftp.c
new file mode 100644
index 00000000000..6bb7a3733a2
--- /dev/null
+++ b/cmd/lwip/tftp.c
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2024-2025 Linaro Ltd. */
+
+#include <command.h>
+#include <net.h>
+
+U_BOOT_CMD(tftpboot, 3, 0, do_tftpb,
+ "boot image via network using TFTP protocol",
+ "[loadAddress] [[hostIPaddr:]bootfilename]");
diff --git a/cmd/lwip/wget.c b/cmd/lwip/wget.c
new file mode 100644
index 00000000000..fc9bc11cd83
--- /dev/null
+++ b/cmd/lwip/wget.c
@@ -0,0 +1,222 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2024-2025 Linaro Ltd. */
+
+#include <command.h>
+#include <env.h>
+#include <image.h>
+#include <net.h>
+#include <lwip/altcp_tls.h>
+
+U_BOOT_CMD(wget, 4, 1, do_wget,
+ "boot image via network using HTTP/HTTPS protocol"
+#if defined(CONFIG_WGET_CACERT)
+ "\nwget cacert - configure wget root certificates"
+#endif
+ ,
+ "[loadAddress] url\n"
+ "wget [loadAddress] [host:]path\n"
+ " - load file"
+#if defined(CONFIG_WGET_CACERT)
+ "\nwget cacert <address> <length>\n"
+ " - provide CA certificates (0 0 to remove current)"
+ "\nwget cacert none|optional|required\n"
+ " - set server certificate verification mode (default: optional)"
+#if defined(CONFIG_WGET_BUILTIN_CACERT)
+ "\nwget cacert builtin\n"
+ " - use the builtin CA certificates"
+#endif
+#endif
+);
+
+#if CONFIG_IS_ENABLED(WGET_CACERT) || CONFIG_IS_ENABLED(WGET_BUILTIN_CACERT)
+char *cacert;
+size_t cacert_size;
+enum auth_mode cacert_auth_mode = AUTH_OPTIONAL;
+
+#if CONFIG_IS_ENABLED(WGET_BUILTIN_CACERT)
+extern const char builtin_cacert[];
+extern const size_t builtin_cacert_size;
+bool cacert_initialized;
+#endif
+
+static int _set_cacert(const void *addr, size_t sz)
+{
+ mbedtls_x509_crt crt;
+ void *p;
+ int ret;
+
+ if (cacert)
+ free(cacert);
+
+ if (!addr) {
+ cacert = NULL;
+ cacert_size = 0;
+ return CMD_RET_SUCCESS;
+ }
+
+ p = malloc(sz);
+ if (!p)
+ return CMD_RET_FAILURE;
+ cacert = p;
+ cacert_size = sz;
+
+ memcpy(cacert, (void *)addr, sz);
+
+ mbedtls_x509_crt_init(&crt);
+ ret = mbedtls_x509_crt_parse(&crt, cacert, cacert_size);
+ if (ret) {
+ if (!wget_info->silent)
+ printf("Could not parse certificates (%d)\n", ret);
+ free(cacert);
+ cacert = NULL;
+ cacert_size = 0;
+ return CMD_RET_FAILURE;
+ }
+
+#if CONFIG_IS_ENABLED(WGET_BUILTIN_CACERT)
+ cacert_initialized = true;
+#endif
+ return CMD_RET_SUCCESS;
+}
+
+#if CONFIG_IS_ENABLED(WGET_BUILTIN_CACERT)
+int set_cacert_builtin(void)
+{
+ cacert_auth_mode = AUTH_REQUIRED;
+ return _set_cacert(builtin_cacert, builtin_cacert_size);
+}
+#endif
+#endif /* CONFIG_WGET_CACERT || CONFIG_WGET_BUILTIN_CACERT */
+
+#if CONFIG_IS_ENABLED(WGET_CACERT)
+static int set_auth(enum auth_mode auth)
+{
+ cacert_auth_mode = auth;
+
+ return CMD_RET_SUCCESS;
+}
+
+static int set_cacert(char * const saddr, char * const ssz)
+{
+ ulong addr, sz;
+
+ addr = hextoul(saddr, NULL);
+ sz = hextoul(ssz, NULL);
+
+ return _set_cacert((void *)addr, sz);
+}
+#endif
+
+/*
+ * Legacy syntax support
+ * Convert [<server_name_or_ip>:]filename into a URL if needed
+ */
+static int parse_legacy_arg(char *arg, char *nurl, size_t rem)
+{
+ char *p = nurl;
+ size_t n;
+ char *col = strchr(arg, ':');
+ char *env;
+ char *server;
+ char *path;
+
+ if (strstr(arg, "http") == arg) {
+ n = snprintf(nurl, rem, "%s", arg);
+ if (n < 0 || n > rem)
+ return -1;
+ return 0;
+ }
+
+ n = snprintf(p, rem, "%s", "http://");
+ if (n < 0 || n > rem)
+ return -1;
+ p += n;
+ rem -= n;
+
+ if (col) {
+ n = col - arg;
+ server = arg;
+ path = col + 1;
+ } else {
+ env = env_get("httpserverip");
+ if (!env)
+ env = env_get("serverip");
+ if (!env) {
+ log_err("error: httpserver/serverip has to be set\n");
+ return -1;
+ }
+ n = strlen(env);
+ server = env;
+ path = arg;
+ }
+
+ if (rem < n)
+ return -1;
+ strncpy(p, server, n);
+ p += n;
+ rem -= n;
+ if (rem < 1)
+ return -1;
+ *p = '/';
+ p++;
+ rem--;
+ n = strlen(path);
+ if (rem < n)
+ return -1;
+ strncpy(p, path, n);
+ p += n;
+ rem -= n;
+ if (rem < 1)
+ return -1;
+ *p = '\0';
+
+ return 0;
+}
+
+int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
+{
+ char *end;
+ char *url;
+ ulong dst_addr;
+ char nurl[1024];
+
+#if CONFIG_IS_ENABLED(WGET_CACERT)
+ if (argc == 4 && !strncmp(argv[1], "cacert", strlen("cacert")))
+ return set_cacert(argv[2], argv[3]);
+ if (argc == 3 && !strncmp(argv[1], "cacert", strlen("cacert"))) {
+#if CONFIG_IS_ENABLED(WGET_BUILTIN_CACERT)
+ if (!strncmp(argv[2], "builtin", strlen("builtin")))
+ return set_cacert_builtin();
+#endif
+ if (!strncmp(argv[2], "none", strlen("none")))
+ return set_auth(AUTH_NONE);
+ if (!strncmp(argv[2], "optional", strlen("optional")))
+ return set_auth(AUTH_OPTIONAL);
+ if (!strncmp(argv[2], "required", strlen("required")))
+ return set_auth(AUTH_REQUIRED);
+ return CMD_RET_USAGE;
+ }
+#endif
+
+ if (argc < 2 || argc > 3)
+ return CMD_RET_USAGE;
+
+ dst_addr = hextoul(argv[1], &end);
+ if (end == (argv[1] + strlen(argv[1]))) {
+ if (argc < 3)
+ return CMD_RET_USAGE;
+ url = argv[2];
+ } else {
+ dst_addr = image_load_addr;
+ url = argv[1];
+ }
+
+ if (parse_legacy_arg(url, nurl, sizeof(nurl)))
+ return CMD_RET_FAILURE;
+
+ wget_info = &default_wget_info;
+ if (wget_do_request(dst_addr, nurl))
+ return CMD_RET_FAILURE;
+
+ return CMD_RET_SUCCESS;
+}
diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
deleted file mode 100644
index cecf8d02555..00000000000
--- a/cmd/net-lwip.c
+++ /dev/null
@@ -1,50 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/* Copyright (C) 2024 Linaro Ltd. */
-
-#include <command.h>
-#include <net.h>
-
-#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
-
-#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,
- "boot image via network using TFTP protocol",
- "[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
-
-#if defined(CONFIG_CMD_WGET)
-U_BOOT_CMD(wget, 4, 1, do_wget,
- "boot image via network using HTTP/HTTPS protocol"
-#if defined(CONFIG_WGET_CACERT)
- "\nwget cacert - configure wget root certificates"
-#endif
- ,
- "[loadAddress] url\n"
- "wget [loadAddress] [host:]path\n"
- " - load file"
-#if defined(CONFIG_WGET_CACERT)
- "\nwget cacert <address> <length>\n"
- " - provide CA certificates (0 0 to remove current)"
- "\nwget cacert none|optional|required\n"
- " - set server certificate verification mode (default: optional)"
-#if defined(CONFIG_WGET_BUILTIN_CACERT)
- "\nwget cacert builtin\n"
- " - use the builtin CA certificates"
-#endif
-#endif
-);
-#endif
diff --git a/cmd/smbios.c b/cmd/smbios.c
index 562dd7959be..ed419f19028 100644
--- a/cmd/smbios.c
+++ b/cmd/smbios.c
@@ -280,7 +280,7 @@ static void smbios_print_type3(struct smbios_type3 *table)
int i;
u8 *addr = (u8 *)table + offsetof(struct smbios_type3, sku_number);
- printf("Baseboard Information\n");
+ printf("Chassis Information\n");
smbios_print_str("Manufacturer", table, table->manufacturer);
printf("\tType: 0x%02x\n", table->chassis_type);
smbios_print_str("Version", table, table->version);
diff --git a/cmd/tpm-v2.c b/cmd/tpm-v2.c
index a62862e94f9..346e21d27bb 100644
--- a/cmd/tpm-v2.c
+++ b/cmd/tpm-v2.c
@@ -113,7 +113,7 @@ static int do_tpm2_pcr_extend(struct cmd_tbl *cmdtp, int flag, int argc,
return CMD_RET_USAGE;
if (argc == 4) {
algo = tpm2_name_to_algorithm(argv[3]);
- if (algo < 0)
+ if (algo == TPM2_ALG_INVAL)
return CMD_RET_FAILURE;
}
algo_len = tpm2_algorithm_to_len(algo);
@@ -157,7 +157,7 @@ static int do_tpm_pcr_read(struct cmd_tbl *cmdtp, int flag, int argc,
return CMD_RET_USAGE;
if (argc == 4) {
algo = tpm2_name_to_algorithm(argv[3]);
- if (algo < 0)
+ if (algo == TPM2_ALG_INVAL)
return CMD_RET_FAILURE;
}
algo_len = tpm2_algorithm_to_len(algo);
@@ -288,7 +288,7 @@ static int do_tpm2_pcrallocate(struct cmd_tbl *cmdtp, int flag, int argc,
return CMD_RET_USAGE;
algo = tpm2_name_to_algorithm(argv[1]);
- if (algo == -EINVAL)
+ if (algo == TPM2_ALG_INVAL)
return CMD_RET_USAGE;
ret = get_tpm(&dev);