From: chaoskagami Date: Sat, 4 Jun 2016 14:49:58 +0000 (-0400) Subject: Fix multiple bugs reported on GbaTemp. AGB and TWL are no longer required to boot... X-Git-Tag: stable-2 X-Git-Url: https://chaos.moe/g/?a=commitdiff_plain;h=acd129eb91c0fd9ab1a29fdc8d5a99a9b50ba26b;p=corbenik%2Fcorbenik.git Fix multiple bugs reported on GbaTemp. AGB and TWL are no longer required to boot and lack thereof shouldn't cause explosions. --- diff --git a/README.dev.txt b/README.dev.txt deleted file mode 100644 index 51c6310..0000000 --- a/README.dev.txt +++ /dev/null @@ -1,45 +0,0 @@ -Corbenik -============================== - -## This is the README intended for people looking at the code. If you're a user, read `README.user.md` instead. - -This is (yet another) CFW for the 3DS. Unlike other CFWs, this was mostly written from scratch and for fun. I'm a control freak, and this carries quite a bit of my mindset being a LFS/Gentoo user. - -Some parts are inherited from other CFWs - e.g. the firmware loading code in `src/firm` is mostly based on Cakes, and the patch bytecode is based on Luma3DS' implementation in C (though it isn't really derived from it.) - -Out of the bunch of CFWs in existence, Corbenik is most similar to cakes of the bunch, in that it uses external patches. External patches are headered, can have dependencies, and consist of a lightweight and specialized bytecode/assembly which is intended solely for effiecient patching. - -See `doc/bytecode.md`, `host/bytecode_asm.py` and `patch/*` for more on this. The assembler is a bit crappy at the moment, and I *do* plan to improve it. However, it outputs the correct code and gets the job done. - -## Rationale - -I was initially going to make cakes dynamic, but I quickly realized a fatal flaw in any "patch" format: what you can do from a patch is limited to what the parser handles. With Cakes, converting to a dynamic method isn't terribly difficult, but what about the patches that have a 'find, then seek backwards until' type of logic? Cakes would need have another construct to decribe that, and at that point, the .cake format has become a kludge. - -In my opinion, the best way to fix this was to externalize patches as programs - arm binaries or bytecode. The former didn't go so well (look back in the history of this repo. Fun times) and I ended up going with the latter. - -I also had a number of mad science experiments which would be very hard to perform in the context of ReiNAND based firmwares, and Cakes wouldn't make it easy either due to its limited patch format. - -## Comparison - -If you want to know how Corbenik sizes up to other CFWs as of NOW - see `doc/features.md`. I don't intend to sugarcoat - Corbenik is under development and is incomplete. There will be no stable release until a number of common features are implemented, such as emunand. - -However! It does have a few legs up on other CFWs, namely: - * Injection of arbitrary ARM11 services, including svcBackdoor. - * Bytecode patches? Bytecode patches. - * Not only corbenik, but the loader replacement uses them too. - * Loader can resize titles in memory and append code to segments. This isn't well tested, and it isn't enabled. - * Pretty much every simple patch that Luma3DS has, and most every patch for loader. - * All of the common bits aside from EmuNand, Reboot, and the exception vector hook, basically. - * Loader is STILL smaller than Nintendo's by two units. - * Loader is a little slower to boot than Cakes, and loader takes negligibly longer to load stuff. I may be able to optimize more, but at this point it is fast enough to not impact me. - -Feedback is welcome, but don't report anything obvious in nightlies. Corbenik is my day-to-day CFW now, so I'll run into the same bugs as you. - -For compilation instructions, see `doc/compiling.md`. - -Unless otherwise noted, everything original in this repo can be used under the terms of the GNU GPLv3 or later. This includes situations where there's no copyright header within a source file. I get lazy with those; assume everything can be used under the GPLv3. No source files within this repo bear questionable licenses, I make sure when it is introduced. - -## Quote of the Day - -Welcome to "The World." - diff --git a/host/copy.sh b/host/copy.sh index 84ce86b..6837bb4 100755 --- a/host/copy.sh +++ b/host/copy.sh @@ -12,6 +12,7 @@ mount ${dev}1 $mnt || exit 0 cp out/arm9loaderhax.bin $mnt/anim/boot/none.bin || exit 0 cp out/arm9loaderhax.bin $mnt/anim/boot/r.bin || exit 0 cp out/arm9loaderhax.bin $mnt/anim/boot/l.bin || exit 0 +rm -rf $mnt/corbenik cp -r out/corbenik $mnt/ || exit 0 cp -r input/corbenik $mnt/ || exit 0 umount $mnt || exit 0 diff --git a/source/firm/firm.c b/source/firm/firm.c index dc6b53d..b0b0687 100644 --- a/source/firm/firm.c +++ b/source/firm/firm.c @@ -30,7 +30,7 @@ slot0x11key96_init() // 9.6 crypto may need us to get the key from somewhere else. // Unless the console already has the key initialized, that is. uint8_t key[AES_BLOCK_SIZE]; - if (read_file(key, PATH_SLOT0X11KEY96, AES_BLOCK_SIZE) || read_file(key, PATH_ALT_SLOT0X11KEY96, AES_BLOCK_SIZE)) { + if (read_file(key, PATH_SLOT0X11KEY96, AES_BLOCK_SIZE) != 0 || read_file(key, PATH_ALT_SLOT0X11KEY96, AES_BLOCK_SIZE) != 0) { // Read key successfully. aes_setkey(0x11, key, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL); @@ -148,7 +148,7 @@ load_firm(firm_h *dest, char *path, char *path_firmkey, uint32_t *size, uint64_t int status = 0; int firmware_changed = 0; - if (read_file(dest, path, *size)) { + if (read_file(dest, path, *size) == 0) { fprintf(BOTTOM_SCREEN, "!"); // Only whine about this if it's NATIVE_FIRM, which is important. @@ -158,9 +158,10 @@ load_firm(firm_h *dest, char *path, char *path_firmkey, uint32_t *size, uint64_t "This is fatal. Aborting.\n"); } - status = 1; - goto exit_error; - } + return 1; + } else { + fprintf(BOTTOM_SCREEN, "l"); + } // Check and decrypt FIRM if it is encrypted. if (dest->magic != FIRM_MAGIC) { @@ -169,8 +170,7 @@ load_firm(firm_h *dest, char *path, char *path_firmkey, uint32_t *size, uint64_t if (firm_title == NATIVE_FIRM_TITLEID) { fprintf(BOTTOM_SCREEN, "\nFailed to decrypt firmware.\n" "This is fatal. Aborting.\n"); - status = 1; - goto exit_error; + return 1; } } firmware_changed = 1; // Decryption performed. @@ -199,8 +199,7 @@ load_firm(firm_h *dest, char *path, char *path_firmkey, uint32_t *size, uint64_t fprintf(BOTTOM_SCREEN, "\nCouldn't decrypt ARM9 FIRM binary.\n" "Check if you have the needed key at:\n" " " PATH_SLOT0X11KEY96 "\n"); - status = 1; - goto exit_error; + return 1; } firmware_changed = 1; // Decryption of arm9bin performed. } else { @@ -238,10 +237,6 @@ load_firm(firm_h *dest, char *path, char *path_firmkey, uint32_t *size, uint64_t } return 0; - -exit_error: - - return status; } // FAIR WARNING; This function is arm11 code, not ARM9. @@ -347,33 +342,40 @@ int firm_loaded = 0; int load_firms() { + int state = 0; + if (firm_loaded) return 0; fprintf(BOTTOM_SCREEN, "FIRM load triggered.\n"); fprintf(BOTTOM_SCREEN, "NATIVE_FIRM\n ["); - if (load_firm(firm_loc, PATH_NATIVE_F, PATH_NATIVE_FIRMKEY, &firm_size, NATIVE_FIRM_TITLEID) != 0) - return 1; + if (load_firm(firm_loc, PATH_NATIVE_F, PATH_NATIVE_FIRMKEY, &firm_size, NATIVE_FIRM_TITLEID) != 0) { + abort("]\n Failed to load NATIVE_FIRM.\n"); + } find_proc9(firm_loc, &firm_proc9, &firm_p9_exefs); fprintf(BOTTOM_SCREEN, "]\nTWL_FIRM\n ["); - if (load_firm(twl_firm_loc, PATH_TWL_F, PATH_TWL_FIRMKEY, &twl_firm_size, TWL_FIRM_TITLEID)) - fprintf(BOTTOM_SCREEN, " \nTWL_FIRM failed to load.\n"); - else + if (load_firm(twl_firm_loc, PATH_TWL_F, PATH_TWL_FIRMKEY, &twl_firm_size, TWL_FIRM_TITLEID) != 0) { + fprintf(BOTTOM_SCREEN, "]\n TWL_FIRM failed to load.\n"); + state =1; + } else { + fprintf(stderr, "]\n"); find_proc9(twl_firm_loc, &twl_firm_proc9, &twl_firm_p9_exefs); + } - fprintf(BOTTOM_SCREEN, "]\nAGB_FIRM\n ["); - if (load_firm(agb_firm_loc, PATH_AGB_F, PATH_AGB_FIRMKEY, &agb_firm_size, AGB_FIRM_TITLEID)) - fprintf(BOTTOM_SCREEN, " \nAGB_FIRM failed to load.\n"); - else + fprintf(BOTTOM_SCREEN, "AGB_FIRM\n ["); + if (load_firm(agb_firm_loc, PATH_AGB_F, PATH_AGB_FIRMKEY, &agb_firm_size, AGB_FIRM_TITLEID) != 0) { + fprintf(BOTTOM_SCREEN, "]\n AGB_FIRM failed to load.\n"); + state = 1; + } else { + fprintf(stderr, "]\n"); find_proc9(agb_firm_loc, &agb_firm_proc9, &agb_firm_p9_exefs); - - fprintf(BOTTOM_SCREEN, "]\n"); + } firm_loaded = 1; // Loaded. - return 0; + return state; } void diff --git a/source/firm/version.c b/source/firm/version.c index db96b37..fd1d858 100644 --- a/source/firm/version.c +++ b/source/firm/version.c @@ -71,16 +71,20 @@ struct firm_signature firm_signatures[] = { .version = 0x00, .version_string = "9.0.0_AGB", .console = console_n3ds }, - {.version = 0xFF } // Terminate list + {.version = 0xFF, + .version_string = "Not found" } // Terminate list }; struct firm_signature * get_firm_info(firm_h *firm) { - for (struct firm_signature *signature = firm_signatures; signature->version != 0xFF; signature++) { + for (struct firm_signature *signature = firm_signatures; ; signature++) { if (memcmp(signature->sig, firm->section[0].hash, 0x10) == 0) { return signature; } + if (signature->version == 0xFF) { + return signature; // Error. Not found, invalid, etc. + } } return NULL; diff --git a/source/interp.c b/source/interp.c index 9489369..6f68b1e 100644 --- a/source/interp.c +++ b/source/interp.c @@ -367,6 +367,10 @@ execb(char *filename, int build_cache) // Read patch to scrap memory. FILE *f = fopen(filename, "r"); + if (!f) { + // File wasn't found. The user didn't enable anything. + return 0; + } size_t len = fsize(f); fread((uint8_t *)FCRAM_PATCH_LOC, 1, len, f); fclose(f); diff --git a/source/menu.c b/source/menu.c index ba49161..fbacc46 100644 --- a/source/menu.c +++ b/source/menu.c @@ -151,12 +151,18 @@ int list_patches_build_back(char* fpath, int desc_is_path) { void list_patches_build(char* name, int desc_is_fname) { current_menu_index_patches = 0; + memset(enable_list, 0, FCRAM_SPACING / 2); + char fpath[256]; strncpy(fpath, name, 256); list_patches_build_back(fpath, desc_is_fname); patches[current_menu_index_patches].index = -1; - read_file(enable_list, PATH_TEMP "/PATCHENABLE", FCRAM_SPACING / 2); + FILE* f; + if ((f = fopen(PATH_TEMP "/PATCHENABLE", "r"))) { + fread(enable_list, 1, FCRAM_SPACING / 2, f); + fclose(f); + } } int show_menu(struct options_s *options, uint8_t* toggles); @@ -207,7 +213,8 @@ menu_info() " Version: %s (%x)\n" "TWL_FIRM / DSi Firmware:\n" " Version: %s (%x)\n", - native->version_string, native->version, agb->version_string, agb->version, twl->version_string, twl->version); + native->version_string, native->version, agb->version_string, agb->version, twl->version_string, twl->version); + wait_key(); need_redraw = 1; diff --git a/source/std/fs.c b/source/std/fs.c index 627056b..5c85a3f 100644 --- a/source/std/fs.c +++ b/source/std/fs.c @@ -108,6 +108,9 @@ fopen(const char *filename, const char *mode) void fclose(FILE *fp) { + if (!fp->is_open) + return; + f_close(&(fp->handle)); memset(fp, 0, sizeof(FILE)); @@ -116,6 +119,9 @@ fclose(FILE *fp) void fseek(FILE *fp, int64_t offset, int whence) { + if (!fp->is_open) + return; + uint32_t fixed_offset; switch (whence) { case SEEK_SET: @@ -137,44 +143,56 @@ fseek(FILE *fp, int64_t offset, int whence) size_t ftell(FILE *fp) { + if (!fp->is_open) + return 0; + return f_tell(&(fp->handle)); } int feof(FILE *fp) { + if (!fp->is_open) + return 0; + return f_eof(&(fp->handle)); } size_t fsize(FILE *fp) { + if (!fp->is_open) + return 0; + return f_size(&(fp->handle)); } size_t fwrite(const void *buffer, size_t elementSize, size_t elementCnt, FILE *fp) { + if (!fp->is_open) + return 0; + UINT br; if (f_write(&(fp->handle), buffer, elementSize * elementCnt, &br)) return 0; - if (br == elementSize * elementCnt) + if (elementSize != 1) br /= elementSize; - else - return 0; return br; } size_t fread(void *buffer, size_t elementSize, size_t elementCnt, FILE *fp) { - UINT br; + if (!fp->is_open) + return 0; + + size_t br; if (f_read(&(fp->handle), buffer, elementSize * elementCnt, &br)) return 0; - if (br == elementSize * elementCnt) + + if (elementSize != 1) br /= elementSize; - else - return 0; return br; } @@ -183,7 +201,7 @@ write_file(void *data, char *path, size_t size) { FILE *temp = fopen(path, "w"); - if (!temp) + if (!temp || !temp->is_open) return 0; size_t wrote = fwrite(data, 1, size, temp); @@ -198,7 +216,7 @@ read_file(void *data, char *path, size_t size) { FILE *temp = fopen(path, "r"); - if (!temp) + if (!temp || !temp->is_open) return 0; size_t read = fread(data, 1, size, temp);