[Feature]Upload Modem source code

Change-Id: Id4294f30faced84d3e6fd6d5e61e1111bf287a37
diff --git a/mcu/tools/NVRAMStatistic/NVRAMAutogen.bat b/mcu/tools/NVRAMStatistic/NVRAMAutogen.bat
new file mode 100755
index 0000000..5bbf66d
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/NVRAMAutogen.bat
@@ -0,0 +1,245 @@
+@echo off

+path ..\..\tools;..\..\..\tools;..\..\..\Tools\MSYS\bin;..\..\..\..\Tools\MSYS\bin;..\..\Tools\MinGW\bin;..\..\..\Tools\MinGW\bin;..\..\..\tools\MinGW\lib\gcc-lib\mingw32\3.3.1;..\debug;.\debug;..\..\..\Tools;%path%;

+if  .%1==.  goto NVRAM_AUTO_GEN_ERROR_1

+

+if %WISDOM_CUSTOM_BUILD%INTERNAL==INTERNAL set WISDOM_CUSTOM_BUILD=FALSE

+

+if %WISDOM_CUSTOM_BUILD%==TRUE (set MSYS_FOLDER=MSYS_WISDOM) else set MSYS_FOLDER=MSYS

+if %WISDOM_CUSTOM_BUILD%==TRUE (if not exist tools\%MSYS_FOLDER% (if exist tools\MSYS (rename tools\MSYS %MSYS_FOLDER%)))

+

+SET NVRAM_AUTO_GEN_PATH=..\..\%7\..\nvram_auto_gen

+SET NVRAM_DEBUG_PATH=%NVRAM_AUTO_GEN_PATH%\debug

+

+echo %NVRAM_AUTO_GEN_PATH%

+

+cd Tools\NVRAMStatistic

+if not exist %NVRAM_AUTO_GEN_PATH%\debug mkdir %NVRAM_AUTO_GEN_PATH%\debug

+cd src

+

+SET ERROR_LOG=..\..\..\%7\log\nvram_gen.log

+SET FULL_LOG=..\..\..\%7\log\nvram_gen_full_log.log

+SET NVRAM_AUTO_GEN_PATH=..\..\..\%7\..\nvram_auto_gen

+SET NVRAM_DEBUG_PATH=%NVRAM_AUTO_GEN_PATH%\debug

+SET CKSYSDRV_PATH=..\..\..\%7\..\cksysdrv

+

+echo %NVRAM_AUTO_GEN_PATH%

+

+if not exist %NVRAM_AUTO_GEN_PATH% mkdir %NVRAM_AUTO_GEN_PATH%

+if not exist %CKSYSDRV_PATH% mkdir %CKSYSDRV_PATH%

+

+if exist %ERROR_LOG% del %ERROR_LOG%

+if exist %FULL_LOG% del %FULL_LOG%

+

+if exist %NVRAM_DEBUG_PATH%\*.d del %NVRAM_DEBUG_PATH%\*.d

+if exist %NVRAM_DEBUG_PATH%\nvram_auto_gen.dep del %NVRAM_DEBUG_PATH%\nvram_auto_gen.dep

+

+echo Parameter 1 = %1 >> %FULL_LOG%

+echo Parameter 2 = %2 >> %FULL_LOG%

+echo Parameter 3 = %3 >> %FULL_LOG%

+echo Parameter 4 = %4 >> %FULL_LOG%

+echo Parameter 5 = %5 >> %FULL_LOG%

+echo Parameter 6 = %6 >> %FULL_LOG%

+echo Parameter 7 = %7 >> %FULL_LOG%

+

+echo ************************************************************ >> %FULL_LOG%

+echo ************* Start to Generate NVRAM Info ***************** >> %FULL_LOG%

+echo ************************************************************ >> %FULL_LOG%

+echo [NVRAM Auto Gen]

+

+if .%5==.VENDOR (

+  if .%6==.TRUE goto VDR

+)

+if .%5==.LEVEL2_OBJ (

+  if not .%6==.FALSE goto SRC

+)

+if exist %NVRAM_DEBUG_PATH%\nvram_data_items.o del %NVRAM_DEBUG_PATH%\nvram_data_items.o

+:SRC

+if not .%5==. (echo LEVEL = %5 >> ..\..\%7\..\nvram_auto_gen\include\custom_option.txt)

+if not .%6==. (echo CUSTOM_RELEASE = %6 >> ..\..\%7\..\nvram_auto_gen\include\custom_option.txt)

+if exist %NVRAM_DEBUG_PATH%\nvram_auto_gen.exe    del %NVRAM_DEBUG_PATH%\nvram_auto_gen.exe

+if exist %NVRAM_DEBUG_PATH%\mmi_cache_gen.exe     del %NVRAM_DEBUG_PATH%\mmi_cache_gen.exe

+if exist %NVRAM_DEBUG_PATH%\nvram_common_config.o del %NVRAM_DEBUG_PATH%\nvram_common_config.o

+if exist %NVRAM_DEBUG_PATH%\nvram_cust_pack.o     del %NVRAM_DEBUG_PATH%\nvram_cust_pack.o

+if exist %NVRAM_DEBUG_PATH%\nvram_gen_util.o      del %NVRAM_DEBUG_PATH%\nvram_gen_util.o

+:VDR

+if not .%5==. (echo LEVEL = %5 >> ..\..\%7\..\nvram_auto_gen\include\custom_option.txt)

+if not .%6==. (echo CUSTOM_RELEASE = %6 >> ..\..\%7\..\nvram_auto_gen\include\custom_option.txt)

+if exist %NVRAM_DEBUG_PATH%\nvram_auto_gen.exe    del %NVRAM_DEBUG_PATH%\nvram_auto_gen.exe

+if exist %NVRAM_DEBUG_PATH%\mmi_cache_gen.exe     del %NVRAM_DEBUG_PATH%\mmi_cache_gen.exe

+if exist %NVRAM_DEBUG_PATH%\nvram_user_config.o   del %NVRAM_DEBUG_PATH%\nvram_user_config.o

+

+if exist %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics_bak.h   del %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics_bak.h

+if exist %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics.h   copy %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics.h %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics_bak.h

+

+echo #ifndef NVRAM_AUTO_GEN                    >      %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics.h

+echo #error NVRAM AUTO GEN not executed       >>      %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics.h

+echo #endif                                   >>      %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics.h

+echo generate nvram_lid_statistics.h success >> %FULL_LOG%

+

+echo #ifndef NVRAM_LID_STATISTIC_H             >      %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics_bak.h

+echo #define NVRAM_LID_STATISTIC_H            >>      %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics_bak.h

+echo #ifndef NVRAM_NOT_PRESENT                >>      %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics_bak.h

+echo #ifndef NVRAM_AUTO_GEN                   >>      %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics_bak.h

+echo #ifndef __RESOURCE_GEN_                  >>      %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics_bak.h

+echo #ifndef GEN_FOR_PC                       >>      %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics_bak.h

+echo #error "nvram_auto_gen fail!"            >>      %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics_bak.h

+echo #endif                                   >>      %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics_bak.h

+echo #endif                                   >>      %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics_bak.h

+echo #endif                                   >>      %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics_bak.h

+echo #define NVRAM_OTP_SIZE    10             >>      %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics_bak.h

+echo #define NVRAM_OTP_TOTAL   1              >>      %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics_bak.h

+echo #define NVRAM_CUSTPACK_TOTAL  13         >>      %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics_bak.h

+echo #define NVRAM_SECUPACK_SIZE  973         >>      %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics_bak.h

+echo #endif                                   >>      %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics_bak.h

+echo #endif                                   >>      %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics_bak.h

+

+echo generate nvram_lid_statistics_bak.h success >> %FULL_LOG%

+

+rem Always generate nvram_gen_trc.h to avoid nvram auto gen false alarm due to codegen fail

+if exist %NVRAM_AUTO_GEN_PATH%\nvram_gen_trc.h   del %NVRAM_AUTO_GEN_PATH%\nvram_gen_trc.h

+echo typedef enum {                     >>      %NVRAM_AUTO_GEN_PATH%\nvram_gen_trc.h

+echo    _NVRAM_EF_SYS_LID = 0,          >>      %NVRAM_AUTO_GEN_PATH%\nvram_gen_trc.h  

+echo    NVRAM_TRC_LID_TOTAL             >>      %NVRAM_AUTO_GEN_PATH%\nvram_gen_trc.h 

+echo }nvram_trc_lid_enum;               >>      %NVRAM_AUTO_GEN_PATH%\nvram_gen_trc.h 

+

+echo generate nvram_gen_trc.h success >> %FULL_LOG%

+

+

+rem Modify custom\common\hal\nvram\nvram_cust_pack.c to avoid include nvram_cuspack_table.c in AUTO gen stage

+echo *********************************************************** >> %FULL_LOG%

+echo ********  Generate fake nvram_custpack_table.c      ******* >> %FULL_LOG%

+echo *********************************************************** >> %FULL_LOG%

+

+

+rem :jump_sp_1

+rem if not exist %3\operator_mmi_cache_config.c goto gen_op

+rem echo #include "operator_mmi_cache_config.c" > operator_mmi_cache_wrapper.c

+rem goto make_nvram

+rem 

+rem :gen_op

+rem echo ************************************************************ >> %FULL_LOG%

+rem echo ******************  Gen operator config file *************** >> %FULL_LOG%

+rem echo ************************************************************ >> %FULL_LOG%

+rem echo #include "nvram_mmi_cache_defs.h"         >      operator_mmi_cache_wrapper.c

+rem echo #ifndef NVRAM_AUTO_GEN                   >>      operator_mmi_cache_wrapper.c

+rem echo #error "nvram_auto_gen fail!"            >>      operator_mmi_cache_wrapper.c

+rem echo #endif                                   >>      operator_mmi_cache_wrapper.c

+rem if %4 == 1 goto jump_sp_2

+rem echo mmi_cache_byte_entry operator_mmi_cache_byte[] = {{0xFF, NVRAM_APP_RESERVED, NVRAM_CACHE_ID_RESERVED, KAL_FALSE, 0xFF, "", "" ,"", "" ,""}}; >> operator_mmi_cache_wrapper.c

+rem echo mmi_cache_short_entry operator_mmi_cache_short[] = {{0xFF, NVRAM_APP_RESERVED, NVRAM_CACHE_ID_RESERVED, KAL_FALSE, 0xFF, 0xFF, "", "", "", "", "", ""}}; >> operator_mmi_cache_wrapper.c

+rem echo mmi_cache_double_entry operator_mmi_cache_double[] = {{0xFF, NVRAM_APP_RESERVED, NVRAM_CACHE_ID_RESERVED, KAL_FALSE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, "", "", "", "", "", "", "", "", "", "", "", ""}}; >> operator_mmi_cache_wrapper.c

+rem 

+rem echo generate operator_mmi_cache_wrapper.c success >> %FULL_LOG%

+

+:jump_sp_2

+

+:make_mmi_cache

+echo     [mmi_cache_gen]

+echo ************************************************************ >> %FULL_LOG%

+echo ******************  Build mmi_cache_gen.exe   ************* >> %FULL_LOG%

+echo ************************************************************ >> %FULL_LOG%

+..\..\%MSYS_FOLDER%\bin\make -s -j 1 mmi_cache_gen 1>>%FULL_LOG% 2>>%ERROR_LOG%

+type %ERROR_LOG% >> %FULL_LOG%

+if not exist %NVRAM_DEBUG_PATH%\mmi_cache_gen.exe goto NVRAM_AUTO_GEN_ERROR_2

+

+:execute_mmi_cache

+echo ************************************************************ >> %FULL_LOG%

+echo ******************  Execute mmi_cache_gen.exe ************* >> %FULL_LOG%

+echo ************************************************************ >> %FULL_LOG%

+%NVRAM_DEBUG_PATH%\mmi_cache_gen.exe %1 %2 %NVRAM_AUTO_GEN_PATH% 1>>%FULL_LOG% 2>>%ERROR_LOG%  

+if %errorlevel% EQU 0 (

+	type %ERROR_LOG% >> %FULL_LOG%

+	echo execute mmi_cache_gen done >> %FULL_LOG%

+) else (

+	type %ERROR_LOG% >> %FULL_LOG%

+	goto NVRAM_AUTO_GEN_ERROR_2

+)

+

+:make_nvram

+echo     [nvram_auto_gen]

+echo ************************************************************ >> %FULL_LOG%

+echo ******************  Build nvram_auto_gen.exe   ************* >> %FULL_LOG%

+echo ************************************************************ >> %FULL_LOG%

+..\..\%MSYS_FOLDER%\bin\make -s -j 1 nvram_auto_gen NVRAM_DEBUG_PATH=%NVRAM_DEBUG_PATH% 1>>%FULL_LOG% 2>>%ERROR_LOG%

+type %ERROR_LOG% >> %FULL_LOG%

+if not exist %NVRAM_DEBUG_PATH%\nvram_auto_gen.exe goto NVRAM_AUTO_GEN_ERROR_2

+

+if exist %NVRAM_DEBUG_PATH%\fs_quota_entry_dump.o del %NVRAM_DEBUG_PATH%\fs_quota_entry_dump.o

+if exist %NVRAM_DEBUG_PATH%\fs_quota_entry_dump.exe del %NVRAM_DEBUG_PATH%\fs_quota_entry_dump.exe

+

+:execute_nvram

+echo ************************************************************ >> %FULL_LOG%

+echo ******************  Execute nvram_auto_gen.exe ************* >> %FULL_LOG%

+echo ************************************************************ >> %FULL_LOG%

+%NVRAM_DEBUG_PATH%\nvram_auto_gen.exe %1 %2 %NVRAM_AUTO_GEN_PATH% 1>>%FULL_LOG% 2>>%ERROR_LOG%  

+if %errorlevel% EQU 0 (

+	type %ERROR_LOG% >> %FULL_LOG%

+	echo execute nvram_auto_gen done >> %FULL_LOG%

+	del %ERROR_LOG%

+) else (

+	type %ERROR_LOG% >> %FULL_LOG%

+	goto NVRAM_AUTO_GEN_ERROR_2

+)

+

+echo     [fs_quota_entry_dump]

+

+

+rem if exist ..\..\..\%7\log\fs_quota_entry_dump.log del ..\..\..\%7\log\fs_quota_entry_dump.log

+rem ..\..\%MSYS_FOLDER%\bin\make -s -j 1 fs_quota_entry_dump 2> ..\..\..\%7\log\fs_quota_entry_dump.log

+

+rem if not exist %NVRAM_DEBUG_PATH%\fs_quota_entry_dump.exe goto FS_QUOTA_GEN_ERROR_1

+rem fs_quota_entry_dump.exe

+

+if %errorlevel% EQU 2 (

+	goto FS_QUOTA_GEN_ERROR_2

+)

+

+rem ************************************************************

+rem ************* Both Procedure finished      *****************

+rem ************************************************************

+perl ..\..\pack_dep_gcc.pl %NVRAM_DEBUG_PATH%\nvram_auto_gen.dep %NVRAM_DEBUG_PATH% tools\NVRAMStatistic\src

+cd ..\..\..\

+

+echo --

+echo Complete!!

+goto done

+

+rem ************************************************************

+rem ************** Error Handling and Messages *****************

+rem ************************************************************

+:NVRAM_AUTO_GEN_ERROR_1

+copy %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics_bak.h %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics.h

+echo Miss arguments!

+goto NVRAM_AUTO_GEN_ERROR

+

+:NVRAM_AUTO_GEN_ERROR_2

+copy %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics_bak.h %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics.h

+echo NVRAM_AUTO_GEN_ERROR_2 >> %FULL_LOG%

+echo Error in NVRAM Generating Process!!

+echo Please Check nvram_gen_full_log.log!!

+type %FULL_LOG%

+cd ..\..\..\

+:NVRAM_AUTO_GEN_ERROR

+exit 3

+

+:NVRAM_COMPRESS_ERROR

+copy %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics_bak.h %NVRAM_AUTO_GEN_PATH%\nvram_lid_statistics.h

+echo NVRAM_COMPRESS_ERROR >> %FULL_LOG%

+exit 3

+

+:FS_QUOTA_GEN_ERROR_1

+cd ..\..\..\

+echo Error in FS_QUOTA Generating Process!!

+echo Please Check fs_quota_entry_dump.log!!

+type .\%7\log\fs_quota_entry_dump.log

+exit 3

+

+:FS_QUOTA_GEN_ERROR_2

+cd ..\..\..\

+echo Please set APP_STORAGE_IN_SYS_DRV as TRUE for those projects which disable phone drive! >> %FULL_LOG%

+echo Error in compile option dependency check!!

+echo Error in compile option dependency check!! >> %FULL_LOG%

+exit 3

+

+:done

+exit 0

diff --git a/mcu/tools/NVRAMStatistic/NVRAM_LID_structure_map.xml b/mcu/tools/NVRAMStatistic/NVRAM_LID_structure_map.xml
new file mode 100644
index 0000000..86e1e91
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/NVRAM_LID_structure_map.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<DB version="1.0">
+    <NVRAM_LIDs>
+        <NVRAM_LID name="NVRAM_EF_SML_LID" id="61201" type_name="nvram_sml_context_struct" is_struct="true" />
+        <NVRAM_LID name="NVRAM_EF_SIM_LOCK_LID" id="61202" type_name="nvram_sml_tmo_context_struct" is_struct="true" />
+        <NVRAM_LID name="NVRAM_EF_L4_SML_TMO_MOVIAL_SIM_LOCK_LID" id="61248" type_name="nvram_sml_tmo_movial_sim_lock_context_struct_type" is_struct="true" />
+        <NVRAM_LID name="NVRAM_EF_L4_SML_TMO_MOVIAL_CORR_ID_LID" id="61249" type_name="nvram_sml_tmo_movial_corr_id_struct_type" is_struct="true" />
+        <NVRAM_LID name="NVRAM_EF_SML_MAX_RETRY_COUNT_LID" id="61230" type_name="nvram_sml_max_retry_count_struct" is_struct="true" />
+        <NVRAM_LID name="NVRAM_EF_SML_GBLOB_LID" id="61231" type_name="nvram_sml_gblob_s_context_struct" is_struct="true" />
+        <NVRAM_LID name="NVRAM_EF_SML_GBLOB_KEY_LID" id="61232"  type_name="nvram_sml_gblob_key_s_context_struct" is_struct="true" />
+        <NVRAM_LID name="NVRAM_EF_SML_S_LID" id="61233" type_name="nvram_sml_context_s_struct" is_struct="true" />
+        <NVRAM_LID name="NVRAM_EF_SML_NONCE_LID" id="61227" type_name="nvram_ef_sml_nonce_struct" is_struct="true" />
+        <NVRAM_LID name="NVRAM_EF_SML_UNLOCK_CODE_LID" id="61228" type_name="nvram_ef_sml_unlock_code_struct" is_struct="true" />
+        <NVRAM_LID name="NVRAM_EF_SML_SIGNATURE_LID" id="61229" type_name="nvram_ef_sml_signature_struct" is_struct="true" />
+        <NVRAM_LID name="NVRAM_EF_SUBSIDY_LOCK_LID" id="61224" type_name="nvram_sml_sl_blob_context_struct" is_struct="true" />
+        <NVRAM_LID name="NVRAM_EF_SUBSIDY_LOCK_ODM_DATA_LID" id="61225" type_name="nvram_sml_sl_odm_data_struct" is_struct="true" />
+        <NVRAM_LID name="NVRAM_EF_L4_CARRIER_RESTRICTION_LID" id="61236" type_name="nvram_smu_carrier_match_context_struct_type" is_struct="true" />
+        <NVRAM_LID name="NVRAM_EF_L4_ATT_SIM_LOCK_LID" id="61240" type_name="nvram_sml_att_context_struct_type" is_struct="true" />
+        <NVRAM_LID name="NVRAM_EF_L4_SML_VZW_SIM_LOCK_LID" id="61241" type_name="nvram_sml_vzw_sim_lock_context_struct_type" is_struct="true" />
+        <NVRAM_LID name="NVRAM_EF_L4_SML_VZW_SIM_LOCK_DEVICE_KEY_LID" id="61242" type_name="nvram_sml_vzw_sim_lock_device_key_struct_type" is_struct="true" />
+        <NVRAM_LID name="NVRAM_EF_L4_SML_VZW_RSU_DELAY_TIMER_LID" id="61243" type_name="nvram_sml_vzw_rsu_delay_timer_struct_type" is_struct="true" />
+        <NVRAM_LID name="NVRAM_EF_L4_SML_OP129_LID" id="61246" type_name="nvram_sml_op129_sim_lock_rawdata_struct_type" is_struct="true" />
+        <NVRAM_LID name="NVRAM_EF_L4_PORTLOCK_LID" id="61253" type_name="nvram_l4c_portlock_struct" is_struct="true" />
+        <NVRAM_LID name="NVRAM_EF_NVRAM_LOCK_LID" id="61446" type_name="nvram_ef_nvram_lock_dummy_struct" is_struct="true" />
+        <NVRAM_LID name="NVRAM_EF_SYS_LID" id="61440" type_name="nvram_ef_sys_dummy_struct" is_struct="true" />
+        <NVRAM_LID name="NVRAM_EF_READ_RESERVED_LID" id="61447" type_name="nvram_ef_read_reserved_dummy_struct" is_struct="true" />
+    </NVRAM_LIDs>
+</DB>
diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/README.txt b/mcu/tools/NVRAMStatistic/autogen_v2/README.txt
new file mode 100644
index 0000000..4b6a92c
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/README.txt
@@ -0,0 +1 @@
+Scripts for nvram auto gen refactory
diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/autogen/__init__.py b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/__init__.py
diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/autogen/main.py b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/main.py
new file mode 100644
index 0000000..0a8c150
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/main.py
@@ -0,0 +1,161 @@
+import operator
+import sys
+import os
+import platform
+
+from .src.initconfig import logical_data_item_table
+from .src.initconfig import const_value
+from .src.initconfig import global_value
+from .src.initconfig import LtableEntry
+from .src.initconfig import printf
+from .src import tableconstructor
+from .src import sys_cache_generator
+from .src import gen_cache_info
+from .src import gen_cat_file
+from .src import gen_lid_information
+from .src import gen_statistic
+from .src import mcf_ota_helper
+from .src import custpackhelper
+from .src import secupackhelper
+from .src import buildtimecheck
+from .src import tableconstructor_win
+
+from .src import gen_assign_entry
+
+
+def main(path):
+    """
+     args:
+        path: gen file output path, path + "nvram_auto_gen" + filename
+    """
+    # set path    
+    global_value.logging_path = path
+    global_value.path = path
+    global_value.autogen_path = os.path.join(global_value.path, "nvram_auto_gen")
+    global_value.log_path = os.path.join(global_value.path, "bin", "log")
+    
+    # check path exist
+    if not os.access(global_value.autogen_path, os.F_OK):
+        printf("error: folder no exist: %s" % global_value.autogen_path)
+        sys.exit(2)
+    if not os.access(global_value.log_path, os.F_OK):
+        printf("error: folder no exist: %s" % global_value.log_path)
+        sys.exit(2)
+	
+	global_value.logger_config()
+    global_value.logger.info("========main========")
+    # set platform
+    global_value.platform = platform.system()
+    if global_value.platform != "Windows" and global_value.platform != "Linux":
+        printf("platform error: platform is not windows or linux!")
+        printf("platform.system() = %s" % platform.system())
+        global_value.logger.error("platform error: platform is not windows or linux!")
+        global_value.logger.error("platform.system() = %s", platform.system())
+        sys.exit(1)
+    
+    global_value.logger.info("path = %s, logging_path = %s, platform = %s", global_value.path, global_value.logging_path
+                             , global_value.platform)
+    
+    global_value.pars_macro_info()
+    
+    if global_value.platform == "Windows":  # windows
+        tableconstructor_win.parse_segment_info_win()
+    elif global_value.platform == "Linux":  # linux  
+        tableconstructor.pars_segment_info()
+    else:
+        pass
+    
+    tableconstructor.parse_lid_table()
+    tableconstructor.parse_lid_item_data()
+    tableconstructor.statistic_lid_item_data()
+
+    # tmp write ltable for NVDB test
+    # tableconstructor.write_logical_table()
+    
+    # sort ,key is lid
+    sort_key = operator.attrgetter('lid')
+    logical_data_item_table.sort(key=sort_key)
+    
+    # # assign entry
+    global_value.logger.info("====================")
+    global_value.logger.info("nvram_gen_assign_entry")
+    gen_assign_entry.nvram_gen_assign_entry()
+    
+    # gen nvram_cache_info.c and nvram_cache_info.h
+    global_value.logger.info("====================")
+    global_value.logger.info("nvram_gen_cache_info")
+    gen_cache_info.nvram_gen_cache_info()
+    
+    # gen custom_nvram_lid_cat.xml
+    global_value.logger.info("====================")
+    global_value.logger.info("nvram_gen_cat_xml")
+    gen_cat_file.nvram_gen_cat_xml()
+    
+    # gen ~nvram_lid_information.log and ~nvram_lid_size.log
+    global_value.logger.info("====================")
+    global_value.logger.info("nvram_gen_info_size_log")
+    gen_lid_information.nvram_gen_info_size_log()
+    
+    # gen nvram_lid_statistics_bak.h
+    global_value.logger.info("====================")
+    global_value.logger.info("nvram_gen_statistic")
+    gen_statistic.nvram_gen_statistic()
+    
+    # gen custom_nvram_restore.c and nvram_restore_dom_new.h
+    global_value.logger.info("====================")
+    global_value.logger.info("nvram_gen_restore_function")
+    sys_cache_generator.nvram_gen_restore_function()    # win || linux
+    
+    # gen nvram_custpack_table.c and nvram_custpack_table_lid.c
+    if (global_value.macro & const_value.__MMI_FMI__) and (not global_value.macro & const_value.__L1_STANDALONE__):
+        global_value.logger.info("====================")
+        global_value.logger.info("nvram_gen_custpack_table")
+        custpackhelper.nvram_gen_custpack_table()
+    
+    # gen custom_nvram_secro.c and custom_nvram_secro_tbl.c
+    if True:  # global_value.macro & const_value.__VENDOR_RELEASE__:
+        global_value.logger.info("====================")
+        global_value.logger.info("nvram_gen_secro")
+        secupackhelper.nvram_gen_secro()    # win || linux
+    
+    # gen nvram_ltable_List.h
+    global_value.logger.info("====================")
+    global_value.logger.info("nvram_gen_ltable_list")
+    mcf_ota_helper.nvram_gen_ltable_list()
+    
+    # gen nvram_lid_list_for_mcf.h
+    global_value.logger.info("====================")
+    global_value.logger.info("nvram_gen_mcf_ota_lid_list")
+    mcf_ota_helper.nvram_gen_mcf_ota_lid_list()
+    
+    global_value.logger.info("====================")
+    global_value.logger.info("build time check: begin")
+    # build time check:lid enum overlapping
+    global_value.logger.info("build time check: lid enum overlapping")
+    buildtimecheck.check_lid_enum_overlapping()
+    buildtimecheck.check_lid_fileprefix_overlapping()
+    # build time check:write protect attr white list
+    global_value.logger.info("build time check: write protect attr white list ")
+    buildtimecheck.check_write_protect()
+    # build time check:cate attr confilicts
+    global_value.logger.info("build time check: cate attr confilicts")
+    buildtimecheck.nvram_gen_check_cate_attr_conflicts()
+    # build time check:hash key check
+    if (global_value.macro & const_value.__NVRAM_LID_HASH_CHECK__) and (global_value.macro & const_value.__MTK_INTERNAL__):
+        global_value.logger.info("build time check: hash key check")
+        buildtimecheck.check_lid_hash_key()
+    # build time check:special lid parameter
+    global_value.logger.info("build time check: special lid parameter")
+    buildtimecheck.check_special_lid_parameter()
+    global_value.logger.info("build time check: end")
+    
+    # gen custom_nvram_database.h
+    global_value.logger.info("build time check: gen custom_nvram_database")
+    tmp_path = os.path.join(path, "nvram_auto_gen", "custom_nvram_database.h")
+    print("custom_nvram database path: {}".format(tmp_path) )
+    f = open(tmp_path, "w")
+    f.close()
+    global_value.logger.info("build time check: end")
+
+if __name__ == '__main__':
+    main()
diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/__init__.py b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/__init__.py
diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/buildtimecheck.py b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/buildtimecheck.py
new file mode 100644
index 0000000..689ee42
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/buildtimecheck.py
@@ -0,0 +1,175 @@
+import hashlib
+import sys
+
+from .initconfig import logical_data_item_table
+from .initconfig import const_value
+from .initconfig import global_value
+
+nvram_white_list_for_multiple_attr = ("NVRAM_EF_SYS_LID", "NVRAM_EF_IMEI_IMEISV_LID", "NVRAM_EF_NVRAM_LOCK_LID")
+con_type_enum = {
+    "attr_attr": 0,
+    "cate_attr": 1,
+    "cate_cate": 2
+
+}
+nvram_cate_attr_conflict_table = [
+    # attribute conflicts
+    [con_type_enum["attr_attr"], const_value.NVRAM_ATTR_MULTIPLE, const_value.NVRAM_ATTR_PACKAGE],
+    [con_type_enum["attr_attr"], const_value.NVRAM_ATTR_OTA_RESET, const_value.NVRAM_ATTR_RESERVE_BACKWARD],
+    [con_type_enum["attr_attr"], const_value.NVRAM_ATTR_RAW_DATA, (const_value.NVRAM_ATTR_PACKAGE | const_value.NVRAM_ATTR_MULTIPLE | const_value.NVRAM_ATTR_RING)],
+    [con_type_enum["attr_attr"], const_value.NVRAM_ATTR_RAW_DATA, (const_value.NVRAM_ATTR_WRITEPROTECT | const_value.NVRAM_ATTR_CONFIDENTIAL | const_value.NVRAM_ATTR_MSP)],
+
+    # category conflicts
+    [con_type_enum["cate_cate"], const_value.NVRAM_CATEGORY_FUNC_DEFAULT, (const_value.NVRAM_CATEGORY_CUSTPACK | const_value.NVRAM_CATEGORY_SECUPACK)],
+    [con_type_enum["cate_cate"], const_value.NVRAM_CATEGORY_CALIBRAT, ~(const_value.NVRAM_CATEGORY_FUNC_DEFAULT | const_value.NVRAM_CATEGORY_CUSTPACK | const_value.NVRAM_CATEGORY_SECUPACK)],
+    [con_type_enum["cate_cate"], const_value.NVRAM_CATEGORY_IMPORTANT, (const_value.NVRAM_CATEGORY_IMPORTANT_L1 | const_value.NVRAM_CATEGORY_IMPORTANT_L4 | const_value.NVRAM_CATEGORY_INTERNAL | const_value.NVRAM_CATEGORY_OTP)],
+    [con_type_enum["cate_cate"], const_value.NVRAM_CATEGORY_IMPORTANT_L4, (const_value.NVRAM_CATEGORY_IMPORTANT_L1 | const_value.NVRAM_CATEGORY_INTERNAL | const_value.NVRAM_CATEGORY_OTP)],
+    [con_type_enum["cate_cate"], const_value.NVRAM_CATEGORY_IMPORTANT_L1, (const_value.NVRAM_CATEGORY_INTERNAL | const_value.NVRAM_CATEGORY_OTP)],
+    [con_type_enum["cate_cate"], const_value.NVRAM_CATEGORY_INTERNAL, (const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE | const_value.NVRAM_CATEGORY_OTP)],
+    [con_type_enum["cate_cate"], const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE, (const_value.NVRAM_CATEGORY_CUSTPACK | const_value.NVRAM_CATEGORY_SECUPACK | const_value.NVRAM_CATEGORY_OTP)],
+    [con_type_enum["cate_cate"], const_value.NVRAM_CATEGORY_CUSTPACK, (const_value.NVRAM_CATEGORY_SECUPACK | const_value.NVRAM_CATEGORY_OTP)],
+    [con_type_enum["cate_cate"], const_value.NVRAM_CATEGORY_SECUPACK, const_value.NVRAM_CATEGORY_OTP],
+
+    # attribute & category conflicts
+    [con_type_enum["cate_attr"], const_value.NVRAM_CATEGORY_CALIBRAT, (const_value.NVRAM_ATTR_MULTIPLE | const_value.NVRAM_ATTR_MSP | const_value.NVRAM_ATTR_RING)],
+    [con_type_enum["cate_attr"], const_value.NVRAM_CATEGORY_CALIBRAT, (const_value.NVRAM_ATTR_OTA_RESET | const_value.NVRAM_ATTR_RESERVE_BACKWARD)],
+    [con_type_enum["cate_attr"], const_value.NVRAM_CATEGORY_INTERNAL, const_value.NVRAM_ATTR_PACKAGE],
+    [con_type_enum["cate_attr"], const_value.NVRAM_CATEGORY_SECUPACK, (const_value.NVRAM_ATTR_PACKAGE | const_value.NVRAM_ATTR_RAW_DATA)],
+    [con_type_enum["cate_attr"], const_value.NVRAM_CATEGORY_CUSTPACK, const_value.NVRAM_ATTR_RAW_DATA],
+    [con_type_enum["cate_attr"], const_value.NVRAM_CATEGORY_FUNC_DEFAULT, const_value.NVRAM_ATTR_RAW_DATA],
+    [con_type_enum["cate_attr"], const_value.NVRAM_CATEGORY_OTP, const_value.NVRAM_ATTR_AVERAGE | const_value.NVRAM_ATTR_GEN_DEFAULT | const_value.NVRAM_ATTR_RESERVE_BACKWARD | const_value.NVRAM_ATTR_RAW_DATA]
+
+]
+
+
+def check_lid_fileprefix_overlapping():
+    check_result = True
+    for i in range(len(logical_data_item_table)):
+        ldi1 = logical_data_item_table[i]
+        for j in range(i + 1, len(logical_data_item_table)):
+            ldi2 = logical_data_item_table[j]
+            if ldi1.FilePrefix == ldi2.FilePrefix:
+                check_result = False
+                global_value.logger.error(
+                    "duplicated fileprefix and fileverno %s %s of %s and %s\n",
+                    ldi1.FilePrefix, ldi1.FileVerno, ldi1.str_LID, ldi2.str_LID)
+    if not check_result:
+        sys.exit("duplicated fileprefix and fileverno!")
+    
+
+def check_lid_enum_overlapping():
+    check_result = True
+    if len(logical_data_item_table) < 2:
+        global_value.logger.error("Invalid total_lid during CheckLidOverlapping()")
+        sys.exit("Invalid total_lid during CheckLidOverlapping()")
+    for i in range(len(logical_data_item_table)):
+        for j in range(i + 1, len(logical_data_item_table)):
+            if logical_data_item_table[i].lid == logical_data_item_table[j].lid:
+                check_result = False
+                global_value.logger.error(
+                    "%d:%s and %d:%s have same enum value, please check if LID duplicated def or enum"
+                    " value overlapped", i, logical_data_item_table[i].lid, j, logical_data_item_table[j].lid)
+    if not check_result:
+        global_value.logger.error("Please contact NVRAM owner if your NVRAM sub-group size should be enlarged")
+        sys.exit("Please contact NVRAM owner if your NVRAM sub-group size should be enlarged")
+
+
+def check_write_protect():
+    check_result = True
+    for ldi in logical_data_item_table:
+        if ldi.lid == 0 or ldi.size == 0 or ldi.total_records == 0:
+            continue
+        if not ldi.attr & const_value.NVRAM_ATTR_WRITEPROTECT:
+            continue
+        in_list = False
+        for str in nvram_white_list_for_multiple_attr:
+            if ldi.str_LID == str:
+                in_list = True
+                break
+        if not in_list:
+            check_result = False
+            global_value.logger.error("LID %s have WRITE_PROTECT attribute but not in white list!!", ldi.str_LID)
+    if not check_result:
+        global_value.logger.error("Please contact NVRAM owner if your really need this attribute for the LID(s)")
+        sys.exit("Please contact NVRAM owner if your really need this attribute for the LID(s)")
+
+
+def check_special_lid_parameter():
+    check_result = True
+    for ldi in logical_data_item_table:
+        if ldi.attr & const_value.NVRAM_ATTR_RAW_DATA:
+            if ldi.total_records > 1:
+                check_result = False
+                global_value.logger.error("NVRAM_ATTR_RAW_DATA can not support multiple record.")
+            if ldi.p_default_value != const_value.NVRAM_EF_ZERO_DEFAULT:
+                check_result = False
+                global_value.logger.error("NVRAM_ATTR_RAW_DATA can only use NVRAM_EF_ZERO_DEFAULT.")
+    if not check_result:
+        sys.exit("NVRAM_ATTR_RAW_DATA can not support multiple record ,and can only use NVRAM_EF_ZERO_DEFAULT.")
+
+
+def hash_md5(strs):
+    m = hashlib.md5()
+    m.update(strs.encode(encoding='utf-8'))
+    list_a = list(m.hexdigest())
+    list_re = []
+    for i in range(16):
+        list_re.append(int(list_a[2*i], 16) * 16 + int(list_a[2*i + 1], 16))
+    return list_re
+
+
+def check_lid_hash_key():
+    first_print = True
+    if global_value.macro & const_value.__NVRAM_LID_HASH_CHECK__ and global_value.macro & const_value.__MTK_INTERNAL__:  # __NVRAM_LID_HASH_CHECK__ and __MTK_INTERNAL__
+        for ldi in logical_data_item_table:
+            global_value.logger.debug("check lid: %s hash key: 0x%08x", ldi.str_LID, ldi.hash_key)
+            if ldi.lid & 0xF000 == 0xF000:
+                global_value.logger.debug("internal lid {}, no check!".format(ldi.str_LID))
+                continue
+            if not (ldi.FilePrefix[0] == 'C' and ldi.FilePrefix[1] == 'U'):
+                strbuf = str(ldi.lid) + ";" + ldi.str_LID + ";" + ldi.FilePrefix + ";" + ldi.FileVerno + ";"
+                digest = hash_md5(strbuf)
+                hash = (digest[4] << 4 | digest[5] >> 4) << 24
+                hash |= (digest[5] << 4 | digest[6] >> 4) << 16
+                hash |= (digest[6] << 4 | digest[7] >> 4) << 8
+                hash |= (digest[7] << 4 | digest[8] >> 4)
+                hash &= 0xffffffff
+                if hash != ldi.hash_key:
+                    if first_print:
+                        global_value.logger.error(
+                            "Need register LID http://wiki.mediatek.inc/display/NVRAM/How+to+apply+LID+HASH+key")
+                        global_value.logger.error(
+                            "This feature is just internal use. Please set NVRAM_LID_HASH_CHECK = FALSE for customer.")
+                        first_print = False
+                    global_value.logger.error("%s (0x%08x) hash key is not match.", ldi.str_LID, ldi.hash_key)
+                    global_value.logger.error("hash in str:%d;%s;%s;%s;", ldi.lid, ldi.str_LID, ldi.FilePrefix, ldi.FileVerno)
+                    global_value.logger.error("hash out: %x", hash)
+        if not first_print:
+            sys.exit("HASH key check error")
+
+
+def nvram_gen_check_cate_attr_conflicts():
+    check_result = True
+
+    for ldi in logical_data_item_table:
+        for check_cond in nvram_cate_attr_conflict_table:
+            if check_cond[0] == con_type_enum["attr_attr"]:
+                if ((ldi.attr & check_cond[1]) != 0) and ((ldi.attr & (~check_cond[1]) & check_cond[2]) != 0):
+                    check_result = False
+                    global_value.logger.error("LID %s have conflict attributes ", ldi.str_LID)
+            elif check_cond[0] == con_type_enum["cate_attr"]:
+                if ((ldi.category & check_cond[1]) != 0) and ((ldi.attr & check_cond[2]) != 0):
+                    check_result = False
+                    global_value.logger.error("LID %s have conflict attributes with category ", ldi.str_LID)
+            elif check_cond[0] == con_type_enum["cate_cate"]:
+                if ((ldi.category & check_cond[1]) != 0) and ((ldi.category & (~check_cond[1]) & check_cond[2]) != 0):
+                    check_result = False
+                    global_value.logger.error("LID %s have conflict categories ", ldi.str_LID)
+            else:
+                pass
+    if not check_result:
+        global_value.logger.error("Please adjust LID's attributes and/or categories")
+        sys.exit("Please adjust LID's attributes and/or categories")
+
+
+
diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/custpackhelper.py b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/custpackhelper.py
new file mode 100644
index 0000000..4277980
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/custpackhelper.py
@@ -0,0 +1,56 @@
+import os
+
+from .initconfig import global_value
+from .initconfig import logical_data_item_table
+from .initconfig import const_value
+from .initconfig import printf
+from .initconfig import autogen_open_file
+
+
+def nvram_gen_custpack_table():
+    """ gen file: nvram_custpack_table.c / nvram_custpack_table_lid.c """
+    fd_1 = autogen_open_file(global_value.autogen_path, "nvram_custpack_table.c", "w+")
+    fd_2 = autogen_open_file(global_value.autogen_path, "nvram_custpack_table_lid.c", "w+")
+
+    printf("#if defined(NVRAM_INTERNAL_USE) && !defined(NVRAM_NOT_PRESENT)\n", file=fd_1, end="")
+    printf("/********************************************************\n", file=fd_1, end="")
+    printf(" *  This file is generated automatically by nvram_auto_gen\n", file=fd_1, end="")
+    printf(" *  Please do not modify it here manually\n", file=fd_1, end="")
+    printf(" ***********************************************************/\n", file=fd_1, end="")
+
+    printf("#if defined(NVRAM_LTABLE_C_ONLY)\n", file=fd_2, end="")
+    printf("const custpack_nvram_header custpack_nvram_ptr = \n", file=fd_1, end="")
+    printf("const nvram_custpack_lid_tbl_struct custpack_nvram_lid_tal = \n", file=fd_2, end="")
+    printf("{\n", file=fd_1, end="")
+    printf("{\n", file=fd_2, end="")
+    printf("    0,\n", file=fd_1, end="")
+    printf("    0,\n", file=fd_2, end="")
+    printf("    {\n", file=fd_1, end="")
+    printf("    {\n", file=fd_2, end="")
+
+    start = global_value.NVRAM_EF_START
+    j = 0
+    for i in range(start, len(logical_data_item_table)):
+        ldi = logical_data_item_table[i]
+        if ldi.lid == 0 or ldi.size == 0 or ldi.total_records == 0:
+            continue
+        if ldi.category & const_value.NVRAM_CATEGORY_CUSTPACK:
+            j += 1
+            printf("        %s" % ldi.str_default_value, file=fd_1, end="")
+            printf("        %d" % ldi.lid, file=fd_2, end="")
+            if j != global_value.custpack_total_to_verify:
+                printf(",", file=fd_1, end="")
+                printf(",", file=fd_2, end="")
+            printf("\n", file=fd_1, end="")
+            printf("\n", file=fd_2, end="")
+    printf("    }\n", file=fd_1, end="")
+    printf("    }\n", file=fd_2, end="")
+    printf("};\n", file=fd_1, end="")
+    printf("};\n", file=fd_2, end="")
+    printf("#endif /* NVRAM_INTERNAL_USE && NVRAM_NOT_PRESENT */\n\n", file=fd_1, end="")
+    printf("#endif\n\n", file=fd_2, end="")
+
+    fd_1.close()
+    fd_2.close()
+
+
diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/gen_assign_entry.py b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/gen_assign_entry.py
new file mode 100644
index 0000000..24a7a5f
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/gen_assign_entry.py
@@ -0,0 +1,383 @@
+import sys
+
+from .initconfig import logical_data_item_table
+from .initconfig import const_value
+from .initconfig import global_value
+from .initconfig import get_checksum_size
+
+
+def adjust_attr_cate_i(ldi):
+    """Do not need multiple attribute if nvram saved on nor flash"""
+    if ldi.total_records < 2 and (
+            ldi.attr & const_value.NVRAM_ATTR_MULTIREC_READ or ldi.attr & const_value.NVRAM_ATTR_MULTI_DEFAULT):
+        global_value.logger.error(
+            "Can't Set the NVRAM_ATTR_MULTIREC_READ or NVRAM_ATTR_MULTI_DEFAULT for the lid with only one record, %d, %s",
+            ldi.lid, ldi.str_LID)
+        sys.exit("Can't Set the NVRAM_ATTR_MULTIREC_READ or NVRAM_ATTR_MULTI_DEFAULT for the lid with only one record")
+    if ldi.p_default_value == const_value.NVRAM_EF_FF_DEFAULT or ldi.p_default_value == const_value.NVRAM_EF_ZERO_DEFAULT:
+        check_result = False
+        if (ldi.attr & const_value.NVRAM_ATTR_GEN_DEFAULT) and not(ldi.category & const_value.NVRAM_CATEGORY_IMPORTANT_L4):
+            if global_value.macro & const_value.__NVRAM_UT_TEST__:
+                if ldi.lid < const_value.NVRAM_EF_NVRAM_UNIT_TEST_LID or ldi.lid > const_value.NVRAM_EF_NVRAM_UNIT_TEST_LID_END:
+                    check_result = True
+                else:
+                    check_result = False
+            else:
+                check_result = True
+        if check_result:
+            global_value.logger.error(
+                "Can't Set the NVRAM_ATTR_GEN_DEFAULT attribute for the lid with Zero of FF default value, %d, %s",
+                ldi.lid, ldi.str_LID)
+            sys.exit("Can't Set the NVRAM_ATTR_GEN_DEFAULT attribute for the lid with Zero of FF default value")
+    if (ldi.category & const_value.NVRAM_CATEGORY_IMPORTANT_L4) and not(ldi.attr & const_value.NVRAM_ATTR_GEN_DEFAULT):
+        global_value.logger.error(
+                "NVRAM_CATEGORY_IMPORTANT_L4 must have NVRAM_ATTR_GEN_DEFAULT attribute!!, %d, %s",
+                ldi.lid, ldi.str_LID)
+        sys.exit("NVRAM_CATEGORY_IMPORTANT_L4 must have NVRAM_ATTR_GEN_DEFAULT attribute!!")
+
+def adjust_attr_cate_ii(ldi):
+    """ MULTIPLE / BACKUP_RAW / BACKUP_FAT are mutually exclusive """
+    if ldi.category & const_value.NVRAM_CATEGORY_CALIBRAT:
+        if ldi.attr & const_value.NVRAM_ATTR_RESERVE_BACKWARD or ldi.attr & const_value.NVRAM_ATTR_MULTIPLE:
+            global_value.logger.error(
+                "Can't Set NVRAM_ATTR_MULTIPLE/NVRAM_ATTR_RESERVE_BACKWARD for Calibrate Lid, %d, %s",
+                ldi.lid, ldi.str_LID)
+            sys.exit("Can't Set NVRAM_ATTR_MULTIPLE/NVRAM_ATTR_RESERVE_BACKWARD for Calibrate Lid")
+        if global_value.macro & const_value.__NVRAM_BACKUP_DISK_FAT__:
+            if ldi.attr & const_value.NVRAM_ATTR_MULTIPLE or ldi.attr & const_value.NVRAM_ATTR_BACKUP_RAW:
+                global_value.logger.error(
+                    "Can't Set the NVRAM_ATTR_MULTIPLE/NVRAM_ATTR_BACKUP_RAW for Calibrate, %d, %s",
+                    ldi.lid, ldi.str_LID)
+                sys.exit("Can't Set the NVRAM_ATTR_MULTIPLE/NVRAM_ATTR_BACKUP_RAW for Calibrate")
+            if (ldi.attr & const_value.NVRAM_ATTR_BACKUP_FAT) == 0:
+                global_value.logger.error(
+                    "Should set the NVRAM_ATTR_BACKUP_FAT for Calibrate, %d, %s",
+                    ldi.lid, ldi.str_LID)
+                sys.exit("Should set the NVRAM_ATTR_BACKUP_FAT for Calibrate")
+        elif global_value.macro & const_value.__NVRAM_BACKUP_DISK_RAW__:
+            if ldi.attr & const_value.NVRAM_ATTR_MULTIPLE or ldi.attr & const_value.NVRAM_ATTR_BACKUP_FAT:
+                global_value.logger.error(
+                    "Can't Set the NVRAM_ATTR_MULTIPLE/NVRAM_ATTR_BACKUP_FAT for Calibrate, %d, %s",
+                    ldi.lid, ldi.str_LID)
+                sys.exit("Can't Set the NVRAM_ATTR_MULTIPLE/NVRAM_ATTR_BACKUP_FAT for Calibrate")
+            if (ldi.attr & const_value.NVRAM_ATTR_BACKUP_RAW) == 0:
+                global_value.logger.error(
+                    "Should set the NVRAM_ATTR_BACKUP_RAW for Calibrate, %d, %s",
+                    ldi.lid, ldi.str_LID)
+                sys.exit("Should set the NVRAM_ATTR_BACKUP_RAW for Calibrate")
+        else:
+            if (not global_value.macro & const_value.__LOW_COST_SUPPORT_COMMON__) and (
+                    not global_value.macro & const_value.__CCCIFS_SUPPORT__) and (
+                    not global_value.macro & const_value.__FS_RAMDISK__):
+                if (ldi.attr & const_value.NVRAM_ATTR_MULTIPLE) == 0:
+                    global_value.logger.error(
+                        "Should set the NVRAM_ATTR_MULTIPLE for Calibrate under this scenario, %d, %s",
+                        ldi.lid, ldi.str_LID)
+                    sys.exit("Should set the NVRAM_ATTR_MULTIPLE for Calibrate under this scenario")
+            if ldi.attr & const_value.NVRAM_ATTR_BACKUP_RAW or ldi.attr & const_value.NVRAM_ATTR_BACKUP_FAT:
+                global_value.logger.error(
+                    "Can't Set the NVRAM_ATTR_BACKUP_RAW/NVRAM_ATTR_BACKUP_FAT for Calibrate, %d, %s",
+                    ldi.lid, ldi.str_LID)
+                sys.exit("Can't Set the NVRAM_ATTR_BACKUP_RAW/NVRAM_ATTR_BACKUP_FAT for Calibrate")
+
+
+def adjust_attr_cate_iii(ldi):
+    """just apply to smartphone
+        1: When AP side clean boot, nvram will reset all lid
+        2: When Modem side restore factory, nvram only reset data item in NVD_DATA
+           and don't care about data item in folder A & B
+        3: So, turn off NVRAM_CATEGORY_FACTORY
+    """
+    if global_value.macro & const_value.__CCCIFS_SUPPORT__:
+        if ldi.category & const_value.NVRAM_CATEGORY_IMPORTANT or ldi.category & const_value.NVRAM_CATEGORY_IMPORTANT_L4:
+            if ldi.attr & const_value.NVRAM_ATTR_RESERVE_BACKWARD:
+                global_value.logger.error(
+                    "Can't Set the NVRAM_ATTR_RESERVE_BACKWARD for Important/Important_L4, %d, %s",
+                    ldi.lid, ldi.str_LID)
+                sys.exit("Can't Set the NVRAM_ATTR_RESERVE_BACKWARD for Important/Important_L4")
+            if (ldi.attr & const_value.NVRAM_ATTR_COMMITTED) == 0:
+                global_value.logger.error(
+                    "Suggest Set the NVRAM_ATTR_COMMITTED for Important/Important_L4, %d, %s",
+                    ldi.lid, ldi.str_LID)
+                sys.exit("Suggest Set the NVRAM_ATTR_COMMITTED for Important/Important_L4")
+
+
+def adjust_attr_cate_iv(ldi):
+    """
+    OTP category cannot use with many attribute together. Because it cannot be reset
+    OTP category also cannot use with other category together
+    """
+    if global_value.macro & const_value.__NVRAM_OTP__:
+        if ldi.category & const_value.NVRAM_CATEGORY_OTP:
+            if ldi.attr & const_value.NVRAM_ATTR_WRITEPROTECT or ldi.attr & const_value.NVRAM_ATTR_MULTIPLE or ldi.attr & const_value.NVRAM_ATTR_MSP or ldi.attr & const_value.NVRAM_ATTR_OTA_RESET:
+                global_value.logger.error(
+                    "Can't Set NVRAM_ATTR_WRITEPROTECT/NVRAM_ATTR_MULTIPLE/NVRAM_ATTR_MSP/NVRAM_ATTR_OTA_RESET for OTP, %d, %s",
+                    ldi.lid, ldi.str_LID)
+                sys.exit(
+                    "Can't Set NVRAM_ATTR_WRITEPROTECT/NVRAM_ATTR_MULTIPLE/NVRAM_ATTR_MSP/NVRAM_ATTR_OTA_RESET for OTP")
+
+
+def adjust_attr_cate_v(ldi):
+    """ Add pseudo merge attribute """
+    
+    nvram_checksum_size = get_checksum_size(ldi)
+    
+    if global_value.macro & const_value.__NVRAM_PSEUDO_MERGE__:
+        if (ldi.attr & const_value.NVRAM_ATTR_PACKAGE) == 0:
+            check_result_1 = False
+            check_result_2 = False
+            check_result_3 = False
+            if (not ldi.category & const_value.NVRAM_CATEGORY_INTERNAL) and \
+                    (not ldi.category & const_value.NVRAM_CATEGORY_SECUPACK) and \
+                    (not ldi.category & const_value.NVRAM_CATEGORY_IMPORTANT) and \
+                    (not ldi.category & const_value.NVRAM_CATEGORY_CALIBRAT) and \
+                    ((ldi.size + nvram_checksum_size) * ldi.total_records < const_value.NVRAM_CLUSTER_SIZE):
+                check_result_1 = True
+            if global_value.macro & const_value.__NVRAM_CUSTOM_SENSITIVE__:
+                if not ldi.category & const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE:
+                    check_result_2 = True
+            else:
+                check_result_2 = True
+            if global_value.macro & const_value.__NVRAM_CUSTOM_DISK__:
+                if not ldi.category & const_value.NVRAM_CATEGORY_CUSTOM_DISK:
+                    check_result_3 = True
+            else:
+                check_result_3 = True
+            if check_result_1 and check_result_2 and check_result_3:
+                global_value.logger.error(
+                    "Should set the NVRAM_ATTR_PACKAGE for this lid, %d, %s",
+                    ldi.lid, ldi.str_LID)
+                sys.exit(
+                    "Should set the NVRAM_ATTR_PACKAGE for this lid")
+        if ldi.attr & const_value.NVRAM_ATTR_PACKAGE:
+            ldi.description = "null"
+            if ldi.attr & const_value.NVRAM_ATTR_MULTIPLE or ldi.attr & const_value.NVRAM_ATTR_MSP:
+                global_value.logger.error(
+                    "Can't Set NVRAM_ATTR_MULTIPLE/NVRAM_ATTR_MSP for PACKAGE Lid, %d, %s",
+                    ldi.lid, ldi.str_LID)
+                sys.exit(
+                    "Can't Set NVRAM_ATTR_MULTIPLE/NVRAM_ATTR_MSP for PACKAGE Lid")
+
+
+def adjust_attr_cate_vi(ldi):
+    """ Add MSP, confidential, multiple with secupack item"""
+    if ldi.category & const_value.NVRAM_CATEGORY_SECUPACK:
+        check_result = False
+        if not (ldi.attr & const_value.NVRAM_ATTR_CONFIDENTIAL):
+            check_result = True
+        if global_value.macro & const_value.__NVRAM_BIND_TO_CHIP_CIPHER__ and (
+                not ldi.attr & const_value.NVRAM_ATTR_MSP):
+            check_result = True
+        if check_result:
+            global_value.logger.error(
+                "Should set the NVRAM_ATTR_MSP/NVRAM_ATTR_CONFIDENTIAL, %d, %s",
+                ldi.lid, ldi.str_LID)
+            sys.exit(
+                "Should set the NVRAM_ATTR_MSP/NVRAM_ATTR_CONFIDENTIAL")
+
+
+def adjust_attr_cate_vii(ldi):
+    """ Add MSP, confidential, multiple with custom sensitive data
+        Simulation/Palladium/FPGA remove NVRAM_ATTR_GEN_DEFAULT
+    """
+    if global_value.macro & const_value.__NVRAM_CUSTOM_SENSITIVE__:
+        if ldi.category & const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE:
+            if (not ldi.attr & const_value.NVRAM_ATTR_MSP) or (not ldi.attr & const_value.NVRAM_ATTR_CONFIDENTIAL) or (
+                    not ldi.attr & const_value.NVRAM_ATTR_MULTIPLE):
+                global_value.logger.error(
+                    "Should set the NVRAM_ATTR_MSP/NVRAM_ATTR_CONFIDENTIAL/NVRAM_ATTR_MULTIPLE, %d, %s",
+                    ldi.lid, ldi.str_LID)
+                sys.exit(
+                    "Should set the NVRAM_ATTR_MSP/NVRAM_ATTR_CONFIDENTIAL/NVRAM_ATTR_MULTIPLE")
+    if global_value.macro & (const_value._SIMULATION | const_value.__PALLADIUM__ | const_value.__FPGA__):
+        if not ldi.category & const_value.NVRAM_CATEGORY_INTERNAL:
+            ldi.attr &= ~const_value.NVRAM_ATTR_GEN_DEFAULT
+
+
+def adjust_attr_cate_viii(ldi):
+    """ remove all attribute if the data is in custom disk"""
+    if global_value.macro & const_value.__NVRAM_CUSTOM_DISK__:
+        if ldi.category & const_value.NVRAM_CATEGORY_CUSTOM_DISK:
+            if ldi.attr != const_value.NVRAM_ATTR_AVERAGE:
+                global_value.logger.error(
+                    "Can't set other attribute except NVRAM_ATTR_AVERAGE, %d, %s",
+                    ldi.lid, ldi.str_LID)
+                sys.exit(
+                    "Can't set other attribute except NVRAM_ATTR_AVERAGE")
+
+
+def adjust_attr_cate_x(ldi):
+    """
+        1. Compress the data in MT table and it is in custpack
+        2. Compress the default value of the data not in MT table
+          and its default value is not zero default or ff default
+    """
+    pass
+
+
+def adjust_attr_cate_xi(ldi):
+    """ Put Internal, Calibration, Important data into SDS"""
+    if global_value.macro & const_value.__NVRAM_SECURE_DATA_STORAGE__:
+        if ldi.category & (
+                const_value.NVRAM_CATEGORY_INTERNAL | const_value.NVRAM_CATEGORY_CALIBRAT | const_value.NVRAM_CATEGORY_IMPORTANT | const_value.NVRAM_CATEGORY_IMPORTANT_L4):
+            ldi.category |= const_value.NVRAM_CATEGORY_BACKUP_SDS
+            ldi.attr &= ~const_value.NVRAM_ATTR_MULTIPLE
+            ldi.attr &= ~const_value.NVRAM_ATTR_RING
+            ldi.attr &= ~const_value.NVRAM_ATTR_PACKAGE
+            ldi.attr &= ~const_value.NVRAM_ATTR_BACKUP_FAT
+            ldi.attr &= ~const_value.NVRAM_ATTR_BACKUP_RAW
+
+
+def check_item_data_i(ldi):
+    """ cannot put the data into two categories that are mutually exclusive"""
+    check_result = False
+
+    if global_value.macro & const_value.__NVRAM_CUSTOM_SENSITIVE__:
+        if (ldi.category & const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE) and (
+                ldi.category & const_value.NVRAM_CATEGORY_CALIBRAT):
+            check_result = True
+        elif (ldi.category & const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE) and (
+                ldi.category & const_value.NVRAM_CATEGORY_IMPORTANT):
+            check_result = True
+        elif (ldi.category & const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE) and (
+                ldi.category & const_value.NVRAM_CATEGORY_IMPORTANT_L4):
+            check_result = True
+        elif (ldi.category & const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE) and (
+                ldi.category & const_value.NVRAM_CATEGORY_IMPORTANT_L1):
+            check_result = True
+    if global_value.macro & const_value.__NVRAM_CUSTOM_DISK__:
+        if (ldi.category & const_value.NVRAM_CATEGORY_CUSTOM_DISK) and (
+                ldi.category & const_value.NVRAM_CATEGORY_INTERNAL):
+            check_result = True
+        elif (ldi.category & const_value.NVRAM_CATEGORY_CUSTOM_DISK) and (
+                ldi.category & const_value.NVRAM_CATEGORY_CALIBRAT):
+            check_result = True
+        elif (ldi.category & const_value.NVRAM_CATEGORY_CUSTOM_DISK) and (
+                ldi.category & const_value.NVRAM_CATEGORY_IMPORTANT):
+            check_result = True
+        elif (ldi.category & const_value.NVRAM_CATEGORY_CUSTOM_DISK) and (
+                ldi.category & const_value.NVRAM_CATEGORY_IMPORTANT_L4):
+            check_result = True
+        elif (ldi.category & const_value.NVRAM_CATEGORY_CUSTOM_DISK) and (
+                ldi.category & const_value.NVRAM_CATEGORY_IMPORTANT_L1):
+            check_result = True
+    if (global_value.macro & const_value.__NVRAM_CUSTOM_SENSITIVE__) and (
+            global_value.macro & const_value.__NVRAM_CUSTOM_DISK__):
+        if (ldi.category & const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE) and (
+                ldi.category & const_value.NVRAM_CATEGORY_CUSTOM_DISK):
+            check_result = True
+    if check_result:
+        global_value.logger.error(
+            "Category internal & calibrat & important & sensitive can't be used at the same time!, %d, %s",
+            ldi.lid, ldi.str_LID)
+        sys.exit(
+            "Category internal & calibrat & important & sensitive can't be used at the same time!")
+
+
+def check_item_data_ii(ldi):
+    """ cannot put the sds data with custom"""
+    nvram_checksum_size = get_checksum_size(ldi)
+    
+    if (global_value.macro & const_value.__NVRAM_SECURE_DATA_STORAGE__) and (
+            ldi.category & const_value.NVRAM_CATEGORY_BACKUP_SDS):
+        if ldi.category & (
+                const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE | const_value.NVRAM_CATEGORY_CUSTOM_DISK | const_value.NVRAM_CATEGORY_OTP):
+            global_value.logger.error(
+                "Sds use with wrong category LID:%s Desc:%s category %d",
+                ldi.str_LID, ldi.str_LID, ldi.category)
+            sys.exit(
+                "Sds use with wrong category")
+        if ldi.attr & (
+                const_value.NVRAM_ATTR_MULTIPLE | const_value.NVRAM_ATTR_RING | const_value.NVRAM_ATTR_PACKAGE | const_value.NVRAM_ATTR_BACKUP_FAT | const_value.NVRAM_ATTR_BACKUP_RAW):
+            global_value.logger.error(
+                "Sds use with wrong attribute LID:%s Desc:%s attribute %d",
+                ldi.str_LID, ldi.str_LID, ldi.attr)
+            sys.exit(
+                "Sds use with wrong attribute LID")
+        if (global_value.macro & const_value.__NVRAM_BIND_TO_CHIP_CIPHER__) and (ldi.attr & const_value.NVRAM_ATTR_MSP):
+            section_size = ldi.size + nvram_checksum_size + (
+                    (~(ldi.size + nvram_checksum_size) + 1) & (const_value.NVRAM_MSP_ALIGNMENT - 1))
+        else:
+            section_size = ldi.size + nvram_checksum_size
+
+        if section_size * ldi.total_records > const_value.NVRAM_CUSTOM_CFG_MAX_RECORD_SIZE:
+            global_value.logger.error(
+                "Data is too large to put into sds LID:%s Desc:%s %d %d",
+                ldi.str_LID, ldi.str_LID, ldi.size, ldi.total_records)
+            sys.exit(
+                "Data is too large to put into sds")
+
+
+def check_item_data_iii(ldi):
+    """ cannot use zero default or ff default with multi default"""
+    if ldi.attr & const_value.NVRAM_ATTR_MULTI_DEFAULT:
+        if ldi.str_default_value == "NVRAM_EF_ZERO_DEFAULT" or ldi.str_default_value == "NVRAM_EF_FF_DEFAULT":
+            global_value.logger.error(
+                "Cannot set ZERO_DEFAULT or FF_DEFAULT with multi_default!, %d, %s",
+                ldi.lid, ldi.str_LID)
+            sys.exit(
+                "Cannot set ZERO_DEFAULT or FF_DEFAULT with multi_default!")
+
+
+def check_item_data_iv(ldi):
+    """ The record size cannot bigger than the biggest control buffer"""
+    
+    nvram_checksum_size = get_checksum_size(ldi)
+    
+    if not global_value.macro & const_value.__NVRAM_LARGE_RECORD_SIZE__:
+        if (global_value.macro & const_value.__NVRAM_BIND_TO_CHIP_CIPHER__) and (ldi.attr & const_value.NVRAM_ATTR_MSP):
+            section_size = ldi.size + nvram_checksum_size + (
+                    (~(ldi.size + nvram_checksum_size) + 1) & (const_value.NVRAM_MSP_ALIGNMENT - 1))
+        else:
+            section_size = ldi.size + nvram_checksum_size
+
+        if section_size > const_value.NVRAM_CUSTOM_CFG_MAX_RECORD_SIZE:
+            global_value.logger.error(
+                "LID Size is too big, %d, %s",
+                ldi.lid, ldi.str_LID)
+            sys.exit(
+                "LID Size is too big")
+
+
+def check_item_data_v(ldi):
+    """ Items in custpack cannot use zero default or ff default as the default value"""
+    if ldi.category & const_value.NVRAM_CATEGORY_CUSTPACK:
+        if ldi.str_default_value == "NVRAM_EF_ZERO_DEFAULT" or ldi.str_default_value == "NVRAM_EF_FF_DEFAULT":
+            global_value.logger.error(
+                "Cannot set ZERO_DEFAULT or FF_DEFAULT with custpack!, %d, %s",
+                ldi.lid, ldi.str_LID)
+            sys.exit(
+                "Cannot set ZERO_DEFAULT or FF_DEFAULT with custpack!")
+
+
+def check_item_data_vi(ldi):
+    """ Build error check: CALIBRAT LID should not have NVRAM_ATTR_OTA_RESET attribute"""
+    if (ldi.category & const_value.NVRAM_CATEGORY_CALIBRAT) and (ldi.attr & const_value.NVRAM_ATTR_OTA_RESET):
+        global_value.logger.error(
+            "CALIBRAT LID should not have NVRAM_ATTR_OTA_RESET attribute!, %d, %s",
+            ldi.lid, ldi.str_LID)
+        sys.exit(
+            "CALIBRAT LID should not have NVRAM_ATTR_OTA_RESET attribute!")
+
+
+def nvram_gen_assign_entry():
+    for ldi in logical_data_item_table:
+        # Tool check begin:
+        # nvram_pre_gen.pl check if it is same asnvram_assign_table_entry() and nvram_gen_assign_entry()
+        adjust_attr_cate_i(ldi)
+        adjust_attr_cate_ii(ldi)
+        adjust_attr_cate_iii(ldi)
+        adjust_attr_cate_iv(ldi)
+        adjust_attr_cate_v(ldi)
+        adjust_attr_cate_vi(ldi)
+        adjust_attr_cate_vii(ldi)
+        adjust_attr_cate_viii(ldi)
+        adjust_attr_cate_xi(ldi)
+        # Tool check end: nvram_pre_gen.pl
+
+        check_item_data_i(ldi)
+        check_item_data_ii(ldi)
+        check_item_data_iii(ldi)
+        check_item_data_iv(ldi)
+        check_item_data_v(ldi)
+        check_item_data_vi(ldi)
diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/gen_cache_info.py b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/gen_cache_info.py
new file mode 100644
index 0000000..4eddc60
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/gen_cache_info.py
@@ -0,0 +1,143 @@
+import os
+import struct
+import re
+
+
+from .initconfig import global_value
+from .initconfig import logical_data_item_table
+from .initconfig import const_value
+from .initconfig import COPYRIGHTS_HEADER
+from .initconfig import printf
+from .initconfig import autogen_open_file
+
+def parse_noncache_list():
+    noncache_list = []
+    if global_value.macro & const_value.__NVRAM_PARTIAL_CACHE__:
+        noncache_list_start = 0
+        fd = autogen_open_file("service/nvram/src", "nvram_cache_white_list.c", "r")
+
+        for each_line in fd:
+            """ remove whitespace"""
+            if each_line.isspace():
+                continue
+            if re.search("kal_uint32 nvram_lid_noncache_list\[\]= \{", each_line):
+                noncache_list_start = 1
+                continue
+            if noncache_list_start != 1:
+                continue
+            if re.search("\}\;", each_line) and (noncache_list_start == 1):
+                break
+            strs = each_line.strip()  # clear tail character ('\n' ' ' '\t' '\r')
+            strlist = strs.split(',')
+            global_value.logger.info("noncache_list_strlist: %s" % strs)
+            noncache_list.append(int(strlist[0]))
+    return noncache_list
+
+def cache_header_generator(fd, dirty_bit_table_length, cache_data_offset, nvram_gen_total_cache_lid):
+    """ write header array"""
+    cache_lid_num = nvram_gen_total_cache_lid
+    table_index_offset = struct.calcsize('8I') # sizeof(nvram_lid_cache_header)
+    table_index_size = struct.calcsize('H6I36c')*nvram_gen_total_cache_lid  # sizeof(nvram_lid_cache_table_struct)
+    data_base_offset = table_index_offset + table_index_size
+    data_base_offset = ((data_base_offset + const_value.SHARE_MEM_64BYTE_ALIGN - 1)//const_value.SHARE_MEM_64BYTE_ALIGN) * const_value.SHARE_MEM_64BYTE_ALIGN
+    dirty_mapping_offset = data_base_offset
+    dirty_mapping_size = ((dirty_bit_table_length + const_value.SHARE_MEM_64BYTE_ALIGN - 1)//const_value.SHARE_MEM_64BYTE_ALIGN) * const_value.SHARE_MEM_64BYTE_ALIGN
+    data_base_offset += dirty_mapping_size
+    valid_mapping_offset = data_base_offset
+
+    data_base_offset += dirty_mapping_size
+    cache_table_offset = data_base_offset
+    cache_table_size = cache_data_offset
+
+    printf("nvram_lid_cache_header cache_info_header = {\n", file=fd, end="")
+    printf("\t%u,\n" % cache_lid_num, file=fd, end="")
+    printf("\t%u,\n" % table_index_offset, file=fd, end="")
+    printf("\t%u,\n" % table_index_size, file=fd, end="")
+    printf("\t%u,\n" % dirty_mapping_offset, file=fd, end="")
+    printf("\t%u,\n" % valid_mapping_offset, file=fd, end="")
+    printf("\t%u,\n" % dirty_mapping_size, file=fd, end="")
+    printf("\t%u,\n" % cache_table_offset, file=fd, end="")
+    printf("\t%u\n" % cache_table_size, file=fd, end="")
+    printf("};\n\n", file=fd, end="")
+    need_shm_size = cache_table_offset + cache_table_size
+    if need_shm_size > const_value.SHARE_MEMORY_SIZE:
+        global_value.logger.error("Error: Please contact NVRAM owner, the NV Cache Share Memory Size Too small. currently total LID size is: 0x%x.\n", need_shm_size)
+        sys.exit(-1)
+
+
+def nvram_gen_cache_info():
+    ''' gen file : nvram_cache_info.c / nvram_cache_info.h '''
+    # Local Variables
+    cache_data_offset = 0
+    dirty_bit_table_offset = 0
+    dirty_bit_table_length = 0
+    nvram_gen_total_cache_lid = 0
+
+    fd = autogen_open_file(global_value.autogen_path, "nvram_cache_info.c", "w+")
+
+    printf(COPYRIGHTS_HEADER % "nvram_cache_info.c", file=fd, end="")
+
+    printf("#include \"nvram_cache_info.h\"\n", file=fd, end="")
+    printf("\n", file=fd, end="")
+    printf("nvram_lid_cache_table_struct cache_info_table[] = {\n", file=fd, end="")
+
+    noncache_list = parse_noncache_list()
+
+    for item in logical_data_item_table:
+        if global_value.macro & const_value.__NVRAM_PARTIAL_CACHE__:
+            if item.lid in noncache_list:
+                continue
+        lid = item.lid
+        total_records = item.total_records
+
+        cache_offset = cache_data_offset
+        
+        if item.attr & const_value.NVRAM_ATTR_CHKSUM_INTEGRATE:
+            global_value.logger.info("checksum integrate: lid: %s", item.str_LID)
+        onefilesize = item.FileSize
+        
+        file_length = onefilesize
+        cache_data_offset += ((file_length+const_value.SHARE_MEM_64BYTE_ALIGN-1)//const_value.SHARE_MEM_64BYTE_ALIGN)*const_value.SHARE_MEM_64BYTE_ALIGN
+        dirty_offset = dirty_bit_table_offset
+        valid_offset = dirty_bit_table_offset
+        dirty_bit_table_offset += ((total_records + 1 + const_value.DIRTY_BLOCK_SIZE - 1)//const_value.DIRTY_BLOCK_SIZE)*const_value.DIRTY_4BYTE_ALIGN
+        full_path = item.FullPath
+
+        printf("\t{\n", file=fd, end="")
+        printf("\t\t%u,\n" % lid, file=fd, end="")
+        printf("\t\t%u,\n" % 0, file=fd, end="")
+        printf("\t\t%u,\n" % total_records, file=fd, end="")
+        printf("\t\t%u,\n" % file_length, file=fd, end="")
+        printf("\t\t%u,\n" % cache_offset, file=fd, end="")
+        printf("\t\t%u,\n" % dirty_offset, file=fd, end="")
+        printf("\t\t%u,\n" % valid_offset, file=fd, end="")
+        printf("\t\t\"%s\"\n" % full_path, file=fd, end="")
+        printf("\t},\n", file=fd, end="")
+        nvram_gen_total_cache_lid += 1
+    printf("};\n", file=fd, end="")
+    dirty_bit_table_length = dirty_bit_table_offset
+
+    # write header array
+    cache_header_generator(fd, dirty_bit_table_length, cache_data_offset, nvram_gen_total_cache_lid)
+
+    fd.close()
+
+    # write nvram_cache_info.h
+    fd = autogen_open_file(global_value.autogen_path, "nvram_cache_info.h", "w+")
+    printf(COPYRIGHTS_HEADER % "nvram_auto_gen/nvram_cache_info.h", file=fd, end="")
+    printf("#ifndef NVRAM_CACHE_INFO_H\n", file=fd, end="")
+    printf("#define NVRAM_CACHE_INFO_H\n", file=fd, end="")
+    printf("#include \"nvram_cache.h\"\n", file=fd, end="")
+    printf("#include \"nvram_enums.h\"\n", file=fd, end="")
+    printf("#include \"kal_general_types.h\"\n\n", file=fd, end="")
+    printf("extern nvram_lid_cache_table_struct cache_info_table[];\n", file=fd, end="")
+    printf("extern nvram_lid_cache_header cache_info_header;\n\n", file=fd, end="")
+    printf("#endif /*NVRAM_CACHE_INFO_H*/\n", file=fd, end="")
+    fd.close()
+
+
+
+
+
+
+
diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/gen_cat_file.py b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/gen_cat_file.py
new file mode 100644
index 0000000..7819174
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/gen_cat_file.py
@@ -0,0 +1,62 @@
+import os
+
+from .initconfig import global_value
+from .initconfig import logical_data_item_table
+from .initconfig import const_value
+from .initconfig import printf
+from .initconfig import autogen_open_file
+
+
+def nvram_gen_cat_xml():
+    """ gen file : custom_nvram_lid_cat.xml """
+    fd = autogen_open_file(global_value.autogen_path, "custom_nvram_lid_cat.xml", "w+")
+    printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", file=fd, end="")
+    printf("<APP>\n", file=fd, end="")
+    for ldi in logical_data_item_table:
+        if ldi.lid == 0 or ldi.size == 0 or ldi.total_records == 0:
+            continue
+        printf("    <NVRAMITEM id=\"%s\"" % ldi.str_LID, file=fd, end="")
+        printf(" prefix=\"%s\"" % ldi.FilePrefix, file=fd, end="")
+        printf(" version=\"%s\"" % ldi.FileVerno, file=fd, end="")
+        printf(" record_size=\"%d\"" % ldi.size, file=fd, end="")
+        printf(" total_record=\"%d\"" % ldi.total_records, file=fd, end="")
+        printf(" lid_enum=\"%d\"" % ldi.lid, file=fd, end="")
+        printf(" category=\"0x%x\"" % ldi.category, file=fd, end="")
+        printf(" attribute=\"0x%x\">\n" % ldi.attr, file=fd, end="")
+        if ldi.category & const_value.NVRAM_CATEGORY_FUNC_DEFAULT:
+            printf("        <DEFAULT_VALUE defaultByteFill=\"%s()\"></DEFAULT_VALUE>\n" % ldi.str_default_value, file=fd, end="")
+        elif ldi.p_default_value == const_value.NVRAM_EF_FF_DEFAULT:
+            printf("        <DEFAULT_VALUE defaultByteFill=\"0xFF\"></DEFAULT_VALUE>\n", file=fd, end="")
+        elif ldi.p_default_value == const_value.NVRAM_EF_ZERO_DEFAULT:
+            printf("        <DEFAULT_VALUE defaultByteFill=\"0x00\"></DEFAULT_VALUE>\n", file=fd, end="")
+        elif ldi.p_default_value == const_value.NVRAM_EF_SPECIAL_DEFAULT:
+            printf("        <DEFAULT_VALUE defaultByteFill=\"0x00\"></DEFAULT_VALUE>\n", file=fd, end="")
+        else:
+            if ldi.attr & const_value.NVRAM_ATTR_MULTI_DEFAULT:
+                printf("        <DEFAULT_VALUE isMultiple=\"TRUE\"> \n", file=fd, end="")
+            else:
+                printf("        <DEFAULT_VALUE> \n", file=fd, end="")
+            for i in range(ldi.default_value_len):
+                if ldi.default_value_len == 1:
+                    printf("            [0x%02X]\n        </DEFAULT_VALUE>\n" % ldi.default_value[i], file=fd, end="")
+                elif i == 0:
+                    printf("            [0x%02X," % ldi.default_value[i], file=fd, end="")
+                elif i == (ldi.default_value_len - 1):
+                    printf(" 0x%02X]\n        </DEFAULT_VALUE>\n" % ldi.default_value[i], file=fd, end="")
+                elif (i & 0x0F) == 0x0F:
+                    printf(" 0x%02X,\n" % ldi.default_value[i], file=fd, end="")
+                elif (i & 0x0F) == 0x00:
+                    printf("             0x%02X," % ldi.default_value[i], file=fd, end="")
+                else:
+                    printf(" 0x%02X," % ldi.default_value[i], file=fd, end="")
+        printf("        <DESCRIPTION> %s </DESCRIPTION>\n" % ldi.str_LID, file=fd, end="")
+        printf("    </NVRAMITEM>\n", file=fd, end="")
+    printf("</APP>\n", file=fd, end="")
+    fd.close()
+
+
+
+
+
+
+
diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/gen_lid_information.py b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/gen_lid_information.py
new file mode 100644
index 0000000..a2d673a
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/gen_lid_information.py
@@ -0,0 +1,174 @@
+import os
+import struct
+import sys
+import json
+
+from .initconfig import global_value
+from .initconfig import logical_data_item_table
+from .initconfig import const_value
+from .initconfig import printf, get_checksum_size
+from .initconfig import autogen_open_file, nvram_algo_type_str
+from .initconfig import nvram_is_category_in_bin_region, nvram_is_category_factory_reset
+
+
+def nvram_gen_info_size_log():
+    ''' gen file : ~nvram_lid_information.log / ~nvram_lid_size.log'''
+    estimate_size = 0
+    estimate_fs_size = 0
+    bin_region_size = 0
+    protect_size = 0
+    # ------------------------------
+    sum = 0
+    nvram_auto_package_num = 0
+    nvram_auto_pack_file_offset = struct.calcsize("6IH") + 8
+    fake_lid = len(logical_data_item_table)
+    lid_detail_info = {"lids":[], "chksum_info":{}}
+    # ------------------------------
+
+    logOfTools = autogen_open_file(global_value.autogen_path, "~nvram_lid_information.log", "w+")
+    logOfSize = autogen_open_file(global_value.autogen_path, "~nvram_lid_size.log", "w+")
+
+    printf("-----------------------------------------------------------------------"
+          "-----------------------------------------------------------------------\n",
+          file=logOfTools, end="")
+    printf("-----------------------------------------------------------------------"
+          "-----------------------------------------------------------------------\n",
+          file=logOfTools, end="")
+    printf("%4s    %55s    %10s    %10s    %11s  %10s   %10s\n" %("LID", "LID(String)", "Filename", "Verno", "Description", "Category", "Attribute"),
+          file=logOfTools, end="")
+    printf("-----------------------------------------------------------------------"
+          "-----------------------------------------------------------------------\n",
+          file=logOfTools, end="")
+    printf("00000       long:%d,char*:%d,padding:%d                     NVRAM_PADDING_TEST\n" %(global_value.nvram_long_length,
+        global_value.nvram_ptr_length, global_value.nvram_padding_length//3), file=logOfSize, end="")
+    printf("--------------------------------------------------------------------------\n", file=logOfSize, end="")
+    # ------------------------------
+    if global_value.macro & const_value.__NVRAM_PSEUDO_MERGE__: # not run
+        # logOfSize_Package = open(os.path.join(global_value.path, "nvram_auto_gen", "nvram_lid_size_merge.log"), "w+")
+        logOfSize_Package = autogen_open_file(global_value.autogen_path, "nvram_lid_size_merge.log", "w+")
+        printf("%4s   %10s    %10s    %10s    %10s    %10s    %10s\n" % (
+        "ldi->LID", "fileprefix", "onefilesize", "oneLIDsize", "single_num", "single_offset", "file_size"),
+              file=logOfSize_Package, end="")
+    # ------------------------------
+    for ldi in logical_data_item_table:
+        if ldi.lid == 0 or ldi.size == 0 or ldi.total_records == 0:
+            continue
+
+        if global_value.macro & const_value.__NVRAM_PSEUDO_MERGE__: # not run
+            sum += 1
+        
+        
+        nvram_checksum_size = get_checksum_size(ldi)
+            
+        
+        # calculate onefilesize not shout CHKSUM_INTEGRATE
+        if (ldi.attr & const_value.NVRAM_ATTR_CONFIDENTIAL) or (ldi.attr & const_value.NVRAM_ATTR_MSP and global_value.macro & const_value.__NVRAM_BIND_TO_CHIP_CIPHER__):
+            remainLen = (~(ldi.size + nvram_checksum_size) + 1) & (const_value.NVRAM_MSP_ALIGNMENT - 1)
+            onefilesize = (
+                                      ldi.size + nvram_checksum_size + remainLen) * ldi.total_records + const_value.NVRAM_LDI_HEADER_SIZE
+        else:
+            onefilesize = (ldi.size + nvram_checksum_size) * ldi.total_records + const_value.NVRAM_LDI_HEADER_SIZE
+        
+        onefilefssize = (ldi.FileSize + const_value.FS_PAGE_SIZE - 1)//const_value.FS_PAGE_SIZE * const_value.FS_PAGE_SIZE
+        if onefilesize :
+            # ------------------------------
+            if global_value.macro & const_value.__NVRAM_PSEUDO_MERGE__: # not run
+                if ldi.attr & const_value.NVRAM_ATTR_PACKAGE:
+                    printf("%4d    %55s    %10s    %10s    %11s    0x%08x  0x%08x\n" % (ldi.lid, ldi.str_LID, "PACK", "LID",
+                    ldi.description, ldi.category, ldi.attr), file=logOfTools, end="")
+
+                    nvram_auto_package_num += 1
+                    printf("%40s" % ldi.description, file=logOfSize_Package, end="")
+                    ldi.description = nvram_auto_pack_file_offset
+                    nvram_auto_pack_file_offset += onefilefssize
+                    printf("%4s   %10s    %10s    %10s    %10s    %10s    %10s\n" % (ldi.lid, ldi.FilePrefix, onefilesize, ldi.size,
+                    nvram_auto_package_num, ldi.description, nvram_auto_pack_file_offset), file=logOfSize_Package, end="")
+                    if ldi.category & const_value.NVRAM_CATEGORY_CUSTPACK:
+                        custpack = "CUSTPACK"
+                    else:
+                        custpack = ""
+                    printf("%4d%10d%60s%20s\n" % (ldi.lid, 0, ldi.str_LID, custpack), file=logOfSize, end="")
+                    continue
+            # ------------------------------
+            estimate_size += ldi.FileSize
+            estimate_fs_size += onefilefssize
+            if ldi.category & const_value.NVRAM_CATEGORY_CUSTPACK:
+                custpack = "CUSTPACK"
+            else:
+                custpack = ""
+            printf("%4d%10d%60s%20s\n" %(ldi.lid, onefilesize, ldi.str_LID, custpack), file=logOfSize, end="")
+            if ldi.attr & const_value.NVRAM_ATTR_MULTIPLE:
+                estimate_size += ldi.FileSize
+                estimate_fs_size += onefilefssize
+                printf("%4d%10d%60s%20s\n" % (ldi.lid, onefilesize, ldi.str_LID, custpack), file=logOfSize, end="")
+            if nvram_is_category_in_bin_region(ldi.category):
+                bin_region_size += onefilefssize
+                if ldi.attr & const_value.NVRAM_ATTR_MULTIPLE:
+                    bin_region_size += onefilefssize
+            if not nvram_is_category_factory_reset(ldi.category):
+                protect_size += onefilefssize
+
+            printf("%4d    %55s    %10s    %10s    %11s    0x%08x  0x%08x\n" %(ldi.lid, ldi.str_LID, ldi.FilePrefix, ldi.FileVerno,
+                  "(" + ldi.description + ")", ldi.category, ldi.attr), file=logOfTools, end="")
+            lid_detail_info["lids"].append({"enum": ldi.lid, "str_LID":ldi.str_LID, "file_prefix":ldi.FilePrefix, "verno":ldi.FileVerno,
+                    "description":ldi.description, "category":ldi.category, "attr":ldi.attr, "size":onefilesize})
+    # ------------------------------
+    if global_value.macro & const_value.__NVRAM_VENDOR_SUPPORT__:
+        printf("%4d%10d%60s\n" % (len(logical_data_item_table), 1024*100, "NVRAM_EF_VENDOR_REMAIN_SPACE_LID"), file=logOfSize, end="")
+    if global_value.macro & const_value.__NVRAM_PSEUDO_MERGE__:  # not run
+        fake_lid = len(logical_data_item_table)
+        if global_value.macro & const_value.__NVRAM_VENDOR_SUPPORT__:
+            fake_lid += 1
+        printf("%4d%10d%40s\n" % (fake_lid, nvram_auto_pack_file_offset, "Package file size"),
+              file=logOfSize, end="")
+        printf("%4d%10d%40s\n" % (fake_lid+1, nvram_auto_package_num*(struct.calcsize("2IH8ss")+2), "Info file A"),
+              file=logOfSize, end="")
+        printf("%4d%10d%40s\n" % (fake_lid+2, nvram_auto_package_num*(struct.calcsize("2IH8ss")+2), "Info file B"),
+              file=logOfSize, end="")
+        printf("%4d%10d%40s\n" % (fake_lid+3, 3*512, "Extra size"),
+              file=logOfSize, end="")
+    # ------------------------------
+
+    printf("--------------------------------------------------------------------------\n", file=logOfSize, end="")
+    printf("-----------------------------------------------------------------------"
+          "---------------------\n",
+          file=logOfTools, end="")
+    if global_value.macro & const_value.__NV_CHKSUM_ENHANCE__:
+        printf("enhance_algo_size=%d\n" % global_value.enhance_size, file=logOfTools, end="")
+        printf("enhance_algo_type=%d\n" % global_value.enhance_type, file=logOfTools, end="")
+        printf("default_algo_size=%d\n" % global_value.default_size, file=logOfTools, end="")
+        printf("default_algo_type=%d\n" % global_value.default_type, file=logOfTools, end="")
+        lid_detail_info["chksum_info"] = {"enhance_algo_size":global_value.enhance_size, "enhance_algo_type":global_value.enhance_type,
+                    "default_algo_size": global_value.default_size, "default_algo_type":global_value.default_type}
+    
+    if global_value.macro & const_value.__NVRAM_COMPRESS_SUPPORT__:
+        printf("NVRAM_COMPRESS=1\n", file=logOfSize, end="")
+    else:
+        printf("NVRAM_COMPRESS=0\n", file=logOfSize, end="")
+
+    printf("NVRAM_ESTIMATE_SIZE=%d\n" % estimate_size, file=logOfSize, end="")
+    printf("NVRAM_ESTIMATE_FS_SIZE=%d\n" % estimate_fs_size, file=logOfSize, end="")
+    printf("bin_region_size=%d\n" % bin_region_size, file=logOfSize, end="")
+    printf("protect_size=%d\n" % protect_size, file=logOfSize, end="")
+    lid_detail_info["total_size"] = estimate_size
+    lid_detail_info["total_fs_size"] = estimate_fs_size
+    
+    if global_value.macro & const_value.__FS_RAMDISK__:
+        printf("RAMDISK_SIZE=%d\n" % const_value.RAM_FS_SIZE, file=logOfSize, end="")
+        lid_detail_info["ramdisk_size"] = const_value.RAM_FS_SIZE
+    if global_value.macro & const_value.__NVRAM_PSEUDO_MERGE__:  # not run
+        logOfSize_Package.close()
+    logOfTools.close()
+    logOfSize.close()
+    # write json
+    with autogen_open_file(global_value.autogen_path, "~nv_lid_detail_info.json", "w") as fh:
+        json.dump(lid_detail_info, fh)
+    if global_value.macro & const_value.__FS_RAMDISK__:
+        if estimate_fs_size > const_value.RAM_FS_SIZE:
+            global_value.logger.error("RAMDISK size is not enough.")
+            global_value.logger.error("NVRAM_ESTIMATE_FS_SIZE=%d", estimate_fs_size)
+            global_value.logger.error("RAMDISK_SIZE=%d", const_value.RAM_FS_SIZE)
+
+            sys.exit("estimate_fs_size > RAMDISK_SIZE")
+
+
diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/gen_statistic.py b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/gen_statistic.py
new file mode 100644
index 0000000..38c6fa8
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/gen_statistic.py
@@ -0,0 +1,36 @@
+import os
+
+from .initconfig import global_value
+from .initconfig import logical_data_item_table
+from .initconfig import const_value
+from .initconfig import COPYRIGHTS_HEADER
+from .initconfig import printf
+from .initconfig import autogen_open_file
+
+
+def nvram_gen_statistic():
+    ''' gen file: nvram_lid_statistic_bak.h'''
+    fd = autogen_open_file(global_value.autogen_path, "nvram_lid_statistics_bak.h", "w+")
+    printf(COPYRIGHTS_HEADER % "nvram_lid_statistics_bak.h", file=fd, end="")
+    printf("#ifndef NVRAM_LID_STATISTIC_H\n", file=fd, end="")
+    printf("#define NVRAM_LID_STATISTIC_H\n", file=fd, end="")
+
+    if global_value.macro & const_value.__NVRAM_OTP__:  # __NVRAM_OTP__
+        printf("#define NVRAM_OTP_SIZE    %d\n" % global_value.otp_size_to_verify, file=fd, end="")
+        printf("#define NVRAM_OTP_TOTAL   %d\n" % global_value.otp_total_to_verify, file=fd, end="")
+    printf("#define NVRAM_CUSTPACK_TOTAL  %d\n" % global_value.custpack_total_to_verify, file=fd, end="")
+
+    printf("#define NVRAM_SECUPACK_SIZE  %d\n" % global_value.secupack_size_to_verify, file=fd, end="")
+    printf("#define NVRAM_SECUPACK_TOTAL  %d\n" % global_value.secupack_total_to_verify, file=fd, end="")
+    if global_value.macro & const_value.__NVRAM_SECURE_DATA_STORAGE__:  # __NVRAM_SECURE_DATA_STORAGE__
+        printf("#define NVRAM_SDS_TOTAL    %d\n" % global_value.sds_total_to_verify, file=fd, end="")
+        printf("#define NVRAM_SDS_SIZE   %d\n" % global_value.sds_size_to_verify, file=fd, end="")
+    if global_value.macro & const_value.__NVRAM_PSEUDO_MERGE__:  # __NVRAM_PSEUDO_MERGE__
+        printf("\n", file=fd, end="")
+        printf("#ifdef __NVRAM_PSEUDO_MERGE__\n", file=fd, end="")
+        printf("#define NVRAM_PACKAGE_LID_NUM     %d\n" % global_value.nvram_auto_package_num, file=fd, end="")
+        printf("#define NVRAM_PACKAGE_LID_SIZE    %d\n" % global_value.nvram_auto_pack_file_offset, file=fd, end="")
+        printf("#endif /* __NVRAM_PSEUDO_MERGE__ */\n", file=fd, end="")
+
+    printf("\n#endif /* NVRAM_LID_STATISTIC_H */\n\n", file=fd, end="")
+    fd.close()
diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/initconfig.py b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/initconfig.py
new file mode 100644
index 0000000..975bfec
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/initconfig.py
@@ -0,0 +1,580 @@
+import logging
+import os
+import re
+import sys
+
+
+nvram_algo_type = {1: "NVRAM_MD5", 2: "NVRAM_HMAC_SHA256"}
+nvram_algo_type_str = {"NVRAM_MD5": 1, "NVRAM_HMAC_SHA256": 2}
+
+def nvram_is_category_in_bin_region(x):
+    return ((x) & (const_value.NVRAM_CATEGORY_CALIBRAT | const_value.NVRAM_CATEGORY_IMPORTANT))
+def nvram_is_category_factory_reset(x):
+    return (not ((x) & (const_value.NVRAM_CATEGORY_IMPORTANT_L1 | const_value.NVRAM_CATEGORY_IMPORTANT_L4)))
+
+def get_checksum_size(ldi):
+    ret = const_value.NVRAM_CHKSUM_SIZE
+    if global_value.macro & const_value.__NV_CHKSUM_ENHANCE__:
+        if ldi.attr & const_value.NVRAM_ATTR_CHKSM_ENHNC_ALGRTHM:
+            if global_value.enhance_type  == nvram_algo_type_str["NVRAM_MD5"]:
+                ret = const_value.NVRAM_CHKSUM_SIZE
+            else:
+                ret = global_value.enhance_size
+        else:
+            if global_value.default_type  == nvram_algo_type_str["NVRAM_MD5"]:
+                ret = const_value.NVRAM_CHKSUM_SIZE
+            else:
+                ret = global_value.default_size
+    
+    return ret
+
+def autogen_open_file(file_path, file_name, mode="r"):
+    file_pathname = os.path.join(file_path, file_name)
+    try:
+        fd = open(file_pathname, mode)
+    except:
+        printf("error: open file error.")
+        printf("file_pathname: %s , mode: %s" % (file_pathname, mode))
+        global_value.logger.error("open file error.")
+        global_value.logger.error("file_pathname: %s , mode: %s", file_pathname, mode)
+        raise
+    
+    return fd
+
+def printf(strs, file=sys.stdout, end="\n", flush=False):
+    strs_val = strs + end
+    file.write(strs_val)
+    if flush:
+        file.flush()
+
+# LID table class =======================================
+class LtableEntry(object):
+    lid = 0
+    total_records = 0
+    size = 0
+    p_str_default_value = 0x00
+    str_default_value = ""
+    p_default_value = 0x00
+    default_value = []
+    default_value_len = 0
+    category = 0
+    attr = 0
+    FilePrefix = ""
+    FileVerno = ""
+    p_str_LID = 0x00
+    str_LID = ""
+    p_description = 0x00
+    description = "null"
+    hash_key = 0
+    FileSize = 0
+    FullPath = ""
+
+    
+# def NVRAM_LID_GRP_INTERNAL(x):
+def nvram_lid_grp_internal(x):
+    return (0xF000 | (0x00FF & x))
+
+# def NVRAM_LID_GRP_CORE(x):
+def nvram_lid_grp_core(x):
+    return (0xF200 | (0x00FF & x))
+
+# const value class =======================================
+class ConstValue(object):
+
+    def __init__(self):
+        # nvram_attr_enum
+        self.NVRAM_ATTR_AVERAGE = 0x00000000
+        self.NVRAM_ATTR_MULTI_DEFAULT = 0x00000001
+        self.NVRAM_ATTR_WRITEPROTECT = 0x00000002
+        self.NVRAM_ATTR_MULTIPLE = 0x00000004
+        self.NVRAM_ATTR_CONFIDENTIAL = 0x00000008
+        self.NVRAM_ATTR_MULTIREC_READ = 0x00000010
+        self.NVRAM_ATTR_MSP = 0x00000020
+        self.NVRAM_ATTR_OTA_RESET = 0x00000040
+        self.NVRAM_ATTR_GEN_DEFAULT = 0x00000080
+        self.NVRAM_ATTR_RING = 0x00000100
+        self.NVRAM_ATTR_PACKAGE = 0x00000200
+        self.NVRAM_ATTR_BACKUP_FAT = 0x00000400
+        self.NVRAM_ATTR_BACKUP_RAW = 0x00000800
+        self.NVRAM_ATTR_RESERVE_BACKWARD = 0x00001000
+        self.NVRAM_ATTR_FAULT_ASSERT = 0x00002000
+        self.NVRAM_ATTR_COMMITTED = 0x00004000
+        self.NVRAM_ATTR_RAW_DATA = 0x00008000
+        self.NVRAM_ATTR_CHKSUM_INTEGRATE = 0x00010000
+        self.NVRAM_ATTR_CHKSM_ENHNC_ALGRTHM = 0x00020000
+        self.NVRAM_ATTR_MCF_OTA_ADDITIONAL_NOT_CHECK_VERNO = 0x10000000
+        self.NVRAM_ATTR_MCF_OTA_FOR_QUERY = 0x20000000
+        self.NVRAM_ATTR_MCF_OTA_BY_OP = 0x40000000
+        self.NVRAM_ATTR_MCF_OTA = 0x80000000
+        self.NVRAM_ATTR_ALL = 0xFFFFFFFF
+
+        # nvram_category_enum
+        self.NVRAM_CATEGORY_USER = 0x0000
+        self.NVRAM_CATEGORY_INTERNAL = 0x0001
+        self.NVRAM_CATEGORY_BACKUP_SDS = 0x0010
+        self.NVRAM_CATEGORY_OTP = 0x0020
+        self.NVRAM_CATEGORY_CUSTOM_DISK = 0x0040
+        self.NVRAM_CATEGORY_CUSTOM_SENSITIVE = 0x0080
+        self.NVRAM_CATEGORY_CUSTPACK = 0x0100
+        self.NVRAM_CATEGORY_SECUPACK = 0x0200
+        self.NVRAM_CATEGORY_FUNC_DEFAULT = 0x0400
+        self.NVRAM_CATEGORY_CALIBRAT = 0x1000
+        self.NVRAM_CATEGORY_IMPORTANT = 0x2000
+        self.NVRAM_CATEGORY_IMPORTANT_L4 = 0x4000
+        self.NVRAM_CATEGORY_IMPORTANT_L1 = 0x8000
+        self.NVRAM_CATEGORY_ALL = 0xFFFF
+        self.NVRAM_CATEGORY_RESERVED = 0x80000000
+
+        self.NVRAM_CHKSUM_SIZE = 8
+        self.NVRAM_CHECKSUM_SIZE = 2
+        self.NVRAM_CLUSTER_SIZE = 900
+        self.NVRAM_RECORD_SECTOR_SIZE = 512
+        self.NVRAM_MSP_ALIGNMENT = 16
+        # share memery padding
+        self.SHARE_MEM_64BYTE_ALIGN = 64
+        self.DIRTY_BLOCK_SIZE = 32
+        self.DIRTY_4BYTE_ALIGN = 4
+        self.FS_PAGE_SIZE = 4096
+        self.NVRAM_LDI_OTA_HEADER_SIZE = 32
+        self.NVRAM_LDI_DEBUG_HEADER_SIZE = 32
+        self.NVRAM_LDI_APPENDIX_HEADER_SIZE = 32
+        self.NVRAM_LDI_HEADER_SIZE = self.NVRAM_LDI_OTA_HEADER_SIZE + self.NVRAM_LDI_DEBUG_HEADER_SIZE
+        self.RAM_FS_SIZE = 0x01000000
+        # cache size
+        self.SHARE_MEMORY_SIZE = 0x1200000
+
+        # core folder
+        self.NVRAM_FS_DATAITEM_PATH = "Z:\\\\NVRAM\\\\NVD_DATA"
+        self.NVRAM_FS_COREITEM_PATH = "Z:\\\\NVRAM\\\\NVD_CORE"
+        self.NVRAM_FS_CALIBRAT_DATAITEM_PATH = "Z:\\\\NVRAM\\\\CALIBRAT"
+        self.NVRAM_FS_IMPT_DATAITEM_PATH = "Z:\\\\NVRAM\\\\NVD_IMEI"
+        self.NVRAM_FS_IMPORTNT_DATAITEM_PATH = "Z:\\\\NVRAM\\\\IMPORTNT"
+        self.NVRAM_FS_CUST_DATAITEM_PATH = "Z:\\\\NVRAM\\\\NVD_CUST"
+        self.NVRAM_FS_BACKUP_ROOT_PATH = "G:\\\\NVRAM"
+
+        self.NVRAM_TEST_FS_DATAITEM_PATH = "Z:\\\\NV_TEST\\\\NVD_DATA"
+        self.NVRAM_TEST_FS_COREITEM_PATH = "Z:\\\\NV_TEST\\\\NVD_CORE"
+        self.NVRAM_TEST_FS_CALIBRAT_DATAITEM_PATH = "Z:\\\\NV_TEST\\\\CALIBRAT"
+        self.NVRAM_TEST_FS_IMPT_DATAITEM_PATH = "Z:\\\\NV_TEST\\\\NVD_IMEI"
+        self.NVRAM_TEST_FS_CUST_DATAITEM_PATH = "Z:\\\\NV_TEST\\\\NVD_CUST"
+        self.NVRAM_TEST_FS_IMPORTNT_DATAITEM_PATH = "Z:\\\\NV_TEST\\\\IMPORTNT"
+
+        # sys cache enum
+        self.NVRAM_SYS_CACHE_BEGIN = 1
+        self.NVRAM_SYS_CACHE_MAX = 18
+        self.NVRAM_APP_TOTAL = 1
+
+        # custom key
+        self.NVRAM_SECRET_KEY_SIZE = 8
+        self.NVRAM_CUSTOM_KEY_SEED_SIZE = 32
+        self.NVRAM_AUTO_GEN_BYTE = 1
+        self.NVRAM_AUTO_GEN_SHORT = 2
+        self.NVRAM_AUTO_GEN_INTEGER = 4
+
+        # macro
+        self.__CCCIFS_SUPPORT__ = 1 << 0
+        self.__NVRAM_LID_CACHE__ = 1 << 1
+        self.__NVRAM_LID_HASH_CHECK__ = 1 << 2
+        self.__MTK_INTERNAL__ = 1 << 3
+        self.__NVRAM_UT_TEST__ = 1 << 4
+        self.__NVRAM_BACKUP_DISK_FAT__ = 1 << 5
+        self.__NVRAM_BACKUP_DISK_RAW__ = 1 << 6
+        self.__LOW_COST_SUPPORT_COMMON__ = 1 << 7
+        self.__FS_RAMDISK__ = 1 << 8
+        self.__NVRAM_OTP__ = 1 << 9
+        self.__NVRAM_PSEUDO_MERGE__ = 1 << 10
+        self.__NVRAM_CUSTOM_SENSITIVE__ = 1 << 11
+        self.__NVRAM_CUSTOM_DISK__ = 1 << 12
+        self.__NVRAM_BIND_TO_CHIP_CIPHER__ = 1 << 13
+        self._SIMULATION = 1 << 14
+        self.__PALLADIUM__ = 1 << 15
+        self.__FPGA__ = 1 << 16
+        self.__NVRAM_SECURE_DATA_STORAGE__ = 1 << 17
+        self.__NVRAM_LARGE_RECORD_SIZE__ = 1 << 18
+        self.__NVRAM_VENDOR_SUPPORT__ = 1 << 19
+        self.__VENDOR_RELEASE__ = 1 << 20
+        self.__L1_STANDALONE__ = 1 << 21
+        self.__MMI_FMI__ = 1 << 22
+        self.__NVRAM_COMPRESS_SUPPORT__ = 1 << 23
+        self.__MTK_TARGET__ = 1 << 24
+        self.__NVRAM_IMPORTANT_PARTIONS__ = 1 << 25
+        self.__NV_CHKSUM_ENHANCE__ = 1 << 26
+        self.__NVRAM_PARTIAL_CACHE__ = 1 << 27
+
+        # 
+        self.NVRAM_EF_NVRAM_UNIT_TEST_LID = nvram_lid_grp_internal(16)      #  NVRAM_LID_GRP_INTERNAL(x)
+        self.NVRAM_EF_NVRAM_UNIT_TEST_LID_END = nvram_lid_grp_internal(34)  #  NVRAM_LID_GRP_CORE(x)
+        self.NVRAM_EF_START = nvram_lid_grp_core(0) # 
+        
+        # check target 64bit or 32bit 
+        self.WIN_BIT_ADDR = 0x84
+        self.WIN_32BIT_DATA = 0x4c
+        self.WIN_64BIT_DATA = 0x64
+        
+        self.LINUX_BIT_ADDR = 0x4
+        self.LINUX_32BIT_DATA = 0x01
+        self.LINUX_64BIT_DATA = 0x02
+        
+        self.TARGET_32BIT = 0x01
+        self.TARGET_64BIT = 0X02
+        
+        
+
+    class ConstError(TypeError):
+        pass
+
+    class ConstCaseError(ConstError):
+        pass
+
+    def __setattr__(self, key, value):
+        if key in self.__dict__.keys():
+            if key is not "SHARE_MEMORY_SIZE":
+                raise self.ConstError("Can't change a const variable: '%s'" % key)
+        if not key.isupper():
+            raise self.ConstCaseError("Const variable must be combined with upper letters:'%s'" % key)
+        # add value
+        self.__dict__[key] = value
+
+    @property
+    def SIMULATION(self):
+        return self._SIMULATION
+
+
+class GlobalValue(object):
+    path = "."
+    logging_path = "."
+    autogen_path = "."
+    log_path = "."
+    const = ConstValue()
+    # logger = logging.getLogger("nvram_auto")
+    logger = logging
+    
+    table_offset = 0x0
+    table_len = 0x0
+    nvram_ltable_entry_length = 0x0
+    platform = ""
+    
+    # .map addr & off (Linux)
+    rodata_lma = 0x0
+    rodata_off = 0x0
+    data_lma = 0x0
+    data_off = 0x0
+    bss_lma = 0x0
+    bss_off = 0x0
+    
+    # .map addr (win)
+    text_addr = 0x0
+    text_len = 0x0
+    data_addr = 0x0
+    data_len = 0x0
+    bss_addr = 0x0
+    bss_len = 0x0
+    image_base = 0x0
+    text_offset = 0x0
+    data_offset = 0x0
+    bss_offset = 0x0
+    ltable_offset = 0x0
+
+    # macro define
+    macro = 0x0
+
+    # information.log
+    nvram_long_length = 0
+    nvram_ptr_length = 0
+    nvram_padding_length = 0
+
+    # statistic lid table
+    otp_size_to_verify = 0
+    otp_total_to_verify = 0
+    custpack_total_to_verify = 0
+    secupack_size_to_verify = 0
+    secupack_total_to_verify = 0
+    sds_total_to_verify = 0
+    sds_size_to_verify = 0
+    nvram_auto_package_num = 0
+    nvram_auto_pack_file_offset = 0
+    
+    # 
+    target_bit = 0x0  # target 32bit or 64bit
+    
+    # enhance algo
+    default_type = 0x00
+    default_size = 0x00
+    enhance_type = 0x00
+    enhance_size = 0x00
+
+    def logger_config(self, outLevel=logging.DEBUG):
+        # create formatter and add it to the handlers
+        formatter = logging.Formatter('%(levelname)-10s : %(message)s')
+        info_log_path = os.path.join(self.log_path, "nvram_gen_full_log.log")
+        self.logger.basicConfig(filename=info_log_path, filemode="a",
+                format='%(levelname)-8s : %(message)s', level=logging.INFO)
+            
+        # add handler for error log
+        err_log_path = os.path.join(self.log_path, "nvram_gen.log")
+        error_handler = logging.FileHandler(err_log_path, mode="a")
+        err_format = logging.Formatter("%(levelname)-6s: [autogen]: %(message)s")
+        error_handler.setFormatter(err_format)
+        error_handler.setLevel(logging.ERROR)
+        self.logger.getLogger("").addHandler(error_handler)
+
+    def pars_macro_info(self):
+        """ parse of macro from info.log """
+        self.logger.info("===== pars_macro_info begin =====")
+        # fd = open(os.path.join(self.path, "bin", "log", "info.log"), "r")
+        fd = autogen_open_file(self.log_path, "info.log", "r")
+        macro_option = 0x0
+        __SYSDRV_BACKUP_DISK__ = 1 << 0
+        __SYSDRV_BACKUP_DISK_FAT__ = 1 << 1
+        __SYSDRV_BACKUP_DISK_RAW__ = 1 << 2
+        __TC01__ = 1 << 3
+        __NVRAM_MULTI_FOLDERS__ = 1 << 4
+        __CUSTOMER_TC01_DISK__ = 1 << 5
+        __MTK_TARGET__ = 1 << 6
+        __SECURE_DATA_STORAGE__ = 1 << 7
+        __LTE_RAT__ = 1 << 8
+        __C2K_RAT__ = 1 << 9
+        __MA_L1__ = 1 << 10
+        __UMTS_RAT__ = 1 << 11
+        __DHL_MODULE__ = 1 << 12
+        NVRAM_CUSTOM_CFG_MAX_RECORD_SECTOR_NUM = 1 << 13
+
+        for each_line in fd:
+            if each_line.isspace():  # It's all blank
+                continue
+            if re.search("\[ COMMON INCLUDE PATH \]", each_line):
+                break
+            if re.search("\[ COMMON OPTION \]", each_line):
+                continue
+            # if each_line.count("[ COMMON INCLUDE PATH ]") != 0:
+            #     break
+            # if (each_line.count("[") != 0) or (each_line.count("]") != 0):
+            #     continue
+            strs = each_line.rstrip()  # clear tail character ('\n' ' ' '\t' '\r')
+            if strs == "__CCCIFS_SUPPORT__":
+                self.macro |= const_value.__CCCIFS_SUPPORT__
+                continue
+            if strs == "__NVRAM_LID_CACHE__":
+                self.macro |= const_value.__NVRAM_LID_CACHE__
+                continue
+            if strs == "__NVRAM_PARTIAL_CACHE__":
+                self.macro |= const_value.__NVRAM_PARTIAL_CACHE__
+                const_value.SHARE_MEMORY_SIZE = 0x700000
+                continue
+            if strs == "__NVRAM_LID_HASH_CHECK__":
+                self.macro |= const_value.__NVRAM_LID_HASH_CHECK__
+                continue
+            if strs == "__MTK_INTERNAL__":
+                self.macro |= const_value.__MTK_INTERNAL__
+                continue
+            if strs == "__NVRAM_UT_TEST__":
+                self.macro |= const_value.__NVRAM_UT_TEST__
+                continue
+            if strs == "__NVRAM_BACKUP_DISK_FAT__":
+                self.macro |= const_value.__NVRAM_BACKUP_DISK_FAT__
+                continue
+            if strs == "__NVRAM_BACKUP_DISK_RAW__":
+                self.macro |= const_value.__NVRAM_BACKUP_DISK_RAW__
+                continue
+            if strs == "__LOW_COST_SUPPORT_COMMON__":
+                self.macro |= const_value.__LOW_COST_SUPPORT_COMMON__
+                continue
+            if strs == "__FS_RAMDISK__":
+                self.macro |= const_value.__FS_RAMDISK__
+                continue
+            if strs == "__NVRAM_OTP__":
+                self.macro |= const_value.__NVRAM_OTP__
+                continue
+            if strs == "__NVRAM_PSEUDO_MERGE__":
+                self.macro |= const_value.__NVRAM_PSEUDO_MERGE__
+                continue
+            if strs == "__NVRAM_CUSTOM_SENSITIVE__":
+                self.macro |= const_value.__NVRAM_CUSTOM_SENSITIVE__
+                continue
+            if strs == "__NVRAM_CUSTOM_DISK__":
+                self.macro |= const_value.__NVRAM_CUSTOM_DISK__
+                continue
+            if strs == "__NVRAM_BIND_TO_CHIP_CIPHER__":
+                self.macro |= const_value.__NVRAM_BIND_TO_CHIP_CIPHER__
+                continue
+            if strs == "_SIMULATION":
+                self.macro |= const_value._SIMULATION
+                continue
+            if strs == "__PALLADIUM__":
+                self.macro |= const_value.__PALLADIUM__
+                continue
+            if strs == "__FPGA__":
+                self.macro |= const_value.__FPGA__
+                continue
+            if strs == "__NVRAM_SECURE_DATA_STORAGE__":
+                self.macro |= const_value.__NVRAM_SECURE_DATA_STORAGE__
+                continue
+            if strs == "__NVRAM_LARGE_RECORD_SIZE__":
+                self.macro |= const_value.__NVRAM_LARGE_RECORD_SIZE__
+                continue
+            if strs == "__NVRAM_VENDOR_SUPPORT__":
+                self.macro |= const_value.__NVRAM_VENDOR_SUPPORT__
+                continue
+            if strs == "__VENDOR_RELEASE__":
+                self.macro |= const_value.__VENDOR_RELEASE__
+                continue
+            if strs == "__L1_STANDALONE__":
+                self.macro |= const_value.__L1_STANDALONE__
+                continue
+            if strs == "__MMI_FMI__":
+                self.macro |= const_value.__MMI_FMI__
+                continue
+            if strs == "__NVRAM_COMPRESS_SUPPORT__":
+                self.macro |= const_value.__NVRAM_COMPRESS_SUPPORT__
+                continue
+            if strs == "__NVRAM_IMPORTANT_PARTIONS__":
+                self.macro |= const_value.__NVRAM_IMPORTANT_PARTIONS__
+                continue
+            if strs == "__NV_CHKSUM_ENHANCE__":
+                self.macro |= const_value.__NV_CHKSUM_ENHANCE__
+                continue
+            if strs == "__SYSDRV_BACKUP_DISK__":
+                macro_option |= __SYSDRV_BACKUP_DISK__
+                continue
+            if strs == "__SYSDRV_BACKUP_DISK_FAT__":
+                macro_option |= __SYSDRV_BACKUP_DISK_FAT__
+                continue
+            if strs == "__SYSDRV_BACKUP_DISK_RAW__":
+                macro_option |= __SYSDRV_BACKUP_DISK_RAW__
+                continue
+            if strs == "__TC01__":
+                macro_option |= __TC01__
+                self.macro |= const_value.__NVRAM_LARGE_RECORD_SIZE__
+                continue
+            if strs == "__NVRAM_MULTI_FOLDERS__":
+                macro_option |= __NVRAM_MULTI_FOLDERS__
+                continue
+            if strs == "__CUSTOMER_TC01_DISK__":
+                macro_option |= __CUSTOMER_TC01_DISK__
+                continue
+            if strs == "__MTK_TARGET__":
+                macro_option |= __MTK_TARGET__
+                self.macro |= const_value.__MTK_TARGET__
+                continue
+            if strs == "__SECURE_DATA_STORAGE__":
+                macro_option |= __SECURE_DATA_STORAGE__
+                continue
+            if strs == "__LTE_RAT__":
+                macro_option |= __LTE_RAT__
+                continue
+            if strs == "__C2K_RAT__":
+                macro_option |= __C2K_RAT__
+                continue
+            if strs == "__MA_L1__":
+                macro_option |= __MA_L1__
+                continue
+            if strs == "__UMTS_RAT__":
+                macro_option |= __UMTS_RAT__
+                continue
+            if strs == "__DHL_MODULE__":
+                macro_option |= __DHL_MODULE__
+                continue
+            """if strs.find("NVRAM_CUSTOM_CFG_MAX_RECORD_SECTOR_NUM") != -1:
+                macro_option |= NVRAM_CUSTOM_CFG_MAX_RECORD_SECTOR_NUM
+                list_temp = re.split("=", strs)
+                const_value.NVRAM_CUSTOM_CFG_MAX_RECORD_SECTOR_NUM = int(list_temp[1])
+                const_value.NVRAM_CUSTOM_CFG_MAX_RECORD_SIZE = const_value.NVRAM_CUSTOM_CFG_MAX_RECORD_SECTOR_NUM * const_value.NVRAM_RECORD_SECTOR_SIZE
+            """
+        if macro_option & __SYSDRV_BACKUP_DISK__:
+            if macro_option & __SYSDRV_BACKUP_DISK_FAT__:
+                self.macro |= const_value.__NVRAM_BACKUP_DISK_FAT__
+            if macro_option & __SYSDRV_BACKUP_DISK_RAW__:
+                self.macro |= const_value.__NVRAM_BACKUP_DISK_RAW__
+        if not (self.macro & const_value.__NVRAM_PSEUDO_MERGE__):
+            macro_option |= __NVRAM_MULTI_FOLDERS__
+                
+        if (macro_option & __TC01__) and (macro_option & __NVRAM_MULTI_FOLDERS__):
+            self.macro |= const_value.__NVRAM_CUSTOM_SENSITIVE__
+        if (macro_option & __CUSTOMER_TC01_DISK__) and (self.macro & const_value.__MTK_TARGET__):
+            self.macro |= const_value.__NVRAM_CUSTOM_DISK__
+        if macro_option & __SECURE_DATA_STORAGE__:
+            self.macro |= const_value.__NVRAM_SECURE_DATA_STORAGE__
+        """if not self.macro & const_value.__NVRAM_SECURE_DATA_STORAGE__:
+            if macro_option & __SECURE_DATA_STORAGE__:
+                self.macro |= const_value.NVRAM_ATTR_BACKUP_FAT
+        """
+        if not macro_option & NVRAM_CUSTOM_CFG_MAX_RECORD_SECTOR_NUM:
+            if macro_option & __LTE_RAT__:
+                const_value.NVRAM_CUSTOM_CFG_MAX_RECORD_SECTOR_NUM = 128
+            elif (macro_option & __C2K_RAT__) and not(macro_option & __LTE_RAT__):
+                const_value.NVRAM_CUSTOM_CFG_MAX_RECORD_SECTOR_NUM = 128
+            elif macro_option & (__MA_L1__ | __UMTS_RAT__):
+                const_value.NVRAM_CUSTOM_CFG_MAX_RECORD_SECTOR_NUM = 16
+            elif macro_option & __DHL_MODULE__:
+                const_value.NVRAM_CUSTOM_CFG_MAX_RECORD_SECTOR_NUM = 8
+            else:
+                const_value.NVRAM_CUSTOM_CFG_MAX_RECORD_SECTOR_NUM = 4
+            const_value.NVRAM_CUSTOM_CFG_MAX_RECORD_SIZE = const_value.NVRAM_CUSTOM_CFG_MAX_RECORD_SECTOR_NUM * const_value.NVRAM_RECORD_SECTOR_SIZE
+        self.logger.info("macro = 0x%x", self.macro)
+        self.logger.info("===== pars_macro_info end =====")
+
+
+logical_data_item_table = []
+const_value = ConstValue()
+global_value = GlobalValue()
+
+COPYRIGHTS_HEADER = """/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2008
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*****************************************************************************
+ *
+ * Filename:
+ *   %s
+ *
+ * Project:
+ *   MAUI
+ *
+ * Description:
+ *   This file is intends for NVRAM auto gen statistics
+ *
+ * Author:
+ *   nvram auto gen !
+ * -------
+ *
+ *============================================================================
+ *
+ * This file is automatically generated by the nvram gen procedure
+ *
+ ****************************************************************************/
+"""
+
+if __name__ == '__main__':
+    pass
+    # const = ConstValue()
diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/mcf_ota_helper.py b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/mcf_ota_helper.py
new file mode 100644
index 0000000..7151997
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/mcf_ota_helper.py
@@ -0,0 +1,82 @@
+import os
+import platform
+import re
+
+from .initconfig import global_value
+from .initconfig import logical_data_item_table
+from .initconfig import const_value
+from .initconfig import COPYRIGHTS_HEADER
+from .initconfig import printf
+from .initconfig import autogen_open_file
+
+
+def nvram_gen_ltable_list():
+    
+    map_file = autogen_open_file(global_value.autogen_path, "nvram_auto_gen_target.map", "r")
+    tbl_list = autogen_open_file(global_value.autogen_path, "nvram_ltable_list.h", "w+")
+    
+    indirect_process_yet = 0
+    indirect_process_ing = 1
+    indirect_process_finished = 2
+    process_indirect_init = indirect_process_yet
+    
+    if global_value.platform == "Windows":  # windows
+        indirect_end_symbol = "_indirect_init_end = ."
+    else:
+        indirect_end_symbol = "indirect_init_end = ."
+    
+    
+
+    line = map_file.readline()
+    while line:
+        if process_indirect_init == indirect_process_yet:
+            if line.find("logical_data_item_table_") != -1:
+                str = re.search("logical_data_item_table_\w*", line).group()
+                printf("#pragma comment(linker, \"/INCLUDE:_%s\")\n" % str, file=tbl_list, end="")
+            if line.find("*(_indirect_init)") != -1:
+                process_indirect_init = indirect_process_ing
+                line = map_file.readline()
+                if line.find(indirect_end_symbol) != -1:
+                    process_indirect_init = indirect_process_finished
+                    break
+        elif process_indirect_init == indirect_process_ing:
+            if line.find(indirect_end_symbol) != -1:
+                process_indirect_init = indirect_process_finished
+                break
+            ptr = line[line.find(" ") + 1:]
+            if line.find("./build/") == -1:
+                printf("#pragma comment(linker, \"/INCLUDE:_%s\")\n" % ptr, file=tbl_list, end="")
+        line = map_file.readline()
+
+    map_file.close()
+    tbl_list.close()
+
+
+def nvram_gen_mcf_ota_lid_list():
+    
+    fd = autogen_open_file(global_value.autogen_path, "nvram_lid_list_for_mcf.h", "w+")
+
+    printf(COPYRIGHTS_HEADER % "nvram_lid_list_for_mcf.h", file=fd, end="")
+    printf("#ifndef __NVRAM_LID_LIST_FOR_MCF__\n", file=fd, end="")
+    printf("#define __NVRAM_LID_LIST_FOR_MCF__\n", file=fd, end="")
+    printf("#include \"kal_general_types.h\"\n", file=fd, end="")
+    printf("typedef enum\n{\n", file=fd, end="")
+    for ldi in logical_data_item_table:
+        if ldi.lid == 0 or ldi.size == 0 or ldi.total_records == 0:
+            continue
+        if ldi.attr & const_value.NVRAM_ATTR_MCF_OTA or ldi.attr & const_value.NVRAM_ATTR_MCF_OTA_FOR_QUERY:
+            printf("    %s,    \n" % ldi.str_LID, file=fd, end="")
+
+    printf("    NVRAM_EF_LAST_%s\n}%s;\n\n" %("LID", "nvram_mcf_ota_lid"), file=fd, end="")
+
+    printf("typedef enum\n{\n", file=fd, end="")
+
+    for ldi in logical_data_item_table:
+        if ldi.lid == 0 or ldi.size == 0 or ldi.total_records == 0:
+            continue
+        if ldi.attr & const_value.NVRAM_ATTR_MCF_OTA_BY_OP:
+            printf("    %s,    \n" % ldi.str_LID, file=fd, end="")
+    printf("    NVRAM_EF_LAST_%s\n}%s;\n\n" % ("LID", "nvram_mcf_ota_by_operator_lid"), file=fd, end="")
+    printf("#endif\n", file=fd, end="")
+    fd.close()
+
diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/secupackhelper.py b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/secupackhelper.py
new file mode 100644
index 0000000..19862ff
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/secupackhelper.py
@@ -0,0 +1,208 @@
+import os
+import re
+import struct
+import sys
+
+from .initconfig import logical_data_item_table
+from .initconfig import const_value
+from .initconfig import global_value
+from .initconfig import COPYRIGHTS_HEADER
+from .initconfig import printf, nvram_algo_type
+from .initconfig import autogen_open_file
+from .tableconstructor import offset_elf
+
+
+def parse_custom_key(fd_target):
+    """ parse key data in .map&.exe"""
+    fd = autogen_open_file(global_value.autogen_path, "nvram_auto_gen_target.map", "r")
+    # -----------------------------
+    # parse offset in target.map
+    for each_line in fd:
+       
+        if re.search("custom_secret_key", each_line):
+            s = each_line.strip()
+            list_secret = s.split()
+            secret_key_offset = int(list_secret[0], base=16)
+            continue
+        
+        if re.search("custom_key_seed", each_line):
+            s = each_line.strip()
+            list_seed = s.split()
+            key_seed_offset = int(list_seed[0], base=16)
+            continue
+    fd.close()
+    # ===
+    global_value.logger.info("secret_key_offset = 0x%x, key_seed_offset = 0x%x", secret_key_offset, key_seed_offset)  
+    if not secret_key_offset:
+        global_value.logger.error("secret_key_offset = 0 ,read secret_key_offset error!")  
+        sys.exit(1)
+    if not key_seed_offset:
+        global_value.logger.error("key_seed_offset = 0 ,read key_seed_offset error!")  
+        sys.exit(1)
+    # ===
+    
+    
+    # -------------------------------
+    # calculate offset
+    secret_key_offset = offset_elf(secret_key_offset)
+    key_seed_offset = offset_elf(key_seed_offset)
+    
+    
+    # -------------------------------
+    # parse key data
+    
+    fd_target.seek(secret_key_offset)
+    r_bin = fd_target.read(const_value.NVRAM_SECRET_KEY_SIZE)
+    s = struct.unpack('8B', r_bin)
+    secret_key_list = list(s)
+
+    fd_target.seek(key_seed_offset)
+    r_bin = fd_target.read(const_value.NVRAM_CUSTOM_KEY_SEED_SIZE)
+    s = struct.unpack('32B', r_bin)
+    key_seed_list = list(s)
+
+    # fd.close()
+
+    return secret_key_list, key_seed_list
+    
+    
+
+
+def write_secro_tbl(fd):
+    """ output secupack lid to custom_nvram_secro_tbl.c"""
+    printf("#if defined(NVRAM_SEC_C_ONLY)\n", file=fd, end="")
+    printf("const nvram_lid_enum secupack_nvram_lid_tbl[%d] = \n" % global_value.secupack_total_to_verify, file=fd,
+          end="")
+    printf("{", file=fd, end="")
+
+    for ldi in logical_data_item_table:
+        if ldi.category & const_value.NVRAM_CATEGORY_SECUPACK:
+            printf("\n   %d," % ldi.lid, file=fd, end="")
+    printf("\n};", file=fd, end="")
+    printf("\n#endif", file=fd, end="")
+
+
+def nvram_gen_array(fd, indent, type, max_size, list, calc_cksum, last_block):
+    """ outpur formatted arrays to custom_nvram_secro
+        args:
+            calc_cksum: true add check sum/ false not add check sum
+    """
+    i = 0
+    byte_chksum = [0, 0]
+    while i < max_size:
+        if calc_cksum and type == const_value.NVRAM_AUTO_GEN_BYTE:
+            if i & 0x1:
+                byte_chksum[1] += list[i]
+            else:
+                byte_chksum[0] += list[i]
+
+        if i % 16 == 0:
+            printf("\n%s" % indent, file=fd, end="")
+
+        if type == const_value.NVRAM_AUTO_GEN_INTEGER:
+            printf("0x%02X%02X%02X%02X" % (list[i + 3], list[i + 2], list[i + 1], list[i]), file=fd, end="")
+        elif type == const_value.NVRAM_AUTO_GEN_SHORT:
+            printf("0x%02X%02X" % (list[i + 1], list[i]), file=fd, end="")
+        else:
+            printf("0x%02X" % list[i], file=fd, end="")
+
+        if i == max_size - type:
+            if calc_cksum and type == const_value.NVRAM_AUTO_GEN_BYTE:
+                printf(",\n%s/* check sum */\n%s0x%02x, 0x%02x" % (
+                indent, indent, byte_chksum[0] & 0xff, byte_chksum[1] & 0xff), file=fd, end="")
+
+            if not last_block:
+                printf(", ", file=fd, end="")
+        else:
+            printf(", ", file=fd, end="")
+        i += type
+
+
+def nvram_gen_secro():
+    """ gen file: custom_nvram_secro.c / custom_nvram_secro_tbl.c"""
+    fd_1 = autogen_open_file(global_value.autogen_path, "custom_nvram_secro.c", "w+")
+    fd_2 = autogen_open_file(global_value.autogen_path, "custom_nvram_secro_tbl.c", "w+")
+    
+    write_secro_tbl(fd_2)
+    fd_2.close()
+    
+    if global_value.platform == "Windows":
+        fd_target = autogen_open_file(global_value.autogen_path, "nvram_auto_gen_target.exe", "rb")
+        
+    else:
+        fd_target = autogen_open_file(global_value.autogen_path, "nvram_auto_gen_target", "rb")
+        
+    
+    custom_secret_key, custom_key_seed = parse_custom_key(fd_target)
+    fd_target.close()
+
+    printf(COPYRIGHTS_HEADER % "custom_nvram_secro.c", file=fd_1, end="")
+
+    printf("#if !defined(NVRAM_NOT_PRESENT)\n", file=fd_1, end="")
+    printf("#include \"kal_general_types.h\"\n", file=fd_1, end="") 
+    printf("#include \"custom_nvram_sec.h\"\n", file=fd_1, end="")    
+    
+
+    # write custom secret key
+    printf("const kal_uint8 NVRAM_CUSTOM_KEY[] = \n", file=fd_1, end="")
+    printf("    {", file=fd_1, end="")
+    nvram_gen_array(fd_1, "        ", const_value.NVRAM_AUTO_GEN_BYTE, const_value.NVRAM_SECRET_KEY_SIZE,
+                    custom_secret_key, False, True)
+    printf("\n    };\n", file=fd_1, end="")
+
+    # write custom key seed
+    printf("const kal_uint8 NVRAM_CUSTOM_KEY_SEED[] = \n", file=fd_1, end="")
+    printf("    {", file=fd_1, end="")
+    nvram_gen_array(fd_1, "        ", const_value.NVRAM_AUTO_GEN_BYTE, const_value.NVRAM_CUSTOM_KEY_SEED_SIZE,
+                    custom_key_seed, False, True)
+    printf("\n    };\n", file=fd_1, end="")
+
+    printf("#if defined(__RES_PROT__)\n", file=fd_1, end="")
+    printf("__attribute__((section(\"PROTECTED_RES_RW\")))\n", file=fd_1, end="")
+    printf("#endif\n", file=fd_1, end="")
+
+    printf("const kal_uint8 NVRAM_SECUPACK_DEFAULT[] = \n", file=fd_1, end="")
+    printf("    {", file=fd_1, end="")
+    secupack_idx = 0
+    for ldi in logical_data_item_table:
+        if ldi.category & const_value.NVRAM_CATEGORY_SECUPACK:
+            if secupack_idx != 0:
+                printf("\n", file=fd_1, end="")
+            printf("\n        /* %s */" % ldi.str_LID, file=fd_1, end="")
+            if secupack_idx + 1 == global_value.secupack_total_to_verify:
+                nvram_gen_array(fd_1, "        ", const_value.NVRAM_AUTO_GEN_BYTE, ldi.default_value_len,
+                                ldi.default_value, True, True)
+            else:
+                nvram_gen_array(fd_1, "        ", const_value.NVRAM_AUTO_GEN_BYTE, ldi.default_value_len,
+                                ldi.default_value, True, False)
+            secupack_idx += 1
+
+    if global_value.secupack_total_to_verify == 0:
+        printf("\n        0x00, 0x00", file=fd_1, end="")
+    printf("\n    };", file=fd_1, end="")
+
+    printf("\nkal_uint32 secupack_total_to_verify = %d;" % global_value.secupack_total_to_verify, file=fd_1, end="")
+    printf("\n#endif /* NVRAM_NOT_PRESENT */", file=fd_1, end="")
+
+    fd_1.close()
+    
+    # write custom algo config
+    if global_value.macro & const_value.__NV_CHKSUM_ENHANCE__:
+        fd = autogen_open_file(global_value.autogen_path, "nvram_chksum_algo_config.c", "w+")
+        printf(COPYRIGHTS_HEADER % "nvram_chksum_algo_config.c", file=fd, end="")
+        printf("#include \"custom_nvram_sec.h\"\n\n\n", file=fd, end="")
+        if global_value.macro & const_value.__NVRAM_UT_TEST__:
+            printf("nvram_checksum_config NVRAM_CHK_CONFIG = \n", file=fd, end="")
+        else:
+            printf("const nvram_checksum_config NVRAM_CHK_CONFIG = \n", file=fd, end="")
+        printf("    {\n", file=fd, end="")
+        printf("       %d, %s, %d, %s\n" % (global_value.enhance_size, nvram_algo_type[global_value.enhance_type],
+                                            global_value.default_size, nvram_algo_type[global_value.default_type]),
+                        file=fd, end="")
+        printf("    };", file=fd, end="")
+        fd.close()
+    
+
+
+if __name__ == '__main__':
+    pass
diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/sys_cache_generator.py b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/sys_cache_generator.py
new file mode 100644
index 0000000..03a0e3b
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/sys_cache_generator.py
@@ -0,0 +1,324 @@
+import os
+import re
+import struct
+import sys
+
+from .initconfig import global_value
+from .initconfig import logical_data_item_table
+from .initconfig import const_value
+from .initconfig import COPYRIGHTS_HEADER
+from .initconfig import autogen_open_file
+from .tableconstructor import read_str_in_binary, offset_elf
+# from .tableconstructor_win import read_str_in_binary_win
+from .initconfig import printf
+
+
+NVRAM_RESTORE_FUNCTION_NAME = '''void nvram_restore_%s_cache(nvram_reset_category_enum category, nvram_app_id_enum app_id, kal_uint8 *buffer)
+{
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    switch(app_id)
+    {
+'''
+NVRAM_AUTO_GEN_COMMENT = "            /* Reset: %s */\n"
+NVRAM_RESTORE_FUNCTION_BREAK = '''
+            if (category == NVRAM_RESET_CERTAIN)
+            {
+                break;
+            }'''
+NVRAM_RESTORE_FUNCTION_TAIL = '''        default:
+        break;
+    }
+}
+
+'''
+
+
+class sys_cache:
+    id = 0
+    app_id = 0
+    restore = 0
+    p_description = 0x00
+    description = ""
+    p_app_id_str = 0x00
+    app_id_str = ""
+    p_id_str = 0x00
+    id_str = ""
+    value = []
+
+
+nvram_sys_cache = []
+nvram_restore_cache_system = []
+nvram_restore_system_idx = []
+
+for i in range(const_value.NVRAM_APP_TOTAL):
+    nvram_restore_system_idx.append(0)
+for i in range(const_value.NVRAM_APP_TOTAL):
+    list = []
+    for j in range(const_value.NVRAM_SYS_CACHE_MAX):
+        list.append(0)
+    nvram_restore_cache_system.append(list)
+
+# win
+def parse_system_cache_win():
+    """ parse system cache in .exe & .map"""
+
+    fd = autogen_open_file(global_value.autogen_path, "nvram_auto_gen_target.map", "r")
+    cache_offset = 0
+    cache_total_len_addr = 0
+    for each_line in fd:
+        if re.search("\s+nvram_sys_cache\s+", each_line):
+            s = each_line.strip()
+            list_sys = s.split()
+            cache_offset = int(list_sys[0], base=16)
+            continue
+        if re.search("\s+nvram_sys_cache_length\s+", each_line):
+            s = each_line.strip()
+            list_sys = s.split()
+            cache_total_len_addr = int(list_sys[0], base=16)
+            continue
+    fd.close()
+    # ===
+    global_value.logger.info("cache_offset = 0x%x, cache_total_len_addr = 0x%x", cache_offset, cache_total_len_addr)  
+    if not cache_offset:
+        global_value.logger.debug("cache_offset = 0 ,read nvram_sys_cache error!")  
+        sys.exit(1)
+    if not cache_total_len_addr:
+        global_value.logger.debug("nvram_sys_cache_length = 0 ,read nvram_sys_cache_length error!")  
+        sys.exit(1)
+    # ===
+
+    
+    
+    fd = autogen_open_file(global_value.autogen_path, "nvram_auto_gen_target.exe", "rb")
+    offset = offset_elf(cache_total_len_addr)
+    fd.seek(offset)
+    r_bin = fd.read(4)
+    cache_total_len = struct.unpack("I", r_bin)[0]
+    
+    if global_value.target_bit == const_value.TARGET_64BIT:
+        fmt = '2H9B11Q'
+    else:
+        fmt = '2H9B11I'
+    
+    cache_item_len = struct.calcsize(fmt)
+    cache_total_item = cache_total_len // cache_item_len
+    cache_offset = offset_elf(cache_offset)
+    fd.seek(cache_offset)
+    for i in range(cache_total_item):
+        r_bin = fd.read(cache_item_len)
+        s = struct.unpack(fmt, r_bin)
+        one_entry = sys_cache()
+        one_entry.id = s[0]
+        one_entry.app_id = s[1]
+        one_entry.restore = s[2]
+        list = []
+        for j in range(3, 3 + 8):
+            list.append(s[j])
+        one_entry.value = list
+        one_entry.p_id_str = s[11]
+        one_entry.p_app_id_str = s[12]
+        one_entry.p_description = s[21]
+        nvram_sys_cache.append(one_entry)
+    
+    for i in range(len(nvram_sys_cache)):
+        item = nvram_sys_cache[i]
+        item.description = read_str_in_binary(fd, item.p_description)
+        item.app_id_str = read_str_in_binary(fd, item.p_app_id_str)
+        item.id_str = read_str_in_binary(fd, item.p_id_str)
+    fd.close()
+    
+    
+    
+
+def parse_system_cache():
+    """ parse system cache in .elf&.map"""
+    # fd = open(os.path.join(global_value.path, "nvram_auto_gen", "nvram_auto_gen_target.map"), "r")
+    fd = autogen_open_file(global_value.autogen_path, "nvram_auto_gen_target.map", "r")
+    for each_line in fd:
+        
+        if re.search("\s+nvram_sys_cache\s+", each_line):
+            s = each_line.strip()
+            # list_sys = re.split("\W+", s)
+            list_sys = s.split()
+            cache_offset = int(list_sys[0], base=16)
+            cache_total_len = int(list_sys[4], base=16)
+            break
+    fd.close()
+    # ===
+    global_value.logger.info("cache_offset = 0x%x, cache_total_len = 0x%x", cache_offset, cache_total_len)  
+    if not cache_offset:
+        global_value.logger.debug("cache_offset = 0 ,read nvram_sys_cache error!")  
+        sys.exit(1)
+    if not cache_total_len:
+        global_value.logger.debug("cache_total_len = 0 ,read nvram_sys_cache error!")  
+        sys.exit(1)
+    # ===
+
+    cache_item_len = struct.calcsize('2H9B11I')
+    cache_total_item = cache_total_len // cache_item_len
+    # cache_offset = cache_offset - global_value.data_lma + global_value.data_off
+    cache_offset = offset_elf(cache_offset)
+    # fd = open(os.path.join(global_value.path, "nvram_auto_gen", "nvram_auto_gen_target"), "rb")
+    fd = autogen_open_file(global_value.autogen_path, "nvram_auto_gen_target", "rb")
+    fd.seek(cache_offset)
+    for i in range(cache_total_item):
+        r_bin = fd.read(cache_item_len)
+        s = struct.unpack('2H9B11I', r_bin)
+        one_entry = sys_cache()
+        one_entry.id = s[0]
+        one_entry.app_id = s[1]
+        one_entry.restore = s[2]
+        list = []
+        for j in range(3, 3 + 8):
+            list.append(s[j])
+        one_entry.value = list
+        one_entry.p_id_str = s[11]
+        one_entry.p_app_id_str = s[12]
+        one_entry.p_description = s[21]
+        nvram_sys_cache.append(one_entry)
+
+    for i in range(len(nvram_sys_cache)):
+        item = nvram_sys_cache[i]
+        item.description = read_str_in_binary(fd, item.p_description)
+        item.app_id_str = read_str_in_binary(fd, item.p_app_id_str)
+        item.id_str = read_str_in_binary(fd, item.p_id_str)
+    fd.close()
+
+
+
+def nvram_gen_check_sys_cache(fh_file):
+    """ output system cache default value to custom_nvram_restore.c"""
+    # Local Variables
+    byte_idx = 0
+    bit_idx = 0
+    data = nvram_sys_cache[const_value.NVRAM_SYS_CACHE_BEGIN - 1].value
+
+    # Code Body
+    for loop_idx in range(const_value.NVRAM_SYS_CACHE_BEGIN, const_value.NVRAM_SYS_CACHE_MAX):
+        if nvram_sys_cache[loop_idx].id != loop_idx + 1:
+            global_value.logger.error("please check nvram_data_item.h and nvram_data_item.c: # sys cache enum (%d) "
+                                      "and # sys cache entry must sync.", loop_idx)
+            sys.exit(3)
+        byte_idx = loop_idx // 8
+        bit_idx = loop_idx % 8
+        if nvram_sys_cache[loop_idx].restore:
+            data[byte_idx] |= (0x1 << bit_idx)
+            nvram_restore_cache_system[nvram_sys_cache[loop_idx].app_id][
+                nvram_restore_system_idx[nvram_sys_cache[loop_idx].app_id]] = loop_idx
+            nvram_restore_system_idx[nvram_sys_cache[loop_idx].app_id] += 1
+    # step 1:generate restore mark
+    printf("kal_uint8 const NVRAM_EF_SYS_CACHE_OCTET_DEFAULT[NVRAM_EF_SYS_CACHE_OCTET_TOTAL * "
+          "NVRAM_EF_SYS_CACHE_OCTET_SIZE] =\n{", file=fh_file)
+    # step 2:generate default value
+    for loop_idx in range(const_value.NVRAM_SYS_CACHE_BEGIN, const_value.NVRAM_SYS_CACHE_MAX):
+        for loop_value_idx in range(struct.calcsize('d')):
+            printf("    0x%02X, " % nvram_sys_cache[loop_idx - 1].value[loop_value_idx], file=fh_file, end="")
+        printf("", file=fh_file)
+    # step 3:generate last
+    for loop_value_idx in range(struct.calcsize('d') - 1):
+        printf("    0x%02X, " % nvram_sys_cache[const_value.NVRAM_SYS_CACHE_MAX - 1].value[loop_value_idx], file=fh_file,
+              end="")
+    printf("    0x%02X " % nvram_sys_cache[const_value.NVRAM_SYS_CACHE_MAX - 1].value[7], file=fh_file, end="")
+    printf("", file=fh_file)
+    printf("};", file=fh_file)
+
+
+def nvram_gen_sys_cache_res_func(fh_file):
+    """ output system cache restore fun to custom_nvram_restore.c """
+    printf(NVRAM_RESTORE_FUNCTION_NAME % "system", file=fh_file, end="")
+    for loop_app_idx in range(const_value.NVRAM_APP_TOTAL):
+        if nvram_restore_system_idx[loop_app_idx]:
+            printf("        case %s :\n" % nvram_sys_cache[nvram_restore_cache_system[loop_app_idx][0]].app_id_str,
+                  file=fh_file, end="")
+        else:
+            continue
+        for loop_app_cache_idx in range(nvram_restore_system_idx[loop_app_idx]):
+            printf(NVRAM_AUTO_GEN_COMMENT % nvram_sys_cache[
+                nvram_restore_cache_system[loop_app_idx][loop_app_cache_idx]].description,
+                  file=fh_file, end="")
+            for loop_value_idx in range(struct.calcsize('d')):
+                printf("            buffer[%d * (%s - 1) + %d] = 0x%02X;\n" % (
+                    struct.calcsize('d'),
+                    nvram_sys_cache[nvram_restore_cache_system[loop_app_idx][loop_app_cache_idx]].id_str,
+                    loop_value_idx,
+                    nvram_sys_cache[nvram_restore_cache_system[loop_app_idx][loop_app_cache_idx]].value[loop_value_idx]
+                ),
+                      file=fh_file, end="")
+        printf(NVRAM_RESTORE_FUNCTION_BREAK, file=fh_file)
+    printf(NVRAM_RESTORE_FUNCTION_TAIL, file=fh_file)
+
+
+def nvram_gen_restore_dom(fh_file):
+    """ output restore enum to custom_nvram_dom.h """
+    nvram_restore_lid_enum_array = []
+    nvram_restore_lid_description_point = []
+    nvram_max_length_lid_str = 0
+    '''
+    for item in logical_data_item_table:
+        if not (item.category & (const_value.NVRAM_CATEGORY_IMPORTANT_L1 | const_value.NVRAM_CATEGORY_IMPORTANT_L4)):
+            if len(item.str_LID) > nvram_max_length_lid_str:
+                nvram_max_length_lid_str = len(item.str_LID)
+            nvram_restore_lid_enum_array.append(item.str_LID)
+            nvram_restore_lid_description_point.append(item.description)
+    '''
+    for ldi in logical_data_item_table:
+        if ldi.lid == 0 or ldi.size == 0 or ldi.total_records == 0:
+            continue
+        onefilefssize = (ldi.FileSize + const_value.FS_PAGE_SIZE - 1) // const_value.FS_PAGE_SIZE * const_value.FS_PAGE_SIZE
+        if onefilefssize:
+            if not (ldi.category & (const_value.NVRAM_CATEGORY_IMPORTANT_L1 | const_value.NVRAM_CATEGORY_IMPORTANT_L4)):
+                if len(ldi.str_LID) > nvram_max_length_lid_str:
+                    nvram_max_length_lid_str = len(ldi.str_LID)
+                nvram_restore_lid_enum_array.append(ldi.str_LID)
+                nvram_restore_lid_description_point.append(ldi.description)
+
+
+    printf("/* %s system settings */\n" % "LID", file=fh_file, end="")
+    printf("typedef enum\n{\n", file=fh_file, end="")
+    for loop_app_idx in range(len(nvram_restore_lid_enum_array)):
+        printf("    %s,    " % nvram_restore_lid_enum_array[loop_app_idx], file=fh_file, end="")
+        for loop_space in range(nvram_max_length_lid_str - len(nvram_restore_lid_enum_array[loop_app_idx])):
+            printf(" ", file=fh_file, end="")
+        if nvram_restore_lid_description_point[loop_app_idx] == "null":
+            printf("/* (%s) */\n" % nvram_restore_lid_description_point[loop_app_idx], file=fh_file, end="")
+        else:
+            printf("/* %s */\n" % nvram_restore_lid_description_point[loop_app_idx], file=fh_file, end="")
+    printf("    NVRAM_LAST_%s_ELEMENT\n}%sDATA;\n\n" % ("LID", "LID"), file=fh_file, end="")
+
+
+def nvram_gen_restore_function():
+    """ gen file: custom_nvram_restore.c / nvram_restore_dom_new.h"""
+    # if sys.platform.count("linux") == 0:
+    if global_value.platform == "Windows":
+        parse_system_cache_win()
+    else:
+        parse_system_cache()
+    # ----------------------------------
+    # gen custom_nvram_restore.c
+    # fd_restore_factory_c = open(os.path.join(global_value.path, "nvram_auto_gen", "custom_nvram_restore.c"), "w+")
+    fd_restore_factory_c = autogen_open_file(global_value.autogen_path, "custom_nvram_restore.c", "w+")
+    printf(COPYRIGHTS_HEADER % "nvram_user_restore_factory.h", file=fd_restore_factory_c)
+
+    printf("#ifndef NVRAM_NOT_PRESENT", file=fd_restore_factory_c)
+    printf("#include \"kal_general_types.h\"", file=fd_restore_factory_c)
+    printf("#include \"nvram_enums.h\"", file=fd_restore_factory_c)
+    printf("#include \"custom_nvram_config.h\"", file=fd_restore_factory_c)
+    printf("#include \"nvram_data_items.h\"", file=fd_restore_factory_c)
+
+    nvram_gen_check_sys_cache(fd_restore_factory_c)
+    nvram_gen_sys_cache_res_func(fd_restore_factory_c)
+    printf("#endif /* NVRAM_NOT_PRESENT */", file=fd_restore_factory_c)
+    fd_restore_factory_c.close()
+
+    # -----------------------------------------
+    # gen custom_nvram_dom.h
+    # fd_restore_dom_h = open(os.path.join(global_value.path, "nvram_auto_gen", "nvram_restore_dom.h"), "w+")
+    fd_restore_dom_h = autogen_open_file(global_value.autogen_path, "nvram_restore_dom.h", "w+")
+    nvram_gen_restore_dom(fd_restore_dom_h)
+    fd_restore_dom_h.close()
+
+
+if __name__ == '__main__':
+    nvram_gen_restore_function()
diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/tableconstructor.py b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/tableconstructor.py
new file mode 100644
index 0000000..9d9e78d
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/tableconstructor.py
@@ -0,0 +1,646 @@
+import struct
+import logging
+import platform
+from .initconfig import logical_data_item_table
+from .initconfig import const_value
+from .initconfig import global_value
+from .initconfig import LtableEntry, get_checksum_size
+from .initconfig import autogen_open_file, nvram_algo_type, nvram_algo_type_str
+import re
+import os
+import sys, json
+from time import time
+from collections import OrderedDict
+
+
+def pars_segment_info():
+    global_value.logger.info("===== pars_segment_info begin =====")
+    fd = autogen_open_file(global_value.autogen_path, "nvram_auto_gen_target.map", "r")
+    p_custom_algo_addr = 0
+    for each_line in fd:
+        if re.match("\s*\d+\s+\.rodata", each_line ):
+            s = each_line.strip()  # clear head&tail character ('\n' ' ' '\t' '\r')
+            list_rodata = s.split()  # split ("" " " "\n" "\t")
+            global_value.rodata_lma = int(list_rodata[4], base=16)
+            global_value.rodata_off = int(list_rodata[5], base=16)
+        elif re.match("\s*\d+\s+\.data", each_line ):
+            s = each_line.strip()  
+            list_data = s.split()  
+            global_value.data_lma = int(list_data[4], base=16)
+            global_value.data_off = int(list_data[5], base=16)
+        elif re.match("\s*\d+\s+\.bss", each_line ):
+            s = each_line.strip()  
+            list_data = s.split()  
+            global_value.bss_lma = int(list_data[4], base=16)
+            global_value.bss_off = int(list_data[5], base=16)
+        elif re.match("\s*\d+\s+NVRAM_LTABLE", each_line ):
+            s = each_line.strip()  
+            list_t = s.split()  
+            global_value.table_offset = int(list_t[5], base=16)
+            global_value.table_len = int(list_t[2], base=16)
+        elif re.search("\s+nvram_long_length\s+", each_line ):
+            s = each_line.strip()
+            list_t = s.split()
+            global_value.nvram_long_length = int(list_t[4], base=16)
+        elif re.search("\s+nvram_ptr_length\s+", each_line ):
+            s = each_line.strip()
+            list_t = s.split()
+            global_value.nvram_ptr_length = int(list_t[4], base=16)
+        elif re.search("\s+nvram_padding_length\s+", each_line ):
+            s = each_line.strip()
+            list_t = s.split()
+            global_value.nvram_padding_length = int(list_t[4], base=16)
+        elif re.search("\s+nvram_ltable_entry_length\s+", each_line ):
+            s = each_line.strip()
+            list_t = s.split()
+            global_value.nvram_ltable_entry_length = int(list_t[4], base=16)
+        elif re.search("\s+NVRAM_EF_ZERO_DEFAULT\s+", each_line ):
+            s = each_line.strip()
+            list_t = s.split()
+            const_value.NVRAM_EF_ZERO_DEFAULT = int(list_t[0], base=16)
+            continue
+        elif re.search("\s+NVRAM_EF_FF_DEFAULT\s+", each_line ):
+            s = each_line.strip()
+            list_t = s.split()
+            const_value.NVRAM_EF_FF_DEFAULT = int(list_t[0], base=16)
+            continue
+        elif re.search("\s+NVRAM_EF_SPECIAL_DEFAULT\s+", each_line ):
+            s = each_line.strip()
+            list_t = s.split()
+            const_value.NVRAM_EF_SPECIAL_DEFAULT = int(list_t[0], base=16)
+            continue
+        elif global_value.macro & const_value.__NV_CHKSUM_ENHANCE__ and re.search("\s+CUSTOM_CHK_ALGO_CONFIG\s+", each_line ):
+            s = each_line.strip()
+            list_t = s.split()
+            p_custom_algo_addr = int(list_t[0], base=16)
+            continue
+    
+    fd.close()
+    
+    global_value.logger.info("rodata_lma = 0x%x, rodata_off = 0x%x", global_value.rodata_lma, global_value.rodata_off)
+    global_value.logger.info("data_lma = 0x%x, data_off = 0x%x", global_value.data_lma, global_value.data_off)
+    global_value.logger.info("bss_lma = 0x%x, bss_off = 0x%x", global_value.bss_lma, global_value.bss_off)
+    global_value.logger.info("table_offset = 0x%x, table_len = 0x%x, nvram_ltable_entry_length = 0x%x", global_value.table_offset,
+                             global_value.table_len, global_value.nvram_ltable_entry_length)
+    global_value.logger.info("nvram_long_length = %d nvram_ptr_length = %d nvram_padding_length = %d",
+                             global_value.nvram_long_length, global_value.nvram_ptr_length,
+                             global_value.nvram_padding_length)
+    global_value.logger.info("p_NVRAM_EF_ZERO_DEFAULT = 0x%x", const_value.NVRAM_EF_ZERO_DEFAULT)
+    global_value.logger.info("p_NVRAM_EF_FF_DEFAULT = 0x%x", const_value.NVRAM_EF_FF_DEFAULT)
+    global_value.logger.info("p_NVRAM_EF_SPECIAL_DEFAULT = 0x%x", const_value.NVRAM_EF_SPECIAL_DEFAULT)
+    global_value.logger.info("p_custom_algo_addr = 0x%x", p_custom_algo_addr)
+    
+    # ===
+    # check read .map , show error log
+    if (not global_value.rodata_lma) or (not global_value.rodata_off):
+        global_value.logger.error("rodata_lma = 0 or rodata_off = 0 ,read .rodata error!")
+        sys.exit(1)
+    if (not global_value.data_lma) or (not global_value.data_off):
+        global_value.logger.error("data_lma = 0 or data_off = 0 ,read .data error!")
+        sys.exit(1)    
+    if (not global_value.bss_lma) or (not global_value.bss_off):
+        global_value.logger.error("bss_lma = 0 or bss_off = 0 ,read .bss error!")
+        sys.exit(1)    
+    if (not global_value.table_offset) or (not global_value.table_len):
+        global_value.logger.error("table_offset = 0 or table_len = 0 ,read NVRAM_LTABLE error!")
+        sys.exit(1)    
+    if not global_value.nvram_ltable_entry_length:
+        global_value.logger.error("nvram_ltable_entry_length = 0 ,read nvram_ltable_entry_length error!")
+        sys.exit(1)    
+    if not const_value.NVRAM_EF_ZERO_DEFAULT:
+        global_value.logger.error("NVRAM_EF_ZERO_DEFAULT = 0 ,read NVRAM_EF_ZERO_DEFAULT error!")
+        sys.exit(1)    
+    if not const_value.NVRAM_EF_FF_DEFAULT:
+        global_value.logger.error("NVRAM_EF_FF_DEFAULT = 0 ,read NVRAM_EF_FF_DEFAULT error!")
+        sys.exit(1)
+    if not const_value.NVRAM_EF_SPECIAL_DEFAULT:
+        global_value.logger.error("NVRAM_EF_SPECIAL_DEFAULT = 0 ,read NVRAM_EF_SPECIAL_DEFAULT error!")
+        sys.exit(1)
+    # ===
+    
+    fd = autogen_open_file(global_value.autogen_path, "nvram_auto_gen_target", "rb")
+    # check target 64bit or 32bit
+    fd.seek(const_value.LINUX_BIT_ADDR)
+    b = fd.read(1)
+    if type(b) == str: # python 2
+        bit_data = ord(b)
+    else:
+        bit_data = int(b[0])
+    
+    if bit_data == const_value.LINUX_64BIT_DATA:  # 64bit
+        global_value.target_bit = const_value.TARGET_64BIT
+        global_value.logger.debug("Linux target is 64bit! ")
+    elif bit_data == const_value.LINUX_32BIT_DATA:  # 32bit
+        global_value.target_bit = const_value.TARGET_32BIT
+        global_value.logger.debug("Linux target is 32bit! ")
+    else:
+        global_value.logger.debug("check Linux bit error! bit_data = 0x%x", bit_data)
+        sys.exit(1)
+    fd.close()
+    
+    # ===========
+    # read custom algo config
+    if global_value.macro & const_value.__NV_CHKSUM_ENHANCE__:
+        fd = autogen_open_file(global_value.autogen_path, "nvram_auto_gen_target", "rb")
+        if not p_custom_algo_addr:
+            global_value.logger.error("read CUSTOM_CHK_ALGO_CONFIG for map error!")
+            sys.exit(1)
+        custom_algo_offset = offset_elf(p_custom_algo_addr)
+        fd.seek(custom_algo_offset)
+        size = struct.calcsize("4I")
+        b = fd.read(size)
+        s = struct.unpack("4I", b)
+        global_value.enhance_size = s[0]
+        global_value.enhance_type = s[1]
+        global_value.default_size = s[2]
+        global_value.default_type = s[3]
+        global_value.logger.info("enhance_type = %s enhance_size = %d", nvram_algo_type[global_value.enhance_type], global_value.enhance_size)
+        global_value.logger.info("default_type = %s default_size = %d", nvram_algo_type[global_value.default_type], global_value.default_size)
+        fd.close()
+     
+    global_value.logger.info("===== pars_segment_info end =====")
+    
+    
+def offset_elf(offset):
+    if platform.system() == "Windows":   # windows
+        if offset < global_value.data_addr:  # .text
+            offset_exe = offset - global_value.image_base - global_value.text_offset
+        else: #elif offset < global_value.bss_addr: # .data
+            offset_exe = offset - global_value.image_base - global_value.data_offset
+        return offset_exe
+    else:
+        if offset < global_value.data_lma:
+            offset_elf = offset - global_value.rodata_lma + global_value.rodata_off
+        else: #elif offset < global_value.bss_lma:
+            offset_elf = offset - global_value.bss_lma + global_value.bss_off
+        return offset_elf
+
+    
+def parse_lid_table():
+    """ read ldi table from exe/elf """
+    # -------------------------------------------------
+    # generate struct.unpack fmt by parse .map and .elf
+    global_value.logger.info("===== parse_lid_table begin =====")
+    
+    entry_table_file = os.path.join(global_value.autogen_path, "entry_tables.json")
+    if os.path.exists(entry_table_file):
+        # reuse entry generated by NVDB
+        zero_default = u"00"
+        ff_default = u"ff"
+        special_default = u"55"
+        
+        with open(entry_table_file, "r") as fh:
+            entry_data = json.load(fh)
+        
+        for entry in entry_data:
+            entry_obj = LtableEntry()
+            entry_obj.lid = entry["LID"]
+            entry_obj.total_records = entry["total_records"]
+            entry_obj.size = entry["size"]
+            # one_entry.p_str_default_value = var[3]
+            #one_entry.p_default_value = var[4]
+            entry_obj.category = entry["category"]
+            entry_obj.attr = entry["attr"]
+            entry_obj.FilePrefix = entry["fileprefix"]
+            entry_obj.FileVerno = entry["fileverno"]
+            entry_obj.str_LID = entry["str_LID"]
+            entry_obj.description = entry["description"]
+            # handle default value
+            if entry["default_value"].isalnum():
+                d_val = entry["default_value"]
+                if entry_obj.attr & const_value.NVRAM_ATTR_MULTI_DEFAULT:
+                    entry_obj.default_value_len = entry_obj.size * entry_obj.total_records
+                else:
+                    entry_obj.default_value_len = entry_obj.size
+                if d_val in (zero_default, ff_default, special_default):       # workaround for custpack default value
+                    entry_obj.default_value_len = 1
+                entry_obj.default_value = [int(d_val[index-2: index], 16) for index in range(2, len(d_val)+1, 2)]
+            elif entry["default_value"] in "NVRAM_EF_ZERO_DEFAULT":
+                entry_obj.p_default_value = const_value.NVRAM_EF_ZERO_DEFAULT
+            elif entry["default_value"] == "NVRAM_EF_FF_DEFAULT":
+                entry_obj.p_default_value = const_value.NVRAM_EF_FF_DEFAULT
+                # entry_obj.default_value = ['FF']
+            else:
+                entry_obj.str_default_value = entry["default_value"]
+            if "hash_key" in entry:
+                entry_obj.hash_key = entry["hash_key"]
+            #if (global_value.macro & const_value.__NVRAM_LID_HASH_CHECK__) and (global_value.macro & const_value.__MTK_INTERNAL__):
+            #    one_entry.hash_key = var[11]
+            logical_data_item_table.append(entry_obj)
+    else:
+        fd_map = autogen_open_file(global_value.autogen_path, "nvram_auto_gen_target.map", "r")
+        if platform.system() == "Windows":   # windows
+            fd_elf = autogen_open_file(global_value.autogen_path, "nvram_auto_gen_target.exe", "rb")
+        else:
+            fd_elf = autogen_open_file(global_value.autogen_path, "nvram_auto_gen_target", "rb")
+        
+        fmt = gen_unpack_fmt(fd_map, fd_elf, global_value.nvram_ltable_entry_length)
+        fd_map.close()
+        global_value.logger.info("unpack fmt = %s", fmt)
+        
+        # -------------------------------------------------
+        # parse lid_table
+        table_total_item = global_value.table_len // global_value.nvram_ltable_entry_length
+        fd_elf.seek(global_value.table_offset)
+        for i in range(table_total_item):
+            r_bin = fd_elf.read(global_value.nvram_ltable_entry_length)
+            var = struct.unpack(fmt, r_bin)
+            one_entry = LtableEntry()
+            one_entry.lid = var[0]
+            one_entry.total_records = var[1]
+            one_entry.size = var[2]
+            one_entry.p_str_default_value = var[3]
+            one_entry.p_default_value = var[4]
+            one_entry.category = var[5]
+            one_entry.attr = var[6]
+            one_entry.FilePrefix = var[7].decode("ascii")[:-1]
+            one_entry.FileVerno = var[8].decode("ascii")[:-1]
+            one_entry.p_str_LID = var[9]
+            one_entry.p_description = var[10]
+            if (global_value.macro & const_value.__NVRAM_LID_HASH_CHECK__) and (global_value.macro & const_value.__MTK_INTERNAL__):
+                one_entry.hash_key = var[11]
+            # ---------------
+            logical_data_item_table.append(one_entry)
+    
+    for i, ldi in enumerate(logical_data_item_table):
+        global_value.logger.debug("%d lid = %d size = %d total = %d", i, ldi.lid, ldi.size, ldi.total_records)
+
+    
+    global_value.logger.info("===== parse_lid_table end =====")
+
+def get_oft_data(fd_map, fd_elf, map_name):
+    """ get real data from map_name """
+    fd_map.seek(0)
+    addr = 0x0
+    find_data = "\s+" + map_name + "\s+"
+    for each_line in fd_map:
+        if re.search(find_data, each_line):
+            s = each_line.strip()
+            list_t = s.split()
+            addr = int(list_t[0], base=16)
+            break
+    if addr == 0:
+        global_value.logger.debug("==== get_oft_data() ====")
+        global_value.logger.debug("find_data = %s", find_data)
+        global_value.logger.error("%s not found in .map ", map_name)
+        sys.exit(1)
+    if check_bss(addr):     # bss 
+        return 0x0
+    offset_for_elf = offset_elf(addr)   
+    
+    # read oft_data
+    fd_elf.seek(offset_for_elf)
+    bin_s = fd_elf.read(2)
+    fmt = "H"
+    offset_data = struct.unpack(fmt, bin_s)[0]
+    return offset_data
+       
+def gen_unpack_fmt(fd_map, fd_elf, ltable_entry_len):
+    """ generate struct.unpack fmt by parse .map and .elf """
+    # define variables
+    ent_fmt = ""
+    pad_str = "x"   # padding fmt
+    # big_endian = ">"
+    # little_endian = "<"
+    ent_stu_list = [    
+        {"map_name": "ent_oft_lid",     "oft_data": 0, "fmt": "H",  "fmt_size": 2},
+        {"map_name": "ent_oft_trecords","oft_data": 0, "fmt": "H",  "fmt_size": 2},
+        {"map_name": "ent_oft_size",    "oft_data": 0, "fmt": "I",  "fmt_size": 4},
+        {"map_name": "ent_oft_str_dval","oft_data": 0, "fmt": "I",  "fmt_size": 4},
+        {"map_name": "ent_oft_d_val",   "oft_data": 0, "fmt": "I",  "fmt_size": 4},
+        {"map_name": "ent_oft_cate",    "oft_data": 0, "fmt": "I",  "fmt_size": 4},
+        {"map_name": "ent_oft_attr",    "oft_data": 0, "fmt": "I",  "fmt_size": 4},
+        {"map_name": "ent_oft_fprefix", "oft_data": 0, "fmt": "5s", "fmt_size": 5},
+        {"map_name": "ent_oft_fverno",  "oft_data": 0, "fmt": "4s", "fmt_size": 4},
+        {"map_name": "ent_oft_s_lid",   "oft_data": 0, "fmt": "I",  "fmt_size": 4},
+        {"map_name": "ent_oft_desc",    "oft_data": 0, "fmt": "I",  "fmt_size": 4},
+    ]
+    if (global_value.macro & const_value.__NVRAM_LID_HASH_CHECK__) and (global_value.macro & const_value.__MTK_INTERNAL__):
+        global_value.logger.info("nvram lid hash check  open")
+        ent_off_item = {"map_name": "ent_oft_hash",    "oft_data": 0, "fmt": "I",  "fmt_size": 4}
+        ent_stu_list.append(ent_off_item)
+    else:
+        global_value.logger.info("hash check disabled")
+        
+    # default 32bit
+    if global_value.target_bit == const_value.TARGET_64BIT:
+        ent_stu_list[3]["fmt"] = "Q"        # p_str_default_value
+        ent_stu_list[3]["fmt_size"] = 8
+        ent_stu_list[4]["fmt"] = "Q"        # p_default_value
+        ent_stu_list[4]["fmt_size"] = 8
+        ent_stu_list[9]["fmt"] = "Q"        # p_str_LID
+        ent_stu_list[9]["fmt_size"] = 8
+        ent_stu_list[10]["fmt"] = "Q"       # p_description
+        ent_stu_list[10]["fmt_size"] = 8
+    
+    
+    
+    for each_list in ent_stu_list:
+        each_list["oft_data"] = get_oft_data(fd_map, fd_elf, each_list["map_name"])
+    
+    real_offset = 0
+    for i in range(len(ent_stu_list)):
+        dict_data = ent_stu_list[i]
+        item_offset = dict_data["oft_data"]
+        item_fmt = dict_data["fmt"]
+        item_size = dict_data["fmt_size"]
+        
+        if real_offset == item_offset:
+            ent_fmt += item_fmt
+            real_offset += item_size
+        elif real_offset < item_offset:     # padding exists
+            padding_size = item_offset - real_offset
+            for j in range(padding_size):   # add padding
+                ent_fmt += pad_str
+                real_offset += 1
+            ent_fmt += item_fmt
+            real_offset += item_size
+        else:   # real_offset > item_offset => error
+            global_value.logger.error("ent_fmt = %s, real_offset = %d, item_offset = %d item_size = %d",
+                                  ent_fmt, real_offset, item_offset, item_size)
+            for j in range(len(ent_stu_list)):
+                data = ent_stu_list[j]
+                global_value.logger.debug("map_name = %s oft_data = %d, fmt = %s fmt_size = %d",
+                                  data["map_name"], data["oft_data"], data["fmt"], data["fmt_size"])
+            sys.exit(1)
+    
+    return ent_fmt
+    
+    
+def read_binary_to_str(fd, offset):
+    """ binary to str"""
+    strs = ""
+    fd.seek(offset)
+    b = fd.read(1)
+    if type(b) == str: # python 2
+        while b != "\x00":
+            strs += b
+            b = fd.read(1)
+    else:  # python 3
+        while int(b[0]) != 0:
+            strs += chr(b[0])
+            b = fd.read(1)
+    return strs
+
+
+
+def read_str_in_binary(fd, addr):
+    offset = offset_elf(addr)
+    strs = read_binary_to_str(fd, offset)
+    return strs
+    
+
+def nvram_util_make_lid_filename(attr, fileprefix, fileverno, first_copy):
+    """ Get nvram file name"""
+    nvram_name = ""
+    if attr & const_value.NVRAM_ATTR_MULTIPLE:
+        if first_copy:
+            nvram_name = fileprefix + "A" + fileverno
+        else:
+            nvram_name = fileprefix + "B" + fileverno
+    else:
+        nvram_name = fileprefix + "_" + fileverno
+
+    return nvram_name
+
+
+def nvram_query_file_name(category, nvram_name):
+    """ Get file full name """
+    if (global_value.macro & const_value.__NVRAM_UT_TEST__) and (not global_value.macro & const_value.__NVRAM_LID_CACHE__):
+        if category & const_value.NVRAM_CATEGORY_INTERNAL:  # CORE
+            src_path = const_value.NVRAM_TEST_FS_COREITEM_PATH + "\\\\" + nvram_name
+        elif category & const_value.NVRAM_CATEGORY_CALIBRAT:  # CALI
+            src_path = const_value.NVRAM_TEST_FS_CALIBRAT_DATAITEM_PATH + "\\\\" + nvram_name
+        elif category & const_value.NVRAM_CATEGORY_IMPORTANT:  # IMPT
+            src_path = const_value.NVRAM_TEST_FS_IMPT_DATAITEM_PATH + "\\\\" + nvram_name
+        elif (category & const_value.NVRAM_CATEGORY_IMPORTANT_L4) and (global_value.macro & const_value.__CCCIFS_SUPPORT__):  # IMPNT
+            if global_value.macro & (const_value.__MTK_TARGET__ | const_value.__NVRAM_IMPORTANT_PARTIONS__ | const_value.__CCCIFS_SUPPORT__):
+                src_path = "X:\\\\NV_TEST\\\\" + nvram_name
+            else:
+                src_path = const_value.NVRAM_TEST_FS_IMPORTNT_DATAITEM_PATH + "\\\\" + nvram_name
+        elif (category & const_value.NVRAM_CATEGORY_IMPORTANT_L1) and (global_value.macro & const_value.__CCCIFS_SUPPORT__):  # IMPNT
+            if global_value.macro & (const_value.__MTK_TARGET__ | const_value.__NVRAM_IMPORTANT_PARTIONS__ | const_value.__CCCIFS_SUPPORT__):
+                src_path = "X:\\\\NV_TEST\\\\" + nvram_name
+            else:
+                src_path = const_value.NVRAM_TEST_FS_IMPORTNT_DATAITEM_PATH + "\\\\" + nvram_name
+        elif (category & const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE) and (global_value.macro & const_value.__NVRAM_CUSTOM_SENSITIVE__):  # CUST
+            src_path = const_value.NVRAM_FS_CUST_DATAITEM_PATH + "\\\\" + nvram_name
+        else:  # DATA
+            src_path = const_value.NVRAM_TEST_FS_DATAITEM_PATH + "\\\\" + nvram_name
+    else:
+        if category & const_value.NVRAM_CATEGORY_INTERNAL:  # CORE
+            src_path = const_value.NVRAM_FS_COREITEM_PATH + "\\\\" + nvram_name
+        elif category & const_value.NVRAM_CATEGORY_CALIBRAT:  # CALI
+            src_path = const_value.NVRAM_FS_CALIBRAT_DATAITEM_PATH + "\\\\" + nvram_name
+        elif category & const_value.NVRAM_CATEGORY_IMPORTANT:  # IMPT
+            src_path = const_value.NVRAM_FS_IMPT_DATAITEM_PATH + "\\\\" + nvram_name
+        elif (category & const_value.NVRAM_CATEGORY_IMPORTANT_L4) and (global_value.macro & const_value.__CCCIFS_SUPPORT__):  # IMPNT
+            if global_value.macro & (const_value.__MTK_TARGET__ | const_value.__NVRAM_IMPORTANT_PARTIONS__ | const_value.__CCCIFS_SUPPORT__):
+                src_path = "X:\\\\" + nvram_name
+            else:
+                src_path = const_value.NVRAM_FS_IMPORTNT_DATAITEM_PATH + "\\\\" + nvram_name
+        elif (category & const_value.NVRAM_CATEGORY_IMPORTANT_L1) and (global_value.macro & const_value.__CCCIFS_SUPPORT__):  # IMPNT
+            if global_value.macro & (const_value.__MTK_TARGET__ | const_value.__NVRAM_IMPORTANT_PARTIONS__ | const_value.__CCCIFS_SUPPORT__):
+                src_path = "X:\\\\" + nvram_name
+            else:
+                src_path = const_value.NVRAM_FS_IMPORTNT_DATAITEM_PATH + "\\\\" + nvram_name
+        elif (category & const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE) and (global_value.macro & const_value.__NVRAM_CUSTOM_SENSITIVE__):  # CUST
+            src_path = const_value.NVRAM_FS_CUST_DATAITEM_PATH + "\\\\" + nvram_name
+        else:  # DATA
+            src_path = const_value.NVRAM_FS_DATAITEM_PATH + "\\\\" + nvram_name
+
+    return src_path
+
+
+def path_finder(ldi):
+    """ Get lid filepath"""
+    # set secupack FilePrefix in "ST**"
+    if ldi.category & const_value.NVRAM_CATEGORY_SECUPACK:
+        prefix_temp = "ST" + ldi.FilePrefix[2:]
+        nvram_name = nvram_util_make_lid_filename(ldi.attr, prefix_temp, ldi.FileVerno, True)
+    else:
+        nvram_name = nvram_util_make_lid_filename(ldi.attr, ldi.FilePrefix, ldi.FileVerno, True)
+    src_path = nvram_query_file_name(ldi.category, nvram_name)
+    return src_path
+
+
+def file_size_collector(ldi):
+    if global_value.macro & const_value.__NV_CHKSUM_ENHANCE__:
+        if ldi.attr & const_value.NVRAM_ATTR_CHKSM_ENHNC_ALGRTHM:
+            if global_value.enhance_type == nvram_algo_type_str["NVRAM_MD5"]:
+                nvram_checksum_size = const_value.NVRAM_CHKSUM_SIZE
+            else:
+                nvram_checksum_size = global_value.enhance_size
+        else:
+            if global_value.default_type == nvram_algo_type_str["NVRAM_MD5"]:
+                nvram_checksum_size = const_value.NVRAM_CHKSUM_SIZE
+            else:
+                nvram_checksum_size = global_value.default_size
+    else:
+        nvram_checksum_size = const_value.NVRAM_CHKSUM_SIZE
+
+    """ Get file size """
+    if (ldi.attr & const_value.NVRAM_ATTR_CONFIDENTIAL) or (ldi.attr & const_value.NVRAM_ATTR_MSP and global_value.macro & const_value.__NVRAM_BIND_TO_CHIP_CIPHER__):
+        remainLen = (~(ldi.size + nvram_checksum_size) + 1) & (const_value.NVRAM_MSP_ALIGNMENT - 1)
+        onefilesize = (
+                                  ldi.size + nvram_checksum_size + remainLen) * ldi.total_records + const_value.NVRAM_LDI_HEADER_SIZE
+    else:
+        onefilesize = (ldi.size + nvram_checksum_size) * ldi.total_records + const_value.NVRAM_LDI_HEADER_SIZE
+    
+    if ldi.attr & const_value.NVRAM_ATTR_CHKSUM_INTEGRATE:
+        # global_value.logger.debug("checksum integrate: lid: %s", ldi.str_LID)
+        onefilesize = onefilesize + const_value.NVRAM_LDI_APPENDIX_HEADER_SIZE + nvram_checksum_size * ldi.total_records
+    
+    return onefilesize
+
+
+def statistic_lid_item_data():
+    """ statistic cuspack/secupack/otp/sds/auto_pack total&size """
+    global_value.logger.info("===== statistic_lid_item_data begin =====")
+    global_value.custpack_total_to_verify = 0
+    global_value.secupack_total_to_verify = 0
+    global_value.secupack_size_to_verify = 0
+    global_value.otp_total_to_verify = 0
+    global_value.otp_size_to_verify = 0
+    global_value.sds_total_to_verify = 0
+    global_value.sds_size_to_verify = 0
+    global_value.nvram_auto_package_num = 0
+    global_value.nvram_auto_pack_file_offset = 0
+
+    for ldi in logical_data_item_table:
+        nvram_checksum_size = get_checksum_size(ldi)
+        # calculate the custpack
+        if ldi.category & const_value.NVRAM_CATEGORY_CUSTPACK:
+            global_value.custpack_total_to_verify += 1
+        # calculate the secupack
+        if ldi.category & const_value.NVRAM_CATEGORY_SECUPACK:
+            global_value.secupack_total_to_verify += 1
+            if ldi.attr & const_value.NVRAM_ATTR_MULTI_DEFAULT:
+                global_value.secupack_size_to_verify += ldi.size * ldi.total_records + nvram_checksum_size
+            else:
+                global_value.secupack_size_to_verify += ldi.size + nvram_checksum_size
+        # calculate the otp
+        if ldi.category & const_value.NVRAM_CATEGORY_OTP:  # __NVRAM_OTP__
+            global_value.otp_total_to_verify += 1
+            global_value.otp_size_to_verify += ldi.size * ldi.total_records
+        # calculate the vendor reserve size
+        if ldi.category & const_value.NVRAM_CATEGORY_BACKUP_SDS:  # __NVRAM_SECURE_DATA_STORAGE__
+            global_value.sds_total_to_verify += 1
+            global_value.sds_size_to_verify += (ldi.size + nvram_checksum_size +
+                                                ((~(ldi.size + nvram_checksum_size) + 1) & (
+                                                        const_value.NVRAM_MSP_ALIGNMENT - 1))
+                                                ) * ldi.total_records
+        # calcluate the package
+        onefilefssize = (
+                                    ldi.FileSize + const_value.FS_PAGE_SIZE - 1) // const_value.FS_PAGE_SIZE * const_value.FS_PAGE_SIZE
+        if onefilefssize & ldi.attr & const_value.NVRAM_ATTR_PACKAGE:  # __NVRAM_PSEUDO_MERGE__
+            global_value.nvram_auto_package_num += 1
+            global_value.nvram_auto_pack_file_offset += onefilefssize
+    global_value.logger.info("===== statistic_lid_item_data end =====")
+
+"""
+check whether it is bss segment
+in : addr for .map
+out: true, bss segment ; false , not bss segment
+"""
+def check_bss(addr):
+    if platform.system() == "Windows":   # windows
+        if addr >= global_value.bss_addr: # .bss ,write 0x00
+            return True
+        else:
+            return False
+    else:
+        if addr >= global_value.bss_lma:
+            return True
+        else:
+            return False
+        
+            
+def parse_lid_item_data():
+    """ read read data from str_default_value/str_LID/description, caluculate filesize/full path """
+    global_value.logger.info("===== parse_lid_item_data begin =====")
+    entry_table_file = os.path.join(global_value.autogen_path, "entry_tables.json")
+    # NVDB not gen ltable entry, read from map and elf
+    if not os.path.exists(entry_table_file):
+        if platform.system() == "Windows":   # windows
+            fd_target = autogen_open_file(global_value.autogen_path, "nvram_auto_gen_target.exe", "rb")
+        else:
+            fd_target = autogen_open_file(global_value.autogen_path, "nvram_auto_gen_target", "rb")
+        
+        # ---------------------------------------------
+        # parse data item in target.elf
+        for i in range(len(logical_data_item_table)):
+            ldi = logical_data_item_table[i]
+            if ldi.category & const_value.NVRAM_CATEGORY_FUNC_DEFAULT:
+                # parse str_default_value
+                ldi.str_default_value = read_str_in_binary(fd_target, ldi.p_str_default_value)
+            elif ldi.p_default_value != const_value.NVRAM_EF_ZERO_DEFAULT \
+                    and ldi.p_default_value != const_value.NVRAM_EF_FF_DEFAULT \
+                    and ldi.p_default_value != const_value.NVRAM_EF_SPECIAL_DEFAULT:
+                # parse default_value
+                if ldi.attr & const_value.NVRAM_ATTR_MULTI_DEFAULT:
+                    ldi.default_value_len = ldi.size * ldi.total_records
+                else:
+                    ldi.default_value_len = ldi.size
+                
+                list_default_value = []
+                if check_bss(ldi.p_default_value):
+                    for j in range(ldi.default_value_len):
+                        list_default_value.append(0x00)
+                else:
+                    offset = offset_elf(ldi.p_default_value)
+                    fd_target.seek(offset)
+                    b = fd_target.read(ldi.default_value_len)
+                    if type(b[0]) == str: # python 2
+                        list_str = list(b)
+                        for data in list_str:
+                            list_default_value.append(ord(data))
+                    else:  # python 3
+                        list_default_value = list(b)
+                        
+                ldi.default_value = list_default_value
+
+            # parse str_LID
+            ldi.str_LID = read_str_in_binary(fd_target, ldi.p_str_LID)
+            # parse description
+            if ldi.p_description != 0:
+                ldi.description = read_str_in_binary(fd_target, ldi.p_description)
+        fd_target.close()
+    
+    # --------------------------
+    # Get full path & file size
+    for lid in logical_data_item_table:
+        lid.FullPath = path_finder(lid)
+        lid.FileSize = file_size_collector(lid)
+
+        # lid = logical_data_item_table[i]
+        global_value.logger.debug("-------------------------------------------------")
+        global_value.logger.debug("lid = %d total = %d size = %d", lid.lid, lid.total_records, lid.size)
+        global_value.logger.debug("cate = 0x%x attr = 0x%x prefix = %s verno = %s", lid.category, lid.attr,
+                                 lid.FilePrefix, lid.FileVerno)
+        global_value.logger.debug("str_LID = %s str_default_value = %s", lid.str_LID, lid.str_default_value)
+        global_value.logger.debug("description = %s", lid.description)
+        global_value.logger.debug("full path = %s", lid.FullPath)
+        global_value.logger.debug("File Size = %s", lid.FileSize)
+    
+    global_value.logger.info("===== parse_lid_item_data end =====")
+
+def write_logical_table():
+    """write entry table into json file. for NVDB debug use"""
+    logical_table_path = os.path.join(global_value.autogen_path, "autogen_v2_ltables.json")
+    ltable_datas = []
+    for ldi in logical_data_item_table:
+        entry = OrderedDict()
+        entry["LID"] = ldi.lid
+        entry["total_records"] = ldi.total_records
+        entry["size"] = ldi.size
+        entry["category"] = ldi.category
+        entry["attr"] = ldi.attr
+        entry["fileprefix"] = ldi.FilePrefix
+        entry["fileverno"] = ldi.FileVerno
+        entry["str_LID"] = ldi.str_LID
+        entry["hash_key"] = ldi.hash_key
+        ltable_datas.append(entry)
+    with open(logical_table_path, "w") as fh:
+        json.dump(ltable_datas, fh)
+        
diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/tableconstructor_win.py b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/tableconstructor_win.py
new file mode 100644
index 0000000..132ba98
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/tableconstructor_win.py
@@ -0,0 +1,253 @@
+import struct
+import logging
+from .initconfig import logical_data_item_table
+from .initconfig import const_value
+from .initconfig import global_value
+from .initconfig import LtableEntry
+from .initconfig import autogen_open_file, nvram_algo_type
+from .tableconstructor import offset_elf
+import re
+import os
+
+def read_int_in_exe(fd, addr):
+    offset = offset_elf(addr)
+    fd.seek(offset)
+    r_bin = fd.read(4)
+    data = struct.unpack("I", r_bin)[0]
+    return data
+
+
+def parse_segment_info_win():
+    """ parse of segment data from target.map & target.exe (.rodata/.data/.bss)  """
+    global_value.logger.info("===== parse_segment_info_win begin ===== ")
+    fd = autogen_open_file(global_value.autogen_path, "nvram_auto_gen_target.map", "r")
+    p_custom_algo_addr = 0
+    
+    for each_line in fd:
+        if re.match(".text", each_line):
+            s = each_line.strip()  # clear head&tail character ('\n' ' ' '\t' '\r')
+            list_rodata = s.split()  # split ("" " " "\n" "\t")
+            global_value.text_addr = int(list_rodata[1], base=16)  # addr 
+            # self.text_len = int(list_rodata[2], base=16)  # length
+        elif re.search("\s+__data_start__\s+", each_line):
+            s = each_line.strip()  # clear head&tail character ('\n' ' ' '\t' '\r')
+            list_data = s.split()  # split ("" " " "\n" "\t")
+            global_value.data_addr = int(list_data[0], base=16)  # addr
+            # self.data_len = int(list_data[2], base=16)  # length
+        elif re.search("\s+__bss_start__\s+", each_line):
+            s = each_line.strip()  # clear head&tail character ('\n' ' ' '\t' '\r')
+            list_bss = s.split()  # split ("" " " "\n" "\t")
+            global_value.bss_addr = int(list_bss[0], base=16)    # addr
+            # self.bss_len = int(list_bss[2], base=16)    # length
+        elif re.search("\s+__image_base__\s+", each_line):
+            s = each_line.strip()  # clear head&tail character ('\n' ' ' '\t' '\r')
+            list_bss = s.split()  # split ("" " " "\n" "\t")
+            global_value.image_base = int(list_bss[0], base=16)   
+        elif re.search("\s+_nvram_ltable_begin\s+", each_line):
+            s = each_line.strip()  # clear head&tail character ('\n' ' ' '\t' '\r')
+            # l = re.split("\W+", s)
+            list_t = s.split()  # split ("" " " "\n" "\t")
+            table_begin = int(list_t[0], base=16)
+        elif re.search("\s+_nvram_ltable_end\s+", each_line):
+            s = each_line.strip()  # clear head&tail character ('\n' ' ' '\t' '\r')
+            # l = re.split("\W+", s)
+            list_t = s.split()  # split ("" " " "\n" "\t")
+            table_end = int(list_t[0], base=16)
+        elif re.search("\s+nvram_ltable_entry_size\s+", each_line):
+            s = each_line.strip()
+            # l = re.split("\W+", s)
+            list_t = s.split()
+            nvram_ltable_entry_size_addr = int(list_t[0], base=16)
+        elif re.search("\s+NVRAM_EF_ZERO_DEFAULT\s+", each_line):
+            s = each_line.strip()
+            list_t = s.split()
+            const_value.NVRAM_EF_ZERO_DEFAULT = int(list_t[0], base=16)
+        elif re.search("\s+NVRAM_EF_FF_DEFAULT\s+", each_line):
+            s = each_line.strip()
+            list_t = s.split()
+            const_value.NVRAM_EF_FF_DEFAULT = int(list_t[0], base=16)
+        elif re.search("\s+NVRAM_EF_SPECIAL_DEFAULT\s+", each_line):
+            s = each_line.strip()
+            list_t = s.split()
+            const_value.NVRAM_EF_SPECIAL_DEFAULT = int(list_t[0], base=16)
+        elif global_value.macro & const_value.__NV_CHKSUM_ENHANCE__ and re.search("\s+CUSTOM_CHK_ALGO_CONFIG\s+", each_line ):
+            s = each_line.strip()
+            list_t = s.split()
+            p_custom_algo_addr = int(list_t[0], base=16)
+            
+    fd.close()
+    
+    
+    global_value.table_len = table_end - table_begin
+    global_value.logger.info("text_addr = 0x%x", global_value.text_addr)
+    global_value.logger.info("data_addr = 0x%x", global_value.data_addr)
+    global_value.logger.info("bss_addr = 0x%x", global_value.bss_addr)
+    global_value.logger.info("image_base = 0x%x", global_value.image_base)
+    global_value.logger.info("nvram_ltable_entry_size_addr = 0x%x", nvram_ltable_entry_size_addr)
+    global_value.logger.info("table_len = 0x%x", global_value.table_len)
+    
+    # ===
+    # check read .map , show error log
+    if not global_value.text_addr:
+        global_value.logger.debug("text_addr = 0 ,read .text error!")
+        sys.exit(1)
+    if not global_value.data_addr:
+        global_value.logger.debug("data_addr = 0 ,read __data_start__ error!")
+        sys.exit(1)
+    if not global_value.bss_addr:
+        global_value.logger.debug("bss_addr = 0 ,read __bss_start__ error!")  
+        sys.exit(1)
+    if not global_value.image_base:
+        global_value.logger.debug("image_base = 0 ,read __image_base__ error!")  
+        sys.exit(1)    
+    if not table_begin:
+        global_value.logger.debug("table_begin = 0 ,read _nvram_ltable_begin error!")  
+        sys.exit(1)    
+    if not table_end:
+        global_value.logger.debug("table_end = 0 ,read _nvram_ltable_end error!")  
+        sys.exit(1)    
+    if not nvram_ltable_entry_size_addr:
+        global_value.logger.debug("nvram_ltable_entry_size_addr = 0 ,read nvram_ltable_entry_size error!")  
+        sys.exit(1)
+    if not const_value.NVRAM_EF_ZERO_DEFAULT:
+        global_value.logger.debug("NVRAM_EF_ZERO_DEFAULT = 0 ,read NVRAM_EF_ZERO_DEFAULT error!")  
+        sys.exit(1)
+    if not const_value.NVRAM_EF_FF_DEFAULT:
+        global_value.logger.debug("NVRAM_EF_FF_DEFAULT = 0 ,read NVRAM_EF_FF_DEFAULT error!")  
+        sys.exit(1)
+    if not const_value.NVRAM_EF_SPECIAL_DEFAULT:
+        global_value.logger.debug("NVRAM_EF_SPECIAL_DEFAULT = 0 ,read NVRAM_EF_SPECIAL_DEFAULT error!")  
+        sys.exit(1)
+    # ===
+    
+    # fd = open(os.path.join(global_value.path, "nvram_auto_gen", "nvram_auto_gen_target.exe"), "rb")
+    fd = autogen_open_file(global_value.autogen_path, "nvram_auto_gen_target.exe", "rb")
+    # read dos header
+    dos_header_len = 0x40
+    r_bin = fd.read(dos_header_len)
+    s = struct.unpack("16I", r_bin)
+    pe_file_header_offset = s[15]
+    # read pe file header
+    fd.seek(pe_file_header_offset)
+    pe_file_header_length = 0x18
+    r_bin = fd.read(pe_file_header_length)
+    s = struct.unpack("5I2H", r_bin)
+    op_header_size = s[5]
+    # read section info
+    section_offset = pe_file_header_offset + pe_file_header_length + op_header_size
+    section_info_length = 0x28
+    fd.seek(section_offset)
+    for i in range(5):
+        r_bin = fd.read(section_info_length)
+        s = struct.unpack("8s6I2HI", r_bin)
+        name = s[0].decode("ascii")[:-1]
+        start = s[2]
+        size = s[3]
+        file_offset = s[4]
+        global_value.logger.info("name = %s, start = %x, size = %x, file_offset = %x",
+                                         name, start, size, file_offset)
+        # if name.count(".text") != 0:
+        if re.match(".text", name):
+            text_offset = start - file_offset
+        # elif name.count(".data") != 0:
+        elif re.match(".data", name):
+            data_offset = start - file_offset
+        # elif name.count(".bss") != 0:
+        elif re.match(".bss", name):
+            bss_offset = start - file_offset
+        # elif name.count(".idata") != 0:
+        elif re.match(".idata", name):
+            pass
+        else:   # ltable
+            ltable_offset = start - file_offset
+    
+    # print("%x %x %x %x" % (text_offset, data_offset, bss_offset, ltable_offset))
+    
+    global_value.text_offset = text_offset
+    global_value.data_offset = data_offset
+    global_value.bss_offset = bss_offset
+    global_value.ltable_offset = ltable_offset
+    global_value.logger.info("text_offset = %x, data_offset = %x, bss_offset = %x, ltable_offset = %x",
+                                         global_value.text_offset, global_value.data_offset,
+                                         global_value.bss_offset, global_value.ltable_offset)
+    # ===
+    if not global_value.text_offset:
+        global_value.logger.debug("text_offset = 0 ,read .exe header error!")  
+        sys.exit(1)
+    if not global_value.data_offset:
+        global_value.logger.debug("data_offset = 0 ,read .exe header error!")  
+        sys.exit(1)    
+    if not global_value.bss_offset:
+        global_value.logger.debug("bss_offset = 0 ,read .exe header error!")  
+        sys.exit(1)
+    if not global_value.ltable_offset:
+        global_value.logger.debug("ltable_offset = 0 ,read .exe header error!")  
+        sys.exit(1)
+    # ===
+                                         
+    global_value.nvram_ltable_entry_length = read_int_in_exe(fd, nvram_ltable_entry_size_addr)
+    global_value.logger.info("nvram_ltable_entry_length = 0x%x", global_value.nvram_ltable_entry_length)
+    
+    
+    # check target 64bit or 32bit
+    fd.seek(const_value.WIN_BIT_ADDR)
+    b = fd.read(1)
+    if type(b) == str: # python 2
+        bit_data = ord(b)
+    else:
+        bit_data = int(b[0])
+    
+    if bit_data == const_value.WIN_64BIT_DATA:  # 64bit
+        global_value.target_bit = const_value.TARGET_64BIT
+        global_value.logger.debug("win target is 64bit! ")
+    elif bit_data == const_value.WIN_32BIT_DATA:  # 32bit
+        global_value.target_bit = const_value.TARGET_32BIT
+        global_value.logger.debug("win target is 32bit! ")
+    else:
+        global_value.logger.debug("check win bit error! bit_data = 0x%x", bit_data)
+        sys.exit(1)
+    
+    
+    
+    fd.close()   
+    
+    if not global_value.nvram_ltable_entry_length:
+        global_value.logger.debug("nvram_ltable_entry_length = 0 ,read .exe info error!")  
+        sys.exit(1)
+    
+    global_value.table_offset = table_begin - global_value.image_base - global_value.ltable_offset
+    global_value.logger.info("table_offset = 0x%x", global_value.table_offset)
+    
+    # ===========
+    # read custom algo config
+    if global_value.macro & const_value.__NV_CHKSUM_ENHANCE__:
+        fd = autogen_open_file(global_value.autogen_path, "nvram_auto_gen_target.exe", "rb")
+        if not p_custom_algo_addr:
+            global_value.logger.debug("read CUSTOM_CHK_ALGO_CONFIG for map error!")
+            sys.exit(1)
+        custom_algo_offset = offset_elf(p_custom_algo_addr)
+        fd.seek(custom_algo_offset)
+        size = struct.calcsize("4I")
+        b = fd.read(size)
+        s = struct.unpack("4I", b)
+        global_value.enhance_size = s[0]
+        global_value.enhance_type = s[1]
+        global_value.default_size = s[2]
+        global_value.default_type = s[3]
+        global_value.logger.info("enhance_type = %s enhance_size = %d", nvram_algo_type[global_value.enhance_type], global_value.enhance_size)
+        global_value.logger.info("default_type = %s default_size = %d", nvram_algo_type[global_value.default_type], global_value.default_size)
+        fd.close()
+    
+    global_value.logger.info("===== parse_segment_info_win end ===== ")
+    
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/targethelper.py b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/targethelper.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/src/targethelper.py
diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/autogen/utils/__init__.py b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/utils/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/utils/__init__.py
diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/autogen/utils/config.py b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/utils/config.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/utils/config.py
diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/autogen/utils/encrypt.py b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/utils/encrypt.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/utils/encrypt.py
diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/autogen/utils/exceptions.py b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/utils/exceptions.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/autogen/utils/exceptions.py
diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/run.py b/mcu/tools/NVRAMStatistic/autogen_v2/run.py
new file mode 100644
index 0000000..26521a1
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/run.py
@@ -0,0 +1,32 @@
+import sys

+import getopt

+from autogen import main

+

+

+if __name__ == '__main__':

+    try:

+        opts, args = getopt.getopt(sys.argv[1:], "tl:p:")

+    except getopt.GetoptError:

+        print("Example of command")

+        print("run autogen_test: run.py -t -p <outPath>")

+        print("run autogen_main: run.py -p <outPath>")

+        sys.exit(2)

+    run = 0

+    for opt, arg in opts:

+        if opt == "-t":

+            run |= 1 << 0

+        elif opt == "-p":

+            run |= 1 << 1

+            out_path = arg

+    if run & 0x3 == 0x3:

+        from tests import test_suite

+        test_suite.main(out_path)

+    elif run & 0x2 == 0x2:

+        main.main(out_path)

+    else:

+        print("Example of command")

+        print("run autogen_test: run.py -t -p <outPath>")

+        print("run autogen_main: run.py -p <outPath>")

+

+

+

diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/startup.py b/mcu/tools/NVRAMStatistic/autogen_v2/startup.py
new file mode 100644
index 0000000..368b245
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/startup.py
@@ -0,0 +1,269 @@
+import os
+import subprocess
+import re
+import sys
+import platform
+from sys import argv
+
+file_out_path = ""
+editor_file_path = [os.path.join("./interface/service/nvram"),os.path.join( "./custom/protocol/common/ps")]
+info_file_path = os.path.join(file_out_path, "bin", "log")
+inc_file_path = os.path.join(file_out_path, "tmp")
+editor_file = []
+def_file = []
+lid_stu_map = {}
+
+def nvram_gen_open_file(file_path, file_name, mode="r"):
+    file_pathname = os.path.join(file_path, file_name)
+    if mode == "r":
+        # file not exist.
+        if not os.access(file_pathname, os.F_OK):   
+            printf("error: %s not exist." % file_pathname)
+            sys.exit(2)
+        # file not read.
+        if not os.access(file_pathname, os.R_OK):
+            printf("error: %s exist, but it cannot be read." % file_pathname)
+            sys.exit(2)
+    elif mode == "w+":
+        # floder not write.
+        if not os.access(file_path, os.F_OK):
+            printf("error: folder no exist: %s" % file_path)
+            sys.exit(2)
+    try:
+        fd = open(file_pathname, mode)
+    except:
+        printf("error: open file error.")
+        printf("file_pathname: %s , mode: %s" % (file_pathname, mode))
+        raise
+    
+    return fd
+
+def printf(strs, file=sys.stdout, end="\n", flush=False):
+    strs_val = strs + end
+    file.write(strs_val)
+    if flush:
+        file.flush()
+
+
+def gen_editor_data_item():
+    """ parse editor file name, create and write nvram_editor_data_item.c """
+    global editor_file
+    """ list containing the names of the entries in the directory given by path. """
+    for editor in editor_file_path:
+        if not os.access(editor, os.F_OK):  
+            printf("error: %s not exist." % editor)
+            sys.exit(2)
+        if not os.access(editor, os.R_OK):
+            printf("error: %s exist, but it cannot be read." % editor)
+            sys.exit(2)
+        dirs = os.listdir(editor)
+        """ check filename, find editor files name saved to list. """
+        editor_pat = re.compile("nvram_editor\.h$")
+        def_pat = re.compile("nvram_def\.h$")
+        for item in dirs:
+            if editor_pat.search(item):
+                editor_file.append(item)
+            if def_pat.search(item):
+                def_file.append(item)
+
+    editor_file.append("nvram_editor_data_item.h")
+    editor_file.sort()
+    """ write include file to file. """
+    fd = nvram_gen_open_file(file_out_path, "nvram_editor_data_item.c", "w+")
+    for item in editor_file:
+        printf("#include \"%s\"" % item, file=fd, flush=True)
+
+    fd.close()
+
+
+def gen_gcc_option():
+    """ parse macro in info.log, save to list, write macro to gcc_option.h """
+    define_data = []
+    """ parse macro in info.log """
+    fd = nvram_gen_open_file(info_file_path, "info.log", "r")
+    for each_line in fd:
+        if each_line.isspace():
+            continue
+        if each_line.count("[ COMMON INCLUDE PATH ]") != 0:
+            break
+        if (each_line.count("[") != 0) or (each_line.count("]") != 0):
+            continue
+        item = each_line.replace("=", " ")
+        item = item.strip()  # remove trailing characters "\n \r \t"
+        define_data.append(item)
+    fd.close()
+    # add compile option for nvram gen 
+    define_data.append("__NVRAM_INTERNAL_LID_DESCRIPTION_ENABLE__")
+    define_data.append("__NV_GEN_FULL_LID__")
+    
+    """ write define macro to file. """
+    fd = nvram_gen_open_file(file_out_path, "gcc_option.h", "w+")
+    printf("#ifndef __GCC_OPTION_H__", file=fd, flush=True)
+    printf("#define __GCC_OPTION_H__", file=fd, flush=True)
+    printf("", file=fd, flush=True)
+
+    for item in define_data:
+        printf("#define %s" % item, file=fd, flush=True)
+
+    printf("", file=fd, flush=True)
+    printf("#endif", file=fd, flush=True)
+    fd.close()
+
+def find_include_path_win(gcc, out_path):
+    """ create gcc preprocessor command and run (win)"""
+    # create gcc preprocess command
+    gcc_command = "\"./" + gcc + "\"" + " -DGEN_FOR_PC -E -imacros gcc_option.h -fno-strict-aliasing -fshort-enums"
+    
+    fd = nvram_gen_open_file(inc_file_path, "~inc.tmp.tmp", "r")
+    for each_line in fd:
+        item = each_line.strip()  # remove trailing characters "\n \r \t"
+        if os.path.exists(item):  # check existing path
+            gcc_command = gcc_command + " -I " + item
+    fd.close()
+    
+    fd_com = nvram_gen_open_file(file_out_path, "gcc_com.mak", "w+")
+    printf("all:", file=fd_com)
+    printf("\t%s" % gcc_command+" "+out_path+"/nvram_auto_gen/nvram_editor_data_item.c"+" -o "+out_path+"/nvram_auto_gen/nvram_editor_data_item.i", file=fd_com)
+    fd_com.close()
+    
+    printf("===============win gcc file build======================")
+    printf("\".\\tools\\MSYS\\bin\\make.exe\" -f "+out_path+"/nvram_auto_gen/gcc_com.mak")
+    p  = subprocess.Popen("\".\\tools\\MSYS\\bin\\make.exe\" -f "+out_path+"/nvram_auto_gen/gcc_com.mak", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    outs, errs = p.communicate()
+    printf("gcc run log:")
+    if p.returncode != 0:   # run fail 
+        printf("gcc run fail! ")
+        printf("exit code = %d" % p.returncode)
+        printf("outs:")
+        printf(str(outs))
+        printf("errs:")
+        printf(str(errs))
+    else:
+        printf("gcc run pass! ")
+        printf("outs:")
+        printf(str(outs))
+
+def find_include_path():
+    """ create gcc preprocessor command and run """
+    # create gcc preprocess command
+    option_path = os.path.join(file_out_path, "gcc_option.h")
+    gcc_command = "gcc -DGEN_FOR_PC -E -C -imacros {} -fno-strict-aliasing -fshort-enums".format(option_path)
+    
+    fd = nvram_gen_open_file(inc_file_path, "~inc.tmp.tmp", "r")
+    for each_line in fd:
+        item = each_line.strip()  # remove trailing characters "\n \r \t"
+        if os.path.exists(item):  # check existing path
+            gcc_command = gcc_command + " -I " + item
+    fd.close()
+    gcc_command = gcc_command + " " + file_out_path + "/nvram_editor_data_item.c" + " -o " + file_out_path + "/nvram_editor_data_item.i"
+    
+    # shell run : gcc preprocess
+    printf("===============linux gcc build======================")
+    # printf("gcc command = %s" % gcc_command)
+    p  = subprocess.Popen(gcc_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    outs, errs = p.communicate()
+    printf("gcc run log:")
+    if p.returncode != 0:   # run fail 
+        printf("gcc run fail! ")
+        printf("exit code = %d" % p.returncode)
+        printf("outs:")
+        printf(outs)
+        printf("errs:")
+        printf(errs)
+    else:
+        printf("gcc run pass! ")
+        printf("outs:")
+        printf(outs)
+
+
+def parse_lid_stu_map():
+    """ parse lid struct name in nvram_editor_data_item.i, save to lid_stu_map dict """
+    global lid_stu_map
+    fd = nvram_gen_open_file(file_out_path, "nvram_editor_data_item.i", "r")
+    strs = fd.read()
+    fd.close()
+
+    """ all non-overlapping matches, return string list """
+    """
+    string format example:
+    LID_BIT "000" NVRAM_EF_STATIC_APPLMN_LID nvram_ef_static_applmn_struct *
+    or
+    LID_BIT MULTIPLE_LID "000" NVRAM_EF_EL1_MPRADJTBL_LID nvrm_el1_mqr_struct *
+    """
+    re_list = re.findall("LID_BIT[\s(MULTIPLE_LID)]*\"[0-9]{3}\"\s*NVRAM_EF_\w*_LID\s*\w*\s*\*", strs)
+
+    for item in re_list:
+        strs = re.sub("LID_BIT[\s(MULTIPLE_LID)]*\"[0-9]{3}\"\s*", "", item, count=1)
+        strs = re.sub("\s*\*", "", strs, count=1)
+        dict = re.split("\s*", strs)
+        lid_stu_map[dict[1]] = dict[0]  # add to dict
+    # for i in lid_stu_map.items():
+    #     printf(i)
+
+
+def gen_lid_stu_file():
+    """ gen nvram_lid_stu_tmp.h file """
+    fd = nvram_gen_open_file(file_out_path, "nvram_lid_stu_tmp.h", "w+")
+
+    printf("#ifndef __NVRAM_LID_STU_TMP_H__", file=fd, flush=True)
+    printf("#define __NVRAM_LID_STU_TMP_H__", file=fd, flush=True)
+    printf("", file=fd, flush=True)
+    printf("#include \"%s\"" % "nvram_group_editor.h" , file=fd, flush=True)
+    printf("#include \"%s\"" % "nvram_group_def.h", file=fd, flush=True)
+    printf("", file=fd, flush=True)
+    printf("/*\n * Variables\n */", file=fd, flush=True)
+    printf("", file=fd, flush=True)
+    for item in lid_stu_map.keys():
+        printf("static ", file=fd, end="", flush=True)
+        printf("%s " % item, file=fd, end="", flush=True)
+        printf("%s" % item + "_var", file=fd, end="", flush=True)
+        printf(" = {0};", file=fd, end="\n", flush=True)
+    printf("", file=fd, flush=True)
+    printf("#endif", file=fd, flush=True)
+
+
+def main(out_path, gcc):
+    global file_out_path
+    global info_file_path
+    global inc_file_path
+    file_out_path = os.path.join(out_path, "nvram_auto_gen")
+    info_file_path = os.path.join(out_path, "bin", "log")
+    inc_file_path = os.path.join(out_path, "tmp")
+    printf("file_out_path = %s" % file_out_path)
+    printf("info_file_path = %s" % info_file_path)
+    printf("inc_file_path = %s" % inc_file_path)
+
+    printf("run gen_editor_data_item()")
+    # gen_editor_data_item()
+    editor_file = os.path.join(file_out_path, "nvram_editor_data_item.c")
+    with open(editor_file, "w") as fd:
+        fd.write('#include "nvram_group_editor.h"')
+    printf("run gen_gcc_option()")
+    gen_gcc_option()
+    printf("run find_include_path()")
+    if platform.system() == "Windows":   # windows
+        find_include_path_win(gcc, out_path)
+    elif platform.system() == "Linux":  # linux              
+        find_include_path()
+    else:
+        printf("platform error: platform is not windows or linux!")
+        printf("platform.system() = %s" % platform.system())
+        sys.exit(1)
+    printf("run parse_lid_stu_map()")
+    parse_lid_stu_map()
+    printf("run gen_lid_stu_file()")
+    gen_lid_stu_file()
+
+
+if __name__ == '__main__':
+    printf("out path = %s" % argv[1])
+    printf("gcc = %s" % argv[2])
+    # printf("platfrom = %s" % argv[3])
+    # if len(argv) != 4:
+    #    printf("command error:")
+    #    printf("Example command: startup.py ./build/MT6885_SP/NLWCTG gcc platfrom" )
+    #else:
+    main(argv[1], argv[2])
+
+        
+        
diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/tests/__init__.py b/mcu/tools/NVRAMStatistic/autogen_v2/tests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/tests/__init__.py
diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/tests/lid_table_handle.py b/mcu/tools/NVRAMStatistic/autogen_v2/tests/lid_table_handle.py
new file mode 100644
index 0000000..305f924
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/tests/lid_table_handle.py
@@ -0,0 +1,163 @@
+from autogen.src.initconfig import logical_data_item_table
+from autogen.src.initconfig import const_value
+from autogen.src.initconfig import global_value
+from autogen.src.initconfig import LtableEntry
+import unittest
+
+fd = open("auto_gen_test_report.txt", "w+")
+# creat TestRunner
+runner = unittest.TextTestRunner(verbosity=3, stream=fd)
+
+def get_attr_str(attr):
+    ret_str = ""
+    if attr == const_value.NVRAM_ATTR_AVERAGE:
+        return "NVRAM_ATTR_AVERAGE"
+    if attr & const_value.NVRAM_ATTR_MULTI_DEFAULT:
+        ret_str += " | NVRAM_ATTR_MULTI_DEFAULT"
+    if attr & const_value.NVRAM_ATTR_WRITEPROTECT:
+        ret_str += " | NVRAM_ATTR_WRITEPROTECT"    
+    if attr & const_value.NVRAM_ATTR_MULTIPLE:
+        ret_str += " | NVRAM_ATTR_MULTIPLE"    
+    if attr & const_value.NVRAM_ATTR_CONFIDENTIAL:
+        ret_str += " | NVRAM_ATTR_CONFIDENTIAL"    
+    if attr & const_value.NVRAM_ATTR_MULTIREC_READ:
+        ret_str += " | NVRAM_ATTR_MULTIREC_READ"    
+    if attr & const_value.NVRAM_ATTR_MSP:
+        ret_str += " | NVRAM_ATTR_MSP"    
+    if attr & const_value.NVRAM_ATTR_OTA_RESET:
+        ret_str += " | NVRAM_ATTR_OTA_RESET"    
+    if attr & const_value.NVRAM_ATTR_GEN_DEFAULT:
+        ret_str += " | NVRAM_ATTR_GEN_DEFAULT"    
+    if attr & const_value.NVRAM_ATTR_RING:
+        ret_str += " | NVRAM_ATTR_RING"    
+    if attr & const_value.NVRAM_ATTR_PACKAGE:
+        ret_str += " | NVRAM_ATTR_PACKAGE"    
+    if attr & const_value.NVRAM_ATTR_BACKUP_FAT:
+        ret_str += " | NVRAM_ATTR_BACKUP_FAT"    
+    if attr & const_value.NVRAM_ATTR_BACKUP_RAW:
+        ret_str += " | NVRAM_ATTR_BACKUP_RAW"    
+    if attr & const_value.NVRAM_ATTR_RESERVE_BACKWARD:
+        ret_str += " | NVRAM_ATTR_RESERVE_BACKWARD"
+    if attr & const_value.NVRAM_ATTR_FAULT_ASSERT:
+        ret_str += " | NVRAM_ATTR_FAULT_ASSERT" 
+    if attr & const_value.NVRAM_ATTR_COMMITTED:
+        ret_str += " | NVRAM_ATTR_COMMITTED" 
+    if attr & const_value.NVRAM_ATTR_RAW_DATA:
+        ret_str += " | NVRAM_ATTR_RAW_DATA" 
+    if attr & const_value.NVRAM_ATTR_CHKSUM_INTEGRATE:
+        ret_str += " | NVRAM_ATTR_CHKSUM_INTEGRATE" 
+    if attr & const_value.NVRAM_ATTR_MCF_OTA_ADDITIONAL_NOT_CHECK_VERNO:
+        ret_str += " | NVRAM_ATTR_MCF_OTA_ADDITIONAL_NOT_CHECK_VERNO" 
+    if attr & const_value.NVRAM_ATTR_MCF_OTA_FOR_QUERY:
+        ret_str += " | NVRAM_ATTR_MCF_OTA_FOR_QUERY" 
+    if attr & const_value.NVRAM_ATTR_MCF_OTA_BY_OP:
+        ret_str += " | NVRAM_ATTR_MCF_OTA_BY_OP" 
+    if attr & const_value.NVRAM_ATTR_MCF_OTA:
+        ret_str += " | NVRAM_ATTR_MCF_OTA" 
+    return ret_str
+    
+
+def get_cate_str(cate): 
+    ret_str = ""
+    if cate == const_value.NVRAM_CATEGORY_USER:
+        return "NVRAM_ATTR_AVERAGE"
+    if cate & const_value.NVRAM_CATEGORY_INTERNAL:
+        ret_str += " | NVRAM_CATEGORY_INTERNAL"
+    if cate & const_value.NVRAM_CATEGORY_BACKUP_SDS:
+        ret_str += " | NVRAM_CATEGORY_BACKUP_SDS"
+    if cate & const_value.NVRAM_CATEGORY_OTP:
+        ret_str += " | NVRAM_CATEGORY_OTP"
+    if cate & const_value.NVRAM_CATEGORY_CUSTOM_DISK:
+        ret_str += " | NVRAM_CATEGORY_CUSTOM_DISK"
+    if cate & const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE:
+        ret_str += " | NVRAM_CATEGORY_CUSTOM_SENSITIVE"
+    if cate & const_value.NVRAM_CATEGORY_CUSTPACK:
+        ret_str += " | NVRAM_CATEGORY_CUSTPACK"
+    if cate & const_value.NVRAM_CATEGORY_SECUPACK:
+        ret_str += " | NVRAM_CATEGORY_SECUPACK"
+    if cate & const_value.NVRAM_CATEGORY_FUNC_DEFAULT:
+        ret_str += " | NVRAM_CATEGORY_FUNC_DEFAULT"
+    if cate & const_value.NVRAM_CATEGORY_CALIBRAT:
+        ret_str += " | NVRAM_CATEGORY_CALIBRAT"
+    if cate & const_value.NVRAM_CATEGORY_IMPORTANT:
+        ret_str += " | NVRAM_CATEGORY_IMPORTANT"
+    if cate & const_value.NVRAM_CATEGORY_IMPORTANT_L4:
+        ret_str += " | NVRAM_CATEGORY_IMPORTANT_L4"
+    if cate & const_value.NVRAM_CATEGORY_IMPORTANT_L1:
+        ret_str += " | NVRAM_CATEGORY_IMPORTANT_L1"
+    if cate & const_value.NVRAM_CATEGORY_RESERVED:
+        ret_str += " | NVRAM_CATEGORY_RESERVED"
+    return ret_str
+    
+def lid_table_creat():
+    for i in range(3):
+        one_entry = LtableEntry()
+        logical_data_item_table.append(one_entry)
+    const_value.NVRAM_EF_ZERO_DEFAULT = 0x00
+    const_value.NVRAM_EF_FF_DEFAULT = 0xff
+    const_value.NVRAM_EF_SPECIAL_DEFAULT = 0x55
+    const_value.NVRAM_CUSTOM_CFG_MAX_RECORD_SECTOR_NUM = 128
+    const_value.NVRAM_CUSTOM_CFG_MAX_RECORD_SIZE = const_value.NVRAM_CUSTOM_CFG_MAX_RECORD_SECTOR_NUM * const_value.NVRAM_RECORD_SECTOR_SIZE
+    global_value.path = "."
+
+    logical_data_item_table[0].lid = 2
+    logical_data_item_table[0].str_LID = "NVRAM_EF_UMTS_IMSI_LID"
+    logical_data_item_table[0].category = 0  # set 0
+    logical_data_item_table[0].attr = 0  # set 0
+    logical_data_item_table[0].total_records = 2
+    logical_data_item_table[0].size = 24
+    logical_data_item_table[0].FilePrefix = "UM02"
+    logical_data_item_table[0].FileVerno = "000"
+    logical_data_item_table[0].description = ""
+    logical_data_item_table[0].hash_key = 0xd5bb3d9e
+
+    logical_data_item_table[1].lid = 3
+    logical_data_item_table[1].str_LID = "NVRAM_EF_UMTS_START_HFN_FDD_LID"
+    logical_data_item_table[1].category = 0  # set 0
+    logical_data_item_table[1].attr = 0  # set 0
+    logical_data_item_table[1].total_records = 2
+    logical_data_item_table[1].size = 6
+    logical_data_item_table[1].FilePrefix = "UM03"
+    logical_data_item_table[1].FileVerno = "000"
+    logical_data_item_table[1].description = ""
+    logical_data_item_table[1].hash_key = 0x6a424feb
+
+    logical_data_item_table[2].lid = 4
+    logical_data_item_table[2].str_LID = "NVRAM_EF_UMTS_START_HFN_TDD_LID"
+    logical_data_item_table[2].category = 0  # set 0
+    logical_data_item_table[2].attr = 0  # set 0
+    logical_data_item_table[2].total_records = 2
+    logical_data_item_table[2].size = 6
+    logical_data_item_table[2].FilePrefix = "UM10"
+    logical_data_item_table[2].FileVerno = "000"
+    logical_data_item_table[2].description = ""
+    logical_data_item_table[2].hash_key = 0x3bb47841
+
+
+def data_restore():
+    logical_data_item_table[0].lid = 2
+    logical_data_item_table[0].str_LID = "NVRAM_EF_UMTS_IMSI_LID"
+    logical_data_item_table[0].category = 0  # set 0
+    logical_data_item_table[0].attr = 0  # set 0
+    logical_data_item_table[0].total_records = 2
+    logical_data_item_table[0].size = 24
+    logical_data_item_table[0].FilePrefix = "UM02"
+    logical_data_item_table[0].FileVerno = "000"
+    logical_data_item_table[0].description = ""
+    logical_data_item_table[0].hash_key = 0xd5bb3d9e
+    logical_data_item_table[0].p_default_value = 0x01
+
+    logical_data_item_table[1].lid = 3
+    logical_data_item_table[2].lid = 4
+    global_value.macro = 0
+
+
+def main():
+    lid_table_creat()
+    data_restore()
+
+
+if __name__ == '__main__':
+    print("run begin.")
+    main()
+    print("run end.")
diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/tests/test_attr_conflict.py b/mcu/tools/NVRAMStatistic/autogen_v2/tests/test_attr_conflict.py
new file mode 100644
index 0000000..8d64dd5
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/tests/test_attr_conflict.py
@@ -0,0 +1,152 @@
+import unittest

+

+from .lid_table_handle import data_restore

+from autogen.src.initconfig import logical_data_item_table

+from autogen.src.initconfig import const_value

+from autogen.src.initconfig import global_value

+from autogen.main import main_test

+

+

+class TestAttributeConflict(unittest.TestCase):

+    def setUp(self):

+        data_restore()

+

+    @classmethod

+    def setUpClass(cls):

+        pass

+

+    @classmethod

+    def tearDownClass(cls):

+        pass

+

+    def test_item_39(self):

+        global_value.macro |= const_value.__NVRAM_PSEUDO_MERGE__

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_PACKAGE

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_MULTIPLE

+

+        with self.assertRaisesRegex(SystemExit, "Can't Set NVRAM_ATTR_MULTIPLE/NVRAM_ATTR_MSP for PACKAGE Lid"):

+            main_test()

+        self.assertEqual(logical_data_item_table[0].description, "null")

+

+    def test_item_40(self):

+        global_value.macro |= const_value.__NVRAM_PSEUDO_MERGE__

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_PACKAGE

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_MSP

+

+        with self.assertRaisesRegex(SystemExit, "Can't Set NVRAM_ATTR_MULTIPLE/NVRAM_ATTR_MSP for PACKAGE Lid"):

+            main_test()

+        self.assertEqual(logical_data_item_table[0].description, "null")

+

+    def test_item_41(self):

+        logical_data_item_table[0].total_records = 1

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_MULTIREC_READ

+

+        with self.assertRaisesRegex(SystemExit,

+                                    "Can't Set the NVRAM_ATTR_MULTIREC_READ or NVRAM_ATTR_MULTI_DEFAULT for the lid "

+                                    "with only one record"):

+            main_test()

+

+    def test_item_42(self):

+        logical_data_item_table[0].total_records = 1

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_MULTI_DEFAULT

+

+        with self.assertRaisesRegex(SystemExit,

+                                    "Can't Set the NVRAM_ATTR_MULTIREC_READ or NVRAM_ATTR_MULTI_DEFAULT for the lid "

+                                    "with only one record"):

+            main_test()

+

+    def test_item_43(self):

+        logical_data_item_table[0].p_default_value = const_value.NVRAM_EF_ZERO_DEFAULT

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_GEN_DEFAULT

+

+        with self.assertRaisesRegex(SystemExit,

+                                    "Can't Set the NVRAM_ATTR_GEN_DEFAULT for the lid with Zero of FF default value"):

+            main_test()

+

+    def test_item_44(self):

+        logical_data_item_table[0].p_default_value = const_value.NVRAM_EF_FF_DEFAULT

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_GEN_DEFAULT

+

+        with self.assertRaisesRegex(SystemExit,

+                                    "Can't Set the NVRAM_ATTR_GEN_DEFAULT for the lid with Zero of FF default value"):

+            main_test()

+

+    def test_item_45(self):

+        logical_data_item_table[0].str_default_value = "NVRAM_EF_ZERO_DEFAULT"

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_MULTI_DEFAULT

+

+        with self.assertRaisesRegex(SystemExit, "Cannot set ZERO_DEFAULT or FF_DEFAULT with multi_default!"):

+            main_test()

+

+    def test_item_46(self):

+        logical_data_item_table[0].str_default_value = "NVRAM_EF_FF_DEFAULT"

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_MULTI_DEFAULT

+

+        with self.assertRaisesRegex(SystemExit,

+                                    "Cannot set ZERO_DEFAULT or FF_DEFAULT with multi_default!"):

+            main_test()

+

+    def test_item_47(self):

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_OTA_RESET

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_RESERVE_BACKWARD

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_48(self):

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_RAW_DATA

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_PACKAGE

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_49(self):

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_RAW_DATA

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_MULTIPLE

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_50(self):

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_RAW_DATA

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_RING

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_51(self):

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_RAW_DATA

+        logical_data_item_table[0].total_records = 0

+

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_WRITEPROTECT

+        logical_data_item_table[0].lid = 61200

+        logical_data_item_table[0].str_LID = "NVRAM_EF_IMEI_IMEISV_LID"

+        logical_data_item_table[0].FilePrefix = "LD0B"

+        logical_data_item_table[0].FileVerno = "001"

+        logical_data_item_table[0].hash_key = 0xad4532bb

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_52(self):

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_RAW_DATA

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_CONFIDENTIAL

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_53(self):

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_RAW_DATA

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_MSP

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_54(self):

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_MULTIPLE

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_PACKAGE

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+

diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/tests/test_cate_attr_conflict.py b/mcu/tools/NVRAMStatistic/autogen_v2/tests/test_cate_attr_conflict.py
new file mode 100644
index 0000000..2b44147
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/tests/test_cate_attr_conflict.py
@@ -0,0 +1,186 @@
+import unittest

+

+from tests.lid_table_handle import data_restore, runner, get_attr_str, get_cate_str

+from autogen.src.initconfig import logical_data_item_table

+from autogen.src.initconfig import const_value

+from autogen.src.initconfig import global_value

+from autogen.src.buildtimecheck import nvram_gen_check_cate_attr_conflicts

+

+

+macro_default = 0x00

+cate_default = 0x00

+attr_default = 0x00

+

+

+class TestCateAttrConflict(unittest.TestCase):

+    def setUp(self):

+        data_restore()

+

+    @classmethod

+    def setUpClass(cls):

+        pass

+

+    @classmethod

+    def tearDownClass(cls):

+        pass

+        

+    def test_check_cate_attr_conflicts(self):

+        # ====================

+        # check func : nvram_gen_check_cate_attr_conflicts

+        test_case = [

+            {"func": nvram_gen_check_cate_attr_conflicts, 

+            "macro": macro_default,  

+            "cate": [const_value.NVRAM_CATEGORY_CALIBRAT ], 

+            "attr": [const_value.NVRAM_ATTR_MULTIPLE, const_value.NVRAM_ATTR_MSP, const_value.NVRAM_ATTR_RING, const_value.NVRAM_ATTR_OTA_RESET, const_value.NVRAM_ATTR_RESERVE_BACKWARD],   

+            "err_str": "Please adjust LID's attributes and/or categories",

+            },

+            {"func": nvram_gen_check_cate_attr_conflicts, 

+            "macro": macro_default,  

+            "cate": [const_value.NVRAM_CATEGORY_INTERNAL], 

+            "attr": [const_value.NVRAM_ATTR_PACKAGE],   

+            "err_str": "Please adjust LID's attributes and/or categories",

+            },

+            {"func": nvram_gen_check_cate_attr_conflicts, 

+            "macro": macro_default,  

+            "cate": [const_value.NVRAM_CATEGORY_SECUPACK ], 

+            "attr": [const_value.NVRAM_ATTR_PACKAGE, const_value.NVRAM_ATTR_RAW_DATA],   

+            "err_str": "Please adjust LID's attributes and/or categories",

+            },

+            {"func": nvram_gen_check_cate_attr_conflicts, 

+            "macro": macro_default,  

+            "cate": [const_value.NVRAM_CATEGORY_CUSTPACK ], 

+            "attr": [const_value.NVRAM_ATTR_RAW_DATA],   

+            "err_str": "Please adjust LID's attributes and/or categories",

+            },

+            {"func": nvram_gen_check_cate_attr_conflicts, 

+            "macro": macro_default,  

+            "cate": [const_value.NVRAM_CATEGORY_FUNC_DEFAULT ], 

+            "attr": [const_value.NVRAM_ATTR_RAW_DATA],   

+            "err_str": "Please adjust LID's attributes and/or categories",

+            },

+            {"func": nvram_gen_check_cate_attr_conflicts, 

+            "macro": macro_default,  

+            "cate": [const_value.NVRAM_CATEGORY_OTP ], 

+            "attr": [const_value.NVRAM_ATTR_GEN_DEFAULT, const_value.NVRAM_ATTR_RESERVE_BACKWARD, const_value.NVRAM_ATTR_RAW_DATA],   

+            "err_str": "Please adjust LID's attributes and/or categories",

+            },

+        ]

+        

+        runner.stream.write("\n")

+        for dict_case in test_case:

+            for cate in dict_case["cate"]:

+                data_restore()

+                logical_data_item_table[0].category = cate

+                for attr in dict_case["attr"]:

+                    logical_data_item_table[0].attr = attr

+                    runner.stream.write("\tcate = %s, attr = %s, fun = %s\n" %(get_cate_str(cate), get_attr_str(attr), dict_case["func"]))

+                    with self.assertRaisesRegex(SystemExit, dict_case["err_str"]):

+                        dict_case["func"]()

+                    logical_data_item_table[0].attr &= ~attr

+                        

+    def test_check_cate_conflicts(self):

+        # ====================

+        # check func : nvram_gen_check_cate_attr_conflicts

+        test_case = [

+            {"func": nvram_gen_check_cate_attr_conflicts, 

+            "macro": macro_default,  

+            "cate": [const_value.NVRAM_CATEGORY_FUNC_DEFAULT ], 

+            "cate_conf": [const_value.NVRAM_CATEGORY_CUSTPACK, const_value.NVRAM_CATEGORY_SECUPACK],   

+            "err_str": "Please adjust LID's attributes and/or categories",

+            },

+

+            {"func": nvram_gen_check_cate_attr_conflicts, 

+            "macro": macro_default,  

+            "cate": [const_value.NVRAM_CATEGORY_CALIBRAT ], 

+            "cate_conf": [const_value.NVRAM_CATEGORY_INTERNAL, const_value.NVRAM_CATEGORY_BACKUP_SDS, 

+                        const_value.NVRAM_CATEGORY_CUSTOM_DISK, const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE,

+                        const_value.NVRAM_CATEGORY_IMPORTANT, const_value.NVRAM_CATEGORY_OTP,

+                        const_value.NVRAM_CATEGORY_IMPORTANT_L4, const_value.NVRAM_CATEGORY_IMPORTANT_L1,

+                        const_value.NVRAM_CATEGORY_RESERVED],   

+            "err_str": "Please adjust LID's attributes and/or categories",

+            },

+            {"func": nvram_gen_check_cate_attr_conflicts, 

+            "macro": macro_default,  

+            "cate": [const_value.NVRAM_CATEGORY_IMPORTANT ], 

+            "cate_conf": [const_value.NVRAM_CATEGORY_IMPORTANT_L1, const_value.NVRAM_CATEGORY_IMPORTANT_L4, const_value.NVRAM_CATEGORY_INTERNAL, const_value.NVRAM_CATEGORY_OTP],   

+            "err_str": "Please adjust LID's attributes and/or categories",

+            },

+            {"func": nvram_gen_check_cate_attr_conflicts, 

+            "macro": macro_default,  

+            "cate": [const_value.NVRAM_CATEGORY_IMPORTANT_L4 ], 

+            "cate_conf": [const_value.NVRAM_CATEGORY_IMPORTANT_L1, const_value.NVRAM_CATEGORY_INTERNAL, const_value.NVRAM_CATEGORY_OTP],   

+            "err_str": "Please adjust LID's attributes and/or categories",

+            },

+            {"func": nvram_gen_check_cate_attr_conflicts, 

+            "macro": macro_default,  

+            "cate": [const_value.NVRAM_CATEGORY_INTERNAL ], 

+            "cate_conf": [const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE, const_value.NVRAM_CATEGORY_OTP],   

+            "err_str": "Please adjust LID's attributes and/or categories",

+            },

+            {"func": nvram_gen_check_cate_attr_conflicts, 

+            "macro": macro_default,  

+            "cate": [const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE ], 

+            "cate_conf": [const_value.NVRAM_CATEGORY_CUSTPACK, const_value.NVRAM_CATEGORY_SECUPACK, const_value.NVRAM_CATEGORY_OTP],   

+            "err_str": "Please adjust LID's attributes and/or categories",

+            },

+            {"func": nvram_gen_check_cate_attr_conflicts, 

+            "macro": macro_default,  

+            "cate": [const_value.NVRAM_CATEGORY_CUSTPACK ], 

+            "cate_conf": [const_value.NVRAM_CATEGORY_SECUPACK, const_value.NVRAM_CATEGORY_OTP],   

+            "err_str": "Please adjust LID's attributes and/or categories",

+            },

+            {"func": nvram_gen_check_cate_attr_conflicts, 

+            "macro": macro_default,  

+            "cate": [const_value.NVRAM_CATEGORY_SECUPACK ], 

+            "cate_conf": [const_value.NVRAM_CATEGORY_OTP],   

+            "err_str": "Please adjust LID's attributes and/or categories",

+            },

+        ]

+        

+        runner.stream.write("\n")

+        for dict_case in test_case:

+            for cate in dict_case["cate"]:

+                data_restore()

+                logical_data_item_table[0].category = cate

+                for cate_conf in dict_case["cate_conf"]:

+                    logical_data_item_table[0].category |= cate_conf

+                    runner.stream.write("\tcate = %s, fun = %s\n" %(get_cate_str(logical_data_item_table[0].category), dict_case["func"]))

+                    with self.assertRaisesRegex(SystemExit, dict_case["err_str"]):

+                        dict_case["func"]()

+                    logical_data_item_table[0].category &= ~cate_conf

+    

+    # ====================

+    # check func : nvram_gen_check_cate_attr_conflicts

+    def test_check_attr_conflicts(self):

+        test_case = [

+            {"func": nvram_gen_check_cate_attr_conflicts, 

+            "macro": macro_default,  

+            "attr": [const_value.NVRAM_ATTR_MULTIPLE ], 

+            "attr_conf": [const_value.NVRAM_ATTR_PACKAGE],   

+            "err_str": "Please adjust LID's attributes and/or categories",

+            },

+            {"func": nvram_gen_check_cate_attr_conflicts, 

+            "macro": macro_default,  

+            "attr": [const_value.NVRAM_ATTR_OTA_RESET ], 

+            "attr_conf": [const_value.NVRAM_ATTR_RESERVE_BACKWARD],   

+            "err_str": "Please adjust LID's attributes and/or categories",

+            },

+            {"func": nvram_gen_check_cate_attr_conflicts, 

+            "macro": macro_default,  

+            "attr": [const_value.NVRAM_ATTR_RAW_DATA ], 

+            "attr_conf": [const_value.NVRAM_ATTR_PACKAGE, const_value.NVRAM_ATTR_MULTIPLE, const_value.NVRAM_ATTR_RING, const_value.NVRAM_ATTR_WRITEPROTECT, const_value.NVRAM_ATTR_CONFIDENTIAL, const_value.NVRAM_ATTR_MSP],   

+            "err_str": "Please adjust LID's attributes and/or categories",

+            },

+        ]

+        runner.stream.write("\n")

+        for dict_case in test_case:

+            for attr in dict_case["attr"]:

+                data_restore()

+                logical_data_item_table[0].attr = attr

+                for attr_conf in dict_case["attr_conf"]:

+                    logical_data_item_table[0].attr |= attr_conf

+                    runner.stream.write("\tattr = %s, fun = %s\n" %(get_attr_str(logical_data_item_table[0].attr), dict_case["func"]))

+                    with self.assertRaisesRegex(SystemExit, dict_case["err_str"]):

+                        dict_case["func"]()

+                    logical_data_item_table[0].attr &= ~attr_conf

+    

diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/tests/test_cate_conflict.py b/mcu/tools/NVRAMStatistic/autogen_v2/tests/test_cate_conflict.py
new file mode 100644
index 0000000..0b35810
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/tests/test_cate_conflict.py
@@ -0,0 +1,388 @@
+import unittest

+

+from tests.lid_table_handle import data_restore

+from autogen.src.initconfig import logical_data_item_table

+from autogen.src.initconfig import const_value

+from autogen.src.initconfig import global_value

+from autogen.main import main_test

+

+

+class TestCategoryConflict(unittest.TestCase):

+

+    def setUp(self):

+        data_restore()

+

+    @classmethod

+    def setUpClass(cls):

+        pass

+

+    @classmethod

+    def tearDownClass(cls):

+        pass

+

+    def test_item_1(self):

+        global_value.macro |= const_value.__NVRAM_SECURE_DATA_STORAGE__

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_BACKUP_SDS

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE

+

+        with self.assertRaisesRegex(SystemExit, "Sds use with wrong category"):

+            main_test()

+

+    def test_item_2(self):

+        global_value.macro |= const_value.__NVRAM_SECURE_DATA_STORAGE__

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_BACKUP_SDS

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_OTP

+

+        with self.assertRaisesRegex(SystemExit, "Sds use with wrong category"):

+            main_test()

+

+    def test_item_3(self):

+        global_value.macro |= const_value.__NVRAM_SECURE_DATA_STORAGE__

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_BACKUP_SDS

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_CUSTOM_DISK

+

+        with self.assertRaisesRegex(SystemExit, "Sds use with wrong category"):

+            main_test()

+

+    def test_item_4(self):

+        global_value.macro |= const_value.__FPGA__

+        global_value.macro |= const_value.__PALLADIUM__

+        global_value.macro |= const_value._SIMULATION

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_GEN_DEFAULT

+        logical_data_item_table[0].category &= ~const_value.NVRAM_CATEGORY_INTERNAL

+

+        self.assertEqual(logical_data_item_table[0].attr & const_value.NVRAM_ATTR_GEN_DEFAULT,

+                         const_value.NVRAM_ATTR_GEN_DEFAULT)

+

+    def test_item_5(self):

+        global_value.macro |= const_value.__NVRAM_SECURE_DATA_STORAGE__

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_INTERNAL

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_MULTIPLE

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_RING

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_PACKAGE

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_BACKUP_FAT

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_BACKUP_RAW

+

+        main_test()

+

+        self.assertEqual(logical_data_item_table[0].category & const_value.NVRAM_CATEGORY_BACKUP_SDS,

+                         const_value.NVRAM_CATEGORY_BACKUP_SDS)

+        self.assertNotEqual(logical_data_item_table[0].attr & const_value.NVRAM_ATTR_MULTIPLE,

+                            const_value.NVRAM_ATTR_MULTIPLE)

+        self.assertNotEqual(logical_data_item_table[0].attr & const_value.NVRAM_ATTR_RING, const_value.NVRAM_ATTR_RING)

+        self.assertNotEqual(logical_data_item_table[0].attr & const_value.NVRAM_ATTR_PACKAGE,

+                            const_value.NVRAM_ATTR_PACKAGE)

+        self.assertNotEqual(logical_data_item_table[0].attr & const_value.NVRAM_ATTR_BACKUP_FAT,

+                            const_value.NVRAM_ATTR_BACKUP_FAT)

+        self.assertNotEqual(logical_data_item_table[0].attr & const_value.NVRAM_ATTR_BACKUP_RAW,

+                            const_value.NVRAM_ATTR_BACKUP_RAW)

+

+    def test_item_6(self):

+        # global_value.macro |= const_value.__NVRAM_SECURE_DATA_STORAGE__

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_CALIBRAT

+

+        # logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_MULTIPLE

+        # logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_BACKUP_RAW

+        # logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_BACKUP_FAT

+        global_value.macro |= const_value.__LOW_COST_SUPPORT_COMMON__

+        logical_data_item_table[0].p_default_value = 6

+

+        # logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_RING

+        # logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_PACKAGE

+

+        main_test()

+

+        self.assertEqual(logical_data_item_table[0].category & const_value.NVRAM_CATEGORY_CALIBRAT,

+                         const_value.NVRAM_CATEGORY_CALIBRAT)

+        self.assertNotEqual(logical_data_item_table[0].attr & const_value.NVRAM_ATTR_MULTIPLE,

+                            const_value.NVRAM_ATTR_MULTIPLE)

+        self.assertNotEqual(logical_data_item_table[0].attr & const_value.NVRAM_ATTR_RING, const_value.NVRAM_ATTR_RING)

+        self.assertNotEqual(logical_data_item_table[0].attr & const_value.NVRAM_ATTR_PACKAGE,

+                            const_value.NVRAM_ATTR_PACKAGE)

+        self.assertNotEqual(logical_data_item_table[0].attr & const_value.NVRAM_ATTR_BACKUP_FAT,

+                            const_value.NVRAM_ATTR_BACKUP_FAT)

+        self.assertNotEqual(logical_data_item_table[0].attr & const_value.NVRAM_ATTR_BACKUP_RAW,

+                            const_value.NVRAM_ATTR_BACKUP_RAW)

+

+    def test_item_7(self):

+        global_value.macro |= const_value.__NVRAM_SECURE_DATA_STORAGE__

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_IMPORTANT

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_MULTIPLE

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_RING

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_PACKAGE

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_BACKUP_FAT

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_BACKUP_RAW

+

+        main_test()

+

+        self.assertEqual(logical_data_item_table[0].category & const_value.NVRAM_CATEGORY_IMPORTANT,

+                         const_value.NVRAM_CATEGORY_IMPORTANT)

+        self.assertNotEqual(logical_data_item_table[0].attr & const_value.NVRAM_ATTR_MULTIPLE,

+                            const_value.NVRAM_ATTR_MULTIPLE)

+        self.assertNotEqual(logical_data_item_table[0].attr & const_value.NVRAM_ATTR_RING, const_value.NVRAM_ATTR_RING)

+        self.assertNotEqual(logical_data_item_table[0].attr & const_value.NVRAM_ATTR_PACKAGE,

+                            const_value.NVRAM_ATTR_PACKAGE)

+        self.assertNotEqual(logical_data_item_table[0].attr & const_value.NVRAM_ATTR_BACKUP_FAT,

+                            const_value.NVRAM_ATTR_BACKUP_FAT)

+        self.assertNotEqual(logical_data_item_table[0].attr & const_value.NVRAM_ATTR_BACKUP_RAW,

+                            const_value.NVRAM_ATTR_BACKUP_RAW)

+

+    def test_item_8(self):

+        global_value.macro |= const_value.__NVRAM_SECURE_DATA_STORAGE__

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_IMPORTANT_L4

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_MULTIPLE

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_RING

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_PACKAGE

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_BACKUP_FAT

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_BACKUP_RAW

+

+        main_test()

+

+        self.assertEqual(logical_data_item_table[0].category & const_value.NVRAM_CATEGORY_IMPORTANT_L4,

+                         const_value.NVRAM_CATEGORY_IMPORTANT_L4)

+        self.assertNotEqual(logical_data_item_table[0].attr & const_value.NVRAM_ATTR_MULTIPLE,

+                            const_value.NVRAM_ATTR_MULTIPLE)

+        self.assertNotEqual(logical_data_item_table[0].attr & const_value.NVRAM_ATTR_RING, const_value.NVRAM_ATTR_RING)

+        self.assertNotEqual(logical_data_item_table[0].attr & const_value.NVRAM_ATTR_PACKAGE,

+                            const_value.NVRAM_ATTR_PACKAGE)

+        self.assertNotEqual(logical_data_item_table[0].attr & const_value.NVRAM_ATTR_BACKUP_FAT,

+                            const_value.NVRAM_ATTR_BACKUP_FAT)

+        self.assertNotEqual(logical_data_item_table[0].attr & const_value.NVRAM_ATTR_BACKUP_RAW,

+                            const_value.NVRAM_ATTR_BACKUP_RAW)

+

+    def test_item_9(self):

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_FUNC_DEFAULT

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_CUSTPACK

+        logical_data_item_table[0].str_default_value = "NVRAM_EF_SPECIAL_DEFAULT"

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_10(self):

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_FUNC_DEFAULT

+

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_SECUPACK

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_CONFIDENTIAL

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_11(self):

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_IMPORTANT

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_IMPORTANT_L1

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_12(self):

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_IMPORTANT

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_IMPORTANT_L4

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_13(self):

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_IMPORTANT

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_INTERNAL

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_14(self):

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_IMPORTANT_L4

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_IMPORTANT_L1

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_15(self):

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_IMPORTANT_L4

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_INTERNAL

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_16(self):

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_IMPORTANT_L1

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_INTERNAL

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_17(self):

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_INTERNAL

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_18(self):

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_CUSTPACK

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_19(self): #

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_SECUPACK

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_CONFIDENTIAL

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_20(self):

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_CUSTPACK

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_SECUPACK

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_CONFIDENTIAL

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_21(self):

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_OTP

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_CALIBRAT

+        global_value.macro |= const_value.__LOW_COST_SUPPORT_COMMON__

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_22(self):

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_OTP

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_IMPORTANT

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_23(self):

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_OTP

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_IMPORTANT_L1

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_24(self):

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_OTP

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_IMPORTANT_L4

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_25(self):

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_OTP

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_INTERNAL

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_26(self):

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_OTP

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_27(self):

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_OTP

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_CUSTPACK

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_28(self):

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_OTP

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_SECUPACK

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_CONFIDENTIAL

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_29(self):

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_CUSTPACK

+        logical_data_item_table[0].str_default_value = "NVRAM_EF_ZERO_DEFAULT"

+

+        with self.assertRaisesRegex(SystemExit, "Cannot set ZERO_DEFAULT or FF_DEFAULT with custpack!"):

+            main_test()

+

+    def test_item_30(self):

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_CUSTPACK

+        logical_data_item_table[0].str_default_value = "NVRAM_EF_FF_DEFAULT"

+

+        with self.assertRaisesRegex(SystemExit, "Cannot set ZERO_DEFAULT or FF_DEFAULT with custpack!"):

+            main_test()

+

+    def test_item_31(self):

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_CALIBRAT

+        global_value.macro |= const_value.__LOW_COST_SUPPORT_COMMON__

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_IMPORTANT

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_32(self):

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_CALIBRAT

+        global_value.macro |= const_value.__LOW_COST_SUPPORT_COMMON__

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_IMPORTANT_L1

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_33(self):

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_CALIBRAT

+        global_value.macro |= const_value.__LOW_COST_SUPPORT_COMMON__

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_IMPORTANT_L4

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_34(self):

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_CALIBRAT

+        global_value.macro |= const_value.__LOW_COST_SUPPORT_COMMON__

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_INTERNAL

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_35(self):

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_CALIBRAT

+        global_value.macro |= const_value.__LOW_COST_SUPPORT_COMMON__

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE

+

+        with self.assertRaisesRegex(SystemExit, "Please adjust LID's attributes and/or categories"):

+            main_test()

+

+    def test_item_36(self):

+        global_value.macro |= const_value.__NVRAM_CUSTOM_SENSITIVE__

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_IMPORTANT

+

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_MSP

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_CONFIDENTIAL

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_MULTIPLE

+

+        with self.assertRaisesRegex(SystemExit, "Category internal & calibrat & important & sensitive can't be used at the same time!"):

+            main_test()

+

+    def test_item_37(self):

+        global_value.macro |= const_value.__NVRAM_CUSTOM_SENSITIVE__

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_IMPORTANT_L1

+

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_MSP

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_CONFIDENTIAL

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_MULTIPLE

+

+        with self.assertRaisesRegex(SystemExit, "Category internal & calibrat & important & sensitive can't be used at the same time!"):

+            main_test()

+

+    def test_item_38(self):

+        global_value.macro |= const_value.__NVRAM_CUSTOM_SENSITIVE__

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE

+        logical_data_item_table[0].category |= const_value.NVRAM_CATEGORY_IMPORTANT_L4

+

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_MSP

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_CONFIDENTIAL

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_MULTIPLE

+

+        with self.assertRaisesRegex(SystemExit, "Category internal & calibrat & important & sensitive can't be used at the same time!"):

+            main_test()

diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/tests/test_other.py b/mcu/tools/NVRAMStatistic/autogen_v2/tests/test_other.py
new file mode 100644
index 0000000..268985d
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/tests/test_other.py
@@ -0,0 +1,547 @@
+import unittest

+

+from tests.lid_table_handle import data_restore, runner, get_attr_str, get_cate_str

+from autogen.src.initconfig import logical_data_item_table

+from autogen.src.initconfig import const_value

+from autogen.src.initconfig import global_value

+

+from autogen.src.gen_assign_entry import adjust_attr_cate_i, adjust_attr_cate_ii, adjust_attr_cate_iii

+from autogen.src.gen_assign_entry import adjust_attr_cate_iv, adjust_attr_cate_v, adjust_attr_cate_vi

+from autogen.src.gen_assign_entry import adjust_attr_cate_vii, adjust_attr_cate_viii, adjust_attr_cate_xi

+from autogen.src.gen_assign_entry import check_item_data_i, check_item_data_ii, check_item_data_iii

+from autogen.src.gen_assign_entry import check_item_data_iv, check_item_data_v, check_item_data_vi

+from autogen.src.buildtimecheck import check_lid_enum_overlapping, check_write_protect

+from autogen.src.buildtimecheck import check_special_lid_parameter, hash_md5, check_lid_hash_key

+from autogen.src.buildtimecheck import check_lid_fileprefix_overlapping

+

+macro_default = 0x00

+cate_default = 0x00

+attr_default = 0x00

+

+

+list_test_item = [

+    # ====================

+    # check func : adjust_attr_cate_ii,

+    {"func": adjust_attr_cate_ii, 

+    "macro": macro_default, 

+    "cate": [const_value.NVRAM_CATEGORY_CALIBRAT], 

+    "attr": [const_value.NVRAM_ATTR_RESERVE_BACKWARD, const_value.NVRAM_ATTR_MULTIPLE],

+    "err_str": "Can't Set NVRAM_ATTR_MULTIPLE/NVRAM_ATTR_RESERVE_BACKWARD for Calibrate Lid",

+    },

+    {"func": adjust_attr_cate_ii, 

+    "macro": const_value.__NVRAM_BACKUP_DISK_FAT__, 

+    "cate": [const_value.NVRAM_CATEGORY_CALIBRAT], 

+    "attr": [const_value.NVRAM_ATTR_BACKUP_RAW],  # const_value.NVRAM_ATTR_MULTIPLE  

+    "err_str": "Can't Set the NVRAM_ATTR_MULTIPLE/NVRAM_ATTR_BACKUP_RAW for Calibrate",

+    },

+    {"func": adjust_attr_cate_ii, 

+    "macro": const_value.__NVRAM_BACKUP_DISK_FAT__, 

+    "cate": [const_value.NVRAM_CATEGORY_CALIBRAT], 

+    "attr": [attr_default],  # no define NVRAM_ATTR_BACKUP_FAT

+    "err_str": "Should set the NVRAM_ATTR_BACKUP_FAT for Calibrate",

+    },

+    {"func": adjust_attr_cate_ii, 

+    "macro": const_value.__NVRAM_BACKUP_DISK_RAW__, 

+    "cate": [const_value.NVRAM_CATEGORY_CALIBRAT], 

+    "attr": [const_value.NVRAM_ATTR_BACKUP_FAT],  # const_value.NVRAM_ATTR_MULTIPLE  

+    "err_str": "Can't Set the NVRAM_ATTR_MULTIPLE/NVRAM_ATTR_BACKUP_FAT for Calibrate",

+    },

+    {"func": adjust_attr_cate_ii, 

+    "macro": const_value.__NVRAM_BACKUP_DISK_RAW__, 

+    "cate": [const_value.NVRAM_CATEGORY_CALIBRAT], 

+    "attr": [attr_default],  # no define NVRAM_ATTR_BACKUP_RAW

+    "err_str": "Should set the NVRAM_ATTR_BACKUP_RAW for Calibrate",

+    },

+    {"func": adjust_attr_cate_ii, 

+    "macro": macro_default,  # no define __LOW_COST_SUPPORT_COMMON__/__CCCIFS_SUPPORT__/__FS_RAMDISK__

+    "cate": [const_value.NVRAM_CATEGORY_CALIBRAT], 

+    "attr": [attr_default],  # no define NVRAM_ATTR_MULTIPLE

+    "err_str": "Should set the NVRAM_ATTR_MULTIPLE for Calibrate under this scenario",

+    },

+    {"func": adjust_attr_cate_ii, 

+    "macro": const_value.__LOW_COST_SUPPORT_COMMON__,  # jump other check

+    "cate": [const_value.NVRAM_CATEGORY_CALIBRAT], 

+    "attr": [const_value.NVRAM_ATTR_BACKUP_RAW, const_value.NVRAM_ATTR_BACKUP_FAT],  

+    "err_str": "Can't Set the NVRAM_ATTR_BACKUP_RAW/NVRAM_ATTR_BACKUP_FAT for Calibrate",

+    },

+    # ====================

+    # check func : adjust_attr_cate_iii,

+    {"func": adjust_attr_cate_iii, 

+    "macro": const_value.__CCCIFS_SUPPORT__,  

+    "cate": [const_value.NVRAM_CATEGORY_IMPORTANT, const_value.NVRAM_CATEGORY_IMPORTANT_L4], 

+    "attr": [const_value.NVRAM_ATTR_RESERVE_BACKWARD],  

+    "err_str": "Can't Set the NVRAM_ATTR_RESERVE_BACKWARD for Important/Important_L4",

+    },

+    {"func": adjust_attr_cate_iii, 

+    "macro": const_value.__CCCIFS_SUPPORT__,  

+    "cate": [const_value.NVRAM_CATEGORY_IMPORTANT, const_value.NVRAM_CATEGORY_IMPORTANT_L4], 

+    "attr": [attr_default],  # no define NVRAM_ATTR_COMMITTED

+    "err_str": "Suggest Set the NVRAM_ATTR_COMMITTED for Important/Important_L4",

+    },

+    # ====================

+    # check func : adjust_attr_cate_iv,

+    {"func": adjust_attr_cate_iv, 

+    "macro": const_value.__NVRAM_OTP__,  

+    "cate": [const_value.NVRAM_CATEGORY_OTP], 

+    "attr": [const_value.NVRAM_ATTR_WRITEPROTECT, const_value.NVRAM_ATTR_MULTIPLE, const_value.NVRAM_ATTR_MSP, const_value.NVRAM_ATTR_OTA_RESET],  

+    "err_str": "Can't Set NVRAM_ATTR_WRITEPROTECT/NVRAM_ATTR_MULTIPLE/NVRAM_ATTR_MSP/NVRAM_ATTR_OTA_RESET for OTP",

+    },

+    # ====================

+    # check func : adjust_attr_cate_vi,

+    {"func": adjust_attr_cate_vi, 

+    "macro": const_value.__NVRAM_OTP__,  

+    "cate": [const_value.NVRAM_CATEGORY_SECUPACK], 

+    "attr": [const_value.NVRAM_ATTR_MSP, attr_default], # not default NVRAM_ATTR_CONFIDENTIAL  

+    "err_str": "Should set the NVRAM_ATTR_MSP/NVRAM_ATTR_CONFIDENTIAL",

+    },

+    {"func": adjust_attr_cate_vi, 

+    "macro": const_value.__NVRAM_OTP__ | const_value.__NVRAM_BIND_TO_CHIP_CIPHER__,  

+    "cate": [const_value.NVRAM_CATEGORY_SECUPACK], 

+    "attr": [attr_default, const_value.NVRAM_ATTR_CONFIDENTIAL, const_value.NVRAM_ATTR_MSP], 

+    "err_str": "Should set the NVRAM_ATTR_MSP/NVRAM_ATTR_CONFIDENTIAL",

+    },

+    # ====================

+    # check func : adjust_attr_cate_viii

+    {"func": adjust_attr_cate_viii, 

+    "macro": const_value.__NVRAM_CUSTOM_DISK__,  

+    "cate": [const_value.NVRAM_CATEGORY_CUSTOM_DISK], 

+    "attr": [const_value.NVRAM_ATTR_MSP], # not equal NVRAM_ATTR_AVERAGE   

+    "err_str": "Can't set other attribute except NVRAM_ATTR_AVERAGE",

+    },

+    # ====================

+    # check func : check_item_data_i

+    {"func": check_item_data_i, 

+    "macro": const_value.__NVRAM_CUSTOM_SENSITIVE__,  

+    "cate": [const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE|const_value.NVRAM_CATEGORY_CALIBRAT,

+             const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE|const_value.NVRAM_CATEGORY_IMPORTANT,

+             const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE|const_value.NVRAM_CATEGORY_IMPORTANT_L4,

+             const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE|const_value.NVRAM_CATEGORY_IMPORTANT_L1], 

+    "attr": [attr_default],   

+    "err_str": "Category internal & calibrat & important & sensitive can't be used at the same time!",

+    },

+    {"func": check_item_data_i, 

+    "macro": const_value.__NVRAM_CUSTOM_DISK__,  

+    "cate": [const_value.NVRAM_CATEGORY_CUSTOM_DISK|const_value.NVRAM_CATEGORY_INTERNAL,

+             const_value.NVRAM_CATEGORY_CUSTOM_DISK|const_value.NVRAM_CATEGORY_CALIBRAT,

+             const_value.NVRAM_CATEGORY_CUSTOM_DISK|const_value.NVRAM_CATEGORY_IMPORTANT,

+             const_value.NVRAM_CATEGORY_CUSTOM_DISK|const_value.NVRAM_CATEGORY_IMPORTANT_L4,

+             const_value.NVRAM_CATEGORY_CUSTOM_DISK|const_value.NVRAM_CATEGORY_IMPORTANT_L1], 

+    "attr": [attr_default],    

+    "err_str": "Category internal & calibrat & important & sensitive can't be used at the same time!",

+    },

+    {"func": check_item_data_i, 

+    "macro": const_value.__NVRAM_CUSTOM_DISK__ | const_value.__NVRAM_CUSTOM_SENSITIVE__,  

+    "cate": [const_value.NVRAM_CATEGORY_CUSTOM_DISK|const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE], 

+    "attr": [attr_default],   

+    "err_str": "Category internal & calibrat & important & sensitive can't be used at the same time!",

+    },

+    # ====================

+    # check func : check_item_data_ii

+    {"func": check_item_data_ii, 

+    "macro": const_value.__NVRAM_SECURE_DATA_STORAGE__,  

+    "cate": [const_value.NVRAM_CATEGORY_BACKUP_SDS|const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE,

+             const_value.NVRAM_CATEGORY_BACKUP_SDS|const_value.NVRAM_CATEGORY_CUSTOM_DISK,

+             const_value.NVRAM_CATEGORY_BACKUP_SDS|const_value.NVRAM_CATEGORY_OTP], 

+    "attr": [attr_default],    

+    "err_str": "Sds use with wrong category",

+    },

+    {"func": check_item_data_ii, 

+    "macro": const_value.__NVRAM_SECURE_DATA_STORAGE__,  

+    "cate": [const_value.NVRAM_CATEGORY_BACKUP_SDS], 

+    "attr": [const_value.NVRAM_ATTR_MULTIPLE, const_value.NVRAM_ATTR_RING, const_value.NVRAM_ATTR_PACKAGE, const_value.NVRAM_ATTR_BACKUP_FAT, const_value.NVRAM_ATTR_BACKUP_RAW],   

+    "err_str": "Sds use with wrong attribute LID",

+    },

+    # check func : check_item_data_vi

+    {"func": check_item_data_vi, 

+    "macro": macro_default,  

+    "cate": [const_value.NVRAM_CATEGORY_CALIBRAT], 

+    "attr": [const_value.NVRAM_ATTR_OTA_RESET],   

+    "err_str": "CALIBRAT LID should not have NVRAM_ATTR_OTA_RESET attribute!",

+    },

+    

+]

+

+

+

+class TestOther(unittest.TestCase):

+    def setUp(self):

+        data_restore()

+

+    @classmethod

+    def setUpClass(cls):

+        pass

+

+    @classmethod

+    def tearDownClass(cls):

+        pass

+            

+    

+    def test_common(self):

+        runner.stream.write("\n")

+        for dict_case in list_test_item:

+            data_restore()

+            global_value.macro = dict_case["macro"]

+            for cate in dict_case["cate"]:

+                logical_data_item_table[0].category = cate

+                for attr in dict_case["attr"]:

+                    logical_data_item_table[0].attr = attr

+                    runner.stream.write("\tcate = %s, attr = %s, fun = %s\n" %(get_cate_str(cate), get_attr_str(attr), dict_case["func"]))

+                    with self.assertRaisesRegex(SystemExit, dict_case["err_str"]):

+                        dict_case["func"](logical_data_item_table[0])

+    

+    # ------------------------------------

+    # test func: adjust_attr_cate_i

+    def test_only_one_record(self):

+        dict_case = {

+            "func": adjust_attr_cate_i, 

+            "macro": macro_default,  

+            "attr": [const_value.NVRAM_ATTR_MULTIREC_READ, const_value.NVRAM_ATTR_MULTI_DEFAULT],  

+            "err_str": "Can't Set the NVRAM_ATTR_MULTIREC_READ or NVRAM_ATTR_MULTI_DEFAULT for the lid with only one record",

+            "total_records": 1

+            }

+        runner.stream.write("\n")

+        logical_data_item_table[0].total_records = dict_case["total_records"]

+        for attr in dict_case["attr"]:

+            logical_data_item_table[0].attr = attr

+            runner.stream.write("\tattr = %s, total_records = %d fun = %s\n" %(get_attr_str(attr), dict_case["total_records"], dict_case["func"]))

+            with self.assertRaisesRegex(SystemExit, dict_case["err_str"]):

+                    dict_case["func"](logical_data_item_table[0])

+    # ------------------------------------

+    # test func: adjust_attr_cate_i

+    def test_default_value(self):

+        test_case = [

+            # ====================

+            # check func : adjust_attr_cate_i

+            {"func": adjust_attr_cate_i, 

+            "macro": macro_default,  

+            "attr": const_value.NVRAM_ATTR_GEN_DEFAULT,  

+            "err_str": "Can't Set the NVRAM_ATTR_GEN_DEFAULT for the lid with Zero of FF default value",

+            "p_def_val": [const_value.NVRAM_EF_FF_DEFAULT, const_value.NVRAM_EF_ZERO_DEFAULT],

+            "lid": [const_value.NVRAM_EF_NVRAM_UNIT_TEST_LID-1, const_value.NVRAM_EF_NVRAM_UNIT_TEST_LID_END+1]

+            },

+            {"func": adjust_attr_cate_i, 

+            "macro": const_value.__NVRAM_UT_TEST__,  

+            "attr": const_value.NVRAM_ATTR_GEN_DEFAULT,  

+            "err_str": "Can't Set the NVRAM_ATTR_GEN_DEFAULT for the lid with Zero of FF default value",

+            "p_def_val": [const_value.NVRAM_EF_FF_DEFAULT, const_value.NVRAM_EF_ZERO_DEFAULT],

+            "lid": [const_value.NVRAM_EF_NVRAM_UNIT_TEST_LID-1, const_value.NVRAM_EF_NVRAM_UNIT_TEST_LID_END+1]

+            },

+        ]

+        runner.stream.write("\n")

+        for dict_case in test_case:

+            global_value.macro = dict_case["macro"]

+            logical_data_item_table[0].attr = dict_case["attr"]

+            for lid in dict_case["lid"]:

+                logical_data_item_table[0].lid = lid

+                for p_def_val in dict_case["p_def_val"]:

+                    logical_data_item_table[0].p_default_value = p_def_val

+                    

+                    # --

+                    if lid == const_value.NVRAM_EF_NVRAM_UNIT_TEST_LID-1:

+                        runner.stream.write("\tattr = %s, p_def_val = 0x%x lid = %s fun = %s\n" %(get_attr_str(logical_data_item_table[0].attr), p_def_val, "NVRAM_EF_NVRAM_UNIT_TEST_LID - 1", dict_case["func"]))

+                    else:

+                        runner.stream.write("\tattr = %s, p_def_val = 0x%x lid = %s fun = %s\n" %(get_attr_str(logical_data_item_table[0].attr), p_def_val, "NVRAM_EF_NVRAM_UNIT_TEST_LID_END + 1", dict_case["func"]))

+                    # --

+                    

+                    with self.assertRaisesRegex(SystemExit, dict_case["err_str"]):

+                        dict_case["func"](logical_data_item_table[0])

+                    

+    # ------------------------------------

+    # test func: adjust_attr_cate_v

+    def test_attr_package_set(self):

+        test_case = [

+            # ====================

+            # check func : adjust_attr_cate_v

+            {"func": adjust_attr_cate_v, 

+            "macro": const_value.__NVRAM_PSEUDO_MERGE__,  

+            "attr": attr_default ,  # not define NVRAM_ATTR_PACKAGE

+            "cate": cate_default,   # not define NVRAM_CATEGORY_INTERNAL|NVRAM_CATEGORY_SECUPACK|NVRAM_CATEGORY_IMPORTANT|NVRAM_CATEGORY_CALIBRAT

+            "err_str": "Should set the NVRAM_ATTR_PACKAGE for this lid",

+            "file_size": 0 # (size+checksum)*total < NVRAM_CLUSTER_SIZE

+            },

+            {"func": adjust_attr_cate_v, 

+            "macro": const_value.__NVRAM_PSEUDO_MERGE__ | const_value.__NVRAM_CUSTOM_SENSITIVE__,  

+            "attr": attr_default ,  # not define NVRAM_ATTR_PACKAGE

+            "cate": cate_default,   # not define NVRAM_CATEGORY_INTERNAL|NVRAM_CATEGORY_SECUPACK|NVRAM_CATEGORY_IMPORTANT|NVRAM_CATEGORY_CALIBRAT|NVRAM_CATEGORY_CUSTOM_SENSITIVE

+            "err_str": "Should set the NVRAM_ATTR_PACKAGE for this lid",

+            "file_size": 0 # (size+checksum)*total < NVRAM_CLUSTER_SIZE

+            },

+            {"func": adjust_attr_cate_v, 

+            "macro": const_value.__NVRAM_PSEUDO_MERGE__ | const_value.__NVRAM_CUSTOM_DISK__,  

+            "attr": attr_default ,  # not define NVRAM_ATTR_PACKAGE

+            "cate": cate_default,   # not define NVRAM_CATEGORY_INTERNAL|NVRAM_CATEGORY_SECUPACK|NVRAM_CATEGORY_IMPORTANT|NVRAM_CATEGORY_CALIBRAT|NVRAM_CATEGORY_CUSTOM_DISK

+            "err_str": "Should set the NVRAM_ATTR_PACKAGE for this lid",

+            "file_size": 0 # (size+checksum)*total < NVRAM_CLUSTER_SIZE

+            },

+            {"func": adjust_attr_cate_v, 

+            "macro": const_value.__NVRAM_PSEUDO_MERGE__ | const_value.__NVRAM_CUSTOM_DISK__ | const_value.__NVRAM_CUSTOM_SENSITIVE__,  

+            "attr": attr_default ,  # not define NVRAM_ATTR_PACKAGE

+            "cate": cate_default,   # not define NVRAM_CATEGORY_INTERNAL|NVRAM_CATEGORY_SECUPACK|NVRAM_CATEGORY_IMPORTANT|NVRAM_CATEGORY_CALIBRAT|NVRAM_CATEGORY_CUSTOM_SENSITIVE|NVRAM_CATEGORY_CUSTOM_DISK

+            "err_str": "Should set the NVRAM_ATTR_PACKAGE for this lid",

+            "file_size": 0 # (size+checksum)*total < NVRAM_CLUSTER_SIZE

+            },

+        ]

+        

+        for dict_case in test_case:

+            global_value.macro = dict_case["macro"]

+            with self.assertRaisesRegex(SystemExit, dict_case["err_str"]):

+                dict_case["func"](logical_data_item_table[0])

+                

+    # ------------------------------------

+    # test func: adjust_attr_cate_v

+    def test_attr_package_conf(self):

+        dict_case = {

+            "func": adjust_attr_cate_v, 

+            "macro": const_value.__NVRAM_PSEUDO_MERGE__,  

+            "attr": const_value.NVRAM_ATTR_PACKAGE ,  

+            "attr_conf": [const_value.NVRAM_ATTR_MULTIPLE, const_value.NVRAM_ATTR_MSP],

+            "err_str": "Can't Set NVRAM_ATTR_MULTIPLE/NVRAM_ATTR_MSP for PACKAGE Lid",

+            "desc": "test"

+            }

+        

+        

+        runner.stream.write("\n")

+        global_value.macro = dict_case["macro"]

+        logical_data_item_table[0].attr = dict_case["attr"]

+        for attr_conf in dict_case["attr_conf"]:

+            logical_data_item_table[0].attr |= attr_conf

+            logical_data_item_table[0].description = dict_case["desc"]

+            runner.stream.write("\tattr = %s desc = %s func = %s\n" %(get_attr_str(logical_data_item_table[0].attr), dict_case["desc"], dict_case["func"]))

+            with self.assertRaisesRegex(SystemExit, dict_case["err_str"]):

+                dict_case["func"](logical_data_item_table[0])

+            self.assertEqual(logical_data_item_table[0].description, "null")

+            logical_data_item_table[0].attr &= ~attr_conf   

+    

+    # ------------------------------------

+    # test func: adjust_attr_cate_vii

+    def test_custom_sensitive(self):

+        dict_case = {

+            "func": adjust_attr_cate_vii, 

+            "macro": const_value.__NVRAM_CUSTOM_SENSITIVE__,

+            "cate": const_value.NVRAM_CATEGORY_CUSTOM_SENSITIVE,

+            "attr": [const_value.NVRAM_ATTR_MSP|const_value.NVRAM_ATTR_CONFIDENTIAL, const_value.NVRAM_ATTR_MSP|const_value.NVRAM_ATTR_MULTIPLE, const_value.NVRAM_ATTR_CONFIDENTIAL|const_value.NVRAM_ATTR_MULTIPLE] ,  

+            "err_str": "Should set the NVRAM_ATTR_MSP/NVRAM_ATTR_CONFIDENTIAL/NVRAM_ATTR_MULTIPLE",

+            }

+        

+        runner.stream.write("\n")

+        global_value.macro = dict_case["macro"]

+        logical_data_item_table[0].category = dict_case["cate"]

+        for attr in dict_case["attr"]:

+            logical_data_item_table[0].attr = attr

+            runner.stream.write("\tattr = %s cate = %s func = %s\n" %(get_attr_str(attr), get_cate_str(dict_case["cate"]), dict_case["func"]))

+            with self.assertRaisesRegex(SystemExit, dict_case["err_str"]):

+                dict_case["func"](logical_data_item_table[0])

+    # ------------------------------------

+    # test func: adjust_attr_cate_vii

+    def test_internal_and_gen_default(self):

+        dict_case = {

+            "func": adjust_attr_cate_vii, 

+            "macro": [const_value._SIMULATION, const_value.__PALLADIUM__, const_value.__FPGA__],

+            "cate": cate_default,   # not define NVRAM_CATEGORY_INTERNAL

+            "attr": const_value.NVRAM_ATTR_GEN_DEFAULT ,  

+            }

+            

+        for macro in dict_case["macro"]:

+            global_value.macro = macro

+            logical_data_item_table[0].attr = dict_case["attr"]

+            dict_case["func"](logical_data_item_table[0])

+            self.assertNotEqual(logical_data_item_table[0].attr&const_value.NVRAM_ATTR_GEN_DEFAULT, const_value.NVRAM_ATTR_GEN_DEFAULT)

+    

+    # ------------------------------------

+    # test func: adjust_attr_cate_xi

+    def test_cate_file_location(self):

+        dict_case = {

+            "func": adjust_attr_cate_xi, 

+            "macro": const_value.__NVRAM_SECURE_DATA_STORAGE__,

+            "cate": [const_value.NVRAM_CATEGORY_INTERNAL, const_value.NVRAM_CATEGORY_CALIBRAT, const_value.NVRAM_CATEGORY_IMPORTANT, const_value.NVRAM_CATEGORY_IMPORTANT_L4],   

+            "attr": const_value.NVRAM_ATTR_MULTIPLE|const_value.NVRAM_ATTR_RING|const_value.NVRAM_ATTR_PACKAGE|const_value.NVRAM_ATTR_BACKUP_FAT|const_value.NVRAM_ATTR_BACKUP_RAW ,  

+            }

+        

+        runner.stream.write("\n")

+        global_value.macro = dict_case["macro"]

+        for cate in dict_case["cate"]:

+            logical_data_item_table[0].category = cate

+            logical_data_item_table[0].attr = dict_case["attr"]

+            runner.stream.write("\tattr = %s cate = %s func = %s\n" %(get_attr_str(dict_case["attr"]), get_cate_str(cate), dict_case["func"]))

+            dict_case["func"](logical_data_item_table[0])

+            self.assertEqual(logical_data_item_table[0].category&const_value.NVRAM_CATEGORY_BACKUP_SDS, const_value.NVRAM_CATEGORY_BACKUP_SDS)

+            self.assertNotEqual(logical_data_item_table[0].attr&const_value.NVRAM_ATTR_MULTIPLE, const_value.NVRAM_ATTR_MULTIPLE)

+            self.assertNotEqual(logical_data_item_table[0].attr&const_value.NVRAM_ATTR_RING, const_value.NVRAM_ATTR_RING)

+            self.assertNotEqual(logical_data_item_table[0].attr&const_value.NVRAM_ATTR_PACKAGE, const_value.NVRAM_ATTR_PACKAGE)

+            self.assertNotEqual(logical_data_item_table[0].attr&const_value.NVRAM_ATTR_BACKUP_FAT, const_value.NVRAM_ATTR_BACKUP_FAT)

+            self.assertNotEqual(logical_data_item_table[0].attr&const_value.NVRAM_ATTR_BACKUP_RAW, const_value.NVRAM_ATTR_BACKUP_RAW)

+    

+    # ------------------------------------

+    # test func: check_item_data_ii

+    def test_data_put_sds(self):

+        list_case = [

+            {"func": check_item_data_ii, 

+            "macro": const_value.__NVRAM_SECURE_DATA_STORAGE__,

+            "cate": const_value.NVRAM_CATEGORY_BACKUP_SDS,  

+            "attr": attr_default,

+            "size": 129,

+            "total_records": 512,

+            "err_str": "Data is too large to put into sds"

+            },

+            {"func": check_item_data_ii, 

+            "macro": const_value.__NVRAM_SECURE_DATA_STORAGE__ | const_value.__NVRAM_BIND_TO_CHIP_CIPHER__,

+            "cate": const_value.NVRAM_CATEGORY_BACKUP_SDS, 

+            "attr": const_value.NVRAM_ATTR_MSP,            

+            "size": 129,

+            "total_records": 512,

+            "err_str": "Data is too large to put into sds"

+            },

+        ]

+        

+        for dict_case in list_case:

+            global_value.macro = dict_case["macro"]

+            logical_data_item_table[0].attr = dict_case["attr"]

+            logical_data_item_table[0].category = dict_case["cate"]

+            logical_data_item_table[0].size = dict_case["size"]

+            logical_data_item_table[0].total_records = dict_case["total_records"]

+            with self.assertRaisesRegex(SystemExit, dict_case["err_str"]):

+                dict_case["func"](logical_data_item_table[0])

+

+    # ------------------------------------

+    # test func: check_item_data_iii

+    def test_attr_multi_default(self):

+        dict_case = {

+            "func": check_item_data_iii, 

+            "str_def_val": ["NVRAM_EF_ZERO_DEFAULT", "NVRAM_EF_FF_DEFAULT"],

+            "attr": const_value.NVRAM_ATTR_MULTI_DEFAULT,  

+            "err_str": "Cannot set ZERO_DEFAULT or FF_DEFAULT with multi_default!",

+            }

+            

+        runner.stream.write("\n")

+        logical_data_item_table[0].attr = dict_case["attr"]

+        for s_def_val in dict_case["str_def_val"]:

+            logical_data_item_table[0].str_default_value = s_def_val

+            runner.stream.write("\tattr = %s str_def_val = %s func = %s\n" %(get_attr_str(dict_case["attr"]), s_def_val, dict_case["func"]))

+            with self.assertRaisesRegex(SystemExit, dict_case["err_str"]):

+                dict_case["func"](logical_data_item_table[0])

+    

+    # ------------------------------------

+    # test func: check_item_data_iv

+    def test_size_big(self):

+        global_value.macro = macro_default # not define __NVRAM_LARGE_RECORD_SIZE__

+        logical_data_item_table[0].total_records = 512

+        logical_data_item_table[0].size = 128 * 512

+        

+        with self.assertRaisesRegex(SystemExit, "LID Size is too big"):

+            check_item_data_iv(logical_data_item_table[0])

+           

+    # ------------------------------------

+    # test func: check_item_data_iv

+    def test_size_bit_msp(self):

+        global_value.macro = const_value.__NVRAM_BIND_TO_CHIP_CIPHER__ # not define __NVRAM_LARGE_RECORD_SIZE__

+        logical_data_item_table[0].attr = const_value.NVRAM_ATTR_MSP

+        logical_data_item_table[0].total_records = 512

+        logical_data_item_table[0].size = 128 * 512

+        with self.assertRaisesRegex(SystemExit, "LID Size is too big"):

+            check_item_data_iv(logical_data_item_table[0])

+    

+    # ------------------------------------

+    # test func: check_item_data_v

+    def test_cate_custpack(self):

+        dict_case = {

+            "func": check_item_data_v, 

+            "str_def_val": ["NVRAM_EF_ZERO_DEFAULT", "NVRAM_EF_FF_DEFAULT"],

+            "cate": const_value.NVRAM_CATEGORY_CUSTPACK,   

+            "err_str": "Cannot set ZERO_DEFAULT or FF_DEFAULT with custpack!",

+            }

+            

+        runner.stream.write("\n")

+        logical_data_item_table[0].category = dict_case["cate"]

+        for s_def_val in dict_case["str_def_val"]:

+            logical_data_item_table[0].str_default_value = s_def_val

+            runner.stream.write("\tcate = %s str_def_val = %s func = %s\n" %(get_cate_str(dict_case["cate"]), s_def_val, dict_case["func"]))

+            with self.assertRaisesRegex(SystemExit, dict_case["err_str"]):

+                dict_case["func"](logical_data_item_table[0])

+    # ------------------------------------

+    # test func: check_lid_enum_overlapping

+    def test_lid_overlapping(self):

+        logical_data_item_table[1].lid = logical_data_item_table[0].lid

+

+        with self.assertRaisesRegex(SystemExit, "Please contact NVRAM owner if your NVRAM sub-group size should be enlarged"):

+            check_lid_enum_overlapping()

+    # ------------------------------------

+    # test func: check_lid_fileprefix_overlapping

+    def test_prefix_overlapping(self):

+        logical_data_item_table[1].FilePrefix = logical_data_item_table[0].FilePrefix

+        

+        with self.assertRaisesRegex(SystemExit, "duplicated fileprefix and fileverno!"):

+            check_lid_fileprefix_overlapping()

+    # ------------------------------------

+    # test func: check_write_protect

+    def test_write_protect(self):

+        logical_data_item_table[0].attr |= const_value.NVRAM_ATTR_WRITEPROTECT

+        logical_data_item_table[0].str_LID = "NVRAM_EF_IMEI_IMEISV_LID_1"   #

+        with self.assertRaisesRegex(SystemExit, "Please contact NVRAM owner if your really need this attribute for the LID"):

+            check_write_protect()

+    

+    # ------------------------------------

+    # test func: check_special_lid_parameter

+    def test_attr_raw_data(self):

+        logical_data_item_table[0].attr = const_value.NVRAM_ATTR_RAW_DATA

+        logical_data_item_table[0].total_records = 2

+        with self.assertRaisesRegex(SystemExit, "NVRAM_ATTR_RAW_DATA can not support multiple record ,and can only use NVRAM_EF_ZERO_DEFAULT."):

+            check_special_lid_parameter()

+    # ------------------------------------

+    # test func: check_special_lid_parameter

+    def test_attr_raw_data(self):

+        logical_data_item_table[0].attr = const_value.NVRAM_ATTR_RAW_DATA

+        logical_data_item_table[0].total_records = 1

+        logical_data_item_table[0].p_default_value = const_value.NVRAM_EF_FF_DEFAULT # not equal NVRAM_EF_ZERO_DEFAULT

+        with self.assertRaisesRegex(SystemExit, "NVRAM_ATTR_RAW_DATA can not support multiple record ,and can only use NVRAM_EF_ZERO_DEFAULT."):

+            check_special_lid_parameter()

+        

+    # ------------------------------------

+    # test func: hash_md5

+    def test_md5(self):

+        strs = "abcde12345"

+        md5 = list("df6f58808ebfd3e609c234cf2283a989")

+        md5_list = []

+        for i in range(16):

+            md5_list.append(int(md5[2 * i], 16) * 16 + int(md5[2 * i + 1], 16))

+

+        self.assertEqual(md5_list, hash_md5(strs))

+    

+    # ------------------------------------

+    # test func: check_lid_hash_key

+    def test_hash_modify_lid(self):

+        global_value.macro |= const_value.__NVRAM_LID_HASH_CHECK__

+        global_value.macro |= const_value.__MTK_INTERNAL__

+        logical_data_item_table[0].lid = 30

+        with self.assertRaisesRegex(SystemExit, "HASH key check error"):

+            check_lid_hash_key()

+    def test_hash_modify_str(self):

+        global_value.macro |= const_value.__NVRAM_LID_HASH_CHECK__

+        global_value.macro |= const_value.__MTK_INTERNAL__

+        logical_data_item_table[0].str_LID = "NVRAM_EF_IMEI_IMEISV_LID_1"

+

+        with self.assertRaisesRegex(SystemExit, "HASH key check error"):

+            check_lid_hash_key()

+    def test_hash_modify_prefix(self):

+        global_value.macro |= const_value.__NVRAM_LID_HASH_CHECK__

+        global_value.macro |= const_value.__MTK_INTERNAL__

+        l_prefix = list(logical_data_item_table[0].FilePrefix)

+        l_prefix[1] = chr(ord(l_prefix[2]) + 1)

+        logical_data_item_table[0].FilePrefix = "".join(l_prefix)

+        with self.assertRaisesRegex(SystemExit, "HASH key check error"):

+            check_lid_hash_key()

+    def test_hash_modify_verno(self):

+        global_value.macro |= const_value.__NVRAM_LID_HASH_CHECK__

+        global_value.macro |= const_value.__MTK_INTERNAL__

+        l_prefix = list(logical_data_item_table[0].FileVerno)

+        l_prefix[1] = chr(ord(l_prefix[0]) + 1)

+        logical_data_item_table[0].FileVerno = "".join(l_prefix)

+

+        with self.assertRaisesRegex(SystemExit, "HASH key check error"):

+            check_lid_hash_key()

+    def test_hash_modify_hashkey(self):

+        global_value.macro |= const_value.__NVRAM_LID_HASH_CHECK__

+        global_value.macro |= const_value.__MTK_INTERNAL__

+        logical_data_item_table[0].hash_key += 1

+

+        with self.assertRaisesRegex(SystemExit, "HASH key check error"):

+            check_lid_hash_key()
\ No newline at end of file
diff --git a/mcu/tools/NVRAMStatistic/autogen_v2/tests/test_suite.py b/mcu/tools/NVRAMStatistic/autogen_v2/tests/test_suite.py
new file mode 100644
index 0000000..ea8011f
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/autogen_v2/tests/test_suite.py
@@ -0,0 +1,43 @@
+import unittest

+

+from tests.lid_table_handle import lid_table_creat, data_restore, runner

+from tests.test_cate_attr_conflict import TestCateAttrConflict

+from tests.test_other import TestOther

+from autogen.src.initconfig import logical_data_item_table

+from autogen.src.initconfig import const_value

+from autogen.src.initconfig import global_value

+from autogen.src.initconfig import LtableEntry

+

+test_cases = (TestOther, TestCateAttrConflict)

+

+

+def main(logging_path):

+    global_value.logging_path = logging_path

+    global_value.logger_config()

+    lid_table_creat()

+    data_restore()

+    

+    suite = unittest.TestSuite()

+

+    # creat TestLoader , load test case

+    loader = unittest.TestLoader()

+    for test_class in test_cases:

+        # loading test cases in a class

+        tests = loader.loadTestsFromTestCase(test_class)

+        # add test case

+        suite.addTests(tests)

+

+    # creat TestRunner

+    # runner = unittest.TextTestRunner(verbosity=3)

+    # fd.close()

+    

+    # test run

+    runner.run(suite)

+    

+    # with open("auto_gen_test_report.txt", "w+") as f:

+    #     # creat TestRunner

+    #     runner = unittest.TextTestRunner(verbosity=3, stream=f)

+    #     runner.stream.write(strs)

+    #     

+    #     # test run

+    #     runner.run(suite)

diff --git a/mcu/tools/NVRAMStatistic/debug/readme.txt b/mcu/tools/NVRAMStatistic/debug/readme.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/debug/readme.txt
diff --git a/mcu/tools/NVRAMStatistic/gen_secure_nvram_lid_structure_to_db.pl b/mcu/tools/NVRAMStatistic/gen_secure_nvram_lid_structure_to_db.pl
new file mode 100644
index 0000000..24d6f91
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/gen_secure_nvram_lid_structure_to_db.pl
@@ -0,0 +1,58 @@
+use strict;
+
+if (@ARGV < 2){
+	print "Parameter formatte error! need two file name.\n";
+}
+
+# 
+my @out_str;
+my $outStream;
+my $VALUE = "STRUCT_DB";
+my ($ERR_OK, $ERR_NOTIFY, $ERR_ERROR, $ERR_WARNING, $ERR_DEBUG, $ERR_OPEN_FILE) = 0..5;
+
+my $inFile = @ARGV[0];
+my $outFile = @ARGV[1];
+
+# READ in  file
+if (not -e $inFile){
+	print "input file $inFile not exists.\n";
+	exit 1;
+} 
+
+
+open FILE_HANDLE, "<$inFile" or die "couldn't open $inFile\n" && return $ERR_OPEN_FILE;
+	
+	while(<FILE_HANDLE>){
+		my $line = $_;
+		chomp($line);
+		if ($line =~ /\s*typedef/){
+			my @line_item = split(/ +/, $line);
+			if ($#line_item >= 2){
+				my @tmp = split(';', $line_item[2]);
+				push(@out_str, $tmp[0]);
+			}
+			else
+			{
+				print "error :\n";
+			}
+			
+		}
+	}
+	close FILE_HANDLE;
+
+# Write file
+foreach my $item (@out_str){
+	my $line = "$item = $VALUE\n";
+	$outStream .= $line;
+}
+
+&WriteFile($outFile, $outStream);
+
+sub WriteFile
+{
+    my ($strFilePath, $strContent) = @_;
+    open FILE_HANDLE, ">>$strFilePath" or  print "couldn't open $strFilePath\n" && return $ERR_OPEN_FILE;
+    print FILE_HANDLE $strContent;
+    close FILE_HANDLE;
+}
+
diff --git a/mcu/tools/NVRAMStatistic/include/nvram_auto_gen.h b/mcu/tools/NVRAMStatistic/include/nvram_auto_gen.h
new file mode 100644
index 0000000..fba4af3
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/include/nvram_auto_gen.h
@@ -0,0 +1,280 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2006
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ * nvram_auto_gen.h
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   This file is intends for generating NVRAM information.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+#ifndef NVRAM_AUTO_GEN_H
+#define NVRAM_AUTO_GEN_H
+
+//MSBB remove #include "kal_non_specific_general_types.h"
+
+#ifndef __packed
+#define __packed
+#endif
+
+#define COPYRIGHTS_HEADER "/*****************************************************************************\n"\
+    "*  Copyright Statement:\n"\
+    "*  --------------------\n"\
+    "*  This software is protected by Copyright and the information contained\n"\
+    "*  herein is confidential. The software may not be copied and the information\n"\
+    "*  contained herein may not be used or disclosed except with the written\n"\
+    "*  permission of MediaTek Inc. (C) 2008\n"\
+    "*\n"\
+    "*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES\n"\
+    "*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS (\"MEDIATEK SOFTWARE\")\n"\
+    "*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON\n"\
+    "*  AN \"AS-IS\" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,\n"\
+    "*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF\n"\
+    "*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.\n"\
+    "*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE\n"\
+    "*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR\n"\
+    "*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH\n"\
+    "*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO\n"\
+    "*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S\n"\
+    "*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.\n"\
+    "*\n"\
+    "*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE\n"\
+    "*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,\n"\
+    "*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,\n"\
+    "*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO\n"\
+    "*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. \n"\
+    "*\n"\
+    "*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE\n"\
+    "*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF\n"\
+    "*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND\n"\
+    "*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER\n"\
+    "*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).\n"\
+    "*\n"\
+    "*****************************************************************************/\n"\
+    "\n"\
+    "/*****************************************************************************\n"\
+    " *\n"\
+    " * Filename:\n"\
+    " *   %s\n"\
+    " *\n"\
+    " * Project:\n"\
+    " *   MAUI\n"\
+    " *\n"\
+    " * Description:\n"\
+    " *   This file is intends for NVRAM auto gen statistics\n"\
+    " *\n"\
+    " * Author:\n"\
+    " *   nvram auto gen !\n"\
+    " * -------\n"\
+    " *\n"\
+    " *============================================================================\n"\
+    " *\n"\
+    " * This file is automatically generated by the nvram gen procedure\n"\
+    " *\n"\
+    " ****************************************************************************/\n"
+
+#define NVRAM_FUNCTION_HEAD \
+"/*****************************************************************************\n"\
+"* FUNCTION\n"\
+"*  %s\n"\
+"* DESCRIPTION\n"\
+"*  used to restore mmi_cache_%s to default value\n"\
+"* PARAMETERS\n"\
+"*  buffer    [IN]\n"\
+"* RETURNS\n"\
+"*  none\n"\
+"*****************************************************************************/\n"
+
+
+#define NVRAM_RESTORE_FUNCTION_NAME \
+"void nvram_restore_%s_cache(nvram_reset_category_enum category, nvram_app_id_enum app_id, kal_uint8 *buffer)\n"\
+"{\n"\
+"    /*----------------------------------------------------------------*/\n"\
+"    /* Code Body                                                      */\n"\
+"    /*----------------------------------------------------------------*/\n"\
+"    switch(app_id)\n"\
+"    {\n"
+
+#define NVRAM_RESTORE_FUNCTION_BREAK    \
+"\n"\
+"            if (category == NVRAM_RESET_CERTAIN)\n"\
+"            {\n"\
+"                break;\n"\
+"            }\n"
+
+#define NVRAM_RESTORE_FUNCTION_TAIL \
+"        default:\n"\
+"        break;\n"\
+"    }\n"\
+"}\n"\
+"\n"\
+"\n"
+
+#define NVRAM_AUTO_GEN_COMMENT  \
+"            /* Reset: %s */\n"\
+
+#define R_F_DOM_COMMENT    \
+"/* %s system settings */\n"
+
+#define R_F_DOM_ENUM_BEGIN  \
+"typedef enum\n"\
+"{\n"
+
+#define R_F_DOM_CONTENT_ID     \
+"    %s,    "\
+
+#define R_F_DOM_CONTENT_DESCRIPTION     \
+"/* %s */\n"\
+
+#define R_F_DOM_ENUM_END    \
+"    NVRAM_LAST_%s_ELEMENT\n"\
+"}%sDATA;\n"\
+"\n"
+
+#define R_F_MCF_ENUM_END    \
+"    NVRAM_EF_LAST_%s\n"\
+"}%s;\n"\
+"\n"
+
+#define NVRAM_AUTO_GEN_MAX_PATH_LEN 128
+#define NVRAM_EXIT_CODE_ERROR 3
+
+#endif/*NVRAM_AUTO_GEN_H*/
diff --git a/mcu/tools/NVRAMStatistic/include/nvram_gen_cache_table.h b/mcu/tools/NVRAMStatistic/include/nvram_gen_cache_table.h
new file mode 100644
index 0000000..f36e8cb
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/include/nvram_gen_cache_table.h
@@ -0,0 +1,235 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+#ifndef NVRAM_GEN_CACHE_TABLE_H
+#define NVRAM_GEN_CACHE_TABLE_H
+
+#include "kal_general_types.h"
+#include "kal_public_api.h"
+
+#include "nvram_auto_gen.h"
+#include "nvram_defs.h"
+#include "nvram_internal.h"
+#include "nvram_enums.h"
+#include "nvram_cache.h"
+
+/* High trace will exist current env */
+#define NVRAM_TRC_HIGH(x)           { printf(x); exit(3);}
+#define NVRAM_TRC_HIGH1(x,y)        { printf(x,y); exit(3);}
+#define NVRAM_TRC_LOW(x)            { printf(x);}
+#define NVRAM_TRC_LOW1(xx, x)       { printf(xx,x);}
+#define NVRAM_TRC_LOW2(xx, x, y)    { printf(xx, x, y);}
+
+#define NVRAM_MAKE_LID_FILENAME(buf, prefix, M, verno) {\
+   ((kal_char*) (buf))[0] = ((kal_char*) (prefix))[0];  \
+   ((kal_char*) (buf))[1] = ((kal_char*) (prefix))[1];  \
+   ((kal_char*) (buf))[2] = ((kal_char*) (prefix))[2];  \
+   ((kal_char*) (buf))[3] = ((kal_char*) (prefix))[3];  \
+   ((kal_char*) (buf))[4] = (kal_char) (M);             \
+   ((kal_char*) (buf))[5] = ((kal_char*) (verno))[0];   \
+   ((kal_char*) (buf))[6] = ((kal_char*) (verno))[1];   \
+   ((kal_char*) (buf))[7] = ((kal_char*) (verno))[2];   \
+   ((kal_char*) (buf))[8] = '\0';                       \
+};
+
+#define NVRAM_MAKE_PACKAGE_FILENAME(buf, M) {       \
+   ((kal_char*) (buf))[0] = 'P';                    \
+   ((kal_char*) (buf))[1] = 'A';                    \
+   ((kal_char*) (buf))[2] = 'C';                    \
+   ((kal_char*) (buf))[3] = 'K';                    \
+   ((kal_char*) (buf))[4] = (kal_char) (M);         \
+   ((kal_char*) (buf))[5] = 'L';                    \
+   ((kal_char*) (buf))[6] = 'I';                    \
+   ((kal_char*) (buf))[7] = 'D';                    \
+   ((kal_char*) (buf))[8] = '\0';                   \
+};
+
+/* core folder */
+#define NVRAM_FS_COREITEM_PATH               "Z:\\\\NVRAM\\\\NVD_CORE"
+#define NVRAM_FS_CALIBRAT_DATAITEM_PATH	     "Z:\\\\NVRAM\\\\CALIBRAT"
+#define NVRAM_FS_IMPT_DATAITEM_PATH    	     "Z:\\\\NVRAM\\\\NVD_IMEI"
+#define NVRAM_FS_CUST_DATAITEM_PATH          "Z:\\\\NVRAM\\\\NVD_CUST"
+#if defined(__MTK_TARGET__) && defined(__NVRAM_IMPORTANT_PARTITIONS__) && defined(__CCCIFS_SUPPORT__)
+    #define NVRAM_FS_IMPORTNT_DATAITEM_PATH           "X:"
+    #define NVRAM_FS_IMPORTNT_DATAITEM_PATH2          "Y:"
+#else
+    #define NVRAM_FS_IMPORTNT_DATAITEM_PATH      "Z:\\\\NVRAM\\\\IMPORTNT"
+#endif
+
+#ifdef __NVRAM_BACKUP_DISK_FAT__
+#if defined(__TC01__) && defined(__MTK_TARGET__)
+#define NVRAM_FS_BACKUP_ROOT_PATH            "G:\\\\NVRAM"
+#else
+#define NVRAM_FS_BACKUP_ROOT_PATH            "Z:\\\\NVRAM_BAK"
+#endif
+#endif
+
+
+#define NVRAM_FS_DATAITEM_PATH               "Z:\\\\NVRAM\\\\NVD_DATA"
+
+#if defined (__NVRAM_UT_TEST__) 
+/*  paths defined in __NVRAM_UT_TEST__ is used for nvram first init test*/
+
+/* NVRAM Test Folder Path */
+#define NVRAM_TEST_FS_COREITEM_PATH               "Z:\\\\NV_TEST\\\\NVD_CORE"
+#define NVRAM_TEST_FS_CALIBRAT_DATAITEM_PATH	     "Z:\\\\NV_TEST\\\\CALIBRAT"
+#define NVRAM_TEST_FS_IMPT_DATAITEM_PATH    	     "Z:\\\\NV_TEST\\\\NVD_IMEI"
+#define NVRAM_TEST_FS_CUST_DATAITEM_PATH          "Z:\\\\NV_TEST\\\\NVD_CUST"
+#define NVRAM_TEST_FS_DATAITEM_PATH               "Z:\\\\NV_TEST\\\\NVD_DATA"
+#if defined(__MTK_TARGET__) && defined(__NVRAM_IMPORTANT_PARTITIONS__) && defined(__CCCIFS_SUPPORT__)
+    #define NVRAM_TEST_FS_IMPORTNT_DATAITEM_PATH           "X:\\\\NV_TEST\\\\"
+    #define NVRAM_TEST_FS_IMPORTNT_DATAITEM_PATH2          "Y:\\\\NV_TEST\\\\"
+#else
+    #define NVRAM_TEST_FS_IMPORTNT_DATAITEM_PATH      "Z:\\\\NV_TEST\\\\IMPORTNT"
+#endif
+
+extern kal_taskid nvram_test_task1_id;
+extern kal_uint8 is_insulation_access;
+
+#endif
+
+
+#if defined (__NVRAM_UT_TEST__) && !defined(__NVRAM_LID_CACHE__)
+#define NVRAM_FS_MAKE_LID_PATH_FILENAME_1( buf, name )   if((is_insulation_access) && (nvram_test_task1_id) && (kal_get_current_task()==nvram_test_task1_id))\
+	sprintf(buf, "%s\\\\%s", NVRAM_TEST_FS_DATAITEM_PATH, name);\
+	else \
+    sprintf(buf, "%s\\\\%s", NVRAM_FS_DATAITEM_PATH, name)
+
+#define NVRAM_FS_MAKE_CORE_PATH_FILENAME(buf, name)   if((is_insulation_access) && (nvram_test_task1_id) && (kal_get_current_task()==nvram_test_task1_id))\
+	sprintf(buf, "%s\\\\%s", NVRAM_TEST_FS_COREITEM_PATH, name);\
+	else \
+	sprintf(buf, "%s\\\\%s", NVRAM_FS_COREITEM_PATH, name)     
+   
+#define NVRAM_FS_MAKE_CRITICAL_CALIBRAT_PATH_FILENAME(buf, name)    if((is_insulation_access) && (nvram_test_task1_id) && (kal_get_current_task()==nvram_test_task1_id))\
+	  sprintf(buf, "%s\\\\%s", NVRAM_TEST_FS_CALIBRAT_DATAITEM_PATH, name);\
+	  else \
+	  sprintf(buf, "%s\\\\%s", NVRAM_FS_CALIBRAT_DATAITEM_PATH, name)  
+   
+#define NVRAM_FS_MAKE_CRITICAL_IMEI_PATH_FILENAME(buf, name)    if((is_insulation_access) && (nvram_test_task1_id) && (kal_get_current_task()==nvram_test_task1_id))\
+	  sprintf(buf, "%s\\\\%s", NVRAM_TEST_FS_IMPT_DATAITEM_PATH, name);\
+	  else \
+	  sprintf(buf, "%s\\\\%s", NVRAM_FS_IMPT_DATAITEM_PATH, name)
+   
+#define NVRAM_FS_MAKE_CUST_PATH_FILENAME(buf, name) if((is_insulation_access) && (nvram_test_task1_id) && (kal_get_current_task()==nvram_test_task1_id))\
+	  sprintf(buf, "%s\\\\%s", NVRAM_TEST_FS_CUST_DATAITEM_PATH, name);\
+	  else \
+	  sprintf(buf, "%s\\\\%s", NVRAM_FS_CUST_DATAITEM_PATH, name)
+   
+#define NVRAM_FS_MAKE_IMPORTNT_PATH_FILENAME(buf, name) if((is_insulation_access) && (nvram_test_task1_id) && (kal_get_current_task()==nvram_test_task1_id))\
+	  sprintf(buf, "%s\\\\%s", NVRAM_TEST_FS_IMPORTNT_DATAITEM_PATH, name);\
+	  else \
+	  sprintf(buf, "%s\\\\%s", NVRAM_FS_IMPORTNT_DATAITEM_PATH, name)
+
+#else
+#define NVRAM_FS_MAKE_LID_PATH_FILENAME_1( buf, name )   \
+   sprintf(buf, "%s\\\\%s", NVRAM_FS_DATAITEM_PATH, name)
+
+#define NVRAM_FS_MAKE_CORE_PATH_FILENAME(buf, name)        \
+   sprintf(buf, "%s\\\\%s", NVRAM_FS_COREITEM_PATH, name);
+
+#define NVRAM_FS_MAKE_CRITICAL_CALIBRAT_PATH_FILENAME(buf, name)    \
+   sprintf(buf, "%s\\\\%s", NVRAM_FS_CALIBRAT_DATAITEM_PATH, name);
+
+#define NVRAM_FS_MAKE_CRITICAL_IMPT_PATH_FILENAME(buf, name)    \
+   sprintf(buf, "%s\\\\%s", NVRAM_FS_IMPT_DATAITEM_PATH, name);
+
+#define NVRAM_FS_MAKE_CRITICAL_IMEI_PATH_FILENAME(buf, name)   \
+	sprintf(buf, "%s\\\\%s", NVRAM_FS_IMPT_DATAITEM_PATH, name);
+   
+#define NVRAM_FS_MAKE_CUST_PATH_FILENAME(buf, name) \
+   sprintf(buf, "%s\\\\%s", NVRAM_FS_CUST_DATAITEM_PATH, name);
+
+#define NVRAM_FS_MAKE_IMPORTNT_PATH_FILENAME(buf, name) \
+   sprintf(buf, "%s\\\\%s", NVRAM_FS_IMPORTNT_DATAITEM_PATH, name);
+
+#endif
+
+/* share memery padding */
+#define SHARE_MEM_64BYTE_ALIGN 64
+#define DIRTY_BLOCK_SIZE 32
+#define DIRTY_4BYTE_ALIGN 4
+
+#ifdef __NVRAM_PARTIAL_CACHE__
+#define SHARE_MEMORY_SIZE (0x700000)
+#else
+#define SHARE_MEMORY_SIZE (0x1200000)
+#endif
+
+/***********************************************************
+ * Global Variable
+ **********************************************************/
+/*
+
+typedef struct {
+    nvram_lid_enum LID;
+    kal_uint32 total_records;
+    kal_uint32 file_length;
+    kal_uint32 cache_offset;
+    kal_uint32 dirty_offset;
+    kal_uint32 valid_offset;
+    kal_char file_path[NVRAM_AUTO_GEN_MAX_PATH_LEN];
+}nvram_cache_lid_info_struct;
+
+
+
+typedef struct
+{
+    kal_uint32 cache_lid_num;
+    kal_uint32 table_index_offset;
+    kal_uint32 table_index_size;
+    kal_uint32 dirty_mapping_offset;
+    kal_uint32 valid_mapping_offset;
+    kal_uint32 dirty_mapping_size;
+    kal_uint32 cache_table_offset;
+    kal_uint32 cache_table_size;
+}nvram_cache_lid_info_header;
+*/
+
+extern kal_uint32 nvram_gen_total_lid;
+
+// nvram_lid_cache_table_struct *cache_info_table = cache_info_array;
+
+
+
+/***********************************************************
+ * Global Function
+ **********************************************************/
+extern nvram_folder_enum nvram_query_folder_index(nvram_category_enum category);
+
+extern void nvram_util_make_lid_filename(nvram_ltable_entry_struct *ldi, NVRAM_FILE_NAME nvramname, kal_bool first_copy);
+
+extern kal_wchar *nvram_query_file_name(nvram_folder_enum folder_idx, kal_char  *nvramname, kal_wchar *filename);
+
+#endif /*NVRAM_GEN_CACHE_TABLE_H*/
+
diff --git a/mcu/tools/NVRAMStatistic/include/nvram_hash_check.h b/mcu/tools/NVRAMStatistic/include/nvram_hash_check.h
new file mode 100644
index 0000000..09a268a
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/include/nvram_hash_check.h
@@ -0,0 +1,71 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2006
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ * nvram_hash_check.c
+ *
+ * Project:
+ * --------
+ *   UMOLYA
+ *
+ * Description:
+ * ------------
+ *   This file is use to check LID hash info correct.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+
+#ifndef NVRAM_HASH_CHECK_H  
+#define NVRAM_HASH_CHECK_H  
+#include "nvram_defs.h"
+
+kal_bool nvram_hash_check(nvram_ltable_entry_struct *ldi);
+#endif /* NVRAM_HASH_CHECK_H */
\ No newline at end of file
diff --git a/mcu/tools/NVRAMStatistic/include/nvram_white_list.h b/mcu/tools/NVRAMStatistic/include/nvram_white_list.h
new file mode 100644
index 0000000..e50200c
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/include/nvram_white_list.h
@@ -0,0 +1,8 @@
+#ifndef __NVRAM_WHITE_LIST_H__
+#define __NVRAM_WHITE_LIST_H__
+extern const char *g_nvram_white_list_for_multiple_attr[];
+extern const int g_nr_nvram_white_list_for_multiple_attr;
+
+extern const char *g_nvram_white_list_for_write_protect_attr[];
+extern const int g_nr_nvram_white_list_for_write_protect_attr;
+#endif
\ No newline at end of file
diff --git a/mcu/tools/NVRAMStatistic/include/zconf.h b/mcu/tools/NVRAMStatistic/include/zconf.h
new file mode 100644
index 0000000..cdfb823
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/include/zconf.h
@@ -0,0 +1,332 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+#ifdef Z_PREFIX
+#  define deflateInit_          z_deflateInit_
+#  define deflate               z_deflate
+#  define deflateEnd            z_deflateEnd
+#  define inflateInit_          z_inflateInit_
+#  define inflate               z_inflate
+#  define inflateEnd            z_inflateEnd
+#  define deflateInit2_         z_deflateInit2_
+#  define deflateSetDictionary  z_deflateSetDictionary
+#  define deflateCopy           z_deflateCopy
+#  define deflateReset          z_deflateReset
+#  define deflateParams         z_deflateParams
+#  define deflateBound          z_deflateBound
+#  define deflatePrime          z_deflatePrime
+#  define inflateInit2_         z_inflateInit2_
+#  define inflateSetDictionary  z_inflateSetDictionary
+#  define inflateSync           z_inflateSync
+#  define inflateSyncPoint      z_inflateSyncPoint
+#  define inflateCopy           z_inflateCopy
+#  define inflateReset          z_inflateReset
+#  define inflateBack           z_inflateBack
+#  define inflateBackEnd        z_inflateBackEnd
+#  define compress              z_compress
+#  define compress2             z_compress2
+#  define compressBound         z_compressBound
+#  define uncompress            z_uncompress
+#  define adler32               z_adler32
+#  define crc32                 z_crc32
+#  define get_crc_table         z_get_crc_table
+#  define zError                z_zError
+
+#  define alloc_func            z_alloc_func
+#  define free_func             z_free_func
+#  define in_func               z_in_func
+#  define out_func              z_out_func
+#  define Byte                  z_Byte
+#  define uInt                  z_uInt
+#  define uLong                 z_uLong
+#  define Bytef                 z_Bytef
+#  define charf                 z_charf
+#  define intf                  z_intf
+#  define uIntf                 z_uIntf
+#  define uLongf                z_uLongf
+#  define voidpf                z_voidpf
+#  define voidp                 z_voidp
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+#  define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+#  define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+#  define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+#  ifndef WIN32
+#    define WIN32
+#  endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+#  if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+#    ifndef SYS16BIT
+#      define SYS16BIT
+#    endif
+#  endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+#  define MAXSEG_64K
+#endif
+#ifdef MSDOS
+#  define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+#  ifndef STDC
+#    define STDC
+#  endif
+#  if __STDC_VERSION__ >= 199901L
+#    ifndef STDC99
+#      define STDC99
+#    endif
+#  endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+#  define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC)    /* iSeries (formerly AS/400). */
+#  define STDC
+#endif
+
+#ifndef STDC
+#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+#    define const       /* note: need a more gentle solution here */
+#  endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
+#  define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+#  ifdef MAXSEG_64K
+#    define MAX_MEM_LEVEL 8
+#  else
+#    define MAX_MEM_LEVEL 9
+#  endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+#  define MAX_WBITS   15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+            (1 << (windowBits+2)) +  (1 << (memLevel+9))
+ that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+   The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+                        /* Type declarations */
+
+#ifndef OF /* function prototypes */
+#  ifdef STDC
+#    define OF(args)  args
+#  else
+#    define OF(args)  ()
+#  endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+#  if defined(M_I86SM) || defined(M_I86MM)
+     /* MSC small or medium model */
+#    define SMALL_MEDIUM
+#    ifdef _MSC_VER
+#      define FAR _far
+#    else
+#      define FAR far
+#    endif
+#  endif
+#  if (defined(__SMALL__) || defined(__MEDIUM__))
+     /* Turbo C small or medium model */
+#    define SMALL_MEDIUM
+#    ifdef __BORLANDC__
+#      define FAR _far
+#    else
+#      define FAR far
+#    endif
+#  endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+   /* If building or using zlib as a DLL, define ZLIB_DLL.
+    * This is not mandatory, but it offers a little performance increase.
+    */
+#  ifdef ZLIB_DLL
+#    if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+#      ifdef ZLIB_INTERNAL
+#        define ZEXTERN extern __declspec(dllexport)
+#      else
+#        define ZEXTERN extern __declspec(dllimport)
+#      endif
+#    endif
+#  endif  /* ZLIB_DLL */
+   /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+    * define ZLIB_WINAPI.
+    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+    */
+#  ifdef ZLIB_WINAPI
+#    ifdef FAR
+#      undef FAR
+#    endif
+#    include <windows.h>
+     /* No need for _export, use ZLIB.DEF instead. */
+     /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+#    define ZEXPORT WINAPI
+#    ifdef WIN32
+#      define ZEXPORTVA WINAPIV
+#    else
+#      define ZEXPORTVA FAR CDECL
+#    endif
+#  endif
+#endif
+
+#if defined (__BEOS__)
+#  ifdef ZLIB_DLL
+#    ifdef ZLIB_INTERNAL
+#      define ZEXPORT   __declspec(dllexport)
+#      define ZEXPORTVA __declspec(dllexport)
+#    else
+#      define ZEXPORT   __declspec(dllimport)
+#      define ZEXPORTVA __declspec(dllimport)
+#    endif
+#  endif
+#endif
+
+#ifndef ZEXTERN
+#  define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+#  define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+#  define ZEXPORTVA
+#endif
+
+#ifndef FAR
+#  define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char  Byte;  /* 8 bits */
+#endif
+typedef unsigned int   uInt;  /* 16 bits or more */
+typedef unsigned long  uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+#  define Bytef Byte FAR
+#else
+   typedef Byte  FAR Bytef;
+#endif
+typedef char  FAR charf;
+typedef int   FAR intf;
+typedef uInt  FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+   typedef void const *voidpc;
+   typedef void FAR   *voidpf;
+   typedef void       *voidp;
+#else
+   typedef Byte const *voidpc;
+   typedef Byte FAR   *voidpf;
+   typedef Byte       *voidp;
+#endif
+
+#if 0           /* HAVE_UNISTD_H -- this line is updated by ./configure */
+/* under construction !*/
+/* under construction !*/
+#  ifdef VMS
+/* under construction !*/
+#  endif
+/* under construction !*/
+#endif
+#ifndef SEEK_SET
+#  define SEEK_SET        0       /* Seek from beginning of file.  */
+#  define SEEK_CUR        1       /* Seek from current position.  */
+#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
+#endif
+#ifndef z_off_t
+#  define z_off_t long
+#endif
+
+#if defined(__OS400__)
+#  define NO_vsnprintf
+#endif
+
+#if defined(__MVS__)
+#  define NO_vsnprintf
+#  ifdef FAR
+#    undef FAR
+#  endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+#   pragma map(deflateInit_,"DEIN")
+#   pragma map(deflateInit2_,"DEIN2")
+#   pragma map(deflateEnd,"DEEND")
+#   pragma map(deflateBound,"DEBND")
+#   pragma map(inflateInit_,"ININ")
+#   pragma map(inflateInit2_,"ININ2")
+#   pragma map(inflateEnd,"INEND")
+#   pragma map(inflateSync,"INSY")
+#   pragma map(inflateSetDictionary,"INSEDI")
+#   pragma map(compressBound,"CMBND")
+#   pragma map(inflate_table,"INTABL")
+#   pragma map(inflate_fast,"INFA")
+#   pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
diff --git a/mcu/tools/NVRAMStatistic/include/zconf.in.h b/mcu/tools/NVRAMStatistic/include/zconf.in.h
new file mode 100644
index 0000000..cdfb823
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/include/zconf.in.h
@@ -0,0 +1,332 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+#ifdef Z_PREFIX
+#  define deflateInit_          z_deflateInit_
+#  define deflate               z_deflate
+#  define deflateEnd            z_deflateEnd
+#  define inflateInit_          z_inflateInit_
+#  define inflate               z_inflate
+#  define inflateEnd            z_inflateEnd
+#  define deflateInit2_         z_deflateInit2_
+#  define deflateSetDictionary  z_deflateSetDictionary
+#  define deflateCopy           z_deflateCopy
+#  define deflateReset          z_deflateReset
+#  define deflateParams         z_deflateParams
+#  define deflateBound          z_deflateBound
+#  define deflatePrime          z_deflatePrime
+#  define inflateInit2_         z_inflateInit2_
+#  define inflateSetDictionary  z_inflateSetDictionary
+#  define inflateSync           z_inflateSync
+#  define inflateSyncPoint      z_inflateSyncPoint
+#  define inflateCopy           z_inflateCopy
+#  define inflateReset          z_inflateReset
+#  define inflateBack           z_inflateBack
+#  define inflateBackEnd        z_inflateBackEnd
+#  define compress              z_compress
+#  define compress2             z_compress2
+#  define compressBound         z_compressBound
+#  define uncompress            z_uncompress
+#  define adler32               z_adler32
+#  define crc32                 z_crc32
+#  define get_crc_table         z_get_crc_table
+#  define zError                z_zError
+
+#  define alloc_func            z_alloc_func
+#  define free_func             z_free_func
+#  define in_func               z_in_func
+#  define out_func              z_out_func
+#  define Byte                  z_Byte
+#  define uInt                  z_uInt
+#  define uLong                 z_uLong
+#  define Bytef                 z_Bytef
+#  define charf                 z_charf
+#  define intf                  z_intf
+#  define uIntf                 z_uIntf
+#  define uLongf                z_uLongf
+#  define voidpf                z_voidpf
+#  define voidp                 z_voidp
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+#  define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+#  define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+#  define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+#  ifndef WIN32
+#    define WIN32
+#  endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+#  if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+#    ifndef SYS16BIT
+#      define SYS16BIT
+#    endif
+#  endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+#  define MAXSEG_64K
+#endif
+#ifdef MSDOS
+#  define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+#  ifndef STDC
+#    define STDC
+#  endif
+#  if __STDC_VERSION__ >= 199901L
+#    ifndef STDC99
+#      define STDC99
+#    endif
+#  endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+#  define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC)    /* iSeries (formerly AS/400). */
+#  define STDC
+#endif
+
+#ifndef STDC
+#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+#    define const       /* note: need a more gentle solution here */
+#  endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
+#  define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+#  ifdef MAXSEG_64K
+#    define MAX_MEM_LEVEL 8
+#  else
+#    define MAX_MEM_LEVEL 9
+#  endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+#  define MAX_WBITS   15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+            (1 << (windowBits+2)) +  (1 << (memLevel+9))
+ that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+   The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+                        /* Type declarations */
+
+#ifndef OF /* function prototypes */
+#  ifdef STDC
+#    define OF(args)  args
+#  else
+#    define OF(args)  ()
+#  endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+#  if defined(M_I86SM) || defined(M_I86MM)
+     /* MSC small or medium model */
+#    define SMALL_MEDIUM
+#    ifdef _MSC_VER
+#      define FAR _far
+#    else
+#      define FAR far
+#    endif
+#  endif
+#  if (defined(__SMALL__) || defined(__MEDIUM__))
+     /* Turbo C small or medium model */
+#    define SMALL_MEDIUM
+#    ifdef __BORLANDC__
+#      define FAR _far
+#    else
+#      define FAR far
+#    endif
+#  endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+   /* If building or using zlib as a DLL, define ZLIB_DLL.
+    * This is not mandatory, but it offers a little performance increase.
+    */
+#  ifdef ZLIB_DLL
+#    if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+#      ifdef ZLIB_INTERNAL
+#        define ZEXTERN extern __declspec(dllexport)
+#      else
+#        define ZEXTERN extern __declspec(dllimport)
+#      endif
+#    endif
+#  endif  /* ZLIB_DLL */
+   /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+    * define ZLIB_WINAPI.
+    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+    */
+#  ifdef ZLIB_WINAPI
+#    ifdef FAR
+#      undef FAR
+#    endif
+#    include <windows.h>
+     /* No need for _export, use ZLIB.DEF instead. */
+     /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+#    define ZEXPORT WINAPI
+#    ifdef WIN32
+#      define ZEXPORTVA WINAPIV
+#    else
+#      define ZEXPORTVA FAR CDECL
+#    endif
+#  endif
+#endif
+
+#if defined (__BEOS__)
+#  ifdef ZLIB_DLL
+#    ifdef ZLIB_INTERNAL
+#      define ZEXPORT   __declspec(dllexport)
+#      define ZEXPORTVA __declspec(dllexport)
+#    else
+#      define ZEXPORT   __declspec(dllimport)
+#      define ZEXPORTVA __declspec(dllimport)
+#    endif
+#  endif
+#endif
+
+#ifndef ZEXTERN
+#  define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+#  define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+#  define ZEXPORTVA
+#endif
+
+#ifndef FAR
+#  define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char  Byte;  /* 8 bits */
+#endif
+typedef unsigned int   uInt;  /* 16 bits or more */
+typedef unsigned long  uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+#  define Bytef Byte FAR
+#else
+   typedef Byte  FAR Bytef;
+#endif
+typedef char  FAR charf;
+typedef int   FAR intf;
+typedef uInt  FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+   typedef void const *voidpc;
+   typedef void FAR   *voidpf;
+   typedef void       *voidp;
+#else
+   typedef Byte const *voidpc;
+   typedef Byte FAR   *voidpf;
+   typedef Byte       *voidp;
+#endif
+
+#if 0           /* HAVE_UNISTD_H -- this line is updated by ./configure */
+/* under construction !*/
+/* under construction !*/
+#  ifdef VMS
+/* under construction !*/
+#  endif
+/* under construction !*/
+#endif
+#ifndef SEEK_SET
+#  define SEEK_SET        0       /* Seek from beginning of file.  */
+#  define SEEK_CUR        1       /* Seek from current position.  */
+#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
+#endif
+#ifndef z_off_t
+#  define z_off_t long
+#endif
+
+#if defined(__OS400__)
+#  define NO_vsnprintf
+#endif
+
+#if defined(__MVS__)
+#  define NO_vsnprintf
+#  ifdef FAR
+#    undef FAR
+#  endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+#   pragma map(deflateInit_,"DEIN")
+#   pragma map(deflateInit2_,"DEIN2")
+#   pragma map(deflateEnd,"DEEND")
+#   pragma map(deflateBound,"DEBND")
+#   pragma map(inflateInit_,"ININ")
+#   pragma map(inflateInit2_,"ININ2")
+#   pragma map(inflateEnd,"INEND")
+#   pragma map(inflateSync,"INSY")
+#   pragma map(inflateSetDictionary,"INSEDI")
+#   pragma map(compressBound,"CMBND")
+#   pragma map(inflate_table,"INTABL")
+#   pragma map(inflate_fast,"INFA")
+#   pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
diff --git a/mcu/tools/NVRAMStatistic/include/zlib.h b/mcu/tools/NVRAMStatistic/include/zlib.h
new file mode 100644
index 0000000..5e19161
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/include/zlib.h
@@ -0,0 +1,1361 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+  version 1.2.3, July 18th, 2005
+
+  Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  jloup@gzip.org          madler@alumni.caltech.edu
+
+
+  The data format used by the zlib library is described by RFCs (Request for
+  Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt
+  (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+#ifndef ZLIB_H
+#define ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.2.3"
+#define ZLIB_VERNUM 0x1230
+
+/*
+     The 'zlib' compression library provides in-memory compression and
+  decompression functions, including integrity checks of the uncompressed
+  data.  This version of the library supports only one compression method
+  (deflation) but other algorithms will be added later and will have the same
+  stream interface.
+
+     Compression can be done in a single step if the buffers are large
+  enough (for example if an input file is mmap'ed), or can be done by
+  repeated calls of the compression function.  In the latter case, the
+  application must provide more input and/or consume the output
+  (providing more output space) before each call.
+
+     The compressed data format used by default by the in-memory functions is
+  the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+  around a deflate stream, which is itself documented in RFC 1951.
+
+     The library also supports reading and writing files in gzip (.gz) format
+  with an interface similar to that of stdio using the functions that start
+  with "gz".  The gzip format is different from the zlib format.  gzip is a
+  gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+     This library can optionally read and write gzip streams in memory as well.
+
+     The zlib format was designed to be compact and fast for use in memory
+  and on communications channels.  The gzip format was designed for single-
+  file compression on file systems, has a larger header than zlib to maintain
+  directory information, and uses a different, slower check method than zlib.
+
+     The library does not install any signal handler. The decoder checks
+  the consistency of the compressed data, so the library should never
+  crash even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void   (*free_func)  OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+    Bytef    *next_in;  /* next input byte */
+    uInt     avail_in;  /* number of bytes available at next_in */
+    uLong    total_in;  /* total nb of input bytes read so far */
+
+    Bytef    *next_out; /* next output byte should be put there */
+    uInt     avail_out; /* remaining free space at next_out */
+    uLong    total_out; /* total nb of bytes output so far */
+
+    char     *msg;      /* last error message, NULL if no error */
+    struct internal_state FAR *state; /* not visible by applications */
+
+    alloc_func zalloc;  /* used to allocate the internal state */
+    free_func  zfree;   /* used to free the internal state */
+    voidpf     opaque;  /* private data object passed to zalloc and zfree */
+
+    int     data_type;  /* best guess about the data type: binary or text */
+    uLong   adler;      /* adler32 value of the uncompressed data */
+    uLong   reserved;   /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+     gzip header information passed to and from zlib routines.  See RFC 1952
+  for more details on the meanings of these fields.
+*/
+typedef struct gz_header_s {
+    int     text;       /* true if compressed data believed to be text */
+    uLong   time;       /* modification time */
+    int     xflags;     /* extra flags (not used when writing a gzip file) */
+    int     os;         /* operating system */
+    Bytef   *extra;     /* pointer to extra field or Z_NULL if none */
+    uInt    extra_len;  /* extra field length (valid if extra != Z_NULL) */
+    uInt    extra_max;  /* space at extra (only when reading header) */
+    Bytef   *name;      /* pointer to zero-terminated file name or Z_NULL */
+    uInt    name_max;   /* space at name (only when reading header) */
+    Bytef   *comment;   /* pointer to zero-terminated comment or Z_NULL */
+    uInt    comm_max;   /* space at comment (only when reading header) */
+    int     hcrc;       /* true if there was or will be a header crc */
+    int     done;       /* true when done reading gzip header (not used
+                           when writing a gzip file) */
+} gz_header;
+
+typedef gz_header FAR *gz_headerp;
+
+/*
+   The application must update next_in and avail_in when avail_in has
+   dropped to zero. It must update next_out and avail_out when avail_out
+   has dropped to zero. The application must initialize zalloc, zfree and
+   opaque before calling the init function. All other fields are set by the
+   compression library and must not be updated by the application.
+
+   The opaque value provided by the application will be passed as the first
+   parameter for calls of zalloc and zfree. This can be useful for custom
+   memory management. The compression library attaches no meaning to the
+   opaque value.
+
+   zalloc must return Z_NULL if there is not enough memory for the object.
+   If zlib is used in a multi-threaded application, zalloc and zfree must be
+   thread safe.
+
+   On 16-bit systems, the functions zalloc and zfree must be able to allocate
+   exactly 65536 bytes, but will not be required to allocate more than this
+   if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+   pointers returned by zalloc for objects of exactly 65536 bytes *must*
+   have their offset normalized to zero. The default allocation function
+   provided by this library ensures this (see zutil.c). To reduce memory
+   requirements and avoid any allocation of 64K objects, at the expense of
+   compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+   The fields total_in and total_out can be used for statistics or
+   progress reports. After compression, total_in holds the total size of
+   the uncompressed data and may be saved for use in the decompressor
+   (particularly if the decompressor wants to decompress everything in
+   a single step).
+*/
+
+                        /* constants */
+
+#define Z_NO_FLUSH      0
+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_SYNC_FLUSH    2
+#define Z_FULL_FLUSH    3
+#define Z_FINISH        4
+#define Z_BLOCK         5
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+#define Z_OK            0
+#define Z_STREAM_END    1
+#define Z_NEED_DICT     2
+#define Z_ERRNO        (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR   (-3)
+#define Z_MEM_ERROR    (-4)
+#define Z_BUF_ERROR    (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION         0
+#define Z_BEST_SPEED             1
+#define Z_BEST_COMPRESSION       9
+#define Z_DEFAULT_COMPRESSION  (-1)
+/* compression levels */
+
+#define Z_FILTERED            1
+#define Z_HUFFMAN_ONLY        2
+#define Z_RLE                 3
+#define Z_FIXED               4
+#define Z_DEFAULT_STRATEGY    0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY   0
+#define Z_TEXT     1
+#define Z_ASCII    Z_TEXT   /* for compatibility with 1.2.2 and earlier */
+#define Z_UNKNOWN  2
+/* Possible values of the data_type field (though see inflate()) */
+
+#define Z_DEFLATED   8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+                        /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+   If the first character differs, the library code actually used is
+   not compatible with the zlib.h header file used by the application.
+   This check is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+     Initializes the internal stream state for compression. The fields
+   zalloc, zfree and opaque must be initialized before by the caller.
+   If zalloc and zfree are set to Z_NULL, deflateInit updates them to
+   use default allocation functions.
+
+     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+   1 gives best speed, 9 gives best compression, 0 gives no compression at
+   all (the input data is simply copied a block at a time).
+   Z_DEFAULT_COMPRESSION requests a default compromise between speed and
+   compression (currently equivalent to level 6).
+
+     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+   with the version assumed by the caller (ZLIB_VERSION).
+   msg is set to null if there is no error message.  deflateInit does not
+   perform any compression: this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+    deflate compresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full. It may introduce some
+  output latency (reading input without producing any output) except when
+  forced to flush.
+
+    The detailed semantics are as follows. deflate performs one or both of the
+  following actions:
+
+  - Compress more input starting at next_in and update next_in and avail_in
+    accordingly. If not all input can be processed (because there is not
+    enough room in the output buffer), next_in and avail_in are updated and
+    processing will resume at this point for the next call of deflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly. This action is forced if the parameter flush is non zero.
+    Forcing flush frequently degrades the compression ratio, so this parameter
+    should be set only when necessary (in interactive applications).
+    Some output may be provided even if flush is not set.
+
+  Before the call of deflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming
+  more output, and updating avail_in or avail_out accordingly; avail_out
+  should never be zero before the call. The application can consume the
+  compressed output when it wants, for example when the output buffer is full
+  (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
+  and with zero avail_out, it must be called again after making room in the
+  output buffer because there might be more output pending.
+
+    Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
+  decide how much data to accumualte before producing output, in order to
+  maximize compression.
+
+    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+  flushed to the output buffer and the output is aligned on a byte boundary, so
+  that the decompressor can get all input data available so far. (In particular
+  avail_in is zero after the call if enough output space has been provided
+  before the call.)  Flushing may degrade compression for some compression
+  algorithms and so it should be used only when necessary.
+
+    If flush is set to Z_FULL_FLUSH, all output is flushed as with
+  Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+  restart from this point if previous compressed data has been damaged or if
+  random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+  compression.
+
+    If deflate returns with avail_out == 0, this function must be called again
+  with the same value of the flush parameter and more output space (updated
+  avail_out), until the flush is complete (deflate returns with non-zero
+  avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
+  avail_out is greater than six to avoid repeated flush markers due to
+  avail_out == 0 on return.
+
+    If the parameter flush is set to Z_FINISH, pending input is processed,
+  pending output is flushed and deflate returns with Z_STREAM_END if there
+  was enough output space; if deflate returns with Z_OK, this function must be
+  called again with Z_FINISH and more output space (updated avail_out) but no
+  more input data, until it returns with Z_STREAM_END or an error. After
+  deflate has returned Z_STREAM_END, the only possible operations on the
+  stream are deflateReset or deflateEnd.
+
+    Z_FINISH can be used immediately after deflateInit if all the compression
+  is to be done in a single step. In this case, avail_out must be at least
+  the value returned by deflateBound (see below). If deflate does not return
+  Z_STREAM_END, then it must be called again as described above.
+
+    deflate() sets strm->adler to the adler32 checksum of all input read
+  so far (that is, total_in bytes).
+
+    deflate() may update strm->data_type if it can make a good guess about
+  the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered
+  binary. This field is only for information purposes and does not affect
+  the compression algorithm in any manner.
+
+    deflate() returns Z_OK if some progress has been made (more input
+  processed or more output produced), Z_STREAM_END if all input has been
+  consumed and all output has been produced (only when flush is set to
+  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+  if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
+  (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not
+  fatal, and deflate() can be called again with more input and more output
+  space to continue compressing.
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any
+   pending output.
+
+     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+   stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+   prematurely (some input or output was discarded). In the error case,
+   msg may be set but then points to a static string (which must not be
+   deallocated).
+*/
+
+
+/*
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+     Initializes the internal stream state for decompression. The fields
+   next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+   the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
+   value depends on the compression method), inflateInit determines the
+   compression method from the zlib header and allocates all data structures
+   accordingly; otherwise the allocation will be deferred to the first call of
+   inflate.  If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+   use default allocation functions.
+
+     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+   version assumed by the caller.  msg is set to null if there is no error
+   message. inflateInit does not perform any decompression apart from reading
+   the zlib header if present: this will be done by inflate().  (So next_in and
+   avail_in may be modified, but next_out and avail_out are unchanged.)
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+    inflate decompresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full. It may introduce
+  some output latency (reading input without producing any output) except when
+  forced to flush.
+
+  The detailed semantics are as follows. inflate performs one or both of the
+  following actions:
+
+  - Decompress more input starting at next_in and update next_in and avail_in
+    accordingly. If not all input can be processed (because there is not
+    enough room in the output buffer), next_in is updated and processing
+    will resume at this point for the next call of inflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly.  inflate() provides as much output as possible, until there
+    is no more input data or no more space in the output buffer (see below
+    about the flush parameter).
+
+  Before the call of inflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming
+  more output, and updating the next_* and avail_* values accordingly.
+  The application can consume the uncompressed output when it wants, for
+  example when the output buffer is full (avail_out == 0), or after each
+  call of inflate(). If inflate returns Z_OK and with zero avail_out, it
+  must be called again after making room in the output buffer because there
+  might be more output pending.
+
+    The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH,
+  Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much
+  output as possible to the output buffer. Z_BLOCK requests that inflate() stop
+  if and when it gets to the next deflate block boundary. When decoding the
+  zlib or gzip format, this will cause inflate() to return immediately after
+  the header and before the first block. When doing a raw inflate, inflate()
+  will go ahead and process the first block, and will return when it gets to
+  the end of that block, or when it runs out of data.
+
+    The Z_BLOCK option assists in appending to or combining deflate streams.
+  Also to assist in this, on return inflate() will set strm->data_type to the
+  number of unused bits in the last byte taken from strm->next_in, plus 64
+  if inflate() is currently decoding the last block in the deflate stream,
+  plus 128 if inflate() returned immediately after decoding an end-of-block
+  code or decoding the complete header up to just before the first byte of the
+  deflate stream. The end-of-block will not be indicated until all of the
+  uncompressed data from that block has been written to strm->next_out.  The
+  number of unused bits may in general be greater than seven, except when
+  bit 7 of data_type is set, in which case the number of unused bits will be
+  less than eight.
+
+    inflate() should normally be called until it returns Z_STREAM_END or an
+  error. However if all decompression is to be performed in a single step
+  (a single call of inflate), the parameter flush should be set to
+  Z_FINISH. In this case all pending input is processed and all pending
+  output is flushed; avail_out must be large enough to hold all the
+  uncompressed data. (The size of the uncompressed data may have been saved
+  by the compressor for this purpose.) The next operation on this stream must
+  be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+  is never required, but can be used to inform inflate that a faster approach
+  may be used for the single inflate() call.
+
+     In this implementation, inflate() always flushes as much output as
+  possible to the output buffer, and always uses the faster approach on the
+  first call. So the only effect of the flush parameter in this implementation
+  is on the return value of inflate(), as noted below, or when it returns early
+  because Z_BLOCK is used.
+
+     If a preset dictionary is needed after this call (see inflateSetDictionary
+  below), inflate sets strm->adler to the adler32 checksum of the dictionary
+  chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
+  strm->adler to the adler32 checksum of all output produced so far (that is,
+  total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
+  below. At the end of the stream, inflate() checks that its computed adler32
+  checksum is equal to that saved by the compressor and returns Z_STREAM_END
+  only if the checksum is correct.
+
+    inflate() will decompress and check either zlib-wrapped or gzip-wrapped
+  deflate data.  The header type is detected automatically.  Any information
+  contained in the gzip header is not retained, so applications that need that
+  information should instead use raw inflate, see inflateInit2() below, or
+  inflateBack() and perform their own processing of the gzip header and
+  trailer.
+
+    inflate() returns Z_OK if some progress has been made (more input processed
+  or more output produced), Z_STREAM_END if the end of the compressed data has
+  been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+  corrupted (input stream not conforming to the zlib format or incorrect check
+  value), Z_STREAM_ERROR if the stream structure was inconsistent (for example
+  if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory,
+  Z_BUF_ERROR if no progress is possible or if there was not enough room in the
+  output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and
+  inflate() can be called again with more input and more output space to
+  continue decompressing. If Z_DATA_ERROR is returned, the application may then
+  call inflateSync() to look for a good compression block if a partial recovery
+  of the data is desired.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any
+   pending output.
+
+     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+   was inconsistent. In the error case, msg may be set but then points to a
+   static string (which must not be deallocated).
+*/
+
+                        /* Advanced functions */
+
+/*
+    The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+                                     int  level,
+                                     int  method,
+                                     int  windowBits,
+                                     int  memLevel,
+                                     int  strategy));
+
+     This is another version of deflateInit with more compression options. The
+   fields next_in, zalloc, zfree and opaque must be initialized before by
+   the caller.
+
+     The method parameter is the compression method. It must be Z_DEFLATED in
+   this version of the library.
+
+     The windowBits parameter is the base two logarithm of the window size
+   (the size of the history buffer). It should be in the range 8..15 for this
+   version of the library. Larger values of this parameter result in better
+   compression at the expense of memory usage. The default value is 15 if
+   deflateInit is used instead.
+
+     windowBits can also be -8..-15 for raw deflate. In this case, -windowBits
+   determines the window size. deflate() will then generate raw deflate data
+   with no zlib header or trailer, and will not compute an adler32 check value.
+
+     windowBits can also be greater than 15 for optional gzip encoding. Add
+   16 to windowBits to write a simple gzip header and trailer around the
+   compressed data instead of a zlib wrapper. The gzip header will have no
+   file name, no extra data, no comment, no modification time (set to zero),
+   no header crc, and the operating system will be set to 255 (unknown).  If a
+   gzip stream is being written, strm->adler is a crc32 instead of an adler32.
+
+     The memLevel parameter specifies how much memory should be allocated
+   for the internal compression state. memLevel=1 uses minimum memory but
+   is slow and reduces compression ratio; memLevel=9 uses maximum memory
+   for optimal speed. The default value is 8. See zconf.h for total memory
+   usage as a function of windowBits and memLevel.
+
+     The strategy parameter is used to tune the compression algorithm. Use the
+   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+   filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
+   string match), or Z_RLE to limit match distances to one (run-length
+   encoding). Filtered data consists mostly of small values with a somewhat
+   random distribution. In this case, the compression algorithm is tuned to
+   compress them better. The effect of Z_FILTERED is to force more Huffman
+   coding and less string matching; it is somewhat intermediate between
+   Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as
+   Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy
+   parameter only affects the compression ratio but not the correctness of the
+   compressed output even if it is not set appropriately.  Z_FIXED prevents the
+   use of dynamic Huffman codes, allowing for a simpler decoder for special
+   applications.
+
+      deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
+   method). msg is set to null if there is no error message.  deflateInit2 does
+   not perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the compression dictionary from the given byte sequence
+   without producing any compressed output. This function must be called
+   immediately after deflateInit, deflateInit2 or deflateReset, before any
+   call of deflate. The compressor and decompressor must use exactly the same
+   dictionary (see inflateSetDictionary).
+
+     The dictionary should consist of strings (byte sequences) that are likely
+   to be encountered later in the data to be compressed, with the most commonly
+   used strings preferably put towards the end of the dictionary. Using a
+   dictionary is most useful when the data to be compressed is short and can be
+   predicted with good accuracy; the data can then be compressed better than
+   with the default empty dictionary.
+
+     Depending on the size of the compression data structures selected by
+   deflateInit or deflateInit2, a part of the dictionary may in effect be
+   discarded, for example if the dictionary is larger than the window size in
+   deflate or deflate2. Thus the strings most likely to be useful should be
+   put at the end of the dictionary, not at the front. In addition, the
+   current implementation of deflate will use at most the window size minus
+   262 bytes of the provided dictionary.
+
+     Upon return of this function, strm->adler is set to the adler32 value
+   of the dictionary; the decompressor may later use this value to determine
+   which dictionary has been used by the compressor. (The adler32 value
+   applies to the whole dictionary even if only a subset of the dictionary is
+   actually used by the compressor.) If a raw deflate was requested, then the
+   adler32 value is not computed and strm->adler is not set.
+
+     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+   parameter is invalid (such as NULL dictionary) or the stream state is
+   inconsistent (for example if deflate has already been called for this stream
+   or if the compression method is bsort). deflateSetDictionary does not
+   perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+                                    z_streamp source));
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when several compression strategies will be
+   tried, for example when there are several ways of pre-processing the input
+   data with a filter. The streams that will be discarded should then be freed
+   by calling deflateEnd.  Note that deflateCopy duplicates the internal
+   compression state which can be quite large, so this strategy is slow and
+   can consume lots of memory.
+
+     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being NULL). msg is left unchanged in both source and
+   destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to deflateEnd followed by deflateInit,
+   but does not free and reallocate all the internal compression state.
+   The stream will keep the same compression level and any other attributes
+   that may have been set by deflateInit2.
+
+      deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+                                      int level,
+                                      int strategy));
+/*
+     Dynamically update the compression level and compression strategy.  The
+   interpretation of level and strategy is as in deflateInit2.  This can be
+   used to switch between compression and straight copy of the input data, or
+   to switch to a different kind of input data requiring a different
+   strategy. If the compression level is changed, the input available so far
+   is compressed with the old level (and may be flushed); the new level will
+   take effect only at the next call of deflate().
+
+     Before the call of deflateParams, the stream state must be set as for
+   a call of deflate(), since the currently available input may have to
+   be compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+     deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+   stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
+   if strm->avail_out was zero.
+*/
+
+ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
+                                    int good_length,
+                                    int max_lazy,
+                                    int nice_length,
+                                    int max_chain));
+/*
+     Fine tune deflate's internal compression parameters.  This should only be
+   used by someone who understands the algorithm used by zlib's deflate for
+   searching for the best matching string, and even then only by the most
+   fanatic optimizer trying to squeeze out the last compressed bit for their
+   specific input data.  Read the deflate.c source code for the meaning of the
+   max_lazy, good_length, nice_length, and max_chain parameters.
+
+     deflateTune() can be called after deflateInit() or deflateInit2(), and
+   returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
+ */
+
+ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
+                                       uLong sourceLen));
+/*
+     deflateBound() returns an upper bound on the compressed size after
+   deflation of sourceLen bytes.  It must be called after deflateInit()
+   or deflateInit2().  This would be used to allocate an output buffer
+   for deflation in a single pass, and so would be called before deflate().
+*/
+
+ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
+                                     int bits,
+                                     int value));
+/*
+     deflatePrime() inserts bits in the deflate output stream.  The intent
+  is that this function is used to start off the deflate output with the
+  bits leftover from a previous deflate stream when appending to it.  As such,
+  this function can only be used for raw deflate, and must be used before the
+  first deflate() call after a deflateInit2() or deflateReset().  bits must be
+  less than or equal to 16, and that many of the least significant bits of
+  value will be inserted in the output.
+
+      deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
+                                         gz_headerp head));
+/*
+      deflateSetHeader() provides gzip header information for when a gzip
+   stream is requested by deflateInit2().  deflateSetHeader() may be called
+   after deflateInit2() or deflateReset() and before the first call of
+   deflate().  The text, time, os, extra field, name, and comment information
+   in the provided gz_header structure are written to the gzip header (xflag is
+   ignored -- the extra flags are set according to the compression level).  The
+   caller must assure that, if not Z_NULL, name and comment are terminated with
+   a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
+   available there.  If hcrc is true, a gzip header crc is included.  Note that
+   the current versions of the command-line version of gzip (up through version
+   1.3.x) do not support header crc's, and will report that it is a "multi-part
+   gzip file" and give up.
+
+      If deflateSetHeader is not used, the default gzip header has text false,
+   the time set to zero, and os set to 255, with no extra, name, or comment
+   fields.  The gzip header is returned to the default state by deflateReset().
+
+      deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+                                     int  windowBits));
+
+     This is another version of inflateInit with an extra parameter. The
+   fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+   before by the caller.
+
+     The windowBits parameter is the base two logarithm of the maximum window
+   size (the size of the history buffer).  It should be in the range 8..15 for
+   this version of the library. The default value is 15 if inflateInit is used
+   instead. windowBits must be greater than or equal to the windowBits value
+   provided to deflateInit2() while compressing, or it must be equal to 15 if
+   deflateInit2() was not used. If a compressed stream with a larger window
+   size is given as input, inflate() will return with the error code
+   Z_DATA_ERROR instead of trying to allocate a larger window.
+
+     windowBits can also be -8..-15 for raw inflate. In this case, -windowBits
+   determines the window size. inflate() will then process raw deflate data,
+   not looking for a zlib or gzip header, not generating a check value, and not
+   looking for any check values for comparison at the end of the stream. This
+   is for use with other formats that use the deflate compressed data format
+   such as zip.  Those formats provide their own check values. If a custom
+   format is developed using the raw deflate format for compressed data, it is
+   recommended that a check value such as an adler32 or a crc32 be applied to
+   the uncompressed data as is done in the zlib, gzip, and zip formats.  For
+   most applications, the zlib format should be used as is. Note that comments
+   above on the use in deflateInit2() applies to the magnitude of windowBits.
+
+     windowBits can also be greater than 15 for optional gzip decoding. Add
+   32 to windowBits to enable zlib and gzip decoding with automatic header
+   detection, or add 16 to decode only the gzip format (the zlib format will
+   return a Z_DATA_ERROR).  If a gzip stream is being decoded, strm->adler is
+   a crc32 instead of an adler32.
+
+     inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg
+   is set to null if there is no error message.  inflateInit2 does not perform
+   any decompression apart from reading the zlib header if present: this will
+   be done by inflate(). (So next_in and avail_in may be modified, but next_out
+   and avail_out are unchanged.)
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the decompression dictionary from the given uncompressed byte
+   sequence. This function must be called immediately after a call of inflate,
+   if that call returned Z_NEED_DICT. The dictionary chosen by the compressor
+   can be determined from the adler32 value returned by that call of inflate.
+   The compressor and decompressor must use exactly the same dictionary (see
+   deflateSetDictionary).  For raw inflate, this function can be called
+   immediately after inflateInit2() or inflateReset() and before any call of
+   inflate() to set the dictionary.  The application must insure that the
+   dictionary that was used for compression is provided.
+
+     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+   parameter is invalid (such as NULL dictionary) or the stream state is
+   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+   expected one (incorrect adler32 value). inflateSetDictionary does not
+   perform any decompression: this will be done by subsequent calls of
+   inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/*
+    Skips invalid compressed data until a full flush point (see above the
+  description of deflate with Z_FULL_FLUSH) can be found, or until all
+  available input is skipped. No output is provided.
+
+    inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
+  if no more input was provided, Z_DATA_ERROR if no flush point has been found,
+  or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+  case, the application may save the current current value of total_in which
+  indicates where valid compressed data was found. In the error case, the
+  application may repeatedly call inflateSync, providing more input each time,
+  until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
+                                    z_streamp source));
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when randomly accessing a large stream.  The
+   first pass through the stream can periodically record the inflate state,
+   allowing restarting inflate at those points when randomly accessing the
+   stream.
+
+     inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being NULL). msg is left unchanged in both source and
+   destination.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to inflateEnd followed by inflateInit,
+   but does not free and reallocate all the internal decompression state.
+   The stream will keep attributes that may have been set by inflateInit2.
+
+      inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
+                                     int bits,
+                                     int value));
+/*
+     This function inserts bits in the inflate input stream.  The intent is
+  that this function is used to start inflating at a bit position in the
+  middle of a byte.  The provided bits will be used before any bytes are used
+  from next_in.  This function should only be used with raw inflate, and
+  should be used before the first inflate() call after inflateInit2() or
+  inflateReset().  bits must be less than or equal to 16, and that many of the
+  least significant bits of value will be inserted in the input.
+
+      inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
+                                         gz_headerp head));
+/*
+      inflateGetHeader() requests that gzip header information be stored in the
+   provided gz_header structure.  inflateGetHeader() may be called after
+   inflateInit2() or inflateReset(), and before the first call of inflate().
+   As inflate() processes the gzip stream, head->done is zero until the header
+   is completed, at which time head->done is set to one.  If a zlib stream is
+   being decoded, then head->done is set to -1 to indicate that there will be
+   no gzip header information forthcoming.  Note that Z_BLOCK can be used to
+   force inflate() to return immediately after header processing is complete
+   and before any actual data is decompressed.
+
+      The text, time, xflags, and os fields are filled in with the gzip header
+   contents.  hcrc is set to true if there is a header CRC.  (The header CRC
+   was valid if done is set to one.)  If extra is not Z_NULL, then extra_max
+   contains the maximum number of bytes to write to extra.  Once done is true,
+   extra_len contains the actual extra field length, and extra contains the
+   extra field, or that field truncated if extra_max is less than extra_len.
+   If name is not Z_NULL, then up to name_max characters are written there,
+   terminated with a zero unless the length is greater than name_max.  If
+   comment is not Z_NULL, then up to comm_max characters are written there,
+   terminated with a zero unless the length is greater than comm_max.  When
+   any of extra, name, or comment are not Z_NULL and the respective field is
+   not present in the header, then that field is set to Z_NULL to signal its
+   absence.  This allows the use of deflateSetHeader() with the returned
+   structure to duplicate the header.  However if those fields are set to
+   allocated memory, then the application will need to save those pointers
+   elsewhere so that they can be eventually freed.
+
+      If inflateGetHeader is not used, then the header information is simply
+   discarded.  The header is always checked for validity, including the header
+   CRC if present.  inflateReset() will reset the process to discard the header
+   information.  The application would need to call inflateGetHeader() again to
+   retrieve the header from the next gzip stream.
+
+      inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
+                                        unsigned char FAR *window));
+
+     Initialize the internal stream state for decompression using inflateBack()
+   calls.  The fields zalloc, zfree and opaque in strm must be initialized
+   before the call.  If zalloc and zfree are Z_NULL, then the default library-
+   derived memory allocation routines are used.  windowBits is the base two
+   logarithm of the window size, in the range 8..15.  window is a caller
+   supplied buffer of that size.  Except for special applications where it is
+   assured that deflate was used with small window sizes, windowBits must be 15
+   and a 32K byte window must be supplied to be able to decompress general
+   deflate streams.
+
+     See inflateBack() for the usage of these routines.
+
+     inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
+   the paramaters are invalid, Z_MEM_ERROR if the internal state could not
+   be allocated, or Z_VERSION_ERROR if the version of the library does not
+   match the version of the header file.
+*/
+
+typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *));
+typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
+
+ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
+                                    in_func in, void FAR *in_desc,
+                                    out_func out, void FAR *out_desc));
+/*
+     inflateBack() does a raw inflate with a single call using a call-back
+   interface for input and output.  This is more efficient than inflate() for
+   file i/o applications in that it avoids copying between the output and the
+   sliding window by simply making the window itself the output buffer.  This
+   function trusts the application to not change the output buffer passed by
+   the output function, at least until inflateBack() returns.
+
+     inflateBackInit() must be called first to allocate the internal state
+   and to initialize the state with the user-provided window buffer.
+   inflateBack() may then be used multiple times to inflate a complete, raw
+   deflate stream with each call.  inflateBackEnd() is then called to free
+   the allocated state.
+
+     A raw deflate stream is one with no zlib or gzip header or trailer.
+   This routine would normally be used in a utility that reads zip or gzip
+   files and writes out uncompressed files.  The utility would decode the
+   header and process the trailer on its own, hence this routine expects
+   only the raw deflate stream to decompress.  This is different from the
+   normal behavior of inflate(), which expects either a zlib or gzip header and
+   trailer around the deflate stream.
+
+     inflateBack() uses two subroutines supplied by the caller that are then
+   called by inflateBack() for input and output.  inflateBack() calls those
+   routines until it reads a complete deflate stream and writes out all of the
+   uncompressed data, or until it encounters an error.  The function's
+   parameters and return types are defined above in the in_func and out_func
+   typedefs.  inflateBack() will call in(in_desc, &buf) which should return the
+   number of bytes of provided input, and a pointer to that input in buf.  If
+   there is no input available, in() must return zero--buf is ignored in that
+   case--and inflateBack() will return a buffer error.  inflateBack() will call
+   out(out_desc, buf, len) to write the uncompressed data buf[0..len-1].  out()
+   should return zero on success, or non-zero on failure.  If out() returns
+   non-zero, inflateBack() will return with an error.  Neither in() nor out()
+   are permitted to change the contents of the window provided to
+   inflateBackInit(), which is also the buffer that out() uses to write from.
+   The length written by out() will be at most the window size.  Any non-zero
+   amount of input may be provided by in().
+
+     For convenience, inflateBack() can be provided input on the first call by
+   setting strm->next_in and strm->avail_in.  If that input is exhausted, then
+   in() will be called.  Therefore strm->next_in must be initialized before
+   calling inflateBack().  If strm->next_in is Z_NULL, then in() will be called
+   immediately for input.  If strm->next_in is not Z_NULL, then strm->avail_in
+   must also be initialized, and then if strm->avail_in is not zero, input will
+   initially be taken from strm->next_in[0 .. strm->avail_in - 1].
+
+     The in_desc and out_desc parameters of inflateBack() is passed as the
+   first parameter of in() and out() respectively when they are called.  These
+   descriptors can be optionally used to pass any information that the caller-
+   supplied in() and out() functions need to do their job.
+
+     On return, inflateBack() will set strm->next_in and strm->avail_in to
+   pass back any unused input that was provided by the last in() call.  The
+   return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
+   if in() or out() returned an error, Z_DATA_ERROR if there was a format
+   error in the deflate stream (in which case strm->msg is set to indicate the
+   nature of the error), or Z_STREAM_ERROR if the stream was not properly
+   initialized.  In the case of Z_BUF_ERROR, an input or output error can be
+   distinguished using strm->next_in which will be Z_NULL only if in() returned
+   an error.  If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to
+   out() returning non-zero.  (in() will always be called before out(), so
+   strm->next_in is assured to be defined if out() returns non-zero.)  Note
+   that inflateBack() cannot return Z_OK.
+*/
+
+ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
+/*
+     All memory allocated by inflateBackInit() is freed.
+
+     inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
+   state was inconsistent.
+*/
+
+ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
+/* Return flags indicating compile-time options.
+
+    Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
+     1.0: size of uInt
+     3.2: size of uLong
+     5.4: size of voidpf (pointer)
+     7.6: size of z_off_t
+
+    Compiler, assembler, and debug options:
+     8: DEBUG
+     9: ASMV or ASMINF -- use ASM code
+     10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
+     11: 0 (reserved)
+
+    One-time table building (smaller code, but not thread-safe if true):
+     12: BUILDFIXED -- build static block decoding tables when needed
+     13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
+     14,15: 0 (reserved)
+
+    Library content (indicates missing functionality):
+     16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
+                          deflate code when not needed)
+     17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
+                    and decode gzip streams (to avoid linking crc code)
+     18-19: 0 (reserved)
+
+    Operation variations (changes in library functionality):
+     20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
+     21: FASTEST -- deflate algorithm with only one, lowest compression level
+     22,23: 0 (reserved)
+
+    The sprintf variant used by gzprintf (zero is best):
+     24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
+     25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
+     26: 0 = returns value, 1 = void -- 1 means inferred string length returned
+
+    Remainder:
+     27-31: 0 (reserved)
+ */
+
+
+                        /* utility functions */
+
+/*
+     The following utility functions are implemented on top of the
+   basic stream-oriented functions. To simplify the interface, some
+   default options are assumed (compression level and memory usage,
+   standard memory allocation functions). The source code of these
+   utility functions can easily be modified if you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,
+                                 const Bytef *source, uLong sourceLen));
+/*
+     Compresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be at least the value returned
+   by compressBound(sourceLen). Upon exit, destLen is the actual size of the
+   compressed buffer.
+     This function can be used to compress a whole file at once if the
+   input file is mmap'ed.
+     compress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,
+                                  const Bytef *source, uLong sourceLen,
+                                  int level));
+/*
+     Compresses the source buffer into the destination buffer. The level
+   parameter has the same meaning as in deflateInit.  sourceLen is the byte
+   length of the source buffer. Upon entry, destLen is the total size of the
+   destination buffer, which must be at least the value returned by
+   compressBound(sourceLen). Upon exit, destLen is the actual size of the
+   compressed buffer.
+
+     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+   Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
+/*
+     compressBound() returns an upper bound on the compressed size after
+   compress() or compress2() on sourceLen bytes.  It would be used before
+   a compress() or compress2() call to allocate the destination buffer.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,
+                                   const Bytef *source, uLong sourceLen));
+/*
+     Decompresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be large enough to hold the
+   entire uncompressed data. (The size of the uncompressed data must have
+   been saved previously by the compressor and transmitted to the decompressor
+   by some mechanism outside the scope of this compression library.)
+   Upon exit, destLen is the actual size of the compressed buffer.
+     This function can be used to decompress a whole file at once if the
+   input file is mmap'ed.
+
+     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.
+*/
+
+
+ZEXTERN int ZEXPORT uncompress_mtk OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, alloc_func gzalloc_func, free_func gzfree_func));
+
+
+
+typedef voidp gzFile;
+
+ZEXTERN gzFile ZEXPORT gzopen  OF((const char *path, const char *mode));
+/*
+     Opens a gzip (.gz) file for reading or writing. The mode parameter
+   is as in fopen ("rb" or "wb") but can also include a compression level
+   ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
+   Huffman only compression as in "wb1h", or 'R' for run-length encoding
+   as in "wb1R". (See the description of deflateInit2 for more information
+   about the strategy parameter.)
+
+     gzopen can be used to read a file which is not in gzip format; in this
+   case gzread will directly read from the file without decompression.
+
+     gzopen returns NULL if the file could not be opened or if there was
+   insufficient memory to allocate the (de)compression state; errno
+   can be checked to distinguish the two cases (if errno is zero, the
+   zlib error is Z_MEM_ERROR).  */
+
+ZEXTERN gzFile ZEXPORT gzdopen  OF((int fd, const char *mode));
+/*
+     gzdopen() associates a gzFile with the file descriptor fd.  File
+   descriptors are obtained from calls like open, dup, creat, pipe or
+   fileno (in the file has been previously opened with fopen).
+   The mode parameter is as in gzopen.
+     The next call of gzclose on the returned gzFile will also close the
+   file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+   descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
+     gzdopen returns NULL if there was insufficient memory to allocate
+   the (de)compression state.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+     Dynamically update the compression level or strategy. See the description
+   of deflateInit2 for the meaning of these parameters.
+     gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+   opened for writing.
+*/
+
+ZEXTERN int ZEXPORT    gzread  OF((gzFile file, voidp buf, unsigned len));
+/*
+     Reads the given number of uncompressed bytes from the compressed file.
+   If the input file was not in gzip format, gzread copies the given number
+   of bytes into the buffer.
+     gzread returns the number of uncompressed bytes actually read (0 for
+   end of file, -1 for error). */
+
+ZEXTERN int ZEXPORT    gzwrite OF((gzFile file,
+                                   voidpc buf, unsigned len));
+/*
+     Writes the given number of uncompressed bytes into the compressed file.
+   gzwrite returns the number of uncompressed bytes actually written
+   (0 in case of error).
+*/
+
+ZEXTERN int ZEXPORTVA   gzprintf OF((gzFile file, const char *format, ...));
+/*
+     Converts, formats, and writes the args to the compressed file under
+   control of the format string, as in fprintf. gzprintf returns the number of
+   uncompressed bytes actually written (0 in case of error).  The number of
+   uncompressed bytes written is limited to 4095. The caller should assure that
+   this limit is not exceeded. If it is exceeded, then gzprintf() will return
+   return an error (0) with nothing written. In this case, there may also be a
+   buffer overflow with unpredictable consequences, which is possible only if
+   zlib was compiled with the insecure functions sprintf() or vsprintf()
+   because the secure snprintf() or vsnprintf() functions were not available.
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+      Writes the given null-terminated string to the compressed file, excluding
+   the terminating null character.
+      gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+      Reads bytes from the compressed file until len-1 characters are read, or
+   a newline character is read and transferred to buf, or an end-of-file
+   condition is encountered.  The string is then terminated with a null
+   character.
+      gzgets returns buf, or Z_NULL in case of error.
+*/
+
+ZEXTERN int ZEXPORT    gzputc OF((gzFile file, int c));
+/*
+      Writes c, converted to an unsigned char, into the compressed file.
+   gzputc returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT    gzgetc OF((gzFile file));
+/*
+      Reads one byte from the compressed file. gzgetc returns this byte
+   or -1 in case of end of file or error.
+*/
+
+ZEXTERN int ZEXPORT    gzungetc OF((int c, gzFile file));
+/*
+      Push one character back onto the stream to be read again later.
+   Only one character of push-back is allowed.  gzungetc() returns the
+   character pushed, or -1 on failure.  gzungetc() will fail if a
+   character has been pushed but not read yet, or if c is -1. The pushed
+   character will be discarded if the stream is repositioned with gzseek()
+   or gzrewind().
+*/
+
+ZEXTERN int ZEXPORT    gzflush OF((gzFile file, int flush));
+/*
+     Flushes all pending output into the compressed file. The parameter
+   flush is as in the deflate() function. The return value is the zlib
+   error number (see function gzerror below). gzflush returns Z_OK if
+   the flush parameter is Z_FINISH and all output could be flushed.
+     gzflush should be called only when strictly necessary because it can
+   degrade compression.
+*/
+
+ZEXTERN z_off_t ZEXPORT    gzseek OF((gzFile file,
+                                      z_off_t offset, int whence));
+/*
+      Sets the starting position for the next gzread or gzwrite on the
+   given compressed file. The offset represents a number of bytes in the
+   uncompressed data stream. The whence parameter is defined as in lseek(2);
+   the value SEEK_END is not supported.
+     If the file is opened for reading, this function is emulated but can be
+   extremely slow. If the file is opened for writing, only forward seeks are
+   supported; gzseek then compresses a sequence of zeroes up to the new
+   starting position.
+
+      gzseek returns the resulting offset location as measured in bytes from
+   the beginning of the uncompressed stream, or -1 in case of error, in
+   particular if the file is opened for writing and the new starting position
+   would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT    gzrewind OF((gzFile file));
+/*
+     Rewinds the given file. This function is supported only for reading.
+
+   gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+ZEXTERN z_off_t ZEXPORT    gztell OF((gzFile file));
+/*
+     Returns the starting position for the next gzread or gzwrite on the
+   given compressed file. This position represents a number of bytes in the
+   uncompressed data stream.
+
+   gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+     Returns 1 when EOF has previously been detected reading the given
+   input stream, otherwise zero.
+*/
+
+ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
+/*
+     Returns 1 if file is being read directly without decompression, otherwise
+   zero.
+*/
+
+ZEXTERN int ZEXPORT    gzclose OF((gzFile file));
+/*
+     Flushes all pending output if necessary, closes the compressed file
+   and deallocates all the (de)compression state. The return value is the zlib
+   error number (see function gzerror below).
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+     Returns the error message for the last error which occurred on the
+   given compressed file. errnum is set to zlib error number. If an
+   error occurred in the file system and not in the compression library,
+   errnum is set to Z_ERRNO and the application may consult errno
+   to get the exact error code.
+*/
+
+ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
+/*
+     Clears the error and end-of-file flags for file. This is analogous to the
+   clearerr() function in stdio. This is useful for continuing to read a gzip
+   file that is being written concurrently.
+*/
+
+                        /* checksum functions */
+
+/*
+     These functions are not related to compression but are exported
+   anyway because they might be useful in applications using the
+   compression library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+/*
+     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+   return the updated checksum. If buf is NULL, this function returns
+   the required initial value for the checksum.
+   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+   much faster. Usage example:
+
+     uLong adler = adler32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       adler = adler32(adler, buffer, length);
+     }
+     if (adler != original_adler) error();
+*/
+
+ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
+                                          z_off_t len2));
+/*
+     Combine two Adler-32 checksums into one.  For two sequences of bytes, seq1
+   and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
+   each, adler1 and adler2.  adler32_combine() returns the Adler-32 checksum of
+   seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.
+*/
+
+ZEXTERN uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));
+/*
+     Update a running CRC-32 with the bytes buf[0..len-1] and return the
+   updated CRC-32. If buf is NULL, this function returns the required initial
+   value for the for the crc. Pre- and post-conditioning (one's complement) is
+   performed within this function so it shouldn't be done by the application.
+   Usage example:
+
+     uLong crc = crc32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       crc = crc32(crc, buffer, length);
+     }
+     if (crc != original_crc) error();
+*/
+
+ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
+
+/*
+     Combine two CRC-32 check values into one.  For two sequences of bytes,
+   seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
+   calculated for each, crc1 and crc2.  crc32_combine() returns the CRC-32
+   check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
+   len2.
+*/
+
+
+                        /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int  level, int  method,
+                                      int windowBits, int memLevel,
+                                      int strategy, const char *version,
+                                      int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,
+                                      const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
+                                         unsigned char FAR *window,
+                                         const char *version,
+                                         int stream_size));
+#define deflateInit(strm, level) \
+        deflateInit_((strm), (level),       ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit(strm) \
+        inflateInit_((strm),                ZLIB_VERSION, sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+        deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+                      (strategy),           ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+        inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+#define inflateBackInit(strm, windowBits, window) \
+        inflateBackInit_((strm), (windowBits), (window), \
+        ZLIB_VERSION, sizeof(z_stream))
+
+
+#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL)
+    struct internal_state {int dummy;}; /* hack for buggy compilers */
+#endif
+
+ZEXTERN const char   * ZEXPORT zError           OF((int));
+ZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp z));
+ZEXTERN const uLongf * ZEXPORT get_crc_table    OF((void));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZLIB_H */
diff --git a/mcu/tools/NVRAMStatistic/nvram_auto_gen.mak b/mcu/tools/NVRAMStatistic/nvram_auto_gen.mak
new file mode 100644
index 0000000..1f8e790
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_auto_gen.mak
@@ -0,0 +1,455 @@
+
+.PHONY: nvram_auto_gen_build 
+
+include make/common/cmd_cfg.mak
+
+ifneq ($(strip $(OS_VERSION)),MSWin32)
+include make/common/option.mak 
+else
+include $(strip $(PROJECT_MAKEFILE))
+endif
+
+ECHO := perl tools/init/echo.pl -n
+
+base_path := $(subst /./,/, $(NVRAM_AUTO_GEN_PATH))
+output_path := $(base_path)/debug
+
+bsp_dir := custom/driver/common
+modem_dir := custom/protocol/common/ps
+middleware_dir := custom/middleware/common
+nvram_dir := custom/service/nvram
+
+bsp_src := $(basename $(notdir $(wildcard $(bsp_dir)/*_nvram_def.c)))
+modem_src := $(basename $(notdir $(wildcard $(modem_dir)/*_nvram_def.c)))
+middleware_src := $(basename $(notdir $(wildcard $(middleware_dir)/*_nvram_def.c)))
+nvram_src := $(basename $(notdir $(wildcard $(nvram_dir)/*_nvram_def.c)))
+# nvram autogen v2 src path
+autogen_v2 := tools/NVRAMStatistic/autogen_v2
+
+include $(base_path)/include/custom_include.txt
+
+ifeq ($(strip $(OS_VERSION)),MSWin32)
+    CUSTOM_OPTION := -imacros $(base_path)/include/custom_option.txt
+    GCC := "tools/MinGW/bin/gcc.exe"
+    OBJDUMP := "echo"
+    LINKER_SCRIPT := tools/NVRAMStatistic/src/nvram_auto_gen_windows.txt
+    LINKER_SCRIPT_TARGET := tools/NVRAMStatistic/src/nvram_auto_gen_windows.txt
+    MV := perl tools/init/move.pl -f
+    override PATH := tools/MinGW/bin:${PATH}
+    export $(PATH)
+else
+include $(base_path)/include/custom_option.txt
+    GCC := "/usr/bin/gcc"
+    OBJDUMP := "/usr/bin/objdump"
+    LINKER_SCRIPT := tools/NVRAMStatistic/src/nvram_auto_gen_linux.txt
+    LINKER_SCRIPT_TARGET := tools/NVRAMStatistic/src/nvram_auto_gen_TARGET.txt
+    #NVM_TARGET_GEN_SRC := nvram_auto_gen_TARGET.o
+    MV := mv
+    CUSTOM_OPTION += -std=c11
+endif
+
+NVM_TARGET_GEN_SRC := nvram_auto_gen_TARGET.o
+
+bsp_obj := $(patsubst %, $(output_path)/%.o, $(bsp_src))
+modem_obj := $(patsubst %, $(output_path)/%.o, $(modem_src))
+middleware_obj := $(patsubst %, $(output_path)/%.o, $(middleware_src))
+nvram_obj := $(patsubst %, $(output_path)/%.o, $(nvram_src))
+
+NVM_CUST_SRC = \
+BSP_LIST \
+MODEM_LIST \
+MIDDLEWARE_LIST \
+NVRAM_LIST \
+nvram_data_items.o \
+nvram_cust_pack.o \
+custom_nvram_sec.o \
+nvram_white_list.o \
+nvram_gen_util.o
+
+ifeq ($(strip $(DEMO_PROJECT)),TRUE)
+NVM_CUST_SRC += \
+md5_dgst.o \
+nvram_hash_check.o
+endif
+ifeq ($(strip $(NVRAM_LID_CACHE)),TRUE)
+NVM_CUST_SRC += \
+nvram_gen_cache_table.o
+endif
+
+
+NVM_TARGET_CUST_SRC = \
+BSP_LIST \
+MODEM_LIST \
+MIDDLEWARE_LIST \
+NVRAM_LIST \
+nvram_data_items.o \
+nvram_cust_pack.o \
+custom_nvram_sec.o \
+nvram_white_list.o
+
+#Vendor only can compile these files
+NVM_VENDOR_SRC = nvram_gen_util.o
+
+NVM_CORE_SRC = \
+nvram_factory_config.o
+
+NVM_GEN_SRC = \
+nvram_auto_gen.o
+
+NVM_LNK_CMD = \
+-Xlinker --script=$(LINKER_SCRIPT) -Xlinker --Map -Xlinker $(output_path)/nvram_auto_gen.map
+
+NVM_LNK_CMD_TARGET = \
+-Xlinker --script=$(LINKER_SCRIPT_TARGET) -Xlinker --Map -Xlinker $(output_path)/nvram_auto_gen.map
+
+NVM_GEN_OBJS = \
+$(output_path)/nvram_auto_gen.o \
+$(output_path)/nvram_white_list.o \
+$(output_path)/nvram_gen_util.o \
+$(output_path)/nvram_factory_config.o \
+$(output_path)/nvram_data_items.o \
+$(output_path)/nvram_cust_pack.o \
+$(output_path)/custom_nvram_sec.o \
+$(modem_obj) \
+$(middleware_obj) \
+$(nvram_obj) \
+$(bsp_obj)
+ifeq ($(strip $(NVRAM_LID_CACHE)),TRUE)
+NVM_GEN_OBJS += $(output_path)/nvram_gen_cache_table.o
+endif
+ifeq ($(strip $(DEMO_PROJECT)),TRUE)
+NVM_GEN_OBJS += $(output_path)/md5_dgst.o \
+$(output_path)/nvram_hash_check.o
+endif
+
+NVM_GEN_OBJS += $(output_path)/fs_quota.o $(output_path)/fs_quota_entry_dump.o
+QUOTA_SRC += fs_quota.o fs_quota_entry_dump.o
+
+NVM_TARGET_GEN_OBJS = \
+$(output_path)/nvram_auto_gen_TARGET.o \
+$(output_path)/nvram_white_list.o \
+$(output_path)/nvram_factory_config.o \
+$(output_path)/nvram_data_items.o \
+$(output_path)/nvram_cust_pack.o \
+$(output_path)/custom_nvram_sec.o \
+$(modem_obj) \
+$(middleware_obj) \
+$(nvram_obj) \
+$(bsp_obj)
+
+ifeq ($(strip $(LEVEL)), VENDOR) # vendor release
+	NVM_OPTION =  -fshort-enums  -D "NVRAM_AUTO_GEN" -D "__VENDOR_RELEASE__" -D "__LITTLE_ENDING"
+else
+	NVM_OPTION =  -fshort-enums  -D "NVRAM_AUTO_GEN" -D "__LITTLE_ENDING"
+endif
+
+NVM_INC = -I "tools/NVRAMStatistic/include" -I "service/nvram/include" -I "interface"
+ifeq ($(strip $(DEMO_PROJECT)),TRUE)
+OPENSSL_INC = -I "tools/NVRAMStatistic/include/openssl"
+endif
+
+QUOTA_OPTION =  -D "BUILD_TIME_CHECK_GEN" -D "GEN_FOR_PC"
+QUOTA_INC = -I "custom/common/"
+
+
+#Using the folder from resource generator
+MTK_DEFS = \
+	-D "__MULTI_BIN_LOAD__" \
+	-D "__EXE_DLL__"
+
+
+.SUFFIXES: .o .cpp .c .txt
+
+
+############ nvram_auto_gen compiling ####################################
+
+BSP_LIST:
+	@${ECHO} "Building BSP data items: $(notdir $(bsp_src))"
+ifneq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)
+	@for f in $(bsp_src) ; do \
+	  ${ECHO} Compile $(subst ,,$(bsp_dir)/$$f.c); \
+	  ${GCC} $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC)  -w -c $(bsp_dir)/$$f.c -MMD -MF $(output_path)/$$f.d -o $(output_path)/$$f.o; \
+	done
+endif	
+ifneq ($(strip $(OS_VERSION)),MSWin32)
+	@for f in $(bsp_src) ; do \
+	  ${CC} $(CFLAGS) $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC)  -w -c $(bsp_dir)/$$f.c -MMD -MF $(output_path)_target/$$f.d -o $(output_path)_target/$$f.o; \
+	done
+else
+  ifeq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)
+	@for f in $(bsp_src) ; do \
+	  ${GCC} $(CFLAGS) $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC)  -w -c $(bsp_dir)/$$f.c -MMD -MF $(output_path)_target/$$f.d -o $(output_path)_target/$$f.o; \
+	done
+  endif
+endif
+	
+	
+MODEM_LIST:
+	@${ECHO} "Building MODEM data items: $(notdir $(modem_src))"
+ifneq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)		
+	@for f in $(modem_src) ; do \
+	  ${ECHO} Compile $(modem_dir)/$$f.c; \
+	  ${GCC} $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC)  -w -c $(modem_dir)/$$f.c -MMD -MF $(output_path)/$$f.d -o $(output_path)/$$f.o; \
+	done	  
+endif	
+ifneq ($(strip $(OS_VERSION)),MSWin32)
+	@for f in $(modem_src) ; do \
+	  ${CC} $(CFLAGS) $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC)  -w -c $(modem_dir)/$$f.c -MMD -MF $(output_path)_target/$$f.d -o $(output_path)_target/$$f.o; \
+	done		
+else
+  ifeq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)
+	@for f in $(modem_src) ; do \
+	  ${GCC} $(CFLAGS) $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC)  -w -c $(modem_dir)/$$f.c -MMD -MF $(output_path)_target/$$f.d -o $(output_path)_target/$$f.o; \
+	done		
+  endif
+endif
+
+MIDDLEWARE_LIST:
+	@${ECHO} "Building MIDDLEWARE data items: $(notdir $(middleware_src))"
+ifneq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)		
+	@for f in $(middleware_src) ; do \
+	  ${ECHO} Compile $(middleware_dir)/$$f.c; \
+	  ${GCC} $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC)  -w -c $(middleware_dir)/$$f.c -MMD -MF $(output_path)/$$f.d -o $(output_path)/$$f.o; \
+	done
+endif	
+ifneq ($(strip $(OS_VERSION)),MSWin32)
+	@for f in $(middleware_src) ; do \
+	  ${CC} $(CFLAGS) $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC)  -w -c $(middleware_dir)/$$f.c -MMD -MF $(output_path)_target/$$f.d -o $(output_path)_target/$$f.o; \
+	done		
+else
+  ifeq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)
+	@for f in $(middleware_src) ; do \
+	  ${GCC} $(CFLAGS) $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC)  -w -c $(middleware_dir)/$$f.c -MMD -MF $(output_path)_target/$$f.d -o $(output_path)_target/$$f.o; \
+	done		
+  endif
+endif
+
+NVRAM_LIST:
+	@${ECHO} "Building NVRAM data items: $(notdir $(nvram_src))"
+ifneq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)		
+	@for f in $(nvram_src) ; do \
+	  ${ECHO} Compile $(nvram_dir)/$$f.c; \
+	  ${GCC} $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC)  -w -c $(nvram_dir)/$$f.c -MMD -MF $(output_path)/$$f.d -o $(output_path)/$$f.o; \
+	done
+endif	
+ifneq ($(strip $(OS_VERSION)),MSWin32)
+	@for f in $(nvram_src) ; do \
+	  ${CC} $(CFLAGS) $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC)  -w -c $(nvram_dir)/$$f.c -MMD -MF $(output_path)_target/$$f.d -o $(output_path)_target/$$f.o; \
+	done		
+else
+  ifeq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)
+	@for f in $(nvram_src) ; do \
+	  ${GCC} $(CFLAGS) $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC)  -w -c $(nvram_dir)/$$f.c -MMD -MF $(output_path)_target/$$f.d -o $(output_path)_target/$$f.o; \
+	done
+  endif
+endif
+
+nvram_data_items.o: custom/service/nvram/nvram_data_items.c
+	@${ECHO} "Compile custom/common/hal/nvram/nvram_data_items.c..."
+ifneq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)			
+	@${GCC} $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC) -w -c $< -MMD -MF $(output_path)/$(basename $(@F)).d -o $(output_path)/$@
+endif
+ifneq ($(strip $(OS_VERSION)),MSWin32)
+	@${CC} $(CFLAGS) $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC) -w -c $< -MMD -MF $(output_path)_target/$(basename $(@F)).d -o $(output_path)_target/$@
+else
+  ifeq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)
+	@${GCC} $(CFLAGS) $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC) -w -c $< -MMD -MF $(output_path)_target/$(basename $(@F)).d -o $(output_path)_target/$@
+  endif
+endif
+	
+nvram_cust_pack.o: custom/service/nvram/nvram_cust_pack.c
+	@${ECHO} "Compile custom/common/hal/nvram/nvram_cust_pack.c..."
+ifneq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)	
+	@${GCC} $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC) -w -c $< -MMD -MF $(output_path)/$(basename $(@F)).d -o $(output_path)/$@
+endif
+ifneq ($(strip $(OS_VERSION)),MSWin32)
+	@${CC} $(CFLAGS) $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC) -w -c $< -MMD -MF $(output_path)_target/$(basename $(@F)).d -o $(output_path)_target/$@
+else
+  ifeq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)
+	@${GCC} $(CFLAGS) $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC) -w -c $< -MMD -MF $(output_path)_target/$(basename $(@F)).d -o $(output_path)_target/$@
+  endif
+endif
+
+custom_nvram_sec.o: custom/service/nvram/custom_nvram_sec.c
+	@${ECHO} "Compile custom/common/hal/nvram/custom_nvram_sec.c..."
+ifneq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)	
+	@${GCC} $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC) -w -c $< -MMD -MF $(output_path)/$(basename $(@F)).d -o $(output_path)/$@
+endif
+ifneq ($(strip $(OS_VERSION)),MSWin32)
+	@${CC} $(CFLAGS) $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC) -w -c $< -MMD -MF $(output_path)_target/$(basename $(@F)).d -o $(output_path)_target/$@
+else
+  ifeq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)
+	@${GCC} $(CFLAGS) $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC) -w -c $< -MMD -MF $(output_path)_target/$(basename $(@F)).d -o $(output_path)_target/$@
+  endif
+endif
+
+
+nvram_factory_config.o: service/nvram/src/nvram_factory_config.c
+	@${ECHO} "Compile common/service/nvram/src/nvram_factory_config.c..."
+ifneq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)	
+	@${GCC} $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC) -w -c $< -MMD -MF $(output_path)/$(basename $(@F)).d -o $(output_path)/$@
+endif
+ifneq ($(strip $(OS_VERSION)),MSWin32)
+	@${CC} $(CFLAGS) $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC) -w -c $< -MMD -MF $(output_path)_target/$(basename $(@F)).d -o $(output_path)_target/$@
+else
+  ifeq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)
+	@${GCC} $(CFLAGS) $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC) -w -c $< -MMD -MF $(output_path)_target/$(basename $(@F)).d -o $(output_path)_target/$@
+  endif
+endif
+
+fs_quota_entry_dump.o: tools/NVRAMStatistic/src/fs_quota_entry_dump.c 
+ifneq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)	
+	@${ECHO} "Compile tools/NVRAMStatistic/src/fs_quota_entry_dump.c..."
+	@${GCC} $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC)  -w -c $< -MMD -MF $(output_path)/$(basename $(@F)).d -o $(output_path)/$@
+else
+	@${ECHO} "skip Compile fs_quota_entry_dump.c..."
+endif	
+fs_quota.o: custom/middleware/common/fs_quota.c
+ifneq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)	
+	@${ECHO} "Compile custom/middleware/common/fs_quota.c..."
+	@${GCC} $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC) -w -c $< -MMD -MF $(output_path)/$(basename $(@F)).d -o $(output_path)/$@
+else
+	@${ECHO} "Skip Compile fs_quota.c..."
+endif
+nvram_auto_gen_TARGET.o: tools/NVRAMStatistic/src/nvram_auto_gen_TARGET.c auto_gen_file
+ifeq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)
+	@${ECHO} "run autogen v2 startup.py..."
+	@python $(autogen_v2)/startup.py $(base_path)/.. $(GCC)
+endif
+	@${ECHO} "Compile nvram_auto_gen_TARGET.o..."
+ifneq ($(strip $(OS_VERSION)),MSWin32)
+	@$(IF_NOT_EXIST) $(output_path)_target $(THEN) ($(MKDIR) $(output_path)_target) $(CMD_END)
+	@${CC} $(CFLAGS) $(CUSTOM_OPTION) $(NVM_OPTION) -D __NV_GEN_FULL_LID__ ${CUSTOM_INC} $(NVM_INC) -w -c $< -MMD -MF $(output_path)_target/$(basename $(@F)).d -o $(output_path)_target/$@
+else
+  ifeq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)
+	@${GCC} $(CFLAGS) $(CUSTOM_OPTION) $(NVM_OPTION) -D __NV_GEN_FULL_LID__ ${CUSTOM_INC} $(NVM_INC) -w -c $< -MMD -MF $(output_path)_target/$(basename $(@F)).d -o $(output_path)_target/$@
+  endif
+endif
+
+auto_gen_file:
+ifneq ($(strip $(OS_VERSION)),MSWin32)
+	@$(IF_NOT_EXIST) $(output_path)_target $(THEN) ($(MKDIR) $(output_path)_target) $(CMD_END)
+endif
+	@$(ECHO) \#ifndef NVRAM_LID_STATISTIC_H >  $(base_path)/nvram_lid_statistics_bak.h
+	@$(ECHO) \#define NVRAM_LID_STATISTIC_H >> $(base_path)/nvram_lid_statistics_bak.h
+	@$(ECHO) \#ifndef NVRAM_NOT_PRESENT >> $(base_path)/nvram_lid_statistics_bak.h
+	@$(ECHO) \#ifndef NVRAM_AUTO_GEN >> $(base_path)/nvram_lid_statistics_bak.h
+	@$(ECHO) \#ifndef __RESOURCE_GEN_ >> $(base_path)/nvram_lid_statistics_bak.h
+	@$(ECHO) \#ifndef GEN_FOR_PC >> $(base_path)/nvram_lid_statistics_bak.h
+	@$(ECHO) \#error "nvram_auto_gen fail!" >> $(base_path)/nvram_lid_statistics_bak.h
+	@$(ECHO) \#endif >> $(base_path)/nvram_lid_statistics_bak.h
+	@$(ECHO) \#endif >> $(base_path)/nvram_lid_statistics_bak.h
+	@$(ECHO) \#endif >> $(base_path)/nvram_lid_statistics_bak.h
+	@$(ECHO) \#define NVRAM_OTP_SIZE 10 >> $(base_path)/nvram_lid_statistics_bak.h
+	@$(ECHO) \#define NVRAM_OTP_TOTAL 1 >> $(base_path)/nvram_lid_statistics_bak.h
+	@$(ECHO) \#define NVRAM_CUSTPACK_TOTAL 14 >> $(base_path)/nvram_lid_statistics_bak.h
+	@$(ECHO) \#define NVRAM_SECUPACK_SIZE 973 >> $(base_path)/nvram_lid_statistics_bak.h
+	@$(ECHO) \#endif >> $(base_path)/nvram_lid_statistics_bak.h
+	@$(ECHO) \#endif >> $(base_path)/nvram_lid_statistics_bak.h
+	@$(CAT)  $(base_path)/nvram_lid_statistics_bak.h > $(base_path)/nvram_lid_statistics.h
+	@$(ECHO) generate nvram_lid_statistics_bak.h success
+
+	@$(ECHO) typedef enum {              >  $(base_path)/nvram_gen_trc.h
+	@$(ECHO)	_NVRAM_EF_SYS_LID = 0,  >> $(base_path)/nvram_gen_trc.h  
+	@$(ECHO)	NVRAM_TRC_LID_TOTAL     >> $(base_path)/nvram_gen_trc.h 
+	@$(ECHO) "}nvram_trc_lid_enum;"     >> $(base_path)/nvram_gen_trc.h 
+	
+	@$(ECHO) generate nvram_gen_trc.h success
+	@${ECHO} "Path = $(PATH)"	
+
+nvram_auto_gen.o: tools/NVRAMStatistic/src/nvram_auto_gen.c auto_gen_file
+ifneq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)
+	@${ECHO} Compile nvram_auto_gen.c...
+	@${GCC} $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC)  -w  -c $< -MMD -MF $(output_path)/$(basename $(@F)).d -o $(output_path)/$@
+else
+	@${ECHO} Skip compile nvram_auto_gen.c...
+endif
+
+nvram_gen_util.o: tools/NVRAMStatistic/src/nvram_gen_util.c
+ifneq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)
+	@${GCC} $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC)  -w -c $< -MMD -MF $(output_path)/$(basename $(@F)).d -o $(output_path)/$@
+else
+	@${ECHO} Skip compile nvram_gen_util.c...
+endif	
+
+ifeq ($(strip $(NVRAM_LID_CACHE)),TRUE)
+nvram_gen_cache_table.o: tools/NVRAMStatistic/src/nvram_gen_cache_table.c
+ifneq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)
+	@${GCC} $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC)  -w -c $< -MMD -MF $(output_path)/$(basename $(@F)).d -o $(output_path)/$@
+endif
+endif
+
+ifeq ($(strip $(DEMO_PROJECT)),TRUE)
+md5_dgst.o: tools/NVRAMStatistic/src/md5_dgst.c
+ifneq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)
+	@${GCC} $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC) $(OPENSSL_INC) -w -c $< -MMD -MF $(output_path)/$(basename $(@F)).d -o $(output_path)/$@
+endif
+	
+nvram_hash_check.o: tools/NVRAMStatistic/src/nvram_hash_check.c
+ifneq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)
+	@${GCC} $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC) $(OPENSSL_INC) -w -c $< -MMD -MF $(output_path)/$(basename $(@F)).d -o $(output_path)/$@
+endif
+endif
+
+nvram_white_list.o: tools/NVRAMStatistic/src/nvram_white_list.c
+ifneq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)	
+	@${GCC} $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC)  -w -c $< -MMD -MF $(output_path)/$(basename $(@F)).d -o $(output_path)/$@
+endif
+ifneq ($(strip $(OS_VERSION)),MSWin32)
+	@${CC} $(CFLAGS) $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC)  -w -c $< -MMD -MF $(output_path)_target/$(basename $(@F)).d -o $(output_path)_target/$@
+else
+  ifeq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)
+	@${GCC} $(CFLAGS) $(CUSTOM_OPTION) $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC)  -w -c $< -MMD -MF $(output_path)_target/$(basename $(@F)).d -o $(output_path)_target/$@
+  endif
+endif
+
+ifneq ($(filter "NVRAM_NOT_PRESENT", $(strip $(CUSTOM_OPTION))),)
+    nvram_auto_gen_build: nvram_auto_gen.o $(QUOTA_SRC) 
+	@${GCC} -o $(output_path)/nvram_auto_gen $(output_path)/nvram_auto_gen.o
+else
+ifeq ($(strip $(LEVEL)), LEVEL2_OBJ)
+  ifneq ($(strip $(CUSTOM_RELEASE)), FALSE)
+        nvram_auto_gen_build: $(NVM_GEN_SRC) $(NVM_TARGET_GEN_SRC) $(NVM_CUST_SRC) $(QUOTA_SRC)
+  else
+        nvram_auto_gen_build: $(NVM_GEN_SRC) $(NVM_TARGET_GEN_SRC) $(NVM_CUST_SRC) $(NVM_CORE_SRC) $(QUOTA_SRC)
+  endif
+	@${GCC} -o $(output_path)/nvram_auto_gen $(output_path)/$(NVM_GEN_OBJS)
+	@${ECHO} "build level2_obj nvram_auto_gen done"
+else
+  ifeq ($(strip $(LEVEL)), VENDOR) # vendor release
+  	@${ECHO} "nvram_auto_gen VENDOR RELEASE"
+    nvram_auto_gen_build: $(NVM_GEN_SRC) $(NVM_TARGET_GEN_SRC) $(NVM_VENDOR_SRC) $(QUOTA_SRC)
+ifneq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE) 
+		@${GCC} $(NVM_LNK_CMD) -o $(output_path)/nvram_auto_gen $(NVM_GEN_OBJS)
+		@${OBJDUMP} -x $(base_path)/nvram_auto_gen > $(base_path)/nvram_auto_gen.map
+endif
+ifneq ($(strip $(OS_VERSION)),MSWin32)
+		@${CC} $(PLATFORM_FLAGS) $(NVM_LNK_CMD_TARGET) -o $(output_path)/nvram_auto_gen_target $(subst debug,debug_target,$(NVM_TARGET_GEN_OBJS))
+		@${OBJDUMP} -x $(base_path)/nvram_auto_gen_target > $(base_path)/nvram_auto_gen_target.map
+else
+  ifeq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)
+		@${GCC} $(PLATFORM_FLAGS) $(NVM_LNK_CMD_TARGET) -o $(output_path)/nvram_auto_gen_target $(subst debug,debug_target,$(NVM_TARGET_GEN_OBJS))
+		@${CAT} $(output_path)/nvram_auto_gen.map > $(base_path)/nvram_auto_gen_target.map
+  endif
+endif
+		@${ECHO} "build vendor nvram_auto_gen done"
+  else 
+    nvram_auto_gen_build: $(NVM_GEN_SRC) $(NVM_TARGET_GEN_SRC) $(NVM_CUST_SRC) $(NVM_CORE_SRC) $(QUOTA_SRC)
+ifneq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)    
+		@${GCC} $(NVM_LNK_CMD) -o $(base_path)/nvram_auto_gen $(NVM_GEN_OBJS)
+		@${OBJDUMP} -x $(base_path)/nvram_auto_gen > $(base_path)/nvram_auto_gen.map
+endif	
+ifneq ($(strip $(OS_VERSION)),MSWin32)
+		@${CC} $(PLATFORM_FLAGS) $(NVM_LNK_CMD_TARGET) -o $(base_path)/nvram_auto_gen_target $(subst debug,debug_target,$(NVM_TARGET_GEN_OBJS))
+		@${OBJDUMP} -x $(base_path)/nvram_auto_gen_target > $(base_path)/nvram_auto_gen_target.map
+else
+  ifeq ($(strip $(NVRAM_AUTOGEN_V2)), TRUE)
+		@${GCC} $(NVM_LNK_CMD_TARGET) -o $(base_path)/nvram_auto_gen_target $(subst debug,debug_target,$(NVM_TARGET_GEN_OBJS))
+		@${CAT} $(output_path)/nvram_auto_gen.map > $(base_path)/nvram_auto_gen_target.map
+  endif 
+endif
+		@${ECHO} "build nvram_auto_gen done"
+  endif
+endif
+endif
+
diff --git a/mcu/tools/NVRAMStatistic/nvram_checksum_algorithm_double_check.py b/mcu/tools/NVRAMStatistic/nvram_checksum_algorithm_double_check.py
new file mode 100644
index 0000000..ac6cb4b
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_checksum_algorithm_double_check.py
@@ -0,0 +1,406 @@
+import getopt

+import sys

+import os

+import re

+import unittest

+

+# class

+class LidInfor(object):

+    enhance_algo_size = 0

+    enhance_algo_type = 0

+    default_algo_size = 0

+    default_algo_type = 0

+    lid_dict = {}   # {lid:[LID_str, verno, category, attr], lid:[LID_str, verno, category, attr]}

+    

+    def __init__(self):

+        self.enhance_algo_size = 0

+        self.enhance_algo_type = 0

+        self.default_algo_size = 0

+        self.default_algo_type = 0

+        self.lid_dict = {}

+

+# global values

+# read nvram_defs.h #define

+NVRAM_ATTR_CHKSUM_ENHNC_ALGRTHM = 1<<17

+NVRAM_CATEGORY_CALIBRAT = 1<<12

+NVRAM_CATEGORY_IMPORTANT = 1<<13

+

+pre_lid_info = LidInfor()

+curr_lid_info = LidInfor()

+pre_algo_info = {"enhance_algo_size":0, "enhance_algo_type":0, "default_algo_size":0, "default_algo_type":0}

+curr_algo_info = {"enhance_algo_size":0, "enhance_algo_type":0, "default_algo_size":0, "default_algo_type":0}

+

+""" printf compatible python2&3 """

+def printf(strs, file=sys.stdout, end="\n", flush=False):

+    strs_val = strs + end

+    file.write(strs_val)

+    if flush:

+        file.flush()

+

+# bit and function

+def attr_chksum_enhnc_algo(attr):

+    return attr & NVRAM_ATTR_CHKSUM_ENHNC_ALGRTHM

+def cate_calibrat(cate):

+    return cate & NVRAM_CATEGORY_CALIBRAT

+def cate_important(cate):

+    return cate & NVRAM_CATEGORY_IMPORTANT

+

+""" 

+description

+    check if customer modified lid & checksum algorithm correctly 

+input 

+    pre_lid : lid info for Previous_information.log (class LidInfor )

+    curr_lid : lid info for Current_information.log (class LidInfor )

+output

+    False : algo type Check fail

+    True : algo type Check pass

+"""

+def nvram_lid_checksum_algo_type_check(pre_lid, curr_lid):

+    ret_value = True

+    

+    if pre_lid.default_algo_type != curr_lid.default_algo_type:

+        ret_value = False

+        printf("================================================")

+        printf("error : default algorithm type is not equal!")

+        printf("error : Previous default algo type  = %d" % pre_lid.default_algo_type)

+        printf("error : Current default algo type = %d" % curr_lid.default_algo_type)

+    

+    for lid in curr_lid.lid_dict.keys():

+        if not lid in pre_lid.lid_dict:

+            printf("warning : lid %d does not exist in Previous_information.log!"  % lid)

+            continue

+        # Collect lid info 

+        curr_verno = curr_lid.lid_dict[lid][1]

+        pre_verno = pre_lid.lid_dict[lid][1]

+        curr_cate = curr_lid.lid_dict[lid][2]

+        pre_cate = pre_lid.lid_dict[lid][2]

+        curr_attr = curr_lid.lid_dict[lid][3]

+        pre_attr = pre_lid.lid_dict[lid][3]

+        

+        

+        if attr_chksum_enhnc_algo(curr_attr) != attr_chksum_enhnc_algo(pre_attr):  # default -> enhance or enhance -> default

+            if curr_verno == pre_verno + 1:

+                continue

+            elif not (cate_calibrat(curr_cate) or cate_important(curr_cate)):   # calibrate|important

+                continue

+            else:

+                ret_value = False

+                printf("================================")

+                printf("error : lid = %d " % lid)

+                printf("\tverno: per = %d curr = %d" % (pre_verno, curr_verno))

+                printf("\tcate: per = %x curr = %x" % (pre_cate, curr_cate))

+                printf("\tattr: per = %x curr = %x" % (pre_attr, curr_attr))

+        else:  # all default or all enhance

+            if not attr_chksum_enhnc_algo(pre_attr):    # all default

+                continue

+            elif pre_lid.enhance_algo_type == curr_lid.enhance_algo_type:   # all enhance, enhance equal

+                continue

+            # enhance A -> enhance B

+            elif curr_verno == pre_verno + 1:

+                continue

+            elif not (cate_calibrat(curr_cate) or cate_important(curr_cate)):

+                continue

+            else:

+                ret_value = False

+                printf("================================")

+                printf("error : lid = %d " % lid)

+                printf("\tverno: per = %d curr = %d" % (pre_verno, curr_verno))

+                printf("\tcate: per = %x curr = %x" % (pre_cate, curr_cate))

+                printf("\tattr: per = %x curr = %x" % (pre_attr, curr_attr))

+    

+    return ret_value

+                

+

+        

+

+def main(PrelogPath, CurrlogPath):

+    PrelogFile = ""

+    CurrlogFile = ""

+    

+    # check file exist

+    PrelogFile = os.path.join(PrelogPath, "~nvram_lid_information.log")

+    CurrlogFile = os.path.join(CurrlogPath, "~nvram_lid_information.log")

+    if not os.path.exists(CurrlogFile): 

+        printf("autogen ~nvram_lid_information.log does not exist!")

+        printf("please ensure NVRAM_autogen runs successfully!")

+        sys.exit(4)

+    if not os.path.exists(PrelogFile):  # Previous info.log not exist => bypass

+        printf("Previous ~nvram_lid_information.log does not exist!")

+        printf("algorithm check bypass!")

+        sys.exit()

+    

+    pre_fd = open(PrelogFile, "r")

+    curr_fd = open(CurrlogFile, "r")

+    

+    # -----------------------------------

+    # read information.log get algo info

+    for each_line in pre_fd:

+        for key in pre_algo_info.keys():

+            if each_line.count(key) != 0:

+                s = each_line.strip()  # clear head&tail character ('\n' ' ' '\t' '\r')

+                list_t = s.split("=")  # split ("" " " "\n" "\t")

+                pre_algo_info[key] = int(list_t[1])

+                break

+    for each_line in curr_fd:

+        for key in curr_algo_info.keys():

+            if each_line.count(key) != 0:

+                s = each_line.strip()  # clear head&tail character ('\n' ' ' '\t' '\r')

+                list_t = s.split("=")  # split ("" " " "\n" "\t")

+                curr_algo_info[key] = int(list_t[1])

+                break

+    printf("========= pre_algo_info =============")

+    for key in pre_algo_info.keys():

+        printf("%s = %d" % (key, pre_algo_info[key]))

+    printf("========= curr_algo_info =============")

+    for key in curr_algo_info.keys():

+        printf("%s = %d" % (key, curr_algo_info[key]))

+        

+    pre_lid_info.enhance_algo_size = pre_algo_info["enhance_algo_size"]

+    pre_lid_info.enhance_algo_type = pre_algo_info["enhance_algo_type"]

+    pre_lid_info.default_algo_size = pre_algo_info["default_algo_size"]

+    pre_lid_info.default_algo_type = pre_algo_info["default_algo_type"]

+    curr_lid_info.enhance_algo_size = curr_algo_info["enhance_algo_size"]

+    curr_lid_info.enhance_algo_type = curr_algo_info["enhance_algo_type"]

+    curr_lid_info.default_algo_size = curr_algo_info["default_algo_size"]

+    curr_lid_info.default_algo_type = curr_algo_info["default_algo_type"]

+    

+    if pre_lid_info.enhance_algo_size == 0 and pre_lid_info.enhance_algo_type == 0 and pre_lid_info.default_algo_size == 0 and pre_lid_info.default_algo_type == 0:

+        printf("waring : property no exist enhance info!")

+        sys.exit()

+    

+    

+    # -----------------------------------

+    # read information.log get lid info

+    pre_fd.seek(0)

+    curr_fd.seek(0)

+    for each_line in pre_fd:

+        if re.search("NVRAM_.*_LID", each_line):

+            s = each_line.strip()  # clear head&tail character ('\n' ' ' '\t' '\r')

+            list_t = s.split()  # split ("" " " "\n" "\t")

+            lid_list = []

+            lid = int(list_t[0])

+            lid_list.append(list_t[1])  # lid_str

+            lid_list.append(int(list_t[3]))  # verno

+            lid_list.append(int(list_t[5], base=16))  # category

+            lid_list.append(int(list_t[6], base=16))  # attr

+            pre_lid_info.lid_dict[lid] = lid_list  # add to lid_info class

+    for each_line in curr_fd:

+        if re.search("NVRAM_.*_LID", each_line):

+            s = each_line.strip()  # clear head&tail character ('\n' ' ' '\t' '\r')

+            list_t = s.split()  # split ("" " " "\n" "\t")

+            lid_list = []

+            lid = int(list_t[0])

+            lid_list.append(list_t[1])  # lid_str

+            lid_list.append(int(list_t[3]))  # verno

+            lid_list.append(int(list_t[5], base=16))  # category

+            lid_list.append(int(list_t[6], base=16))  # attr

+            curr_lid_info.lid_dict[lid] = lid_list  # add to lid_info class

+    pre_fd.close()

+    curr_fd.close()

+    

+    # printf("========= pre_lid_info =============")

+    # for i in pre_lid_info.lid_dict.keys():

+    #     printf("lid = %6d " % i, end="")

+    #     printf("verno = %4d " % pre_lid_info.lid_dict[i][1], end="")

+    #     printf("category = %8x " % pre_lid_info.lid_dict[i][2], end="")

+    #     printf("attr = %8x " % pre_lid_info.lid_dict[i][3])

+    # printf("========= curr_lid_info =============")

+    # for i in curr_lid_info.lid_dict.keys():

+    #     printf("lid = %6d " % i, end="")

+    #     printf("verno = %4d " % curr_lid_info.lid_dict[i][1], end="")

+    #     printf("category = %8x " % curr_lid_info.lid_dict[i][2], end="")

+    #     printf("attr = %8x " % curr_lid_info.lid_dict[i][3])

+    

+    if not nvram_lid_checksum_algo_type_check(pre_lid_info, curr_lid_info):

+        printf("algo type check error!")

+        sys.exit(5)

+        

+# ================================================

+# UT_TEST code 

+def data_restore():

+    pre_lid_info.enhance_algo_size = 32

+    pre_lid_info.enhance_algo_type = 2

+    pre_lid_info.default_algo_size = 16

+    pre_lid_info.default_algo_type = 1

+    curr_lid_info.enhance_algo_size = 32

+    curr_lid_info.enhance_algo_type = 2

+    curr_lid_info.default_algo_size = 16

+    curr_lid_info.default_algo_type = 1

+    lid = 61956

+    pre_lid_list = ["NVRAM_EF_CORE_INTERNAL_CLONE_LID", 0, 0, 0]  # [LID_str, verno, category, attr]

+    curr_lid_list = ["NVRAM_EF_CORE_INTERNAL_CLONE_LID", 0, 0, 0]  # [LID_str, verno, category, attr]

+    pre_lid_info.lid_dict[lid] = pre_lid_list

+    curr_lid_info.lid_dict[lid] = curr_lid_list

+

+class TestChangeDefaultType(unittest.TestCase):

+    def setUp(self):

+        data_restore()

+    @classmethod

+    def setUpClass(cls):

+        pass

+    @classmethod

+    def tearDownClass(cls):

+        pass

+    def test_item_1(self):

+        curr_lid_info.default_algo_type = 2

+        self.assertEqual(False, nvram_lid_checksum_algo_type_check(pre_lid_info, curr_lid_info))

+        

+class TestAddEnhance(unittest.TestCase):

+    def setUp(self):

+        data_restore()

+    @classmethod

+    def setUpClass(cls):

+        pass

+    @classmethod

+    def tearDownClass(cls):

+        pass

+    def test_item_2(self):

+        curr_lid_info.lid_dict[clone_lid][3] |= NVRAM_ATTR_CHKSUM_ENHNC_ALGRTHM

+        

+        # verno + 1 

+        curr_lid_info.lid_dict[clone_lid][1] += 1

+        self.assertEqual(True, nvram_lid_checksum_algo_type_check(pre_lid_info, curr_lid_info)) # verno + 1

+        

+        # not define calibrate|important

+        curr_lid_info.lid_dict[clone_lid][3] = NVRAM_ATTR_CHKSUM_ENHNC_ALGRTHM

+        self.assertEqual(True, nvram_lid_checksum_algo_type_check(pre_lid_info, curr_lid_info)) # not verno + 1, not define calibrate|important

+        

+        # not verno + 1, define calibrate|important

+        curr_lid_info.lid_dict[clone_lid][1] = 0

+        curr_lid_info.lid_dict[clone_lid][2] |= NVRAM_CATEGORY_CALIBRAT

+        curr_lid_info.lid_dict[clone_lid][2] |= NVRAM_CATEGORY_IMPORTANT

+        self.assertEqual(False, nvram_lid_checksum_algo_type_check(pre_lid_info, curr_lid_info)) # define calibrate|important, not verno         

+        

+class TestModifyEnhance(unittest.TestCase):

+    def setUp(self):

+        data_restore()

+    @classmethod

+    def setUpClass(cls):

+        pass

+    @classmethod

+    def tearDownClass(cls):

+        pass

+    def test_item_3(self):

+    

+        # not define enhance

+        self.assertEqual(True, nvram_lid_checksum_algo_type_check(pre_lid_info, curr_lid_info)) # not define enhance

+        

+        # enhance type qeual

+        pre_lid_info.lid_dict[clone_lid][3] |= NVRAM_ATTR_CHKSUM_ENHNC_ALGRTHM

+        curr_lid_info.lid_dict[clone_lid][3] |= NVRAM_ATTR_CHKSUM_ENHNC_ALGRTHM

+        self.assertEqual(True, nvram_lid_checksum_algo_type_check(pre_lid_info, curr_lid_info)) # define enhance, enhance type qeual

+        

+        # verno + 1

+        curr_lid_info.enhance_algo_type = 1

+        curr_lid_info.enhance_algo_size = 16

+        curr_lid_info.lid_dict[clone_lid][1] += 1

+        self.assertEqual(True, nvram_lid_checksum_algo_type_check(pre_lid_info, curr_lid_info)) # define enhance, enhance type not qeual, verno + 1

+        

+        # not define important|calibrate

+        curr_lid_info.lid_dict[clone_lid][3] = NVRAM_ATTR_CHKSUM_ENHNC_ALGRTHM

+        self.assertEqual(True, nvram_lid_checksum_algo_type_check(pre_lid_info, curr_lid_info)) # define enhance, enhance type not qeual, not verno + 1, not define calibrate|important

+        

+        # define enhance, enhance type not qeual, not verno + 1, define calibrate|important

+        curr_lid_info.lid_dict[clone_lid][1] = 0

+        curr_lid_info.lid_dict[clone_lid][2] |= NVRAM_CATEGORY_CALIBRAT

+        curr_lid_info.lid_dict[clone_lid][2] |= NVRAM_CATEGORY_IMPORTANT

+        self.assertEqual(False, nvram_lid_checksum_algo_type_check(pre_lid_info, curr_lid_info))

+    

+class TestRemoveEnhance(unittest.TestCase):

+    def setUp(self):

+        data_restore()

+    @classmethod

+    def setUpClass(cls):

+        pass

+    @classmethod

+    def tearDownClass(cls):

+        pass   

+    def test_item_4(self):

+        pre_lid_info.lid_dict[clone_lid][3] |= NVRAM_ATTR_CHKSUM_ENHNC_ALGRTHM

+        

+        # verno + 1 

+        curr_lid_info.lid_dict[clone_lid][1] += 1

+        self.assertEqual(True, nvram_lid_checksum_algo_type_check(pre_lid_info, curr_lid_info)) # verno + 1

+        

+        # not define calibrate|important

+        curr_lid_info.lid_dict[clone_lid][3] = 0

+        self.assertEqual(True, nvram_lid_checksum_algo_type_check(pre_lid_info, curr_lid_info)) # not verno + 1, not define OTA, not define calibrate|important

+        

+        # not verno + 1, define calibrate|important

+        curr_lid_info.lid_dict[clone_lid][1] = 0

+        curr_lid_info.lid_dict[clone_lid][2] |= NVRAM_CATEGORY_CALIBRAT

+        curr_lid_info.lid_dict[clone_lid][2] |= NVRAM_CATEGORY_IMPORTANT

+        self.assertEqual(False, nvram_lid_checksum_algo_type_check(pre_lid_info, curr_lid_info)) # calibrate|important, not verno +1

+

+# ------------------------------------------------------------------

+# ut test global values

+clone_lid = 61956

+test_cases = (TestChangeDefaultType, TestAddEnhance, TestModifyEnhance, TestRemoveEnhance)

+

+# read nvram_defs.h #define

+NVRAM_ATTR_CHKSUM_ENHNC_ALGRTHM = 1<<17

+NVRAM_ATTR_OTA_RESET = 1<<6

+NVRAM_CATEGORY_CALIBRAT = 1<<12

+NVRAM_CATEGORY_IMPORTANT = 1<<13

+def test_main(out_file):

+    suite = unittest.TestSuite()

+    

+    # creat TestLoader , load test case

+    loader = unittest.TestLoader()

+    for test_class in test_cases:

+        # loading test cases in a class

+        tests = loader.loadTestsFromTestCase(test_class)

+        # add test case

+        suite.addTests(tests)

+

+    with open(out_file, "w+") as f:

+        # creat TestRunner

+        runner = unittest.TextTestRunner(verbosity=2, stream=f)

+        # test run

+        runner.run(suite)

+

+

+# ======================================

+# run main or test_main

+

+if __name__ == '__main__':

+

+    PrelogPath = ""

+    CurrlogPath = ""

+    argc = len(sys.argv)

+    

+    if sys.argv[1] == "-t":

+        test_out_file = os.path.join(sys.argv[2], "checksum_algo_ut_test.txt")

+        test_main(test_out_file)

+    elif argc != 3:

+        printf("python call command error!")

+        printf("input command:", end="")

+        for i in range(argc):

+            printf("%s " % sys.argv[i], end="")

+        printf("")

+        printf("Example of command:")

+        printf("python nvram_checksum_algorithm_double_check.py <p4_info_path> <autogen_info_path>")

+        printf("ut test: .py -t <ut_test_out_path>")

+        sys.exit(2)

+    else:

+        PrelogPath = sys.argv[1]

+        CurrlogPath = sys.argv[2]

+        printf("Previous Path:%s" % PrelogPath)

+        printf("Current Path:%s" % CurrlogPath)

+        

+        # # path exist check

+        # if not os.path.exists(PrelogPath):

+        #     printf("Previous Path does not exist!")

+        #     sys.exit()

+        # if not os.path.exists(CurrlogPath):

+        #     printf("Current Path does not exist!")

+        #     sys.exit(3)

+        

+        main(PrelogPath, CurrlogPath)

+

+

+

+

+

+

+

diff --git a/mcu/tools/NVRAMStatistic/nvram_edit_gen.mak b/mcu/tools/NVRAMStatistic/nvram_edit_gen.mak
new file mode 100644
index 0000000..bc4c449
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_edit_gen.mak
@@ -0,0 +1,142 @@
+# NVRAM Editor

+.PHONY: NVRAM_EDITOR_H_TO_DB 

+

+include make/common/cmd_cfg.mak

+

+

+nvram_auto_gen_path := $(strip $(NVRAM_AUTO_GEN_PATH))/nvram_auto_gen

+

+ifeq ($(strip $(OS_VERSION)),MSWin32)

+  nvram_dir_list := driver\common middleware\common protocol\common\ps service\nvram

+	

+  def_h += $(foreach DIR,$(nvram_dir_list), \

+    $(foreach FILE,$(shell if exist custom\$(DIR)\*_nvram_def.h dir custom\$(DIR)\*_nvram_def.h /b),$(FILE)) \

+  )

+  tmp_def_h = $(strip $(def_h))

+  

+  editor_h += $(foreach DIR,$(nvram_dir_list), \

+    $(foreach FILE,$(shell if exist custom\$(DIR)\*_nvram_editor.h dir custom\$(DIR)\*_nvram_editor.h /b),$(FILE)) \

+  )

+  tmp_editor_h = $(strip $(editor_h))

+

+  def_c +=$(foreach DIR,$(nvram_dir_list), \

+    $(foreach FILE,$(shell if exist custom\$(DIR)\*_nvram_def.c dir custom\$(DIR)\*_nvram_def.c /b),$(FILE)) \

+  )

+

+  def_obj := $(patsubst %, %.obj, $(basename $(notdir $(def_c))))

+  tbl_list += logical_data_item_table_core \

+    logical_data_item_table_internal \

+    logical_data_item_table_factory \

+    logical_data_item_table_exception \

+					$(patsubst %, logical_data_item_table_%, $(subst _nvram_def.obj,,$(def_obj)))

+

+  ifeq ($(strip $(CUSTOM_RELEASE)),TRUE)

+    ifneq ($(filter custom,$(CUS_REL_MTK_COMP)),)

+        NVRAM_OBJ_LIST += $(patsubst %,$(strip $(CUS_MTK_LIB))\libcustom.a(%.obj), $(basename $(notdir $(def_c)))) $(CUS_MTK_LIB)\libcustom.a(nvram_data_items.obj) $(CUS_MTK_LIB)\libcustom.a(fs_quota.obj)

+    else

+      ifneq ($(filter custom,$(COMPLIST)),)

+            NVRAM_OBJ_LIST += $(patsubst %,$(strip $(COMPLIBDIR))\libcustom.a(%.obj), $(basename $(notdir $(def_c)))) $(COMPLIBDIR)\libcustom.a(nvram_data_items.obj) $(COMPLIBDIR)\libcustom.a(fs_quota.obj)

+      endif

+    endif

+    ifneq ($(filter nvram,$(CUS_REL_MTK_COMP)),)

+        NVRAM_OBJ_LIST += $(strip $(CUS_MTK_LIB))\libnvram.a(nvram_factory_config.obj)

+    else

+      ifneq ($(filter nvram,$(COMPLIST)),)

+        NVRAM_OBJ_LIST += $(strip $(COMPLIBDIR))\libnvram.a(nvram_factory_config.obj)

+      endif

+    endif

+  else

+    ifneq ($(filter custom,$(COMPLIST)),)

+        NVRAM_OBJ_LIST += $(patsubst %,$(strip $(COMPLIBDIR))\libcustom.a(%.obj), $(basename $(notdir $(def_c)))) $(COMPLIBDIR)\libcustom.a(nvram_data_items.obj) $(COMPLIBDIR)\libcustom.a(fs_quota.obj)

+    endif

+    ifneq ($(filter nvram,$(COMPLIST)),)

+        NVRAM_OBJ_LIST += $(strip $(COMPLIBDIR))\libnvram.a(nvram_factory_config.obj)

+    endif

+  endif

+

+

+  ifneq ($(strip $(MMI_VERSION)),EMPTY_MMI)

+    ifeq ($(strip $(CUSTOM_RELEASE)),TRUE)

+      ifneq ($(filter custom,$(COMPLIST)),)

+        ifneq ($(filter custom,$(CUS_REL_MTK_COMP)),)

+          NVRAM_OBJ_LIST += $(strip $(CUS_MTK_LIB))\libcustom.a(nvram_common_config.obj) $(strip $(CUS_MTK_LIB))\libcustom.a(nvram_user_config.obj)

+        else

+          NVRAM_OBJ_LIST += $(strip $(COMPLIBDIR))\libcustom.a(nvram_common_config.obj) $(strip $(COMPLIBDIR))\libcustom.a(nvram_user_config.obj)

+        endif

+      endif  

+    else

+      ifneq ($(filter custom,$(COMPLIST)),)

+        NVRAM_OBJ_LIST += $(strip $(COMPLIBDIR))\libcustom.a(nvram_common_config.obj) $(strip $(COMPLIBDIR))\libcustom.a(nvram_user_config.obj)

+      endif

+    endif

+

+    tbl_list +=logical_data_item_table_common_app logical_data_item_table_cust

+  endif

+

+  tbl_list +=g_fs_quota_init g_nvram_custpack_init

+

+  NVRAM_LNK_OPT := $(patsubst %, --keep=%, $(tbl_list))

+else

+  

+  nvram_dir_list := /driver/common /middleware/common /protocol/common/ps

+

+  def_h := $(foreach DIR, $(nvram_dir_list), $(subst custom/$(DIR)/,,$(wildcard custom/$(DIR)/*_nvram_def.h)))

+

+  editor_h := $(foreach DIR, $(nvram_dir_list), $(subst custom/$(DIR)/,,$(wildcard custom/$(DIR)/*_nvram_editor.h)))

+

+  def_c := $(foreach DIR, $(nvram_dir_list), $(wildcard /custom/$(DIR)/*_nvram_def.c))

+

+endif

+

+NVRAM_EDITOR_H_TO_DB:

+	@$(ECHO) -n $(nvram_auto_gen_path)/nvram_editor.h

+	@$(ECHO) -n OS_VERSION = $(OS_VERSION)

+

+ifeq ($(strip $(OS_VERSION)),MSWin32)

+	@echo #ifdef GEN_FOR_PC >  $(nvram_auto_gen_path)/nvram_editor.h

+	@echo #ifndef __NVRAM_EDITOR_H__ >>	$(nvram_auto_gen_path)/nvram_editor.h

+	@echo #define __NVRAM_EDITOR_H__ >>	$(nvram_auto_gen_path)/nvram_editor.h

+

+	@echo  tmp_def_h = $(tmp_def_h)

+  ifneq ($(words $(tmp_def_h)),0)

+	@for %%f in ($(tmp_def_h)) do echo #include "%%f" >> $(nvram_auto_gen_path)/nvram_editor.h

+  endif

+

+	@$(ECHO) -n tmp_editor_h = $(tmp_editor_h)

+  ifneq ($(words $(tmp_editor_h)),0)

+	@for %%f in ($(tmp_editor_h)) do echo #include "%%f" >> $(nvram_auto_gen_path)/nvram_editor.h

+  endif

+

+	@echo #endif >>  $(nvram_auto_gen_path)/nvram_editor.h

+	@echo #endif >>  $(nvram_auto_gen_path)/nvram_editor.h

+

+	@${CAT} $(nvram_auto_gen_path)/nvram_editor.h

+else	

+	@$(ECHO) -n \#ifdef GEN_FOR_PC >  $(nvram_auto_gen_path)/nvram_editor.h

+	@$(ECHO) -n \#ifndef __NVRAM_EDITOR_H__ >>	$(nvram_auto_gen_path)/nvram_editor.h

+	@$(ECHO) -n \#define __NVRAM_EDITOR_H__ >>	$(nvram_auto_gen_path)/nvram_editor.h

+	

+	@$(ECHO) -n def_h = $(def_h)

+    ifneq ($(words $(def_h)),0)

+		@for f in $(def_h); \

+		do \

+		$(ECHO) -n  \#include \"$$f\" >>  $(nvram_auto_gen_path)/nvram_editor.h;\

+		done

+    endif

+	@$(ECHO) -n \#include \"nvram_group_def.h\" >>  $(nvram_auto_gen_path)/nvram_editor.h

+

+	@$(ECHO) -n editor_h = $(editor_h)

+    ifneq ($(words $(editor_h)),0)

+		@for f in $(editor_h); \

+		do \

+		$(ECHO) -n  \#include \"$$f\" >>  $(nvram_auto_gen_path)/nvram_editor.h;\

+		done

+    endif

+		@$(ECHO) -n \#include \"nvram_group_editor.h\" >>  $(nvram_auto_gen_path)/nvram_editor.h

+		@$(ECHO) -n \#endif >>  $(nvram_auto_gen_path)/nvram_editor.h

+		@$(ECHO) -n \#endif >>  $(nvram_auto_gen_path)/nvram_editor.h

+

+endif  

+

+

+	

diff --git a/mcu/tools/NVRAMStatistic/nvram_gen_excel/input_config.ini b/mcu/tools/NVRAMStatistic/nvram_gen_excel/input_config.ini
new file mode 100644
index 0000000..24e03e9
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_gen_excel/input_config.ini
@@ -0,0 +1,58 @@
+[Config]
+
+
+#========================================================================================
+#These parameters are used to generate the excel
+#When using -a or -g parameter run the tool,tool need the following parameters.
+#========================================================================================
+#RawData XML exported from platform 
+#Input file
+#NVRAMReader_XML = nvram_reader.xml
+
+#Lid DB info file must be provided when using -g parameter run the tool
+#If using -a, the tool will not reference the paramters NVRAMLidDB_XML
+NVRAMLidDB_XML = MDDB.META.ODB.XML
+
+#ouput excel file name
+Excel_Output = (20190122)nvram_LID_detailed_description_customer.xlsx
+
+#========================================================================================
+#The following paramter are for some  special usage,use the default setting is OK.
+#========================================================================================
+Output_Array = TRUE
+Output_Possible_Val = TRUE
+
+#Bypass_No_Description is true,the lid with no description will not be generated to excel
+Bypass_No_Description = FALSE
+
+#DebugMode is only for tool debug
+DebugMode = FALSE
+
+
+# Add scure LID in excel
+Parse_Editor = TRUE 
+
+# Script log file name
+LogFile = LID_List_with_conflict_description.log
+IntegrityCheckLog = LID_List_without_full_description.log
+
+# sqlite file
+DBFile = NVRAM_LID_Detail.db
+
+# MONITOR
+# DB record lid owner map
+# NvramWebSQLite = /project/moly/nvram_check_log/db.sqlite3
+NvramWebSQLite = /mtkeda/wcpsm/USR/UMOLY/db.sqlite3
+
+#========================================================================================
+#The following parameters decide the scope of Lid generated to excel 
+#Structure_Deep is larger,the structure is unfolded detailedly more
+#========================================================================================
+[Filter]
+#
+# LID_Name : Structure_Deep
+#
+NVRAM_EF_*:99
+#NVRAM_EF_SBP_MODEM_CONFIG_LID:99
+#NVRAM_EF_SBP_MODEM_DATA_CONFIG_LID:99
+#NVRAM_EF_UL1_*:2
diff --git a/mcu/tools/NVRAMStatistic/nvram_gen_excel/nvram_gen_LID_description_integrity_check.py b/mcu/tools/NVRAMStatistic/nvram_gen_excel/nvram_gen_LID_description_integrity_check.py
new file mode 100644
index 0000000..f043dac
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_gen_excel/nvram_gen_LID_description_integrity_check.py
@@ -0,0 +1,300 @@
+"""
+NVRAM Description integrity check
+unintegrity:
+    struct has one field have no description.
+BY pass:
+    [1] field no description, there are descripted bit data have description
+    [2] TAG BY PASS:Any field have tag pointed at 'Pass_tag', the same as field child
+        => A.B has [INTERNAL],  by pass struct: [B, B.*]
+"""
+
+# TODO coding style !!! 
+
+import os, sys
+import re
+import pdb
+import json
+import time
+import ConfigParser
+try:
+    import xml.etree.cElementTree as ET
+except ImportError:
+    import xml.etree.ElementTree as ET
+    
+# record child:parent map  [{A:PARENT:[A1, A2]}]
+parentRelation = {}
+structBitdatas = {}
+ERR_OK, ERR_ERROR = [0, 1]
+STATUS = ERR_OK
+
+# global flag
+TAG_BY_PASS = True
+Pass_tag = ["INTERNAL", "DOC"]
+TAG = {"MCF":0x1,"LOCK":0x2, "RUNTIME":0x4, "DOC":0x8, "INTERNAL":0X10, "TIER1":0x20}
+    
+class DBParser(object):
+    def __init__(self, filename):
+        if not os.path.exists(filename):
+            print("[Error] DB file {} not exists".format(filename))
+            raise
+        self.struct_tag_map = {}
+        self.bypass_struct = []
+        # Structs which has no desc Bit datas(must be no desc except tag Bypass)
+        self.bit_data_no_desc = []
+        self.bypass_tag = 0x0
+        for key in Pass_tag:
+            self.bypass_tag = self.bypass_tag | TAG[key]
+            
+        self.tree = ET.ElementTree(file=filename)
+        # Find XML Node DB
+        self.root = self.tree.getroot()
+        if self.root.tag != 'DB':
+            self.root = self.root.find("./DB")
+        lids = self.tree.iter(tag="NVRAM_LID")
+        self.lids = lids
+        tmp_map = {}
+        
+        self.structs = {item.get("name"):item for item in self.tree.iter(tag="Struct")}
+        self.unions = self.tree.iter(tag="Union")
+        self.Typedefs = self.tree.iter(tag="Typedef")
+        tmp_def = {}
+        for item in self.Typedefs:
+            if item.get("defined_type") in ["struct"]:
+                tmp_def[item.get("defined_type_name")] = item
+        self.Typedefs = tmp_def
+        
+        
+def parse_struct(db, s_name):
+    """parse struct field and record parent if has parent
+    s_name: struct name
+    return all field offset which lack of description
+    """
+    # struct-parents map format=>{Child: [{p1_name: c_offset}, {p2_name:c_offset}]}
+    global parentRelation
+    
+    no_desc_field_offsets = []    
+    struct = db.structs[s_name]
+    fields = struct.getchildren()
+    
+    # one_filed : ElementTree
+    for one_field in fields:
+        filed_type = one_field.get("type", "")
+        type_name = one_field.get("type_name")
+        field_name = one_field.get("name")
+        field_offset = int(one_field.get("offset"))
+        bit_datas = []
+        tag = 0X0
+        
+        description = one_field.get("description", "").strip()
+        if not description:
+            print("--[No desc field]{}.{}".format(s_name, field_name) )
+            no_desc_field_offsets.append(field_offset)
+        
+        # Record parentRelation:{Child: {p1_name: c_offset, p2_name:c_offset}}
+        if filed_type in ["struct"]:
+            if type_name in parentRelation:
+                if s_name not in parentRelation[type_name]:
+                    parentRelation[type_name][s_name]= field_offset
+            else:   
+                parentRelation[type_name] = {s_name:field_offset}  
+            if TAG_BY_PASS and description:
+                tag = tag_parse(type_name, description, db)
+                if tag & db.bypass_tag and type_name not  in db.bypass_struct:
+                    db.bypass_struct.append(type_name)
+            
+        # Bit datas
+        bit_data_dom = one_field.getchildren()
+        if bit_data_dom:
+            bit_datas = bit_data_parse(bit_data_dom)
+            if bit_datas:
+                if s_name in structBitdatas:
+                    structBitdatas[s_name].extend(bit_datas)
+                else:
+                    structBitdatas[s_name] = bit_datas
+    return no_desc_field_offsets
+    
+    
+def bit_data_parse(bit_child):
+    bit_data_with_desc = []
+    
+    for child in bit_child:
+        # offset related to top struct 
+        bit_offset = int(child.get("byte_offset"))
+        if child.get("description", "").strip():
+            bit_data_with_desc.append(bit_offset)
+    return bit_data_with_desc
+        
+    
+def tag_parse(name, description, db):
+    """Parse struct tag"""
+    # if one_field.get("type") not in ["struct", "union"]:
+        # return
+    # name = one_field.get("type_name")
+    tag_pattern = re.compile(r"\[[A-Z\s,]+\]")
+    
+    tags = tag_pattern.findall(description)
+    tag = 0X0
+    
+    for group in tags:
+        # group = '[DOC, MCF]'
+        for item in TAG.keys():
+            if item in group:
+                tag = tag | TAG[item]
+    tag = tag if name not in db.struct_tag_map else (tag | db.struct_tag_map[name])
+    if tag:
+        db.struct_tag_map[name] = tag
+    return tag
+    
+
+def get_top(db, child, no_desc_struct_map, parent_list=None, bits=None, child_struct='', pre_offset=0):
+    # global PARENT_RELATION
+    if child in parentRelation:
+        field_parents = parentRelation[child]
+        # All parent chain
+        for item in field_parents.keys():
+            # record bit data by pass
+            Bypass = False
+            if TAG_BY_PASS and item in db.bypass_struct:
+                # print ("Bypas struct: {}".format(item))
+                continue
+            p_offset = pre_offset + field_parents[item]
+            # -----
+            if item in structBitdatas:
+                # parent have bit data TOP STRUCT
+                # print("parent all bits have desce: {}".format(structBitdatas[item]) )
+                bits = [i-p_offset for i in structBitdatas[item]]
+            # -----
+            if item in parentRelation and child in parentRelation[item]:
+                continue
+            else:
+                get_top(db, item, no_desc_struct_map, parent_list, bits, child_struct, p_offset)
+    else:  # find top struct: All no_desc_offset in bits=>by pass
+        if bits:
+            for one_offset in no_desc_struct_map[child_struct]:
+                if one_offset not in bits:
+                    if child not in parent_list:
+                        parent_list.append(child)
+                    break
+        else:
+            if child not in parent_list:
+                parent_list.append(child)
+            
+def get_top_struct(db, child, no_desc_struct_map, Top_structs, child_str=""):
+    """search top struct
+        child: {name: xxx, size:xxx}
+    """
+    # global PARENT_RELATION
+    if child in parentRelation:
+        parent_list = []
+        # Assert all bit data under top_struct
+        bits = []
+        # print("Begin to find parent of struct: {}".format(child) )
+        get_top(db, child, no_desc_struct_map, parent_list, bits, child, 0)
+        
+        for item in parent_list:
+            if item not in Top_structs:
+                Top_structs[item] = [child]
+            elif child not in Top_structs[item]:
+                Top_structs[item].append(child)
+            # child_str.append("{}: top_struct: {} \n".format(item, Top_structs[item]))
+    else:   
+        # Top struct have no desc
+        if child in Top_structs:
+            Top_structs[child].append(child)
+        else:
+            Top_structs[child] = [child]
+        return 
+        
+def get_rel_lid(db, struct_name):
+    """get LID"""
+    structs = [struct_name]
+    while struct_name in db.Typedefs:
+        if struct_name == db.Typedefs[struct_name].get("name"):
+            print "----------S----------struct_name: ".format(struct_name)
+            break
+        struct_name = db.Typedefs[struct_name].get("name")
+        structs.append(struct_name)
+    result = []
+    for struct_name in structs:
+        lid = db.root.findall("*/NVRAM_LID/[@type_name='{}']".format(struct_name))
+        result += [item.get("name") for item in lid] if lid != [] else []
+    return result
+        
+def main(xml_file=None):
+    # global PARENT_RELATION
+    gen_nvram_tool_path = os.path.dirname(os.path.realpath(sys.argv[0]))
+    start = time.time()
+    NoDesLids = {}    # 
+    # Load config file
+    config_file = gen_nvram_tool_path + "/input_config.ini"
+    cf = ConfigParser.ConfigParser()
+    cf.read(config_file)
+     
+    if not xml_file:
+        xml_file = gen_nvram_tool_path + "/" + cf.get("Config", "NVRAMLidDB_XML")
+    record_file = cf.get("Config", "IntegrityCheckLog")
+    db = DBParser(xml_file)
+    
+    # Find No description struct =>{name: [offset1, offset2...]}
+    no_desc_struct_map = {}
+    for struct_name in db.structs:
+        result = parse_struct(db, struct_name)
+        if result:
+            if struct_name not in no_desc_struct_map:
+                no_desc_struct_map[struct_name] = result
+            else:
+                no_desc_struct_map[struct_name].extend(result)
+                # use twice (TOP STRUCT?)
+                pdb.set_trace()
+    
+    print("No description len:{} List : ".format(len(no_desc_struct_map.keys()) ))
+    print("-------"*10)
+    
+    # Collect mulit use struct
+    # for k, v in parentRelation.items():
+        # if len(v) > 1:
+            # mulit_use_struct.append(k)
+    content = []
+    Top_structs = {}
+    # 
+    for struct in no_desc_struct_map:
+        if TAG_BY_PASS and struct in db.bypass_struct:
+            continue
+        else:
+            get_top_struct(db, struct, no_desc_struct_map, Top_structs, content)
+            
+    for top_struct in Top_structs.keys():
+        real_lids = get_rel_lid(db, top_struct)
+        if not real_lids:
+            continue
+        for lid in real_lids:
+            NoDesLids[lid] = Top_structs[top_struct]
+    print("Find lid spend: {}".format(time.time()- start))
+    
+    # print("Write log file: {}".format(record_file) )
+    print("Write log file: {}".format(record_file) )
+    # mulit_use_struct = list(set(mulit_use_struct))
+    with open(record_file, "w") as f:
+        # f.write("mulit used structs count: {}struct list: \n".format(len(mulit_use_struct)))
+        # f.write(json.dumps(mulit_use_struct)+"\n")
+        # ----
+        f.write("-----------------No DESC list: {}----------------------\n".format(len(no_desc_struct_map.keys() )))
+        tmp_str = "\t".join(no_desc_struct_map)
+        f.write(tmp_str)
+        if NoDesLids:
+            STATUS = ERR_ERROR
+            f.write("\n-----------------Total LID count: {}-------------------------\n".format(len(NoDesLids.keys())))
+            f.write("LID NAME LIST: \n\t")
+            total_lids = NoDesLids.keys()
+            total_lids.sort()
+            content = "\n\t".join(total_lids)
+            f.write(content)
+            f.write("\n--------------------------Detail------------------------\n")
+            for k, v in NoDesLids.items():
+                f.write("\n{}:\n\t".format(k))
+                content = "\n\t".join(v)
+                f.write(content)
+    return NoDesLids
+
+if __name__ == "__main__":
+    main()
diff --git a/mcu/tools/NVRAMStatistic/nvram_gen_excel/nvram_gen_LID_description_to_excel.py b/mcu/tools/NVRAMStatistic/nvram_gen_excel/nvram_gen_LID_description_to_excel.py
new file mode 100644
index 0000000..8c30d07
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_gen_excel/nvram_gen_LID_description_to_excel.py
@@ -0,0 +1,1810 @@
+import sys, os, shutil, gc, traceback
+import re
+import json
+
+import glob, gzip
+import ConfigParser
+import time, datetime
+import zipfile
+import platform
+import getopt
+import pdb 
+import sqlite3
+from collections import namedtuple, OrderedDict
+try:
+    import xml.etree.cElementTree as ET
+except ImportError:
+    import xml.etree.ElementTree as ET
+
+
+# Global init ==============================================================
+app_version = "v1.1.8_20180119"
+
+OutputArray = False
+OutputBit = False
+BypassNoDes = False
+DebugMode = False
+
+build_path = ""
+gen_nvram_tool_path = ""
+
+IsCustomer = False
+
+# LID attribute
+# NVRAM_ATTR_AVERAGE          0x00000000UL
+NVRAM_ATTR_MULTI_DEFAULT = 0x00000001
+# NVRAM_ATTR_WRITEPROTECT     0x00000002UL
+# NVRAM_ATTR_MULTIPLE         0x00000004UL
+# NVRAM_ATTR_CONFIDENTIAL     0x00000008UL
+# NVRAM_ATTR_MULTIREC_READ    0x00000010UL
+# NVRAM_ATTR_MSP              0x00000020UL /* Protected by MTK Secure Platform */
+NVRAM_ATTR_OTA_RESET =         0x00000040
+# NVRAM_ATTR_GEN_DEFAULT      0x00000080UL
+# NVRAM_ATTR_RING             0x00000100UL
+# NVRAM_ATTR_PACKAGE          0x00000200UL /* NVRAM Reserved.LID will package in file */
+# NVRAM_ATTR_BACKUP_FAT       0x00000400UL /* Put a copy into backup partition, and the format is FAT */
+# NVRAM_ATTR_BACKUP_RAW       0x00000800UL /* Put a copy into backup partition, and the format is Raw data */
+# NVRAM_ATTR_RESERVE_BACKWARD 0x00001000
+# NVRAM_ATTR_FAULT_ASSERT     0x00002000
+
+NVRAM_CATEGORY_FUNC_DEFAULT = 0x00000400
+
+# Struct description tag 
+TAG = {"MCF":0x1,"LOCK":0x2, "RUNTIME":0x4, "DOC":0x8, "INTERNAL":0X10, "TIER1":0x20}
+
+ERR_OK, ERR_ERROR = [0, 1]
+STATUS = ERR_OK
+
+lid_default = ""
+ParseEditor = False
+gcc_include = ""
+lid_default = ""
+TAG_CONFLICT = {}
+
+# EditorParser Class =======================================================
+class EditorParser:
+  """
+  collect LID description & information
+  """
+  def __init__(self, lines=None):
+    self.offset = 0
+    # header: [lid_name, description, information]
+    self.header = ['','','']
+    self.lines = lines      # .split('\n')
+  
+  def FindLidHeader(self):
+    """Find LID editor section start lines"""
+    # LID head editor start line: '* NVRAM_EF_DRP_IMS_PROFILE_LID'
+    head_p = re.compile(r"(\*)\s*NVRAM_EF_[A-Z\d_]+_LID")
+    head_lines = filter(head_p.match, self.lines)
+    return head_lines
+    
+  
+  def GetLidHeader(self, head_line):
+    # parse lid description & information from lid description header
+    self.header = ["", "", ""]
+    index = self.lines.index(head_line)
+    self.header[0] = self.lines[index].replace("*", "").strip()
+    desc = False
+    info_index = -1
+    for line in self.lines[index+1:]:
+        if not line.startswith("*"):
+            break
+        if "DESCRIPTION" in line:
+            desc = True
+            continue
+        if 'INFOMATION' in line or 'INFORMATION' in line:
+            info_index = self.lines.index(line) + 1
+            break
+        if desc:
+            self.header[1] += line.replace("*", "").strip()
+            continue 
+    if info_index:
+        tmp_info = "".join(self.lines[info_index: info_index+2])
+        self.header[2] = tmp_info.replace("*", "").strip()
+    return self.header
+
+# StructEntry Class ========================================================
+class StructEntry(object):
+  TAG_Y = 'Y'
+  TAG_N = 'N'
+  def __copy(self, CopyFrom=None):
+    self.name = CopyFrom.name
+    self.description = CopyFrom.description
+    self.offset = CopyFrom.offset
+    self.size = CopyFrom.size
+    self.bit_data = CopyFrom.bit_data
+    self.bit_offset = CopyFrom.bit_offset
+    self.bit_count = CopyFrom.bit_count
+    self.byte_offset = CopyFrom.byte_offset
+    self.array_size = CopyFrom.array_size
+    # copy struct tag -------
+    self.tag = CopyFrom.tag
+    self.parent_tag = CopyFrom.parent_tag
+    self.application_note = CopyFrom.application_note
+    self.is_bit_data = CopyFrom.is_bit_data
+    
+  def __init__(self, CopyFrom=None):
+    if(CopyFrom == None):
+      self.name = ""
+      self.description = ""
+      self.offset = 0
+      self.size = 0
+      self.bit_data = []
+      self.bit_offset = 0
+      self.bit_count = 0
+      self.byte_offset = 0
+      self.array_size = 0
+      # struct tag --------  
+      self.tag = 0
+      self.parent_tag = 0
+      self.application_note = ""
+      self.is_bit_data = False
+    else:
+      self.__copy(CopyFrom)
+      
+  def CopyFrom(self, CopyFrom):
+    self.__copy(CopyFrom)
+    
+  def __str__(self):
+    return "name: {}, offset: {}".format(self.name, self.offset)
+    
+  def __repr__(self):
+    return "name: {}, offset: {}".format(self.name, self.offset)
+
+    
+# MDDBParser Class
+class MDDBParser:
+
+    # Secure lid description file
+    SECURE_LID_FILES = ["interface/service/nvram/l4_nvram_editor.h", 
+            "interface/service/nvram/nvram_editor_data_item.h"]
+    SEC_XML = "../NVRAM_LID_structure_map.xml"
+
+    def __init__(self, filename=None):
+        """
+        Load MDDB file
+        collect security lids
+        parse and merge security struct description into MDDB
+        Coeect NVRAM groups
+        """
+        global gen_nvram_tool_path
+        self.secure_lids = []
+        self.inter_use = "@INTERNAL_USE@"
+        self.ap_noti_mark = "AN:"
+        self.groups = {}
+        self.group_lid_map = {}
+        self.description_deep = 0
+        self.entry_deep = 0
+        
+        self.lidDB_tree = ET.ElementTree(file=filename)
+        self.root = self.lidDB_tree.getroot()
+        self.lid_info_dom = self.lidDB_tree.find('LID_INFO')
+        lid_doc = ET.Element("ROOT")
+        lid_doc.append(self.lid_info_dom)
+        if DebugMode:
+          # Record LID_INFO IN MDDB
+          temp_file_name = ""
+          filename_split_array = ""
+          if(platform.system() == "Windows"):
+            filename_split_array = filename.split("\\")
+          else:
+            filename_split_array = filename.split("/")
+          temp_file_name = filename_split_array[-1]
+          temp_lid_doc_file_name = gen_nvram_tool_path + "/CAT_" + temp_file_name
+          WriteEelementDoc(lid_doc,temp_lid_doc_file_name)
+        
+        # Create LIDs dict
+        self.LIDs = list(self.root.iter('NVRAM_LID'))
+        self.lid_names = [item.get("name") for item in self.LIDs]
+        
+        self.Structs = {item.get("name"):list(item.iter("Field"))  for item in self.root.iter("Struct")}
+        self.Unions = {item.get("name"):item.find("Field")  for item in self.root.iter("Union")}
+        self.Typedefs = {item.get("name"):item.get("defined_type_name")  for item in self.root.iter("Typedef")}
+        self.Platform = {item.get("name"):item.get("value")  for item in self.root.iter("Information")}
+        
+        # Merge secure LIDs in
+        if ParseEditor:
+            nvram_lids_element = self.root.find("*/NVRAM_LIDs")
+            secure_lids_iter = self.load_secure_lid()
+            for sec_lid in secure_lids_iter:
+                if sec_lid.get("name") not in self.lid_names:
+                    self.secure_lids.append(sec_lid)
+                    self.LIDs.append(sec_lid)
+                    nvram_lids_element.append(sec_lid)
+            # parse secure lid structure description join into DB
+            self.SecureEditorParser()
+            # if DebugMode:
+            if build_path:
+                temp_file_name = build_path + "/nvram_auto_gen/MDDB_with_secure.xml"
+            else:
+                temp_file_name = "MDDB_with_secure.xml"
+            WriteEelementDoc(self.root, temp_file_name)
+        
+        # Find all NVRAM Groups
+        self.parse_group_map()
+        self.entry_type = ''
+        self.lid_type = 'NULL'
+  
+    def GetLidInfo(self, idx):
+        if(idx >= len(self.LIDs)):
+            return -1
+        self.id = self.LIDs[idx].get("id")
+        self.lid_name = self.LIDs[idx].get("name")
+        self.lid_type = self.LIDs[idx].get("type_name")
+        
+        self.record_count = 1   # int(self.LIDs[idx].getAttribute("record_count"))
+        self.description_deep = 0
+        self.entry_deep = 0
+        info_lid = self.lid_info_dom.find(self.lid_name)
+        
+        if info_lid is not None:
+            self.hex_attr = int(info_lid.get('attribute'), 16)
+            category = info_lid.get('category')
+            self.hex_category = int(category, 16) if category else 0
+            if not self.id:
+                self.id = info_lid.get("lid_enum")
+        else:
+            self.hex_attr = 0
+            self.hex_category = 0
+        
+        # Lid which has attr 'mulit_default' expand all records 
+        self.mulit_default = self.AttrMatch(NVRAM_ATTR_MULTI_DEFAULT)
+        self.function_default = self.CategoryMatch(NVRAM_CATEGORY_FUNC_DEFAULT)
+        if self.mulit_default:
+            self.record_count = int(self.LIDs[idx].get("record_count")) 
+        if self.function_default: 
+            self.record_count = 1
+        # Collection lid group map info 
+        if self.id:
+            self.FindLidGroup()
+        elif DebugMode:
+            print("WARNNING: LID {} DON'T FIND ENUM!".format(self.lid_name) )
+        return idx
+  
+    def CategoryMatch(self, category=NVRAM_CATEGORY_FUNC_DEFAULT):
+        """attribute match"""
+        return self.hex_category & category
+        
+    def AttrMatch(self, attr=NVRAM_ATTR_MULTI_DEFAULT):
+        """attribute match"""
+        return self.hex_attr & attr
+      
+    def GetPlatformInfo(self, infoName):
+        if infoName in self.Platform:
+            return self.Platform[infoName]
+        return ""
+
+    def ConvertTypedef(self, typeName):
+        while typeName in self.Typedefs:
+            tmpName = self.Typedefs[typeName]
+            if tmpName != typeName:
+                typeName = tmpName
+            else:
+                # typedef define_type_name == name
+                break
+        return typeName
+        
+    def ConvertArray(self, arrayStr, baseStr="", entryRet=[]):
+        if(arrayStr == "" or OutputArray == False):
+          return [""]
+        if(baseStr == ""):
+          entryRet = []
+        s = arrayStr.find(",")  
+        cnt = int(arrayStr) if(s == -1) else int(arrayStr[0:s])
+        for i in range(0, cnt):
+          if(s == -1):
+            entryRet.append(baseStr + "[" + str(i) + "]")
+          else:
+            self.ConvertArray(arrayStr[s+1:], baseStr + "[" + str(i) + "]", entryRet)
+        return entryRet
+  
+    def RecursiveBitEntry(self, entry, entry_idx, type_name):
+        tmp_bits = []
+        parent_node = entry[entry_idx]
+        entries = entry[entry_idx].bit_data
+        pre_name = entry[entry_idx].name
+        pre_size = entry[entry_idx].size
+        pre_description = entry[entry_idx].description
+        pre_array_size = entry[entry_idx].array_size
+        for i in range(0, len(entries)):
+          one_bit = StructEntry()
+          tmp_bits.append(one_bit)
+          # entry_idx = (len(tmp_bits) - 1)
+          one_bit.is_bit_data = True
+          one_bit.byte_offset = int(entries[i].get("byte_offset"))
+          one_bit.bit_offset = int(entries[i].get("bit_offset"))
+          one_bit.bit_count = int(entries[i].get("bit_count"))
+          one_bit.description = entries[i].get("description")
+          one_bit.parent_tag = parent_node.tag
+          self._description_handler(one_bit)
+          
+          one_bit.offset = 0
+          one_bit.size = pre_size
+          one_bit.bit_data = entries[i].findall("Bit_Value")
+          # one_bit.array_size = pre_array_size
+          
+          # tmp_bits[entry_idx].byte_offset -= pre_offset
+          one_bit.bit_name = entries[i].get('name')
+          # one_bit.name = pre_name + "[" + str(one_bit.byte_offset / pre_array_size) + "]:" + one_bit.bit_name
+        return tmp_bits
+
+    def ReturnStructEntry(self, structName):
+        structName = self.ConvertTypedef(structName)
+        if(self.Structs.has_key(structName) == True):
+          return self.Structs[structName]
+        if(self.Unions.has_key(structName) == True):
+          return [self.Unions[structName]]
+        
+        return []
+        
+    def RecursiveStructEntry(self, entry, entry_idx, type_name, deep, deep_limit):
+        if(deep_limit < 1):
+          return []
+        # record parent_node info
+        parent_node = entry[entry_idx]
+        entries = self.ReturnStructEntry(type_name)
+        pre_name = entry[entry_idx].name
+        for i in range(0, len(entries)):
+          if(entries[i].get("type") in ["struct","union"]):
+            array = entries[i].get("array_sizes", "")
+            array = self.ConvertArray(array)
+          else:
+            array = [""]
+          array_size = entries[i].get("array_sizes", "")
+          array_size = len(self.ConvertArray(array_size))
+          array_size = 1 if(array_size == '') else int(entries[i].get("size"))/int(array_size)
+          tmp_entry = []
+          one_entry = StructEntry()
+          tmp_entry.append(one_entry)
+          one_entry.description = entries[i].get("description", "")
+          one_entry.parent_tag = parent_node.tag
+          if one_entry.description:
+            self._description_handler(one_entry)
+          else:
+            one_entry.tag = parent_node.tag
+          if(self.entry_deep < deep):
+              self.entry_deep = deep
+            
+          if one_entry.description and (self.description_deep < deep):
+            print("self.description_deep +1 : {}".format(entries[i].get("name")))
+            self.description_deep = deep
+          one_entry.size = (int(entries[i].get("size")) / len(array))
+          bit_data = entries[i].findall("NVRAM_Bit_Data")
+          
+          if entries[i].get("type") not in ["struct"]:
+            one_entry.bit_data = entries[i].findall("NVRAM_Bit_Data")
+          elif bit_data:
+            print("[Error] field have bit data and not STRUcT")
+            pdb.set_trace()
+          one_entry.array_size = array_size
+          if(entries[i].get("type") in ["struct","union"]):
+            type_name = entries[i].get("type_name")
+            self.RecursiveStructEntry(tmp_entry, 0, entries[i].get("type_name"), (deep + 1), (deep_limit - 1))
+          else:
+            if((len(one_entry.bit_data) > 0) and OutputBit):
+              # assert all bit data under top struct
+              pdb.set_trace()
+              recursive_bits = self.RecursiveBitEntry(tmp_entry, 0, entries[i].get("type_name"))
+              tmp_entry += recursive_bits
+          tmp_offset = int(entries[i].get("offset")) if entries[i].get("offset", "") else 0 
+          if entries[i].get("offset", "") == "":
+            print("struct item not find offset: {}".format(entries[i].get("name") ))
+          for j in range(0, len(array)):
+            for k in range(0, len(tmp_entry)):
+              entry.append(StructEntry(tmp_entry[k]))
+              entry_idx = (len(entry) - 1)
+              entry[entry_idx].name = pre_name + "." + entries[i].get("name") + array[j] + tmp_entry[k].name
+              entry[entry_idx].offset = tmp_entry[k].offset + tmp_offset
+            tmp_offset += array_size
+          del tmp_entry, tmp_offset, array_size, array
+        
+    def GetLidStructure(self, deep_limit):
+        if(deep_limit < 1):
+          return []
+        if(self.entry_type == self.lid_type):
+          return self.entry
+        self.description_deep = 0
+        self.entry_deep = 0
+        self.entry = []
+        entries = self.ReturnStructEntry(self.lid_type)
+        self.entry = []
+        for i in range(0, len(entries)):
+          # Array output Only for struct,union
+          if(entries[i].get("type") in ["struct","union"]): 
+              array = entries[i].get("array_sizes", "")
+              array = self.ConvertArray(array)
+          else:
+              array = [""]
+          field_name = entries[i].get("name")
+          array_size = entries[i].get("array_sizes", "")
+          array_size = len(self.ConvertArray(array_size))
+          array_size = 1 if(array_size == '') else int(entries[i].get("size"))/int(array_size)
+          tmp_entry = []
+          one_entry = StructEntry()
+          tmp_entry.append(one_entry)
+          # handle description
+          one_entry.description = entries[i].get("description", "").strip()
+          if one_entry.description:
+            self._description_handler(one_entry)
+            if self.description_deep == 0:
+                self.description_deep = 1
+            
+          if(self.entry_deep == 0):
+            self.entry_deep = 1
+          one_entry.size = (int(entries[i].get("size")) / len(array))
+          one_entry.bit_data = entries[i].findall("NVRAM_Bit_Data")
+          one_entry.array_size = array_size
+          field_type = entries[i].get("type")
+          
+          if field_type in ["struct","union"]:
+            tmp_name = entries[i].get("type_name")
+            self.RecursiveStructEntry(tmp_entry, 0, entries[i].get("type_name"), 2, (deep_limit - 1))
+          
+          # recursive_bits = {offet: [bit_obj1,..]}
+          recursive_bits = OrderedDict()
+          if one_entry.bit_data and OutputBit:
+            bit_datas = self.RecursiveBitEntry(tmp_entry, 0, entries[i].get("type_name"))
+            for item in bit_datas:
+                bit_offset = item.byte_offset 
+                recursive_bits.setdefault(bit_offset, []).append(item)
+          recursive_bits_offset = recursive_bits.keys()
+          recursive_bits_offset.sort()  
+          tmp_entry[0].bit_data = []
+          
+          tmp_offset = int(entries[i].get("offset"))
+          field_entry = []
+          pre_offset = 0
+          for j in range(0, len(array)):
+            for k in range(0, len(tmp_entry)):
+              one_entry = StructEntry(tmp_entry[k])
+              one_entry.name = field_name + array[j] + tmp_entry[k].name
+              cur_offset = tmp_entry[k].offset + tmp_offset
+              one_entry.offset = cur_offset
+              # Add bit datas
+              if cur_offset != pre_offset and recursive_bits_offset:
+                tmp_bit_data = {}
+                for offset in recursive_bits_offset:
+                    if offset < cur_offset:
+                        tmp_bit_data[offset] = recursive_bits[offset]
+                        recursive_bits_offset.remove(offset)
+                        del recursive_bits[offset]
+                    else:
+                        break
+                if tmp_bit_data:
+                    pre_entry = field_entry[-1]
+                    self._bit_data_merge(pre_entry, tmp_bit_data, field_entry)
+                pre_offset = cur_offset
+              field_entry.append(one_entry)
+            tmp_offset += array_size
+          if recursive_bits:
+            pre_entry = field_entry[-1]
+            self._bit_data_merge(pre_entry, recursive_bits, field_entry)
+          self.entry += field_entry
+        # print("entry_deep:{}, description_deep:{}".format(self.entry_deep, self.description_deep))
+        # Rebuild entry
+        if(BypassNoDes and (self.description_deep < self.entry_deep)):
+          print("second get lid structure:{}".format(self.lid_name))
+          del self.entry
+          self.entry = self.GetLidStructure(self.description_deep)
+        self.entry_type = self.lid_type
+        return self.entry
+                
+    def _bit_data_merge(self, item, bit_datas, field_entry, is_struct=False):
+        """
+      item: Parent node
+      bit_datas: {real_offset: [b1, b2..]}
+      """
+        name_flag = False if '.' in item.name else True
+        for offset, bit_items in bit_datas.items():
+            # bit_items = bit_datas[offset]
+            for bit_item in bit_items:
+                # item.description = bit_item.description
+                # TAG and description update to bit data's description
+                if not OutputBit:
+                    item.bit_data.extend(bit_item.bit_data)
+                bit_item.name = item.name +"." + bit_item.bit_name
+                bit_item.offset = offset  
+                bit_item.byte_offset = 0    
+                field_entry.append(bit_item)
+
+    def _description_handler(self, one_entry):
+        """description handle:
+        replace str: @INTER_USE@
+        extract application notifaction: xxxx AN:xxxxx
+        TAG match
+        """
+        # DELETE STR INTER_USE
+        if self.inter_use in one_entry.description:
+            one_entry.description = one_entry.description.replace(self.inter_use, "")
+        # parse application notification (default_format: this is desc AN:xxxxxx)
+        if self.ap_noti_mark in one_entry.description:
+            one_entry.description, one_entry.application_note = one_entry.description.split(self.ap_noti_mark)
+        self.TagMatch(one_entry)
+        
+    def TagMatch(self, current_node):
+        """tag match:current struct tag=current_node.tag|current_node.parent_tag"""
+        if current_node.description:
+            description = current_node.description
+            tag_pattern = re.compile(r"\[[a-zA-Z,\d\s]+\]")
+            tag_strs = tag_pattern.findall(description)
+            for tag_str in tag_strs:
+                tmp_tag = tag_str
+                flag = 0
+                tag_str = re.sub(r"[\[\]]", "", tag_str)
+                tag_str = [item.strip() for item in tag_str.split(",")]
+                for item in tag_str:
+                    if item in TAG:
+                        current_node.tag = current_node.tag|TAG[item]
+                        flag = 1
+                if flag:
+                    current_node.description = current_node.description.replace(tmp_tag, "")
+            # current_node.description = re.sub(r"[\[\]]", "", current_node.description)
+        current_node.tag = current_node.tag|current_node.parent_tag
+        return current_node.tag
+        
+    def parse_group_map(self):
+        """parse group-lid mapping
+        group_line: #define NVRAM_LID_GRP_C2K(x)                (0xE400 | (0x00FF & x))     //CK 
+       """
+        # add GRP
+        group_line = re.compile(r"#define\s*NVRAM_LID_GRP[A-Z_\d]+\(x\)\s*\(0x[\dA-F]+\s*\|.*\)")
+        group_value = re.compile(r"\(0x[\dA-F]+\s*\|\s*\(0x[\dA-F]+\s*&.*\)\)")
+        group_pattern = re.compile(r"NVRAM_LID_GRP[A-Z_\d]+")
+        group_file = "nvram_enums.h"
+        # LR13.R1.NVRAM.DESCIPTION.DEV\mcu\interface\service\nvram
+        fullpath = gen_nvram_tool_path+ "/../../../interface/service/nvram/"+ group_file
+        # print("group file path: {}".format(fullpath))
+        content = ""
+        if not os.path.exists(fullpath):
+            print("parse group Error: file {} not exists!".format(fullpath) )
+            return
+        with open(fullpath, "r") as f:
+            content = f.readlines()
+        content = (item.strip() for item in content if item.strip())
+        group_define = filter(group_line.match, content)
+        
+        for line in group_define:
+            one_group = group_pattern.search(line)
+            if not one_group:
+                print("Error: group line not found Group.", line)
+                continue
+            else:
+                one_group = one_group.group()
+            value_section = group_value.search(line).group()
+            value_section = re.sub(r'[\(\)]', '', value_section)
+            min_addr, max_addr = value_section.split("|")
+            max_addr = max_addr.split("&")[0]
+            min_addr = int(min_addr, 16)
+            max_addr = min_addr + int(max_addr, 16)
+            # self.groups[min_addr] = {"name": group_name, "max": max_addr}
+            self.groups[min_addr] = {"name": one_group, "max": max_addr}
+        # self.sort_group_by_min(groups)
+        print("self.groups: {}", len(self.groups.keys()))
+        
+    def FindLidGroup(self):
+        """find lid group by lid id from DB"""
+        flag = False
+        sort_group = sorted(self.groups.keys())
+        for item in sort_group:
+            if item > int(self.id):
+                flag = True
+                break
+        if flag:
+            group_index = sort_group.index(item)
+            group_min = sort_group[group_index-1]  # min address
+        else:
+            group_min = sort_group[-1]
+        tmp_group = self.groups[group_min]
+        assert int(self.id) in range(group_min, tmp_group["max"])
+        _add_item_to_dict(self.group_lid_map, tmp_group['name'], [self.lid_name, self.id])
+    
+    def SecureEditorParser(self):
+        """Parse secure LID structure description and merge into MDDB structure"""
+        sec_lid_type_map = {item.get("name"): item.get("type_name") for item in self.secure_lids} 
+        
+        # mcu path
+        build_path = gen_nvram_tool_path + "/../../.."
+        # regular pattern
+        line_re = re.compile(r"LID_BIT[\sA-Z_]*VER_LID\s*\(NVRAM_EF_[A-Z\d_]+_LID\)")
+        lid_re = re.compile(r"NVRAM_EF_[A-Z\d_]+_LID")
+        for editor_file in self.SECURE_LID_FILES:
+            file_path = build_path + "/" + editor_file
+            if not os.path.exists(file_path):
+                print("editor file: {} not found in disk Bypass!".format(file_path))
+                continue
+            with open(file_path) as f:
+                content = f.readlines()
+            content = [item.strip() for item in content]
+            # Match all LID description in editor 
+            matched = filter(line_re.match, content)
+            for index in range(0, len(matched)):
+                match_item = matched[index]
+                lid_name = lid_re.search(match_item).group()
+                if lid_name not in sec_lid_type_map:
+                    continue
+                start_index = content.index(match_item)
+                # Lid code section
+                if index == len(matched)-1:
+                    section = content[start_index:]
+                else:
+                    end_line = content.index(matched[index+1])
+                    if end_line > start_index:
+                        section = content[start_index: end_line]
+                    else:
+                        # ASSERT never hit
+                        pdb.set_trace()
+                        next_matched = filter(line_re.match, content[start_index+1:])
+                        end_line = content[start_index: ].index(next_matched[1])
+                        section = content[start_index: start_index+end_line]
+                # Find lid structure description
+                struct_name_description_map = self.parse_editor_description(section)
+                if struct_name_description_map:
+                    # if DebugMode :
+                    tmp_secure_desc = "tmp_secure_desc.json"
+                    with open(tmp_secure_desc, "a+") as f:
+                        f.write("LID: {}\n".format(lid_name))
+                        f.write(json.dumps(struct_name_description_map)+"\n")
+                        f.write("--------------------------------------------\n")
+                # merge editor description into DB
+                    entries = self.ReturnStructEntry(sec_lid_type_map[lid_name])
+                    self.merge_description(entries, struct_name_description_map)
+ 
+    def merge_description(self, entries, description_map):
+        """merge description map into MDDB XML structure
+        According to name
+        """
+        for name in description_map.keys():
+            name_list = name.split(".")
+            struct_entry = entries
+            flag = False
+            offset = 0
+            # Bit data that should be joined under top structure
+            Bit_datas = []
+            cur_offset = 0
+            top_entry = None
+            # Find top entry
+            for name_item in name_list: 
+                flag = False
+                for entry in struct_entry:
+                    cur_entry_name = entry.get("name")
+                    if cur_entry_name == name_item:
+                        flag = True
+                        break
+                if flag:
+                    child_struct = entry.get("type_name")
+                    struct_entry = self.Structs[child_struct] if child_struct in self.Structs else []
+                else:
+                    # TODO type=union serach from union list
+                    print("struct :{} in editor not found in db".format(name))
+                    pdb.set_trace()
+                    break
+            if flag:     # Find it
+                entry.set("description", description_map[name]["description"])
+                cur_offset = int(entry.get("offset"))
+                # TODO [0] one array only
+                if description_map[name]["bit_data"]:
+                    self.check_bit_offset(description_map[name]["bit_data"], entry, offset, cur_offset)
+                    Bit_datas = description_map[name]["bit_data"]
+                offset += cur_offset
+            if Bit_datas:
+                # find top struct
+                top_struct = None
+                for entry in entries:
+                    if entry.get("name") == name_list[0]:
+                        top_struct = entry
+                        break
+                try:
+                    assert top_struct is not None
+                except Exception as e:
+                    print e
+                    pdb.set_trace()
+                # All Bit data under top struct
+                under_bit_datas = entry.findall("NVRAM_Bit_Data")
+                for new_bit in Bit_datas:
+                    flag = False
+                    for db_bit in under_bit_datas:
+                        db_bit_name = db_bit.get("name")
+                        db_bit_offset = db_bit.get("byte_offset")
+                        # According name and offset confirm one bit data
+                        if db_bit_name == new_bit["name"] and db_bit_offset == new_bit["byte_offset"]:
+                            flag = True
+                            break
+                    if flag:
+                        if new_bit["description"]:
+                            db_bit.set("description", new_bit["description"])
+                        if new_bit["bit_value"]:
+                            bit_values = db_bit.findall("Bit_Value")
+                            bit_values = {item.get("value"): item for item in bit_values}
+                            for new_value in new_bit["bit_value"]:
+                                if new_value["name"] in bit_values:
+                                    bit_values[new_value["name"]].set("description", new_value["description"])
+                    else:
+                        # Bit data not found under top strut, add new dom
+                        new_bit_dom = self._gen_bit_xml_dom(new_bit)
+                        top_struct.append(new_bit_dom)
+                Bit_datas = []
+                
+    def _gen_bit_xml_dom(self, bit_dict):
+        """translate bit_dict to xml dom object
+        bit_dict:{name: xx, description:xx, bit_count:xx, byte_offset: xx,
+                bit_value:[{name: bb, description: xx},..]
+        return: NVRAM_Bit_Data dom include bit_value if bit data have bit_value
+        }
+        """
+        bit_data = ET.Element("NVRAM_Bit_Data")
+        # bit data dom init
+        bit_data.set("name", bit_dict.get("name"))
+        description = bit_dict.get("description", "")
+        if description:
+            bit_data.set("description", description)
+        bit_data.set("byte_offset", bit_dict.get("byte_offset"))
+        bit_data.set("bit_count", bit_dict.get("bit_count"))
+        bit_data.set("bit_offset", bit_dict.get("bit_offset"))
+        if bit_dict.get("bit_value", ""):
+            bit_values = bit_dict.get("bit_value")
+            for bit_item in bit_values:
+                value_dom = ET.SubElement(bit_data, "Bit_Value")
+                value_dom.set("value", bit_item.get("name"))
+                value_dom.set("description", bit_item.get("description", ""))
+        return bit_data
+            
+    def check_bit_offset(self, bit_description_list, entry, base_offset, parent_offset):
+        """offset: parent base offset
+        not merge into DB, just update offset
+        """
+        # TODO size="1, 2"
+        field_array = int(entry.get("array_sizes")) if entry.get("array_sizes") else 0
+        if field_array:
+            size = int(entry.get("size"))/ field_array
+        else:
+            size = int(entry.get("size"))
+       # For bit_offset
+        pre_bit_count = 0
+        pre_bit_offset = 0
+        pre_byte_offset = 0
+        for bit_item in bit_description_list:
+            array = bit_item.get("array", "")
+            if array:
+                # TODO [0][0] not conside
+                array = int(array[1:-1])
+                cur_offset = base_offset + (array * size + parent_offset)
+            else:
+                cur_offset = base_offset + parent_offset
+            bit_item["byte_offset"] = str(cur_offset)
+            if cur_offset == pre_byte_offset:
+                pre_bit_offset = pre_bit_count + pre_bit_offset
+            else:
+                # New bit begin bit_offset begin from 0
+                pre_bit_offset = 0
+            pre_bit_count = int(bit_item.get("bit_count"))
+            bit_item["bit_offset"] = str(pre_bit_offset)
+            pre_byte_offset = cur_offset
+
+    def parse_editor_description(self, section):
+        """find struct_name and description mapping from editor code section
+        regular:
+            Field:          "name": "description"
+            NVRAM_Bit_Data: "name": bit_count + "description" 
+            bit_value:      "0x ": description
+        result_map(dict)=> 
+        name: 
+            {   description: desc, 
+                Bit_data:[{name: desc}]}
+        """
+        result_map = {}
+        parent_name = "" 
+        bit_data = {}
+        is_array = False
+        # bit_data_re regular to match bit_data name
+        bit_data_re = re.compile(r".+(\s*):(\s*)\d")
+        bit_value_re = re.compile(r"^0x\d+")
+        array_re = re.compile(r"[a-zA-Z_\d\.]+(\[\d\])+")       # Match format like: a.b.c[0][1] {};
+        
+        for line in section:
+            line = re.sub(r'[";\{\}]', "", line)
+            if not line:
+                continue
+            if ":" not in line:
+                # Try to match array  => array[0] {} TODO array[*]
+                array_line = array_re.match(line)
+                # pdb.set_trace()
+                if array_line:
+                    is_array = array_line
+                    is_array = is_array.group()
+                    assert parent_name in is_array
+                    is_array = is_array[len(parent_name):].strip()
+                continue
+            # match bit data
+            bit_name = bit_data_re.match(line)
+            if bit_name:
+                # if have bit data didn't join result map join it
+                if bit_data:
+                    result_map[parent_name]["bit_data"].append(bit_data)
+                    bit_data = {}
+                bit_name = bit_name.group()
+                name, bit_count = bit_name.split(":")
+                description = line[len(bit_name):].strip()
+                bit_data = {"name": name, "bit_count":bit_count.strip(), 
+                    "description":description, "bit_value":[], "array": is_array}
+            elif bit_value_re.match(line):
+                # bit value data: add into bit data list
+                name = bit_value_re.match(line).group()  # 0x
+                value = line[len(name)+1:]
+                name = str(int(name, 16))
+                value = ":".join([name, value])
+                bit_data["bit_value"].append({"name":name, "description":value})
+            else:
+                if bit_data:
+                    # bit data join result_map
+                    result_map[parent_name]["bit_data"].append(bit_data)
+                    bit_data = {}
+                    # parent_name = ""
+                index = line.find(":")
+                key = line[:index].strip()
+                if "*" in key:
+                    continue
+                value = line[index+1:]
+                # TODO struct A: no description but A have bit data 
+                result_map[key] = {"description": value.replace('"', ''), "bit_data":[]}
+                parent_name = key
+                is_array = False
+        # Merge last bit data in 
+        if bit_data and parent_name:
+            result_map[parent_name]["bit_data"].append(bit_data)
+        return result_map
+        
+    def load_secure_lid(self):
+        """
+        Load security LID xml return all NVRAM_LID iter
+       """
+        SEC_XML = gen_nvram_tool_path + "/" + self.SEC_XML
+        if not os.path.exists(SEC_XML):
+            print("Secure file: {} not exists, ByPass!".format(SEC_XML))
+            return []
+        secure_tree = ET.ElementTree(file=SEC_XML)
+        sec_lids = secure_tree.iter("NVRAM_LID")
+        return sec_lids
+
+# Excel Editor Class =======================================================
+class ExcelEditor():
+  row_pattern = [
+                '<row r="%%ROW_ID%%" spans="1:14" ht="30">'
+                '<c r="A%%ROW_ID%%" s="6" t="s"><v>%%STR_A%%</v></c>'
+                '<c r="B%%ROW_ID%%" s="18" t="s"><v>%%STR_B%%</v></c>'
+                '<c r="C%%ROW_ID%%" s="7" t="s"><v>%%STR_C%%</v></c>'
+                '<c r="D%%ROW_ID%%" s="7" t="s"><v>%%STR_D%%</v></c>'
+                '<c r="E%%ROW_ID%%" s="7" t="s"><v>%%STR_E%%</v></c>'
+                '<c r="F%%ROW_ID%%" s="7" t="s"><v>%%STR_F%%</v></c>'
+                '<c r="G%%ROW_ID%%" s="8" t="s"><v>%%STR_G%%</v></c>'
+                '<c r="H%%ROW_ID%%" s="9" t="s"><v>%%STR_H%%</v></c>'
+                '<c r="I%%ROW_ID%%" s="9" t="s"><v>%%STR_I%%</v></c>'
+                '<c r="J%%ROW_ID%%" s="9" t="s"><v>%%STR_J%%</v></c>'
+                '<c r="K%%ROW_ID%%" s="9" t="s"><v>%%STR_K%%</v></c>'
+                '<c r="L%%ROW_ID%%" s="9" t="s"><v>%%STR_L%%</v></c>'
+                '<c r="M%%ROW_ID%%" s="%%TAG_STYLE%%" t="s"><v>%%STR_M%%</v></c>'
+                '<c r="N%%ROW_ID%%" s="%%TAG_STYLE%%" t="s"><v>%%STR_N%%</v></c></row>',
+                
+                '<c r="M5" s="%%TAG_STYLE%%" t="s"><v>16</v></c>'
+                '<c r="N5" s="%%TAG_STYLE%%" t="s"><v>17</v></c></row>\n'
+                ]
+  col_name = [["A","%%STR_A%%"],["B","%%STR_B%%"],["C","%%STR_C%%"],["D","%%STR_D%%"],["E","%%STR_E%%"],
+                ["F","%%STR_F%%"],["G","%%STR_G%%"],["H","%%STR_H%%"],["I","%%STR_I%%"],
+                ["J","%%STR_J%%"],["K","%%STR_K%%"], ["L","%%STR_L%%"], ["M","%%STR_M%%"], ["N","%%STR_N%%"]]
+  def __init__(self, filename, isCustomer):
+    try:
+      self.filename = filename  
+      self.excel_template_file = gen_nvram_tool_path + "/nvram_gen_excel.xltx"
+      # self.excel_template_file = gen_nvram_tool_path + "/Macro_MD1.1.xltx"
+      zip_file = zipfile.ZipFile(os.path.realpath(self.excel_template_file))
+      zip_file.extractall(gen_nvram_tool_path + '/tmp')
+      zip_file.close()
+      
+      self.ShareString = ''
+      # self.ShareString_CntDef = 17
+      # self.ShareString_Cnt = 17
+      self.ShareString_CntDef = 18
+      self.ShareString_Cnt = 18
+
+      self.Sheet1 = ''
+      self.Sheet1Row_idx = 6
+      self.Sheet1Merge = ""
+      self.Sheet1Merge_Cnt = 0
+      # self.Sheet1Merge = '<mergeCell ref="B1:C1"/>\n<mergeCell ref="B2:C2"/>\n'
+      # self.Sheet1Merge_Cnt = 2
+
+      self.MTK_Version = ''
+      self.MTK_Project = ''
+      self.color = 0
+    except Exception as e:
+      print "ExcelEditor init fail."
+      print "Please check file nvram_gen_excel.xltx."
+      pause()
+      os._exit(0)
+    self.excel_tag = OrderedDict([("I", "LOCK"), ("J", "MCF"), ("K", "RUNTIME"), ("L", "DOC")])
+    self.inter_tag = OrderedDict([("M", "INTERNAL"), ("N", "TIER1")])
+    if not isCustomer:
+        for k, v in self.inter_tag.items():
+            self.excel_tag[k] = v
+    self.lid_details = []
+    return
+
+  def Save(self, last=None):
+    # write SharedStrings
+    f = open(gen_nvram_tool_path + '/tmp/xl/sharedStrings.xml','a+')
+    f.write(self.ShareString)
+    f.close()
+    self.ShareString = ''
+
+    # write sheet1
+    f = open(gen_nvram_tool_path + '/tmp/xl/worksheets/sheet1.xml','a+')
+    f.write(self.Sheet1)
+    f.close()
+    self.Sheet1 = ''
+    
+    # write sheet1.merge
+    f = open(gen_nvram_tool_path + '/tmp/xl/worksheets/sheet1_merge.xml','a+')
+    f.write(self.Sheet1Merge)
+    f.close()
+    self.Sheet1Merge = ''
+    
+    # compress to xlsx
+    if(last <> None):
+      f = open(gen_nvram_tool_path + '/tmp/xl/worksheets/sheet1_merge.xml','r')
+      sheet1_merge = f.read()
+      f.close()
+      if(len(sheet1_merge) > 0):
+        sheet1_merge = '<mergeCells count="' + str(self.Sheet1Merge_Cnt) + '">' + sheet1_merge + '</mergeCells>'
+      # os.remove('tmp/xl/worksheets/sheet1_merge.xml')
+      
+      f = open(gen_nvram_tool_path + '/tmp/xl/worksheets/sheet1.xml','a+')
+      f.write('</sheetData>')
+      f.write(sheet1_merge)
+      # f.write('<pageMargins left="0.7" right="0.7" top="0.75" bottom="0.75" header="0.3" footer="0.3"/></worksheet>')
+      f.write('<phoneticPr fontId="4" type="noConversion"/>'
+                    '<pageMargins left="0.7" right="0.7" top="0.75" bottom="0.75" header="0.3" footer="0.3"/>'
+                    '<pageSetup paperSize="9" orientation="portrait" r:id="rId1"/></worksheet>')
+      f.close()
+
+      f = open(gen_nvram_tool_path + '/tmp/xl/sharedStrings.xml','r')
+      fb = f.read(700)
+      fbe = f.read()
+      f.close()
+      fb = fb.replace('%%COUNT%%', str(self.ShareString_Cnt))
+      fb = fb.replace("%%MTK_VERSION%%", self.MTK_Version)
+      fb = fb.replace("%%MTK_PROJECT%%", self.MTK_Project)
+      if IsCustomer:
+        # fb = fb.replace("%%TAG_STYLE%%", str(1))
+        fb = fb.replace("%%INTERNAL%%", " ")
+        fb = fb.replace("%%TIER1%%", " ")
+      else:
+        # fb = fb.replace("%%TAG_STYLE%%", str(13))
+        fb = fb.replace("%%INTERNAL%%", "INTERNAL")
+        fb = fb.replace("%%TIER1%%", "TIER1")
+      f = open(gen_nvram_tool_path + '/tmp/xl/sharedStrings.xml','w')
+      f.write(fb)
+      f.write(fbe)
+      f.write('</sst>')
+      f.close() 
+      
+      try:
+        zip_file = zipfile.ZipFile(self.filename, 'w')
+        for root,dirs,files in os.walk(gen_nvram_tool_path + '/tmp'):
+          for f in files:
+            abs_path = os.path.join(os.path.join(root,f))
+            rel_path = os.path.relpath(abs_path, os.path.dirname(gen_nvram_tool_path + '/tmp/'))
+            zip_file.write(abs_path, rel_path, zipfile.ZIP_DEFLATED)
+        zip_file.close()
+        shutil.rmtree(gen_nvram_tool_path + "/tmp/")
+      except:
+        print "write file fail. " + self.filename
+        pause()
+        os._exit(0)
+    return
+  
+  def CreateRow(self, record, entry, excel_value):
+    startRow = self.Sheet1Row_idx
+    # create row
+    TmpOutput = []
+    TmpSheet = []
+    for r in range(0, record * entry):   
+      row_data = self.row_pattern[0]
+      # 
+      row_data = row_data.replace("%%ROW_ID%%", str(self.Sheet1Row_idx))
+      
+      TmpString = [] 
+      for nm in self.col_name:  # col data?
+        row_data = row_data.replace(nm[1], str(self.ShareString_Cnt))
+        idx = nm[0] + str(self.Sheet1Row_idx)
+         
+        if(excel_value.has_key(idx) == True):
+          val = excel_value[idx]
+        else:
+          val = ''
+        
+        if(nm[0] in ['D','E','H']):
+          TmpString.append('<si><t xml:space="preserve">')
+          TmpString.append(val)
+          TmpString.append('</t></si>\n')
+        else:
+          TmpString.append('<si><t>')
+          TmpString.append(val)
+          TmpString.append('</t></si>\n')
+        self.ShareString_Cnt += 1
+      TmpOutput.append(''.join(TmpString))      
+      self.Sheet1Row_idx += 1
+      TmpSheet.append(row_data)
+      del TmpString
+      del row_data
+    # merge col
+    self.ShareString = ''.join(TmpOutput)
+    self.Sheet1 = ''.join(TmpSheet)
+    if IsCustomer:
+        self.Sheet1 = self.Sheet1.replace("%%TAG_STYLE%%", str(1))
+    else:
+        self.Sheet1 = self.Sheet1.replace("%%TAG_STYLE%%", str(9))
+    del TmpOutput
+    del TmpSheet
+    TmpSheet1Merge = []
+    if((record * entry) > 1):
+      TmpSheet1Merge.append('<mergeCell ref="A')
+      TmpSheet1Merge.append(str(startRow))
+      TmpSheet1Merge.append(':A')
+      TmpSheet1Merge.append(str(self.Sheet1Row_idx - 1))
+      TmpSheet1Merge.append('"/>\n')
+      
+      self.Sheet1Merge_Cnt += 1
+    if(entry > 1):
+      for i in range(0, record):
+        TmpSheet1Merge.append('<mergeCell ref="B')
+        TmpSheet1Merge.append(str(startRow + (entry * i)))
+        TmpSheet1Merge.append(':B')
+        TmpSheet1Merge.append(str(startRow + (entry * (i+1)) - 1))
+        TmpSheet1Merge.append('"/>\n')
+        self.Sheet1Merge_Cnt += 1 
+    self.Sheet1Merge = ''.join(TmpSheet1Merge)
+    del TmpSheet1Merge
+    
+    return
+    
+  def __ConvertLSB(self, string):
+    s = ""
+    for i in range(0, len(string), 2):
+      s = string[i:i+2] + s
+    return s
+  
+  def GetValueStr(self, value, entry):
+    if(entry.name == u'byte23[0]:0*3'):
+      print "debug use"
+    if(value == "0x00"):
+      value = "00" * entry.size
+      byte_offset = 0
+    elif(value == "0xFF"):
+      value = "FF" * entry.size
+      byte_offset = 0
+    # ------------------
+    elif('()' in value):
+        value = "Callback function No default_value"
+        return value
+    else:
+        byte_offset = entry.offset 
+    value = value[(byte_offset*2):((byte_offset + entry.size)*2)]
+    # ---------
+    if(entry.bit_count > 0):    # count bit data default value
+      byte_size = ((entry.bit_count - 1) / 8 + 1)
+      value = value[(entry.byte_offset*2):((entry.byte_offset + byte_size)*2)]
+      if " " not in value:
+          value = self.__ConvertLSB(value)
+          mask = ("1" * entry.bit_count)
+          value = hex((int(value, 16) >> entry.bit_offset) & int(mask, 2))
+          value = self.__ConvertLSB(value[2:])
+      else:
+        value = " "
+    return value
+  
+  def FillEntry(self, MDDB_obj, entry):
+    # lid_name, record
+    # global lid_doc
+    global lid_default
+    self.lid_details = []
+    
+    lid_name = MDDB_obj.lid_name
+    record = MDDB_obj.record_count
+    excel_value = {}
+    startRow = self.Sheet1Row_idx
+    conflicted_tag = set()
+    conflicted_msg = set()
+    #fill LID header
+    entry_cnt = len(entry)
+    # excel_value.update({'A'+str(startRow):lid_name})
+    info_lid = MDDB_obj.lid_info_dom.find(lid_name)
+    if info_lid is None:
+        print "[Warning]Can't find the LID:" + lid_name + "in custom_nvram_lid_cat.xml and Bypass it\n"
+        return {};
+    default_val = info_lid.get("defaultByteFill")
+    # record_val = lid[0].getElementsByTagName("Record")
+    record_size = cint(info_lid.get("record_size"))
+    struct_size = cint(info_lid.get("struct_size"))
+    
+    #fill LID structure
+    str_mask_size = 0 
+    DefaultData = default_val
+    
+    # struct_size != record_size default value match 
+    default_val_len = len(DefaultData)
+    if '()' in DefaultData or DefaultData in ['0x00', '0xFF']:
+        DefaultData = DefaultData
+    else:
+        #  Default value size < record_size * record add ' ' in the end
+        if default_val_len < record_size*record*2:
+            gap = (record_size * record*2) - default_val_len
+            DefaultData += " "*gap 
+    for i in range(0, record):
+      currentRow = ((entry_cnt * i) + startRow)
+      excel_value.update({'B'+str(currentRow):str(i+1)})
+      # Record default value 
+      if '()' not in DefaultData and DefaultData not in ["0x00", "0xFF"]:   # (len(DefaultData) == (cint(record_size) * 2*cint(record))):
+        default_val = DefaultData[i*cint(record_size)*2: (i+1)*cint(record_size)*2]
+        tmp_val_len = len(default_val)
+        if tmp_val_len < struct_size*2:
+            default_val += " " * (struct_size*2 - tmp_val_len)
+            print("LID: {} add ' ' default value: {}---".format(lid_name, default_val))
+        #use the default value exported from platform by user
+        # default_val = DefaultData
+        if((i == 0) and (DebugMode == True)):
+            print "[Notify]default value will be filled by the raw data's default value"
+      for cur_entry in entry:
+         # ["name", "records","e_name", "purpose", "AN", "offset", 
+        # "defaultvalue", "p_values", "LOCK", "MCF", "RUNTIME","DOC", "INTERNAL", "TIER1"]
+        detail_info = [lid_name, i+1, cur_entry.name]
+        
+        excel_value.update({'A'+str(currentRow):lid_name})
+        excel_value.update({'C'+str(currentRow):cur_entry.name})
+        value = cur_entry.description
+        value = value.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
+        excel_value.update({'D'+str(currentRow):value})
+        detail_info.append(value)
+        value = cur_entry.application_note.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
+        excel_value['E'+str(currentRow)] = value
+        detail_info.append(value)
+        # offset summary two types 1:offset = 2   2:offset: byte:bit offset
+        bit_offset = 0
+        if cur_entry.is_bit_data:
+            bit_offset = str(cur_entry.bit_offset) if cur_entry.bit_count == 1 else (str(cur_entry.bit_offset) + "~" + str(cur_entry.bit_offset + cur_entry.bit_count - 1))
+            entry_offset = str(cur_entry.offset + cur_entry.byte_offset)+ ":" + bit_offset 
+        else:
+            entry_offset = str(cur_entry.offset + cur_entry.byte_offset)
+        
+        excel_value['F'+str(currentRow)] = entry_offset
+        detail_info.append(entry_offset)
+        #fill default value
+        value = self.GetValueStr(default_val, cur_entry) if((default_val in ["0x00", "0xFF"]) or default_val) else ""
+        if(len(value) > 32700):
+            value = value[0:32700] + ' ('+ str(len(value) - 32700) +' bytes left)'
+        excel_value.update({'G'+str(currentRow):value})
+        detail_info.append(value)
+        bit_description = ""
+        if cur_entry.bit_data != []:
+            # bit_description = "\n".join([item.get("description", "") for item in cur_entry.bit_data])
+            if len(cur_entry.bit_data) > 400:
+                # Excel cell limit:one cell can include '\n'<=253
+                cur_entry.bit_data = cur_entry.bit_data[:400]
+            bit_description = "\n".join(item.get("description", '') for item in cur_entry.bit_data)
+        
+        bit_description = bit_description.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
+        excel_value.update({'H'+str(currentRow):bit_description})
+        detail_info.append(bit_description)
+       
+        # file struct tag
+        # value = cur_entry.tag
+        tag_value = cur_entry.tag
+        
+        # Tag conflict check
+        self.tag_conflict_check(cur_entry, MDDB_obj, conflicted_tag, conflicted_msg)
+        
+        for col, t_name in self.excel_tag.items():
+            cell_value = cur_entry.TAG_Y if TAG[t_name] & tag_value else cur_entry.TAG_N
+            detail_info.append(cell_value)
+            excel_value[col+str(currentRow)] = cell_value
+        
+        currentRow += 1
+        self.lid_details.append(detail_info)
+    if conflicted_msg:
+        TAG_CONFLICT[MDDB_obj.lid_name] = list(conflicted_msg)
+    for item in conflicted_tag:
+        print item
+    #fill bit description
+    return excel_value
+  
+  def tag_conflict_check(self, cur_entry, md_obj, conflicted_tag, conflicted_msg):
+    global STATUS
+    """value: cur_entry.tag(hex), md_obj: MDDB object"""
+    if cur_entry.tag & TAG['LOCK']:
+        if md_obj.AttrMatch(NVRAM_ATTR_OTA_RESET):
+            msg = "[TAG Conflict] TAG: ['LOCK'] Attribute: ['NVRAM_ATTR_OTA_RESET'] CONFLICTED."
+            conflicted_msg.add(msg)
+            conflicted_tag.add("[TAG Conflict]: ITEM: {} TAG: ['LOCK'] Attribute: ['NVRAM_ATTR_OTA_RESET'] CONFLICTED.".format(re.sub(r'\[\d+\]', '', cur_entry.name)))
+            STATUS = ERR_ERROR
+        # conflict tag list
+        conf_tags = ["MCF", "RUNTIME"]
+        for tag_name in conf_tags:
+            if cur_entry.tag & TAG[tag_name]:
+                STATUS = ERR_ERROR
+                msg = "[TAG Conflict] TAG: ['LOCK', '{}'] have conflict.".format(tag_name)
+                conflicted_msg.add(msg)
+                conflicted_tag.add("[TAG Conflict]: ITEM: {} TAG: ['LOCK', '{}'] have conflict.".format(re.sub(r'\[\d+\]', '', cur_entry.name), tag_name))
+    if cur_entry.tag & TAG['INTERNAL']:
+        conf_tags = ["MCF"]
+        for tag_name in conf_tags:
+            if cur_entry.tag & TAG[tag_name]:
+                STATUS = ERR_ERROR
+                msg = "[TAG Conflict]: TAG ['INTERNAL', '{}'] have conflict.".format(tag_name)
+                conflicted_msg.add(msg)
+                conflicted_tag.add("[TAG Conflict]: ITEM: {} TAG ['INTERNAL', '{}'] have conflict.".format(re.sub(r'\[\d+\]', '', cur_entry.name), tag_name))
+                
+def _add_item_to_dict(dict_obj, key, item):
+    """Add into dict_obj with structure like: dict_obj[key]: [item1,item2..]"""
+    dict_obj.setdefault(key, []).append(item)
+    # dict_obj.setdefault(key, set()).add(item)
+    
+        
+# Global funtion ===========================================================
+def cint(d):
+  try:
+    return int(d)
+  except:
+    return 0
+
+def SortFilterConfig(filter):
+  cnt = len(filter)
+  for i in range(0, cnt):
+    for j in range(i+1, cnt):
+      if(len(filter[j][0]) > len(filter[i][0])):
+        filter[i],filter[j] = filter[j],filter[i]
+
+def CompareFilterConfig(filter, lid_name):
+  cnt = len(filter)
+  for i in range(0, cnt):
+    if(lid_name.lower().find(filter[i][0].lower().replace('*','')) == 0):
+      return filter[i][1]
+  return -1
+        
+def WriteEelementDoc(fl_doc,filename):
+        print '[WriteEditorInfo]: filename:{}'.format(filename)
+        content = ET.tostring(fl_doc, "utf-8")
+        with open(filename, "w") as f:
+            f.write(content.replace("><", ">\n<"))
+        
+    
+def CollectEditorInfo(filelist, gcc_path, build_path, parent_element):
+  # global gcc_path
+  global gcc_include
+  include = ""
+  
+  fileW = open('nvram_editor_data_item.c', 'w')
+  for path in filelist:
+    for parent,dirname,filenames in os.walk(path):
+      for fname in filenames:
+        if(fname.find('_editor.h')>0 or fname=='nvram_editor_data_item.h'):
+          # find editor file
+          fileW.write('#include "'+fname+'"\n')
+      break
+    include += (' -I "'+path+'"')
+  fileW.close()
+  output = ""
+  if(platform.system() == "Windows"):
+    gcc_include = include
+  ps = os.popen(gcc_path+' -DGEN_FOR_PC -E -C -imacros gcc_option.h -fno-strict-aliasing -fshort-enums -c -w nvram_editor_data_item.c '+gcc_include)
+  
+  #remove the white line
+  lines = ps.readlines()
+  ps.close()
+  lines = [line for line in lines if line.strip()]
+  tmp_path = build_path + '/nvram_auto_gen/nvram_editor_temp.txt'
+  if DebugMode:
+      with open(tmp_path,'w') as f:
+        f.write("".join(lines))
+  
+  parser = EditorParser(lines)
+  for line in parser.FindLidHeader():
+    header = parser.GetLidHeader(line)
+    lid = ET.SubElement(parent_element, header[0])
+    lid.set("LID_NAME", header[0])
+    lid.set("DESCRIPTION", header[1])
+    lid.set("INFORMATION", header[2])
+  
+
+def PrepareGCCEnvironment(build_path, mcu_path):
+  # Prepare compile option
+  global gcc_include
+  option_items = []
+  
+  StartParsing = 0
+  option_path = build_path + "/bin/log/info.log"
+  file = open(option_path)
+    
+  for line in file:
+    line = line.strip()
+    if "[ COMMON OPTION ]" in line:
+        StartParsing = 1
+        continue
+    
+    if(line.find("[") > -1):
+      break
+    if((StartParsing == 1) and len(line)):
+      line = line.replace("=", " ")
+      option_items.append('#define '+line)
+  with open('gcc_option.h', "w") as f:
+    f.write("\n".join(option_items))
+  # include path
+  inc_file = build_path + "/tmp/~inc.tmp.tmp"
+  inc_lines = []
+  with open(inc_file, "r") as f:
+    inc_lines = f.readlines()
+  gcc_include = '-I "' + '" -I "'.join([os.path.realpath(mcu_path+"/"+line.strip()) for line in inc_lines])+'"'
+  file.close() 
+  
+
+def pause():
+  if(platform.system() == "Windows"):
+    os.system("pause")
+  else:
+    import termios
+    fd = sys.stdin.fileno()
+    old_ttyinfo = termios.tcgetattr(fd)
+    new_ttyinfo = old_ttyinfo[:]
+    new_ttyinfo[3] &= ~termios.ECHO
+    sys.stdout.write('Press any key to continue . . .\n')
+    sys.stdout.flush()
+    termios.tcsetattr(fd, termios.TCSANOW, new_ttyinfo)
+    os.read(fd, 7)
+    termios.tcsetattr(fd, termios.TCSANOW, old_ttyinfo)
+def usage():
+    print "Tool user manual:"
+    print "Before run the tool,must check the parameters in input_config.ini is configured right,"
+    print "You can see the input_config.ini file under the same folder with this tool."
+    print "Generate the LID info database,run cmd:nvram_gen_excel.exe -e"
+    print "Generate the LID excel file,run cmd:nvram_gen_excel.exe -g"
+    print "Generate the LID info database and excel file,run the cmd:nvram_gen_excel.exe -a"
+    
+
+        
+class SqlHandler(object):
+    def __init__(self, filename, isCustomer):
+        if os.path.exists(filename):
+            os.remove(filename)
+        self.isCustomer = isCustomer
+        self.conn = self.create_connection(filename)
+        self.groups = """
+        CREATE TABLE groups(
+            id integer PRIMARY KEY,
+            name text NOT NULL
+        );"""
+        self.lid_info="""
+        CREATE TABLE lid_info(
+            id integer PRIMARY KEY,
+            name text NOT NULL,
+            lid_enum text NOT NULL,
+            group_id integer NOT NULL,
+            FOREIGN KEY(group_id) REFERENCES groups (id)
+        );
+        """
+        self.lid_detail_INTER = """
+        CREATE TABLE "lids" (
+            `LIDName` TEXT,
+            `RecordNum` TEXT,
+            `ElementName` TEXT,
+            `Purpose` TEXT,
+            `APNotification` REAL,
+            `Offset` TEXT,
+            `DefaultValue` TEXT,
+            `PossibleValues` TEXT,
+            `LOCK` TEXT,
+            `MCF` TEXT,
+            `RUNTIME` TEXT,
+            `DOC` TEXT,
+            `INTERNAL` TEXT,
+            `TIER1` TEXT );
+        """
+        self.lid_detail = """
+        CREATE TABLE "lids" (
+            `LIDName` TEXT,
+            `RecordNum` TEXT,
+            `ElementName` TEXT,
+            `Purpose` TEXT,
+            `APNotification` REAL,
+            `Offset` TEXT,
+            `DefaultValue` TEXT,
+            `PossibleValues` TEXT,
+            `LOCK` TEXT,
+            `MCF` TEXT,
+            `RUNTIME` TEXT,
+            `DOC` TEXT);
+        """ if self.isCustomer else self.lid_detail_INTER 
+        self.sql_detail_insert_INTER = """
+        INSERT INTO lids(LIDName, RecordNum, ElementName, Purpose, APNotification, Offset, 
+        DefaultValue, PossibleValues, LOCK, MCF, RUNTIME, DOC, INTERNAL, TIER1) VALUES
+        (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+        """
+        self.sql_detail_insert = """
+        INSERT INTO lids(LIDName, RecordNum, ElementName, Purpose, APNotification, Offset, 
+        DefaultValue, PossibleValues, LOCK, MCF, RUNTIME, DOC) VALUES
+        (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+        """ if self.isCustomer else self.sql_detail_insert_INTER
+        try:
+            self.cursor = self.conn.cursor()
+            self.cursor.execute(self.groups)
+            self.cursor.execute(self.lid_info)
+            self.cursor.execute(self.lid_detail)
+            # print("db create success")
+        except sqlite3.Error as e:
+            print("create table error: ", e)
+        # cursor.close()
+        
+    def lid_detail_writer(self, lines):
+        """insert one lid all detail lines 
+        lines: [(name,record,offset, description, tag..), (...)...]"""
+        for line in lines:
+            try:
+                self.cursor.execute(self.sql_detail_insert, line)
+            except Exception as e:
+                print(e)
+                print("Error record lid: {} into sqlite".format(line[0]) )
+        
+    def write_data(self, mddb):
+        """write sqlite db"""
+        if not self.conn:
+            print("connection Error!")
+            return
+        cursor = self.conn.cursor()
+        groups = mddb.groups   # data.keys()
+        groups = [v['name'] for k, v  in groups.items()]
+        sql_group = "INSERT INTO groups(name) VALUES (?)"
+        sql_lid_info = "INSERT INTO LID_INFO (name, lid_enum, group_id) VALUES (?, ?, ?)"
+        
+        for group in groups:
+            cursor.execute(sql_group, [group])
+            group_id = cursor.lastrowid
+            if group in mddb.group_lid_map:
+                for lid_data in mddb.group_lid_map[group]:    # data[group]:
+                    lid_data.append(group_id)
+                    cursor.execute(sql_lid_info, lid_data)
+        cursor.close()
+    
+    def create_connection(self, filename):
+        conn = None
+        try:
+            conn = sqlite3.connect(filename)
+        except sqlite3.Error as e:
+            print(e)
+        return conn
+
+        
+def CatAttributeMerage(lid, cat_lid, parent_element):
+    """merge lid attribute(id, record_size, total_record, attribute..) from cat.xml to MDDB"""
+    def_val = cat_lid.find("DEFAULT_VALUE")
+    #print "def_val" + str(defa_val)
+    def_fill = def_val.get("defaultByteFill")
+    if def_val.text:
+      def_fill = re.sub(r'[,\s\[\]]', r'', def_val.text).replace("0x", "")
+    lid_name = cat_lid.get("id")
+    if lid is None:
+        lid = ET.SubElement(parent_element, lid_name)
+        lid.set('LID_NAME', lid_name)
+        if DebugMode:
+            print "[Debug]: append a new lid:" + lid_name + " record_size:" + str(cat_lid.getAttribute("record_size")) + " total_record:" + str(cat_lid.getAttribute("total_record"))
+    else:
+        if DebugMode:
+            print "[Debug]: update lid info:" + lid_name + " record_size:" + str(cat_lid.getAttribute("record_size")) + " total_record:" + str(cat_lid.getAttribute("total_record"))
+    lid.set('record_size', cat_lid.get("record_size"))
+    lid.set('total_record', cat_lid.get("total_record"))
+    lid.set('lid_enum', cat_lid.get("lid_enum"))
+    lid.set('category', cat_lid.get("category", ""))
+    lid.set('attribute', cat_lid.get("attribute"))
+    lid.set('defaultByteFill', def_fill)
+    if DebugMode and ("()" in def_fill):
+        print "[Debug]: " + lid_name + " default value generated from callback function"
+    return lid
+
+def NvramGenDB():
+    """
+    Target:Merge cat.xml(default value, attribute...) into MDDB for gen excel
+    return: new db path
+  """
+    global build_path
+    old_date = datetime.datetime.now()
+    if(len(sys.argv) < 3):
+        print "%%ERROR%%Invalid argument number:",len(sys.argv)
+        usage()
+        sys.exit()
+    # build_path: xxx/mcu/build/xx_project/flavor
+    build_path = sys.argv[2]
+    
+    autogen_root = ET.Element("ROOT")
+    element_lid_info = ET.SubElement(autogen_root, "LID_INFO")
+    autogen_tree = ET.ElementTree(autogen_root)
+    
+    # Parsing editor.h for LID description & information
+    split_path_array = build_path.split("/")  
+    project_name = split_path_array[-2]
+    flavor_name = split_path_array[-1]
+    print "project_name: " + project_name + " flavor_name: " + flavor_name
+    project_flavor = project_name + "_" + flavor_name
+    
+    mcu_path = "/".join(split_path_array[:-3])
+    mcu_path = os.path.realpath(mcu_path)
+    if(platform.system() == "Windows"):
+      gcc_path = os.path.realpath(mcu_path + '/tools/MinGW/bin/gcc.exe')
+    else:
+      gcc_path = 'gcc'
+    PrepareGCCEnvironment(build_path, mcu_path)
+    
+    filelist = [mcu_path + '/interface/service/nvram']
+    filelist.append(mcu_path + '/custom/driver/common')
+    filelist.append(mcu_path + '/custom/middleware/common')
+    filelist.append(mcu_path + '/custom/modem/common/ps')
+    filelist.append(mcu_path + '/interface/driver/drv_def')  
+    CollectEditorInfo(filelist, gcc_path, build_path, element_lid_info)
+    # WriteEditorInfo(ET.tostring(autogen_root), "a_liddb_doc.xml")
+    
+    os.remove(r'gcc_option.h')
+    os.remove(r'nvram_editor_data_item.c')
+    print "Parsing editor.h success."
+    # Unzip MD database *.GZ
+    try:
+        dhl_path = os.path.realpath(build_path + '/dhl/database')
+        dhl_path = glob.glob(dhl_path + "/*.GZ")
+        g=gzip.GzipFile(mode='rb', fileobj=open(dhl_path[0],'rb'))
+        open(r'MDDB.XML','wb').write(g.read())
+        g.close()
+        print "Unzip MD database success."
+    except Exception as e:
+        print "MD database unzip fail."
+        print("Error: {}".format(e) )
+        STATUS = ERR_ERROR
+        # pause()
+        sys.exit()
+
+    # Merge custom_nvram_lid_cat.xml to MDDB (default value, attribute, struct_size...)
+    try:
+      MDDB_tree = ET.ElementTree(file="MDDB.XML")
+      MDDB_root = MDDB_tree.getroot()
+      # -----------------------
+      codegen_lids = {item.get("name"): item for item in MDDB_tree.iter('NVRAM_LID')}
+      codegen_struct_size_map = {item.get("name"): item.get("size") \
+            for item in MDDB_tree.iter(tag="Struct")}
+      codegen_define_type_size_map = {item.get("name"): item.get("size") for item in MDDB_tree.iter("Typedef")}
+      
+      cat_path = os.path.realpath(build_path + '/nvram_auto_gen/custom_nvram_lid_cat.xml')
+      cat_tree = ET.ElementTree(file=cat_path)
+      cat_root = cat_tree.getroot()
+      # AUTO GEN LID
+      autogen_lids = {}
+      nvitem = cat_root.iter('NVRAMITEM')
+      for cat_lid in nvitem:
+        lid_name = cat_lid.get("id")
+        autogen_lids[lid_name] = cat_lid
+        
+        autogen_lid = element_lid_info.find(lid_name)
+        autogen_lid = CatAttributeMerage(autogen_lid, cat_lid, element_lid_info)
+        # Check LID in AUTO gen but not in codegen
+        if lid_name not in codegen_lids:
+            if DebugMode:
+                print "[Waring]: {} in Autogen not in Codgen".format(lid_name)
+            continue
+        # Check lid's record size and structure size whether match
+        cat_lid_type = codegen_lids[lid_name].get("type_name")
+        size = ""
+        if cat_lid_type in codegen_struct_size_map:
+            size = codegen_struct_size_map[cat_lid_type]
+        elif cat_lid_type in codegen_define_type_size_map:
+            size = codegen_define_type_size_map[cat_lid_type]
+        if size != autogen_lid.get("record_size") and DebugMode:
+            if size == "":
+                print "can't find out struct_size for lid:{}".format(lid_name)
+            else:
+                print "[Waring]: " + lid_name + " record size(" + autogen_lid.getAttribute('record_size') + ") in Autogen mismatch with codegen(" + size + ")"            
+        autogen_lid.set("struct_size", size)
+      # WriteEelementDoc(autogen_root, "a_liddb_doc.xml")
+      
+      # Check lid in codegen not in AUTO GEN
+      for lid in codegen_lids:
+        if lid not in autogen_lids and DebugMode:
+            print "[Warning]: {} in Codgen not in Autogen".format(lid)
+      # Merge
+      autogen_root.append(MDDB_root)
+      
+      # Write new MDDB to disk
+      lidDB_version = ""
+      sw_version_element = MDDB_root.find("*/Information/[@name='MTK_TARGET_SW_VERSION_FOR_CATCHER']")
+      lidDB_version = sw_version_element.get("value", "")
+      
+      project_flavor = lidDB_version + "_"+ project_flavor
+      lidDB_filename = project_flavor + "_LidDBInfo.xml"
+      lidDB_path = os.path.realpath(build_path + '/nvram_auto_gen/' + lidDB_filename)
+      print("New MDDB path: {}".format(lidDB_path) )
+      # WriteEditorInfo(lidDB_doc,lidDB_path)
+      WriteEelementDoc(autogen_root, lidDB_path)
+      # merge db success
+      print "Merge custom_nvram_lid_cat.xml to MDDB success."
+    except Exception as e:
+      print build_path + "/nvram_auto_gen/custom_nvram_lid_cat.xml load fail."
+      STATUS = ERR_ERROR
+      raise
+      # pause()
+      sys.exit()
+    print "Generate LID DB success,you can find the file:"
+    print lidDB_path + "\n"
+    print "Start: " + str(old_date)
+    print "End:   " + str(datetime.datetime.now())
+    return lidDB_path
+
+    
+def NvramGenExcel(db_file):
+    """Generate excel include detail LID informations"""
+    global DebugMode, STATUS, ParseEditor, TAG_CONFLICT, build_path, IsCustomer, OutputBit, \
+        OutputArray, BypassNoDes
+    
+    old_date = datetime.datetime.now()
+    try:
+        # Load input_config.ini
+        config_file = "input_config.ini"
+        config_file_path = gen_nvram_tool_path + "/" + config_file
+        cf = ConfigParser.ConfigParser()
+        cf.read(config_file_path)        
+        Filter = cf.items("Filter")
+        SortFilterConfig(Filter)
+        ExcelOutput = gen_nvram_tool_path + "/" + cf.get("Config", "Excel_Output")
+        OutputArray = (str(cf.get("Config", "Output_Array")).lower() == "true")
+        OutputBit = (str(cf.get("Config", "Output_Possible_Val")).lower() == "true")
+        BypassNoDes = (str(cf.get("Config", "Bypass_No_Description")).lower() == "true")
+        DebugMode = (str(cf.get("Config", "DebugMode")).lower() == "true")
+        ParseEditor = (str(cf.get("Config", "Parse_Editor")).lower() == "true" )
+        ERR_LOG = cf.get("Config", "LogFile")
+        DBFile = cf.get("Config", "DBFile")
+        # read customer flag from config file 
+        IsCustomer = (cf.get("Config", "Is_Customer").lower() == 'true') if cf.has_option("Config", "Is_Customer") else True
+        if(cf.has_section('Config')==False or cf.has_section('Filter')==False):
+          print "Please input valid config.ini"
+          pause()
+          os._exit(0)
+        print "Load config file input_config.ini success."
+        if(len(sys.argv) >= 3):
+            # Only when sys.argv[2] == 'MTK' IsCustomer=False
+            if sys.argv[2].upper() == "MTK":
+                IsCustomer = False
+    except:
+        print "Open config file  config.ini error"
+        raise
+    NVRAMLidDB_XML_File = cf.get("Config", "NVRAMLidDB_XML") if not db_file else db_file 
+    start = time.time()
+    print "Start to Load Lid DB info file: " + NVRAMLidDB_XML_File
+    
+    # Parsing MD database
+    try:
+        MDDB = MDDBParser(NVRAMLidDB_XML_File)
+        print "Lid DB info Load success \n"
+    except Exception as e:
+        print e
+        traceback.print_exc(file=sys.stdout)
+        print "Lid MDDB DB file: " + NVRAMLidDB_XML_File + " load fail"
+        raise
+        # pause()
+        sys.exit()
+    # Gen secure structure description
+    if build_path:
+        ERR_LOG = "/".join([build_path, "nvram_auto_gen", ERR_LOG])
+    else:
+        ERR_LOG = gen_nvram_tool_path + "/" + ERR_LOG
+    
+    # INIT EXCEL template
+    Excel = ExcelEditor(ExcelOutput, IsCustomer)
+    print "Output version to Excel"
+    Excel.MTK_Version = MDDB.GetPlatformInfo("MTK_TARGET_SW_VERSION_FOR_CATCHER")
+    Excel.MTK_Project = MDDB.GetPlatformInfo("@PROJECT_NAME@MTK")  
+    Excel.Sheet1 = Excel.row_pattern[1]
+    if IsCustomer:
+      Excel.Sheet1 = Excel.Sheet1.replace('%%TAG_STYLE%%', str(1))
+    else:
+      Excel.Sheet1 = Excel.Sheet1.replace('%%TAG_STYLE%%', str(13))
+    Excel.Save()   # WRITE name, project merge info
+    
+    # write all groups and lid_group map 
+    DBFile = gen_nvram_tool_path + "/" + DBFile
+    sql_handler = SqlHandler(DBFile, IsCustomer)
+    
+    lidInfos = []
+    MDDB_len = len(MDDB.LIDs)
+    for i in range(0, MDDB_len):
+      if(MDDB.GetLidInfo(i) == -1):
+        break
+      print "Check: "+MDDB.lid_name+" (" + str(i) + "/" + str(MDDB_len) + ")"
+      filterDeep = CompareFilterConfig(Filter, MDDB.lid_name)
+      print "  filterDeep: "+str(filterDeep)
+      if(filterDeep == -1):
+        continue
+      entry = MDDB.GetLidStructure(int(filterDeep))
+      print "  entry size: "+str(len(entry))
+      if(len(entry) == 0):
+        continue
+      print "Output " + MDDB.lid_name + " to Excel"
+      if(DebugMode== True):
+        print "[Debug]: MDDB.record_count " + str(MDDB.record_count)
+        for j in range(0, len(entry)):
+          print "  " + entry[j].name + " : " + entry[j].description + ", " + str(entry[j].offset) + ", " + str(entry[j].size)
+      
+      excel_value = Excel.FillEntry(MDDB, entry)
+      if(excel_value != {}):
+        Excel.CreateRow(MDDB.record_count, len(entry), excel_value)
+      Excel.Save()
+      with sql_handler.conn:
+        sql_handler.lid_detail_writer(Excel.lid_details)
+     
+      # print("lid: {} insered".format(MDDB.lid_name))
+    print "Start: " + str(old_date)
+    print "End:   " + str(datetime.datetime.now())
+    Excel.Save(1)
+    # Backup excel to build LOG path
+    if build_path:
+        try:
+            log_path = "/".join([build_path, "nvram_auto_gen/"])
+            shutil.copy(ExcelOutput, log_path)
+        except Exception as e:
+            print e
+        
+    print "Gen Excel Successful"
+    
+    # write all groups and lid_group map 
+    with sql_handler.conn:
+        sql_handler.write_data(MDDB)
+    
+    with open(ERR_LOG, "w") as f:
+        start = datetime.time()
+        f.write("-------------------Nvram gen excel bulid log:\n")
+        if STATUS:     # STATUS=0/1  SUCCESS/FAIL:
+            f.write("Result: {} , Bulid Error!\n".format(STATUS) )
+            for one_lid in TAG_CONFLICT.keys():
+                content = one_lid + ":\n\t" + "\n\t".join(TAG_CONFLICT[one_lid])+ "\n"
+                f.write(content)
+                STATUS = ERR_ERROR
+        else:
+            f.write("Result: {}, Bulid Success!\n".format(STATUS) )
+    return STATUS, Excel.MTK_Version, Excel.MTK_Project
+    
+# Main funtion ===========================================================
+def main(db_file=None): 
+  print "MTK NVRAM Description Generator " + app_version
+  print "---------------------------------------"
+  GenLidDBOnly = False
+  GenLidExcelOnly = False
+  global  gen_nvram_tool_path
+  result = ERR_OK
+  lidDB_path = ""
+  
+  if(len(sys.argv) < 2):
+        print "%%ERROR%%Invalid argument number:",len(sys.argv)
+        usage()
+        sys.exit() 
+  opts,args = getopt.getopt(sys.argv[1:],"heg")
+  
+  for op,value in opts:
+      if op == "-h":
+          usage()
+          sys.exit()
+      elif op == "-e":
+          GenLidDBOnly = True
+      elif op == "-g":
+          GenLidExcelOnly = True
+            
+  gen_nvram_tool_path = os.path.dirname(os.path.realpath(sys.argv[0]))
+  # print "gen_nvram_excel_tool_full_path: " + gen_nvram_tool_path
+  if GenLidDBOnly:
+    result = NvramGenDB()
+  elif GenLidExcelOnly:
+    result = NvramGenExcel(db_file)    
+  print "Done."
+  return result
+  
+
+if __name__ == "__main__":
+  main()
\ No newline at end of file
diff --git a/mcu/tools/NVRAMStatistic/nvram_gen_excel/nvram_gen_excel.exe b/mcu/tools/NVRAMStatistic/nvram_gen_excel/nvram_gen_excel.exe
new file mode 100755
index 0000000..8219bdd
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_gen_excel/nvram_gen_excel.exe
Binary files differ
diff --git a/mcu/tools/NVRAMStatistic/nvram_gen_excel/nvram_gen_excel.py b/mcu/tools/NVRAMStatistic/nvram_gen_excel/nvram_gen_excel.py
new file mode 100644
index 0000000..79b7223
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_gen_excel/nvram_gen_excel.py
@@ -0,0 +1,1358 @@
+import sys, os, shutil, gc

+import glob, gzip

+import ConfigParser

+import xml.dom.minidom

+from xml.dom.minidom import Document

+import time, datetime

+import subprocess

+import zipfile

+import platform

+import getopt

+import pdb 

+

+

+# Global init ==============================================================

+app_version = "v1.1.8_20180119"

+

+lid_doc = Document()

+lid_info = lid_doc.documentElement

+

+lidDB_doc = Document()

+lidDB_root = lid_doc.createElement('ROOT')

+lidDB_doc.appendChild(lidDB_root)

+lidDB_info = lidDB_doc.createElement('LID_INFO')

+lidDB_root.appendChild(lidDB_info)

+

+OutputArray = False

+OutputBit = False

+BypassNoDes = False

+DebugMode = False

+GenLidDBOnly = False

+GenLidExcelOnly = False

+build_path = ""

+gen_nvram_tool_path = ""

+AP_NOTI_MARK = "AN:"

+IsCustomer = False

+

+# LID attribute

+# NVRAM_ATTR_AVERAGE          0x00000000UL

+NVRAM_ATTR_MULTI_DEFAULT = 0x00000001

+# NVRAM_ATTR_WRITEPROTECT     0x00000002UL

+# NVRAM_ATTR_MULTIPLE         0x00000004UL

+# NVRAM_ATTR_CONFIDENTIAL     0x00000008UL

+# NVRAM_ATTR_MULTIREC_READ    0x00000010UL

+# NVRAM_ATTR_MSP              0x00000020UL /* Protected by MTK Secure Platform */

+# NVRAM_ATTR_OTA_RESET        0x00000040UL

+# NVRAM_ATTR_GEN_DEFAULT      0x00000080UL

+# NVRAM_ATTR_RING             0x00000100UL

+# NVRAM_ATTR_PACKAGE          0x00000200UL /* NVRAM Reserved.LID will package in file */

+# NVRAM_ATTR_BACKUP_FAT       0x00000400UL /* Put a copy into backup partition, and the format is FAT */

+# NVRAM_ATTR_BACKUP_RAW       0x00000800UL /* Put a copy into backup partition, and the format is Raw data */

+# NVRAM_ATTR_RESERVE_BACKWARD 0x00001000

+# NVRAM_ATTR_FAULT_ASSERT     0x00002000

+

+# struct description tag 

+TAG = {"MCF":0x1,"LOCK":0x2, "RUNTIME":0x4, "DOC":0x8, "INTERNAL":0X10, "TIER1":0x20}

+

+INTER_USE = "@INTERNAL_USE@"

+

+

+lid_default = ""

+

+# EditorParser Class =======================================================

+class EditorParser:

+  """

+  def __init__(self, filename=None):

+    self.offset = 0

+    self.header = ['','','']

+    f = open(filename, "r")

+    self.lines = f.readlines()

+    f.close()

+  """

+  def __init__(self, lines=None):

+    self.offset = 0

+    self.header = ['','','']

+    self.lines = lines.split('\n')

+  

+  def FindLidHeader(self):

+    if(self.offset >= len(self.lines)):

+      return -1

+    for i in range(self.offset, (len(self.lines)-3)):

+      if(self.lines[i].find('* LID_NAME') >= 0):

+        i += 1

+        while(len(self.lines[i].strip()) == 0):

+          i += 1

+        self.offset = i

+        return i

+    return -1

+  

+  def GetLidHeader(self):

+    i = self.offset

+    self.header[0] = self.lines[i][2:999].strip()

+    while(1):

+      i += 1

+      if(self.lines[i].strip() != "*"):

+        break

+    while(len(self.lines[i].strip()) == 0):

+      i += 1

+    if(self.lines[i].find('DESCRIPTION') < 0):

+      return -1

+    i += 1

+    while(len(self.lines[i].strip()) == 0):

+    	i +=1

+    self.header[1] = ""

+    while(1):

+      if(self.lines[i][0:3] != "*  "):

+        break

+      str0 = self.lines[i][2:999].strip()

+      self.header[1] = (self.header[1] + str0 + "\n")

+      i += 1

+    self.header[2] = ""

+    if(self.lines[i].find('INFOMATION') < 0 and self.lines[i].find('INFORMATION') < 0):

+      return self.header

+    i += 1

+    while(1):

+      if(self.lines[i][0:3] != "*  "):

+        break

+      str0 = self.lines[i][2:999].strip()

+      self.header[2] = (self.header[2] + str0 + "\n")

+      i += 1

+    return self.header

+

+# StructEntry Class ========================================================

+class StructEntry:

+  TAG_Y = 'Y'

+  TAG_N = 'N'

+  def __copy(self, CopyFrom=None):

+    self.name = CopyFrom.name

+    self.description = CopyFrom.description

+    self.offset = CopyFrom.offset

+    self.size = CopyFrom.size

+    self.bit_data = CopyFrom.bit_data

+    self.bit_offset = CopyFrom.bit_offset

+    self.bit_count = CopyFrom.bit_count

+    self.byte_offset = CopyFrom.byte_offset

+    self.array_size = CopyFrom.array_size

+    # copy struct tag -------

+    self.tag = CopyFrom.tag

+    self.parent_tag = CopyFrom.parent_tag

+    self.application_note = CopyFrom.application_note

+    self.is_parent = CopyFrom.is_parent

+    self.is_bit_data = CopyFrom.is_bit_data

+    

+  def __init__(self, CopyFrom=None):

+    if(CopyFrom == None):

+      self.name = ""

+      self.description = ""

+      self.offset = 0

+      self.size = 0

+      self.bit_data = []

+      self.bit_offset = 0

+      self.bit_count = 0

+      self.byte_offset = 0

+      self.array_size = 0

+      # struct tag --------  

+      self.tag = 0

+      self.parent_tag = 0

+      self.application_note = ""

+      self.is_parent = False

+      self.is_bit_data = False

+    else:

+      self.__copy(CopyFrom)

+      

+  def CopyFrom(self, CopyFrom):

+    self.__copy(CopyFrom)

+    

+# MDDBParser Class

+class MDDBParser:

+  def __init__(self, filename=None):

+    global lidDB_doc

+    global gen_nvram_tool_path

+    self.lid_struct = []

+    self.description_deep = 0

+    self.entry_deep = 0

+    lidDB_doc = xml.dom.minidom.parse(filename)

+    lidDB_root = lidDB_doc.documentElement

+    MDDB_doc = Document()

+    MDDB_doc.appendChild(lidDB_root.getElementsByTagName('DB')[0])

+    root = MDDB_doc.documentElement

+    

+    if(DebugMode == True):

+      temp_file_name = ""

+      filename_split_array = ""

+      if(platform.system() == "Windows"):

+        filename_split_array = filename.split("\\")

+      else:

+        filename_split_array = filename.split("/")

+      temp_file_name = filename_split_array[len(filename_split_array)-1]

+      temp_file_name = gen_nvram_tool_path + "/MDDB_" + temp_file_name

+      WriteEditorInfo(MDDB_doc,temp_file_name)

+    #create LIDs dist

+    self.LIDs = root.getElementsByTagName('NVRAM_LIDs')[0].getElementsByTagName('NVRAM_LID')

+    #create Structs dist

+    self.Structs = root.getElementsByTagName('Structs')[0].getElementsByTagName('Struct')

+    tmpdist = {}

+    for t in self.Structs:

+      tmpdist.update({t.getAttribute("name"):t.getElementsByTagName("Field")})

+    del self.Structs

+    self.Structs = tmpdist

+    #create Unions dist

+    self.Unions = root.getElementsByTagName('Unions')[0].getElementsByTagName('Union')

+    tmpdist = {}

+    for t in self.Unions:

+      tmpdist.update({t.getAttribute("name"):t.getElementsByTagName("Field")[0]})

+    del self.Unions

+    self.Unions = tmpdist

+    #create Typedefs dist

+    self.Typedefs = root.getElementsByTagName('Typedefs')[0].getElementsByTagName('Typedef')

+    tmpdist = {}

+    for t in self.Typedefs:

+      tmpdist.update({t.getAttribute("name"):t.getAttribute("defined_type_name")})

+    del self.Typedefs

+    self.Typedefs = tmpdist

+    #create Platform dist

+    self.Platform = root.getElementsByTagName('Platform')[0].getElementsByTagName('Information')

+    tmpdist = {}

+    for t in self.Platform:

+      tmpdist.update({t.getAttribute("name"):t.getAttribute("value")})

+    del self.Platform

+    self.Platform = tmpdist

+    

+    self.entry_type = ''

+    self.lid_type = 'NULL'

+    # gc.collect()

+    

+  def GetLidCount(self):

+    return len(self.LIDs)

+  

+  def GetLidInfo(self, idx):

+    if(idx >= len(self.LIDs)):

+        return -1

+    self.lid_name = self.LIDs[idx].getAttribute("name")

+    self.lid_type = self.LIDs[idx].getAttribute("type_name")

+    self.record_count = 1 #int(self.LIDs[idx].getAttribute("record_count"))

+    self.description_deep = 0

+    self.entry_deep = 0

+    

+    lid_tmp = lid_doc.getElementsByTagName(self.lid_name)

+    # if lid_name not in lid_doc default: self.hex_attr=0

+    if lid_tmp:

+        lid_tmp = lid_tmp[0] 

+        self.hex_attr = int(lid_tmp.getAttribute('attribute'), 16)

+    else:

+        self.hex_attr = 0

+    # lid has attribute mulit_default 

+    self.mulit_default = self.AttrMatch(NVRAM_ATTR_MULTI_DEFAULT)

+    # ---------------

+    if self.mulit_default:

+        # print("LID: {} has attribute mulit_default".format(self.lid_name))

+        self.record_count = int(self.LIDs[idx].getAttribute("record_count")) 

+    return idx

+  

+  def AttrMatch(self, attr=NVRAM_ATTR_MULTI_DEFAULT):

+    """attribute match"""

+    return self.hex_attr & attr

+  

+  def GetPlatformInfo(self, infoName):

+    if(self.Platform.has_key(infoName) == True):

+        return self.Platform[infoName]

+    return ""

+

+  def ConvertTypedef(self, typeName):

+    if(self.Typedefs.has_key(typeName) == True):

+      return self.Typedefs[typeName]

+    return typeName

+

+  def ConvertArray(self, arrayStr, baseStr="", entryRet=[]):

+    if(arrayStr == "" or OutputArray == False):

+      return [""]

+    if(baseStr == ""):

+      entryRet = []

+      #gc.collect()

+    s = arrayStr.find(",")  

+    cnt = int(arrayStr) if(s == -1) else int(arrayStr[0:s])

+    for i in range(0, cnt):

+      if(s == -1):

+        entryRet.append(baseStr + "[" + str(i) + "]")

+      else:

+        self.ConvertArray(arrayStr[s+1:], baseStr + "[" + str(i) + "]", entryRet)

+    return entryRet

+  

+  def RecursiveBitEntry(self, entry, entry_idx, type_name):

+    tmp_bits = []

+    parent_node = entry[entry_idx]

+    entries = entry[entry_idx].bit_data

+    pre_name = entry[entry_idx].name

+    pre_size = entry[entry_idx].size

+    pre_description = entry[entry_idx].description

+    pre_array_size = entry[entry_idx].array_size

+    for i in range(0, len(entries)):

+      # entry.append(StructEntry())

+      tmp_bits.append(StructEntry())

+      entry_idx = (len(tmp_bits) - 1)

+      tmp_bits[entry_idx].is_bit_data = True

+      if i == 0:

+        pre_offset = int(entries[i].getAttribute("byte_offset"))

+      tmp_bits[entry_idx].byte_offset = int(entries[i].getAttribute("byte_offset"))

+      tmp_bits[entry_idx].bit_offset = int(entries[i].getAttribute("bit_offset"))

+      tmp_bits[entry_idx].bit_count = int(entries[i].getAttribute("bit_count"))

+      #entry[entry_idx].name = pre_name + ":" + entries[i].getAttribute("name")

+      #entry[entry_idx].description = pre_description + "(" + entries[i].getAttribute("description") +")"

+      tmp_bits[entry_idx].description = entries[i].getAttribute("description")

+      tmp_bits[entry_idx].parent_tag = parent_node.tag

+      tmp_bits[entry_idx].tag = parent_node.tag if not tmp_bits[entry_idx].description else self.TagMatch(tmp_bits[entry_idx])

+      # parse application notification (default_format: this is desc AN:xxxxxx)

+      if AP_NOTI_MARK in tmp_bits[entry_idx].description:

+        str_indx = tmp_bits[entry_idx].description.find(AP_NOTI_MARK) 

+        tmp_bits[entry_idx].application_note = tmp_bits[entry_idx].description[str_indx+len(AP_NOTI_MARK):]

+        tmp_bits[entry_idx].description = tmp_bits[entry_idx].description[:str_indx]

+      else:

+        tmp_bits[entry_idx].application_note = ""

+      # DELETE STR INTER_USE

+      inter_str_index = tmp_bits[entry_idx].description.find(INTER_USE)

+      if inter_str_index >= 0:

+        tmp_bits[entry_idx].description = tmp_bits[entry_idx].description[:inter_str_index] + tmp_bits[entry_idx].description[inter_str_index+len(INTER_USE):]

+    

+      tmp_bits[entry_idx].offset = 0

+      tmp_bits[entry_idx].size = pre_size

+      tmp_bits[entry_idx].bit_data = entries[i].getElementsByTagName("Bit_Value")

+      tmp_bits[entry_idx].array_size = pre_array_size

+      

+      tmp_bits[entry_idx].byte_offset -= pre_offset

+      tmp_bits[entry_idx].bit_name = entries[i].getAttribute('name')

+      """if((tmp_bits[entry_idx].bit_count == pre_array_size*8) and (tmp_bits[entry_idx].bit_offset == 0)):

+        tmp_bits[entry_idx].name = pre_name + "[" + str(tmp_bits[entry_idx].byte_offset / pre_array_size) + "]"

+      elif(tmp_bits[entry_idx].bit_count == 1):

+      if(tmp_bits[entry_idx].bit_count == 1):  

+        tmp_bits[entry_idx].name = pre_name + "[" + str(tmp_bits[entry_idx].byte_offset / pre_array_size) + "]."+ tmp_bits[entry_idx].bit_name

+      else:

+        tmp_bits[entry_idx].name = pre_name + "[" + str(tmp_bits[entry_idx].byte_offset / pre_array_size) + "]." + tmp_bits[entry_idx].bit_name

+   """

+      tmp_bits[entry_idx].name = pre_name + "[" + str(tmp_bits[entry_idx].byte_offset / pre_array_size) + "]:" + tmp_bits[entry_idx].bit_name

+    

+    #gc.collect()

+    return tmp_bits

+

+  def ReturnStructEntry(self, structName):

+    structName = self.ConvertTypedef(structName)

+    # bug fix: struct typedef may have two type of 

+    if self.Typedefs.has_key(structName):

+        structName = self.ConvertTypedef(structName)

+    if(self.Structs.has_key(structName) == True):

+      return self.Structs[structName]

+    if(self.Unions.has_key(structName) == True):

+      return [self.Unions[structName]]

+    

+    return []

+      

+  def RecursiveStructEntry(self, entry, entry_idx, type_name, deep, deep_limit):

+    if(deep_limit < 1):

+      return []

+    # record parent_node info

+    parent_node = entry[entry_idx]

+    # ---------------

+    entries = self.ReturnStructEntry(type_name)

+    pre_name = entry[entry_idx].name

+    #pre_offset = entry[entry_idx].offset

+    for i in range(0, len(entries)):

+      if(entries[i].getAttribute("type") in ["struct","union"]):

+        array = entries[i].getAttribute("array_sizes")

+        array = self.ConvertArray(array)

+      else:

+        array = [""]

+      array_size = entries[i].getAttribute("array_sizes")

+      array_size = len(self.ConvertArray(array_size))

+      array_size = 1 if(array_size == '') else int(entries[i].getAttribute("size"))/int(array_size)

+      tmp_entry = []

+      tmp_entry.append(StructEntry())

+      tmp_entry[0].description = entries[i].getAttribute("description")

+      tmp_entry[0].parent_tag = parent_node.tag

+      tmp_entry[0].tag = parent_node.tag if not tmp_entry[0].description else self.TagMatch(tmp_entry[0])

+      # parse application notification (default_format: this is desc AN:xxxxxx)

+      if AP_NOTI_MARK in tmp_entry[0].description:

+        str_indx = tmp_entry[0].description.find(AP_NOTI_MARK) 

+        tmp_entry[0].application_note = tmp_entry[0].description[str_indx+len(AP_NOTI_MARK):]

+        tmp_entry[0].description = tmp_entry[0].description[:str_indx]

+      else:

+        tmp_entry[0].application_note = ""

+      # DELETE STR INTER_USE

+      inter_str_index = tmp_entry[0].description.find(INTER_USE)

+      if inter_str_index >= 0:

+          # pdb.set_trace()

+          tmp_entry[0].description = tmp_entry[0].description[:inter_str_index] + tmp_entry[0].description[inter_str_index+len(INTER_USE):]

+          

+      

+      if(self.entry_deep < deep):

+        self.entry_deep = deep

+      if((len(entry[entry_idx].description) > 0) and (self.description_deep < deep)):

+        self.description_deep = deep

+      tmp_entry[0].size = (int(entries[i].getAttribute("size")) / len(array))

+      if entries[i].getAttribute("type") not in ["struct"]:

+        tmp_entry[0].bit_data = entries[i].getElementsByTagName("NVRAM_Bit_Data")

+      tmp_entry[0].array_size = array_size

+      if(entries[i].getAttribute("type") in ["struct","union"]):

+        self.RecursiveStructEntry(tmp_entry, 0, entries[i].getAttribute("type_name"), (deep + 1), (deep_limit - 1))

+      else:

+        if((len(tmp_entry[0].bit_data) > 0) and OutputBit):

+          recursive_bits = self.RecursiveBitEntry(tmp_entry, 0, entries[i].getAttribute("type_name"))

+          tmp_entry += recursive_bits

+      tmp_offset = 0 if(entries[i].getAttribute("offset")=="") else int(entries[i].getAttribute("offset"))

+      for j in range(0, len(array)):

+        for k in range(0, len(tmp_entry)):

+          entry.append(StructEntry(tmp_entry[k]))

+          

+          entry_idx = (len(entry) - 1)

+          entry[entry_idx].name = pre_name + "." + entries[i].getAttribute("name") + array[j] + tmp_entry[k].name

+          entry[entry_idx].offset = tmp_entry[k].offset + tmp_offset

+        tmp_offset += array_size

+      del tmp_entry, tmp_offset, array_size, array

+    #gc.collect()

+    

+  def GetLidStructure(self, deep_limit):

+    if(deep_limit < 1):

+      return []

+    if(self.entry_type == self.lid_type):

+      return self.entry

+    self.description_deep = 0

+    self.entry_deep = 0

+    self.entry = []

+    entries = self.ReturnStructEntry(self.lid_type)

+    self.entry = []

+    for i in range(0, len(entries)):

+      if(entries[i].getAttribute("type") in ["struct","union"]):

+          array = entries[i].getAttribute("array_sizes")

+          array = self.ConvertArray(array)

+      else:

+          array = [""]

+      array_size = entries[i].getAttribute("array_sizes")

+      array_size = len(self.ConvertArray(array_size))

+      array_size = 1 if(array_size == '') else int(entries[i].getAttribute("size"))/int(array_size)

+      tmp_entry = []

+      tmp_entry.append(StructEntry())

+      tmp_entry[0].description = entries[i].getAttribute("description")

+      

+      if tmp_entry[0].description:

+        self.TagMatch(tmp_entry[0])

+        # parse application notification (default_format: this is desc AN:xxxxxx)

+        if AP_NOTI_MARK in tmp_entry[0].description:

+            str_indx = tmp_entry[0].description.find(AP_NOTI_MARK) 

+            tmp_entry[0].application_note = tmp_entry[0].description[str_indx+len(AP_NOTI_MARK):]

+            tmp_entry[0].description = tmp_entry[0].description[:str_indx]

+        else:

+            tmp_entry[0].application_note = ""     

+        # DELETE STR INTER_USE

+        inter_str_index = tmp_entry[0].description.find(INTER_USE)

+        if inter_str_index >= 0:

+            # pdb.set_trace()

+            tmp_entry[0].description = tmp_entry[0].description[:inter_str_index] + tmp_entry[0].description[inter_str_index+len(INTER_USE):]

+            

+      if(self.entry_deep == 0):

+        self.entry_deep = 1

+      if((len(tmp_entry[0].description) > 0) and (self.description_deep == 0)):

+        self.description_deep = 1

+      tmp_entry[0].size = (int(entries[i].getAttribute("size")) / len(array))

+      

+      tmp_entry[0].bit_data = entries[i].getElementsByTagName("NVRAM_Bit_Data")

+      tmp_entry[0].array_size = array_size

+      if(entries[i].getAttribute("type") in ["struct","union"]):

+        self.RecursiveStructEntry(tmp_entry, 0, entries[i].getAttribute("type_name"), 2, (deep_limit - 1))

+      recursive_bits = []

+      if((len(tmp_entry[0].bit_data) > 0) and OutputBit):

+        tmp_entry[0].is_parent = True

+        pre_offset = int(tmp_entry[0].bit_data[0].getAttribute('byte_offset'))

+        bit_datas = self.RecursiveBitEntry(tmp_entry, 0, entries[i].getAttribute("type_name"))

+       

+        if entries[i].getAttribute("type") not in ["struct","union"]:

+            tmp_entry += bit_datas

+        # recursive_bits = {offet: [bit_obj]}

+        recursive_bits = {}

+        for item in bit_datas:

+            bit_offset = item.byte_offset+pre_offset

+            if bit_offset not in recursive_bits:

+                recursive_bits[bit_offset] = [item]  

+            else:

+                recursive_bits[bit_offset].append(item)

+      tmp_entry[0].bit_data = []

+      # pdb.set_trace()

+      tmp_offset = int(entries[i].getAttribute("offset"))

+      field_entry = []

+      

+      for j in range(0, len(array)):

+        for k in range(0, len(tmp_entry)):

+          field_entry.append(StructEntry(tmp_entry[k]))

+          entry_idx = (len(field_entry) - 1)

+          if tmp_entry[k].is_bit_data:

+            field_entry[entry_idx].name = entries[i].getAttribute("name")+"." + array[j] + tmp_entry[k].bit_name

+          else:

+            field_entry[entry_idx].name = entries[i].getAttribute("name") + array[j] + tmp_entry[k].name

+          field_entry[entry_idx].offset = tmp_entry[k].offset + tmp_offset

+        tmp_offset += array_size

+      # ADD bit data

+      entry_len = len(field_entry)

+      if recursive_bits and (entries[i].getAttribute("type") in ["struct","union"]):

+          for index in range(entry_len-1, -1, -1):

+            if field_entry[index].offset in recursive_bits:

+                item = field_entry[index]

+                name_flag = False if '.' in item.name else True

+                # bit_file name A.B.bit_data ==> bit data name :bit_offset

+                for k in range(0, len(recursive_bits[item.offset])):

+                    bit_item = recursive_bits[item.offset][k]

+                    item.description = bit_item.description

+                    # tag and description update to bit data's description

+                    if item.description:

+                        self.TagMatch(item)

+                        # parse application notification (default_format: this is desc AN:xxxxxx)

+                        if AP_NOTI_MARK in item.description:

+                            str_indx = item.description.find(AP_NOTI_MARK) 

+                            item.application_note = item.description[str_indx+len(AP_NOTI_MARK):]

+                            item.description = item.description[:str_indx]

+                        else:

+                            item.application_note = ""

+                            

+                    item.bit_data = bit_item.bit_data

+                    # add bit data

+                    if not name_flag:

+                        point = bit_item.name.find(":")

+                        bit_item.name = bit_item.name[point:]

+                          

+                    bit_item.name = item.name +"." + bit_item.bit_name

+                    bit_item.offset = item.offset

+                    bit_item.byte_offset = 0

+                    field_entry.insert(index+1+k, bit_item)

+                del recursive_bits[item.offset]

+      

+      self.entry += field_entry

+      del tmp_entry, tmp_offset, array_size, array

+    # Rebuild entry

+    if(BypassNoDes and (self.description_deep < self.entry_deep)):

+      del self.entry

+      self.entry = self.GetLidStructure(self.description_deep)

+    self.entry_type = self.lid_type

+    return self.entry

+    

+  def TagMatch(self, current_node):

+    """tag match:current struct tag=current_node.tag|current_node.parent_tag"""

+    if current_node.description:

+        description = current_node.description

+        l_bracket = description.find('[')

+        r_barcket = description.find(']')

+        if l_bracket >= 0 and r_barcket>0:

+            # description without tag desc

+            current_node.description = current_node.description[:l_bracket] + current_node.description[r_barcket+1:]

+            tag_str = description[l_bracket+1: r_barcket].upper()

+            tags = tag_str.strip().split(",")

+            tags = [item.strip() for item in tags]

+            for item in tags:

+                if TAG.has_key(item):

+                    current_node.tag = current_node.tag|TAG[item]

+        current_node.tag = current_node.tag|current_node.parent_tag

+    else:

+        current_node.tag = current_node.parent_tag

+    return current_node.tag

+        

+

+# Excel Editor Class =======================================================

+class ExcelEditor():

+  row_pattern = [

+                '<row r="%%ROW_ID%%" spans="1:14" ht="30">'

+                '<c r="A%%ROW_ID%%" s="6" t="s"><v>%%STR_A%%</v></c>'

+                '<c r="B%%ROW_ID%%" s="18" t="s"><v>%%STR_B%%</v></c>'

+                '<c r="C%%ROW_ID%%" s="7" t="s"><v>%%STR_C%%</v></c>'

+                '<c r="D%%ROW_ID%%" s="7" t="s"><v>%%STR_D%%</v></c>'

+                '<c r="E%%ROW_ID%%" s="7" t="s"><v>%%STR_E%%</v></c>'

+                '<c r="F%%ROW_ID%%" s="7" t="s"><v>%%STR_F%%</v></c>'

+                '<c r="G%%ROW_ID%%" s="8" t="s"><v>%%STR_G%%</v></c>'

+                '<c r="H%%ROW_ID%%" s="9" t="s"><v>%%STR_H%%</v></c>'

+                '<c r="I%%ROW_ID%%" s="9" t="s"><v>%%STR_I%%</v></c>'

+                '<c r="J%%ROW_ID%%" s="9" t="s"><v>%%STR_J%%</v></c>'

+                '<c r="K%%ROW_ID%%" s="9" t="s"><v>%%STR_K%%</v></c>'

+                '<c r="L%%ROW_ID%%" s="9" t="s"><v>%%STR_L%%</v></c>'

+                '<c r="M%%ROW_ID%%" s="%%TAG_STYLE%%" t="s"><v>%%STR_M%%</v></c>'

+                '<c r="N%%ROW_ID%%" s="%%TAG_STYLE%%" t="s"><v>%%STR_N%%</v></c></row>',

+                

+                '<c r="M5" s="%%TAG_STYLE%%" t="s"><v>16</v></c>'

+                '<c r="N5" s="%%TAG_STYLE%%" t="s"><v>17</v></c></row>\n'

+                ]

+  col_name = [["A","%%STR_A%%"],["B","%%STR_B%%"],["C","%%STR_C%%"],["D","%%STR_D%%"],["E","%%STR_E%%"],

+                ["F","%%STR_F%%"],["G","%%STR_G%%"],["H","%%STR_H%%"],["I","%%STR_I%%"],

+                ["J","%%STR_J%%"],["K","%%STR_K%%"], ["L","%%STR_L%%"], ["M","%%STR_M%%"], ["N","%%STR_N%%"]]

+  def __init__(self, filename):

+    try:

+      self.filename = filename  

+      zip_file = zipfile.ZipFile(os.path.realpath('nvram_gen_excel.xltx'))

+      zip_file.extractall('tmp')

+      zip_file.close()

+      

+      self.ShareString = ''

+      # self.ShareString_CntDef = 17

+      # self.ShareString_Cnt = 17

+      self.ShareString_CntDef = 18

+      self.ShareString_Cnt = 18

+

+      self.Sheet1 = ''

+      self.Sheet1Row_idx = 6

+      self.Sheet1Merge = ""

+      self.Sheet1Merge_Cnt = 0

+      # self.Sheet1Merge = '<mergeCell ref="B1:C1"/>\n<mergeCell ref="B2:C2"/>\n'

+      # self.Sheet1Merge_Cnt = 2

+

+      self.MTK_Version = ''

+      self.MTK_Project = ''

+      self.color = 0

+    except Exception as e:

+      print "ExcelEditor init fail."

+      print "Please check file nvram_gen_excel.xltx."

+      pause()

+      os._exit(0)

+    return

+

+  def Save(self, last=None):

+    # write SharedStrings

+    f = open('tmp/xl/sharedStrings.xml','a+')

+    f.write(self.ShareString)

+    f.close()

+    self.ShareString = ''

+

+    # write sheet1

+    f = open('tmp/xl/worksheets/sheet1.xml','a+')

+    f.write(self.Sheet1)

+    f.close()

+    self.Sheet1 = ''

+    

+    # write sheet1.merge

+    f = open('tmp/xl/worksheets/sheet1_merge.xml','a+')

+    f.write(self.Sheet1Merge)

+    f.close()

+    self.Sheet1Merge = ''

+    

+    # compress to xlsx

+    if(last <> None):

+      f = open('tmp/xl/worksheets/sheet1_merge.xml','r')

+      sheet1_merge = f.read()

+      f.close()

+      if(len(sheet1_merge) > 0):

+        sheet1_merge = '<mergeCells count="' + str(self.Sheet1Merge_Cnt) + '">' + sheet1_merge + '</mergeCells>'

+      # os.remove('tmp/xl/worksheets/sheet1_merge.xml')

+      

+      f = open('tmp/xl/worksheets/sheet1.xml','a+')

+      f.write('</sheetData>')

+      f.write(sheet1_merge)

+      # f.write('<pageMargins left="0.7" right="0.7" top="0.75" bottom="0.75" header="0.3" footer="0.3"/></worksheet>')

+      f.write('<phoneticPr fontId="4" type="noConversion"/>'

+                    '<pageMargins left="0.7" right="0.7" top="0.75" bottom="0.75" header="0.3" footer="0.3"/>'

+                    '<pageSetup paperSize="9" orientation="portrait" r:id="rId1"/></worksheet>')

+      f.close()

+

+      f = open('tmp/xl/sharedStrings.xml','r')

+      fb = f.read(700)

+      fbe = f.read()

+      f.close()

+      fb = fb.replace('%%COUNT%%', str(self.ShareString_Cnt))

+      fb = fb.replace("%%MTK_VERSION%%", self.MTK_Version)

+      fb = fb.replace("%%MTK_PROJECT%%", self.MTK_Project)

+      if IsCustomer:

+        # fb = fb.replace("%%TAG_STYLE%%", str(1))

+        fb = fb.replace("%%INTERNAL%%", " ")

+        fb = fb.replace("%%TIER1%%", " ")

+      else:

+        # fb = fb.replace("%%TAG_STYLE%%", str(13))

+        fb = fb.replace("%%INTERNAL%%", "INTERNAL")

+        fb = fb.replace("%%TIER1%%", "TIER1")

+      f = open('tmp/xl/sharedStrings.xml','w')

+      f.write(fb)

+      f.write(fbe)

+      f.write('</sst>')

+      f.close() 

+      

+      try:

+        zip_file = zipfile.ZipFile(self.filename, 'w')

+        for root,dirs,files in os.walk('tmp'):

+          for f in files:

+            abs_path = os.path.join(os.path.join(root,f))

+            rel_path = os.path.relpath(abs_path, os.path.dirname('tmp/'))

+            zip_file.write(abs_path, rel_path, zipfile.ZIP_DEFLATED)

+        zip_file.close()

+        shutil.rmtree("tmp/")

+      except:

+        print "write file fail. " + self.filename

+        pause()

+        os._exit(0)

+    return

+  

+  def CreateRow(self, record, entry, excel_value):

+    startRow = self.Sheet1Row_idx

+    # create row

+    TmpOutput = []

+    TmpSheet = []

+    for r in range(0, record * entry):   

+      row_data = self.row_pattern[0]

+      # 

+      row_data = row_data.replace("%%ROW_ID%%", str(self.Sheet1Row_idx))

+      

+      TmpString = [] 

+      for nm in self.col_name:  # col data?

+        row_data = row_data.replace(nm[1], str(self.ShareString_Cnt))

+        idx = nm[0] + str(self.Sheet1Row_idx)

+         

+        if(excel_value.has_key(idx) == True):

+          val = excel_value[idx]

+        else:

+          val = ''

+        

+        if(nm[0] in ['D','E','H']):

+          TmpString.append('<si><t xml:space="preserve">')

+          TmpString.append(val)

+          TmpString.append('</t></si>\n')

+        else:

+          TmpString.append('<si><t>')

+          TmpString.append(val)

+          TmpString.append('</t></si>\n')

+        self.ShareString_Cnt += 1

+      TmpOutput.append(''.join(TmpString))      

+      self.Sheet1Row_idx += 1

+      TmpSheet.append(row_data)

+      del TmpString

+      del row_data

+    # merge col

+    self.ShareString = ''.join(TmpOutput)

+    self.Sheet1 = ''.join(TmpSheet)

+    if IsCustomer:

+        self.Sheet1 = self.Sheet1.replace("%%TAG_STYLE%%", str(1))

+    else:

+        self.Sheet1 = self.Sheet1.replace("%%TAG_STYLE%%", str(9))

+    del TmpOutput

+    del TmpSheet

+    TmpSheet1Merge = []

+    if((record * entry) > 1):

+      TmpSheet1Merge.append('<mergeCell ref="A')

+      TmpSheet1Merge.append(str(startRow))

+      TmpSheet1Merge.append(':A')

+      TmpSheet1Merge.append(str(self.Sheet1Row_idx - 1))

+      TmpSheet1Merge.append('"/>\n')

+      

+      self.Sheet1Merge_Cnt += 1

+    if(entry > 1):

+      for i in range(0, record):

+        TmpSheet1Merge.append('<mergeCell ref="B')

+        TmpSheet1Merge.append(str(startRow + (entry * i)))

+        TmpSheet1Merge.append(':B')

+        TmpSheet1Merge.append(str(startRow + (entry * (i+1)) - 1))

+        TmpSheet1Merge.append('"/>\n')

+        self.Sheet1Merge_Cnt += 1 

+    self.Sheet1Merge = ''.join(TmpSheet1Merge)

+    del TmpSheet1Merge

+    

+    return

+    

+  def __ConvertLSB(self, string):

+    s = ""

+    for i in range(0, len(string), 2):

+      s = string[i:i+2] + s

+    return s

+  

+  def GetValueStr(self, value, entry):

+    if(entry.name == u'byte23[0]:0*3'):

+      print "debug use"

+    if(value == "0x00"):

+      value = "00" * entry.size

+      byte_offset = 0

+    elif(value == "0xFF"):

+      value = "FF" * entry.size

+      byte_offset = 0

+    # ------------------

+    elif('()' in value):

+        #value = "Callback function:{}, no default_value.".format(value)

+        value = "Callback function No default_value"

+        return value

+    else:

+        byte_offset = entry.offset 

+    value = value[(byte_offset*2):((byte_offset + entry.size)*2)]

+    # ---------

+    if(entry.bit_count > 0):    # count bit data default value

+      byte_size = ((entry.bit_count - 1) / 8 + 1)

+      value = value[(entry.byte_offset*2):((entry.byte_offset + byte_size)*2)]

+      if " " not in value:

+          value = self.__ConvertLSB(value)

+          mask = ("1" * entry.bit_count)

+          value = hex((int(value, 16) >> entry.bit_offset) & int(mask, 2))

+          value = self.__ConvertLSB(value[2:])

+      else:

+        print("---entry.name: {} offset: {}, bit_count:{} value: {} --bit data defalut value has blank ' ' in ".format(

+                        entry.name, entry.offset, entry.bit_count, value))

+        value = " "

+    return value

+  

+  def FillEntry(self, MDDB_obj, entry):

+    # lid_name, record

+    global lid_doc

+    global lid_default

+    

+    lid_name = MDDB_obj.lid_name

+    record = MDDB_obj.record_count

+    excel_value = {}

+    startRow = self.Sheet1Row_idx

+    #fill LID header

+    entry_cnt = len(entry)

+    excel_value.update({'A'+str(startRow):lid_name})

+    lid = lid_doc.getElementsByTagName(lid_name)

+    if(len(lid) == 0):

+        print "[Warning]Can't find the LID:" + lid_name + "in custom_nvram_lid_cat.xml and Bypass it\n"

+        return {};

+    default_val = lid[0].getAttribute("defaultByteFill")

+    # record_val = lid[0].getElementsByTagName("Record")

+    record_size = cint(lid[0].getAttribute("record_size"))

+    struct_size = cint(lid[0].getAttribute("struct_size"))

+    

+    #fill LID structure

+    str_mask_size = 0 

+    DefaultData = default_val

+    

+    # struct_size != record_size default value match 

+    default_val_len = len(DefaultData)

+    if '()' in DefaultData or DefaultData in ['0x00', '0xFF']:

+        DefaultData = DefaultData

+    else:

+        #  default value size < record_size * record add ' ' in the end

+        if default_val_len < record_size*record*2:

+            print("-----lid_name: {} default value size < record_size * record ".format(lid_name))

+            gap = (record_size * record*2) - default_val_len

+            DefaultData += " "*gap 

+    for i in range(0, record):

+      currentRow = ((entry_cnt * i) + startRow)

+      excel_value.update({'B'+str(currentRow):str(i+1)})

+      # ----------Record default value 

+      if '()' not in DefaultData and DefaultData not in ["0x00", "0xFF"]:   # (len(DefaultData) == (cint(record_size) * 2*cint(record))):

+        default_val = DefaultData[i*cint(record_size)*2: (i+1)*cint(record_size)*2]

+        tmp_val_len = len(default_val)

+        if tmp_val_len < struct_size*2:

+            default_val += " " * (struct_size*2 - tmp_val_len)

+            print("LID: {} add ' ' default value: {}---".format(lid_name, default_val))

+        #use the default value exported from platform by user

+        # default_val = DefaultData

+        if((i == 0) and (DebugMode == True)):

+            print "[Notify]default value will be filled by the raw data's default value"

+      """

+      if '()' not in DefaultData and (len(DefaultData) == (cint(struct_size) * 2*cint(record))):

+        default_val = DefaultData[i*cint(struct_size)*2: (i+1)*cint(struct_size)*2]

+      	#use the default value exported from platform by user

+      	# default_val = DefaultData

+      	if((i == 0) and (DebugMode == True)):

+          print "[Notify]default value will be filled by the raw data's default value"

+      elif '()' in DefaultData:

+        default_val = default_val

+      elif(struct_size != record_size) and default_val not in ['0x00', '0xFF']:

+        if((DebugMode == True) and (i == 0)):

+          print "[Warning]:" + lid_name + " record_size: " + record_size + " not match with struct_size: " + struct_size

+        print "[Warning]:default value will be set Null"

+        # default_val = "" 

+        record_size = cint(record_size)

+        start_point = i*cint(record_size)*2

+        # default_value

+        if (start_point + record_size) > default_val_len:

+            gap = start_point + record_size - default_val_len

+            default_val = DefaultData[start_point:]

+            default_val += [" "]*gap

+            # assert len(default_val) == record_size

+        else:

+            default_val = DefaultData[i*cint(record_size)*2: (i+1)*cint(record_size)*2]

+      """

+      # -----------------------------------

+      

+      # if((default_val.find("()") >= 0) and (i == 0) ):

+      #    print "[Notify]: " + lid_name + " default value not filled as no default data and also has callback function"

+      for cur_entry in entry:

+        excel_value.update({'C'+str(currentRow):cur_entry.name})

+        value = cur_entry.description

+        value = value.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')

+        excel_value.update({'D'+str(currentRow):value})

+        value = cur_entry.application_note.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')

+        excel_value['E'+str(currentRow)] = value

+        # offset summary two types 1:offset = 2   2:offset: byte:bit offset

+        bit_offset = 0

+        if cur_entry.is_bit_data:

+            bit_offset = str(cur_entry.bit_offset) if cur_entry.bit_count == 1 else (str(cur_entry.bit_offset) + "~" + str(cur_entry.bit_offset + cur_entry.bit_count - 1))

+            entry_offset = str(cur_entry.offset + cur_entry.byte_offset)+ ":" + bit_offset 

+        else:

+            entry_offset = str(cur_entry.offset + cur_entry.byte_offset)

+        value = str(cur_entry.offset + cur_entry.byte_offset)

+        if bit_offset:

+            value = value + ":" + bit_offset

+        excel_value['F'+str(currentRow)] = value

+        #fill default value

+        value = self.GetValueStr(default_val, cur_entry) if((default_val in ["0x00", "0xFF"]) or default_val) else ""

+        if(len(value) > 32700):

+            value = value[0:32700] + ' ('+ str(len(value) - 32700) +' bytes left)'

+        excel_value.update({'G'+str(currentRow):value})

+        bit_description = ""

+        # if not cur_entry.is_parent:

+        for k in range(0, len(cur_entry.bit_data)):

+          bit_description = bit_description + cur_entry.bit_data[k].getAttribute("description")

+          bit_description += "\n" if((k + 1) != len(cur_entry.bit_data)) else ""

+        

+        bit_description = bit_description.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')

+        excel_value.update({'H'+str(currentRow):bit_description})

+        

+        # file struct tag

+        value = cur_entry.tag

+        excel_value["I"+str(currentRow)] = cur_entry.TAG_Y if (TAG['LOCK']&value) else cur_entry.TAG_N

+        excel_value["J"+str(currentRow)] = cur_entry.TAG_Y if (TAG['MCF']&value) else cur_entry.TAG_N

+        excel_value["K"+str(currentRow)] = cur_entry.TAG_Y if (TAG['RUNTIME']&value) else cur_entry.TAG_N

+        excel_value["L"+str(currentRow)] = cur_entry.TAG_Y if (TAG['DOC']&value) else cur_entry.TAG_N

+        if not IsCustomer:

+            excel_value["M"+str(currentRow)] = cur_entry.TAG_Y if (TAG['INTERNAL']&value) else cur_entry.TAG_N

+            excel_value["N"+str(currentRow)] = cur_entry.TAG_Y if (TAG['TIER1']&value) else cur_entry.TAG_N

+        

+        currentRow += 1

+    #fill bit description

+    return excel_value

+  

+# Global funtion ===========================================================

+def cint(d):

+  try:

+    return int(d)

+  except:

+    return 0

+

+def SortFilterConfig(filter):

+  cnt = len(filter)

+  for i in range(0, cnt):

+    for j in range(i+1, cnt):

+      if(len(filter[j][0]) > len(filter[i][0])):

+        filter[i],filter[j] = filter[j],filter[i]

+

+def CompareFilterConfig(filter, lid_name):

+  cnt = len(filter)

+  for i in range(0, cnt):

+    if(lid_name.lower().find(filter[i][0].lower().replace('*','')) == 0):

+      return filter[i][1]

+  return -1

+

+#Write collected info for debug

+def WriteEditorInfo(fl_doc,filename):

+        print '[WriteEditorInfo]: filename:{}'.format(filename)

+        f = open(filename,'w')

+        f.write(fl_doc.toprettyxml(indent = ''))

+        # f.write(fl_doc.toxml("UTF-8"))

+        f.close()

+	

+#Load collected info for debug

+def LoadEditorInfo(filename):

+  global lid_doc

+  global lid_info

+  global lidDB_doc

+  global gen_nvram_tool_path

+  lidDB_doc = xml.dom.minidom.parse(filename)

+  root = lidDB_doc.documentElement

+  lid_doc.appendChild(root.getElementsByTagName('LID_INFO')[0])

+  lid_info = lid_doc.documentElement

+  

+  if(DebugMode == True):

+    temp_file_name = ""

+    filename_split_array = ""

+    if(platform.system() == "Windows"):

+    	filename_split_array = filename.split("\\")

+    else:

+    	filename_split_array = filename.split("/")    

+    temp_file_name = filename_split_array[len(filename_split_array)-1]

+    temp_file_name = gen_nvram_tool_path + "/CAT_" + temp_file_name

+    WriteEditorInfo(lid_doc,temp_file_name)

+  

+def CollectEditorInfo(filelist):

+  global gcc_path

+  global gcc_include

+  global lidDB_doc

+  global build_path

+  include = ""

+  

+  fileW = open('nvram_editor_data_item.c', 'w')

+  for path in filelist:

+    for parent,dirname,filenames in os.walk(path):

+      for fname in filenames:

+        if(fname.find('_editor.h')>0 or fname=='nvram_editor_data_item.h'):

+          # find editor file

+          fileW.write('#include "'+fname+'"\n')

+      break

+    include += (' -I "'+path+'"')

+  fileW.close()

+  output = ""

+  if(platform.system() == "Windows"):

+    gcc_include = include

+  ps = os.popen(gcc_path+' -DGEN_FOR_PC -E -C -imacros gcc_option.h -fno-strict-aliasing -fshort-enums -c nvram_editor_data_item.c '+gcc_include)

+  #output = ps.read()

+  

+  #remove the white line

+  lines = ps.readlines()

+  ps.close()

+  f = open(build_path + '/nvram_auto_gen/nvram_editor_temp.txt','w')

+  for line in lines:

+    if(len(line.strip()) != 0):

+     f.write(line)

+  f.close()

+  f = open(build_path + '/nvram_auto_gen/nvram_editor_temp.txt','r')

+  output = f.read()

+  f.close()

+  # if(DebugMode == False):

+  os.remove(build_path + '/nvram_auto_gen/nvram_editor_temp.txt')

+  parser = EditorParser(output)

+  while(parser.FindLidHeader() >= 0):

+    header = parser.GetLidHeader()

+    lid = lidDB_doc.createElement(header[0])

+    lid.setAttribute('LID_NAME', header[0])

+    lid.setAttribute('DESCRIPTION', header[1])

+    lid.setAttribute('INFORMATION', header[2])

+    lidDB_doc.getElementsByTagName('LID_INFO')[0].appendChild(lid)

+  # retrieve memory

+  del parser, output, ps

+  # gc.collect()

+

+def PrepareGCCEnvironment(build_path):

+  # Prepare compile option

+  global gcc_include

+  

+  StartParsing = 0

+  option_path = build_path + "/bin/log/info.log"

+  file = open(option_path)

+  fileW = open('gcc_option.h', 'w')

+  for line in file:

+    line = line.replace('\r', '').replace('\n', '')

+    if(line.find("[ COMMON OPTION ]") > -1):

+      StartParsing = 1

+      continue

+    if(line.find("[ COMMON INCLUDE PATH ]") > -1):

+      StartParsing = 2

+      continue

+    if(line.find("[") > -1):

+      StartParsing = 0

+      continue

+    if((StartParsing == 1) and len(line)):

+      line = line.split("=")

+      if(len(line) == 1):

+        fileW.write('#define '+line[0]+'\n')

+      else:

+        fileW.write('#define '+line[0]+' '+line[1]+'\n')

+    if((StartParsing == 2) and len(line)):

+      gcc_include += (' -I "' + os.path.realpath(mcu_path+'/'+line) + '"')

+  fileW.close()

+  file.close()  

+

+def pause():

+  if(platform.system() == "Windows"):

+    os.system("pause")

+  else:

+    import termios

+    fd = sys.stdin.fileno()

+    old_ttyinfo = termios.tcgetattr(fd)

+    new_ttyinfo = old_ttyinfo[:]

+    new_ttyinfo[3] &= ~termios.ECHO

+    sys.stdout.write('Press any key to continue . . .\n')

+    sys.stdout.flush()

+    termios.tcsetattr(fd, termios.TCSANOW, new_ttyinfo)

+    os.read(fd, 7)

+    termios.tcsetattr(fd, termios.TCSANOW, old_ttyinfo)

+def usage():

+    print "Tool user manual:"

+    print "Before run the tool,must check the parameters in input_config.ini is configured right,"

+    print "You can see the input_config.ini file under the same folder with this tool."

+    print "Generate the LID info database,run cmd:nvram_gen_excel.exe -e"

+    print "Generate the LID excel file,run cmd:nvram_gen_excel.exe -g"

+    print "Generate the LID info database and excel file,run the cmd:nvram_gen_excel.exe -a"

+    

+

+# Main funtion ===========================================================

+gcc_include = ""

+lid_default = ""

+if __name__ == "__main__":

+  print "MTK NVRAM Description Generator " + app_version

+  print "---------------------------------------"

+  old_date = datetime.datetime.now()

+  

+  if(len(sys.argv) < 2):

+        print "%%ERROR%%Invalid argument number:",len(sys.argv)

+        usage()

+        sys.exit() 

+  opts,args = getopt.getopt(sys.argv[1:],"heg")

+  for op,value in opts:

+      if op == "-h":

+          usage()

+          sys.exit()

+      elif op == "-e":

+          GenLidDBOnly = True

+      elif op == "-g":

+          GenLidExcelOnly = True

+            

+  gen_nvram_tool_path = os.path.dirname(os.path.realpath(sys.argv[0]))

+  print "gen_nvram_excel_tool_full_path: " + gen_nvram_tool_path

+  #

+  try:

+    if(GenLidExcelOnly == True):  

+        # Load input_config.ini

+        config_file = "input_config.ini"

+        config_file_path = gen_nvram_tool_path + "/" + config_file

+        cf = ConfigParser.ConfigParser()

+        cf.read(config_file_path)        

+        filter = cf.items("Filter")

+        SortFilterConfig(filter)

+        ExcelOutput = cf.get("Config", "Excel_Output")

+        OutputArray = (str(cf.get("Config", "Output_Array")).lower() == "true")

+        OutputBit = (str(cf.get("Config", "Output_Possible_Val")).lower() == "true")

+        BypassNoDes = (str(cf.get("Config", "Bypass_No_Description")).lower() == "true")

+        DebugMode = (str(cf.get("Config", "DebugMode")).lower() == "true")

+        

+        # lid list file 

+        Lid_List = cf.get("Config", "Lid_List") if cf.has_option("Config", "Lid_List") else None

+        # read customer flag from config file 

+        IsCustomer = (cf.get("Config", "Is_Customer").lower() == 'true') if cf.has_option("Config", "Is_Customer") else True

+        if(cf.has_section('Config')==False or cf.has_section('Filter')==False):

+          print "Please input valid config.ini"

+          pause()

+          os._exit(0)

+        print "Load config file input_config.ini success."

+        if(len(sys.argv) >= 3):

+            # GenExcelOnly only when sys.argv[2] == 'MTK' IsCustomer=False

+            if sys.argv[2].upper() == "MTK":

+                IsCustomer = False

+    else:

+        if(len(sys.argv) < 3):

+              print "%%ERROR%%Invalid argument number:",len(sys.argv)

+              usage()

+              sys.exit()

+        build_path = sys.argv[2] 

+  except:

+    if(GenLidExcelOnly == True):

+        print "Open config file  config.ini error"

+    pause()

+    sys.exit()

+    

+  if(GenLidDBOnly == True):

+    # Parsing editor.h to xml

+    split_path_array = ""

+    split_path_array = build_path.split("/")  

+    project_name = split_path_array[len(split_path_array)-2]

+    flavor_name = split_path_array[len(split_path_array)-1]

+    print "project_name: " + project_name + " flavor_name: " + flavor_name

+    project_flavor = project_name + "_" + flavor_name

+    

+    mcu_path = os.path.realpath(build_path + '/../../../')

+    if(platform.system() == "Windows"):

+      gcc_path = os.path.realpath(mcu_path + '/tools/MinGW/bin/gcc.exe')

+    else:

+      gcc_path = 'gcc'

+    PrepareGCCEnvironment(build_path)

+    filelist = [mcu_path + '/interface/service/nvram']

+    filelist.append(mcu_path + '/custom/driver/common')

+    filelist.append(mcu_path + '/custom/middleware/common')

+    filelist.append(mcu_path + '/custom/modem/common/ps')

+    filelist.append(mcu_path + '/interface/driver/drv_def')  

+    CollectEditorInfo(filelist)

+    del mcu_path, gcc_path, filelist

+    os.remove(r'gcc_option.h')

+    os.remove(r'nvram_editor_data_item.c')

+    print "Parsing editor.h success."

+    

+    # Merge custom_nvram_lid_cat.xml

+    try:

+      cat_path = os.path.realpath(build_path + '/nvram_auto_gen/custom_nvram_lid_cat.xml')

+      cat_doc = xml.dom.minidom.parse(cat_path)

+      cat_root = cat_doc.documentElement

+      nvitem = cat_root.getElementsByTagName('NVRAMITEM')

+      for i in range(0, len(nvitem)):

+        def_val = nvitem[i].getElementsByTagName("DEFAULT_VALUE")

+        #print "def_val" + str(defa_val)

+        def_fill = def_val[0].getAttribute("defaultByteFill")

+        #print "def_fill" + str(def_fill)

+        if(def_val[0].firstChild != None):

+          def_fill = def_val[0].firstChild.data

+          def_fill = def_fill.replace("0x","").replace(",","").replace(" ","").replace("\n","").replace("[","").replace("]","")

+        lid = lidDB_doc.getElementsByTagName(nvitem[i].getAttribute("id"))

+        if(lid == []):

+          lid = lidDB_doc.createElement(nvitem[i].getAttribute("id"))

+          lid.setAttribute('LID_NAME', nvitem[i].getAttribute("id"))

+          lid.setAttribute('record_size', nvitem[i].getAttribute("record_size"))

+          lid.setAttribute('total_record', nvitem[i].getAttribute("total_record"))

+          lid.setAttribute('attribute', nvitem[i].getAttribute("attribute"))

+          lid.setAttribute('defaultByteFill', def_fill)

+          if(DebugMode == True):

+            print "[Debug]: append a new lid:" + str(nvitem[i].getAttribute("id")) + " record_size:" + str(nvitem[i].getAttribute("record_size")) + " total_record:" + str(nvitem[i].getAttribute("total_record"))

+          lidDB_doc.getElementsByTagName('LID_INFO')[0].appendChild(lid)

+        else:

+          lid[0].setAttribute('record_size', nvitem[i].getAttribute("record_size"))

+          lid[0].setAttribute('total_record', nvitem[i].getAttribute("total_record"))

+          lid[0].setAttribute('attribute', nvitem[i].getAttribute("attribute"))

+          lid[0].setAttribute('defaultByteFill', def_fill)

+          if(DebugMode == True):

+            print "[Debug]: update lid info:" + str(nvitem[i].getAttribute("id")) + " record_size:" + str(nvitem[i].getAttribute("record_size")) + " total_record:" + str(nvitem[i].getAttribute("total_record"))

+        if((DebugMode == True) and (def_fill.find("()") >= 0)):

+          print "[Debug]: " + nvitem[i].getAttribute("id") + " default value generated from callback function"

+      del nvitem

+      # merge db success

+      # gc.collect()

+      print "Load custom_nvram_lid_cat.xml success."

+    except Exception as e:

+      print build_path + "/nvram_auto_gen/custom_nvram_lid_cat.xml load fail."

+      pause()

+      sys.exit()

+    # Unzip MD database *.GZ

+    try:

+        dhl_path = os.path.realpath(build_path + '/dhl/database')

+        dhl_path = glob.glob(dhl_path + "/*.GZ")

+        g=gzip.GzipFile(mode='rb', fileobj=open(dhl_path[0],'rb'))

+        open(r'MDDB.XML','wb').write(g.read())

+        g.close()

+        del dhl_path, g

+        # gc.collect()

+        print "Unzip MD database success."

+    except:

+        print "MD database unzip fail."

+        pause()

+        sys.exit()   

+    # Write LID DB Info to XML file

+    try:

+        MDDB_doc = xml.dom.minidom.parse("MDDB.XML")

+        MDDB_root = MDDB_doc.documentElement

+        Platform_info = MDDB_root.getElementsByTagName("Platform")[0].getElementsByTagName("Information")

+        #check lid's record size and structure size whether match

+        nvitem = cat_root.getElementsByTagName('NVRAMITEM')

+        for i in range(0, len(nvitem)):

+          size = ""

+          MDDB_Lid_typename = ""

+          lid_find_inCodegen = False

+          lid = lidDB_doc.getElementsByTagName(nvitem[i].getAttribute("id"))

+          MDDB_Lid_item = MDDB_root.getElementsByTagName("NVRAM_LIDs")[0].getElementsByTagName('NVRAM_LID')

+          for j in range(0, len(MDDB_Lid_item)):

+            if(MDDB_Lid_item[j].getAttribute("name") == nvitem[i].getAttribute("id")):

+              lid_find_inCodegen = True

+              MDDB_Lid_typename = MDDB_Lid_item[j].getAttribute("type_name")

+              break

+          if((lid_find_inCodegen == False) and (DebugMode == True)):

+            print "[Waring]: " + nvitem[i].getAttribute("id") + " in Autogen not in Codgen"

+            continue

+          if((MDDB_Lid_typename == "") and (DebugMode == True)):

+            print "[Waring]: " + "can't find out struct name for lid:" + nvitem[i].getAttribute("id")

+            continue

+          MDDB_Lid_structs = MDDB_root.getElementsByTagName('Structs')[0].getElementsByTagName('Struct')

+          for k in range(0,len(MDDB_Lid_structs)):

+            if(MDDB_Lid_structs[k].getAttribute("name") == MDDB_Lid_typename):

+              size = MDDB_Lid_structs[k].getAttribute("size")

+              break

+          if(size == ""):

+            MDDB_Lid_Typedefs = MDDB_root.getElementsByTagName('Typedefs')[0].getElementsByTagName('Typedef')

+            for m in range(0,len(MDDB_Lid_Typedefs)):

+              if(MDDB_Lid_Typedefs[m].getAttribute("name") == MDDB_Lid_typename):

+                size = MDDB_Lid_Typedefs[m].getAttribute("size")                

+                break

+          if((size == "") and (DebugMode == True)):    

+            print "can't find out struct_size for lid:" + nvitem[i].getAttribute("id")

+          lid[0].setAttribute('struct_size', size)

+          if((lid[0].getAttribute('record_size') != lid[0].getAttribute('struct_size')) and (DebugMode == True)):

+            print "[Waring]: " + nvitem[i].getAttribute("id") + " record size(" + lid[0].getAttribute('record_size') + ") in Autogen mismatch with codegen(" + size + ")"            

+        

+        print "nvitem ending-----------"

+        lid_find_inAutogen = False

+        for i in range(0, len(MDDB_Lid_item)):

+          for j in range(0, len(nvitem)):

+            if(MDDB_Lid_item[i].getAttribute("name") == nvitem[j].getAttribute("id")):

+              lid_find_inAutogen = True

+              break

+          if((lid_find_inAutogen == False) and (DebugMode == True)):

+            print "[Warning]: " + MDDB_Lid_item[i].getAttribute("name") + " in Codgen not in Autogen"            

+        del cat_path, nvitem, cat_root, cat_doc

+        lidDB_doc.firstChild.appendChild(MDDB_doc.firstChild)

+        lidDB_version = ""

+        for i in range(0,len(Platform_info)):

+          if(Platform_info[i].getAttribute("name") == "MTK_TARGET_SW_VERSION_FOR_CATCHER"):

+          	lidDB_version = Platform_info[i].getAttribute("value")

+          	print "MD image version: " + lidDB_version

+          	break

+        project_flavor = lidDB_version + "_"+ project_flavor

+        lidDB_filename = project_flavor + "_LidDBInfo.xml"

+        lidDB_path = os.path.realpath(build_path + '/nvram_auto_gen/' + lidDB_filename)

+        WriteEditorInfo(lidDB_doc,lidDB_path)

+        # os.remove(r'MDDB.XML')

+        del MDDB_Lid_Typedefs,MDDB_Lid_structs,MDDB_Lid_item,MDDB_root,MDDB_doc

+        # gc.collect()

+    except Exception as e:

+        print "Generate LID DB info fail."

+        print "Error:{}".format(e)

+        pause()

+        sys.exit()

+    print "Generate LID DB success,you can find the file:"

+    print lidDB_path + "\n"

+    print "Start: " + str(old_date)

+    print "End:   " + str(datetime.datetime.now())

+  if(GenLidExcelOnly == True):

+    NVRAMLidDB_XML_File = cf.get("Config", "NVRAMLidDB_XML")

+    print "Start to Load Lid DB info file: " + NVRAMLidDB_XML_File

+    try:

+      LoadEditorInfo(NVRAMLidDB_XML_File)

+    except:

+      print "Lid Info DB file: " + NVRAMLidDB_XML_File + " load fail"

+      pause()

+      sys.exit()

+    # Parsing MD database

+    MDDB = MDDBParser(NVRAMLidDB_XML_File)

+    print "Lid DB info Load success \n"

+    

+    # gen LID LIST

+    if Lid_List and os.path.exists(Lid_List):

+        tmp_lid_list = []

+        with open(Lid_List, 'r') as lid_file:

+            one_line = lid_file.readline()

+            while one_line:

+                one_line.strip()  # remove more space symbal

+                tmp_lid_list.append(one_line.split(' ')[0])

+                one_line = lid_file.readline()

+        Lid_List = tmp_lid_list

+    else: 

+        Lid_List = []

+    MDDB_len = MDDB.GetLidCount()

+    

+    Excel = ExcelEditor(ExcelOutput)

+    old_date = datetime.datetime.now()

+    print "Output version to Excel"

+    Excel.MTK_Version = MDDB.GetPlatformInfo("MTK_TARGET_SW_VERSION_FOR_CATCHER")

+    Excel.MTK_Project = MDDB.GetPlatformInfo("@PROJECT_NAME@MTK")  

+    Excel.Sheet1 = Excel.row_pattern[1]

+    if IsCustomer:

+      Excel.Sheet1 = Excel.Sheet1.replace('%%TAG_STYLE%%', str(1))

+    else:

+      Excel.Sheet1 = Excel.Sheet1.replace('%%TAG_STYLE%%', str(13))

+    Excel.Save()   # WRITE name, project merge info

+    # Lid_List = None

+    # MDDB_len = 300

+    for i in range(0, MDDB_len):

+      if(MDDB.GetLidInfo(i) == -1):

+        break

+      # LID LIST =[] gen all lids else gen lids which in LID LIST --------

+      if Lid_List and MDDB.lid_name not in Lid_List:

+        continue

+      start = time.time()

+      print "Check: "+MDDB.lid_name+" (" + str(i) + "/" + str(MDDB_len) + ")"

+      filterDeep = CompareFilterConfig(filter, MDDB.lid_name)

+      print "  filterDeep: "+str(filterDeep)

+      if(filterDeep == -1):

+        continue

+      entry = MDDB.GetLidStructure(int(filterDeep))

+      print "  entry size: "+str(len(entry))

+      if(len(entry) == 0):

+        continue

+      print "Output " + MDDB.lid_name + " to Excel"

+      if(DebugMode== True):

+        print "[Debug]: MDDB.record_count " + str(MDDB.record_count)

+        for j in range(0, len(entry)):

+          print "  " + entry[j].name + " : " + entry[j].description + ", " + str(entry[j].offset) + ", " + str(entry[j].size)

+      

+      excel_value = Excel.FillEntry(MDDB, entry)

+      if(excel_value != {}):

+        Excel.CreateRow(MDDB.record_count, len(entry), excel_value)

+      Excel.Save()

+      # gc.collect()

+    #except:

+    #  print "DHL parsing fail."

+    #  sys.exit()

+    print "Start: " + str(old_date)

+    print "End:   " + str(datetime.datetime.now())

+    Excel.Save(1)

+    print "Gen Excel Successful"

+  print "Done."

+  #pause()

+  sys.exit()

diff --git a/mcu/tools/NVRAMStatistic/nvram_gen_excel/nvram_gen_excel.xltx b/mcu/tools/NVRAMStatistic/nvram_gen_excel/nvram_gen_excel.xltx
new file mode 100644
index 0000000..85d3583
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_gen_excel/nvram_gen_excel.xltx
Binary files differ
diff --git a/mcu/tools/NVRAMStatistic/nvram_gen_excel/nvram_gen_web_db.py b/mcu/tools/NVRAMStatistic/nvram_gen_excel/nvram_gen_web_db.py
new file mode 100644
index 0000000..4791c48
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_gen_excel/nvram_gen_web_db.py
@@ -0,0 +1,1234 @@
+import sys, os, shutil, gc, traceback
+import re
+import json
+import glob, gzip
+try:
+    import ConfigParser as configparser
+except ImportError:
+    # py3
+    import configparser
+import time, datetime
+import zipfile
+import platform
+import getopt
+# import pdb 
+import sqlite3
+import base64
+import logging
+from collections import namedtuple, OrderedDict
+try:
+    import xml.etree.cElementTree as ET
+except ImportError:
+    import xml.etree.ElementTree as ET
+
+from utils.encryptDB import generateEDB
+from utils.mergeMDDB import NvramGenDB
+from utils.editorParser import EditorParser
+
+"""
+Not include:
+    array same default value bypass
+"""
+
+# Global init ==============================================================
+app_version = "v1_20190808"
+
+OutputArray = False
+OutputBit = False
+BypassNoDes = False
+DebugMode = False
+
+build_path = ""
+gen_nvram_tool_path = ""
+
+IsCustomer = True
+
+# LID attribute
+NVRAM_ATTR_MULTI_DEFAULT = 0x00000001
+NVRAM_ATTR_OTA_RESET =         0x00000040
+
+NVRAM_CATEGORY_FUNC_DEFAULT = 0x00000400
+
+# Struct description tag 
+TAG = {"MCF":0x1,"LOCK":0x2, "RUNTIME":0x4, "DOC":0x8, "INTERNAL":0X10, "TIER1":0x20}
+DB_TAG = ["LOCK", "MCF", "RUNTIME", "DOC"]
+INTERNAL_TAG = ["INTERNAL", "TIER1"]
+
+ERR_OK, ERR_ERROR = [0, 1]
+STATUS = ERR_OK
+
+ParseEditor = False
+gcc_include = ""
+TAG_CONFLICT = {}
+
+
+
+# StructEntry Class ========================================================
+class StructEntry(object):
+  TAG_Y = 'Y'
+  TAG_N = 'N'
+  def __copy(self, CopyFrom=None):
+    self.name = CopyFrom.name
+    self.description = CopyFrom.description
+    self.offset = CopyFrom.offset
+    self.size = CopyFrom.size
+    self.bit_data = CopyFrom.bit_data
+    self.bit_offset = CopyFrom.bit_offset
+    self.bit_count = CopyFrom.bit_count
+    self.byte_offset = CopyFrom.byte_offset
+    self.array_size = CopyFrom.array_size
+    # copy struct tag -------
+    self.tag = CopyFrom.tag
+    self.parent_tag = CopyFrom.parent_tag
+    self.application_note = CopyFrom.application_note
+    self.is_bit_data = CopyFrom.is_bit_data
+    
+  def __init__(self, CopyFrom=None):
+    if(CopyFrom == None):
+      self.name = ""
+      self.description = ""
+      self.offset = 0
+      self.size = 0
+      self.bit_data = []
+      self.bit_offset = 0
+      self.bit_count = 0
+      self.byte_offset = 0
+      self.array_size = 0
+      # struct tag --------  
+      self.tag = 0
+      self.parent_tag = 0
+      self.application_note = ""
+      self.is_bit_data = False
+    else:
+      self.__copy(CopyFrom)
+      
+  def CopyFrom(self, CopyFrom):
+    self.__copy(CopyFrom)
+    
+  def __str__(self):
+    return "name: {}, offset: {}".format(self.name, self.offset)
+    
+  def __repr__(self):
+    return "name: {}, offset: {}".format(self.name, self.offset)
+
+    
+# MDDBParser Class
+class MDDBParser:
+
+    # Secure lid description file
+    SECURE_LID_FILES = ["interface/service/nvram/l4_nvram_editor.h", 
+            "interface/service/nvram/nvram_editor_data_item.h"]
+    SEC_XML = "NVRAM_LID_structure_map.xml"
+
+    def __init__(self, filename=None):
+        """
+        Load MDDB file
+        collect security lids
+        parse and merge security struct description into MDDB
+        Coeect NVRAM groups
+        """
+        global gen_nvram_tool_path
+        self.secure_lids = []
+        self.inter_use = "@INTERNAL_USE@"
+        self.ap_noti_mark = "AN:"
+        self.groups = {}
+        self.group_lid_map = {}
+        self.description_deep = 0
+        self.entry_deep = 0
+        
+        self.lidDB_tree = ET.ElementTree(file=filename)
+        self.root = self.lidDB_tree.getroot()
+        self.lid_info_dom = self.lidDB_tree.find('LID_INFO')
+        lid_doc = ET.Element("ROOT")
+        lid_doc.append(self.lid_info_dom)
+        if DebugMode:
+            # Record LID_INFO IN MDDB
+            temp_file_name = ""
+            filename_split_array = filename.split(os.sep)
+            temp_file_name = filename_split_array[-1]
+            temp_lid_doc_file_name = gen_nvram_tool_path + "/CAT_" + temp_file_name
+            WriteEelementDoc(lid_doc,temp_lid_doc_file_name)
+        
+        # Create LIDs dict
+        self.LIDs =  OrderedDict([(item.get("name"), item) for item in self.root.iter("NVRAM_LID")])
+        self.Structs = {item.get("name"):list(item.iter("Field"))  for item in self.root.iter("Struct")}
+        self.Unions = {item.get("name"):item.find("Field")  for item in self.root.iter("Union")}
+        self.Typedefs = {item.get("name"):item.get("defined_type_name")  for item in self.root.iter("Typedef")}
+        self.Platform = {item.get("name"):item.get("value")  for item in self.root.iter("Information")}
+        
+        # Merge secure LIDs in
+        if ParseEditor:
+            secure_lids_iter = self.load_secure_lid()
+            for sec_lid in secure_lids_iter:
+                sec_name = sec_lid.get("name")
+                if sec_name not in self.LIDs:
+                    self.secure_lids.append(sec_lid)
+                    self.LIDs[sec_name] = sec_lid
+                    self.root.find("*/NVRAM_LIDs").append(sec_lid)
+            # parse secure lid structure description join into DB
+            self.SecureEditorParser()
+            # if DebugMode:
+            
+            if build_path:
+                temp_file_name = build_path + "/nvram_auto_gen/MDDB_with_secure.xml"
+            else:
+                temp_file_name = os.path.join(gen_nvram_tool_path, "MDDB_with_secure.xml")
+            WriteEelementDoc(self.root, temp_file_name)
+        
+        # Find all NVRAM Groups
+        self.parse_group_map()
+        self.entry_type = ''
+        self.lid_type = 'NULL'
+  
+    def GetLidInfo(self, lid):
+        
+        self.id = lid.get("id")
+        self.lid_name = lid.get("name")
+        self.lid_type = lid.get("type_name")
+        
+        self.record_count = 1   
+        self.description_deep = 0
+        self.entry_deep = 0
+        info_lid = self.lid_info_dom.find(self.lid_name)
+        
+        if info_lid is not None:
+            self.hex_attr = int(info_lid.get('attribute'), 16)
+            category = info_lid.get('category')
+            self.hex_category = int(category, 16) if category else 0
+            if not self.id:
+                self.id = info_lid.get("lid_enum")
+        else:
+            # Bypass lid which not in LID_INFO
+            self.hex_attr = 0
+            self.hex_category = 0
+            logging.info("Lid {} in MDDB list not in CAT list, Bypass!".format(self.lid_name) )
+            return False
+        # Lid which has attr 'mulit_default' expand all records 
+        self.mulit_default = self.AttrMatch(NVRAM_ATTR_MULTI_DEFAULT)
+        self.function_default = self.CategoryMatch(NVRAM_CATEGORY_FUNC_DEFAULT)
+        if self.mulit_default and not self.function_default:
+            self.record_count = int(lid.get("record_count")) 
+        # Collection lid group map info 
+        if self.id:
+            self.FindLidGroup()
+        elif DebugMode:
+            print("WARNNING: LID {} DON'T FIND ENUM!".format(self.lid_name) )
+            logging.warn("LID {} DON'T FIND ENUM!".format(self.lid_name))
+        return True
+  
+    def SecureEditorParser(self):
+        """parse desc from editor file"""
+        mcu_path = os.path.realpath(gen_nvram_tool_path + "/../../..")
+        self.SECURE_LID_FILES = [mcu_path + "/" + fpath for fpath in self.SECURE_LID_FILES]
+        e_parser = EditorParser(self.SECURE_LID_FILES, [lid.get("name") for lid in self.secure_lids])
+        e_parser.extract_desc()
+        for lid_name, desc_map in  e_parser.l_stu_map.items():
+            # merge per lid desc into mddb
+            lid_node = self.LIDs[lid_name]
+            type_name = lid_node.get("type_name")
+            self.merge_description(self.ReturnStructEntry(type_name), desc_map)
+  
+    def CategoryMatch(self, category=NVRAM_CATEGORY_FUNC_DEFAULT):
+        """attribute match"""
+        return self.hex_category & category
+        
+    def AttrMatch(self, attr=NVRAM_ATTR_MULTI_DEFAULT):
+        """attribute match"""
+        return self.hex_attr & attr
+      
+    def GetPlatformInfo(self, infoName):
+        if infoName in self.Platform:
+            return self.Platform[infoName]
+        return ""
+
+    def ConvertTypedef(self, typeName):
+        while typeName in self.Typedefs:
+            tmpName = self.Typedefs[typeName]
+            if tmpName != typeName:
+                typeName = tmpName
+            else:
+                # typedef define_type_name == name
+                break
+        return typeName
+        
+    def ConvertArray(self, arrayStr, baseStr="", entryRet=[]):
+        if(arrayStr == "" or OutputArray == False):
+          return [""]
+        if(baseStr == ""):
+          entryRet = []
+        s = arrayStr.find(",")  
+        cnt = int(arrayStr) if(s == -1) else int(arrayStr[0:s])
+        for i in range(0, cnt):
+          if(s == -1):
+            entryRet.append(baseStr + "[" + str(i) + "]")
+          else:
+            self.ConvertArray(arrayStr[s+1:], baseStr + "[" + str(i) + "]", entryRet)
+        return entryRet
+  
+    def RecursiveBitEntry(self, entry, entry_idx, type_name):
+        tmp_bits = []
+        parent_node = entry[entry_idx]
+        entries = entry[entry_idx].bit_data
+        pre_name = entry[entry_idx].name
+        pre_size = entry[entry_idx].size
+        pre_description = entry[entry_idx].description
+        pre_array_size = entry[entry_idx].array_size
+        for i in range(0, len(entries)):
+          one_bit = StructEntry()
+          tmp_bits.append(one_bit)
+          # entry_idx = (len(tmp_bits) - 1)
+          one_bit.is_bit_data = True
+          one_bit.byte_offset = int(entries[i].get("byte_offset"))
+          one_bit.bit_offset = int(entries[i].get("bit_offset"))
+          one_bit.bit_count = int(entries[i].get("bit_count"))
+          one_bit.description = entries[i].get("description")
+          one_bit.parent_tag = parent_node.tag
+          self._description_handler(one_bit)
+          
+          one_bit.offset = 0
+          one_bit.size = pre_size
+          one_bit.bit_data = entries[i].findall("Bit_Value")
+          
+          # tmp_bits[entry_idx].byte_offset -= pre_offset
+          one_bit.bit_name = entries[i].get('name')
+          # one_bit.name = pre_name + "[" + str(one_bit.byte_offset / pre_array_size) + "]:" + one_bit.bit_name
+        return tmp_bits
+
+    def ReturnStructEntry(self, structName):
+        structName = self.ConvertTypedef(structName)
+        if(self.Structs.has_key(structName) == True):
+          return self.Structs[structName]
+        if(self.Unions.has_key(structName) == True):
+          return [self.Unions[structName]]
+        
+        return []
+        
+    def RecursiveStructEntry(self, entry, entry_idx, type_name, deep, deep_limit):
+        if(deep_limit < 1):
+          return []
+        # record parent_node info
+        parent_node = entry[entry_idx]
+        entries = self.ReturnStructEntry(type_name)
+        pre_name = entry[entry_idx].name
+        for i in range(0, len(entries)):
+          if(entries[i].get("type") in ["struct","union"]):
+            array = entries[i].get("array_sizes", "")
+            array = self.ConvertArray(array)
+          else:
+            array = [""]
+          array_size = entries[i].get("array_sizes", "")
+          array_size = len(self.ConvertArray(array_size))
+          array_size = 1 if(array_size == '') else int(entries[i].get("size"))/int(array_size)
+          tmp_entry = []
+          one_entry = StructEntry()
+          tmp_entry.append(one_entry)
+          one_entry.description = entries[i].get("description", "")
+          one_entry.parent_tag = parent_node.tag
+          if one_entry.description:
+            self._description_handler(one_entry)
+          else:
+            one_entry.tag = parent_node.tag
+          if(self.entry_deep < deep):
+              self.entry_deep = deep
+            
+          if one_entry.description and (self.description_deep < deep):
+            print("self.description_deep +1 : {}".format(entries[i].get("name")))
+            self.description_deep = deep
+          one_entry.size = (int(entries[i].get("size")) / len(array))
+          bit_data = entries[i].findall("NVRAM_Bit_Data")
+          
+          if entries[i].get("type") not in ["struct"]:
+            one_entry.bit_data = entries[i].findall("NVRAM_Bit_Data")
+          elif bit_data:
+            logging.info("[Error] field have bit data and not STRUcT")
+            
+          one_entry.array_size = array_size
+          if(entries[i].get("type") in ["struct","union"]):
+            type_name = entries[i].get("type_name")
+            self.RecursiveStructEntry(tmp_entry, 0, entries[i].get("type_name"), (deep + 1), (deep_limit - 1))
+          else:
+            if((len(one_entry.bit_data) > 0) and OutputBit):
+              # assert all bit data under top struct
+              # pdb.set_trace()
+              recursive_bits = self.RecursiveBitEntry(tmp_entry, 0, entries[i].get("type_name"))
+              tmp_entry += recursive_bits
+          tmp_offset = int(entries[i].get("offset")) if entries[i].get("offset", "") else 0 
+          if entries[i].get("offset", "") == "":
+            print("struct item not find offset: {}".format(entries[i].get("name") ))
+          for j in range(0, len(array)):
+            for k in range(0, len(tmp_entry)):
+              entry.append(StructEntry(tmp_entry[k]))
+              entry_idx = (len(entry) - 1)
+              entry[entry_idx].name = pre_name + "." + entries[i].get("name") + array[j] + tmp_entry[k].name
+              entry[entry_idx].offset = tmp_entry[k].offset + tmp_offset
+            tmp_offset += array_size
+          del tmp_entry, tmp_offset, array_size, array
+        
+    def GetLidStructure(self, deep_limit):
+        if(deep_limit < 1):
+          return []
+        if(self.entry_type == self.lid_type):
+          return self.entry
+        self.description_deep = 0
+        self.entry_deep = 0
+        self.entry = []
+        entries = self.ReturnStructEntry(self.lid_type)
+        self.entry = []
+        for i in range(0, len(entries)):
+          # Array output Only for struct,union
+          if(entries[i].get("type") in ["struct","union"]): 
+              array = entries[i].get("array_sizes", "")
+              array = self.ConvertArray(array)
+          else:
+              array = [""]
+          field_name = entries[i].get("name")
+          array_size = entries[i].get("array_sizes", "")
+          array_size = len(self.ConvertArray(array_size))
+          if "size" in entries and int(entries[i].get("size")):
+            array_size = 1 if(array_size == '') else int(entries[i].get("size"))/int(array_size)
+          else: 
+            array_size = 1
+          tmp_entry = []
+          one_entry = StructEntry()
+          tmp_entry.append(one_entry)
+          # handle description
+          one_entry.description = entries[i].get("description", "").strip()
+          if one_entry.description:
+            self._description_handler(one_entry)
+            if self.description_deep == 0:
+                self.description_deep = 1
+            
+          if(self.entry_deep == 0):
+            self.entry_deep = 1
+          one_entry.size = (int(entries[i].get("size")) / len(array))
+          one_entry.bit_data = entries[i].findall("NVRAM_Bit_Data")
+          one_entry.array_size = array_size
+          field_type = entries[i].get("type")
+          
+          if field_type in ["struct","union"]:
+            tmp_name = entries[i].get("type_name")
+            self.RecursiveStructEntry(tmp_entry, 0, entries[i].get("type_name"), 2, (deep_limit - 1))
+          
+          # recursive_bits = {offet: [bit_obj1,..]}
+          recursive_bits = OrderedDict()
+          if one_entry.bit_data and OutputBit:
+            bit_datas = self.RecursiveBitEntry(tmp_entry, 0, entries[i].get("type_name"))
+            for item in bit_datas:
+                bit_offset = item.byte_offset 
+                recursive_bits.setdefault(bit_offset, []).append(item)
+          recursive_bits_offset = recursive_bits.keys()
+          recursive_bits_offset.sort()  
+          tmp_entry[0].bit_data = []
+          
+          tmp_offset = int(entries[i].get("offset"))
+          field_entry = []
+          pre_offset = 0
+          for j in range(0, len(array)):
+            for k in range(0, len(tmp_entry)):
+              one_entry = StructEntry(tmp_entry[k])
+              one_entry.name = field_name + array[j] + tmp_entry[k].name
+              cur_offset = tmp_entry[k].offset + tmp_offset
+              one_entry.offset = cur_offset
+              # Add bit datas
+              if cur_offset != pre_offset and recursive_bits_offset:
+                tmp_bit_data = {}
+                for offset in recursive_bits_offset:
+                    if offset < cur_offset:
+                        tmp_bit_data[offset] = recursive_bits[offset]
+                        recursive_bits_offset.remove(offset)
+                        del recursive_bits[offset]
+                    else:
+                        break
+                if tmp_bit_data:
+                    pre_entry = field_entry[-1]
+                    self._bit_data_merge(pre_entry, tmp_bit_data, field_entry)
+                pre_offset = cur_offset
+              field_entry.append(one_entry)
+            tmp_offset += array_size
+          if recursive_bits:
+            pre_entry = field_entry[-1]
+            self._bit_data_merge(pre_entry, recursive_bits, field_entry)
+          self.entry += field_entry
+        # print("entry_deep:{}, description_deep:{}".format(self.entry_deep, self.description_deep))
+        # Rebuild entry
+        if(BypassNoDes and (self.description_deep < self.entry_deep)):
+          print("second get lid structure:{}".format(self.lid_name))
+          del self.entry
+          self.entry = self.GetLidStructure(self.description_deep)
+        self.entry_type = self.lid_type
+        return self.entry
+                
+    def _bit_data_merge(self, item, bit_datas, field_entry, is_struct=False):
+        """
+      item: Parent node
+      bit_datas: {real_offset: [b1, b2..]}
+      """
+        name_flag = False if '.' in item.name else True
+        for offset, bit_items in bit_datas.items():
+            # bit_items = bit_datas[offset]
+            for bit_item in bit_items:
+                # item.description = bit_item.description
+                # TAG and description update to bit data's description
+                if not OutputBit:
+                    item.bit_data.extend(bit_item.bit_data)
+                bit_item.name = item.name +"." + bit_item.bit_name
+                bit_item.offset = offset  
+                bit_item.byte_offset = 0    
+                field_entry.append(bit_item)
+
+    def _description_handler(self, one_entry):
+        """description handle:
+        replace str: @INTER_USE@
+        extract application notifaction: xxxx AN:xxxxx
+        TAG match
+        """
+        # DELETE STR INTER_USE
+        if self.inter_use in one_entry.description:
+            one_entry.description = one_entry.description.replace(self.inter_use, "")
+        # parse application notification (default_format: this is desc AN:xxxxxx)
+        if self.ap_noti_mark in one_entry.description:
+            one_entry.description, one_entry.application_note = one_entry.description.split(self.ap_noti_mark)
+        self.TagMatch(one_entry)
+        
+    def TagMatch(self, current_node):
+        """tag match:current struct tag=current_node.tag|current_node.parent_tag"""
+        if current_node.description:
+            description = current_node.description
+            tag_pattern = re.compile(r"\[[a-zA-Z,\d\s]+\]")
+            tag_strs = tag_pattern.findall(description)
+            for tag_str in tag_strs:
+                tmp_tag = tag_str
+                flag = 0
+                tag_str = re.sub(r"[\[\]]", "", tag_str)
+                tag_str = [item.strip() for item in tag_str.split(",")]
+                for item in tag_str:
+                    if item in TAG:
+                        current_node.tag = current_node.tag|TAG[item]
+                        flag = 1
+                if flag:
+                    current_node.description = current_node.description.replace(tmp_tag, "")
+            # current_node.description = re.sub(r"[\[\]]", "", current_node.description)
+        current_node.tag = current_node.tag|current_node.parent_tag
+        return current_node.tag
+        
+    def parse_group_map(self):
+        """parse group-lid mapping
+        group_line: #define NVRAM_LID_GRP_C2K(x)                (0xE400 | (0x00FF & x))     //CK 
+       """
+        # add GRP
+        group_line = re.compile(r"#define\s*NVRAM_LID_GRP[A-Z_\d]+\(x\)\s*\(0x[\dA-F]+\s*\|.*\)")
+        group_value = re.compile(r"\(0x[\dA-F]+\s*\|\s*\(0x[\dA-F]+\s*&.*\)\)")
+        group_pattern = re.compile(r"NVRAM_LID_GRP[A-Z_\d]+")
+        group_file = "nvram_enums.h"
+        # LR13.R1.NVRAM.DESCIPTION.DEV\mcu\interface\service\nvram
+        fullpath = gen_nvram_tool_path+ "/../../../interface/service/nvram/"+ group_file
+        # print("group file path: {}".format(fullpath))
+        content = ""
+        if not os.path.exists(fullpath):
+            print("parse group Error: file {} not exists!".format(fullpath) )
+            logging.warn("Parse group Error: file {} not exists!".format(fullpath))
+            return
+        with open(fullpath, "r") as f:
+            content = f.readlines()
+        content = (item.strip() for item in content if item.strip())
+        group_define = filter(group_line.match, content)
+        
+        for line in group_define:
+            one_group = group_pattern.search(line)
+            if not one_group:
+                print("Error: group line not found Group.", line)
+                continue
+            else:
+                one_group = one_group.group()
+            value_section = group_value.search(line).group()
+            value_section = re.sub(r'[\(\)]', '', value_section)
+            min_addr, max_addr = value_section.split("|")
+            max_addr = max_addr.split("&")[0]
+            min_addr = int(min_addr, 16)
+            max_addr = min_addr + int(max_addr, 16)
+            # self.groups[min_addr] = {"name": group_name, "max": max_addr}
+            self.groups[min_addr] = {"name": one_group, "max": max_addr}
+        # self.sort_group_by_min(groups)
+        print("self.groups: ", len(self.groups.keys()))
+        
+    def FindLidGroup(self):
+        """find lid group by lid id from DB"""
+        flag = False
+        sort_group = sorted(self.groups.keys())
+        for item in sort_group:
+            if item > int(self.id):
+                flag = True
+                break
+        if flag:
+            group_index = sort_group.index(item)
+            group_min = sort_group[group_index-1]  # min address
+        else:
+            group_min = sort_group[-1]
+        tmp_group = self.groups[group_min]
+        assert int(self.id) in range(group_min, tmp_group["max"])
+        _add_item_to_dict(self.group_lid_map, tmp_group['name'], [self.lid_name, self.id])
+    
+
+    def merge_description(self, entries, description_map):
+        """merge description map into MDDB XML structure
+        According to name
+        """
+        for name in description_map.keys():
+            name_list = name.split(".")
+            struct_entry = entries
+            flag = False
+            offset = 0
+            # Bit data that should be joined under top structure
+            Bit_datas = []
+            cur_offset = 0
+            top_entry = None
+            # Find top entry
+            for name_item in name_list: 
+                flag = False
+                for entry in struct_entry:
+                    cur_entry_name = entry.get("name")
+                    if cur_entry_name == name_item:
+                        flag = True
+                        break
+                if flag:
+                    child_struct = entry.get("type_name")
+                    struct_entry = self.Structs[child_struct] if child_struct in self.Structs else []
+                else:
+                    # TODO type=union serach from union list
+                    print("struct :{} in editor not found in db".format(name))
+                    # pdb.set_trace()
+                    break
+            if flag:     # Find it
+                entry.set("description", description_map[name]["description"])
+                cur_offset = int(entry.get("offset"))
+                # TODO [0] one array only
+                if description_map[name]["bit_data"]:
+                    self.check_bit_offset(description_map[name]["bit_data"], entry, offset, cur_offset)
+                    Bit_datas = description_map[name]["bit_data"]
+                offset += cur_offset
+            if Bit_datas:
+                # find top struct
+                top_struct = None
+                for entry in entries:
+                    if entry.get("name") == name_list[0]:
+                        top_struct = entry
+                        break
+                try:
+                    assert top_struct is not None
+                except Exception as e:
+                    traceback.format_exc()
+                    #pdb.set_trace()
+                # All Bit data under top struct
+                under_bit_datas = entry.findall("NVRAM_Bit_Data")
+                for new_bit in Bit_datas:
+                    flag = False
+                    for db_bit in under_bit_datas:
+                        db_bit_name = db_bit.get("name")
+                        db_bit_offset = db_bit.get("byte_offset")
+                        # According name and offset confirm one bit data
+                        if db_bit_name == new_bit["name"] and db_bit_offset == new_bit["byte_offset"]:
+                            flag = True
+                            break
+                    if flag:
+                        if new_bit["description"]:
+                            db_bit.set("description", new_bit["description"])
+                        if new_bit["bit_value"]:
+                            bit_values = db_bit.findall("Bit_Value")
+                            bit_values = {item.get("value"): item for item in bit_values}
+                            for new_value in new_bit["bit_value"]:
+                                if new_value["name"] in bit_values:
+                                    bit_values[new_value["name"]].set("description", new_value["description"])
+                    else:
+                        # Bit data not found under top strut, add new dom
+                        new_bit_dom = self._gen_bit_xml_dom(new_bit)
+                        top_struct.append(new_bit_dom)
+                Bit_datas = []
+                
+    def _gen_bit_xml_dom(self, bit_dict):
+        """translate bit_dict to xml dom object
+        bit_dict:{name: xx, description:xx, bit_count:xx, byte_offset: xx,
+                bit_value:[{name: bb, description: xx},..]
+        return: NVRAM_Bit_Data dom include bit_value if bit data have bit_value
+        }
+        """
+        bit_data = ET.Element("NVRAM_Bit_Data")
+        # bit data dom init
+        bit_data.set("name", bit_dict.get("name"))
+        description = bit_dict.get("description", "")
+        if description:
+            bit_data.set("description", description)
+        bit_data.set("byte_offset", bit_dict.get("byte_offset"))
+        bit_data.set("bit_count", bit_dict.get("bit_count"))
+        bit_data.set("bit_offset", bit_dict.get("bit_offset"))
+        if bit_dict.get("bit_value", ""):
+            bit_values = bit_dict.get("bit_value")
+            for bit_item in bit_values:
+                value_dom = ET.SubElement(bit_data, "Bit_Value")
+                value_dom.set("value", bit_item.get("name"))
+                value_dom.set("description", bit_item.get("description", ""))
+        return bit_data
+            
+    def check_bit_offset(self, bit_description_list, entry, base_offset, parent_offset):
+        """offset: parent base offset
+        not merge into DB, just update offset
+        """
+        # TODO size="1, 2"
+        field_array = int(entry.get("array_sizes")) if entry.get("array_sizes") else 0
+        if field_array:
+            size = int(entry.get("size"))/ field_array
+        else:
+            size = int(entry.get("size"))
+       # For bit_offset
+        pre_bit_count = 0
+        pre_bit_offset = 0
+        pre_byte_offset = 0
+        for bit_item in bit_description_list:
+            array = bit_item.get("array", "")
+            if array:
+                # TODO [0][0] not conside
+                array = int(array[1:-1])
+                cur_offset = base_offset + (array * size + parent_offset)
+            else:
+                cur_offset = base_offset + parent_offset
+            bit_item["byte_offset"] = str(cur_offset)
+            if cur_offset == pre_byte_offset:
+                pre_bit_offset = pre_bit_count + pre_bit_offset
+            else:
+                # New bit begin bit_offset begin from 0
+                pre_bit_offset = 0
+            pre_bit_count = int(bit_item.get("bit_count"))
+            bit_item["bit_offset"] = str(pre_bit_offset)
+            pre_byte_offset = cur_offset
+
+    def load_secure_lid(self):
+        """
+        Load security LID xml return all NVRAM_LID iter
+       """
+        SEC_XML = os.path.realpath(gen_nvram_tool_path + "/../" + self.SEC_XML)
+        if not os.path.exists(SEC_XML):
+            print("Secure file: {} not exists, ByPass!".format(SEC_XML))
+            logging.warn("Secure file: {} not exists, ByPass!".format(SEC_XML))
+            return []
+        secure_tree = ET.ElementTree(file=SEC_XML)
+        sec_lids = secure_tree.iter("NVRAM_LID")
+        return sec_lids
+
+
+def __ConvertLSB(string):
+    s = ""
+    for i in range(0, len(string), 2):
+      s = string[i:i+2] + s
+    return s
+  
+def GetValueStr(value, entry):
+    if(entry.name == u'byte23[0]:0*3'):
+      print("debug use")
+    if(value == "0x00"):
+      value = "00" * entry.size
+      byte_offset = 0
+    elif(value == "0xFF"):
+      value = "FF" * entry.size
+      byte_offset = 0
+    # ------------------
+    elif('()' in value):
+        value = "Callback function No default_value"
+        return value
+    else:
+        byte_offset = entry.offset 
+    value = value[(byte_offset*2):((byte_offset + entry.size)*2)]
+    # ---------
+    if(entry.bit_count > 0):    # count bit data default value
+      byte_size = ((entry.bit_count - 1) / 8 + 1)
+      value = value[(entry.byte_offset*2):((entry.byte_offset + byte_size)*2)]
+      if " " not in value:
+          value = __ConvertLSB(value)
+          mask = ("1" * entry.bit_count)
+          value = hex((int(value, 16) >> entry.bit_offset) & int(mask, 2))
+          value = __ConvertLSB(value[2:])
+      else:
+        value = " "
+    return value
+  
+def FillEntry(MDDB_obj, entry):
+    lid_details = []
+    lid_name = MDDB_obj.lid_name
+    record = MDDB_obj.record_count
+    excel_value = {}
+    # startRow = self.Sheet1Row_idx
+    conflicted_tag = set()
+    conflicted_msg = set()
+    #fill LID header
+    entry_cnt = len(entry)
+    # excel_value.update({'A'+str(startRow):lid_name})
+    info_lid = MDDB_obj.lid_info_dom.find(lid_name)
+    if info_lid is None:
+        print("[Warning]Can't find the LID:" + lid_name + "in custom_nvram_lid_cat.xml and Bypass it\n")
+        return {};
+    default_val = info_lid.get("defaultByteFill")
+    # record_val = lid[0].getElementsByTagName("Record")
+    record_size = cint(info_lid.get("record_size"))
+    struct_size = cint(info_lid.get("struct_size"))
+    
+    #fill LID structure
+    str_mask_size = 0 
+    DefaultData = default_val
+    
+    # struct_size != record_size default value match 
+    default_val_len = len(DefaultData)
+    if '()' in DefaultData or DefaultData in ['0x00', '0xFF']:
+        DefaultData = DefaultData
+    else:
+        #  Default value size < record_size * record add ' ' in the end
+        if default_val_len < record_size*record*2:
+            gap = (record_size * record*2) - default_val_len
+            DefaultData += " "*gap 
+    for i in range(0, record):
+      # currentRow = ((entry_cnt * i) + startRow)
+      # excel_value.update({'B'+str(currentRow):str(i+1)})
+      # Record default value 
+      if '()' not in DefaultData and DefaultData not in ["0x00", "0xFF"]:   # (len(DefaultData) == (cint(record_size) * 2*cint(record))):
+        default_val = DefaultData[i*cint(record_size)*2: (i+1)*cint(record_size)*2]
+        tmp_val_len = len(default_val)
+        if tmp_val_len < struct_size*2:
+            default_val += " " * (struct_size*2 - tmp_val_len)
+            print("LID: {} add ' ' default value: {}---".format(lid_name, default_val))
+        #use the default value exported from platform by user
+        # default_val = DefaultData
+        if((i == 0) and (DebugMode == True)):
+            print("[Notify]default value will be filled by the raw data's default value")
+      for cur_entry in entry:
+         # ["name", "records","e_name", "purpose", "AN", "offset", 
+        # "defaultvalue", "p_values", "LOCK", "MCF", "RUNTIME","DOC", "INTERNAL", "TIER1"]
+        detail_info = [lid_name, i+1, cur_entry.name]
+        value = cur_entry.description.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
+        detail_info.append(value)
+        value = cur_entry.application_note.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
+        detail_info.append(value)
+        # offset summary two types 1:offset = 2   2:offset: byte:bit offset
+        bit_offset = 0
+        if cur_entry.is_bit_data:
+            bit_offset = str(cur_entry.bit_offset) if cur_entry.bit_count == 1 else (str(cur_entry.bit_offset) + "~" + str(cur_entry.bit_offset + cur_entry.bit_count - 1))
+            entry_offset = str(cur_entry.offset + cur_entry.byte_offset)+ ":" + bit_offset 
+        else:
+            entry_offset = str(cur_entry.offset + cur_entry.byte_offset)
+        
+        detail_info.append(entry_offset)
+        #fill default value
+        value = GetValueStr(default_val, cur_entry) if((default_val in ["0x00", "0xFF"]) or default_val) else ""
+        if(len(value) > 32700):
+            value = value[0:32700] + ' ('+ str(len(value) - 32700) +' bytes left)'
+        detail_info.append(value)
+        bit_description = ""
+        if cur_entry.bit_data != []:
+            # bit_description = "\n".join([item.get("description", "") for item in cur_entry.bit_data])
+            if len(cur_entry.bit_data) > 400:
+                # Excel cell limit:one cell can include '\n'<=253
+                cur_entry.bit_data = cur_entry.bit_data[:400]
+            bit_description = "\n".join(item.get("description", '') for item in cur_entry.bit_data)
+        
+        bit_description = bit_description.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
+        detail_info.append(bit_description)
+        # file struct tag
+        tag_value = cur_entry.tag
+        
+        # Tag conflict check
+        tag_conflict_check(cur_entry, MDDB_obj, conflicted_tag, conflicted_msg)
+        
+        for t_name in DB_TAG:
+            cell_value = cur_entry.TAG_Y if TAG[t_name] & tag_value else cur_entry.TAG_N
+            detail_info.append(cell_value)
+        
+        lid_details.append(detail_info)
+    
+    if conflicted_msg:
+        # logging.error("LID: {} [TAG CONFLICT]".format(MDDB_obj.lid_name ) )
+        TAG_CONFLICT[MDDB_obj.lid_name] = list(conflicted_msg)
+        # for msg in conflicted_msg:
+        #     logging.error(msg)
+        # logger.error("")
+        # TAG_CONFLICT[MDDB_obj.lid_name] = list(conflicted_msg)
+    # for item in conflicted_tag:
+    #     print item
+    #fill bit description
+    return lid_details
+  
+def tag_conflict_check(cur_entry, md_obj, conflicted_tag, conflicted_msg):
+    global STATUS
+    """value: cur_entry.tag(hex), md_obj: MDDB object"""
+    if cur_entry.tag & TAG['LOCK']:
+        if md_obj.AttrMatch(NVRAM_ATTR_OTA_RESET):
+            msg = "[TAG Conflict] TAG: ['LOCK'] Attribute: ['NVRAM_ATTR_OTA_RESET'] CONFLICTED."
+            conflicted_msg.add(msg)
+            # conflicted_tag.add("[TAG Conflict]: ITEM: {} TAG: ['LOCK'] Attribute: ['NVRAM_ATTR_OTA_RESET'] CONFLICTED.".format(re.sub(r'\[\d+\]', '', cur_entry.name)))
+            STATUS = ERR_ERROR
+        # conflict tag list
+        conf_tags = ["MCF", "RUNTIME"]
+        for tag_name in conf_tags:
+            if cur_entry.tag & TAG[tag_name]:
+                STATUS = ERR_ERROR
+                msg = "[TAG Conflict] TAG: ['LOCK', '{}'] have conflict.".format(tag_name)
+                conflicted_msg.add(msg)
+                # conflicted_tag.add("[TAG Conflict]: ITEM: {} TAG: ['LOCK', '{}'] have conflict.".format(re.sub(r'\[\d+\]', '', cur_entry.name), tag_name))
+    if cur_entry.tag & TAG['INTERNAL']:
+        conf_tags = ["MCF"]
+        for tag_name in conf_tags:
+            if cur_entry.tag & TAG[tag_name]:
+                STATUS = ERR_ERROR
+                msg = "[TAG Conflict]: TAG ['INTERNAL', '{}'] have conflict.".format(tag_name)
+                conflicted_msg.add(msg)
+                # conflicted_tag.add("[TAG Conflict]: ITEM: {} TAG ['INTERNAL', '{}'] have conflict.".format(re.sub(r'\[\d+\]', '', cur_entry.name), tag_name))
+
+
+def _add_item_to_dict(dict_obj, key, item):
+    """Add into dict_obj with structure like: dict_obj[key]: [item1,item2..]"""
+    dict_obj.setdefault(key, []).append(item)
+    
+        
+# Global funtion ===========================================================
+def cint(d):
+  try:
+    return int(d)
+  except:
+    return 0
+
+def SortFilterConfig(filter):
+  cnt = len(filter)
+  for i in range(0, cnt):
+    for j in range(i+1, cnt):
+      if(len(filter[j][0]) > len(filter[i][0])):
+        filter[i],filter[j] = filter[j],filter[i]
+
+def CompareFilterConfig(filter, lid_name):
+  cnt = len(filter)
+  for i in range(0, cnt):
+    if(lid_name.lower().find(filter[i][0].lower().replace('*','')) == 0):
+      return filter[i][1]
+  return -1
+        
+def WriteEelementDoc(fl_doc,filename):
+        print('[WriteEditorInfo]: filename:{}'.format(filename))
+        content = ET.tostring(fl_doc, "utf-8")
+        with open(filename, "w") as f:
+            f.write(content.replace("><", ">\n<"))
+        
+
+def pause():
+    if(platform.system() == "Windows"):
+        os.system("pause")
+    else:
+        import termios
+        fd = sys.stdin.fileno()
+        old_ttyinfo = termios.tcgetattr(fd)
+        new_ttyinfo = old_ttyinfo[:]
+        new_ttyinfo[3] &= ~termios.ECHO
+        sys.stdout.write('Press any key to continue . . .\n')
+        sys.stdout.flush()
+        termios.tcsetattr(fd, termios.TCSANOW, new_ttyinfo)
+        os.read(fd, 7)
+        termios.tcsetattr(fd, termios.TCSANOW, old_ttyinfo)
+def usage():
+    print("Tool user manual:")
+    print("Before run the tool,must check the parameters in input_config.ini is configured right,")
+    print("You can see the input_config.ini file under the same folder with this tool.")
+    print("Generate the LID info database,run cmd:nvram_gen_excel.exe -e build_path")
+    print("Generate the LID excel file,run cmd:nvram_gen_excel.exe -g CUS_NUMBER")
+   #  print "Generate the LID info database and excel file,run the cmd:nvram_gen_excel.exe -a"
+    
+
+        
+class SqlHandler(object):
+    def __init__(self, filename, isCustomer, *args):
+        """Create tables"""
+        if os.path.exists(filename):
+            os.remove(filename)
+        self.db_file = filename
+        self.isCustomer = isCustomer
+        self.conn = self.create_connection(filename)
+        self.groups = """
+        CREATE TABLE groups(
+            id integer PRIMARY KEY,
+            name text NOT NULL
+        );"""
+        self.lid_info="""
+        CREATE TABLE lid_info(
+            id integer PRIMARY KEY,
+            name text NOT NULL,
+            lid_enum text NOT NULL,
+            group_id integer NOT NULL,
+            FOREIGN KEY(group_id) REFERENCES groups (id)
+        );
+        """
+        self.lid_detail_INTER = """
+        CREATE TABLE "lids" (
+            `LIDName` TEXT,
+            `RecordNum` TEXT,
+            `ElementName` TEXT,
+            `Purpose` TEXT,
+            `APNotification` REAL,
+            `Offset` TEXT,
+            `DefaultValue` TEXT,
+            `PossibleValues` TEXT,
+            `LOCK` TEXT,
+            `MCF` TEXT,
+            `RUNTIME` TEXT,
+            `DOC` TEXT,
+            `INTERNAL` TEXT,
+            `TIER1` TEXT );
+        """
+        self.lid_detail = """
+        CREATE TABLE "lids" (
+            `LIDName` TEXT,
+            `RecordNum` TEXT,
+            `ElementName` TEXT,
+            `Purpose` TEXT,
+            `APNotification` REAL,
+            `Offset` TEXT,
+            `DefaultValue` TEXT,
+            `PossibleValues` TEXT,
+            `LOCK` TEXT,
+            `MCF` TEXT,
+            `RUNTIME` TEXT,
+            `DOC` TEXT);
+        """ if self.isCustomer else self.lid_detail_INTER 
+        self.sql_detail_insert_INTER = """
+        INSERT INTO lids(LIDName, RecordNum, ElementName, Purpose, APNotification, Offset, 
+        DefaultValue, PossibleValues, LOCK, MCF, RUNTIME, DOC, INTERNAL, TIER1) VALUES
+        (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+        """
+        self.sql_detail_insert = """
+        INSERT INTO lids(LIDName, RecordNum, ElementName, Purpose, APNotification, Offset, 
+        DefaultValue, PossibleValues, LOCK, MCF, RUNTIME, DOC) VALUES
+        (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+        """ if self.isCustomer else self.sql_detail_insert_INTER
+        try:
+            self.cursor = self.conn.cursor()
+            self.cursor.execute(self.groups)
+            self.cursor.execute(self.lid_info)
+            self.cursor.execute(self.lid_detail)
+        except sqlite3.Error as e:
+            logging.error("Create table error")
+            logging.error(traceback.format_exc())
+            syt.exit(ERR_ERROR)
+        
+    def lid_detail_writer(self, lines):
+        """insert one lid all detail lines 
+        lines: [(name,record,offset, description, tag..), (...)...]"""
+        for line in lines:
+            try:
+                self.cursor.execute(self.sql_detail_insert, line)
+            except Exception as e:
+                # print(e)
+                logging.warn("Error record lid: {} into sqlite".format(line[0]) )
+        
+    def write_useful_data(self, mddb, *args, **kwargs):
+        """write sqlite db"""
+        cursor = self.conn.cursor()
+        groups = mddb.groups   # data.keys()
+        groups = [v['name'] for k, v  in groups.items()]
+        sql_group = "INSERT INTO groups(name) VALUES (?)"
+        sql_lid_info = "INSERT INTO LID_INFO (name, lid_enum, group_id) VALUES (?, ?, ?)"
+        
+        for group in groups:
+            cursor.execute(sql_group, [group])
+            group_id = cursor.lastrowid
+            if group in mddb.group_lid_map:
+                for lid_data in mddb.group_lid_map[group]:    # data[group]:
+                    lid_data.append(group_id)
+                    cursor.execute(sql_lid_info, lid_data)
+        proj_str = base64.b64encode(args[0])
+        v_str = base64.b64encode(args[1])
+        self.cursor.execute("Insert into lid_info(name, lid_enum, group_id) \
+            values('{}', '{}', 0)".format(proj_str, v_str))
+        cursor.close()
+    
+    def create_connection(self, filename):
+        conn = None
+        try:
+            conn = sqlite3.connect(filename)
+        except sqlite3.Error as e:
+            logging.error("create sqlite DB connect error")
+            logging.error(traceback.format_exc())
+        return conn
+
+    
+def NvramGenExcel(db_file):
+    """Generate excel include detail LID informations"""
+    global DebugMode, STATUS, ParseEditor, TAG_CONFLICT, build_path, IsCustomer, OutputBit, \
+        OutputArray, BypassNoDes
+    CUSTOMERS = ["customer1","customer2","customer2","customer3","customer4","customer5","customer6",
+        "customer7","customer8"]
+    is_monitor = False
+    # customer marke
+    cus_num = sys.argv[2].lower()
+    if cus_num == "monitor":
+        is_monitor = True
+    elif cus_num not in CUSTOMERS:
+        print("Error: customer {} not found, check again".format(sys.argv[2]) )
+        logging.error("Customer {} not found, check again".format(sys.argv[2]) )
+        usage()
+        sys.exit(ERR_ERROR)
+    old_date = datetime.datetime.now()
+    try:
+        # Load input_config.ini
+        config_file = "input_config.ini"
+        config_file_path = gen_nvram_tool_path + "/" + config_file
+        cf = configparser.ConfigParser()
+        cf.read(config_file_path)        
+        if(cf.has_section('Config')==False or cf.has_section('Filter')==False):
+            print("Please input valid config.ini")
+            logging.error("Lack of section(Config or Filter), Please input valid config.ini")
+            pause()
+            sys.exit(ERR_ERROR)
+        Filter = cf.items("Filter")
+        SortFilterConfig(Filter)
+        ExcelOutput = gen_nvram_tool_path + "/" + cf.get("Config", "Excel_Output")
+        OutputArray = (str(cf.get("Config", "Output_Array")).lower() == "true")
+        OutputBit = (str(cf.get("Config", "Output_Possible_Val")).lower() == "true")
+        BypassNoDes = (str(cf.get("Config", "Bypass_No_Description")).lower() == "true")
+        DebugMode = (str(cf.get("Config", "DebugMode")).lower() == "true")
+        ParseEditor = (str(cf.get("Config", "Parse_Editor")).lower() == "true" )
+        ERR_LOG = cf.get("Config", "LogFile")
+        DBFile = cf.get("Config", "DBFile")
+        # read customer flag from config file 
+        IsCustomer = (cf.get("Config", "Is_Customer").lower() == 'true') if cf.has_option("Config", "Is_Customer") else True
+        print("Load config file input_config.ini success.")
+        if(len(sys.argv) >= 4):
+            # Only when sys.argv[3] == 'MTK' IsCustomer=False
+            if sys.argv[3].upper() == "MTK":
+                IsCustomer = False
+    except:
+        print("Open config file  config.ini error")
+        logging.error("Load config file error, please cehck")
+        raise
+    NVRAMLidDB_XML_File = cf.get("Config", "NVRAMLidDB_XML") if not db_file else db_file 
+    start = time.time()
+    logging.info("Start to Load Lid DB info file: " + NVRAMLidDB_XML_File)
+    if not IsCustomer:
+        DB_TAG.extend(INTERNAL_TAG)
+    # Parsing MD database
+    try:
+        MDDB = MDDBParser(NVRAMLidDB_XML_File)
+        print("Lid DB info Load success \n")
+        logging.info("Lid DB info Load success \n")
+    except Exception as e:
+        logging.error("Load MDDB error")
+        logging.error(traceback.format_exc())
+        print("Lid MDDB DB file: " + NVRAMLidDB_XML_File + " load fail")
+        raise
+        sys.exit(ERR_ERROR)
+    # Gen secure structure description
+    if build_path:
+        ERR_LOG = os.path.join(build_path, "nvram_auto_gen", ERR_LOG)
+    else:
+        ERR_LOG = os.path.join(gen_nvram_tool_path, ERR_LOG)
+    logging.info("Output version")
+    MTK_Version = MDDB.GetPlatformInfo("MTK_TARGET_SW_VERSION_FOR_CATCHER")
+    MTK_Project = MDDB.GetPlatformInfo("@PROJECT_NAME@MTK")  
+    logging.info("MTK_Version: {}".format(MTK_Version) )
+    logging.info("MTK_Project: {}".format(MTK_Project) )
+    
+    # write all groups and lid_group map 
+    web_db = gen_nvram_tool_path + "/" + DBFile
+    if not is_monitor:
+        sql_handler = SqlHandler(web_db, IsCustomer)
+    index = 0
+    MDDB_len = len(MDDB.LIDs)
+    for lid_name, lid_node in MDDB.LIDs.items():
+      index += 1
+      if not MDDB.GetLidInfo(lid_node):
+        continue
+      print("Check: "+lid_name+" (" + str(index) + "/" + str(MDDB_len) + ")")
+      logging.info("Check: {} ({}/{})".format(lid_name, index, MDDB_len))
+      filterDeep = CompareFilterConfig(Filter, lid_name)
+      print("  filterDeep: "+str(filterDeep))
+      logging.info("  filterDeep: {}".format(filterDeep))
+      if(filterDeep == -1):
+        continue
+      entry = MDDB.GetLidStructure(int(filterDeep))
+      print("  entry size: "+str(len(entry)))
+      logging.info("  entry size: {}".format(len(entry)))
+      if(len(entry) == 0):
+        continue
+      print("Output " + lid_name + " to Excel")
+      logging.info("Output {} to Excel".format(MDDB.lid_name ) )
+      if DebugMode:
+        print("[Debug]: MDDB.record_count " + str(MDDB.record_count))
+        for j in range(0, len(entry)):
+          print("  " + entry[j].name + " : " + entry[j].description + ", " + str(entry[j].offset) + ", " + str(entry[j].size))
+      
+      lid_details = FillEntry(MDDB, entry)
+      if lid_details and not is_monitor:
+          with sql_handler.conn:
+            sql_handler.lid_detail_writer(lid_details)
+     
+    print("Start: " + str(old_date))
+    print("End:   " + str(datetime.datetime.now()))
+    print("Collect Lid Info Successful")
+    
+    # monitor no need to generate DB
+    if not is_monitor:
+        with sql_handler.conn:
+            sql_handler.write_useful_data(MDDB, MTK_Project, MTK_Version)
+        generateEDB(web_db, cus_num, out_path=gen_nvram_tool_path + "/E"+DBFile)
+        if not DebugMode:
+            os.remove(web_db)
+    # Write tag conflict into log file
+    with open(ERR_LOG, "w") as f:
+        if STATUS:     # STATUS=0/1  SUCCESS/FAIL:
+            f.write("Result: {} , Bulid Error!\n".format(STATUS) )
+            for one_lid in TAG_CONFLICT.keys():
+                content = one_lid + ":\n\t" + "\n\t".join(TAG_CONFLICT[one_lid])+ "\n"
+                f.write(content)
+                STATUS = ERR_ERROR
+        else:
+            f.write("Result: {}, Bulid Success!\n".format(STATUS) )
+    return STATUS, MTK_Version, MTK_Project
+
+def init_log(l_file, level=logging.INFO, f_mod="w"):
+    # Config logging
+    # !!! Must be configure before first use logging
+    logging.basicConfig(filename=l_file, level=level, filemode=f_mod)
+    
+# Main funtion ===========================================================
+def main(db_file=None): 
+    global  gen_nvram_tool_path
+    
+    print("MTK NVRAM Description Generator " + app_version)
+    print("---------------------------------------")
+    logging.info("MTK NVRAM Description Generator " + app_version)
+    logging.info("---------------------------------------")
+    GenLidDBOnly = False
+    GenLidExcelOnly = False
+    result = ERR_OK
+    lidDB_path = ""
+  
+    if(len(sys.argv) < 3):
+        print("%%ERROR%%Invalid argument number:",len(sys.argv))
+        logging.error("Invalid argument number: {}, Please check usage".format(len(sys.argv)) )
+        usage()
+        sys.exit(ERR_ERROR) 
+    opts,args = getopt.getopt(sys.argv[1:],"heg")
+  
+    for op,value in opts:
+        if op == "-h":
+            usage()
+            sys.exit(ERR_OK)
+        elif op == "-e":
+            GenLidDBOnly = True
+        elif op == "-g":
+            GenLidExcelOnly = True
+            
+    gen_nvram_tool_path = os.path.dirname(os.path.realpath(sys.argv[0]))
+    if GenLidDBOnly:
+        build_path= os.path.realpath(sys.argv[2])
+        result = NvramGenDB(build_path)
+    elif GenLidExcelOnly:
+        result = NvramGenExcel(db_file)    
+    print("Done.")
+    logging.info("Done")
+    return result
+  
+
+if __name__ == "__main__":
+    init_log("gen_web_db.log")
+    main()
diff --git a/mcu/tools/NVRAMStatistic/nvram_gen_excel/nvram_monitor.py b/mcu/tools/NVRAMStatistic/nvram_gen_excel/nvram_monitor.py
new file mode 100644
index 0000000..ce7c002
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_gen_excel/nvram_monitor.py
@@ -0,0 +1,375 @@
+"""
+NVRAM monitor:
+    1. Tag conflict 
+    2. Description integrity
+Check and mail notify
+"""
+
+import time
+import os, sys, shutil
+from datetime import datetime
+# import pdb
+import sqlite3
+import traceback
+import io
+import re
+try:
+    import ConfigParser as configparser
+except ImportError:
+    # py3
+    import configparser
+    
+# import nvram_gen_LID_description_to_excel as gen_excel
+import nvram_gen_web_db as gen_excel
+import nvram_gen_LID_description_integrity_check as desc_check
+
+# GLOBAL variable
+PROJECT_PATH = ""
+BRANCH = ""
+
+class NotifyHandler(object):
+    
+    nvram_script_owner = ["MDNVRAM_SUPPORT@mediatek.com"]
+    msg_file = "/nvram_auto_gen/NVRAM_notify_msg.html"
+    user_file = "/nvram_auto_gen/NVRAM_notify_user.txt"
+    
+    def __init__(self, gen_nvram_tool_path):
+        # self.msgs = msg_list
+        self.head = u"""<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <body style="font-size:12pt;font-family:Calibri"><p><b>Dear all,</b></p>\
+    <div class="indentation" style="margin-left: 20px;">
+    <p><b>We found some NVRAM LIDs have the TAG conflict or no have the full description,<br/>
+    please the LID owner follow the<a href="http://wiki.mediatek.inc/display/NVRAM/How+to+Modify+module_nvram_editor.h" target="_blank">NVRAM Wiki</a> to fix it ASAP.<br/>
+    If you are not the right owner,please help update the LID owner on the <a href="http://nvram.mediatek.inc/" target="_blank">LID web system</a> <br/><br>
+    """
+        # self.label = label
+        # self.flavor = flavor
+        self.version_info = "<br>Branch Info: <br> Label: %%label%%<br/> Flavor: %%flavor%%<br/>\
+        Check time: %%cur_time%%</b></p>"
+        self.content = ""
+        self.end_str = "</div></body>"
+        self.notify_users = [] 
+        self.msg_file = sys.argv[1] + self.msg_file
+        self.user_file = sys.argv[1] + self.user_file
+     
+    def prepare_version_str(self):
+        self.version_info = self.version_info.replace("%%label%%", self.label)
+        self.version_info = self.version_info.replace("%%flavor%%", self.flavor)
+        now = datetime.now()
+        self.version_info = self.version_info.replace("%%cur_time%%", now.strftime("%Y-%m-%d %H:%M:%S"))
+        self.content = self.version_info + self.content
+        
+        
+    def seaction_generator(self, owner, owner_msg):
+        """owner_msg: msg object list of same owner"""
+        head = u"<hr><b>LID Owner: {} <br>".format(owner.split("(")[0])
+        end = "<br><br><br>"
+        # owner = owner
+        tag_head = "[LID list with conflicting TAG]<br><br><table border='1' style='font-size:'12';font-family:Calibri;'>"
+        desc_head = "[LID list without full description]<br><table border='1' style='font-size:'12';font-family:Calibri;'>"
+        tag_table = ""
+        desc_table = ""
+        
+        for one_msg in owner_msg:
+            assert one_msg.owner == owner
+            if one_msg.mail and one_msg.mail not in self.notify_users:
+                self.notify_users.append(one_msg.mail)
+                
+            # TAG conflict notify format [lid, msg]
+            if one_msg.tag_conflict:
+                cols = [one_msg.lid_name, "<br>".join(one_msg.tag_conflict)]
+                tag_table += self.table_row(cols)
+            # DESC uncomplete notify format [lid, struct list]
+            if one_msg.desc_uncomplete:
+                cols = [one_msg.lid_name, "<br>".join(one_msg.desc_uncomplete)]
+                desc_table += self.table_row(cols)
+        if tag_table:
+            cols = ["LID name", "Error message"]
+            tag_table = tag_head + self.table_row(cols, head=True)+tag_table + "</table>"
+        if desc_table:
+            cols = ["LID name", "Structure list"]
+            desc_table = desc_head + self.table_row(cols, head=True)+desc_table + "</table>"        
+        # head = head.replace("%%owner%%", owner)
+        self.content += head+tag_table+desc_table+end 
+        
+    
+    def fill_content(self, content):
+        self.content += content
+    
+    def table_row(self, keys, head=False):
+        content = "<tr>"
+        content += "".join(["<td>{}</td>".format(item) for item in keys])
+        content += "</tr>"
+        if head:
+            content = content.replace("td", "th")
+            content = content.replace("<tr>", "<tr bgcolor='lightgreen'>")
+        return content
+    
+    def write(self, label, flavor):
+        """write file"""
+        self.label = label
+        self.flavor = flavor
+        self.prepare_version_str()
+        # self.content = (self.head + self.content + self.end_str).encode("utf8")
+        self.content = (self.head + self.content + self.end_str)
+        # with open(self.msg_file, "w") as f:
+        with io.open(self.msg_file, "w", encoding="utf-8") as f:
+            f.write(self.content)
+        # Write notify user list
+        with open(self.user_file, "w") as f:
+            all_notify_users = set(self.nvram_script_owner + self.notify_users)
+            if DebugMode:
+                f.write(",".join(self.nvram_script_owner))
+            else:
+                f.write(",".join(all_notify_users))
+            
+            
+class MSG(object):
+    """MSG object
+    """
+    default_owner = "NA"
+    
+    def __init__ (self, lid):
+        self.owner = self.default_owner
+        self.mail = None
+        self.lid_name = lid
+        self.tag_conflict = []
+        self.desc_uncomplete = []
+        
+    # def __repr__(self):
+    #     return "<class MSG>: owner->{}, lid_name->:".format(self.owner, self.lid_name)
+
+def gen_excel_caller(cf):
+    """call gen excel for tag conflict check
+    return Gen_excel result: 0/1 => success/have tag conflict
+    """
+    result=  []
+    label = ""
+    flavor = ""
+    # build_path = sys.argv[1]
+    # Merge CAT xml with MDDB 
+    db_name = gen_mddb_with_default_value()
+    # db_name = "./tools/NVRAMStatistic/nvram_gen_excel/LR13.R1.MP.W19.04.LTE.p13_MT6779_SP_LWCTG_LidDBInfo.xml"
+    cf.set("Config", "NVRAMLidDB_XML", db_name)
+    # Call to Gen EXCEL CMD:python gen_excel.py -g  
+    sys.argv[1] = "-g"
+    sys.argv[2] = "Monitor"
+    # db_name=> ABS MDDB path for gen excel load 
+    result, label, flavor = gen_excel.main(db_file=db_name)
+    print("gen excel db result: {}".format(result) )
+    return result, label, flavor
+        
+def gen_mddb_with_default_value():
+    """Call Gen excel -e: 
+    Mearge cat xml into MDDB 
+    Return new DB name"""
+    assert len(sys.argv) == 2  
+    sys.argv.insert(1, "-e")
+    mddb_path = gen_excel.main()
+    
+    return mddb_path
+    
+    
+def collect_notify_lid(tag_conflict, notify_msg_obj_map, flag="tag"):
+    """
+    params: tag_conflict ==> {lid: [msg1, msg2]}
+    collect tag conflict lid to msg object
+    """
+    for lid, err_msg in tag_conflict.items():
+        if lid not in notify_msg_obj_map:
+            notify_msg_obj_map[lid] = MSG(lid)
+        obj = notify_msg_obj_map[lid]
+        if flag == "tag":
+            obj.tag_conflict.extend(err_msg)
+        else:
+            obj.desc_uncomplete.extend(err_msg)
+            
+            
+def crate_sqlite_connect(file_path):
+    conn = None
+    if not os.path.exists(file_path):
+        return conn
+        # raise Exception("SQLiteDB file {} not exists!".format(file_path))
+    try:
+        conn = sqlite3.connect(file_path)
+        # cursor = self.conn.cursor()
+        print("db create success")
+    except sqlite3.Error as e:
+        print("DB path: {}".format(file_path) )
+        print("create table error: ", e)
+    return conn
+            
+def find_owners(notify_msg_objs, db_conn):
+    """Find owner of notify lid, collect notify user email
+    db_conn: one sqlite db connect object
+    return: owner_msg_map
+    """
+    owner_msg_map = {}
+    owner_address = []
+    cursor = db_conn.cursor()
+    
+    sql = """
+    select first_name, email from auth_user where id=(select lid_branch.user_id from LIDMS_lidbranchinfo lid_branch
+    JOIN LIDMS_lidbasicinfo lid on lid.id= lid_branch.lid_id 
+    JOIN LIDMS_mdbranchinfo branch ON branch.id=lid_branch.branch_id
+    WHERE 
+        lid.name="{}"
+        and branch.name="{}");
+    """
+    for one_msg in notify_msg_objs.values():
+        try:
+            cursor.execute(sql.format(one_msg.lid_name, BRANCH ))
+            result = cursor.fetchone()
+            # print result     
+            if result:
+                one_msg.owner, one_msg.mail = result
+                
+        except Exception as e:
+            print('query owner: branch: {}, lid: {}'.format(BRANCH, one_msg.lid_name) )
+            print("Error when query owner: {}".format(e))
+            # continue
+            raise
+        finally:
+            if one_msg.owner in owner_msg_map:
+                owner_msg_map[one_msg.owner].append(one_msg)
+                assert one_msg.mail in owner_address
+            else:
+                owner_msg_map[one_msg.owner] = [one_msg]
+                owner_address.append(one_msg.mail)
+    cursor.close()
+    print("notify owner: {}".format(len(owner_address))  )
+    return owner_msg_map
+
+def choose_branch(db_con):
+    """correct branch
+    [UMOLYE, UMOLYA,VMOLY]
+    """
+    global BRANCH
+    
+    cursor = db_con.cursor()
+    cursor.execute("select * from LIDMS_mdbranchinfo where name='{}'".format(BRANCH) )
+    result = cursor.fetchone()
+    if not result:
+        BRANCH = " ".join([BRANCH, "TRUNK"])
+    cursor.close()
+    
+    
+def write_tmp_log(notify_lids, file_name):
+    # file_name = "nvram_monitor_notify_lids.txt"
+    cur_stamp = time.time()
+    desc_notify = []
+    tag_confilict_notify = []
+    for lid, msg_obj in notify_lids.items():
+        if msg_obj.tag_conflict:
+            tag_confilict_notify.append(lid)
+        if msg_obj.desc_uncomplete:
+            desc_notify.append(lid)
+            
+    with open(file_name, "w") as f:
+        f.write("Check time: {}\n".format(datetime.utcfromtimestamp(cur_stamp).strftime("%Y-%m-%d %H:%M:%S") ))
+        if desc_notify:
+            f.write("[DESC UNCOMPLETE]\n")
+            f.write("\n".join(desc_notify))
+        if tag_confilict_notify:
+            f.write("\n[TAG CONFLICT]\n")
+            f.write("\n".join(tag_confilict_notify))
+          
+          
+DebugMode = False
+                
+def main():
+    global DebugMode, BRANCH
+    print("nvram monitor begin")
+    gen_nvram_tool_path = os.path.dirname(os.path.realpath(sys.argv[0]))
+    build_path = os.path.realpath(sys.argv[1])
+    # Load config
+    config_file_path = gen_nvram_tool_path + "/input_config.ini" 
+    cf = configparser.ConfigParser()
+    cf.read(config_file_path)
+    DebugMode = (str(cf.get("Config", "DebugMode")).lower() == "true")
+    SQLiteDB = cf.get("Config","NvramWebSQLite") 
+    # SQLiteDB = gen_nvram_tool_path + "/monitor_source/db.sqlite3"
+    Parse_Editor = (str(cf.get("Config", "Parse_Editor")).lower() == "true")
+    
+    label = ""
+    flavor = ""
+    # 
+    start = time.time()
+    PROJECT_PATH = sys.argv[1]
+    print("project path: {}".format(PROJECT_PATH) )
+    notify_msg_obj = {}
+    # Init NotifyHandler obj for write report HTML 
+    notifier = NotifyHandler(gen_nvram_tool_path)
+    try:
+        # TAG conflict check
+        result, label, flavor = gen_excel_caller(cf)
+        if result:
+            print("tag conflict len: ",len(gen_excel.TAG_CONFLICT.keys()))
+            collect_notify_lid(gen_excel.TAG_CONFLICT, notify_msg_obj)
+            # raise Exception("Some error")
+
+        # find branch from label str
+        try:
+            BRANCH = re.split(".W\d{2}.\d{2}", label)[0]
+        except Exception as e:
+            BRANCH = ""
+            print("Branch not found, lable {}".format(label) )
+            notifier.fill_content("<p>"+ "Branch not found, lable: "+label+"</p>")
+        print("nvram monitor branch name: {}".format(BRANCH) )
+        if Parse_Editor:
+            # db_with_secure_lids = "/".join([build_path, "nvram_auto_gen", "MDDB_with_secure.xml"])
+            db_with_secure_lids = os.path.join(gen_nvram_tool_path, "MDDB_with_secure.xml")
+        else:
+            db_with_secure_lids = cf.get("Config", "NVRAMLidDB_XML")
+        print("------ ", db_with_secure_lids)
+        no_desc_dict = desc_check.main(xml_file=db_with_secure_lids)
+        if no_desc_dict:
+            print("desc check lid: {}".format(len(no_desc_dict.keys() )) )
+            collect_notify_lid(no_desc_dict, notify_msg_obj, flag="desc")
+    
+        print("Notify msg len: {}".format(len(notify_msg_obj.keys() ) ) )
+        if DebugMode:
+            monitor_log = "/".join( (build_path, "nvram_auto_gen", "nvram_monitor_notify_lids.txt"))
+            write_tmp_log(notify_msg_obj, monitor_log)
+        
+        # Find owner --- branch = "LR13.R1.MP"
+        conn = crate_sqlite_connect(SQLiteDB)
+        owner_msg_map = {}
+        if conn:
+            with conn as db_conn:
+                choose_branch(db_conn)
+                owner_msg_map = find_owners(notify_msg_obj, db_conn)
+        else:
+            owner_msg_map[MSG.default_owner] = notify_msg_obj.values()
+        if owner_msg_map:
+            na_owner = None
+            # DEBUG------
+            # new_msg = MSG("NVRAM_EF_SELF_TEST_LID")
+            # new_msg.tag_conflict.append("TAG: [TAG1, TAG2] have conflict") 
+            # if MSG.default_owner in owner_msg_map:
+                # owner_msg_map['NA'].append(new_msg)
+            # else:
+                # owner_msg_map['NA'] = [new_msg]
+            # ------
+            if MSG.default_owner in owner_msg_map:
+                na_owner = owner_msg_map[MSG.default_owner]
+                del owner_msg_map[MSG.default_owner]
+            for owner, msg_list in owner_msg_map.items():
+                notifier.seaction_generator(owner, msg_list)
+            if na_owner:
+                notifier.seaction_generator(MSG.default_owner, na_owner)
+        else:
+            notifier.fill_content("<p>There're no conflict LIDs!</p>")
+            
+    except Exception as e:
+        print("nvram monitor error: {}".format(e) )
+        err_msg = traceback.format_exc()
+        err_msg = err_msg.replace("\n", "<br>")
+        notifier.fill_content("<h2>Error: </h2><p>"+err_msg+"</p>")
+    finally:
+        notifier.write(label, flavor)
+    print("NVRAM monitor end.spend: {}".format(time.time()-start ))
+
+    
+if __name__ == "__main__":
+    main()
diff --git a/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/__init__.py b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/__init__.py
diff --git a/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/cus_keys/cus1.pub b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/cus_keys/cus1.pub
new file mode 100644
index 0000000..daab801
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/cus_keys/cus1.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC2mdmFhCCkseXanAkPQaecVVpeHWcsiJaedQnpFQQlNmgK29HmQpVXGJ4fSSdt4tgHeZYo7sG7inV/FP89F2Xza7DaUs2BfeKrmnkbEY1TGmNNSK2JXZzgvWzuZbyaWO/c5dRQMmnJFGS4vfGRu1kCxrOfgz+TrAdxTKd9hx92S/1vvuyJGQqpF1YxbqcQkeGchDfEidbl0sDZnFZ5+F2h7h20Sd3PL+uUjxcUHW+b5WRY95I9H9OvO36RvekkL22ZbeUjIPujRn6ROrcYg3ezrS8uO6RZMMukY50NZ6CfgIDqeJXI3dtoQCtk9Wfdz6zZkprG+C9NyCjaDweMcR65 CUS1
diff --git a/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/cus_keys/cus2.pub b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/cus_keys/cus2.pub
new file mode 100644
index 0000000..2b09ab0
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/cus_keys/cus2.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD7mHWGHF9em+m0pyX457AWtXMo9XM0XzApW2J42itFzHuVf92rq6ZHMa8H5zI5HgKIlqK4phs4gXNCYgB18E8ii28gfY/MSqLWIHQ3Jpf1Cy6ez1D1nNhJtGTNIkvVNbiEUL9JnS2vUNvIEicr7DYz1gs0F+L/eatJCSKpvwrwDrBFA/ds8utYiNUP1AWB4uOC15ZTZwWp3tCeB+My/3snppn1PYve0Ar1usL6A0vDpTMR6fNVC7gUPgguZv0SK3rDkTdV7i1C9bnls3ZhOKRXOoeFhcgVngM0erLV1cMq2HSSX3EArYfsSa3a73IJRGtN6iyH9bG5tUWLJjkKm+TD CUS2
diff --git a/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/cus_keys/cus3.pub b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/cus_keys/cus3.pub
new file mode 100644
index 0000000..02d96ae
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/cus_keys/cus3.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC/j+i8mkdzjSFPWuIKgh+rRxdkffcU6EiM0uwHO6ofKmKJp7rpjtwC+BNbgnWyErIsAwl5FdOL9S7Yt/epWsJOtSUZ8a+zqj02+2O7DptnLdxqzgDE90n1Q8/ozuH+Eo08p/Yc3XfaZxldISNGXwZyxiSfZgLcvsCwJtXn80QLUtzajyENm9wCHNQloH9j4c7ChptZ2i1ZAbjsloBQPB6TnlNGvJ6c3k3DbwZXahn2xOEa9cBUc9m5NxkPEGpPW9w0bvvco7natsYSks0LNCUzO/dmKrxexer+umW/Kvs5hpzj35yIWbpLgGrL0/Z4xpK4RRhR4KvLdJ7GZ9DdHcs9 CUS3
diff --git a/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/cus_keys/cus4.pub b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/cus_keys/cus4.pub
new file mode 100644
index 0000000..562f8f9
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/cus_keys/cus4.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDAPvmPYEbmkJm3II/FCqGcfedv4uig6IbaZvQN088rZqfEwjA36/8D+5ugh7obcCiRkxLCusSUfLe/CfKFk3cGj8GAGRt82gp7Arp5USLPWSf9OURO65GfkDtCOIpJY2ARWb540NVJq9U3gVN5OPlV08faMYinSNkVh0fttbmSzercIW5/gYRGDhIPz+5Z5gPKzPRRmE9GJ7Z6Z9L9OXJHWaoesSJP8AChzgkgdJJfLWrpzRKWeYs1KzuuCLzCGiCmMKzFJXCAUR775YGDaf9TIJAQELApAlhpMlj+XLapqWHFvzaaKPvk+IDUdnPwBp1uLAAZOjs33CLzy9mTu6DV CUS4
diff --git a/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/cus_keys/cus5.pub b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/cus_keys/cus5.pub
new file mode 100644
index 0000000..91f4c42
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/cus_keys/cus5.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC38ik/gM7r2gTRk8I1e3TyStpCOVUWPk3K89VgYJqevQuOS0ofANRPWo8MNed0taa02xPvxn9YnjBbEg3+wu42xf0mx0pGE6B/DBRDAOAhMD08OcFHVJBsNA77aNXR+zJ5q81ZxwPYBVoXySP0DHtAhR3lt9vE7vdcrP8wocKllvLrhcUD82D2wxdeHoaZe4coxZnyX8CCEtP9OPjLQIEuDNY8lNWYWt4rdCF0sAPAoOif3T4L8H4McQWi6rhe0BFFsgVaow3AxfONOHIM5JHcPydxEFUJ/bLGT2hf6+nxPgufXt8YvOk/zHhvPU2bS1pV7oyCZ8WSXHlU/5yBn9el CUS5
diff --git a/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/cus_keys/cus6.pub b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/cus_keys/cus6.pub
new file mode 100644
index 0000000..227f57c
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/cus_keys/cus6.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC3LiLFxBGlTMs1VBpgeLTYew773lCCgzqXRKWEGTNypduTqw9YHi1KpijEseBQ9qDMNbkVudgeoyH9rbfVYZ1SRZTpOnicegXW45dCIN0QKEi9oaY7/I5b6+/hVy+lp/tMRWpCi6TY8pyykg3JlCdHI1wfnEFb9nav2x3oL62YDiTfzE2eM+cpn63o7rFsQqGcy8JnVQBkiRKjbQpaA5prkcoqW+H3rxQ+aYSIlqoNatAta/k7worrdmw4iyhNlaONbSlZ9ewXsbbKs7V2k0eslpSLVrhzVLcMmXbR5D+EzkmCl6HNvJMpTvYpygX+/69EUPBhfviU8DL2w49tSkIf CUS6
diff --git a/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/cus_keys/cus7.pub b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/cus_keys/cus7.pub
new file mode 100644
index 0000000..440daa3
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/cus_keys/cus7.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC2vuwnTMDdFP+6Gz6Z+Qz+QvrCYOe+/SpqNHJJGRxzebKsyfUG+K1CX+hip8mmwJ+bOTdqphXfMW5aS+rD/VXT1t2e5fVz3CU+FBWd6HAdoYiyXZo55UzrYFMFNQt0u1pCkdtnpOGpRU/7UOo9TCKJ7tfZ6j4JJKj/gcBLtOcL5gJgU6N4/l+TQ7U8W44bXtNTxg6WSghlzpRJ33h0HyXanhodjfIrqi6IE86qZJShtULPeXkCZOOchJc1PlRkCAPFv8GdORX8kHC9a2yQQtoP1EHPQFxzhaB3VTg/BK83IjSjEMb49I5d2oJYd5pFjpR90TMJRXHYJimQ9HZ/tggB CUS7
diff --git a/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/cus_keys/cus8.pub b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/cus_keys/cus8.pub
new file mode 100644
index 0000000..c4a5166
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/cus_keys/cus8.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+l1SfBDDwvYFfAFzjrzrpyQnT/HEwsQ3HJU/fSTNDfpBn9bm4575MKSgPFew/2OWGjuTF6To3Q5jRMpYNT/2jvi3mBZ/p4CbxhqwEGUgzya1rr0e7mWPC3GQ43Dd1SE4rWp+W+NjRfqvFZIoZinPNgySNAd0rCayons2URnQaY41f0arOQ/NAUxcZ322RBk2aDPIpOuEj6+GE9WUp5o3xWe+HuIqQyfd7FRffeVfjQ0L/HQOe2xhOal7XQZXaB048A0DnkdPBjbPNsJVV9qfuW/S079DN4CyEkwuxmXzS2QU68m2qcVyZPSa+4X1B+ycixFlEq7B9vkMDnAWB2C37 CUS8
diff --git a/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/cus_keys/cus9.pub b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/cus_keys/cus9.pub
new file mode 100644
index 0000000..88c7d83
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/cus_keys/cus9.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDGNWSoe+RN+zha5hK6EwiYQf/FbRfAlmzDWdCqutU/i7wq67bX3+ZPNa0/97NtlRTNRYd+ZH1APPAKVQLTQAPqcZvxfjXfnUMlhMRH9I9xWp2gbtipBnW7iYAtXFRLqN8IL8ADi/N3fr+dDvDKrCXqYwyRR03OzKreEH7cFH3c18c69bOp9H2m9rA+rx0j8L37RO7OfqmlvbUWvkpMdUJBzeUATaWZPVstKJOpexATPwNNYl2D77S1cbny9rKTnYJa5RPkNT8U1A50ZbmWF8gRukgGEO+ACn1V+vVRyqBl3TaCw57wTO4RvAMl2M7LZCh0XS7Wz2TJs3y0LQyOW5RX CUS9
diff --git a/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/editorParser.py b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/editorParser.py
new file mode 100644
index 0000000..10c179e
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/editorParser.py
@@ -0,0 +1,241 @@
+"""
+Parse structure description from editor
+folder:[list] list of editor file/folder
+lids: Lids need to parse, if None: parse all lids 
+"""
+import os
+import re
+import json
+import pdb
+import logging
+
+class EditorParser(object):
+    def __init__(self, folders, LIDs=None):
+        """parse lid structure description from pointed floders editors
+        folders: [type:list] 
+        LIDs:[type:list] lid name list of need parse, all LID if LIDs=None
+        """
+        self.lids = LIDs
+        self.files = self._translate_folder(folders)
+        self.l_stu_map = {}
+    
+    def _translate_folder(self, folders):
+        """translate folder to editor file list
+       folders: can be single/list folder, single/list file 
+        editor file: file name **_editor.h | ['nvram_editor_data_item.h']    
+        """
+        file_list = []
+        
+        if isinstance(folders, list):
+            for path in folders:
+                # if folder : find editor files
+                path = os.path.realpath(path)
+                if os.path.isdir(path):
+                    editor_file = self._collect_folder_editor_file(path)
+                    file_list.extend(editor_file)
+                else:
+                    file_list.append(path)
+                    
+        elif os.path.isdir(folders):
+            editor_file = self._collect_folder_editor_file(folders)
+            file_list.extend(editor_file)
+        else:
+            file_list.append(folders)
+        return file_list
+    
+    def _collect_folder_editor_file(self, path):
+        special_editors = ['nvram_editor_data_item.h']
+        editors = []
+        for d_path, name, filenames in os.walk(path): 
+            for one_file in filenames:
+                if one_file.endswith("_editor.h") or one_file in special_editors:
+                    editors.append(d_path + "/" +one_file)
+        return editors
+    
+    
+    def parse_editor_description(self, section):
+        """find struct_name and description mapping from editor code section
+        regular:
+            Field:          "name": "description"
+            NVRAM_Bit_Data: "name": bit_count + "description" 
+            bit_value:      "0x ": description
+        result_map(dict)=> 
+        name: 
+            {   description: desc, 
+                Bit_data:[{name: desc}]}
+        """
+        result_map = {}
+        parent_name = "" 
+        bit_data = {}
+        is_array = False
+        # bit_data_re regular to match bit_data name
+        bit_data_re = re.compile(r".+(\s*):(\s*)\d")
+        bit_value_re = re.compile(r"^0x\d+")
+        array_re = re.compile(r"[a-zA-Z_\d\.]+(\[\d\])+")       # Match format like: a.b.c[0][1] {};
+        
+        for line in section:
+            line = re.sub(r'[";\{\}]', "", line)
+            if not line:
+                continue
+            if ":" not in line:
+                # Try to match array  => array[0] {} TODO array[*]
+                array_line = array_re.match(line)
+                # pdb.set_trace()
+                if array_line:
+                    is_array = array_line
+                    is_array = is_array.group()
+                    assert parent_name in is_array
+                    is_array = is_array[len(parent_name):].strip()
+                continue
+            # match bit data
+            bit_name = bit_data_re.match(line)
+            if bit_name:
+                # if have bit data didn't join result map join it
+                if bit_data:
+                    result_map[parent_name]["bit_data"].append(bit_data)
+                    bit_data = {}
+                bit_name = bit_name.group()
+                name, bit_count = bit_name.split(":")
+                description = line[len(bit_name):].strip()
+                bit_data = {"name": name, "bit_count":bit_count.strip(), 
+                    "description":description, "bit_value":[], "array": is_array}
+            elif bit_value_re.match(line):
+                # bit value data: add into bit data list
+                name = bit_value_re.match(line).group()  # 0x
+                value = line[len(name)+1:]
+                name = str(int(name, 16))
+                value = ":".join([name, value])
+                bit_data["bit_value"].append({"name":name, "description":value})
+            else:
+                if bit_data:
+                    # bit data join result_map
+                    result_map[parent_name]["bit_data"].append(bit_data)
+                    bit_data = {}
+                    # parent_name = ""
+                index = line.find(":")
+                key = line[:index].strip()
+                if "*" in key:
+                    continue
+                value = line[index+1:]
+                # TODO struct A: no description but A have bit data 
+                result_map[key] = {"description": value.replace('"', ''), "bit_data":[]}
+                parent_name = key
+                is_array = False
+        # Merge last bit data in 
+        if bit_data and parent_name:
+            result_map[parent_name]["bit_data"].append(bit_data)
+        return result_map
+    
+    def extract_desc(self):
+        """Parse secure LID structure description and merge into MDDB structure"""
+        # sec_lid_type_map = {item.get("name"): item.get("type_name") for item in self.secure_lids} 
+        
+        line_re = re.compile(r"LID_BIT[\sA-Z_]*VER_LID\s*\(NVRAM_EF_[A-Z\d_]+_LID\)")
+        lid_re = re.compile(r"NVRAM_EF_[A-Z\d_]+_LID")
+        for editor_file in self.files:
+            if not os.path.exists(editor_file):
+                logging.info("editor file: {} not found in disk Bypass!".format(editor_file))
+                continue
+            with open(editor_file) as f:
+                content = f.readlines()
+            content = [item.strip() for item in content]
+            # Match all LID description in editor 
+            matched = filter(line_re.match, content)
+            for index in range(0, len(matched)):
+                match_item = matched[index]
+                lid_name = lid_re.search(match_item).group()
+                if self.lids and lid_name not in self.lids:
+                    continue
+                start_index = content.index(match_item)
+                # Lid code section
+                if index == len(matched)-1:
+                    section = content[start_index:]
+                else:
+                    end_line = content.index(matched[index+1])
+                    if end_line > start_index:
+                        section = content[start_index: end_line]
+                    else:
+                        # ASSERT never hit
+                        # pdb.set_trace()
+                        next_matched = filter(line_re.match, content[start_index+1:])
+                        end_line = content[start_index: ].index(next_matched[1])
+                        section = content[start_index: start_index+end_line]
+                # Find lid structure description
+                struct_name_desc_map = self.parse_editor_description(section)
+                if struct_name_desc_map:
+                    self.l_stu_map[lid_name] = struct_name_desc_map
+                    # For DebugMode :
+                    # self.l_stu_map[lid_name] = struct_name_desc_map
+                    # tmp_secure_desc = "tmp_secure_desc.json"
+                    # with open(tmp_secure_desc, "a+") as f:
+                    #     f.write("LID: {}\n".format(lid_name))
+                    #     f.write(json.dumps(struct_name_desc_map)+"\n")
+                    #     f.write("--------------------------------------------\n")
+
+
+# EditorParser Class =======================================================
+class EditorHeaderParser:
+  """
+  collect LID description & information
+  """
+  def __init__(self, lines=None):
+    self.offset = 0
+    # header: [lid_name, description, information]
+    self.header = ['','','']
+    self.lines = lines      # .split('\n')
+    self.lid_name_p = re.compile(r"NVRAM_EF_[A-Z\d_]+_LID")
+    self.head_p = re.compile(r"(\*)\s*NVRAM_EF_[A-Z\d_]+_LID")
+  
+  def FindLidHeader(self):
+    """Find LID editor section start lines"""
+    # LID head editor start line: '* NVRAM_EF_DRP_IMS_PROFILE_LID'
+    end = False
+    while self.offset < len(self.lines):
+        if self.head_p.match(self.lines[self.offset]):
+            return self.offset
+        self.offset += 1
+    return end
+  
+  def GetLidHeader(self):
+    # parse lid description & information from lid description header
+    self.header = ["", "", ""]
+    head_line = self.lines[self.offset]
+    self.header[0] = head_line.replace("*", "").strip()
+    desc = False
+    info = False
+    info_index = -1
+    offset = 0
+    while self.offset < len(self.lines):
+        self.offset += 1
+        line = self.lines[self.offset]
+        if not line.startswith("*"):
+            break
+        if "DESCRIPTION" in line:
+            desc = True
+            continue
+        if 'INFOMATION' in line or 'INFORMATION' in line:
+            desc = False
+            info = True
+            continue
+        if desc:
+            self.header[1] += line.replace("*", "").strip()
+        elif info:
+            if "*/" not in line:
+                self.header[2] += line.replace("*", "").strip()
+            
+    lid_name  = self.lid_name_p.search(self.lines[self.offset])
+    if lid_name:
+        lid_name = lid_name.group()
+        if lid_name != self.header[0]:
+            print("LID NAME differ: {} -> {}".format(lid_name, self.header[0]))
+        self.header[0] = lid_name
+    self.offset += 1
+    return self.header
+    
+
+def main(folder, lids=None):
+    pass
+    
+
+if __name__ == "__main__":
+    main()
diff --git a/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/encryptDB.py b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/encryptDB.py
new file mode 100644
index 0000000..9579d20
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/encryptDB.py
@@ -0,0 +1,106 @@
+import os
+import time
+import pdb
+from Crypto.PublicKey import RSA
+from Crypto.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5
+from Crypto import Random
+from Crypto.Cipher import AES
+from functools import wraps
+import base64
+import logging
+
+
+rng = Random.new().read
+
+pub_file_path = "cus_keys/"
+ori_file = "../NVRAM_LID_Detail.db"
+
+def time_counter(func):
+    @wraps(func)
+    def decorate(*args, **kwargs):
+        start = time.time()
+        result = func(*args, **kwargs)
+        print("{} spend: {}".format(func.__name__, time.time()-start ))
+        return result
+    return decorate
+
+    
+@time_counter
+def generateEDB(db_file, cus_num, out_path): 
+    # AES enc
+    with open(db_file, "rb") as f:
+        content = f.read()
+    aes_content = aes_obj.encrypt(content)
+    
+    # reaD PUBLIC key
+    key_file = cus_num.lower()
+    key_file = os.path.join(os.path.dirname(db_file), "utils", pub_file_path , key_file[:3] + key_file[-1] + ".pub")
+    try:
+        assert os.path.exists(key_file)
+    except AssertionError:
+        print("Error: key file {} not exists".format(key_file) )
+        raise(AssertionError, "file not exists" )
+    pub_key = RSA.importKey(open(key_file))
+    cipher = Cipher_pkcs1_v1_5.new(pub_key)
+    
+    rsa_text = cipher.encrypt(aes_obj.key)
+    rsa_text = base64.b64encode(rsa_text)
+    enc_content = rsa_text + aes_content
+    
+    with open(out_path, "wb") as f:
+        f.write(enc_content)
+    # os.remove(db_file)
+    return enc_content
+    
+            
+@time_counter
+def dec_file(filename):
+    with open(filename, "rb") as f:
+        content = f.read()
+    
+    key = RSA.importKey(open(pri_file))
+    cipher = Cipher_pkcs1_v1_5.new(key)
+    block_one = content[:344]
+    block_one = base64.b64decode(block_one)
+    dec_one = cipher.decrypt(block_one, rng)
+    print("block_one : {}".format(dec_one))
+    # duicheng decript
+    dec_content = aes_obj.decrypt(content[344:])
+    with open('new_db.db', "wb") as f:
+        f.write(dec_content)
+    print("Done")
+    
+    
+class AESCipher(object):
+    
+    def encrypt(self, content):
+        # return hex str
+        self.key = Random.get_random_bytes(16)
+        self.iv = Random.get_random_bytes(16)
+        padding = " "
+        # if not len(content)%16:
+        #    content += (16 - len(content)%16) * padding  
+        cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
+        enc_text = cipher.encrypt(content)
+        self.key  = (self.key+ self.iv).encode("hex")
+        
+        return enc_text.encode("hex")
+    
+    def decrypt(self, con):
+        con = con.decode("hex")
+        self.key = self.key.decode("hex")
+        self.iv = self.key[17:]
+        self.key = self.key[:17]
+        obj2 = AES.new(self.key, AES.MODE_CBC, self.iv)
+        dec_text = obj2.decrypt(con)
+        return dec_text
+    
+aes_obj = AESCipher()
+    
+if __name__ == "__main__":
+    encrypted = ''
+    encrypted_file = "enc_ffff.db"
+    encrypted = enc_file(ori_file, encrypted_file)
+    # print("encrypt text: {}".format(encrypted) )
+    dec_file(encrypted_file)
+    #  aes_enc()
\ No newline at end of file
diff --git a/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/mddb_utils.py b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/mddb_utils.py
new file mode 100644
index 0000000..46b9291
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/mddb_utils.py
@@ -0,0 +1,511 @@
+
+import os
+import re
+import sys
+import time
+import shutil
+import platform
+import datetime
+import glob, gzip
+import pdb 
+import json
+import logging
+ 
+try:
+    import xml.etree.cElementTree as ET
+except ImportError:
+    import xml.etree.ElementTree as ET
+
+    
+ERR_OK, ERR_ERROR = [0, 1]
+STATUS = ERR_OK
+DebugMode = False
+    
+# EditorParser Class =======================================================
+class EditorHeaderParser:
+  """
+  collect LID description & information
+  """
+  def __init__(self, lines=None):
+    self.offset = 0
+    # header: [lid_name, description, information]
+    self.header = ['','','']
+    self.lines = lines      # .split('\n')
+    self.lid_name_p = re.compile(r"NVRAM_EF_[A-Z\d_]+_LID")
+    self.head_p = re.compile(r"(\*)\s*NVRAM_EF_[A-Z\d_]+_LID")
+  
+  def FindLidHeader(self):
+    """Find LID editor section start lines"""
+    # LID head editor start line: '* NVRAM_EF_DRP_IMS_PROFILE_LID'
+    end = False
+    while self.offset < len(self.lines):
+        if self.head_p.match(self.lines[self.offset]):
+            return self.offset
+        self.offset += 1
+    return end
+  
+  def GetLidHeader(self):
+    # parse lid description & information from lid description header
+    self.header = ["", "", ""]
+    head_line = self.lines[self.offset]
+    # index = self.lines.index(head_line)
+    self.header[0] = head_line.replace("*", "").strip()
+    desc = False
+    info = False
+    info_index = -1
+    offset = 0
+    while self.offset < len(self.lines):
+        self.offset += 1
+        line = self.lines[self.offset]
+        if not line.startswith("*"):
+            break
+        if "DESCRIPTION" in line:
+            desc = True
+            continue
+        if 'INFOMATION' in line or 'INFORMATION' in line:
+            desc = False
+            info = True
+            continue
+        if desc:
+            self.header[1] += line.replace("*", "").strip()
+        elif info:
+            if "*/" not in line:
+                self.header[2] += line.replace("*", "").strip()
+            
+    lid_name  = self.lid_name_p.search(self.lines[self.offset])
+    if lid_name:
+        lid_name = lid_name.group()
+        if lid_name != self.header[0]:
+            print("LID NAME differ: {} -> {}".format(lid_name, self.header[0]))
+        self.header[0] = lid_name
+    self.offset += 1
+    return self.header
+    
+def WriteEelementDoc(fl_doc,filename):
+        print '[WriteEditorInfo]: filename:{}'.format(filename)
+        content = ET.tostring(fl_doc, "utf-8")
+        with open(filename, "w") as f:
+            f.write(content.replace("><", ">\n<"))
+        
+    
+def CollectEditorInfo(filelist, gcc_path, build_path, parent_element):
+  # global gcc_path
+  global gcc_include
+  include = ""
+  
+  fileW = open('nvram_editor_data_item.c', 'w')
+  for path in filelist:
+    for parent,dirname,filenames in os.walk(path):
+      for fname in filenames:
+        if(fname.find('_editor.h')>0 or fname=='nvram_editor_data_item.h'):
+          # find editor file
+          fileW.write('#include "'+fname+'"\n')
+      break
+    include += (' -I "'+path+'"')
+  fileW.close()
+  output = ""
+  if(platform.system() == "Windows"):
+    gcc_include = include
+  ps = os.popen(gcc_path+' -DGEN_FOR_PC -E -C -imacros gcc_option.h -fno-strict-aliasing -fshort-enums -c -w nvram_editor_data_item.c '+gcc_include)
+  
+  #remove the white line
+  lines = ps.readlines()
+  ps.close()
+  lines = [line for line in lines if line.strip()]
+  tmp_path = build_path + '/nvram_auto_gen/nvram_editor_temp.txt'
+  # if DebugMode:
+  with open(tmp_path,'w') as f:
+    f.write("".join(lines))
+  # pdb.set_trace()
+  parser = EditorHeaderParser(lines)
+  # while parser.offset < len(lines):
+  while  parser.FindLidHeader():
+      header = parser.GetLidHeader()
+      lid = ET.SubElement(parent_element, header[0])
+      lid.set("LID_NAME", header[0])
+      lid.set("DESCRIPTION", header[1])
+      lid.set("INFORMATION", header[2])
+  # print("All lid {}, error str'infomation' {}".format(len(headers), parser.count) )
+  
+
+
+def PrepareGCCEnvironment(build_path, mcu_path):
+  # Prepare compile option
+  global gcc_include
+  option_items = []
+  
+  StartParsing = 0
+  option_path = build_path + "/bin/log/info.log"
+  file = open(option_path)
+    
+  for line in file:
+    line = line.strip()
+    if "[ COMMON OPTION ]" in line:
+        StartParsing = 1
+        continue
+    
+    if(line.find("[") > -1):
+      break
+    if((StartParsing == 1) and len(line)):
+      line = line.replace("=", " ")
+      option_items.append('#define '+line)
+  with open('gcc_option.h', "w") as f:
+    f.write("\n".join(option_items))
+  # include path
+  inc_file = build_path + "/tmp/~inc.tmp.tmp"
+  inc_lines = []
+  with open(inc_file, "r") as f:
+    inc_lines = f.readlines()
+  gcc_include = '-I "' + '" -I "'.join([os.path.realpath(mcu_path+"/"+line.strip()) for line in inc_lines])+'"'
+  file.close() 
+
+  
+def CatAttributeMerage(lid, cat_lid, parent_element):
+    """merge lid attribute(id, record_size, total_record, attribute..) from cat.xml to MDDB"""
+    def_val = cat_lid.find("DEFAULT_VALUE")
+    #print "def_val" + str(defa_val)
+    def_fill = def_val.get("defaultByteFill")
+    if def_val.text:
+      def_fill = re.sub(r'[,\s\[\]]', r'', def_val.text).replace("0x", "")
+    lid_name = cat_lid.get("id")
+    if lid is None:
+        lid = ET.SubElement(parent_element, lid_name)
+        lid.set('LID_NAME', lid_name)
+        if DebugMode:
+            print "[Debug]: append a new lid:" + lid_name + " record_size:" + str(cat_lid.getAttribute("record_size")) + " total_record:" + str(cat_lid.getAttribute("total_record"))
+    else:
+        if DebugMode:
+            print "[Debug]: update lid info:" + lid_name + " record_size:" + str(cat_lid.getAttribute("record_size")) + " total_record:" + str(cat_lid.getAttribute("total_record"))
+    lid.set('record_size', cat_lid.get("record_size"))
+    lid.set('total_record', cat_lid.get("total_record"))
+    lid.set('lid_enum', cat_lid.get("lid_enum"))
+    lid.set('category', cat_lid.get("category", ""))
+    lid.set('attribute', cat_lid.get("attribute"))
+    lid.set('defaultByteFill', def_fill)
+    if DebugMode and ("()" in def_fill):
+        print "[Debug]: " + lid_name + " default value generated from callback function"
+    return lid
+
+
+def NvramGenDB(b_path):
+    """
+    Target:Merge cat.xml(default value, attribute...) into MDDB for gen excel
+    return: new db path
+  """
+    global build_path
+    old_date = datetime.datetime.now()
+    
+    build_path = b_path
+    autogen_root = ET.Element("ROOT")
+    element_lid_info = ET.SubElement(autogen_root, "LID_INFO")
+    autogen_tree = ET.ElementTree(autogen_root)
+    
+    # Parsing editor.h for LID description & information
+    split_path_array = build_path.split("/")  
+    project_name = split_path_array[-2]
+    flavor_name = split_path_array[-1]
+    print "project_name: " + project_name + " flavor_name: " + flavor_name
+    project_flavor = project_name + "_" + flavor_name
+    
+    mcu_path = "/".join(split_path_array[:-3])
+    mcu_path = os.path.realpath(mcu_path)
+    if(platform.system() == "Windows"):
+      gcc_path = os.path.realpath(mcu_path + '/tools/MinGW/bin/gcc.exe')
+    else:
+      gcc_path = 'gcc'
+    PrepareGCCEnvironment(build_path, mcu_path)
+    
+    filelist = [mcu_path + '/interface/service/nvram']
+    filelist.append(mcu_path + '/custom/driver/common')
+    filelist.append(mcu_path + '/custom/middleware/common')
+    filelist.append(mcu_path + '/custom/modem/common/ps')
+    filelist.append(mcu_path + '/interface/driver/drv_def')  
+    CollectEditorInfo(filelist, gcc_path, build_path, element_lid_info)
+    # WriteEditorInfo(ET.tostring(autogen_root), "a_liddb_doc.xml")
+    
+    os.remove(r'gcc_option.h')
+    os.remove(r'nvram_editor_data_item.c')
+    print "Parsing editor.h success."
+    # Unzip MD database *.GZ
+    try:
+        dhl_path = os.path.realpath(build_path + '/dhl/database')
+        dhl_path = glob.glob(dhl_path + "/*.GZ")
+        g=gzip.GzipFile(mode='rb', fileobj=open(dhl_path[0],'rb'))
+        open(r'MDDB.XML','wb').write(g.read())
+        g.close()
+        print "Unzip MD database success."
+    except Exception as e:
+        print "MD database unzip fail."
+        print("Error: {}".format(e) )
+        STATUS = ERR_ERROR
+        # pause()
+        sys.exit()
+
+    # Merge custom_nvram_lid_cat.xml to MDDB (default value, attribute, struct_size...)
+    try:
+      MDDB_tree = ET.ElementTree(file="MDDB.XML")
+      MDDB_root = MDDB_tree.getroot()
+      # -----------------------
+      codegen_lids = {item.get("name"): item for item in MDDB_tree.iter('NVRAM_LID')}
+      codegen_struct_size_map = {item.get("name"): item.get("size") \
+            for item in MDDB_tree.iter(tag="Struct")}
+      codegen_define_type_size_map = {item.get("name"): item.get("size") for item in MDDB_tree.iter("Typedef")}
+      
+      cat_path = os.path.realpath(build_path + '/nvram_auto_gen/custom_nvram_lid_cat.xml')
+      cat_tree = ET.ElementTree(file=cat_path)
+      cat_root = cat_tree.getroot()
+      # AUTO GEN LID
+      autogen_lids = {}
+      nvitem = cat_root.iter('NVRAMITEM')
+      for cat_lid in nvitem:
+        lid_name = cat_lid.get("id")
+        autogen_lids[lid_name] = cat_lid
+        
+        autogen_lid = element_lid_info.find(lid_name)
+        autogen_lid = CatAttributeMerage(autogen_lid, cat_lid, element_lid_info)
+        # Check LID in AUTO gen but not in codegen
+        if lid_name not in codegen_lids:
+            if DebugMode:
+                print "[Waring]: {} in Autogen not in Codgen".format(lid_name)
+            continue
+        # Check lid's record size and structure size whether match
+        cat_lid_type = codegen_lids[lid_name].get("type_name")
+        size = ""
+        if cat_lid_type in codegen_struct_size_map:
+            size = codegen_struct_size_map[cat_lid_type]
+        elif cat_lid_type in codegen_define_type_size_map:
+            size = codegen_define_type_size_map[cat_lid_type]
+        if size != autogen_lid.get("record_size") and DebugMode:
+            if size == "":
+                print "can't find out struct_size for lid:{}".format(lid_name)
+            else:
+                print "[Waring]: " + lid_name + " record size(" + autogen_lid.getAttribute('record_size') + ") in Autogen mismatch with codegen(" + size + ")"            
+        autogen_lid.set("struct_size", size)
+      # WriteEelementDoc(autogen_root, "a_liddb_doc.xml")
+      
+      # Check lid in codegen not in AUTO GEN
+      for lid in codegen_lids:
+        if lid not in autogen_lids and DebugMode:
+            print "[Warning]: {} in Codgen not in Autogen".format(lid)
+      # Merge
+      autogen_root.append(MDDB_root)
+      
+      # Write new MDDB to disk
+      lidDB_version = ""
+      sw_version_element = MDDB_root.find("*/Information/[@name='MTK_TARGET_SW_VERSION_FOR_CATCHER']")
+      lidDB_version = sw_version_element.get("value", "")
+      
+      project_flavor = lidDB_version + "_"+ project_flavor
+      lidDB_filename = project_flavor + "_LidDBInfo.xml"
+      lidDB_path = os.path.realpath(build_path + '/nvram_auto_gen/' + lidDB_filename)
+      print("New MDDB path: {}".format(lidDB_path) )
+      # WriteEditorInfo(lidDB_doc,lidDB_path)
+      WriteEelementDoc(autogen_root, lidDB_path)
+      # merge db success
+      print "Merge custom_nvram_lid_cat.xml to MDDB success."
+    except Exception as e:
+      print build_path + "/nvram_auto_gen/custom_nvram_lid_cat.xml load fail."
+      STATUS = ERR_ERROR
+      raise
+      # pause()
+      sys.exit()
+    print "Generate LID DB success,you can find the file:"
+    print lidDB_path + "\n"
+    print "Start: " + str(old_date)
+    print "End:   " + str(datetime.datetime.now())
+    return lidDB_path
+
+class EditorParser(object):
+    def __init__(self, folders, LIDs=None):
+        """parse lid structure description from pointed floders editors
+        folders: [type:list] 
+        LIDs:[type:list] lid name list of need parse, all LID if LIDs=None
+        """
+        self.lids = LIDs
+        self.files = self._translate_folder(folders)
+        self.l_stu_map = {}
+        print("-------------")
+    
+    def _translate_folder(self, folders):
+        """translate folder to editor file list
+        editor file: file name **_editor.h | ['nvram_editor_data_item.h']    
+        """
+        file_list = []
+        
+        if isinstance(folders, list):
+            for path in folders:
+                # if folder : find editor files
+                path = os.path.realpath(path)
+                if os.path.isdir(path):
+                    # for d_path, name, filenames in os.walk(path):
+                    editor_file = self._collect_folder_editor_file(path)
+                    file_list.extend(editor_file)
+                else:
+                    if os.path.exists(path):
+                        file_list.append(path)
+                    else:
+                        pdb.set_trace()
+                        print(" ****  Assert never hit!!!!!")
+        elif os.path.isdir(folders):
+            editor_file = self._collect_folder_editor_file(folders)
+            file_list.extend(editor_file)
+        else:
+            file_list.append(folders)
+        return file_list
+    
+    def _collect_folder_editor_file(self, path):
+        special_editors = ['nvram_editor_data_item.h']
+        editors = []
+        for d_path, name, filenames in os.walk(path): 
+            for one_file in filenames:
+                if one_file.endswith("_editor.h") or one_file in special_editors:
+                    # TODO one_file is full path ?????
+                    editors.append(d_path + "/" +one_file)
+        return editors
+    
+    
+    def parse_editor_description(self, section):
+        """find struct_name and description mapping from editor code section
+        regular:
+            Field:          "name": "description"
+            NVRAM_Bit_Data: "name": bit_count + "description" 
+            bit_value:      "0x ": description
+        result_map(dict)=> 
+        name: 
+            {   description: desc, 
+                Bit_data:[{name: desc}]}
+        """
+        result_map = {}
+        parent_name = "" 
+        bit_data = {}
+        is_array = False
+        # bit_data_re regular to match bit_data name
+        bit_data_re = re.compile(r".+(\s*):(\s*)\d")
+        bit_value_re = re.compile(r"^0x\d+")
+        array_re = re.compile(r"[a-zA-Z_\d\.]+(\[\d\])+")       # Match format like: a.b.c[0][1] {};
+        
+        for line in section:
+            line = re.sub(r'[";\{\}]', "", line)
+            if not line:
+                continue
+            if ":" not in line:
+                # Try to match array  => array[0] {} TODO array[*]
+                array_line = array_re.match(line)
+                # pdb.set_trace()
+                if array_line:
+                    is_array = array_line
+                    is_array = is_array.group()
+                    assert parent_name in is_array
+                    is_array = is_array[len(parent_name):].strip()
+                continue
+            # match bit data
+            bit_name = bit_data_re.match(line)
+            if bit_name:
+                # if have bit data didn't join result map join it
+                if bit_data:
+                    result_map[parent_name]["bit_data"].append(bit_data)
+                    bit_data = {}
+                bit_name = bit_name.group()
+                name, bit_count = bit_name.split(":")
+                description = line[len(bit_name):].strip()
+                bit_data = {"name": name, "bit_count":bit_count.strip(), 
+                    "description":description, "bit_value":[], "array": is_array}
+            elif bit_value_re.match(line):
+                # bit value data: add into bit data list
+                name = bit_value_re.match(line).group()  # 0x
+                value = line[len(name)+1:]
+                name = str(int(name, 16))
+                value = ":".join([name, value])
+                bit_data["bit_value"].append({"name":name, "description":value})
+            else:
+                if bit_data:
+                    # bit data join result_map
+                    result_map[parent_name]["bit_data"].append(bit_data)
+                    bit_data = {}
+                    # parent_name = ""
+                index = line.find(":")
+                key = line[:index].strip()
+                if "*" in key:
+                    continue
+                value = line[index+1:]
+                # TODO struct A: no description but A have bit data 
+                result_map[key] = {"description": value.replace('"', ''), "bit_data":[]}
+                parent_name = key
+                is_array = False
+        # Merge last bit data in 
+        if bit_data and parent_name:
+            result_map[parent_name]["bit_data"].append(bit_data)
+        return result_map
+    
+    def extract_desc(self):
+        """Parse secure LID structure description and merge into MDDB structure"""
+        # sec_lid_type_map = {item.get("name"): item.get("type_name") for item in self.secure_lids} 
+        
+        # Define regular pattern
+        line_re = re.compile(r"LID_BIT[\sA-Z_]*VER_LID\s*\(NVRAM_EF_[A-Z\d_]+_LID\)")
+        lid_re = re.compile(r"NVRAM_EF_[A-Z\d_]+_LID")
+        for editor_file in self.files:
+            if not os.path.exists(editor_file):
+                print("editor file: {} not found in disk Bypass!".format(editor_file))
+                continue
+            with open(editor_file) as f:
+                content = f.readlines()
+            content = [item.strip() for item in content]
+            # Match all LID description in editor 
+            matched = filter(line_re.match, content)
+            for index in range(0, len(matched)):
+                match_item = matched[index]
+                lid_name = lid_re.search(match_item).group()
+                if self.lids and lid_name not in self.lids:
+                    continue
+                start_index = content.index(match_item)
+                # Lid code section
+                if index == len(matched)-1:
+                    section = content[start_index:]
+                else:
+                    end_line = content.index(matched[index+1])
+                    if end_line > start_index:
+                        section = content[start_index: end_line]
+                    else:
+                        # ASSERT never hit
+                        # pdb.set_trace()
+                        next_matched = filter(line_re.match, content[start_index+1:])
+                        end_line = content[start_index: ].index(next_matched[1])
+                        section = content[start_index: start_index+end_line]
+                # Find lid structure description
+                struct_name_desc_map = self.parse_editor_description(section)
+                if struct_name_desc_map:
+                    if DebugMode :
+                        self.l_stu_map[lid_name] = struct_name_desc_map
+                        tmp_secure_desc = "tmp_secure_desc.json"
+                        with open(tmp_secure_desc, "a+") as f:
+                            f.write("LID: {}\n".format(lid_name))
+                            f.write(json.dumps(struct_name_desc_map)+"\n")
+                            f.write("--------------------------------------------\n")
+    
+def nvram_merge_db():
+    bpath = "../../../../build/MT3967_SP/LWCTG"
+    NvramGenDB(bpath)
+
+def parse_security_lid():
+    # parse editor structure detail description
+    bpath = "../../../../build/MT3967_SP/LWCTG"
+    lids = ["NVRAM_EF_SIM_LOCK_LID", "NVRAM_EF_SML_S_LID"]
+    
+    folders = ["../../../../interface/service/nvram"]
+    parser = EditorParser(folders, lids)
+    
+    parser.extract_desc()
+    if parser.l_stu_map:
+        pdb.set_trace()
+        print("find lid desc: {}".format(len(parser.l_stu_map))  )
+    print("--------parse editor end --------------")
+    
+def main():
+    parse_security_lid()
+    
+if __name__ == "__main__":
+    main()
+
+    
+    
\ No newline at end of file
diff --git a/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/mergeMDDB.py b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/mergeMDDB.py
new file mode 100644
index 0000000..b337bbd
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/mergeMDDB.py
@@ -0,0 +1,239 @@
+
+import os
+import re
+import sys
+import pdb
+import glob, gzip
+import datetime
+import logging
+import platform
+try:
+    import xml.etree.cElementTree as ET
+except ImportError:
+    import xml.etree.ElementTree as ET
+
+from util import WriteEelementToDoc
+from editorParser import EditorHeaderParser
+
+
+def NvramGenDB(build_path):
+    """
+    Target:Merge cat.xml(default value, attribute...) into MDDB for gen excel
+    return: new db path
+  """
+    old_date = datetime.datetime.now()
+   
+    autogen_root = ET.Element("ROOT")
+    element_lid_info = ET.SubElement(autogen_root, "LID_INFO")
+    autogen_tree = ET.ElementTree(autogen_root)
+    
+    # Parsing editor.h for LID description & information
+    split_path_array = build_path.split(os.sep)  
+    project_name = split_path_array[-2]
+    flavor_name = split_path_array[-1]
+    print "project_name: " + project_name + " flavor_name: " + flavor_name
+    project_flavor = project_name + "_" + flavor_name
+    
+    mcu_path = os.sep.join(split_path_array[:-3])
+    mcu_path = os.path.realpath(mcu_path)
+    if(platform.system() == "Windows"):
+      gcc_path = os.path.realpath(mcu_path + '/tools/MinGW/bin/gcc.exe')
+    else:
+      gcc_path = 'gcc'
+    PrepareGCCEnvironment(build_path, mcu_path)
+    
+    filelist = [mcu_path + '/interface/service/nvram']
+    filelist.append(mcu_path + '/custom/driver/common')
+    filelist.append(mcu_path + '/custom/middleware/common')
+    filelist.append(mcu_path + '/custom/modem/common/ps')
+    filelist.append(mcu_path + '/interface/driver/drv_def')  
+    CollectEditorInfo(filelist, gcc_path, build_path, element_lid_info)
+    # WriteEditorInfo(ET.tostring(autogen_root), "a_liddb_doc.xml")
+    
+    os.remove(r'gcc_option.h')
+    os.remove(r'nvram_editor_data_item.c')
+    print "Parsing editor.h success."
+    # Unzip MD database *.GZ
+    try:
+        dhl_path = os.path.realpath(build_path + '/dhl/database')
+        dhl_path = glob.glob(dhl_path + "/*.GZ")
+        g=gzip.GzipFile(mode='rb', fileobj=open(dhl_path[0],'rb'))
+        open(r'MDDB.XML','wb').write(g.read())
+        g.close()
+        print "Unzip MD database success."
+    except Exception as e:
+        print "MD database unzip fail."
+        print("Error: {}".format(e) )
+        # pause()
+        sys.exit()
+
+    # Merge custom_nvram_lid_cat.xml to MDDB (default value, attribute, struct_size...)
+    try:
+      MDDB_tree = ET.ElementTree(file="MDDB.XML")
+      MDDB_root = MDDB_tree.getroot()
+      # -----------------------
+      codegen_lids = {item.get("name"): item for item in MDDB_tree.iter('NVRAM_LID')}
+      codegen_struct_size_map = {item.get("name"): item.get("size") \
+            for item in MDDB_tree.iter(tag="Struct")}
+      codegen_define_type_size_map = {item.get("name"): item.get("size") for item in MDDB_tree.iter("Typedef")}
+      
+      cat_path = os.path.realpath(build_path + '/nvram_auto_gen/custom_nvram_lid_cat.xml')
+      cat_tree = ET.ElementTree(file=cat_path)
+      cat_root = cat_tree.getroot()
+      # AUTO GEN LID
+      autogen_lids = {}
+      nvitem = cat_root.iter('NVRAMITEM')
+      for cat_lid in nvitem:
+        lid_name = cat_lid.get("id")
+        autogen_lids[lid_name] = cat_lid
+        
+        autogen_lid = element_lid_info.find(lid_name)
+        autogen_lid = CatAttributeMerage(autogen_lid, cat_lid, element_lid_info)
+        # Check LID in AUTO gen but not in codegen
+        if lid_name not in codegen_lids:
+            logging.debug("[Waring]: {} in Autogen not in Codgen".format(lid_name))
+            continue
+        # Check lid's record size and structure size whether match
+        cat_lid_type = codegen_lids[lid_name].get("type_name")
+        size = ""
+        if cat_lid_type in codegen_struct_size_map:
+            size = codegen_struct_size_map[cat_lid_type]
+        elif cat_lid_type in codegen_define_type_size_map:
+            size = codegen_define_type_size_map[cat_lid_type]
+        if size != autogen_lid.get("record_size"):
+            if size == "":
+                logging.debug("can't find out struct_size for lid:{}".format(lid_name))
+            else:
+                logging.debug("[Waring]: " + lid_name + " record size(" + autogen_lid.get('record_size') + ") in Autogen mismatch with codegen(" + size + ")")        
+        autogen_lid.set("struct_size", size)
+      # WriteEelementToDoc(autogen_root, "a_liddb_doc.xml")
+      
+      # Check lid in codegen not in AUTO GEN
+      for lid in codegen_lids:
+        if lid not in autogen_lids:
+            logging.debug("[Warning]: {} in Codgen not in Autogen".format(lid))
+      # Merge
+      autogen_root.append(MDDB_root)
+      
+      # Write new MDDB to disk
+      lidDB_version = ""
+      sw_version_element = MDDB_root.find("*/Information/[@name='MTK_TARGET_SW_VERSION_FOR_CATCHER']")
+      lidDB_version = sw_version_element.get("value", "")
+      
+      project_flavor = lidDB_version + "_"+ project_flavor
+      lidDB_filename = project_flavor + "_LidDBInfo.xml"
+      lidDB_path = os.path.realpath(build_path + '/nvram_auto_gen/' + lidDB_filename)
+      print("New MDDB path: {}".format(lidDB_path) )
+      WriteEelementToDoc(autogen_root, lidDB_path)
+      # merge db success
+      print "Merge custom_nvram_lid_cat.xml to MDDB success."
+    except Exception as e:
+      print build_path + "/nvram_auto_gen/custom_nvram_lid_cat.xml load fail."
+      raise
+      # pause()
+      sys.exit()
+    os.remove("MDDB.XML")
+    print "Generate LID DB success,you can find the file:"
+    print lidDB_path + "\n"
+    print "Start: " + str(old_date)
+    print "End:   " + str(datetime.datetime.now())
+    return lidDB_path
+
+
+def CollectEditorInfo(filelist, gcc_path, build_path, parent_element):
+  # global gcc_path
+  global gcc_include
+  include = ""
+  
+  fileW = open('nvram_editor_data_item.c', 'w')
+  for path in filelist:
+    for parent,dirname,filenames in os.walk(path):
+      for fname in filenames:
+        if(fname.find('_editor.h')>0 or fname=='nvram_editor_data_item.h'):
+          # find editor file
+          fileW.write('#include "'+fname+'"\n')
+      break
+    include += (' -I "'+path+'"')
+  fileW.close()
+  output = ""
+  if(platform.system() == "Windows"):
+    gcc_include = include
+  ps = os.popen(gcc_path+' -DGEN_FOR_PC -E -C -imacros gcc_option.h -fno-strict-aliasing -fshort-enums -c -w nvram_editor_data_item.c '+gcc_include)
+  
+  #remove the white line
+  lines = ps.readlines()
+  ps.close()
+  lines = [line for line in lines if line.strip()]
+  # For debug
+  # tmp_path = build_path + '/nvram_auto_gen/nvram_editor_temp.txt'
+  # with open(tmp_path,'w') as f:
+  #      f.write("".join(lines))
+  parser = EditorHeaderParser(lines)
+  while  parser.FindLidHeader():
+      header = parser.GetLidHeader()
+      lid = ET.SubElement(parent_element, header[0])
+      lid.set("LID_NAME", header[0])
+      lid.set("DESCRIPTION", header[1])
+      lid.set("INFORMATION", header[2])
+  
+
+def PrepareGCCEnvironment(build_path, mcu_path):
+  # Prepare compile option
+  global gcc_include
+  option_items = []
+  
+  StartParsing = 0
+  option_path = build_path + "/bin/log/info.log"
+  file = open(option_path)
+    
+  for line in file:
+    line = line.strip()
+    if "[ COMMON OPTION ]" in line:
+        StartParsing = 1
+        continue
+    
+    if(line.find("[") > -1):
+      break
+    if((StartParsing == 1) and len(line)):
+      line = line.replace("=", " ")
+      option_items.append('#define '+line)
+  with open('gcc_option.h', "w") as f:
+    f.write("\n".join(option_items))
+  # include path
+  inc_file = build_path + "/tmp/~inc.tmp.tmp"
+  inc_lines = []
+  with open(inc_file, "r") as f:
+    inc_lines = f.readlines()
+  gcc_include = '-I "' + '" -I "'.join([os.path.realpath(mcu_path+"/"+line.strip()) for line in inc_lines])+'"'
+  file.close() 
+
+  
+def CatAttributeMerage(lid, cat_lid, parent_element):
+    """merge lid attribute(id, record_size, total_record, attribute..) from cat.xml to MDDB"""
+    def_val = cat_lid.find("DEFAULT_VALUE")
+    #print "def_val" + str(defa_val)
+    def_fill = def_val.get("defaultByteFill")
+    if def_val.text:
+      def_fill = re.sub(r'[,\s\[\]]', r'', def_val.text).replace("0x", "")
+    lid_name = cat_lid.get("id")
+    if lid is None:
+        lid = ET.SubElement(parent_element, lid_name)
+        lid.set('LID_NAME', lid_name)
+        logging.debug("append a new lid:" + lid_name + " record_size:" + str(cat_lid.get("record_size")) + " total_record:" + str(cat_lid.get("total_record")))
+    else:
+        logging.debug("update lid info:" + lid_name + " record_size:" + str(cat_lid.get("record_size")) + " total_record:" + str(cat_lid.get("total_record")))
+    lid.set('record_size', cat_lid.get("record_size"))
+    lid.set('total_record', cat_lid.get("total_record"))
+    lid.set('lid_enum', cat_lid.get("lid_enum"))
+    lid.set('category', cat_lid.get("category", ""))
+    lid.set('attribute', cat_lid.get("attribute"))
+    lid.set('defaultByteFill', def_fill)
+    if "()" in def_fill:
+        logging.debug( "{} default value generated from callback function".format(lid_name))
+    return lid
+
+if __name__ == "__main__":
+    b_path = os.path.realpath("../../../../build/MT3967_SP/LWCTG")
+    NvramGenDB(b_path)
+
+    
\ No newline at end of file
diff --git a/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/util.py b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/util.py
new file mode 100644
index 0000000..6f4f2c1
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_gen_excel/utils/util.py
@@ -0,0 +1,25 @@
+
+import time
+import logging
+from functools import wraps
+
+try:
+    import xml.etree.cElementTree as ET
+except ImportError:
+    import xml.etree.ElementTree as ET
+
+def time_counter(func):
+    @wraps(func)
+    def decorate(*args, **kwargs):
+        start = time.time()
+        result = func(*args, **kwargs)
+        print("{} spend: {}".format(func.__name__, time.time()-start ))
+        return result
+    return decorate
+
+def WriteEelementToDoc(fl_doc,filename):
+    print '[WriteEditorInfo]: filename:{}'.format(filename)
+    content = ET.tostring(fl_doc, "utf-8")
+    with open(filename, "w") as f:
+        f.write(content.replace("><", ">\n<"))
+    
\ No newline at end of file
diff --git a/mcu/tools/NVRAMStatistic/nvram_lid_check.pl b/mcu/tools/NVRAMStatistic/nvram_lid_check.pl
new file mode 100644
index 0000000..e9aab63
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_lid_check.pl
@@ -0,0 +1,1425 @@
+use strict;
+use warnings;
+use Cwd qw(abs_path);
+use File::Find;
+use File::Copy;
+use File::Spec::Functions;
+use XML::Simple;
+use Digest::MD5;
+# Main Start ----------------------------------------------------------------------------------
+	#my $version = "v9502_20180111 + (Bypass MODIS) + (Bypass VerConflict)"; ==> v9503_20180402
+	my $version = "v9503_20180402 + (Union Check) + (Fix bitfields) + (Load SecXML)";
+	my ($ERR_OK, $ERR_NOTIFY, $ERR_ERROR, $ERR_WARNING, $ERR_DEBUG, $ERR_OPEN_FILE) = 0..5;
+	my ($MARK_NEW, $MARK_CHANGED, $MARK_BITFIELDS) = 0..2;
+	my ($ATTR_MULTIPLE, $ATTR_OTA_RESET) = (0x0004,0x0040);
+	my ($CATEGORY_INTERNAL, $CATEGORY_OTP, $CATEGORY_CUSTOM_SENSITIVE, $CATEGORY_CALIBRAT, $CATEGORY_IMPORTANT, $CATEGORY_IMPORTANT_L4, $CATEGORY_IMPORTANT_L1) = (0x0001,0x0020,0x0080,0x1000,0x2000,0x4000,0x8000);
+	my $CATEGORY_IMPORTANT_ALL = ($CATEGORY_CALIBRAT|$CATEGORY_IMPORTANT|$CATEGORY_IMPORTANT_L4);
+	my $debug_mode = 0; #$ERR_DEBUG;
+	my $PrelogPath = "";
+	my $CurrlogPath = "";
+	my $OutputPath = "";
+	my $Parameter = "";
+	my %PreDatabase;
+	my %CurrDatabase;
+	my $PreDatabaseIdx;
+	my $CurrDatabaseIdx;
+	my $Result = $ERR_OK;
+	my $SkipWarning = 0;
+	my $SmartReset = 0;
+	my $cnt;
+
+	my $platform = 0;
+	my $streamstr = "";
+	my $starttime = time();
+	my $usetime = 0;
+	my @ota_reset_lid_white_list;
+	my @nvram_editor_path;
+	
+	my $xml;
+	my $current_xml;
+	my $previous_xml;
+	my %current_LID_structure_sign;
+	my %previous_LID_structure_sign;
+	my $current_sign_status;
+	my $previous_sign_status;
+	my %compare_LID_structure_sign;
+	my %changed_LID_structure;
+	my %changed_LID_name;
+	my @lid_struct_bypass_white_list = ("NVRAM_EF_SYS_LID","NVRAM_EF_NVRAM_LOCK_LID","NVRAM_EF_READ_RESERVED_LID","NVRAM_EF_MML1_RF_SELF_CAL_TX_SB_LID","NVRAM_EF_MML1_RF_SELF_CAL_DET_TX_LID","NVRAM_EF_CORE_FACTORY_RESET_AND_OTA_LID", "NVRAM_EF_NVRAM_SEC_CHECK_LID", "NVRAM_EF_CORE_CHKSUM_INFO_LID","NVRAM_EF_CORE_INTERNAL_CLONE_LID","NVRAM_EF_CORE_BNRG_CHKSUM_ALGRTHM_LID","NVRAM_EF_MMRFC_RF_SELF_CAL_TX_SB_OTA_LID","NVRAM_EF_MMRFC_RF_SELF_CAL_DET_TX_OTA_LID");
+	my @cgen_auto_rename_list = ("struct_gename_","struct_apname_","struct_ap[0-9]*nam_","struct_ap[0-9]*na_","struct_cmname_","struct_cm[0-9]*nam_","struct_cm[0-9]*na_","union_gename_","union_apname_","union_ap[0-9]*nam_","union_ap[0-9]*na_","union_cmname_","union_cm[0-9]*nam_","union_cm[0-9]*na_","enum_gename_","enum_apname_","enum_ap[0-9]*nam_","enum_ap[0-9]*na_","enum_cmname_","enum_cm[0-9]*nam_","enum_cm[0-9]*na_");
+	
+	# define Security XML  PATH   
+	my $secure_lid_list_path = "./tools/NVRAMStatistic/NVRAM_LID_structure_map.xml";
+	my $secure_xml;
+	$PrelogPath = $ARGV[0];
+	$CurrlogPath = $ARGV[1];
+	if(scalar(@ARGV) > 2) {
+		$OutputPath = $ARGV[2];
+	}
+	else {
+		$OutputPath = "./nvram_lid_check.log";
+	}
+	if(scalar(@ARGV) > 3) {
+		$Parameter = $ARGV[3];
+	}
+	if ($Parameter =~ /\/s/)
+	{
+		$SkipWarning = 1;
+	}
+	if ($PrelogPath eq "")
+	{
+	  $PrelogPath = "./tools/NVRAMStatistic/debug";
+	}
+	if ($CurrlogPath eq "")
+	{
+	  $CurrlogPath = "./build/";
+	}
+	if(grep /NVRAM_OTA_SMART_RESET=TRUE/,@ARGV)
+	{
+		$SmartReset = 1;
+	}
+
+	if ($^O eq "MSWin32")
+	{
+		print "nvram_lid_check.pl not support MSWin32!!";
+		exit $ERR_OK;
+	}
+	@nvram_editor_path = ("./interface/service/nvram","./custom/protocol/common/ps","./custom/driver/common","./custom/middleware/common");
+	&kal_print(0, "Script ver: $version\n");
+	&kal_print(0, "Platform is: $^O\n");
+	#$streamstr .= sprintf("Param: \n", $parrameter);
+	&kal_print(0, "Parameter: $Parameter\n");
+	&kal_print(0, "SmartReset: $SmartReset\n");
+	&kal_print(0, "Previous Path: $PrelogPath   ");
+	%PreDatabase = &scan_context($PrelogPath);
+	$PreDatabaseIdx = (keys %PreDatabase);
+	&kal_print(0, "lid_count:$PreDatabaseIdx\n");
+
+	&kal_print(0, "Current Path: $CurrlogPath   ");
+	%CurrDatabase = &scan_context($CurrlogPath);
+	$CurrDatabaseIdx = (keys %CurrDatabase);
+	&kal_print(0, "lid_count:$CurrDatabaseIdx\n");	
+	
+	# Load Secure LID list
+	if (-e $secure_lid_list_path){
+		$secure_xml = XMLin($secure_lid_list_path);
+		# Adjust one field format in XML
+		if (defined $secure_xml->{NVRAM_LIDs}->{NVRAM_LID}->{name}){
+			my $new_item = $secure_xml->{NVRAM_LIDs}->{NVRAM_LID};
+			delete $secure_xml->{NVRAM_LIDs}->{NVRAM_LID};
+			$secure_xml->{NVRAM_LIDs}->{NVRAM_LID}->{$new_item->{name}} = $new_item;
+		}
+	}
+	
+	# Load MDDB XML
+	($previous_sign_status, %previous_LID_structure_sign) = &get_LID_structure_sign($PrelogPath);
+	$previous_xml = $xml;
+	($current_sign_status, %current_LID_structure_sign) = &get_LID_structure_sign($CurrlogPath);
+	$current_xml = $xml;
+	
+	# Bypass, if open ~nvram_lid_xxx.log unexpected
+	if(($PreDatabaseIdx eq 0) or ($CurrDatabaseIdx eq 0))
+	{
+		&kal_print(0, "Log file read unexpected. Skip check script.\n");
+		exit $ERR_OK;
+	}
+	# Check LID structure
+	if(((keys %previous_LID_structure_sign) eq 0) or ((keys %current_LID_structure_sign) eq 0)) {
+		&kal_print(0, "XML file read unexpected. Skip check LID structure.\n");
+	}
+	else {
+		# Get changed struct/union
+		%compare_LID_structure_sign = &compare_LID_structure_sign();
+		if((keys %compare_LID_structure_sign) > 0) {
+			&kal_print($ERR_DEBUG, "Find LID structure changed.\n");
+			foreach my $nm (keys %compare_LID_structure_sign) {
+				# Get all of the structure which reference by %compare_LID_structure_sign
+				my $mark = $MARK_CHANGED;
+				if($compare_LID_structure_sign{$nm} eq 'bitfields') {
+					$mark = $MARK_BITFIELDS;
+				}
+				elsif (not $compare_LID_structure_sign{$nm} =~ /:/){
+					# New struct only in new_lid_xml
+					$mark = $MARK_NEW;
+				}
+				&search_structure_reference($nm, $mark);
+			}
+			# Get LID by changed struct/union name --> %changed_LID_name
+			&search_LID_by_structure_sign();
+		}
+		# Get inconsistent LID type_name --> %changed_LID_name
+		&compare_LID_defined_structure();
+		# Check LID VERNO+1 <-- %changed_LID_name
+		$cnt = &check_lid_structure_verno(\%PreDatabase, \%CurrDatabase);
+		if($cnt ne 0)
+		{
+			$Result = $ERR_ERROR;
+		}	
+	}
+	# Check OTA rule
+	$cnt = &check_lid_filename_length(\%CurrDatabase);
+	if($cnt ne 0)
+	{
+		$Result = $ERR_ERROR;
+	}
+	@ota_reset_lid_white_list = &get_ota_reset_white_list();
+	#$cnt = check_lid_filename_length(\%PreDatabase);
+	#$cnt = check_lid_filename_duplicate(\%PreDatabase);
+	$cnt = &check_lid_filename_length(\%CurrDatabase);
+	if($cnt ne 0)
+	{
+		$Result = $ERR_ERROR;
+	}
+	$cnt = &check_lid_filename_duplicate(\%CurrDatabase);
+	if($cnt ne 0)
+	{
+		$Result = $ERR_ERROR;
+	}	
+	$cnt = &check_OTA_delete(\%PreDatabase, \%CurrDatabase);
+	if($cnt ne 0)
+	{
+		$Result = $ERR_ERROR;
+	}	
+	$cnt = &check_OTA_assert(\%PreDatabase, \%CurrDatabase);
+	if($cnt ne 0)
+	{
+		$Result = $ERR_ERROR;
+	}
+	$cnt = &check_OTA_filename_conflict(\%PreDatabase, \%CurrDatabase);
+	if($cnt ne 0)
+	{
+		$Result = $ERR_ERROR;
+	}
+		
+	#&kal_print(0, "=======================\n");
+	$cnt = &check_OTA_add(\%PreDatabase, \%CurrDatabase);
+	if(($cnt ne 0) and ($Result eq $ERR_OK) and ($SkipWarning eq 0))
+	{
+		$Result = $ERR_WARNING;
+	}	
+	$cnt = &check_OTA_filename(\%PreDatabase, \%CurrDatabase);
+	if(($cnt ne 0) and ($Result eq $ERR_OK) and ($SkipWarning eq 0))
+	{
+		$Result = $ERR_WARNING;
+	}	
+	$cnt = &check_OTA_category(\%PreDatabase, \%CurrDatabase);
+	if(($cnt ne 0) and ($Result eq $ERR_OK) and ($SkipWarning eq 0))
+	{
+		$Result = $ERR_WARNING;
+	}		
+	$cnt = &check_OTA_size_warning(\%PreDatabase, \%CurrDatabase);
+	if(($cnt ne 0) and ($Result eq $ERR_OK) and ($SkipWarning eq 0))
+	{
+		$Result = $ERR_WARNING;
+	}	
+	$cnt = &check_OTA_attibute(\%PreDatabase, \%CurrDatabase);
+	if(($cnt ne 0) and ($Result eq $ERR_OK) and ($SkipWarning eq 0))
+	{
+		$Result = $ERR_WARNING;
+	}		
+	
+	$usetime = time() - $starttime;	
+	&kal_print(0, "nvram_lid_check spend time:  $usetime s\n");
+	&kal_print(0, "outputfile: $OutputPath\n");
+	&kal_print(0, "Return: $Result\n");
+	#&WriteFile("$OutputPath",$streamstr);
+	exit $Result;
+# Main End ----------------------------------------------------------------------------------
+
+sub get_lid_size
+{	 
+	(my ($lidname),my ($lidid),my($strFilePath)) = @_;
+	my ($filename) = "$strFilePath/~nvram_lid_size.log";
+
+	open FILEHANDLE2, "<$filename" or die "couldn't open $filename\n" && return $ERR_OPEN_FILE;
+	while (<FILEHANDLE2>) 
+	{		
+		my $line = $_;      
+		chomp($line);
+
+		if($line =~ /\s$lidname/g)
+		{
+			$line = trim($line);
+			my @lidinfo = split(/ +/, $line);
+			if($lidid eq $lidinfo[0])
+			{
+				return $lidinfo[1];
+				last;
+			}
+		}
+    } 	
+	close FILEHANDLE2;
+	return 0;
+}	
+	
+sub scan_context
+{	
+	my %database;
+	my ($strFilePath) = @_;
+	my $filename = "$strFilePath/~nvram_lid_information.log";
+	my $count = 0;
+	
+	open FILEHANDLE, "<$filename" or die "couldn't open $filename\n" && return;
+
+	my $nvram_padding_test = get_lid_size('NVRAM_PADDING_TEST', '00000', $strFilePath);
+	$database{'NVRAM_PADDING_TEST'} = {(LID_Str=>"NVRAM_PADDING_TEST", Value=>"$nvram_padding_test")};
+	
+	while (<FILEHANDLE>) 
+	{		
+		my $line = $_;      
+		chomp($line);
+
+		if($line =~ /\s*NVRAM_.*_LID/g)
+		{
+			$line = trim($line);
+			my @lidinfo = split(/ +/, $line);
+			$lidinfo[4] = get_lid_size($lidinfo[1], $lidinfo[0], $strFilePath);
+			#print "@lidinfo\r\n";
+			#&kal_print($ERR_NOTIFY, "@lidinfo\r\n");
+			#  @lidinfo[0]  LID,
+			#  @lidinfo[1]  LID_Str,
+			#  @lidinfo[2]  Filename,
+			#  @lidinfo[3]  Verno,
+			#  @lidinfo[4]  Length,
+			#  @lidinfo[5]  Category,
+			#  @lidinfo[6]  Attribute
+			my %lidinfo = (LID=>"$lidinfo[0]", LID_Str=>"$lidinfo[1]", Filename=>"$lidinfo[2]", Verno=>"$lidinfo[3]", Length=>"$lidinfo[4]", Category=>"$lidinfo[5]", Attribute=>"$lidinfo[6]");
+			#push(@database, {%lidinfo});
+			$database{$lidinfo[1]} = {%lidinfo};
+			$count++;
+		} 
+	}
+	close FILEHANDLE;
+
+	return %database; 
+}	
+	
+sub check_lid_filename_length()
+{
+	my $database = shift;
+	my $ret = 0;
+
+	foreach my $lid_name (keys %$database)
+	{
+		my %lid = %{$database->{$lid_name}};
+		if(not defined $lid{LID})
+		{
+			next;
+		}
+		# check filename length
+		if(length($lid{Filename}) ne 4)
+		{
+			&kal_print($ERR_ERROR, "LID:$lid{LID} $lid{LID_Str} filename \"$lid{Filename}\" unexpected.\n");
+			$ret ++;
+		}
+		# check file verno length
+		if(length($lid{Verno}) ne 3)
+		{
+			&kal_print($ERR_ERROR, "LID:$lid{LID} $lid{LID_Str} file verno \"$lid{Verno}\" unexpected.\n");
+			$ret ++;
+		}
+	}
+	return $ret;
+}
+
+sub check_lid_filename_duplicate()
+{
+	my $database = shift;
+	my @database_array = (keys %$database);
+	my $length = @database_array;
+	my ($i, $j);
+	my $ret = 0;
+
+	for($i = 0; $i < ($length-1); $i++)
+	{
+		for($j = ($i+1); $j < $length; $j++)
+		{
+			# check filename duplicate
+			my $Category_MASK = ($CATEGORY_IMPORTANT_ALL|$CATEGORY_OTP|$CATEGORY_INTERNAL);
+			if(not defined $database->{$database_array[$i]}->{LID}) { next;}
+			if(not defined $database->{$database_array[$j]}->{LID}) { next;}
+			my %lid_i = %{$database->{$database_array[$i]}};
+			my %lid_j = %{$database->{$database_array[$j]}};
+			if(($lid_i{Filename} eq $lid_j{Filename}) and
+			   ((hex($lid_i{Category}) & $Category_MASK) eq (hex($lid_j{Category}) & $Category_MASK)) )
+			{
+				&kal_print($ERR_ERROR, "LID:$lid_i{LID} $lid_i{LID_Str} filename \"$lid_i{Filename}\" duplicate with LID:$lid_j{LID} $lid_j{LID_Str}.\n");
+				$ret ++;
+			}
+		}
+	}
+	return $ret;
+}
+
+sub check_OTA_add()
+{
+	my $database1 = shift;
+	my $database2 = shift;
+	my @database1 = values %$database1;
+	my @database2 = values %$database2;
+	my $db1_idx = @database1;
+	my $db2_idx = @database2;
+	my $ret = 0;
+	my ($i,$j,$flag);
+	my $Category_MASK = ($CATEGORY_CALIBRAT|$CATEGORY_IMPORTANT|$CATEGORY_IMPORTANT_L4);
+	
+	for($j = 0; $j < $db2_idx; $j++)
+	{
+		if(not defined $database2[$j]{LID}) { next;}
+		$flag = 0;
+		for($i = 0; $i < $db1_idx; $i++)
+		{
+			if(not defined $database1[$i]{LID}) { next;}
+			if($database2[$j]{LID_Str} eq $database1[$i]{LID_Str})
+			{
+				$flag = 1;
+				last;
+			}
+		}
+		if($flag eq 0)
+		{
+			if((hex($database2[$j]{Attribute}) & $ATTR_OTA_RESET) ne 0)
+			{
+				&kal_print($ERR_NOTIFY, "New LID:$database2[$j]{LID} $database2[$j]{LID_Str} with OTA_RESET will be reset to default value.\r\n");
+			}
+			elsif((hex($database2[$j]{Category}) & $CATEGORY_CALIBRAT) ne 0)
+			{
+				&kal_print($ERR_WARNING, "New Calibrate LID:$database2[$j]{LID} $database2[$j]{LID_Str}.\r\n");
+			}
+			elsif((hex($database2[$j]{Category}) & $CATEGORY_IMPORTANT) ne 0)
+			{
+				&kal_print($ERR_WARNING, "New Important LID:$database2[$j]{LID} $database2[$j]{LID_Str}.\r\n");
+			}
+			elsif((hex($database2[$j]{Category}) & $CATEGORY_IMPORTANT_L4) ne 0)
+			{
+				&kal_print($ERR_WARNING, "New Important_L4 LID:$database2[$j]{LID} $database2[$j]{LID_Str}.\r\n");
+			}
+			else
+			{
+				&kal_print($ERR_NOTIFY, "New LID:$database2[$j]{LID} $database2[$j]{LID_Str} will be reset to default value.\r\n");
+			}			
+			#$ret ++;
+		}
+	}
+	return $ret;
+}
+
+sub check_OTA_filename()
+{
+	my $param1 = shift;
+	my $param2 = shift;
+	my %database1 = %{$param1};
+	my %database2 = %{$param2};
+	my @database1 = values %database1;
+	my @database2 = values %database2;
+	my $db1_idx = @database1;
+	my $db2_idx = @database2;
+	my $ret = 0;
+	my ($i,$j,$flag);
+	
+	for($j = 0; $j < $db2_idx; $j++)
+	{
+		if(not defined $database2[$j]{LID}) { next;}
+		$flag = 0;
+		for($i = 0; $i < $db1_idx; $i++)
+		{
+			if(not defined $database1[$i]{LID}) { next;}
+			if(($database2[$j]{LID_Str} eq $database1[$i]{LID_Str}) and
+			   (($database2[$j]{Filename} ne $database1[$i]{Filename}) or ($database2[$j]{Verno} ne $database1[$i]{Verno})) )
+			{
+				&kal_print($ERR_NOTIFY, "    $database1[$i]{LID} $database1[$i]{LID_Str} $database1[$i]{Filename} $database1[$i]{Verno}\r\n");
+				&kal_print($ERR_NOTIFY, "  ->$database2[$j]{LID} $database2[$j]{LID_Str} $database2[$j]{Filename} $database2[$j]{Verno}\r\n");
+				$flag = 1;
+				last;
+			}
+		}
+		if($flag eq 1)
+		{
+			my $lid_name = $database2[$j]{LID_Str};
+			if(not grep /^$lid_name$/,@ota_reset_lid_white_list) {
+				if((hex($database2[$j]{Attribute}) & $ATTR_OTA_RESET) ne 0)
+				{
+					&kal_print($ERR_NOTIFY, "Filename Change:$database2[$j]{LID} $database2[$j]{LID_Str} will be reset to default value with OTA_RESET.\r\n");					
+				}
+				elsif((hex($database2[$j]{Category}) & $CATEGORY_CALIBRAT) ne 0)
+				{
+					&kal_print($ERR_WARNING, "Calibrate LID Filename Change:$database2[$j]{LID} $database2[$j]{LID_Str}.\r\n");
+					$ret ++;
+				}
+				elsif((hex($database2[$j]{Category}) & $CATEGORY_IMPORTANT) ne 0)
+				{
+					&kal_print($ERR_WARNING, "Important LID Filename Change:$database2[$j]{LID} $database2[$j]{LID_Str}.\r\n");
+					$ret ++;
+				}
+				elsif((hex($database2[$j]{Category}) & $CATEGORY_IMPORTANT_L4) ne 0)
+				{
+					&kal_print($ERR_WARNING, "Important_L4 LID Filename Change:$database2[$j]{LID} $database2[$j]{LID_Str}.\r\n");
+					$ret ++;
+				}
+				else
+				{
+					&kal_print($ERR_NOTIFY, "Other LID Filename Change:$database2[$j]{LID} $database2[$j]{LID_Str} will be reset to default value.\r\n");
+				}
+			}
+			else {
+				&kal_print($ERR_NOTIFY, "Other LID Filename Change:$database2[$j]{LID} $database2[$j]{LID_Str} will be reset to default value because in white list.\r\n");
+			}
+		}
+	}
+	return $ret;
+}
+
+sub check_OTA_delete()
+{
+	my $param1 = shift;
+	my $param2 = shift;
+	my %database1 = %{$param1};
+	my %database2 = %{$param2};
+	my @database1 = values %database1;
+	my @database2 = values %database2;	
+	my $db1_idx = @database1;
+	my $db2_idx = @database2;
+	my $ret = 0;
+	my ($i,$j,$flag);
+	
+	for($i = 0; $i < $db1_idx; $i++)
+	{
+		if(not defined $database1[$i]{LID}) { next;}
+		$flag = 0;
+		for($j = 0; $j < $db2_idx; $j++)
+		{
+			if(not defined $database2[$j]{LID}) { next;}
+			if($database2[$j]{LID_Str} eq $database1[$i]{LID_Str})
+			{
+				$flag = 1;
+				last;
+			}
+		}
+		my $Category_MASK = ($CATEGORY_CALIBRAT|$CATEGORY_IMPORTANT|$CATEGORY_IMPORTANT_L4);
+		if(($flag eq 0) and ((hex($database1[$i]{Category}) & $Category_MASK) ne 0) )
+		{
+			&kal_print($ERR_WARNING, "Delete LID:$database1[$i]{LID} $database1[$i]{LID_Str}.\r\n");
+			#$ret ++;
+		}
+	}
+	return $ret;
+}
+
+sub trim()
+{
+	my ($str) = @_;
+	$str =~ s/^\s+//;
+	$str =~ s/\s+$//;
+	return $str;
+}
+	
+sub check_OTA_assert()
+{
+	my $param1 = shift;
+	my $param2 = shift;
+	my %database1 = %{$param1};
+	my %database2 = %{$param2};
+	my @database1 = values %database1;
+	my @database2 = values %database2;
+	my $db1_idx = @database1;
+	my $db2_idx = @database2;
+	my $ret = 0;
+	my ($i,$j,$flag);
+
+	# ================================================================================
+	# Replace nvram_auto_gen compiler, the LID size will be change.
+	my $ERR_LEVEL = $ERR_ERROR;
+	if($database2{NVRAM_PADDING_TEST}->{Value} ne $database1{NVRAM_PADDING_TEST}->{Value}) {
+		&kal_print(0, "($database2{NVRAM_PADDING_TEST}->{Value})=>($database1{NVRAM_PADDING_TEST}->{Value}) Special version bypass.\n");
+		$ERR_LEVEL = $ERR_WARNING;
+	}
+	# ================================================================================		
+	
+	for($i = 0; $i < $db1_idx; $i++)
+	{
+		if(not defined $database1[$i]{LID}) { next;}
+		$flag = 0;
+		for($j = 0; $j < $db2_idx; $j++)
+		{
+			if(not defined $database2[$j]{LID}) { next;}
+			# calibration & important LID length change.
+			if($database1[$i]{Filename} eq $database2[$j]{Filename} and
+				$database1[$i]{Verno} eq $database2[$j]{Verno})
+			{
+				#CALIBRAT
+				if((hex($database1[$i]{Category}) & $CATEGORY_CALIBRAT) and 
+					(hex($database2[$j]{Category}) & $CATEGORY_CALIBRAT) and
+					$database1[$i]{Length} ne $database2[$j]{Length})
+				{
+					if(grep /^$database1[$i]{LID_Str}$/,@lid_struct_bypass_white_list)
+					{
+						#bypass lid exist in lid_struct_bypass_white_list						
+						&kal_print($ERR_NOTIFY, "Bypass CALIBRAT LID:$database2[$j]{LID} $database2[$j]{LID_Str} length changed. $database1[$i]{Length} -> $database2[$j]{Length}\n");						
+					}
+					else
+					{
+						&kal_print($ERR_ERROR, "CALIBRAT LID:$database2[$j]{LID} $database2[$j]{LID_Str} length changed. $database1[$i]{Length} -> $database2[$j]{Length}\r\n");
+						$flag = 1;
+					}
+				}
+				#IMPORTANT
+				if((hex($database1[$i]{Category}) & $CATEGORY_IMPORTANT) and
+					(hex($database2[$j]{Category}) & $CATEGORY_IMPORTANT) and
+					$database1[$i]{Length} ne $database2[$j]{Length})
+				{
+					if(grep /^$database1[$i]{LID_Str}$/,@lid_struct_bypass_white_list) {
+						#bypass lid exist in lid_struct_bypass_white_list						
+						&kal_print($ERR_NOTIFY, "Bypass IMPORTANT LID:$database2[$j]{LID} $database2[$j]{LID_Str} length changed. $database1[$i]{Length} -> $database2[$j]{Length}.\n");						
+					}
+					else
+					{
+						&kal_print($ERR_ERROR, "IMPORTANT LID:$database2[$j]{LID} $database2[$j]{LID_Str} length changed. $database1[$i]{Length} -> $database2[$j]{Length}\r\n");
+						$flag = 1;
+					}
+				}
+				#IMPORTANT_L4
+				if((hex($database1[$i]{Category}) & $CATEGORY_IMPORTANT_L4) and
+					(hex($database2[$j]{Category}) & $CATEGORY_IMPORTANT_L4) and
+					$database1[$i]{Length} ne $database2[$j]{Length})
+				{
+					if(grep /^$database1[$i]{LID_Str}$/,@lid_struct_bypass_white_list) {
+						#bypass lid exist in lid_struct_bypass_white_list						
+						&kal_print($ERR_NOTIFY, "Bypass IMPORTANT_L4 LID:$database2[$j]{LID} $database2[$j]{LID_Str} length changed. $database1[$i]{Length} -> $database2[$j]{Length}.\n");						
+					}
+					else
+					{
+						&kal_print($ERR_WARNING, "IMPORTANT_L4 LID:$database2[$j]{LID} $database2[$j]{LID_Str} length changed. $database1[$i]{Length} -> $database2[$j]{Length}\r\n");
+						$flag = 1;
+					}
+				}
+				last;
+			}
+			elsif ($database1[$i]{Filename} eq $database2[$j]{Filename} and
+				$database1[$i]{Verno} ne $database2[$j]{Verno})
+			{
+				#CALIBRAT
+				if((hex($database1[$i]{Category}) & $CATEGORY_CALIBRAT) and 
+					(hex($database2[$j]{Category}) & $CATEGORY_CALIBRAT) and
+					$database1[$i]{Length} ne $database2[$j]{Length})
+				{
+					if(grep /^$database1[$i]{LID_Str}$/,@lid_struct_bypass_white_list)
+					{
+						#bypass lid exist in lid_struct_bypass_white_list						
+						&kal_print($ERR_NOTIFY, "Bypass CALIBRAT LID:$database2[$j]{LID} $database2[$j]{LID_Str} verno and length changed. $database1[$i]{Verno} -> $database2[$j]{Verno}, $database1[$i]{Length} -> $database2[$j]{Length}\n");						
+					}
+					else
+					{
+						&kal_print($ERR_WARNING, "CALIBRAT LID:$database2[$j]{LID} $database2[$j]{LID_Str} verno and length changed. $database1[$i]{Verno} -> $database2[$j]{Verno}, $database1[$i]{Length} -> $database2[$j]{Length}\r\n");						
+					}
+				}
+				#IMPORTANT
+				if((hex($database1[$i]{Category}) & $CATEGORY_IMPORTANT) and
+					(hex($database2[$j]{Category}) & $CATEGORY_IMPORTANT) and
+					$database1[$i]{Length} ne $database2[$j]{Length})
+				{
+					if(grep /^$database1[$i]{LID_Str}$/,@lid_struct_bypass_white_list) {
+						#bypass lid exist in lid_struct_bypass_white_list						
+						&kal_print($ERR_NOTIFY, "Bypass IMPORTANT LID:$database2[$j]{LID} $database2[$j]{LID_Str} verno and length changed. $database1[$i]{Verno} -> $database2[$j]{Verno}, $database1[$i]{Length} -> $database2[$j]{Length}.\n");						
+					}
+					else
+					{
+						&kal_print($ERR_WARNING, "IMPORTANT LID:$database2[$j]{LID} $database2[$j]{LID_Str} verno and length changed. $database1[$i]{Verno} -> $database2[$j]{Verno}, $database1[$i]{Length} -> $database2[$j]{Length}\r\n");
+					}
+				}
+				#IMPORTANT_L4
+				if((hex($database1[$i]{Category}) & $CATEGORY_IMPORTANT_L4) and
+					(hex($database2[$j]{Category}) & $CATEGORY_IMPORTANT_L4) and
+					$database1[$i]{Length} ne $database2[$j]{Length})
+				{
+					if(grep /^$database1[$i]{LID_Str}$/,@lid_struct_bypass_white_list) {
+						#bypass lid exist in lid_struct_bypass_white_list						
+						&kal_print($ERR_NOTIFY, "Bypass IMPORTANT_L4 LID:$database2[$j]{LID} $database2[$j]{LID_Str} verno and length changed. $database1[$i]{Verno} -> $database2[$j]{Verno}, $database1[$i]{Length} -> $database2[$j]{Length}.\n");						
+					}
+					else
+					{
+						&kal_print($ERR_WARNING, "IMPORTANT_L4 LID:$database2[$j]{LID} $database2[$j]{LID_Str} verno and length changed. $database1[$i]{Verno} -> $database2[$j]{Verno},$database1[$i]{Length} -> $database2[$j]{Length}\r\n");
+					}
+				}
+				last;
+			}
+		}
+		if(($flag eq 1) and ($ERR_LEVEL eq $ERR_ERROR))
+		{
+			$ret ++;
+		}
+	}
+	return $ret;
+}	
+
+sub check_OTA_size_warning()
+{
+	my $param1 = shift;
+	my $param2 = shift;
+	my %database1 = %{$param1};
+	my %database2 = %{$param2};
+	my @database1 = values %database1;
+	my @database2 = values %database2;
+	my $db1_idx = @database1;
+	my $db2_idx = @database2;
+	my $ret = 0;
+	my ($i,$j,$flag);
+	
+	for($i = 0; $i < $db1_idx; $i++)
+	{
+		if(not defined $database1[$i]{LID}) { next;}
+		$flag = 0;
+		for($j = 0; $j < $db2_idx; $j++)
+		{
+			if(not defined $database2[$j]{LID}) { next;}
+			# user LID length change.
+			if($database1[$i]{Filename} eq $database2[$j]{Filename} and
+				$database1[$i]{Verno} eq $database2[$j]{Verno})
+			{
+				#USER & IMPORTANT_L1
+				if(((hex($database1[$i]{Category}) & $CATEGORY_IMPORTANT_ALL) eq 0) and
+					((hex($database2[$j]{Category}) & $CATEGORY_IMPORTANT_ALL) eq 0) and
+					$database1[$i]{Length} ne $database2[$j]{Length} )
+				{
+					my $Category_name = "USER";
+					if(hex($database2[$j]{Category}) & $CATEGORY_IMPORTANT_L1) {
+						$Category_name = "IMPORTANT_L1";
+					}
+					my $lid_name=$database1[$i]{LID_Str};
+					if(grep /^$lid_name$/,@ota_reset_lid_white_list) {
+						&kal_print($ERR_NOTIFY, "$Category_name LID:$database2[$j]{LID} $database2[$j]{LID_Str} will be reset to default value. length changed $database1[$i]{Length} -> $database2[$j]{Length}\r\n");
+					}
+					else 
+					{
+						if((hex($database2[$j]{Attribute}) & $ATTR_OTA_RESET) ne 0)
+						{
+							&kal_print($ERR_NOTIFY, "$Category_name LID:$database2[$j]{LID} $database2[$j]{LID_Str} will be reset to default value. length changed $database1[$i]{Length} -> $database2[$j]{Length}\r\n");
+						}
+						else
+						{
+							&kal_print($ERR_WARNING, "$Category_name LID:$database2[$j]{LID} $database2[$j]{LID_Str} will be reset to default value. length changed $database1[$i]{Length} -> $database2[$j]{Length}\r\n");
+							$flag = 1;
+						}	
+					}
+				}
+				last;
+			}
+		}
+		if($flag eq 1)
+		{
+			$ret ++;
+		}
+	}
+	return $ret;
+}	
+
+sub check_OTA_filename_conflict()
+{
+	my $param1 = shift;
+	my $param2 = shift;
+	my %database1 = %{$param1};
+	my %database2 = %{$param2};
+	my @database1 = values %database1;
+	my @database2 = values %database2;
+	my $db1_idx = @database1;
+	my $db2_idx = @database2;
+	my $ret = 0;
+	my ($i,$j,$flag);
+	
+	for($i = 0; $i < $db1_idx; $i++)
+	{
+		if(not defined $database1[$i]{LID}) { next;}
+		$flag = 0;
+		for($j = 0; $j < $db2_idx; $j++)
+		{
+			if(not defined $database2[$j]{LID}) { next;}
+			# user LID length change.
+			if($database1[$i]{Filename} eq $database2[$j]{Filename} and
+				$database1[$i]{LID_Str} ne $database2[$j]{LID_Str} and
+				(hex($database1[$i]{Category}) & $CATEGORY_IMPORTANT_ALL) eq (hex($database1[$j]{Category}) & $CATEGORY_IMPORTANT_ALL) )
+			{
+
+				&kal_print($ERR_ERROR, "$database1[$i]{LID_Str}:$database1[$i]{Filename} $database2[$j]{LID_Str}:$database2[$j]{Filename}\r\n");
+				$flag = 1;
+				last;
+			}
+		}
+		if($flag eq 1)
+		{
+			$ret ++;
+		}
+	}
+	return $ret;
+}	
+	
+sub check_OTA_category()
+{
+	my $param1 = shift;
+	my $param2 = shift;
+	my %database1 = %{$param1};
+	my %database2 = %{$param2};
+	my @database1 = values %database1;
+	my @database2 = values %database2;
+	my $db1_idx = @database1;
+	my $db2_idx = @database2;
+	my $ret = 0;
+	my ($i,$j,$flag);
+	
+	for($i = 0; $i < $db1_idx; $i++)
+	{
+		if(not defined $database1[$i]{LID}) { next;}
+		$flag = 0;
+		for($j = 0; $j < $db2_idx; $j++)
+		{
+			if(not defined $database2[$j]{LID}) { next;}
+			# calibration & important LID length change.
+			if($database1[$i]{LID_Str} eq $database2[$j]{LID_Str})
+			{
+				#CALIBRAT category change
+				if(((hex($database1[$i]{Category}) & $CATEGORY_CALIBRAT) and ((hex($database2[$j]{Category}) & $CATEGORY_CALIBRAT) eq 0)) or
+				   ((hex($database2[$j]{Category}) & $CATEGORY_CALIBRAT) and ((hex($database1[$i]{Category}) & $CATEGORY_CALIBRAT) eq 0)) )
+				{
+					&kal_print($ERR_WARNING, "CALIBRAT LID:$database2[$j]{LID} $database2[$j]{LID_Str} category changed. $database1[$i]{Category} -> $database2[$j]{Category}\r\n");
+					$flag = 1;
+					last;
+				}
+				#IMPORTANT category change
+				if(((hex($database1[$i]{Category}) & $CATEGORY_IMPORTANT) and ((hex($database2[$j]{Category}) & $CATEGORY_IMPORTANT) eq 0)) or
+				   ((hex($database2[$j]{Category}) & $CATEGORY_IMPORTANT) and ((hex($database1[$i]{Category}) & $CATEGORY_IMPORTANT) eq 0)) )
+				{
+					&kal_print($ERR_WARNING, "IMPORTANT LID:$database2[$j]{LID} $database2[$j]{LID_Str} category changed. $database1[$i]{Category} -> $database2[$j]{Category}\r\n");
+					$flag = 1;
+					last;
+				}
+				#IMPORTANT_L4 category change
+				if(((hex($database1[$i]{Category}) & $CATEGORY_IMPORTANT_L4) and ((hex($database2[$j]{Category}) & $CATEGORY_IMPORTANT_L4) eq 0)) or
+				   ((hex($database2[$j]{Category}) & $CATEGORY_IMPORTANT_L4) and ((hex($database1[$i]{Category}) & $CATEGORY_IMPORTANT_L4) eq 0)) )
+				{
+					&kal_print($ERR_WARNING, "IMPORTANT_L4 LID:$database2[$j]{LID} $database2[$j]{LID_Str} category changed. $database1[$i]{Category} -> $database2[$j]{Category}\r\n");
+					$flag = 1;
+					last;
+				}
+				#IMPORTANT_L1 category change
+				if(((hex($database1[$i]{Category}) & $CATEGORY_IMPORTANT_L1) and ((hex($database2[$j]{Category}) & $CATEGORY_IMPORTANT_L1) eq 0)) or
+				   ((hex($database2[$j]{Category}) & $CATEGORY_IMPORTANT_L1) and ((hex($database1[$i]{Category}) & $CATEGORY_IMPORTANT_L1) eq 0)) )
+				{
+					&kal_print($ERR_WARNING, "IMPORTANT_L1 LID:$database2[$j]{LID} $database2[$j]{LID_Str} category changed. $database1[$i]{Category} -> $database2[$j]{Category}\r\n");
+					$flag = 1;
+					last;
+				}
+				
+			}
+		}
+		if($flag eq 1)
+		{
+			$ret ++;
+		}
+	}
+	return $ret;
+}	
+	
+sub check_OTA_attibute()
+{
+	my $param1 = shift;
+	my $param2 = shift;
+	my %database1 = %{$param1};
+	my %database2 = %{$param2};
+	my @database1 = values %database1;
+	my @database2 = values %database2;
+	my $db1_idx = @database1;
+	my $db2_idx = @database2;
+	my $ret = 0;
+	my ($i,$j,$flag);
+	
+	for($i = 0; $i < $db1_idx; $i++)
+	{
+		if(not defined $database1[$i]{LID}) { next;}
+		$flag = 0;
+		for($j = 0; $j < $db2_idx; $j++)
+		{
+			if(not defined $database2[$j]{LID}) { next;}
+			# multiple attribute change.
+			if($database1[$i]{LID_Str} eq $database2[$j]{LID_Str})
+			{
+				#MULTIPLE
+				if(((hex($database1[$i]{Attribute}) & $ATTR_MULTIPLE) and ((hex($database2[$j]{Attribute}) & $ATTR_MULTIPLE) eq 0)) or
+				   ((hex($database2[$j]{Attribute}) & $ATTR_MULTIPLE) and ((hex($database1[$i]{Attribute}) & $ATTR_MULTIPLE) eq 0)) )
+				{
+					&kal_print($ERR_WARNING, "MULTIPLE LID:$database2[$j]{LID} $database2[$j]{LID_Str} attribute changed. $database1[$i]{Attribute} -> $database2[$j]{Attribute}\r\n");
+					$flag = 1;
+					last;
+				}
+
+			}
+		}
+		if($flag eq 1)
+		{
+			$ret ++;
+		}
+	}
+	return $ret;
+}		
+
+sub kal_print()
+{
+	my ($level, $msg) = @_;
+	if($level eq $ERR_ERROR)
+	{
+		print "Error: ";
+		$streamstr .= "Error: ";
+	}
+	if($level eq $ERR_WARNING)
+	{
+		print "Warning: ";
+		$streamstr .= "Warning: ";
+	}	
+	if($level eq $ERR_NOTIFY)
+	{
+		print "Notify: ";
+		$streamstr .= "Notify: ";
+	}	
+	if($level eq $ERR_DEBUG) {
+		if($debug_mode eq $ERR_DEBUG) {
+			print "Debug: ";
+		}
+		else {
+			return;
+		}		
+	}
+
+	print "$msg";
+	$streamstr .= "$msg";
+}
+	
+sub WriteFile
+{
+    my ($strFilePath, $strContent) = @_;
+    open FILE_HANDLE, ">$strFilePath" or  print "couldn't open $strFilePath\n" && return $ERR_OPEN_FILE;
+    print FILE_HANDLE $strContent;
+    close FILE_HANDLE;
+}
+sub get_ota_reset_white_list
+{
+	my @lids;
+	my $nvram_editor_dir;
+	my $nvram_editor_files = 0;
+	my $nvram_editor_file_name;
+	my $is_one_lid_des_start = 0;
+	my $current_nvram_lid_item_name = "";
+	my $nvram_editor_folder = "";
+	my $is_nvram_lid_not_get;
+	my $gcc_include_dir = "";
+	my $gcc_path = "";
+	
+    if (-e "$CurrlogPath/nvram_editor_data_item.i") {}
+    else{
+        # Prepare compile option
+        if(-e "$CurrlogPath/../bin/log/info.log") {}
+        else {
+            &kal_print($ERR_WARNING, "Can not open $CurrlogPath/../bin/log/info.log\n");
+            lbWhitelistFail:
+            &kal_print($ERR_WARNING, "Reset Whitelist create unexpected.\n");
+            return @lids;
+        }
+        my $gcc_option_file = abs_path("$CurrlogPath/../bin/log/info.log");
+        open(FILE_HANDLE, "<$gcc_option_file");
+        open(FILE_OUTPUT, "> $CurrlogPath/gcc_option.h");
+        while (<FILE_HANDLE>) {
+            my $line = $_;
+            if(index($line, "[ COMMON OPTION ]") ne -1) {
+                while(<FILE_HANDLE>) {
+                    $line = $_;
+                    chomp($line);
+                    if(index($line, "[") ne -1) {
+                        last;
+                    }
+                    my @array = split(/=/, $line);
+                    if(scalar(@array) eq 1) {
+                        print FILE_OUTPUT "#define $array[0]\n";
+                    }
+                    elsif(scalar(@array) eq 2){
+                        print FILE_OUTPUT "#define $array[0] $array[1]\n";
+                    }
+                }
+            }
+        }
+        close(FILE_HANDLE);
+        close(FILE_OUTPUT);
+        # Read GCC pre-processing include path 
+        my $gcc_include_file = abs_path("$CurrlogPath/../tmp/~inc.tmp.tmp");
+        open(FILE_HANDLE, "<$gcc_include_file");
+        while (<FILE_HANDLE>){
+            my $line = $_;
+            chomp($line);
+            if(length($line) == 0){
+                last;
+            }
+            $gcc_include_dir = "$gcc_include_dir -I \"$line\"";
+        }
+        close(FILE_HANDLE);
+        if ($^O eq "MSWin32") {
+            #$gcc_path = abs_path("$CurrlogPath/../../../../tools/MinGW/bin/gcc.exe");
+            $gcc_path = abs_path("./tools/MinGW/bin/gcc.exe");
+        }
+        else {
+            $gcc_path = "gcc";
+        }
+        
+        # Prepare editor info
+        open(FILE_HANDLE, "> $CurrlogPath/nvram_editor_data_item.c");
+        foreach $nvram_editor_folder (@nvram_editor_path){
+            opendir($nvram_editor_dir, $nvram_editor_folder) or die "cannot open build folder $nvram_editor_folder!";
+            &kal_print($ERR_NOTIFY, "open build folder $nvram_editor_folder success! \n");
+            while ($nvram_editor_file_name = readdir($nvram_editor_dir))
+            {
+                next if(($nvram_editor_file_name =~ /^\./) or !($nvram_editor_file_name =~ /\S*nvram_editor.h/));
+                #$nvram_editor_file_name = catfile($nvram_editor_folder,$nvram_editor_file_name);
+                print FILE_HANDLE "#include \"$nvram_editor_file_name\"\n";
+                &kal_print($ERR_DEBUG, "$nvram_editor_file_name\n");
+                $nvram_editor_files ++;
+            }
+            closedir($nvram_editor_dir);
+        }
+        close(FILE_HANDLE);
+        if($nvram_editor_files eq 0) {
+            unlink "$CurrlogPath/gcc_option.h", "$CurrlogPath/nvram_editor_data_item.c";
+            goto lbWhitelistFail;
+        }
+        
+        # Pre-Compile editor.h
+        &kal_print($ERR_NOTIFY, "Compile *_nvram_editor.h\n");
+        
+        my $gcc_command = "$gcc_path -DGEN_FOR_PC -E -C -imacros $CurrlogPath/gcc_option.h -fno-strict-aliasing -fshort-enums -c $CurrlogPath/nvram_editor_data_item.c $gcc_include_dir >$CurrlogPath/nvram_editor_data_item.i 2>>$OutputPath";	
+        &kal_print($ERR_DEBUG, "$gcc_command");
+        my $result = system($gcc_command);
+        &kal_print($ERR_DEBUG, "$gcc_command");
+        if ($result ne 0){
+            # &kal_print($ERR_ERROR, "Gcc pre-compile error when get ota reset whitelist return code: $result\n");
+            &kal_print($ERR_ERROR, "Get OTA reset white list error\n");
+            &kal_print($ERR_NOTIFY, "For more detail information, Please check $CurrlogPath/lid_check_err.log \n");
+            unlink "$CurrlogPath/gcc_option.h", "$CurrlogPath/nvram_editor_data_item.c", "$CurrlogPath/nvram_editor_data_item.i";
+            $Result = $ERR_ERROR;
+            #&WriteFile("$OutputPath",$streamstr);
+            print("Return: $Result\n");
+            exit $Result;
+        }
+    }
+	#open(FILE_HANDLE, "< $CurrlogPath/lid_check_preprocess.txt");
+	open(FILE_HANDLE, "< $CurrlogPath/nvram_editor_data_item.i");
+	#  Analyze whitelist
+	while(<FILE_HANDLE>){
+		my $line = $_;
+		chomp($line);
+		if ($line =~ /^#/) {
+			next;
+		}
+		if ($line =~ /^.*\/[*]+/){
+			#print"Start at $line \n";
+			$is_one_lid_des_start = 1;
+			$is_nvram_lid_not_get = 1;
+		}
+		#if ($line =~ /^.*LID_NAME/i){
+		#	$is_one_lid_des_start = 1;
+		#}
+		if(($line =~ /^.*(NVRAM_[A-Za-z0-9_]+_LID)\s*/) and $is_nvram_lid_not_get ){
+			$current_nvram_lid_item_name = $1;
+			$is_nvram_lid_not_get = 0;
+			#print"$current_nvram_lid_item_name\n";
+		}
+		if(($line =~ /^.*Can OTA Reset/i) and $is_one_lid_des_start){
+			if($line =~ /^.*Yes/i){
+				push(@lids, $current_nvram_lid_item_name);
+			}
+		}
+		if($line =~ /^.*[*]+\//){
+			#print "End at $line \n";
+			$is_one_lid_des_start = 0;
+			$is_nvram_lid_not_get = 0;
+		}
+		#if($line =~ /^.*Update Scenario/i){
+		#	$is_one_lid_des_start = 0;
+		#}
+	};
+    close(FILE_HANDLE);
+	unlink "$CurrlogPath/gcc_option.h", "$CurrlogPath/nvram_editor_data_item.c";
+	
+	&kal_print(0, "Reset Whitelist: @lids\n");
+	&kal_print($ERR_DEBUG, "editor file cnt: $nvram_editor_files\n");
+	return @lids;
+}
+
+sub get_LID_structure_sign
+{
+	my %sign;
+	my $filename = shift;
+	my $gzip_path = "";
+	my $ret_fail = 0;
+
+	# Varify DB exists
+	if(!(-e "$filename")){
+		# DB path not exists
+		&kal_print($ERR_NOTIFY, "DB path: $filename not exists!\n");
+		return %sign; 
+	}
+
+	#Open XML file
+	if(!(-e "$filename/MDDB.META.ODB.XML")) {
+		if ($^O eq "MSWin32") {
+			if($debug_mode eq $ERR_DEBUG) {
+				$gzip_path = abs_path("$CurrlogPath/../../../../tools/NVRAMStatistic/gzip.exe");
+			}
+			else {
+				&kal_print(0, "Can not unzip MDDB.META.ODB.XML in MSWin32.\n");
+				return %sign;
+			}
+		}
+		else {
+			$gzip_path = "gzip";
+		}
+		&kal_print(0, "Unzip $filename/../dhl/database/*.GZ\n");
+		my $gzip_command = "$gzip_path -d -c $filename/../dhl/database/*.GZ > $filename/MDDB.META.ODB.XML 2>>$OutputPath";
+		&kal_print($ERR_DEBUG, "$gzip_command");
+		my $result = system($gzip_command);
+		&kal_print(0, "gzip result: $result \n");
+		if ($result ne 0)
+		{
+			# GZIP ERROR, return 0
+			&kal_print($ERR_DEBUG, "Gzip error, filepath: $filename/../dhl/database/*.GZ \n");
+			unlink "$filename/MDDB.META.ODB.XML";
+			return %sign;
+		}
+	}
+	
+	#$xml = XMLin("$filename/MDDB.META.ODB.XML", ForceArray=>["Field"], KeyAttr=>{"Field"=>"name"});
+	$xml = XMLin("$filename/MDDB.META.ODB.XML");
+	
+	# Merge Secure LIDs into CGEN XML LIDs
+	my @new_lids = (keys (%{$secure_xml->{NVRAM_LIDs}->{NVRAM_LID}}));
+	# Merge secure lid list into CGEN XML LIDs when LID not in CGEN XML LIDs and struct defined 
+	foreach my $secure_lid (@new_lids){
+		my $secure_lid_def = $secure_xml->{NVRAM_LIDs}->{NVRAM_LID}->{$secure_lid};
+		# Switch type_name to struct name
+		my $struct_name = &get_typedefs($xml, $secure_lid_def->{type_name});
+		if ((not defined $xml->{NVRAM_LIDs}->{NVRAM_LID}->{$secure_lid}) and (defined $xml->{Structs}->{Struct}->{$struct_name})){
+			$xml->{NVRAM_LIDs}->{NVRAM_LID}->{$secure_lid} = $secure_lid_def;
+		}
+		elsif((not defined $xml->{NVRAM_LIDs}->{NVRAM_LID}->{$secure_lid}) and (not defined $xml->{Structs}->{Struct}->{$struct_name}))
+		{
+			&kal_print($ERR_WARNING, "Structure $struct_name belongs to SECURE LID: $ secure_lid doesn't exists in $filename/MDDB.META.ODB.XML \n");
+		}
+	}
+	
+	# Relevant entry parent and generate struct/union MD5
+	my @lid_struct_union_name =  ((keys (%{$xml->{Structs}->{Struct}})),(keys (%{$xml->{Unions}->{Union}})));
+	foreach my $lid_struct (@lid_struct_union_name) {
+		my $lid_struct_xml;
+		if(defined $xml->{Structs}->{Struct}->{$lid_struct}) {
+			$lid_struct_xml = $xml->{Structs}->{Struct}->{$lid_struct};
+		}
+		else {
+			$lid_struct_xml = $xml->{Unions}->{Union}->{$lid_struct};
+			# Fill dummy offset sort by field name
+			my $dummy_offset = 0;
+			if(defined $lid_struct_xml->{Field}->{name} and defined $lid_struct_xml->{Field}->{type}) {
+				# This union have just one entry
+				$lid_struct_xml->{Field}->{offset} = 0;
+			}
+			else {
+				foreach my $lid_struct_entry (sort{$a cmp $b} keys (%{$lid_struct_xml->{Field}})) {
+					$lid_struct_xml->{Field}->{$lid_struct_entry}->{offset} = $dummy_offset;
+					$dummy_offset++;
+				}
+			}
+		}
+		my $lid_struct_entry_chksum = "$lid_struct_xml->{size};\n";
+		# Adjust one field format in XML
+		if(defined $lid_struct_xml->{Field}->{name} and defined $lid_struct_xml->{Field}->{type}) {
+			my $new_hash = $lid_struct_xml->{Field};
+			delete $lid_struct_xml->{Field};
+			$lid_struct_xml->{Field}->{$new_hash->{name}} = $new_hash;
+		}
+		# Traversal each field by offset
+		foreach my $lid_struct_entry (sort{$lid_struct_xml->{Field}{$a}->{offset} <=> $lid_struct_xml->{Field}{$b}->{offset} } keys (%{$lid_struct_xml->{Field}})) {
+			my $lid_struct_entry_val = $lid_struct_xml->{Field}->{$lid_struct_entry};
+			# Record define bit variable in structure
+			if($lid_struct_entry =~ /\bbitfields_/) {
+				my $type_name = "$lid_struct:bit";
+				$sign{$type_name}->{$lid_struct_entry} = $lid_struct_entry_val->{offset};
+			}
+			# Collect filed info - Filed name
+			$lid_struct_entry_chksum .= $lid_struct_entry;
+			# Collect filed info - Type_name/Type
+			if(defined $lid_struct_entry_val->{type_name}) {
+				# Mark invalid type_name which in @cgen_auto_rename_list
+				if(grep $lid_struct_entry_val->{type_name} =~ /\b$_/,@cgen_auto_rename_list) {
+					# Rename type_name to Typedefs
+					my $new_name = "$lid_struct-$lid_struct_entry";
+					&add_typedefs($xml, $lid_struct_entry_val->{type_name}, $new_name);
+					# Rename type_name to %sign
+					if(defined $sign{$lid_struct_entry_val->{type_name}}) {
+						$sign{$new_name} =  $sign{$lid_struct_entry_val->{type_name}};
+						delete $sign{$lid_struct_entry_val->{type_name}};
+					}
+				}
+				# Skip get_typedefs when field is pointer
+				if(defined $lid_struct_entry_val->{pointer_count}) {
+					$lid_struct_entry_chksum = "$lid_struct_entry_chksum,$lid_struct_entry_val->{type_name}";
+					goto SKIP_GET_TYPEDEFS;
+				}
+				# replace typedefs
+				(my $pointer_count, my $array_size, $lid_struct_entry_val->{type_name}) = &get_typedefs($xml, $lid_struct_entry_val->{type_name});
+				$lid_struct_entry_chksum = "$lid_struct_entry_chksum,$lid_struct_entry_val->{type_name}";
+				# add {array_size} to filed
+				if($array_size ne '') {
+					$lid_struct_entry_val->{array_sizes} .= $array_size;
+					$lid_struct_entry_val->{array_sizes} =~ s/^,//;
+				}
+				# add {pointer_count} to filed
+				if($pointer_count ne 0) {
+					$lid_struct_entry_val->{pointer_count} = $pointer_count;
+				}
+				SKIP_GET_TYPEDEFS:
+			}
+			else {
+				# The field is not struct/union. No type_name attr.
+				$lid_struct_entry_chksum = "$lid_struct_entry_chksum,$lid_struct_entry_val->{type}";
+			}
+			# Collect filed info - Array
+			if(defined $lid_struct_entry_val->{array_sizes}) {
+				my $array_val = $lid_struct_entry_val->{array_sizes};
+				if($array_val =~ /,/) {
+					$lid_struct_entry_chksum = "$lid_struct_entry_chksum,array[$array_val]";
+				}
+			}
+			# Collect filed info - Pointer
+			if(defined $lid_struct_entry_val->{pointer_count}) {
+				$lid_struct_entry_chksum = "$lid_struct_entry_chksum,pointer";
+			}			
+			# Collect filed info - Offset
+			$lid_struct_entry_chksum = "$lid_struct_entry_chksum,$lid_struct_entry_val->{offset}";
+			# Collect filed info - Size
+			$lid_struct_entry_chksum = "$lid_struct_entry_chksum,$lid_struct_entry_val->{size};\n";
+			# Mark structure/union parent relation
+			if(grep /^$lid_struct_entry_val->{type}$/,("struct", "union")) {
+				if(defined $lid_struct_entry_val->{pointer_count}) {
+					#bypass pointer recursion
+				}
+				else {
+					my $type_name = $lid_struct_entry_val->{type_name};
+					$type_name = "$type_name:parent";
+					$sign{$type_name}->{$lid_struct} = 1;
+				}
+			}
+		}
+		# Calculate struct/union MD5 with field info
+		my $md5 = Digest::MD5->new;
+		$md5->add($lid_struct_entry_chksum);
+		$lid_struct = &get_typedefs($xml, $lid_struct);
+		$sign{$lid_struct} = $md5->b64digest;
+		&kal_print($ERR_DEBUG, "$lid_struct: $md5->b64digest\n");
+	}
+	
+	return ($ret_fail, %sign);
+}
+
+sub compare_LID_structure_sign
+{
+	my %result;
+	
+	foreach my $LID_struct (keys %current_LID_structure_sign) {
+		# Skip parent relation items
+		if(($LID_struct =~ /:parent/)) {
+			next;
+		}
+		# force mark changes when bitfields
+		if(($LID_struct =~ /:bit/)) {
+			my $type_name = substr($LID_struct, 0, -4);
+			$result{$type_name} = "bitfields";
+			next;
+		}
+		if(exists $previous_LID_structure_sign{$LID_struct}) {
+			if($previous_LID_structure_sign{$LID_struct} cmp $current_LID_structure_sign{$LID_struct}) {
+				# LID structure MD5 not match
+				my $data1 = $previous_LID_structure_sign{$LID_struct};
+				my $data2 = $current_LID_structure_sign{$LID_struct};
+				$result{$LID_struct} = "$data1:$data2";
+			}
+		}
+		else {
+			$result{$LID_struct} = $current_LID_structure_sign{$LID_struct};
+		}
+	}
+	return %result;
+}
+
+sub compare_LID_defined_structure
+{
+	foreach my $lid_name (keys (%{$current_xml->{NVRAM_LIDs}->{NVRAM_LID}})) {
+		my $lid_def = $current_xml->{NVRAM_LIDs}->{NVRAM_LID}->{$lid_name};
+		if(exists $previous_xml->{NVRAM_LIDs}->{NVRAM_LID}->{$lid_name}) {
+			my $lid_def2 = $previous_xml->{NVRAM_LIDs}->{NVRAM_LID}->{$lid_name};
+			# replace typedefs
+			$lid_def2->{type_name} = &get_typedefs($previous_xml, $lid_def2->{type_name});
+			$lid_def->{type_name} = &get_typedefs($current_xml, $lid_def->{type_name});
+			
+			if($lid_def->{type_name} cmp $lid_def2->{type_name}) {
+				#LID defined structure are different
+				$changed_LID_name{$lid_name} = $MARK_CHANGED;
+				&kal_print($ERR_DEBUG, "$lid_name structure changed.\n");
+			}
+		}
+		else {
+			#LID not in previous xml, mark to 0
+			if(not defined $changed_LID_name{$lid_name}) {
+				$changed_LID_name{$lid_name} = $MARK_NEW;
+			}
+			&kal_print($ERR_DEBUG, "$lid_name structure created.\n");
+		}
+	}
+}
+
+sub search_structure_reference()
+{
+	my $nm = shift;
+	my $mark = shift;
+	my $nm_ref = "$nm:parent";
+	
+	$xml = $current_xml;
+	if(exists $current_LID_structure_sign{$nm_ref}) {
+		foreach my $nm (keys %{$current_LID_structure_sign{$nm_ref}}) {
+			&search_structure_reference($nm, $mark);
+		}
+	}
+	$changed_LID_structure{$nm} = $mark;
+}
+
+sub search_LID_by_structure_sign()
+{
+	my @structure_list = (keys %changed_LID_structure);
+	$xml = $current_xml;
+	foreach my $lid_name (keys (%{$xml->{NVRAM_LIDs}->{NVRAM_LID}})) {
+		my $lid_def = $xml->{NVRAM_LIDs}->{NVRAM_LID}->{$lid_name};
+		# replace typedefs
+		$lid_def->{type_name} = &get_typedefs($xml, $lid_def->{type_name});
+		if(grep /^$lid_def->{type_name}$/,@structure_list) {
+			&kal_print($ERR_DEBUG, "$lid_name structure changed.\n");
+			$changed_LID_name{$lid_name} = $changed_LID_structure{$lid_def->{type_name}};
+		}
+	}
+}
+
+sub check_lid_structure_verno()
+{
+	my ($param1, $param2) = @_;
+	my %pre_database = %{$param1};
+	my %cur_database = %{$param2};
+	my $ret = 0;
+
+	# check no description LID
+	$xml = $current_xml;
+	foreach my $lid_name (keys %cur_database) {
+		if( (defined $cur_database{$lid_name}->{LID}) and (not exists $xml->{NVRAM_LIDs}->{NVRAM_LID}->{$lid_name}) ) {
+			#check bypass white list
+			if(not grep /^$lid_name$/,@lid_struct_bypass_white_list) {
+				#lid not exist in XML
+				&kal_print($ERR_ERROR, "$lid_name have no description in editor.\n");
+				$ret ++;
+			}
+		}
+	}
+	
+	# check LID structure change without VERNO+1
+	my $Category_MASK = ($CATEGORY_IMPORTANT_ALL|$CATEGORY_OTP|$CATEGORY_INTERNAL);
+	foreach my $lid_name (keys %changed_LID_name) {
+		# handle bitfields
+		if($changed_LID_name{$lid_name} eq $MARK_BITFIELDS) {			
+			if(grep /^$lid_name$/,@lid_struct_bypass_white_list) {
+				#bypass lid exist in lid_struct_bypass_white_list
+				&kal_print($ERR_NOTIFY, "$lid_name structure include bitfields.\n");
+				&kal_print($ERR_NOTIFY, "Bypass check the LID $lid_name.\n");
+				next;
+			}
+			&kal_print($ERR_ERROR, "$lid_name structure include bitfields.\n");
+			$ret ++;
+		}
+		if($changed_LID_name{$lid_name} eq $MARK_CHANGED)
+		{
+			if((hex($cur_database{$lid_name}->{Category}) & $CATEGORY_CALIBRAT) ne 0)
+			{
+				&kal_print($ERR_WARNING, "Calibrate LID:$lid_name structure changed.\r\n");
+			}
+			elsif((hex($cur_database{$lid_name}->{Category}) & $CATEGORY_IMPORTANT) ne 0)
+			{
+				&kal_print($ERR_WARNING, "Important LID:$lid_name strcture changed.\r\n");
+			}
+			else
+			{
+				&kal_print($ERR_NOTIFY, "Other LID:$lid_name strcture changed.\r\n");
+			}
+		}
+		
+		# handle structure change
+		if( ($changed_LID_name{$lid_name} eq $MARK_CHANGED) and
+			(defined $pre_database{$lid_name}) and
+			(defined $cur_database{$lid_name}) and
+			$pre_database{$lid_name}->{Verno} eq $cur_database{$lid_name}->{Verno} ) 
+		{
+			if((hex($cur_database{$lid_name}->{Attribute}) & $ATTR_OTA_RESET) eq 0) {
+				if(($SmartReset eq 1) and ((hex($cur_database{$lid_name}->{Category}) & $Category_MASK) eq 0) ) {
+					&kal_print($ERR_WARNING, "$lid_name structure changed without VERNO+1. (SmartReset)\n");
+				}
+				else {
+						if(grep /^$lid_name$/,@lid_struct_bypass_white_list) {
+							#bypass lid exist in lid_struct_bypass_white_list
+							&kal_print($ERR_NOTIFY, "Bypass check the LID $lid_name.\n");
+							next;
+						}
+						else{
+							&kal_print($ERR_ERROR, "$lid_name structure changed without VERNO+1.\n");
+							$ret ++;
+						}
+				}
+			}
+		}
+	}
+
+	return $ret;
+}
+
+sub get_typedefs()
+{
+	my ($xml, $type_name) = @_;
+	my $array_size = '';
+	my $pointer_count = 0;
+
+	while(exists $xml->{Typedefs}->{Typedef}->{$type_name}->{defined_type_name})
+	{
+		my $Typedef = $xml->{Typedefs}->{Typedef}->{$type_name};
+		my $defined_type_name = $Typedef->{defined_type_name};
+		# merge array info
+		if(defined $Typedef->{defined_array_sizes}) {
+			$array_size = "$array_size,$Typedef->{defined_array_sizes}";
+		}
+		# bypass pointer recursion
+		if(defined $Typedef->{defined_pointer_count}) {
+			$pointer_count = $Typedef->{defined_pointer_count};
+			$type_name = $defined_type_name;
+			last;
+		}
+		# Stop when type_name eq defined_type_name
+		if($type_name eq $Typedef->{defined_type_name}){
+			last;
+		}
+		$type_name = $defined_type_name;
+	}
+	return ($pointer_count, $array_size, $type_name);
+}
+
+sub add_typedefs()
+{
+	my ($xml, $type_name, $new_name) = @_;
+	
+	# replace typedefs
+	if(not exists $xml->{Typedefs}->{Typedef}->{$type_name}->{defined_type_name}) {
+		$xml->{Typedefs}->{Typedef}->{$type_name}->{defined_type_name} = $new_name;
+	}
+}
\ No newline at end of file
diff --git a/mcu/tools/NVRAMStatistic/nvram_post_gen.pl b/mcu/tools/NVRAMStatistic/nvram_post_gen.pl
new file mode 100644
index 0000000..464f645
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_post_gen.pl
@@ -0,0 +1,586 @@
+use strict;
+use warnings;
+use Cwd qw(abs_path);
+use File::Find;
+use File::Copy;
+use File::Spec::Functions;
+use XML::Simple;
+use Digest::MD5;
+
+# Main Start ----------------------------------------------------------------------------------
+	my $version = "v9302_20180425 + (Union Check) + (Fix bitfields)";
+	my ($ERR_OK, $ERR_NOTIFY, $ERR_ERROR, $ERR_WARNING, $ERR_DEBUG, $ERR_OPEN_FILE) = 0..5;
+	my ($ATTR_MULTIPLE, $ATTR_OTA_RESET) = (0x0004,0x0040);
+	my ($CATEGORY_INTERNAL, $CATEGORY_OTP, $CATEGORY_CUSTOM_SENSITIVE, $CATEGORY_FUNC_DEFAULT, $CATEGORY_CALIBRAT, $CATEGORY_IMPORTANT, $CATEGORY_IMPORTANT_L4, $CATEGORY_IMPORTANT_L1) = (0x0001,0x0020,0x0080,0x0400,0x1000,0x2000,0x4000,0x8000);
+	my $CATEGORY_IMPORTANT_ALL = ($CATEGORY_CALIBRAT|$CATEGORY_IMPORTANT|$CATEGORY_IMPORTANT_L4);
+	my $debug_mode = 0; #$ERR_DEBUG;
+	my $CurrlogPath = "";
+	my $OutputPath = "";
+	my $Parameter = "";
+
+	my %CurrDatabase;
+	my $Result = $ERR_OK;
+	my $platform = 0;
+	my $streamstr = "";
+	my $starttime = time();
+	my $usetime = 0;
+	my @ota_reset_lid_white_list;
+	
+	my $xml;
+	my $xml_def;
+	my %current_LID_structure_sign;
+	my $current_sign_status;	
+	my %current_LID_default_value_sign;
+	my %current_LID_chksum;
+	my @cgen_auto_rename_list = ("struct_gename_","struct_apname_","struct_ap[0-9]*nam_","struct_ap[0-9]*na_","struct_cmname_","struct_cm[0-9]*nam_","struct_cm[0-9]*na_","union_gename_","union_apname_","union_ap[0-9]*nam_","union_ap[0-9]*na_","union_cmname_","union_cm[0-9]*nam_","union_cm[0-9]*na_","enum_gename_","enum_apname_","enum_ap[0-9]*nam_","enum_ap[0-9]*na_","enum_cmname_","enum_cm[0-9]*nam_","enum_cm[0-9]*na_");
+	my $swap_file = $0;
+	my $swap_xml;
+	
+	$CurrlogPath = $ARGV[0];
+	if(scalar(@ARGV) > 1) {
+		$OutputPath = $ARGV[1];
+	}
+	else {
+		$OutputPath = "./nvram_post_gen.log";
+	}
+	if ($CurrlogPath eq "")
+	{
+	  $CurrlogPath = "./build/";
+	}
+
+	#if ($^O eq "MSWin32")
+	#{
+	#	print "nvram_lid_check.pl not support MSWin32!!";
+	#	exit $ERR_OK;
+	#}
+	&kal_print(0, "NVRAM post-generation script ver: $version\n");
+	&kal_print(0, "Platform is: $^O\n");
+	&kal_print(0, "Path: $CurrlogPath   ");
+	# Load LID info from log
+	%CurrDatabase = &scan_context($CurrlogPath);
+	# Load Default value
+	%current_LID_default_value_sign = &get_LID_default_value_sign($CurrlogPath);
+	# Load MDDB XML
+	($current_sign_status, %current_LID_structure_sign) = &get_LID_structure_sign($CurrlogPath);
+	# Load Checksum Swap List
+	$swap_file =~ s/nvram_post_gen.pl/checksum_swap_list.xml/;
+	$swap_xml = &load_checksum_swap_list($swap_file);
+	# Calculate LID structure checksum
+	if((keys %current_LID_structure_sign) eq 0) {
+		&kal_print(0, "XML file read unexpected. Skip calculate LID structure checksum.\n");
+	}
+	elsif($current_sign_status ne 0) {
+		&kal_print($ERR_ERROR, "Can not define bit variable in structure/union.\n");
+		$Result = $ERR_ERROR;
+	}
+	else {	
+		my $Category_MASK = ($CATEGORY_IMPORTANT_ALL|$CATEGORY_INTERNAL);
+		foreach my $lid_name (keys (%{$xml->{NVRAM_LIDs}->{NVRAM_LID}})) {
+			if(not defined $CurrDatabase{$lid_name}) {
+				&kal_print($ERR_WARNING, "XML:$lid_name do not exists in log file.\n");
+				next;
+			}
+			my $lid_category = hex($CurrDatabase{$lid_name}->{Category});
+			my $lid_attr = hex($CurrDatabase{$lid_name}->{Attribute});
+			if( (($lid_category & $Category_MASK) eq 0) and
+				(($lid_attr & $ATTR_OTA_RESET) eq 0) ) 
+			{
+				if(($lid_category & $CATEGORY_FUNC_DEFAULT) eq 0) {
+					$current_LID_chksum{$lid_name}->{Default} = $current_LID_default_value_sign{$lid_name};
+				}
+				my $type_name = $xml->{NVRAM_LIDs}->{NVRAM_LID}->{$lid_name}->{type_name};
+				my $chksum = &integrate_LID_structure_sign($xml, \%current_LID_structure_sign, $type_name);
+				if($chksum eq 'bitfields') {
+					&kal_print($ERR_ERROR, "$lid_name structure include bitfields.\n");
+					$Result = $ERR_ERROR;
+				}
+				$current_LID_chksum{$lid_name}->{Structure} = $chksum;				
+			}			
+		}
+	}
+	my $output_chksum = &output_LID_structure_sign("$CurrlogPath/nvram_checksum_reset.h");
+	$usetime = time() - $starttime;	
+	&kal_print(0, "nvram_post_gen spend time:  $usetime s\n");
+	&kal_print(0, "outputfile: $OutputPath\n");
+	&kal_print(0, "Return: $Result\n");
+	&WriteFile("$OutputPath",$streamstr); 
+	exit $Result;
+# Main End ----------------------------------------------------------------------------------
+
+sub get_lid_size
+{	 
+	(my ($lidname),my ($lidid),my($strFilePath)) = @_;
+	my ($filename) = "$strFilePath/~nvram_lid_size.log";
+
+	open FILEHANDLE2, "<$filename" or die "couldn't open $filename\n" && return $ERR_OPEN_FILE;
+	while (<FILEHANDLE2>) 
+	{		
+		my $line = $_;      
+		chomp($line);
+
+		if($line =~ /\s$lidname/g)
+		{
+			$line = trim($line);
+			my @lidinfo = split(/ +/, $line);
+			if($lidid eq $lidinfo[0])
+			{
+				return $lidinfo[1];
+				last;
+			}
+		}
+    } 	
+	close FILEHANDLE2;
+	return 0;
+}	
+	
+sub scan_context
+{	
+	my %database;
+	my ($strFilePath) = @_;
+	my $filename = "$strFilePath/~nvram_lid_information.log";
+	my $count = 0;
+	
+	open FILEHANDLE, "<$filename" or die "couldn't open $filename\n" && return;
+
+	while (<FILEHANDLE>) 
+	{		
+		my $line = $_;      
+		chomp($line);
+
+		if($line =~ /\s*NVRAM_.*_LID/g)
+		{
+			$line = trim($line);
+			my @lidinfo = split(/ +/, $line);
+			$lidinfo[4] = get_lid_size($lidinfo[1], $lidinfo[0], $strFilePath);
+			#print "@lidinfo\r\n";
+			#&kal_print($ERR_NOTIFY, "@lidinfo\r\n");
+			#  @lidinfo[0]  LID,
+			#  @lidinfo[1]  LID_Str,
+			#  @lidinfo[2]  Filename,
+			#  @lidinfo[3]  Verno,
+			#  @lidinfo[4]  Length,
+			#  @lidinfo[5]  Category,
+			#  @lidinfo[6]  Attribute
+			my %lidinfo = (LID=>"$lidinfo[0]", LID_Str=>"$lidinfo[1]", Filename=>"$lidinfo[2]", Verno=>"$lidinfo[3]", Length=>"$lidinfo[4]", Category=>"$lidinfo[5]", Attribute=>"$lidinfo[6]");
+			#push(@database, {%lidinfo});
+			$database{$lidinfo[1]} = {%lidinfo};
+			$count++;
+		} 
+	}
+	close FILEHANDLE;
+
+	return %database; 
+}	
+	
+sub trim()
+{
+	my ($str) = @_;
+	$str =~ s/^\s+//;
+	$str =~ s/\s+$//;
+	return $str;
+}
+
+sub kal_print()
+{
+	my ($level, $msg) = @_;
+	if($level eq $ERR_ERROR)
+	{
+		print "Error: ";
+		$streamstr .= "Error: ";
+	}
+	if($level eq $ERR_WARNING)
+	{
+		print "Warning: ";
+		$streamstr .= "Warning: ";
+	}	
+	if($level eq $ERR_NOTIFY)
+	{
+		print "Notify: ";
+		$streamstr .= "Notify: ";
+	}	
+	if($level eq $ERR_DEBUG) {
+		if($debug_mode eq $ERR_DEBUG) {
+			print "Debug: ";
+		}
+		else {
+			return;
+		}		
+	}
+
+	print "$msg";
+	$streamstr .= "$msg";
+}
+	
+sub WriteFile
+{
+    my ($strFilePath, $strContent) = @_;
+    open FILE_HANDLE, ">$strFilePath" or  print "couldn't open $strFilePath\n" && return $ERR_OPEN_FILE;
+    print FILE_HANDLE $strContent;
+    close FILE_HANDLE;
+}
+
+sub get_LID_default_value_sign
+{
+	my %sign;
+	my $filename = shift;
+
+	if(!(-e "$filename/custom_nvram_lid_cat.xml")) {
+		return %sign;
+	}
+	$xml_def = XMLin("$filename/custom_nvram_lid_cat.xml");
+	foreach my $lid_name (keys (%{$xml_def->{NVRAMITEM}})) {
+		my $default_val;
+		my $lid_xml = $xml_def->{NVRAMITEM}->{$lid_name}->{DEFAULT_VALUE};
+		if($lid_xml =~ /\s*\[/g) {
+			# const default value
+			$default_val = &trim($lid_xml);
+		}
+		elsif(exists $lid_xml->{defaultByteFill}) {
+			$default_val = $lid_xml->{defaultByteFill};
+			# function default value
+			if($default_val =~ /\s*\(\)/g) {
+				next;
+			}
+			# static default value
+			$default_val = "[$default_val]";
+		}
+		else {
+			$default_val = &trim($lid_xml->{content});
+		}
+		my $md5 = Digest::MD5->new;
+		$md5->add($default_val);
+		$sign{$lid_name} = $md5->hexdigest;
+		&kal_print($ERR_DEBUG, "$lid_name: $md5->hexdigest\n");
+	}
+	
+	return %sign;
+}
+
+sub get_LID_structure_sign
+{
+	my %sign;
+	my $filename = shift;
+	my $gzip_path = "";
+	my $ret_fail = 0;
+
+	#Open XML file
+	if(!(-e "$filename/MDDB.META.ODB.XML")) {
+		if ($^O eq "MSWin32") {
+			if($debug_mode eq $ERR_DEBUG) {
+				$gzip_path = abs_path("$CurrlogPath/../../../../pcore/tools/NVRAMStatistic/gzip.exe");
+			}
+			else {
+				&kal_print(0, "Can not unzip MDDB.META.ODB.XML in MSWin32.\n");
+				return %sign;
+			}
+		}
+		else {
+			$gzip_path = "gzip";
+		}
+		&kal_print(0, "Unzip $filename/*.GZ\n");
+		my $gzip_command = "$gzip_path -d -c $filename/../dhl/database/*.GZ > $filename/MDDB.META.ODB.XML";
+		&kal_print($ERR_DEBUG, "$gzip_command");
+		my @result = readpipe("$gzip_command");
+		if((stat "$filename/MDDB.META.ODB.XML")[7] eq '0') {
+			unlink glob "$filename/MDDB.META.ODB.XML";
+		}
+	}
+	if(!(-e "$filename/MDDB.META.ODB.XML")) {
+		return %sign;
+	}
+	#$xml = XMLin("$filename/MDDB.META.ODB.XML", ForceArray=>["Field"], KeyAttr=>{"Field"=>"name"});
+	$xml = XMLin("$filename/MDDB.META.ODB.XML");
+	
+	# Relevant entry parent and generate struct/union MD5
+	my @lid_struct_union_name =  ((keys (%{$xml->{Structs}->{Struct}})),(keys (%{$xml->{Unions}->{Union}})));
+	foreach my $lid_struct (@lid_struct_union_name) {
+		my $lid_struct_xml;
+		if(defined $xml->{Structs}->{Struct}->{$lid_struct}) {
+			$lid_struct_xml = $xml->{Structs}->{Struct}->{$lid_struct};
+		}
+		else {
+			$lid_struct_xml = $xml->{Unions}->{Union}->{$lid_struct};
+			# Fill dummy offset sort by field name
+			my $dummy_offset = 0;
+			if(defined $lid_struct_xml->{Field}->{name} and defined $lid_struct_xml->{Field}->{type}) {
+				# This union have just one entry
+				$lid_struct_xml->{Field}->{offset} = 0;
+			}
+			else {
+				foreach my $lid_struct_entry (sort{$a cmp $b} keys (%{$lid_struct_xml->{Field}})) {
+					$lid_struct_xml->{Field}->{$lid_struct_entry}->{offset} = $dummy_offset;
+					$dummy_offset++;
+				}
+			}
+		}
+		my $lid_struct_entry_chksum = "$lid_struct_xml->{size};\n";
+		# Adjust one field format in XML
+		if(defined $lid_struct_xml->{Field}->{name} and defined $lid_struct_xml->{Field}->{type}) {
+			my $new_hash = $lid_struct_xml->{Field};
+			delete $lid_struct_xml->{Field};
+			$lid_struct_xml->{Field}->{$new_hash->{name}} = $new_hash;
+		}
+		# Traversal each field by offset
+		foreach my $lid_struct_entry (sort{$lid_struct_xml->{Field}{$a}->{offset} <=> $lid_struct_xml->{Field}{$b}->{offset} } keys (%{$lid_struct_xml->{Field}})) {
+			my $lid_struct_entry_val = $lid_struct_xml->{Field}->{$lid_struct_entry};
+			# Record define bit variable in structure
+			if($lid_struct_entry =~ /\bbitfields_/) {
+				my $type_name = "$lid_struct:bit";
+				$sign{$type_name}->{$lid_struct_entry} = $lid_struct_entry_val->{offset};
+			}
+			# Collect filed info - Filed name
+			$lid_struct_entry_chksum .= $lid_struct_entry;
+			# Collect filed info - Type_name/Type
+			if(defined $lid_struct_entry_val->{type_name}) {
+				# Mark invalid type_name which in @cgen_auto_rename_list
+				if(grep $lid_struct_entry_val->{type_name} =~ /\b$_/,@cgen_auto_rename_list) {
+					# Rename type_name to Typedefs
+					my $new_name = "$lid_struct-$lid_struct_entry";
+					&add_typedefs($xml, $lid_struct_entry_val->{type_name}, $new_name);
+					# Rename type_name to %sign
+					if(defined $sign{$lid_struct_entry_val->{type_name}}) {
+						$sign{$new_name} =  $sign{$lid_struct_entry_val->{type_name}};
+						delete $sign{$lid_struct_entry_val->{type_name}};
+					}
+				}
+				# Skip get_typedefs when field is pointer
+				if(defined $lid_struct_entry_val->{pointer_count}) {
+					$lid_struct_entry_chksum = "$lid_struct_entry_chksum,$lid_struct_entry_val->{type_name}";
+					goto SKIP_GET_TYPEDEFS;
+				}
+				# replace typedefs
+				(my $pointer_count, my $array_size, $lid_struct_entry_val->{type_name}) = &get_typedefs($xml, $lid_struct_entry_val->{type_name});
+				$lid_struct_entry_chksum = "$lid_struct_entry_chksum,$lid_struct_entry_val->{type_name}";
+				# add {array_size} to filed
+				if($array_size ne '') {
+					$lid_struct_entry_val->{array_sizes} .= $array_size;
+					$lid_struct_entry_val->{array_sizes} =~ s/^,//;
+				}
+				# add {pointer_count} to filed
+				if($pointer_count ne 0) {
+					$lid_struct_entry_val->{pointer_count} = $pointer_count;
+				}
+				SKIP_GET_TYPEDEFS:
+			}
+			else {
+				# The field is not struct/union. No type_name attr.
+				$lid_struct_entry_chksum = "$lid_struct_entry_chksum,$lid_struct_entry_val->{type}";
+			}
+			# Collect filed info - Array
+			if(defined $lid_struct_entry_val->{array_sizes}) {
+				my $array_val = $lid_struct_entry_val->{array_sizes};
+				if($array_val =~ /,/) {
+					$lid_struct_entry_chksum = "$lid_struct_entry_chksum,array[$array_val]";
+				}
+			}
+			# Collect filed info - Pointer
+			if(defined $lid_struct_entry_val->{pointer_count}) {
+				$lid_struct_entry_chksum = "$lid_struct_entry_chksum,pointer";
+			}			
+			# Collect filed info - Offset
+			$lid_struct_entry_chksum = "$lid_struct_entry_chksum,$lid_struct_entry_val->{offset}";
+			# Collect filed info - Size
+			$lid_struct_entry_chksum = "$lid_struct_entry_chksum,$lid_struct_entry_val->{size};\n";
+			# Mark structure/union child relation
+			if(grep /^$lid_struct_entry_val->{type}$/,("struct", "union")) {
+				if(defined $lid_struct_entry_val->{pointer_count}) {
+					#bypass pointer recursion
+				}
+				else {
+					my $type_name = "$lid_struct:child";
+					$sign{$type_name}->{$lid_struct_entry_val->{type_name}} = $lid_struct_entry_val->{offset};
+				}
+			}
+		}
+		# Calculate struct/union MD5 with field info
+		my $md5 = Digest::MD5->new;
+		$md5->add($lid_struct_entry_chksum);
+		$lid_struct = &get_typedefs($xml, $lid_struct);
+		$sign{$lid_struct} = $md5->digest;
+		&kal_print($ERR_DEBUG, "$lid_struct: $md5->digest\n");
+	}
+	
+	return ($ret_fail, %sign);
+}
+
+sub integrate_LID_structure_sign
+{
+	my ($gXml, $param2, $type_name) = @_;
+	my %LID_structure_sign = %{$param2};
+	
+	# replace typedefs
+	$type_name = &get_typedefs($gXml, $type_name);
+	my $chksum = $LID_structure_sign{$type_name};
+	&kal_print($ERR_DEBUG, "$type_name: $chksum\n");
+	# check bitfields
+	$type_name = "$type_name:bit";
+	if(defined $LID_structure_sign{$type_name}) {
+		return 'bitfields';
+	}
+	# integrate child structure md5
+	$type_name = "$type_name:child";
+	if(defined $LID_structure_sign{$type_name}) {
+		foreach my $struct_name (sort{$LID_structure_sign{$type_name}->{$a} <=> $LID_structure_sign{$type_name}->{$b} } keys (%{$LID_structure_sign{$type_name}})) {
+			#print "$struct_name";
+			my $ref_chksum = &integrate_LID_structure_sign($gXml, \%LID_structure_sign, $struct_name);
+			if($ref_chksum eq 'bitfields') {
+				return 'bitfields';
+			}
+			$chksum = "$chksum;$ref_chksum";
+		}
+	}
+	my $md5 = Digest::MD5->new;
+	$md5->add($chksum);
+	return $md5->hexdigest;	
+}
+
+sub output_LID_structure_sign()
+{
+	my $filename = shift;
+	my $default_write_to_file = "";
+	my $struct_write_to_file = "";
+	
+	foreach my $LID_name (sort{$a cmp $b} keys %current_LID_chksum) {
+		my $LID_id = $xml->{NVRAM_LIDs}->{NVRAM_LID}->{$LID_name}->{id};
+		my $output = "";
+		my $chksum = $current_LID_chksum{$LID_name}->{Structure};
+		if($chksum eq 'bitfields') {
+			$output = "$LID_name structure include bitfields";
+		}
+		else {
+			for (my $idx = 0; $idx < 32; $idx = $idx + 2) {
+				my $data = substr($chksum, $idx, 2);
+				$output = "$output 0x$data,";
+			}
+			$output = substr($output, 1, 94);
+			$output = &check_checksum_swap($LID_name, $LID_id, $output, 'struct_checksum', $swap_xml);
+		}
+		$struct_write_to_file = "$struct_write_to_file\t{$LID_id /*$LID_name*/, {$output}},\n";
+		
+		if(defined $current_LID_chksum{$LID_name}->{Default}) {
+			my $output = "";
+			my $chksum = $current_LID_chksum{$LID_name}->{Default};
+			for (my $idx = 0; $idx < 32; $idx = $idx + 2) {
+				my $data = substr($chksum, $idx, 2);
+				$output = "$output 0x$data,";
+			}
+			$output = substr($output, 1, 94);
+			$output = &check_checksum_swap($LID_name, $LID_id, $output, 'default_checksum', $swap_xml);
+			$default_write_to_file = "$default_write_to_file\t{$LID_id /*$LID_name*/, {$output}},\n";
+		}
+	}
+	# Write to file
+	open (OUT, ">$filename");
+	print OUT "#ifndef NVRAM_CHECKSUM_RESET_H\n";
+	print OUT "#define NVRAM_CHECKSUM_RESET_H\n";
+	print OUT "\n";
+	print OUT "#ifdef __cplusplus\n";
+	print OUT "extern \"C\"\n";
+	print OUT "{\n";
+	print OUT "#endif /* __cplusplus */\n";
+	print OUT "\n";
+	print OUT "const checksum_reset_struct lid_default_value_chksum[] =\n";
+	print OUT "{\n";
+	print OUT "\t{0 /*dummy_item to avoid build error*/, {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}},\n";
+	print OUT "$default_write_to_file\n";
+	print OUT "};\n";
+	print OUT "\n";
+	print OUT "const checksum_reset_struct lid_structure_chksum[] =\n";
+	print OUT "{\n";
+	print OUT "\t{0 /*dummy_item to avoid build error*/, {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}},\n";
+	print OUT "$struct_write_to_file\n";
+	print OUT "};\n";
+	print OUT "\n";
+	print OUT "kal_uint32 lid_structure_chksum_num = sizeof(lid_structure_chksum)/sizeof(checksum_reset_struct);\n";
+	print OUT "kal_uint32 lid_default_value_chksum_num = sizeof(lid_default_value_chksum)/sizeof(checksum_reset_struct);\n";
+	print OUT "\n";
+	print OUT "#ifdef __cplusplus\n";
+	print OUT "}\n";
+	print OUT "#endif\n";
+	print OUT "#endif\n";
+	close OUT;
+}
+
+sub get_typedefs()
+{
+	my ($xml, $type_name) = @_;
+	my $array_size = '';
+	my $pointer_count = 0;
+
+	while(exists $xml->{Typedefs}->{Typedef}->{$type_name}->{defined_type_name})
+	{
+		my $Typedef = $xml->{Typedefs}->{Typedef}->{$type_name};
+		my $defined_type_name = $Typedef->{defined_type_name};
+		# merge array info
+		if(defined $Typedef->{defined_array_sizes}) {
+			$array_size = "$array_size,$Typedef->{defined_array_sizes}";
+		}
+		# bypass pointer recursion
+		if(defined $Typedef->{defined_pointer_count}) {
+			$pointer_count = $Typedef->{defined_pointer_count};
+			$type_name = $defined_type_name;
+			last;
+		}
+		# Stop when type_name eq defined_type_name
+		if($type_name eq $Typedef->{defined_type_name}){
+			last;
+		}
+		$type_name = $defined_type_name;
+	}
+	return ($pointer_count, $array_size, $type_name);
+}
+
+sub add_typedefs()
+{
+	my ($xml, $type_name, $new_name) = @_;
+	
+	# replace typedefs
+	if(not exists $xml->{Typedefs}->{Typedef}->{$type_name}->{defined_type_name}) {
+		$xml->{Typedefs}->{Typedef}->{$type_name}->{defined_type_name} = $new_name;
+	}
+}
+
+sub load_checksum_swap_list()
+{
+	my $filename = shift;
+	my $swap_xml;
+	
+	#Open XML file
+	if(-e "$filename") {
+		$swap_xml = XMLin("$filename");
+	}
+	if(not defined $swap_xml->{NVRAM_LIDs}) {
+		$swap_xml = {EMTRY => 0};
+		return $swap_xml;
+	}
+	return $swap_xml->{NVRAM_LIDs}->{NVRAM_LID};
+}
+
+sub check_checksum_swap()
+{
+	my ($lid_name, $lid_id, $lid_chksum, $swap_type, $swap_xml) = @_;
+	
+	if(not defined $swap_xml->{$lid_name}) {
+		return $lid_chksum;
+	}
+	# Adjust one field format in XMLs
+	if(defined $swap_xml->{$lid_name}->{Field}->{checksum}) {
+		my $new_hash = $swap_xml->{$lid_name}->{Field};
+		delete $swap_xml->{$lid_name}->{Field};
+		$swap_xml->{$lid_name}->{Field}->{0} = $new_hash;
+	}
+	# Check LID name
+	my $lid_entry = $swap_xml->{$lid_name}->{Field};
+	foreach my $swap_id (keys (%{$lid_entry})) {
+		if(($lid_entry->{$swap_id}->{type} eq $swap_type) and
+		   ($lid_entry->{$swap_id}->{checksum} eq $lid_chksum)) 
+		{
+			# replace checksum by swap_checksum
+			&kal_print($ERR_DEBUG, "hit swap checksum $lid_name\n");
+			$lid_chksum = $lid_entry->{$swap_id}->{swap_checksum};
+			last;
+		}
+	}
+	return $lid_chksum;
+}
+
diff --git a/mcu/tools/NVRAMStatistic/nvram_pre_gen.pl b/mcu/tools/NVRAMStatistic/nvram_pre_gen.pl
new file mode 100644
index 0000000..01575e2
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_pre_gen.pl
@@ -0,0 +1,376 @@
+use strict;

+use warnings;

+use Cwd;

+use File::Find;

+use File::Copy;

+

+

+	my ($ERR_OK, $ERR_OPEN_FILE, $ERR_HISR_INDEX) = 0..2;

+	my $outputpath = $ARGV[0]; 

+

+	my $debug = 0;

+	my $platform = 0;

+	my $streamstr =(["0", "1"]);

+	my $starttime = time();

+	my $usetime = 0;

+	 

+	my @resultlist;

+	my $arrayC = 0;

+	my $arrayL = 0;

+	my $index = 0;

+  	my $mycur = cwd;

+

+	my $tooldir = "../../pcore/tools/NVRAMStatistic";

+	my $curdir;

+	my $searchdir = "../../custom";

+

+	print "Platform is: $^O\n";

+	

+	if ($^O eq "MSWin32")

+	{

+		$platform = 0;

+	}

+	else

+	{

+		$platform = 1;

+	}

+

+	if ($platform == 1)

+	{

+	  chdir("./pcore/tools/NVRAMStatistic");

+	}	

+	

+	chdir($searchdir);

+	find(\&CheckLidFileName, cwd);

+

+	if($platform == 0)

+	{		

+		my $srchdir = "../nvram/src";

+		chdir($srchdir);		

+		find(\&CheckLidFileName, cwd);

+		chdir("../../custom");

+	}

+	else

+	{

+		my $srchdir = "../../pcore/service/nvram/src";

+		chdir($srchdir);

+		

+		find(\&CheckLidFileName, cwd);

+		chdir("../../../custom");

+	}

+	

+	my $indexarray = $#resultlist+1;  

+  

+	$streamstr .= sprintf("Total LID Num: %d \n", $indexarray);

+

+	$streamstr .= "\n sort LID file name \n";		

+	$streamstr .= "\n    Nvram LID                                      File name \n";

+		

+	my $temp;

+	my $tempName;

+	my $temp1;

+	my $tempName1;

+	my $repeat = 0;

+	my $j;

+	my @list = sort{$a->[1] cmp $b->[1]}@resultlist;     #sort array 

+	

+	$tempName = $list[1][0];

+	$temp = $list[1][1];

+

+	for(my $i = 1; $i < $#list+1; $i++)

+	{

+		for($j = 0; $j <2; $j++)

+		{

+			if($j==0)

+  		  {

+	  		$tempName1 = $list[$i][$j];

+		  }

+		  else

+		  {

+			  $temp1 = $list[$i][$j];

+					  

+			  if (($tempName eq $tempName1) && ($temp eq $temp1) && $i > 1)

+			  {			  	

+			  	$repeat = 1;

+			  }

+			  else

+			  {			  	

+			  	$repeat = 0;

+			  }			

+		  }

+		}

+		

+		if( $repeat == 0 )

+		{

+			$streamstr .= sprintf("%-64s", $tempName1);

+			$streamstr .= sprintf("%-64s", $temp1);

+			$streamstr .= "\n";			

+		}		

+		$tempName = $tempName1;

+		$temp = $temp1;			

+	}

+			

+	chdir($tooldir);

+	

+	my @gen_array;

+	my $genindex= 0;

+	my @tar_array;

+	my $tarindex= 0;

+    

+	# get code from nvram_gen_assign_entry() 

+	my $searchfiledir = "src/";  

+	my $searchfilefile = "nvram_gen_util.c"; 

+	chdir($searchfiledir);

+	find(\&CheckLIDAssginTableEntry, $searchfilefile);

+	$curdir ="../";

+	chdir($curdir);

+   

+  # get code from nvram_assign_table_entry() 

+	my $searchtardir; 

+	if($platform == 0)

+	{

+		$searchtardir = "../../nvram/src/"; 

+	}

+	else

+	{

+		$searchtardir = "../../../pcore/service/nvram/src/";

+	}

+	

+	my $searchtarfile = "nvram_ltable.c";

+	chdir($searchtardir);

+	find(\&CheckLIDAssginTableEntry, $searchtarfile); 

+

+    if($platform == 0)

+    {

+		$curdir ="../../../pcore/tools/NVRAMStatistic";

+	}

+	else

+	{

+		$curdir ="../../../../pcore/tools/NVRAMStatistic";

+	}

+	

+	chdir($curdir);

+	my $dif = 0;

+	

+	print "genindex = $genindex   tarindex = $tarindex \n";

+	if( $genindex == $tarindex )

+	{

+		for(my $i = 0; $i<$#gen_array; $i++)

+		{

+			if($gen_array[$i] ne $tar_array[$i])

+			{

+			    $dif++;

+			}	

+		}

+	}

+	else

+	{

+		print" \n warning: genindex != tarindex !!!!\n";

+	}

+	

+	if($dif > 0)

+	{

+		print" dif = $dif \n";

+		$streamstr .= "Warning: nvram_assign_table_entry is different with nvram_gen_assign_entry!!!!!\n";

+		$streamstr .= sprintf("dif = %d \n", $dif);

+	}	

+	

+	$usetime = time() - $starttime;	

+	print "Buid spend time:  $usetime S\n";		

+	$streamstr .= sprintf("Nvram_pre_gen Check spend time: %d \n", $usetime);

+	WriteFile("../../$outputpath/nvramfilenameinfo.log",$streamstr); 

+	WriteFile("/nvramfilenameinfo.log", $streamstr);

+	exit $ERR_OK;

+  

+sub CheckLidFileName

+{

+	my $file = $File::Find::name; 	

+

+	if($platform == 0)

+	{

+		$file =~ s,/,\\,g;

+	}

+	return unless $file =~ /.*nvram_.*\.c$/gi;  #file pattern

+	search_context($file);

+}

+

+sub search_context

+{	 

+	my ($strFilePath) = @_;

+

+	open FILEHANDLE, "<$strFilePath" or die "couldn't open $strFilePath\n" && return $ERR_OPEN_FILE;

+	

+	my $bLtable = 0;     # found ltable_entry_struct logi

+	my $startparse = 0;  # first {

+	my $bfindLid = 0;    # need to find a lid  ,if no lid ,how to do

+	my $bfindFname = 0;

+	my $finishFlag = 0;

+	my $count = 0;

+    

+	while (<FILEHANDLE>) 

+	{		

+    my $line = $_;      

+    chomp($line);

+      

+    if($line =~ /\s*ltable_entry_struct.+logical_data_item_table_.*=.*/g)

+    {

+    	$streamstr .= sprintf("\n %d %s \n", $index, $line);

+    	

+    	$bLtable = 1;

+    	$startparse = 0;   # first {

+    	$bfindLid = 1;

+    	$bfindFname = 0;

+    	$finishFlag = 0;

+    	$index++;

+    	next;

+    } 

+    

+    if($finishFlag == 0 && $startparse ==0 && $bLtable == 1 )

+    {

+    	my $tmpline = $line;

+    	

+    	$tmpline =~ s/\s*//;

+    	

+    	if( $tmpline =~ /{.*/g)

+    	{

+    		$finishFlag ++;

+    		#avoid blank line or line with "; ,"

+    		$startparse = 1;

+    		next;

+    	}	

+    	 

+      if( $tmpline =~ /}.*/g)

+    	{

+    		$finishFlag --;

+    		next;

+    	}	 

+    }

+    

+    if($finishFlag == 0 && $finishFlag == 1 )

+    {

+    	#ltable finished    	

+    	$bLtable = 0;

+    	$startparse = 0;

+    	$bfindLid = 0;

+    	$bfindFname = 0;

+    	next;

+    }       

+    

+    if( $startparse ==1 && $bLtable == 1 && $bfindLid == 1 )

+    {

+    	#find the lid name NVRAM_EF_***_LID

+    	my $lidstr = $line;

+    	$lidstr =~ s/\s*//;

+    	chomp($lidstr);

+

+    	if($lidstr =~ /^NVRAM_EF_.+_LID.*,/g) 

+		{

+			my $lidstr = $line;

+			$lidstr =~ s/\s*//; 

+

+			do{;}until(chop($lidstr) eq ",");

+

+			$resultlist[$arrayC][$arrayL] = $lidstr;

+			$streamstr .= sprintf("%-54s", $resultlist[$arrayC][$arrayL]);

+			$arrayL++;	

+			$bfindFname = 1;   #should get the file name

+			next;			    		

+		}

+    	

+    	if ( $startparse ==1 && $bLtable == 1 && $bfindFname == 1)

+	    {

+	    	# fine file name  "MT010001"

+	    	if($line =~ /".+"/g) 

+	    	{

+	    		my $lidstr = $line;

+	    		$lidstr =~ s/\s*//; 

+	    		

+	    		do{;}until(chop($lidstr) eq ",");

+	    		

+	    		$resultlist[$arrayC][$arrayL] = $lidstr; 

+	    		$streamstr .= sprintf("%s\n", $resultlist[$arrayC][$arrayL]);

+	    		$arrayC++;

+	    		$arrayL = 0; 

+	    		$bfindFname = 0;	

+	    	}

+	    	next;

+	    }     	

+    }    

+  }   

+  return;   

+}

+

+

+sub CheckLIDAssginTableEntry

+{

+	my $file = $File::Find::name; 	

+

+	if($platform == 0)

+	{

+		$file =~ s,/,\\,g;         # with path and file name

+	}

+	

+	if($file =~ /\s*nvram_ltable.c$/gi)

+	{  

+		copyCode($file,0);

+	}	

+	if($file =~ /\s*nvram_gen_util.c$/gi)

+	{

+		copyCode($file,1);

+	}

+}

+	

+sub copyCode

+{

+	my ($file, $index) = @_;

+	my $startflag = 0;

+

+	open FILEHANDLE, "<$file" or die "couldn't open $file\n" && return $ERR_OPEN_FILE;

+	

+	while (<FILEHANDLE>) 

+	{		

+	    my $line = $_;

+	        

+	    chomp($line);

+   

+    if($line =~ /\s*.*Tool check begin: nvram_pre_gen.pl.*/g)

+    {

+    	$startflag = 1;

+    	next;

+    }

+    

+    if($startflag == 1)

+    {

+    	if($line =~ /\s*.*Tool check end: nvram_pre_gen.pl/g)

+    	{

+    		$startflag = 0;

+    		last;

+    	}

+    	else

+    	{

+    		if($line !~ /\s*nvram_gen_backup.*/g )

+    		{

+	    		if($index ==1)

+		    	{

+			    	$gen_array[$genindex] = $line;

+			    	$genindex++;

+		    	}

+		    	else

+		    	{

+		    		$tar_array[$tarindex] = $line;

+			    	$tarindex++;

+		    	}	    		  

+    		}  

+    		next;		

+    	}   	

+    }

+  }

+}  

+

+sub WriteFile

+{

+    my ($strFilePath, $strContent) = @_;

+    open FILE_HANDLE, ">$strFilePath" or  print "couldn't open $strFilePath\n" && return $ERR_OPEN_FILE;

+    print FILE_HANDLE $strContent;

+    close FILE_HANDLE;

+}
\ No newline at end of file
diff --git a/mcu/tools/NVRAMStatistic/nvram_usage_check.pl b/mcu/tools/NVRAMStatistic/nvram_usage_check.pl
new file mode 100644
index 0000000..b0f89ae
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_usage_check.pl
@@ -0,0 +1,161 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use Cwd;
+use File::Find;
+use File::Copy;
+use File::Spec::Functions;
+
+	my ($i, $j, $k, $t);
+	my ($ERR_OK, $ERR_ERROR, $ERR_WARNING) = 0..2;
+	my $exist_duplicate = 0;
+	my @name_array;
+	my $name_num = 0;
+	my @file_list;
+	my $file_path_num;
+	my $file_list_num;
+	my @group_end_index;
+	my $group_num;
+	my $cur_dir = getcwd;
+	my $log_info = ""; 
+	my $log_out_file;
+
+	#nvram_usage_check.pl is called by codegen.mak and codegen.mak is run in mcu folder
+	#so in this script will use $cur_dir to get mcu folder's path
+	#this path is normal nvram group file path
+	my @file_path = qw(
+						/custom/service/nvram
+						/custom/middleware/common
+						/custom/driver/common
+						/custom/protocol/common/ps
+						/service/nvram/src
+					  );
+
+	#print "\n^^^^^^^^^^^^^^^^^^^^^^  $cur_dir  ^^^^^^^^^^^^^^^^^^^^^^\n";
+
+	#generate log out put path
+	$i = @ARGV;
+	if($i >= 1)
+	{
+		$log_out_file = $ARGV[0];
+	}
+	else
+	{
+		$log_out_file = "./nvram_usage_check.log";
+	}
+	
+	if ($^O eq "MSWin32")
+	{
+		print "nvram_usage_check.pl not support MSWin32!";
+		exit $ERR_OK;
+	}
+	
+	#generate full file path in normal path
+	$file_path_num = @file_path;
+	for($i = 0; $i < $file_path_num; $i++)
+	{
+		$file_path[$i] = catfile($cur_dir, $file_path[$i]);
+	}
+	
+	#find out all the LID definition file and store to @file_list
+	#nvram LIDs are defined in *_nvram_def.c / nvram_data_items.c / nvram_factory_config.c / nvram_ltable.c(nvram_gen_util.c is same with this)
+	#normal path
+	foreach(@file_path)
+	{
+		opendir my $dir, $_ or die "Error: NVRAM USAGE CHECK cannot open $_";
+		while(my $name = readdir $dir)
+		{
+			next if $name =~ /^\./; #skip file name begin with "."
+			if($name =~ /.+nvram_def.c$/)
+			{
+				$name = catfile($_, $name);
+				push(@file_list, $name);
+			}
+			elsif($name =~ /nvram_data_items.c$/)
+			{
+				$name = catfile($_, $name);
+				push(@file_list, $name);
+			}
+			elsif($name =~ /nvram_ltable.c$/)
+			{
+				$name = catfile($_, $name);
+				push(@file_list, $name);
+			}
+			elsif($name =~ /nvram_factory_config.c$/)
+			{
+				$name = catfile($_, $name);
+				push(@file_list, $name);
+			}
+		}
+	}
+	#print "@file_list\n";
+		
+	#find out all the LID name and store to @name_array
+	$file_list_num = @file_list;
+	if($file_list_num == 0)
+	{
+			print "Warning: Can not find at least 1 LID define file.\n";
+			exit $ERR_WARNING;
+	}
+	for($i = 0; $i < $file_list_num; $i++)
+	{
+		open LIDINFO, $file_list[$i] or die "Error: NVRAM USAGE CHECK cannot open $file_list[$i].\n";
+		while( <LIDINFO> )
+		{
+			while($_ =~ /\"([0-9|A-Z]{4})\"/g)
+			{
+				push(@name_array, $1);
+			}
+		}
+		close LIDINFO;
+		$name_num = @name_array; #get current LID name numbers
+		push(@group_end_index, $name_num);
+	}
+	#print "@name_array\n";
+	#print "group index: @group_end_index\n";
+	
+	#check whether exists duplicate LID name
+	#build error will happen only if there have duplicate LID name in different file
+	$name_num = @name_array;
+	$group_num = @group_end_index;
+	for($i = 0, $k = 0; $k < ($group_num - 1); $k++) #group count
+	{
+		for(; $i < $group_end_index[$k]; $i++) #LID names in first file
+		{
+			for($j = $group_end_index[$k]; $j < $name_num; $j++) #LID names in other files
+			{
+				if($name_array[$i] eq $name_array[$j])
+				{
+					#the first duplicate name is in $file_list[$k], this for loop is to find out the other file
+					for($t = 0; $t < $group_end_index[$group_num - 1]; $t++)
+					{
+						if($group_end_index[$t] > $j)
+						{
+							last;
+						}
+					}
+					print "Error: duplicate LID name \"$name_array[$i]\" in $file_list[$k] and $file_list[$t]\n";
+					$log_info .= "Error: duplicate LID name \"$name_array[$i]\" in $file_list[$k] and $file_list[$t]\n";
+					$exist_duplicate = 1;
+				}
+			}
+		}
+	}
+	
+	#print log to file
+	#open FILE_HANDLE, ">$log_out_file" or die "Error: NVRAM USAGE CHECK cannot open $log_out_file.\n";
+	#if($log_info ne "")
+	#{
+	#	print FILE_HANDLE $log_info;
+	#}
+	#close FILE_HANDLE;
+	
+	if($exist_duplicate eq 1)
+	{
+		exit $ERR_ERROR;
+	}
+	else
+	{
+		print "NVRAM USAGE CHECK: duplicate LID name check pass!\n";
+		exit $ERR_OK;
+	}
\ No newline at end of file
diff --git a/mcu/tools/NVRAMStatistic/nvram_vc_build.pl b/mcu/tools/NVRAMStatistic/nvram_vc_build.pl
new file mode 100644
index 0000000..b394612
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/nvram_vc_build.pl
@@ -0,0 +1,299 @@
+#!/usr/bin/perl -w

+

+# Author: Chenxiang Zhao

+# function: Create VC Debug enviornment of NvramAutoGen

+

+$customer_folder = "";

+$mmi_folder = "";

+$vc_build_dir = "vc_build";

+$is_vc_build_dir_exist = 1;

+$nvram_dsp_name = "nvram_auto_gen";

+$fsquota_dsp_name = "fs_quota";

+$nvram_dsw_name = $nvram_dsp_name;

+$compile_option = "";

+$include_path = "";

+

+

+$custom_option_pathname = "include\\custom_option.txt";

+$custom_include_pathname = "include\\custom_include.txt";

+

+#use this two func to init $customer_folder $mmi_folder

+#and parse the custom_option.txt and custom_include.txt,convert the

+#the defination of macro or inc to the format which VC knows.

+#after call, both $compile_option and $include_path are initialized. 

+parse_custom_option($custom_option_pathname);

+parse_custom_include($custom_include_pathname);

+

+$nvram_compile_option = $compile_option;

+$nvram_include_path = $include_path;

+

+$fsquota_compile_option = $compile_option;

+$fsquota_include_path = $include_path;

+

+$nvram_compile_option = $nvram_compile_option."/D \"NVRAM_AUTO_GEN\"\n";

+$nvram_include_path = $nvram_include_path."/I \"..\\include\"\n";

+

+$fsquota_compile_option = $fsquota_compile_option."/D \"BUILD_TIME_CHECK_GEN\"\n";

+$fsquota_include_path = $fsquota_include_path."/I \"..\\..\\..\\custom\\common\\\"\n";

+

+@compile_option_array = ($nvram_compile_option, $nvram_compile_option, $fsquota_compile_option);

+@include_path_array = ($nvram_include_path, $nvram_include_path, $fsquota_include_path);

+

+$nvram_src_list = "..\\src\\nvram_auto_gen.c\n";

+$nvram_src_list = $nvram_src_list."..\\src\\nvram_gen_util.c\n";

+$nvram_src_list = $nvram_src_list."..\\src\\nvram_white_list.c\n";

+$nvram_src_list = $nvram_src_list."..\\src\\operator_mmi_cache_wrapper.c\n";

+$nvram_src_list = $nvram_src_list."..\\..\\..\\custom\\common\\$mmi_folder\\common_mmi_cache_config.c\n";

+$nvram_src_list = $nvram_src_list."..\\..\\..\\custom\\app\\$customer_folder\\custom_mmi_cache_config.c\n";

+$nvram_src_list = $nvram_src_list."..\\..\\..\\custom\\common\\$mmi_folder\\nvram_common_config.c\n";

+$nvram_src_list = $nvram_src_list."..\\..\\..\\custom\\app\\$customer_folder\\nvram_user_config.c\n";

+$nvram_src_list = $nvram_src_list."..\\..\\..\\custom\\app\\$customer_folder\\nvram_cust_pack.c\n";

+$nvram_src_list = $nvram_src_list."..\\..\\..\\nvram\\src\\nvram_data_items.c\n";

+

+

+$fsquota_src_list = "..\\src\\fs_quota_entry_dump.c\n";

+

+#if add one new project, you need add two new var: xxx_dsp_name  xxx_src_list

+#and you should add them to the following two array respectively.

+@project_name_array = ($nvram_dsp_name, $fsquota_dsp_name);

+@project_src_array = ($nvram_src_list, $fsquota_src_list);

+

+#create vc build environment root dir

+if (!-e $vc_build_dir) {

+	$is_vc_build_dir_exist = 0;

+}

+else {

+	if (!-d $vc_build_dir) {

+		unlink $vc_build_dir || die "cannot delete file $vc_build_dir : $!";

+		$is_vc_build_dir_exist = 0;

+	}

+}

+

+if (!$is_vc_build_dir_exist) {

+	mkdir $vc_build_dir || die "cannot create dir $vc_build_dir : $!";

+}

+else {

+	chdir $vc_build_dir;

+	unlink <*.*>;

+	chdir "..\\";

+}

+

+#enter vc build dir

+chdir $vc_build_dir;

+create_vc_dsw($nvram_dsw_name, @project_name_array);

+

+

+for ($i = 0; $i <= $#project_name_array; $i++)

+{

+#uncomment this to support one project in individual folder

+=pod

+	if (!$is_vc_build_dir_exist) {

+		mkdir $project_name_array[$i] || die "cannot create dir $project_name_array[$i]";

+	}

+	else {

+		if (!-e $project_name_array[$i] || (-e $project_name_array[$i] && !-d $project_name_array[$i])) {

+			if (-e $project_name_array[$i]) {

+				unlink $project_name_array[$i] || die "cannot delete file $project_name_array[$i] : $!";

+			}

+			mkdir $project_name_array[$i] || die "cannot create dir $project_name_array[$i] : $!";

+		}

+	}

+	#enter each project folder

+	chdir $project_name_array[$i];

+=cut

+	create_vc_dsp($project_name_array[$i],

+		$compile_option_array[$i],

+		$include_path_array[$i],

+		$project_src_array[$i]);

+	#leave this project folder

+#	chdir "..\\";

+}

+

+#leave vc build dir

+chdir "..\\";

+

+exit(0);

+

+

+#create_vc_dsp($name, $compile_option, $include_path, $src_list) $src_list consists of xx.c\nxxx.c\nxx.c\n 

+sub create_vc_dsp {

+	open(dspFile, ">$_[0].dsp") || die "cannot open $_[0].dsp : $!";

+	print dspFile qq(# Microsoft Developer Studio Project File - Name="$_[0]" - Package Owner=<4>\n);

+	print dspFile qq(# Microsoft Developer Studio Generated Build File, Format Version 6.00\n);

+	print dspFile qq(# ** DO NOT EDIT **\n\n);

+	

+	print dspFile qq(# TARGTYPE "Win32 (x86) Console Application" 0x0103\n\n);

+	

+	print dspFile qq(CFG=$_[0] - Win32 Debug\n);

+	print dspFile qq(!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n);

+	print dspFile qq(!MESSAGE use the Export Makefile command and run\n);

+	print dspFile qq(!MESSAGE\n);

+	print dspFile qq(!MESSAGE NMAKE /f "$_[0].mak".\n);

+	print dspFile qq(!MESSAGE\n);	

+	print dspFile qq(!MESSAGE You can specify a configuration when running NMAKE\n);

+	print dspFile qq(!MESSAGE by defining the macro CFG on the command line. For example:\n);

+	print dspFile qq(!MESSAGE\n);

+	print dspFile qq(!MESSAGE NMAKE /f "$_[0].mak" CFG="$_[0] - Win32 Debug"\n);

+	print dspFile qq(!MESSAGE\n);

+	print dspFile qq(!MESSAGE Possible choices for configuration are:\n);

+	print dspFile qq(!MESSAGE\n);

+	print dspFile qq,!MESSAGE "$_[0] - Win32 Release" (based on "Win32 (x86) Console Application")\n,;

+	print dspFile qq,!MESSAGE "$_[0] - Win32 Debug" (based on "Win32 (x86) Console Application")\n,;

+	print dspFile qq(!MESSAGE\n\n);

+	print dspFile qq(# Begin Project\n);

+	print dspFile qq(# PROP AllowPerConfigDependencies 0\n);

+	print dspFile qq(# PROP Scc_ProjName ""\n);

+	print dspFile qq(# PROP Scc_LocalPath ""\n);

+	print dspFile qq(CPP=cl.exe\n);

+	print dspFile qq(RSC=rc.exe\n\n);

+	

+	print dspFile qq(!IF  "\$(CFG)" == "$_[0] - Win32 Release"\n\n);

+	

+	print dspFile qq(# PROP BASE Use_MFC 0\n);

+	print dspFile qq(# PROP BASE Use_Debug_Libraries 0\n);

+	print dspFile qq(# PROP BASE Output_Dir "..\\Release"\n);

+	print dspFile qq(# PROP BASE Intermediate_Dir "..\\Release"\n);

+	print dspFile qq(# PROP BASE Target_Dir ""\n);

+	print dspFile qq(# PROP Use_MFC 0\n);

+	print dspFile qq(# PROP Use_Debug_Libraries 0\n);

+	print dspFile qq(# PROP Output_Dir "..\\Release"\n);

+	print dspFile qq(# PROP Intermediate_Dir "Release"\n);

+	print dspFile qq(# PROP Target_Dir ""\n);

+	print dspFile qq(# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\n);

+	print dspFile qq(# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\n);

+	print dspFile qq(# ADD CPP @"$_[0].ini"\n);

+	print dspFile qq(# ADD BASE RSC /l 0x804 /d "NDEBUG"\n);

+	print dspFile qq(# ADD RSC /l 0x804 /d "NDEBUG"\n);

+	print dspFile qq(BSC32=bscmake.exe\n);

+	print dspFile qq(# ADD BASE BSC32 /nologo\n);

+	print dspFile qq(# ADD BSC32 /nologo\n);

+	print dspFile qq(LINK32=link.exe\n);

+	print dspFile qq(# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n);

+	print dspFile qq(# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n\n);

+	print dspFile qq(!ELSEIF  "\$(CFG)" == "$_[0] - Win32 Debug" \n\n);	

+	

+	print dspFile qq(# PROP BASE Use_MFC 0\n);

+	print dspFile qq(# PROP BASE Use_Debug_Libraries 1\n);

+	print dspFile qq(# PROP BASE Output_Dir "..\\debug"\n);

+	print dspFile qq(# PROP BASE Intermediate_Dir "..\\debug"\n);

+	print dspFile qq(# PROP BASE Target_Dir ""\n);

+	print dspFile qq(# PROP Use_MFC 0\n);

+	print dspFile qq(# PROP Use_Debug_Libraries 1\n);

+	print dspFile qq(# PROP Output_Dir "..\\debug"\n);

+	print dspFile qq(# PROP Intermediate_Dir "..\\debug"\n);

+	print dspFile qq(# PROP Target_Dir ""\n);

+	print dspFile qq(# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c\n);

+	print dspFile qq(# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c\n);

+	print dspFile qq(# ADD CPP @"$_[0].ini"\n);

+	print dspFile qq(# ADD BASE RSC /l 0x804 /d "_DEBUG"\n);

+	print dspFile qq(# ADD RSC /l 0x804 /d "_DEBUG"\n);

+	print dspFile qq(# ADD BSC32 /nologo\n);

+	print dspFile qq(LINK32=link.exe\n);

+	print dspFile qq(# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n);

+	print dspFile qq(# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n\n);

+	

+	print dspFile qq(!ENDIF\n\n);

+

+	print dspFile qq(# Begin Target\n\n);

+	

+	print dspFile qq(# Name "$_[0] - Win32 Release"\n);

+	print dspFile qq(# Name "$_[0] - Win32 Debug"\n);

+	my @src_array = split(/\n\s*/, $_[3]);

+	foreach $one_src(@src_array) {

+		print dspFile qq(# Begin Source File\n\n);

+		

+		print dspFile qq(SOURCE=$one_src\n);

+		print dspFile qq(# End Source File\n);	

+	}

+

+	print dspFile qq(# End Target\n);

+	print dspFile qq(# End Project\n);

+	#make project ini file

+	open(f_ini, ">$_[0].ini") || die "cannot create $_[0].ini or write it: $!";

+	print f_ini $_[1];

+	print f_ini $_[2];

+	close(f_ini);

+	close(dspFile);	

+}

+

+#create_vc_dsw($name, @project_name_array)

+sub create_vc_dsw {

+	my $dsw_file;

+

+	(my $name, my @dsp_array) = @_;

+	open($dsw_file, ">$name.dsw") || die "cannot open $name.dsw: $!";

+	print $dsw_file qq(Microsoft Developer Studio Workspace File, Format Version 6.00\n);

+	print $dsw_file qq(# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\n\n);

+	

+	print $dsw_file qq(###############################################################################\n\n);

+

+	for ($i = 0; $i <= $#dsp_array; $i++) {

+		print $dsw_file qq(Project: "$dsp_array[$i]"=.\\$dsp_array[$i].dsp - Package Owner=<4>\n\n);

+		print $dsw_file qq(Package=<5>\n);

+		print $dsw_file qq({{{\n);

+		print $dsw_file qq(}}}\n\n);

+		

+		print $dsw_file qq(Package=<4>\n);

+		print $dsw_file qq({{{\n);

+		print $dsw_file qq(}}}\n\n);

+		

+		print $dsw_file qq(###############################################################################\n\n);

+		

+	}

+	print $dsw_file qq(Global:\n\n);

+	print $dsw_file qq(Package=<5>\n);

+	print $dsw_file qq({{{\n);

+	print $dsw_file qq(}}}\n\n);

+	

+	print $dsw_file qq(Package=<3>\n);

+	print $dsw_file qq({{{\n);

+	print $dsw_file qq(}}}\n\n);

+	

+	print $dsw_file qq(###############################################################################\n\n\n);

+	close($dsw_file);

+}

+

+#parse_custom_option($filename)

+sub parse_custom_option {

+	open(f_custom_option, "<$_[0]") || die "cannot open $_[0]: $!";

+	my $first_line = <f_custom_option>;

+	chomp $first_line;

+	my @customer_folder_pair = split(/\s*=\s*/, $first_line);

+	$customer_folder = $customer_folder_pair[1];

+	my $second_line = <f_custom_option>;

+	chomp $second_line;

+	my @mmi_folder_pair = split(/\s*=\s*/, $second_line);

+	$mmi_folder = $mmi_folder_pair[1];

+	my $custom_option_line = "";

+	while (<f_custom_option>) {

+		$_ =~ s/\\/ /;

+		$_ =~ s/\n/ /;

+		$custom_option_line = $custom_option_line.$_;

+		

+	}

+	my @vc_custom_option;

+	@vc_custom_option = split(/\s*CUSTOM_OPTION\s*=\s*/, $custom_option_line);

+	$compile_option = $vc_custom_option[1];

+	$compile_option =~ s/\"\s+-D/\"\n-D/g;

+	$compile_option =~ s/-D /\/D /g;

+	$compile_option = $compile_option."\n";

+	$compile_option =~ s/\/D\s*\"__MTK_TARGET__\"\s*\n//;

+	close(f_custom_option);

+}

+

+#parse_custom_include($filename);

+sub parse_custom_include {

+	open(f_custom_include, "<$_[0]") || die "cannot open $_[0]: $!";

+	my $custom_include_line = "";

+	while (<f_custom_include>) {

+		$_ =~ s/\n/ /;

+		$custom_include_line = $custom_include_line.$_;

+	}

+	my @vc_custom_include;

+	@vc_custom_include = split(/\s*CUSTOM_INC\s*=\s*/, $custom_include_line);

+	$include_path = $vc_custom_include[1];

+	$include_path =~ s/\"\s+-I/\"\n-I/g;

+	$include_path =~ s/-I\s*/\/I /g;

+	$include_path = $include_path."\n";

+	close(f_custom_include);

+}

diff --git a/mcu/tools/NVRAMStatistic/src/Makefile b/mcu/tools/NVRAMStatistic/src/Makefile
new file mode 100644
index 0000000..b4d204f
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/src/Makefile
@@ -0,0 +1,266 @@
+

+.PHONY: nvram_auto_gen 

+

+modem_dir := ../../../custom/modem/common/ps

+nvram_dir := ../../../custom/service/nvram

+bsp_dir := ../../../custom/driver/common

+#mmi_dir := ../../../custom/common

+

+bsp_src := $(basename $(notdir $(wildcard $(bsp_dir)/*_nvram_def.c)))

+modem_src := $(basename $(notdir $(wildcard $(modem_dir)/*_nvram_def.c)))

+#mmi_src := $(basename $(notdir $(wildcard $(mmi_dir)/*_nvram_def.c)))

+#nvram_src := $(basename $(notdir $(wildcard $(nvram_dir)/*.c)))

+

+debug_path := $(subst \,/, $(NVRAM_DEBUG_PATH))

+

+include $(debug_path)/../include/custom_include.txt

+include $(debug_path)/../include/custom_option.txt

+

+bsp_obj := $(patsubst %, $(debug_path)/%.o, $(bsp_src))

+modem_obj := $(patsubst %, $(debug_path)/%.o, $(modem_src))

+mmi_obj := $(patsubst %, $(debug_path)/%.o, $(mmi_src))

+

+NVM_CUST_SRC = \

+BSP_LIST \

+MODEM_LIST \

+nvram_data_items.o \

+nvram_cust_pack.o \

+custom_nvram_sec.o \

+nvram_gen_util.o

+

+ifneq ($(filter "__MMI_FMI__", $(strip $(CUSTOM_OPTION))),)

+

+	NVM_CUST_SRC += nvram_common_config.o \

+                    nvram_user_config.o

+endif

+

+ifneq ($(words $(mmi_src)), 0)

+  NVM_CUST_SRC += MMI_LIST    

+endif

+

+

+#Vendor only can compile these files

+NVM_VENDOR_SRC = nvram_gen_util.o

+

+ifneq ($(filter "__MMI_FMI__", $(strip $(CUSTOM_OPTION))),)

+    NVM_VENDOR_SRC += nvram_user_config.o

+endif

+

+

+

+NVM_CORE_SRC = \

+nvram_factory_config.o

+

+NVM_GEN_SRC = \

+nvram_auto_gen.o

+

+NVM_LNK_CMD = \

+-Xlinker --script=nvram_auto_gen.txt -Xlinker --Map -Xlinker $(debug_path)/nvram_auto_gen.map

+

+NVM_GEN_OBJS = \

+$(debug_path)/nvram_auto_gen.o \

+$(debug_path)/nvram_gen_util.o \

+$(debug_path)/nvram_factory_config.o \

+$(debug_path)/nvram_data_items.o \

+$(debug_path)/nvram_cust_pack.o \

+$(debug_path)/custom_nvram_sec.o \

+$(debug_path)/fs_quota_entry_dump.o \

+$(modem_obj) \

+$(bsp_obj)

+

+ifneq ($(filter "__MMI_FMI__", $(strip $(CUSTOM_OPTION))),)

+    NVM_GEN_OBJS += $(debug_path)/nvram_user_config.o \

+                    $(debug_path)/nvram_common_config.o \

+                    $(mmi_obj)

+endif

+

+ifneq ($(filter "__FS_QM_SUPPORT__", $(strip $(CUSTOM_OPTION))),)

+    NVM_GEN_OBJS += $(debug_path)/fs_quota.o

+endif

+

+QUOTA_SRC = fs_quota_entry_dump.o

+

+ifneq ($(filter "__FS_QM_SUPPORT__", $(strip $(CUSTOM_OPTION))),)

+	QUOTA_SRC += fs_quota.o

+endif

+

+ifeq ($(strip $(LEVEL)), VENDOR) # vendor release

+	NVM_OPTION =  -fshort-enums  -D "NVRAM_AUTO_GEN" -D "__VENDOR_RELEASE__"

+else

+	NVM_OPTION =  -fshort-enums  -D "NVRAM_AUTO_GEN" 

+endif

+

+NVM_INC = -I "../include"

+

+QUOTA_OPTION =  -D "BUILD_TIME_CHECK_GEN" -D "GEN_FOR_PC"

+QUOTA_INC = -I "../../../custom/common/"

+

+

+#Using the folder from resource generator

+MTK_DEFS = \

+	-D "__MULTI_BIN_LOAD__" \

+	-D "__EXE_DLL__"

+

+

+

+############ MMI CACHE Makefile ####################################

+

+ifeq ($(strip $(MMI_FOLDER)), NEPTUNE_MMI) 

+	MMI_CACHE_GEN_CMD = \

+	$(debug_path)/nvram_gen_mmi_cache.o \

+	$(debug_path)/common_mmi_cache_config.o \

+	$(debug_path)/custom_mmi_cache_config.o 

+else

+	MMI_CACHE_GEN_CMD = \

+	$(debug_path)/nvram_gen_mmi_cache.o

+endif

+

+ifeq ($(strip $(MMI_FOLDER)), NEPTUNE_MMI) 

+	NVM_CACHE_OBJS = \

+	nvram_gen_mmi_cache.o \

+	common_mmi_cache_config.o \

+	custom_mmi_cache_config.o

+else

+	NVM_CACHE_OBJS = \

+	nvram_gen_mmi_cache.o

+endif

+

+.SUFFIXES: .o .cpp .c .txt

+

+############### mmi cache compiling ####################

+

+common_mmi_cache_config.o: ../../../custom/common/${MMI_FOLDER}/common_mmi_cache_config.c

+	gcc ${CUSTOM_OPTION} $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC) -w -c $< -MMD -MF $(debug_path)/$(basename $(@F)).d -o $(debug_path)/$@

+	echo "common_mmi_cache_config.o done"

+

+custom_mmi_cache_config.o: ../../../custom/app/$(strip $(CUSTOM_FOLDER))/custom_mmi_cache_config.c

+	gcc ${CUSTOM_OPTION} $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC) -w -c $< -MMD -MF $(debug_path)/$(basename $(@F)).d -o $(debug_path)/$@

+	echo "custom_mmi_cache_config.o done"

+

+nvram_gen_mmi_cache.o: nvram_gen_mmi_cache.c

+	gcc ${CUSTOM_OPTION} $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC) -w -c $< -MMD -MF $(debug_path)/$(basename $(@F)).d -o $(debug_path)/$@

+	echo "nvram_gen_mmi_cache.o done"

+

+ifeq ($(strip $(LEVEL)), LEVEL2_OBJ)

+  mmi_cache_gen: $(NVM_CACHE_OBJS)

+	gcc -o $(debug_path)/mmi_cache_gen $(MMI_CACHE_GEN_CMD)

+	echo "build level2_obj nvram_auto_gen done" 

+else

+  ifeq ($(strip $(LEVEL)), VENDOR) # vendor release

+    mmi_cache_gen: 

+		gcc -o $(debug_path)/mmi_cache_gen $(MMI_CACHE_GEN_CMD)

+		echo "build vendor mmi_cache_gen done"

+  else 

+    mmi_cache_gen: $(NVM_CACHE_OBJS)

+		gcc -o $(debug_path)/mmi_cache_gen $(MMI_CACHE_GEN_CMD)

+		echo "build mmi_cache_gen done"

+  endif

+endif

+

+

+############ nvram_auto_gen compiling ####################################

+

+MMI_LIST:

+#	echo "Building MMI: $(notdir $(mmi_src))"

+#	for f in $(mmi_src) ; do \

+#	  echo Compile $(mmi_dir)/$$f.c; \

+#	  gcc ${CUSTOM_OPTION} $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC)  -w -c $(mmi_dir)/$$f.c -MMD -MF $(debug_path)/$$f.d -o $(debug_path)/$$f.o; \

+#	done

+

+BSP_LIST:

+	echo "Building BSP: $(notdir $(bsp_src))"

+	for f in $(bsp_src) ; do \

+	  echo Compile $(bsp_dir)/$$f.c; \

+	  gcc ${CUSTOM_OPTION} $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC)  -w -c $(bsp_dir)/$$f.c -MMD -MF $(debug_path)/$$f.d -o $(debug_path)/$$f.o; \

+	done

+

+	

+

+MODEM_LIST:

+	echo "Building MODEM: $(notdir $(modem_src))"

+	for f in $(modem_src) ; do \

+	  echo Compile $(modem_dir)/$$f.c; \

+	  gcc ${CUSTOM_OPTION} $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC)  -w -c $(modem_dir)/$$f.c -MMD -MF $(debug_path)/$$f.d -o $(debug_path)/$$f.o; \

+	done

+

+#NVRAM_LIST: 

+#	echo "Building NVRAM: $(notdir $(nvram_src))"

+#	for f in $(nvram_src) ; do \

+#	  echo Compile $(nvram_dir)/$$f.c; \

+#	  gcc ${CUSTOM_OPTION} $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC)  -w -c $(nvram_dir)/$$f.c -MMD -MF $(debug_path)/$$f.d -o $(debug_path)/$$f.o; \

+#	done

+

+

+nvram_data_items.o: ../../../custom/service/nvram/nvram_data_items.c

+	echo "Compile ../../../custom/service/nvram/nvram_data_items.c"

+	gcc ${CUSTOM_OPTION} $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC) -w -c $< -MMD -MF $(debug_path)/$(basename $(@F)).d -o $(debug_path)/$@

+

+nvram_cust_pack.o: ../../../custom/service/nvram/nvram_cust_pack.c

+	echo "Compile ../../../custom/service/nvram/nvram_cust_pack.c"

+	gcc ${CUSTOM_OPTION} $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC) -w -c $< -MMD -MF $(debug_path)/$(basename $(@F)).d -o $(debug_path)/$@

+

+custom_nvram_sec.o: ../../../custom/service/nvram/custom_nvram_sec.c

+	echo "Compile ../../../custom/service/nvram/custom_nvram_sec.c"

+	gcc ${CUSTOM_OPTION} $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC) -w -c $< -MMD -MF $(debug_path)/$(basename $(@F)).d -o $(debug_path)/$@

+

+

+nvram_factory_config.o: ../../../service/nvram/src/nvram_factory_config.c

+	gcc ${CUSTOM_OPTION} $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC) -w -c $< -MMD -MF $(debug_path)/$(basename $(@F)).d -o $(debug_path)/$@

+	echo "nvram_factory_config.o done"

+

+ifneq ($(filter "__MMI_FMI__", $(strip $(CUSTOM_OPTION))),)

+nvram_user_config.o: ../../../custom/app/$(strip $(CUSTOM_FOLDER))/nvram_user_config.c

+	gcc ${CUSTOM_OPTION} $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC) -w -c $< -MMD -MF $(debug_path)/$(basename $(@F)).d -o $(debug_path)/$@

+	echo "nvram_user_config.o done"

+

+nvram_common_config.o: ../../../custom/common/${MMI_FOLDER}/nvram_common_config.c

+	gcc ${CUSTOM_OPTION} $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC) -w -c $< -MMD -MF $(debug_path)/$(basename $(@F)).d -o $(debug_path)/$@

+	echo "nvram_common_config.o done"

+endif

+

+fs_quota_entry_dump.o: fs_quota_entry_dump.c 

+	gcc ${CUSTOM_OPTION} $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC)  -w -c $< -MMD -MF $(debug_path)/$(basename $(@F)).d -o $(debug_path)/$@

+

+

+fs_quota.o: ../../../custom/common/fs_quota.c

+	gcc ${CUSTOM_OPTION} $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC) -w -c $< -MMD -MF $(debug_path)/$(basename $(@F)).d -o $(debug_path)/$@

+

+nvram_auto_gen.o: nvram_auto_gen.c

+	echo "Compile nvram_auto_gen.c"

+	gcc ${CUSTOM_OPTION} $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC)  -w -c $< -MMD -MF $(debug_path)/$(basename $(@F)).d -o $(debug_path)/$@

+	echo "nvram_auto_gen.o done"

+

+nvram_gen_util.o: nvram_gen_util.c

+	gcc ${CUSTOM_OPTION} $(NVM_OPTION) ${CUSTOM_INC} $(NVM_INC)  -w -c $< -MMD -MF $(debug_path)/$(basename $(@F)).d -o $(debug_path)/$@

+	echo "nvram_gen_util.o done"

+

+ifneq ($(filter "NVRAM_NOT_PRESENT", $(strip $(CUSTOM_OPTION))),)

+    nvram_auto_gen: nvram_auto_gen.o $(QUOTA_SRC)

+	gcc -o $(debug_path)/nvram_auto_gen $(debug_path)/nvram_auto_gen.o

+	echo "build nvram_auto_gen done"

+else

+ifeq ($(strip $(LEVEL)), LEVEL2_OBJ)

+  ifneq ($(strip $(CUSTOM_RELEASE)), FALSE)

+        nvram_auto_gen: $(NVM_GEN_SRC) $(NVM_CUST_SRC) $(QUOTA_SRC)

+  else

+        nvram_auto_gen: $(NVM_GEN_SRC) $(NVM_CUST_SRC) $(NVM_CORE_SRC) $(QUOTA_SRC)

+  endif

+	gcc -o $(debug_path)/nvram_auto_gen $(debug_path)/$(NVM_GEN_OBJS)

+	echo "build level2_obj nvram_auto_gen done"

+else

+  ifeq ($(strip $(LEVEL)), VENDOR) # vendor release

+    nvram_auto_gen: $(NVM_GEN_SRC) $(NVM_VENDOR_SRC) $(QUOTA_SRC)

+		gcc $(NVM_LNK_CMD) -o $(debug_path)/nvram_auto_gen $(NVM_GEN_OBJS)

+		echo "build vendor nvram_auto_gen done"

+  else 

+    nvram_auto_gen: $(NVM_GEN_SRC) $(NVM_CUST_SRC) $(NVM_CORE_SRC) $(QUOTA_SRC)

+#    nvram_auto_gen: nvram_auto_gen.o nvram_gen_util.o

+		gcc $(NVM_LNK_CMD) -o $(debug_path)/nvram_auto_gen $(NVM_GEN_OBJS)

+#		ld  nvram_auto_gen.txt -o $(debug_path)/nvram_auto_gen $(NVM_GEN_OBJS) -Map $(debug_path)/nvram_auto_gen.map 

+#		gcc -o $(debug_path)/nvram_auto_gen $(NVM_GEN_OBJS)

+		echo "build nvram_auto_gen done"

+  endif

+endif

+endif

+############### fs quota compiling ####################

+

diff --git a/mcu/tools/NVRAMStatistic/src/ckSySDrv_flash_cfg_preproc.c b/mcu/tools/NVRAMStatistic/src/ckSySDrv_flash_cfg_preproc.c
new file mode 100644
index 0000000..3d3d740
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/src/ckSySDrv_flash_cfg_preproc.c
@@ -0,0 +1,301 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2008
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ *   ckSysDrv_flash_cfg_preproc.c
+ *
+ * Project:
+ * --------
+ *   Maui_Software
+ *
+ * Description:
+ * ------------
+ *   To calculate System Drive Disk Space accuratly in build time utilities ckSysDrv.pl ,
+ *   flash configuration parameters is required by C pre-processor with this temporal C source code.
+ *
+ * Author:
+ * -------
+ *
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+
+#include "flash_opt.h"
+#include "custom_flash.c"  // for including flash configurations, e.g., RegionInfo...
+#include "custom_nvram_int_config.h"
+
+/*--------------------------------------------------
+ * ckSysDrv Switch On/Off
+ *--------------------------------------------------*/
+
+#if defined(__CCCIFS_SUPPORT__) || defined(__RAMDISK__)
+    int cksysdrv_enabled = 0;   // ckSysDrv is disabled on Smart Phone project
+#else
+    int cksysdrv_enabled = 1;
+#endif
+
+/*--------------------------------------------------
+ * Auto adjust On/Off
+ *--------------------------------------------------*/
+#if defined(__FS_AUTO_CONFIG_SUPPORT__)
+   int fs_auto_config_support = 1;
+#else
+   int fs_auto_config_support = 0;
+#endif /* __FS_AUTO_CONFIG_SUPPORT__ */
+
+/*--------------------------------------------------
+ * Get system drive information by compile options
+ *--------------------------------------------------*/
+
+#if defined(APP_STORAGE_IN_SYS_DRV)
+        int app_storage_in_sys_drv = 1;
+#else
+        int app_storage_in_sys_drv = 0;
+#endif
+    
+
+#if defined(__EMMC_BOOTING__)
+
+int system_drive_size      = EMMC_FS_SYSTEM_DRIVE_SIZE;
+int system_drive_location  = 3;  // EMMC
+
+int allocated_fat_space    = EMMC_FS_SIZE / 512;
+int partition_sectors      = 0;
+int flash_base_address     = EMMC_FS_BASE_ADDRESS / 512;
+
+#elif defined(_NAND_FLASH_BOOTING_) || defined(__FS_SYSDRV_ON_NAND__)  // system drive on NAND
+
+int allocated_fat_space    = NAND_ALLOCATED_FAT_SPACE;
+int partition_sectors      = NAND_PARTITION_SECTORS;
+int flash_base_address     = NAND_FLASH_BASE_ADDRESS;
+int system_drive_location  = 1;  // NAND
+
+#else /* !_NAND_FLASH_BOOTING_ && !__FS_SYSDRV_ON_NAND__ */          // system drive on NOR
+
+int allocated_fat_space    = NOR_ALLOCATED_FAT_SPACE;
+int partition_sectors      = NOR_PARTITION_SECTORS;
+int flash_base_address     = NOR_FLASH_BASE_ADDRESS;
+int system_drive_location  = 2;  // NOR
+
+#endif /* _NAND_FLASH_BOOTING_ || __FS_SYSDRV_ON_NAND__ */
+
+/*----------------------------------------------------------
+ * File system format information for FlashTool Auto Format
+ *----------------------------------------------------------*/
+
+#if defined(__EMMC_BOOTING__)
+
+    int fs_nand_base_address   = 0;
+    int fs_nand_length         = 0;
+    int fs_nor_base_address    = 0;
+    int fs_nor_length          = 0;
+    int fs_emmc_base_address   = EMMC_FS_BASE_ADDRESS / 512;
+    
+    #if (EMMC_FS_SIZE == 0)
+        int fs_emmc_length         = 0xFFFFFFFF;
+    #else
+        int fs_emmc_length         = EMMC_FS_SIZE / 512;
+    #endif
+
+#else   // !__EMMC_BOOTING__
+
+    #if defined(_NAND_FLASH_BOOTING_) || defined(__FS_SYSDRV_ON_NAND__) || (defined(__FOTA_DM__) && defined(__UP_PKG_ON_NAND__) && defined(NAND_SUPPORT))
+
+        int fs_nand_base_address   = NAND_FLASH_BASE_ADDRESS;
+        int fs_nand_length         = NAND_ALLOCATED_FAT_SPACE;
+
+    #endif /* _NAND_FLASH_BOOTING_ || __FS_SYSDRV_ON_NAND__ && (__FOTA_DM__ && __UP_PKG_ON_NAND__ && NAND_SUPPORT) */
+
+    #if !defined(_NAND_FLASH_BOOTING_) && !defined(__FS_SYSDRV_ON_NAND__)
+
+        int fs_nor_base_address    = NOR_FLASH_BASE_ADDRESS;
+
+        /*
+         * If __NOR_SUPPORT_RAW_DISK__ is defined, there are at most 2 additional disks behind system and user drives.
+         * We must ensure that these additional disks could be auto-formatted by FlashTool.
+         */
+
+        #ifndef __NOR_SUPPORT_RAW_DISK__
+        int fs_nor_length          = NOR_ALLOCATED_FAT_SPACE;
+        #else // __NOR_SUPPORT_RAW_DISK__
+
+        #if (2 == NOR_BOOTING_NOR_DISK_NUM)
+        int fs_nor_length          = NOR_BOOTING_NOR_DISK1_BASE_ADDRESS + NOR_BOOTING_NOR_DISK1_SIZE - NOR_FLASH_BASE_ADDRESS;
+        #elif (1 == NOR_BOOTING_NOR_DISK_NUM)
+        int fs_nor_length          = NOR_BOOTING_NOR_DISK0_BASE_ADDRESS + NOR_BOOTING_NOR_DISK0_SIZE - NOR_FLASH_BASE_ADDRESS;
+        #else
+        int fs_nor_length          = NOR_ALLOCATED_FAT_SPACE;
+        #endif
+        #endif // !__NOR_SUPPORT_RAW_DISK__
+
+    #endif /* !_NAND_FLASH_BOOTING_ && !__FS_SYSDRV_ON_NAND__ */
+
+#endif // __EMMC_BOOTING__
+
+
+/*--------------------------------------------------
+ * File system information
+ *--------------------------------------------------*/
+
+#if !defined(__LOW_COST_SUPPORT_ULC__)
+   int fs_low_cost_support = 0;
+#else
+   int fs_low_cost_support = 1;
+#endif /* __LOW_COST_SUPPORT_ULC__ */
+
+/*--------------------------------------------------
+ * Flash geometry
+ *--------------------------------------------------*/
+
+#if defined(NAND_TOTAL_SIZE) && defined(NAND_BLOCK_SIZE)
+   int nand_total_size = NAND_TOTAL_SIZE;    // (MB)
+   int nand_block_size = NAND_BLOCK_SIZE;    // (KB)
+#else
+   int nand_total_size = 0;
+   int nand_block_size = 0;
+#endif
+
+/*--------------------------------------------------
+ * NAND FDM information
+ *--------------------------------------------------*/
+
+#if defined(__NAND_FDM_50__)
+   int nand_fdm_version = 5;
+#else
+   int nand_fdm_version = 4;
+#endif
+
+/*--------------------------------------------------
+ * NOR FDM information
+ *--------------------------------------------------*/
+
+// NRVAM max number of record sectors
+int nvram_custom_cfg_max_record_sector_num = NVRAM_CUSTOM_CFG_MAX_RECORD_SECTOR_NUM;
+
+// reserved blocks in NOR FDM
+   float nor_reserved_blocks = NOR_SYSTEM_DRIVE_RESERVED_BLOCK;
+   int nor_single_bank_support = 0;
+
+// FDM sector size
+#if defined(__INTEL_SIBLEY__)
+   int nor_sector_size = 1024;
+#else
+   int nor_sector_size = 512;
+#endif /* __INTEL_SIBLEY__ */
+
diff --git a/mcu/tools/NVRAMStatistic/src/fs_quota_entry_dump.c b/mcu/tools/NVRAMStatistic/src/fs_quota_entry_dump.c
new file mode 100644
index 0000000..0dad3be
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/src/fs_quota_entry_dump.c
@@ -0,0 +1,257 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2006
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ * fs_quota_entry_dump.c
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   This file is intends for dump the fs quota setting
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+
+/***************************************************************************** 
+* Include
+*****************************************************************************/
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#ifdef __FS_QM_SUPPORT__
+
+#include "flash_opt.h"
+#include "kal_public_defs.h"
+#include "fs_gprot.h"
+
+/***************************************************************************** 
+* Define
+* Aim to pass compile, dummy function or gloabl variable here
+*****************************************************************************/
+FS_QuotaStruct *gFS_IntQuotaSet;
+UINT        FS_MAX_QSET;
+
+/***************************************************************************** 
+* Local Variable
+*****************************************************************************/
+extern void nvram_gen_create_file(FILE **file_handle, char *file_path, char *file_name);
+
+/*****************************************************************************
+* FUNCTION
+*  main
+* DESCRIPTION
+*  main function.
+* PARAMETERS
+*  None
+* RETURNS
+*  None
+*****************************************************************************/
+void FS_QuotaInit(FS_QuotaStruct *quota, kal_uint32 total)
+{
+    
+    printf("FS_QuotaInit: %X, %d\n", quota, total);
+    gFS_IntQuotaSet = quota;
+    FS_MAX_QSET = total;
+}
+
+int nvram_gen_fs_quota(char *pathname)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    FILE* outputLog;
+    int   i;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+
+    #ifndef __PUBLIC_DRIVE_AVAILABLE__
+        #ifdef MMS_SUPPORT
+	        #ifdef MMS_IN_LARGE_STORAGE
+	            fprintf(stderr, "Please set APP_STORAGE_IN_SYS_DRV as TRUE for those projects which disable phone drive!\n");        
+	            exit(2);
+	        #endif
+        #endif
+    #endif
+
+    nvram_gen_create_file(&outputLog, pathname, "cksysdrv/~fs_quota_usage.log");
+    
+    fprintf(outputLog, "gFS_ExtQuotaSet[]\n");
+    fprintf(outputLog, "-----------------------------------------------------------\n");
+
+    for (i = 0; i < FS_MAX_QSET ; i++)
+    {
+       printf("{ %-20s , %5d , %10d , 0x%x , 0x%x },\n",
+                 gFS_IntQuotaSet[i].Path,
+                 gFS_IntQuotaSet[i].Priority,
+                 gFS_IntQuotaSet[i].Qmin,
+                 gFS_IntQuotaSet[i].Qmax,
+                 gFS_IntQuotaSet[i].Uint);
+
+       fprintf(outputLog, "{ %-20s , %5d , %10d , 0x%x , 0x%x },\n",
+                gFS_IntQuotaSet[i].Path,
+                gFS_IntQuotaSet[i].Priority,
+                gFS_IntQuotaSet[i].Qmin,
+                gFS_IntQuotaSet[i].Qmax,
+                gFS_IntQuotaSet[i].Uint);
+    }
+    printf("output finish\n");
+    fclose(outputLog);
+    printf("close successfully\n");
+}
+
+#else /* __FS_QM_SUPPORT__ */
+int nvram_gen_fs_quota(char *pathname)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    FILE* outputLog;
+    int   i;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    nvram_gen_create_file(&outputLog, pathname, "cksysdrv/~fs_quota_usage.log");
+    
+    fprintf(outputLog, "__FS_QM_SUPPORT__ Off\n");
+
+    fclose(outputLog);
+    return 0;
+}
+#endif
diff --git a/mcu/tools/NVRAMStatistic/src/md5_dgst.c b/mcu/tools/NVRAMStatistic/src/md5_dgst.c
new file mode 100644
index 0000000..fbede67
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/src/md5_dgst.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "md5_locl.h"
+#include <openssl/opensslv.h>
+
+/*
+ * Implemented from RFC1321 The MD5 Message-Digest Algorithm
+ */
+
+#define INIT_DATA_A (unsigned long)0x67452301L
+#define INIT_DATA_B (unsigned long)0xefcdab89L
+#define INIT_DATA_C (unsigned long)0x98badcfeL
+#define INIT_DATA_D (unsigned long)0x10325476L
+
+int MD5_Init(MD5_CTX *c)
+{
+    memset(c, 0, sizeof(*c));
+    c->A = INIT_DATA_A;
+    c->B = INIT_DATA_B;
+    c->C = INIT_DATA_C;
+    c->D = INIT_DATA_D;
+    return 1;
+}
+
+#ifndef md5_block_data_order
+# ifdef X
+#  undef X
+# endif
+void md5_block_data_order(MD5_CTX *c, const void *data_, size_t num)
+{
+    const unsigned char *data = data_;
+    register unsigned MD32_REG_T A, B, C, D, l;
+# ifndef MD32_XARRAY
+    /* See comment in crypto/sha/sha_locl.h for details. */
+    unsigned MD32_REG_T XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7,
+        XX8, XX9, XX10, XX11, XX12, XX13, XX14, XX15;
+#  define X(i)   XX##i
+# else
+    MD5_LONG XX[MD5_LBLOCK];
+#  define X(i)   XX[i]
+# endif
+
+    A = c->A;
+    B = c->B;
+    C = c->C;
+    D = c->D;
+
+    for (; num--;) {
+        (void)HOST_c2l(data, l);
+        X(0) = l;
+        (void)HOST_c2l(data, l);
+        X(1) = l;
+        /* Round 0 */
+        R0(A, B, C, D, X(0), 7, 0xd76aa478L);
+        (void)HOST_c2l(data, l);
+        X(2) = l;
+        R0(D, A, B, C, X(1), 12, 0xe8c7b756L);
+        (void)HOST_c2l(data, l);
+        X(3) = l;
+        R0(C, D, A, B, X(2), 17, 0x242070dbL);
+        (void)HOST_c2l(data, l);
+        X(4) = l;
+        R0(B, C, D, A, X(3), 22, 0xc1bdceeeL);
+        (void)HOST_c2l(data, l);
+        X(5) = l;
+        R0(A, B, C, D, X(4), 7, 0xf57c0fafL);
+        (void)HOST_c2l(data, l);
+        X(6) = l;
+        R0(D, A, B, C, X(5), 12, 0x4787c62aL);
+        (void)HOST_c2l(data, l);
+        X(7) = l;
+        R0(C, D, A, B, X(6), 17, 0xa8304613L);
+        (void)HOST_c2l(data, l);
+        X(8) = l;
+        R0(B, C, D, A, X(7), 22, 0xfd469501L);
+        (void)HOST_c2l(data, l);
+        X(9) = l;
+        R0(A, B, C, D, X(8), 7, 0x698098d8L);
+        (void)HOST_c2l(data, l);
+        X(10) = l;
+        R0(D, A, B, C, X(9), 12, 0x8b44f7afL);
+        (void)HOST_c2l(data, l);
+        X(11) = l;
+        R0(C, D, A, B, X(10), 17, 0xffff5bb1L);
+        (void)HOST_c2l(data, l);
+        X(12) = l;
+        R0(B, C, D, A, X(11), 22, 0x895cd7beL);
+        (void)HOST_c2l(data, l);
+        X(13) = l;
+        R0(A, B, C, D, X(12), 7, 0x6b901122L);
+        (void)HOST_c2l(data, l);
+        X(14) = l;
+        R0(D, A, B, C, X(13), 12, 0xfd987193L);
+        (void)HOST_c2l(data, l);
+        X(15) = l;
+        R0(C, D, A, B, X(14), 17, 0xa679438eL);
+        R0(B, C, D, A, X(15), 22, 0x49b40821L);
+        /* Round 1 */
+        R1(A, B, C, D, X(1), 5, 0xf61e2562L);
+        R1(D, A, B, C, X(6), 9, 0xc040b340L);
+        R1(C, D, A, B, X(11), 14, 0x265e5a51L);
+        R1(B, C, D, A, X(0), 20, 0xe9b6c7aaL);
+        R1(A, B, C, D, X(5), 5, 0xd62f105dL);
+        R1(D, A, B, C, X(10), 9, 0x02441453L);
+        R1(C, D, A, B, X(15), 14, 0xd8a1e681L);
+        R1(B, C, D, A, X(4), 20, 0xe7d3fbc8L);
+        R1(A, B, C, D, X(9), 5, 0x21e1cde6L);
+        R1(D, A, B, C, X(14), 9, 0xc33707d6L);
+        R1(C, D, A, B, X(3), 14, 0xf4d50d87L);
+        R1(B, C, D, A, X(8), 20, 0x455a14edL);
+        R1(A, B, C, D, X(13), 5, 0xa9e3e905L);
+        R1(D, A, B, C, X(2), 9, 0xfcefa3f8L);
+        R1(C, D, A, B, X(7), 14, 0x676f02d9L);
+        R1(B, C, D, A, X(12), 20, 0x8d2a4c8aL);
+        /* Round 2 */
+        R2(A, B, C, D, X(5), 4, 0xfffa3942L);
+        R2(D, A, B, C, X(8), 11, 0x8771f681L);
+        R2(C, D, A, B, X(11), 16, 0x6d9d6122L);
+        R2(B, C, D, A, X(14), 23, 0xfde5380cL);
+        R2(A, B, C, D, X(1), 4, 0xa4beea44L);
+        R2(D, A, B, C, X(4), 11, 0x4bdecfa9L);
+        R2(C, D, A, B, X(7), 16, 0xf6bb4b60L);
+        R2(B, C, D, A, X(10), 23, 0xbebfbc70L);
+        R2(A, B, C, D, X(13), 4, 0x289b7ec6L);
+        R2(D, A, B, C, X(0), 11, 0xeaa127faL);
+        R2(C, D, A, B, X(3), 16, 0xd4ef3085L);
+        R2(B, C, D, A, X(6), 23, 0x04881d05L);
+        R2(A, B, C, D, X(9), 4, 0xd9d4d039L);
+        R2(D, A, B, C, X(12), 11, 0xe6db99e5L);
+        R2(C, D, A, B, X(15), 16, 0x1fa27cf8L);
+        R2(B, C, D, A, X(2), 23, 0xc4ac5665L);
+        /* Round 3 */
+        R3(A, B, C, D, X(0), 6, 0xf4292244L);
+        R3(D, A, B, C, X(7), 10, 0x432aff97L);
+        R3(C, D, A, B, X(14), 15, 0xab9423a7L);
+        R3(B, C, D, A, X(5), 21, 0xfc93a039L);
+        R3(A, B, C, D, X(12), 6, 0x655b59c3L);
+        R3(D, A, B, C, X(3), 10, 0x8f0ccc92L);
+        R3(C, D, A, B, X(10), 15, 0xffeff47dL);
+        R3(B, C, D, A, X(1), 21, 0x85845dd1L);
+        R3(A, B, C, D, X(8), 6, 0x6fa87e4fL);
+        R3(D, A, B, C, X(15), 10, 0xfe2ce6e0L);
+        R3(C, D, A, B, X(6), 15, 0xa3014314L);
+        R3(B, C, D, A, X(13), 21, 0x4e0811a1L);
+        R3(A, B, C, D, X(4), 6, 0xf7537e82L);
+        R3(D, A, B, C, X(11), 10, 0xbd3af235L);
+        R3(C, D, A, B, X(2), 15, 0x2ad7d2bbL);
+        R3(B, C, D, A, X(9), 21, 0xeb86d391L);
+
+        A = c->A += A;
+        B = c->B += B;
+        C = c->C += C;
+        D = c->D += D;
+    }
+}
+#endif
diff --git a/mcu/tools/NVRAMStatistic/src/med_mem_info.c b/mcu/tools/NVRAMStatistic/src/med_mem_info.c
new file mode 100644
index 0000000..f7849da
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/src/med_mem_info.c
@@ -0,0 +1,169 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2006
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ * fs_quota_entry_dump.c
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   This file is intends for dump med memory run-time info
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+
+/***************************************************************************** 
+* Include
+*****************************************************************************/
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#ifndef MED_NOT_PRESENT
+#ifdef __inline
+    #undef __inline
+#endif /* __inline */
+
+#ifdef __GNUC__
+    #define __inline static inline
+#else
+    #define __inline static
+#endif
+
+//MSBB remove #include "kal_non_specific_general_types.h"
+#include "med_global.h"
+
+/***************************************************************************** 
+* Define
+* Aim to pass compile, dummy function or gloabl variable here
+*****************************************************************************/
+kal_int32 system_boot_mode;
+/***************************************************************************** 
+* Local Variable
+*****************************************************************************/
+#ifdef _STACK_LTLCOM_H
+void free_int_ilm(ilm_struct *ilm_ptr, kal_char* file_name, kal_uint32 line)
+{   return;
+}
+#endif
+
+/*****************************************************************************
+* FUNCTION
+*  main
+* DESCRIPTION
+*  main function.
+* PARAMETERS
+*  None
+* RETURNS
+*  None
+*****************************************************************************/
+int main()
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    FILE* outputLog;
+    int   i;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+
+    outputLog = fopen("..\\..\\..\\~med_mem_info.log","w+");
+    
+    fprintf(outputLog, "***********************************************************************\n");
+    fprintf(outputLog, "Med Memory Information\n");
+    fprintf(outputLog, "***********************************************************************\n");
+    fprintf(outputLog, "sizeof(aud_ext_mem_union) == %d\n", sizeof(aud_ext_mem_union));
+    fprintf(outputLog, "sizeof(med_ext_mem_union) == %d\n", sizeof(med_ext_mem_union));
+    fprintf(outputLog, "sizeof(med_int_mem_union) == %d\n", sizeof(med_int_mem_union));
+    fclose(outputLog);
+    return 0;
+}
+
+#else /* MED_NOT_PRESENT */
+int main()
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    FILE* outputLog;
+    int   i;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    outputLog = fopen("..\\..\\..\\~med_mem_info.log","w+");
+    
+    fprintf(outputLog, "MED_NOT_PRESENT\n");
+
+    fclose(outputLog);
+    return 0;
+}
+#endif
diff --git a/mcu/tools/NVRAMStatistic/src/nvram_auto_gen.c b/mcu/tools/NVRAMStatistic/src/nvram_auto_gen.c
new file mode 100644
index 0000000..96f6bfb
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/src/nvram_auto_gen.c
@@ -0,0 +1,3008 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2006
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ * nvram_auto_gen.c
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   This file is intends for generating NVRAM information.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+
+#ifndef NVRAM_NOT_PRESENT
+/*****************************************************************************
+* Include
+*****************************************************************************/
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/io.h>
+#include <errno.h>
+
+#include "nvram_auto_gen.h"
+#include "custom_nvram_config.h"
+#include "custom_nvram_sec.h"   // add ,get checksum type/size.
+#include "nvram_editor_data_item.h"
+#include "nvram_group_editor.h" //add for break group files from header file
+#include "nvram_data_items.h"
+#include "nvram_hash_check.h"
+#include "nvram_group_def.h" //add for break group files from header file
+
+#if defined(__MMI_FMI__)
+#include "nvram_user_defs.h"
+
+#endif
+
+#ifndef __VENDOR_RELEASE__
+#include "custom_nvram_sec.h"
+#endif
+
+#ifdef __FS_RAMDISK__
+#include "driver/storage/ramdisk_gprot.h"
+#endif
+
+/* Add pseudo merge headfile */
+#include "nvram_pseudo_merge.h"
+
+#include "nvram_internal.h"
+
+#include "nvram_white_list.h"
+/*
+ * Variables
+ */
+extern kal_uint32 custpack_total_to_verify;
+
+extern nvram_ltable_entry_struct *logical_data_item_table;
+extern kal_uint32 nvram_gen_total_lid;
+
+#ifdef __NVRAM_OTP__
+extern kal_uint32 otp_total_to_verify;
+extern kal_uint32 otp_size_to_verify;
+#endif
+
+extern kal_uint32 secupack_total_to_verify;
+extern kal_uint32 secupack_size_to_verify;
+extern kal_uint16 secupack_idx;
+
+#ifdef __NVRAM_VENDOR_SUPPORT__
+extern kal_uint32 nvram_vendor_reserve_size;
+#endif
+
+#if defined(__NVRAM_SECURE_DATA_STORAGE__)
+extern kal_uint32 sds_total_to_verify;
+extern kal_uint32 sds_size_to_verify;
+#endif
+
+
+/* system cache configure*/
+extern nvram_sys_cache_entry nvram_sys_cache[];
+
+#ifdef __NV_CHKSUM_ENHANCE__
+/* CUSTOM_CHK_ALGO_CONFIG configure*/
+extern nvram_checksum_config CUSTOM_CHK_ALGO_CONFIG;
+#endif
+
+#define NVRAM_AUTO_GEN_BYTE       1
+#define NVRAM_AUTO_GEN_SHORT      2
+#define NVRAM_AUTO_GEN_INTEGER    4
+
+#define fprintf_blank_line(x) fprintf (x,"\n")
+
+static FILE* logOfSize;
+static FILE* logOfTools;
+#ifdef __NVRAM_PSEUDO_MERGE__
+static FILE* logOfSize_Package;
+#endif
+
+/* used to package samll lid */
+#ifdef __NVRAM_PSEUDO_MERGE__
+static int nvram_auto_package_num;
+static int nvram_auto_pack_file_offset = NVRAM_FILE_HEAD_SIZE;
+#endif
+
+static int nvram_restore_cache_system[NVRAM_APP_TOTAL][NVRAM_SYS_CACHE_MAX];
+static int nvram_restore_system_idx[NVRAM_APP_TOTAL];
+static char **nvram_restore_lid_enum_array;
+static char **nvram_restore_lid_description_point;
+static int nvram_max_length_lid_str;
+static int nvram_total_num_restore_lid;
+static char base_path[NVRAM_AUTO_GEN_MAX_PATH_LEN];
+
+kal_uint32 nvram_long_length;
+kal_uint32 nvram_ptr_length;
+kal_uint32 nvram_padding_length;
+kal_uint32 nvram_ltable_entry_length;
+
+/*****************************************************************************
+* FUNCTION
+*   nvram_gen_check_sys_cache
+* DESCRIPTION
+*   output system cache default value to nvram_mmi_cust_pack.h
+* PARAMETERS
+*
+* RETURNS
+*   none
+*****************************************************************************/
+void nvram_gen_check_sys_cache(void)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    int loop_idx;
+    int byte_idx;
+    int bit_idx;
+    kal_uint8 *data = &(nvram_sys_cache[NVRAM_SYS_CACHE_BEGIN-1].value1);
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    for (loop_idx = NVRAM_SYS_CACHE_BEGIN; loop_idx < NVRAM_SYS_CACHE_MAX; loop_idx++)
+    {
+        if(nvram_sys_cache[loop_idx].id != loop_idx+1)
+        {
+            fprintf(stderr, "ERROR: please check nvram_data_items.h and nvram_data_items.c: # sys cache enum (%d) and # sys cache entry must sync.", loop_idx);
+            exit(3);
+        }
+
+        byte_idx = loop_idx / 8;
+        bit_idx = loop_idx % 8;
+        if (nvram_sys_cache[loop_idx].restore)
+        {
+            data[byte_idx] |= (0x01 << bit_idx);
+            nvram_restore_cache_system[nvram_sys_cache[loop_idx].app_id][nvram_restore_system_idx[nvram_sys_cache[loop_idx].app_id]] = loop_idx;
+            nvram_restore_system_idx[nvram_sys_cache[loop_idx].app_id]++;
+        }
+    }
+}
+
+
+void nvram_gen_sys_cache_default(FILE *fh_file)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    int loop_idx;
+    int loop_value_idx;
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    /* step 1: generate restore mark */
+    fprintf(fh_file, "kal_uint8 const NVRAM_EF_SYS_CACHE_OCTET_DEFAULT[NVRAM_EF_SYS_CACHE_OCTET_TOTAL * NVRAM_EF_SYS_CACHE_OCTET_SIZE] =\n");
+    fprintf(fh_file, "{\n");
+
+    /* step 2: generate default value */
+    for (loop_idx = NVRAM_SYS_CACHE_BEGIN; loop_idx < NVRAM_SYS_CACHE_MAX; loop_idx++)
+    {
+        for (loop_value_idx = 0; loop_value_idx < sizeof(double); loop_value_idx++)
+        {
+            fprintf(fh_file,"    0x%02X, ",
+                    *(kal_uint8 *)(&(nvram_sys_cache[loop_idx - 1].value1) + loop_value_idx));
+        }
+        fprintf(fh_file, "\n");
+    }
+
+    /* step 3: generate last */
+    for (loop_value_idx = 0; loop_value_idx < sizeof(double) - 1; loop_value_idx++)
+    {
+        fprintf(fh_file, "    0x%02X, ",
+                *(&(nvram_sys_cache[NVRAM_SYS_CACHE_MAX - 1].value1) + loop_value_idx));
+    }
+
+    fprintf(fh_file, "    0x%02X ", nvram_sys_cache[NVRAM_SYS_CACHE_MAX - 1].value8);
+
+    fprintf(fh_file, "\n");
+
+    fprintf(fh_file, "};\n");
+}
+
+
+void nvram_gen_sys_cache_res_func(FILE *fh_file)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    int loop_app_idx;
+    int loop_app_cache_idx;
+    int loop_value_idx;
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    fprintf(fh_file, NVRAM_RESTORE_FUNCTION_NAME, "system");
+
+    for (loop_app_idx = 0; loop_app_idx < NVRAM_APP_TOTAL; loop_app_idx++)
+    {
+        if (nvram_restore_system_idx[loop_app_idx])
+        {
+            fprintf(fh_file,"        case %s :\n", nvram_sys_cache[nvram_restore_cache_system[loop_app_idx][0]].app_id_str);
+        }
+        else
+        {
+            continue;
+        }
+
+        for (loop_app_cache_idx = 0; loop_app_cache_idx < nvram_restore_system_idx[loop_app_idx]; loop_app_cache_idx++)
+        {
+            /*-----------------------------------------------------------
+            fprintf(fh_restore_dom_h, R_F_DOM_CONTENT_ID,
+                        nvram_mmi_cache_double[nvram_restore_cache_double[loop_app_idx][loop_app_cache_idx]].id_str);
+
+            for (loop_space = 0; loop_space < nvram_max_length_double_id_str - strlen(nvram_mmi_cache_double[nvram_restore_cache_double[loop_app_idx][loop_app_cache_idx]].id_str); loop_space++)
+            {
+                fprintf(fh_restore_dom_h, " ");
+            }
+
+            fprintf(fh_restore_dom_h, R_F_DOM_CONTENT_DESCRIPTION,
+                        nvram_mmi_cache_double[nvram_restore_cache_double[loop_app_idx][loop_app_cache_idx]].discription);
+            -----------------------------------------------------------*/
+
+            fprintf(fh_file, NVRAM_AUTO_GEN_COMMENT, nvram_sys_cache[nvram_restore_cache_system[loop_app_idx][loop_app_cache_idx]].description);
+
+            for (loop_value_idx = 0; loop_value_idx < sizeof(double); loop_value_idx++)
+            {
+                fprintf(fh_file,"            buffer[%d * (%s - 1) + %d] = 0x%02X;\n",
+                        sizeof(double),
+                        nvram_sys_cache[nvram_restore_cache_system[loop_app_idx][loop_app_cache_idx]].id_str,
+                        loop_value_idx,
+                        *(&(nvram_sys_cache[nvram_restore_cache_system[loop_app_idx][loop_app_cache_idx]].value1) + loop_value_idx));
+            }
+        }
+
+        fprintf(fh_file,NVRAM_RESTORE_FUNCTION_BREAK);
+    }
+    fprintf(fh_file, NVRAM_RESTORE_FUNCTION_TAIL);
+}
+
+
+/*****************************************************************************
+* FUNCTION
+*  nvram_gen_lid_size
+* DESCRIPTION
+*  Output NVRAM LID size Information.
+* PARAMETERS
+*  None
+* RETURNS
+*  None
+*****************************************************************************/
+char s[512];
+char indirect_end_symbol[40];
+
+void nvram_gen_ltable_list(void)
+{
+
+    typedef enum
+    {
+      INDIRECT_PROCESS_YET,
+      INDIRECT_PROCESS_ING,
+      INDIRECT_PROCESS_FINISHED
+    }indirect_process_enum;
+    
+    FILE* tbl_list = NULL;
+    FILE* map_file = NULL;
+    char pathname[NVRAM_AUTO_GEN_MAX_PATH_LEN*2];
+    indirect_process_enum process_indirect_init = INDIRECT_PROCESS_YET;
+
+
+    sprintf(pathname,"%s/nvram_auto_gen/nvram_ltable_list.h",base_path);
+    printf("%s\n", pathname);
+    tbl_list= fopen(pathname,"w+");
+    if (tbl_list == NULL)
+    {
+        fprintf(stderr, "error: %s - nvram_ltable_list.h\n", strerror(errno));
+        return;
+    }
+
+    sprintf(pathname,"%s/nvram_auto_gen/debug/nvram_auto_gen.map",base_path);
+    printf("%s\n", pathname);
+    map_file = fopen(pathname,"r");
+
+    if (map_file == NULL)
+    {
+        fprintf(stderr, "error: %s - nvram_auto_gen.map\n", strerror(errno));
+        fclose(tbl_list);
+        return;
+    }
+
+
+
+    while (fgets(s, 512, map_file) > 0)
+    {
+        char *ptr;
+        char *brk;
+        s[511] = 0;
+        
+        brk = strchr(s, '\n');
+
+        if (brk)
+            *brk = 0;
+
+        if (process_indirect_init == INDIRECT_PROCESS_YET)
+        {
+            if ((ptr = strstr(s, "logical_data_item_table_")))
+            {
+        
+                fprintf(tbl_list, "#pragma comment(linker, \"/INCLUDE:_%s\")\n", ptr);
+            }
+        
+            if (strstr(s, "*(_indirect_init)"))
+            {
+                process_indirect_init = INDIRECT_PROCESS_ING;
+                fgets(s, 512, map_file); /* skip one line */
+                s[511] = 0;
+        
+                if (strstr(s, indirect_end_symbol))
+                {
+                    process_indirect_init = INDIRECT_PROCESS_FINISHED;
+                    break;
+                }
+            }
+        }
+    else if (process_indirect_init == INDIRECT_PROCESS_ING)
+    {
+    
+        if (strstr(s, indirect_end_symbol))
+        {
+            process_indirect_init = INDIRECT_PROCESS_FINISHED;
+            break;
+        }
+    
+        ptr = strrchr(s, ' ') + 1;
+        printf("%s\n", ptr);
+        
+        if (!strstr(ptr, "./build/"))
+        {
+            fprintf(tbl_list, "#pragma comment(linker, \"/INCLUDE:_%s\")\n", ptr);                
+        }
+    }
+
+    }
+
+    fclose(map_file);   
+    fclose(tbl_list);
+
+}
+
+#ifdef __NV_CHKSUM_ENHANCE__
+kal_uint32 get_checksum_size(nvram_ltable_entry_struct* ldi)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    kal_uint32 nvram_checksum_size = NVRAM_CHKSUM_SIZE;
+    
+    
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    if(NVRAM_IS_ATTR_CHKSUM_ENHANC_ALGRTHM(ldi->attr))
+    {
+        if(CUSTOM_CHK_ALGO_CONFIG.enhance_algo_type == NVRAM_MD5)
+        {
+            nvram_checksum_size = NVRAM_CHKSUM_SIZE;
+        }
+        else
+        {
+            nvram_checksum_size = CUSTOM_CHK_ALGO_CONFIG.enhance_algo_size;
+        }
+    }
+    else
+    {
+        if(CUSTOM_CHK_ALGO_CONFIG.default_algo_type == NVRAM_MD5)
+        {
+            nvram_checksum_size = NVRAM_CHKSUM_SIZE;
+        }
+        else
+        {
+            nvram_checksum_size = CUSTOM_CHK_ALGO_CONFIG.default_algo_size;
+        }
+    }
+    
+    return nvram_checksum_size;
+}
+
+/*****************************************************************************
+* FUNCTION
+*  nvram_gen_array
+* DESCRIPTION
+*  Output formatted arrays to custom_nvram_secro, i.e. 16 bytes/line
+* PARAMETERS
+*  None
+* RETURNS
+*  None
+*****************************************************************************/
+void nvram_gen_chk_algo_config(FILE* handle)
+{
+    fprintf(handle, "\n       %d, ", CUSTOM_CHK_ALGO_CONFIG.enhance_algo_size);
+    switch(CUSTOM_CHK_ALGO_CONFIG.enhance_algo_type)
+    {
+        case NVRAM_HMAC_SHA256:
+            fprintf(handle, "NVRAM_HMAC_SHA256, ");
+            break;
+        case NVRAM_MD5:
+            fprintf(handle, "NVRAM_MD5, ");
+            break;
+        default:
+            break;
+    }
+    fprintf(handle, "%d, ", CUSTOM_CHK_ALGO_CONFIG.default_algo_size);
+    switch(CUSTOM_CHK_ALGO_CONFIG.default_algo_type)
+    {
+        case NVRAM_HMAC_SHA256:
+            fprintf(handle, "NVRAM_HMAC_SHA256");
+            break;
+        case NVRAM_MD5:
+            fprintf(handle, "NVRAM_MD5");
+            break;
+        default:
+            break;
+    }
+}
+
+/*****************************************************************************
+ * FUNCTION
+ *  cache_info_table_generator
+ * DESCRIPTION
+ *  Generate cache info table
+ * PARAMETERS
+ *  
+ * RETURNS
+ *  
+ *****************************************************************************/
+void chksum_algo_config_generator(char *base_path)
+{
+    /*******************************************/
+    kal_uint32 i = 0, tb_size;
+	
+    char chksum_algo_config_file_path[NVRAM_AUTO_GEN_MAX_PATH_LEN];
+	char chksum_algo_config_file_name[] = "nvram_chksum_algo_config.c";
+    FILE *fp;
+
+    sprintf(chksum_algo_config_file_path, "%s/nvram_auto_gen/%s", base_path, chksum_algo_config_file_name);
+
+	fp = fopen(chksum_algo_config_file_path, "w");
+	fprintf(fp, COPYRIGHTS_HEADER, chksum_algo_config_file_name);
+    fprintf(fp, "#include \"custom_nvram_sec.h\"\n");
+	fprintf(fp, "\n");
+    #if defined (__NVRAM_UT_TEST__)
+    fprintf(fp, "\nnvram_checksum_config NVRAM_CHK_CONFIG = ");
+    #else
+    fprintf(fp, "\nconst nvram_checksum_config NVRAM_CHK_CONFIG = ");
+    #endif
+    fprintf(fp, "\n    {");
+    nvram_gen_chk_algo_config(fp);
+    fprintf(fp, "\n    };");
+
+	fclose(fp);
+}
+
+#endif
+
+void nvram_gen_lid_size(void)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+#ifdef __NVRAM_PSEUDO_MERGE__
+    kal_uint16 fake_lid;
+    int sum = 0;
+#endif
+    kal_uint32 i,j;
+    char pathname[NVRAM_AUTO_GEN_MAX_PATH_LEN*2];
+    kal_uint32 estimate_size = 0;
+    kal_uint32 estimate_fs_size = 0;
+    kal_uint32 bin_region_size = 0;
+    kal_uint32 protect_size = 0;
+    kal_uint32 remainLen = 0;
+    kal_uint32 nvram_checksum_size = 0;
+
+    #define FS_PAGE_SIZE    4096
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+
+   
+    /* Gen information for tools */
+    sprintf(pathname, "%s/nvram_auto_gen/~nvram_lid_information.log", base_path);
+    logOfTools = fopen(pathname,"w+");
+    if (logOfTools == NULL)
+    {
+        fprintf(stderr, "error: %s - ~nvram_lid_information.log\n", strerror(errno));
+    }
+    else
+    {
+        fprintf(logOfTools,"----------------------------------------------------------------------------------------------------------------------------------------------\n");
+        fprintf(logOfTools,"----------------------------------------------------------------------------------------------------------------------------------------------\n");
+        fprintf(logOfTools,"%4s    %55s    %10s    %10s    %11s  %10s   %10s\n","LID","LID(String)","Filename","Verno","Description", "Category", "Attribute");
+        fprintf(logOfTools,"----------------------------------------------------------------------------------------------------------------------------------------------\n");
+    } /* end for tools */
+
+    sprintf(pathname, "%s/nvram_auto_gen/~nvram_lid_size.log", base_path);
+    logOfSize = fopen(pathname,"w+");
+    if (logOfSize == NULL)
+    {
+        fprintf(stderr, "error: %s - ~nvram_lid_size.log\n", strerror(errno));
+    }
+    else
+    {
+        kal_uint32 onefilesize = 0;
+        kal_uint32 onefilefssize = 0;
+        nvram_ltable_entry_struct *ldi;
+
+        fprintf(logOfSize, "00000       long:%d,char*:%d,padding:%d                     NVRAM_PADDING_TEST\n", nvram_long_length, nvram_ptr_length, (nvram_padding_length / 3));
+        fprintf(logOfSize, "--------------------------------------------------------------------------\n");
+
+        #ifdef __NVRAM_PSEUDO_MERGE__
+        sprintf(pathname, "%s/nvram_auto_gen/nvram_lid_size_merge.log", base_path);
+        logOfSize_Package = fopen(pathname,"w+");
+        if (logOfSize_Package == NULL)
+        {
+            fprintf(stderr, "error: %s - nvram_lid_size_merge.log\n", strerror(errno));
+        }
+        else
+        {
+            fprintf(logOfSize_Package, "%4s   %10s    %10s    %10s    %10s    %10s    %10s\n",
+                    "ldi->LID", "fileprefix", "onefilesize", "oneLIDsize", "single_num", "single_offset", "file_size");
+        }
+
+        #endif
+
+        nvram_restore_lid_enum_array = malloc(sizeof(char *) * nvram_gen_total_lid);
+        nvram_restore_lid_description_point = malloc(sizeof(char *) * nvram_gen_total_lid);
+
+        
+        for (i = 0;i < nvram_gen_total_lid; i++)
+        {
+            ldi = &logical_data_item_table[i];
+
+            if (ldi == NULL ||
+                (ldi->LID == 0 && ldi->size == 0 && ldi->total_records == 0))
+            {
+                continue;   /* invalid LID */
+            }
+        #ifdef __NVRAM_PSEUDO_MERGE__
+            sum ++;
+        #endif
+            /* Output data item size */
+
+            #ifdef __NV_CHKSUM_ENHANCE__
+            nvram_checksum_size = get_checksum_size(ldi); // get nvram_checksum_size , read CUSTOM_CHK_ALGO_CONFIG.
+            #else
+            nvram_checksum_size = NVRAM_CHKSUM_SIZE;
+            #endif
+
+            if(ldi->attr & NVRAM_ATTR_CONFIDENTIAL
+                #ifdef __NVRAM_BIND_TO_CHIP_CIPHER__ //if HW encrypt is enable
+                || ldi->attr & NVRAM_ATTR_MSP
+                #endif
+              )
+            {
+                remainLen = NVRAM_MSP_ALIGNMENT_REMAINDER(ldi->size + nvram_checksum_size);
+                onefilesize = (ldi->size + nvram_checksum_size + remainLen)*ldi->total_records + NVRAM_LDI_HEADER_SIZE;
+            }
+            else
+            {
+                onefilesize = (ldi->size + nvram_checksum_size) * ldi->total_records + NVRAM_LDI_HEADER_SIZE;
+            }
+            onefilefssize = (onefilesize+FS_PAGE_SIZE-1)/FS_PAGE_SIZE*FS_PAGE_SIZE; //align to FS_PAGE_SIZE
+
+            if(onefilesize)
+            {
+            /* Record data item will be restored (begin) */
+                if (NVRAM_IS_CATEGORY_FACTORY_RESET(ldi->category))
+                {
+                    if (strlen(ldi->str_LID) > nvram_max_length_lid_str)
+                    {
+                        nvram_max_length_lid_str = strlen(ldi->str_LID);
+                    }
+                    nvram_restore_lid_enum_array[nvram_total_num_restore_lid] = ldi->str_LID;
+                    nvram_restore_lid_description_point[nvram_total_num_restore_lid] = ldi->description;
+                    nvram_total_num_restore_lid++;
+                }
+            /* Record data item will be restored (end) */
+            #ifdef __NVRAM_PSEUDO_MERGE__
+                if (NVRAM_IS_ATTR_PACKAGE(ldi->attr))
+                {
+                    /* Gen information for tools */
+                    if (logOfTools)
+                    {
+                        fprintf(logOfTools,"%4d    %55s    %10s    %10s    %11s    0x%08x  0x%08x\n",ldi->LID,ldi->str_LID,"PACK","LID",ldi->description, ldi->category, ldi->attr);
+                    }
+                    /* end */
+
+                    nvram_auto_package_num++;
+                    {
+                        fprintf(logOfSize_Package, "%40s", ldi->description);
+                        ldi->description = nvram_auto_pack_file_offset;
+                        nvram_auto_pack_file_offset += onefilesize;
+                        fprintf(logOfSize_Package, "%4d    %10s    %10d    %10d    %10d    %10d    %10d\n",
+                                ldi->LID, ldi->fileprefix, onefilesize, ldi->size, nvram_auto_package_num, (kal_int32)(ldi->description), nvram_auto_pack_file_offset);
+                    }
+
+                    fprintf(logOfSize, "%4d%10d%60s%20s\n", ldi->LID, 0, ldi->str_LID, NVRAM_IS_CATEGORY_CUSTPACK(ldi->category)?"CUSTPACK":"");
+
+                    continue;   /* already calculate in package file */
+                }
+            #endif
+                fprintf(logOfSize, "%4d%10d%60s%20s\n", ldi->LID, onefilesize, ldi->str_LID, NVRAM_IS_CATEGORY_CUSTPACK(ldi->category)?"CUSTPACK":"");
+                estimate_size += onefilesize;
+                estimate_fs_size += onefilefssize;
+
+                if (NVRAM_IS_ATTR_MULTIPLE(ldi->attr))
+                {
+                    fprintf(logOfSize, "%4d%10d%60s%20s\n", ldi->LID, onefilesize, ldi->str_LID, NVRAM_IS_CATEGORY_CUSTPACK(ldi->category)?"CUSTPACK":"");
+                    estimate_size += onefilesize;
+                    estimate_fs_size += onefilefssize;
+                }
+
+                if(NVRAM_IS_CATEGORY_IN_BIN_REGION(ldi->category))
+                {
+                    bin_region_size += onefilefssize;
+                    if (NVRAM_IS_ATTR_MULTIPLE(ldi->attr))
+                    {
+                        bin_region_size += onefilefssize;
+                    }
+                }
+
+                if(!NVRAM_IS_CATEGORY_FACTORY_RESET(ldi->category))
+                {
+                    protect_size += onefilefssize;
+                }
+
+                /* Gen information for tools */
+                if (logOfTools)
+                {
+                    fprintf(logOfTools,"%4d    %55s    %10s    %10s    %11s    0x%08x  0x%08x\n",ldi->LID,ldi->str_LID,ldi->fileprefix,ldi->fileverno,ldi->description, ldi->category, ldi->attr);
+                }
+                /* end */
+            }
+        }
+
+    #ifdef __NVRAM_VENDOR_SUPPORT__
+        fprintf(logOfSize,
+                "%4d%10d%60s\n",
+                nvram_gen_total_lid,
+                nvram_vendor_reserve_size,
+                "NVRAM_EF_VENDOR_REMAIN_SPACE_LID"
+                );
+    #endif /* __NVRAM_VENDOR_SUPPORT__ */
+
+    #ifdef __NVRAM_PSEUDO_MERGE__
+        fake_lid = nvram_gen_total_lid;
+    #ifdef __NVRAM_VENDOR_SUPPORT__
+        fake_lid += 1;
+    #endif
+        fprintf(logOfSize, "%4d%10d%40s\n", fake_lid, nvram_auto_pack_file_offset, "Package file size");
+        /* LID information nvram_auto_package_num */
+        fprintf(logOfSize, "%4d%10d%40s\n", fake_lid + 1, nvram_auto_package_num * (sizeof(LID_info_struct) + 2), "Info file A");
+        fprintf(logOfSize, "%4d%10d%40s\n", fake_lid + 2, nvram_auto_package_num * (sizeof(LID_info_struct) + 2), "Info file B");
+        /* extra cluster is need, for temp file, package file, truncate file */
+        fprintf(logOfSize, "%4d%10d%40s\n", fake_lid + 3, 3 * 512,"Extra size");
+       /***
+        * fprintf(logOfSize,"sum: %4d   nvram_auto_package_num = %4d\n",sum,nvram_auto_package_num);
+        */
+    #endif /* __NVRAM_PSEUDO_MERGE__ */
+
+        fprintf(logOfSize, "--------------------------------------------------------------------------\n");
+
+        #ifdef __NVRAM_COMPRESS_SUPPORT__
+        fprintf(logOfSize, "NVRAM_COMPRESS=1\n");
+        #else
+        fprintf(logOfSize, "NVRAM_COMPRESS=0\n");
+        #endif
+        fprintf(logOfSize, "NVRAM_ESTIMATE_SIZE=%d\n", estimate_size);
+        fprintf(logOfSize, "NVRAM_ESTIMATE_FS_SIZE=%d\n", estimate_fs_size);
+        fprintf(logOfSize, "bin_region_size=%d\n", bin_region_size);
+        fprintf(logOfSize, "protect_size=%d\n", protect_size);
+        #ifdef __FS_RAMDISK__
+        fprintf(logOfSize, "RAMDISK_SIZE=%d\n", RAM_FS_SIZE);
+        #endif
+
+        fclose(logOfSize);
+    #ifdef __NVRAM_PSEUDO_MERGE__
+        fclose(logOfSize_Package);
+    #endif
+    }
+
+    #ifdef __NV_CHKSUM_ENHANCE__
+    /* Gen information for tools */
+    if (logOfTools)
+    {
+        fprintf(logOfTools,"--------------------------------------------------------------------------------------------\n");
+        fprintf(logOfTools, "enhance_algo_size=%d\n", CUSTOM_CHK_ALGO_CONFIG.enhance_algo_size);
+        fprintf(logOfTools, "enhance_algo_type=%d\n", CUSTOM_CHK_ALGO_CONFIG.enhance_algo_type);
+        fprintf(logOfTools, "default_algo_size=%d\n", CUSTOM_CHK_ALGO_CONFIG.default_algo_size);
+        fprintf(logOfTools, "default_algo_type=%d\n", CUSTOM_CHK_ALGO_CONFIG.default_algo_type);
+        fclose(logOfTools);
+    }
+    #endif
+    /* end */
+
+    for (i = 0;i < nvram_gen_total_lid; i++)
+    {
+        nvram_ltable_entry_struct *ldi1, *ldi2;
+
+        ldi1 = &logical_data_item_table[i];
+
+        if (ldi1 == NULL || (ldi1->LID == 0 && ldi1->size == 0 && ldi1->total_records == 0))
+        {
+            continue;   /* invalid LID */
+        }
+
+        if (strcasecmp(ldi1->fileprefix, "") == 0)
+        {
+            fprintf(stderr, "error: fileprefix of %s = %d cannot be NULL!\n", ldi1->str_LID, ldi1->LID);
+            exit(NVRAM_EXIT_CODE_ERROR);
+        }
+        if (strlen(ldi1->fileprefix) != FILE_PREFIX_LEN)
+        {
+            fprintf(stderr, "error: fileprefix length of %s is invalid!\n", ldi1->str_LID);
+            exit(NVRAM_EXIT_CODE_ERROR);
+        }
+        if (strlen(ldi1->fileverno) != FILE_VERNO_LEN)
+        {
+            fprintf(stderr, "error: fileverno length of %s is invalid!\n", ldi1->str_LID);
+            exit(NVRAM_EXIT_CODE_ERROR);
+        }       
+
+        for (j = i + 1 ;j < nvram_gen_total_lid; j++)
+        {
+            ldi2 = &logical_data_item_table[j];
+
+            if (ldi2 == NULL || (ldi2->LID == 0 && ldi2->size == 0 && ldi2->total_records == 0))
+            {
+                continue;   /* invalid LID */
+            }
+            if (strcasecmp(ldi1->fileprefix, ldi2->fileprefix) == 0)
+            {
+                fprintf(stderr, "error: duplicated fileprefix and fileverno %s %s of %s and %s\n", ldi1->fileprefix, ldi1->fileverno, ldi1->str_LID, ldi2->str_LID);
+                exit(NVRAM_EXIT_CODE_ERROR);
+            }
+        }
+   
+    }
+
+#ifdef __FS_RAMDISK__
+    if(estimate_fs_size > RAM_FS_SIZE)
+    {
+        fprintf(stderr, "error: RAMDISK size is not enough.\n");
+        fprintf(stderr, "error: NVRAM_ESTIMATE_FS_SIZE=%d\n", estimate_fs_size);
+        fprintf(stderr, "error: RAMDISK_SIZE=%d\n", RAM_FS_SIZE);
+
+        exit(NVRAM_EXIT_CODE_ERROR);
+    }
+#endif    
+}
+
+
+/*****************************************************************************
+* FUNCTION
+*  nvram_gen_statistic
+* DESCRIPTION
+*  Output nvram_lid_statistic.h
+* PARAMETERS
+*  None
+* RETURNS
+*  None
+*****************************************************************************/
+void nvram_gen_statistic(void)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    kal_uint32   error = 0;
+    FILE* outputHeader;
+    kal_uint8    sys_str[2048];
+    char pathname[NVRAM_AUTO_GEN_MAX_PATH_LEN*2];
+    char pathnameOrg[NVRAM_AUTO_GEN_MAX_PATH_LEN*2];
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    sprintf(pathname, "%s/nvram_auto_gen/nvram_lid_statistics_bak.h", base_path);
+    sprintf(pathnameOrg, "%s/nvram_auto_gen/nvram_lid_statistics.h", base_path);
+    outputHeader = fopen(pathname,"w+");
+    if (outputHeader == NULL)
+    {
+        fprintf(stderr, "error: %s - %s\n",strerror(errno) ,pathname);
+    }
+    else
+    {
+
+        fprintf(outputHeader, COPYRIGHTS_HEADER, "nvram_lid_statistics_bak.h");
+
+        fprintf(outputHeader, "#ifndef NVRAM_LID_STATISTIC_H\n#define NVRAM_LID_STATISTIC_H\n");
+
+    #ifdef __NVRAM_OTP__
+        fprintf(outputHeader, "#define NVRAM_OTP_SIZE    %d\n", otp_size_to_verify);
+        fprintf(outputHeader, "#define NVRAM_OTP_TOTAL   %d\n", otp_total_to_verify);
+    #endif
+
+        fprintf(outputHeader, "#define NVRAM_CUSTPACK_TOTAL  %d\n", custpack_total_to_verify);
+
+        fprintf(outputHeader, "#define NVRAM_SECUPACK_SIZE  %d\n", secupack_size_to_verify);
+        fprintf(outputHeader, "#define NVRAM_SECUPACK_TOTAL  %d\n", secupack_total_to_verify);
+
+    #if defined(__NVRAM_SECURE_DATA_STORAGE__)
+        fprintf(outputHeader, "#define NVRAM_SDS_TOTAL  %d\n", sds_total_to_verify);
+        fprintf(outputHeader, "#define NVRAM_SDS_SIZE  %d\n", sds_size_to_verify);
+    #endif
+
+    #ifdef __NVRAM_PSEUDO_MERGE__
+        fprintf_blank_line(outputHeader);
+        fprintf(outputHeader, "#ifdef __NVRAM_PSEUDO_MERGE__\n");
+        fprintf(outputHeader, "#define NVRAM_PACKAGE_LID_NUM     %d\n", nvram_auto_package_num);
+        fprintf(outputHeader, "#define NVRAM_PACKAGE_LID_SIZE    %d\n", nvram_auto_pack_file_offset);
+        fprintf(outputHeader, "#endif /* __NVRAM_PSEUDO_MERGE__ */\n");
+    #endif
+
+        fprintf(outputHeader,"\n#endif /* NVRAM_LID_STATISTIC_H */\n\n");
+        fclose(outputHeader);
+
+#if 0
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+#endif        
+    }
+}
+
+
+/*****************************************************************************
+* FUNCTION
+*  nvram_gen_array
+* DESCRIPTION
+*  Output formatted arrays to custom_nvram_secro, i.e. 16 bytes/line
+* PARAMETERS
+*  None
+* RETURNS
+*  None
+*****************************************************************************/
+void nvram_gen_array(FILE* handle, kal_char* indent, kal_uint8 type, kal_uint32 max_size, kal_uint8 *array, kal_bool calc_cksum, kal_bool last_block)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    kal_uint32 i;
+    kal_uint8 byte_chksum[2] = {0};
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+
+    /* We only support checksum on NVRAM_AUTO_GEN_BYTE */
+
+    for (i = 0; i < max_size; i += type)
+    {
+        if (calc_cksum && type == NVRAM_AUTO_GEN_BYTE)
+        {
+            if (i & 0x1)
+            {
+                byte_chksum[1] += array[i];
+            }
+            else
+            {
+                byte_chksum[0] += array[i];
+            }
+        }
+
+        if (i % 16 == 0)
+        {
+            fprintf(handle, "\n%s", indent);
+        }
+
+        switch (type)
+        {
+            case NVRAM_AUTO_GEN_INTEGER:
+                fprintf(handle, "0x%02X%02X%02X%02X", array[i + 3], array[i + 2], array[i + 1], array[i]);
+                break;
+            case NVRAM_AUTO_GEN_SHORT:
+                fprintf(handle, "0x%02X%02X", array[i + 1], array[i]);
+                break;
+            case NVRAM_AUTO_GEN_BYTE:
+            default:
+                fprintf(handle, "0x%02X", array[i]);
+                break;
+        }
+
+        if (i == max_size - type)
+        {
+            if (calc_cksum && type == NVRAM_AUTO_GEN_BYTE)
+                fprintf(handle, ",\n%s/* check sum */\n%s0x%02x, 0x%02x", indent, indent, byte_chksum[0], byte_chksum[1]);
+
+            if (!last_block)
+            {
+                fprintf(handle, ", ");
+            }
+        }
+        else
+        {
+            fprintf(handle, ", ");
+        }
+    }
+
+
+}
+
+#ifndef __VENDOR_RELEASE__
+/*****************************************************************************
+* FUNCTION
+*  nvram_gen_secro
+* DESCRIPTION
+*  Output custom_nvram_secro.c.
+* PARAMETERS
+*  None
+* RETURNS
+*  None
+*****************************************************************************/
+void nvram_gen_secro(void)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    int i = 0;
+    FILE* outputHeader;
+    FILE* outputHeader2;
+    char pathname[NVRAM_AUTO_GEN_MAX_PATH_LEN*2];
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    sprintf(pathname, "%s/nvram_auto_gen/custom_nvram_secro.c", base_path);
+    outputHeader = fopen(pathname,"w+");
+    sprintf(pathname, "%s/nvram_auto_gen/custom_nvram_secro_tbl.c", base_path);    
+    outputHeader2 = fopen(pathname,"w+");
+    
+    if ((outputHeader == NULL) || (outputHeader2 == NULL))    {
+        fprintf(stderr, "error: %s - custom_nvram_secro.c\n", strerror(errno));
+        if(outputHeader != NULL)
+        {
+            fclose(outputHeader);
+        }
+        if(outputHeader2 != NULL)
+        {
+            fclose(outputHeader2);
+        }
+    }
+    else
+    {
+        fprintf(outputHeader, COPYRIGHTS_HEADER, "custom_nvram_secro.c");
+
+        fprintf(outputHeader, "#if !defined(NVRAM_NOT_PRESENT)");
+
+        fprintf(outputHeader, "\n#include \"kal_general_types.h\"");
+        fprintf(outputHeader, "\n#include \"custom_nvram_sec.h\"");
+
+
+
+
+        i = 0;
+        secupack_idx = 0;
+        fprintf(outputHeader2, "#if defined(NVRAM_SEC_C_ONLY)");
+        fprintf(outputHeader2, "\nconst nvram_lid_enum secupack_nvram_lid_tbl[%d] = ", secupack_total_to_verify);
+        fprintf(outputHeader2, "\n{");
+
+        while (i < nvram_gen_total_lid)
+        {
+            nvram_ltable_entry_struct *ldi = &logical_data_item_table[i];
+            if (ldi && ldi->category & NVRAM_CATEGORY_SECUPACK)
+            {
+                fprintf(outputHeader2, "\n   %d,", ldi->LID);
+
+
+                secupack_idx++;
+            }
+            i++;
+        }
+
+
+        fprintf(outputHeader2, "\n};");
+        fprintf(outputHeader2, "\n#endif");
+        fclose(outputHeader2);
+
+        fprintf(outputHeader, "\nconst kal_uint8 NVRAM_CUSTOM_KEY[] = ");
+
+        fprintf(outputHeader, "\n    {");
+        nvram_gen_array(outputHeader, "        ", NVRAM_AUTO_GEN_BYTE, NVRAM_SECRET_KEY_SIZE, custom_secret_key, KAL_FALSE, KAL_TRUE);
+        fprintf(outputHeader, "\n    };");
+
+
+        fprintf(outputHeader, "\nconst kal_uint8 NVRAM_CUSTOM_KEY_SEED[] = ");
+        fprintf(outputHeader, "\n    {");
+        nvram_gen_array(outputHeader, "        ", NVRAM_AUTO_GEN_BYTE, NVRAM_CUSTOM_KEY_SEED_SIZE, custom_key_seed, KAL_FALSE, KAL_TRUE);
+        fprintf(outputHeader, "\n    };");
+        // #endif
+        fprintf(outputHeader, "\n#if defined(__RES_PROT__)");
+        fprintf(outputHeader, "\n__attribute__((section(\"PROTECTED_RES_RW\")))");
+        fprintf(outputHeader, "\n#endif");
+
+        fprintf(outputHeader, "\nconst kal_uint8 NVRAM_SECUPACK_DEFAULT[] = ");
+
+        fprintf(outputHeader, "\n    {");
+
+        i = 0;
+        secupack_idx = 0;
+        while (i < nvram_gen_total_lid)
+        {
+            nvram_ltable_entry_struct *ldi = &logical_data_item_table[i];
+            if (ldi && ldi->category & NVRAM_CATEGORY_SECUPACK)
+            {
+            #ifndef __NVRAM_PSEUDO_MERGE__
+                if (secupack_idx != 0)
+                    fprintf(outputHeader, "\n");
+
+                fprintf(outputHeader, "\n        /* %s */", ldi->str_LID);
+            #endif
+                nvram_gen_array(outputHeader,
+                    "        ",
+                    NVRAM_AUTO_GEN_BYTE,
+                    ldi->size * (ldi->attr & NVRAM_ATTR_MULTI_DEFAULT? ldi->total_records : 1),
+                    (kal_uint8 *)ldi->default_value,
+                    KAL_TRUE,
+                    (secupack_idx + 1 == secupack_total_to_verify));
+                secupack_idx++;
+            }
+            i++;
+        }
+
+
+        /* Fake data for special case */
+        if (secupack_total_to_verify == 0)
+        {
+            fprintf(outputHeader, "\n        0x00, 0x00");
+        }
+
+        fprintf(outputHeader, "\n    };");
+
+
+
+        fprintf(outputHeader, "\nkal_uint32 secupack_total_to_verify = %d;", secupack_total_to_verify);
+        fprintf(outputHeader, "\n#endif /* NVRAM_NOT_PRESENT */");
+        fclose(outputHeader);
+    }
+}
+#endif /* __VENDOR_RELEASE__ */
+
+/*****************************************************************************
+* FUNCTION
+*   nvram_gen_mmi_cache
+* DESCRIPTION
+*   output restore head file to nvram_restore_headfile.h
+* PARAMETERS
+*   project_name    [IN]
+*   broad_ver       [IN]
+* RETURNS
+*   none
+*****************************************************************************/
+void nvram_gen_create_file(FILE **file_handle, char *file_path, char *file_name)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    int  mode_result;
+    char file_pathname[NVRAM_AUTO_GEN_MAX_PATH_LEN];
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    sprintf(file_pathname, "%s/%s", file_path, file_name);
+
+    mode_result = access(file_pathname, 0);
+
+    if (mode_result == 0)
+    {
+        /* exists,but check if it can be written. */
+        mode_result = access(file_pathname, 2);
+        if (mode_result != 0)
+        {
+            fprintf(stderr, "error: %s exists,but it cannot be written.\n", file_name);
+            exit(NVRAM_EXIT_CODE_ERROR);
+        }
+    }
+    else
+    {
+        /* file not exist*/
+        mode_result = access(file_path, 2);
+        if (mode_result != 0)
+        {
+            fprintf(stderr, "error: cannot create file in folder: %s\n", file_path);
+            exit(NVRAM_EXIT_CODE_ERROR);
+        }
+    }
+
+    *file_handle = fopen(file_pathname, "w+");
+    if (*file_handle == NULL)
+    {
+        fprintf(stderr, "error: cannot write to %s in folder: %s(%s)\n", file_name, file_path, strerror(errno));
+        exit(NVRAM_EXIT_CODE_ERROR);
+    }
+    else
+    {
+         printf("Create %x:%s successfully!\n", *file_handle, file_pathname);   
+    }
+    return;
+}
+
+void nvram_gen_close_file(FILE **file_handle)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+
+    fclose(*file_handle);
+}
+/*****************************************************************************
+* FUNCTION
+*   nvram_gen_restore_function
+* DESCRIPTION
+*   output restore function to nvram_user_restore_factory.c
+* PARAMETERS
+*   project_name    [IN]
+*   broad_ver       [IN]
+* RETURNS
+*   none
+*****************************************************************************/
+void nvram_gen_restore_function(void)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    FILE *fh_restore_factory_c;
+    FILE *fh_restore_dom_h;
+    char output_pathname[NVRAM_AUTO_GEN_MAX_PATH_LEN];
+    int  loop_app_idx;
+    int  loop_space;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    sprintf(output_pathname, "nvram_auto_gen/custom_nvram_restore.c");
+    nvram_gen_create_file(&fh_restore_factory_c,base_path,output_pathname);
+
+    sprintf(output_pathname,"nvram_auto_gen/nvram_restore_dom.h");
+    nvram_gen_create_file(&fh_restore_dom_h,base_path,output_pathname);
+
+    /* generate head file */
+    fprintf(fh_restore_factory_c, COPYRIGHTS_HEADER, "nvram_user_restore_factory.h");
+
+    fprintf_blank_line(fh_restore_factory_c);
+
+    fprintf(fh_restore_factory_c, "#ifndef NVRAM_NOT_PRESENT\n");
+    fprintf(fh_restore_factory_c, "#include \"kal_general_types.h\"\n");
+    fprintf(fh_restore_factory_c, "#include \"nvram_enums.h\"\n");
+    fprintf(fh_restore_factory_c, "#include \"custom_nvram_config.h\"\n");
+    fprintf(fh_restore_factory_c, "#include \"nvram_data_items.h\"\n");
+
+
+    /*
+     * Begin deal with system cache
+     */
+    nvram_gen_check_sys_cache();
+    nvram_gen_sys_cache_default(fh_restore_factory_c);
+    nvram_gen_sys_cache_res_func(fh_restore_factory_c);
+
+    /* Dom: data item (begin) */
+    fprintf(fh_restore_dom_h, R_F_DOM_COMMENT, "LID");
+    fprintf(fh_restore_dom_h, R_F_DOM_ENUM_BEGIN);
+
+    for (loop_app_idx = 0; loop_app_idx < nvram_total_num_restore_lid; loop_app_idx++)
+    {
+        fprintf(fh_restore_dom_h, R_F_DOM_CONTENT_ID, nvram_restore_lid_enum_array[loop_app_idx]);
+        for (loop_space = 0; loop_space < nvram_max_length_lid_str - strlen(nvram_restore_lid_enum_array[loop_app_idx]); loop_space++)
+        {
+            fprintf(fh_restore_dom_h, " ");
+        }
+        fprintf(fh_restore_dom_h, R_F_DOM_CONTENT_DESCRIPTION, nvram_restore_lid_description_point[loop_app_idx]);
+    }
+    fprintf(fh_restore_dom_h, R_F_DOM_ENUM_END, "LID", "LID");
+    /* Dom: data item (begin) */
+
+    /*
+     * End deal with system cache
+     */
+
+    fprintf(fh_restore_factory_c, "#endif /* NVRAM_NOT_PRESENT */");
+
+    nvram_gen_close_file(&fh_restore_factory_c);
+    nvram_gen_close_file(&fh_restore_dom_h);
+}
+
+#ifndef __VENDOR_RELEASE__
+/*****************************************************************************
+* FUNCTION
+*  nvram_gen_database_key
+* DESCRIPTION
+*  This function is used to generate the database key into custom_nvram_database.h
+*  After that, codegen will use this file and generate the key into NVRAM database.
+*  Metatool will read the key from database also.
+*  Please notify codegen owner and metatool owner if you want to change the format.
+* PARAMETERS
+*  void
+* RETURNS
+*  void
+*****************************************************************************/
+void nvram_gen_database_key(void)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    FILE *database_h;
+    FILE *fh_restore_dom_h;
+    char output_pathname[NVRAM_AUTO_GEN_MAX_PATH_LEN];
+    int i;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    sprintf(output_pathname, "nvram_auto_gen/custom_nvram_database.h");
+    nvram_gen_create_file(&database_h,base_path,output_pathname);
+
+    nvram_gen_close_file(&database_h);
+}
+#endif  /* __VENDOR_RELEASE__ */
+
+/*****************************************************************************
+* FUNCTION
+*   nvram_gen_custpack_table
+* DESCRIPTION
+* PARAMETERS
+* RETURNS
+*****************************************************************************/
+void nvram_gen_custpack_table(void)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    FILE *output, *output2;
+    char output_path[NVRAM_AUTO_GEN_MAX_PATH_LEN*2], output_path2[NVRAM_AUTO_GEN_MAX_PATH_LEN*2];
+    int i,j;
+    nvram_ltable_entry_struct *ldi;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    sprintf(output_path, "%s/nvram_auto_gen/nvram_custpack_table.c", base_path);
+    sprintf(output_path2, "%s/nvram_auto_gen/nvram_custpack_table_lid.c", base_path);
+
+    if(!(output = fopen(output_path, "w+")))
+    {
+        exit(NVRAM_EXIT_CODE_ERROR);
+    }
+
+    if(!(output2 = fopen(output_path2, "w+")))
+    {
+        exit(NVRAM_EXIT_CODE_ERROR);
+    }
+
+    fprintf(output,"#if defined(NVRAM_INTERNAL_USE) && !defined(NVRAM_NOT_PRESENT)\n");
+    fprintf(output,"/********************************************************\n");
+    fprintf(output," *  This file is generated automatically by nvram_auto_gen\n");
+    fprintf(output," *  Please do not modify it here manually \n");
+    fprintf(output," ***********************************************************/\n");
+
+    fprintf(output2,"#if defined(NVRAM_LTABLE_C_ONLY)\n");
+/*
+    for (i = NVRAM_EF_START, j = 0; i < nvram_gen_total_lid; i++)
+    {
+        ldi = &logical_data_item_table[i];
+
+        if (ldi == NULL ||
+            (ldi->LID == 0 && ldi->size == 0 && ldi->total_records == 0))
+        {
+            continue;
+        }
+
+        if (NVRAM_IS_CATEGORY_CUSTPACK(ldi->category))
+        {
+            j++;
+            fprintf(output, "extern kal_uint8 *%s;\n", ldi->str_default_value);
+        }
+    }
+
+    fprintf(output,"\n");    
+*/
+    fprintf(output, "const custpack_nvram_header custpack_nvram_ptr = \n");
+    fprintf(output2, "const nvram_custpack_lid_tbl_struct custpack_nvram_lid_tbl = \n");
+
+    fprintf(output, "{\n");         fprintf(output2, "{\n");
+    fprintf(output, "    0,\n");    fprintf(output2, "    0,\n");
+    fprintf(output, "    {\n");     fprintf(output2, "    {\n");
+
+    for (i = NVRAM_EF_START, j = 0; i < nvram_gen_total_lid; i++)
+    {
+        ldi = &logical_data_item_table[i];
+
+        if (ldi == NULL ||
+            (ldi->LID == 0 && ldi->size == 0 && ldi->total_records == 0))
+        {
+            continue;
+        }
+
+        if (NVRAM_IS_CATEGORY_CUSTPACK(ldi->category))
+        {
+            j++;
+            fprintf(output, "        %s", ldi->str_default_value);
+            fprintf(output2, "        %d", ldi->LID);
+
+            if (j != custpack_total_to_verify)
+            {
+                fprintf(output,",");    fprintf(output2,",");
+            }
+            fprintf(output,"\n");       fprintf(output2,"\n");
+        }
+    }
+
+
+    fprintf(output, "    }\n");         fprintf(output2, "    }\n");
+    fprintf(output, "};\n");            fprintf(output2, "};\n");
+    fprintf(output, "#endif /* NVRAM_INTERNAL_USE && NVRAM_NOT_PRESENT */\n\n");
+    fprintf(output2, "#endif\n\n");
+
+    fclose(output);        fclose(output2);
+}
+
+/*****************************************************************************
+* FUNCTION
+*  nvram_parsing_size_from_mapfile
+* DESCRIPTION
+*  get default value size.
+* PARAMETERS
+*  None
+* RETURNS
+*  None
+*****************************************************************************/
+kal_uint32 nvram_parsing_size_from_mapfile(char *line_buf)
+{
+    char *pos = strrchr(line_buf, ' ');
+    kal_uint32 val = 0;
+
+    //skip LID name
+    if(pos == NULL) {
+        return 0;
+    }
+    *pos = '\0';
+    pos = strrchr(line_buf, '0');
+    if(pos == NULL) {
+        return 0;
+    }
+    pos = strrchr(line_buf, '\t');
+    if(pos == NULL) {
+        return 0;
+    }
+    val = strtol(++pos, NULL, 16);
+    //printf("%s:%d\n", pos, val);
+    return val;
+}
+
+/*****************************************************************************
+* FUNCTION
+*  nvram_parsing_size_from_mapfile
+* DESCRIPTION
+*  get default value size.
+* PARAMETERS
+*  None
+* RETURNS
+*  None
+*****************************************************************************/
+kal_uint32 nvram_split(char *line_buf, char **dest)
+{
+    kal_uint32 num = 0;
+    char *pNext = line_buf;
+
+    while(*pNext != '\0' && (*pNext == ' ' || *pNext == '\t')) {
+        pNext++;
+    }
+    *dest = pNext;
+    while(*pNext != '\0') {
+        if(*pNext == ' ' || *pNext == '\t') {
+           *pNext = '\0';
+           while(*(++pNext) != '\0' && (*pNext == ' ' || *pNext == '\t'));
+           *(++dest) = pNext;
+           ++num;
+        }
+        pNext++;
+    }
+    return num;
+}
+
+/*****************************************************************************
+* FUNCTION
+*  nvram_parsing_default_from_elf
+* DESCRIPTION
+*  get default value from elf.
+* PARAMETERS
+*  None
+* RETURNS
+*  None
+*****************************************************************************/
+kal_uint32 nvram_parsing_default_from_elf(char *file_path, nvram_ltable_entry_struct *ldi)
+{
+    kal_uint32 offset = 0, session = 0;
+    kal_uint32 offset4 = 0, offset5 = 0, size = 0;
+    FILE *file_handle = NULL;
+    char file_pathname[NVRAM_AUTO_GEN_MAX_PATH_LEN] = {0};
+    char line_buf[128];
+    char session_name[128];
+    char *dest[16];
+    char *str_default_value = ldi->str_default_value;
+        
+    while(*str_default_value == '&') {
+        str_default_value++;
+    }
+    //Get default value start address from map
+    sprintf(file_pathname, "%s.map", file_path);
+    file_handle = fopen(file_pathname, "r");
+    if (file_handle == NULL)
+    {
+        printf("fail to open file %s\n", file_pathname);
+        return 0;
+    }
+    while(!feof(file_handle))
+    {
+        fgets(line_buf, 128, file_handle);
+        if((offset == 0) && strstr(line_buf, str_default_value)) {
+            nvram_split(line_buf, dest);
+            strcpy(session_name, dest[3]);
+            sscanf(dest[0],"%x", &offset);
+            sscanf(dest[4],"%x", &size);
+            ldi->default_value = malloc(size);
+            fseek(file_handle, 0, SEEK_SET);
+            continue;
+        }
+        if((offset > 0) && strstr(line_buf, session_name)) {
+            nvram_split(line_buf, dest);
+            sscanf(dest[4],"%x", &offset4);
+            sscanf(dest[5],"%x", &offset5);
+            offset -= (offset4 - offset5);
+            break;
+        }        
+    }
+    fclose(file_handle);
+    file_handle = fopen(file_path, "rb");
+    if (file_handle == NULL)
+    {
+        printf("fail to open file %s\n", file_path);
+        return 0;
+    }
+    fseek(file_handle, offset, SEEK_SET);
+    fread(ldi->default_value, size, 1, file_handle);
+    fclose(file_handle);
+
+    return offset;
+}
+
+/*****************************************************************************
+* FUNCTION
+*  nvram_default_value_check
+* DESCRIPTION
+*  Check NVRAM LID size fit default value.
+* PARAMETERS
+*  None
+* RETURNS
+*  None
+*****************************************************************************/
+void nvram_default_value_check()
+{
+    kal_bool err = KAL_FALSE;
+    int mode_result;
+    FILE *file_handle;
+    char file_pathname[NVRAM_AUTO_GEN_MAX_PATH_LEN];
+    char line_buf[128];
+    nvram_ltable_entry_struct *ldi;
+    kal_uint32 i, default_val_size, ldi_size;
+
+    sprintf(file_pathname, "%s/nvram_auto_gen/nvram_auto_gen_target.map", base_path);
+    mode_result = access(file_pathname, 0);
+
+    if (mode_result != 0)
+    {
+        sprintf(file_pathname, "%s/nvram_auto_gen/nvram_auto_gen.map", base_path);
+        mode_result = access(file_pathname, 0);
+        if (mode_result != 0)
+        {
+            //file not exist
+            printf("MAP file not exist: %s\n", file_pathname);
+            return;
+        }        
+    }
+
+    file_handle = fopen(file_pathname, "r");
+    if (file_handle == NULL)
+    {
+        fprintf(stderr, "error: cannot open file %s\n", file_pathname);
+        exit(NVRAM_EXIT_CODE_ERROR);
+    }
+
+    while(!feof(file_handle))
+    {
+        fgets(line_buf, 128, file_handle);
+        for (i = 0; i < nvram_gen_total_lid; i++)
+        {
+            ldi = &logical_data_item_table[i];
+            if((ldi->default_value == NVRAM_EF_FF_DEFAULT) || 
+                (ldi->default_value == NVRAM_EF_ZERO_DEFAULT) ||
+                (ldi->default_value == NVRAM_EF_SPECIAL_DEFAULT) ||
+                (ldi->category & NVRAM_CATEGORY_FUNC_DEFAULT))
+            {
+                continue;
+            }
+            if(strstr(line_buf, ldi->str_default_value))
+            {
+                printf("%s", line_buf);
+                default_val_size = nvram_parsing_size_from_mapfile(line_buf);
+                if(!default_val_size) {
+                    continue;
+                }
+                if (ldi->attr & NVRAM_ATTR_MULTI_DEFAULT) {
+                    ldi_size = ldi->size * ldi->total_records;
+                }
+                else {
+                    ldi_size = ldi->size;
+                }
+                
+                if(default_val_size < ldi_size) {
+                    fprintf(stderr, "error: %s[%d] does not match with %s (size %d)\n", ldi->str_default_value, default_val_size, ldi->str_LID, ldi_size);
+                    err = KAL_TRUE;
+                }
+                else if((default_val_size > ldi_size) && (default_val_size % ldi_size)) {
+                    fprintf(stderr, "error: %s[%d] does not match with %s (size %d)\n", ldi->str_default_value, default_val_size, ldi->str_LID, ldi_size);
+                    err = KAL_TRUE;
+                }
+            }
+        }
+    }
+    fclose(file_handle);
+
+    if(err) {
+        exit(NVRAM_EXIT_CODE_ERROR);
+    }
+    return;    
+}
+
+/*****************************************************************************
+* FUNCTION
+*  nvram_gen_cat_xml
+* DESCRIPTION
+*  Output NVRAM LID size Information.
+* PARAMETERS
+*  None
+* RETURNS
+*  None
+*****************************************************************************/
+void nvram_gen_cat_xml(void)
+{
+
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    FILE *cat_xml_file;
+    char output_pathname[NVRAM_AUTO_GEN_MAX_PATH_LEN];
+    kal_int32 i,j;
+    nvram_ltable_entry_struct *ldi;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    sprintf(output_pathname, "nvram_auto_gen/custom_nvram_lid_cat.xml");
+    nvram_gen_create_file(&cat_xml_file,base_path,output_pathname);
+
+    fprintf(cat_xml_file, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+
+    fprintf(cat_xml_file, "<APP>\n");
+
+    for (i = 0; i < nvram_gen_total_lid; i++)
+    {
+        ldi = &logical_data_item_table[i];
+
+        if (ldi == NULL || (ldi->LID == 0 && ldi->size == 0 && ldi->total_records == 0))
+        {
+            continue;
+        }
+
+        fprintf(cat_xml_file, "    <NVRAMITEM id=\"%s\"", ldi->str_LID);
+        fprintf(cat_xml_file, " prefix=\"%s\"", ldi->fileprefix);
+        fprintf(cat_xml_file, " version=\"%s\"", ldi->fileverno);
+        fprintf(cat_xml_file, " record_size=\"%d\"", ldi->size);
+        fprintf(cat_xml_file, " total_record=\"%d\"", ldi->total_records);
+        fprintf(cat_xml_file, " lid_enum=\"%d\"", ldi->LID);
+         fprintf(cat_xml_file, " category=\"0x%x\"", ldi->category);
+        fprintf(cat_xml_file, " attribute=\"0x%x\">\n", ldi->attr);
+        if (ldi->category & NVRAM_CATEGORY_FUNC_DEFAULT)
+        {
+            fprintf(cat_xml_file, "        <DEFAULT_VALUE defaultByteFill=\"%s()\"></DEFAULT_VALUE>\n", ldi->str_default_value);
+        }
+        else if (ldi->default_value == NVRAM_EF_FF_DEFAULT)
+        {
+            fprintf(cat_xml_file, "        <DEFAULT_VALUE defaultByteFill=\"0xFF\"></DEFAULT_VALUE>\n");
+        }
+        else if (ldi->default_value == NVRAM_EF_ZERO_DEFAULT)
+        {
+            fprintf(cat_xml_file, "        <DEFAULT_VALUE defaultByteFill=\"0x00\"></DEFAULT_VALUE>\n");
+        }
+        else if (ldi->default_value == NVRAM_EF_SPECIAL_DEFAULT)
+        {
+            fprintf(cat_xml_file, "        <DEFAULT_VALUE defaultByteFill=\"0x00\"></DEFAULT_VALUE>\n");
+        }    
+        else
+        {
+            kal_uint32 default_value_size;
+
+
+            if (ldi->attr & NVRAM_ATTR_MULTI_DEFAULT)
+            {
+                fprintf(cat_xml_file, "        <DEFAULT_VALUE isMultiple=\"TRUE\"> \n");
+                default_value_size = ldi->size * ldi->total_records;
+            }
+            else
+            {
+                fprintf(cat_xml_file, "        <DEFAULT_VALUE> \n");
+                default_value_size = ldi->size;
+            }
+            if(ldi->default_value == NULL) {
+                default_value_size = 0;
+            }
+
+            for ( j = 0 ; j < default_value_size ; j++)
+            {
+                if(default_value_size == 1)
+                {
+                    fprintf(cat_xml_file, "            [0x%02X]\n        </DEFAULT_VALUE>\n", ldi->default_value[j]);
+                }            
+                else if (j == 0)
+                {
+                    fprintf(cat_xml_file, "            [0x%02X,", ldi->default_value[j]);
+                }
+                else if (j == (default_value_size - 1))
+                {
+                    fprintf(cat_xml_file, " 0x%02X]\n        </DEFAULT_VALUE>\n", ldi->default_value[j]);
+                }
+                else if ((j & 0x0F) == 0x0F)
+                {
+                    fprintf(cat_xml_file, " 0x%02X,\n", ldi->default_value[j]);
+                }
+                else if ((j & 0x0F) == 0)
+                {
+                    fprintf(cat_xml_file, "             0x%02X,", ldi->default_value[j]);
+                }
+                else
+                {
+                    fprintf(cat_xml_file, " 0x%02X,", ldi->default_value[j]);
+                }
+            }
+        }
+
+        //fprintf(cat_xml_file, "        <DESCRIPTION> %s </DESCRIPTION>\n", ldi->description);
+        fprintf(cat_xml_file, "        <DESCRIPTION> %s </DESCRIPTION>\n", ldi->str_LID);
+        fprintf(cat_xml_file, "    </NVRAMITEM>\n");
+    }
+
+    fprintf(cat_xml_file, "</APP>\n");
+
+    nvram_gen_close_file(&cat_xml_file);
+}
+
+#ifndef __VENDOR_RELEASE__
+/*****************************************************************************
+* FUNCTION
+*  nvram_gen_cat_xml
+* DESCRIPTION
+*  Output NVRAM LID size Information.
+* PARAMETERS
+*  None
+* RETURNS
+*  None
+*****************************************************************************/
+void nvram_gen_trace(void)
+{
+
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    FILE *trace_file;
+    char output_pathname[NVRAM_AUTO_GEN_MAX_PATH_LEN];
+    kal_int32 i,j;
+    nvram_ltable_entry_struct *ldi;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    sprintf(output_pathname, "nvram_auto_gen/nvram_gen_trc.h");
+    nvram_gen_create_file(&trace_file,base_path,output_pathname);
+
+    fprintf(trace_file, "typedef enum {\n");
+    
+    for (i = NVRAM_EF_SYS_LID; i < nvram_gen_total_lid; i++)
+    {
+        ldi = &logical_data_item_table[i];
+
+        if (ldi == NULL || (ldi->LID == 0 && ldi->size == 0 && ldi->total_records == 0))
+        {
+            continue;
+        }
+        else
+        {
+            fprintf(trace_file, "    _%s = %d,\n", ldi->str_LID, ldi->LID);
+        }
+    }
+
+    fprintf(trace_file, "    NVRAM_TRC_LID_TOTAL\n}nvram_trc_lid_enum;\n");
+
+    nvram_gen_close_file(&trace_file);
+}
+
+#endif    //__VENDOR_RELEASE__
+#endif /* NVRAM_NOT_PRESENT */
+
+void nvram_gen_check_multiple_attr_white_list()
+{
+    int i, j;
+    nvram_ltable_entry_struct *ldi;
+    kal_bool in_list;
+    kal_bool check_result = KAL_TRUE;
+
+
+    for (i = 0; i < nvram_gen_total_lid; i++)
+    {
+        ldi = &logical_data_item_table[i];
+        if (ldi == NULL || (ldi->LID == 0 && ldi->size == 0 && ldi->total_records == 0))
+        {
+            continue;
+        }
+
+        if (!NVRAM_IS_ATTR_MULTIPLE(ldi->attr))
+        {
+            continue;
+        }
+
+    #ifdef __NVRAM_BIND_TO_CHIP_CIPHER__
+        if (ldi->attr & NVRAM_ATTR_MSP)
+        {
+            continue;
+        }
+    #endif
+
+        if (ldi->str_LID == NULL) {
+            continue;
+        }
+
+        in_list = KAL_FALSE;
+
+        for (j = 0; j < g_nr_nvram_white_list_for_multiple_attr; j++)
+        {
+            if (0 == strcmp(ldi->str_LID, g_nvram_white_list_for_multiple_attr[j])) {
+                in_list = KAL_TRUE;
+                break;
+            }
+        }
+
+        if (KAL_TRUE != in_list) {
+            // Not in white list
+            check_result = KAL_FALSE;
+            fprintf(stderr, "error: LID %s have MULTIPLE attribute but not in white list!!\n", ldi->str_LID);
+        }
+    }
+
+    if (KAL_TRUE != check_result) {
+        fprintf(stderr, "error: Please contact NVRAM owner if you really need this attribute for the LID\n");
+        exit(-1);
+    }
+}
+
+
+void nvram_gen_check_write_protect_attr_white_list()
+{
+    int i, j;
+    nvram_ltable_entry_struct *ldi;
+    kal_bool in_list;
+    kal_bool check_result = KAL_TRUE;
+
+    for (i = 0; i < nvram_gen_total_lid; i++)
+    {
+        ldi = &logical_data_item_table[i];
+        if (ldi == NULL || (ldi->LID == 0 && ldi->size == 0 && ldi->total_records == 0))
+        {
+            continue;
+        }
+
+        if (!NVRAM_IS_ATTR_WRITEPROTECT(ldi->attr))
+        {
+            continue;
+        }
+
+        if (ldi->str_LID == NULL) {
+            continue;
+        }
+
+        in_list = KAL_FALSE;
+
+        for (j = 0; j < g_nr_nvram_white_list_for_write_protect_attr; j++)
+        {
+        if (0 == strcmp(ldi->str_LID, g_nvram_white_list_for_write_protect_attr[j])) {
+        in_list = KAL_TRUE;
+        break;
+        }
+        }
+
+        if (KAL_TRUE != in_list) {
+            // Not in white list
+            check_result = KAL_FALSE;
+            fprintf(stderr, "LID %s have WRITE_PROTECT attribute but not in white list!!\n", ldi->str_LID);
+        }
+    }
+
+    if (KAL_TRUE != check_result) {
+        fprintf(stderr, "Please contact NVRAM owner if you really need this attribute for the LID(s)\n");
+        exit(-2);
+    }
+}
+
+void nvram_gen_check_lid_enum_overlapping()
+{
+    int i, j;
+    nvram_ltable_entry_struct *ldi1;
+    nvram_ltable_entry_struct *ldi2;
+    
+    kal_bool check_result = KAL_TRUE;
+
+	if(nvram_gen_total_lid < 2) {
+		fprintf(stderr, "error: Invalid nvram_gen_total_lid during nvram_gen_check_lid_enum_overlapping()\n");
+		exit(-3);
+	}
+    for (i = 0; i < nvram_gen_total_lid-1; i++)
+    {
+        ldi1 = &logical_data_item_table[i];
+        for (j = i+1; j < nvram_gen_total_lid; j++) {
+            ldi2 = &logical_data_item_table[j];
+            if (ldi1->LID == ldi2->LID) {
+                check_result = KAL_FALSE;
+                fprintf(stderr, "error: %d:%s and %d:%s have same enum value, please check if LID duplicated defined or enum value overlapped\n", i, ldi1->str_LID, j, ldi2->str_LID);
+            }
+        }
+    }
+
+    if (KAL_TRUE != check_result) {
+        fprintf(stderr, "error: Please contact NVRAM owner if your NVRAM sub-group size should be enlarged\n");
+        exit(-3);
+    }
+}
+
+
+typedef enum {
+    NVRAM_CONFLICT_ATTR_ATTR,
+    NVRAM_CONFLICT_CATE_ATTR,
+    NVRAM_CONFLICT_CATE_CATE,
+} nvram_CATE_ATTR_conflict_type_enum;
+
+typedef struct  {
+    nvram_CATE_ATTR_conflict_type_enum type;
+    kal_uint32 cate_attr1;
+    kal_char *cate_attr1_str;
+    kal_uint32 cate_attr2;
+    kal_char *cate_attr2_str;
+}nvram_CATE_ATTR_conflict_struct;
+
+#define CATE_ATTR(x)     (x), #x
+
+static nvram_CATE_ATTR_conflict_struct nvram_CATE_ATTR_conflict_table[] = 
+{
+    // Attribute conflicts
+    {NVRAM_CONFLICT_ATTR_ATTR, CATE_ATTR(NVRAM_ATTR_MULTIPLE), CATE_ATTR(NVRAM_ATTR_PACKAGE)},
+    {NVRAM_CONFLICT_ATTR_ATTR, CATE_ATTR(NVRAM_ATTR_OTA_RESET), CATE_ATTR(NVRAM_ATTR_RESERVE_BACKWARD)},
+    {NVRAM_CONFLICT_ATTR_ATTR, CATE_ATTR(NVRAM_ATTR_RAW_DATA), CATE_ATTR(NVRAM_ATTR_PACKAGE|NVRAM_ATTR_MULTIPLE|NVRAM_ATTR_RING)},
+    {NVRAM_CONFLICT_ATTR_ATTR, CATE_ATTR(NVRAM_ATTR_RAW_DATA), CATE_ATTR(NVRAM_ATTR_WRITEPROTECT|NVRAM_ATTR_CONFIDENTIAL|NVRAM_ATTR_MSP)},
+
+    // Categories conflicts
+    {NVRAM_CONFLICT_CATE_CATE, CATE_ATTR(NVRAM_CATEGORY_FUNC_DEFAULT), CATE_ATTR(NVRAM_CATEGORY_CUSTPACK|NVRAM_CATEGORY_SECUPACK)},
+    {NVRAM_CONFLICT_CATE_CATE, CATE_ATTR(NVRAM_CATEGORY_CALIBRAT), CATE_ATTR(~(NVRAM_CATEGORY_FUNC_DEFAULT|NVRAM_CATEGORY_CUSTPACK|NVRAM_CATEGORY_SECUPACK))},
+    {NVRAM_CONFLICT_CATE_CATE, CATE_ATTR(NVRAM_CATEGORY_IMPORTANT), CATE_ATTR(NVRAM_CATEGORY_IMPORTANT_L1|NVRAM_CATEGORY_IMPORTANT_L4|NVRAM_CATEGORY_INTERNAL|NVRAM_CATEGORY_OTP)},
+    {NVRAM_CONFLICT_CATE_CATE, CATE_ATTR(NVRAM_CATEGORY_IMPORTANT_L4), CATE_ATTR(NVRAM_CATEGORY_IMPORTANT_L1|NVRAM_CATEGORY_INTERNAL|NVRAM_CATEGORY_OTP)},
+    {NVRAM_CONFLICT_CATE_CATE, CATE_ATTR(NVRAM_CATEGORY_IMPORTANT_L1), CATE_ATTR(NVRAM_CATEGORY_INTERNAL|NVRAM_CATEGORY_OTP)},
+    {NVRAM_CONFLICT_CATE_CATE, CATE_ATTR(NVRAM_CATEGORY_INTERNAL), CATE_ATTR(NVRAM_CATEGORY_CUSTOM_SENSITIVE |NVRAM_CATEGORY_OTP)},
+    {NVRAM_CONFLICT_CATE_CATE, CATE_ATTR(NVRAM_CATEGORY_CUSTOM_SENSITIVE), CATE_ATTR(NVRAM_CATEGORY_CUSTPACK|NVRAM_CATEGORY_SECUPACK|NVRAM_CATEGORY_OTP)},
+    {NVRAM_CONFLICT_CATE_CATE, CATE_ATTR(NVRAM_CATEGORY_CUSTPACK), CATE_ATTR(NVRAM_CATEGORY_SECUPACK|NVRAM_CATEGORY_OTP)},
+    {NVRAM_CONFLICT_CATE_CATE, CATE_ATTR(NVRAM_CATEGORY_SECUPACK), CATE_ATTR(NVRAM_CATEGORY_OTP)},
+
+    //  Attribute & Category conflicts
+    {NVRAM_CONFLICT_CATE_ATTR, CATE_ATTR(NVRAM_CATEGORY_CALIBRAT), CATE_ATTR(NVRAM_ATTR_MULTIPLE|NVRAM_ATTR_MSP|NVRAM_ATTR_RING)},
+    {NVRAM_CONFLICT_CATE_ATTR, CATE_ATTR(NVRAM_CATEGORY_CALIBRAT), CATE_ATTR(NVRAM_ATTR_OTA_RESET|NVRAM_ATTR_RESERVE_BACKWARD)},
+    {NVRAM_CONFLICT_CATE_ATTR, CATE_ATTR(NVRAM_CATEGORY_INTERNAL), CATE_ATTR(NVRAM_ATTR_PACKAGE)},
+    {NVRAM_CONFLICT_CATE_ATTR, CATE_ATTR(NVRAM_CATEGORY_SECUPACK), CATE_ATTR(NVRAM_ATTR_PACKAGE|NVRAM_ATTR_RAW_DATA)},
+    {NVRAM_CONFLICT_CATE_ATTR, CATE_ATTR(NVRAM_CATEGORY_CUSTPACK), CATE_ATTR(NVRAM_ATTR_RAW_DATA)},
+    {NVRAM_CONFLICT_CATE_ATTR, CATE_ATTR(NVRAM_CATEGORY_FUNC_DEFAULT), CATE_ATTR(NVRAM_ATTR_RAW_DATA)},
+    {NVRAM_CONFLICT_CATE_ATTR, CATE_ATTR(NVRAM_CATEGORY_OTP), CATE_ATTR(NVRAM_ATTR_AVERAGE)},
+};
+
+static kal_int32 nvram_CATE_ATTR_conflict_table_entries = sizeof(nvram_CATE_ATTR_conflict_table)/sizeof(nvram_CATE_ATTR_conflict_table[0]);
+
+void nvram_gen_check_cate_attr_confilicts()
+{
+    int i, j;
+    nvram_ltable_entry_struct *ldi;
+    
+    kal_bool check_result = KAL_TRUE;
+
+    for (i = 0; i < nvram_gen_total_lid-1; i++)
+    {
+        ldi = &logical_data_item_table[i];
+        for (j = 0; j < nvram_CATE_ATTR_conflict_table_entries; j++) {
+            nvram_CATE_ATTR_conflict_struct *check_cond = &nvram_CATE_ATTR_conflict_table[j];
+            switch (check_cond->type) {
+            case NVRAM_CONFLICT_ATTR_ATTR:
+                if ((ldi->attr & check_cond->cate_attr1) != 0  && (ldi->attr & (~check_cond->cate_attr1) & check_cond->cate_attr2) != 0) {
+                    check_result = KAL_FALSE;
+                    fprintf(stderr, "error: LID %s have conflict attributes %s and %s\n", ldi->str_LID, check_cond->cate_attr1_str, check_cond->cate_attr2_str);
+                }
+                break;
+            case NVRAM_CONFLICT_CATE_ATTR:
+                if ((ldi->category & check_cond->cate_attr1) != 0  && (ldi->attr & check_cond->cate_attr2) != 0) {
+                    check_result = KAL_FALSE;
+                    fprintf(stderr, "error: LID %s have conflict category %s with attribute %s\n", ldi->str_LID, check_cond->cate_attr1_str, check_cond->cate_attr2_str);
+                }
+                break;
+            case NVRAM_CONFLICT_CATE_CATE:
+                if ((ldi->category & check_cond->cate_attr1) != 0  && (ldi->category & (~check_cond->cate_attr1) & check_cond->cate_attr2) != 0) {
+                    check_result = KAL_FALSE;
+                    fprintf(stderr, "error: LID %s have conflict categories %s and %s\n", ldi->str_LID, check_cond->cate_attr1_str, check_cond->cate_attr2_str);
+                }
+                break;
+            default:
+                break;
+            }
+        }
+    }
+
+    if (KAL_TRUE != check_result) {
+        fprintf(stderr, "error: Please adjust LID's attributes and/or categories\n");
+        exit(-4);
+    }
+}
+
+void nvram_gen_check_special_lid_parameter()
+{
+    int i, j;
+    nvram_ltable_entry_struct *ldi;
+    kal_bool check_result = KAL_TRUE;
+
+    for (i = 0; i < nvram_gen_total_lid; i++)
+    {
+        ldi = &logical_data_item_table[i];
+        
+        // check RAW_DATA size and default value
+        if(ldi->attr & NVRAM_ATTR_RAW_DATA) {
+            if(ldi->total_records > 1) {
+                check_result = KAL_FALSE;
+                fprintf(stderr, "error: NVRAM_ATTR_RAW_DATA can not support multiple record.\n");
+            }
+            if(ldi->default_value != NVRAM_EF_ZERO_DEFAULT) {
+                check_result = KAL_FALSE;
+                fprintf(stderr, "error: NVRAM_ATTR_RAW_DATA can only use NVRAM_EF_ZERO_DEFAULT.\n");
+            }            
+        }
+
+    #if (defined(__NVRAM_LID_HASH_CHECK__) && defined(__MTK_INTERNAL__))
+        // check LID hash key
+        printf("check %s hash key 0x%08x\n", ldi->str_LID, ldi->hash_key);
+        if(!(ldi->fileprefix[0]=='C' && ldi->fileprefix[1]=='U')) {
+            if(!nvram_hash_check(ldi)) {
+                check_result = KAL_FALSE;
+            }
+        }
+    #endif
+    }
+
+    if (KAL_TRUE != check_result) {
+        exit(-5);
+    }
+}
+
+void nvram_fix_lid_size()
+{
+    kal_uint32 i, j, offset = 0;
+    FILE *file_handle = NULL;
+    char file_pathname[NVRAM_AUTO_GEN_MAX_PATH_LEN] = {0};
+    nvram_ltable_entry_struct *ldi = NULL;
+    nvram_ltable_entry_struct_target *ldi_target = NULL;
+    char line_buf[128], *dest[16];
+    char *ldi_buf = NULL;
+
+    //Get NVRAM_LTABLE Start
+    sprintf(file_pathname, "%s/nvram_auto_gen/nvram_auto_gen_target.map", base_path);
+    file_handle = fopen(file_pathname, "r");
+    if (file_handle == NULL)
+    {
+        printf("fail to open file %s\n", file_pathname);
+        return;
+    }
+    while(!feof(file_handle))
+    {
+        fgets(line_buf, 128, file_handle);
+        if(!offset && strstr(line_buf, "NVRAM_LTABLE")) {
+            nvram_split(line_buf, dest);
+            sscanf(dest[5],"%x", &offset);
+            continue;
+        }
+        if(strstr(line_buf, "nvram_long_length")) {
+            nvram_split(line_buf, dest);
+            sscanf(dest[4],"%x", &nvram_long_length);
+            continue;
+        }
+        if(strstr(line_buf, "nvram_ptr_length")) {
+            nvram_split(line_buf, dest);
+            sscanf(dest[4],"%x", &nvram_ptr_length);
+            continue;
+        }
+        if(strstr(line_buf, "nvram_padding_length")) {
+            nvram_split(line_buf, dest);
+            sscanf(dest[4],"%x", &nvram_padding_length);
+            continue;
+        }
+        if(strstr(line_buf, "nvram_ltable_entry_length")) {
+            nvram_split(line_buf, dest);
+            sscanf(dest[4],"%x", &nvram_ltable_entry_length);
+            continue;
+        }
+    }
+    fclose(file_handle);
+
+    //Fix LID size in ltable
+    sprintf(file_pathname, "%s/nvram_auto_gen/nvram_auto_gen_target", base_path);
+    file_handle = fopen(file_pathname, "rb");
+    if (file_handle == NULL)
+    {
+        printf("fail to open file %s\n", file_pathname);
+        return;
+    }
+    fseek(file_handle, offset, SEEK_SET);
+    ldi_buf = malloc(nvram_ltable_entry_length * nvram_gen_total_lid);
+    fread(ldi_buf, nvram_ltable_entry_length * nvram_gen_total_lid, 1, file_handle);
+    fclose(file_handle); 
+    
+    for (i = 0; i < nvram_gen_total_lid; i++)
+    {
+        ldi = &logical_data_item_table[i];
+        // search lid in target load
+        for(j = 0; j < nvram_gen_total_lid; j++) {
+            ldi_target = &ldi_buf[nvram_ltable_entry_length * j];
+            if((ldi->LID == ldi_target->LID) && 
+               (*(kal_uint32*)ldi->fileprefix == *(kal_uint32*)ldi_target->fileprefix) ) 
+            {
+                break;
+            }
+        }
+        if(ldi->LID != ldi_target->LID) {
+            if((ldi->LID & 0xFF00) != NVRAM_LID_GRP_INTERNAL(0)) {
+                printf("%s[%d] search fail in target load.\n", ldi->str_LID, ldi->LID);
+            }
+            continue;
+        }
+        if(ldi->size != ldi_target->size) {
+            printf("%s[%d] fix record %s(size %d) <= %s(size %d)\n", ldi->str_LID, ldi->LID, ldi->fileprefix, ldi->size, ldi_target->fileprefix, ldi_target->size);
+            ldi->size = ldi_target->size;
+            //Mark default value mistake
+            if (!(ldi->category & NVRAM_CATEGORY_FUNC_DEFAULT) &&
+                (ldi->default_value != NVRAM_EF_FF_DEFAULT) &&
+                (ldi->default_value != NVRAM_EF_ZERO_DEFAULT) )
+            {
+                offset = nvram_parsing_default_from_elf(file_pathname, ldi);
+                printf("%s[%d] fix default %s from 0x%X\n", ldi->str_LID, ldi->LID, ldi->str_default_value, offset);
+            }
+        }
+        else {
+            //printf("%s[%d] check pass.\n", ldi->str_LID, ldi->LID);
+        }
+    }
+    
+}
+
+void nvram_gen_mcf_ota_lid_list(void)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    kal_uint32 i,j;
+    FILE* ota_lid_list_hdl;
+    nvram_ltable_entry_struct *ldi;
+    static char **nvram_ota_lid_str_point;
+    static char **nvram_ota_by_op_lid_str_point;
+    int nvram_total_num_ota_lid = 0;
+    int nvram_total_num_ota_by_op_lid = 0;
+    char pathname[NVRAM_AUTO_GEN_MAX_PATH_LEN*2];
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+
+    /* Gen information for tools */
+    sprintf(pathname, "%s/nvram_auto_gen/nvram_lid_list_for_mcf.h", base_path);
+    ota_lid_list_hdl = fopen(pathname,"w+");
+    if (ota_lid_list_hdl == NULL)
+    {
+        fprintf(stderr, "error: %s - nvram_lid_list_for_mcf.h\n", strerror(errno));
+    }
+    else
+    {
+        nvram_ota_lid_str_point = malloc(sizeof(char *) * nvram_gen_total_lid);
+        nvram_ota_by_op_lid_str_point = malloc(sizeof(char *) * nvram_gen_total_lid);    
+        for (i = 0;i < nvram_gen_total_lid; i++)
+        {
+            ldi = &logical_data_item_table[i];
+            if (ldi == NULL ||
+                (ldi->LID == 0 && ldi->size == 0 && ldi->total_records == 0))
+            {
+                continue;   /* invalid LID */
+            }
+            if(ldi->attr & NVRAM_ATTR_MCF_OTA)
+            {
+                nvram_ota_lid_str_point[nvram_total_num_ota_lid] = ldi->str_LID;
+                nvram_total_num_ota_lid++;
+            }
+            else if(ldi->attr & NVRAM_ATTR_MCF_OTA_FOR_QUERY)
+            {
+                nvram_ota_lid_str_point[nvram_total_num_ota_lid] = ldi->str_LID;
+                nvram_total_num_ota_lid++;
+            }
+            if(ldi->attr &  NVRAM_ATTR_MCF_OTA_BY_OP)
+            {
+                nvram_ota_by_op_lid_str_point[nvram_total_num_ota_by_op_lid] = ldi->str_LID;
+                nvram_total_num_ota_by_op_lid++;
+            }
+            else
+            {
+                continue;
+            }
+        }
+        
+        fprintf(ota_lid_list_hdl, COPYRIGHTS_HEADER, "nvram_lid_list_for_mcf.h");
+        
+        fprintf(ota_lid_list_hdl, "#ifndef __NVRAM_LID_LIST_FOR_MCF__\n");
+        fprintf(ota_lid_list_hdl, "#define __NVRAM_LID_LIST_FOR_MCF__\n");
+        fprintf(ota_lid_list_hdl, "#include \"kal_general_types.h\"\n");
+
+        fprintf(ota_lid_list_hdl, R_F_DOM_ENUM_BEGIN);
+        for(j = 0; j < nvram_total_num_ota_lid;j++)
+        {
+            fprintf(ota_lid_list_hdl, "    %s,    \n", nvram_ota_lid_str_point[j]);
+        }
+        fprintf(ota_lid_list_hdl, R_F_MCF_ENUM_END, "LID", "nvram_mcf_ota_lid");
+
+        fprintf(ota_lid_list_hdl, R_F_DOM_ENUM_BEGIN);
+        for(j = 0; j < nvram_total_num_ota_by_op_lid;j++)
+        {
+            fprintf(ota_lid_list_hdl, "    %s,    \n", nvram_ota_by_op_lid_str_point[j]);
+        }
+        fprintf(ota_lid_list_hdl, R_F_MCF_ENUM_END, "LID", "nvram_mcf_ota_by_operator_lid");
+        fprintf(ota_lid_list_hdl, "#endif\n");
+        fclose(ota_lid_list_hdl);
+    }
+}
+
+
+/*****************************************************************************
+* FUNCTION
+*  main
+* DESCRIPTION
+*  main function.
+* PARAMETERS
+*  None
+* RETURNS
+*  None
+*****************************************************************************/
+int main(int argc, char *argv[])
+{
+
+#ifndef NVRAM_NOT_PRESENT
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+
+    if (argc > 0)
+    {
+        
+        typedef void (*_indirect_init_func)(void);
+        extern unsigned char indirect_init_begin, indirect_init_end;
+        extern void fs_quota_init(void);
+
+        kal_uint32 *value = (kal_uint32 *)&indirect_init_begin;
+        kal_uint32 i, total = (kal_uint32)(&indirect_init_end - &indirect_init_begin)/sizeof(_indirect_init_func);
+
+        printf("begin:%x, end:%x\n", &indirect_init_begin, &indirect_init_end);
+        printf("init_func = %x, total = %d\n", *value, total);
+        for (i = 0; i < total; i++)
+        {
+            _indirect_init_func init_func = (_indirect_init_func)*value + i ;
+
+            printf("init_func[%i] = %x\n", i, init_func);    
+            if (init_func)
+            {
+                init_func();
+            }
+        }
+
+        printf("argv[1] = %s, argv[2] = %s\n", argv[1], argv[2]);
+
+        if (strcasecmp(argv[1], "MSWin32") == 0)
+        {
+            sprintf(indirect_end_symbol, "_indirect_init_end = .");
+        }
+        else
+        {
+            sprintf(indirect_end_symbol, "indirect_init_end = .");
+        }
+
+
+        printf("nvram_gen_construct_ltable\n");
+        nvram_gen_construct_ltable();
+
+        sprintf(base_path, "%s", argv[1]);
+
+        printf("nvram_fix_lid_size\n");
+        nvram_fix_lid_size();
+        #if defined(__NVRAM_LID_CACHE__)
+		printf("nvram construct cache info table\n");
+		cache_info_table_generator(base_path);
+		#endif
+
+        #if defined(__NV_CHKSUM_ENHANCE__)
+        chksum_algo_config_generator(base_path);
+        #endif
+        
+        printf("nvram_default_value_check\n");
+        nvram_default_value_check();
+		
+    #ifndef __VENDOR_RELEASE__
+        printf("nvram_gen_trace\n");
+        nvram_gen_trace();
+    #endif
+
+        printf("nvram_gen_cat_xml\n");
+        nvram_gen_cat_xml();
+
+        printf("nvram_gen_lid_size\n");
+        nvram_gen_lid_size();
+
+        printf("nvram_gen_statistic\n");
+        nvram_gen_statistic();
+
+        printf("nvram_gen_restore_function\n");
+        nvram_gen_restore_function();
+
+    #if !defined(__L1_STANDALONE__) && defined(__MMI_FMI__)
+        printf("nvram_gen_custpack_table\n");
+        nvram_gen_custpack_table();
+    #endif
+
+    #ifndef __VENDOR_RELEASE__
+        printf("nvram_gen_secro\n");
+        nvram_gen_secro();
+    #endif
+    
+    #if !defined(__VENDOR_RELEASE__)
+        printf("nvram_gen_database_key\n");
+        nvram_gen_database_key();
+    #endif
+
+        printf("nvram_gen_fs_quota: begin\n");
+        nvram_gen_fs_quota(base_path);
+        printf("nvram_gen_fs_quota: end\n");
+
+        printf("build time check: begin\n");
+        printf("build time check: lid enum overlapping\n");
+        nvram_gen_check_lid_enum_overlapping();
+        //printf("build time check: multiple attr white list\n");
+        //nvram_gen_check_multiple_attr_white_list();
+        printf("build time check: write protect attr white list\n");
+        nvram_gen_check_write_protect_attr_white_list();
+        printf("build time check: cate attr confilicts\n");
+        nvram_gen_check_cate_attr_confilicts();
+        printf("build time check: special lid parameter\n");
+        nvram_gen_check_special_lid_parameter();
+        printf("build time check: end\n");
+
+        nvram_gen_ltable_list();
+        nvram_gen_mcf_ota_lid_list();
+
+       
+    
+    }
+    return 0;
+#else
+    printf("NVRAM_NOT_PRESENT\n");
+    return 0;
+#endif
+}
diff --git a/mcu/tools/NVRAMStatistic/src/nvram_auto_gen.txt b/mcu/tools/NVRAMStatistic/src/nvram_auto_gen.txt
new file mode 100644
index 0000000..ccf5661
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/src/nvram_auto_gen.txt
@@ -0,0 +1,121 @@
+OUTPUT_FORMAT(pei-i386)

+SEARCH_DIR("/mingw/mingw32/lib"); SEARCH_DIR("/mingw/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib");

+ENTRY(_mainCRTStartup)

+SECTIONS

+{

+  .text  __image_base__ + __section_alignment__  :

+  {

+     *(.init)

+    *(.text)

+    *(SORT(.text$*))

+    *(.glue_7t)

+    *(.glue_7)

+     ___CTOR_LIST__ = .; __CTOR_LIST__ = . ;

+			LONG (-1); *(SORT(.ctors.*)); *(.ctors); *(.ctor); LONG (0);

+     ___DTOR_LIST__ = .; __DTOR_LIST__ = . ;

+			LONG (-1); *(SORT(.dtors.*)); *(.dtors); *(.dtor);  LONG (0);

+     *(.fini)

+    /* ??? Why is .gcc_exc here?  */

+     *(.gcc_exc)

+     etext = .;

+    *(.gcc_except_table)

+  }

+  /* The Cygwin32 library uses a section to avoid copying certain data

+     on fork.  This used to be named ".data".  The linker used

+     to include this between __data_start__ and __data_end__, but that

+     breaks building the cygwin32 dll.  Instead, we name the section

+     ".data_cygwin_nocopy" and explictly include it after __data_end__. */

+  .data BLOCK(__section_alignment__) :

+  {

+    __data_start__ = . ;

+    *(.data)

+    *(.data2)

+    *(SORT(.data$*))

+    __data_end__ = . ;

+    *(.data_cygwin_nocopy)

+  }

+  .rdata BLOCK(__section_alignment__) :

+  {

+    *(.rdata)

+    *(SORT(.rdata$*))

+    *(.eh_frame)

+    ___RUNTIME_PSEUDO_RELOC_LIST__ = .;

+    __RUNTIME_PSEUDO_RELOC_LIST__ = .;

+    *(.rdata_runtime_pseudo_reloc)

+    ___RUNTIME_PSEUDO_RELOC_LIST_END__ = .;

+    __RUNTIME_PSEUDO_RELOC_LIST_END__ = .;

+  }

+  .pdata BLOCK(__section_alignment__) :

+  {

+    *(.pdata)

+  }

+  .bss BLOCK(__section_alignment__) :

+  {

+    __bss_start__ = . ;

+    *(.bss)

+    *(COMMON)

+    __bss_end__ = . ;

+  }

+  .edata BLOCK(__section_alignment__) :

+  {

+    *(.edata)

+  }

+  /DISCARD/ :

+  {

+    *(.debug$S)

+    *(.debug$T)

+    *(.debug$F)

+    *(.drectve)

+  }

+  .idata BLOCK(__section_alignment__) :

+  {

+    /* This cannot currently be handled with grouped sections.

+	See pe.em:sort_sections.  */

+    SORT(*)(.idata$2)

+    SORT(*)(.idata$3)

+    /* These zeroes mark the end of the import list.  */

+    LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);

+    SORT(*)(.idata$4)

+    SORT(*)(.idata$5)

+    SORT(*)(.idata$6)

+    SORT(*)(.idata$7)

+  }

+  .CRT BLOCK(__section_alignment__) :

+  {

+    *(SORT(.CRT$*))

+  }

+  .endjunk BLOCK(__section_alignment__) :

+  {

+    /* end is deprecated, don't use it */

+     end = .;

+     _end = .;

+     __end__ = .;

+  }

+  .rsrc BLOCK(__section_alignment__) :

+  {

+    *(.rsrc)

+    *(SORT(.rsrc$*))

+  }

+  .reloc BLOCK(__section_alignment__) :

+  {

+    *(.reloc)

+  }

+  .stab BLOCK(__section_alignment__) (NOLOAD) :

+  {

+    [ .stab ]

+  }

+  .stabstr BLOCK(__section_alignment__) (NOLOAD) :

+  {

+    [ .stabstr ]

+  }

+

+  NVRAM_LTABLE :

+  {

+    _nvram_ltable_begin = .;

+  	*(_nvram_ltable)

+    _nvram_ltable_end = .;

+    _indirect_init_begin = .;

+    *(_indirect_init)

+    _indirect_init_end = .;

+  }

+}

diff --git a/mcu/tools/NVRAMStatistic/src/nvram_auto_gen_TARGET.c b/mcu/tools/NVRAMStatistic/src/nvram_auto_gen_TARGET.c
new file mode 100644
index 0000000..ae4e4cf
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/src/nvram_auto_gen_TARGET.c
@@ -0,0 +1,473 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2006
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ * nvram_auto_gen_TARGET.c
+ *
+ * Project:
+ * --------
+ *   UMOLYA
+ *
+ * Description:
+ * ------------
+ *   This file is intends for generating NVRAM ltable information. Not for execute.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+
+/*****************************************************************************
+* Include
+*****************************************************************************/
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stddef.h>
+
+#include "nvram_auto_gen.h"
+#include "custom_nvram_config.h"
+#include "nvram_editor_data_item.h"
+#include "nvram_data_items.h"
+
+#if defined(__MMI_FMI__)
+#include "nvram_user_defs.h"
+#endif
+
+#ifndef __VENDOR_RELEASE__
+#include "custom_nvram_sec.h"
+#endif
+
+/* Add pseudo merge headfile */
+#include "nvram_pseudo_merge.h"
+
+#include "nvram_internal.h"
+
+#include "nvram_white_list.h"
+#ifdef  __NVRAM_AUTOGEN_V2__
+#include "nvram_lid_stu_tmp.h"
+#endif
+
+
+typedef struct  {
+    kal_uint8 test;
+	kal_uint16 test2;
+}nvram_padding_structure2; 
+typedef struct  {
+    nvram_padding_structure2 test[3];
+}nvram_padding_structure; 
+
+kal_char const nvram_long_length[sizeof(long)] = {0};
+kal_char const nvram_ptr_length[sizeof(char*)] = {0};
+kal_char const nvram_padding_length[sizeof(nvram_padding_structure)] = {0};
+kal_char const nvram_ltable_entry_length[sizeof(nvram_ltable_entry_struct)] = {0};
+
+kal_uint32 nvram_ltable_entry_size = sizeof(nvram_ltable_entry_struct);
+kal_uint16 ent_oft_lid = offsetof(nvram_ltable_entry_struct, LID);
+kal_uint16 ent_oft_trecords = offsetof(nvram_ltable_entry_struct, total_records);
+kal_uint16 ent_oft_size = offsetof(nvram_ltable_entry_struct, size);
+kal_uint16 ent_oft_str_dval = offsetof(nvram_ltable_entry_struct, str_default_value);
+kal_uint16 ent_oft_d_val = offsetof(nvram_ltable_entry_struct, default_value);
+kal_uint16 ent_oft_cate = offsetof(nvram_ltable_entry_struct, category);
+kal_uint16 ent_oft_attr = offsetof(nvram_ltable_entry_struct, attr);
+kal_uint16 ent_oft_fprefix = offsetof(nvram_ltable_entry_struct, fileprefix);
+kal_uint16 ent_oft_fverno = offsetof(nvram_ltable_entry_struct, fileverno);
+kal_uint16 ent_oft_s_lid = offsetof(nvram_ltable_entry_struct, str_LID);
+kal_uint16 ent_oft_desc = offsetof(nvram_ltable_entry_struct, description);
+
+#if(defined(__NVRAM_LID_HASH_CHECK__) && defined(__MTK_INTERNAL__))
+kal_uint16 ent_oft_hash = offsetof(nvram_ltable_entry_struct, hash_key);
+#endif
+
+#if defined (__NVRAM_UT_TEST__)
+kal_uint8 NVRAM_EF_TEST_8_DEFAULT[NVRAM_EF_TEST_8_LID_RECORD_TOTAL][NVRAM_EF_TEST_8_LID_SIZE] = {
+    {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08},
+    {0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18},
+    {0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28},
+};
+#endif
+
+
+// =============internal ltable ======================
+
+ltable_entry_struct logical_data_item_table_internal[] =
+{
+    {
+        NVRAM_EF_SYS_LID,
+        NVRAM_EF_SYS_TOTAL,
+        NVRAM_EF_SYS_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_FF_DEFAULT),
+        NVRAM_CATEGORY_IMPORTANT_L1 ,
+        NVRAM_ATTR_WRITEPROTECT | NVRAM_ATTR_MULTIPLE ,
+        "MT00",
+        VER(NVRAM_EF_SYS_LID)
+    },
+
+#ifdef __NVRAM_SUPPORT_CUSTPACK__
+    {
+        NVRAM_EF_CUSTPACK_VERNO_LID,
+        NVRAM_EF_CUSTPACK_VERNO_TOTAL,
+        NVRAM_EF_CUSTPACK_VERNO_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_INTERNAL,
+        NVRAM_ATTR_WRITEPROTECT | NVRAM_ATTR_AVERAGE,
+        "MT02",
+        VER(NVRAM_EF_CUSTPACK_VERNO_LID)
+    },
+#endif
+    {
+        NVRAM_EF_NVRAM_LOCK_LID,
+        NVRAM_EF_NVRAM_LOCK_TOTAL,
+        NVRAM_EF_NVRAM_LOCK_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_FF_DEFAULT),
+        NVRAM_CATEGORY_IMPORTANT ,
+        NVRAM_ATTR_WRITEPROTECT | NVRAM_ATTR_CONFIDENTIAL | NVRAM_ATTR_FAULT_ASSERT | NVRAM_ATTR_COMMITTED
+        #ifdef __NVRAM_BIND_TO_CHIP_CIPHER__
+         | NVRAM_ATTR_MSP | NVRAM_ATTR_MULTIPLE
+        #endif
+        ,
+        "NV01",
+        VER(NVRAM_EF_NVRAM_LOCK_LID)
+    },
+#ifdef __NVRAM_READ_RESERVED_FILE__    
+    {
+        NVRAM_EF_READ_RESERVED_LID,
+        NVRAM_EF_READ_RESERVED_TOTAL,
+        NVRAM_EF_READ_RESERVED_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_RESERVED,
+        NVRAM_ATTR_AVERAGE,
+        "NONE",
+        VER(NVRAM_EF_READ_RESERVED_LID)
+    }, 
+#endif    
+#ifdef __NVRAM_SEC_CHECK_EN__
+    {
+        NVRAM_EF_NVRAM_SEC_CHECK_LID,
+        NVRAM_EF_NVRAM_SEC_CHECK_TOTAL,
+        NVRAM_EF_NVRAM_SEC_CHECK_SIZE,
+        NVRAM_DEFAULT_FUNC(nvram_get_sec_default_value_to_write),
+        NVRAM_CATEGORY_IMPORTANT | NVRAM_CATEGORY_FUNC_DEFAULT,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_FAULT_ASSERT | NVRAM_ATTR_GEN_DEFAULT | NVRAM_ATTR_MULTI_DEFAULT
+        #if defined (__CCCIFS_SUPPORT__)
+         | NVRAM_ATTR_COMMITTED
+        #endif
+        ,
+        "NV0S",
+        VER(NVRAM_EF_NVRAM_SEC_CHECK_LID)
+    },
+#endif
+#ifdef __NVRAM_UNIT_TEST__
+    {
+        NVRAM_EF_NVRAM_UNIT_TEST_LID,
+        NVRAM_EF_NVRAM_UNIT_TEST_TOTAL,
+        NVRAM_EF_NVRAM_UNIT_TEST_SIZE,
+        NVRAM_NORMAL((const kal_uint8 *)NVRAM_EF_ZERO_DEFAULT),
+#ifdef __SECURE_DATA_STORAGE__
+        NVRAM_CATEGORY_INTERNAL,
+#else
+        NVRAM_CATEGORY_USER,
+#endif
+        NVRAM_ATTR_AVERAGE,
+        "MT10",
+        VER(NVRAM_EF_NVRAM_UNIT_TEST_LID)
+    },
+#endif
+
+#if defined (__NVRAM_UT_TEST__)
+
+    {
+        NVRAM_EF_NVRAM_TEST_1_LID,
+        NVRAM_EF_TEST_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_USER,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_GEN_DEFAULT,
+        "MTT1",
+        VER(NVRAM_EF_NVRAM_TEST_1_LID)
+    },
+
+    {
+        NVRAM_EF_NVRAM_TEST_2_LID,
+        NVRAM_EF_TEST_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_INTERNAL,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_GEN_DEFAULT, 
+        "MTT2",
+        VER(NVRAM_EF_NVRAM_TEST_2_LID)
+    },
+
+    {
+        NVRAM_EF_NVRAM_TEST_3_LID,
+        NVRAM_EF_TEST_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_CALIBRAT,
+        NVRAM_ATTR_AVERAGE,
+        "MTT3",
+        VER(NVRAM_EF_NVRAM_TEST_3_LID)
+    },
+
+    {
+        NVRAM_EF_NVRAM_TEST_4_LID,
+        NVRAM_EF_TEST_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_IMPORTANT,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_GEN_DEFAULT
+        #if defined (__CCCIFS_SUPPORT__)
+         | NVRAM_ATTR_COMMITTED
+        #endif
+        , 
+        "MTT4",
+        VER(NVRAM_EF_NVRAM_TEST_4_LID)
+    },
+
+    {
+        NVRAM_EF_NVRAM_TEST_5_LID,
+        NVRAM_EF_TEST_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_IMPORTANT_L1,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_GEN_DEFAULT,
+        "MTT5",
+        VER(NVRAM_EF_NVRAM_TEST_5_LID)
+    },
+    
+    {
+        NVRAM_EF_NVRAM_TEST_6_LID,
+        NVRAM_EF_TEST_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_IMPORTANT_L4,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_GEN_DEFAULT | NVRAM_ATTR_CHKSUM_INTEGRATE
+        #if defined (__CCCIFS_SUPPORT__)
+         | NVRAM_ATTR_COMMITTED
+        #endif
+        ,
+        "MTT6",
+        VER(NVRAM_EF_NVRAM_TEST_6_LID)
+    },
+
+    {
+        NVRAM_EF_NVRAM_TEST_7_LID,
+        1, //NVRAM_EF_TEST_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_CALIBRAT,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_RAW_DATA,
+        "MTT7",
+        VER(NVRAM_EF_NVRAM_TEST_7_LID)
+    },
+
+    {
+        NVRAM_EF_NVRAM_TEST_8_LID,
+        NVRAM_EF_TEST_8_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_8_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_TEST_8_DEFAULT),
+        NVRAM_CATEGORY_USER,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_MULTI_DEFAULT | NVRAM_ATTR_CHKSUM_INTEGRATE,
+        "MTT8",
+        VER(NVRAM_EF_NVRAM_TEST_8_LID)
+    },
+    {
+        NVRAM_EF_NVRAM_TEST_9_LID,
+        NVRAM_EF_TEST_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_USER,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_GEN_DEFAULT | NVRAM_ATTR_MCF_OTA_FOR_QUERY,
+        "MTT9",
+        VER(NVRAM_EF_NVRAM_TEST_9_LID)
+    },
+    {
+        NVRAM_EF_NVRAM_TEST_10_LID,
+        NVRAM_EF_TEST_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_USER,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_GEN_DEFAULT | NVRAM_ATTR_MCF_OTA_BY_OP,
+        "MTTA",
+        VER(NVRAM_EF_NVRAM_TEST_10_LID)
+    },
+    {
+        NVRAM_EF_NVRAM_TEST_11_LID,
+        NVRAM_EF_TEST_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_USER,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_GEN_DEFAULT | NVRAM_ATTR_MCF_OTA | NVRAM_ATTR_MCF_OTA_BY_OP,
+        "MTTB",
+        VER(NVRAM_EF_NVRAM_TEST_11_LID)
+    },
+    {
+        NVRAM_EF_NVRAM_TEST_12_LID,
+        NVRAM_EF_TEST_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_USER,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_GEN_DEFAULT | NVRAM_ATTR_MCF_OTA,
+        "MTTC",
+        VER(NVRAM_EF_NVRAM_TEST_12_LID)
+    },
+    {
+        NVRAM_EF_INTERNAL_13_LID,
+        NVRAM_EF_TEST_13_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_13_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_IMPORTANT_L1,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_GEN_DEFAULT,
+        "MTTD",
+        VER(NVRAM_EF_INTERNAL_13_LID)
+    },
+    {
+        NVRAM_EF_INTERNAL_TEST_14_LID,
+        NVRAM_EF_TEST_14_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_14_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_USER,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_GEN_DEFAULT,
+        "MTTE",
+        VER(NVRAM_EF_INTERNAL_TEST_14_LID)
+    },
+	{
+        NVRAM_EF_INTERNAL_TEST_16_LID,
+        NVRAM_EF_INTERNAL_TEST_16_LID_RECORD_TOTAL,
+        NVRAM_EF_INTERNAL_TEST_16_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_CALIBRAT,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_CHKSUM_INTEGRATE | NVRAM_ATTR_FAULT_ASSERT,
+        "MTTG",
+        VER(NVRAM_EF_INTERNAL_TEST_16_LID)
+    },
+    {
+        NVRAM_EF_INTERNAL_TEST_17_LID,
+        NVRAM_EF_TEST_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_USER,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_MULTIPLE,
+        "MTTH",
+        VER(NVRAM_EF_INTERNAL_TEST_17_LID)
+    },
+#endif
+
+#if defined(__NVRAM_STRUCTURE_CHANGE_RESET__) || defined(__NVRAM_DEFVAL_CHANGE_RESET__)
+    {
+        NVRAM_EF_CHKSUM_RESET_REC_LID,
+        NVRAM_EF_CHKSUM_RESET_REC_LID_TOTAL,
+        NVRAM_EF_CHKSUM_RESET_REC_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_INTERNAL,
+        NVRAM_ATTR_AVERAGE,
+        "MTCR", //NVRAM check sum reset
+        VER(NVRAM_EF_CHKSUM_RESET_REC_LID)
+    },
+#endif    
+
+};
+
+
+/*****************************************************************************
+* FUNCTION
+*  main
+* DESCRIPTION
+*  main function.
+* PARAMETERS
+*  None
+* RETURNS
+*  None
+*****************************************************************************/
+int main(int argc, char *argv[])
+{
+#ifndef NVRAM_NOT_PRESENT
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    return 0;
+#else
+    return 0;
+#endif
+}
diff --git a/mcu/tools/NVRAMStatistic/src/nvram_auto_gen_TARGET.txt b/mcu/tools/NVRAMStatistic/src/nvram_auto_gen_TARGET.txt
new file mode 100644
index 0000000..935a665
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/src/nvram_auto_gen_TARGET.txt
@@ -0,0 +1,220 @@
+ENTRY(_start)

+SECTIONS

+{

+  /* Read-only sections, merged into text segment: */

+  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = 

+SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;

+

+  .interp         : { *(.interp) }

+  .note.gnu.build-id : { *(.note.gnu.build-id) }

+  .hash           : { *(.hash) }

+  .gnu.hash       : { *(.gnu.hash) }

+  .dynsym         : { *(.dynsym) }

+  .dynstr         : { *(.dynstr) }

+  .gnu.version    : { *(.gnu.version) }

+  .gnu.version_d  : { *(.gnu.version_d) }

+  .gnu.version_r  : { *(.gnu.version_r) }

+  .rela.dyn       :

+    {

+      *(.rela.init)

+      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)

+      *(.rela.fini)

+      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)

+      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)

+      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)

+      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)

+      *(.rela.ctors)

+      *(.rela.dtors)

+      *(.rela.got)

+      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)

+      *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)

+      *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)

+      *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)

+      *(.rela.ifunc)

+    }

+  .rela.plt       :

+    {

+      *(.rela.plt)

+      PROVIDE_HIDDEN (__rela_iplt_start = .);

+      *(.rela.iplt)

+      PROVIDE_HIDDEN (__rela_iplt_end = .);

+    }

+  .init           :

+  {

+    KEEP (*(.init))

+  } =0x90909090

+  .plt            : { *(.plt) *(.iplt) }

+  .text           :

+  {

+    *(.text.unlikely .text.*_unlikely)

+    *(.text .stub .text.* .gnu.linkonce.t.*)

+    /* .gnu.warning sections are handled specially by elf32.em.  */

+    *(.gnu.warning)

+  } =0x90909090

+  .fini           :

+  {

+    KEEP (*(.fini))

+  } =0x90909090

+  PROVIDE (__etext = .);

+  PROVIDE (_etext = .);

+  PROVIDE (etext = .);

+  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }

+  .rodata1        : { *(.rodata1) }

+  .eh_frame_hdr : { *(.eh_frame_hdr) }

+  .eh_frame       : { KEEP (*(.eh_frame)) }

+  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }

+  /* Adjust the address for the data segment.  We want to adjust up to

+     the same address within the page on the next page up.  */

+  . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (

+CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), 

+CONSTANT (COMMONPAGESIZE));

+

+  /* Exception handling  */

+  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }

+  /* Thread Local Storage sections  */

+  .tdata	  : { *(.tdata .tdata.* .gnu.linkonce.td.*) }

+  .tbss		  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }

+  .preinit_array     :

+  {

+    PROVIDE_HIDDEN (__preinit_array_start = .);

+    KEEP (*(.preinit_array))

+    PROVIDE_HIDDEN (__preinit_array_end = .);

+  }

+  .init_array     :

+  {

+     PROVIDE_HIDDEN (__init_array_start = .);

+     KEEP (*(SORT(.init_array.*)))

+     KEEP (*(.init_array))

+     PROVIDE_HIDDEN (__init_array_end = .);

+  }

+  .fini_array     :

+  {

+    PROVIDE_HIDDEN (__fini_array_start = .);

+    KEEP (*(.fini_array))

+    KEEP (*(SORT(.fini_array.*)))

+    PROVIDE_HIDDEN (__fini_array_end = .);

+  }

+  .ctors          :

+  {

+    /* gcc uses crtbegin.o to find the start of

+       the constructors, so we make sure it is

+       first.  Because this is a wildcard, it

+       doesn't matter if the user does not

+       actually link against crtbegin.o; the

+       linker won't look for a file to match a

+       wildcard.  The wildcard also means that it

+       doesn't matter which directory crtbegin.o

+       is in.  */

+    KEEP (*crtbegin.o(.ctors))

+    KEEP (*crtbegin?.o(.ctors))

+    /* We don't want to include the .ctor section from

+       the crtend.o file until after the sorted ctors.

+       The .ctor section from the crtend file contains the

+       end of ctors marker and it must be last */

+    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))

+    KEEP (*(SORT(.ctors.*)))

+    KEEP (*(.ctors))

+  }

+  .dtors          :

+  {

+    KEEP (*crtbegin.o(.dtors))

+    KEEP (*crtbegin?.o(.dtors))

+    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))

+    KEEP (*(SORT(.dtors.*)))

+    KEEP (*(.dtors))

+  }

+  .jcr            : { KEEP (*(.jcr)) }

+  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.

+data.rel.ro* .gnu.linkonce.d.rel.ro.*) }

+

+  .dynamic        : { *(.dynamic) }

+  .got            : { *(.got) *(.igot) }

+  . = DATA_SEGMENT_RELRO_END (24, .);

+  .got.plt        : { *(.got.plt)  *(.igot.plt) }

+  .data           :

+  {

+    *(.data .data.* .gnu.linkonce.d.*)

+    SORT(CONSTRUCTORS)

+  }

+  .data1          : { *(.data1) }

+  _edata = .; PROVIDE (edata = .);

+  __bss_start = .;

+  .bss            :

+  {

+   *(.dynbss)

+   *(.bss .bss.* .gnu.linkonce.b.*)

+   *(COMMON)

+   /* Align here to ensure that the .bss section occupies space up to

+      _end.  Align after .bss to ensure correct alignment even if the

+      .bss section disappears because there are no input sections.

+      FIXME: Why do we need it? When there is no .bss section, we don't

+      pad the .data section.  */

+   . = ALIGN(. != 0 ? 64 / 8 : 1);

+  }

+  .lbss   :

+  {

+    *(.dynlbss)

+    *(.lbss .lbss.* .gnu.linkonce.lb.*)

+    *(LARGE_COMMON)

+  }

+  NVRAM_LTABLE :

+  { nvram_ltable_begin = .;

+  	*(_nvram_ltable) nvram_ltable_end = .;

+    indirect_init_begin = .;

+    *(_indirect_init)

+    indirect_init_end = .; } 

+  . = ALIGN(64 / 8);

+  .lrodata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)

+) :

+

+  {

+    *(.lrodata .lrodata.* .gnu.linkonce.lr.*)

+  }

+  .ldata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :

+  {

+    *(.ldata .ldata.* .gnu.linkonce.l.*)

+    . = ALIGN(. != 0 ? 64 / 8 : 1);

+  }

+  . = ALIGN(64 / 8);

+  _end = .; PROVIDE (end = .);

+  . = DATA_SEGMENT_END (.);

+  /* Stabs debugging sections.  */

+  .stab          0 : { *(.stab) }

+  .stabstr       0 : { *(.stabstr) }

+  .stab.excl     0 : { *(.stab.excl) }

+  .stab.exclstr  0 : { *(.stab.exclstr) }

+  .stab.index    0 : { *(.stab.index) }

+  .stab.indexstr 0 : { *(.stab.indexstr) }

+  .comment       0 : { *(.comment) }

+  /* DWARF debug sections.

+     Symbols in the DWARF debugging sections are relative to the beginning

+     of the section so we begin them at 0.  */

+  /* DWARF 1 */

+  .debug          0 : { *(.debug) }

+  .line           0 : { *(.line) }

+  /* GNU DWARF 1 extensions */

+  .debug_srcinfo  0 : { *(.debug_srcinfo) }

+  .debug_sfnames  0 : { *(.debug_sfnames) }

+  /* DWARF 1.1 and DWARF 2 */

+  .debug_aranges  0 : { *(.debug_aranges) }

+  .debug_pubnames 0 : { *(.debug_pubnames) }

+  /* DWARF 2 */

+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }

+  .debug_abbrev   0 : { *(.debug_abbrev) }

+  .debug_line     0 : { *(.debug_line) }

+  .debug_frame    0 : { *(.debug_frame) }

+  .debug_str      0 : { *(.debug_str) }

+  .debug_loc      0 : { *(.debug_loc) }

+  .debug_macinfo  0 : { *(.debug_macinfo) }

+  /* SGI/MIPS DWARF 2 extensions */

+  .debug_weaknames 0 : { *(.debug_weaknames) }

+  .debug_funcnames 0 : { *(.debug_funcnames) }

+  .debug_typenames 0 : { *(.debug_typenames) }

+  .debug_varnames  0 : { *(.debug_varnames) }

+  /* DWARF 3 */

+  .debug_pubtypes 0 : { *(.debug_pubtypes) }

+  .debug_ranges   0 : { *(.debug_ranges) }

+  .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }

+  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }

+

+}

diff --git a/mcu/tools/NVRAMStatistic/src/nvram_auto_gen_linux.txt b/mcu/tools/NVRAMStatistic/src/nvram_auto_gen_linux.txt
new file mode 100644
index 0000000..c128761
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/src/nvram_auto_gen_linux.txt
@@ -0,0 +1,229 @@
+OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",

+	      "elf64-x86-64")

+OUTPUT_ARCH(i386:x86-64)

+ENTRY(_start)

+SEARCH_DIR("/usr/x86_64-linux-gnu/lib64"); SEARCH_DIR("/usr/local/lib64"); 

+SEARCH_DIR("/lib64"); SEARCH_DIR("/usr/lib64"); SEARCH_DIR("/usr/x86_64-linux-

+gnu/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/

+lib");

+

+SECTIONS

+{

+  /* Read-only sections, merged into text segment: */

+  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = 

+SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;

+

+  .interp         : { *(.interp) }

+  .note.gnu.build-id : { *(.note.gnu.build-id) }

+  .hash           : { *(.hash) }

+  .gnu.hash       : { *(.gnu.hash) }

+  .dynsym         : { *(.dynsym) }

+  .dynstr         : { *(.dynstr) }

+  .gnu.version    : { *(.gnu.version) }

+  .gnu.version_d  : { *(.gnu.version_d) }

+  .gnu.version_r  : { *(.gnu.version_r) }

+  .rela.dyn       :

+    {

+      *(.rela.init)

+      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)

+      *(.rela.fini)

+      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)

+      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)

+      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)

+      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)

+      *(.rela.ctors)

+      *(.rela.dtors)

+      *(.rela.got)

+      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)

+      *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)

+      *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)

+      *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)

+      *(.rela.ifunc)

+    }

+  .rela.plt       :

+    {

+      *(.rela.plt)

+      PROVIDE_HIDDEN (__rela_iplt_start = .);

+      *(.rela.iplt)

+      PROVIDE_HIDDEN (__rela_iplt_end = .);

+    }

+  .init           :

+  {

+    KEEP (*(.init))

+  } =0x90909090

+  .plt            : { *(.plt) *(.iplt) }

+  .text           :

+  {

+    *(.text.unlikely .text.*_unlikely)

+    *(.text .stub .text.* .gnu.linkonce.t.*)

+    /* .gnu.warning sections are handled specially by elf32.em.  */

+    *(.gnu.warning)

+  } =0x90909090

+  .fini           :

+  {

+    KEEP (*(.fini))

+  } =0x90909090

+  PROVIDE (__etext = .);

+  PROVIDE (_etext = .);

+  PROVIDE (etext = .);

+  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }

+  .rodata1        : { *(.rodata1) }

+  .eh_frame_hdr : { *(.eh_frame_hdr) }

+  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }

+  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }

+  /* Adjust the address for the data segment.  We want to adjust up to

+     the same address within the page on the next page up.  */

+  . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (

+CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), 

+CONSTANT (COMMONPAGESIZE));

+

+  /* Exception handling  */

+  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }

+  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }

+  /* Thread Local Storage sections  */

+  .tdata	  : { *(.tdata .tdata.* .gnu.linkonce.td.*) }

+  .tbss		  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }

+  .preinit_array     :

+  {

+    PROVIDE_HIDDEN (__preinit_array_start = .);

+    KEEP (*(.preinit_array))

+    PROVIDE_HIDDEN (__preinit_array_end = .);

+  }

+  .init_array     :

+  {

+     PROVIDE_HIDDEN (__init_array_start = .);

+     KEEP (*(SORT(.init_array.*)))

+     KEEP (*(.init_array))

+     PROVIDE_HIDDEN (__init_array_end = .);

+  }

+  .fini_array     :

+  {

+    PROVIDE_HIDDEN (__fini_array_start = .);

+    KEEP (*(.fini_array))

+    KEEP (*(SORT(.fini_array.*)))

+    PROVIDE_HIDDEN (__fini_array_end = .);

+  }

+  .ctors          :

+  {

+    /* gcc uses crtbegin.o to find the start of

+       the constructors, so we make sure it is

+       first.  Because this is a wildcard, it

+       doesn't matter if the user does not

+       actually link against crtbegin.o; the

+       linker won't look for a file to match a

+       wildcard.  The wildcard also means that it

+       doesn't matter which directory crtbegin.o

+       is in.  */

+    KEEP (*crtbegin.o(.ctors))

+    KEEP (*crtbegin?.o(.ctors))

+    /* We don't want to include the .ctor section from

+       the crtend.o file until after the sorted ctors.

+       The .ctor section from the crtend file contains the

+       end of ctors marker and it must be last */

+    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))

+    KEEP (*(SORT(.ctors.*)))

+    KEEP (*(.ctors))

+  }

+  .dtors          :

+  {

+    KEEP (*crtbegin.o(.dtors))

+    KEEP (*crtbegin?.o(.dtors))

+    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))

+    KEEP (*(SORT(.dtors.*)))

+    KEEP (*(.dtors))

+  }

+  .jcr            : { KEEP (*(.jcr)) }

+  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.

+data.rel.ro* .gnu.linkonce.d.rel.ro.*) }

+

+  .dynamic        : { *(.dynamic) }

+  .got            : { *(.got) *(.igot) }

+  . = DATA_SEGMENT_RELRO_END (24, .);

+  .got.plt        : { *(.got.plt)  *(.igot.plt) }

+  .data           :

+  {

+    *(.data .data.* .gnu.linkonce.d.*)

+    SORT(CONSTRUCTORS)

+  }

+  .data1          : { *(.data1) }

+  _edata = .; PROVIDE (edata = .);

+  __bss_start = .;

+  .bss            :

+  {

+   *(.dynbss)

+   *(.bss .bss.* .gnu.linkonce.b.*)

+   *(COMMON)

+   /* Align here to ensure that the .bss section occupies space up to

+      _end.  Align after .bss to ensure correct alignment even if the

+      .bss section disappears because there are no input sections.

+      FIXME: Why do we need it? When there is no .bss section, we don't

+      pad the .data section.  */

+   . = ALIGN(. != 0 ? 64 / 8 : 1);

+  }

+  .lbss   :

+  {

+    *(.dynlbss)

+    *(.lbss .lbss.* .gnu.linkonce.lb.*)

+    *(LARGE_COMMON)

+  }

+  NVRAM_LTABLE :

+  { nvram_ltable_begin = .;

+  	*(_nvram_ltable) nvram_ltable_end = .;

+    indirect_init_begin = .;

+    *(_indirect_init)

+    indirect_init_end = .; } 

+  . = ALIGN(64 / 8);

+  .lrodata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)

+) :

+

+  {

+    *(.lrodata .lrodata.* .gnu.linkonce.lr.*)

+  }

+  .ldata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :

+  {

+    *(.ldata .ldata.* .gnu.linkonce.l.*)

+    . = ALIGN(. != 0 ? 64 / 8 : 1);

+  }

+  . = ALIGN(64 / 8);

+  _end = .; PROVIDE (end = .);

+  . = DATA_SEGMENT_END (.);

+  /* Stabs debugging sections.  */

+  .stab          0 : { *(.stab) }

+  .stabstr       0 : { *(.stabstr) }

+  .stab.excl     0 : { *(.stab.excl) }

+  .stab.exclstr  0 : { *(.stab.exclstr) }

+  .stab.index    0 : { *(.stab.index) }

+  .stab.indexstr 0 : { *(.stab.indexstr) }

+  .comment       0 : { *(.comment) }

+  /* DWARF debug sections.

+     Symbols in the DWARF debugging sections are relative to the beginning

+     of the section so we begin them at 0.  */

+  /* DWARF 1 */

+  .debug          0 : { *(.debug) }

+  .line           0 : { *(.line) }

+  /* GNU DWARF 1 extensions */

+  .debug_srcinfo  0 : { *(.debug_srcinfo) }

+  .debug_sfnames  0 : { *(.debug_sfnames) }

+  /* DWARF 1.1 and DWARF 2 */

+  .debug_aranges  0 : { *(.debug_aranges) }

+  .debug_pubnames 0 : { *(.debug_pubnames) }

+  /* DWARF 2 */

+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }

+  .debug_abbrev   0 : { *(.debug_abbrev) }

+  .debug_line     0 : { *(.debug_line) }

+  .debug_frame    0 : { *(.debug_frame) }

+  .debug_str      0 : { *(.debug_str) }

+  .debug_loc      0 : { *(.debug_loc) }

+  .debug_macinfo  0 : { *(.debug_macinfo) }

+  /* SGI/MIPS DWARF 2 extensions */

+  .debug_weaknames 0 : { *(.debug_weaknames) }

+  .debug_funcnames 0 : { *(.debug_funcnames) }

+  .debug_typenames 0 : { *(.debug_typenames) }

+  .debug_varnames  0 : { *(.debug_varnames) }

+  /* DWARF 3 */

+  .debug_pubtypes 0 : { *(.debug_pubtypes) }

+  .debug_ranges   0 : { *(.debug_ranges) }

+  .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }

+  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }

+

+}

diff --git a/mcu/tools/NVRAMStatistic/src/nvram_auto_gen_windows.txt b/mcu/tools/NVRAMStatistic/src/nvram_auto_gen_windows.txt
new file mode 100644
index 0000000..ccf5661
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/src/nvram_auto_gen_windows.txt
@@ -0,0 +1,121 @@
+OUTPUT_FORMAT(pei-i386)

+SEARCH_DIR("/mingw/mingw32/lib"); SEARCH_DIR("/mingw/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib");

+ENTRY(_mainCRTStartup)

+SECTIONS

+{

+  .text  __image_base__ + __section_alignment__  :

+  {

+     *(.init)

+    *(.text)

+    *(SORT(.text$*))

+    *(.glue_7t)

+    *(.glue_7)

+     ___CTOR_LIST__ = .; __CTOR_LIST__ = . ;

+			LONG (-1); *(SORT(.ctors.*)); *(.ctors); *(.ctor); LONG (0);

+     ___DTOR_LIST__ = .; __DTOR_LIST__ = . ;

+			LONG (-1); *(SORT(.dtors.*)); *(.dtors); *(.dtor);  LONG (0);

+     *(.fini)

+    /* ??? Why is .gcc_exc here?  */

+     *(.gcc_exc)

+     etext = .;

+    *(.gcc_except_table)

+  }

+  /* The Cygwin32 library uses a section to avoid copying certain data

+     on fork.  This used to be named ".data".  The linker used

+     to include this between __data_start__ and __data_end__, but that

+     breaks building the cygwin32 dll.  Instead, we name the section

+     ".data_cygwin_nocopy" and explictly include it after __data_end__. */

+  .data BLOCK(__section_alignment__) :

+  {

+    __data_start__ = . ;

+    *(.data)

+    *(.data2)

+    *(SORT(.data$*))

+    __data_end__ = . ;

+    *(.data_cygwin_nocopy)

+  }

+  .rdata BLOCK(__section_alignment__) :

+  {

+    *(.rdata)

+    *(SORT(.rdata$*))

+    *(.eh_frame)

+    ___RUNTIME_PSEUDO_RELOC_LIST__ = .;

+    __RUNTIME_PSEUDO_RELOC_LIST__ = .;

+    *(.rdata_runtime_pseudo_reloc)

+    ___RUNTIME_PSEUDO_RELOC_LIST_END__ = .;

+    __RUNTIME_PSEUDO_RELOC_LIST_END__ = .;

+  }

+  .pdata BLOCK(__section_alignment__) :

+  {

+    *(.pdata)

+  }

+  .bss BLOCK(__section_alignment__) :

+  {

+    __bss_start__ = . ;

+    *(.bss)

+    *(COMMON)

+    __bss_end__ = . ;

+  }

+  .edata BLOCK(__section_alignment__) :

+  {

+    *(.edata)

+  }

+  /DISCARD/ :

+  {

+    *(.debug$S)

+    *(.debug$T)

+    *(.debug$F)

+    *(.drectve)

+  }

+  .idata BLOCK(__section_alignment__) :

+  {

+    /* This cannot currently be handled with grouped sections.

+	See pe.em:sort_sections.  */

+    SORT(*)(.idata$2)

+    SORT(*)(.idata$3)

+    /* These zeroes mark the end of the import list.  */

+    LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);

+    SORT(*)(.idata$4)

+    SORT(*)(.idata$5)

+    SORT(*)(.idata$6)

+    SORT(*)(.idata$7)

+  }

+  .CRT BLOCK(__section_alignment__) :

+  {

+    *(SORT(.CRT$*))

+  }

+  .endjunk BLOCK(__section_alignment__) :

+  {

+    /* end is deprecated, don't use it */

+     end = .;

+     _end = .;

+     __end__ = .;

+  }

+  .rsrc BLOCK(__section_alignment__) :

+  {

+    *(.rsrc)

+    *(SORT(.rsrc$*))

+  }

+  .reloc BLOCK(__section_alignment__) :

+  {

+    *(.reloc)

+  }

+  .stab BLOCK(__section_alignment__) (NOLOAD) :

+  {

+    [ .stab ]

+  }

+  .stabstr BLOCK(__section_alignment__) (NOLOAD) :

+  {

+    [ .stabstr ]

+  }

+

+  NVRAM_LTABLE :

+  {

+    _nvram_ltable_begin = .;

+  	*(_nvram_ltable)

+    _nvram_ltable_end = .;

+    _indirect_init_begin = .;

+    *(_indirect_init)

+    _indirect_init_end = .;

+  }

+}

diff --git a/mcu/tools/NVRAMStatistic/src/nvram_compress.c b/mcu/tools/NVRAMStatistic/src/nvram_compress.c
new file mode 100644
index 0000000..ad08a84
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/src/nvram_compress.c
@@ -0,0 +1,1521 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ *  nvram_compress.c
+ *
+ * Project:
+ * -------- 
+ *  MAUI
+ *
+ * Description:
+ * ------------
+ *  compress nvram default value.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <io.h>
+
+#ifdef __NVRAM_COMPRESS_SUPPORT__
+/*****************************************************************************
+ * Header file
+ *****************************************************************************/
+#include "nvram_auto_gen.h"
+
+#include "zlib.h"
+
+#if defined(__MMI_FMI__)
+#include "custom_mmi_default_value.h"
+#include "nvram_user_defs.h"
+#endif
+
+/*****************************************************************************
+ * Typedef
+ *****************************************************************************/
+#define RESULT_HEADER_PATH                      "..\\..\\..\\custom\\common\\pluto_mmi\\nvram_default_value.h"
+#define RESULT_SRC_PATH                         "..\\..\\..\\custom\\common\\pluto_mmi\\nvram_default_value.c"
+#define CUSTPACK_PATH                           "..\\..\\..\\custom\\common\\pluto_mmi\\nvram_cust_pack_default_value.c"
+#define COMPRESS_REPORT_FILE                    "..\\..\\..\\~nvram_compress.txt"
+
+#define CUSTPACK_FILE_INCLUDE                   "\n#include \"kal_release.h\"\n#include \"nvram_defs.h\"\n"
+
+#define FILE_HEADER                             "\/* \nThis file is generated by nvram auto gen, all modification will be lost, \n Author: Wen Wu(MTK80153)\n *\/"
+#define FILE_INCLUDE                            "\n#include \"kal_general_types.h\"\n"
+#define FILE_COMPILE_OPTION_START               "\n#ifdef __NVRAM_COMPRESS_SUPPORT__\n"
+#define FILE_COMPILE_OPTION_END                 "\n#endif\n\n"
+#define CUSTPACK_FILE_COMPILE_OPTION_START      "\n#ifdef NVRAM_INTERNAL_USE\n#ifdef __NVRAM_COMPRESS_SUPPORT__\n"
+#define CUSTPACK_FILE_COMPILE_OPTION_END        "\n#endif\n#endif\n\n"
+
+#define VALUE_MACRO_START                       "\n#ifndef __NVRAM_DEFAULT_VALUE_H__\n#define __NVRAM_DEFAULT_VALUE_H__\n"
+#define VALUE_MACRO_END                         "\n#endif\n\n"
+
+#define VALUE_START                             "\nconst kal_uint8 %s_ZIP[%d] =\n"
+#define VALUE_BRACE                             "{"
+#define VALUE_END                               "\n};\n"
+
+#define VALUE_EXTERN                            "\nextern const kal_uint8 %s_ZIP[];\n"
+#define VALUE_REDEFINE                          "\n#define %s_ZIP %s\n"
+#define VAR_TABLE_ENTRY                         "\t{%s,%d,%d},\n"
+
+#define VALUE_MAX_SIZE                          "\n#define NVRAM_MAX_DEFAULE_VALUE_SIZE %d\n"
+
+#define BUFFER_FOR_LEN 4
+
+/* High trace will exist current env */
+#define NVRAM_TRC_HIGH(x)           { printf(x); exit(3);}
+#define NVRAM_TRC_HIGH1(x,y)        { printf(x,y); exit(3);}
+#define NVRAM_TRC_LOW(x)            { printf(x);}
+#define NVRAM_TRC_LOW1(xx, x)       { printf(xx,x);}
+#define NVRAM_TRC_LOW2(xx, x, y)    { printf(xx, x, y);}
+
+#define RETURN_IF_FAIL(p)           if(!(p)){printf("NVRAM abormal return at line %d\n", __LINE__);return;}
+#define RETURN_VAL_IF_FAIL(p, ret)  if(!(p)){ printf("NVRAM return fail at line %d\n", __LINE__); return (ret);}
+
+#define NVRAM_MALLOC(size)          malloc(size)
+#define NVRAM_MFREE(p)              if(!p) {free(p); p = NULL;}
+
+#define NVRAM_MEM_FACTOR1 10
+#define NVRAM_MEM_FACTOR2 50
+
+#define NVRAM_TEMP_BUFFER_SIZE 512
+#define NVRAM_ZLIB_BUFF_SIZE (80*1024)
+
+/*
+ *  conv between unsigned char to unsigned int
+ */
+#define CONV_4BYTES_TO_INT(b, i) (i = ((b[0] << 24) + (b[1] << 16) + (b[2] << 8) + b[3]))
+#define CONV_INT_TO_4BYTES(b, i) \
+            b[0] = (kal_uint8)(i >> 24); \
+            b[1] = (kal_uint8)(i >> 16); \
+            b[2] = (kal_uint8)(i >> 8); \
+            b[3] = (kal_uint8)i;
+
+
+/*****************************************************************************
+ * define
+ *****************************************************************************/
+typedef enum{
+    RET_OK,
+    RET_STOP,
+    RET_OOM,
+    RET_TOTAL
+}Ret;
+
+typedef kal_int32 (*compress_funcptr)(kal_uint8 *dest, kal_uint32 *destLen,const kal_uint8 *source, kal_uint32 sourceLen, kal_int32 level);
+typedef kal_int32 (*uncompress_funcptr)(kal_uint8 *dest, kal_uint32 *destLen, const kal_uint8 *source, kal_uint32 sourceLen);
+typedef Ret (*visit_funcptr)(void *data, void* usr_data);
+
+
+typedef struct _NvramCompress
+{
+    compress_funcptr onCompress;
+    uncompress_funcptr onUncompress;
+    kal_uint32 count;
+    kal_uint32 org_total_size;
+    kal_uint32 compress_total_size;
+    kal_uint32 max_default_value;
+    kal_uint32 last_custpack;
+    kal_uint32 custpack_index;
+    kal_uint32 custpack_total;
+    FILE *result_src_fp;
+    FILE *custpack_fp;
+    FILE *result_header_fp;
+    FILE *report_fp;
+}NvramCompress;
+
+/*****************************************************************************
+ * Global variable
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Local variable
+ *****************************************************************************/
+static NvramCompress g_nvram_compress_cntx;
+
+/*****************************************************************************
+ * Local Function
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Global Function
+ *****************************************************************************/
+
+/*****************************************************************************
+* FUNCTION
+*   nvram_for_each
+* DESCRIPTION
+*   scan all the lid of the table
+* PARAMETERS
+*   table       [IN]    the logical table
+*   visit       [IN]    vist function pointer
+*   usr_data    [IN]    user data
+* RETURNS
+*   void
+*****************************************************************************/
+static void nvram_for_each(const ltable_entry_struct *table, visit_funcptr visit, void *usr_data)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    nvram_lid_enum i = 0;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    RETURN_IF_FAIL(table != NULL && visit != NULL);
+
+    while (table[i].LID != NVRAM_EF_RESERVED_LID &&
+        table[i].LID < NVRAM_EF_LAST_LID_CUST)
+    {
+        if (visit(&table[i], usr_data) == RET_STOP)
+        {
+            break;
+        }
+        i++;
+    }
+
+}
+
+/*****************************************************************************
+* FUNCTION
+*  nvram_compress_mem_dump
+* DESCRIPTION
+*   Dump memory
+* PARAMETERS
+*  None
+* RETURNS
+*  None
+*****************************************************************************/
+static void nvram_compress_mem_dump(kal_uint8 *str1, kal_uint8 *buffer, kal_uint32 size, FILE* fp)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    kal_uint32 i;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    fprintf(fp, "\nMemoryDump:");
+    fprintf(fp, "%s:{",str1);
+
+    for(i = 0; i < size; i++)
+    {
+        if ((i % 20 == 0))
+        {
+            fprintf(fp, "\n\t");
+        }
+
+        fprintf(fp, "%2x,", buffer[i]);
+    }
+    fprintf(fp, "}\n");
+    fflush(fp);
+}
+
+/*****************************************************************************
+* FUNCTION
+*   nvram_check_compress
+* DESCRIPTION
+*   To check whether the entry can be compressed
+* PARAMETERS
+*   entry       [IN]    the logical table
+* RETURNS
+*   kal_bool
+*****************************************************************************/
+static kal_bool nvram_check_compress(const ltable_entry_struct *entry)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    RETURN_VAL_IF_FAIL(entry != NULL, KAL_FALSE);
+
+    /* No data */
+    if (entry == NULL ||
+        entry->LID == 0 ||
+        entry->size == 0 ||
+        entry->total_records == 0)
+    {
+        return KAL_FALSE;
+    }
+
+    /* Some default value can't be compressed */
+    if (strstr(entry->str_default_value, "NVRAM_EF_ZERO_DEFAULT") != NULL ||
+        strstr(entry->str_default_value, "NVRAM_EF_FF_DEFAULT") != NULL)
+    {
+        return KAL_FALSE;
+    }
+
+    return KAL_TRUE;
+}
+
+/*****************************************************************************
+* FUNCTION
+*   nvram_compress_custpack_callback
+* DESCRIPTION
+*   Compress the custpack entry
+* PARAMETERS
+*   data        [IN]data item
+*   usr_data    [IN]user data
+* RETURNS
+*   Ret
+*****************************************************************************/
+static Ret nvram_compress_custpack_callback(void *data, void* usr_data)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    ltable_entry_struct *entry;
+    kal_uint32 size, value_size;
+    kal_int32 ret;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    RETURN_VAL_IF_FAIL(data != NULL && usr_data != NULL, RET_STOP);
+
+    entry = (ltable_entry_struct *)data;
+
+    /*
+     *  Only care about custpack entry in this callback
+     */
+    if (NVRAM_IS_CATEGORY_CUSTPACK(entry->category))
+    {
+        nvram_compress_callback(entry, usr_data);
+    }
+
+    return RET_OK;
+}
+
+
+
+/*****************************************************************************
+* FUNCTION
+*   nvram_compress_callback
+* DESCRIPTION
+*   Compress the entry
+* PARAMETERS
+*   data        [IN]data item
+*   usr_data    [IN]user data
+* RETURNS
+*   Ret
+*****************************************************************************/
+static Ret nvram_compress_callback(void *data, void* usr_data)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    ltable_entry_struct *entry;
+    kal_uint32 size, value_size, i;
+    kal_uint32 *compress_size;
+    kal_int32 ret;
+    kal_uint8 *dest = NULL, *data_ptr, *str, *default_value;
+    NvramCompress *thiz;
+    FILE* fp;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    RETURN_VAL_IF_FAIL(data != NULL && usr_data != NULL, RET_STOP);
+
+    thiz = (NvramCompress *)usr_data;
+    entry = (ltable_entry_struct *)data;
+
+    if (!nvram_check_compress(entry))
+    {
+        return RET_OK;
+    }
+
+    /* Port default value to nvram_default_value.c */
+    str = nvram_compress_locate_default_value(entry->str_default_value);
+    if (str == NULL)
+    {
+        NVRAM_TRC_HIGH1("No default value! %d", entry->LID);
+        return RET_OK;
+    }
+
+    /* we only compress the data in internal category */
+    if (NVRAM_IS_CATEGORY_INTERNAL(entry->category) ||
+        NVRAM_IS_CATEGORY_CALIBRAT(entry->category) ||
+        NVRAM_IS_CATEGORY_IMPORTANT(entry->category) ||
+        NVRAM_IS_CATEGORY_SECUPACK(entry->category))
+    {
+        fprintf(thiz->result_header_fp, VALUE_REDEFINE, str, str);
+        return RET_OK;
+    }
+
+
+    if (NVRAM_IS_ATTR_NOT_ZIP_DEFAULT(entry->attr))
+    {
+        if (NVRAM_IS_CATEGORY_CUSTPACK(entry->category))
+        {
+            NVRAM_TRC_HIGH1("Custpack with not compress attribute %d!\n", entry->LID);
+        }
+
+        fprintf(thiz->result_header_fp, VALUE_REDEFINE, str, str);
+        return RET_OK;
+    }
+
+    if (NVRAM_IS_ATTR_MULTI_DEFAULT(entry->attr))
+    {
+        value_size = entry->size * entry->total_records;
+    }
+    else
+    {
+        value_size = entry->size;
+    }
+
+    /*
+     *  1. For custpack default value, redirect it to nvram_custpack_default_value.c
+     *    because ExtractObj.exe needs to find nvram default value from nvram_cust_pack.obj.
+     *  2. always compress custpack so that custpack tool don't need to care which data is compressed or not.
+     */
+    if (NVRAM_IS_CATEGORY_CUSTPACK(entry->category))
+    {
+        thiz->last_custpack = entry->LID;
+        fp = thiz->custpack_fp;
+        default_value = custpack_nvram_ptr.custpack_default[thiz->custpack_index];
+        thiz->custpack_index++;
+    }
+    else
+    {
+        fp = thiz->result_src_fp;
+        default_value = entry->default_value;
+    }
+
+    if (default_value == NVRAM_EF_FF_DEFAULT ||
+        default_value == NVRAM_EF_ZERO_DEFAULT)
+    {
+        NVRAM_TRC_LOW(("Wrong default to compress for LID:%d \n", entry->str_LID));
+        NVRAM_TRC_HIGH("ZERO or FF default!\n");
+    }
+
+    /* At compressing state */
+    if (value_size < 20)
+    {
+        size = NVRAM_MEM_FACTOR2 * value_size;
+    }
+    else
+    {
+        size = NVRAM_MEM_FACTOR1 * value_size;
+    }
+
+    dest = (kal_uint8*)NVRAM_MALLOC(size);
+
+    if (dest == NULL)
+    {
+        NVRAM_TRC_HIGH("No Memory!\n");
+    }
+
+    /* compress function need to know the output buffer size. */
+    /*The first 4 bytes will be compressed buffer size, after this int, there will be compressed data */
+    data_ptr = dest + BUFFER_FOR_LEN;
+    size -= BUFFER_FOR_LEN;
+    ret = thiz->onCompress(data_ptr, &size, default_value, value_size, Z_BEST_COMPRESSION);
+    if (ret != Z_OK)
+    {
+        nvram_compress_mem_dump(entry->str_LID, default_value, value_size, thiz->report_fp);
+        NVRAM_TRC_LOW2("Compress [%s]not Z_OK, %d!\n",entry->str_LID, ret);
+
+        NVRAM_MFREE(dest);
+        return RET_OK;
+    }
+    NVRAM_TRC_LOW(("Compress [%s] OK!\n", entry->str_LID));
+
+    /* Uncompress and verify the data */
+    nvram_compress_verify(thiz, default_value, value_size, data_ptr, size);
+
+    CONV_INT_TO_4BYTES(dest, size);
+
+    if (thiz->max_default_value < value_size)
+    {
+        thiz->max_default_value = value_size;
+    }
+
+    size += BUFFER_FOR_LEN;
+    thiz->org_total_size += value_size;
+    thiz->compress_total_size += size;
+
+    nvram_compress_port_default_value_to_file(str, dest, size, fp);
+
+    /* Port default value extern to nvram_default_value.h */
+    fprintf(thiz->result_header_fp, VALUE_EXTERN, str);
+    /* Write data struct to table */
+    fprintf(thiz->report_fp, VAR_TABLE_ENTRY, entry->str_LID, size, value_size);
+    fflush(thiz->report_fp);
+
+    NVRAM_MFREE(dest);
+
+    return RET_OK;
+}
+
+
+/*****************************************************************************
+ * FUNCTION
+ *   nvram_compress_verify
+ * DESCRIPTION
+ *   Verify the compressed data
+ * PARAMETERS
+ *   thiz           [IN]
+ *   org_buff       [IN]
+ *   org_buff_size  [IN]
+ *   buffer         [IN]
+ *  buff_size       [IN]
+ * RETURNS
+ *   Ret
+ *****************************************************************************/
+static void nvram_compress_verify(NvramCompress *thiz,
+                                    kal_uint8  *org_buff,
+                                    kal_uint32 org_buff_size,
+                                    kal_uint8  *buffer,
+                                    kal_uint32 buff_size)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    kal_int32 ret;
+    kal_uint8* dbuffer;
+    kal_uint32 size;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    RETURN_IF_FAIL(thiz != NULL);
+    RETURN_IF_FAIL(org_buff != NULL && org_buff_size != 0);
+    RETURN_IF_FAIL(buffer != NULL && buff_size != 0);
+
+    size = 50 * org_buff_size;
+    dbuffer = NVRAM_MALLOC(size);
+    ret = thiz->onUncompress(dbuffer, &size, buffer, buff_size);
+    if (ret != Z_OK)
+    {
+        NVRAM_TRC_HIGH1("Uncompress verify failed 1, ret=%d!\n", ret);
+    }
+
+    if (size != org_buff_size)
+    {
+    NVRAM_TRC_HIGH("Uncompress verify failed 2!\n");
+    }
+
+    if (memcmp(dbuffer, org_buff, org_buff_size) != 0)
+    {
+        NVRAM_TRC_HIGH("Uncompress verify failed 3!\n");
+    }
+
+    NVRAM_MFREE(dbuffer);
+
+    NVRAM_TRC_LOW("Uncompress verify OK!\n");
+}
+
+
+/*****************************************************************************
+ * FUNCTION
+ *   nvram_compress_locate_default_value
+ * DESCRIPTION
+ *   Locate the default value string
+ * PARAMETERS
+ *   value  [IN]
+ * RETURNS
+ *   kal_uint8 *
+ *****************************************************************************/
+static kal_uint8 *nvram_compress_locate_default_value(const kal_uint8 *value)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    kal_uint8 *str;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    RETURN_VAL_IF_FAIL(value != NULL, NULL);
+
+    str = strstr(value, ")");
+    if (str == NULL)
+    {
+        str = value;
+    }
+    else
+    {
+        str++;
+    }
+
+    if (*str == '&')
+    {
+        str++;
+    }
+
+    return str;
+}
+
+
+/*****************************************************************************
+ * FUNCTION
+ *   nvram_compress_port_default_value_to_file
+ * DESCRIPTION
+ *   Port default value to another file
+ * PARAMETERS
+ *   value_name     [IN]
+ *   buffer         [IN]
+ *   buffer_len     [IN]
+ *   fp             [IN]
+ * RETURNS
+ *   void
+ *****************************************************************************/
+static void nvram_compress_port_default_value_to_file(
+                const kal_uint8 *value_name,
+                const kal_uint8 *buffer,
+                const kal_uint32 buffer_len,
+                FILE *fp)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    kal_uint32 i;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    RETURN_IF_FAIL(value_name != NULL);
+    RETURN_IF_FAIL(buffer != NULL && buffer_len != 0);
+    RETURN_IF_FAIL(fp != NULL);
+
+    fprintf(fp, VALUE_START, value_name, buffer_len);
+    fprintf(fp, VALUE_BRACE);
+
+    for(i = 0; i < buffer_len; i++)
+    {
+        if ((i % 8 == 0))
+        {
+            fprintf(fp, "\n\t");
+        }
+
+        if ((i + 1) == buffer_len)
+        {
+            fprintf(fp, "0x%02X", buffer[i]);
+        }
+        else
+        {
+            fprintf(fp, "0x%02X,", buffer[i]);
+        }
+    }
+
+    fprintf(fp, VALUE_END);
+    fflush(fp);
+
+}
+
+
+/*****************************************************************************
+ * FUNCTION
+ *   nvram_compress_custpack_jump_tbl_callback
+ * DESCRIPTION
+ *   regenerate jump table callback
+ * PARAMETERS
+ *   data           [IN]
+ *   usr_data       [IN]
+ * RETURNS
+ *   Ret
+ *****************************************************************************/
+static Ret nvram_compress_custpack_jump_tbl_callback(void *data, void* usr_data)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    ltable_entry_struct *entry;
+    NvramCompress *thiz;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    RETURN_VAL_IF_FAIL(data != NULL && usr_data != NULL, RET_STOP);
+
+    thiz = (NvramCompress *)usr_data;
+    entry = (ltable_entry_struct *)data;
+
+    if (entry == NULL ||
+        entry->LID == 0 ||
+        entry->size == 0 ||
+        entry->total_records == 0)
+    {
+        return RET_OK;
+    }
+
+    if (strstr(entry->str_default_value, "NVRAM_EF_ZERO_DEFAULT") ||
+        strstr(entry->str_default_value, "NVRAM_EF_FF_DEFAULT"))
+    {
+        return RET_OK;
+    }
+
+    if (NVRAM_IS_CATEGORY_CUSTPACK(entry->category))
+    {
+        fprintf(thiz->custpack_fp, "        %s_ZIP", entry->str_default_value);
+        if (thiz->last_custpack != entry->LID)
+        {
+            fprintf(thiz->custpack_fp, ",");
+        }
+        fprintf(thiz->custpack_fp, "\n");
+    }
+
+    return RET_OK;
+}
+
+
+/*****************************************************************************
+ * FUNCTION
+ *   nvram_compress_custpack_jump_tbl
+ * DESCRIPTION
+ *   regenerate jump table callback
+ * PARAMETERS
+ *   data           [IN]
+ *   usr_data       [IN]
+ * RETURNS
+ *   Ret
+ *****************************************************************************/
+static void nvram_compress_custpack_jump_tbl(NvramCompress *thiz, FILE* output)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    kal_uint32 i, tbl_idx = sizeof(table_pool)/sizeof(nvram_ltable_tbl_struct) - 1;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    RETURN_IF_FAIL(thiz != NULL && output != NULL);
+
+    fprintf(output, "const custpack_nvram_header custpack_nvram_ptr = \n");
+    fprintf(output, "{\n");
+    fprintf(output, "    %d,\n", 0);
+    fprintf(output, "    {\n");
+    for (;tbl_idx >= 0; tbl_idx--)
+    {
+        ltable_entry_struct **ltable = table[tbl_idx].ltable;
+        
+        nvram_for_each(ltable, nvram_compress_custpack_jump_tbl_callback, thiz);
+    }
+
+    fprintf(output, "    }\n");
+    fprintf(output, "};\n");
+}
+
+
+/*****************************************************************************
+* FUNCTION
+*   nvram_compress_create
+* DESCRIPTION
+*   create nvram compresser handler
+* PARAMETERS
+*   void
+* RETURNS
+*   NvramCompress
+*****************************************************************************/
+static NvramCompress* nvram_compress_create(void)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    return &g_nvram_compress_cntx;
+}
+
+
+/*****************************************************************************
+* FUNCTION
+*   nvram_compress_init
+* DESCRIPTION
+*   init comprresser struct
+* PARAMETERS
+*   thiz
+* RETURNS
+*   void
+*****************************************************************************/
+static void nvram_compress_init(NvramCompress *thiz)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    RETURN_IF_FAIL(thiz != NULL);
+
+    thiz->count = 0;
+    thiz->max_default_value = 0;
+
+    thiz->report_fp = fopen(COMPRESS_REPORT_FILE, "w+");
+    if (thiz->report_fp == NULL)
+    {
+        NVRAM_TRC_HIGH("File Create Failed!\n");
+    }
+
+    thiz->result_header_fp = fopen(RESULT_HEADER_PATH, "w+");
+    if (thiz->result_header_fp == NULL)
+    {
+        NVRAM_TRC_HIGH("File Create Failed!\n");
+    }
+
+    fprintf(thiz->result_header_fp, FILE_HEADER);
+    fprintf(thiz->result_header_fp, VALUE_MACRO_START);
+
+
+    thiz->result_src_fp = fopen(RESULT_SRC_PATH, "w+");
+    if (thiz->result_src_fp == NULL)
+    {
+        NVRAM_TRC_HIGH("File Create Failed!\n");
+    }
+    fprintf(thiz->result_src_fp, FILE_HEADER);
+    fprintf(thiz->result_src_fp, FILE_INCLUDE);
+    fprintf(thiz->result_src_fp, FILE_COMPILE_OPTION_START);
+
+    // custpack default value file
+    thiz->custpack_fp = fopen(CUSTPACK_PATH, "w+");
+    if (thiz->custpack_fp == NULL)
+    {
+        NVRAM_TRC_HIGH("Custpack file create failed!\n");
+    }
+
+    fprintf(thiz->custpack_fp, FILE_HEADER);
+    fprintf(thiz->custpack_fp, CUSTPACK_FILE_INCLUDE);
+    fprintf(thiz->custpack_fp, CUSTPACK_FILE_COMPILE_OPTION_START);
+
+    thiz->org_total_size = 0;
+    thiz->compress_total_size = 0;
+    thiz->onCompress = compress2;
+    thiz->onUncompress = uncompress;
+
+}
+
+
+/*****************************************************************************
+* FUNCTION
+*   nvram_compress_close
+* DESCRIPTION
+*   close comprresser handler
+* PARAMETERS
+*   thiz
+* RETURNS
+*   void
+*****************************************************************************/
+static void nvram_compress_close(NvramCompress *thiz)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    kal_uint8 buffer[NVRAM_TEMP_BUFFER_SIZE];
+    kal_uint32 size;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    RETURN_IF_FAIL(thiz != NULL);
+
+    /* header file */
+    fprintf(thiz->result_header_fp, VALUE_MAX_SIZE, thiz->max_default_value);
+    fprintf(thiz->result_header_fp, VALUE_MACRO_END);
+    fclose(thiz->result_header_fp);
+
+    nvram_compress_custpack_jump_tbl(thiz, thiz->custpack_fp);
+
+    fprintf(thiz->custpack_fp, CUSTPACK_FILE_COMPILE_OPTION_END);
+    fclose(thiz->custpack_fp);
+
+    /* move table item to src file */
+    fclose(thiz->report_fp);
+
+    fprintf(thiz->result_src_fp, FILE_COMPILE_OPTION_END);
+    fclose(thiz->result_src_fp);
+
+    NVRAM_TRC_LOW2("\n\nTotal: original data=%d, compressed data=%d\n", thiz->org_total_size, thiz->compress_total_size);
+
+    thiz->count = 0;
+    thiz->onCompress = NULL;
+    thiz->onUncompress = NULL;
+    thiz->org_total_size = 0;
+    thiz->compress_total_size = 0;
+}
+
+
+
+/*****************************************************************************
+* FUNCTION
+*   nvram_compress
+* DESCRIPTION
+*   compress all nvram default value
+* PARAMETERS
+*   void
+* RETURNS
+*   void
+*****************************************************************************/
+static void nvram_compress(char *project_name, char *broad_ver)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    NvramCompress *thiz = nvram_compress_create();
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    nvram_compress_init(thiz);
+
+    /* Only compress comm and cust table */
+    nvram_for_each(logical_data_item_table_core, nvram_compress_callback, thiz);
+    nvram_for_each(logical_data_item_table_comm_app, nvram_compress_callback, thiz);
+    nvram_for_each(logical_data_item_table_cust, nvram_compress_callback, thiz);
+
+    nvram_compress_close(thiz);
+}
+
+
+#endif /* __NVRAM_COMPRESS_SUPPORT__ */
+
+#ifdef NVRAM_GEN_LID_TABLE
+
+/* core folder */
+#define NVRAM_FS_COREITEM_PATH               "Z:\\NVRAM\\NVD_CORE"
+#define NVRAM_FS_CALIBRAT_DATAITEM_PATH	     "Z:\\NVRAM\\CALIBRAT"
+#define NVRAM_FS_IMPT_DATAITEM_PATH    	     "Z:\\NVRAM\\NVD_IMEI"
+#define NVRAM_FS_CUST_DATAITEM_PATH          "Z:\\NVRAM\\NVD_CUST"
+#define NVRAM_FS_IMPORTNT_DATAITEM_PATH      "Z:\\NVRAM\\IMPORTNT"
+
+#ifdef __NVRAM_BACKUP_DISK_FAT__
+#if defined(__TC01__) && defined(__MTK_TARGET__)
+#define NVRAM_FS_BACKUP_ROOT_PATH            "G:\\NVRAM"
+#else
+#define NVRAM_FS_BACKUP_ROOT_PATH            "Z:\\NVRAM_BAK"
+#endif
+#endif
+
+
+#define NVRAM_FS_DATAITEM_PATH               "Z:\\NVRAM\\NVD_DATA"
+
+#if defined (__NVRAM_UT_TEST__)
+/*  paths defined in __NVRAM_UT_TEST__ is used for nvram first init test*/
+
+/* NVRAM Test Folder Path */
+#define NVRAM_TEST_FS_COREITEM_PATH               "Z:\\NV_TEST\\NVD_CORE"
+#define NVRAM_TEST_FS_CALIBRAT_DATAITEM_PATH	     "Z:\\NV_TEST\\CALIBRAT"
+#define NVRAM_TEST_FS_IMPT_DATAITEM_PATH    	     "Z:\\NV_TEST\\NVD_IMEI"
+#define NVRAM_TEST_FS_CUST_DATAITEM_PATH          "Z:\\NV_TEST\\NVD_CUST"
+#define NVRAM_TEST_FS_IMPORTNT_DATAITEM_PATH      "Z:\\NV_TEST\\IMPORTNT"
+#define NVRAM_TEST_FS_DATAITEM_PATH               "Z:\\NV_TEST\\NVD_DATA"
+
+extern kal_taskid nvram_test_task1_id;
+extern kal_uint8 is_insulation_access;
+#endif //__NVRAM_UT_TEST__
+
+
+#if defined (__NVRAM_UT_TEST__)  && !defined(__NVRAM_LID_CACHE__)
+#define NVRAM_FS_MAKE_LID_PATH_FILENAME_1( buf, name )   if((is_insulation_access) && (nvram_test_task1_id) && (kal_get_current_task()==nvram_test_task1_id))\
+	sprintf(buf, "%s\\%s", NVRAM_TEST_FS_DATAITEM_PATH, name);\
+	else \
+    sprintf(buf, "%s\\%s", NVRAM_FS_DATAITEM_PATH, name)
+
+#define NVRAM_FS_MAKE_CORE_PATH_FILENAME(buf, name)   if((is_insulation_access) && (nvram_test_task1_id) && (kal_get_current_task()==nvram_test_task1_id))\
+	sprintf(buf, "%s\\%s", NVRAM_TEST_FS_COREITEM_PATH, name);\
+	else \
+	sprintf(buf, "%s\\%s", NVRAM_FS_COREITEM_PATH, name)     
+   
+#define NVRAM_FS_MAKE_CRITICAL_CALIBRAT_PATH_FILENAME(buf, name)    if((is_insulation_access) && (nvram_test_task1_id) && (kal_get_current_task()==nvram_test_task1_id))\
+	  sprintf(buf, "%s\\%s", NVRAM_TEST_FS_CALIBRAT_DATAITEM_PATH, name);\
+	  else \
+	  sprintf(buf, "%s\\%s", NVRAM_FS_CALIBRAT_DATAITEM_PATH, name)  
+   
+#define NVRAM_FS_MAKE_CRITICAL_IMEI_PATH_FILENAME(buf, name)    if((is_insulation_access) && (nvram_test_task1_id) && (kal_get_current_task()==nvram_test_task1_id))\
+	  sprintf(buf, "%s\\%s", NVRAM_TEST_FS_IMPT_DATAITEM_PATH, name);\
+	  else \
+	  sprintf(buf, "%s\\%s", NVRAM_FS_IMPT_DATAITEM_PATH, name)
+   
+#define NVRAM_FS_MAKE_CUST_PATH_FILENAME(buf, name) if((is_insulation_access) && (nvram_test_task1_id) && (kal_get_current_task()==nvram_test_task1_id))\
+	  sprintf(buf, "%s\\%s", NVRAM_TEST_FS_CUST_DATAITEM_PATH, name);\
+	  else \
+	  sprintf(buf, "%s\\%s", NVRAM_FS_CUST_DATAITEM_PATH, name)
+   
+#define NVRAM_FS_MAKE_IMPORTNT_PATH_FILENAME(buf, name) if((is_insulation_access) && (nvram_test_task1_id) && (kal_get_current_task()==nvram_test_task1_id))\
+	  sprintf(buf, "%s\\%s", NVRAM_TEST_FS_IMPORTNT_DATAITEM_PATH, name);\
+	  else \
+	  sprintf(buf, "%s\\%s", NVRAM_FS_IMPORTNT_DATAITEM_PATH, name)
+
+#else
+#define NVRAM_FS_MAKE_LID_PATH_FILENAME_1( buf, name )   \
+   sprintf(buf, "%s\\%s", NVRAM_FS_DATAITEM_PATH, name)
+
+#define NVRAM_FS_MAKE_CORE_PATH_FILENAME(buf, name)        \
+   sprintf(buf, "%s\\%s", NVRAM_FS_COREITEM_PATH, name);
+
+#define NVRAM_FS_MAKE_CRITICAL_CALIBRAT_PATH_FILENAME(buf, name)    \
+   sprintf(buf, "%s\\%s", NVRAM_FS_CALIBRAT_DATAITEM_PATH, name);
+
+#define NVRAM_FS_MAKE_CRITICAL_IMPT_PATH_FILENAME(buf, name)    \
+   sprintf(buf, "%s\\%s", NVRAM_FS_IMPT_DATAITEM_PATH, name);
+
+#define NVRAM_FS_MAKE_CUST_PATH_FILENAME(buf, name) \
+   sprintf(buf, "%s\\%s", NVRAM_FS_CUST_DATAITEM_PATH, name);
+
+#define NVRAM_FS_MAKE_IMPORTNT_PATH_FILENAME(buf, name) \
+   sprintf(buf, "%s\\%s", NVRAM_FS_IMPORTNT_DATAITEM_PATH, name);
+
+#endif
+
+#ifdef __NVRAM_BACKUP_DISK_FAT__
+#define NVRAM_FS_MAKE_BACKUP_PATH_FILENAME(buf, name) \
+	sprintf(buf, "%s\\%s", NVRAM_FS_BACKUP_ROOT_PATH, name);
+#endif
+
+
+#define NVRAM_MAKE_LID_FILENAME(buf, prefix, M, verno) {\
+   ((kal_char*) (buf))[0] = ((kal_char*) (prefix))[0];  \
+   ((kal_char*) (buf))[1] = ((kal_char*) (prefix))[1];  \
+   ((kal_char*) (buf))[2] = ((kal_char*) (prefix))[2];  \
+   ((kal_char*) (buf))[3] = ((kal_char*) (prefix))[3];  \
+   ((kal_char*) (buf))[4] = (kal_char) (M);             \
+   ((kal_char*) (buf))[5] = ((kal_char*) (verno))[0];   \
+   ((kal_char*) (buf))[6] = ((kal_char*) (verno))[1];   \
+   ((kal_char*) (buf))[7] = ((kal_char*) (verno))[2];   \
+   ((kal_char*) (buf))[8] = '\0';                       \
+};
+
+#define NVRAM_MAKE_PACKAGE_FILENAME(buf, M) {       \
+   ((kal_char*) (buf))[0] = 'P';                    \
+   ((kal_char*) (buf))[1] = 'A';                    \
+   ((kal_char*) (buf))[2] = 'C';                    \
+   ((kal_char*) (buf))[3] = 'K';                    \
+   ((kal_char*) (buf))[4] = (kal_char) (M);         \
+   ((kal_char*) (buf))[5] = 'L';                    \
+   ((kal_char*) (buf))[6] = 'I';                    \
+   ((kal_char*) (buf))[7] = 'D';                    \
+   ((kal_char*) (buf))[8] = '\0';                   \
+};
+
+#define TABLE_FILE "..\\..\\..\\~nvram_lid_table.xls"
+
+
+/*****************************************************************************
+ * FUNCTION
+ *  nvram_make_lid_filename
+ * DESCRIPTION
+ * PARAMETERS
+ * RETURNS
+ *****************************************************************************/
+static void nvram_util_make_lid_filename(ltable_entry_struct *ldi, NVRAM_FILE_NAME nvramname, kal_bool first_copy)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+
+    if (ldi == NULL)
+    {
+        NVRAM_TRC_HIGH("Empty ldi ");
+        return;
+    }
+
+#ifdef __NVRAM_PSEUDO_MERGE__
+    if (NVRAM_IS_ATTR_PACKAGE(ldi->attr))
+    {
+        NVRAM_MAKE_PACKAGE_FILENAME(nvramname, 'A');
+        return;
+    }
+#endif
+
+    if (NVRAM_IS_ATTR_MULTIPLE(ldi->attr))
+    {
+        if (first_copy)
+        {
+            NVRAM_MAKE_LID_FILENAME(nvramname, ldi->fileprefix, 'A', ldi->fileverno);
+        }
+        else
+        {
+            NVRAM_MAKE_LID_FILENAME(nvramname, ldi->fileprefix, 'B', ldi->fileverno);
+        }
+    }
+    else
+    {
+        NVRAM_MAKE_LID_FILENAME(nvramname, ldi->fileprefix, '_', ldi->fileverno);
+    }
+
+    return;
+
+}
+
+
+
+/*****************************************************************************
+ * FUNCTION
+ *  nvram_query_folder_index
+ * DESCRIPTION
+ *  Get the index of folder
+ * PARAMETERS
+ *  category
+ * RETURNS
+ *  Success or Fail
+ *****************************************************************************/
+static nvram_folder_enum nvram_query_folder_index(nvram_category_enum category)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    nvram_folder_enum folder_index;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+#ifdef __NVRAM_MULTI_FOLDERS__
+    if (NVRAM_IS_CATEGORY_INTERNAL(category))
+    {
+        folder_index = NVRAM_NVD_CORE;
+    }
+    else if (NVRAM_IS_CATEGORY_CALIBRAT(category))
+    {
+        folder_index = NVRAM_NVD_CALI;
+    }
+    else if (NVRAM_IS_CATEGORY_IMPORTANT(category))
+    {
+        folder_index = NVRAM_NVD_IMPT;
+    }
+#ifdef __CCCIFS_SUPPORT__
+    else if (category & NVRAM_CATEGORY_IMPORTANT_L4)
+    {
+        folder_index = NVRAM_NVD_IMPNT;
+    }
+    else if (NVRAM_IS_CATEGORY_IMPORTANT_L1(category)
+    {
+        folder_index = NVRAM_NVD_IMPNT;
+    }
+#endif
+    #ifdef __NVRAM_CUSTOM_SENSITIVE__
+    else if (NVRAM_IS_CATEGORY_CUSTOM_SENSITIVE(category))
+    {
+        folder_index = NVRAM_NVD_CUST;
+    }
+    #endif
+    else
+#endif /* __NVRAM_MULTI_FOLDERS__ */
+    {
+        folder_index = NVRAM_NVD_DATA;
+    }
+
+    return folder_index;
+}
+
+
+/*****************************************************************************
+ * FUNCTION
+ *  nvram_query_file_name
+ * DESCRIPTION
+ *  Get file full name
+ * PARAMETERS
+ *  folder_idx  :
+ *  nvramname   : nvram file
+ *  filename    : full name of nvram file
+ * RETURNS
+ *  Success or Fail
+ *****************************************************************************/
+static kal_wchar * nvram_query_file_name(nvram_folder_enum folder_idx, kal_char *nvramname, kal_wchar *filename)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    switch (folder_idx)
+    {
+        case NVRAM_NVD_DATA:
+        {
+            NVRAM_FS_MAKE_LID_PATH_FILENAME_1(filename, nvramname);
+            break;
+        }
+    #ifdef __NVRAM_MULTI_FOLDERS__
+        case NVRAM_NVD_CORE:
+        {
+            NVRAM_FS_MAKE_CORE_PATH_FILENAME(filename, nvramname);
+            break;
+        }
+        case NVRAM_NVD_CALI:
+        {
+            NVRAM_FS_MAKE_CRITICAL_CALIBRAT_PATH_FILENAME(filename, nvramname);
+            break;
+        }
+        case NVRAM_NVD_IMPT:
+        {
+            NVRAM_FS_MAKE_CRITICAL_IMEI_PATH_FILENAME(filename, nvramname);
+            break;
+        }
+        #ifdef __CCCIFS_SUPPORT__
+        case NVRAM_NVD_IMPNT:
+        {
+            NVRAM_FS_MAKE_IMPORTNT_PATH_FILENAME(filename, nvramname);
+            break;
+        }
+        #endif
+        #ifdef __NVRAM_CUSTOM_SENSITIVE__
+        case NVRAM_NVD_CUST:
+        {
+            NVRAM_FS_MAKE_CUST_PATH_FILENAME(filename, nvramname);
+            break;
+        }
+        #endif
+    #endif /* __NVRAM_MULTI_FOLDERS__ */
+    #ifdef __NVRAM_BACKUP_DISK_FAT__
+        case NVRAM_NVD_BAK:
+        {
+            NVRAM_FS_MAKE_BACKUP_PATH_FILENAME(filename, nvramname);
+            break;
+        }
+    #endif
+        default:
+        {
+            NVRAM_TRC_HIGH("Wrong folder idex !");
+            break;
+        }
+    }
+
+    return filename;
+}
+
+
+/*****************************************************************************
+* FUNCTION
+*  nvram_gen_table_callback
+* DESCRIPTION
+*  main function.
+* PARAMETERS
+*  None
+* RETURNS
+*  None
+*****************************************************************************/
+static Ret nvram_gen_table_callback(void *data, void* usr_data)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    ltable_entry_struct *entry;
+    FILE* fp;
+    kal_uint8 filename[9];
+    kal_uint16 folder_idx;
+    kal_char src_path[32];
+
+    kal_char nvramname[9];
+
+    #define TABLE_PATTARN "\n%s\t%s\t%s"
+    #define TABLE_SEL_FLAG	"\t#"
+    #define TABLE_UNSEL_FLAG	"\t"
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    RETURN_VAL_IF_FAIL(data != NULL && usr_data != NULL, RET_STOP);
+    entry = (ltable_entry_struct *)data;
+    fp = (FILE *)usr_data;
+
+    folder_idx = nvram_query_folder_index(entry->category);
+
+    nvram_util_make_lid_filename(entry, nvramname, KAL_TRUE);
+    nvram_query_file_name(folder_idx, nvramname, src_path);
+
+    fprintf(fp, TABLE_PATTARN, entry->str_LID, entry->description, src_path);
+
+    /* System */
+    if (entry->attr & NVRAM_ATTR_OTA_RESET)
+    {
+        fprintf(fp, TABLE_SEL_FLAG);
+    }
+    else
+    {
+        fprintf(fp, TABLE_UNSEL_FLAG);
+    }
+
+    /* custpack */
+    if (NVRAM_IS_CATEGORY_CUSTPACK(entry->category))
+    {
+        fprintf(fp, TABLE_SEL_FLAG);
+    }
+    else
+    {
+        fprintf(fp, TABLE_UNSEL_FLAG);
+    }
+
+    /* Calibartion */
+    if (NVRAM_IS_CATEGORY_CALIBRAT(entry->category))
+    {
+        fprintf(fp, TABLE_SEL_FLAG);
+    }
+    else
+    {
+        fprintf(fp, TABLE_UNSEL_FLAG);
+    }
+
+    /* Internal */
+    if (NVRAM_IS_CATEGORY_INTERNAL(entry->category))
+    {
+        fprintf(fp, TABLE_SEL_FLAG);
+    }
+    else
+    {
+        fprintf(fp, TABLE_UNSEL_FLAG);
+    }
+
+    /* Important */
+    if (NVRAM_IS_CATEGORY_IMPORTANT(entry->category))
+    {
+        fprintf(fp, TABLE_SEL_FLAG);
+    }
+    else
+    {
+        fprintf(fp, TABLE_UNSEL_FLAG);
+    }
+
+    /* Secupack */
+    if (NVRAM_IS_CATEGORY_SECUPACK(entry->category))
+    {
+        fprintf(fp, TABLE_SEL_FLAG);
+    }
+    else
+    {
+        fprintf(fp, TABLE_UNSEL_FLAG);
+    }
+
+    /* Factory Reset */
+    if (NVRAM_IS_CATEGORY_FACTORY_RESET(entry->category))
+    {
+        fprintf(fp, TABLE_SEL_FLAG);
+    }
+    else
+    {
+        fprintf(fp, TABLE_UNSEL_FLAG);
+    }
+
+#ifdef __NVRAM_COMPRESS_SUPPORT__
+    /* Zip default value */
+    if ((entry->attr & NVRAM_ATTR_ZIP_DEFAULT) ||
+        NVRAM_IS_CATEGORY_CUSTPACK(entry->category))
+    {
+        fprintf(fp, TABLE_SEL_FLAG);
+    }
+    else
+#endif /* __NVRAM_COMPRESS_SUPPORT__ */
+    {
+        fprintf(fp, TABLE_UNSEL_FLAG);
+    }
+
+
+    return RET_OK;
+}
+
+
+/*****************************************************************************
+* FUNCTION
+*  nvram_compress_gen_lid_table
+* DESCRIPTION
+*  main function.
+* PARAMETERS
+*  None
+* RETURNS
+*  None
+*****************************************************************************/
+void nvram_gen_lid_table(void)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    FILE *fp;
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    fp = fopen(TABLE_FILE, "w");
+    if (fp == NULL)
+    {
+        NVRAM_TRC_HIGH("File Open Error!");
+    }
+    fprintf(fp, "LID      \t LID_description \t folder      \t System \t Custpack \t Calibartion \t Internal \t Important \t Secupack \t Restore \t compress");
+
+    nvram_for_each(logical_data_item_table_core, nvram_gen_table_callback, fp);
+    nvram_for_each(logical_data_item_table_comm_app, nvram_gen_table_callback, fp);
+    nvram_for_each(logical_data_item_table_cust, nvram_gen_table_callback, fp);
+
+    fclose(fp);
+}
+#endif /* NVRAM_GEN_LID_TABLE */
+
+/*****************************************************************************
+* FUNCTION
+*  main
+* DESCRIPTION
+*  main function.
+* PARAMETERS
+*  None
+* RETURNS
+*  None
+*****************************************************************************/
+int main(int argc, char *argv[])
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+
+    if (argc > 1)
+    {
+    #ifdef __NVRAM_COMPRESS_SUPPORT__
+        NVRAM_TRC_LOW("\nNvram default value compressing....\n");
+        nvram_compress(argv[1], argv[2]);
+
+    #else /* __NVRAM_COMPRESS_SUPPORT__ */
+        printf("\nDon't support nvram compress!\n");
+    #endif /* __NVRAM_COMPRESS_SUPPORT__ */
+
+    #ifdef NVRAM_GEN_LID_TABLE
+        nvram_gen_lid_table();
+    #endif
+    }
+    return 0;
+}
+
diff --git a/mcu/tools/NVRAMStatistic/src/nvram_gen_cache_table.c b/mcu/tools/NVRAMStatistic/src/nvram_gen_cache_table.c
new file mode 100644
index 0000000..684e752
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/src/nvram_gen_cache_table.c
@@ -0,0 +1,544 @@
+#ifndef NVRAM_NOT_PRESENT
+/*
+ * Include
+ */
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/io.h>
+#include <string.h>
+
+#if defined(__MMI_FMI__)
+#include "nvram_user_defs.h"
+#endif
+#include "custom_nvram_cat.h"
+#include "custom_nvram_config.h"  /* __NVRAM_VENDOR_SUPPORT__ */
+#include "nvram_editor_data_item.h"
+#include "nvram_group_editor.h" //add for break group files from header file
+#ifdef __NVRAM_PSEUDO_MERGE__
+#include "nvram_pseudo_merge.h"
+#endif
+
+#include "custom_nvram_int_config.h"
+#include "nvram_gen_cache_table.h"
+#ifdef __NV_CHKSUM_ENHANCE__
+#include "custom_nvram_sec.h"   // add ,get checksum type/size.
+
+/* CUSTOM_CHK_ALGO_CONFIG configure*/
+extern nvram_checksum_config CUSTOM_CHK_ALGO_CONFIG;
+kal_uint32 get_checksum_size(nvram_ltable_entry_struct* ldi);
+#endif
+kal_uint32 nvram_gen_total_cache_lid = 0;
+
+
+#ifdef __NVRAM_PARTIAL_CACHE__
+/*You must synchronization modify the nvram_lid_noncache_list in service/nvram/src/nvram_cache_white_list.c if you want to add or delete a member of below list.*/
+kal_uint32 autogen_nvram_lid_noncache_list[]= {
+    1245,   /*NVRAM_EF_MML1_RF_SELF_CAL_RX_TYPE1_LID*/
+    1248,   /*NVRAM_EF_MML1_RF_SELF_CAL_DET_TX_LID*/
+    1249,   /*NVRAM_EF_MML1_RF_SELF_CAL_TX_SB_LID*/
+    57346,  /*NVRAM_EF_NL1_TXCALDATA_BLOCK_LID*/
+    57348,  /*NVRAM_EF_NL1_RXSSIGAIN_TYPE1_BLOCK_LID*/
+    57350,  /*NVRAM_EF_NL1_RXSSIGAIN_TYPE2_BLOCK_LID*/
+    57356,  /*NVRAM_EF_NL1_DPD_CAL_DATABASE_LID*/
+    57365,  /*NVRAM_EF_NL1_ET_CAL_DATABASE_LID*/
+    60479,  /*NVRAM_EF_EL1_RF_SELF_CAL_RX_DC_IRR_LID*/
+    60481,  /*NVRAM_EF_EL1_RF_SELF_CAL_DET_TX_LID*/
+    60548,  /*NVRAM_EF_EL1_TXCALDATA_BLOCK_LID*/
+    60550,  /*NVRAM_EF_EL1_RXSSIGAIN_TYPE1_BLOCK_LID*/
+    60552,  /*NVRAM_EF_EL1_RXSSIGAIN_TYPE2_BLOCK_LID*/
+    60566,  /*NVRAM_EF_EL1_DPD_CAL_DATABASE_LID*/
+    60571,  /*NVRAM_EF_EL1_ET_CAL_DATABASE_LID*/
+};
+
+kal_uint16 autogen_nvram_lid_noncache_list_amount = sizeof(autogen_nvram_lid_noncache_list)/sizeof(kal_uint32);
+
+#endif
+
+extern nvram_ltable_entry_struct *logical_data_item_table;
+static kal_uint32 cache_data_offset = 0;
+static kal_uint32 dirty_bit_table_offset = 0;
+static kal_uint32 dirty_bit_table_length = 0;
+
+/*****************************************************************************
+  * FUNCTION
+  *  autogen_is_in_noncache_list
+  * DESCRIPTION
+  *  NVRAM lid whether in non-cache list
+  * PARAMETERS
+  *  LDI             [IN]
+  * RETURNS
+  *  success or fail
+  *You must synchronization modify the is_in_noncache_list in service/nvram/src/nvram_cache_white_list.c if you want to add or delete a member of below list.
+  *****************************************************************************/
+kal_bool autogen_is_in_noncache_list(nvram_lid_enum LID)
+{
+    #ifdef __NVRAM_PARTIAL_CACHE__
+    kal_uint32 idx;
+    for(idx = 0; idx < autogen_nvram_lid_noncache_list_amount; idx++)
+    {
+        if(autogen_nvram_lid_noncache_list[idx] == LID)
+        {
+            return KAL_TRUE;
+        }
+    }
+    #endif
+    return KAL_FALSE;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ *  nvram_query_folder_index
+ * DESCRIPTION
+ *  Get the index of folder
+ * PARAMETERS
+ *  category
+ * RETURNS
+ *  Success or Fail
+ *****************************************************************************/
+nvram_folder_enum nvram_query_folder_index(nvram_category_enum category)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    nvram_folder_enum folder_index;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+#ifdef __NVRAM_MULTI_FOLDERS__
+    if (NVRAM_IS_CATEGORY_INTERNAL(category))
+    {
+        folder_index = NVRAM_NVD_CORE;
+    }
+    else if (NVRAM_IS_CATEGORY_CALIBRAT(category))
+    {
+        folder_index = NVRAM_NVD_CALI;
+    }
+    else if (NVRAM_IS_CATEGORY_IMPORTANT(category))
+    {
+        folder_index = NVRAM_NVD_IMPT;
+    }
+#ifdef __CCCIFS_SUPPORT__
+    else if (category & NVRAM_CATEGORY_IMPORTANT_L4)
+    {
+        folder_index = NVRAM_NVD_IMPNT;
+    }
+    else if (NVRAM_IS_CATEGORY_IMPORTANT_L1(category))
+    {
+        folder_index = NVRAM_NVD_IMPNT;
+    }
+#endif
+    #ifdef __NVRAM_CUSTOM_SENSITIVE__
+    else if (NVRAM_IS_CATEGORY_CUSTOM_SENSITIVE(category))
+    {
+        folder_index = NVRAM_NVD_CUST;
+    }
+    #endif
+    else
+#endif /* __NVRAM_MULTI_FOLDERS__ */
+    {
+        folder_index = NVRAM_NVD_DATA;
+    }
+
+    return folder_index;
+}
+
+ 
+/*****************************************************************************
+ * FUNCTION
+ *  nvram_util_make_lid_filename
+ * DESCRIPTION
+ * PARAMETERS
+ * RETURNS
+ *****************************************************************************/
+void nvram_util_make_lid_filename(nvram_ltable_entry_struct *ldi, NVRAM_FILE_NAME nvramname, kal_bool first_copy)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+
+    if (ldi == NULL)
+    {
+        NVRAM_TRC_HIGH("Empty ldi ");
+        return;
+    }
+
+#ifdef __NVRAM_PSEUDO_MERGE__
+    if (NVRAM_IS_ATTR_PACKAGE(ldi->attr))
+    {
+        NVRAM_MAKE_PACKAGE_FILENAME(nvramname, 'A');
+        return;
+    }
+#endif
+
+    if (NVRAM_IS_ATTR_MULTIPLE(ldi->attr))
+    {
+        if (first_copy)
+        {
+            NVRAM_MAKE_LID_FILENAME(nvramname, ldi->fileprefix, 'A', ldi->fileverno);
+        }
+        else
+        {
+            NVRAM_MAKE_LID_FILENAME(nvramname, ldi->fileprefix, 'B', ldi->fileverno);
+        }
+    }
+    else
+    {
+        NVRAM_MAKE_LID_FILENAME(nvramname, ldi->fileprefix, '_', ldi->fileverno);
+    }
+
+    return;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ *  nvram_query_file_name
+ * DESCRIPTION
+ *  Get file full name
+ * PARAMETERS
+ *  folder_idx  :
+ *  nvramname   : nvram file
+ *  filename    : full name of nvram file
+ * RETURNS
+ *  Success or Fail
+ *****************************************************************************/
+kal_wchar * nvram_query_file_name(nvram_folder_enum folder_idx, kal_char *nvramname, kal_wchar *filename)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    switch (folder_idx)
+    {
+        case NVRAM_NVD_DATA:
+        {
+            NVRAM_FS_MAKE_LID_PATH_FILENAME_1(filename, nvramname);
+            break;
+        }
+    #ifdef __NVRAM_MULTI_FOLDERS__
+        case NVRAM_NVD_CORE:
+        {
+            NVRAM_FS_MAKE_CORE_PATH_FILENAME(filename, nvramname);
+            break;
+        }
+        case NVRAM_NVD_CALI:
+        {
+            NVRAM_FS_MAKE_CRITICAL_CALIBRAT_PATH_FILENAME(filename, nvramname);
+            break;
+        }
+        case NVRAM_NVD_IMPT:
+        {
+            NVRAM_FS_MAKE_CRITICAL_IMEI_PATH_FILENAME(filename, nvramname);
+            break;
+        }
+        #ifdef __CCCIFS_SUPPORT__
+        case NVRAM_NVD_IMPNT:
+        {
+            NVRAM_FS_MAKE_IMPORTNT_PATH_FILENAME(filename, nvramname);
+            break;
+        }
+        #endif
+        #ifdef __NVRAM_CUSTOM_SENSITIVE__
+        case NVRAM_NVD_CUST:
+        {
+            NVRAM_FS_MAKE_CUST_PATH_FILENAME(filename, nvramname);
+            break;
+        }
+        #endif
+    #endif /* __NVRAM_MULTI_FOLDERS__ */
+    #ifdef __NVRAM_BACKUP_DISK_FAT__
+        case NVRAM_NVD_BAK:
+        {
+            NVRAM_FS_MAKE_BACKUP_PATH_FILENAME(filename, nvramname);
+            break;
+        }
+    #endif
+        default:
+        {
+            NVRAM_TRC_HIGH("Wrong folder idex !");
+            break;
+        }
+    }
+
+    return filename;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ *  filepath_finder
+ * DESCRIPTION
+ *  Get lid filepath
+ * PARAMETERS
+ *  ldi   : nvram lid entry
+ * RETURNS
+ *  Full path
+ *****************************************************************************/
+kal_char* path_finder(nvram_ltable_entry_struct *ldi, kal_char *src_path)
+{
+    NVRAM_FILE_NAME nvramname;
+    nvram_folder_enum folder_idx;
+    
+    folder_idx = nvram_query_folder_index(ldi->category);
+
+    /* prefix */
+    if (NVRAM_IS_CATEGORY_SECUPACK(ldi->category))
+    {
+        ldi->fileprefix[0] = 'S';
+        ldi->fileprefix[1] = 'T';
+    }
+    nvram_util_make_lid_filename(ldi, nvramname, KAL_TRUE);
+    nvram_query_file_name(folder_idx, nvramname, src_path);
+    return src_path;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ *  filepath_finder
+ * DESCRIPTION
+ *  Get lid filepath
+ * PARAMETERS
+ *  ldi   : nvram lid entry
+ * RETURNS
+ *  Full path
+ *****************************************************************************/
+kal_uint32 file_size_collector(nvram_ltable_entry_struct *ldi)
+{
+    kal_uint32 onefilesize = 0;
+    kal_uint32 onefilefssize = 0;   // 32 byte padding
+    kal_uint32 remainLen = 0;
+    static kal_uint32 esfilesize = 0;
+    kal_uint32 nvram_checksum_size = 0;
+    
+    #ifdef __NV_CHKSUM_ENHANCE__
+    nvram_checksum_size = get_checksum_size(ldi); // get nvram_checksum_size , read CUSTOM_CHK_ALGO_CONFIG.
+    #else
+    nvram_checksum_size = NVRAM_CHKSUM_SIZE;
+    #endif
+    
+    if(ldi->attr & NVRAM_ATTR_CONFIDENTIAL
+        #ifdef __NVRAM_BIND_TO_CHIP_CIPHER__ //if HW encrypt is enable
+        || ldi->attr & NVRAM_ATTR_MSP
+        #endif
+      )
+    {
+        remainLen = NVRAM_MSP_ALIGNMENT_REMAINDER(ldi->size + nvram_checksum_size);
+        onefilesize = (ldi->size + nvram_checksum_size + remainLen)*ldi->total_records + NVRAM_LDI_HEADER_SIZE;
+    }
+    else
+    {
+        onefilesize = (ldi->size + nvram_checksum_size) * ldi->total_records + NVRAM_LDI_HEADER_SIZE;
+    }
+    if(ldi->attr & NVRAM_ATTR_CHKSUM_INTEGRATE)
+    {   
+        printf("checksum integrate: lid: %s\n", ldi->str_LID);
+        onefilesize = onefilesize + NVRAM_LDI_APPENDIX_HEADER_SIZE + nvram_checksum_size * ldi->total_records;
+    }
+    return onefilesize;
+}
+
+void cache_header_writer(FILE *fp, nvram_lid_cache_header *cache_header)
+{
+	fprintf(fp, "nvram_lid_cache_header cache_info_header = {\n");
+
+    fprintf(fp, "\t%u,\n", cache_header->cache_lid_num);
+    fprintf(fp, "\t%u,\n", cache_header->table_index_offset);
+    fprintf(fp, "\t%u,\n", cache_header->table_index_size);
+    fprintf(fp, "\t%u,\n", cache_header->dirty_mapping_offset);
+    fprintf(fp, "\t%u,\n", cache_header->valid_mapping_offset);
+    fprintf(fp, "\t%u,\n", cache_header->dirty_mapping_size);
+    fprintf(fp, "\t%u,\n", cache_header->cache_table_offset);
+    fprintf(fp, "\t%u\n", cache_header->cache_table_size);
+    fprintf(fp, "};\n\n");
+}
+
+
+void cache_table_writer(FILE *fp, nvram_lid_cache_table_struct *cache_info)
+{
+    fprintf(fp, "\t{\n");
+    fprintf(fp, "\t\t%hu,\n", cache_info->LID);
+    fprintf(fp, "\t\t%u,\n", cache_info->total_records);
+	fprintf(fp, "\t\t%u,\n", cache_info->file_length);
+	fprintf(fp, "\t\t%u,\n", cache_info->cache_offset);
+	fprintf(fp, "\t\t%u,\n", cache_info->dirty_offset);
+	fprintf(fp, "\t\t%u,\n", cache_info->valid_offset);
+	fprintf(fp, "\t\t\"%s\"\n", cache_info->file_path);
+	fprintf(fp, "\t},\n");
+}
+
+void cache_header_generator(FILE *fp, nvram_lid_cache_header *cache_info_header)
+{
+    kal_uint32 data_base_offset = 0;
+    // align 32byte
+    data_base_offset = sizeof(nvram_lid_cache_header) + sizeof(nvram_lid_cache_table_struct)* nvram_gen_total_cache_lid;
+    data_base_offset = ((data_base_offset + SHARE_MEM_64BYTE_ALIGN -1)/SHARE_MEM_64BYTE_ALIGN)*SHARE_MEM_64BYTE_ALIGN;
+    printf("nvram gen total cache lid num: %d\n", nvram_gen_total_cache_lid);
+    // Fill cache info header
+    cache_info_header->cache_lid_num = nvram_gen_total_cache_lid;
+    cache_info_header->table_index_offset = sizeof(nvram_lid_cache_header);
+    cache_info_header->table_index_size = sizeof(nvram_lid_cache_table_struct)* nvram_gen_total_cache_lid;
+    cache_info_header->dirty_mapping_offset = data_base_offset;
+	dirty_bit_table_length = ((dirty_bit_table_length + SHARE_MEM_64BYTE_ALIGN -1)/SHARE_MEM_64BYTE_ALIGN)*SHARE_MEM_64BYTE_ALIGN; //align to cache line
+    cache_info_header->dirty_mapping_size = dirty_bit_table_length;
+    data_base_offset = data_base_offset + dirty_bit_table_length;
+    cache_info_header->valid_mapping_offset = data_base_offset;
+    
+    // valid block has same size as dirty block
+    data_base_offset += dirty_bit_table_length;
+    cache_info_header->cache_table_offset = data_base_offset;
+    cache_info_header->cache_table_size = cache_data_offset;
+    // 
+    cache_header_writer(fp, cache_info_header);
+
+    if ((cache_info_header->cache_table_offset + cache_info_header->cache_table_size) >= SHARE_MEMORY_SIZE) {
+        fprintf(stderr, "Error: Please contact NVRAM owner, the NV Cache Share Memory Size Too small. currently total LID size is: %x.\n",(cache_info_header->cache_table_offset + cache_info_header->cache_table_size));
+        exit(-1);
+    }
+    // return cache_info_header;
+}
+
+void gen_cache_file(char *base_path)
+{
+	char cache_header_path[NVRAM_AUTO_GEN_MAX_PATH_LEN];
+	char cache_source_pathname[NVRAM_AUTO_GEN_MAX_PATH_LEN];
+	FILE *fp;
+
+	sprintf(cache_header_path, "nvram_auto_gen/nvram_cache_info.h");
+	nvram_gen_create_file(&fp,base_path,cache_header_path);
+	fprintf(fp, COPYRIGHTS_HEADER, cache_header_path);
+	fprintf(fp, "#ifndef NVRAM_CACHE_INFO_H\n");
+	fprintf(fp, "#define NVRAM_CACHE_INFO_H\n");
+    fprintf(fp, "#include \"nvram_cache.h\"\n");
+    fprintf(fp, "#include \"nvram_enums.h\"\n");
+    fprintf(fp, "#include \"kal_general_types.h\"\n\n");
+	fprintf(fp, "extern nvram_lid_cache_table_struct cache_info_table[];\n");
+	fprintf(fp, "extern nvram_lid_cache_header cache_info_header;\n\n");
+	fprintf(fp, "#endif /*NVRAM_CACHE_INFO_H*/\n");
+
+	nvram_gen_close_file(&fp);
+
+}
+
+
+int ltable_enum_cmp(nvram_ltable_entry_struct *ent_a, nvram_ltable_entry_struct *ent_b)
+{
+    return (int)(ent_a->LID - ent_b->LID);
+}
+
+
+/*****************************************************************************
+ * FUNCTION
+ *  ltable_enum_sort
+ * DESCRIPTION
+ *  Sort lid by LID enum 
+ * PARAMETERS
+ *  
+ * RETURNS
+ *  
+ *****************************************************************************/
+void lid_table_enum_sort(nvram_ltable_entry_struct *lid_ltable_array)
+{
+	 /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+	// extern unsigned char nvram_ltable_begin, nvram_ltable_end;
+    kal_uint32 i = 0;
+    size_t table_size = sizeof(nvram_ltable_entry_struct);
+    printf("cache_table size: %d\n", table_size);
+    qsort(lid_ltable_array, nvram_gen_total_lid, table_size, ltable_enum_cmp);
+}
+
+
+/*****************************************************************************
+ * FUNCTION
+ *  cache_info_table_generator
+ * DESCRIPTION
+ *  Generate cache info table
+ * PARAMETERS
+ *  
+ * RETURNS
+ *  
+ *****************************************************************************/
+void cache_info_table_generator(char *base_path)
+{
+    /*******************************************/
+    extern unsigned char nvram_ltable_begin, nvram_ltable_end;
+    kal_uint32 i = 0, tb_size;
+	
+    char cache_file_path[NVRAM_AUTO_GEN_MAX_PATH_LEN];
+	char cache_file_name[] = "nvram_cache_info.c";
+    FILE *fp;
+    nvram_ltable_entry_struct *ldi;
+	nvram_ltable_entry_struct *ltable_bak;
+    nvram_lid_cache_table_struct info_item = {};
+    // nvram_lid_cache_table_struct *cache_info_array;
+    nvram_lid_cache_header cache_info_header;
+	
+    cache_data_offset = 0;
+    dirty_bit_table_offset = 0;
+    dirty_bit_table_length = 0;
+    sprintf(cache_file_path, "%s/nvram_auto_gen/%s", base_path, cache_file_name);
+	tb_size = (kal_uint32)(&nvram_ltable_end - &nvram_ltable_begin);
+	ltable_bak = (nvram_ltable_entry_struct *)malloc(tb_size); 
+	memcpy(ltable_bak, logical_data_item_table,tb_size);
+	lid_table_enum_sort(ltable_bak);
+
+	fp = fopen(cache_file_path, "w");
+	fprintf(fp, COPYRIGHTS_HEADER, cache_file_name);
+	fprintf(fp, "#include \"nvram_cache_info.h\"\n");
+	fprintf(fp, "\n");	
+	fprintf(fp, "nvram_lid_cache_table_struct cache_info_table[] = {\n");
+
+	for(i=0; i< nvram_gen_total_lid; i++)
+    {
+        ldi = &ltable_bak[i];
+        #ifdef __NVRAM_PARTIAL_CACHE__
+        if(autogen_is_in_noncache_list(ldi->LID))
+        {
+            continue;
+        }
+        #endif
+		info_item.LID = ldi->LID;
+        info_item.total_records = ldi->total_records;
+   
+        info_item.cache_offset = cache_data_offset;
+        // find file lenght
+		info_item.file_length = file_size_collector(ldi);
+		cache_data_offset += ((info_item.file_length+SHARE_MEM_64BYTE_ALIGN-1)/SHARE_MEM_64BYTE_ALIGN)*SHARE_MEM_64BYTE_ALIGN; //align to cache line
+        info_item.dirty_offset = dirty_bit_table_offset;
+        info_item.valid_offset = dirty_bit_table_offset;
+        dirty_bit_table_offset += ((ldi->total_records + 1 + DIRTY_BLOCK_SIZE -1)/DIRTY_BLOCK_SIZE) * DIRTY_4BYTE_ALIGN;
+		path_finder(ldi, info_item.file_path);
+        
+		// cache_table_writer(fp, &info_item);
+		fprintf(fp, "\t{\n");
+	    fprintf(fp, "\t\t%hu,\n", info_item.LID);
+        fprintf(fp, "\t\t%hu,\n", 0);
+	    fprintf(fp, "\t\t%u,\n", info_item.total_records);
+		fprintf(fp, "\t\t%u,\n", info_item.file_length);
+		fprintf(fp, "\t\t%u,\n", info_item.cache_offset);
+		fprintf(fp, "\t\t%u,\n", info_item.dirty_offset);
+		fprintf(fp, "\t\t%u,\n", info_item.valid_offset);
+		fprintf(fp, "\t\t\"%s\"\n", info_item.file_path);
+		fprintf(fp, "\t},\n");
+        nvram_gen_total_cache_lid += 1;
+    }
+	fprintf(fp, "};\n\n");
+	dirty_bit_table_length = dirty_bit_table_offset;
+	// cache header;
+    cache_header_generator(fp, &cache_info_header);
+	fclose(fp);
+    gen_cache_file(base_path);
+	free(ltable_bak);
+}
+
+
+#endif /* NVRAM_NOT_PRESENT */
diff --git a/mcu/tools/NVRAMStatistic/src/nvram_gen_mmi_cache.c b/mcu/tools/NVRAMStatistic/src/nvram_gen_mmi_cache.c
new file mode 100644
index 0000000..7a3242c
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/src/nvram_gen_mmi_cache.c
@@ -0,0 +1,1873 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2006
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ * nvram_auto_gen.c
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   This file is intends for generating NVRAM information.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+#ifndef NVRAM_NOT_PRESENT
+#if defined(NEPTUNE_MMI)
+/*****************************************************************************
+* Include
+*****************************************************************************/
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <io.h>
+
+#include "nvram_auto_gen.h"
+
+#if defined(__MMI_FMI__)
+#include "nvram_common_defs.h"
+#include "nvram_mmi_cache_defs.h"
+#endif
+
+#define BYTE_ENTRY_COUNT    (NVRAM_CACHE_SIZE)
+#define SHORT_ENTRY_COUNT   (NVRAM_CACHE_SIZE >> 1)
+#define DOUBLE_ENTRY_COUNT  (NVRAM_CACHE_SIZE >> 3)
+
+extern mmi_cache_byte_entry common_mmi_cache_byte[];
+extern mmi_cache_short_entry common_mmi_cache_short[];
+extern mmi_cache_double_entry common_mmi_cache_double[];
+
+extern mmi_cache_byte_entry custom_mmi_cache_byte[];
+extern mmi_cache_short_entry custom_mmi_cache_short[];
+extern mmi_cache_double_entry custom_mmi_cache_double[];
+
+#ifndef __OPTR_NONE__
+extern mmi_cache_byte_entry operator_mmi_cache_byte[];
+extern mmi_cache_short_entry operator_mmi_cache_short[];
+extern mmi_cache_double_entry operator_mmi_cache_double[];
+#endif /* __OPTR_NONE__ */
+
+static int nvram_gen_compare_byte(const void *a, const void *b);
+static int nvram_gen_compare_short(const void *a, const void *b);
+static int nvram_gen_compare_double(const void *a, const void *b);
+static int nvram_sort_byte(void);
+static int nvram_sort_short(void);
+static int nvram_sort_double(void);
+static int nvram_merge_byte(
+            mmi_cache_byte_entry[],
+            int,
+            mmi_cache_byte_entry[],
+            int,
+            mmi_cache_byte_entry[]);
+static int nvram_merge_short(
+            mmi_cache_short_entry[],
+            int,
+            mmi_cache_short_entry[],
+            int,
+            mmi_cache_short_entry[]);
+static int nvram_merge_double(
+            mmi_cache_double_entry[],
+            int,
+            mmi_cache_double_entry[],
+            int,
+            mmi_cache_double_entry[]);
+
+/* get user fills count */
+static int nvram_get_byte_entry_count(mmi_cache_byte_entry[]);
+static int nvram_get_short_entry_count(mmi_cache_short_entry[]);
+static int nvram_get_double_entry_count(mmi_cache_double_entry[]);
+
+/* The following should be initialized in main function */
+static int nvram_common_byte_count;
+static int nvram_common_short_count;
+static int nvram_common_double_count;
+
+static int nvram_custom_byte_count;
+static int nvram_custom_short_count;
+static int nvram_custom_double_count;
+
+/* if operator exists */
+#ifndef __OPTR_NONE__
+static int nvram_operator_byte_count;
+static int nvram_operator_short_count;
+static int nvram_operator_double_count;
+#endif
+
+
+/* After merge */
+/* used to save the result of merging common and custom part */
+static int nvram_byte_count;
+static int nvram_short_count;
+static int nvram_double_count;
+
+/* used to save the result of final result */
+#ifndef __OPTR_NONE__
+static int nvram_op_byte_count;
+static int nvram_op_short_count;
+static int nvram_op_double_count;
+#endif /* __OPTR_NONE__ */
+
+
+/* used to save the final result */
+static mmi_cache_byte_entry nvram_mmi_cache_byte[BYTE_ENTRY_COUNT];
+static mmi_cache_short_entry nvram_mmi_cache_short[SHORT_ENTRY_COUNT];
+static mmi_cache_double_entry nvram_mmi_cache_double[DOUBLE_ENTRY_COUNT];
+
+
+/* used to save the result of merging common and custom part */
+#ifndef __OPTR_NONE__
+static mmi_cache_byte_entry nvram_op_byte[BYTE_ENTRY_COUNT];
+static mmi_cache_short_entry nvram_op_short[SHORT_ENTRY_COUNT];
+static mmi_cache_double_entry nvram_op_double[DOUBLE_ENTRY_COUNT];
+#endif /* __OPTR_NONE__ */
+static int nvram_restore_cache_byte[NVRAM_APP_TOTAL][BYTE_ENTRY_COUNT];
+static int nvram_restore_cache_short[NVRAM_APP_TOTAL][SHORT_ENTRY_COUNT];
+static int nvram_restore_cache_double[NVRAM_APP_TOTAL][DOUBLE_ENTRY_COUNT];
+/* record total number of each application */
+static int nvram_restore_byte_idx[NVRAM_APP_TOTAL];
+static int nvram_restore_short_idx[NVRAM_APP_TOTAL];
+static int nvram_restore_double_idx[NVRAM_APP_TOTAL];
+
+/* record max length of id str */
+static int nvram_max_length_byte_id_str;
+static int nvram_max_length_short_id_str;
+static int nvram_max_length_double_id_str;
+
+static char nvram_auto_gen_output_path[NVRAM_AUTO_GEN_MAX_PATH_LEN];
+
+/*****************************************************************************
+* FUNCTION
+*  nvram_gen_compare_byte
+* DESCRIPTION
+*  used by quick sort function
+* PARAMETERS
+*  a    [IN]
+*  b    [IN]
+* RETURNS
+*  none
+*****************************************************************************/
+int nvram_gen_compare_byte(const void *a, const void *b)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    mmi_cache_byte_entry *former, *latter;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    former = a;
+    latter = b;
+    if ((former->id < 0 || former->id >= BYTE_ENTRY_COUNT) ||
+        (latter->id < 0 || latter->id >= BYTE_ENTRY_COUNT))
+    {
+        /* assert(0); */
+        return 0;
+    }
+    if (former->id < latter->id)
+    {
+        return -1;
+    }
+    else if (former->id > latter->id)
+    {
+        return 1;
+    }
+    else
+    {
+        return 0;
+    }
+    return 0;
+}
+
+
+/*****************************************************************************
+* FUNCTION
+*  nvram_gen_compare_short
+* DESCRIPTION
+*  used by quick sort function
+* PARAMETERS
+*  a    [IN]
+*  b    [IN]
+* RETURNS
+*  none
+*****************************************************************************/
+int nvram_gen_compare_short(const void *a, const void *b)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    mmi_cache_short_entry *former, *latter;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    former = a;
+    latter = b;
+    if ((former->id < 0 || former->id >= SHORT_ENTRY_COUNT) ||
+        (latter->id < 0 || latter->id >= SHORT_ENTRY_COUNT))
+    {
+        /* assert(0); */
+        return 0;
+    }
+    if (former->id < latter->id)
+    {
+        return -1;
+    }
+    else if (former->id > latter->id)
+    {
+        return 1;
+    }
+    else
+    {
+        return 0;
+    }
+    return 0;
+}
+
+
+/*****************************************************************************
+* FUNCTION
+*  nvram_gen_compare_double
+* DESCRIPTION
+*  used by quick sort function
+* PARAMETERS
+*  a    [IN]
+*  b    [IN]
+* RETURNS
+*  none
+*****************************************************************************/
+int nvram_gen_compare_double(const void *a, const void *b)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    mmi_cache_double_entry *former, *latter;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    former = a;
+    latter = b;
+    if ((former->id < 0 || former->id >= DOUBLE_ENTRY_COUNT) ||
+        (latter->id < 0 || latter->id >= DOUBLE_ENTRY_COUNT))
+    {
+        /* assert(0); */
+        return 0;
+    }
+    if (former->id < latter->id)
+    {
+        return -1;
+    }
+    else if (former->id > latter->id)
+    {
+        return 1;
+    }
+    else
+    {
+        return 0;
+    }
+    return 0;
+}
+
+
+/*****************************************************************************
+* FUNCTION
+*   nvram_merge_byte
+* DESCRIPTION
+*   merge two byte_cache array
+* PARAMETERS
+*   low_pri      [IN]
+*   low_count    [IN]
+*   high_pri     [IN]
+*   high_count   [IN]
+*   result_array [OUT]
+* RETURNS
+*   the count of result array after merging
+*****************************************************************************/
+int nvram_merge_byte(
+        mmi_cache_byte_entry low_pri[],
+        int low_count,
+        mmi_cache_byte_entry high_pri[],
+        int high_count,
+        mmi_cache_byte_entry result_array[]
+        )
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    int i, low_pri_p, high_pri_p;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    i = 0;
+    low_pri_p = 0;
+    high_pri_p = 0;
+    while (low_pri_p < low_count || high_pri_p < high_count)
+    {
+        if (low_pri_p >= low_count)
+        {
+            /* Avoid same */
+            if (i > 0)
+            {
+                if (result_array[i - 1].id == high_pri[high_pri_p].id)
+                {
+                    return -1;
+                }
+            }
+            memcpy(result_array + i,
+                high_pri + high_pri_p,
+                sizeof(mmi_cache_byte_entry));
+            i++;
+            high_pri_p++;
+            continue;
+        }
+        if (high_pri_p >= high_count)
+        {
+            /* Avoid same */
+            if (i > 0)
+            {
+                if (result_array[i - 1].id == low_pri[low_pri_p].id)
+                {
+                    return -1;
+                }
+            }
+            memcpy(result_array + i,
+                low_pri + low_pri_p,
+                sizeof(mmi_cache_byte_entry));
+            i++;
+            low_pri_p++;
+            continue;
+        }
+        if (low_pri[low_pri_p].id == high_pri[high_pri_p].id)
+        {
+            /* Avoid same */
+            if (i > 0)
+            {
+                if (result_array[i - 1].id == high_pri[high_pri_p].id)
+                {
+                    return -1;
+                }
+            }
+            memcpy(result_array + i,
+                high_pri + high_pri_p,
+                sizeof(mmi_cache_byte_entry));
+            i++;
+            low_pri_p++;
+            high_pri_p++;
+        }
+        else if (low_pri[low_pri_p].id < high_pri[high_pri_p].id)
+        {
+            /* Avoid same */
+            if (i > 0)
+            {
+                if (result_array[i - 1].id == low_pri[low_pri_p].id)
+                {
+                    return -1;
+                }
+            }
+            memcpy(result_array + i,
+                low_pri + low_pri_p,
+                sizeof(mmi_cache_byte_entry));
+            i++;
+            low_pri_p++;
+        }
+        else
+        {
+            /* Avoid same */
+            if (i > 0)
+            {
+                if (result_array[i - 1].id == high_pri[high_pri_p].id)
+                {
+                    return -1;
+                }
+            }
+            memcpy(result_array + i,
+                high_pri + high_pri_p,
+                sizeof(mmi_cache_byte_entry));
+            i++;
+            high_pri_p++;
+        }
+    }
+    return i;
+}
+
+
+/*****************************************************************************
+* FUNCTION
+*   nvram_merge_short
+* DESCRIPTION
+*   merge two short_cache array
+* PARAMETERS
+*   low_pri      [IN]
+*   low_count    [IN]
+*   high_pri     [IN]
+*   high_count   [IN]
+*   result_array [OUT]
+* RETURNS
+*   the count of result array after merging
+*****************************************************************************/
+int nvram_merge_short(
+        mmi_cache_short_entry low_pri[],
+        int low_count,
+        mmi_cache_short_entry high_pri[],
+        int high_count,
+        mmi_cache_short_entry result_array[])
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    int i, low_pri_p, high_pri_p;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    i = 0;
+    low_pri_p = 0;
+    high_pri_p = 0;
+    while (low_pri_p < low_count || high_pri_p < high_count)
+    {
+        if (low_pri_p >= low_count)
+        {
+            /* Avoid same */
+            if (i > 0)
+            {
+                if (result_array[i - 1].id == high_pri[high_pri_p].id)
+                {
+                    return -1;
+                }
+            }
+            memcpy(result_array + i,
+                high_pri + high_pri_p,
+                sizeof(mmi_cache_short_entry));
+            i++;
+            high_pri_p++;
+            continue;
+        }
+        if (high_pri_p >= high_count)
+        {
+            /* Avoid same */
+            if (i > 0)
+            {
+                if (result_array[i - 1].id == low_pri[low_pri_p].id)
+                {
+                    return -1;
+                }
+            }
+            memcpy(result_array + i,
+                low_pri + low_pri_p,
+                sizeof(mmi_cache_short_entry));
+            i++;
+            low_pri_p++;
+            continue;
+        }
+        if (low_pri[low_pri_p].id == high_pri[high_pri_p].id)
+        {
+            /* Avoid same */
+            if (i > 0)
+            {
+                if (result_array[i - 1].id == high_pri[high_pri_p].id)
+                {
+                    return -1;
+                }
+            }
+            memcpy(result_array + i,
+                high_pri + high_pri_p,
+                sizeof(mmi_cache_short_entry));
+            i++;
+            low_pri_p++;
+            high_pri_p++;
+        }
+        else if (low_pri[low_pri_p].id < high_pri[high_pri_p].id)
+        {
+            /* Avoid same */
+            if (i > 0)
+            {
+                if (result_array[i - 1].id == low_pri[low_pri_p].id)
+                {
+                    return -1;
+                }
+            }
+            memcpy(result_array + i,
+                low_pri + low_pri_p,
+                sizeof(mmi_cache_short_entry));
+            i++;
+            low_pri_p++;
+        }
+        else
+        {
+            /* Avoid same */
+            if (i > 0)
+            {
+                if (result_array[i - 1].id == high_pri[high_pri_p].id)
+                {
+                    return -1;
+                }
+            }
+            memcpy(result_array + i,
+                high_pri + high_pri_p,
+                sizeof(mmi_cache_short_entry));
+            i++;
+            high_pri_p++;
+        }
+    }
+    return i;
+}
+
+
+/*****************************************************************************
+* FUNCTION
+*   nvram_merge_double
+* DESCRIPTION
+*   merge two double_cache array
+* PARAMETERS
+*   low_pri      [IN]
+*   low_count    [IN]
+*   high_pri     [IN]
+*   high_count   [IN]
+*   result_array [OUT]
+* RETURNS
+*   the count of result array after merging
+*****************************************************************************/
+int nvram_merge_double(
+        mmi_cache_double_entry low_pri[],
+        int low_count,
+        mmi_cache_double_entry high_pri[],
+        int high_count,
+        mmi_cache_double_entry result_array[])
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    int i, low_pri_p, high_pri_p;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    i = 0;
+    low_pri_p = 0;
+    high_pri_p = 0;
+    while (low_pri_p < low_count || high_pri_p < high_count)
+    {
+        if (low_pri_p >= low_count)
+        {
+            /* Avoid same */
+            if (i > 0)
+            {
+                if (result_array[i - 1].id == high_pri[high_pri_p].id)
+                {
+                    return -1;
+                }
+            }
+            memcpy(result_array + i,
+                high_pri + high_pri_p,
+                sizeof(mmi_cache_double_entry));
+            i++;
+            high_pri_p++;
+            continue;
+        }
+        if (high_pri_p >= high_count)
+        {
+            /* Avoid same */
+            if (i > 0)
+            {
+                if (result_array[i - 1].id == low_pri[low_pri_p].id)
+                {
+                    return -1;
+                }
+            }
+            memcpy(result_array + i,
+                low_pri + low_pri_p,
+                sizeof(mmi_cache_double_entry));
+            i++;
+            low_pri_p++;
+            continue;
+        }
+        if (low_pri[low_pri_p].id == high_pri[high_pri_p].id)
+        {
+            /* Avoid same */
+            if (i > 0)
+            {
+                if (result_array[i - 1].id == high_pri[high_pri_p].id)
+                {
+                    return -1;
+                }
+            }
+            memcpy(result_array + i,
+                high_pri + high_pri_p,
+                sizeof(mmi_cache_double_entry));
+            i++;
+            low_pri_p++;
+            high_pri_p++;
+        }
+        else if (low_pri[low_pri_p].id < high_pri[high_pri_p].id)
+        {
+            /* Avoid same */
+            if (i > 0)
+            {
+                if (result_array[i - 1].id == low_pri[low_pri_p].id)
+                {
+                    return -1;
+                }
+            }
+            memcpy(result_array + i,
+                low_pri + low_pri_p,
+                sizeof(mmi_cache_double_entry));
+            i++;
+            low_pri_p++;
+        }
+        else
+        {
+            /* Avoid same */
+            if (i > 0)
+            {
+                if (result_array[i - 1].id == high_pri[high_pri_p].id)
+                {
+                    return -1;
+                }
+            }
+            memcpy(result_array + i,
+                high_pri + high_pri_p,
+                sizeof(mmi_cache_double_entry));
+            i++;
+            high_pri_p++;
+        }
+    }
+    return i;
+}
+
+
+/*****************************************************************************
+* FUNCTION
+*   nvram_get_byte_entry_count
+* DESCRIPTION
+*   get entries count of a byte_cache
+* PARAMETERS
+*   mmi_cache_byte_array    [IN]
+* RETURNS
+*   the count of the entries
+*****************************************************************************/
+int nvram_get_byte_entry_count(mmi_cache_byte_entry mmi_cache_byte_array[])
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    int i;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    i = 0;
+    while (1)
+    {
+        if (mmi_cache_byte_array[i].id == 0xFF &&
+            mmi_cache_byte_array[i].value == 0xFF &&
+            *(mmi_cache_byte_array[i].id_str) == '\0')
+        {
+            break;
+        }
+        else
+        {
+            i++;
+        }
+        if (i >= BYTE_ENTRY_COUNT)
+        {
+            /* exceed the max count */
+            return -1;
+        }
+    }
+    return i;
+}
+
+
+/*****************************************************************************
+* FUNCTION
+*   nvram_get_short_entry_count
+* DESCRIPTION
+*   get entries count of a short_cache
+* PARAMETERS
+*   mmi_cache_short_array    [IN]
+* RETURNS
+*   the count of the entries
+*****************************************************************************/
+int nvram_get_short_entry_count(mmi_cache_short_entry mmi_cache_short_array[])
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    int i;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    i = 0;
+    while (1)
+    {
+        if (mmi_cache_short_array[i].id == 0xFF &&
+            mmi_cache_short_array[i].value1 == 0xFF &&
+            mmi_cache_short_array[i].value2 == 0xFF &&
+            *(mmi_cache_short_array[i].id_str) == '\0')
+        {
+            break;
+        }
+        else
+        {
+            i++;
+        }
+        if (i >= SHORT_ENTRY_COUNT)
+        {
+            /* exceed the max count */
+            return -1;
+        }
+    }
+    return i;
+}
+
+
+/*****************************************************************************
+* FUNCTION
+*   nvram_get_double_entry_count
+* DESCRIPTION
+*   get entries count of a double_cache
+* PARAMETERS
+*   mmi_cache_double_array    [IN]
+* RETURNS
+*   the count of the entries
+*****************************************************************************/
+int nvram_get_double_entry_count(mmi_cache_double_entry mmi_cache_double_array[])
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    int i;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    i = 0;
+    while (1)
+    {
+        if (mmi_cache_double_array[i].id == 0xFF &&
+            mmi_cache_double_array[i].value1 == 0xFF &&
+            mmi_cache_double_array[i].value2 == 0xFF &&
+            mmi_cache_double_array[i].value3 == 0xFF &&
+            mmi_cache_double_array[i].value4 == 0xFF &&
+            mmi_cache_double_array[i].value5 == 0xFF &&
+            mmi_cache_double_array[i].value6 == 0xFF &&
+            mmi_cache_double_array[i].value7 == 0xFF &&
+            mmi_cache_double_array[i].value8 == 0xFF &&
+            *(mmi_cache_double_array[i].id_str) == '\0')
+        {
+            break;
+        }
+        else
+        {
+            i++;
+        }
+        if (i >= DOUBLE_ENTRY_COUNT)
+        {
+            /* exceed the max count */
+            return -1;
+        }
+    }
+    return i;
+}
+
+
+/*****************************************************************************
+* FUNCTION
+*   nvram_sort_byte
+* DESCRIPTION
+*   sort one byte_cache
+* PARAMETERS
+*   none
+* RETURNS
+*   none
+*****************************************************************************/
+int nvram_sort_byte(void)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    /* sort common */
+    qsort((void *)common_mmi_cache_byte, nvram_common_byte_count, sizeof(mmi_cache_byte_entry), &nvram_gen_compare_byte);
+
+    /* sort custom */
+    qsort((void *)custom_mmi_cache_byte, nvram_custom_byte_count, sizeof(mmi_cache_byte_entry), &nvram_gen_compare_byte);
+
+    /* sort operator */
+#ifndef __OPTR_NONE__
+    qsort((void *)operator_mmi_cache_byte, nvram_operator_byte_count, sizeof(mmi_cache_byte_entry), &nvram_gen_compare_byte);
+#endif
+    return 0;
+}
+
+
+/*****************************************************************************
+* FUNCTION
+*   nvram_sort_short
+* DESCRIPTION
+*   sort one short_cache
+* PARAMETERS
+*   none
+* RETURNS
+*   none
+*****************************************************************************/
+int nvram_sort_short(void)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    /* sort common */
+    qsort((void *)common_mmi_cache_short, nvram_common_short_count, sizeof(mmi_cache_short_entry), &nvram_gen_compare_short);
+
+    /* sort custom */
+    qsort((void *)custom_mmi_cache_short, nvram_custom_short_count, sizeof(mmi_cache_short_entry), &nvram_gen_compare_short);
+
+    /* sort operator */
+#ifndef __OPTR_NONE__
+    qsort((void *)operator_mmi_cache_short, nvram_operator_short_count, sizeof(mmi_cache_short_entry), &nvram_gen_compare_short);
+#endif
+    return 0;
+}
+
+
+/*****************************************************************************
+* FUNCTION
+*   nvram_sort_double
+* DESCRIPTION
+*   sort one double_cache
+* PARAMETERS
+*   none
+* RETURNS
+*   none
+*****************************************************************************/
+int nvram_sort_double(void)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    /* sort common */
+    qsort((void *)common_mmi_cache_double, nvram_common_double_count, sizeof(mmi_cache_double_entry), &nvram_gen_compare_double);
+
+    /* sort custom */
+    qsort((void *)custom_mmi_cache_double, nvram_custom_double_count, sizeof(mmi_cache_double_entry), &nvram_gen_compare_double);
+
+#ifndef __OPTR_NONE__
+    qsort((void *)operator_mmi_cache_double, nvram_operator_double_count, sizeof(mmi_cache_double_entry), &nvram_gen_compare_double);
+#endif
+    return 0;
+}
+
+/*****************************************************************************
+* FUNCTION
+*   nvram_gen_mmi_cache
+* DESCRIPTION
+*   output mmi cache default value to nvram_mmi_cust_pack.h
+* PARAMETERS
+*   project_name    [IN]
+*   broad_ver       [IN]
+* RETURNS
+*   none
+*****************************************************************************/
+void nvram_gen_mmi_cache(char *project_name, char *broad_ver)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    FILE *output;
+    int i, k;
+    int byte_max_len, short_max_len, double_max_len;
+    char output_pathname[NVRAM_AUTO_GEN_MAX_PATH_LEN];
+    int mode_result;
+    nvram_lid_enum last_custpack_lid;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    sprintf(output_pathname, "%s\\nvram_mmi_cache_cust_pack.h", nvram_auto_gen_output_path);
+
+    printf("nvram_gen_mmi_cache milestone1\n");
+
+    /* check if the file exists. */
+    mode_result = access(output_pathname, 0);
+    if (mode_result == 0)
+    {
+        /* exists,but check if it can be written. */
+        mode_result = access(output_pathname, 2);
+        if (mode_result != 0)
+        {
+            fprintf(stderr, "error: nvram_mmi_cache_cust_pack.h exists,but it cannot be written.\n");
+            exit(NVRAM_EXIT_CODE_ERROR);
+        }
+    }
+    else
+    {
+        /* file not exist*/
+        mode_result = access(nvram_auto_gen_output_path, 2);
+        if (mode_result != 0)
+        {
+            fprintf(stderr, "error: cannot create file in The project_BB folder\n");
+            exit(NVRAM_EXIT_CODE_ERROR);
+        }
+    }
+    output = fopen(output_pathname, "w+");
+    if (output == NULL)
+    {
+        fprintf(stderr, "error: cannot write to nvram_mmi_cache_cust_pack.h in The project_BB folder\n");
+        exit(NVRAM_EXIT_CODE_ERROR);
+    }
+    fprintf(output, "/* This file is generated automatically by nvram_auto_gen.exe, please do not modify it here manually */\n");
+
+    printf("nvram_gen_mmi_cache milestone2\n");
+
+    nvram_common_byte_count = nvram_get_byte_entry_count(common_mmi_cache_byte);
+    if (nvram_common_byte_count < 0)
+    {
+        fprintf(stderr, "error: configuration exceeds common_byte_cache max count.\n");
+        exit(NVRAM_EXIT_CODE_ERROR);
+    }
+    nvram_common_short_count = nvram_get_short_entry_count(common_mmi_cache_short);
+    if (nvram_common_short_count < 0)
+    {
+        fprintf(stderr, "error: configuration exceeds common_short_cache max count.\n");
+        exit(NVRAM_EXIT_CODE_ERROR);
+    }
+    nvram_common_double_count = nvram_get_double_entry_count(common_mmi_cache_double);
+    if (nvram_common_double_count < 0)
+    {
+        fprintf(stderr, "error: configuration exceeds common_double_cache max count.\n");
+        exit(NVRAM_EXIT_CODE_ERROR);
+    }
+    nvram_custom_byte_count = nvram_get_byte_entry_count(custom_mmi_cache_byte);
+    if (nvram_custom_byte_count < 0)
+    {
+        fprintf(stderr, "error: configuration exceeds custom_byte_cache max count.\n");
+        exit(NVRAM_EXIT_CODE_ERROR);
+    }
+
+    nvram_custom_short_count = nvram_get_short_entry_count(custom_mmi_cache_short);
+    if (nvram_custom_short_count < 0)
+    {
+        fprintf(stderr, "error: configuration exceeds custom_short_cache max count.\n");
+        exit(NVRAM_EXIT_CODE_ERROR);
+    }
+
+    nvram_custom_double_count = nvram_get_double_entry_count(custom_mmi_cache_double);
+    if (nvram_custom_double_count < 0)
+    {
+        fprintf(stderr, "error: configuration exceeds custom_double_cache max count.\n");
+        exit(NVRAM_EXIT_CODE_ERROR);
+    }
+#ifndef __OPTR_NONE__
+    nvram_operator_byte_count = nvram_get_byte_entry_count(operator_mmi_cache_byte);
+    if (nvram_operator_byte_count < 0)
+    {
+        fprintf(stderr, "error: configuration exceeds operator_byte_cache max count.\n");
+        exit(NVRAM_EXIT_CODE_ERROR);
+    }
+    nvram_operator_short_count = nvram_get_short_entry_count(operator_mmi_cache_short);
+    if (nvram_operator_short_count < 0)
+    {
+        fprintf(stderr, "error: configuration exceeds operator_short_cache max count.\n");
+        exit(NVRAM_EXIT_CODE_ERROR);
+    }
+    nvram_operator_double_count = nvram_get_double_entry_count(operator_mmi_cache_double);
+    if (nvram_operator_double_count < 0)
+    {
+        fprintf(stderr, "error: configuration exceeds operator_double_cache max count.\n");
+        exit(NVRAM_EXIT_CODE_ERROR);
+    }
+#endif
+
+    printf("nvram_gen_mmi_cache milestone3\n");
+
+    nvram_sort_byte();
+    nvram_sort_short();
+    nvram_sort_double();
+    /*
+    fprintf(output, "nvram_common_byte_count : %d--------------------------------------------\n", nvram_common_byte_count);
+    for (i = 0; i < nvram_common_byte_count; i++)
+    {
+        fprintf(output, "%s, %s\n", common_mmi_cache_byte[i].id_str, common_mmi_cache_byte[i].value_str);
+    }
+    fprintf(output, "nvram_common_short_count : %d--------------------------------------------\n", nvram_common_short_count);
+    fprintf(output, "nvram_common_double_count : %d--------------------------------------------\n", nvram_common_double_count);
+    fprintf(output, "nvram_custom_byte_count : %d--------------------------------------------\n", nvram_custom_byte_count);
+    for (i = 0; i < nvram_custom_byte_count; i++)
+    {
+        fprintf(output, "%s, %s\n", custom_mmi_cache_byte[i].id_str, custom_mmi_cache_byte[i].value_str);
+    }
+    */
+
+    printf("nvram_gen_mmi_cache milestone4\n");
+
+#ifndef __OPTR_NONE__
+    nvram_op_byte_count = nvram_merge_byte(
+                        common_mmi_cache_byte,
+                        nvram_common_byte_count,
+                        custom_mmi_cache_byte,
+                        nvram_custom_byte_count,
+                        nvram_op_byte);
+    if (nvram_op_byte_count < 0)
+    {
+        fprintf(stderr, "error: duplicate byte entries exist.\n");
+        exit(NVRAM_EXIT_CODE_ERROR);
+    }
+    nvram_op_short_count = nvram_merge_short(
+                        common_mmi_cache_short,
+                        nvram_common_short_count,
+                        custom_mmi_cache_short,
+                        nvram_custom_short_count,
+                        nvram_op_short);
+    if (nvram_op_short_count < 0)
+    {
+        fprintf(stderr, "error: duplicate short entries exist.\n");
+        exit(NVRAM_EXIT_CODE_ERROR);
+    }
+    nvram_op_double_count = nvram_merge_double(
+                        common_mmi_cache_double,
+                        nvram_common_double_count,
+                        custom_mmi_cache_double,
+                        nvram_custom_double_count,
+                        nvram_op_double);
+    if (nvram_op_double_count < 0)
+    {
+        fprintf(stderr, "error: duplicate double entries exist.\n");
+        exit(NVRAM_EXIT_CODE_ERROR);
+    }
+    nvram_byte_count = nvram_merge_byte(
+                    nvram_op_byte,
+                    nvram_op_byte_count,
+                    operator_mmi_cache_byte,
+                    nvram_operator_byte_count,
+                    nvram_mmi_cache_byte);
+    if (nvram_byte_count < 0)
+    {
+        fprintf(stderr, "error: duplicate nvram_op_byte entries exist.\n");
+        exit(NVRAM_EXIT_CODE_ERROR);
+    }
+    nvram_short_count = nvram_merge_short(
+                    nvram_op_short,
+                    nvram_op_short_count,
+                    operator_mmi_cache_short,
+                    nvram_operator_short_count,
+                    nvram_mmi_cache_short);
+    if (nvram_short_count < 0)
+    {
+        fprintf(stderr, "error: duplicate nvram_op_short entries exist.\n");
+        exit(NVRAM_EXIT_CODE_ERROR);
+    }
+
+    nvram_double_count = nvram_merge_double(
+                    nvram_op_double,
+                    nvram_op_double_count,
+                    operator_mmi_cache_double,
+                    nvram_operator_double_count,
+                    nvram_mmi_cache_double);
+    if (nvram_double_count < 0)
+    {
+        fprintf(stderr, "error: duplicate nvram_op_double entries exist.\n");
+        exit(NVRAM_EXIT_CODE_ERROR);
+    }
+#else /* __OPTR_NONE__ */
+    nvram_byte_count = nvram_merge_byte(
+                    common_mmi_cache_byte,
+                    nvram_common_byte_count,
+                    custom_mmi_cache_byte,
+                    nvram_custom_byte_count,
+                    nvram_mmi_cache_byte);
+    if (nvram_byte_count < 0)
+    {
+        fprintf(stderr, "error: duplicate byte entries exist.\n");
+        exit(NVRAM_EXIT_CODE_ERROR);
+    }
+    nvram_short_count = nvram_merge_short(
+                    common_mmi_cache_short,
+                    nvram_common_short_count,
+                    custom_mmi_cache_short,
+                    nvram_custom_short_count,
+                    nvram_mmi_cache_short);
+    if (nvram_short_count < 0)
+    {
+        fprintf(stderr, "error: duplicate short entries exist.\n");
+        exit(NVRAM_EXIT_CODE_ERROR);
+    }
+    nvram_double_count = nvram_merge_double(
+                    common_mmi_cache_double,
+                    nvram_common_double_count,
+                    custom_mmi_cache_double,
+                    nvram_custom_double_count,
+                    nvram_mmi_cache_double);
+    if (nvram_double_count < 0)
+    {
+        fprintf(stderr, "error: duplicate double entries exist.\n");
+        exit(NVRAM_EXIT_CODE_ERROR);
+    }
+
+#endif /* __OPTR_NONE__ */
+
+    /*
+    if (nvram_mmi_cache_byte[nvram_byte_count - 1].id != NVRAM_LAST_BYTE_ELEMENT - 1)
+    {
+        fprintf(stderr, "warning: there is byte enum id that does not config default value\n");
+    }
+    if (nvram_mmi_cache_short[nvram_short_count - 1].id != NVRAM_LAST_SHORT_ELEMENT - 1)
+    {
+        fprintf(stderr, "warning: there is short enum id that does not config default value\n");
+    }
+    if (nvram_mmi_cache_double[nvram_double_count - 1].id != NVRAM_LAST_DOUBLE_ELEMENT - 1)
+    {
+        fprintf(stderr, "warning: there is double enum id that does not config default value\n");
+    }
+    */
+
+    printf("nvram_gen_mmi_cache milestone5\n");
+
+    byte_max_len = 0;
+    short_max_len = 0;
+    double_max_len = 0;
+    for (i = 0; i < nvram_byte_count; i++)
+    {
+        if (strlen(nvram_mmi_cache_byte[i].value_str) > byte_max_len)
+        {
+            byte_max_len = strlen(nvram_mmi_cache_byte[i].value_str);
+        }
+    }
+    for (i = 0; i < nvram_short_count; i++)
+    {
+        if (strlen(nvram_mmi_cache_short[i].value1_str) > short_max_len)
+        {
+            short_max_len = strlen(nvram_mmi_cache_short[i].value1_str);
+        }
+        if (strlen(nvram_mmi_cache_short[i].value2_str) > short_max_len)
+        {
+            short_max_len = strlen(nvram_mmi_cache_short[i].value2_str);
+        }
+    }
+    for (i = 0; i < nvram_double_count; i++)
+    {
+        if (strlen(nvram_mmi_cache_double[i].value1_str) > double_max_len)
+        {
+            double_max_len = strlen(nvram_mmi_cache_double[i].value1_str);
+        }
+        if (strlen(nvram_mmi_cache_double[i].value2_str) > double_max_len)
+        {
+            double_max_len = strlen(nvram_mmi_cache_double[i].value2_str);
+        }
+        if (strlen(nvram_mmi_cache_double[i].value3_str) > double_max_len)
+        {
+            double_max_len = strlen(nvram_mmi_cache_double[i].value3_str);
+        }
+        if (strlen(nvram_mmi_cache_double[i].value4_str) > double_max_len)
+        {
+            double_max_len = strlen(nvram_mmi_cache_double[i].value4_str);
+        }
+        if (strlen(nvram_mmi_cache_double[i].value5_str) > double_max_len)
+        {
+            double_max_len = strlen(nvram_mmi_cache_double[i].value5_str);
+        }
+        if (strlen(nvram_mmi_cache_double[i].value6_str) > double_max_len)
+        {
+            double_max_len = strlen(nvram_mmi_cache_double[i].value6_str);
+        }
+        if (strlen(nvram_mmi_cache_double[i].value7_str) > double_max_len)
+        {
+            double_max_len = strlen(nvram_mmi_cache_double[i].value7_str);
+        }
+        if (strlen(nvram_mmi_cache_double[i].value8_str) > double_max_len)
+        {
+            double_max_len = strlen(nvram_mmi_cache_double[i].value8_str);
+        }
+    }
+
+
+    printf("nvram_gen_mmi_cache milestone6\n");
+
+    /* Begin output NVRAM_CACHE_BYTE_DEFAULT */
+    i = 0;
+    fprintf(output, "/* The count of byte configuaration: %d */\n", nvram_byte_count);
+    fprintf(output, "/* BYTEDATA enum Max index: %d */\n", NVRAM_LAST_BYTE_ELEMENT - 1);
+    fprintf(output, "const kal_uint8 NVRAM_CACHE_BYTE_DEFAULT[NVRAM_CACHE_SIZE] =\n");
+    fprintf(output, "{\n");
+    for (k = 0; k < BYTE_ENTRY_COUNT; k++)
+    {
+        int j;
+        if (i < nvram_byte_count)
+        {
+            if (nvram_mmi_cache_byte[i].id == k)    /* enum <--->entry */
+            {
+            /* Begin to restore factory */
+                if (nvram_mmi_cache_byte[i].restore)
+                {
+                    /* Get max length begin */
+                    if(strlen(nvram_mmi_cache_byte[i].id_str) > nvram_max_length_byte_id_str)
+                    {
+                        nvram_max_length_byte_id_str = strlen(nvram_mmi_cache_byte[i].id_str);
+                    }
+                    /* Get max length end */
+
+                    nvram_restore_cache_byte[nvram_mmi_cache_byte[i].app_id][nvram_restore_byte_idx[nvram_mmi_cache_byte[i].app_id]]
+                        = i;
+                    nvram_restore_byte_idx[nvram_mmi_cache_byte[i].app_id]++;
+                    //cache_struct_idx++;
+                }
+            /* End to restore factory */
+                fprintf(output, "    %s", nvram_mmi_cache_byte[i].value_str);
+                if (k != BYTE_ENTRY_COUNT - 1)
+                {
+                    fprintf(output, ",");
+                }
+                for (j = 0; j < byte_max_len - strlen(nvram_mmi_cache_byte[i].value_str) + 4; j++)
+                {
+                    fprintf(output, " ");
+                }
+                fprintf(output, "/* %3d  : %s */\n", nvram_mmi_cache_byte[i].id, nvram_mmi_cache_byte[i].id_str);
+                i++;
+            }
+            else
+            {
+                fprintf(output, "    0xFF");
+                if (k != BYTE_ENTRY_COUNT - 1)
+                {
+                    fprintf(output, ",/* unset */");
+                }
+                fprintf(output, "\n");
+            }
+        }
+        else
+        {
+            fprintf(output, "    0xFF");
+            if (k != BYTE_ENTRY_COUNT - 1)
+            {
+                fprintf(output, ",");
+            }
+            fprintf(output, "\n");
+        }
+    }
+    fprintf(output, "};\n\n\n");
+    /* End output NVRAM_CACHE_BYTE_DEFAULT */
+
+
+    /* Begin output NVRAM_CACHE_SHORT_DEFAULT */
+    i = 0;
+    fprintf(output, "/* The count of short configuaration: %d */\n", nvram_short_count);
+    fprintf(output, "/* SHORTDATA enum Max index: %d */\n", NVRAM_LAST_SHORT_ELEMENT - 1);
+
+    fprintf(output, "const kal_uint8 NVRAM_CACHE_SHORT_DEFAULT[NVRAM_CACHE_SIZE] =\n");
+    fprintf(output, "{\n");
+    for (k = 0; k < SHORT_ENTRY_COUNT; k++)
+    {
+        int j;
+        if (i < nvram_short_count)
+        {
+            if (nvram_mmi_cache_short[i].id == k)
+            {
+                /* Get max length begin */
+                if(strlen(nvram_mmi_cache_short[i].id_str) > nvram_max_length_short_id_str)
+                {
+                    nvram_max_length_short_id_str = strlen(nvram_mmi_cache_short[i].id_str);
+                }
+                /* Get max length end */
+
+            /* Begin to restore factory */
+                if (nvram_mmi_cache_short[i].restore)
+                {
+                    nvram_restore_cache_short[nvram_mmi_cache_short[i].app_id][nvram_restore_short_idx[nvram_mmi_cache_short[i].app_id]]
+                        //= nvram_mmi_cache_short[i].id;
+                        = i;
+                    nvram_restore_short_idx[nvram_mmi_cache_short[i].app_id]++;
+                }
+            /* End to restore factory */
+                fprintf(output, "    %s,", nvram_mmi_cache_short[i].value1_str);
+                for (j = 0; j < short_max_len - strlen(nvram_mmi_cache_short[i].value1_str) + 4; j++)
+                {
+                    fprintf(output, " ");
+                }
+                fprintf(output, "/* %3d  : %s */\n", nvram_mmi_cache_short[i].id, nvram_mmi_cache_short[i].id_str);
+                fprintf(output, "    %s", nvram_mmi_cache_short[i].value2_str);
+                if (k != SHORT_ENTRY_COUNT - 1)
+                {
+                    fprintf(output, ",");
+                }
+                fprintf(output, "\n");
+                i++;
+            }
+            else
+            {
+                fprintf(output, "    0xFF,/* unset */\n");
+                fprintf(output, "    0xFF");
+                if (k != SHORT_ENTRY_COUNT - 1)
+                {
+                    fprintf(output, ",");
+                }
+                fprintf(output, "\n");
+            }
+        }
+        else
+        {
+            fprintf(output, "    0xFF,\n");
+            fprintf(output, "    0xFF");
+            if (k != SHORT_ENTRY_COUNT - 1)
+            {
+                fprintf(output, ",");
+            }
+            fprintf(output, "\n");
+        }
+
+    }
+
+    fprintf(output, "};\n\n\n");
+    /* End output NVRAM_CACHE_SHORT_DEFAULT */
+
+
+    /* Begin output NVRAM_CACHE_DOUBLE_DEFAULT */
+    i = 0;
+    fprintf(output, "/* The count of double configuaration: %d */\n", nvram_double_count);
+    fprintf(output, "/* DOUBLEDATA enum Max index: %d */\n", NVRAM_LAST_DOUBLE_ELEMENT - 1);
+
+    fprintf(output, "const kal_uint8 NVRAM_CACHE_DOUBLE_DEFAULT[NVRAM_CACHE_SIZE] =\n");
+    fprintf(output, "{\n");
+    for (k = 0; k < DOUBLE_ENTRY_COUNT; k++)
+    {
+        int j;
+        if (i < nvram_double_count)
+        {
+            if (nvram_mmi_cache_double[i].id == k)
+            {
+            /* Begin to restore factory */
+                if (nvram_mmi_cache_double[i].restore)
+                {
+                    /* Get max length begin */
+                    if(strlen(nvram_mmi_cache_double[i].id_str) > nvram_max_length_double_id_str)
+                    {
+                        nvram_max_length_double_id_str = strlen(nvram_mmi_cache_double[i].id_str);
+                    }
+                    /* Get max length end */
+
+                    nvram_restore_cache_double[nvram_mmi_cache_double[i].app_id][nvram_restore_double_idx[nvram_mmi_cache_double[i].app_id]]
+                        = i;
+                    nvram_restore_double_idx[nvram_mmi_cache_double[i].app_id]++;
+                }
+            /* End to restore factory */
+                fprintf(output, "    %s,", nvram_mmi_cache_double[i].value1_str);
+                for (j = 0; j < short_max_len - strlen(nvram_mmi_cache_double[i].value1_str) + 4; j++)
+                {
+                    fprintf(output, " ");
+                }
+                fprintf(output, "/* %3d  : %s */\n", nvram_mmi_cache_double[i].id, nvram_mmi_cache_double[i].id_str);
+                fprintf(output, "    %s,\n", nvram_mmi_cache_double[i].value2_str);
+                fprintf(output, "    %s,\n", nvram_mmi_cache_double[i].value3_str);
+                fprintf(output, "    %s,\n", nvram_mmi_cache_double[i].value4_str);
+                fprintf(output, "    %s,\n", nvram_mmi_cache_double[i].value5_str);
+                fprintf(output, "    %s,\n", nvram_mmi_cache_double[i].value6_str);
+                fprintf(output, "    %s,\n", nvram_mmi_cache_double[i].value7_str);
+                fprintf(output, "    %s", nvram_mmi_cache_double[i].value8_str);
+                if (k != DOUBLE_ENTRY_COUNT - 1)
+                {
+                    fprintf(output, ",");
+                }
+                fprintf(output, "\n");
+                i++;
+            }
+            else
+            {
+                fprintf(output,
+                    "    0xFF,/* unset */\n    0xFF,\n    0xFF,\n    0xFF,\n    0xFF,\n    0xFF,\n    0xFF,\n    0xFF");
+                if (k != DOUBLE_ENTRY_COUNT - 1)
+                {
+                    fprintf(output, ",");
+                }
+                fprintf(output, "\n");
+            }
+        }
+        else
+        {
+            fprintf(output, "    0xFF,\n    0xFF,\n    0xFF,\n    0xFF,\n    0xFF,\n    0xFF,\n    0xFF,\n    0xFF");
+            if (k != DOUBLE_ENTRY_COUNT - 1)
+            {
+                fprintf(output, ",");
+            }
+            fprintf(output, "\n");
+        }
+    }
+    fprintf(output, "};\n\n\n");
+    fclose(output);
+}
+
+void nvram_gen_mmi_cache_res_func(FILE *fh_restore_factory_c, FILE *fh_restore_dom_h)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    int  loop_app_idx;
+    int  loop_app_cache_idx;
+    int  loop_value_idx;
+    int  loop_space;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+
+    /* step 1: generate function name */
+    fprintf(fh_restore_factory_c,NVRAM_FUNCTION_HEAD, "nvram_restore_byte_cache()", "byte");
+    fprintf(fh_restore_factory_c, NVRAM_RESTORE_FUNCTION_NAME, "byte", "kal_uint8", "b", "kal_uint8");
+
+    /* Dom: byte (begin) */
+    fprintf(fh_restore_dom_h, R_F_DOM_COMMENT, "BYTE -8bit");
+    fprintf(fh_restore_dom_h, R_F_DOM_ENUM_BEGIN);
+    /* Dom: byte (end) */
+
+    /* step 2: generate function context */
+    for (loop_app_idx = 0; loop_app_idx < NVRAM_APP_TOTAL; loop_app_idx++)
+    {
+        if (nvram_restore_byte_idx[loop_app_idx])
+        {
+            fprintf(fh_restore_factory_c,"        case %s :\n", nvram_mmi_cache_byte[nvram_restore_cache_byte[loop_app_idx][0]].app_id_str);
+        }
+        else
+        {
+            continue;
+        }
+
+        for (loop_app_cache_idx = 0; loop_app_cache_idx < nvram_restore_byte_idx[loop_app_idx]; loop_app_cache_idx++)
+        {
+            /* Dom: byte (begin) */
+            fprintf(fh_restore_dom_h, R_F_DOM_CONTENT_ID,
+                        nvram_mmi_cache_byte[nvram_restore_cache_byte[loop_app_idx][loop_app_cache_idx]].id_str);
+
+            for (loop_space = 0; loop_space < nvram_max_length_byte_id_str - strlen(nvram_mmi_cache_byte[nvram_restore_cache_byte[loop_app_idx][loop_app_cache_idx]].id_str); loop_space++)
+            {
+                fprintf(fh_restore_dom_h, " ");
+            }
+
+            fprintf(fh_restore_dom_h, R_F_DOM_CONTENT_DESCRIPTION,
+                        nvram_mmi_cache_byte[nvram_restore_cache_byte[loop_app_idx][loop_app_cache_idx]].description);
+            /* Dom: byte (end) */
+
+            if (nvram_mmi_cache_byte[nvram_restore_cache_byte[loop_app_idx][loop_app_cache_idx]].restore_id == NVRAM_CACHE_ID_RESERVED)
+            {
+                fprintf(fh_restore_factory_c,"            buffer[%s] = %s;\n",
+                        nvram_mmi_cache_byte[nvram_restore_cache_byte[loop_app_idx][loop_app_cache_idx]].id_str,
+                        nvram_mmi_cache_byte[nvram_restore_cache_byte[loop_app_idx][loop_app_cache_idx]].value_str);
+            }
+            else
+            {
+                fprintf(fh_restore_factory_c,"            b_buffer[%s] = b_buffer[%s];\n",
+                        nvram_mmi_cache_byte[nvram_restore_cache_byte[loop_app_idx][loop_app_cache_idx]].id_str,
+                        nvram_mmi_cache_byte[nvram_restore_cache_byte[loop_app_idx][loop_app_cache_idx]].restore_id_str);
+            }
+        }
+
+        fprintf(fh_restore_factory_c,NVRAM_RESTORE_FUNCTION_BREAK);
+    }
+    /* step 3: generate function end */
+    fprintf(fh_restore_factory_c, NVRAM_RESTORE_FUNCTION_TAIL, 1);
+    fprintf(fh_restore_dom_h, R_F_DOM_ENUM_END, "BYTE", "BYTE");
+
+    /*
+     * generate restore function: cache short
+     *
+     */
+
+    /* step 1: generate function name */
+    fprintf(fh_restore_factory_c,NVRAM_FUNCTION_HEAD, "nvram_restore_short_cache()", "short");
+    fprintf(fh_restore_factory_c, NVRAM_RESTORE_FUNCTION_NAME, "short", "kal_uint16", "s", "kal_uint16");
+
+    /* Dom: short (begin) */
+    fprintf(fh_restore_dom_h, R_F_DOM_COMMENT, "SHORT -16bit");
+    fprintf(fh_restore_dom_h, R_F_DOM_ENUM_BEGIN);
+    /* Dom: short (end) */
+
+    /* step 2: generate function context */
+    for (loop_app_idx = 0; loop_app_idx < NVRAM_APP_TOTAL; loop_app_idx++)
+    {
+        if (nvram_restore_short_idx[loop_app_idx])
+        {
+            fprintf(fh_restore_factory_c,"        case %s :\n", nvram_mmi_cache_short[nvram_restore_cache_short[loop_app_idx][0]].app_id_str);
+        }
+        else
+        {
+            continue;
+        }
+
+        for (loop_app_cache_idx = 0; loop_app_cache_idx < nvram_restore_short_idx[loop_app_idx]; loop_app_cache_idx++)
+        {
+            /* Dom: short context (begin) */
+            fprintf(fh_restore_dom_h, R_F_DOM_CONTENT_ID,
+                        nvram_mmi_cache_short[nvram_restore_cache_short[loop_app_idx][loop_app_cache_idx]].id_str);
+
+            for (loop_space = 0; loop_space < nvram_max_length_short_id_str - strlen(nvram_mmi_cache_short[nvram_restore_cache_short[loop_app_idx][loop_app_cache_idx]].id_str); loop_space++)
+            {
+                fprintf(fh_restore_dom_h, " ");
+            }
+
+            fprintf(fh_restore_dom_h, R_F_DOM_CONTENT_DESCRIPTION,
+                        nvram_mmi_cache_short[nvram_restore_cache_short[loop_app_idx][loop_app_cache_idx]].description);
+            /* Dom: short context (end) */
+
+            if (nvram_mmi_cache_short[nvram_restore_cache_short[loop_app_idx][loop_app_cache_idx]].restore_id == NVRAM_CACHE_ID_RESERVED)
+            {
+                fprintf(fh_restore_factory_c, NVRAM_AUTO_GEN_COMMENT, nvram_mmi_cache_short[nvram_restore_cache_short[loop_app_idx][loop_app_cache_idx]].description);
+
+                for (loop_value_idx = 0; loop_value_idx < sizeof(short); loop_value_idx++)
+                {
+                    fprintf(fh_restore_factory_c,"            buffer[%d * %s + %d] = 0x%02X;\n",
+                            sizeof(short),
+                            nvram_mmi_cache_short[nvram_restore_cache_short[loop_app_idx][loop_app_cache_idx]].id_str,
+                            loop_value_idx,
+                            *(&(nvram_mmi_cache_short[nvram_restore_cache_short[loop_app_idx][loop_app_cache_idx]].value1) + loop_value_idx));
+                }
+
+            }
+            else
+            {
+                fprintf(fh_restore_factory_c,"            s_buffer[%s] = s_buffer[%s];\n",
+                        nvram_mmi_cache_short[nvram_restore_cache_short[loop_app_idx][loop_app_cache_idx]].id_str,
+                        nvram_mmi_cache_short[nvram_restore_cache_short[loop_app_idx][loop_app_cache_idx]].restore_id_str);
+            }
+        }
+
+        fprintf(fh_restore_factory_c,NVRAM_RESTORE_FUNCTION_BREAK);
+    }
+    /* step 3: generate function end */
+    fprintf(fh_restore_factory_c, NVRAM_RESTORE_FUNCTION_TAIL, 2);
+    fprintf(fh_restore_dom_h, R_F_DOM_ENUM_END, "SHORT", "SHORT");
+
+    /*
+     * generate restore function: cache double
+     *
+     */
+
+    /* step 1: generate function name */
+    fprintf(fh_restore_factory_c,NVRAM_FUNCTION_HEAD, "nvram_restore_double_cache()", "double");
+    fprintf(fh_restore_factory_c, NVRAM_RESTORE_FUNCTION_NAME, "double", "double", "d", "double");
+    /* Dom: double (begin) */
+    fprintf(fh_restore_dom_h, R_F_DOM_COMMENT, "DOUBLE -64bit");
+    fprintf(fh_restore_dom_h, R_F_DOM_ENUM_BEGIN);
+    /* Dom: double (end) */
+
+    /* step 2: generate function context */
+    for (loop_app_idx = 0; loop_app_idx < NVRAM_APP_TOTAL; loop_app_idx++)
+    {
+        if (nvram_restore_double_idx[loop_app_idx])
+        {
+            fprintf(fh_restore_factory_c,"        case %s :\n", nvram_mmi_cache_byte[nvram_restore_cache_byte[loop_app_idx][0]].app_id_str);
+        }
+        else
+        {
+            continue;
+        }
+
+        for (loop_app_cache_idx = 0; loop_app_cache_idx < nvram_restore_double_idx[loop_app_idx]; loop_app_cache_idx++)
+        {
+            /* Dom: double context (begin) */
+            fprintf(fh_restore_dom_h, R_F_DOM_CONTENT_ID,
+                        nvram_mmi_cache_double[nvram_restore_cache_double[loop_app_idx][loop_app_cache_idx]].id_str);
+
+            for (loop_space = 0; loop_space < nvram_max_length_double_id_str - strlen(nvram_mmi_cache_double[nvram_restore_cache_double[loop_app_idx][loop_app_cache_idx]].id_str); loop_space++)
+            {
+                fprintf(fh_restore_dom_h, " ");
+            }
+
+            fprintf(fh_restore_dom_h, R_F_DOM_CONTENT_DESCRIPTION,
+                        nvram_mmi_cache_double[nvram_restore_cache_double[loop_app_idx][loop_app_cache_idx]].description);
+            /* Dom: double context (end) */
+
+            fprintf(fh_restore_factory_c, NVRAM_AUTO_GEN_COMMENT, nvram_mmi_cache_double[nvram_restore_cache_double[loop_app_idx][loop_app_cache_idx]].description);
+
+            if (nvram_mmi_cache_double[nvram_restore_cache_double[loop_app_idx][loop_app_cache_idx]].restore_id == NVRAM_CACHE_ID_RESERVED)
+            {
+                for (loop_value_idx = 0; loop_value_idx < sizeof(double); loop_value_idx++)
+                {
+                    fprintf(fh_restore_factory_c,"            buffer[%d * %s + %d] = 0x%02X;\n",
+                            sizeof(double),
+                            nvram_mmi_cache_double[nvram_restore_cache_double[loop_app_idx][loop_app_cache_idx]].id_str,
+                            loop_value_idx,
+                            *(&(nvram_mmi_cache_double[nvram_restore_cache_double[loop_app_idx][loop_app_cache_idx]].value1) + loop_value_idx));
+                }
+            }
+            else
+            {
+                fprintf(fh_restore_factory_c,"            d_buffer[%s] = d_buffer[%s];\n",
+                        nvram_mmi_cache_double[nvram_restore_cache_double[loop_app_idx][loop_app_cache_idx]].id_str,
+                        nvram_mmi_cache_double[nvram_restore_cache_double[loop_app_idx][loop_app_cache_idx]].restore_id_str);
+            }
+        }
+
+        fprintf(fh_restore_factory_c,NVRAM_RESTORE_FUNCTION_BREAK);
+    }
+    /* step 3: generate function end */
+    fprintf(fh_restore_factory_c, NVRAM_RESTORE_FUNCTION_TAIL, 3);
+    fprintf(fh_restore_dom_h, R_F_DOM_ENUM_END, "DOUBLE", "DOUBLE");
+}
+
+/*****************************************************************************
+* FUNCTION
+*   nvram_gen_mmi_cache
+* DESCRIPTION
+*   output restore head file to nvram_restore_headfile.h
+* PARAMETERS
+*   project_name    [IN]
+*   broad_ver       [IN]
+* RETURNS
+*   none
+*****************************************************************************/
+void nvram_gen_create_file(FILE **file_handle, char *file_path, char *file_name)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    int  mode_result;
+    char file_pathname[NVRAM_AUTO_GEN_MAX_PATH_LEN];
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    sprintf(file_pathname, "%s\\%s", file_path, file_name);
+
+    mode_result = access(file_pathname, 0);
+
+    if (mode_result == 0)
+    {
+        /* exists,but check if it can be written. */
+        mode_result = access(file_pathname, 2);
+        if (mode_result != 0)
+        {
+            fprintf(stderr, "error: %s exists,but it cannot be written.\n", file_name);
+            exit(NVRAM_EXIT_CODE_ERROR);
+        }
+    }
+    else
+    {
+        /* file not exist*/
+        mode_result = access(file_path, 2);
+        if (mode_result != 0)
+        {
+            fprintf(stderr, "error: cannot create file in folder: %s\n", file_path);
+            exit(NVRAM_EXIT_CODE_ERROR);
+        }
+    }
+
+    *file_handle = fopen(file_pathname, "w+");
+    if (file_handle == NULL)
+    {
+        fprintf(stderr, "error: cannot write to %s in folder: %s\n", file_name, file_path);
+        exit(NVRAM_EXIT_CODE_ERROR);
+    }
+
+    return;
+}
+
+void nvram_gen_close_file(FILE **file_handle)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+
+    fclose(*file_handle);
+}
+
+/*****************************************************************************
+* FUNCTION
+*   nvram_gen_restore_function
+* DESCRIPTION
+*   output restore function to nvram_user_restore_factory.c
+* PARAMETERS
+*   project_name    [IN]
+*   broad_ver       [IN]
+* RETURNS
+*   none
+*****************************************************************************/
+void nvram_gen_restore_function(char *project_name, char *broad_ver)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    FILE *fh_restore_factory_c;
+    FILE *fh_restore_dom_h;
+    char output_pathname[NVRAM_AUTO_GEN_MAX_PATH_LEN];
+    int  loop_app_idx;
+    int  loop_space;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    sprintf(output_pathname, "mmi_cache_restore.c");
+    nvram_gen_create_file(&fh_restore_factory_c,nvram_auto_gen_output_path,output_pathname);
+
+    sprintf(output_pathname,"mmi_cache_restore_dom.h");
+    nvram_gen_create_file(&fh_restore_dom_h,nvram_auto_gen_output_path,output_pathname);
+
+    /* generate head file */
+    fprintf(fh_restore_factory_c, COPYRIGHTS_HEADER, "custom_mmi_cache_restore.c");
+    fprintf(fh_restore_factory_c, "#ifndef NVRAM_NOT_PRESENT\n");
+    fprintf(fh_restore_factory_c, "#include \"kal_general_types.h\"\n");
+    fprintf(fh_restore_factory_c, "#include \"nvram_enums.h\"\n");
+    fprintf(fh_restore_factory_c, "#include \"custom_nvram_config.h\"\n");
+    fprintf(fh_restore_factory_c, "#include \"custom_mmi_default_value.h\"\n");
+
+    nvram_gen_mmi_cache_res_func(fh_restore_factory_c, fh_restore_dom_h);
+
+    fprintf(fh_restore_factory_c, "#endif /* NVRAM_NOT_PRESENT */");
+
+    nvram_gen_close_file(&fh_restore_factory_c);
+    nvram_gen_close_file(&fh_restore_dom_h);
+}
+
+#endif /* #if defined(NEPTUNE_MMI) */
+#endif /* NVRAM_NOT_PRESENT */
+
+/*****************************************************************************
+* FUNCTION
+*  main
+* DESCRIPTION
+*  main function.
+* PARAMETERS
+*  None
+* RETURNS
+*  None
+*****************************************************************************/
+int main(int argc, char *argv[])
+{
+#if defined(NEPTUNE_MMI) && !defined(NVRAM_NOT_PRESENT)
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+
+    if (argc > 1)
+    {
+        sprintf(nvram_auto_gen_output_path, "%s", argv[3]);
+	
+        printf("nvram_gen_mmi_cache\n");
+        nvram_gen_mmi_cache(argv[1], argv[2]);
+
+        printf("nvram_gen_mmi_cache_res_func\n");
+        nvram_gen_restore_function(argv[1], argv[2]);
+
+    }
+    return 0;
+#else
+    printf("Old mmi cache mechanism is already phased out\n");
+    return 0;
+#endif
+}
+
diff --git a/mcu/tools/NVRAMStatistic/src/nvram_gen_util.c b/mcu/tools/NVRAMStatistic/src/nvram_gen_util.c
new file mode 100644
index 0000000..2500552
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/src/nvram_gen_util.c
@@ -0,0 +1,1456 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2006
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ * nvram_gen_util.c
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   This file is intends for generating NVRAM information.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+
+#ifndef NVRAM_NOT_PRESENT
+/*
+ * Include
+ */
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/io.h>
+#include "kal_public_api.h"
+
+#include "nvram_auto_gen.h"
+#if defined(__MMI_FMI__)
+#include "nvram_user_defs.h"
+#endif
+#include "nvram_defs.h" /* NVRAM_MSP_ALIGNMENT_REMAINDER */
+#include "custom_nvram_cat.h"
+#include "custom_nvram_config.h"  /* __NVRAM_VENDOR_SUPPORT__ */
+#include "nvram_editor_data_item.h"
+#include "nvram_group_editor.h" //add for break group files from header file
+#ifdef __NVRAM_PSEUDO_MERGE__
+#include "nvram_pseudo_merge.h"
+#endif
+
+#include "nvram_internal.h"
+
+#include "custom_nvram_int_config.h"
+#ifdef __NV_CHKSUM_ENHANCE__
+#include "custom_nvram_sec.h"   // add ,get checksum type/size.
+
+/* CUSTOM_CHK_ALGO_CONFIG configure*/
+extern nvram_checksum_config CUSTOM_CHK_ALGO_CONFIG;
+kal_uint32 get_checksum_size(nvram_ltable_entry_struct* ldi);
+#endif
+
+kal_uint32 custpack_total_to_verify = 0;
+
+#ifdef __NVRAM_VENDOR_SUPPORT__
+kal_uint32 nvram_vendor_reserve_size = NVRAM_MAX_VENDOR_LID_SIZE;
+#endif
+
+#ifdef __NVRAM_OTP__
+kal_uint32 otp_total_to_verify = 0;
+kal_uint32 otp_size_to_verify = 0;
+#endif
+
+kal_uint32 secupack_total_to_verify = 0;
+kal_uint32 secupack_size_to_verify = 0;
+kal_uint16 secupack_idx = 0;
+
+#if defined(__NVRAM_SECURE_DATA_STORAGE__)
+kal_uint32 sds_total_to_verify = 0;
+kal_uint32 sds_size_to_verify = 0;
+#endif
+
+kal_uint32 nvram_gen_backup_size = 0;
+kal_uint32 nvram_gen_backup_total = 0;
+
+boot_mode_type system_boot_mode;
+
+
+nvram_ltable_entry_struct *logical_data_item_table;
+
+kal_uint32 nvram_gen_total_lid;
+
+/* Fake free_ilm */
+void free_int_ilm(ilm_struct *ilm_ptr, kal_char* file_name, kal_uint32 line)
+{
+}
+
+#define IS_POWER_OF_2(v) ((v & (v - 1)) == 0)
+
+
+ltable_entry_struct logical_data_item_table_internal[] =
+{
+    {
+        NVRAM_EF_SYS_LID,
+        NVRAM_EF_SYS_TOTAL,
+        NVRAM_EF_SYS_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_FF_DEFAULT),
+        NVRAM_CATEGORY_IMPORTANT_L1,
+        NVRAM_ATTR_WRITEPROTECT | NVRAM_ATTR_MULTIPLE,
+        "MT00",
+        VER(NVRAM_EF_SYS_LID)
+    },
+#ifdef __NVRAM_SUPPORT_CUSTPACK__
+    {
+        NVRAM_EF_CUSTPACK_VERNO_LID,
+        NVRAM_EF_CUSTPACK_VERNO_TOTAL,
+        NVRAM_EF_CUSTPACK_VERNO_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_INTERNAL,
+        NVRAM_ATTR_WRITEPROTECT | NVRAM_ATTR_AVERAGE,
+        "MT02",
+        VER(NVRAM_EF_CUSTPACK_VERNO_LID)
+    },
+#endif
+    {
+        NVRAM_EF_NVRAM_LOCK_LID,
+        NVRAM_EF_NVRAM_LOCK_TOTAL,
+        NVRAM_EF_NVRAM_LOCK_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_FF_DEFAULT),
+        NVRAM_CATEGORY_IMPORTANT,
+        NVRAM_ATTR_WRITEPROTECT | NVRAM_ATTR_CONFIDENTIAL | NVRAM_ATTR_FAULT_ASSERT | NVRAM_ATTR_COMMITTED
+        #ifdef __NVRAM_BIND_TO_CHIP_CIPHER__
+         | NVRAM_ATTR_MSP | NVRAM_ATTR_MULTIPLE
+        #endif
+        ,
+        "NV01",
+        VER(NVRAM_EF_NVRAM_LOCK_LID)
+    },
+#ifdef __NVRAM_READ_RESERVED_FILE__    
+    {
+        NVRAM_EF_READ_RESERVED_LID,
+        NVRAM_EF_READ_RESERVED_TOTAL,
+        NVRAM_EF_READ_RESERVED_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_RESERVED,
+        NVRAM_ATTR_AVERAGE,
+        "NONE",
+        VER(NVRAM_EF_READ_RESERVED_LID)
+    },
+#endif    
+#ifdef __NVRAM_UNIT_TEST__
+    {
+        NVRAM_EF_NVRAM_UNIT_TEST_LID,
+        NVRAM_EF_NVRAM_UNIT_TEST_TOTAL,
+        NVRAM_EF_NVRAM_UNIT_TEST_SIZE,
+        NVRAM_NORMAL((const kal_uint8 *)NVRAM_EF_ZERO_DEFAULT),
+#ifdef __SECURE_DATA_STORAGE__
+        NVRAM_CATEGORY_INTERNAL,
+#else
+        NVRAM_CATEGORY_USER,
+#endif
+        NVRAM_ATTR_AVERAGE,
+        "MT10",
+        VER(NVRAM_EF_NVRAM_UNIT_TEST_LID)
+    },
+#endif
+
+#if defined (__NVRAM_UT_TEST__)
+
+    {
+        NVRAM_EF_NVRAM_TEST_1_LID,
+        NVRAM_EF_TEST_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_USER,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_GEN_DEFAULT,
+        "MTT1",
+        VER(NVRAM_EF_NVRAM_TEST_1_LID)
+    },
+
+    {
+        NVRAM_EF_NVRAM_TEST_2_LID,
+        NVRAM_EF_TEST_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_INTERNAL,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_GEN_DEFAULT,
+        "MTT2",
+        VER(NVRAM_EF_NVRAM_TEST_2_LID)
+    },
+
+    {
+        NVRAM_EF_NVRAM_TEST_3_LID,
+        NVRAM_EF_TEST_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_CALIBRAT,
+        NVRAM_ATTR_AVERAGE,
+        "MTT3",
+        VER(NVRAM_EF_NVRAM_TEST_3_LID)
+    },
+
+    {
+        NVRAM_EF_NVRAM_TEST_4_LID,
+        NVRAM_EF_TEST_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_IMPORTANT,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_GEN_DEFAULT
+        #if defined (__CCCIFS_SUPPORT__)
+        | NVRAM_ATTR_COMMITTED
+        #endif
+        ,
+        "MTT4",
+        VER(NVRAM_EF_NVRAM_TEST_4_LID)
+    },
+
+    {
+        NVRAM_EF_NVRAM_TEST_5_LID,
+        NVRAM_EF_TEST_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_IMPORTANT_L1,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_GEN_DEFAULT,
+        "MTT5",
+        VER(NVRAM_EF_NVRAM_TEST_5_LID)
+    },
+    
+    {
+        NVRAM_EF_NVRAM_TEST_6_LID,
+        NVRAM_EF_TEST_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_IMPORTANT_L4,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_GEN_DEFAULT | NVRAM_ATTR_CHKSUM_INTEGRATE
+        #if defined (__CCCIFS_SUPPORT__)
+         | NVRAM_ATTR_COMMITTED
+        #endif
+        ,
+        "MTT6",
+        VER(NVRAM_EF_NVRAM_TEST_6_LID)
+    },
+
+    {
+        NVRAM_EF_NVRAM_TEST_7_LID,
+        1, //NVRAM_EF_TEST_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_CALIBRAT,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_RAW_DATA,
+        "MTT7",
+        VER(NVRAM_EF_NVRAM_TEST_7_LID)
+    },
+
+    {
+        NVRAM_EF_NVRAM_TEST_8_LID,
+        NVRAM_EF_TEST_8_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_8_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_USER,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_CHKSUM_INTEGRATE,
+        "MTT8",
+        VER(NVRAM_EF_NVRAM_TEST_8_LID)
+    },     
+    {
+        NVRAM_EF_NVRAM_TEST_9_LID,
+        NVRAM_EF_TEST_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_USER,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_GEN_DEFAULT | NVRAM_ATTR_MCF_OTA_FOR_QUERY,
+        "MTT9",
+        VER(NVRAM_EF_NVRAM_TEST_9_LID)
+    },
+    {
+        NVRAM_EF_NVRAM_TEST_10_LID,
+        NVRAM_EF_TEST_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_USER,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_GEN_DEFAULT | NVRAM_ATTR_MCF_OTA_BY_OP,
+        "MTTA",
+        VER(NVRAM_EF_NVRAM_TEST_10_LID)
+    },
+    {
+        NVRAM_EF_NVRAM_TEST_11_LID,
+        NVRAM_EF_TEST_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_USER,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_GEN_DEFAULT | NVRAM_ATTR_MCF_OTA | NVRAM_ATTR_MCF_OTA_BY_OP,
+        "MTTB",
+        VER(NVRAM_EF_NVRAM_TEST_11_LID)
+    },
+    {
+        NVRAM_EF_NVRAM_TEST_12_LID,
+        NVRAM_EF_TEST_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_USER,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_GEN_DEFAULT | NVRAM_ATTR_MCF_OTA,
+        "MTTC",
+        VER(NVRAM_EF_NVRAM_TEST_12_LID)
+    },
+    {
+        NVRAM_EF_INTERNAL_13_LID,
+        NVRAM_EF_TEST_13_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_13_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_IMPORTANT_L1,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_GEN_DEFAULT,
+        "MTTD",
+        VER(NVRAM_EF_INTERNAL_13_LID)
+    },
+    {
+        NVRAM_EF_INTERNAL_TEST_14_LID,
+        NVRAM_EF_TEST_14_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_14_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_USER,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_GEN_DEFAULT,
+        "MTTE",
+        VER(NVRAM_EF_INTERNAL_TEST_14_LID)
+    },
+	{
+        NVRAM_EF_INTERNAL_TEST_16_LID,
+        NVRAM_EF_INTERNAL_TEST_16_LID_RECORD_TOTAL,
+        NVRAM_EF_INTERNAL_TEST_16_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_CALIBRAT,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_CHKSUM_INTEGRATE | NVRAM_ATTR_FAULT_ASSERT,
+        "MTTG",
+        VER(NVRAM_EF_INTERNAL_TEST_16_LID)
+    },
+    {
+        NVRAM_EF_INTERNAL_TEST_17_LID,
+        NVRAM_EF_TEST_LID_RECORD_TOTAL,
+        NVRAM_EF_TEST_LID_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_USER,
+        NVRAM_ATTR_AVERAGE | NVRAM_ATTR_MULTIPLE,
+        "MTTH",
+        VER(NVRAM_EF_INTERNAL_TEST_17_LID)
+    },
+#endif
+
+#if defined(__NVRAM_STRUCTURE_CHANGE_RESET__) || defined(__NVRAM_DEFVAL_CHANGE_RESET__)
+    {
+        NVRAM_EF_CHKSUM_RESET_REC_LID,
+        NVRAM_EF_CHKSUM_RESET_REC_LID_TOTAL,
+        NVRAM_EF_CHKSUM_RESET_REC_SIZE,
+        NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
+        NVRAM_CATEGORY_INTERNAL,
+        NVRAM_ATTR_AVERAGE,
+        "MTCR", //NVRAM check sum reset
+        VER(NVRAM_EF_CHKSUM_RESET_REC_LID)
+    },
+#endif
+
+};
+
+/*****************************************************************************
+* FUNCTION
+*  nvram_gen_assign_entry
+* DESCRIPTION
+*  construct table
+* PARAMETERS
+*  position    [IN]
+*  ldi         [IN]
+* RETURNS
+*  none
+*****************************************************************************/
+void nvram_gen_assign_entry(nvram_ltable_entry_struct* ldi)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    kal_int32 value;
+    kal_uint32 section_size;
+    
+    kal_uint32 tbl_idx = 0, entry_idx = 0;
+    kal_uint32 nvram_checksum_size = 0;
+    
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+
+    #ifdef __NV_CHKSUM_ENHANCE__
+    nvram_checksum_size = get_checksum_size(ldi); // get nvram_checksum_size , read CUSTOM_CHK_ALGO_CONFIG.
+    #else
+    nvram_checksum_size = NVRAM_CHKSUM_SIZE;
+    #endif
+    
+    /*  Step 1:  Adjust attr / Category
+        Step 2:  Verify
+        Step 3:  Statistics */
+    
+    //Tool check begin: nvram_pre_gen.pl check if it is same as nvram_assign_table_entry() and nvram_gen_assign_entry() 
+    //***************************************************************************
+    // Adjust Attr/Category I
+    //     Do not need multiple attribute if nvram saved on nor flash
+    //***************************************************************************
+    if( (ldi->total_records < 2) && ( (ldi->attr & NVRAM_ATTR_MULTIREC_READ) || (ldi->attr & NVRAM_ATTR_MULTI_DEFAULT)))
+    {
+        fprintf(stderr,
+                "Can't Set the NVRAM_ATTR_MULTIREC_READ or NVRAM_ATTR_MULTI_DEFAULT for the lid with only one record, %d, %s\n", ldi->LID, ldi->str_LID);
+        exit(3); /* NVRAM_EXIT_CODE_ERROR */
+    }
+
+    if (ldi->default_value == (kal_uint8 const*)NVRAM_EF_FF_DEFAULT ||
+        ldi->default_value == (kal_uint8 const*)NVRAM_EF_ZERO_DEFAULT)
+    {
+        #if defined (__NVRAM_UT_TEST__)
+        // Don't remove test lid gen default attribute
+        if(ldi->LID < NVRAM_EF_NVRAM_UNIT_TEST_LID || ldi->LID > NVRAM_EF_NVRAM_UNIT_TEST_LID_END)
+        #endif
+        if((ldi->attr & NVRAM_ATTR_GEN_DEFAULT) && !(NVRAM_IS_CATEGORY_IMPORTANT_L4(ldi->category)))
+        {
+           fprintf(stderr,
+                "Can't Set the NVRAM_ATTR_GEN_DEFAULT for the lid with Zero or FF default value, %d, %s\n", ldi->LID, ldi->str_LID);
+            exit(3); /* NVRAM_EXIT_CODE_ERROR */
+        }
+    }
+
+    if(NVRAM_IS_CATEGORY_IMPORTANT_L4(ldi->category) && !(ldi->attr & NVRAM_ATTR_GEN_DEFAULT))
+    {
+        fprintf(stderr,
+                "Must Set the NVRAM_ATTR_GEN_DEFAULT for L4 Category LID, %d, %s\n", ldi->LID, ldi->str_LID);
+            exit(3); /* NVRAM_EXIT_CODE_ERROR */
+    }
+    
+    //***************************************************************************
+    // Adjust Attr/Category II
+    //     MULTIPLE / BACKUP_RAW / BACKUP_FAT  are mutually exclusive
+    //***************************************************************************
+    if (NVRAM_IS_CATEGORY_CALIBRAT(ldi->category))
+    {
+        if((ldi->attr &NVRAM_ATTR_RESERVE_BACKWARD) || (ldi->attr &NVRAM_ATTR_MULTIPLE))
+        {
+            fprintf(stderr,
+                "Can't Set NVRAM_ATTR_MULTIPLE/NVRAM_ATTR_RESERVE_BACKWARD for Calibrate Lid, %d, %s\n", ldi->LID, ldi->str_LID);
+            exit(3); /* NVRAM_EXIT_CODE_ERROR */
+        }    
+    #if defined(__NVRAM_BACKUP_DISK_FAT__)
+
+        if((ldi->attr & NVRAM_ATTR_MULTIPLE) || (ldi->attr & NVRAM_ATTR_BACKUP_RAW))
+        {
+            fprintf(stderr,
+                "Can't Set the NVRAM_ATTR_MULTIPLE/NVRAM_ATTR_BACKUP_RAW for Calibrat, %d, %s\n", ldi->LID, ldi->str_LID);
+                exit(3); /* NVRAM_EXIT_CODE_ERROR */
+        }
+        if((ldi->attr & NVRAM_ATTR_BACKUP_FAT) == 0)
+        {
+            fprintf(stderr,
+                "Should set the NVRAM_ATTR_BACKUP_FAT for Calibrat, %d, %s\n", ldi->LID, ldi->str_LID);
+                exit(3); /* NVRAM_EXIT_CODE_ERROR */
+        }
+        
+    #elif defined(__NVRAM_BACKUP_DISK_RAW__)
+        if((ldi->attr & NVRAM_ATTR_MULTIPLE) || (ldi->attr & NVRAM_ATTR_BACKUP_FAT))
+        {
+            fprintf(stderr,
+                "Can't Set the NVRAM_ATTR_MULTIPLE/NVRAM_ATTR_BACKUP_FAT for Calibrat, %d, %s\n", ldi->LID, ldi->str_LID);
+                exit(3); /* NVRAM_EXIT_CODE_ERROR */
+        }
+        if((ldi->attr & NVRAM_ATTR_BACKUP_RAW) == 0)
+        {
+            fprintf(stderr,
+                "Should set the NVRAM_ATTR_BACKUP_RAW for Calibrat, %d, %s\n", ldi->LID, ldi->str_LID);
+                exit(3); /* NVRAM_EXIT_CODE_ERROR */
+        }
+    #else
+        #if !defined(__LOW_COST_SUPPORT_COMMON__) && !defined(__CCCIFS_SUPPORT__) && !defined(__FS_RAMDISK__)
+        if((ldi->attr & NVRAM_ATTR_MULTIPLE) == 0)
+        {
+            fprintf(stderr,
+                "Should set the NVRAM_ATTR_MULTIPLE for Calibrat under this scenario, %d, %s\n", ldi->LID, ldi->str_LID);
+                exit(3); /* NVRAM_EXIT_CODE_ERROR */
+        }
+        #endif
+        if((ldi->attr & NVRAM_ATTR_BACKUP_RAW) || (ldi->attr & NVRAM_ATTR_BACKUP_FAT))
+        {
+            fprintf(stderr,
+                "Can't Set the NVRAM_ATTR_BACKUP_RAW/NVRAM_ATTR_BACKUP_FAT for Calibrat, %d, %s\n", ldi->LID, ldi->str_LID);
+                exit(3); /* NVRAM_EXIT_CODE_ERROR */
+        }
+    #endif
+    }
+
+    //***************************************************************************
+    // Adjust Attr/Category III
+    //     Just apply to smartphone
+    //     1: When AP side clean boot, nvram will reset all lid
+    //     2: When Modern side restore factory, nvram only reset data item in NVD_DATA
+    //        and don't care about data item in folder A & B
+    //     3: So, turn off NVRAM_CATEGORY_FACTORY
+    //***************************************************************************
+#if defined(__CCCIFS_SUPPORT__)
+    if (NVRAM_IS_CATEGORY_IMPORTANT(ldi->category) || NVRAM_IS_CATEGORY_IMPORTANT_L4(ldi->category))
+    {
+        if((ldi->attr & NVRAM_ATTR_RESERVE_BACKWARD))
+        {
+            fprintf(stderr,
+                "Can't Set the NVRAM_ATTR_RESERVE_BACKWARD for Important/Impotant_L4, %d, %s\n", ldi->LID, ldi->str_LID);
+                exit(3); /* NVRAM_EXIT_CODE_ERROR */
+        }
+        if((ldi->attr & NVRAM_ATTR_COMMITTED) == 0)
+        {
+            fprintf(stderr,
+                "Suggest Set the NVRAM_ATTR_COMMITTED for Important/Impotant_L4, %d, %s\n", ldi->LID, ldi->str_LID);
+                exit(3); /* NVRAM_EXIT_CODE_ERROR */
+        }
+    }   
+#endif
+
+    //***************************************************************************
+    // Adjust Attr/Category IV
+    //       OTP category cannot use with many attribute together. Because it cannot be reset
+    //       OTP category also cannot use with other category together.
+    //***************************************************************************
+#ifdef __NVRAM_OTP__
+    if (NVRAM_IS_CATEGORY_OTP(ldi->category))
+    {
+        if( (ldi->attr & NVRAM_ATTR_WRITEPROTECT) || (ldi->attr & NVRAM_ATTR_MULTIPLE) || (ldi->attr & NVRAM_ATTR_MSP) || (ldi->attr & NVRAM_ATTR_OTA_RESET) )
+        {
+            fprintf(stderr,
+                "Can't Set NVRAM_ATTR_WRITEPROTECT/NVRAM_ATTR_MULTIPLE/NVRAM_ATTR_MSP/NVRAM_ATTR_OTA_RESET for OTP, %d, %s\n", ldi->LID, ldi->str_LID);
+                exit(3); /* NVRAM_EXIT_CODE_ERROR */
+        }
+    }
+#endif
+
+    //***************************************************************************
+    // Adjust Attr/Category V
+    //      Add pseudo merge attribute
+    //***************************************************************************
+    /* Record data item will be restored (end) */
+#ifdef __NVRAM_PSEUDO_MERGE__
+    if (!NVRAM_IS_CATEGORY_INTERNAL(ldi->category) &&
+        !NVRAM_IS_CATEGORY_SECUPACK(ldi->category) &&
+        !NVRAM_IS_CATEGORY_IMPORTANT(ldi->category) &&
+        !NVRAM_IS_CATEGORY_CALIBRAT(ldi->category) &&
+    #ifdef __NVRAM_CUSTOM_SENSITIVE__
+        !NVRAM_IS_CATEGORY_CUSTOM_SENSITIVE(ldi->category) &&
+    #endif
+    #ifdef __NVRAM_CUSTOM_DISK__
+        !NVRAM_IS_CATEGORY_CUSTOM_DISK(ldi->category) &&
+    #endif
+          ((ldi->size + nvram_checksum_size) * ldi->total_records < NVRAM_CLUSTER_SIZE))
+    {
+        if((ldi->attr & NVRAM_ATTR_PACKAGE) == 0)
+        {
+            fprintf(stderr,
+                "Should set the NVRAM_ATTR_PACKAGE for this lid %d, %s\n", ldi->LID, ldi->str_LID);
+                exit(3); /* NVRAM_EXIT_CODE_ERROR */
+        }
+    }
+
+    if (NVRAM_IS_ATTR_PACKAGE(ldi->attr))
+    {
+        ldi->description = NULL;
+        if( (ldi->attr & NVRAM_ATTR_MULTIPLE) || (ldi->attr & NVRAM_ATTR_MSP))
+        {
+            fprintf(stderr,
+                "Can't Set NVRAM_ATTR_MULTIPLE/NVRAM_ATTR_MSP for PACKAGE Lid, %d, %s\n", ldi->LID, ldi->str_LID);
+                exit(3); /* NVRAM_EXIT_CODE_ERROR */
+        }
+        }
+    #endif
+
+    //***************************************************************************
+    // Adjust Attr/Category VI
+    //      Add MSP, confidential, multiple with secupack item
+    //***************************************************************************
+
+    if (NVRAM_IS_CATEGORY_SECUPACK(ldi->category))
+    {
+        if(!(ldi->attr & NVRAM_ATTR_CONFIDENTIAL) 
+            #ifdef __NVRAM_BIND_TO_CHIP_CIPHER__ 
+            || !(ldi->attr & NVRAM_ATTR_MSP)
+            #endif
+         )
+        {
+            fprintf(stderr,
+                "Should set the NVRAM_ATTR_MSP/NVRAM_ATTR_CONFIDENTIAL, %d, %s\n", ldi->LID, ldi->str_LID);
+            exit(3); /* NVRAM_EXIT_CODE_ERROR */
+        }
+    }
+
+    //***************************************************************************
+    // Adjust Attr/Category VII
+    //      Add MSP, confidential, multiple with custom sensitve data
+    //***************************************************************************
+
+#ifdef __NVRAM_CUSTOM_SENSITIVE__
+    if (NVRAM_IS_CATEGORY_CUSTOM_SENSITIVE(ldi->category))
+    {
+        if( !(ldi->attr & NVRAM_ATTR_MSP) || !(ldi->attr & NVRAM_ATTR_CONFIDENTIAL) || !(ldi->attr & NVRAM_ATTR_MULTIPLE))
+        {
+            fprintf(stderr,
+                "Should Set the NVRAM_ATTR_MSP/NVRAM_ATTR_CONFIDENTIAL/NVRAM_ATTR_MULTIPLE, %d, %s\n", ldi->LID, ldi->str_LID);
+                exit(3); /* NVRAM_EXIT_CODE_ERROR */
+        }
+    }
+#endif
+
+    //***************************************************************************
+    // Adjust Attr/Category
+    //      Simulation/Palladium/FPGA remove NVRAM_ATTR_GEN_DEFAULT
+    //***************************************************************************
+#if defined(_SIMULATION) || defined(__PALLADIUM__) || defined(__FPGA__)
+    if (!NVRAM_IS_CATEGORY_INTERNAL(ldi->category))
+    {
+        ldi->attr &= ~(NVRAM_ATTR_GEN_DEFAULT);
+    }
+#endif
+
+    //***************************************************************************
+    // Adjust Attr/Category VIII
+    //      remove all attribute if the data is in custom disk
+    //***************************************************************************
+#ifdef __NVRAM_CUSTOM_DISK__
+    if (NVRAM_IS_CATEGORY_CUSTOM_DISK(ldi->category))
+    {
+        if(ldi->attr != NVRAM_ATTR_AVERAGE)
+        {
+            fprintf(stderr,
+                "Can't set other attribute except NVRAM_ATTR_AVERAGE, %d, %s\n", ldi->LID, ldi->str_LID);
+                exit(3); /* NVRAM_EXIT_CODE_ERROR */
+        }
+    }
+#endif
+
+    //***************************************************************************
+    // Adjust Attr/Category X
+    //      1. Compress the data in MT table and it is in custpack
+    //      2. Compress the default value of the data not in MT table
+    //         and its default value is not zero default or ff default
+    // coppress function had phaseout
+    //***************************************************************************
+
+    //***************************************************************************
+    // Adjust Attr/Category XI
+    //      Put Internal, Calibration, Important data into SDS
+    //***************************************************************************
+#if defined(__NVRAM_SECURE_DATA_STORAGE__)
+    if (NVRAM_IS_CATEGORY_INTERNAL(ldi->category) ||
+        NVRAM_IS_CATEGORY_CALIBRAT(ldi->category) ||
+        NVRAM_IS_CATEGORY_IMPORTANT(ldi->category) ||
+        NVRAM_IS_CATEGORY_IMPORTANT_L4(ldi->category))
+    {
+        ldi->category |= NVRAM_CATEGORY_BACKUP_SDS;
+
+        ldi->attr &= ~ NVRAM_ATTR_MULTIPLE;
+        ldi->attr &= ~ NVRAM_ATTR_RING;
+        ldi->attr &= ~ NVRAM_ATTR_PACKAGE;
+        ldi->attr &= ~ NVRAM_ATTR_BACKUP_FAT;
+        ldi->attr &= ~ NVRAM_ATTR_BACKUP_RAW;
+    }
+    #endif
+    //Tool check end: nvram_pre_gen.pl
+
+    //***************************************************************************
+    // Check I
+    //     cannot put the data into two categories that are mutually exclusive
+    //***************************************************************************
+
+    value = (ldi->category &
+             (NVRAM_CATEGORY_INTERNAL
+             | NVRAM_CATEGORY_CALIBRAT
+             | NVRAM_CATEGORY_IMPORTANT
+             | NVRAM_CATEGORY_IMPORTANT_L4
+             | NVRAM_CATEGORY_IMPORTANT_L1
+            #ifdef __NVRAM_CUSTOM_SENSITIVE__
+             | NVRAM_CATEGORY_CUSTOM_SENSITIVE
+            #endif
+            #ifdef __NVRAM_CUSTOM_DISK__
+             | NVRAM_CATEGORY_CUSTOM_DISK
+            #endif
+             ));
+
+    /* check if value is power of 2 */
+    if (!IS_POWER_OF_2(value))
+    {
+        fprintf(stderr,
+                "Category inernal & calibrate & important & sensitive can't be used at the same time!, %d, %s\n", ldi->LID, ldi->str_LID);
+        exit(3); /* NVRAM_EXIT_CODE_ERROR */
+
+    }
+
+
+    //***************************************************************************
+    // Check II
+    //     cannot put the sds data with custom
+    //***************************************************************************
+#if defined(__NVRAM_SECURE_DATA_STORAGE__)
+    if (NVRAM_IS_CATEGORY_BACKUP_SDS(ldi->category))
+    {
+        if (NVRAM_IS_CATEGORY_CUSTOM_SENSITIVE(ldi->category) ||
+            NVRAM_IS_CATEGORY_CUSTOM_DISK(ldi->category)      ||
+            NVRAM_IS_CATEGORY_OTP(ldi->category))
+        {
+            fprintf(stderr,"Error: Sds use with wrong category LID:%s Desc:%s category %d\n",
+                ldi->str_LID, ldi->str_LID, ldi->category);
+
+            exit(3); /* NVRAM_EXIT_CODE_ERROR */
+        }
+
+        if ((ldi->attr & NVRAM_ATTR_MULTIPLE)   ||
+            (ldi->attr & NVRAM_ATTR_RING)       ||
+            (ldi->attr & NVRAM_ATTR_PACKAGE)    ||
+            (ldi->attr & NVRAM_ATTR_BACKUP_FAT) ||
+            (ldi->attr & NVRAM_ATTR_BACKUP_RAW))
+        {
+            fprintf(stderr,"Error: Sds use with wrong attribute LID:%s Desc:%s attribute %d\n",
+                ldi->str_LID, ldi->str_LID, ldi->attr);
+
+            exit(3); /* NVRAM_EXIT_CODE_ERROR */
+        }
+
+
+    #ifdef __NVRAM_BIND_TO_CHIP_CIPHER__
+        if (ldi->attr & NVRAM_ATTR_MSP)
+        {
+                /* 16 byte alignment */
+            section_size = ldi->size + nvram_checksum_size + NVRAM_MSP_ALIGNMENT_REMAINDER(ldi->size + nvram_checksum_size);
+        }
+        else
+    #endif
+        {
+            section_size = ldi->size + nvram_checksum_size;
+        }
+
+        if (section_size * ldi->total_records > NVRAM_CUSTOM_CFG_MAX_RECORD_SIZE)
+        {
+            fprintf(stderr,"Error: Data is too large to put into sds LID:%s Desc:%s %d %d\n",
+                ldi->str_LID, ldi->str_LID, ldi->size, ldi->total_records);
+
+            exit(3); /* NVRAM_EXIT_CODE_ERROR */
+        }
+    }
+#endif
+
+
+    //***************************************************************************
+    // Check (III)
+    //     Cannot use zero default or ff default with multi default
+    //***************************************************************************
+
+    if (ldi->attr & NVRAM_ATTR_MULTI_DEFAULT)
+    {
+        if (strcmp(ldi->str_default_value, "NVRAM_EF_ZERO_DEFAULT") == 0 ||
+            strcmp(ldi->str_default_value, "NVRAM_EF_FF_DEFAULT") == 0)
+        {
+            fprintf(stderr,
+                "Cannot set ZERO_DEFAULT or FF_DEFAULT with multi_default!, %d, %s\n", ldi->LID, ldi->str_LID);
+            exit(3);
+        }
+    }
+
+    //***************************************************************************
+    // Check (IV)
+    //     The record size cannot bigger than the biggest control buffer
+    //***************************************************************************
+#ifndef __NVRAM_LARGE_RECORD_SIZE__
+
+#ifdef __NVRAM_BIND_TO_CHIP_CIPHER__
+    if (ldi->attr & NVRAM_ATTR_MSP)
+    {
+            /* 16 byte alignment */
+        section_size = ldi->size + nvram_checksum_size + NVRAM_MSP_ALIGNMENT_REMAINDER(ldi->size + nvram_checksum_size);
+    }
+    else
+#endif
+    {
+        section_size = ldi->size + nvram_checksum_size;
+    }
+
+
+
+    if (section_size > NVRAM_CUSTOM_CFG_MAX_RECORD_SIZE)
+    {
+        fprintf(stderr,
+                "LID Size is too big!, %d, %s\n", ldi->LID, ldi->str_LID);
+        exit(3);
+    }
+#endif
+
+    //***************************************************************************
+    // Check V
+    //      Items in custpack cannot use zero default or ff default as the default value
+    //***************************************************************************
+    if (NVRAM_IS_CATEGORY_CUSTPACK(ldi->category))
+    {
+        if (strcmp(ldi->str_default_value, "NVRAM_EF_ZERO_DEFAULT") == 0 ||
+            strcmp(ldi->str_default_value, "NVRAM_EF_FF_DEFAULT") == 0)
+        {
+            fprintf(stderr,
+                "Cannot set ZERO_DEFAULT or FF_DEFAULT with custpack!, %d, %s\n", ldi->LID, ldi->str_LID);
+            exit(3);
+
+        }
+    }
+    
+    //***************************************************************************
+    // Check VI
+    //     Build error check: CALIBRAT LID should not have NVRAM_ATTR_OTA_RESET attribute.
+    //***************************************************************************
+    if (NVRAM_IS_CATEGORY_CALIBRAT(ldi->category) && (ldi->attr&NVRAM_ATTR_OTA_RESET))
+    {
+        fprintf(stderr,
+                "Error usage: NVRAM_ATTR_SW_VERNO_REST and NVRAM_CATEGORY_CALIBRAT should not use together!, %d, %s\n", ldi->LID, ldi->str_LID);
+            exit(3);
+            
+    }
+    
+    //***************************************************************************
+    //  Statistics I
+    //      calculate the custpack
+    //***************************************************************************
+    if (NVRAM_IS_CATEGORY_CUSTPACK(ldi->category))
+    {
+        custpack_total_to_verify++;
+    }
+    //***************************************************************************
+    //  Statistics II
+    //      calculate the secupack
+    //***************************************************************************
+
+    if (NVRAM_IS_CATEGORY_SECUPACK(ldi->category))
+    {
+        secupack_total_to_verify++;
+
+        if (ldi->attr & NVRAM_ATTR_MULTI_DEFAULT)
+        {
+            secupack_size_to_verify += ldi->size * ldi->total_records + nvram_checksum_size;
+        }
+        else
+        {
+            secupack_size_to_verify += ldi->size + nvram_checksum_size;
+        }
+    }
+
+    //***************************************************************************
+    //  Statistics III
+    //      calculate the otp
+    //***************************************************************************
+#ifdef __NVRAM_OTP__
+    if (NVRAM_IS_CATEGORY_OTP(ldi->category))
+    {
+        otp_total_to_verify++;
+        otp_size_to_verify += ldi->size * ldi->total_records;
+    }
+#endif /* __NVRAM_OTP__ */
+
+
+    //***************************************************************************
+    //  Statistics IV
+    //      calculate the vendor reserve size
+    //***************************************************************************
+
+#ifdef __NVRAM_VENDOR_SUPPORT__
+    if (is_customregion)
+    {
+        kal_uint32 section_size = ldi->size * ldi->total_records + nvram_checksum_size;
+        if (section_size < nvram_vendor_reserve_size)
+        {
+            nvram_vendor_reserve_size -= section_size;
+        }
+        else
+        {
+            fprintf(stderr,
+                    "My dear, total size for vendor nvram shouldn't be larger than %d!\n", NVRAM_MAX_VENDOR_LID_SIZE);
+            exit(3); /* NVRAM_EXIT_CODE_ERROR */
+        }
+    }
+#endif /* __NVRAM_VENDOR_SUPPORT__ */
+
+    //***************************************************************************
+    //  Statistics IV
+    //      calculate the vendor reserve size
+    //***************************************************************************
+#if defined(__NVRAM_SECURE_DATA_STORAGE__)
+    if (NVRAM_IS_CATEGORY_BACKUP_SDS(ldi->category))
+    {
+        sds_total_to_verify++;
+        sds_size_to_verify += (ldi->size + nvram_checksum_size + NVRAM_MSP_ALIGNMENT_REMAINDER(ldi->size + nvram_checksum_size)) * ldi->total_records;
+    }
+#endif
+
+}
+
+/*****************************************************************************
+ * FUNCTION
+ *  nvram_assign_cat_entry
+ * DESCRIPTION
+ * PARAMETERS
+ * RETURNS
+ *****************************************************************************/
+static void nvram_gen_assign_cat_default_value(nvram_lid_enum position, nvram_cat_replace_setting* cat_item)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+
+    if (cat_item->size != logical_data_item_table[position].size ||
+        cat_item->total_records != logical_data_item_table[position].total_records)
+    {
+        return;
+    }
+
+    logical_data_item_table[position].default_value = cat_item->default_value;
+
+    if (cat_item->is_multi_default)
+    {
+        logical_data_item_table[position].attr &= NVRAM_ATTR_MULTI_DEFAULT;
+    }
+    else
+    {
+        logical_data_item_table[position].attr &= ~NVRAM_ATTR_MULTI_DEFAULT;
+    }
+}
+
+int ltable_enum_cmp_local(nvram_ltable_entry_struct *ent_a, nvram_ltable_entry_struct *ent_b)
+{
+    return (int)(ent_a->LID - ent_b->LID);
+}
+
+/*****************************************************************************
+* FUNCTION
+*  nvram_gen_construct_ltable
+* DESCRIPTION
+*  To construct ltable.
+* PARAMETERS
+*  None
+* RETURNS
+*  None
+*****************************************************************************/
+void nvram_gen_construct_ltable(void)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    extern unsigned char nvram_ltable_begin, nvram_ltable_end;
+    kal_uint32 i = 0, tbl_idx = 0, tbl_size;
+    nvram_ltable_entry_struct *logical_data_item_table_bak;
+	size_t tbl_entry_size = sizeof(nvram_ltable_entry_struct);
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+
+    logical_data_item_table_bak = (nvram_ltable_entry_struct *)&nvram_ltable_begin;
+    tbl_size = (kal_uint32)(&nvram_ltable_end - &nvram_ltable_begin);
+    nvram_gen_total_lid = tbl_size/sizeof(nvram_ltable_entry_struct);
+	logical_data_item_table = (nvram_ltable_entry_struct *) malloc(tbl_size);
+	memcpy(logical_data_item_table, logical_data_item_table_bak, tbl_size);
+	qsort(logical_data_item_table, nvram_gen_total_lid, tbl_entry_size, ltable_enum_cmp_local);
+    printf("addr = %x, entry size: %d, real size: %d %s result size:%d\n", logical_data_item_table, sizeof(nvram_ltable_entry_struct), tbl_size, tbl_size%sizeof(nvram_ltable_entry_struct)?"!=":"=",nvram_gen_total_lid * sizeof(nvram_ltable_entry_struct));
+
+    do 
+    {
+        printf("ltable[%d](0x%x) = %s(%d), size = %d, total_records = %d\n",
+            i, &logical_data_item_table[i], logical_data_item_table[i].str_LID, logical_data_item_table[i].LID, logical_data_item_table[i].size, logical_data_item_table[i].total_records);
+
+        nvram_gen_assign_entry(&logical_data_item_table[i]);
+
+    }while(++i < nvram_gen_total_lid);
+
+#if 0    
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+#endif
+}
+
+/*****************************************************************************
+ * FUNCTION
+ *  nvram_gen_search_entry
+ * DESCRIPTION
+ *  To construct ltable.
+ * PARAMETERS
+ *  None
+ * RETURNS
+ *  None
+ *****************************************************************************/
+nvram_ltable_entry_struct* nvram_gen_search_entry(nvram_lid_enum lid)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    kal_uint32 i = 0;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    do 
+    {
+        if (logical_data_item_table[i].LID == lid)
+        {
+            return &logical_data_item_table[i];
+        }
+
+    }while(++i < nvram_gen_total_lid);
+
+    return NULL;
+}
+
+
+#endif /* NVRAM_NOT_PRESENT */
diff --git a/mcu/tools/NVRAMStatistic/src/nvram_hash_check.c b/mcu/tools/NVRAMStatistic/src/nvram_hash_check.c
new file mode 100644
index 0000000..2a6afe3
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/src/nvram_hash_check.c
@@ -0,0 +1,132 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2006
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ * nvram_hash_check.c
+ *
+ * Project:
+ * --------
+ *   UMOLYA
+ *
+ * Description:
+ * ------------
+ *   This file is use to check LID hash info correct.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+
+#include <string.h>
+#include "nvram_hash_check.h" 
+#include "md5.h"
+
+//#define HASH_CHECK_DEBUG
+
+kal_bool nvram_hash_check(nvram_ltable_entry_struct *ldi) {
+#ifdef __NVRAM_LID_HASH_CHECK__
+	static kal_bool first_print = KAL_TRUE;
+	char strbuf[256] = {0};
+	unsigned char digest[17] = {0};
+	unsigned int hash;
+	MD5_CTX context = {0};
+	
+	MD5_Init(&context);
+	sprintf(strbuf, "%d;%s;%s;%s;", ldi->LID, ldi->str_LID, ldi->fileprefix, ldi->fileverno);
+#ifdef HASH_CHECK_DEBUG
+	fprintf(stderr, "debug: %s\n", strbuf);
+#endif
+	MD5_Update(&context, strbuf, strlen(strbuf));
+	MD5_Final(digest, &context);
+#ifdef HASH_CHECK_DEBUG
+	fprintf(stderr, "debug: %02X %02X %02X %02X\n", digest[0], digest[1], digest[2], digest[3]);
+	fprintf(stderr, "debug: %02X %02X %02X %02X\n", digest[4], digest[5], digest[6], digest[7]);
+	fprintf(stderr, "debug: %02X %02X %02X %02X\n", digest[8], digest[9], digest[10], digest[11]);
+#endif	
+	hash =  (digest[4]<<4 | digest[5]>>4) << 24;
+	hash |= (digest[5]<<4 | digest[6]>>4) << 16;
+	hash |= (digest[6]<<4 | digest[7]>>4) << 8;
+	hash |= (digest[7]<<4 | digest[8]>>4);
+#ifdef HASH_CHECK_DEBUG
+	fprintf(stderr, "debug: 0x%08X\n", hash);
+#endif	
+	if(hash != ldi->hash_key) {
+		if(first_print) {
+			fprintf(stderr, "error: Need register LID http://wiki.mediatek.inc/display/NVRAM/How+to+apply+LID+HASH+key\n");
+			fprintf(stderr, "error: This feature is just internal use. Please set NVRAM_LID_HASH_CHECK = FALSE for customer.\n");
+			first_print = KAL_FALSE;
+		}
+		fprintf(stderr, "error: %s (0x%08x) hash key is not match.\n", ldi->str_LID, ldi->hash_key);
+		fprintf(stderr, "debug: %d %s %s %s\n", ldi->LID, ldi->str_LID, ldi->fileprefix, ldi->fileverno);
+		return KAL_FALSE;
+	}
+#endif
+	return KAL_TRUE;
+}
diff --git a/mcu/tools/NVRAMStatistic/src/nvram_white_list.c b/mcu/tools/NVRAMStatistic/src/nvram_white_list.c
new file mode 100644
index 0000000..c4095ff
--- /dev/null
+++ b/mcu/tools/NVRAMStatistic/src/nvram_white_list.c
@@ -0,0 +1,18 @@
+#define ARRAY_ENT_NR(_array)  (sizeof(_array)/sizeof(_array[0]))
+
+
+const char *g_nvram_white_list_for_multiple_attr[] = 
+{
+	"NVRAM_EF_SYS_LID",
+	"NVRAM_EF_SML_LID",
+	"NVRAM_EF_SIM_LOCK_LID"
+};
+const int g_nr_nvram_white_list_for_multiple_attr = ARRAY_ENT_NR(g_nvram_white_list_for_multiple_attr);
+
+const char *g_nvram_white_list_for_write_protect_attr[] = 
+{
+	"NVRAM_EF_SYS_LID",
+	"NVRAM_EF_IMEI_IMEISV_LID",
+	"NVRAM_EF_NVRAM_LOCK_LID"
+};
+const int g_nr_nvram_white_list_for_write_protect_attr = ARRAY_ENT_NR(g_nvram_white_list_for_write_protect_attr);