Move source files to src/, add Makefile, fix all build and linkage errors, etc.

This commit is contained in:
TuxSH 2018-02-25 20:00:50 +01:00
parent 4c7aa566f0
commit b0ea9c1a0b
58 changed files with 385 additions and 203 deletions

71
exosphere/Makefile Normal file
View file

@ -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=<path to>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) $<

View file

@ -6,7 +6,7 @@ endif
include $(DEVKITARM)/base_tools
name := $(shell basename $(CURDIR))
name := bpmpfw
dir_source := src
dir_build := build

BIN
exosphere/build/bpmpfw.bin Normal file

Binary file not shown.

16
exosphere/linker.ld Normal file
View file

@ -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(.);
}

BIN
exosphere/out/exosphere.bin Normal file

Binary file not shown.

View file

@ -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 */
}

View file

@ -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);

View file

@ -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 */
}

View file

@ -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 */
}

View file

@ -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) {

View file

@ -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 */
}

View file

@ -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

View file

@ -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

View file

@ -1,5 +1,3 @@
#include <stbool.h>
#include <stdint.h>
#include <string.h>
#include "fuse.h"
@ -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));
}
@ -77,7 +75,7 @@ uint32_t fuse_hw_read(uint32_t addr)
}
/* 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();

View file

@ -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);

View file

@ -1,5 +1,3 @@
#include <stbool.h>
#include <stdint.h>
#include <string.h>
#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;
}

View file

@ -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. */

View file

@ -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;
}

View file

@ -1,10 +1,9 @@
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#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;

View file

@ -4,14 +4,15 @@
#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) {

View file

@ -1,5 +1,3 @@
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#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)) {
@ -351,7 +344,7 @@ 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);
@ -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);
}
}

View file

@ -4,6 +4,8 @@
#include <stdint.h>
#include <stddef.h>
#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);

View file

@ -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 *)) {
@ -286,6 +287,7 @@ uint32_t smc_get_result(smc_args_t *args) {
}
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 */
}

View file

@ -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);

View file

@ -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) {
@ -606,10 +607,11 @@ uint32_t user_unwrap_aes_wrapped_titlekey(smc_args_t *args) {
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 */
}

View file

@ -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

View file

@ -2,6 +2,7 @@
#include <string.h>
#include "utils.h"
#include "cache.h"
#include "titlekey.h"
#include "masterkey.h"
@ -50,7 +51,7 @@ void calculate_mgf1_and_xor(void *masked, size_t masked_size, const void *seed,
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++) {

View file

@ -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);

18
exosphere/src/utils.c Normal file
View file

@ -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;
}

44
exosphere/src/utils.h Normal file
View file

@ -0,0 +1,44 @@
#ifndef EXOSPHERE_UTILS_H
#define EXOSPHERE_UTILS_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#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

View file

@ -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;
}

View file

@ -1,49 +0,0 @@
#ifndef EXOSPHERE_UTILS_H
#define EXOSPHERE_UTILS_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#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