More actions
Horizon nand-dumper | |
---|---|
General | |
Author | asdfaaasssdddfff |
Type | PC Utilities |
Version | 2018 |
License | MIT License |
Last Updated | 2018/09/15 |
Links | |
Source Only Download | |
Website | |
An open source tool which dumps the nand from horizon, similar to what reinx-toolbox does.
It's mostly a direct port of this pegaswitch-script.
It will dump boot0+1, prodinfo and the rawnand to the root of the sdcard, automatically splitting the file if on a fat32-sdcard (source below).
Warning: This may or may not result in a corrupted backup, the author takes no responsibility whatsoever for bricks. If you want a proper backup use hekate which has proper backup-verification.
#include <string.h> #include <stdlib.h> #include <stdio.h> #include <sys/statvfs.h> #include <unistd.h> #include <switch.h> #define MIN(x, y) (((x) < (y)) ? (x) : (y)) /* This is basically a port of this pegaswitch-script: https://github.com/reswitched/pegaswitch/blob/master/usefulscripts/DumpBIS.js */ int partitionIds[] = {0, 10, 27, 20}; char *partitionNames[] = {"BOOT0", "BOOT1", "PRODINFO", "rawnand"}; #define BufSize 0x500000 long GetAvailableSpace(const char *path) { struct statvfs stat; if (statvfs(path, &stat) != 0) { // error happens, just quits here return -1; } // the available size is f_bsize * f_bavail return stat.f_bsize * stat.f_bavail; } int dumpPartition(int partitionIndex) { printf("\n%s\n", partitionNames[partitionIndex]); int id = partitionIds[partitionIndex]; char *buffer = malloc(BufSize); FsStorage partition; fsOpenBisStorage(&partition, id); u64 size = 0; fsStorageGetSize(&partition, &size); if (GetAvailableSpace("/") < size) { consoleClear(); fsStorageClose(&partition); printf("Not enough space left on the sd!\n"); while (appletMainLoop()) { hidScanInput(); u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO); if (kDown & KEY_PLUS) break; gfxFlushBuffers(); gfxSwapBuffers(); } return -1; } int file_num = 0; char filename[100]; sprintf(filename, "/%s.bin", partitionNames[partitionIndex]); FILE *partitionfile = fopen(filename, "wb"); u64 curPos = 0; bool isFat32 = false; // dump loop while (appletMainLoop()) { u64 readSize = MIN(size - curPos, BufSize); if (readSize == 0) break; fsStorageRead(&partition, curPos, buffer, readSize); u64 sucessfullyWriten = fwrite(buffer, 1, readSize, partitionfile); curPos += sucessfullyWriten; if (sucessfullyWriten < readSize) { fclose(partitionfile); // Filesystem doesn't support big files if(!isFat32) { char oldFilename[100]; strcpy(oldFilename, filename); sprintf(filename, "/%s_%d.bin", partitionNames[partitionIndex], file_num++); rename(oldFilename, filename); isFat32 = true; } sprintf(filename, "/%s_%d.bin", partitionNames[partitionIndex], file_num++); partitionfile = fopen(filename, "wb"); } printf("\r%lu/%lu", curPos, size); gfxFlushBuffers(); gfxSwapBuffers(); } fclose(partitionfile); fsStorageClose(&partition); free(buffer); return 0; } int main(int argc, char **argv) { gfxInitDefault(); consoleInit(NULL); printf("ATTENTION, DO NOT USE THIS AS YOUR PRIMARY BACKUP!\n"); printf("I'm serious: I'll not be responsible for any bricks because of this!\n"); printf("Press + if you want to continue\n"); while (appletMainLoop()) { hidScanInput(); u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO); if (kDown & KEY_PLUS) break; gfxFlushBuffers(); gfxSwapBuffers(); } consoleClear(); for (int i = 0; i < (sizeof(partitionIds) / sizeof(int)); i++) { if(dumpPartition(i) != 0) return 0; } printf("\nDump complete!\nPress + to exit"); while (appletMainLoop()) { hidScanInput(); u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO); if (kDown & KEY_PLUS) break; gfxFlushBuffers(); gfxSwapBuffers(); } gfxExit(); return 0; }