mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
Move source files to src/, add Makefile, fix all build and linkage errors, etc.
This commit is contained in:
parent
4c7aa566f0
commit
b0ea9c1a0b
58 changed files with 385 additions and 203 deletions
71
exosphere/Makefile
Normal file
71
exosphere/Makefile
Normal 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) $<
|
|
@ -6,7 +6,7 @@ endif
|
||||||
|
|
||||||
include $(DEVKITARM)/base_tools
|
include $(DEVKITARM)/base_tools
|
||||||
|
|
||||||
name := $(shell basename $(CURDIR))
|
name := bpmpfw
|
||||||
|
|
||||||
dir_source := src
|
dir_source := src
|
||||||
dir_build := build
|
dir_build := build
|
||||||
|
|
BIN
exosphere/build/bpmpfw.bin
Normal file
BIN
exosphere/build/bpmpfw.bin
Normal file
Binary file not shown.
16
exosphere/linker.ld
Normal file
16
exosphere/linker.ld
Normal 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
BIN
exosphere/out/exosphere.bin
Normal file
Binary file not shown.
40
exosphere/src/bootconfig.c
Normal file
40
exosphere/src/bootconfig.c
Normal 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 */
|
||||||
|
}
|
|
@ -6,7 +6,7 @@
|
||||||
void tlb_invalidate_all(void);
|
void tlb_invalidate_all(void);
|
||||||
void tlb_invalidate_all_inner_shareable(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 tlb_invalidate_page_inner_shareable(const void *page);
|
||||||
|
|
||||||
void flush_dcache_all(void);
|
void flush_dcache_all(void);
|
|
@ -2,6 +2,7 @@
|
||||||
#include "mmu.h"
|
#include "mmu.h"
|
||||||
#include "memory_map.h"
|
#include "memory_map.h"
|
||||||
|
|
||||||
|
/*
|
||||||
extern void (*__preinit_array_start[])(void);
|
extern void (*__preinit_array_start[])(void);
|
||||||
extern void (*__preinit_array_end[])(void);
|
extern void (*__preinit_array_end[])(void);
|
||||||
extern void (*__init_array_start[])(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 __warmboot_crt0_start__[], __warmboot_crt0_end__[], __warmboot_crt0_lma__[];
|
||||||
extern uint8_t __main_start__[], __main_end__[], __main_lma__[];
|
extern uint8_t __main_start__[], __main_end__[], __main_lma__[];
|
||||||
extern uint8_t __pk2ldr_start__[], __pk2ldr_end__[], __pk2ldr_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 flush_dcache_all_tzram_pa(void);
|
||||||
extern void invalidate_icache_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);
|
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) {
|
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 = vma_is_pa ? tzram_get_segment_pa(segment_id) : tzram_get_segment_address(segment_id);
|
||||||
uintptr_t vma_offset = (uintptr_t)lma & 0xFFF;
|
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++)
|
for (size_t i = 0; i < __init_array_end - __init_array_start; i++)
|
||||||
__init_array_start[i]();
|
__init_array_start[i]();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
uintptr_t get_coldboot_crt0_stack_address(void) {
|
uintptr_t get_coldboot_crt0_stack_address(void) {
|
||||||
return tzram_get_segment_pa(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x800;
|
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) {
|
void coldboot_init(void) {
|
||||||
/* TODO: Set NX BOOTLOADER clock time field */
|
/* 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: set some mmio regs, etc. */
|
||||||
/* TODO: initialize DMA controllers */
|
/* TODO: initialize DMA controllers */
|
||||||
configure_ttbls();
|
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_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 */
|
/* TODO: set the MMU regs & tlbi & enable MMU */
|
||||||
|
|
||||||
flush_dcache_all_tzram_pa();
|
flush_dcache_all_tzram_pa();
|
||||||
invalidate_icache_all_tzram_pa();
|
invalidate_icache_all_tzram_pa();
|
||||||
/* TODO: zero-initialize the cpu context */
|
/* TODO: zero-initialize the cpu context */
|
||||||
/* Nintendo clears the (emtpy) pk2ldr's BSS section, but we embed it 0-filled in the binary */
|
/* 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 */
|
||||||
}
|
}
|
|
@ -2,10 +2,12 @@
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "mmu.h"
|
#include "mmu.h"
|
||||||
#include "memory_map.h"
|
#include "memory_map.h"
|
||||||
|
#include "cache.h"
|
||||||
|
|
||||||
|
/*
|
||||||
extern void (*__fini_array_start[])(void);
|
extern void (*__fini_array_start[])(void);
|
||||||
extern void (*__fini_array_end[])(void);
|
extern void (*__fini_array_end[])(void);
|
||||||
extern void _fini(void);
|
extern void _fini(void);*/
|
||||||
|
|
||||||
extern uint8_t __pk2ldr_start__[], __pk2ldr_end__[];
|
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);
|
void coldboot_main(void);
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* Needs to be called for EL3->EL3 chainloading (and only in that case). TODO: use it */
|
/* 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--)
|
for (size_t i = __fini_array_end - __fini_array_start; i > 0; i--)
|
||||||
__fini_array_start[i - 1]();
|
__fini_array_start[i - 1]();
|
||||||
_fini(); /* FIXME: do we have this gcc-provided symbol if we build with -nostartfiles? */
|
_fini(); /* FIXME: do we have this gcc-provided symbol if we build with -nostartfiles? */
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void coldboot_main(void) {
|
void coldboot_main(void) {
|
||||||
|
#if 0
|
||||||
uintptr_t *mmu_l3_table = (uintptr_t *)tzram_get_segment_address(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE);
|
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) */
|
/* Clear and unmap pk2ldr (which is reused as exception entry stacks) */
|
||||||
memset(pk2ldr, 0, __pk2ldr_end__ - __pk2ldr_start__);
|
memset((void *)pk2ldr, 0, __pk2ldr_end__ - __pk2ldr_start__);
|
||||||
mmu_unmap_range(mmu_l3_table, pk2ldr, __pk2ldr_end__ - __pk2ldr_start__);
|
mmu_unmap_range(3, mmu_l3_table, pk2ldr, __pk2ldr_end__ - __pk2ldr_start__);
|
||||||
tlb_invalidate_all_inner_shareable();
|
tlb_invalidate_all_inner_shareable();
|
||||||
|
#endif
|
||||||
|
|
||||||
/* TODO: stuff & jump to lower EL */
|
/* TODO: stuff & jump to lower EL */
|
||||||
}
|
}
|
|
@ -5,6 +5,7 @@
|
||||||
#include "interrupt.h"
|
#include "interrupt.h"
|
||||||
#include "package2.h"
|
#include "package2.h"
|
||||||
#include "se.h"
|
#include "se.h"
|
||||||
|
#include "fuse.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
int g_battery_profile = 0;
|
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;
|
g_battery_profile = ((int)(value != 0)) & 1;
|
||||||
|
return 0; /* FIXME: what should we return there */
|
||||||
}
|
}
|
||||||
|
|
||||||
bool configitem_is_recovery_boot(void) {
|
bool configitem_is_recovery_boot(void) {
|
|
@ -26,4 +26,4 @@ uint32_t configitem_get(enum ConfigItem item, uint64_t *p_outvalue);
|
||||||
bool configitem_is_recovery_boot(void);
|
bool configitem_is_recovery_boot(void);
|
||||||
bool configitem_is_retail(void);
|
bool configitem_is_retail(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -56,3 +56,15 @@ uint32_t cpu_on(uint32_t core, uint64_t entrypoint_addr, uint64_t context_id) {
|
||||||
return 0;
|
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 */
|
||||||
|
}
|
|
@ -47,8 +47,8 @@ typedef struct {
|
||||||
void set_core_entrypoint_and_context_id(uint32_t core, uint64_t entrypoint_addr, uint64_t context_id);
|
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_on(uint32_t core, uint64_t entrypoint_addr, uint64_t context_id);
|
||||||
uint32_t cpu_off(void);
|
uint32_t cpu_off(void); /* TODO */
|
||||||
uint32_t cpu_suspend(uint64_t power_state, uint64_t entrypoint_addr, uint64_t context_id);
|
uint32_t cpu_suspend(uint64_t power_state, uint64_t entrypoint_addr, uint64_t context_id); /* TODO */
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -50,9 +50,6 @@
|
||||||
.endif
|
.endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Actual Vectors for Exosphere. */
|
/* Actual Vectors for Exosphere. */
|
||||||
.global exosphere_vectors
|
.global exosphere_vectors
|
||||||
vector_base exosphere_vectors
|
vector_base exosphere_vectors
|
||||||
|
@ -69,32 +66,32 @@ vector_entry synch_sp0
|
||||||
|
|
||||||
vector_entry irq_sp0
|
vector_entry irq_sp0
|
||||||
b unknown_exception
|
b unknown_exception
|
||||||
check_vector irq_sp0
|
check_vector_size irq_sp0
|
||||||
|
|
||||||
vector_entry fiq_sp0
|
vector_entry fiq_sp0
|
||||||
b unknown_exception
|
b unknown_exception
|
||||||
check_vector fiq_sp0
|
check_vector_size fiq_sp0
|
||||||
|
|
||||||
vector_entry serror_sp0
|
vector_entry serror_sp0
|
||||||
b unknown_exception
|
b unknown_exception
|
||||||
check_vector serror_sp0
|
check_vector_size serror_sp0
|
||||||
|
|
||||||
/* Current EL, SPx */
|
/* Current EL, SPx */
|
||||||
vector_entry synch_spx
|
vector_entry synch_spx
|
||||||
b unknown_exception
|
b unknown_exception
|
||||||
check_vector synch_spx
|
check_vector_size synch_spx
|
||||||
|
|
||||||
vector_entry irq_spx
|
vector_entry irq_spx
|
||||||
b unknown_exception
|
b unknown_exception
|
||||||
check_vector irq_spx
|
check_vector_size irq_spx
|
||||||
|
|
||||||
vector_entry fiq_spx
|
vector_entry fiq_spx
|
||||||
b unknown_exception
|
b unknown_exception
|
||||||
check_vector fiq_spx
|
check_vector_size fiq_spx
|
||||||
|
|
||||||
vector_entry serror_spx
|
vector_entry serror_spx
|
||||||
b unknown_exception
|
b unknown_exception
|
||||||
check_vector serror_spx
|
check_vector_size serror_spx
|
||||||
|
|
||||||
/* Lower EL, A64 */
|
/* Lower EL, A64 */
|
||||||
vector_entry synch_a64
|
vector_entry synch_a64
|
||||||
|
@ -108,22 +105,22 @@ vector_entry synch_a64
|
||||||
/* Call appropriate handler. */
|
/* Call appropriate handler. */
|
||||||
stp x29, x30, [sp, #-0x10]!
|
stp x29, x30, [sp, #-0x10]!
|
||||||
mrs x29, mpidr_el1
|
mrs x29, mpidr_el1
|
||||||
and x29, x39, #0x3
|
and x29, x29, #0x3
|
||||||
cmp x29, #0x3
|
cmp x29, #0x3
|
||||||
b.ne handle_core012_smc_exception
|
b.ne handle_core012_smc_exception
|
||||||
bl handle_core3_smc_exception
|
bl handle_core3_smc_exception
|
||||||
ldp x29, x30, [sp],#0x10
|
ldp x29, x30, [sp],#0x10
|
||||||
eret
|
eret
|
||||||
check_vector synch_a64
|
check_vector_size synch_a64
|
||||||
|
|
||||||
vector_entry irq_a64
|
vector_entry irq_a64
|
||||||
b unknown_exception
|
b unknown_exception
|
||||||
check_vector irq_a64
|
check_vector_size irq_a64
|
||||||
|
|
||||||
vector_entry fiq_a64
|
vector_entry fiq_a64
|
||||||
stp x29, x30, [sp, #-0x10]!
|
stp x29, x30, [sp, #-0x10]!
|
||||||
mrs x29, mpidr_el1
|
mrs x29, mpidr_el1
|
||||||
and x29, x39, #0x3
|
and x29, x29, #0x3
|
||||||
cmp x29, #0x3
|
cmp x29, #0x3
|
||||||
b.ne unknown_exception
|
b.ne unknown_exception
|
||||||
stp x28, x29, [sp, #-0x10]!
|
stp x28, x29, [sp, #-0x10]!
|
||||||
|
@ -133,7 +130,7 @@ vector_entry fiq_a64
|
||||||
ldp x28, x29, [sp],#0x10
|
ldp x28, x29, [sp],#0x10
|
||||||
ldp x29, x30, [sp],#0x10
|
ldp x29, x30, [sp],#0x10
|
||||||
eret
|
eret
|
||||||
check_vector fiq_a64
|
check_vector_size fiq_a64
|
||||||
|
|
||||||
vector_entry serror_a64
|
vector_entry serror_a64
|
||||||
b unknown_exception
|
b unknown_exception
|
||||||
|
@ -171,18 +168,15 @@ handle_core012_smc_exception:
|
||||||
ldp x6, x7, [sp],#0x10
|
ldp x6, x7, [sp],#0x10
|
||||||
ldp x29, x30, [sp],#0x10
|
ldp x29, x30, [sp],#0x10
|
||||||
eret
|
eret
|
||||||
.if (. - serror_a64) > (32 * 4)
|
|
||||||
.error "Vector exceeds 32 instructions"
|
|
||||||
.endif
|
|
||||||
|
|
||||||
/* Lower EL, A32 */
|
/* Lower EL, A32 */
|
||||||
vector_entry synch_a32
|
vector_entry synch_a32
|
||||||
b unknown_exception
|
b unknown_exception
|
||||||
check_vector synch_a32
|
check_vector_size synch_a32
|
||||||
|
|
||||||
vector_entry irq_a32
|
vector_entry irq_a32
|
||||||
b unknown_exception
|
b unknown_exception
|
||||||
check_vector irq_a32
|
check_vector_size irq_a32
|
||||||
|
|
||||||
vector_entry fiq_a32
|
vector_entry fiq_a32
|
||||||
b fiq_a64
|
b fiq_a64
|
||||||
|
@ -222,9 +216,6 @@ handle_fiq_exception:
|
||||||
ldp x24, x25, [sp],#0x10
|
ldp x24, x25, [sp],#0x10
|
||||||
ldp x29, x30, [sp],#0x10
|
ldp x29, x30, [sp],#0x10
|
||||||
ret
|
ret
|
||||||
.if (. - fiq_a32) > (32 * 4)
|
|
||||||
.error "Vector exceeds 32 instructions"
|
|
||||||
.endif
|
|
||||||
|
|
||||||
vector_entry serror_a32
|
vector_entry serror_a32
|
||||||
b unknown_exception
|
b unknown_exception
|
||||||
|
@ -260,6 +251,3 @@ handle_core3_smc_exception:
|
||||||
ldp x16, x17, [sp],#0x10
|
ldp x16, x17, [sp],#0x10
|
||||||
ldp x18, x19, [sp],#0x10
|
ldp x18, x19, [sp],#0x10
|
||||||
ret
|
ret
|
||||||
.if (. - serror_a32) > (32 * 4)
|
|
||||||
.error "Vector exceeds 32 instructions"
|
|
||||||
.endif
|
|
|
@ -1,5 +1,3 @@
|
||||||
#include <stbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "fuse.h"
|
#include "fuse.h"
|
||||||
|
@ -17,7 +15,7 @@ void fuse_wait_idle(void);
|
||||||
void fuse_init(void)
|
void fuse_init(void)
|
||||||
{
|
{
|
||||||
fuse_make_regs_visible();
|
fuse_make_regs_visible();
|
||||||
|
|
||||||
/* TODO: Overrides (iROM patches) and various reads happen here */
|
/* TODO: Overrides (iROM patches) and various reads happen here */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +23,7 @@ void fuse_init(void)
|
||||||
void fuse_make_regs_visible(void)
|
void fuse_make_regs_visible(void)
|
||||||
{
|
{
|
||||||
/* TODO: Replace this with a proper CLKRST driver */
|
/* 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;
|
uint32_t misc_clk_val = *misc_clk_reg;
|
||||||
*misc_clk_reg = (misc_clk_val | (1 << 28));
|
*misc_clk_reg = (misc_clk_val | (1 << 28));
|
||||||
}
|
}
|
||||||
|
@ -48,7 +46,7 @@ void fuse_disable_power(void)
|
||||||
void fuse_wait_idle(void)
|
void fuse_wait_idle(void)
|
||||||
{
|
{
|
||||||
uint32_t ctrl_val = 0;
|
uint32_t ctrl_val = 0;
|
||||||
|
|
||||||
/* Wait for STATE_IDLE */
|
/* Wait for STATE_IDLE */
|
||||||
while ((ctrl_val & (0xF0000)) != 0x40000)
|
while ((ctrl_val & (0xF0000)) != 0x40000)
|
||||||
{
|
{
|
||||||
|
@ -61,36 +59,36 @@ void fuse_wait_idle(void)
|
||||||
uint32_t fuse_hw_read(uint32_t addr)
|
uint32_t fuse_hw_read(uint32_t addr)
|
||||||
{
|
{
|
||||||
fuse_wait_idle();
|
fuse_wait_idle();
|
||||||
|
|
||||||
/* Program the target address */
|
/* Program the target address */
|
||||||
FUSE_REGS->FUSE_REG_ADDR = addr;
|
FUSE_REGS->FUSE_REG_ADDR = addr;
|
||||||
|
|
||||||
/* Enable read operation in control register */
|
/* Enable read operation in control register */
|
||||||
uint32_t ctrl_val = FUSE_REGS->FUSE_CTRL;
|
uint32_t ctrl_val = FUSE_REGS->FUSE_CTRL;
|
||||||
ctrl_val &= ~0x3;
|
ctrl_val &= ~0x3;
|
||||||
ctrl_val |= 0x1; /* Set FUSE_READ command */
|
ctrl_val |= 0x1; /* Set FUSE_READ command */
|
||||||
FUSE_REGS->FUSE_CTRL = ctrl_val;
|
FUSE_REGS->FUSE_CTRL = ctrl_val;
|
||||||
|
|
||||||
fuse_wait_idle();
|
fuse_wait_idle();
|
||||||
|
|
||||||
return FUSE_REGS->FUSE_REG_READ;
|
return FUSE_REGS->FUSE_REG_READ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write a fuse in the hardware array */
|
/* 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();
|
fuse_wait_idle();
|
||||||
|
|
||||||
/* Program the target address and value */
|
/* Program the target address and value */
|
||||||
FUSE_REGS->FUSE_REG_ADDR = addr;
|
FUSE_REGS->FUSE_REG_ADDR = addr;
|
||||||
FUSE_REGS->FUSE_REG_WRITE = value;
|
FUSE_REGS->FUSE_REG_WRITE = value;
|
||||||
|
|
||||||
/* Enable write operation in control register */
|
/* Enable write operation in control register */
|
||||||
uint32_t ctrl_val = FUSE_REGS->FUSE_CTRL;
|
uint32_t ctrl_val = FUSE_REGS->FUSE_CTRL;
|
||||||
ctrl_val &= ~0x3;
|
ctrl_val &= ~0x3;
|
||||||
ctrl_val |= 0x2; /* Set FUSE_WRITE command */
|
ctrl_val |= 0x2; /* Set FUSE_WRITE command */
|
||||||
FUSE_REGS->FUSE_CTRL = ctrl_val;
|
FUSE_REGS->FUSE_CTRL = ctrl_val;
|
||||||
|
|
||||||
fuse_wait_idle();
|
fuse_wait_idle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,13 +96,13 @@ void fuse_hw_write(uint32_t, value, uint32_t addr)
|
||||||
void fuse_hw_sense(void)
|
void fuse_hw_sense(void)
|
||||||
{
|
{
|
||||||
fuse_wait_idle();
|
fuse_wait_idle();
|
||||||
|
|
||||||
/* Enable sense operation in control register */
|
/* Enable sense operation in control register */
|
||||||
uint32_t ctrl_val = FUSE_REGS->FUSE_CTRL;
|
uint32_t ctrl_val = FUSE_REGS->FUSE_CTRL;
|
||||||
ctrl_val &= ~0x3;
|
ctrl_val &= ~0x3;
|
||||||
ctrl_val |= 0x3; /* Set FUSE_SENSE command */
|
ctrl_val |= 0x3; /* Set FUSE_SENSE command */
|
||||||
FUSE_REGS->FUSE_CTRL = ctrl_val;
|
FUSE_REGS->FUSE_CTRL = ctrl_val;
|
||||||
|
|
||||||
fuse_wait_idle();
|
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 fuse_get_spare_bit(uint32_t idx)
|
||||||
{
|
{
|
||||||
uint32_t spare_bit_val = 0;
|
uint32_t spare_bit_val = 0;
|
||||||
|
|
||||||
if ((idx >= 0) && (idx < 32))
|
if ((idx >= 0) && (idx < 32))
|
||||||
spare_bit_val = FUSE_CHIP_REGS->FUSE_SPARE_BIT[idx];
|
spare_bit_val = FUSE_CHIP_REGS->FUSE_SPARE_BIT[idx];
|
||||||
|
|
||||||
return spare_bit_val;
|
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. */
|
/* Derive the 16-byte Hardware Info using values in the shadow cache, and copy to output buffer. */
|
||||||
void fuse_get_hardware_info(void *dst) {
|
void fuse_get_hardware_info(void *dst) {
|
||||||
uint32_t hw_info[0x4];
|
uint32_t hw_info[0x4];
|
||||||
|
|
||||||
uint32_t unk_hw_fuse = FUSE_CHIP_REGS->_0x120 & 0x3F;
|
uint32_t unk_hw_fuse = FUSE_CHIP_REGS->_0x120 & 0x3F;
|
||||||
uint32_t y_coord = FUSE_CHIP_REGS->FUSE_Y_COORDINATE & 0x1FF;
|
uint32_t y_coord = FUSE_CHIP_REGS->FUSE_Y_COORDINATE & 0x1FF;
|
||||||
uint32_t x_coord = FUSE_CHIP_REGS->FUSE_X_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[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[2] = (uint32_t)((fab_code << 26) | (lot_code_0 >> 6));
|
||||||
hw_info[3] = (uint32_t)(vendor_code);
|
hw_info[3] = (uint32_t)(vendor_code);
|
||||||
|
|
||||||
memcpy(dst, hw_info, 0x10);
|
memcpy(dst, hw_info, 0x10);
|
||||||
}
|
}
|
|
@ -174,7 +174,7 @@ typedef struct {
|
||||||
void fuse_init(void);
|
void fuse_init(void);
|
||||||
|
|
||||||
uint32_t fuse_hw_read(uint32_t addr);
|
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_hw_sense(void);
|
||||||
void fuse_disable_programming(void);
|
void fuse_disable_programming(void);
|
||||||
void fuse_secondary_private_key_disable(void);
|
void fuse_secondary_private_key_disable(void);
|
|
@ -1,5 +1,3 @@
|
||||||
#include <stbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "i2c.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;
|
uint32_t val = r;
|
||||||
if (src_size <= 3) {
|
if (src_size <= 3) {
|
||||||
memcpy(((uint8_t *)&val) + 1, src, src_size);
|
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 {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
|
@ -10,21 +10,22 @@ struct {
|
||||||
void (*handler)(void);
|
void (*handler)(void);
|
||||||
} g_registered_interrupts[MAX_REGISTERED_INTERRUPTS] = { {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL} };
|
} g_registered_interrupts[MAX_REGISTERED_INTERRUPTS] = { {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL} };
|
||||||
|
|
||||||
/* Prototypes for internal (private) functions. */
|
static unsigned int get_interrupt_id(void) {
|
||||||
unsigned int get_interrupt_id(void);
|
return 0;
|
||||||
|
/* TODO */
|
||||||
|
}
|
||||||
|
|
||||||
/* Initializes the GIC. TODO: This must be called during wakeup. */
|
/* Initializes the GIC. TODO: This must be called during wakeup. */
|
||||||
void intr_initialize_gic(void) {
|
void intr_initialize_gic(void) {
|
||||||
/* Setup interrupts 0-0x1F as nonsecure with highest non-secure priority. */
|
/* Setup interrupts 0-0x1F as nonsecure with highest non-secure priority. */
|
||||||
GICD_IGROUPR[0] = 0xFFFFFFFF;
|
GICD_IGROUPR[0] = 0xFFFFFFFF;
|
||||||
for (unsigned int i = 0; i < 0x20; i++) {
|
for (unsigned int i = 0; i < 0x20; i++) {
|
||||||
GICD_IPRIORITYR[i] = GIC_PRI_HIGHEST;
|
GICD_IPRIORITYR[i] = GIC_PRI_HIGHEST_NONSECURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Setup the GICC. */
|
/* Setup the GICC. */
|
||||||
GICC_CTLR = 0x1D9;
|
GICC_CTLR = 0x1D9;
|
||||||
GICC_PMR = GIC_PRI_HIGHEST;
|
GICC_PMR = GIC_PRI_HIGHEST_NONSECURE;
|
||||||
GICC_BPR = 7;
|
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. */
|
/* Sets an interrupt's edge/level bits in the GICD. */
|
||||||
void intr_set_edge_level(unsigned int id, int edge_level) {
|
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. */
|
/* Sets an interrupt's enabled status in the GICD. */
|
|
@ -108,7 +108,7 @@ static const struct {
|
||||||
#define WARMBOOT_RAM_SEGMENT_ID_SE_STATE 0
|
#define WARMBOOT_RAM_SEGMENT_ID_SE_STATE 0
|
||||||
#define WARMBOOT_RAM_SEGMENT_ID_TZRAM 1
|
#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_PK2LDR 1
|
||||||
#define TZRAM_SEGMENT_ID_USERPAGE 2
|
#define TZRAM_SEGMENT_ID_USERPAGE 2
|
||||||
#define TZRAM_SEGMENT_ID_CORE012_STACK 3
|
#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;
|
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++) {
|
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;
|
uint64_t attributes = base_attributes | g_identity_mappings[i].attributes;
|
||||||
if(g_identity_mappings[i].is_block_range) {
|
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);
|
g_identity_mappings[i].size, attributes);
|
||||||
}
|
}
|
||||||
else {
|
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++) {
|
for(size_t i = 0; i < sizeof(g_identity_mappings) / sizeof(g_identity_mappings[0]); i++) {
|
||||||
if(g_identity_mappings[i].is_block_range) {
|
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 {
|
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
|
#ifndef MEMORY_MAP_USE_IDENTIY_MAPPING
|
||||||
static inline uintptr_t lp0_get_plaintext_ram_segment_address(unsigned int segment_id) {
|
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
|
#else
|
||||||
static inline uintptr_t lp0_get_plaintext_ram_segment_address(unsigned int segment_id) {
|
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) {
|
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++) {
|
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;
|
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);
|
g_lp0_entry_ram_segments[i].size, attributes);
|
||||||
offset += 0x10000;
|
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) {
|
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++) {
|
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;
|
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;
|
offset += g_warmboot_ram_segments[i].size;
|
||||||
}
|
}
|
||||||
|
|
||||||
return LP0_CIPHERTEXT_RAM_SEGMENT_BASE + offset;
|
return WARMBOOT_RAM_SEGMENT_BASE + offset;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static inline uintptr_t lp0_get_ciphertext_ram_segment_address(unsigned int segment_id) {
|
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) {
|
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++) {
|
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;
|
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);
|
g_warmboot_ram_segments[i].size, attributes);
|
||||||
offset += g_warmboot_ram_segments[i].size;
|
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) {
|
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++) {
|
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;
|
offset += g_warmboot_ram_segments[i].size;
|
||||||
}
|
}
|
|
@ -1,10 +1,9 @@
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "memory_map.h"
|
#include "memory_map.h"
|
||||||
|
|
||||||
|
#include "cpu_context.h"
|
||||||
#include "package2.h"
|
#include "package2.h"
|
||||||
#include "configitem.h"
|
#include "configitem.h"
|
||||||
#include "se.h"
|
#include "se.h"
|
||||||
|
@ -22,7 +21,7 @@ static void setup_se(void) {
|
||||||
se_clear_interrupts();
|
se_clear_interrupts();
|
||||||
|
|
||||||
/* Perform some sanity initialization. */
|
/* 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->_0x4 = 0;
|
||||||
p_security_engine->AES_KEY_READ_DISABLE_REG = 0;
|
p_security_engine->AES_KEY_READ_DISABLE_REG = 0;
|
||||||
p_security_engine->RSA_KEY_READ_DISABLE_REG = 0;
|
p_security_engine->RSA_KEY_READ_DISABLE_REG = 0;
|
|
@ -4,21 +4,22 @@
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "randomcache.h"
|
#include "randomcache.h"
|
||||||
#include "se.h"
|
#include "se.h"
|
||||||
|
#include "cache.h"
|
||||||
|
|
||||||
/* TrustZone maintains a cache of random for the kernel. */
|
/* TrustZone maintains a cache of random for the kernel. */
|
||||||
/* So that requests can still be serviced even when a */
|
/* So that requests can still be serviced even when a */
|
||||||
/* usermode SMC is in progress. */
|
/* usermode SMC is in progress. */
|
||||||
|
|
||||||
volatile uint8_t g_random_cache[0x400];
|
static uint8_t g_random_cache[0x400];
|
||||||
volatile unsigned int g_random_cache_low = 0;
|
static unsigned int g_random_cache_low = 0;
|
||||||
volatile unsigned int g_random_cache_high = 0x3FF;
|
static unsigned int g_random_cache_high = 0x3FF;
|
||||||
|
|
||||||
|
|
||||||
void randomcache_refill_segment(unsigned int offset, unsigned int size) {
|
void randomcache_refill_segment(unsigned int offset, unsigned int size) {
|
||||||
if (offset + size >= 0x400) {
|
if (offset + size >= 0x400) {
|
||||||
size = 0x400 - offset;
|
size = 0x400 - offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
flush_dcache_range(&g_random_cache[offset], &g_random_cache[offset + size]);
|
flush_dcache_range(&g_random_cache[offset], &g_random_cache[offset + size]);
|
||||||
se_generate_random(KEYSLOT_SWITCH_RNGKEY, &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]);
|
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;
|
g_random_cache_low = new_low;
|
||||||
}
|
}
|
|
@ -1,5 +1,3 @@
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "utils.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. */
|
ll->num_entries = 0; /* 1 Entry. */
|
||||||
|
|
||||||
if (buffer != NULL) {
|
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;
|
ll->addr_info.size = (uint32_t) size;
|
||||||
} else {
|
} else {
|
||||||
ll->addr_info.address = 0;
|
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));
|
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)) {
|
void set_security_engine_callback(unsigned int (*callback)(void)) {
|
||||||
if (callback == NULL || g_se_callback != NULL) {
|
if (callback == NULL || g_se_callback != NULL) {
|
||||||
generic_panic();
|
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);
|
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;
|
SECURITY_ENGINE->CRYPTO_KEYTABLE_DST_REG = keyslot_dst << 8;
|
||||||
|
|
||||||
flush_dcache_range(wrapped_key, (const uint8_t *)wrapped_key + wrapped_key_size);
|
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)) {
|
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 {
|
} else {
|
||||||
SECURITY_ENGINE->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY);
|
SECURITY_ENGINE->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Setup Crypto register. */
|
/* Setup Crypto register. */
|
||||||
SECURITY_ENGINE->CRYPTO_REG = crypt_config | (keyslot << 24) | (encrypt << 8);
|
SECURITY_ENGINE->CRYPTO_REG = crypt_config | (keyslot << 24) | (encrypt << 8);
|
||||||
|
|
||||||
/* Mark this encryption as insecure -- this makes the SE not a secure busmaster. */
|
/* Mark this encryption as insecure -- this makes the SE not a secure busmaster. */
|
||||||
SECURITY_ENGINE->CRYPTO_REG |= 0x80000000;
|
SECURITY_ENGINE->CRYPTO_REG |= 0x80000000;
|
||||||
|
|
||||||
/* Appropriate number of blocks. */
|
/* Appropriate number of blocks. */
|
||||||
SECURITY_ENGINE->BLOCK_COUNT_REG = (size >> 4) - 1;
|
SECURITY_ENGINE->BLOCK_COUNT_REG = (size >> 4) - 1;
|
||||||
|
|
||||||
/* Set the callback, for after the async operation. */
|
/* Set the callback, for after the async operation. */
|
||||||
set_security_engine_callback(callback);
|
set_security_engine_callback(callback);
|
||||||
|
|
||||||
/* Enable SE Interrupt firing for async op. */
|
/* Enable SE Interrupt firing for async op. */
|
||||||
SECURITY_ENGINE->INT_ENABLE_REG = 0x10;
|
SECURITY_ENGINE->INT_ENABLE_REG = 0x10;
|
||||||
|
|
||||||
/* Setup Input/Output lists */
|
/* Setup Input/Output lists */
|
||||||
SECURITY_ENGINE->IN_LL_ADDR_REG = in_ll_paddr;
|
SECURITY_ENGINE->IN_LL_ADDR_REG = in_ll_paddr;
|
||||||
SECURITY_ENGINE->OUT_LL_ADDR_REG = out_ll_paddr;
|
SECURITY_ENGINE->OUT_LL_ADDR_REG = out_ll_paddr;
|
||||||
|
|
||||||
/* Set registers for operation. */
|
/* Set registers for operation. */
|
||||||
SECURITY_ENGINE->ERR_STATUS_REG = SECURITY_ENGINE->ERR_STATUS_REG;
|
SECURITY_ENGINE->ERR_STATUS_REG = SECURITY_ENGINE->ERR_STATUS_REG;
|
||||||
SECURITY_ENGINE->INT_STATUS_REG = SECURITY_ENGINE->INT_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) {
|
void trigger_se_rsa_op(void *buf, size_t size) {
|
||||||
se_ll_t in_ll;
|
se_ll_t in_ll;
|
||||||
ll_init(&in_ll, buf, size);
|
ll_init(&in_ll, (void *)buf, size);
|
||||||
|
|
||||||
/* Set the input LL. */
|
/* Set the input LL. */
|
||||||
SECURITY_ENGINE->IN_LL_ADDR_REG = get_physical_address(&in_ll);
|
SECURITY_ENGINE->IN_LL_ADDR_REG = get_physical_address(&in_ll);
|
||||||
|
|
||||||
/* Set registers for operation. */
|
/* Set registers for operation. */
|
||||||
SECURITY_ENGINE->ERR_STATUS_REG = SECURITY_ENGINE->ERR_STATUS_REG;
|
SECURITY_ENGINE->ERR_STATUS_REG = SECURITY_ENGINE->ERR_STATUS_REG;
|
||||||
SECURITY_ENGINE->INT_STATUS_REG = SECURITY_ENGINE->INT_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 in_ll;
|
||||||
se_ll_t out_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);
|
ll_init(&out_ll, dst, dst_size);
|
||||||
|
|
||||||
/* Set the LLs. */
|
/* 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) {
|
if (src_size < dst_size) {
|
||||||
last_block_size = src_size - aligned_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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "memory_map.h"
|
||||||
|
|
||||||
/* Exosphere driver for the Tegra X1 security engine. */
|
/* Exosphere driver for the Tegra X1 security engine. */
|
||||||
|
|
||||||
#define KEYSLOT_SWITCH_PACKAGE2KEY 0x8
|
#define KEYSLOT_SWITCH_PACKAGE2KEY 0x8
|
||||||
|
@ -136,13 +138,16 @@ typedef struct {
|
||||||
/* WIP, API subject to change. */
|
/* 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. */
|
/* This function MUST be registered to fire on the appropriate interrupt. */
|
||||||
void se_operation_completed(void);
|
void se_operation_completed(void);
|
||||||
|
|
||||||
security_engine_t *get_security_engine_address(void);
|
|
||||||
|
|
||||||
void se_check_for_error(void);
|
void se_check_for_error(void);
|
||||||
void se_trigger_interrupt(void);
|
void se_trigger_interrupt(void);
|
||||||
|
void se_clear_interrupts(void); /* TODO */
|
||||||
|
|
||||||
void se_verify_flags_cleared(void);
|
void se_verify_flags_cleared(void);
|
||||||
|
|
|
@ -113,7 +113,7 @@ uintptr_t get_smc_core012_stack_address(void) {
|
||||||
return tzram_get_segment_address(TZRAM_SEGMENT_ID_CORE012_STACK) + 0x1000;
|
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 */
|
/* For core3, this is also the smc stack */
|
||||||
if (core_id == 3) {
|
if (core_id == 3) {
|
||||||
return tzram_get_segment_address(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x1000;
|
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. */
|
/* Call function. */
|
||||||
args->X[0] = smc_handler(args);
|
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 *)) {
|
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;
|
uint32_t status;
|
||||||
unsigned char result_buf[0x400];
|
unsigned char result_buf[0x400];
|
||||||
upage_ref_t page_ref;
|
upage_ref_t page_ref;
|
||||||
|
|
||||||
void *user_address = (void *)args->X[2];
|
void *user_address = (void *)args->X[2];
|
||||||
|
|
||||||
if (g_smc_callback_key == 0) {
|
if (g_smc_callback_key == 0) {
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args->X[1] != g_smc_callback_key) {
|
if (args->X[1] != g_smc_callback_key) {
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check result size */
|
/* Check result size */
|
||||||
if (args->X[3] > 0x400) {
|
if (args->X[3] > 0x400) {
|
||||||
return 2;
|
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]);
|
args->X[1] = g_smc_callback(result_buf, args->X[3]);
|
||||||
g_smc_callback_key = 0;
|
g_smc_callback_key = 0;
|
||||||
|
|
||||||
/* Initialize page reference. */
|
/* Initialize page reference. */
|
||||||
if (upage_init(&page_ref, user_address) == 0) {
|
if (upage_init(&page_ref, user_address) == 0) {
|
||||||
return 2;
|
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) {
|
if (secure_copy_to_user(&page_ref, user_address, result_buf, (size_t)args->X[3]) == 0) {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
(void)status; /* FIXME: status unused */
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t smc_exp_mod_get_result(void *buf, uint64_t size) {
|
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;
|
return 2;
|
||||||
}
|
}
|
||||||
/* Check for PMC registers. */
|
/* Check for PMC registers. */
|
||||||
if (0x7000E400ULL <= address && address <= 0x7000EFFFULL) {
|
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};
|
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 */
|
/* Offset = Address - PMC_BASE */
|
||||||
uint32_t offset = (uint32_t)(address - 0x7000E400ULL);
|
uint32_t offset = (uint32_t)(address - 0x7000E400);
|
||||||
uint32_t wl_ind = (offset >> 5);
|
uint32_t wl_ind = (offset >> 5);
|
||||||
/* If address is whitelisted, allow write. */
|
/* If address is whitelisted, allow write. */
|
||||||
if (wl_ind < sizeof(pmc_whitelist) && (pmc_whitelist[wl_ind] & (1 << ((offset >> 2) & 0x7)))) {
|
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 {
|
} else {
|
||||||
return 2;
|
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+ */
|
/* 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};
|
const uint8_t mc_whitelist[0x68] = {
|
||||||
uint32_t offset = (uint32_t)(address - 0x70019000ULL);
|
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);
|
uint32_t wl_ind = (offset >> 5);
|
||||||
/* If address is whitelisted, allow write. */
|
/* If address is whitelisted, allow write. */
|
||||||
if (wl_ind < sizeof(mc_whitelist) && (mc_whitelist[wl_ind] & (1 << ((offset >> 2) & 0x7)))) {
|
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;
|
configured_carveouts[carveout_id] = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t smc_panic(smc_args_t *args) {
|
||||||
|
(void)args;
|
||||||
|
return 0;
|
||||||
|
/* TODO */
|
||||||
|
}
|
|
@ -14,7 +14,7 @@ void set_priv_smc_in_progress(void);
|
||||||
void clear_priv_smc_in_progress(void);
|
void clear_priv_smc_in_progress(void);
|
||||||
|
|
||||||
uintptr_t get_smc_core012_stack_address(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);
|
void call_smc_handler(unsigned int handler_id, smc_args_t *args);
|
||||||
|
|
|
@ -10,16 +10,17 @@
|
||||||
#include "smc_api.h"
|
#include "smc_api.h"
|
||||||
#include "smc_user.h"
|
#include "smc_user.h"
|
||||||
#include "se.h"
|
#include "se.h"
|
||||||
|
#include "fuse.h"
|
||||||
#include "sealedkeys.h"
|
#include "sealedkeys.h"
|
||||||
#include "userpage.h"
|
#include "userpage.h"
|
||||||
#include "titlekey.h"
|
#include "titlekey.h"
|
||||||
|
|
||||||
/* Globals. */
|
/* Globals. */
|
||||||
bool g_crypt_aes_done = false;
|
static bool g_crypt_aes_done = false;
|
||||||
bool g_exp_mod_done = false;
|
static bool g_exp_mod_done = false;
|
||||||
|
|
||||||
uint8_t g_secure_exp_mod_exponent[0x100];
|
static uint8_t g_secure_exp_mod_exponent[0x100];
|
||||||
uint8_t g_rsa_oaep_exponent[0x100];
|
static uint8_t g_rsa_oaep_exponent[0x100];
|
||||||
|
|
||||||
|
|
||||||
void set_exp_mod_done(bool done) {
|
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[0] = args->X[1];
|
||||||
aes_wrapped_titlekey[1] = args->X[2];
|
aes_wrapped_titlekey[1] = args->X[2];
|
||||||
unsigned int master_key_rev = (unsigned int)args->X[3];
|
unsigned int master_key_rev = (unsigned int)args->X[3];
|
||||||
|
|
||||||
|
|
||||||
if (master_key_rev >= MASTERKEY_REVISION_MAX) {
|
if (master_key_rev >= MASTERKEY_REVISION_MAX) {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
tkey_set_master_key_rev(master_key_rev);
|
tkey_set_master_key_rev(master_key_rev);
|
||||||
|
|
||||||
|
|
||||||
tkey_aes_unwrap(titlekey, 0x10, aes_wrapped_titlekey, 0x10);
|
tkey_aes_unwrap(titlekey, 0x10, aes_wrapped_titlekey, 0x10);
|
||||||
seal_titlekey(sealed_titlekey, 0x10, titlekey, 0x10);
|
seal_titlekey(sealed_titlekey, 0x10, titlekey, 0x10);
|
||||||
|
|
||||||
args->X[1] = sealed_titlekey[0];
|
args->X[1] = sealed_titlekey[0];
|
||||||
args->X[2] = sealed_titlekey[1];
|
args->X[2] = sealed_titlekey[1];
|
||||||
|
|
||||||
|
return 0; /* FIXME: what should we return there */
|
||||||
}
|
}
|
|
@ -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
|
.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 */
|
/* 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 */
|
/* if the OS lock is set, disable it and request a warm reset */
|
||||||
mrs x0, oslsr_el1
|
mrs x0, oslsr_el1
|
||||||
ands x0, x0, #2
|
ands x0, x0, #2
|
||||||
b.eq _set_lock_and_sp
|
b.eq 2f
|
||||||
mov x0, xzr
|
mov x0, xzr
|
||||||
msr oslar_el1, x0
|
msr oslar_el1, x0
|
||||||
|
|
||||||
|
@ -48,14 +50,14 @@
|
||||||
isb
|
isb
|
||||||
dsb sy
|
dsb sy
|
||||||
/* Nintendo forgot to copy-paste the branch instruction below. */
|
/* Nintendo forgot to copy-paste the branch instruction below. */
|
||||||
_reset_wfi:
|
1:
|
||||||
wfi
|
wfi
|
||||||
b _reset_wfi
|
b 1b
|
||||||
.rept 65
|
.rept 65
|
||||||
nop /* guard against speculative excecution */
|
nop /* guard against speculative excecution */
|
||||||
.endr
|
.endr
|
||||||
|
|
||||||
_set_lock_and_sp:
|
2:
|
||||||
/* set the OS lock */
|
/* set the OS lock */
|
||||||
mov x0, #1
|
mov x0, #1
|
||||||
msr oslar_el1, x0
|
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! */
|
/* If SPSel == 1 on entry, make sure your function doesn't use stack variables! */
|
||||||
mov x16, lr
|
mov x16, lr
|
||||||
mrs x17, spsel
|
mrs x17, spsel
|
||||||
msr x0, mpidr_el1
|
mrs x0, mpidr_el1
|
||||||
and w0, w0, #3
|
and w0, w0, #3
|
||||||
bl get_exception_entry_stack_address /* should be optimized so it doesn't make function calls */
|
bl get_exception_entry_stack_address /* should be optimized so it doesn't make function calls */
|
||||||
msr spsel, #1
|
msr spsel, #1
|
||||||
|
@ -138,8 +140,8 @@ __jump_to_lower_el:
|
||||||
/* x0: arg (context ID), x1: entrypoint, w2: exception level */
|
/* x0: arg (context ID), x1: entrypoint, w2: exception level */
|
||||||
msr elr_el3, x1
|
msr elr_el3, x1
|
||||||
|
|
||||||
mov x1, #((0b1111 << 6) | 1) /* DAIF set and SP = SP_ELx*/
|
mov w1, #((0b1111 << 6) | 1) /* DAIF set and SP = SP_ELx*/
|
||||||
orr x1, w2, lsl#2
|
orr w1, w2, w2, lsl#2
|
||||||
msr spsr_el3, x1
|
msr spsr_el3, x1
|
||||||
|
|
||||||
bl __set_exception_entry_stack_pointer
|
bl __set_exception_entry_stack_pointer
|
|
@ -2,6 +2,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "cache.h"
|
||||||
|
|
||||||
#include "titlekey.h"
|
#include "titlekey.h"
|
||||||
#include "masterkey.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 + 2] = (uint8_t)((round >> 8) & 0xFF);
|
||||||
hash_buf[seed_size + 3] = (uint8_t)((round >> 0) & 0xFF);
|
hash_buf[seed_size + 3] = (uint8_t)((round >> 0) & 0xFF);
|
||||||
round++;
|
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);
|
se_calculate_sha256(cur_hash, hash_buf, hash_buf_size);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < cur_size; i++) {
|
for (unsigned int i = 0; i < cur_size; i++) {
|
|
@ -5,10 +5,10 @@
|
||||||
#include "memory_map.h"
|
#include "memory_map.h"
|
||||||
#include "cache.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) {
|
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. */
|
/* 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->user_address = get_page_for_address(user_address);
|
||||||
upage->secure_monitor_address = 0ULL;
|
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. */
|
/* Different physical address indicate SPL was rebooted, or another process got access to svcCallSecureMonitor. Panic. */
|
||||||
if (g_user_page_user_address != upage->user_address) {
|
if (g_user_page_user_address != upage->user_address) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
|
@ -26,7 +26,8 @@ bool upage_init(upage_ref_t *upage, void *user_address) {
|
||||||
} else {
|
} else {
|
||||||
/* Weakly validate SPL's physically random address is in DRAM. */
|
/* Weakly validate SPL's physically random address is in DRAM. */
|
||||||
if (upage->user_address >> 31) {
|
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;
|
g_user_page_user_address = upage->user_address;
|
||||||
mmu_map_page(mmu_l3_tbl, USER_PAGE_SECURE_MONITOR_ADDR, upage->user_address, userpage_attributes);
|
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);
|
tlb_invalidate_page_inner_shareable((void *)USER_PAGE_SECURE_MONITOR_ADDR);
|
18
exosphere/src/utils.c
Normal file
18
exosphere/src/utils.c
Normal 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
44
exosphere/src/utils.h
Normal 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
|
|
@ -11,6 +11,6 @@ void invalidate_icache_all_tzram_pa(void) {
|
||||||
/* TODO */
|
/* 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;
|
return tzram_get_segment_pa(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x800;
|
||||||
}
|
}
|
|
@ -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
|
|
Loading…
Reference in a new issue