1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - FS - libraries
3 File: fs_overlay.c
4
5 Copyright 2007-2008 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Date:: 2008-10-02#$
14 $Rev: 8829 $
15 $Author: yosizaki $
16
17 *---------------------------------------------------------------------------*/
18
19
20 #include <nitro/misc.h>
21 #include <nitro/types.h>
22 #include <nitro/os.h>
23 #include <nitro/mi.h>
24
25 #include <nitro/fs.h>
26 #include <nitro/math/dgt.h>
27
28
29 #include "../include/util.h"
30 #include "../include/rom.h"
31
32
33 /*---------------------------------------------------------------------------*/
34 /* Declarations */
35
36 // Destructor callback.
37 typedef void (*MWI_DESTRUCTOR_FUNC) (void *p_this);
38
39 // Destructor chain (Each element is prepared by the global object itself)
40 typedef struct MWiDestructorChain
41 {
42 struct MWiDestructorChain *next;
43 MWI_DESTRUCTOR_FUNC dtor;
44 void *obj;
45 }
46 MWiDestructorChain;
47
48
49 /*---------------------------------------------------------------------------*/
50 /* Constants */
51
52 /*
53 #define OVERLAYPROC_ARM9 0
54 #define OVERLAYPROC_ARM7 1
55 */
56 typedef enum
57 {
58 OVERLAYPROC_ARM9,
59 OVERLAYPROC_ARM7
60 }
61 OVERLAYPROC;
62
63 #define FS_OVERLAY_FLAG_COMP 0x0001
64 #define FS_OVERLAY_FLAG_AUTH 0x0002
65 #define FS_OVERLAY_DIGEST_SIZE MATH_SHA1_DIGEST_SIZE
66
67 // Digest of the overall overlay table
68 extern u8 SDK_OVERLAYTABLE_DIGEST[];
69 #ifdef SDK_TWL
70 extern u8 SDK_LTDOVERLAYTABLE_DIGEST[];
71 #else
72 #define SDK_LTDOVERLAYTABLE_DIGEST NULL
73 #endif // SDK_TWL
74 // Overlay digest table (First half: NTR; Second half: LTD)
75 extern u8 SDK_OVERLAY_DIGEST[];
76 extern u8 SDK_OVERLAY_DIGEST_END[];
77 // Total count of the overlay
78 extern u8 SDK_OVERLAY_NUMBER[];
79 #ifdef SDK_TWL
80 extern u8 SDK_LTDOVERLAY_NUMBER[];
81 #else
82 #define SDK_LTDOVERLAY_NUMBER 0
83 #endif // SDK_TWL
84 #define FS_OVERLAY_NTR_TOTAL (u32)SDK_OVERLAY_NUMBER
85 #define FS_OVERLAY_TWL_TOTAL (u32)SDK_LTDOVERLAY_NUMBER
86
87
88 // Key constant for generating a digest with the same value as compstatic
89 static const u8 fsi_def_digest_key[64] =
90 {
91 0x21, 0x06, 0xc0, 0xde,
92 0xba, 0x98, 0xce, 0x3f,
93 0xa6, 0x92, 0xe3, 0x9d,
94 0x46, 0xf2, 0xed, 0x01,
95
96 0x76, 0xe3, 0xcc, 0x08,
97 0x56, 0x23, 0x63, 0xfa,
98 0xca, 0xd4, 0xec, 0xdf,
99 0x9a, 0x62, 0x78, 0x34,
100
101 0x8f, 0x6d, 0x63, 0x3c,
102 0xfe, 0x22, 0xca, 0x92,
103 0x20, 0x88, 0x97, 0x23,
104 0xd2, 0xcf, 0xae, 0xc2,
105
106 0x32, 0x67, 0x8d, 0xfe,
107 0xca, 0x83, 0x64, 0x98,
108 0xac, 0xfd, 0x3e, 0x37,
109 0x87, 0x46, 0x58, 0x24,
110 };
111
112
113 /*---------------------------------------------------------------------------*/
114 /* Variables */
115
116 // Global destructor chain
117 // Added at the top, so that they will be called in the reverse order of the ctor.
118 extern MWiDestructorChain *__global_destructor_chain;
119
120 // Structure for overlay information management
121 typedef struct FSOverlaySource
122 {
123 // Archive of the overlay storage source
124 FSArchive *arc;
125 // Overlay table pointer explicitly attached
126 CARDRomRegion ovt9;
127 CARDRomRegion ovt7;
128 // Key constant for digest generation
129 const void *digest_key_ptr;
130 u32 digest_key_len;
131 }
132 FSOverlaySource;
133
134 static FSOverlaySource FSiOverlayContext;
135
136
137 /*---------------------------------------------------------------------------*/
138 /* functions */
139
140 #if defined(SDK_FINALROM)
141
142 // Invalidate the call itself of the call for debugger for FINALROM
143 #define FSi_RegisterOverlayToDebugger(ovi) (void)0
144 #define FSi_UnregisterOverlayToDebugger(ovi) (void)0
145
146 #else // defined (SDK_FINALROM)
147
148 int _ISDbgLib_RegistOverlayInfo(OVERLAYPROC nProc, u32 nAddrRAM, u32 nAddrROM, u32 nSize);
149 int _ISTDbgLib_RegistOverlayInfoByAddr(OVERLAYPROC nProc, u32 nAddrRAM, u32 nSlot, u32 nAddrROM, u32 nSize);
150 int _ISDbgLib_UnregistOverlayInfo(OVERLAYPROC nProc, u32 nAddrRAM, u32 nSize);
151 int _ISTDbgLib_UnregistOverlayInfoByAddr(OVERLAYPROC nProc, u32 nAddrRAM, u32 nSize);
152
DUMMY_REGISTER(OVERLAYPROC nProc,u32 nAddrRAM,u32 nAddrROM,u32 nSize)153 static int DUMMY_REGISTER(OVERLAYPROC nProc, u32 nAddrRAM, u32 nAddrROM, u32 nSize)
154 {
155 (void)nProc;
156 (void)nAddrRAM;
157 (void)nAddrROM;
158 (void)nSize;
159 return 0;
160 }
DUMMY_UNREGISTER(OVERLAYPROC nProc,u32 nAddrRAM,u32 nSize)161 static int DUMMY_UNREGISTER(OVERLAYPROC nProc, u32 nAddrRAM, u32 nSize)
162 {
163 (void)nProc;
164 (void)nAddrRAM;
165 (void)nSize;
166 return 0;
167 }
168
169 #if defined(SDK_NITRO)
170
171 // When in NITRO-compatible mode, use the dedicated call when running the IS-NITRO-DEBUGGER
172 #define FS_REGISTER_OVERLAY_INFO(nProc, nAddrRAM, nAddrROM, nSize) ((OS_GetConsoleType() & OS_CONSOLE_ISDEBUGGER) ? _ISDbgLib_RegistOverlayInfo(nProc, nAddrRAM, nAddrROM, nSize) : \
173 DUMMY_REGISTER(nProc, nAddrRAM, nAddrROM, nSize))
174 #define FS_UNREGISTER_OVERLAY_INFO(nProc, nAddrRAM, nSize) ((OS_GetConsoleType() & OS_CONSOLE_ISDEBUGGER) ? _ISDbgLib_UnregistOverlayInfo(nProc, nAddrRAM, nSize) : \
175 DUMMY_UNREGISTER(nProc, nAddrRAM, nSize))
176
177 #elif defined(SDK_TWLLTD) && defined(SDK_TWL)/*Just in case*/
178
179 // When in TWL-dedicated mode, use the dedicated call when running the IS-TWL-DEBUGGER
180 #define FS_REGISTER_OVERLAY_INFO(nProc, nAddrRAM, nAddrROM, nSize) ((OS_GetConsoleType() & OS_CONSOLE_TWLDEBUGGER) ? _ISTDbgLib_RegistOverlayInfoByAddr(nProc, nAddrRAM, 0, nAddrROM, nSize) : \
181 DUMMY_REGISTER(nProc, nAddrRAM, nAddrROM, nSize))
182 #define FS_UNREGISTER_OVERLAY_INFO(nProc, nAddrRAM, nSize) ((OS_GetConsoleType() & OS_CONSOLE_TWLDEBUGGER) ? _ISTDbgLib_UnregistOverlayInfoByAddr(nProc, nAddrRAM, nSize) : \
183 DUMMY_UNREGISTER(nProc, nAddrRAM, nSize))
184
185 #elif defined(SDK_TWLHYB) && defined(SDK_TWL)/*Just in case*/
186
187 // When in HYBRID mode, it is necessary to use calls accordingly, by dynamically determining the environment
188 #define FS_REGISTER_OVERLAY_INFO(nProc, nAddrRAM, nAddrROM, nSize) ((OS_GetConsoleType() & OS_CONSOLE_TWLDEBUGGER) ? _ISTDbgLib_RegistOverlayInfoByAddr(nProc, nAddrRAM, 0, nAddrROM, nSize) : \
189 (OS_GetConsoleType() & OS_CONSOLE_ISDEBUGGER) ? _ISDbgLib_RegistOverlayInfo(nProc, nAddrRAM, nAddrROM, nSize) : DUMMY_REGISTER(nProc, nAddrRAM, nAddrROM, nSize))
190 #define FS_UNREGISTER_OVERLAY_INFO(nProc, nAddrRAM, nSize) ((OS_GetConsoleType() & OS_CONSOLE_TWLDEBUGGER) ? _ISTDbgLib_UnregistOverlayInfoByAddr(nProc, nAddrRAM, nSize) : \
191 (OS_GetConsoleType() & OS_CONSOLE_ISDEBUGGER) ? _ISDbgLib_UnregistOverlayInfo(nProc, nAddrRAM, nSize) : DUMMY_UNREGISTER(nProc, nAddrRAM, nSize))
192
193 #else
194
195 // Unexpected environment, such as the defined rules of the build option being changed
196 SDK_ERR("unsupported platform!\n")
197
198 #endif
199
200 /*---------------------------------------------------------------------------*
201 Name: FSi_RegisterOverlayToDebugger
202
203 Description: Notifies the debugger that the overlay was loaded on the memory
204
205 Arguments: ovi: FSOverlayInfo structure that stores the overlay information
206
207 Returns: None.
208 *---------------------------------------------------------------------------*/
FSi_RegisterOverlayToDebugger(const FSOverlayInfo * ovi)209 SDK_INLINE void FSi_RegisterOverlayToDebugger(const FSOverlayInfo *ovi)
210 {
211 const OVERLAYPROC proc = (ovi->target == MI_PROCESSOR_ARM9) ? OVERLAYPROC_ARM9 : OVERLAYPROC_ARM7;
212 const u32 address = (u32)FS_GetOverlayAddress(ovi);
213 const u32 offset = ovi->file_pos.offset;
214 const u32 length = FS_GetOverlayImageSize(ovi);
215 (void)FS_REGISTER_OVERLAY_INFO(proc, address, offset, length);
216 }
217
218 /*---------------------------------------------------------------------------*
219 Name: FSi_UnregisterOverlayToDebugger
220
221 Description: Notifies the debugger that the overlay was unloaded from the memory
222
223 Arguments: ovi: FSOverlayInfo structure that stores the overlay information
224
225 Returns: None.
226 *---------------------------------------------------------------------------*/
FSi_UnregisterOverlayToDebugger(const FSOverlayInfo * ovi)227 SDK_INLINE void FSi_UnregisterOverlayToDebugger(const FSOverlayInfo *ovi)
228 {
229 const OVERLAYPROC proc = (ovi->target == MI_PROCESSOR_ARM9) ? OVERLAYPROC_ARM9 : OVERLAYPROC_ARM7;
230 const u32 address = (u32)FS_GetOverlayAddress(ovi);
231 const u32 length = FS_GetOverlayImageSize(ovi);
232 (void)FS_UNREGISTER_OVERLAY_INFO(proc, address, length);
233 }
234 #endif // defined (SDK_FINALROM)
235
236 /*---------------------------------------------------------------------------*
237 Name: __register_global_object
238
239 Description: Process system definition function
240 Insert one chain at the front of the global destructor chain
241
242 Arguments: obj: Pointer to the object to destroy
243 dtor: Destructor routine
244 chain: Pointer to the chain structure
245 (Global object provides one for each.)
246
247 Returns: None.
248 *---------------------------------------------------------------------------*/
249 void __register_global_object(void *obj, MWI_DESTRUCTOR_FUNC dtor, MWiDestructorChain * chain);
250 /*
251 {
252 chain->next = __global_destructor_chain;
253 chain->dtor = dtor;
254 chain->obj = obj;
255 __global_destructor_chain = chain;
256 }
257 */
258
259 /*---------------------------------------------------------------------------*
260 Name: FSi_InitOverlay
261
262 Description: Initializes overlay management information
263
264 Arguments: None.
265
266 Returns: None.
267 *---------------------------------------------------------------------------*/
FSi_InitOverlay(void)268 void FSi_InitOverlay(void)
269 {
270 // If downloaded child device, overlay is invalid
271 if (OS_GetBootType() == OS_BOOTTYPE_DOWNLOAD_MB)
272 {
273 FSiOverlayContext.ovt9.offset = (u32)~0;
274 FSiOverlayContext.ovt9.length = 0;
275 FSiOverlayContext.ovt7.offset = (u32)~0;
276 FSiOverlayContext.ovt7.length = 0;
277 }
278 else
279 {
280 FSiOverlayContext.ovt9.offset = 0;
281 FSiOverlayContext.ovt9.length = 0;
282 FSiOverlayContext.ovt7.offset = 0;
283 FSiOverlayContext.ovt7.length = 0;
284 }
285 FSiOverlayContext.digest_key_ptr = fsi_def_digest_key;
286 FSiOverlayContext.digest_key_len = sizeof(fsi_def_digest_key);
287 FSiOverlayContext.arc = FS_FindArchive("rom", 3);
288 }
289
290 /*---------------------------------------------------------------------------*
291 Name: FSi_GetOverlayBinarySize
292
293 Description: Get file-size which contains an image of overlay module.
294
295 Arguments: p_ovi: pointer to FSOverlayInfo
296
297 Returns: File size of overlay.
298 *---------------------------------------------------------------------------*/
FSi_GetOverlayBinarySize(const FSOverlayInfo * p_ovi)299 static u32 FSi_GetOverlayBinarySize(const FSOverlayInfo *p_ovi)
300 {
301 u32 size = (((p_ovi->header.flag & FS_OVERLAY_FLAG_COMP) != 0)
302 ? p_ovi->header.compressed : p_ovi->header.ram_size);
303 return size;
304 }
305
306 /*---------------------------------------------------------------------------*
307 Name: FS_ClearOverlayImage
308
309 Description: 0-clear the memory where FS_GetOverlayAddress() points,
310 and invalidate its region of cache.
311 This function is called in the FS_LoadOverlayImage function.
312
313 Arguments: p_ovi: pointer to FSOverlayInfo
314
315 Returns: None.
316 *---------------------------------------------------------------------------*/
FS_ClearOverlayImage(FSOverlayInfo * p_ovi)317 void FS_ClearOverlayImage(FSOverlayInfo *p_ovi)
318 {
319 u8 *const addr = FS_GetOverlayAddress(p_ovi);
320 const u32 image_size = FS_GetOverlayImageSize(p_ovi);
321 const u32 total_size = FS_GetOverlayTotalSize(p_ovi);
322 #if defined(SDK_ARM9)
323 IC_InvalidateRange(addr, total_size);
324 DC_InvalidateRange(addr, total_size);
325 #endif
326 MI_CpuFill8(addr + image_size, 0, total_size - image_size);
327 }
328
329
330 #if defined(FS_IMPLEMENT)
331
332 /*---------------------------------------------------------------------------*
333 Name: FS_GetOverlayFileID
334
335 Description: Gets file-id which contains an image of overlay module.
336
337 Arguments: p_ovi: pointer to FSOverlayInfo
338
339 Returns: File-id of overlay.
340 *---------------------------------------------------------------------------*/
FS_GetOverlayFileID(const FSOverlayInfo * p_ovi)341 FSFileID FS_GetOverlayFileID(const FSOverlayInfo *p_ovi)
342 {
343 FSFileID ret;
344 ret.arc = FSiOverlayContext.arc;
345 ret.file_id = p_ovi->header.file_id;
346 return ret;
347 }
348
349 /*---------------------------------------------------------------------------*
350 Name: FS_LoadOverlayInfo
351
352 Description: Loads the information for specified overlay module.
353
354 Arguments: p_ovi: pointer to destination FSOverlayInfo
355 target: ARM9 or ARM7
356 id: overlay-id (FS_OVERLAY_ID(overlay-name))
357
358 Returns: If succeeded, TRUE.
359 *---------------------------------------------------------------------------*/
FS_LoadOverlayInfo(FSOverlayInfo * p_ovi,MIProcessor target,FSOverlayID id)360 BOOL FS_LoadOverlayInfo(FSOverlayInfo *p_ovi, MIProcessor target, FSOverlayID id)
361 {
362 BOOL retval = FALSE;
363 const u32 pos = (u32)id * sizeof(FSOverlayInfoHeader);
364 const CARDRomRegion *pr = (target == MI_PROCESSOR_ARM9) ?
365 &FSiOverlayContext.ovt9 : &FSiOverlayContext.ovt7;
366 #if !defined(SDK_NITRO)
367 // Cannot get the overlay for the TWL mode if not in the TWL environment
368 if ((id >= FS_OVERLAY_NTR_TOTAL) && !OS_IsRunOnTwl())
369 {
370 OS_TWarning("TWL-overlay is not available on NTR-mode.\n");
371 }
372 else
373 #endif // !defined(SDK_NITRO)
374 {
375 if (pr->offset)
376 {
377 if (pos < pr->length)
378 {
379 FSFile file[1];
380 FS_InitFile(file);
381 MI_CpuCopy8((const void *)(pr->offset + pos), p_ovi, sizeof(FSOverlayInfoHeader));
382 {
383 {
384 p_ovi->target = target;
385 if (FS_OpenFileFast(file, FS_GetOverlayFileID(p_ovi)))
386 {
387 p_ovi->file_pos.offset = FS_GetFileImageTop(file);
388 p_ovi->file_pos.length = FS_GetFileLength(file);
389 (void)FS_CloseFile(file);
390 retval = TRUE;
391 }
392 }
393 }
394 }
395 }
396 else
397 {
398 pr = (target == MI_PROCESSOR_ARM9) ?
399 CARD_GetRomRegionOVT(MI_PROCESSOR_ARM9) :
400 CARD_GetRomRegionOVT(MI_PROCESSOR_ARM7);
401 if (pos < pr->length)
402 {
403 FSFile file[1];
404 FS_InitFile(file);
405 if (FS_CreateFileFromRom(file, pr->offset + pos, pr->offset + pr->length))
406 {
407 if (FS_ReadFile(file, p_ovi, sizeof(FSOverlayInfoHeader)) !=
408 sizeof(FSOverlayInfoHeader))
409 {
410 (void)FS_CloseFile(file);
411 }
412 else
413 {
414 (void)FS_CloseFile(file);
415 p_ovi->target = target;
416 if (FS_OpenFileFast(file, FS_GetOverlayFileID(p_ovi)))
417 {
418 p_ovi->file_pos.offset = FS_GetFileImageTop(file);
419 p_ovi->file_pos.length = FS_GetFileLength(file);
420 (void)FS_CloseFile(file);
421 retval = TRUE;
422 }
423 }
424 }
425 }
426 }
427 }
428 return retval;
429 }
430
431 /*---------------------------------------------------------------------------*
432 Name: FS_LoadOverlayImageAsync
433
434 Description: Load the image of overlay module without 'static initializer'.
435 By this call, the memory where FS_GetOverlayAddress() points
436 is set to rare initial status.
437
438 Arguments: p_ovi: pointer to FSOverlayInfo
439 p_file: pointer to FSFile for asynchronous reading
440
441 Returns: If succeeded, TRUE.
442 *---------------------------------------------------------------------------*/
FS_LoadOverlayImageAsync(FSOverlayInfo * p_ovi,FSFile * p_file)443 BOOL FS_LoadOverlayImageAsync(FSOverlayInfo *p_ovi, FSFile *p_file)
444 {
445 BOOL retval = FALSE;
446 FS_InitFile(p_file);
447 if (FS_OpenFileFast(p_file, FS_GetOverlayFileID(p_ovi)))
448 {
449 s32 size = (s32)FSi_GetOverlayBinarySize(p_ovi);
450 FS_ClearOverlayImage(p_ovi);
451 if (FS_ReadFileAsync(p_file, FS_GetOverlayAddress(p_ovi), size) == size)
452 {
453 retval = TRUE;
454 }
455 else
456 {
457 (void)FS_CloseFile(p_file);
458 }
459 }
460 return retval;
461 }
462
463 /*---------------------------------------------------------------------------*
464 Name: FS_LoadOverlayImage
465
466 Description: Load the image of overlay module without 'static initializer'.
467 By this call, the memory where FS_GetOverlayAddress() points
468 is set to rare initial status.
469
470 Arguments: p_ovi: pointer to FSOverlayInfo
471
472 Returns: If succeeded, TRUE.
473 *---------------------------------------------------------------------------*/
FS_LoadOverlayImage(FSOverlayInfo * p_ovi)474 BOOL FS_LoadOverlayImage(FSOverlayInfo *p_ovi)
475 {
476 BOOL retval = FALSE;
477 FSFile p_file[1];
478 FS_InitFile(p_file);
479 if (FS_OpenFileFast(p_file, FS_GetOverlayFileID(p_ovi)))
480 {
481 s32 size = (s32)FSi_GetOverlayBinarySize(p_ovi);
482 FS_ClearOverlayImage(p_ovi);
483 if (FS_ReadFile(p_file, FS_GetOverlayAddress(p_ovi), size) == size)
484 {
485 retval = TRUE;
486 }
487 (void)FS_CloseFile(p_file);
488 }
489 return retval;
490 }
491
492 #else
493
494 /*---------------------------------------------------------------------------*
495 Name: FS_LoadOverlayInfo
496
497 Description: Loads the information for specified overlay module.
498
499 Arguments: p_ovi: pointer to destination FSOverlayInfo
500 target: ARM9 or ARM7
501 id: overlay-id (FS_OVERLAY_ID(overlay-name))
502
503 Returns: If succeeded, TRUE.
504 *---------------------------------------------------------------------------*/
FS_LoadOverlayInfo(FSOverlayInfo * p_ovi,MIProcessor target,FSOverlayID id)505 BOOL FS_LoadOverlayInfo(FSOverlayInfo *p_ovi, MIProcessor target, FSOverlayID id)
506 {
507 BOOL retval = FALSE;
508 const u32 pos = (u32)id * sizeof(FSOverlayInfoHeader);
509 const CARDRomRegion *pr;
510 pr = (target == MI_PROCESSOR_ARM9) ?
511 &FSiOverlayContext.ovt9 :
512 &FSiOverlayContext.ovt7;
513 if (pr->offset)
514 {
515 if (pos < pr->length)
516 {
517 MI_CpuCopy8((const void *)(pr->offset + pos), p_ovi, sizeof(FSOverlayInfoHeader));
518 p_ovi->target = target;
519 {
520 FSFile file[1];
521 FS_InitFile(file);
522 if (FS_OpenFileFast(file, FS_GetOverlayFileID(p_ovi)))
523 {
524 p_ovi->file_pos.offset = FS_GetFileImageTop(file);
525 p_ovi->file_pos.length = FS_GetLength(file);
526 (void)FS_CloseFile(file);
527 retval = TRUE;
528 }
529 }
530 }
531 }
532 else
533 {
534 pr = CARD_GetRomRegionOVT(target);
535 if (pos < pr->length)
536 {
537 FSi_ReadRomDirect((const void*)(pr->offset + pos), p_ovi, sizeof(FSOverlayInfoHeader));
538 p_ovi->target = target;
539 {
540 retval = TRUE;
541 }
542 }
543 }
544 return retval;
545 }
546
547 /*---------------------------------------------------------------------------*
548 Name: FS_LoadOverlayImage
549
550 Description: Load the image of overlay module without 'static initializer'.
551 By this call, the memory where FS_GetOverlayAddress() points
552 is set to rare initial status.
553
554 Arguments: p_ovi: pointer to FSOverlayInfo
555
556 Returns: If succeeded, TRUE.
557 *---------------------------------------------------------------------------*/
FS_LoadOverlayImage(FSOverlayInfo * p_ovi)558 BOOL FS_LoadOverlayImage(FSOverlayInfo *p_ovi)
559 {
560 BOOL retval = FALSE;
561 const CARDRomRegion *fat = CARD_GetRomRegionFAT();
562 u32 pos = p_ovi->header.file_id * sizeof(FSArchiveFAT);
563 if (pos < fat->length)
564 {
565 FSArchiveFAT fat_info;
566 FSi_ReadRomDirect((const void*)(fat->offset + pos), &fat_info, sizeof(FSArchiveFAT));
567 FS_ClearOverlayImage(p_ovi);
568 FSi_ReadRomDirect((const void*)(fat_info.top), p_ovi->header.ram_address, fat_info.bottom - fat_info.top);
569 retval = TRUE;
570 }
571 return retval;
572 }
573
574 #endif /* FS_IMPLEMENT */
575
576 /*---------------------------------------------------------------------------*
577 Name: FSi_CompareOverlayDigest
578
579 Description: Compares overlay digest values
580
581 Arguments: spec_digest: Comparison source digest value
582 src: Comparison target data.
583 len: src byte size.
584 table_mode: TRUE if calculating the overlay table
585
586 Returns: TRUE if comparison matches. Otherwise, FALSE.
587 *---------------------------------------------------------------------------*/
FSi_CompareDigest(const u8 * spec_digest,void * src,int len,BOOL table_mode)588 static BOOL FSi_CompareDigest(const u8 *spec_digest, void *src, int len, BOOL table_mode)
589 {
590 int i;
591 u8 digest[FS_OVERLAY_DIGEST_SIZE];
592 u8 digest_key[64];
593
594 MI_CpuClear8(digest, sizeof(digest));
595 MI_CpuCopy8(FSiOverlayContext.digest_key_ptr, digest_key,
596 FSiOverlayContext.digest_key_len);
597 // If possible, use the high-speed SVC function
598 #ifdef SDK_TWL
599 if (!table_mode && OS_IsRunOnTwl())
600 {
601 SVC_CalcHMACSHA1(digest, src, (u32)len, digest_key, FSiOverlayContext.digest_key_len);
602 }
603 else
604 #endif
605 {
606 // It is necessary to consider the ID portion 0 for the digest of the overlay table
607 int bak_ovt_mode = FALSE;
608 if (table_mode)
609 {
610 bak_ovt_mode = MATHi_SetOverlayTableMode(TRUE);
611 }
612 MATH_CalcHMACSHA1(digest, src, (u32)len, digest_key, FSiOverlayContext.digest_key_len);
613 if (table_mode)
614 {
615 (void)MATHi_SetOverlayTableMode(bak_ovt_mode);
616 }
617 }
618 for (i = 0; i < sizeof(digest); i += sizeof(u32))
619 {
620 if (*(const u32 *)(digest + i) != *(const u32 *)(spec_digest + i))
621 {
622 break;
623 }
624 }
625 return (i == sizeof(digest));
626 }
627
628 /*---------------------------------------------------------------------------*
629 Name: FS_StartOverlay
630
631 Description: Execute 'static initializer'.
632 This function needs:
633 the memory where FS_GetOverlayAddress() points is
634 set by data which FS_LoadOverlayImage() makes.
635
636 Arguments: p_ovi: pointer to FSOverlayInfo
637
638 Returns: None.
639 *---------------------------------------------------------------------------*/
FS_StartOverlay(FSOverlayInfo * p_ovi)640 void FS_StartOverlay(FSOverlayInfo *p_ovi)
641 {
642 u32 rare_size = FSi_GetOverlayBinarySize(p_ovi);
643
644 #ifdef SDK_TWL
645 // Because there is the possibility that the application that mistakenly referenced a sampling demo prior to TWL-SDK5.0FC has an overlay that would damage the LTDMAIN, raise user caution by outputting a warning for such cases.
646 //
647 //
648 // However, because this is useful with HYBRID running in NTR, after establishing a short transition period, terminate the warning.
649 //
650 {
651 extern const u8 SDK_LTDAUTOLOAD_LTDMAIN_START[];
652 extern const u8 SDK_LTDAUTOLOAD_LTDMAIN_END[];
653 extern const u8 SDK_LTDAUTOLOAD_LTDMAIN_BSS_END[];
654 if ((p_ovi->header.ram_address >= SDK_LTDAUTOLOAD_LTDMAIN_START) &&
655 (p_ovi->header.ram_address < SDK_LTDAUTOLOAD_LTDMAIN_BSS_END) &&
656 OS_IsRunOnTwl())
657 {
658 static BOOL once = FALSE;
659 if (!once)
660 {
661 OS_TWarning("specified overlay(%d) might have destroyed LTDMAIN segment!\n"
662 "(please move LTDMAIN after overlay(%d))",
663 p_ovi->header.id, p_ovi->header.id);
664 once = TRUE;
665 }
666 }
667 }
668 #endif
669
670 // If authentication of the overlay fails in storage other than ROM, invalidate the image.
671 if (OS_GetBootType() != OS_BOOTTYPE_ROM)
672 {
673 BOOL ret = FALSE;
674
675 if ((p_ovi->header.flag & FS_OVERLAY_FLAG_AUTH) != 0)
676 {
677 const u32 odt_max =
678 (u32)((SDK_OVERLAY_DIGEST_END - SDK_OVERLAY_DIGEST) / FS_OVERLAY_DIGEST_SIZE);
679 if (p_ovi->header.id < odt_max)
680 {
681 const u8 *spec_digest = (SDK_OVERLAY_DIGEST +
682 FS_OVERLAY_DIGEST_SIZE * p_ovi->header.id);
683 ret = FSi_CompareDigest(spec_digest, p_ovi->header.ram_address, (int)rare_size, FALSE);
684 }
685 }
686 if (!ret)
687 {
688 MI_CpuClear8(p_ovi->header.ram_address, rare_size);
689 OS_TPanic("FS_StartOverlay() failed! (invalid overlay-segment data)");
690 return;
691 }
692 }
693
694 if ((p_ovi->header.flag & FS_OVERLAY_FLAG_COMP) != 0)
695 {
696 MIi_UncompressBackward(p_ovi->header.ram_address + rare_size);
697 }
698 #if defined(SDK_ARM9)
699 DC_FlushRange(FS_GetOverlayAddress(p_ovi), FS_GetOverlayImageSize(p_ovi));
700 #endif
701 FSi_RegisterOverlayToDebugger(p_ovi);
702
703 {
704 FSOverlayInitFunc *p = p_ovi->header.sinit_init;
705 FSOverlayInitFunc *q = p_ovi->header.sinit_init_end;
706 for (; p < q; ++p)
707 {
708 if (*p)
709 {
710 (**p) ();
711 }
712 }
713 }
714 }
715
716 /*---------------------------------------------------------------------------*
717 Name: FS_EndOverlay
718
719 Description: Executes 'static initializer'.
720 By this function:
721 all the destructors in specified overlay module
722 are removed from global destructor chain and executed.
723
724 Arguments: p_ovi: pointer to FSOverlayInfo
725
726 Returns: None.
727 *---------------------------------------------------------------------------*/
FS_EndOverlay(FSOverlayInfo * p_ovi)728 void FS_EndOverlay(FSOverlayInfo *p_ovi)
729 {
730 for (;;)
731 {
732 // Extract the object to be released from the destructor chain
733 // Should be released if the object is in the overlay range.
734 // However, if the object is NULL, this is an array object destructor, so dtor is a target for a range check.
735 //
736 MWiDestructorChain *head = NULL, *tail = NULL;
737 const u32 region_top = (u32)FS_GetOverlayAddress(p_ovi);
738 const u32 region_bottom = region_top + FS_GetOverlayTotalSize(p_ovi);
739
740 {
741 OSIntrMode bak_psr = OS_DisableInterrupts();
742 MWiDestructorChain *prev = NULL;
743 MWiDestructorChain *base = __global_destructor_chain;
744 MWiDestructorChain *p = base;
745 while (p)
746 {
747 MWiDestructorChain *next = p->next;
748 const u32 dtor = (u32)p->dtor;
749 const u32 obj = (u32)p->obj;
750 if (((obj == 0) && (dtor >= region_top) && (dtor < region_bottom)) ||
751 ((obj >= region_top) && (obj < region_bottom)))
752 {
753 if (!tail)
754 {
755 head = p;
756 }
757 else
758 {
759 tail->next = p;
760 }
761 if (base == p)
762 {
763 base = __global_destructor_chain = next;
764 }
765 tail = p, p->next = NULL;
766 if (prev)
767 {
768 prev->next = next;
769 }
770 }
771 else
772 {
773 prev = p;
774 }
775 p = next;
776 }
777 (void)OS_RestoreInterrupts(bak_psr);
778 }
779
780 // Quit if there is not even one destructor.
781 if (!head)
782 {
783 break;
784 }
785 // If one exists, execute in order from the front and destroy
786 do
787 {
788 MWiDestructorChain *next = head->next;
789 if (head->dtor)
790 {
791 (*head->dtor) (head->obj);
792 }
793 head = next;
794 }
795 while (head);
796 // If there is a local-static-object accessed for the first time in the destructor, there are further additions to the destructor chain at this stage, so retry until not even one can be found.
797 //
798 //
799 }
800
801 FSi_UnregisterOverlayToDebugger(p_ovi);
802
803 }
804
805 /*---------------------------------------------------------------------------*
806 Name: FS_UnloadOverlayImage
807
808 Description: Unloads overlay module.
809
810 Arguments: p_ovi: pointer to FSOverlayInfo
811
812 Returns: If succeeded, TRUE.
813 *---------------------------------------------------------------------------*/
FS_UnloadOverlayImage(FSOverlayInfo * p_ovi)814 BOOL FS_UnloadOverlayImage(FSOverlayInfo *p_ovi)
815 {
816 FS_EndOverlay(p_ovi);
817 return TRUE;
818 }
819
820 /*---------------------------------------------------------------------------*
821 Name: FS_LoadOverlay
822
823 Description: Loads overlay module and initializes.
824
825 Arguments: target: ARM9 or ARM7
826 id: overlay-id (FS_OVERLAY_ID(overlay-name))
827
828 Returns: If succeeded, TRUE.
829 *---------------------------------------------------------------------------*/
FS_LoadOverlay(MIProcessor target,FSOverlayID id)830 BOOL FS_LoadOverlay(MIProcessor target, FSOverlayID id)
831 {
832 BOOL retval = FALSE;
833 SDK_ASSERT(FS_IsAvailable());
834 {
835 FSOverlayInfo ovi;
836 if (FS_LoadOverlayInfo(&ovi, target, id))
837 {
838 if (FS_LoadOverlayImage(&ovi))
839 {
840 FS_StartOverlay(&ovi);
841 retval = TRUE;
842 }
843 }
844 }
845 return retval;
846 }
847
848 /*---------------------------------------------------------------------------*
849 Name: FS_UnloadOverlay
850
851 Description: Unloads overlay module and cleans up.
852
853 Arguments: target: ARM9 or ARM7
854 id: overlay-id (FS_OVERLAY_ID(overlay-name))
855
856 Returns: If succeeded, TRUE.
857 *---------------------------------------------------------------------------*/
FS_UnloadOverlay(MIProcessor target,FSOverlayID id)858 BOOL FS_UnloadOverlay(MIProcessor target, FSOverlayID id)
859 {
860 BOOL retval = FALSE;
861 SDK_ASSERT(FS_IsAvailable());
862 {
863 FSOverlayInfo ovi;
864 if (FS_LoadOverlayInfo(&ovi, target, id))
865 {
866 if (FS_UnloadOverlayImage(&ovi))
867 {
868 retval = TRUE;
869 }
870 }
871 }
872 return retval;
873 }
874
875 /*---------------------------------------------------------------------------*
876 Name: FS_AttachOverlayTable
877
878 Description: Attaches the overlayinfo-table (OVT) to file-system.
879 After setting, the FS_LoadOverlayInfo function
880 loads overlay-info from specified memory.
881
882 Arguments: target: ARM9 or ARM7
883 ptr: pointer to buffer which contains OVT.
884 If ptr is NULL, reset to default (from CARD).
885 len: length of OVT.
886
887 Returns: None.
888 *---------------------------------------------------------------------------*/
FS_AttachOverlayTable(MIProcessor target,const void * ptr,u32 len)889 void FS_AttachOverlayTable(MIProcessor target, const void *ptr, u32 len)
890 {
891 if ((ptr != NULL) && (target == MI_PROCESSOR_ARM9))
892 {
893 // The overlay table is really for itself, but compare digests.
894 // Because the first half of the table element is NTR compatible and the second half is for TWL mode, it is possible that only the NTR compatible portion will be used when running in HYBRID.
895 //
896 const int length_ntr = (int)(FS_OVERLAY_NTR_TOTAL * sizeof(FSOverlayInfoHeader));
897 const int length_twl = (int)(FS_OVERLAY_TWL_TOTAL * sizeof(FSOverlayInfoHeader));
898 // If the specified size is incomplete, this fails
899 if ((len != length_ntr) && (len != length_ntr + length_twl))
900 {
901 OS_TPanic("specified overlay-digest-table is invalid size!");
902 }
903 else
904 {
905 // The NTR compatible portion always exists (including when the size is 0)
906 u8 *buffer_ntr = (u8 *)ptr;
907 if (!FSi_CompareDigest((const u8 *)SDK_OVERLAYTABLE_DIGEST, buffer_ntr, length_ntr, TRUE))
908 {
909 OS_TPanic("specified overlay-digest-table is invalid!");
910 }
911 // If specified, determine the TWL mode portion too
912 else if (length_twl != 0)
913 {
914 u8 *buffer_twl = buffer_ntr + length_ntr;
915 if (!FSi_CompareDigest((const u8 *)SDK_LTDOVERLAYTABLE_DIGEST, buffer_twl, length_twl, TRUE))
916 {
917 OS_TPanic("specified overlay-digest-table is invalid!");
918 }
919 }
920 }
921 }
922
923 {
924 CARDRomRegion *const pr = (target == MI_PROCESSOR_ARM9) ?
925 &FSiOverlayContext.ovt9 : &FSiOverlayContext.ovt7;
926 OSIntrMode bak_psr = OS_DisableInterrupts();
927 pr->offset = (u32)ptr;
928 pr->length = len;
929 (void)OS_RestoreInterrupts(bak_psr);
930 }
931 }
932