1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - FS - libraries
3 File: fs_overlay.c
4
5 Copyright 2007-2009 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:: 2009-06-04#$
14 $Rev: 10698 $
15 $Author: okubata_ryoma $
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 // It is necessary to use calls accordingly, by dynamically determining the environment
170 #define FS_REGISTER_OVERLAY_INFO(nProc, nAddrRAM, nAddrROM, nSize) ((OS_GetConsoleType() & OS_CONSOLE_TWLDEBUGGER) ? _ISTDbgLib_RegistOverlayInfoByAddr(nProc, nAddrRAM, 0, nAddrROM, nSize) : \
171 (OS_GetConsoleType() & OS_CONSOLE_ISDEBUGGER) ? _ISDbgLib_RegistOverlayInfo(nProc, nAddrRAM, nAddrROM, nSize) : DUMMY_REGISTER(nProc, nAddrRAM, nAddrROM, nSize))
172 #define FS_UNREGISTER_OVERLAY_INFO(nProc, nAddrRAM, nSize) ((OS_GetConsoleType() & OS_CONSOLE_TWLDEBUGGER) ? _ISTDbgLib_UnregistOverlayInfoByAddr(nProc, nAddrRAM, nSize) : \
173 (OS_GetConsoleType() & OS_CONSOLE_ISDEBUGGER) ? _ISDbgLib_UnregistOverlayInfo(nProc, nAddrRAM, nSize) : DUMMY_UNREGISTER(nProc, nAddrRAM, nSize))
174
175
176 /*---------------------------------------------------------------------------*
177 Name: FSi_RegisterOverlayToDebugger
178
179 Description: Notifies the debugger that the overlay was loaded on the memory
180
181 Arguments: ovi: FSOverlayInfo structure that stores the overlay information
182
183 Returns: None.
184 *---------------------------------------------------------------------------*/
FSi_RegisterOverlayToDebugger(const FSOverlayInfo * ovi)185 SDK_INLINE void FSi_RegisterOverlayToDebugger(const FSOverlayInfo *ovi)
186 {
187 const OVERLAYPROC proc = (ovi->target == MI_PROCESSOR_ARM9) ? OVERLAYPROC_ARM9 : OVERLAYPROC_ARM7;
188 const u32 address = (u32)FS_GetOverlayAddress(ovi);
189 const u32 offset = ovi->file_pos.offset;
190 const u32 length = FS_GetOverlayImageSize(ovi);
191 (void)FS_REGISTER_OVERLAY_INFO(proc, address, offset, length);
192 }
193
194 /*---------------------------------------------------------------------------*
195 Name: FSi_UnregisterOverlayToDebugger
196
197 Description: Notifies the debugger that the overlay was unloaded from the memory
198
199 Arguments: ovi: FSOverlayInfo structure that stores the overlay information
200
201 Returns: None.
202 *---------------------------------------------------------------------------*/
FSi_UnregisterOverlayToDebugger(const FSOverlayInfo * ovi)203 SDK_INLINE void FSi_UnregisterOverlayToDebugger(const FSOverlayInfo *ovi)
204 {
205 const OVERLAYPROC proc = (ovi->target == MI_PROCESSOR_ARM9) ? OVERLAYPROC_ARM9 : OVERLAYPROC_ARM7;
206 const u32 address = (u32)FS_GetOverlayAddress(ovi);
207 const u32 length = FS_GetOverlayImageSize(ovi);
208 (void)FS_UNREGISTER_OVERLAY_INFO(proc, address, length);
209 }
210 #endif // defined (SDK_FINALROM)
211
212 /*---------------------------------------------------------------------------*
213 Name: __register_global_object
214
215 Description: Process system definition function
216 Insert one chain at the front of the global destructor chain
217
218 Arguments: obj: Pointer to the object to destroy
219 dtor: Destructor routine
220 chain: Pointer to the chain structure
221 (Global object provides one for each)
222
223 Returns: None.
224 *---------------------------------------------------------------------------*/
225 void __register_global_object(void *obj, MWI_DESTRUCTOR_FUNC dtor, MWiDestructorChain * chain);
226 /*
227 {
228 chain->next = __global_destructor_chain;
229 chain->dtor = dtor;
230 chain->obj = obj;
231 __global_destructor_chain = chain;
232 }
233 */
234
235 /*---------------------------------------------------------------------------*
236 Name: FSi_InitOverlay
237
238 Description: Initializes overlay management information
239
240 Arguments: None.
241
242 Returns: None.
243 *---------------------------------------------------------------------------*/
FSi_InitOverlay(void)244 void FSi_InitOverlay(void)
245 {
246 // If downloaded child device, overlay is invalid
247 if (OS_GetBootType() == OS_BOOTTYPE_DOWNLOAD_MB)
248 {
249 FSiOverlayContext.ovt9.offset = (u32)~0;
250 FSiOverlayContext.ovt9.length = 0;
251 FSiOverlayContext.ovt7.offset = (u32)~0;
252 FSiOverlayContext.ovt7.length = 0;
253 }
254 else
255 {
256 FSiOverlayContext.ovt9.offset = 0;
257 FSiOverlayContext.ovt9.length = 0;
258 FSiOverlayContext.ovt7.offset = 0;
259 FSiOverlayContext.ovt7.length = 0;
260 }
261 FSiOverlayContext.digest_key_ptr = fsi_def_digest_key;
262 FSiOverlayContext.digest_key_len = sizeof(fsi_def_digest_key);
263 FSiOverlayContext.arc = FS_FindArchive("rom", 3);
264 }
265
266 /*---------------------------------------------------------------------------*
267 Name: FSi_GetOverlayBinarySize
268
269 Description: Gets file-size that contains an image of overlay module.
270
271 Arguments: p_ovi: Pointer to FSOverlayInfo
272
273 Returns: File size of overlay.
274 *---------------------------------------------------------------------------*/
FSi_GetOverlayBinarySize(const FSOverlayInfo * p_ovi)275 static u32 FSi_GetOverlayBinarySize(const FSOverlayInfo *p_ovi)
276 {
277 u32 size = (((p_ovi->header.flag & FS_OVERLAY_FLAG_COMP) != 0)
278 ? p_ovi->header.compressed : p_ovi->header.ram_size);
279 return size;
280 }
281
282 /*---------------------------------------------------------------------------*
283 Name: FS_ClearOverlayImage
284
285 Description: Zero-clear the memory where FS_GetOverlayAddress() points,
286 and invalidate its region of cache.
287 This function is called in FS_LoadOverlayImage().
288
289 Arguments: p_ovi: Pointer to FSOverlayInfo
290
291 Returns: None.
292 *---------------------------------------------------------------------------*/
FS_ClearOverlayImage(FSOverlayInfo * p_ovi)293 void FS_ClearOverlayImage(FSOverlayInfo *p_ovi)
294 {
295 u8 *const addr = FS_GetOverlayAddress(p_ovi);
296 const u32 image_size = FS_GetOverlayImageSize(p_ovi);
297 const u32 total_size = FS_GetOverlayTotalSize(p_ovi);
298 #if defined(SDK_ARM9)
299 IC_InvalidateRange(addr, total_size);
300 DC_InvalidateRange(addr, total_size);
301 #endif
302 MI_CpuFill8(addr + image_size, 0, total_size - image_size);
303 }
304
305
306 #if defined(FS_IMPLEMENT)
307
308 /*---------------------------------------------------------------------------*
309 Name: FS_GetOverlayFileID
310
311 Description: Gets file-id that contains an image of overlay module.
312
313 Arguments: p_ovi: Pointer to FSOverlayInfo
314
315 Returns: File-id of overlay.
316 *---------------------------------------------------------------------------*/
FS_GetOverlayFileID(const FSOverlayInfo * p_ovi)317 FSFileID FS_GetOverlayFileID(const FSOverlayInfo *p_ovi)
318 {
319 FSFileID ret;
320 ret.arc = FSiOverlayContext.arc;
321 ret.file_id = p_ovi->header.file_id;
322 return ret;
323 }
324
325 /*---------------------------------------------------------------------------*
326 Name: FS_LoadOverlayInfo
327
328 Description: Loads the information of specified overlay module.
329
330 Arguments: p_ovi: Pointer to destination FSOverlayInfo
331 target: ARM9 or ARM7
332 id: Overlay-id (FS_OVERLAY_ID(overlay-name))
333
334 Returns: If succeeded, TRUE.
335 *---------------------------------------------------------------------------*/
FS_LoadOverlayInfo(FSOverlayInfo * p_ovi,MIProcessor target,FSOverlayID id)336 BOOL FS_LoadOverlayInfo(FSOverlayInfo *p_ovi, MIProcessor target, FSOverlayID id)
337 {
338 BOOL retval = FALSE;
339 const u32 pos = (u32)id * sizeof(FSOverlayInfoHeader);
340 const CARDRomRegion *pr = (target == MI_PROCESSOR_ARM9) ?
341 &FSiOverlayContext.ovt9 : &FSiOverlayContext.ovt7;
342 #if !defined(SDK_NITRO)
343 // Cannot get the overlay for the TWL mode if not in the TWL environment
344 if ((id >= FS_OVERLAY_NTR_TOTAL) && !OS_IsRunOnTwl())
345 {
346 OS_TWarning("TWL-overlay is not available on NTR-mode.\n");
347 }
348 else
349 #endif // !defined(SDK_NITRO)
350 {
351 if (pr->offset)
352 {
353 if (pos < pr->length)
354 {
355 FSFile file[1];
356 FS_InitFile(file);
357 MI_CpuCopy8((const void *)(pr->offset + pos), p_ovi, sizeof(FSOverlayInfoHeader));
358 {
359 {
360 p_ovi->target = target;
361 if (FS_OpenFileFast(file, FS_GetOverlayFileID(p_ovi)))
362 {
363 p_ovi->file_pos.offset = FS_GetFileImageTop(file);
364 p_ovi->file_pos.length = FS_GetFileLength(file);
365 (void)FS_CloseFile(file);
366 retval = TRUE;
367 }
368 }
369 }
370 }
371 }
372 else
373 {
374 pr = (target == MI_PROCESSOR_ARM9) ?
375 CARD_GetRomRegionOVT(MI_PROCESSOR_ARM9) :
376 CARD_GetRomRegionOVT(MI_PROCESSOR_ARM7);
377 if (pos < pr->length)
378 {
379 FSFile file[1];
380 FS_InitFile(file);
381 if (FS_CreateFileFromRom(file, pr->offset + pos, pr->offset + pr->length))
382 {
383 if (FS_ReadFile(file, p_ovi, sizeof(FSOverlayInfoHeader)) !=
384 sizeof(FSOverlayInfoHeader))
385 {
386 (void)FS_CloseFile(file);
387 }
388 else
389 {
390 (void)FS_CloseFile(file);
391 p_ovi->target = target;
392 if (FS_OpenFileFast(file, FS_GetOverlayFileID(p_ovi)))
393 {
394 p_ovi->file_pos.offset = FS_GetFileImageTop(file);
395 p_ovi->file_pos.length = FS_GetFileLength(file);
396 (void)FS_CloseFile(file);
397 retval = TRUE;
398 }
399 }
400 }
401 }
402 }
403 }
404 return retval;
405 }
406
407 /*---------------------------------------------------------------------------*
408 Name: FS_LoadOverlayImageAsync
409
410 Description: Loads the image of overlay module without 'static initializer'.
411 By this call, the memory where FS_GetOverlayAddress() points
412 is set to rare initial status.
413
414 Arguments: p_ovi: Pointer to FSOverlayInfo
415 p_file: Pointer to FSFile for asynchronous reading
416
417 Returns: If succeeded, TRUE.
418 *---------------------------------------------------------------------------*/
FS_LoadOverlayImageAsync(FSOverlayInfo * p_ovi,FSFile * p_file)419 BOOL FS_LoadOverlayImageAsync(FSOverlayInfo *p_ovi, FSFile *p_file)
420 {
421 BOOL retval = FALSE;
422 FS_InitFile(p_file);
423 if (FS_OpenFileFast(p_file, FS_GetOverlayFileID(p_ovi)))
424 {
425 s32 size = (s32)FSi_GetOverlayBinarySize(p_ovi);
426 FS_ClearOverlayImage(p_ovi);
427 if (FS_ReadFileAsync(p_file, FS_GetOverlayAddress(p_ovi), size) == size)
428 {
429 retval = TRUE;
430 }
431 else
432 {
433 (void)FS_CloseFile(p_file);
434 }
435 }
436 return retval;
437 }
438
439 /*---------------------------------------------------------------------------*
440 Name: FS_LoadOverlayImage
441
442 Description: Loads the image of overlay module without 'static initializer'.
443 By this call, the memory where FS_GetOverlayAddress() points
444 is set to rare initial status.
445
446 Arguments: p_ovi: Pointer to FSOverlayInfo
447
448 Returns: If succeeded, TRUE.
449 *---------------------------------------------------------------------------*/
FS_LoadOverlayImage(FSOverlayInfo * p_ovi)450 BOOL FS_LoadOverlayImage(FSOverlayInfo *p_ovi)
451 {
452 BOOL retval = FALSE;
453 FSFile p_file[1];
454 FS_InitFile(p_file);
455 if (FS_OpenFileFast(p_file, FS_GetOverlayFileID(p_ovi)))
456 {
457 s32 size = (s32)FSi_GetOverlayBinarySize(p_ovi);
458 FS_ClearOverlayImage(p_ovi);
459 if (FS_ReadFile(p_file, FS_GetOverlayAddress(p_ovi), size) == size)
460 {
461 retval = TRUE;
462 }
463 (void)FS_CloseFile(p_file);
464 }
465 return retval;
466 }
467
468 #else
469
470 /*---------------------------------------------------------------------------*
471 Name: FS_LoadOverlayInfo
472
473 Description: Loads the information of specified overlay module.
474
475 Arguments: p_ovi: Pointer to destination FSOverlayInfo
476 target: ARM9 or ARM7
477 id: Overlay-id (FS_OVERLAY_ID(overlay-name))
478
479 Returns: If succeeded, TRUE.
480 *---------------------------------------------------------------------------*/
FS_LoadOverlayInfo(FSOverlayInfo * p_ovi,MIProcessor target,FSOverlayID id)481 BOOL FS_LoadOverlayInfo(FSOverlayInfo *p_ovi, MIProcessor target, FSOverlayID id)
482 {
483 BOOL retval = FALSE;
484 const u32 pos = (u32)id * sizeof(FSOverlayInfoHeader);
485 const CARDRomRegion *pr;
486 pr = (target == MI_PROCESSOR_ARM9) ?
487 &FSiOverlayContext.ovt9 :
488 &FSiOverlayContext.ovt7;
489 if (pr->offset)
490 {
491 if (pos < pr->length)
492 {
493 MI_CpuCopy8((const void *)(pr->offset + pos), p_ovi, sizeof(FSOverlayInfoHeader));
494 p_ovi->target = target;
495 {
496 FSFile file[1];
497 FS_InitFile(file);
498 if (FS_OpenFileFast(file, FS_GetOverlayFileID(p_ovi)))
499 {
500 p_ovi->file_pos.offset = FS_GetFileImageTop(file);
501 p_ovi->file_pos.length = FS_GetLength(file);
502 (void)FS_CloseFile(file);
503 retval = TRUE;
504 }
505 }
506 }
507 }
508 else
509 {
510 pr = CARD_GetRomRegionOVT(target);
511 if (pos < pr->length)
512 {
513 FSi_ReadRomDirect((const void*)(pr->offset + pos), p_ovi, sizeof(FSOverlayInfoHeader));
514 p_ovi->target = target;
515 {
516 retval = TRUE;
517 }
518 }
519 }
520 return retval;
521 }
522
523 /*---------------------------------------------------------------------------*
524 Name: FS_LoadOverlayImage
525
526 Description: Loads the image of overlay module without 'static initializer'.
527 By this call, the memory where FS_GetOverlayAddress() points
528 is set to rare initial status.
529
530 Arguments: p_ovi: Pointer to FSOverlayInfo
531
532 Returns: If succeeded, TRUE.
533 *---------------------------------------------------------------------------*/
FS_LoadOverlayImage(FSOverlayInfo * p_ovi)534 BOOL FS_LoadOverlayImage(FSOverlayInfo *p_ovi)
535 {
536 BOOL retval = FALSE;
537 const CARDRomRegion *fat = CARD_GetRomRegionFAT();
538 u32 pos = p_ovi->header.file_id * sizeof(FSArchiveFAT);
539 if (pos < fat->length)
540 {
541 FSArchiveFAT fat_info;
542 FSi_ReadRomDirect((const void*)(fat->offset + pos), &fat_info, sizeof(FSArchiveFAT));
543 FS_ClearOverlayImage(p_ovi);
544 FSi_ReadRomDirect((const void*)(fat_info.top), p_ovi->header.ram_address, fat_info.bottom - fat_info.top);
545 retval = TRUE;
546 }
547 return retval;
548 }
549
550 #endif /* FS_IMPLEMENT */
551
552 /*---------------------------------------------------------------------------*
553 Name: FSi_CompareOverlayDigest
554
555 Description: Compares overlay digest values
556
557 Arguments: spec_digest: Comparison source digest value
558 src: Comparison target data
559 len: src byte size
560 table_mode: TRUE if calculating the overlay table
561
562 Returns: TRUE if comparison matches. Otherwise, FALSE.
563 *---------------------------------------------------------------------------*/
FSi_CompareDigest(const u8 * spec_digest,void * src,int len,BOOL table_mode)564 static BOOL FSi_CompareDigest(const u8 *spec_digest, void *src, int len, BOOL table_mode)
565 {
566 int i;
567 u8 digest[FS_OVERLAY_DIGEST_SIZE];
568 u8 digest_key[64];
569
570 MI_CpuClear8(digest, sizeof(digest));
571 MI_CpuCopy8(FSiOverlayContext.digest_key_ptr, digest_key,
572 FSiOverlayContext.digest_key_len);
573 // If possible, use the high-speed SVC function
574 #ifdef SDK_TWL
575 if (!table_mode && OS_IsRunOnTwl())
576 {
577 SVC_CalcHMACSHA1(digest, src, (u32)len, digest_key, FSiOverlayContext.digest_key_len);
578 }
579 else
580 #endif
581 {
582 // It is necessary to consider the ID portion 0 for the digest of the overlay table
583 int bak_ovt_mode = FALSE;
584 if (table_mode)
585 {
586 bak_ovt_mode = MATHi_SetOverlayTableMode(TRUE);
587 }
588 MATH_CalcHMACSHA1(digest, src, (u32)len, digest_key, FSiOverlayContext.digest_key_len);
589 if (table_mode)
590 {
591 (void)MATHi_SetOverlayTableMode(bak_ovt_mode);
592 }
593 }
594 for (i = 0; i < sizeof(digest); i += sizeof(u32))
595 {
596 if (*(const u32 *)(digest + i) != *(const u32 *)(spec_digest + i))
597 {
598 break;
599 }
600 }
601 return (i == sizeof(digest));
602 }
603
604 /*---------------------------------------------------------------------------*
605 Name: FS_StartOverlay
606
607 Description: Executes 'static initializer'.
608 This function needs:
609 the memory where FS_GetOverlayAddress() points is
610 set by data which FS_LoadOverlayImage() makes.
611
612 Arguments: p_ovi: Pointer to FSOverlayInfo
613
614 Returns: None.
615 *---------------------------------------------------------------------------*/
FS_StartOverlay(FSOverlayInfo * p_ovi)616 void FS_StartOverlay(FSOverlayInfo *p_ovi)
617 {
618 u32 rare_size = FSi_GetOverlayBinarySize(p_ovi);
619
620 #ifdef SDK_TWL
621 // It is possible that an application has the overlays that would damage the LTDMAIN after using a sample demo from TWL-SDK 5.0 FC and earlier incorrectly. In such cases, output a warning.
622 //
623 //
624 // However, because this is sometimes useful with a hybrid running on NTR, after a short transition period, terminate the warning.
625 //
626 {
627 extern const u8 SDK_LTDAUTOLOAD_LTDMAIN_START[];
628 extern const u8 SDK_LTDAUTOLOAD_LTDMAIN_END[];
629 extern const u8 SDK_LTDAUTOLOAD_LTDMAIN_BSS_END[];
630 if ((p_ovi->header.ram_address >= SDK_LTDAUTOLOAD_LTDMAIN_START) &&
631 (p_ovi->header.ram_address < SDK_LTDAUTOLOAD_LTDMAIN_BSS_END) &&
632 OS_IsRunOnTwl())
633 {
634 static BOOL once = FALSE;
635 if (!once)
636 {
637 OS_TWarning("specified overlay(%d) might have destroyed LTDMAIN segment!\n"
638 "(please move LTDMAIN after overlay(%d))",
639 p_ovi->header.id, p_ovi->header.id);
640 once = TRUE;
641 }
642 }
643 }
644 #endif
645
646 // If authentication of the overlay fails in storage other than ROM, invalidate the image
647 if (OS_GetBootType() != OS_BOOTTYPE_ROM)
648 {
649 BOOL ret = FALSE;
650
651 if ((p_ovi->header.flag & FS_OVERLAY_FLAG_AUTH) != 0)
652 {
653 const u32 odt_max =
654 (u32)((SDK_OVERLAY_DIGEST_END - SDK_OVERLAY_DIGEST) / FS_OVERLAY_DIGEST_SIZE);
655 if (p_ovi->header.id < odt_max)
656 {
657 const u8 *spec_digest = (SDK_OVERLAY_DIGEST +
658 FS_OVERLAY_DIGEST_SIZE * p_ovi->header.id);
659 ret = FSi_CompareDigest(spec_digest, p_ovi->header.ram_address, (int)rare_size, FALSE);
660 }
661 }
662 if (!ret)
663 {
664 MI_CpuClear8(p_ovi->header.ram_address, rare_size);
665 OS_TPanic("FS_StartOverlay() failed! (invalid overlay-segment data)");
666 return;
667 }
668 }
669
670 if ((p_ovi->header.flag & FS_OVERLAY_FLAG_COMP) != 0)
671 {
672 MIi_UncompressBackward(p_ovi->header.ram_address + rare_size);
673 }
674 #if defined(SDK_ARM9)
675 DC_FlushRange(FS_GetOverlayAddress(p_ovi), FS_GetOverlayImageSize(p_ovi));
676 #endif
677 FSi_RegisterOverlayToDebugger(p_ovi);
678
679 {
680 FSOverlayInitFunc *p = p_ovi->header.sinit_init;
681 FSOverlayInitFunc *q = p_ovi->header.sinit_init_end;
682 for (; p < q; ++p)
683 {
684 if (*p)
685 {
686 (**p) ();
687 }
688 }
689 }
690 }
691
692 /*---------------------------------------------------------------------------*
693 Name: FS_EndOverlay
694
695 Description: Executes 'static initializer'.
696 By this function:
697 all the destructors in specified overlay module
698 are removed from global destructor chain and executed.
699
700 Arguments: p_ovi: Pointer to FSOverlayInfo
701
702 Returns: None.
703 *---------------------------------------------------------------------------*/
FS_EndOverlay(FSOverlayInfo * p_ovi)704 void FS_EndOverlay(FSOverlayInfo *p_ovi)
705 {
706 for (;;)
707 {
708 // Extract the object to be released from the destructor chain
709 // Should be released if the object is in the overlay range.
710 // However, if the object is NULL, this is an array object destructor, so dtor is the target for the range check.
711 //
712 MWiDestructorChain *head = NULL, *tail = NULL;
713 const u32 region_top = (u32)FS_GetOverlayAddress(p_ovi);
714 const u32 region_bottom = region_top + FS_GetOverlayTotalSize(p_ovi);
715
716 {
717 OSIntrMode bak_psr = OS_DisableInterrupts();
718 MWiDestructorChain *prev = NULL;
719 MWiDestructorChain *base = __global_destructor_chain;
720 MWiDestructorChain *p = base;
721 while (p)
722 {
723 MWiDestructorChain *next = p->next;
724 const u32 dtor = (u32)p->dtor;
725 const u32 obj = (u32)p->obj;
726 if (((obj == 0) && (dtor >= region_top) && (dtor < region_bottom)) ||
727 ((obj >= region_top) && (obj < region_bottom)))
728 {
729 if (!tail)
730 {
731 head = p;
732 }
733 else
734 {
735 tail->next = p;
736 }
737 if (base == p)
738 {
739 base = __global_destructor_chain = next;
740 }
741 tail = p, p->next = NULL;
742 if (prev)
743 {
744 prev->next = next;
745 }
746 }
747 else
748 {
749 prev = p;
750 }
751 p = next;
752 }
753 (void)OS_RestoreInterrupts(bak_psr);
754 }
755
756 // Quit if there is not even one destructor
757 if (!head)
758 {
759 break;
760 }
761 // If one exists, execute in order from the front and destroy
762 do
763 {
764 MWiDestructorChain *next = head->next;
765 if (head->dtor)
766 {
767 (*head->dtor) (head->obj);
768 }
769 head = next;
770 }
771 while (head);
772 // 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.
773 //
774 //
775 }
776
777 FSi_UnregisterOverlayToDebugger(p_ovi);
778
779 }
780
781 /*---------------------------------------------------------------------------*
782 Name: FS_UnloadOverlayImage
783
784 Description: Unloads overlay module.
785
786 Arguments: p_ovi: Pointer to FSOverlayInfo
787
788 Returns: If succeeded, TRUE.
789 *---------------------------------------------------------------------------*/
FS_UnloadOverlayImage(FSOverlayInfo * p_ovi)790 BOOL FS_UnloadOverlayImage(FSOverlayInfo *p_ovi)
791 {
792 FS_EndOverlay(p_ovi);
793 return TRUE;
794 }
795
796 /*---------------------------------------------------------------------------*
797 Name: FS_LoadOverlay
798
799 Description: Loads overlay module and initializes.
800
801 Arguments: target: ARM9 or ARM7
802 id: Overlay-id (FS_OVERLAY_ID(overlay-name))
803
804 Returns: If succeeded, TRUE.
805 *---------------------------------------------------------------------------*/
FS_LoadOverlay(MIProcessor target,FSOverlayID id)806 BOOL FS_LoadOverlay(MIProcessor target, FSOverlayID id)
807 {
808 BOOL retval = FALSE;
809 SDK_ASSERT(FS_IsAvailable());
810 {
811 FSOverlayInfo ovi;
812 if (FS_LoadOverlayInfo(&ovi, target, id))
813 {
814 if (FS_LoadOverlayImage(&ovi))
815 {
816 FS_StartOverlay(&ovi);
817 retval = TRUE;
818 }
819 }
820 }
821 return retval;
822 }
823
824 /*---------------------------------------------------------------------------*
825 Name: FS_UnloadOverlay
826
827 Description: Unloads overlay module and cleans up.
828
829 Arguments: target: ARM9 or ARM7
830 id: Overlay-id (FS_OVERLAY_ID(overlay-name))
831
832 Returns: If succeeded, TRUE.
833 *---------------------------------------------------------------------------*/
FS_UnloadOverlay(MIProcessor target,FSOverlayID id)834 BOOL FS_UnloadOverlay(MIProcessor target, FSOverlayID id)
835 {
836 BOOL retval = FALSE;
837 SDK_ASSERT(FS_IsAvailable());
838 {
839 FSOverlayInfo ovi;
840 if (FS_LoadOverlayInfo(&ovi, target, id))
841 {
842 if (FS_UnloadOverlayImage(&ovi))
843 {
844 retval = TRUE;
845 }
846 }
847 }
848 return retval;
849 }
850
851 /*---------------------------------------------------------------------------*
852 Name: FS_AttachOverlayTable
853
854 Description: Attaches the overlayinfo-table (OVT) to file-system.
855 After setting, FS_LoadOverlayInfo()
856 loads overlay-info from specified memory.
857
858 Arguments: target: ARM9 or ARM7
859 ptr: Pointer to buffer which contains OVT.
860 If ptr is NULL, reset to default(from CARD).
861 len: Length of OVT
862
863 Returns: None.
864 *---------------------------------------------------------------------------*/
FS_AttachOverlayTable(MIProcessor target,const void * ptr,u32 len)865 void FS_AttachOverlayTable(MIProcessor target, const void *ptr, u32 len)
866 {
867 if ((ptr != NULL) && (target == MI_PROCESSOR_ARM9))
868 {
869 // The overlay table is really for itself, but compare digests.
870 // Because the first half of the elements in the table is NTR compatible and the second half is for TWL mode, it is possible that only the NTR compatible portion is used when running a hybrid.
871 //
872 const int length_ntr = (int)(FS_OVERLAY_NTR_TOTAL * sizeof(FSOverlayInfoHeader));
873 const int length_twl = (int)(FS_OVERLAY_TWL_TOTAL * sizeof(FSOverlayInfoHeader));
874 // If the specified size is incomplete, this fails
875 if ((len != length_ntr) && (len != length_ntr + length_twl))
876 {
877 OS_TPanic("specified overlay-digest-table is invalid size!");
878 }
879 else
880 {
881 // The NTR compatible portion always exists (including when the size is 0)
882 u8 *buffer_ntr = (u8 *)ptr;
883 if (!FSi_CompareDigest((const u8 *)SDK_OVERLAYTABLE_DIGEST, buffer_ntr, length_ntr, TRUE))
884 {
885 OS_TPanic("specified overlay-digest-table is invalid!");
886 }
887 // If specified, determine the TWL mode portion, too
888 else if (length_twl != 0)
889 {
890 u8 *buffer_twl = buffer_ntr + length_ntr;
891 if (!FSi_CompareDigest((const u8 *)SDK_LTDOVERLAYTABLE_DIGEST, buffer_twl, length_twl, TRUE))
892 {
893 OS_TPanic("specified overlay-digest-table is invalid!");
894 }
895 }
896 }
897 }
898
899 {
900 CARDRomRegion *const pr = (target == MI_PROCESSOR_ARM9) ?
901 &FSiOverlayContext.ovt9 : &FSiOverlayContext.ovt7;
902 OSIntrMode bak_psr = OS_DisableInterrupts();
903 pr->offset = (u32)ptr;
904 pr->length = len;
905 (void)OS_RestoreInterrupts(bak_psr);
906 }
907 }
908