]> Chaos Git - corbenik/corbenik.git/commitdiff
Multiple things (again) v0.0.4
authorchaoskagami <chaos.kagami@gmail.com>
Mon, 6 Jun 2016 08:00:02 +0000 (04:00 -0400)
committerchaoskagami <chaos.kagami@gmail.com>
Mon, 6 Jun 2016 09:42:56 +0000 (05:42 -0400)
 * EmuNAND support (only one right now, but all I need is a menu/option for more)
   * This is both normal layout (RedNAND) and gateway layout (header at back)
 * Loader now has three different rel options for text, data, and ro
 * Screeninit.

31 files changed:
external/Makefile
external/loader/source/interp.h
external/loader/source/loader.c
external/loader/source/patcher.c
external/loader/source/patcher.h
external/screeninit/Makefile [new file with mode: 0755]
external/screeninit/linker.ld [new file with mode: 0755]
external/screeninit/source/main.c [new file with mode: 0755]
external/screeninit/source/start.s [new file with mode: 0644]
external/screeninit/source/types.h [new file with mode: 0755]
external/svc/Makefile
external/svc/emunand.s [new file with mode: 0644]
external/svc/patches.s [new file with mode: 0644]
host/bytecode_asm.py
source/config.h
source/fatfs/ff.c
source/fatfs/ff.h
source/fatfs/sdmmc.c
source/interp.c
source/main.c
source/menu.c
source/patch/emunand.c [new file with mode: 0644]
source/patch/emunand.h [new file with mode: 0644]
source/patch_format.h
source/patcher.c
source/screeninit.c [new file with mode: 0644]
source/screeninit.h [new file with mode: 0644]
source/std/draw.c
source/std/fs.c
source/std/fs.h
source/std/types.h

index 68c70ee0c3feb6e1f4bc0f8fe40599d3c616dcb6..f30799acde727aa1f2c54110b38ba3841b2270a3 100644 (file)
@@ -1,12 +1,15 @@
 .PHONY: all
-all: loader svc
+all: loader svc screeninit
        mkdir -p ../out/corbenik/module
        mkdir -p ../out/corbenik/svc
+       mkdir -p ../out/corbenik/bits
        cp loader/loader.cxi ../out/corbenik/module/loader.cxi
        cp svc/7b.bin ../out/corbenik/svc/7b.bin
+       cp svc/emunand.bin ../out/corbenik/bits/emunand.bin
+       cp screeninit/build/screeninit.bin ../out/corbenik/bits/screeninit.bin
 
 .PHONY: clean
-clean: clean_loader clean_svc
+clean: clean_loader clean_svc clean_screeninit
        rm -rf ../out/corbenik/svc
        rm -rf ../out/corbenik/module
 
@@ -14,14 +17,22 @@ clean: clean_loader clean_svc
 loader:
        make -C loader
 
-.PHONY: clean_loader
-clean_loader:
-       make -C loader clean
-
 .PHONY: svc
 svc:
        make -C svc
 
+.PHONY: screeninit
+screeninit:
+       make -C screeninit
+
+.PHONY: clean_loader
+clean_loader:
+       make -C loader clean
+
 .PHONY: clean_svc
 clean_svc:
        make -C svc clean
+
+.PHONY: clean_screeninit
+screeninit_clean:
+       make -C screeninit clean
index 091b4c14e5604eea09cf23ab62f0088c3007f6f3..4399324710076c6c154c001f307d982497f4d2f9 100644 (file)
@@ -1,6 +1,9 @@
 #ifndef __INTERP_H
 #define __INTERP_H
 
-int execb(uint64_t tid, uint16_t ver, uint8_t *search_mem, uint32_t search_len);
+int execb(uint64_t tid, uint16_t ver,
+    uint8_t *text_mem, uint32_t text_len,
+    uint8_t *data_mem, uint32_t data_size,
+    uint8_t *ro_mem, uint32_t ro_size);
 
 #endif
index 1b76653a68a43433f6f1916609fb65bf156f9b89..960764f5e5f65fd0cf57041e62ee43cb994e053a 100644 (file)
@@ -95,9 +95,9 @@ load_code(u64 progid, u16 progver, prog_addrs_t *shared, prog_addrs_t *original,
     }
 
     // Patch segments
-    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);
+    patch_exe (progid, progver, (u8 *)shared->text_addr, shared->text_size << 12, original->text_size << 12,
+                                (u8 *)shared->data_addr, shared->data_size << 12, original->data_size << 12,
+                                (u8 *)shared->ro_addr, shared->ro_size << 12, original->ro_size << 12);
 
     return 0;
 }
index 598a072788b5c40d7d9699df9052d3ee05246bcf..4551a4a2152a700017dd12eaad2c322250b9aff6 100644 (file)
@@ -307,28 +307,19 @@ overlay_patch(u64 progId, u8 *code, u32 size)
     // TODO - Implement. Needs some thought. This should allow usage of files off SD rather than RomFS.
 }
 
-// This is only for the .data segment.
-void
-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, u16 progver, u8 *ro, u32 size, u32 orig_size)
-{
-}
-
 // This is only for the .code segment.
 void
-patch_text(u64 progId, u16 progver, u8 *text, u32 size, u32 orig_size)
+patch_exe(u64 progId, u16 progver,
+    u8 *text, u32 text_size, u32 orig_text,
+    u8* data, u32 data_size, u32 orig_data,
+    u8* ro, u32 ro_size, u32 orig_ro)
 {
     if (progId == 0x0004013000008002LL)
-        adjust_cpu_settings(progId, text, orig_size);
+        adjust_cpu_settings(progId, text, orig_text);
 
-    execb(progId, progver, text, orig_size);
+    execb(progId, progver, text, orig_text, data, orig_data, ro, orig_ro);
 
-    language_emu(progId, text, orig_size);
+    language_emu(progId, text, orig_text);
 }
 
 // Gets how many bytes .text must be extended by for patches to fit.
index 44a6223ba22400283be2a8f047da89ccd66d1145..460b3d90e54b85ac195c72f4397a83b054c1fd70 100644 (file)
@@ -3,9 +3,10 @@
 
 #include <3ds/types.h>
 
-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);
+void patch_exe(u64 progId, u16 progver,
+    u8 *text, u32 text_size, u32 orig_text,
+    u8* data, u32 data_size, u32 orig_data,
+    u8* ro, u32 ro_size, u32 orig_ro);
 
 u32 get_text_extend(u64 progId, u16 progver, u32 size_orig);
 u32 get_ro_extend(u64 progId, u16 progver, u32 size_orig);
diff --git a/external/screeninit/Makefile b/external/screeninit/Makefile
new file mode 100755 (executable)
index 0000000..745782b
--- /dev/null
@@ -0,0 +1,47 @@
+rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2))
+
+ifeq ($(strip $(DEVKITARM)),)
+$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
+endif
+
+include $(DEVKITARM)/3ds_rules
+
+CC := arm-none-eabi-gcc
+AS := arm-none-eabi-as
+LD := arm-none-eabi-ld
+OC := arm-none-eabi-objcopy
+
+name := $(shell basename $(CURDIR))
+
+dir_source := source
+dir_build := build
+
+ASFLAGS := -mcpu=mpcore -mfloat-abi=hard
+CFLAGS  := -Wall -Wextra -MMD -MP -mthumb -mthumb-interwork $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math
+LDFLAGS := -nostdlib
+
+objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
+          $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
+          $(call rwildcard, $(dir_source), *.s *.c)))
+
+.PHONY: all
+all: $(dir_build)/$(name).bin
+
+.PHONY: clean
+clean:
+       @rm -rf $(dir_build)
+
+$(dir_build)/$(name).bin: $(dir_build)/$(name).elf
+       $(OC) -S -O binary $< $@
+
+$(dir_build)/$(name).elf: $(objects)
+       $(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^
+
+$(dir_build)/%.o: $(dir_source)/%.c
+       @mkdir -p "$(@D)"
+       $(COMPILE.c) $(OUTPUT_OPTION) $<
+
+$(dir_build)/%.o: $(dir_source)/%.s
+       @mkdir -p "$(@D)"
+       $(COMPILE.s) $(OUTPUT_OPTION) $<
+include $(call rwildcard, $(dir_build), *.d)
diff --git a/external/screeninit/linker.ld b/external/screeninit/linker.ld
new file mode 100755 (executable)
index 0000000..9ae0eaa
--- /dev/null
@@ -0,0 +1,12 @@
+ENTRY(_start)
+SECTIONS
+{
+    . = 0x24FFFC00;
+    .text.start : { *(.text.start) }
+    .text : { *(.text) }
+    .data : { *(.data) }
+    .bss : { *(.bss COMMON) }
+    .rodata : { *(.rodata) }
+    . = ALIGN(4);
+}
+
diff --git a/external/screeninit/source/main.c b/external/screeninit/source/main.c
new file mode 100755 (executable)
index 0000000..318911a
--- /dev/null
@@ -0,0 +1,106 @@
+#include "types.h"
+
+void main(void)
+{
+   // FIXME - We could use some serious macros here...
+
+   u32 brightnessLevel = *(vu32 *)0x24FFFC08;
+   vu32 *const arm11 = (u32 *)0x1FFFFFF8;
+
+   *(vu32 *)0x10141200 = 0x1007F;
+   *(vu32 *)0x10202014 = 0x00000001;
+   *(vu32 *)0x1020200C &= 0xFFFEFFFE;
+   *(vu32 *)0x10202240 = brightnessLevel; // Alteration; directly read brightness.
+   *(vu32 *)0x10202A40 = brightnessLevel;
+   *(vu32 *)0x10202244 = 0x1023E;
+   *(vu32 *)0x10202A44 = 0x1023E;
+
+   // Top screen
+   *(vu32 *)0x10400400 = 0x000001c2;
+   *(vu32 *)0x10400404 = 0x000000d1;
+   *(vu32 *)0x10400408 = 0x000001c1;
+   *(vu32 *)0x1040040c = 0x000001c1;
+   *(vu32 *)0x10400410 = 0x00000000;
+   *(vu32 *)0x10400414 = 0x000000cf;
+   *(vu32 *)0x10400418 = 0x000000d1;
+   *(vu32 *)0x1040041c = 0x01c501c1;
+   *(vu32 *)0x10400420 = 0x00010000;
+   *(vu32 *)0x10400424 = 0x0000019d;
+   *(vu32 *)0x10400428 = 0x00000002;
+   *(vu32 *)0x1040042c = 0x00000192;
+   *(vu32 *)0x10400430 = 0x00000192;
+   *(vu32 *)0x10400434 = 0x00000192;
+   *(vu32 *)0x10400438 = 0x00000001;
+   *(vu32 *)0x1040043c = 0x00000002;
+   *(vu32 *)0x10400440 = 0x01960192;
+   *(vu32 *)0x10400444 = 0x00000000;
+   *(vu32 *)0x10400448 = 0x00000000;
+   *(vu32 *)0x1040045C = 0x00f00190;
+   *(vu32 *)0x10400460 = 0x01c100d1;
+   *(vu32 *)0x10400464 = 0x01920002;
+   *(vu32 *)0x10400468 = 0x18300000;
+   *(vu32 *)0x10400470 = 0x80341;
+   *(vu32 *)0x10400474 = 0x00010501;
+   *(vu32 *)0x10400478 = 0;
+   *(vu32 *)0x10400490 = 0x000002D0;
+   *(vu32 *)0x1040049C = 0x00000000;
+
+   // Disco register
+   for(u32 i = 0; i < 256; i++)
+       *(vu32 *)0x10400484 = 0x10101 * i;
+
+   // Bottom screen
+   *(vu32 *)0x10400500 = 0x000001c2;
+   *(vu32 *)0x10400504 = 0x000000d1;
+   *(vu32 *)0x10400508 = 0x000001c1;
+   *(vu32 *)0x1040050c = 0x000001c1;
+   *(vu32 *)0x10400510 = 0x000000cd;
+   *(vu32 *)0x10400514 = 0x000000cf;
+   *(vu32 *)0x10400518 = 0x000000d1;
+   *(vu32 *)0x1040051c = 0x01c501c1;
+   *(vu32 *)0x10400520 = 0x00010000;
+   *(vu32 *)0x10400524 = 0x0000019d;
+   *(vu32 *)0x10400528 = 0x00000052;
+   *(vu32 *)0x1040052c = 0x00000192;
+   *(vu32 *)0x10400530 = 0x00000192;
+   *(vu32 *)0x10400534 = 0x0000004f;
+   *(vu32 *)0x10400538 = 0x00000050;
+   *(vu32 *)0x1040053c = 0x00000052;
+   *(vu32 *)0x10400540 = 0x01980194;
+   *(vu32 *)0x10400544 = 0x00000000;
+   *(vu32 *)0x10400548 = 0x00000011;
+   *(vu32 *)0x1040055C = 0x00f00140;
+   *(vu32 *)0x10400560 = 0x01c100d1;
+   *(vu32 *)0x10400564 = 0x01920052;
+   *(vu32 *)0x10400568 = 0x18300000 + 0x46500;
+   *(vu32 *)0x10400570 = 0x80301;
+   *(vu32 *)0x10400574 = 0x00010501;
+   *(vu32 *)0x10400578 = 0;
+   *(vu32 *)0x10400590 = 0x000002D0;
+   *(vu32 *)0x1040059C = 0x00000000;
+
+   // Disco register
+   for(u32 i = 0; i < 256; i++)
+       *(vu32 *)0x10400584 = 0x10101 * i;
+
+   *(vu32 *)0x10400468 = 0x18300000;
+   *(vu32 *)0x1040046c = 0x18300000;
+   *(vu32 *)0x10400494 = 0x18300000;
+   *(vu32 *)0x10400498 = 0x18300000;
+   *(vu32 *)0x10400568 = 0x18346500;
+   *(vu32 *)0x1040056c = 0x18346500;
+
+   //Set CakeBrah framebuffers
+   *((vu32 *)0x23FFFE00) = 0x18300000;
+   *((vu32 *)0x23FFFE04) = 0x18300000;
+   *((vu32 *)0x23FFFE08) = 0x18346500;
+
+   //Clear ARM11 entry offset
+   *arm11 = 0;
+
+   //Wait for the entry to be set
+   while(!*arm11);
+
+   //Jump to it
+   ((void (*)())*arm11)();
+}
diff --git a/external/screeninit/source/start.s b/external/screeninit/source/start.s
new file mode 100644 (file)
index 0000000..40392d1
--- /dev/null
@@ -0,0 +1,10 @@
+.section .text.start
+.align 4
+.global _start
+_start:
+    @ Disable interrupts
+    CPSID aif
+
+    b main
+
+    .word 0
diff --git a/external/screeninit/source/types.h b/external/screeninit/source/types.h
new file mode 100755 (executable)
index 0000000..d27412b
--- /dev/null
@@ -0,0 +1,13 @@
+#pragma once
+
+#include <stdint.h>
+
+//Common data types
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+typedef volatile u8 vu8;
+typedef volatile u16 vu16;
+typedef volatile u32 vu32;
+typedef volatile u64 vu64;
\ No newline at end of file
index 3e2acda3198eb33910bb380b81c2c516ed7f8d0c..243b4c84af1cd4252bd792cd4c31aadbadd65469 100644 (file)
@@ -1,6 +1,6 @@
 PATH := $(PATH):$(DEVKITARM)/bin
 
-all: 7b.bin stub.bin
+all: 7b.bin stub.bin emunand.bin
 
 %.o: %.s
        arm-none-eabi-as -o $@ $<
diff --git a/external/svc/emunand.s b/external/svc/emunand.s
new file mode 100644 (file)
index 0000000..0655d25
--- /dev/null
@@ -0,0 +1,45 @@
+.section .text
+.global _start
+_start:
+    // Original code that still needs to be executed.
+    mov r4, r0
+    mov r5, r1
+    mov r7, r2
+    mov r6, r3
+
+main:
+    // If we're already trying to access the SD, return.
+    ldr r2, [r0, #4]
+    ldr r1, sdmmc // In armips this instruction uses pc-releative loading
+    cmp r2, r1
+    beq nand_sd_ret
+
+    str r1, [r0, #4]  // Set object to be SD
+    ldr r2, [r0, #8]  // Get sector to read
+       cmp r2, #0        // Gateway compat
+
+    ldr r3, nand_offset // ^ see above
+    add r2, r3  // Add the offset to the NAND in the SD.
+
+    ldreq r3, ncsd_offset // ^ see above
+    addeq r2, r3
+
+    str r2, [r0, #8]  // Store sector to read
+
+    nand_sd_ret:
+        // Restore registers.
+        mov r0, r4
+        mov r1, r5
+        mov r2, r7
+        mov r3, r6
+
+        // Return 4 bytes behind where we got called,
+        // due to the offset of this function being stored there.
+        mov r0, lr
+        add r0, #4
+        bx  r0
+
+sdmmc:              .ascii "SDMC" // The offset of the sdmmc object.
+nand_offset:        .ascii "NAND" // The starting offset of the emuNAND on the SD.
+ncsd_offset:        .ascii "NCSD" // Location of the NCSD header relative to nand_offset
+
diff --git a/external/svc/patches.s b/external/svc/patches.s
new file mode 100644 (file)
index 0000000..44eaf6f
--- /dev/null
@@ -0,0 +1,77 @@
+.arm.little
+
+.create "patch1.bin", 0
+.arm
+nand_sd:
+    ; Original code that still needs to be executed.
+    mov r4, r0
+    mov r5, r1
+    mov r7, r2
+    mov r6, r3
+    ; End.
+
+    ; If we're already trying to access the SD, return.
+    ldr r2, [r0, #4]
+    ldr r1, [sdmmc]
+    cmp r2, r1
+    beq nand_sd_ret
+
+    str r1, [r0, #4]  ; Set object to be SD
+    ldr r2, [r0, #8]  ; Get sector to read
+    cmp r2, #0  ; For GW compatibility, see if we're trying to read the ncsd header (sector 0)
+
+    ldr r3, [nand_offset]
+    add r2, r3  ; Add the offset to the NAND in the SD.
+
+    ldreq r3, [ncsd_header_offset]
+    addeq r2, r3  ; If we're reading the ncsd header, add the offset of that sector.
+
+    str r2, [r0, #8]  ; Store sector to read
+
+    nand_sd_ret:
+        ; Restore registers.
+        mov r1, r5
+        mov r2, r7
+        mov r3, r6
+
+        ; Return 4 bytes behind where we got called,
+        ;   due to the offset of this function being stored there.
+        mov r0, lr
+        add r0, #4
+        bx r0
+.pool
+nand_offset: .ascii "NAND"  ; The starting offset of the emuNAND on the SD.
+ncsd_header_offset: .ascii "NCSD"  ; The offset of the first emuNAND sector relative to the start of the emuNAND (Used for when the first sector is placed at the end).
+sdmmc: .ascii "sdmmc"  ; The offset of the sdmmc object.
+.close
+
+.create "patch2.bin", 0
+.arm
+       .word 0x360003
+       .word 0x10100000
+       .word 0x1000001
+       .word 0x360003
+       .word 0x20000000
+       .word 0x1010101
+       .word 0x200603
+       .word 0x8000000
+       .word 0x1010101
+       .word 0x1C0603
+       .word 0x8020000
+.close
+
+.create "patch3.bin", 0
+.thumb
+       ldr r4, [_nand_sd_write]
+       blx r4
+.align 4
+_nand_sd_write: .ascii "mem"
+.close
+
+.create "patch4.bin", 0
+.thumb
+       ldr r4, [_nand_sd_read]
+       blx r4
+.align 4
+_nand_sd_read: .ascii "mem"
+.close
index a963501c3315081466a08b0de7e03b73694d3404..a97c5412ab305877617cf6fa7250807bbc947e80 100755 (executable)
@@ -48,6 +48,10 @@ def rel_name(x):
                'twl_s1'   : "0F",
                'twl_s2'   : "10",
                'twl_s3'   : "11",
+
+               'exe_text' : "12",
+               'exe_data' : "13",
+               'exe_ro'   : "14",
        }.get(x, "-1")
 
 name = "NO NAME"
index e612267ddc12877650746d947cfbf3958adc1692..7095b4a57ea997080e47869a7b481cf2bde8e901 100644 (file)
@@ -96,6 +96,9 @@ struct options_s
 // Allow enabling patches which are marked as 'incompatible'. Chances are there's a reason.
 #define IGNORE_BROKEN_SHIT 15
 
+// Whether to use an EmuNAND
+#define OPTION_EMUNAND 16
+
 // Save log files during boot and from loader.
 // This will slow things down a bit.
 #define OPTION_SAVE_LOGS 253
index df502b9603d5e61cc648eb35d92a9b9822d58489..ad5cb7e6de67a5eb2c360d029fd194a2c98b0642 100644 (file)
@@ -2729,6 +2729,56 @@ f_open(FIL *fp,           /* Pointer to the blank file object */
     LEAVE_FF(dj.fs, res);
 }
 
+/*-----------------------------------------------------------------------*/
+/* Read File                                                             */
+/*-----------------------------------------------------------------------*/
+
+
+FRESULT
+f_getsector(FIL *fp,    /* Pointer to the file object */
+       UINT *sec    /* Pointer to uint which will contain the sector */
+       )
+{
+    FRESULT res;
+    DWORD clst = 0, sect = 0;
+    BYTE csect;
+
+    res = validate(fp); /* Check validity */
+
+    if (res != FR_OK)
+        LEAVE_FF(fp->fs, res);
+    if (fp->err) /* Check error */
+        LEAVE_FF(fp->fs, (FRESULT)fp->err);
+    if (!(fp->flag & FA_READ)) /* Check access mode */
+        LEAVE_FF(fp->fs, FR_DENIED);
+
+    if ((fp->fptr % SS(fp->fs)) == 0) {                              /* On the sector boundary? */
+       csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */
+       if (!csect) {                                                /* On the cluster boundary? */
+           if (fp->fptr == 0) {                                     /* On the top of the file? */
+               clst = fp->sclust;                                   /* Follow from the origin */
+           } else {                                                 /* Middle or end of the file */
+               clst = get_fat(fp->fs, fp->clust); /* Follow cluster chain on the FAT */
+           }
+
+           if (clst < 2)
+               ABORT(fp->fs, FR_INT_ERR);
+           if (clst == 0xFFFFFFFF)
+               ABORT(fp->fs, FR_DISK_ERR);
+       }
+
+           sect = clust2sect(fp->fs, clst); /* Get current sector */
+       if (!sect)
+               ABORT(fp->fs, FR_INT_ERR);
+       sect += csect;
+       }
+
+       *sec = sect;
+
+       return 0;
+}
+
+
 /*-----------------------------------------------------------------------*/
 /* Read File                                                             */
 /*-----------------------------------------------------------------------*/
index 40c9ffca4df5751e55a9bdc03dfa2af6e7d33d30..0bbe5bba9274b1245217c68d7472cb46d1c33e12 100644 (file)
@@ -225,6 +225,7 @@ FRESULT f_setlabel(const TCHAR *label);
 FRESULT f_mount(FATFS *fs, const TCHAR *path, BYTE opt);                             /* Mount/Unmount a logical drive */
 FRESULT f_mkfs(const TCHAR *path, BYTE sfd, UINT au);                                /* Create a file system on the volume */
 FRESULT f_fdisk(BYTE pdrv, const DWORD szt[], void *work);                           /* Divide a physical drive into some partitions */
+FRESULT f_getsector(FIL *fp, UINT *sec);
 int f_putc(TCHAR c, FIL *fp);                                                        /* Put a character to the file */
 int f_puts(const TCHAR *str, FIL *cp);                                               /* Put a string to the file */
 int f_printf(FIL *fp, const TCHAR *str, ...);                                        /* Put a formatted string to the file */
index f2fd67eae83582a8c8c265c895978aa32049c78a..34c4a6049a22517fbde2a287c07539736b31b484 100644 (file)
  * along with this program. If not, see http://www.gnu.org/licenses/.
  */
 
+// LEGAL - Note that despite the above notice, it must be used under
+// MPL 2.0 here. GPLv2 and GPLv3 are not compatible, and his software
+// delcares specifically GPLv2. We have to treat it as MPL 2.0 to
+// not violate any licensing.
+
 #include <stdint.h>
-#include <string.h>
-#include <stdlib.h>
+#include <stddef.h>
 #include <inttypes.h>
-#include <malloc.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <errno.h>
 
 #include "sdmmc.h"
 //#include "DrawCharacter.h"
index ad1fb77198a526a4693252d5033ab75f28891970..141af48aa09d4faf8f74aa03817cb0879558943a 100644 (file)
@@ -42,8 +42,7 @@ struct mode
     uint8_t *memory;
     uint32_t size;
 };
-
-struct mode modes[19];
+struct mode modes[21];
 int init_bytecode = 0;
 
 int
@@ -71,48 +70,45 @@ exec_bytecode(uint8_t *bytecode, uint16_t ver, uint32_t len, int debug)
         modes[5].size = firm_p9_exefs->fileHeaders[0].size;
 
         // NATIVE_FIRM Sect 0
-        modes[6].memory = (uint8_t *)&firm_loc->section[0] + firm_loc->section[0].offset;
+        modes[6].memory = (uint8_t *)firm_loc + firm_loc->section[0].offset;
         modes[6].size = firm_loc->section[0].size;
         // NATIVE_FIRM Sect 1
-        modes[7].memory = (uint8_t *)&firm_loc->section[1] + firm_loc->section[1].offset;
+        modes[7].memory = (uint8_t *)firm_loc + firm_loc->section[1].offset;
         modes[7].size = firm_loc->section[1].size;
         // NATIVE_FIRM Sect 2
-        modes[8].memory = (uint8_t *)&firm_loc->section[2] + firm_loc->section[2].offset;
+        modes[8].memory = (uint8_t *)firm_loc + firm_loc->section[2].offset;
         modes[8].size = firm_loc->section[2].size;
         // NATIVE_FIRM Sect 3
-        modes[9].memory = (uint8_t *)&firm_loc->section[3] + firm_loc->section[3].offset;
+        modes[9].memory = (uint8_t *)firm_loc + firm_loc->section[3].offset;
         modes[9].size = firm_loc->section[3].size;
 
         // AGB_FIRM Sect 0
-        modes[10].memory = (uint8_t *)&agb_firm_loc->section[0] + agb_firm_loc->section[0].offset;
+        modes[10].memory = (uint8_t *)agb_firm_loc + agb_firm_loc->section[0].offset;
         modes[10].size = agb_firm_loc->section[0].size;
         // AGB_FIRM Sect 1
-        modes[11].memory = (uint8_t *)&agb_firm_loc->section[1] + agb_firm_loc->section[1].offset;
+        modes[11].memory = (uint8_t *)agb_firm_loc + agb_firm_loc->section[1].offset;
         modes[11].size = agb_firm_loc->section[1].size;
         // AGB_FIRM Sect 2
-        modes[12].memory = (uint8_t *)&agb_firm_loc->section[2] + agb_firm_loc->section[2].offset;
+        modes[12].memory = (uint8_t *)agb_firm_loc + agb_firm_loc->section[2].offset;
         modes[12].size = agb_firm_loc->section[2].size;
         // AGB_FIRM Sect 3
-        modes[13].memory = (uint8_t *)&agb_firm_loc->section[3] + agb_firm_loc->section[3].offset;
+        modes[13].memory = (uint8_t *)agb_firm_loc + agb_firm_loc->section[3].offset;
         modes[13].size = agb_firm_loc->section[3].size;
 
         // TWL_FIRM Sect 0
-        modes[14].memory = (uint8_t *)&twl_firm_loc->section[0] + twl_firm_loc->section[0].offset;
+        modes[14].memory = (uint8_t *)twl_firm_loc + twl_firm_loc->section[0].offset;
         modes[14].size = twl_firm_loc->section[0].size;
         // TWL_FIRM Sect 1
-        modes[15].memory = (uint8_t *)&twl_firm_loc->section[1] + twl_firm_loc->section[1].offset;
+        modes[15].memory = (uint8_t *)twl_firm_loc + twl_firm_loc->section[1].offset;
         modes[15].size = twl_firm_loc->section[1].size;
         // TWL_FIRM Sect 2
-        modes[16].memory = (uint8_t *)&twl_firm_loc->section[2] + twl_firm_loc->section[2].offset;
+        modes[16].memory = (uint8_t *)twl_firm_loc + twl_firm_loc->section[2].offset;
         modes[16].size = twl_firm_loc->section[2].size;
         // TWL_FIRM Sect 3
-        modes[17].memory = (uint8_t *)&twl_firm_loc->section[3] + twl_firm_loc->section[3].offset;
+        modes[17].memory = (uint8_t *)twl_firm_loc + twl_firm_loc->section[3].offset;
         modes[17].size = twl_firm_loc->section[3].size;
 #endif
 
-        // Loader (not valid in bootmode)
-        // modes[18] = { 0, 0 };
-
         init_bytecode = 1;
     }
 
@@ -139,10 +135,6 @@ exec_bytecode(uint8_t *bytecode, uint16_t ver, uint32_t len, int debug)
                 test_was_false = 0;
                 break;
             case OP_REL: // Change relativity.
-#ifdef LOADER
-                // Loader doesn't support this. Just treat it like a two-byte NOP.
-                code += 2;
-#else
                 if (debug)
                     log("rel\n");
                 code++;
@@ -152,7 +144,6 @@ exec_bytecode(uint8_t *bytecode, uint16_t ver, uint32_t len, int debug)
                     test_was_false = 0;
                 set_mode = *code;
                 code++;
-#endif
                 break;
             case OP_FIND: // Find pattern.
                 if (debug)
@@ -319,6 +310,9 @@ exec_bytecode(uint8_t *bytecode, uint16_t ver, uint32_t len, int debug)
 #ifndef LOADER
                 set_mode = 3;
                 current_mode = &modes[set_mode];
+#else
+                set_mode = 18;
+                current_mode = &modes[set_mode];
 #endif
                 offset = 0;
                 test_was_false = 0;
@@ -351,7 +345,10 @@ exec_bytecode(uint8_t *bytecode, uint16_t ver, uint32_t len, int debug)
 
 #ifdef LOADER
 int
-execb(uint64_t tid, uint16_t ver, uint8_t *search_mem, uint32_t search_len)
+execb(uint64_t tid, uint16_t ver,
+      uint8_t *text_mem, uint32_t text_len,
+      uint8_t* data_mem, uint32_t data_len,
+      uint8_t* ro_mem, uint32_t ro_len)
 {
 #else
 int
@@ -413,8 +410,16 @@ execb(char *filename, int build_cache)
     FSFILE_Close(file); // Done reading in.
 
     // Set memory.
-    modes[18].memory = search_mem;
-    modes[18].size = search_len;
+    modes[18].memory = text_mem;
+    modes[18].size   = text_len;
+
+    // Set memory.
+    modes[19].memory = data_mem;
+    modes[19].size   = data_len;
+
+    // Set memory.
+    modes[20].memory = ro_mem;
+    modes[20].size   = ro_len;
 
     log("  exec\n");
 
index eaecc1dfc6e91c9b25cfe7ce5eaf043958235626..6c6a0f0ba121968f884d886686bbb73720ce6148 100644 (file)
@@ -2,6 +2,8 @@
 #include "firm/firm.h"
 #include "input.h"
 #include "config.h"
+#include "screeninit.h"
+#include "std/abort.h"
 
 int menu_handler();
 
@@ -11,9 +13,12 @@ void shut_up();
 int
 main()
 {
-    if (fmount()) {
+       int c = fmount();
+       screen_init();
+
+    if (c) {
         // Failed to mount SD. Bomb out.
-        fprintf(BOTTOM_SCREEN, "%pFailed to mount SD card.\n", COLOR(RED, BLACK));
+        abort("Failed to mount SD card.\n");
     }
 
     load_config(); // Load configuration.
index e02f36dd6224ef858e9d500f0b207359e98b390f..f9d05be5a52046a79591db26807c73233318763f 100644 (file)
@@ -32,6 +32,10 @@ static struct options_s options[] = {
 
     { 0, "", "", not_option, 0, 0 },
 
+    { OPTION_EMUNAND, "EmuNAND", "Redirects NAND write/read to EmuNAND #0. Right now, only one is supported (but the work is done)", boolean_val, 0, 0 },
+
+    { 0, "", "", not_option, 0, 0 },
+
     { OPTION_AUTOBOOT, "Autoboot", "Boot the system automatically, unless the R key is held.", boolean_val, 0, 0 },
     { OPTION_SILENCE, "  Silent mode", "Suppress all debug output during autoboot. You'll see the screen turn on, then off.", boolean_val, 0, 0 },
 
diff --git a/source/patch/emunand.c b/source/patch/emunand.c
new file mode 100644 (file)
index 0000000..dfeab0a
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+*   emunand.c
+*/
+
+#include "emunand.h"
+#include "../std/memory.h"
+#include "../std/draw.h"
+#include "../std/fs.h"
+#include "../std/abort.h"
+#include "../firm/firm.h"
+#include "../firm/fcram.h"
+#include "../fatfs/sdmmc.h"
+#include "../firm/headers.h"
+#include "../patch_format.h"
+
+uint8_t *temp = (uint8_t*)FCRAM_JUNK_LOC;
+
+void verify_loop_emunand(char* filename) {
+       // FIXME - This won't work unless the NAND file is completely contiguous on disk, sadly.
+       // Technically speaking if I were to defrag my SD this would work, I suspect.
+
+       uint32_t offset = get_file_sector(filename); // Get the sector of the file
+
+    // Check for RedNAND image on SD
+    if(!sdmmc_sdcard_readsectors(offset, 1, temp) && *(uint32_t *)(temp + 0x100) == NCSD_MAGIC) {
+               fprintf(stderr, "emunand: found NCSD magic\n");
+    } else {
+               abort("emunand: selected NAND image is not valid.\n");
+       }
+}
+
+void verify_emunand(uint32_t index, uint32_t* off, uint32_t* head) {
+       uint32_t nandSize = getMMCDevice(0)->total_size;
+
+       uint32_t offset;
+       if (nandSize > 0x200000)
+               offset = 0x400000 * index;
+       else
+               offset = 0x200000 * index;
+
+    // Check for RedNAND/Normal physical layout on SD
+    if(!sdmmc_sdcard_readsectors(offset + 1, 1, temp) && *(uint32_t *)(temp + 0x100) == NCSD_MAGIC) {
+               *off  = offset + 1;
+               *head = offset + 1;
+
+               fprintf(stderr, "emunand: found NCSD magic for #%u\n", index);
+               fprintf(stderr, "emunand: layout is normal\n");
+    }
+    // Check for GW EmuNAND on SD
+    else if(!sdmmc_sdcard_readsectors(offset + nandSize, 1, temp) && *(uint32_t *)(temp + 0x100) == NCSD_MAGIC) {
+               *off  = offset;
+               *head = offset + nandSize;
+
+               fprintf(stderr, "emunand: found NCSD magic for %u\n", index);
+               fprintf(stderr, "emunand: layout is gateway\n");
+    } else {
+               abort("emunand: selected NAND image is not valid.\n");
+       }
+}
+
+static void *getEmuCode(uint8_t *pos, uint32_t size)
+{
+    const uint8_t pattern[] = {0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00};
+
+    //Looking for the last free space before Process9
+    void* ret = memfind(pos + 0x13500, size - 0x13500, pattern, 6) + 0x455;
+
+       if (ret) {
+               fprintf(stderr, "emunand: free space @ %x\n", ret);
+               fprintf(stderr, "emunand: size is %u bytes\n", (uint8_t*)ret - pos);
+       }
+
+       return ret;
+}
+
+static uint32_t getSDMMC(uint8_t *pos, uint32_t size)
+{
+    //Look for struct code
+    const uint8_t pattern[] = {0x21, 0x20, 0x18, 0x20};
+    const uint8_t *off = memfind(pos, size, pattern, 4);
+
+    uint32_t ret = *(uint32_t *)(off + 9) + *(uint32_t *)(off + 0xD);
+
+       fprintf(stderr, "emunand: SDMMC code @ %x\n", ret);
+
+       return ret;
+}
+
+static void patchNANDRW(uint8_t *pos, uint32_t size, uint32_t branchOffset)
+{
+    const uint16_t nandRedir[2] = {0x4C00, 0x47A0};
+
+    //Look for read/write code
+    const uint8_t pattern[] = {0x1E, 0x00, 0xC8, 0x05};
+
+    uint16_t *readOffset  = (uint16_t *)memfind(pos, size, pattern, 4) - 3;
+    uint16_t *writeOffset = (uint16_t *)memfind((uint8_t *)(readOffset + 5), 0x100, pattern, 4) - 3;
+
+    *readOffset = nandRedir[0];
+    readOffset[1] = nandRedir[1];
+    ((uint32_t *)readOffset)[1] = branchOffset;
+
+    *writeOffset = nandRedir[0];
+    writeOffset[1] = nandRedir[1];
+    ((uint32_t *)writeOffset)[1] = branchOffset;
+
+       fprintf(stderr, "emunand: write @ %x\n", writeOffset);
+       fprintf(stderr, "emunand: read @ %x\n", readOffset);
+}
+
+static void patchMPU(uint8_t *pos, uint32_t size)
+{
+    const uint32_t mpuPatch[3] = {0x00360003, 0x00200603, 0x001C0603};
+
+    //Look for MPU pattern
+    const uint8_t pattern[] = {0x03, 0x00, 0x24, 0x00};
+
+    uint32_t *off = (uint32_t *)memfind(pos, size, pattern, 4);
+
+    off[0] = mpuPatch[0];
+    off[6] = mpuPatch[1];
+    off[9] = mpuPatch[2];
+
+       fprintf(stderr, "emunand: mpu @ %x\n", off);
+}
+
+void patch_emunand(uint32_t index) {
+       //uint8_t *arm9Section, uint32_t arm9SectionSize, uint8_t *process9Offset, uint32_t process9Size, uint32_t emuOffset, uint32_t emuHeader, uint32_t branchAdditive)
+
+    // ARM9 section.
+       uint8_t* arm9Section  = (uint8_t*)firm_loc + firm_loc->section[2].offset;
+       uint32_t arm9SectionSize = firm_loc->section[2].size;
+
+       uint8_t* process9Offset = (uint8_t *)firm_p9_exefs + sizeof(exefs_h) + firm_p9_exefs->fileHeaders[0].offset;
+       uint32_t process9Size   = firm_p9_exefs->fileHeaders[0].size;
+
+    //Copy emuNAND code
+    void *emuCodeOffset = getEmuCode(arm9Section, arm9SectionSize);
+       if (!emuCodeOffset)
+               abort("emunand: code missing from arm9?\n");
+
+       FILE* f = fopen(PATH_EMUNAND_CODE, "r");
+       if (!f)
+               abort("emunand: code not found on SD.\n");
+
+       uint32_t emunand_size = fsize(f);
+       fread(emuCodeOffset, 1, emunand_size, f);
+       fclose(f);
+
+    uint32_t branchOffset = (uint32_t)emuCodeOffset - ((uint32_t)firm_loc + firm_loc->section[2].offset - firm_loc->section[2].address);
+
+       fprintf(stderr, "emunand: read in emunand code - %x\n", emuCodeOffset);
+
+    //Add the data of the found emuNAND
+    uint32_t *pos_offset = (uint32_t *)memfind(emuCodeOffset, emunand_size, "NAND", 4),
+             *pos_head   = (uint32_t *)memfind(emuCodeOffset, emunand_size, "NCSD", 4),
+             *pos_sdmmc  = (uint32_t *)memfind(emuCodeOffset, emunand_size, "SDMC", 4);
+
+       verify_emunand(index, pos_offset, pos_head);
+
+       fprintf(stderr, "emunand: nand is on sector %u\n", *pos_offset);
+       fprintf(stderr, "emunand: head is on sector %u\n", *pos_head);
+
+       if (!pos_offset || !pos_head || !pos_sdmmc)
+               abort("emunand: couldn't find pattern in hook?\n");
+
+    //Add emuNAND hooks
+    patchNANDRW(process9Offset, process9Size, branchOffset);
+
+       fprintf(stderr, "emunand: patched read/write calls\n");
+
+    //Find and add the SDMMC struct
+
+    *pos_sdmmc = getSDMMC(process9Offset, process9Size);
+
+    //Set MPU for emu code region
+    patchMPU(arm9Section, arm9SectionSize);
+
+       fprintf(stderr, "emunand: patched MPU settings\n");
+}
+
diff --git a/source/patch/emunand.h b/source/patch/emunand.h
new file mode 100644 (file)
index 0000000..35b3c56
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __EMUNAND_H
+#define __EMUNAND_H
+
+#include <stdint.h>
+
+void patch_emunand(uint32_t size);
+
+#endif
index c9af51b3d37a37ff40ee5f5a12400f179e851da1..ea1a4204bf6242ff378c2666c1a34e16f24b7faa 100644 (file)
                                               // additionally the root if not found.
 #define PATH_EXEFS PATH_CFW "/exe"            // ExeFS overrides, named like '<titleid>.exefs' - NYI
 
+#define PATH_BITS PATH_CFW "/bits"            // Path to misc bits we need (emunand code, reboot code, etc)
+
+#define PATH_EMUNAND_CODE PATH_BITS "/emunand.bin" // Emunand hook.
+#define PATH_SCREENINIT_CODE PATH_BITS "/screeninit.bin" // Screeninit code (ARM11)
+
 #define PATH_NATIVE_F PATH_FIRMWARES "/native"
 #define PATH_AGB_F PATH_FIRMWARES "/agb"
 #define PATH_TWL_F PATH_FIRMWARES "/twl"
index b8ae1edb18badc5fd9d4792f7465874e87f7f72f..1dd98d8ad0494e7df782e9a4d8f0f5d3c71addae 100644 (file)
@@ -5,6 +5,7 @@
 #include "config.h"
 #include "common.h"
 #include "interp.h"
+#include "patch/emunand.h"
 
 // TODO - Basically all this needs to move to patcher programs.
 
@@ -84,5 +85,15 @@ patch_firm_all()
         wait();
     }
 
+    // Use loopback EmuNAND?
+    if (config.options[OPTION_EMUNAND]) {
+        // Yes.
+               patch_emunand(0);
+//             patch_loop_emunand("/nand.bin");
+
+        // FIXME - NYI
+        wait();
+    }
+
     return 0;
 }
diff --git a/source/screeninit.c b/source/screeninit.c
new file mode 100644 (file)
index 0000000..9ce3eac
--- /dev/null
@@ -0,0 +1,26 @@
+#include "std/fs.h"
+#include "i2c.h"
+#include "patch_format.h"
+
+#define PDN_GPU_CNT (*(volatile uint8_t *)0x10141200)
+
+static volatile uint32_t *const a11_entry = (volatile uint32_t *)0x1FFFFFF8;
+
+void screen_init() {
+       if (PDN_GPU_CNT == 1) {
+               uint32_t* screenInitAddress = (uint32_t*)0x24FFFC00;
+
+               FILE* f = fopen(PATH_SCREENINIT_CODE, "r");
+               fread(screenInitAddress, 1, fsize(f), f); // Read in the screeninit payload.
+               fclose(f);
+
+               //Write brightness level for the stub to pick up
+               screenInitAddress[2] = 0x5F;
+               *a11_entry = (uint32_t)screenInitAddress;
+
+               while(*a11_entry);
+
+               //Turn on backlight
+               i2cWriteRegister(I2C_DEV_MCU, 0x22, 0x2A);
+       }
+}
diff --git a/source/screeninit.h b/source/screeninit.h
new file mode 100644 (file)
index 0000000..5105774
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __SCREENINIT_H
+#define __SCREENINIT_H
+
+// Inits the screen if needed.
+void screen_init();
+
+#endif
index 08f62830f123d15daab04a48c888c3bd933360db..3dc565ab5001073cf955eac797b61f6144ac9652 100644 (file)
@@ -51,8 +51,10 @@ clear_disp(uint8_t *screen)
         fseek(f, 0, SEEK_END);
         for (int i = 0; i < TEXT_BOTTOM_HEIGHT; i++) {
             char *text = text_buffer_bottom + (TEXT_BOTTOM_WIDTH * i);
-            if (text[0] == 0)
-                break;
+                       for(int j = 0; j < TEXT_BOTTOM_WIDTH; j++) {
+                               if (text[j] == 0)
+                                       text[j] = ' ';
+                       }
             fwrite(text, 1, strnlen(text, TEXT_BOTTOM_WIDTH), f);
             fwrite("\n", 1, 1, f);
         }
index 1b1db706f3ae5325ac83fcca945db9c9417a5357..38ee108a389fb38345da4601358656375f0f478f 100644 (file)
@@ -229,3 +229,24 @@ read_file(void *data, char *path, size_t size)
 
     return read;
 }
+
+//    DWORD fptr;   /* File read/write pointer (Zeroed on file open) */
+//    DWORD fsize;  /* File size */
+//    DWORD sclust; /* File start cluster (0:no cluster chain, always 0 when fsize is 0) */
+//    DWORD clust;  /* Current cluster of fpter (not valid when fprt is 0) */
+//    DWORD dsect;  /* Sector number appearing in buf[] (0:invalid) */
+
+size_t get_file_sector(char* path) {
+       FILE* temp = fopen(path, "r");
+
+    if (!temp || !temp->is_open)
+        return 0;
+
+       UINT sector;
+
+       f_getsector(& temp->handle, &sector);
+
+       fclose(temp);
+
+       return sector;
+}
index 852a389abc42bc29250073ec60b9094f4c50e3ac..5aac56960d2e1437cc6ce186dbfb14d0f3f743c7 100644 (file)
@@ -43,4 +43,6 @@ size_t fread(void *buffer, size_t elementSize, size_t elementCnt, FILE *fp);
 size_t write_file(void *data, char *path, size_t size);
 size_t read_file(void *data, char *path, size_t size);
 
+size_t get_file_sector(char* path);
+
 #endif
index 290a10d92c8fb91e0771f09b3282c926e8dc06da..99a085be48d61e7db8df9b4d867489c95b787742 100644 (file)
@@ -2,7 +2,6 @@
 #define __STD_TYPES_H
 
 #include <stdint.h>
-#include <stdlib.h>
 
 #define CFG_BOOTENV *(volatile uint32_t *)0x10010000
 #define HID ~*(volatile uint32_t *)0x10146000