Some bootmeths support scanning a partition without a filesystem on it.
Add a flag to support this.

This will allow the ChromiumOS bootmeth to find kernel partition, which
are stored in a special format, without a filesystem.

Signed-off-by: Simon Glass <s...@chromium.org>
---

 boot/bootdev-uclass.c   | 17 ++++++++++++++---
 doc/develop/bootstd.rst | 11 ++++++-----
 include/bootmeth.h      |  3 +++
 3 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c
index 00dc28e623a2..eab89088b63d 100644
--- a/boot/bootdev-uclass.c
+++ b/boot/bootdev-uclass.c
@@ -111,6 +111,8 @@ int bootdev_bind(struct udevice *parent, const char 
*drv_name, const char *name,
 int bootdev_find_in_blk(struct udevice *dev, struct udevice *blk,
                        struct bootflow_iter *iter, struct bootflow *bflow)
 {
+       struct bootmeth_uc_plat *plat = dev_get_uclass_plat(bflow->method);
+       bool allow_any_part = plat->flags & BOOTMETHF_ANY_PART;
        struct blk_desc *desc = dev_get_uclass_plat(blk);
        struct disk_partition info;
        char partstr[20];
@@ -142,6 +144,7 @@ int bootdev_find_in_blk(struct udevice *dev, struct udevice 
*blk,
         * us whether there is valid media there
         */
        ret = part_get_info(desc, iter->part, &info);
+       log_debug("part_get_info() returned %d\n", ret);
        if (!iter->part && ret == -ENOENT)
                ret = 0;
 
@@ -154,7 +157,7 @@ int bootdev_find_in_blk(struct udevice *dev, struct udevice 
*blk,
                ret = -ESHUTDOWN;
        else
                bflow->state = BOOTFLOWST_MEDIA;
-       if (ret) {
+       if (ret && !allow_any_part) {
                /* allow partition 1 to be missing */
                if (iter->part == 1) {
                        iter->max_part = 3;
@@ -174,9 +177,15 @@ int bootdev_find_in_blk(struct udevice *dev, struct 
udevice *blk,
        if (!iter->part) {
                iter->first_bootable = part_get_bootable(desc);
                log_debug("checking bootable=%d\n", iter->first_bootable);
+       } else if (allow_any_part) {
+               /*
+                * allow any partition to be scanned, by skipping any checks
+                * for filesystems or partition contents on this disk
+                */
 
        /* if there are bootable partitions, scan only those */
-       } else if (iter->first_bootable ? !info.bootable : iter->part != 1) {
+       } else if (iter->first_bootable >= 0 &&
+                  (iter->first_bootable ? !info.bootable : iter->part != 1)) {
                return log_msg_ret("boot", -EINVAL);
        } else {
                ret = fs_set_blk_dev_with_part(desc, bflow->part);
@@ -193,6 +202,7 @@ int bootdev_find_in_blk(struct udevice *dev, struct udevice 
*blk,
                bflow->state = BOOTFLOWST_FS;
        }
 
+       log_debug("method %s\n", bflow->method->name);
        ret = bootmeth_read_bootflow(bflow->method, bflow);
        if (ret)
                return log_msg_ret("method", ret);
@@ -555,7 +565,8 @@ int bootdev_get_bootflow(struct udevice *dev, struct 
bootflow_iter *iter,
 {
        const struct bootdev_ops *ops = bootdev_get_ops(dev);
 
-       log_debug("->get_bootflow %s=%p\n", dev->name, ops->get_bootflow);
+       log_debug("->get_bootflow %s,%x=%p\n", dev->name, iter->part,
+                 ops->get_bootflow);
        bootflow_init(bflow, dev, iter->method);
        if (!ops->get_bootflow)
                return default_get_bootflow(dev, iter, bflow);
diff --git a/doc/develop/bootstd.rst b/doc/develop/bootstd.rst
index 7a2a69fdfcec..23ea46d6c304 100644
--- a/doc/develop/bootstd.rst
+++ b/doc/develop/bootstd.rst
@@ -677,11 +677,12 @@ Assuming the bootmeth is happy, or at least indicates 
that it is willing to try
 partition. If that works it tries to detect a file system. If that works then 
it
 calls the bootmeth device once more, this time to read the bootflow.
 
-Note: At present a filesystem is needed for the bootmeth to be called on block
-devices, simply because we don't have any examples where this is not the case.
-This feature can be added as needed. Note that sandbox is a special case, since
-in that case the host filesystem can be accessed even though the block device
-is NULL.
+Note: Normally a filesystem is needed for the bootmeth to be called on block
+devices, but bootmeths which don't need that can set the BOOTMETHF_ANY_PART
+flag to indicate that they can scan any partition. An example is the ChromiumOS
+bootmeth which can store a kernel in a raw partition. Note also that sandbox is
+a special case, since in that case the host filesystem can be accessed even
+though the block device is NULL.
 
 If we take the example of the `bootmeth_extlinux` driver, this call ends up at
 `extlinux_read_bootflow()`. It has the filesystem ready, so tries various
diff --git a/include/bootmeth.h b/include/bootmeth.h
index d3d8d608cd78..0fc36104ece0 100644
--- a/include/bootmeth.h
+++ b/include/bootmeth.h
@@ -16,9 +16,12 @@ struct udevice;
  * enum bootmeth_flags - Flags for bootmeths
  *
  * @BOOTMETHF_GLOBAL: bootmeth handles bootdev selection automatically
+ * @BOOTMETHF_ANY_PART: bootmeth is willing to check any partition, even if it
+ * has no filesystem
  */
 enum bootmeth_flags {
        BOOTMETHF_GLOBAL        = BIT(0),
+       BOOTMETHF_ANY_PART      = BIT(1),
 };
 
 /**
-- 
2.41.0.640.ga95def55d0-goog

Reply via email to