diff --git a/Makefile b/Makefile index cc371e3..b4a3b29 100644 --- a/Makefile +++ b/Makefile @@ -1,90 +1,109 @@ -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=devkitARM") -endif - -include $(DEVKITARM)/base_rules - -################################################################################ - -IPL_LOAD_ADDR := 0x40008000 -VERSION := $(shell cat VERSION) - -################################################################################ - -TARGET := omninx-installer -OUTPUT_NAME := OmniNX-Installer.bin -BUILDDIR := build -OUTPUTDIR := output -SOURCEDIR := source -BDKDIR := bdk -BDKINC := -I./$(BDKDIR) -VPATH = $(dir ./$(SOURCEDIR)/) $(dir $(wildcard ./$(SOURCEDIR)/*/)) $(dir $(wildcard ./$(SOURCEDIR)/*/*/)) -VPATH += $(dir $(wildcard ./$(BDKDIR)/)) $(dir $(wildcard ./$(BDKDIR)/*/)) $(dir $(wildcard ./$(BDKDIR)/*/*/)) - -# All source files -OBJS = $(patsubst $(SOURCEDIR)/%.S, $(BUILDDIR)/$(TARGET)/%.o, \ - $(patsubst $(SOURCEDIR)/%.c, $(BUILDDIR)/$(TARGET)/%.o, \ - $(call rwildcard, $(SOURCEDIR), *.S *.c))) -OBJS += $(patsubst $(BDKDIR)/%.S, $(BUILDDIR)/$(TARGET)/%.o, \ - $(patsubst $(BDKDIR)/%.c, $(BUILDDIR)/$(TARGET)/%.o, \ - $(call rwildcard, $(BDKDIR), *.S *.c))) - -GFX_INC := '"../$(SOURCEDIR)/gfx.h"' -FFCFG_INC := '"../$(SOURCEDIR)/libs/fatfs/ffconf.h"' - -################################################################################ - -CUSTOMDEFINES := -DIPL_LOAD_ADDR=$(IPL_LOAD_ADDR) -CUSTOMDEFINES += -DGFX_INC=$(GFX_INC) -DFFCFG_INC=$(FFCFG_INC) -CUSTOMDEFINES += -DVERSION='"$(VERSION)"' - -ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork -CFLAGS = $(ARCH) -Os -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11 -Wall -Wno-missing-braces $(CUSTOMDEFINES) -LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=IPL_LOAD_ADDR=$(IPL_LOAD_ADDR) - -################################################################################ - -.PHONY: all clean release - -all: $(OUTPUTDIR)/$(OUTPUT_NAME) - $(eval BIN_SIZE = $(shell wc -c < $(OUTPUTDIR)/$(OUTPUT_NAME))) - @echo "Payload size is $(BIN_SIZE) bytes" - @echo "Max size is 126296 bytes." - -clean: - @rm -rf $(BUILDDIR) - @rm -rf $(OUTPUTDIR) - @rm -rf release - @rm -f $(TARGET)-*.zip - -$(OUTPUTDIR)/$(OUTPUT_NAME): $(BUILDDIR)/$(TARGET)/$(TARGET).elf - @mkdir -p "$(@D)" - $(OBJCOPY) -S -O binary $< $(OUTPUTDIR)/$(TARGET).bin - @mv $(OUTPUTDIR)/$(TARGET).bin $(OUTPUTDIR)/$(OUTPUT_NAME) - -$(BUILDDIR)/$(TARGET)/$(TARGET).elf: $(OBJS) - $(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $^ -o $@ - -$(BUILDDIR)/$(TARGET)/%.o: $(SOURCEDIR)/%.c - @mkdir -p "$(@D)" - $(CC) $(CFLAGS) $(BDKINC) -I$(SOURCEDIR) -c $< -o $@ - -$(BUILDDIR)/$(TARGET)/%.o: $(SOURCEDIR)/%.S - @mkdir -p "$(@D)" - $(CC) $(CFLAGS) -c $< -o $@ - -$(BUILDDIR)/$(TARGET)/%.o: $(BDKDIR)/%.c - @mkdir -p "$(@D)" - $(CC) $(CFLAGS) $(BDKINC) -I$(SOURCEDIR) -c $< -o $@ - -$(BUILDDIR)/$(TARGET)/%.o: $(BDKDIR)/%.S - @mkdir -p "$(@D)" - $(CC) $(CFLAGS) -c $< -o $@ - -release: $(OUTPUTDIR)/$(OUTPUT_NAME) - @mkdir -p release/bootloader/payloads - @cp $(OUTPUTDIR)/$(OUTPUT_NAME) release/bootloader/payloads/$(OUTPUT_NAME) - @cd release && zip -r ../$(TARGET)-$(VERSION).zip bootloader - @echo "Release package created: $(TARGET)-$(VERSION).zip" +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=devkitARM") +endif + +include $(DEVKITARM)/base_rules + +################################################################################ + +IPL_LOAD_ADDR := 0x40008000 +VERSION := $(shell cat VERSION) + +################################################################################ + +TARGET := omninx-installer +OUTPUT_NAME := OmniNX-Installer.bin +BUILDDIR := build +OUTPUTDIR := output +SOURCEDIR := source +BDKDIR := bdk +BDKINC := -I./$(BDKDIR) +VPATH = $(dir ./$(SOURCEDIR)/) $(dir $(wildcard ./$(SOURCEDIR)/*/)) $(dir $(wildcard ./$(SOURCEDIR)/*/*/)) +VPATH += $(dir $(wildcard ./$(BDKDIR)/)) $(dir $(wildcard ./$(BDKDIR)/*/)) $(dir $(wildcard ./$(BDKDIR)/*/*/)) + +# All source files +OBJS = $(patsubst $(SOURCEDIR)/%.S, $(BUILDDIR)/$(TARGET)/%.o, \ + $(patsubst $(SOURCEDIR)/%.c, $(BUILDDIR)/$(TARGET)/%.o, \ + $(call rwildcard, $(SOURCEDIR), *.S *.c))) +OBJS += $(patsubst $(BDKDIR)/%.S, $(BUILDDIR)/$(TARGET)/%.o, \ + $(patsubst $(BDKDIR)/%.c, $(BUILDDIR)/$(TARGET)/%.o, \ + $(call rwildcard, $(BDKDIR), *.S *.c))) + +GFX_INC := '"../$(SOURCEDIR)/gfx.h"' +FFCFG_INC := '"../$(SOURCEDIR)/libs/fatfs/ffconf.h"' + +################################################################################ + +CUSTOMDEFINES := -DIPL_LOAD_ADDR=$(IPL_LOAD_ADDR) +CUSTOMDEFINES += -DGFX_INC=$(GFX_INC) -DFFCFG_INC=$(FFCFG_INC) +CUSTOMDEFINES += -DVERSION='"$(VERSION)"' + +ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork +CFLAGS = $(ARCH) -Os -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11 -Wall -Wno-missing-braces $(CUSTOMDEFINES) +LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=IPL_LOAD_ADDR=$(IPL_LOAD_ADDR) + +################################################################################ + +RAMTEST_BIN := $(OUTPUTDIR)/RAM-Test.bin +OBJS_RAMTEST := $(filter-out $(BUILDDIR)/$(TARGET)/main.o,$(OBJS)) \ + $(BUILDDIR)/$(TARGET)/ram_test_main.o + +.PHONY: all clean release ram-test + +all: $(OUTPUTDIR)/$(OUTPUT_NAME) + $(eval BIN_SIZE = $(shell wc -c < $(OUTPUTDIR)/$(OUTPUT_NAME))) + @echo "Payload size is $(BIN_SIZE) bytes" + @echo "Max size is 126296 bytes." + +clean: + @rm -rf $(BUILDDIR) + @rm -rf $(OUTPUTDIR) + @rm -f $(RAMTEST_BIN) + @rm -rf release + @rm -f $(TARGET)-*.zip + +$(OUTPUTDIR)/$(OUTPUT_NAME): $(BUILDDIR)/$(TARGET)/$(TARGET).elf + @mkdir -p "$(@D)" + $(OBJCOPY) -S -O binary $< $(OUTPUTDIR)/$(TARGET).bin + @mv $(OUTPUTDIR)/$(TARGET).bin $(OUTPUTDIR)/$(OUTPUT_NAME) + +$(BUILDDIR)/$(TARGET)/$(TARGET).elf: $(OBJS) + $(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $^ -o $@ + +$(BUILDDIR)/$(TARGET)/ram_test_main.o: tools/ram_test_main.c + @mkdir -p "$(@D)" + $(CC) $(CFLAGS) $(BDKINC) -I$(SOURCEDIR) -c $< -o $@ + +$(BUILDDIR)/$(TARGET)/ram_test.elf: $(OBJS_RAMTEST) + $(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $^ -o $@ + +$(RAMTEST_BIN): $(BUILDDIR)/$(TARGET)/ram_test.elf + @mkdir -p "$(@D)" + $(OBJCOPY) -S -O binary $< $@ + @echo "RAM-Test payload: $(RAMTEST_BIN) ($$(wc -c < $@) bytes)" + +ram-test: $(RAMTEST_BIN) + +$(BUILDDIR)/$(TARGET)/%.o: $(SOURCEDIR)/%.c + @mkdir -p "$(@D)" + $(CC) $(CFLAGS) $(BDKINC) -I$(SOURCEDIR) -c $< -o $@ + +$(BUILDDIR)/$(TARGET)/%.o: $(SOURCEDIR)/%.S + @mkdir -p "$(@D)" + $(CC) $(CFLAGS) -c $< -o $@ + +$(BUILDDIR)/$(TARGET)/%.o: $(BDKDIR)/%.c + @mkdir -p "$(@D)" + $(CC) $(CFLAGS) $(BDKINC) -I$(SOURCEDIR) -c $< -o $@ + +$(BUILDDIR)/$(TARGET)/%.o: $(BDKDIR)/%.S + @mkdir -p "$(@D)" + $(CC) $(CFLAGS) -c $< -o $@ + +release: $(OUTPUTDIR)/$(OUTPUT_NAME) + @mkdir -p release/bootloader/payloads + @cp $(OUTPUTDIR)/$(OUTPUT_NAME) release/bootloader/payloads/$(OUTPUT_NAME) + @cd release && zip -r ../$(TARGET)-$(VERSION).zip bootloader + @echo "Release package created: $(TARGET)-$(VERSION).zip" diff --git a/source/dram_fuse.c b/source/dram_fuse.c new file mode 100644 index 0000000..c97465a --- /dev/null +++ b/source/dram_fuse.c @@ -0,0 +1,46 @@ +/* + * DRAM capacity from fuse (SKU), not physical probe. + */ + +#include "dram_fuse.h" +#include +#include +#include + +static int mariko_dram_mib(u32 dram_id) +{ + switch (dram_id) { + case 9: + case 13: + case 18: + case 21: + case 23: + case 28: + return 8192; + default: + if (dram_id >= 3 && dram_id <= 28) + return 4096; + return -1; + } +} + +static int erista_dram_mib(u32 dram_id) +{ + if (dram_id == 4) + return 6144; + if (dram_id <= 6) + return 4096; + return -1; +} + +int dram_capacity_mib_from_fuse(void) +{ + u32 nid = fuse_read_dramid(false); + u32 chip = hw_get_chip_id(); + + if (chip == GP_HIDREV_MAJOR_T210) + return erista_dram_mib(nid); + if (chip == GP_HIDREV_MAJOR_T210B01) + return mariko_dram_mib(nid); + return -1; +} diff --git a/source/dram_fuse.h b/source/dram_fuse.h new file mode 100644 index 0000000..045e732 --- /dev/null +++ b/source/dram_fuse.h @@ -0,0 +1,6 @@ +#pragma once + +#include + +/* DRAM capacity in MiB from fuse DRAM ID + SoC (same table as RAM test payload). */ +int dram_capacity_mib_from_fuse(void); diff --git a/source/install.c b/source/install.c index d5f12e3..dd68165 100644 --- a/source/install.c +++ b/source/install.c @@ -3,6 +3,7 @@ */ #include "install.h" +#include "dram_fuse.h" #include "fs.h" #include "version.h" #include "gfx.h" @@ -618,6 +619,50 @@ int delete_path_list(const char* paths[], const char* description) { return (failed == 0) ? FR_OK : FR_DISK_ERR; } +#define HEKATE_8GB_SRC "sd:/bootloader/hekate_8gb.bin" +#define PAYLOAD_BIN_DST "sd:/payload.bin" +#define UPDATE_BIN_DST "sd:/bootloader/update.bin" + +static void unlink_ignore_err(const char *path) +{ + FILINFO fno; + if (f_stat(path, &fno) != FR_OK) + return; + if (fno.fattrib & AM_RDO) + f_chmod(path, fno.fattrib & ~AM_RDO, AM_RDO); + f_unlink(path); +} + +/* After pack copy: if >4 GiB fuse RAM, install 8GB Hekate to payload.bin + bootloader/update.bin; always remove hekate_8gb.bin when done or if not used. */ +static void install_hekate_8gb_post_copy(void) +{ + if (!install_path_exists(HEKATE_8GB_SRC)) + return; + + int mib = dram_capacity_mib_from_fuse(); + if (mib > 4096) { + install_set_color(COLOR_CYAN); + gfx_printf("\nMehr als 4 GB RAM erkannt (Fuse). Die 8-GB-Hekate-Variante wird verwendet.\n"); + gfx_printf("Kopiere nach payload.bin und bootloader/update.bin...\n"); + install_set_color(COLOR_WHITE); + + int r1 = file_copy(HEKATE_8GB_SRC, PAYLOAD_BIN_DST); + int r2 = file_copy(HEKATE_8GB_SRC, UPDATE_BIN_DST); + if (r1 == FR_OK && r2 == FR_OK) { + install_set_color(COLOR_GREEN); + gfx_printf(" [OK] Hekate 8 GB installiert.\n"); + install_set_color(COLOR_WHITE); + unlink_ignore_err(HEKATE_8GB_SRC); + } else { + install_set_color(COLOR_ORANGE); + gfx_printf(" [WARN] Kopie fehlgeschlagen (payload: %d, update: %d). hekate_8gb.bin bleibt.\n", r1, r2); + install_set_color(COLOR_WHITE); + } + } else { + unlink_ignore_err(HEKATE_8GB_SRC); + } +} + // Main installation function int perform_installation(omninx_variant_t pack_variant, install_mode_t mode) { int res; @@ -637,7 +682,9 @@ int perform_installation(omninx_variant_t pack_variant, install_mode_t mode) { install_set_color(COLOR_WHITE); res = update_mode_install(pack_variant); if (res != FR_OK) return res; - + + install_hekate_8gb_post_copy(); + install_check_and_clear_screen_if_needed(); // Remove staging directory (installed pack) res = cleanup_staging_directory(pack_variant); @@ -676,7 +723,9 @@ int perform_installation(omninx_variant_t pack_variant, install_mode_t mode) { install_set_color(COLOR_WHITE); res = clean_mode_install(pack_variant); if (res != FR_OK) return res; - + + install_hekate_8gb_post_copy(); + install_check_and_clear_screen_if_needed(); // Remove staging directory (installed pack) res = cleanup_staging_directory(pack_variant); diff --git a/tools/ram_test_main.c b/tools/ram_test_main.c new file mode 100644 index 0000000..a412679 --- /dev/null +++ b/tools/ram_test_main.c @@ -0,0 +1,70 @@ +/* + * Minimal RAM info test payload (fuse DRAM ID + SK table -> MiB). + * Build: make ram-test -> output/RAM-Test.bin + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dram_fuse.h" +#include "gfx.h" + +#undef COLOR_CYAN +#undef COLOR_WHITE +#define COLOR_CYAN 0xFF00FFFF +#define COLOR_WHITE 0xFFFFFFFF + +/* Required by BDK */ +boot_cfg_t __attribute__((section("._boot_cfg"))) b_cfg; +volatile nyx_storage_t *nyx_str = (nyx_storage_t *)NYX_STORAGE_ADDR; + +extern void pivot_stack(u32 stack_top); + +void ipl_main(void) +{ + hw_init(); + pivot_stack(IPL_STACK_TOP); + heap_init(IPL_HEAP_START); + + minerva_init(); + minerva_change_freq(FREQ_800); + + display_init(); + u32 *fb = display_init_framebuffer_pitch(); + gfx_init_ctxt(fb, 720, 1280, 720); + gfx_con_init(); + display_backlight_pwm_init(); + display_backlight_brightness(100, 1000); + + bpmp_clk_rate_set(BPMP_CLK_DEFAULT_BOOST); + + gfx_clear_grey(0x1B); + gfx_con_setpos(0, 0); + gfx_con_setcol(COLOR_CYAN, gfx_con.fillbg, gfx_con.bgcol); + gfx_printf("RAM test payload\n\n"); + gfx_con_setcol(COLOR_WHITE, gfx_con.fillbg, gfx_con.bgcol); + + u32 raw = fuse_read_dramid(true); + u32 nid = fuse_read_dramid(false); + u32 chip = hw_get_chip_id(); + int mib = dram_capacity_mib_from_fuse(); + + gfx_printf("SoC: %s\n", chip == GP_HIDREV_MAJOR_T210B01 ? "Mariko (T210B01)" : "Erista (T210)"); + gfx_printf("DRAM fuse: raw %d norm %d\n", raw, nid); + if (mib > 0) + gfx_printf("Table MiB: %d (fuse SKU, not probe)\n", mib); + else + gfx_printf("Table MiB: (unknown id for this SoC)\n"); + + gfx_printf("\nHang — power off or inject payload.\n"); + + while (1) + msleep(500); +}