iPXE
image.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006 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 <stddef.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <ctype.h>
31 #include <errno.h>
32 #include <assert.h>
33 #include <libgen.h>
34 #include <syslog.h>
35 #include <ipxe/list.h>
36 #include <ipxe/umalloc.h>
37 #include <ipxe/uri.h>
38 #include <ipxe/image.h>
39 
40 /** @file
41  *
42  * Executable images
43  *
44  */
45 
46 /* Disambiguate the various error causes */
47 #define EACCES_UNTRUSTED \
48  __einfo_error ( EINFO_EACCES_UNTRUSTED )
49 #define EINFO_EACCES_UNTRUSTED \
50  __einfo_uniqify ( EINFO_EACCES, 0x01, "Untrusted image" )
51 #define EACCES_PERMANENT \
52  __einfo_error ( EINFO_EACCES_PERMANENT )
53 #define EINFO_EACCES_PERMANENT \
54  __einfo_uniqify ( EINFO_EACCES, 0x02, "Trust requirement is permanent" )
55 
56 /** List of registered images */
58 
59 /** Image selected for execution */
61  .name = "SELECTED",
62 };
63 
64 /** Currently-executing image */
66  .name = "CURRENT",
67 };
68 
69 /** Current image trust requirement */
70 static int require_trusted_images = 0;
71 
72 /** Prevent changes to image trust requirement */
74 
75 /**
76  * Free executable image
77  *
78  * @v refcnt Reference counter
79  */
80 static void free_image ( struct refcnt *refcnt ) {
81  struct image *image = container_of ( refcnt, struct image, refcnt );
82  struct image_tag *tag;
83 
84  DBGC ( image, "IMAGE %s freed\n", image->name );
86  if ( tag->image == image )
87  tag->image = NULL;
88  }
89  free ( image->name );
90  free ( image->cmdline );
91  uri_put ( image->uri );
92  ufree ( image->data );
94  free ( image );
95 }
96 
97 /**
98  * Allocate executable image
99  *
100  * @v uri URI, or NULL
101  * @ret image Executable image
102  */
103 struct image * alloc_image ( struct uri *uri ) {
104  struct image *image;
105  int rc;
106 
107  /* Allocate image */
108  image = zalloc ( sizeof ( *image ) );
109  if ( ! image )
110  goto err_alloc;
111 
112  /* Initialise image */
114  if ( uri && ( ( rc = image_set_uri ( image, uri ) ) != 0 ) )
115  goto err_set_uri;
116 
117  return image;
118 
119  err_set_uri:
120  image_put ( image );
121  err_alloc:
122  return NULL;
123 }
124 
125 /**
126  * Set image URI
127  *
128  * @v image Image
129  * @v uri New image URI
130  * @ret rc Return status code
131  */
132 int image_set_uri ( struct image *image, struct uri *uri ) {
133  const char *name;
134  int rc;
135 
136  /* Set name, if image does not already have one */
137  if ( ! ( image->name && image->name[0] ) ) {
138  name = ( uri->path ? uri->path : uri->opaque );
139  if ( name ) {
140  name = basename ( ( char * ) name );
141  if ( ( rc = image_set_name ( image, name ) ) != 0 )
142  return rc;
143  }
144  }
145 
146  /* Update image URI */
147  uri_put ( image->uri );
148  image->uri = uri_get ( uri );
149 
150  return 0;
151 }
152 
153 /**
154  * Set image name
155  *
156  * @v image Image
157  * @v name New image name
158  * @ret rc Return status code
159  */
160 int image_set_name ( struct image *image, const char *name ) {
161  char *name_copy;
162 
163  /* Duplicate name */
164  name_copy = strdup ( name );
165  if ( ! name_copy )
166  return -ENOMEM;
167 
168  /* Replace existing name */
169  free ( image->name );
170  image->name = name_copy;
171 
172  return 0;
173 }
174 
175 /**
176  * Strip dot suffix from image name, if present
177  *
178  * @v image Image
179  * @ret sep Position of old dot separator, or NULL
180  */
181 char * image_strip_suffix ( struct image *image ) {
182  char *dot;
183 
184  /* Locate and strip suffix, if present */
185  if ( image->name &&
186  ( ( dot = strrchr ( image->name, '.' ) ) != NULL ) ) {
187  *dot = '\0';
188  return dot;
189  }
190 
191  return NULL;
192 }
193 
194 /**
195  * Set image command line
196  *
197  * @v image Image
198  * @v cmdline New image command line, or NULL
199  * @ret rc Return status code
200  */
201 int image_set_cmdline ( struct image *image, const char *cmdline ) {
202 
203  free ( image->cmdline );
204  image->cmdline = NULL;
205  if ( cmdline ) {
206  image->cmdline = strdup ( cmdline );
207  if ( ! image->cmdline )
208  return -ENOMEM;
209  }
210  return 0;
211 }
212 
213 /**
214  * Set image length
215  *
216  * @v image Image
217  * @v len Length of image data
218  * @ret rc Return status code
219  */
220 int image_set_len ( struct image *image, size_t len ) {
221  userptr_t new;
222 
223  /* (Re)allocate image data */
224  new = urealloc ( image->data, len );
225  if ( ! new )
226  return -ENOMEM;
227  image->data = new;
228  image->len = len;
229 
230  return 0;
231 }
232 
233 /**
234  * Set image data
235  *
236  * @v image Image
237  * @v data Image data
238  * @v len Length of image data
239  * @ret rc Return status code
240  */
241 int image_set_data ( struct image *image, userptr_t data, size_t len ) {
242  int rc;
243 
244  /* Set image length */
245  if ( ( rc = image_set_len ( image, len ) ) != 0 )
246  return rc;
247 
248  /* Copy in new image data */
249  memcpy_user ( image->data, 0, data, 0, len );
250 
251  return 0;
252 }
253 
254 /**
255  * Determine image type
256  *
257  * @v image Executable image
258  * @ret rc Return status code
259  */
260 static int image_probe ( struct image *image ) {
261  struct image_type *type;
262  int rc;
263 
264  /* Try each type in turn */
266  if ( ( rc = type->probe ( image ) ) == 0 ) {
267  image->type = type;
268  DBGC ( image, "IMAGE %s is %s\n",
269  image->name, type->name );
270  return 0;
271  }
272  DBGC ( image, "IMAGE %s is not %s: %s\n", image->name,
273  type->name, strerror ( rc ) );
274  }
275 
276  DBGC ( image, "IMAGE %s format not recognised\n", image->name );
277  return -ENOTSUP;
278 }
279 
280 /**
281  * Register executable image
282  *
283  * @v image Executable image
284  * @ret rc Return status code
285  */
286 int register_image ( struct image *image ) {
287  static unsigned int imgindex = 0;
288  char name[8]; /* "imgXXXX" */
289  int rc;
290 
291  /* Create image name if it doesn't already have one */
292  if ( ! image->name ) {
293  snprintf ( name, sizeof ( name ), "img%d", imgindex++ );
294  if ( ( rc = image_set_name ( image, name ) ) != 0 )
295  return rc;
296  }
297 
298  /* Add to image list */
299  image_get ( image );
301  list_add_tail ( &image->list, &images );
302  DBGC ( image, "IMAGE %s at [%lx,%lx) registered\n",
303  image->name, user_to_phys ( image->data, 0 ),
304  user_to_phys ( image->data, image->len ) );
305 
306  /* Try to detect image type, if applicable. Ignore failures,
307  * since we expect to handle some unrecognised images
308  * (e.g. kernel initrds, multiboot modules, random files
309  * provided via our EFI virtual filesystem, etc).
310  */
311  if ( ! image->type )
312  image_probe ( image );
313 
314  return 0;
315 }
316 
317 /**
318  * Unregister executable image
319  *
320  * @v image Executable image
321  */
322 void unregister_image ( struct image *image ) {
323 
324  /* Do nothing unless image is registered */
325  if ( ! ( image->flags & IMAGE_REGISTERED ) )
326  return;
327 
328  DBGC ( image, "IMAGE %s unregistered\n", image->name );
329  list_del ( &image->list );
331  image_put ( image );
332 }
333 
334 /**
335  * Find image by name
336  *
337  * @v name Image name
338  * @ret image Executable image, or NULL
339  */
340 struct image * find_image ( const char *name ) {
341  struct image *image;
342 
343  for_each_image ( image ) {
344  if ( strcmp ( image->name, name ) == 0 )
345  return image;
346  }
347 
348  return NULL;
349 }
350 
351 /**
352  * Find image by tag
353  *
354  * @v tag Image tag
355  * @ret image Executable image, or NULL
356  */
357 struct image * find_image_tag ( struct image_tag *tag ) {
358  struct image *image;
359 
360  for_each_image ( image ) {
361  if ( tag->image == image )
362  return image;
363  }
364 
365  return NULL;
366 }
367 
368 /**
369  * Execute image
370  *
371  * @v image Executable image
372  * @ret rc Return status code
373  *
374  * The image must already be registered. Note that executing an image
375  * may cause it to unregister itself. The caller must therefore
376  * assume that the image pointer becomes invalid.
377  */
378 int image_exec ( struct image *image ) {
379  struct image *saved_current_image;
380  struct image *replacement = NULL;
381  struct uri *old_cwuri;
382  int rc;
383 
384  /* Sanity check */
386 
387  /* Switch current working directory to be that of the image
388  * itself, if applicable
389  */
390  old_cwuri = uri_get ( cwuri );
391  if ( image->uri )
392  churi ( image->uri );
393 
394  /* Set as currently running image */
395  saved_current_image = image_tag ( image, &current_image );
396 
397  /* Take out a temporary reference to the image, so that it
398  * does not get freed when temporarily unregistered.
399  */
400  image_get ( image );
401 
402  /* Check that this image can be executed */
403  if ( ! ( image->type && image->type->exec ) ) {
404  rc = -ENOEXEC;
405  goto err;
406  }
407 
408  /* Check that image is trusted (if applicable) */
409  if ( require_trusted_images && ! ( image->flags & IMAGE_TRUSTED ) ) {
410  DBGC ( image, "IMAGE %s is not trusted\n", image->name );
411  rc = -EACCES_UNTRUSTED;
412  goto err;
413  }
414 
415  /* Record boot attempt */
416  syslog ( LOG_NOTICE, "Executing \"%s\"\n", image->name );
417 
418  /* Temporarily unregister the image during its execution */
420 
421  /* Try executing the image */
422  if ( ( rc = image->type->exec ( image ) ) != 0 ) {
423  DBGC ( image, "IMAGE %s could not execute: %s\n",
424  image->name, strerror ( rc ) );
425  /* Do not return yet; we still have clean-up to do */
426  }
427 
428  /* Record result of boot attempt */
429  if ( rc == 0 ) {
430  syslog ( LOG_NOTICE, "Execution of \"%s\" completed\n",
431  image->name );
432  } else {
433  syslog ( LOG_ERR, "Execution of \"%s\" failed: %s\n",
434  image->name, strerror ( rc ) );
435  }
436 
437  /* Re-register image (unless due to be replaced) */
438  if ( ! image->replacement )
439  register_image ( image );
440 
441  /* Pick up replacement image before we drop the original
442  * image's temporary reference. The replacement image must
443  * already be registered, so we don't need to hold a temporary
444  * reference (which would complicate the tail-recursion).
445  */
447  if ( replacement )
448  assert ( replacement->flags & IMAGE_REGISTERED );
449 
450  err:
451  /* Unregister image if applicable */
454 
455  /* Debug message for tail-recursion. Placed here because the
456  * image_put() may end up freeing the image.
457  */
458  if ( replacement ) {
459  DBGC ( image, "IMAGE %s replacing self with IMAGE %s\n",
460  image->name, replacement->name );
461  }
462 
463  /* Drop temporary reference to the original image */
464  image_put ( image );
465 
466  /* Restore previous currently-running image */
467  image_tag ( saved_current_image, &current_image );
468 
469  /* Reset current working directory */
470  churi ( old_cwuri );
471  uri_put ( old_cwuri );
472 
473  /* Tail-recurse into replacement image, if one exists */
474  if ( replacement )
475  return image_exec ( replacement );
476 
477  return rc;
478 }
479 
480 /**
481  * Set replacement image
482  *
483  * @v replacement Replacement image
484  * @ret rc Return status code
485  *
486  * The replacement image must already be registered, and must remain
487  * registered until the currently-executing image returns.
488  */
489 int image_replace ( struct image *replacement ) {
490  struct image *image = current_image.image;
491  int rc;
492 
493  /* Sanity check */
494  assert ( replacement->flags & IMAGE_REGISTERED );
495 
496  /* Fail unless there is a currently-executing image */
497  if ( ! image ) {
498  rc = -ENOTTY;
499  DBGC ( replacement, "IMAGE %s cannot replace non-existent "
500  "image: %s\n", replacement->name, strerror ( rc ) );
501  return rc;
502  }
503 
504  /* Check that the replacement image can be executed */
505  if ( ! ( replacement->type && replacement->type->exec ) )
506  return -ENOEXEC;
507 
508  /* Clear any existing replacement */
510 
511  /* Set replacement */
513  DBGC ( image, "IMAGE %s will replace self with IMAGE %s\n",
514  image->name, replacement->name );
515 
516  return 0;
517 }
518 
519 /**
520  * Select image for execution
521  *
522  * @v image Executable image
523  * @ret rc Return status code
524  */
525 int image_select ( struct image *image ) {
526 
527  /* Check that this image can be executed */
528  if ( ! ( image->type && image->type->exec ) )
529  return -ENOEXEC;
530 
531  /* Mark image as selected */
533 
534  return 0;
535 }
536 
537 /**
538  * Change image trust requirement
539  *
540  * @v require_trusted Require trusted images
541  * @v permanent Make trust requirement permanent
542  * @ret rc Return status code
543  */
544 int image_set_trust ( int require_trusted, int permanent ) {
545 
546  /* Update trust requirement, if permitted to do so */
548  require_trusted_images = require_trusted;
550  }
551 
552  /* Fail if we attempted to change the trust requirement but
553  * were not permitted to do so.
554  */
555  if ( require_trusted_images != require_trusted )
556  return -EACCES_PERMANENT;
557 
558  return 0;
559 }
560 
561 /**
562  * Create registered image from block of memory
563  *
564  * @v name Name
565  * @v data Image data
566  * @v len Length
567  * @ret image Image, or NULL on error
568  */
569 struct image * image_memory ( const char *name, userptr_t data, size_t len ) {
570  struct image *image;
571  int rc;
572 
573  /* Allocate image */
574  image = alloc_image ( NULL );
575  if ( ! image ) {
576  rc = -ENOMEM;
577  goto err_alloc_image;
578  }
579 
580  /* Set name */
581  if ( ( rc = image_set_name ( image, name ) ) != 0 )
582  goto err_set_name;
583 
584  /* Set data */
585  if ( ( rc = image_set_data ( image, data, len ) ) != 0 )
586  goto err_set_data;
587 
588  /* Register image */
589  if ( ( rc = register_image ( image ) ) != 0 )
590  goto err_register;
591 
592  /* Drop local reference to image */
593  image_put ( image );
594 
595  return image;
596 
597  err_register:
598  err_set_data:
599  err_set_name:
600  image_put ( image );
601  err_alloc_image:
602  return NULL;
603 }
604 
605 /**
606  * Find argument within image command line
607  *
608  * @v image Image
609  * @v key Argument search key (including trailing delimiter)
610  * @ret value Argument value, or NULL if not found
611  */
612 const char * image_argument ( struct image *image, const char *key ) {
613  const char *cmdline = image->cmdline;
614  const char *search;
615  const char *match;
616  const char *next;
617 
618  /* Find argument */
619  for ( search = cmdline ; search ; search = next ) {
620 
621  /* Find next occurrence, if any */
622  match = strstr ( search, key );
623  if ( ! match )
624  break;
625  next = ( match + strlen ( key ) );
626 
627  /* Check preceding delimiter, if any */
628  if ( ( match == cmdline ) || isspace ( match[-1] ) )
629  return next;
630  }
631 
632  return NULL;
633 }
#define IMAGE_TYPES
Executable image type table.
Definition: image.h:148
int image_set_trust(int require_trusted, int permanent)
Change image trust requirement.
Definition: image.c:544
unsigned int flags
Flags.
Definition: image.h:36
struct image_tag selected_image
static int require_trusted_images_permanent
Prevent changes to image trust requirement.
Definition: image.c:73
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
const char * name
Definition: ath9k_hw.c:1984
int image_select(struct image *image)
Select image for execution.
Definition: image.c:525
int image_set_uri(struct image *image, struct uri *uri)
Set image URI.
Definition: image.c:132
userptr_t data
Raw file image.
Definition: image.h:41
static void uri_put(struct uri *uri)
Decrement URI reference count.
Definition: uri.h:205
An image tag.
Definition: image.h:154
static struct uri * uri_get(struct uri *uri)
Increment URI reference count.
Definition: uri.h:194
char * strrchr(const char *src, int character)
Find rightmost character within a string.
Definition: string.c:289
uint32_t next
Next descriptor address.
Definition: myson.h:18
struct image * find_image(const char *name)
Find image by name.
Definition: image.c:340
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition: refcnt.h:64
Error codes.
#define EACCES_UNTRUSTED
Definition: image.c:47
char * image_strip_suffix(struct image *image)
Strip dot suffix from image name, if present.
Definition: image.c:181
#define ENOEXEC
Exec format error.
Definition: errno.h:519
struct image_type * type
Image type, if known.
Definition: image.h:46
uint32_t type
Operating system type.
Definition: ena.h:12
static struct image * image_get(struct image *image)
Increment reference count on an image.
Definition: image.h:219
unsigned long user_to_phys(userptr_t userptr, off_t offset)
Convert user pointer to physical address.
#define DBGC(...)
Definition: compiler.h:505
An executable image type.
Definition: image.h:76
struct image * image_memory(const char *name, userptr_t data, size_t len)
Create registered image from block of memory.
Definition: image.c:569
#define EACCES_PERMANENT
Definition: image.c:51
An executable image.
Definition: image.h:24
Character types.
struct image_tag selected_image __image_tag
Image selected for execution.
Definition: image.c:60
#define LOG_ERR
Error: error conditions.
Definition: syslog.h:35
Uniform Resource Identifiers.
struct image * image
Image (weak reference, nullified when image is freed)
Definition: image.h:158
#define IMAGE_AUTO_UNREGISTER
Image will be automatically unregistered after execution.
Definition: image.h:70
int(* exec)(struct image *image)
Execute image.
Definition: image.h:94
#define ENOTSUP
Operation not supported.
Definition: errno.h:589
char * cmdline
Command line to pass to image.
Definition: image.h:39
A doubly-linked list entry (or list head)
Definition: list.h:18
A reference counter.
Definition: refcnt.h:26
int image_exec(struct image *image)
Execute image.
Definition: image.c:378
struct image * find_image_tag(struct image_tag *tag)
Find image by tag.
Definition: image.c:357
static void free_image(struct refcnt *refcnt)
Free executable image.
Definition: image.c:80
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
static int image_probe(struct image *image)
Determine image type.
Definition: image.c:260
char * strstr(const char *haystack, const char *needle)
Find substring.
Definition: string.c:309
#define ENOMEM
Not enough space.
Definition: errno.h:534
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
struct image_tag current_image
uint32_t userptr_t
A pointer to a user buffer.
Definition: libkir.h:159
Assertions.
void churi(struct uri *uri)
Change working URI.
Definition: cwuri.c:45
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:35
Executable images.
const char * replacement
Definition: editstring.h:53
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition: list.h:93
const char * path
Path (after URI decoding)
Definition: uri.h:80
#define IMAGE_REGISTERED
Image is registered.
Definition: image.h:64
#define IMAGE_TAGS
Image tag table.
Definition: image.h:162
userptr_t urealloc(userptr_t userptr, size_t new_size)
Reallocate external memory.
Linked lists.
int register_image(struct image *image)
Register executable image.
Definition: image.c:286
#define for_each_image(image)
Iterate over all registered images.
Definition: image.h:172
System logger.
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
char * basename(char *path)
Return base name from path.
Definition: basename.c:42
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
size_t len
Length of raw file image.
Definition: image.h:43
int image_replace(struct image *replacement)
Set replacement image.
Definition: image.c:489
struct list_head images
List of registered images.
Definition: image.c:57
int image_set_name(struct image *image, const char *name)
Set image name.
Definition: image.c:160
#define IMAGE_TRUSTED
Image is trusted.
Definition: image.h:67
char * strdup(const char *src)
Duplicate string.
Definition: string.c:393
User memory allocation.
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition: tables.h:385
struct uri * uri
URI of image.
Definition: image.h:32
int isspace(int character)
Check to see if character is a space.
Definition: ctype.c:41
size_t strlen(const char *src)
Get length of string.
Definition: string.c:243
static void image_put(struct image *image)
Decrement reference count on an image.
Definition: image.h:229
int image_set_data(struct image *image, userptr_t data, size_t len)
Set image data.
Definition: image.c:241
void unregister_image(struct image *image)
Unregister executable image.
Definition: image.c:322
int image_set_len(struct image *image, size_t len)
Set image length.
Definition: image.c:220
static __always_inline void ufree(userptr_t userptr)
Free external memory.
Definition: umalloc.h:65
const char * opaque
Opaque part.
Definition: uri.h:70
#define ENOTTY
Inappropriate I/O control operation.
Definition: errno.h:594
int strcmp(const char *first, const char *second)
Compare strings.
Definition: string.c:173
const char * image_argument(struct image *image, const char *key)
Find argument within image command line.
Definition: image.c:612
#define syslog(priority, fmt,...)
Write message to system log.
Definition: syslog.h:93
uint8_t data[48]
Additional event data.
Definition: ena.h:22
struct image * replacement
Replacement image.
Definition: image.h:60
int image_set_cmdline(struct image *image, const char *cmdline)
Set image command line.
Definition: image.c:201
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition: vsprintf.c:382
A Uniform Resource Identifier.
Definition: uri.h:64
static int require_trusted_images
Current image trust requirement.
Definition: image.c:70
#define LIST_HEAD_INIT(list)
Initialise a static list head.
Definition: list.h:30
struct list_head list
List of registered images.
Definition: image.h:29
struct uri * cwuri
Current working URI.
Definition: cwuri.c:38
static struct image * image_tag(struct image *image, struct image_tag *tag)
Tag image.
Definition: image.h:276
uint32_t cmdline
Definition: multiboot.h:16
struct image * alloc_image(struct uri *uri)
Allocate executable image.
Definition: image.c:103
uint64_t tag
Identity tag.
Definition: edd.h:30
char * name
Name.
Definition: image.h:34
uint32_t len
Length.
Definition: ena.h:14
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
String functions.
#define LOG_NOTICE
Notice: normal but significant conditions.
Definition: syslog.h:41
const char * name
Name.
Definition: image.h:156
union @383 key
Sense key.
Definition: scsi.h:18
void memcpy_user(userptr_t dest, off_t dest_off, userptr_t src, off_t src_off, size_t len)
Copy data between user buffers.
struct refcnt refcnt
Reference count.
Definition: image.h:26