/* Allocate the XZ decoder state and register the character device. */ static int __init xz_dec_test_init(void) { static const struct file_operations fileops = { .owner = THIS_MODULE, .open = &xz_dec_test_open, .release = &xz_dec_test_release, .write = &xz_dec_test_write }; state = xz_dec_init(XZ_PREALLOC, DICT_MAX); if (state == NULL) return -ENOMEM; device_major = register_chrdev(0, DEVICE_NAME, &fileops); if (device_major < 0) { xz_dec_end(state); return device_major; } printk(KERN_INFO DEVICE_NAME ": module loaded\n"); printk(KERN_INFO DEVICE_NAME ": Create a device node with " "'mknod " DEVICE_NAME " c %d 0' and write .xz files " "to it.\n", device_major); return 0; }
int main(void) { struct xz_buf b; struct xz_dec *s; enum xz_ret ret; xz_crc32_init(); s = xz_dec_init(XZ_SINGLE, 0); if (s == NULL) { fputs("Initialization failed", stderr); return 1; } b.in = in; b.in_pos = 0; b.in_size = fread(in, 1, sizeof(in), stdin); b.out = out; b.out_pos = 0; b.out_size = sizeof(out); ret = xz_dec_run(s, &b); xz_dec_end(s); fwrite(out, 1, b.out_pos, stdout); fprintf(stderr, "%d\n", ret); return 0; }
static int decrunch_xz(FILE *in, FILE *out) { struct xz_buf b; struct xz_dec *state; unsigned char *membuf; int ret = 0; crc32_init_A(); memset(&b, 0, sizeof(b)); if ((membuf = malloc(2 * BUFFER_SIZE)) == NULL) return -1; b.in = membuf; b.out = membuf + BUFFER_SIZE; b.out_size = BUFFER_SIZE; /* Limit memory usage to 16M */ state = xz_dec_init(XZ_DYNALLOC, 16 * 1024 * 1024); while (1) { enum xz_ret r; if (b.in_pos == b.in_size) { int rd = fread(membuf, 1, BUFFER_SIZE, in); if (rd < 0) { ret = -1; break; } b.in_size = rd; b.in_pos = 0; } r = xz_dec_run(state, &b); if (b.out_pos) { fwrite(b.out, 1, b.out_pos, out); b.out_pos = 0; } if (r == XZ_STREAM_END) { break; } if (r != XZ_OK && r != XZ_UNSUPPORTED_CHECK) { ret = -1; break; } } xz_dec_end(state); free(membuf); return ret; }
static int decompressor_xz_destroy(struct microfs_sb_info* sbi, void* data) { struct decompressor_xz_data* xzdat = data; if (xzdat) { xz_dec_end(xzdat->xz_state); kfree(xzdat); } return 0; }
/* Release everything, including the underlying file object. */ static grub_err_t grub_xzio_close (grub_file_t file) { grub_xzio_t xzio = file->data; xz_dec_end (xzio->dec); grub_file_close (xzio->file); grub_free (xzio); /* Device must not be closed twice. */ file->device = 0; return grub_errno; }
static void __exit xz_dec_test_exit(void) { unregister_chrdev(device_major, DEVICE_NAME); xz_dec_end(state); printk(KERN_INFO DEVICE_NAME ": module unloaded\n"); }
static grub_file_t grub_xzio_open (grub_file_t io) { grub_file_t file; grub_xzio_t xzio; file = (grub_file_t) grub_zalloc (sizeof (*file)); if (!file) return 0; xzio = grub_zalloc (sizeof (*xzio)); if (!xzio) { grub_free (file); return 0; } xzio->file = io; xzio->saved_offset = 0; file->device = io->device; file->offset = 0; file->data = xzio; file->read_hook = 0; file->fs = &grub_xzio_fs; file->size = GRUB_FILE_SIZE_UNKNOWN; file->not_easly_seekable = 1; if (grub_file_tell (xzio->file) != 0) grub_file_seek (xzio->file, 0); /* Allocated 64KiB for dictionary. * Decoder will relocate if bigger is needed. */ xzio->dec = xz_dec_init (1 << 16); if (!xzio->dec) { grub_free (file); grub_free (xzio); return 0; } xzio->buf.in = xzio->inbuf; xzio->buf.in_pos = 0; xzio->buf.in_size = 0; xzio->buf.out = xzio->outbuf; xzio->buf.out_pos = 0; xzio->buf.out_size = XZBUFSIZ; /* FIXME: don't test footer on not easily seekable files. */ if (!test_header (file) || !test_footer (file)) { grub_errno = GRUB_ERR_NONE; grub_file_seek (io, 0); xz_dec_end (xzio->dec); grub_free (xzio); grub_free (file); return io; } return file; }
/* * This function implements the API defined in <linux/decompress/generic.h>. * * This wrapper will automatically choose single-call or multi-call mode * of the native XZ decoder API. The single-call mode can be used only when * both input and output buffers are available as a single chunk, i.e. when * fill() and flush() won't be used. */ STATIC int decompress_unxz(unsigned char *in, int in_size, int (*fill)(void *dest, unsigned int size), int (*flush)(void *src, unsigned int size), unsigned char *out, int *in_used, void (*error)(char *x)) { struct xz_buf b; struct xz_dec *s; enum xz_ret ret; bool must_free_in = false; #if XZ_INTERNAL_CRC32 xz_crc32_init(); #endif if (in_used != NULL) *in_used = 0; if (fill == NULL && flush == NULL) s = xz_dec_init(XZ_SINGLE, 0); else s = xz_dec_init(XZ_DYNALLOC, (uint32_t)-1); if (s == NULL) goto error_alloc_state; if (flush == NULL) { b.out = out; b.out_size = (size_t)-1; } else { b.out_size = XZ_IOBUF_SIZE; b.out = MALLOC(XZ_IOBUF_SIZE); if (b.out == NULL) goto error_alloc_out; } if (in == NULL) { must_free_in = true; in = MALLOC(XZ_IOBUF_SIZE); if (in == NULL) goto error_alloc_in; } b.in = in; b.in_pos = 0; b.in_size = in_size; b.out_pos = 0; if (fill == NULL && flush == NULL) { ret = xz_dec_run(s, &b); } else { do { if (b.in_pos == b.in_size && fill != NULL) { if (in_used != NULL) *in_used += b.in_pos; b.in_pos = 0; in_size = fill(in, XZ_IOBUF_SIZE); if (in_size < 0) { /* * This isn't an optimal error code * but it probably isn't worth making * a new one either. */ ret = XZ_BUF_ERROR; break; } b.in_size = in_size; } ret = xz_dec_run(s, &b); if (flush != NULL && (b.out_pos == b.out_size || (ret != XZ_OK && b.out_pos > 0))) { /* * Setting ret here may hide an error * returned by xz_dec_run(), but probably * it's not too bad. */ if (flush(b.out, b.out_pos) != (long)b.out_pos) ret = XZ_BUF_ERROR; b.out_pos = 0; } } while (ret == XZ_OK); if (must_free_in) FREE(in); if (flush != NULL) FREE(b.out); } if (in_used != NULL) *in_used += b.in_pos; xz_dec_end(s); switch (ret) { case XZ_STREAM_END: return 0; case XZ_MEM_ERROR: /* This can occur only in multi-call mode. */ error("XZ decompressor ran out of memory"); break; case XZ_FORMAT_ERROR: error("Input is not in the XZ format (wrong magic bytes)"); break; case XZ_OPTIONS_ERROR: error("Input was encoded with settings that are not " "supported by this XZ decoder"); break; case XZ_DATA_ERROR: case XZ_BUF_ERROR: error("XZ-compressed data is corrupt"); break; default: error("Bug in the XZ decompressor"); break; } return -1; error_alloc_in: if (flush != NULL) FREE(b.out); error_alloc_out: xz_dec_end(s); error_alloc_state: error("XZ decompressor ran out of memory"); return -1; }
static void crypto_xz_decomp_exit(struct xz_comp_ctx *ctx) { xz_dec_end(ctx->decomp_state); }
static errlHndl_t load_pnor_section(PNOR::SectionId i_section, uint64_t i_physAddr) { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,ENTER_MRK"load_pnor_section()"); errlHndl_t err = nullptr; #ifdef CONFIG_SECUREBOOT // Securely load section TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,"load_pnor_section: secure section load of secId=0x%X (%s)", i_section, PNOR::SectionIdToString(i_section)); err = PNOR::loadSecureSection(i_section); if (err) { return err; } // Do not need to unload since we have plenty of memory at this point. #endif // Get the section info from PNOR. PNOR::SectionInfo_t pnorSectionInfo; err = PNOR::getSectionInfo( i_section, pnorSectionInfo ); if( err != nullptr ) { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "load_pnor_section: Could not get section info from %x", i_section); return err; } // XZ repository: http:git.tukaani.org/xz.git // Header specifics can be found in xz/doc/xz-file-format.txt const uint8_t HEADER_MAGIC[]= { 0xFD, '7', 'z', 'X', 'Z', 0x00 }; uint8_t* l_pnor_header = reinterpret_cast<uint8_t *>(pnorSectionInfo.vaddr); bool l_pnor_is_XZ_compressed = (0 == memcmp(l_pnor_header, HEADER_MAGIC, sizeof(HEADER_MAGIC))); TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "load_pnor_section: is XZ_compressed: %d", l_pnor_is_XZ_compressed); // This assumes that the maximum decompression ratio will always be less // than 1:16 (compressed:uncompressed). This works because XZ compression // is usually 14.1%, the decompressor does not need the exact size, and // we have all of mainstore memory at this point. uint32_t uncompressedPayloadSize = l_pnor_is_XZ_compressed ? (pnorSectionInfo.size * 16) : pnorSectionInfo.size; const uint32_t originalPayloadSize = pnorSectionInfo.size; printk( "Loading PNOR section %d (%s) %d bytes @0x%lx\n", i_section, pnorSectionInfo.name, originalPayloadSize, i_physAddr ); void * loadAddr = NULL; // Map in the physical memory we are loading into. // If we are not xz compressed, the uncompressedSize // is equal to the original size. loadAddr = mm_block_map( reinterpret_cast<void*>( i_physAddr ), uncompressedPayloadSize ); // Print out inital progress bar. #ifdef CONFIG_CONSOLE const int progressSteps = 80; int progress = 0; for ( int i = 0; i < progressSteps; ++i ) { printk( "." ); } printk( "\r" ); #endif if(!l_pnor_is_XZ_compressed) { // Load the data block by block and update the progress bar. const uint32_t BLOCK_SIZE = 4096; for ( uint32_t i = 0; i < originalPayloadSize; i += BLOCK_SIZE ) { memcpy( reinterpret_cast<void*>( reinterpret_cast<uint64_t>(loadAddr) + i ), reinterpret_cast<void*>( pnorSectionInfo.vaddr + i ), std::min( originalPayloadSize - i, BLOCK_SIZE ) ); #ifdef CONFIG_CONSOLE for ( int new_progress = (i * progressSteps) / originalPayloadSize; progress <= new_progress; progress++ ) { printk( "=" ); } #endif } #ifdef CONFIG_CONSOLE printk( "\n" ); #endif } if(l_pnor_is_XZ_compressed) { struct xz_buf b; struct xz_dec *s; enum xz_ret ret; xz_crc32_init(); s = xz_dec_init(XZ_SINGLE, 0); if(s == NULL) { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,ERR_MRK "load_pnor_section: XZ Embedded Initialization failed"); return err; } static const uint64_t compressed_SIZE = originalPayloadSize; static const uint64_t decompressed_SIZE = uncompressedPayloadSize; b.in = reinterpret_cast<uint8_t *>( pnorSectionInfo.vaddr); b.in_pos = 0; b.in_size = compressed_SIZE; b.out = reinterpret_cast<uint8_t *>(loadAddr); b.out_pos = 0; b.out_size = decompressed_SIZE; ret = xz_dec_run(s, &b); if(ret == XZ_STREAM_END) { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "load_pnor_section: The %s section was decompressed.", pnorSectionInfo.name); }else { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,ERR_MRK "load_pnor_section: xz-embedded returned an error, ", "the ret is %d",ret); /*@ * @errortype * @reasoncode fapi::RC_INVALID_RETURN_XZ_CODE * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE * @moduleid fapi::MOD_START_XZ_PAYLOAD * @devdesc xz-embedded has returned an error. * the return code can be found in xz.h * @custdesc Error uncompressing payload image from * boot flash * @userdata1 Return code from xz-embedded * @userdata2[0:31] Original Payload Size * @userdata2[32:63] Uncompressed Payload Size */ err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, fapi::MOD_START_XZ_PAYLOAD, fapi::RC_INVALID_RETURN_XZ_CODE, ret,TWO_UINT32_TO_UINT64( originalPayloadSize, uncompressedPayloadSize)); err->addProcedureCallout(HWAS::EPUB_PRC_PHYP_CODE, HWAS::SRCI_PRIORITY_HIGH); } //Clean up memory xz_dec_end(s); } int rc = 0; rc = mm_block_unmap(reinterpret_cast<void *>(loadAddr)); if(rc) { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,ERR_MRK "load_pnor_section: mm_block_unmap returned 1"); /*@ * @errortype * @reasoncode fapi::RC_MM_UNMAP_ERR * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE * @moduleid fapi::MOD_START_XZ_PAYLOAD * @devdesc mm_block_unmap returned incorrectly with 0 * @custdesc Error unmapping memory section */ err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, fapi::MOD_START_XZ_PAYLOAD, fapi::RC_MM_UNMAP_ERR, 0,0,0); } return err; }
int main(int argc, char **argv, char *envp[]) { struct xz_buf b; struct xz_dec *s; enum xz_ret ret; const char *msg; if (argc >= 2 && strcmp(argv[1], "--help") == 0) { fputs("Uncompress a .xz file from stdin to stdout.\n" "Arguments other than `--help' are ignored.\n", stdout); return 0; } xz_crc32_init(); /* * Support up to 64 MiB dictionary. The actually needed memory * is allocated once the headers have been parsed. */ s = xz_dec_init(XZ_DYNALLOC, 1 << 26); if (s == NULL) { msg = "Memory allocation failed\n"; goto error; } b.in = in; b.in_pos = 0; b.in_size = BUFSIZ; b.out = out; b.out_pos = 0; b.out_size = BUFSIZ; // TODO add error checking char temp_dir_name[] = "/tmp/unv_installer_XXXXXX"; /* TODO: find tmpdir, don't assume it is /tmp */ mkdtemp(temp_dir_name); char temp_file_name[256]; sprintf(temp_file_name, "%s/installer", temp_dir_name); FILE* temp_fp = fopen(temp_file_name, "w"); while (true) { ret = xz_dec_run(s, &b); /*So that xz_dec_run will consume another BUFSIZ bytes (it reads from b.in_pos till b.in_size)*/ if (fwrite(b.out, 1, b.out_pos, temp_fp) != b.out_pos) { msg = "Write error\n"; goto error; } if (ret == XZ_OK){ b.in_size+=BUFSIZ; b.out_pos=0; continue; } #ifdef XZ_DEC_ANY_CHECK if (ret == XZ_UNSUPPORTED_CHECK) { fputs(argv[0], stderr); fputs(": ", stderr); fputs("Unsupported check; not verifying " "file integrity\n", stderr); continue; } #endif switch (ret) { case XZ_STREAM_END: xz_dec_end(s); chmod(temp_file_name, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); fclose(temp_fp); printf("%s\n", temp_file_name); int i = 0; while (envp[i] != NULL){ i++; } char **env = malloc((i+1)*sizeof(char *)); memcpy(env, envp, i*sizeof(char *)); char var[256]; sprintf(var, "LD_LIBRARY_PATH=%s", temp_dir_name); env[i] = var; env[i+1] = (char*) NULL; // {"LD_LIBRARY_PATH=", (char *) NULL}; execle(temp_file_name, temp_file_name, (char*) NULL, env); printf("Weird\n"); return 1; /*Will only occur if execl call failed.*/ case XZ_MEM_ERROR: msg = "Memory allocation failed\n"; goto error; case XZ_MEMLIMIT_ERROR: msg = "Memory usage limit reached\n"; goto error; case XZ_FORMAT_ERROR: msg = "Not a .xz file\n"; goto error; case XZ_OPTIONS_ERROR: msg = "Unsupported options in the .xz headers\n"; goto error; case XZ_DATA_ERROR: case XZ_BUF_ERROR: msg = "File is corrupt\n"; goto error; default: msg = "Bug!\n"; goto error; } } error: xz_dec_end(s); fputs(argv[0], stderr); fputs(": ", stderr); fputs(msg, stderr); return 1; }
/** * Compress command: tar -c car/ | xz --check=crc32 --lzma2=preset=6e,dict=512Ki > car.tar.xz * | ./iap 0.0.0.0 'target file' * * Decompress command: dxz 'src file' 'dest file' * dxz 'src file' | tar xv -C */ int dxz_file(FILE *src, FILE *dest) { struct xz_buf b; struct xz_dec *s; int ret; int show_flag = 0; xz_crc32_init(); s = xz_dec_init(XZ_PREALLOC, XZ_IN_BUFFSIZE); if (NULL == s) { DBG("Can not initialzation decompress object!\n"); return -1; } b.in = xz_ibuf; b.in_pos = 0; b.out = xz_obuf; b.out_pos = 0; b.out_size = sizeof(xz_obuf); do { if (0 == b.in_pos) { while(!CAN_READ_FILE(fileno(src), 10)); b.in_size = fread(xz_ibuf, 1, sizeof(xz_ibuf), src); if (!b.in_size) { return -1; } if (!show_flag) { show_flag = ~show_flag; disp_share_stat("正在解包."); } } ret = xz_dec_run(s, &b); disp_share_process(); if (b.in_pos == b.in_size) b.in_pos = 0; if (b.out_pos == b.out_size) { if (fwrite(xz_obuf, 1, b.out_size, dest) != b.out_size) { DBG("Write file fail!\n"); ret = -1; goto end; } b.out_pos = 0; } }while (XZ_OK == ret); if (XZ_STREAM_END == ret) { if (b.out_pos) { if (fwrite(xz_obuf, 1, b.out_pos, dest) != b.out_pos) { DBG("Write file fail!\n"); ret = -1; goto end; } } ret = 0; disp_share_stat("解包完成!\n"); } else { DBG("Decompress fail!(ret: %d)\n", ret); ret = -1; } end: xz_dec_end(s); if (ret != 0) { DBG("Processing fail!\n"); disp_share_stat("解包失败!\n"); sleep(2); } return ret; }
/* * This function implements the API defined in <linux/decompress/generic.h>. * * This wrapper will automatically choose single-call or multi-call mode * of the native XZ decoder API. The single-call mode can be used only when * both input and output buffers are available as a single chunk, i.e. when * fill() and flush() won't be used. * * This API doesn't provide a way to specify the maximum dictionary size * for the multi-call mode of the native XZ decoder API. We will use * DICT_MAX bytes, which will be allocated with vmalloc(). */ STATIC int XZ_FUNC unxz(/*const*/ unsigned char *in, int in_size, int (*fill)(void *dest, unsigned int size), int (*flush)(/*const*/ void *src, unsigned int size), unsigned char *out, int *in_used, void (*error)(/*const*/ char *x)) { struct xz_buf b; struct xz_dec *s; enum xz_ret ret; xz_crc32_init(); if (in != NULL && out != NULL) s = xz_dec_init(XZ_SINGLE, 0); else s = xz_dec_init(XZ_PREALLOC /*FIXME*/, DICT_MAX); if (s == NULL) goto error_alloc_state; b.in = in; b.in_pos = 0; b.in_size = in_size; b.out_pos = 0; if (in_used != NULL) *in_used = 0; if (fill == NULL && flush == NULL) { b.out = out; b.out_size = (size_t)-1; ret = xz_dec_run(s, &b); } else { b.out_size = XZ_IOBUF_SIZE; b.out = kmalloc(XZ_IOBUF_SIZE, GFP_KERNEL); if (b.out == NULL) goto error_alloc_out; if (fill != NULL) { in = kmalloc(XZ_IOBUF_SIZE, GFP_KERNEL); if (in == NULL) goto error_alloc_in; b.in = in; } do { if (b.in_pos == b.in_size && fill != NULL) { if (in_used != NULL) *in_used += b.in_pos; b.in_pos = 0; in_size = fill(in, XZ_IOBUF_SIZE); if (in_size < 0) { /* * This isn't an optimal error code * but it probably isn't worth making * a new one either. */ ret = XZ_BUF_ERROR; break; } b.in_size = in_size; } ret = xz_dec_run(s, &b); if (b.out_pos == b.out_size || ret != XZ_OK) { /* * Setting ret here may hide an error * returned by xz_dec_run(), but probably * it's not too bad. */ if (flush(b.out, b.out_pos) != (int)b.out_pos) ret = XZ_BUF_ERROR; b.out_pos = 0; } } while (ret == XZ_OK); if (fill != NULL) kfree(in); kfree(b.out); } if (in_used != NULL) *in_used += b.in_pos; xz_dec_end(s); switch (ret) { case XZ_STREAM_END: return 0; case XZ_MEMLIMIT_ERROR: /* This can occur only in multi-call mode. */ error("Multi-call XZ decompressor limits " "the LZMA2 dictionary to 1 MiB"); break; case XZ_FORMAT_ERROR: error("Input is not in the XZ format (wrong magic bytes)"); break; case XZ_OPTIONS_ERROR: error("Input was encoded with settings that are not " "supported by this XZ decoder"); break; case XZ_DATA_ERROR: error("XZ-compressed data is corrupt"); break; case XZ_BUF_ERROR: error("Output buffer is too small or the " "XZ-compressed data is corrupt"); break; default: error("Bug in the XZ decompressor"); break; } return -1; error_alloc_in: kfree(b.out); error_alloc_out: xz_dec_end(s); error_alloc_state: error("XZ decompressor ran out of memory"); return -1; }
XzStreamReader::~XzStreamReader() { xz_dec_end(m_decoder); }
int xz_decompress(unsigned char *encoded, int encoded_size, unsigned char **decoded, int *decoded_size) { static int xz_initialized = 0; enum xz_ret ret; struct xz_dec *xz; struct xz_buf buf; unsigned char *dec_buffer; unsigned char *temp; int dec_size; if (!xz_initialized) { xz_crc32_init(); xz_initialized = 1; } *decoded = NULL; *decoded_size = 0; buf.in = encoded; buf.in_pos = 0; buf.in_size = encoded_size; dec_size = BUFFER_INCREMENT; dec_buffer = (unsigned char *)malloc(dec_size); if (!dec_buffer) { return 0; } buf.out = dec_buffer; buf.out_pos = 0; buf.out_size = dec_size; xz = xz_dec_init(XZ_DYNALLOC, (uint32_t)-1); if (!xz) { free(dec_buffer); return 0; } do { ret = xz_dec_run(xz, &buf); if (ret == XZ_OK) { /* things are okay, but more buffer space is needed */ dec_size += BUFFER_INCREMENT; temp = realloc(dec_buffer, dec_size); if (!temp) { free(dec_buffer); xz_dec_end(xz); return 0; } else dec_buffer = temp; buf.out_size = dec_size; buf.out = dec_buffer; } else { /* any other status is an exit condition (either error or stream end) */ break; } } while (ret != XZ_STREAM_END); if (ret == XZ_STREAM_END) { /* resize the final buffer */ dec_size = buf.out_pos; temp = realloc(dec_buffer, dec_size); if (!temp) { free(dec_buffer); xz_dec_end(xz); return 0; } *decoded = temp; *decoded_size = dec_size; xz_dec_end(xz); return 1; } else { xz_dec_end(xz); free(dec_buffer); return 0; } }