From fbcaf3da81e6b416c76d12fdb96e20929b5a37cf Mon Sep 17 00:00:00 2001 From: ggow Date: Thu, 23 May 2019 15:17:28 +0100 Subject: [PATCH] lab126: Add idme driver --- arch/arm/configs/austin_defconfig | 2 + arch/arm/configs/ford_defconfig | 2 + arch/arm/include/uapi/asm/setup.h | 11 ++ arch/arm/kernel/atags_parse.c | 15 ++ drivers/staging/Kconfig | 2 + drivers/staging/Makefile | 1 + drivers/staging/amazon/Kconfig | 21 +++ drivers/staging/amazon/Makefile | 1 + drivers/staging/amazon/idme.c | 270 ++++++++++++++++++++++++++++++ 9 files changed, 325 insertions(+) create mode 100644 drivers/staging/amazon/Kconfig create mode 100644 drivers/staging/amazon/Makefile create mode 100644 drivers/staging/amazon/idme.c diff --git a/arch/arm/configs/austin_defconfig b/arch/arm/configs/austin_defconfig index dce5fc87120..04810131d30 100644 --- a/arch/arm/configs/austin_defconfig +++ b/arch/arm/configs/austin_defconfig @@ -3312,5 +3312,7 @@ CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y # CONFIG_CORDIC is not set # CONFIG_DDR is not set # CONFIG_VIRTUALIZATION is not set +CONFIG_AMAZON=y +CONFIG_IDME=y CONFIG_MTK_WD_KICKER=y CONFIG_MTK_HALL_SENSOR=y diff --git a/arch/arm/configs/ford_defconfig b/arch/arm/configs/ford_defconfig index a5f404a4a71..14b9b5bc148 100644 --- a/arch/arm/configs/ford_defconfig +++ b/arch/arm/configs/ford_defconfig @@ -3303,4 +3303,6 @@ CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y # CONFIG_CORDIC is not set # CONFIG_DDR is not set # CONFIG_VIRTUALIZATION is not set +CONFIG_AMAZON=y +CONFIG_IDME=y CONFIG_MTK_WD_KICKER=y diff --git a/arch/arm/include/uapi/asm/setup.h b/arch/arm/include/uapi/asm/setup.h index ab3e3fe5f2d..6a23da41525 100644 --- a/arch/arm/include/uapi/asm/setup.h +++ b/arch/arm/include/uapi/asm/setup.h @@ -200,6 +200,14 @@ typedef struct { mem_desc_t rank_info[4]; } dram_info_t; +#ifdef CONFIG_IDME +#define ATAG_IDME 0x54410010 +#define ATAG_IDME_SIZE 8736 +struct tag_idme { + u8 idme[ATAG_IDME_SIZE+1]; +}; +#endif + struct tag { struct tag_header hdr; union { @@ -213,6 +221,9 @@ struct tag { struct tag_revision revision; struct tag_videolfb videolfb; struct tag_cmdline cmdline; +#ifdef CONFIG_IDME + struct tag_idme idme; +#endif /* * Acorn specific diff --git a/arch/arm/kernel/atags_parse.c b/arch/arm/kernel/atags_parse.c index 883e249eb1e..526d2c10589 100644 --- a/arch/arm/kernel/atags_parse.c +++ b/arch/arm/kernel/atags_parse.c @@ -36,6 +36,12 @@ char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; #define MEM_SIZE (16*1024*1024) #endif +#ifdef CONFIG_IDME +#define IDME_ATAG_SIZE 8736 +unsigned char system_idme[IDME_ATAG_SIZE+1]; +EXPORT_SYMBOL(system_idme); +#endif + static struct { struct tag_header hdr1; struct tag_core core; @@ -139,6 +145,15 @@ static int __init parse_tag_cmdline(const struct tag *tag) __tagtable(ATAG_CMDLINE, parse_tag_cmdline); +#ifdef CONFIG_IDME +static int __init parse_tag_idme(const struct tag *tag) +{ + memset(system_idme, 0, IDME_ATAG_SIZE+1); + memcpy(system_idme, tag->u.idme.idme, IDME_ATAG_SIZE); /* idme item */ +} +__tagtable(ATAG_IDME, parse_tag_idme); +#endif + /* * Scan the tag table for this tag, and call its parse function. * The tag table is built by the linker from all the __tagtable diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index aefe820a800..a8c969b47c2 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -140,4 +140,6 @@ source "drivers/staging/netlogic/Kconfig" source "drivers/staging/dwc2/Kconfig" +source "drivers/staging/amazon/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 415772ea306..f5505a6b2a6 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -62,3 +62,4 @@ obj-$(CONFIG_FIREWIRE_SERIAL) += fwserial/ obj-$(CONFIG_ZCACHE) += zcache/ obj-$(CONFIG_GOLDFISH) += goldfish/ obj-$(CONFIG_USB_DWC2) += dwc2/ +obj-$(CONFIG_AMAZON) += amazon/ diff --git a/drivers/staging/amazon/Kconfig b/drivers/staging/amazon/Kconfig new file mode 100644 index 00000000000..6905787c267 --- /dev/null +++ b/drivers/staging/amazon/Kconfig @@ -0,0 +1,21 @@ +menu "AMAZON" + +config AMAZON + bool "Amazon Drivers" + default N + ---help--- + Enable support for various drivers needed on the Amazon hardware platform + +if AMAZON + +config IDME + bool "IDME support" + depends on PROC_FS + default N + help + Select Y here to enable IDME support to read the data + via userspace (i.e. /proc/idme/* entries) + +endif # if AMAZON + +endmenu diff --git a/drivers/staging/amazon/Makefile b/drivers/staging/amazon/Makefile new file mode 100644 index 00000000000..eb2764c9c66 --- /dev/null +++ b/drivers/staging/amazon/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_IDME) += idme.o diff --git a/drivers/staging/amazon/idme.c b/drivers/staging/amazon/idme.c new file mode 100644 index 00000000000..8f339dc9684 --- /dev/null +++ b/drivers/staging/amazon/idme.c @@ -0,0 +1,270 @@ +/* + * board IDME driver + * + * Copyright (C) 2015 Amazon Inc., All Rights Reserved. + * + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +#define DRIVER_VER "2.0" + +/* Idme proc dir */ +#define IDME_PROC_DIR "idme" +#define IDME_MAGIC_NUMBER "beefdeed" +#define IDME_MAX_NAME_LEN 16 + +#define MAC_SEC_KEY "mac_sec" +#define MAC_SEC_OWNER 1000 + +#define DRIVER_INFO "Lab126 IDME driver version " DRIVER_VER +#define IDME_ATAG_SIZE 2048 +#define IDME_MAX_ITEMS 50 +extern unsigned char system_idme[IDME_ATAG_SIZE+1]; +static unsigned char idme_item_name[IDME_MAX_ITEMS][IDME_MAX_NAME_LEN]; + +#ifndef MIN +#define MIN(x,y) ((x) < (y) ? (x) : (y)) +#endif + +#define IDME_ITEM_NEXT(curr_item) \ + curr_item = (struct item_t *)((char *)curr_item + sizeof(struct idme_desc) + curr_item->desc.size) + +/* data structure definition for IDME */ +struct idme_desc { + char name[IDME_MAX_NAME_LEN]; + unsigned int size; + unsigned int exportable; + unsigned int permission; +}; + +struct item_t { + struct idme_desc desc; + unsigned char data[0]; +}; + +struct idme_t { + char magic[8]; + char version[4]; + unsigned int items_num; + + unsigned char item_data[0]; +}; + + +int idme_check_magic_number(struct idme_t *pidme) +{ + if(pidme == NULL) { + printk(KERN_ERR "IDME: the pointer of pidme_data is NULL.\n"); + return -1; + } + + if (strncmp(pidme->magic, IDME_MAGIC_NUMBER, strlen(IDME_MAGIC_NUMBER))){ + printk(KERN_ERR "IDME: idme data is invalid!\n"); + return -2; + } + else + return 0; +} + +/*#define FORD_HVT_DEVICE_ID_DEFAULT*/ +/* to be removed when this field is written in factory and populated in LK */ +#if defined(FORD_HVT_DEVICE_ID_DEFAULT) +static unsigned char ford_device_type[]="A2M4YX06LWP8WI"; +static unsigned char ford_device_type_name[]="device_type_id"; +#endif + +int idme_get_var(const char *name, char *buf, unsigned int length) +{ + int ret = -1; + unsigned int i = 0; + struct idme_t *pdata = (struct idme_t *)&system_idme[0]; + struct item_t *pitem = NULL; + + if (0 != idme_check_magic_number(pdata)){ + printk(KERN_ERR "The idme magic number error.\n"); + return -1; + } + + if (NULL == buf) + return -1; + +#if defined(FORD_HVT_DEVICE_ID_DEFAULT) + if (strcmp(name, ford_device_type_name) == 0) + { + ret = sizeof(ford_device_type); + printk(KERN_ERR "%s: ford_device_type = %s[%d]\n",__func__,ford_device_type,ret); + memcpy(buf,ford_device_type,ret); + return ret; + } +#endif + + pitem = (struct item_t *)(&(pdata->item_data[0])); + for (i = 0; i < pdata->items_num; i++) { + if ( 0 == strcmp(name, pitem->desc.name) ) { + memcpy(buf, &(pitem->data[0]), MIN( pitem->desc.size, length ) ); + ret = MIN(pitem->desc.size, length); + break; + }else{ + IDME_ITEM_NEXT(pitem); + } + } + + return ret; +} + + + +static ssize_t idme_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + char *idme_item_name; + unsigned char idme_item_data[1028] = {'\0'}; + int idme_item_size = 0; + size_t size = 0; + loff_t pos = *ppos; + + idme_item_name = PDE_DATA(file_inode(file)); + if(!(idme_item_name)){ + printk(KERN_ERR "IDME Name is Null"); + return 0; + } + //printk(KERN_ERR "%s: item name is %s %zx %d\n", __func__, idme_item_name, count, (int)pos); + + idme_item_size = idme_get_var((const char*)idme_item_name, idme_item_data, sizeof(idme_item_data)); + if (pos >= idme_item_size) return 0; + if (idme_item_size > 0) { + size = MIN(count, idme_item_size); + copy_to_user(buf,idme_item_data, size); + } else { + printk(KERN_ERR "%s: idme read error\n", __func__); + } + + if ((ssize_t) size > 0) + *ppos = pos + size; + return size; +} + +static const struct file_operations idme_proc_fops = { + .read = idme_read, +}; + +void create_idme_proc(void) +{ + int i = 0; + struct proc_dir_entry *proc_item[100]; + unsigned char *pidme; + unsigned int *scan; + char name[32] = {'\0'}; + char idme_magic_number[9] = {'\0'}; + char idme_version[5] = {'\0'}; + unsigned int idme_item_num, exportable, permission, data_size; + unsigned int *ptemp; + unsigned char data[128] = {0}; + struct proc_dir_entry *idme_dir = NULL; + bool access_restrict = false; + + pidme = &system_idme[0]; + idme_dir = proc_mkdir(IDME_PROC_DIR, NULL); + + /* check IDME magic number */ + strncpy(idme_magic_number, pidme, 8); + if (strncmp(idme_magic_number, IDME_MAGIC_NUMBER, strlen(IDME_MAGIC_NUMBER))) { + printk(KERN_ERR"%s: invalid IDME magic number %s\n", __func__, idme_magic_number); + return; + } + pidme += 8; + + /* check IDME version */ + strncpy(idme_version, pidme, 4); + pidme += 4; + + /* get the IDME item number */ + ptemp = (unsigned int *)pidme; + idme_item_num = *ptemp; + pidme += sizeof(unsigned int); + printk(KERN_INFO"%s: IDME version %s, item size %d\n", __func__, idme_version, idme_item_num); + + for (i = 0; i < idme_item_num; i++) { + // set get name + strncpy(name, pidme, 16); + pidme += 16; + + // get data size + ptemp = (unsigned int *)pidme; + data_size = *ptemp; + pidme += sizeof(unsigned int); + + // get exportable + ptemp = (unsigned int *)pidme; + exportable = *ptemp; + pidme += sizeof(unsigned int); + + // get permission + ptemp = (unsigned int *)pidme; + permission = *ptemp; + pidme += sizeof(unsigned int); + + // get data + //memcpy(data, pidme, data_size); + pidme += data_size; + + /* Restrict mac_sec */ + if (strcmp(name, MAC_SEC_KEY) == 0) { + access_restrict = true; + permission = 0400; + } else { + access_restrict = false; + } + + // set name and read its function + if(exportable > 0) { + strncpy(idme_item_name[i], name, strlen(name)); + proc_item[i] = proc_create_data(name, permission, idme_dir, &idme_proc_fops, idme_item_name[i]); + + if (proc_item[i] && access_restrict) + proc_set_user(proc_item[i], MAC_SEC_OWNER, 0); + } + } +#if defined(FORD_HVT_DEVICE_ID_DEFAULT) + /* add device_type_id */ + proc_create_data(ford_device_type_name, permission, idme_dir, &idme_proc_fops, ford_device_type_name); +#endif + return; +} + +/* copy initialize the idme */ +static void initialize_idme(void) +{ + create_idme_proc(); +} + +void init_idme(void) +{ + printk(DRIVER_INFO "\n"); + initialize_idme(); +} + +module_init(init_idme);