xref: /rk3399_rockchip-uboot/drivers/misc/misc_decompress.c (revision cc05bcfa9647acc2c5814e03eb72c8c2cc98d462)
1*cc05bcfaSJason Zhu // SPDX-License-Identifier:     GPL-2.0+
2*cc05bcfaSJason Zhu /*
3*cc05bcfaSJason Zhu  * Copyright (C) 2020 Rockchip Electronics Co., Ltd
4*cc05bcfaSJason Zhu  */
5*cc05bcfaSJason Zhu #include <common.h>
6*cc05bcfaSJason Zhu #include <dm.h>
7*cc05bcfaSJason Zhu #include <dm/uclass.h>
8*cc05bcfaSJason Zhu #include <misc.h>
9*cc05bcfaSJason Zhu #include <misc_decompress.h>
10*cc05bcfaSJason Zhu 
11*cc05bcfaSJason Zhu #define HEAD_CRC		2
12*cc05bcfaSJason Zhu #define EXTRA_FIELD		4
13*cc05bcfaSJason Zhu #define ORIG_NAME		8
14*cc05bcfaSJason Zhu #define COMMENT			0x10
15*cc05bcfaSJason Zhu #define RESERVED		0xe0
16*cc05bcfaSJason Zhu #define DEFLATED		8
17*cc05bcfaSJason Zhu 
18*cc05bcfaSJason Zhu static int misc_gzip_parse_header(const unsigned char *src, unsigned long len)
19*cc05bcfaSJason Zhu {
20*cc05bcfaSJason Zhu 	int i, flags;
21*cc05bcfaSJason Zhu 
22*cc05bcfaSJason Zhu 	/* skip header */
23*cc05bcfaSJason Zhu 	i = 10;
24*cc05bcfaSJason Zhu 	flags = src[3];
25*cc05bcfaSJason Zhu 	if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
26*cc05bcfaSJason Zhu 		debug("Error: Bad gzipped data\n");
27*cc05bcfaSJason Zhu 		return (-1);
28*cc05bcfaSJason Zhu 	}
29*cc05bcfaSJason Zhu 	if ((flags & EXTRA_FIELD) != 0)
30*cc05bcfaSJason Zhu 		i = 12 + src[10] + (src[11] << 8);
31*cc05bcfaSJason Zhu 	if ((flags & ORIG_NAME) != 0)
32*cc05bcfaSJason Zhu 		while (src[i++] != 0)
33*cc05bcfaSJason Zhu 			;
34*cc05bcfaSJason Zhu 	if ((flags & COMMENT) != 0)
35*cc05bcfaSJason Zhu 		while (src[i++] != 0)
36*cc05bcfaSJason Zhu 			;
37*cc05bcfaSJason Zhu 	if ((flags & HEAD_CRC) != 0)
38*cc05bcfaSJason Zhu 		i += 2;
39*cc05bcfaSJason Zhu 	if (i >= len) {
40*cc05bcfaSJason Zhu 		puts("Error: gunzip out of data in header\n");
41*cc05bcfaSJason Zhu 		return (-1);
42*cc05bcfaSJason Zhu 	}
43*cc05bcfaSJason Zhu 	return i;
44*cc05bcfaSJason Zhu }
45*cc05bcfaSJason Zhu 
46*cc05bcfaSJason Zhu struct udevice *misc_decompress_get_device(u32 capability)
47*cc05bcfaSJason Zhu {
48*cc05bcfaSJason Zhu 	const struct misc_ops *ops;
49*cc05bcfaSJason Zhu 	struct udevice *dev;
50*cc05bcfaSJason Zhu 	struct uclass *uc;
51*cc05bcfaSJason Zhu 	int ret;
52*cc05bcfaSJason Zhu 	u32 cap;
53*cc05bcfaSJason Zhu 
54*cc05bcfaSJason Zhu 	ret = uclass_get(UCLASS_MISC, &uc);
55*cc05bcfaSJason Zhu 	if (ret)
56*cc05bcfaSJason Zhu 		return NULL;
57*cc05bcfaSJason Zhu 
58*cc05bcfaSJason Zhu 	for (uclass_first_device(UCLASS_MISC, &dev);
59*cc05bcfaSJason Zhu 	     dev;
60*cc05bcfaSJason Zhu 	     uclass_next_device(&dev)) {
61*cc05bcfaSJason Zhu 		ops = device_get_ops(dev);
62*cc05bcfaSJason Zhu 		if (!ops || !ops->ioctl)
63*cc05bcfaSJason Zhu 			continue;
64*cc05bcfaSJason Zhu 
65*cc05bcfaSJason Zhu 		cap = ops->ioctl(dev, IOCTL_REQ_CAPABILITY, NULL);
66*cc05bcfaSJason Zhu 		if ((cap & capability) == capability)
67*cc05bcfaSJason Zhu 			return dev;
68*cc05bcfaSJason Zhu 	}
69*cc05bcfaSJason Zhu 
70*cc05bcfaSJason Zhu 	return NULL;
71*cc05bcfaSJason Zhu }
72*cc05bcfaSJason Zhu 
73*cc05bcfaSJason Zhu int misc_decompress_start(struct udevice *dev, unsigned long src,
74*cc05bcfaSJason Zhu 			  unsigned long dst, unsigned long size)
75*cc05bcfaSJason Zhu {
76*cc05bcfaSJason Zhu 	struct decom_param param;
77*cc05bcfaSJason Zhu 
78*cc05bcfaSJason Zhu 	param.addr_dst = dst;
79*cc05bcfaSJason Zhu 	param.addr_src = src;
80*cc05bcfaSJason Zhu 	param.size = size;
81*cc05bcfaSJason Zhu 	if (misc_gzip_parse_header((unsigned char *)src, 0xffff) > 0) {
82*cc05bcfaSJason Zhu 		param.mode = GZIP_MOD;
83*cc05bcfaSJason Zhu 	} else {
84*cc05bcfaSJason Zhu 		printf("Unsupported decompression format.\n");
85*cc05bcfaSJason Zhu 		return -EPERM;
86*cc05bcfaSJason Zhu 	}
87*cc05bcfaSJason Zhu 
88*cc05bcfaSJason Zhu 	return misc_ioctl(dev, IOCTL_REQ_START, &param);
89*cc05bcfaSJason Zhu }
90*cc05bcfaSJason Zhu 
91*cc05bcfaSJason Zhu int misc_decompress_stop(struct udevice *dev)
92*cc05bcfaSJason Zhu {
93*cc05bcfaSJason Zhu 	return misc_ioctl(dev, IOCTL_REQ_STOP, NULL);
94*cc05bcfaSJason Zhu }
95*cc05bcfaSJason Zhu 
96*cc05bcfaSJason Zhu int misc_decompress_is_complete(struct udevice *dev)
97*cc05bcfaSJason Zhu {
98*cc05bcfaSJason Zhu 	return misc_ioctl(dev, IOCTL_REQ_POLL, NULL);
99*cc05bcfaSJason Zhu }
100