⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eeprom.c

📁 linux for amd development lx8
💻 C
字号:
/* * Driver for the EEPROM encryption key storage on the Geode GX  * Copyright (C) 2003 Advanced Micro Devices, Inc.  All Rights Reserved. *//* This driver allows the user to read and write the 238 bytes of user   on the EEPROM.  This is the space above the access control bytes and   the hidden key, which couldn't be read even if we wanted to.  As far   as the user is concerned, he can seek, read and (if the bytes are set),   write up to 238 bytes of general storage.   Setting the key and the access control bytes is handled by the ioctl   commands.*/#include <linux/kernel.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/miscdevice.h>#include <asm/io.h>#include <asm/uaccess.h>#include <asm/delay.h>#include "geode_crypto.h"static inteeprom_read_dev(struct geode_crypt_driver *driver, u8 *data, int offset, 		int size) {	u32 ctrl = readl(driver->base + EEPROM_CTRL_REG);	int i = 0;	int ret = -EINVAL;	/* Sanity check */	if (offset + size > 255) return -EINVAL;		/* Just a simple wait loop */		for(i = 0; i < size; i++) {		u32 reg = ctrl;		u32 value = 0;		writel(0x0 | ((offset + i) & 0xFF), 		       driver->base + EEPROM_ADDR_REG);				reg &= ~EEPROM_CTRL_WRITE;		reg |= EEPROM_CTRL_START;				writel(reg, driver->base + EEPROM_CTRL_REG);				while(1) {			reg = readl(driver->base + EEPROM_CTRL_REG);			if (reg & EEPROM_CTRL_EXCEPT) goto exit_read;			else if (!(reg & EEPROM_CTRL_START)) break;			udelay(10);		}		value = readl(driver->base + EEPROM_DATA_REG);		data[i] = value & 0xFF;    	}	ret = 0; exit_read:	writel(ctrl | EEPROM_CTRL_EXCEPT, driver->base + EEPROM_CTRL_REG);	return ret;}static int eeprom_write_dev(struct geode_crypt_driver *driver, u8 *data, 		 int offset, int size) {	int i = 0;	int ret = -EINVAL;	u32 in = readl(driver->base + EEPROM_SEC_REG);	u32 mask = offset < 127 ? EEPROM_ACCESS_WPL : EEPROM_ACCESS_WPU;	u32 ctrl = readl(driver->base + EEPROM_CTRL_REG);	/* Sanity check */	if (offset + size > 255) return -EINVAL;		/* Make sure that we have permission to write */	if ((in & mask) != mask) return -EACCES;		/* Just a simple wait loop */		for(i = 0; i < size; i++) {		u32 reg = 0;		writel(0x0 | ((offset + i) & 0xFF), 		       driver->base + EEPROM_ADDR_REG);		writel(0x0 | (data[i] & 0xFF), driver->base + EEPROM_DATA_REG);				writel(ctrl | EEPROM_CTRL_WRITE | EEPROM_CTRL_START,		       driver->base + EEPROM_CTRL_REG);		 while(1) {			 reg = readl(driver->base + EEPROM_CTRL_REG);			 if (reg & EEPROM_CTRL_EXCEPT) goto exit_write;			 else if (!(reg & EEPROM_CTRL_START)) break;			 udelay(10);		 }		 	}	ret = 0; exit_write:	writel(ctrl  | EEPROM_CTRL_EXCEPT, driver->base + EEPROM_CTRL_REG);	return ret;}static loff_t eeprom_lseek(struct file * file, loff_t offset, int orig) {			switch(orig) {	case 0:		if (offset < 0 || offset > 237) return -EINVAL;		file->f_pos = (unsigned int) offset;		return file->f_pos;			case 1:		if (file->f_pos + offset > 237) return -EINVAL;		if (file->f_pos + offset < 0) return -EINVAL;		file->f_pos += offset;		return file->f_pos;    	default:		return -EINVAL;	}}static ssize_t eeprom_write(struct file *filep, const char *buffer, 	     size_t count, loff_t * ppos) {	struct geode_crypt_driver *driver = 		(struct geode_crypt_driver *) filep->private_data;	u8 local[238]; 	int len, ret;		if (filep->f_pos > 237) return 0; 	len = (filep->f_pos + count > 237) ? 238 - filep->f_pos : count;	if (copy_from_user(local, buffer, len))		return -EFAULT;		down(&driver->eeprom_mutex); 	ret = eeprom_write_dev(driver, local, 18 + filep->f_pos, len);	up(&driver->eeprom_mutex);  	if (ret) return ret;			*ppos += len;	return len;}static ssize_t eeprom_read(struct file *filep, char *buffer, size_t count, loff_t * ppos) {		struct geode_crypt_driver *driver = 		(struct geode_crypt_driver *) filep->private_data;		u8 local[238]; 	int len, ret;	if (filep->f_pos > EEPROM_SIZE) return 0; 	len = (filep->f_pos + count > EEPROM_SIZE) 		? (EEPROM_SIZE + 1) - filep->f_pos : count;	down(&driver->eeprom_mutex); 	ret = eeprom_read_dev(driver, local, 			      EEPROM_ID_OFFSET + filep->f_pos, len);	up(&driver->eeprom_mutex);   	if (ret) return ret;  	if (copy_to_user(buffer, local, len))		return -EFAULT;	*ppos += len;	return len;}  static int eeprom_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, 	     unsigned long arg) {	struct geode_crypt_driver *driver = 		(struct geode_crypt_driver *) filp->private_data;	u32 in, mask;	/* Return -EINVAL if there is an exepction on the device */	in = readl(driver->base + EEPROM_CTRL_REG);	if (in & EEPROM_CTRL_EXCEPT) 	  return -EINVAL;	switch(cmd) {	case EIOCSKEYOFF:		in |= EEPROM_CTRL_KEYDISABLE;		writel(in, driver->base + EEPROM_CTRL_REG);		return 0;    	case EIOCSLOCKUP:	case EIOCSLOCKLW:		mask = (cmd == EIOCSLOCKLW) ? 			EEPROM_ACCESS_WPL : EEPROM_ACCESS_WPU;	  		in = readl(driver->base + EEPROM_SEC_REG);	  		/* If write access is enabled, then we can lock it */		/* This will take effect on the next reset */	  		if ((in & mask) == mask) {			char ctrl = 0x00;		  			eeprom_read_dev(driver, &ctrl, 0, 1);			ctrl &= ~mask;			eeprom_write_dev(driver, &ctrl, 0, 1);		}    		return 0;    	case EIOSKEY: {		u8 key[32];		if (!arg) return -EINVAL;		copy_from_user((u8 *) key, (u8 *) arg, sizeof(key));		return eeprom_write_dev(driver, (u8 *) key, 					EEPROM_KEY_OFFSET, 16);	}	case EIOGPERMS: {		int ret = 0;				in = readl(driver->base + EEPROM_SEC_REG);		if ((in & EEPROM_ACCESS_WPL) == EEPROM_ACCESS_WPL) 			ret |= EEPROM_LOWER_RW;		if ((in & EEPROM_ACCESS_WPU) == EEPROM_ACCESS_WPL) 			ret |= EEPROM_UPPER_RW;		return ret;	}	}	return -EINVAL;}extern struct geode_crypt_driver *crypto_driver;static int eeprom_open(struct inode * inode, struct file * filp) {	filp->private_data = (void *) crypto_driver;	return 0;}static struct file_operations geode_eeprom_fops = {	owner:          THIS_MODULE,	open:           eeprom_open,	read:           eeprom_read,	write:          eeprom_write,	llseek:         eeprom_lseek,	ioctl:		eeprom_ioctl,}; struct miscdevice geode_eeprom_device = {	GEODE_EEPROM_MINOR_DEV,	"geode_eeprom",	&geode_eeprom_fops};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -