direct-io.hg

view tools/libxc/xc_load_bin.c @ 12988:e080700efa56

[TOOLS] Fix the build. Clearly demarcate PPC-specific stuff.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Wed Dec 13 10:23:53 2006 +0000 (2006-12-13)
parents cc006f78cbe2
children 3e2d3d737624
line source
1 /******************************************************************************
2 * xc_bin_load.c
3 *
4 * Based on xc_elf_load.c
5 *
6 * Loads simple binary images. It's like a .COM file in MS-DOS. No headers are
7 * present. The only requirement is that it must have a xen_bin_image table
8 * somewhere in the first 8192 bytes, starting on a 32-bit aligned address.
9 * Those familiar with the multiboot specification should recognize this, it's
10 * (almost) the same as the multiboot header.
11 * The layout of the xen_bin_image table is:
12 *
13 * Offset Type Name Note
14 * 0 uint32_t magic required
15 * 4 uint32_t flags required
16 * 8 uint32_t checksum required
17 * 12 uint32_t header_addr required
18 * 16 uint32_t load_addr required
19 * 20 uint32_t load_end_addr required
20 * 24 uint32_t bss_end_addr required
21 * 28 uint32_t entry_addr required
22 *
23 * - magic
24 * Magic number identifying the table. For images to be loaded by Xen 3, the
25 * magic value is 0x336ec578 ("xEn3" with the 0x80 bit of the "E" set).
26 * - flags
27 * bit 0: indicates whether the image needs to be loaded on a page boundary
28 * bit 1: reserved, must be 0 (the multiboot spec uses this bit to indicate
29 * that memory info should be passed to the image)
30 * bit 2: reserved, must be 0 (the multiboot spec uses this bit to indicate
31 * that the bootloader should pass video mode info to the image)
32 * bit 16: reserved, must be 1 (the multiboot spec uses this bit to indicate
33 * that the values in the fields header_addr - entry_addr are
34 * valid)
35 * All other bits should be set to 0.
36 * - checksum
37 * When added to "magic" and "flags", the resulting value should be 0.
38 * - header_addr
39 * Contains the virtual address corresponding to the beginning of the
40 * table - the memory location at which the magic value is supposed to be
41 * loaded. This field serves to synchronize the mapping between OS image
42 * offsets and virtual memory addresses.
43 * - load_addr
44 * Contains the virtual address of the beginning of the text segment. The
45 * offset in the OS image file at which to start loading is defined by the
46 * offset at which the table was found, minus (header addr - load addr).
47 * load addr must be less than or equal to header addr.
48 * - load_end_addr
49 * Contains the virtual address of the end of the data segment.
50 * (load_end_addr - load_addr) specifies how much data to load. This implies
51 * that the text and data segments must be consecutive in the OS image. If
52 * this field is zero, the domain builder assumes that the text and data
53 * segments occupy the whole OS image file.
54 * - bss_end_addr
55 * Contains the virtual address of the end of the bss segment. The domain
56 * builder initializes this area to zero, and reserves the memory it occupies
57 * to avoid placing boot modules and other data relevant to the loaded image
58 * in that area. If this field is zero, the domain builder assumes that no bss
59 * segment is present.
60 * - entry_addr
61 * The virtual address at which to start execution of the loaded image.
62 *
63 * Some of the field descriptions were copied from "The Multiboot
64 * Specification", Copyright 1995, 96 Bryan Ford <baford@cs.utah.edu>,
65 * Erich Stefan Boleyn <erich@uruk.org> Copyright 1999, 2000, 2001, 2002
66 * Free Software Foundation, Inc.
67 */
69 #include "xg_private.h"
70 #include <stdlib.h>
72 #define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
73 #define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
75 #define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
76 #define round_pgdown(_p) ((_p)&PAGE_MASK)
78 struct xen_bin_image_table
79 {
80 unsigned long magic;
81 unsigned long flags;
82 unsigned long checksum;
83 unsigned long header_addr;
84 unsigned long load_addr;
85 unsigned long load_end_addr;
86 unsigned long bss_end_addr;
87 unsigned long entry_addr;
88 };
90 #define XEN_REACTOS_MAGIC3 0x336ec578
92 #define XEN_REACTOS_FLAG_ALIGN4K 0x00000001
93 #define XEN_REACTOS_FLAG_NEEDMEMINFO 0x00000002
94 #define XEN_REACTOS_FLAG_NEEDVIDINFO 0x00000004
95 #define XEN_REACTOS_FLAG_ADDRSVALID 0x00010000
97 /* Flags we test for */
98 #define FLAGS_MASK ((~ 0) & (~ XEN_REACTOS_FLAG_ALIGN4K))
99 #define FLAGS_REQUIRED XEN_REACTOS_FLAG_ADDRSVALID
101 static struct xen_bin_image_table *
102 findtable(const char *image, unsigned long image_size);
103 static int
104 parsebinimage(
105 const char *image, unsigned long image_size,
106 struct domain_setup_info *dsi);
107 static int
108 loadbinimage(
109 const char *image, unsigned long image_size, int xch, uint32_t dom,
110 xen_pfn_t *parray, struct domain_setup_info *dsi);
112 int probe_bin(const char *image,
113 unsigned long image_size,
114 struct load_funcs *load_funcs)
115 {
116 if ( findtable(image, image_size) == NULL )
117 return -EINVAL;
119 load_funcs->parseimage = parsebinimage;
120 load_funcs->loadimage = loadbinimage;
122 return 0;
123 }
125 static struct xen_bin_image_table *
126 findtable(const char *image, unsigned long image_size)
127 {
128 struct xen_bin_image_table *table;
129 unsigned long *probe_ptr;
130 unsigned probe_index;
131 unsigned probe_count;
133 /* Don't go outside the image */
134 if ( image_size < sizeof(struct xen_bin_image_table) )
135 return NULL;
137 probe_count = image_size;
138 /* Restrict to first 8k */
139 if ( probe_count > 8192 )
140 probe_count = 8192;
141 probe_count = (probe_count - sizeof(struct xen_bin_image_table)) /
142 sizeof(unsigned long);
144 /* Search for the magic header */
145 probe_ptr = (unsigned long *) image;
146 table = NULL;
147 for ( probe_index = 0; probe_index < probe_count; probe_index++ )
148 {
149 if ( XEN_REACTOS_MAGIC3 == *probe_ptr )
150 {
151 table = (struct xen_bin_image_table *) probe_ptr;
152 /* Checksum correct? */
153 if ( 0 == table->magic + table->flags + table->checksum )
154 {
155 return table;
156 }
157 }
158 probe_ptr++;
159 }
161 return NULL;
162 }
164 static int parsebinimage(const char *image,
165 unsigned long image_size,
166 struct domain_setup_info *dsi)
167 {
168 struct xen_bin_image_table *image_info;
169 unsigned long start_addr;
170 unsigned long end_addr;
172 image_info = findtable(image, image_size);
173 if ( NULL == image_info )
174 {
175 ERROR("Image does not have a valid xen_bin_image_table table.");
176 return -EINVAL;
177 }
179 /* Check the flags */
180 if ( FLAGS_REQUIRED != (image_info->flags & FLAGS_MASK) )
181 {
182 ERROR("xen_bin_image_table flags required 0x%08x found 0x%08lx",
183 FLAGS_REQUIRED, image_info->flags & FLAGS_MASK);
184 return -EINVAL;
185 }
187 /* Sanity check on the addresses */
188 if ( image_info->header_addr < image_info->load_addr ||
189 ((char *) image_info - image) <
190 (image_info->header_addr - image_info->load_addr) )
191 {
192 ERROR("Invalid header_addr.");
193 return -EINVAL;
194 }
195 start_addr = image_info->header_addr - ((char *) image_info - image);
196 if ( 0 != image_info->load_end_addr &&
197 ( image_info->load_end_addr < image_info->load_end_addr ||
198 start_addr + image_size < image_info->load_end_addr ) )
199 {
200 ERROR("Invalid load_end_addr");
201 return -EINVAL;
202 }
203 end_addr = (0 == image_info->load_end_addr ? start_addr + image_size :
204 image_info->load_end_addr);
205 if ( 0 != image_info->bss_end_addr &&
206 image_info->bss_end_addr < end_addr )
207 {
208 ERROR("Invalid bss_end_addr");
209 return -EINVAL;
210 }
212 dsi->v_start = image_info->load_addr;
213 if ( 0 != image_info->bss_end_addr )
214 {
215 dsi->v_end = image_info->bss_end_addr;
216 }
217 else if ( 0 != image_info->load_end_addr )
218 {
219 dsi->v_end = image_info->load_end_addr;
220 }
221 else
222 {
223 dsi->v_end = image_info->load_addr + image_size -
224 (((char *) image_info - image) -
225 (image_info->header_addr - image_info->load_addr));
226 }
227 dsi->v_kernstart = dsi->v_start;
228 dsi->v_kernend = dsi->v_end;
229 dsi->v_kernentry = image_info->entry_addr;
230 dsi->__xen_guest_string = NULL;
232 return 0;
233 }
235 static int
236 loadbinimage(
237 const char *image, unsigned long image_size, int xch, uint32_t dom,
238 xen_pfn_t *parray, struct domain_setup_info *dsi)
239 {
240 unsigned long size;
241 char *va;
242 unsigned long done, chunksz;
243 struct xen_bin_image_table *image_info;
245 image_info = findtable(image, image_size);
246 if ( NULL == image_info )
247 {
248 ERROR("Image does not have a valid xen_bin_image_table table.");
249 return -EINVAL;
250 }
252 /* Determine image size */
253 if ( 0 == image_info->load_end_addr )
254 {
255 size = image_size - (((char *) image_info - image) -
256 (image_info->header_addr -
257 image_info->load_addr));
258 }
259 else
260 {
261 size = image_info->load_end_addr - image_info->load_addr;
262 }
264 /* It's possible that we need to skip the first part of the image */
265 image += ((char *)image_info - image) -
266 (image_info->header_addr - image_info->load_addr);
268 for ( done = 0; done < size; done += chunksz )
269 {
270 va = xc_map_foreign_range(
271 xch, dom, PAGE_SIZE, PROT_WRITE, parray[done>>PAGE_SHIFT]);
272 chunksz = size - done;
273 if ( chunksz > PAGE_SIZE )
274 chunksz = PAGE_SIZE;
275 memcpy(va, image + done, chunksz);
276 munmap(va, PAGE_SIZE);
277 }
279 if ( 0 != image_info->bss_end_addr &&
280 image_info->load_addr + size < image_info->bss_end_addr )
281 {
282 size = image_info->bss_end_addr - image_info->load_addr;
283 }
284 for ( ; done < size; done += chunksz )
285 {
286 va = xc_map_foreign_range(
287 xch, dom, PAGE_SIZE, PROT_WRITE, parray[done>>PAGE_SHIFT]);
288 chunksz = size - done;
289 if ( chunksz > (PAGE_SIZE - (done & (PAGE_SIZE-1))) )
290 chunksz = PAGE_SIZE - (done & (PAGE_SIZE-1));
291 memset(va + (done & (PAGE_SIZE-1)), 0, chunksz);
292 munmap(va, PAGE_SIZE);
293 }
295 return 0;
296 }
298 /*
299 * Local variables:
300 * mode: C
301 * c-set-style: "BSD"
302 * c-basic-offset: 4
303 * tab-width: 4
304 * indent-tabs-mode: nil
305 * End:
306 */