summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/boards/efi.rst4
-rw-r--r--Documentation/devicetree/bindings/mtd/partition.txt21
-rw-r--r--arch/x86/configs/efi_defconfig3
-rw-r--r--common/blspec.c16
-rw-r--r--common/efi/efi.c66
-rw-r--r--common/state/backend_format_dtb.c2
-rw-r--r--common/state/backend_format_raw.c2
-rw-r--r--common/state/backend_storage.c2
-rw-r--r--drivers/of/of_path.c17
-rw-r--r--fs/devfs-core.c14
-rw-r--r--fs/efi.c4
-rw-r--r--include/driver.h1
12 files changed, 134 insertions, 18 deletions
diff --git a/Documentation/boards/efi.rst b/Documentation/boards/efi.rst
index ecadb3ebba..8f78a800ef 100644
--- a/Documentation/boards/efi.rst
+++ b/Documentation/boards/efi.rst
@@ -42,6 +42,10 @@ architectures. Switching to USB boot in the BIOS should then be enough to
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 0000000000..ab21ff25bb
--- /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 0d9a44a4d2..3e83fd92d9 100644
--- a/arch/x86/configs/efi_defconfig
+++ b/arch/x86/configs/efi_defconfig
@@ -15,12 +15,12 @@ CONFIG_CONSOLE_ACTIVATE_ALL=y
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_NODE=y
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 8132d141ab..b258e6600b 100644
--- a/common/blspec.c
+++ b/common/blspec.c
@@ -361,6 +361,14 @@ static bool entry_is_of_compatible(struct blspec_entry *entry)
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 @@ static bool entry_is_of_compatible(struct blspec_entry *entry)
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 05c58250f4..4b42f5d676 100644
--- a/common/efi/efi.c
+++ b/common/efi/efi.c
@@ -40,6 +40,9 @@
#include <efi.h>
#include <efi/efi.h>
#include <efi/efi-device.h>
+#include <libfile.h>
+#include <state.h>
+#include <bbu.h>
efi_runtime_services_t *RT;
efi_boot_services_t *BS;
@@ -266,8 +269,7 @@ static int efi_console_init(void)
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 @@ static int efi_postcore_init(void)
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 e88cda499b..4c9d2eefc7 100644
--- a/common/state/backend_format_dtb.c
+++ b/common/state/backend_format_dtb.c
@@ -49,7 +49,7 @@ static int state_backend_format_dtb_verify(struct state_backend_format *format,
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 d76718cf82..2ba97e08a0 100644
--- a/common/state/backend_format_raw.c
+++ b/common/state/backend_format_raw.c
@@ -108,7 +108,7 @@ static int backend_format_raw_verify(struct state_backend_format *format,
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 3249d0bca6..d2d1778915 100644
--- a/common/state/backend_storage.c
+++ b/common/state/backend_storage.c
@@ -247,7 +247,7 @@ static int state_storage_mtd_buckets_init(struct state_backend_storage *storage,
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 334eab841a..e53041b0a1 100644
--- a/drivers/of/of_path.c
+++ b/drivers/of/of_path.c
@@ -56,11 +56,26 @@ static int __of_find_path(struct device_node *node, const char *part, char **out
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 3368d3ed68..be56edd18d 100644
--- a/fs/devfs-core.c
+++ b/fs/devfs-core.c
@@ -95,6 +95,20 @@ struct cdev *cdev_by_device_node(struct device_node *node)
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 0c0f52e87c..85ff914291 100644
--- a/fs/efi.c
+++ b/fs/efi.c
@@ -407,9 +407,7 @@ static int efifs_stat(struct device_d *dev, const char *filename, struct stat *s
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 3d701f2439..8617872053 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -472,6 +472,7 @@ struct cdev *cdev_by_name(const char *filename);
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);