Annotation of qemu/roms/openbios/utils/devbios/filesystem.c, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.