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

📄 filesystem.c

📁 Linux下操作Bios的驱动
💻 C
字号:
/* * BIOS/Flashrom driver for Linux * * Copyright (C) 1998-2002 Stefan Reinauer <stepan@suse.de> * */#include <linux/errno.h>#include <linux/types.h>#include <linux/vmalloc.h>#include <linux/fcntl.h>#include <linux/delay.h>#include <asm/uaccess.h>#include "bios.h"#include "flashchips.h"#include "pcisets.h"#include "programming.h"#ifdef MODULEvoid inc_mod(void);void dec_mod(void);#endif/* * ****************************************** * *	/dev/bios filesystem operations * * ******************************************  */static loff_t bios_llseek(struct file *file, loff_t offset, int origin ){	switch(origin) {	  case 0:		break;	  case 1:		offset += file->f_pos;		break;	  case 2:		offset += BIOS_SIZE;		break;	}	return((offset >= 0)?(file->f_pos = offset):-EINVAL);}static ssize_t bios_read(struct file *file, char *buffer, size_t count, loff_t *ppos){	signed int size=((BIOS_SIZE-*ppos>count) ? count : BIOS_SIZE-*ppos);	int i;	bios = flashdevices[FDEV].mapped+flashdevices[FDEV].offset;	flashdevices[FDEV].activate(1,flashdevices[FDEV].data);	for (i=0;i<size;i++) 		buffer[i]=flash_readb(*ppos+i);	flashdevices[FDEV].activate(0,flashdevices[FDEV].data);	*ppos+=size;	return size;}static ssize_t bios_write(struct file *file, const char *buffer, size_t count, loff_t *ppos){        unsigned long flags;	unsigned int offset=0, startsec=0, endsec=0;	unsigned int secnum=0, size=0, writeoffs=0;	unsigned char *clipboard;	unsigned int fn=flashdevices[FDEV].flashnum;	int i;	bios=flashdevices[FDEV].mapped+flashdevices[FDEV].offset;	/* Some security checks. */	if (!suser())		return -EACCES;	if (!flashchips[fn].supported) {		printk (KERN_ERR "BIOS: Flash device not supported.\n");		return -EMEDIUMTYPE;	}	if (!write) {		printk (KERN_WARNING "Writing is disabled for security reasons. RTFM.\n");		return -EACCES;	}	if ( count > BIOS_SIZE-*ppos )		return -EFBIG;	/* FIXME: Autoselect(AMD) BC-90 	 * -> 00/MID; 	 *    01/PID; 	 *    02/Protected (1=yes/0=no)	 */	/* Determine size of data to be written */	if (!(flashchips[fn].flags & f_needs_erase) ) {		offset=(unsigned int)*ppos&~(flashchips[fn].pagesize-1);		size=(((unsigned int)*ppos+count+(flashchips[fn].pagesize-1))&~(flashchips[flashdevices[FDEV].flashnum].pagesize-1))-offset;	} else {		while (flashchips[fn].sectors[secnum] <= flashchips[fn].size ) {			if ((unsigned int)*ppos >= flashchips[fn].sectors[secnum]*1024) {				offset=flashchips[fn].sectors[secnum]*1024;				startsec=secnum;			}			if ((unsigned int)*ppos+count-1 <= flashchips[fn].sectors[secnum]*1024) {				size=(flashchips[fn].sectors[secnum]*1024)-offset;				endsec=secnum-1;				break;			}			secnum++;		}	}#ifdef DEBUG	printk (KERN_DEBUG "BIOS: Write [0x%06x..0x%06x] [0x%06x..0x%06x]\n",			(unsigned int)(*ppos),(unsigned int)(*ppos+count-1),offset,offset+size-1);#endif	/* prepare data for writing */	clipboard=vmalloc(size);	spin_lock_irqsave(&bios_lock, flags);	flashdevices[FDEV].activate(1,flashdevices[FDEV].data);	for (i=0; i < size; i++) 		clipboard[i] = flash_readb(offset+i);	copy_from_user(clipboard+(*ppos-offset), buffer, count);	/* start write access */	if (flashchips[fn].flags & f_intel_compl) {		iflash_erase_sectors(fn,startsec,endsec);		for (i=0;i<size;i++)			iflash_program_byte(offset+i, clipboard[i]);		flash_command(0xff);	} else {	  if (flashchips[fn].flags & f_needs_erase) {	    if (size == flashchips[fn].size*1024) { /* whole chip erase */	      printk (KERN_DEBUG "BIOS: Erasing via whole chip method\n");	      flash_erase(fn);	    } else {	      printk (KERN_DEBUG "BIOS: Erasing via sector method\n");	      flash_erase_sectors(fn,startsec,endsec);	    }	  } 	  while (size>0) {	    if ((flashchips[fn].flags & f_manuf_compl) != f_atmel_compl) {	      flash_program();	    } else {	      flash_program_atmel();	    }	    for (i=0;i<flashchips[fn].pagesize;i++) {	      flash_writeb(offset+writeoffs+i,clipboard[writeoffs+i]);	    }	    if ((flashchips[fn].flags & f_manuf_compl) == f_atmel_compl) {	      udelay(750);	    } else {		    if (flashchips[fn].pagesize==1)			    udelay(30);	 	    else	      		    udelay(300);	    }	    if (flash_ready_poll(offset+writeoffs+flashchips[fn].pagesize-1,				 clipboard[writeoffs+flashchips[fn].pagesize-1])) {	      printk (KERN_ERR "BIOS: Error occured, please repeat write operation.\n");	    }	    flash_command(0xf0);	    	    writeoffs += flashchips[fn].pagesize;	    size	  -= flashchips[fn].pagesize;	  }	}	flashdevices[FDEV].activate(0,flashdevices[FDEV].data);	spin_unlock_irqrestore(&bios_lock, flags);	vfree(clipboard);	*ppos+=count;	return count;}static int bios_open(struct inode *inode, struct file *file){	if (flashcount<=FDEV) {		printk (KERN_ERR "BIOS: There is no device (%d).\n",FDEV);		return -ENODEV;	}#ifdef DEBUG	printk(KERN_DEBUG "BIOS: Opening device %d\n",FDEV);#endif	/* Only one shall open for writing */	if ((flashdevices[FDEV].open_cnt && (file->f_flags & O_EXCL)) ||		(flashdevices[FDEV].open_mode & O_EXCL) ||		((file->f_mode & 2) && (flashdevices[FDEV].open_mode & O_RDWR)))		return -EBUSY;	if (file->f_flags & O_EXCL)		flashdevices[FDEV].open_mode |= O_EXCL;	if (file->f_mode & 2)		flashdevices[FDEV].open_mode |= O_RDWR;	flashdevices[FDEV].open_cnt++;	#ifdef MODULE	inc_mod();#endif	return 0;}static int bios_release(struct inode *inode, struct file *file){	if (file->f_flags & O_EXCL)		flashdevices[FDEV].open_mode &= ~O_EXCL;	if (file->f_mode & 2)		flashdevices[FDEV].open_mode &= ~O_RDWR;	flashdevices[FDEV].open_cnt--;	#ifdef MODULE	dec_mod();#endif	return 0;}struct file_operations bios_fops = {	llseek:		bios_llseek,	read:		bios_read,	write:		bios_write,	open:		bios_open,	release:	bios_release};

⌨️ 快捷键说明

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