mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-05-30 14:35:17 -04:00
Merge branch 'master' into emunand_dev
This commit is contained in:
commit
a9afbd2458
123 changed files with 6022 additions and 1386 deletions
|
@ -41,6 +41,8 @@ static const char *get_error_desc_str(uint32_t error_desc) {
|
|||
return "SError";
|
||||
case 0x301:
|
||||
return "Bad SVC";
|
||||
case 0xFFE:
|
||||
return "std::abort() called";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
|
@ -48,7 +50,8 @@ static const char *get_error_desc_str(uint32_t error_desc) {
|
|||
|
||||
static void _check_and_display_atmosphere_fatal_error(void) {
|
||||
/* Check for valid magic. */
|
||||
if (ATMOSPHERE_FATAL_ERROR_CONTEXT->magic != ATMOSPHERE_REBOOT_TO_FATAL_MAGIC) {
|
||||
if (ATMOSPHERE_FATAL_ERROR_CONTEXT->magic != ATMOSPHERE_REBOOT_TO_FATAL_MAGIC &&
|
||||
ATMOSPHERE_FATAL_ERROR_CONTEXT->magic != ATMOSPHERE_REBOOT_TO_FATAL_MAGIC_0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,10 @@
|
|||
|
||||
#define PANIC_CODE_SAFEMODE 0x00000020
|
||||
|
||||
|
||||
#define AMS_FATAL_ERROR_MAX_STACKTRACE 0x20
|
||||
#define AMS_FATAL_ERROR_MAX_STACKDUMP 0x100
|
||||
|
||||
/* Atmosphere reboot-to-fatal-error. */
|
||||
typedef struct {
|
||||
uint32_t magic;
|
||||
|
@ -43,17 +47,23 @@ typedef struct {
|
|||
};
|
||||
};
|
||||
uint64_t pc;
|
||||
uint64_t padding;
|
||||
uint64_t module_base;
|
||||
uint32_t pstate;
|
||||
uint32_t afsr0;
|
||||
uint32_t afsr1;
|
||||
uint32_t esr;
|
||||
uint64_t far;
|
||||
uint64_t report_identifier; /* Normally just system tick. */
|
||||
uint64_t stack_trace_size;
|
||||
uint64_t stack_dump_size;
|
||||
uint64_t stack_trace[AMS_FATAL_ERROR_MAX_STACKTRACE];
|
||||
uint8_t stack_dump[AMS_FATAL_ERROR_MAX_STACKDUMP];
|
||||
} atmosphere_fatal_error_ctx;
|
||||
|
||||
/* "AFE1" */
|
||||
#define ATMOSPHERE_REBOOT_TO_FATAL_MAGIC 0x31454641
|
||||
/* "AFE0" */
|
||||
#define ATMOSPHERE_REBOOT_TO_FATAL_MAGIC 0x30454641
|
||||
#define ATMOSPHERE_REBOOT_TO_FATAL_MAGIC_0 0x30454641
|
||||
|
||||
#define ATMOSPHERE_FATAL_ERROR_CONTEXT ((volatile atmosphere_fatal_error_ctx *)(0x4003E000))
|
||||
|
||||
|
|
|
@ -1202,6 +1202,9 @@ void sdmmc_finish(sdmmc_t *sdmmc)
|
|||
|
||||
/* Power cycle for 100ms without power. */
|
||||
mdelay(100);
|
||||
|
||||
/* Disable the regulator. */
|
||||
max77620_regulator_enable(REGULATOR_LDO2, 0);
|
||||
}
|
||||
|
||||
/* Force a register read to refresh the clock control value. */
|
||||
|
|
|
@ -84,7 +84,7 @@ ifneq ($(BUILD),$(notdir $(CURDIR)))
|
|||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
export TOPDIR := $(CURDIR)
|
||||
|
||||
export KIPDIRS := $(AMS)/stratosphere/loader $(AMS)/stratosphere/pm $(AMS)/stratosphere/sm $(AMS)/stratosphere/boot $(AMS)/stratosphere/ams_mitm
|
||||
export KIPDIRS := $(AMS)/stratosphere/loader $(AMS)/stratosphere/pm $(AMS)/stratosphere/sm $(AMS)/stratosphere/boot $(AMS)/stratosphere/spl $(AMS)/stratosphere/ams_mitm
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
|
||||
$(AMS)/exosphere $(AMS)/exosphere/lp0fw $(AMS)/exosphere/rebootstub \
|
||||
|
@ -96,7 +96,7 @@ export DEPSDIR := $(CURDIR)/$(BUILD)
|
|||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
KIPFILES := loader.kip pm.kip sm.kip ams_mitm.kip boot_100.kip boot_200.kip
|
||||
KIPFILES := loader.kip pm.kip sm.kip ams_mitm.kip spl.kip boot_100.kip boot_200.kip
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) fusee-primary.bin \
|
||||
exosphere.bin lp0fw.bin rebootstub.bin thermosphere.bin splash_screen.bmp \
|
||||
sept-primary.bin sept-secondary.enc \
|
||||
|
|
|
@ -242,6 +242,8 @@ SECTIONS
|
|||
PROVIDE(__sept_secondary_enc_size__ = sept_secondary_enc_end - sept_secondary_enc);
|
||||
PROVIDE(__sm_kip_start__ = sm_kip - __start__);
|
||||
PROVIDE(__sm_kip_size__ = sm_kip_end - sm_kip);
|
||||
PROVIDE(__spl_kip_start__ = spl_kip - __start__);
|
||||
PROVIDE(__spl_kip_size__ = spl_kip_end - spl_kip);
|
||||
PROVIDE(__splash_screen_bmp_start__ = splash_screen_bmp - __start__);
|
||||
PROVIDE(__splash_screen_bmp_size__ = splash_screen_bmp_end - splash_screen_bmp);
|
||||
PROVIDE(__thermosphere_bin_start__ = thermosphere_bin - __start__);
|
||||
|
|
|
@ -41,6 +41,10 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
uint8_t hash[0x20]; /* TODO: Come up with a better way to identify kernels, that doesn't rely on hashing them. */
|
||||
size_t hash_offset; /* Start hashing at offset N, if this is set. */
|
||||
size_t hash_size; /* Only hash the first N bytes of the kernel, if this is set. */
|
||||
size_t embedded_ini_offset; /* 8.0.0+ embeds the INI in kernel section. */
|
||||
size_t embedded_ini_ptr; /* 8.0.0+ embeds the INI in kernel section. */
|
||||
size_t free_code_space_offset;
|
||||
unsigned int num_patches;
|
||||
const kernel_patch_t *patches;
|
||||
|
@ -366,11 +370,67 @@ static const instruction_t MAKE_KERNEL_PATCH_NAME(700, proc_id_send)[] = {0xA9BF
|
|||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(700, proc_id_recv)[] = {0x68, 0x03, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0xE0, 0x03, 0x1B, 0xAA, 0x00, 0x01, 0x3F, 0xD6, 0xA9, 0x83, 0x50, 0xF8, 0xE8, 0x03, 0x16, 0x2A, 0xD6, 0x0A, 0x00, 0x11};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(700, proc_id_recv)[] = {0xA9BF2FEA, 0xF9404FEB, 0x2A1603EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400368, 0xF9401D08, 0xAA1B03E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
|
||||
|
||||
/*
|
||||
stp x10, x11, [sp, #-0x10]!
|
||||
ldr x11, [sp, #0x70]
|
||||
mov w10, w25
|
||||
lsl x10, x10, #2
|
||||
ldr x10, [x11, x10]
|
||||
mov x9, #0x0000ffffffffffff
|
||||
and x8, x10, x9
|
||||
mov x9, #0xffff000000000000
|
||||
and x10, x10, x9
|
||||
mov x9, #0xfffe000000000000
|
||||
cmp x10, x9
|
||||
beq #0x20
|
||||
|
||||
stp x8, x9, [sp, #-0x10]!
|
||||
ldr x8, [x21]
|
||||
ldr x8, [x8, #0x38]
|
||||
mov x0, x21
|
||||
blr x8
|
||||
ldp x8, x9, [sp],#0x10
|
||||
mov x8, x0
|
||||
|
||||
ldp x10, x11, [sp],#0x10
|
||||
mov x0, x8
|
||||
*/
|
||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(800, proc_id_send)[] = {0xA8, 0x02, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0xE0, 0x03, 0x15, 0xAA, 0x00, 0x01, 0x3F, 0xD6, 0xE8, 0x03, 0x19, 0x2A, 0x39, 0x0B, 0x00, 0x11, 0x08, 0xF5, 0x7E, 0xD3};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(800, proc_id_send)[] = {0xA9BF2FEA, 0xF9403BEB, 0x2A1903EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF94002A8, 0xF9401D08, 0xAA1503E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
|
||||
/*
|
||||
stp x10, x11, [sp, #-0x10]!
|
||||
ldr x11, [sp, #0x98]
|
||||
mov w10, w22
|
||||
lsl x10, x10, #2
|
||||
ldr x10, [x11, x10]
|
||||
mov x9, #0x0000ffffffffffff
|
||||
and x8, x10, x9
|
||||
mov x9, #0xffff000000000000
|
||||
and x10, x10, x9
|
||||
mov x9, #0xfffe000000000000
|
||||
cmp x10, x9
|
||||
beq #0x20
|
||||
|
||||
stp x8, x9, [sp, #-0x10]!
|
||||
ldr x8, [x27]
|
||||
ldr x8, [x8, #0x38]
|
||||
mov x0, x27
|
||||
blr x8
|
||||
ldp x8, x9, [sp],#0x10
|
||||
mov x8, x0
|
||||
|
||||
ldp x10, x11, [sp],#0x10
|
||||
mov x0, x8
|
||||
*/
|
||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(800, proc_id_recv)[] = {0x68, 0x03, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0xE0, 0x03, 0x1B, 0xAA, 0x00, 0x01, 0x3F, 0xD6, 0xA9, 0x83, 0x50, 0xF8, 0xE8, 0x03, 0x16, 0x2A, 0xD6, 0x0A, 0x00, 0x11};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(800, proc_id_recv)[] = {0xA9BF2FEA, 0xF9404FEB, 0x2A1603EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400368, 0xF9401D08, 0xAA1B03E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
|
||||
|
||||
/* svcControlCodeMemory Patches */
|
||||
/* b.eq -> nop */
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(500, svc_control_codememory)[] = {MAKE_NOP};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(600, svc_control_codememory)[] = {MAKE_NOP};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(700, svc_control_codememory)[] = {MAKE_NOP};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(800, svc_control_codememory)[] = {MAKE_NOP};
|
||||
|
||||
/* Hook Definitions. */
|
||||
static const kernel_patch_t g_kernel_patches_100[] = {
|
||||
|
@ -532,6 +592,29 @@ static const kernel_patch_t g_kernel_patches_700[] = {
|
|||
.patch_offset = 0x3C6E0,
|
||||
}
|
||||
};
|
||||
static const kernel_patch_t g_kernel_patches_800[] = {
|
||||
{ /* Send Message Process ID Patch. */
|
||||
.pattern_size = 0x1C,
|
||||
.pattern = MAKE_KERNEL_PATTERN_NAME(800, proc_id_send),
|
||||
.pattern_hook_offset = 0x0,
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(800, proc_id_send))/sizeof(instruction_t),
|
||||
.branch_back_offset = 0x10,
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(800, proc_id_send)
|
||||
},
|
||||
{ /* Receive Message Process ID Patch. */
|
||||
.pattern_size = 0x1C,
|
||||
.pattern = MAKE_KERNEL_PATTERN_NAME(800, proc_id_recv),
|
||||
.pattern_hook_offset = 0x0,
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(800, proc_id_recv))/sizeof(instruction_t),
|
||||
.branch_back_offset = 0x10,
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(800, proc_id_recv)
|
||||
},
|
||||
{ /* svcControlCodeMemory Patch. */
|
||||
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(800, svc_control_codememory))/sizeof(instruction_t),
|
||||
.payload = MAKE_KERNEL_PATCH_NAME(800, svc_control_codememory),
|
||||
.patch_offset = 0x3FAD0,
|
||||
}
|
||||
};
|
||||
|
||||
#define KERNEL_PATCHES(vers) .num_patches = sizeof(g_kernel_patches_##vers)/sizeof(kernel_patch_t), .patches = g_kernel_patches_##vers,
|
||||
|
||||
|
@ -581,6 +664,15 @@ static const kernel_info_t g_kernel_infos[] = {
|
|||
.hash = {0xA2, 0x5E, 0x47, 0x0C, 0x8E, 0x6D, 0x2F, 0xD7, 0x5D, 0xAD, 0x24, 0xD7, 0xD8, 0x24, 0x34, 0xFB, 0xCD, 0x77, 0xBB, 0xE6, 0x66, 0x03, 0xCB, 0xAF, 0xAB, 0x85, 0x45, 0xA0, 0x91, 0xAF, 0x34, 0x25},
|
||||
.free_code_space_offset = 0x5FEC0,
|
||||
KERNEL_PATCHES(700)
|
||||
},
|
||||
{ /* 8.0.0. */
|
||||
.hash = {0xA6, 0xAD, 0x5D, 0x7F, 0xCF, 0x25, 0x80, 0xAE, 0xE6, 0x57, 0x9F, 0x6F, 0xC5, 0xC5, 0xF6, 0x13, 0x77, 0x23, 0xAC, 0x88, 0x79, 0x76, 0xF7, 0x25, 0x06, 0x16, 0x35, 0x3B, 0x3F, 0xA7, 0x59, 0x49},
|
||||
.hash_offset = 0x1A8,
|
||||
.hash_size = 0x95000 - 0x1A8,
|
||||
.embedded_ini_offset = 0x95000,
|
||||
.embedded_ini_ptr = 0x168,
|
||||
.free_code_space_offset = 0x607F0,
|
||||
KERNEL_PATCHES(800)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -607,17 +699,27 @@ uint8_t *search_pattern(void *_mem, size_t mem_size, const void *_pattern, size_
|
|||
|
||||
const kernel_info_t *get_kernel_info(void *kernel, size_t size) {
|
||||
uint8_t calculated_hash[0x20];
|
||||
uint8_t calculated_partial_hash[0x20];
|
||||
se_calculate_sha256(calculated_hash, kernel, size);
|
||||
|
||||
for (unsigned int i = 0; i < sizeof(g_kernel_infos)/sizeof(kernel_info_t); i++) {
|
||||
if (memcmp(calculated_hash, g_kernel_infos[i].hash, sizeof(calculated_hash)) == 0) {
|
||||
return &g_kernel_infos[i];
|
||||
if (g_kernel_infos[i].hash_size == 0 || size <= g_kernel_infos[i].hash_size) {
|
||||
if (memcmp(calculated_hash, g_kernel_infos[i].hash, sizeof(calculated_hash)) == 0) {
|
||||
return &g_kernel_infos[i];
|
||||
}
|
||||
} else {
|
||||
se_calculate_sha256(calculated_partial_hash, (void *)((uintptr_t)kernel + g_kernel_infos[i].hash_offset), g_kernel_infos[i].hash_size);
|
||||
if (memcmp(calculated_partial_hash, g_kernel_infos[i].hash, sizeof(calculated_partial_hash)) == 0) {
|
||||
return &g_kernel_infos[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void package2_patch_kernel(void *_kernel, size_t size, bool is_sd_kernel) {
|
||||
void package2_patch_kernel(void *_kernel, size_t size, bool is_sd_kernel, void **out_ini1) {
|
||||
const kernel_info_t *kernel_info = get_kernel_info(_kernel, size);
|
||||
*out_ini1 = NULL;
|
||||
|
||||
/* Apply IPS patches. */
|
||||
apply_kernel_ips_patches(_kernel, size);
|
||||
|
@ -631,6 +733,11 @@ void package2_patch_kernel(void *_kernel, size_t size, bool is_sd_kernel) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (kernel_info->embedded_ini_offset != 0) {
|
||||
*out_ini1 = (void *)((uintptr_t)_kernel + kernel_info->embedded_ini_offset);
|
||||
*((volatile uint64_t *)((uintptr_t)_kernel + kernel_info->embedded_ini_ptr)) = (uint64_t)size;
|
||||
}
|
||||
|
||||
/* Apply hooks and patches. */
|
||||
uint8_t *kernel = (uint8_t *)_kernel;
|
||||
size_t free_space_offset = kernel_info->free_code_space_offset;
|
||||
|
|
|
@ -19,6 +19,6 @@
|
|||
|
||||
#include "utils.h"
|
||||
|
||||
void package2_patch_kernel(void *kernel, size_t kernel_size, bool is_sd_kernel);
|
||||
void package2_patch_kernel(void *kernel, size_t kernel_size, bool is_sd_kernel, void **out_ini1);
|
||||
|
||||
#endif
|
|
@ -149,6 +149,7 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui
|
|||
desired_keyblob = MASTERKEY_REVISION_620;
|
||||
break;
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_700:
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_800:
|
||||
desired_keyblob = MASTERKEY_REVISION_700_CURRENT;
|
||||
break;
|
||||
default:
|
||||
|
@ -223,6 +224,7 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui
|
|||
case ATMOSPHERE_TARGET_FIRMWARE_600:
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_620:
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_700:
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_800:
|
||||
decrypt_data_into_keyslot(0xA, 0xF, devicekey_4x_seed, 0x10);
|
||||
decrypt_data_into_keyslot(0xF, 0xF, devicekey_seed, 0x10);
|
||||
decrypt_data_into_keyslot(0xE, 0xC, masterkey_4x_seed, 0x10);
|
||||
|
|
|
@ -60,6 +60,7 @@ static void setup_env(void) {
|
|||
train_dram();
|
||||
}
|
||||
|
||||
|
||||
static void cleanup_env(void) {
|
||||
/* Unmount everything (this causes all open files to be flushed and closed) */
|
||||
nxfs_end();
|
||||
|
@ -119,6 +120,8 @@ int main(int argc, void **argv) {
|
|||
uint32_t boot_memaddr = nxboot_main();
|
||||
/* Wait for the splash screen to have been displayed as long as it should be. */
|
||||
splash_screen_wait_delay();
|
||||
/* Cleanup environment. */
|
||||
cleanup_env();
|
||||
/* Finish boot. */
|
||||
nxboot_finish(boot_memaddr);
|
||||
} else {
|
||||
|
|
|
@ -190,8 +190,10 @@ static uint32_t nxboot_get_target_firmware(const void *package1loader) {
|
|||
fatal_error("[NXBOOT] Unable to identify package1!\n");
|
||||
}
|
||||
}
|
||||
case 0x0F:
|
||||
case 0x0F: /* 7.0.0 - 7.0.1 */
|
||||
return ATMOSPHERE_TARGET_FIRMWARE_700;
|
||||
case 0x10: /* 8.0.0 */
|
||||
return ATMOSPHERE_TARGET_FIRMWARE_800;
|
||||
default:
|
||||
fatal_error("[NXBOOT] Unable to identify package1!\n");
|
||||
}
|
||||
|
@ -514,7 +516,7 @@ uint32_t nxboot_main(void) {
|
|||
if (!package1_get_tsec_fw(&tsec_fw, package1loader, package1loader_size)) {
|
||||
fatal_error("[NXBOOT] Failed to read the TSEC firmware from Package1loader!\n");
|
||||
}
|
||||
if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_700) {
|
||||
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_700) {
|
||||
tsec_fw_size = 0x3000;
|
||||
} else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_620) {
|
||||
tsec_fw_size = 0x2900;
|
||||
|
|
|
@ -56,7 +56,8 @@ SdmmcPartitionNum g_current_emmc_partition = SDMMC_PARTITION_INVALID;
|
|||
static int mmc_partition_initialize(device_partition_t *devpart) {
|
||||
mmc_partition_info_t *mmcpart = (mmc_partition_info_t *)devpart->device_struct;
|
||||
|
||||
if (devpart->read_cipher != NULL || devpart->write_cipher != NULL) {
|
||||
/* Allocate the crypto work buffer. */
|
||||
if ((devpart->read_cipher != NULL) || (devpart->write_cipher != NULL)) {
|
||||
devpart->crypto_work_buffer = memalign(16, devpart->sector_size * 16);
|
||||
if (devpart->crypto_work_buffer == NULL) {
|
||||
return ENOMEM;
|
||||
|
@ -74,6 +75,7 @@ static int mmc_partition_initialize(device_partition_t *devpart) {
|
|||
g_ahb_redirect_enabled = true;
|
||||
}
|
||||
|
||||
/* Initialize hardware. */
|
||||
if (mmcpart->device == &g_sd_device) {
|
||||
if (!g_sd_device_initialized) {
|
||||
int rc = sdmmc_device_sd_init(mmcpart->device, &g_sd_sdmmc, SDMMC_BUS_WIDTH_4BIT, SDMMC_SPEED_SDR104) ? 0 : EIO;
|
||||
|
@ -98,13 +100,33 @@ static int mmc_partition_initialize(device_partition_t *devpart) {
|
|||
}
|
||||
|
||||
static void mmc_partition_finalize(device_partition_t *devpart) {
|
||||
free(devpart->crypto_work_buffer);
|
||||
mmc_partition_info_t *mmcpart = (mmc_partition_info_t *)devpart->device_struct;
|
||||
|
||||
/* Finalize hardware. */
|
||||
if (mmcpart->device == &g_sd_device) {
|
||||
if (g_sd_device_initialized) {
|
||||
sdmmc_device_finish(&g_sd_device);
|
||||
g_sd_device_initialized = false;
|
||||
}
|
||||
devpart->initialized = false;
|
||||
} else if (mmcpart->device == &g_emmc_device) {
|
||||
if (g_emmc_device_initialized) {
|
||||
sdmmc_device_finish(&g_emmc_device);
|
||||
g_emmc_device_initialized = false;
|
||||
}
|
||||
devpart->initialized = false;
|
||||
}
|
||||
|
||||
/* Disable AHB redirection if necessary. */
|
||||
if (g_ahb_redirect_enabled) {
|
||||
mc_disable_ahb_redirect();
|
||||
g_ahb_redirect_enabled = false;
|
||||
}
|
||||
|
||||
/* Free the crypto work buffer. */
|
||||
if (devpart->crypto_work_buffer != NULL) {
|
||||
free(devpart->crypto_work_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
static int mmc_partition_read(device_partition_t *devpart, void *dst, uint64_t sector, uint64_t num_sectors) {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <atmosphere.h>
|
||||
#include "utils.h"
|
||||
#include "masterkey.h"
|
||||
#include "stratosphere.h"
|
||||
|
@ -86,10 +87,22 @@ void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firm
|
|||
}
|
||||
|
||||
/* Perform any patches we want to the NX kernel. */
|
||||
package2_patch_kernel(kernel, kernel_size, is_sd_kernel);
|
||||
|
||||
package2_patch_kernel(kernel, kernel_size, is_sd_kernel, (void *)&orig_ini1);
|
||||
|
||||
/* Ensure we know where embedded INI is if present, and we don't if not. */
|
||||
if ((target_firmware < ATMOSPHERE_TARGET_FIRMWARE_800 && orig_ini1 != NULL) ||
|
||||
(target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_800 && orig_ini1 == NULL)) {
|
||||
fatal_error("Error: inappropriate kernel embedded ini context");
|
||||
}
|
||||
|
||||
print(SCREEN_LOG_LEVEL_DEBUG, "Rebuilding the INI1 section...\n");
|
||||
package2_get_src_section((void *)&orig_ini1, package2, PACKAGE2_SECTION_INI1);
|
||||
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_800) {
|
||||
package2_get_src_section((void *)&orig_ini1, package2, PACKAGE2_SECTION_INI1);
|
||||
} else {
|
||||
/* On 8.0.0, place INI1 right after kernelldr for our sanity. */
|
||||
package2->metadata.section_offsets[PACKAGE2_SECTION_INI1] = package2->metadata.section_offsets[PACKAGE2_SECTION_KERNEL] + package2->metadata.section_sizes[PACKAGE2_SECTION_KERNEL];
|
||||
}
|
||||
|
||||
/* Perform any patches to the INI1, rebuilding it (This is where our built-in sysmodules will be added.) */
|
||||
rebuilt_ini1 = package2_rebuild_ini1(orig_ini1, target_firmware);
|
||||
print(SCREEN_LOG_LEVEL_DEBUG, "Rebuilt INI1...\n");
|
||||
|
@ -187,10 +200,15 @@ static bool package2_validate_metadata(package2_meta_t *metadata, uint8_t data[]
|
|||
}
|
||||
|
||||
/* Ensure no overlap with later sections. */
|
||||
for (unsigned int later_section = section + 1; later_section < PACKAGE2_SECTION_MAX; later_section++) {
|
||||
uint32_t later_section_end = metadata->section_offsets[later_section] + metadata->section_sizes[later_section];
|
||||
if (overlaps(metadata->section_offsets[section], section_end, metadata->section_offsets[later_section], later_section_end)) {
|
||||
return false;
|
||||
if (metadata->section_sizes[section] != 0) {
|
||||
for (unsigned int later_section = section + 1; later_section < PACKAGE2_SECTION_MAX; later_section++) {
|
||||
if (metadata->section_sizes[later_section] == 0) {
|
||||
continue;
|
||||
}
|
||||
uint32_t later_section_end = metadata->section_offsets[later_section] + metadata->section_sizes[later_section];
|
||||
if (overlaps(metadata->section_offsets[section], section_end, metadata->section_offsets[later_section], later_section_end)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1202,6 +1202,9 @@ void sdmmc_finish(sdmmc_t *sdmmc)
|
|||
|
||||
/* Power cycle for 100ms without power. */
|
||||
mdelay(100);
|
||||
|
||||
/* Disable the regulator. */
|
||||
max77620_regulator_enable(REGULATOR_LDO2, 0);
|
||||
}
|
||||
|
||||
/* Force a register read to refresh the clock control value. */
|
||||
|
|
|
@ -191,6 +191,14 @@ _content_headers:
|
|||
.asciz "sm"
|
||||
.align 5
|
||||
|
||||
/* spl content header */
|
||||
.word __spl_kip_start__
|
||||
.word __spl_kip_size__
|
||||
.word CONTENT_TYPE_KIP
|
||||
.word 0xCCCCCCCC
|
||||
.asciz "spl"
|
||||
.align 5
|
||||
|
||||
/* splash_screen content header */
|
||||
.word __splash_screen_bmp_start__
|
||||
.word __splash_screen_bmp_size__
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "ams_mitm_kip.h"
|
||||
#include "boot_100_kip.h"
|
||||
#include "boot_200_kip.h"
|
||||
#include "spl_kip.h"
|
||||
#undef u8
|
||||
#undef u32
|
||||
|
||||
|
@ -45,12 +46,13 @@ static bool g_stratosphere_loader_enabled = true;
|
|||
static bool g_stratosphere_sm_enabled = true;
|
||||
static bool g_stratosphere_pm_enabled = true;
|
||||
static bool g_stratosphere_ams_mitm_enabled = true;
|
||||
static bool g_stratosphere_spl_enabled = true;
|
||||
static bool g_stratosphere_boot_enabled = false;
|
||||
|
||||
extern const uint8_t boot_100_kip[], boot_200_kip[];
|
||||
extern const uint8_t loader_kip[], pm_kip[], sm_kip[], ams_mitm_kip[];
|
||||
extern const uint8_t loader_kip[], pm_kip[], sm_kip[], spl_kip[], ams_mitm_kip[];
|
||||
extern const uint32_t boot_100_kip_size, boot_200_kip_size;
|
||||
extern const uint32_t loader_kip_size, pm_kip_size, sm_kip_size, ams_mitm_kip_size;
|
||||
extern const uint32_t loader_kip_size, pm_kip_size, sm_kip_size, spl_kip_size, ams_mitm_kip_size;
|
||||
|
||||
/* GCC doesn't consider the size as const... we have to write it ourselves. */
|
||||
|
||||
|
@ -90,6 +92,11 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) {
|
|||
num_processes++;
|
||||
}
|
||||
|
||||
if (g_stratosphere_spl_enabled) {
|
||||
size += spl_kip_size;
|
||||
num_processes++;
|
||||
}
|
||||
|
||||
if (g_stratosphere_ams_mitm_enabled) {
|
||||
size += ams_mitm_kip_size;
|
||||
num_processes++;
|
||||
|
@ -129,6 +136,11 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) {
|
|||
data += sm_kip_size;
|
||||
}
|
||||
|
||||
if (g_stratosphere_spl_enabled) {
|
||||
memcpy(data, spl_kip, spl_kip_size);
|
||||
data += spl_kip_size;
|
||||
}
|
||||
|
||||
if (g_stratosphere_ams_mitm_enabled) {
|
||||
memcpy(data, ams_mitm_kip, ams_mitm_kip_size);
|
||||
data += ams_mitm_kip_size;
|
||||
|
|
|
@ -168,9 +168,9 @@ __attribute__((noreturn)) void fatal_error(const char *fmt, ...) {
|
|||
|
||||
__attribute__((noinline)) bool overlaps(uint64_t as, uint64_t ae, uint64_t bs, uint64_t be)
|
||||
{
|
||||
if(as <= bs && bs <= ae)
|
||||
if(as <= bs && bs < ae)
|
||||
return true;
|
||||
if(bs <= as && as <= be)
|
||||
if(bs <= as && as < be)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue