176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifndef _GPXE_IMAGE_H
276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define _GPXE_IMAGE_H
376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @file
676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Executable/loadable images
876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
1176d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanFILE_LICENCE ( GPL2_OR_LATER );
1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/tables.h>
1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/list.h>
1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/uaccess.h>
1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/refcnt.h>
1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct uri;
1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct image_type;
2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** An executable or loadable image */
2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct image {
2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/** Reference count */
2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	struct refcnt refcnt;
2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/** List of registered images */
2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	struct list_head list;
2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/** URI of image */
3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	struct uri *uri;
3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/** Name */
3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	char name[16];
3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/** Flags */
3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	unsigned int flags;
3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/** Command line to pass to image */
3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	char *cmdline;
3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/** Raw file image */
3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	userptr_t data;
4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/** Length of raw file image */
4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	size_t len;
4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/** Image type, if known */
4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	struct image_type *type;
4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/** Image type private data */
4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	union {
4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		physaddr_t phys;
4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		userptr_t user;
4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		unsigned long ul;
5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	} priv;
5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/** Replacement image
5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 *
5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * An image wishing to replace itself with another image (in a
5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * style similar to a Unix exec() call) should return from its
5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * exec() method with the replacement image set to point to
5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * the new image.  The new image must already be in a suitable
5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * state for execution (i.e. loaded).
5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 *
6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * If an image unregisters itself as a result of being
6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * executed, it must make sure that its replacement image (if
6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * any) is registered, otherwise the replacement is likely to
6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * be freed before it can be executed.
6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 */
6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	struct image *replacement;
6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** Image is loaded */
6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define IMAGE_LOADED 0x0001
7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** An executable or loadable image type */
7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct image_type {
7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/** Name of this image type */
7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	char *name;
7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/**
7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * Load image into memory
7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 *
7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * @v image		Executable/loadable image
7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * @ret rc		Return status code
8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 *
8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * Load the image into memory at the correct location as
8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * determined by the file format.
8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 *
8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * If the file image is in the correct format, the method must
8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * update @c image->type to point to its own type (unless @c
8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * image->type is already set).  This allows the autoloading
8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * code to disambiguate between "this is not my image format"
8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * and "there is something wrong with this image".  In
8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * particular, setting @c image->type and then returning an
9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * error will cause image_autoload() to abort and return an
9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * error, rather than continuing to the next image type.
9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 */
9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	int ( * load ) ( struct image *image );
9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/**
9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * Execute loaded image
9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 *
9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * @v image		Loaded image
9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * @ret rc		Return status code
9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 *
10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * Note that the image may be invalidated by the act of
10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * execution, i.e. an image is allowed to choose to unregister
10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * (and so potentially free) itself.
10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 */
10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	int ( * exec ) ( struct image *image );
10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Multiboot image probe priority
10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Multiboot images are also valid executables in another format
11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * (e.g. ELF), so we must perform the multiboot probe first.
11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define PROBE_MULTIBOOT	01
11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Normal image probe priority
11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define PROBE_NORMAL 02
11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * PXE image probe priority
12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * PXE images have no signature checks, so will claim all image files.
12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * They must therefore be tried last in the probe order list.
12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define PROBE_PXE 03
12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** Executable or loadable image type table */
12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define IMAGE_TYPES __table ( struct image_type, "image_types" )
13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** An executable or loadable image type */
13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define __image_type( probe_order ) __table_entry ( IMAGE_TYPES, probe_order )
13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern struct list_head images;
13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** Iterate over all registered images */
13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define for_each_image( image ) \
13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	list_for_each_entry ( (image), &images, list )
13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Test for existence of images
14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret existence	Some images exist
14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic inline int have_images ( void ) {
14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return ( ! list_empty ( &images ) );
14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern struct image * alloc_image ( void );
15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern int image_set_uri ( struct image *image, struct uri *uri );
15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern int image_set_cmdline ( struct image *image, const char *cmdline );
15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern int register_image ( struct image *image );
15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern void unregister_image ( struct image *image );
15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern void promote_image ( struct image *image );
15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct image * find_image ( const char *name );
15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern int image_load ( struct image *image );
15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern int image_autoload ( struct image *image );
15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern int image_exec ( struct image *image );
15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern int register_and_autoload_image ( struct image *image );
16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern int register_and_autoexec_image ( struct image *image );
16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Increment reference count on an image
16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v image		Image
16676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret image		Image
16776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
16876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic inline struct image * image_get ( struct image *image ) {
16976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	ref_get ( &image->refcnt );
17076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return image;
17176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
17276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
17376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
17476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Decrement reference count on an image
17576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
17676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v image		Image
17776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
17876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic inline void image_put ( struct image *image ) {
17976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	ref_put ( &image->refcnt );
18076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
18176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
18276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
18376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Set image name
18476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
18576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v image		Image
18676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v name		New image name
18776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret rc		Return status code
18876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
18976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic inline int image_set_name ( struct image *image, const char *name ) {
19076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	strncpy ( image->name, name, ( sizeof ( image->name ) - 1 ) );
19176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return 0;
19276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
19376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
19476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* _GPXE_IMAGE_H */
195