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