#include #include #include "utils.h" #include "userpage.h" #include "memory_map.h" uint64_t g_secure_page_user_address = NULL; /* Create a user page reference for the desired address. */ /* Returns 1 on success, 0 on failure. */ bool upage_init(upage_ref_t *upage, void *user_address) { upage->user_page = get_page_for_address(user_address); upage->secure_page = 0ULL; if (g_secure_page_user_address != NULL) { /* Different physical address indicate SPL was rebooted, or another process got access to svcCallSecureMonitor. Panic. */ if (g_secure_page_user_address != upage->user_page) { generic_panic(); } upage->secure_page = SECURE_USER_PAGE_ADDR; } else { /* Weakly validate SPL's physically random address is in DRAM. */ if (upage->user_page >> 31) { g_secure_page_user_address = upage->user_page; mmu_map_page_range(mmu_l3_tbl, tzram_get_segment_address(TZRAM_SEGMENT_ID_USERPAGE), upage->user_page, 0x1000, MMU_PTE_BLOCK_XN | MMU_PTE_BLOCK_INNER_SHAREBLE | ATTRIB_MEMTYPE_NORMAL); /* TODO: Invalidate the TLB to make this page readable. */ upage->secure_page = SECURE_USER_PAGE_ADDR; } } return upage->secure_page != 0ULL; } bool user_copy_to_secure(upage_ref_t *upage, void *secure_dst, void *user_src, size_t size) { /* Fail if the page doesn't match. */ if (get_page_for_address(user_src) != upage->user_page) { return false; } /* Fail if we go past the page boundary. */ if (size != 0 && get_page_for_address(user_src + size - 1) != upage->user_page) { return false; } void *secure_src = (void *)(upage->secure_page + ((uint64_t)user_src - upage->user_page)); memcpy(secure_dst, secure_src, size); return true; } bool secure_copy_to_user(upage_ref_t *upage, void *user_dst, void *secure_src, size_t size) { /* Fail if the page doesn't match. */ if (get_page_for_address(user_dst) != upage->user_page) { return false; } /* Fail if we go past the page boundary. */ if (size != 0 && get_page_for_address(user_dst + size - 1) != upage->user_page) { return false; } void *secure_dst = (void *)(upage->secure_page + ((uint64_t)user_dst - upage->user_page)); memcpy(secure_dst, secure_src, size); return true; }