diff options
Diffstat (limited to 'cmd')
-rw-r--r-- | cmd/Kconfig | 65 | ||||
-rw-r--r-- | cmd/Makefile | 5 | ||||
-rw-r--r-- | cmd/abootimg.c | 2 | ||||
-rw-r--r-- | cmd/booti.c | 10 | ||||
-rw-r--r-- | cmd/bootz.c | 10 | ||||
-rw-r--r-- | cmd/eficonfig.c | 146 | ||||
-rw-r--r-- | cmd/help.c | 6 | ||||
-rw-r--r-- | cmd/load.c | 9 | ||||
-rw-r--r-- | cmd/lwip/Makefile | 6 | ||||
-rw-r--r-- | cmd/lwip/dhcp.c | 9 | ||||
-rw-r--r-- | cmd/lwip/dns.c | 116 | ||||
-rw-r--r-- | cmd/lwip/ping.c | 182 | ||||
-rw-r--r-- | cmd/lwip/sntp.c | 134 | ||||
-rw-r--r-- | cmd/lwip/tftp.c | 9 | ||||
-rw-r--r-- | cmd/lwip/wget.c | 222 | ||||
-rw-r--r-- | cmd/net-lwip.c | 50 | ||||
-rw-r--r-- | cmd/smbios.c | 2 | ||||
-rw-r--r-- | cmd/tpm-v2.c | 6 |
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); |