summaryrefslogtreecommitdiff
path: root/xen/common/gunzip.c
blob: 71ec5f26bea0ad54a051c62a860ff8d00f338de3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include <xen/errno.h>
#include <xen/gunzip.h>
#include <xen/init.h>
#include <xen/lib.h>
#include <xen/mm.h>

#define HEAPORDER 3

static unsigned char *__initdata window;
#define memptr long
static memptr __initdata free_mem_ptr;
static memptr __initdata free_mem_end_ptr;

#define WSIZE           0x80000000

static unsigned char *__initdata inbuf;
static unsigned int __initdata insize;

/* Index of next byte to be processed in inbuf: */
static unsigned int __initdata inptr;

/* Bytes in output buffer: */
static unsigned int __initdata outcnt;

#define OF(args)        args

#define memzero(s, n)   memset((s), 0, (n))

typedef unsigned char   uch;
typedef unsigned short  ush;
typedef unsigned long   ulg;

#define get_byte()      (inptr < insize ? inbuf[inptr++] : fill_inbuf())

/* Diagnostic functions */
#ifdef DEBUG
#  define Assert(cond, msg) do { if (!(cond)) error(msg); } while (0)
#  define Trace(x)      do { fprintf x; } while (0)
#  define Tracev(x)     do { if (verbose) fprintf x ; } while (0)
#  define Tracevv(x)    do { if (verbose > 1) fprintf x ; } while (0)
#  define Tracec(c, x)  do { if (verbose && (c)) fprintf x ; } while (0)
#  define Tracecv(c, x) do { if (verbose > 1 && (c)) fprintf x ; } while (0)
#else
#  define Assert(cond, msg)
#  define Trace(x)
#  define Tracev(x)
#  define Tracevv(x)
#  define Tracec(c, x)
#  define Tracecv(c, x)
#endif

static long __initdata bytes_out;
static void flush_window(void);

static __init void error(char *x)
{
    panic("%s\n", x);
}

static __init int fill_inbuf(void)
{
        error("ran out of input data");
        return 0;
}


#include "inflate.c"

static __init void flush_window(void)
{
    /*
     * The window is equal to the output buffer therefore only need to
     * compute the crc.
     */
    unsigned long c = crc;
    unsigned int n;
    unsigned char *in, ch;

    in = window;
    for ( n = 0; n < outcnt; n++ )
    {
        ch = *in++;
        c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
    }
    crc = c;

    bytes_out += (unsigned long)outcnt;
    outcnt = 0;
}

__init int gzip_check(char *image, unsigned long image_len)
{
    unsigned char magic0, magic1;

    if ( image_len < 2 )
        return 0;

    magic0 = (unsigned char)image[0];
    magic1 = (unsigned char)image[1];

    return (magic0 == 0x1f) && ((magic1 == 0x8b) || (magic1 == 0x9e));
}

__init int perform_gunzip(char *output, char *image, unsigned long image_len)
{
    int rc;

    if ( !gzip_check(image, image_len) )
        return 1;

    window = (unsigned char *)output;

    free_mem_ptr = (unsigned long)alloc_xenheap_pages(HEAPORDER, 0);
    if ( !free_mem_ptr )
        return -ENOMEM;

    free_mem_end_ptr = free_mem_ptr + (PAGE_SIZE << HEAPORDER);
    init_allocator();

    inbuf = (unsigned char *)image;
    insize = image_len;
    inptr = 0;
    bytes_out = 0;

    makecrc();

    if ( gunzip() < 0 )
    {
        rc = -EINVAL;
    }
    else
    {
        rc = 0;
    }

    free_xenheap_pages((void *)free_mem_ptr, HEAPORDER);

    return rc;
}