iPXE
interface.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 #include <string.h>
27 #include <ipxe/interface.h>
28 
29 /** @file
30  *
31  * Object interfaces
32  *
33  */
34 
35 /*****************************************************************************
36  *
37  * The null interface
38  *
39  */
40 
41 /**
42  * Close null interface
43  *
44  * @v intf Null interface
45  * @v rc Reason for close
46  */
47 static void null_intf_close ( struct interface *intf __unused,
48  int rc __unused ) {
49 
50  /* Do nothing. In particular, do not call intf_restart(),
51  * since that would result in an infinite loop.
52  */
53 }
54 
55 /** Null interface operations */
56 static struct interface_operation null_intf_op[] = {
58 };
59 
60 /** Null interface descriptor */
63 
64 /** The null interface */
66 
67 /*****************************************************************************
68  *
69  * Object interface plumbing
70  *
71  */
72 
73 /**
74  * Plug an object interface into a new destination object interface
75  *
76  * @v intf Object interface
77  * @v dest New destination object interface
78  *
79  * The reference to the existing destination interface is dropped, a
80  * reference to the new destination interface is obtained, and the
81  * interface is updated to point to the new destination interface.
82  */
83 void intf_plug ( struct interface *intf, struct interface *dest ) {
84 
85  if ( intf == &null_intf )
86  return;
87 
88  DBGC ( INTF_COL ( intf ),
89  "INTF " INTF_INTF_FMT " replug to " INTF_FMT "\n",
90  INTF_INTF_DBG ( intf, intf->dest ), INTF_DBG ( dest ) );
91 
92  intf_get ( dest );
93  intf_put ( intf->dest );
94  intf->dest = dest;
95 }
96 
97 /**
98  * Plug two object interfaces together
99  *
100  * @v a Object interface A
101  * @v b Object interface B
102  *
103  * Plugs interface A into interface B, and interface B into interface
104  * A. (The basic plug() function is unidirectional; this function is
105  * merely a shorthand for two calls to plug(), hence the name.)
106  */
107 void intf_plug_plug ( struct interface *a, struct interface *b ) {
108  intf_plug ( a, b );
109  intf_plug ( b, a );
110 }
111 
112 /**
113  * Unplug an object interface
114  *
115  * @v intf Object interface
116  */
117 void intf_unplug ( struct interface *intf ) {
118  DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " unplug\n",
119  INTF_INTF_DBG ( intf, intf->dest ) );
120  intf_put ( intf->dest );
121  intf->dest = &null_intf;
122 }
123 
124 /**
125  * Ignore all further operations on an object interface
126  *
127  * @v intf Object interface
128  */
129 void intf_nullify ( struct interface *intf ) {
130  intf->desc = &null_intf_desc;
131 }
132 
133 /**
134  * Increment reference count on an object interface
135  *
136  * @v intf Object interface
137  * @ret intf Object interface
138  */
139 struct interface * intf_get ( struct interface *intf ) {
140  ref_get ( intf->refcnt );
141  return intf;
142 }
143 
144 /**
145  * Decrement reference count on an object interface
146  *
147  * @v intf Object interface
148  */
149 void intf_put ( struct interface *intf ) {
150  ref_put ( intf->refcnt );
151 }
152 
153 /**
154  * Get pointer to object containing object interface
155  *
156  * @v intf Object interface
157  * @ret object Containing object
158  */
159 void * intf_object ( struct interface *intf ) {
160  return ( ( ( void * ) intf ) - intf->desc->offset );
161 }
162 
163 /**
164  * Get pass-through interface
165  *
166  * @v intf Object interface
167  * @ret passthru Pass-through interface, or NULL
168  */
169 static struct interface * intf_get_passthru ( struct interface *intf ) {
170  struct interface_descriptor *desc = intf->desc;
171 
172  if ( desc->passthru_offset ) {
173  return ( ( ( void * ) intf ) + desc->passthru_offset );
174  } else {
175  return NULL;
176  }
177 }
178 
179 /**
180  * Get object interface destination and operation method (without pass-through)
181  *
182  * @v intf Object interface
183  * @v type Operation type
184  * @ret dest Destination interface
185  * @ret func Implementing method, or NULL
186  */
188  void *type,
189  struct interface **dest ) {
190  struct interface_descriptor *desc;
191  struct interface_operation *op;
192  unsigned int i;
193 
194  *dest = intf_get ( intf->dest );
195  desc = (*dest)->desc;
196  for ( i = desc->num_op, op = desc->op ; i ; i--, op++ ) {
197  if ( op->type == type )
198  return op->func;
199  }
200 
201  return NULL;
202 }
203 
204 /**
205  * Get object interface destination and operation method
206  *
207  * @v intf Object interface
208  * @v type Operation type
209  * @ret dest Destination interface
210  * @ret func Implementing method, or NULL
211  */
212 void * intf_get_dest_op_untyped ( struct interface *intf, void *type,
213  struct interface **dest ) {
214  void *func;
215 
216  while ( 1 ) {
217 
218  /* Search for an implementing method provided by the
219  * current destination interface.
220  */
222  if ( func )
223  return func;
224 
225  /* Pass through to the underlying interface, if applicable */
226  if ( ! ( intf = intf_get_passthru ( *dest ) ) )
227  return NULL;
228  intf_put ( *dest );
229  }
230 }
231 
232 /*****************************************************************************
233  *
234  * Generic interface operations
235  *
236  */
237 
238 /**
239  * Close an object interface
240  *
241  * @v intf Object interface
242  * @v rc Reason for close
243  *
244  * Note that this function merely informs the destination object that
245  * the interface is about to be closed; it doesn't actually disconnect
246  * the interface. In most cases, you probably want to use
247  * intf_shutdown() or intf_restart() instead.
248  */
249 void intf_close ( struct interface *intf, int rc ) {
250  struct interface *dest;
251  intf_close_TYPE ( void * ) *op =
252  intf_get_dest_op ( intf, intf_close, &dest );
253  void *object = intf_object ( dest );
254 
255  DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " close (%s)\n",
256  INTF_INTF_DBG ( intf, dest ), strerror ( rc ) );
257 
258  if ( op ) {
259  op ( object, rc );
260  } else {
261  /* Default is to restart the interface */
262  intf_restart ( dest, rc );
263  }
264 
265  intf_put ( dest );
266 }
267 
268 /**
269  * Shut down an object interface
270  *
271  * @v intf Object interface
272  * @v rc Reason for close
273  *
274  * Blocks further operations from being received via the interface,
275  * executes a close operation on the destination interface, and
276  * unplugs the interface.
277  */
278 void intf_shutdown ( struct interface *intf, int rc ) {
279  struct interface tmp;
280 
281  DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " shutting down (%s)\n",
282  INTF_DBG ( intf ), strerror ( rc ) );
283 
284  /* Block further operations */
285  intf_nullify ( intf );
286 
287  /* Transfer destination to temporary interface */
288  tmp.dest = intf->dest;
289  intf->dest = &null_intf;
290 
291  /* Notify destination of close via temporary interface */
292  intf_close ( &tmp, rc );
293 
294  /* Unplug temporary interface */
295  intf_unplug ( &tmp );
296 }
297 
298 /**
299  * Shut down multiple object interfaces
300  *
301  * @v intfs Object interfaces
302  * @v rc Reason for close
303  */
304 void intfs_vshutdown ( va_list intfs, int rc ) {
305  struct interface *intf;
306  va_list tmp;
307 
308  /* Nullify all interfaces to avoid potential loops */
309  va_copy ( tmp, intfs );
310  while ( ( intf = va_arg ( tmp, struct interface * ) ) )
311  intf_nullify ( intf );
312  va_end ( tmp );
313 
314  /* Shut down all interfaces */
315  while ( ( intf = va_arg ( intfs, struct interface * ) ) )
316  intf_shutdown ( intf, rc );
317 }
318 
319 /**
320  * Shut down multiple object interfaces
321  *
322  * @v rc Reason for close
323  * @v ... Object interfaces
324  */
325 void intfs_shutdown ( int rc, ... ) {
326  va_list intfs;
327 
328  va_start ( intfs, rc );
329  intfs_vshutdown ( intfs, rc );
330  va_end ( intfs );
331 }
332 
333 /**
334  * Shut down and restart an object interface
335  *
336  * @v intf Object interface
337  * @v rc Reason for close
338  *
339  * Shuts down the interface, then unblocks operations that were
340  * blocked during shutdown.
341  */
342 void intf_restart ( struct interface *intf, int rc ) {
343 
344  /* Shut down the interface */
345  intf_shutdown ( intf, rc );
346 
347  DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " restarting\n",
348  INTF_DBG ( intf ) );
349 
350  /* Restore the interface descriptor. Must be done after
351  * shutdown (rather than inhibiting intf_shutdown() from
352  * nullifying the descriptor) in order to avoid a potential
353  * infinite loop as the intf_close() operations on each side
354  * of the link call each other recursively.
355  */
356  intf_reinit ( intf );
357 }
358 
359 /**
360  * Shut down and restart multiple object interfaces
361  *
362  * @v intfs Object interfaces
363  * @v rc Reason for close
364  */
365 void intfs_vrestart ( va_list intfs, int rc ) {
366  struct interface *intf;
367  va_list tmp;
368 
369  /* Shut down all interfaces */
370  va_copy ( tmp, intfs );
371  intfs_vshutdown ( tmp, rc );
372  va_end ( tmp );
373 
374  /* Reinitialise all interfaces */
375  while ( ( intf = va_arg ( intfs, struct interface * ) ) )
376  intf_reinit ( intf );
377 }
378 
379 /**
380  * Shut down and restart multiple object interfaces
381  *
382  * @v rc Reason for close
383  * @v ... Object interfaces
384  */
385 void intfs_restart ( int rc, ... ) {
386  va_list intfs;
387 
388  va_start ( intfs, rc );
389  intfs_vrestart ( intfs, rc );
390  va_end ( intfs );
391 }
392 
393 /**
394  * Insert a filter interface
395  *
396  * @v intf Object interface
397  * @v upper Upper end of filter
398  * @v lower Lower end of filter
399  */
400 void intf_insert ( struct interface *intf, struct interface *upper,
401  struct interface *lower ) {
402  struct interface *dest = intf->dest;
403 
404  intf_get ( dest );
405  intf_plug_plug ( intf, upper );
406  intf_plug_plug ( lower, dest );
407  intf_put ( dest );
408 }
409 
410 /**
411  * Poke an object interface
412  *
413  * @v intf Object interface
414  * @v type Operation type
415  *
416  * This is a helper function to implement methods which take no
417  * parameters and return nothing.
418  */
419 void intf_poke ( struct interface *intf,
420  void ( type ) ( struct interface *intf ) ) {
421  struct interface *dest;
422  intf_poke_TYPE ( void * ) *op =
423  intf_get_dest_op_untyped ( intf, type, &dest );
424  void *object = intf_object ( dest );
425 
426  if ( op ) {
427  op ( object );
428  } else {
429  /* Default is to do nothing */
430  }
431 
432  intf_put ( dest );
433 }
static struct interface * intf_get_passthru(struct interface *intf)
Get pass-through interface.
Definition: interface.c:169
struct interface * intf_get(struct interface *intf)
Increment reference count on an object interface.
Definition: interface.c:139
An object interface operation.
Definition: interface.h:17
void * intf_get_dest_op_untyped(struct interface *intf, void *type, struct interface **dest)
Get object interface destination and operation method.
Definition: interface.c:212
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition: interface.c:249
#define INTF_INTF_FMT
printf() format string for INTF_INTF_DBG()
Definition: interface.h:257
struct interface null_intf
The null interface.
Definition: interface.c:65
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition: interface.c:342
#define va_end(ap)
Definition: stdarg.h:9
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition: interface.c:278
#define INTF_DBG(intf)
printf() arguments for representing an object interface
Definition: interface.h:254
struct interface_descriptor null_intf_desc
Null interface descriptor.
Definition: interface.c:61
#define INTF_INTF_DBG(intf, dest)
printf() arguments for representing an object interface pair
Definition: interface.h:266
#define INTF_INIT(descriptor)
Initialise a static object interface.
Definition: interface.h:204
uint32_t type
Operating system type.
Definition: ena.h:12
#define INTF_COL(intf)
Find debugging colourisation for an object interface.
Definition: interface.h:243
#define DBGC(...)
Definition: compiler.h:505
static void null_intf_close(struct interface *intf __unused, int rc __unused)
Close null interface.
Definition: interface.c:47
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
Definition: interface.c:107
#define INTF_DESC_PURE(operations)
Define an object interface descriptor for a pure-interface object.
Definition: interface.h:115
#define va_copy(dest, src)
Definition: stdarg.h:10
void intfs_shutdown(int rc,...)
Shut down multiple object interfaces.
Definition: interface.c:325
void intfs_restart(int rc,...)
Shut down and restart multiple object interfaces.
Definition: interface.c:385
uint32_t a
Definition: md4.c:28
void * intf_object(struct interface *intf)
Get pointer to object containing object interface.
Definition: interface.c:159
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
void * func
Implementing method.
Definition: interface.h:21
unsigned int num_op
Number of interface operations.
Definition: interface.h:59
struct interface * dest
Destination object interface.
Definition: interface.h:133
struct interface_operation * op
Object interface operations.
Definition: interface.h:61
#define va_arg(ap, type)
Definition: stdarg.h:8
An object interface.
Definition: interface.h:124
ssize_t passthru_offset
Offset to pass-through interface, if present.
Definition: interface.h:63
Object interfaces.
static void * dest
Definition: strings.h:176
void intf_unplug(struct interface *intf)
Unplug an object interface.
Definition: interface.c:117
An object interface descriptor.
Definition: interface.h:55
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
#define ref_get(refcnt)
Get additional reference to object.
Definition: refcnt.h:92
uint8_t * tmp
Definition: entropy.h:156
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition: interface.h:32
#define intf_poke_TYPE(object_type)
Definition: interface.h:177
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
static uint16_t struct vmbus_xfer_pages_operations * op
Definition: netvsc.h:327
void intf_insert(struct interface *intf, struct interface *upper, struct interface *lower)
Insert a filter interface.
Definition: interface.c:400
void intf_nullify(struct interface *intf)
Ignore all further operations on an object interface.
Definition: interface.c:129
__builtin_va_list va_list
Definition: stdarg.h:6
static struct interface_operation null_intf_op[]
Null interface operations.
Definition: interface.c:56
void intfs_vshutdown(va_list intfs, int rc)
Shut down multiple object interfaces.
Definition: interface.c:304
uint32_t b
Definition: md4.c:29
void intf_put(struct interface *intf)
Decrement reference count on an object interface.
Definition: interface.c:149
void * intf_get_dest_op_no_passthru_untyped(struct interface *intf, void *type, struct interface **dest)
Get object interface destination and operation method (without pass-through)
Definition: interface.c:187
struct interface_descriptor * desc
Interface descriptor.
Definition: interface.h:141
struct refcnt * refcnt
Reference counter.
Definition: interface.h:139
#define va_start(ap, last)
Definition: stdarg.h:7
void intfs_vrestart(va_list intfs, int rc)
Shut down and restart multiple object interfaces.
Definition: interface.c:365
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
void intf_poke(struct interface *intf, void(type)(struct interface *intf))
Poke an object interface.
Definition: interface.c:419
String functions.
#define intf_get_dest_op(intf, type, dest)
Get object interface destination and operation method.
Definition: interface.h:231
#define intf_close_TYPE(object_type)
Definition: interface.h:163
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:106
void intf_plug(struct interface *intf, struct interface *dest)
Plug an object interface into a new destination object interface.
Definition: interface.c:83
#define INTF_FMT
printf() format string for INTF_DBG()
Definition: interface.h:246
static void intf_reinit(struct interface *intf)
Reinitialise an object interface.
Definition: interface.h:273