用过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