1 #include <xen/cache.h>
2 #include <xen/errno.h>
3 #include <xen/lib.h>
4 #include <xen/mm.h>
5 #include <xen/string.h>
6 #include <xen/types.h>
7 #include <xen/gunzip.h>
8 #include <xen/decompress.h>
9 #include <xen/libelf.h>
10 #include <asm/bzimage.h>
11
output_length(void * image,unsigned long image_len)12 static __init unsigned long output_length(void *image, unsigned long image_len)
13 {
14 return *(uint32_t *)(image + image_len - 4);
15 }
16
17 struct __packed setup_header {
18 uint8_t _pad0[0x1f1]; /* skip uninteresting stuff */
19 uint8_t setup_sects;
20 uint16_t root_flags;
21 uint32_t syssize;
22 uint16_t ram_size;
23 uint16_t vid_mode;
24 uint16_t root_dev;
25 uint16_t boot_flag;
26 uint16_t jump;
27 uint32_t header;
28 #define HDR_MAGIC "HdrS"
29 #define HDR_MAGIC_SZ 4
30 uint16_t version;
31 #define VERSION(h,l) (((h)<<8) | (l))
32 uint32_t realmode_swtch;
33 uint16_t start_sys;
34 uint16_t kernel_version;
35 uint8_t type_of_loader;
36 uint8_t loadflags;
37 uint16_t setup_move_size;
38 uint32_t code32_start;
39 uint32_t ramdisk_image;
40 uint32_t ramdisk_size;
41 uint32_t bootsect_kludge;
42 uint16_t heap_end_ptr;
43 uint16_t _pad1;
44 uint32_t cmd_line_ptr;
45 uint32_t initrd_addr_max;
46 uint32_t kernel_alignment;
47 uint8_t relocatable_kernel;
48 uint8_t _pad2[3];
49 uint32_t cmdline_size;
50 uint32_t hardware_subarch;
51 uint64_t hardware_subarch_data;
52 uint32_t payload_offset;
53 uint32_t payload_length;
54 };
55
bzimage_check(struct setup_header * hdr,unsigned long len)56 static __init int bzimage_check(struct setup_header *hdr, unsigned long len)
57 {
58 if ( len < sizeof(struct setup_header) )
59 return 0;
60
61 if ( memcmp(&hdr->header, HDR_MAGIC, HDR_MAGIC_SZ) != 0 )
62 return 0;
63
64 if ( hdr->version < VERSION(2,8) ) {
65 printk("Cannot load bzImage v%d.%02d at least v2.08 is required\n",
66 hdr->version >> 8, hdr->version & 0xff);
67 return -EINVAL;
68 }
69 return 1;
70 }
71
72 static unsigned long __initdata orig_image_len;
73
bzimage_headroom(void * image_start,unsigned long image_length)74 unsigned long __init bzimage_headroom(void *image_start,
75 unsigned long image_length)
76 {
77 struct setup_header *hdr = (struct setup_header *)image_start;
78 int err;
79 unsigned long headroom;
80
81 err = bzimage_check(hdr, image_length);
82 if ( err < 0 )
83 return 0;
84
85 if ( err > 0 )
86 {
87 image_start += (hdr->setup_sects + 1) * 512 + hdr->payload_offset;
88 image_length = hdr->payload_length;
89 }
90
91 if ( elf_is_elfbinary(image_start, image_length) )
92 return 0;
93
94 orig_image_len = image_length;
95 headroom = output_length(image_start, image_length);
96 if (gzip_check(image_start, image_length))
97 {
98 headroom += headroom >> 12; /* Add 8 bytes for every 32K input block */
99 headroom += (32768 + 18); /* Add 32K + 18 bytes of extra headroom */
100 } else
101 headroom += image_length;
102 headroom = (headroom + 4095) & ~4095;
103
104 return headroom;
105 }
106
bzimage_parse(void * image_base,void ** image_start,unsigned long * image_len)107 int __init bzimage_parse(void *image_base, void **image_start,
108 unsigned long *image_len)
109 {
110 struct setup_header *hdr = (struct setup_header *)(*image_start);
111 int err = bzimage_check(hdr, *image_len);
112 unsigned long output_len;
113
114 if ( err < 0 )
115 return err;
116
117 if ( err > 0 )
118 {
119 *image_start += (hdr->setup_sects + 1) * 512 + hdr->payload_offset;
120 *image_len = hdr->payload_length;
121 }
122
123 if ( elf_is_elfbinary(*image_start, *image_len) )
124 return 0;
125
126 BUG_ON(!(image_base < *image_start));
127
128 output_len = output_length(*image_start, orig_image_len);
129
130 if ( (err = perform_gunzip(image_base, *image_start, orig_image_len)) > 0 )
131 err = decompress(*image_start, orig_image_len, image_base);
132
133 if ( !err )
134 {
135 *image_start = image_base;
136 *image_len = output_len;
137 }
138
139 return err > 0 ? 0 : err;
140 }
141
142 /*
143 * Local variables:
144 * mode: C
145 * c-file-style: "BSD"
146 * c-basic-offset: 4
147 * tab-width: 4
148 * indent-tabs-mode: nil
149 * End:
150 */
151