18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci 38c2ecf20Sopenharmony_ci/* P9 gunzip sample code for demonstrating the P9 NX hardware 48c2ecf20Sopenharmony_ci * interface. Not intended for productive uses or for performance or 58c2ecf20Sopenharmony_ci * compression ratio measurements. Note also that /dev/crypto/gzip, 68c2ecf20Sopenharmony_ci * VAS and skiboot support are required 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Copyright 2020 IBM Corp. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Author: Bulent Abali <abali@us.ibm.com> 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * https://github.com/libnxz/power-gzip for zlib api and other utils 138c2ecf20Sopenharmony_ci * Definitions of acronyms used here. See 148c2ecf20Sopenharmony_ci * P9 NX Gzip Accelerator User's Manual for details: 158c2ecf20Sopenharmony_ci * https://github.com/libnxz/power-gzip/blob/develop/doc/power_nx_gzip_um.pdf 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * adler/crc: 32 bit checksums appended to stream tail 188c2ecf20Sopenharmony_ci * ce: completion extension 198c2ecf20Sopenharmony_ci * cpb: coprocessor parameter block (metadata) 208c2ecf20Sopenharmony_ci * crb: coprocessor request block (command) 218c2ecf20Sopenharmony_ci * csb: coprocessor status block (status) 228c2ecf20Sopenharmony_ci * dht: dynamic huffman table 238c2ecf20Sopenharmony_ci * dde: data descriptor element (address, length) 248c2ecf20Sopenharmony_ci * ddl: list of ddes 258c2ecf20Sopenharmony_ci * dh/fh: dynamic and fixed huffman types 268c2ecf20Sopenharmony_ci * fc: coprocessor function code 278c2ecf20Sopenharmony_ci * histlen: history/dictionary length 288c2ecf20Sopenharmony_ci * history: sliding window of up to 32KB of data 298c2ecf20Sopenharmony_ci * lzcount: Deflate LZ symbol counts 308c2ecf20Sopenharmony_ci * rembytecnt: remaining byte count 318c2ecf20Sopenharmony_ci * sfbt: source final block type; last block's type during decomp 328c2ecf20Sopenharmony_ci * spbc: source processed byte count 338c2ecf20Sopenharmony_ci * subc: source unprocessed bit count 348c2ecf20Sopenharmony_ci * tebc: target ending bit count; valid bits in the last byte 358c2ecf20Sopenharmony_ci * tpbc: target processed byte count 368c2ecf20Sopenharmony_ci * vas: virtual accelerator switch; the user mode interface 378c2ecf20Sopenharmony_ci */ 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#define _ISOC11_SOURCE // For aligned_alloc() 408c2ecf20Sopenharmony_ci#define _DEFAULT_SOURCE // For endian.h 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#include <stdio.h> 438c2ecf20Sopenharmony_ci#include <stdlib.h> 448c2ecf20Sopenharmony_ci#include <string.h> 458c2ecf20Sopenharmony_ci#include <unistd.h> 468c2ecf20Sopenharmony_ci#include <stdint.h> 478c2ecf20Sopenharmony_ci#include <sys/types.h> 488c2ecf20Sopenharmony_ci#include <sys/stat.h> 498c2ecf20Sopenharmony_ci#include <sys/time.h> 508c2ecf20Sopenharmony_ci#include <sys/fcntl.h> 518c2ecf20Sopenharmony_ci#include <sys/mman.h> 528c2ecf20Sopenharmony_ci#include <endian.h> 538c2ecf20Sopenharmony_ci#include <bits/endian.h> 548c2ecf20Sopenharmony_ci#include <sys/ioctl.h> 558c2ecf20Sopenharmony_ci#include <assert.h> 568c2ecf20Sopenharmony_ci#include <errno.h> 578c2ecf20Sopenharmony_ci#include <signal.h> 588c2ecf20Sopenharmony_ci#include "nxu.h" 598c2ecf20Sopenharmony_ci#include "nx.h" 608c2ecf20Sopenharmony_ci#include "crb.h" 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ciint nx_dbg; 638c2ecf20Sopenharmony_ciFILE *nx_gzip_log; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci#define NX_MIN(X, Y) (((X) < (Y))?(X):(Y)) 668c2ecf20Sopenharmony_ci#define NX_MAX(X, Y) (((X) > (Y))?(X):(Y)) 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci#define GETINPC(X) fgetc(X) 698c2ecf20Sopenharmony_ci#define FNAME_MAX 1024 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci/* fifo queue management */ 728c2ecf20Sopenharmony_ci#define fifo_used_bytes(used) (used) 738c2ecf20Sopenharmony_ci#define fifo_free_bytes(used, len) ((len)-(used)) 748c2ecf20Sopenharmony_ci/* amount of free bytes in the first and last parts */ 758c2ecf20Sopenharmony_ci#define fifo_free_first_bytes(cur, used, len) ((((cur)+(used)) <= (len)) \ 768c2ecf20Sopenharmony_ci ? (len)-((cur)+(used)) : 0) 778c2ecf20Sopenharmony_ci#define fifo_free_last_bytes(cur, used, len) ((((cur)+(used)) <= (len)) \ 788c2ecf20Sopenharmony_ci ? (cur) : (len)-(used)) 798c2ecf20Sopenharmony_ci/* amount of used bytes in the first and last parts */ 808c2ecf20Sopenharmony_ci#define fifo_used_first_bytes(cur, used, len) ((((cur)+(used)) <= (len)) \ 818c2ecf20Sopenharmony_ci ? (used) : (len)-(cur)) 828c2ecf20Sopenharmony_ci#define fifo_used_last_bytes(cur, used, len) ((((cur)+(used)) <= (len)) \ 838c2ecf20Sopenharmony_ci ? 0 : ((used)+(cur))-(len)) 848c2ecf20Sopenharmony_ci/* first and last free parts start here */ 858c2ecf20Sopenharmony_ci#define fifo_free_first_offset(cur, used) ((cur)+(used)) 868c2ecf20Sopenharmony_ci#define fifo_free_last_offset(cur, used, len) \ 878c2ecf20Sopenharmony_ci fifo_used_last_bytes(cur, used, len) 888c2ecf20Sopenharmony_ci/* first and last used parts start here */ 898c2ecf20Sopenharmony_ci#define fifo_used_first_offset(cur) (cur) 908c2ecf20Sopenharmony_ci#define fifo_used_last_offset(cur) (0) 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ciconst int fifo_in_len = 1<<24; 938c2ecf20Sopenharmony_ciconst int fifo_out_len = 1<<24; 948c2ecf20Sopenharmony_ciconst int page_sz = 1<<16; 958c2ecf20Sopenharmony_ciconst int line_sz = 1<<7; 968c2ecf20Sopenharmony_ciconst int window_max = 1<<15; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci/* 998c2ecf20Sopenharmony_ci * Adds an (address, len) pair to the list of ddes (ddl) and updates 1008c2ecf20Sopenharmony_ci * the base dde. ddl[0] is the only dde in a direct dde which 1018c2ecf20Sopenharmony_ci * contains a single (addr,len) pair. For more pairs, ddl[0] becomes 1028c2ecf20Sopenharmony_ci * the indirect (base) dde that points to a list of direct ddes. 1038c2ecf20Sopenharmony_ci * See Section 6.4 of the NX-gzip user manual for DDE description. 1048c2ecf20Sopenharmony_ci * Addr=NULL, len=0 clears the ddl[0]. Returns the total number of 1058c2ecf20Sopenharmony_ci * bytes in ddl. Caller is responsible for allocting the array of 1068c2ecf20Sopenharmony_ci * nx_dde_t *ddl. If N addresses are required in the scatter-gather 1078c2ecf20Sopenharmony_ci * list, the ddl array must have N+1 entries minimum. 1088c2ecf20Sopenharmony_ci */ 1098c2ecf20Sopenharmony_cistatic inline uint32_t nx_append_dde(struct nx_dde_t *ddl, void *addr, 1108c2ecf20Sopenharmony_ci uint32_t len) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci uint32_t ddecnt; 1138c2ecf20Sopenharmony_ci uint32_t bytes; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci if (addr == NULL && len == 0) { 1168c2ecf20Sopenharmony_ci clearp_dde(ddl); 1178c2ecf20Sopenharmony_ci return 0; 1188c2ecf20Sopenharmony_ci } 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci NXPRT(fprintf(stderr, "%d: %s addr %p len %x\n", __LINE__, addr, 1218c2ecf20Sopenharmony_ci __func__, len)); 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci /* Number of ddes in the dde list ; == 0 when it is a direct dde */ 1248c2ecf20Sopenharmony_ci ddecnt = getpnn(ddl, dde_count); 1258c2ecf20Sopenharmony_ci bytes = getp32(ddl, ddebc); 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci if (ddecnt == 0 && bytes == 0) { 1288c2ecf20Sopenharmony_ci /* First dde is unused; make it a direct dde */ 1298c2ecf20Sopenharmony_ci bytes = len; 1308c2ecf20Sopenharmony_ci putp32(ddl, ddebc, bytes); 1318c2ecf20Sopenharmony_ci putp64(ddl, ddead, (uint64_t) addr); 1328c2ecf20Sopenharmony_ci } else if (ddecnt == 0) { 1338c2ecf20Sopenharmony_ci /* Converting direct to indirect dde 1348c2ecf20Sopenharmony_ci * ddl[0] becomes head dde of ddl 1358c2ecf20Sopenharmony_ci * copy direct to indirect first. 1368c2ecf20Sopenharmony_ci */ 1378c2ecf20Sopenharmony_ci ddl[1] = ddl[0]; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci /* Add the new dde next */ 1408c2ecf20Sopenharmony_ci clear_dde(ddl[2]); 1418c2ecf20Sopenharmony_ci put32(ddl[2], ddebc, len); 1428c2ecf20Sopenharmony_ci put64(ddl[2], ddead, (uint64_t) addr); 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci /* Ddl head points to 2 direct ddes */ 1458c2ecf20Sopenharmony_ci ddecnt = 2; 1468c2ecf20Sopenharmony_ci putpnn(ddl, dde_count, ddecnt); 1478c2ecf20Sopenharmony_ci bytes = bytes + len; 1488c2ecf20Sopenharmony_ci putp32(ddl, ddebc, bytes); 1498c2ecf20Sopenharmony_ci /* Pointer to the first direct dde */ 1508c2ecf20Sopenharmony_ci putp64(ddl, ddead, (uint64_t) &ddl[1]); 1518c2ecf20Sopenharmony_ci } else { 1528c2ecf20Sopenharmony_ci /* Append a dde to an existing indirect ddl */ 1538c2ecf20Sopenharmony_ci ++ddecnt; 1548c2ecf20Sopenharmony_ci clear_dde(ddl[ddecnt]); 1558c2ecf20Sopenharmony_ci put64(ddl[ddecnt], ddead, (uint64_t) addr); 1568c2ecf20Sopenharmony_ci put32(ddl[ddecnt], ddebc, len); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci putpnn(ddl, dde_count, ddecnt); 1598c2ecf20Sopenharmony_ci bytes = bytes + len; 1608c2ecf20Sopenharmony_ci putp32(ddl, ddebc, bytes); /* byte sum of all dde */ 1618c2ecf20Sopenharmony_ci } 1628c2ecf20Sopenharmony_ci return bytes; 1638c2ecf20Sopenharmony_ci} 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci/* 1668c2ecf20Sopenharmony_ci * Touch specified number of pages represented in number bytes 1678c2ecf20Sopenharmony_ci * beginning from the first buffer in a dde list. 1688c2ecf20Sopenharmony_ci * Do not touch the pages past buf_sz-th byte's page. 1698c2ecf20Sopenharmony_ci * 1708c2ecf20Sopenharmony_ci * Set buf_sz = 0 to touch all pages described by the ddep. 1718c2ecf20Sopenharmony_ci */ 1728c2ecf20Sopenharmony_cistatic int nx_touch_pages_dde(struct nx_dde_t *ddep, long buf_sz, long page_sz, 1738c2ecf20Sopenharmony_ci int wr) 1748c2ecf20Sopenharmony_ci{ 1758c2ecf20Sopenharmony_ci uint32_t indirect_count; 1768c2ecf20Sopenharmony_ci uint32_t buf_len; 1778c2ecf20Sopenharmony_ci long total; 1788c2ecf20Sopenharmony_ci uint64_t buf_addr; 1798c2ecf20Sopenharmony_ci struct nx_dde_t *dde_list; 1808c2ecf20Sopenharmony_ci int i; 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci assert(!!ddep); 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci indirect_count = getpnn(ddep, dde_count); 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci NXPRT(fprintf(stderr, "%s dde_count %d request len ", __func__, 1878c2ecf20Sopenharmony_ci indirect_count)); 1888c2ecf20Sopenharmony_ci NXPRT(fprintf(stderr, "0x%lx\n", buf_sz)); 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci if (indirect_count == 0) { 1918c2ecf20Sopenharmony_ci /* Direct dde */ 1928c2ecf20Sopenharmony_ci buf_len = getp32(ddep, ddebc); 1938c2ecf20Sopenharmony_ci buf_addr = getp64(ddep, ddead); 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci NXPRT(fprintf(stderr, "touch direct ddebc 0x%x ddead %p\n", 1968c2ecf20Sopenharmony_ci buf_len, (void *)buf_addr)); 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci if (buf_sz == 0) 1998c2ecf20Sopenharmony_ci nxu_touch_pages((void *)buf_addr, buf_len, page_sz, wr); 2008c2ecf20Sopenharmony_ci else 2018c2ecf20Sopenharmony_ci nxu_touch_pages((void *)buf_addr, NX_MIN(buf_len, 2028c2ecf20Sopenharmony_ci buf_sz), page_sz, wr); 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci return ERR_NX_OK; 2058c2ecf20Sopenharmony_ci } 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci /* Indirect dde */ 2088c2ecf20Sopenharmony_ci if (indirect_count > MAX_DDE_COUNT) 2098c2ecf20Sopenharmony_ci return ERR_NX_EXCESSIVE_DDE; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci /* First address of the list */ 2128c2ecf20Sopenharmony_ci dde_list = (struct nx_dde_t *) getp64(ddep, ddead); 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci if (buf_sz == 0) 2158c2ecf20Sopenharmony_ci buf_sz = getp32(ddep, ddebc); 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci total = 0; 2188c2ecf20Sopenharmony_ci for (i = 0; i < indirect_count; i++) { 2198c2ecf20Sopenharmony_ci buf_len = get32(dde_list[i], ddebc); 2208c2ecf20Sopenharmony_ci buf_addr = get64(dde_list[i], ddead); 2218c2ecf20Sopenharmony_ci total += buf_len; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci NXPRT(fprintf(stderr, "touch loop len 0x%x ddead %p total ", 2248c2ecf20Sopenharmony_ci buf_len, (void *)buf_addr)); 2258c2ecf20Sopenharmony_ci NXPRT(fprintf(stderr, "0x%lx\n", total)); 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci /* Touching fewer pages than encoded in the ddebc */ 2288c2ecf20Sopenharmony_ci if (total > buf_sz) { 2298c2ecf20Sopenharmony_ci buf_len = NX_MIN(buf_len, total - buf_sz); 2308c2ecf20Sopenharmony_ci nxu_touch_pages((void *)buf_addr, buf_len, page_sz, wr); 2318c2ecf20Sopenharmony_ci NXPRT(fprintf(stderr, "touch loop break len 0x%x ", 2328c2ecf20Sopenharmony_ci buf_len)); 2338c2ecf20Sopenharmony_ci NXPRT(fprintf(stderr, "ddead %p\n", (void *)buf_addr)); 2348c2ecf20Sopenharmony_ci break; 2358c2ecf20Sopenharmony_ci } 2368c2ecf20Sopenharmony_ci nxu_touch_pages((void *)buf_addr, buf_len, page_sz, wr); 2378c2ecf20Sopenharmony_ci } 2388c2ecf20Sopenharmony_ci return ERR_NX_OK; 2398c2ecf20Sopenharmony_ci} 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci/* 2428c2ecf20Sopenharmony_ci * Src and dst buffers are supplied in scatter gather lists. 2438c2ecf20Sopenharmony_ci * NX function code and other parameters supplied in cmdp. 2448c2ecf20Sopenharmony_ci */ 2458c2ecf20Sopenharmony_cistatic int nx_submit_job(struct nx_dde_t *src, struct nx_dde_t *dst, 2468c2ecf20Sopenharmony_ci struct nx_gzip_crb_cpb_t *cmdp, void *handle) 2478c2ecf20Sopenharmony_ci{ 2488c2ecf20Sopenharmony_ci uint64_t csbaddr; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci memset((void *)&cmdp->crb.csb, 0, sizeof(cmdp->crb.csb)); 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci cmdp->crb.source_dde = *src; 2538c2ecf20Sopenharmony_ci cmdp->crb.target_dde = *dst; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci /* Status, output byte count in tpbc */ 2568c2ecf20Sopenharmony_ci csbaddr = ((uint64_t) &cmdp->crb.csb) & csb_address_mask; 2578c2ecf20Sopenharmony_ci put64(cmdp->crb, csb_address, csbaddr); 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci /* NX reports input bytes in spbc; cleared */ 2608c2ecf20Sopenharmony_ci cmdp->cpb.out_spbc_comp_wrap = 0; 2618c2ecf20Sopenharmony_ci cmdp->cpb.out_spbc_comp_with_count = 0; 2628c2ecf20Sopenharmony_ci cmdp->cpb.out_spbc_decomp = 0; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci /* Clear output */ 2658c2ecf20Sopenharmony_ci put32(cmdp->cpb, out_crc, INIT_CRC); 2668c2ecf20Sopenharmony_ci put32(cmdp->cpb, out_adler, INIT_ADLER); 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci /* Submit the crb, the job descriptor, to the accelerator. */ 2698c2ecf20Sopenharmony_ci return nxu_submit_job(cmdp, handle); 2708c2ecf20Sopenharmony_ci} 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ciint decompress_file(int argc, char **argv, void *devhandle) 2738c2ecf20Sopenharmony_ci{ 2748c2ecf20Sopenharmony_ci FILE *inpf = NULL; 2758c2ecf20Sopenharmony_ci FILE *outf = NULL; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci int c, expect, i, cc, rc = 0; 2788c2ecf20Sopenharmony_ci char gzfname[FNAME_MAX]; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci /* Queuing, file ops, byte counting */ 2818c2ecf20Sopenharmony_ci char *fifo_in, *fifo_out; 2828c2ecf20Sopenharmony_ci int used_in, cur_in, used_out, cur_out, read_sz, n; 2838c2ecf20Sopenharmony_ci int first_free, last_free, first_used, last_used; 2848c2ecf20Sopenharmony_ci int first_offset, last_offset; 2858c2ecf20Sopenharmony_ci int write_sz, free_space, source_sz; 2868c2ecf20Sopenharmony_ci int source_sz_estimate, target_sz_estimate; 2878c2ecf20Sopenharmony_ci uint64_t last_comp_ratio = 0; /* 1000 max */ 2888c2ecf20Sopenharmony_ci uint64_t total_out = 0; 2898c2ecf20Sopenharmony_ci int is_final, is_eof; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci /* nx hardware */ 2928c2ecf20Sopenharmony_ci int sfbt, subc, spbc, tpbc, nx_ce, fc, resuming = 0; 2938c2ecf20Sopenharmony_ci int history_len = 0; 2948c2ecf20Sopenharmony_ci struct nx_gzip_crb_cpb_t cmd, *cmdp; 2958c2ecf20Sopenharmony_ci struct nx_dde_t *ddl_in; 2968c2ecf20Sopenharmony_ci struct nx_dde_t dde_in[6] __aligned(128); 2978c2ecf20Sopenharmony_ci struct nx_dde_t *ddl_out; 2988c2ecf20Sopenharmony_ci struct nx_dde_t dde_out[6] __aligned(128); 2998c2ecf20Sopenharmony_ci int pgfault_retries; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci /* when using mmap'ed files */ 3028c2ecf20Sopenharmony_ci off_t input_file_offset; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci if (argc > 2) { 3058c2ecf20Sopenharmony_ci fprintf(stderr, "usage: %s <fname> or stdin\n", argv[0]); 3068c2ecf20Sopenharmony_ci fprintf(stderr, " writes to stdout or <fname>.nx.gunzip\n"); 3078c2ecf20Sopenharmony_ci return -1; 3088c2ecf20Sopenharmony_ci } 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci if (argc == 1) { 3118c2ecf20Sopenharmony_ci inpf = stdin; 3128c2ecf20Sopenharmony_ci outf = stdout; 3138c2ecf20Sopenharmony_ci } else if (argc == 2) { 3148c2ecf20Sopenharmony_ci char w[1024]; 3158c2ecf20Sopenharmony_ci char *wp; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci inpf = fopen(argv[1], "r"); 3188c2ecf20Sopenharmony_ci if (inpf == NULL) { 3198c2ecf20Sopenharmony_ci perror(argv[1]); 3208c2ecf20Sopenharmony_ci return -1; 3218c2ecf20Sopenharmony_ci } 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci /* Make a new file name to write to. Ignoring '.gz' */ 3248c2ecf20Sopenharmony_ci wp = (NULL != (wp = strrchr(argv[1], '/'))) ? (wp+1) : argv[1]; 3258c2ecf20Sopenharmony_ci strcpy(w, wp); 3268c2ecf20Sopenharmony_ci strcat(w, ".nx.gunzip"); 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci outf = fopen(w, "w"); 3298c2ecf20Sopenharmony_ci if (outf == NULL) { 3308c2ecf20Sopenharmony_ci perror(w); 3318c2ecf20Sopenharmony_ci return -1; 3328c2ecf20Sopenharmony_ci } 3338c2ecf20Sopenharmony_ci } 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci /* Decode the gzip header */ 3368c2ecf20Sopenharmony_ci c = GETINPC(inpf); expect = 0x1f; /* ID1 */ 3378c2ecf20Sopenharmony_ci if (c != expect) 3388c2ecf20Sopenharmony_ci goto err1; 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci c = GETINPC(inpf); expect = 0x8b; /* ID2 */ 3418c2ecf20Sopenharmony_ci if (c != expect) 3428c2ecf20Sopenharmony_ci goto err1; 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci c = GETINPC(inpf); expect = 0x08; /* CM */ 3458c2ecf20Sopenharmony_ci if (c != expect) 3468c2ecf20Sopenharmony_ci goto err1; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci int flg = GETINPC(inpf); /* FLG */ 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci if (flg & 0xE0 || flg & 0x4 || flg == EOF) 3518c2ecf20Sopenharmony_ci goto err2; 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci fprintf(stderr, "gzHeader FLG %x\n", flg); 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci /* Read 6 bytes; ignoring the MTIME, XFL, OS fields in this 3568c2ecf20Sopenharmony_ci * sample code. 3578c2ecf20Sopenharmony_ci */ 3588c2ecf20Sopenharmony_ci for (i = 0; i < 6; i++) { 3598c2ecf20Sopenharmony_ci char tmp[10]; 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci tmp[i] = GETINPC(inpf); 3628c2ecf20Sopenharmony_ci if (tmp[i] == EOF) 3638c2ecf20Sopenharmony_ci goto err3; 3648c2ecf20Sopenharmony_ci fprintf(stderr, "%02x ", tmp[i]); 3658c2ecf20Sopenharmony_ci if (i == 5) 3668c2ecf20Sopenharmony_ci fprintf(stderr, "\n"); 3678c2ecf20Sopenharmony_ci } 3688c2ecf20Sopenharmony_ci fprintf(stderr, "gzHeader MTIME, XFL, OS ignored\n"); 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci /* FNAME */ 3718c2ecf20Sopenharmony_ci if (flg & 0x8) { 3728c2ecf20Sopenharmony_ci int k = 0; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci do { 3758c2ecf20Sopenharmony_ci c = GETINPC(inpf); 3768c2ecf20Sopenharmony_ci if (c == EOF || k >= FNAME_MAX) 3778c2ecf20Sopenharmony_ci goto err3; 3788c2ecf20Sopenharmony_ci gzfname[k++] = c; 3798c2ecf20Sopenharmony_ci } while (c); 3808c2ecf20Sopenharmony_ci fprintf(stderr, "gzHeader FNAME: %s\n", gzfname); 3818c2ecf20Sopenharmony_ci } 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci /* FHCRC */ 3848c2ecf20Sopenharmony_ci if (flg & 0x2) { 3858c2ecf20Sopenharmony_ci c = GETINPC(inpf); 3868c2ecf20Sopenharmony_ci if (c == EOF) 3878c2ecf20Sopenharmony_ci goto err3; 3888c2ecf20Sopenharmony_ci c = GETINPC(inpf); 3898c2ecf20Sopenharmony_ci if (c == EOF) 3908c2ecf20Sopenharmony_ci goto err3; 3918c2ecf20Sopenharmony_ci fprintf(stderr, "gzHeader FHCRC: ignored\n"); 3928c2ecf20Sopenharmony_ci } 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci used_in = cur_in = used_out = cur_out = 0; 3958c2ecf20Sopenharmony_ci is_final = is_eof = 0; 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci /* Allocate one page larger to prevent page faults due to NX 3988c2ecf20Sopenharmony_ci * overfetching. 3998c2ecf20Sopenharmony_ci * Either do this (char*)(uintptr_t)aligned_alloc or use 4008c2ecf20Sopenharmony_ci * -std=c11 flag to make the int-to-pointer warning go away. 4018c2ecf20Sopenharmony_ci */ 4028c2ecf20Sopenharmony_ci assert((fifo_in = (char *)(uintptr_t)aligned_alloc(line_sz, 4038c2ecf20Sopenharmony_ci fifo_in_len + page_sz)) != NULL); 4048c2ecf20Sopenharmony_ci assert((fifo_out = (char *)(uintptr_t)aligned_alloc(line_sz, 4058c2ecf20Sopenharmony_ci fifo_out_len + page_sz + line_sz)) != NULL); 4068c2ecf20Sopenharmony_ci /* Leave unused space due to history rounding rules */ 4078c2ecf20Sopenharmony_ci fifo_out = fifo_out + line_sz; 4088c2ecf20Sopenharmony_ci nxu_touch_pages(fifo_out, fifo_out_len, page_sz, 1); 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci ddl_in = &dde_in[0]; 4118c2ecf20Sopenharmony_ci ddl_out = &dde_out[0]; 4128c2ecf20Sopenharmony_ci cmdp = &cmd; 4138c2ecf20Sopenharmony_ci memset(&cmdp->crb, 0, sizeof(cmdp->crb)); 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ciread_state: 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci /* Read from .gz file */ 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci NXPRT(fprintf(stderr, "read_state:\n")); 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci if (is_eof != 0) 4228c2ecf20Sopenharmony_ci goto write_state; 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci /* We read in to fifo_in in two steps: first: read in to from 4258c2ecf20Sopenharmony_ci * cur_in to the end of the buffer. last: if free space wrapped 4268c2ecf20Sopenharmony_ci * around, read from fifo_in offset 0 to offset cur_in. 4278c2ecf20Sopenharmony_ci */ 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci /* Reset fifo head to reduce unnecessary wrap arounds */ 4308c2ecf20Sopenharmony_ci cur_in = (used_in == 0) ? 0 : cur_in; 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci /* Free space total is reduced by a gap */ 4338c2ecf20Sopenharmony_ci free_space = NX_MAX(0, fifo_free_bytes(used_in, fifo_in_len) 4348c2ecf20Sopenharmony_ci - line_sz); 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci /* Free space may wrap around as first and last */ 4378c2ecf20Sopenharmony_ci first_free = fifo_free_first_bytes(cur_in, used_in, fifo_in_len); 4388c2ecf20Sopenharmony_ci last_free = fifo_free_last_bytes(cur_in, used_in, fifo_in_len); 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci /* Start offsets of the free memory */ 4418c2ecf20Sopenharmony_ci first_offset = fifo_free_first_offset(cur_in, used_in); 4428c2ecf20Sopenharmony_ci last_offset = fifo_free_last_offset(cur_in, used_in, fifo_in_len); 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci /* Reduce read_sz because of the line_sz gap */ 4458c2ecf20Sopenharmony_ci read_sz = NX_MIN(free_space, first_free); 4468c2ecf20Sopenharmony_ci n = 0; 4478c2ecf20Sopenharmony_ci if (read_sz > 0) { 4488c2ecf20Sopenharmony_ci /* Read in to offset cur_in + used_in */ 4498c2ecf20Sopenharmony_ci n = fread(fifo_in + first_offset, 1, read_sz, inpf); 4508c2ecf20Sopenharmony_ci used_in = used_in + n; 4518c2ecf20Sopenharmony_ci free_space = free_space - n; 4528c2ecf20Sopenharmony_ci assert(n <= read_sz); 4538c2ecf20Sopenharmony_ci if (n != read_sz) { 4548c2ecf20Sopenharmony_ci /* Either EOF or error; exit the read loop */ 4558c2ecf20Sopenharmony_ci is_eof = 1; 4568c2ecf20Sopenharmony_ci goto write_state; 4578c2ecf20Sopenharmony_ci } 4588c2ecf20Sopenharmony_ci } 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci /* If free space wrapped around */ 4618c2ecf20Sopenharmony_ci if (last_free > 0) { 4628c2ecf20Sopenharmony_ci /* Reduce read_sz because of the line_sz gap */ 4638c2ecf20Sopenharmony_ci read_sz = NX_MIN(free_space, last_free); 4648c2ecf20Sopenharmony_ci n = 0; 4658c2ecf20Sopenharmony_ci if (read_sz > 0) { 4668c2ecf20Sopenharmony_ci n = fread(fifo_in + last_offset, 1, read_sz, inpf); 4678c2ecf20Sopenharmony_ci used_in = used_in + n; /* Increase used space */ 4688c2ecf20Sopenharmony_ci free_space = free_space - n; /* Decrease free space */ 4698c2ecf20Sopenharmony_ci assert(n <= read_sz); 4708c2ecf20Sopenharmony_ci if (n != read_sz) { 4718c2ecf20Sopenharmony_ci /* Either EOF or error; exit the read loop */ 4728c2ecf20Sopenharmony_ci is_eof = 1; 4738c2ecf20Sopenharmony_ci goto write_state; 4748c2ecf20Sopenharmony_ci } 4758c2ecf20Sopenharmony_ci } 4768c2ecf20Sopenharmony_ci } 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci /* At this point we have used_in bytes in fifo_in with the 4798c2ecf20Sopenharmony_ci * data head starting at cur_in and possibly wrapping around. 4808c2ecf20Sopenharmony_ci */ 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ciwrite_state: 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci /* Write decompressed data to output file */ 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci NXPRT(fprintf(stderr, "write_state:\n")); 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci if (used_out == 0) 4898c2ecf20Sopenharmony_ci goto decomp_state; 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci /* If fifo_out has data waiting, write it out to the file to 4928c2ecf20Sopenharmony_ci * make free target space for the accelerator used bytes in 4938c2ecf20Sopenharmony_ci * the first and last parts of fifo_out. 4948c2ecf20Sopenharmony_ci */ 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci first_used = fifo_used_first_bytes(cur_out, used_out, fifo_out_len); 4978c2ecf20Sopenharmony_ci last_used = fifo_used_last_bytes(cur_out, used_out, fifo_out_len); 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci write_sz = first_used; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci n = 0; 5028c2ecf20Sopenharmony_ci if (write_sz > 0) { 5038c2ecf20Sopenharmony_ci n = fwrite(fifo_out + cur_out, 1, write_sz, outf); 5048c2ecf20Sopenharmony_ci used_out = used_out - n; 5058c2ecf20Sopenharmony_ci /* Move head of the fifo */ 5068c2ecf20Sopenharmony_ci cur_out = (cur_out + n) % fifo_out_len; 5078c2ecf20Sopenharmony_ci assert(n <= write_sz); 5088c2ecf20Sopenharmony_ci if (n != write_sz) { 5098c2ecf20Sopenharmony_ci fprintf(stderr, "error: write\n"); 5108c2ecf20Sopenharmony_ci rc = -1; 5118c2ecf20Sopenharmony_ci goto err5; 5128c2ecf20Sopenharmony_ci } 5138c2ecf20Sopenharmony_ci } 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci if (last_used > 0) { /* If more data available in the last part */ 5168c2ecf20Sopenharmony_ci write_sz = last_used; /* Keep it here for later */ 5178c2ecf20Sopenharmony_ci n = 0; 5188c2ecf20Sopenharmony_ci if (write_sz > 0) { 5198c2ecf20Sopenharmony_ci n = fwrite(fifo_out, 1, write_sz, outf); 5208c2ecf20Sopenharmony_ci used_out = used_out - n; 5218c2ecf20Sopenharmony_ci cur_out = (cur_out + n) % fifo_out_len; 5228c2ecf20Sopenharmony_ci assert(n <= write_sz); 5238c2ecf20Sopenharmony_ci if (n != write_sz) { 5248c2ecf20Sopenharmony_ci fprintf(stderr, "error: write\n"); 5258c2ecf20Sopenharmony_ci rc = -1; 5268c2ecf20Sopenharmony_ci goto err5; 5278c2ecf20Sopenharmony_ci } 5288c2ecf20Sopenharmony_ci } 5298c2ecf20Sopenharmony_ci } 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_cidecomp_state: 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci /* NX decompresses input data */ 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci NXPRT(fprintf(stderr, "decomp_state:\n")); 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci if (is_final) 5388c2ecf20Sopenharmony_ci goto finish_state; 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci /* Address/len lists */ 5418c2ecf20Sopenharmony_ci clearp_dde(ddl_in); 5428c2ecf20Sopenharmony_ci clearp_dde(ddl_out); 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci /* FC, CRC, HistLen, Table 6-6 */ 5458c2ecf20Sopenharmony_ci if (resuming) { 5468c2ecf20Sopenharmony_ci /* Resuming a partially decompressed input. 5478c2ecf20Sopenharmony_ci * The key to resume is supplying the 32KB 5488c2ecf20Sopenharmony_ci * dictionary (history) to NX, which is basically 5498c2ecf20Sopenharmony_ci * the last 32KB of output produced. 5508c2ecf20Sopenharmony_ci */ 5518c2ecf20Sopenharmony_ci fc = GZIP_FC_DECOMPRESS_RESUME; 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci cmdp->cpb.in_crc = cmdp->cpb.out_crc; 5548c2ecf20Sopenharmony_ci cmdp->cpb.in_adler = cmdp->cpb.out_adler; 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci /* Round up the history size to quadword. Section 2.10 */ 5578c2ecf20Sopenharmony_ci history_len = (history_len + 15) / 16; 5588c2ecf20Sopenharmony_ci putnn(cmdp->cpb, in_histlen, history_len); 5598c2ecf20Sopenharmony_ci history_len = history_len * 16; /* bytes */ 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci if (history_len > 0) { 5628c2ecf20Sopenharmony_ci /* Chain in the history buffer to the DDE list */ 5638c2ecf20Sopenharmony_ci if (cur_out >= history_len) { 5648c2ecf20Sopenharmony_ci nx_append_dde(ddl_in, fifo_out 5658c2ecf20Sopenharmony_ci + (cur_out - history_len), 5668c2ecf20Sopenharmony_ci history_len); 5678c2ecf20Sopenharmony_ci } else { 5688c2ecf20Sopenharmony_ci nx_append_dde(ddl_in, fifo_out 5698c2ecf20Sopenharmony_ci + ((fifo_out_len + cur_out) 5708c2ecf20Sopenharmony_ci - history_len), 5718c2ecf20Sopenharmony_ci history_len - cur_out); 5728c2ecf20Sopenharmony_ci /* Up to 32KB history wraps around fifo_out */ 5738c2ecf20Sopenharmony_ci nx_append_dde(ddl_in, fifo_out, cur_out); 5748c2ecf20Sopenharmony_ci } 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci } 5778c2ecf20Sopenharmony_ci } else { 5788c2ecf20Sopenharmony_ci /* First decompress job */ 5798c2ecf20Sopenharmony_ci fc = GZIP_FC_DECOMPRESS; 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci history_len = 0; 5828c2ecf20Sopenharmony_ci /* Writing 0 clears out subc as well */ 5838c2ecf20Sopenharmony_ci cmdp->cpb.in_histlen = 0; 5848c2ecf20Sopenharmony_ci total_out = 0; 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci put32(cmdp->cpb, in_crc, INIT_CRC); 5878c2ecf20Sopenharmony_ci put32(cmdp->cpb, in_adler, INIT_ADLER); 5888c2ecf20Sopenharmony_ci put32(cmdp->cpb, out_crc, INIT_CRC); 5898c2ecf20Sopenharmony_ci put32(cmdp->cpb, out_adler, INIT_ADLER); 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci /* Assuming 10% compression ratio initially; use the 5928c2ecf20Sopenharmony_ci * most recently measured compression ratio as a 5938c2ecf20Sopenharmony_ci * heuristic to estimate the input and output 5948c2ecf20Sopenharmony_ci * sizes. If we give too much input, the target buffer 5958c2ecf20Sopenharmony_ci * overflows and NX cycles are wasted, and then we 5968c2ecf20Sopenharmony_ci * must retry with smaller input size. 1000 is 100%. 5978c2ecf20Sopenharmony_ci */ 5988c2ecf20Sopenharmony_ci last_comp_ratio = 100UL; 5998c2ecf20Sopenharmony_ci } 6008c2ecf20Sopenharmony_ci cmdp->crb.gzip_fc = 0; 6018c2ecf20Sopenharmony_ci putnn(cmdp->crb, gzip_fc, fc); 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci /* 6048c2ecf20Sopenharmony_ci * NX source buffers 6058c2ecf20Sopenharmony_ci */ 6068c2ecf20Sopenharmony_ci first_used = fifo_used_first_bytes(cur_in, used_in, fifo_in_len); 6078c2ecf20Sopenharmony_ci last_used = fifo_used_last_bytes(cur_in, used_in, fifo_in_len); 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci if (first_used > 0) 6108c2ecf20Sopenharmony_ci nx_append_dde(ddl_in, fifo_in + cur_in, first_used); 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci if (last_used > 0) 6138c2ecf20Sopenharmony_ci nx_append_dde(ddl_in, fifo_in, last_used); 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci /* 6168c2ecf20Sopenharmony_ci * NX target buffers 6178c2ecf20Sopenharmony_ci */ 6188c2ecf20Sopenharmony_ci first_free = fifo_free_first_bytes(cur_out, used_out, fifo_out_len); 6198c2ecf20Sopenharmony_ci last_free = fifo_free_last_bytes(cur_out, used_out, fifo_out_len); 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci /* Reduce output free space amount not to overwrite the history */ 6228c2ecf20Sopenharmony_ci int target_max = NX_MAX(0, fifo_free_bytes(used_out, fifo_out_len) 6238c2ecf20Sopenharmony_ci - (1<<16)); 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci NXPRT(fprintf(stderr, "target_max %d (0x%x)\n", target_max, 6268c2ecf20Sopenharmony_ci target_max)); 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci first_free = NX_MIN(target_max, first_free); 6298c2ecf20Sopenharmony_ci if (first_free > 0) { 6308c2ecf20Sopenharmony_ci first_offset = fifo_free_first_offset(cur_out, used_out); 6318c2ecf20Sopenharmony_ci nx_append_dde(ddl_out, fifo_out + first_offset, first_free); 6328c2ecf20Sopenharmony_ci } 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci if (last_free > 0) { 6358c2ecf20Sopenharmony_ci last_free = NX_MIN(target_max - first_free, last_free); 6368c2ecf20Sopenharmony_ci if (last_free > 0) { 6378c2ecf20Sopenharmony_ci last_offset = fifo_free_last_offset(cur_out, used_out, 6388c2ecf20Sopenharmony_ci fifo_out_len); 6398c2ecf20Sopenharmony_ci nx_append_dde(ddl_out, fifo_out + last_offset, 6408c2ecf20Sopenharmony_ci last_free); 6418c2ecf20Sopenharmony_ci } 6428c2ecf20Sopenharmony_ci } 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci /* Target buffer size is used to limit the source data size 6458c2ecf20Sopenharmony_ci * based on previous measurements of compression ratio. 6468c2ecf20Sopenharmony_ci */ 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci /* source_sz includes history */ 6498c2ecf20Sopenharmony_ci source_sz = getp32(ddl_in, ddebc); 6508c2ecf20Sopenharmony_ci assert(source_sz > history_len); 6518c2ecf20Sopenharmony_ci source_sz = source_sz - history_len; 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci /* Estimating how much source is needed to 3/4 fill a 6548c2ecf20Sopenharmony_ci * target_max size target buffer. If we overshoot, then NX 6558c2ecf20Sopenharmony_ci * must repeat the job with smaller input and we waste 6568c2ecf20Sopenharmony_ci * bandwidth. If we undershoot then we use more NX calls than 6578c2ecf20Sopenharmony_ci * necessary. 6588c2ecf20Sopenharmony_ci */ 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_ci source_sz_estimate = ((uint64_t)target_max * last_comp_ratio * 3UL) 6618c2ecf20Sopenharmony_ci / 4000; 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci if (source_sz_estimate < source_sz) { 6648c2ecf20Sopenharmony_ci /* Target might be small, therefore limiting the 6658c2ecf20Sopenharmony_ci * source data. 6668c2ecf20Sopenharmony_ci */ 6678c2ecf20Sopenharmony_ci source_sz = source_sz_estimate; 6688c2ecf20Sopenharmony_ci target_sz_estimate = target_max; 6698c2ecf20Sopenharmony_ci } else { 6708c2ecf20Sopenharmony_ci /* Source file might be small, therefore limiting target 6718c2ecf20Sopenharmony_ci * touch pages to a smaller value to save processor cycles. 6728c2ecf20Sopenharmony_ci */ 6738c2ecf20Sopenharmony_ci target_sz_estimate = ((uint64_t)source_sz * 1000UL) 6748c2ecf20Sopenharmony_ci / (last_comp_ratio + 1); 6758c2ecf20Sopenharmony_ci target_sz_estimate = NX_MIN(2 * target_sz_estimate, 6768c2ecf20Sopenharmony_ci target_max); 6778c2ecf20Sopenharmony_ci } 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci source_sz = source_sz + history_len; 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci /* Some NX condition codes require submitting the NX job again. 6828c2ecf20Sopenharmony_ci * Kernel doesn't handle NX page faults. Expects user code to 6838c2ecf20Sopenharmony_ci * touch pages. 6848c2ecf20Sopenharmony_ci */ 6858c2ecf20Sopenharmony_ci pgfault_retries = NX_MAX_FAULTS; 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_cirestart_nx: 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci putp32(ddl_in, ddebc, source_sz); 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci /* Fault in pages */ 6928c2ecf20Sopenharmony_ci nxu_touch_pages(cmdp, sizeof(struct nx_gzip_crb_cpb_t), page_sz, 1); 6938c2ecf20Sopenharmony_ci nx_touch_pages_dde(ddl_in, 0, page_sz, 0); 6948c2ecf20Sopenharmony_ci nx_touch_pages_dde(ddl_out, target_sz_estimate, page_sz, 1); 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci /* Send job to NX */ 6978c2ecf20Sopenharmony_ci cc = nx_submit_job(ddl_in, ddl_out, cmdp, devhandle); 6988c2ecf20Sopenharmony_ci 6998c2ecf20Sopenharmony_ci switch (cc) { 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci case ERR_NX_AT_FAULT: 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci /* We touched the pages ahead of time. In the most common case 7048c2ecf20Sopenharmony_ci * we shouldn't be here. But may be some pages were paged out. 7058c2ecf20Sopenharmony_ci * Kernel should have placed the faulting address to fsaddr. 7068c2ecf20Sopenharmony_ci */ 7078c2ecf20Sopenharmony_ci NXPRT(fprintf(stderr, "ERR_NX_AT_FAULT %p\n", 7088c2ecf20Sopenharmony_ci (void *)cmdp->crb.csb.fsaddr)); 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci if (pgfault_retries == NX_MAX_FAULTS) { 7118c2ecf20Sopenharmony_ci /* Try once with exact number of pages */ 7128c2ecf20Sopenharmony_ci --pgfault_retries; 7138c2ecf20Sopenharmony_ci goto restart_nx; 7148c2ecf20Sopenharmony_ci } else if (pgfault_retries > 0) { 7158c2ecf20Sopenharmony_ci /* If still faulting try fewer input pages 7168c2ecf20Sopenharmony_ci * assuming memory outage 7178c2ecf20Sopenharmony_ci */ 7188c2ecf20Sopenharmony_ci if (source_sz > page_sz) 7198c2ecf20Sopenharmony_ci source_sz = NX_MAX(source_sz / 2, page_sz); 7208c2ecf20Sopenharmony_ci --pgfault_retries; 7218c2ecf20Sopenharmony_ci goto restart_nx; 7228c2ecf20Sopenharmony_ci } else { 7238c2ecf20Sopenharmony_ci fprintf(stderr, "cannot make progress; too many "); 7248c2ecf20Sopenharmony_ci fprintf(stderr, "page fault retries cc= %d\n", cc); 7258c2ecf20Sopenharmony_ci rc = -1; 7268c2ecf20Sopenharmony_ci goto err5; 7278c2ecf20Sopenharmony_ci } 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci case ERR_NX_DATA_LENGTH: 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_ci NXPRT(fprintf(stderr, "ERR_NX_DATA_LENGTH; ")); 7328c2ecf20Sopenharmony_ci NXPRT(fprintf(stderr, "stream may have trailing data\n")); 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_ci /* Not an error in the most common case; it just says 7358c2ecf20Sopenharmony_ci * there is trailing data that we must examine. 7368c2ecf20Sopenharmony_ci * 7378c2ecf20Sopenharmony_ci * CC=3 CE(1)=0 CE(0)=1 indicates partial completion 7388c2ecf20Sopenharmony_ci * Fig.6-7 and Table 6-8. 7398c2ecf20Sopenharmony_ci */ 7408c2ecf20Sopenharmony_ci nx_ce = get_csb_ce_ms3b(cmdp->crb.csb); 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_ci if (!csb_ce_termination(nx_ce) && 7438c2ecf20Sopenharmony_ci csb_ce_partial_completion(nx_ce)) { 7448c2ecf20Sopenharmony_ci /* Check CPB for more information 7458c2ecf20Sopenharmony_ci * spbc and tpbc are valid 7468c2ecf20Sopenharmony_ci */ 7478c2ecf20Sopenharmony_ci sfbt = getnn(cmdp->cpb, out_sfbt); /* Table 6-4 */ 7488c2ecf20Sopenharmony_ci subc = getnn(cmdp->cpb, out_subc); /* Table 6-4 */ 7498c2ecf20Sopenharmony_ci spbc = get32(cmdp->cpb, out_spbc_decomp); 7508c2ecf20Sopenharmony_ci tpbc = get32(cmdp->crb.csb, tpbc); 7518c2ecf20Sopenharmony_ci assert(target_max >= tpbc); 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci goto ok_cc3; /* not an error */ 7548c2ecf20Sopenharmony_ci } else { 7558c2ecf20Sopenharmony_ci /* History length error when CE(1)=1 CE(0)=0. */ 7568c2ecf20Sopenharmony_ci rc = -1; 7578c2ecf20Sopenharmony_ci fprintf(stderr, "history length error cc= %d\n", cc); 7588c2ecf20Sopenharmony_ci goto err5; 7598c2ecf20Sopenharmony_ci } 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci case ERR_NX_TARGET_SPACE: 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci /* Target buffer not large enough; retry smaller input 7648c2ecf20Sopenharmony_ci * data; give at least 1 byte. SPBC/TPBC are not valid. 7658c2ecf20Sopenharmony_ci */ 7668c2ecf20Sopenharmony_ci assert(source_sz > history_len); 7678c2ecf20Sopenharmony_ci source_sz = ((source_sz - history_len + 2) / 2) + history_len; 7688c2ecf20Sopenharmony_ci NXPRT(fprintf(stderr, "ERR_NX_TARGET_SPACE; retry with ")); 7698c2ecf20Sopenharmony_ci NXPRT(fprintf(stderr, "smaller input data src %d hist %d\n", 7708c2ecf20Sopenharmony_ci source_sz, history_len)); 7718c2ecf20Sopenharmony_ci goto restart_nx; 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci case ERR_NX_OK: 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci /* This should not happen for gzip formatted data; 7768c2ecf20Sopenharmony_ci * we need trailing crc and isize 7778c2ecf20Sopenharmony_ci */ 7788c2ecf20Sopenharmony_ci fprintf(stderr, "ERR_NX_OK\n"); 7798c2ecf20Sopenharmony_ci spbc = get32(cmdp->cpb, out_spbc_decomp); 7808c2ecf20Sopenharmony_ci tpbc = get32(cmdp->crb.csb, tpbc); 7818c2ecf20Sopenharmony_ci assert(target_max >= tpbc); 7828c2ecf20Sopenharmony_ci assert(spbc >= history_len); 7838c2ecf20Sopenharmony_ci source_sz = spbc - history_len; 7848c2ecf20Sopenharmony_ci goto offsets_state; 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci default: 7878c2ecf20Sopenharmony_ci fprintf(stderr, "error: cc= %d\n", cc); 7888c2ecf20Sopenharmony_ci rc = -1; 7898c2ecf20Sopenharmony_ci goto err5; 7908c2ecf20Sopenharmony_ci } 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ciok_cc3: 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_ci NXPRT(fprintf(stderr, "cc3: sfbt: %x\n", sfbt)); 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_ci assert(spbc > history_len); 7978c2ecf20Sopenharmony_ci source_sz = spbc - history_len; 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci /* Table 6-4: Source Final Block Type (SFBT) describes the 8008c2ecf20Sopenharmony_ci * last processed deflate block and clues the software how to 8018c2ecf20Sopenharmony_ci * resume the next job. SUBC indicates how many input bits NX 8028c2ecf20Sopenharmony_ci * consumed but did not process. SPBC indicates how many 8038c2ecf20Sopenharmony_ci * bytes of source were given to the accelerator including 8048c2ecf20Sopenharmony_ci * history bytes. 8058c2ecf20Sopenharmony_ci */ 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci switch (sfbt) { 8088c2ecf20Sopenharmony_ci int dhtlen; 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_ci case 0x0: /* Deflate final EOB received */ 8118c2ecf20Sopenharmony_ci 8128c2ecf20Sopenharmony_ci /* Calculating the checksum start position. */ 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci source_sz = source_sz - subc / 8; 8158c2ecf20Sopenharmony_ci is_final = 1; 8168c2ecf20Sopenharmony_ci break; 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci /* Resume decompression cases are below. Basically 8198c2ecf20Sopenharmony_ci * indicates where NX has suspended and how to resume 8208c2ecf20Sopenharmony_ci * the input stream. 8218c2ecf20Sopenharmony_ci */ 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_ci case 0x8: /* Within a literal block; use rembytecount */ 8248c2ecf20Sopenharmony_ci case 0x9: /* Within a literal block; use rembytecount; bfinal=1 */ 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci /* Supply the partially processed source byte again */ 8278c2ecf20Sopenharmony_ci source_sz = source_sz - ((subc + 7) / 8); 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_ci /* SUBC LS 3bits: number of bits in the first source byte need 8308c2ecf20Sopenharmony_ci * to be processed. 8318c2ecf20Sopenharmony_ci * 000 means all 8 bits; Table 6-3 8328c2ecf20Sopenharmony_ci * Clear subc, histlen, sfbt, rembytecnt, dhtlen 8338c2ecf20Sopenharmony_ci */ 8348c2ecf20Sopenharmony_ci cmdp->cpb.in_subc = 0; 8358c2ecf20Sopenharmony_ci cmdp->cpb.in_sfbt = 0; 8368c2ecf20Sopenharmony_ci putnn(cmdp->cpb, in_subc, subc % 8); 8378c2ecf20Sopenharmony_ci putnn(cmdp->cpb, in_sfbt, sfbt); 8388c2ecf20Sopenharmony_ci putnn(cmdp->cpb, in_rembytecnt, getnn(cmdp->cpb, 8398c2ecf20Sopenharmony_ci out_rembytecnt)); 8408c2ecf20Sopenharmony_ci break; 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci case 0xA: /* Within a FH block; */ 8438c2ecf20Sopenharmony_ci case 0xB: /* Within a FH block; bfinal=1 */ 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_ci source_sz = source_sz - ((subc + 7) / 8); 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci /* Clear subc, histlen, sfbt, rembytecnt, dhtlen */ 8488c2ecf20Sopenharmony_ci cmdp->cpb.in_subc = 0; 8498c2ecf20Sopenharmony_ci cmdp->cpb.in_sfbt = 0; 8508c2ecf20Sopenharmony_ci putnn(cmdp->cpb, in_subc, subc % 8); 8518c2ecf20Sopenharmony_ci putnn(cmdp->cpb, in_sfbt, sfbt); 8528c2ecf20Sopenharmony_ci break; 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci case 0xC: /* Within a DH block; */ 8558c2ecf20Sopenharmony_ci case 0xD: /* Within a DH block; bfinal=1 */ 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_ci source_sz = source_sz - ((subc + 7) / 8); 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci /* Clear subc, histlen, sfbt, rembytecnt, dhtlen */ 8608c2ecf20Sopenharmony_ci cmdp->cpb.in_subc = 0; 8618c2ecf20Sopenharmony_ci cmdp->cpb.in_sfbt = 0; 8628c2ecf20Sopenharmony_ci putnn(cmdp->cpb, in_subc, subc % 8); 8638c2ecf20Sopenharmony_ci putnn(cmdp->cpb, in_sfbt, sfbt); 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci dhtlen = getnn(cmdp->cpb, out_dhtlen); 8668c2ecf20Sopenharmony_ci putnn(cmdp->cpb, in_dhtlen, dhtlen); 8678c2ecf20Sopenharmony_ci assert(dhtlen >= 42); 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_ci /* Round up to a qword */ 8708c2ecf20Sopenharmony_ci dhtlen = (dhtlen + 127) / 128; 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci while (dhtlen > 0) { /* Copy dht from cpb.out to cpb.in */ 8738c2ecf20Sopenharmony_ci --dhtlen; 8748c2ecf20Sopenharmony_ci cmdp->cpb.in_dht[dhtlen] = cmdp->cpb.out_dht[dhtlen]; 8758c2ecf20Sopenharmony_ci } 8768c2ecf20Sopenharmony_ci break; 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci case 0xE: /* Within a block header; bfinal=0; */ 8798c2ecf20Sopenharmony_ci /* Also given if source data exactly ends (SUBC=0) with 8808c2ecf20Sopenharmony_ci * EOB code with BFINAL=0. Means the next byte will 8818c2ecf20Sopenharmony_ci * contain a block header. 8828c2ecf20Sopenharmony_ci */ 8838c2ecf20Sopenharmony_ci case 0xF: /* within a block header with BFINAL=1. */ 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci source_sz = source_sz - ((subc + 7) / 8); 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci /* Clear subc, histlen, sfbt, rembytecnt, dhtlen */ 8888c2ecf20Sopenharmony_ci cmdp->cpb.in_subc = 0; 8898c2ecf20Sopenharmony_ci cmdp->cpb.in_sfbt = 0; 8908c2ecf20Sopenharmony_ci putnn(cmdp->cpb, in_subc, subc % 8); 8918c2ecf20Sopenharmony_ci putnn(cmdp->cpb, in_sfbt, sfbt); 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci /* Engine did not process any data */ 8948c2ecf20Sopenharmony_ci if (is_eof && (source_sz == 0)) 8958c2ecf20Sopenharmony_ci is_final = 1; 8968c2ecf20Sopenharmony_ci } 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_cioffsets_state: 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_ci /* Adjust the source and target buffer offsets and lengths */ 9018c2ecf20Sopenharmony_ci 9028c2ecf20Sopenharmony_ci NXPRT(fprintf(stderr, "offsets_state:\n")); 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci /* Delete input data from fifo_in */ 9058c2ecf20Sopenharmony_ci used_in = used_in - source_sz; 9068c2ecf20Sopenharmony_ci cur_in = (cur_in + source_sz) % fifo_in_len; 9078c2ecf20Sopenharmony_ci input_file_offset = input_file_offset + source_sz; 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci /* Add output data to fifo_out */ 9108c2ecf20Sopenharmony_ci used_out = used_out + tpbc; 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci assert(used_out <= fifo_out_len); 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci total_out = total_out + tpbc; 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci /* Deflate history is 32KB max. No need to supply more 9178c2ecf20Sopenharmony_ci * than 32KB on a resume. 9188c2ecf20Sopenharmony_ci */ 9198c2ecf20Sopenharmony_ci history_len = (total_out > window_max) ? window_max : total_out; 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci /* To estimate expected expansion in the next NX job; 500 means 50%. 9228c2ecf20Sopenharmony_ci * Deflate best case is around 1 to 1000. 9238c2ecf20Sopenharmony_ci */ 9248c2ecf20Sopenharmony_ci last_comp_ratio = (1000UL * ((uint64_t)source_sz + 1)) 9258c2ecf20Sopenharmony_ci / ((uint64_t)tpbc + 1); 9268c2ecf20Sopenharmony_ci last_comp_ratio = NX_MAX(NX_MIN(1000UL, last_comp_ratio), 1); 9278c2ecf20Sopenharmony_ci NXPRT(fprintf(stderr, "comp_ratio %ld source_sz %d spbc %d tpbc %d\n", 9288c2ecf20Sopenharmony_ci last_comp_ratio, source_sz, spbc, tpbc)); 9298c2ecf20Sopenharmony_ci 9308c2ecf20Sopenharmony_ci resuming = 1; 9318c2ecf20Sopenharmony_ci 9328c2ecf20Sopenharmony_cifinish_state: 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_ci NXPRT(fprintf(stderr, "finish_state:\n")); 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci if (is_final) { 9378c2ecf20Sopenharmony_ci if (used_out) 9388c2ecf20Sopenharmony_ci goto write_state; /* More data to write out */ 9398c2ecf20Sopenharmony_ci else if (used_in < 8) { 9408c2ecf20Sopenharmony_ci /* Need at least 8 more bytes containing gzip crc 9418c2ecf20Sopenharmony_ci * and isize. 9428c2ecf20Sopenharmony_ci */ 9438c2ecf20Sopenharmony_ci rc = -1; 9448c2ecf20Sopenharmony_ci goto err4; 9458c2ecf20Sopenharmony_ci } else { 9468c2ecf20Sopenharmony_ci /* Compare checksums and exit */ 9478c2ecf20Sopenharmony_ci int i; 9488c2ecf20Sopenharmony_ci unsigned char tail[8]; 9498c2ecf20Sopenharmony_ci uint32_t cksum, isize; 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 9528c2ecf20Sopenharmony_ci tail[i] = fifo_in[(cur_in + i) % fifo_in_len]; 9538c2ecf20Sopenharmony_ci fprintf(stderr, "computed checksum %08x isize %08x\n", 9548c2ecf20Sopenharmony_ci cmdp->cpb.out_crc, (uint32_t) (total_out 9558c2ecf20Sopenharmony_ci % (1ULL<<32))); 9568c2ecf20Sopenharmony_ci cksum = ((uint32_t) tail[0] | (uint32_t) tail[1]<<8 9578c2ecf20Sopenharmony_ci | (uint32_t) tail[2]<<16 9588c2ecf20Sopenharmony_ci | (uint32_t) tail[3]<<24); 9598c2ecf20Sopenharmony_ci isize = ((uint32_t) tail[4] | (uint32_t) tail[5]<<8 9608c2ecf20Sopenharmony_ci | (uint32_t) tail[6]<<16 9618c2ecf20Sopenharmony_ci | (uint32_t) tail[7]<<24); 9628c2ecf20Sopenharmony_ci fprintf(stderr, "stored checksum %08x isize %08x\n", 9638c2ecf20Sopenharmony_ci cksum, isize); 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci if (cksum == cmdp->cpb.out_crc && isize == (uint32_t) 9668c2ecf20Sopenharmony_ci (total_out % (1ULL<<32))) { 9678c2ecf20Sopenharmony_ci rc = 0; goto ok1; 9688c2ecf20Sopenharmony_ci } else { 9698c2ecf20Sopenharmony_ci rc = -1; goto err4; 9708c2ecf20Sopenharmony_ci } 9718c2ecf20Sopenharmony_ci } 9728c2ecf20Sopenharmony_ci } else 9738c2ecf20Sopenharmony_ci goto read_state; 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_ci return -1; 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_cierr1: 9788c2ecf20Sopenharmony_ci fprintf(stderr, "error: not a gzip file, expect %x, read %x\n", 9798c2ecf20Sopenharmony_ci expect, c); 9808c2ecf20Sopenharmony_ci return -1; 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_cierr2: 9838c2ecf20Sopenharmony_ci fprintf(stderr, "error: the FLG byte is wrong or not being handled\n"); 9848c2ecf20Sopenharmony_ci return -1; 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_cierr3: 9878c2ecf20Sopenharmony_ci fprintf(stderr, "error: gzip header\n"); 9888c2ecf20Sopenharmony_ci return -1; 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_cierr4: 9918c2ecf20Sopenharmony_ci fprintf(stderr, "error: checksum missing or mismatch\n"); 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_cierr5: 9948c2ecf20Sopenharmony_ciok1: 9958c2ecf20Sopenharmony_ci fprintf(stderr, "decomp is complete: fclose\n"); 9968c2ecf20Sopenharmony_ci fclose(outf); 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_ci return rc; 9998c2ecf20Sopenharmony_ci} 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ciint main(int argc, char **argv) 10038c2ecf20Sopenharmony_ci{ 10048c2ecf20Sopenharmony_ci int rc; 10058c2ecf20Sopenharmony_ci struct sigaction act; 10068c2ecf20Sopenharmony_ci void *handle; 10078c2ecf20Sopenharmony_ci 10088c2ecf20Sopenharmony_ci nx_dbg = 0; 10098c2ecf20Sopenharmony_ci nx_gzip_log = NULL; 10108c2ecf20Sopenharmony_ci act.sa_handler = 0; 10118c2ecf20Sopenharmony_ci act.sa_sigaction = nxu_sigsegv_handler; 10128c2ecf20Sopenharmony_ci act.sa_flags = SA_SIGINFO; 10138c2ecf20Sopenharmony_ci act.sa_restorer = 0; 10148c2ecf20Sopenharmony_ci sigemptyset(&act.sa_mask); 10158c2ecf20Sopenharmony_ci sigaction(SIGSEGV, &act, NULL); 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci handle = nx_function_begin(NX_FUNC_COMP_GZIP, 0); 10188c2ecf20Sopenharmony_ci if (!handle) { 10198c2ecf20Sopenharmony_ci fprintf(stderr, "Unable to init NX, errno %d\n", errno); 10208c2ecf20Sopenharmony_ci exit(-1); 10218c2ecf20Sopenharmony_ci } 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_ci rc = decompress_file(argc, argv, handle); 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci nx_function_end(handle); 10268c2ecf20Sopenharmony_ci 10278c2ecf20Sopenharmony_ci return rc; 10288c2ecf20Sopenharmony_ci} 1029