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, ¶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 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