diff --git a/dump.scr b/dump.scr new file mode 100644 index 0000000..2e30689 --- /dev/null +++ b/dump.scr @@ -0,0 +1,23 @@ +echo "Dumping script" +nquery 0 + +set NAND_ECCPOS 3 +rebuildcfg +boot + +echo "Configured for bootloader IO!" + +ndump 0 0 64 "dump/nand.bin" + +set NAND_ECCPOS 8 +rebuildcfg +boot + +echo "Configuration restored" + +ndump 0 128 66 "dump/loader.bin" +ndump 0 256 1 "dump/def_boot.bin" +ndump 0 512 3061 "dump/img_boot.bin" +ndump 0 8192 8192 "dump/minios.bin" +ndump 0 32768 32768 "dump/res.bin" + diff --git a/ingenic.c b/ingenic.c index 68946b3..b3ac770 100644 --- a/ingenic.c +++ b/ingenic.c @@ -504,4 +504,73 @@ int ingenic_query_nand(void *hndl, int cs, nand_info_t *info) { return 0; } +int ingenic_dump_nand(void *hndl, int cs, int start, int pages, 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; + + debug(LEVEL_DEBUG, "Ingenic: NAND dump: page size: %d bytes, pages in chunk: %d\n", page_size, chunk_pages); + + FILE *dest = fopen(filename, "wb"); + + if(dest == NULL) + return -1; + + void *iobuf = malloc(chunk_pages * page_size); + + int ret = 0; + + while(pages > 0) { + int chunk = pages < chunk_pages ? pages : chunk_pages; + 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); + + 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_READ, type); + + if(ret == -1) + break; + + int ret = usbdev_recvbulk(handle->usb, iobuf, bytes); + + if(ret == -1) + return -1; + + if(ret != bytes) { + debug(LEVEL_ERROR, "Ingenic: NAND dump truncated: expected %d bytes, received %d\n", bytes, ret); + + errno = EIO; + + return -1; + } + + uint32_t result[4]; + + ret = usbdev_recvbulk(handle->usb, result, sizeof(result)); + + if(ret == -1) + return -1; + + fwrite(iobuf, bytes, 1, dest); + + + start += chunk; + pages -= chunk; + } + + free(iobuf); + fclose(dest); + + return ret; +} \ No newline at end of file diff --git a/ingenic.h b/ingenic.h index c7563eb..ae10ea8 100644 --- a/ingenic.h +++ b/ingenic.h @@ -32,6 +32,8 @@ #define STAGE2_CODESIZE 0x400000 #define SDRAM_BASE 0x80000000 +#define STAGE2_IOBUF (2048 * 128) + #define DS_flash_info 0 #define DS_hand 1 @@ -47,6 +49,10 @@ #define NAND_PROGRAM 7 #define NAND_READ_TO_RAM 8 +#define OOB_ECC 0 +#define OOB_NO_ECC 1 +#define NO_OOB 2 + typedef struct { /* debug args */ uint8_t debug_ops; @@ -128,5 +134,6 @@ int ingenic_load_sdram_file(void *hndl, uint32_t base, const char *filename); int ingenic_go(void *hndl, uint32_t address); 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); #endif diff --git a/usbboot_cmdset.c b/usbboot_cmdset.c index 75dbd7a..0827a6a 100644 --- a/usbboot_cmdset.c +++ b/usbboot_cmdset.c @@ -28,6 +28,7 @@ static int usbboot_boot(int argc, char *argv[]); static int usbboot_load(int argc, char *argv[]); static int usbboot_go(int argc, char *argv[]); static int usbboot_nquery(int argc, char *argv[]); +static int usbboot_ndump(int argc, char *argv[]); const shell_command_t usbboot_cmdset[] = { @@ -36,7 +37,9 @@ const shell_command_t usbboot_cmdset[] = { { "go", "
- Jump to
", usbboot_go }, { "nquery", " - Query NAND information", usbboot_nquery }, - + { "ndump", " - Dump NAND to file", usbboot_ndump }, + { "ndump_oob", " - Dump NAND with OOB to file", usbboot_ndump }, + { NULL, NULL, NULL } }; @@ -108,3 +111,23 @@ static int usbboot_nquery(int argc, char *argv[]) { return 0; } +static int usbboot_ndump(int argc, char *argv[]) { + if(argc != 5) { + printf("Usage: %s \n", argv[0]); + + return -1; + } + + int type = strcmp(argv[0], "ndump_oob") ? NO_OOB : OOB_ECC; + + int ret = ingenic_dump_nand(shell_device(), atoi(argv[1]), atoi(argv[2]), atoi(argv[3]), type, argv[4]); + + if(ret == -1) { + perror("ingenic_dump_nand"); + + return -1; + } + + return 0; +} +