struct image *image = container_of ( refcnt, struct image, refcnt );
DBGC ( image, "RUNTIME freeing command line\n" );
+ free_image ( refcnt );
free ( cmdline_copy );
}
static struct image cmdline_image = {
.refcnt = REF_INIT ( cmdline_image_free ),
.name = "<CMDLINE>",
+ .flags = ( IMAGE_STATIC | IMAGE_STATIC_NAME ),
.type = &script_image_type,
};
* Free executable image
*
* @v refcnt Reference counter
+ *
+ * Image consumers must call image_put() rather than calling
+ * free_image() directly. This function is exposed for use only by
+ * static images.
*/
-static void free_image ( struct refcnt *refcnt ) {
+void free_image ( struct refcnt *refcnt ) {
struct image *image = container_of ( refcnt, struct image, refcnt );
struct image_tag *tag;
+ /* Sanity check: free_image() should not be called directly on
+ * dynamically allocated images.
+ */
+ assert ( refcnt->count < 0 );
DBGC ( image, "IMAGE %s freed\n", image->name );
+
+ /* Clear any tag weak references */
for_each_table_entry ( tag, IMAGE_TAGS ) {
if ( tag->image == image )
tag->image = NULL;
}
- free ( image->name );
+
+ /* Free dynamic allocations used by both static and dynamic images */
free ( image->cmdline );
uri_put ( image->uri );
- ufree ( image->data );
image_put ( image->replacement );
- free ( image );
+
+ /* Free image name, if dynamically allocated */
+ if ( ! ( image->flags & IMAGE_STATIC_NAME ) )
+ free ( image->name );
+
+ /* Free image data and image itself, if dynamically allocated */
+ if ( ! ( image->flags & IMAGE_STATIC ) ) {
+ ufree ( image->data );
+ free ( image );
+ }
}
/**
if ( ! name_copy )
return -ENOMEM;
+ /* Free existing name, if not statically allocated */
+ if ( ! ( image->flags & IMAGE_STATIC_NAME ) )
+ free ( image->name );
+
/* Replace existing name */
- free ( image->name );
image->name = name_copy;
+ image->flags &= ~IMAGE_STATIC_NAME;
return 0;
}
int image_set_len ( struct image *image, size_t len ) {
void *new;
+ /* Refuse to reallocate static images */
+ if ( image->flags & IMAGE_STATIC )
+ return -ENOTTY;
+
/* (Re)allocate image data */
new = urealloc ( image->data, len );
if ( ! new )
char name[8]; /* "imgXXXX" */
int rc;
+ /* Sanity checks */
+ if ( image->flags & IMAGE_STATIC ) {
+ assert ( ( image->name == NULL ) ||
+ ( image->flags & IMAGE_STATIC_NAME ) );
+ assert ( image->cmdline == NULL );
+ }
+
/* Create image name if it doesn't already have one */
if ( ! image->name ) {
snprintf ( name, sizeof ( name ), "img%d", imgindex++ );
/* Image structures for all embedded images */
#undef EMBED
#define EMBED( _index, _path, _name ) { \
- .refcnt = REF_INIT ( ref_no_free ), \
+ .refcnt = REF_INIT ( free_image ), \
.name = _name, \
+ .flags = ( IMAGE_STATIC | IMAGE_STATIC_NAME ), \
.data = ( userptr_t ) ( embedded_image_ ## _index ## _data ), \
.len = ( size_t ) embedded_image_ ## _index ## _len, \
},
/** URI of image */
struct uri *uri;
- /** Name */
+ /** Name
+ *
+ * If the @c IMAGE_STATIC_NAME flag is set, then this is a
+ * statically allocated string.
+ */
char *name;
/** Flags */
unsigned int flags;
/** Command line to pass to image */
char *cmdline;
- /** Raw file image */
+ /** Raw file image
+ *
+ * If the @c IMAGE_STATIC flag is set, then this is a
+ * statically allocated image.
+ */
void *data;
/** Length of raw file image */
size_t len;
/** Image will be hidden from enumeration */
#define IMAGE_HIDDEN 0x0008
+/** Image is statically allocated */
+#define IMAGE_STATIC 0x0010
+
+/** Image name is statically allocated */
+#define IMAGE_STATIC_NAME 0x0020
+
/** An executable image type */
struct image_type {
/** Name of this image type */
return list_first_entry ( &images, struct image, list );
}
+extern void free_image ( struct refcnt *refcnt );
extern struct image * alloc_image ( struct uri *uri );
extern int image_set_uri ( struct image *image, struct uri *uri );
extern int image_set_name ( struct image *image, const char *name );
struct image *image = container_of ( refcnt, struct image, refcnt );
DBGC ( image, "CMDLINE freeing command line\n" );
+ free_image ( refcnt );
free ( efi_cmdline_copy );
}
static struct image efi_cmdline_image = {
.refcnt = REF_INIT ( efi_cmdline_free ),
.name = "<CMDLINE>",
+ .flags = ( IMAGE_STATIC | IMAGE_STATIC_NAME ),
.type = &script_image_type,
};
static struct image _name ## __image = { \
.refcnt = REF_INIT ( ref_no_free ), \
.name = #_name, \
+ .flags = ( IMAGE_STATIC | IMAGE_STATIC_NAME ), \
.data = ( userptr_t ) ( _name ## __file ), \
.len = sizeof ( _name ## __file ), \
}; \
.image = { \
.refcnt = REF_INIT ( ref_no_free ), \
.name = #NAME, \
+ .flags = ( IMAGE_STATIC | IMAGE_STATIC_NAME ), \
.data = ( userptr_t ) ( NAME ## _data ), \
.len = sizeof ( NAME ## _data ), \
}, \
.image = { \
.refcnt = REF_INIT ( ref_no_free ), \
.name = #NAME, \
+ .flags = ( IMAGE_STATIC | IMAGE_STATIC_NAME ), \
.data = ( userptr_t ) ( NAME ## _data ), \
.len = sizeof ( NAME ## _data ), \
}, \
.image = { \
.refcnt = REF_INIT ( ref_no_free ), \
.name = #NAME, \
+ .flags = ( IMAGE_STATIC | IMAGE_STATIC_NAME ), \
.type = &der_image_type, \
.data = ( userptr_t ) ( NAME ## _data ), \
.len = sizeof ( NAME ## _data ), \
static struct image _name ## __image = { \
.refcnt = REF_INIT ( ref_no_free ), \
.name = #_name, \
+ .flags = ( IMAGE_STATIC | IMAGE_STATIC_NAME ), \
.data = ( userptr_t ) ( _name ## __file ), \
.len = sizeof ( _name ## __file ), \
}; \
static struct image test_image = {
.refcnt = REF_INIT ( ref_no_free ),
.name = "<TESTS>",
+ .flags = ( IMAGE_STATIC | IMAGE_STATIC_NAME ),
.type = &test_image_type,
};