Commit f91e9fba authored by Peter Bigot's avatar Peter Bigot Committed by Anas Nashif
Browse files

device: fix potential truncation of DT-derived device names



While using the encoded path to a device tree node guarantees a unique
identifier for the corresponding device there is a limit on the number
of characters of that name that can be captured when looking up a
device by name from user mode, and the path can exceed that limit.

Synthesize a unique name from the node dependency ordinal instead, and
update the gen_defines script to record the name associated with the
full path in the extern declaration.

Add a build-time check that no device is created with a name that
violates the user mode requirement.

Also update the network device DTS helper functions to use the same
inference for dev_name and label that the real one does, since they
bypass the real one.

Signed-off-by: default avatarPeter Bigot <peter.bigot@nordicsemi.no>
parent 0782f9c4
Loading
Loading
Loading
Loading
+19 −6
Original line number Diff line number Diff line
@@ -99,7 +99,8 @@ extern "C" {
 * since the API is not specified;
 *
 * @param dev_name Device name. This must be less than Z_DEVICE_MAX_NAME_LEN
 * characters in order to be looked up from user mode with device_get_binding().
 * characters (including terminating NUL) in order to be looked up from user
 * mode with device_get_binding().
 *
 * @param drv_name The name this instance of the driver exposes to
 * the system.
@@ -168,7 +169,7 @@ extern "C" {
 */
#define DEVICE_DT_DEFINE(node_id, init_fn, pm_control_fn,		\
			 data_ptr, cfg_ptr, level, prio, api_ptr)	\
	Z_DEVICE_DEFINE(node_id, node_id,				\
	Z_DEVICE_DEFINE(node_id, Z_DEVICE_DT_DEV_NAME(node_id),		\
			DT_PROP_OR(node_id, label, NULL), init_fn,	\
			pm_control_fn,					\
			data_ptr, cfg_ptr, level, prio, api_ptr)
@@ -202,7 +203,7 @@ extern "C" {
 * @return The expanded name of the device object created by
 * DEVICE_DT_DEFINE()
 */
#define DEVICE_DT_NAME_GET(node_id) DEVICE_NAME_GET(node_id)
#define DEVICE_DT_NAME_GET(node_id) DEVICE_NAME_GET(Z_DEVICE_DT_DEV_NAME(node_id))

/**
 * @def DEVICE_DT_GET
@@ -688,10 +689,20 @@ static inline int device_pm_put_sync(const struct device *dev) { return -ENOTSUP
 * @}
 */

/* Node paths can exceed the maximum size supported by device_get_binding() in user mode,
 * so synthesize a unique dev_name from the devicetree node.
 *
 * The ordinal used in this name can be mapped to the path by
 * examining zephyr/include/generated/device_extern.h header.  If the
 * format of this conversion changes, gen_defines should be updated to
 * match it.
 */
#define Z_DEVICE_DT_DEV_NAME(node_id) _CONCAT(dts_ord_, DT_DEP_ORD(node_id))

#define Z_DEVICE_DEFINE(node_id, dev_name, drv_name, init_fn, pm_control_fn, \
			data_ptr, cfg_ptr, level, prio, api_ptr)	\
	Z_DEVICE_DEFINE_PM(dev_name)					\
	COND_CODE_1(DT_NODE_EXISTS(dev_name), (), (static))		\
	COND_CODE_1(DT_NODE_EXISTS(node_id), (), (static))		\
		const Z_DECL_ALIGN(struct device)			\
		DEVICE_NAME_GET(dev_name) __used			\
	__attribute__((__section__(".device_" #level STRINGIFY(prio)))) = { \
@@ -701,8 +712,10 @@ static inline int device_pm_put_sync(const struct device *dev) { return -ENOTSUP
		.data = (data_ptr),					\
		Z_DEVICE_DEFINE_PM_INIT(dev_name, pm_control_fn)	\
	};								\
	Z_INIT_ENTRY_DEFINE(_CONCAT(__device_, dev_name), init_fn,	\
			    (&_CONCAT(__device_, dev_name)), level, prio)
	BUILD_ASSERT(sizeof(Z_STRINGIFY(drv_name)) <= Z_DEVICE_MAX_NAME_LEN, \
		     Z_STRINGIFY(DEVICE_GET_NAME(drv_name)) " too long"); \
	Z_INIT_ENTRY_DEFINE(DEVICE_NAME_GET(dev_name), init_fn,		\
		(&DEVICE_NAME_GET(dev_name)), level, prio)

#ifdef CONFIG_PM_DEVICE
#define Z_DEVICE_DEFINE_PM(dev_name)					\
+2 −1
Original line number Diff line number Diff line
@@ -711,7 +711,8 @@ static inline bool net_eth_get_vlan_status(struct net_if *iface)
 */
#define ETH_NET_DEVICE_DT_DEFINE(node_id, init_fn, pm_control_fn, data,	\
			       cfg, prio, api, mtu)			\
	Z_ETH_NET_DEVICE_INIT(node_id, node_id, DT_LABEL(node_id),	\
	Z_ETH_NET_DEVICE_INIT(node_id, Z_DEVICE_DT_DEV_NAME(node_id),	\
			      DT_PROP_OR(node_id, label, NULL),		\
			      init_fn, pm_control_fn, data, cfg, prio,	\
			      api, mtu)

+2 −1
Original line number Diff line number Diff line
@@ -2268,7 +2268,8 @@ struct net_if_api {
 */
#define NET_DEVICE_DT_DEFINE(node_id, init_fn, pm_control_fn, data, cfg,	\
			   prio, api, l2, l2_ctx_type, mtu)		\
	Z_NET_DEVICE_INIT(node_id, node_id, DT_LABEL(node_id), init_fn,	\
	Z_NET_DEVICE_INIT(node_id, Z_DEVICE_DT_DEV_NAME(node_id),	\
			  DT_PROP_OR(node_id, label, NULL), init_fn,	\
			  pm_control_fn, data, cfg, prio, api, l2,	\
			  l2_ctx_type, mtu)

+2 −1
Original line number Diff line number Diff line
@@ -132,7 +132,8 @@ def write_device_extern_header(device_header_out, edt):
        print("", file=dev_header_file)

        for node in sorted(edt.nodes, key=lambda node: node.dep_ordinal):
            print(f"extern const struct device DEVICE_DT_NAME_GET(DT_{node.z_path_id});", file=dev_header_file)
            print(f"extern const struct device DEVICE_DT_NAME_GET(DT_{node.z_path_id}); /* dts_ord_{node.dep_ordinal} */",
                  file=dev_header_file)

        print("", file=dev_header_file)
        print("#ifdef __cplusplus", file=dev_header_file)