bootstd: Support bootmeths which can scan any partition

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 <sjg@chromium.org>
This commit is contained in:
Simon Glass 2023-08-24 13:55:43 -06:00 committed by Tom Rini
parent f55aa4454a
commit 831405f41d
3 changed files with 23 additions and 8 deletions

View File

@ -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);
@ -559,7 +569,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);

View File

@ -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

View File

@ -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),
};
/**