2020-01-18 16:23:09 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <getopt.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <linux/types.h>
|
|
|
|
|
|
|
|
#include "flash.h"
|
|
|
|
#include "flash.c"
|
|
|
|
|
|
|
|
static int verbose = 0;
|
|
|
|
|
2020-03-31 16:37:31 +02:00
|
|
|
static int yesno()
|
|
|
|
{
|
|
|
|
char c;
|
|
|
|
|
|
|
|
printf("\n\nNew firmware available\nReally flash now? y/n\n");
|
|
|
|
fflush(0);
|
|
|
|
c = getchar();
|
|
|
|
if (c!='y') {
|
|
|
|
printf("\nFlashing aborted.\n\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
printf("\nStarting to flash\n\n");
|
|
|
|
return 1;
|
|
|
|
}
|
2020-01-18 16:23:09 +01:00
|
|
|
|
|
|
|
static int update_flash(struct ddflash *ddf)
|
|
|
|
{
|
2020-09-17 09:55:48 +02:00
|
|
|
char *fname, *default_fname;
|
2020-01-18 16:23:09 +01:00
|
|
|
int res, stat = 0;
|
2020-09-17 09:55:48 +02:00
|
|
|
char *name = 0, *dname;
|
2020-01-18 16:23:09 +01:00
|
|
|
|
|
|
|
switch (ddf->id.device) {
|
|
|
|
case 0x300:
|
|
|
|
case 0x301:
|
|
|
|
case 0x302:
|
|
|
|
case 0x307:
|
|
|
|
if ((res = update_image(ddf, "/boot/bs.img", 0x4000, 0x1000, 0, 0)) == 1)
|
|
|
|
stat |= 4;
|
|
|
|
if ((res = update_image(ddf, "/boot/uboot.img", 0xb0000, 0xb0000, 0, 0)) == 1)
|
|
|
|
stat |= 2;
|
|
|
|
if (fexists("/config/gtl.enabled")) {
|
|
|
|
if ((res = update_image(ddf, "/config/fpga_gtl.img", 0x10000, 0xa0000, 1, 0)) == 1)
|
|
|
|
stat |= 1;
|
|
|
|
if (res == -1)
|
|
|
|
if ((res = update_image(ddf, "/boot/fpga_gtl.img", 0x10000, 0xa0000, 1, 0)) == 1)
|
|
|
|
stat |= 1;
|
|
|
|
} else if (fexists("/config/gtl.disabled")) {
|
|
|
|
if ((res = update_image(ddf, "/config/fpga.img", 0x10000, 0xa0000, 1, 0)) == 1)
|
|
|
|
stat |= 1;
|
|
|
|
if (res == -1)
|
|
|
|
if ((res = update_image(ddf, "/boot/fpga.img", 0x10000, 0xa0000, 1, 0)) == 1)
|
|
|
|
stat |= 1;
|
|
|
|
} else {
|
|
|
|
if (ddf->id.device == 0x0307) {
|
|
|
|
if (res == -1)
|
|
|
|
if ((res = update_image(ddf, "/config/fpga_gtl.img", 0x10000, 0xa0000, 1, 1)) == 1)
|
|
|
|
stat |= 1;
|
|
|
|
if (res == -1)
|
|
|
|
if ((res = update_image(ddf, "/boot/fpga_gtl.img", 0x10000, 0xa0000, 1, 1)) == 1)
|
|
|
|
stat |= 1;
|
|
|
|
} else {
|
|
|
|
if ((res = update_image(ddf, "/config/fpga.img", 0x10000, 0xa0000, 1, 1)) == 1)
|
|
|
|
stat |= 1;
|
|
|
|
if (res == -1)
|
|
|
|
if ((res = update_image(ddf, "/boot/fpga.img", 0x10000, 0xa0000, 1, 1)) == 1)
|
|
|
|
stat |= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#if 1
|
|
|
|
if ( (stat&1) && (ddf->id.hw & 0xffffff) <= 0x010001) {
|
|
|
|
if (ddf->id.device == 0x0307) {
|
|
|
|
if ((res = update_image(ddf, "/config/fpga_gtl.img", 0x160000, 0x80000, 1, 0)) == 1)
|
|
|
|
stat |= 1;
|
|
|
|
if (res == -1)
|
|
|
|
if ((res = update_image(ddf, "/boot/fpga_gtl.img", 0x160000, 0x80000, 1, 0)) == 1)
|
|
|
|
stat |= 1;
|
|
|
|
} else {
|
|
|
|
if ((res = update_image(ddf, "/config/fpga.img", 0x160000, 0x80000, 1, 0)) == 1)
|
|
|
|
stat |= 1;
|
|
|
|
if (res == -1)
|
|
|
|
if ((res = update_image(ddf, "/boot/fpga.img", 0x160000, 0x80000, 1, 0)) == 1)
|
|
|
|
stat |= 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
break;
|
|
|
|
case 0x320:
|
|
|
|
//fname="/boot/DVBNetV1A_DD01_0300.bit";
|
|
|
|
fname="/boot/fpga.img";
|
|
|
|
if ((res = update_image(ddf, fname, 0x10000, 0x100000, 1, 0)) == 1)
|
|
|
|
stat |= 1;
|
|
|
|
return stat;
|
|
|
|
break;
|
|
|
|
case 0x322:
|
|
|
|
//fname="/boot/DVBNetV1A_DD01_0300.bit";
|
|
|
|
fname="/boot/fpga.img";
|
|
|
|
if ((res = update_image(ddf, fname, 0x10000, 0x100000, 1, 0)) == 1)
|
|
|
|
stat |= 1;
|
|
|
|
return stat;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
fname = ddf->fname;
|
2020-09-17 09:55:48 +02:00
|
|
|
default_fname = devid2fname(ddf->id.device, &name);
|
2020-01-18 16:23:09 +01:00
|
|
|
if (!fname)
|
2020-09-17 09:55:48 +02:00
|
|
|
fname = default_fname;
|
2020-01-18 16:23:09 +01:00
|
|
|
if (name)
|
2020-12-01 15:51:13 +01:00
|
|
|
printf("Card: %s\n", name);
|
2020-01-22 09:58:13 +01:00
|
|
|
if (ddf->flash_name)
|
2020-12-01 15:51:13 +01:00
|
|
|
printf("Flash: %s\n", ddf->flash_name);
|
|
|
|
printf("Version: %08x\n", ddf->id.hw);
|
|
|
|
printf("REGMAP : %08x\n", ddf->id.regmap);
|
2021-03-10 21:38:19 +01:00
|
|
|
if ((res = update_image(ddf, fname, 0x10000, ddf->size / 2, 1, 0)) == 1)
|
2020-01-18 16:23:09 +01:00
|
|
|
stat |= 1;
|
|
|
|
return stat;
|
|
|
|
}
|
|
|
|
return stat;
|
|
|
|
}
|
|
|
|
|
2020-01-22 09:58:13 +01:00
|
|
|
static int update_link(struct ddflash *ddf)
|
2020-01-18 16:23:09 +01:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = flash_detect(ddf);
|
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
|
|
|
ret = update_flash(ddf);
|
|
|
|
|
|
|
|
if (ddf->buffer)
|
|
|
|
free(ddf->buffer);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2020-12-01 15:51:13 +01:00
|
|
|
static int update_card(int ddbnum, char *fname, int force)
|
2020-01-18 16:23:09 +01:00
|
|
|
{
|
|
|
|
struct ddflash ddf;
|
|
|
|
char ddbname[80];
|
|
|
|
struct ddb_id ddbid;
|
|
|
|
int ddb, ret, link, links;
|
|
|
|
|
|
|
|
sprintf(ddbname, "/dev/ddbridge/card%d", ddbnum);
|
|
|
|
ddb = open(ddbname, O_RDWR);
|
|
|
|
if (ddb < 0)
|
|
|
|
return -3;
|
|
|
|
ddf.fd = ddb;
|
|
|
|
ddf.link = 0;
|
|
|
|
ddf.fname = fname;
|
2020-12-01 15:51:13 +01:00
|
|
|
ddf.force = force;
|
2020-01-18 16:23:09 +01:00
|
|
|
links = 1;
|
|
|
|
|
|
|
|
for (link = 0; link < links; link++) {
|
|
|
|
ddf.link = link;
|
|
|
|
if (verbose >= 2)
|
|
|
|
printf("Get id card %u link %u\n", ddbnum, link);
|
|
|
|
ret = get_id(&ddf);
|
|
|
|
if (ret < 0)
|
|
|
|
goto out;
|
|
|
|
if (!link) {
|
|
|
|
switch (ddf.id.device) {
|
|
|
|
case 0x20:
|
|
|
|
links = 4;
|
|
|
|
break;
|
|
|
|
case 0x300:
|
|
|
|
case 0x301:
|
|
|
|
case 0x307:
|
2020-01-22 09:58:13 +01:00
|
|
|
links = 2;
|
2020-01-18 16:23:09 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//printf("%08x %08x\n", ddf.id.device, ddf.id.subdevice);
|
|
|
|
if (ddf.id.device) {
|
2020-01-22 09:58:13 +01:00
|
|
|
printf("\n\nUpdate card %s link %u:\n", ddbname, link);
|
|
|
|
ret = update_link(&ddf);
|
|
|
|
//if (ret < 0)
|
|
|
|
// break;
|
2020-01-18 16:23:09 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
close(ddb);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2020-03-31 16:37:31 +02:00
|
|
|
static int usage()
|
2020-01-22 09:58:13 +01:00
|
|
|
{
|
|
|
|
printf("ddupdate [OPTION]\n\n"
|
|
|
|
"-n N\n only update card N (default with N=0)\n\n"
|
|
|
|
"-a \n update all cards\n\n"
|
|
|
|
"-b file\n fpga image file override (ignored if -a is used)\n\n"
|
2021-02-24 20:12:54 +01:00
|
|
|
"-f \n force update\n\n"
|
2020-01-22 09:58:13 +01:00
|
|
|
"-v \n more verbose (up to -v -v -v)\n\n"
|
|
|
|
);
|
|
|
|
}
|
2020-01-18 16:23:09 +01:00
|
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
2020-12-01 15:51:13 +01:00
|
|
|
int ddbnum = -1, all = 0, i, force = 0, reboot_len = -1;
|
2020-01-18 16:36:16 +01:00
|
|
|
char *fname = 0;
|
2020-12-01 15:51:13 +01:00
|
|
|
int ret;
|
2020-01-18 16:23:09 +01:00
|
|
|
|
|
|
|
while (1) {
|
|
|
|
int option_index = 0;
|
|
|
|
int c;
|
|
|
|
static struct option long_options[] = {
|
2020-12-01 15:51:13 +01:00
|
|
|
{"reboot", optional_argument , NULL, 'r'},
|
2020-01-18 16:23:09 +01:00
|
|
|
{"help", no_argument , NULL, 'h'},
|
|
|
|
{0, 0, 0, 0}
|
|
|
|
};
|
|
|
|
c = getopt_long(argc, argv,
|
2020-12-01 15:51:13 +01:00
|
|
|
"n:havfb:r::",
|
2020-01-18 16:23:09 +01:00
|
|
|
long_options, &option_index);
|
|
|
|
if (c==-1)
|
|
|
|
break;
|
|
|
|
|
|
|
|
switch (c) {
|
|
|
|
case 'b':
|
|
|
|
fname = optarg;
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
ddbnum = strtol(optarg, NULL, 0);
|
|
|
|
break;
|
|
|
|
case 'a':
|
|
|
|
all = 1;
|
|
|
|
break;
|
2020-12-01 15:51:13 +01:00
|
|
|
case 'f':
|
|
|
|
force = 1;
|
|
|
|
break;
|
2020-01-18 16:23:09 +01:00
|
|
|
case 'v':
|
|
|
|
verbose++;
|
|
|
|
break;
|
2020-12-01 15:51:13 +01:00
|
|
|
case 'r':
|
|
|
|
if (optarg)
|
|
|
|
reboot_len = strtol(optarg, NULL, 0);
|
|
|
|
else
|
|
|
|
reboot_len = 40;
|
|
|
|
if (!reboot_len)
|
|
|
|
reboot(40);
|
|
|
|
break;
|
2020-01-18 16:23:09 +01:00
|
|
|
case 'h':
|
2020-01-22 09:58:13 +01:00
|
|
|
usage();
|
2021-02-24 20:13:24 +01:00
|
|
|
return 0;
|
2020-01-18 16:23:09 +01:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (optind < argc) {
|
|
|
|
printf("Warning: unused arguments\n");
|
|
|
|
}
|
2020-01-22 09:58:13 +01:00
|
|
|
if (!all && (ddbnum < 0)) {
|
|
|
|
printf("Select card number or all cards\n\n");
|
|
|
|
usage();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-01-18 16:23:09 +01:00
|
|
|
if (!all)
|
2020-12-01 15:51:13 +01:00
|
|
|
ret = update_card(ddbnum, fname, force);
|
|
|
|
else
|
|
|
|
for (i = 0; i < 100; i++) {
|
|
|
|
ret = update_card(i, 0, 0);
|
|
|
|
|
|
|
|
if (ret == -3) /* could not open, no more cards! */
|
|
|
|
break;
|
|
|
|
if (ret < 0)
|
|
|
|
return i; /* fatal error */
|
|
|
|
if (verbose >= 1)
|
|
|
|
printf("card %d up to date\n", i);
|
|
|
|
}
|
|
|
|
if (reboot_len > 0)
|
|
|
|
reboot(reboot_len);
|
2020-01-18 16:23:09 +01:00
|
|
|
return 0;
|
|
|
|
}
|