提交 3ae1d266 编写于 作者: Y yanxiaoyong-ch 提交者: Jinliang Li

remove ota component's gpl related files. (#1438)

* fix read memory overflow risk of linksdk's mqtt.

* remove ota component's gpl related files.
上级 51138f44
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include "2ndboot.h"
#include "updater.h"
int ota_patch_show_percent(int per)
{
int ret = 0;
OTA_LOG_I("Show upgrade percent:%d \n", per);
return ret;
}
int ota_updater(void)
{
int ret = -1;
ota_boot_param_t ota_param = {0};
ret = ota_patch_read_param(&ota_param);
if(ret < 0) {
OTA_LOG_I("read param err.\n");
return -1;
}
ota_param.boot_count++;
OTA_LOG_I("ota upg_flag:0x%04x count:%d crc;0x%04x \n", ota_param.upg_flag, ota_param.boot_count, ota_param.param_crc);
if(ota_param.upg_flag == OTA_UPGRADE_DIFF) {
ret = ota_nbpatch_main();
} else if(ota_param.upg_flag == OTA_UPGRADE_XZ) {
ret = ota_xz_main();
} else if(ota_param.upg_flag == OTA_UPGRADE_ALL) {
if(ota_param.boot_type == 0) {
ret = ota_image_check(ota_param.src_adr, ota_param.len, ota_param.crc);
if(ret < 0) {
OTA_LOG_I("CRC fail.\n");
goto EXIT;
}
ret = ota_image_copy(ota_param.dst_adr, ota_param.src_adr, ota_param.len);
} else {
OTA_LOG_I("dual boot, not copy.\n");
}
} else {
OTA_LOG_I("No OTA upgrade.\n");
return 0;
}
EXIT:
OTA_LOG_I("ota update complete ret:%d \n", ret);
if(ret < 0 && ota_param.boot_count <= 3) {
ota_patch_write_param(&ota_param);
sys_delayms(100);
sys_reboot();
} else {
if(ota_param.upg_flag != 0) {
ota_param.upg_flag = 0;
ota_patch_write_param(&ota_param);
}
if(ota_param.boot_count > 3) { /* todo: rollback old version for dual banker boot. */
}
}
return ret;
}
void ota_2ndboot_error(void *errinfo)
{
printf(errinfo);
sys_reboot();
}
void print_usage(void)
{
printf("2ndboot ver: " SYSINFO_2NDBOOT_VERSION "\r\n");
#ifdef AOS_2ND_BOOT_AB
printf("Please input 1-4 to select functions\r\n");
#else
printf("Please input 1-2 to select functions\r\n");
#endif
printf("[1] Uart Ymodem Upgrade \r\n");
printf("[2] System Reboot \r\n");
#ifdef AOS_2ND_BOOT_AB
printf("[3] Show AB Boot \r\n");
printf("[4] Switch AB Boot \r\n");
#endif
printf("[h] Help Info\r\n");
}
static void ota_2ndboot_cli_menu(void)
{
unsigned char c = 0;
#ifdef AOS_2ND_BOOT_AB
int ab = 0;
#endif
print_usage();
printf("\r\naos boot# ");
while(1) {
if(uart_recv_byte(&c)) {
if('w' == c) {
continue;
}
if( ('\r' == c) || ('\n' == c) ) {
printf("\r\naos boot# ");
continue;
}
printf("%c \r\n", c);
switch(c) {
case '1' :
ymodem_upgrade();
break;
case '2' :
printf("Reboot \r\n");
sys_reboot();
break;
#ifdef AOS_2ND_BOOT_AB
case '3' :
ab = ota_2ndboot_ab_get();
printf("%s Boot .. \r\n", (ab == 0)?"A":"B");
break;
case '4' :
ab = ota_2ndboot_ab_get();
printf("Switch %s to %s Boot .. \r\n", (ab == 0)?"A":"B", (ab == 0)?"B":"A");
ota_2ndboot_ab_switch();
break;
#endif
default:
print_usage();
break;
}
printf("\r\naos boot# ");
sys_delayms(1);
}
}
}
static int ota_2ndboot_init()
{
#ifdef AOS_2ND_BOOT_NO_LDS
_rec_heap_start = sys_set_heap(&_rec_heap_len);
#endif
}
int ota_2ndboot_main(void)
{
int ret = 0;
unsigned char c = 0;
unsigned int i = 0;
ota_2ndboot_init();
uart_init();
printf("\r\nPress key \'w\' to 2ndboot cli menu in 100ms.\r\n");
while(1) {
if(uart_recv_byte(&c) && ('w' == c)) {
ota_2ndboot_cli_menu();
return 0;
}
i ++;
if(i >= 100)break;
sys_delayms(1);
}
wdg_init(OTA_2NDBOOT_WDG_TIMEOUT*1000);
wdg_feed();
/* check OTA upgrade */
ret = ota_updater();
wdg_finish();
return ret;
}
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef SECOND_BOOT_HAL_H
#define SECOND_BOOT_HAL_H
#include "aos/hal/flash.h"
#include "updater.h"
#define SECTOR_SIZE 0x1000 /* flash sector size */
#ifndef OTA_2NDBOOT_WDG_TIMEOUT
#define OTA_2NDBOOT_WDG_TIMEOUT 120
#endif
#define ROUND_DOWN(a,b) (((a) / (b)) * (b))
#define FLASH_ALIGN_MASK ~(sizeof(unsigned int) - 1)
#define FLASH_ALIGN sizeof(unsigned int)
/* system APIs */
void sys_reboot(void);
void sys_delayms(volatile int ms);
#ifdef AOS_2ND_BOOT_NO_LDS
void *sys_set_heap(unsigned int *size);
#endif
/* uart APIs */
void uart_init(void);
void uart_send(unsigned char *buf, int len);
void uart_send_string(char *buf);
unsigned char uart_recv_byte(unsigned char *c);
void uart_send_byte(unsigned char buf);
/* flash APIs */
int flash_erase(unsigned int offset, unsigned int len);
int flash_read_data(unsigned int offset, unsigned char *buf, unsigned int len);
int flash_write_data(unsigned int offset, unsigned char *buf, unsigned int len);
hal_logic_partition_t *flash_get_info(hal_partition_t no);
/* watchdog APIs */
void wdg_init(unsigned int ms);
void wdg_feed(void);
void wdg_finish(void);
#ifdef AOS_2ND_BOOT_AB
/* 0: A, 1: B*/
int ota_2ndboot_ab_get(void);
void ota_2ndboot_ab_switch(void);
#endif
#endif /*SECOND_BOOT_HAL_H */
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef OTA_LIBC_H
#define OTA_LIBC_H
#define ALIGN(x,a) (((x) + (a) - 1) & ~((a) - 1))
#define XZ_HEAP_ALIGNMENT 4
#define XZ_HEAP_BLK_HEAD_SIZE ALIGN(sizeof(blk_head_t), XZ_HEAP_ALIGNMENT)
#define XZ_HEAP_BLK_MIN ((XZ_HEAP_BLK_HEAD_SIZE) << 1)
#define XZ_HEAP_MAGIC (0xF0000000)
#define OTA_LOG_I(fmt, ...) printf("%d: "fmt"\r\n", __LINE__, ##__VA_ARGS__)
#if defined __LINUX_HOST__
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#else
#ifndef AOS_2ND_BOOT_NO_LDS
extern void *_rec_heap_start;
extern void *_rec_heap_len;
#define XZ_HEAP_BASE ((int)&_rec_heap_start)
#define XZ_HEAP_SIZE ((int)&_rec_heap_len)
#else
extern void *_rec_heap_start;
extern unsigned int _rec_heap_len;
#define XZ_HEAP_BASE ((unsigned int)_rec_heap_start)
#define XZ_HEAP_SIZE (_rec_heap_len)
#endif
#define memset ota_memset
#define memcpy ota_memcpy
#define memcmp ota_memcmp
#define memmove ota_memmove
#define strlen ota_strlen
#define strcat ota_strcat
#define printf ota_printf
#define malloc ota_heap_malloc
#define free ota_heap_free
#define puts ota_puts
#endif
void *ota_memset(void *s, int c, unsigned int n);
void *ota_memcpy(void *dest, const void *src, unsigned int n);
int ota_memcmp(const void * buf1, const void * buf2, unsigned int count);
void *ota_memmove(void *dest, const void *src, unsigned int count);
unsigned int ota_strlen(char * str);
char *ota_strcat (char * dst, const char * src);
int ota_puts(const char *str);
int ota_printf(const char *format, ...);
void *ota_heap_malloc(unsigned int alloc_size);
void ota_heap_free(void *pfree);
typedef struct {
unsigned short crc;
} CRC16_CTX;
void crc16_init(CRC16_CTX *inContext);
void crc16_update(CRC16_CTX *inContext, const void *inSrc, long inLen);
void crc16_final(CRC16_CTX *inContext, unsigned short *outResult);
unsigned short crc16_computer(void *buf, long len);
#endif /* _OTA_LIBC_H_ */
#ifndef OTA_UPDATE
#define OTA_UPDATE
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
// #include "libc.h"
#include "2ndboot.h"
#include "ota_updater.h"
#ifndef XZ_BUF_SIZE
#define XZ_BUF_SIZE 2048
#endif
/* OTA upgrade magic <--> upg_flag */
#define OTA_UPGRADE_ALL 0x9669 /* upgrade all image: kernel+framework+app */
#define OTA_UPGRADE_XZ 0xA55A /* upgrade xz compressed image */
#define OTA_UPGRADE_DIFF 0xB44B /* upgrade diff compressed image */
#define OTA_UPGRADE_KERNEL 0xC33C /* upgrade kernel image only */
#define OTA_UPGRADE_APP 0xD22D /* upgrade app image only */
#endif
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <stdarg.h>
#include "libc.h"
#include "updater.h"
#if !defined __LINUX_HOST__
#include "2ndboot.h"
typedef struct blklist {
struct blklist *next;
unsigned int magic_size;
} blk_head_t;
static blk_head_t freelist_head;
static blk_head_t *freelist_tail = NULL;
static unsigned int heap_free_size;
static unsigned int heap_free_size_min;
#endif
#ifdef AOS_2ND_BOOT_NO_LDS
void *_rec_heap_start;
unsigned int _rec_heap_len;
#endif
/* memory & string operation */
void *ota_memcpy(void *dest, const void *src, unsigned int n)
{
if (NULL == dest || NULL == src)
return NULL;
char *tempDest = (char *)dest;
char *tempSrc = (char *)src;
while (n-- > 0)
*tempDest++ = *tempSrc++;
return dest;
}
void *ota_memset(void *s, int c, unsigned int n)
{
if (NULL == s)
return NULL;
char * tmpS = (char *)s;
while(n-- > 0)
*tmpS++ = c;
return s;
}
unsigned int ota_strlen(char * str)
{
const char *eos = str;
while(*eos++) ;
return (eos - str - 1);
}
char *ota_strcat (char * dst, const char * src)
{
char * cp = dst;
while( *cp )
cp++;
while( cp && src) {
*cp++ = *src++;
}
return dst;
}
int ota_memcmp(const void * buf1, const void * buf2, unsigned int count)
{
if (!count)
return(0);
while ( --count && *(char *)buf1 == *(char *)buf2 ) {
buf1 = (char *)buf1 + 1;
buf2 = (char *)buf2 + 1;
}
return (*((unsigned char *)buf1) - *((unsigned char *)buf2));
}
void *ota_memmove(void *dest, const void *src, unsigned int count)
{
char *tmp;
const char *s;
if (dest <= src) {
tmp = dest;
s = src;
while (count--)
*tmp++ = *s++;
} else {
tmp = dest;
tmp += count;
s = src;
s += count;
while (count--)
*--tmp = *--s;
}
return dest;
}
#if !defined __LINUX_HOST__
char* uitoa_16(unsigned int value, char *str){
char reverse[36] = {0};
char *p = reverse;
*p++ = '\0';
do{
*p++ = "0123456789abcdef"[value%16];
value /= 16;
}while(value != 0);
p--;
while (p >= reverse) {
*str++ = *p--;
}
return str;
}
char* itoa_10(int value, char *str){
char reverse[40] = {0};
char *p = reverse;
int tmp = value;
*p++ = '\0';
if(value < 0) {
tmp = -value;
}
do{
*p++ = "0123456789"[tmp%10];
tmp /= 10;
}while(tmp != 0);
if(value < 0) {
*p++ = '-';
}
p--;
while (p >= reverse){
*str++ = *p--;
}
return str;
}
char* uitoa_10(unsigned int value, char *str){
char reverse[36] = {0};
char *p = reverse;
*p++ = '\0';
do{
*p++ = "0123456789"[value%10];
value /= 10;
}while(value != 0);
p--;
while (p >= reverse) {
*str++ = *p--;
}
return str;
}
int ota_puts(const char *str)
{
uart_send_string(str);
}
int ota_printf(const char *fmt, ...)
{
char buf[256];
char *p = NULL;
char *s = NULL;
int i = 0;
int len = 0;
int waiting_fmt = 0;
va_list args;
memset(buf, 0, sizeof(buf));
va_start(args, fmt);
for (p = buf; *fmt;) {
if (waiting_fmt == 0 && *fmt != '%') {
*p++ = *fmt++;
continue;
}
if (waiting_fmt > 8) {
puts("Non supported format!\r\n");
*p = '\0';
va_end(args);
return puts(buf);
}
fmt++;
switch (*fmt){
case 'd':
itoa_10(va_arg(args, unsigned int),p);
p += strlen(p);
waiting_fmt = 0;
fmt++;
break;
case 'u':
uitoa_10(va_arg(args, unsigned int),p);
p += strlen(p);
waiting_fmt = 0;
fmt++;
break;
case 'x':
case 'p':
uitoa_16(va_arg(args, unsigned int),p);
p += strlen(p);
waiting_fmt = 0;
fmt++;
waiting_fmt = 0;
fmt++;
break;
case 'c':
*p++ = va_arg(args, int);
waiting_fmt = 0;
fmt++;
break;
case 's':
*p = '\0';
s = va_arg(args, char *);
if (!s) {
s = "<NULL>";
len = 7;
} else {
len = (strlen(s) > 128 ? 128 : strlen(s));
}
for (i = 0; i < len; ++i) *p++ = *s++;
waiting_fmt = 0;
fmt++;
break;
default:
waiting_fmt++;
break;
}
}
*p = '\0';
va_end(args);
return puts(buf);
}
/* HEAP implement */
static void heap_init(void)
{
blk_head_t *free_blk = NULL;
if ( XZ_HEAP_BASE%XZ_HEAP_ALIGNMENT != 0
|| XZ_HEAP_SIZE > (~XZ_HEAP_MAGIC)
|| XZ_HEAP_SIZE < XZ_HEAP_BLK_MIN*2 ) {
OTA_LOG_I("err:param invalid!\n");
return;
}
heap_free_size = XZ_HEAP_SIZE;
heap_free_size_min = XZ_HEAP_SIZE;
freelist_head.next = (void *) XZ_HEAP_BASE;
freelist_head.magic_size = 0;
freelist_tail = (void *)(XZ_HEAP_BASE + ALIGN(XZ_HEAP_SIZE, XZ_HEAP_ALIGNMENT) -
XZ_HEAP_BLK_HEAD_SIZE);
freelist_tail->next = NULL;
freelist_tail->magic_size = 0;
/* Only one block when init. */
free_blk = (void *) XZ_HEAP_BASE;
free_blk->next = freelist_tail;
free_blk->magic_size = (unsigned int)freelist_tail - (unsigned int) free_blk;
heap_free_size = free_blk->magic_size;
heap_free_size_min = free_blk->magic_size;
}
static void heap_freeblk_insert(blk_head_t *blk_insert)
{
blk_head_t *blk_before = NULL;
blk_head_t *blk_after = NULL;
/* freelist is ordered by address, find blk_before */
for (blk_before = &freelist_head; blk_before->next < blk_insert; blk_before = blk_before->next) {
if (blk_before == freelist_tail) {
return;
}
}
blk_after = blk_before->next;
if ((char *)blk_before + blk_before->magic_size == (char *)blk_insert) {
blk_before->magic_size += blk_insert->magic_size;
blk_insert = blk_before;
} else {
/* do not merge, just insert new node to freelist */
blk_before->next = blk_insert;
}
/* try to merge blk_insert and blk_after */
if (blk_after != freelist_tail &&
(char *)blk_insert + blk_insert->magic_size == (char *)blk_after) {
blk_insert->magic_size += blk_after->magic_size;
blk_insert->next = blk_after->next;
} else {
/* do not merge, just insert new node to freelist */
blk_insert->next = blk_after;
}
}
void * ota_heap_malloc(unsigned int alloc_size)
{
blk_head_t *blk_alloc = NULL;
blk_head_t *blk_prev = NULL;
blk_head_t *blk_left = NULL;
if (freelist_tail == NULL) {
heap_init();
}
if ((alloc_size == 0) || (alloc_size > heap_free_size)) {
return NULL;
}
alloc_size += XZ_HEAP_BLK_HEAD_SIZE;
alloc_size = ALIGN(alloc_size, XZ_HEAP_ALIGNMENT);
/* find a free block bigger than alloc_size */
blk_prev = &freelist_head;
blk_alloc = freelist_head.next;
while ((blk_alloc->magic_size < alloc_size) && (blk_alloc->next != NULL)) {
blk_prev = blk_alloc;
blk_alloc = blk_alloc->next;
}
if (blk_alloc->next == NULL) {
return NULL;
}
/* delete blk_alloc from freelist */
blk_prev->next = blk_alloc->next;
/* check whether blk_alloc can split */
if (blk_alloc->magic_size - alloc_size > XZ_HEAP_BLK_MIN) {
/* split */
blk_left = (void *)((char *)blk_alloc + alloc_size);
blk_left->magic_size = blk_alloc->magic_size - alloc_size;
blk_alloc->magic_size = alloc_size;
/* Insert the new block into the list of free blocks. */
heap_freeblk_insert(blk_left);
}
/* update statistic */
heap_free_size -= blk_alloc->magic_size;
if (heap_free_size < heap_free_size_min) {
heap_free_size_min = heap_free_size;
}
/* blk belong to APP, magic set */
blk_alloc->magic_size |= XZ_HEAP_MAGIC;
blk_alloc->next = NULL;
/* app used addr is after blk_head_t */
return (void *)((char *)blk_alloc + XZ_HEAP_BLK_HEAD_SIZE);
}
void ota_heap_free(void *pfree)
{
blk_head_t *free_blk;
if (pfree == NULL) {
return;
}
free_blk = (blk_head_t *)((char *)pfree - XZ_HEAP_BLK_HEAD_SIZE);
if (free_blk->next != NULL
||(free_blk->magic_size & XZ_HEAP_MAGIC) != XZ_HEAP_MAGIC) {
OTA_LOG_I("err:block destroyed!\n");
return;
}
/* blk belong to free list, magic clear */
free_blk->magic_size &= ~XZ_HEAP_MAGIC;
/* update statistic */
heap_free_size += free_blk->magic_size;
heap_freeblk_insert(free_blk);
}
#endif
unsigned short update(unsigned short crcIn, unsigned char byte)
{
unsigned int crc = crcIn;
unsigned int in = byte | 0x100;
do {
crc <<= 1;
in <<= 1;
if (in & 0x100) {
++crc;
}
if (crc & 0x10000) {
crc ^= 0x1021;
}
} while (!(in & 0x10000));
return crc & 0xffffu;
}
void crc16_init(CRC16_CTX *inContext)
{
inContext->crc = 0;
}
void crc16_update(CRC16_CTX *inContext, const void *inSrc, long inLen)
{
const unsigned char *src = (const unsigned char *) inSrc;
const unsigned char *srcEnd = src + inLen;
while ( src < srcEnd ) {
inContext->crc = update(inContext->crc, *src++);
}
}
void crc16_final(CRC16_CTX *inContext, unsigned short *outResult)
{
inContext->crc = update(inContext->crc, 0);
inContext->crc = update(inContext->crc, 0);
*outResult = inContext->crc & 0xffffu;
}
unsigned short crc16_computer(void *buf, long len)
{
unsigned short patch_crc = 0;
CRC16_CTX crc_ctx;
crc16_init(&crc_ctx);
crc16_update(&crc_ctx, buf, len);
crc16_final(&crc_ctx, &patch_crc);
return patch_crc;
}
/*-
* Copyright 2003-2005 Colin Percival
* All rights reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted providing that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "nbpatch.h"
#include "libc.h"
#include "updater.h"
#define HEADER_SIZE 48
long offtin(unsigned char *buf) {
long y;
y = buf[7] & 0x7F;
y <<= 8; y += buf[6];
y <<= 8; y += buf[5];
y <<= 8; y += buf[4];
y <<= 8; y += buf[3];
y <<= 8; y += buf[2];
y <<= 8; y += buf[1];
y <<= 8; y += buf[0];
if (buf[7] & 0x80)
y = -y;
return y;
}
long xz_read(xzReadHandler *handler, struct xz_buf *b,struct xz_dec *s, unsigned long patch, unsigned char *buf, int len)
{
long ret = 0;
if (handler == NULL || b == NULL || s == NULL || patch == 0 || buf == NULL || len <= 0) {
return 0;
};
b->out = buf;
b->out_pos = 0;
b->out_size = len;
while(true) {
if (b->in_pos == b->in_size && handler->avail_size > 0) {
size_t readsize = IN_BUF_MAX > handler->avail_size ? handler->avail_size:IN_BUF_MAX;
b->in_size = ota_patch_read(patch, handler->in_buf, handler->read_pos, readsize);
handler->avail_size -= readsize;
handler->read_pos += readsize;
b->in_pos = 0;
b->in = handler->in_buf;
}
ret = xz_dec_run(s, b);
if (ret != XZ_OK && ret != XZ_STREAM_END) {
OTA_LOG_I("xz dec err:%ld \n", ret);
return 0;
}
if (handler->avail_size <= 0 && b->in_pos == b->in_size
&& b->out_pos < len) {
return b->out_pos;
}
if (b->out_pos == len) {
return len;
}
}
return ret;
}
static long ota_nbpatch(const unsigned long old_addr, long old_size, unsigned long patch, long *seek_pos, int num)
{
int ret = 0;
long new_size = 0;
long ctrl_len = 0;
long diff_len = 0;
long extra_len = 0;
unsigned char header[HEADER_SIZE], buf[8];
unsigned char *old_buf = NULL;
unsigned char *new_buf = NULL;
long old_pos = 0;
long new_pos = 0;
long ctrl[3] = {0};
long read_len = 0;
long i = 0;
CRC16_CTX crc_ctx;
unsigned short patch_crc = 0;
unsigned short crc = 0, cal_crc = 0;
struct xz_dec *ctrl_dec = NULL, *diff_dec = NULL, *extra_dec = NULL;
struct xz_buf cb = {0}, db = {0}, eb = {0};
if(!old_addr || !patch || !seek_pos ) {
ret = OTA_NB_INVALID_PARAM;
goto EXIT;
}
long patch_pos = *seek_pos;
old_buf = malloc(SECTOR_SIZE);
if (old_buf == NULL){
ret = OTA_NB_MEMORY_FAIL;
goto EXIT;
}
/*
File format:
0 8 "BSDIFF40"
8 8 X
16 8 Y
24 8 sizeof(newfile)
32 X bzip2(control block)
32+X bzip2(diff block)
32+X+Y bzip2(extra block)
with control block a set of triples (x,y,z) meaning "add x bytes
from oldfile to x bytes from the diff block; copy y bytes from the
extra block; seek forwards in oldfile by z bytes".
*/
ret = ota_patch_read(patch, header, patch_pos, HEADER_SIZE);
if(ret < 0) {
ret = OTA_NB_HEADER_FAIL;
goto EXIT;
}
/* Check for appropriate magic */
if (memcmp(header, "BSDIFF40", 8) != 0) {
ret = OTA_NB_HEADER_FAIL;
goto EXIT;
}
/* Read lengths from header */
ctrl_len = offtin(header + 8);
diff_len = offtin(header + 16);
extra_len = offtin(header + 24);
new_size = offtin(header + 32);
crc = offtin(header + 40);
if ((ctrl_len < 0) || (diff_len < 0) || (new_size < 0)) {
ret = OTA_NB_HEADER_FAIL;
goto EXIT;
}
OTA_LOG_I("nbpatch %d header clen:%ld dlen:%ld elen:%ld crc:0x%02x... \n", num, ctrl_len, diff_len, extra_len, crc);
new_buf = malloc(new_size);
if (new_buf == NULL) {
ret = OTA_NB_MEMORY_FAIL;
goto EXIT;
}
crc16_init(&crc_ctx);
xz_crc32_init();
ctrl_dec = xz_dec_init(XZ_DYNALLOC, DIFF_DICT_SIZE);
if (ctrl_dec == NULL) {
ret = OTA_NB_MEMORY_FAIL;
goto EXIT;
}
diff_dec = xz_dec_init(XZ_DYNALLOC, DIFF_DICT_SIZE);
if (diff_dec == NULL) {
ret = OTA_NB_MEMORY_FAIL;
goto EXIT;
}
extra_dec = xz_dec_init(XZ_DYNALLOC, DIFF_DICT_SIZE);
if (extra_dec == NULL) {
ret = OTA_NB_MEMORY_FAIL;
goto EXIT;
}
xzReadHandler cbhandler;
memset(&cbhandler, 0, sizeof(xzReadHandler));
cbhandler.avail_size = ctrl_len;
cbhandler.read_pos = patch_pos + HEADER_SIZE;
xzReadHandler diffhandler;
memset(&diffhandler, 0, sizeof(xzReadHandler));
diffhandler.avail_size = diff_len;
diffhandler.read_pos = patch_pos + HEADER_SIZE + ctrl_len;
xzReadHandler extrahandler;
memset(&extrahandler, 0, sizeof(xzReadHandler));
extrahandler.avail_size = extra_len;
extrahandler.read_pos = patch_pos + HEADER_SIZE + ctrl_len + diff_len;
while (new_pos < new_size) {
/* Read control data */
for (i = 0; i <= 2; i++) {
read_len = xz_read(&cbhandler, &cb, ctrl_dec, patch, buf, 8);
if (read_len < 8) {
ret = OTA_NB_READ_CTRL_FAIL;
goto EXIT;
}
ctrl[i] = offtin(buf);
/* OTA_LOG_I("ctrlp[i] %ld", ctrl[i]); */
};
/* Sanity-check */
if (new_pos + ctrl[0] > new_size){
ret = OTA_NB_READ_DIFF_FAIL;
goto EXIT;
}
/* Read diff string */
read_len = xz_read(&diffhandler, &db, diff_dec, patch, new_buf + new_pos, ctrl[0]);
if ((read_len < ctrl[0])){
ret = OTA_NB_READ_DIFF_FAIL;
goto EXIT;
}
if(old_pos > old_size || old_pos + ctrl[0] > old_size) {
ret = OTA_NB_READ_OLD_FAIL;
goto EXIT;
}
long cp_size = ctrl[0];
long base_pos = 0;
int idx = 0;
long i;
for (i = 0; i < ctrl[0]; i++) {
if (!(i % SECTOR_SIZE)) {
base_pos = (idx++) * SECTOR_SIZE;
long osize = cp_size > SECTOR_SIZE ? SECTOR_SIZE : cp_size;
memset(old_buf, 0, osize);
ret = ota_patch_read(old_addr, old_buf, old_pos + base_pos, osize);
if(ret < 0) {
ret = OTA_NB_READ_OLD_FAIL;
goto EXIT;
}
cp_size -= osize;
/* OTA_LOG_I("start cp:%ld bp:%ld",cp_size, base_pos); */
}
if (i >= base_pos) {
new_buf[new_pos + i] += old_buf[i - base_pos];
}
}
crc16_update(&crc_ctx, new_buf + new_pos, ctrl[0]);
/* Adjust pointers */
new_pos += ctrl[0];
old_pos += ctrl[0];
/* Sanity-check */
if (new_pos + ctrl[1] > new_size) {
ret = OTA_NB_READ_EXTRA_FAIL;
goto EXIT;
}
/* Read extra string */
read_len = xz_read(&extrahandler, &eb, extra_dec, patch, new_buf + new_pos, ctrl[1]);
if (read_len < ctrl[1]) {
ret = OTA_NB_READ_EXTRA_FAIL;
goto EXIT;
}
crc16_update(&crc_ctx, new_buf + new_pos, ctrl[1]);
/* Adjust pointers */
new_pos += ctrl[1];
old_pos += ctrl[2];
};
crc16_final(&crc_ctx, &patch_crc);
cal_crc = crc16_computer(new_buf, new_size);
if(cal_crc != crc) {
OTA_LOG_I("cal %02x != crc %02x", cal_crc, crc);
ret = OTA_NB_CRC_COMP_FAIL;
goto EXIT;
}
ret = ota_patch_new_data(new_buf, new_size);
if(ret < 0) {
ret = OTA_NB_WRITE_DATA_FAIL;
goto EXIT;
}
patch_pos += HEADER_SIZE;
patch_pos += ctrl_len;
patch_pos += diff_len;
patch_pos += extra_len;
*seek_pos = patch_pos;
EXIT:
OTA_LOG_I("nbpatch %d end cal_crc:0x%02x patch_crc:0x%02x ret:%d\n", num, cal_crc, patch_crc, ret);
if(ctrl_dec){
xz_dec_end(ctrl_dec);
ctrl_dec = NULL;
}
if(diff_dec) {
xz_dec_end(diff_dec);
diff_dec = NULL;
}
if(extra_dec){
xz_dec_end(extra_dec);
extra_dec = NULL;
}
if(old_buf){
free(old_buf);
old_buf = NULL;
}
if(new_buf){
free(new_buf);
new_buf = NULL;
}
return (ret < 0) ? ret: new_size;
}
int ota_nbpatch_main(void) {
int ret = -1;
unsigned long old_addr = 0;
unsigned long patch_addr = 0;
int patch_num = 0;
long patch_off = 0;
long patch_size = 0;
long old_size = 0;
long new_off = 0;
long new_size = 0;
ota_boot_param_t ota_param = {0};
memset(&ota_param, 0, sizeof(ota_boot_param_t));
ret = ota_patch_read_param(&ota_param);
if(ret < 0){
OTA_LOG_I("r param err.\n");
return OTA_NB_INVALID_PARAM;
}
old_addr = ota_param.dst_adr;
patch_addr = ota_param.src_adr;
patch_off = ota_param.patch_off;
patch_size = ota_param.len;
old_size = ota_param.old_size;
new_off = ota_param.new_off;
new_size = ota_param.new_size;
if (!old_addr || !patch_addr || old_size <= 0 || patch_size <= 0 || (ota_param.upg_flag != OTA_UPGRADE_DIFF)) {
OTA_LOG_I("param check err.\n");
return OTA_NB_INVALID_PARAM;
}
OTA_LOG_I("oaddr:0x%lx paddr:0x%lx num:%d noff:%lx nsize:%lx poff:%lx psize:%ld status:%d \n", old_addr, patch_addr, patch_num, new_off, new_size, patch_off, patch_size, ota_param.patch_status);
while (patch_off < patch_size) {
if(!ota_param.patch_status) {
new_size = ota_nbpatch(old_addr, old_size, patch_addr, &patch_off, patch_num);
ota_param.patch_num = ++patch_num;
ota_param.patch_off = patch_off;
ota_param.new_off = new_off;
ota_param.new_size = new_size;
ota_param.patch_status = 1;
if (new_size < 0) {
ret = new_size;
goto EXIT;
}
ota_patch_write_param(&ota_param);
}
ret = ota_load_new_data(new_off, new_size);
if(ret < 0) {
ret = OTA_NB_WRITE_DATA_FAIL;
OTA_LOG_I("err new off:%ld \n", new_size);
goto EXIT;
}
new_off += new_size;
ota_param.patch_status = 0;
ota_param.new_off = new_off;
ota_patch_write_param(&ota_param);
}
EXIT:
if(patch_off > patch_size) {
ota_param.patch_num = 0;
ota_param.patch_off = 0;
ota_param.patch_status = 0;
ota_param.new_off = 0;
ota_param.new_size = 0;
ota_param.upg_flag = 0;
}
ota_patch_write_param(&ota_param);
OTA_LOG_I("nbpatch complete ret: %d new off:%lx size:0x%lx patch_off:0x%lx \n",ret, new_off, new_size, patch_off);
return (ret < 0) ? ret: new_off;
}
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef NBPATCH_H
#define NBPATCH_H
#include "xz.h"
#define NBPATCH_VERSION "3.1.0"
#define IN_BUF_MAX 1024
#define OUT_BUF_MAX 4096
#define DIFF_DICT_SIZE (1 << 14)
#if defined __LINUX_HOST__
#define DIFF_BLOCK_SIZE (0x400000)
#else
#define DIFF_BLOCK_SIZE (0x40000)
#endif
typedef struct xzReadHandler {
unsigned char in_buf [IN_BUF_MAX];
size_t avail_size;
size_t read_pos;
} xzReadHandler;
long xz_read(xzReadHandler *handler, struct xz_buf *b,struct xz_dec *s, unsigned long patch, unsigned char *buf, int len);
int ota_nbpatch_main(void);
int ota_patch_show_percent(int per);
int ota_patch_read(unsigned long src, unsigned char *buffer, unsigned long pos, unsigned long size);
int ota_patch_write(unsigned long dst, unsigned char *buffer, unsigned long pos, unsigned long size);
int ota_patch_new_data(unsigned char *buf, long size);
int ota_load_new_data(unsigned long dst, long size);
unsigned short ota_patch_crc(void *addr, long len);
#endif /* NBPATCH_H_ */
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include "nbpatch.h"
#include "updater.h"
int ota_patch_read(unsigned long src, unsigned char *buffer, unsigned long pos, unsigned long size)
{
unsigned long base = pos;
unsigned long read_size = 0;
int ret = 0;
while(size > 0) {
read_size = size > SECTOR_SIZE ? SECTOR_SIZE : size;
ret = flash_read_data(src + pos, buffer+pos-base, read_size);
if(ret < 0) {
return -1;
}
pos += read_size;
size -= read_size;
}
return pos - base;
}
int ota_patch_write(unsigned long dst, unsigned char *buffer, unsigned long pos, unsigned long size)
{
unsigned long base = pos;
unsigned long write_size = 0;
int ret = 0;
while(size > 0) {
write_size = size > SECTOR_SIZE? SECTOR_SIZE:size;
ret = flash_erase(dst + pos, write_size);
if(ret < 0) {
return ret;
}
ret = flash_write_data(dst + pos, buffer+pos-base, write_size);
if(ret < 0) {
return ret;
}
pos += write_size;
size -= write_size;
}
return pos - base;
}
int ota_patch_new_data(unsigned char *buf, long size)
{
unsigned long pos = 0;
unsigned long bsize = 0;
int ret = 0;
hal_logic_partition_t *ota_info = flash_get_info(HAL_PARTITION_OTA_TEMP);
if(ota_info == NULL) {
printf("ota flash info err.\r\n");
return -1;
}
unsigned int diff_data = ota_info->partition_start_addr + ota_info->partition_length - DIFF_BLOCK_SIZE;
while (size > 0) {
bsize = size > SECTOR_SIZE ? SECTOR_SIZE : size;
ret = flash_erase(diff_data + pos, bsize);
if(ret < 0) {
return ret;
}
ret = flash_write_data(diff_data + pos, buf + pos, bsize);
if(ret < 0) {
return ret;
}
pos += bsize;
size -= bsize;
}
return 0;
}
int ota_load_new_data(unsigned long dst, long size) {
unsigned char tmp[SECTOR_SIZE];
unsigned long pos = 0;
unsigned long bsize = 0;
int ret = 0;
hal_logic_partition_t *app_info = flash_get_info(HAL_PARTITION_APPLICATION);
hal_logic_partition_t *ota_info = flash_get_info(HAL_PARTITION_OTA_TEMP);
if(app_info == NULL || ota_info == NULL) {
printf("ota data & app info err.\r\n");
return -1;
}
unsigned int diff_data = ota_info->partition_start_addr + ota_info->partition_length - DIFF_BLOCK_SIZE;
unsigned int diff_app = app_info->partition_start_addr;
while (size > 0) {
bsize = size > SECTOR_SIZE ? SECTOR_SIZE : size;
memset(tmp, 0, SECTOR_SIZE);
ret = flash_read_data(diff_data + pos, tmp, bsize);
if(ret < 0) {
return ret;
}
ret = flash_erase(diff_app + dst + pos, bsize);
if(ret < 0) {
return ret;
}
ret = flash_write_data(diff_app + dst + pos, tmp, bsize);
if(ret < 0) {
return ret;
}
pos += bsize;
size -= bsize;
}
return ret;
}
int ota_patch_read_param(ota_boot_param_t *ota_param) {
int ret = -1;
unsigned short patch_crc = 0;
if(!ota_param){
return -1;
}
hal_logic_partition_t *par_info = flash_get_info(HAL_PARTITION_PARAMETER_1);
if(par_info == NULL) {
printf("par info err.\r\n");
return -1;
}
ret = flash_read_data(par_info->partition_start_addr,(unsigned char *)ota_param, sizeof(ota_boot_param_t));
if(ret < 0) {
return -1;
}
patch_crc = crc16_computer(ota_param, sizeof(ota_boot_param_t) - sizeof(unsigned short));
if(patch_crc == ota_param->param_crc) {
return 0;
}
OTA_LOG_I("ota crc cal:0x%04x param:0x%04x \n", patch_crc, ota_param->param_crc);
return ret;
}
int ota_patch_write_param(ota_boot_param_t *ota_param) {
int ret = 0;
if(!ota_param){
return -1;
}
hal_logic_partition_t *par_info = flash_get_info(HAL_PARTITION_PARAMETER_1);
if(par_info == NULL) {
printf("par info err.\r\n");
return -1;
}
ota_param->param_crc = crc16_computer(ota_param, sizeof(ota_boot_param_t) - sizeof(unsigned short));
ret = flash_erase(par_info->partition_start_addr, sizeof(ota_boot_param_t));
if(ret < 0) {
return -1;
}
ret = flash_write_data(par_info->partition_start_addr, (unsigned char *) ota_param, sizeof(ota_boot_param_t));
if (ret < 0) {
return -1;
}
return ret;
}
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#include <errno.h>
#include "nbpatch.h"
#include "updater.h"
#include "aos/hal/flash.h"
#define FLASH_SIZE 0x2000000
unsigned char* memory_base = NULL;
int ota_patch_init(char* old_file, char* patch_file){
int ret = 0;
int app_size = 0;
int patch_size = 0;
unsigned char* pos = NULL;
int read_size = 0;
int size = 0;
FILE *old_fd = NULL;
hal_logic_partition_t *ota_info = flash_get_info(HAL_PARTITION_OTA_TEMP);
hal_logic_partition_t *app_info = flash_get_info(HAL_PARTITION_APPLICATION);
if(ota_info == NULL || app_info == NULL) {
OTA_LOG_I("flash info err.\r\n");
return -1;
}
ota_boot_param_t ota_param = {0};
memory_base = malloc (FLASH_SIZE);
if(memory_base == NULL) {
return -1;
}
memset(memory_base, 0xFF, FLASH_SIZE);
old_fd = fopen (old_file, "rb" );
if (old_fd==NULL) {
OTA_LOG_I("open old err:%d\n",errno);
return -1;
}
fseek (old_fd , 0 , SEEK_END);
app_size = ftell(old_fd);
rewind (old_fd);
pos = (unsigned char*)(memory_base + app_info->partition_start_addr);
read_size = 0;
size = app_size;
while(size > 0) {
read_size = size > SECTOR_SIZE ? SECTOR_SIZE : size;
ret = fread(pos, read_size, 1, old_fd);
if(ret < 0 ) {
OTA_LOG_I("read old err:%d ret:%d rsize:%d \n",errno, ret, read_size);
return -1;
}
pos += read_size;
size -= read_size;
}
fclose(old_fd);
old_fd = fopen (patch_file, "rb" );
if (old_fd==NULL) {
OTA_LOG_I("open old err:%d\n",errno);
return -1;
}
fseek (old_fd , 0 , SEEK_END);
patch_size = ftell(old_fd);
rewind (old_fd);
memset(&ota_param, 0x00, sizeof(ota_boot_param_t));
ota_param.dst_adr = app_info->partition_start_addr;
ota_param.src_adr = ota_info->partition_start_addr;
ota_param.len = patch_size;
ota_param.old_size = app_info->partition_length;
ota_param.upg_flag = OTA_UPGRADE_DIFF;
ret = ota_patch_write_param(&ota_param);
if(ret < 0) {
OTA_LOG_I("write parameter err.\n");
return -1;
}
pos = (unsigned char*)(memory_base + ota_info->partition_start_addr);
read_size = 0;
size = app_size;
while(size > 0) {
read_size = size > SECTOR_SIZE ? SECTOR_SIZE:size;
ret = fread(pos, read_size, 1, old_fd);
if(ret < 0) {
OTA_LOG_I("read patch err:%d ret:%d rsize:%d \n",errno, ret, read_size);
return -1;
}
pos += read_size;
size -= read_size;
}
fclose(old_fd);
old_fd = NULL;
OTA_LOG_I("ota patch load app size:0x%x patch size:0x%x success.\n", app_size, patch_size);
return ret;
}
int ota_patch_dump_flash(char* name, int size){
int ret = 0;
FILE* all_fd = NULL;
all_fd = fopen (name, "wb" );
if (all_fd==NULL) {
OTA_LOG_I("open name err:%d\n",errno);
return -1;
}
hal_logic_partition_t *app_info = flash_get_info(HAL_PARTITION_APPLICATION);
if(app_info == NULL) {
OTA_LOG_I("app info err.\r\n");
return -1;
}
OTA_LOG_I("ota patch new file off:%d size:%d.\n", app_info->partition_start_addr, size);
ret = fwrite(memory_base + app_info->partition_start_addr, size, 1, all_fd);
if(ret < 0){
OTA_LOG_I("write name err:%d\n",errno);
return -1;
}
fflush(all_fd);
return ret;
}
int main(int argc, char *argv[])
{
char *old_file = NULL;
char *new_file = NULL;
char *diff_file = NULL;
int ret = 0;
OTA_LOG_I("nbpatch ver:%s start ...\n", NBPATCH_VERSION);
if(argc < 4) {
OTA_LOG_I("Usage: %s old_file new_file diff file [log_file]\r\n", argv[0]);
OTA_LOG_I("Notice: old file and new file less than 8M. \r\n");
return -1;
}
old_file = argv[1];
new_file = argv[2];
diff_file = argv[3];
OTA_LOG_I("ota patch old:%s new:%s diff:%s.\n", old_file, new_file, diff_file);
ret = ota_patch_init(old_file, diff_file);
if(ret < 0){
return -1;
}
ret = ota_nbpatch_main();
if(ret < 0) {
return -1;
}
ret = ota_patch_dump_flash(new_file, ret);
if(ret < 0) {
return -1;
}
OTA_LOG_I("ota patch success. \n");
return 0;
}
/*
* Wrapper for decompressing XZ-compressed kernel, initramfs, and initrd
*
* Author: Lasse Collin <lasse.collin@tukaani.org>
*
* This file has been put into the public domain.
* You can do whatever you want with this file.
*/
#ifndef DECOMPRESS_UNXZ_H
#define DECOMPRESS_UNXZ_H
int 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));
#endif
/*
* XZ decompressor
*
* Authors: Lasse Collin <lasse.collin@tukaani.org>
* Igor Pavlov <http://7-zip.org/>
*
* This file has been put into the public domain.
* You can do whatever you want with this file.
*/
#ifndef XZ_H
#define XZ_H
#include "updater.h"
#ifdef __cplusplus
extern "C" {
#endif
/* In Linux, this is used to make extern functions static when needed. */
#ifndef XZ_EXTERN
# define XZ_EXTERN extern
#endif
/**
* enum xz_mode - Operation mode
*
* @XZ_SINGLE: Single-call mode. This uses less RAM than
* than multi-call modes, because the LZMA2
* dictionary doesn't need to be allocated as
* part of the decoder state. All required data
* structures are allocated at initialization,
* so xz_dec_run() cannot return XZ_MEM_ERROR.
* @XZ_PREALLOC: Multi-call mode with preallocated LZMA2
* dictionary buffer. All data structures are
* allocated at initialization, so xz_dec_run()
* cannot return XZ_MEM_ERROR.
* @XZ_DYNALLOC: Multi-call mode. The LZMA2 dictionary is
* allocated once the required size has been
* parsed from the stream headers. If the
* allocation fails, xz_dec_run() will return
* XZ_MEM_ERROR.
*
* It is possible to enable support only for a subset of the above
* modes at compile time by defining XZ_DEC_SINGLE, XZ_DEC_PREALLOC,
* or XZ_DEC_DYNALLOC. The xz_dec kernel module is always compiled
* with support for all operation modes, but the preboot code may
* be built with fewer features to minimize code size.
*/
enum xz_mode {
XZ_SINGLE,
XZ_PREALLOC,
XZ_DYNALLOC
};
/**
* enum xz_ret - Return codes
* @XZ_OK: Everything is OK so far. More input or more
* output space is required to continue. This
* return code is possible only in multi-call mode
* (XZ_PREALLOC or XZ_DYNALLOC).
* @XZ_STREAM_END: Operation finished successfully.
* @XZ_UNSUPPORTED_CHECK: Integrity check type is not supported. Decoding
* is still possible in multi-call mode by simply
* calling xz_dec_run() again.
* Note that this return value is used only if
* XZ_DEC_ANY_CHECK was defined at build time,
* which is not used in the kernel. Unsupported
* check types return XZ_OPTIONS_ERROR if
* XZ_DEC_ANY_CHECK was not defined at build time.
* @XZ_MEM_ERROR: Allocating memory failed. This return code is
* possible only if the decoder was initialized
* with XZ_DYNALLOC. The amount of memory that was
* tried to be allocated was no more than the
* dict_max argument given to xz_dec_init().
* @XZ_MEMLIMIT_ERROR: A bigger LZMA2 dictionary would be needed than
* allowed by the dict_max argument given to
* xz_dec_init(). This return value is possible
* only in multi-call mode (XZ_PREALLOC or
* XZ_DYNALLOC); the single-call mode (XZ_SINGLE)
* ignores the dict_max argument.
* @XZ_FORMAT_ERROR: File format was not recognized (wrong magic
* bytes).
* @XZ_OPTIONS_ERROR: This implementation doesn't support the requested
* compression options. In the decoder this means
* that the header CRC32 matches, but the header
* itself specifies something that we don't support.
* @XZ_DATA_ERROR: Compressed data is corrupt.
* @XZ_BUF_ERROR: Cannot make any progress. Details are slightly
* different between multi-call and single-call
* mode; more information below.
*
* In multi-call mode, XZ_BUF_ERROR is returned when two consecutive calls
* to XZ code cannot consume any input and cannot produce any new output.
* This happens when there is no new input available, or the output buffer
* is full while at least one output byte is still pending. Assuming your
* code is not buggy, you can get this error only when decoding a compressed
* stream that is truncated or otherwise corrupt.
*
* In single-call mode, XZ_BUF_ERROR is returned only when the output buffer
* is too small or the compressed input is corrupt in a way that makes the
* decoder produce more output than the caller expected. When it is
* (relatively) clear that the compressed input is truncated, XZ_DATA_ERROR
* is used instead of XZ_BUF_ERROR.
*/
enum xz_ret {
XZ_OK,
XZ_STREAM_END,
XZ_UNSUPPORTED_CHECK,
XZ_MEM_ERROR,
XZ_MEMLIMIT_ERROR,
XZ_FORMAT_ERROR,
XZ_OPTIONS_ERROR,
XZ_DATA_ERROR,
XZ_BUF_ERROR
};
/**
* struct xz_buf - Passing input and output buffers to XZ code
* @in: Beginning of the input buffer. This may be NULL if and only
* if in_pos is equal to in_size.
* @in_pos: Current position in the input buffer. This must not exceed
* in_size.
* @in_size: Size of the input buffer
* @out: Beginning of the output buffer. This may be NULL if and only
* if out_pos is equal to out_size.
* @out_pos: Current position in the output buffer. This must not exceed
* out_size.
* @out_size: Size of the output buffer
*
* Only the contents of the output buffer from out[out_pos] onward, and
* the variables in_pos and out_pos are modified by the XZ code.
*/
struct xz_buf {
const uint8_t *in;
size_t in_pos;
size_t in_size;
uint8_t *out;
size_t out_pos;
size_t out_size;
};
/**
* struct xz_dec - Opaque type to hold the XZ decoder state
*/
struct xz_dec;
/**
* xz_dec_init() - Allocate and initialize a XZ decoder state
* @mode: Operation mode
* @dict_max: Maximum size of the LZMA2 dictionary (history buffer) for
* multi-call decoding. This is ignored in single-call mode
* (mode == XZ_SINGLE). LZMA2 dictionary is always 2^n bytes
* or 2^n + 2^(n-1) bytes (the latter sizes are less common
* in practice), so other values for dict_max don't make sense.
* In the kernel, dictionary sizes of 64 KiB, 128 KiB, 256 KiB,
* 512 KiB, and 1 MiB are probably the only reasonable values,
* except for kernel and initramfs images where a bigger
* dictionary can be fine and useful.
*
* Single-call mode (XZ_SINGLE): xz_dec_run() decodes the whole stream at
* once. The caller must provide enough output space or the decoding will
* fail. The output space is used as the dictionary buffer, which is why
* there is no need to allocate the dictionary as part of the decoder's
* internal state.
*
* Because the output buffer is used as the workspace, streams encoded using
* a big dictionary are not a problem in single-call mode. It is enough that
* the output buffer is big enough to hold the actual uncompressed data; it
* can be smaller than the dictionary size stored in the stream headers.
*
* Multi-call mode with preallocated dictionary (XZ_PREALLOC): dict_max bytes
* of memory is preallocated for the LZMA2 dictionary. This way there is no
* risk that xz_dec_run() could run out of memory, since xz_dec_run() will
* never allocate any memory. Instead, if the preallocated dictionary is too
* small for decoding the given input stream, xz_dec_run() will return
* XZ_MEMLIMIT_ERROR. Thus, it is important to know what kind of data will be
* decoded to avoid allocating excessive amount of memory for the dictionary.
*
* Multi-call mode with dynamically allocated dictionary (XZ_DYNALLOC):
* dict_max specifies the maximum allowed dictionary size that xz_dec_run()
* may allocate once it has parsed the dictionary size from the stream
* headers. This way excessive allocations can be avoided while still
* limiting the maximum memory usage to a sane value to prevent running the
* system out of memory when decompressing streams from untrusted sources.
*
* On success, xz_dec_init() returns a pointer to struct xz_dec, which is
* ready to be used with xz_dec_run(). If memory allocation fails,
* xz_dec_init() returns NULL.
*/
XZ_EXTERN struct xz_dec *xz_dec_init(enum xz_mode mode, uint32_t dict_max);
/**
* xz_dec_run() - Run the XZ decoder
* @s: Decoder state allocated using xz_dec_init()
* @b: Input and output buffers
*
* The possible return values depend on build options and operation mode.
* See enum xz_ret for details.
*
* Note that if an error occurs in single-call mode (return value is not
* XZ_STREAM_END), b->in_pos and b->out_pos are not modified and the
* contents of the output buffer from b->out[b->out_pos] onward are
* undefined. This is true even after XZ_BUF_ERROR, because with some filter
* chains, there may be a second pass over the output buffer, and this pass
* cannot be properly done if the output buffer is truncated. Thus, you
* cannot give the single-call decoder a too small buffer and then expect to
* get that amount valid data from the beginning of the stream. You must use
* the multi-call decoder if you don't want to uncompress the whole stream.
*/
XZ_EXTERN enum xz_ret xz_dec_run(struct xz_dec *s, struct xz_buf *b);
/**
* xz_dec_reset() - Reset an already allocated decoder state
* @s: Decoder state allocated using xz_dec_init()
*
* This function can be used to reset the multi-call decoder state without
* freeing and reallocating memory with xz_dec_end() and xz_dec_init().
*
* In single-call mode, xz_dec_reset() is always called in the beginning of
* xz_dec_run(). Thus, explicit call to xz_dec_reset() is useful only in
* multi-call mode.
*/
XZ_EXTERN void xz_dec_reset(struct xz_dec *s);
/**
* xz_dec_end() - Free the memory allocated for the decoder state
* @s: Decoder state allocated using xz_dec_init(). If s is NULL,
* this function does nothing.
*/
XZ_EXTERN void xz_dec_end(struct xz_dec *s);
/*
* Standalone build (userspace build or in-kernel build for boot time use)
* needs a CRC32 implementation. For normal in-kernel use, kernel's own
* CRC32 module is used instead, and users of this module don't need to
* care about the functions below.
*/
#ifndef XZ_INTERNAL_CRC32
# ifdef __KERNEL__
# define XZ_INTERNAL_CRC32 0
# else
# define XZ_INTERNAL_CRC32 1
# endif
#endif
/*
* If CRC64 support has been enabled with XZ_USE_CRC64, a CRC64
* implementation is needed too.
*/
#ifndef XZ_USE_CRC64
# undef XZ_INTERNAL_CRC64
# define XZ_INTERNAL_CRC64 0
#endif
#ifndef XZ_INTERNAL_CRC64
# ifdef __KERNEL__
# error Using CRC64 in the kernel has not been implemented.
# else
# define XZ_INTERNAL_CRC64 1
# endif
#endif
#if XZ_INTERNAL_CRC32
/*
* This must be called before any other xz_* function to initialize
* the CRC32 lookup table.
*/
XZ_EXTERN void xz_crc32_init(void);
/*
* Update CRC32 value using the polynomial from IEEE-802.3. To start a new
* calculation, the third argument must be zero. To continue the calculation,
* the previously returned value is passed as the third argument.
*/
XZ_EXTERN uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc);
#endif
#if XZ_INTERNAL_CRC64
/*
* This must be called before any other xz_* function (except xz_crc32_init())
* to initialize the CRC64 lookup table.
*/
XZ_EXTERN void xz_crc64_init(void);
/*
* Update CRC64 value using the polynomial from ECMA-182. To start a new
* calculation, the third argument must be zero. To continue the calculation,
* the previously returned value is passed as the third argument.
*/
XZ_EXTERN uint64_t xz_crc64(const uint8_t *buf, size_t size, uint64_t crc);
#endif
#ifdef __cplusplus
}
#endif
#endif
/*
* Wrapper for decompressing XZ-compressed kernel, initramfs, and initrd
*
* Author: Lasse Collin <lasse.collin@tukaani.org>
*
* This file has been put into the public domain.
* You can do whatever you want with this file.
*/
/*
* Important notes about in-place decompression
*
* At least on x86, the kernel is decompressed in place: the compressed data
* is placed to the end of the output buffer, and the decompressor overwrites
* most of the compressed data. There must be enough safety margin to
* guarantee that the write position is always behind the read position.
*
* The safety margin for XZ with LZMA2 or BCJ+LZMA2 is calculated below.
* Note that the margin with XZ is bigger than with Deflate (gzip)!
*
* The worst case for in-place decompression is that the beginning of
* the file is compressed extremely well, and the rest of the file is
* uncompressible. Thus, we must look for worst-case expansion when the
* compressor is encoding uncompressible data.
*
* The structure of the .xz file in case of a compresed kernel is as follows.
* Sizes (as bytes) of the fields are in parenthesis.
*
* Stream Header (12)
* Block Header:
* Block Header (8-12)
* Compressed Data (N)
* Block Padding (0-3)
* CRC32 (4)
* Index (8-20)
* Stream Footer (12)
*
* Normally there is exactly one Block, but let's assume that there are
* 2-4 Blocks just in case. Because Stream Header and also Block Header
* of the first Block don't make the decompressor produce any uncompressed
* data, we can ignore them from our calculations. Block Headers of possible
* additional Blocks have to be taken into account still. With these
* assumptions, it is safe to assume that the total header overhead is
* less than 128 bytes.
*
* Compressed Data contains LZMA2 or BCJ+LZMA2 encoded data. Since BCJ
* doesn't change the size of the data, it is enough to calculate the
* safety margin for LZMA2.
*
* LZMA2 stores the data in chunks. Each chunk has a header whose size is
* a maximum of 6 bytes, but to get round 2^n numbers, let's assume that
* the maximum chunk header size is 8 bytes. After the chunk header, there
* may be up to 64 KiB of actual payload in the chunk. Often the payload is
* quite a bit smaller though; to be safe, let's assume that an average
* chunk has only 32 KiB of payload.
*
* The maximum uncompressed size of the payload is 2 MiB. The minimum
* uncompressed size of the payload is in practice never less than the
* payload size itself. The LZMA2 format would allow uncompressed size
* to be less than the payload size, but no sane compressor creates such
* files. LZMA2 supports storing uncompressible data in uncompressed form,
* so there's never a need to create payloads whose uncompressed size is
* smaller than the compressed size.
*
* The assumption, that the uncompressed size of the payload is never
* smaller than the payload itself, is valid only when talking about
* the payload as a whole. It is possible that the payload has parts where
* the decompressor consumes more input than it produces output. Calculating
* the worst case for this would be tricky. Instead of trying to do that,
* let's simply make sure that the decompressor never overwrites any bytes
* of the payload which it is currently reading.
*
* Now we have enough information to calculate the safety margin. We need
* - 128 bytes for the .xz file format headers;
* - 8 bytes per every 32 KiB of uncompressed size (one LZMA2 chunk header
* per chunk, each chunk having average payload size of 32 KiB); and
* - 64 KiB (biggest possible LZMA2 chunk payload size) to make sure that
* the decompressor never overwrites anything from the LZMA2 chunk
* payload it is currently reading.
*
* We get the following formula:
*
* safety_margin = 128 + uncompressed_size * 8 / 32768 + 65536
* = 128 + (uncompressed_size >> 12) + 65536
*
* For comparison, according to arch/x86/boot/compressed/misc.c, the
* equivalent formula for Deflate is this:
*
* safety_margin = 18 + (uncompressed_size >> 12) + 32768
*
* Thus, when updating Deflate-only in-place kernel decompressor to
* support XZ, the fixed overhead has to be increased from 18+32768 bytes
* to 128+65536 bytes.
*/
/*
* STATIC is defined to "static" if we are being built for kernel
* decompression (pre-boot code). <linux/decompress/mm.h> will define
* STATIC to empty if it wasn't already defined. Since we will need to
* know later if we are being used for kernel decompression, we define
* XZ_PREBOOT here.
*/
#ifdef STATIC
# define XZ_PREBOOT
#endif
#ifdef __KERNEL__
# include <linux/decompress/mm.h>
#endif
#define XZ_EXTERN STATIC
#ifndef XZ_PREBOOT
# include <linux/slab.h>
# include <linux/xz.h>
#else
/*
* Use the internal CRC32 code instead of kernel's CRC32 module, which
* is not available in early phase of booting.
*/
#define XZ_INTERNAL_CRC32 1
/*
* For boot time use, we enable only the BCJ filter of the current
* architecture or none if no BCJ filter is available for the architecture.
*/
#ifdef CONFIG_X86
# define XZ_DEC_X86
#endif
#ifdef CONFIG_PPC
# define XZ_DEC_POWERPC
#endif
#ifdef CONFIG_ARM
# define XZ_DEC_ARM
#endif
#ifdef CONFIG_IA64
# define XZ_DEC_IA64
#endif
#ifdef CONFIG_SPARC
# define XZ_DEC_SPARC
#endif
/*
* This will get the basic headers so that memeq() and others
* can be defined.
*/
#include "xz/xz_private.h"
/*
* Replace the normal allocation functions with the versions from
* <linux/decompress/mm.h>. vfree() needs to support vfree(NULL)
* when XZ_DYNALLOC is used, but the pre-boot free() doesn't support it.
* Workaround it here because the other decompressors don't need it.
*/
#undef kmalloc
#undef kfree
#undef vmalloc
#undef vfree
#define kmalloc(size, flags) malloc(size)
#define kfree(ptr) free(ptr)
#define vmalloc(size) malloc(size)
#define vfree(ptr) do { if (ptr != NULL) free(ptr); } while (0)
/*
* FIXME: Not all basic memory functions are provided in architecture-specific
* files (yet). We define our own versions here for now, but this should be
* only a temporary solution.
*
* memeq and memzero are not used much and any remotely sane implementation
* is fast enough. memcpy/memmove speed matters in multi-call mode, but
* the kernel image is decompressed in single-call mode, in which only
* memcpy speed can matter and only if there is a lot of uncompressible data
* (LZMA2 stores uncompressible chunks in uncompressed form). Thus, the
* functions below should just be kept small; it's probably not worth
* optimizing for speed.
*/
#ifndef memeq
static bool memeq(const void *a, const void *b, size_t size)
{
const uint8_t *x = a;
const uint8_t *y = b;
size_t i;
for (i = 0; i < size; ++i)
if (x[i] != y[i])
return false;
return true;
}
#endif
#ifndef memzero
static void memzero(void *buf, size_t size)
{
uint8_t *b = buf;
uint8_t *e = b + size;
while (b != e)
*b++ = '\0';
}
#endif
#ifndef memmove
/* Not static to avoid a conflict with the prototype in the Linux headers. */
void *memmove(void *dest, const void *src, size_t size)
{
uint8_t *d = dest;
const uint8_t *s = src;
size_t i;
if (d < s) {
for (i = 0; i < size; ++i)
d[i] = s[i];
} else if (d > s) {
i = size;
while (i-- > 0)
d[i] = s[i];
}
return dest;
}
#endif
/*
* Since we need memmove anyway, would use it as memcpy too.
* Commented out for now to avoid breaking things.
*/
/*
#ifndef memcpy
# define memcpy memmove
#endif
*/
#include "xz/xz_crc32.c"
#include "xz/xz_dec_stream.c"
#include "xz/xz_dec_lzma2.c"
#include "xz/xz_dec_bcj.c"
#endif /* XZ_PREBOOT */
/* Size of the input and output buffers in multi-call mode */
#define XZ_IOBUF_SIZE 4096
/*
* 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 INIT 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) != (int)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;
}
/*
* This macro is used by architecture-specific files to decompress
* the kernel image.
*/
#define decompress unxz
/*
* Private includes and definitions for userspace use of XZ Embedded
*
* Author: Lasse Collin <lasse.collin@tukaani.org>
*
* This file has been put into the public domain.
* You can do whatever you want with this file.
*/
#ifndef XZ_CONFIG_H
#define XZ_CONFIG_H
/* Uncomment to enable CRC64 support. */
/* #define XZ_USE_CRC64 */
/* Uncomment as needed to enable BCJ filter decoders. */
/* #define XZ_DEC_X86 */
/* #define XZ_DEC_POWERPC */
/* #define XZ_DEC_IA64 */
/* #define XZ_DEC_ARM */
/* #define XZ_DEC_ARMTHUMB */
/* #define XZ_DEC_SPARC */
/*
* MSVC doesn't support modern C but XZ Embedded is mostly C89
* so these are enough.
*/
#ifdef _MSC_VER
typedef unsigned char bool;
# define true 1
# define false 0
# define inline __inline
#else
# include <stdbool.h>
#endif
#include "xz.h"
#define kmalloc(size, flags) malloc(size)
#define kfree(ptr) free(ptr)
#define vmalloc(size) malloc(size)
#define vfree(ptr) free(ptr)
#define memeq(a, b, size) (memcmp(a, b, size) == 0)
#define memzero(buf, size) memset(buf, 0, size)
#ifndef min
# define min(x, y) ((x) < (y) ? (x) : (y))
#endif
#define min_t(type, x, y) min(x, y)
/*
* Some functions have been marked with __always_inline to keep the
* performance reasonable even when the compiler is optimizing for
* small code size. You may be able to save a few bytes by #defining
* __always_inline to plain inline, but don't complain if the code
* becomes slow.
*
* NOTE: System headers on GNU/Linux may #define this macro already,
* so if you want to change it, you need to #undef it first.
*/
#ifndef __always_inline
# ifdef __GNUC__
# define __always_inline \
inline __attribute__((__always_inline__))
# else
# define __always_inline inline
# endif
#endif
/* Inline functions to access unaligned unsigned 32-bit integers */
#ifndef get_unaligned_le32
static inline uint32_t get_unaligned_le32(const uint8_t *buf)
{
return (uint32_t)buf[0]
| ((uint32_t)buf[1] << 8)
| ((uint32_t)buf[2] << 16)
| ((uint32_t)buf[3] << 24);
}
#endif
#ifndef get_unaligned_be32
static inline uint32_t get_unaligned_be32(const uint8_t *buf)
{
return (uint32_t)(buf[0] << 24)
| ((uint32_t)buf[1] << 16)
| ((uint32_t)buf[2] << 8)
| (uint32_t)buf[3];
}
#endif
#ifndef put_unaligned_le32
static inline void put_unaligned_le32(uint32_t val, uint8_t *buf)
{
buf[0] = (uint8_t)val;
buf[1] = (uint8_t)(val >> 8);
buf[2] = (uint8_t)(val >> 16);
buf[3] = (uint8_t)(val >> 24);
}
#endif
#ifndef put_unaligned_be32
static inline void put_unaligned_be32(uint32_t val, uint8_t *buf)
{
buf[0] = (uint8_t)(val >> 24);
buf[1] = (uint8_t)(val >> 16);
buf[2] = (uint8_t)(val >> 8);
buf[3] = (uint8_t)val;
}
#endif
/*
* Use get_unaligned_le32() also for aligned access for simplicity. On
* little endian systems, #define get_le32(ptr) (*(const uint32_t *)(ptr))
* could save a few bytes in code size.
*/
#ifndef get_le32
# define get_le32 get_unaligned_le32
#endif
#endif
/*
* CRC32 using the polynomial from IEEE-802.3
*
* Authors: Lasse Collin <lasse.collin@tukaani.org>
* Igor Pavlov <http://7-zip.org/>
*
* This file has been put into the public domain.
* You can do whatever you want with this file.
*/
/*
* This is not the fastest implementation, but it is pretty compact.
* The fastest versions of xz_crc32() on modern CPUs without hardware
* accelerated CRC instruction are 3-5 times as fast as this version,
* but they are bigger and use more memory for the lookup table.
*/
#include "xz_private.h"
/*
* STATIC_RW_DATA is used in the pre-boot environment on some architectures.
* See <linux/decompress/mm.h> for details.
*/
#ifndef STATIC_RW_DATA
# define STATIC_RW_DATA static
#endif
STATIC_RW_DATA const uint32_t xz_crc32_table[256]= {0x00000000,0x77073096,0xee0e612c,0x990951ba,0x076dc419,0x706af48f,0xe963a535,0x9e6495a3,0x0edb8832,0x79dcb8a4,0xe0d5e91e,0x97d2d988,0x09b64c2b,0x7eb17cbd,0xe7b82d07,0x90bf1d91,0x1db71064,0x6ab020f2,0xf3b97148,0x84be41de,0x1adad47d,0x6ddde4eb,0xf4d4b551,0x83d385c7,0x136c9856,0x646ba8c0,0xfd62f97a,0x8a65c9ec,0x14015c4f,0x63066cd9,0xfa0f3d63,0x8d080df5,0x3b6e20c8,0x4c69105e,0xd56041e4,0xa2677172,0x3c03e4d1,0x4b04d447,0xd20d85fd,0xa50ab56b,0x35b5a8fa,0x42b2986c,0xdbbbc9d6,0xacbcf940,0x32d86ce3,0x45df5c75,0xdcd60dcf,0xabd13d59,0x26d930ac,0x51de003a,0xc8d75180,0xbfd06116,0x21b4f4b5,0x56b3c423,0xcfba9599,0xb8bda50f,0x2802b89e,0x5f058808,0xc60cd9b2,0xb10be924,0x2f6f7c87,0x58684c11,0xc1611dab,0xb6662d3d,0x76dc4190,0x01db7106,0x98d220bc,0xefd5102a,0x71b18589,0x06b6b51f,0x9fbfe4a5,0xe8b8d433,0x7807c9a2,0x0f00f934,0x9609a88e,0xe10e9818,0x7f6a0dbb,0x086d3d2d,0x91646c97,0xe6635c01,0x6b6b51f4,0x1c6c6162,0x856530d8,0xf262004e,0x6c0695ed,0x1b01a57b,0x8208f4c1,0xf50fc457,0x65b0d9c6,0x12b7e950,0x8bbeb8ea,0xfcb9887c,0x62dd1ddf,0x15da2d49,0x8cd37cf3,0xfbd44c65,0x4db26158,0x3ab551ce,0xa3bc0074,0xd4bb30e2,0x4adfa541,0x3dd895d7,0xa4d1c46d,0xd3d6f4fb,0x4369e96a,0x346ed9fc,0xad678846,0xda60b8d0,0x44042d73,0x33031de5,0xaa0a4c5f,0xdd0d7cc9,0x5005713c,0x270241aa,0xbe0b1010,0xc90c2086,0x5768b525,0x206f85b3,0xb966d409,0xce61e49f,0x5edef90e,0x29d9c998,0xb0d09822,0xc7d7a8b4,0x59b33d17,0x2eb40d81,0xb7bd5c3b,0xc0ba6cad,0xedb88320,0x9abfb3b6,0x03b6e20c,0x74b1d29a,0xead54739,0x9dd277af,0x04db2615,0x73dc1683,0xe3630b12,0x94643b84,0x0d6d6a3e,0x7a6a5aa8,0xe40ecf0b,0x9309ff9d,0x0a00ae27,0x7d079eb1,0xf00f9344,0x8708a3d2,0x1e01f268,0x6906c2fe,0xf762575d,0x806567cb,0x196c3671,0x6e6b06e7,0xfed41b76,0x89d32be0,0x10da7a5a,0x67dd4acc,0xf9b9df6f,0x8ebeeff9,0x17b7be43,0x60b08ed5,0xd6d6a3e8,0xa1d1937e,0x38d8c2c4,0x4fdff252,0xd1bb67f1,0xa6bc5767,0x3fb506dd,0x48b2364b,0xd80d2bda,0xaf0a1b4c,0x36034af6,0x41047a60,0xdf60efc3,0xa867df55,0x316e8eef,0x4669be79,0xcb61b38c,0xbc66831a,0x256fd2a0,0x5268e236,0xcc0c7795,0xbb0b4703,0x220216b9,0x5505262f,0xc5ba3bbe,0xb2bd0b28,0x2bb45a92,0x5cb36a04,0xc2d7ffa7,0xb5d0cf31,0x2cd99e8b,0x5bdeae1d,0x9b64c2b0,0xec63f226,0x756aa39c,0x026d930a,0x9c0906a9,0xeb0e363f,0x72076785,0x05005713,0x95bf4a82,0xe2b87a14,0x7bb12bae,0x0cb61b38,0x92d28e9b,0xe5d5be0d,0x7cdcefb7,0x0bdbdf21,0x86d3d2d4,0xf1d4e242,0x68ddb3f8,0x1fda836e,0x81be16cd,0xf6b9265b,0x6fb077e1,0x18b74777,0x88085ae6,0xff0f6a70,0x66063bca,0x11010b5c,0x8f659eff,0xf862ae69,0x616bffd3,0x166ccf45,0xa00ae278,0xd70dd2ee,0x4e048354,0x3903b3c2,0xa7672661,0xd06016f7,0x4969474d,0x3e6e77db,0xaed16a4a,0xd9d65adc,0x40df0b66,0x37d83bf0,0xa9bcae53,0xdebb9ec5,0x47b2cf7f,0x30b5ffe9,0xbdbdf21c,0xcabac28a,0x53b39330,0x24b4a3a6,0xbad03605,0xcdd70693,0x54de5729,0x23d967bf,0xb3667a2e,0xc4614ab8,0x5d681b02,0x2a6f2b94,0xb40bbe37,0xc30c8ea1,0x5a05df1b,0x2d02ef8d};
XZ_EXTERN void xz_crc32_init(void)
{
return;
}
XZ_EXTERN uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc)
{
crc = ~crc;
while (size != 0) {
crc = xz_crc32_table[*buf++ ^ (crc & 0xFF)] ^ (crc >> 8);
--size;
}
return ~crc;
}
/*
* LZMA2 definitions
*
* Authors: Lasse Collin <lasse.collin@tukaani.org>
* Igor Pavlov <http://7-zip.org/>
*
* This file has been put into the public domain.
* You can do whatever you want with this file.
*/
#ifndef XZ_LZMA2_H
#define XZ_LZMA2_H
/* Range coder constants */
#define RC_SHIFT_BITS 8
#define RC_TOP_BITS 24
#define RC_TOP_VALUE (1 << RC_TOP_BITS)
#define RC_BIT_MODEL_TOTAL_BITS 11
#define RC_BIT_MODEL_TOTAL (1 << RC_BIT_MODEL_TOTAL_BITS)
#define RC_MOVE_BITS 5
/*
* Maximum number of position states. A position state is the lowest pb
* number of bits of the current uncompressed offset. In some places there
* are different sets of probabilities for different position states.
*/
#define POS_STATES_MAX (1 << 4)
/*
* This enum is used to track which LZMA symbols have occurred most recently
* and in which order. This information is used to predict the next symbol.
*
* Symbols:
* - Literal: One 8-bit byte
* - Match: Repeat a chunk of data at some distance
* - Long repeat: Multi-byte match at a recently seen distance
* - Short repeat: One-byte repeat at a recently seen distance
*
* The symbol names are in from STATE_oldest_older_previous. REP means
* either short or long repeated match, and NONLIT means any non-literal.
*/
enum lzma_state {
STATE_LIT_LIT,
STATE_MATCH_LIT_LIT,
STATE_REP_LIT_LIT,
STATE_SHORTREP_LIT_LIT,
STATE_MATCH_LIT,
STATE_REP_LIT,
STATE_SHORTREP_LIT,
STATE_LIT_MATCH,
STATE_LIT_LONGREP,
STATE_LIT_SHORTREP,
STATE_NONLIT_MATCH,
STATE_NONLIT_REP
};
/* Total number of states */
#define STATES 12
/* The lowest 7 states indicate that the previous state was a literal. */
#define LIT_STATES 7
/* Indicate that the latest symbol was a literal. */
static inline void lzma_state_literal(enum lzma_state *state)
{
if (*state <= STATE_SHORTREP_LIT_LIT)
*state = STATE_LIT_LIT;
else if (*state <= STATE_LIT_SHORTREP)
*state -= 3;
else
*state -= 6;
}
/* Indicate that the latest symbol was a match. */
static inline void lzma_state_match(enum lzma_state *state)
{
*state = *state < LIT_STATES ? STATE_LIT_MATCH : STATE_NONLIT_MATCH;
}
/* Indicate that the latest state was a long repeated match. */
static inline void lzma_state_long_rep(enum lzma_state *state)
{
*state = *state < LIT_STATES ? STATE_LIT_LONGREP : STATE_NONLIT_REP;
}
/* Indicate that the latest symbol was a short match. */
static inline void lzma_state_short_rep(enum lzma_state *state)
{
*state = *state < LIT_STATES ? STATE_LIT_SHORTREP : STATE_NONLIT_REP;
}
/* Test if the previous symbol was a literal. */
static inline bool lzma_state_is_literal(enum lzma_state state)
{
return state < LIT_STATES;
}
/* Each literal coder is divided in three sections:
* - 0x001-0x0FF: Without match byte
* - 0x101-0x1FF: With match byte; match bit is 0
* - 0x201-0x2FF: With match byte; match bit is 1
*
* Match byte is used when the previous LZMA symbol was something else than
* a literal (that is, it was some kind of match).
*/
#define LITERAL_CODER_SIZE 0x300
/* Maximum number of literal coders */
#define LITERAL_CODERS_MAX (1 << 4)
/* Minimum length of a match is two bytes. */
#define MATCH_LEN_MIN 2
/* Match length is encoded with 4, 5, or 10 bits.
*
* Length Bits
* 2-9 4 = Choice=0 + 3 bits
* 10-17 5 = Choice=1 + Choice2=0 + 3 bits
* 18-273 10 = Choice=1 + Choice2=1 + 8 bits
*/
#define LEN_LOW_BITS 3
#define LEN_LOW_SYMBOLS (1 << LEN_LOW_BITS)
#define LEN_MID_BITS 3
#define LEN_MID_SYMBOLS (1 << LEN_MID_BITS)
#define LEN_HIGH_BITS 8
#define LEN_HIGH_SYMBOLS (1 << LEN_HIGH_BITS)
#define LEN_SYMBOLS (LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS + LEN_HIGH_SYMBOLS)
/*
* Maximum length of a match is 273 which is a result of the encoding
* described above.
*/
#define MATCH_LEN_MAX (MATCH_LEN_MIN + LEN_SYMBOLS - 1)
/*
* Different sets of probabilities are used for match distances that have
* very short match length: Lengths of 2, 3, and 4 bytes have a separate
* set of probabilities for each length. The matches with longer length
* use a shared set of probabilities.
*/
#define DIST_STATES 4
/*
* Get the index of the appropriate probability array for decoding
* the distance slot.
*/
static inline uint32_t lzma_get_dist_state(uint32_t len)
{
return len < DIST_STATES + MATCH_LEN_MIN
? len - MATCH_LEN_MIN : DIST_STATES - 1;
}
/*
* The highest two bits of a 32-bit match distance are encoded using six bits.
* This six-bit value is called a distance slot. This way encoding a 32-bit
* value takes 6-36 bits, larger values taking more bits.
*/
#define DIST_SLOT_BITS 6
#define DIST_SLOTS (1 << DIST_SLOT_BITS)
/* Match distances up to 127 are fully encoded using probabilities. Since
* the highest two bits (distance slot) are always encoded using six bits,
* the distances 0-3 don't need any additional bits to encode, since the
* distance slot itself is the same as the actual distance. DIST_MODEL_START
* indicates the first distance slot where at least one additional bit is
* needed.
*/
#define DIST_MODEL_START 4
/*
* Match distances greater than 127 are encoded in three pieces:
* - distance slot: the highest two bits
* - direct bits: 2-26 bits below the highest two bits
* - alignment bits: four lowest bits
*
* Direct bits don't use any probabilities.
*
* The distance slot value of 14 is for distances 128-191.
*/
#define DIST_MODEL_END 14
/* Distance slots that indicate a distance <= 127. */
#define FULL_DISTANCES_BITS (DIST_MODEL_END / 2)
#define FULL_DISTANCES (1 << FULL_DISTANCES_BITS)
/*
* For match distances greater than 127, only the highest two bits and the
* lowest four bits (alignment) is encoded using probabilities.
*/
#define ALIGN_BITS 4
#define ALIGN_SIZE (1 << ALIGN_BITS)
#define ALIGN_MASK (ALIGN_SIZE - 1)
/* Total number of all probability variables */
#define PROBS_TOTAL (1846 + LITERAL_CODERS_MAX * LITERAL_CODER_SIZE)
/*
* LZMA remembers the four most recent match distances. Reusing these
* distances tends to take less space than re-encoding the actual
* distance value.
*/
#define REPS 4
#endif
/*
* Private includes and definitions
*
* Author: Lasse Collin <lasse.collin@tukaani.org>
*
* This file has been put into the public domain.
* You can do whatever you want with this file.
*/
#ifndef XZ_PRIVATE_H
#define XZ_PRIVATE_H
#ifdef __KERNEL__
# include <linux/xz.h>
# include <linux/kernel.h>
# include <asm/unaligned.h>
/* XZ_PREBOOT may be defined only via decompress_unxz.c. */
# ifndef XZ_PREBOOT
# include <linux/slab.h>
# include <linux/vmalloc.h>
# include <linux/string.h>
# ifdef CONFIG_XZ_DEC_X86
# define XZ_DEC_X86
# endif
# ifdef CONFIG_XZ_DEC_POWERPC
# define XZ_DEC_POWERPC
# endif
# ifdef CONFIG_XZ_DEC_IA64
# define XZ_DEC_IA64
# endif
# ifdef CONFIG_XZ_DEC_ARM
# define XZ_DEC_ARM
# endif
# ifdef CONFIG_XZ_DEC_ARMTHUMB
# define XZ_DEC_ARMTHUMB
# endif
# ifdef CONFIG_XZ_DEC_SPARC
# define XZ_DEC_SPARC
# endif
# define memeq(a, b, size) (memcmp(a, b, size) == 0)
# define memzero(buf, size) memset(buf, 0, size)
# endif
# define get_le32(p) le32_to_cpup((const uint32_t *)(p))
#else
/*
* For userspace builds, use a separate header to define the required
* macros and functions. This makes it easier to adapt the code into
* different environments and avoids clutter in the Linux kernel tree.
*/
# include "xz_config.h"
#endif
/* If no specific decoding mode is requested, enable support for all modes. */
#if !defined(XZ_DEC_SINGLE) && !defined(XZ_DEC_PREALLOC) \
&& !defined(XZ_DEC_DYNALLOC)
# define XZ_DEC_SINGLE
# define XZ_DEC_PREALLOC
# define XZ_DEC_DYNALLOC
#endif
/*
* The DEC_IS_foo(mode) macros are used in "if" statements. If only some
* of the supported modes are enabled, these macros will evaluate to true or
* false at compile time and thus allow the compiler to omit unneeded code.
*/
#ifdef XZ_DEC_SINGLE
# define DEC_IS_SINGLE(mode) ((mode) == XZ_SINGLE)
#else
# define DEC_IS_SINGLE(mode) (false)
#endif
#ifdef XZ_DEC_PREALLOC
# define DEC_IS_PREALLOC(mode) ((mode) == XZ_PREALLOC)
#else
# define DEC_IS_PREALLOC(mode) (false)
#endif
#ifdef XZ_DEC_DYNALLOC
# define DEC_IS_DYNALLOC(mode) ((mode) == XZ_DYNALLOC)
#else
# define DEC_IS_DYNALLOC(mode) (false)
#endif
#if !defined(XZ_DEC_SINGLE)
# define DEC_IS_MULTI(mode) (true)
#elif defined(XZ_DEC_PREALLOC) || defined(XZ_DEC_DYNALLOC)
# define DEC_IS_MULTI(mode) ((mode) != XZ_SINGLE)
#else
# define DEC_IS_MULTI(mode) (false)
#endif
/*
* If any of the BCJ filter decoders are wanted, define XZ_DEC_BCJ.
* XZ_DEC_BCJ is used to enable generic support for BCJ decoders.
*/
#ifndef XZ_DEC_BCJ
# if defined(XZ_DEC_X86) || defined(XZ_DEC_POWERPC) \
|| defined(XZ_DEC_IA64) || defined(XZ_DEC_ARM) \
|| defined(XZ_DEC_ARM) || defined(XZ_DEC_ARMTHUMB) \
|| defined(XZ_DEC_SPARC)
# define XZ_DEC_BCJ
# endif
#endif
/*
* Allocate memory for LZMA2 decoder. xz_dec_lzma2_reset() must be used
* before calling xz_dec_lzma2_run().
*/
XZ_EXTERN struct xz_dec_lzma2 *xz_dec_lzma2_create(enum xz_mode mode,
uint32_t dict_max);
/*
* Decode the LZMA2 properties (one byte) and reset the decoder. Return
* XZ_OK on success, XZ_MEMLIMIT_ERROR if the preallocated dictionary is not
* big enough, and XZ_OPTIONS_ERROR if props indicates something that this
* decoder doesn't support.
*/
XZ_EXTERN enum xz_ret xz_dec_lzma2_reset(struct xz_dec_lzma2 *s,
uint8_t props);
/* Decode raw LZMA2 stream from b->in to b->out. */
XZ_EXTERN enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s,
struct xz_buf *b);
/* Free the memory allocated for the LZMA2 decoder. */
XZ_EXTERN void xz_dec_lzma2_end(struct xz_dec_lzma2 *s);
#ifdef XZ_DEC_BCJ
/*
* Allocate memory for BCJ decoders. xz_dec_bcj_reset() must be used before
* calling xz_dec_bcj_run().
*/
XZ_EXTERN struct xz_dec_bcj *xz_dec_bcj_create(bool single_call);
/*
* Decode the Filter ID of a BCJ filter. This implementation doesn't
* support custom start offsets, so no decoding of Filter Properties
* is needed. Returns XZ_OK if the given Filter ID is supported.
* Otherwise XZ_OPTIONS_ERROR is returned.
*/
XZ_EXTERN enum xz_ret xz_dec_bcj_reset(struct xz_dec_bcj *s, uint8_t id);
/*
* Decode raw BCJ + LZMA2 stream. This must be used only if there actually is
* a BCJ filter in the chain. If the chain has only LZMA2, xz_dec_lzma2_run()
* must be called directly.
*/
XZ_EXTERN enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s,
struct xz_dec_lzma2 *lzma2,
struct xz_buf *b);
/* Free the memory allocated for the BCJ filters. */
#define xz_dec_bcj_end(s) kfree(s)
#endif
#endif
/*
* Definitions for handling the .xz file format
*
* Author: Lasse Collin <lasse.collin@tukaani.org>
*
* This file has been put into the public domain.
* You can do whatever you want with this file.
*/
#ifndef XZ_STREAM_H
#define XZ_STREAM_H
#if defined(__KERNEL__) && !XZ_INTERNAL_CRC32
# include <linux/crc32.h>
# undef crc32
# define xz_crc32(buf, size, crc) \
(~crc32_le(~(uint32_t)(crc), buf, size))
#endif
/*
* See the .xz file format specification at
* http://tukaani.org/xz/xz-file-format.txt
* to understand the container format.
*/
#define STREAM_HEADER_SIZE 12
#define HEADER_MAGIC "\3757zXZ"
#define HEADER_MAGIC_SIZE 6
#define FOOTER_MAGIC "YZ"
#define FOOTER_MAGIC_SIZE 2
/*
* Variable-length integer can hold a 63-bit unsigned integer or a special
* value indicating that the value is unknown.
*
* Experimental: vli_type can be defined to uint32_t to save a few bytes
* in code size (no effect on speed). Doing so limits the uncompressed and
* compressed size of the file to less than 256 MiB and may also weaken
* error detection slightly.
*/
typedef uint64_t vli_type;
#define VLI_MAX ((vli_type)-1 / 2)
#define VLI_UNKNOWN ((vli_type)-1)
/* Maximum encoded size of a VLI */
#define VLI_BYTES_MAX (sizeof(vli_type) * 8 / 7)
/* Integrity Check types */
enum xz_check {
XZ_CHECK_NONE = 0,
XZ_CHECK_CRC32 = 1,
XZ_CHECK_CRC64 = 4,
XZ_CHECK_SHA256 = 10
};
/* Maximum possible Check ID */
#define XZ_CHECK_MAX 15
#endif
此差异已折叠。
此差异已折叠。
......@@ -53,12 +53,6 @@ build_config:
- tools
internal_include:
- hal
- 2ndboot/include
- 2ndboot/updater/include
- 2ndboot/updater/xz/linux/lib/xz
- 2ndboot/updater/xz/linux/include/linux
- tools/xz/include
libs:
......
此差异已折叠。
/*
* Private includes and definitions for userspace use of XZ Embedded
*
* Author: Lasse Collin <lasse.collin@tukaani.org>
*
* This file has been put into the public domain.
* You can do whatever you want with this file.
*/
#ifndef XZ_CONFIG_H
#define XZ_CONFIG_H
/* Uncomment to enable CRC64 support. */
/* #define XZ_USE_CRC64 */
/* Uncomment as needed to enable BCJ filter decoders. */
/* #define XZ_DEC_X86 */
/* #define XZ_DEC_POWERPC */
/* #define XZ_DEC_IA64 */
/* #define XZ_DEC_ARM */
/* #define XZ_DEC_ARMTHUMB */
/* #define XZ_DEC_SPARC */
/*
* MSVC doesn't support modern C but XZ Embedded is mostly C89
* so these are enough.
*/
#ifdef _MSC_VER
typedef unsigned char bool;
#define true 1
#define false 0
#define inline __inline
#else
#include <stdbool.h>
#endif
#include "xz.h"
#define kmalloc(size, flags) ota_malloc(size)
#define kfree(ptr) ota_free(ptr)
#define vmalloc(size) ota_malloc(size)
#define vfree(ptr) ota_free(ptr)
#define memeq(a, b, size) (memcmp(a, b, size) == 0)
#define memzero(buf, size) memset(buf, 0, size)
#ifndef min
#define min(x, y) ((x) < (y) ? (x) : (y))
#endif
#define min_t(type, x, y) min(x, y)
/*
* Some functions have been marked with __always_inline to keep the
* performance reasonable even when the compiler is optimizing for
* small code size. You may be able to save a few bytes by #defining
* __always_inline to plain inline, but don't complain if the code
* becomes slow.
*
* NOTE: System headers on GNU/Linux may #define this macro already,
* so if you want to change it, you need to #undef it first.
*/
#ifndef __always_inline
#ifdef __GNUC__
#define __always_inline \
inline __attribute__((__always_inline__))
#else
#define __always_inline inline
#endif
#endif
/* Inline functions to access unaligned unsigned 32-bit integers */
#ifndef get_unaligned_le32
static inline uint32_t get_unaligned_le32(const uint8_t *buf)
{
return (uint32_t)buf[0]
| ((uint32_t)buf[1] << 8)
| ((uint32_t)buf[2] << 16)
| ((uint32_t)buf[3] << 24);
}
#endif
#ifndef get_unaligned_be32
static inline uint32_t get_unaligned_be32(const uint8_t *buf)
{
return (uint32_t)(buf[0] << 24)
| ((uint32_t)buf[1] << 16)
| ((uint32_t)buf[2] << 8)
| (uint32_t)buf[3];
}
#endif
#ifndef put_unaligned_le32
static inline void put_unaligned_le32(uint32_t val, uint8_t *buf)
{
buf[0] = (uint8_t)val;
buf[1] = (uint8_t)(val >> 8);
buf[2] = (uint8_t)(val >> 16);
buf[3] = (uint8_t)(val >> 24);
}
#endif
#ifndef put_unaligned_be32
static inline void put_unaligned_be32(uint32_t val, uint8_t *buf)
{
buf[0] = (uint8_t)(val >> 24);
buf[1] = (uint8_t)(val >> 16);
buf[2] = (uint8_t)(val >> 8);
buf[3] = (uint8_t)val;
}
#endif
/*
* Use get_unaligned_le32() also for aligned access for simplicity. On
* little endian systems, #define get_le32(ptr) (*(const uint32_t *)(ptr))
* could save a few bytes in code size.
*/
#ifndef get_le32
#define get_le32 get_unaligned_le32
#endif
#endif
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef XZ_EXPORT_H
#define XZ_EXPORT_H
#include "aos/hal/flash.h"
#define XZ_SUCCESS 0
#define XZ_INPURT_PARAM_ERR -1
#define XZ_MALLOC_FAILED -2
#define XZ_READ_FLASH_FAILED -3
#define XZ_WRITE_FLASH_FAILED -4
#define XZ_ERASE_FLASH_FAILED -5
#define XZ_CRC_ERROR -6
#define XZ_UNPROCESS_FAILED -7
#define XZ_VERIFY_FAILED -8
#define XZ_FILE_IDENTIFY_FAILED -9
int xz_file_uncompress(hal_partition_t des_partition, hal_partition_t src_partition, unsigned int xz_size, unsigned short xz_crc16);
#endif /*XZ_EXPORT_H */
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef XZ_HAL_PLAT_H
#define XZ_HAL_PLAT_H
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "aos/hal/flash.h"
#define SECTOR_SIZE 0x1000 /* flash sector size */
#ifndef XZ_BUF_SIZE
#define XZ_BUF_SIZE 2048
#endif
/* flash APIs */
int xz_flash_erase(hal_partition_t flash_partition, unsigned int offset, unsigned int len);
int xz_flash_read_data(hal_partition_t flash_partition, unsigned int offset, unsigned char *buf, unsigned int len);
int xz_flash_write_data(hal_partition_t flash_partition, unsigned int offset, unsigned char *buf, unsigned int len);
#endif /*XZ_HAL_PLAT_H */
此差异已折叠。
此差异已折叠。
/*
* Definitions for handling the .xz file format
*
* Author: Lasse Collin <lasse.collin@tukaani.org>
*
* This file has been put into the public domain.
* You can do whatever you want with this file.
*/
#ifndef XZ_STREAM_H
#define XZ_STREAM_H
#if defined(__KERNEL__) && !XZ_INTERNAL_CRC32
#include <linux/crc32.h>
#undef crc32
#define xz_crc32(buf, size, crc) \
(~crc32_le(~(uint32_t)(crc), buf, size))
#endif
/*
* See the .xz file format specification at
* http://tukaani.org/xz/xz-file-format.txt
* to understand the container format.
*/
#define STREAM_HEADER_SIZE 12
#define HEADER_MAGIC "\3757zXZ"
#define HEADER_MAGIC_SIZE 6
#define FOOTER_MAGIC "YZ"
#define FOOTER_MAGIC_SIZE 2
/*
* Variable-length integer can hold a 63-bit unsigned integer or a special
* value indicating that the value is unknown.
*
* Experimental: vli_type can be defined to uint32_t to save a few bytes
* in code size (no effect on speed). Doing so limits the uncompressed and
* compressed size of the file to less than 256 MiB and may also weaken
* error detection slightly.
*/
typedef uint64_t vli_type;
#define VLI_MAX ((vli_type)-1 / 2)
#define VLI_UNKNOWN ((vli_type)-1)
/* Maximum encoded size of a VLI */
#define VLI_BYTES_MAX (sizeof(vli_type) * 8 / 7)
/* Integrity Check types */
enum xz_check {
XZ_CHECK_NONE = 0,
XZ_CHECK_CRC32 = 1,
XZ_CHECK_CRC64 = 4,
XZ_CHECK_SHA256 = 10
};
/* Maximum possible Check ID */
#define XZ_CHECK_MAX 15
#endif
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册