xref: /plan9/sys/src/9/pcboot/inflate.guts.c (revision 25210b069a6ed8c047fa67220cf1dff32812f121)
1*25210b06SDavid du Colombier /* included by expand and 9boot with different header files */
2*25210b06SDavid du Colombier 
3*25210b06SDavid du Colombier typedef struct Biobuf	Biobuf;
4*25210b06SDavid du Colombier 
5*25210b06SDavid du Colombier struct Biobuf
6*25210b06SDavid du Colombier {
7*25210b06SDavid du Colombier 	uchar *bp;
8*25210b06SDavid du Colombier 	uchar *p;
9*25210b06SDavid du Colombier 	uchar *ep;
10*25210b06SDavid du Colombier };
11*25210b06SDavid du Colombier 
12*25210b06SDavid du Colombier static ulong	Boffset(Biobuf *bp);
13*25210b06SDavid du Colombier static int	crcwrite(void *out, void *buf, int n);
14*25210b06SDavid du Colombier static ulong	get4(Biobuf *b);
15*25210b06SDavid du Colombier static int	getc(void*);
16*25210b06SDavid du Colombier static int	header(Biobuf*);
17*25210b06SDavid du Colombier static ulong	offset(Biobuf*);
18*25210b06SDavid du Colombier static int	trailer(Biobuf*, Biobuf*);
19*25210b06SDavid du Colombier 
20*25210b06SDavid du Colombier /* GZIP flags */
21*25210b06SDavid du Colombier enum {
22*25210b06SDavid du Colombier 	Ftext=		(1<<0),
23*25210b06SDavid du Colombier 	Fhcrc=		(1<<1),
24*25210b06SDavid du Colombier 	Fextra=		(1<<2),
25*25210b06SDavid du Colombier 	Fname=		(1<<3),
26*25210b06SDavid du Colombier 	Fcomment=	(1<<4),
27*25210b06SDavid du Colombier 
28*25210b06SDavid du Colombier 	GZCRCPOLY	= 0xedb88320UL,
29*25210b06SDavid du Colombier };
30*25210b06SDavid du Colombier 
31*25210b06SDavid du Colombier static ulong	*crctab;
32*25210b06SDavid du Colombier static ulong	crc;
33*25210b06SDavid du Colombier 
34*25210b06SDavid du Colombier int
gunzip(uchar * out,int outn,uchar * in,int inn)35*25210b06SDavid du Colombier gunzip(uchar *out, int outn, uchar *in, int inn)
36*25210b06SDavid du Colombier {
37*25210b06SDavid du Colombier 	Biobuf bin, bout;
38*25210b06SDavid du Colombier 	int err;
39*25210b06SDavid du Colombier 
40*25210b06SDavid du Colombier 	crc = 0;
41*25210b06SDavid du Colombier 	crctab = mkcrctab(GZCRCPOLY);
42*25210b06SDavid du Colombier 	err = inflateinit();
43*25210b06SDavid du Colombier 	if(err != FlateOk)
44*25210b06SDavid du Colombier 		print("inflateinit failed: %s\n", flateerr(err));
45*25210b06SDavid du Colombier 
46*25210b06SDavid du Colombier 	bin.bp = bin.p = in;
47*25210b06SDavid du Colombier 	bin.ep = in+inn;
48*25210b06SDavid du Colombier 	bout.bp = bout.p = out;
49*25210b06SDavid du Colombier 	bout.ep = out+outn;
50*25210b06SDavid du Colombier 
51*25210b06SDavid du Colombier 	err = header(&bin);
52*25210b06SDavid du Colombier 	if(err != FlateOk)
53*25210b06SDavid du Colombier 		return err;
54*25210b06SDavid du Colombier 
55*25210b06SDavid du Colombier 	err = inflate(&bout, crcwrite, &bin, getc);
56*25210b06SDavid du Colombier 	if(err != FlateOk)
57*25210b06SDavid du Colombier 		print("inflate failed: %s\n", flateerr(err));
58*25210b06SDavid du Colombier 
59*25210b06SDavid du Colombier 	err = trailer(&bout, &bin);
60*25210b06SDavid du Colombier 	if(err != FlateOk)
61*25210b06SDavid du Colombier 		return err;
62*25210b06SDavid du Colombier 
63*25210b06SDavid du Colombier 	return Boffset(&bout);
64*25210b06SDavid du Colombier }
65*25210b06SDavid du Colombier 
66*25210b06SDavid du Colombier static int
header(Biobuf * bin)67*25210b06SDavid du Colombier header(Biobuf *bin)
68*25210b06SDavid du Colombier {
69*25210b06SDavid du Colombier 	int i, flag;
70*25210b06SDavid du Colombier 
71*25210b06SDavid du Colombier 	if(getc(bin) != 0x1f || getc(bin) != 0x8b){
72*25210b06SDavid du Colombier 		print("bad magic\n");
73*25210b06SDavid du Colombier 		return FlateCorrupted;
74*25210b06SDavid du Colombier 	}
75*25210b06SDavid du Colombier 	if(getc(bin) != 8){
76*25210b06SDavid du Colombier 		print("unknown compression type\n");
77*25210b06SDavid du Colombier 		return FlateCorrupted;
78*25210b06SDavid du Colombier 	}
79*25210b06SDavid du Colombier 
80*25210b06SDavid du Colombier 	flag = getc(bin);
81*25210b06SDavid du Colombier 
82*25210b06SDavid du Colombier 	/* mod time */
83*25210b06SDavid du Colombier 	get4(bin);
84*25210b06SDavid du Colombier 
85*25210b06SDavid du Colombier 	/* extra flags */
86*25210b06SDavid du Colombier 	getc(bin);
87*25210b06SDavid du Colombier 
88*25210b06SDavid du Colombier 	/* OS type */
89*25210b06SDavid du Colombier 	getc(bin);
90*25210b06SDavid du Colombier 
91*25210b06SDavid du Colombier 	if(flag & Fextra)
92*25210b06SDavid du Colombier 		for(i=getc(bin); i>0; i--)
93*25210b06SDavid du Colombier 			getc(bin);
94*25210b06SDavid du Colombier 
95*25210b06SDavid du Colombier 	/* name */
96*25210b06SDavid du Colombier 	if(flag&Fname)
97*25210b06SDavid du Colombier 		while(getc(bin) != 0)
98*25210b06SDavid du Colombier 			;
99*25210b06SDavid du Colombier 
100*25210b06SDavid du Colombier 	/* comment */
101*25210b06SDavid du Colombier 	if(flag&Fcomment)
102*25210b06SDavid du Colombier 		while(getc(bin) != 0)
103*25210b06SDavid du Colombier 			;
104*25210b06SDavid du Colombier 
105*25210b06SDavid du Colombier 	/* crc16 */
106*25210b06SDavid du Colombier 	if(flag&Fhcrc) {
107*25210b06SDavid du Colombier 		getc(bin);
108*25210b06SDavid du Colombier 		getc(bin);
109*25210b06SDavid du Colombier 	}
110*25210b06SDavid du Colombier 
111*25210b06SDavid du Colombier 	return FlateOk;
112*25210b06SDavid du Colombier }
113*25210b06SDavid du Colombier 
114*25210b06SDavid du Colombier static int
trailer(Biobuf * bout,Biobuf * bin)115*25210b06SDavid du Colombier trailer(Biobuf *bout, Biobuf *bin)
116*25210b06SDavid du Colombier {
117*25210b06SDavid du Colombier 	/* crc32 */
118*25210b06SDavid du Colombier 	if(crc != get4(bin)){
119*25210b06SDavid du Colombier 		print("crc mismatch\n");
120*25210b06SDavid du Colombier 		return FlateCorrupted;
121*25210b06SDavid du Colombier 	}
122*25210b06SDavid du Colombier 
123*25210b06SDavid du Colombier 	/* length */
124*25210b06SDavid du Colombier 	if(get4(bin) != Boffset(bout)){
125*25210b06SDavid du Colombier 		print("bad output len\n");
126*25210b06SDavid du Colombier 		return FlateCorrupted;
127*25210b06SDavid du Colombier 	}
128*25210b06SDavid du Colombier 	return FlateOk;
129*25210b06SDavid du Colombier }
130*25210b06SDavid du Colombier 
131*25210b06SDavid du Colombier static ulong
get4(Biobuf * b)132*25210b06SDavid du Colombier get4(Biobuf *b)
133*25210b06SDavid du Colombier {
134*25210b06SDavid du Colombier 	ulong v;
135*25210b06SDavid du Colombier 	int i, c;
136*25210b06SDavid du Colombier 
137*25210b06SDavid du Colombier 	v = 0;
138*25210b06SDavid du Colombier 	for(i = 0; i < 4; i++){
139*25210b06SDavid du Colombier 		c = getc(b);
140*25210b06SDavid du Colombier 		v |= c << (i * 8);
141*25210b06SDavid du Colombier 	}
142*25210b06SDavid du Colombier 	return v;
143*25210b06SDavid du Colombier }
144*25210b06SDavid du Colombier 
145*25210b06SDavid du Colombier static int
getc(void * in)146*25210b06SDavid du Colombier getc(void *in)
147*25210b06SDavid du Colombier {
148*25210b06SDavid du Colombier 	Biobuf *bp = in;
149*25210b06SDavid du Colombier 
150*25210b06SDavid du Colombier //	if((bp->p - bp->bp) % 10000 == 0)
151*25210b06SDavid du Colombier //		print(".");
152*25210b06SDavid du Colombier 	if(bp->p >= bp->ep){
153*25210b06SDavid du Colombier 		print("EOF");
154*25210b06SDavid du Colombier 		return -1;
155*25210b06SDavid du Colombier 	}
156*25210b06SDavid du Colombier 	return *bp->p++;
157*25210b06SDavid du Colombier }
158*25210b06SDavid du Colombier 
159*25210b06SDavid du Colombier static ulong
Boffset(Biobuf * bp)160*25210b06SDavid du Colombier Boffset(Biobuf *bp)
161*25210b06SDavid du Colombier {
162*25210b06SDavid du Colombier 	return bp->p - bp->bp;
163*25210b06SDavid du Colombier }
164*25210b06SDavid du Colombier 
165*25210b06SDavid du Colombier static int
crcwrite(void * out,void * buf,int n)166*25210b06SDavid du Colombier crcwrite(void *out, void *buf, int n)
167*25210b06SDavid du Colombier {
168*25210b06SDavid du Colombier 	Biobuf *bp;
169*25210b06SDavid du Colombier 	int nn;
170*25210b06SDavid du Colombier 
171*25210b06SDavid du Colombier 	crc = blockcrc(crctab, crc, buf, n);
172*25210b06SDavid du Colombier 	bp = out;
173*25210b06SDavid du Colombier 	nn = n;
174*25210b06SDavid du Colombier 	if(nn > bp->ep-bp->p)
175*25210b06SDavid du Colombier 		nn = bp->ep-bp->p;
176*25210b06SDavid du Colombier 	if(nn > 0)
177*25210b06SDavid du Colombier 		memmove(bp->p, buf, nn);
178*25210b06SDavid du Colombier 	bp->p += n;
179*25210b06SDavid du Colombier 	return n;
180*25210b06SDavid du Colombier }
181