1 /*
2 * parse xen-specific information out of elf kernel binaries.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation;
7 * version 2.1 of the License.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "libelf-private.h"
19
20 #if defined(__i386__) || defined(__x86_64__)
21 #define ARCH_PHYS_MIN_DEFAULT 0
22 #define ARCH_PHYS_MAX_DEFAULT (GB(4) - 1)
23 #else
24 #define ARCH_PHYS_MIN_DEFAULT 0
25 #define ARCH_PHYS_MAX_DEFAULT 0
26 #endif
27
28 /* ------------------------------------------------------------------------ */
29 /* xen features */
30
31 static const char *const elf_xen_feature_names[] = {
32 [XENFEAT_writable_page_tables] = "writable_page_tables",
33 [XENFEAT_writable_descriptor_tables] = "writable_descriptor_tables",
34 [XENFEAT_auto_translated_physmap] = "auto_translated_physmap",
35 [XENFEAT_supervisor_mode_kernel] = "supervisor_mode_kernel",
36 [XENFEAT_pae_pgdir_above_4gb] = "pae_pgdir_above_4gb",
37 [XENFEAT_hvm_callback_vector] = "hvm_callback_vector",
38 [XENFEAT_dom0] = "dom0"
39 };
40 static const unsigned elf_xen_features =
41 sizeof(elf_xen_feature_names) / sizeof(elf_xen_feature_names[0]);
42
elf_xen_parse_features(const char * features,uint32_t * supported,uint32_t * required)43 elf_errorstatus elf_xen_parse_features(const char *features,
44 uint32_t *supported,
45 uint32_t *required)
46 {
47 unsigned char feature[64];
48 unsigned pos, len, i;
49
50 if ( features == NULL )
51 return 0;
52
53 for ( pos = 0; features[pos] != '\0'; pos += len )
54 {
55 elf_memset_unchecked(feature, 0, sizeof(feature));
56 for ( len = 0;; len++ )
57 {
58 if ( len >= sizeof(feature)-1 )
59 break;
60 if ( features[pos + len] == '\0' )
61 break;
62 if ( features[pos + len] == '|' )
63 {
64 len++;
65 break;
66 }
67 feature[len] = features[pos + len];
68 }
69
70 for ( i = 0; i < elf_xen_features; i++ )
71 {
72 if ( !elf_xen_feature_names[i] )
73 continue;
74 if ( feature[0] == '!' )
75 {
76 /* required */
77 if ( !strcmp(feature + 1, elf_xen_feature_names[i]) )
78 {
79 elf_xen_feature_set(i, supported);
80 if ( required )
81 elf_xen_feature_set(i, required);
82 break;
83 }
84 }
85 else
86 {
87 /* supported */
88 if ( !strcmp(feature, elf_xen_feature_names[i]) )
89 {
90 elf_xen_feature_set(i, supported);
91 break;
92 }
93 }
94 }
95 if ( i == elf_xen_features && required && feature[0] == '!' )
96 return -1;
97 }
98
99 return 0;
100 }
101
102 /* ------------------------------------------------------------------------ */
103 /* xen elf notes */
104
elf_xen_parse_note(struct elf_binary * elf,struct elf_dom_parms * parms,ELF_HANDLE_DECL (elf_note)note)105 elf_errorstatus elf_xen_parse_note(struct elf_binary *elf,
106 struct elf_dom_parms *parms,
107 ELF_HANDLE_DECL(elf_note) note)
108 {
109 /* *INDENT-OFF* */
110 static const struct {
111 const char *name;
112 enum {
113 ELFNOTE_INT,
114 ELFNOTE_STRING,
115 ELFNOTE_NAME,
116 } type;
117 } note_desc[] = {
118 [XEN_ELFNOTE_ENTRY] = { "ENTRY", ELFNOTE_INT },
119 [XEN_ELFNOTE_HYPERCALL_PAGE] = { "HYPERCALL_PAGE", ELFNOTE_INT },
120 [XEN_ELFNOTE_VIRT_BASE] = { "VIRT_BASE", ELFNOTE_INT },
121 [XEN_ELFNOTE_INIT_P2M] = { "INIT_P2M", ELFNOTE_INT },
122 [XEN_ELFNOTE_PADDR_OFFSET] = { "PADDR_OFFSET", ELFNOTE_INT },
123 [XEN_ELFNOTE_HV_START_LOW] = { "HV_START_LOW", ELFNOTE_INT },
124 [XEN_ELFNOTE_XEN_VERSION] = { "XEN_VERSION", ELFNOTE_STRING },
125 [XEN_ELFNOTE_GUEST_OS] = { "GUEST_OS", ELFNOTE_STRING },
126 [XEN_ELFNOTE_GUEST_VERSION] = { "GUEST_VERSION", ELFNOTE_STRING },
127 [XEN_ELFNOTE_LOADER] = { "LOADER", ELFNOTE_STRING },
128 [XEN_ELFNOTE_PAE_MODE] = { "PAE_MODE", ELFNOTE_STRING },
129 [XEN_ELFNOTE_FEATURES] = { "FEATURES", ELFNOTE_STRING },
130 [XEN_ELFNOTE_SUPPORTED_FEATURES] = { "SUPPORTED_FEATURES", ELFNOTE_INT },
131 [XEN_ELFNOTE_BSD_SYMTAB] = { "BSD_SYMTAB", ELFNOTE_STRING },
132 [XEN_ELFNOTE_L1_MFN_VALID] = { "L1_MFN_VALID", ELFNOTE_NAME },
133 [XEN_ELFNOTE_SUSPEND_CANCEL] = { "SUSPEND_CANCEL", ELFNOTE_INT },
134 [XEN_ELFNOTE_MOD_START_PFN] = { "MOD_START_PFN", ELFNOTE_INT },
135 [XEN_ELFNOTE_PHYS32_ENTRY] = { "PHYS32_ENTRY", ELFNOTE_INT },
136 [XEN_ELFNOTE_PHYS32_RELOC] = { "PHYS32_RELOC", ELFNOTE_NAME },
137 };
138 /* *INDENT-ON* */
139
140 const char *str = NULL;
141 uint64_t val = 0;
142 unsigned int i;
143 unsigned type = elf_uval(elf, note, type);
144 unsigned descsz = elf_uval(elf, note, descsz);
145
146 if ( (type >= sizeof(note_desc) / sizeof(note_desc[0])) ||
147 (note_desc[type].name == NULL) )
148 {
149 elf_msg(elf, "ELF: note: unknown (%#x)\n", type);
150 return 0;
151 }
152
153 switch ( note_desc[type].type )
154 {
155 case ELFNOTE_STRING :
156 str = elf_strval(elf, elf_note_desc(elf, note));
157 if (str == NULL)
158 /* elf_strval will mark elf broken if it fails so no need to log */
159 return 0;
160 elf_msg(elf, "ELF: note: %s = \"%s\"\n", note_desc[type].name, str);
161 parms->elf_notes[type].type = XEN_ENT_STR;
162 parms->elf_notes[type].data.str = str;
163 break;
164
165 case ELFNOTE_INT:
166 val = elf_note_numeric(elf, note);
167 elf_msg(elf, "ELF: note: %s = %#" PRIx64 "\n", note_desc[type].name, val);
168 parms->elf_notes[type].type = XEN_ENT_LONG;
169 parms->elf_notes[type].data.num = val;
170 break;
171
172 case ELFNOTE_NAME:
173 /* NB: Newline emitted further down. */
174 elf_msg(elf, "ELF: note: %s", note_desc[type].name);
175 break;
176 }
177 parms->elf_notes[type].name = note_desc[type].name;
178
179 switch ( type )
180 {
181 case XEN_ELFNOTE_LOADER:
182 safe_strcpy(parms->loader, str);
183 break;
184 case XEN_ELFNOTE_GUEST_OS:
185 safe_strcpy(parms->guest_os, str);
186 break;
187 case XEN_ELFNOTE_GUEST_VERSION:
188 safe_strcpy(parms->guest_ver, str);
189 break;
190 case XEN_ELFNOTE_XEN_VERSION:
191 safe_strcpy(parms->xen_ver, str);
192 break;
193 case XEN_ELFNOTE_PAE_MODE:
194 if ( !strcmp(str, "yes") )
195 parms->pae = XEN_PAE_EXTCR3;
196 if ( strstr(str, "bimodal") )
197 parms->pae = XEN_PAE_BIMODAL;
198 break;
199 case XEN_ELFNOTE_BSD_SYMTAB:
200 if ( !strcmp(str, "yes") )
201 parms->bsd_symtab = 1;
202 break;
203
204 case XEN_ELFNOTE_VIRT_BASE:
205 parms->virt_base = val;
206 break;
207 case XEN_ELFNOTE_ENTRY:
208 parms->virt_entry = val;
209 break;
210 case XEN_ELFNOTE_INIT_P2M:
211 parms->p2m_base = val;
212 break;
213 case XEN_ELFNOTE_MOD_START_PFN:
214 parms->unmapped_initrd = !!val;
215 break;
216 case XEN_ELFNOTE_PADDR_OFFSET:
217 parms->elf_paddr_offset = val;
218 break;
219 case XEN_ELFNOTE_HYPERCALL_PAGE:
220 parms->virt_hypercall = val;
221 break;
222 case XEN_ELFNOTE_HV_START_LOW:
223 parms->virt_hv_start_low = val;
224 break;
225
226 case XEN_ELFNOTE_FEATURES:
227 if ( elf_xen_parse_features(str, parms->f_supported,
228 parms->f_required) )
229 return -1;
230 break;
231
232 case XEN_ELFNOTE_SUPPORTED_FEATURES:
233 for ( i = 0; i < XENFEAT_NR_SUBMAPS; ++i )
234 parms->f_supported[i] |= elf_note_numeric_array(
235 elf, note, sizeof(*parms->f_supported), i);
236 break;
237
238 case XEN_ELFNOTE_PHYS32_ENTRY:
239 parms->phys_entry = val;
240 break;
241
242 case XEN_ELFNOTE_PHYS32_RELOC:
243 parms->phys_reloc = true;
244
245 if ( descsz >= 4 )
246 {
247 parms->phys_align = elf_note_numeric_array(elf, note, 4, 0);
248 elf_msg(elf, " align: %#"PRIx32, parms->phys_align);
249 }
250 if ( descsz >= 8 )
251 {
252 parms->phys_min = elf_note_numeric_array(elf, note, 4, 1);
253 elf_msg(elf, " min: %#"PRIx32, parms->phys_min);
254 }
255 if ( descsz >= 12 )
256 {
257 parms->phys_max = elf_note_numeric_array(elf, note, 4, 2);
258 elf_msg(elf, " max: %#"PRIx32, parms->phys_max);
259 }
260
261 break;
262 }
263
264 if ( note_desc[type].type == ELFNOTE_NAME)
265 elf_msg(elf, "\n");
266
267 return 0;
268 }
269
270 #define ELF_NOTE_INVALID (~0U)
271
elf_xen_parse_notes(struct elf_binary * elf,struct elf_dom_parms * parms,elf_ptrval start,elf_ptrval end,unsigned * total_note_count)272 static unsigned elf_xen_parse_notes(struct elf_binary *elf,
273 struct elf_dom_parms *parms,
274 elf_ptrval start,
275 elf_ptrval end,
276 unsigned *total_note_count)
277 {
278 unsigned xen_elfnotes = 0;
279 ELF_HANDLE_DECL(elf_note) note;
280 const char *note_name;
281
282 parms->elf_note_start = start;
283 parms->elf_note_end = end;
284 for ( note = ELF_MAKE_HANDLE(elf_note, parms->elf_note_start);
285 ELF_HANDLE_PTRVAL(note) < parms->elf_note_end;
286 note = elf_note_next(elf, note) )
287 {
288 #ifdef __XEN__
289 process_pending_softirqs();
290 #endif
291
292 if ( *total_note_count >= ELF_MAX_TOTAL_NOTE_COUNT )
293 {
294 elf_mark_broken(elf, "too many ELF notes");
295 break;
296 }
297 (*total_note_count)++;
298 note_name = elf_note_name(elf, note);
299 if ( note_name == NULL )
300 continue;
301 if ( strcmp(note_name, "Xen") )
302 continue;
303 if ( elf_xen_parse_note(elf, parms, note) )
304 return ELF_NOTE_INVALID;
305 xen_elfnotes++;
306 }
307 return xen_elfnotes;
308 }
309
310 /* ------------------------------------------------------------------------ */
311 /* __xen_guest section */
312
elf_xen_parse_guest_info(struct elf_binary * elf,struct elf_dom_parms * parms)313 elf_errorstatus elf_xen_parse_guest_info(struct elf_binary *elf,
314 struct elf_dom_parms *parms)
315 {
316 elf_ptrval h;
317 unsigned char name[32], value[128];
318 unsigned len;
319 elf_errorstatus ret = 0;
320
321 h = parms->guest_info;
322 #define STAR(h) (elf_access_unsigned(elf, (h), 0, 1))
323 while ( STAR(h) )
324 {
325 elf_memset_unchecked(name, 0, sizeof(name));
326 elf_memset_unchecked(value, 0, sizeof(value));
327 for ( len = 0;; len++, h++ )
328 {
329 if ( len >= sizeof(name)-1 )
330 break;
331 if ( STAR(h) == '\0' )
332 break;
333 if ( STAR(h) == ',' )
334 {
335 h++;
336 break;
337 }
338 if ( STAR(h) == '=' )
339 {
340 h++;
341 for ( len = 0;; len++, h++ )
342 {
343 if ( len >= sizeof(value)-1 )
344 break;
345 if ( STAR(h) == '\0' )
346 break;
347 if ( STAR(h) == ',' )
348 {
349 h++;
350 break;
351 }
352 value[len] = STAR(h);
353 }
354 break;
355 }
356 name[len] = STAR(h);
357 }
358 elf_msg(elf, "ELF: %s=\"%s\"\n", name, value);
359
360 /* strings */
361 if ( !strcmp(name, "LOADER") )
362 safe_strcpy(parms->loader, value);
363 if ( !strcmp(name, "GUEST_OS") )
364 safe_strcpy(parms->guest_os, value);
365 if ( !strcmp(name, "GUEST_VER") )
366 safe_strcpy(parms->guest_ver, value);
367 if ( !strcmp(name, "XEN_VER") )
368 safe_strcpy(parms->xen_ver, value);
369 if ( !strcmp(name, "PAE") )
370 {
371 if ( !strcmp(value, "yes[extended-cr3]") )
372 parms->pae = XEN_PAE_EXTCR3;
373 else if ( !strncmp(value, "yes", 3) )
374 parms->pae = XEN_PAE_YES;
375 }
376 if ( !strcmp(name, "BSD_SYMTAB") )
377 parms->bsd_symtab = 1;
378
379 /* longs */
380 if ( !strcmp(name, "VIRT_BASE") )
381 parms->virt_base = strtoull(value, NULL, 0);
382 if ( !strcmp(name, "VIRT_ENTRY") )
383 parms->virt_entry = strtoull(value, NULL, 0);
384 if ( !strcmp(name, "ELF_PADDR_OFFSET") )
385 parms->elf_paddr_offset = strtoull(value, NULL, 0);
386 if ( !strcmp(name, "HYPERCALL_PAGE") )
387 parms->virt_hypercall = strtoull(value, NULL, 0) << 12;
388
389 /* other */
390 if ( !strcmp(name, "FEATURES") )
391 if ( elf_xen_parse_features(value, parms->f_supported,
392 parms->f_required) )
393 {
394 ret = -1;
395 break;
396 }
397 }
398
399 if ( (parms->virt_base != UNSET_ADDR) &&
400 (parms->virt_hypercall != UNSET_ADDR) )
401 parms->virt_hypercall += parms->virt_base;
402
403 return ret;
404 }
405
406 /* ------------------------------------------------------------------------ */
407 /* sanity checks */
408
elf_xen_note_check(struct elf_binary * elf,struct elf_dom_parms * parms,bool hvm)409 static elf_errorstatus elf_xen_note_check(struct elf_binary *elf,
410 struct elf_dom_parms *parms, bool hvm)
411 {
412 if ( (ELF_PTRVAL_INVALID(parms->elf_note_start)) &&
413 (ELF_PTRVAL_INVALID(parms->guest_info)) )
414 {
415 unsigned machine = elf_uval(elf, elf->ehdr, e_machine);
416 if ( (machine == EM_386) || (machine == EM_X86_64) )
417 {
418 elf_err(elf, "ERROR: Not a Xen-ELF image: "
419 "No ELF notes or '__xen_guest' section found\n");
420 return -1;
421 }
422 return 0;
423 }
424
425 if ( elf_uval(elf, elf->ehdr, e_machine) == EM_ARM )
426 {
427 elf_msg(elf, "ELF: Not bothering with notes on ARM\n");
428 return 0;
429 }
430
431 /* PVH only requires one ELF note to be set */
432 if ( parms->phys_entry != UNSET_ADDR32 && hvm )
433 {
434 elf_msg(elf, "ELF: Found PVH image\n");
435 return 0;
436 }
437
438 /* Check the contents of the Xen notes or guest string. */
439 if ( ((strlen(parms->loader) == 0) ||
440 strncmp(parms->loader, "generic", 7)) &&
441 ((strlen(parms->guest_os) == 0) ||
442 strncmp(parms->guest_os, "linux", 5)) )
443 {
444 elf_err(elf,
445 "ERROR: Will only load images built for the generic loader or Linux images"
446 " (Not '%.*s' and '%.*s') or with PHYS32_ENTRY set\n",
447 (int)sizeof(parms->loader), parms->loader,
448 (int)sizeof(parms->guest_os), parms->guest_os);
449 return -1;
450 }
451
452 if ( (strlen(parms->xen_ver) == 0) ||
453 strncmp(parms->xen_ver, "xen-3.0", 7) )
454 {
455 elf_err(elf, "ERROR: Xen will only load images built for Xen v3.0 "
456 "(Not '%.*s')\n",
457 (int)sizeof(parms->xen_ver), parms->xen_ver);
458 return -1;
459 }
460 return 0;
461 }
462
elf_xen_addr_calc_check(struct elf_binary * elf,struct elf_dom_parms * parms,bool hvm)463 static elf_errorstatus elf_xen_addr_calc_check(struct elf_binary *elf,
464 struct elf_dom_parms *parms, bool hvm)
465 {
466 uint64_t virt_offset;
467
468 if ( (parms->elf_paddr_offset != UNSET_ADDR) &&
469 (parms->virt_base == UNSET_ADDR) &&
470 !hvm )
471 {
472 elf_err(elf, "ERROR: ELF_PADDR_OFFSET set, VIRT_BASE unset\n");
473 return -1;
474 }
475
476 /*
477 * Initial guess for virt_base is 0 if it is not explicitly defined in the
478 * PV case. For PVH virt_base is forced to 0 because paging is disabled.
479 */
480 if ( parms->virt_base == UNSET_ADDR || hvm )
481 {
482 parms->virt_base = 0;
483 if ( !hvm )
484 elf_msg(elf, "ELF: VIRT_BASE unset, using 0\n");
485 }
486
487 /*
488 * If we are using the legacy __xen_guest section then elf_pa_off
489 * defaults to v_start in order to maintain compatibility with
490 * older hypervisors which set padd in the ELF header to
491 * virt_base.
492 *
493 * If we are using the modern ELF notes interface then the default
494 * is 0.
495 *
496 * For PVH this is forced to 0, as it's already a legacy option for PV.
497 */
498 if ( parms->elf_paddr_offset == UNSET_ADDR || hvm )
499 {
500 if ( parms->elf_note_start || hvm )
501 parms->elf_paddr_offset = 0;
502 else
503 parms->elf_paddr_offset = parms->virt_base;
504 if ( !hvm )
505 elf_msg(elf, "ELF_PADDR_OFFSET unset, using %#" PRIx64 "\n",
506 parms->elf_paddr_offset);
507 }
508
509 virt_offset = parms->virt_base - parms->elf_paddr_offset;
510 parms->virt_kstart = elf->pstart + virt_offset;
511 parms->virt_kend = elf->pend + virt_offset;
512
513 if ( parms->virt_entry == UNSET_ADDR || hvm )
514 {
515 if ( parms->phys_entry != UNSET_ADDR32 && hvm )
516 parms->virt_entry = parms->phys_entry;
517 else
518 parms->virt_entry = elf_uval(elf, elf->ehdr, e_entry);
519 }
520
521 if ( parms->bsd_symtab )
522 {
523 elf_parse_bsdsyms(elf, elf->pend);
524 if ( elf->bsd_symtab_pend )
525 parms->virt_kend = elf->bsd_symtab_pend + virt_offset;
526 }
527
528 elf_msg(elf, "ELF: addresses:\n");
529 elf_msg(elf, " virt_base = 0x%" PRIx64 "\n", parms->virt_base);
530 elf_msg(elf, " elf_paddr_offset = 0x%" PRIx64 "\n", parms->elf_paddr_offset);
531 elf_msg(elf, " virt_offset = 0x%" PRIx64 "\n", virt_offset);
532 elf_msg(elf, " virt_kstart = 0x%" PRIx64 "\n", parms->virt_kstart);
533 elf_msg(elf, " virt_kend = 0x%" PRIx64 "\n", parms->virt_kend);
534 elf_msg(elf, " virt_entry = 0x%" PRIx64 "\n", parms->virt_entry);
535 elf_msg(elf, " p2m_base = 0x%" PRIx64 "\n", parms->p2m_base);
536
537 if ( (parms->virt_kstart > parms->virt_kend) ||
538 (parms->virt_entry < parms->virt_kstart) ||
539 (parms->virt_entry > parms->virt_kend) ||
540 (parms->virt_base > parms->virt_kstart) )
541 {
542 elf_err(elf, "ERROR: ELF start or entries are out of bounds\n");
543 return -1;
544 }
545
546 if ( (parms->p2m_base != UNSET_ADDR) &&
547 (parms->p2m_base >= parms->virt_kstart) &&
548 (parms->p2m_base < parms->virt_kend) )
549 {
550 elf_err(elf, "ERROR: P->M table base is out of bounds\n");
551 return -1;
552 }
553
554 return 0;
555 }
556
557 /* ------------------------------------------------------------------------ */
558 /* glue it all together ... */
559
elf_xen_parse(struct elf_binary * elf,struct elf_dom_parms * parms,bool hvm)560 elf_errorstatus elf_xen_parse(struct elf_binary *elf,
561 struct elf_dom_parms *parms, bool hvm)
562 {
563 ELF_HANDLE_DECL(elf_shdr) shdr;
564 ELF_HANDLE_DECL(elf_phdr) phdr;
565 unsigned xen_elfnotes = 0;
566 unsigned i, count, more_notes;
567 unsigned total_note_count = 0;
568
569 elf_memset_unchecked(parms, 0, sizeof(*parms));
570 parms->virt_base = UNSET_ADDR;
571 parms->virt_entry = UNSET_ADDR;
572 parms->virt_hypercall = UNSET_ADDR;
573 parms->virt_hv_start_low = UNSET_ADDR;
574 parms->p2m_base = UNSET_ADDR;
575 parms->elf_paddr_offset = UNSET_ADDR;
576 parms->phys_entry = UNSET_ADDR32;
577 parms->phys_align = UNSET_ADDR32;
578 parms->phys_min = ARCH_PHYS_MIN_DEFAULT;
579 parms->phys_max = ARCH_PHYS_MAX_DEFAULT;
580 parms->phys_reloc = false;
581
582 /* Find and parse elf notes. */
583 count = elf_phdr_count(elf);
584 for ( i = 0; i < count; i++ )
585 {
586 phdr = elf_phdr_by_index(elf, i);
587 if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(phdr), 1) )
588 /* input has an insane program header count field */
589 break;
590 if ( elf_uval(elf, phdr, p_type) != PT_NOTE )
591 continue;
592
593 /*
594 * Some versions of binutils do not correctly set p_offset for
595 * note segments.
596 */
597 if (elf_uval(elf, phdr, p_offset) == 0)
598 continue;
599
600 more_notes = elf_xen_parse_notes(elf, parms,
601 elf_segment_start(elf, phdr),
602 elf_segment_end(elf, phdr),
603 &total_note_count);
604 if ( more_notes == ELF_NOTE_INVALID )
605 return -1;
606
607 xen_elfnotes += more_notes;
608 }
609
610 /*
611 * Fall back to any SHT_NOTE sections if no valid note segments
612 * were found.
613 */
614 if ( xen_elfnotes == 0 )
615 {
616 count = elf_shdr_count(elf);
617 for ( i = 1; i < count; i++ )
618 {
619 shdr = elf_shdr_by_index(elf, i);
620 if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
621 /* input has an insane section header count field */
622 break;
623
624 if ( elf_uval(elf, shdr, sh_type) != SHT_NOTE )
625 continue;
626
627 more_notes = elf_xen_parse_notes(elf, parms,
628 elf_section_start(elf, shdr),
629 elf_section_end(elf, shdr),
630 &total_note_count);
631
632 if ( more_notes == ELF_NOTE_INVALID )
633 return -1;
634
635 if ( xen_elfnotes == 0 && more_notes > 0 )
636 elf_msg(elf, "ELF: using notes from SHT_NOTE section\n");
637
638 xen_elfnotes += more_notes;
639 }
640
641 }
642
643 /* Finally fall back to the __xen_guest section for PV guests only. */
644 if ( xen_elfnotes == 0 && !hvm )
645 {
646 shdr = elf_shdr_by_name(elf, "__xen_guest");
647 if ( ELF_HANDLE_VALID(shdr) )
648 {
649 parms->guest_info = elf_section_start(elf, shdr);
650 parms->elf_note_start = ELF_INVALID_PTRVAL;
651 parms->elf_note_end = ELF_INVALID_PTRVAL;
652 elf_msg(elf, "ELF: __xen_guest: \"%s\"\n",
653 elf_strfmt(elf, parms->guest_info));
654 elf_xen_parse_guest_info(elf, parms);
655 }
656 }
657
658 if ( elf_xen_note_check(elf, parms, hvm) != 0 )
659 return -1;
660 if ( elf_xen_addr_calc_check(elf, parms, hvm) != 0 )
661 return -1;
662 return 0;
663 }
664
665 /*
666 * Local variables:
667 * mode: C
668 * c-file-style: "BSD"
669 * c-basic-offset: 4
670 * tab-width: 4
671 * indent-tabs-mode: nil
672 * End:
673 */
674