iPXE
lkrn.c File Reference

Linux kernel image format. More...

#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <byteswap.h>
#include <ipxe/image.h>
#include <ipxe/memmap.h>
#include <ipxe/uaccess.h>
#include <ipxe/segment.h>
#include <ipxe/initrd.h>
#include <ipxe/io.h>
#include <ipxe/fdt.h>
#include <ipxe/init.h>
#include <ipxe/lkrn.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (FORBIDDEN)
static int lkrn_parse (struct image *image, struct lkrn_context *ctx)
 Parse kernel image.
static int lkrn_ram (struct image *image, struct lkrn_context *ctx)
 Locate start of RAM.
static int lkrn_exec (struct image *image)
 Execute kernel image.
static int lkrn_probe (struct image *image)
 Probe kernel image.
struct image_type lkrn_image_type __image_type (PROBE_NORMAL)
 Linux kernel image type.
static int zimg_parse (struct image *image, struct zimg_context *zctx)
 Parse compressed kernel image.
static int zimg_extract (struct image *image, struct image *extracted)
 Extract compresed kernel image.
static int zimg_probe (struct image *image)
 Probe compressed kernel image.

Detailed Description

Linux kernel image format.

Definition in file lkrn.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( FORBIDDEN )

◆ lkrn_parse()

int lkrn_parse ( struct image * image,
struct lkrn_context * ctx )
static

Parse kernel image.

Parameters
imageKernel image
ctxKernel image context
Return values
rcReturn status code

Definition at line 54 of file lkrn.c.

54 {
55 const struct lkrn_header *hdr;
56
57 /* Initialise context */
58 memset ( ctx, 0, sizeof ( *ctx ) );
59
60 /* Read image header */
61 if ( image->len < sizeof ( *hdr ) ) {
62 DBGC ( image, "LKRN %s too short for header\n", image->name );
63 return -ENOEXEC;
64 }
65 hdr = image->data;
66
67 /* Check magic value */
68 if ( hdr->magic != cpu_to_le32 ( LKRN_MAGIC_ARCH ) ) {
69 DBGC ( image, "LKRN %s bad magic value %#08x\n",
70 image->name, le32_to_cpu ( hdr->magic ) );
71 return -ENOEXEC;
72 }
73
74 /* Record load offset */
75 ctx->offset = le64_to_cpu ( hdr->text_offset );
76 if ( ctx->offset & ( ctx->offset - 1 ) ) {
77 DBGC ( image, "LKRN %s offset %#zx is not a power of two\n",
78 image->name, ctx->offset );
79 return -ENOEXEC;
80 }
81
82 /* Record and check image size */
83 ctx->filesz = image->len;
84 ctx->memsz = le64_to_cpu ( hdr->image_size );
85 if ( ctx->filesz > ctx->memsz ) {
86 DBGC ( image, "LKRN %s invalid image size %#zx/%#zx\n",
87 image->name, ctx->filesz, ctx->memsz );
88 return -ENOEXEC;
89 }
90
91 return 0;
92}
struct golan_eq_context ctx
Definition CIB_PRM.h:0
struct golan_inbox_hdr hdr
Message header.
Definition CIB_PRM.h:0
#define LKRN_MAGIC_ARCH
Definition lkrn.h:16
#define DBGC(...)
Definition compiler.h:505
#define ENOEXEC
Exec format error.
Definition errno.h:520
#define le64_to_cpu(value)
Definition byteswap.h:115
#define le32_to_cpu(value)
Definition byteswap.h:114
#define cpu_to_le32(value)
Definition byteswap.h:108
void * memset(void *dest, int character, size_t len) __nonnull
An executable image.
Definition image.h:24
const void * data
Read-only data.
Definition image.h:51
char * name
Name.
Definition image.h:38
size_t len
Length of raw file image.
Definition image.h:56
Kernel image header.
Definition lkrn.h:16

References cpu_to_le32, ctx, image::data, DBGC, ENOEXEC, hdr, le32_to_cpu, le64_to_cpu, image::len, LKRN_MAGIC_ARCH, memset(), and image::name.

Referenced by lkrn_exec(), and lkrn_probe().

◆ lkrn_ram()

int lkrn_ram ( struct image * image,
struct lkrn_context * ctx )
static

Locate start of RAM.

Parameters
imageKernel image
ctxKernel image context
Return values
rcReturn status code

Definition at line 101 of file lkrn.c.

101 {
102 struct memmap_region region;
103
104 /* Locate start of RAM */
105 for_each_memmap ( &region, 0 ) {
106 DBGC_MEMMAP ( image, &region );
107 if ( ! ( region.flags & MEMMAP_FL_MEMORY ) )
108 continue;
109 ctx->ram = region.min;
110 DBGC ( image, "LKRN %s RAM starts at %#08lx\n",
111 image->name, ctx->ram );
112 return 0;
113 }
114
115 DBGC ( image, "LKRN %s found no RAM\n", image->name );
116 return -ENOTSUP;
117}
#define ENOTSUP
Operation not supported.
Definition errno.h:590
#define MEMMAP_FL_MEMORY
Contains memory.
Definition memmap.h:60
#define for_each_memmap(region, hide)
Iterate over memory regions.
Definition memmap.h:184
#define DBGC_MEMMAP(...)
Definition memmap.h:207
A memory region descriptor.
Definition memmap.h:49

References ctx, DBGC, DBGC_MEMMAP, ENOTSUP, memmap_region::flags, for_each_memmap, MEMMAP_FL_MEMORY, memmap_region::min, and image::name.

Referenced by lkrn_exec().

◆ lkrn_exec()

int lkrn_exec ( struct image * image)
static

Execute kernel image.

Parameters
imageKernel image
Return values
rcReturn status code

Definition at line 125 of file lkrn.c.

125 {
126 static struct image fdtimg = {
127 .refcnt = REF_INIT ( free_image ),
128 .name = "<FDT>",
129 .flags = ( IMAGE_STATIC | IMAGE_STATIC_NAME ),
130 };
131 struct lkrn_context ctx;
132 struct memmap_region region;
133 struct fdt_header *fdt;
134 size_t initrdsz;
135 size_t totalsz;
136 void *dest;
137 int rc;
138
139 /* Parse header */
140 if ( ( rc = lkrn_parse ( image, &ctx ) ) != 0 )
141 goto err_parse;
142
143 /* Locate start of RAM */
144 if ( ( rc = lkrn_ram ( image, &ctx ) ) != 0 )
145 goto err_ram;
146
147 /* Place kernel at specified address from start of RAM */
148 ctx.entry = ( ctx.ram + ctx.offset );
149 DBGC ( image, "LKRN %s loading to [%#08lx,%#08lx,%#08lx)\n",
150 image->name, ctx.entry, ( ctx.entry + ctx.filesz ),
151 ( ctx.entry + ctx.memsz ) );
152
153 /* Place initrd after kernel, aligned to the kernel's image offset */
154 ctx.initrd = ( ctx.ram + initrd_align ( ctx.offset + ctx.memsz ) );
155 ctx.initrd = ( ( ctx.initrd + ctx.offset - 1 ) & ~( ctx.offset - 1 ) );
156 initrdsz = initrd_len();
157 if ( initrdsz ) {
158 DBGC ( image, "LKRN %s initrd at [%#08lx,%#08lx)\n",
159 image->name, ctx.initrd, ( ctx.initrd + initrdsz ) );
160 }
161
162 /* Place device tree after initrd */
163 ctx.fdt = ( ctx.initrd + initrd_align ( initrdsz ) );
164
165 /* Construct device tree and post-initrd image */
166 if ( ( rc = fdt_create ( &fdt, image->cmdline, ctx.initrd,
167 initrdsz ) ) != 0 ) {
168 goto err_fdt;
169 }
170 fdtimg.data = fdt;
171 fdtimg.len = be32_to_cpu ( fdt->totalsize );
172 list_add_tail ( &fdtimg.list, &images );
173 DBGC ( image, "LKRN %s FDT at [%08lx,%08lx)\n",
174 image->name, ctx.fdt, ( ctx.fdt + fdtimg.len ) );
175
176 /* Find post-reshuffle region */
177 if ( ( rc = initrd_region ( initrdsz, &region ) ) != 0 ) {
178 DBGC ( image, "LKRN %s no available region: %s\n",
179 image->name, strerror ( rc ) );
180 goto err_region;
181 }
182
183 /* Check that everything can be placed at its target addresses */
184 totalsz = ( ctx.fdt + fdtimg.len - ctx.ram );
185 if ( ( ctx.entry >= region.min ) &&
186 ( ( ctx.offset + totalsz ) <= memmap_size ( &region ) ) ) {
187 /* Target addresses are within the reshuffle region */
188 DBGC ( image, "LKRN %s fits within reshuffle region\n",
189 image->name );
190 } else {
191 /* Target addresses are outside the reshuffle region */
192 if ( ( rc = prep_segment ( phys_to_virt ( ctx.entry ),
193 totalsz, totalsz ) ) != 0 ) {
194 DBGC ( image, "LKRN %s could not prepare segment: "
195 "%s\n", image->name, strerror ( rc ) );
196 goto err_segment;
197 }
198 }
199
200 /* This is the point of no return: we are about to reshuffle
201 * and thereby destroy the external heap. No errors are
202 * allowed to occur after this point.
203 */
204
205 /* Shut down ready for boot */
207
208 /* Prepend kernel to reshuffle list, reshuffle, and remove kernel */
209 list_add ( &image->list, &images );
211 list_del ( &image->list );
212
213 /* Load kernel to entry point and zero bss */
214 dest = phys_to_virt ( ctx.entry );
215 memmove ( dest, image->data, ctx.filesz );
216 memset ( ( dest + ctx.filesz ), 0, ( ctx.memsz - ctx.filesz ) );
217
218 /* Load initrds and device tree */
219 dest = phys_to_virt ( ctx.initrd );
221
222 /* Jump to kernel entry point */
223 DBGC ( image, "LKRN %s jumping to kernel at %#08lx\n",
224 image->name, ctx.entry );
225 lkrn_jump ( ctx.entry, ctx.fdt );
226
227 /* There is no way for the image to return, since we provide
228 * no return address.
229 */
230 assert ( 0 );
231
232 return -ECANCELED; /* -EIMPOSSIBLE */
233
234 err_segment:
235 err_region:
236 list_del ( &fdtimg.list );
237 fdt_remove ( fdt );
238 err_fdt:
239 err_ram:
240 err_parse:
241 return rc;
242}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" retur dest)
Definition string.h:151
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
void fdt_remove(struct fdt_header *hdr)
Remove device tree.
Definition fdt.c:1459
int fdt_create(struct fdt_header **hdr, const char *cmdline, physaddr_t initrd, size_t initrd_len)
Create device tree.
Definition fdt.c:1408
#define ECANCELED
Operation canceled.
Definition errno.h:344
struct list_head images
List of registered images.
Definition image.c:59
void free_image(struct refcnt *refcnt)
Free executable image.
Definition image.c:86
#define IMAGE_STATIC_NAME
Image name is statically allocated.
Definition image.h:92
#define IMAGE_STATIC
Image is statically allocated.
Definition image.h:89
#define be32_to_cpu(value)
Definition byteswap.h:117
static uint64_t memmap_size(const struct memmap_region *region)
Get remaining size of memory region (from the described address upwards)
Definition memmap.h:99
void * memmove(void *dest, const void *src, size_t len) __nonnull
static void shutdown_boot(void)
Shut down system for OS boot.
Definition init.h:78
int initrd_region(size_t len, struct memmap_region *region)
Calculate post-reshuffle initrd load region.
Definition initrd.c:354
void initrd_reshuffle(void)
Reshuffle initrds into desired order at top of memory.
Definition initrd.c:229
size_t initrd_load_all(void *address)
Load all initrds.
Definition initrd.c:317
static size_t initrd_align(size_t len)
Align initrd length.
Definition initrd.h:30
void lkrn_jump(physaddr_t entry, physaddr_t fdt)
Jump to kernel entry point.
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition list.h:94
#define list_del(list)
Delete an entry from a list.
Definition list.h:120
#define list_add(new, head)
Add a new entry to the head of a list.
Definition list.h:70
static int lkrn_parse(struct image *image, struct lkrn_context *ctx)
Parse kernel image.
Definition lkrn.c:54
static int lkrn_ram(struct image *image, struct lkrn_context *ctx)
Locate start of RAM.
Definition lkrn.c:101
#define REF_INIT(free_fn)
Initialise a static reference counter.
Definition refcnt.h:78
#define initrd_len
Definition runtime.c:63
int prep_segment(void *segment, size_t filesz, size_t memsz)
Prepare segment for loading.
Definition segment.c:61
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
Device tree header.
Definition fdt.h:19
A device tree.
Definition fdt.h:89
struct list_head list
List of registered images.
Definition image.h:29
char * cmdline
Command line to pass to image.
Definition image.h:43
Kernel image context.
Definition lkrn.h:44

References assert, be32_to_cpu, image::cmdline, ctx, image::data, DBGC, dest, ECANCELED, fdt_create(), fdt_remove(), free_image(), IMAGE_STATIC, IMAGE_STATIC_NAME, images, initrd_align(), initrd_len, initrd_load_all(), initrd_region(), initrd_reshuffle(), image::len, image::list, list_add, list_add_tail, list_del, lkrn_jump(), lkrn_parse(), lkrn_ram(), memmap_size(), memmove(), memset(), memmap_region::min, image::name, prep_segment(), rc, REF_INIT, shutdown_boot(), and strerror().

Referenced by __image_type().

◆ lkrn_probe()

int lkrn_probe ( struct image * image)
static

Probe kernel image.

Parameters
imageKernel image
Return values
rcReturn status code

Definition at line 250 of file lkrn.c.

250 {
251 struct lkrn_context ctx;
252 int rc;
253
254 /* Parse header */
255 if ( ( rc = lkrn_parse ( image, &ctx ) ) != 0 )
256 return rc;
257
258 DBGC ( image, "LKRN %s is a Linux kernel\n", image->name );
259 return 0;
260}

References ctx, DBGC, lkrn_parse(), image::name, and rc.

Referenced by __image_type().

◆ __image_type()

struct image_type lkrn_image_type __image_type ( PROBE_NORMAL )

Linux kernel image type.

Linux kernel compressed image type.

References __image_type, lkrn_exec(), lkrn_probe(), and PROBE_NORMAL.

◆ zimg_parse()

int zimg_parse ( struct image * image,
struct zimg_context * zctx )
static

Parse compressed kernel image.

Parameters
imageCompressed kernel image
zctxCompressed kernel image context
Return values
rcReturn status code

Definition at line 276 of file lkrn.c.

276 {
277 const struct zimg_header *zhdr;
278
279 /* Initialise context */
280 memset ( zctx, 0, sizeof ( *zctx ) );
281
282 /* Parse header */
283 if ( image->len < sizeof ( *zhdr ) ) {
284 DBGC ( image, "ZIMG %s too short for header\n",
285 image->name );
286 return -ENOEXEC;
287 }
288 zhdr = image->data;
289
290 /* Check magic value */
291 if ( zhdr->magic != cpu_to_le32 ( ZIMG_MAGIC ) ) {
292 DBGC ( image, "ZIMG %s bad magic value %#08x\n",
293 image->name, le32_to_cpu ( zhdr->magic ) );
294 return -ENOEXEC;
295 }
296
297 /* Record and check offset and length */
298 zctx->offset = le32_to_cpu ( zhdr->offset );
299 zctx->len = le32_to_cpu ( zhdr->len );
300 if ( ( zctx->offset > image->len ) ||
301 ( zctx->len > ( image->len - zctx->offset ) ) ) {
302 DBGC ( image, "ZIMG %s bad range [+%#zx,+%#zx)/%#zx\n",
303 image->name, zctx->offset,
304 (zctx->offset + zctx->len ), image->len );
305 return -ENOEXEC;
306 }
307
308 /* Record compression type */
309 zctx->type.raw = zhdr->type;
310
311 return 0;
312}
#define ZIMG_MAGIC
Compressed kernel image magic value.
Definition lkrn.h:79
uint32_t raw
Raw type.
Definition lkrn.h:90
union zimg_context::@135361332027261305314226050111277005146143137103 type
Compression type.
size_t len
Length of compressed data.
Definition lkrn.h:86
size_t offset
Offset to compressed data.
Definition lkrn.h:84
Compressed kernel image header.
Definition lkrn.h:63
uint32_t len
Length of payload.
Definition lkrn.h:71
uint32_t offset
Offset to payload.
Definition lkrn.h:69
uint32_t type
Compression type.
Definition lkrn.h:75
uint32_t magic
Magic.
Definition lkrn.h:67

References cpu_to_le32, image::data, DBGC, ENOEXEC, le32_to_cpu, image::len, zimg_context::len, zimg_header::len, zimg_header::magic, memset(), image::name, zimg_context::offset, zimg_header::offset, zimg_context::raw, zimg_context::type, zimg_header::type, and ZIMG_MAGIC.

Referenced by zimg_extract(), and zimg_probe().

◆ zimg_extract()

int zimg_extract ( struct image * image,
struct image * extracted )
static

Extract compresed kernel image.

Parameters
imageCompressed kernel image
extractedExtracted image
Return values
rcReturn status code

Definition at line 321 of file lkrn.c.

321 {
322 struct zimg_context zctx;
323 const void *payload;
324 int rc;
325
326 /* Parse header */
327 if ( ( rc = zimg_parse ( image, &zctx ) ) != 0 )
328 return rc;
329 DBGC ( image, "ZIMG %s has %s-compressed payload at [+%#zx,+%#zx)\n",
330 image->name, zctx.type.string, zctx.offset,
331 ( zctx.offset + zctx.len ) );
332
333 /* Extract compressed payload */
334 payload = ( image->data + zctx.offset );
335 if ( ( rc = image_set_data ( extracted, payload, zctx.len ) ) != 0 ) {
336 DBGC ( image, "ZIMG %s could not extract: %s\n",
337 image->name, strerror ( rc ) );
338 return rc;
339 }
340
341 return 0;
342}
int image_set_data(struct image *image, const void *data, size_t len)
Set image data.
Definition image.c:270
static int zimg_parse(struct image *image, struct zimg_context *zctx)
Parse compressed kernel image.
Definition lkrn.c:276
Compressed kernel image context.
Definition lkrn.h:82

References image::data, DBGC, image_set_data(), zimg_context::len, image::name, zimg_context::offset, rc, strerror(), zimg_context::string, zimg_context::type, and zimg_parse().

◆ zimg_probe()

int zimg_probe ( struct image * image)
static

Probe compressed kernel image.

Parameters
imageCompressed kernel image
Return values
rcReturn status code

Definition at line 350 of file lkrn.c.

350 {
351 struct zimg_context zctx;
352 int rc;
353
354 /* Parse header */
355 if ( ( rc = zimg_parse ( image, &zctx ) ) != 0 )
356 return rc;
357
358 DBGC ( image, "ZIMG %s is a %s-compressed Linux kernel\n",
359 image->name, zctx.type.string );
360 return 0;
361}

References DBGC, image::name, rc, zimg_context::string, zimg_context::type, and zimg_parse().