📄 filesystem.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 + -