From: wurui <wu...@actions-semi.com> commit 2f8ff0630784e6ec5af114f8945ff159a8996fd5 from https://github.com/xapp-le/kernel.git
Change-Id: I288a6e5444b9850f9481347a365b8997085ce373 --- drivers/misc/Kconfig | 1 + drivers/misc/Makefile | 1 + drivers/misc/misc-info/Kconfig | 16 + drivers/misc/misc-info/Makefile | 9 + drivers/misc/misc-info/mi_debug.c | 388 +++++++++++++ drivers/misc/misc-info/misc_info.c | 1106 ++++++++++++++++++++++++++++++++++++ drivers/misc/misc-info/misc_info.h | 110 ++++ 7 files changed, 1631 insertions(+) mode change 100644 => 100755 drivers/misc/Kconfig mode change 100644 => 100755 drivers/misc/Makefile create mode 100755 drivers/misc/misc-info/Kconfig create mode 100755 drivers/misc/misc-info/Makefile create mode 100755 drivers/misc/misc-info/mi_debug.c create mode 100755 drivers/misc/misc-info/misc_info.c create mode 100755 drivers/misc/misc-info/misc_info.h diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig old mode 100644 new mode 100755 index b3c10b7..f6bcd7d --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -528,4 +528,5 @@ source "drivers/misc/mic/Kconfig" source "drivers/misc/genwqe/Kconfig" source "drivers/misc/echo/Kconfig" source "drivers/misc/cxl/Kconfig" +source "drivers/misc/misc-info/Kconfig" endmenu diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile old mode 100644 new mode 100755 index 7d5c4cd..8af3148 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -56,3 +56,4 @@ obj-$(CONFIG_GENWQE) += genwqe/ obj-$(CONFIG_ECHO) += echo/ obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o obj-$(CONFIG_CXL_BASE) += cxl/ +obj-$(CONFIG_MISC_INFO) += misc-info/ \ No newline at end of file diff --git a/drivers/misc/misc-info/Kconfig b/drivers/misc/misc-info/Kconfig new file mode 100755 index 0000000..ec360c4 --- /dev/null +++ b/drivers/misc/misc-info/Kconfig @@ -0,0 +1,16 @@ +# +# ACTIONS's MISC INFO ACCESS driver for save important data like serial num, +# wifi mac etc. +# +menu "ACTIONS MISC INFO ACCESS DRIVER" +config MISC_INFO + tristate "Misc info access driver" + default y + help + The Misc info access driver save the hardware information like + serial no, wifi mac etc. + Each function can be configured and enabled/disabled + dynamically from userspace through a debugfs interface. + + If unsure, say "y". +endmenu diff --git a/drivers/misc/misc-info/Makefile b/drivers/misc/misc-info/Makefile new file mode 100755 index 0000000..b711b93 --- /dev/null +++ b/drivers/misc/misc-info/Makefile @@ -0,0 +1,9 @@ +# +# Makefile for ACTIONS's misc info access driver +# +# + +EXTRA_CFLAGS += -DOS_LINUX + +obj-$(CONFIG_MISC_INFO) += mi.o +mi-objs := misc_info.o mi_debug.o diff --git a/drivers/misc/misc-info/mi_debug.c b/drivers/misc/misc-info/mi_debug.c new file mode 100755 index 0000000..c62d60c --- /dev/null +++ b/drivers/misc/misc-info/mi_debug.c @@ -0,0 +1,388 @@ + +#ifdef OS_LINUX +#include <linux/debugfs.h> +#include "misc_info.h" +#endif + + +int debug_enable = 0; + +#ifdef OS_LINUX +struct dentry *dirent; +struct dentry *file; + +typedef void (*debug_func_t)(char *param); +typedef struct +{ + char *func_name; + char *param; + debug_func_t func; +} struct_debug_func; + + +extern int read_storage(void *buf, int start, int size); +extern int write_storage(void *buf, int start, int size); +extern int format_misc_info(void); +extern int read_mi_head(misc_info_head_t * head); +extern void print_mi_items(misc_info_head_t * head); +extern int get_item_size(misc_info_head_t * head, char *name); +extern int read_mi_item(char *name, void *buf, unsigned int count); +extern int write_mi_item(char *name, void *buf, unsigned int count); + +static void debug_help(char *param); +static void debug_print(char *param); +static void debug_dump(char *param); +static void debug_format(char *param); +static void debug_print_items(char *param); +static void debug_get_item(char *param); +static void debug_set_item(char *param); + +struct_debug_func debug_func_table[] = +{ + { + "help", + "", + debug_help, + }, + { + "print", + "enable", + debug_print, + }, + { + "format", + "", + debug_format, + }, + { + "dump_mem", + "start size", + debug_dump, + }, + { + "print_items", + "", + debug_print_items, + }, + { + "read_item", + "name", + debug_get_item, + }, + { + "write_item", + "name type value type:C/c(char) or H/h(hex), value:length < 200", + debug_set_item, + }, +}; + +static void debug_help(char *param) +{ + int i; + PRINT_DBG("%s, line %d\n",__FUNCTION__, __LINE__); + + for(i = 0; i < sizeof(debug_func_table)/sizeof(struct_debug_func); i++) + { + PRINT("[%d] %s %s\n", i, debug_func_table[i].func_name, debug_func_table[i].param); + } +} + +static void debug_print(char *param) +{ + int enable = 0; + + PRINT_DBG("%s, line %d\n",__FUNCTION__, __LINE__); + sscanf(param, "%d", &enable); + + if(enable == 0 || enable == 1){ + debug_enable = enable; + }else{ + PRINT_ERR("invalid param\n"); + return; + } +} + +static void debug_dump(char *param) +{ + int start = 0, size = 0; + unsigned char *buf; + + PRINT_DBG("%s, line %d\n",__FUNCTION__, __LINE__); + sscanf(param, "%d %d", &start, &size); + PRINT_DBG("dump memory start %d, size %d\n", start, size); + if(start < 0 || size < 0 || (start + size) > MISC_INFO_MAX_SIZE){ + PRINT_ERR("invalid param\n"); + return; + } + + buf = MALLOC(size); + if(!buf){ + PRINT_ERR("MALLOC FAILED\n"); + return; + } + if(read_storage(buf, start, size) < 0){ + PRINT_ERR("read_storage failed\n"); + goto OUT; + } + dump_mem(buf, 0, size); +OUT: + if(buf){ + FREE(buf); + buf = NULL; + } +} + +static void debug_format(char *param) +{ + PRINT_DBG("%s, line %d\n",__FUNCTION__, __LINE__); + format_misc_info(); +} + +static void debug_print_items(char *param) +{ + misc_info_head_t *head; + int head_length; + + PRINT_DBG("%s, line %d\n",__FUNCTION__, __LINE__); + head_length = sizeof(misc_info_head_t); + head = MALLOC(head_length); + memset(head, 0, head_length); + + if(read_mi_head(head) < 0){ + PRINT_ERR("read Head failed\n"); + return; + } + print_mi_items(head); + + if(head){ + FREE(head); + head = NULL; + } +} + +static void debug_get_item(char *param) +{ + char name[8] = {0}; + int head_length, size, ret = -1; + void *buf; + misc_info_head_t *head; + + sscanf(param, "%s", name); + if(name[7] != 0) + name[7] = 0; + PRINT_DBG("%s, line %d, name %s\n",__FUNCTION__, __LINE__, name); + + head_length = sizeof(misc_info_head_t); + head = MALLOC(head_length); + memset(head, 0, head_length); + + if(read_mi_head(head) < 0){ + PRINT_ERR("read Head failed\n"); + goto OUT_FAILED; + } + size = get_item_size(head, name); + if(size <= 0){ + PRINT_ERR("no item named %s\n",name); + goto OUT_FAILED; + } + buf = MALLOC(size); + memset(buf, 0, size); + ret = read_mi_item(name, buf, size); + if(ret < 0){ + PRINT_ERR("read data failed\n"); + }else{ + dump_mem(buf, 0, ret); + } + + if(buf){ + FREE(buf); + buf = NULL; + } + +OUT_FAILED: + if(head){ + FREE(head); + head = NULL; + } +} + +int check_hex(char *buf) +{ + int i; + for(i = 0; i < strlen(buf); i++){ + if((buf[i] >= '0' && buf[i] <= '9') + || (buf[i] >= 'a' && buf[i] <= 'f') + || (buf[i] >= 'A' && buf[i] <= 'F')){ + continue; + }else{ + return -1; + } + } + return 0; +} + +void char_to_hex(char *in, char *out) +{ + int i; + char tmp = 0, value = 0; + char buf[128] = {0}; + + //printk("%s, strlen(in)=%d\n",__FUNCTION__, (int)strlen(in)); + if(strlen(in) % 2 == 1){ + PRINT_ERR("must be divide 2\n"); + return; + } + for(i = 0; i < strlen(in); i++){ + if(in[i] >= '0' && in[i] <= '9') + tmp = in[i] - '0'; + else if(in[i] >= 'a' && in[i] <= 'f') + tmp = in[i] - 'a' + 10; + else if(in[i] >= 'A' && in[i] <= 'F') + tmp = in[i] - 'A' + 10; + + if(i % 2 == 0){ + value = tmp * 16; + }else{ + value += tmp; + buf[i/2] = value; + } + } + memcpy(out, buf, strlen(in)/2); +} + +static void debug_set_item(char *param) +{ + char name[8] = {0}; + int ret = -1; + char type; + char value[256] = {0}, buf[256] = {0}; + + sscanf(param, "%s %c %s", name, &type, value); + PRINT_DBG("%s, line %d\n",__FUNCTION__, __LINE__); + PRINT_DBG("name %s, type %c, value %s\n", name, type, value); + + if(type == 'H' || type == 'h'){ + if(check_hex(value) < 0){ + PRINT_ERR("err, has invalid hex\n"); + return; + } + char_to_hex(value, buf); + ret = strlen(value) / 2;//!!!not strlen(buf), because aa00 can be turn to aa. + }else if(type == 'C' || type == 'c'){ + memcpy(buf, value, strlen(value)); + ret = strlen(value); + }else{ + PRINT_ERR("invalid type %c\n", type); + return; + } + //dump_mem(buf, 0, ret); + + ret = write_mi_item(name, buf, ret); + if(ret < 0){ + PRINT_ERR("read data failed\n"); + } +} + +static ssize_t mi_debug_write(struct file *file, const char __user *buf, size_t size, loff_t *ppos) +{ + char cmd[512] = {0}; + char func_name[32] = {0}; + char param[256] = {0}; + + char *cmd_ptr, *param_ptr; + int i, len, flag; + +// printk("%s, line %d\n",__FUNCTION__, __LINE__); + + if(copy_from_user(cmd, buf, size)) + { + PRINT_ERR("%s %d, copy_from_user has wrong\n", __FUNCTION__, __LINE__); + } +// printk("cmd %s\n", cmd); + + for(i = 0; i < size; i++) + { + if(cmd[i] == '\n') + { + cmd[i] = 0; + break; + } + } + + len = strlen(cmd); + flag = 0; + for(i = 0; i < len; i++) + { + if(cmd[i] != ' '){ + flag = 1; + } + else if(flag == 1) + { + memcpy(func_name, cmd, i); + func_name[i] = 0; + break; + } + } + if(i == len) + strcpy(func_name, cmd); + + PRINT_DBG("func_name=%s\n", func_name); + + if(i != len) + { + cmd_ptr = cmd + i + 1; + param_ptr = param; + len = strlen(cmd_ptr); + for(i = 0; i < len; i++) + { + if(cmd_ptr[i] != ' '){ + *param_ptr++ = cmd_ptr[i]; + } + else if(param_ptr > param && *(param_ptr-1) != ' ') + { + *param_ptr++ = ' '; + } + } + *param_ptr = 0; + PRINT_DBG("param=%s\n", param); + } + + for(i = 0; i < sizeof(debug_func_table)/sizeof(struct_debug_func); i++) + { + if(strcmp(func_name, debug_func_table[i].func_name) == 0 ) + { + (debug_func_table[i].func)(param); + break; + } + } + + if(i == sizeof(debug_func_table)/sizeof(struct_debug_func)) + { + PRINT_ERR("can not find function %s\n", func_name); + } + return size; +} + +static const struct file_operations mi_op = { + .write = mi_debug_write, +}; + +int mi_debug_init(void) +{ + PRINT("%s, line %d\n",__FUNCTION__, __LINE__); + dirent = debugfs_create_dir("misc_info", NULL); + file = debugfs_create_file("debug", S_IFREG | S_IRUGO, dirent, NULL, &mi_op); + + return 0; +} + +int mi_debug_exit(void) +{ + PRINT("%s, line %d\n",__FUNCTION__, __LINE__); + debugfs_remove(file); + debugfs_remove(dirent); + return 0; +} + +#endif + diff --git a/drivers/misc/misc-info/misc_info.c b/drivers/misc/misc-info/misc_info.c new file mode 100755 index 0000000..6946f56 --- /dev/null +++ b/drivers/misc/misc-info/misc_info.c @@ -0,0 +1,1106 @@ +/* + * Misc info Access driver + * + * Copyright 2015 Actions Company + * + * Use consistent with the GNU GPL is permitted, + * provided that this copyright notice is + * preserved in its entirety in all copies and derived works. + * + * + * The driver is used to save the important device hardware information, + * ie. Serial No, HDCP Key and etc. + * The misc info area is 1M Byte, start from 4M to 5M in storage like + * NandFlash or e-MMC and etc. + * The driver has 2 copy, one is in kernel, the other is in u-boot. + * + * Author: Alex Sun + * 28 Aug 2015 + */ + +#ifdef OS_LINUX +#include <linux/moduleparam.h> +#include <linux/module.h> +#include <linux/capability.h> +#include <linux/compat.h> +#include <linux/miscdevice.h> +#include <linux/fs.h> +#else +#include <common.h> +#include <errno.h> +#include <asm/arch/owl_afi.h> +#endif + +#include "misc_info.h" + +int read_misc_info(void *buf, unsigned int count); +int write_misc_info(void *buf, unsigned int count); + +#ifdef OS_LINUX +extern int mi_debug_init(void); +extern int mi_debug_exit(void); + +const char *mi_file[4]= +{ + "/dev/nand0", + "/dev/block/nand0", + "/dev/mmcblk0", + "/dev/block/mmcblk0" +}; + +/* + * get checksum on the base of 2 bytes + */ +static unsigned short get_checksum(unsigned short *buf,unsigned int len) +{ + unsigned int loop; + unsigned short sum = 0; + + if(!buf || len == 0) + return 0; + + for(loop = 0; loop <len; loop++){ + sum += buf[loop]; + } + sum ^= (unsigned short)0x55aa; + + return sum; +} + +/* + * read storage + * + * 1.ret < 0 read fail + * 2.ret >= 0 read success, ret is read length + * 3. + */ +int read_storage(void *buf, int start, int size) +{ + int i, ret = -1; + off_t offset; + int count; + mm_segment_t old_fs; + struct file *file = NULL; + + PRINT_DBG("%s, line %d, buf 0x%p, start %d, size %d\n",__FUNCTION__, __LINE__, buf, start, size); + if(!buf || size <= 0){ + PRINT_ERR("invalid param\n"); + goto OUT; + } + old_fs = get_fs(); + set_fs(get_ds()); + + for(i = 0; i < 4; i++){ + file = filp_open(mi_file[i], O_RDONLY, 0); + if (IS_ERR(file) || file->f_op == NULL){ + if(!IS_ERR(file)) + filp_close(file, NULL); + if(i < 3){ + continue; + }else{ + PRINT_ERR("no blk dev\n"); + ret = -EAGAIN; + goto OUT; + } + }else{ + PRINT_DBG("open file %s success\n", mi_file[i]); + break; + } + } + offset = file->f_op->llseek(file, (MISC_INFO_OFFSET + start), 0); + if(offset != (MISC_INFO_OFFSET + start)){ + PRINT_ERR("lseek failed, offset %d\n", (int)offset); + ret = -1; + goto OUT; + } + count = vfs_read(file, (unsigned char *)buf, size, &file->f_pos); + //dump_mem(buf, 0, count); + if(count != size) + { + PRINT_ERR("should read %d, but only read %d!\n", size, count); + } + PRINT_DBG("read count:%d\n", count); + ret = count; + + filp_close(file, NULL); + set_fs(old_fs); + +OUT: + return ret; +} + +/* + * write storage + * + * 1.ret < 0 write fail + * 2.ret >= 0 write success, ret is write length + * 3. + */ +int write_storage(void *buf, int start, int size) +{ + int i, ret = -1; + off_t offset; + int count; + mm_segment_t old_fs; + struct file *file = NULL; + + PRINT_DBG("%s, line %d, buf 0x%p, start %d, size %d\n",__FUNCTION__, __LINE__, buf, start, size); + if(!buf || size <= 0){ + PRINT_ERR("invalid param\n"); + goto OUT; + } + + old_fs = get_fs(); + set_fs(get_ds()); + + for(i = 0; i < 4; i++){ + file = filp_open(mi_file[i], O_RDWR, 0); + if (IS_ERR(file) || file->f_op == NULL || file->f_op->write == NULL){ + if(!IS_ERR(file)) + filp_close(file, NULL); + if(i < 3){ + continue; + }else{ + PRINT_ERR("no blk dev\n"); + ret = -EAGAIN; + goto OUT; + } + }else{ + PRINT_DBG("open file %s success\n", mi_file[i]); + break; + } + } + + offset = file->f_op->llseek(file, (MISC_INFO_OFFSET + start), 0); + if(offset != (MISC_INFO_OFFSET + start)){ + PRINT_ERR("lseek failed, offset %d\n", (int)offset); + ret = -1; + goto OUT; + } + count = file->f_op->write(file, (unsigned char *)buf, size, &file->f_pos); + //dump_mem(buf, 0, count); + if(count != size) + { + PRINT_ERR("should write %d, but only write %d!\n", size, count); + } + PRINT_DBG("write count:%d\n", count); + ret = count; + + filp_close(file, NULL); + set_fs(old_fs); + +OUT: + return ret; +} + +#else + +#define BLOCK_SIZE 512 + +extern int owl_get_boot_dev(void); +extern int LDL_DeviceOpReadSectors(unsigned int start, unsigned int nsector, void *buf, int diskNo); +extern int LDL_DeviceOpWriteSectors(unsigned int start, unsigned int nsector, void *buf, int diskNo); +extern ulong mmc_bread(int dev_num, lbaint_t start, lbaint_t blkcnt, void *dst); +extern ulong mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt, const void *src); + +static int blk_read(void *buf, unsigned int start, unsigned int blkcnt) +{ + int ret = -1; + + ret = owl_get_boot_dev(); + if(ret == OWL_BOOTDEV_NAND){ +// ret = LDL_DeviceOpReadSectors(start, blkcnt, buf, 0); + }else{ + if(ret == OWL_BOOTDEV_SD0) + ret = mmc_bread(0, start, blkcnt, buf); + else if(ret == OWL_BOOTDEV_SD2) + ret = mmc_bread(1, start, blkcnt, buf); + else + ret = -1; + if(ret != blkcnt) + ret = -1; + else + ret = 0; + } + return ret; +} + +static int blk_write(void *buf, unsigned int start, unsigned int blkcnt) +{ + int ret = -1; + + ret = owl_get_boot_dev(); + if(ret == OWL_BOOTDEV_NAND){ +// ret = LDL_DeviceOpWriteSectors(start, blkcnt, buf, 0); + }else{ + if(ret == OWL_BOOTDEV_SD0) + ret = mmc_bwrite(0, start, blkcnt, buf); + else if(ret == OWL_BOOTDEV_SD2) + ret = mmc_bwrite(1, start, blkcnt, buf); + else + ret = -1; + if(ret != blkcnt) + ret = -1; + else + ret = 0; + } + return ret; +} + +/* + * read storage + * + * 1.ret < 0 read fail + * 2.ret >= 0 read success, ret is read length + * 3. + */ +int read_storage(void *buf, int start, int size) +{ + int start_blk, start_in_blk, count; + char *blk_buf; + int ret = size; + + PRINT_DBG("%s, line %d, buf 0x%p, start %d, size %d\n",__FUNCTION__, __LINE__, buf, start, size); + + if(!buf || size <= 0){ + PRINT_ERR("invalid param\n"); + ret = -1; + goto OUT_NULL; + } + + blk_buf = MALLOC(BLOCK_SIZE); + if(!blk_buf){ + PRINT_ERR("MALLOC FAILED\n"); + ret = -ENOMEM; + goto OUT_NULL; + } + memset(blk_buf, 0, BLOCK_SIZE); + + if(start % BLOCK_SIZE != 0){ + start_in_blk = (MISC_INFO_OFFSET + start) % BLOCK_SIZE; + start_blk = (MISC_INFO_OFFSET + start) / BLOCK_SIZE;//from sector 0 + if(blk_read(blk_buf, start_blk, 1) < 0){ + PRINT_ERR("blk_read failed, start blk %d, blkcnt 1\n", start_blk); + ret = -1; + goto OUT_FAILED; + } + count = size > (BLOCK_SIZE - start_in_blk) ? (BLOCK_SIZE - start_in_blk) : size; + memcpy(buf, blk_buf + start_in_blk, count); + buf += count; + start += count; + size -= count; + } + while(size > BLOCK_SIZE){ + start_blk = (MISC_INFO_OFFSET + start) / BLOCK_SIZE;//from sector 0 + if(blk_read(blk_buf, start_blk, 1) < 0){ + PRINT_ERR("blk_read failed, start blk %d, blkcnt 1\n", start_blk); + ret = -1; + goto OUT_FAILED; + } + memcpy(buf, blk_buf, BLOCK_SIZE); + buf += BLOCK_SIZE; + start += BLOCK_SIZE; + size -= BLOCK_SIZE; + } + if(size > 0){ + start_blk = (MISC_INFO_OFFSET + start) / BLOCK_SIZE;//from sector 0 + if(blk_read(blk_buf, start_blk, 1) < 0){ + PRINT_ERR("blk_read failed, start blk %d, blkcnt 1\n", start_blk); + ret = -1; + goto OUT_FAILED; + } + memcpy(buf, blk_buf, size); + } + +OUT_FAILED: + if(blk_buf){ + FREE(blk_buf); + blk_buf = NULL; + } +OUT_NULL: + return ret; +} +/* + * write storage + * + * 1.ret < 0 write fail + * 2.ret >= 0 write success, ret is write length + * 3. + */ +int write_storage(void *buf, int start, int size) +{ + int start_blk, start_in_blk, count; + char *blk_buf; + int ret = size; + + PRINT_DBG("%s, line %d, buf 0x%p, start %d, size %d\n",__FUNCTION__, __LINE__, buf, start, size); + + if(!buf || size <= 0){ + PRINT_ERR("invalid param\n"); + ret = -1; + goto OUT_NULL; + } + + blk_buf = MALLOC(BLOCK_SIZE); + if(!blk_buf){ + PRINT_ERR("MALLOC FAILED\n"); + ret = -ENOMEM; + goto OUT_NULL; + } + memset(blk_buf, 0, BLOCK_SIZE); + + if(start % BLOCK_SIZE != 0){ + start_in_blk = (MISC_INFO_OFFSET + start) % BLOCK_SIZE; + start_blk = (MISC_INFO_OFFSET + start) / BLOCK_SIZE;//from sector 0 + if(blk_read(blk_buf, start_blk, 1) < 0){ + PRINT_ERR("blk_read failed, start blk %d, blkcnt 1\n", start_blk); + ret = -1; + goto OUT_FAILED; + } + count = size > (BLOCK_SIZE - start_in_blk) ? (BLOCK_SIZE - start_in_blk) : size; + memcpy(blk_buf + start_in_blk, buf, count); + if(blk_write(blk_buf, start_blk, 1) < 0){ + PRINT_ERR("blk_write failed, start blk %d, blkcnt 1\n", start_blk); + ret = -1; + goto OUT_FAILED; + } + buf += count; + start += count; + size -= count; + } + while(size > BLOCK_SIZE){ + start_blk = (MISC_INFO_OFFSET + start) / BLOCK_SIZE;//from sector 0 + memcpy(blk_buf, buf, BLOCK_SIZE); + if(blk_write(blk_buf, start_blk, 1) < 0){ + PRINT_ERR("blk_write failed, start blk %d, blkcnt 1\n", start_blk); + ret = -1; + goto OUT_FAILED; + } + buf += BLOCK_SIZE; + start += BLOCK_SIZE; + size -= BLOCK_SIZE; + } + if(size > 0){ + start_blk = (MISC_INFO_OFFSET + start) / BLOCK_SIZE;//from sector 0 + if(blk_read(blk_buf, start_blk, 1) < 0){ + PRINT_ERR("blk_read failed, start blk %d, blkcnt 1\n", start_blk); + ret = -1; + goto OUT_FAILED; + } + memcpy(blk_buf, buf, size); + if(blk_write(blk_buf, start_blk, 1) < 0){ + PRINT_ERR("blk_write failed, start blk %d, blkcnt 1\n", start_blk); + ret = -1; + goto OUT_FAILED; + } + } + +OUT_FAILED: + if(blk_buf){ + FREE(blk_buf); + blk_buf = NULL; + } +OUT_NULL: + return ret; +} +#endif + + +/* + * read misc info head + * + * 1.ret < 0 read fail + * 2.ret == 0 read data invalid + * 3.ret > 0 read success + */ +int read_mi_head(misc_info_head_t * head) +{ + int ret, head_length; + misc_info_head_t *tmp_head = NULL; + char *head_buf = NULL; + + PRINT_DBG("%s, line %d\n",__func__, __LINE__); + head_length = sizeof(misc_info_head_t); + head_buf = MALLOC(head_length); + if(!head_buf){ + PRINT_ERR("MALLOC head failed\n"); + ret = -ENOMEM; + goto OUT_NULL; + } + memset(head_buf, 0, head_length); + + ret = read_storage(head_buf, 0, head_length); + if(ret < 0){ + PRINT_ERR("read MiscInfoHeader failed\n"); + goto OUT_FAILED; + } + if(ret != head_length){ + PRINT_ERR("read_storage return %d, but should be %d\n", ret, head_length); + goto OUT_FAILED; + } + tmp_head = (misc_info_head_t *)head_buf; + if(tmp_head->magic != MISC_INFO_MAGIC || tmp_head->length > MISC_INFO_MAX_SIZE + || tmp_head->item_num > MISC_INFO_MAX_ITEM_NUM){ + PRINT_ERR("%s, line %d, magic 0x%x, length %d, item num %d\n", __FUNCTION__, __LINE__, + tmp_head->magic, tmp_head->length, tmp_head->item_num); + ret = 0; + goto OUT_FAILED; + } + memcpy(head, (misc_info_head_t *)head_buf, head_length); + ret = head_length; + if(debug_enable) + dump_mem(head, 0, head_length); + +OUT_FAILED: + if(head_buf){ + FREE(head_buf); + head_buf = NULL; + } +OUT_NULL: + return ret; +} + +/* + * read misc info item + * + * 1.ret < 0 read fail + * 2.ret > 0 read success, ret is read length + * + */ +int read_mi_item(char *name, void *buf, unsigned int count) +{ + int ret = -1, item; + unsigned short chksum_calc, chksum_rec; + misc_info_head_t *head = NULL; + unsigned char *data = NULL; + + PRINT_DBG("%s, line %d, buf 0x%p, count %d\n", __func__, __LINE__, buf, count); + if(!name || !buf || count == 0){ + PRINT_ERR("%s, line %d, err\n", __func__, __LINE__); + goto OUT_NULL; + } + + head = MALLOC(sizeof(misc_info_head_t)); + if(!head){ + PRINT_ERR("MALLOC head failed\n"); + ret = -ENOMEM; + goto OUT_NULL; + } + memset(head, 0, sizeof(misc_info_head_t)); + + ret = read_mi_head(head); + if(ret < 0){ + PRINT_ERR("read Head failed\n"); + goto OUT_FAILED; + }else if(ret == 0){ + PRINT_ERR("read Head null\n"); + ret = -1; + goto OUT_FAILED; + } + PRINT_DBG("%s, line %d, misc info: length %d, item num %d\n", __func__, __LINE__, head->length, head->item_num); + + if(strlen(name) > sizeof(head->item_head[0].name)){ + PRINT_ERR("invalid name, too large\n"); + goto OUT_FAILED; + } + for(item = 0; item < head->item_num; item++) + { + if(memcmp(name, head->item_head[item].name, strlen(name)) == 0){ + break; + } + } + if(item == head->item_num){ + PRINT_ERR("can not find %s\n", name); + goto OUT_FAILED; + } + PRINT_DBG("%s, line %d, name %s, size %d, offset %d, checksum 0x%x\n", __func__, __LINE__, + head->item_head[item].name, head->item_head[item].size, + head->item_head[item].offset, head->item_head[item].chk_sum); + + data = MALLOC(head->item_head[item].size); + if(!data){ + PRINT_ERR("MALLOC head failed\n"); + ret = -ENOMEM; + goto OUT_FAILED; + } + memset(data, 0, head->item_head[item].size); + ret = read_storage(data, head->item_head[item].offset, head->item_head[item].size); + if(ret < 0){ + PRINT_ERR("read item %s data failed\n", name); + goto OUT_FAILED; + } + if(debug_enable) + dump_mem(data, 0, head->item_head[item].size); + chksum_rec = head->item_head[item].chk_sum; + chksum_calc = get_checksum((unsigned short *)data, head->item_head[item].size/2); + if(chksum_rec != chksum_calc) + { + PRINT_ERR("get %s chksum failed, calc:0x%x rec:0x%x\n", name, chksum_calc, chksum_rec); + //dump_mem(data, 0, head->item_head[item].size); + ret = -1; + goto OUT_INVALID; + } + ret = (count > head->item_head[item].size) ? head->item_head[item].size : count; + memcpy(buf, data, ret); + PRINT("%s, line %d, success\n", __func__, __LINE__); + +OUT_INVALID: + if(data){ + FREE(data); + data = NULL; + } +OUT_FAILED: + if(head){ + FREE(head); + head = NULL; + } +OUT_NULL: + return ret; +} + +/* + * write misc info item + * + * 1.ret < 0 write fail + * 2.ret >= 0 write success, ret is write length + * + */ +int write_mi_item(char *name, void *buf, unsigned int count) +{ + int ret = -1, pack_len; + usb_packet_t *packet = NULL; + + PRINT_DBG("%s, line %d, buf 0x%p, count %d\n", __func__, __LINE__, buf, count); + if(!name || !buf || count == 0){ + PRINT_ERR("%s, line %d, err\n", __func__, __LINE__); + goto OUT_NULL; + } + pack_len = sizeof(int) + sizeof(packet_item_t) + count; + + packet = MALLOC(pack_len); + if(!packet){ + PRINT_ERR("MALLOC packet failed\n"); + ret = -ENOMEM; + goto OUT_NULL; + } + memset(packet, 0, pack_len); + + packet->length = pack_len; + packet->item[0].magic = MISC_INFO_MAGIC;// FIXME + if(strlen(name) > sizeof(packet->item[0].name)){ + PRINT_ERR("invalid name, too large, must < 7 Byte\n"); + goto OUT_FAILED; + } + memcpy(packet->item[0].name, name, strlen(name)); + packet->item[0].size = count; + memcpy(packet->item[0].data, buf, count); + + ret = write_misc_info(packet, packet->length); + if(ret != packet->length){ + PRINT_ERR("write item failed, ret %d\n", ret); + } + PRINT("%s, line %d, success\n", __func__, __LINE__); + +OUT_FAILED: + if(packet){ + FREE(packet); + packet = NULL; + } +OUT_NULL: + return ret; +} + +/* + * print all item info + * + */ +void print_mi_items(misc_info_head_t * head) +{ + int item; + if(!head){ + PRINT_ERR("%s, line %d, buf is NULL\n", __func__, __LINE__); + return; + } + + for(item = 0; item < head->item_num; item++){ + PRINT("[%02d] name:%s size:%d\n", item, head->item_head[item].name, + head->item_head[item].size); + } +} + +/* + * get item size + * + */ +int get_item_size(misc_info_head_t * head, char *name) +{ + int ret = -1, item; + if(!head || !name){ + PRINT_ERR("%s, line %d, buf is NULL\n", __func__, __LINE__); + return ret; + } + + if(strlen(name) > sizeof(head->item_head[0].name)){ + PRINT_ERR("invalid name, too large, must < 7 Byte\n"); + return ret; + } + for(item = 0; item < head->item_num; item++){ + if(memcmp(head->item_head[item].name, name, strlen(name)) == 0){ + return head->item_head[item].size; + } + } + return ret; +} + +/* + * read misc info + * + * 1.the data is read to pc tool through USB. + * 2. + */ +int read_misc_info(void *buf, unsigned int count) +{ + int ret = -1, i; + int head_length, data_length, pack_length, data_offset; + unsigned short chksum_calc, chksum_rec; + misc_info_head_t *head = NULL; + unsigned char *data = NULL; + usb_packet_t *packet = NULL; + packet_item_t *item = NULL; + + PRINT_DBG("%s, line %d, buf 0x%p, count %d\n", __func__, __LINE__, buf, count); + + if(!buf){ + PRINT_ERR("%s, line %d, buf is NULL\n", __func__, __LINE__); + return ret; + } + + head_length = sizeof(misc_info_head_t); + head = MALLOC(head_length); + if(!head){ + PRINT_ERR("MALLOC head failed\n"); + ret = -ENOMEM; + goto MALLOC_FAILED; + } + memset(head, 0, head_length); + + ret = read_mi_head(head); + if(ret < 0){ + PRINT_ERR("read Head failed\n"); + ret = -1; + goto READ_HEAD_FAILED; + }else if(ret == 0){ + memset(head, 0, head_length); + }else{ + PRINT_DBG("%s, line %d, misc info: length %d, item num %d\n", __func__, __LINE__, head->length, head->item_num); + data_length = head->length - head_length; + data = MALLOC(data_length); + if(!data){ + PRINT_ERR("MALLOC data failed\n"); + ret = -ENOMEM; + goto READ_HEAD_FAILED; + } + memset(data, 0, data_length); + + if(read_storage(data, head_length, data_length) < 0){ + PRINT_ERR("read data failed\n"); + goto READ_DATA_FAILED; + } + if(debug_enable) + dump_mem(data, 0, data_length); + } + + pack_length = sizeof(int); + for(i=0; i<head->item_num; i++) + { + pack_length += sizeof(packet_item_t) + head->item_head[i].size;//sizeof(packet_item_t)==4+8+4? + } + PRINT_DBG("%s, line %d, packet length %d\n", __func__, __LINE__, pack_length); + + packet = (usb_packet_t *) MALLOC(pack_length); + if(!packet){ + PRINT_ERR("MALLOC packet failed\n"); + ret = -ENOMEM; + goto READ_DATA_FAILED; + } + memset(packet, 0, pack_length); + item = packet->item; + + packet->length = pack_length; + for(i=0; i<head->item_num; i++){ + item->magic = head->item_head[i].magic; + memcpy(item->name, head->item_head[i].name, strlen(head->item_head[i].name)); + item->size = head->item_head[i].size; + data_offset = head->item_head[i].offset - head_length; + memcpy(item->data, data + data_offset, item->size); + + chksum_rec = head->item_head[i].chk_sum; + chksum_calc = get_checksum((unsigned short *)item->data, item->size/2); + if(chksum_rec != chksum_calc){ + PRINT_ERR("get %s chksum failed calc:%x rec:%x\n", item->name, chksum_calc, chksum_rec); + //dump_mem(item->data, 0, item->size); + } + item = (packet_item_t *)((char *)item + sizeof(packet_item_t) + item->size); + } + dump_mem(packet, 0, packet->length); + + ret = (count > packet->length) ? packet->length : count; + memcpy(buf, packet, ret); + PRINT("%s, line %d, success\n", __func__, __LINE__); + + if(packet){ + FREE(packet); + packet = NULL; + } +READ_DATA_FAILED: + if(data){ + FREE(data); + data = NULL; + } +READ_HEAD_FAILED: + if(head){ + FREE(head); + head = NULL; + } +MALLOC_FAILED: + return ret; +} + +/* + * write misc info + * + * 1.the data is written from pc tool through USB. + * 2.if the data is incomplete, write part of it. + * 3.item will be merged, item with same name will override the old. + */ +int write_misc_info(void *buf, unsigned int count) +{ + int ret = -1, offset = 0, item_size, head_length; + int index = 0, pack_item_num, pack_pos, i, j; + usb_packet_t *packet = NULL; + packet_item_t *pack_item = NULL; + misc_info_t *old_misc = NULL, *new_misc = NULL; + misc_info_head_t *new_head = NULL, *old_head = NULL; + unsigned char *new_data = NULL, *old_data = NULL; + + PRINT_DBG("%s, line %d, buf 0x%p, count %d\n", __FUNCTION__, __LINE__, buf, count); + if(buf == NULL){ + PRINT_ERR("%s, line %d, buf is null\n",__FUNCTION__, __LINE__); + return -1; + } + if(debug_enable) + dump_mem(buf, 0, count); + + packet = (usb_packet_t *)buf; + + if(count <= sizeof(int) + sizeof(packet_item_t)){ + return 0; + } + + old_misc = (misc_info_t *) MALLOC(MISC_INFO_MAX_SIZE); + if(!old_misc){ + PRINT_ERR("MALLOC old_misc failed\n"); + ret = -ENOMEM; + goto MALLOC_OLD_MISC_FAILED; + } + new_misc = (misc_info_t *) MALLOC(MISC_INFO_MAX_SIZE); + if(!new_misc){ + PRINT_ERR("MALLOC new_misc failed\n"); + ret = -ENOMEM; + goto MALLOC_NEW_MISC_FAILED; + } + memset(old_misc, 0, MISC_INFO_MAX_SIZE); + memset(new_misc, 0, MISC_INFO_MAX_SIZE); + + head_length = sizeof(misc_info_head_t); + new_head = &new_misc->head; + new_data = (char *)new_misc + head_length;////!!!!(char *) is must, so easy to forget + PRINT_DBG("new_head 0x%p, new_data 0x%p\n",new_head,new_data); + + pack_item = packet->item; + pack_pos = sizeof(packet->length); + PRINT_DBG("%s, line %d, length %d\n", __FUNCTION__, __LINE__, packet->length); + + //parse packet + while(pack_pos < packet->length) + { + //check packet data completable + if(count < pack_pos + sizeof(packet_item_t) + pack_item->size){ + PRINT_ERR("%s, line %d, pack_pos %d, sizeof(packet_item_t) %d, pack_item->size %d\n", + __FUNCTION__, __LINE__, pack_pos, sizeof(packet_item_t), pack_item->size); + break; + } + new_head->item_head[index].magic = pack_item->magic; + memcpy(new_head->item_head[index].name, pack_item->name, strlen(pack_item->name)); + new_head->item_head[index].size = pack_item->size; + new_head->item_head[index].offset = head_length + offset;//offset is from begining + offset += new_head->item_head[index].size; + new_head->item_head[index].chk_sum = get_checksum((unsigned short *)pack_item->data, pack_item->size/2); + //copy + memcpy(new_data, pack_item->data, new_head->item_head[index].size); + new_data += new_head->item_head[index].size; + + item_size = sizeof(packet_item_t) + pack_item->size; + pack_pos += item_size; + pack_item = (packet_item_t *)((unsigned char *)pack_item + item_size); + index++; + } + ret = pack_pos; + PRINT_DBG("pack_pos %d\n", pack_pos); + pack_item_num = index; + + //read misc info to merge with packet data + if(read_storage((unsigned char*)old_misc, 0, MISC_INFO_MAX_SIZE) < 0){ + PRINT_ERR("readMiscInfo failed\n"); + ret = -1; + goto OUT_END; + } + old_head = &old_misc->head; + old_data = (char *)old_misc + head_length;////!!!!(char *) is must, so easy to forget + if(old_head->magic != MISC_INFO_MAGIC || old_head->length > MISC_INFO_MAX_SIZE + || old_head->item_num > MISC_INFO_MAX_ITEM_NUM){ + PRINT_ERR("%s, line %d, magic 0x%x, length %d, item num %d\n", __FUNCTION__, __LINE__, + old_head->magic, old_head->length, old_head->item_num); + PRINT_ERR("invalid old misc info\n"); + }else{ + PRINT_DBG("%s, line %d, old misc info: length %d, item num %d\n", __func__, __LINE__, old_head->length, old_head->item_num); + for(i=0; i<old_head->item_num; i++) + { + for(j=0; j<pack_item_num; j++) + { + if(memcmp(old_head->item_head[i].name, new_head->item_head[j].name, sizeof(old_head->item_head[i].name)) == 0){ + break; + } + } + if(j < pack_item_num) + continue; + + memcpy(&new_head->item_head[index], &old_head->item_head[i], sizeof(item_head_t)); + new_head->item_head[index].offset = head_length + offset; + offset += new_head->item_head[index].size; + + //copy data + //!!!old_misc->data is wrong + old_data = (char *)old_misc + old_head->item_head[i].offset; + memcpy(new_data, old_data, old_head->item_head[i].size); + new_data += new_head->item_head[index].size; + + index++; + } + } + + //build head + new_head->magic = MISC_INFO_MAGIC; + new_head->item_num = index; + new_head->length = head_length; + for(i=0; i<new_head->item_num; i++){ + new_head->length += new_head->item_head[i].size; + } + PRINT_DBG("%s, line %d, new misc info: length %d, item num %d\n", __func__, __LINE__, new_head->length, new_head->item_num); + + //check total length + if(new_head->length > MISC_INFO_MAX_SIZE){ + PRINT_ERR("new misc info length > MISC_INFO_MAX_SIZE, do nothing\n"); + dump_mem(new_misc, 0, new_head->length); + ret = -1; + goto OUT_END; + } + + if(debug_enable) + dump_mem(new_misc, 0, new_head->length); + + //write + if(write_storage(new_misc, 0, new_head->length) < 0){ + PRINT_ERR("%s, line %d, write_storage failed\n", __FUNCTION__, __LINE__); + ret = -1; + } + PRINT("%s, line %d, success\n", __func__, __LINE__); + +OUT_END: +MALLOC_NEW_MISC_FAILED: + if(new_misc){ + FREE(new_misc); + new_misc = NULL; + } +MALLOC_OLD_MISC_FAILED: + if(old_misc){ + FREE(old_misc); + old_misc = NULL; + } + + return ret; +} + +int format_misc_info(void) +{ + unsigned char *buf = NULL; + + PRINT_DBG("%s, line %d\n",__func__, __LINE__); + buf = MALLOC(MISC_INFO_MAX_SIZE); + if(!buf){ + PRINT_ERR("MALLOC buf failed\n"); + return -ENOMEM; + } + memset(buf, 0, MISC_INFO_MAX_SIZE); + + if(write_storage(buf, 0, MISC_INFO_MAX_SIZE) < 0){ + PRINT_ERR("%s, line %d, write_storage failed\n", __func__, __LINE__); + return -1; + } + + if(buf){ + FREE(buf); + buf = NULL; + } + PRINT("%s, line %d, success\n", __func__, __LINE__); + + return 0; +} + +#ifdef OS_LINUX + +static int mi_open(struct inode *inode, struct file *filp) +{ + if(nonseekable_open(inode, filp)) + { + PRINT_ERR ("misc nonseekable_open failed\n"); + return -1; + } + return 0; +} + +static int mi_release(struct inode *inode, struct file *filp) +{ + return 0; +} + +static long mi_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + int ret = -1; + ioctl_item_t item; + char *buf = NULL; + + switch(cmd){ + case GET_ITEM_DATA: + if(copy_from_user(&item, (void*)arg, sizeof(ioctl_item_t)) != 0){ + PRINT_ERR("copy_from_user failed\n"); + goto OUT_NULL; + } + PRINT_DBG("item.name %s, len %d\n", item.name, strlen(item.name)); + PRINT_DBG("item.size %d\n", item.size); + PRINT_DBG("item.data 0x%p\n", item.data); + + buf = MALLOC(item.size); + if(!buf){ + PRINT_ERR("MALLOC buf failed\n"); + ret = -ENOMEM; + goto OUT_NULL; + } + ret = read_mi_item(item.name, buf, item.size); + if(ret <= 0){ + PRINT_ERR("read_mi_item failed\n"); + goto OUT_FAILED; + } + PRINT_DBG("read_mi_item ret %d\n", ret); + if(debug_enable) + dump_mem(buf, 0, ret); + if(copy_to_user(item.data, buf, ret) != 0){ + PRINT_ERR("copy_to_user failed\n"); + ret = -1; + goto OUT_FAILED; + } + break; + case SET_ITEM_DATA: + if(copy_from_user(&item, (void*)arg, sizeof(ioctl_item_t)) != 0){ + PRINT_ERR("copy_from_user failed\n"); + goto OUT_NULL; + } + PRINT_DBG("item.name %s, len %d\n", item.name, strlen(item.name)); + PRINT_DBG("item.size %d\n", item.size); + PRINT_DBG("item.data 0x%p\n", item.data); + + buf = MALLOC(item.size); + if(!buf){ + PRINT_ERR("MALLOC buf failed\n"); + ret = -ENOMEM; + goto OUT_NULL; + } + if(copy_from_user(buf, item.data, item.size) != 0){ + PRINT_ERR("copy_from_user failed\n"); + ret = -1; + goto OUT_FAILED; + } + if(debug_enable) + dump_mem(buf, 0, item.size); + ret = write_mi_item(item.name, buf, item.size); + if(ret < 0){ + PRINT_ERR("write_mi_item failed\n"); + goto OUT_FAILED; + } + break; + case FORMAT_MISC_INFO: + if(format_misc_info() < 0){ + PRINT_ERR("format misc info failed\n"); + ret = -1; + } + break; + } + return ret; + +OUT_FAILED: + if(buf){ + FREE(buf); + buf = NULL; + } +OUT_NULL: + return ret; +} + +static struct file_operations mi_fops = +{ + .owner = THIS_MODULE, + .unlocked_ioctl = mi_ioctl, + .open = mi_open, + .release = mi_release +}; + +static struct miscdevice mi_dev = { + .minor = MISC_DYNAMIC_MINOR, + .name = "misc_info", + .fops = &mi_fops, +}; + +static int __init misc_info_init(void) +{ + PRINT("%s, line %d\n", __FUNCTION__, __LINE__); + + if(misc_register(&mi_dev) < 0) + return -1; + mi_debug_init(); + + return 0; +} + +static void __exit misc_info_exit(void) +{ + PRINT("%s, line %d\n", __FUNCTION__, __LINE__); + + misc_deregister(&mi_dev); + mi_debug_exit(); + return; +} + +module_init(misc_info_init); +module_exit(misc_info_exit); + +EXPORT_SYMBOL_GPL(read_misc_info); +EXPORT_SYMBOL_GPL(write_misc_info); +EXPORT_SYMBOL_GPL(format_misc_info); +EXPORT_SYMBOL_GPL(read_mi_item); +EXPORT_SYMBOL_GPL(write_mi_item); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Alex.Sun"); +MODULE_DESCRIPTION("MISC INFO access driver"); + +#endif diff --git a/drivers/misc/misc-info/misc_info.h b/drivers/misc/misc-info/misc_info.h new file mode 100755 index 0000000..a07954e --- /dev/null +++ b/drivers/misc/misc-info/misc_info.h @@ -0,0 +1,110 @@ +#ifndef __MISC_INFO_H_ +#define __MISC_INFO_H_ + + + +#ifdef OS_LINUX +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/errno.h> +#include <asm/uaccess.h> + +#define PRINT(x...) printk(x) +#define PRINT_DBG(x...) if(debug_enable)printk(x) +#define PRINT_ERR(x...) printk(KERN_ERR x) +#define INFO(x...) +#define MALLOC(x) kmalloc(x, GFP_KERNEL) +#define FREE(x) kfree(x) + +#else +#define PRINT(x...) printf(x) +#define PRINT_DBG(x...) if(debug_enable)printf(x) +#define PRINT_ERR(x...) printf(x) +#define INFO(x...) +#define MALLOC(x) malloc(x) +#define FREE(x) free(x) +#endif + +extern void *malloc(unsigned int size); +extern void free(void *ptr); +extern int debug_enable; + +#define MISC_INFO_MAGIC 0x55aa55aa +#define MISC_INFO_OFFSET 4*1024*1024 +#define MISC_INFO_MAX_SIZE 1024*1024 +#define MISC_INFO_MAX_ITEM_NUM 16 +#define MISC_INFO_HEAD_ALIGN 1024 + +#define GET_ITEM_DATA 0 +#define SET_ITEM_DATA 1 +#define FORMAT_MISC_INFO 2 + +typedef struct +{ + unsigned char name[8]; + unsigned int size; + unsigned char *data; +}ioctl_item_t; + +typedef struct +{ + unsigned int magic; + unsigned char name[8]; + unsigned int size; + unsigned char data[]; +}packet_item_t; + +typedef struct +{ + unsigned int length;//packet length + packet_item_t item[]; +}usb_packet_t; + + +typedef struct +{ + unsigned char name[8]; + unsigned int magic; + unsigned short size; //size of item data + unsigned short offset; //offset from the beginning + unsigned short chk_sum; + unsigned char reserved[16]; +}__attribute__((aligned(4)))item_head_t; + +typedef struct +{ + unsigned int magic; + unsigned short length; //total length of misc info + unsigned short item_num; + unsigned char reserved[8]; + item_head_t item_head[MISC_INFO_MAX_ITEM_NUM]; +}__attribute__((aligned(MISC_INFO_HEAD_ALIGN)))misc_info_head_t; + +typedef struct +{ + misc_info_head_t head; + unsigned char *data; +}misc_info_t; + +static void dump_mem(void *buf, unsigned int start, unsigned int size) +{ + unsigned char *ptr; + int i; + + if(!buf){ + PRINT_ERR("%s, buf is null\n", __FUNCTION__); + return; + } + + ptr = (unsigned char *)buf + start; + for(i = 0; i < size; i++){ + if(i % 16 == 0) + PRINT("%d: ", start + i); + PRINT("%.2x ", *ptr++); + if(i % 16 == 15) + PRINT("\n"); + } + PRINT("\n"); +} + +#endif -- 2.7.4 -- _______________________________________________ linux-yocto mailing list linux-yocto@yoctoproject.org https://lists.yoctoproject.org/listinfo/linux-yocto