From 867ff62dfac1cc59f76b6e8adc681d5bd709416a Mon Sep 17 00:00:00 2001 From: Christoph Baumann Date: Tue, 13 May 2025 13:07:25 +0200 Subject: [PATCH] Support for booting from eMMC Fusee will Look for FAT32 partition on BOOT1 (1MB offset), BOOT1, GPP, SD, in this order If a .no_boot_storage file is found in the root directory, the partition is skipped --- fusee/program/source/fatfs/diskio.c | 11 ++ fusee/program/source/fatfs/diskio.h | 2 + fusee/program/source/fatfs/diskio_cpp.h | 3 + fusee/program/source/fatfs/ffconf.h | 6 +- fusee/program/source/fatfs/fusee_diskio.cpp | 9 ++ fusee/program/source/fs/fusee_fs_api.cpp | 47 ++++++- fusee/program/source/fs/fusee_fs_api.hpp | 10 ++ fusee/program/source/fusee_boot_storage.cpp | 136 +++++++++++++++++++ fusee/program/source/fusee_boot_storage.hpp | 19 +++ fusee/program/source/fusee_fatal.cpp | 2 +- fusee/program/source/fusee_main.cpp | 18 +-- fusee/program/source/fusee_mmc.cpp | 8 ++ fusee/program/source/fusee_mmc.hpp | 1 + fusee/program/source/fusee_setup_horizon.cpp | 18 +-- fusee/program/source/fusee_stratosphere.cpp | 6 +- 15 files changed, 264 insertions(+), 32 deletions(-) create mode 100644 fusee/program/source/fusee_boot_storage.cpp create mode 100644 fusee/program/source/fusee_boot_storage.hpp diff --git a/fusee/program/source/fatfs/diskio.c b/fusee/program/source/fatfs/diskio.c index a91dd722c..e4c636d88 100644 --- a/fusee/program/source/fatfs/diskio.c +++ b/fusee/program/source/fatfs/diskio.c @@ -15,6 +15,8 @@ #include "diskio_cpp.h" +#define BOOT1_OFFSET_SCT_1MB 0x800 + /*-----------------------------------------------------------------------*/ /* Get Drive Status */ /*-----------------------------------------------------------------------*/ @@ -57,6 +59,11 @@ DRESULT disk_read ( return diskio_read_sd_card(buff, count * 512, sector, count) ? RES_OK : RES_ERROR; case DRIVE_SYS: return diskio_read_system(buff, count * 512, sector, count) ? RES_OK : RES_ERROR; + case DRIVE_BOOT1: + return diskio_read_boot1(buff, count * 512, sector, count) ? RES_OK : RES_ERROR; + case DRIVE_BOOT1_OFF: + return diskio_read_boot1(buff, count * 512, sector + BOOT1_OFFSET_SCT_1MB, count) ? RES_OK : RES_ERROR; + default: return RES_PARERR; } @@ -82,6 +89,10 @@ DRESULT disk_write ( return diskio_write_sd_card(sector, count, buff, count * 512) ? RES_OK : RES_ERROR; case DRIVE_SYS: return diskio_write_system(sector, count, buff, count * 512) ? RES_OK : RES_ERROR; + case DRIVE_BOOT1: + return diskio_write_boot1(sector, count, buff, count * 512) ? RES_OK : RES_ERROR; + case DRIVE_BOOT1_OFF: + return diskio_write_boot1(sector + DRIVE_BOOT1_OFF, count, buff, count * 512) ? RES_OK : RES_ERROR; default: return RES_PARERR; } diff --git a/fusee/program/source/fatfs/diskio.h b/fusee/program/source/fatfs/diskio.h index 9b2bbb30d..b127bc6ff 100644 --- a/fusee/program/source/fatfs/diskio.h +++ b/fusee/program/source/fatfs/diskio.h @@ -25,6 +25,8 @@ typedef enum { typedef enum { DRIVE_SD, DRIVE_SYS, + DRIVE_BOOT1, + DRIVE_BOOT1_OFF, } DDRIVE; diff --git a/fusee/program/source/fatfs/diskio_cpp.h b/fusee/program/source/fatfs/diskio_cpp.h index 6c48d7d14..f29bd0a6a 100644 --- a/fusee/program/source/fatfs/diskio_cpp.h +++ b/fusee/program/source/fatfs/diskio_cpp.h @@ -25,6 +25,9 @@ bool diskio_write_sd_card(size_t sector_index, size_t sector_count, const void * bool diskio_read_system(void *dst, size_t size, size_t sector_index, size_t sector_count); bool diskio_write_system(size_t sector_index, size_t sector_count, const void *src, size_t size); +bool diskio_read_boot1(void *dst, size_t size, size_t sector_index, size_t sector_count); +bool diskio_write_boot1(size_t sector_index, size_t sector_count, const void *src, size_t size); + #ifdef __cplusplus } #endif diff --git a/fusee/program/source/fatfs/ffconf.h b/fusee/program/source/fatfs/ffconf.h index 5be0a26c7..81e3369ec 100644 --- a/fusee/program/source/fatfs/ffconf.h +++ b/fusee/program/source/fatfs/ffconf.h @@ -150,7 +150,7 @@ */ -#define FF_FS_RPATH 0 +#define FF_FS_RPATH 1 /* This option configures support for relative path. / / 0: Disable relative path and remove related functions. @@ -163,12 +163,12 @@ / Drive/Volume Configurations /---------------------------------------------------------------------------*/ -#define FF_VOLUMES 2 +#define FF_VOLUMES 4 /* Number of volumes (logical drives) to be used. (1-10) */ #define FF_STR_VOLUME_ID 1 -#define FF_VOLUME_STRS "sdmc","sys" +#define FF_VOLUME_STRS "sdmc","sys","boot1","boot1_off" /* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings. / When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive / number in the path name. FF_VOLUME_STRS defines the volume ID strings for each diff --git a/fusee/program/source/fatfs/fusee_diskio.cpp b/fusee/program/source/fatfs/fusee_diskio.cpp index 74cbad17f..eb211e532 100644 --- a/fusee/program/source/fatfs/fusee_diskio.cpp +++ b/fusee/program/source/fatfs/fusee_diskio.cpp @@ -33,4 +33,13 @@ bool diskio_read_system(void *dst, size_t size, size_t sector_index, size_t sect bool diskio_write_system(size_t sector_index, size_t sector_count, const void *src, size_t size) { /* Don't allow writes to eMMC GPP partition */ return false; +} + +bool diskio_read_boot1(void *dst, size_t size, size_t sector_index, size_t sector_count) { + return R_SUCCEEDED(::ams::nxboot::ReadMmc(dst, size, ::ams::sdmmc::MmcPartition::MmcPartition_BootPartition2, sector_index, sector_count)); +} + +bool diskio_write_boot1(size_t sector_index, size_t sector_count, const void *src, size_t size) { + /* Don't allow writes to eMMC BOOT1 */ + return false; } \ No newline at end of file diff --git a/fusee/program/source/fs/fusee_fs_api.cpp b/fusee/program/source/fs/fusee_fs_api.cpp index 4338b2c8a..b602c1cea 100644 --- a/fusee/program/source/fs/fusee_fs_api.cpp +++ b/fusee/program/source/fs/fusee_fs_api.cpp @@ -26,11 +26,14 @@ namespace ams::fs { constexpr size_t MaxFiles = 8 + 64; constexpr size_t MaxDirectories = 2; - constinit bool g_is_sd_mounted = false; - constinit bool g_is_sys_mounted = false; + constinit bool g_is_sd_mounted = false; + constinit bool g_is_sys_mounted = false; + constinit bool g_is_boot1_mounted = false; + constinit bool g_is_boot1_off_mounted = false; - alignas(0x10) constinit FATFS g_sd_fs = {}; - alignas(0x10) constinit FATFS g_sys_fs = {}; + alignas(0x10) constinit FATFS g_sd_fs = {}; + alignas(0x10) constinit FATFS g_sys_fs = {}; + alignas(0x10) constinit FATFS g_boot1_fs = {}; alignas(0x10) constinit FIL g_files[MaxFiles] = {}; alignas(0x10) constinit DIR g_dirs[MaxDirectories] = {}; @@ -119,6 +122,32 @@ namespace ams::fs { } + bool MountBoot1() { + /* Can't mount both */ + AMS_ASSERT(!g_is_boot1_mounted && !g_is_boot1_off_mounted); + g_is_boot1_mounted = f_mount(std::addressof(g_boot1_fs), "boot1:", 1) == FR_OK; + return g_is_boot1_mounted; + } + + void UnmountBoot1 () { + AMS_ASSERT(g_is_boot1_mounted); + f_unmount("boot1:"); + g_is_boot1_mounted = false; + } + + bool MountBoot1Off() { + /* Can't mount both */ + AMS_ASSERT(!g_is_boot1_mounted && !g_is_boot1_off_mounted); + g_is_boot1_off_mounted = f_mount(std::addressof(g_boot1_fs), "boot1_off:", 1) == FR_OK; + return g_is_boot1_off_mounted; + } + + void UnmountBoot1Off () { + AMS_ASSERT(g_is_boot1_off_mounted); + f_unmount("boot1_off:"); + g_is_boot1_off_mounted = false; + } + bool MountSys() { AMS_ASSERT(!g_is_sys_mounted); g_is_sys_mounted = f_mount(std::addressof(g_sys_fs), "sys:", 1) == FR_OK; @@ -143,6 +172,16 @@ namespace ams::fs { g_is_sd_mounted = false; } + Result ChangeDrive(const char *path) { + R_TRY(TranslateFatFsError(f_chdrive(path))); + R_SUCCEED(); + } + + Result ChangeDirectory(const char *path) { + R_TRY(TranslateFatFsError(f_chdir(path))); + R_SUCCEED(); + } + Result GetEntryType(DirectoryEntryType *out_entry_type, bool *out_archive, const char *path) { /* Get the file info. */ FILINFO info; diff --git a/fusee/program/source/fs/fusee_fs_api.hpp b/fusee/program/source/fs/fusee_fs_api.hpp index e97a19c8c..1bc9bdd7e 100644 --- a/fusee/program/source/fs/fusee_fs_api.hpp +++ b/fusee/program/source/fs/fusee_fs_api.hpp @@ -101,6 +101,16 @@ namespace ams::fs { bool MountSys(); void UnmountSys(); + bool MountBoot1(); + void UnmountBoot1(); + + /* Mount FAT32 FS on BOOT1 at 1MB offset */ + bool MountBoot1Off(); + void UnmountBoot1Off(); + + Result ChangeDrive(const char *path); + Result ChangeDirectory(const char *path); + Result GetEntryType(DirectoryEntryType *out_entry_type, bool *out_archive, const char *path); Result CreateFile(const char *path, s64 size); diff --git a/fusee/program/source/fusee_boot_storage.cpp b/fusee/program/source/fusee_boot_storage.cpp new file mode 100644 index 000000000..557f22b10 --- /dev/null +++ b/fusee/program/source/fusee_boot_storage.cpp @@ -0,0 +1,136 @@ +#include "fusee_boot_storage.hpp" +#include "fs/fusee_fs_api.hpp" +#include "fusee_display.hpp" +#include "fusee_mmc.hpp" +#include "fusee_sd_card.hpp" +#include +#include + +namespace ams::nxboot { + namespace { + constinit BootStorage g_boot_storage = BootDrive_Invalid; + + Result IsBootStorageValid() { + fs::DirectoryEntryType entry_type; + bool is_archive; + Result r; + if(R_SUCCEEDED(r = fs::GetEntryType(std::addressof(entry_type), std::addressof(is_archive), ".no_boot_storage"))) { + if(entry_type == fs::DirectoryEntryType_File) { + R_THROW(fs::ResultInvalidMountName()); + } + } + R_SUCCEED(); + } + + Result BootStorageInitializeAndMount(BootStorage storage) { + AMS_ASSERT(g_boot_storage == BootDrive_Invalid); + + switch(storage) { + case BootDrive_Boot1Off: + { + R_TRY(InitializeMmc()); + ON_RESULT_FAILURE { FinalizeMmc(); }; + R_UNLESS(fs::MountBoot1Off(), fs::ResultInvalidMountName()); + ON_RESULT_FAILURE_2 { fs::UnmountBoot1Off(); }; + R_TRY(fs::ChangeDrive("boot1_off:")); + R_TRY(IsBootStorageValid()); + g_boot_storage = storage; + R_SUCCEED(); + } break; + case BootDrive_Boot1: + { + R_TRY(InitializeMmc()); + ON_RESULT_FAILURE { FinalizeMmc(); }; + R_UNLESS(fs::MountBoot1(), fs::ResultInvalidMountName()); + ON_RESULT_FAILURE_2 { fs::UnmountBoot1(); }; + R_TRY(fs::ChangeDrive("boot1:")); + R_TRY(IsBootStorageValid()); + g_boot_storage = storage; + R_SUCCEED(); + } break; + case BootDrive_System: + { + R_TRY(InitializeMmc()); + ON_RESULT_FAILURE { FinalizeMmc(); }; + R_UNLESS(fs::MountSys(), fs::ResultInvalidMountName()); + ON_RESULT_FAILURE_2 { fs::UnmountSys(); }; + R_TRY(fs::ChangeDrive("sys:")); + R_TRY(IsBootStorageValid()); + g_boot_storage = storage; + R_SUCCEED(); + } break; + case BootDrive_SD: + { + R_TRY(InitializeSdCard()); + ON_RESULT_FAILURE { FinalizeSdCard(); }; + R_UNLESS(fs::MountSdCard(), fs::ResultInvalidMountName()); + ON_RESULT_FAILURE_2 { fs::UnmountSdCard(); }; + R_TRY(fs::ChangeDrive("sdmc:")); + R_TRY(IsBootStorageValid()); + g_boot_storage = storage; + R_SUCCEED(); + } break; + AMS_UNREACHABLE_DEFAULT_CASE(); + } + + R_THROW(fs::ResultInvalidMountName()); + } + + } + + Result MountBootStorage() { + for(uint32_t i = BootDrive_Min; i < BootDrive_Max; i++) { + R_SUCCEED_IF(R_SUCCEEDED(BootStorageInitializeAndMount(static_cast(i)))); + } + R_THROW(fs::ResultInvalidMountName()); + } + + void FinalizeBootStorage() { + AMS_ASSERT(g_boot_storage != BootDrive_Invalid); + + switch(g_boot_storage) { + case BootDrive_Boot1Off: + fs::UnmountBoot1Off(); + FinalizeMmc(); + break; + case BootDrive_Boot1: + fs::UnmountBoot1(); + FinalizeMmc(); + break; + case BootDrive_System: + fs::UnmountSys(); + FinalizeMmc(); + break; + case BootDrive_SD: + fs::UnmountSdCard(); + FinalizeSdCard(); + break; + AMS_UNREACHABLE_DEFAULT_CASE(); + } + } + + void UnmountBootStorage() { + AMS_ASSERT(g_boot_storage != BootDrive_Invalid); + + switch(g_boot_storage) { + case BootDrive_Boot1Off: + fs::UnmountBoot1Off(); + break; + case BootDrive_Boot1: + fs::UnmountBoot1(); + break; + case BootDrive_System: + fs::UnmountSys(); + break; + case BootDrive_SD: + fs::UnmountSdCard(); + break; + AMS_UNREACHABLE_DEFAULT_CASE(); + } + } + + BootStorage GetBootStorage(){ + return g_boot_storage; + } + +} \ No newline at end of file diff --git a/fusee/program/source/fusee_boot_storage.hpp b/fusee/program/source/fusee_boot_storage.hpp new file mode 100644 index 000000000..aeca6d50e --- /dev/null +++ b/fusee/program/source/fusee_boot_storage.hpp @@ -0,0 +1,19 @@ +#include + +namespace ams::nxboot { + enum BootStorage : u32 { + BootDrive_Min = 0, + BootDrive_Boot1Off = 0, + BootDrive_Boot1, + BootDrive_System, + BootDrive_SD, + BootDrive_Max, + BootDrive_Invalid = BootDrive_Max, + }; + + + Result MountBootStorage(); + void FinalizeBootStorage(); + void UnmountBootStorage(); + BootStorage GetBootStorage(); +} \ No newline at end of file diff --git a/fusee/program/source/fusee_fatal.cpp b/fusee/program/source/fusee_fatal.cpp index 843b1c236..7481edb14 100644 --- a/fusee/program/source/fusee_fatal.cpp +++ b/fusee/program/source/fusee_fatal.cpp @@ -30,7 +30,7 @@ namespace ams::nxboot { { /* Generate the file path. */ char path[0x40]; - util::TSNPrintf(path, sizeof(path), "sdmc:/atmosphere/fatal_errors/report_%016" PRIx64 ".bin", ctx->report_identifier); + util::TSNPrintf(path, sizeof(path), "atmosphere/fatal_errors/report_%016" PRIx64 ".bin", ctx->report_identifier); /* Create the file. */ R_TRY(fs::CreateFile(path, sizeof(*ctx))); diff --git a/fusee/program/source/fusee_main.cpp b/fusee/program/source/fusee_main.cpp index 9409d1740..f7119a234 100644 --- a/fusee/program/source/fusee_main.cpp +++ b/fusee/program/source/fusee_main.cpp @@ -14,6 +14,7 @@ * along with this program. If not, see . */ #include +#include "fusee_boot_storage.hpp" #include "fusee_display.hpp" #include "sein/fusee_secure_initialize.hpp" #include "sdram/fusee_sdram.hpp" @@ -30,7 +31,7 @@ namespace ams::nxboot { namespace { - constexpr const char ExternalPackageFilePath[] = "sdmc:/atmosphere/package3"; + constexpr const char ExternalPackageFilePath[] = "atmosphere/package3"; constinit fs::FileHandle g_package_file; @@ -81,17 +82,9 @@ namespace ams::nxboot { /* Initialize cache. */ hw::InitializeDataCache(); - /* Initialize SD card. */ - { - Result result = InitializeSdCard(); - if (R_FAILED(result)) { - ShowFatalError("Failed to initialize the SD card: 0x%08" PRIx32 "\n", result.GetValue()); - } - } - - /* Mount SD card. */ - if (!fs::MountSdCard()) { - ShowFatalError("Failed to mount the SD card."); + /* Initialize and mount boot storage. */ + if (R_FAILED(MountBootStorage())) { + ShowFatalError("Failed to mount boot storage."); } /* If we have a fatal error, save and display it. */ @@ -135,6 +128,7 @@ namespace ams::nxboot { FinalizeDisplay(); /* Finalize sd card. */ + UnmountBootStorage(); FinalizeSdCard(); /* Finalize the data cache. */ diff --git a/fusee/program/source/fusee_mmc.cpp b/fusee/program/source/fusee_mmc.cpp index 639c83e6f..19de3550e 100644 --- a/fusee/program/source/fusee_mmc.cpp +++ b/fusee/program/source/fusee_mmc.cpp @@ -39,6 +39,14 @@ namespace ams::nxboot { } + void FinalizeMmc() { + /* Deactivate MMC. */ + sdmmc::Deactivate(MmcPort); + + /* Finalize MMC. */ + sdmmc::Finalize(MmcPort); + } + Result InitializeMmc() { /* Initialize the mmc. */ sdmmc::Initialize(MmcPort); diff --git a/fusee/program/source/fusee_mmc.hpp b/fusee/program/source/fusee_mmc.hpp index f69ba61a8..639fb8ea4 100644 --- a/fusee/program/source/fusee_mmc.hpp +++ b/fusee/program/source/fusee_mmc.hpp @@ -19,6 +19,7 @@ namespace ams::nxboot { Result InitializeMmc(); + void FinalizeMmc(); Result CheckMmcConnection(sdmmc::SpeedMode *out_sm, sdmmc::BusWidth *out_bw); Result GetMmcMemoryCapacity(u32 *out_num_sectors, sdmmc::MmcPartition partition); diff --git a/fusee/program/source/fusee_setup_horizon.cpp b/fusee/program/source/fusee_setup_horizon.cpp index 0a2000bc3..c34c211b6 100644 --- a/fusee/program/source/fusee_setup_horizon.cpp +++ b/fusee/program/source/fusee_setup_horizon.cpp @@ -143,7 +143,7 @@ namespace ams::nxboot { { IniSectionList sections; - if (ParseIniSafe(sections, "sdmc:/emummc/emummc.ini")) { + if (ParseIniSafe(sections, "emummc/emummc.ini")) { for (const auto §ion : sections){ /* Skip non-emummc sections */ if (std::strcmp(section.name, "emummc")) { @@ -215,7 +215,7 @@ namespace ams::nxboot { { IniSectionList sections; - if (ParseIniSafe(sections, "sdmc:/emusd/emusd.ini")) { + if (ParseIniSafe(sections, "emusd/emusd.ini")) { for (const auto §ion : sections){ /* Skip non-emummc sections */ if (std::strcmp(section.name, "emusd")) { @@ -431,7 +431,7 @@ namespace ams::nxboot { std::memcpy(warmboot_dst + 0x248, std::addressof(target_firmware), sizeof(target_firmware)); } else /* if (soc_type == fuse::SocType_Mariko) */ { /* Declare path for mariko warmboot files. */ - char warmboot_path[0x80] = "sdmc:/warmboot_mariko/wb_xx.bin"; + char warmboot_path[0x80] = "warmboot_mariko/wb_xx.bin"; auto UpdateWarmbootPath = [&warmboot_path](u8 fuses) { warmboot_path[0x19] = "0123456789abcdef"[(fuses >> 4) & 0xF]; @@ -477,7 +477,7 @@ namespace ams::nxboot { /* If we should, save the current warmboot firmware. */ UpdateWarmbootPath(expected_fuses); if (!IsFileExist(warmboot_path)) { - fs::CreateDirectory("sdmc:/warmboot_mariko"); + fs::CreateDirectory("warmboot_mariko"); fs::CreateFile(warmboot_path, warmboot_src_size); Result result; @@ -576,7 +576,7 @@ namespace ams::nxboot { /* Parse fields from exosphere.ini */ { IniSectionList sections; - if (ParseIniSafe(sections, "sdmc:/exosphere.ini")) { + if (ParseIniSafe(sections, "exosphere.ini")) { for (const auto §ion : sections) { /* We only care about the [exosphere] section. */ if (std::strcmp(section.name, "exosphere")) { @@ -651,7 +651,7 @@ namespace ams::nxboot { /* Parse usb setting from system_settings.ini */ { IniSectionList sections; - if (ParseIniSafe(sections, "sdmc:/atmosphere/config/system_settings.ini")) { + if (ParseIniSafe(sections, "atmosphere/config/system_settings.ini")) { for (const auto §ion : sections) { /* We only care about the [usb] section. */ if (std::strcmp(section.name, "usb")) { @@ -676,7 +676,7 @@ namespace ams::nxboot { { /* Try to use an sd card file, if present. */ fs::FileHandle exo_file; - if (R_SUCCEEDED(fs::OpenFile(std::addressof(exo_file), "sdmc:/atmosphere/exosphere.bin", fs::OpenMode_Read))) { + if (R_SUCCEEDED(fs::OpenFile(std::addressof(exo_file), "atmosphere/exosphere.bin", fs::OpenMode_Read))) { ON_SCOPE_EXIT { fs::CloseFile(exo_file); }; /* Note that we're using sd_exo. */ @@ -708,7 +708,7 @@ namespace ams::nxboot { { /* Try to use an sd card file, if present. */ fs::FileHandle mariko_program_file; - if (R_SUCCEEDED(fs::OpenFile(std::addressof(mariko_program_file), "sdmc:/atmosphere/mariko_fatal.bin", fs::OpenMode_Read))) { + if (R_SUCCEEDED(fs::OpenFile(std::addressof(mariko_program_file), "atmosphere/mariko_fatal.bin", fs::OpenMode_Read))) { ON_SCOPE_EXIT { fs::CloseFile(mariko_program_file); }; /* Note that we're using sd mariko fatal. */ @@ -754,7 +754,7 @@ namespace ams::nxboot { /* First parse from ini. */ { IniSectionList sections; - if (ParseIniSafe(sections, "sdmc:/atmosphere/config/stratosphere.ini")) { + if (ParseIniSafe(sections, "atmosphere/config/stratosphere.ini")) { for (const auto §ion : sections) { /* We only care about the [stratosphere] section. */ if (std::strcmp(section.name, "stratosphere")) { diff --git a/fusee/program/source/fusee_stratosphere.cpp b/fusee/program/source/fusee_stratosphere.cpp index 2ad85fb8d..1c0ccc868 100644 --- a/fusee/program/source/fusee_stratosphere.cpp +++ b/fusee/program/source/fusee_stratosphere.cpp @@ -769,7 +769,7 @@ namespace ams::nxboot { { /* Create kip dir path. */ char kip_path[0x120]; - std::memcpy(kip_path, "sdmc:/atmosphere/kips", 0x16); + std::memcpy(kip_path, "atmosphere/kips", 0x16); fs::DirectoryHandle kip_dir; if (R_SUCCEEDED(fs::OpenDirectory(std::addressof(kip_dir), kip_path))) { @@ -899,7 +899,7 @@ namespace ams::nxboot { /* Load mesosphere. */ s64 meso_size; - if (void *sd_meso = ReadFile(std::addressof(meso_size), "sdmc:/atmosphere/mesosphere.bin"); sd_meso != nullptr) { + if (void *sd_meso = ReadFile(std::addressof(meso_size), "atmosphere/mesosphere.bin"); sd_meso != nullptr) { std::memcpy(payload_data, sd_meso, meso_size); } else { meso_size = external_package.header.meso_size; @@ -910,7 +910,7 @@ namespace ams::nxboot { const InitialProcessHeader *emummc; s64 emummc_size; if (emummc_driver_enabled) { - emummc = static_cast(ReadFile(std::addressof(emummc_size), "sdmc:/atmosphere/emummc.kip")); + emummc = static_cast(ReadFile(std::addressof(emummc_size), "atmosphere/emummc.kip")); if (emummc == nullptr) { emummc = reinterpret_cast(external_package.kips + external_package.header.emummc_meta.offset); emummc_size = external_package.header.emummc_meta.size;