summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAidan MacDonald <amachronic@protonmail.com>2022-03-19 14:07:55 +0000
committerAidan MacDonald <amachronic@protonmail.com>2022-03-24 23:40:07 +0000
commit0d21d80ca8fc5f287eeb12ca67cc070b55ab46fa (patch)
treedc0c0106353708e1ac0e9df851c7fe4d85d91d3f
parentee68d9df8e6b53476bb3bce8a024da60f9310a8b (diff)
downloadrockbox-0d21d80ca8fc5f287eeb12ca67cc070b55ab46fa.tar.gz
rockbox-0d21d80ca8fc5f287eeb12ca67cc070b55ab46fa.zip
x1000: bootloader: add basic flash dump utility
Change-Id: Id4ce0f00a78ef27399bdef6a7b32c23f89b9cb05
-rw-r--r--bootloader/x1000/utils.c78
-rw-r--r--bootloader/x1000/x1000bootloader.h5
2 files changed, 83 insertions, 0 deletions
diff --git a/bootloader/x1000/utils.c b/bootloader/x1000/utils.c
index b8f86c3ed1..1b56bdf50a 100644
--- a/bootloader/x1000/utils.c
+++ b/bootloader/x1000/utils.c
@@ -172,3 +172,81 @@ int load_uimage_flash(uint32_t addr, uint32_t length,
return handle;
}
+
+int dump_flash(int fd, uint32_t addr, uint32_t length)
+{
+ static char buf[8192];
+ int ret = 0;
+
+ nand_drv* ndrv = nand_init();
+ nand_lock(ndrv);
+
+ ret = nand_open(ndrv);
+ if(ret != NAND_SUCCESS) {
+ splashf(5*HZ, "NAND open failed\n");
+ nand_unlock(ndrv);
+ return ret;
+ }
+
+ while(length > 0) {
+ uint32_t count = MIN(length, sizeof(buf));
+ ret = nand_read_bytes(ndrv, addr, count, buf);
+ if(ret != NAND_SUCCESS) {
+ splashf(5*HZ, "Dump failed\nNAND I/O error");
+ goto out;
+ }
+
+ if(write(fd, buf, count) != (ssize_t)count) {
+ splashf(5*HZ, "Dump failed\nFile I/O error");
+ ret = -1;
+ goto out;
+ }
+
+ length -= count;
+ addr += count;
+ }
+
+ out:
+ nand_close(ndrv);
+ nand_unlock(ndrv);
+ return ret;
+}
+
+int dump_flash_file(const char* file, uint32_t addr, uint32_t length)
+{
+ if(check_disk(true) != DISK_PRESENT)
+ return -1;
+
+ splashf(0, "Dumping...\n%s\n0x%08lx\n%lu bytes", file, addr, length);
+
+ int fd = open(file, O_WRONLY|O_CREAT|O_TRUNC);
+ if(fd < 0) {
+ splashf(5*HZ, "Cannot open file\n%s", file);
+ return -2;
+ }
+
+ int rc = dump_flash(fd, addr, length);
+ if(rc < 0) {
+ close(fd);
+ remove(file);
+ return -3;
+ }
+
+ splashf(5*HZ, "Dumped\n%s", file);
+ close(fd);
+ return 0;
+}
+
+void dump_of_player(void)
+{
+#ifdef OF_PLAYER_ADDR
+ dump_flash_file("/of_player.img", OF_PLAYER_ADDR, OF_PLAYER_LENGTH);
+#endif
+}
+
+void dump_of_recovery(void)
+{
+#ifdef OF_RECOVERY_ADDR
+ dump_flash_file("/of_recovery.img", OF_RECOVERY_ADDR, OF_RECOVERY_LENGTH);
+#endif
+}
diff --git a/bootloader/x1000/x1000bootloader.h b/bootloader/x1000/x1000bootloader.h
index 0309421ced..a7c9927f1b 100644
--- a/bootloader/x1000/x1000bootloader.h
+++ b/bootloader/x1000/x1000bootloader.h
@@ -167,6 +167,11 @@ int load_uimage_file(const char* filename,
int load_uimage_flash(uint32_t addr, uint32_t length,
struct uimage_header* uh, size_t* sizep);
+int dump_flash(int fd, uint32_t addr, uint32_t length);
+int dump_flash_file(const char* file, uint32_t addr, uint32_t length);
+void dump_of_player(void);
+void dump_of_recovery(void);
+
void recovery_menu(void) __attribute__((noreturn));
#endif /* __X1000BOOTLOADER_H__ */