1
/******************************************************************************
3
* Loads simple binary images. It's like a .COM file in MS-DOS. No headers are
4
* present. The only requirement is that it must have a xen_bin_image table
5
* somewhere in the first 8192 bytes, starting on a 32-bit aligned address.
6
* Those familiar with the multiboot specification should recognize this, it's
7
* (almost) the same as the multiboot header.
8
* The layout of the xen_bin_image table is:
10
* Offset Type Name Note
11
* 0 uint32_t magic required
12
* 4 uint32_t flags required
13
* 8 uint32_t checksum required
14
* 12 uint32_t header_addr required
15
* 16 uint32_t load_addr required
16
* 20 uint32_t load_end_addr required
17
* 24 uint32_t bss_end_addr required
18
* 28 uint32_t entry_addr required
21
* Magic number identifying the table. For images to be loaded by Xen 3, the
22
* magic value is 0x336ec578 ("xEn3" with the 0x80 bit of the "E" set).
24
* bit 0: indicates whether the image needs to be loaded on a page boundary
25
* bit 1: reserved, must be 0 (the multiboot spec uses this bit to indicate
26
* that memory info should be passed to the image)
27
* bit 2: reserved, must be 0 (the multiboot spec uses this bit to indicate
28
* that the bootloader should pass video mode info to the image)
29
* bit 16: reserved, must be 1 (the multiboot spec uses this bit to indicate
30
* that the values in the fields header_addr - entry_addr are
32
* All other bits should be set to 0.
34
* When added to "magic" and "flags", the resulting value should be 0.
36
* Contains the virtual address corresponding to the beginning of the
37
* table - the memory location at which the magic value is supposed to be
38
* loaded. This field serves to synchronize the mapping between OS image
39
* offsets and virtual memory addresses.
41
* Contains the virtual address of the beginning of the text segment. The
42
* offset in the OS image file at which to start loading is defined by the
43
* offset at which the table was found, minus (header addr - load addr).
44
* load addr must be less than or equal to header addr.
46
* Contains the virtual address of the end of the data segment.
47
* (load_end_addr - load_addr) specifies how much data to load. This implies
48
* that the text and data segments must be consecutive in the OS image. If
49
* this field is zero, the domain builder assumes that the text and data
50
* segments occupy the whole OS image file.
52
* Contains the virtual address of the end of the bss segment. The domain
53
* builder initializes this area to zero, and reserves the memory it occupies
54
* to avoid placing boot modules and other data relevant to the loaded image
55
* in that area. If this field is zero, the domain builder assumes that no bss
58
* The virtual address at which to start execution of the loaded image.
60
* Some of the field descriptions were copied from "The Multiboot
61
* Specification", Copyright 1995, 96 Bryan Ford <baford@cs.utah.edu>,
62
* Erich Stefan Boleyn <erich@uruk.org> Copyright 1999, 2000, 2001, 2002
63
* Free Software Foundation, Inc.
69
#include "xg_private.h"
72
#define round_pgup(_p) (((_p)+(PAGE_SIZE_X86-1))&PAGE_MASK_X86)
73
#define round_pgdown(_p) ((_p)&PAGE_MASK_X86)
75
struct xen_bin_image_table
82
uint32_t load_end_addr;
83
uint32_t bss_end_addr;
87
#define XEN_MULTIBOOT_MAGIC3 0x336ec578
89
#define XEN_MULTIBOOT_FLAG_ALIGN4K 0x00000001
90
#define XEN_MULTIBOOT_FLAG_NEEDMEMINFO 0x00000002
91
#define XEN_MULTIBOOT_FLAG_NEEDVIDINFO 0x00000004
92
#define XEN_MULTIBOOT_FLAG_ADDRSVALID 0x00010000
93
#define XEN_MULTIBOOT_FLAG_PAE_SHIFT 14
94
#define XEN_MULTIBOOT_FLAG_PAE_MASK (3 << XEN_MULTIBOOT_FLAG_PAE_SHIFT)
96
/* Flags we test for */
97
#define FLAGS_MASK ((~ 0) & (~ XEN_MULTIBOOT_FLAG_ALIGN4K) & \
98
(~ XEN_MULTIBOOT_FLAG_PAE_MASK))
99
#define FLAGS_REQUIRED XEN_MULTIBOOT_FLAG_ADDRSVALID
101
/* --------------------------------------------------------------------- */
103
static struct xen_bin_image_table *find_table(struct xc_dom_image *dom)
105
struct xen_bin_image_table *table;
109
probe_ptr = dom->kernel_blob;
110
probe_end = dom->kernel_blob + dom->kernel_size - sizeof(*table);
111
if ( (void*)probe_end > (dom->kernel_blob + 8192) )
112
probe_end = dom->kernel_blob + 8192;
114
for ( table = NULL; probe_ptr < probe_end; probe_ptr++ )
116
if ( *probe_ptr == XEN_MULTIBOOT_MAGIC3 )
118
table = (struct xen_bin_image_table *) probe_ptr;
119
/* Checksum correct? */
120
if ( (table->magic + table->flags + table->checksum) == 0 )
127
static int xc_dom_probe_bin_kernel(struct xc_dom_image *dom)
129
return find_table(dom) ? 0 : -EINVAL;
132
static int xc_dom_parse_bin_kernel(struct xc_dom_image *dom)
134
struct xen_bin_image_table *image_info;
135
char *image = dom->kernel_blob;
136
size_t image_size = dom->kernel_size;
138
uint32_t load_end_addr;
139
uint32_t bss_end_addr;
142
image_info = find_table(dom);
146
xc_dom_printf("%s: multiboot header fields\n", __FUNCTION__);
147
xc_dom_printf(" flags: 0x%" PRIx32 "\n", image_info->flags);
148
xc_dom_printf(" header_addr: 0x%" PRIx32 "\n", image_info->header_addr);
149
xc_dom_printf(" load_addr: 0x%" PRIx32 "\n", image_info->load_addr);
150
xc_dom_printf(" load_end_addr: 0x%" PRIx32 "\n", image_info->load_end_addr);
151
xc_dom_printf(" bss_end_addr: 0x%" PRIx32 "\n", image_info->bss_end_addr);
152
xc_dom_printf(" entry_addr: 0x%" PRIx32 "\n", image_info->entry_addr);
154
/* Check the flags */
155
if ( (image_info->flags & FLAGS_MASK) != FLAGS_REQUIRED )
157
xc_dom_panic(XC_INVALID_KERNEL,
158
"%s: xen_bin_image_table flags required "
159
"0x%08" PRIx32 " found 0x%08" PRIx32 "\n",
160
__FUNCTION__, FLAGS_REQUIRED, image_info->flags & FLAGS_MASK);
164
/* Sanity check on the addresses */
165
if ( (image_info->header_addr < image_info->load_addr) ||
166
((char *) image_info - image) <
167
(image_info->header_addr - image_info->load_addr) )
169
xc_dom_panic(XC_INVALID_KERNEL, "%s: Invalid header_addr.",
174
start_addr = image_info->header_addr - ((char *)image_info - image);
175
load_end_addr = image_info->load_end_addr ?: start_addr + image_size;
176
bss_end_addr = image_info->bss_end_addr ?: load_end_addr;
178
xc_dom_printf("%s: calculated addresses\n", __FUNCTION__);
179
xc_dom_printf(" start_addr: 0x%" PRIx32 "\n", start_addr);
180
xc_dom_printf(" load_end_addr: 0x%" PRIx32 "\n", load_end_addr);
181
xc_dom_printf(" bss_end_addr: 0x%" PRIx32 "\n", bss_end_addr);
183
if ( (start_addr + image_size) < load_end_addr )
185
xc_dom_panic(XC_INVALID_KERNEL, "%s: Invalid load_end_addr.\n",
190
if ( bss_end_addr < load_end_addr)
192
xc_dom_panic(XC_INVALID_KERNEL, "%s: Invalid bss_end_addr.\n",
197
dom->kernel_seg.vstart = image_info->load_addr;
198
dom->kernel_seg.vend = bss_end_addr;
199
dom->parms.virt_base = start_addr;
200
dom->parms.virt_entry = image_info->entry_addr;
202
pae_flags = image_info->flags & XEN_MULTIBOOT_FLAG_PAE_MASK;
203
switch (pae_flags >> XEN_MULTIBOOT_FLAG_PAE_SHIFT) {
205
dom->guest_type = "xen-3.0-x86_32";
208
dom->guest_type = "xen-3.0-x86_32p";
211
dom->guest_type = "xen-3.0-x86_64";
214
/* Kernel detects PAE at runtime. So try to figure whenever
215
* xen supports PAE and advertise a PAE-capable kernel in case
217
dom->guest_type = "xen-3.0-x86_32";
218
if ( strstr(dom->xen_caps, "xen-3.0-x86_32p") )
220
xc_dom_printf("%s: PAE fixup\n", __FUNCTION__);
221
dom->guest_type = "xen-3.0-x86_32p";
229
static int xc_dom_load_bin_kernel(struct xc_dom_image *dom)
231
struct xen_bin_image_table *image_info;
232
char *image = dom->kernel_blob;
234
size_t image_size = dom->kernel_size;
236
uint32_t load_end_addr;
237
uint32_t bss_end_addr;
238
uint32_t skip, text_size, bss_size;
240
image_info = find_table(dom);
244
start_addr = image_info->header_addr - ((char *)image_info - image);
245
load_end_addr = image_info->load_end_addr ?: start_addr + image_size;
246
bss_end_addr = image_info->bss_end_addr ?: load_end_addr;
248
/* It's possible that we need to skip the first part of the image */
249
skip = image_info->load_addr - start_addr;
250
text_size = load_end_addr - image_info->load_addr;
251
bss_size = bss_end_addr - load_end_addr;
253
xc_dom_printf("%s: calculated sizes\n", __FUNCTION__);
254
xc_dom_printf(" skip: 0x%" PRIx32 "\n", skip);
255
xc_dom_printf(" text_size: 0x%" PRIx32 "\n", text_size);
256
xc_dom_printf(" bss_size: 0x%" PRIx32 "\n", bss_size);
258
dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart);
259
memcpy(dest, image + skip, text_size);
260
memset(dest + text_size, 0, bss_size);
265
/* ------------------------------------------------------------------------ */
267
static struct xc_dom_loader bin_loader = {
268
.name = "multiboot-binary",
269
.probe = xc_dom_probe_bin_kernel,
270
.parser = xc_dom_parse_bin_kernel,
271
.loader = xc_dom_load_bin_kernel,
274
static void __init register_loader(void)
276
xc_dom_register_loader(&bin_loader);
285
* indent-tabs-mode: nil