|
|
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.