diff --git a/Documentation/boards/efi.rst b/Documentation/boards/efi.rst index ecadb3e..8f78a80 100644 --- a/Documentation/boards/efi.rst +++ b/Documentation/boards/efi.rst @@ -42,6 +42,10 @@ start barebox via USB. Some BIOSes allow to specify a path to a binary to be executed, others have a "start UEFI shell" entry which executes EFI/Shellx64.efi on the :term:`ESP`. This can be a barebox binary aswell. +To use the :ref:`state_framework`, the describing devicetree file ``state.dtb`` +has to be put into the ``EFI/barebox/`` directory. +Supported backends for EFI are raw partitions that can be discovered via a +partition UUID. Running EFI barebox on qemu ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Documentation/devicetree/bindings/mtd/partition.txt b/Documentation/devicetree/bindings/mtd/partition.txt new file mode 100644 index 0000000..ab21ff2 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/partition.txt @@ -0,0 +1,21 @@ +Representing flash partitions in devicetree + +In addition to the upstream binding, another property is added: + +Optional properties: +- partuuid : The partition UUID for this partition. + + +Examples: + +flash@0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + state_part: state { + partuuid = "16367da7-c518-499f-9aad-e1f366692365"; + }; + }; +}; diff --git a/arch/x86/configs/efi_defconfig b/arch/x86/configs/efi_defconfig index 0d9a44a..3e83fd9 100644 --- a/arch/x86/configs/efi_defconfig +++ b/arch/x86/configs/efi_defconfig @@ -15,12 +15,12 @@ CONFIG_PARTITION_DISK_EFI=y CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y CONFIG_POLLER=y +CONFIG_STATE=y CONFIG_DEBUG_INFO=y CONFIG_DEBUG_LL=y CONFIG_LONGHELP=y CONFIG_CMD_IOMEM=y CONFIG_CMD_MEMINFO=y -# CONFIG_CMD_LINUX16 is not set CONFIG_CMD_GO=y CONFIG_CMD_LOADB=y CONFIG_CMD_RESET=y @@ -61,6 +61,7 @@ CONFIG_CMD_OF_PROPERTY=y CONFIG_CMD_OFTREE=y CONFIG_CMD_TIME=y +CONFIG_CMD_STATE=y CONFIG_NET=y CONFIG_NET_NFS=y CONFIG_NET_NETCONSOLE=y diff --git a/common/blspec.c b/common/blspec.c index 8132d14..b258e66 100644 --- a/common/blspec.c +++ b/common/blspec.c @@ -361,6 +361,14 @@ const char *compat; char *filename; + /* If the entry doesn't specifiy a devicetree we are compatible */ + devicetree = blspec_entry_var_get(entry, "devicetree"); + if (!devicetree) + return true; + + if (!strcmp(devicetree, "none")) + return true; + /* If we don't have a root node every entry is compatible */ barebox_root = of_get_root_node(); if (!barebox_root) @@ -375,14 +383,6 @@ else abspath = ""; - /* If the entry doesn't specifiy a devicetree we are compatible */ - devicetree = blspec_entry_var_get(entry, "devicetree"); - if (!devicetree) - return true; - - if (!strcmp(devicetree, "none")) - return true; - filename = basprintf("%s/%s", abspath, devicetree); fdt = read_file(filename, &size); diff --git a/common/efi/efi.c b/common/efi/efi.c index 05c5825..4b42f5d 100644 --- a/common/efi/efi.c +++ b/common/efi/efi.c @@ -40,6 +40,9 @@ #include #include #include +#include +#include +#include efi_runtime_services_t *RT; efi_boot_services_t *BS; @@ -266,8 +269,7 @@ add_generic_device("efi-stdio", DEVICE_ID_SINGLE, NULL, 0 , 0, 0, NULL); - if (IS_ENABLED(CONFIG_ARCH_EFI_REGISTER_COM1)) - add_ns16550_device(0, 0x3f8, 0x10, IORESOURCE_IO | IORESOURCE_MEM_8BIT, + add_ns16550_device(0, 0x3f8, 0x10, IORESOURCE_IO | IORESOURCE_MEM_8BIT, &ns16550_plat); return 0; @@ -381,10 +383,70 @@ free(uuid16); } + bbu_register_std_file_update("fat", 0, "/boot/EFI/BOOT/BOOTx64.EFI", + filetype_exe); + return 0; } postcore_initcall(efi_postcore_init); +static int efi_late_init(void) +{ + char *state_desc; + int ret; + + if (!IS_ENABLED(CONFIG_STATE)) + return 0; + + state_desc = xasprintf("/boot/EFI/barebox/state.dtb"); + + if (state_desc) { + void *fdt; + size_t size; + struct device_node *root = NULL; + struct device_node *np = NULL; + struct state *state; + + fdt = read_file(state_desc, &size); + if (!fdt) { + pr_err("unable to read %s: %s\n", state_desc, + strerror(errno)); + return -errno; + } + + if (file_detect_type(fdt, size) != filetype_oftree) { + pr_err("%s is not an oftree file.\n", state_desc); + free(fdt); + return -EINVAL; + } + + root = of_unflatten_dtb(fdt); + + free(fdt); + + if (IS_ERR(root)) + return PTR_ERR(root); + + of_set_root_node(root); + + np = of_find_node_by_alias(root, "state"); + + state = state_new_from_node(np, NULL, 0, 0, false); + if (IS_ERR(state)) + return PTR_ERR(state); + + ret = state_load(state); + if (ret) + pr_warn("Failed to load persistent state, continuing with defaults, %d\n", + ret); + + return 0; + } + + return 0; +} +late_initcall(efi_late_init); + static int do_efiexit(int argc, char *argv[]) { return BS->exit(efi_parent_image, EFI_SUCCESS, 0, NULL); diff --git a/common/state/backend_format_dtb.c b/common/state/backend_format_dtb.c index e88cda4..4c9d2ee 100644 --- a/common/state/backend_format_dtb.c +++ b/common/state/backend_format_dtb.c @@ -49,7 +49,7 @@ size_t len = *lenp; if (dtb_len > len) { - dev_err(fdtb->dev, "Error, stored DTB length (%d) longer than read buffer (%d)\n", + dev_err(fdtb->dev, "Error, stored DTB length (%zd) longer than read buffer (%zd)\n", dtb_len, len); return -EINVAL; } diff --git a/common/state/backend_format_raw.c b/common/state/backend_format_raw.c index d76718c..2ba97e0 100644 --- a/common/state/backend_format_raw.c +++ b/common/state/backend_format_raw.c @@ -108,7 +108,7 @@ ssize_t complete_len; if (len < format_raw_min_length) { - dev_err(backend_raw->dev, "Error, buffer length (%d) is shorter than the minimum required header length\n", + dev_err(backend_raw->dev, "Error, buffer length (%zd) is shorter than the minimum required header length\n", len); return -EINVAL; } diff --git a/common/state/backend_storage.c b/common/state/backend_storage.c index 3249d0b..d2d1778 100644 --- a/common/state/backend_storage.c +++ b/common/state/backend_storage.c @@ -247,7 +247,7 @@ end = meminfo->size; if (!IS_ALIGNED(storage->offset, meminfo->erasesize)) { - dev_err(storage->dev, "Offset within the device is not aligned to eraseblocks. Offset is %ld, erasesize %zu\n", + dev_err(storage->dev, "Offset within the device is not aligned to eraseblocks. Offset is %ld, erasesize %u\n", storage->offset, meminfo->erasesize); return -EINVAL; } diff --git a/drivers/of/of_path.c b/drivers/of/of_path.c index 334eab8..e53041b 100644 --- a/drivers/of/of_path.c +++ b/drivers/of/of_path.c @@ -56,11 +56,26 @@ dev = of_find_device_by_node_path(node->full_name); if (!dev) { + int ret; + const char *uuid; struct device_node *devnode = node->parent; - if (of_device_is_compatible(devnode, "fixed-partitions")) + if (of_device_is_compatible(devnode, "fixed-partitions")) { devnode = devnode->parent; + /* when partuuid is specified short-circuit the search for the cdev */ + ret = of_property_read_string(node, "partuuid", &uuid); + if (!ret) { + cdev = cdev_by_partuuid(uuid); + if (!cdev) + return -ENODEV; + + *outpath = basprintf("/dev/%s", cdev->name); + + return 0; + } + } + dev = of_find_device_by_node_path(devnode->full_name); if (!dev) return -ENODEV; diff --git a/fs/devfs-core.c b/fs/devfs-core.c index 3368d3e..be56edd 100644 --- a/fs/devfs-core.c +++ b/fs/devfs-core.c @@ -95,6 +95,20 @@ return NULL; } +struct cdev *cdev_by_partuuid(const char *partuuid) +{ + struct cdev *cdev; + + if (!partuuid) + return NULL; + + list_for_each_entry(cdev, &cdev_list, list) { + if (!strcmp(cdev->partuuid, partuuid)) + return cdev; + } + return NULL; +} + /** * device_find_partition - find a partition belonging to a physical device * diff --git a/fs/efi.c b/fs/efi.c index 0c0f52e..85ff914 100644 --- a/fs/efi.c +++ b/fs/efi.c @@ -407,9 +407,7 @@ efiret = priv->root_dir->open(priv->root_dir, &entry, efi_path, EFI_FILE_MODE_READ, 0ULL); if (EFI_ERROR(efiret)) { - pr_err("%s: unable to Open %s: %s\n", __func__, filename, - efi_strerror(efiret)); - ret = -efi_errno(efiret); + ret = -ENOENT; goto out_free; } diff --git a/include/driver.h b/include/driver.h index 3d701f2..8617872 100644 --- a/include/driver.h +++ b/include/driver.h @@ -472,6 +472,7 @@ struct cdev *lcdev_by_name(const char *filename); struct cdev *cdev_readlink(struct cdev *cdev); struct cdev *cdev_by_device_node(struct device_node *node); +struct cdev *cdev_by_partuuid(const char *partuuid); struct cdev *cdev_open(const char *name, unsigned long flags); struct cdev *cdev_create_loop(const char *path, ulong flags); void cdev_remove_loop(struct cdev *cdev);