CFE(UBOOT)集成bzip2测试

用过bcm解决方案都知道,CFE是bcm的uboot,其中用的是zlib的解压方式进行解压

但zlib的压缩比不如bzip2,因而考虑集成bzip2进去提高压缩比,以缩减flash的使用

 

看了下cfe的代码,虽然是用c写的,但其对象思想非常明显,可参考我之前的文章或看看dfb的代码风格

就是那种用c写对象代码的水平,所以集成bzip2只需要添加东西,不需要修改之前集成zlib的任何东西,包括上层调用

 

/*  *********************************************************************
    *  File system list
    ********************************************************************* */

static const fileio_dispatch_t * const cfe_filesystems[] = {
    &raw_fileops,
#if CFG_NETWORK
    &tftp_fileops,
#endif
#if CFG_FATFS
    &fatfs_fileops,
    &pfatfs_fileops,
#endif
#if CFG_ZLIB
    &zlibfs_fileops,
#endif
#if CFG_BZIP
    &bzipfs_fileops,
#endif
    NULL
};

 

这里zlibfs_fileops就是file system对象了,这里只需要增加bzipfs_fileops,然后按照其规则编写对应的接口便可

 

#if CFG_BZIP

#include "lib_types.h"
#include "lib_string.h"
#include "lib_queue.h"
#include "lib_malloc.h"
#include "lib_printf.h"

#include "cfe_error.h"
#include "cfe_fileops.h"
#include "cfe_iocb.h"
#include "cfe_devfuncs.h"
#include "cfe_console.h"

#include "cfe.h"

#include "bzlib.h"
#include "bsp_config.h"


#define BZIPFS_BUFSIZE (48 * 1024)
#define BZIPFS_OUTBUFSIZE (4 * 1024)
#define TEST_MEM_BUFFER 0x8c800000


typedef struct bzipfs_fsctx_s {
    void *bzipfsctx_subfsctx;
    const fileio_dispatch_t *bzipfsctx_subops;
    int bzipfsctx_refcnt;
} bzipfs_fsctx_t;

typedef struct bzipfs_file_s
{
    bz_stream bzipStream;
    void* subfile;
    int bzipfs_fileoffset;
    bzipfs_fsctx_t* bzip_fsctx;
    uint8_t* bzip_inbuf;
    uint8_t* bzip_outbuf;
    uint8_t* bzipfs_outptr;
    int bzipfs_eofseen;
    int bzipfs_outlen;
}bzipfs_file_t;


/*  *********************************************************************
    *  Prototypes
    ********************************************************************* */
static void* bzcalloc(void* opaque,int items, int size);
static void bzcfree(void* opaque,void* ptr);


static int bzipfs_fileop_init(void **fsctx,void *ctx);
static int bzipfs_fileop_open(void **ref,void *fsctx,char *filename,int mode);
static int bzipfs_fileop_read(void *ref,uint8_t *buf,int len);
static int bzipfs_fileop_write(void *ref,uint8_t *buf,int len);
static int bzipfs_fileop_seek(void *ref,int offset,int how);
static void bzipfs_fileop_close(void *ref);
static void bzipfs_fileop_uninit(void *fsctx);

const fileio_dispatch_t bzipfs_fileops = {
    "b",
    0,
    bzipfs_fileop_init,
    bzipfs_fileop_open,
    bzipfs_fileop_read,
    bzipfs_fileop_write,
    bzipfs_fileop_seek,
    bzipfs_fileop_close,
    bzipfs_fileop_uninit
};


/*
 * Utility functions needed by the BZIP routines
 */
static int s_nBufferOffset = 0;
 
static void* bzcalloc(void* opaque,int items, int size)
{
    void *ptr;

    ptr = (uint8_t *)PHYS_TO_K0(TEST_MEM_BUFFER + s_nBufferOffset);
    s_nBufferOffset = s_nBufferOffset + items * size;
    xprintf("Offset is: %d\n", s_nBufferOffset);

    if (ptr) lib_memset(ptr,0,items*size);
    return ptr;
}

static void bzcfree(void* opaque,void* ptr)
{
    return;
}


static int bzipfs_fileop_init(void **newfsctx,void *curfsvoid)
{
    bzipfs_fsctx_t *fsctx;
    fileio_ctx_t *curfsctx = (fileio_ctx_t *) curfsvoid;

    *newfsctx = NULL;

    fsctx = KMALLOC(sizeof(bzipfs_fsctx_t),0);
    if (!fsctx) {
	return CFE_ERR_NOMEM;
	}

    fsctx->bzipfsctx_refcnt = 0;
    fsctx->bzipfsctx_subops  =  curfsctx->ops;
    fsctx->bzipfsctx_subfsctx = curfsctx->fsctx;

    *newfsctx = fsctx;

    return 0;
}

static int bzipfs_fileop_open(void **ref,void *fsctx_arg,char *filename,int mode)
{
    bzipfs_file_t* file = NULL;
    bzipfs_fsctx_t *fsctx;
    int err;
    /* static char pInbuf[BZIPFS_BUFSIZE];*/
    
    if (mode != FILE_MODE_READ) return CFE_ERR_UNSUPPORTED;

    fsctx = (bzipfs_fsctx_t *) fsctx_arg;


    file = KMALLOC(sizeof(bzipfs_file_t), 0);
    err = BDOPEN(fsctx->bzipfsctx_subops,&(file->subfile),
		 fsctx->bzipfsctx_subfsctx,filename);

    if (err != 0) {
       KFREE(file);
	return err;
	}
    
    file->bzip_fsctx = fsctx;
    file->bzip_inbuf = (uint8_t *)PHYS_TO_K0(TEST_MEM_BUFFER);
    s_nBufferOffset += BZIPFS_BUFSIZE;
    file->bzip_outbuf = KMALLOC(BZIPFS_OUTBUFSIZE, 0);
    file->bzipfs_fileoffset = 0;
    file->bzipStream.bzalloc = bzcalloc;
    file->bzipStream.bzfree = bzcfree;
    file->bzipStream.opaque = NULL;

    err = BZ2_bzDecompressInit(&(file->bzipStream), 0, 0);

    file->bzipStream.next_in = file->bzip_inbuf;
    file->bzipStream.next_out = file->bzip_outbuf;
    file->bzipStream.avail_out = 0;
    file->bzipStream.avail_in = 0;
    file->bzipfs_outlen = 0;	
    file->bzipfs_outptr = file->bzip_outbuf;
    file->bzipfs_eofseen = 0;

    fsctx->bzipfsctx_refcnt++;
    
    *ref = file;
    return 0;
}

static int bzipfs_fileop_read(void *ref,uint8_t *buf,int len)
{
    bzipfs_file_t *file = (bzipfs_file_t *) ref;
    int res = 0;
    int err;
    int amtcopy;
    int ttlcopy = 0;
    int nReturn = 0;	

    if (len == 0) return 0;

    while (len) {

	/* Figure the amount to copy.  This is the min of what we
	   have left to do and what is available. */
	amtcopy = len;
	if (amtcopy > file->bzipStream.avail_out) {
	    amtcopy = file->bzipStream.avail_out;
	    }

	/* Copy the data. */

	if (buf && (amtcopy != 0)) {
	    memcpy(buf,file->bzipfs_outptr,amtcopy);
	    buf += amtcopy;
	    }

       file->bzipStream.avail_out = BZIPFS_OUTBUFSIZE;

	/* Update the pointers. */    
	file->bzipfs_outptr += amtcopy;
	file->bzipfs_outlen -= amtcopy;
	len -= amtcopy;
	ttlcopy += amtcopy;

	/* If we've eaten all of the output, reset and call inflate
	   again. */

	if (file->bzipfs_outlen == 0) {
	    /* If no input data to decompress, get some more if we can. */
	    if (file->bzipfs_eofseen) break;
	    if (file->bzipStream.avail_in == 0) 
		{
		res = BDREAD(file->bzip_fsctx->bzipfsctx_subops,
			     file->subfile,
			     file->bzip_inbuf,		   
			     BZIPFS_BUFSIZE);
		/* If at EOF or error, get out. */
		if (res <= 0) break;
		file->bzipStream.next_in = file->bzip_inbuf;
		file->bzipStream.avail_in = res;
		}

	    /* inflate the input data. */
	    file->bzipStream.next_out = file->bzip_outbuf;
	    file->bzipStream.avail_out = BZIPFS_OUTBUFSIZE;
	    file->bzipfs_outptr = file->bzip_outbuf;
	    err = BZ2_bzDecompress(&(file->bzipStream));
	    if (err == BZ_STREAM_END) {
		/* We can get a partial buffer fill here. */
	        file->bzipfs_eofseen = 1;
		}
	    else if (err != BZ_OK) {
		res = CFE_ERR;
		break;
		}
	    file->bzipfs_outlen = (int)(file->bzipStream.next_out) - (int)(file->bzipfs_outptr);
	    }

	}

    file->bzipfs_fileoffset += ttlcopy;
    nReturn = (res < 0) ? res : ttlcopy;
    return nReturn;	
}

static int bzipfs_fileop_write(void *ref,uint8_t *buf,int len)
{
    return CFE_ERR_UNSUPPORTED;
}

static int bzipfs_fileop_seek(void *ref,int offset,int how)
{
    bzipfs_file_t *file = (bzipfs_file_t *) ref;
    int res;
    int delta;

    switch (how) {
	case FILE_SEEK_BEGINNING:
	    delta = offset - file->bzipfs_fileoffset;
	    break;
	case FILE_SEEK_CURRENT:
	    delta = offset;
	    break;
	default:
	    return CFE_ERR_UNSUPPORTED;
	    break;
	}

    /* backward seeking not allowed on compressed streams */
    if (delta < 0) {
	return CFE_ERR_UNSUPPORTED;
	}

    res = bzipfs_fileop_read(ref,NULL,delta);

    if (res < 0) return res;

    return file->bzipfs_fileoffset;
}


static void bzipfs_fileop_close(void *ref)
{
    bzipfs_file_t *file = (bzipfs_file_t *) ref;


    file->bzip_fsctx->bzipfsctx_refcnt--;

    BZ2_bzDecompressEnd(&(file->bzipStream));

    BDCLOSE(file->bzip_fsctx->bzipfsctx_subops,file->subfile);

/*  if(file->bzip_outbuf)
    {
        KFREE(file->bzip_outbuf);
        file->bzip_outbuf = NULL;
    }    */
    KFREE(file);
}

static void bzipfs_fileop_uninit(void *fsctx_arg)
{
    bzipfs_fsctx_t *fsctx = (bzipfs_fsctx_t *) fsctx_arg;

    BDUNINIT(fsctx->bzipfsctx_subops,fsctx->bzipfsctx_subfsctx);

    KFREE(fsctx);
}


#endif


bzipfs_fileops的编写

由于bzip2的解压需要更大的block,因而分配内存使用直接地址取址,而不使用从内存池分配出来的地址(heap只有4096)

 

然后将kernel用bzip2进行压缩,压缩比先不要太高,如果用到9,那么block(上面代码是BZIPFS_BUFSIZE)则要开到(3 * 128 * 1024)

bzip2 -1fc vmlinux > vmlinuz_bz

然后cfe将这个kernel烧写到flash里

之后再通过cfe解压然后跑这个elf

结果出现

**Exception 32: EPC=8045DF40, Cause=00008028, VAddr=E01834A8
                RA=87014A64, PRID=00025A11

        0  ($00) = 00000000     AT ($01) = A0000000
        v0 ($02) = 00040000     v1 ($03) = 00000080
        a0 ($04) = 8706E1E0     a1 ($05) = 00000000
        a2 ($06) = 87014AD8     a3 ($07) = 43464531
        t0 ($08) = 8045DF40     t1 ($09) = 8003FF80
        t2 ($10) = FFFFFF80     t3 ($11) = 870B97D8
        t4 ($12) = 87012144     t5 ($13) = 00000115
        t6 ($14) = 87014F44     t7 ($15) = 87010ED0
        s0 ($16) = 87014A64     s1 ($17) = 87051EB4
        s2 ($18) = 87051EC4     s3 ($19) = 8045DF40
        s4 ($20) = 87468578     s5 ($21) = 87094370
        s6 ($22) = 87468520     s7 ($23) = 8701CA10
        t8 ($24) = 870655E4     t9 ($25) = 8C81BA74
        k0 ($26) = 87066510     k1 ($27) = 87066544
        gp ($28) = 8706E1E0     sp ($29) = 874683C8
        fp ($30) = 8703C448     ra ($31) = 87014A64


*** Waiting for system reset ***


这个错误,是调用cfe_launch后产生的

cfe_launch里面的运行代码是汇编代码

初步怀疑是解压过大文件的时候擦除了必要运行内存地址的信息所致,有待debug

你可能感兴趣的:(CFE(UBOOT)集成bzip2测试)