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