diff options
author | PikalaxALT <pikalaxalt@gmail.com> | 2020-05-07 13:48:17 -0400 |
---|---|---|
committer | PikalaxALT <pikalaxalt@gmail.com> | 2020-05-07 13:49:50 -0400 |
commit | 5928e2511db179bdc809f252a3b7fcd7798726db (patch) | |
tree | e7ce827057873f803f61a94853d717ed4407e713 /arm9/lib | |
parent | 1762253800d072790303d8cd3b047bab25f8eaed (diff) | |
parent | d4575098dbd671e2b6fd27ad65b984502c90465b (diff) |
Merge branch 'libfs' of github.com:PikalaxALT/pokediamond into libfs
Diffstat (limited to 'arm9/lib')
-rw-r--r-- | arm9/lib/include/CARD_rom.h | 9 | ||||
-rw-r--r-- | arm9/lib/include/DGT_common.h | 6 | ||||
-rw-r--r-- | arm9/lib/include/DGT_dgt.h | 6 | ||||
-rw-r--r-- | arm9/lib/include/FS_archive.h | 56 | ||||
-rw-r--r-- | arm9/lib/include/FS_command.h | 9 | ||||
-rw-r--r-- | arm9/lib/include/FS_file.h | 33 | ||||
-rw-r--r-- | arm9/lib/include/FS_mw_dtor.h | 16 | ||||
-rw-r--r-- | arm9/lib/include/FS_overlay.h | 15 | ||||
-rw-r--r-- | arm9/lib/include/FS_rom.h | 7 | ||||
-rw-r--r-- | arm9/lib/include/MI_memory.h | 10 | ||||
-rw-r--r-- | arm9/lib/include/MI_uncompress.h | 6 | ||||
-rw-r--r-- | arm9/lib/include/OS_cache.h | 9 | ||||
-rw-r--r-- | arm9/lib/include/OS_system.h | 5 | ||||
-rw-r--r-- | arm9/lib/include/OS_thread.h | 1 | ||||
-rw-r--r-- | arm9/lib/src/FS_archive.c | 147 | ||||
-rw-r--r-- | arm9/lib/src/FS_file.c | 10 | ||||
-rw-r--r-- | arm9/lib/src/FS_overlay.c | 297 |
17 files changed, 632 insertions, 10 deletions
diff --git a/arm9/lib/include/CARD_rom.h b/arm9/lib/include/CARD_rom.h index 327bc995..c43a2f06 100644 --- a/arm9/lib/include/CARD_rom.h +++ b/arm9/lib/include/CARD_rom.h @@ -1,6 +1,8 @@ #ifndef NITRO_CARD_ROM_H_ #define NITRO_CARD_ROM_H_ +#include "MI_exMemory.h" + typedef struct { u32 offset; @@ -8,4 +10,11 @@ typedef struct } CARDRomRegion; +static inline const CARDRomRegion * CARD_GetRomRegionOVT(MIProcessor target) +{ + return (target == MI_PROCESSOR_ARM9) + ? (const CARDRomRegion *)((const u8 *)HW_ROM_HEADER_BUF + 0x50) + : (const CARDRomRegion *)((const u8 *)HW_ROM_HEADER_BUF + 0x58); +} + #endif //NITRO_CARD_ROM_H_ diff --git a/arm9/lib/include/DGT_common.h b/arm9/lib/include/DGT_common.h new file mode 100644 index 00000000..c74ae7cd --- /dev/null +++ b/arm9/lib/include/DGT_common.h @@ -0,0 +1,6 @@ +#ifndef NITRO_DGT_COMMON_H_ +#define NITRO_DGT_COMMON_H_ + +#define DGT_HASH2_DIGEST_SIZE (160/8) + +#endif //NITRO_DGT_COMMON_H_ diff --git a/arm9/lib/include/DGT_dgt.h b/arm9/lib/include/DGT_dgt.h new file mode 100644 index 00000000..1c48531c --- /dev/null +++ b/arm9/lib/include/DGT_dgt.h @@ -0,0 +1,6 @@ +#ifndef NITRO_DGT_DGT_H_ +#define NITRO_DGT_DGT_H_ + +void DGT_Hash2CalcHmac(void* digest, void* bin_ptr, int bin_len, void* key_ptr, int keylen); + +#endif //NITRO_DGT_DGT_H_ diff --git a/arm9/lib/include/FS_archive.h b/arm9/lib/include/FS_archive.h index 66840b32..b39e7738 100644 --- a/arm9/lib/include/FS_archive.h +++ b/arm9/lib/include/FS_archive.h @@ -47,6 +47,37 @@ typedef enum { FS_COMMAND_INVALID } FSCommandType; +/* Asynchronous commands*/ +#define FS_ARCHIVE_PROC_READFILE (1 << FS_COMMAND_READFILE) +#define FS_ARCHIVE_PROC_WRITEFILE (1 << FS_COMMAND_WRITEFILE) +/* All asynchronous commands*/ +#define FS_ARCHIVE_PROC_ASYNC \ + (FS_ARCHIVE_PROC_READFILE | FS_ARCHIVE_PROC_WRITEFILE) + +/* Synchronous commands*/ +#define FS_ARCHIVE_PROC_SEEKDIR (1 << FS_COMMAND_SEEKDIR) +#define FS_ARCHIVE_PROC_READDIR (1 << FS_COMMAND_READDIR) +#define FS_ARCHIVE_PROC_FINDPATH (1 << FS_COMMAND_FINDPATH) +#define FS_ARCHIVE_PROC_GETPATH (1 << FS_COMMAND_GETPATH) +#define FS_ARCHIVE_PROC_OPENFILEFAST (1 << FS_COMMAND_OPENFILEFAST) +#define FS_ARCHIVE_PROC_OPENFILEDIRECT (1 << FS_COMMAND_OPENFILEDIRECT) +#define FS_ARCHIVE_PROC_CLOSEFILE (1 << FS_COMMAND_CLOSEFILE) +/* All synchronous commands*/ +#define FS_ARCHIVE_PROC_SYNC \ + (FS_ARCHIVE_PROC_SEEKDIR | FS_ARCHIVE_PROC_READDIR | \ + FS_ARCHIVE_PROC_FINDPATH | FS_ARCHIVE_PROC_GETPATH | \ + FS_ARCHIVE_PROC_OPENFILEFAST | FS_ARCHIVE_PROC_OPENFILEDIRECT | FS_ARCHIVE_PROC_CLOSEFILE) + +/* Messages when status changes*/ +#define FS_ARCHIVE_PROC_ACTIVATE (1 << FS_COMMAND_ACTIVATE) +#define FS_ARCHIVE_PROC_IDLE (1 << FS_COMMAND_IDLE) +#define FS_ARCHIVE_PROC_SUSPENDING (1 << FS_COMMAND_SUSPEND) +#define FS_ARCHIVE_PROC_RESUME (1 << FS_COMMAND_RESUME) +/* All messages when status changes*/ +#define FS_ARCHIVE_PROC_STATUS \ + (FS_ARCHIVE_PROC_ACTIVATE | FS_ARCHIVE_PROC_IDLE | \ + FS_ARCHIVE_PROC_SUSPENDING | FS_ARCHIVE_PROC_RESUME) + typedef enum { FS_RESULT_SUCCESS = 0, FS_RESULT_FAILURE, @@ -107,6 +138,31 @@ static inline BOOL FS_IsArchiveLoaded(volatile const FSArchive * p_arc) return (p_arc->flag & FS_ARCHIVE_FLAG_LOADED) ? TRUE : FALSE; } +static inline u32 FS_GetArchiveOffset(const FSArchive * p_arc, u32 pos) +{ + return p_arc->base + pos; +} + +static inline BOOL FSi_IsArchiveCanceling(volatile const FSArchive * p_arc) +{ + return (p_arc->flag & FS_ARCHIVE_FLAG_CANCELING) != 0; +} + +static inline BOOL FS_IsArchiveSuspended(volatile const FSArchive * p_arc) +{ + return (p_arc->flag & FS_ARCHIVE_FLAG_SUSPEND) ? TRUE : FALSE; +} + +static inline BOOL FSi_IsArchiveSuspending(volatile const FSArchive * p_arc) +{ + return (p_arc->flag & FS_ARCHIVE_FLAG_SUSPENDING) != 0; +} + +static inline BOOL FSi_IsArchiveRunning(volatile const FSArchive * p_arc) +{ + return (p_arc->flag & FS_ARCHIVE_FLAG_RUNNING) != 0; +} + BOOL FSi_SendCommand(struct FSFile * file, FSCommandType command); BOOL FSi_ExecuteSyncCommand(struct FSFile * file); diff --git a/arm9/lib/include/FS_command.h b/arm9/lib/include/FS_command.h new file mode 100644 index 00000000..db878f3f --- /dev/null +++ b/arm9/lib/include/FS_command.h @@ -0,0 +1,9 @@ +#ifndef NITRO_FS_COMMAND_H_ +#define NITRO_FS_COMMAND_H_ + +#include "FS_file.h" + +void FSi_ReleaseCommand(FSFile * file, FSResult signal); +FSResult FSi_TranslateCommand(FSFile * file, FSCommandType command); + +#endif //NITRO_FS_COMMAND_H_ diff --git a/arm9/lib/include/FS_file.h b/arm9/lib/include/FS_file.h index 4871b660..92e2149e 100644 --- a/arm9/lib/include/FS_file.h +++ b/arm9/lib/include/FS_file.h @@ -175,5 +175,38 @@ FSFile; u32 FS_SetDefaultDMA(u32 dma_no); // returns the previous selection void FS_InitFile(FSFile * p_file); BOOL FS_WaitAsync(FSFile * p_file); +BOOL FS_OpenFileDirect(FSFile * p_file, FSArchive * p_arc, u32 image_top, u32 image_bottom, u32 file_index); +int FS_ReadFile(FSFile * p_file, void * dst, s32 len); +int FS_ReadFileAsync(FSFile * p_file, void * dst, s32 len); +BOOL FS_OpenFileFast(FSFile * p_file, FSFileID file_id); + +static inline u32 const FS_GetFileImageTop(volatile const FSFile * p_file) { + return p_file->prop.file.top; +} + +static inline u32 const FS_GetLength(volatile const FSFile * p_file) +{ + return p_file->prop.file.bottom - p_file->prop.file.top; +} + +static inline BOOL FS_IsCanceling(volatile const FSFile * p_file) +{ + return (p_file->stat & FS_FILE_STATUS_CANCEL) ? TRUE : FALSE; +} + +static inline BOOL FS_IsFileSyncMode(volatile const FSFile * p_file) +{ + return (p_file->stat & FS_FILE_STATUS_SYNC) ? TRUE : FALSE; +} + +static inline BOOL FS_IsBusy(volatile const FSFile * p_file) +{ + return p_file->stat & FS_FILE_STATUS_BUSY ? TRUE : FALSE; +} + +static inline BOOL FS_IsSucceeded(volatile const FSFile * p_file) +{ + return (p_file->error == FS_RESULT_SUCCESS) ? TRUE : FALSE; +} #endif //NITRO_FS_FILE_H_ diff --git a/arm9/lib/include/FS_mw_dtor.h b/arm9/lib/include/FS_mw_dtor.h new file mode 100644 index 00000000..a746ed19 --- /dev/null +++ b/arm9/lib/include/FS_mw_dtor.h @@ -0,0 +1,16 @@ +#ifndef NITRO_FS_MW_DTOR_H_ +#define NITRO_FS_MW_DTOR_H_ + +typedef void (*MWI_DESTRUCTOR_FUNC) (void *); + +typedef struct MWiDestructorChain +{ + struct MWiDestructorChain *next; + MWI_DESTRUCTOR_FUNC dtor; + void *obj; +} +MWiDestructorChain; + +extern MWiDestructorChain *__global_destructor_chain; + +#endif //NITRO_FS_MW_DTOR_H_ diff --git a/arm9/lib/include/FS_overlay.h b/arm9/lib/include/FS_overlay.h index c2634509..1ef6469c 100644 --- a/arm9/lib/include/FS_overlay.h +++ b/arm9/lib/include/FS_overlay.h @@ -30,6 +30,21 @@ typedef struct FSOverlayInfo CARDRomRegion file_pos; } FSOverlayInfo; +static inline u8 *const FS_GetOverlayAddress(FSOverlayInfo * p_ovi) +{ + return p_ovi->header.ram_address; +} + +static inline u32 const FS_GetOverlayImageSize(FSOverlayInfo * p_ovi) +{ + return p_ovi->header.ram_size; +} + +static inline u32 const FS_GetOverlayTotalSize(FSOverlayInfo * p_ovi) +{ + return p_ovi->header.ram_size + p_ovi->header.bss_size; +} + BOOL FS_LoadOverlayInfo(FSOverlayInfo *p_ovi, MIProcessor target, FSOverlayID id); BOOL FS_LoadOverlay(MIProcessor target, FSOverlayID id); BOOL FS_UnloadOverlay(MIProcessor target, FSOverlayID id); diff --git a/arm9/lib/include/FS_rom.h b/arm9/lib/include/FS_rom.h index fc62b579..0bba46bf 100644 --- a/arm9/lib/include/FS_rom.h +++ b/arm9/lib/include/FS_rom.h @@ -1,6 +1,13 @@ #ifndef NITRO_FS_ROM_H_ #define NITRO_FS_ROM_H_ +#include "FS_archive.h" +#include "CARD_rom.h" + +extern FSArchive fsi_arc_rom; +extern CARDRomRegion fsi_ovt7; +extern CARDRomRegion fsi_ovt9; + void FSi_InitRom(u32 default_dma_no); #endif //NITRO_FS_ROM_H_ diff --git a/arm9/lib/include/MI_memory.h b/arm9/lib/include/MI_memory.h new file mode 100644 index 00000000..d9935a5f --- /dev/null +++ b/arm9/lib/include/MI_memory.h @@ -0,0 +1,10 @@ +#ifndef NITRO_MI_MEMORY_H_ +#define NITRO_MI_MEMORY_H_ + +void MI_CpuFill8(void *dest, u8 data, u32 size); +void MI_CpuCopy8(void const *src, void *dest, u32 size); +static inline void MI_CpuClear8(void *dest, u32 size) { + MI_CpuFill8(dest, 0, size); +} + +#endif //NITRO_MI_MEMORY_H_ diff --git a/arm9/lib/include/MI_uncompress.h b/arm9/lib/include/MI_uncompress.h new file mode 100644 index 00000000..55f28e27 --- /dev/null +++ b/arm9/lib/include/MI_uncompress.h @@ -0,0 +1,6 @@ +#ifndef NITRO_MI_UNCOMPRESS_H_ +#define NITRO_MI_UNCOMPRESS_H_ + +void MIi_UncompressBackward(void * bottom); + +#endif //NITRO_MI_UNCOMPRESS_H_ diff --git a/arm9/lib/include/OS_cache.h b/arm9/lib/include/OS_cache.h new file mode 100644 index 00000000..bee42d45 --- /dev/null +++ b/arm9/lib/include/OS_cache.h @@ -0,0 +1,9 @@ +#ifndef NITRO_OS_CACHE_H_ +#define NITRO_OS_CACHE_H_ + +void IC_InvalidateRange(void *startAddr, u32 nBytes); +void IC_FlushRange(void *startAddr, u32 nBytes); +void DC_InvalidateRange(void *startAddr, u32 nBytes); +void DC_FlushRange(void *startAddr, u32 nBytes); + +#endif //NITRO_OS_CACHE_H_ diff --git a/arm9/lib/include/OS_system.h b/arm9/lib/include/OS_system.h index 65c58f57..1b263b19 100644 --- a/arm9/lib/include/OS_system.h +++ b/arm9/lib/include/OS_system.h @@ -36,5 +36,10 @@ OSIntrMode OS_GetCpsrIrq(); OSProcMode OS_GetProcMode(); void OS_SpinWait(); void OS_WaitVBlankIntr(); +void OS_Terminate(void); +static inline void OS_TPanic(const char * message) +{ + OS_Terminate(); +} #endif //POKEDIAMOND_OS_SYSTEM_H diff --git a/arm9/lib/include/OS_thread.h b/arm9/lib/include/OS_thread.h index 8820a7a0..c5602559 100644 --- a/arm9/lib/include/OS_thread.h +++ b/arm9/lib/include/OS_thread.h @@ -29,6 +29,7 @@ struct _OSThread }; void OS_SleepThread(OSThreadQueue * queue); +void OS_WakeupThread(OSThreadQueue * queue); static inline void OS_InitThreadQueue(OSThreadQueue * queue) { queue->head = queue->tail = NULL; diff --git a/arm9/lib/src/FS_archive.c b/arm9/lib/src/FS_archive.c new file mode 100644 index 00000000..39daa324 --- /dev/null +++ b/arm9/lib/src/FS_archive.c @@ -0,0 +1,147 @@ +#include "FS_archive.h" +#include "FS_file.h" +#include "FS_command.h" +#include "MI_memory.h" +#include "MI_byteAccess.h" + +FSArchive * arc_list = NULL; +FSDirPos current_dir_pos; + +u32 FSi_GetPackedName(const char * name, int name_len) +{ + u32 ret = 0; + if (name_len <= FS_ARCHIVE_NAME_LEN_MAX) + { + int i = 0; + for (; i < name_len; i++) + { + u32 c = MI_ReadByte(name + i); + if (!c) + break; + c = (u32)(c - 'A'); + if (c <= (u32)('Z' - 'A')) + c = (u32)(c + 'a'); + else + c = (u32)(c + 'A'); + ret |= (u32)(c << (i * 8)); + } + } + return ret; +} + +FSResult FSi_ReadMemCallback(FSArchive * p_arc, u8 * dest, u32 offset, u32 size) +{ + MI_CpuCopy8((const void *)FS_GetArchiveOffset(p_arc, offset), dest, size); + return FS_RESULT_SUCCESS; +} + +FSResult FSi_WriteMemCallback(FSArchive * p_arc, const u8 * src, u32 offset, u32 size) +{ + MI_CpuCopy8(src, (void *)FS_GetArchiveOffset(p_arc, offset), size); + return FS_RESULT_SUCCESS; +} + +FSResult FSi_ReadMemoryCore(FSArchive * p_arc, u8 * dest, u32 offset, u32 size) +{ + MI_CpuCopy8((const void *)offset, dest, size); + return FS_RESULT_SUCCESS; +} + +FSFile * FSi_NextCommand(FSArchive * p_arc) +{ + OSIntrMode bak_psr = OS_DisableInterrupts(); + if (FSi_IsArchiveCanceling(p_arc)) + { + FSFile *p, *q; + p_arc->flag &= ~FS_ARCHIVE_FLAG_CANCELING; + for (p = p_arc->list.next; p; p = q) + { + q = p->link.next; + if (FS_IsCanceling(p)) + { + if (p_arc->list.next == p) + p_arc->list.next = q; + FSi_ReleaseCommand(p, FS_RESULT_CANCELED); + if (!q) + q = p_arc->list.next; + } + } + } + if (!FSi_IsArchiveSuspending(p_arc) && !FS_IsArchiveSuspended(p_arc)) + { + FSFile * p_file = p_arc->list.next; + if (p_file != NULL) + { + const BOOL is_start = !FSi_IsArchiveRunning(p_arc); + if (is_start) + p_arc->flag |= FS_ARCHIVE_FLAG_RUNNING; + OS_RestoreInterrupts(bak_psr); + if (is_start) + { + if ((p_arc->proc_flag & FS_ARCHIVE_PROC_ACTIVATE) != 0) + (*p_arc->proc) (p_file, FS_COMMAND_ACTIVATE); + } + bak_psr = OS_DisableInterrupts(); + p_file->stat |= FS_FILE_STATUS_OPERATING; + if (FS_IsFileSyncMode(p_file)) + { + OS_WakeupThread(p_file->queue); + OS_RestoreInterrupts(bak_psr); + return NULL; + } + OS_RestoreInterrupts(bak_psr); + return p_file; + } + } + if (FSi_IsArchiveRunning(p_arc)) + { + p_arc->flag &= ~FS_ARCHIVE_FLAG_RUNNING; + if (p_arc->proc_flag & FS_ARCHIVE_PROC_IDLE) + { + FSFile tmp; + FS_InitFile(&tmp); + tmp.arc = p_arc; + (*p_arc->proc)(&tmp, FS_COMMAND_IDLE); + } + } + if (FSi_IsArchiveSuspending(p_arc)) + { + p_arc->flag &= ~FS_ARCHIVE_FLAG_SUSPENDING; + p_arc->flag |= FS_ARCHIVE_FLAG_SUSPEND; + OS_WakeupThread(&p_arc->stat_q); + } + OS_RestoreInterrupts(bak_psr); + return NULL; +} + +void FSi_ExecuteAsyncCommand(FSFile * p_file) +{ + FSArchive *const p_arc = p_file->arc; + while (p_file) + { + OSIntrMode bak_psr = OS_DisableInterrupts(); + p_file->stat |= FS_FILE_STATUS_OPERATING; + if (FS_IsFileSyncMode(p_file)) + { + OS_WakeupThread(p_file->queue); + OS_RestoreInterrupts(bak_psr); + break; + } + p_file->stat |= FS_FILE_STATUS_ASYNC; + OS_RestoreInterrupts(bak_psr); + if (FSi_TranslateCommand(p_file, p_file->command) == FS_RESULT_PROC_ASYNC) + break; + p_file = FSi_NextCommand(p_arc); + } +} + +BOOL FSi_ExecuteSyncCommand(FSFile * p_file) +{ + FSFile * p_target; + FSResult ret = FSi_TranslateCommand(p_file, p_file->command); + FSi_ReleaseCommand(p_file, ret); + p_target = FSi_NextCommand(p_file->arc); + if (p_target) + FSi_ExecuteAsyncCommand(p_target); + return FS_IsSucceeded(p_file); +} diff --git a/arm9/lib/src/FS_file.c b/arm9/lib/src/FS_file.c index 8ca89af8..479a5085 100644 --- a/arm9/lib/src/FS_file.c +++ b/arm9/lib/src/FS_file.c @@ -11,16 +11,6 @@ static inline BOOL FSi_IsSlash(u32 c) return (c == '/') || (c == '\\'); } -static inline BOOL FS_IsBusy(volatile const FSFile * p_file) -{ - return p_file->stat & FS_FILE_STATUS_BUSY ? TRUE : FALSE; -} - -static inline BOOL FS_IsSucceeded(volatile const FSFile * p_file) -{ - return p_file->error == FS_RESULT_SUCCESS ? TRUE : FALSE; -} - void FS_Init(u32 default_dma_no) { if (!is_init) diff --git a/arm9/lib/src/FS_overlay.c b/arm9/lib/src/FS_overlay.c new file mode 100644 index 00000000..d8d53570 --- /dev/null +++ b/arm9/lib/src/FS_overlay.c @@ -0,0 +1,297 @@ +#include "nitro.h" +#include "DGT_common.h" +#include "DGT_dgt.h" +#include "OS_cache.h" +#include "OS_system.h" +#include "MI_memory.h" +#include "MI_uncompress.h" +#include "FS_rom.h" +#include "FS_overlay.h" +#include "FS_mw_dtor.h" +#include "MB_mb.h" + +#define FS_OVERLAY_FLAG_COMP 0x0001 +#define FS_OVERLAY_FLAG_AUTH 0x0002 +#define FS_OVERLAY_DIGEST_SIZE DGT_HASH2_DIGEST_SIZE + +u32 FSi_GetOverlayBinarySize(FSOverlayInfo * p_ovi) +{ + u32 size = (p_ovi->header.flag & FS_OVERLAY_FLAG_COMP) + ? p_ovi->header.compressed + : p_ovi->header.ram_size; + return size; +} + +void FS_ClearOverlayImage(FSOverlayInfo * p_ovi) +{ + u8 * const im_start = FS_GetOverlayAddress(p_ovi); + u32 const ram_size = FS_GetOverlayImageSize(p_ovi); + u32 const total_size = FS_GetOverlayTotalSize(p_ovi); + + IC_InvalidateRange(im_start, total_size); + DC_InvalidateRange(im_start, total_size); + MI_CpuFill8(im_start + ram_size, 0, total_size - ram_size); +} + +FSFileID FS_GetOverlayFileID(FSOverlayInfo * p_ovi) +{ + FSFileID ret; + ret.arc = &fsi_arc_rom; + ret.file_id = p_ovi->header.file_id; + return ret; +} + +BOOL FSi_LoadOverlayInfoCore(FSOverlayInfo * p_ovi, MIProcessor target, FSOverlayID id, FSArchive * arc, u32 offset_arm9, u32 len_arm9, u32 offset_arm7, u32 len_arm7) +{ + CARDRomRegion pr[1]; + u32 pos; + if (target == MI_PROCESSOR_ARM9) + { + pr->offset = offset_arm9; + pr->length = len_arm9; + } + else + { + pr->offset = offset_arm7; + pr->length = len_arm7; + } + pos = (u32) id * sizeof(FSOverlayInfoHeader); + if (pos >= pr->length) + return FALSE; + + FSFile file[1]; + FS_InitFile(file); + // BOOL FS_OpenFileDirect(FSFile * p_file, FSArchive * p_arc, u32 image_top, u32 image_bottom, u32 file_index) + if (!FS_OpenFileDirect(file, arc, pr->offset + pos, pr->offset + pr->length, (u32)~0)) + return FALSE; + if (FS_ReadFile(file, p_ovi, sizeof(FSOverlayInfoHeader)) != sizeof(FSOverlayInfoHeader)) + { + FS_CloseFile(file); + return FALSE; + } + FS_CloseFile(file); + p_ovi->target = target; + if (!FS_OpenFileFast(file, FS_GetOverlayFileID(p_ovi))) + return FALSE; + p_ovi->file_pos.offset = FS_GetFileImageTop(file); + p_ovi->file_pos.length = FS_GetLength(file); + FS_CloseFile(file); + return TRUE; +} + +BOOL FS_LoadOverlayInfo(FSOverlayInfo * p_ovi, MIProcessor target, FSOverlayID id) +{ + CARDRomRegion * const pr = (target == MI_PROCESSOR_ARM9) ? &fsi_ovt9 : &fsi_ovt7; + if (pr->offset) + { + FSFile file[1]; + const u32 pos = id * sizeof(FSOverlayInfoHeader); + if (pos >= pr->length) + return FALSE; + MI_CpuCopy8((const void *)(pr->offset + pos), p_ovi, sizeof(FSOverlayInfoHeader)); + p_ovi->target = target; + FS_InitFile(file); + if (!FS_OpenFileFast(file, FS_GetOverlayFileID(p_ovi))) + return FALSE; + p_ovi->file_pos.offset = FS_GetFileImageTop(file); + p_ovi->file_pos.length = FS_GetLength(file); + FS_CloseFile(file); + return TRUE; + } + else + { + const CARDRomRegion * const p_ovt9 = CARD_GetRomRegionOVT(MI_PROCESSOR_ARM9); + const CARDRomRegion * const p_ovt7 = CARD_GetRomRegionOVT(MI_PROCESSOR_ARM7); + return FSi_LoadOverlayInfoCore(p_ovi, target, id, &fsi_arc_rom, p_ovt9->offset, p_ovt9->length, p_ovt7->offset, p_ovt7->length); + } +} + +BOOL FS_LoadOverlayImageAsync(FSOverlayInfo * p_ovi, FSFile * p_file) +{ + FS_InitFile(p_file); + if (!FS_OpenFileFast(p_file, FS_GetOverlayFileID(p_ovi))) + return FALSE; + else + { + s32 size = FSi_GetOverlayBinarySize(p_ovi); + FS_ClearOverlayImage(p_ovi); + if (FS_ReadFileAsync(p_file, FS_GetOverlayAddress(p_ovi), size) != size) + { + FS_CloseFile(p_file); + return FALSE; + } + return TRUE; + } +} + +BOOL FS_LoadOverlayImage(FSOverlayInfo * p_ovi) +{ + FSFile file[1]; + FS_InitFile(file); + if (!FS_OpenFileFast(file, FS_GetOverlayFileID(p_ovi))) + return FALSE; + else + { + s32 size = FSi_GetOverlayBinarySize(p_ovi); + FS_ClearOverlayImage(p_ovi); + if (FS_ReadFile(file, FS_GetOverlayAddress(p_ovi), size) != size) + { + FS_CloseFile(file); + return FALSE; + } + FS_CloseFile(file); + return TRUE; + } +} + +const void *fsi_digest_key_ptr; +u32 fsi_digest_key_len; + +BOOL FSi_CompareDigest(const u8 *spec_digest, void *src, int len) +{ + int i; + u8 digest[FS_OVERLAY_DIGEST_SIZE]; + u8 digest_key[64]; + + MI_CpuClear8(digest, sizeof(digest)); + MI_CpuCopy8(fsi_digest_key_ptr, digest_key, fsi_digest_key_len); + DGT_Hash2CalcHmac(digest, src, len, digest_key, fsi_digest_key_len); + for (i = 0; i < sizeof(digest); i += sizeof(u32)) + { + if (*(const u32 *)(digest + i) != *(const u32 *)(spec_digest + i)) + break; + } + return i == sizeof(digest); +} + +extern u8 SDK_OVERLAY_DIGEST[]; +extern u8 SDK_OVERLAY_DIGEST_END[]; + +void FS_StartOverlay(FSOverlayInfo * p_ovi) +{ + u32 rare_size = FSi_GetOverlayBinarySize(p_ovi); + if (MB_IsMultiBootChild()) + { + BOOL ret = FALSE; + + if (p_ovi->header.flag & FS_OVERLAY_FLAG_AUTH) + { + const u32 odt_max = (u32)((SDK_OVERLAY_DIGEST_END - SDK_OVERLAY_DIGEST) / FS_OVERLAY_DIGEST_SIZE); + if (p_ovi->header.id < odt_max) + { + const u8 * spec_digest = SDK_OVERLAY_DIGEST + FS_OVERLAY_DIGEST_SIZE * p_ovi->header.id; + ret = FSi_CompareDigest(spec_digest, p_ovi->header.ram_address, (int)rare_size); + } + } + if (!ret) + { + MI_CpuClear8(p_ovi->header.ram_address, rare_size); + OS_TPanic("FS_StartOverlay() failed! (invalid overlay-segment data)"); + return; + } + } + if (p_ovi->header.flag & FS_OVERLAY_FLAG_COMP) + { + MIi_UncompressBackward(p_ovi->header.ram_address + rare_size); + } + DC_FlushRange(p_ovi->header.ram_address, p_ovi->header.ram_size); + + { + FSOverlayInitFunc *p = p_ovi->header.sinit_init; + FSOverlayInitFunc *q = p_ovi->header.sinit_init_end; + for (; p < q; ++p) + { + if (*p) + (**p)(); + } + } +} + +void FS_EndOverlay(FSOverlayInfo *p_ovi) +{ + for (;;) + { + MWiDestructorChain *head = NULL, *tail = NULL; + const u32 region_top = (u32)FS_GetOverlayAddress(p_ovi); + const u32 region_bottom = region_top + FS_GetOverlayTotalSize(p_ovi); + + { + OSIntrMode bak_psr = OS_DisableInterrupts(); + MWiDestructorChain *prev = NULL; + MWiDestructorChain *base = __global_destructor_chain; + MWiDestructorChain *p = base; + while (p) + { + MWiDestructorChain *next = p->next; + const u32 dtor = (u32)p->dtor; + const u32 obj = (u32)p->obj; + if (((obj == 0) && (dtor >= region_top) && (dtor < region_bottom)) || + ((obj >= region_top) && (obj < region_bottom))) + { + /* If appropriate, extract*/ + if (!tail) + { + head = p; + } + else + { + tail->next = p; + } + if (base == p) + { + base = __global_destructor_chain = next; + } + tail = p, p->next = NULL; + if (prev) + { + prev->next = next; + } + } + else + { + prev = p; + } + p = next; + } + OS_RestoreInterrupts(bak_psr); + } + + if (!head) + { + break; + } + do + { + MWiDestructorChain *next = head->next; + if (head->dtor) + { + (*head->dtor) (head->obj); + } + head = next; + } + while (head); + } +} + +BOOL FS_UnloadOverlayImage(FSOverlayInfo * p_ovi) +{ + FS_EndOverlay(p_ovi); + return TRUE; +} + +BOOL FS_LoadOverlay(MIProcessor target, FSOverlayID id) +{ + FSOverlayInfo ovi; + if (!FS_LoadOverlayInfo(&ovi, target, id) || !FS_LoadOverlayImage(&ovi)) + return FALSE; + FS_StartOverlay(&ovi); + return TRUE; +} + +BOOL FS_UnloadOverlay(MIProcessor target, FSOverlayID id) +{ + FSOverlayInfo ovi; + if (!FS_LoadOverlayInfo(&ovi, target, id) || !FS_UnloadOverlayImage(&ovi)) + return FALSE; + return TRUE; +} |