summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2025-01-15 17:34:26 -0600
committerTom Rini <[email protected]>2025-01-15 19:27:14 -0600
commit178f6ecb21fe12ada74a9a1a08093c812b15eea5 (patch)
tree60dee6152b33cbd13f311875ce2fc8e9350a8c3d /include
parente26a9ac4c6900cac2fa043ac50a3a3c038f4505d (diff)
parenta3d0fadca6b14f57477a4143334993daf52f89dc (diff)
Merge patch series "bootstd: Support recording images"
Simon Glass <[email protected]> says: This series provides a way to keep track of the images used in bootstd, including the type of each image. At present this is sort-of handled by struct bootflow but in quite an ad-hoc way. The structure has become quite large and is hard to query. Future work will be able to reduce its size. Ultimately the 'bootflow info' command may change to also show images as a list, but that is left for later, as this series is already fairly long. So for now, just introduce the concept and adjust bootstd to use it, with a simple command to list the images. This series includes various alist enhancements, to make use of this new data structure a little easier. [trini: Drop patch 18 and 19 for now due to size considerations] Link: https://lore.kernel.org/r/[email protected]
Diffstat (limited to 'include')
-rw-r--r--include/bootdev.h36
-rw-r--r--include/bootflow.h85
-rw-r--r--include/bootmeth.h22
-rw-r--r--include/bootstd.h50
-rw-r--r--include/pxe_utils.h14
5 files changed, 161 insertions, 46 deletions
diff --git a/include/bootdev.h b/include/bootdev.h
index ad4af0d1310..12c90c4ec1b 100644
--- a/include/bootdev.h
+++ b/include/bootdev.h
@@ -109,11 +109,9 @@ struct bootdev_hunter {
* This is attached to each device in the bootdev uclass and accessible via
* dev_get_uclass_plat(dev)
*
- * @bootflows: List of available bootflows for this bootdev
* @piro: Priority of this bootdev
*/
struct bootdev_uc_plat {
- struct list_head bootflow_head;
enum bootdev_prio_t prio;
};
@@ -186,31 +184,6 @@ int bootdev_find_in_blk(struct udevice *dev, struct udevice *blk,
void bootdev_list(bool probe);
/**
- * bootdev_clear_bootflows() - Clear bootflows from a bootdev
- *
- * Each bootdev maintains a list of discovered bootflows. This provides a
- * way to clear it. These bootflows are removed from the global list too.
- *
- * @dev: bootdev device to update
- */
-void bootdev_clear_bootflows(struct udevice *dev);
-
-/**
- * bootdev_add_bootflow() - Add a bootflow to the bootdev's list
- *
- * All fields in @bflow must be set up. Note that @bflow->dev is used to add the
- * bootflow to that device.
- *
- * @dev: Bootdev device to add to
- * @bflow: Bootflow to add. Note that fields within bflow must be allocated
- * since this function takes over ownership of these. This functions makes
- * a copy of @bflow itself (without allocating its fields again), so the
- * caller must dispose of the memory used by the @bflow pointer itself
- * Return: 0 if OK, -ENOMEM if out of memory
- */
-int bootdev_add_bootflow(struct bootflow *bflow);
-
-/**
* bootdev_first_bootflow() - Get the first bootflow from a bootdev
*
* Returns the first bootflow attached to a bootdev
@@ -429,6 +402,15 @@ static int bootdev_setup_for_sibling_blk(struct udevice *blk,
int bootdev_get_sibling_blk(struct udevice *dev, struct udevice **blkp);
/**
+ * bootdev_get_from_blk() - Get the bootdev given a block device
+ *
+ * @blk: Block device to check
+ * @bootdebp: Returns the bootdev found, if any
+ * Return 0 if OK, -ve on error
+ */
+int bootdev_get_from_blk(struct udevice *blk, struct udevice **bootdevp);
+
+/**
* bootdev_unbind_dev() - Unbind a bootdev device
*
* Remove and unbind a bootdev device which is a child of @parent. This should
diff --git a/include/bootflow.h b/include/bootflow.h
index 4d2fc7b69b5..480cf8a5af1 100644
--- a/include/bootflow.h
+++ b/include/bootflow.h
@@ -7,7 +7,9 @@
#ifndef __bootflow_h
#define __bootflow_h
+#include <alist.h>
#include <bootdev.h>
+#include <image.h>
#include <dm/ofnode_decl.h>
#include <linux/list.h>
@@ -56,13 +58,8 @@ enum bootflow_flags_t {
/**
* struct bootflow - information about a bootflow
*
- * This is connected into two separate linked lists:
+ * All bootflows are listed in bootstd's bootflow alist in struct bootstd_priv
*
- * bm_sibling - links all bootflows in the same bootdev
- * glob_sibling - links all bootflows in all bootdevs
- *
- * @bm_node: Points to siblings in the same bootdev
- * @glob_node: Points to siblings in the global list (all bootdev)
* @dev: Bootdev device which produced this bootflow, NULL for flows created by
* BOOTMETHF_GLOBAL bootmeths
* @blk: Block device which contains this bootflow, NULL if this is a network
@@ -90,10 +87,9 @@ enum bootflow_flags_t {
* @cmdline: OS command line, or NULL if not known (allocated)
* @x86_setup: Pointer to x86 setup block inside @buf, NULL if not present
* @bootmeth_priv: Private data for the bootmeth
+ * @images: List of loaded images (struct bootstd_img)
*/
struct bootflow {
- struct list_head bm_node;
- struct list_head glob_node;
struct udevice *dev;
struct udevice *blk;
int part;
@@ -116,6 +112,44 @@ struct bootflow {
char *cmdline;
void *x86_setup;
void *bootmeth_priv;
+ struct alist images;
+};
+
+/**
+ * bootflow_img_t: Supported image types
+ *
+ * This uses image_type_t for most types, but extends it
+ *
+ * @BFI_EXTLINUX_CFG: extlinux configuration-file
+ * @BFI_LOGO: logo image
+ * @BFI_EFI: EFI PE image
+ * @BFI_CMDLINE: OS command-line string
+ */
+enum bootflow_img_t {
+ BFI_FIRST = IH_TYPE_COUNT,
+ BFI_EXTLINUX_CFG = BFI_FIRST,
+ BFI_LOGO,
+ BFI_EFI,
+ BFI_CMDLINE,
+
+ BFI_COUNT,
+};
+
+/**
+ * struct bootflow_img - Information about an image which has been loaded
+ *
+ * This keeps track of a single, loaded image.
+ *
+ * @fname: Filename used to load the image (allocated)
+ * @type: Image type (IH_TYPE_...)
+ * @addr: Address to which the image was loaded, 0 if not yet loaded
+ * @size: Size of the image
+ */
+struct bootflow_img {
+ char *fname;
+ enum bootflow_img_t type;
+ ulong addr;
+ ulong size;
};
/**
@@ -393,7 +427,10 @@ const char *bootflow_state_get_name(enum bootflow_state_t state);
/**
* bootflow_remove() - Remove a bootflow and free its memory
*
- * This updates the linked lists containing the bootflow then frees it.
+ * This updates the 'global' linked list containing the bootflow, then frees it.
+ * It does not remove it from bootflows alist in struct bootstd_priv
+ *
+ * This does not free bflow itself, since this is assumed to be in an alist
*
* @bflow: Bootflow to remove
*/
@@ -569,4 +606,34 @@ int bootflow_cmdline_get_arg(struct bootflow *bflow, const char *arg,
*/
int bootflow_cmdline_auto(struct bootflow *bflow, const char *arg);
+/**
+ * bootflow_img_type_name() - Get the name for an image type
+ *
+ * @type: Type to check (either enum bootflow_img_t or enum image_type_t
+ * Return: Image name, or "unknown" if not known
+ */
+const char *bootflow_img_type_name(enum bootflow_img_t type);
+
+/**
+ * bootflow_img_add() - Add a new image to a bootflow
+ *
+ * @bflow: Bootflow to add to
+ * @fname: Image filename (will be allocated)
+ * @type: Image type
+ * @addr: Address the image was loaded to, or 0 if not loaded
+ * @size: Image size
+ * Return: pointer to the added image, or NULL if out of memory
+ */
+struct bootflow_img *bootflow_img_add(struct bootflow *bflow, const char *fname,
+ enum bootflow_img_t type, ulong addr,
+ ulong size);
+/**
+ * bootflow_get_seq() - Get the sequence number of a bootflow
+ *
+ * Bootflows are numbered by their position in the bootstd list.
+ *
+ * Return: Sequence number of bootflow (0 = first)
+ */
+int bootflow_get_seq(const struct bootflow *bflow);
+
#endif
diff --git a/include/bootmeth.h b/include/bootmeth.h
index a08ebf005ad..26de593a9a4 100644
--- a/include/bootmeth.h
+++ b/include/bootmeth.h
@@ -7,11 +7,10 @@
#ifndef __bootmeth_h
#define __bootmeth_h
+#include <bootflow.h>
#include <linux/bitops.h>
struct blk_desc;
-struct bootflow;
-struct bootflow_iter;
struct udevice;
/**
@@ -117,13 +116,15 @@ struct bootmeth_ops {
* @bflow: Bootflow providing info on where to read from
* @file_path: Path to file (may be absolute or relative)
* @addr: Address to load file
+ * @type: File type (IH_TYPE_...)
* @sizep: On entry provides the maximum permitted size; on exit
* returns the size of the file
* Return: 0 if OK, -ENOSPC if the file is too large for @sizep, other
* -ve value if something else goes wrong
*/
int (*read_file)(struct udevice *dev, struct bootflow *bflow,
- const char *file_path, ulong addr, ulong *sizep);
+ const char *file_path, ulong addr,
+ enum bootflow_img_t type, ulong *sizep);
#if CONFIG_IS_ENABLED(BOOTSTD_FULL)
/**
* readall() - read all files for a bootflow
@@ -245,13 +246,15 @@ int bootmeth_set_bootflow(struct udevice *dev, struct bootflow *bflow,
* @bflow: Bootflow providing info on where to read from
* @file_path: Path to file (may be absolute or relative)
* @addr: Address to load file
+ * @type: File type (IH_TYPE_...)
* @sizep: On entry provides the maximum permitted size; on exit
* returns the size of the file
* Return: 0 if OK, -ENOSPC if the file is too large for @sizep, other
* -ve value if something else goes wrong
*/
int bootmeth_read_file(struct udevice *dev, struct bootflow *bflow,
- const char *file_path, ulong addr, ulong *sizep);
+ const char *file_path, ulong addr,
+ enum bootflow_img_t type, ulong *sizep);
/**
* bootmeth_read_all() - read all bootflow files
@@ -365,10 +368,12 @@ int bootmeth_try_file(struct bootflow *bflow, struct blk_desc *desc,
* @bflow: Information about file to read
* @size_limit: Maximum file size to permit
* @align: Allocation alignment (1 for unaligned)
+ * @type: File type (IH_TYPE_...)
* Return: 0 if OK, -E2BIG if file is too large, -ENOMEM if out of memory,
* other -ve on other error
*/
-int bootmeth_alloc_file(struct bootflow *bflow, uint size_limit, uint align);
+int bootmeth_alloc_file(struct bootflow *bflow, uint size_limit, uint align,
+ enum bootflow_img_t type);
/**
* bootmeth_alloc_other() - Allocate and read a file for a bootflow
@@ -379,12 +384,13 @@ int bootmeth_alloc_file(struct bootflow *bflow, uint size_limit, uint align);
*
* @bflow: Information about file to read
* @fname: Filename to read from (within bootflow->subdir)
+ * @type: File type (IH_TYPE_...)
* @bufp: Returns a pointer to the allocated buffer
* @sizep: Returns the size of the buffer
* Return: 0 if OK, -ENOMEM if out of memory, other -ve on other error
*/
int bootmeth_alloc_other(struct bootflow *bflow, const char *fname,
- void **bufp, uint *sizep);
+ enum bootflow_img_t type, void **bufp, uint *sizep);
/**
* bootmeth_common_read_file() - Common handler for reading a file
@@ -395,11 +401,13 @@ int bootmeth_alloc_other(struct bootflow *bflow, const char *fname,
* @bflow: Bootflow information
* @file_path: Path to file
* @addr: Address to load file to
+ * @type: File type (IH_TYPE_...)
* @sizep: On entry, the maximum file size to accept, on exit the actual file
* size read
*/
int bootmeth_common_read_file(struct udevice *dev, struct bootflow *bflow,
- const char *file_path, ulong addr, ulong *sizep);
+ const char *file_path, ulong addr,
+ enum bootflow_img_t type, ulong *sizep);
/**
* bootmeth_get_bootflow() - Get a bootflow from a global bootmeth
diff --git a/include/bootstd.h b/include/bootstd.h
index ac756e98d84..3398e48e88b 100644
--- a/include/bootstd.h
+++ b/include/bootstd.h
@@ -9,6 +9,7 @@
#ifndef __bootstd_h
#define __bootstd_h
+#include <alist.h>
#include <dm/ofnode_decl.h>
#include <linux/list.h>
#include <linux/types.h>
@@ -30,7 +31,8 @@ struct udevice;
* terminated)
* @cur_bootdev: Currently selected bootdev (for commands)
* @cur_bootflow: Currently selected bootflow (for commands)
- * @glob_head: Head for the global list of all bootflows across all bootdevs
+ * @bootflows: (struct bootflow) Global list of all bootflows across all
+ * bootdevs
* @bootmeth_count: Number of bootmeth devices in @bootmeth_order
* @bootmeth_order: List of bootmeth devices to use, in order, NULL-terminated
* @vbe_bootmeth: Currently selected VBE bootmeth, NULL if none
@@ -44,7 +46,7 @@ struct bootstd_priv {
const char **env_order;
struct udevice *cur_bootdev;
struct bootflow *cur_bootflow;
- struct list_head glob_head;
+ struct alist bootflows;
int bootmeth_count;
struct udevice **bootmeth_order;
struct udevice *vbe_bootmeth;
@@ -90,6 +92,23 @@ const char *const *const bootstd_get_prefixes(struct udevice *dev);
int bootstd_get_priv(struct bootstd_priv **stdp);
/**
+ * bootstd_try_priv() - Try to get the (single) state for the bootstd system
+ *
+ * The state holds a global list of all bootflows that have been found. This
+ * function returns the state if available, but takes care not to create the
+ * device (or uclass) if it doesn't exist.
+ *
+ * This function is safe to use in the 'unbind' path. It will always return NULL
+ * unless the bootstd device is probed and ready, e.g. bootstd_get_priv() has
+ * previously been called.
+ *
+ * TODO([email protected]): Consider adding a bootstd pointer to global_data
+ *
+ * Return: pointer if the device exists, else NULL
+ */
+struct bootstd_priv *bootstd_try_priv(void);
+
+/**
* bootstd_clear_glob() - Clear the global list of bootflows
*
* This removes all bootflows globally and across all bootdevs.
@@ -105,4 +124,31 @@ void bootstd_clear_glob(void);
*/
int bootstd_prog_boot(void);
+/**
+ * bootstd_add_bootflow() - Add a bootflow to the global list
+ *
+ * All fields in @bflow must be set up. Note that @bflow->dev is used to add the
+ * bootflow to that device.
+ *
+ * The bootflow is also added to the global list of all bootflows
+ *
+ * @dev: Bootdev device to add to
+ * @bflow: Bootflow to add. Note that fields within bflow must be allocated
+ * since this function takes over ownership of these. This functions makes
+ * a copy of @bflow itself (without allocating its fields again), so the
+ * caller must dispose of the memory used by the @bflow pointer itself
+ * Return: element number in the list, if OK, -ENOMEM if out of memory
+ */
+int bootstd_add_bootflow(struct bootflow *bflow);
+
+/**
+ * bootstd_clear_bootflows_for_bootdev() - Clear bootflows from a bootdev
+ *
+ * Each bootdev maintains a list of discovered bootflows. This provides a
+ * way to clear it. These bootflows are removed from the global list too.
+ *
+ * @dev: bootdev device to update
+ */
+int bootstd_clear_bootflows_for_bootdev(struct udevice *dev);
+
#endif
diff --git a/include/pxe_utils.h b/include/pxe_utils.h
index 68ac40b64ad..0378f2889f7 100644
--- a/include/pxe_utils.h
+++ b/include/pxe_utils.h
@@ -3,6 +3,7 @@
#ifndef __PXE_UTILS_H
#define __PXE_UTILS_H
+#include <bootflow.h>
#include <linux/list.h>
/*
@@ -82,8 +83,19 @@ struct pxe_menu {
};
struct pxe_context;
+
+/**
+ * Read a file
+ *
+ * @ctx: PXE context
+ * @file_path: Full path to filename to read
+ * @file_addr: String containing the to which to read the file
+ * @type: File type
+ * @fileszeip: Returns file size
+ */
typedef int (*pxe_getfile_func)(struct pxe_context *ctx, const char *file_path,
- char *file_addr, ulong *filesizep);
+ char *file_addr, enum bootflow_img_t type,
+ ulong *filesizep);
/**
* struct pxe_context - context information for PXE parsing