1 // Copyright 2017 Citra Emulator Project
2 // Licensed under GPLv2 or any later version
3 // Refer to the license.txt file included.
4 
5 #pragma once
6 
7 #include <cstddef>
8 #include <memory>
9 #include <string>
10 #include <vector>
11 #include "common/bit_field.h"
12 #include "common/common_types.h"
13 #include "common/file_util.h"
14 #include "common/swap.h"
15 #include "core/core.h"
16 #include "core/file_sys/romfs_reader.h"
17 
18 enum NCSDContentIndex { Main = 0, Manual = 1, DLP = 2, New3DSUpdate = 6, Update = 7 };
19 
20 struct NCSD_Partitions {
21     u32 offset;
22     u32 size;
23 };
24 
25 struct NCSD_Header {
26     u8 signature[0x100];
27     u32_le magic;
28     u32_le media_size;
29     u8 media_id[8];
30     u8 partition_fs_type[8];
31     u8 partition_crypt_type[8];
32     NCSD_Partitions partitions[8];
33     u8 extended_header_hash[0x20];
34     u32_le additional_header_size;
35     u32_le sector_zero_offset;
36     u8 partition_flags[8];
37     u8 partition_id_table[0x40];
38     u8 reserved[0x30];
39 };
40 
41 static_assert(sizeof(NCSD_Header) == 0x200, "NCCH header structure size is wrong");
42 
43 ////////////////////////////////////////////////////////////////////////////////////////////////////
44 /// NCCH header (Note: "NCCH" appears to be a publicly unknown acronym)
45 
46 struct NCCH_Header {
47     u8 signature[0x100];
48     u32_le magic;
49     u32_le content_size;
50     u8 partition_id[8];
51     u16_le maker_code;
52     u16_le version;
53     u8 reserved_0[4];
54     u64_le program_id;
55     u8 reserved_1[0x10];
56     u8 logo_region_hash[0x20];
57     u8 product_code[0x10];
58     u8 extended_header_hash[0x20];
59     u32_le extended_header_size;
60     u8 reserved_2[4];
61     u8 reserved_flag[3];
62     u8 secondary_key_slot;
63     u8 platform;
64     enum class ContentType : u8 {
65         Application = 0,
66         SystemUpdate = 1,
67         Manual = 2,
68         Child = 3,
69         Trial = 4,
70     };
71     union {
72         BitField<0, 1, u8> is_data;
73         BitField<1, 1, u8> is_executable;
74         BitField<2, 3, ContentType> content_type;
75     };
76     u8 content_unit_size;
77     union {
78         BitField<0, 1, u8> fixed_key;
79         BitField<1, 1, u8> no_romfs;
80         BitField<2, 1, u8> no_crypto;
81         BitField<5, 1, u8> seed_crypto;
82     };
83     u32_le plain_region_offset;
84     u32_le plain_region_size;
85     u32_le logo_region_offset;
86     u32_le logo_region_size;
87     u32_le exefs_offset;
88     u32_le exefs_size;
89     u32_le exefs_hash_region_size;
90     u8 reserved_3[4];
91     u32_le romfs_offset;
92     u32_le romfs_size;
93     u32_le romfs_hash_region_size;
94     u8 reserved_4[4];
95     u8 exefs_super_block_hash[0x20];
96     u8 romfs_super_block_hash[0x20];
97 };
98 
99 static_assert(sizeof(NCCH_Header) == 0x200, "NCCH header structure size is wrong");
100 
101 ////////////////////////////////////////////////////////////////////////////////////////////////////
102 // ExeFS (executable file system) headers
103 
104 struct ExeFs_SectionHeader {
105     char name[8];
106     u32 offset;
107     u32 size;
108 };
109 
110 struct ExeFs_Header {
111     ExeFs_SectionHeader section[8];
112     u8 reserved[0x80];
113     u8 hashes[8][0x20];
114 };
115 
116 ////////////////////////////////////////////////////////////////////////////////////////////////////
117 // ExHeader (executable file system header) headers
118 
119 struct ExHeader_SystemInfoFlags {
120     u8 reserved[5];
121     u8 flag;
122     u8 remaster_version[2];
123 };
124 
125 struct ExHeader_CodeSegmentInfo {
126     u32 address;
127     u32 num_max_pages;
128     u32 code_size;
129 };
130 
131 struct ExHeader_CodeSetInfo {
132     u8 name[8];
133     ExHeader_SystemInfoFlags flags;
134     ExHeader_CodeSegmentInfo text;
135     u32 stack_size;
136     ExHeader_CodeSegmentInfo ro;
137     u8 reserved[4];
138     ExHeader_CodeSegmentInfo data;
139     u32 bss_size;
140 };
141 
142 struct ExHeader_DependencyList {
143     u8 program_id[0x30][8];
144 };
145 
146 struct ExHeader_SystemInfo {
147     u64 save_data_size;
148     u64_le jump_id;
149     u8 reserved_2[0x30];
150 };
151 
152 struct ExHeader_StorageInfo {
153     union {
154         u64_le ext_save_data_id;
155         // When using extended savedata access
156         // Prefer the ID specified in the most significant bits
157         BitField<40, 20, u64> extdata_id3;
158         BitField<20, 20, u64> extdata_id4;
159         BitField<0, 20, u64> extdata_id5;
160     };
161     u8 system_save_data_id[8];
162     union {
163         u64_le storage_accessible_unique_ids;
164         // When using extended savedata access
165         // Prefer the ID specified in the most significant bits
166         BitField<40, 20, u64> extdata_id0;
167         BitField<20, 20, u64> extdata_id1;
168         BitField<0, 20, u64> extdata_id2;
169     };
170     u8 access_info[7];
171     u8 other_attributes;
172 };
173 
174 struct ExHeader_ARM11_SystemLocalCaps {
175     u64_le program_id;
176     u32_le core_version;
177     u8 reserved_flag;
178     u8 n3ds_mode;
179     union {
180         u8 flags0;
181         BitField<0, 2, u8> ideal_processor;
182         BitField<2, 2, u8> affinity_mask;
183         BitField<4, 4, u8> system_mode;
184     };
185     u8 priority;
186     u8 resource_limit_descriptor[0x10][2];
187     ExHeader_StorageInfo storage_info;
188     u8 service_access_control[0x20][8];
189     u8 ex_service_access_control[0x2][8];
190     u8 reserved[0xf];
191     u8 resource_limit_category;
192 };
193 
194 struct ExHeader_ARM11_KernelCaps {
195     static constexpr std::size_t NUM_DESCRIPTORS = 28;
196 
197     u32_le descriptors[NUM_DESCRIPTORS];
198     u8 reserved[0x10];
199 };
200 
201 struct ExHeader_ARM9_AccessControl {
202     static constexpr std::size_t NUM_DESCRIPTORS = 15;
203 
204     u8 descriptors[NUM_DESCRIPTORS];
205     u8 descversion;
206 };
207 
208 struct ExHeader_Header {
209     ExHeader_CodeSetInfo codeset_info;
210     ExHeader_DependencyList dependency_list;
211     ExHeader_SystemInfo system_info;
212     ExHeader_ARM11_SystemLocalCaps arm11_system_local_caps;
213     ExHeader_ARM11_KernelCaps arm11_kernel_caps;
214     ExHeader_ARM9_AccessControl arm9_access_control;
215     struct {
216         u8 signature[0x100];
217         u8 ncch_public_key_modulus[0x100];
218         ExHeader_ARM11_SystemLocalCaps arm11_system_local_caps;
219         ExHeader_ARM11_KernelCaps arm11_kernel_caps;
220         ExHeader_ARM9_AccessControl arm9_access_control;
221     } access_desc;
222 };
223 
224 static_assert(sizeof(ExHeader_Header) == 0x800, "ExHeader structure size is wrong");
225 
226 ////////////////////////////////////////////////////////////////////////////////////////////////////
227 // FileSys namespace
228 
229 namespace FileSys {
230 
231 /**
232  * Helper which implements an interface to deal with NCCH containers which can
233  * contain ExeFS archives or RomFS archives for games or other applications.
234  */
235 class NCCHContainer {
236 public:
237     NCCHContainer(const std::string& filepath, u32 ncch_offset = 0, u32 partition = 0);
NCCHContainer()238     NCCHContainer() {}
239 
240     Loader::ResultStatus OpenFile(const std::string& filepath, u32 ncch_offset = 0,
241                                   u32 partition = 0);
242 
243     /**
244      * Ensure NCCH header is loaded and ready for reading sections
245      * @return ResultStatus result of function
246      */
247     Loader::ResultStatus LoadHeader();
248 
249     /**
250      * Ensure ExeFS and exheader is loaded and ready for reading sections
251      * @return ResultStatus result of function
252      */
253     Loader::ResultStatus Load();
254 
255     /**
256      * Attempt to find overridden sections for the NCCH and mark the container as tainted
257      * if any are found.
258      * @return ResultStatus result of function
259      */
260     Loader::ResultStatus LoadOverrides();
261 
262     /**
263      * Reads an application ExeFS section of an NCCH file (e.g. .code, .logo, etc.)
264      * @param name Name of section to read out of NCCH file
265      * @param buffer Vector to read data into
266      * @return ResultStatus result of function
267      */
268     Loader::ResultStatus LoadSectionExeFS(const char* name, std::vector<u8>& buffer);
269 
270     /**
271      * Reads an application ExeFS section from external files instead of an NCCH file,
272      * (e.g. code.bin, logo.bcma.lz, icon.icn, banner.bnr)
273      * @param name Name of section to read from external files
274      * @param buffer Vector to read data into
275      * @return ResultStatus result of function
276      */
277     Loader::ResultStatus LoadOverrideExeFSSection(const char* name, std::vector<u8>& buffer);
278 
279     /**
280      * Get the RomFS of the NCCH container
281      * Since the RomFS can be huge, we return a file reference instead of copying to a buffer
282      * @param romfs_file The file containing the RomFS
283      * @param offset The offset the romfs begins on
284      * @param size The size of the romfs
285      * @return ResultStatus result of function
286      */
287     Loader::ResultStatus ReadRomFS(std::shared_ptr<RomFSReader>& romfs_file,
288                                    bool use_layered_fs = true);
289 
290     /**
291      * Dump the RomFS of the NCCH container to the user folder.
292      * @param target_path target path to dump to
293      * @return ResultStatus result of function.
294      */
295     Loader::ResultStatus DumpRomFS(const std::string& target_path);
296 
297     /**
298      * Get the override RomFS of the NCCH container
299      * Since the RomFS can be huge, we return a file reference instead of copying to a buffer
300      * @param romfs_file The file containing the RomFS
301      * @param offset The offset the romfs begins on
302      * @param size The size of the romfs
303      * @return ResultStatus result of function
304      */
305     Loader::ResultStatus ReadOverrideRomFS(std::shared_ptr<RomFSReader>& romfs_file);
306 
307     /**
308      * Get the Program ID of the NCCH container
309      * @return ResultStatus result of function
310      */
311     Loader::ResultStatus ReadProgramId(u64_le& program_id);
312 
313     /**
314      * Get the Extdata ID of the NCCH container
315      * @return ResultStatus result of function
316      */
317     Loader::ResultStatus ReadExtdataId(u64& extdata_id);
318 
319     /**
320      * Apply a patch for .code (if it exists).
321      * This should only be called after allocating .bss.
322      * @return ResultStatus success if a patch was applied, ErrorNotUsed if no patch was found
323      */
324     Loader::ResultStatus ApplyCodePatch(std::vector<u8>& code) const;
325 
326     /**
327      * Checks whether the NCCH container contains an ExeFS
328      * @return bool check result
329      */
330     bool HasExeFS();
331 
332     /**
333      * Checks whether the NCCH container contains a RomFS
334      * @return bool check result
335      */
336     bool HasRomFS();
337 
338     /**
339      * Checks whether the NCCH container contains an ExHeader
340      * @return bool check result
341      */
342     bool HasExHeader();
343 
344     NCCH_Header ncch_header;
345     ExeFs_Header exefs_header;
346     ExHeader_Header exheader_header;
347 
348 private:
349     bool has_header = false;
350     bool has_exheader = false;
351     bool has_exefs = false;
352     bool has_romfs = false;
353 
354     bool is_tainted = false; // Are there parts of this container being overridden?
355     bool is_loaded = false;
356     bool is_compressed = false;
357 
358     bool is_encrypted = false;
359     // for decrypting exheader, exefs header and icon/banner section
360     std::array<u8, 16> primary_key{};
361     std::array<u8, 16> secondary_key{}; // for decrypting romfs and .code section
362     std::array<u8, 16> exheader_ctr{};
363     std::array<u8, 16> exefs_ctr{};
364     std::array<u8, 16> romfs_ctr{};
365 
366     u32 ncch_offset = 0; // Offset to NCCH header, can be 0 for NCCHs or non-zero for CIAs/NCSDs
367     u32 exefs_offset = 0;
368     u32 partition = 0;
369 
370     std::string filepath;
371     FileUtil::IOFile file;
372     FileUtil::IOFile exefs_file;
373 };
374 
375 } // namespace FileSys
376