1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
|
#ifndef _GPXE_IMAGE_H
#define _GPXE_IMAGE_H
/**
* @file
*
* Executable/loadable images
*
*/
FILE_LICENCE ( GPL2_OR_LATER );
#include <gpxe/tables.h>
#include <gpxe/list.h>
#include <gpxe/uaccess.h>
#include <gpxe/refcnt.h>
struct uri;
struct image_type;
/** An executable or loadable image */
struct image {
/** Reference count */
struct refcnt refcnt;
/** List of registered images */
struct list_head list;
/** URI of image */
struct uri *uri;
/** Name */
char name[16];
/** Flags */
unsigned int flags;
/** Command line to pass to image */
char *cmdline;
/** Raw file image */
userptr_t data;
/** Length of raw file image */
size_t len;
/** Image type, if known */
struct image_type *type;
/** Image type private data */
union {
physaddr_t phys;
userptr_t user;
unsigned long ul;
} priv;
/** Replacement image
*
* An image wishing to replace itself with another image (in a
* style similar to a Unix exec() call) should return from its
* exec() method with the replacement image set to point to
* the new image. The new image must already be in a suitable
* state for execution (i.e. loaded).
*
* If an image unregisters itself as a result of being
* executed, it must make sure that its replacement image (if
* any) is registered, otherwise the replacement is likely to
* be freed before it can be executed.
*/
struct image *replacement;
};
/** Image is loaded */
#define IMAGE_LOADED 0x0001
/** An executable or loadable image type */
struct image_type {
/** Name of this image type */
char *name;
/**
* Load image into memory
*
* @v image Executable/loadable image
* @ret rc Return status code
*
* Load the image into memory at the correct location as
* determined by the file format.
*
* If the file image is in the correct format, the method must
* update @c image->type to point to its own type (unless @c
* image->type is already set). This allows the autoloading
* code to disambiguate between "this is not my image format"
* and "there is something wrong with this image". In
* particular, setting @c image->type and then returning an
* error will cause image_autoload() to abort and return an
* error, rather than continuing to the next image type.
*/
int ( * load ) ( struct image *image );
/**
* Execute loaded image
*
* @v image Loaded image
* @ret rc Return status code
*
* Note that the image may be invalidated by the act of
* execution, i.e. an image is allowed to choose to unregister
* (and so potentially free) itself.
*/
int ( * exec ) ( struct image *image );
};
/**
* Multiboot image probe priority
*
* Multiboot images are also valid executables in another format
* (e.g. ELF), so we must perform the multiboot probe first.
*/
#define PROBE_MULTIBOOT 01
/**
* Normal image probe priority
*/
#define PROBE_NORMAL 02
/**
* PXE image probe priority
*
* PXE images have no signature checks, so will claim all image files.
* They must therefore be tried last in the probe order list.
*/
#define PROBE_PXE 03
/** Executable or loadable image type table */
#define IMAGE_TYPES __table ( struct image_type, "image_types" )
/** An executable or loadable image type */
#define __image_type( probe_order ) __table_entry ( IMAGE_TYPES, probe_order )
extern struct list_head images;
/** Iterate over all registered images */
#define for_each_image( image ) \
list_for_each_entry ( (image), &images, list )
/**
* Test for existence of images
*
* @ret existence Some images exist
*/
static inline int have_images ( void ) {
return ( ! list_empty ( &images ) );
}
extern struct image * alloc_image ( void );
extern int image_set_uri ( struct image *image, struct uri *uri );
extern int image_set_cmdline ( struct image *image, const char *cmdline );
extern int register_image ( struct image *image );
extern void unregister_image ( struct image *image );
extern void promote_image ( struct image *image );
struct image * find_image ( const char *name );
extern int image_load ( struct image *image );
extern int image_autoload ( struct image *image );
extern int image_exec ( struct image *image );
extern int register_and_autoload_image ( struct image *image );
extern int register_and_autoexec_image ( struct image *image );
/**
* Increment reference count on an image
*
* @v image Image
* @ret image Image
*/
static inline struct image * image_get ( struct image *image ) {
ref_get ( &image->refcnt );
return image;
}
/**
* Decrement reference count on an image
*
* @v image Image
*/
static inline void image_put ( struct image *image ) {
ref_put ( &image->refcnt );
}
/**
* Set image name
*
* @v image Image
* @v name New image name
* @ret rc Return status code
*/
static inline int image_set_name ( struct image *image, const char *name ) {
strncpy ( image->name, name, ( sizeof ( image->name ) - 1 ) );
return 0;
}
#endif /* _GPXE_IMAGE_H */
|