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, ¶m); 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