diff --git a/exosphere/Makefile b/exosphere/Makefile new file mode 100644 index 000000000..3bdaf7249 --- /dev/null +++ b/exosphere/Makefile @@ -0,0 +1,71 @@ +rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2)) + +ifeq ($(strip $(DEVKITPRO)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") +endif + +include $(DEVKITPRO)/devkitA64/base_tools + +name := exosphere + +dir_source := src +dir_build := build +dir_out := out +dir_bpmpfw := bpmpfw + +ARCH := -march=armv8-a -mtune=cortex-a57 + +ASFLAGS := -g $(ARCH) + +CFLAGS = \ + $(ARCH) \ + -g \ + -O2 \ + -ffunction-sections \ + -fdata-sections \ + -fomit-frame-pointer \ + -std=gnu11 \ + -Werror \ + -Wall + +LDFLAGS = -g $(ARCH) -nostartfiles -Wl,--nmagic,--gc-sections + +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_out)/$(name).bin + +.PHONY: clean +clean: + @$(MAKE) -C $(dir_bpmpfw) clean + @rm -rf $(dir_build) + @rm -rf $(dir_out) + +.PHONY: $(dir_bpmpfw) + +$(dir_out)/$(name).bin: $(dir_build)/$(name).elf + @mkdir -p "$(@D)" + $(OBJCOPY) -S -O binary $< $@ + +$(dir_build)/$(name).elf: $(objects) + $(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^ + +$(dir_bpmpfw)/out/bpmpfw.bin: $(dir_bpmpfw) + @$(MAKE) -C $< + +$(dir_build)/bpmpfw.bin: $(dir_bpmpfw)/out/bpmpfw.bin + @mkdir -p "$(@D)" + @cp $< $(@D) + +$(dir_build)/%.bin.o: $(dir_build)/%.bin + @$(bin2o) + +$(dir_build)/%.o: $(dir_source)/%.c $(dir_build)/bpmpfw.bin.o + @mkdir -p "$(@D)" + $(COMPILE.c) $(OUTPUT_OPTION) $< + +$(dir_build)/%.o: $(dir_source)/%.s + @mkdir -p "$(@D)" + $(COMPILE.c) -x assembler-with-cpp $(OUTPUT_OPTION) $< diff --git a/exosphere/bpmpfw/Makefile b/exosphere/bpmpfw/Makefile index 87df99b5e..74ca355ba 100644 --- a/exosphere/bpmpfw/Makefile +++ b/exosphere/bpmpfw/Makefile @@ -6,7 +6,7 @@ endif include $(DEVKITARM)/base_tools -name := $(shell basename $(CURDIR)) +name := bpmpfw dir_source := src dir_build := build diff --git a/exosphere/build/bpmpfw.bin b/exosphere/build/bpmpfw.bin new file mode 100644 index 000000000..a362f8eb1 Binary files /dev/null and b/exosphere/build/bpmpfw.bin differ diff --git a/exosphere/linker.ld b/exosphere/linker.ld new file mode 100644 index 000000000..af74fd16e --- /dev/null +++ b/exosphere/linker.ld @@ -0,0 +1,16 @@ +ENTRY(__start_cold) +SECTIONS +{ + /* DUMMY LINKER SCRIPT, REPLACE ASAP */ + . = 0xF0000000; + + __start__ = ABSOLUTE(.); + + .text : ALIGN(4) { *(.text*); . = ALIGN(4); } + .rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); } + .data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); } + + . = ALIGN(4); + + __end__ = ABSOLUTE(.); +} diff --git a/exosphere/out/exosphere.bin b/exosphere/out/exosphere.bin new file mode 100644 index 000000000..d3b67d219 Binary files /dev/null and b/exosphere/out/exosphere.bin differ diff --git a/exosphere/src/bootconfig.c b/exosphere/src/bootconfig.c new file mode 100644 index 000000000..589327321 --- /dev/null +++ b/exosphere/src/bootconfig.c @@ -0,0 +1,40 @@ +#include "bootconfig.h" + +void bootconfig_load_and_verify(const bootconfig_t *bootconfig) { + /* TODO */ +} + +void bootconfig_clear(void){ + /* TODO */ +} + +/* Actual configuration getters. */ +bool bootconfig_is_package2_plaintext(void) { + return false; + /* TODO */ +} + +bool bootconfig_is_package2_unsigned(void) { + return false; + /* TODO */ +} + +bool bootconfig_disable_program_verification(void) { + return false; + /* TODO */ +} + +bool bootconfig_is_debug_mode(void) { + return false; + /* TODO */ +} + +uint64_t bootconfig_get_memory_arrangement(void) { + return 0ULL; + /* TODO */ +} + +uint64_t bootconfig_get_kernel_memory_configuration(void) { + return 0ULL; + /* TODO */ +} diff --git a/exosphere/bootconfig.h b/exosphere/src/bootconfig.h similarity index 100% rename from exosphere/bootconfig.h rename to exosphere/src/bootconfig.h diff --git a/exosphere/cache.h b/exosphere/src/cache.h similarity index 89% rename from exosphere/cache.h rename to exosphere/src/cache.h index 03fa1a9a4..e8f8c4a9d 100644 --- a/exosphere/cache.h +++ b/exosphere/src/cache.h @@ -6,7 +6,7 @@ void tlb_invalidate_all(void); void tlb_invalidate_all_inner_shareable(void); -void tlb_invalidate_page(const void *page); +void tlb_invalidate_page(const volatile void *page); void tlb_invalidate_page_inner_shareable(const void *page); void flush_dcache_all(void); diff --git a/exosphere/cache.s b/exosphere/src/cache.s similarity index 100% rename from exosphere/cache.s rename to exosphere/src/cache.s diff --git a/exosphere/coldboot_init.c b/exosphere/src/coldboot_init.c similarity index 89% rename from exosphere/coldboot_init.c rename to exosphere/src/coldboot_init.c index 0992a103b..b62650c08 100644 --- a/exosphere/coldboot_init.c +++ b/exosphere/src/coldboot_init.c @@ -2,6 +2,7 @@ #include "mmu.h" #include "memory_map.h" +/* extern void (*__preinit_array_start[])(void); extern void (*__preinit_array_end[])(void); extern void (*__init_array_start[])(void); @@ -11,7 +12,7 @@ extern void _init(void); extern uint8_t __warmboot_crt0_start__[], __warmboot_crt0_end__[], __warmboot_crt0_lma__[]; extern uint8_t __main_start__[], __main_end__[], __main_lma__[]; extern uint8_t __pk2ldr_start__[], __pk2ldr_end__[], __pk2ldr_lma__[]; -extern uint8_t __vectors_start__[], __vectors_end__[], __vectors_lma__[]; +extern uint8_t __vectors_start__[], __vectors_end__[], __vectors_lma__[];*/ extern void flush_dcache_all_tzram_pa(void); extern void invalidate_icache_all_tzram_pa(void); @@ -44,6 +45,8 @@ static void configure_ttbls(void) { tzram_map_all_segments(mmu_l3_tbl); } +#if 0 + static void copy_lma_to_vma(unsigned int segment_id, void *lma, size_t size, bool vma_is_pa) { uintptr_t vma = vma_is_pa ? tzram_get_segment_pa(segment_id) : tzram_get_segment_address(segment_id); uintptr_t vma_offset = (uintptr_t)lma & 0xFFF; @@ -61,6 +64,7 @@ static void __libc_init_array(void) { for (size_t i = 0; i < __init_array_end - __init_array_start; i++) __init_array_start[i](); } +#endif uintptr_t get_coldboot_crt0_stack_address(void) { return tzram_get_segment_pa(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x800; @@ -68,18 +72,18 @@ uintptr_t get_coldboot_crt0_stack_address(void) { void coldboot_init(void) { /* TODO: Set NX BOOTLOADER clock time field */ - copy_lma_to_vma(TZRAM_SEGMENT_ID_WARMBOOT_CRT0_AND_MAIN, __warmboot_crt0_lma__, __warmboot_crt0_end__ - __warmboot_crt0_start__, true); + /*copy_lma_to_vma(TZRAM_SEGMENT_ID_WARMBOOT_CRT0_AND_MAIN, __warmboot_crt0_lma__, __warmboot_crt0_end__ - __warmboot_crt0_start__, true);*/ /* TODO: set some mmio regs, etc. */ /* TODO: initialize DMA controllers */ configure_ttbls(); - copy_lma_to_vma(TZRAM_SEGMENT_ID_WARMBOOT_CRT0_AND_MAIN, __main_lma__, __main_end__ - __main_start__, false); + /*copy_lma_to_vma(TZRAM_SEGMENT_ID_WARMBOOT_CRT0_AND_MAIN, __main_lma__, __main_end__ - __main_start__, false); copy_lma_to_vma(TZRAM_SEGMENT_ID_PK2LDR, __pk2ldr_lma__, __pk2ldr_end__ - __pk2ldr_start__, false); - copy_lma_to_vma(TZRAM_SEGEMENT_ID_SECMON_EVT, __vectors_lma__, __vectors_end__ - __vectors_start__, false); + copy_lma_to_vma(TZRAM_SEGEMENT_ID_SECMON_EVT, __vectors_lma__, __vectors_end__ - __vectors_start__, false);*/ /* TODO: set the MMU regs & tlbi & enable MMU */ flush_dcache_all_tzram_pa(); invalidate_icache_all_tzram_pa(); /* TODO: zero-initialize the cpu context */ /* Nintendo clears the (emtpy) pk2ldr's BSS section, but we embed it 0-filled in the binary */ - __libc_init_array(); /* construct global objects */ + /*__libc_init_array(); construct global objects */ } diff --git a/exosphere/coldboot_main.c b/exosphere/src/coldboot_main.c similarity index 71% rename from exosphere/coldboot_main.c rename to exosphere/src/coldboot_main.c index bb76ce8dc..9917edfd1 100644 --- a/exosphere/coldboot_main.c +++ b/exosphere/src/coldboot_main.c @@ -2,10 +2,12 @@ #include "utils.h" #include "mmu.h" #include "memory_map.h" +#include "cache.h" +/* extern void (*__fini_array_start[])(void); extern void (*__fini_array_end[])(void); -extern void _fini(void); +extern void _fini(void);*/ extern uint8_t __pk2ldr_start__[], __pk2ldr_end__[]; @@ -13,21 +15,25 @@ extern void __jump_to_lower_el(uint64_t arg, uintptr_t ep, unsigned int el); void coldboot_main(void); +#if 0 /* Needs to be called for EL3->EL3 chainloading (and only in that case). TODO: use it */ -static void __libc_fini_array(void) __attribute__((used)) { +__attribute__((used)) static void __libc_fini_array(void) { for (size_t i = __fini_array_end - __fini_array_start; i > 0; i--) __fini_array_start[i - 1](); _fini(); /* FIXME: do we have this gcc-provided symbol if we build with -nostartfiles? */ } +#endif void coldboot_main(void) { + #if 0 uintptr_t *mmu_l3_table = (uintptr_t *)tzram_get_segment_address(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); - void *pk2ldr = (void *)tzram_get_segment_address(TZRAM_SEGMENT_ID_PK2LDR); + uintptr_t pk2ldr = tzram_get_segment_address(TZRAM_SEGMENT_ID_PK2LDR); /* Clear and unmap pk2ldr (which is reused as exception entry stacks) */ - memset(pk2ldr, 0, __pk2ldr_end__ - __pk2ldr_start__); - mmu_unmap_range(mmu_l3_table, pk2ldr, __pk2ldr_end__ - __pk2ldr_start__); + memset((void *)pk2ldr, 0, __pk2ldr_end__ - __pk2ldr_start__); + mmu_unmap_range(3, mmu_l3_table, pk2ldr, __pk2ldr_end__ - __pk2ldr_start__); tlb_invalidate_all_inner_shareable(); + #endif /* TODO: stuff & jump to lower EL */ } diff --git a/exosphere/configitem.c b/exosphere/src/configitem.c similarity index 97% rename from exosphere/configitem.c rename to exosphere/src/configitem.c index 2e21a4dbf..ed5a3221a 100644 --- a/exosphere/configitem.c +++ b/exosphere/src/configitem.c @@ -5,6 +5,7 @@ #include "interrupt.h" #include "package2.h" #include "se.h" +#include "fuse.h" #include "utils.h" int g_battery_profile = 0; @@ -15,6 +16,7 @@ uint32_t configitem_set(enum ConfigItem item, uint64_t value) { } g_battery_profile = ((int)(value != 0)) & 1; + return 0; /* FIXME: what should we return there */ } bool configitem_is_recovery_boot(void) { diff --git a/exosphere/configitem.h b/exosphere/src/configitem.h similarity index 99% rename from exosphere/configitem.h rename to exosphere/src/configitem.h index f176d9bde..65ba0c9e0 100644 --- a/exosphere/configitem.h +++ b/exosphere/src/configitem.h @@ -26,4 +26,4 @@ uint32_t configitem_get(enum ConfigItem item, uint64_t *p_outvalue); bool configitem_is_recovery_boot(void); bool configitem_is_retail(void); -#endif \ No newline at end of file +#endif diff --git a/exosphere/cpu_context.c b/exosphere/src/cpu_context.c similarity index 87% rename from exosphere/cpu_context.c rename to exosphere/src/cpu_context.c index b80d26c58..c5e84f529 100644 --- a/exosphere/cpu_context.c +++ b/exosphere/src/cpu_context.c @@ -56,3 +56,15 @@ uint32_t cpu_on(uint32_t core, uint64_t entrypoint_addr, uint64_t context_id) { return 0; } +uint32_t cpu_off(void) { + return 0; + /* TODO */ +} + +uint32_t cpu_suspend(uint64_t power_state, uint64_t entrypoint_addr, uint64_t context_id) { + (void)power_state; + (void)entrypoint_addr; + (void)context_id; + return 0; + /* TODO */ +} diff --git a/exosphere/cpu_context.h b/exosphere/src/cpu_context.h similarity index 93% rename from exosphere/cpu_context.h rename to exosphere/src/cpu_context.h index dbf94d199..85149eaf5 100644 --- a/exosphere/cpu_context.h +++ b/exosphere/src/cpu_context.h @@ -47,8 +47,8 @@ typedef struct { void set_core_entrypoint_and_context_id(uint32_t core, uint64_t entrypoint_addr, uint64_t context_id); uint32_t cpu_on(uint32_t core, uint64_t entrypoint_addr, uint64_t context_id); -uint32_t cpu_off(void); -uint32_t cpu_suspend(uint64_t power_state, uint64_t entrypoint_addr, uint64_t context_id); +uint32_t cpu_off(void); /* TODO */ +uint32_t cpu_suspend(uint64_t power_state, uint64_t entrypoint_addr, uint64_t context_id); /* TODO */ -#endif \ No newline at end of file +#endif diff --git a/exosphere/exceptions.s b/exosphere/src/exceptions.s similarity index 90% rename from exosphere/exceptions.s rename to exosphere/src/exceptions.s index 14ce6e3a7..660792e09 100644 --- a/exosphere/exceptions.s +++ b/exosphere/src/exceptions.s @@ -50,9 +50,6 @@ .endif .endm - - - /* Actual Vectors for Exosphere. */ .global exosphere_vectors vector_base exosphere_vectors @@ -69,32 +66,32 @@ vector_entry synch_sp0 vector_entry irq_sp0 b unknown_exception - check_vector irq_sp0 + check_vector_size irq_sp0 vector_entry fiq_sp0 b unknown_exception - check_vector fiq_sp0 + check_vector_size fiq_sp0 vector_entry serror_sp0 b unknown_exception - check_vector serror_sp0 + check_vector_size serror_sp0 /* Current EL, SPx */ vector_entry synch_spx b unknown_exception - check_vector synch_spx + check_vector_size synch_spx vector_entry irq_spx b unknown_exception - check_vector irq_spx + check_vector_size irq_spx vector_entry fiq_spx b unknown_exception - check_vector fiq_spx + check_vector_size fiq_spx vector_entry serror_spx b unknown_exception - check_vector serror_spx + check_vector_size serror_spx /* Lower EL, A64 */ vector_entry synch_a64 @@ -108,22 +105,22 @@ vector_entry synch_a64 /* Call appropriate handler. */ stp x29, x30, [sp, #-0x10]! mrs x29, mpidr_el1 - and x29, x39, #0x3 + and x29, x29, #0x3 cmp x29, #0x3 b.ne handle_core012_smc_exception bl handle_core3_smc_exception ldp x29, x30, [sp],#0x10 eret - check_vector synch_a64 + check_vector_size synch_a64 vector_entry irq_a64 b unknown_exception - check_vector irq_a64 + check_vector_size irq_a64 vector_entry fiq_a64 stp x29, x30, [sp, #-0x10]! mrs x29, mpidr_el1 - and x29, x39, #0x3 + and x29, x29, #0x3 cmp x29, #0x3 b.ne unknown_exception stp x28, x29, [sp, #-0x10]! @@ -133,7 +130,7 @@ vector_entry fiq_a64 ldp x28, x29, [sp],#0x10 ldp x29, x30, [sp],#0x10 eret - check_vector fiq_a64 + check_vector_size fiq_a64 vector_entry serror_a64 b unknown_exception @@ -171,18 +168,15 @@ handle_core012_smc_exception: ldp x6, x7, [sp],#0x10 ldp x29, x30, [sp],#0x10 eret - .if (. - serror_a64) > (32 * 4) - .error "Vector exceeds 32 instructions" - .endif - + /* Lower EL, A32 */ vector_entry synch_a32 b unknown_exception - check_vector synch_a32 + check_vector_size synch_a32 vector_entry irq_a32 b unknown_exception - check_vector irq_a32 + check_vector_size irq_a32 vector_entry fiq_a32 b fiq_a64 @@ -222,9 +216,6 @@ handle_fiq_exception: ldp x24, x25, [sp],#0x10 ldp x29, x30, [sp],#0x10 ret - .if (. - fiq_a32) > (32 * 4) - .error "Vector exceeds 32 instructions" - .endif vector_entry serror_a32 b unknown_exception @@ -260,6 +251,3 @@ handle_core3_smc_exception: ldp x16, x17, [sp],#0x10 ldp x18, x19, [sp],#0x10 ret - .if (. - serror_a32) > (32 * 4) - .error "Vector exceeds 32 instructions" - .endif diff --git a/exosphere/fuse.c b/exosphere/src/fuse.c similarity index 96% rename from exosphere/fuse.c rename to exosphere/src/fuse.c index c034c1460..62794a366 100644 --- a/exosphere/fuse.c +++ b/exosphere/src/fuse.c @@ -1,5 +1,3 @@ -#include -#include #include #include "fuse.h" @@ -17,7 +15,7 @@ void fuse_wait_idle(void); void fuse_init(void) { fuse_make_regs_visible(); - + /* TODO: Overrides (iROM patches) and various reads happen here */ } @@ -25,7 +23,7 @@ void fuse_init(void) void fuse_make_regs_visible(void) { /* TODO: Replace this with a proper CLKRST driver */ - uint32_t* misc_clk_reg = (volatile uint32_t *)mmio_get_device_address(MMIO_DEVID_CLKRST) + 0x48; + volatile uint32_t* misc_clk_reg = (volatile uint32_t *)mmio_get_device_address(MMIO_DEVID_CLKRST) + 0x48; uint32_t misc_clk_val = *misc_clk_reg; *misc_clk_reg = (misc_clk_val | (1 << 28)); } @@ -48,7 +46,7 @@ void fuse_disable_power(void) void fuse_wait_idle(void) { uint32_t ctrl_val = 0; - + /* Wait for STATE_IDLE */ while ((ctrl_val & (0xF0000)) != 0x40000) { @@ -61,36 +59,36 @@ void fuse_wait_idle(void) uint32_t fuse_hw_read(uint32_t addr) { fuse_wait_idle(); - + /* Program the target address */ FUSE_REGS->FUSE_REG_ADDR = addr; - + /* Enable read operation in control register */ uint32_t ctrl_val = FUSE_REGS->FUSE_CTRL; ctrl_val &= ~0x3; ctrl_val |= 0x1; /* Set FUSE_READ command */ FUSE_REGS->FUSE_CTRL = ctrl_val; - + fuse_wait_idle(); - + return FUSE_REGS->FUSE_REG_READ; } /* Write a fuse in the hardware array */ -void fuse_hw_write(uint32_t, value, uint32_t addr) +void fuse_hw_write(uint32_t value, uint32_t addr) { fuse_wait_idle(); - + /* Program the target address and value */ FUSE_REGS->FUSE_REG_ADDR = addr; FUSE_REGS->FUSE_REG_WRITE = value; - + /* Enable write operation in control register */ uint32_t ctrl_val = FUSE_REGS->FUSE_CTRL; ctrl_val &= ~0x3; ctrl_val |= 0x2; /* Set FUSE_WRITE command */ FUSE_REGS->FUSE_CTRL = ctrl_val; - + fuse_wait_idle(); } @@ -98,13 +96,13 @@ void fuse_hw_write(uint32_t, value, uint32_t addr) void fuse_hw_sense(void) { fuse_wait_idle(); - + /* Enable sense operation in control register */ uint32_t ctrl_val = FUSE_REGS->FUSE_CTRL; ctrl_val &= ~0x3; ctrl_val |= 0x3; /* Set FUSE_SENSE command */ FUSE_REGS->FUSE_CTRL = ctrl_val; - + fuse_wait_idle(); } @@ -135,10 +133,10 @@ uint32_t fuse_get_bootrom_patch_version(void) uint32_t fuse_get_spare_bit(uint32_t idx) { uint32_t spare_bit_val = 0; - + if ((idx >= 0) && (idx < 32)) spare_bit_val = FUSE_CHIP_REGS->FUSE_SPARE_BIT[idx]; - + return spare_bit_val; } @@ -211,7 +209,7 @@ uint32_t fuse_get_retail_type(void) { /* Derive the 16-byte Hardware Info using values in the shadow cache, and copy to output buffer. */ void fuse_get_hardware_info(void *dst) { uint32_t hw_info[0x4]; - + uint32_t unk_hw_fuse = FUSE_CHIP_REGS->_0x120 & 0x3F; uint32_t y_coord = FUSE_CHIP_REGS->FUSE_Y_COORDINATE & 0x1FF; uint32_t x_coord = FUSE_CHIP_REGS->FUSE_X_COORDINATE & 0x1FF; @@ -226,6 +224,6 @@ void fuse_get_hardware_info(void *dst) { hw_info[1] = (uint32_t)((lot_code_0 << 26) | (lot_code_1 >> 2)); hw_info[2] = (uint32_t)((fab_code << 26) | (lot_code_0 >> 6)); hw_info[3] = (uint32_t)(vendor_code); - + memcpy(dst, hw_info, 0x10); -} \ No newline at end of file +} diff --git a/exosphere/fuse.h b/exosphere/src/fuse.h similarity index 98% rename from exosphere/fuse.h rename to exosphere/src/fuse.h index 9a68725b5..1d602f73a 100644 --- a/exosphere/fuse.h +++ b/exosphere/src/fuse.h @@ -174,7 +174,7 @@ typedef struct { void fuse_init(void); uint32_t fuse_hw_read(uint32_t addr); -void fuse_hw_write(uint32_t, value, uint32_t addr); +void fuse_hw_write(uint32_t value, uint32_t addr); void fuse_hw_sense(void); void fuse_disable_programming(void); void fuse_secondary_private_key_disable(void); diff --git a/exosphere/gcm.c b/exosphere/src/gcm.c similarity index 100% rename from exosphere/gcm.c rename to exosphere/src/gcm.c diff --git a/exosphere/gcm.h b/exosphere/src/gcm.h similarity index 100% rename from exosphere/gcm.h rename to exosphere/src/gcm.h diff --git a/exosphere/i2c.c b/exosphere/src/i2c.c similarity index 97% rename from exosphere/i2c.c rename to exosphere/src/i2c.c index 72565dbf0..d98700859 100644 --- a/exosphere/i2c.c +++ b/exosphere/src/i2c.c @@ -1,5 +1,3 @@ -#include -#include #include #include "i2c.h" @@ -135,7 +133,7 @@ bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_ uint32_t val = r; if (src_size <= 3) { memcpy(((uint8_t *)&val) + 1, src, src_size); - return i2c_write(i2c_get_registers_from_id(id), &val, src_size + 1, device); + return i2c_write(i2c_get_registers_from_id(id), device, &val, src_size + 1); } else { return false; } diff --git a/exosphere/i2c.h b/exosphere/src/i2c.h similarity index 100% rename from exosphere/i2c.h rename to exosphere/src/i2c.h diff --git a/exosphere/interrupt.c b/exosphere/src/interrupt.c similarity index 90% rename from exosphere/interrupt.c rename to exosphere/src/interrupt.c index 2bec9849c..fd4d1df0a 100644 --- a/exosphere/interrupt.c +++ b/exosphere/src/interrupt.c @@ -10,21 +10,22 @@ struct { void (*handler)(void); } g_registered_interrupts[MAX_REGISTERED_INTERRUPTS] = { {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL} }; -/* Prototypes for internal (private) functions. */ -unsigned int get_interrupt_id(void); - +static unsigned int get_interrupt_id(void) { + return 0; + /* TODO */ +} /* Initializes the GIC. TODO: This must be called during wakeup. */ void intr_initialize_gic(void) { /* Setup interrupts 0-0x1F as nonsecure with highest non-secure priority. */ GICD_IGROUPR[0] = 0xFFFFFFFF; for (unsigned int i = 0; i < 0x20; i++) { - GICD_IPRIORITYR[i] = GIC_PRI_HIGHEST; + GICD_IPRIORITYR[i] = GIC_PRI_HIGHEST_NONSECURE; } /* Setup the GICC. */ GICC_CTLR = 0x1D9; - GICC_PMR = GIC_PRI_HIGHEST; + GICC_PMR = GIC_PRI_HIGHEST_NONSECURE; GICC_BPR = 7; } @@ -50,7 +51,7 @@ void intr_set_cpu_mask(unsigned int id, uint8_t mask) { /* Sets an interrupt's edge/level bits in the GICD. */ void intr_set_edge_level(unsigned int id, int edge_level) { - GICD_ICFGR[id >> 4] = (GICD_ICFGR[id >> 4] & (~(3 << ((id & 0xF) << 1))) | (((edge_level & 1) << 1) << ((id & 0xF) << 1)); + GICD_ICFGR[id >> 4] = GICD_ICFGR[id >> 4] & ((~(3 << ((id & 0xF) << 1))) | (((edge_level & 1) << 1) << ((id & 0xF) << 1))); } /* Sets an interrupt's enabled status in the GICD. */ diff --git a/exosphere/interrupt.h b/exosphere/src/interrupt.h similarity index 100% rename from exosphere/interrupt.h rename to exosphere/src/interrupt.h diff --git a/exosphere/lock.h b/exosphere/src/lock.h similarity index 100% rename from exosphere/lock.h rename to exosphere/src/lock.h diff --git a/exosphere/masterkey.c b/exosphere/src/masterkey.c similarity index 100% rename from exosphere/masterkey.c rename to exosphere/src/masterkey.c diff --git a/exosphere/masterkey.h b/exosphere/src/masterkey.h similarity index 100% rename from exosphere/masterkey.h rename to exosphere/src/masterkey.h diff --git a/exosphere/mc.c b/exosphere/src/mc.c similarity index 100% rename from exosphere/mc.c rename to exosphere/src/mc.c diff --git a/exosphere/mc.h b/exosphere/src/mc.h similarity index 100% rename from exosphere/mc.h rename to exosphere/src/mc.h diff --git a/exosphere/memory_map.h b/exosphere/src/memory_map.h similarity index 91% rename from exosphere/memory_map.h rename to exosphere/src/memory_map.h index a0a05a8dc..1bb9dd964 100644 --- a/exosphere/memory_map.h +++ b/exosphere/src/memory_map.h @@ -108,7 +108,7 @@ static const struct { #define WARMBOOT_RAM_SEGMENT_ID_SE_STATE 0 #define WARMBOOT_RAM_SEGMENT_ID_TZRAM 1 -#define TZRAM_SEGMENT_ID_WARMBOOT_CRT0_MAIN_CODE 0 +#define TZRAM_SEGMENT_ID_WARMBOOT_CRT0_AND_MAIN 0 #define TZRAM_SEGMENT_ID_PK2LDR 1 #define TZRAM_SEGMENT_ID_USERPAGE 2 #define TZRAM_SEGMENT_ID_CORE012_STACK 3 @@ -119,12 +119,12 @@ static const struct { /**********************************************************************************************/ -static inline uintptr_t identity_map_all_mappings(uintptr_t *mmu_l1_tbl, uintptr_t *mmu_l3_tbl) { +static inline void identity_map_all_mappings(uintptr_t *mmu_l1_tbl, uintptr_t *mmu_l3_tbl) { static uint64_t base_attributes = MMU_PTE_BLOCK_INNER_SHAREBLE | ATTRIB_MEMTYPE_NORMAL; for(size_t i = 0; i < sizeof(g_identity_mappings) / sizeof(g_identity_mappings[0]); i++) { uint64_t attributes = base_attributes | g_identity_mappings[i].attributes; if(g_identity_mappings[i].is_block_range) { - mmu_map_block_range(mmu_l1_tbl, g_identity_mappings[i].address, g_identity_mappings[i].address, + mmu_map_block_range(1, mmu_l1_tbl, g_identity_mappings[i].address, g_identity_mappings[i].address, g_identity_mappings[i].size, attributes); } else { @@ -134,13 +134,13 @@ static inline uintptr_t identity_map_all_mappings(uintptr_t *mmu_l1_tbl, uintptr } } -static inline uintptr_t identity_unmap_all_mappings(uintptr_t *mmu_l1_tbl, uintptr_t *mmu_l3_tbl) { +static inline void identity_unmap_all_mappings(uintptr_t *mmu_l1_tbl, uintptr_t *mmu_l3_tbl) { for(size_t i = 0; i < sizeof(g_identity_mappings) / sizeof(g_identity_mappings[0]); i++) { if(g_identity_mappings[i].is_block_range) { - mmu_unmap_block_range(mmu_l1_tbl, g_identity_mappings[i].address, g_identity_mappings[i].size); + mmu_unmap_range(1, mmu_l1_tbl, g_identity_mappings[i].address, g_identity_mappings[i].size); } else { - mmu_unmap_page_range(mmu_l3_tbl, g_identity_mappings[i].address, g_identity_mappings[i].size); + mmu_unmap_range(3, mmu_l3_tbl, g_identity_mappings[i].address, g_identity_mappings[i].size); } } } @@ -198,7 +198,7 @@ static inline uintptr_t lp0_get_plaintext_ram_segment_pa(unsigned int segment_id #ifndef MEMORY_MAP_USE_IDENTIY_MAPPING static inline uintptr_t lp0_get_plaintext_ram_segment_address(unsigned int segment_id) { - return LP0_PLAINTEXT_RAM_SEGMENT_BASE + 0x10000 * segment_id; + return LP0_ENTRY_RAM_SEGMENT_BASE + 0x10000 * segment_id; } #else static inline uintptr_t lp0_get_plaintext_ram_segment_address(unsigned int segment_id) { @@ -209,7 +209,7 @@ static inline uintptr_t lp0_get_plaintext_ram_segment_address(unsigned int segme static inline void lp0_map_all_plaintext_ram_segments(uintptr_t *mmu_l3_tbl) { for(size_t i = 0, offset = 0; i < sizeof(g_lp0_entry_ram_segments) / sizeof(g_lp0_entry_ram_segments[0]); i++) { uint64_t attributes = MMU_PTE_BLOCK_XN | MMU_PTE_BLOCK_INNER_SHAREBLE | g_lp0_entry_ram_segments[i].attributes; - mmu_map_page_range(mmu_l3_tbl, LP0_PLAINTEXT_RAM_SEGMENT_BASE + offset, g_lp0_entry_ram_segments[i].pa, + mmu_map_page_range(mmu_l3_tbl, LP0_ENTRY_RAM_SEGMENT_BASE + offset, g_lp0_entry_ram_segments[i].pa, g_lp0_entry_ram_segments[i].size, attributes); offset += 0x10000; } @@ -217,7 +217,7 @@ static inline void lp0_map_all_plaintext_ram_segments(uintptr_t *mmu_l3_tbl) { static inline void lp0_unmap_all_plaintext_ram_segments(uintptr_t *mmu_l3_tbl) { for(size_t i = 0, offset = 0; i < sizeof(g_lp0_entry_ram_segments) / sizeof(g_lp0_entry_ram_segments[0]); i++) { - mmu_unmap_range(3, mmu_l3_tbl, LP0_PLAINTEXT_RAM_SEGMENT_BASE + offset, g_lp0_entry_ram_segments[i].size); + mmu_unmap_range(3, mmu_l3_tbl, LP0_ENTRY_RAM_SEGMENT_BASE + offset, g_lp0_entry_ram_segments[i].size); offset += 0x10000; } @@ -236,7 +236,7 @@ static inline uintptr_t lp0_get_ciphertext_ram_segment_address(unsigned int segm offset += g_warmboot_ram_segments[i].size; } - return LP0_CIPHERTEXT_RAM_SEGMENT_BASE + offset; + return WARMBOOT_RAM_SEGMENT_BASE + offset; } #else static inline uintptr_t lp0_get_ciphertext_ram_segment_address(unsigned int segment_id) { @@ -247,7 +247,7 @@ static inline uintptr_t lp0_get_ciphertext_ram_segment_address(unsigned int segm static inline void lp0_map_all_ciphertext_ram_segments(uintptr_t *mmu_l3_tbl) { for(size_t i = 0, offset = 0; i < sizeof(g_warmboot_ram_segments) / sizeof(g_warmboot_ram_segments[0]); i++) { uint64_t attributes = MMU_PTE_BLOCK_XN | MMU_PTE_BLOCK_INNER_SHAREBLE | g_warmboot_ram_segments[i].attributes; - mmu_map_page_range(mmu_l3_tbl, LP0_CIPHERTEXT_RAM_SEGMENT_BASE + offset, g_warmboot_ram_segments[i].pa, + mmu_map_page_range(mmu_l3_tbl, WARMBOOT_RAM_SEGMENT_BASE + offset, g_warmboot_ram_segments[i].pa, g_warmboot_ram_segments[i].size, attributes); offset += g_warmboot_ram_segments[i].size; } @@ -255,7 +255,7 @@ static inline void lp0_map_all_ciphertext_ram_segments(uintptr_t *mmu_l3_tbl) { static inline void lp0_unmap_all_ciphertext_ram_segments(uintptr_t *mmu_l3_tbl) { for(size_t i = 0, offset = 0; i < sizeof(g_warmboot_ram_segments) / sizeof(g_warmboot_ram_segments[0]); i++) { - mmu_unmap_range(3, mmu_l3_tbl, LP0_CIPHERTEXT_RAM_SEGMENT_BASE + offset, g_warmboot_ram_segments[i].size); + mmu_unmap_range(3, mmu_l3_tbl, WARMBOOT_RAM_SEGMENT_BASE + offset, g_warmboot_ram_segments[i].size); offset += g_warmboot_ram_segments[i].size; } diff --git a/exosphere/mmu.h b/exosphere/src/mmu.h similarity index 100% rename from exosphere/mmu.h rename to exosphere/src/mmu.h diff --git a/exosphere/package2.c b/exosphere/src/package2.c similarity index 99% rename from exosphere/package2.c rename to exosphere/src/package2.c index a96cfb299..7c96d1ee0 100644 --- a/exosphere/package2.c +++ b/exosphere/src/package2.c @@ -1,10 +1,9 @@ -#include -#include #include #include "utils.h" #include "memory_map.h" +#include "cpu_context.h" #include "package2.h" #include "configitem.h" #include "se.h" @@ -22,7 +21,7 @@ static void setup_se(void) { se_clear_interrupts(); /* Perform some sanity initialization. */ - security_engine_t *p_security_engine = get_security_engine_address(); + volatile security_engine_t *p_security_engine = get_security_engine_address(); p_security_engine->_0x4 = 0; p_security_engine->AES_KEY_READ_DISABLE_REG = 0; p_security_engine->RSA_KEY_READ_DISABLE_REG = 0; diff --git a/exosphere/package2.h b/exosphere/src/package2.h similarity index 100% rename from exosphere/package2.h rename to exosphere/src/package2.h diff --git a/exosphere/pmc.h b/exosphere/src/pmc.h similarity index 100% rename from exosphere/pmc.h rename to exosphere/src/pmc.h diff --git a/exosphere/randomcache.c b/exosphere/src/randomcache.c similarity index 94% rename from exosphere/randomcache.c rename to exosphere/src/randomcache.c index a941cd304..4d80a5f7a 100644 --- a/exosphere/randomcache.c +++ b/exosphere/src/randomcache.c @@ -4,21 +4,22 @@ #include "utils.h" #include "randomcache.h" #include "se.h" +#include "cache.h" /* TrustZone maintains a cache of random for the kernel. */ /* So that requests can still be serviced even when a */ /* usermode SMC is in progress. */ -volatile uint8_t g_random_cache[0x400]; -volatile unsigned int g_random_cache_low = 0; -volatile unsigned int g_random_cache_high = 0x3FF; +static uint8_t g_random_cache[0x400]; +static unsigned int g_random_cache_low = 0; +static unsigned int g_random_cache_high = 0x3FF; void randomcache_refill_segment(unsigned int offset, unsigned int size) { if (offset + size >= 0x400) { size = 0x400 - offset; } - + flush_dcache_range(&g_random_cache[offset], &g_random_cache[offset + size]); se_generate_random(KEYSLOT_SWITCH_RNGKEY, &g_random_cache[offset], size); flush_dcache_range(&g_random_cache[offset], &g_random_cache[offset + size]); @@ -69,4 +70,4 @@ void randomcache_getbytes(void *dst, size_t num_bytes) { } g_random_cache_low = new_low; -} \ No newline at end of file +} diff --git a/exosphere/randomcache.h b/exosphere/src/randomcache.h similarity index 100% rename from exosphere/randomcache.h rename to exosphere/src/randomcache.h diff --git a/exosphere/se.c b/exosphere/src/se.c similarity index 97% rename from exosphere/se.c rename to exosphere/src/se.c index afecd035c..d9caebf23 100644 --- a/exosphere/se.c +++ b/exosphere/src/se.c @@ -1,5 +1,3 @@ -#include -#include #include #include "utils.h" @@ -27,7 +25,7 @@ void ll_init(se_ll_t *ll, void *buffer, size_t size) { ll->num_entries = 0; /* 1 Entry. */ if (buffer != NULL) { - ll->addr_info.address = get_physical_address(buffer); + ll->addr_info.address = (uint32_t) get_physical_address(buffer); ll->addr_info.size = (uint32_t) size; } else { ll->addr_info.address = 0; @@ -37,11 +35,6 @@ void ll_init(se_ll_t *ll, void *buffer, size_t size) { flush_dcache_range((uint8_t *)ll, (uint8_t *)ll + sizeof(*ll)); } -/* Gets security engine pointer. */ -security_engine_t *get_security_engine_address(void) { - return SECURITY_ENGINE; -} - void set_security_engine_callback(unsigned int (*callback)(void)) { if (callback == NULL || g_se_callback != NULL) { generic_panic(); @@ -66,7 +59,7 @@ void se_check_for_error(void) { } } -void se_trigger_intrrupt(void) { +void se_trigger_interrupt(void) { intr_set_pending(INTERRUPT_ID_USER_SECURITY_ENGINE); } @@ -214,7 +207,7 @@ void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_sr SECURITY_ENGINE->CRYPTO_KEYTABLE_DST_REG = keyslot_dst << 8; flush_dcache_range(wrapped_key, (const uint8_t *)wrapped_key + wrapped_key_size); - trigger_se_aes_op(OP_START, NULL, 0, wrapped_key, wrapped_key_size); + /* TODO: trigger_se_aes_op(OP_START, NULL, 0, wrapped_key, wrapped_key_size); */ } void se_aes_crypt_insecure_internal(unsigned int keyslot, uint32_t out_ll_paddr, uint32_t in_ll_paddr, size_t size, unsigned int crypt_config, bool encrypt, unsigned int (*callback)(void)) { @@ -232,26 +225,26 @@ void se_aes_crypt_insecure_internal(unsigned int keyslot, uint32_t out_ll_paddr, } else { SECURITY_ENGINE->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY); } - + /* Setup Crypto register. */ SECURITY_ENGINE->CRYPTO_REG = crypt_config | (keyslot << 24) | (encrypt << 8); - + /* Mark this encryption as insecure -- this makes the SE not a secure busmaster. */ SECURITY_ENGINE->CRYPTO_REG |= 0x80000000; - + /* Appropriate number of blocks. */ SECURITY_ENGINE->BLOCK_COUNT_REG = (size >> 4) - 1; - + /* Set the callback, for after the async operation. */ set_security_engine_callback(callback); - + /* Enable SE Interrupt firing for async op. */ SECURITY_ENGINE->INT_ENABLE_REG = 0x10; - + /* Setup Input/Output lists */ SECURITY_ENGINE->IN_LL_ADDR_REG = in_ll_paddr; SECURITY_ENGINE->OUT_LL_ADDR_REG = out_ll_paddr; - + /* Set registers for operation. */ SECURITY_ENGINE->ERR_STATUS_REG = SECURITY_ENGINE->ERR_STATUS_REG; SECURITY_ENGINE->INT_STATUS_REG = SECURITY_ENGINE->INT_STATUS_REG; @@ -351,11 +344,11 @@ void se_get_exp_mod_output(void *buf, size_t size) { void trigger_se_rsa_op(void *buf, size_t size) { se_ll_t in_ll; - ll_init(&in_ll, buf, size); - + ll_init(&in_ll, (void *)buf, size); + /* Set the input LL. */ SECURITY_ENGINE->IN_LL_ADDR_REG = get_physical_address(&in_ll); - + /* Set registers for operation. */ SECURITY_ENGINE->ERR_STATUS_REG = SECURITY_ENGINE->ERR_STATUS_REG; SECURITY_ENGINE->INT_STATUS_REG = SECURITY_ENGINE->INT_STATUS_REG; @@ -369,7 +362,7 @@ void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const v se_ll_t in_ll; se_ll_t out_ll; - ll_init(&in_ll, src, src_size); + ll_init(&in_ll, (void *)src, src_size); ll_init(&out_ll, dst, dst_size); /* Set the LLs. */ @@ -434,7 +427,7 @@ void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const vo if (src_size < dst_size) { last_block_size = src_size - aligned_size; } - se_perform_aes_block_operation(dst + aligned_size, last_block_size, src + aligned_size, src - aligned_size); + se_perform_aes_block_operation(dst + aligned_size, last_block_size, (uint8_t *)src + aligned_size, src_size - aligned_size); } } diff --git a/exosphere/se.h b/exosphere/src/se.h similarity index 96% rename from exosphere/se.h rename to exosphere/src/se.h index 4b5faf594..3b0fe777c 100644 --- a/exosphere/se.h +++ b/exosphere/src/se.h @@ -4,6 +4,8 @@ #include #include +#include "memory_map.h" + /* Exosphere driver for the Tegra X1 security engine. */ #define KEYSLOT_SWITCH_PACKAGE2KEY 0x8 @@ -136,13 +138,16 @@ typedef struct { /* WIP, API subject to change. */ +static inline volatile security_engine_t *get_security_engine_address(void) { + return (volatile security_engine_t *)(mmio_get_device_address(MMIO_DEVID_SE)); +} + /* This function MUST be registered to fire on the appropriate interrupt. */ void se_operation_completed(void); -security_engine_t *get_security_engine_address(void); - void se_check_for_error(void); void se_trigger_interrupt(void); +void se_clear_interrupts(void); /* TODO */ void se_verify_flags_cleared(void); diff --git a/exosphere/sealedkeys.c b/exosphere/src/sealedkeys.c similarity index 100% rename from exosphere/sealedkeys.c rename to exosphere/src/sealedkeys.c diff --git a/exosphere/sealedkeys.h b/exosphere/src/sealedkeys.h similarity index 100% rename from exosphere/sealedkeys.h rename to exosphere/src/sealedkeys.h diff --git a/exosphere/smc_api.c b/exosphere/src/smc_api.c similarity index 90% rename from exosphere/smc_api.c rename to exosphere/src/smc_api.c index e22fbc8a4..f282d0dd9 100644 --- a/exosphere/smc_api.c +++ b/exosphere/src/smc_api.c @@ -113,7 +113,7 @@ uintptr_t get_smc_core012_stack_address(void) { return tzram_get_segment_address(TZRAM_SEGMENT_ID_CORE012_STACK) + 0x1000; } -uintptr_t get_exception_entry_core3_stack_address(unsigned int core_id) { +uintptr_t get_exception_entry_stack_address(unsigned int core_id) { /* For core3, this is also the smc stack */ if (core_id == 3) { return tzram_get_segment_address(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x1000; @@ -187,6 +187,7 @@ void call_smc_handler(uint32_t handler_id, smc_args_t *args) { /* Call function. */ args->X[0] = smc_handler(args); + (void)result; /* FIXME: result unused */ } uint32_t smc_wrapper_sync(smc_args_t *args, uint32_t (*handler)(smc_args_t *)) { @@ -256,17 +257,17 @@ uint32_t smc_get_result(smc_args_t *args) { uint32_t status; unsigned char result_buf[0x400]; upage_ref_t page_ref; - + void *user_address = (void *)args->X[2]; if (g_smc_callback_key == 0) { return 4; } - + if (args->X[1] != g_smc_callback_key) { return 5; } - + /* Check result size */ if (args->X[3] > 0x400) { return 2; @@ -274,7 +275,7 @@ uint32_t smc_get_result(smc_args_t *args) { args->X[1] = g_smc_callback(result_buf, args->X[3]); g_smc_callback_key = 0; - + /* Initialize page reference. */ if (upage_init(&page_ref, user_address) == 0) { return 2; @@ -284,8 +285,9 @@ uint32_t smc_get_result(smc_args_t *args) { if (secure_copy_to_user(&page_ref, user_address, result_buf, (size_t)args->X[3]) == 0) { return 2; } - + return 0; + (void)status; /* FIXME: status unused */ } uint32_t smc_exp_mod_get_result(void *buf, uint64_t size) { @@ -454,10 +456,16 @@ uint32_t smc_read_write_register(smc_args_t *args) { return 2; } /* Check for PMC registers. */ - if (0x7000E400ULL <= address && address <= 0x7000EFFFULL) { - const uint8_t pmc_whitelist[0x28] = {0xB9, 0xF9, 0x07, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0xC4, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00}; + if (0x7000E400 <= address && address <= 0x7000EFFF) { + const uint8_t pmc_whitelist[0x28] = { + 0xB9, 0xF9, 0x07, 0x00, 0x00, 0x00, 0x80, 0x03, + 0x00, 0x00, 0x00, 0x17, 0x00, 0xC4, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00 + }; /* Offset = Address - PMC_BASE */ - uint32_t offset = (uint32_t)(address - 0x7000E400ULL); + uint32_t offset = (uint32_t)(address - 0x7000E400); uint32_t wl_ind = (offset >> 5); /* If address is whitelisted, allow write. */ if (wl_ind < sizeof(pmc_whitelist) && (pmc_whitelist[wl_ind] & (1 << ((offset >> 2) & 0x7)))) { @@ -465,10 +473,25 @@ uint32_t smc_read_write_register(smc_args_t *args) { } else { return 2; } - } else if (mkey_get_revision() >= MASTERKEY_REVISION_400_CURRENT && devices[MMIO_DEVID_MC].pa <= address && address < devices[MMIO_DEVID_MC].pa + devices[MMIO_DEVID_MC].size) { + } else if (mkey_get_revision() >= MASTERKEY_REVISION_400_CURRENT && mmio_get_device_pa(MMIO_DEVID_MC) <= address && + address < mmio_get_device_pa(MMIO_DEVID_MC) + 0x1000) { /* Memory Controller RW supported only on 4.0.0+ */ - const uint8_t mc_whitelist[0x68] = {0x9F, 0x31, 0x30, 0x00, 0xF0, 0xFF, 0xF7, 0x01, 0xCD, 0xFE, 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x03, 0x40, 0x73, 0x3E, 0x2F, 0x00, 0x00, 0x6E, 0x30, 0x05, 0x06, 0xB0, 0x71, 0xC8, 0x43, 0x04, 0x80, 0x1F, 0x08, 0x80, 0x03, 0x00, 0x0E, 0x00, 0x08, 0x00, 0xE0, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xF0, 0x03, 0x03, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x40, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xFE, 0x0F, 0x01, 0x00, 0x80, 0x00, 0x00, 0x08, 0x00, 0x00}; - uint32_t offset = (uint32_t)(address - 0x70019000ULL); + const uint8_t mc_whitelist[0x68] = { + 0x9F, 0x31, 0x30, 0x00, 0xF0, 0xFF, 0xF7, 0x01, + 0xCD, 0xFE, 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x40, 0x73, 0x3E, 0x2F, 0x00, 0x00, 0x6E, + 0x30, 0x05, 0x06, 0xB0, 0x71, 0xC8, 0x43, 0x04, + 0x80, 0x1F, 0x08, 0x80, 0x03, 0x00, 0x0E, 0x00, + 0x08, 0x00, 0xE0, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0xF0, 0x03, 0x03, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xFE, 0x0F, + 0x01, 0x00, 0x80, 0x00, 0x00, 0x08, 0x00, 0x00 + }; + uint32_t offset = (uint32_t)(address - 0x70019000); uint32_t wl_ind = (offset >> 5); /* If address is whitelisted, allow write. */ if (wl_ind < sizeof(mc_whitelist) && (mc_whitelist[wl_ind] & (1 << ((offset >> 2) & 0x7)))) { @@ -531,3 +554,9 @@ uint32_t smc_configure_carveout(smc_args_t *args) { configured_carveouts[carveout_id] = true; return 0; } + +uint32_t smc_panic(smc_args_t *args) { + (void)args; + return 0; + /* TODO */ +} diff --git a/exosphere/smc_api.h b/exosphere/src/smc_api.h similarity index 85% rename from exosphere/smc_api.h rename to exosphere/src/smc_api.h index d006e654e..affc68359 100644 --- a/exosphere/smc_api.h +++ b/exosphere/src/smc_api.h @@ -14,7 +14,7 @@ void set_priv_smc_in_progress(void); void clear_priv_smc_in_progress(void); uintptr_t get_smc_core012_stack_address(void); -uintptr_t get_exception_entry_core3_stack_address(void); +uintptr_t get_exception_entry_stack_address(unsigned int core_id); void call_smc_handler(unsigned int handler_id, smc_args_t *args); diff --git a/exosphere/smc_user.c b/exosphere/src/smc_user.c similarity index 98% rename from exosphere/smc_user.c rename to exosphere/src/smc_user.c index 51cb1ddf8..512f438f9 100644 --- a/exosphere/smc_user.c +++ b/exosphere/src/smc_user.c @@ -10,16 +10,17 @@ #include "smc_api.h" #include "smc_user.h" #include "se.h" +#include "fuse.h" #include "sealedkeys.h" #include "userpage.h" #include "titlekey.h" /* Globals. */ -bool g_crypt_aes_done = false; -bool g_exp_mod_done = false; +static bool g_crypt_aes_done = false; +static bool g_exp_mod_done = false; -uint8_t g_secure_exp_mod_exponent[0x100]; -uint8_t g_rsa_oaep_exponent[0x100]; +static uint8_t g_secure_exp_mod_exponent[0x100]; +static uint8_t g_rsa_oaep_exponent[0x100]; void set_exp_mod_done(bool done) { @@ -598,18 +599,19 @@ uint32_t user_unwrap_aes_wrapped_titlekey(smc_args_t *args) { aes_wrapped_titlekey[0] = args->X[1]; aes_wrapped_titlekey[1] = args->X[2]; unsigned int master_key_rev = (unsigned int)args->X[3]; - - + + if (master_key_rev >= MASTERKEY_REVISION_MAX) { return 2; } - + tkey_set_master_key_rev(master_key_rev); - - + tkey_aes_unwrap(titlekey, 0x10, aes_wrapped_titlekey, 0x10); seal_titlekey(sealed_titlekey, 0x10, titlekey, 0x10); - + args->X[1] = sealed_titlekey[0]; args->X[2] = sealed_titlekey[1]; + + return 0; /* FIXME: what should we return there */ } diff --git a/exosphere/smc_user.h b/exosphere/src/smc_user.h similarity index 100% rename from exosphere/smc_user.h rename to exosphere/src/smc_user.h diff --git a/exosphere/start.s b/exosphere/src/start.s similarity index 93% rename from exosphere/start.s rename to exosphere/src/start.s index aee471a56..d1a611ecb 100644 --- a/exosphere/start.s +++ b/exosphere/src/start.s @@ -1,3 +1,5 @@ +/* For some reason GAS doesn't know about it, even with .cpu cortex-a57 */ +#define cpuactlr_el1 s3_1_c15_c2_0 .macro ERRATUM_INVALIDATE_BTB_AT_BOOT /* Nintendo copy-pasted https://github.com/ARM-software/arm-trusted-firmware/blob/master/plat/nvidia/tegra/common/aarch64/tegra_helpers.S#L312 */ /* @@ -36,7 +38,7 @@ /* if the OS lock is set, disable it and request a warm reset */ mrs x0, oslsr_el1 ands x0, x0, #2 - b.eq _set_lock_and_sp + b.eq 2f mov x0, xzr msr oslar_el1, x0 @@ -48,14 +50,14 @@ isb dsb sy /* Nintendo forgot to copy-paste the branch instruction below. */ - _reset_wfi: + 1: wfi - b _reset_wfi + b 1b .rept 65 nop /* guard against speculative excecution */ .endr - _set_lock_and_sp: + 2: /* set the OS lock */ mov x0, #1 msr oslar_el1, x0 @@ -122,7 +124,7 @@ __set_exception_entry_stack_pointer: /* If SPSel == 1 on entry, make sure your function doesn't use stack variables! */ mov x16, lr mrs x17, spsel - msr x0, mpidr_el1 + mrs x0, mpidr_el1 and w0, w0, #3 bl get_exception_entry_stack_address /* should be optimized so it doesn't make function calls */ msr spsel, #1 @@ -138,8 +140,8 @@ __jump_to_lower_el: /* x0: arg (context ID), x1: entrypoint, w2: exception level */ msr elr_el3, x1 - mov x1, #((0b1111 << 6) | 1) /* DAIF set and SP = SP_ELx*/ - orr x1, w2, lsl#2 + mov w1, #((0b1111 << 6) | 1) /* DAIF set and SP = SP_ELx*/ + orr w1, w2, w2, lsl#2 msr spsr_el3, x1 bl __set_exception_entry_stack_pointer diff --git a/exosphere/timers.c b/exosphere/src/timers.c similarity index 100% rename from exosphere/timers.c rename to exosphere/src/timers.c diff --git a/exosphere/timers.h b/exosphere/src/timers.h similarity index 100% rename from exosphere/timers.h rename to exosphere/src/timers.h diff --git a/exosphere/titlekey.c b/exosphere/src/titlekey.c similarity index 98% rename from exosphere/titlekey.c rename to exosphere/src/titlekey.c index 0873040ad..a55bd21fa 100644 --- a/exosphere/titlekey.c +++ b/exosphere/src/titlekey.c @@ -2,6 +2,7 @@ #include #include "utils.h" +#include "cache.h" #include "titlekey.h" #include "masterkey.h" @@ -49,8 +50,8 @@ void calculate_mgf1_and_xor(void *masked, size_t masked_size, const void *seed, hash_buf[seed_size + 2] = (uint8_t)((round >> 8) & 0xFF); hash_buf[seed_size + 3] = (uint8_t)((round >> 0) & 0xFF); round++; - - cache_flush(hash_buf, hash_buf + hash_buf_size); + + flush_dcache_range(hash_buf, hash_buf + hash_buf_size); se_calculate_sha256(cur_hash, hash_buf, hash_buf_size); for (unsigned int i = 0; i < cur_size; i++) { diff --git a/exosphere/titlekey.h b/exosphere/src/titlekey.h similarity index 100% rename from exosphere/titlekey.h rename to exosphere/src/titlekey.h diff --git a/exosphere/uart.c b/exosphere/src/uart.c similarity index 100% rename from exosphere/uart.c rename to exosphere/src/uart.c diff --git a/exosphere/uart.h b/exosphere/src/uart.h similarity index 100% rename from exosphere/uart.h rename to exosphere/src/uart.h diff --git a/exosphere/userpage.c b/exosphere/src/userpage.c similarity index 85% rename from exosphere/userpage.c rename to exosphere/src/userpage.c index a24d2d659..d767a3612 100644 --- a/exosphere/userpage.c +++ b/exosphere/src/userpage.c @@ -5,10 +5,10 @@ #include "memory_map.h" #include "cache.h" -static uintptr_t g_user_page_user_address = NULL; +static uintptr_t g_user_page_user_address = 0ULL; static inline uintptr_t get_page_for_address(void *address) { - return ((uintptr_t)(address)) & ~0xFFF; + return ((uintptr_t)(address)) & ~0xFFFULL; } /* Create a user page reference for the desired address. */ @@ -17,7 +17,7 @@ bool upage_init(upage_ref_t *upage, void *user_address) { upage->user_address = get_page_for_address(user_address); upage->secure_monitor_address = 0ULL; - if (g_user_page_user_address != NULL) { + if (g_user_page_user_address != 0ULL) { /* Different physical address indicate SPL was rebooted, or another process got access to svcCallSecureMonitor. Panic. */ if (g_user_page_user_address != upage->user_address) { generic_panic(); @@ -26,7 +26,8 @@ bool upage_init(upage_ref_t *upage, void *user_address) { } else { /* Weakly validate SPL's physically random address is in DRAM. */ if (upage->user_address >> 31) { - static const userpage_attributes = MMU_PTE_BLOCK_XN | MMU_PTE_BLOCK_INNER_SHAREBLE | MMU_PTE_BLOCK_NS | ATTRIB_MEMTYPE_NORMAL; + static const uint64_t userpage_attributes = MMU_PTE_BLOCK_XN | MMU_PTE_BLOCK_INNER_SHAREBLE | MMU_PTE_BLOCK_NS | ATTRIB_MEMTYPE_NORMAL; + uintptr_t *mmu_l3_tbl = (uintptr_t *)tzram_get_segment_address(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); g_user_page_user_address = upage->user_address; mmu_map_page(mmu_l3_tbl, USER_PAGE_SECURE_MONITOR_ADDR, upage->user_address, userpage_attributes); tlb_invalidate_page_inner_shareable((void *)USER_PAGE_SECURE_MONITOR_ADDR); diff --git a/exosphere/userpage.h b/exosphere/src/userpage.h similarity index 100% rename from exosphere/userpage.h rename to exosphere/src/userpage.h diff --git a/exosphere/src/utils.c b/exosphere/src/utils.c new file mode 100644 index 000000000..2a8bbadac --- /dev/null +++ b/exosphere/src/utils.c @@ -0,0 +1,18 @@ +#include "utils.h" + +void panic(uint32_t code) { + (void)code; /* TODO */ +} + +void generic_panic(void) { + /* TODO */ +} + +__attribute__((noinline)) bool overlaps(uint64_t as, uint64_t ae, uint64_t bs, uint64_t be) +{ + if(as <= bs && bs <= ae) + return true; + if(bs <= as && as <= be) + return true; + return false; +} diff --git a/exosphere/src/utils.h b/exosphere/src/utils.h new file mode 100644 index 000000000..c731d2743 --- /dev/null +++ b/exosphere/src/utils.h @@ -0,0 +1,44 @@ +#ifndef EXOSPHERE_UTILS_H +#define EXOSPHERE_UTILS_H + +#include +#include +#include + +#define BIT(x) (1u << (x)) +#define BITL(x) (1ull << (x)) + +void panic(uint32_t code); +void generic_panic(void); +bool overlaps(uint64_t as, uint64_t ae, uint64_t bs, uint64_t be); + +static inline uintptr_t get_physical_address(const void *vaddr) { + uintptr_t PAR; + __asm__ __volatile__ ("at s1e3r, %0" :: "r"(vaddr)); + __asm__ __volatile__ ("mrs %0, par_el1" : "=r"(PAR)); + return (PAR & 1) ? 0ULL : (PAR & 0x00000FFFFFFFF000ULL) | ((uintptr_t)vaddr & 0xFFF); +} + +static inline uint32_t read32le(const volatile void *dword, size_t offset) { + return *(uint32_t *)((uintptr_t)dword + offset); +} + +static inline uint32_t read32be(const volatile void *dword, size_t offset) { + return __builtin_bswap32(read32le(dword, offset)); +} + +static inline uint64_t read64le(const volatile void *qword, size_t offset) { + return *(uint64_t *)((uintptr_t)qword + offset); +} + +static inline unsigned int get_core_id(void) { + uint64_t core_id; + __asm__ __volatile__ ("mrs %0, mpidr_el1" : "=r"(core_id)); + return (unsigned int)core_id & 3; +} + +static inline bool check_32bit_additive_overflow(uint32_t a, uint32_t b) { + return __builtin_add_overflow_p(a, b, (uint32_t)0); +} + +#endif diff --git a/exosphere/warmboot_init.c b/exosphere/src/warmboot_init.c similarity index 85% rename from exosphere/warmboot_init.c rename to exosphere/src/warmboot_init.c index ae7dcdd05..e28005a47 100644 --- a/exosphere/warmboot_init.c +++ b/exosphere/src/warmboot_init.c @@ -11,6 +11,6 @@ void invalidate_icache_all_tzram_pa(void) { /* TODO */ } -uintptr_t get_coldboot_crt0_stack_address(void) { +uintptr_t get_warmboot_crt0_stack_address(void) { return tzram_get_segment_pa(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x800; } diff --git a/exosphere/warmboot_main.c b/exosphere/src/warmboot_main.c similarity index 100% rename from exosphere/warmboot_main.c rename to exosphere/src/warmboot_main.c diff --git a/exosphere/utils.h b/exosphere/utils.h deleted file mode 100644 index d7b471c4d..000000000 --- a/exosphere/utils.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef EXOSPHERE_UTILS_H -#define EXOSPHERE_UTILS_H - -#include -#include -#include - -#define BIT(x) (1u << (x)) -#define BITL(x) (1ull << (x)) - -void panic(uint32_t code); -void generic_panic(void); - -uint32_t get_physical_address(void *vaddr); - -static inline uint32_t read32le(const void *dword, size_t offset) { - return *(uint32_t *)((uintptr_t)dword + offset); -} - -static inline uint32_t read32be(const unsigned char *dword, size_t offset) { - return __builtin_bswap32(read32le(dword, offset)); -} - -static inline uint64_t read64le(const void *qword, size_t offset) { - return *(uint64_t *)((uintptr_t)dword + offset); -} - -static __attribute__((noinline)) bool check_32bit_additive_overflow(uint32_t a, uint32_t b) { - uint64_t x = (uint64_t)a + (uint64_t)b; - return x > (uint64_t)(UINT32_MAX); -} - -static __attribute__((noinline)) bool overlaps(uint64_t as, uint64_t ae, uint64_t bs, uint64_t be) -{ - if(as <= bs && bs <= ae) - return true; - if(bs <= as && as <= be) - return true; - return false; -} - - -static inline unsigned int get_core_id(void) { - uint64_t core_id; - __asm__ __volatile__ ("mrs %0, MPIDR_EL1" : "=r"(core_id)); - return (unsigned int)core_id & 3; -} - -#endif