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