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