mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-09 22:56:35 +00:00
fusee_cpp: implement exosphere load/configuration
This commit is contained in:
parent
1dd0297db3
commit
e0a41e9d33
8 changed files with 236 additions and 13 deletions
|
@ -582,6 +582,10 @@ namespace ams::nxboot {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u16 GetDisplayLcdVendor() {
|
||||||
|
return g_lcd_vendor;
|
||||||
|
}
|
||||||
|
|
||||||
void ShowFatalError(const ams::impl::FatalErrorContext *f_ctx, const Result save_result) {
|
void ShowFatalError(const ams::impl::FatalErrorContext *f_ctx, const Result save_result) {
|
||||||
/* If needed, initialize the display. */
|
/* If needed, initialize the display. */
|
||||||
if (!IsDisplayInitialized()) {
|
if (!IsDisplayInitialized()) {
|
||||||
|
|
|
@ -26,6 +26,8 @@ namespace ams::nxboot {
|
||||||
void InitializeDisplay();
|
void InitializeDisplay();
|
||||||
void FinalizeDisplay();
|
void FinalizeDisplay();
|
||||||
|
|
||||||
|
u16 GetDisplayLcdVendor();
|
||||||
|
|
||||||
void ShowDisplay();
|
void ShowDisplay();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ namespace ams::nxboot {
|
||||||
file_size = std::min(IniFileSizeMax, file_size);
|
file_size = std::min(IniFileSizeMax, file_size);
|
||||||
|
|
||||||
/* Allocate memory for file. */
|
/* Allocate memory for file. */
|
||||||
char *buffer = static_cast<char *>(AllocateMemory(util::AlignUp(file_size + 1, 0x10)));
|
char *buffer = static_cast<char *>(AllocateAligned(util::AlignUp(file_size + 1, 0x10), 0x10));
|
||||||
buffer[file_size] = '\x00';
|
buffer[file_size] = '\x00';
|
||||||
|
|
||||||
/* Read file. */
|
/* Read file. */
|
||||||
|
@ -64,6 +64,7 @@ namespace ams::nxboot {
|
||||||
SectionName,
|
SectionName,
|
||||||
Key,
|
Key,
|
||||||
KvSpace,
|
KvSpace,
|
||||||
|
KvSpace2,
|
||||||
Value,
|
Value,
|
||||||
TrailingSpace,
|
TrailingSpace,
|
||||||
};
|
};
|
||||||
|
@ -120,20 +121,33 @@ namespace ams::nxboot {
|
||||||
} else if (c == '=') {
|
} else if (c == '=') {
|
||||||
buffer[i] = '\x00';
|
buffer[i] = '\x00';
|
||||||
|
|
||||||
val_start = buffer + i + 1;
|
state = State::KvSpace2;
|
||||||
|
|
||||||
state = State::Value;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case State::KvSpace:
|
case State::KvSpace:
|
||||||
if (c == '=') {
|
if (c == '=') {
|
||||||
val_start = buffer + i + 1;
|
state = State::KvSpace2;
|
||||||
|
|
||||||
state = State::Value;
|
|
||||||
} else if (!IsWhiteSpace(c)) {
|
} else if (!IsWhiteSpace(c)) {
|
||||||
return ParseIniResult_InvalidFormat;
|
return ParseIniResult_InvalidFormat;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case State::KvSpace2:
|
||||||
|
if (c == '\n') {
|
||||||
|
buffer[i] = '\x00';
|
||||||
|
|
||||||
|
auto *entry = AllocateObject<IniKeyValueEntry>();
|
||||||
|
entry->key = key_start;
|
||||||
|
entry->value = buffer + i;
|
||||||
|
|
||||||
|
cur_sec->kv_list.push_back(*entry);
|
||||||
|
|
||||||
|
state = State::Newline;
|
||||||
|
} else if (!IsWhiteSpace(c)) {
|
||||||
|
val_start = buffer + i;
|
||||||
|
|
||||||
|
state = State::Value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case State::Value:
|
case State::Value:
|
||||||
if (IsWhiteSpace(c) || c == '\n') {
|
if (IsWhiteSpace(c) || c == '\n') {
|
||||||
buffer[i] = '\x00';
|
buffer[i] = '\x00';
|
||||||
|
|
|
@ -26,6 +26,10 @@ namespace ams::nxboot {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InitializeSecureMonitorMailbox() {
|
||||||
|
std::memset(std::addressof(GetSecureMonitorParameters()), 0, sizeof(GetSecureMonitorParameters()));
|
||||||
|
}
|
||||||
|
|
||||||
void WaitSecureMonitorState(pkg1::SecureMonitorState state) {
|
void WaitSecureMonitorState(pkg1::SecureMonitorState state) {
|
||||||
auto &secmon_params = GetSecureMonitorParameters();
|
auto &secmon_params = GetSecureMonitorParameters();
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
|
|
||||||
namespace ams::nxboot {
|
namespace ams::nxboot {
|
||||||
|
|
||||||
|
void InitializeSecureMonitorMailbox();
|
||||||
|
|
||||||
void WaitSecureMonitorState(pkg1::SecureMonitorState state);
|
void WaitSecureMonitorState(pkg1::SecureMonitorState state);
|
||||||
void SetBootloaderState(pkg1::BootloaderState state);
|
void SetBootloaderState(pkg1::BootloaderState state);
|
||||||
|
|
||||||
|
|
|
@ -70,8 +70,8 @@ namespace ams::nxboot {
|
||||||
u8 mariko_fatal[0x1C000]; /* 0x004000-0x020000 */
|
u8 mariko_fatal[0x1C000]; /* 0x004000-0x020000 */
|
||||||
u8 ovl_mtc_erista[0x14000]; /* 0x020000-0x034000 */
|
u8 ovl_mtc_erista[0x14000]; /* 0x020000-0x034000 */
|
||||||
u8 ovl_mtc_mariko[0x14000]; /* 0x034000-0x048000 */
|
u8 ovl_mtc_mariko[0x14000]; /* 0x034000-0x048000 */
|
||||||
u8 exosphere[0x10000]; /* 0x048000-0x058000 */
|
u8 exosphere[0xE000]; /* 0x048000-0x056000 */
|
||||||
u8 mesosphere[0xA8000]; /* 0x058000-0x100000 */
|
u8 mesosphere[0xAA000]; /* 0x056000-0x100000 */
|
||||||
u8 kips[3_MB]; /* 0x100000-0x400000 */
|
u8 kips[3_MB]; /* 0x100000-0x400000 */
|
||||||
u8 splash_screen_fb[FrameBufferSize]; /* 0x400000-0x7C0000 */
|
u8 splash_screen_fb[FrameBufferSize]; /* 0x400000-0x7C0000 */
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#include <exosphere.hpp>
|
#include <exosphere.hpp>
|
||||||
|
#include <exosphere/secmon/secmon_monitor_context.hpp>
|
||||||
#include "fusee_key_derivation.hpp"
|
#include "fusee_key_derivation.hpp"
|
||||||
#include "fusee_secondary_archive.hpp"
|
#include "fusee_secondary_archive.hpp"
|
||||||
#include "fusee_setup_horizon.hpp"
|
#include "fusee_setup_horizon.hpp"
|
||||||
|
@ -91,6 +92,23 @@ namespace ams::nxboot {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 ParseDecimalInteger(const char *s) {
|
||||||
|
u32 x = 0;
|
||||||
|
while (true) {
|
||||||
|
const char c = *(s++);
|
||||||
|
|
||||||
|
if (c == '\x00') {
|
||||||
|
return x;
|
||||||
|
} else {
|
||||||
|
x *= 10;
|
||||||
|
|
||||||
|
if ('0' <= c && c <= '9') {
|
||||||
|
x += c - '0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool IsDirectoryExist(const char *path) {
|
bool IsDirectoryExist(const char *path) {
|
||||||
fs::DirectoryEntryType entry_type;
|
fs::DirectoryEntryType entry_type;
|
||||||
bool archive;
|
bool archive;
|
||||||
|
@ -505,7 +523,7 @@ namespace ams::nxboot {
|
||||||
|
|
||||||
/* Allocate memory. */
|
/* Allocate memory. */
|
||||||
warmboot_src_size = static_cast<size_t>(size);
|
warmboot_src_size = static_cast<size_t>(size);
|
||||||
void *tmp = AllocateMemory(warmboot_src_size);
|
void *tmp = AllocateAligned(warmboot_src_size, 0x10);
|
||||||
|
|
||||||
/* Read the file. */
|
/* Read the file. */
|
||||||
if (R_FAILED(fs::ReadFile(file, 0, tmp, warmboot_src_size))) {
|
if (R_FAILED(fs::ReadFile(file, 0, tmp, warmboot_src_size))) {
|
||||||
|
@ -542,6 +560,184 @@ namespace ams::nxboot {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConfigureExosphere(fuse::SocType soc_type, ams::TargetFirmware target_firmware, bool emummc_enabled) {
|
||||||
|
/* Get monitor configuration. */
|
||||||
|
auto &storage_ctx = *secmon::MemoryRegionPhysicalDramMonitorConfiguration.GetPointer<secmon::SecureMonitorStorageConfiguration>();
|
||||||
|
std::memset(std::addressof(storage_ctx), 0, sizeof(storage_ctx));
|
||||||
|
|
||||||
|
/* Set magic. */
|
||||||
|
storage_ctx.magic = secmon::SecureMonitorStorageConfiguration::Magic;
|
||||||
|
|
||||||
|
/* Set some defaults. */
|
||||||
|
storage_ctx.target_firmware = target_firmware;
|
||||||
|
storage_ctx.lcd_vendor = GetDisplayLcdVendor();
|
||||||
|
storage_ctx.emummc_cfg = g_emummc_cfg;
|
||||||
|
storage_ctx.flags[0] = secmon::SecureMonitorConfigurationFlag_Default;
|
||||||
|
storage_ctx.flags[1] = secmon::SecureMonitorConfigurationFlag_None;
|
||||||
|
storage_ctx.log_port = uart::Port_ReservedDebug;
|
||||||
|
storage_ctx.log_baud_rate = 115200;
|
||||||
|
|
||||||
|
/* Parse fields from exosphere.ini */
|
||||||
|
{
|
||||||
|
IniSectionList sections;
|
||||||
|
if (ParseIniSafe(sections, "sdmc:/exosphere.ini")) {
|
||||||
|
for (const auto §ion : sections) {
|
||||||
|
/* We only care about the [exosphere] section. */
|
||||||
|
if (std::strcmp(section.name, "exosphere")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle individual fields. */
|
||||||
|
for (const auto &entry : section.kv_list) {
|
||||||
|
if (std::strcmp(entry.key, "debugmode") == 0) {
|
||||||
|
if (entry.value[0] == '1') {
|
||||||
|
storage_ctx.flags[0] |= secmon::SecureMonitorConfigurationFlag_IsDevelopmentFunctionEnabledForKernel;
|
||||||
|
} else {
|
||||||
|
storage_ctx.flags[0] &= ~secmon::SecureMonitorConfigurationFlag_IsDevelopmentFunctionEnabledForKernel;
|
||||||
|
}
|
||||||
|
} else if (std::strcmp(entry.key, "debugmode_user") == 0) {
|
||||||
|
if (entry.value[0] == '1') {
|
||||||
|
storage_ctx.flags[0] |= secmon::SecureMonitorConfigurationFlag_IsDevelopmentFunctionEnabledForUser;
|
||||||
|
} else {
|
||||||
|
storage_ctx.flags[0] &= ~secmon::SecureMonitorConfigurationFlag_IsDevelopmentFunctionEnabledForUser;
|
||||||
|
}
|
||||||
|
} else if (std::strcmp(entry.key, "disable_user_exception_handlers") == 0) {
|
||||||
|
if (entry.value[0] == '1') {
|
||||||
|
storage_ctx.flags[0] |= secmon::SecureMonitorConfigurationFlag_DisableUserModeExceptionHandlers;
|
||||||
|
} else {
|
||||||
|
storage_ctx.flags[0] &= ~secmon::SecureMonitorConfigurationFlag_DisableUserModeExceptionHandlers;
|
||||||
|
}
|
||||||
|
} else if (std::strcmp(entry.key, "enable_user_pmu_access") == 0) {
|
||||||
|
if (entry.value[0] == '1') {
|
||||||
|
storage_ctx.flags[0] |= secmon::SecureMonitorConfigurationFlag_EnableUserModePerformanceCounterAccess;
|
||||||
|
} else {
|
||||||
|
storage_ctx.flags[0] &= ~secmon::SecureMonitorConfigurationFlag_EnableUserModePerformanceCounterAccess;
|
||||||
|
}
|
||||||
|
} else if (std::strcmp(entry.key, "blank_prodinfo_sysmmc") == 0) {
|
||||||
|
if (entry.value[0] == '1' && !emummc_enabled) {
|
||||||
|
storage_ctx.flags[0] |= secmon::SecureMonitorConfigurationFlag_ShouldUseBlankCalibrationBinary;
|
||||||
|
} else {
|
||||||
|
storage_ctx.flags[0] &= ~secmon::SecureMonitorConfigurationFlag_ShouldUseBlankCalibrationBinary;
|
||||||
|
}
|
||||||
|
} else if (std::strcmp(entry.key, "blank_prodinfo_emummc") == 0) {
|
||||||
|
if (entry.value[0] == '1' && emummc_enabled) {
|
||||||
|
storage_ctx.flags[0] |= secmon::SecureMonitorConfigurationFlag_ShouldUseBlankCalibrationBinary;
|
||||||
|
} else {
|
||||||
|
storage_ctx.flags[0] &= ~secmon::SecureMonitorConfigurationFlag_ShouldUseBlankCalibrationBinary;
|
||||||
|
}
|
||||||
|
} else if (std::strcmp(entry.key, "allow_writing_to_cal_sysmmc") == 0) {
|
||||||
|
if (entry.value[0] == '1') {
|
||||||
|
storage_ctx.flags[0] |= secmon::SecureMonitorConfigurationFlag_AllowWritingToCalibrationBinarySysmmc;
|
||||||
|
} else {
|
||||||
|
storage_ctx.flags[0] &= ~secmon::SecureMonitorConfigurationFlag_AllowWritingToCalibrationBinarySysmmc;
|
||||||
|
}
|
||||||
|
} else if (std::strcmp(entry.key, "log_port") == 0) {
|
||||||
|
const u32 log_port = ParseDecimalInteger(entry.value);
|
||||||
|
if (0 <= log_port && log_port < 4) {
|
||||||
|
storage_ctx.log_port = log_port;
|
||||||
|
}
|
||||||
|
} else if (std::strcmp(entry.key, "log_baud_rate") == 0) {
|
||||||
|
storage_ctx.log_baud_rate = ParseDecimalInteger(entry.value);
|
||||||
|
} else if (std::strcmp(entry.key, "log_inverted") == 0) {
|
||||||
|
if (entry.value[0] == 1) {
|
||||||
|
storage_ctx.log_flags |= uart::Flag_Inverted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse usb setting from system_settings.ini */
|
||||||
|
{
|
||||||
|
IniSectionList sections;
|
||||||
|
if (ParseIniSafe(sections, "sdmc:/atmosphere/config/system_settings.ini")) {
|
||||||
|
for (const auto §ion : sections) {
|
||||||
|
/* We only care about the [usb] section. */
|
||||||
|
if (std::strcmp(section.name, "usb")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle individual fields. */
|
||||||
|
for (const auto &entry : section.kv_list) {
|
||||||
|
if (std::strcmp(entry.key, "usb30_force_enabled") == 0) {
|
||||||
|
if (std::strcmp(entry.value, "u8!0x1") == 0) {
|
||||||
|
storage_ctx.flags[0] |= secmon::SecureMonitorConfigurationFlag_ForceEnableUsb30;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy exosphere. */
|
||||||
|
void *exosphere_dst = reinterpret_cast<void *>(0x40030000);
|
||||||
|
bool use_sd_exo = false;
|
||||||
|
{
|
||||||
|
/* 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))) {
|
||||||
|
ON_SCOPE_EXIT { fs::CloseFile(exo_file); };
|
||||||
|
|
||||||
|
/* Note that we're using sd_exo. */
|
||||||
|
use_sd_exo = true;
|
||||||
|
|
||||||
|
Result result;
|
||||||
|
|
||||||
|
/* Get the size. */
|
||||||
|
s64 size;
|
||||||
|
if (R_FAILED((result = fs::GetFileSize(std::addressof(size), exo_file))) || size > sizeof(GetSecondaryArchive().exosphere)) {
|
||||||
|
ShowFatalError("Invalid SD exosphere size: 0x%08" PRIx32 ", %" PRIx64 "!\n", result.GetValue(), static_cast<u64>(size));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read the file. */
|
||||||
|
if (R_FAILED((result = fs::ReadFile(exo_file, 0, exosphere_dst, size)))) {
|
||||||
|
ShowFatalError("Failed to read SD exosphere: 0x%08" PRIx32 "!\n", result.GetValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!use_sd_exo) {
|
||||||
|
std::memcpy(exosphere_dst, GetSecondaryArchive().exosphere, sizeof(GetSecondaryArchive().exosphere));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy mariko fatal. */
|
||||||
|
if (soc_type == fuse::SocType_Mariko) {
|
||||||
|
u8 *mariko_fatal_dst = secmon::MemoryRegionPhysicalMarikoProgramImage.GetPointer<u8>();
|
||||||
|
bool use_sd_mariko_fatal = false;
|
||||||
|
{
|
||||||
|
/* 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))) {
|
||||||
|
ON_SCOPE_EXIT { fs::CloseFile(mariko_program_file); };
|
||||||
|
|
||||||
|
/* Note that we're using sd_exo. */
|
||||||
|
use_sd_exo = true;
|
||||||
|
|
||||||
|
Result result;
|
||||||
|
|
||||||
|
/* Get the size. */
|
||||||
|
s64 size;
|
||||||
|
if (R_FAILED((result = fs::GetFileSize(std::addressof(size), mariko_program_file))) || size > sizeof(GetSecondaryArchive().mariko_fatal)) {
|
||||||
|
ShowFatalError("Invalid SD exosphere size: 0x%08" PRIx32 ", %" PRIx64 "!\n", result.GetValue(), static_cast<u64>(size));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read the file. */
|
||||||
|
if (R_FAILED((result = fs::ReadFile(mariko_program_file, 0, mariko_fatal_dst, size)))) {
|
||||||
|
ShowFatalError("Failed to read SD exosphere: 0x%08" PRIx32 "!\n", result.GetValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear the remainder. */
|
||||||
|
std::memset(mariko_fatal_dst + size, 0, sizeof(GetSecondaryArchive().mariko_fatal) - size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!use_sd_mariko_fatal) {
|
||||||
|
std::memcpy(mariko_fatal_dst, GetSecondaryArchive().mariko_fatal, sizeof(GetSecondaryArchive().mariko_fatal));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupAndStartHorizon() {
|
void SetupAndStartHorizon() {
|
||||||
|
@ -571,7 +767,8 @@ namespace ams::nxboot {
|
||||||
/* Setup warmboot firmware. */
|
/* Setup warmboot firmware. */
|
||||||
LoadWarmbootFirmware(soc_type, target_firmware, package1);
|
LoadWarmbootFirmware(soc_type, target_firmware, package1);
|
||||||
|
|
||||||
/* TODO: Setup exosphere. */
|
/* Setup exosphere. */
|
||||||
|
ConfigureExosphere(soc_type, target_firmware, emummc_enabled);
|
||||||
|
|
||||||
/* TODO: Start CPU. */
|
/* TODO: Start CPU. */
|
||||||
/* NOTE: Security Engine unusable past this point. */
|
/* NOTE: Security Engine unusable past this point. */
|
||||||
|
|
|
@ -47,9 +47,9 @@ def main(argc, argv):
|
||||||
# Write Mariko MTC
|
# Write Mariko MTC
|
||||||
f.write(get_overlay(data, 2))
|
f.write(get_overlay(data, 2))
|
||||||
# TODO: Write exosphere
|
# TODO: Write exosphere
|
||||||
f.write('\xCC'*0x10000)
|
f.write('\xCC'*0xE000)
|
||||||
# TODO: Write mesosphere
|
# TODO: Write mesosphere
|
||||||
f.write('\xCC'*0xA8000)
|
f.write('\xCC'*0xAA000)
|
||||||
# TODO: Write kips
|
# TODO: Write kips
|
||||||
f.write('\xCC'*0x300000)
|
f.write('\xCC'*0x300000)
|
||||||
# Write Splash Screen
|
# Write Splash Screen
|
||||||
|
|
Loading…
Reference in a new issue