From f7598cb433d6daabc24b16ae089bf0d6a3edec19 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 23 Feb 2018 01:12:38 -0800 Subject: [PATCH] Implement smcConfigureCarveout --- exosphere/mc.c | 104 ++++++++++++++++++++++++++++++++++++++++++++ exosphere/mc.h | 40 +++++++++++++++++ exosphere/smc_api.c | 28 ++++++++++++ 3 files changed, 172 insertions(+) create mode 100644 exosphere/mc.c create mode 100644 exosphere/mc.h diff --git a/exosphere/mc.c b/exosphere/mc.c new file mode 100644 index 000000000..fe2233183 --- /dev/null +++ b/exosphere/mc.c @@ -0,0 +1,104 @@ +#include + +#include "mmu.h" +#include "mc.h" + +volatile security_carveout_t *get_carveout_by_id(unsigned int carveout) { + if (CARVEOUT_ID_MIN <= carveout <= CARVEOUT_ID_MAX) { + return (volatile security_carveout_t *)(MC_BASE + 0xC08ULL + 0x50 * (carveout - CARVEOUT_ID_MIN)); + } + panic(); + return NULL; + switch (carveout) { + case 4: /* Kernel carveout */ + return (volatile security_carveout_t *)(MC_BASE + 0xCF8ULL); + case 5: /* Unused Kernel carveout */ + return (volatile security_carveout_t *)(MC_BASE + 0xD48ULL); + default: + panic(); + return NULL; + } +} + +void configure_default_carveouts(void) { + /* Configure Carveout 1 (UNUSED) */ + volatile security_carveout_t *carveout = get_carveout_by_id(1); + carveout->paddr_low = 0; + carveout->paddr_high = 0; + carveout->size_big_pages = 0; + carveout->flags_0 = 0; + carveout->flags_1 = 0; + carveout->flags_2 = 0; + carveout->flags_3 = 0; + carveout->flags_4 = 0; + carveout->flags_5 = 0; + carveout->flags_6 = 0; + carveout->flags_7 = 0; + carveout->flags_8 = 0; + carveout->flags_9 = 0; + carveout->allowed_clients = 0x04000006; + + /* Configure Carveout 2 (GPU UCODE) */ + carveout = get_carveout_by_id(2); + carveout->paddr_low = 0x80020000; + carveout->paddr_high = 0; + carveout->size_big_pages = 2; /* 0x40000 */ + carveout->flags_0 = 0; + carveout->flags_1 = 0; + carveout->flags_2 = 0x3000000; + carveout->flags_3 = 0; + carveout->flags_4 = 0x300; + carveout->flags_5 = 0; + carveout->flags_6 = 0; + carveout->flags_7 = 0; + carveout->flags_8 = 0; + carveout->flags_9 = 0; + carveout->allowed_clients = 0x440167E; + + /* Configure Carveout 3 (UNUSED GPU) */ + carveout = get_carveout_by_id(3); + carveout->paddr_low = 0; + carveout->paddr_high = 0; + carveout->size_big_pages = 0; + carveout->flags_0 = 0; + carveout->flags_1 = 0; + carveout->flags_2 = 0x3000000; + carveout->flags_3 = 0; + carveout->flags_4 = 0x300; + carveout->flags_5 = 0; + carveout->flags_6 = 0; + carveout->flags_7 = 0; + carveout->flags_8 = 0; + carveout->flags_9 = 0; + carveout->allowed_clients = 0x4401E7E; + + /* Configure default Kernel carveouts based on 2.0.0+. */ + + /* Configure Carveout 4 (KERNEL_BUILTINS) */ + configure_kernel_carveout(5, 0x80060000, KERNEL_CARVEOUT_SIZE_MAX); + + /* Configure Carveout 5 (KERNEL_UNUSED) */ + configure_kernel_carveout(5, 0, 0); +} + +void configure_kernel_carveout(unsigned int carveout_id, uint64_t address, uint64_t size) { + if (carveout_id != 4 && carveout_id != 5) { + panic(); + } + + volatile security_carveout_t *carveout = get_carveout_by_id(carveout_id); + carveout->paddr_low = (uint32_t)(address & 0xFFFFFFFF); + carveout->paddr_high = (uint32_t)(address >> 32); + carveout->size_big_pages = (uint32_t)(size >> 17); + carveout->flags_0 = 0x70E3407F; + carveout->flags_1 = 0x1A620880; + carveout->flags_2 = 0x303C00; + carveout->flags_3 = 0xCF0830BB; + carveout->flags_4 = 0x3; + carveout->flags_5 = 0; + carveout->flags_6 = 0; + carveout->flags_7 = 0; + carveout->flags_8 = 0; + carveout->flags_9 = 0; + carveout->allowed_clients = 0x8B; +} diff --git a/exosphere/mc.h b/exosphere/mc.h new file mode 100644 index 000000000..908359d7a --- /dev/null +++ b/exosphere/mc.h @@ -0,0 +1,40 @@ +#ifndef EXOSPHERE_MC_H +#define EXOSPHERE_MC_H + +#include +#include "mmu.h" + +/* Exosphere driver for the Tegra X1 Memory Controller. */ + +#define MC_BASE (mmio_get_device_address(MMIO_DEVID_MC)) + +#define CARVEOUT_ID_MIN 1 +#define CARVEOUT_ID_MAX 5 + +#define KERNEL_CARVEOUT_SIZE_MAX 0x1FFE0000 + +typedef struct { + uint32_t allowed_clients; + uint32_t paddr_low; + uint32_t paddr_high; + uint32_t size_big_pages; + uint32_t flags_0; + uint32_t flags_1; + uint32_t flags_2; + uint32_t flags_3; + uint32_t flags_4; + uint32_t flags_5; + uint32_t flags_6; + uint32_t flags_7; + uint32_t flags_8; + uint32_t flags_9; + uint8_t padding[0x28]; +} security_carveout_t; + + +volatile security_carveout_t *get_carveout_by_id(unsigned int carveout); +void configure_default_carveouts(void); +void configure_kernel_carveout(unsigned int carveout_id, uint64_t address, uint64_t size); + + +#endif \ No newline at end of file diff --git a/exosphere/smc_api.c b/exosphere/smc_api.c index fdc6a8bee..e026b6c41 100644 --- a/exosphere/smc_api.c +++ b/exosphere/smc_api.c @@ -3,6 +3,8 @@ #include "utils.h" #include "configitem.h" #include "cpu_context.h" +#include "mc.h" +#include "mmu.h" #include "smc_api.h" #include "smc_user.h" #include "se.h" @@ -478,3 +480,29 @@ uint32_t smc_read_write_register(smc_args_t *args) { return 2; } + + +uint32_t smc_configure_carveout(smc_args_t *args) { + if (args->X[0] > 1) { + return 2; + } + + unsigned int carveout_id = (unsigned int)args->X[1]; + uint64_t address = args->X[2]; + uint64_t size = args->X[3]; + + /* Ensure carveout isn't too big. */ + if (size > KERNEL_CARVEOUT_SIZE_MAX) { + return 2; + } + + /* Configuration is one-shot, and cannot be done multiple times. */ + static bool configured_carveouts[2] = {false, false}; + if (configured_carveouts[carveout_id]) { + return 2; + } + + configure_kernel_carveout(carveout_id + 4, address, size); + configured_carveouts[carveout_id] = true; + return 0; +} \ No newline at end of file