[release] Update version information for 0.9.4 release
[gpxe.git] / contrib / smc9462tx-flash / dp83820_write.c
blobab6e566203af1f9272cc5aea5b731c20d2b8fcb5
1 /*
2 DP83820 flash utility written by Dave Ashley for NXTV, Inc.
3 Copyright (C) 2004 by NXTV, Inc.
4 Written 20040219 by Dave Ashley.
6 Currently only supports the AT29C512
8 This code is released under the terms of the GPL. No warranty.
11 THEORY:
12 This code uses the /proc/dp83820 file which is created by the
13 dp83820flash.o module. That file allows single byte reads + writes
14 to the bootrom.
18 #include <unistd.h>
19 #include <sys/io.h>
20 #include <stdio.h>
21 #include <unistd.h>
22 #include <sys/mman.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <stdlib.h>
27 #include <signal.h>
30 // SMC9462TX card has D5 + D6 on the bootrom socket reversed
31 int fixb(int val)
33 return (val&~0x60) | ((val&0x20)<<1) | ((val&0x40)>>1);
35 int openit(void)
37 int fd;
38 fd=open("/proc/dp83820",O_RDWR);
39 if(fd<0)
41 printf("Failed to open the /proc/dp83820 file to access the flashrom.\n");
42 printf("Make sure you've done:\n");
43 printf(" modprobe dp83820flash\n");
44 exit(-1);
46 return fd;
48 void set(int addr, unsigned char val)
50 unsigned char msg[3];
51 int fd;
52 fd=openit();
53 msg[0]=addr;
54 msg[1]=addr>>8;
55 msg[2]=val;
56 write(fd,msg,3);
57 close(fd);
59 int get(int addr)
61 unsigned char msg[2];
62 int fd;
63 fd=openit();
64 msg[0]=addr;
65 msg[1]=addr>>8;
66 write(fd,msg,2);
67 read(fd,msg,1);
68 close(fd);
69 return msg[0];
73 int getromsize(unsigned char *id)
75 if(id[0]==0xbf && id[1]==0xb6) return 0x40000;
76 if(id[0]==0xc2 && id[1]==0xb0) return 0x40000;
77 if(id[0]==0x1f && id[1]==0x3d) return 0x10000;
78 return -1;
81 #define MAXROMSIZE 0x200000
82 unsigned char *buffer;
84 int loadfile(char *name)
86 int filefd;
87 int filesize;
88 filefd=open(name,O_RDONLY);
89 if(filefd<0)
91 printf("Couldn't open file %s\n",name);
92 return -1;
94 filesize=read(filefd,buffer,MAXROMSIZE);
95 close(filefd);
96 if(filesize<0)
98 printf("Error trying to read from file %s\n",name);
100 return filesize;
103 void readbios(char *name,int len)
105 int filefd;
106 int filesize=0;
107 unsigned char block[256];
108 int i,j;
110 filefd=open(name,O_WRONLY|O_TRUNC|O_CREAT,0644);
111 if(filefd<0)
113 printf("Couldn't create file %s for writing\n",name);
114 return;
116 for(i=j=0;i<len;++i)
118 block[j++]=get(i);
119 if(j<sizeof(block)) continue;
120 filesize+=write(filefd,block,j);
121 j=0;
123 close(filefd);
124 if(filesize!=len)
126 printf("Error during write of %s file\n",name);
127 return;
129 printf("BIOS contents saved to %s, $%x bytes\n",name,len);
132 int verifybios(char *name,int len, int print)
134 int filelen;
135 int i;
136 int same=0;
138 filelen=loadfile(name);
139 for(i=0;i<filelen;++i)
140 if(get(i)!=buffer[i]) break;
141 if(i<filelen)
143 if(print)
144 printf("BIOS contents does not match file %s, from byte $%x\n",
145 name,i);
146 } else
148 if(print)
149 printf("BIOS contents match file %s for all of its $%x bytes\n",
150 name,i);
151 same=1;
153 return same;
156 void writebios(char *name,int len,unsigned char *id)
158 int i;
159 int p1,p2;
160 int sectorsize=128;
162 if(len!=loadfile(name))
164 printf("File size does not match expected ROM size\n");
165 return;
167 if(0 && (id[0]!=0xbf || id[1]!=0xb6))
169 printf("Don't know how to write this kind of flash device\n");
170 return;
173 printf("Erasing device\n");
174 set(0x5555,fixb(0xaa));
175 set(0x2aaa,fixb(0x55));
176 set(0x5555,fixb(0x80));
177 set(0x5555,fixb(0xaa));
178 set(0x2aaa,fixb(0x55));
179 set(0x5555,fixb(0x10));
181 for(;;)
183 printf(".");fflush(stdout);
184 usleep(250000);
185 if(get(0)==get(0) && get(0)==get(0))
186 break;
188 printf("BIOS erased\n");
190 printf("Writing to BIOS\n");
191 p1=-1;
192 for(i=0;i<len;++i)
194 p2=100*i/(len-1);
195 if(p2!=p1)
197 printf("\r%d%%",p1=p2);
198 fflush(stdout);
200 if(i%sectorsize==0)
202 set(0x5555,fixb(0xaa));
203 set(0x2aaa,fixb(0x55));
204 set(0x5555,fixb(0xa0));
206 set(i,buffer[i]);
207 if(i%sectorsize==sectorsize-1)
208 while(get(0)!=get(0) || get(0)!=get(0));
210 printf("\n");
213 void helptext(char *name)
215 printf("USE: %s <options>\n",name);
216 printf(" -v <filename> = verify bios rom contents with file\n");
217 printf(" -w <filename> = write to bios rom contents from file\n");
218 printf(" -r <filename> = read from bios rom contents to file\n");
219 printf(" -f = force erase/write even if contents already match\n");
220 exit(0);
223 int main(int argc,char **argv)
225 int i;
226 int vals;
227 unsigned char id[4];
228 char *filename=0;
229 char action=0;
230 int romsize;
231 int force=0;
232 int same;
234 vals=0;
236 if(argc<2) helptext(argv[0]);
237 for(i=1;i<argc;++i)
239 if(argv[i][0]!='-')
240 helptext(argv[0]);
241 switch(argv[i][1])
243 case 'f':
244 force=1;
245 break;
246 case 'v':
247 case 'w':
248 case 'r':
249 action=argv[i][1];
250 if(i+1<argc)
251 filename=argv[++i];
252 else helptext(argv[0]);
253 break;
254 default:
255 helptext(argv[0]);
260 buffer=malloc(MAXROMSIZE);
261 if(!buffer)
263 printf("No memory available!\n");
264 exit(-1);
267 set(0x5555,fixb(0xaa)); // get into flash ID mode
268 set(0x2aaa,fixb(0x55));
269 set(0x5555,fixb(0x90));
271 for(i=0;i<4;++i) id[i]=get(i);
273 set(0x5555,fixb(0xaa)); // get out of flash ID mode
274 set(0x2aaa,fixb(0x55));
275 set(0x5555,fixb(0xf0));
276 usleep(10000);
278 for(i=0;i<4;++i)
279 if(id[i]!=get(i)) break;
280 if(i==4)
282 printf("Could not read BIOS flashrom ID.\n");
283 goto biosdone;
285 printf("ID %02x %02x\n",id[0],id[1]);
286 romsize=getromsize(id);
287 if(romsize<0)
289 printf("Unknown rom type\n");
290 goto biosdone;
292 printf("romsize=$%x bytes\n",romsize);
293 if(action=='r')
294 readbios(filename,romsize);
295 if(action=='w')
297 if(!force)
298 same=verifybios(filename,romsize,0);
299 else
300 same=0;
301 if(!same)
302 writebios(filename,romsize,id);
304 if(action=='v' || action=='w')
305 verifybios(filename,romsize,1);
307 biosdone:
309 return 0;