Merge branch 'master' into emunand_dev

This commit is contained in:
hexkyz 2019-04-28 16:53:39 +01:00
commit a9afbd2458
123 changed files with 6022 additions and 1386 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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