aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2022-07-08 14:39:07 -0400
committerTom Rini <trini@konsulko.com>2022-07-08 14:39:07 -0400
commit9ff4ce8abc627b8696c9bd6fd726dd1dbf4b9a5c (patch)
treed28c5d99d4996b080ec0c38f24a0232d611ea847 /include
parent7bc0be96f79344d7b103dd64c31be0574f7b39e9 (diff)
parente87da5704ffa6fc782d93d137fa30a37a5df3566 (diff)
downloadu-boot-9ff4ce8abc627b8696c9bd6fd726dd1dbf4b9a5c.zip
u-boot-9ff4ce8abc627b8696c9bd6fd726dd1dbf4b9a5c.tar.gz
u-boot-9ff4ce8abc627b8696c9bd6fd726dd1dbf4b9a5c.tar.bz2
Merge tag 'dm-pull-28jun22' of https://source.denx.de/u-boot/custodians/u-boot-dm into next
nman external-symbol improvements Driver model memory-usage reporting patman test-reporting improvements Add bloblist design goals
Diffstat (limited to 'include')
-rw-r--r--include/binman_sym.h51
-rw-r--r--include/bloblist.h62
-rw-r--r--include/dm/device.h25
-rw-r--r--include/dm/ofnode.h66
-rw-r--r--include/dm/root.h45
-rw-r--r--include/dm/tag.h32
-rw-r--r--include/dm/test.h7
-rw-r--r--include/dm/util.h11
-rw-r--r--include/os.h7
-rw-r--r--include/spl.h2
10 files changed, 275 insertions, 33 deletions
diff --git a/include/binman_sym.h b/include/binman_sym.h
index 72e6765..528d7e4 100644
--- a/include/binman_sym.h
+++ b/include/binman_sym.h
@@ -11,9 +11,11 @@
#ifndef __BINMAN_SYM_H
#define __BINMAN_SYM_H
+/* BSYM in little endian, keep in sync with tools/binman/elf.py */
+#define BINMAN_SYM_MAGIC_VALUE (0x4d595342UL)
#define BINMAN_SYM_MISSING (-1UL)
-#ifdef CONFIG_BINMAN
+#if CONFIG_IS_ENABLED(BINMAN_SYMBOLS)
/**
* binman_symname() - Internal function to get a binman symbol name
@@ -63,6 +65,37 @@
section(".binman_sym")))
/**
+ * _binman_sym_magic - Internal magic symbol for validity checks
+ *
+ * When building images, binman fills in this symbol with the magic
+ * value #defined above. This is used to check at runtime if the
+ * symbol values were filled in and are OK to use.
+ */
+extern ulong _binman_sym_magic;
+
+/**
+ * DECLARE_BINMAN_MAGIC_SYM - Declare the internal magic symbol
+ *
+ * This macro declares the _binman_sym_magic symbol so that it exists.
+ * Declaring it here would cause errors during linking due to multiple
+ * definitions of the symbol.
+ */
+#define DECLARE_BINMAN_MAGIC_SYM \
+ ulong _binman_sym_magic \
+ __attribute__((aligned(4), section(".binman_sym")))
+
+/**
+ * BINMAN_SYMS_OK - Check if the symbol values are valid
+ *
+ * This macro checks if the magic symbol's value is filled properly,
+ * which indicates that other symbols are OK to use as well.
+ *
+ * Return: 1 if binman symbol values are usable, 0 if not
+ */
+#define BINMAN_SYMS_OK \
+ (*(ulong *)&_binman_sym_magic == BINMAN_SYM_MAGIC_VALUE)
+
+/**
* binman_sym() - Access a previously declared symbol
*
* This is used to get the value of a symbol. E.g.:
@@ -72,12 +105,16 @@
* @_type: Type f the symbol (e.g. unsigned long)
* @entry_name: Name of the entry to look for (e.g. 'u_boot_spl')
* @_prop_name: Property value to get from that entry (e.g. 'pos')
- * @returns value of that property (filled in by binman)
+ *
+ * Return: value of that property (filled in by binman), or
+ * BINMAN_SYM_MISSING if the value is unavailable
*/
#define binman_sym(_type, _entry_name, _prop_name) \
- (*(_type *)&binman_symname(_entry_name, _prop_name))
+ (BINMAN_SYMS_OK ? \
+ (*(_type *)&binman_symname(_entry_name, _prop_name)) : \
+ BINMAN_SYM_MISSING)
-#else /* !BINMAN */
+#else /* !CONFIG_IS_ENABLED(BINMAN_SYMBOLS) */
#define binman_sym_declare(_type, _entry_name, _prop_name)
@@ -85,8 +122,12 @@
#define binman_sym_extern(_type, _entry_name, _prop_name)
+#define DECLARE_BINMAN_MAGIC_SYM
+
+#define BINMAN_SYMS_OK (0)
+
#define binman_sym(_type, _entry_name, _prop_name) BINMAN_SYM_MISSING
-#endif /* BINMAN */
+#endif /* CONFIG_IS_ENABLED(BINMAN_SYMBOLS) */
#endif
diff --git a/include/bloblist.h b/include/bloblist.h
index d0e128a..9684bfd 100644
--- a/include/bloblist.h
+++ b/include/bloblist.h
@@ -3,8 +3,66 @@
* This provides a standard way of passing information between boot phases
* (TPL -> SPL -> U-Boot proper.)
*
- * A list of blobs of data, tagged with their owner. The list resides in memory
- * and can be updated by SPL, U-Boot, etc.
+ * It consists of a list of blobs of data, tagged with their owner / contents.
+ * The list resides in memory and can be updated by SPL, U-Boot, etc.
+ *
+ * Design goals for bloblist:
+ *
+ * 1. Small and efficient structure. This avoids UUIDs or 16-byte name fields,
+ * since a 32-bit tag provides enough space for all the tags we will even need.
+ * If UUIDs are desired, they can be added inside a particular blob.
+ *
+ * 2. Avoids use of pointers, so the structure can be relocated in memory. The
+ * data in each blob is inline, rather than using pointers.
+ *
+ * 3. Bloblist is designed to start small in TPL or SPL, when only a few things
+ * are needed, like the memory size or whether console output should be enabled.
+ * Then it can grow in U-Boot proper, e.g. to include space for ACPI tables.
+ *
+ * 4. The bloblist structure is simple enough that it can be implemented in a
+ * small amount of C code. The API does not require use of strings or UUIDs,
+ * which would add to code size. For Thumb-2 the code size needed in SPL is
+ * approximately 940 bytes (e.g. for chromebook_bob).
+ *
+ * 5. Bloblist uses 16-byte alignment internally and is designed to start on a
+ * 16-byte boundary. Its headers are multiples of 16 bytes. This makes it easier
+ * to deal with data structures which need this level of alignment, such as ACPI
+ * tables. For use in SPL and TPL the alignment can be relaxed, since it can be
+ * relocated to an aligned address in U-Boot proper.
+ *
+ * 6. Bloblist is designed to be passed to Linux as reserved memory. While linux
+ * doesn't understand the bloblist header, it can be passed the indivdual blobs.
+ * For example, ACPI tables can reside in a blob and the address of those is
+ * passed to Linux, without Linux ever being away of the existence of a
+ * bloblist. Having all the blobs contiguous in memory simplifies the
+ * reserved-memory space.
+ *
+ * 7. Bloblist tags are defined in the enum below. There is an area for
+ * project-specific stuff (e.g. U-Boot, TF-A) and vendor-specific stuff, e.g.
+ * something used only on a particular SoC. There is also a private area for
+ * temporary, local use.
+ *
+ * 8. Bloblist includes a simple checksum, so that each boot phase can update
+ * this and allow the next phase to check that all is well. While the bloblist
+ * is small, this is quite cheap to calculate. When it grows (e.g. in U-Boot\
+ * proper), the CPU is likely running faster, so it is not prohibitive. Having
+ * said that, U-Boot is often the last phase that uses bloblist, so calculating
+ * the checksum there may not be necessary.
+ *
+ * 9. It would be possible to extend bloblist to support a non-contiguous
+ * structure, e.g. by creating a blob type that points to the next bloblist.
+ * This does not seem necessary for now. It adds complexity and code. We can
+ * always just copy it.
+ *
+ * 10. Bloblist is designed for simple structures, those that can be defined by
+ * a single C struct. More complex structures should be passed in a device tree.
+ * There are some exceptions, chiefly the various binary structures that Intel
+ * is fond of creating. But device tree provides a dictionary-type format which
+ * is fairly efficient (for use in U-Boot proper and Linux at least), along with
+ * a schema and a good set of tools. New formats should be designed around
+ * device tree rather than creating new binary formats, unless they are needed
+ * early in boot (where libfdt's 3KB of overhead is too large) and are trival
+ * enough to be described by a C struct.
*
* Copyright 2018 Google, Inc
* Written by Simon Glass <sjg@chromium.org>
diff --git a/include/dm/device.h b/include/dm/device.h
index 5bdb106..12c6ba3 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -11,6 +11,7 @@
#define _DM_DEVICE_H
#include <dm/ofnode.h>
+#include <dm/tag.h>
#include <dm/uclass-id.h>
#include <fdtdec.h>
#include <linker_lists.h>
@@ -547,6 +548,30 @@ void *dev_get_parent_priv(const struct udevice *dev);
void *dev_get_uclass_priv(const struct udevice *dev);
/**
+ * dev_get_attach_ptr() - Get the value of an attached pointed tag
+ *
+ * The tag is assumed to hold a pointer, if it exists
+ *
+ * @dev: Device to look at
+ * @tag: Tag to access
+ * @return value of tag, or NULL if there is no tag of this type
+ */
+void *dev_get_attach_ptr(const struct udevice *dev, enum dm_tag_t tag);
+
+/**
+ * dev_get_attach_size() - Get the size of an attached tag
+ *
+ * Core tags have an automatic-allocation mechanism where the allocated size is
+ * defined by the device, parent or uclass. This returns the size associated
+ * with a particular tag
+ *
+ * @dev: Device to look at
+ * @tag: Tag to access
+ * @return size of auto-allocated data, 0 if none
+ */
+int dev_get_attach_size(const struct udevice *dev, enum dm_tag_t tag);
+
+/**
* dev_get_parent() - Get the parent of a device
*
* @child: Child to check
diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
index 2c4d72d..bb60433 100644
--- a/include/dm/ofnode.h
+++ b/include/dm/ofnode.h
@@ -1182,6 +1182,33 @@ int ofnode_write_string(ofnode node, const char *propname, const char *value);
int ofnode_set_enabled(ofnode node, bool value);
/**
+ * ofnode_get_phy_node() - Get PHY node for a MAC (if not fixed-link)
+ *
+ * This function parses PHY handle from the Ethernet controller's ofnode
+ * (trying all possible PHY handle property names), and returns the PHY ofnode.
+ *
+ * Before this is used, ofnode_phy_is_fixed_link() should be checked first, and
+ * if the result to that is true, this function should not be called.
+ *
+ * @eth_node: ofnode belonging to the Ethernet controller
+ * Return: ofnode of the PHY, if it exists, otherwise an invalid ofnode
+ */
+ofnode ofnode_get_phy_node(ofnode eth_node);
+
+/**
+ * ofnode_read_phy_mode() - Read PHY connection type from a MAC node
+ *
+ * This function parses the "phy-mode" / "phy-connection-type" property and
+ * returns the corresponding PHY interface type.
+ *
+ * @mac_node: ofnode containing the property
+ * Return: one of PHY_INTERFACE_MODE_* constants, PHY_INTERFACE_MODE_NA on
+ * error
+ */
+phy_interface_t ofnode_read_phy_mode(ofnode mac_node);
+
+#if CONFIG_IS_ENABLED(DM)
+/**
* ofnode_conf_read_bool() - Read a boolean value from the U-Boot config
*
* This reads a property from the /config node of the devicetree.
@@ -1218,30 +1245,21 @@ int ofnode_conf_read_int(const char *prop_name, int default_val);
*/
const char *ofnode_conf_read_str(const char *prop_name);
-/**
- * ofnode_get_phy_node() - Get PHY node for a MAC (if not fixed-link)
- *
- * This function parses PHY handle from the Ethernet controller's ofnode
- * (trying all possible PHY handle property names), and returns the PHY ofnode.
- *
- * Before this is used, ofnode_phy_is_fixed_link() should be checked first, and
- * if the result to that is true, this function should not be called.
- *
- * @eth_node: ofnode belonging to the Ethernet controller
- * Return: ofnode of the PHY, if it exists, otherwise an invalid ofnode
- */
-ofnode ofnode_get_phy_node(ofnode eth_node);
+#else /* CONFIG_DM */
+static inline bool ofnode_conf_read_bool(const char *prop_name)
+{
+ return false;
+}
-/**
- * ofnode_read_phy_mode() - Read PHY connection type from a MAC node
- *
- * This function parses the "phy-mode" / "phy-connection-type" property and
- * returns the corresponding PHY interface type.
- *
- * @mac_node: ofnode containing the property
- * Return: one of PHY_INTERFACE_MODE_* constants, PHY_INTERFACE_MODE_NA on
- * error
- */
-phy_interface_t ofnode_read_phy_mode(ofnode mac_node);
+static inline int ofnode_conf_read_int(const char *prop_name, int default_val)
+{
+ return default_val;
+}
+
+static inline const char *ofnode_conf_read_str(const char *prop_name)
+{
+ return NULL;
+}
+#endif /* CONFIG_DM */
#endif
diff --git a/include/dm/root.h b/include/dm/root.h
index e888fb9..b2f30a8 100644
--- a/include/dm/root.h
+++ b/include/dm/root.h
@@ -9,12 +9,50 @@
#ifndef _DM_ROOT_H_
#define _DM_ROOT_H_
+#include <dm/tag.h>
+
struct udevice;
/* Head of the uclass list if CONFIG_OF_PLATDATA_INST is enabled */
extern struct list_head uclass_head;
/**
+ * struct dm_stats - Information about driver model memory usage
+ *
+ * @total_size: All data
+ * @dev_count: Number of devices
+ * @dev_size: Size of all devices (just the struct udevice)
+ * @dev_name_size: Bytes used by device names
+ * @uc_count: Number of uclasses
+ * @uc_size: Size of all uclasses (just the struct uclass)
+ * @tag_count: Number of tags
+ * @tag_size: Bytes used by all tags
+ * @uc_attach_count: Number of uclasses with attached data (priv)
+ * @uc_attach_size: Total size of that attached data
+ * @attach_count_total: Total number of attached data items for all udevices and
+ * uclasses
+ * @attach_size_total: Total number of bytes of attached data
+ * @attach_count: Number of devices with attached, for each type
+ * @attach_size: Total number of bytes of attached data, for each type
+ */
+struct dm_stats {
+ int total_size;
+ int dev_count;
+ int dev_size;
+ int dev_name_size;
+ int uc_count;
+ int uc_size;
+ int tag_count;
+ int tag_size;
+ int uc_attach_count;
+ int uc_attach_size;
+ int attach_count_total;
+ int attach_size_total;
+ int attach_count[DM_TAG_ATTACH_COUNT];
+ int attach_size[DM_TAG_ATTACH_COUNT];
+};
+
+/**
* dm_root() - Return pointer to the top of the driver tree
*
* This function returns pointer to the root node of the driver tree,
@@ -141,4 +179,11 @@ static inline int dm_remove_devices_flags(uint flags) { return 0; }
*/
void dm_get_stats(int *device_countp, int *uclass_countp);
+/**
+ * dm_get_mem() - Get stats on memory usage in driver model
+ *
+ * @stats: Place to put the information
+ */
+void dm_get_mem(struct dm_stats *stats);
+
#endif
diff --git a/include/dm/tag.h b/include/dm/tag.h
index 54fc31e..745088f 100644
--- a/include/dm/tag.h
+++ b/include/dm/tag.h
@@ -10,11 +10,23 @@
#include <linux/list.h>
#include <linux/types.h>
+struct dm_stats;
struct udevice;
enum dm_tag_t {
+ /* Types of core tags that can be attached to devices */
+ DM_TAG_PLAT,
+ DM_TAG_PARENT_PLAT,
+ DM_TAG_UC_PLAT,
+
+ DM_TAG_PRIV,
+ DM_TAG_PARENT_PRIV,
+ DM_TAG_UC_PRIV,
+ DM_TAG_DRIVER_DATA,
+ DM_TAG_ATTACH_COUNT,
+
/* EFI_LOADER */
- DM_TAG_EFI = 0,
+ DM_TAG_EFI = DM_TAG_ATTACH_COUNT,
DM_TAG_COUNT,
};
@@ -107,4 +119,22 @@ int dev_tag_del(struct udevice *dev, enum dm_tag_t tag);
*/
int dev_tag_del_all(struct udevice *dev);
+/**
+ * dev_tag_collect_stats() - Collect information on driver model performance
+ *
+ * This collects information on how driver model is performing. For now it only
+ * includes memory usage
+ *
+ * @stats: Place to put the collected information
+ */
+void dev_tag_collect_stats(struct dm_stats *stats);
+
+/**
+ * tag_get_name() - Get the name of a tag
+ *
+ * @tag: Tag to look up, which must be valid
+ * Returns: Name of tag
+ */
+const char *tag_get_name(enum dm_tag_t tag);
+
#endif /* _DM_TAG_H */
diff --git a/include/dm/test.h b/include/dm/test.h
index 4919064..b593750 100644
--- a/include/dm/test.h
+++ b/include/dm/test.h
@@ -93,6 +93,13 @@ struct dm_test_uclass_priv {
};
/**
+ * struct dm_test_uclass_plat - private plat data for test uclass
+ */
+struct dm_test_uclass_plat {
+ char dummy[32];
+};
+
+/**
* struct dm_test_parent_data - parent's information on each child
*
* @sum: Test value used to check parent data works correctly
diff --git a/include/dm/util.h b/include/dm/util.h
index 4428f04..e10c606 100644
--- a/include/dm/util.h
+++ b/include/dm/util.h
@@ -6,6 +6,8 @@
#ifndef __DM_UTIL_H
#define __DM_UTIL_H
+struct dm_stats;
+
#if CONFIG_IS_ENABLED(DM_WARN)
#define dm_warn(fmt...) log(LOGC_DM, LOGL_WARNING, ##fmt)
#else
@@ -25,7 +27,7 @@ struct list_head;
int list_count_items(struct list_head *head);
/* Dump out a tree of all devices */
-void dm_dump_all(void);
+void dm_dump_tree(void);
/* Dump out a list of uclasses and their devices */
void dm_dump_uclass(void);
@@ -48,6 +50,13 @@ void dm_dump_driver_compat(void);
/* Dump out a list of drivers with static platform data */
void dm_dump_static_driver_info(void);
+/**
+ * dm_dump_mem() - Dump stats on memory usage in driver model
+ *
+ * @mem: Stats to dump
+ */
+void dm_dump_mem(struct dm_stats *stats);
+
#if CONFIG_IS_ENABLED(OF_PLATDATA_INST) && CONFIG_IS_ENABLED(READ_ONLY)
void *dm_priv_to_rw(void *priv);
#else
diff --git a/include/os.h b/include/os.h
index 10e198c..1481787 100644
--- a/include/os.h
+++ b/include/os.h
@@ -17,6 +17,13 @@ struct rtc_time;
struct sandbox_state;
/**
+ * os_printf() - print directly to OS console
+ *
+ * @format: format string
+ */
+int os_printf(const char *format, ...);
+
+/**
* Access to the OS read() system call
*
* @fd: File descriptor as returned by os_open()
diff --git a/include/spl.h b/include/spl.h
index cc78bc3..aac6648 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -288,6 +288,8 @@ binman_sym_extern(ulong, u_boot_any, image_pos);
binman_sym_extern(ulong, u_boot_any, size);
binman_sym_extern(ulong, u_boot_spl, image_pos);
binman_sym_extern(ulong, u_boot_spl, size);
+binman_sym_extern(ulong, u_boot_vpl, image_pos);
+binman_sym_extern(ulong, u_boot_vpl, size);
/**
* spl_get_image_pos() - get the image position of the next phase