162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci/* P9 gzip sample code for demonstrating the P9 NX hardware interface. 462306a36Sopenharmony_ci * Not intended for productive uses or for performance or compression 562306a36Sopenharmony_ci * ratio measurements. For simplicity of demonstration, this sample 662306a36Sopenharmony_ci * code compresses in to fixed Huffman blocks only (Deflate btype=1) 762306a36Sopenharmony_ci * and has very simple memory management. Dynamic Huffman blocks 862306a36Sopenharmony_ci * (Deflate btype=2) are more involved as detailed in the user guide. 962306a36Sopenharmony_ci * Note also that /dev/crypto/gzip, VAS and skiboot support are 1062306a36Sopenharmony_ci * required. 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * Copyright 2020 IBM Corp. 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * https://github.com/libnxz/power-gzip for zlib api and other utils 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * Author: Bulent Abali <abali@us.ibm.com> 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * Definitions of acronyms used here. See 1962306a36Sopenharmony_ci * P9 NX Gzip Accelerator User's Manual for details: 2062306a36Sopenharmony_ci * https://github.com/libnxz/power-gzip/blob/develop/doc/power_nx_gzip_um.pdf 2162306a36Sopenharmony_ci * 2262306a36Sopenharmony_ci * adler/crc: 32 bit checksums appended to stream tail 2362306a36Sopenharmony_ci * ce: completion extension 2462306a36Sopenharmony_ci * cpb: coprocessor parameter block (metadata) 2562306a36Sopenharmony_ci * crb: coprocessor request block (command) 2662306a36Sopenharmony_ci * csb: coprocessor status block (status) 2762306a36Sopenharmony_ci * dht: dynamic huffman table 2862306a36Sopenharmony_ci * dde: data descriptor element (address, length) 2962306a36Sopenharmony_ci * ddl: list of ddes 3062306a36Sopenharmony_ci * dh/fh: dynamic and fixed huffman types 3162306a36Sopenharmony_ci * fc: coprocessor function code 3262306a36Sopenharmony_ci * histlen: history/dictionary length 3362306a36Sopenharmony_ci * history: sliding window of up to 32KB of data 3462306a36Sopenharmony_ci * lzcount: Deflate LZ symbol counts 3562306a36Sopenharmony_ci * rembytecnt: remaining byte count 3662306a36Sopenharmony_ci * sfbt: source final block type; last block's type during decomp 3762306a36Sopenharmony_ci * spbc: source processed byte count 3862306a36Sopenharmony_ci * subc: source unprocessed bit count 3962306a36Sopenharmony_ci * tebc: target ending bit count; valid bits in the last byte 4062306a36Sopenharmony_ci * tpbc: target processed byte count 4162306a36Sopenharmony_ci * vas: virtual accelerator switch; the user mode interface 4262306a36Sopenharmony_ci */ 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#define _ISOC11_SOURCE // For aligned_alloc() 4562306a36Sopenharmony_ci#define _DEFAULT_SOURCE // For endian.h 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci#include <stdio.h> 4862306a36Sopenharmony_ci#include <stdlib.h> 4962306a36Sopenharmony_ci#include <string.h> 5062306a36Sopenharmony_ci#include <unistd.h> 5162306a36Sopenharmony_ci#include <stdint.h> 5262306a36Sopenharmony_ci#include <sys/types.h> 5362306a36Sopenharmony_ci#include <sys/stat.h> 5462306a36Sopenharmony_ci#include <sys/time.h> 5562306a36Sopenharmony_ci#include <sys/fcntl.h> 5662306a36Sopenharmony_ci#include <sys/mman.h> 5762306a36Sopenharmony_ci#include <endian.h> 5862306a36Sopenharmony_ci#include <bits/endian.h> 5962306a36Sopenharmony_ci#include <sys/ioctl.h> 6062306a36Sopenharmony_ci#include <assert.h> 6162306a36Sopenharmony_ci#include <errno.h> 6262306a36Sopenharmony_ci#include <signal.h> 6362306a36Sopenharmony_ci#include "utils.h" 6462306a36Sopenharmony_ci#include "nxu.h" 6562306a36Sopenharmony_ci#include "nx.h" 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ciint nx_dbg; 6862306a36Sopenharmony_ciFILE *nx_gzip_log; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci#define NX_MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) 7162306a36Sopenharmony_ci#define FNAME_MAX 1024 7262306a36Sopenharmony_ci#define FEXT ".nx.gz" 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci#define SYSFS_MAX_REQ_BUF_PATH "devices/vio/ibm,compression-v1/nx_gzip_caps/req_max_processed_len" 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci/* 7762306a36Sopenharmony_ci * LZ counts returned in the user supplied nx_gzip_crb_cpb_t structure. 7862306a36Sopenharmony_ci */ 7962306a36Sopenharmony_cistatic int compress_fht_sample(char *src, uint32_t srclen, char *dst, 8062306a36Sopenharmony_ci uint32_t dstlen, int with_count, 8162306a36Sopenharmony_ci struct nx_gzip_crb_cpb_t *cmdp, void *handle) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci uint32_t fc; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci assert(!!cmdp); 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci put32(cmdp->crb, gzip_fc, 0); /* clear */ 8862306a36Sopenharmony_ci fc = (with_count) ? GZIP_FC_COMPRESS_RESUME_FHT_COUNT : 8962306a36Sopenharmony_ci GZIP_FC_COMPRESS_RESUME_FHT; 9062306a36Sopenharmony_ci putnn(cmdp->crb, gzip_fc, fc); 9162306a36Sopenharmony_ci putnn(cmdp->cpb, in_histlen, 0); /* resuming with no history */ 9262306a36Sopenharmony_ci memset((void *) &cmdp->crb.csb, 0, sizeof(cmdp->crb.csb)); 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci /* Section 6.6 programming notes; spbc may be in two different 9562306a36Sopenharmony_ci * places depending on FC. 9662306a36Sopenharmony_ci */ 9762306a36Sopenharmony_ci if (!with_count) 9862306a36Sopenharmony_ci put32(cmdp->cpb, out_spbc_comp, 0); 9962306a36Sopenharmony_ci else 10062306a36Sopenharmony_ci put32(cmdp->cpb, out_spbc_comp_with_count, 0); 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci /* Figure 6-3 6-4; CSB location */ 10362306a36Sopenharmony_ci put64(cmdp->crb, csb_address, 0); 10462306a36Sopenharmony_ci put64(cmdp->crb, csb_address, 10562306a36Sopenharmony_ci (uint64_t) &cmdp->crb.csb & csb_address_mask); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci /* Source direct dde (scatter-gather list) */ 10862306a36Sopenharmony_ci clear_dde(cmdp->crb.source_dde); 10962306a36Sopenharmony_ci putnn(cmdp->crb.source_dde, dde_count, 0); 11062306a36Sopenharmony_ci put32(cmdp->crb.source_dde, ddebc, srclen); 11162306a36Sopenharmony_ci put64(cmdp->crb.source_dde, ddead, (uint64_t) src); 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci /* Target direct dde (scatter-gather list) */ 11462306a36Sopenharmony_ci clear_dde(cmdp->crb.target_dde); 11562306a36Sopenharmony_ci putnn(cmdp->crb.target_dde, dde_count, 0); 11662306a36Sopenharmony_ci put32(cmdp->crb.target_dde, ddebc, dstlen); 11762306a36Sopenharmony_ci put64(cmdp->crb.target_dde, ddead, (uint64_t) dst); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci /* Submit the crb, the job descriptor, to the accelerator */ 12062306a36Sopenharmony_ci return nxu_submit_job(cmdp, handle); 12162306a36Sopenharmony_ci} 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci/* 12462306a36Sopenharmony_ci * Prepares a blank no filename no timestamp gzip header and returns 12562306a36Sopenharmony_ci * the number of bytes written to buf. 12662306a36Sopenharmony_ci * Gzip specification at https://tools.ietf.org/html/rfc1952 12762306a36Sopenharmony_ci */ 12862306a36Sopenharmony_ciint gzip_header_blank(char *buf) 12962306a36Sopenharmony_ci{ 13062306a36Sopenharmony_ci int i = 0; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci buf[i++] = 0x1f; /* ID1 */ 13362306a36Sopenharmony_ci buf[i++] = 0x8b; /* ID2 */ 13462306a36Sopenharmony_ci buf[i++] = 0x08; /* CM */ 13562306a36Sopenharmony_ci buf[i++] = 0x00; /* FLG */ 13662306a36Sopenharmony_ci buf[i++] = 0x00; /* MTIME */ 13762306a36Sopenharmony_ci buf[i++] = 0x00; /* MTIME */ 13862306a36Sopenharmony_ci buf[i++] = 0x00; /* MTIME */ 13962306a36Sopenharmony_ci buf[i++] = 0x00; /* MTIME */ 14062306a36Sopenharmony_ci buf[i++] = 0x04; /* XFL 4=fastest */ 14162306a36Sopenharmony_ci buf[i++] = 0x03; /* OS UNIX */ 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci return i; 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci/* 14762306a36Sopenharmony_ci * Z_SYNC_FLUSH as described in zlib.h. 14862306a36Sopenharmony_ci * Returns number of appended bytes 14962306a36Sopenharmony_ci */ 15062306a36Sopenharmony_ciint append_sync_flush(char *buf, int tebc, int final) 15162306a36Sopenharmony_ci{ 15262306a36Sopenharmony_ci uint64_t flush; 15362306a36Sopenharmony_ci int shift = (tebc & 0x7); 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci if (tebc > 0) { 15662306a36Sopenharmony_ci /* Last byte is partially full */ 15762306a36Sopenharmony_ci buf = buf - 1; 15862306a36Sopenharmony_ci *buf = *buf & (unsigned char) ((1<<tebc)-1); 15962306a36Sopenharmony_ci } else 16062306a36Sopenharmony_ci *buf = 0; 16162306a36Sopenharmony_ci flush = ((0x1ULL & final) << shift) | *buf; 16262306a36Sopenharmony_ci shift = shift + 3; /* BFINAL and BTYPE written */ 16362306a36Sopenharmony_ci shift = (shift <= 8) ? 8 : 16; 16462306a36Sopenharmony_ci flush |= (0xFFFF0000ULL) << shift; /* Zero length block */ 16562306a36Sopenharmony_ci shift = shift + 32; 16662306a36Sopenharmony_ci while (shift > 0) { 16762306a36Sopenharmony_ci *buf++ = (unsigned char) (flush & 0xffULL); 16862306a36Sopenharmony_ci flush = flush >> 8; 16962306a36Sopenharmony_ci shift = shift - 8; 17062306a36Sopenharmony_ci } 17162306a36Sopenharmony_ci return(((tebc > 5) || (tebc == 0)) ? 5 : 4); 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci/* 17562306a36Sopenharmony_ci * Final deflate block bit. This call assumes the block 17662306a36Sopenharmony_ci * beginning is byte aligned. 17762306a36Sopenharmony_ci */ 17862306a36Sopenharmony_cistatic void set_bfinal(void *buf, int bfinal) 17962306a36Sopenharmony_ci{ 18062306a36Sopenharmony_ci char *b = buf; 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci if (bfinal) 18362306a36Sopenharmony_ci *b = *b | (unsigned char) 0x01; 18462306a36Sopenharmony_ci else 18562306a36Sopenharmony_ci *b = *b & (unsigned char) 0xfe; 18662306a36Sopenharmony_ci} 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ciint compress_file(int argc, char **argv, void *handle) 18962306a36Sopenharmony_ci{ 19062306a36Sopenharmony_ci char *inbuf, *outbuf, *srcbuf, *dstbuf; 19162306a36Sopenharmony_ci char outname[FNAME_MAX]; 19262306a36Sopenharmony_ci uint32_t srclen, dstlen; 19362306a36Sopenharmony_ci uint32_t flushlen, chunk; 19462306a36Sopenharmony_ci size_t inlen, outlen, dsttotlen, srctotlen; 19562306a36Sopenharmony_ci uint32_t crc, spbc, tpbc, tebc; 19662306a36Sopenharmony_ci int lzcounts = 0; 19762306a36Sopenharmony_ci int cc; 19862306a36Sopenharmony_ci int num_hdr_bytes; 19962306a36Sopenharmony_ci struct nx_gzip_crb_cpb_t *cmdp; 20062306a36Sopenharmony_ci uint32_t pagelen = 65536; 20162306a36Sopenharmony_ci int fault_tries = NX_MAX_FAULTS; 20262306a36Sopenharmony_ci char buf[32]; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci cmdp = (void *)(uintptr_t) 20562306a36Sopenharmony_ci aligned_alloc(sizeof(struct nx_gzip_crb_cpb_t), 20662306a36Sopenharmony_ci sizeof(struct nx_gzip_crb_cpb_t)); 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci if (argc != 2) { 20962306a36Sopenharmony_ci fprintf(stderr, "usage: %s <fname>\n", argv[0]); 21062306a36Sopenharmony_ci exit(-1); 21162306a36Sopenharmony_ci } 21262306a36Sopenharmony_ci if (read_file_alloc(argv[1], &inbuf, &inlen)) 21362306a36Sopenharmony_ci exit(-1); 21462306a36Sopenharmony_ci fprintf(stderr, "file %s read, %ld bytes\n", argv[1], inlen); 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci /* Generous output buffer for header/trailer */ 21762306a36Sopenharmony_ci outlen = 2 * inlen + 1024; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci assert(NULL != (outbuf = (char *)malloc(outlen))); 22062306a36Sopenharmony_ci nxu_touch_pages(outbuf, outlen, pagelen, 1); 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci /* 22362306a36Sopenharmony_ci * On PowerVM, the hypervisor defines the maximum request buffer 22462306a36Sopenharmony_ci * size is defined and this value is available via sysfs. 22562306a36Sopenharmony_ci */ 22662306a36Sopenharmony_ci if (!read_sysfs_file(SYSFS_MAX_REQ_BUF_PATH, buf, sizeof(buf))) { 22762306a36Sopenharmony_ci chunk = atoi(buf); 22862306a36Sopenharmony_ci } else { 22962306a36Sopenharmony_ci /* sysfs entry is not available on PowerNV */ 23062306a36Sopenharmony_ci /* Compress piecemeal in smallish chunks */ 23162306a36Sopenharmony_ci chunk = 1<<22; 23262306a36Sopenharmony_ci } 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci /* Write the gzip header to the stream */ 23562306a36Sopenharmony_ci num_hdr_bytes = gzip_header_blank(outbuf); 23662306a36Sopenharmony_ci dstbuf = outbuf + num_hdr_bytes; 23762306a36Sopenharmony_ci outlen = outlen - num_hdr_bytes; 23862306a36Sopenharmony_ci dsttotlen = num_hdr_bytes; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci srcbuf = inbuf; 24162306a36Sopenharmony_ci srctotlen = 0; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci /* Init the CRB, the coprocessor request block */ 24462306a36Sopenharmony_ci memset(&cmdp->crb, 0, sizeof(cmdp->crb)); 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci /* Initial gzip crc32 */ 24762306a36Sopenharmony_ci put32(cmdp->cpb, in_crc, 0); 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci while (inlen > 0) { 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci /* Submit chunk size source data per job */ 25262306a36Sopenharmony_ci srclen = NX_MIN(chunk, inlen); 25362306a36Sopenharmony_ci /* Supply large target in case data expands */ 25462306a36Sopenharmony_ci dstlen = NX_MIN(2*srclen, outlen); 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci /* Page faults are handled by the user code */ 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci /* Fault-in pages; an improved code wouldn't touch so 25962306a36Sopenharmony_ci * many pages but would try to estimate the 26062306a36Sopenharmony_ci * compression ratio and adjust both the src and dst 26162306a36Sopenharmony_ci * touch amounts. 26262306a36Sopenharmony_ci */ 26362306a36Sopenharmony_ci nxu_touch_pages(cmdp, sizeof(struct nx_gzip_crb_cpb_t), pagelen, 26462306a36Sopenharmony_ci 1); 26562306a36Sopenharmony_ci nxu_touch_pages(srcbuf, srclen, pagelen, 0); 26662306a36Sopenharmony_ci nxu_touch_pages(dstbuf, dstlen, pagelen, 1); 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci cc = compress_fht_sample( 26962306a36Sopenharmony_ci srcbuf, srclen, 27062306a36Sopenharmony_ci dstbuf, dstlen, 27162306a36Sopenharmony_ci lzcounts, cmdp, handle); 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci if (cc != ERR_NX_OK && cc != ERR_NX_TPBC_GT_SPBC && 27462306a36Sopenharmony_ci cc != ERR_NX_AT_FAULT) { 27562306a36Sopenharmony_ci fprintf(stderr, "nx error: cc= %d\n", cc); 27662306a36Sopenharmony_ci exit(-1); 27762306a36Sopenharmony_ci } 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci /* Page faults are handled by the user code */ 28062306a36Sopenharmony_ci if (cc == ERR_NX_AT_FAULT) { 28162306a36Sopenharmony_ci NXPRT(fprintf(stderr, "page fault: cc= %d, ", cc)); 28262306a36Sopenharmony_ci NXPRT(fprintf(stderr, "try= %d, fsa= %08llx\n", 28362306a36Sopenharmony_ci fault_tries, 28462306a36Sopenharmony_ci (unsigned long long) cmdp->crb.csb.fsaddr)); 28562306a36Sopenharmony_ci fault_tries--; 28662306a36Sopenharmony_ci if (fault_tries > 0) { 28762306a36Sopenharmony_ci continue; 28862306a36Sopenharmony_ci } else { 28962306a36Sopenharmony_ci fprintf(stderr, "error: cannot progress; "); 29062306a36Sopenharmony_ci fprintf(stderr, "too many faults\n"); 29162306a36Sopenharmony_ci exit(-1); 29262306a36Sopenharmony_ci } 29362306a36Sopenharmony_ci } 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci fault_tries = NX_MAX_FAULTS; /* Reset for the next chunk */ 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci inlen = inlen - srclen; 29862306a36Sopenharmony_ci srcbuf = srcbuf + srclen; 29962306a36Sopenharmony_ci srctotlen = srctotlen + srclen; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci /* Two possible locations for spbc depending on the function 30262306a36Sopenharmony_ci * code. 30362306a36Sopenharmony_ci */ 30462306a36Sopenharmony_ci spbc = (!lzcounts) ? get32(cmdp->cpb, out_spbc_comp) : 30562306a36Sopenharmony_ci get32(cmdp->cpb, out_spbc_comp_with_count); 30662306a36Sopenharmony_ci assert(spbc == srclen); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci /* Target byte count */ 30962306a36Sopenharmony_ci tpbc = get32(cmdp->crb.csb, tpbc); 31062306a36Sopenharmony_ci /* Target ending bit count */ 31162306a36Sopenharmony_ci tebc = getnn(cmdp->cpb, out_tebc); 31262306a36Sopenharmony_ci NXPRT(fprintf(stderr, "compressed chunk %d ", spbc)); 31362306a36Sopenharmony_ci NXPRT(fprintf(stderr, "to %d bytes, tebc= %d\n", tpbc, tebc)); 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci if (inlen > 0) { /* More chunks to go */ 31662306a36Sopenharmony_ci set_bfinal(dstbuf, 0); 31762306a36Sopenharmony_ci dstbuf = dstbuf + tpbc; 31862306a36Sopenharmony_ci dsttotlen = dsttotlen + tpbc; 31962306a36Sopenharmony_ci outlen = outlen - tpbc; 32062306a36Sopenharmony_ci /* Round up to the next byte with a flush 32162306a36Sopenharmony_ci * block; do not set the BFINAqL bit. 32262306a36Sopenharmony_ci */ 32362306a36Sopenharmony_ci flushlen = append_sync_flush(dstbuf, tebc, 0); 32462306a36Sopenharmony_ci dsttotlen = dsttotlen + flushlen; 32562306a36Sopenharmony_ci outlen = outlen - flushlen; 32662306a36Sopenharmony_ci dstbuf = dstbuf + flushlen; 32762306a36Sopenharmony_ci NXPRT(fprintf(stderr, "added sync_flush %d bytes\n", 32862306a36Sopenharmony_ci flushlen)); 32962306a36Sopenharmony_ci } else { /* Done */ 33062306a36Sopenharmony_ci /* Set the BFINAL bit of the last block per Deflate 33162306a36Sopenharmony_ci * specification. 33262306a36Sopenharmony_ci */ 33362306a36Sopenharmony_ci set_bfinal(dstbuf, 1); 33462306a36Sopenharmony_ci dstbuf = dstbuf + tpbc; 33562306a36Sopenharmony_ci dsttotlen = dsttotlen + tpbc; 33662306a36Sopenharmony_ci outlen = outlen - tpbc; 33762306a36Sopenharmony_ci } 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci /* Resuming crc32 for the next chunk */ 34062306a36Sopenharmony_ci crc = get32(cmdp->cpb, out_crc); 34162306a36Sopenharmony_ci put32(cmdp->cpb, in_crc, crc); 34262306a36Sopenharmony_ci crc = be32toh(crc); 34362306a36Sopenharmony_ci } 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci /* Append crc32 and ISIZE to the end */ 34662306a36Sopenharmony_ci memcpy(dstbuf, &crc, 4); 34762306a36Sopenharmony_ci memcpy(dstbuf+4, &srctotlen, 4); 34862306a36Sopenharmony_ci dsttotlen = dsttotlen + 8; 34962306a36Sopenharmony_ci outlen = outlen - 8; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci assert(FNAME_MAX > (strlen(argv[1]) + strlen(FEXT))); 35262306a36Sopenharmony_ci strcpy(outname, argv[1]); 35362306a36Sopenharmony_ci strcat(outname, FEXT); 35462306a36Sopenharmony_ci if (write_file(outname, outbuf, dsttotlen)) { 35562306a36Sopenharmony_ci fprintf(stderr, "write error: %s\n", outname); 35662306a36Sopenharmony_ci exit(-1); 35762306a36Sopenharmony_ci } 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci fprintf(stderr, "compressed %ld to %ld bytes total, ", srctotlen, 36062306a36Sopenharmony_ci dsttotlen); 36162306a36Sopenharmony_ci fprintf(stderr, "crc32 checksum = %08x\n", crc); 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci if (inbuf != NULL) 36462306a36Sopenharmony_ci free(inbuf); 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci if (outbuf != NULL) 36762306a36Sopenharmony_ci free(outbuf); 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci return 0; 37062306a36Sopenharmony_ci} 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ciint main(int argc, char **argv) 37362306a36Sopenharmony_ci{ 37462306a36Sopenharmony_ci int rc; 37562306a36Sopenharmony_ci struct sigaction act; 37662306a36Sopenharmony_ci void *handle; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci nx_dbg = 0; 37962306a36Sopenharmony_ci nx_gzip_log = NULL; 38062306a36Sopenharmony_ci act.sa_handler = 0; 38162306a36Sopenharmony_ci act.sa_sigaction = nxu_sigsegv_handler; 38262306a36Sopenharmony_ci act.sa_flags = SA_SIGINFO; 38362306a36Sopenharmony_ci act.sa_restorer = 0; 38462306a36Sopenharmony_ci sigemptyset(&act.sa_mask); 38562306a36Sopenharmony_ci sigaction(SIGSEGV, &act, NULL); 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci handle = nx_function_begin(NX_FUNC_COMP_GZIP, 0); 38862306a36Sopenharmony_ci if (!handle) { 38962306a36Sopenharmony_ci fprintf(stderr, "Unable to init NX, errno %d\n", errno); 39062306a36Sopenharmony_ci exit(-1); 39162306a36Sopenharmony_ci } 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci rc = compress_file(argc, argv, handle); 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci nx_function_end(handle); 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci return rc; 39862306a36Sopenharmony_ci} 399