diff --git a/src/lib/cbfs_core.c b/src/lib/cbfs_core.c index 839b994cf3..50c037e573 100644 --- a/src/lib/cbfs_core.c +++ b/src/lib/cbfs_core.c @@ -202,6 +202,12 @@ int cbfs_decompress(int algo, void *src, void *dst, int len) { switch (algo) { case CBFS_COMPRESS_NONE: + /* Reads need to be aligned at 4 bytes to avoid + poor flash performance. */ + while (len && ((u32)src & 3)) { + *(u8*)dst++ = *(u8*)src++; + len--; + } memmove(dst, src, len); return len; #ifdef CBFS_CORE_WITH_LZMA diff --git a/src/lib/lzmadecode.c b/src/lib/lzmadecode.c index 1cf647d27b..fb57f4fd4d 100644 --- a/src/lib/lzmadecode.c +++ b/src/lib/lzmadecode.c @@ -28,7 +28,10 @@ #define kBitModelTotal (1 << kNumBitModelTotalBits) #define kNumMoveBits 5 -#define RC_READ_BYTE (*Buffer++) +/* Use 32-bit reads whenever possible to avoid bad flash performance. */ +#define RC_READ_BYTE (look_ahead_ptr < 4 ? look_ahead.raw[look_ahead_ptr++] \ + : ((((UInt32) Buffer & 3) || ((SizeT) (BufferLim - Buffer) < 4)) ? (*Buffer++) \ + : ((look_ahead.dw = *(UInt32 *)Buffer), (Buffer += 4), (look_ahead_ptr = 1), look_ahead.raw[0]))) #define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \ { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }} @@ -149,6 +152,12 @@ int LzmaDecode(CLzmaDecoderState *vs, int len = 0; const Byte *Buffer; const Byte *BufferLim; + int look_ahead_ptr = 4; + union + { + Byte raw[4]; + UInt32 dw; + } look_ahead; UInt32 Range; UInt32 Code;