]> rtime.felk.cvut.cz Git - sysless.git/commitdiff
Add missing files from uLan repository
authorMichal Sojka <sojkam1@fel.cvut.cz>
Tue, 1 Mar 2011 21:16:35 +0000 (22:16 +0100)
committerMichal Sojka <sojkam1@fel.cvut.cz>
Tue, 1 Mar 2011 21:16:35 +0000 (22:16 +0100)
These files are needed to compile some parts of sysless. Namely, this fixes
build of lpc2364-12 board.

arch/generic/defines/Makefile.omk
arch/generic/defines/ads1x46.h [new file with mode: 0644]
arch/generic/defines/keyval_id_his.h [new file with mode: 0644]
libs4c/keyval/Makefile [new file with mode: 0644]
libs4c/keyval/Makefile.omk [new file with mode: 0644]
libs4c/keyval/keyval_id.h [new file with mode: 0644]
libs4c/keyval/keyval_mem_store.c [new file with mode: 0644]
libs4c/keyval/keyval_mem_store.h [new file with mode: 0644]
libs4c/keyval/keyvalpb.c [new file with mode: 0644]
libs4c/keyval/keyvalpb.h [new file with mode: 0644]

index 713fdd58ab3404927428a8383af1b388b6e34204..23a50b3539ba1556981945e5ad5a71178d58a1cd 100644 (file)
@@ -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 (file)
index 0000000..96df9f6
--- /dev/null
@@ -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 (file)
index 0000000..f07cc45
--- /dev/null
@@ -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 (file)
index 0000000..76b56fd
--- /dev/null
@@ -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 (file)
index 0000000..35b5272
--- /dev/null
@@ -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 (file)
index 0000000..68b3d5a
--- /dev/null
@@ -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 (file)
index 0000000..b32e4df
--- /dev/null
@@ -0,0 +1,63 @@
+/******************************************************************************/
+/* Key Value block in RAM */
+
+#include <malloc.h>
+#include <string.h>
+#include <keyvalpb.h>
+#include <keyval_mem_store.h>
+
+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 (file)
index 0000000..af3fdeb
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _KEYVAL_MEM_STORE_H
+#define _KEYVAL_MEM_STORE_H
+
+#include <keyvalpb.h>
+
+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 (file)
index 0000000..394a559
--- /dev/null
@@ -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 <string.h>
+#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)<ksize)
+      return NULL;
+    p+=kvpb_chunk_align(kvpb_block,ksize+sizeof(kvpb_key_t))+
+       (kvpb_block->flags&KVPB_DESC_CHUNKWO?kvpb_chunk_size(kvpb_block):0);
+  } while(1);
+  r=(KVPB_DPTRTYPE uint8_t*)p+size+sizeof(kvpb_key_t);
+  if(r<p)
+    return NULL;
+  if ((uint8_t*)kvpb_psum_align(kvpb_block,psum-1)<r) {
+    return NULL;
+  }
+  return (KVPB_DPTRTYPE kvpb_key_t*)p;
+}
+
+
+#ifndef KVPB_WITHOUT_HADLE
+/**
+ * kvpb_check - Check data consistency of the KVPB storage
+ * @kvpb_block: Pointer to the KVPB access information/state structure
+ * @mode: if mode is nonzero, try to restore valid state or erase all data
+ *
+ * Return Value: 0 .. all regions are correct, 1 .. the first region is valid, the second
+ *     region is invalid or has been updated if @mode has been set, 2 .. the second region
+ *     is valid, the first is invalid or has been updated if @mode has been set, 3 .. both
+ *     regions has been erased and emptied, -1 .. the state is inconsistent and no valid
+ *     region has been found and state has not be corrected
+ * File: keyvalpb.c
+ */
+int kvpb_check(kvpb_block_t *kvpb_block, uint8_t mode)
+#else
+int __kvpb_check(uint8_t mode)
+#endif
+{
+  KVPB_DPTRTYPE uint8_t *p;
+  KVPB_LOCALDATA int ret=-1;
+  KVPB_LOCALDATA kvpb_sum_t sum;
+
+  kvpb_block->flags&=~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->size<size)
+      size=key->size;
+    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 (file)
index 0000000..210a02b
--- /dev/null
@@ -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 <inttypes.h>
+#include <types.h>
+#include <system_def.h>
+#include <cpu_def.h>
+
+#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_ */
+