1  #include <errno.h>
2  #include <fcntl.h>
3  #include <inttypes.h>
4  #include <stdio.h>
5  #include <stdlib.h>
6  #include <string.h>
7  #include <unistd.h>
8  #include <stdarg.h>
9  
10  #include <sys/types.h>
11  #include <sys/stat.h>
12  #include <sys/mman.h>
13  
14  #include <xg_private.h>
15  #include <xc_dom.h> /* gunzip bits */
16  
17  #include <xen/libelf/libelf.h>
18  
19  static xc_interface *xch;
20  
21  /* According to the implemation of xc_dom_probe_bzimage_kernel() function */
22  /* We add support of bzImage kernel */
23  /* Copied from tools/libxc/xc_doom_bzImageloader.c */
24  struct setup_header {
25  	uint8_t  _pad0[0x1f1];  /* skip uninteresting stuff */
26  	uint8_t  setup_sects;
27  	uint16_t root_flags;
28  	uint32_t syssize;
29  	uint16_t ram_size;
30  	uint16_t vid_mode;
31  	uint16_t root_dev;
32  	uint16_t boot_flag;
33  	uint16_t jump;
34  	uint32_t header;
35  #define HDR_MAGIC  "HdrS"
36  #define HDR_MAGIC_SZ 4
37  	uint16_t version;
38  #define VERSION(h,l) (((h)<<8) | (l))
39  	uint32_t realmode_swtch;
40  	uint16_t start_sys;
41  	uint16_t kernel_version;
42  	uint8_t  type_of_loader;
43  	uint8_t  loadflags;
44  	uint16_t setup_move_size;
45  	uint32_t code32_start;
46  	uint32_t ramdisk_image;
47  	uint32_t ramdisk_size;
48  	uint32_t bootsect_kludge;
49  	uint16_t heap_end_ptr;
50  	uint16_t _pad1;
51  	uint32_t cmd_line_ptr;
52  	uint32_t initrd_addr_max;
53  	uint32_t kernel_alignment;
54  	uint8_t  relocatable_kernel;
55  	uint8_t  _pad2[3];
56  	uint32_t cmdline_size;
57  	uint32_t hardware_subarch;
58  	uint64_t hardware_subarch_data;
59  	uint32_t payload_offset;
60  	uint32_t payload_length;
61  } __attribute__((packed));
62  
print_string_note(const char * prefix,struct elf_binary * elf,ELF_HANDLE_DECL (elf_note)note)63  static void print_string_note(const char *prefix, struct elf_binary *elf,
64  			      ELF_HANDLE_DECL(elf_note) note)
65  {
66  	printf("%s: %s\n", prefix, elf_strfmt(elf, elf_note_desc(elf, note)));
67  }
68  
print_numeric_note(const char * prefix,struct elf_binary * elf,ELF_HANDLE_DECL (elf_note)note)69  static void print_numeric_note(const char *prefix, struct elf_binary *elf,
70  			       ELF_HANDLE_DECL(elf_note) note)
71  {
72  	uint64_t value = elf_note_numeric(elf, note);
73  	unsigned descsz = elf_uval(elf, note, descsz);
74  
75  	printf("%s: %#*" PRIx64 " (%d bytes)\n",
76  	       prefix, 2+2*descsz, value, descsz);
77  }
78  
print_l1_mfn_valid_note(const char * prefix,struct elf_binary * elf,ELF_HANDLE_DECL (elf_note)note)79  static void print_l1_mfn_valid_note(const char *prefix, struct elf_binary *elf,
80  				    ELF_HANDLE_DECL(elf_note) note)
81  {
82  	unsigned descsz = elf_uval(elf, note, descsz);
83  	elf_ptrval desc = elf_note_desc(elf, note);
84  
85  	/* XXX should be able to cope with a list of values. */
86  	switch ( descsz / 2 )
87  	{
88  	case 8:
89  		printf("%s: mask=%#"PRIx64" value=%#"PRIx64"\n", prefix,
90  		       elf_access_unsigned(elf, desc, 0, 8),
91  		       elf_access_unsigned(elf, desc, 8, 8));
92  		break;
93  	case 4:
94  		printf("%s: mask=%#"PRIx32" value=%#"PRIx32"\n", prefix,
95  		       (uint32_t)elf_access_unsigned(elf, desc, 0, 4),
96  		       (uint32_t)elf_access_unsigned(elf, desc, 4, 4));
97  		break;
98  	}
99  
100  }
101  
print_notes(struct elf_binary * elf,ELF_HANDLE_DECL (elf_note)start,ELF_HANDLE_DECL (elf_note)end)102  static unsigned print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start, ELF_HANDLE_DECL(elf_note) end)
103  {
104  	ELF_HANDLE_DECL(elf_note) note;
105  	unsigned notes_found = 0;
106  	const char *this_note_name;
107  
108  	for ( note = start; ELF_HANDLE_PTRVAL(note) < ELF_HANDLE_PTRVAL(end); note = elf_note_next(elf, note) )
109  	{
110  		this_note_name = elf_note_name(elf, note);
111  		if (NULL == this_note_name)
112  			continue;
113  		if (0 != strcmp(this_note_name, "Xen"))
114  			continue;
115  
116  		notes_found++;
117  
118  		switch(elf_uval(elf, note, type))
119  		{
120  		case XEN_ELFNOTE_INFO:
121  			print_string_note("INFO", elf , note);
122  			break;
123  		case XEN_ELFNOTE_ENTRY:
124  			print_numeric_note("ENTRY", elf , note);
125  			break;
126  		case XEN_ELFNOTE_HYPERCALL_PAGE:
127  			print_numeric_note("HYPERCALL_PAGE", elf , note);
128  			break;
129  		case XEN_ELFNOTE_VIRT_BASE:
130  			print_numeric_note("VIRT_BASE", elf , note);
131  			break;
132  		case XEN_ELFNOTE_PADDR_OFFSET:
133  			print_numeric_note("PADDR_OFFSET", elf , note);
134  			break;
135  		case XEN_ELFNOTE_XEN_VERSION:
136  			print_string_note("XEN_VERSION", elf , note);
137  			break;
138  		case XEN_ELFNOTE_GUEST_OS:
139  			print_string_note("GUEST_OS", elf , note);
140  			break;
141  		case XEN_ELFNOTE_GUEST_VERSION:
142  			print_string_note("GUEST_VERSION", elf , note);
143  			break;
144  		case XEN_ELFNOTE_LOADER:
145  			print_string_note("LOADER", elf , note);
146  			break;
147  		case XEN_ELFNOTE_PAE_MODE:
148  			print_string_note("PAE_MODE", elf , note);
149  			break;
150  		case XEN_ELFNOTE_FEATURES:
151  			print_string_note("FEATURES", elf , note);
152  			break;
153  		case XEN_ELFNOTE_HV_START_LOW:
154  			print_numeric_note("HV_START_LOW", elf , note);
155  			break;
156  		case XEN_ELFNOTE_SUSPEND_CANCEL:
157  			print_numeric_note("SUSPEND_CANCEL", elf, note);
158  			break;
159  		case XEN_ELFNOTE_L1_MFN_VALID:
160  			print_l1_mfn_valid_note("L1_MFN_VALID", elf , note);
161  			break;
162  		case XEN_ELFNOTE_PHYS32_ENTRY:
163  			print_numeric_note("PHYS32_ENTRY", elf , note);
164  			break;
165  		default:
166  			printf("unknown note type %#x\n",
167  			       (unsigned)elf_uval(elf, note, type));
168  			break;
169  		}
170  	}
171  	return notes_found;
172  }
173  
main(int argc,char ** argv)174  int main(int argc, char **argv)
175  {
176  	const char *f;
177  	int fd;
178  	unsigned h,size,usize,count;
179  	void *image,*tmp;
180  	struct stat st;
181  	struct elf_binary elf;
182  	ELF_HANDLE_DECL(elf_shdr) shdr;
183  	unsigned notes_found = 0;
184  
185  	struct setup_header *hdr;
186  	uint64_t payload_offset, payload_length;
187  
188  	if (argc != 2)
189  	{
190  		fprintf(stderr, "Usage: readnotes <elfimage>\n");
191  		return 1;
192  	}
193  	f = argv[1];
194  
195          xch = xc_interface_open(0,0,XC_OPENFLAG_DUMMY);
196  
197  	fd = open(f, O_RDONLY);
198  	if (fd == -1)
199  	{
200  		fprintf(stderr, "Unable to open %s: %s\n", f, strerror(errno));
201  		return 1;
202  	}
203  	if (fstat(fd, &st) == -1)
204  	{
205  		fprintf(stderr, "Unable to determine size of %s: %s\n",
206  			f, strerror(errno));
207  		return 1;
208  	}
209  
210  	image = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
211  	if (image == MAP_FAILED)
212  	{
213  		fprintf(stderr, "Unable to map %s: %s\n", f, strerror(errno));
214  		return 1;
215  	}
216  
217  	/* Check the magic of bzImage kernel */
218  	hdr = (struct setup_header *)image;
219  	if ( memcmp(&hdr->header, HDR_MAGIC, HDR_MAGIC_SZ) == 0 )
220  	{
221  		if ( hdr->version < VERSION(2,8) )
222  		{
223  			printf("%s: boot protocol too old (%04x)", __FUNCTION__, hdr->version);
224  			return 1;
225  		}
226  
227  		/* upcast to 64 bits to avoid overflow */
228  		/* setup_sects is u8 and so cannot overflow */
229  		payload_offset = (hdr->setup_sects + 1) * 512;
230  		payload_offset += hdr->payload_offset;
231  		payload_length = hdr->payload_length;
232  
233  		if ( payload_offset >= st.st_size )
234  		{
235  			printf("%s: payload offset overflow", __FUNCTION__);
236  			return 1;
237  		}
238  		if ( (payload_offset + payload_length) > st.st_size )
239  		{
240  			printf("%s: payload length overflow", __FUNCTION__);
241  			return 1;
242  		}
243  
244  		image = image + payload_offset;
245  		size = payload_length;
246  	} else {
247  		size = st.st_size;
248  	}
249  
250  	usize = xc_dom_check_gzip(xch, image, size);
251  	if (usize)
252  	{
253  		tmp = malloc(usize);
254  		xc_dom_do_gunzip(xch, image, size, tmp, usize);
255  		image = tmp;
256  		size = usize;
257  	}
258  
259  	if (0 != elf_init(&elf, image, size))
260  	{
261  		fprintf(stderr, "File %s is not an ELF image\n", f);
262  		return 1;
263  	}
264  	xc_elf_set_logfile(xch, &elf, 0);
265  
266  	count = elf_phdr_count(&elf);
267  	for ( h=0; h < count; h++)
268  	{
269  		ELF_HANDLE_DECL(elf_phdr) phdr;
270  		phdr = elf_phdr_by_index(&elf, h);
271  		if (elf_uval(&elf, phdr, p_type) != PT_NOTE)
272  			continue;
273  
274  		/* Some versions of binutils do not correctly set
275  		 * p_offset for note segments.
276  		 */
277  		if (elf_uval(&elf, phdr, p_offset) == 0)
278  			continue;
279  
280  		notes_found = print_notes(&elf,
281  					  ELF_MAKE_HANDLE(elf_note, elf_segment_start(&elf, phdr)),
282  					  ELF_MAKE_HANDLE(elf_note, elf_segment_end(&elf, phdr)));
283  	}
284  
285  	if ( notes_found == 0 )
286  	{
287  		count = elf_shdr_count(&elf);
288  		for ( h=0; h < count; h++)
289  		{
290  			ELF_HANDLE_DECL(elf_shdr) shdr;
291  			shdr = elf_shdr_by_index(&elf, h);
292  			if (elf_uval(&elf, shdr, sh_type) != SHT_NOTE)
293  				continue;
294  			notes_found = print_notes(&elf,
295  						  ELF_MAKE_HANDLE(elf_note, elf_section_start(&elf, shdr)),
296  						  ELF_MAKE_HANDLE(elf_note, elf_section_end(&elf, shdr)));
297  			if ( notes_found )
298  				fprintf(stderr, "using notes from SHT_NOTE section\n");
299  
300  		}
301  	}
302  
303  	shdr = elf_shdr_by_name(&elf, "__xen_guest");
304  	if (ELF_HANDLE_VALID(shdr))
305  		printf("__xen_guest: %s\n",
306                         elf_strfmt(&elf, elf_section_start(&elf, shdr)));
307  
308  	if (elf_check_broken(&elf))
309  		printf("warning: broken ELF: %s\n", elf_check_broken(&elf));
310  
311  	return 0;
312  }
313  
314  
315