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