1  /* SPDX-License-Identifier: GPL-2.0 */
2  /* Copyright (c) Meta Platforms, Inc. and affiliates. */
3  
4  #ifndef _FBNIC_TLV_H_
5  #define _FBNIC_TLV_H_
6  
7  #include <asm/byteorder.h>
8  #include <linux/bits.h>
9  #include <linux/const.h>
10  #include <linux/types.h>
11  
12  #define FBNIC_TLV_MSG_ALIGN(len)	ALIGN(len, sizeof(u32))
13  #define FBNIC_TLV_MSG_SIZE(len)		\
14  		(FBNIC_TLV_MSG_ALIGN(len) / sizeof(u32))
15  
16  /* TLV Header Format
17   *    3			  2		      1
18   *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
19   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
20   * |		Length		   |M|I|RSV|	   Type / ID	   |
21   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
22   *
23   * The TLV header format described above will be used for transferring
24   * messages between the host and the firmware. To ensure byte ordering
25   * we have defined all fields as being little endian.
26   * Type/ID: Identifier for message and/or attribute
27   * RSV: Reserved field for future use, likely as additional flags
28   * I: cannot_ignore flag, identifies if unrecognized attribute can be ignored
29   * M: is_msg, indicates that this is the start of a new message
30   * Length: Total length of message in dwords including header
31   *		or
32   *	   Total length of attribute in bytes including header
33   */
34  struct fbnic_tlv_hdr {
35  #if defined(__LITTLE_ENDIAN_BITFIELD)
36  	u16 type		: 12; /* 0 .. 11  Type / ID */
37  	u16 rsvd		: 2;  /* 12 .. 13 Reserved for future use */
38  	u16 cannot_ignore	: 1;  /* 14	  Attribute can be ignored */
39  	u16 is_msg		: 1;  /* 15	  Header belongs to message */
40  #elif defined(__BIG_ENDIAN_BITFIELD)
41  	u16 is_msg		: 1;  /* 15	  Header belongs to message */
42  	u16 cannot_ignore	: 1;  /* 14	  Attribute can be ignored */
43  	u16 rsvd		: 2;  /* 13 .. 12 Reserved for future use */
44  	u16 type		: 12; /* 11 .. 0  Type / ID */
45  #else
46  #error "Missing defines from byteorder.h"
47  #endif
48  	__le16 len;		/* 16 .. 32	length including TLV header */
49  };
50  
51  #define FBNIC_TLV_RESULTS_MAX		32
52  
53  struct fbnic_tlv_msg {
54  	struct fbnic_tlv_hdr	hdr;
55  	__le32			value[];
56  };
57  
58  #define FBNIC_TLV_MSG_ID_UNKNOWN		USHRT_MAX
59  
60  enum fbnic_tlv_type {
61  	FBNIC_TLV_STRING,
62  	FBNIC_TLV_FLAG,
63  	FBNIC_TLV_UNSIGNED,
64  	FBNIC_TLV_SIGNED,
65  	FBNIC_TLV_BINARY,
66  	FBNIC_TLV_NESTED,
67  	FBNIC_TLV_ARRAY,
68  	__FBNIC_TLV_MAX_TYPE
69  };
70  
71  /* TLV Index
72   * Defines the relationship between the attribute IDs and their types.
73   * For each entry in the index there will be a size and type associated
74   * with it so that we can use this to parse the data and verify it matches
75   * the expected layout.
76   */
77  struct fbnic_tlv_index {
78  	u16			id;
79  	u16			len;
80  	enum fbnic_tlv_type	type;
81  };
82  
83  #define TLV_MAX_DATA			(PAGE_SIZE - 512)
84  #define FBNIC_TLV_ATTR_ID_UNKNOWN	USHRT_MAX
85  #define FBNIC_TLV_ATTR_STRING(id, len)	{ id, len, FBNIC_TLV_STRING }
86  #define FBNIC_TLV_ATTR_FLAG(id)		{ id, 0, FBNIC_TLV_FLAG }
87  #define FBNIC_TLV_ATTR_U32(id)		{ id, sizeof(u32), FBNIC_TLV_UNSIGNED }
88  #define FBNIC_TLV_ATTR_U64(id)		{ id, sizeof(u64), FBNIC_TLV_UNSIGNED }
89  #define FBNIC_TLV_ATTR_S32(id)		{ id, sizeof(s32), FBNIC_TLV_SIGNED }
90  #define FBNIC_TLV_ATTR_S64(id)		{ id, sizeof(s64), FBNIC_TLV_SIGNED }
91  #define FBNIC_TLV_ATTR_MAC_ADDR(id)	{ id, ETH_ALEN, FBNIC_TLV_BINARY }
92  #define FBNIC_TLV_ATTR_NESTED(id)	{ id, 0, FBNIC_TLV_NESTED }
93  #define FBNIC_TLV_ATTR_ARRAY(id)	{ id, 0, FBNIC_TLV_ARRAY }
94  #define FBNIC_TLV_ATTR_RAW_DATA(id)	{ id, TLV_MAX_DATA, FBNIC_TLV_BINARY }
95  #define FBNIC_TLV_ATTR_LAST		{ FBNIC_TLV_ATTR_ID_UNKNOWN, 0, 0 }
96  
97  struct fbnic_tlv_parser {
98  	u16				id;
99  	const struct fbnic_tlv_index	*attr;
100  	int				(*func)(void *opaque,
101  						struct fbnic_tlv_msg **results);
102  };
103  
104  #define FBNIC_TLV_PARSER(id, attr, func) { FBNIC_TLV_MSG_ID_##id, attr, func }
105  
106  static inline void *
fbnic_tlv_attr_get_value_ptr(struct fbnic_tlv_msg * attr)107  fbnic_tlv_attr_get_value_ptr(struct fbnic_tlv_msg *attr)
108  {
109  	return (void *)&attr->value[0];
110  }
111  
fbnic_tlv_attr_get_bool(struct fbnic_tlv_msg * attr)112  static inline bool fbnic_tlv_attr_get_bool(struct fbnic_tlv_msg *attr)
113  {
114  	return !!attr;
115  }
116  
117  u64 fbnic_tlv_attr_get_unsigned(struct fbnic_tlv_msg *attr);
118  s64 fbnic_tlv_attr_get_signed(struct fbnic_tlv_msg *attr);
119  size_t fbnic_tlv_attr_get_string(struct fbnic_tlv_msg *attr, char *str,
120  				 size_t max_size);
121  
122  #define get_unsigned_result(id, location) \
123  do { \
124  	struct fbnic_tlv_msg *result = results[id]; \
125  	if (result) \
126  		location = fbnic_tlv_attr_get_unsigned(result); \
127  } while (0)
128  
129  #define get_signed_result(id, location) \
130  do { \
131  	struct fbnic_tlv_msg *result = results[id]; \
132  	if (result) \
133  		location = fbnic_tlv_attr_get_signed(result); \
134  } while (0)
135  
136  #define get_string_result(id, size, str, max_size) \
137  do { \
138  	struct fbnic_tlv_msg *result = results[id]; \
139  	if (result) \
140  		size = fbnic_tlv_attr_get_string(result, str, max_size); \
141  } while (0)
142  
143  #define get_bool(id) (!!(results[id]))
144  
145  struct fbnic_tlv_msg *fbnic_tlv_msg_alloc(u16 msg_id);
146  int fbnic_tlv_attr_put_flag(struct fbnic_tlv_msg *msg, const u16 attr_id);
147  int fbnic_tlv_attr_put_value(struct fbnic_tlv_msg *msg, const u16 attr_id,
148  			     const void *value, const int len);
149  int __fbnic_tlv_attr_put_int(struct fbnic_tlv_msg *msg, const u16 attr_id,
150  			     s64 value, const int len);
151  #define fbnic_tlv_attr_put_int(msg, attr_id, value) \
152  	__fbnic_tlv_attr_put_int(msg, attr_id, value, \
153  				 FBNIC_TLV_MSG_ALIGN(sizeof(value)))
154  int fbnic_tlv_attr_put_mac_addr(struct fbnic_tlv_msg *msg, const u16 attr_id,
155  				const u8 *mac_addr);
156  int fbnic_tlv_attr_put_string(struct fbnic_tlv_msg *msg, u16 attr_id,
157  			      const char *string);
158  struct fbnic_tlv_msg *fbnic_tlv_attr_nest_start(struct fbnic_tlv_msg *msg,
159  						u16 attr_id);
160  void fbnic_tlv_attr_nest_stop(struct fbnic_tlv_msg *msg);
161  void fbnic_tlv_attr_addr_copy(u8 *dest, struct fbnic_tlv_msg *src);
162  int fbnic_tlv_attr_parse_array(struct fbnic_tlv_msg *attr, int len,
163  			       struct fbnic_tlv_msg **results,
164  			       const struct fbnic_tlv_index *tlv_index,
165  			       u16 tlv_attr_id, size_t array_len);
166  int fbnic_tlv_attr_parse(struct fbnic_tlv_msg *attr, int len,
167  			 struct fbnic_tlv_msg **results,
168  			 const struct fbnic_tlv_index *tlv_index);
169  int fbnic_tlv_msg_parse(void *opaque, struct fbnic_tlv_msg *msg,
170  			const struct fbnic_tlv_parser *parser);
171  int fbnic_tlv_parser_error(void *opaque, struct fbnic_tlv_msg **results);
172  
173  #define FBNIC_TLV_MSG_ERROR \
174  	FBNIC_TLV_PARSER(UNKNOWN, NULL, fbnic_tlv_parser_error)
175  #endif /* _FBNIC_TLV_H_ */
176