Pull request for efi-2022-07-rc1-3
Documentation: * Document image size parameter of bootefi command UEFI: * avoid building partition support in SPL/TPL where not required * improve integration of EFI subsystem and driver model * restore ability to boot arbitrary blob -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEbcT5xx8ppvoGt20zxIHbvCwFGsQFAmJka8UACgkQxIHbvCwF GsQXVw/+OuG4lYgiBZUUOFtu7CZZTrEnMGszRhXmwEzTMNq2NBNRP1lRJFhyyU50 ElS/I7wZwhFtEnsL5H4mf3Ww7BQLELecg/Q7bnDYhPNg4JWUWUSCGOVUkNRs5O1h 3f6HBkdbvDVvITgopqEj1v4sNwSJCr8sFJQPe0o7i9FAb0+dbO/Er3Z6afp9vcsQ C6iiNq4zTaGm0YUZf1wOCJMngijvkJ+z+McAFCCAwH0zbT7GfNpmGNr8iviYPWJM tKzkvO73+LhGR6fgRl9XewbV0Mlkd2q54nfZrP+7tTycIrj0G/OUOyPnOUaJk485 keouzcIVSzZGjeQtsZ9Rrw8EounuMJ/pRyGNsoWIyeY98gqJxtVYnrlNm/TvFs6F vALsqq0LsRkVmM/ut8eleV/U8Q6n6IYL4xtAH0tm4Jf4mrW1zt8IgWQnNOlHqg9J RjOAF0y38KUAoC7RzGjU+RJcWPoYuKGxEWEdGvIu3qP9blwaZ7UKRxqWilOgbypf pxbp9YsnT8pqY9cs6mzSZHPjJFSMVocaRzD521kgShS4cxOJHpZHU4wzd5hS4BFr BIMCSPPyuRmn3E2DDqncEtL4C7OoPV+LLXVyrF2neiWwjMd/4rGAoYnDwjRkD7dP uSFsNt9N3Mqpjwl/iMI5Kd+mOJ77TWnf9fKrEft4BIXexopzAms= =a5qc -----END PGP SIGNATURE----- Merge tag 'efi-2022-07-rc1-3' of https://source.denx.de/u-boot/custodians/u-boot-efi Pull request for efi-2022-07-rc1-3 Documentation: * Document image size parameter of bootefi command UEFI: * avoid building partition support in SPL/TPL where not required * improve integration of EFI subsystem and driver model * restore ability to boot arbitrary blob
This commit is contained in:
commit
46a06ed82a
@ -422,10 +422,11 @@ static int do_efibootmgr(void)
|
||||
* Set up memory image for the binary to be loaded, prepare device path, and
|
||||
* then call do_bootefi_exec() to execute it.
|
||||
*
|
||||
* @image_opt: string of image start address
|
||||
* @image_opt: string with image start address
|
||||
* @size_opt: string with image size or NULL
|
||||
* Return: status code
|
||||
*/
|
||||
static int do_bootefi_image(const char *image_opt)
|
||||
static int do_bootefi_image(const char *image_opt, const char *size_opt)
|
||||
{
|
||||
void *image_buf;
|
||||
unsigned long addr, size;
|
||||
@ -443,14 +444,21 @@ static int do_bootefi_image(const char *image_opt)
|
||||
/* Check that a numeric value was passed */
|
||||
if (!addr)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
image_buf = map_sysmem(addr, 0);
|
||||
|
||||
if (image_buf != image_addr) {
|
||||
log_err("No UEFI binary known at %s\n", image_opt);
|
||||
return CMD_RET_FAILURE;
|
||||
if (size_opt) {
|
||||
size = strtoul(size_opt, NULL, 16);
|
||||
if (!size)
|
||||
return CMD_RET_USAGE;
|
||||
efi_clear_bootdev();
|
||||
} else {
|
||||
if (image_buf != image_addr) {
|
||||
log_err("No UEFI binary known at %s\n",
|
||||
image_opt);
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
size = image_size;
|
||||
}
|
||||
size = image_size;
|
||||
}
|
||||
ret = efi_run_image(image_buf, size);
|
||||
|
||||
@ -654,7 +662,7 @@ static int do_bootefi(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
|
||||
if (argc > 2) {
|
||||
if (argc > 2 && strcmp(argv[2], "-")) {
|
||||
uintptr_t fdt_addr;
|
||||
|
||||
fdt_addr = hextoul(argv[2], NULL);
|
||||
@ -677,15 +685,15 @@ static int do_bootefi(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||
return do_efi_selftest();
|
||||
#endif
|
||||
|
||||
return do_bootefi_image(argv[1]);
|
||||
return do_bootefi_image(argv[1], argc > 3 ? argv[3] : NULL);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYS_LONGHELP
|
||||
static char bootefi_help_text[] =
|
||||
"<image address> [fdt address]\n"
|
||||
" - boot EFI payload stored at address <image address>.\n"
|
||||
" If specified, the device tree located at <fdt address> gets\n"
|
||||
" exposed as EFI configuration table.\n"
|
||||
"<image address> [fdt address [image size]]\n"
|
||||
" - boot EFI payload stored at <image address>\n"
|
||||
" fdt address, address of device-tree or '-'\n"
|
||||
" image size, required if image not preloaded\n"
|
||||
#ifdef CONFIG_CMD_BOOTEFI_HELLO
|
||||
"bootefi hello\n"
|
||||
" - boot a sample Hello World application stored within U-Boot\n"
|
||||
@ -707,7 +715,7 @@ static char bootefi_help_text[] =
|
||||
#endif
|
||||
|
||||
U_BOOT_CMD(
|
||||
bootefi, 3, 0, do_bootefi,
|
||||
bootefi, 4, 0, do_bootefi,
|
||||
"Boots an EFI payload from memory",
|
||||
bootefi_help_text
|
||||
);
|
||||
|
@ -463,7 +463,7 @@ static void bootmenu_show(int delay)
|
||||
}
|
||||
|
||||
for (iter = bootmenu->first; iter; iter = iter->next) {
|
||||
if (!menu_item_add(menu, iter->key, iter))
|
||||
if (menu_item_add(menu, iter->key, iter) != 1)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -476,7 +476,7 @@ static void bootmenu_show(int delay)
|
||||
|
||||
init = 1;
|
||||
|
||||
if (menu_get_choice(menu, &choice)) {
|
||||
if (menu_get_choice(menu, &choice) == 1) {
|
||||
iter = choice;
|
||||
title = strdup(iter->title);
|
||||
command = strdup(iter->command);
|
||||
|
@ -795,7 +795,7 @@ static init_fnc_t init_sequence_r[] = {
|
||||
initr_mem,
|
||||
#endif
|
||||
#ifdef CONFIG_EFI_SETUP_EARLY
|
||||
(init_fnc_t)efi_init_obj_list,
|
||||
efi_init_early,
|
||||
#endif
|
||||
run_main_loop,
|
||||
};
|
||||
|
@ -54,8 +54,11 @@ void main_loop(void)
|
||||
if (IS_ENABLED(CONFIG_UPDATE_TFTP))
|
||||
update_tftp(0UL, NULL, NULL);
|
||||
|
||||
if (IS_ENABLED(CONFIG_EFI_CAPSULE_ON_DISK_EARLY))
|
||||
efi_launch_capsules();
|
||||
if (IS_ENABLED(CONFIG_EFI_CAPSULE_ON_DISK_EARLY)) {
|
||||
/* efi_init_early() already called */
|
||||
if (efi_init_obj_list() == EFI_SUCCESS)
|
||||
efi_launch_capsules();
|
||||
}
|
||||
|
||||
s = bootdelay_process();
|
||||
if (cli_process_fdt(&s))
|
||||
|
37
disk/Kconfig
37
disk/Kconfig
@ -2,8 +2,7 @@
|
||||
menu "Partition Types"
|
||||
|
||||
config PARTITIONS
|
||||
bool "Enable Partition Labels (disklabels) support"
|
||||
default y
|
||||
bool
|
||||
help
|
||||
Partition Labels (disklabels) Supported:
|
||||
Zero or more of the following:
|
||||
@ -20,8 +19,7 @@ config PARTITIONS
|
||||
as well.
|
||||
|
||||
config SPL_PARTITIONS
|
||||
bool "Enable Partition Labels (disklabels) support in SPL"
|
||||
default y if PARTITIONS
|
||||
bool
|
||||
select SPL_SPRINTF
|
||||
select SPL_STRTO
|
||||
help
|
||||
@ -30,8 +28,7 @@ config SPL_PARTITIONS
|
||||
small amount of size to SPL, typically 500 bytes.
|
||||
|
||||
config TPL_PARTITIONS
|
||||
bool "Enable Partition Labels (disklabels) support in TPL"
|
||||
default y if PARTITIONS
|
||||
bool
|
||||
select TPL_SPRINTF
|
||||
select TPL_STRTO
|
||||
help
|
||||
@ -41,57 +38,61 @@ config TPL_PARTITIONS
|
||||
|
||||
config MAC_PARTITION
|
||||
bool "Enable Apple's MacOS partition table"
|
||||
depends on PARTITIONS
|
||||
select PARTITIONS
|
||||
help
|
||||
Say Y here if you would like to use device under U-Boot which
|
||||
were partitioned on a Macintosh.
|
||||
|
||||
config SPL_MAC_PARTITION
|
||||
bool "Enable Apple's MacOS partition table for SPL"
|
||||
depends on SPL && PARTITIONS
|
||||
depends on SPL
|
||||
default y if MAC_PARTITION
|
||||
select SPL_PARTITIONS
|
||||
|
||||
config DOS_PARTITION
|
||||
bool "Enable MS Dos partition table"
|
||||
depends on PARTITIONS
|
||||
default y if DISTRO_DEFAULTS
|
||||
default y if x86 || CMD_FAT || USB_STORAGE
|
||||
select PARTITIONS
|
||||
help
|
||||
traditional on the Intel architecture, USB sticks, etc.
|
||||
|
||||
config SPL_DOS_PARTITION
|
||||
bool "Enable MS Dos partition table for SPL"
|
||||
depends on SPL && PARTITIONS
|
||||
depends on SPL
|
||||
default n if ARCH_SUNXI
|
||||
default y if DOS_PARTITION
|
||||
select SPL_PARTITIONS
|
||||
|
||||
config ISO_PARTITION
|
||||
bool "Enable ISO partition table"
|
||||
depends on PARTITIONS
|
||||
default y if DISTRO_DEFAULTS
|
||||
default y if MIPS || ARCH_TEGRA
|
||||
select PARTITIONS
|
||||
|
||||
config SPL_ISO_PARTITION
|
||||
bool "Enable ISO partition table for SPL"
|
||||
depends on SPL && PARTITIONS
|
||||
depends on SPL
|
||||
select SPL_PARTITIONS
|
||||
|
||||
config AMIGA_PARTITION
|
||||
bool "Enable AMIGA partition table"
|
||||
depends on PARTITIONS
|
||||
select PARTITIONS
|
||||
help
|
||||
Say Y here if you would like to use device under U-Boot which
|
||||
were partitioned under AmigaOS.
|
||||
|
||||
config SPL_AMIGA_PARTITION
|
||||
bool "Enable AMIGA partition table for SPL"
|
||||
depends on SPL && PARTITIONS
|
||||
depends on SPL
|
||||
default y if AMIGA_PARTITION
|
||||
select SPL_PARTITIONS
|
||||
|
||||
config EFI_PARTITION
|
||||
bool "Enable EFI GPT partition table"
|
||||
depends on PARTITIONS
|
||||
default y if DISTRO_DEFAULTS
|
||||
default y if ARCH_TEGRA
|
||||
select PARTITIONS
|
||||
select LIB_UUID
|
||||
help
|
||||
Say Y here if you would like to use device under U-Boot which
|
||||
@ -128,9 +129,10 @@ config EFI_PARTITION_ENTRIES_OFF
|
||||
|
||||
config SPL_EFI_PARTITION
|
||||
bool "Enable EFI GPT partition table for SPL"
|
||||
depends on SPL && PARTITIONS
|
||||
depends on SPL
|
||||
default n if ARCH_SUNXI
|
||||
default y if EFI_PARTITION
|
||||
select SPL_PARTITIONS
|
||||
|
||||
config PARTITION_UUIDS
|
||||
bool "Enable support of UUID for partition"
|
||||
@ -143,12 +145,11 @@ config PARTITION_UUIDS
|
||||
|
||||
config SPL_PARTITION_UUIDS
|
||||
bool "Enable support of UUID for partition in SPL"
|
||||
depends on SPL && PARTITIONS
|
||||
depends on SPL_PARTITIONS
|
||||
default y if SPL_EFI_PARTITION
|
||||
|
||||
config PARTITION_TYPE_GUID
|
||||
bool "Enable support of GUID for partition type"
|
||||
depends on PARTITIONS
|
||||
depends on EFI_PARTITION
|
||||
help
|
||||
Activate the configuration of GUID type
|
||||
|
@ -6,6 +6,9 @@
|
||||
#ccflags-y += -DET_DEBUG -DDEBUG
|
||||
|
||||
obj-$(CONFIG_$(SPL_TPL_)PARTITIONS) += part.o
|
||||
ifdef CONFIG_$(SPL_TPL_)BLK
|
||||
obj-$(CONFIG_$(SPL_TPL_)PARTITIONS) += disk-uclass.o
|
||||
endif
|
||||
obj-$(CONFIG_$(SPL_TPL_)MAC_PARTITION) += part_mac.o
|
||||
obj-$(CONFIG_$(SPL_TPL_)DOS_PARTITION) += part_dos.o
|
||||
obj-$(CONFIG_$(SPL_TPL_)ISO_PARTITION) += part_iso.o
|
||||
|
247
disk/disk-uclass.c
Normal file
247
disk/disk-uclass.c
Normal file
@ -0,0 +1,247 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Software partition device (UCLASS_PARTITION)
|
||||
*
|
||||
* Copyright (c) 2021 Linaro Limited
|
||||
* Author: AKASHI Takahiro
|
||||
*/
|
||||
|
||||
#define LOG_CATEGORY UCLASS_PARTITION
|
||||
|
||||
#include <blk.h>
|
||||
#include <dm.h>
|
||||
#include <log.h>
|
||||
#include <part.h>
|
||||
#include <vsprintf.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include <dm/lists.h>
|
||||
|
||||
int part_create_block_devices(struct udevice *blk_dev)
|
||||
{
|
||||
int part, count;
|
||||
struct blk_desc *desc = dev_get_uclass_plat(blk_dev);
|
||||
struct disk_partition info;
|
||||
struct disk_part *part_data;
|
||||
char devname[32];
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
|
||||
if (!CONFIG_IS_ENABLED(PARTITIONS) ||
|
||||
!CONFIG_IS_ENABLED(HAVE_BLOCK_DEVICE))
|
||||
return 0;
|
||||
|
||||
if (device_get_uclass_id(blk_dev) != UCLASS_BLK)
|
||||
return 0;
|
||||
|
||||
/* Add devices for each partition */
|
||||
for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) {
|
||||
if (part_get_info(desc, part, &info))
|
||||
continue;
|
||||
snprintf(devname, sizeof(devname), "%s:%d", blk_dev->name,
|
||||
part);
|
||||
|
||||
ret = device_bind_driver(blk_dev, "blk_partition",
|
||||
strdup(devname), &dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
part_data = dev_get_uclass_plat(dev);
|
||||
part_data->partnum = part;
|
||||
part_data->gpt_part_info = info;
|
||||
count++;
|
||||
|
||||
ret = device_probe(dev);
|
||||
if (ret) {
|
||||
debug("Can't probe\n");
|
||||
count--;
|
||||
device_unbind(dev);
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
debug("%s: %d partitions found in %s\n", __func__, count,
|
||||
blk_dev->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ulong blk_part_read(struct udevice *dev, lbaint_t start,
|
||||
lbaint_t blkcnt, void *buffer)
|
||||
{
|
||||
struct udevice *parent;
|
||||
struct disk_part *part;
|
||||
const struct blk_ops *ops;
|
||||
|
||||
parent = dev_get_parent(dev);
|
||||
ops = blk_get_ops(parent);
|
||||
if (!ops->read)
|
||||
return -ENOSYS;
|
||||
|
||||
part = dev_get_uclass_plat(dev);
|
||||
if (start >= part->gpt_part_info.size)
|
||||
return 0;
|
||||
|
||||
if ((start + blkcnt) > part->gpt_part_info.size)
|
||||
blkcnt = part->gpt_part_info.size - start;
|
||||
start += part->gpt_part_info.start;
|
||||
|
||||
return ops->read(parent, start, blkcnt, buffer);
|
||||
}
|
||||
|
||||
static ulong blk_part_write(struct udevice *dev, lbaint_t start,
|
||||
lbaint_t blkcnt, const void *buffer)
|
||||
{
|
||||
struct udevice *parent;
|
||||
struct disk_part *part;
|
||||
const struct blk_ops *ops;
|
||||
|
||||
parent = dev_get_parent(dev);
|
||||
ops = blk_get_ops(parent);
|
||||
if (!ops->write)
|
||||
return -ENOSYS;
|
||||
|
||||
part = dev_get_uclass_plat(dev);
|
||||
if (start >= part->gpt_part_info.size)
|
||||
return 0;
|
||||
|
||||
if ((start + blkcnt) > part->gpt_part_info.size)
|
||||
blkcnt = part->gpt_part_info.size - start;
|
||||
start += part->gpt_part_info.start;
|
||||
|
||||
return ops->write(parent, start, blkcnt, buffer);
|
||||
}
|
||||
|
||||
static ulong blk_part_erase(struct udevice *dev, lbaint_t start,
|
||||
lbaint_t blkcnt)
|
||||
{
|
||||
struct udevice *parent;
|
||||
struct disk_part *part;
|
||||
const struct blk_ops *ops;
|
||||
|
||||
parent = dev_get_parent(dev);
|
||||
ops = blk_get_ops(parent);
|
||||
if (!ops->erase)
|
||||
return -ENOSYS;
|
||||
|
||||
part = dev_get_uclass_plat(dev);
|
||||
if (start >= part->gpt_part_info.size)
|
||||
return 0;
|
||||
|
||||
if ((start + blkcnt) > part->gpt_part_info.size)
|
||||
blkcnt = part->gpt_part_info.size - start;
|
||||
start += part->gpt_part_info.start;
|
||||
|
||||
return ops->erase(parent, start, blkcnt);
|
||||
}
|
||||
|
||||
static const struct blk_ops blk_part_ops = {
|
||||
.read = blk_part_read,
|
||||
.write = blk_part_write,
|
||||
.erase = blk_part_erase,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(blk_partition) = {
|
||||
.name = "blk_partition",
|
||||
.id = UCLASS_PARTITION,
|
||||
.ops = &blk_part_ops,
|
||||
};
|
||||
|
||||
/*
|
||||
* BLOCK IO APIs
|
||||
*/
|
||||
static struct blk_desc *dev_get_blk(struct udevice *dev)
|
||||
{
|
||||
struct blk_desc *block_dev;
|
||||
|
||||
switch (device_get_uclass_id(dev)) {
|
||||
/*
|
||||
* We won't support UCLASS_BLK with dev_* interfaces.
|
||||
*/
|
||||
case UCLASS_PARTITION:
|
||||
block_dev = dev_get_uclass_plat(dev_get_parent(dev));
|
||||
break;
|
||||
default:
|
||||
block_dev = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return block_dev;
|
||||
}
|
||||
|
||||
unsigned long dev_read(struct udevice *dev, lbaint_t start,
|
||||
lbaint_t blkcnt, void *buffer)
|
||||
{
|
||||
struct blk_desc *block_dev;
|
||||
const struct blk_ops *ops;
|
||||
struct disk_part *part;
|
||||
lbaint_t start_in_disk;
|
||||
ulong blks_read;
|
||||
|
||||
block_dev = dev_get_blk(dev);
|
||||
if (!block_dev)
|
||||
return -ENOSYS;
|
||||
|
||||
ops = blk_get_ops(dev);
|
||||
if (!ops->read)
|
||||
return -ENOSYS;
|
||||
|
||||
start_in_disk = start;
|
||||
if (device_get_uclass_id(dev) == UCLASS_PARTITION) {
|
||||
part = dev_get_uclass_plat(dev);
|
||||
start_in_disk += part->gpt_part_info.start;
|
||||
}
|
||||
|
||||
if (blkcache_read(block_dev->if_type, block_dev->devnum,
|
||||
start_in_disk, blkcnt, block_dev->blksz, buffer))
|
||||
return blkcnt;
|
||||
blks_read = ops->read(dev, start, blkcnt, buffer);
|
||||
if (blks_read == blkcnt)
|
||||
blkcache_fill(block_dev->if_type, block_dev->devnum,
|
||||
start_in_disk, blkcnt, block_dev->blksz, buffer);
|
||||
|
||||
return blks_read;
|
||||
}
|
||||
|
||||
unsigned long dev_write(struct udevice *dev, lbaint_t start,
|
||||
lbaint_t blkcnt, const void *buffer)
|
||||
{
|
||||
struct blk_desc *block_dev;
|
||||
const struct blk_ops *ops;
|
||||
|
||||
block_dev = dev_get_blk(dev);
|
||||
if (!block_dev)
|
||||
return -ENOSYS;
|
||||
|
||||
ops = blk_get_ops(dev);
|
||||
if (!ops->write)
|
||||
return -ENOSYS;
|
||||
|
||||
blkcache_invalidate(block_dev->if_type, block_dev->devnum);
|
||||
|
||||
return ops->write(dev, start, blkcnt, buffer);
|
||||
}
|
||||
|
||||
unsigned long dev_erase(struct udevice *dev, lbaint_t start,
|
||||
lbaint_t blkcnt)
|
||||
{
|
||||
struct blk_desc *block_dev;
|
||||
const struct blk_ops *ops;
|
||||
|
||||
block_dev = dev_get_blk(dev);
|
||||
if (!block_dev)
|
||||
return -ENOSYS;
|
||||
|
||||
ops = blk_get_ops(dev);
|
||||
if (!ops->erase)
|
||||
return -ENOSYS;
|
||||
|
||||
blkcache_invalidate(block_dev->if_type, block_dev->devnum);
|
||||
|
||||
return ops->erase(dev, start, blkcnt);
|
||||
}
|
||||
|
||||
UCLASS_DRIVER(partition) = {
|
||||
.id = UCLASS_PARTITION,
|
||||
.per_device_plat_auto = sizeof(struct disk_part),
|
||||
.name = "partition",
|
||||
};
|
@ -10,6 +10,7 @@ the following SoCs work:
|
||||
- Apple M1 SoC (t8103)
|
||||
- Apple M1 Pro SoC (t6000)
|
||||
- Apple M1 Max SoC (t6001)
|
||||
- Apple M1 Ultra SoC (t6002)
|
||||
|
||||
On these SoCs the following hardware is supported:
|
||||
|
||||
@ -78,5 +79,5 @@ supported SoCs.
|
||||
- Base Address
|
||||
* - M1 (t8103)
|
||||
- 0x235200000
|
||||
* - M1 Pro/Max (t6000/t6001)
|
||||
* - M1 Pro/Max/Ultra (t6000/t6001/t6002)
|
||||
- 0x39b200000
|
||||
|
@ -1042,6 +1042,27 @@ data structure might be worthwhile in some rare cases, once we understand
|
||||
what the bottlenecks are.
|
||||
|
||||
|
||||
Tag Support
|
||||
-----------
|
||||
|
||||
It is sometimes useful for a subsystem to associate its own private
|
||||
data (or object) to a DM device, i.e. struct udevice, to support
|
||||
additional features.
|
||||
|
||||
Tag support in driver model will give us the ability to do so dynamically
|
||||
instead of modifying "udevice" data structure. In the initial release, we
|
||||
will support two type of attributes:
|
||||
|
||||
- a pointer with dm_tag_set_ptr(), and
|
||||
- an unsigned long with dm_tag_set_val()
|
||||
|
||||
For example, UEFI subsystem utilizes the feature to maintain efi_disk
|
||||
objects depending on linked udevice's lifecycle.
|
||||
|
||||
While the current implementation is quite simple, it will get evolved
|
||||
as the feature is more extensively used in U-Boot subsystems.
|
||||
|
||||
|
||||
Changes since v1
|
||||
----------------
|
||||
|
||||
|
@ -74,7 +74,7 @@ BootROM's standard input and BootROM's terminal echo are active and working
|
||||
fine. To workaround this BootROM bug with standard output, it is possible
|
||||
to manually overwrite BootROM variables stored in SRAM which BootROM use
|
||||
for checking if standard output is enabled or not. To enable BootROM
|
||||
standard output on UART, type this command folled by ENTER key:
|
||||
standard output on UART, type this command followed by ENTER key:
|
||||
|
||||
.RS 1.2i
|
||||
.TP
|
||||
|
@ -9,7 +9,7 @@ Synopsis
|
||||
|
||||
::
|
||||
|
||||
bootefi [image_addr] [fdt_addr]
|
||||
bootefi [image_addr] [fdt_addr [image_size]]
|
||||
bootefi bootmgr [fdt_addr]
|
||||
bootefi hello [fdt_addr]
|
||||
bootefi selftest [fdt_addr]
|
||||
@ -41,13 +41,28 @@ command sequence to run a UEFI application might look like
|
||||
load mmc 0:1 $kernel_addr_r /EFI/grub/grubaa64.efi
|
||||
bootefi $kernel_addr_r $fdt_addr_r
|
||||
|
||||
The last file loaded defines the image file path in the loaded image protocol.
|
||||
Hence the executable should always be loaded last.
|
||||
The last UEFI binary loaded defines the image file path in the loaded image
|
||||
protocol.
|
||||
|
||||
The value of the environment variable *bootargs* is converted from UTF-8 to
|
||||
UTF-16 and passed as load options in the loaded image protocol to the UEFI
|
||||
binary.
|
||||
|
||||
image_addr
|
||||
Address of the UEFI binary.
|
||||
|
||||
fdt_addr
|
||||
Address of the device-tree or '-'. If no address is specifiy, the
|
||||
environment variable $fdt_addr is used as first fallback, the address of
|
||||
U-Boot's internal device-tree $fdtcontroladdr as second fallback.
|
||||
When using ACPI no device-tree shall be specified.
|
||||
|
||||
image_size
|
||||
Size of the UEFI binary file. This argument is only needed if *image_addr*
|
||||
does not match the address of the last loaded UEFI binary. In this case
|
||||
a memory device path will be used as image file path in the loaded image
|
||||
protocol.
|
||||
|
||||
Note
|
||||
UEFI binaries that are contained in FIT images are launched via the
|
||||
*bootm* command.
|
||||
|
@ -741,6 +741,10 @@ static int blk_post_probe(struct udevice *dev)
|
||||
struct blk_desc *desc = dev_get_uclass_plat(dev);
|
||||
|
||||
part_init(desc);
|
||||
|
||||
if (desc->part_type != PART_TYPE_UNKNOWN &&
|
||||
part_create_block_devices(dev))
|
||||
debug("*** creating partitions failed\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -29,7 +29,7 @@ int dev_tag_set_ptr(struct udevice *dev, enum dm_tag_t tag, void *ptr)
|
||||
|
||||
node = calloc(sizeof(*node), 1);
|
||||
if (!node)
|
||||
return -ENOSPC;
|
||||
return -ENOMEM;
|
||||
|
||||
node->dev = dev;
|
||||
node->tag = tag;
|
||||
@ -53,7 +53,7 @@ int dev_tag_set_val(struct udevice *dev, enum dm_tag_t tag, ulong val)
|
||||
|
||||
node = calloc(sizeof(*node), 1);
|
||||
if (!node)
|
||||
return -ENOSPC;
|
||||
return -ENOMEM;
|
||||
|
||||
node->dev = dev;
|
||||
node->tag = tag;
|
||||
|
@ -83,6 +83,7 @@ enum uclass_id {
|
||||
UCLASS_P2SB, /* (x86) Primary-to-Sideband Bus */
|
||||
UCLASS_PANEL, /* Display panel, such as an LCD */
|
||||
UCLASS_PANEL_BACKLIGHT, /* Backlight controller for panel */
|
||||
UCLASS_PARTITION, /* Logical disk partition device */
|
||||
UCLASS_PCH, /* x86 platform controller hub */
|
||||
UCLASS_PCI, /* PCI bus */
|
||||
UCLASS_PCI_EP, /* PCI endpoint device */
|
||||
|
@ -493,6 +493,8 @@ struct efi_register_notify_event {
|
||||
/* List of all events registered by RegisterProtocolNotify() */
|
||||
extern struct list_head efi_register_notify_events;
|
||||
|
||||
/* called at pre-initialization */
|
||||
int efi_init_early(void);
|
||||
/* Initialize efi execution environment */
|
||||
efi_status_t efi_init_obj_list(void);
|
||||
/* Install device tree */
|
||||
@ -523,8 +525,8 @@ void efi_carve_out_dt_rsv(void *fdt);
|
||||
void efi_try_purge_kaslr_seed(void *fdt);
|
||||
/* Called by bootefi to make console interface available */
|
||||
efi_status_t efi_console_register(void);
|
||||
/* Called by bootefi to make all disk storage accessible as EFI objects */
|
||||
efi_status_t efi_disk_register(void);
|
||||
/* Called by efi_init_obj_list() to initialize efi_disks */
|
||||
efi_status_t efi_disk_init(void);
|
||||
/* Called by efi_init_obj_list() to install EFI_RNG_PROTOCOL */
|
||||
efi_status_t efi_rng_register(void);
|
||||
/* Called by efi_init_obj_list() to install EFI_TCG2_PROTOCOL */
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <ide.h>
|
||||
#include <uuid.h>
|
||||
#include <linker_lists.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
struct block_drvr {
|
||||
@ -86,7 +87,7 @@ struct disk_part {
|
||||
};
|
||||
|
||||
/* Misc _get_dev functions */
|
||||
#ifdef CONFIG_PARTITIONS
|
||||
#if CONFIG_IS_ENABLED(PARTITIONS)
|
||||
/**
|
||||
* blk_get_dev() - get a pointer to a block device given its type and number
|
||||
*
|
||||
@ -103,7 +104,6 @@ struct disk_part {
|
||||
struct blk_desc *blk_get_dev(const char *ifname, int dev);
|
||||
|
||||
struct blk_desc *mg_disk_get_dev(int dev);
|
||||
int host_get_dev_err(int dev, struct blk_desc **blk_devp);
|
||||
|
||||
/* disk/part.c */
|
||||
int part_get_info(struct blk_desc *dev_desc, int part,
|
||||
@ -275,6 +275,22 @@ static inline int blk_get_device_part_str(const char *ifname,
|
||||
struct disk_partition *info,
|
||||
int allow_whole_dev)
|
||||
{ *dev_desc = NULL; return -1; }
|
||||
|
||||
static inline int part_get_info_by_name_type(struct blk_desc *dev_desc,
|
||||
const char *name,
|
||||
struct disk_partition *info,
|
||||
int part_type)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int part_get_info_by_name(struct blk_desc *dev_desc,
|
||||
const char *name,
|
||||
struct disk_partition *info)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int
|
||||
part_get_info_by_dev_and_name_or_num(const char *dev_iface,
|
||||
const char *dev_part_str,
|
||||
@ -287,6 +303,23 @@ part_get_info_by_dev_and_name_or_num(const char *dev_iface,
|
||||
}
|
||||
#endif
|
||||
|
||||
struct udevice;
|
||||
/**
|
||||
* part_create_block_devices - Create block devices for disk partitions
|
||||
*
|
||||
* Create UCLASS_PARTITION udevices for each of disk partitions in @parent
|
||||
*
|
||||
* @blk_dev: Whole disk device
|
||||
*/
|
||||
int part_create_block_devices(struct udevice *blk_dev);
|
||||
|
||||
unsigned long dev_read(struct udevice *dev, lbaint_t start,
|
||||
lbaint_t blkcnt, void *buffer);
|
||||
unsigned long dev_write(struct udevice *dev, lbaint_t start,
|
||||
lbaint_t blkcnt, const void *buffer);
|
||||
unsigned long dev_erase(struct udevice *dev, lbaint_t start,
|
||||
lbaint_t blkcnt);
|
||||
|
||||
/*
|
||||
* We don't support printing partition information in SPL and only support
|
||||
* getting partition information in a few cases.
|
||||
@ -496,7 +529,7 @@ int layout_mbr_partitions(struct disk_partition *p, int count,
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PARTITIONS
|
||||
#if CONFIG_IS_ENABLED(PARTITIONS)
|
||||
/**
|
||||
* part_driver_get_count() - get partition driver count
|
||||
*
|
||||
|
@ -26,4 +26,6 @@ struct host_block_dev {
|
||||
*/
|
||||
int host_dev_bind(int dev, char *filename, bool removable);
|
||||
|
||||
int host_get_dev_err(int dev, struct blk_desc **blk_devp);
|
||||
|
||||
#endif
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <malloc.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include <dm/root.h>
|
||||
#include <dm/tag.h>
|
||||
|
||||
/*
|
||||
* EFI attributes of the udevice handled by this driver.
|
||||
@ -106,25 +107,6 @@ static ulong efi_bl_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
|
||||
return blkcnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create partions for the block device.
|
||||
*
|
||||
* @handle: EFI handle of the block device
|
||||
* @dev: udevice of the block device
|
||||
* Return: number of partitions created
|
||||
*/
|
||||
static int efi_bl_bind_partitions(efi_handle_t handle, struct udevice *dev)
|
||||
{
|
||||
struct blk_desc *desc;
|
||||
const char *if_typename;
|
||||
|
||||
desc = dev_get_uclass_plat(dev);
|
||||
if_typename = blk_get_if_type_name(desc->if_type);
|
||||
|
||||
return efi_disk_create_partitions(handle, desc, if_typename,
|
||||
desc->devnum, dev->name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a block device for a handle
|
||||
*
|
||||
@ -139,7 +121,6 @@ static int efi_bl_bind(efi_handle_t handle, void *interface)
|
||||
char *name;
|
||||
struct efi_object *obj = efi_search_obj(handle);
|
||||
struct efi_block_io *io = interface;
|
||||
int disks;
|
||||
struct efi_blk_plat *plat;
|
||||
|
||||
EFI_PRINT("%s: handle %p, interface %p\n", __func__, handle, io);
|
||||
@ -173,15 +154,20 @@ static int efi_bl_bind(efi_handle_t handle, void *interface)
|
||||
plat->handle = handle;
|
||||
plat->io = interface;
|
||||
|
||||
/*
|
||||
* FIXME: necessary because we won't do almost nothing in
|
||||
* efi_disk_create() when called from device_probe().
|
||||
*/
|
||||
ret = dev_tag_set_ptr(bdev, DM_TAG_EFI, handle);
|
||||
if (ret)
|
||||
/* FIXME: cleanup for bdev */
|
||||
return ret;
|
||||
|
||||
ret = device_probe(bdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
EFI_PRINT("%s: block device '%s' created\n", __func__, bdev->name);
|
||||
|
||||
/* Create handles for the partions of the block device */
|
||||
disks = efi_bl_bind_partitions(handle, bdev);
|
||||
EFI_PRINT("Found %d partitions\n", disks);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -14,8 +14,10 @@ config EFI_LOADER
|
||||
depends on DM_ETH || !NET
|
||||
depends on !EFI_APP
|
||||
default y if !ARM || SYS_CPU = armv7 || SYS_CPU = armv8
|
||||
select DM_EVENT
|
||||
select EVENT_DYNAMIC
|
||||
select LIB_UUID
|
||||
select PARTITION_UUIDS
|
||||
imply PARTITION_UUIDS
|
||||
select HAVE_BLOCK_DEVICE
|
||||
select REGEX
|
||||
imply FAT
|
||||
@ -40,6 +42,7 @@ config CMD_BOOTEFI_BOOTMGR
|
||||
|
||||
config EFI_SETUP_EARLY
|
||||
bool
|
||||
default y
|
||||
|
||||
choice
|
||||
prompt "Store for non-volatile UEFI variables"
|
||||
|
@ -68,7 +68,7 @@ obj-y += efi_watchdog.o
|
||||
obj-$(CONFIG_EFI_ESRT) += efi_esrt.o
|
||||
obj-$(CONFIG_LCD) += efi_gop.o
|
||||
obj-$(CONFIG_DM_VIDEO) += efi_gop.o
|
||||
obj-$(CONFIG_PARTITIONS) += efi_disk.o
|
||||
obj-$(CONFIG_BLK) += efi_disk.o
|
||||
obj-$(CONFIG_NET) += efi_net.o
|
||||
obj-$(CONFIG_GENERATE_ACPI_TABLE) += efi_acpi.o
|
||||
obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += efi_smbios.o
|
||||
|
@ -864,11 +864,16 @@ static void *dp_part_node(void *buf, struct blk_desc *desc, int part)
|
||||
break;
|
||||
case SIG_TYPE_GUID:
|
||||
hddp->signature_type = 2;
|
||||
#if CONFIG_IS_ENABLED(PARTITION_UUIDS)
|
||||
/* info.uuid exists only with PARTITION_UUIDS */
|
||||
if (uuid_str_to_bin(info.uuid,
|
||||
hddp->partition_signature, 1))
|
||||
hddp->partition_signature,
|
||||
UUID_STR_FORMAT_GUID)) {
|
||||
log_warning(
|
||||
"Partition no. %d: invalid guid: %s\n",
|
||||
"Partition %d: invalid GUID %s\n",
|
||||
part, info.uuid);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,9 @@
|
||||
#include <common.h>
|
||||
#include <blk.h>
|
||||
#include <dm.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include <dm/tag.h>
|
||||
#include <event.h>
|
||||
#include <efi_loader.h>
|
||||
#include <fs.h>
|
||||
#include <log.h>
|
||||
@ -33,7 +36,7 @@ const efi_guid_t efi_system_partition_guid = PARTITION_SYSTEM_GUID;
|
||||
* @part: partition
|
||||
* @volume: simple file system protocol of the partition
|
||||
* @offset: offset into disk for simple partition
|
||||
* @desc: internal block device descriptor
|
||||
* @dev: associated DM device
|
||||
*/
|
||||
struct efi_disk_obj {
|
||||
struct efi_object header;
|
||||
@ -45,7 +48,7 @@ struct efi_disk_obj {
|
||||
unsigned int part;
|
||||
struct efi_simple_file_system_protocol *volume;
|
||||
lbaint_t offset;
|
||||
struct blk_desc *desc;
|
||||
struct udevice *dev; /* TODO: move it to efi_object */
|
||||
};
|
||||
|
||||
/**
|
||||
@ -80,14 +83,12 @@ static efi_status_t efi_disk_rw_blocks(struct efi_block_io *this,
|
||||
void *buffer, enum efi_disk_direction direction)
|
||||
{
|
||||
struct efi_disk_obj *diskobj;
|
||||
struct blk_desc *desc;
|
||||
int blksz;
|
||||
int blocks;
|
||||
unsigned long n;
|
||||
|
||||
diskobj = container_of(this, struct efi_disk_obj, ops);
|
||||
desc = (struct blk_desc *) diskobj->desc;
|
||||
blksz = desc->blksz;
|
||||
blksz = diskobj->media.block_size;
|
||||
blocks = buffer_size / blksz;
|
||||
lba += diskobj->offset;
|
||||
|
||||
@ -98,10 +99,21 @@ static efi_status_t efi_disk_rw_blocks(struct efi_block_io *this,
|
||||
if (buffer_size & (blksz - 1))
|
||||
return EFI_BAD_BUFFER_SIZE;
|
||||
|
||||
#if CONFIG_IS_ENABLED(PARTITIONS)
|
||||
if (direction == EFI_DISK_READ)
|
||||
n = dev_read(diskobj->dev, lba, blocks, buffer);
|
||||
else
|
||||
n = dev_write(diskobj->dev, lba, blocks, buffer);
|
||||
#else
|
||||
/* dev is always a block device (UCLASS_BLK) */
|
||||
struct blk_desc *desc;
|
||||
|
||||
desc = dev_get_uclass_plat(diskobj->dev);
|
||||
if (direction == EFI_DISK_READ)
|
||||
n = blk_dread(desc, lba, blocks, buffer);
|
||||
else
|
||||
n = blk_dwrite(desc, lba, blocks, buffer);
|
||||
#endif
|
||||
|
||||
/* We don't do interrupts, so check for timers cooperatively */
|
||||
efi_timer_check();
|
||||
@ -443,7 +455,6 @@ static efi_status_t efi_disk_add_dev(
|
||||
diskobj->ops = block_io_disk_template;
|
||||
diskobj->ifname = if_typename;
|
||||
diskobj->dev_index = dev_index;
|
||||
diskobj->desc = desc;
|
||||
|
||||
/* Fill in EFI IO Media info (for read/write callbacks) */
|
||||
diskobj->media.removable_media = desc->removable;
|
||||
@ -487,103 +498,255 @@ error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_disk_create_partitions() - create handles and protocols for partitions
|
||||
/*
|
||||
* Create a handle for a whole raw disk
|
||||
*
|
||||
* Create handles and protocols for the partitions of a block device.
|
||||
* @dev uclass device (UCLASS_BLK)
|
||||
*
|
||||
* @parent: handle of the parent disk
|
||||
* @desc: block device
|
||||
* @if_typename: interface type
|
||||
* @diskid: device number
|
||||
* @pdevname: device name
|
||||
* Return: number of partitions created
|
||||
* Create an efi_disk object which is associated with @dev.
|
||||
* The type of @dev must be UCLASS_BLK.
|
||||
*
|
||||
* @return 0 on success, -1 otherwise
|
||||
*/
|
||||
int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc,
|
||||
const char *if_typename, int diskid,
|
||||
const char *pdevname)
|
||||
{
|
||||
int disks = 0;
|
||||
char devname[32] = { 0 }; /* dp->str is u16[32] long */
|
||||
int part;
|
||||
struct efi_device_path *dp = NULL;
|
||||
efi_status_t ret;
|
||||
struct efi_handler *handler;
|
||||
|
||||
/* Get the device path of the parent */
|
||||
ret = efi_search_protocol(parent, &efi_guid_device_path, &handler);
|
||||
if (ret == EFI_SUCCESS)
|
||||
dp = handler->protocol_interface;
|
||||
|
||||
/* Add devices for each partition */
|
||||
for (part = 1; part <= MAX_SEARCH_PARTITIONS; part++) {
|
||||
struct disk_partition info;
|
||||
|
||||
if (part_get_info(desc, part, &info))
|
||||
continue;
|
||||
snprintf(devname, sizeof(devname), "%s:%x", pdevname,
|
||||
part);
|
||||
ret = efi_disk_add_dev(parent, dp, if_typename, desc, diskid,
|
||||
&info, part, NULL);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
log_err("Adding partition %s failed\n", pdevname);
|
||||
continue;
|
||||
}
|
||||
disks++;
|
||||
}
|
||||
|
||||
return disks;
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_disk_register() - register block devices
|
||||
*
|
||||
* U-Boot doesn't have a list of all online disk devices. So when running our
|
||||
* EFI payload, we scan through all of the potentially available ones and
|
||||
* store them in our object pool.
|
||||
*
|
||||
* This function is called in efi_init_obj_list().
|
||||
*
|
||||
* TODO(sjg@chromium.org): Actually with CONFIG_BLK, U-Boot does have this.
|
||||
* Consider converting the code to look up devices as needed. The EFI device
|
||||
* could be a child of the UCLASS_BLK block device, perhaps.
|
||||
*
|
||||
* Return: status code
|
||||
*/
|
||||
efi_status_t efi_disk_register(void)
|
||||
static int efi_disk_create_raw(struct udevice *dev)
|
||||
{
|
||||
struct efi_disk_obj *disk;
|
||||
int disks = 0;
|
||||
struct blk_desc *desc;
|
||||
const char *if_typename;
|
||||
int diskid;
|
||||
efi_status_t ret;
|
||||
struct udevice *dev;
|
||||
|
||||
for (uclass_first_device_check(UCLASS_BLK, &dev); dev;
|
||||
uclass_next_device_check(&dev)) {
|
||||
struct blk_desc *desc = dev_get_uclass_plat(dev);
|
||||
const char *if_typename = blk_get_if_type_name(desc->if_type);
|
||||
desc = dev_get_uclass_plat(dev);
|
||||
if_typename = blk_get_if_type_name(desc->if_type);
|
||||
diskid = desc->devnum;
|
||||
|
||||
/* Add block device for the full device */
|
||||
log_info("Scanning disk %s...\n", dev->name);
|
||||
ret = efi_disk_add_dev(NULL, NULL, if_typename,
|
||||
desc, desc->devnum, NULL, 0, &disk);
|
||||
if (ret == EFI_NOT_READY) {
|
||||
ret = efi_disk_add_dev(NULL, NULL, if_typename, desc,
|
||||
diskid, NULL, 0, &disk);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
if (ret == EFI_NOT_READY)
|
||||
log_notice("Disk %s not ready\n", dev->name);
|
||||
continue;
|
||||
}
|
||||
if (ret) {
|
||||
log_err("ERROR: failure to add disk device %s, r = %lu\n",
|
||||
dev->name, ret & ~EFI_ERROR_MASK);
|
||||
continue;
|
||||
}
|
||||
disks++;
|
||||
else
|
||||
log_err("Adding disk for %s failed\n", dev->name);
|
||||
|
||||
/* Partitions show up as block devices in EFI */
|
||||
disks += efi_disk_create_partitions(
|
||||
&disk->header, desc, if_typename,
|
||||
desc->devnum, dev->name);
|
||||
return -1;
|
||||
}
|
||||
disk->dev = dev;
|
||||
if (dev_tag_set_ptr(dev, DM_TAG_EFI, &disk->header)) {
|
||||
efi_free_pool(disk->dp);
|
||||
efi_delete_handle(&disk->header);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
log_info("Found %d disks\n", disks);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a handle for a disk partition
|
||||
*
|
||||
* @dev uclass device (UCLASS_PARTITION)
|
||||
*
|
||||
* Create an efi_disk object which is associated with @dev.
|
||||
* The type of @dev must be UCLASS_PARTITION.
|
||||
*
|
||||
* @return 0 on success, -1 otherwise
|
||||
*/
|
||||
static int efi_disk_create_part(struct udevice *dev)
|
||||
{
|
||||
efi_handle_t parent;
|
||||
struct blk_desc *desc;
|
||||
const char *if_typename;
|
||||
struct disk_part *part_data;
|
||||
struct disk_partition *info;
|
||||
unsigned int part;
|
||||
int diskid;
|
||||
struct efi_handler *handler;
|
||||
struct efi_device_path *dp_parent;
|
||||
struct efi_disk_obj *disk;
|
||||
efi_status_t ret;
|
||||
|
||||
if (dev_tag_get_ptr(dev_get_parent(dev), DM_TAG_EFI, (void **)&parent))
|
||||
return -1;
|
||||
|
||||
desc = dev_get_uclass_plat(dev_get_parent(dev));
|
||||
if_typename = blk_get_if_type_name(desc->if_type);
|
||||
diskid = desc->devnum;
|
||||
|
||||
part_data = dev_get_uclass_plat(dev);
|
||||
part = part_data->partnum;
|
||||
info = &part_data->gpt_part_info;
|
||||
|
||||
ret = efi_search_protocol(parent, &efi_guid_device_path, &handler);
|
||||
if (ret != EFI_SUCCESS)
|
||||
return -1;
|
||||
dp_parent = (struct efi_device_path *)handler->protocol_interface;
|
||||
|
||||
ret = efi_disk_add_dev(parent, dp_parent, if_typename, desc, diskid,
|
||||
info, part, &disk);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
log_err("Adding partition for %s failed\n", dev->name);
|
||||
return -1;
|
||||
}
|
||||
disk->dev = dev;
|
||||
if (dev_tag_set_ptr(dev, DM_TAG_EFI, &disk->header)) {
|
||||
efi_free_pool(disk->dp);
|
||||
efi_delete_handle(&disk->header);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create efi_disk objects for a block device
|
||||
*
|
||||
* @dev uclass device (UCLASS_BLK)
|
||||
*
|
||||
* Create efi_disk objects for partitions as well as a raw disk
|
||||
* which is associated with @dev.
|
||||
* The type of @dev must be UCLASS_BLK.
|
||||
* This function is expected to be called at EV_PM_POST_PROBE.
|
||||
*
|
||||
* @return 0 on success, -1 otherwise
|
||||
*/
|
||||
static int efi_disk_probe(void *ctx, struct event *event)
|
||||
{
|
||||
struct udevice *dev;
|
||||
enum uclass_id id;
|
||||
struct blk_desc *desc;
|
||||
struct udevice *child;
|
||||
int ret;
|
||||
|
||||
dev = event->data.dm.dev;
|
||||
id = device_get_uclass_id(dev);
|
||||
|
||||
/* TODO: We won't support partitions in a partition */
|
||||
if (id != UCLASS_BLK)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* avoid creating duplicated objects now that efi_driver
|
||||
* has already created an efi_disk at this moment.
|
||||
*/
|
||||
desc = dev_get_uclass_plat(dev);
|
||||
if (desc->if_type != IF_TYPE_EFI_LOADER) {
|
||||
ret = efi_disk_create_raw(dev);
|
||||
if (ret)
|
||||
return -1;
|
||||
}
|
||||
|
||||
device_foreach_child(child, dev) {
|
||||
ret = efi_disk_create_part(child);
|
||||
if (ret)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete an efi_disk object for a whole raw disk
|
||||
*
|
||||
* @dev uclass device (UCLASS_BLK)
|
||||
*
|
||||
* Delete an efi_disk object which is associated with @dev.
|
||||
* The type of @dev must be UCLASS_BLK.
|
||||
*
|
||||
* @return 0 on success, -1 otherwise
|
||||
*/
|
||||
static int efi_disk_delete_raw(struct udevice *dev)
|
||||
{
|
||||
efi_handle_t handle;
|
||||
struct blk_desc *desc;
|
||||
struct efi_disk_obj *diskobj;
|
||||
|
||||
if (dev_tag_get_ptr(dev, DM_TAG_EFI, (void **)&handle))
|
||||
return -1;
|
||||
|
||||
desc = dev_get_uclass_plat(dev);
|
||||
if (desc->if_type != IF_TYPE_EFI_LOADER) {
|
||||
diskobj = container_of(handle, struct efi_disk_obj, header);
|
||||
efi_free_pool(diskobj->dp);
|
||||
}
|
||||
|
||||
efi_delete_handle(handle);
|
||||
dev_tag_del(dev, DM_TAG_EFI);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete an efi_disk object for a disk partition
|
||||
*
|
||||
* @dev uclass device (UCLASS_PARTITION)
|
||||
*
|
||||
* Delete an efi_disk object which is associated with @dev.
|
||||
* The type of @dev must be UCLASS_PARTITION.
|
||||
*
|
||||
* @return 0 on success, -1 otherwise
|
||||
*/
|
||||
static int efi_disk_delete_part(struct udevice *dev)
|
||||
{
|
||||
efi_handle_t handle;
|
||||
struct efi_disk_obj *diskobj;
|
||||
|
||||
if (dev_tag_get_ptr(dev, DM_TAG_EFI, (void **)&handle))
|
||||
return -1;
|
||||
|
||||
diskobj = container_of(handle, struct efi_disk_obj, header);
|
||||
|
||||
efi_free_pool(diskobj->dp);
|
||||
efi_delete_handle(handle);
|
||||
dev_tag_del(dev, DM_TAG_EFI);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete an efi_disk object for a block device
|
||||
*
|
||||
* @dev uclass device (UCLASS_BLK or UCLASS_PARTITION)
|
||||
*
|
||||
* Delete an efi_disk object which is associated with @dev.
|
||||
* The type of @dev must be either UCLASS_BLK or UCLASS_PARTITION.
|
||||
* This function is expected to be called at EV_PM_PRE_REMOVE.
|
||||
*
|
||||
* @return 0 on success, -1 otherwise
|
||||
*/
|
||||
static int efi_disk_remove(void *ctx, struct event *event)
|
||||
{
|
||||
enum uclass_id id;
|
||||
struct udevice *dev;
|
||||
|
||||
dev = event->data.dm.dev;
|
||||
id = device_get_uclass_id(dev);
|
||||
|
||||
if (id == UCLASS_BLK)
|
||||
return efi_disk_delete_raw(dev);
|
||||
else if (id == UCLASS_PARTITION)
|
||||
return efi_disk_delete_part(dev);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
efi_status_t efi_disk_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = event_register("efi_disk add", EVT_DM_POST_PROBE,
|
||||
efi_disk_probe, NULL);
|
||||
if (ret) {
|
||||
log_err("Event registration for efi_disk add failed\n");
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
ret = event_register("efi_disk del", EVT_DM_PRE_REMOVE,
|
||||
efi_disk_remove, NULL);
|
||||
if (ret) {
|
||||
log_err("Event registration for efi_disk del failed\n");
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
@ -174,6 +174,55 @@ static efi_status_t efi_init_os_indications(void)
|
||||
&os_indications_supported, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* __efi_init_early() - handle initialization at early stage
|
||||
*
|
||||
* This function is called in efi_init_obj_list() only if
|
||||
* !CONFIG_EFI_SETUP_EARLY.
|
||||
*
|
||||
* Return: status code
|
||||
*/
|
||||
static efi_status_t __efi_init_early(void)
|
||||
{
|
||||
efi_status_t ret = EFI_SUCCESS;
|
||||
|
||||
/* Allow unaligned memory access */
|
||||
allow_unaligned();
|
||||
|
||||
/* Initialize root node */
|
||||
ret = efi_root_node_register();
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto out;
|
||||
|
||||
ret = efi_console_register();
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto out;
|
||||
|
||||
ret = efi_disk_init();
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_init_early() - handle initialization at early stage
|
||||
*
|
||||
* external version of __efi_init_early(); expected to be called in
|
||||
* board_init_r().
|
||||
*
|
||||
* Return: status code
|
||||
*/
|
||||
int efi_init_early(void)
|
||||
{
|
||||
efi_status_t ret;
|
||||
|
||||
ret = __efi_init_early();
|
||||
if (ret != EFI_SUCCESS) {
|
||||
/* never re-init UEFI subsystem */
|
||||
efi_obj_list_initialized = ret;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_init_obj_list() - Initialize and populate EFI object list
|
||||
@ -188,23 +237,12 @@ efi_status_t efi_init_obj_list(void)
|
||||
if (efi_obj_list_initialized != OBJ_LIST_NOT_INITIALIZED)
|
||||
return efi_obj_list_initialized;
|
||||
|
||||
/* Allow unaligned memory access */
|
||||
allow_unaligned();
|
||||
if (!IS_ENABLED(CONFIG_EFI_SETUP_EARLY)) {
|
||||
ret = __efi_init_early();
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Initialize root node */
|
||||
ret = efi_root_node_register();
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto out;
|
||||
|
||||
ret = efi_console_register();
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto out;
|
||||
|
||||
#ifdef CONFIG_PARTITIONS
|
||||
ret = efi_disk_register();
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto out;
|
||||
#endif
|
||||
if (IS_ENABLED(CONFIG_EFI_RNG_PROTOCOL)) {
|
||||
ret = efi_rng_register();
|
||||
if (ret != EFI_SUCCESS)
|
||||
|
@ -102,6 +102,7 @@ obj-y += syscon.o
|
||||
obj-$(CONFIG_RESET_SYSCON) += syscon-reset.o
|
||||
obj-$(CONFIG_SYSINFO) += sysinfo.o
|
||||
obj-$(CONFIG_SYSINFO_GPIO) += sysinfo-gpio.o
|
||||
obj-$(CONFIG_UT_DM) += tag.o
|
||||
obj-$(CONFIG_TEE) += tee.o
|
||||
obj-$(CONFIG_TIMER) += timer.o
|
||||
obj-$(CONFIG_DM_USB) += usb.o
|
||||
|
84
test/dm/tag.c
Normal file
84
test/dm/tag.c
Normal file
@ -0,0 +1,84 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* DM tag test
|
||||
*
|
||||
* Copyright (c) 2021 Linaro Limited
|
||||
* Author: AKASHI Takahiro
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm/tag.h>
|
||||
#include <dm/test.h> /* DM_TEST() */
|
||||
#include <test/test.h> /* struct unit_test_state */
|
||||
#include <test/ut.h> /* assertions */
|
||||
|
||||
/*
|
||||
* Test dm_tag_ptr() API
|
||||
*/
|
||||
static int dm_test_tag_ptr(struct unit_test_state *uts)
|
||||
{
|
||||
ulong val;
|
||||
void *ptr = NULL;
|
||||
|
||||
ut_assertok(dev_tag_set_ptr(uts->root, DM_TAG_EFI, &val));
|
||||
|
||||
ut_assertok(dev_tag_get_ptr(uts->root, DM_TAG_EFI, &ptr));
|
||||
|
||||
ut_asserteq_ptr(&val, ptr);
|
||||
|
||||
ut_assertok(dev_tag_del(uts->root, DM_TAG_EFI));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DM_TEST(dm_test_tag_ptr, 0);
|
||||
|
||||
/*
|
||||
* Test dm_tag_val() API
|
||||
*/
|
||||
static int dm_test_tag_val(struct unit_test_state *uts)
|
||||
{
|
||||
ulong val1 = 0x12345678, val2 = 0;
|
||||
|
||||
ut_assertok(dev_tag_set_val(uts->root, DM_TAG_EFI, val1));
|
||||
|
||||
ut_assertok(dev_tag_get_val(uts->root, DM_TAG_EFI, &val2));
|
||||
|
||||
ut_asserteq_64(val1, val2);
|
||||
|
||||
ut_assertok(dev_tag_del(uts->root, DM_TAG_EFI));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DM_TEST(dm_test_tag_val, 0);
|
||||
|
||||
/*
|
||||
* Test against an invalid tag
|
||||
*/
|
||||
static int dm_test_tag_inval(struct unit_test_state *uts)
|
||||
{
|
||||
ulong val;
|
||||
|
||||
ut_asserteq(-EINVAL, dev_tag_set_ptr(uts->root, DM_TAG_COUNT, &val));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DM_TEST(dm_test_tag_inval, 0);
|
||||
|
||||
/*
|
||||
* Test dm_tag_del_all() AP:
|
||||
*/
|
||||
static int dm_test_tag_del_all(struct unit_test_state *uts)
|
||||
{
|
||||
ulong val;
|
||||
|
||||
ut_assertok(dev_tag_set_ptr(uts->root, DM_TAG_EFI, &val));
|
||||
|
||||
ut_assertok(dev_tag_del_all(uts->root));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DM_TEST(dm_test_tag_del_all, 0);
|
Loading…
Reference in New Issue
Block a user