1 #ifndef _IPXE_INTERFACE_H
2 #define _IPXE_INTERFACE_H
3 
4 /** @file
5  *
6  * Object interfaces
7  *
8  */
9 
10 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11 
12 #include <stddef.h>
13 #include <stdarg.h>
14 #include <ipxe/refcnt.h>
15 
16 /** An object interface operation */
17 struct interface_operation {
18 	/** Operation type */
19 	void *type;
20 	/** Implementing method */
21 	void *func;
22 };
23 
24 /**
25  * Define an object interface operation
26  *
27  * @v op_type		Operation type
28  * @v object_type	Implementing method's expected object type
29  * @v op_func		Implementing method
30  * @ret op		Object interface operation
31  */
32 #define INTF_OP( op_type, object_type, op_func ) {			      \
33 		.type = op_type,					      \
34 		.func = ( ( ( ( typeof ( op_func ) * ) NULL ) ==	      \
35 			    ( ( op_type ## _TYPE ( object_type ) * ) NULL ) ) \
36 			  ? op_func : op_func ),			      \
37 	}
38 
39 /**
40  * Define an unused object interface operation
41  *
42  * @v op_type		Operation type
43  * @v object_type	Implementing method's expected object type
44  * @v op_func		Implementing method
45  * @ret op		Object interface operation
46  */
47 #define UNUSED_INTF_OP( op_type, object_type, op_func ) {		      \
48 		.type = NULL,						      \
49 		.func = ( ( ( ( typeof ( op_func ) * ) NULL ) ==	      \
50 			    ( ( op_type ## _TYPE ( object_type ) * ) NULL ) ) \
51 			  ? NULL : NULL ),				      \
52 	}
53 
54 /** An object interface descriptor */
55 struct interface_descriptor {
56 	/** Offset of interface within containing object */
57 	size_t offset;
58 	/** Number of interface operations */
59 	unsigned int num_op;
60 	/** Object interface operations */
61 	struct interface_operation *op;
62 	/** Offset to pass-through interface, if present */
63 	ssize_t passthru_offset;
64 };
65 
66 #define intf_offset( object_type, intf )				      \
67 	( ( ( ( typeof ( ( ( object_type * ) NULL )->intf ) * ) NULL )	      \
68 	    == ( ( struct interface * ) NULL ) )			      \
69 	  ? offsetof ( object_type, intf )				      \
70 	  : offsetof ( object_type, intf ) )
71 
72 /**
73  * Define an object interface descriptor
74  *
75  * @v object_type	Containing object data type
76  * @v intf		Interface name (i.e. field within object data type)
77  * @v operations	Object interface operations array
78  * @ret desc		Object interface descriptor
79  */
80 #define INTF_DESC( object_type, intf, operations ) {			      \
81 		.offset = intf_offset ( object_type, intf ),		      \
82 		.op = operations,					      \
83 		.num_op = ( sizeof ( operations ) /			      \
84 			    sizeof ( operations[0] ) ),			      \
85 		.passthru_offset = 0,					      \
86 	}
87 
88 /**
89  * Define an object interface descriptor with pass-through interface
90  *
91  * @v object_type	Containing object data type
92  * @v intf		Interface name (i.e. field within object data type)
93  * @v operations	Object interface operations array
94  * @v passthru		Pass-through interface name
95  * @ret desc		Object interface descriptor
96  */
97 #define INTF_DESC_PASSTHRU( object_type, intf, operations, passthru ) {	      \
98 		.offset = offsetof ( object_type, intf ),		      \
99 		.op = operations,					      \
100 		.num_op = ( sizeof ( operations ) /			      \
101 			    sizeof ( operations[0] ) ),			      \
102 		.passthru_offset = ( intf_offset ( object_type, passthru ) -  \
103 				     intf_offset ( object_type, intf ) ),     \
104 	}
105 
106 /**
107  * Define an object interface descriptor for a pure-interface object
108  *
109  * @v operations	Object interface operations array
110  * @ret desc		Object interface descriptor
111  *
112  * A pure-interface object is an object that consists solely of a
113  * single interface.
114  */
115 #define INTF_DESC_PURE( operations ) {					      \
116 		.offset = 0,						      \
117 		.op = operations,					      \
118 		.num_op = ( sizeof ( operations ) /			      \
119 			    sizeof ( operations[0] ) ),			      \
120 		.passthru_offset = 0,					      \
121 	}
122 
123 /** An object interface */
124 struct interface {
125 	/** Destination object interface
126 	 *
127 	 * When the containing object invokes an operation on this
128 	 * interface, it will be executed by the destination object.
129 	 *
130 	 * This pointer may never be NULL.  When the interface is
131 	 * unplugged, it should point to the null interface.
132 	 */
133 	struct interface *dest;
134 	/** Reference counter
135 	 *
136 	 * If this interface is not part of a reference-counted
137 	 * object, this field may be NULL.
138 	 */
139 	struct refcnt *refcnt;
140 	/** Interface descriptor */
141 	struct interface_descriptor *desc;
142 	/** Original interface descriptor
143 	 *
144 	 * Used by intf_reinit().
145 	 */
146 	struct interface_descriptor *original;
147 };
148 
149 extern void intf_plug ( struct interface *intf, struct interface *dest );
150 extern void intf_plug_plug ( struct interface *a, struct interface *b );
151 extern void intf_unplug ( struct interface *intf );
152 extern void intf_nullify ( struct interface *intf );
153 extern struct interface * intf_get ( struct interface *intf );
154 extern void intf_put ( struct interface *intf );
155 extern void * __attribute__ (( pure )) intf_object ( struct interface *intf );
156 extern void * intf_get_dest_op_no_passthru_untyped ( struct interface *intf,
157 						     void *type,
158 						     struct interface **dest );
159 extern void * intf_get_dest_op_untyped ( struct interface *intf, void *type,
160 					 struct interface **dest );
161 
162 extern void intf_close ( struct interface *intf, int rc );
163 #define intf_close_TYPE( object_type ) \
164 	typeof ( void ( object_type, int rc ) )
165 
166 extern void intf_shutdown ( struct interface *intf, int rc );
167 extern void intfs_vshutdown ( va_list intfs, int rc );
168 extern void intfs_shutdown ( int rc, ... ) __attribute__ (( sentinel ));
169 extern void intf_restart ( struct interface *intf, int rc );
170 extern void intfs_vrestart ( va_list intfs, int rc );
171 extern void intfs_restart ( int rc, ... ) __attribute__ (( sentinel ));
172 extern void intf_insert ( struct interface *intf, struct interface *upper,
173 			  struct interface *lower );
174 
175 extern void intf_poke ( struct interface *intf,
176 			void ( type ) ( struct interface *intf ) );
177 #define intf_poke_TYPE( object_type ) \
178 	typeof ( void ( object_type ) )
179 
180 extern struct interface_descriptor null_intf_desc;
181 extern struct interface null_intf;
182 
183 /**
184  * Initialise an object interface
185  *
186  * @v intf		Object interface
187  * @v desc		Object interface descriptor
188  * @v refcnt		Containing object reference counter, or NULL
189  */
intf_init(struct interface * intf,struct interface_descriptor * desc,struct refcnt * refcnt)190 static inline void intf_init ( struct interface *intf,
191 			       struct interface_descriptor *desc,
192 			       struct refcnt *refcnt ) {
193 	intf->dest = &null_intf;
194 	intf->refcnt = refcnt;
195 	intf->desc = desc;
196 	intf->original = desc;
197 }
198 
199 /**
200  * Initialise a static object interface
201  *
202  * @v descriptor	Object interface descriptor
203  */
204 #define INTF_INIT( descriptor ) {		\
205 		.dest = &null_intf,		\
206 		.refcnt = NULL,			\
207 		.desc = &(descriptor),		\
208 		.original = &(descriptor),	\
209 	}
210 
211 /**
212  * Get object interface destination and operation method (without pass-through)
213  *
214  * @v intf		Object interface
215  * @v type		Operation type
216  * @ret dest		Destination interface
217  * @ret func		Implementing method, or NULL
218  */
219 #define intf_get_dest_op_no_passthru( intf, type, dest )		\
220 	( ( type ## _TYPE ( void * ) * )				\
221 	  intf_get_dest_op_no_passthru_untyped ( intf, type, dest ) )
222 
223 /**
224  * Get object interface destination and operation method
225  *
226  * @v intf		Object interface
227  * @v type		Operation type
228  * @ret dest		Destination interface
229  * @ret func		Implementing method, or NULL
230  */
231 #define intf_get_dest_op( intf, type, dest )				\
232 	( ( type ## _TYPE ( void * ) * )				\
233 	  intf_get_dest_op_untyped ( intf, type, dest ) )
234 
235 /**
236  * Find debugging colourisation for an object interface
237  *
238  * @v intf		Object interface
239  * @ret col		Debugging colourisation
240  *
241  * Use as the first argument to DBGC() or equivalent macro.
242  */
243 #define INTF_COL( intf ) intf_object ( intf )
244 
245 /** printf() format string for INTF_DBG() */
246 #define INTF_FMT "%p+%zx"
247 
248 /**
249  * printf() arguments for representing an object interface
250  *
251  * @v intf		Object interface
252  * @ret args		printf() argument list corresponding to INTF_FMT
253  */
254 #define INTF_DBG( intf ) intf_object ( intf ), (intf)->desc->offset
255 
256 /** printf() format string for INTF_INTF_DBG() */
257 #define INTF_INTF_FMT INTF_FMT "->" INTF_FMT
258 
259 /**
260  * printf() arguments for representing an object interface pair
261  *
262  * @v intf		Object interface
263  * @v dest		Destination object interface
264  * @ret args		printf() argument list corresponding to INTF_INTF_FMT
265  */
266 #define INTF_INTF_DBG( intf, dest ) INTF_DBG ( intf ), INTF_DBG ( dest )
267 
268 /**
269  * Reinitialise an object interface
270  *
271  * @v intf		Object interface
272  */
intf_reinit(struct interface * intf)273 static inline void intf_reinit ( struct interface *intf ) {
274 
275 	/* Restore original interface descriptor */
276 	intf->desc = intf->original;
277 }
278 
279 #endif /* _IPXE_INTERFACE_H */
280