Here is the flash utility I use without problems on every epia-m I've ever run across: #include <unistd.h> #include <sys/io.h> #include <stdio.h> #include <unistd.h> #include <sys/mman.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> #include <signal.h>
/* VIA EPIA-M BIOS Flash utility written by Dave Ashley for NXTV Software. Written 20030418 by Dave Ashley. Use at your own risk, no warranties are implied or given. This code released under the terms of the GPL.
Currently only supports the SST39SF020A */
#define MEMNAME "/dev/mem"
void outpci(int addr,unsigned char value) { unsigned long val,mask; int shift; outl(0x80000000 | (17<<11) | (addr&0xfc),0xcf8); val=inl(0xcfc); shift=(addr&3)<<3; mask=0xff<<shift; outl((val&~mask) | (value<<shift),0xcfc); } unsigned char inpci(int addr) { outl(0x80000000 | (17<<11) | (addr&0xfc),0xcf8); return 255 & (inl(0xcfc)>>((addr&3)<<3)); }
unsigned char vt8235[4]={0x06, 0x11, 0x77, 0x31};
int getromsize(unsigned char *id) { if(id[0]==0xbf && id[1]==0xb6) return 0x40000; if(id[0]==0xc2 && id[1]==0xb0) return 0x40000; return -1; }
#define MAXROMSIZE 0x200000 unsigned char *buffer;
int loadfile(char *name) { int filefd; int filesize; filefd=open(name,O_RDONLY); if(filefd<0) { printf("Couldn't open file %s\n",name); return -1; } filesize=read(filefd,buffer,MAXROMSIZE); close(filefd); if(filesize<0) { printf("Error trying to read from file %s\n",name); } return filesize; }
void readbios(char *name,volatile unsigned char *where,int len) { int filefd; int filesize;
filefd=open(name,O_WRONLY|O_TRUNC|O_CREAT,0644); if(filefd<0) { printf("Couldn't create file %s for writing\n",name); return; } filesize=write(filefd,(void *)where,len); close(filefd); if(filesize!=len) { printf("Error during write of %s file\n",name); return; } printf("BIOS contents saved to %s, $%x bytes\n",name,len); }
int verifybios(char *name,volatile unsigned char *where,int len, int print) { int filelen; int i; int same=0;
filelen=loadfile(name); for(i=0;i<filelen;++i) if(where[i]!=buffer[i]) break; if(i<filelen) { if(print) printf("BIOS contents does not match file %s, from byte $%x\n", name,i); } else { if(print) printf("BIOS contents match file %s for all of its $%x bytes\n", name,i); same=1; } return same; }
void writebios(char *name,volatile unsigned char *where,int len,unsigned char *id) { int i; int p1,p2;
if(len!=loadfile(name)) { printf("File size does not match expected ROM size\n"); return; } if(0 && (id[0]!=0xbf || id[1]!=0xb6)) { printf("Don't know how to write this kind of flash device\n"); return; }
printf("Erasing device\n"); where[0x5555]=0xaa; where[0x2aaa]=0x55; where[0x5555]=0x80; where[0x5555]=0xaa; where[0x2aaa]=0x55; where[0x5555]=0x10;
for(;;) { printf(".");fflush(stdout); usleep(250000); if(where[0]==where[0] && where[0]==where[0]) break; } printf("BIOS erased\n");
printf("Writing to BIOS\n"); p1=-1; for(i=0;i<len;++i) { p2=100*i/(len-1); if(p2!=p1) { printf("\r%d%%",p1=p2); fflush(stdout); } where[0x5555]=0xaa; where[0x2aaa]=0x55; where[0x5555]=0xa0; where[i]=buffer[i]; while(where[0]!=where[0] || where[0]!=where[0]); } printf("\n"); }
void helptext(char *name) { printf("USE: %s <options>\n",name); printf(" -v <filename> = verify bios rom contents with file\n"); printf(" -w <filename> = write to bios rom contents from file\n"); printf(" -r <filename> = read from bios rom contents to file\n"); printf(" -f = force erase/write even if contents already match\n"); exit(0); }
int main(int argc,char **argv) { int i; int fd; volatile unsigned char *where; unsigned long save; int vals; unsigned char save4d; int powermanagement; unsigned char id[4]; char *filename=0; char action=0; int romsize; int force=0; int same;
vals=0;
if(argc<2) helptext(argv[0]); for(i=1;i<argc;++i) { if(argv[i][0]!='-') helptext(argv[0]); switch(argv[i][1]) { case 'f': force=1; break; case 'v': case 'w': case 'r': action=argv[i][1]; if(i+1<argc) filename=argv[++i]; else helptext(argv[0]); break; default: helptext(argv[0]); }
}
buffer=malloc(MAXROMSIZE); if(!buffer) { printf("No memory available!\n"); exit(-1); }
iopl(3);
for(i=0;i<4;++i) if(inpci(i)!=vt8235[i]) { printf("Could not find VT8235 Bus control and power management device\n"); exit(-1); }
fd=open(MEMNAME,O_RDWR);
where=mmap(0,0x40000,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0xfffc0000); if(where==(void *)0xffffffff) { printf("Could not mmap\n"); exit(-2); }
// Determine where power management registers have been located powermanagement=(inpci(0x88)&0x80) | (inpci(0x89)<<8);
save4d=inb(powermanagement+0x4d); outb(save4d | 0x80,powermanagement+0x4d); // enable writes to bios
save=inpci(0x40); outpci(0x40,0x10 | save);// enable writes to bios, GPO15 must go high
where[0x5555]=0xaa; // get into flash ID mode where[0x2aaa]=0x55; where[0x5555]=0x90;
for(i=0;i<4;++i) id[i]=where[i];
where[0x5555]=0xaa; where[0x2aaa]=0x55; where[0x5555]=0xf0;
for(i=0;i<4;++i) if(id[i]!=where[i]) break; if(i==4) { printf("Could not read BIOS flashrom ID.\n"); goto biosdone; } printf("ID %02x %02x\n",id[0],id[1]); romsize=getromsize(id); if(romsize<0) { printf("Unknown rom type\n"); goto biosdone; } printf("romsize=$%x bytes\n",romsize); if(action=='r') readbios(filename,where,romsize); if(action=='w') { if(!force) same=verifybios(filename,where,romsize,0); else same=0; if(!same) writebios(filename,where,romsize,id); } if(action=='v' || action=='w') verifybios(filename,where,romsize,1);
biosdone: outpci(0x40,save);// disable writes to bios outb(save4d,powermanagement+0x4d); // restore write protect bit
return 0; }