mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-12-24 03:06:17 +00:00
set.mitm: fake compatibility for usb!usb30_force_enabled on 9.0.0+ (#1391)
* set.mitm: fake compatibility for usb!usb30_force_enabled on 9.0.0+ * set.mitm: add value meaning comment for usb!usb30_force_enabled * loader: pretend to be polite about patch ordering
This commit is contained in:
parent
c9015581ca
commit
a6729171d3
14 changed files with 205 additions and 24 deletions
|
@ -1,9 +1,13 @@
|
|||
; Disable uploading error reports to Nintendo
|
||||
[eupld]
|
||||
; Disable uploading error reports to Nintendo
|
||||
; upload_enabled = u8!0x0
|
||||
[usb]
|
||||
; Enable USB 3.0 superspeed for homebrew
|
||||
; 0 = USB 3.0 support is system default (usually disabled), 1 = USB 3.0 support is enabled.
|
||||
; usb30_force_enabled = u8!0x0
|
||||
[ro]
|
||||
; Control whether RO should ease its validation of NROs.
|
||||
; (note: this is normally not necessary, and ips patches can be used.)
|
||||
[ro]
|
||||
; ease_nro_restriction = u8!0x1
|
||||
; Atmosphere custom settings
|
||||
[atmosphere]
|
||||
|
|
|
@ -286,6 +286,10 @@ namespace ams::secmon::smc {
|
|||
/* Get the log configuration. */
|
||||
args.r[1] = (static_cast<u64>(static_cast<u8>(secmon::GetLogPort())) << 32) | static_cast<u64>(secmon::GetLogBaudRate());
|
||||
break;
|
||||
case ConfigItem::ExosphereForceEnableUsb30:
|
||||
/* Get whether usb 3.0 should be force-enabled. */
|
||||
args.r[1] = GetSecmonConfiguration().IsUsb30ForceEnabled();
|
||||
break;
|
||||
default:
|
||||
return SmcResult::InvalidArgument;
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ namespace ams::secmon::smc {
|
|||
ExosphereEmummcType = 65007,
|
||||
ExospherePayloadAddress = 65008,
|
||||
ExosphereLogConfiguration = 65009,
|
||||
ExosphereForceEnableUsb30 = 65010,
|
||||
};
|
||||
|
||||
SmcResult SmcGetConfigUser(SmcArguments &args);
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#define EXOSPHERE_FLAG_ENABLE_USERMODE_PMU_ACCESS (1 << 4u)
|
||||
#define EXOSPHERE_FLAG_BLANK_PRODINFO (1 << 5u)
|
||||
#define EXOSPHERE_FLAG_ALLOW_WRITING_TO_CAL_SYSMMC (1 << 6u)
|
||||
#define EXOSPHERE_FLAG_FORCE_ENABLE_USB_30 (1 << 7u)
|
||||
|
||||
#define EXOSPHERE_LOG_FLAG_INVERTED (1 << 0u)
|
||||
|
||||
|
|
|
@ -256,6 +256,24 @@ static int stratosphere_ini_handler(void *user, const char *section, const char
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int system_settings_ini_handler(void *user, const char *section, const char *name, const char *value) {
|
||||
uint32_t *flags = (uint32_t *)user;
|
||||
if (strcmp(section, "usb") == 0) {
|
||||
if (strcmp(name, "usb30_force_enabled") == 0) {
|
||||
if (strcmp(value, "u8!0x1") == 0) {
|
||||
*flags |= EXOSPHERE_FLAG_FORCE_ENABLE_USB_30;
|
||||
} else if (strcmp(value, "u8!0x0") == 0) {
|
||||
*flags &= ~(EXOSPHERE_FLAG_FORCE_ENABLE_USB_30);
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool is_nca_present(const char *nca_name) {
|
||||
char path[0x100];
|
||||
snprintf(path, sizeof(path), "system:/contents/registered/%s.nca", nca_name);
|
||||
|
@ -537,6 +555,15 @@ static void nxboot_configure_exosphere(uint32_t target_firmware, unsigned int ke
|
|||
/* Apply lcd vendor. */
|
||||
exo_cfg.lcd_vendor = display_get_lcd_vendor();
|
||||
|
||||
/* Read and parse system settings.ini to determine usb 3.0 enable. */
|
||||
char *settings_ini = calloc(1, 0x20000);
|
||||
if (read_from_file(settings_ini, 0x1FFFF, "atmosphere/config/system_settings.ini")) {
|
||||
if (ini_parse_string(settings_ini, system_settings_ini_handler, &exo_cfg.flags[0]) < 0) {
|
||||
fatal_error("[NXBOOT] Failed to parse system_settings.ini!\n");
|
||||
}
|
||||
}
|
||||
free(settings_ini);
|
||||
|
||||
if ((exo_cfg.target_firmware < ATMOSPHERE_TARGET_FIRMWARE_MIN) || (exo_cfg.target_firmware > ATMOSPHERE_TARGET_FIRMWARE_MAX)) {
|
||||
fatal_error("[NXBOOT] Invalid Exosphere target firmware!\n");
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ namespace ams::secmon {
|
|||
SecureMonitorConfigurationFlag_EnableUserModePerformanceCounterAccess = (1u << 4),
|
||||
SecureMonitorConfigurationFlag_ShouldUseBlankCalibrationBinary = (1u << 5),
|
||||
SecureMonitorConfigurationFlag_AllowWritingToCalibrationBinarySysmmc = (1u << 6),
|
||||
SecureMonitorConfigurationFlag_ForceEnableUsb30 = (1u << 7),
|
||||
|
||||
SecureMonitorConfigurationFlag_Default = SecureMonitorConfigurationFlag_IsDevelopmentFunctionEnabledForKernel,
|
||||
};
|
||||
|
@ -101,6 +102,7 @@ namespace ams::secmon {
|
|||
constexpr bool EnableUserModePerformanceCounterAccess() const { return (this->flags[0] & SecureMonitorConfigurationFlag_EnableUserModePerformanceCounterAccess) != 0; }
|
||||
constexpr bool ShouldUseBlankCalibrationBinary() const { return (this->flags[0] & SecureMonitorConfigurationFlag_ShouldUseBlankCalibrationBinary) != 0; }
|
||||
constexpr bool AllowWritingToCalibrationBinarySysmmc() const { return (this->flags[0] & SecureMonitorConfigurationFlag_AllowWritingToCalibrationBinarySysmmc) != 0; }
|
||||
constexpr bool IsUsb30ForceEnabled() const { return (this->flags[0] & SecureMonitorConfigurationFlag_ForceEnableUsb30) != 0; }
|
||||
|
||||
constexpr bool IsDevelopmentFunctionEnabled(bool for_kern) const { return for_kern ? this->IsDevelopmentFunctionEnabledForKernel() : this->IsDevelopmentFunctionEnabledForUser(); }
|
||||
};
|
||||
|
|
|
@ -78,6 +78,10 @@ namespace ams::spl {
|
|||
return ::ams::spl::GetConfigBool(::ams::spl::ConfigItem::DisableProgramVerification);
|
||||
}
|
||||
|
||||
inline bool IsUsb30ForceEnabled() {
|
||||
return ::ams::spl::GetConfigBool(::ams::spl::ConfigItem::ExosphereForceEnableUsb30);
|
||||
}
|
||||
|
||||
Result SetBootReason(BootReasonValue boot_reason);
|
||||
Result GetBootReason(BootReasonValue *out);
|
||||
|
||||
|
|
|
@ -223,26 +223,30 @@ namespace ams::spl {
|
|||
Package2Hash = 17,
|
||||
|
||||
/* Extension config items for exosphere. */
|
||||
ExosphereApiVersion = 65000,
|
||||
ExosphereNeedsReboot = 65001,
|
||||
ExosphereNeedsShutdown = 65002,
|
||||
ExosphereGitCommitHash = 65003,
|
||||
ExosphereHasRcmBugPatch = 65004,
|
||||
ExosphereBlankProdInfo = 65005,
|
||||
ExosphereAllowCalWrites = 65006,
|
||||
ExosphereEmummcType = 65007,
|
||||
ExospherePayloadAddress = 65008,
|
||||
ExosphereApiVersion = 65000,
|
||||
ExosphereNeedsReboot = 65001,
|
||||
ExosphereNeedsShutdown = 65002,
|
||||
ExosphereGitCommitHash = 65003,
|
||||
ExosphereHasRcmBugPatch = 65004,
|
||||
ExosphereBlankProdInfo = 65005,
|
||||
ExosphereAllowCalWrites = 65006,
|
||||
ExosphereEmummcType = 65007,
|
||||
ExospherePayloadAddress = 65008,
|
||||
ExosphereLogConfiguration = 65009,
|
||||
ExosphereForceEnableUsb30 = 65010,
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/* Extensions to libnx spl config item enum. */
|
||||
constexpr inline SplConfigItem SplConfigItem_ExosphereApiVersion = static_cast<SplConfigItem>(65000);
|
||||
constexpr inline SplConfigItem SplConfigItem_ExosphereNeedsReboot = static_cast<SplConfigItem>(65001);
|
||||
constexpr inline SplConfigItem SplConfigItem_ExosphereNeedsShutdown = static_cast<SplConfigItem>(65002);
|
||||
constexpr inline SplConfigItem SplConfigItem_ExosphereGitCommitHash = static_cast<SplConfigItem>(65003);
|
||||
constexpr inline SplConfigItem SplConfigItem_ExosphereHasRcmBugPatch = static_cast<SplConfigItem>(65004);
|
||||
constexpr inline SplConfigItem SplConfigItem_ExosphereBlankProdInfo = static_cast<SplConfigItem>(65005);
|
||||
constexpr inline SplConfigItem SplConfigItem_ExosphereAllowCalWrites = static_cast<SplConfigItem>(65006);
|
||||
constexpr inline SplConfigItem SplConfigItem_ExosphereEmummcType = static_cast<SplConfigItem>(65007);
|
||||
constexpr inline SplConfigItem SplConfigItem_ExospherePayloadAddress = static_cast<SplConfigItem>(65008);
|
||||
constexpr inline SplConfigItem SplConfigItem_ExosphereApiVersion = static_cast<SplConfigItem>(65000);
|
||||
constexpr inline SplConfigItem SplConfigItem_ExosphereNeedsReboot = static_cast<SplConfigItem>(65001);
|
||||
constexpr inline SplConfigItem SplConfigItem_ExosphereNeedsShutdown = static_cast<SplConfigItem>(65002);
|
||||
constexpr inline SplConfigItem SplConfigItem_ExosphereGitCommitHash = static_cast<SplConfigItem>(65003);
|
||||
constexpr inline SplConfigItem SplConfigItem_ExosphereHasRcmBugPatch = static_cast<SplConfigItem>(65004);
|
||||
constexpr inline SplConfigItem SplConfigItem_ExosphereBlankProdInfo = static_cast<SplConfigItem>(65005);
|
||||
constexpr inline SplConfigItem SplConfigItem_ExosphereAllowCalWrites = static_cast<SplConfigItem>(65006);
|
||||
constexpr inline SplConfigItem SplConfigItem_ExosphereEmummcType = static_cast<SplConfigItem>(65007);
|
||||
constexpr inline SplConfigItem SplConfigItem_ExospherePayloadAddress = static_cast<SplConfigItem>(65008);
|
||||
constexpr inline SplConfigItem SplConfigItem_ExosphereLogConfiguration = static_cast<SplConfigItem>(65009);
|
||||
constexpr inline SplConfigItem SplConfigItem_ExosphereForceEnableUsb30 = static_cast<SplConfigItem>(65010);
|
||||
|
|
|
@ -307,6 +307,10 @@ namespace ams::boot2 {
|
|||
});
|
||||
}
|
||||
|
||||
bool IsUsbRequiredToMountSdCard() {
|
||||
return hos::GetVersion() >= hos::Version_9_0_0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Boot2 API. */
|
||||
|
@ -347,8 +351,10 @@ namespace ams::boot2 {
|
|||
/* Launch pcv. */
|
||||
LaunchProgram(nullptr, ncm::ProgramLocation::Make(ncm::SystemProgramId::Pcv, ncm::StorageId::BuiltInSystem), 0);
|
||||
|
||||
/* Launch usb. */
|
||||
LaunchProgram(nullptr, ncm::ProgramLocation::Make(ncm::SystemProgramId::Usb, ncm::StorageId::BuiltInSystem), 0);
|
||||
/* On 9.0.0+, FS depends on the USB sysmodule having been launched in order to mount the SD card. */
|
||||
if (IsUsbRequiredToMountSdCard()) {
|
||||
LaunchProgram(nullptr, ncm::ProgramLocation::Make(ncm::SystemProgramId::Usb, ncm::StorageId::BuiltInSystem), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for the SD card required services to be ready. */
|
||||
|
@ -371,6 +377,11 @@ namespace ams::boot2 {
|
|||
void LaunchPostSdCardBootPrograms() {
|
||||
/* This code is normally run by boot2. */
|
||||
|
||||
/* Launch the usb system module, if we haven't already. */
|
||||
if (!IsUsbRequiredToMountSdCard()) {
|
||||
LaunchProgram(nullptr, ncm::ProgramLocation::Make(ncm::SystemProgramId::Usb, ncm::StorageId::BuiltInSystem), 0);
|
||||
}
|
||||
|
||||
/* Find out whether we are maintenance mode. */
|
||||
const bool maintenance = IsMaintenanceMode();
|
||||
if (maintenance) {
|
||||
|
|
|
@ -310,6 +310,9 @@ namespace ams::settings::fwdbg {
|
|||
/* Disable uploading error reports to Nintendo. */
|
||||
R_ABORT_UNLESS(ParseSettingsItemValue("eupld", "upload_enabled", "u8!0x0"));
|
||||
|
||||
/* Enable USB 3.0 superspeed for homebrew */
|
||||
R_ABORT_UNLESS(ParseSettingsItemValue("usb", "usb30_force_enabled", spl::IsUsb30ForceEnabled() ? "u8!0x1" : "u8!0x0"));
|
||||
|
||||
/* Control whether RO should ease its validation of NROs. */
|
||||
/* (note: this is normally not necessary, and ips patches can be used.) */
|
||||
R_ABORT_UNLESS(ParseSettingsItemValue("ro", "ease_nro_restriction", "u8!0x1"));
|
||||
|
|
37
stratosphere/loader/source/ldr_embedded_usb_patches.inc
Normal file
37
stratosphere/loader/source/ldr_embedded_usb_patches.inc
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2021 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Patch fallback case to mov w0, #1 rather than retrieving settings flag. */
|
||||
constexpr inline const EmbeddedPatchEntry Usb30ForceEnablePatches_9_0_0[] = {
|
||||
{ 0x521C, "\x20\x00\x80\x52", 4 },
|
||||
};
|
||||
|
||||
/* Patch fallback case to mov w0, #1 rather than retrieving settings flag. */
|
||||
constexpr inline const EmbeddedPatchEntry Usb30ForceEnablePatches_10_0_0[] = {
|
||||
{ 0x5494, "\x20\x00\x80\x52", 4 },
|
||||
};
|
||||
|
||||
/* Patch getter functions to return 1. */
|
||||
constexpr inline const EmbeddedPatchEntry Usb30ForceEnablePatches_11_0_0[] = {
|
||||
{ 0x85DC, "\x20\x00\x80\x52\xC0\x03\x5F\xD6", 8 },
|
||||
{ 0x866C, "\x20\x00\x80\x52\xC0\x03\x5F\xD6", 8 },
|
||||
};
|
||||
|
||||
constexpr inline const EmbeddedPatch Usb30ForceEnablePatches[] = {
|
||||
{ ParseModuleId("C0D3F4E87E8B0FE9BBE9F1968A20767F3DC08E03"), util::size(Usb30ForceEnablePatches_9_0_0), Usb30ForceEnablePatches_9_0_0 },
|
||||
{ ParseModuleId("B9C700CA8335F8BAA0D2041D8D09F772890BA988"), util::size(Usb30ForceEnablePatches_10_0_0), Usb30ForceEnablePatches_10_0_0 },
|
||||
{ ParseModuleId("95BAF06A69650C215A5DD50CF8BD2A603E7AD3C2"), util::size(Usb30ForceEnablePatches_11_0_0), Usb30ForceEnablePatches_11_0_0 },
|
||||
};
|
|
@ -30,8 +30,12 @@ namespace ams::ldr {
|
|||
constexpr const char * const LoaderSdMountName = "#amsldr-sdpatch";
|
||||
static_assert(sizeof(LoaderSdMountName) <= fs::MountNameLengthMax);
|
||||
|
||||
os::Mutex g_ldr_sd_lock(false);
|
||||
bool g_mounted_sd;
|
||||
constinit os::SdkMutex g_ldr_sd_lock;
|
||||
constinit bool g_mounted_sd;
|
||||
|
||||
constinit os::SdkMutex g_embedded_patch_lock;
|
||||
constinit bool g_got_embedded_patch_settings;
|
||||
constinit bool g_force_enable_usb30;
|
||||
|
||||
bool EnsureSdCardMounted() {
|
||||
std::scoped_lock lk(g_ldr_sd_lock);
|
||||
|
@ -51,6 +55,59 @@ namespace ams::ldr {
|
|||
return (g_mounted_sd = true);
|
||||
}
|
||||
|
||||
bool IsUsb30ForceEnabled() {
|
||||
std::scoped_lock lk(g_embedded_patch_lock);
|
||||
|
||||
if (!g_got_embedded_patch_settings) {
|
||||
g_force_enable_usb30 = spl::IsUsb30ForceEnabled();
|
||||
g_got_embedded_patch_settings = true;
|
||||
}
|
||||
|
||||
return g_force_enable_usb30;
|
||||
}
|
||||
|
||||
consteval u8 ParseNybble(char c) {
|
||||
AMS_ASSUME(('0' <= c && c <= '9') || ('A' <= c && c <= 'F') || ('a' <= c && c <= 'f'));
|
||||
if ('0' <= c && c <= '9') {
|
||||
return c - '0' + 0x0;
|
||||
} else if ('A' <= c && c <= 'F') {
|
||||
return c - 'A' + 0xA;
|
||||
} else /* if ('a' <= c && c <= 'f') */ {
|
||||
return c - 'a' + 0xa;
|
||||
}
|
||||
}
|
||||
|
||||
consteval ro::ModuleId ParseModuleId(const char *str) {
|
||||
/* Parse a static module id. */
|
||||
ro::ModuleId module_id = {};
|
||||
|
||||
size_t ofs = 0;
|
||||
while (str[0] != 0) {
|
||||
AMS_ASSUME(ofs < sizeof(module_id));
|
||||
AMS_ASSUME(str[1] != 0);
|
||||
|
||||
module_id.build_id[ofs] = (ParseNybble(str[0]) << 4) | (ParseNybble(str[1]) << 0);
|
||||
|
||||
str += 2;
|
||||
ofs++;
|
||||
}
|
||||
|
||||
return module_id;
|
||||
}
|
||||
|
||||
struct EmbeddedPatchEntry {
|
||||
uintptr_t offset;
|
||||
const void * const data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct EmbeddedPatch {
|
||||
ro::ModuleId module_id;
|
||||
size_t num_entries;
|
||||
const EmbeddedPatchEntry *entries;
|
||||
};
|
||||
|
||||
#include "ldr_embedded_usb_patches.inc"
|
||||
|
||||
}
|
||||
|
||||
|
@ -65,4 +122,24 @@ namespace ams::ldr {
|
|||
ams::patcher::LocateAndApplyIpsPatchesToModule(LoaderSdMountName, NsoPatchesDirectory, NsoPatchesProtectedSize, NsoPatchesProtectedOffset, &module_id, reinterpret_cast<u8 *>(mapped_nso), mapped_size);
|
||||
}
|
||||
|
||||
/* Apply embedded patches. */
|
||||
void ApplyEmbeddedPatchesToModule(const u8 *build_id, uintptr_t mapped_nso, size_t mapped_size) {
|
||||
/* Make module id. */
|
||||
ro::ModuleId module_id;
|
||||
std::memcpy(&module_id.build_id, build_id, sizeof(module_id.build_id));
|
||||
|
||||
if (IsUsb30ForceEnabled()) {
|
||||
for (const auto &patch : Usb30ForceEnablePatches) {
|
||||
if (std::memcmp(std::addressof(patch.module_id), std::addressof(module_id), sizeof(module_id)) == 0) {
|
||||
for (size_t i = 0; i < patch.num_entries; ++i) {
|
||||
const auto &entry = patch.entries[i];
|
||||
if (entry.offset + entry.size <= mapped_size) {
|
||||
std::memcpy(reinterpret_cast<void *>(mapped_nso + entry.offset), entry.data, entry.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -21,4 +21,7 @@ namespace ams::ldr {
|
|||
/* Apply IPS patches. */
|
||||
void LocateAndApplyIpsPatchesToModule(const u8 *build_id, uintptr_t mapped_nso, size_t mapped_size);
|
||||
|
||||
/* Apply embedded patches. */
|
||||
void ApplyEmbeddedPatchesToModule(const u8 *build_id, uintptr_t mapped_nso, size_t mapped_size);
|
||||
|
||||
}
|
|
@ -534,6 +534,9 @@ namespace ams::ldr {
|
|||
std::memset(reinterpret_cast<void *>(map_address + ro_end), 0, nso_header->rw_dst_offset - ro_end);
|
||||
std::memset(reinterpret_cast<void *>(map_address + rw_end), 0, nso_header->bss_size);
|
||||
|
||||
/* Apply embedded patches. */
|
||||
ApplyEmbeddedPatchesToModule(nso_header->build_id, map_address, nso_size);
|
||||
|
||||
/* Apply IPS patches. */
|
||||
LocateAndApplyIpsPatchesToModule(nso_header->build_id, map_address, nso_size);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue