a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync#ifndef _IPXE_IMAGE_H
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync#define _IPXE_IMAGE_H
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync/**
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * @file
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync *
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * Executable images
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync *
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncFILE_LICENCE ( GPL2_OR_LATER );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync#include <ipxe/tables.h>
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync#include <ipxe/list.h>
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync#include <ipxe/uaccess.h>
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync#include <ipxe/refcnt.h>
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncstruct uri;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncstruct image_type;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync/** An executable image */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncstruct image {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync /** Reference count */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync struct refcnt refcnt;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync /** List of registered images */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync struct list_head list;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync /** URI of image */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync struct uri *uri;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync /** Name */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync char *name;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync /** Flags */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync unsigned int flags;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync /** Command line to pass to image */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync char *cmdline;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync /** Raw file image */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync userptr_t data;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync /** Length of raw file image */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync size_t len;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync /** Image type, if known */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync struct image_type *type;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync /** Replacement image
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync *
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * An image wishing to replace itself with another image (in a
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * style similar to a Unix exec() call) should return from its
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * exec() method with the replacement image set to point to
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * the new image.
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync *
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * If an image unregisters itself as a result of being
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * executed, it must make sure that its replacement image (if
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * any) is registered, otherwise the replacement is likely to
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * be freed before it can be executed.
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync struct image *replacement;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync};
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync/** Image is registered */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync#define IMAGE_REGISTERED 0x00001
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync/** Image is selected for execution */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync#define IMAGE_SELECTED 0x0002
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync/** Image is trusted */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync#define IMAGE_TRUSTED 0x0004
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync/** An executable image type */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncstruct image_type {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync /** Name of this image type */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync char *name;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync /** Probe image
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync *
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * @v image Executable image
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * @ret rc Return status code
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync *
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * Return success if the image is of this image type.
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync int ( * probe ) ( struct image *image );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync /**
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * Execute image
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync *
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * @v image Executable image
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * @ret rc Return status code
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync int ( * exec ) ( struct image *image );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync};
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync/**
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * Multiboot image probe priority
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync *
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * Multiboot images are also valid executables in another format
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * (e.g. ELF), so we must perform the multiboot probe first.
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync#define PROBE_MULTIBOOT 01
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync/**
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * Normal image probe priority
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync#define PROBE_NORMAL 02
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync/**
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * PXE image probe priority
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync *
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * PXE images have no signature checks, so will claim all image files.
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * They must therefore be tried last in the probe order list.
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync#define PROBE_PXE 03
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync/** Executable image type table */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync#define IMAGE_TYPES __table ( struct image_type, "image_types" )
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync/** An executable image type */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync#define __image_type( probe_order ) __table_entry ( IMAGE_TYPES, probe_order )
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncextern struct list_head images;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncextern struct image *current_image;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync/** Iterate over all registered images */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync#define for_each_image( image ) \
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync list_for_each_entry ( (image), &images, list )
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync/** Iterate over all registered images, safe against deletion */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync#define for_each_image_safe( image, tmp ) \
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync list_for_each_entry_safe ( (image), (tmp), &images, list )
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync/**
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * Test for existence of images
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync *
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * @ret existence Some images exist
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncstatic inline int have_images ( void ) {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync return ( ! list_empty ( &images ) );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync}
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync/**
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * Retrieve first image
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync *
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * @ret image Image, or NULL
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncstatic inline struct image * first_image ( void ) {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync return list_first_entry ( &images, struct image, list );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync}
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncextern struct image * alloc_image ( struct uri *uri );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncextern int image_set_name ( struct image *image, const char *name );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncextern int image_set_cmdline ( struct image *image, const char *cmdline );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncextern int register_image ( struct image *image );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncextern void unregister_image ( struct image *image );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncstruct image * find_image ( const char *name );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncextern int image_probe ( struct image *image );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncextern int image_exec ( struct image *image );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncextern int image_replace ( struct image *replacement );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncextern int image_select ( struct image *image );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncextern struct image * image_find_selected ( void );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncextern int image_set_trust ( int require_trusted, int permanent );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync/**
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * Increment reference count on an image
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync *
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * @v image Image
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * @ret image Image
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncstatic inline struct image * image_get ( struct image *image ) {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync ref_get ( &image->refcnt );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync return image;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync}
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync/**
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * Decrement reference count on an image
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync *
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * @v image Image
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncstatic inline void image_put ( struct image *image ) {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync ref_put ( &image->refcnt );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync}
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync/**
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * Clear image command line
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync *
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * @v image Image
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncstatic inline void image_clear_cmdline ( struct image *image ) {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync image_set_cmdline ( image, NULL );
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync}
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync/**
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * Set image as trusted
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync *
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * @v image Image
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncstatic inline void image_trust ( struct image *image ) {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync image->flags |= IMAGE_TRUSTED;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync}
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync/**
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * Set image as untrusted
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync *
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync * @v image Image
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync */
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsyncstatic inline void image_untrust ( struct image *image ) {
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync image->flags &= ~IMAGE_TRUSTED;
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync}
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync
a734c64bff58bda2fa48c2795453e092167b0ff7vboxsync#endif /* _IPXE_IMAGE_H */