mirror of
				https://github.com/Atmosphere-NX/Atmosphere.git
				synced 2025-10-31 19:25:46 +01:00 
			
		
		
		
	fusee: Greatly simplify and improve KIP loading
This commit is contained in:
		
							parent
							
								
									49f627bb28
								
							
						
					
					
						commit
						bfa5847e48
					
				| @ -283,6 +283,7 @@ static ini1_header_t *package2_rebuild_ini1(ini1_header_t *ini1, uint32_t target | ||||
|     ini1_header_t *inis_to_merge[STRATOSPHERE_INI1_MAX] = {0}; | ||||
|     ini1_header_t *merged; | ||||
| 
 | ||||
|     inis_to_merge[STRATOSPHERE_INI1_SDFILES]  = stratosphere_get_sd_files_ini1(); | ||||
|     inis_to_merge[STRATOSPHERE_INI1_EMBEDDED] = stratosphere_get_ini1(target_firmware); | ||||
|     inis_to_merge[STRATOSPHERE_INI1_PACKAGE2] = ini1; | ||||
| 
 | ||||
|  | ||||
| @ -17,11 +17,13 @@ | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <stdint.h> | ||||
| #include <dirent.h> | ||||
| #include "exocfg.h" | ||||
| #include "utils.h" | ||||
| #include "package2.h" | ||||
| #include "stratosphere.h" | ||||
| #include "fs_utils.h" | ||||
| #include "lib/log.h" | ||||
| 
 | ||||
| #define u8 uint8_t | ||||
| #define u32 uint32_t | ||||
| @ -34,6 +36,7 @@ | ||||
| #undef u32 | ||||
| 
 | ||||
| static ini1_header_t *g_stratosphere_ini1 = NULL; | ||||
| static ini1_header_t *g_sd_files_ini1 = NULL; | ||||
| 
 | ||||
| static bool g_stratosphere_loader_enabled = true; | ||||
| static bool g_stratosphere_sm_enabled = true; | ||||
| @ -137,13 +140,111 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) { | ||||
| } | ||||
| 
 | ||||
| void stratosphere_free_ini1(void) { | ||||
|     free(g_stratosphere_ini1); | ||||
|     g_stratosphere_ini1 = NULL; | ||||
|     if (g_stratosphere_ini1 != NULL) { | ||||
|         free(g_stratosphere_ini1); | ||||
|         g_stratosphere_ini1 = NULL; | ||||
|     } | ||||
|     if (g_sd_files_ini1 != NULL) { | ||||
|         free(g_sd_files_ini1); | ||||
|         g_sd_files_ini1 = NULL; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| static void try_add_sd_kip(ini1_header_t *ini1, const char *kip_path) { | ||||
|     size_t file_size = get_file_size(kip_path); | ||||
|      | ||||
|     if (ini1->size + file_size > PACKAGE2_SIZE_MAX) { | ||||
|         fatal_error("Failed to load %s: INI1 would be too large!\n", kip_path); | ||||
|     } | ||||
|      | ||||
|     kip1_header_t kip_header; | ||||
|     if (read_from_file(&kip_header, sizeof(kip_header), kip_path) != sizeof(kip_header) || kip_header.magic != MAGIC_KIP1) { | ||||
|         return; | ||||
|     } | ||||
|      | ||||
|     size_t kip_size = kip1_get_size_from_header(&kip_header); | ||||
|     if (kip_size > file_size) { | ||||
|         fatal_error("Failed to load %s: KIP size is corrupt!\n", kip_path); | ||||
|     } | ||||
|      | ||||
|     if (read_from_file(ini1->kip_data + ini1->size - sizeof(ini1_header_t), kip_size, kip_path) != kip_size) { | ||||
|         /* TODO: is this error fatal? */ | ||||
|         return; | ||||
|     } | ||||
|      | ||||
|     ini1->size += kip_size; | ||||
|     ini1->num_processes++; | ||||
| } | ||||
| 
 | ||||
| ini1_header_t *stratosphere_get_sd_files_ini1(void) {     | ||||
|     if (g_sd_files_ini1 != NULL) { | ||||
|         return g_sd_files_ini1; | ||||
|     } | ||||
|      | ||||
|     /* Allocate space. */ | ||||
|     g_sd_files_ini1 = (ini1_header_t *)malloc(PACKAGE2_SIZE_MAX); | ||||
|     g_sd_files_ini1->magic = MAGIC_INI1; | ||||
|     g_sd_files_ini1->size = sizeof(ini1_header_t); | ||||
|     g_sd_files_ini1->num_processes = 0; | ||||
|     g_sd_files_ini1->_0xC = 0; | ||||
|      | ||||
|     /* Load all kips from /atmosphere/kips/<*>.kip or /atmosphere/kips/<*>/<*>.kip. */ | ||||
|     DIR *kips_dir = opendir("atmosphere/kips"); | ||||
|     struct dirent *ent; | ||||
|     if (kips_dir != NULL) { | ||||
|         while ((ent = readdir(kips_dir)) != NULL) { | ||||
|             if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) { | ||||
|                 continue; | ||||
|             } | ||||
|              | ||||
|             char kip_path[0x301] = {0}; | ||||
|             snprintf(kip_path, 0x300, "atmosphere/kips/%s", ent->d_name); | ||||
|              | ||||
|             struct stat kip_stat; | ||||
|             if (stat(kip_path, &kip_stat) == -1) { | ||||
|                 continue; | ||||
|             } | ||||
|              | ||||
|             if ((kip_stat.st_mode & S_IFMT) == S_IFREG) { | ||||
|                 /* If file, add to ini1. */ | ||||
|                 try_add_sd_kip(g_sd_files_ini1, kip_path); | ||||
|             } else if ((kip_stat.st_mode & S_IFMT) == S_IFDIR) { | ||||
|                 /* Otherwise, allow one level of nesting. */ | ||||
|                 DIR *sub_dir = opendir(kip_path); | ||||
|                 struct dirent *sub_ent; | ||||
|                 if (sub_dir != NULL) { | ||||
|                     while ((sub_ent = readdir(sub_dir)) != NULL) { | ||||
|                         if (strcmp(sub_ent->d_name, ".") == 0 || strcmp(sub_ent->d_name, "..") == 0) { | ||||
|                             continue; | ||||
|                         } | ||||
|                          | ||||
|                         /* Reuse kip path variable. */ | ||||
|                         memset(kip_path, 0, sizeof(kip_path)); | ||||
|                         snprintf(kip_path, 0x300, "atmosphere/kips/%s/%s", ent->d_name, sub_ent->d_name); | ||||
|                          | ||||
|                         if (stat(kip_path, &kip_stat) == -1) { | ||||
|                             continue; | ||||
|                         } | ||||
|                          | ||||
|                         if ((kip_stat.st_mode & S_IFMT) == S_IFREG) { | ||||
|                             /* If file, add to ini1. */ | ||||
|                             try_add_sd_kip(g_sd_files_ini1, kip_path); | ||||
|                         } | ||||
|                     } | ||||
|                     closedir(sub_dir); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         closedir(kips_dir); | ||||
|     } | ||||
|      | ||||
|     return g_sd_files_ini1; | ||||
| } | ||||
| 
 | ||||
| /* Merges some number of INI1s into a single INI1. It's assumed that the INIs are in order of preference. */ | ||||
| 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. */ | ||||
| @ -170,7 +271,6 @@ ini1_header_t *stratosphere_merge_inis(ini1_header_t **inis, size_t num_inis) { | ||||
|     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; | ||||
| 
 | ||||
| @ -196,34 +296,13 @@ ini1_header_t *stratosphere_merge_inis(ini1_header_t **inis, size_t num_inis) { | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             /* 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); | ||||
| 
 | ||||
|             /* Try to load an override KIP from SD, if possible. */ | ||||
|             read_size = read_from_file(current_dst_kip, remaining_size, sd_path); | ||||
|             if (read_size != 0) { | ||||
|                 kip1_header_t *sd_kip = (kip1_header_t *)(current_dst_kip); | ||||
|                 if (read_size < sizeof(kip1_header_t) || sd_kip->magic != MAGIC_KIP1) { | ||||
|                     fatal_error("%s is not a KIP1?\n", sd_path); | ||||
|                 } else if (sd_kip->title_id != current_kip->title_id) { | ||||
|                     fatal_error("%s has wrong Title ID!\n", sd_path); | ||||
|                 } | ||||
|                 size_t expected_sd_kip_size = kip1_get_size_from_header(sd_kip); | ||||
|                 if (expected_sd_kip_size != read_size) { | ||||
|                     fatal_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); | ||||
|                 } | ||||
|                 remaining_size -= expected_sd_kip_size; | ||||
|                 current_dst_kip += expected_sd_kip_size; | ||||
|             } else { | ||||
|                 size_t current_kip_size = kip1_get_size_from_header(current_kip); | ||||
|                 if (current_kip_size > remaining_size) { | ||||
|                     fatal_error("Not enough space for all the KIP1s!\n"); | ||||
|                 } | ||||
|                 memcpy(current_dst_kip, current_kip, current_kip_size); | ||||
|                 remaining_size -= current_kip_size; | ||||
|                 current_dst_kip += current_kip_size; | ||||
|             size_t current_kip_size = kip1_get_size_from_header(current_kip); | ||||
|             if (current_kip_size > remaining_size) { | ||||
|                 fatal_error("Not enough space for all the KIP1s!\n"); | ||||
|             } | ||||
|             memcpy(current_dst_kip, current_kip, current_kip_size); | ||||
|             remaining_size -= current_kip_size; | ||||
|             current_dst_kip += current_kip_size; | ||||
| 
 | ||||
|             process_list[merged->num_processes++] = current_kip->title_id; | ||||
|         } | ||||
|  | ||||
| @ -20,11 +20,13 @@ | ||||
| #include "utils.h" | ||||
| #include "kip.h" | ||||
| 
 | ||||
| #define STRATOSPHERE_INI1_EMBEDDED 0x0 | ||||
| #define STRATOSPHERE_INI1_PACKAGE2 0x1 | ||||
| #define STRATOSPHERE_INI1_MAX      0x2 | ||||
| #define STRATOSPHERE_INI1_SDFILES  0x0 | ||||
| #define STRATOSPHERE_INI1_EMBEDDED 0x1 | ||||
| #define STRATOSPHERE_INI1_PACKAGE2 0x2 | ||||
| #define STRATOSPHERE_INI1_MAX      0x3 | ||||
| 
 | ||||
| ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware); | ||||
| ini1_header_t *stratosphere_get_sd_files_ini1(void); | ||||
| void stratosphere_free_ini1(void); | ||||
| 
 | ||||
| ini1_header_t *stratosphere_merge_inis(ini1_header_t **inis, unsigned int num_inis); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user