1 /*
2 * Xen domain builder -- ELF bits.
3 *
4 * Parse and load ELF kernel images.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation;
9 * version 2.1 of the License.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; If not, see <http://www.gnu.org/licenses/>.
18 *
19 * written 2006 by Gerd Hoffmann <kraxel@suse.de>.
20 *
21 */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <inttypes.h>
27
28 #include "xg_private.h"
29 #include "xc_dom.h"
30 #include "xc_bitops.h"
31
32 #define XEN_VER "xen-3.0"
33
34 /* ------------------------------------------------------------------------ */
35
log_callback(struct elf_binary * elf,void * caller_data,bool iserr,const char * fmt,va_list al)36 static void log_callback(struct elf_binary *elf, void *caller_data,
37 bool iserr, const char *fmt, va_list al) {
38 xc_interface *xch = caller_data;
39
40 xc_reportv(xch,
41 xch->dombuild_logger ? xch->dombuild_logger : xch->error_handler,
42 iserr ? XTL_ERROR : XTL_DETAIL,
43 iserr ? XC_INVALID_KERNEL : XC_ERROR_NONE,
44 fmt, al);
45 }
46
xc_elf_set_logfile(xc_interface * xch,struct elf_binary * elf,int verbose)47 void xc_elf_set_logfile(xc_interface *xch, struct elf_binary *elf,
48 int verbose) {
49 elf_set_log(elf, log_callback, xch, verbose /* convert to bool */);
50 }
51
52 /* ------------------------------------------------------------------------ */
53
xc_dom_guest_type(struct xc_dom_image * dom,struct elf_binary * elf)54 static char *xc_dom_guest_type(struct xc_dom_image *dom,
55 struct elf_binary *elf)
56 {
57 uint64_t machine = elf_uval(elf, elf->ehdr, e_machine);
58
59 if ( dom->container_type == XC_DOM_HVM_CONTAINER &&
60 dom->parms.phys_entry != UNSET_ADDR32 )
61 return "hvm-3.0-x86_32";
62 if ( dom->container_type == XC_DOM_HVM_CONTAINER )
63 {
64 xc_dom_panic(dom->xch, XC_INVALID_KERNEL,
65 "%s: image not capable of booting inside a HVM container",
66 __FUNCTION__);
67 return "xen-3.0-unknown";
68 }
69
70 switch ( machine )
71 {
72 case EM_386:
73 switch ( dom->parms.pae )
74 {
75 case XEN_PAE_BIMODAL:
76 if ( strstr(dom->xen_caps, "xen-3.0-x86_32p") )
77 return "xen-3.0-x86_32p";
78 return "xen-3.0-x86_32";
79 case XEN_PAE_EXTCR3:
80 case XEN_PAE_YES:
81 return "xen-3.0-x86_32p";
82 case XEN_PAE_NO:
83 default:
84 return "xen-3.0-x86_32";
85 }
86 case EM_X86_64:
87 return "xen-3.0-x86_64";
88 default:
89 return "xen-3.0-unknown";
90 }
91 }
92
93 /* ------------------------------------------------------------------------ */
94 /* parse elf binary */
95
check_elf_kernel(struct xc_dom_image * dom,bool verbose)96 static elf_negerrnoval check_elf_kernel(struct xc_dom_image *dom, bool verbose)
97 {
98 if ( dom->kernel_blob == NULL )
99 {
100 if ( verbose )
101 xc_dom_panic(dom->xch,
102 XC_INTERNAL_ERROR, "%s: no kernel image loaded",
103 __FUNCTION__);
104 return -EINVAL;
105 }
106
107 if ( !elf_is_elfbinary(dom->kernel_blob, dom->kernel_size) )
108 {
109 if ( verbose )
110 xc_dom_panic(dom->xch,
111 XC_INVALID_KERNEL, "%s: kernel is not an ELF image",
112 __FUNCTION__);
113 return -EINVAL;
114 }
115 return 0;
116 }
117
xc_dom_probe_elf_kernel(struct xc_dom_image * dom)118 static elf_negerrnoval xc_dom_probe_elf_kernel(struct xc_dom_image *dom)
119 {
120 struct elf_binary elf;
121 int rc;
122
123 rc = check_elf_kernel(dom, 0);
124 if ( rc != 0 )
125 return rc;
126
127 rc = elf_init(&elf, dom->kernel_blob, dom->kernel_size);
128 if ( rc != 0 )
129 return rc;
130
131 /*
132 * We need to check that it contains Xen ELFNOTES,
133 * or else we might be trying to load a plain ELF.
134 */
135 elf_parse_binary(&elf);
136 rc = elf_xen_parse(&elf, &dom->parms);
137 if ( rc != 0 )
138 return rc;
139
140 return 0;
141 }
142
xc_dom_parse_elf_kernel(struct xc_dom_image * dom)143 static elf_errorstatus xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
144 /*
145 * This function sometimes returns -1 for error and sometimes
146 * an errno value. ?!?!
147 */
148 {
149 struct elf_binary *elf;
150 elf_errorstatus rc;
151
152 rc = check_elf_kernel(dom, 1);
153 if ( rc != 0 )
154 return rc;
155
156 elf = xc_dom_malloc(dom, sizeof(*elf));
157 if ( elf == NULL )
158 return -1;
159 dom->private_loader = elf;
160 rc = elf_init(elf, dom->kernel_blob, dom->kernel_size);
161 xc_elf_set_logfile(dom->xch, elf, 1);
162 if ( rc != 0 )
163 {
164 xc_dom_panic(dom->xch, XC_INVALID_KERNEL, "%s: corrupted ELF image",
165 __FUNCTION__);
166 return rc;
167 }
168
169 /* Find the section-header strings table. */
170 if ( ELF_PTRVAL_INVALID(elf->sec_strtab) )
171 {
172 xc_dom_panic(dom->xch, XC_INVALID_KERNEL, "%s: ELF image"
173 " has no shstrtab", __FUNCTION__);
174 rc = -EINVAL;
175 goto out;
176 }
177
178 /* parse binary and get xen meta info */
179 elf_parse_binary(elf);
180 if ( (rc = elf_xen_parse(elf, &dom->parms)) != 0 )
181 {
182 goto out;
183 }
184
185 if ( elf_xen_feature_get(XENFEAT_dom0, dom->parms.f_required) )
186 {
187 xc_dom_panic(dom->xch, XC_INVALID_KERNEL, "%s: Kernel does not"
188 " support unprivileged (DomU) operation", __FUNCTION__);
189 rc = -EINVAL;
190 goto out;
191 }
192
193 /* find kernel segment */
194 dom->kernel_seg.vstart = dom->parms.virt_kstart;
195 dom->kernel_seg.vend = dom->parms.virt_kend;
196
197 dom->guest_type = xc_dom_guest_type(dom, elf);
198 DOMPRINTF("%s: %s: 0x%" PRIx64 " -> 0x%" PRIx64 "",
199 __FUNCTION__, dom->guest_type,
200 dom->kernel_seg.vstart, dom->kernel_seg.vend);
201 rc = 0;
202 out:
203 if ( elf_check_broken(elf) )
204 DOMPRINTF("%s: ELF broken: %s", __FUNCTION__,
205 elf_check_broken(elf));
206
207 return rc;
208 }
209
xc_dom_load_elf_kernel(struct xc_dom_image * dom)210 static elf_errorstatus xc_dom_load_elf_kernel(struct xc_dom_image *dom)
211 {
212 struct elf_binary *elf = dom->private_loader;
213 elf_errorstatus rc;
214 xen_pfn_t pages;
215
216 elf->dest_base = xc_dom_seg_to_ptr_pages(dom, &dom->kernel_seg, &pages);
217 if ( elf->dest_base == NULL )
218 {
219 DOMPRINTF("%s: xc_dom_vaddr_to_ptr(dom,dom->kernel_seg)"
220 " => NULL", __FUNCTION__);
221 return -1;
222 }
223 elf->dest_size = pages * XC_DOM_PAGE_SIZE(dom);
224
225 rc = elf_load_binary(elf);
226 if ( rc < 0 )
227 {
228 DOMPRINTF("%s: failed to load elf binary", __FUNCTION__);
229 return rc;
230 }
231 return 0;
232 }
233
234 /* ------------------------------------------------------------------------ */
235
236 struct xc_dom_loader elf_loader = {
237 .name = "ELF-generic",
238 .probe = xc_dom_probe_elf_kernel,
239 .parser = xc_dom_parse_elf_kernel,
240 .loader = xc_dom_load_elf_kernel,
241 };
242
register_loader(void)243 static void __init register_loader(void)
244 {
245 xc_dom_register_loader(&elf_loader);
246 }
247
248 /*
249 * Local variables:
250 * mode: C
251 * c-file-style: "BSD"
252 * c-basic-offset: 4
253 * tab-width: 4
254 * indent-tabs-mode: nil
255 * End:
256 */
257