rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
Functions | Variables
compressed_block_device.cpp File Reference

Detailed Description

This file implements a ChibiOS block device backed by a compressed (gzip) store.

Date
Mar 4, 2021
Author
Matthew Kennedy, (c) 2021

This works by decompressing one block (512 bytes) at a time.

For sequential reads, the performance is great - the gzip decompress can only go forwards in the file. If a block later in the file (but with a gap) is requested, we decompress (and discard) the blocks in the gap, returning the block requested.

If a block is requested from before the previous block, we discard decompression state, reinitialize, and decompress up to that block.

NOTE: This means performance is terrible for "true" random access! Things go best when you have a few big files in the filesystem with no fragmentation, so they can be read out in large sequential chunks.

Definition in file compressed_block_device.cpp.

Functions

static bool is_inserted (void *)
 
static bool is_protected (void *)
 
static bool connect (void *instance)
 
static bool disconnect (void *instance)
 
static bool read (void *instance, uint32_t startblk, uint8_t *buffer, uint32_t)
 
static bool write (void *, uint32_t, const uint8_t *, uint32_t)
 
constexpr size_t gzSize (const uint8_t *image, size_t imageSize)
 
static bool get_info (void *instance, BlockDeviceInfo *bdip)
 
static bool sync (void *instance)
 
void compressedBlockDeviceObjectInit (CompressedBlockDevice *cbd)
 
void compressedBlockDeviceStart (CompressedBlockDevice *cbd, const uint8_t *source, size_t sourceSize)
 

Variables

static const BaseBlockDeviceVMT cbdVmt
 

Function Documentation

◆ compressedBlockDeviceObjectInit()

void compressedBlockDeviceObjectInit ( CompressedBlockDevice cbd)

Definition at line 138 of file compressed_block_device.cpp.

138 {
139 cbd->vmt = &cbdVmt;
140 memset(cbd->dictionary, 0, sizeof(cbd->dictionary));
141 cbd->state = BLK_STOP;
142}
static const BaseBlockDeviceVMT cbdVmt
static CompressedBlockDevice cbd
const BaseBlockDeviceVMT * vmt

Referenced by getRamdiskDevice().

Here is the caller graph for this function:

◆ compressedBlockDeviceStart()

void compressedBlockDeviceStart ( CompressedBlockDevice cbd,
const uint8_t *  source,
size_t  sourceSize 
)

Definition at line 144 of file compressed_block_device.cpp.

144 {
145 cbd->source = source;
146 cbd->sourceSize = sourceSize;
147 cbd->state = BLK_READY;
148 cbd->lastBlock = -1;
149}
_base_block_device_data int32_t lastBlock

Referenced by getRamdiskDevice().

Here is the caller graph for this function:

◆ connect()

static bool connect ( void *  instance)
static

Definition at line 38 of file compressed_block_device.cpp.

38 {
40 if (BLK_STOP == cbd->state) {
41 cbd->state = BLK_READY;
42 }
43 return HAL_SUCCESS;
44}
static BenchController instance

◆ disconnect()

static bool disconnect ( void *  instance)
static

Definition at line 46 of file compressed_block_device.cpp.

46 {
48 if (BLK_STOP != cbd->state) {
49 cbd->state = BLK_STOP;
50 }
51 return HAL_SUCCESS;
52}

◆ get_info()

static bool get_info ( void *  instance,
BlockDeviceInfo *  bdip 
)
static

Definition at line 102 of file compressed_block_device.cpp.

102 {
104 if (cbd->state != BLK_READY) {
105 return HAL_FAILED;
106 }
107
108 // The last 4 bytes of the gzip stream encode the total size in bytes
109 size_t size = gzSize(cbd->source, cbd->sourceSize);
110
111 bdip->blk_num = size / BLOCK_SIZE;
112 bdip->blk_size = BLOCK_SIZE;
113 return HAL_SUCCESS;
114}
constexpr size_t gzSize(const uint8_t *image, size_t imageSize)
composite packet size
Here is the call graph for this function:

◆ gzSize()

constexpr size_t gzSize ( const uint8_t *  image,
size_t  imageSize 
)
constexpr

Definition at line 93 of file compressed_block_device.cpp.

93 {
94 // The last 4 bytes of the gzip stream encode the total size in bytes
95 const uint8_t* pSize = image + imageSize - 1;
96 size_t size = *pSize--;
97 size = 256 * size + *pSize--;
98 size = 256 * size + *pSize--;
99 return 256 * size + *pSize--;
100}

Referenced by get_info().

Here is the caller graph for this function:

◆ is_inserted()

static bool is_inserted ( void *  )
static

Definition at line 28 of file compressed_block_device.cpp.

28 {
29 // Device is always inserted
30 return true;
31}

◆ is_protected()

static bool is_protected ( void *  )
static

Definition at line 33 of file compressed_block_device.cpp.

33 {
34 // Write protected - we can't do random access writes to a compressed volume
35 return true;
36}

◆ read()

static bool read ( void *  instance,
uint32_t  startblk,
uint8_t *  buffer,
uint32_t   
)
static

Definition at line 54 of file compressed_block_device.cpp.

54 {
56
57 // If we just initialized, or trying to seek backwards, (re)initialize the decompressor
58 if (cbd->lastBlock == -1 || (int32_t)startblk <= cbd->lastBlock) {
59 uzlib_uncompress_init(&cbd->d, cbd->dictionary, sizeof(cbd->dictionary));
60
61 cbd->d.source = cbd->source;
62 cbd->d.source_limit = cbd->d.source + cbd->sourceSize;
63 cbd->d.source_read_cb = NULL;
64
65 uzlib_gzip_parse_header(&cbd->d);
66
67 cbd->lastBlock = -1;
68 }
69
70 // How many blocks do we need to decompress to get to the one requested?
71 size_t blocks_ahead = startblk - cbd->lastBlock;
72
73 // Decompress blocks until we get to the block we need
74 for (size_t i = 0; i < blocks_ahead; i++) {
75 cbd->d.dest = cbd->d.dest_start = buffer;
76 cbd->d.dest_limit = buffer + BLOCK_SIZE;
77
78 // Decompress one chunk
79 uzlib_uncompress(&cbd->d);
80 }
81
82 // Save the current position in the stream so we can efficiently seek forward later
83 cbd->lastBlock = startblk;
84
85 return HAL_SUCCESS;
86}
static BigBufferHandle buffer

◆ sync()

static bool sync ( void *  instance)
static

Definition at line 116 of file compressed_block_device.cpp.

116 {
118 if (BLK_READY != cbd->state) {
119 return HAL_FAILED;
120 }
121 else {
122 return HAL_SUCCESS;
123 }
124}

◆ write()

static bool write ( void *  ,
uint32_t  ,
const uint8_t *  ,
uint32_t   
)
static

Definition at line 88 of file compressed_block_device.cpp.

88 {
89 // you shouldn't be able to do this anyway, so just swallow it, I guess?
90 return HAL_SUCCESS;
91}

Variable Documentation

◆ cbdVmt

const BaseBlockDeviceVMT cbdVmt
static
Initial value:
= {
(size_t)0,
}
static bool write(void *, uint32_t, const uint8_t *, uint32_t)
static bool is_inserted(void *)
static bool disconnect(void *instance)
static bool get_info(void *instance, BlockDeviceInfo *bdip)
static bool connect(void *instance)
static bool read(void *instance, uint32_t startblk, uint8_t *buffer, uint32_t)
static bool is_protected(void *)
static bool sync(void *instance)

Definition at line 126 of file compressed_block_device.cpp.

126 {
127 (size_t)0, // instanceOffset
130 connect,
132 read,
133 write,
134 sync,
135 get_info,
136};

Referenced by compressedBlockDeviceObjectInit().

Go to the source code of this file.