[GDB] Zero-extend 16-bit segment registers
[people/balajirrao/gpxe.git] / contrib / smc9462tx-flash / dp83820_write.c
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.
5
6    Currently only supports the AT29C512
7
8    This code is released under the terms of the GPL. No warranty.
9
10
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.
15
16 */
17
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>
28
29
30 // SMC9462TX card has D5 + D6 on the bootrom socket reversed
31 int fixb(int val)
32 {
33         return (val&~0x60) | ((val&0x20)<<1) | ((val&0x40)>>1);
34 }
35 int openit(void)
36 {
37 int fd;
38         fd=open("/proc/dp83820",O_RDWR);
39         if(fd<0)
40         {
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);
45         }
46         return fd;
47 }
48 void set(int addr, unsigned char val)
49 {
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);
58 }
59 int get(int addr)
60 {
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];
70 }
71
72
73 int getromsize(unsigned char *id)
74 {
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;
79 }
80
81 #define MAXROMSIZE 0x200000
82 unsigned char *buffer;
83
84 int loadfile(char *name)
85 {
86 int filefd;
87 int filesize;
88         filefd=open(name,O_RDONLY);
89         if(filefd<0)
90         {
91                 printf("Couldn't open file %s\n",name);
92                 return -1;
93         }
94         filesize=read(filefd,buffer,MAXROMSIZE);
95         close(filefd);
96         if(filesize<0)
97         {
98                 printf("Error trying to read from file %s\n",name);
99         }
100         return filesize;
101 }
102
103 void readbios(char *name,int len)
104 {
105 int filefd;
106 int filesize=0;
107 unsigned char block[256];
108 int i,j;
109
110         filefd=open(name,O_WRONLY|O_TRUNC|O_CREAT,0644);
111         if(filefd<0)
112         {
113                 printf("Couldn't create file %s for writing\n",name);
114                 return;
115         }
116         for(i=j=0;i<len;++i)
117         {
118                 block[j++]=get(i);
119                 if(j<sizeof(block)) continue;
120                 filesize+=write(filefd,block,j);
121                 j=0;
122         }
123         close(filefd);
124         if(filesize!=len)
125         {
126                 printf("Error during write of %s file\n",name);
127                 return;
128         }
129         printf("BIOS contents saved to %s, $%x bytes\n",name,len);
130 }
131
132 int verifybios(char *name,int len, int print)
133 {
134 int filelen;
135 int i;
136 int same=0;
137
138         filelen=loadfile(name);
139         for(i=0;i<filelen;++i)
140                 if(get(i)!=buffer[i]) break;
141         if(i<filelen)
142         {
143                 if(print)
144                         printf("BIOS contents does not match file %s, from byte $%x\n",
145                                 name,i);
146         } else
147         {
148                 if(print)
149                         printf("BIOS contents match file %s for all of its $%x bytes\n",
150                                 name,i);
151                 same=1;
152         }
153         return same;
154 }
155
156 void writebios(char *name,int len,unsigned char *id)
157 {
158 int i;
159 int p1,p2;
160 int sectorsize=128;
161
162         if(len!=loadfile(name))
163         {
164                 printf("File size does not match expected ROM size\n");
165                 return;
166         }
167         if(0 && (id[0]!=0xbf || id[1]!=0xb6))
168         {
169                 printf("Don't know how to write this kind of flash device\n");
170                 return;
171         }
172
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));
180
181         for(;;)
182         {
183                 printf(".");fflush(stdout);
184                 usleep(250000);
185                 if(get(0)==get(0) && get(0)==get(0))
186                         break;
187         }
188         printf("BIOS erased\n");
189
190         printf("Writing to BIOS\n");
191         p1=-1;
192         for(i=0;i<len;++i)
193         {
194                 p2=100*i/(len-1);
195                 if(p2!=p1)
196                 {
197                         printf("\r%d%%",p1=p2);
198                         fflush(stdout);
199                 }
200                 if(i%sectorsize==0)
201                 {
202                         set(0x5555,fixb(0xaa));
203                         set(0x2aaa,fixb(0x55));
204                         set(0x5555,fixb(0xa0));
205                 }
206                 set(i,buffer[i]);
207                 if(i%sectorsize==sectorsize-1)
208                         while(get(0)!=get(0) || get(0)!=get(0));
209         }
210         printf("\n");
211 }
212
213 void helptext(char *name)
214 {
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);
221 }
222
223 int main(int argc,char **argv)
224 {
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;
233
234         vals=0;
235
236         if(argc<2) helptext(argv[0]);
237         for(i=1;i<argc;++i)
238         {
239                 if(argv[i][0]!='-')
240                         helptext(argv[0]);
241                 switch(argv[i][1])
242                 {
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]);
256                 }
257                 
258         }
259
260         buffer=malloc(MAXROMSIZE);
261         if(!buffer)
262         {
263                 printf("No memory available!\n");
264                 exit(-1);
265         }
266
267         set(0x5555,fixb(0xaa)); // get into flash ID mode
268         set(0x2aaa,fixb(0x55));
269         set(0x5555,fixb(0x90));
270
271         for(i=0;i<4;++i) id[i]=get(i);
272
273         set(0x5555,fixb(0xaa)); // get out of flash ID mode
274         set(0x2aaa,fixb(0x55));
275         set(0x5555,fixb(0xf0));
276         usleep(10000);
277
278         for(i=0;i<4;++i)
279                 if(id[i]!=get(i)) break;
280         if(i==4)
281         {
282                 printf("Could not read BIOS flashrom ID.\n");
283                 goto biosdone;
284         }
285         printf("ID %02x %02x\n",id[0],id[1]);
286         romsize=getromsize(id);
287         if(romsize<0)
288         {
289                 printf("Unknown rom type\n");
290                 goto biosdone;
291         }
292         printf("romsize=$%x bytes\n",romsize);
293         if(action=='r')
294                 readbios(filename,romsize);
295         if(action=='w')
296         {
297                 if(!force)
298                         same=verifybios(filename,romsize,0);
299                 else
300                         same=0;
301                 if(!same)
302                         writebios(filename,romsize,id);
303         }
304         if(action=='v' || action=='w')
305                 verifybios(filename,romsize,1);
306
307 biosdone:
308
309         return 0;
310 }