mirror of
git://projects.qi-hardware.com/xburst-tools.git
synced 2024-11-22 23:58:05 +02:00
Implemented nprogram (USE WITH CARE!)
This commit is contained in:
parent
a821e6cf48
commit
8dbb1401fd
8
dump.scr
8
dump.scr
@ -1,16 +1,18 @@
|
|||||||
echo "Dumping script"
|
echo "Dumping script"
|
||||||
nquery 0
|
nquery 0
|
||||||
|
|
||||||
set NAND_IGNORE_ECC 1
|
#set NAND_RAW 1
|
||||||
set NAND_ECCPOS 3
|
set NAND_ECCPOS 3
|
||||||
rebuildcfg
|
rebuildcfg
|
||||||
boot
|
boot
|
||||||
|
|
||||||
echo "Configured for bootloader IO!"
|
echo "Configured for bootloader IO!"
|
||||||
|
|
||||||
ndump 0 0 64 "dump/nand.bin"
|
ndump_oob 0 0 128 "dump/nand.bin"
|
||||||
|
|
||||||
set NAND_IGNORE_ECC
|
exit
|
||||||
|
|
||||||
|
set NAND_RAW
|
||||||
set NAND_ECCPOS 8
|
set NAND_ECCPOS 8
|
||||||
rebuildcfg
|
rebuildcfg
|
||||||
boot
|
boot
|
||||||
|
85
ingenic.c
85
ingenic.c
@ -489,6 +489,9 @@ int ingenic_query_nand(void *hndl, int cs, nand_info_t *info) {
|
|||||||
int ingenic_dump_nand(void *hndl, int cs, int start, int pages, int type, const char *filename) {
|
int ingenic_dump_nand(void *hndl, int cs, int start, int pages, int type, const char *filename) {
|
||||||
HANDLE;
|
HANDLE;
|
||||||
|
|
||||||
|
int raw = type & NAND_RAW;
|
||||||
|
type &= ~NAND_RAW;
|
||||||
|
|
||||||
int page_size = (handle->nand.nand_ps + (type == NO_OOB ? 0 : handle->nand.nand_os));
|
int page_size = (handle->nand.nand_ps + (type == NO_OOB ? 0 : handle->nand.nand_os));
|
||||||
int chunk_pages = STAGE2_IOBUF / page_size;
|
int chunk_pages = STAGE2_IOBUF / page_size;
|
||||||
|
|
||||||
@ -500,8 +503,6 @@ int ingenic_dump_nand(void *hndl, int cs, int start, int pages, int type, const
|
|||||||
void *iobuf = malloc(chunk_pages * page_size);
|
void *iobuf = malloc(chunk_pages * page_size);
|
||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int ignore_ecc = type & IGNORE_ECC;
|
|
||||||
type &= ~IGNORE_ECC;
|
|
||||||
|
|
||||||
while(pages > 0) {
|
while(pages > 0) {
|
||||||
int chunk = pages < chunk_pages ? pages : chunk_pages;
|
int chunk = pages < chunk_pages ? pages : chunk_pages;
|
||||||
@ -517,7 +518,7 @@ int ingenic_dump_nand(void *hndl, int cs, int start, int pages, int type, const
|
|||||||
if(ret == -1)
|
if(ret == -1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ret = ingenic_nandop(handle->usb, cs, NAND_READ, type);
|
ret = ingenic_nandop(handle->usb, cs, raw ? NAND_READ_RAW : NAND_READ, type);
|
||||||
|
|
||||||
if(ret == -1)
|
if(ret == -1)
|
||||||
break;
|
break;
|
||||||
@ -543,7 +544,7 @@ int ingenic_dump_nand(void *hndl, int cs, int start, int pages, int type, const
|
|||||||
if(ret == -1)
|
if(ret == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if(result[3] != 0 && !ignore_ecc) {
|
if(result[3] != 0 && !raw) {
|
||||||
debug(LEVEL_ERROR, "Ingenic: ECC failure while reading NAND. See UART output for details\n");
|
debug(LEVEL_ERROR, "Ingenic: ECC failure while reading NAND. See UART output for details\n");
|
||||||
|
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
@ -586,3 +587,79 @@ int ingenic_erase_nand(void *hndl, int cs, int start, int blocks) {
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ingenic_program_nand(void *hndl, int cs, int start, int type, const char *filename) {
|
||||||
|
HANDLE;
|
||||||
|
|
||||||
|
int page_size = (handle->nand.nand_ps + (type == NO_OOB ? 0 : handle->nand.nand_os));
|
||||||
|
int chunk_pages = STAGE2_IOBUF / page_size;
|
||||||
|
|
||||||
|
FILE *in = fopen(filename, "rb");
|
||||||
|
|
||||||
|
if(in == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
fseek(in, 0, SEEK_END);
|
||||||
|
int file_size = ftell(in);
|
||||||
|
fseek(in, 0, SEEK_SET);
|
||||||
|
|
||||||
|
int pages = file_size / page_size;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
void *iobuf = malloc(chunk_pages * page_size);
|
||||||
|
|
||||||
|
debug(LEVEL_INFO, "Programming %d pages from %d (%d bytes, %d bytes/page)\n", pages, start, file_size, page_size);
|
||||||
|
|
||||||
|
while(pages > 0) {
|
||||||
|
int chunk = pages < chunk_pages ? pages : chunk_pages;
|
||||||
|
int bytes = chunk * page_size;
|
||||||
|
|
||||||
|
debug(LEVEL_DEBUG, "Writing %d pages from %d\n", chunk, start);
|
||||||
|
|
||||||
|
ret = fread(iobuf, 1, bytes, in);
|
||||||
|
|
||||||
|
if(ret != bytes) {
|
||||||
|
debug(LEVEL_ERROR, "fread: %d\n", ret);
|
||||||
|
|
||||||
|
ret = -1;
|
||||||
|
errno = EIO;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(usbdev_sendbulk(handle->usb, iobuf, bytes) == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = ingenic_wordop(handle->usb, VR_SET_DATA_ADDRESS, start);
|
||||||
|
|
||||||
|
if(ret == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
ret = ingenic_wordop(handle->usb, VR_SET_DATA_LENGTH, chunk);
|
||||||
|
|
||||||
|
if(ret == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
ret = ingenic_nandop(handle->usb, cs, NAND_PROGRAM, type);
|
||||||
|
|
||||||
|
if(ret == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
uint16_t result[4];
|
||||||
|
|
||||||
|
ret = usbdev_recvbulk(handle->usb, result, sizeof(result));
|
||||||
|
|
||||||
|
if(ret == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
hexdump(result, ret);
|
||||||
|
|
||||||
|
start += chunk;
|
||||||
|
pages -= chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(iobuf);
|
||||||
|
fclose(in);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@ -52,7 +52,7 @@
|
|||||||
#define OOB_ECC 0
|
#define OOB_ECC 0
|
||||||
#define OOB_NO_ECC 1
|
#define OOB_NO_ECC 1
|
||||||
#define NO_OOB 2
|
#define NO_OOB 2
|
||||||
#define IGNORE_ECC (1 << 7)
|
#define NAND_RAW (1 << 7)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* debug args */
|
/* debug args */
|
||||||
@ -136,6 +136,7 @@ int ingenic_go(void *hndl, uint32_t address);
|
|||||||
|
|
||||||
int ingenic_query_nand(void *hndl, int cs, nand_info_t *info);
|
int ingenic_query_nand(void *hndl, int cs, nand_info_t *info);
|
||||||
int ingenic_dump_nand(void *hndl, int cs, int start, int pages, int type, const char *filename);
|
int ingenic_dump_nand(void *hndl, int cs, int start, int pages, int type, const char *filename);
|
||||||
|
int ingenic_program_nand(void *hndl, int cs, int start, int type, const char *filename);
|
||||||
int ingenic_erase_nand(void *hndl, int cs, int start, int blocks);
|
int ingenic_erase_nand(void *hndl, int cs, int start, int blocks);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,6 +31,7 @@ static int usbboot_go(int argc, char *argv[]);
|
|||||||
static int usbboot_nquery(int argc, char *argv[]);
|
static int usbboot_nquery(int argc, char *argv[]);
|
||||||
static int usbboot_ndump(int argc, char *argv[]);
|
static int usbboot_ndump(int argc, char *argv[]);
|
||||||
static int usbboot_nerase(int argc, char *argv[]);
|
static int usbboot_nerase(int argc, char *argv[]);
|
||||||
|
static int usbboot_nprogram(int argc, char *argv[]);
|
||||||
|
|
||||||
const shell_command_t usbboot_cmdset[] = {
|
const shell_command_t usbboot_cmdset[] = {
|
||||||
|
|
||||||
@ -42,6 +43,8 @@ const shell_command_t usbboot_cmdset[] = {
|
|||||||
{ "ndump", "<DEVICE> <STARTPAGE> <PAGES> <FILE> - Dump NAND to file", usbboot_ndump },
|
{ "ndump", "<DEVICE> <STARTPAGE> <PAGES> <FILE> - Dump NAND to file", usbboot_ndump },
|
||||||
{ "ndump_oob", "<DEVICE> <STARTPAGE> <PAGES> <FILE> - Dump NAND with OOB to file", usbboot_ndump },
|
{ "ndump_oob", "<DEVICE> <STARTPAGE> <PAGES> <FILE> - Dump NAND with OOB to file", usbboot_ndump },
|
||||||
{ "nerase", "<DEVICE> <STARTBLOCK> <BLOCKS> - Erase NAND blocks", usbboot_nerase },
|
{ "nerase", "<DEVICE> <STARTBLOCK> <BLOCKS> - Erase NAND blocks", usbboot_nerase },
|
||||||
|
{ "nprogram", "<DEVICE> <STARTPAGE> <FILE> - Program NAND from file", usbboot_nprogram },
|
||||||
|
{ "nprogram_oob", "<DEVICE> <STARTPAGE> <FILE> - Program NAND with OOB from file", usbboot_nprogram },
|
||||||
|
|
||||||
{ NULL, NULL, NULL }
|
{ NULL, NULL, NULL }
|
||||||
};
|
};
|
||||||
@ -123,8 +126,8 @@ static int usbboot_ndump(int argc, char *argv[]) {
|
|||||||
|
|
||||||
int type = strcmp(argv[0], "ndump_oob") ? NO_OOB : OOB_ECC;
|
int type = strcmp(argv[0], "ndump_oob") ? NO_OOB : OOB_ECC;
|
||||||
|
|
||||||
if(cfg_getenv("NAND_IGNORE_ECC"))
|
if(cfg_getenv("NAND_RAW"))
|
||||||
type |= IGNORE_ECC;
|
type |= NAND_RAW;
|
||||||
|
|
||||||
int ret = ingenic_dump_nand(shell_device(), atoi(argv[1]), atoi(argv[2]), atoi(argv[3]), type, argv[4]);
|
int ret = ingenic_dump_nand(shell_device(), atoi(argv[1]), atoi(argv[2]), atoi(argv[3]), type, argv[4]);
|
||||||
|
|
||||||
@ -149,3 +152,28 @@ static int usbboot_nerase(int argc, char *argv[]) {
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int usbboot_nprogram(int argc, char *argv[]) {
|
||||||
|
if(argc != 4) {
|
||||||
|
printf("Usage: %s <DEVICE> <STARTPAGE> <FILE>\n", argv[0]);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int type = strcmp(argv[0], "nprogram_oob") ? NO_OOB : OOB_ECC;
|
||||||
|
|
||||||
|
if(strcmp(argv[0], "nprogram_oob") == 0) {
|
||||||
|
if(cfg_getenv("NAND_RAW"))
|
||||||
|
type = OOB_ECC;
|
||||||
|
else
|
||||||
|
type = OOB_NO_ECC;
|
||||||
|
} else
|
||||||
|
type = NO_OOB;
|
||||||
|
|
||||||
|
int ret = ingenic_program_nand(shell_device(), atoi(argv[1]), atoi(argv[2]), type, argv[3]);
|
||||||
|
|
||||||
|
if(ret == -1)
|
||||||
|
perror("ingenic_program_nand");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user