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