lab126: Add idme driver
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -140,4 +140,6 @@ source "drivers/staging/netlogic/Kconfig"
|
||||
|
||||
source "drivers/staging/dwc2/Kconfig"
|
||||
|
||||
source "drivers/staging/amazon/Kconfig"
|
||||
|
||||
endif # STAGING
|
||||
|
||||
@@ -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/
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
obj-$(CONFIG_IDME) += idme.o
|
||||
@@ -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 <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/bugs.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
|
||||
|
||||
#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);
|
||||
Reference in New Issue
Block a user