Pull request for efi-2022-10-rc5

Documentation:
 
 * man-page for tftpput
 
 UEFI:
 
 * fix driver binding protocol for block IO devices
 * don't delete invalid handles
 * add a unit test for the EFI Conformance Profile Table
 
 Other:
 
 * correct short text for tftpboot
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEbcT5xx8ppvoGt20zxIHbvCwFGsQFAmMbeUEACgkQxIHbvCwF
 GsSGsw//WJAuuzP5ufWGxJk2pR9v9LatIsV+w2W1fBTsTb/dbMZ4Sika2Z1izeer
 vmakldnOTLoTXZxng/Ke9J7PEefS8NSUgHbXYLq6a5ckrsji58kGHhDvUjrU2eOf
 D4SBh8eGW/wgmnzHgmsVU0vcXbtWUomWlV4v8SGjYWq5KOTOdFGYmMddqv8cnUVa
 wXHktLaDi9TzzFdfeYPbAlKboQTdRkw0CbzY8z6jlxm2Yd/i7Iw9v7MWwFN5rv1N
 Zlx9Kl0SV1Jz//yzUajyiXXVYK+kVcpjDcvOPhx4GL96mcvW4yyGlOKjpUkTR3H3
 l7112u4lwNSUIJIeDMCazqKgdGMsl+RLuJymAIRCdaBs3c0FsuX4WHNAr0H1KT9X
 oVnzeBKZKjFTT76Q39F80O0JrdDMxqMm1fGiy1ySlRCJNd+dlYZKoopt8PpWkk1E
 IBHsE1m1OXe+n2PNrh6YR9egv9RmfdwBEl0wBftNb9DQ+gNAvR7wVRpmDRCqYuBR
 l/k6GsznHK4hh1Wh+BhrrUeQ3YbboK3RvGA9toYp6BEk/5F2dDuy5pVM7OETjGEY
 DaKjqPjMv41SCIzpcEkzPJEvQ0tEFuk+GEC168IXQmcV/gttvuLNLFfnlLE1amQr
 g09ePeaXKzjiWYSi5wEz1GQs7W9WBnJ5+2zOL41ih125xra6/NE=
 =1zZW
 -----END PGP SIGNATURE-----

Merge tag 'efi-2022-10-rc5' of https://source.denx.de/u-boot/custodians/u-boot-efi

Pull request for efi-2022-10-rc5

Documentation:

* man-page for tftpput

UEFI:

* fix driver binding protocol for block IO devices
* don't delete invalid handles
* add a unit test for the EFI Conformance Profile Table

Other:

* correct short text for tftpboot
This commit is contained in:
Tom Rini 2022-09-09 14:10:51 -04:00
commit a5fc388ed9
12 changed files with 290 additions and 64 deletions

View file

@ -1719,7 +1719,7 @@ config CMD_TFTPBOOT
bool "tftpboot"
default y
help
tftpboot - boot image via network using TFTP protocol
tftpboot - load file via network using TFTP protocol
config CMD_TFTPPUT
bool "tftp put"

View file

@ -46,7 +46,7 @@ int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
U_BOOT_CMD(
tftpboot, 3, 1, do_tftpb,
"boot image via network using TFTP protocol",
"load file via network using TFTP protocol",
"[loadAddress] [[hostIPaddr:]bootfilename]"
);
#endif
@ -189,30 +189,49 @@ static void netboot_update_env(void)
#endif
}
static int netboot_common(enum proto_t proto, struct cmd_tbl *cmdtp, int argc,
char *const argv[])
/**
* parse_addr_size() - parse address and size arguments for tftpput
*
* @argv: command line arguments
* Return: 0 on success
*/
static int parse_addr_size(char * const argv[])
{
if (strict_strtoul(argv[1], 16, &image_save_addr) < 0 ||
strict_strtoul(argv[2], 16, &image_save_size) < 0) {
printf("Invalid address/size\n");
return CMD_RET_USAGE;
}
return 0;
}
/**
* parse_args() - parse command line arguments
*
* @proto: command prototype
* @argc: number of arguments
* @argv: command line arguments
* Return: 0 on success
*/
static int parse_args(enum proto_t proto, int argc, char *const argv[])
{
char *s;
char *end;
int rcode = 0;
int size;
ulong addr;
net_boot_file_name_explicit = false;
/* pre-set image_load_addr */
s = env_get("loadaddr");
if (s != NULL)
image_load_addr = hextoul(s, NULL);
char *end;
switch (argc) {
case 1:
if (CONFIG_IS_ENABLED(CMD_TFTPPUT) && proto == TFTPPUT)
return 1;
/* refresh bootfile name from env */
copy_filename(net_boot_file_name, env_get("bootfile"),
sizeof(net_boot_file_name));
break;
case 2: /*
case 2:
if (CONFIG_IS_ENABLED(CMD_TFTPPUT) && proto == TFTPPUT)
return 1;
/*
* Only one arg - accept two forms:
* Just load address, or just boot file name. The latter
* form must be written in a format which can not be
@ -232,29 +251,52 @@ static int netboot_common(enum proto_t proto, struct cmd_tbl *cmdtp, int argc,
break;
case 3:
image_load_addr = hextoul(argv[1], NULL);
net_boot_file_name_explicit = true;
copy_filename(net_boot_file_name, argv[2],
sizeof(net_boot_file_name));
if (CONFIG_IS_ENABLED(CMD_TFTPPUT) && proto == TFTPPUT) {
if (parse_addr_size(argv))
return 1;
} else {
image_load_addr = hextoul(argv[1], NULL);
net_boot_file_name_explicit = true;
copy_filename(net_boot_file_name, argv[2],
sizeof(net_boot_file_name));
}
break;
#ifdef CONFIG_CMD_TFTPPUT
case 4:
if (strict_strtoul(argv[1], 16, &image_save_addr) < 0 ||
strict_strtoul(argv[2], 16, &image_save_size) < 0) {
printf("Invalid address/size\n");
return CMD_RET_USAGE;
}
if (parse_addr_size(argv))
return 1;
net_boot_file_name_explicit = true;
copy_filename(net_boot_file_name, argv[3],
sizeof(net_boot_file_name));
break;
#endif
default:
return 1;
}
return 0;
}
static int netboot_common(enum proto_t proto, struct cmd_tbl *cmdtp, int argc,
char *const argv[])
{
char *s;
int rcode = 0;
int size;
net_boot_file_name_explicit = false;
*net_boot_file_name = '\0';
/* pre-set image_load_addr */
s = env_get("loadaddr");
if (s != NULL)
image_load_addr = hextoul(s, NULL);
if (parse_args(proto, argc, argv)) {
bootstage_error(BOOTSTAGE_ID_NET_START);
return CMD_RET_USAGE;
}
bootstage_mark(BOOTSTAGE_ID_NET_START);
size = net_loop(proto);

87
doc/usage/cmd/tftpput.rst Normal file
View file

@ -0,0 +1,87 @@
.. SPDX-License-Identifier: GPL-2.0+:
tftpput command
===============
Synopsis
--------
::
tftpput address size [[hostIPaddr:]filename]
Description
-----------
The tftpput command is used to transfer a file to a TFTP server.
By default the destination port is 69 and the source port is pseudo-random.
If CONFIG_TFTP_PORT=y, the environment variable *tftpsrcp* can be used to set
the source port and the environment variable *tftpdstp* can be used to set
the destination port.
address
memory address where the data starts
size
number of bytes to be transferred
hostIPaddr
IP address of the TFTP server, defaults to the value of environment
variable *serverip*
filename
path of the file to be written. If not provided, the client's IP address is
used to construct a default file name, e.g. C0.A8.00.28.img for IP address
192.168.0.40.
Example
-------
In the example the following steps are executed:
* setup client network address
* load a file from the SD-card
* send the file via TFTP to a server
::
=> setenv autoload no
=> dhcp
BOOTP broadcast 1
DHCP client bound to address 192.168.1.40 (7 ms)
=> load mmc 0:1 $loadaddr test.txt
260096 bytes read in 13 ms (19.1 MiB/s)
=> tftpput $loadaddr $filesize 192.168.1.3:upload/test.txt
Using ethernet@1c30000 device
TFTP to server 192.168.1.3; our IP address is 192.168.1.40
Filename 'upload/test.txt'.
Save address: 0x42000000
Save size: 0x3f800
Saving: #################
4.4 MiB/s
done
Bytes transferred = 260096 (3f800 hex)
=>
Configuration
-------------
The command is only available if CONFIG_CMD_TFTPPUT=y.
CONFIG_TFTP_BLOCKSIZE defines the size of the TFTP blocks sent. It defaults
to 1468 matching an ethernet MTU of 1500.
If CONFIG_TFTP_PORT=y, the environment variables *tftpsrcp* and *tftpdstp* can
be used to set the source and the destination ports.
CONFIG_TFTP_WINDOWSIZE can be used to set the TFTP window size of transmits
after which an ACK response is required. The window size defaults to 1.
If CONFIG_TFTP_TSIZE=y, the progress bar is limited to 50 '#' characters.
Otherwise an '#' is written per UDP package which may decrease performance.
Return value
------------
The return value $? is 0 (true) on success and 1 (false) otherwise.

View file

@ -63,6 +63,7 @@ Shell commands
cmd/scp03
cmd/setexpr
cmd/size
cmd/tftpput
cmd/true
cmd/ums
cmd/wdt

View file

@ -18,6 +18,9 @@
#define EFI_ST_FAILURE 1
#define EFI_ST_SUCCESS_STR u"SUCCESS"
extern const struct efi_system_table *st_systable;
extern const struct efi_boot_services *st_boottime;
/**
* efi_st_printf() - print a message
*
@ -130,6 +133,14 @@ u16 *efi_st_translate_code(u16 code);
*/
int efi_st_strcmp_16_8(const u16 *buf1, const char *buf2);
/**
* efi_st_get_config_table() - get configuration table
*
* @guid: GUID of the configuration table
* Return: pointer to configuration table or NULL
*/
void *efi_st_get_config_table(const efi_guid_t *guid);
/**
* efi_st_get_key() - reads an Unicode character from the input device
*

View file

@ -71,6 +71,15 @@ static efi_status_t EFIAPI efi_uc_supported(
EFI_ENTRY("%p, %p, %ls", this, controller_handle,
efi_dp_str(remaining_device_path));
/*
* U-Boot internal devices install protocols interfaces without calling
* ConnectController(). Hence we should not bind an extra driver.
*/
if (controller_handle->dev) {
ret = EFI_UNSUPPORTED;
goto out;
}
ret = EFI_CALL(systab.boottime->open_protocol(
controller_handle, bp->ops->protocol,
&interface, this->driver_binding_handle,

View file

@ -619,9 +619,14 @@ efi_status_t efi_remove_all_protocols(const efi_handle_t handle)
*/
void efi_delete_handle(efi_handle_t handle)
{
if (!handle)
efi_status_t ret;
ret = efi_remove_all_protocols(handle);
if (ret == EFI_INVALID_PARAMETER) {
log_err("Can't remove invalid handle %p\n", handle);
return;
efi_remove_all_protocols(handle);
}
list_del(&handle->link);
free(handle);
}

View file

@ -49,6 +49,7 @@ efi_selftest_variables.o \
efi_selftest_variables_runtime.o \
efi_selftest_watchdog.o
obj-$(CONFIG_EFI_ECPT) += efi_selftest_ecpt.o
obj-$(CONFIG_NET) += efi_selftest_snp.o
obj-$(CONFIG_EFI_DEVICE_PATH_TO_TEXT) += efi_selftest_devicepath.o

View file

@ -14,8 +14,8 @@
#define EFI_ST_EXECUTE 2
#define EFI_ST_TEARDOWN 4
static const struct efi_system_table *systable;
static const struct efi_boot_services *boottime;
const struct efi_system_table *st_systable;
const struct efi_boot_services *st_boottime;
static const struct efi_runtime_services *runtime;
static efi_handle_t handle;
static u16 reset_message[] = u"Selftest completed";
@ -41,7 +41,7 @@ void efi_st_exit_boot_services(void)
/* Do not detach devices in ExitBootServices. We need the console. */
efi_st_keep_devices = true;
ret = boottime->get_memory_map(&map_size, NULL, &map_key, &desc_size,
ret = st_boottime->get_memory_map(&map_size, NULL, &map_key, &desc_size,
&desc_version);
if (ret != EFI_BUFFER_TOO_SMALL) {
efi_st_error(
@ -50,19 +50,19 @@ void efi_st_exit_boot_services(void)
}
/* Allocate extra space for newly allocated memory */
map_size += sizeof(struct efi_mem_desc);
ret = boottime->allocate_pool(EFI_BOOT_SERVICES_DATA, map_size,
ret = st_boottime->allocate_pool(EFI_BOOT_SERVICES_DATA, map_size,
(void **)&memory_map);
if (ret != EFI_SUCCESS) {
efi_st_error("AllocatePool did not return EFI_SUCCESS\n");
return;
}
ret = boottime->get_memory_map(&map_size, memory_map, &map_key,
ret = st_boottime->get_memory_map(&map_size, memory_map, &map_key,
&desc_size, &desc_version);
if (ret != EFI_SUCCESS) {
efi_st_error("GetMemoryMap did not return EFI_SUCCESS\n");
return;
}
ret = boottime->exit_boot_services(handle, map_key);
ret = st_boottime->exit_boot_services(handle, map_key);
if (ret != EFI_SUCCESS) {
efi_st_error("ExitBootServices did not return EFI_SUCCESS\n");
return;
@ -84,7 +84,7 @@ static int setup(struct efi_unit_test *test, unsigned int *failures)
if (!test->setup)
return EFI_ST_SUCCESS;
efi_st_printc(EFI_LIGHTBLUE, "\nSetting up '%s'\n", test->name);
ret = test->setup(handle, systable);
ret = test->setup(handle, st_systable);
if (ret != EFI_ST_SUCCESS) {
efi_st_error("Setting up '%s' failed\n", test->name);
++*failures;
@ -240,8 +240,8 @@ void efi_st_do_tests(const u16 *testname, unsigned int phase,
* All tests use a driver model and are run in three phases:
* setup, execute, teardown.
*
* A test may be setup and executed at boottime,
* it may be setup at boottime and executed at runtime,
* A test may be setup and executed at st_boottime,
* it may be setup at st_boottime and executed at runtime,
* or it may be setup and executed at runtime.
*
* After executing all tests the system is reset.
@ -257,14 +257,14 @@ efi_status_t EFIAPI efi_selftest(efi_handle_t image_handle,
struct efi_loaded_image *loaded_image;
efi_status_t ret;
systable = systab;
boottime = systable->boottime;
runtime = systable->runtime;
st_systable = systab;
st_boottime = st_systable->boottime;
runtime = st_systable->runtime;
handle = image_handle;
con_out = systable->con_out;
con_in = systable->con_in;
con_out = st_systable->con_out;
con_in = st_systable->con_in;
ret = boottime->handle_protocol(image_handle, &efi_guid_loaded_image,
ret = st_boottime->handle_protocol(image_handle, &efi_guid_loaded_image,
(void **)&loaded_image);
if (ret != EFI_SUCCESS) {
efi_st_error("Cannot open loaded image protocol\n");
@ -280,9 +280,9 @@ efi_status_t EFIAPI efi_selftest(efi_handle_t image_handle,
list_all_tests();
/*
* TODO:
* Once the Exit boottime service is correctly
* Once the Exit st_boottime service is correctly
* implemented we should call
* boottime->exit(image_handle, EFI_SUCCESS, 0, NULL);
* st_boottime->exit(image_handle, EFI_SUCCESS, 0, NULL);
* here, cf.
* https://lists.denx.de/pipermail/u-boot/2017-October/308720.html
*/
@ -300,7 +300,7 @@ efi_status_t EFIAPI efi_selftest(efi_handle_t image_handle,
efi_unit_test));
/* Allocate buffer for setup results */
ret = boottime->allocate_pool(EFI_RUNTIME_SERVICES_DATA, sizeof(int) *
ret = st_boottime->allocate_pool(EFI_RUNTIME_SERVICES_DATA, sizeof(int) *
ll_entry_count(struct efi_unit_test,
efi_unit_test),
(void **)&setup_status);
@ -309,7 +309,7 @@ efi_status_t EFIAPI efi_selftest(efi_handle_t image_handle,
return ret;
}
/* Execute boottime tests */
/* Execute st_boottime tests */
efi_st_do_tests(testname, EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
EFI_ST_SETUP | EFI_ST_EXECUTE | EFI_ST_TEARDOWN,
&failures);

View file

@ -0,0 +1,76 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* efi_selftest_fdt
*
* Copyright (c) 2022 Heinrich Schuchardt <xypron.glpk@gmx.de>
*
* Check the EFI_CONFORMANCE_PROFILE_TABLE
*/
#include <efi_selftest.h>
static const efi_guid_t guid_ecpt = EFI_CONFORMANCE_PROFILES_TABLE_GUID;
static const efi_guid_t guid_ebbr_2_0 = EFI_CONFORMANCE_PROFILE_EBBR_2_0_GUID;
/*
* ecpt_find_guid() - find GUID in EFI Conformance Profile Table
*
* @ecpt: EFI Conformance Profile Table
* @guid: GUID to find
* Return: EFI_ST_SUCCESS for success
*/
static int ecpt_find_guid(struct efi_conformance_profiles_table *ecpt,
const efi_guid_t *guid) {
int i;
for (i = 0; i < ecpt->number_of_profiles; ++i) {
if (!memcmp(&ecpt->conformance_profiles[i], guid, 16))
return EFI_ST_SUCCESS;
}
efi_st_error("GUID %pU not found\n", guid);
return EFI_ST_FAILURE;
}
/*
* Execute unit test.
*
* Return: EFI_ST_SUCCESS for success
*/
static int execute(void)
{
struct efi_conformance_profiles_table *ecpt;
int expected_entries = 0;
ecpt = efi_st_get_config_table(&guid_ecpt);
if (!ecpt) {
efi_st_error("Missing EFI Conformance Profile Table\n");
return EFI_ST_FAILURE;
}
if (ecpt->version != EFI_CONFORMANCE_PROFILES_TABLE_VERSION) {
efi_st_error("Wrong table version\n");
return EFI_ST_FAILURE;
}
if (CONFIG_IS_ENABLED(EFI_EBBR_2_0_CONFORMANCE)) {
++expected_entries;
if (ecpt_find_guid(ecpt, &guid_ebbr_2_0))
return EFI_ST_FAILURE;
}
if (ecpt->number_of_profiles != expected_entries) {
efi_st_error("Expected %d entries, found %d\n",
expected_entries, ecpt->number_of_profiles);
return EFI_ST_FAILURE;
}
return EFI_ST_SUCCESS;
}
EFI_UNIT_TEST(ecpt) = {
.name = "conformance profile table",
.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
.execute = execute,
};

View file

@ -144,23 +144,6 @@ static char *get_property(const u16 *property, const u16 *node)
return NULL;
}
/**
* efi_st_get_config_table() - get configuration table
*
* @guid: GUID of the configuration table
* Return: pointer to configuration table or NULL
*/
static void *efi_st_get_config_table(const efi_guid_t *guid)
{
size_t i;
for (i = 0; i < systab.nr_tables; i++) {
if (!guidcmp(guid, &systemtab->tables[i].guid))
return systemtab->tables[i].table;
}
return NULL;
}
/*
* Setup unit test.
*

View file

@ -110,3 +110,14 @@ int efi_st_strcmp_16_8(const u16 *buf1, const char *buf2)
}
return 0;
}
void *efi_st_get_config_table(const efi_guid_t *guid)
{
size_t i;
for (i = 0; i < st_systable->nr_tables; i++) {
if (!guidcmp(guid, &st_systable->tables[i].guid))
return st_systable->tables[i].table;
}
return NULL;
}