.PHONY: all
-all: loader service
+all: loader svc
mkdir -p ../out/corbenik/module
- mkdir -p ../out/corbenik/service
+ mkdir -p ../out/corbenik/svc
cp loader/loader.cxi ../out/corbenik/module/loader.cxi
- cp service/7b.bin ../out/corbenik/service/7b.bin
+ cp svc/7b.bin ../out/corbenik/svc/7b.bin
.PHONY: clean
-clean: clean_loader clean_service
- rm -rf ../out/corbenik/service
+clean: clean_loader clean_svc
+ rm -rf ../out/corbenik/svc
rm -rf ../out/corbenik/module
.PHONY: loader
clean_loader:
make -C loader clean
-.PHONY: service
-service:
- make -C service
+.PHONY: svc
+svc:
+ make -C svc
-.PHONY: clean_service
-clean_service:
- make -C service clean
+.PHONY: clean_svc
+clean_svc:
+ make -C svc clean
#ifndef __INTERP_H
#define __INTERP_H
-int execb(uint64_t tid, uint8_t *search_mem, uint32_t search_len);
+int execb(uint64_t tid, uint16_t ver, uint8_t *search_mem, uint32_t search_len);
#endif
}
static Result
-load_code(u64 progid, prog_addrs_t *shared, prog_addrs_t *original, u64 prog_handle, int is_compressed)
+load_code(u64 progid, u16 progver, prog_addrs_t *shared, prog_addrs_t *original, u64 prog_handle, int is_compressed)
{
Handle handle;
FS_Path archivePath;
}
// Patch segments
- patch_text(progid, (u8 *)shared->text_addr, shared->text_size << 12, original->text_size << 12);
- patch_data(progid, (u8 *)shared->data_addr, shared->data_size << 12, original->data_size << 12);
- patch_ro(progid, (u8 *)shared->ro_addr, shared->ro_size << 12, original->ro_size << 12);
+ patch_text(progid, progver, (u8 *)shared->text_addr, shared->text_size << 12, original->text_size << 12);
+ patch_data(progid, progver, (u8 *)shared->data_addr, shared->data_size << 12, original->data_size << 12);
+ patch_ro(progid, progver, (u8 *)shared->ro_addr, shared->ro_size << 12, original->ro_size << 12);
return 0;
}
u32 data_mem_size;
u64 progid;
u32 text_grow, data_grow, ro_grow;
+ u16 progver;
openLogger();
// load code
progid = g_exheader.arm11systemlocalcaps.programid;
+ progver = g_exheader.codesetinfo.flags.remasterversion[0] + g_exheader.codesetinfo.flags.remasterversion[1] * 0x100;
logu64(progid);
logstr(" validated params\n");
original_vaddr.total_size = original_vaddr.text_size + original_vaddr.ro_size + original_vaddr.data_size;
// Allow changing code, ro, data sizes to allow adding code
- text_grow = get_text_extend(progid, g_exheader.codesetinfo.text.codesize);
- ro_grow = get_ro_extend(progid, g_exheader.codesetinfo.ro.codesize);
- data_grow = get_data_extend(progid, g_exheader.codesetinfo.data.codesize);
+ text_grow = get_text_extend(progid, progver, g_exheader.codesetinfo.text.codesize);
+ ro_grow = get_ro_extend(progid, progver, g_exheader.codesetinfo.ro.codesize);
+ data_grow = get_data_extend(progid, progver, g_exheader.codesetinfo.data.codesize);
// One page is 4096 bytes, thus all the 4095 constants.
return res;
}
- if ((res = load_code(progid, &shared_addr, &original_vaddr, prog_handle, g_exheader.codesetinfo.flags.flag & 1)) >= 0) {
+ if ((res = load_code(progid, progver, &shared_addr, &original_vaddr, prog_handle, g_exheader.codesetinfo.flags.flag & 1)) >= 0) {
memcpy(&codesetinfo.name, g_exheader.codesetinfo.name, 8);
codesetinfo.program_id = progid;
codesetinfo.text_addr = vaddr.text_addr;
// This is only for the .data segment.
void
-patch_data(u64 progId, u8 *data, u32 size, u32 orig_size)
+patch_data(u64 progId, u16 progver, u8 *data, u32 size, u32 orig_size)
{
}
// This is only for the .ro segment.
void
-patch_ro(u64 progId, u8 *ro, u32 size, u32 orig_size)
+patch_ro(u64 progId, u16 progver, u8 *ro, u32 size, u32 orig_size)
{
}
// This is only for the .code segment.
void
-patch_text(u64 progId, u8 *text, u32 size, u32 orig_size)
+patch_text(u64 progId, u16 progver, u8 *text, u32 size, u32 orig_size)
{
if (progId == 0x0004013000008002LL)
adjust_cpu_settings(progId, text, orig_size);
- execb(progId, text, orig_size);
+ execb(progId, progver, text, orig_size);
language_emu(progId, text, orig_size);
}
// Gets how many bytes .text must be extended by for patches to fit.
u32
-get_text_extend(u64 progId, u32 size_orig)
+get_text_extend(u64 progId, u16 progver, u32 size_orig)
{
return 0; // Stub - nothing needs this yet
}
// Gets how many bytes .ro must be extended.
u32
-get_ro_extend(u64 progId, u32 size_orig)
+get_ro_extend(u64 progId, u16 progver, u32 size_orig)
{
return 0; // Stub - nothing needs this yet
}
// Again, same, but for .data.
u32
-get_data_extend(u64 progId, u32 size_orig)
+get_data_extend(u64 progId, u16 progver, u32 size_orig)
{
return 0; // Stub - nothing needs this yet
}
#include <3ds/types.h>
-void patch_text(u64 progId, u8 *text, u32 size, u32 orig_size);
-void patch_data(u64 progId, u8 *data, u32 size, u32 orig_size);
-void patch_ro(u64 progId, u8 *ro, u32 size, u32 orig_size);
+void patch_text(u64 progId, u16 progver, u8 *text, u32 size, u32 orig_size);
+void patch_data(u64 progId, u16 progver, u8 *data, u32 size, u32 orig_size);
+void patch_ro(u64 progId, u16 progver, u8 *ro, u32 size, u32 orig_size);
-u32 get_text_extend(u64 progId, u32 size_orig);
-u32 get_ro_extend(u64 progId, u32 size_orig);
-u32 get_data_extend(u64 progId, u32 size_orig);
+u32 get_text_extend(u64 progId, u16 progver, u32 size_orig);
+u32 get_ro_extend(u64 progId, u16 progver, u32 size_orig);
+u32 get_data_extend(u64 progId, u16 progver, u32 size_orig);
void load_config();
-This directory contains service fragments for ARM11. This includes svcbackdoor.
+This directory contains svc fragments for ARM11. This includes svcbackdoor.
As easy as it would be to rely on armips (bleh) I've instead taken the harder route of clever gas and objcopy use. No armips will ever be required for this repo.
#!/usr/bin/env python2
# -*- encoding: utf8 -*-
+# This assembler is very dumb and needs severe improvement.
+# Maybe I should rewrite it as an LLVM backend. That would
+# be much easier to maintain and far less hackish.
+
+# Either way, expect this code to change, a lot. The bytecode
+# format probably won't.
+
import os
import sys
import re
if s != 2:
syn_err("invalid number of arguments")
- # We cut corners and calculate stuff manually.
- return bytearray.fromhex("09") + bytearray.fromhex(token_list[1])
+ return bytearray.fromhex("0C") + bytearray.fromhex(token_list[1])
+ elif token_list[0] == "ver":
+ if s != 2:
+ syn_err("invalid number of arguments")
+
+ return bytearray.fromhex("0D") + bytearray.fromhex(token_list[1])
def pad_zero_r(x, c):
while len(x) < c:
offsets += [size]
size += len(bytes)
+ offsets += [size+1] # So we can jump past the last instruction for 'exit' type behavior
+
ins.seek(0)
for line in ins:
#ifdef DATA32_SUPPORT
*(volatile uint16_t *)0x10006100 |= 0x402u; // SDDATACTL32
#else
- *(volatile uint16_t *)0x10006100 |= 0x402u; // SDDATACTL32
+ *(volatile uint16_t *)0x10006100 |= 0x402u; // SDDATACTL32
#endif
*(volatile uint16_t *)0x100060D8 = (*(volatile uint16_t *)0x100060D8 & 0xFFDD) | 2;
#ifdef DATA32_SUPPORT
*(volatile uint16_t *)0x10006100 &= 0xFFFFu; // SDDATACTL32
*(volatile uint16_t *)0x100060D8 &= 0xFFDFu; // SDDATACTL
- *(volatile uint16_t *)0x10006104 = 512; // SDBLKLEN32
+ *(volatile uint16_t *)0x10006104 = 512; // SDBLKLEN32
#else
*(volatile uint16_t *)0x10006100 &= 0xFFFDu; // SDDATACTL32
*(volatile uint16_t *)0x100060D8 &= 0xFFDDu; // SDDATACTL
- *(volatile uint16_t *)0x10006104 = 0; // SDBLKLEN32
+ *(volatile uint16_t *)0x10006104 = 0; // SDBLKLEN32
#endif
- *(volatile uint16_t *)0x10006108 = 1; // SDBLKCOUNT32
- *(volatile uint16_t *)0x100060E0 &= 0xFFFEu; // SDRESET
- *(volatile uint16_t *)0x100060E0 |= 1u; // SDRESET
- *(volatile uint16_t *)0x10006020 |= TMIO_MASK_ALL; // SDIR_MASK0
+ *(volatile uint16_t *)0x10006108 = 1; // SDBLKCOUNT32
+ *(volatile uint16_t *)0x100060E0 &= 0xFFFEu; // SDRESET
+ *(volatile uint16_t *)0x100060E0 |= 1u; // SDRESET
+ *(volatile uint16_t *)0x10006020 |= TMIO_MASK_ALL; // SDIR_MASK0
*(volatile uint16_t *)0x10006022 |= TMIO_MASK_ALL >> 16; // SDIR_MASK1
- *(volatile uint16_t *)0x100060FC |= 0xDBu; // SDCTL_RESERVED7
- *(volatile uint16_t *)0x100060FE |= 0xDBu; // SDCTL_RESERVED8
- *(volatile uint16_t *)0x10006002 &= 0xFFFCu; // SDPORTSEL
+ *(volatile uint16_t *)0x100060FC |= 0xDBu; // SDCTL_RESERVED7
+ *(volatile uint16_t *)0x100060FE |= 0xDBu; // SDCTL_RESERVED8
+ *(volatile uint16_t *)0x10006002 &= 0xFFFCu; // SDPORTSEL
#ifdef DATA32_SUPPORT
*(volatile uint16_t *)0x10006024 = 0x20;
*(volatile uint16_t *)0x10006028 = 0x40EE;
#else
- *(volatile uint16_t *)0x10006024 = 0x40; // Nintendo sets this to 0x20
- *(volatile uint16_t *)0x10006028 = 0x40EB; // Nintendo sets this to 0x40EE
+ *(volatile uint16_t *)0x10006024 = 0x40; // Nintendo sets this to 0x20
+ *(volatile uint16_t *)0x10006028 = 0x40EB; // Nintendo sets this to 0x40EE
#endif
*(volatile uint16_t *)0x10006002 &= 0xFFFCu; ////SDPORTSEL
- *(volatile uint16_t *)0x10006026 = 512; // SDBLKLEN
- *(volatile uint16_t *)0x10006008 = 0; // SDSTOP
+ *(volatile uint16_t *)0x10006026 = 512; // SDBLKLEN
+ *(volatile uint16_t *)0x10006008 = 0; // SDSTOP
inittarget(&handelSD);
}
fprintf(BOTTOM_SCREEN, "]\n TWL_FIRM failed to load.\n");
state = 1;
} else {
- fprintf(stderr, "]\n");
find_proc9(twl_firm_loc, &twl_firm_proc9, &twl_firm_p9_exefs);
+ fprintf(stderr, "]\n");
}
fprintf(BOTTOM_SCREEN, "AGB_FIRM\n [");
fprintf(BOTTOM_SCREEN, "]\n AGB_FIRM failed to load.\n");
state = 1;
} else {
- fprintf(stderr, "]\n");
find_proc9(agb_firm_loc, &agb_firm_proc9, &agb_firm_p9_exefs);
+ fprintf(stderr, "]\n");
}
firm_loaded = 1; // Loaded.
#define OP_OR 0x0A
#define OP_XOR 0x0B
#define OP_NOT 0x0C
+#define OP_VER 0x0D
#define OP_NEXT 0xFF
int init_bytecode = 0;
int
-exec_bytecode(uint8_t *bytecode, uint32_t len, int debug)
+exec_bytecode(uint8_t *bytecode, uint16_t ver, uint32_t len, int debug)
{
if (!init_bytecode) {
#ifndef LOADER
}
code += 2;
break;
+ case OP_VER:
+ if (debug)
+ log("ver\n");
+ code++;
+ if (!test_was_false) {
+ if (*(uint16_t *)code != ver) {
+ test_was_false = 1;
+ }
+ } else {
+ test_was_false = 0;
+ }
+ code += 2;
+ break;
case OP_NEXT:
if (debug)
log("next\n");
#ifdef LOADER
int
-execb(uint64_t tid, uint8_t *search_mem, uint32_t search_len)
+execb(uint64_t tid, uint16_t ver, uint8_t *search_mem, uint32_t search_len)
{
#else
int
execb(char *filename, int build_cache)
{
+ uint16_t ver = 0; // FIXME - Provide native_firm version
#endif
uint32_t patch_len;
#ifdef LOADER
patch_mem = (uint8_t *)FCRAM_PATCH_LOC;
patch_len = len;
}
-
#endif
int debug = 0;
}
#endif
- return exec_bytecode(patch_mem, patch_len, debug);
+ return exec_bytecode(patch_mem, ver, patch_len, debug);
}
#define PATH_PATCHES PATH_CFW "/patch" // Patch binary folder.
#define PATH_FIRMWARES PATH_CFW "/firmware" // Firmware folder.
#define PATH_MODULES PATH_CFW "/module" // Sysmodule location
-#define PATH_SERVICES PATH_CFW "/service" // Service code location.
+#define PATH_SERVICES PATH_CFW "/svc" // Svc code location.
#define PATH_TEMP PATH_CFW "/cache" // Files that are transient and used to speed operation
#define PATH_LOADER_CACHE PATH_TEMP "/loader" // Cached patch bytecode for loader.
#define PATH_KEYS PATH_CFW "/keys" // Keyfiles will be loaded from this dir, and
// additionally the root if not found.
-#define PATH_EXEFS PATH_CFW "/exe" // ExeFS overrides, named like '<titleid>.exefs'
+#define PATH_EXEFS PATH_CFW "/exe" // ExeFS overrides, named like '<titleid>.exefs' - NYI
#define PATH_NATIVE_F PATH_FIRMWARES "/native"
#define PATH_AGB_F PATH_FIRMWARES "/agb"