From 7df879d346dda28d8dc793ddb2a56e1013355227 Mon Sep 17 00:00:00 2001 From: TuxSH Date: Tue, 8 May 2018 18:46:54 +0200 Subject: [PATCH] Change the allocation logic in stratosphere.c --- fusee/fusee-secondary/src/kip.h | 9 +- fusee/fusee-secondary/src/package2.c | 10 ++- fusee/fusee-secondary/src/stratosphere.c | 107 +++++++++++++---------- fusee/fusee-secondary/src/stratosphere.h | 5 +- 4 files changed, 76 insertions(+), 55 deletions(-) diff --git a/fusee/fusee-secondary/src/kip.h b/fusee/fusee-secondary/src/kip.h index b0e9a5711..08e2a680f 100644 --- a/fusee/fusee-secondary/src/kip.h +++ b/fusee/fusee-secondary/src/kip.h @@ -14,7 +14,7 @@ typedef struct { uint32_t size; uint32_t num_processes; uint32_t _0xC; - unsigned char kip_data[]; + uint8_t kip_data[]; } ini1_header_t; typedef struct { @@ -35,13 +35,12 @@ typedef struct { uint8_t flags; kip_section_header_t section_headers[6]; uint32_t capabilities[0x20]; - unsigned char data[]; + uint8_t data[]; } kip1_header_t; -static inline uint64_t kip1_get_size_from_header(kip1_header_t *header) { +static inline size_t kip1_get_size_from_header(kip1_header_t *header) { /* Header + .text + .rodata + .rwdata */ return 0x100 + header->section_headers[0].compressed_size + header->section_headers[1].compressed_size + header->section_headers[2].compressed_size; } - -#endif \ No newline at end of file +#endif diff --git a/fusee/fusee-secondary/src/package2.c b/fusee/fusee-secondary/src/package2.c index 25fb24877..19fef1d81 100644 --- a/fusee/fusee-secondary/src/package2.c +++ b/fusee/fusee-secondary/src/package2.c @@ -233,11 +233,19 @@ void package2_patch_kernel(void) { void package2_patch_ini1(void) { /* TODO: Do we want to support loading another INI from sd:/whatever/INI1.bin? */ ini1_header_t *inis_to_merge[STRATOSPHERE_INI1_MAX] = {0}; + ini1_header_t *merged; + inis_to_merge[STRATOSPHERE_INI1_EMBEDDED] = stratosphere_get_ini1(); inis_to_merge[STRATOSPHERE_INI1_PACKAGE2] = (ini1_header_t *)g_package2_sections[PACKAGE2_SECTION_INI1]; /* Merge all of the INI1s. */ - g_patched_package2_header->metadata.section_sizes[PACKAGE2_SECTION_INI1] = stratosphere_merge_inis(g_package2_sections[PACKAGE2_SECTION_INI1], inis_to_merge, STRATOSPHERE_INI1_MAX); + merged = stratosphere_merge_inis(inis_to_merge, STRATOSPHERE_INI1_MAX); + memcpy(g_package2_sections[PACKAGE2_SECTION_INI1], merged, merged->size); + g_patched_package2_header->metadata.section_sizes[PACKAGE2_SECTION_INI1] = merged->size; + + /* Free temporary buffers. */ + free(merged); + stratosphere_free_ini1(); } void package2_fixup_header_and_section_hashes(void) { diff --git a/fusee/fusee-secondary/src/stratosphere.c b/fusee/fusee-secondary/src/stratosphere.c index e592d110d..a1023ebc8 100644 --- a/fusee/fusee-secondary/src/stratosphere.c +++ b/fusee/fusee-secondary/src/stratosphere.c @@ -6,74 +6,84 @@ #include "stratosphere.h" #include "sd_utils.h" -static uint8_t *g_stratosphere_ini1; -static bool g_initialized_stratosphere_ini1 = false; - -static uint8_t *g_ini1_buffer; - -void stratosphere_allocate_mem(void) { - /* TODO call it*/ - g_stratosphere_ini1 = (uint8_t *)malloc(PACKAGE2_SIZE_MAX); - g_ini1_buffer = (uint8_t *)malloc(PACKAGE2_SIZE_MAX); -} - -void stratosphere_free_mem(void) { - /* TODO call it*/ - free(g_stratosphere_ini1); - free(g_ini1_buffer); -} +static ini1_header_t *g_stratosphere_ini1 = NULL; ini1_header_t *stratosphere_get_ini1(void) { - ini1_header_t *ini1_header = (ini1_header_t *)g_stratosphere_ini1; - if (g_initialized_stratosphere_ini1) { - return ini1_header; + if (g_stratosphere_ini1 != NULL) { + return g_stratosphere_ini1; } - ini1_header->magic = MAGIC_INI1; - ini1_header->size = sizeof(ini1_header_t); - ini1_header->num_processes = 0; - ini1_header->_0xC = 0; + + size_t size = 0; /* TODO */ + g_stratosphere_ini1 = (ini1_header_t *)malloc(size); + + if (g_stratosphere_ini1 != NULL) { + printf("Error: stratosphere_get_ini1: out of memory!\n"); + generic_panic(); + } + + g_stratosphere_ini1->magic = MAGIC_INI1; + g_stratosphere_ini1->size = sizeof(ini1_header_t); + g_stratosphere_ini1->num_processes = 0; + g_stratosphere_ini1->_0xC = 0; /* TODO: When we have processes, copy them into ini1_header->kip_data here. */ - g_initialized_stratosphere_ini1 = true; - return ini1_header; + return g_stratosphere_ini1; +} + +void stratosphere_free_ini1(void) { + free(g_stratosphere_ini1); + g_stratosphere_ini1 = NULL; } /* Merges some number of INI1s into a single INI1. It's assumed that the INIs are in order of preference. */ -size_t stratosphere_merge_inis(void *dst, ini1_header_t **inis, unsigned int num_inis) { +ini1_header_t *stratosphere_merge_inis(ini1_header_t **inis, size_t num_inis) { char sd_path[0x100] = {0}; + uint32_t total_num_processes = 0; + /* Validate all ini headers. */ - for (unsigned int i = 0; i < num_inis; i++) { + for (size_t i = 0; i < num_inis; i++) { if (inis[i] == NULL || inis[i]->magic != MAGIC_INI1 || inis[i]->num_processes > INI1_MAX_KIPS) { printf("Error: INI1s[%d] section appears to not contain an INI1!\n", i); generic_panic(); + } else { + total_num_processes += inis[i]->num_processes; } } - uint64_t process_list[INI1_MAX_KIPS] = {0}; + if (total_num_processes > INI1_MAX_KIPS) { + printf("Error: The resulting INI1 would have too many KIPs!\n"); + generic_panic(); + } + + uint64_t process_list[INI1_MAX_KIPS] = {0}; + ini1_header_t *merged = (ini1_header_t *)malloc(PACKAGE2_SIZE_MAX); /* because of SD file overrides */ + + if (merged == NULL) { + printf("Error: stratosphere_merge_inis: out of memory!\n"); + generic_panic(); + } - memset(g_ini1_buffer, 0, PACKAGE2_SIZE_MAX); - ini1_header_t *merged = (ini1_header_t *)g_ini1_buffer; merged->magic = MAGIC_INI1; merged->num_processes = 0; merged->_0xC = 0; size_t remaining_size = PACKAGE2_SIZE_MAX - sizeof(ini1_header_t); + size_t read_size; unsigned char *current_dst_kip = merged->kip_data; /* Actually merge into the inis. */ - for (unsigned int i = 0; i < num_inis; i++) { - uint64_t offset = 0; - for (unsigned int p = 0; p < inis[i]->num_processes; p++) { + for (size_t i = 0; i < num_inis; i++) { + size_t offset = 0; + for (size_t p = 0; p < (size_t)inis[i]->num_processes; p++) { kip1_header_t *current_kip = (kip1_header_t *)(inis[i]->kip_data + offset); if (current_kip->magic != MAGIC_KIP1) { - printf("Error: INI1s[%d][%d] appears not to be a KIP1!\n", i, p); + printf("Error: INI1s[%zu][%zu] appears not to be a KIP1!\n", i, p); generic_panic(); } - bool already_loaded = false; - for (unsigned int j = 0; j < merged->num_processes; j++) { + for (uint32_t j = 0; j < merged->num_processes; j++) { if (process_list[j] == current_kip->title_id) { already_loaded = true; break; @@ -84,23 +94,29 @@ size_t stratosphere_merge_inis(void *dst, ini1_header_t **inis, unsigned int num } /* TODO: What folder should these be read out of? */ - snprintf(sd_path, sizeof(sd_path), "atmosphere/titles/%016llx/%016llx.kip", current_kip->title_id, current_kip->title_id); + snprintf(sd_path, sizeof(sd_path), "atmosphere/titles/%016llX/%016llX.kip", current_kip->title_id, current_kip->title_id); /* Try to load an override KIP from SD, if possible. */ - if (read_sd_file(current_dst_kip, remaining_size, sd_path)) { + read_size = read_sd_file(current_dst_kip, remaining_size, sd_path); + if (read_size != 0) { kip1_header_t *sd_kip = (kip1_header_t *)(current_dst_kip); - if (sd_kip->magic != MAGIC_KIP1) { + if (read_size < sizeof(kip1_header_t) || sd_kip->magic != MAGIC_KIP1) { printf("Error: %s is not a KIP1?\n", sd_path); generic_panic(); } else if (sd_kip->title_id != current_kip->title_id) { printf("Error: %s has wrong Title ID!\n", sd_path); generic_panic(); } - uint64_t sd_kip_size = kip1_get_size_from_header(sd_kip); - remaining_size -= sd_kip_size; - current_dst_kip += sd_kip_size; + size_t expected_sd_kip_size = kip1_get_size_from_header(sd_kip); + if (expected_sd_kip_size != read_size) { + printf("Error: %s has wrong size or there is not enough space (expected 0x%zx, read 0x%zx)!\n", + sd_path, expected_sd_kip_size, read_size); + generic_panic(); + } + remaining_size -= expected_sd_kip_size; + current_dst_kip += expected_sd_kip_size; } else { - uint64_t current_kip_size = kip1_get_size_from_header(current_kip); + size_t current_kip_size = kip1_get_size_from_header(current_kip); if (current_kip_size > remaining_size) { printf("Error: Not enough space for all the KIP1s!\n"); generic_panic(); @@ -115,8 +131,5 @@ size_t stratosphere_merge_inis(void *dst, ini1_header_t **inis, unsigned int num } merged->size = sizeof(ini1_header_t) + (uint32_t)(current_dst_kip - merged->kip_data); - /* Copy merged INI1 to destination. */ - memcpy(dst, merged, merged->size); - - return merged->size; + return merged; } diff --git a/fusee/fusee-secondary/src/stratosphere.h b/fusee/fusee-secondary/src/stratosphere.h index 89160b688..399b699ec 100644 --- a/fusee/fusee-secondary/src/stratosphere.h +++ b/fusee/fusee-secondary/src/stratosphere.h @@ -9,7 +9,8 @@ #define STRATOSPHERE_INI1_MAX 0x2 ini1_header_t *stratosphere_get_ini1(void); +void stratosphere_free_ini1(void); -size_t stratosphere_merge_inis(void *dst, ini1_header_t **inis, unsigned int num_inis); +ini1_header_t *stratosphere_merge_inis(ini1_header_t **inis, unsigned int num_inis); -#endif \ No newline at end of file +#endif