|
|
1.1 ! root 1: /* ! 2: * OpenBIOS - free your system! ! 3: * ( firmware/flash device driver for Linux ) ! 4: * ! 5: * filesystem.c - vfs character device interface ! 6: * ! 7: * This program is part of a free implementation of the IEEE 1275-1994 ! 8: * Standard for Boot (Initialization Configuration) Firmware. ! 9: * ! 10: * Copyright (C) 1998-2004 Stefan Reinauer, <[email protected]> ! 11: * ! 12: * This program is free software; you can redistribute it and/or modify ! 13: * it under the terms of the GNU General Public License as published by ! 14: * the Free Software Foundation; version 2 of the License. ! 15: * ! 16: * This program is distributed in the hope that it will be useful, ! 17: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 18: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 19: * GNU General Public License for more details. ! 20: * ! 21: * You should have received a copy of the GNU General Public License ! 22: * along with this program; if not, write to the Free Software ! 23: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA ! 24: * ! 25: */ ! 26: ! 27: #include <linux/config.h> ! 28: #include <linux/version.h> ! 29: #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) && defined(MODVERSIONS) ! 30: #include <linux/modversions.h> ! 31: #endif ! 32: #include <linux/module.h> ! 33: #include <linux/errno.h> ! 34: #include <linux/types.h> ! 35: #include <linux/vmalloc.h> ! 36: #include <linux/fcntl.h> ! 37: #include <linux/delay.h> ! 38: ! 39: #include <asm/uaccess.h> ! 40: ! 41: #include "bios.h" ! 42: #include "flashchips.h" ! 43: #include "pcisets.h" ! 44: #include "programming.h" ! 45: ! 46: #ifdef MODULE ! 47: void inc_mod(void); ! 48: void dec_mod(void); ! 49: #endif ! 50: ! 51: /* ! 52: * ****************************************** ! 53: * ! 54: * /dev/bios filesystem operations ! 55: * ! 56: * ****************************************** ! 57: */ ! 58: ! 59: #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) ! 60: #define FDEV (MINOR(file->f_dentry->d_inode->i_rdev)) ! 61: #else ! 62: #define FDEV (iminor(file->f_dentry->d_inode)) ! 63: #endif ! 64: #define CFLASH flashdevices[FDEV] ! 65: // #define BIOS_SIZE ((flashchips[CFLASH.flashnum].size)*1024) ! 66: #define BIOS_SIZE (CFLASH.size) ! 67: ! 68: static loff_t bios_llseek(struct file *file, loff_t offset, int origin ) ! 69: { ! 70: currflash=FDEV; ! 71: switch(origin) { ! 72: case 0: ! 73: break; ! 74: case 1: ! 75: offset += file->f_pos; ! 76: break; ! 77: case 2: ! 78: offset += BIOS_SIZE; ! 79: break; ! 80: } ! 81: return((offset >= 0)?(file->f_pos = offset):-EINVAL); ! 82: } ! 83: ! 84: static ssize_t bios_read(struct file *file, char *buffer, size_t count, loff_t *ppos) ! 85: { ! 86: signed int size=((BIOS_SIZE-*ppos>count) ? count : BIOS_SIZE-*ppos); ! 87: unsigned char *addr = (unsigned char*)CFLASH.mapped + CFLASH.offset; ! 88: int i; ! 89: ! 90: currflash = FDEV; ! 91: ! 92: devices[flashdevices[currflash].idx].activate(); ! 93: ! 94: for (i=0;i<size;i++) ! 95: buffer[i]=flash_readb(addr,*ppos+i); ! 96: ! 97: devices[flashdevices[currflash].idx].deactivate(); ! 98: ! 99: *ppos+=size; ! 100: return size; ! 101: } ! 102: ! 103: static ssize_t bios_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) ! 104: { ! 105: unsigned long flags; ! 106: unsigned int offset=0, startsec=0, endsec=0; ! 107: unsigned int secnum=0, size=0, writeoffs=0; ! 108: unsigned int i, fn; ! 109: unsigned char *clipboard; ! 110: unsigned char *addr = (unsigned char*)CFLASH.mapped + CFLASH.offset; ! 111: ! 112: currflash=FDEV; ! 113: fn=CFLASH.flashnum; ! 114: ! 115: /* Some security checks. */ ! 116: ! 117: #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ! 118: if (!suser()) ! 119: return -EACCES; ! 120: #endif ! 121: ! 122: if (!write) { ! 123: printk (KERN_WARNING "Writing is disabled for security reasons. RTFM.\n"); ! 124: return -EACCES; ! 125: } ! 126: ! 127: if (!flashchips[fn].supported) { ! 128: printk (KERN_ERR "BIOS: Flash device not supported.\n"); ! 129: return -EMEDIUMTYPE; ! 130: } ! 131: ! 132: if ( count > BIOS_SIZE-*ppos ) ! 133: return -EFBIG; ! 134: ! 135: /* FIXME: Autoselect(AMD) BC-90 ! 136: * -> 00/MID; ! 137: * 01/PID; ! 138: * 02/Protected (1=yes/0=no) ! 139: */ ! 140: ! 141: /* Determine size of data to be written */ ! 142: ! 143: if (!(flashchips[fn].flags & f_needs_erase) ) { ! 144: offset=(unsigned int)*ppos&~(flashchips[fn].pagesize-1); ! 145: size=(((unsigned int)*ppos+count+(flashchips[fn].pagesize-1))& ! 146: ~(flashchips[CFLASH.flashnum].pagesize-1))-offset; ! 147: } else { ! 148: while (flashchips[fn].sectors[secnum] <= flashchips[fn].size ) { ! 149: if ((unsigned int)*ppos >= flashchips[fn].sectors[secnum]*1024) { ! 150: offset=flashchips[fn].sectors[secnum]*1024; ! 151: startsec=secnum; ! 152: } ! 153: if ((unsigned int)*ppos+count-1 <= flashchips[fn].sectors[secnum]*1024) { ! 154: size=(flashchips[fn].sectors[secnum]*1024)-offset; ! 155: endsec=secnum-1; ! 156: break; ! 157: } ! 158: secnum++; ! 159: } ! 160: } ! 161: ! 162: #ifdef DEBUG ! 163: printk (KERN_DEBUG "BIOS: Write [0x%06x..0x%06x] [0x%06x..0x%06x]\n", ! 164: (unsigned int)(*ppos),(unsigned int)(*ppos+count-1),offset,offset+size-1); ! 165: #endif ! 166: ! 167: /* prepare data for writing */ ! 168: ! 169: clipboard=vmalloc(size); ! 170: ! 171: spin_lock_irqsave(&bios_lock, flags); ! 172: ! 173: devices[flashdevices[currflash].idx].activate(); ! 174: ! 175: for (i=0; i < size; i++) ! 176: clipboard[i] = flash_readb(addr,offset+i); ! 177: ! 178: copy_from_user(clipboard+(*ppos-offset), buffer, count); ! 179: ! 180: /* start write access */ ! 181: ! 182: if (flashchips[fn].flags & f_intel_compl) { ! 183: iflash_erase_sectors(addr,fn,startsec,endsec); ! 184: ! 185: for (i=0;i<size;i++) ! 186: iflash_program_byte(addr, offset+i, clipboard[i]); ! 187: ! 188: flash_command(addr, 0xff); ! 189: ! 190: } else { ! 191: ! 192: if (flashchips[fn].flags & f_needs_erase) { ! 193: if (size == flashchips[fn].size*1024) { /* whole chip erase */ ! 194: printk (KERN_DEBUG "BIOS: Erasing via whole chip method\n"); ! 195: flash_erase(addr, fn); ! 196: } else { ! 197: printk (KERN_DEBUG "BIOS: Erasing via sector method\n"); ! 198: flash_erase_sectors(addr, fn,startsec,endsec); ! 199: } ! 200: } ! 201: ! 202: while (size>0) { ! 203: if ((flashchips[fn].flags & f_manuf_compl) != f_atmel_compl) { ! 204: flash_program(addr); ! 205: } else { ! 206: flash_program_atmel(addr); ! 207: } ! 208: for (i=0;i<flashchips[fn].pagesize;i++) { ! 209: flash_writeb(addr,offset+writeoffs+i,clipboard[writeoffs+i]); ! 210: } ! 211: if ((flashchips[fn].flags & f_manuf_compl) == f_atmel_compl) { ! 212: udelay(750); ! 213: } else { ! 214: if (flashchips[fn].pagesize==1) ! 215: udelay(30); ! 216: else ! 217: udelay(300); ! 218: } ! 219: ! 220: if (flash_ready_poll(addr,offset+writeoffs+flashchips[fn].pagesize-1, ! 221: clipboard[writeoffs+flashchips[fn].pagesize-1])) { ! 222: printk (KERN_ERR "BIOS: Error occured, please repeat write operation.\n"); ! 223: } ! 224: flash_command(addr, 0xf0); ! 225: ! 226: writeoffs += flashchips[fn].pagesize; ! 227: size -= flashchips[fn].pagesize; ! 228: } ! 229: } ! 230: ! 231: devices[flashdevices[currflash].idx].deactivate(); ! 232: ! 233: spin_unlock_irqrestore(&bios_lock, flags); ! 234: ! 235: vfree(clipboard); ! 236: ! 237: *ppos+=count; ! 238: return count; ! 239: } ! 240: ! 241: static int bios_open(struct inode *inode, struct file *file) ! 242: { ! 243: currflash=FDEV; ! 244: ! 245: if (flashcount<=FDEV) { ! 246: printk (KERN_ERR "BIOS: There is no device (%d).\n",FDEV); ! 247: return -ENODEV; ! 248: } ! 249: ! 250: #ifdef DEBUG ! 251: printk(KERN_DEBUG "BIOS: Opening device %d\n",FDEV); ! 252: #endif ! 253: /* Only one shall open for writing */ ! 254: ! 255: if ((CFLASH.open_cnt && (file->f_flags & O_EXCL)) || ! 256: (CFLASH.open_mode & O_EXCL) || ! 257: ((file->f_mode & 2) && (CFLASH.open_mode & O_RDWR))) ! 258: return -EBUSY; ! 259: ! 260: if (file->f_flags & O_EXCL) ! 261: CFLASH.open_mode |= O_EXCL; ! 262: ! 263: if (file->f_mode & 2) ! 264: CFLASH.open_mode |= O_RDWR; ! 265: ! 266: CFLASH.open_cnt++; ! 267: ! 268: ! 269: #ifdef MODULE ! 270: inc_mod(); ! 271: #endif ! 272: return 0; ! 273: } ! 274: ! 275: static int bios_release(struct inode *inode, struct file *file) ! 276: { ! 277: currflash=FDEV; ! 278: if (file->f_flags & O_EXCL) ! 279: CFLASH.open_mode &= ~O_EXCL; ! 280: ! 281: if (file->f_mode & 2) ! 282: CFLASH.open_mode &= ~O_RDWR; ! 283: ! 284: CFLASH.open_cnt--; ! 285: ! 286: #ifdef MODULE ! 287: dec_mod(); ! 288: #endif ! 289: return 0; ! 290: } ! 291: ! 292: struct file_operations bios_fops = { ! 293: .owner = THIS_MODULE, ! 294: .llseek = bios_llseek, ! 295: .read = bios_read, ! 296: .write = bios_write, ! 297: .open = bios_open, ! 298: .release = bios_release, ! 299: }; ! 300:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.