Write ARM9 module info in buildrom

This commit is contained in:
Aetias
2024-02-03 18:15:20 +01:00
parent fc98f547c5
commit ed32e278b1
4 changed files with 120 additions and 34 deletions
+10 -6
View File
@@ -911,17 +911,21 @@ func_02000b60: ; 0x02000b60
.global spAutoloadBlockInfosStart
spAutoloadBlockInfosStart: ; 0x02000b64
.word 0x02060fc0
.word 0x0
.global spAutoloadBlockInfosEnd
spAutoloadBlockInfosEnd: ; 0x02000b68
.word 0x02060fd8
.word 0x0
.global spAutoloadCode
spAutoloadCode: ; 0x02000b6c
.word 0x02058e20
.word 0x0
.global spBssStart
spBssStart: ; 0x02000b70
.word 0x02058e20
.word 0x0
.global spBssEnd
spBssEnd: ; 0x02000b74
.word 0x020773c0
.word 0x0
sCompressedCodeEnd: ; 0x02000b78
.word 0x02041a64
.word 0x0
sSdkVersion: ; 0x02000b7c
.word 0x04007530
.word 0xdec00621 ; nitrocode
+12
View File
@@ -269,9 +269,11 @@ with open(f'{BUILD}arm9_linker_script.lcf', 'w') as file:
for obj in ARM9_OBJECTS: file.write(f' {name(obj)}.o(.sinit)\n')
file.write(' . = ALIGN(32);\n')
for obj in ARM9_OBJECTS: file.write(f' {name(obj)}.o(.data)\n')
file.write(' arm9_bss_start = .;\n')
for obj in ARM9_OBJECTS: file.write(f' {name(obj)}.o(.bss)\n')
for obj in ARM9_OBJECTS: file.write(f' {name(obj)}.o(.sbss)\n')
file.write(' . = ALIGN(32);\n')
file.write(' arm9_bss_end = .;\n')
file.write(' } > ARM9\n')
file.write('\n')
file.write(' .itcm : {\n')
@@ -291,13 +293,18 @@ with open(f'{BUILD}arm9_linker_script.lcf', 'w') as file:
for obj in DTCM_OBJECTS: file.write(f' {name(obj)}.o(.data)\n')
file.write(' dtcm_end = .;\n')
file.write(' dtcm_size = dtcm_end - dtcm_start;\n')
file.write(' . = ALIGN(32);\n')
file.write(' dtcm_end = .;\n')
file.write(' dtcm_aligned_size = dtcm_end - dtcm_start;\n')
for obj in DTCM_OBJECTS: file.write(f' {name(obj)}.o(.bss)\n')
for obj in DTCM_OBJECTS: file.write(f' {name(obj)}.o(.sbss)\n')
file.write(' } > DTCM\n')
file.write('\n')
file.write(' .autoloads : {\n')
file.write(' autoloads_start = arm9_bss_start + itcm_size + dtcm_size;\n')
file.write(' WRITEW ADDR(ITCM); WRITEW itcm_size; WRITEW 0;\n')
file.write(' WRITEW ADDR(DTCM); WRITEW dtcm_size; WRITEW 0xec0;\n')
file.write(' autoloads_end = . + autoloads_start;\n')
file.write(' } > AUTOLOADS\n')
file.write('\n')
file.write(' .footer : {\n')
@@ -311,6 +318,11 @@ with open(f'{BUILD}arm9_linker_script.lcf', 'w') as file:
file.write(' WRITEW spAutoloadBlockInfosStart - ADDR(ARM9);\n')
file.write(' WRITEW Entry;\n')
file.write(' WRITEW ADDR(ARM9);\n')
file.write(' WRITEW autoloads_start;\n')
file.write(' WRITEW autoloads_end;\n')
file.write(' WRITEW arm9_bss_start;\n')
file.write(' WRITEW arm9_bss_start;\n')
file.write(' WRITEW arm9_bss_end;\n')
file.write(' } > METADATA\n')
file.write('\n')
for ov in OVERLAYS:
+96 -28
View File
@@ -8,7 +8,7 @@
#include "util.h"
#include "files.h"
#define VERSION "1.0.1"
#define VERSION "1.1"
#define BUFFER_SIZE 1024 * 1024
uint8_t *readBuffer = NULL;
@@ -184,6 +184,57 @@ void InitHeader(Header *pHeader, const BuildInfo *info) {
memset(&pHeader->reserved7, 0, sizeof(pHeader->reserved7));
}
typedef struct {
uint32_t autoloadBlocksStart;
uint32_t autoloadBlocksEnd;
uint32_t autoloadCode;
uint32_t bssStart;
uint32_t bssEnd;
} Arm9ModuleInfo;
typedef struct {
uint32_t autoloadCallback;
uint32_t autoloadBlockInfos;
uint32_t entryAddr;
uint32_t baseAddr;
Arm9ModuleInfo moduleInfo;
} Arm9Metadata;
bool LoadArm9Metadata(Arm9Metadata *pMetadata) {
FILE *fp = fopen(ARM9_METADATA_FILE, "rb");
if (fp == NULL) FATAL("Failed to open ARM9 metadata '" ARM9_METADATA_FILE "'\n");
if (fread(pMetadata, sizeof(*pMetadata), 1, fp) != 1) FATAL("Failed to read ARM9 metadata '" ARM9_METADATA_FILE "'\n");
fclose(fp);
return true;
}
// Reads an entire file into a newly allocated buffer and writes it to *pBuffer if successful.
// If pFileSize != NULL, this function writes the file's size into *pFileSize.
// The buffer can be freed with free().
bool ReadFile(const char *filePath, uint8_t **pBuffer, uint32_t *pFileSize) {
FILE *fp = fopen(filePath, "rb");
if (fp == NULL) FATAL("Failed to open file '%s'\n", filePath);
fseek(fp, 0, SEEK_END);
size_t size = ftell(fp);
fseek(fp, 0, SEEK_SET);
uint8_t *buffer = malloc(size);
if (buffer == NULL) FATAL("Failed to allocate buffer for file '%s'\n", filePath);
uint8_t *current = buffer;
uint8_t *end = buffer + size;
while (current < end) {
size_t bytesRead = fread(current, 1, BUFFER_SIZE, fp);
if (bytesRead == 0) FATAL("Failed to read from file '%s'\n", filePath);
current += bytesRead;
}
fclose(fp);
*pBuffer = buffer;
if (pFileSize != NULL) *pFileSize = size;
return true;
}
bool AppendFile(FILE *fpRom, const char *filePath, size_t *pAddress, uint32_t *pFileSize) {
assert(readBuffer != NULL);
@@ -207,6 +258,37 @@ bool AppendFile(FILE *fpRom, const char *filePath, size_t *pAddress, uint32_t *p
return true;
}
bool WriteArm9Program(FILE *fpRom, size_t *pAddress, uint32_t *pFileSize, uint32_t *pSecureArea, const Arm9Metadata *metadata) {
size_t address = *pAddress;
uint8_t *arm9;
uint32_t fileSize;
if (!ReadFile(ARM9_PROGRAM_FILE, &arm9, &fileSize)) return false;
// Write module info, see spAutoloadBlockInfosStart in asm/main.s
// This might seem unsafe since the ARM9 program is compressed, but the addresses we're writing to are in the secure area,
// which is uncompressed.
size_t offset = metadata->autoloadBlockInfos;
// First five values, from spAutoloadBlockInfosStart to spBssEnd
memcpy(&arm9[offset], &metadata->moduleInfo, sizeof(metadata->moduleInfo));
offset += sizeof(metadata->moduleInfo);
// Last value, sCompressedCodeEnd
uint32_t compressedCodeEnd = 0x2000000 + fileSize;
memcpy(&arm9[offset], &compressedCodeEnd, sizeof(compressedCodeEnd));
offset += compressedCodeEnd;
if (fwrite(arm9, fileSize, 1, fpRom) != 1) FATAL("Failed to write ARM9 program\n");
address += fileSize;
memcpy(pSecureArea, arm9, SECURE_AREA_SIZE);
free(arm9);
*pAddress = address;
*pFileSize = fileSize;
return true;
}
bool Align(size_t alignment, FILE *fpRom, size_t *pAddress) {
assert((alignment & (alignment - 1)) == 0);
@@ -661,25 +743,12 @@ bool RewriteFat(FILE *fpRom, size_t fatStart, const FatEntry *entries, size_t nu
return true;
}
typedef struct {
uint32_t autoloadCallback;
uint32_t autoloadBlockInfos;
uint32_t entryAddr;
uint32_t baseAddr;
} Arm9Metadata;
bool FinalizeHeader(FILE *fpRom, Header *pHeader, const char *arm7bios) {
bool FinalizeHeader(FILE *fpRom, Header *pHeader, const char *arm7bios, uint32_t *secureArea, const Arm9Metadata *metadata) {
Header header;
memcpy(&header, pHeader, sizeof(header));
if (arm7bios != NULL) {
FILE *fp = fopen(ARM9_PROGRAM_FILE, "rb");
if (fp == NULL) FATAL("Failed to open ARM9 program '" ARM9_PROGRAM_FILE "'\n");
uint32_t secureArea[0x1000];
if (fread(secureArea, sizeof(secureArea), 1, fp) != 1) FATAL("Failed to read secure area\n");
fclose(fp);
fp = fopen(arm7bios, "rb");
FILE *fp = fopen(arm7bios, "rb");
if (fp == NULL) FATAL("Failed to open ARM7 BIOS '%s'\n", arm7bios);
fseek(fp, 0x30, SEEK_SET);
uint8_t encKey[sizeof(Blowfish)];
@@ -694,18 +763,13 @@ bool FinalizeHeader(FILE *fpRom, Header *pHeader, const char *arm7bios) {
BlowfishEncrypt(&secureArea[0], &secureArea[1]);
if (!BlowfishInit(encKey, pHeader, 2)) return false;
BlowfishEncrypt(&secureArea[0], &secureArea[1]);
header.secureAreaCrc = Crc(secureArea, 0x4000);
header.secureAreaCrc = Crc(secureArea, SECURE_AREA_SIZE);
}
FILE *fp = fopen(ARM9_METADATA_FILE, "rb");
if (fp == NULL) FATAL("Failed to open ARM9 metadata '" ARM9_METADATA_FILE "'\n");
Arm9Metadata metadata;
if (fread(&metadata, sizeof(metadata), 1, fp) != 1) FATAL("Failed to read ARM9 metadata '" ARM9_METADATA_FILE "'\n");
fclose(fp);
header.arm9.entry = metadata.entryAddr;
header.arm9.baseAddr = metadata.baseAddr;
header.arm9AutoloadCallback = metadata.autoloadCallback;
header.autoloadBlockInfosOffset = header.arm9.offset + metadata.autoloadBlockInfos;
header.arm9.entry = metadata->entryAddr;
header.arm9.baseAddr = metadata->baseAddr;
header.arm9AutoloadCallback = metadata->autoloadCallback;
header.autoloadBlockInfosOffset = header.arm9.offset + metadata->autoloadBlockInfos;
header.headerCrc = Crc(&header, offsetof(Header, headerCrc));
@@ -877,7 +941,11 @@ int main(int argc, char **argv) {
if (!Align(512, fpRom, &address)) return 1;
header.arm9.offset = address;
if (!AppendFile(fpRom, ARM9_PROGRAM_FILE, &address, &header.arm9.size)) return 1;
Arm9Metadata metadata;
if (!LoadArm9Metadata(&metadata)) return 1;
uint32_t secureArea[SECURE_AREA_SIZE / sizeof(uint32_t)];
if (!WriteArm9Program(fpRom, &address, &header.arm9.size, secureArea, &metadata)) return 1;
if (!AppendFile(fpRom, ARM9_FOOTER_FILE, &address, NULL)) return 1;
@@ -986,7 +1054,7 @@ int main(int argc, char **argv) {
return 1;
}
if (!FinalizeHeader(fpRom, &header, arm7bios)) return false;
if (!FinalizeHeader(fpRom, &header, arm7bios, secureArea, &metadata)) return false;
FreeFullPath(&arm7bios);
if (chdir(rootDir) != 0) {
+2
View File
@@ -5,6 +5,8 @@
#include <stddef.h>
#include <stdint.h>
#define SECURE_AREA_SIZE 0x4000
typedef struct {
/* 00 */ uint32_t offset;
/* 04 */ uint32_t entry;