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 #include <misc_decompress.h> 10cc05bcfaSJason Zhu 11cc05bcfaSJason Zhu #define HEAD_CRC 2 12cc05bcfaSJason Zhu #define EXTRA_FIELD 4 13cc05bcfaSJason Zhu #define ORIG_NAME 8 14cc05bcfaSJason Zhu #define COMMENT 0x10 15cc05bcfaSJason Zhu #define RESERVED 0xe0 16cc05bcfaSJason Zhu #define DEFLATED 8 17cc05bcfaSJason Zhu 18cc05bcfaSJason Zhu static int misc_gzip_parse_header(const unsigned char *src, unsigned long len) 19cc05bcfaSJason Zhu { 20cc05bcfaSJason Zhu int i, flags; 21cc05bcfaSJason Zhu 22cc05bcfaSJason Zhu /* skip header */ 23cc05bcfaSJason Zhu i = 10; 24cc05bcfaSJason Zhu flags = src[3]; 25cc05bcfaSJason Zhu if (src[2] != DEFLATED || (flags & RESERVED) != 0) { 26cc05bcfaSJason Zhu debug("Error: Bad gzipped data\n"); 27cc05bcfaSJason Zhu return (-1); 28cc05bcfaSJason Zhu } 29cc05bcfaSJason Zhu if ((flags & EXTRA_FIELD) != 0) 30cc05bcfaSJason Zhu i = 12 + src[10] + (src[11] << 8); 31cc05bcfaSJason Zhu if ((flags & ORIG_NAME) != 0) 32cc05bcfaSJason Zhu while (src[i++] != 0) 33cc05bcfaSJason Zhu ; 34cc05bcfaSJason Zhu if ((flags & COMMENT) != 0) 35cc05bcfaSJason Zhu while (src[i++] != 0) 36cc05bcfaSJason Zhu ; 37cc05bcfaSJason Zhu if ((flags & HEAD_CRC) != 0) 38cc05bcfaSJason Zhu i += 2; 39cc05bcfaSJason Zhu if (i >= len) { 40cc05bcfaSJason Zhu puts("Error: gunzip out of data in header\n"); 41cc05bcfaSJason Zhu return (-1); 42cc05bcfaSJason Zhu } 43cc05bcfaSJason Zhu return i; 44cc05bcfaSJason Zhu } 45cc05bcfaSJason Zhu 46cc05bcfaSJason Zhu struct udevice *misc_decompress_get_device(u32 capability) 47cc05bcfaSJason Zhu { 48cc05bcfaSJason Zhu const struct misc_ops *ops; 49cc05bcfaSJason Zhu struct udevice *dev; 50cc05bcfaSJason Zhu struct uclass *uc; 51cc05bcfaSJason Zhu int ret; 52cc05bcfaSJason Zhu u32 cap; 53cc05bcfaSJason Zhu 54cc05bcfaSJason Zhu ret = uclass_get(UCLASS_MISC, &uc); 55cc05bcfaSJason Zhu if (ret) 56cc05bcfaSJason Zhu return NULL; 57cc05bcfaSJason Zhu 58cc05bcfaSJason Zhu for (uclass_first_device(UCLASS_MISC, &dev); 59cc05bcfaSJason Zhu dev; 60cc05bcfaSJason Zhu uclass_next_device(&dev)) { 61cc05bcfaSJason Zhu ops = device_get_ops(dev); 62cc05bcfaSJason Zhu if (!ops || !ops->ioctl) 63cc05bcfaSJason Zhu continue; 64cc05bcfaSJason Zhu 65cc05bcfaSJason Zhu cap = ops->ioctl(dev, IOCTL_REQ_CAPABILITY, NULL); 66cc05bcfaSJason Zhu if ((cap & capability) == capability) 67cc05bcfaSJason Zhu return dev; 68cc05bcfaSJason Zhu } 69cc05bcfaSJason Zhu 70cc05bcfaSJason Zhu return NULL; 71cc05bcfaSJason Zhu } 72cc05bcfaSJason Zhu 73cc05bcfaSJason Zhu int misc_decompress_start(struct udevice *dev, unsigned long src, 74cc05bcfaSJason Zhu unsigned long dst, unsigned long size) 75cc05bcfaSJason Zhu { 76cc05bcfaSJason Zhu struct decom_param param; 77cc05bcfaSJason Zhu 78cc05bcfaSJason Zhu param.addr_dst = dst; 79cc05bcfaSJason Zhu param.addr_src = src; 80cc05bcfaSJason Zhu param.size = size; 81cc05bcfaSJason Zhu if (misc_gzip_parse_header((unsigned char *)src, 0xffff) > 0) { 82*5b7d3298SJason Zhu param.mode = DECOM_GZIP; 83cc05bcfaSJason Zhu } else { 84cc05bcfaSJason Zhu printf("Unsupported decompression format.\n"); 85cc05bcfaSJason Zhu return -EPERM; 86cc05bcfaSJason Zhu } 87cc05bcfaSJason Zhu 88cc05bcfaSJason Zhu return misc_ioctl(dev, IOCTL_REQ_START, ¶m); 89cc05bcfaSJason Zhu } 90cc05bcfaSJason Zhu 91cc05bcfaSJason Zhu int misc_decompress_stop(struct udevice *dev) 92cc05bcfaSJason Zhu { 93cc05bcfaSJason Zhu return misc_ioctl(dev, IOCTL_REQ_STOP, NULL); 94cc05bcfaSJason Zhu } 95cc05bcfaSJason Zhu 96cc05bcfaSJason Zhu int misc_decompress_is_complete(struct udevice *dev) 97cc05bcfaSJason Zhu { 98cc05bcfaSJason Zhu return misc_ioctl(dev, IOCTL_REQ_POLL, NULL); 99cc05bcfaSJason Zhu } 100