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