1 /*******************************************************************
2 Key Value Persistent Storage
4 keyvalpb.h - key value parameters block
6 (C) Copyright 2003-2005 by Pavel Pisa - Originator
7 (C) Copyright 2004-2005 by Petr Smolik - Originator
9 The uLan utilities library can be used, copied and modified under
11 - GPL - GNU General Public License
12 - LGPL - GNU Lesser General Public License
13 - MPL - Mozilla Public License
14 - and other licenses added by project originators
15 Code can be modified and re-distributed under any combination
16 of the above listed licenses. If contributor does not agree with
17 some of the licenses, he/she can delete appropriate line.
18 Warning, if you delete all lines, you are not allowed to
19 distribute source code and/or binaries utilizing code.
21 See files COPYING and README for details.
23 *******************************************************************/
28 //#include <inttypes.h>
30 #include <system_def.h>
33 #ifdef KVPB_MINIMALIZED
34 #define KVPB_WITHOUT_HADLE
35 #define KVPB_DPTRTYPE CODE
36 #define KVPB_LOCALDATA DATA
37 #endif /*KVPB_MINIMALIZED*/
41 #endif /*KVPB_DPTRTYPE*/
43 #ifndef KVPB_LOCALDATA
44 #define KVPB_LOCALDATA
45 #endif /*KVPB_DPTRTYPE*/
47 #ifndef KVPB_BLOCK_LOC
48 #define KVPB_BLOCK_LOC
49 #endif /*KVPB_BLOCK_LOC*/
51 #define KVPB_EMPTY ((kvpb_size_t)~0)
53 #define KVPB_KEYID_INVALID 0
54 #define KVPB_KEYID_DUPLIC ((((kvpb_keyid_t)~0)>>1)+1)
55 #define KBPB_KEYID_INVALID_BIT (KVPB_KEYID_DUPLIC>>1)
57 #define KVPB_SUM_MASK (((kvpb_sum_t)~0)>>2)
58 #define KVPB_SUM_OKVAL (KVPB_SUM_MASK+1)
60 #define KVPB_DESC_DOUBLE 0x01
61 #define KVPB_DESC_USE2ND 0x02
62 #define KVPB_DESC_VALID 0x04
63 #define KVPB_DESC_RO 0x08
64 #define KVPB_DESC_CHUNKWO 0x10
65 #define KVPB_DESC_ALIGN4 0x40
66 #define KVPB_DESC_FLASH 0x80
68 #ifdef KVPB_MINIMALIZED
69 typedef uint16_t kvpb_sum_t;
70 typedef uint16_t kvpb_size_t;
71 typedef uint8_t kvpb_keyid_t;
72 #else /*KVPB_MINIMALIZED*/
73 typedef uint32_t kvpb_sum_t;
74 typedef uint32_t kvpb_size_t;
75 typedef uint32_t kvpb_keyid_t;
76 #endif /*KVPB_MINIMALIZED*/
79 * struct kvpb_block - Key-value parameter block access information
80 * @base: Pointer to the start of physically mapped key-value block data
81 * @size: Size of one region (one data copy) of parameter block
82 * @flags: Block state flags:
83 * %KVPB_DESC_DOUBLE - the information is stored in two consecutive redundant copies/regions;
84 * %KVPB_DESC_USE2ND - data will be read from the second copy because first one is damaged;
85 * %KVPB_DESC_VALID - at least one region is valid;
86 * %KVPB_DESC_RO - because of some problems, only read access is allowed
87 * %KVPB_DESC_CHUNKWO - chunk can be written only once between erase operations
88 * %KVPB_DESC_ALIGN4 - data has to be aligned to four bytes
89 * %KVPB_DESC_FLASH - flash memory is used for data storage
90 * @psum1: Pointer to the control checksum of the first data region
91 * @psum2: Pointer to the control checksum of the second data region
92 * @erase: Function to erase some range of the storage region
93 * @copy: Function to copy data into or between storage regions
94 * @flush: Function to finish pending copy operations
95 * @chunk_size: Minimal store chunk size which can be independently modified
99 typedef struct kvpb_block {
100 KVPB_DPTRTYPE uint8_t *base;
103 KVPB_DPTRTYPE kvpb_sum_t *psum1;
104 KVPB_DPTRTYPE kvpb_sum_t *psum2;
105 #ifndef KVPB_MINIMALIZED
106 int (*erase)(struct kvpb_block *store, void *base,int size);
107 int (*copy)(struct kvpb_block *store, void *des,const void *src,int len);
108 int (*flush)(struct kvpb_block *store);
110 #endif /* KVPB_MINIMALIZED */
114 #define kvpb_region_base(block,regidx) (((block)->base+(regidx*(block)->size)))
116 #ifndef KVPB_MINIMALIZED
117 #ifndef kvpb_chunk_size
118 #define kvpb_chunk_size(store) ((store)->chunk_size<4?4:(store)->chunk_size)
119 #endif /*kvpb_chunk_size*/
120 #define kvpb_chunk_size_mask(store) (kvpb_chunk_size(store)-1)
123 * kvpb_chunk_align - Round up KVPB size to minimal store chunk size multiple
124 * @store: Pointer to the KVPB access information/state structure
125 * @size: Unaligned size
127 * Return Value: Minimal aligned size to hold unaligned size.
130 static inline unsigned kvpb_chunk_align(struct kvpb_block *store, unsigned size)
132 return ((size)+kvpb_chunk_size_mask(store))&~kvpb_chunk_size_mask(store);
136 * kvpb_psum_align - Round up KVPB size to minimal store chunk size multiple
137 * @store: Pointer to the KVPB access information/state structure
138 * @psum: Pointer to proposed location of next check sum location
140 * Return Value: Pointer to next check sum location rounded down to next slot.
143 static inline kvpb_sum_t* kvpb_psum_align(struct kvpb_block *store, kvpb_sum_t *psum)
145 unsigned long mask=~kvpb_chunk_size_mask(store);
146 if(store->flags&KVPB_DESC_CHUNKWO)
148 return (kvpb_sum_t*)(((unsigned long)(psum))&mask);
152 * kvpb_psum_valid_loc - Return pointer to check sum validity info location
153 * @store: Pointer to the KVPB access information/state structure
154 * @psum: Pointer to corectly aligned check sum location
156 * Return Value: Pointer to location which indicates by zero value, that check sum
160 static inline kvpb_sum_t* kvpb_psum_valid_loc(struct kvpb_block *store, kvpb_sum_t *psum)
162 if(!(store->flags&KVPB_DESC_CHUNKWO))
165 return (kvpb_sum_t*)(((char *)(psum))+kvpb_chunk_size(store));
169 * kvpb_block_erase - Wrapper function to call KVPB specific data erase function
170 * @store: Pointer to the KVPB access information/state structure
171 * @base: Base address of erased region inside parameter block data region
172 * @size: Number of bytes to erase
174 * The KVPB mechanism is intended for FLASH type memories and it expect
175 * that only whole data region can be erased at time. The expected erase state
176 * is all bits set to the ones.
178 * Return Value: Negative value indicates operation fault.
181 static inline int kvpb_block_erase(struct kvpb_block *store, void *base,int size)
183 return store->erase(store, base,size) ;
187 * kvpb_block_copy - Wrapper function to call KVPB specific data copy function
188 * @store: Pointer to the KVPB access information/state structure
189 * @des: Address of data destination pointing inside mapped parameter block data region
190 * @src: Address of data source pointing inside mapped parameter block data or RAM memory
191 * @len: Number of bytes to transfer
193 * Return Value: Negative value indicates operation fault.
196 static inline int kvpb_block_copy(struct kvpb_block *store, void *des,const void *src,int len)
198 return store->copy(store, des, src, len);
202 * kvpb_block_flush - Wrapper function to call KVPB specific flush function
203 * @store: Pointer to the KVPB access information/state structure
205 * Return Value: Negative value indicates operation fault.
208 static inline int kvpb_block_flush(struct kvpb_block *store)
210 if(!(store->flush)) return 0;
211 return store->flush(store);
214 #else /* KVPB_MINIMALIZED */
215 #ifndef kvpb_chunk_size
216 #define kvpb_chunk_size(store) 1
217 #endif /*kvpb_chunk_size*/
218 #define kvpb_chunk_size_mask(store) (kvpb_chunk_size(store)-1)
219 #define kvpb_chunk_align(store,x) \
220 (((x)+kvpb_chunk_size_mask(store))&~kvpb_chunk_size_mask(store))
221 #define kvpb_psum_align(store,x) \
222 ((KVPB_DPTRTYPE kvpb_sum_t*)((unsigned)(x)&~kvpb_chunk_size_mask(store)))
223 #define kvpb_psum_valid_loc(store,x) \
224 ((kvpb_sum_t*)((char*)(x)+0*kvpb_chunk_size(store)))
225 #define kvpb_block_erase(store, base, size) flash_erase(base, size)
226 #define kvpb_block_copy(store, des, src, len) flash_copy(des, src, len)
227 #define kvpb_block_flush(store) flash_flush()
228 /* forward declarations for external procedures */
229 int flash_erase(void *base,int size);
230 int flash_copy(void *des,const void *src,int len);
232 int flash_flush(void);
233 #endif /* flash_flush */
234 #endif /* KVPB_MINIMALIZED */
237 * struct kvpb_key - Header of stored key value pair and structure for iteration over KVPB
238 * @size: Non-aligned byte size of the stored value
239 * @keyid: Ordinal value representing stored data key
241 * The header structure is followed by @size data bytes in the KVPB storage block.
242 * Because only word aligned write accesses are possible on some architectures
243 * and memory types the whole size of space occupied by one key-value pair is
244 * sum of rounded-up data size kvpb_chunk_align(@size) and size of header sizeof(kvpb_key_t).
246 typedef struct kvpb_key {
251 #ifndef KVPB_WITHOUT_HADLE
252 static inline kvpb_keyid_t* kvpb_keyid_valid(struct kvpb_block *store, kvpb_key_t *key)
254 if(store->flags&KVPB_DESC_CHUNKWO)
255 return (kvpb_keyid_t*)((uint8_t*)key+(kvpb_chunk_align(store,key->size+sizeof(kvpb_key_t))));
256 return &(key->keyid);
259 #define kvpb_keyid_valid(store,key) (&((key)->keyid))
260 #endif /*KVPB_WITHOUT_HADLE*/
263 #ifndef KVPB_WITHOUT_HADLE
264 KVPB_DPTRTYPE kvpb_key_t *kvpb_first(kvpb_block_t *block, uint8_t mode);
265 KVPB_DPTRTYPE kvpb_key_t *kvpb_next(kvpb_block_t *block, KVPB_DPTRTYPE kvpb_key_t *key);
266 KVPB_DPTRTYPE kvpb_key_t *kvpb_find(kvpb_block_t *block, kvpb_keyid_t keyid, uint8_t mode, KVPB_DPTRTYPE kvpb_key_t *key);
267 int kvpb_get_key(kvpb_block_t *kvpb_block, kvpb_keyid_t keyid, kvpb_size_t size, void *buf);
268 int kvpb_set_key(kvpb_block_t *kvpb_block, kvpb_keyid_t keyid, kvpb_size_t size, const void *buf);
269 int kvpb_err_keys(kvpb_block_t *kvpb_block, kvpb_keyid_t keyid);
270 int kvpb_check(kvpb_block_t *kvpb_block, uint8_t mode);
272 extern KVPB_BLOCK_LOC kvpb_block_t kvpb_block_global;
273 #define kvpb_block (&kvpb_block_global)
274 KVPB_DPTRTYPE kvpb_sum_t *__kvpb_get_psum(KVPB_DPTRTYPE uint8_t *base, kvpb_size_t size);
275 KVPB_DPTRTYPE kvpb_key_t *__kvpb_first(uint8_t mode);
276 KVPB_DPTRTYPE kvpb_key_t *__kvpb_next(KVPB_DPTRTYPE kvpb_key_t *key);
277 KVPB_DPTRTYPE kvpb_key_t *__kvpb_find(kvpb_keyid_t keyid, uint8_t mode, KVPB_DPTRTYPE kvpb_key_t *key);
278 int __kvpb_get_key(kvpb_keyid_t keyid, kvpb_size_t size, void *buf);
279 int __kvpb_set_key(kvpb_keyid_t keyid, kvpb_size_t size, const void *buf);
280 int __kvpb_check(uint8_t mode);
281 #define kvpb_get_psum(block, base, size) __kvpb_get_psum(base, size)
282 #define kvpb_first(block, mode) __kvpb_first(mode)
283 #define kvpb_next(block, key) __kvpb_next(key)
284 #define kvpb_find(block, keyid, mode, key) __kvpb_find(keyid, mode, key)
285 #define kvpb_get_key(block, keyid, size, buf) __kvpb_get_key(keyid, size, buf)
286 #define kvpb_set_key(block, keyid, size, buf) __kvpb_set_key(keyid, size, buf)
287 #define kvpb_err_keys(block,keyid) kvpb_set_key(block,keyid,0,NULL)
288 #define kvpb_check(block, mode) __kvpb_check(mode)
289 #define kvpb_compact_region(block, mode, keyid) __kvpb_compact_region(mode, keyid)
290 #define kvpb_get_cfk(block,mode,size) __kvpb_get_cfk(mode,size)
294 * kvpb_for_each - Iterate over all key value pairs
295 * @root: Pointer to the KVPB access information/state structure
296 * @key: Iterator of kvpb_key_t* type
297 * @mode: iteration mode modifier: 0 .. iterate over active/valid data region;
298 * 1 .. iterate over first copy, 2 .. iterate over second copy
302 #define kvpb_for_each(root, key,mode) \
303 for(key=kvpb_first(root,mode);key;\
307 * kvpb_for_each - Iterate over all key value pairs matching given key ID
308 * @root: Pointer to the KVPB access information/state structure
309 * @keyid: Ordinal value representing key ID
310 * @key: Iterator of kvpb_key_t* type
311 * @mode: iteration mode modifier: 0 .. iterate over active/valid data region;
312 * 1 .. iterate over first copy, 2 .. iterate over second copy
316 #define kvpb_each_from(root, keyid, mode, key) \
317 for(key=kvpb_find(root,keyid,mode,NULL);key;\
318 key=kvpb_find(root,keyid,mode,key))
320 #ifdef KVPB_MINIMALIZED
321 #define kvpb_key2data(key) ((void*)(key+1))
322 #else /*KVPB_MINIMALIZED*/
323 static inline void* kvpb_key2data(kvpb_key_t *key) { return key+1; }
324 #endif /*KVPB_MINIMALIZED*/
326 #endif /* _KEYVALPB_H_ */