Compare commits

...

11 Commits

Author SHA1 Message Date
Michael Scire
9b480e4757 pm: add api for ams.mitm to steal application memory 2023-05-09 15:07:40 -07:00
Michael Scire
e1c4523c41 fs.mitm: skeleton the use of special allocation in romfs build 2023-05-09 14:22:04 -07:00
Michael Scire
85c23b5781 fusee: actually identify new FS 2023-05-08 18:38:13 -07:00
Michael Scire
8e042f2262 git subrepo push emummc
subrepo:
  subdir:   "emummc"
  merged:   "30205111e"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "30205111e"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2023-05-08 18:25:25 -07:00
Michael Scire
81e9154a52 emummc: add enums for 16.0.3 2023-05-08 18:24:49 -07:00
Michael Scire
e9b9dbc2aa docs: add changelog for 1.5.3 2023-05-08 18:19:31 -07:00
Michael Scire
7e6c849ca4 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "cd0fc2c1d"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "cd0fc2c1d"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2023-05-08 18:06:50 -07:00
Michael Scire
8ec7c096d0 git subrepo push emummc
subrepo:
  subdir:   "emummc"
  merged:   "d2fcc73eb"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "d2fcc73eb"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2023-05-08 18:05:36 -07:00
Michael Scire
6e5b901a9b emummc: support 16.0.3 2023-05-08 18:03:35 -07:00
Michael Scire
b800953d66 ams: recognize 16.0.3('s FS) 2023-05-08 17:51:13 -07:00
Michael Scire
f0240db75a fs.mitm: mitm glue for font replacement, before I forget 2023-05-08 17:40:10 -07:00
27 changed files with 415 additions and 101 deletions

View File

@ -1,4 +1,15 @@
# Changelog # Changelog
## 1.5.3
+ Support was added for 16.0.3.
+ Atmosphère was updated to use GCC 13/newlib (latest devkitA64/devkitARM releases).
+ **Please note**: This introduces a known issue, which is currently being worked on.
+ As you may recall from the 1.4.1 changelog, Fire Emblem: Engage requires enormous amounts of memory to support using layeredfs mods with the game.
+ Latest GCC/newlib slightly increases malloc overhead size, which makes the previous memory increase insufficient.
+ A general-case solution to this is in the works, which should hopefully fix the problem in a way that doesn't jinx me for the future.
+ A number of minor issues were fixed and improvements were made, including:
+ An issue was fixed that caused system font replacement to not work on 16.0.0+.
+ An minor accuracy issue was addressed in mesosphere's management of certain memory ranges; this issue would have had zero visible impact to the end-user.
+ General system stability improvements to enhance the user's experience.
## 1.5.2 ## 1.5.2
+ A homebrew application (`haze`) was added for performing USB file transfer (with thanks to @liamwhite for both design and implementation). + A homebrew application (`haze`) was added for performing USB file transfer (with thanks to @liamwhite for both design and implementation).
+ `haze` is included with atmosphère, and provides access to the SD card via the PTP/MTP protocol. + `haze` is included with atmosphère, and provides access to the SD card via the PTP/MTP protocol.

4
emummc/.gitrepo vendored
View File

@ -6,7 +6,7 @@
[subrepo] [subrepo]
remote = https://github.com/m4xw/emummc remote = https://github.com/m4xw/emummc
branch = develop branch = develop
commit = bba1f1fb65f75721caf6d023a35d75d3c9aafd0f commit = 30205111ee375bef96f0f76cb6a3130a2f0fc85c
parent = 1ab8b234447864503e21c600681219a96962e6c1 parent = 81e9154a52a976f85317bddd0131426599d26a62
method = merge method = merge
cmdver = 0.4.1 cmdver = 0.4.1

2
emummc/README.md vendored
View File

@ -2,7 +2,7 @@
*A SDMMC driver replacement for Nintendo's Filesystem Services, by **m4xw*** *A SDMMC driver replacement for Nintendo's Filesystem Services, by **m4xw***
### Supported Horizon Versions ### Supported Horizon Versions
**1.0.0 - 16.0.0** **1.0.0 - 16.0.3**
## Features ## Features
* Arbitrary SDMMC backend selection * Arbitrary SDMMC backend selection

View File

@ -65,6 +65,8 @@
#include "offsets/1500_exfat.h" #include "offsets/1500_exfat.h"
#include "offsets/1600.h" #include "offsets/1600.h"
#include "offsets/1600_exfat.h" #include "offsets/1600_exfat.h"
#include "offsets/1603.h"
#include "offsets/1603_exfat.h"
#include "../utils/fatal.h" #include "../utils/fatal.h"
#define GET_OFFSET_STRUCT_NAME(vers) g_offsets##vers #define GET_OFFSET_STRUCT_NAME(vers) g_offsets##vers
@ -141,6 +143,8 @@ DEFINE_OFFSET_STRUCT(_1500);
DEFINE_OFFSET_STRUCT(_1500_EXFAT); DEFINE_OFFSET_STRUCT(_1500_EXFAT);
DEFINE_OFFSET_STRUCT(_1600); DEFINE_OFFSET_STRUCT(_1600);
DEFINE_OFFSET_STRUCT(_1600_EXFAT); DEFINE_OFFSET_STRUCT(_1600_EXFAT);
DEFINE_OFFSET_STRUCT(_1603);
DEFINE_OFFSET_STRUCT(_1603_EXFAT);
const fs_offsets_t *get_fs_offsets(enum FS_VER version) { const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
switch (version) { switch (version) {
@ -242,6 +246,10 @@ const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
return &(GET_OFFSET_STRUCT_NAME(_1600)); return &(GET_OFFSET_STRUCT_NAME(_1600));
case FS_VER_16_0_0_EXFAT: case FS_VER_16_0_0_EXFAT:
return &(GET_OFFSET_STRUCT_NAME(_1600_EXFAT)); return &(GET_OFFSET_STRUCT_NAME(_1600_EXFAT));
case FS_VER_16_0_3:
return &(GET_OFFSET_STRUCT_NAME(_1603));
case FS_VER_16_0_3_EXFAT:
return &(GET_OFFSET_STRUCT_NAME(_1603_EXFAT));
default: default:
fatal_abort(Fatal_UnknownVersion); fatal_abort(Fatal_UnknownVersion);
} }

View File

@ -95,6 +95,9 @@ enum FS_VER
FS_VER_16_0_0, FS_VER_16_0_0,
FS_VER_16_0_0_EXFAT, FS_VER_16_0_0_EXFAT,
FS_VER_16_0_3,
FS_VER_16_0_3_EXFAT,
FS_VER_MAX, FS_VER_MAX,
}; };

59
emummc/source/FS/offsets/1603.h vendored Normal file
View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* Copyright (c) 2019 Atmosphere-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/>.
*/
#ifndef __FS_1603_H__
#define __FS_1603_H__
// Accessor vtable getters
#define FS_OFFSET_1603_SDMMC_ACCESSOR_GC 0x1862F0
#define FS_OFFSET_1603_SDMMC_ACCESSOR_SD 0x187F70
#define FS_OFFSET_1603_SDMMC_ACCESSOR_NAND 0x1867B0
// Hooks
#define FS_OFFSET_1603_SDMMC_WRAPPER_READ 0x182240
#define FS_OFFSET_1603_SDMMC_WRAPPER_WRITE 0x1822A0
#define FS_OFFSET_1603_RTLD 0x269B0
#define FS_OFFSET_1603_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C)))
#define FS_OFFSET_1603_CLKRST_SET_MIN_V_CLK_RATE 0x1A2D80
// Misc funcs
#define FS_OFFSET_1603_LOCK_MUTEX 0x17B780
#define FS_OFFSET_1603_UNLOCK_MUTEX 0x17B7D0
#define FS_OFFSET_1603_SDMMC_WRAPPER_CONTROLLER_OPEN 0x182200
#define FS_OFFSET_1603_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x182220
// Misc Data
#define FS_OFFSET_1603_SD_MUTEX 0xFFB3F0
#define FS_OFFSET_1603_NAND_MUTEX 0xFF6B58
#define FS_OFFSET_1603_ACTIVE_PARTITION 0xFF6B98
#define FS_OFFSET_1603_SDMMC_DAS_HANDLE 0xFDC8B0
// NOPs
#define FS_OFFSET_1603_SD_DAS_INIT 0x258D4
// Nintendo Paths
#define FS_OFFSET_1603_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x00063B98, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x00070DBC, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0007795C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0008A7A4, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_1603_H__

59
emummc/source/FS/offsets/1603_exfat.h vendored Normal file
View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* Copyright (c) 2019 Atmosphere-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/>.
*/
#ifndef __FS_1603_EXFAT_H__
#define __FS_1603_EXFAT_H__
// Accessor vtable getters
#define FS_OFFSET_1603_EXFAT_SDMMC_ACCESSOR_GC 0x190FD0
#define FS_OFFSET_1603_EXFAT_SDMMC_ACCESSOR_SD 0x192C50
#define FS_OFFSET_1603_EXFAT_SDMMC_ACCESSOR_NAND 0x191490
// Hooks
#define FS_OFFSET_1603_EXFAT_SDMMC_WRAPPER_READ 0x18CF20
#define FS_OFFSET_1603_EXFAT_SDMMC_WRAPPER_WRITE 0x18CF80
#define FS_OFFSET_1603_EXFAT_RTLD 0x269B0
#define FS_OFFSET_1603_EXFAT_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C)))
#define FS_OFFSET_1603_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x1ADA60
// Misc funcs
#define FS_OFFSET_1603_EXFAT_LOCK_MUTEX 0x186460
#define FS_OFFSET_1603_EXFAT_UNLOCK_MUTEX 0x1864B0
#define FS_OFFSET_1603_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x18CEE0
#define FS_OFFSET_1603_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x18CF00
// Misc Data
#define FS_OFFSET_1603_EXFAT_SD_MUTEX 0x100D3F0
#define FS_OFFSET_1603_EXFAT_NAND_MUTEX 0x1008B58
#define FS_OFFSET_1603_EXFAT_ACTIVE_PARTITION 0x1008B98
#define FS_OFFSET_1603_EXFAT_SDMMC_DAS_HANDLE 0xFE98B0
// NOPs
#define FS_OFFSET_1603_EXFAT_SD_DAS_INIT 0x258D4
// Nintendo Paths
#define FS_OFFSET_1603_EXFAT_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x00063B98, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x00070DBC, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0007795C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0008A7A4, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_1603_EXFAT_H__

View File

@ -162,6 +162,9 @@ namespace ams::nxboot {
FsVersion_16_0_0, FsVersion_16_0_0,
FsVersion_16_0_0_Exfat, FsVersion_16_0_0_Exfat,
FsVersion_16_0_3,
FsVersion_16_0_3_Exfat,
FsVersion_Count, FsVersion_Count,
}; };
@ -239,6 +242,9 @@ namespace ams::nxboot {
{ 0x56, 0xE8, 0x56, 0x56, 0x6C, 0x38, 0xD8, 0xBE }, /* FsVersion_16_0_0 */ { 0x56, 0xE8, 0x56, 0x56, 0x6C, 0x38, 0xD8, 0xBE }, /* FsVersion_16_0_0 */
{ 0xCF, 0xAB, 0x45, 0x0C, 0x2C, 0x53, 0x9D, 0xA9 }, /* FsVersion_16_0_0_Exfat */ { 0xCF, 0xAB, 0x45, 0x0C, 0x2C, 0x53, 0x9D, 0xA9 }, /* FsVersion_16_0_0_Exfat */
{ 0x39, 0xEE, 0x1F, 0x1E, 0x0E, 0xA7, 0x32, 0x5D }, /* FsVersion_16_0_3 */
{ 0x62, 0xC6, 0x5E, 0xFD, 0x9A, 0xBF, 0x7C, 0x43 }, /* FsVersion_16_0_3_Exfat */
}; };
const InitialProcessBinaryHeader *FindInitialProcessBinary(const pkg2::Package2Header *header, const u8 *data, ams::TargetFirmware target_firmware) { const InitialProcessBinaryHeader *FindInitialProcessBinary(const pkg2::Package2Header *header, const u8 *data, ams::TargetFirmware target_firmware) {
@ -656,6 +662,14 @@ namespace ams::nxboot {
AddPatch(fs_meta, 0x1913B9, NogcPatch0, sizeof(NogcPatch0)); AddPatch(fs_meta, 0x1913B9, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x16B950, NogcPatch1, sizeof(NogcPatch1)); AddPatch(fs_meta, 0x16B950, NogcPatch1, sizeof(NogcPatch1));
break; break;
case FsVersion_16_0_3:
AddPatch(fs_meta, 0x186729, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x160CC0, NogcPatch1, sizeof(NogcPatch1));
break;
case FsVersion_16_0_3_Exfat:
AddPatch(fs_meta, 0x191409, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x16B9A0, NogcPatch1, sizeof(NogcPatch1));
break;
default: default:
break; break;
} }

View File

@ -6,7 +6,7 @@
[subrepo] [subrepo]
remote = https://github.com/Atmosphere-NX/Atmosphere-libs remote = https://github.com/Atmosphere-NX/Atmosphere-libs
branch = master branch = master
commit = ecc8b18111730acef0a353f6f61c45c1f143a793 commit = cd0fc2c1d5728ec45414aaaa6efa28c269695992
parent = d8aed7de6d39dd29b75e34f24d376decfb77a5b4 parent = 8ec7c096d04e6f9586be2cb785840cd482d4b900
method = merge method = merge
cmdver = 0.4.1 cmdver = 0.4.1

View File

@ -78,6 +78,7 @@ namespace ams::hos {
Version_16_0_0 = ::ams::TargetFirmware_16_0_0, Version_16_0_0 = ::ams::TargetFirmware_16_0_0,
Version_16_0_1 = ::ams::TargetFirmware_16_0_1, Version_16_0_1 = ::ams::TargetFirmware_16_0_1,
Version_16_0_2 = ::ams::TargetFirmware_16_0_2, Version_16_0_2 = ::ams::TargetFirmware_16_0_2,
Version_16_0_3 = ::ams::TargetFirmware_16_0_3,
Version_Current = ::ams::TargetFirmware_Current, Version_Current = ::ams::TargetFirmware_Current,

View File

@ -30,7 +30,8 @@
AMS_SF_METHOD_INFO(C, H, 7, Result, BoostSystemMemoryResourceLimit, (u64 boost_size), (boost_size)) \ AMS_SF_METHOD_INFO(C, H, 7, Result, BoostSystemMemoryResourceLimit, (u64 boost_size), (boost_size)) \
AMS_SF_METHOD_INFO(C, H, 8, Result, BoostApplicationThreadResourceLimit, (), ()) \ AMS_SF_METHOD_INFO(C, H, 8, Result, BoostApplicationThreadResourceLimit, (), ()) \
AMS_SF_METHOD_INFO(C, H, 9, void, GetBootFinishedEventHandle, (sf::OutCopyHandle out), (out), hos::Version_8_0_0) \ AMS_SF_METHOD_INFO(C, H, 9, void, GetBootFinishedEventHandle, (sf::OutCopyHandle out), (out), hos::Version_8_0_0) \
AMS_SF_METHOD_INFO(C, H, 10, Result, BoostSystemThreadResourceLimit, (), ()) AMS_SF_METHOD_INFO(C, H, 10, Result, BoostSystemThreadResourceLimit, (), ()) \
AMS_SF_METHOD_INFO(C, H, 65000, Result, AtmosphereBoostSystemMemoryResourceLimitForMitm, (u64 boost_size), (boost_size))
AMS_SF_DEFINE_INTERFACE(ams::pm::impl, IShellInterface, AMS_PM_I_SHELL_INTERFACE_INTERFACE_INFO, 0x387D60C0) AMS_SF_DEFINE_INTERFACE(ams::pm::impl, IShellInterface, AMS_PM_I_SHELL_INTERFACE_INTERFACE_INFO, 0x387D60C0)
@ -44,6 +45,8 @@ AMS_SF_DEFINE_INTERFACE(ams::pm::impl, IShellInterface, AMS_PM_I_SHELL_INTERFACE
AMS_SF_METHOD_INFO(C, H, 6, Result, ClearExceptionOccurred, (os::ProcessId process_id), (process_id)) \ AMS_SF_METHOD_INFO(C, H, 6, Result, ClearExceptionOccurred, (os::ProcessId process_id), (process_id)) \
AMS_SF_METHOD_INFO(C, H, 7, void, NotifyBootFinished, (), ()) \ AMS_SF_METHOD_INFO(C, H, 7, void, NotifyBootFinished, (), ()) \
AMS_SF_METHOD_INFO(C, H, 8, Result, GetApplicationProcessIdForShell, (sf::Out<os::ProcessId> out), (out)) \ AMS_SF_METHOD_INFO(C, H, 8, Result, GetApplicationProcessIdForShell, (sf::Out<os::ProcessId> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 9, Result, BoostSystemMemoryResourceLimit, (u64 boost_size), (boost_size), hos::Version_4_0_0) AMS_SF_METHOD_INFO(C, H, 9, Result, BoostSystemMemoryResourceLimit, (u64 boost_size), (boost_size), hos::Version_4_0_0) \
AMS_SF_METHOD_INFO(C, H, 10, Result, BoostSystemThreadResourceLimit, (), ()) \
AMS_SF_METHOD_INFO(C, H, 65000, Result, AtmosphereBoostSystemMemoryResourceLimitForMitm, (u64 boost_size), (boost_size))
AMS_SF_DEFINE_INTERFACE(ams::pm::impl, IDeprecatedShellInterface, AMS_PM_I_DEPRECATED_SHELL_INTERFACE_INTERFACE_INFO, 0x387D60C0) AMS_SF_DEFINE_INTERFACE(ams::pm::impl, IDeprecatedShellInterface, AMS_PM_I_DEPRECATED_SHELL_INTERFACE_INTERFACE_INFO, 0x387D60C0)

View File

@ -32,4 +32,6 @@ namespace ams::pm::shell {
Result BoostApplicationThreadResourceLimit(); Result BoostApplicationThreadResourceLimit();
Result BoostSystemThreadResourceLimit(); Result BoostSystemThreadResourceLimit();
Result AtmosphereBoostSystemMemoryResourceLimitForMitm(u64 size);
} }

View File

@ -90,3 +90,9 @@ Result pmdmntAtmosphereGetCurrentLimitInfo(u64 *out_cur, u64 *out_lim, u32 group
return rc; return rc;
} }
Result pmshellAtmosphereBoostSystemMemoryResourceLimitForMitm(u64 size) {
return serviceDispatchIn(pmshellGetServiceSession(), 65000, size);
}

View File

@ -26,6 +26,8 @@ Result pminfoAtmosphereGetProcessInfo(NcmProgramLocation *loc_out, CfgOverrideSt
Result pmdmntAtmosphereGetProcessInfo(Handle *out, NcmProgramLocation *loc_out, CfgOverrideStatus *status_out, u64 pid); Result pmdmntAtmosphereGetProcessInfo(Handle *out, NcmProgramLocation *loc_out, CfgOverrideStatus *status_out, u64 pid);
Result pmdmntAtmosphereGetCurrentLimitInfo(u64 *out_cur, u64 *out_lim, u32 group, u32 resource); Result pmdmntAtmosphereGetCurrentLimitInfo(u64 *out_cur, u64 *out_lim, u32 group, u32 resource);
Result pmshellAtmosphereBoostSystemMemoryResourceLimitForMitm(u64 size);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -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 <stratosphere.hpp> #include <stratosphere.hpp>
#include "pm_ams.os.horizon.h"
namespace ams::pm::shell { namespace ams::pm::shell {
@ -57,6 +58,10 @@ namespace ams::pm::shell {
Result BoostSystemThreadResourceLimit() { Result BoostSystemThreadResourceLimit() {
R_RETURN(::pmshellBoostSystemThreadResourceLimit()); R_RETURN(::pmshellBoostSystemThreadResourceLimit());
} }
Result AtmosphereBoostSystemMemoryResourceLimitForMitm(u64 size) {
R_RETURN(pmshellAtmosphereBoostSystemMemoryResourceLimitForMitm(size));
}
#endif #endif
} }

View File

@ -17,10 +17,10 @@
#define ATMOSPHERE_RELEASE_VERSION_MAJOR 1 #define ATMOSPHERE_RELEASE_VERSION_MAJOR 1
#define ATMOSPHERE_RELEASE_VERSION_MINOR 5 #define ATMOSPHERE_RELEASE_VERSION_MINOR 5
#define ATMOSPHERE_RELEASE_VERSION_MICRO 2 #define ATMOSPHERE_RELEASE_VERSION_MICRO 3
#define ATMOSPHERE_RELEASE_VERSION ATMOSPHERE_RELEASE_VERSION_MAJOR, ATMOSPHERE_RELEASE_VERSION_MINOR, ATMOSPHERE_RELEASE_VERSION_MICRO #define ATMOSPHERE_RELEASE_VERSION ATMOSPHERE_RELEASE_VERSION_MAJOR, ATMOSPHERE_RELEASE_VERSION_MINOR, ATMOSPHERE_RELEASE_VERSION_MICRO
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 16 #define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 16
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 0 #define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 0
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MICRO 2 #define ATMOSPHERE_SUPPORTED_HOS_VERSION_MICRO 3

View File

@ -76,8 +76,9 @@
#define ATMOSPHERE_TARGET_FIRMWARE_16_0_0 ATMOSPHERE_TARGET_FIRMWARE(16, 0, 0) #define ATMOSPHERE_TARGET_FIRMWARE_16_0_0 ATMOSPHERE_TARGET_FIRMWARE(16, 0, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_16_0_1 ATMOSPHERE_TARGET_FIRMWARE(16, 0, 1) #define ATMOSPHERE_TARGET_FIRMWARE_16_0_1 ATMOSPHERE_TARGET_FIRMWARE(16, 0, 1)
#define ATMOSPHERE_TARGET_FIRMWARE_16_0_2 ATMOSPHERE_TARGET_FIRMWARE(16, 0, 2) #define ATMOSPHERE_TARGET_FIRMWARE_16_0_2 ATMOSPHERE_TARGET_FIRMWARE(16, 0, 2)
#define ATMOSPHERE_TARGET_FIRMWARE_16_0_3 ATMOSPHERE_TARGET_FIRMWARE(16, 0, 3)
#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_16_0_2 #define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_16_0_3
#define ATMOSPHERE_TARGET_FIRMWARE_MIN ATMOSPHERE_TARGET_FIRMWARE(0, 0, 0) #define ATMOSPHERE_TARGET_FIRMWARE_MIN ATMOSPHERE_TARGET_FIRMWARE(0, 0, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_CURRENT #define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_CURRENT
@ -146,6 +147,7 @@ namespace ams {
TargetFirmware_16_0_0 = ATMOSPHERE_TARGET_FIRMWARE_16_0_0, TargetFirmware_16_0_0 = ATMOSPHERE_TARGET_FIRMWARE_16_0_0,
TargetFirmware_16_0_1 = ATMOSPHERE_TARGET_FIRMWARE_16_0_1, TargetFirmware_16_0_1 = ATMOSPHERE_TARGET_FIRMWARE_16_0_1,
TargetFirmware_16_0_2 = ATMOSPHERE_TARGET_FIRMWARE_16_0_2, TargetFirmware_16_0_2 = ATMOSPHERE_TARGET_FIRMWARE_16_0_2,
TargetFirmware_16_0_3 = ATMOSPHERE_TARGET_FIRMWARE_16_0_3,
TargetFirmware_Current = ATMOSPHERE_TARGET_FIRMWARE_CURRENT, TargetFirmware_Current = ATMOSPHERE_TARGET_FIRMWARE_CURRENT,

View File

@ -54,7 +54,8 @@ namespace ams::mitm::fs {
} }
/* We want to mitm sdb, to support sd-romfs redirection of common system archives (like system font, etc). */ /* We want to mitm sdb, to support sd-romfs redirection of common system archives (like system font, etc). */
if (program_id == ncm::SystemProgramId::Sdb) { /* NOTE: In 16.0.0+, this was moved to glue. */
if (program_id == ncm::SystemProgramId::Sdb || program_id == ncm::SystemProgramId::Glue) {
return true; return true;
} }

View File

@ -22,7 +22,7 @@ namespace ams::mitm::fs {
class LayeredRomfsStorageImpl { class LayeredRomfsStorageImpl {
private: private:
std::vector<romfs::SourceInfo> m_source_infos; romfs::Builder::SourceInfoVector m_source_infos;
std::unique_ptr<ams::fs::IStorage> m_storage_romfs; std::unique_ptr<ams::fs::IStorage> m_storage_romfs;
std::unique_ptr<ams::fs::IStorage> m_file_romfs; std::unique_ptr<ams::fs::IStorage> m_file_romfs;
os::Event m_initialize_event; os::Event m_initialize_event;

View File

@ -23,6 +23,27 @@ namespace ams::mitm::fs {
namespace romfs { namespace romfs {
namespace {
/* TODO: Fancy Dynamic allocation globals. */
}
void *AllocateTracked(AllocationType type, size_t size) {
AMS_UNUSED(type);
/* TODO: Fancy dynamic allocation with memory stealing from application pool. */
return std::malloc(size);
}
void FreeTracked(AllocationType type, void *p, size_t size) {
AMS_UNUSED(type);
AMS_UNUSED(size);
/* TODO: Fancy dynamic allocation with memory stealing from application pool. */
return std::free(p);
}
namespace { namespace {
constexpr u32 EmptyEntry = 0xFFFFFFFF; constexpr u32 EmptyEntry = 0xFFFFFFFF;
@ -71,22 +92,23 @@ namespace ams::mitm::fs {
static constexpr size_t MaxCachedSize = (1_MB / 4); static constexpr size_t MaxCachedSize = (1_MB / 4);
private: private:
size_t m_cache_bitsize; size_t m_cache_bitsize;
size_t m_cache_size;
protected: protected:
void *m_cache; void *m_cache;
protected: protected:
DynamicTableCache(size_t sz) { DynamicTableCache(size_t sz) {
size_t cache_size = util::CeilingPowerOfTwo(std::min(sz, MaxCachedSize)); m_cache_size = util::CeilingPowerOfTwo(std::min(sz, MaxCachedSize));
m_cache = std::malloc(cache_size); m_cache = AllocateTracked(AllocationType_TableCache, m_cache_size);
while (m_cache == nullptr) { while (m_cache == nullptr) {
cache_size >>= 1; m_cache_size >>= 1;
AMS_ABORT_UNLESS(cache_size >= 16_KB); AMS_ABORT_UNLESS(m_cache_size >= 16_KB);
m_cache = std::malloc(cache_size); m_cache = AllocateTracked(AllocationType_TableCache, m_cache_size);
} }
m_cache_bitsize = util::CountTrailingZeros(cache_size); m_cache_bitsize = util::CountTrailingZeros(m_cache_size);
} }
~DynamicTableCache() { ~DynamicTableCache() {
std::free(m_cache); FreeTracked(AllocationType_TableCache, m_cache, m_cache_size);
} }
ALWAYS_INLINE size_t GetCacheSize() const { return static_cast<size_t>(1) << m_cache_bitsize; } ALWAYS_INLINE size_t GetCacheSize() const { return static_cast<size_t>(1) << m_cache_bitsize; }
@ -293,7 +315,7 @@ namespace ams::mitm::fs {
} }
Builder::Builder(ncm::ProgramId pr_id) : m_program_id(pr_id), m_num_dirs(0), m_num_files(0), m_dir_table_size(0), m_file_table_size(0), m_dir_hash_table_size(0), m_file_hash_table_size(0), m_file_partition_size(0) { Builder::Builder(ncm::ProgramId pr_id) : m_program_id(pr_id), m_num_dirs(0), m_num_files(0), m_dir_table_size(0), m_file_table_size(0), m_dir_hash_table_size(0), m_file_hash_table_size(0), m_file_partition_size(0) {
auto res = m_directories.emplace(std::make_unique<BuildDirectoryContext>(BuildDirectoryContext::RootTag{})); auto res = m_directories.emplace(std::unique_ptr<BuildDirectoryContext>(AllocateTyped<BuildDirectoryContext>(AllocationType_BuildDirContext, BuildDirectoryContext::RootTag{})));
AMS_ABORT_UNLESS(res.second); AMS_ABORT_UNLESS(res.second);
m_root = res.first->get(); m_root = res.first->get();
m_num_dirs = 1; m_num_dirs = 1;
@ -347,9 +369,9 @@ namespace ams::mitm::fs {
AMS_ABORT_UNLESS(num_child_dirs >= 0); AMS_ABORT_UNLESS(num_child_dirs >= 0);
{ {
BuildDirectoryContext **child_dirs = num_child_dirs != 0 ? reinterpret_cast<BuildDirectoryContext **>(std::malloc(sizeof(BuildDirectoryContext *) * num_child_dirs)) : nullptr; BuildDirectoryContext **child_dirs = num_child_dirs != 0 ? reinterpret_cast<BuildDirectoryContext **>(AllocateTracked(AllocationType_DirPointerArray, sizeof(BuildDirectoryContext *) * num_child_dirs)) : nullptr;
AMS_ABORT_UNLESS(num_child_dirs == 0 || child_dirs != nullptr); AMS_ABORT_UNLESS(num_child_dirs == 0 || child_dirs != nullptr);
ON_SCOPE_EXIT { std::free(child_dirs); }; ON_SCOPE_EXIT { if (child_dirs != nullptr) { FreeTracked(AllocationType_DirPointerArray, child_dirs, sizeof(BuildDirectoryContext *) * num_child_dirs); } };
s64 cur_child_dir_ind = 0; s64 cur_child_dir_ind = 0;
{ {
@ -368,12 +390,12 @@ namespace ams::mitm::fs {
AMS_ABORT_UNLESS(child_dirs != nullptr); AMS_ABORT_UNLESS(child_dirs != nullptr);
BuildDirectoryContext *real_child = nullptr; BuildDirectoryContext *real_child = nullptr;
this->AddDirectory(std::addressof(real_child), parent, std::make_unique<BuildDirectoryContext>(m_dir_entry.name, strlen(m_dir_entry.name))); this->AddDirectory(std::addressof(real_child), parent, std::unique_ptr<BuildDirectoryContext>(AllocateTyped<BuildDirectoryContext>(AllocationType_BuildDirContext, m_dir_entry.name, strlen(m_dir_entry.name))));
AMS_ABORT_UNLESS(real_child != nullptr); AMS_ABORT_UNLESS(real_child != nullptr);
child_dirs[cur_child_dir_ind++] = real_child; child_dirs[cur_child_dir_ind++] = real_child;
AMS_ABORT_UNLESS(cur_child_dir_ind <= num_child_dirs); AMS_ABORT_UNLESS(cur_child_dir_ind <= num_child_dirs);
} else /* if (m_dir_entry.type == FsDirEntryType_File) */ { } else /* if (m_dir_entry.type == FsDirEntryType_File) */ {
this->AddFile(parent, std::make_unique<BuildFileContext>(m_dir_entry.name, strlen(m_dir_entry.name), m_dir_entry.file_size, 0, m_cur_source_type)); this->AddFile(parent, std::unique_ptr<BuildFileContext>(AllocateTyped<BuildFileContext>(AllocationType_BuildFileContext, m_dir_entry.name, strlen(m_dir_entry.name), m_dir_entry.file_size, 0, m_cur_source_type)));
} }
} }
} }
@ -403,7 +425,7 @@ namespace ams::mitm::fs {
while (cur_file_offset != EmptyEntry) { while (cur_file_offset != EmptyEntry) {
const FileEntry *cur_file = file_table.GetEntry(cur_file_offset); const FileEntry *cur_file = file_table.GetEntry(cur_file_offset);
this->AddFile(parent, std::make_unique<BuildFileContext>(cur_file->name, cur_file->name_size, cur_file->size, cur_file->offset, m_cur_source_type)); this->AddFile(parent, std::unique_ptr<BuildFileContext>(AllocateTyped<BuildFileContext>(AllocationType_BuildFileContext, cur_file->name, cur_file->name_size, cur_file->size, cur_file->offset, m_cur_source_type)));
cur_file_offset = cur_file->sibling; cur_file_offset = cur_file->sibling;
} }
@ -415,7 +437,7 @@ namespace ams::mitm::fs {
{ {
const DirectoryEntry *cur_child = dir_table.GetEntry(cur_child_offset); const DirectoryEntry *cur_child = dir_table.GetEntry(cur_child_offset);
this->AddDirectory(std::addressof(real_child), parent, std::make_unique<BuildDirectoryContext>(cur_child->name, cur_child->name_size)); this->AddDirectory(std::addressof(real_child), parent, std::unique_ptr<BuildDirectoryContext>(AllocateTyped<BuildDirectoryContext>(AllocationType_BuildDirContext, cur_child->name, cur_child->name_size)));
AMS_ABORT_UNLESS(real_child != nullptr); AMS_ABORT_UNLESS(real_child != nullptr);
next_child_offset = cur_child->sibling; next_child_offset = cur_child->sibling;
@ -438,7 +460,7 @@ namespace ams::mitm::fs {
/* If there is no romfs folder on the SD, don't bother continuing. */ /* If there is no romfs folder on the SD, don't bother continuing. */
{ {
FsDir dir; FsDir dir;
if (R_FAILED(mitm::fs::OpenAtmosphereRomfsDirectory(std::addressof(dir), m_program_id, m_root->path.get(), OpenDirectoryMode_Directory, std::addressof(sd_filesystem)))) { if (R_FAILED(mitm::fs::OpenAtmosphereRomfsDirectory(std::addressof(dir), m_program_id, m_root->path, OpenDirectoryMode_Directory, std::addressof(sd_filesystem)))) {
return; return;
} }
fsDirClose(std::addressof(dir)); fsDirClose(std::addressof(dir));
@ -461,7 +483,7 @@ namespace ams::mitm::fs {
this->VisitDirectory(m_root, 0x0, dir_table, file_table); this->VisitDirectory(m_root, 0x0, dir_table, file_table);
} }
void Builder::Build(std::vector<SourceInfo> *out_infos) { void Builder::Build(SourceInfoVector *out_infos) {
/* Clear output. */ /* Clear output. */
out_infos->clear(); out_infos->clear();
@ -477,7 +499,7 @@ namespace ams::mitm::fs {
m_file_hash_table_size = sizeof(u32) * num_file_hash_table_entries; m_file_hash_table_size = sizeof(u32) * num_file_hash_table_entries;
/* Allocate metadata, make pointers. */ /* Allocate metadata, make pointers. */
Header *header = reinterpret_cast<Header *>(std::malloc(sizeof(Header))); Header *header = reinterpret_cast<Header *>(AllocateTracked(AllocationType_Memory, sizeof(Header)));
std::memset(header, 0x00, sizeof(*header)); std::memset(header, 0x00, sizeof(*header));
/* Open metadata file. */ /* Open metadata file. */
@ -552,13 +574,13 @@ namespace ams::mitm::fs {
/* Set all files' hash value = hash index. */ /* Set all files' hash value = hash index. */
for (const auto &it : m_files) { for (const auto &it : m_files) {
BuildFileContext *cur_file = it.get(); BuildFileContext *cur_file = it.get();
cur_file->hash_value = CalculatePathHash(cur_file->parent->entry_offset, cur_file->path.get(), 0, cur_file->path_len) % num_file_hash_table_entries; cur_file->hash_value = CalculatePathHash(cur_file->parent->entry_offset, cur_file->path, 0, cur_file->path_len) % num_file_hash_table_entries;
} }
/* Set all directories' hash value = hash index. */ /* Set all directories' hash value = hash index. */
for (const auto &it : m_directories) { for (const auto &it : m_directories) {
BuildDirectoryContext *cur_dir = it.get(); BuildDirectoryContext *cur_dir = it.get();
cur_dir->hash_value = CalculatePathHash(cur_dir == m_root ? 0 : cur_dir->parent->entry_offset, cur_dir->path.get(), 0, cur_dir->path_len) % num_dir_hash_table_entries; cur_dir->hash_value = CalculatePathHash(cur_dir == m_root ? 0 : cur_dir->parent->entry_offset, cur_dir->path, 0, cur_dir->path_len) % num_dir_hash_table_entries;
} }
/* Write hash tables. */ /* Write hash tables. */
@ -661,7 +683,7 @@ namespace ams::mitm::fs {
const u32 name_size = cur_file->path_len; const u32 name_size = cur_file->path_len;
cur_entry->name_size = name_size; cur_entry->name_size = name_size;
if (name_size) { if (name_size) {
std::memcpy(cur_entry->name, cur_file->path.get(), name_size); std::memcpy(cur_entry->name, cur_file->path, name_size);
for (size_t i = name_size; i < util::AlignUp(name_size, 4); i++) { for (size_t i = name_size; i < util::AlignUp(name_size, 4); i++) {
cur_entry->name[i] = 0; cur_entry->name[i] = 0;
} }
@ -688,9 +710,10 @@ namespace ams::mitm::fs {
AMS_ABORT_UNLESS(path_needed_size <= sizeof(full_path)); AMS_ABORT_UNLESS(path_needed_size <= sizeof(full_path));
cur_file->GetPath(full_path); cur_file->GetPath(full_path);
cur_file->path.reset(); FreeTracked(AllocationType_FileName, cur_file->path, cur_file->path_len + 1);
cur_file->path = nullptr;
char *new_path = new char[path_needed_size]; char *new_path = static_cast<char *>(AllocateTracked(AllocationType_FullPath, path_needed_size));
std::memcpy(new_path, full_path, path_needed_size); std::memcpy(new_path, full_path, path_needed_size);
out_infos->emplace_back(cur_file->offset + FilePartitionOffset, cur_file->size, cur_file->source_type, new_path); out_infos->emplace_back(cur_file->offset + FilePartitionOffset, cur_file->size, cur_file->source_type, new_path);
} }
@ -719,7 +742,7 @@ namespace ams::mitm::fs {
const u32 name_size = cur_dir->path_len; const u32 name_size = cur_dir->path_len;
cur_entry->name_size = name_size; cur_entry->name_size = name_size;
if (name_size) { if (name_size) {
std::memcpy(cur_entry->name, cur_dir->path.get(), name_size); std::memcpy(cur_entry->name, cur_dir->path, name_size);
for (size_t i = name_size; i < util::AlignUp(name_size, 4); i++) { for (size_t i = name_size; i < util::AlignUp(name_size, 4); i++) {
cur_entry->name[i] = 0; cur_entry->name[i] = 0;
} }

View File

@ -27,6 +27,52 @@ namespace ams::mitm::fs::romfs {
Memory, Memory,
}; };
enum AllocationType {
AllocationType_FileName,
AllocationType_DirName,
AllocationType_FullPath,
AllocationType_SourceInfo,
AllocationType_BuildFileContext,
AllocationType_BuildDirContext,
AllocationType_TableCache,
AllocationType_DirPointerArray,
AllocationType_DirContextSet,
AllocationType_FileContextSet,
AllocationType_Memory,
AllocationType_Count,
};
void *AllocateTracked(AllocationType type, size_t size);
void FreeTracked(AllocationType type, void *p, size_t size);
template<typename T, typename... Args>
T *AllocateTyped(AllocationType type, Args &&... args) {
void *mem = AllocateTracked(type, sizeof(T));
return std::construct_at(static_cast<T *>(mem), std::forward<Args>(args)...);
}
template<AllocationType AllocType, typename T>
class TrackedAllocator {
public:
using value_type = T;
template<typename U>
struct rebind {
using other = TrackedAllocator<AllocType, U>;
};
public:
TrackedAllocator() = default;
T *allocate(size_t n) {
return static_cast<T *>(AllocateTracked(AllocType, sizeof(T) * n));
}
void deallocate(T *p, size_t n) {
FreeTracked(AllocType, p, sizeof(T) * n);
}
};
struct SourceInfo { struct SourceInfo {
s64 virtual_offset; s64 virtual_offset;
s64 size; s64 size;
@ -89,10 +135,10 @@ namespace ams::mitm::fs::romfs {
delete this->metadata_source_info.file; delete this->metadata_source_info.file;
break; break;
case DataSourceType::LooseSdFile: case DataSourceType::LooseSdFile:
delete[] this->loose_source_info.path; FreeTracked(AllocationType_FullPath, this->loose_source_info.path, std::strlen(this->loose_source_info.path) + 1);
break; break;
case DataSourceType::Memory: case DataSourceType::Memory:
std::free(static_cast<void *>(this->memory_source_info.data)); FreeTracked(AllocationType_Memory, this->memory_source_info.data, this->size);
break; break;
AMS_UNREACHABLE_DEFAULT_CASE(); AMS_UNREACHABLE_DEFAULT_CASE();
} }
@ -113,7 +159,7 @@ namespace ams::mitm::fs::romfs {
NON_COPYABLE(BuildDirectoryContext); NON_COPYABLE(BuildDirectoryContext);
NON_MOVEABLE(BuildDirectoryContext); NON_MOVEABLE(BuildDirectoryContext);
std::unique_ptr<char[]> path; char *path;
union { union {
BuildDirectoryContext *parent; BuildDirectoryContext *parent;
}; };
@ -139,16 +185,28 @@ namespace ams::mitm::fs::romfs {
struct RootTag{}; struct RootTag{};
BuildDirectoryContext(RootTag) : parent(nullptr), child(nullptr), sibling(nullptr), file(nullptr), path_len(0), entry_offset(0), hash_value(0xFFFFFFFF) { BuildDirectoryContext(RootTag) : parent(nullptr), child(nullptr), sibling(nullptr), file(nullptr), path_len(0), entry_offset(0), hash_value(0xFFFFFFFF) {
this->path = std::make_unique<char[]>(1); this->path = static_cast<char *>(AllocateTracked(AllocationType_DirName, 1));
this->path[0] = '\x00';
} }
BuildDirectoryContext(const char *entry_name, size_t entry_name_len) : parent(nullptr), child(nullptr), sibling(nullptr), file(nullptr), entry_offset(0) { BuildDirectoryContext(const char *entry_name, size_t entry_name_len) : parent(nullptr), child(nullptr), sibling(nullptr), file(nullptr), entry_offset(0) {
this->path_len = entry_name_len; this->path_len = entry_name_len;
this->path = std::unique_ptr<char[]>(new char[this->path_len + 1]); this->path = static_cast<char *>(AllocateTracked(AllocationType_DirName, this->path_len + 1));
std::memcpy(this->path.get(), entry_name, entry_name_len); std::memcpy(this->path, entry_name, entry_name_len);
this->path[this->path_len] = '\x00'; this->path[this->path_len] = '\x00';
} }
~BuildDirectoryContext() {
if (this->path != nullptr) {
FreeTracked(AllocationType_DirName, this->path, this->path_len + 1);
this->path = nullptr;
}
}
void operator delete(void *p) {
FreeTracked(AllocationType_BuildDirContext, p, sizeof(BuildDirectoryContext));
}
size_t GetPathLength() const { size_t GetPathLength() const {
if (this->parent == nullptr) { if (this->parent == nullptr) {
return 0; return 0;
@ -165,7 +223,7 @@ namespace ams::mitm::fs::romfs {
const size_t parent_len = this->parent->GetPath(dst); const size_t parent_len = this->parent->GetPath(dst);
dst[parent_len] = '/'; dst[parent_len] = '/';
std::memcpy(dst + parent_len + 1, this->path.get(), this->path_len); std::memcpy(dst + parent_len + 1, this->path, this->path_len);
dst[parent_len + 1 + this->path_len] = '\x00'; dst[parent_len + 1 + this->path_len] = '\x00';
return parent_len + 1 + this->path_len; return parent_len + 1 + this->path_len;
} }
@ -187,7 +245,7 @@ namespace ams::mitm::fs::romfs {
NON_COPYABLE(BuildFileContext); NON_COPYABLE(BuildFileContext);
NON_MOVEABLE(BuildFileContext); NON_MOVEABLE(BuildFileContext);
std::unique_ptr<char[]> path; char *path;
BuildDirectoryContext *parent; BuildDirectoryContext *parent;
union { union {
BuildFileContext *sibling; BuildFileContext *sibling;
@ -203,11 +261,22 @@ namespace ams::mitm::fs::romfs {
BuildFileContext(const char *entry_name, size_t entry_name_len, s64 sz, s64 o_o, DataSourceType type) : parent(nullptr), sibling(nullptr), offset(0), size(sz), orig_offset(o_o), entry_offset(0), hash_value(0xFFFFFFFF), source_type(type) { BuildFileContext(const char *entry_name, size_t entry_name_len, s64 sz, s64 o_o, DataSourceType type) : parent(nullptr), sibling(nullptr), offset(0), size(sz), orig_offset(o_o), entry_offset(0), hash_value(0xFFFFFFFF), source_type(type) {
this->path_len = entry_name_len; this->path_len = entry_name_len;
this->path = std::unique_ptr<char[]>(new char[this->path_len + 1]); this->path = static_cast<char *>(AllocateTracked(AllocationType_FileName, this->path_len + 1));
std::memcpy(this->path.get(), entry_name, entry_name_len); std::memcpy(this->path, entry_name, entry_name_len);
this->path[this->path_len] = 0; this->path[this->path_len] = 0;
} }
~BuildFileContext() {
if (this->path != nullptr) {
FreeTracked(AllocationType_FileName, this->path, this->path_len + 1);
this->path = nullptr;
}
}
void operator delete(void *p) {
FreeTracked(AllocationType_BuildFileContext, p, sizeof(BuildFileContext));
}
size_t GetPathLength() const { size_t GetPathLength() const {
if (this->parent == nullptr) { if (this->parent == nullptr) {
return 0; return 0;
@ -224,7 +293,7 @@ namespace ams::mitm::fs::romfs {
const size_t parent_len = this->parent->GetPath(dst); const size_t parent_len = this->parent->GetPath(dst);
dst[parent_len] = '/'; dst[parent_len] = '/';
std::memcpy(dst + parent_len + 1, this->path.get(), this->path_len); std::memcpy(dst + parent_len + 1, this->path, this->path_len);
dst[parent_len + 1 + this->path_len] = '\x00'; dst[parent_len + 1 + this->path_len] = '\x00';
return parent_len + 1 + this->path_len; return parent_len + 1 + this->path_len;
} }
@ -248,6 +317,8 @@ namespace ams::mitm::fs::romfs {
class Builder { class Builder {
NON_COPYABLE(Builder); NON_COPYABLE(Builder);
NON_MOVEABLE(Builder); NON_MOVEABLE(Builder);
public:
using SourceInfoVector = std::vector<SourceInfo, TrackedAllocator<AllocationType_SourceInfo, SourceInfo>>;
private: private:
template<typename T> template<typename T>
struct Comparator { struct Comparator {
@ -270,13 +341,13 @@ namespace ams::mitm::fs::romfs {
} }
}; };
template<typename T> template<AllocationType AllocType, typename T>
using ContextSet = std::set<std::unique_ptr<T>, Comparator<T>>; using ContextSet = std::set<std::unique_ptr<T>, Comparator<T>, TrackedAllocator<AllocType, std::unique_ptr<T>>>;
private: private:
ncm::ProgramId m_program_id; ncm::ProgramId m_program_id;
BuildDirectoryContext *m_root; BuildDirectoryContext *m_root;
ContextSet<BuildDirectoryContext> m_directories; ContextSet<AllocationType_DirContextSet, BuildDirectoryContext> m_directories;
ContextSet<BuildFileContext> m_files; ContextSet<AllocationType_FileContextSet, BuildFileContext> m_files;
size_t m_num_dirs; size_t m_num_dirs;
size_t m_num_files; size_t m_num_files;
size_t m_dir_table_size; size_t m_dir_table_size;
@ -299,7 +370,7 @@ namespace ams::mitm::fs::romfs {
void AddSdFiles(); void AddSdFiles();
void AddStorageFiles(ams::fs::IStorage *storage, DataSourceType source_type); void AddStorageFiles(ams::fs::IStorage *storage, DataSourceType source_type);
void Build(std::vector<SourceInfo> *out_infos); void Build(SourceInfoVector *out_infos);
}; };
} }

View File

@ -713,4 +713,8 @@ namespace ams::pm::impl {
R_RETURN(resource::GetResourceLimitValues(out_cur_val, out_lim_val, static_cast<ResourceLimitGroup>(group), static_cast<svc::LimitableResource>(resource))); R_RETURN(resource::GetResourceLimitValues(out_cur_val, out_lim_val, static_cast<ResourceLimitGroup>(group), static_cast<svc::LimitableResource>(resource)));
} }
Result BoostSystemMemoryResourceLimitForMitm(u64 boost_size) {
R_RETURN(resource::BoostSystemMemoryResourceLimitForMitm(boost_size));
}
} }

View File

@ -55,5 +55,6 @@ namespace ams::pm::impl {
Result GetAppletCurrentResourceLimitValues(pm::ResourceLimitValues *out); Result GetAppletCurrentResourceLimitValues(pm::ResourceLimitValues *out);
Result GetAppletPeakResourceLimitValues(pm::ResourceLimitValues *out); Result GetAppletPeakResourceLimitValues(pm::ResourceLimitValues *out);
Result AtmosphereGetCurrentLimitInfo(s64 *out_cur_val, s64 *out_lim_val, u32 group, u32 resource); Result AtmosphereGetCurrentLimitInfo(s64 *out_cur_val, s64 *out_lim_val, u32 group, u32 resource);
Result BoostSystemMemoryResourceLimitForMitm(u64 boost_size);
} }

View File

@ -52,9 +52,16 @@ namespace ams::pm::resource {
constinit os::SdkMutex g_resource_limit_lock; constinit os::SdkMutex g_resource_limit_lock;
constinit os::NativeHandle g_resource_limit_handles[ResourceLimitGroup_Count]; constinit os::NativeHandle g_resource_limit_handles[ResourceLimitGroup_Count];
constinit spl::MemoryArrangement g_memory_arrangement = spl::MemoryArrangement_Standard; constinit spl::MemoryArrangement g_memory_arrangement = spl::MemoryArrangement_Standard;
constinit u64 g_system_memory_boost_size = 0;
constinit u64 g_extra_threads_available[ResourceLimitGroup_Count]; constinit u64 g_extra_threads_available[ResourceLimitGroup_Count];
constinit os::SdkMutex g_system_memory_boost_lock;
constinit u64 g_system_memory_boost_size = 0;
constinit u64 g_system_memory_boost_size_for_mitm = 0;
ALWAYS_INLINE u64 GetCurrentSystemMemoryBoostSize() {
return g_system_memory_boost_size + g_system_memory_boost_size_for_mitm;
}
constinit u64 g_resource_limits[ResourceLimitGroup_Count][svc::LimitableResource_Count] = { constinit u64 g_resource_limits[ResourceLimitGroup_Count][svc::LimitableResource_Count] = {
[ResourceLimitGroup_System] = { [ResourceLimitGroup_System] = {
[svc::LimitableResource_PhysicalMemoryMax] = 0, /* Initialized dynamically later. */ [svc::LimitableResource_PhysicalMemoryMax] = 0, /* Initialized dynamically later. */
@ -220,6 +227,47 @@ namespace ams::pm::resource {
R_SUCCEED(); R_SUCCEED();
} }
Result BoostSystemMemoryResourceLimitLocked(u64 normal_boost, u64 mitm_boost) {
/* Check pre-conditions. */
AMS_ASSERT(g_system_memory_boost_lock.IsLockedByCurrentThread());
/* Determine total boost. */
const u64 boost_size = normal_boost + mitm_boost;
/* Don't allow all application memory to be taken away. */
R_UNLESS(boost_size <= g_memory_resource_limits[g_memory_arrangement][ResourceLimitGroup_Application], pm::ResultInvalidSize());
const u64 new_app_size = g_memory_resource_limits[g_memory_arrangement][ResourceLimitGroup_Application] - boost_size;
{
std::scoped_lock lk(g_resource_limit_lock);
if (hos::GetVersion() >= hos::Version_5_0_0) {
/* Starting in 5.0.0, PM does not allow for only one of the sets to fail. */
if (boost_size < GetCurrentSystemMemoryBoostSize()) {
R_TRY(svc::SetUnsafeLimit(boost_size));
R_ABORT_UNLESS(SetMemoryResourceLimitLimitValue(ResourceLimitGroup_Application, new_app_size));
} else {
R_TRY(SetMemoryResourceLimitLimitValue(ResourceLimitGroup_Application, new_app_size));
R_ABORT_UNLESS(svc::SetUnsafeLimit(boost_size));
}
} else {
const u64 new_sys_size = g_memory_resource_limits[g_memory_arrangement][ResourceLimitGroup_System] + boost_size;
if (boost_size < GetCurrentSystemMemoryBoostSize()) {
R_TRY(SetMemoryResourceLimitLimitValue(ResourceLimitGroup_System, new_sys_size));
R_TRY(SetMemoryResourceLimitLimitValue(ResourceLimitGroup_Application, new_app_size));
} else {
R_TRY(SetMemoryResourceLimitLimitValue(ResourceLimitGroup_Application, new_app_size));
R_TRY(SetMemoryResourceLimitLimitValue(ResourceLimitGroup_System, new_sys_size));
}
}
g_system_memory_boost_size = normal_boost;
g_system_memory_boost_size_for_mitm = mitm_boost;
}
R_SUCCEED();
}
} }
/* Resource API. */ /* Resource API. */
@ -352,37 +400,19 @@ namespace ams::pm::resource {
} }
Result BoostSystemMemoryResourceLimit(u64 boost_size) { Result BoostSystemMemoryResourceLimit(u64 boost_size) {
/* Don't allow all application memory to be taken away. */ /* Ensure only one boost change happens at a time. */
R_UNLESS(boost_size <= g_memory_resource_limits[g_memory_arrangement][ResourceLimitGroup_Application], pm::ResultInvalidSize()); std::scoped_lock lk(g_system_memory_boost_lock);
const u64 new_app_size = g_memory_resource_limits[g_memory_arrangement][ResourceLimitGroup_Application] - boost_size; /* Boost to the appropriate total amount. */
{ R_RETURN(BoostSystemMemoryResourceLimitLocked(boost_size, g_system_memory_boost_size_for_mitm));
std::scoped_lock lk(g_resource_limit_lock);
if (hos::GetVersion() >= hos::Version_5_0_0) {
/* Starting in 5.0.0, PM does not allow for only one of the sets to fail. */
if (boost_size < g_system_memory_boost_size) {
R_TRY(svc::SetUnsafeLimit(boost_size));
R_ABORT_UNLESS(SetMemoryResourceLimitLimitValue(ResourceLimitGroup_Application, new_app_size));
} else {
R_TRY(SetMemoryResourceLimitLimitValue(ResourceLimitGroup_Application, new_app_size));
R_ABORT_UNLESS(svc::SetUnsafeLimit(boost_size));
}
} else {
const u64 new_sys_size = g_memory_resource_limits[g_memory_arrangement][ResourceLimitGroup_System] + boost_size;
if (boost_size < g_system_memory_boost_size) {
R_TRY(SetMemoryResourceLimitLimitValue(ResourceLimitGroup_System, new_sys_size));
R_TRY(SetMemoryResourceLimitLimitValue(ResourceLimitGroup_Application, new_app_size));
} else {
R_TRY(SetMemoryResourceLimitLimitValue(ResourceLimitGroup_Application, new_app_size));
R_TRY(SetMemoryResourceLimitLimitValue(ResourceLimitGroup_System, new_sys_size));
}
} }
g_system_memory_boost_size = boost_size; Result BoostSystemMemoryResourceLimitForMitm(u64 boost_size) {
} /* Ensure only one boost change happens at a time. */
std::scoped_lock lk(g_system_memory_boost_lock);
R_SUCCEED(); /* Boost to the appropriate total amount. */
R_RETURN(BoostSystemMemoryResourceLimitLocked(g_system_memory_boost_size, boost_size));
} }
Result BoostApplicationThreadResourceLimit() { Result BoostApplicationThreadResourceLimit() {

View File

@ -24,6 +24,8 @@ namespace ams::pm::resource {
Result BoostApplicationThreadResourceLimit(); Result BoostApplicationThreadResourceLimit();
Result BoostSystemThreadResourceLimit(); Result BoostSystemThreadResourceLimit();
Result BoostSystemMemoryResourceLimitForMitm(u64 boost_size);
os::NativeHandle GetResourceLimitHandle(ResourceLimitGroup group); os::NativeHandle GetResourceLimitHandle(ResourceLimitGroup group);
os::NativeHandle GetResourceLimitHandle(const ldr::ProgramInfo *info); os::NativeHandle GetResourceLimitHandle(const ldr::ProgramInfo *info);

View File

@ -87,4 +87,8 @@ namespace ams::pm {
R_RETURN(impl::BoostSystemThreadResourceLimit()); R_RETURN(impl::BoostSystemThreadResourceLimit());
} }
Result ShellService::AtmosphereBoostSystemMemoryResourceLimitForMitm(u64 boost_size) {
R_RETURN(impl::BoostSystemMemoryResourceLimitForMitm(boost_size));
}
} }

View File

@ -34,6 +34,9 @@ namespace ams::pm {
Result BoostApplicationThreadResourceLimit(); Result BoostApplicationThreadResourceLimit();
void GetBootFinishedEventHandle(sf::OutCopyHandle out); void GetBootFinishedEventHandle(sf::OutCopyHandle out);
Result BoostSystemThreadResourceLimit(); Result BoostSystemThreadResourceLimit();
/* Atmosphere extension command implementations. */
Result AtmosphereBoostSystemMemoryResourceLimitForMitm(u64 boost_size);
}; };
static_assert(pm::impl::IsIShellInterface<ShellService>); static_assert(pm::impl::IsIShellInterface<ShellService>);