2016-12-22 01:35:35 +01:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "common.h"
|
|
|
|
|
|
|
|
#define FIRM_MAGIC 'F', 'I', 'R', 'M'
|
|
|
|
|
2017-02-03 02:21:16 +01:00
|
|
|
#define FIRM_MAX_SIZE 0x400000 // 4MB, due to FIRM partition size
|
2017-02-12 16:00:59 +01:00
|
|
|
#define ARM11NCCH_OFFSET 0, 0x2A000, 0x2B000, 0x2C000
|
2016-12-22 01:35:35 +01:00
|
|
|
#define ARM9BIN_OFFSET 0x800
|
2017-09-29 03:14:06 +02:00
|
|
|
// ARM9 entrypoint after decryption - TWL/AGB and NATIVE/SAFE_MODE
|
|
|
|
// see: https://github.com/AuroraWright/Luma3DS/blob/master/source/firm.c#L349
|
|
|
|
// and: https://github.com/AuroraWright/Luma3DS/blob/master/source/firm.c#L424
|
|
|
|
// and: https://github.com/AuroraWright/Luma3DS/blob/master/source/firm.c#L463
|
|
|
|
#define ARM9ENTRY_FIX(firm) (((firm)->sections[3].offset) ? 0x801301C : 0x0801B01C)
|
2016-12-22 01:35:35 +01:00
|
|
|
|
2017-09-12 01:52:46 +02:00
|
|
|
#define FIRM_NDMA_CPY 0
|
|
|
|
#define FIRM_XDMA_CPY 1
|
|
|
|
#define FIRM_CPU_MEMCPY 2
|
|
|
|
|
2017-09-29 03:14:06 +02:00
|
|
|
#define IsInstallableFirm(firm, firm_size) (ValidateFirm(firm, firm_size, true) == 0)
|
|
|
|
#define IsBootableFirm(firm, firm_size) (ValidateFirm(firm, firm_size, false) == 0)
|
|
|
|
|
|
|
|
|
2016-12-22 01:35:35 +01:00
|
|
|
// see: https://www.3dbrew.org/wiki/FIRM#Firmware_Section_Headers
|
|
|
|
typedef struct {
|
|
|
|
u32 offset;
|
|
|
|
u32 address;
|
|
|
|
u32 size;
|
2017-09-12 01:52:46 +02:00
|
|
|
u32 method;
|
2016-12-22 01:35:35 +01:00
|
|
|
u8 hash[0x20];
|
2019-07-23 14:09:18 -03:00
|
|
|
} PACKED_STRUCT FirmSectionHeader;
|
2016-12-22 01:35:35 +01:00
|
|
|
|
|
|
|
// see: https://www.3dbrew.org/wiki/FIRM#FIRM_Header
|
|
|
|
typedef struct {
|
|
|
|
u8 magic[4];
|
|
|
|
u8 dec_magic[4];
|
|
|
|
u32 entry_arm11;
|
|
|
|
u32 entry_arm9;
|
2017-08-20 15:31:30 +02:00
|
|
|
u8 reserved0[0x30];
|
2016-12-22 01:35:35 +01:00
|
|
|
FirmSectionHeader sections[4];
|
|
|
|
u8 signature[0x100];
|
|
|
|
} __attribute__((packed, aligned(16))) FirmHeader;
|
|
|
|
|
|
|
|
// see: https://www.3dbrew.org/wiki/FIRM#New_3DS_FIRM
|
|
|
|
typedef struct {
|
|
|
|
u8 keyX0x15[0x10]; // this is encrypted
|
|
|
|
u8 keyY0x150x16[0x10];
|
|
|
|
u8 ctr[0x10];
|
|
|
|
char size_ascii[0x8];
|
|
|
|
u8 reserved[0x8];
|
|
|
|
u8 control[0x10];
|
|
|
|
u8 k9l[0x10];
|
|
|
|
u8 keyX0x16[0x10]; // this is encrypted
|
2019-10-03 18:44:45 +02:00
|
|
|
u8 padding[0x190];
|
2016-12-22 01:35:35 +01:00
|
|
|
} __attribute__((packed, aligned(16))) FirmA9LHeader;
|
|
|
|
|
2017-02-03 02:21:16 +01:00
|
|
|
u32 ValidateFirmHeader(FirmHeader* header, u32 data_size);
|
2016-12-22 01:35:35 +01:00
|
|
|
u32 ValidateFirmA9LHeader(FirmA9LHeader* header);
|
2017-08-20 15:31:30 +02:00
|
|
|
u32 ValidateFirm(void* firm, u32 firm_size, bool installable);
|
2017-09-27 01:32:26 +02:00
|
|
|
u32 GetFirmSize(FirmHeader* header);
|
2016-12-22 19:00:03 +01:00
|
|
|
|
2016-12-22 01:35:35 +01:00
|
|
|
FirmSectionHeader* FindFirmArm9Section(FirmHeader* firm);
|
2016-12-22 19:00:03 +01:00
|
|
|
u32 GetArm9BinarySize(FirmA9LHeader* a9l);
|
2016-12-22 01:35:35 +01:00
|
|
|
|
2016-12-22 19:00:03 +01:00
|
|
|
u32 SetupArm9BinaryCrypto(FirmA9LHeader* header);
|
2016-12-22 01:35:35 +01:00
|
|
|
u32 DecryptA9LHeader(FirmA9LHeader* header);
|
2017-06-01 15:11:41 +02:00
|
|
|
u32 DecryptFirm(void* data, u32 offset, u32 size, FirmHeader* firm, FirmA9LHeader* a9l);
|
|
|
|
u32 DecryptArm9Binary(void* data, u32 offset, u32 size, FirmA9LHeader* a9l);
|
|
|
|
u32 DecryptFirmSequential(void* data, u32 offset, u32 size);
|
2017-09-29 03:14:06 +02:00
|
|
|
u32 DecryptFirmFull(void* data, u32 size);
|