Add device_info partition.

Change-Id: Ia8d86a5cd4b1bd46cd3923f2cad09931fc877eb0
diff --git a/mbtk/Makefile b/mbtk/Makefile
index d9878d1..3245e82 100755
--- a/mbtk/Makefile
+++ b/mbtk/Makefile
@@ -11,6 +11,8 @@
 
 DIRS += test
 
+DIRS += mbtk_device_info
+
 all:
 	@echo $(ROOT)
 	@echo $(CC)
diff --git a/mbtk/include/mbtk/mbtk_device.h b/mbtk/include/mbtk/mbtk_device.h
new file mode 100755
index 0000000..fdda843
--- /dev/null
+++ b/mbtk/include/mbtk/mbtk_device.h
@@ -0,0 +1,95 @@
+/*
+* mbtk_device.h
+*
+* MBTK device_info partition data header.
+*
+* Author : lb
+* Date   : 2023/12/30 11:36:35
+*/
+#ifndef _MBTK_DEVICE_H
+#define _MBTK_DEVICE_H
+#include "mbtk_type.h"
+
+#define MBTK_DEVICE_INFO_PARTITION_NAME "device_info"
+#define MBTK_DEVICE_INFO_PARTITION_TAG 0x87878787
+#define MBTK_DEVICE_INFO_CURR_VERSION 1
+
+// 78,147,482,134742231
+#define MBTK_BAND_ALL_GSM_DEFAULT 78             // GSM : ASR default.
+#define MBTK_BAND_ALL_WCDMA_DEFAULT 147          // WCDMA : ASR default.
+#define MBTK_BAND_ALL_TDLTE_DEFAULT 482          // TDD-LTE : ASR default.
+#define MBTK_BAND_ALL_FDDLTE_DEFAULT 134742231   // FDD-LTE : ASR default.
+#define MBTK_BAND_CN_GSM_DEFAULT 11             // GSM : B3/B8 (PGSM 900/DCS GSM 1800/EGSM 900)
+#define MBTK_BAND_CN_WCDMA_DEFAULT 145          // WCDMA : B1/B5/B8
+#define MBTK_BAND_CN_TDLTE_DEFAULT 482          // TDD-LTE : B34/B38/B39/B40/B41
+#define MBTK_BAND_CN_FDDLTE_DEFAULT 149         // FDD-LTE : B1/B3/B5/B8
+#define MBTK_BAND_EU_GSM_DEFAULT 11             // GSM : B3/B8 (PGSM 900/DCS GSM 1800/EGSM 900)
+#define MBTK_BAND_EU_WCDMA_DEFAULT 145          // WCDMA : B1/B5/B8
+#define MBTK_BAND_EU_TDLTE_DEFAULT 416          // TDD-LTE : B38/B40/B41
+#define MBTK_BAND_EU_FDDLTE_DEFAULT 134742229   // FDD-LTE : B1/B3/B5/B7/B8/B20/B28
+
+#define MBTK_DEVICE_INFO_ITEM_STR_BASIC "BASIC"
+#define MBTK_DEVICE_INFO_ITEM_STR_FOTA "FOTA"
+#define MBTK_DEVICE_INFO_ITEM_STR_MODEM "MODEM"
+#define MBTK_DEVICE_INFO_ITEM_STR_LOG "LOG"
+
+typedef enum {
+    MBTK_DEVICE_INFO_ITEM_BASIC = 0,
+    MBTK_DEVICE_INFO_ITEM_FOTA,
+    MBTK_DEVICE_INFO_ITEM_MODEM,
+    MBTK_DEVICE_INFO_ITEM_LOG,
+
+    MBTK_DEVICE_INFO_ITEM_NUM
+} mbtk_device_info_item_enum;
+
+typedef struct {
+    mbtk_device_info_item_enum item;
+    uint32 addr;
+} mbtk_device_info_item_header_t;
+
+typedef struct {
+    uint32 tag;
+    uint32 version;             // Default : 0x01
+    uint32 item_count;
+    mbtk_device_info_item_header_t item_header[MBTK_DEVICE_INFO_ITEM_NUM];
+} mbtk_device_info_header_t;
+
+typedef struct {
+    uint8 name[16];
+    uint32 version;             // Default : 0x01
+    uint8 project[16];          // T108 / L508_X6
+    uint8 project_cust[16];     // T108_C1 / L508_X6_C1  (Refer to: Custom_Model in blf file.)
+    uint32 ab_support;          // 1 for ab
+    uint8 revision_out[48];     // L508_X6v01.01b04.00
+    uint8 revision_in[64];
+} mbtk_device_info_basic_t;
+
+typedef struct {
+    uint8 name[16];
+    uint32 version;             // Default : 0x01
+    uint32 state;               //
+} mbtk_device_info_fota_t;
+
+typedef enum {
+    MBTK_MODEM_BAND_AREA_ALL,
+    MBTK_MODEM_BAND_AREA_CN,
+    MBTK_MODEM_BAND_AREA_EU
+} mbtk_modem_band_area_enum;
+
+typedef struct {
+    uint8 name[16];
+    uint32 version;             // Default : 0x01
+    mbtk_modem_band_area_enum band_area;
+    uint32 band_gsm;
+    uint32 band_wcdma;
+    uint32 band_tdlte;
+    uint32 band_fddlte;
+} mbtk_device_info_modem_t;
+
+typedef struct {
+    uint8 name[16];
+    uint32 version;             // Default : 0x01
+    uint32 state;               //
+} mbtk_device_info_log_t;
+
+#endif /* _MBTK_DEVICE_H */
diff --git a/mbtk/include/mbtk/mbtk_mtd.h b/mbtk/include/mbtk/mbtk_mtd.h
new file mode 100755
index 0000000..0e4b80d
--- /dev/null
+++ b/mbtk/include/mbtk/mbtk_mtd.h
@@ -0,0 +1,26 @@
+/*
+* mbtk_mtd.h
+*
+* MBTK mtd partition utils header.
+*
+* Author : lb
+* Date   : 2024/2/26 16:03:50
+*/
+#ifndef _MBTK_MTD_H
+#define _MBTK_MTD_H
+#include "mbtk_type.h"
+
+#define MBTK_PARTITION_NUM_MAX 30
+
+typedef struct {
+    char name[32];
+    char dev[16];
+    uint32 partition_start;
+    uint32 partition_size;
+
+    bool used;
+} mbtk_partition_info_t;
+
+mbtk_partition_info_t* mbtk_partition_get();
+
+#endif /* _MBTK_MTD_H */
diff --git a/mbtk/mbtk_device_info/Makefile b/mbtk/mbtk_device_info/Makefile
new file mode 100755
index 0000000..3d44e2e
--- /dev/null
+++ b/mbtk/mbtk_device_info/Makefile
@@ -0,0 +1,33 @@
+ROOT = $(shell pwd)/../..
+include ../Make.defines
+
+LOCAL_PATH=$(BUILD_ROOT)/mbtk_device_info
+
+INC_DIR += \
+		-I$(LOCAL_PATH)
+
+CC=gcc
+
+MY_FILES_PATH:=$(LOCAL_PATH)
+
+LOCAL_SRC_FILES = $(wildcard *.c)
+OBJS = $(patsubst %.c, %.o, $(patsubst %.cpp, %.o, $(LOCAL_SRC_FILES)))
+$(info OBJS = $(OBJS))
+
+dtarget := $(OUT_DIR)/bin/device_info_generate
+
+all: $(dtarget)
+
+$(dtarget): $(OBJS)
+	@echo "  BIN     $@"
+	$(CC) $(OBJS) -o $@
+
+%.o:%.c
+	$(CC) $(INC_DIR) -c $< -o $@
+
+%.o:%.cpp
+	$(CC) $(INC_DIR) -c $< -o $@
+
+clean:
+	rm -f $(OBJS) $(dtarget)
+
diff --git a/mbtk/mbtk_device_info/main.c b/mbtk/mbtk_device_info/main.c
new file mode 100755
index 0000000..5be2289
--- /dev/null
+++ b/mbtk/mbtk_device_info/main.c
@@ -0,0 +1,230 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "mbtk_device.h"
+
+static mbtk_device_info_header_t info_header = {
+    .tag = MBTK_DEVICE_INFO_PARTITION_TAG,
+    .version = MBTK_DEVICE_INFO_CURR_VERSION,
+    .item_count = MBTK_DEVICE_INFO_ITEM_NUM,
+    .item_header = {
+        {MBTK_DEVICE_INFO_ITEM_BASIC, 0},
+        {MBTK_DEVICE_INFO_ITEM_FOTA, 0},
+        {MBTK_DEVICE_INFO_ITEM_MODEM, 0},
+        {MBTK_DEVICE_INFO_ITEM_LOG, 0},
+    }
+};
+
+static mbtk_device_info_basic_t item_basic = {
+    .name = MBTK_DEVICE_INFO_ITEM_STR_BASIC,
+    .version = MBTK_DEVICE_INFO_CURR_VERSION,
+    .project = {0},
+    .project_cust = {0},
+    .ab_support = 1,            // Default for ab system.
+    .revision_out = {0},
+    .revision_in = {0}
+};
+
+static mbtk_device_info_fota_t item_fota = {
+    .name = MBTK_DEVICE_INFO_ITEM_STR_FOTA,
+    .version = MBTK_DEVICE_INFO_CURR_VERSION,
+    .state = 0
+};
+
+static mbtk_device_info_modem_t item_modem = {
+    .name = MBTK_DEVICE_INFO_ITEM_STR_MODEM,
+    .version = MBTK_DEVICE_INFO_CURR_VERSION,
+    .band_area = MBTK_MODEM_BAND_AREA_ALL,  // Default for all bands.
+    .band_gsm = MBTK_BAND_ALL_GSM_DEFAULT,
+    .band_wcdma = MBTK_BAND_ALL_WCDMA_DEFAULT,
+    .band_tdlte = MBTK_BAND_ALL_TDLTE_DEFAULT,
+    .band_fddlte = MBTK_BAND_ALL_FDDLTE_DEFAULT
+};
+
+static mbtk_device_info_log_t item_log = {
+    .name = MBTK_DEVICE_INFO_ITEM_STR_LOG,
+    .version = MBTK_DEVICE_INFO_CURR_VERSION,
+    .state = 0
+};
+
+static void help()
+{
+    printf("device_info_generate -a [a/ab] -b [revision_out] -c [revision_in] -d [project] -e [project_cust] -f [cn/eu/all] -o [out_bin]\n");
+}
+
+static int update_and_write_header(int fd, mbtk_device_info_header_t *header)
+{
+    header->item_header[MBTK_DEVICE_INFO_ITEM_BASIC].addr = sizeof(mbtk_device_info_header_t);
+    header->item_header[MBTK_DEVICE_INFO_ITEM_FOTA].addr = header->item_header[MBTK_DEVICE_INFO_ITEM_BASIC].addr + sizeof(mbtk_device_info_basic_t);
+    header->item_header[MBTK_DEVICE_INFO_ITEM_MODEM].addr = header->item_header[MBTK_DEVICE_INFO_ITEM_FOTA].addr + sizeof(mbtk_device_info_fota_t);
+    header->item_header[MBTK_DEVICE_INFO_ITEM_LOG].addr = header->item_header[MBTK_DEVICE_INFO_ITEM_MODEM].addr + sizeof(mbtk_device_info_modem_t);
+
+    if(sizeof(mbtk_device_info_header_t) != write(fd, header, sizeof(mbtk_device_info_header_t))) {
+        printf("Write header fail:%d\n", errno);
+        return -1;
+    }
+
+    return 0;
+}
+
+static int write_item_basic(int fd, mbtk_device_info_basic_t *item_basic)
+{
+    if(sizeof(mbtk_device_info_basic_t) != write(fd, item_basic, sizeof(mbtk_device_info_basic_t))) {
+        printf("Write item basic fail:%d\n", errno);
+        return -1;
+    }
+
+    return 0;
+}
+
+static int write_item_fota(int fd, mbtk_device_info_fota_t *item_fota)
+{
+    if(sizeof(mbtk_device_info_fota_t) != write(fd, item_fota, sizeof(mbtk_device_info_fota_t))) {
+        printf("Write item fota fail:%d\n", errno);
+        return -1;
+    }
+
+    return 0;
+}
+
+static int write_item_modem(int fd, mbtk_device_info_modem_t *item_modem)
+{
+    if(sizeof(mbtk_device_info_modem_t) != write(fd, item_modem, sizeof(mbtk_device_info_modem_t))) {
+        printf("Write item modem fail:%d\n", errno);
+        return -1;
+    }
+
+    return 0;
+}
+
+static int write_item_log(int fd, mbtk_device_info_log_t *item_log)
+{
+    if(sizeof(mbtk_device_info_log_t) != write(fd, item_log, sizeof(mbtk_device_info_log_t))) {
+        printf("Write item log fail:%d\n", errno);
+        return -1;
+    }
+
+    return 0;
+}
+
+/*
+*
+* device_info_generate -a [a/ab] -b [revision_out] -c [revision_in] -d [project] -e [project_cust] -f [cn/eu/all] -o [out_bin]
+*
+*/
+int main(int argc, char *argv[])
+{
+    int ch;
+    char out_bin[128] = {0};
+    while((ch = getopt(argc, argv, "a:b:c:d:e:f:o:"))!= -1){
+        switch(ch)
+        {
+            case 'a':
+                if(strcmp(optarg, "ab") == 0) {
+                    item_basic.ab_support = 1;
+                } else if(strcmp(optarg, "a") == 0) {
+                    item_basic.ab_support = 0;
+                } else {
+                    printf("Must be a/ab.\n");
+                    return -1;
+                }
+                break;
+            case 'b':
+                if(strlen(optarg) > 0)
+                    memcpy(item_basic.revision_out, optarg, strlen(optarg));
+                break;
+            case 'c':
+                if(strlen(optarg) > 0)
+                    memcpy(item_basic.revision_in, optarg, strlen(optarg));
+                break;
+            case 'd':
+                if(strlen(optarg) > 0)
+                    memcpy(item_basic.project, optarg, strlen(optarg));
+                break;
+            case 'e':
+                if(strlen(optarg) > 0)
+                    memcpy(item_basic.project_cust, optarg, strlen(optarg));
+                break;
+            case 'f':
+                if(strcmp(optarg, "cn") == 0) {
+                    item_modem.band_area = MBTK_MODEM_BAND_AREA_CN;
+                    item_modem.band_gsm = MBTK_BAND_CN_GSM_DEFAULT;
+                    item_modem.band_wcdma = MBTK_BAND_CN_WCDMA_DEFAULT;
+                    item_modem.band_tdlte = MBTK_BAND_CN_TDLTE_DEFAULT;
+                    item_modem.band_fddlte = MBTK_BAND_CN_FDDLTE_DEFAULT;
+                } else if(strcmp(optarg, "eu") == 0) {
+                    item_modem.band_area = MBTK_MODEM_BAND_AREA_EU;
+                    item_modem.band_gsm = MBTK_BAND_EU_GSM_DEFAULT;
+                    item_modem.band_wcdma = MBTK_BAND_EU_WCDMA_DEFAULT;
+                    item_modem.band_tdlte = MBTK_BAND_EU_TDLTE_DEFAULT;
+                    item_modem.band_fddlte = MBTK_BAND_EU_FDDLTE_DEFAULT;
+                } else {
+                    item_modem.band_area = MBTK_MODEM_BAND_AREA_ALL;
+                    item_modem.band_gsm = MBTK_BAND_ALL_GSM_DEFAULT;
+                    item_modem.band_wcdma = MBTK_BAND_ALL_WCDMA_DEFAULT;
+                    item_modem.band_tdlte = MBTK_BAND_ALL_TDLTE_DEFAULT;
+                    item_modem.band_fddlte = MBTK_BAND_ALL_FDDLTE_DEFAULT;
+                    printf("Set to default band.\n");
+                }
+                break;
+            case 'o':
+                if(strlen(optarg) > 0)
+                    memcpy(out_bin, optarg, strlen(optarg));
+                break;
+            default:
+                help();
+                return -1;
+        }
+    }
+    if(strlen(item_basic.revision_out) == 0 || strlen(out_bin) == 0) {
+        help();
+        return -1;
+    }
+
+    printf("Version:%s, Bin:%s\n", item_basic.revision_out, out_bin);
+
+    int fd = open(out_bin, O_WRONLY | O_TRUNC | O_CREAT, 0644);
+    if(fd < 0) {
+        printf("Open(%s) fail:%d\n", out_bin, errno);
+        return -1;
+    }
+
+    if(update_and_write_header(fd, &info_header)) {
+        printf("update_and_write_header() fail.");
+        goto fail;
+    }
+
+    if(write_item_basic(fd, &item_basic)) {
+        printf("update_and_write_item_basic() fail.");
+        goto fail;
+    }
+
+    if(write_item_fota(fd, &item_fota)) {
+        printf("update_and_write_item_fota() fail.");
+        goto fail;
+    }
+
+    if(write_item_modem(fd, &item_modem)) {
+        printf("update_and_write_item_modem() fail.");
+        goto fail;
+    }
+
+    if(write_item_log(fd, &item_log)) {
+        printf("update_and_write_item_log() fail.");
+        goto fail;
+    }
+
+    printf("Success generate device_info bin:%s\n", out_bin);
+    close(fd);
+    return 0;
+fail:
+    close(fd);
+    return -1;
+}
+
diff --git a/mbtk/mbtk_lib/Makefile b/mbtk/mbtk_lib/Makefile
index 216821d..3494835 100755
--- a/mbtk/mbtk_lib/Makefile
+++ b/mbtk/mbtk_lib/Makefile
@@ -83,13 +83,14 @@
 	src/mbtk_utf.c \
 	src/mbtk_utils.c \
 	src/mbtk_fota.c \
-	src/ringbuffer.c
+	src/ringbuffer.c \
+	src/mbtk_mtd.c
 
 ifeq ($(BUILD_PLATFORM), asr1803)
 LOCAL_SRC_FILES +=  \
 				   src/mbtk_audio_alsa.c \
 				   src/mbtk_audio.c
-				   
+
 ifeq ($(BUILD_BRANCH), rls3671)
 LOCAL_SRC_FILES += src/mbtk_mp3_to_wav.c
 endif
diff --git a/mbtk/mbtk_lib/src/mbtk_device_info.c b/mbtk/mbtk_lib/src/mbtk_device_info.c
new file mode 100755
index 0000000..86744a6
--- /dev/null
+++ b/mbtk/mbtk_lib/src/mbtk_device_info.c
@@ -0,0 +1,141 @@
+/*
+*    mbtk_device_info.c
+*
+*    MBTK device partition information utils.
+*
+*/
+/******************************************************************************
+
+                          EDIT HISTORY FOR FILE
+
+  WHEN        WHO       WHAT,WHERE,WHY
+--------    --------    -------------------------------------------------------
+2024/2/27     LiuBin      Initial version
+
+******************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "mbtk_device.h"
+#include "mbtk_log.h"
+#include "mbtk_str.h"
+#include "mbtk_mtd.h"
+
+/*
+* mbtk_device_info_basic_t
+* mbtk_device_info_fota_t
+
+*/
+int mbtk_dev_info_read(mbtk_device_info_item_enum item_type, void *item_ptr, int item_size)
+{
+    int fd, len, i;
+    mbtk_device_info_header_t info_header;
+    memset(&info_header, 0, sizeof(mbtk_device_info_header_t));
+
+    switch(item_type) {
+        case MBTK_DEVICE_INFO_ITEM_BASIC:
+        {
+            if(item_ptr == NULL || item_size != sizeof(mbtk_device_info_basic_t)) {
+                LOGE("ARG error:item-%d, item_size-%d", item_type, item_size);
+                return -1;
+            }
+            break;
+        }
+        case MBTK_DEVICE_INFO_ITEM_FOTA:
+        {
+            if(item_ptr == NULL || item_size != sizeof(mbtk_device_info_fota_t)) {
+                LOGE("ARG error:item-%d, item_size-%d", item_type, item_size);
+                return -1;
+            }
+            break;
+        }
+        case MBTK_DEVICE_INFO_ITEM_MODEM:
+        {
+            if(item_ptr == NULL || item_size != sizeof(mbtk_device_info_modem_t)) {
+                LOGE("ARG error:item-%d, item_size-%d", item_type, item_size);
+                return -1;
+            }
+            break;
+        }
+        case MBTK_DEVICE_INFO_ITEM_LOG:
+        {
+            if(item_ptr == NULL || item_size != sizeof(mbtk_device_info_log_t)) {
+                LOGE("ARG error:item-%d, item_size-%d", item_type, item_size);
+                return -1;
+            }
+            break;
+        }
+        default:
+        {
+            LOGE("Item type[%d] error.", item_type);
+            return -1;
+        }
+    }
+
+    mbtk_partition_info_t *partition_info = mbtk_partition_get();
+    if(partition_info == NULL) {
+        LOGE("mbtk_partition_get() fail.");
+        return -1;
+    }
+
+    i = 0;
+    char dev[32] = {0};
+    while(i < MBTK_PARTITION_NUM_MAX) {
+        if(partition_info[i].used && strcmp(partition_info[i].name, MBTK_DEVICE_INFO_PARTITION_NAME) == 0) {
+            snprintf(dev, 32, "/dev/%s", partition_info[i].dev);
+            LOGD("%s -> %s", strcmp(partition_info[i].name, dev);
+            break;
+        }
+        i++;
+    }
+    if(strlen(dev) == 0) {
+        LOGE("DEV is null.");
+        return -1;
+    }
+
+    fd = open(dev, O_RDONLY);
+    if (fd < 0) {
+        LOGE("Fatal error: can't open device_info %s\n", dev);
+        return -1;
+    }
+
+    len = read(fd, &info_header, sizeof(mbtk_device_info_header_t));
+    if (len != sizeof(mbtk_device_info_header_t)) {
+        LOGE("Fatal error: read %d bytes(expect %d)\n", len, sizeof(mbtk_device_info_header_t));
+        close(fd);
+        goto fail;
+    }
+
+    if(info_header.tag != MBTK_DEVICE_INFO_PARTITION_TAG) {
+        LOGE("TAG error : %08x", info_header.tag);
+        goto fail;
+    }
+
+    if(info_header.version != MBTK_DEVICE_INFO_CURR_VERSION) {
+        LOGE("Version error : %d", info_header.version);
+        goto fail;
+    }
+
+    LOGD("Item count:%d", info_header.item_count);
+
+    if(info_header.item_header[item_type].addr == 0) {
+        LOGE("No found item : %d", item_type);
+        goto fail;
+    }
+
+    lseek(fd, info_header.item_header[item_type].addr, SEEK_SET);
+    if (read(fd, item_ptr, item_size) != item_size) {
+        LOGE("Read fail:%d", errno);
+        goto fail;
+    }
+
+    close(fd);
+    return 0;
+
+fail:
+    close(fd);
+    return -1;
+}
+
diff --git a/mbtk/mbtk_lib/src/mbtk_mtd.c b/mbtk/mbtk_lib/src/mbtk_mtd.c
new file mode 100755
index 0000000..4f1c2be
--- /dev/null
+++ b/mbtk/mbtk_lib/src/mbtk_mtd.c
@@ -0,0 +1,90 @@
+/*
+*    mbtk_mtd.c
+*
+*    MBTK mtd partition utils API.
+*
+*/
+/******************************************************************************
+
+                          EDIT HISTORY FOR FILE
+
+  WHEN        WHO       WHAT,WHERE,WHY
+--------    --------    -------------------------------------------------------
+2024/2/26     LiuBin      Initial version
+
+******************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "mbtk_mtd.h"
+#include "mbtk_log.h"
+#include "mbtk_str.h"
+
+static mbtk_partition_info_t partition_list[MBTK_PARTITION_NUM_MAX];
+static bool partition_inited = FALSE;
+
+mbtk_partition_info_t* mbtk_partition_get()
+{
+    if(partition_inited) {
+        return partition_list;
+    }
+
+    memset(partition_list, 0x0, sizeof(partition_list));
+    FILE *fp = fopen("/proc/mtd", "r");
+    if(fp == NULL) {
+        LOGE("fopen(/proc/mtd) fail:%d", errno);
+        return NULL;
+    }
+
+    char buff[64];
+    int index = 0;
+    char size_str[16];
+    char name[32];
+    memset(buff, 0x0, 64);
+    while(fgets(buff, 64, fp)) {
+        if(str_startwith(buff, "mtd")) {
+            memset(size_str, 0x0, 16);
+            memset(name, 0x0, 32);
+            if(3 == sscanf(buff, "%s %s %*s %s", partition_list[index].dev, size_str, name)) {
+                if(name[0] == '\"' && name[strlen(name) - 1] == '\"') {
+                    memcpy(partition_list[index].name, name + 1, strlen(name) - 2); // No copy ""
+                } else {
+                    LOGE("partition(%s) name error.", buff);
+                    return NULL;
+                }
+
+                if(partition_list[index].dev[strlen(partition_list[index].dev) - 1] == ':') {
+                    partition_list[index].dev[strlen(partition_list[index].dev) - 1] = '\0';
+                }
+
+                partition_list[index].partition_size = (uint32)strtoul(size_str, NULL, 16);
+                if(index > 0) {
+                    partition_list[index].partition_start = partition_list[index - 1].partition_start + partition_list[index - 1].partition_size;
+                }
+                partition_list[index].used = TRUE;
+            } else {
+                LOGE("sscanf(%s) fail:%d", buff, errno);
+                return NULL;
+            }
+            index++;
+        }
+        memset(buff, 0x0, 64);
+    }
+    fclose(fp);
+
+    int i = 0;
+    while(i < MBTK_PARTITION_NUM_MAX) {
+        if(partition_list[i].used) {
+            LOGD("%s(%s) : %08x %08x", partition_list[i].name, partition_list[i].dev,
+                partition_list[i].partition_start, partition_list[i].partition_size);
+        }
+        i++;
+    }
+
+    partition_inited = TRUE;
+    return partition_list;
+}
+
+
diff --git a/mbtk/test/mbtk_mtd_test.c b/mbtk/test/mbtk_mtd_test.c
new file mode 100755
index 0000000..8076076
--- /dev/null
+++ b/mbtk/test/mbtk_mtd_test.c
@@ -0,0 +1,19 @@
+#include "mbtk_mtd.h"
+
+
+int main(int argc, char *argv[])
+{
+    mbtk_partition_info_t *partition_info = mbtk_partition_get();
+    if(partition_info != NULL) {
+        int i = 0;
+        while(i < MBTK_PARTITION_NUM_MAX) {
+            if(partition_info[i].used) {
+                printf("%s(%s) : %08x %08x\n", partition_info[i].name, partition_info[i].dev,
+                    partition_info[i].partition_start, partition_info[i].partition_size);
+            }
+            i++;
+        }
+    }
+    return 0;
+}
+