summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2021-02-04 17:35:50 -0500
committerTom Rini <trini@konsulko.com>2021-02-04 17:35:50 -0500
commit55ffabec7f9108060350fae29b932fbd832f8296 (patch)
treeca7399205efb7aeb994def6728c6d79fc10d4ba5
parent21cb717e79e3f6588abae52fe55e2c415850c913 (diff)
parent5489448cd7d46554f7f45a180754be78eff9f54d (diff)
downloadu-boot-WIP/04Feb2021.tar.gz
Merge tag 'efi-2021-04-rc2' of https://gitlab.denx.de/u-boot/custodians/u-boot-efiWIP/04Feb2021
Pull request for UEFI sub-system for efi-2021-04-rc2 Bug fixes: * do not allow creating of files with filenames on FAT file system * install UEFI System Partition GUID on ESP handle * in dtbdump.efi test tool use GUID to find ESP handle Documentation: * man-page for load command * describe end of life of plat_auto
-rw-r--r--cmd/efidebug.c5
-rw-r--r--doc/driver-model/design.rst6
-rw-r--r--doc/usage/exception.rst5
-rw-r--r--doc/usage/index.rst1
-rw-r--r--doc/usage/load.rst74
-rw-r--r--fs/fat/fat_write.c70
-rw-r--r--lib/efi_loader/efi_device_path_to_text.c15
-rw-r--r--lib/efi_loader/efi_disk.c15
-rw-r--r--lib/efi_loader/efi_dt_fixup.c25
-rw-r--r--lib/efi_selftest/dtbdump.c85
10 files changed, 214 insertions, 87 deletions
diff --git a/cmd/efidebug.c b/cmd/efidebug.c
index 83bc2196a5..bbbcb0a546 100644
--- a/cmd/efidebug.c
+++ b/cmd/efidebug.c
@@ -16,6 +16,7 @@
#include <log.h>
#include <malloc.h>
#include <mapmem.h>
+#include <part.h>
#include <search.h>
#include <linux/ctype.h>
@@ -502,6 +503,10 @@ static const struct {
"Device-Tree Fixup",
EFI_DT_FIXUP_PROTOCOL_GUID,
},
+ {
+ "System Partition",
+ PARTITION_SYSTEM_GUID
+ },
/* Configuration table GUIDs */
{
"ACPI table",
diff --git a/doc/driver-model/design.rst b/doc/driver-model/design.rst
index 2417976ab7..4e5cecbab6 100644
--- a/doc/driver-model/design.rst
+++ b/doc/driver-model/design.rst
@@ -725,7 +725,7 @@ The steps are:
2. If plat_auto is non-zero, then the platform data space
is allocated. This is only useful for device tree operation, since
- otherwise you would have to specific the platform data in the
+ otherwise you would have to specify the platform data in the
U_BOOT_DRVINFO() declaration. The space is allocated for the device and
zeroed. It will be accessible as dev->plat.
@@ -861,8 +861,8 @@ remove it. This performs the probe steps in reverse:
be dynamically allocated, and thus needs to be deallocated during the
remove() method, either:
- - if the plat_auto is non-zero, the deallocation
- happens automatically within the driver model core; or
+ - if the plat_auto is non-zero, the deallocation happens automatically
+ within the driver model core in the unbind stage; or
- when plat_auto is 0, both the allocation (in probe()
or preferably of_to_plat()) and the deallocation in remove()
diff --git a/doc/usage/exception.rst b/doc/usage/exception.rst
index 412a03ba0f..db1490f005 100644
--- a/doc/usage/exception.rst
+++ b/doc/usage/exception.rst
@@ -61,8 +61,3 @@ Examples
pc = 0x56076dd1a0f9, pc_reloc = 0x540f9
resetting ...
-
-Return value
-------------
-
-The return value $? is always set to 0 (true).
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 83cfbafd90..5754958d7e 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -23,6 +23,7 @@ Shell commands
exit
false
for
+ load
loady
mbr
pstore
diff --git a/doc/usage/load.rst b/doc/usage/load.rst
new file mode 100644
index 0000000000..1efee77317
--- /dev/null
+++ b/doc/usage/load.rst
@@ -0,0 +1,74 @@
+.. SPDX-License-Identifier: GPL-2.0+:
+
+load command
+============
+
+Synopsis
+--------
+
+::
+
+ load <interface> [<dev[:part]> [<addr> [<filename> [bytes [pos]]]]]
+
+Description
+-----------
+
+The load command is used to read a file from a filesystem into memory.
+
+The number of transferred bytes is saved in the environment variable filesize.
+The load address is saved in the environment variable fileaddr.
+
+interface
+ interface for accessing the block device (mmc, sata, scsi, usb, ....)
+
+dev
+ device number
+
+part
+ partition number, defaults to 0 (whole device)
+
+addr
+ load address, defaults to environment variable loadaddr or if loadaddr is
+ not set to configuration variable CONFIG_SYS_LOAD_ADDR
+
+filename
+ path to file, defaults to environment variable bootfile
+
+bytes
+ maximum number of bytes to load
+
+pos
+ number of bytes to skip
+
+addr, bytes, pos are hexadecimal numbers.
+
+Example
+-------
+
+::
+
+ => load mmc 0:1 ${kernel_addr_r} snp.efi
+ 149280 bytes read in 11 ms (12.9 MiB/s)
+ =>
+ => load mmc 0:1 ${kernel_addr_r} snp.efi 1000000
+ 149280 bytes read in 9 ms (15.8 MiB/s)
+ =>
+ => load mmc 0:1 ${kernel_addr_r} snp.efi 1000000 100
+ 149024 bytes read in 10 ms (14.2 MiB/s)
+ =>
+ => load mmc 0:1 ${kernel_addr_r} snp.efi 10
+ 16 bytes read in 1 ms (15.6 KiB/s)
+ =>
+
+Configuration
+-------------
+
+The load command is only available if CONFIG_CMD_FS_GENERIC=y.
+
+Return value
+------------
+
+The return value $? is set to 0 (true) if the file was successfully loaded
+even if the number of bytes is less then the specified length.
+
+If an error occurs, the return value $? is set to 1 (false).
diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c
index b43a27b205..8ff2f6def0 100644
--- a/fs/fat/fat_write.c
+++ b/fs/fat/fat_write.c
@@ -1237,12 +1237,38 @@ again:
}
*last_slash_cont = '\0';
- *basename = last_slash_cont + 1;
+ filename = last_slash_cont + 1;
} else {
*dirname = "/"; /* root by default */
- *basename = filename;
}
+ /*
+ * The FAT32 File System Specification v1.03 requires leading and
+ * trailing spaces as well as trailing periods to be ignored.
+ */
+ for (; *filename == ' '; ++filename)
+ ;
+
+ /* Keep special entries '.' and '..' */
+ if (filename[0] == '.' &&
+ (!filename[1] || (filename[1] == '.' && !filename[2])))
+ goto done;
+
+ /* Remove trailing periods and spaces */
+ for (p = filename + strlen(filename) - 1; p >= filename; --p) {
+ switch (*p) {
+ case ' ':
+ case '.':
+ *p = 0;
+ break;
+ default:
+ goto done;
+ }
+ }
+
+done:
+ *basename = filename;
+
return 0;
}
@@ -1259,8 +1285,10 @@ again:
static int normalize_longname(char *l_filename, const char *filename)
{
const char *p, illegal[] = "<>:\"/\\|?*";
+ size_t len;
- if (strlen(filename) >= VFAT_MAXLEN_BYTES)
+ len = strlen(filename);
+ if (!len || len >= VFAT_MAXLEN_BYTES || filename[len - 1] == '.')
return -1;
for (p = filename; *p; ++p) {
@@ -1299,9 +1327,8 @@ int file_fat_write_at(const char *filename, loff_t pos, void *buffer,
goto exit;
}
- filename = basename;
- if (normalize_longname(l_filename, filename)) {
- printf("FAT: illegal filename (%s)\n", filename);
+ if (normalize_longname(l_filename, basename)) {
+ printf("FAT: illegal filename (%s)\n", basename);
ret = -EINVAL;
goto exit;
}
@@ -1349,15 +1376,6 @@ int file_fat_write_at(const char *filename, loff_t pos, void *buffer,
char shortname[SHORT_NAME_SIZE];
int ndent;
- if (itr->is_root) {
- /* root dir cannot have "." or ".." */
- if (!strcmp(l_filename, ".") ||
- !strcmp(l_filename, "..")) {
- ret = -EINVAL;
- goto exit;
- }
- }
-
if (pos) {
/* No hole allowed */
ret = -EINVAL;
@@ -1365,7 +1383,7 @@ int file_fat_write_at(const char *filename, loff_t pos, void *buffer,
}
/* Check if long name is needed */
- ndent = set_name(itr, filename, shortname);
+ ndent = set_name(itr, basename, shortname);
if (ndent < 0) {
ret = ndent;
goto exit;
@@ -1375,7 +1393,7 @@ int file_fat_write_at(const char *filename, loff_t pos, void *buffer,
goto exit;
if (ndent > 1) {
/* Set long name entries */
- ret = fill_dir_slot(itr, filename, shortname);
+ ret = fill_dir_slot(itr, basename, shortname);
if (ret)
goto exit;
}
@@ -1611,31 +1629,31 @@ exit:
return ret;
}
-int fat_mkdir(const char *new_dirname)
+int fat_mkdir(const char *dirname)
{
dir_entry *retdent;
fsdata datablock = { .fatbuf = NULL, };
fsdata *mydata = &datablock;
fat_itr *itr = NULL;
- char *dirname_copy, *parent, *dirname;
+ char *dirname_copy, *parent, *basename;
char l_dirname[VFAT_MAXLEN_BYTES];
int ret = -1;
loff_t actwrite;
unsigned int bytesperclust;
dir_entry *dotdent = NULL;
- dirname_copy = strdup(new_dirname);
+ dirname_copy = strdup(dirname);
if (!dirname_copy)
goto exit;
- split_filename(dirname_copy, &parent, &dirname);
- if (!strlen(dirname)) {
+ split_filename(dirname_copy, &parent, &basename);
+ if (!strlen(basename)) {
ret = -EINVAL;
goto exit;
}
- if (normalize_longname(l_dirname, dirname)) {
- printf("FAT: illegal filename (%s)\n", dirname);
+ if (normalize_longname(l_dirname, basename)) {
+ printf("FAT: illegal filename (%s)\n", basename);
ret = -EINVAL;
goto exit;
}
@@ -1678,7 +1696,7 @@ int fat_mkdir(const char *new_dirname)
}
/* Check if long name is needed */
- ndent = set_name(itr, dirname, shortname);
+ ndent = set_name(itr, basename, shortname);
if (ndent < 0) {
ret = ndent;
goto exit;
@@ -1688,7 +1706,7 @@ int fat_mkdir(const char *new_dirname)
goto exit;
if (ndent > 1) {
/* Set long name entries */
- ret = fill_dir_slot(itr, dirname, shortname);
+ ret = fill_dir_slot(itr, basename, shortname);
if (ret)
goto exit;
}
diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c
index 5ae4833fa7..1aaa9f94fa 100644
--- a/lib/efi_loader/efi_device_path_to_text.c
+++ b/lib/efi_loader/efi_device_path_to_text.c
@@ -244,6 +244,21 @@ static char *dp_media(char *s, struct efi_device_path *dp)
cddp->partition_start, cddp->partition_size);
break;
}
+ case DEVICE_PATH_SUB_TYPE_VENDOR_PATH: {
+ int i, n;
+ struct efi_device_path_vendor *vdp =
+ (struct efi_device_path_vendor *)dp;
+
+ s += sprintf(s, "VenMedia(%pUl", &vdp->guid);
+ n = (int)vdp->dp.length - sizeof(struct efi_device_path_vendor);
+ if (n > 0) {
+ s += sprintf(s, ",");
+ for (i = 0; i < n; ++i)
+ s += sprintf(s, "%02x", vdp->vendor_data[i]);
+ }
+ s += sprintf(s, ")");
+ break;
+ }
case DEVICE_PATH_SUB_TYPE_FILE_PATH: {
struct efi_device_path_file_path *fp =
(struct efi_device_path_file_path *)dp;
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index d0aad0252a..1f6b817dea 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -19,6 +19,7 @@
struct efi_system_partition efi_system_partition;
const efi_guid_t efi_block_io_guid = EFI_BLOCK_IO_PROTOCOL_GUID;
+const efi_guid_t efi_system_partition_guid = PARTITION_SYSTEM_GUID;
/**
* struct efi_disk_obj - EFI disk object
@@ -362,6 +363,7 @@ static efi_status_t efi_disk_add_dev(
{
struct efi_disk_obj *diskobj;
struct efi_object *handle;
+ const efi_guid_t *guid = NULL;
efi_status_t ret;
/* Don't add empty devices */
@@ -400,6 +402,8 @@ static efi_status_t efi_disk_add_dev(
efi_free_pool(node);
diskobj->offset = part_info->start;
diskobj->media.last_block = part_info->size - 1;
+ if (part_info->bootable & PART_EFI_SYSTEM_PARTITION)
+ guid = &efi_system_partition_guid;
} else {
diskobj->dp = efi_dp_from_part(desc, part);
diskobj->offset = 0;
@@ -417,7 +421,8 @@ static efi_status_t efi_disk_add_dev(
handle = &diskobj->header;
ret = EFI_CALL(efi_install_multiple_protocol_interfaces(
&handle, &efi_guid_device_path, diskobj->dp,
- &efi_block_io_guid, &diskobj->ops, NULL));
+ &efi_block_io_guid, &diskobj->ops,
+ guid, NULL, NULL));
if (ret != EFI_SUCCESS)
return ret;
@@ -467,13 +472,7 @@ static efi_status_t efi_disk_add_dev(
/* Store first EFI system partition */
if (part && !efi_system_partition.if_type) {
- int r;
- struct disk_partition info;
-
- r = part_get_info(desc, part, &info);
- if (r)
- return EFI_DEVICE_ERROR;
- if (info.bootable & PART_EFI_SYSTEM_PARTITION) {
+ if (part_info->bootable & PART_EFI_SYSTEM_PARTITION) {
efi_system_partition.if_type = desc->if_type;
efi_system_partition.devnum = desc->devnum;
efi_system_partition.part = part;
diff --git a/lib/efi_loader/efi_dt_fixup.c b/lib/efi_loader/efi_dt_fixup.c
index 3850ab3b0f..6de57b84d2 100644
--- a/lib/efi_loader/efi_dt_fixup.c
+++ b/lib/efi_loader/efi_dt_fixup.c
@@ -110,6 +110,7 @@ efi_dt_fixup(struct efi_dt_fixup_protocol *this, void *dtb,
{
efi_status_t ret;
size_t required_size;
+ size_t total_size;
bootm_headers_t img = { 0 };
EFI_ENTRY("%p, %p, %p, %d", this, dtb, buffer_size, flags);
@@ -124,20 +125,20 @@ efi_dt_fixup(struct efi_dt_fixup_protocol *this, void *dtb,
goto out;
}
if (flags & EFI_DT_APPLY_FIXUPS) {
+ /* Check size */
required_size = fdt_off_dt_strings(dtb) +
fdt_size_dt_strings(dtb) +
0x3000;
- } else {
- required_size = fdt_totalsize(dtb);
- }
- if (required_size > *buffer_size) {
- *buffer_size = required_size;
- ret = EFI_BUFFER_TOO_SMALL;
- goto out;
- }
- fdt_set_totalsize(dtb, *buffer_size);
+ total_size = fdt_totalsize(dtb);
+ if (required_size < total_size)
+ required_size = total_size;
+ if (required_size > *buffer_size) {
+ *buffer_size = required_size;
+ ret = EFI_BUFFER_TOO_SMALL;
+ goto out;
+ }
- if (flags & EFI_DT_APPLY_FIXUPS) {
+ fdt_set_totalsize(dtb, *buffer_size);
if (image_setup_libfdt(&img, dtb, 0, NULL)) {
log_err("failed to process device tree\n");
ret = EFI_INVALID_PARAMETER;
@@ -147,10 +148,10 @@ efi_dt_fixup(struct efi_dt_fixup_protocol *this, void *dtb,
if (flags & EFI_DT_RESERVE_MEMORY)
efi_carve_out_dt_rsv(dtb);
- if (EFI_DT_INSTALL_TABLE) {
+ if (flags & EFI_DT_INSTALL_TABLE) {
ret = efi_install_configuration_table(&efi_guid_fdt, dtb);
if (ret != EFI_SUCCESS) {
- log_err("ERROR: failed to install device tree\n");
+ log_err("failed to install device tree\n");
goto out;
}
}
diff --git a/lib/efi_selftest/dtbdump.c b/lib/efi_selftest/dtbdump.c
index 953b264d9d..38ab9f8bf0 100644
--- a/lib/efi_selftest/dtbdump.c
+++ b/lib/efi_selftest/dtbdump.c
@@ -9,6 +9,7 @@
#include <common.h>
#include <efi_api.h>
#include <efi_dt_fixup.h>
+#include <part.h>
#define BUFFER_SIZE 64
#define ESC 0x17
@@ -27,6 +28,7 @@ static efi_handle_t handle;
static struct efi_system_table *systable;
static const efi_guid_t efi_dt_fixup_protocol_guid = EFI_DT_FIXUP_PROTOCOL_GUID;
static const efi_guid_t efi_file_info_guid = EFI_FILE_INFO_GUID;
+static const efi_guid_t efi_system_partition_guid = PARTITION_SYSTEM_GUID;
/**
* print() - print string
@@ -231,6 +233,52 @@ void do_help(void)
}
/**
+ * open_file_system() - open simple file system protocol
+ *
+ * file_system: interface of the simple file system protocol
+ * Return: status code
+ */
+static efi_status_t
+open_file_system(struct efi_simple_file_system_protocol **file_system)
+{
+ struct efi_loaded_image *loaded_image;
+ efi_status_t ret;
+ efi_handle_t *handle_buffer = NULL;
+ efi_uintn_t count;
+
+ ret = bs->open_protocol(handle, &loaded_image_guid,
+ (void **)&loaded_image, NULL, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (ret != EFI_SUCCESS) {
+ error(L"Loaded image protocol not found\r\n");
+ return ret;
+ }
+
+ /* Open the simple file system protocol on the same partition */
+ ret = bs->open_protocol(loaded_image->device_handle,
+ &guid_simple_file_system_protocol,
+ (void **)file_system, NULL, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (ret == EFI_SUCCESS)
+ return ret;
+
+ /* Open the simple file system protocol on the UEFI system partition */
+ ret = bs->locate_handle_buffer(BY_PROTOCOL, &efi_system_partition_guid,
+ NULL, &count, &handle_buffer);
+ if (ret == EFI_SUCCESS && handle_buffer)
+ ret = bs->open_protocol(handle_buffer[0],
+ &guid_simple_file_system_protocol,
+ (void **)file_system, NULL, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (ret != EFI_SUCCESS)
+ error(L"Failed to open simple file system protocol\r\n");
+ if (handle)
+ bs->free_pool(handle_buffer);
+
+ return ret;
+}
+
+/**
* do_load() - load and install device-tree
*
* @filename: file name
@@ -239,7 +287,6 @@ void do_help(void)
efi_status_t do_load(u16 *filename)
{
struct efi_dt_fixup_protocol *dt_fixup_prot;
- struct efi_loaded_image *loaded_image;
struct efi_simple_file_system_protocol *file_system;
struct efi_file_handle *root = NULL, *file = NULL;
u64 addr = 0;
@@ -258,22 +305,9 @@ efi_status_t do_load(u16 *filename)
filename = skip_whitespace(filename);
- ret = bs->open_protocol(handle, &loaded_image_guid,
- (void **)&loaded_image, NULL, NULL,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL);
- if (ret != EFI_SUCCESS) {
- error(L"Loaded image protocol not found\r\n");
- return ret;
- }
- /* Open the simple file system protocol */
- ret = bs->open_protocol(loaded_image->device_handle,
- &guid_simple_file_system_protocol,
- (void **)&file_system, NULL, NULL,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL);
- if (ret != EFI_SUCCESS) {
- error(L"Failed to open simple file system protocol\r\n");
+ ret = open_file_system(&file_system);
+ if (ret != EFI_SUCCESS)
goto out;
- }
/* Open volume */
ret = file_system->open_volume(file_system, &root);
@@ -389,7 +423,6 @@ out:
*/
efi_status_t do_save(u16 *filename)
{
- struct efi_loaded_image *loaded_image;
struct efi_simple_file_system_protocol *file_system;
efi_uintn_t dtb_size;
struct efi_file_handle *root, *file;
@@ -409,23 +442,9 @@ efi_status_t do_save(u16 *filename)
filename = skip_whitespace(filename);
- ret = bs->open_protocol(handle, &loaded_image_guid,
- (void **)&loaded_image, NULL, NULL,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL);
- if (ret != EFI_SUCCESS) {
- error(L"Loaded image protocol not found\r\n");
- return ret;
- }
-
- /* Open the simple file system protocol */
- ret = bs->open_protocol(loaded_image->device_handle,
- &guid_simple_file_system_protocol,
- (void **)&file_system, NULL, NULL,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL);
- if (ret != EFI_SUCCESS) {
- error(L"Failed to open simple file system protocol\r\n");
+ ret = open_file_system(&file_system);
+ if (ret != EFI_SUCCESS)
return ret;
- }
/* Open volume */
ret = file_system->open_volume(file_system, &root);