mirror of
git://projects.qi-hardware.com/xburst-tools.git
synced 2024-11-22 18:37:31 +02:00
Implemented ECC bypass in nread; implemented nerase
This commit is contained in:
parent
9f966656d4
commit
a821e6cf48
2
dump.scr
2
dump.scr
@ -1,6 +1,7 @@
|
|||||||
echo "Dumping script"
|
echo "Dumping script"
|
||||||
nquery 0
|
nquery 0
|
||||||
|
|
||||||
|
set NAND_IGNORE_ECC 1
|
||||||
set NAND_ECCPOS 3
|
set NAND_ECCPOS 3
|
||||||
rebuildcfg
|
rebuildcfg
|
||||||
boot
|
boot
|
||||||
@ -9,6 +10,7 @@ echo "Configured for bootloader IO!"
|
|||||||
|
|
||||||
ndump 0 0 64 "dump/nand.bin"
|
ndump 0 0 64 "dump/nand.bin"
|
||||||
|
|
||||||
|
set NAND_IGNORE_ECC
|
||||||
set NAND_ECCPOS 8
|
set NAND_ECCPOS 8
|
||||||
rebuildcfg
|
rebuildcfg
|
||||||
boot
|
boot
|
||||||
|
70
ingenic.c
70
ingenic.c
@ -104,11 +104,8 @@ static uint32_t ingenic_probe(void *usb_hndl) {
|
|||||||
magic[8] = 0;
|
magic[8] = 0;
|
||||||
|
|
||||||
for(int i = 0; magic_list[i].magic != NULL; i++)
|
for(int i = 0; magic_list[i].magic != NULL; i++)
|
||||||
if(strcmp(magic_list[i].magic, magic) == 0) {
|
if(strcmp(magic_list[i].magic, magic) == 0)
|
||||||
debug(LEVEL_DEBUG, "Magic: '%s', type: %08X\n", magic, magic_list[i].id);
|
|
||||||
|
|
||||||
return magic_list[i].id;
|
return magic_list[i].id;
|
||||||
}
|
|
||||||
|
|
||||||
debug(LEVEL_ERROR, "Unknown CPU: '%s'\n", magic);
|
debug(LEVEL_ERROR, "Unknown CPU: '%s'\n", magic);
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
@ -204,10 +201,6 @@ int ingenic_rebuild(void *hndl) {
|
|||||||
* (handle->cfg.bank_num + 1) * 2
|
* (handle->cfg.bank_num + 1) * 2
|
||||||
* (2 - handle->cfg.bus_width);
|
* (2 - handle->cfg.bus_width);
|
||||||
|
|
||||||
debug(LEVEL_DEBUG, "Firmware configuration dump:\n");
|
|
||||||
|
|
||||||
hexdump(&handle->cfg, sizeof(firmware_config_t));
|
|
||||||
|
|
||||||
handle->nand.cpuid = CPUID(handle->type);
|
handle->nand.cpuid = CPUID(handle->type);
|
||||||
|
|
||||||
NOPT("BUSWIDTH", bw, 1);
|
NOPT("BUSWIDTH", bw, 1);
|
||||||
@ -225,10 +218,6 @@ int ingenic_rebuild(void *hndl) {
|
|||||||
NOPT("WPPIN", wppin, 1);
|
NOPT("WPPIN", wppin, 1);
|
||||||
NOPT("BLOCKPERCHIP", bpc, 1);
|
NOPT("BLOCKPERCHIP", bpc, 1);
|
||||||
|
|
||||||
debug(LEVEL_DEBUG, "NAND configuration dump:\n");
|
|
||||||
|
|
||||||
hexdump(&handle->nand, sizeof(nand_config_t));
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,9 +239,6 @@ int ingenic_stage1_debugop(void *hndl, const char *filename, uint32_t op, uint32
|
|||||||
handle->cfg.debug.start = base;
|
handle->cfg.debug.start = base;
|
||||||
handle->cfg.debug.size = size;
|
handle->cfg.debug.size = size;
|
||||||
|
|
||||||
debug(LEVEL_DEBUG, "Debug configuration dump:\n");
|
|
||||||
hexdump(&handle->cfg, sizeof(firmware_config_t));
|
|
||||||
|
|
||||||
int ret = ingenic_loadstage(handle, INGENIC_STAGE1, filename);
|
int ret = ingenic_loadstage(handle, INGENIC_STAGE1, filename);
|
||||||
|
|
||||||
memset(&handle->cfg.debug, 0, sizeof(ingenic_stage1_debug_t));
|
memset(&handle->cfg.debug, 0, sizeof(ingenic_stage1_debug_t));
|
||||||
@ -398,8 +384,6 @@ int ingenic_configure_stage2(void *hndl) {
|
|||||||
if(ret == -1)
|
if(ret == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
debug(LEVEL_DEBUG, "Stage2 configured\n");
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -409,8 +393,6 @@ int ingenic_load_sdram(void *hndl, void *data, uint32_t base, uint32_t size) {
|
|||||||
while(size) {
|
while(size) {
|
||||||
int block = size > 65535 ? 65535 : size;
|
int block = size > 65535 ? 65535 : size;
|
||||||
|
|
||||||
debug(LEVEL_DEBUG, "Loading SDRAM from %p to 0x%08X, size %u\n", data, base, block);
|
|
||||||
|
|
||||||
if(ingenic_wordop(handle->usb, VR_SET_DATA_ADDRESS, base) == -1)
|
if(ingenic_wordop(handle->usb, VR_SET_DATA_ADDRESS, base) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -510,8 +492,6 @@ int ingenic_dump_nand(void *hndl, int cs, int start, int pages, int type, const
|
|||||||
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;
|
||||||
|
|
||||||
debug(LEVEL_DEBUG, "Ingenic: NAND dump: page size: %d bytes, pages in chunk: %d\n", page_size, chunk_pages);
|
|
||||||
|
|
||||||
FILE *dest = fopen(filename, "wb");
|
FILE *dest = fopen(filename, "wb");
|
||||||
|
|
||||||
if(dest == NULL)
|
if(dest == NULL)
|
||||||
@ -520,13 +500,13 @@ 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;
|
||||||
int bytes = chunk * page_size;
|
int bytes = chunk * page_size;
|
||||||
|
|
||||||
debug(LEVEL_DEBUG, "Ingenic: dumping NAND %d to file %s from page %d, size: %d bytes (%d pages)\n", cs, filename, start, bytes, chunk);
|
|
||||||
|
|
||||||
ret = ingenic_wordop(handle->usb, VR_SET_DATA_ADDRESS, start);
|
ret = ingenic_wordop(handle->usb, VR_SET_DATA_ADDRESS, start);
|
||||||
|
|
||||||
if(ret == -1)
|
if(ret == -1)
|
||||||
@ -549,21 +529,29 @@ int ingenic_dump_nand(void *hndl, int cs, int start, int pages, int type, const
|
|||||||
|
|
||||||
if(ret != bytes) {
|
if(ret != bytes) {
|
||||||
debug(LEVEL_ERROR, "Ingenic: NAND dump truncated: expected %d bytes, received %d\n", bytes, ret);
|
debug(LEVEL_ERROR, "Ingenic: NAND dump truncated: expected %d bytes, received %d\n", bytes, ret);
|
||||||
|
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
|
|
||||||
return -1;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t result[4];
|
uint16_t result[4];
|
||||||
|
|
||||||
|
|
||||||
ret = usbdev_recvbulk(handle->usb, result, sizeof(result));
|
ret = usbdev_recvbulk(handle->usb, result, sizeof(result));
|
||||||
|
|
||||||
if(ret == -1)
|
if(ret == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if(result[3] != 0 && !ignore_ecc) {
|
||||||
|
debug(LEVEL_ERROR, "Ingenic: ECC failure while reading NAND. See UART output for details\n");
|
||||||
|
|
||||||
|
errno = EIO;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
fwrite(iobuf, bytes, 1, dest);
|
fwrite(iobuf, bytes, 1, dest);
|
||||||
|
|
||||||
|
|
||||||
start += chunk;
|
start += chunk;
|
||||||
pages -= chunk;
|
pages -= chunk;
|
||||||
@ -573,4 +561,28 @@ int ingenic_dump_nand(void *hndl, int cs, int start, int pages, int type, const
|
|||||||
fclose(dest);
|
fclose(dest);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ingenic_erase_nand(void *hndl, int cs, int start, int blocks) {
|
||||||
|
HANDLE;
|
||||||
|
|
||||||
|
if(ingenic_wordop(handle->usb, VR_SET_DATA_ADDRESS, start) == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if(ingenic_wordop(handle->usb, VR_SET_DATA_LENGTH, blocks) == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if(ingenic_nandop(handle->usb, cs, NAND_ERASE, 0) == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
uint16_t result[4];
|
||||||
|
|
||||||
|
int ret = usbdev_recvbulk(handle->usb, result, sizeof(result));
|
||||||
|
|
||||||
|
if(ret == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
hexdump(result, ret);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -52,6 +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)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* debug args */
|
/* debug args */
|
||||||
@ -135,5 +136,6 @@ 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_erase_nand(void *hndl, int cs, int start, int blocks);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
BIN
usb_boot.bin
BIN
usb_boot.bin
Binary file not shown.
@ -23,12 +23,14 @@
|
|||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "ingenic.h"
|
#include "ingenic.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
static int usbboot_boot(int argc, char *argv[]);
|
static int usbboot_boot(int argc, char *argv[]);
|
||||||
static int usbboot_load(int argc, char *argv[]);
|
static int usbboot_load(int argc, char *argv[]);
|
||||||
static int usbboot_go(int argc, char *argv[]);
|
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[]);
|
||||||
|
|
||||||
const shell_command_t usbboot_cmdset[] = {
|
const shell_command_t usbboot_cmdset[] = {
|
||||||
|
|
||||||
@ -39,6 +41,7 @@ const shell_command_t usbboot_cmdset[] = {
|
|||||||
{ "nquery", "<DEVICE> - Query NAND information", usbboot_nquery },
|
{ "nquery", "<DEVICE> - Query NAND information", usbboot_nquery },
|
||||||
{ "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 },
|
||||||
|
|
||||||
{ NULL, NULL, NULL }
|
{ NULL, NULL, NULL }
|
||||||
};
|
};
|
||||||
@ -120,14 +123,29 @@ 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"))
|
||||||
|
type |= IGNORE_ECC;
|
||||||
|
|
||||||
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]);
|
||||||
|
|
||||||
if(ret == -1) {
|
if(ret == -1)
|
||||||
perror("ingenic_dump_nand");
|
perror("ingenic_dump_nand");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbboot_nerase(int argc, char *argv[]) {
|
||||||
|
if(argc != 4) {
|
||||||
|
printf("Usage: %s <DEVICE> <STARTBLOCK> <BLOCKS>\n", argv[0]);
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
int ret = ingenic_erase_nand(shell_device(), atoi(argv[1]), atoi(argv[2]), atoi(argv[3]));
|
||||||
|
|
||||||
|
if(ret == -1)
|
||||||
|
perror("ingenic_erase_nand");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user