From d88dfa81b53a701579699fd8e4afe782c3a771d8 Mon Sep 17 00:00:00 2001 From: Michal Sojka Date: Tue, 1 Mar 2011 22:16:35 +0100 Subject: [PATCH] Add missing files from uLan repository These files are needed to compile some parts of sysless. Namely, this fixes build of lpc2364-12 board. --- arch/generic/defines/Makefile.omk | 4 +- arch/generic/defines/ads1x46.h | 56 +++ arch/generic/defines/keyval_id_his.h | 12 + libs4c/keyval/Makefile | 14 + libs4c/keyval/Makefile.omk | 13 + libs4c/keyval/keyval_id.h | 17 + libs4c/keyval/keyval_mem_store.c | 63 ++++ libs4c/keyval/keyval_mem_store.h | 10 + libs4c/keyval/keyvalpb.c | 501 +++++++++++++++++++++++++++ libs4c/keyval/keyvalpb.h | 331 ++++++++++++++++++ 10 files changed, 1019 insertions(+), 2 deletions(-) create mode 100644 arch/generic/defines/ads1x46.h create mode 100644 arch/generic/defines/keyval_id_his.h create mode 100644 libs4c/keyval/Makefile create mode 100644 libs4c/keyval/Makefile.omk create mode 100644 libs4c/keyval/keyval_id.h create mode 100644 libs4c/keyval/keyval_mem_store.c create mode 100644 libs4c/keyval/keyval_mem_store.h create mode 100644 libs4c/keyval/keyvalpb.c create mode 100644 libs4c/keyval/keyvalpb.h diff --git a/arch/generic/defines/Makefile.omk b/arch/generic/defines/Makefile.omk index 713fdd5..23a50b3 100644 --- a/arch/generic/defines/Makefile.omk +++ b/arch/generic/defines/Makefile.omk @@ -1,8 +1,8 @@ # -*- makefile -*- -#include_HEADERS += byteswap.h endian.h +include_HEADERS += byteswap.h endian.h include_HEADERS += lt_timer.h lt_timer_types.h deb_led.h -#include_HEADERS += keyval_id_his.h ads1x46.h +include_HEADERS += keyval_id_his.h ads1x46.h include_HEADERS += irq_generic.h #include_HEADERS = $(notdir $(wildcard $(SOURCES_DIR)/*.h)) diff --git a/arch/generic/defines/ads1x46.h b/arch/generic/defines/ads1x46.h new file mode 100644 index 0000000..96df9f6 --- /dev/null +++ b/arch/generic/defines/ads1x46.h @@ -0,0 +1,56 @@ +#ifndef _ADS1X46_H +#define _ADS1X46_H + +#define ADS_REG_BCS 0x00 +#define RBCS1 (1<<7) +#define RBCS0 (1<<6) + +#define ADS_REG_VBIAS 0x01 +#define RVBIAS1 (1<<1) +#define RVBIAS0 (1<<0) + +#define ADS_REG_MUX1 0x02 +#define RCLKSTAT (1<<7) +#define RMUXCAL2 (1<<2) +#define RMUXCAL1 (1<<1) +#define RMUXCAL0 (1<<0) + +#define ADS_REG_SYS0 0x03 +#define RPGA2 (1<<6) +#define RPGA1 (1<<5) +#define RPGA0 (1<<4) +#define RDR3 (1<<3) +#define RDR2 (1<<2) +#define RDR1 (1<<1) +#define RDR0 (1<<0) + +#define ADS_REG_OFC0 0x04 +#define ADS_REG_OFC1 0x05 +#define ADS_REG_OFC2 0x06 +#define ADS_REG_FSC0 0x07 +#define ADS_REG_FSC1 0x08 +#define ADS_REG_FSC2 0x09 +#define ADS_REG_ID 0x0A +#define RDRDY_MODE (1<<3) + +#define ADS_CMD_WAKEUP 0x00 +#define ADS_CMD_SLEEP 0x02 +#define ADS_CMD_SYNC 0x04 +#define ADS_CMD_RESET 0x06 +#define ADS_CMD_PO_INIT 0x0E +#define ADS_CMD_NOP 0xFF + +#define ADS_CMD_RDATA 0x12 +#define ADS_CMD_RDATAC 0x14 +#define ADS_CMD_SDATAC 0x16 + +#define ADS_CMD_RREG 0x20 +#define ADS_CMD_WREG 0x40 + +#define ADS_CMD_SYSOCAL 0x60 +#define ADS_CMD_SYSGCAL 0x61 +#define ADS_CMD_SELFCAL 0x62 + + +#endif /* _ADS1X46_H */ + diff --git a/arch/generic/defines/keyval_id_his.h b/arch/generic/defines/keyval_id_his.h new file mode 100644 index 0000000..f07cc45 --- /dev/null +++ b/arch/generic/defines/keyval_id_his.h @@ -0,0 +1,12 @@ +#ifndef _KEYVAL_ID_HIS_H_ +#define _KEYVAL_ID_HISC_H_ + +#include "keyvalpb.h" + +#define KVPB_KEYID_BLINDER_POSSITION 0x20 +#define KVPB_KEYID_BLINDER_OPENTIME 0x21 +#define KVPB_KEYID_BLP_UP 0x22 +#define KVPB_KEYID_BLP_DOWN 0x23 + +#endif /* _KEYVAL_ID_HIS_H_ */ + diff --git a/libs4c/keyval/Makefile b/libs4c/keyval/Makefile new file mode 100644 index 0000000..76b56fd --- /dev/null +++ b/libs4c/keyval/Makefile @@ -0,0 +1,14 @@ +# Generic directory or leaf node makefile for OCERA make framework + +ifndef MAKERULES_DIR +MAKERULES_DIR := $(shell ( old_pwd="" ; while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" = `pwd` ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) ) +endif + +ifeq ($(MAKERULES_DIR),) +all : default +.DEFAULT:: + @echo -e "\nThe Makefile.rules has not been found in this or parent directory\n" +else +include $(MAKERULES_DIR)/Makefile.rules +endif + diff --git a/libs4c/keyval/Makefile.omk b/libs4c/keyval/Makefile.omk new file mode 100644 index 0000000..35b5272 --- /dev/null +++ b/libs4c/keyval/Makefile.omk @@ -0,0 +1,13 @@ +# -*- makefile -*- + +default_CONFIG = CONFIG_KEYVAL=n + +ifeq ($(CONFIG_KEYVAL),y) +lib_LIBRARIES = keyval +include_HEADERS += keyvalpb.h keyval_id.h +keyval_SOURCES += keyvalpb.c + +include_HEADERS += keyval_mem_store.h +keyval_SOURCES += keyval_mem_store.c + +endif #CONFIG_KEYVAL diff --git a/libs4c/keyval/keyval_id.h b/libs4c/keyval/keyval_id.h new file mode 100644 index 0000000..68b3d5a --- /dev/null +++ b/libs4c/keyval/keyval_id.h @@ -0,0 +1,17 @@ +#ifndef _KEYVAL_ID_H_ +#define _KEYVAL_ID_H_ + +#include "keyvalpb.h" + +#define KVPB_KEYID_ULAN_ADDR 0x10 +#define KVPB_KEYID_ULAN_SN 0x11 + +#define KVPB_KEYID_ULAN_PICO 0x15 +#define KVPB_KEYID_ULAN_POCO 0x16 +#define KVPB_KEYID_ULAN_PIOM 0x17 +#define KVPB_KEYID_ULAN_PEV2C 0x18 + +#define KVPB_KEYID_HIS_ACCESS_CODE 0x20 + +#endif /* _KEYVAL_ID_H_ */ + diff --git a/libs4c/keyval/keyval_mem_store.c b/libs4c/keyval/keyval_mem_store.c new file mode 100644 index 0000000..b32e4df --- /dev/null +++ b/libs4c/keyval/keyval_mem_store.c @@ -0,0 +1,63 @@ +/******************************************************************************/ +/* Key Value block in RAM */ + +#include +#include +#include +#include + +int kvpb_mem_erase(kvpb_block_t *store, void *base,int size) +{ + memset(base,0xff,size); + return 0; +} + +int kvpb_mem_copy(kvpb_block_t *store, void *dst,const void *src,int len) +{ + memcpy(dst,src,len); + return 0; +} + +#ifndef KVPB_MINIMALIZED +kvpb_block_t *kvpb_store_create_ram(int size) +{ + kvpb_block_t *store; + int res; + + if(!size) + size=0x4000; + + store = malloc(sizeof(*store)); + if(store == NULL) + return NULL; + + memset(store, 0, sizeof(*store)); + + store->base = malloc(size*2); + if(store->base == NULL) + goto error_ret; + + store->size = size; + store->flags = KVPB_DESC_DOUBLE; + #ifndef KVPB_MINIMALIZED + store->erase = kvpb_mem_erase, + store->copy = kvpb_mem_copy; + #endif /* KVPB_MINIMALIZED */ + + kvpb_block_erase(store, store->base,store->size); + if(store->flags & KVPB_DESC_DOUBLE) + kvpb_block_erase(store, (uint8_t*)store->base+store->size,store->size); + + res=kvpb_check(store,3); + + if(res<0) + goto error_ret; + + return store; + + error_ret: + if(store) + free(store); + return NULL; +} +#endif /* KVPB_MINIMALIZED */ diff --git a/libs4c/keyval/keyval_mem_store.h b/libs4c/keyval/keyval_mem_store.h new file mode 100644 index 0000000..af3fdeb --- /dev/null +++ b/libs4c/keyval/keyval_mem_store.h @@ -0,0 +1,10 @@ +#ifndef _KEYVAL_MEM_STORE_H +#define _KEYVAL_MEM_STORE_H + +#include + +int kvpb_mem_erase(kvpb_block_t *store, void *base,int size); +int kvpb_mem_copy(kvpb_block_t *store, void *dst,const void *src,int len); +kvpb_block_t *kvpb_store_create_ram(int size); + +#endif /*_KEYVAL_MEM_STORE_H*/ diff --git a/libs4c/keyval/keyvalpb.c b/libs4c/keyval/keyvalpb.c new file mode 100644 index 0000000..394a559 --- /dev/null +++ b/libs4c/keyval/keyvalpb.c @@ -0,0 +1,501 @@ +/******************************************************************* + Key Value Persistent Storage + + keyvalpb.c - key value parameters block + + (C) Copyright 2003-2005 by Pavel Pisa - Originator + (C) Copyright 2004-2005 by Petr Smolik - Originator + + The uLan utilities library can be used, copied and modified under + next licenses + - GPL - GNU General Public License + - LGPL - GNU Lesser General Public License + - MPL - Mozilla Public License + - and other licenses added by project originators + Code can be modified and re-distributed under any combination + of the above listed licenses. If contributor does not agree with + some of the licenses, he/she can delete appropriate line. + Warning, if you delete all lines, you are not allowed to + distribute source code and/or binaries utilizing code. + + See files COPYING and README for details. + + *******************************************************************/ + +#include +#include "keyvalpb.h" + +/* + * kvpb_memsum - Compute checksum of given memory area + * @base: Pointer to the base of of the region + * @size: Size of utilized part of the region + * + * Return Value: Computed checksum value + * File: keyvalpb.c + */ +kvpb_sum_t kvpb_memsum(KVPB_DPTRTYPE uint8_t *base, kvpb_size_t size) +{ + KVPB_LOCALDATA kvpb_sum_t sum=0; + KVPB_DPTRTYPE uint16_t *p=(KVPB_DPTRTYPE uint16_t *)base; + size=(size+1)>>1; + while(size--){ + sum+=*(p++); + } + sum&=KVPB_SUM_MASK; + sum|=KVPB_SUM_OKVAL; + return sum; +} + +#ifndef KVPB_WITHOUT_HADLE +/* + * kvpb_get_psum - Get pointer to the region check sum + * @kvpb_block: Pointer to the KVPB access information/state structure + * @base: Pointer to the base of of the region + * @size: Size of one data block region + * + * Return Value: Pointer to the actual region check sum placement + * File: keyvalpb.c + */ +KVPB_DPTRTYPE kvpb_sum_t *kvpb_get_psum(kvpb_block_t *kvpb_block, + KVPB_DPTRTYPE uint8_t *base, kvpb_size_t size) +#else +KVPB_DPTRTYPE kvpb_sum_t *__kvpb_get_psum( + KVPB_DPTRTYPE uint8_t *base, kvpb_size_t size) +#endif +{ + KVPB_DPTRTYPE kvpb_sum_t *psum; + psum=kvpb_psum_align(kvpb_block,(KVPB_DPTRTYPE kvpb_sum_t*)(base+size)-1); + while((KVPB_DPTRTYPE uint8_t*)psum>=base) { + if (*kvpb_psum_valid_loc(kvpb_block,psum)!=0) + return psum; + psum=kvpb_psum_align(kvpb_block,psum-1); + } + return NULL; +} + +#ifndef KVPB_WITHOUT_HADLE +/* + * kvpb_get_cfk - Get space where to place new key-value pair + * @kvpb_block: Pointer to the KVPB access information/state structure + * @mode: 0 .. work on active/valid data region; + * 1 .. work on the first copy/region, 2 .. work on the second copy/region + * @size: Size of required space for stored value + * + * Return Value: Pointer where next pair should be stored or %NULL + * File: keyvalpb.c + */ +KVPB_DPTRTYPE kvpb_key_t *kvpb_get_cfk(kvpb_block_t *kvpb_block,uint8_t mode,int size) +#else +KVPB_DPTRTYPE kvpb_key_t *__kvpb_get_cfk(uint8_t mode,int size) +#endif +{ + KVPB_DPTRTYPE kvpb_sum_t *psum; + KVPB_DPTRTYPE uint8_t *p; + KVPB_DPTRTYPE uint8_t *r; + p=kvpb_region_base(kvpb_block,0); + size=kvpb_chunk_align(kvpb_block,size+sizeof(kvpb_key_t))+ + (kvpb_block->flags&KVPB_DESC_CHUNKWO?kvpb_chunk_size(kvpb_block):0); + psum=kvpb_block->psum1; + if((!mode && (kvpb_block->flags & KVPB_DESC_USE2ND))||(mode==2)) { + if(!(kvpb_block->flags&KVPB_DESC_DOUBLE)) + return NULL; + p=kvpb_region_base(kvpb_block,1); + psum=kvpb_block->psum2; + } + do { + kvpb_size_t ksize=((KVPB_DPTRTYPE kvpb_key_t *)p)->size; + if(ksize==KVPB_EMPTY) + break; + if(((uint8_t*)psum-(uint8_t*)p)flags&KVPB_DESC_CHUNKWO?kvpb_chunk_size(kvpb_block):0); + } while(1); + r=(KVPB_DPTRTYPE uint8_t*)p+size+sizeof(kvpb_key_t); + if(rflags&=~KVPB_DESC_USE2ND; + + p=kvpb_region_base(kvpb_block,0); + kvpb_block->psum1=kvpb_get_psum(kvpb_block,p,kvpb_block->size); + if (kvpb_block->psum1) { + sum=kvpb_memsum(p,(KVPB_DPTRTYPE uint8_t*)kvpb_block->psum1-p); + if(*kvpb_block->psum1==sum){ + ret=1; + } + } + + if(kvpb_block->flags&KVPB_DESC_DOUBLE){ + p=kvpb_region_base(kvpb_block,1); + kvpb_block->psum2=kvpb_get_psum(kvpb_block,p,kvpb_block->size); + if (kvpb_block->psum2) { + sum=kvpb_memsum(p,(KVPB_DPTRTYPE uint8_t*)kvpb_block->psum2-p); + if(*kvpb_block->psum2==sum) { + if(ret>=0){ + ret=0; + } else { + ret=2; + kvpb_block->flags|=KVPB_DESC_USE2ND; + } + } + } + } else { + if(ret>=0) + ret=0; + } + + if(ret){ + if(!mode) { + kvpb_block->flags|=KVPB_DESC_RO; + } else { + /* correct for FLASH */ + if(ret<0){ + p=kvpb_region_base(kvpb_block,0); + kvpb_block_erase(kvpb_block,p,kvpb_block->size); + kvpb_block->psum1=kvpb_psum_align(kvpb_block,(KVPB_DPTRTYPE kvpb_sum_t*)(p+kvpb_block->size)-1); + sum=kvpb_memsum(p,(KVPB_DPTRTYPE uint8_t*)kvpb_block->psum1-p); + kvpb_block_copy(kvpb_block,kvpb_block->psum1,&sum,sizeof(kvpb_sum_t)); + if(kvpb_block->flags&KVPB_DESC_DOUBLE){ + p=kvpb_region_base(kvpb_block,1); + kvpb_block_erase(kvpb_block,p,kvpb_block->size); + kvpb_block->psum2=kvpb_psum_align(kvpb_block,(KVPB_DPTRTYPE kvpb_sum_t*)(p+kvpb_block->size)-1); + sum=kvpb_memsum(p,(KVPB_DPTRTYPE uint8_t*)kvpb_block->psum2-p); + kvpb_block_copy(kvpb_block,kvpb_block->psum2,&sum,sizeof(kvpb_sum_t)); + } + ret=3; + }else{ + if(ret==1){ + kvpb_block_erase(kvpb_block,kvpb_region_base(kvpb_block,1),kvpb_block->size); + kvpb_block_copy(kvpb_block,kvpb_region_base(kvpb_block,1), + kvpb_region_base(kvpb_block,0),kvpb_block->size); + + }else{ + kvpb_block_erase(kvpb_block,kvpb_region_base(kvpb_block,0),kvpb_block->size); + kvpb_block_copy(kvpb_block,kvpb_region_base(kvpb_block,0), + kvpb_region_base(kvpb_block,1),kvpb_block->size); + } + } + kvpb_block->flags&=~KVPB_DESC_RO; + } + } + kvpb_block_flush(kvpb_block); + if(ret>=0) kvpb_block->flags|=KVPB_DESC_VALID; + return ret; +} + +#ifndef KVPB_WITHOUT_HADLE +/** + * kvpb_first - Get pointer to the first key-value pair in the KVPB storage + * @kvpb_block: Pointer to the KVPB access information/state structure + * @mode: 0 .. iterate over active/valid data region; + * 1 .. iterate over first copy/region, 2 .. iterate over second copy/region + * + * Return Value: Pointer to the first key-value pair + * or %NULL if no pair exist. + * File: keyvalpb.c + */ +KVPB_DPTRTYPE kvpb_key_t *kvpb_first(kvpb_block_t *kvpb_block, uint8_t mode) +#else +KVPB_DPTRTYPE kvpb_key_t *__kvpb_first(uint8_t mode) +#endif +{ + KVPB_DPTRTYPE kvpb_key_t *key=(KVPB_DPTRTYPE kvpb_key_t *)kvpb_region_base(kvpb_block,0); + if((!mode && (kvpb_block->flags & KVPB_DESC_USE2ND))||(mode==2)) { + if(!(kvpb_block->flags&KVPB_DESC_DOUBLE)) + return NULL; + key=(KVPB_DPTRTYPE kvpb_key_t *)kvpb_region_base(kvpb_block,1); + } + while(*kvpb_keyid_valid(kvpb_block,key)==KVPB_KEYID_INVALID) { + key=kvpb_next(kvpb_block,key); + if (!key) + return NULL; + } + return key->size!=KVPB_EMPTY?key:NULL; +} + +#ifndef KVPB_WITHOUT_HADLE +/** + * kvpb_next - Iterate to the next consecutive key-value pair + * @kvpb_block: Pointer to the KVPB access information/state structure + * @key: Pointer to the previous key-value pair + * + * Return Value: Pointer to the next key-value pair + * or %NULL if no/no-more pairs exist. + * File: keyvalpb.c + */ +KVPB_DPTRTYPE kvpb_key_t *kvpb_next(kvpb_block_t *kvpb_block, KVPB_DPTRTYPE kvpb_key_t *key) +#else +KVPB_DPTRTYPE kvpb_key_t *__kvpb_next(KVPB_DPTRTYPE kvpb_key_t *key) +#endif +{ + do { + key=(KVPB_DPTRTYPE kvpb_key_t *)((KVPB_DPTRTYPE uint8_t *)key+ + kvpb_chunk_align(kvpb_block,key->size+sizeof(kvpb_key_t))+ + (kvpb_block->flags&KVPB_DESC_CHUNKWO?kvpb_chunk_size(kvpb_block):0)); + if (key->size==KVPB_EMPTY) return NULL; + } while(*kvpb_keyid_valid(kvpb_block,key)==KVPB_KEYID_INVALID); + return key; +} + +#ifndef KVPB_WITHOUT_HADLE +/** + * kvpb_find - Find first of occurrence of given key ID + * @kvpb_block: Pointer to the KVPB access information/state structure + * @keyid: Ordinal value representing key ID + * @mode: iteration mode modifier: 0 .. search in the active/valid data region; + * 1 .. search in the first copy/region, 2 .. search in the second copy/region + * @key: Previous key occurrence pointer or %NULL value to find first key ID named key-value pair + * + * Return Value: Pointer to the first on subsequent occurrence of key-value pair addressed by given key ID + * or %NULL if no/no-more occurrences exists. + * File: keyvalpb.c + */ +KVPB_DPTRTYPE kvpb_key_t *kvpb_find(kvpb_block_t *kvpb_block, kvpb_keyid_t keyid, uint8_t mode, KVPB_DPTRTYPE kvpb_key_t *key) +#else +KVPB_DPTRTYPE kvpb_key_t *__kvpb_find(kvpb_keyid_t keyid, uint8_t mode, KVPB_DPTRTYPE kvpb_key_t *key) +#endif +{ + if(!(kvpb_block->flags&KVPB_DESC_VALID)) + return NULL; + if (key) { + key=kvpb_next(kvpb_block, key); + } else { + key=kvpb_first(kvpb_block, mode); + } + while(key) { + if((key->keyid==keyid) || (keyid==0)) + return key; + key=kvpb_next(kvpb_block, key); + } + return key; +} + +#ifndef KVPB_WITHOUT_HADLE +/** + * kvpb_compact_region - Compact one KVPB data block/region + * @kvpb_block: Pointer to the KVPB access information/state structure + * @keyid: Key ID which should be omitted from compacted data + * @mode: 0 .. compact active/valid data region; + * 1 .. compact the first data copy, 2 .. compact the second copy + * + * Return Value: Operation cannot be finished. + * File: keyvalpb.c + */ +int kvpb_compact_region(kvpb_block_t *kvpb_block, uint8_t mode, kvpb_keyid_t keyid) +#else +int __kvpb_compact_region(uint8_t mode, kvpb_keyid_t keyid) +#endif +{ + KVPB_DPTRTYPE uint8_t *p; + KVPB_DPTRTYPE kvpb_key_t *des,*src; + + p=kvpb_region_base(kvpb_block,0); + des=(KVPB_DPTRTYPE kvpb_key_t*)p; + if(kvpb_block->flags&KVPB_DESC_DOUBLE) + src=(KVPB_DPTRTYPE kvpb_key_t*)kvpb_region_base(kvpb_block,1); + else + src=(KVPB_DPTRTYPE kvpb_key_t*)p; + + if((!mode && (kvpb_block->flags & KVPB_DESC_USE2ND))||(mode==2)) { + if(!(kvpb_block->flags&KVPB_DESC_DOUBLE)) + return -1; + des=src; + src=(KVPB_DPTRTYPE kvpb_key_t*)p; + p=(KVPB_DPTRTYPE uint8_t *)des; + kvpb_block->psum2=kvpb_psum_align(kvpb_block, + (KVPB_DPTRTYPE kvpb_sum_t*)(p+kvpb_block->size)-1); + } else { + kvpb_block->psum1=kvpb_psum_align(kvpb_block, + (KVPB_DPTRTYPE kvpb_sum_t*)(p+kvpb_block->size)-1); + } + kvpb_block_flush(kvpb_block); + kvpb_block_erase(kvpb_block,des,kvpb_block->size); + while(src) { + int s=kvpb_chunk_align(kvpb_block,src->size+sizeof(kvpb_key_t)); + if((*kvpb_keyid_valid(kvpb_block,src)!=KVPB_KEYID_INVALID) && (src->keyid!=keyid)) { + if(src!=des) + kvpb_block_copy(kvpb_block,des,src,s); + if (kvpb_block->flags&KVPB_DESC_CHUNKWO) s+=kvpb_chunk_size(kvpb_block); + des=(KVPB_DPTRTYPE kvpb_key_t*)((uint8_t*)des+s); + } + src=kvpb_next(kvpb_block, src); + } + kvpb_block_flush(kvpb_block); + return 0; +} + +#ifndef KVPB_WITHOUT_HADLE +/** + * kvpb_get_key - Get value for given key ID + * @kvpb_block: Pointer to the KVPB access information/state structure + * @keyid: Ordinal value representing key ID + * @size: The size of the buffer provided to store data into + * @buf: Pointer to the buffer, where retrieved data should be copied + * + * Return Value: Number of retrieved value bytes if operation is successful + * or -1 if there is no such key ID or operation fails for other reason. + * File: keyvalpb.c + */ +int kvpb_get_key(kvpb_block_t *kvpb_block, kvpb_keyid_t keyid, kvpb_size_t size, void *buf) +#else +int __kvpb_get_key(kvpb_keyid_t keyid, kvpb_size_t size, void *buf) +#endif +{ + KVPB_DPTRTYPE kvpb_key_t *key; + key=kvpb_find(kvpb_block,keyid,0,NULL); + if(!key) return -1; + if(size && buf){ + if(key->sizesize; + memcpy(buf,key+1,size); + } + return key->size; +} + + +#ifndef KVPB_WITHOUT_HADLE +/** + * kvpb_set_key - Set new value or define new key-value pair + * @kvpb_block: Pointer to the KVPB access information/state structure + * @keyid: Ordinal value representing key ID, if or-red with %KVPB_KEYID_DUPLIC, + * the key ID can be defined/inserted multiple times + * @size: Stored value size in bytes + * @buf: Pointer to the stored value data + * + * Return Value: Number of stored bytes (equal to @size) if operation is successful + * or -1 if operation fails. + * File: keyvalpb.c + */ +int kvpb_set_key(kvpb_block_t *kvpb_block, kvpb_keyid_t keyid, kvpb_size_t size, const void *buf) +#else +int __kvpb_set_key(kvpb_keyid_t keyid, kvpb_size_t size, const void *buf) +#endif +{ + KVPB_LOCALDATA kvpb_sum_t sum; + KVPB_DPTRTYPE kvpb_sum_t *psum; + KVPB_DPTRTYPE kvpb_key_t *key; + KVPB_DPTRTYPE uint8_t *p; + + if(!(kvpb_block->flags&KVPB_DESC_VALID)) + return -1; + if(kvpb_block->flags&KVPB_DESC_RO) + return -1; + + /*first region*/ + psum=kvpb_psum_align(kvpb_block,kvpb_block->psum1); + sum=0; + kvpb_block_copy(kvpb_block,kvpb_psum_valid_loc(kvpb_block,psum),&sum,sizeof(kvpb_sum_t)); + kvpb_block->psum1=kvpb_psum_align(kvpb_block,kvpb_block->psum1-1); + if (!(keyid&KVPB_KEYID_DUPLIC) || !buf) { + kvpb_each_from(kvpb_block,keyid,1,key) { + kvpb_keyid_t dkeyid=KVPB_KEYID_INVALID; + kvpb_block_copy(kvpb_block,kvpb_keyid_valid(kvpb_block,key),&dkeyid,sizeof(kvpb_keyid_t)); + } + } + key=kvpb_get_cfk(kvpb_block,1,size); + if (!key) { + kvpb_compact_region(kvpb_block,1,(keyid&KVPB_KEYID_DUPLIC)?0:keyid); + key=kvpb_get_cfk(kvpb_block,1,size); + } + if (keyid && key && buf) { + kvpb_block_copy(kvpb_block,&key->size,&size,sizeof(kvpb_size_t)); + kvpb_block_copy(kvpb_block,&key->keyid,&keyid,sizeof(kvpb_keyid_t)); + kvpb_block_copy(kvpb_block,(uint8_t*)(key+1),buf,/*align???*/ size); + } + /* need flush data to count correct value of new check sum */ + kvpb_block_flush(kvpb_block); + + p=kvpb_region_base(kvpb_block,0); + sum=kvpb_memsum(p,(KVPB_DPTRTYPE uint8_t*)kvpb_block->psum1-p); + kvpb_block_copy(kvpb_block,kvpb_block->psum1,&sum,sizeof(kvpb_sum_t)); + kvpb_block_flush(kvpb_block); + if(!(kvpb_block->flags&KVPB_DESC_DOUBLE)) + return key?size:-1; + + /*Write in the first region failed, switching to backup region */ + if(kvpb_block->flags&KVPB_DESC_RO){ + kvpb_block->flags|=KVPB_DESC_USE2ND; + return -1; + } + + /*second region*/ + psum=kvpb_psum_align(kvpb_block,kvpb_block->psum2); + sum=0; + kvpb_block_copy(kvpb_block,kvpb_psum_valid_loc(kvpb_block,psum),&sum,sizeof(kvpb_sum_t)); + kvpb_block->psum2=kvpb_psum_align(kvpb_block,kvpb_block->psum2-1); + if (!(keyid&KVPB_KEYID_DUPLIC) || !buf) { + kvpb_each_from(kvpb_block,keyid,2,key) { + kvpb_keyid_t dkeyid=KVPB_KEYID_INVALID; + kvpb_block_copy(kvpb_block,kvpb_keyid_valid(kvpb_block,key),&dkeyid,sizeof(kvpb_keyid_t)); + } + } + key=kvpb_get_cfk(kvpb_block,2,size); + if (!key) { + kvpb_compact_region(kvpb_block,2,(keyid&KVPB_KEYID_DUPLIC)?0:keyid); + key=kvpb_get_cfk(kvpb_block,2,size); + } + if (keyid && key && buf) { + kvpb_block_copy(kvpb_block,&key->size,&size,sizeof(kvpb_size_t)); + kvpb_block_copy(kvpb_block,&key->keyid,&keyid,sizeof(kvpb_keyid_t)); + kvpb_block_copy(kvpb_block,(uint8_t*)(key+1),buf,/*align???*/ size); + } + kvpb_block_flush(kvpb_block); + + p=kvpb_region_base(kvpb_block,1); + sum=kvpb_memsum(p,(KVPB_DPTRTYPE uint8_t*)kvpb_block->psum2-p); + kvpb_block_copy(kvpb_block,kvpb_block->psum2,&sum,sizeof(kvpb_sum_t)); + kvpb_block_flush(kvpb_block); + /*Write in the second region failed, switching to the first region */ + if(kvpb_block->flags&KVPB_DESC_RO){ + kvpb_block->flags&=~KVPB_DESC_USE2ND; + return -1; + } + + return key?size:-1; +} + +#ifndef KVPB_MINIMALIZED +/** + * kvpb_err_keys - Erase/delete key-value pair + * @kvpb_block: Pointer to the KVPB access information/state structure + * @keyid: Ordinal value representing key ID + * + * Return Value: Positive or zero value informs about successful operation, + * -1 if operation fails. + * File: keyvalpb.c + */ +int kvpb_err_keys(kvpb_block_t *kvpb_block, kvpb_keyid_t keyid) +{ + return kvpb_set_key(kvpb_block,keyid,0,NULL); +} +#endif /*KVPB_MINIMALIZED*/ + diff --git a/libs4c/keyval/keyvalpb.h b/libs4c/keyval/keyvalpb.h new file mode 100644 index 0000000..210a02b --- /dev/null +++ b/libs4c/keyval/keyvalpb.h @@ -0,0 +1,331 @@ +/******************************************************************* + Key Value Persistent Storage + + keyvalpb.h - key value parameters block + + (C) Copyright 2003-2005 by Pavel Pisa - Originator + (C) Copyright 2004-2005 by Petr Smolik - Originator + + The uLan utilities library can be used, copied and modified under + next licenses + - GPL - GNU General Public License + - LGPL - GNU Lesser General Public License + - MPL - Mozilla Public License + - and other licenses added by project originators + Code can be modified and re-distributed under any combination + of the above listed licenses. If contributor does not agree with + some of the licenses, he/she can delete appropriate line. + Warning, if you delete all lines, you are not allowed to + distribute source code and/or binaries utilizing code. + + See files COPYING and README for details. + + *******************************************************************/ + +#ifndef _KEYVALPB_H_ +#define _KEYVALPB_H_ + +//#include +#include +#include +#include + +#ifdef KVPB_MINIMALIZED +#define KVPB_WITHOUT_HADLE +#define KVPB_DPTRTYPE CODE +#define KVPB_LOCALDATA DATA +#endif /*KVPB_MINIMALIZED*/ + +#ifndef KVPB_DPTRTYPE +#define KVPB_DPTRTYPE +#endif /*KVPB_DPTRTYPE*/ + +#ifndef KVPB_LOCALDATA +#define KVPB_LOCALDATA +#endif /*KVPB_DPTRTYPE*/ + +#ifndef KVPB_BLOCK_LOC +#define KVPB_BLOCK_LOC +#endif /*KVPB_BLOCK_LOC*/ + +#define KVPB_EMPTY ((kvpb_size_t)~0) + +#define KVPB_KEYID_INVALID 0 +#define KVPB_KEYID_DUPLIC ((((kvpb_keyid_t)~0)>>1)+1) +#define KBPB_KEYID_INVALID_BIT (KVPB_KEYID_DUPLIC>>1) + +#define KVPB_SUM_MASK (((kvpb_sum_t)~0)>>2) +#define KVPB_SUM_OKVAL (KVPB_SUM_MASK+1) + +#define KVPB_DESC_DOUBLE 0x01 +#define KVPB_DESC_USE2ND 0x02 +#define KVPB_DESC_VALID 0x04 +#define KVPB_DESC_RO 0x08 +#define KVPB_DESC_CHUNKWO 0x10 +#define KVPB_DESC_ALIGN4 0x40 +#define KVPB_DESC_FLASH 0x80 + +#ifdef KVPB_MINIMALIZED +typedef uint16_t kvpb_sum_t; +typedef uint16_t kvpb_size_t; +typedef uint8_t kvpb_keyid_t; +#else /*KVPB_MINIMALIZED*/ +typedef uint32_t kvpb_sum_t; +typedef uint32_t kvpb_size_t; +typedef uint32_t kvpb_keyid_t; +#endif /*KVPB_MINIMALIZED*/ + +/** + * struct kvpb_block - Key-value parameter block access information + * @base: Pointer to the start of physically mapped key-value block data + * @size: Size of one region (one data copy) of parameter block + * @flags: Block state flags: + * %KVPB_DESC_DOUBLE - the information is stored in two consecutive redundant copies/regions; + * %KVPB_DESC_USE2ND - data will be read from the second copy because first one is damaged; + * %KVPB_DESC_VALID - at least one region is valid; + * %KVPB_DESC_RO - because of some problems, only read access is allowed + * %KVPB_DESC_CHUNKWO - chunk can be written only once between erase operations + * %KVPB_DESC_ALIGN4 - data has to be aligned to four bytes + * %KVPB_DESC_FLASH - flash memory is used for data storage + * @psum1: Pointer to the control checksum of the first data region + * @psum2: Pointer to the control checksum of the second data region + * @erase: Function to erase some range of the storage region + * @copy: Function to copy data into or between storage regions + * @flush: Function to finish pending copy operations + * @chunk_size: Minimal store chunk size which can be independently modified + * + * File: keyvalpb.h + */ +typedef struct kvpb_block { + KVPB_DPTRTYPE uint8_t *base; + kvpb_size_t size; + short flags; + KVPB_DPTRTYPE kvpb_sum_t *psum1; + KVPB_DPTRTYPE kvpb_sum_t *psum2; + #ifndef KVPB_MINIMALIZED + int (*erase)(struct kvpb_block *store, void *base,int size); + int (*copy)(struct kvpb_block *store, void *des,const void *src,int len); + int (*flush)(struct kvpb_block *store); + unsigned chunk_size; + #endif /* KVPB_MINIMALIZED */ +} kvpb_block_t; + + +#define kvpb_region_base(block,regidx) \ + ((((KVPB_DPTRTYPE uint8_t *)(block)->base)+(regidx*(block)->size))) + +#ifndef KVPB_MINIMALIZED + #ifndef kvpb_chunk_size + #define kvpb_chunk_size(store) ((store)->chunk_size<4?4:(store)->chunk_size) + #endif /*kvpb_chunk_size*/ + #define kvpb_chunk_size_mask(store) (kvpb_chunk_size(store)-1) + +/** + * kvpb_chunk_align - Round up KVPB size to minimal store chunk size multiple + * @store: Pointer to the KVPB access information/state structure + * @size: Unaligned size + * + * Return Value: Minimal aligned size to hold unaligned size. + * File: keyvalpb.h + */ + static inline unsigned kvpb_chunk_align(struct kvpb_block *store, unsigned size) + { + return ((size)+kvpb_chunk_size_mask(store))&~kvpb_chunk_size_mask(store); + } + +/** + * kvpb_psum_align - Round up KVPB size to minimal store chunk size multiple + * @store: Pointer to the KVPB access information/state structure + * @psum: Pointer to proposed location of next check sum location + * + * Return Value: Pointer to next check sum location rounded down to next slot. + * File: keyvalpb.h + */ + static inline kvpb_sum_t* kvpb_psum_align(struct kvpb_block *store, kvpb_sum_t *psum) + { + unsigned long mask=~kvpb_chunk_size_mask(store); + if(store->flags&KVPB_DESC_CHUNKWO) + mask<<=1; + return (kvpb_sum_t*)(((unsigned long)(psum))&mask); + } + +/** + * kvpb_psum_valid_loc - Return pointer to check sum validity info location + * @store: Pointer to the KVPB access information/state structure + * @psum: Pointer to corectly aligned check sum location + * + * Return Value: Pointer to location which indicates by zero value, that check sum + * is invalidated. + * File: keyvalpb.h + */ + static inline kvpb_sum_t* kvpb_psum_valid_loc(struct kvpb_block *store, kvpb_sum_t *psum) + { + if(!(store->flags&KVPB_DESC_CHUNKWO)) + return psum; + else + return (kvpb_sum_t*)(((char *)(psum))+kvpb_chunk_size(store)); + } + +/** + * kvpb_block_erase - Wrapper function to call KVPB specific data erase function + * @store: Pointer to the KVPB access information/state structure + * @base: Base address of erased region inside parameter block data region + * @size: Number of bytes to erase + * + * The KVPB mechanism is intended for FLASH type memories and it expect + * that only whole data region can be erased at time. The expected erase state + * is all bits set to the ones. + * + * Return Value: Negative value indicates operation fault. + * File: keyvalpb.h + */ + static inline int kvpb_block_erase(struct kvpb_block *store, void *base,int size) + { + return store->erase(store, base,size) ; + } + +/** + * kvpb_block_copy - Wrapper function to call KVPB specific data copy function + * @store: Pointer to the KVPB access information/state structure + * @des: Address of data destination pointing inside mapped parameter block data region + * @src: Address of data source pointing inside mapped parameter block data or RAM memory + * @len: Number of bytes to transfer + * + * Return Value: Negative value indicates operation fault. + * File: keyvalpb.h + */ + static inline int kvpb_block_copy(struct kvpb_block *store, void *des,const void *src,int len) + { + return store->copy(store, des, src, len); + } + +/** + * kvpb_block_flush - Wrapper function to call KVPB specific flush function + * @store: Pointer to the KVPB access information/state structure + * + * Return Value: Negative value indicates operation fault. + * File: keyvalpb.h + */ + static inline int kvpb_block_flush(struct kvpb_block *store) + { + if(!(store->flush)) return 0; + return store->flush(store); + } + +#else /* KVPB_MINIMALIZED */ + #ifndef kvpb_chunk_size + #define kvpb_chunk_size(store) 1 + #endif /*kvpb_chunk_size*/ + #define kvpb_chunk_size_mask(store) (kvpb_chunk_size(store)-1) + #define kvpb_chunk_align(store,x) \ + (((x)+kvpb_chunk_size_mask(store))&~kvpb_chunk_size_mask(store)) + #define kvpb_psum_align(store,x) \ + ((KVPB_DPTRTYPE kvpb_sum_t*)((unsigned)(x)&~kvpb_chunk_size_mask(store))) + #define kvpb_psum_valid_loc(store,x) \ + ((kvpb_sum_t*)((char*)(x)+0*kvpb_chunk_size(store))) +#ifndef kvpb_block_copy + #define kvpb_block_erase(store, base, size) flash_erase(base, size) + #define kvpb_block_copy(store, des, src, len) flash_copy(des, src, len) + #define kvpb_block_flush(store) flash_flush() + + /* forward declarations for external procedures */ + int flash_erase(void *base,int size); + int flash_copy(void *des,const void *src,int len); +#ifndef flash_flush + int flash_flush(void); +#endif /* flash_flush */ +#endif /* kvpb_block_copy */ +#endif /* KVPB_MINIMALIZED */ + +/** + * struct kvpb_key - Header of stored key value pair and structure for iteration over KVPB + * @size: Non-aligned byte size of the stored value + * @keyid: Ordinal value representing stored data key + * + * The header structure is followed by @size data bytes in the KVPB storage block. + * Because only word aligned write accesses are possible on some architectures + * and memory types the whole size of space occupied by one key-value pair is + * sum of rounded-up data size kvpb_chunk_align(@size) and size of header sizeof(kvpb_key_t). + */ +typedef struct kvpb_key { + kvpb_size_t size; + kvpb_keyid_t keyid; +} kvpb_key_t; + +#ifndef KVPB_WITHOUT_HADLE + static inline kvpb_keyid_t* kvpb_keyid_valid(struct kvpb_block *store, kvpb_key_t *key) + { + if(store->flags&KVPB_DESC_CHUNKWO) + return (kvpb_keyid_t*)((uint8_t*)key+(kvpb_chunk_align(store,key->size+sizeof(kvpb_key_t)))); + return &(key->keyid); + } +#else + #define kvpb_keyid_valid(store,key) (&((key)->keyid)) +#endif /*KVPB_WITHOUT_HADLE*/ + + +#ifndef KVPB_WITHOUT_HADLE +KVPB_DPTRTYPE kvpb_key_t *kvpb_first(kvpb_block_t *block, uint8_t mode); +KVPB_DPTRTYPE kvpb_key_t *kvpb_next(kvpb_block_t *block, KVPB_DPTRTYPE kvpb_key_t *key); +KVPB_DPTRTYPE kvpb_key_t *kvpb_find(kvpb_block_t *block, kvpb_keyid_t keyid, uint8_t mode, KVPB_DPTRTYPE kvpb_key_t *key); +int kvpb_get_key(kvpb_block_t *kvpb_block, kvpb_keyid_t keyid, kvpb_size_t size, void *buf); +int kvpb_set_key(kvpb_block_t *kvpb_block, kvpb_keyid_t keyid, kvpb_size_t size, const void *buf); +int kvpb_err_keys(kvpb_block_t *kvpb_block, kvpb_keyid_t keyid); +int kvpb_check(kvpb_block_t *kvpb_block, uint8_t mode); +#else +extern KVPB_BLOCK_LOC kvpb_block_t kvpb_block_global; +#define kvpb_block (&kvpb_block_global) +KVPB_DPTRTYPE kvpb_sum_t *__kvpb_get_psum(KVPB_DPTRTYPE uint8_t *base, kvpb_size_t size); +KVPB_DPTRTYPE kvpb_key_t *__kvpb_first(uint8_t mode); +KVPB_DPTRTYPE kvpb_key_t *__kvpb_next(KVPB_DPTRTYPE kvpb_key_t *key); +KVPB_DPTRTYPE kvpb_key_t *__kvpb_find(kvpb_keyid_t keyid, uint8_t mode, KVPB_DPTRTYPE kvpb_key_t *key); +int __kvpb_get_key(kvpb_keyid_t keyid, kvpb_size_t size, void *buf); +int __kvpb_set_key(kvpb_keyid_t keyid, kvpb_size_t size, const void *buf); +int __kvpb_check(uint8_t mode); +#define kvpb_get_psum(block, base, size) __kvpb_get_psum(base, size) +#define kvpb_first(block, mode) __kvpb_first(mode) +#define kvpb_next(block, key) __kvpb_next(key) +#define kvpb_find(block, keyid, mode, key) __kvpb_find(keyid, mode, key) +#define kvpb_get_key(block, keyid, size, buf) __kvpb_get_key(keyid, size, buf) +#define kvpb_set_key(block, keyid, size, buf) __kvpb_set_key(keyid, size, buf) +#define kvpb_err_keys(block,keyid) kvpb_set_key(block,keyid,0,NULL) +#define kvpb_check(block, mode) __kvpb_check(mode) +#define kvpb_compact_region(block, mode, keyid) __kvpb_compact_region(mode, keyid) +#define kvpb_get_cfk(block,mode,size) __kvpb_get_cfk(mode,size) +#endif + +/** + * kvpb_for_each - Iterate over all key value pairs + * @root: Pointer to the KVPB access information/state structure + * @key: Iterator of kvpb_key_t* type + * @mode: iteration mode modifier: 0 .. iterate over active/valid data region; + * 1 .. iterate over first copy, 2 .. iterate over second copy + * + * File: keyvalpb.h + */ +#define kvpb_for_each(root, key,mode) \ + for(key=kvpb_first(root,mode);key;\ + key=kvpb_next(root, key)) + +/** + * kvpb_for_each - Iterate over all key value pairs matching given key ID + * @root: Pointer to the KVPB access information/state structure + * @keyid: Ordinal value representing key ID + * @key: Iterator of kvpb_key_t* type + * @mode: iteration mode modifier: 0 .. iterate over active/valid data region; + * 1 .. iterate over first copy, 2 .. iterate over second copy + * + * File: keyvalpb.h + */ +#define kvpb_each_from(root, keyid, mode, key) \ + for(key=kvpb_find(root,keyid,mode,NULL);key;\ + key=kvpb_find(root,keyid,mode,key)) + +#ifdef KVPB_MINIMALIZED +#define kvpb_key2data(key) ((void*)(key+1)) +#else /*KVPB_MINIMALIZED*/ +static inline void* kvpb_key2data(kvpb_key_t *key) { return key+1; } +#endif /*KVPB_MINIMALIZED*/ + +#endif /* _KEYVALPB_H_ */ + -- 2.39.2