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 { 47374c241cSJoseph 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, ¶m); 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 73809af6baSJason Zhu bool misc_decompress_is_complete(struct udevice *dev) 74cc05bcfaSJason Zhu { 75809af6baSJason Zhu if (misc_ioctl(dev, IOCTL_REQ_POLL, NULL)) 76809af6baSJason Zhu return false; 77809af6baSJason Zhu else 78809af6baSJason Zhu return true; 79cc05bcfaSJason Zhu } 80*4298c19dSJason Zhu 81*4298c19dSJason Zhu int misc_decompress_process(unsigned long src, 82*4298c19dSJason Zhu unsigned long dst, 83*4298c19dSJason Zhu unsigned long limit_size, 84*4298c19dSJason Zhu u32 cap) 85*4298c19dSJason Zhu { 86*4298c19dSJason Zhu struct udevice *dev; 87*4298c19dSJason Zhu int timeout = 10000; 88*4298c19dSJason Zhu int ret; 89*4298c19dSJason Zhu 90*4298c19dSJason Zhu dev = misc_decompress_get_device(cap); 91*4298c19dSJason Zhu if (!dev) 92*4298c19dSJason Zhu return -EIO; 93*4298c19dSJason Zhu 94*4298c19dSJason Zhu while (!misc_decompress_is_complete(dev)) { 95*4298c19dSJason Zhu if (timeout < 0) 96*4298c19dSJason Zhu return -EIO; 97*4298c19dSJason Zhu timeout--; 98*4298c19dSJason Zhu udelay(10); 99*4298c19dSJason Zhu } 100*4298c19dSJason Zhu 101*4298c19dSJason Zhu ret = misc_decompress_stop(dev); 102*4298c19dSJason Zhu if (ret) 103*4298c19dSJason Zhu return -EIO; 104*4298c19dSJason Zhu 105*4298c19dSJason Zhu return misc_decompress_start(dev, src, dst, limit_size); 106*4298c19dSJason Zhu } 107