1
0
mirror of https://github.com/DigitalDevices/dddvb.git synced 2023-10-10 13:37:43 +02:00
dddvb/apps/flashprog.c

291 lines
6.5 KiB
C
Raw Normal View History

2015-08-05 17:22:42 +02:00
/*
/* flashprog - Programmer for flash on Digital Devices Octopus
*
* Copyright (C) 2010-2011 Digital Devices GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 only, as published by the Free Software Foundation.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/types.h>
2020-01-18 16:23:09 +01:00
#include <errno.h>
2015-08-05 17:22:42 +02:00
2016-10-24 15:15:09 +02:00
#include "flash.h"
2020-01-18 16:23:09 +01:00
#include "flash.c"
2015-08-05 17:22:42 +02:00
2020-01-18 16:23:09 +01:00
void get_ddid(int ddb, struct ddb_id *ddbid) {
2015-08-05 17:22:42 +02:00
uint8_t id[4];
if (ioctl(ddb, IOCTL_DDB_ID, ddbid)>=0)
return;
memset(ddbid, 0, sizeof(*ddbid));
2020-01-22 09:58:13 +01:00
flashread(ddb, linknr, id, 0, 4);
2015-08-05 17:22:42 +02:00
printf("%02x %02x %02x %02x\n",
id[0], id[1], id[2], id[3]);
ddbid->subvendor=(id[0] << 8) | id[1];
ddbid->subdevice=(id[2] << 8) | id[3];
}
int sure()
{
char c;
printf("\n\nWARNING! Flashing a new FPGA image might make your card unusable!\n");
printf("\n\nWARNUNG! Das Flashen eines neuen FPGA-Images kann Ihre Karte unbrauchbar machen.\n");
printf("\n\nAre you sure? y/n?");
printf("\n\nSind Sie sicher? y/n?");
fflush(0);
c = getchar();
if (c!='y') {
printf("\nFlashing aborted.\n\n");
return -1;
}
printf("\nStarting to flash\n\n");
return 0;
}
int main(int argc, char **argv)
{
char ddbname[80];
2020-09-17 09:55:24 +02:00
char *flashname;
2015-08-05 17:22:42 +02:00
int type = 0;
struct ddb_id ddbid;
uint8_t *buffer;
int BufferSize = 0;
int BlockErase = 0;
uint32_t FlashOffset = 0x10000;
int ddb;
int i, err;
2016-10-24 15:15:09 +02:00
uint32_t SectorSize=0;
uint32_t FlashSize=0;
2015-08-05 17:22:42 +02:00
int Flash;
uint32_t svid=0, jump=0, dump=0;
int bin;
int ddbnum = 0;
int force = 0;
2016-10-10 00:10:39 +02:00
char *fname = NULL;
2015-08-05 17:22:42 +02:00
while (1) {
int option_index = 0;
int c;
static struct option long_options[] = {
{"svid", required_argument, NULL, 's'},
{"help", no_argument , NULL, 'h'},
{"force", no_argument , NULL, 'f'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv,
2016-10-10 00:10:39 +02:00
"d:n:s:o:l:dfhjb:",
2015-08-05 17:22:42 +02:00
long_options, &option_index);
if (c==-1)
break;
switch (c) {
2016-10-10 00:10:39 +02:00
case 'b':
fname = optarg;
break;
2015-08-05 17:22:42 +02:00
case 'd':
dump = strtoul(optarg, NULL, 16);
break;
case 's':
svid = strtoul(optarg, NULL, 16);
break;
case 'o':
FlashOffset = strtoul(optarg, NULL, 16);
break;
case 'n':
ddbnum = strtol(optarg, NULL, 0);
break;
case 'l':
linknr = strtol(optarg, NULL, 0);
break;
case 'f':
force = 1;
break;
case 'j':
jump = 1;
break;
case 'h':
default:
break;
}
}
if (optind<argc) {
printf("Warning: unused arguments\n");
}
sprintf(ddbname, "/dev/ddbridge/card%d", ddbnum);
ddb=open(ddbname, O_RDWR);
if (ddb < 0) {
printf("Could not open device\n");
return -1;
}
2020-09-17 09:55:24 +02:00
Flash = flashdetect(ddb, &SectorSize, &FlashSize, &flashname);
2015-08-05 17:22:42 +02:00
2020-01-18 16:23:09 +01:00
get_ddid(ddb, &ddbid);
#if 0
2015-08-05 17:22:42 +02:00
printf("%04x %04x %04x %04x %08x %08x\n",
ddbid.vendor, ddbid.device,
ddbid.subvendor, ddbid.subdevice,
ddbid.hw, ddbid.regmap);
#endif
if (dump) {
2020-01-22 09:58:13 +01:00
flashdump(ddb, linknr, dump, 128);
2015-08-05 17:22:42 +02:00
return 0;
}
if (!SectorSize)
return 0;
if (jump) {
uint32_t Jump = 0x200000;
BufferSize = SectorSize;
FlashOffset = FlashSize - SectorSize;
buffer = malloc(BufferSize);
if (!buffer) {
printf("out of memory\n");
return 0;
}
memset(buffer, 0xFF, BufferSize);
memset(&buffer[BufferSize - 256 + 0x10], 0x00, 16);
buffer[BufferSize - 256 + 0x10] = 0xbd;
buffer[BufferSize - 256 + 0x11] = 0xb3;
buffer[BufferSize - 256 + 0x12] = 0xc4;
buffer[BufferSize - 256 + 0x1a] = 0xfe;
buffer[BufferSize - 256 + 0x1e] = 0x03;
buffer[BufferSize - 256 + 0x1f] = ( ( Jump >> 16 ) & 0xFF );
buffer[BufferSize - 256 + 0x20] = ( ( Jump >> 8 ) & 0xFF );
buffer[BufferSize - 256 + 0x21] = ( ( Jump ) & 0xFF );
} else if (svid) {
BufferSize = SectorSize;
FlashOffset = 0;
buffer = malloc(BufferSize);
if (!buffer) {
printf("out of memory\n");
return 0;
}
memset(buffer,0xFF,BufferSize);
buffer[0] = ((svid >> 24 ) & 0xFF);
buffer[1] = ((svid >> 16 ) & 0xFF);
buffer[2] = ((svid >> 8 ) & 0xFF);
buffer[3] = ((svid ) & 0xFF);
} else {
int fh, i;
int fsize;
2020-01-18 16:23:09 +01:00
char *name;
2015-08-05 17:22:42 +02:00
2016-10-10 00:10:39 +02:00
if (!fname)
2020-01-18 16:23:09 +01:00
fname = devid2fname(ddbid.device, &name);
if (name)
printf("Card: %s\n", name);
2015-08-05 17:22:42 +02:00
fh = open(fname, O_RDONLY);
if (fh < 0 ) {
2016-10-10 00:10:39 +02:00
printf("File %s not found \n", fname);
2015-08-05 17:22:42 +02:00
return 0;
}
printf("Using bitstream %s\n", fname);
fsize = lseek(fh,0,SEEK_END);
2019-03-14 12:41:31 +01:00
if( fsize > FlashSize/2 - 0x10000 || fsize < SectorSize )
2015-08-05 17:22:42 +02:00
{
close(fh);
printf("Invalid File Size \n");
return 0;
}
if( Flash == ATMEL_AT45DB642D ) {
BlockErase = fsize >= 8192;
if( BlockErase )
BufferSize = (fsize + 8191) & ~8191;
else
BufferSize = (fsize + 1023) & ~1023;
} else {
BufferSize = (fsize + SectorSize - 1 ) & ~(SectorSize - 1);
}
printf(" Size %08x, target %08x\n", BufferSize, FlashOffset);
buffer = malloc(BufferSize);
if( buffer == NULL ) {
close(fh);
printf("out of memory\n");
return 0;
}
memset(buffer, 0xFF, BufferSize);
lseek(fh, 0, SEEK_SET);
read(fh, buffer, fsize);
close(fh);
if (BufferSize >= 0x10000) {
for(i = 0; i < 0x200; i += 1 ) {
if ( *(uint16_t *) (&buffer[i]) == 0xFFFF )
break;
buffer[i] = 0xFF;
}
}
}
if (!force && sure()<0)
return 0;
switch(Flash) {
case ATMEL_AT45DB642D:
err = FlashWriteAtmel(ddb,FlashOffset,buffer,BufferSize);
break;
case SSTI_SST25VF016B:
case SSTI_SST25VF032B:
err = FlashWriteSSTI_B(ddb,FlashOffset,buffer,BufferSize);
break;
case SSTI_SST25VF064C:
err = FlashWritePageMode(ddb,FlashOffset,buffer,BufferSize,0x3C);
break;
case SPANSION_S25FL116K:
2017-01-09 19:26:52 +01:00
case SPANSION_S25FL164K:
2019-01-10 17:48:00 +01:00
case WINBOND_W25Q16JV:
2022-03-22 15:22:43 +01:00
case WINBOND_W25Q32JV:
2015-08-05 17:22:42 +02:00
err = FlashWritePageMode(ddb,FlashOffset,buffer,BufferSize,0x1C);
break;
}
if (err < 0)
printf("Programming Error\n");
else
printf("Programming Done\n");
free(buffer);
return 0;
}