summaryrefslogtreecommitdiff
path: root/arm9/lib
diff options
context:
space:
mode:
Diffstat (limited to 'arm9/lib')
-rw-r--r--arm9/lib/include/CARD_rom.h9
-rw-r--r--arm9/lib/include/DGT_common.h6
-rw-r--r--arm9/lib/include/DGT_dgt.h6
-rw-r--r--arm9/lib/include/FS_file.h13
-rw-r--r--arm9/lib/include/FS_mw_dtor.h16
-rw-r--r--arm9/lib/include/FS_overlay.h15
-rw-r--r--arm9/lib/include/FS_rom.h7
-rw-r--r--arm9/lib/include/MI_memory.h10
-rw-r--r--arm9/lib/include/MI_uncompress.h6
-rw-r--r--arm9/lib/include/OS_cache.h9
-rw-r--r--arm9/lib/include/OS_system.h5
-rw-r--r--arm9/lib/src/FS_overlay.c297
12 files changed, 399 insertions, 0 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_file.h b/arm9/lib/include/FS_file.h
index 4871b660..89f69d86 100644
--- a/arm9/lib/include/FS_file.h
+++ b/arm9/lib/include/FS_file.h
@@ -175,5 +175,18 @@ 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;
+}
#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/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;
+}