Compare commits

...

46 Commits
0.9.1 ... 0.9.2

Author SHA1 Message Date
Michael Scire
b0a66a63ba Fix sept-secondary headers in fusee-secondary 2019-06-29 20:13:24 -07:00
Michael Scire
0d840e199d Bump version to 0.9.2. 2019-06-29 20:05:21 -07:00
Michael Scire
3a2bceef8d git subrepo pull emummc
subrepo:
  subdir:   "emummc"
  merged:   "5f51fa3b"
upstream:
  origin:   "https://github.com/m4xw/emuMMC"
  branch:   "develop"
  commit:   "5f51fa3b"
git-subrepo:
  version:  "0.4.0"
  origin:   "https://github.com/ingydotnet/git-subrepo"
  commit:   "5d6aba9"
2019-06-28 11:36:07 -07:00
hexkyz
e871a754a8 fusee: remove unnecessary prefix from emummc config keys 2019-06-28 16:35:18 +01:00
hexkyz
6333327b81 fusee: update partition based emummc sector detection 2019-06-28 16:34:04 +01:00
Michael Scire
18ca8aaf5b stratosphere: all in on enum class CommandId 2019-06-27 23:34:53 -07:00
SciresM
67c0f4527e Merge pull request #603 from Atmosphere-NX/ldr_rewrite
loader: completely rewrite.
2019-06-27 23:28:00 -07:00
Michael Scire
e5c5101e8a Add missing extension cleanup. 2019-06-27 20:51:57 -07:00
Michael Scire
934ff7bbde <int> -> <s32> 2019-06-27 20:16:56 -07:00
Michael Scire
014f08f6b4 ldr: fix mount check mistake 2019-06-27 18:01:44 -07:00
Michael Scire
6ba2090c01 ldr: address review commentary. 2019-06-27 17:37:33 -07:00
Michael Scire
61fcf5e0f4 loader: completely rewrite. 2019-06-26 15:46:19 -07:00
Michael Scire
9217e4c5f9 sm: add HasService/HasMitm, refactor into sts:: 2019-06-24 17:57:49 -07:00
SciresM
3ccbb34c62 Merge pull request #598 from Atmosphere-NX/ro_refactor
ro: refactor/rewrite into sts:: namespace
2019-06-24 15:40:45 -07:00
Michael Scire
9baa4a17ed ro: refactor/rewrite into sts:: namespace 2019-06-24 02:05:51 -07:00
SciresM
6bbece39bc Merge pull request #592 from Atmosphere-NX/boot_refactor
Refactor boot sysmodule to use sts::boot namespace.
2019-06-23 20:39:39 -07:00
hexkyz
729447eab0 fusee: cleanup and simplify emummc logic 2019-06-23 18:50:20 +01:00
Michael Scire
1e7f41ea9f boot: move updater into libstrat 2019-06-22 12:30:36 -07:00
Michael Scire
d0d4888184 boot/spl: update for spl-in-libstrat 2019-06-22 12:23:46 -07:00
Michael Scire
804e5d49bb boot: split out gpio, pinmux. 2019-06-22 11:34:18 -07:00
Michael Scire
6d1d226842 remove unnecessary sts:: prefixing 2019-06-22 00:14:24 -07:00
Michael Scire
06416aeded boot: refactor to use sts::boot namespace 2019-06-22 00:10:21 -07:00
Michael Scire
4fbae9e5a4 boot: move updater to sts::updater namespace 2019-06-21 21:06:04 -07:00
Michael Scire
c87be7cd69 boot: refactor i2c driver into namespace 2019-06-21 20:25:27 -07:00
SciresM
e62754ed56 Merge pull request #585 from Atmosphere-NX/sm_rewrite
Completely re-write sm.
2019-06-21 17:37:06 -07:00
Michael Scire
53d7281e66 sm: use enums for GetInfo 2019-06-21 17:37:01 -07:00
SciresM
731a2c11a4 Merge pull request #587 from Atmosphere-NX/spl_refactor
spl: refactor into sts namespace
2019-06-21 17:33:34 -07:00
hexkyz
ec4d078d6d fusee: fix emummc multipart device 2019-06-21 22:14:14 +01:00
Michael Scire
f9b48f06a3 spl: refactor into sts namespace 2019-06-21 01:36:00 -07:00
Michael Scire
d986ffa153 sm: use AutoHandles 2019-06-20 23:51:15 -07:00
Michael Scire
2357bc70a7 Implementation cleanup 2019-06-20 23:34:59 -07:00
Michael Scire
e86e1588e3 Simplify namespacing 2019-06-20 18:32:00 -07:00
Michael Scire
4be88c7180 sm: adjust Makefile 2019-06-20 18:24:35 -07:00
Michael Scire
8e8daa64ba sm: completely rewrite module 2019-06-20 18:23:40 -07:00
Michael Scire
1671c04e24 stratosphere: prefer static waitable managers 2019-06-20 13:15:39 -07:00
Michael Scire
d3d6c552b7 stratosphere: remove trailing whitespace 2019-06-20 13:00:32 -07:00
Michael Scire
8d9336f561 git subrepo clone --branch=develop --force https://github.com/m4xw/emuMMC emummc
subrepo:
  subdir:   "emummc"
  merged:   "e935968d"
upstream:
  origin:   "https://github.com/m4xw/emuMMC"
  branch:   "develop"
  commit:   "e935968d"
git-subrepo:
  version:  "0.4.0"
  origin:   "https://github.com/ingydotnet/git-subrepo"
  commit:   "5d6aba9"
2019-06-20 12:41:50 -07:00
Michael Scire
169ec9c12e Update libstrat 2019-06-20 05:01:42 -07:00
Michael Scire
60b831f369 ams_mitm: refactor for R_TRY 2019-06-20 04:04:33 -07:00
Michael Scire
4191dcee75 dmnt: fix missing init 2019-06-20 04:04:11 -07:00
Michael Scire
44725c8910 sm: refactor mitm service handle acquisition 2019-06-20 02:21:01 -07:00
Michael Scire
cead8a36ea stratosphere: more result cleanup 2019-06-20 02:00:59 -07:00
Michael Scire
7b6050a0cb boot: refactor for R_TRY 2019-06-20 00:57:17 -07:00
Michael Scire
491383c637 dmnt: trailing whitespace 2019-06-19 22:20:44 -07:00
Michael Scire
d7a3645f7f dmnt: update for R_TRY 2019-06-19 22:19:53 -07:00
Michael Scire
241b8f4627 fusee: fix config init/ini read order 2019-06-19 20:28:06 -07:00
382 changed files with 13779 additions and 19869 deletions

View File

@@ -19,7 +19,7 @@
#define ATMOSPHERE_RELEASE_VERSION_MAJOR 0 #define ATMOSPHERE_RELEASE_VERSION_MAJOR 0
#define ATMOSPHERE_RELEASE_VERSION_MINOR 9 #define ATMOSPHERE_RELEASE_VERSION_MINOR 9
#define ATMOSPHERE_RELEASE_VERSION_MICRO 1 #define ATMOSPHERE_RELEASE_VERSION_MICRO 2
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 8 #define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 8
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 1 #define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 1

View File

@@ -1,4 +1,27 @@
# Changelog # Changelog
## 0.9.2
+ A number of emummc bugfixes were added (all thanks to @m4xw's hard work). The following is a summary of emummc changes:
+ Support for file-based emummc instances was fixed.
+ Please note: file-based emummc is still unoptimized, and so may be much slower than partition-based.
+ This speed differential should hopefully be made better in a future emummc update.
+ The way emummc handles power management was completely overhauled.
+ Emummc now properly handles init/de-init, and now supports low voltage mode.
+ Much better support for shutdown was added, which should assuage corruption/synchronization problems.
+ This should also improve support for more types of SD cards.
+ A bug was fixed that caused emummc to not work on lower system versions due to missing SVC access.
+ **Please note**: The configuration entries used for emummc have been changed.
+ `emummc_` prefixes have been removed, since they are superfluous given the `emummc` category they are under.
+ As an example, `emummc!emummc_enabled` is now `emummc!enabled`.
+ INI configurations made by @CTCaer's [tool](https://github.com/ctcaer/hekate/releases/latest) (which is the recommended way to manage emummc) should automatically work as expected/be corrected.
+ **If you do not wish to use the above, you will need to manually correct your configuration file**.
+ General system stability improvements to enhance the user's experience.
+ Stratosphere is currently in the process of being re-written/refactored.
+ Stratosphere was my (SciresM's) first C++ project, ever -- the code written for it a year ago when I was learning C++ is/was of much lower quality than code written more recently.
+ Code is thus being re-rwitten for clarity/stlye/to de-duplicate functionality, with much being moved into libstratosphere.
+ Stratosphere will, after the rewrite, globally use the `sts::` namespace -- this should greatly enhancing libstratosphere's ability to provide functionality for system modules.
+ The rewritten modules consistently have lower memory footprints, and should be easier to maintain going forwards.
+ The `sm`, `boot`, `spl`, `ro`, and `loader` modules have been tackled so far.
+ General system stability improvements to enhance the user's experience.
## 0.9.1 ## 0.9.1
+ Support was added for 8.1.0. + Support was added for 8.1.0.
+ Please note, emummc is still considered **beta/experimental** -- this is not the inevitable bugfix update for it, although some number of bugs have been fixed. :) + Please note, emummc is still considered **beta/experimental** -- this is not the inevitable bugfix update for it, although some number of bugs have been fixed. :)

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 = e7799388e8d3de17fd178ffe310be2e81ef46d6f commit = 5f51fa3b81d2b14b348f6e8579454007019fc7a6
parent = f2086fe05492cb523b60fa10e4425c4ea59521b3 parent = e871a754a87631c3036ca985ff1c223e00ef4dda
method = rebase method = rebase
cmdver = 0.4.0 cmdver = 0.4.0

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 - 8.0.1** **1.0.0 - 8.1.0**
## Features ## Features
* Arbitrary SDMMC backend selection * Arbitrary SDMMC backend selection

View File

@@ -116,6 +116,7 @@
"svcReplyAndReceive": "0x43", "svcReplyAndReceive": "0x43",
"svcReplyAndReceiveWithUserBuffer": "0x44", "svcReplyAndReceiveWithUserBuffer": "0x44",
"svcCreateEvent": "0x45", "svcCreateEvent": "0x45",
"svcReadWriteRegister": "0x4E",
"svcCreateInterruptEvent": "0x53", "svcCreateInterruptEvent": "0x53",
"svcQueryIoMapping": "0x55", "svcQueryIoMapping": "0x55",
"svcCreateDeviceAddressSpace": "0x56", "svcCreateDeviceAddressSpace": "0x56",

View File

@@ -47,23 +47,23 @@
#define DEFINE_OFFSET_STRUCT(vers) \ #define DEFINE_OFFSET_STRUCT(vers) \
static const fs_offsets_t GET_OFFSET_STRUCT_NAME(vers) = { \ static const fs_offsets_t GET_OFFSET_STRUCT_NAME(vers) = { \
.sdmmc_accessor_gc = FS_OFFSET##vers##_SDMMC_ACCESSOR_GC, \ .sdmmc_accessor_gc = FS_OFFSET##vers##_SDMMC_ACCESSOR_GC, \
.sdmmc_accessor_sd = FS_OFFSET##vers##_SDMMC_ACCESSOR_SD, \ .sdmmc_accessor_sd = FS_OFFSET##vers##_SDMMC_ACCESSOR_SD, \
.sdmmc_accessor_nand = FS_OFFSET##vers##_SDMMC_ACCESSOR_NAND, \ .sdmmc_accessor_nand = FS_OFFSET##vers##_SDMMC_ACCESSOR_NAND, \
.sdmmc_wrapper_read = FS_OFFSET##vers##_SDMMC_WRAPPER_READ, \ .sdmmc_wrapper_read = FS_OFFSET##vers##_SDMMC_WRAPPER_READ, \
.sdmmc_wrapper_write = FS_OFFSET##vers##_SDMMC_WRAPPER_WRITE, \ .sdmmc_wrapper_write = FS_OFFSET##vers##_SDMMC_WRAPPER_WRITE, \
.clkrst_set_min_v_clock_rate = FS_OFFSET##vers##_CLKRST_SET_MIN_V_CLK_RATE, \ .clkrst_set_min_v_clock_rate = FS_OFFSET##vers##_CLKRST_SET_MIN_V_CLK_RATE, \
.rtld = FS_OFFSET##vers##_RTLD, \ .rtld = FS_OFFSET##vers##_RTLD, \
.rtld_destination = FS_OFFSET##vers##_RTLD_DESTINATION, \ .rtld_destination = FS_OFFSET##vers##_RTLD_DESTINATION, \
.lock_mutex = FS_OFFSET##vers##_LOCK_MUTEX, \ .lock_mutex = FS_OFFSET##vers##_LOCK_MUTEX, \
.unlock_mutex = FS_OFFSET##vers##_UNLOCK_MUTEX, \ .unlock_mutex = FS_OFFSET##vers##_UNLOCK_MUTEX, \
.sd_mutex = FS_OFFSET##vers##_SD_MUTEX, \ .sd_mutex = FS_OFFSET##vers##_SD_MUTEX, \
.nand_mutex = FS_OFFSET##vers##_NAND_MUTEX, \ .nand_mutex = FS_OFFSET##vers##_NAND_MUTEX, \
.active_partition = FS_OFFSET##vers##_ACTIVE_PARTITION, \ .active_partition = FS_OFFSET##vers##_ACTIVE_PARTITION, \
.sdmmc_das_handle = FS_OFFSET##vers##_SDMMC_DAS_HANDLE, \ .sdmmc_das_handle = FS_OFFSET##vers##_SDMMC_DAS_HANDLE, \
.shutdown_sd = FS_OFFSET##vers##_SHUTDOWN_SD, \ .sdmmc_accessor_controller_close = FS_OFFSET##vers##_SDMMC_WRAPPER_CONTROLLER_CLOSE, \
.sd_das_init = FS_OFFSET##vers##_SD_DAS_INIT, \ .sd_das_init = FS_OFFSET##vers##_SD_DAS_INIT, \
.nintendo_paths = FS_OFFSET##vers##_NINTENDO_PATHS, \ .nintendo_paths = FS_OFFSET##vers##_NINTENDO_PATHS, \
} }
// Actually define offset structs // Actually define offset structs

View File

@@ -41,13 +41,13 @@ typedef struct {
// Misc funcs // Misc funcs
uintptr_t lock_mutex; uintptr_t lock_mutex;
uintptr_t unlock_mutex; uintptr_t unlock_mutex;
uintptr_t sdmmc_accessor_controller_close;
// Misc data // Misc data
uintptr_t sd_mutex; uintptr_t sd_mutex;
uintptr_t nand_mutex; uintptr_t nand_mutex;
uintptr_t active_partition; uintptr_t active_partition;
uintptr_t sdmmc_das_handle; uintptr_t sdmmc_das_handle;
// NOPs // NOPs
uintptr_t shutdown_sd;
uintptr_t sd_das_init; uintptr_t sd_das_init;
// Nintendo Paths // Nintendo Paths
fs_offsets_nintendo_path_t nintendo_paths[]; fs_offsets_nintendo_path_t nintendo_paths[];

View File

@@ -36,7 +36,7 @@ typedef struct sdmmc_accessor_vt
void *map_device_addr_space; void *map_device_addr_space;
void *unmap_device_addr_space; void *unmap_device_addr_space;
void *controller_open; void *controller_open;
void *controller_close; uint64_t (*sdmmc_accessor_controller_close)(void *);
uint64_t (*read_write)(void *, uint64_t, uint64_t, void *, uint64_t, uint64_t); uint64_t (*read_write)(void *, uint64_t, uint64_t, void *, uint64_t, uint64_t);
// More not included because we don't use it. // More not included because we don't use it.
} sdmmc_accessor_vt_t; } sdmmc_accessor_vt_t;

View File

@@ -34,6 +34,8 @@
#define FS_OFFSET_100_LOCK_MUTEX 0x2884 #define FS_OFFSET_100_LOCK_MUTEX 0x2884
#define FS_OFFSET_100_UNLOCK_MUTEX 0x28F0 #define FS_OFFSET_100_UNLOCK_MUTEX 0x28F0
#define FS_OFFSET_100_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x6A8AC
// Misc Data // Misc Data
#define FS_OFFSET_100_SD_MUTEX 0xE36058 #define FS_OFFSET_100_SD_MUTEX 0xE36058
#define FS_OFFSET_100_NAND_MUTEX 0xE30610 #define FS_OFFSET_100_NAND_MUTEX 0xE30610
@@ -41,7 +43,6 @@
#define FS_OFFSET_100_SDMMC_DAS_HANDLE 0xE2F730 #define FS_OFFSET_100_SDMMC_DAS_HANDLE 0xE2F730
// NOPs // NOPs
#define FS_OFFSET_100_SHUTDOWN_SD 0x22548
#define FS_OFFSET_100_SD_DAS_INIT 0x0 #define FS_OFFSET_100_SD_DAS_INIT 0x0
// Nintendo Paths // Nintendo Paths

View File

@@ -34,6 +34,8 @@
#define FS_OFFSET_200_LOCK_MUTEX 0x3264 #define FS_OFFSET_200_LOCK_MUTEX 0x3264
#define FS_OFFSET_200_UNLOCK_MUTEX 0x32D0 #define FS_OFFSET_200_UNLOCK_MUTEX 0x32D0
#define FS_OFFSET_200_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x733F4
// Misc Data // Misc Data
#define FS_OFFSET_200_SD_MUTEX 0xE42268 #define FS_OFFSET_200_SD_MUTEX 0xE42268
#define FS_OFFSET_200_NAND_MUTEX 0xE3CED0 #define FS_OFFSET_200_NAND_MUTEX 0xE3CED0
@@ -41,7 +43,6 @@
#define FS_OFFSET_200_SDMMC_DAS_HANDLE 0xE3BDD0 #define FS_OFFSET_200_SDMMC_DAS_HANDLE 0xE3BDD0
// NOPs // NOPs
#define FS_OFFSET_200_SHUTDOWN_SD 0x20C48
#define FS_OFFSET_200_SD_DAS_INIT 0x0 #define FS_OFFSET_200_SD_DAS_INIT 0x0
// Nintendo Paths // Nintendo Paths

View File

@@ -34,6 +34,8 @@
#define FS_OFFSET_200_EXFAT_LOCK_MUTEX 0x3264 #define FS_OFFSET_200_EXFAT_LOCK_MUTEX 0x3264
#define FS_OFFSET_200_EXFAT_UNLOCK_MUTEX 0x32D0 #define FS_OFFSET_200_EXFAT_UNLOCK_MUTEX 0x32D0
#define FS_OFFSET_200_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x733F4
// Misc Data // Misc Data
#define FS_OFFSET_200_EXFAT_SD_MUTEX 0xF22268 #define FS_OFFSET_200_EXFAT_SD_MUTEX 0xF22268
#define FS_OFFSET_200_EXFAT_NAND_MUTEX 0xF1CED0 #define FS_OFFSET_200_EXFAT_NAND_MUTEX 0xF1CED0
@@ -41,7 +43,6 @@
#define FS_OFFSET_200_EXFAT_SDMMC_DAS_HANDLE 0xF1BDD0 #define FS_OFFSET_200_EXFAT_SDMMC_DAS_HANDLE 0xF1BDD0
// NOPs // NOPs
#define FS_OFFSET_200_EXFAT_SHUTDOWN_SD 0x20C48
#define FS_OFFSET_200_EXFAT_SD_DAS_INIT 0x0 #define FS_OFFSET_200_EXFAT_SD_DAS_INIT 0x0
// Nintendo Paths // Nintendo Paths

View File

@@ -34,6 +34,8 @@
#define FS_OFFSET_210_LOCK_MUTEX 0x3264 #define FS_OFFSET_210_LOCK_MUTEX 0x3264
#define FS_OFFSET_210_UNLOCK_MUTEX 0x32D0 #define FS_OFFSET_210_UNLOCK_MUTEX 0x32D0
#define FS_OFFSET_210_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x737D4
// Misc Data // Misc Data
#define FS_OFFSET_210_SD_MUTEX 0xE43268 #define FS_OFFSET_210_SD_MUTEX 0xE43268
#define FS_OFFSET_210_NAND_MUTEX 0xE3DED0 #define FS_OFFSET_210_NAND_MUTEX 0xE3DED0
@@ -41,7 +43,6 @@
#define FS_OFFSET_210_SDMMC_DAS_HANDLE 0xE3CDD0 #define FS_OFFSET_210_SDMMC_DAS_HANDLE 0xE3CDD0
// NOPs // NOPs
#define FS_OFFSET_210_SHUTDOWN_SD 0x20E60
#define FS_OFFSET_210_SD_DAS_INIT 0x0 #define FS_OFFSET_210_SD_DAS_INIT 0x0
// Nintendo Paths // Nintendo Paths

View File

@@ -34,6 +34,8 @@
#define FS_OFFSET_210_EXFAT_LOCK_MUTEX 0x3264 #define FS_OFFSET_210_EXFAT_LOCK_MUTEX 0x3264
#define FS_OFFSET_210_EXFAT_UNLOCK_MUTEX 0x32D0 #define FS_OFFSET_210_EXFAT_UNLOCK_MUTEX 0x32D0
#define FS_OFFSET_210_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x737D4
// Misc Data // Misc Data
#define FS_OFFSET_210_EXFAT_SD_MUTEX 0xF22268 #define FS_OFFSET_210_EXFAT_SD_MUTEX 0xF22268
#define FS_OFFSET_210_EXFAT_NAND_MUTEX 0xF1CED0 #define FS_OFFSET_210_EXFAT_NAND_MUTEX 0xF1CED0
@@ -41,7 +43,6 @@
#define FS_OFFSET_210_EXFAT_SDMMC_DAS_HANDLE 0xF1BDD0 #define FS_OFFSET_210_EXFAT_SDMMC_DAS_HANDLE 0xF1BDD0
// NOPs // NOPs
#define FS_OFFSET_210_EXFAT_SHUTDOWN_SD 0x20E60
#define FS_OFFSET_210_EXFAT_SD_DAS_INIT 0x0 #define FS_OFFSET_210_EXFAT_SD_DAS_INIT 0x0
// Nintendo Paths // Nintendo Paths

View File

@@ -34,6 +34,8 @@
#define FS_OFFSET_300_LOCK_MUTEX 0x35CC #define FS_OFFSET_300_LOCK_MUTEX 0x35CC
#define FS_OFFSET_300_UNLOCK_MUTEX 0x3638 #define FS_OFFSET_300_UNLOCK_MUTEX 0x3638
#define FS_OFFSET_300_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A270
// Misc Data // Misc Data
#define FS_OFFSET_300_SD_MUTEX 0xE69268 #define FS_OFFSET_300_SD_MUTEX 0xE69268
#define FS_OFFSET_300_NAND_MUTEX 0xE646F0 #define FS_OFFSET_300_NAND_MUTEX 0xE646F0
@@ -41,7 +43,6 @@
#define FS_OFFSET_300_SDMMC_DAS_HANDLE 0xE635A0 #define FS_OFFSET_300_SDMMC_DAS_HANDLE 0xE635A0
// NOPs // NOPs
#define FS_OFFSET_300_SHUTDOWN_SD 0x258D8
#define FS_OFFSET_300_SD_DAS_INIT 0x0 #define FS_OFFSET_300_SD_DAS_INIT 0x0
// Nintendo Paths // Nintendo Paths

View File

@@ -34,6 +34,8 @@
#define FS_OFFSET_300_EXFAT_LOCK_MUTEX 0x35CC #define FS_OFFSET_300_EXFAT_LOCK_MUTEX 0x35CC
#define FS_OFFSET_300_EXFAT_UNLOCK_MUTEX 0x3638 #define FS_OFFSET_300_EXFAT_UNLOCK_MUTEX 0x3638
#define FS_OFFSET_300_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A270
// Misc Data // Misc Data
#define FS_OFFSET_300_EXFAT_SD_MUTEX 0xF4C268 #define FS_OFFSET_300_EXFAT_SD_MUTEX 0xF4C268
#define FS_OFFSET_300_EXFAT_NAND_MUTEX 0xF476F0 #define FS_OFFSET_300_EXFAT_NAND_MUTEX 0xF476F0
@@ -41,7 +43,6 @@
#define FS_OFFSET_300_EXFAT_SDMMC_DAS_HANDLE 0xF465A0 #define FS_OFFSET_300_EXFAT_SDMMC_DAS_HANDLE 0xF465A0
// NOPs // NOPs
#define FS_OFFSET_300_EXFAT_SHUTDOWN_SD 0x258D8
#define FS_OFFSET_300_EXFAT_SD_DAS_INIT 0x0 #define FS_OFFSET_300_EXFAT_SD_DAS_INIT 0x0
// Nintendo Paths // Nintendo Paths

View File

@@ -34,6 +34,8 @@
#define FS_OFFSET_301_LOCK_MUTEX 0x3638 #define FS_OFFSET_301_LOCK_MUTEX 0x3638
#define FS_OFFSET_301_UNLOCK_MUTEX 0x36A4 #define FS_OFFSET_301_UNLOCK_MUTEX 0x36A4
#define FS_OFFSET_301_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A32C
// Misc Data // Misc Data
#define FS_OFFSET_301_SD_MUTEX 0xE69268 #define FS_OFFSET_301_SD_MUTEX 0xE69268
#define FS_OFFSET_301_NAND_MUTEX 0xE646F0 #define FS_OFFSET_301_NAND_MUTEX 0xE646F0
@@ -41,7 +43,6 @@
#define FS_OFFSET_301_SDMMC_DAS_HANDLE 0xE635A0 #define FS_OFFSET_301_SDMMC_DAS_HANDLE 0xE635A0
// NOPs // NOPs
#define FS_OFFSET_301_SHUTDOWN_SD 0x25944
#define FS_OFFSET_301_SD_DAS_INIT 0x0 #define FS_OFFSET_301_SD_DAS_INIT 0x0
// Nintendo Paths // Nintendo Paths

View File

@@ -34,6 +34,8 @@
#define FS_OFFSET_301_EXFAT_LOCK_MUTEX 0x3638 #define FS_OFFSET_301_EXFAT_LOCK_MUTEX 0x3638
#define FS_OFFSET_301_EXFAT_UNLOCK_MUTEX 0x36A4 #define FS_OFFSET_301_EXFAT_UNLOCK_MUTEX 0x36A4
#define FS_OFFSET_301_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A32C
// Misc Data // Misc Data
#define FS_OFFSET_301_EXFAT_SD_MUTEX 0xF4C268 #define FS_OFFSET_301_EXFAT_SD_MUTEX 0xF4C268
#define FS_OFFSET_301_EXFAT_NAND_MUTEX 0xF476F0 #define FS_OFFSET_301_EXFAT_NAND_MUTEX 0xF476F0
@@ -41,7 +43,6 @@
#define FS_OFFSET_301_EXFAT_SDMMC_DAS_HANDLE 0xF465A0 #define FS_OFFSET_301_EXFAT_SDMMC_DAS_HANDLE 0xF465A0
// NOPs // NOPs
#define FS_OFFSET_301_EXFAT_SHUTDOWN_SD 0x25944
#define FS_OFFSET_301_EXFAT_SD_DAS_INIT 0x0 #define FS_OFFSET_301_EXFAT_SD_DAS_INIT 0x0
// Nintendo Paths // Nintendo Paths

View File

@@ -34,6 +34,8 @@
#define FS_OFFSET_400_LOCK_MUTEX 0x39A0 #define FS_OFFSET_400_LOCK_MUTEX 0x39A0
#define FS_OFFSET_400_UNLOCK_MUTEX 0x3A0C #define FS_OFFSET_400_UNLOCK_MUTEX 0x3A0C
#define FS_OFFSET_400_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DB48
// Misc Data // Misc Data
#define FS_OFFSET_400_SD_MUTEX 0xE80268 #define FS_OFFSET_400_SD_MUTEX 0xE80268
#define FS_OFFSET_400_NAND_MUTEX 0xE7BC60 #define FS_OFFSET_400_NAND_MUTEX 0xE7BC60
@@ -41,7 +43,6 @@
#define FS_OFFSET_400_SDMMC_DAS_HANDLE 0xE7ABF0 #define FS_OFFSET_400_SDMMC_DAS_HANDLE 0xE7ABF0
// NOPs // NOPs
#define FS_OFFSET_400_SHUTDOWN_SD 0x32D70
#define FS_OFFSET_400_SD_DAS_INIT 0x0 #define FS_OFFSET_400_SD_DAS_INIT 0x0
// Nintendo Paths // Nintendo Paths

View File

@@ -34,6 +34,8 @@
#define FS_OFFSET_400_EXFAT_LOCK_MUTEX 0x39A0 #define FS_OFFSET_400_EXFAT_LOCK_MUTEX 0x39A0
#define FS_OFFSET_400_EXFAT_UNLOCK_MUTEX 0x3A0C #define FS_OFFSET_400_EXFAT_UNLOCK_MUTEX 0x3A0C
#define FS_OFFSET_400_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DB48
// Misc Data // Misc Data
#define FS_OFFSET_400_EXFAT_SD_MUTEX 0xF63268 #define FS_OFFSET_400_EXFAT_SD_MUTEX 0xF63268
#define FS_OFFSET_400_EXFAT_NAND_MUTEX 0xF5EC60 #define FS_OFFSET_400_EXFAT_NAND_MUTEX 0xF5EC60
@@ -41,7 +43,6 @@
#define FS_OFFSET_400_EXFAT_SDMMC_DAS_HANDLE 0xF5DBF0 #define FS_OFFSET_400_EXFAT_SDMMC_DAS_HANDLE 0xF5DBF0
// NOPs // NOPs
#define FS_OFFSET_400_EXFAT_SHUTDOWN_SD 0x32D70
#define FS_OFFSET_400_EXFAT_SD_DAS_INIT 0x0 #define FS_OFFSET_400_EXFAT_SD_DAS_INIT 0x0
// Nintendo Paths // Nintendo Paths

View File

@@ -34,6 +34,8 @@
#define FS_OFFSET_410_LOCK_MUTEX 0x39A0 #define FS_OFFSET_410_LOCK_MUTEX 0x39A0
#define FS_OFFSET_410_UNLOCK_MUTEX 0x3A0C #define FS_OFFSET_410_UNLOCK_MUTEX 0x3A0C
#define FS_OFFSET_410_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DBAC
// Misc Data // Misc Data
#define FS_OFFSET_410_SD_MUTEX 0xE80268 #define FS_OFFSET_410_SD_MUTEX 0xE80268
#define FS_OFFSET_410_NAND_MUTEX 0xE7BC60 #define FS_OFFSET_410_NAND_MUTEX 0xE7BC60
@@ -41,7 +43,6 @@
#define FS_OFFSET_410_SDMMC_DAS_HANDLE 0xE7ABF0 #define FS_OFFSET_410_SDMMC_DAS_HANDLE 0xE7ABF0
// NOPs // NOPs
#define FS_OFFSET_410_SHUTDOWN_SD 0x32D70
#define FS_OFFSET_410_SD_DAS_INIT 0x0 #define FS_OFFSET_410_SD_DAS_INIT 0x0
// Nintendo Paths // Nintendo Paths

View File

@@ -34,6 +34,8 @@
#define FS_OFFSET_410_EXFAT_LOCK_MUTEX 0x39A0 #define FS_OFFSET_410_EXFAT_LOCK_MUTEX 0x39A0
#define FS_OFFSET_410_EXFAT_UNLOCK_MUTEX 0x3A0C #define FS_OFFSET_410_EXFAT_UNLOCK_MUTEX 0x3A0C
#define FS_OFFSET_410_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DBAC
// Misc Data // Misc Data
#define FS_OFFSET_410_EXFAT_SD_MUTEX 0xF63268 #define FS_OFFSET_410_EXFAT_SD_MUTEX 0xF63268
#define FS_OFFSET_410_EXFAT_NAND_MUTEX 0xF5EC60 #define FS_OFFSET_410_EXFAT_NAND_MUTEX 0xF5EC60
@@ -41,7 +43,6 @@
#define FS_OFFSET_410_EXFAT_SDMMC_DAS_HANDLE 0xF5DBF0 #define FS_OFFSET_410_EXFAT_SDMMC_DAS_HANDLE 0xF5DBF0
// NOPs // NOPs
#define FS_OFFSET_410_EXFAT_SHUTDOWN_SD 0x32D70
#define FS_OFFSET_410_EXFAT_SD_DAS_INIT 0x0 #define FS_OFFSET_410_EXFAT_SD_DAS_INIT 0x0
// Nintendo Paths // Nintendo Paths

View File

@@ -34,6 +34,8 @@
#define FS_OFFSET_500_LOCK_MUTEX 0x4080 #define FS_OFFSET_500_LOCK_MUTEX 0x4080
#define FS_OFFSET_500_UNLOCK_MUTEX 0x40D0 #define FS_OFFSET_500_UNLOCK_MUTEX 0x40D0
#define FS_OFFSET_500_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9380
// Misc Data // Misc Data
#define FS_OFFSET_500_SD_MUTEX 0xEC3268 #define FS_OFFSET_500_SD_MUTEX 0xEC3268
#define FS_OFFSET_500_NAND_MUTEX 0xEBDE58 #define FS_OFFSET_500_NAND_MUTEX 0xEBDE58
@@ -41,7 +43,6 @@
#define FS_OFFSET_500_SDMMC_DAS_HANDLE 0xEBCE30 #define FS_OFFSET_500_SDMMC_DAS_HANDLE 0xEBCE30
// NOPs // NOPs
#define FS_OFFSET_500_SHUTDOWN_SD 0x443E8
#define FS_OFFSET_500_SD_DAS_INIT 0x0 #define FS_OFFSET_500_SD_DAS_INIT 0x0
// Nintendo Paths // Nintendo Paths

View File

@@ -34,6 +34,8 @@
#define FS_OFFSET_500_EXFAT_LOCK_MUTEX 0x4080 #define FS_OFFSET_500_EXFAT_LOCK_MUTEX 0x4080
#define FS_OFFSET_500_EXFAT_UNLOCK_MUTEX 0x40D0 #define FS_OFFSET_500_EXFAT_UNLOCK_MUTEX 0x40D0
#define FS_OFFSET_500_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9380
// Misc Data // Misc Data
#define FS_OFFSET_500_EXFAT_SD_MUTEX 0xFA8268 #define FS_OFFSET_500_EXFAT_SD_MUTEX 0xFA8268
#define FS_OFFSET_500_EXFAT_NAND_MUTEX 0xFA2E58 #define FS_OFFSET_500_EXFAT_NAND_MUTEX 0xFA2E58
@@ -41,7 +43,6 @@
#define FS_OFFSET_500_EXFAT_SDMMC_DAS_HANDLE 0xFA1E30 #define FS_OFFSET_500_EXFAT_SDMMC_DAS_HANDLE 0xFA1E30
// NOPs // NOPs
#define FS_OFFSET_500_EXFAT_SHUTDOWN_SD 0x443E8
#define FS_OFFSET_500_EXFAT_SD_DAS_INIT 0x0 #define FS_OFFSET_500_EXFAT_SD_DAS_INIT 0x0
// Nintendo Paths // Nintendo Paths

View File

@@ -34,6 +34,8 @@
#define FS_OFFSET_510_LOCK_MUTEX 0x4080 #define FS_OFFSET_510_LOCK_MUTEX 0x4080
#define FS_OFFSET_510_UNLOCK_MUTEX 0x40D0 #define FS_OFFSET_510_UNLOCK_MUTEX 0x40D0
#define FS_OFFSET_510_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9750
// Misc Data // Misc Data
#define FS_OFFSET_510_SD_MUTEX 0xEC4268 #define FS_OFFSET_510_SD_MUTEX 0xEC4268
#define FS_OFFSET_510_NAND_MUTEX 0xEBEE58 #define FS_OFFSET_510_NAND_MUTEX 0xEBEE58
@@ -41,7 +43,6 @@
#define FS_OFFSET_510_SDMMC_DAS_HANDLE 0xEBDE30 #define FS_OFFSET_510_SDMMC_DAS_HANDLE 0xEBDE30
// NOPs // NOPs
#define FS_OFFSET_510_SHUTDOWN_SD 0x44578
#define FS_OFFSET_510_SD_DAS_INIT 0x0 #define FS_OFFSET_510_SD_DAS_INIT 0x0
// Nintendo Paths // Nintendo Paths

View File

@@ -34,6 +34,8 @@
#define FS_OFFSET_510_EXFAT_LOCK_MUTEX 0x4080 #define FS_OFFSET_510_EXFAT_LOCK_MUTEX 0x4080
#define FS_OFFSET_510_EXFAT_UNLOCK_MUTEX 0x40D0 #define FS_OFFSET_510_EXFAT_UNLOCK_MUTEX 0x40D0
#define FS_OFFSET_510_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9750
// Misc Data // Misc Data
#define FS_OFFSET_510_EXFAT_SD_MUTEX 0xFA9268 #define FS_OFFSET_510_EXFAT_SD_MUTEX 0xFA9268
#define FS_OFFSET_510_EXFAT_NAND_MUTEX 0xFA3E58 #define FS_OFFSET_510_EXFAT_NAND_MUTEX 0xFA3E58
@@ -41,7 +43,6 @@
#define FS_OFFSET_510_EXFAT_SDMMC_DAS_HANDLE 0xFA2E30 #define FS_OFFSET_510_EXFAT_SDMMC_DAS_HANDLE 0xFA2E30
// NOPs // NOPs
#define FS_OFFSET_510_EXFAT_SHUTDOWN_SD 0x44578
#define FS_OFFSET_510_EXFAT_SD_DAS_INIT 0x0 #define FS_OFFSET_510_EXFAT_SD_DAS_INIT 0x0
// Nintendo Paths // Nintendo Paths

View File

@@ -34,6 +34,8 @@
#define FS_OFFSET_600_LOCK_MUTEX 0x1412C0 #define FS_OFFSET_600_LOCK_MUTEX 0x1412C0
#define FS_OFFSET_600_UNLOCK_MUTEX 0x141310 #define FS_OFFSET_600_UNLOCK_MUTEX 0x141310
#define FS_OFFSET_600_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x148500
// Misc Data // Misc Data
#define FS_OFFSET_600_SD_MUTEX 0xF06268 #define FS_OFFSET_600_SD_MUTEX 0xF06268
#define FS_OFFSET_600_NAND_MUTEX 0xF01BA0 #define FS_OFFSET_600_NAND_MUTEX 0xF01BA0
@@ -41,7 +43,6 @@
#define FS_OFFSET_600_SDMMC_DAS_HANDLE 0xE01670 #define FS_OFFSET_600_SDMMC_DAS_HANDLE 0xE01670
// NOPs // NOPs
#define FS_OFFSET_600_SHUTDOWN_SD 0xB2F28
#define FS_OFFSET_600_SD_DAS_INIT 0x0 #define FS_OFFSET_600_SD_DAS_INIT 0x0
// Nintendo Paths // Nintendo Paths

View File

@@ -34,6 +34,8 @@
#define FS_OFFSET_600_EXFAT_LOCK_MUTEX 0x14C9C0 #define FS_OFFSET_600_EXFAT_LOCK_MUTEX 0x14C9C0
#define FS_OFFSET_600_EXFAT_UNLOCK_MUTEX 0x14CA10 #define FS_OFFSET_600_EXFAT_UNLOCK_MUTEX 0x14CA10
#define FS_OFFSET_600_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x153C00
// Misc Data // Misc Data
#define FS_OFFSET_600_EXFAT_SD_MUTEX 0xFEB268 #define FS_OFFSET_600_EXFAT_SD_MUTEX 0xFEB268
#define FS_OFFSET_600_EXFAT_NAND_MUTEX 0xFE6BA0 #define FS_OFFSET_600_EXFAT_NAND_MUTEX 0xFE6BA0
@@ -41,7 +43,6 @@
#define FS_OFFSET_600_EXFAT_SDMMC_DAS_HANDLE 0xEE6670 #define FS_OFFSET_600_EXFAT_SDMMC_DAS_HANDLE 0xEE6670
// NOPs // NOPs
#define FS_OFFSET_600_EXFAT_SHUTDOWN_SD 0xBE628
#define FS_OFFSET_600_EXFAT_SD_DAS_INIT 0x0 #define FS_OFFSET_600_EXFAT_SD_DAS_INIT 0x0
// Nintendo Paths // Nintendo Paths

View File

@@ -34,6 +34,8 @@
#define FS_OFFSET_700_LOCK_MUTEX 0x148A90 #define FS_OFFSET_700_LOCK_MUTEX 0x148A90
#define FS_OFFSET_700_UNLOCK_MUTEX 0x148AE0 #define FS_OFFSET_700_UNLOCK_MUTEX 0x148AE0
#define FS_OFFSET_700_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x14FD50
// Misc Data // Misc Data
#define FS_OFFSET_700_SD_MUTEX 0xF123E8 #define FS_OFFSET_700_SD_MUTEX 0xF123E8
#define FS_OFFSET_700_NAND_MUTEX 0xF0DBE8 #define FS_OFFSET_700_NAND_MUTEX 0xF0DBE8
@@ -41,7 +43,6 @@
#define FS_OFFSET_700_SDMMC_DAS_HANDLE 0xE0E7A0 #define FS_OFFSET_700_SDMMC_DAS_HANDLE 0xE0E7A0
// NOPs // NOPs
#define FS_OFFSET_700_SHUTDOWN_SD 0xB8FCC
#define FS_OFFSET_700_SD_DAS_INIT 0x85FE8 #define FS_OFFSET_700_SD_DAS_INIT 0x85FE8
// Nintendo Paths // Nintendo Paths

View File

@@ -34,6 +34,8 @@
#define FS_OFFSET_700_EXFAT_LOCK_MUTEX 0x154040 #define FS_OFFSET_700_EXFAT_LOCK_MUTEX 0x154040
#define FS_OFFSET_700_EXFAT_UNLOCK_MUTEX 0x154090 #define FS_OFFSET_700_EXFAT_UNLOCK_MUTEX 0x154090
#define FS_OFFSET_700_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x15B300
// Misc Data // Misc Data
#define FS_OFFSET_700_EXFAT_SD_MUTEX 0xFF73E8 #define FS_OFFSET_700_EXFAT_SD_MUTEX 0xFF73E8
#define FS_OFFSET_700_EXFAT_NAND_MUTEX 0xFF2BE8 #define FS_OFFSET_700_EXFAT_NAND_MUTEX 0xFF2BE8
@@ -41,7 +43,6 @@
#define FS_OFFSET_700_EXFAT_SDMMC_DAS_HANDLE 0xEF3A00 #define FS_OFFSET_700_EXFAT_SDMMC_DAS_HANDLE 0xEF3A00
// NOPs // NOPs
#define FS_OFFSET_700_EXFAT_SHUTDOWN_SD 0xC457C
#define FS_OFFSET_700_EXFAT_SD_DAS_INIT 0x91598 #define FS_OFFSET_700_EXFAT_SD_DAS_INIT 0x91598
// Nintendo Paths // Nintendo Paths

View File

@@ -34,6 +34,8 @@
#define FS_OFFSET_800_LOCK_MUTEX 0x14B6D0 #define FS_OFFSET_800_LOCK_MUTEX 0x14B6D0
#define FS_OFFSET_800_UNLOCK_MUTEX 0x14B720 #define FS_OFFSET_800_UNLOCK_MUTEX 0x14B720
#define FS_OFFSET_800_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1529E0
// Misc Data // Misc Data
#define FS_OFFSET_800_SD_MUTEX 0xF1A3E8 #define FS_OFFSET_800_SD_MUTEX 0xF1A3E8
#define FS_OFFSET_800_NAND_MUTEX 0xF15BE8 #define FS_OFFSET_800_NAND_MUTEX 0xF15BE8
@@ -41,7 +43,6 @@
#define FS_OFFSET_800_SDMMC_DAS_HANDLE 0xE167C0 #define FS_OFFSET_800_SDMMC_DAS_HANDLE 0xE167C0
// NOPs // NOPs
#define FS_OFFSET_800_SHUTDOWN_SD 0xBAF6C
#define FS_OFFSET_800_SD_DAS_INIT 0x87D58 #define FS_OFFSET_800_SD_DAS_INIT 0x87D58
// Nintendo Paths // Nintendo Paths

View File

@@ -34,6 +34,8 @@
#define FS_OFFSET_800_EXFAT_LOCK_MUTEX 0x156C80 #define FS_OFFSET_800_EXFAT_LOCK_MUTEX 0x156C80
#define FS_OFFSET_800_EXFAT_UNLOCK_MUTEX 0x156CD0 #define FS_OFFSET_800_EXFAT_UNLOCK_MUTEX 0x156CD0
#define FS_OFFSET_800_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x15DF90
// Misc Data // Misc Data
#define FS_OFFSET_800_EXFAT_SD_MUTEX 0xFFE3E8 #define FS_OFFSET_800_EXFAT_SD_MUTEX 0xFFE3E8
#define FS_OFFSET_800_EXFAT_NAND_MUTEX 0xFF9BE8 #define FS_OFFSET_800_EXFAT_NAND_MUTEX 0xFF9BE8
@@ -41,7 +43,6 @@
#define FS_OFFSET_800_EXFAT_SDMMC_DAS_HANDLE 0xEFAA20 #define FS_OFFSET_800_EXFAT_SDMMC_DAS_HANDLE 0xEFAA20
// NOPs // NOPs
#define FS_OFFSET_800_EXFAT_SHUTDOWN_SD 0xC651C
#define FS_OFFSET_800_EXFAT_SD_DAS_INIT 0x93308 #define FS_OFFSET_800_EXFAT_SD_DAS_INIT 0x93308
// Nintendo Paths // Nintendo Paths

View File

@@ -34,6 +34,8 @@
#define FS_OFFSET_810_LOCK_MUTEX 0x14B6D0 #define FS_OFFSET_810_LOCK_MUTEX 0x14B6D0
#define FS_OFFSET_810_UNLOCK_MUTEX 0x14B720 #define FS_OFFSET_810_UNLOCK_MUTEX 0x14B720
#define FS_OFFSET_810_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1529E0
// Misc Data // Misc Data
#define FS_OFFSET_810_SD_MUTEX 0xF1A3E8 #define FS_OFFSET_810_SD_MUTEX 0xF1A3E8
#define FS_OFFSET_810_NAND_MUTEX 0xF15BE8 #define FS_OFFSET_810_NAND_MUTEX 0xF15BE8
@@ -41,7 +43,6 @@
#define FS_OFFSET_810_SDMMC_DAS_HANDLE 0xE167C0 #define FS_OFFSET_810_SDMMC_DAS_HANDLE 0xE167C0
// NOPs // NOPs
#define FS_OFFSET_810_SHUTDOWN_SD 0xBAF6C
#define FS_OFFSET_810_SD_DAS_INIT 0x87D58 #define FS_OFFSET_810_SD_DAS_INIT 0x87D58
// Nintendo Paths // Nintendo Paths

View File

@@ -34,6 +34,8 @@
#define FS_OFFSET_810_EXFAT_LOCK_MUTEX 0x156C80 #define FS_OFFSET_810_EXFAT_LOCK_MUTEX 0x156C80
#define FS_OFFSET_810_EXFAT_UNLOCK_MUTEX 0x156CD0 #define FS_OFFSET_810_EXFAT_UNLOCK_MUTEX 0x156CD0
#define FS_OFFSET_810_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x15DF90
// Misc Data // Misc Data
#define FS_OFFSET_810_EXFAT_SD_MUTEX 0xFFE3E8 #define FS_OFFSET_810_EXFAT_SD_MUTEX 0xFFE3E8
#define FS_OFFSET_810_EXFAT_NAND_MUTEX 0xFF9BE8 #define FS_OFFSET_810_EXFAT_NAND_MUTEX 0xFF9BE8
@@ -41,7 +43,6 @@
#define FS_OFFSET_810_EXFAT_SDMMC_DAS_HANDLE 0xEFAA20 #define FS_OFFSET_810_EXFAT_SDMMC_DAS_HANDLE 0xEFAA20
// NOPs // NOPs
#define FS_OFFSET_810_EXFAT_SHUTDOWN_SD 0xC651C
#define FS_OFFSET_810_EXFAT_SD_DAS_INIT 0x93308 #define FS_OFFSET_810_EXFAT_SD_DAS_INIT 0x93308
// Nintendo Paths // Nintendo Paths

View File

@@ -24,11 +24,13 @@
#include "../utils/types.h" #include "../utils/types.h"
#include "../utils/util.h" #include "../utils/util.h"
#include "../utils/fatal.h" #include "../utils/fatal.h"
#include "../emuMMC/emummc.h"
#define DPRINTF(...) //fprintf(stdout, __VA_ARGS__) #define DPRINTF(...) //fprintf(stdout, __VA_ARGS__)
sdmmc_accessor_t *_current_accessor = NULL; sdmmc_accessor_t *_current_accessor = NULL;
bool sdmmc_memcpy_buf = false; bool sdmmc_memcpy_buf = false;
extern bool custom_driver;
static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size) static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size)
{ {
@@ -52,25 +54,25 @@ intptr_t sdmmc_calculate_dma_addr(sdmmc_accessor_t *_this, void *buf, unsigned i
char *_buf = (char *)buf; char *_buf = (char *)buf;
char *actual_buf_start = _buf; char *actual_buf_start = _buf;
char *actual_buf_end = &_buf[512 * num_sectors]; char *actual_buf_end = &_buf[512 * num_sectors];
char *dma_buffer_start = _this->parent->dmaBuffers[FS_SDMMC_EMMC].device_addr_buffer; char *dma_buffer_start = _this->parent->dmaBuffers[0].device_addr_buffer;
if (dma_buffer_start <= _buf && actual_buf_end <= &dma_buffer_start[_this->parent->dmaBuffers[FS_SDMMC_EMMC].device_addr_buffer_size]) if (dma_buffer_start <= _buf && actual_buf_end <= &dma_buffer_start[_this->parent->dmaBuffers[0].device_addr_buffer_size])
{ {
dma_buf_idx = FS_SDMMC_EMMC; dma_buf_idx = 0;
} }
else else
{ {
dma_buffer_start = _this->parent->dmaBuffers[FS_SDMMC_SD].device_addr_buffer; dma_buffer_start = _this->parent->dmaBuffers[1].device_addr_buffer;
if (dma_buffer_start <= actual_buf_start && actual_buf_end <= &dma_buffer_start[_this->parent->dmaBuffers[FS_SDMMC_SD].device_addr_buffer_size]) if (dma_buffer_start <= actual_buf_start && actual_buf_end <= &dma_buffer_start[_this->parent->dmaBuffers[1].device_addr_buffer_size])
{ {
dma_buf_idx = FS_SDMMC_SD; dma_buf_idx = 1;
} }
else else
{ {
dma_buffer_start = _this->parent->dmaBuffers[FS_SDMMC_GC].device_addr_buffer; dma_buffer_start = _this->parent->dmaBuffers[2].device_addr_buffer;
if (dma_buffer_start <= actual_buf_start && actual_buf_end <= &dma_buffer_start[_this->parent->dmaBuffers[FS_SDMMC_GC].device_addr_buffer_size]) if (dma_buffer_start <= actual_buf_start && actual_buf_end <= &dma_buffer_start[_this->parent->dmaBuffers[2].device_addr_buffer_size])
{ {
dma_buf_idx = FS_SDMMC_GC; dma_buf_idx = 2;
} }
else else
{ {
@@ -86,30 +88,69 @@ intptr_t sdmmc_calculate_dma_addr(sdmmc_accessor_t *_this, void *buf, unsigned i
return admaaddr; return admaaddr;
} }
int sdmmc_get_fitting_dma_index(sdmmc_accessor_t *_this, unsigned int num_sectors) int sdmmc_calculate_dma_index(sdmmc_accessor_t *_this, void *buf, unsigned int num_sectors)
{ {
int dma_buf_idx = 0; int dma_buf_idx = 0;
int blkSize = num_sectors * 512; char *_buf = (char *)buf;
char *actual_buf_start = _buf;
char *actual_buf_end = &_buf[512 * num_sectors];
char *dma_buffer_start = _this->parent->dmaBuffers[0].device_addr_buffer;
if (_this->parent->dmaBuffers[FS_SDMMC_EMMC].device_addr_buffer_size >= blkSize) if (dma_buffer_start <= _buf && actual_buf_end <= &dma_buffer_start[_this->parent->dmaBuffers[0].device_addr_buffer_size])
{ {
dma_buf_idx = FS_SDMMC_EMMC; dma_buf_idx = 0;
} }
else else
{ {
if (_this->parent->dmaBuffers[FS_SDMMC_SD].device_addr_buffer_size >= blkSize) dma_buffer_start = _this->parent->dmaBuffers[1].device_addr_buffer;
if (dma_buffer_start <= actual_buf_start && actual_buf_end <= &dma_buffer_start[_this->parent->dmaBuffers[1].device_addr_buffer_size])
{ {
dma_buf_idx = FS_SDMMC_SD; dma_buf_idx = 1;
} }
else else
{ {
if (_this->parent->dmaBuffers[FS_SDMMC_GC].device_addr_buffer_size >= blkSize) dma_buffer_start = _this->parent->dmaBuffers[2].device_addr_buffer;
if (dma_buffer_start <= actual_buf_start && actual_buf_end <= &dma_buffer_start[_this->parent->dmaBuffers[2].device_addr_buffer_size])
{ {
dma_buf_idx = FS_SDMMC_GC; dma_buf_idx = 2;
} }
else else
{ {
// If buffer is on a random heap // If buffer is on a random heap
return -1;
}
}
}
sdmmc_memcpy_buf = false;
return dma_buf_idx;
}
int sdmmc_calculate_fitting_dma_index(sdmmc_accessor_t *_this, unsigned int num_sectors)
{
int dma_buf_idx = 0;
int blkSize = num_sectors * 512;
if (_this->parent->dmaBuffers[0].device_addr_buffer_size >= blkSize)
{
dma_buf_idx = 0;
}
else
{
if (_this->parent->dmaBuffers[1].device_addr_buffer_size >= blkSize)
{
dma_buf_idx = 1;
}
else
{
if (_this->parent->dmaBuffers[2].device_addr_buffer_size >= blkSize)
{
dma_buf_idx = 2;
}
else
{
// Can't find a fitting buffer
return 0; return 0;
} }
} }
@@ -266,14 +307,112 @@ out:;
return 1; return 1;
} }
extern _sdmmc_accessor_sd sdmmc_accessor_sd;
extern _sdmmc_accessor_nand sdmmc_accessor_nand;
int sdmmc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf) int sdmmc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf)
{ {
return _sdmmc_storage_readwrite(storage, sector, num_sectors, buf, 0); if (!custom_driver)
{
sdmmc_accessor_t *accessor_sd = sdmmc_accessor_sd();
sdmmc_accessor_t *accessor_nand = sdmmc_accessor_nand();
if (sdmmc_calculate_dma_addr(accessor_sd, buf, num_sectors))
{
return !accessor_sd->vtab->read_write(accessor_sd, sector, num_sectors, buf, num_sectors * 512, 1);
}
else
{
if (sdmmc_calculate_dma_addr(accessor_nand, buf, num_sectors))
{
// buf is on the nand dma buffer
int original_dma_idx = sdmmc_calculate_dma_index(accessor_nand, buf, num_sectors);
sdmmc_dma_buffer_t *original_dma_buffer = &accessor_nand->parent->dmaBuffers[original_dma_idx];
// Next entry
int dma_idx = sdmmc_calculate_fitting_dma_index(accessor_sd, num_sectors) + 1;
accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer = original_dma_buffer->device_addr_buffer;
accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer_masked = original_dma_buffer->device_addr_buffer_masked;
accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer_size = original_dma_buffer->device_addr_buffer_size;
u64 res = accessor_sd->vtab->read_write(accessor_sd, sector, num_sectors, buf, num_sectors * 512, 1);
accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer = 0;
accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer_masked = 0;
accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer_size = 0;
return !res;
}
else
{
// buf is on a heap
int dma_idx = sdmmc_calculate_fitting_dma_index(accessor_sd, num_sectors);
void *dma_buf = &accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer[0];
u64 res = accessor_sd->vtab->read_write(accessor_sd, sector, num_sectors, dma_buf, num_sectors * 512, 1);
memcpy(buf, dma_buf, num_sectors * 512);
return !res;
}
}
}
else
{
return _sdmmc_storage_readwrite(storage, sector, num_sectors, buf, 0);
}
} }
int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf) int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf)
{ {
return _sdmmc_storage_readwrite(storage, sector, num_sectors, buf, 1); if (!custom_driver)
{
sdmmc_accessor_t *accessor_sd = sdmmc_accessor_sd();
sdmmc_accessor_t *accessor_nand = sdmmc_accessor_nand();
if (sdmmc_calculate_dma_addr(accessor_sd, buf, num_sectors))
{
return !accessor_sd->vtab->read_write(accessor_sd, sector, num_sectors, buf, num_sectors * 512, 0);
}
else
{
if (sdmmc_calculate_dma_addr(accessor_nand, buf, num_sectors))
{
// buf is on the nand dma buffer
int original_dma_idx = sdmmc_calculate_dma_index(accessor_nand, buf, num_sectors);
sdmmc_dma_buffer_t *original_dma_buffer = &accessor_nand->parent->dmaBuffers[original_dma_idx];
// Next entry
int dma_idx = sdmmc_calculate_fitting_dma_index(accessor_sd, num_sectors) + 1;
accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer = original_dma_buffer->device_addr_buffer;
accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer_masked = original_dma_buffer->device_addr_buffer_masked;
accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer_size = original_dma_buffer->device_addr_buffer_size;
u64 res = accessor_sd->vtab->read_write(accessor_sd, sector, num_sectors, buf, num_sectors * 512, 0);
accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer = 0;
accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer_masked = 0;
accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer_size = 0;
return !res;
}
else
{
// buf is on a heap
int dma_idx = sdmmc_calculate_fitting_dma_index(accessor_sd, num_sectors);
void *dma_buf = &accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer[0];
memcpy(dma_buf, buf, num_sectors * 512);
u64 res = accessor_sd->vtab->read_write(accessor_sd, sector, num_sectors, dma_buf, num_sectors * 512, 0);
return !res;
}
}
}
else
{
return _sdmmc_storage_readwrite(storage, sector, num_sectors, buf, 1);
}
} }
/* /*
@@ -703,7 +842,7 @@ static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, i
if (cond & SD_OCR_CCS) if (cond & SD_OCR_CCS)
storage->has_sector_access = 1; storage->has_sector_access = 1;
if (false && cond & SD_ROCR_S18A && supports_low_voltage) if (cond & SD_ROCR_S18A && supports_low_voltage)
{ {
//The low voltage regulator configuration is valid for SDMMC1 only. //The low voltage regulator configuration is valid for SDMMC1 only.
if (storage->sdmmc->id == SDMMC_1 && if (storage->sdmmc->id == SDMMC_1 &&

View File

@@ -114,6 +114,7 @@ int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition);
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32 bus_width, u32 type); int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32 bus_width, u32 type);
int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc); int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc);
intptr_t sdmmc_calculate_dma_addr(sdmmc_accessor_t *_this, void *buf, unsigned int num_sectors); intptr_t sdmmc_calculate_dma_addr(sdmmc_accessor_t *_this, void *buf, unsigned int num_sectors);
int sdmmc_get_fitting_dma_index(sdmmc_accessor_t *_this, unsigned int num_sectors); int sdmmc_calculate_dma_index(sdmmc_accessor_t *_this, void *buf, unsigned int num_sectors);
int sdmmc_calculate_fitting_dma_index(sdmmc_accessor_t *_this, unsigned int num_sectors);
#endif #endif

View File

@@ -641,23 +641,6 @@ static int _sdmmc_autocal_config_offset(sdmmc_t *sdmmc, u32 power)
static void _sdmmc_autocal_execute(sdmmc_t *sdmmc, u32 power) static void _sdmmc_autocal_execute(sdmmc_t *sdmmc, u32 power)
{ {
if(sdmmc->id == SDMMC_1)
{
static int last_power = SDMMC_POWER_3_3;
if(power == SDMMC_POWER_1_8 && last_power == SDMMC_POWER_3_3)
{
last_power = power = SDMMC_POWER_1_8;
if (!_sdmmc_autocal_config_offset(sdmmc, power))
return;
}
else if(power == SDMMC_POWER_3_3 && last_power == SDMMC_POWER_1_8)
{
last_power = power = SDMMC_POWER_3_3;
if (!_sdmmc_autocal_config_offset(sdmmc, power))
return;
}
}
bool should_enable_sd_clock = false; bool should_enable_sd_clock = false;
if (sdmmc->regs->clkcon & TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE) if (sdmmc->regs->clkcon & TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE)
{ {
@@ -811,7 +794,7 @@ static int _sdmmc_config_dma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req)
if (!admaaddr) if (!admaaddr)
{ {
// buf is on a heap // buf is on a heap
int dma_idx = sdmmc_get_fitting_dma_index(_current_accessor, blkcnt); int dma_idx = sdmmc_calculate_fitting_dma_index(_current_accessor, blkcnt);
admaaddr = (u64)&_current_accessor->parent->dmaBuffers[dma_idx].device_addr_buffer_masked[0]; admaaddr = (u64)&_current_accessor->parent->dmaBuffers[dma_idx].device_addr_buffer_masked[0];
sdmmc->last_dma_idx = dma_idx; sdmmc->last_dma_idx = dma_idx;
} }
@@ -1011,10 +994,13 @@ static int _sdmmc_config_sdmmc1()
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT1) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP; PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT1) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP;
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT0) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP; PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT0) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP;
//Make sure SDMMC1 controller is reset.
smcReadWriteRegister(PMC_BASE + APBDEV_PMC_NO_IOPOWER, (1 << 12), (1 << 12));
usleep(1000);
//Make sure the SDMMC1 controller is powered. //Make sure the SDMMC1 controller is powered.
//PMC(APBDEV_PMC_NO_IOPOWER) &= ~(1 << 12); smcReadWriteRegister(PMC_BASE + APBDEV_PMC_NO_IOPOWER, ~(1 << 12), (1 << 12));
//Assume 3.3V SD card voltage. smcReadWriteRegister(PMC_BASE + APBDEV_PMC_PWR_DET_VAL, (1 << 12), (1 << 12));
//PMC(APBDEV_PMC_PWR_DET_VAL) |= (1 << 12);
//Set enable SD card power. //Set enable SD card power.
PINMUX_AUX(PINMUX_AUX_DMIC3_CLK) = PINMUX_INPUT_ENABLE | PINMUX_PULL_DOWN | 1; //GPIO control, pull down. PINMUX_AUX(PINMUX_AUX_DMIC3_CLK) = PINMUX_INPUT_ENABLE | PINMUX_PULL_DOWN | 1; //GPIO control, pull down.
@@ -1025,10 +1011,10 @@ static int _sdmmc_config_sdmmc1()
usleep(1000); usleep(1000);
//Enable SD card power. //Enable SD card power.
//max77620_regulator_set_voltage(REGULATOR_LDO2, 3300000); max77620_regulator_set_voltage(REGULATOR_LDO2, 3300000);
//max77620_regulator_enable(REGULATOR_LDO2, 1); max77620_regulator_enable(REGULATOR_LDO2, 1);
//usleep(1000); usleep(1000);
//For good measure. //For good measure.
APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL) = 0x10000000; APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL) = 0x10000000;
@@ -1071,7 +1057,7 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int n
sdmmc->regs->veniotrimctl &= 0xFFFFFFFB; sdmmc->regs->veniotrimctl &= 0xFFFFFFFB;
static const u32 trim_values[] = { 2, 8, 3, 8 }; static const u32 trim_values[] = { 2, 8, 3, 8 };
sdmmc->regs->venclkctl = (sdmmc->regs->venclkctl & 0xE0FFFFFF) | (trim_values[sdmmc->id] << 24); sdmmc->regs->venclkctl = (sdmmc->regs->venclkctl & 0xE0FFFFFF) | (trim_values[sdmmc->id] << 24);
sdmmc->regs->sdmemcmppadctl = (sdmmc->regs->sdmemcmppadctl & 0xF) | 7; sdmmc->regs->sdmemcmppadctl = (sdmmc->regs->sdmemcmppadctl & 0xFFFFFFF0) | 7;
if (!_sdmmc_autocal_config_offset(sdmmc, power)) if (!_sdmmc_autocal_config_offset(sdmmc, power))
return 0; return 0;
_sdmmc_autocal_execute(sdmmc, power); _sdmmc_autocal_execute(sdmmc, power);
@@ -1103,8 +1089,9 @@ void sdmmc_end(sdmmc_t *sdmmc)
if (sdmmc->id == SDMMC_1) if (sdmmc->id == SDMMC_1)
{ {
gpio_output_enable(GPIO_PORT_E, GPIO_PIN_4, GPIO_OUTPUT_DISABLE); gpio_output_enable(GPIO_PORT_E, GPIO_PIN_4, GPIO_OUTPUT_DISABLE);
//max77620_regulator_enable(REGULATOR_LDO2, 0); msleep(1); // To power cycle min 1ms without power is needed.
msleep(100); // To power cycle min 1ms without power is needed. max77620_regulator_enable(REGULATOR_LDO2, 0);
msleep(100); // Some extra.
} }
_sdmmc_get_clkcon(sdmmc); _sdmmc_get_clkcon(sdmmc);
@@ -1158,7 +1145,7 @@ int sdmmc_enable_low_voltage(sdmmc_t *sdmmc)
_sdmmc_get_clkcon(sdmmc); _sdmmc_get_clkcon(sdmmc);
max77620_regulator_set_voltage(REGULATOR_LDO2, 1800000); max77620_regulator_set_voltage(REGULATOR_LDO2, 1800000);
PMC(APBDEV_PMC_PWR_DET_VAL) &= ~(1 << 12); smcReadWriteRegister(PMC_BASE + APBDEV_PMC_PWR_DET_VAL, ~(1 << 12), (1 << 12));
_sdmmc_autocal_config_offset(sdmmc, SDMMC_POWER_1_8); _sdmmc_autocal_config_offset(sdmmc, SDMMC_POWER_1_8);
_sdmmc_autocal_execute(sdmmc, SDMMC_POWER_1_8); _sdmmc_autocal_execute(sdmmc, SDMMC_POWER_1_8);

View File

@@ -92,26 +92,9 @@ static void _sdmmc_ensure_initialized(void)
} }
} }
void sdmmc_finalize(void)
{
if (!sdmmc_storage_end(&sd_storage))
{
fatal_abort(Fatal_InitSD);
}
storageSDinitialized = false;
}
static void _file_based_update_filename(char *outFilename, u32 sd_path_len, u32 part_idx) static void _file_based_update_filename(char *outFilename, u32 sd_path_len, u32 part_idx)
{ {
if (part_idx < 10) snprintf(outFilename + sd_path_len, 3, "%02d", part_idx);
{
outFilename[sd_path_len] = '0';
itoa(part_idx, &outFilename[sd_path_len + 1], 10);
}
else
{
itoa(part_idx, &outFilename[sd_path_len], 10);
}
} }
static void _file_based_emmc_finalize(void) static void _file_based_emmc_finalize(void)
@@ -119,11 +102,13 @@ static void _file_based_emmc_finalize(void)
if ((emuMMC_ctx.EMMC_Type == emuMMC_SD_File) && fat_mounted) if ((emuMMC_ctx.EMMC_Type == emuMMC_SD_File) && fat_mounted)
{ {
// Close all open handles. // Close all open handles.
f_close(f_emu.fp_boot0); f_close(&f_emu.fp_boot0);
f_close(f_emu.fp_boot1); f_close(&f_emu.fp_boot1);
for (int i = 0; i < f_emu.parts; i++) for (int i = 0; i < f_emu.parts; i++)
f_close(f_emu.fp_gpp[i]); {
f_close(&f_emu.fp_gpp[i]);
}
// Force unmount FAT volume. // Force unmount FAT volume.
f_mount(NULL, "", 1); f_mount(NULL, "", 1);
@@ -132,6 +117,18 @@ static void _file_based_emmc_finalize(void)
} }
} }
void sdmmc_finalize(void)
{
_file_based_emmc_finalize();
if (!sdmmc_storage_end(&sd_storage))
{
fatal_abort(Fatal_InitSD);
}
storageSDinitialized = false;
}
static void _file_based_emmc_initialize(void) static void _file_based_emmc_initialize(void)
{ {
char path[sizeof(emuMMC_ctx.storagePath) + 0x20]; char path[sizeof(emuMMC_ctx.storagePath) + 0x20];
@@ -143,36 +140,32 @@ static void _file_based_emmc_initialize(void)
int path_len = strlen(path); int path_len = strlen(path);
// Open BOOT0 physical partition. // Open BOOT0 physical partition.
f_emu.fp_boot0 = (FIL *)malloc(sizeof(FIL));
memcpy(path + path_len, "BOOT0", 6); memcpy(path + path_len, "BOOT0", 6);
if (f_open(f_emu.fp_boot0, path, FA_READ | FA_WRITE) != FR_OK) if (f_open(&f_emu.fp_boot0, path, FA_READ | FA_WRITE) != FR_OK)
fatal_abort(Fatal_InitSD); fatal_abort(Fatal_InitSD);
// Open BOOT1 physical partition. // Open BOOT1 physical partition.
f_emu.fp_boot1 = (FIL *)malloc(sizeof(FIL));
memcpy(path + path_len, "BOOT1", 6); memcpy(path + path_len, "BOOT1", 6);
if (f_open(f_emu.fp_boot1, path, FA_READ | FA_WRITE) != FR_OK) if (f_open(&f_emu.fp_boot1, path, FA_READ | FA_WRITE) != FR_OK)
fatal_abort(Fatal_InitSD); fatal_abort(Fatal_InitSD);
// Open handles for GPP physical partition files. // Open handles for GPP physical partition files.
_file_based_update_filename(path, path_len, 00); _file_based_update_filename(path, path_len, 00);
if (f_open(f_emu.fp_gpp[0], path, FA_READ | FA_WRITE) != FR_OK)
if (f_open(&f_emu.fp_gpp[0], path, FA_READ | FA_WRITE) != FR_OK)
fatal_abort(Fatal_InitSD); fatal_abort(Fatal_InitSD);
f_emu.part_size = f_size(f_emu.fp_gpp[0]); f_emu.part_size = f_size(&f_emu.fp_gpp[0]) >> 9;
// Iterate folder for split parts and stop if next doesn't exist. // Iterate folder for split parts and stop if next doesn't exist.
// Supports up to 32 parts of any size. // Supports up to 32 parts of any size.
// TODO: decide on max parts and define them. (hekate produces up to 30 parts on 1GB mode.) // TODO: decide on max parts and define them. (hekate produces up to 30 parts on 1GB mode.)
for (f_emu.parts = 1; f_emu.parts < 32; f_emu.parts++) for (f_emu.parts = 1; f_emu.parts < 32; f_emu.parts++)
{ {
f_emu.fp_gpp[f_emu.parts] = (FIL *)malloc(sizeof(FIL));
_file_based_update_filename(path, path_len, f_emu.parts); _file_based_update_filename(path, path_len, f_emu.parts);
if (f_open(f_emu.fp_gpp[f_emu.parts], path, FA_READ | FA_WRITE) != FR_OK) if (f_open(&f_emu.fp_gpp[f_emu.parts], path, FA_READ | FA_WRITE) != FR_OK)
{ {
free(f_emu.fp_gpp[f_emu.parts]);
// Check if single file. // Check if single file.
if (f_emu.parts == 1) if (f_emu.parts == 1)
f_emu.parts = 0; f_emu.parts = 0;
@@ -257,14 +250,20 @@ sdmmc_accessor_t *sdmmc_accessor_get(int mmc_id)
void mutex_lock_handler(int mmc_id) void mutex_lock_handler(int mmc_id)
{ {
lock_mutex(sd_mutex); if (custom_driver)
{
lock_mutex(sd_mutex);
}
lock_mutex(nand_mutex); lock_mutex(nand_mutex);
} }
void mutex_unlock_handler(int mmc_id) void mutex_unlock_handler(int mmc_id)
{ {
unlock_mutex(nand_mutex); unlock_mutex(nand_mutex);
unlock_mutex(sd_mutex); if (custom_driver)
{
unlock_mutex(sd_mutex);
}
} }
int sdmmc_nand_get_active_partition_index() int sdmmc_nand_get_active_partition_index()
@@ -303,19 +302,19 @@ static uint64_t emummc_read_write_inner(void *buf, unsigned int sector, unsigned
case FS_EMMC_PARTITION_GPP: case FS_EMMC_PARTITION_GPP:
if (f_emu.parts) if (f_emu.parts)
{ {
fp_tmp = f_emu.fp_gpp[sector / f_emu.part_size]; fp_tmp = &f_emu.fp_gpp[sector / f_emu.part_size];
sector = sector % f_emu.part_size; sector = sector % f_emu.part_size;
} }
else else
{ {
fp_tmp = f_emu.fp_gpp[0]; fp_tmp = &f_emu.fp_gpp[0];
} }
break; break;
case FS_EMMC_PARTITION_BOOT1: case FS_EMMC_PARTITION_BOOT1:
fp_tmp = f_emu.fp_boot1; fp_tmp = &f_emu.fp_boot1;
break; break;
case FS_EMMC_PARTITION_BOOT0: case FS_EMMC_PARTITION_BOOT0:
fp_tmp = f_emu.fp_boot0; fp_tmp = &f_emu.fp_boot0;
break; break;
} }
@@ -324,10 +323,44 @@ static uint64_t emummc_read_write_inner(void *buf, unsigned int sector, unsigned
; //TODO. Out of range. close stuff and fatal? ; //TODO. Out of range. close stuff and fatal?
} }
uint64_t res = 0;
if (!is_write) if (!is_write)
return !(f_read(fp_tmp, buf, num_sectors << 9, NULL)); res = !(f_read(fp_tmp, buf, num_sectors << 9, NULL));
else else
return !(f_write(fp_tmp, buf, num_sectors << 9, NULL)); res = !(f_write(fp_tmp, buf, num_sectors << 9, NULL));
return res;
}
// Controller close wrapper
uint64_t sdmmc_wrapper_controller_close(int mmc_id)
{
sdmmc_accessor_t *_this;
_this = sdmmc_accessor_get(mmc_id);
if (_this != NULL)
{
if (mmc_id == FS_SDMMC_SD)
{
return 0;
}
if (mmc_id == FS_SDMMC_EMMC)
{
// Close file handles and unmount
_file_based_emmc_finalize();
// Close SD
sdmmc_accessor_get(FS_SDMMC_SD)->vtab->sdmmc_accessor_controller_close(sdmmc_accessor_get(FS_SDMMC_SD));
// Close eMMC
return _this->vtab->sdmmc_accessor_controller_close(_this);
}
return _this->vtab->sdmmc_accessor_controller_close(_this);
}
fatal_abort(Fatal_CloseAccessor);
} }
// FS read wrapper. // FS read wrapper.
@@ -366,6 +399,18 @@ uint64_t sdmmc_wrapper_read(void *buf, uint64_t bufSize, int mmc_id, unsigned in
if (mmc_id == FS_SDMMC_SD) if (mmc_id == FS_SDMMC_SD)
{ {
static bool first_sd_read = true;
if (first_sd_read)
{
first_sd_read = false;
// Because some SD cards have issues with emuMMC's driver
// we currently swap to FS's driver after first SD read
// TODO: Fix remaining driver issues
custom_driver = false;
// FS will handle sd mutex w/o custom driver from here on
unlock_mutex(sd_mutex);
}
// Call hekates driver. // Call hekates driver.
if (sdmmc_storage_read(&sd_storage, sector, num_sectors, buf)) if (sdmmc_storage_read(&sd_storage, sector, num_sectors, buf))
{ {

View File

@@ -50,6 +50,8 @@ sdmmc_accessor_t *sdmmc_accessor_get(int mmc_id);
void mutex_lock_handler(int mmc_id); void mutex_lock_handler(int mmc_id);
void mutex_unlock_handler(int mmc_id); void mutex_unlock_handler(int mmc_id);
// Hooks
uint64_t sdmmc_wrapper_controller_close(int mmc_id);
uint64_t sdmmc_wrapper_read(void *buf, uint64_t bufSize, int mmc_id, unsigned int sector, unsigned int num_sectors); uint64_t sdmmc_wrapper_read(void *buf, uint64_t bufSize, int mmc_id, unsigned int sector, unsigned int num_sectors);
uint64_t sdmmc_wrapper_write(int mmc_id, unsigned int sector, unsigned int num_sectors, void *buf, uint64_t bufSize); uint64_t sdmmc_wrapper_write(int mmc_id, unsigned int sector, unsigned int num_sectors, void *buf, uint64_t bufSize);
@@ -59,9 +61,9 @@ typedef struct _file_based_ctxt
uint64_t parts; uint64_t parts;
uint64_t part_size; uint64_t part_size;
FATFS *sd_fs; FATFS *sd_fs;
FIL *fp_boot0; FIL fp_boot0;
FIL *fp_boot1; FIL fp_boot1;
FIL *fp_gpp[32]; FIL fp_gpp[32];
} file_based_ctxt; } file_based_ctxt;
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -22,6 +22,8 @@
#include <string.h> #include <string.h>
#include "nx/svc.h" #include "nx/svc.h"
#include "nx/smc.h" #include "nx/smc.h"
#include "soc/clock.h"
#include "soc/i2c.h"
#include "emuMMC/emummc.h" #include "emuMMC/emummc.h"
#include "emuMMC/emummc_ctx.h" #include "emuMMC/emummc_ctx.h"
#include "FS/FS_offsets.h" #include "FS/FS_offsets.h"
@@ -174,6 +176,8 @@ void setup_hooks(void)
INJECT_HOOK(fs_offsets->sdmmc_wrapper_read, sdmmc_wrapper_read); INJECT_HOOK(fs_offsets->sdmmc_wrapper_read, sdmmc_wrapper_read);
// sdmmc_wrapper_write hook // sdmmc_wrapper_write hook
INJECT_HOOK(fs_offsets->sdmmc_wrapper_write, sdmmc_wrapper_write); INJECT_HOOK(fs_offsets->sdmmc_wrapper_write, sdmmc_wrapper_write);
// sdmmc_wrapper_controller_close hook
INJECT_HOOK(fs_offsets->sdmmc_accessor_controller_close, sdmmc_wrapper_controller_close);
// On 8.0.0+, we need to hook the regulator setup, because // On 8.0.0+, we need to hook the regulator setup, because
// otherwise it will abort because we have already turned it on. // otherwise it will abort because we have already turned it on.
@@ -203,10 +207,6 @@ void populate_function_pointers(void)
void write_nops(void) void write_nops(void)
{ {
// This NOPs out a call to ShutdownSdCard when preparing for shutdown/reboot.
// This prevents the PatrolReader from hanging when saving its state, which
// occurs immediately afterwards (in ShutdownMmc).
INJECT_NOP(fs_offsets->shutdown_sd);
// On 7.0.0+, we need to attach to device address space ourselves. // On 7.0.0+, we need to attach to device address space ourselves.
// This patches an abort that happens when Nintendo's code sees SD // This patches an abort that happens when Nintendo's code sees SD
// is already attached // is already attached
@@ -316,4 +316,7 @@ void __init()
populate_function_pointers(); populate_function_pointers();
write_nops(); write_nops();
setup_nintendo_paths(); setup_nintendo_paths();
clock_enable_i2c5();
i2c_init();
} }

View File

@@ -20,7 +20,8 @@
#include "../utils/util.h" #include "../utils/util.h"
#include "t210.h" #include "t210.h"
static u32 i2c_addrs[] = { // TODO: not hardcode I2C_5
static u64 i2c_addrs[] = {
0x7000C000, 0x7000C400, 0x7000C500, 0x7000C000, 0x7000C400, 0x7000C500,
0x7000C700, 0x7000D000, 0x7000D100 0x7000C700, 0x7000D000, 0x7000D100
}; };
@@ -28,6 +29,7 @@ static u32 i2c_addrs[] = {
static void _i2c_wait(vu32 *base) static void _i2c_wait(vu32 *base)
{ {
base[I2C_CONFIG_LOAD] = 0x25; base[I2C_CONFIG_LOAD] = 0x25;
for (u32 i = 0; i < 20; i++) for (u32 i = 0; i < 20; i++)
{ {
usleep(1); usleep(1);
@@ -44,8 +46,7 @@ static int _i2c_send_pkt(u32 idx, u32 x, u8 *buf, u32 size)
u32 tmp = 0; u32 tmp = 0;
memcpy(&tmp, buf, size); memcpy(&tmp, buf, size);
vu32 *base = (vu32 *)QueryIoMapping(i2c_addrs[0], 0x2000); vu32 *base = (vu32 *)QueryIoMapping(i2c_addrs[I2C_5], 0x1000);
base = base + (i2c_addrs[idx] - i2c_addrs[0]);
base[I2C_CMD_ADDR0] = x << 1; //Set x (send mode). base[I2C_CMD_ADDR0] = x << 1; //Set x (send mode).
base[I2C_CMD_DATA1] = tmp; //Set value. base[I2C_CMD_DATA1] = tmp; //Set value.
base[I2C_CNFG] = (2 * size - 2) | 0x2800; //Set size and send mode. base[I2C_CNFG] = (2 * size - 2) | 0x2800; //Set size and send mode.
@@ -66,8 +67,7 @@ static int _i2c_recv_pkt(u32 idx, u8 *buf, u32 size, u32 x)
if (size > 8) if (size > 8)
return 0; return 0;
vu32 *base = (vu32 *)QueryIoMapping(i2c_addrs[0], 0x2000); vu32 *base = (vu32 *)QueryIoMapping(i2c_addrs[I2C_5], 0x1000);
base = base + (i2c_addrs[idx] - i2c_addrs[0]);
base[I2C_CMD_ADDR0] = (x << 1) | 1; // Set x (recv mode). base[I2C_CMD_ADDR0] = (x << 1) | 1; // Set x (recv mode).
base[I2C_CNFG] = (size - 1) << 1 | 0x2840; // Set size and recv mode. base[I2C_CNFG] = (size - 1) << 1 | 0x2840; // Set size and recv mode.
@@ -93,10 +93,9 @@ static int _i2c_recv_pkt(u32 idx, u8 *buf, u32 size, u32 x)
return 1; return 1;
} }
void i2c_init(u32 idx) void i2c_init()
{ {
vu32 *base = (vu32 *)QueryIoMapping(i2c_addrs[0], 0x2000); vu32 *base = (vu32 *)QueryIoMapping(i2c_addrs[I2C_5], 0x1000);
base = base + (i2c_addrs[idx] - i2c_addrs[0]);
base[I2C_CLK_DIVISOR_REGISTER] = 0x50001; base[I2C_CLK_DIVISOR_REGISTER] = 0x50001;
base[I2C_BUS_CLEAR_CONFIG] = 0x90003; base[I2C_BUS_CLEAR_CONFIG] = 0x90003;
@@ -104,7 +103,6 @@ void i2c_init(u32 idx)
for (u32 i = 0; i < 10; i++) for (u32 i = 0; i < 10; i++)
{ {
usleep(20000);
if (base[INTERRUPT_STATUS_REGISTER] & 0x800) if (base[INTERRUPT_STATUS_REGISTER] & 0x800)
break; break;
} }

View File

@@ -37,7 +37,7 @@
#define I2C_BUS_CLEAR_STATUS 0x22 #define I2C_BUS_CLEAR_STATUS 0x22
#define I2C_CONFIG_LOAD 0x23 #define I2C_CONFIG_LOAD 0x23
void i2c_init(u32 idx); void i2c_init();
int i2c_send_buf_small(u32 idx, u32 x, u32 y, u8 *buf, u32 size); int i2c_send_buf_small(u32 idx, u32 x, u32 y, u8 *buf, u32 size);
int i2c_recv_buf_small(u8 *buf, u32 size, u32 idx, u32 x, u32 y); int i2c_recv_buf_small(u8 *buf, u32 size, u32 idx, u32 x, u32 y);
int i2c_send_byte(u32 idx, u32 x, u32 y, u8 b); int i2c_send_byte(u32 idx, u32 x, u32 y, u8 b);

View File

@@ -28,6 +28,7 @@ enum FatalReason {
Fatal_UnknownVersion, Fatal_UnknownVersion,
Fatal_BadResult, Fatal_BadResult,
Fatal_GetConfig, Fatal_GetConfig,
Fatal_CloseAccessor,
Fatal_Max Fatal_Max
}; };

View File

@@ -109,7 +109,7 @@ int emu_device_partition_read_data(device_partition_t *devpart, void *dst, uint6
/* Treat the path as a folder with each part inside. */ /* Treat the path as a folder with each part inside. */
snprintf(target_path, sizeof(target_path) - 1, "%s/%02d", origin_path, target_part); snprintf(target_path, sizeof(target_path) - 1, "%s/%02d", origin_path, target_part);
} else { } else {
target_sector = sector; /* If there are no parts, copy the origin path directly. */
strcpy(target_path, origin_path); strcpy(target_path, origin_path);
} }
@@ -182,7 +182,7 @@ int emu_device_partition_write_data(device_partition_t *devpart, const void *src
/* Treat the path as a folder with each part inside. */ /* Treat the path as a folder with each part inside. */
snprintf(target_path, sizeof(target_path) - 1, "%s/%02d", origin_path, target_part); snprintf(target_path, sizeof(target_path) - 1, "%s/%02d", origin_path, target_part);
} else { } else {
target_sector = sector; /* If there are no parts, copy the origin path directly. */
strcpy(target_path, origin_path); strcpy(target_path, origin_path);
} }

View File

@@ -80,7 +80,7 @@ static emudev_device_t *emudev_find_device(const char *name) {
return NULL; return NULL;
} }
int emudev_mount_device(const char *name, const device_partition_t *devpart, const char *origin_path) { int emudev_mount_device(const char *name, const device_partition_t *devpart, const char *origin_path, int num_parts, uint64_t part_limit) {
emudev_device_t *device = NULL; emudev_device_t *device = NULL;
if (name[0] == '\0' || devpart == NULL) { if (name[0] == '\0' || devpart == NULL) {
@@ -120,80 +120,6 @@ int emudev_mount_device(const char *name, const device_partition_t *devpart, con
if (devpart->emu_use_file) if (devpart->emu_use_file)
strcpy(device->origin_path, origin_path); strcpy(device->origin_path, origin_path);
device->num_parts = 0;
device->part_limit = 0;
device->devoptab.name = device->name;
device->devoptab.deviceData = device;
/* Initialize immediately. */
int rc = device->devpart.initializer(&device->devpart);
if (rc != 0) {
errno = rc;
return -1;
}
/* Allocate memory for our intermediate sector. */
device->tmp_sector = (uint8_t *)malloc(devpart->sector_size);
if (device->tmp_sector == NULL) {
errno = ENOMEM;
return -1;
}
device->setup = true;
device->registered = false;
return 0;
}
int emudev_mount_device_multipart(const char *name, const device_partition_t *devpart, const char *origin_path, int num_parts, uint64_t part_limit) {
emudev_device_t *device = NULL;
if (name[0] == '\0' || devpart == NULL) {
errno = EINVAL;
return -1;
}
if (strlen(name) > 32) {
errno = ENAMETOOLONG;
return -1;
}
if (emudev_find_device(name) != NULL) {
errno = EEXIST; /* Device already exists */
return -1;
}
/* Invalid number of parts. */
if (num_parts <= 1) {
errno = EINVAL;
return -1;
}
/* Part limit is invalid. */
if ((part_limit % (1ull << 30)) != 0) {
errno = EINVAL;
return -1;
}
/* Find an unused slot. */
for (size_t i = 0; i < EMUDEV_MAX_DEVICES; i++) {
if (!g_emudev_devices[i].setup) {
device = &g_emudev_devices[i];
break;
}
}
if (device == NULL) {
errno = ENOMEM;
return -1;
}
memset(device, 0, sizeof(emudev_device_t));
device->devoptab = g_emudev_devoptab;
device->devpart = *devpart;
strcpy(device->name, name);
strcpy(device->root_path, name);
strcat(device->root_path, ":/");
strcpy(device->origin_path, origin_path);
device->num_parts = num_parts; device->num_parts = num_parts;
device->part_limit = part_limit; device->part_limit = part_limit;

View File

@@ -24,8 +24,7 @@
#define EMUDEV_MAX_DEVICES 16 #define EMUDEV_MAX_DEVICES 16
int emudev_mount_device(const char *name, const device_partition_t *devpart, const char *origin_path); int emudev_mount_device(const char *name, const device_partition_t *devpart, const char *origin_path, int num_parts, uint64_t part_limit);
int emudev_mount_device_multipart(const char *name, const device_partition_t *devpart, const char *origin_path, int num_parts, uint64_t part_limit);
int emudev_register_device(const char *name); int emudev_register_device(const char *name);
int emudev_unregister_device(const char *name); int emudev_unregister_device(const char *name);
int emudev_unmount_device(const char *name); /* also unregisters. */ int emudev_unmount_device(const char *name); /* also unregisters. */

View File

@@ -113,7 +113,7 @@ int gpt_iterate_through_entries(FILE *disk, size_t sector_size, gpt_entry_iterat
return 0; return 0;
} }
int gpt_iterate_through_emu_entries(FILE *disk, size_t sector_size, gpt_emu_entry_iterator_t callback, void *param, const char *origin_path, bool is_multipart, int num_parts, uint64_t part_limit) { int gpt_iterate_through_emu_entries(FILE *disk, size_t sector_size, gpt_emu_entry_iterator_t callback, void *param, const char *origin_path, int num_parts, uint64_t part_limit) {
efi_header_t hdr; efi_header_t hdr;
efi_entry_t entry; efi_entry_t entry;
size_t offset = 2 * 512; /* Sector #2. */ size_t offset = 2 * 512; /* Sector #2. */
@@ -138,7 +138,7 @@ int gpt_iterate_through_emu_entries(FILE *disk, size_t sector_size, gpt_emu_entr
return -1; return -1;
} }
if (callback(&entry, param, offset, disk, origin_path, is_multipart, num_parts, part_limit) != 0) { if (callback(&entry, param, offset, disk, origin_path, num_parts, part_limit) != 0) {
return -1; return -1;
} }

View File

@@ -52,10 +52,10 @@ typedef struct efi_header {
} __attribute__((packed, aligned(4))) efi_header_t; } __attribute__((packed, aligned(4))) efi_header_t;
typedef int (*gpt_entry_iterator_t)(const efi_entry_t *entry, void *param, size_t entry_offset, FILE *disk); typedef int (*gpt_entry_iterator_t)(const efi_entry_t *entry, void *param, size_t entry_offset, FILE *disk);
typedef int (*gpt_emu_entry_iterator_t)(const efi_entry_t *entry, void *param, size_t entry_offset, FILE *disk, const char *origin_path, bool is_multipart, int num_parts, uint64_t part_limit); typedef int (*gpt_emu_entry_iterator_t)(const efi_entry_t *entry, void *param, size_t entry_offset, FILE *disk, const char *origin_path, int num_parts, uint64_t part_limit);
int gpt_get_header(efi_header_t *out, FILE *disk, size_t sector_size); int gpt_get_header(efi_header_t *out, FILE *disk, size_t sector_size);
int gpt_iterate_through_entries(FILE *disk, size_t sector_size, gpt_entry_iterator_t callback, void *param); int gpt_iterate_through_entries(FILE *disk, size_t sector_size, gpt_entry_iterator_t callback, void *param);
int gpt_iterate_through_emu_entries(FILE *disk, size_t sector_size, gpt_emu_entry_iterator_t callback, void *param, const char *origin_path, bool is_multipart, int num_parts, uint64_t part_limit); int gpt_iterate_through_emu_entries(FILE *disk, size_t sector_size, gpt_emu_entry_iterator_t callback, void *param, const char *origin_path, int num_parts, uint64_t part_limit);
#endif #endif

View File

@@ -223,7 +223,14 @@ static uint32_t nxboot_get_target_firmware(const void *package1loader) {
} }
static bool nxboot_configure_emummc(exo_emummc_config_t *exo_emummc_config) { static bool nxboot_configure_emummc(exo_emummc_config_t *exo_emummc_config) {
emummc_config_t emummc_cfg = {.enabled = false, .id = 0, .sector = -1, .path = "", .nintendo_path = ""}; emummc_config_t emummc_cfg = {.enabled = false, .id = 0, .sector = 0, .path = "", .nintendo_path = ""};
/* Initialize some defaults. */
memset(exo_emummc_config, 0, sizeof(*exo_emummc_config));
exo_emummc_config->base_cfg.magic = MAGIC_EMUMMC_CONFIG;
exo_emummc_config->base_cfg.type = EMUMMC_TYPE_NONE;
exo_emummc_config->base_cfg.id = 0;
exo_emummc_config->base_cfg.fs_version = FS_VER_1_0_0; /* Will be filled out later. */
char *emummc_ini = calloc(1, 0x10000); char *emummc_ini = calloc(1, 0x10000);
if (!read_from_file(emummc_ini, 0xFFFF, "emummc/emummc.ini")) { if (!read_from_file(emummc_ini, 0xFFFF, "emummc/emummc.ini")) {
@@ -238,16 +245,13 @@ static bool nxboot_configure_emummc(exo_emummc_config_t *exo_emummc_config) {
free(emummc_ini); free(emummc_ini);
memset(exo_emummc_config, 0, sizeof(*exo_emummc_config)); /* Initialize values from emummc config. */
exo_emummc_config->base_cfg.magic = MAGIC_EMUMMC_CONFIG;
exo_emummc_config->base_cfg.type = EMUMMC_TYPE_NONE;
exo_emummc_config->base_cfg.id = emummc_cfg.id; exo_emummc_config->base_cfg.id = emummc_cfg.id;
exo_emummc_config->base_cfg.fs_version = FS_VER_1_0_0; /* Will be filled out later. */
strncpy(exo_emummc_config->emu_dir_path, emummc_cfg.nintendo_path, sizeof(exo_emummc_config->emu_dir_path)); strncpy(exo_emummc_config->emu_dir_path, emummc_cfg.nintendo_path, sizeof(exo_emummc_config->emu_dir_path));
exo_emummc_config->emu_dir_path[sizeof(exo_emummc_config->emu_dir_path) - 1] = '\0'; exo_emummc_config->emu_dir_path[sizeof(exo_emummc_config->emu_dir_path) - 1] = '\0';
if (emummc_cfg.enabled) { if (emummc_cfg.enabled) {
if (emummc_cfg.sector != -1) { if (emummc_cfg.sector > 0) {
exo_emummc_config->base_cfg.type = EMUMMC_TYPE_PARTITION; exo_emummc_config->base_cfg.type = EMUMMC_TYPE_PARTITION;
exo_emummc_config->partition_cfg.start_sector = emummc_cfg.sector; exo_emummc_config->partition_cfg.start_sector = emummc_cfg.sector;

View File

@@ -19,11 +19,11 @@
#include "utils.h" #include "utils.h"
#define EMUMMC_ENABLED_KEY "emummc_enabled" #define EMUMMC_ENABLED_KEY "enabled"
#define EMUMMC_SECTOR_KEY "emummc_sector" #define EMUMMC_SECTOR_KEY "sector"
#define EMUMMC_PATH_KEY "emummc_path" #define EMUMMC_PATH_KEY "path"
#define EMUMMC_NINTENDO_PATH_KEY "emummc_nintendo_path" #define EMUMMC_NINTENDO_PATH_KEY "nintendo_path"
#define EMUMMC_ID_KEY "emummc_id" #define EMUMMC_ID_KEY "id"
typedef struct { typedef struct {
bool enabled; bool enabled;

View File

@@ -352,7 +352,7 @@ static int nxfs_mount_partition_gpt_callback(const efi_entry_t *entry, void *par
return 0; return 0;
} }
static int nxfs_mount_emu_partition_gpt_callback(const efi_entry_t *entry, void *param, size_t entry_offset, FILE *disk, const char *origin_path, bool is_multipart, int num_parts, uint64_t part_limit) { static int nxfs_mount_emu_partition_gpt_callback(const efi_entry_t *entry, void *param, size_t entry_offset, FILE *disk, const char *origin_path, int num_parts, uint64_t part_limit) {
(void)entry_offset; (void)entry_offset;
(void)disk; (void)disk;
device_partition_t *parent = (device_partition_t *)param; device_partition_t *parent = (device_partition_t *)param;
@@ -416,16 +416,9 @@ static int nxfs_mount_emu_partition_gpt_callback(const efi_entry_t *entry, void
} }
} }
} else { } else {
if (is_multipart) { rc = emudev_mount_device(known_partitions[i].mount_point, &devpart, origin_path, num_parts, part_limit);
rc = emudev_mount_device_multipart(known_partitions[i].mount_point, &devpart, origin_path, num_parts, part_limit); if (rc == -1) {
if (rc == -1) { return -1;
return -1;
}
} else {
rc = emudev_mount_device(known_partitions[i].mount_point, &devpart, origin_path);
if (rc == -1) {
return -1;
}
} }
if (known_partitions[i].register_immediately) { if (known_partitions[i].register_immediately) {
rc = emudev_register_device(known_partitions[i].mount_point); rc = emudev_register_device(known_partitions[i].mount_point);
@@ -564,7 +557,7 @@ int nxfs_mount_emummc_partition(uint64_t emummc_start_sector) {
model.emu_use_file = false; model.emu_use_file = false;
/* Mount emulated boot0 device. */ /* Mount emulated boot0 device. */
rc = emudev_mount_device("boot0", &model, NULL); rc = emudev_mount_device("boot0", &model, NULL, 0, 0);
/* Failed to mount boot0 device. */ /* Failed to mount boot0 device. */
if (rc == -1) { if (rc == -1) {
@@ -586,7 +579,7 @@ int nxfs_mount_emummc_partition(uint64_t emummc_start_sector) {
model.emu_use_file = false; model.emu_use_file = false;
/* Mount emulated boot1 device. */ /* Mount emulated boot1 device. */
rc = emudev_mount_device("boot1", &model, NULL); rc = emudev_mount_device("boot1", &model, NULL, 0, 0);
/* Failed to mount boot1. */ /* Failed to mount boot1. */
if (rc == -1) { if (rc == -1) {
@@ -602,7 +595,7 @@ int nxfs_mount_emummc_partition(uint64_t emummc_start_sector) {
model.emu_use_file = false; model.emu_use_file = false;
/* Mount emulated raw NAND device. */ /* Mount emulated raw NAND device. */
rc = emudev_mount_device("rawnand", &model, NULL); rc = emudev_mount_device("rawnand", &model, NULL, 0, 0);
/* Failed to mount raw NAND. */ /* Failed to mount raw NAND. */
if (rc == -1) { if (rc == -1) {
@@ -626,7 +619,7 @@ int nxfs_mount_emummc_partition(uint64_t emummc_start_sector) {
} }
/* Iterate the GPT and mount each emulated raw NAND partition. */ /* Iterate the GPT and mount each emulated raw NAND partition. */
rc = gpt_iterate_through_emu_entries(rawnand, model.sector_size, nxfs_mount_emu_partition_gpt_callback, &model, NULL, false, 0, 0); rc = gpt_iterate_through_emu_entries(rawnand, model.sector_size, nxfs_mount_emu_partition_gpt_callback, &model, NULL, 0, 0);
/* Close emulated raw NAND device. */ /* Close emulated raw NAND device. */
fclose(rawnand); fclose(rawnand);
@@ -647,7 +640,6 @@ int nxfs_mount_emummc_file(const char *emummc_path, int num_parts, uint64_t part
bool is_exfat; bool is_exfat;
char emummc_boot0_path[0x300 + 1] = {0}; char emummc_boot0_path[0x300 + 1] = {0};
char emummc_boot1_path[0x300 + 1] = {0}; char emummc_boot1_path[0x300 + 1] = {0};
char emummc_rawnand_path[0x300 + 1] = {0};
/* Check if the SD card is EXFAT formatted. */ /* Check if the SD card is EXFAT formatted. */
rc = fsdev_is_exfat("sdmc"); rc = fsdev_is_exfat("sdmc");
@@ -660,17 +652,22 @@ int nxfs_mount_emummc_file(const char *emummc_path, int num_parts, uint64_t part
/* Set EXFAT status. */ /* Set EXFAT status. */
is_exfat = (rc == 1); is_exfat = (rc == 1);
/* Reject single part in FAT32. */
if (!is_exfat && (num_parts <= 1)) {
return -2;
}
/* We want a folder with the archive bit set. */ /* We want a folder with the archive bit set. */
rc = fsdev_get_attr(emummc_path); rc = fsdev_get_attr(emummc_path);
/* Failed to get file DOS attributes. */ /* Failed to get file DOS attributes. */
if (rc == -1) { if (rc == -1) {
return -1; return -3;
} }
/* Our path is not a directory. */ /* Our path is not a directory. */
if (!(rc & AM_DIR)) { if (!(rc & AM_DIR)) {
return -1; return -4;
} }
/* Check if the archive bit is not set. */ /* Check if the archive bit is not set. */
@@ -680,7 +677,7 @@ int nxfs_mount_emummc_file(const char *emummc_path, int num_parts, uint64_t part
/* Failed to set file DOS attributes. */ /* Failed to set file DOS attributes. */
if (rc == -1) { if (rc == -1) {
return -1; return -5;
} }
} }
@@ -694,11 +691,11 @@ int nxfs_mount_emummc_file(const char *emummc_path, int num_parts, uint64_t part
snprintf(emummc_boot0_path, sizeof(emummc_boot0_path) - 1, "%s/%s", emummc_path, "boot0"); snprintf(emummc_boot0_path, sizeof(emummc_boot0_path) - 1, "%s/%s", emummc_path, "boot0");
/* Mount emulated boot0 device. */ /* Mount emulated boot0 device. */
rc = emudev_mount_device("boot0", &model, emummc_boot0_path); rc = emudev_mount_device("boot0", &model, emummc_boot0_path, 0, 0);
/* Failed to mount boot0 device. */ /* Failed to mount boot0 device. */
if (rc == -1) { if (rc == -1) {
return -1; return -6;
} }
/* Register emulated boot0 device. */ /* Register emulated boot0 device. */
@@ -706,7 +703,7 @@ int nxfs_mount_emummc_file(const char *emummc_path, int num_parts, uint64_t part
/* Failed to register boot0 device. */ /* Failed to register boot0 device. */
if (rc == -1) { if (rc == -1) {
return -1; return -7;
} }
/* Setup an emulation template for boot1. */ /* Setup an emulation template for boot1. */
@@ -719,11 +716,11 @@ int nxfs_mount_emummc_file(const char *emummc_path, int num_parts, uint64_t part
snprintf(emummc_boot1_path, sizeof(emummc_boot1_path) - 1, "%s/%s", emummc_path, "boot1"); snprintf(emummc_boot1_path, sizeof(emummc_boot1_path) - 1, "%s/%s", emummc_path, "boot1");
/* Mount emulated boot1 device. */ /* Mount emulated boot1 device. */
rc = emudev_mount_device("boot1", &model, emummc_boot1_path); rc = emudev_mount_device("boot1", &model, emummc_boot1_path, 0, 0);
/* Failed to mount boot1. */ /* Failed to mount boot1. */
if (rc == -1) { if (rc == -1) {
return -1; return -8;
} }
/* Register emulated boot1 device. */ /* Register emulated boot1 device. */
@@ -731,7 +728,7 @@ int nxfs_mount_emummc_file(const char *emummc_path, int num_parts, uint64_t part
/* Failed to register boot1 device. */ /* Failed to register boot1 device. */
if (rc == -1) { if (rc == -1) {
return -1; return -9;
} }
/* Setup a template for raw NAND. */ /* Setup a template for raw NAND. */
@@ -740,19 +737,12 @@ int nxfs_mount_emummc_file(const char *emummc_path, int num_parts, uint64_t part
model.num_sectors = (256ull << 30) / model.sector_size; model.num_sectors = (256ull << 30) / model.sector_size;
model.emu_use_file = true; model.emu_use_file = true;
/* Prepare single raw NAND file path. */
snprintf(emummc_rawnand_path, sizeof(emummc_rawnand_path) - 1, "%s/%02d", emummc_path, 0);
/* Mount emulated raw NAND device from single or multiple parts. */ /* Mount emulated raw NAND device from single or multiple parts. */
if (!is_exfat) { rc = emudev_mount_device("rawnand", &model, emummc_path, num_parts, part_limit);
rc = emudev_mount_device_multipart("rawnand", &model, emummc_path, num_parts, part_limit);
} else {
rc = emudev_mount_device("rawnand", &model, emummc_rawnand_path);
}
/* Failed to mount raw NAND. */ /* Failed to mount raw NAND. */
if (rc == -1) { if (rc == -1) {
return -1; return -10;
} }
/* Register emulated raw NAND device. */ /* Register emulated raw NAND device. */
@@ -760,7 +750,7 @@ int nxfs_mount_emummc_file(const char *emummc_path, int num_parts, uint64_t part
/* Failed to register raw NAND device. */ /* Failed to register raw NAND device. */
if (rc == -1) { if (rc == -1) {
return -1; return -11;
} }
/* Open emulated raw NAND device. */ /* Open emulated raw NAND device. */
@@ -768,15 +758,11 @@ int nxfs_mount_emummc_file(const char *emummc_path, int num_parts, uint64_t part
/* Failed to open emulated raw NAND device. */ /* Failed to open emulated raw NAND device. */
if (rawnand == NULL) { if (rawnand == NULL) {
return -1; return -12;
} }
/* Iterate the GPT and mount each emulated raw NAND partition. */ /* Iterate the GPT and mount each emulated raw NAND partition. */
if (!is_exfat) { rc = gpt_iterate_through_emu_entries(rawnand, model.sector_size, nxfs_mount_emu_partition_gpt_callback, &model, emummc_path, num_parts, part_limit);
rc = gpt_iterate_through_emu_entries(rawnand, model.sector_size, nxfs_mount_emu_partition_gpt_callback, &model, emummc_path, true, num_parts, part_limit);
} else {
rc = gpt_iterate_through_emu_entries(rawnand, model.sector_size, nxfs_mount_emu_partition_gpt_callback, &model, emummc_rawnand_path, false, 0, 0);
}
/* Close emulated raw NAND device. */ /* Close emulated raw NAND device. */
fclose(rawnand); fclose(rawnand);

View File

@@ -173,7 +173,7 @@ _content_headers:
.word __sept_secondary_00_enc_size__ .word __sept_secondary_00_enc_size__
.word CONTENT_TYPE_SP2 .word CONTENT_TYPE_SP2
.word 0xCCCCCCCC .word 0xCCCCCCCC
.asciz "sept_secondary_00" .asciz "septsecondary00"
.align 5 .align 5
/* sept_secondary 01 content header */ /* sept_secondary 01 content header */
@@ -181,7 +181,7 @@ _content_headers:
.word __sept_secondary_01_enc_size__ .word __sept_secondary_01_enc_size__
.word CONTENT_TYPE_SP2 .word CONTENT_TYPE_SP2
.word 0xCCCCCCCC .word 0xCCCCCCCC
.asciz "sept_secondary_01" .asciz "septsecondary01"
.align 5 .align 5
/* sm content header */ /* sm content header */

View File

@@ -31,7 +31,7 @@ DATA := data
INCLUDES := include ../../common/include INCLUDES := include ../../common/include
EXEFS_SRC := exefs_src EXEFS_SRC := exefs_src
DEFINES := -DDISABLE_IPC -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\" DEFINES := -DRESULT_ABORT_ON_ASSERT -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\"
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# options for code generation # options for code generation

View File

@@ -69,25 +69,12 @@ void __libnx_initheap(void) {
} }
void __appInit(void) { void __appInit(void) {
Result rc;
SetFirmwareVersionForLibnx(); SetFirmwareVersionForLibnx();
DoWithSmSession([&]() { DoWithSmSession([&]() {
rc = fsInitialize(); R_ASSERT(fsInitialize());
if (R_FAILED(rc)) { R_ASSERT(pmdmntInitialize());
std::abort(); R_ASSERT(pminfoInitialize());
}
rc = pmdmntInitialize();
if (R_FAILED(rc)) {
std::abort();
}
rc = pminfoInitialize();
if (R_FAILED(rc)) {
std::abort();
}
}); });
CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION); CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION);
@@ -105,12 +92,8 @@ int main(int argc, char **argv)
LaunchAllMitmModules(); LaunchAllMitmModules();
if (R_FAILED(initializer_thread.Initialize(&Utils::InitializeThreadFunc, NULL, 0x4000, 0x15))) { R_ASSERT(initializer_thread.Initialize(&Utils::InitializeThreadFunc, NULL, 0x4000, 0x15));
std::abort(); R_ASSERT(initializer_thread.Start());
}
if (R_FAILED(initializer_thread.Start())) {
std::abort();
}
/* Wait for all mitm modules to end. */ /* Wait for all mitm modules to end. */
WaitAllMitmModules(); WaitAllMitmModules();

View File

@@ -43,16 +43,12 @@ void LaunchAllMitmModules() {
/* Create thread for each module. */ /* Create thread for each module. */
for (u32 i = 0; i < static_cast<u32>(MitmModuleId_Count); i++) { for (u32 i = 0; i < static_cast<u32>(MitmModuleId_Count); i++) {
const auto cur_module = &g_module_definitions[i]; const auto cur_module = &g_module_definitions[i];
if (R_FAILED(g_module_threads[i].Initialize(cur_module->main, nullptr, cur_module->stack_size, cur_module->priority))) { R_ASSERT(g_module_threads[i].Initialize(cur_module->main, nullptr, cur_module->stack_size, cur_module->priority));
std::abort();
}
} }
/* Start thread for each module. */ /* Start thread for each module. */
for (u32 i = 0; i < static_cast<u32>(MitmModuleId_Count); i++) { for (u32 i = 0; i < static_cast<u32>(MitmModuleId_Count); i++) {
if (R_FAILED(g_module_threads[i].Start())) { R_ASSERT(g_module_threads[i].Start());
std::abort();
}
} }
} }

View File

@@ -20,15 +20,14 @@
#include "../utils.hpp" #include "../utils.hpp"
enum BpcAtmosphereCmd : u32 {
BpcAtmosphereCmd_RebootToFatalError = 65000,
};
class BpcAtmosphereService : public IServiceObject { class BpcAtmosphereService : public IServiceObject {
enum class CommandId {
RebootToFatalError = 65000,
};
private: private:
Result RebootToFatalError(InBuffer<AtmosphereFatalErrorContext> ctx); Result RebootToFatalError(InBuffer<AtmosphereFatalErrorContext> ctx);
public: public:
DEFINE_SERVICE_DISPATCH_TABLE { DEFINE_SERVICE_DISPATCH_TABLE {
MakeServiceCommandMeta<BpcAtmosphereCmd_RebootToFatalError, &BpcAtmosphereService::RebootToFatalError>(), MAKE_SERVICE_COMMAND_META(BpcAtmosphereService, RebootToFatalError),
}; };
}; };

View File

@@ -20,12 +20,12 @@
#include "../utils.hpp" #include "../utils.hpp"
enum BpcCmd : u32 {
BpcCmd_ShutdownSystem = 0,
BpcCmd_RebootSystem = 1,
};
class BpcMitmService : public IMitmServiceObject { class BpcMitmService : public IMitmServiceObject {
private:
enum class CommandId {
ShutdownSystem = 0,
RebootSystem = 1,
};
public: public:
BpcMitmService(std::shared_ptr<Service> s, u64 pid) : IMitmServiceObject(s, pid) { BpcMitmService(std::shared_ptr<Service> s, u64 pid) : IMitmServiceObject(s, pid) {
/* ... */ /* ... */
@@ -48,7 +48,7 @@ class BpcMitmService : public IMitmServiceObject {
Result RebootSystem(); Result RebootSystem();
public: public:
DEFINE_SERVICE_DISPATCH_TABLE { DEFINE_SERVICE_DISPATCH_TABLE {
MakeServiceCommandMeta<BpcCmd_ShutdownSystem, &BpcMitmService::ShutdownSystem>(), MAKE_SERVICE_COMMAND_META(BpcMitmService, ShutdownSystem),
MakeServiceCommandMeta<BpcCmd_RebootSystem, &BpcMitmService::RebootSystem>(), MAKE_SERVICE_COMMAND_META(BpcMitmService, RebootSystem),
}; };
}; };

View File

@@ -38,23 +38,20 @@ void BpcMitmMain(void *arg) {
BpcRebootManager::Initialize(); BpcRebootManager::Initialize();
/* Create server manager */ /* Create server manager */
auto server_manager = new WaitableManager(2); static auto s_server_manager = WaitableManager(2);
/* Create bpc mitm. */ /* Create bpc mitm. */
const char *service_name = "bpc"; const char *service_name = "bpc";
if (GetRuntimeFirmwareVersion() < FirmwareVersion_200) { if (GetRuntimeFirmwareVersion() < FirmwareVersion_200) {
service_name = "bpc:c"; service_name = "bpc:c";
} }
AddMitmServerToManager<BpcMitmService>(server_manager, service_name, 13); AddMitmServerToManager<BpcMitmService>(&s_server_manager, service_name, 13);
/* Extension: Allow for reboot-to-error. */ /* Extension: Allow for reboot-to-error. */
/* Must be managed port in order for sm to be able to access. */ /* Must be managed port in order for sm to be able to access. */
server_manager->AddWaitable(new ManagedPortServer<BpcAtmosphereService>("bpc:ams", 1)); s_server_manager.AddWaitable(new ManagedPortServer<BpcAtmosphereService>("bpc:ams", 1));
/* Loop forever, servicing our services. */ /* Loop forever, servicing our services. */
server_manager->Process(); s_server_manager.Process();
delete server_manager;
} }

View File

@@ -21,15 +21,12 @@
#include "fs_ifile.hpp" #include "fs_ifile.hpp"
Result FsDirUtils::CopyFile(IFileSystem *dst_fs, IFileSystem *src_fs, const FsPath &dst_parent_path, const FsPath &src_path, const FsDirectoryEntry *dir_ent, void *work_buf, size_t work_buf_size) { Result FsDirUtils::CopyFile(IFileSystem *dst_fs, IFileSystem *src_fs, const FsPath &dst_parent_path, const FsPath &src_path, const FsDirectoryEntry *dir_ent, void *work_buf, size_t work_buf_size) {
Result rc;
std::unique_ptr<IFile> src_file; std::unique_ptr<IFile> src_file;
std::unique_ptr<IFile> dst_file; std::unique_ptr<IFile> dst_file;
const u64 file_size = dir_ent->fileSize; const u64 file_size = dir_ent->fileSize;
/* Open source file for reading. */ /* Open source file for reading. */
if (R_FAILED((rc = src_fs->OpenFile(src_file, src_path, OpenMode_Read)))) { R_TRY(src_fs->OpenFile(src_file, src_path, OpenMode_Read));
return rc;
}
/* Create and open destination file. */ /* Create and open destination file. */
{ {
@@ -39,24 +36,16 @@ Result FsDirUtils::CopyFile(IFileSystem *dst_fs, IFileSystem *src_fs, const FsPa
std::abort(); std::abort();
} }
if (R_FAILED((rc = dst_fs->CreateFile(dst_path, file_size)))) { R_TRY(dst_fs->CreateFile(dst_path, file_size));
return rc; R_TRY(dst_fs->OpenFile(dst_file, dst_path, OpenMode_Write));
}
if (R_FAILED((rc = dst_fs->OpenFile(dst_file, dst_path, OpenMode_Write)))) {
return rc;
}
} }
/* Read/Write work_buf_size chunks. */ /* Read/Write work_buf_size chunks. */
u64 offset = 0; u64 offset = 0;
while (offset < file_size) { while (offset < file_size) {
u64 read_size; u64 read_size;
if (R_FAILED((rc = src_file->Read(&read_size, offset, work_buf, work_buf_size)))) { R_TRY(src_file->Read(&read_size, offset, work_buf, work_buf_size));
return rc; R_TRY(dst_file->Write(offset, work_buf, read_size));
}
if (R_FAILED((rc = dst_file->Write(offset, work_buf, read_size)))) {
return rc;
}
offset += read_size; offset += read_size;
} }
@@ -99,12 +88,9 @@ Result FsDirUtils::CopyDirectoryRecursively(IFileSystem *dst_fs, IFileSystem *sr
Result FsDirUtils::EnsureDirectoryExists(IFileSystem *fs, const FsPath &path) { Result FsDirUtils::EnsureDirectoryExists(IFileSystem *fs, const FsPath &path) {
FsPath normal_path; FsPath normal_path;
size_t normal_path_len; size_t normal_path_len;
Result rc;
/* Normalize the path. */ /* Normalize the path. */
if (R_FAILED((rc = FsPathUtils::Normalize(normal_path.str, sizeof(normal_path.str) - 1, path.str, &normal_path_len)))) { R_TRY(FsPathUtils::Normalize(normal_path.str, sizeof(normal_path.str) - 1, path.str, &normal_path_len));
return rc;
}
/* Repeatedly call CreateDirectory on each directory leading to the target. */ /* Repeatedly call CreateDirectory on each directory leading to the target. */
for (size_t i = 1; i < normal_path_len; i++) { for (size_t i = 1; i < normal_path_len; i++) {
@@ -112,22 +98,22 @@ Result FsDirUtils::EnsureDirectoryExists(IFileSystem *fs, const FsPath &path) {
if (normal_path.str[i] == '/') { if (normal_path.str[i] == '/') {
normal_path.str[i] = 0; normal_path.str[i] = 0;
{ {
rc = fs->CreateDirectory(normal_path); R_TRY_CATCH(fs->CreateDirectory(normal_path)) {
if (rc == ResultFsPathAlreadyExists) { R_CATCH(ResultFsPathAlreadyExists) {
rc = ResultSuccess; /* If path already exists, there's no problem. */
} }
if (R_FAILED(rc)) { } R_END_TRY_CATCH;
return rc;
}
} }
normal_path.str[i] = '/'; normal_path.str[i] = '/';
} }
} }
/* Call CreateDirectory on the final path. */ /* Call CreateDirectory on the final path. */
rc = fs->CreateDirectory(normal_path); R_TRY_CATCH(fs->CreateDirectory(normal_path)) {
if (rc == ResultFsPathAlreadyExists) { R_CATCH(ResultFsPathAlreadyExists) {
rc = ResultSuccess; /* If path already exists, there's no problem. */
} }
return rc; } R_END_TRY_CATCH;
return ResultSuccess;
} }

View File

@@ -24,13 +24,10 @@ class FsDirUtils {
private: private:
template<typename OnEnterDir, typename OnExitDir, typename OnFile> template<typename OnEnterDir, typename OnExitDir, typename OnFile>
static Result IterateDirectoryRecursivelyInternal(IFileSystem *fs, FsPath &work_path, FsDirectoryEntry *ent_buf, OnEnterDir on_enter_dir, OnExitDir on_exit_dir, OnFile on_file) { static Result IterateDirectoryRecursivelyInternal(IFileSystem *fs, FsPath &work_path, FsDirectoryEntry *ent_buf, OnEnterDir on_enter_dir, OnExitDir on_exit_dir, OnFile on_file) {
Result rc;
std::unique_ptr<IDirectory> dir; std::unique_ptr<IDirectory> dir;
/* Open the directory. */ /* Open the directory. */
if (R_FAILED((rc = fs->OpenDirectory(dir, work_path, DirectoryOpenMode_All)))) { R_TRY(fs->OpenDirectory(dir, work_path, DirectoryOpenMode_All));
return rc;
}
const size_t parent_len = strnlen(work_path.str, sizeof(work_path.str) - 1); const size_t parent_len = strnlen(work_path.str, sizeof(work_path.str) - 1);
@@ -38,9 +35,7 @@ class FsDirUtils {
while (true) { while (true) {
/* Read a single entry. */ /* Read a single entry. */
u64 read_count; u64 read_count;
if (R_FAILED((rc = dir->Read(&read_count, ent_buf, 1)))) { R_TRY(dir->Read(&read_count, ent_buf, 1));
return rc;
}
/* If we're out of entries, we're done. */ /* If we're out of entries, we're done. */
if (read_count == 0) { if (read_count == 0) {
@@ -59,25 +54,17 @@ class FsDirUtils {
strncat(work_path.str, ent_buf->name, sizeof(work_path.str) - 1 - parent_len); strncat(work_path.str, ent_buf->name, sizeof(work_path.str) - 1 - parent_len);
if (is_dir) { if (is_dir) {
/* Enter directory. */ /* Enter directory. */
if (R_FAILED((rc = on_enter_dir(work_path, ent_buf)))) { R_TRY(on_enter_dir(work_path, ent_buf));
return rc;
}
/* Append separator, recurse. */ /* Append separator, recurse. */
strncat(work_path.str, "/", sizeof(work_path.str) - 1 - parent_len - child_name_len); strncat(work_path.str, "/", sizeof(work_path.str) - 1 - parent_len - child_name_len);
if (R_FAILED((rc = IterateDirectoryRecursivelyInternal(fs, work_path, ent_buf, on_enter_dir, on_exit_dir, on_file)))) { R_TRY(IterateDirectoryRecursivelyInternal(fs, work_path, ent_buf, on_enter_dir, on_exit_dir, on_file));
return rc;
}
/* Exit directory. */ /* Exit directory. */
if (R_FAILED((rc = on_exit_dir(work_path, ent_buf)))) { R_TRY(on_exit_dir(work_path, ent_buf));
return rc;
}
} else { } else {
/* Call file handler. */ /* Call file handler. */
if (R_FAILED((rc = on_file(work_path, ent_buf)))) { R_TRY(on_file(work_path, ent_buf));
return rc;
}
} }
/* Restore parent path. */ /* Restore parent path. */
@@ -140,19 +127,16 @@ class FsDirUtils {
template<typename F> template<typename F>
static Result RetryUntilTargetNotLocked(F f) { static Result RetryUntilTargetNotLocked(F f) {
const size_t MaxRetries = 10; const size_t MaxRetries = 10;
Result rc = ResultSuccess;
for (size_t i = 0; i < MaxRetries; i++) { for (size_t i = 0; i < MaxRetries; i++) {
rc = f(); R_TRY_CATCH(f()) {
R_CATCH(ResultFsTargetLocked) {
if (rc != ResultFsTargetLocked) { /* If target is locked, wait 100ms and try again. */
break; svcSleepThread(100'000'000ul);
} }
} R_END_TRY_CATCH;
/* If target is locked, wait 100ms and try again. */
svcSleepThread(100'000'000ul);
} }
return rc; return ResultSuccess;
} }
}; };

View File

@@ -26,11 +26,7 @@ static char *GetNormalizedDirectory(const char *dir_prefix) {
/* Normalize the path. */ /* Normalize the path. */
char normal_path[FS_MAX_PATH + 1]; char normal_path[FS_MAX_PATH + 1];
size_t normal_path_len; size_t normal_path_len;
Result rc = FsPathUtils::Normalize(normal_path, sizeof(normal_path), dir_prefix, &normal_path_len); R_ASSERT(FsPathUtils::Normalize(normal_path, sizeof(normal_path), dir_prefix, &normal_path_len));
if (R_FAILED(rc)) {
/* N calls svcBreak here. */
std::abort();
}
/* Ensure terminating '/' */ /* Ensure terminating '/' */
if (normal_path[normal_path_len-1] != '/') { if (normal_path[normal_path_len-1] != '/') {
@@ -69,10 +65,7 @@ Result DirectoryRedirectionFileSystem::Initialize(const char *before, const char
Result DirectoryRedirectionFileSystem::GetFullPath(char *out, size_t out_size, const char *relative_path) { Result DirectoryRedirectionFileSystem::GetFullPath(char *out, size_t out_size, const char *relative_path) {
FsPath tmp_rel_path; FsPath tmp_rel_path;
Result rc = FsPathUtils::Normalize(tmp_rel_path.str, sizeof(tmp_rel_path), relative_path, nullptr); R_TRY(FsPathUtils::Normalize(tmp_rel_path.str, sizeof(tmp_rel_path), relative_path, nullptr));
if (R_FAILED(rc)) {
return rc;
}
if (std::strncmp(tmp_rel_path.str, this->before_dir, this->before_dir_len) == 0) { if (std::strncmp(tmp_rel_path.str, this->before_dir, this->before_dir_len) == 0) {
if (this->after_dir_len + strnlen(tmp_rel_path.str, FS_MAX_PATH) - this->before_dir_len > out_size) { if (this->after_dir_len + strnlen(tmp_rel_path.str, FS_MAX_PATH) - this->before_dir_len > out_size) {
@@ -99,120 +92,64 @@ Result DirectoryRedirectionFileSystem::GetFullPath(char *out, size_t out_size, c
} }
Result DirectoryRedirectionFileSystem::CreateFileImpl(const FsPath &path, uint64_t size, int flags) { Result DirectoryRedirectionFileSystem::CreateFileImpl(const FsPath &path, uint64_t size, int flags) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
return this->base_fs->CreateFile(full_path, size, flags); return this->base_fs->CreateFile(full_path, size, flags);
} }
Result DirectoryRedirectionFileSystem::DeleteFileImpl(const FsPath &path) { Result DirectoryRedirectionFileSystem::DeleteFileImpl(const FsPath &path) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
return this->base_fs->DeleteFile(full_path); return this->base_fs->DeleteFile(full_path);
} }
Result DirectoryRedirectionFileSystem::CreateDirectoryImpl(const FsPath &path) { Result DirectoryRedirectionFileSystem::CreateDirectoryImpl(const FsPath &path) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
return this->base_fs->CreateDirectory(full_path); return this->base_fs->CreateDirectory(full_path);
} }
Result DirectoryRedirectionFileSystem::DeleteDirectoryImpl(const FsPath &path) { Result DirectoryRedirectionFileSystem::DeleteDirectoryImpl(const FsPath &path) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
return this->base_fs->DeleteDirectory(full_path); return this->base_fs->DeleteDirectory(full_path);
} }
Result DirectoryRedirectionFileSystem::DeleteDirectoryRecursivelyImpl(const FsPath &path) { Result DirectoryRedirectionFileSystem::DeleteDirectoryRecursivelyImpl(const FsPath &path) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
return this->base_fs->DeleteDirectoryRecursively(full_path); return this->base_fs->DeleteDirectoryRecursively(full_path);
} }
Result DirectoryRedirectionFileSystem::RenameFileImpl(const FsPath &old_path, const FsPath &new_path) { Result DirectoryRedirectionFileSystem::RenameFileImpl(const FsPath &old_path, const FsPath &new_path) {
Result rc;
FsPath full_old_path, full_new_path; FsPath full_old_path, full_new_path;
R_TRY(GetFullPath(full_old_path, old_path));
if (R_FAILED((rc = GetFullPath(full_old_path, old_path)))) { R_TRY(GetFullPath(full_new_path, new_path));
return rc;
}
if (R_FAILED((rc = GetFullPath(full_new_path, new_path)))) {
return rc;
}
return this->base_fs->RenameFile(full_old_path, full_new_path); return this->base_fs->RenameFile(full_old_path, full_new_path);
} }
Result DirectoryRedirectionFileSystem::RenameDirectoryImpl(const FsPath &old_path, const FsPath &new_path) { Result DirectoryRedirectionFileSystem::RenameDirectoryImpl(const FsPath &old_path, const FsPath &new_path) {
Result rc;
FsPath full_old_path, full_new_path; FsPath full_old_path, full_new_path;
R_TRY(GetFullPath(full_old_path, old_path));
if (R_FAILED((rc = GetFullPath(full_old_path, old_path)))) { R_TRY(GetFullPath(full_new_path, new_path));
return rc;
}
if (R_FAILED((rc = GetFullPath(full_new_path, new_path)))) {
return rc;
}
return this->base_fs->RenameDirectory(full_old_path, full_new_path); return this->base_fs->RenameDirectory(full_old_path, full_new_path);
} }
Result DirectoryRedirectionFileSystem::GetEntryTypeImpl(DirectoryEntryType *out, const FsPath &path) { Result DirectoryRedirectionFileSystem::GetEntryTypeImpl(DirectoryEntryType *out, const FsPath &path) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
return this->base_fs->GetEntryType(out, full_path); return this->base_fs->GetEntryType(out, full_path);
} }
Result DirectoryRedirectionFileSystem::OpenFileImpl(std::unique_ptr<IFile> &out_file, const FsPath &path, OpenMode mode) { Result DirectoryRedirectionFileSystem::OpenFileImpl(std::unique_ptr<IFile> &out_file, const FsPath &path, OpenMode mode) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
return this->base_fs->OpenFile(out_file, full_path, mode); return this->base_fs->OpenFile(out_file, full_path, mode);
} }
Result DirectoryRedirectionFileSystem::OpenDirectoryImpl(std::unique_ptr<IDirectory> &out_dir, const FsPath &path, DirectoryOpenMode mode) { Result DirectoryRedirectionFileSystem::OpenDirectoryImpl(std::unique_ptr<IDirectory> &out_dir, const FsPath &path, DirectoryOpenMode mode) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
return this->base_fs->OpenDirectory(out_dir, full_path, mode); return this->base_fs->OpenDirectory(out_dir, full_path, mode);
} }
@@ -221,56 +158,31 @@ Result DirectoryRedirectionFileSystem::CommitImpl() {
} }
Result DirectoryRedirectionFileSystem::GetFreeSpaceSizeImpl(uint64_t *out, const FsPath &path) { Result DirectoryRedirectionFileSystem::GetFreeSpaceSizeImpl(uint64_t *out, const FsPath &path) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
return this->base_fs->GetFreeSpaceSize(out, full_path); return this->base_fs->GetFreeSpaceSize(out, full_path);
} }
Result DirectoryRedirectionFileSystem::GetTotalSpaceSizeImpl(uint64_t *out, const FsPath &path) { Result DirectoryRedirectionFileSystem::GetTotalSpaceSizeImpl(uint64_t *out, const FsPath &path) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
return this->base_fs->GetTotalSpaceSize(out, full_path); return this->base_fs->GetTotalSpaceSize(out, full_path);
} }
Result DirectoryRedirectionFileSystem::CleanDirectoryRecursivelyImpl(const FsPath &path) { Result DirectoryRedirectionFileSystem::CleanDirectoryRecursivelyImpl(const FsPath &path) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
return this->base_fs->CleanDirectoryRecursively(full_path); return this->base_fs->CleanDirectoryRecursively(full_path);
} }
Result DirectoryRedirectionFileSystem::GetFileTimeStampRawImpl(FsTimeStampRaw *out, const FsPath &path) { Result DirectoryRedirectionFileSystem::GetFileTimeStampRawImpl(FsTimeStampRaw *out, const FsPath &path) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
return this->base_fs->GetFileTimeStampRaw(out, full_path); return this->base_fs->GetFileTimeStampRaw(out, full_path);
} }
Result DirectoryRedirectionFileSystem::QueryEntryImpl(char *out, uint64_t out_size, const char *in, uint64_t in_size, int query, const FsPath &path) { Result DirectoryRedirectionFileSystem::QueryEntryImpl(char *out, uint64_t out_size, const char *in, uint64_t in_size, int query, const FsPath &path) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
return this->base_fs->QueryEntry(out, out_size, in, in_size, query, full_path); return this->base_fs->QueryEntry(out, out_size, in, in_size, query, full_path);
} }

View File

@@ -31,17 +31,11 @@ class DirectoryRedirectionFileSystem : public IFileSystem {
public: public:
DirectoryRedirectionFileSystem(IFileSystem *fs, const char *before, const char *after) : base_fs(fs) { DirectoryRedirectionFileSystem(IFileSystem *fs, const char *before, const char *after) : base_fs(fs) {
Result rc = this->Initialize(before, after); R_ASSERT(this->Initialize(before, after));
if (R_FAILED(rc)) {
fatalSimple(rc);
}
} }
DirectoryRedirectionFileSystem(std::shared_ptr<IFileSystem> fs, const char *before, const char *after) : base_fs(fs) { DirectoryRedirectionFileSystem(std::shared_ptr<IFileSystem> fs, const char *before, const char *after) : base_fs(fs) {
Result rc = this->Initialize(before, after); R_ASSERT(this->Initialize(before, after));
if (R_FAILED(rc)) {
fatalSimple(rc);
}
} }

View File

@@ -62,59 +62,44 @@ class DirectorySaveDataFile : public IFile {
/* ================================================================================================ */ /* ================================================================================================ */
Result DirectorySaveDataFileSystem::Initialize() { Result DirectorySaveDataFileSystem::Initialize() {
Result rc;
DirectoryEntryType ent_type; DirectoryEntryType ent_type;
/* Check that the working directory exists. */ /* Check that the working directory exists. */
if (R_FAILED((rc = this->fs->GetEntryType(&ent_type, WorkingDirectoryPath)))) { R_TRY_CATCH(this->fs->GetEntryType(&ent_type, WorkingDirectoryPath)) {
/* If path isn't found, create working directory and committed directory. */ /* If path isn't found, create working directory and committed directory. */
if (rc == ResultFsPathNotFound) { R_CATCH(ResultFsPathNotFound) {
if (R_FAILED((rc = this->fs->CreateDirectory(WorkingDirectoryPath)))) { R_TRY(this->fs->CreateDirectory(WorkingDirectoryPath));
return rc; R_TRY(this->fs->CreateDirectory(CommittedDirectoryPath));
}
if (R_FAILED((rc = this->fs->CreateDirectory(CommittedDirectoryPath)))) {
return rc;
}
} else {
return rc;
} }
} } R_END_TRY_CATCH;
/* Now check for the committed directory. */ /* Now check for the committed directory. */
rc = this->fs->GetEntryType(&ent_type, CommittedDirectoryPath); R_TRY_CATCH(this->fs->GetEntryType(&ent_type, CommittedDirectoryPath)) {
if (R_SUCCEEDED(rc)) { /* Committed doesn't exist, so synchronize and rename. */
/* If committed exists, synchronize it to the working directory. */ R_CATCH(ResultFsPathNotFound) {
return this->SynchronizeDirectory(WorkingDirectoryPath, CommittedDirectoryPath); R_TRY(this->SynchronizeDirectory(SynchronizingDirectoryPath, WorkingDirectoryPath));
} else if (rc == ResultFsPathNotFound) { return this->fs->RenameDirectory(SynchronizingDirectoryPath, CommittedDirectoryPath);
if (R_FAILED((rc = this->SynchronizeDirectory(SynchronizingDirectoryPath, WorkingDirectoryPath)))) {
return rc;
} }
return this->fs->RenameDirectory(SynchronizingDirectoryPath, CommittedDirectoryPath); } R_END_TRY_CATCH;
} else {
return rc; /* If committed exists, synchronize it to the working directory. */
} return this->SynchronizeDirectory(WorkingDirectoryPath, CommittedDirectoryPath);
} }
Result DirectorySaveDataFileSystem::SynchronizeDirectory(const FsPath &dst_dir, const FsPath &src_dir) { Result DirectorySaveDataFileSystem::SynchronizeDirectory(const FsPath &dst_dir, const FsPath &src_dir) {
Result rc;
/* Delete destination dir and recreate it. */ /* Delete destination dir and recreate it. */
if (R_FAILED((rc = this->fs->DeleteDirectoryRecursively(dst_dir)))) { R_TRY_CATCH(this->fs->DeleteDirectoryRecursively(dst_dir)) {
/* Nintendo returns error unconditionally, but I think that's a bug in their code. */ R_CATCH(ResultFsPathNotFound) {
if (rc != ResultFsPathNotFound) { /* Nintendo returns error unconditionally, but I think that's a bug in their code. */
return rc;
} }
} } R_END_TRY_CATCH;
if (R_FAILED((rc = this->fs->CreateDirectory(dst_dir)))) {
return rc; R_TRY(this->fs->CreateDirectory(dst_dir));
}
/* Get a buffer to work with. */ /* Get a buffer to work with. */
void *work_buf = nullptr; void *work_buf = nullptr;
size_t work_buf_size = 0; size_t work_buf_size = 0;
if (R_FAILED((rc = this->AllocateWorkBuffer(&work_buf, &work_buf_size, IdealWorkBuffersize)))) { R_TRY(this->AllocateWorkBuffer(&work_buf, &work_buf_size, IdealWorkBuffersize));
return rc;
}
ON_SCOPE_EXIT { free(work_buf); }; ON_SCOPE_EXIT { free(work_buf); };
return FsDirUtils::CopyDirectoryRecursively(this->fs, dst_dir, src_dir, work_buf, work_buf_size); return FsDirUtils::CopyDirectoryRecursively(this->fs, dst_dir, src_dir, work_buf, work_buf_size);
@@ -168,20 +153,13 @@ void DirectorySaveDataFileSystem::OnWritableFileClose() {
Result DirectorySaveDataFileSystem::CopySaveFromProxy() { Result DirectorySaveDataFileSystem::CopySaveFromProxy() {
if (this->proxy_save_fs != nullptr) { if (this->proxy_save_fs != nullptr) {
Result rc;
/* Get a buffer to work with. */ /* Get a buffer to work with. */
void *work_buf = nullptr; void *work_buf = nullptr;
size_t work_buf_size = 0; size_t work_buf_size = 0;
if (R_FAILED((rc = this->AllocateWorkBuffer(&work_buf, &work_buf_size, IdealWorkBuffersize)))) { R_TRY(this->AllocateWorkBuffer(&work_buf, &work_buf_size, IdealWorkBuffersize));
return rc;
}
ON_SCOPE_EXIT { free(work_buf); }; ON_SCOPE_EXIT { free(work_buf); };
rc = FsDirUtils::CopyDirectoryRecursively(this, this->proxy_save_fs.get(), FsPathUtils::RootPath, FsPathUtils::RootPath, work_buf, work_buf_size); R_TRY(FsDirUtils::CopyDirectoryRecursively(this, this->proxy_save_fs.get(), FsPathUtils::RootPath, FsPathUtils::RootPath, work_buf, work_buf_size));
if (R_FAILED(rc)) {
return rc;
}
return this->Commit(); return this->Commit();
} }
return ResultSuccess; return ResultSuccess;
@@ -190,125 +168,81 @@ Result DirectorySaveDataFileSystem::CopySaveFromProxy() {
/* ================================================================================================ */ /* ================================================================================================ */
Result DirectorySaveDataFileSystem::CreateFileImpl(const FsPath &path, uint64_t size, int flags) { Result DirectorySaveDataFileSystem::CreateFileImpl(const FsPath &path, uint64_t size, int flags) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
std::scoped_lock<HosMutex> lk(this->lock); std::scoped_lock<HosMutex> lk(this->lock);
return this->fs->CreateFile(full_path, size, flags); return this->fs->CreateFile(full_path, size, flags);
} }
Result DirectorySaveDataFileSystem::DeleteFileImpl(const FsPath &path) { Result DirectorySaveDataFileSystem::DeleteFileImpl(const FsPath &path) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
std::scoped_lock<HosMutex> lk(this->lock); std::scoped_lock<HosMutex> lk(this->lock);
return this->fs->DeleteFile(full_path); return this->fs->DeleteFile(full_path);
} }
Result DirectorySaveDataFileSystem::CreateDirectoryImpl(const FsPath &path) { Result DirectorySaveDataFileSystem::CreateDirectoryImpl(const FsPath &path) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
std::scoped_lock<HosMutex> lk(this->lock); std::scoped_lock<HosMutex> lk(this->lock);
return this->fs->CreateDirectory(full_path); return this->fs->CreateDirectory(full_path);
} }
Result DirectorySaveDataFileSystem::DeleteDirectoryImpl(const FsPath &path) { Result DirectorySaveDataFileSystem::DeleteDirectoryImpl(const FsPath &path) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
std::scoped_lock<HosMutex> lk(this->lock); std::scoped_lock<HosMutex> lk(this->lock);
return this->fs->DeleteDirectory(full_path); return this->fs->DeleteDirectory(full_path);
} }
Result DirectorySaveDataFileSystem::DeleteDirectoryRecursivelyImpl(const FsPath &path) { Result DirectorySaveDataFileSystem::DeleteDirectoryRecursivelyImpl(const FsPath &path) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
std::scoped_lock<HosMutex> lk(this->lock); std::scoped_lock<HosMutex> lk(this->lock);
return this->fs->DeleteDirectoryRecursively(full_path); return this->fs->DeleteDirectoryRecursively(full_path);
} }
Result DirectorySaveDataFileSystem::RenameFileImpl(const FsPath &old_path, const FsPath &new_path) { Result DirectorySaveDataFileSystem::RenameFileImpl(const FsPath &old_path, const FsPath &new_path) {
Result rc;
FsPath full_old_path, full_new_path; FsPath full_old_path, full_new_path;
R_TRY(GetFullPath(full_old_path, old_path));
if (R_FAILED((rc = GetFullPath(full_old_path, old_path)))) { R_TRY(GetFullPath(full_new_path, new_path));
return rc;
}
if (R_FAILED((rc = GetFullPath(full_new_path, new_path)))) {
return rc;
}
std::scoped_lock<HosMutex> lk(this->lock); std::scoped_lock<HosMutex> lk(this->lock);
return this->fs->RenameFile(full_old_path, full_new_path); return this->fs->RenameFile(full_old_path, full_new_path);
} }
Result DirectorySaveDataFileSystem::RenameDirectoryImpl(const FsPath &old_path, const FsPath &new_path) { Result DirectorySaveDataFileSystem::RenameDirectoryImpl(const FsPath &old_path, const FsPath &new_path) {
Result rc;
FsPath full_old_path, full_new_path; FsPath full_old_path, full_new_path;
R_TRY(GetFullPath(full_old_path, old_path));
if (R_FAILED((rc = GetFullPath(full_old_path, old_path)))) { R_TRY(GetFullPath(full_new_path, new_path));
return rc;
}
if (R_FAILED((rc = GetFullPath(full_new_path, new_path)))) {
return rc;
}
std::scoped_lock<HosMutex> lk(this->lock); std::scoped_lock<HosMutex> lk(this->lock);
return this->fs->RenameDirectory(full_old_path, full_new_path); return this->fs->RenameDirectory(full_old_path, full_new_path);
} }
Result DirectorySaveDataFileSystem::GetEntryTypeImpl(DirectoryEntryType *out, const FsPath &path) { Result DirectorySaveDataFileSystem::GetEntryTypeImpl(DirectoryEntryType *out, const FsPath &path) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
std::scoped_lock<HosMutex> lk(this->lock); std::scoped_lock<HosMutex> lk(this->lock);
return this->fs->GetEntryType(out, full_path); return this->fs->GetEntryType(out, full_path);
} }
Result DirectorySaveDataFileSystem::OpenFileImpl(std::unique_ptr<IFile> &out_file, const FsPath &path, OpenMode mode) { Result DirectorySaveDataFileSystem::OpenFileImpl(std::unique_ptr<IFile> &out_file, const FsPath &path, OpenMode mode) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
std::scoped_lock<HosMutex> lk(this->lock); std::scoped_lock<HosMutex> lk(this->lock);
{ {
/* Open the raw file. */ /* Open the raw file. */
std::unique_ptr<IFile> file; std::unique_ptr<IFile> file;
if (R_FAILED((rc = this->fs->OpenFile(file, full_path, mode)))) { R_TRY(this->fs->OpenFile(file, full_path, mode));
return rc;
}
/* Create DirectorySaveDataFile wrapper. */ /* Create DirectorySaveDataFile wrapper. */
out_file = std::make_unique<DirectorySaveDataFile>(std::move(file), this, mode); out_file = std::make_unique<DirectorySaveDataFile>(std::move(file), this, mode);
@@ -328,12 +262,8 @@ Result DirectorySaveDataFileSystem::OpenFileImpl(std::unique_ptr<IFile> &out_fil
} }
Result DirectorySaveDataFileSystem::OpenDirectoryImpl(std::unique_ptr<IDirectory> &out_dir, const FsPath &path, DirectoryOpenMode mode) { Result DirectorySaveDataFileSystem::OpenDirectoryImpl(std::unique_ptr<IDirectory> &out_dir, const FsPath &path, DirectoryOpenMode mode) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
std::scoped_lock<HosMutex> lk(this->lock); std::scoped_lock<HosMutex> lk(this->lock);
return this->fs->OpenDirectory(out_dir, full_path, mode); return this->fs->OpenDirectory(out_dir, full_path, mode);
@@ -349,7 +279,6 @@ Result DirectorySaveDataFileSystem::CommitImpl() {
/* Instead, we will synchronize first, then delete committed, then rename. */ /* Instead, we will synchronize first, then delete committed, then rename. */
std::scoped_lock<HosMutex> lk(this->lock); std::scoped_lock<HosMutex> lk(this->lock);
Result rc;
/* Ensure we don't have any open writable files. */ /* Ensure we don't have any open writable files. */
if (this->open_writable_files != 0) { if (this->open_writable_files != 0) {
@@ -361,25 +290,20 @@ Result DirectorySaveDataFileSystem::CommitImpl() {
const auto RenameSynchDir = [&]() { return this->fs->RenameDirectory(SynchronizingDirectoryPath, CommittedDirectoryPath); }; const auto RenameSynchDir = [&]() { return this->fs->RenameDirectory(SynchronizingDirectoryPath, CommittedDirectoryPath); };
/* Synchronize working directory. */ /* Synchronize working directory. */
if (R_FAILED((rc = FsDirUtils::RetryUntilTargetNotLocked(std::move(SynchronizeWorkingDir))))) { R_TRY(FsDirUtils::RetryUntilTargetNotLocked(std::move(SynchronizeWorkingDir)));
return rc;
}
/* Delete committed directory. */ /* Delete committed directory. */
if (R_FAILED((rc = FsDirUtils::RetryUntilTargetNotLocked(std::move(DeleteCommittedDir))))) { R_TRY_CATCH(FsDirUtils::RetryUntilTargetNotLocked(std::move(DeleteCommittedDir))) {
/* It is okay for us to not have a committed directory here. */ R_CATCH(ResultFsPathNotFound) {
if (rc != ResultFsPathNotFound) { /* It is okay for us to not have a committed directory here. */
return rc;
} }
} } R_END_TRY_CATCH;
/* Rename synchronizing directory to committed directory. */ /* Rename synchronizing directory to committed directory. */
if (R_FAILED((rc = FsDirUtils::RetryUntilTargetNotLocked(std::move(RenameSynchDir))))) { R_TRY(FsDirUtils::RetryUntilTargetNotLocked(std::move(RenameSynchDir)));
return rc;
}
/* TODO: Should I call this->fs->Commit()? Nintendo does not. */ /* TODO: Should I call this->fs->Commit()? Nintendo does not. */
return rc; return ResultSuccess;
} }
Result DirectorySaveDataFileSystem::GetFreeSpaceSizeImpl(uint64_t *out, const FsPath &path) { Result DirectorySaveDataFileSystem::GetFreeSpaceSizeImpl(uint64_t *out, const FsPath &path) {
@@ -393,12 +317,8 @@ Result DirectorySaveDataFileSystem::GetTotalSpaceSizeImpl(uint64_t *out, const F
} }
Result DirectorySaveDataFileSystem::CleanDirectoryRecursivelyImpl(const FsPath &path) { Result DirectorySaveDataFileSystem::CleanDirectoryRecursivelyImpl(const FsPath &path) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
std::scoped_lock<HosMutex> lk(this->lock); std::scoped_lock<HosMutex> lk(this->lock);
return this->fs->CleanDirectoryRecursively(full_path); return this->fs->CleanDirectoryRecursively(full_path);

View File

@@ -43,26 +43,17 @@ class DirectorySaveDataFileSystem : public IFileSystem {
public: public:
DirectorySaveDataFileSystem(IFileSystem *fs, std::unique_ptr<IFileSystem> pfs) : unique_fs(fs), proxy_save_fs(std::move(pfs)) { DirectorySaveDataFileSystem(IFileSystem *fs, std::unique_ptr<IFileSystem> pfs) : unique_fs(fs), proxy_save_fs(std::move(pfs)) {
this->fs = this->unique_fs.get(); this->fs = this->unique_fs.get();
Result rc = this->Initialize(); R_ASSERT(this->Initialize());
if (R_FAILED(rc)) {
fatalSimple(rc);
}
} }
DirectorySaveDataFileSystem(std::unique_ptr<IFileSystem> fs, std::unique_ptr<IFileSystem> pfs) : unique_fs(std::move(fs)), proxy_save_fs(std::move(pfs)) { DirectorySaveDataFileSystem(std::unique_ptr<IFileSystem> fs, std::unique_ptr<IFileSystem> pfs) : unique_fs(std::move(fs)), proxy_save_fs(std::move(pfs)) {
this->fs = this->unique_fs.get(); this->fs = this->unique_fs.get();
Result rc = this->Initialize(); R_ASSERT(this->Initialize());
if (R_FAILED(rc)) {
fatalSimple(rc);
}
} }
DirectorySaveDataFileSystem(std::shared_ptr<IFileSystem> fs, std::unique_ptr<IFileSystem> pfs) : shared_fs(fs), proxy_save_fs(std::move(pfs)) { DirectorySaveDataFileSystem(std::shared_ptr<IFileSystem> fs, std::unique_ptr<IFileSystem> pfs) : shared_fs(fs), proxy_save_fs(std::move(pfs)) {
this->fs = this->shared_fs.get(); this->fs = this->shared_fs.get();
Result rc = this->Initialize(); R_ASSERT(this->Initialize());
if (R_FAILED(rc)) {
fatalSimple(rc);
}
} }
virtual ~DirectorySaveDataFileSystem() { } virtual ~DirectorySaveDataFileSystem() { }

View File

@@ -29,7 +29,6 @@ Result FileStorage::UpdateSize() {
} }
Result FileStorage::Read(void *buffer, size_t size, u64 offset) { Result FileStorage::Read(void *buffer, size_t size, u64 offset) {
Result rc;
u64 read_size; u64 read_size;
if (size == 0) { if (size == 0) {
@@ -38,9 +37,7 @@ Result FileStorage::Read(void *buffer, size_t size, u64 offset) {
if (buffer == nullptr) { if (buffer == nullptr) {
return ResultFsNullptrArgument; return ResultFsNullptrArgument;
} }
if (R_FAILED((rc = this->UpdateSize()))) { R_TRY(this->UpdateSize());
return rc;
}
if (!IStorage::IsRangeValid(offset, size, this->size)) { if (!IStorage::IsRangeValid(offset, size, this->size)) {
return ResultFsOutOfRange; return ResultFsOutOfRange;
} }
@@ -54,17 +51,13 @@ Result FileStorage::Read(void *buffer, size_t size, u64 offset) {
} }
Result FileStorage::Write(void *buffer, size_t size, u64 offset) { Result FileStorage::Write(void *buffer, size_t size, u64 offset) {
Result rc;
if (size == 0) { if (size == 0) {
return ResultSuccess; return ResultSuccess;
} }
if (buffer == nullptr) { if (buffer == nullptr) {
return ResultFsNullptrArgument; return ResultFsNullptrArgument;
} }
if (R_FAILED((rc = this->UpdateSize()))) { R_TRY(this->UpdateSize());
return rc;
}
if (!IStorage::IsRangeValid(offset, size, this->size)) { if (!IStorage::IsRangeValid(offset, size, this->size)) {
return ResultFsOutOfRange; return ResultFsOutOfRange;
} }
@@ -77,10 +70,7 @@ Result FileStorage::Flush() {
} }
Result FileStorage::GetSize(u64 *out_size) { Result FileStorage::GetSize(u64 *out_size) {
Result rc = this->UpdateSize(); R_TRY(this->UpdateSize());
if (R_FAILED(rc)) {
return rc;
}
*out_size = this->size; *out_size = this->size;
return ResultSuccess; return ResultSuccess;
} }
@@ -91,8 +81,6 @@ Result FileStorage::SetSize(u64 size) {
} }
Result FileStorage::OperateRange(FsOperationId operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) { Result FileStorage::OperateRange(FsOperationId operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) {
Result rc;
switch (operation_type) { switch (operation_type) {
case FsOperationId_InvalidateCache: case FsOperationId_InvalidateCache:
case FsOperationId_QueryRange: case FsOperationId_QueryRange:
@@ -106,9 +94,7 @@ Result FileStorage::OperateRange(FsOperationId operation_type, u64 offset, u64 s
} }
return ResultSuccess; return ResultSuccess;
} }
if (R_FAILED((rc = this->UpdateSize()))) { R_TRY(this->UpdateSize());
return rc;
}
/* N checks for positivity + signed overflow on offset/size here, but we're using unsigned types... */ /* N checks for positivity + signed overflow on offset/size here, but we're using unsigned types... */
return this->file->OperateRange(operation_type, offset, size, out_range_info); return this->file->OperateRange(operation_type, offset, size, out_range_info);
default: default:

View File

@@ -18,11 +18,6 @@
#include <switch.h> #include <switch.h>
#include <stratosphere.hpp> #include <stratosphere.hpp>
enum FsIDirectoryCmd : u32 {
FsIDirectoryCmd_Read = 0,
FsIDirectoryCmd_GetEntryCount = 1,
};
class IDirectory { class IDirectory {
public: public:
virtual ~IDirectory() {} virtual ~IDirectory() {}
@@ -56,6 +51,11 @@ class IDirectory {
}; };
class IDirectoryInterface : public IServiceObject { class IDirectoryInterface : public IServiceObject {
private:
enum class CommandId {
Read = 0,
GetEntryCount = 1,
};
private: private:
std::unique_ptr<IDirectory> base_dir; std::unique_ptr<IDirectory> base_dir;
public: public:
@@ -77,8 +77,8 @@ class IDirectoryInterface : public IServiceObject {
public: public:
DEFINE_SERVICE_DISPATCH_TABLE { DEFINE_SERVICE_DISPATCH_TABLE {
/* 1.0.0- */ /* 1.0.0- */
MakeServiceCommandMeta<FsIDirectoryCmd_Read, &IDirectoryInterface::Read>(), MAKE_SERVICE_COMMAND_META(IDirectoryInterface, Read),
MakeServiceCommandMeta<FsIDirectoryCmd_GetEntryCount, &IDirectoryInterface::GetEntryCount>(), MAKE_SERVICE_COMMAND_META(IDirectoryInterface, GetEntryCount),
}; };
}; };
@@ -104,13 +104,10 @@ class ProxyDirectory : public IDirectory {
public: public:
virtual Result ReadImpl(uint64_t *out_count, FsDirectoryEntry *out_entries, uint64_t max_entries) { virtual Result ReadImpl(uint64_t *out_count, FsDirectoryEntry *out_entries, uint64_t max_entries) {
size_t count; size_t count;
R_TRY(fsDirRead(this->base_dir.get(), 0, &count, max_entries, out_entries));
Result rc = fsDirRead(this->base_dir.get(), 0, &count, max_entries, out_entries); *out_count = count;
if (R_SUCCEEDED(rc)) { return ResultSuccess;
*out_count = count;
}
return rc;
} }
virtual Result GetEntryCountImpl(uint64_t *count) { virtual Result GetEntryCountImpl(uint64_t *count) {
return fsDirGetEntryCount(this->base_dir.get(), count); return fsDirGetEntryCount(this->base_dir.get(), count);

View File

@@ -20,15 +20,6 @@
#include "fs_shim.h" #include "fs_shim.h"
enum FsIFileCmd : u32 {
FsIFileCmd_Read = 0,
FsIFileCmd_Write = 1,
FsIFileCmd_Flush = 2,
FsIFileCmd_SetSize = 3,
FsIFileCmd_GetSize = 4,
FsIFileCmd_OperateRange = 5,
};
class IFile { class IFile {
public: public:
virtual ~IFile() {} virtual ~IFile() {}
@@ -106,6 +97,15 @@ class IFile {
}; };
class IFileInterface : public IServiceObject { class IFileInterface : public IServiceObject {
private:
enum class CommandId {
Read = 0,
Write = 1,
Flush = 2,
SetSize = 3,
GetSize = 4,
OperateRange = 5,
};
private: private:
std::unique_ptr<IFile> base_file; std::unique_ptr<IFile> base_file;
public: public:
@@ -139,14 +139,14 @@ class IFileInterface : public IServiceObject {
public: public:
DEFINE_SERVICE_DISPATCH_TABLE { DEFINE_SERVICE_DISPATCH_TABLE {
/* 1.0.0- */ /* 1.0.0- */
MakeServiceCommandMeta<FsIFileCmd_Read, &IFileInterface::Read>(), MAKE_SERVICE_COMMAND_META(IFileInterface, Read),
MakeServiceCommandMeta<FsIFileCmd_Write, &IFileInterface::Write>(), MAKE_SERVICE_COMMAND_META(IFileInterface, Write),
MakeServiceCommandMeta<FsIFileCmd_Flush, &IFileInterface::Flush>(), MAKE_SERVICE_COMMAND_META(IFileInterface, Flush),
MakeServiceCommandMeta<FsIFileCmd_SetSize, &IFileInterface::SetSize>(), MAKE_SERVICE_COMMAND_META(IFileInterface, SetSize),
MakeServiceCommandMeta<FsIFileCmd_GetSize, &IFileInterface::GetSize>(), MAKE_SERVICE_COMMAND_META(IFileInterface, GetSize),
/* 4.0.0- */ /* 4.0.0- */
MakeServiceCommandMeta<FsIFileCmd_OperateRange, &IFileInterface::OperateRange, FirmwareVersion_400>(), MAKE_SERVICE_COMMAND_META(IFileInterface, OperateRange, FirmwareVersion_400),
}; };
}; };
@@ -172,13 +172,10 @@ class ProxyFile : public IFile {
public: public:
virtual Result ReadImpl(u64 *out, u64 offset, void *buffer, u64 size) override { virtual Result ReadImpl(u64 *out, u64 offset, void *buffer, u64 size) override {
size_t out_sz; size_t out_sz;
R_TRY(fsFileRead(this->base_file.get(), offset, buffer, size, FS_READOPTION_NONE, &out_sz));
Result rc = fsFileRead(this->base_file.get(), offset, buffer, size, FS_READOPTION_NONE, &out_sz); *out = out_sz;
if (R_SUCCEEDED(rc)) { return ResultSuccess;
*out = out_sz;
}
return rc;
} }
virtual Result GetSizeImpl(u64 *out) override { virtual Result GetSizeImpl(u64 *out) override {
return fsFileGetSize(this->base_file.get(), out); return fsFileGetSize(this->base_file.get(), out);

View File

@@ -26,30 +26,6 @@
#include "fs_ifile.hpp" #include "fs_ifile.hpp"
#include "fs_idirectory.hpp" #include "fs_idirectory.hpp"
enum FsIFileSystemCmd : u32 {
/* 1.0.0+ */
FsIFileSystemCmd_CreateFile = 0,
FsIFileSystemCmd_DeleteFile = 1,
FsIFileSystemCmd_CreateDirectory = 2,
FsIFileSystemCmd_DeleteDirectory = 3,
FsIFileSystemCmd_DeleteDirectoryRecursively = 4,
FsIFileSystemCmd_RenameFile = 5,
FsIFileSystemCmd_RenameDirectory = 6,
FsIFileSystemCmd_GetEntryType = 7,
FsIFileSystemCmd_OpenFile = 8,
FsIFileSystemCmd_OpenDirectory = 9,
FsIFileSystemCmd_Commit = 10,
FsIFileSystemCmd_GetFreeSpaceSize = 11,
FsIFileSystemCmd_GetTotalSpaceSize = 12,
/* 3.0.0+ */
FsIFileSystemCmd_CleanDirectoryRecursively = 13,
FsIFileSystemCmd_GetFileTimeStampRaw = 14,
/* 4.0.0+ */
FsIFileSystemCmd_QueryEntry = 15,
};
class IFile; class IFile;
class IDirectory; class IDirectory;
@@ -197,6 +173,30 @@ class IFileSystem {
}; };
class IFileSystemInterface : public IServiceObject { class IFileSystemInterface : public IServiceObject {
private:
enum class CommandId {
/* 1.0.0+ */
CreateFile = 0,
DeleteFile = 1,
CreateDirectory = 2,
DeleteDirectory = 3,
DeleteDirectoryRecursively = 4,
RenameFile = 5,
RenameDirectory = 6,
GetEntryType = 7,
OpenFile = 8,
OpenDirectory = 9,
Commit = 10,
GetFreeSpaceSize = 11,
GetTotalSpaceSize = 12,
/* 3.0.0+ */
CleanDirectoryRecursively = 13,
GetFileTimeStampRaw = 14,
/* 4.0.0+ */
QueryEntry = 15,
};
private: private:
std::unique_ptr<IFileSystem> unique_fs; std::unique_ptr<IFileSystem> unique_fs;
std::shared_ptr<IFileSystem> shared_fs; std::shared_ptr<IFileSystem> shared_fs;
@@ -216,55 +216,35 @@ class IFileSystemInterface : public IServiceObject {
/* Actual command API. */ /* Actual command API. */
virtual Result CreateFile(InPointer<char> in_path, uint64_t size, int flags) final { virtual Result CreateFile(InPointer<char> in_path, uint64_t size, int flags) final {
FsPath path; FsPath path;
R_TRY(FsPathUtils::ConvertPathForServiceObject(&path, in_path.pointer));
Result rc;
if (R_FAILED((rc = FsPathUtils::ConvertPathForServiceObject(&path, in_path.pointer)))) {
return rc;
}
return this->base_fs->CreateFile(path, size, flags); return this->base_fs->CreateFile(path, size, flags);
} }
virtual Result DeleteFile(InPointer<char> in_path) final { virtual Result DeleteFile(InPointer<char> in_path) final {
FsPath path; FsPath path;
R_TRY(FsPathUtils::ConvertPathForServiceObject(&path, in_path.pointer));
Result rc;
if (R_FAILED((rc = FsPathUtils::ConvertPathForServiceObject(&path, in_path.pointer)))) {
return rc;
}
return this->base_fs->DeleteFile(path); return this->base_fs->DeleteFile(path);
} }
virtual Result CreateDirectory(InPointer<char> in_path) final { virtual Result CreateDirectory(InPointer<char> in_path) final {
FsPath path; FsPath path;
R_TRY(FsPathUtils::ConvertPathForServiceObject(&path, in_path.pointer));
Result rc;
if (R_FAILED((rc = FsPathUtils::ConvertPathForServiceObject(&path, in_path.pointer)))) {
return rc;
}
return this->base_fs->CreateDirectory(path); return this->base_fs->CreateDirectory(path);
} }
virtual Result DeleteDirectory(InPointer<char> in_path) final { virtual Result DeleteDirectory(InPointer<char> in_path) final {
FsPath path; FsPath path;
R_TRY(FsPathUtils::ConvertPathForServiceObject(&path, in_path.pointer));
Result rc;
if (R_FAILED((rc = FsPathUtils::ConvertPathForServiceObject(&path, in_path.pointer)))) {
return rc;
}
return this->base_fs->DeleteDirectory(path); return this->base_fs->DeleteDirectory(path);
} }
virtual Result DeleteDirectoryRecursively(InPointer<char> in_path) final { virtual Result DeleteDirectoryRecursively(InPointer<char> in_path) final {
FsPath path; FsPath path;
R_TRY(FsPathUtils::ConvertPathForServiceObject(&path, in_path.pointer));
Result rc;
if (R_FAILED((rc = FsPathUtils::ConvertPathForServiceObject(&path, in_path.pointer)))) {
return rc;
}
return this->base_fs->DeleteDirectoryRecursively(path); return this->base_fs->DeleteDirectoryRecursively(path);
} }
@@ -272,14 +252,8 @@ class IFileSystemInterface : public IServiceObject {
virtual Result RenameFile(InPointer<char> in_old_path, InPointer<char> in_new_path) final { virtual Result RenameFile(InPointer<char> in_old_path, InPointer<char> in_new_path) final {
FsPath old_path; FsPath old_path;
FsPath new_path; FsPath new_path;
R_TRY(FsPathUtils::ConvertPathForServiceObject(&old_path, in_old_path.pointer));
Result rc; R_TRY(FsPathUtils::ConvertPathForServiceObject(&new_path, in_new_path.pointer));
if (R_FAILED((rc = FsPathUtils::ConvertPathForServiceObject(&old_path, in_old_path.pointer)))) {
return rc;
}
if (R_FAILED((rc = FsPathUtils::ConvertPathForServiceObject(&new_path, in_new_path.pointer)))) {
return rc;
}
return this->base_fs->RenameFile(old_path, new_path); return this->base_fs->RenameFile(old_path, new_path);
} }
@@ -287,14 +261,8 @@ class IFileSystemInterface : public IServiceObject {
virtual Result RenameDirectory(InPointer<char> in_old_path, InPointer<char> in_new_path) final { virtual Result RenameDirectory(InPointer<char> in_old_path, InPointer<char> in_new_path) final {
FsPath old_path; FsPath old_path;
FsPath new_path; FsPath new_path;
R_TRY(FsPathUtils::ConvertPathForServiceObject(&old_path, in_old_path.pointer));
Result rc; R_TRY(FsPathUtils::ConvertPathForServiceObject(&new_path, in_new_path.pointer));
if (R_FAILED((rc = FsPathUtils::ConvertPathForServiceObject(&old_path, in_old_path.pointer)))) {
return rc;
}
if (R_FAILED((rc = FsPathUtils::ConvertPathForServiceObject(&new_path, in_new_path.pointer)))) {
return rc;
}
return this->base_fs->RenameDirectory(old_path, new_path); return this->base_fs->RenameDirectory(old_path, new_path);
} }
@@ -302,54 +270,35 @@ class IFileSystemInterface : public IServiceObject {
virtual Result GetEntryType(Out<u32> out_type, InPointer<char> in_path) final { virtual Result GetEntryType(Out<u32> out_type, InPointer<char> in_path) final {
FsPath path; FsPath path;
R_TRY(FsPathUtils::ConvertPathForServiceObject(&path, in_path.pointer));
Result rc;
if (R_FAILED((rc = FsPathUtils::ConvertPathForServiceObject(&path, in_path.pointer)))) {
return rc;
}
DirectoryEntryType type; DirectoryEntryType type;
rc = this->base_fs->GetEntryType(&type, path); R_TRY(this->base_fs->GetEntryType(&type, path));
if (R_SUCCEEDED(rc)) {
out_type.SetValue(type); out_type.SetValue(type);
} return ResultSuccess;
return rc;
} }
virtual Result OpenFile(Out<std::shared_ptr<IFileInterface>> out_intf, InPointer<char> in_path, uint32_t mode) final { virtual Result OpenFile(Out<std::shared_ptr<IFileInterface>> out_intf, InPointer<char> in_path, uint32_t mode) final {
FsPath path; FsPath path;
R_TRY(FsPathUtils::ConvertPathForServiceObject(&path, in_path.pointer));
std::unique_ptr<IFile> out_file; std::unique_ptr<IFile> out_file;
R_TRY(this->base_fs->OpenFile(out_file, path, static_cast<OpenMode>(mode)));
Result rc; out_intf.SetValue(std::make_shared<IFileInterface>(std::move(out_file)));
if (R_FAILED((rc = FsPathUtils::ConvertPathForServiceObject(&path, in_path.pointer)))) { return ResultSuccess;
return rc;
}
rc = this->base_fs->OpenFile(out_file, path, static_cast<OpenMode>(mode));
if (R_SUCCEEDED(rc)) {
out_intf.SetValue(std::make_shared<IFileInterface>(std::move(out_file)));
/* TODO: Nintendo checks allocation success here, should we?. */
}
return rc;
} }
virtual Result OpenDirectory(Out<std::shared_ptr<IDirectoryInterface>> out_intf, InPointer<char> in_path, uint32_t mode) final { virtual Result OpenDirectory(Out<std::shared_ptr<IDirectoryInterface>> out_intf, InPointer<char> in_path, uint32_t mode) final {
FsPath path; FsPath path;
R_TRY(FsPathUtils::ConvertPathForServiceObject(&path, in_path.pointer));
std::unique_ptr<IDirectory> out_dir; std::unique_ptr<IDirectory> out_dir;
R_TRY(this->base_fs->OpenDirectory(out_dir, path, static_cast<DirectoryOpenMode>(mode)));
Result rc; out_intf.SetValue(std::make_shared<IDirectoryInterface>(std::move(out_dir)));
if (R_FAILED((rc = FsPathUtils::ConvertPathForServiceObject(&path, in_path.pointer)))) { return ResultSuccess;
return rc;
}
rc = this->base_fs->OpenDirectory(out_dir, path, static_cast<DirectoryOpenMode>(mode));
if (R_SUCCEEDED(rc)) {
out_intf.SetValue(std::make_shared<IDirectoryInterface>(std::move(out_dir)));
/* TODO: Nintendo checks allocation success here, should we?. */
}
return rc;
} }
virtual Result Commit() final { virtual Result Commit() final {
@@ -358,81 +307,61 @@ class IFileSystemInterface : public IServiceObject {
virtual Result GetFreeSpaceSize(Out<uint64_t> out_size, InPointer<char> in_path) final { virtual Result GetFreeSpaceSize(Out<uint64_t> out_size, InPointer<char> in_path) final {
FsPath path; FsPath path;
R_TRY(FsPathUtils::ConvertPathForServiceObject(&path, in_path.pointer));
Result rc;
if (R_FAILED((rc = FsPathUtils::ConvertPathForServiceObject(&path, in_path.pointer)))) {
return rc;
}
return this->base_fs->GetFreeSpaceSize(out_size.GetPointer(), path); return this->base_fs->GetFreeSpaceSize(out_size.GetPointer(), path);
} }
virtual Result GetTotalSpaceSize(Out<uint64_t> out_size, InPointer<char> in_path) final { virtual Result GetTotalSpaceSize(Out<uint64_t> out_size, InPointer<char> in_path) final {
FsPath path; FsPath path;
R_TRY(FsPathUtils::ConvertPathForServiceObject(&path, in_path.pointer));
Result rc;
if (R_FAILED((rc = FsPathUtils::ConvertPathForServiceObject(&path, in_path.pointer)))) {
return rc;
}
return this->base_fs->GetTotalSpaceSize(out_size.GetPointer(), path); return this->base_fs->GetTotalSpaceSize(out_size.GetPointer(), path);
} }
virtual Result CleanDirectoryRecursively(InPointer<char> in_path) final { virtual Result CleanDirectoryRecursively(InPointer<char> in_path) final {
FsPath path; FsPath path;
R_TRY(FsPathUtils::ConvertPathForServiceObject(&path, in_path.pointer));
Result rc;
if (R_FAILED((rc = FsPathUtils::ConvertPathForServiceObject(&path, in_path.pointer)))) {
return rc;
}
return this->base_fs->CleanDirectoryRecursively(path); return this->base_fs->CleanDirectoryRecursively(path);
} }
virtual Result GetFileTimeStampRaw(Out<FsTimeStampRaw> out_timestamp, InPointer<char> in_path) final { virtual Result GetFileTimeStampRaw(Out<FsTimeStampRaw> out_timestamp, InPointer<char> in_path) final {
FsPath path; FsPath path;
R_TRY(FsPathUtils::ConvertPathForServiceObject(&path, in_path.pointer));
Result rc;
if (R_FAILED((rc = FsPathUtils::ConvertPathForServiceObject(&path, in_path.pointer)))) {
return rc;
}
return this->base_fs->GetFileTimeStampRaw(out_timestamp.GetPointer(), path); return this->base_fs->GetFileTimeStampRaw(out_timestamp.GetPointer(), path);
} }
virtual Result QueryEntry(OutBuffer<char, BufferType_Type1> out_buffer, InBuffer<char, BufferType_Type1> in_buffer, int query, InPointer<char> in_path) final { virtual Result QueryEntry(OutBuffer<char, BufferType_Type1> out_buffer, InBuffer<char, BufferType_Type1> in_buffer, int query, InPointer<char> in_path) final {
FsPath path; FsPath path;
R_TRY(FsPathUtils::ConvertPathForServiceObject(&path, in_path.pointer));
Result rc;
if (R_FAILED((rc = FsPathUtils::ConvertPathForServiceObject(&path, in_path.pointer)))) {
return rc;
}
return this->base_fs->QueryEntry(out_buffer.buffer, out_buffer.num_elements, in_buffer.buffer, in_buffer.num_elements, query, path); return this->base_fs->QueryEntry(out_buffer.buffer, out_buffer.num_elements, in_buffer.buffer, in_buffer.num_elements, query, path);
} }
public: public:
DEFINE_SERVICE_DISPATCH_TABLE { DEFINE_SERVICE_DISPATCH_TABLE {
/* 1.0.0- */ /* 1.0.0- */
MakeServiceCommandMeta<FsIFileSystemCmd_CreateFile, &IFileSystemInterface::CreateFile>(), MAKE_SERVICE_COMMAND_META(IFileSystemInterface, CreateFile),
MakeServiceCommandMeta<FsIFileSystemCmd_DeleteFile, &IFileSystemInterface::DeleteFile>(), MAKE_SERVICE_COMMAND_META(IFileSystemInterface, DeleteFile),
MakeServiceCommandMeta<FsIFileSystemCmd_CreateDirectory, &IFileSystemInterface::CreateDirectory>(), MAKE_SERVICE_COMMAND_META(IFileSystemInterface, CreateDirectory),
MakeServiceCommandMeta<FsIFileSystemCmd_DeleteDirectory, &IFileSystemInterface::DeleteDirectory>(), MAKE_SERVICE_COMMAND_META(IFileSystemInterface, DeleteDirectory),
MakeServiceCommandMeta<FsIFileSystemCmd_DeleteDirectoryRecursively, &IFileSystemInterface::DeleteDirectoryRecursively>(), MAKE_SERVICE_COMMAND_META(IFileSystemInterface, DeleteDirectoryRecursively),
MakeServiceCommandMeta<FsIFileSystemCmd_RenameFile, &IFileSystemInterface::RenameFile>(), MAKE_SERVICE_COMMAND_META(IFileSystemInterface, RenameFile),
MakeServiceCommandMeta<FsIFileSystemCmd_RenameDirectory, &IFileSystemInterface::RenameDirectory>(), MAKE_SERVICE_COMMAND_META(IFileSystemInterface, RenameDirectory),
MakeServiceCommandMeta<FsIFileSystemCmd_GetEntryType, &IFileSystemInterface::GetEntryType>(), MAKE_SERVICE_COMMAND_META(IFileSystemInterface, GetEntryType),
MakeServiceCommandMeta<FsIFileSystemCmd_OpenFile, &IFileSystemInterface::OpenFile>(), MAKE_SERVICE_COMMAND_META(IFileSystemInterface, OpenFile),
MakeServiceCommandMeta<FsIFileSystemCmd_OpenDirectory, &IFileSystemInterface::OpenDirectory>(), MAKE_SERVICE_COMMAND_META(IFileSystemInterface, OpenDirectory),
MakeServiceCommandMeta<FsIFileSystemCmd_Commit, &IFileSystemInterface::Commit>(), MAKE_SERVICE_COMMAND_META(IFileSystemInterface, Commit),
MakeServiceCommandMeta<FsIFileSystemCmd_GetFreeSpaceSize, &IFileSystemInterface::GetFreeSpaceSize>(), MAKE_SERVICE_COMMAND_META(IFileSystemInterface, GetFreeSpaceSize),
MakeServiceCommandMeta<FsIFileSystemCmd_GetTotalSpaceSize, &IFileSystemInterface::GetTotalSpaceSize>(), MAKE_SERVICE_COMMAND_META(IFileSystemInterface, GetTotalSpaceSize),
/* 3.0.0- */ /* 3.0.0- */
MakeServiceCommandMeta<FsIFileSystemCmd_CleanDirectoryRecursively, &IFileSystemInterface::CleanDirectoryRecursively, FirmwareVersion_300>(), MAKE_SERVICE_COMMAND_META(IFileSystemInterface, CleanDirectoryRecursively, FirmwareVersion_300),
MakeServiceCommandMeta<FsIFileSystemCmd_GetFileTimeStampRaw, &IFileSystemInterface::GetFileTimeStampRaw, FirmwareVersion_300>(), MAKE_SERVICE_COMMAND_META(IFileSystemInterface, GetFileTimeStampRaw, FirmwareVersion_300),
/* 4.0.0- */ /* 4.0.0- */
MakeServiceCommandMeta<FsIFileSystemCmd_QueryEntry, &IFileSystemInterface::QueryEntry, FirmwareVersion_400>(), MAKE_SERVICE_COMMAND_META(IFileSystemInterface, QueryEntry, FirmwareVersion_400),
}; };
}; };
@@ -487,34 +416,25 @@ class ProxyFileSystem : public IFileSystem {
virtual Result GetEntryTypeImpl(DirectoryEntryType *out, const FsPath &path) { virtual Result GetEntryTypeImpl(DirectoryEntryType *out, const FsPath &path) {
FsEntryType type; FsEntryType type;
R_TRY(fsFsGetEntryType(this->base_fs.get(), path.str, &type));
Result rc = fsFsGetEntryType(this->base_fs.get(), path.str, &type); *out = static_cast<DirectoryEntryType>(static_cast<u32>(type));
if (R_SUCCEEDED(rc)) { return ResultSuccess;
*out = static_cast<DirectoryEntryType>(static_cast<u32>(type));
}
return rc;
} }
virtual Result OpenFileImpl(std::unique_ptr<IFile> &out_file, const FsPath &path, OpenMode mode) { virtual Result OpenFileImpl(std::unique_ptr<IFile> &out_file, const FsPath &path, OpenMode mode) {
FsFile f; FsFile f;
R_TRY(fsFsOpenFile(this->base_fs.get(), path.str, static_cast<int>(mode), &f));
Result rc = fsFsOpenFile(this->base_fs.get(), path.str, static_cast<int>(mode), &f); out_file = std::make_unique<ProxyFile>(f);
if (R_SUCCEEDED(rc)) { return ResultSuccess;
out_file = std::make_unique<ProxyFile>(f);
}
return rc;
} }
virtual Result OpenDirectoryImpl(std::unique_ptr<IDirectory> &out_dir, const FsPath &path, DirectoryOpenMode mode) { virtual Result OpenDirectoryImpl(std::unique_ptr<IDirectory> &out_dir, const FsPath &path, DirectoryOpenMode mode) {
FsDir d; FsDir d;
R_TRY(fsFsOpenDirectory(this->base_fs.get(), path.str, static_cast<int>(mode), &d));
Result rc = fsFsOpenDirectory(this->base_fs.get(), path.str, static_cast<int>(mode), &d); out_dir = std::make_unique<ProxyDirectory>(d);
if (R_SUCCEEDED(rc)) { return ResultSuccess;
out_dir = std::make_unique<ProxyDirectory>(d);
}
return rc;
} }
virtual Result CommitImpl() { virtual Result CommitImpl() {

View File

@@ -21,15 +21,6 @@
#include "../debug.hpp" #include "../debug.hpp"
enum FsIStorageCmd : u32 {
FsIStorageCmd_Read = 0,
FsIStorageCmd_Write = 1,
FsIStorageCmd_Flush = 2,
FsIStorageCmd_SetSize = 3,
FsIStorageCmd_GetSize = 4,
FsIStorageCmd_OperateRange = 5,
};
class IStorage { class IStorage {
public: public:
virtual ~IStorage(); virtual ~IStorage();
@@ -47,6 +38,15 @@ class IStorage {
}; };
class IStorageInterface : public IServiceObject { class IStorageInterface : public IServiceObject {
private:
enum class CommandId {
Read = 0,
Write = 1,
Flush = 2,
SetSize = 3,
GetSize = 4,
OperateRange = 5,
};
private: private:
IStorage *base_storage; IStorage *base_storage;
public: public:
@@ -81,14 +81,14 @@ class IStorageInterface : public IServiceObject {
public: public:
DEFINE_SERVICE_DISPATCH_TABLE { DEFINE_SERVICE_DISPATCH_TABLE {
/* 1.0.0- */ /* 1.0.0- */
MakeServiceCommandMeta<FsIStorageCmd_Read, &IStorageInterface::Read>(), MAKE_SERVICE_COMMAND_META(IStorageInterface, Read),
MakeServiceCommandMeta<FsIStorageCmd_Write, &IStorageInterface::Write>(), MAKE_SERVICE_COMMAND_META(IStorageInterface, Write),
MakeServiceCommandMeta<FsIStorageCmd_Flush, &IStorageInterface::Flush>(), MAKE_SERVICE_COMMAND_META(IStorageInterface, Flush),
MakeServiceCommandMeta<FsIStorageCmd_SetSize, &IStorageInterface::SetSize>(), MAKE_SERVICE_COMMAND_META(IStorageInterface, SetSize),
MakeServiceCommandMeta<FsIStorageCmd_GetSize, &IStorageInterface::GetSize>(), MAKE_SERVICE_COMMAND_META(IStorageInterface, GetSize),
/* 4.0.0- */ /* 4.0.0- */
MakeServiceCommandMeta<FsIStorageCmd_OperateRange, &IStorageInterface::OperateRange, FirmwareVersion_400>(), MAKE_SERVICE_COMMAND_META(IStorageInterface, OperateRange, FirmwareVersion_400),
}; };
}; };

View File

@@ -260,7 +260,8 @@ Result FsPathUtils::Normalize(char *out, size_t max_out_size, const char *src, s
/* Assert normalized. */ /* Assert normalized. */
bool normalized = false; bool normalized = false;
if (R_FAILED(FsPathUtils::IsNormalized(&normalized, out)) || !normalized) { R_ASSERT(FsPathUtils::IsNormalized(&normalized, out));
if (!normalized) {
std::abort(); std::abort();
} }

View File

@@ -100,12 +100,10 @@ Result FsSaveUtils::GetSaveDataTypeString(const char **out_str, u8 save_data_typ
Result FsSaveUtils::GetSaveDataDirectoryPath(FsPath &out_path, u8 space_id, u8 save_data_type, u64 title_id, u128 user_id, u64 save_id) { Result FsSaveUtils::GetSaveDataDirectoryPath(FsPath &out_path, u8 space_id, u8 save_data_type, u64 title_id, u128 user_id, u64 save_id) {
const char *space_id_str, *save_type_str; const char *space_id_str, *save_type_str;
Result rc;
/* Get space_id, save_data_type strings. */ /* Get space_id, save_data_type strings. */
if (R_FAILED((rc = GetSaveDataSpaceIdString(&space_id_str, space_id))) || R_FAILED((rc = GetSaveDataTypeString(&save_type_str, save_data_type)))) { R_TRY(GetSaveDataSpaceIdString(&space_id_str, space_id));
return rc; R_TRY(GetSaveDataTypeString(&save_type_str, save_data_type));
}
/* Clear and initialize the path. */ /* Clear and initialize the path. */
std::memset(&out_path, 0, sizeof(out_path)); std::memset(&out_path, 0, sizeof(out_path));

View File

@@ -30,11 +30,7 @@ Result SubDirectoryFileSystem::Initialize(const char *bp) {
/* Normalize the path. */ /* Normalize the path. */
char normal_path[FS_MAX_PATH + 1]; char normal_path[FS_MAX_PATH + 1];
size_t normal_path_len; size_t normal_path_len;
Result rc = FsPathUtils::Normalize(normal_path, sizeof(normal_path), bp, &normal_path_len); R_ASSERT(FsPathUtils::Normalize(normal_path, sizeof(normal_path), bp, &normal_path_len));
if (R_FAILED(rc)) {
/* N calls svcBreak here. */
std::abort();
}
/* Ensure terminating '/' */ /* Ensure terminating '/' */
if (normal_path[normal_path_len-1] != '/') { if (normal_path[normal_path_len-1] != '/') {
@@ -72,119 +68,73 @@ Result SubDirectoryFileSystem::GetFullPath(char *out, size_t out_size, const cha
} }
Result SubDirectoryFileSystem::CreateFileImpl(const FsPath &path, uint64_t size, int flags) { Result SubDirectoryFileSystem::CreateFileImpl(const FsPath &path, uint64_t size, int flags) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
return this->base_fs->CreateFile(full_path, size, flags); return this->base_fs->CreateFile(full_path, size, flags);
} }
Result SubDirectoryFileSystem::DeleteFileImpl(const FsPath &path) { Result SubDirectoryFileSystem::DeleteFileImpl(const FsPath &path) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
return this->base_fs->DeleteFile(full_path); return this->base_fs->DeleteFile(full_path);
} }
Result SubDirectoryFileSystem::CreateDirectoryImpl(const FsPath &path) { Result SubDirectoryFileSystem::CreateDirectoryImpl(const FsPath &path) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
return this->base_fs->CreateDirectory(full_path); return this->base_fs->CreateDirectory(full_path);
} }
Result SubDirectoryFileSystem::DeleteDirectoryImpl(const FsPath &path) { Result SubDirectoryFileSystem::DeleteDirectoryImpl(const FsPath &path) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
return this->base_fs->DeleteDirectory(full_path); return this->base_fs->DeleteDirectory(full_path);
} }
Result SubDirectoryFileSystem::DeleteDirectoryRecursivelyImpl(const FsPath &path) { Result SubDirectoryFileSystem::DeleteDirectoryRecursivelyImpl(const FsPath &path) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
return this->base_fs->DeleteDirectoryRecursively(full_path); return this->base_fs->DeleteDirectoryRecursively(full_path);
} }
Result SubDirectoryFileSystem::RenameFileImpl(const FsPath &old_path, const FsPath &new_path) { Result SubDirectoryFileSystem::RenameFileImpl(const FsPath &old_path, const FsPath &new_path) {
Result rc;
FsPath full_old_path, full_new_path; FsPath full_old_path, full_new_path;
R_TRY(GetFullPath(full_old_path, old_path));
if (R_FAILED((rc = GetFullPath(full_old_path, old_path)))) { R_TRY(GetFullPath(full_new_path, new_path));
return rc;
}
if (R_FAILED((rc = GetFullPath(full_new_path, new_path)))) {
return rc;
}
return this->base_fs->RenameFile(full_old_path, full_new_path); return this->base_fs->RenameFile(full_old_path, full_new_path);
} }
Result SubDirectoryFileSystem::RenameDirectoryImpl(const FsPath &old_path, const FsPath &new_path) { Result SubDirectoryFileSystem::RenameDirectoryImpl(const FsPath &old_path, const FsPath &new_path) {
Result rc;
FsPath full_old_path, full_new_path; FsPath full_old_path, full_new_path;
R_TRY(GetFullPath(full_old_path, old_path));
if (R_FAILED((rc = GetFullPath(full_old_path, old_path)))) { R_TRY(GetFullPath(full_new_path, new_path));
return rc;
}
if (R_FAILED((rc = GetFullPath(full_new_path, new_path)))) {
return rc;
}
return this->base_fs->RenameDirectory(full_old_path, full_new_path); return this->base_fs->RenameDirectory(full_old_path, full_new_path);
} }
Result SubDirectoryFileSystem::GetEntryTypeImpl(DirectoryEntryType *out, const FsPath &path) { Result SubDirectoryFileSystem::GetEntryTypeImpl(DirectoryEntryType *out, const FsPath &path) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
return this->base_fs->GetEntryType(out, full_path); return this->base_fs->GetEntryType(out, full_path);
} }
Result SubDirectoryFileSystem::OpenFileImpl(std::unique_ptr<IFile> &out_file, const FsPath &path, OpenMode mode) { Result SubDirectoryFileSystem::OpenFileImpl(std::unique_ptr<IFile> &out_file, const FsPath &path, OpenMode mode) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
return this->base_fs->OpenFile(out_file, full_path, mode); return this->base_fs->OpenFile(out_file, full_path, mode);
} }
Result SubDirectoryFileSystem::OpenDirectoryImpl(std::unique_ptr<IDirectory> &out_dir, const FsPath &path, DirectoryOpenMode mode) { Result SubDirectoryFileSystem::OpenDirectoryImpl(std::unique_ptr<IDirectory> &out_dir, const FsPath &path, DirectoryOpenMode mode) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
return this->base_fs->OpenDirectory(out_dir, full_path, mode); return this->base_fs->OpenDirectory(out_dir, full_path, mode);
} }
@@ -194,56 +144,36 @@ Result SubDirectoryFileSystem::CommitImpl() {
} }
Result SubDirectoryFileSystem::GetFreeSpaceSizeImpl(uint64_t *out, const FsPath &path) { Result SubDirectoryFileSystem::GetFreeSpaceSizeImpl(uint64_t *out, const FsPath &path) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
return this->base_fs->GetFreeSpaceSize(out, full_path); return this->base_fs->GetFreeSpaceSize(out, full_path);
} }
Result SubDirectoryFileSystem::GetTotalSpaceSizeImpl(uint64_t *out, const FsPath &path) { Result SubDirectoryFileSystem::GetTotalSpaceSizeImpl(uint64_t *out, const FsPath &path) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
return this->base_fs->GetTotalSpaceSize(out, full_path); return this->base_fs->GetTotalSpaceSize(out, full_path);
} }
Result SubDirectoryFileSystem::CleanDirectoryRecursivelyImpl(const FsPath &path) { Result SubDirectoryFileSystem::CleanDirectoryRecursivelyImpl(const FsPath &path) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
return this->base_fs->CleanDirectoryRecursively(full_path); return this->base_fs->CleanDirectoryRecursively(full_path);
} }
Result SubDirectoryFileSystem::GetFileTimeStampRawImpl(FsTimeStampRaw *out, const FsPath &path) { Result SubDirectoryFileSystem::GetFileTimeStampRawImpl(FsTimeStampRaw *out, const FsPath &path) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
return this->base_fs->GetFileTimeStampRaw(out, full_path); return this->base_fs->GetFileTimeStampRaw(out, full_path);
} }
Result SubDirectoryFileSystem::QueryEntryImpl(char *out, uint64_t out_size, const char *in, uint64_t in_size, int query, const FsPath &path) { Result SubDirectoryFileSystem::QueryEntryImpl(char *out, uint64_t out_size, const char *in, uint64_t in_size, int query, const FsPath &path) {
Result rc;
FsPath full_path; FsPath full_path;
R_TRY(GetFullPath(full_path, path));
if (R_FAILED((rc = GetFullPath(full_path, path)))) {
return rc;
}
return this->base_fs->QueryEntry(out, out_size, in, in_size, query, full_path); return this->base_fs->QueryEntry(out, out_size, in, in_size, query, full_path);
} }

View File

@@ -29,17 +29,11 @@ class SubDirectoryFileSystem : public IFileSystem {
public: public:
SubDirectoryFileSystem(IFileSystem *fs, const char *bp) : base_fs(fs) { SubDirectoryFileSystem(IFileSystem *fs, const char *bp) : base_fs(fs) {
Result rc = this->Initialize(bp); R_ASSERT(this->Initialize(bp));
if (R_FAILED(rc)) {
fatalSimple(rc);
}
} }
SubDirectoryFileSystem(std::shared_ptr<IFileSystem> fs, const char *bp) : base_fs(fs) { SubDirectoryFileSystem(std::shared_ptr<IFileSystem> fs, const char *bp) : base_fs(fs) {
Result rc = this->Initialize(bp); R_ASSERT(this->Initialize(bp));
if (R_FAILED(rc)) {
fatalSimple(rc);
}
} }

View File

@@ -45,7 +45,6 @@ Result Boot0Storage::Read(void *_buffer, size_t size, u64 offset) {
Result Boot0Storage::Write(void *_buffer, size_t size, u64 offset) { Result Boot0Storage::Write(void *_buffer, size_t size, u64 offset) {
std::scoped_lock<HosMutex> lk{g_boot0_mutex}; std::scoped_lock<HosMutex> lk{g_boot0_mutex};
Result rc = ResultSuccess;
u8 *buffer = static_cast<u8 *>(_buffer); u8 *buffer = static_cast<u8 *>(_buffer);
/* Protect the keyblob region from writes. */ /* Protect the keyblob region from writes. */
@@ -59,9 +58,7 @@ Result Boot0Storage::Write(void *_buffer, size_t size, u64 offset) {
} else { } else {
/* Perform portion of write falling past end of keyblobs. */ /* Perform portion of write falling past end of keyblobs. */
const u64 diff = EksEnd - offset; const u64 diff = EksEnd - offset;
if (R_FAILED((rc = Base::Write(buffer + diff, size - diff, EksEnd)))) { R_TRY(Base::Write(buffer + diff, size - diff, EksEnd));
return rc;
}
/* Adjust size to avoid writing end of data. */ /* Adjust size to avoid writing end of data. */
size = EksStart - offset; size = EksStart - offset;
} }
@@ -94,16 +91,12 @@ Result Boot0Storage::Write(void *_buffer, size_t size, u64 offset) {
/* First, let's deal with the data past the end. */ /* First, let's deal with the data past the end. */
if (offset + size >= BctEndOffset) { if (offset + size >= BctEndOffset) {
const u64 diff = BctEndOffset - offset; const u64 diff = BctEndOffset - offset;
if (R_FAILED((rc = ProxyStorage::Write(buffer + diff, size - diff, BctEndOffset)))) { R_TRY(ProxyStorage::Write(buffer + diff, size - diff, BctEndOffset));
return rc;
}
size = diff; size = diff;
} }
/* Read in the current BCT region. */ /* Read in the current BCT region. */
if (R_FAILED((rc = ProxyStorage::Read(g_boot0_bct_buffer, BctEndOffset, 0)))) { R_TRY(ProxyStorage::Read(g_boot0_bct_buffer, BctEndOffset, 0));
return rc;
}
/* Update the bct buffer. */ /* Update the bct buffer. */
for (u64 cur_ofs = offset; cur_ofs < BctEndOffset && cur_ofs < offset + size; cur_ofs++) { for (u64 cur_ofs = offset; cur_ofs < BctEndOffset && cur_ofs < offset + size; cur_ofs++) {

View File

@@ -39,7 +39,6 @@ class SectoredProxyStorage : public ProxyStorage {
SectoredProxyStorage(FsStorage s) : ProxyStorage(s) { } SectoredProxyStorage(FsStorage s) : ProxyStorage(s) { }
public: public:
virtual Result Read(void *_buffer, size_t size, u64 offset) override { virtual Result Read(void *_buffer, size_t size, u64 offset) override {
Result rc = ResultSuccess;
u8 *buffer = static_cast<u8 *>(_buffer); u8 *buffer = static_cast<u8 *>(_buffer);
this->Seek(offset); this->Seek(offset);
@@ -48,9 +47,7 @@ class SectoredProxyStorage : public ProxyStorage {
return ProxyStorage::Read(buffer, size, offset); return ProxyStorage::Read(buffer, size, offset);
} }
if (R_FAILED((rc = ProxyStorage::Read(this->sector_buf, SectorSize, this->cur_seek)))) { R_TRY(ProxyStorage::Read(this->sector_buf, SectorSize, this->cur_seek));
return rc;
}
if (size + this->cur_sector_ofs <= SectorSize) { if (size + this->cur_sector_ofs <= SectorSize) {
memcpy(buffer, sector_buf + this->cur_sector_ofs, size); memcpy(buffer, sector_buf + this->cur_sector_ofs, size);
@@ -63,26 +60,22 @@ class SectoredProxyStorage : public ProxyStorage {
/* We're guaranteed alignment, here. */ /* We're guaranteed alignment, here. */
const size_t aligned_remaining_size = size - (size % SectorSize); const size_t aligned_remaining_size = size - (size % SectorSize);
if (aligned_remaining_size) { if (aligned_remaining_size) {
if (R_FAILED((rc = ProxyStorage::Read(buffer + ofs, aligned_remaining_size, offset + ofs)))) { R_TRY(ProxyStorage::Read(buffer + ofs, aligned_remaining_size, offset + ofs));
return rc;
}
ofs += aligned_remaining_size; ofs += aligned_remaining_size;
size -= aligned_remaining_size; size -= aligned_remaining_size;
} }
/* Read any leftover data. */ /* Read any leftover data. */
if (size) { if (size) {
if (R_FAILED((rc = ProxyStorage::Read(this->sector_buf, SectorSize, offset + ofs)))) { R_TRY(ProxyStorage::Read(this->sector_buf, SectorSize, offset + ofs));
return rc;
}
memcpy(buffer + ofs, sector_buf, size); memcpy(buffer + ofs, sector_buf, size);
} }
} }
return rc; return ResultSuccess;
}; }
virtual Result Write(void *_buffer, size_t size, u64 offset) override { virtual Result Write(void *_buffer, size_t size, u64 offset) override {
Result rc = ResultSuccess;
u8 *buffer = static_cast<u8 *>(_buffer); u8 *buffer = static_cast<u8 *>(_buffer);
this->Seek(offset); this->Seek(offset);
@@ -91,45 +84,36 @@ class SectoredProxyStorage : public ProxyStorage {
return ProxyStorage::Write(buffer, size, offset); return ProxyStorage::Write(buffer, size, offset);
} }
if (R_FAILED((rc = ProxyStorage::Read(this->sector_buf, SectorSize, this->cur_seek)))) { R_TRY(ProxyStorage::Read(this->sector_buf, SectorSize, this->cur_seek));
return rc;
}
if (size + this->cur_sector_ofs <= SectorSize) { if (size + this->cur_sector_ofs <= SectorSize) {
memcpy(this->sector_buf + this->cur_sector_ofs, buffer, size); memcpy(this->sector_buf + this->cur_sector_ofs, buffer, size);
rc = ProxyStorage::Write(this->sector_buf, SectorSize, this->cur_seek); R_TRY(ProxyStorage::Write(this->sector_buf, SectorSize, this->cur_seek));
} else { } else {
/* Leaving the sector... */ /* Leaving the sector... */
size_t ofs = SectorSize - this->cur_sector_ofs; size_t ofs = SectorSize - this->cur_sector_ofs;
memcpy(this->sector_buf + this->cur_sector_ofs, buffer, ofs); memcpy(this->sector_buf + this->cur_sector_ofs, buffer, ofs);
if (R_FAILED((rc = ProxyStorage::Write(this->sector_buf, ofs, this->cur_seek)))) { R_TRY(ProxyStorage::Write(this->sector_buf, ofs, this->cur_seek));
return rc;
}
size -= ofs; size -= ofs;
/* We're guaranteed alignment, here. */ /* We're guaranteed alignment, here. */
const size_t aligned_remaining_size = size - (size % SectorSize); const size_t aligned_remaining_size = size - (size % SectorSize);
if (aligned_remaining_size) { if (aligned_remaining_size) {
if (R_FAILED((rc = ProxyStorage::Write(buffer + ofs, aligned_remaining_size, offset + ofs)))) { R_TRY(ProxyStorage::Write(buffer + ofs, aligned_remaining_size, offset + ofs));
return rc;
}
ofs += aligned_remaining_size; ofs += aligned_remaining_size;
size -= aligned_remaining_size; size -= aligned_remaining_size;
} }
/* Write any leftover data. */ /* Write any leftover data. */
if (size) { if (size) {
if (R_FAILED((rc = ProxyStorage::Read(this->sector_buf, SectorSize, offset + ofs)))) { R_TRY(ProxyStorage::Read(this->sector_buf, SectorSize, offset + ofs));
return rc;
}
memcpy(this->sector_buf, buffer + ofs, size); memcpy(this->sector_buf, buffer + ofs, size);
rc = ProxyStorage::Write(this->sector_buf, SectorSize, this->cur_seek); R_TRY(ProxyStorage::Write(this->sector_buf, SectorSize, this->cur_seek));
} }
} }
return rc; return ResultSuccess;
}; }
}; };
/* Represents an RCM-preserving BOOT0 partition. */ /* Represents an RCM-preserving BOOT0 partition. */

View File

@@ -78,7 +78,6 @@ Result LayeredRomFS::Read(void *buffer, size_t size, u64 offset) {
} }
} }
Result rc;
size_t read_so_far = 0; size_t read_so_far = 0;
while (read_so_far < size) { while (read_so_far < size) {
RomFSSourceInfo *cur_source = &((*this->p_source_infos)[cur_source_ind]); RomFSSourceInfo *cur_source = &((*this->p_source_infos)[cur_source_ind]);
@@ -91,15 +90,11 @@ Result LayeredRomFS::Read(void *buffer, size_t size, u64 offset) {
case RomFSDataSource::MetaData: case RomFSDataSource::MetaData:
{ {
FsFile file; FsFile file;
if (R_FAILED((rc = Utils::OpenSdFileForAtmosphere(this->title_id, ROMFS_METADATA_FILE_PATH, FS_OPEN_READ, &file)))) { R_ASSERT(Utils::OpenSdFileForAtmosphere(this->title_id, ROMFS_METADATA_FILE_PATH, FS_OPEN_READ, &file));
fatalSimple(rc);
}
size_t out_read; size_t out_read;
if (R_FAILED((rc = fsFileRead(&file, (offset - cur_source->virtual_offset), (void *)((uintptr_t)buffer + read_so_far), cur_read_size, FS_READOPTION_NONE, &out_read)))) { R_ASSERT(fsFileRead(&file, (offset - cur_source->virtual_offset), (void *)((uintptr_t)buffer + read_so_far), cur_read_size, FS_READOPTION_NONE, &out_read));
fatalSimple(rc);
}
if (out_read != cur_read_size) { if (out_read != cur_read_size) {
Reboot(); std::abort();
} }
fsFileClose(&file); fsFileClose(&file);
} }
@@ -107,15 +102,11 @@ Result LayeredRomFS::Read(void *buffer, size_t size, u64 offset) {
case RomFSDataSource::LooseFile: case RomFSDataSource::LooseFile:
{ {
FsFile file; FsFile file;
if (R_FAILED((rc = Utils::OpenRomFSSdFile(this->title_id, cur_source->loose_source_info.path, FS_OPEN_READ, &file)))) { R_ASSERT(Utils::OpenRomFSSdFile(this->title_id, cur_source->loose_source_info.path, FS_OPEN_READ, &file));
fatalSimple(rc);
}
size_t out_read; size_t out_read;
if (R_FAILED((rc = fsFileRead(&file, (offset - cur_source->virtual_offset), (void *)((uintptr_t)buffer + read_so_far), cur_read_size, FS_READOPTION_NONE, &out_read)))) { R_ASSERT(fsFileRead(&file, (offset - cur_source->virtual_offset), (void *)((uintptr_t)buffer + read_so_far), cur_read_size, FS_READOPTION_NONE, &out_read));
fatalSimple(rc);
}
if (out_read != cur_read_size) { if (out_read != cur_read_size) {
Reboot(); std::abort();
} }
fsFileClose(&file); fsFileClose(&file);
} }
@@ -127,23 +118,16 @@ Result LayeredRomFS::Read(void *buffer, size_t size, u64 offset) {
break; break;
case RomFSDataSource::BaseRomFS: case RomFSDataSource::BaseRomFS:
{ {
if (R_FAILED((rc = this->storage_romfs->Read((void *)((uintptr_t)buffer + read_so_far), cur_read_size, cur_source->base_source_info.offset + (offset - cur_source->virtual_offset))))) { R_ASSERT(this->storage_romfs->Read((void *)((uintptr_t)buffer + read_so_far), cur_read_size, cur_source->base_source_info.offset + (offset - cur_source->virtual_offset)));
/* TODO: Can this ever happen? */
/* fatalSimple(rc); */
return rc;
}
} }
break; break;
case RomFSDataSource::FileRomFS: case RomFSDataSource::FileRomFS:
{ {
if (R_FAILED((rc = this->file_romfs->Read((void *)((uintptr_t)buffer + read_so_far), cur_read_size, cur_source->base_source_info.offset + (offset - cur_source->virtual_offset))))) { R_ASSERT(this->file_romfs->Read((void *)((uintptr_t)buffer + read_so_far), cur_read_size, cur_source->base_source_info.offset + (offset - cur_source->virtual_offset)));
fatalSimple(rc);
}
} }
break; break;
default: default:
/* TODO: Better error. */ std::abort();
fatalSimple(ResultKernelConnectionClosed);
break; break;
} }
read_so_far += cur_read_size; read_so_far += cur_read_size;

View File

@@ -37,14 +37,12 @@ using FsMitmManager = WaitableManager<FsMitmManagerOptions>;
void FsMitmMain(void *arg) { void FsMitmMain(void *arg) {
/* Create server manager. */ /* Create server manager. */
auto server_manager = new FsMitmManager(5); static auto s_server_manager = FsMitmManager(5);
/* Create fsp-srv mitm. */ /* Create fsp-srv mitm. */
AddMitmServerToManager<FsMitmService>(server_manager, "fsp-srv", 61); AddMitmServerToManager<FsMitmService>(&s_server_manager, "fsp-srv", 61);
/* Loop forever, servicing our services. */ /* Loop forever, servicing our services. */
server_manager->Process(); s_server_manager.Process();
delete server_manager;
} }

View File

@@ -24,62 +24,66 @@
void RomFSBuildContext::VisitDirectory(FsFileSystem *filesys, RomFSBuildDirectoryContext *parent) { void RomFSBuildContext::VisitDirectory(FsFileSystem *filesys, RomFSBuildDirectoryContext *parent) {
FsDir dir; FsDir dir;
Result rc;
std::vector<RomFSBuildDirectoryContext *> child_dirs; std::vector<RomFSBuildDirectoryContext *> child_dirs;
/* Open the current parent directory. */ /* Open the current parent directory. */
if (R_FAILED((rc = Utils::OpenRomFSDir(filesys, this->title_id, parent->path, &dir)))) { R_ASSERT(Utils::OpenRomFSDir(filesys, this->title_id, parent->path, &dir));
fatalSimple(rc); {
} ON_SCOPE_EXIT { fsDirClose(&dir); };
u64 read_entries; u64 read_entries;
while (R_SUCCEEDED((rc = fsDirRead(&dir, 0, &read_entries, 1, &this->dir_entry))) && read_entries == 1) { while (true) {
if (this->dir_entry.type == ENTRYTYPE_DIR) { R_ASSERT(fsDirRead(&dir, 0, &read_entries, 1, &this->dir_entry));
RomFSBuildDirectoryContext *child = new RomFSBuildDirectoryContext({0}); if (read_entries != 1) {
/* Set child's path. */ break;
child->cur_path_ofs = parent->path_len + 1;
child->path_len = child->cur_path_ofs + strlen(this->dir_entry.name);
child->path = new char[child->path_len + 1];
strcpy(child->path, parent->path);
if (child->path_len > FS_MAX_PATH - 1) {
fatalSimple(ResultFsTooLongPath);
} }
strcat(child->path + parent->path_len, "/");
strcat(child->path + parent->path_len, this->dir_entry.name);
if (!this->AddDirectory(parent, child, NULL)) { if (this->dir_entry.type == ENTRYTYPE_DIR) {
delete[] child->path; RomFSBuildDirectoryContext *child = new RomFSBuildDirectoryContext({0});
delete child; /* Set child's path. */
child->cur_path_ofs = parent->path_len + 1;
child->path_len = child->cur_path_ofs + strlen(this->dir_entry.name);
child->path = new char[child->path_len + 1];
strcpy(child->path, parent->path);
if (child->path_len > FS_MAX_PATH - 1) {
fatalSimple(ResultFsTooLongPath);
}
strcat(child->path + parent->path_len, "/");
strcat(child->path + parent->path_len, this->dir_entry.name);
if (!this->AddDirectory(parent, child, NULL)) {
delete[] child->path;
delete child;
} else {
child_dirs.push_back(child);
}
} else if (this->dir_entry.type == ENTRYTYPE_FILE) {
RomFSBuildFileContext *child = new RomFSBuildFileContext({0});
/* Set child's path. */
child->cur_path_ofs = parent->path_len + 1;
child->path_len = child->cur_path_ofs + strlen(this->dir_entry.name);
child->path = new char[child->path_len + 1];
strcpy(child->path, parent->path);
if (child->path_len > FS_MAX_PATH - 1) {
fatalSimple(ResultFsTooLongPath);
}
strcat(child->path + parent->path_len, "/");
strcat(child->path + parent->path_len, this->dir_entry.name);
child->source = this->cur_source_type;
child->size = this->dir_entry.fileSize;
if (!this->AddFile(parent, child)) {
delete[] child->path;
delete child;
}
} else { } else {
child_dirs.push_back(child); std::abort();
} }
} else if (this->dir_entry.type == ENTRYTYPE_FILE) {
RomFSBuildFileContext *child = new RomFSBuildFileContext({0});
/* Set child's path. */
child->cur_path_ofs = parent->path_len + 1;
child->path_len = child->cur_path_ofs + strlen(this->dir_entry.name);
child->path = new char[child->path_len + 1];
strcpy(child->path, parent->path);
if (child->path_len > FS_MAX_PATH - 1) {
fatalSimple(ResultFsTooLongPath);
}
strcat(child->path + parent->path_len, "/");
strcat(child->path + parent->path_len, this->dir_entry.name);
child->source = this->cur_source_type;
child->size = this->dir_entry.fileSize;
if (!this->AddFile(parent, child)) {
delete[] child->path;
delete child;
}
} else {
fatalSimple(rc);
} }
} }
fsDirClose(&dir);
for (auto &child : child_dirs) { for (auto &child : child_dirs) {
this->VisitDirectory(filesys, child); this->VisitDirectory(filesys, child);
@@ -174,25 +178,18 @@ void RomFSBuildContext::VisitDirectory(RomFSBuildDirectoryContext *parent, u32 p
} }
void RomFSBuildContext::MergeRomStorage(IROStorage *storage, RomFSDataSource source) { void RomFSBuildContext::MergeRomStorage(IROStorage *storage, RomFSDataSource source) {
Result rc;
RomFSHeader header; RomFSHeader header;
if (R_FAILED((rc = storage->Read(&header, sizeof(header), 0)))) { R_ASSERT(storage->Read(&header, sizeof(header), 0));
fatalSimple(rc);
}
if (header.header_size != sizeof(header)) { if (header.header_size != sizeof(header)) {
/* what */ /* what */
return; std::abort();
} }
/* Read tables. */ /* Read tables. */
auto dir_table = std::make_unique<u8[]>(header.dir_table_size); auto dir_table = std::make_unique<u8[]>(header.dir_table_size);
auto file_table = std::make_unique<u8[]>(header.file_table_size); auto file_table = std::make_unique<u8[]>(header.file_table_size);
if (R_FAILED((rc = storage->Read(dir_table.get(), header.dir_table_size, header.dir_table_ofs)))) { R_ASSERT(storage->Read(dir_table.get(), header.dir_table_size, header.dir_table_ofs));
fatalSimple(rc); R_ASSERT(storage->Read(file_table.get(), header.file_table_size, header.file_table_ofs));
}
if (R_FAILED((rc = storage->Read(file_table.get(), header.file_table_size, header.file_table_ofs)))) {
fatalSimple(rc);
}
this->cur_source_type = source; this->cur_source_type = source;
this->VisitDirectory(this->root, 0x0, dir_table.get(), (size_t)header.dir_table_size, file_table.get(), (size_t)header.file_table_size); this->VisitDirectory(this->root, 0x0, dir_table.get(), (size_t)header.dir_table_size, file_table.get(), (size_t)header.file_table_size);

View File

@@ -38,11 +38,11 @@ class RomFileStorage : public IROStorage {
public: public:
Result Read(void *buffer, size_t size, u64 offset) override { Result Read(void *buffer, size_t size, u64 offset) override {
size_t out_sz = 0; size_t out_sz = 0;
Result rc = fsFileRead(this->base_file, offset, buffer, size, FS_READOPTION_NONE, &out_sz); R_TRY(fsFileRead(this->base_file, offset, buffer, size, FS_READOPTION_NONE, &out_sz));
if (R_SUCCEEDED(rc) && out_sz != size && out_sz) { if (out_sz != size && out_sz) {
return this->Read((void *)((uintptr_t)buffer + out_sz), size - out_sz, offset + out_sz); R_TRY(this->Read((void *)((uintptr_t)buffer + out_sz), size - out_sz, offset + out_sz));
} }
return rc; return ResultSuccess;
}; };
Result GetSize(u64 *out_size) override { Result GetSize(u64 *out_size) override {
return fsFileGetSize(this->base_file, out_size); return fsFileGetSize(this->base_file, out_size);

View File

@@ -69,8 +69,8 @@ static void StorageCacheSetEntry(u64 title_id, std::shared_ptr<IStorageInterface
void FsMitmService::PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx) { void FsMitmService::PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx) {
auto this_ptr = static_cast<FsMitmService *>(obj); auto this_ptr = static_cast<FsMitmService *>(obj);
switch ((FspSrvCmd)ctx->cmd_id) { switch (static_cast<CommandId>(ctx->cmd_id)) {
case FspSrvCmd_SetCurrentProcess: case CommandId::SetCurrentProcess:
if (R_SUCCEEDED(ctx->rc)) { if (R_SUCCEEDED(ctx->rc)) {
this_ptr->has_initialized = true; this_ptr->has_initialized = true;
this_ptr->process_id = ctx->request.Pid; this_ptr->process_id = ctx->request.Pid;
@@ -87,31 +87,18 @@ void FsMitmService::PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx
} }
Result FsMitmService::OpenHblWebContentFileSystem(Out<std::shared_ptr<IFileSystemInterface>> &out_fs) { Result FsMitmService::OpenHblWebContentFileSystem(Out<std::shared_ptr<IFileSystemInterface>> &out_fs) {
std::shared_ptr<IFileSystemInterface> fs = nullptr;
u32 out_domain_id = 0;
Result rc = ResultSuccess;
ON_SCOPE_EXIT {
if (R_SUCCEEDED(rc)) {
out_fs.SetValue(std::move(fs));
if (out_fs.IsDomain()) {
out_fs.ChangeObjectId(out_domain_id);
}
}
};
/* Mount the SD card using fs.mitm's session. */ /* Mount the SD card using fs.mitm's session. */
FsFileSystem sd_fs; FsFileSystem sd_fs;
rc = fsMountSdcard(&sd_fs); R_TRY(fsMountSdcard(&sd_fs));
if (R_SUCCEEDED(rc)) {
std::unique_ptr<IFileSystem> web_ifs = std::make_unique<SubDirectoryFileSystem>(std::make_shared<ProxyFileSystem>(sd_fs), AtmosphereHblWebContentDir); /* Set output filesystem. */
fs = std::make_shared<IFileSystemInterface>(std::move(web_ifs)); std::unique_ptr<IFileSystem> web_ifs = std::make_unique<SubDirectoryFileSystem>(std::make_shared<ProxyFileSystem>(sd_fs), AtmosphereHblWebContentDir);
if (out_fs.IsDomain()) { out_fs.SetValue(std::make_shared<IFileSystemInterface>(std::move(web_ifs)));
out_domain_id = sd_fs.s.object_id; if (out_fs.IsDomain()) {
} out_fs.ChangeObjectId(sd_fs.s.object_id);
} }
return rc; return ResultSuccess;
} }
Result FsMitmService::OpenFileSystemWithPatch(Out<std::shared_ptr<IFileSystemInterface>> out_fs, u64 title_id, u32 filesystem_type) { Result FsMitmService::OpenFileSystemWithPatch(Out<std::shared_ptr<IFileSystemInterface>> out_fs, u64 title_id, u32 filesystem_type) {
@@ -171,32 +158,18 @@ Result FsMitmService::OpenSdCardFileSystem(Out<std::shared_ptr<IFileSystemInterf
return ResultAtmosphereMitmShouldForwardToSession; return ResultAtmosphereMitmShouldForwardToSession;
} }
std::shared_ptr<IFileSystemInterface> fs = nullptr;
u32 out_domain_id = 0;
Result rc = ResultSuccess;
ON_SCOPE_EXIT {
if (R_SUCCEEDED(rc)) {
out_fs.SetValue(std::move(fs));
if (out_fs.IsDomain()) {
out_fs.ChangeObjectId(out_domain_id);
}
}
};
/* Mount the SD card. */ /* Mount the SD card. */
FsFileSystem sd_fs; FsFileSystem sd_fs;
if (R_FAILED((rc = fsMountSdcard(&sd_fs)))) { R_TRY(fsMountSdcard(&sd_fs));
return rc;
}
std::shared_ptr<IFileSystem> redir_fs = std::make_shared<DirectoryRedirectionFileSystem>(new ProxyFileSystem(sd_fs), "/Nintendo", GetEmummcNintendoDirPath()); /* Set output filesystem. */
fs = std::make_shared<IFileSystemInterface>(redir_fs); std::unique_ptr<IFileSystem> redir_fs = std::make_unique<DirectoryRedirectionFileSystem>(new ProxyFileSystem(sd_fs), "/Nintendo", GetEmummcNintendoDirPath());
out_fs.SetValue(std::make_shared<IFileSystemInterface>(std::move(redir_fs)));
if (out_fs.IsDomain()) { if (out_fs.IsDomain()) {
out_domain_id = sd_fs.s.object_id; out_fs.ChangeObjectId(sd_fs.s.object_id);
} }
return rc; return ResultSuccess;
} }
Result FsMitmService::OpenSaveDataFileSystem(Out<std::shared_ptr<IFileSystemInterface>> out_fs, u8 space_id, FsSave save_struct) { Result FsMitmService::OpenSaveDataFileSystem(Out<std::shared_ptr<IFileSystemInterface>> out_fs, u8 space_id, FsSave save_struct) {
@@ -219,33 +192,16 @@ Result FsMitmService::OpenSaveDataFileSystem(Out<std::shared_ptr<IFileSystemInte
std::unique_ptr<IFileSystem> save_ifs = std::make_unique<ProxyFileSystem>(save_fs); std::unique_ptr<IFileSystem> save_ifs = std::make_unique<ProxyFileSystem>(save_fs);
{ {
std::shared_ptr<IFileSystemInterface> fs = nullptr;
u32 out_domain_id = 0;
Result rc = ResultSuccess;
ON_SCOPE_EXIT {
if (R_SUCCEEDED(rc)) {
out_fs.SetValue(std::move(fs));
if (out_fs.IsDomain()) {
out_fs.ChangeObjectId(out_domain_id);
}
}
};
/* Mount the SD card using fs.mitm's session. */ /* Mount the SD card using fs.mitm's session. */
FsFileSystem sd_fs; FsFileSystem sd_fs;
if (R_FAILED((rc = fsMountSdcard(&sd_fs)))) { R_TRY(fsMountSdcard(&sd_fs));
return rc;
}
std::shared_ptr<IFileSystem> sd_ifs = std::make_shared<ProxyFileSystem>(sd_fs); std::shared_ptr<IFileSystem> sd_ifs = std::make_shared<ProxyFileSystem>(sd_fs);
/* Verify that we can open the save directory, and that it exists. */ /* Verify that we can open the save directory, and that it exists. */
const u64 target_tid = save_struct.titleID == 0 ? this->title_id : save_struct.titleID; const u64 target_tid = save_struct.titleID == 0 ? this->title_id : save_struct.titleID;
FsPath save_dir_path; FsPath save_dir_path;
if (R_FAILED((rc = FsSaveUtils::GetSaveDataDirectoryPath(save_dir_path, space_id, save_struct.SaveDataType, target_tid, save_struct.userID, save_struct.saveID)))) { R_TRY(FsSaveUtils::GetSaveDataDirectoryPath(save_dir_path, space_id, save_struct.SaveDataType, target_tid, save_struct.userID, save_struct.saveID));
return rc;
}
/* Check if this is the first time we're making the save. */ /* Check if this is the first time we're making the save. */
bool is_new_save = false; bool is_new_save = false;
@@ -257,9 +213,7 @@ Result FsMitmService::OpenSaveDataFileSystem(Out<std::shared_ptr<IFileSystemInte
} }
/* Ensure the directory exists. */ /* Ensure the directory exists. */
if (R_FAILED((rc = FsDirUtils::EnsureDirectoryExists(sd_ifs.get(), save_dir_path)))) { R_TRY(FsDirUtils::EnsureDirectoryExists(sd_ifs.get(), save_dir_path));
return rc;
}
std::shared_ptr<DirectorySaveDataFileSystem> dirsave_ifs = std::make_shared<DirectorySaveDataFileSystem>(new SubDirectoryFileSystem(sd_ifs, save_dir_path.str), std::move(save_ifs)); std::shared_ptr<DirectorySaveDataFileSystem> dirsave_ifs = std::make_shared<DirectorySaveDataFileSystem>(new SubDirectoryFileSystem(sd_ifs, save_dir_path.str), std::move(save_ifs));
@@ -269,206 +223,170 @@ Result FsMitmService::OpenSaveDataFileSystem(Out<std::shared_ptr<IFileSystemInte
dirsave_ifs->CopySaveFromProxy(); dirsave_ifs->CopySaveFromProxy();
} }
fs = std::make_shared<IFileSystemInterface>(static_cast<std::shared_ptr<IFileSystem>>(dirsave_ifs)); out_fs.SetValue(std::make_shared<IFileSystemInterface>(static_cast<std::shared_ptr<IFileSystem>>(dirsave_ifs)));
if (out_fs.IsDomain()) { if (out_fs.IsDomain()) {
out_domain_id = sd_fs.s.object_id; out_fs.ChangeObjectId(sd_fs.s.object_id);
} }
return rc; return ResultSuccess;
} }
} }
/* Gate access to the BIS partitions. */ /* Gate access to the BIS partitions. */
Result FsMitmService::OpenBisStorage(Out<std::shared_ptr<IStorageInterface>> out_storage, u32 _bis_partition_id) { Result FsMitmService::OpenBisStorage(Out<std::shared_ptr<IStorageInterface>> out_storage, u32 _bis_partition_id) {
std::shared_ptr<IStorageInterface> storage = nullptr;
u32 out_domain_id = 0;
Result rc = ResultSuccess;
const FsBisStorageId bis_partition_id = static_cast<FsBisStorageId>(_bis_partition_id); const FsBisStorageId bis_partition_id = static_cast<FsBisStorageId>(_bis_partition_id);
ON_SCOPE_EXIT { /* Try to open a storage for the partition. */
if (R_SUCCEEDED(rc)) { FsStorage bis_storage;
out_storage.SetValue(std::move(storage)); R_TRY(fsOpenBisStorageFwd(this->forward_service.get(), &bis_storage, bis_partition_id));
if (out_storage.IsDomain()) {
out_storage.ChangeObjectId(out_domain_id);
}
}
};
{ const bool is_sysmodule = TitleIdIsSystem(this->title_id);
FsStorage bis_storage; const bool has_bis_write_flag = Utils::HasFlag(this->title_id, "bis_write");
rc = fsOpenBisStorageFwd(this->forward_service.get(), &bis_storage, bis_partition_id); const bool has_cal0_read_flag = Utils::HasFlag(this->title_id, "cal_read");
if (R_SUCCEEDED(rc)) {
const bool is_sysmodule = TitleIdIsSystem(this->title_id); /* Set output storage. */
const bool has_bis_write_flag = Utils::HasFlag(this->title_id, "bis_write"); if (bis_partition_id == FsBisStorageId_Boot0) {
const bool has_cal0_read_flag = Utils::HasFlag(this->title_id, "cal_read"); out_storage.SetValue(std::make_shared<IStorageInterface>(new Boot0Storage(bis_storage, this->title_id)));
if (bis_partition_id == FsBisStorageId_Boot0) { } else if (bis_partition_id == FsBisStorageId_CalibrationBinary) {
storage = std::make_shared<IStorageInterface>(new Boot0Storage(bis_storage, this->title_id)); /* PRODINFO should *never* be writable. */
} else if (bis_partition_id == FsBisStorageId_CalibrationBinary) { if (is_sysmodule || has_cal0_read_flag) {
/* PRODINFO should *never* be writable. */ out_storage.SetValue(std::make_shared<IStorageInterface>(new ReadOnlyStorageAdapter(new ProxyStorage(bis_storage))));
if (is_sysmodule || has_cal0_read_flag) { } else {
storage = std::make_shared<IStorageInterface>(new ReadOnlyStorageAdapter(new ProxyStorage(bis_storage))); /* Do not allow non-sysmodules to read *or* write CAL0. */
} else { fsStorageClose(&bis_storage);
/* Do not allow non-sysmodules to read *or* write CAL0. */ return ResultFsPermissionDenied;
fsStorageClose(&bis_storage); }
rc = ResultFsPermissionDenied; } else {
return rc; if (is_sysmodule || has_bis_write_flag) {
} /* Sysmodules should still be allowed to read and write. */
} else { out_storage.SetValue(std::make_shared<IStorageInterface>(new ProxyStorage(bis_storage)));
if (is_sysmodule || has_bis_write_flag) { } else if (Utils::IsHblTid(this->title_id) &&
/* Sysmodules should still be allowed to read and write. */ ((FsBisStorageId_BootConfigAndPackage2NormalMain <= bis_partition_id && bis_partition_id <= FsBisStorageId_BootConfigAndPackage2RepairSub) ||
storage = std::make_shared<IStorageInterface>(new ProxyStorage(bis_storage)); bis_partition_id == FsBisStorageId_Boot1)) {
} else if (Utils::IsHblTid(this->title_id) && /* Allow HBL to write to boot1 (safe firm) + package2. */
((FsBisStorageId_BootConfigAndPackage2NormalMain <= bis_partition_id && bis_partition_id <= FsBisStorageId_BootConfigAndPackage2RepairSub) || /* This is needed to not break compatibility with ChoiDujourNX, which does not check for write access before beginning an update. */
bis_partition_id == FsBisStorageId_Boot1)) { /* TODO: get fixed so that this can be turned off without causing bricks :/ */
/* Allow HBL to write to boot1 (safe firm) + package2. */ out_storage.SetValue(std::make_shared<IStorageInterface>(new ProxyStorage(bis_storage)));
/* This is needed to not break compatibility with ChoiDujourNX, which does not check for write access before beginning an update. */ } else {
/* TODO: get fixed so that this can be turned off without causing bricks :/ */ /* Non-sysmodules should be allowed to read. */
storage = std::make_shared<IStorageInterface>(new ProxyStorage(bis_storage)); out_storage.SetValue(std::make_shared<IStorageInterface>(new ReadOnlyStorageAdapter(new ProxyStorage(bis_storage))));
} else {
/* Non-sysmodules should be allowed to read. */
storage = std::make_shared<IStorageInterface>(new ReadOnlyStorageAdapter(new ProxyStorage(bis_storage)));
}
}
if (out_storage.IsDomain()) {
out_domain_id = bis_storage.s.object_id;
}
} }
} }
return rc; /* Copy domain id. */
if (out_storage.IsDomain()) {
out_storage.ChangeObjectId(bis_storage.s.object_id);
}
return ResultSuccess;
} }
/* Add redirection for RomFS to the SD card. */ /* Add redirection for RomFS to the SD card. */
Result FsMitmService::OpenDataStorageByCurrentProcess(Out<std::shared_ptr<IStorageInterface>> out_storage) { Result FsMitmService::OpenDataStorageByCurrentProcess(Out<std::shared_ptr<IStorageInterface>> out_storage) {
std::shared_ptr<IStorageInterface> storage = nullptr;
u32 out_domain_id = 0;
Result rc = ResultSuccess;
if (!this->should_override_contents) { if (!this->should_override_contents) {
return ResultAtmosphereMitmShouldForwardToSession; return ResultAtmosphereMitmShouldForwardToSession;
} }
bool has_cache = StorageCacheGetEntry(this->title_id, &storage); /* If we don't have anything to modify, there's no sense in maintaining a copy of the metadata tables. */
if (!Utils::HasSdRomfsContent(this->title_id)) {
return ResultAtmosphereMitmShouldForwardToSession;
}
ON_SCOPE_EXIT { /* Try to get from the cache. */
if (R_SUCCEEDED(rc)) { {
if (!has_cache) { std::shared_ptr<IStorageInterface> cached_storage = nullptr;
StorageCacheSetEntry(this->title_id, &storage); bool has_cache = StorageCacheGetEntry(this->title_id, &cached_storage);
}
out_storage.SetValue(std::move(storage)); if (has_cache) {
if (out_storage.IsDomain()) { if (out_storage.IsDomain()) {
out_storage.ChangeObjectId(out_domain_id); /* TODO: Don't leak object id? */
} FsStorage s = {0};
} R_TRY(fsOpenDataStorageByCurrentProcessFwd(this->forward_service.get(), &s));
}; out_storage.ChangeObjectId(s.s.object_id);
if (has_cache) {
if (out_storage.IsDomain()) {
FsStorage s = {0};
rc = fsOpenDataStorageByCurrentProcessFwd(this->forward_service.get(), &s);
if (R_SUCCEEDED(rc)) {
out_domain_id = s.s.object_id;
}
} else {
rc = ResultSuccess;
}
if (R_FAILED(rc)) {
storage.reset();
}
} else {
FsStorage data_storage;
FsFile data_file;
rc = fsOpenDataStorageByCurrentProcessFwd(this->forward_service.get(), &data_storage);
Log(armGetTls(), 0x100);
if (R_SUCCEEDED(rc)) {
if (Utils::HasSdRomfsContent(this->title_id)) {
/* TODO: Is there a sensible path that ends in ".romfs" we can use?" */
if (R_SUCCEEDED(Utils::OpenSdFileForAtmosphere(this->title_id, "romfs.bin", FS_OPEN_READ, &data_file))) {
storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<ReadOnlyStorageAdapter>(new ProxyStorage(data_storage)), std::make_shared<ReadOnlyStorageAdapter>(new FileStorage(new ProxyFile(data_file))), this->title_id));
} else {
storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<ReadOnlyStorageAdapter>(new ProxyStorage(data_storage)), nullptr, this->title_id));
}
if (out_storage.IsDomain()) {
out_domain_id = data_storage.s.object_id;
}
} else {
/* If we don't have anything to modify, there's no sense in maintaining a copy of the metadata tables. */
fsStorageClose(&data_storage);
rc = ResultAtmosphereMitmShouldForwardToSession;
} }
out_storage.SetValue(std::move(cached_storage));
return ResultSuccess;
} }
} }
return rc; /* Try to open process romfs. */
FsStorage data_storage;
R_TRY(fsOpenDataStorageByCurrentProcessFwd(this->forward_service.get(), &data_storage));
/* Make new layered romfs, cacheing to storage. */
{
std::shared_ptr<IStorageInterface> storage_to_cache = nullptr;
/* TODO: Is there a sensible path that ends in ".romfs" we can use?" */
FsFile data_file;
if (R_SUCCEEDED(Utils::OpenSdFileForAtmosphere(this->title_id, "romfs.bin", FS_OPEN_READ, &data_file))) {
storage_to_cache = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<ReadOnlyStorageAdapter>(new ProxyStorage(data_storage)), std::make_shared<ReadOnlyStorageAdapter>(new FileStorage(new ProxyFile(data_file))), this->title_id));
} else {
storage_to_cache = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<ReadOnlyStorageAdapter>(new ProxyStorage(data_storage)), nullptr, this->title_id));
}
StorageCacheSetEntry(this->title_id, &storage_to_cache);
out_storage.SetValue(std::move(storage_to_cache));
if (out_storage.IsDomain()) {
out_storage.ChangeObjectId(data_storage.s.object_id);
}
}
return ResultSuccess;
} }
/* Add redirection for System Data Archives to the SD card. */ /* Add redirection for System Data Archives to the SD card. */
Result FsMitmService::OpenDataStorageByDataId(Out<std::shared_ptr<IStorageInterface>> out_storage, u64 data_id, u8 sid) { Result FsMitmService::OpenDataStorageByDataId(Out<std::shared_ptr<IStorageInterface>> out_storage, u64 data_id, u8 sid) {
FsStorageId storage_id = (FsStorageId)sid;
FsStorage data_storage;
FsFile data_file;
if (!this->should_override_contents) { if (!this->should_override_contents) {
return ResultAtmosphereMitmShouldForwardToSession; return ResultAtmosphereMitmShouldForwardToSession;
} }
std::shared_ptr<IStorageInterface> storage = nullptr; /* If we don't have anything to modify, there's no sense in maintaining a copy of the metadata tables. */
u32 out_domain_id = 0; if (!Utils::HasSdRomfsContent(data_id)) {
Result rc = ResultSuccess; return ResultAtmosphereMitmShouldForwardToSession;
}
bool has_cache = StorageCacheGetEntry(data_id, &storage); FsStorageId storage_id = static_cast<FsStorageId>(sid);
ON_SCOPE_EXIT { /* Try to get from the cache. */
if (R_SUCCEEDED(rc)) { {
if (!has_cache) { std::shared_ptr<IStorageInterface> cached_storage = nullptr;
StorageCacheSetEntry(data_id, &storage); bool has_cache = StorageCacheGetEntry(data_id, &cached_storage);
}
out_storage.SetValue(std::move(storage)); if (has_cache) {
if (out_storage.IsDomain()) { if (out_storage.IsDomain()) {
out_storage.ChangeObjectId(out_domain_id); /* TODO: Don't leak object id? */
} FsStorage s = {0};
} R_TRY(fsOpenDataStorageByDataIdFwd(this->forward_service.get(), storage_id, data_id, &s));
}; out_storage.ChangeObjectId(s.s.object_id);
if (has_cache) {
if (out_storage.IsDomain()) {
FsStorage s = {0};
rc = fsOpenDataStorageByDataIdFwd(this->forward_service.get(), storage_id, data_id, &s);
if (R_SUCCEEDED(rc)) {
out_domain_id = s.s.object_id;
}
} else {
rc = ResultSuccess;
}
if (R_FAILED(rc)) {
storage.reset();
}
} else {
rc = fsOpenDataStorageByDataIdFwd(this->forward_service.get(), storage_id, data_id, &data_storage);
if (R_SUCCEEDED(rc)) {
if (Utils::HasSdRomfsContent(data_id)) {
/* TODO: Is there a sensible path that ends in ".romfs" we can use?" */
if (R_SUCCEEDED(Utils::OpenSdFileForAtmosphere(data_id, "romfs.bin", FS_OPEN_READ, &data_file))) {
storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<ReadOnlyStorageAdapter>(new ProxyStorage(data_storage)), std::make_shared<ReadOnlyStorageAdapter>(new FileStorage(new ProxyFile(data_file))), data_id));
} else {
storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<ReadOnlyStorageAdapter>(new ProxyStorage(data_storage)), nullptr, data_id));
}
if (out_storage.IsDomain()) {
out_domain_id = data_storage.s.object_id;
}
} else {
/* If we don't have anything to modify, there's no sense in maintaining a copy of the metadata tables. */
fsStorageClose(&data_storage);
rc = ResultAtmosphereMitmShouldForwardToSession;
} }
out_storage.SetValue(std::move(cached_storage));
return ResultSuccess;
} }
} }
return rc; /* Try to open data storage. */
FsStorage data_storage;
R_TRY(fsOpenDataStorageByDataIdFwd(this->forward_service.get(), storage_id, data_id, &data_storage));
/* Make new layered romfs, cacheing to storage. */
{
std::shared_ptr<IStorageInterface> storage_to_cache = nullptr;
/* TODO: Is there a sensible path that ends in ".romfs" we can use?" */
FsFile data_file;
if (R_SUCCEEDED(Utils::OpenSdFileForAtmosphere(data_id, "romfs.bin", FS_OPEN_READ, &data_file))) {
storage_to_cache = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<ReadOnlyStorageAdapter>(new ProxyStorage(data_storage)), std::make_shared<ReadOnlyStorageAdapter>(new FileStorage(new ProxyFile(data_file))), data_id));
} else {
storage_to_cache = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<ReadOnlyStorageAdapter>(new ProxyStorage(data_storage)), nullptr, data_id));
}
StorageCacheSetEntry(data_id, &storage_to_cache);
out_storage.SetValue(std::move(storage_to_cache));
if (out_storage.IsDomain()) {
out_storage.ChangeObjectId(data_storage.s.object_id);
}
}
return ResultSuccess;
} }

View File

@@ -21,24 +21,23 @@
#include "fs_ifilesystem.hpp" #include "fs_ifilesystem.hpp"
#include "../utils.hpp" #include "../utils.hpp"
enum FspSrvCmd : u32 {
FspSrvCmd_OpenFileSystemDeprecated = 0,
FspSrvCmd_SetCurrentProcess = 1,
FspSrvCmd_OpenFileSystemWithPatch = 7,
FspSrvCmd_OpenFileSystemWithId = 8,
FspSrvCmd_OpenSdCardFileSystem = 18,
FspSrvCmd_OpenSaveDataFileSystem = 51,
FspSrvCmd_OpenBisStorage = 12,
FspSrvCmd_OpenDataStorageByCurrentProcess = 200,
FspSrvCmd_OpenDataStorageByDataId = 202,
};
class FsMitmService : public IMitmServiceObject { class FsMitmService : public IMitmServiceObject {
private:
enum class CommandId {
OpenFileSystemDeprecated = 0,
SetCurrentProcess = 1,
OpenFileSystemWithPatch = 7,
OpenFileSystemWithId = 8,
OpenSdCardFileSystem = 18,
OpenSaveDataFileSystem = 51,
OpenBisStorage = 12,
OpenDataStorageByCurrentProcess = 200,
OpenDataStorageByDataId = 202,
};
private: private:
static constexpr const char *AtmosphereHblWebContentDir = "/atmosphere/hbl_html"; static constexpr const char *AtmosphereHblWebContentDir = "/atmosphere/hbl_html";
private: private:
@@ -84,13 +83,13 @@ class FsMitmService : public IMitmServiceObject {
Result OpenDataStorageByDataId(Out<std::shared_ptr<IStorageInterface>> out, u64 data_id, u8 storage_id); Result OpenDataStorageByDataId(Out<std::shared_ptr<IStorageInterface>> out, u64 data_id, u8 storage_id);
public: public:
DEFINE_SERVICE_DISPATCH_TABLE { DEFINE_SERVICE_DISPATCH_TABLE {
/* TODO MakeServiceCommandMeta<FspSrvCmd_OpenFileSystemDeprecated, &FsMitmService::OpenFileSystemDeprecated>(), */ /* TODO MAKE_SERVICE_COMMAND_META(FsMitmService, OpenFileSystemDeprecated), */
MakeServiceCommandMeta<FspSrvCmd_OpenFileSystemWithPatch, &FsMitmService::OpenFileSystemWithPatch, FirmwareVersion_200>(), MAKE_SERVICE_COMMAND_META(FsMitmService, OpenFileSystemWithPatch, FirmwareVersion_200),
MakeServiceCommandMeta<FspSrvCmd_OpenFileSystemWithId, &FsMitmService::OpenFileSystemWithId, FirmwareVersion_200>(), MAKE_SERVICE_COMMAND_META(FsMitmService, OpenFileSystemWithId, FirmwareVersion_200),
MakeServiceCommandMeta<FspSrvCmd_OpenSdCardFileSystem, &FsMitmService::OpenSdCardFileSystem>(), MAKE_SERVICE_COMMAND_META(FsMitmService, OpenSdCardFileSystem),
MakeServiceCommandMeta<FspSrvCmd_OpenSaveDataFileSystem, &FsMitmService::OpenSaveDataFileSystem>(), MAKE_SERVICE_COMMAND_META(FsMitmService, OpenSaveDataFileSystem),
MakeServiceCommandMeta<FspSrvCmd_OpenBisStorage, &FsMitmService::OpenBisStorage>(), MAKE_SERVICE_COMMAND_META(FsMitmService, OpenBisStorage),
MakeServiceCommandMeta<FspSrvCmd_OpenDataStorageByCurrentProcess, &FsMitmService::OpenDataStorageByCurrentProcess>(), MAKE_SERVICE_COMMAND_META(FsMitmService, OpenDataStorageByCurrentProcess),
MakeServiceCommandMeta<FspSrvCmd_OpenDataStorageByDataId, &FsMitmService::OpenDataStorageByDataId>(), MAKE_SERVICE_COMMAND_META(FsMitmService, OpenDataStorageByDataId),
}; };
}; };

View File

@@ -29,10 +29,13 @@ Result NsAmMitmService::GetApplicationContentPath(OutBuffer<u8> out_path, u64 ap
} }
Result NsAmMitmService::ResolveApplicationContentPath(u64 title_id, u8 storage_type) { Result NsAmMitmService::ResolveApplicationContentPath(u64 title_id, u8 storage_type) {
Result rc = nsamResolveApplicationContentPathFwd(this->forward_service.get(), title_id, static_cast<FsStorageId>(storage_type));
/* Always succeed for web applet asking about HBL. */ /* Always succeed for web applet asking about HBL. */
return (Utils::IsWebAppletTid(this->title_id) && Utils::IsHblTid(title_id)) ? 0 : rc; if (Utils::IsWebAppletTid(this->title_id) && Utils::IsHblTid(title_id)) {
nsamResolveApplicationContentPathFwd(this->forward_service.get(), title_id, static_cast<FsStorageId>(storage_type));
return ResultSuccess;
}
return nsamResolveApplicationContentPathFwd(this->forward_service.get(), title_id, static_cast<FsStorageId>(storage_type));
} }
Result NsAmMitmService::GetRunningApplicationProgramId(Out<u64> out_tid, u64 app_id) { Result NsAmMitmService::GetRunningApplicationProgramId(Out<u64> out_tid, u64 app_id) {

View File

@@ -20,9 +20,13 @@
#include "../utils.hpp" #include "../utils.hpp"
#include "nsmitm_service_common.hpp"
class NsAmMitmService : public IMitmServiceObject { class NsAmMitmService : public IMitmServiceObject {
private:
enum class CommandId {
GetApplicationContentPath = 21,
ResolveApplicationContentPath = 23,
GetRunningApplicationProgramId = 92,
};
public: public:
NsAmMitmService(std::shared_ptr<Service> s, u64 pid) : IMitmServiceObject(s, pid) { NsAmMitmService(std::shared_ptr<Service> s, u64 pid) : IMitmServiceObject(s, pid) {
/* ... */ /* ... */
@@ -44,8 +48,8 @@ class NsAmMitmService : public IMitmServiceObject {
Result GetRunningApplicationProgramId(Out<u64> out_tid, u64 app_id); Result GetRunningApplicationProgramId(Out<u64> out_tid, u64 app_id);
public: public:
DEFINE_SERVICE_DISPATCH_TABLE { DEFINE_SERVICE_DISPATCH_TABLE {
MakeServiceCommandMeta<NsSrvCmd_GetApplicationContentPath, &NsAmMitmService::GetApplicationContentPath>(), MAKE_SERVICE_COMMAND_META(NsAmMitmService, GetApplicationContentPath),
MakeServiceCommandMeta<NsSrvCmd_ResolveApplicationContentPath, &NsAmMitmService::ResolveApplicationContentPath>(), MAKE_SERVICE_COMMAND_META(NsAmMitmService, ResolveApplicationContentPath),
MakeServiceCommandMeta<NsSrvCmd_GetRunningApplicationProgramId, &NsAmMitmService::GetRunningApplicationProgramId, FirmwareVersion_600>(), MAKE_SERVICE_COMMAND_META(NsAmMitmService, GetRunningApplicationProgramId, FirmwareVersion_600),
}; };
}; };

View File

@@ -36,26 +36,21 @@ void NsMitmMain(void *arg) {
/* Ensure we can talk to NS. */ /* Ensure we can talk to NS. */
DoWithSmSession([&]() { DoWithSmSession([&]() {
if (R_FAILED(nsInitialize())) { R_ASSERT(nsInitialize());
std::abort();
}
nsExit();
}); });
nsExit();
/* Create server manager */ /* Create server manager */
auto server_manager = new WaitableManager(1); static auto s_server_manager = WaitableManager(1);
/* Create ns mitm. */ /* Create ns mitm. */
if (GetRuntimeFirmwareVersion() < FirmwareVersion_300) { if (GetRuntimeFirmwareVersion() < FirmwareVersion_300) {
AddMitmServerToManager<NsAmMitmService>(server_manager, "ns:am", 5); AddMitmServerToManager<NsAmMitmService>(&s_server_manager, "ns:am", 5);
} else { } else {
AddMitmServerToManager<NsWebMitmService>(server_manager, "ns:web", 5); AddMitmServerToManager<NsWebMitmService>(&s_server_manager, "ns:web", 5);
} }
/* Loop forever, servicing our services. */ /* Loop forever, servicing our services. */
server_manager->Process(); s_server_manager.Process();
delete server_manager;
} }

View File

@@ -24,30 +24,17 @@ void NsWebMitmService::PostProcess(IMitmServiceObject *obj, IpcResponseContext *
} }
Result NsWebMitmService::GetDocumentInterface(Out<std::shared_ptr<NsDocumentService>> out_intf) { Result NsWebMitmService::GetDocumentInterface(Out<std::shared_ptr<NsDocumentService>> out_intf) {
std::shared_ptr<NsDocumentService> intf = nullptr;
u32 out_domain_id = 0;
Result rc = ResultSuccess;
ON_SCOPE_EXIT {
if (R_SUCCEEDED(rc)) {
out_intf.SetValue(std::move(intf));
if (out_intf.IsDomain()) {
out_intf.ChangeObjectId(out_domain_id);
}
}
};
/* Open a document interface. */ /* Open a document interface. */
NsDocumentInterface doc; NsDocumentInterface doc;
rc = nsGetDocumentInterfaceFwd(this->forward_service.get(), &doc); R_TRY(nsGetDocumentInterfaceFwd(this->forward_service.get(), &doc));
if (R_SUCCEEDED(rc)) {
intf = std::make_shared<NsDocumentService>(this->title_id, doc); /* Set output interface. */
if (out_intf.IsDomain()) { out_intf.SetValue(std::move(std::make_shared<NsDocumentService>(this->title_id, doc)));
out_domain_id = doc.s.object_id; if (out_intf.IsDomain()) {
} out_intf.ChangeObjectId(doc.s.object_id);
} }
return rc; return ResultSuccess;
} }
Result NsDocumentService::GetApplicationContentPath(OutBuffer<u8> out_path, u64 app_id, u8 storage_type) { Result NsDocumentService::GetApplicationContentPath(OutBuffer<u8> out_path, u64 app_id, u8 storage_type) {
@@ -55,10 +42,13 @@ Result NsDocumentService::GetApplicationContentPath(OutBuffer<u8> out_path, u64
} }
Result NsDocumentService::ResolveApplicationContentPath(u64 title_id, u8 storage_type) { Result NsDocumentService::ResolveApplicationContentPath(u64 title_id, u8 storage_type) {
Result rc = nswebResolveApplicationContentPath(this->srv.get(), title_id, static_cast<FsStorageId>(storage_type));
/* Always succeed for web applet asking about HBL. */ /* Always succeed for web applet asking about HBL. */
return (Utils::IsWebAppletTid(this->title_id) && Utils::IsHblTid(title_id)) ? 0 : rc; if (Utils::IsWebAppletTid(this->title_id) && Utils::IsHblTid(title_id)) {
nswebResolveApplicationContentPath(this->srv.get(), title_id, static_cast<FsStorageId>(storage_type));
return ResultSuccess;
}
return nswebResolveApplicationContentPath(this->srv.get(), title_id, static_cast<FsStorageId>(storage_type));
} }
Result NsDocumentService::GetRunningApplicationProgramId(Out<u64> out_tid, u64 app_id) { Result NsDocumentService::GetRunningApplicationProgramId(Out<u64> out_tid, u64 app_id) {

View File

@@ -20,10 +20,15 @@
#include "../utils.hpp" #include "../utils.hpp"
#include "nsmitm_service_common.hpp"
#include "ns_shim.h" #include "ns_shim.h"
class NsDocumentService : public IServiceObject { class NsDocumentService : public IServiceObject {
private:
enum class CommandId {
GetApplicationContentPath = 21,
ResolveApplicationContentPath = 23,
GetRunningApplicationProgramId = 92,
};
private: private:
u64 title_id; u64 title_id;
std::unique_ptr<NsDocumentInterface> srv; std::unique_ptr<NsDocumentInterface> srv;
@@ -50,13 +55,17 @@ class NsDocumentService : public IServiceObject {
Result GetRunningApplicationProgramId(Out<u64> out_tid, u64 app_id); Result GetRunningApplicationProgramId(Out<u64> out_tid, u64 app_id);
public: public:
DEFINE_SERVICE_DISPATCH_TABLE { DEFINE_SERVICE_DISPATCH_TABLE {
MakeServiceCommandMeta<NsSrvCmd_GetApplicationContentPath, &NsDocumentService::GetApplicationContentPath>(), MAKE_SERVICE_COMMAND_META(NsDocumentService, GetApplicationContentPath),
MakeServiceCommandMeta<NsSrvCmd_ResolveApplicationContentPath, &NsDocumentService::ResolveApplicationContentPath>(), MAKE_SERVICE_COMMAND_META(NsDocumentService, ResolveApplicationContentPath),
MakeServiceCommandMeta<NsSrvCmd_GetRunningApplicationProgramId, &NsDocumentService::GetRunningApplicationProgramId, FirmwareVersion_600>(), MAKE_SERVICE_COMMAND_META(NsDocumentService, GetRunningApplicationProgramId, FirmwareVersion_600),
}; };
}; };
class NsWebMitmService : public IMitmServiceObject { class NsWebMitmService : public IMitmServiceObject {
private:
enum class CommandId {
GetDocumentInterface = 7999,
};
public: public:
NsWebMitmService(std::shared_ptr<Service> s, u64 pid) : IMitmServiceObject(s, pid) { NsWebMitmService(std::shared_ptr<Service> s, u64 pid) : IMitmServiceObject(s, pid) {
/* ... */ /* ... */
@@ -76,6 +85,6 @@ class NsWebMitmService : public IMitmServiceObject {
Result GetDocumentInterface(Out<std::shared_ptr<NsDocumentService>> out_intf); Result GetDocumentInterface(Out<std::shared_ptr<NsDocumentService>> out_intf);
public: public:
DEFINE_SERVICE_DISPATCH_TABLE { DEFINE_SERVICE_DISPATCH_TABLE {
MakeServiceCommandMeta<NsGetterCmd_GetDocumentInterface, &NsWebMitmService::GetDocumentInterface, FirmwareVersion_300>(), MAKE_SERVICE_COMMAND_META(NsWebMitmService, GetDocumentInterface, FirmwareVersion_300),
}; };
}; };

View File

@@ -63,7 +63,7 @@ bool SetMitmService::IsValidRegionCode(u32 region_code) {
return region_code < RegionCode_Max; return region_code < RegionCode_Max;
} }
void SetMitmService::EnsureLocale() { Result SetMitmService::EnsureLocale() {
std::scoped_lock<HosMutex> lk(this->lock); std::scoped_lock<HosMutex> lk(this->lock);
if (!this->got_locale) { if (!this->got_locale) {
@@ -71,19 +71,16 @@ void SetMitmService::EnsureLocale() {
if (this->title_id == TitleId_Ns) { if (this->title_id == TitleId_Ns) {
u64 app_pid = 0; u64 app_pid = 0;
u64 app_tid = 0; u64 app_tid = 0;
Result rc; R_TRY(pmdmntGetApplicationPid(&app_pid));
if (R_FAILED((rc = pmdmntGetApplicationPid(&app_pid)))) { R_TRY(pminfoGetTitleId(&app_tid, app_pid));
return;
}
if (R_FAILED((rc = pminfoGetTitleId(&app_tid, app_pid)))) {
return;
}
this->locale = Utils::GetTitleOverrideLocale(app_tid); this->locale = Utils::GetTitleOverrideLocale(app_tid);
} else { } else {
this->locale = Utils::GetTitleOverrideLocale(this->title_id); this->locale = Utils::GetTitleOverrideLocale(this->title_id);
this->got_locale = true; this->got_locale = true;
} }
} }
return ResultSuccess;
} }
Result SetMitmService::GetLanguageCode(Out<u64> out_lang_code) { Result SetMitmService::GetLanguageCode(Out<u64> out_lang_code) {

View File

@@ -20,16 +20,16 @@
#include "../utils.hpp" #include "../utils.hpp"
enum SetCmd : u32 {
SetCmd_GetLanguageCode = 0,
SetCmd_GetRegionCode = 4,
/* Commands for which set:sys *must* act as a passthrough. */
/* TODO: Solve the relevant IPC detection problem. */
SetCmd_GetAvailableLanguageCodes = 1,
};
class SetMitmService : public IMitmServiceObject { class SetMitmService : public IMitmServiceObject {
private:
enum class CommandId {
GetLanguageCode = 0,
GetRegionCode = 4,
/* Commands for which set:sys *must* act as a passthrough. */
/* TODO: Solve the relevant IPC detection problem. */
GetAvailableLanguageCodes = 1,
};
private: private:
HosMutex lock; HosMutex lock;
OverrideLocale locale; OverrideLocale locale;
@@ -50,7 +50,7 @@ class SetMitmService : public IMitmServiceObject {
static bool IsValidLanguageCode(u64 lang_code); static bool IsValidLanguageCode(u64 lang_code);
static bool IsValidRegionCode(u32 region_code); static bool IsValidRegionCode(u32 region_code);
void EnsureLocale(); Result EnsureLocale();
protected: protected:
/* Overridden commands. */ /* Overridden commands. */
Result GetLanguageCode(Out<u64> out_lang_code); Result GetLanguageCode(Out<u64> out_lang_code);
@@ -60,9 +60,9 @@ class SetMitmService : public IMitmServiceObject {
Result GetAvailableLanguageCodes(OutPointerWithClientSize<u64> out_language_codes, Out<s32> out_count); Result GetAvailableLanguageCodes(OutPointerWithClientSize<u64> out_language_codes, Out<s32> out_count);
public: public:
DEFINE_SERVICE_DISPATCH_TABLE { DEFINE_SERVICE_DISPATCH_TABLE {
MakeServiceCommandMeta<SetCmd_GetLanguageCode, &SetMitmService::GetLanguageCode>(), MAKE_SERVICE_COMMAND_META(SetMitmService, GetLanguageCode),
MakeServiceCommandMeta<SetCmd_GetRegionCode, &SetMitmService::GetRegionCode>(), MAKE_SERVICE_COMMAND_META(SetMitmService, GetRegionCode),
MakeServiceCommandMeta<SetCmd_GetAvailableLanguageCodes, &SetMitmService::GetAvailableLanguageCodes>(), MAKE_SERVICE_COMMAND_META(SetMitmService, GetAvailableLanguageCodes),
}; };
}; };

View File

@@ -48,18 +48,15 @@ void SetMitmMain(void *arg) {
VersionManager::Initialize(); VersionManager::Initialize();
/* Create server manager */ /* Create server manager */
auto server_manager = new SetMitmManager(4); static auto s_server_manager = SetMitmManager(4);
/* Create set:sys mitm. */ /* Create set:sys mitm. */
AddMitmServerToManager<SetSysMitmService>(server_manager, "set:sys", 60); AddMitmServerToManager<SetSysMitmService>(&s_server_manager, "set:sys", 60);
/* Create set mitm. */ /* Create set mitm. */
AddMitmServerToManager<SetMitmService>(server_manager, "set", 60); AddMitmServerToManager<SetMitmService>(&s_server_manager, "set", 60);
/* Loop forever, servicing our services. */ /* Loop forever, servicing our services. */
server_manager->Process(); s_server_manager.Process();
delete server_manager;
} }

View File

@@ -32,7 +32,8 @@ void VersionManager::Initialize() {
} }
/* Mount firmware version data archive. */ /* Mount firmware version data archive. */
if (R_SUCCEEDED(romfsMountFromDataArchive(TitleId_ArchiveSystemVersion, FsStorageId_NandSystem, "sysver"))) { R_ASSERT(romfsMountFromDataArchive(TitleId_ArchiveSystemVersion, FsStorageId_NandSystem, "sysver"));
{
ON_SCOPE_EXIT { romfsUnmount("sysver"); }; ON_SCOPE_EXIT { romfsUnmount("sysver"); };
SetSysFirmwareVersion fw_ver; SetSysFirmwareVersion fw_ver;
@@ -52,9 +53,6 @@ void VersionManager::Initialize() {
g_fw_version = fw_ver; g_fw_version = fw_ver;
g_ams_fw_version = fw_ver; g_ams_fw_version = fw_ver;
} else {
/* Failure to open data archive is an abort. */
std::abort();
} }
/* Modify the output firmware version. */ /* Modify the output firmware version. */

View File

@@ -26,15 +26,13 @@ void SetSysMitmService::PostProcess(IMitmServiceObject *obj, IpcResponseContext
} }
Result SetSysMitmService::GetFirmwareVersion(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out) { Result SetSysMitmService::GetFirmwareVersion(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out) {
Result rc = VersionManager::GetFirmwareVersion(this->title_id, out.pointer); /* Get firmware version from manager. */
R_TRY(VersionManager::GetFirmwareVersion(this->title_id, out.pointer));
/* GetFirmwareVersion sanitizes these fields. */ /* GetFirmwareVersion sanitizes these fields. */
if (R_SUCCEEDED(rc)) { out.pointer->revision_major = 0;
out.pointer->revision_major = 0; out.pointer->revision_minor = 0;
out.pointer->revision_minor = 0; return ResultSuccess;
}
return rc;
} }
Result SetSysMitmService::GetFirmwareVersion2(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out) { Result SetSysMitmService::GetFirmwareVersion2(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out) {
@@ -45,15 +43,9 @@ Result SetSysMitmService::GetSettingsItemValueSize(Out<u64> out_size, InPointer<
char name[SET_MAX_NAME_SIZE] = {0}; char name[SET_MAX_NAME_SIZE] = {0};
char key[SET_MAX_NAME_SIZE] = {0}; char key[SET_MAX_NAME_SIZE] = {0};
Result rc = SettingsItemManager::ValidateName(in_name.pointer); /* Validate name and key. */
if (R_FAILED(rc)) { R_TRY(SettingsItemManager::ValidateName(in_name.pointer));
return rc; R_TRY(SettingsItemManager::ValidateKey(in_key.pointer));
}
rc = SettingsItemManager::ValidateKey(in_key.pointer);
if (R_FAILED(rc)) {
return rc;
}
if (in_name.num_elements < SET_MAX_NAME_SIZE) { if (in_name.num_elements < SET_MAX_NAME_SIZE) {
strncpy(name, in_name.pointer, in_name.num_elements); strncpy(name, in_name.pointer, in_name.num_elements);
@@ -67,27 +59,21 @@ Result SetSysMitmService::GetSettingsItemValueSize(Out<u64> out_size, InPointer<
strncpy(key, in_key.pointer, SET_MAX_NAME_SIZE-1); strncpy(key, in_key.pointer, SET_MAX_NAME_SIZE-1);
} }
rc = SettingsItemManager::GetValueSize(name, key, out_size.GetPointer()); /* Try to get override setting, fall back to real setting. */
if (R_FAILED(rc)) { if (R_FAILED(SettingsItemManager::GetValueSize(name, key, out_size.GetPointer()))) {
rc = setsysGetSettingsItemValueSize(name, key, out_size.GetPointer()); R_TRY(setsysGetSettingsItemValueSize(name, key, out_size.GetPointer()));
} }
return rc; return ResultSuccess;
} }
Result SetSysMitmService::GetSettingsItemValue(Out<u64> out_size, OutBuffer<u8> out_value, InPointer<char> in_name, InPointer<char> in_key) { Result SetSysMitmService::GetSettingsItemValue(Out<u64> out_size, OutBuffer<u8> out_value, InPointer<char> in_name, InPointer<char> in_key) {
char name[SET_MAX_NAME_SIZE] = {0}; char name[SET_MAX_NAME_SIZE] = {0};
char key[SET_MAX_NAME_SIZE] = {0}; char key[SET_MAX_NAME_SIZE] = {0};
Result rc = SettingsItemManager::ValidateName(in_name.pointer); /* Validate name and key. */
if (R_FAILED(rc)) { R_TRY(SettingsItemManager::ValidateName(in_name.pointer));
return rc; R_TRY(SettingsItemManager::ValidateKey(in_key.pointer));
}
rc = SettingsItemManager::ValidateKey(in_key.pointer);
if (R_FAILED(rc)) {
return rc;
}
if (out_value.buffer == nullptr) { if (out_value.buffer == nullptr) {
return ResultSettingsItemValueBufferNull; return ResultSettingsItemValueBufferNull;
@@ -105,13 +91,12 @@ Result SetSysMitmService::GetSettingsItemValue(Out<u64> out_size, OutBuffer<u8>
strncpy(key, in_key.pointer, SET_MAX_NAME_SIZE-1); strncpy(key, in_key.pointer, SET_MAX_NAME_SIZE-1);
} }
rc = SettingsItemManager::GetValue(name, key, out_value.buffer, out_value.num_elements, out_size.GetPointer()); /* Try to get override setting, fall back to real setting. */
if (R_FAILED(SettingsItemManager::GetValue(name, key, out_value.buffer, out_value.num_elements, out_size.GetPointer()))) {
if (R_FAILED(rc)) { R_TRY(setsysGetSettingsItemValueFwd(this->forward_service.get(), name, key, out_value.buffer, out_value.num_elements, out_size.GetPointer()));
rc = setsysGetSettingsItemValueFwd(this->forward_service.get(), name, key, out_value.buffer, out_value.num_elements, out_size.GetPointer());
} }
return rc; return ResultSuccess;
} }
Result SetSysMitmService::GetEdid(OutPointerWithServerSize<SetSysEdid, 0x1> out) { Result SetSysMitmService::GetEdid(OutPointerWithServerSize<SetSysEdid, 0x1> out) {

View File

@@ -20,18 +20,18 @@
#include "setsys_shim.h" #include "setsys_shim.h"
enum SetSysCmd : u32 {
SetSysCmd_GetFirmwareVersion = 3,
SetSysCmd_GetFirmwareVersion2 = 4,
SetSysCmd_GetSettingsItemValueSize = 37,
SetSysCmd_GetSettingsItemValue = 38,
/* Commands for which set:sys *must* act as a passthrough. */
/* TODO: Solve the relevant IPC detection problem. */
SetSysCmd_GetEdid = 41,
};
class SetSysMitmService : public IMitmServiceObject { class SetSysMitmService : public IMitmServiceObject {
private:
enum class CommandId {
GetFirmwareVersion = 3,
GetFirmwareVersion2 = 4,
GetSettingsItemValueSize = 37,
GetSettingsItemValue = 38,
/* Commands for which set:sys *must* act as a passthrough. */
/* TODO: Solve the relevant IPC detection problem. */
GetEdid = 41,
};
public: public:
SetSysMitmService(std::shared_ptr<Service> s, u64 pid) : IMitmServiceObject(s, pid) { SetSysMitmService(std::shared_ptr<Service> s, u64 pid) : IMitmServiceObject(s, pid) {
/* ... */ /* ... */
@@ -55,11 +55,11 @@ class SetSysMitmService : public IMitmServiceObject {
Result GetEdid(OutPointerWithServerSize<SetSysEdid, 0x1> out); Result GetEdid(OutPointerWithServerSize<SetSysEdid, 0x1> out);
public: public:
DEFINE_SERVICE_DISPATCH_TABLE { DEFINE_SERVICE_DISPATCH_TABLE {
MakeServiceCommandMeta<SetSysCmd_GetFirmwareVersion, &SetSysMitmService::GetFirmwareVersion>(), MAKE_SERVICE_COMMAND_META(SetSysMitmService, GetFirmwareVersion),
MakeServiceCommandMeta<SetSysCmd_GetFirmwareVersion2, &SetSysMitmService::GetFirmwareVersion2>(), MAKE_SERVICE_COMMAND_META(SetSysMitmService, GetFirmwareVersion2),
MakeServiceCommandMeta<SetSysCmd_GetSettingsItemValueSize, &SetSysMitmService::GetSettingsItemValueSize>(), MAKE_SERVICE_COMMAND_META(SetSysMitmService, GetSettingsItemValueSize),
MakeServiceCommandMeta<SetSysCmd_GetSettingsItemValue, &SetSysMitmService::GetSettingsItemValue>(), MAKE_SERVICE_COMMAND_META(SetSysMitmService, GetSettingsItemValue),
MakeServiceCommandMeta<SetSysCmd_GetEdid, &SetSysMitmService::GetEdid>(), MAKE_SERVICE_COMMAND_META(SetSysMitmService, GetEdid),
}; };
}; };

View File

@@ -38,11 +38,8 @@ static bool g_threw_fatal = false;
static HosThread g_fatal_thread; static HosThread g_fatal_thread;
static void FatalThreadFunc(void *arg) { static void FatalThreadFunc(void *arg) {
Result rc = (Result)((uintptr_t)arg);
svcSleepThread(5000000000ULL); svcSleepThread(5000000000ULL);
fatalSimple(static_cast<Result>(reinterpret_cast<uintptr_t>(arg)));
fatalSimple(rc);
} }
static bool IsCorrectFormat(const char *str, size_t len) { static bool IsCorrectFormat(const char *str, size_t len) {
@@ -225,30 +222,30 @@ static Result ParseValue(const char *name, const char *key, const char *val_tup)
return ResultSuccess; return ResultSuccess;
} }
static int SettingsItemIniHandler(void *user, const char *name, const char *key, const char *value) { static Result ParseSettingsItemValue(const char *name, const char *key, const char *value) {
Result rc = *(reinterpret_cast<Result *>(user)); /* Validate name and key, then parse value. */
ON_SCOPE_EXIT { *(reinterpret_cast<Result *>(user)) = rc; }; R_TRY(SettingsItemManager::ValidateName(name));
R_TRY(SettingsItemManager::ValidateKey(name));
if (R_SUCCEEDED(rc)) { R_TRY(ParseValue(name, key, value));
rc = SettingsItemManager::ValidateName(name); return ResultSuccess;
}
if (R_SUCCEEDED(rc)) {
rc = SettingsItemManager::ValidateKey(name);
}
if (R_SUCCEEDED(rc)) {
rc = ParseValue(name, key, value);
}
return R_SUCCEEDED(rc) ? 1 : 0;
} }
void SettingsItemManager::LoadConfiguration() { static int SettingsItemIniHandler(void *user, const char *name, const char *key, const char *value) {
Result *user_res = reinterpret_cast<Result *>(user);
/* Stop parsing after we fail to parse a value. */
if (R_FAILED(*user_res)) {
return 0;
}
*user_res = ParseSettingsItemValue(name, key, value);
return R_SUCCEEDED(*user_res) ? 1 : 0;
}
static Result LoadConfigurationImpl() {
/* Open file. */ /* Open file. */
FsFile config_file; FsFile config_file;
Result rc = Utils::OpenSdFile("/atmosphere/system_settings.ini", FS_OPEN_READ, &config_file); R_TRY(Utils::OpenSdFile("/atmosphere/system_settings.ini", FS_OPEN_READ, &config_file));
if (R_FAILED(rc)) {
return;
}
ON_SCOPE_EXIT { ON_SCOPE_EXIT {
fsFileClose(&config_file); fsFileClose(&config_file);
}; };
@@ -257,19 +254,21 @@ void SettingsItemManager::LoadConfiguration() {
std::string config_buf(0xFFFF, '\0'); std::string config_buf(0xFFFF, '\0');
/* Read from file. */ /* Read from file. */
if (R_SUCCEEDED(rc)) { size_t actual_size;
size_t actual_size; R_TRY(fsFileRead(&config_file, 0, config_buf.data(), config_buf.size(), FS_READOPTION_NONE, &actual_size));
rc = fsFileRead(&config_file, 0, config_buf.data(), config_buf.size(), FS_READOPTION_NONE, &actual_size);
}
if (R_SUCCEEDED(rc)) { /* Parse. */
ini_parse_string(config_buf.c_str(), SettingsItemIniHandler, &rc); Result parse_res = ResultSuccess;
} ini_parse_string(config_buf.c_str(), SettingsItemIniHandler, &parse_res);
return parse_res;
}
/* Report error if we encountered one. */ void SettingsItemManager::LoadConfiguration() {
if (R_FAILED(rc) && !g_threw_fatal) { const Result load_res = LoadConfigurationImpl();
if (R_FAILED(load_res) && !g_threw_fatal) {
/* Report error if we encountered one. */
g_threw_fatal = true; g_threw_fatal = true;
g_fatal_thread.Initialize(&FatalThreadFunc, reinterpret_cast<void *>(rc), 0x1000, 49); g_fatal_thread.Initialize(&FatalThreadFunc, reinterpret_cast<void *>(load_res), 0x1000, 49);
g_fatal_thread.Start(); g_fatal_thread.Start();
} }
} }

View File

@@ -37,7 +37,7 @@ static std::atomic_bool g_has_hid_session = false;
/* Content override support variables/types */ /* Content override support variables/types */
static OverrideKey g_default_override_key = { static OverrideKey g_default_override_key = {
.key_combination = KEY_R, .key_combination = KEY_L,
.override_by_default = true .override_by_default = true
}; };
@@ -49,11 +49,11 @@ struct HblOverrideConfig {
static HblOverrideConfig g_hbl_override_config = { static HblOverrideConfig g_hbl_override_config = {
.override_key = { .override_key = {
.key_combination = KEY_L, .key_combination = KEY_R,
.override_by_default = true .override_by_default = false
}, },
.title_id = TitleId_AppletPhotoViewer, .title_id = TitleId_AppletPhotoViewer,
.override_any_app = false .override_any_app = true
}; };
/* Static buffer for loader.ini contents at runtime. */ /* Static buffer for loader.ini contents at runtime. */
@@ -85,11 +85,8 @@ void Utils::InitializeThreadFunc(void *args) {
Handle tmp_hnd = 0; Handle tmp_hnd = 0;
static const char * const required_active_services[] = {"pcv", "gpio", "pinmux", "psc:c"}; static const char * const required_active_services[] = {"pcv", "gpio", "pinmux", "psc:c"};
for (unsigned int i = 0; i < sizeof(required_active_services) / sizeof(required_active_services[0]); i++) { for (unsigned int i = 0; i < sizeof(required_active_services) / sizeof(required_active_services[0]); i++) {
if (R_FAILED(smGetServiceOriginal(&tmp_hnd, smEncodeName(required_active_services[i])))) { R_ASSERT(smGetServiceOriginal(&tmp_hnd, smEncodeName(required_active_services[i])));
std::abort(); svcCloseHandle(tmp_hnd);
} else {
svcCloseHandle(tmp_hnd);
}
} }
}); });
@@ -102,9 +99,8 @@ void Utils::InitializeThreadFunc(void *args) {
fsFsCreateDirectory(&g_sd_filesystem, "/atmosphere/automatic_backups"); fsFsCreateDirectory(&g_sd_filesystem, "/atmosphere/automatic_backups");
{ {
FsStorage cal0_storage; FsStorage cal0_storage;
if (R_FAILED(fsOpenBisStorage(&cal0_storage, FsBisStorageId_CalibrationBinary)) || R_FAILED(fsStorageRead(&cal0_storage, 0, g_cal0_storage_backup, ProdinfoSize))) { R_ASSERT(fsOpenBisStorage(&cal0_storage, FsBisStorageId_CalibrationBinary));
std::abort(); R_ASSERT(fsStorageRead(&cal0_storage, 0, g_cal0_storage_backup, ProdinfoSize));
}
fsStorageClose(&cal0_storage); fsStorageClose(&cal0_storage);
char serial_number[0x40] = {0}; char serial_number[0x40] = {0};
@@ -213,9 +209,7 @@ void Utils::InitializeThreadFunc(void *args) {
/* Initialize set:sys. */ /* Initialize set:sys. */
DoWithSmSession([&]() { DoWithSmSession([&]() {
if (R_FAILED(setsysInitialize())) { R_ASSERT(setsysInitialize());
std::abort();
}
}); });
/* Signal SD is initialized. */ /* Signal SD is initialized. */
@@ -360,8 +354,6 @@ Result Utils::SaveSdFileForAtmosphere(u64 title_id, const char *fn, void *data,
return ResultFsSdCardNotPresent; return ResultFsSdCardNotPresent;
} }
Result rc = ResultSuccess;
char path[FS_MAX_PATH]; char path[FS_MAX_PATH];
if (*fn == '/') { if (*fn == '/') {
snprintf(path, sizeof(path), "/atmosphere/titles/%016lx%s", title_id, fn); snprintf(path, sizeof(path), "/atmosphere/titles/%016lx%s", title_id, fn);
@@ -374,26 +366,16 @@ Result Utils::SaveSdFileForAtmosphere(u64 title_id, const char *fn, void *data,
fsFsCreateFile(&g_sd_filesystem, path, size, 0); fsFsCreateFile(&g_sd_filesystem, path, size, 0);
/* Try to open. */ /* Try to open. */
rc = fsFsOpenFile(&g_sd_filesystem, path, FS_OPEN_READ | FS_OPEN_WRITE, &f); R_TRY(fsFsOpenFile(&g_sd_filesystem, path, FS_OPEN_READ | FS_OPEN_WRITE, &f));
if (R_FAILED(rc)) { ON_SCOPE_EXIT { fsFileClose(&f); };
return rc;
}
/* Always close, if we opened. */
ON_SCOPE_EXIT {
fsFileClose(&f);
};
/* Try to make it big enough. */ /* Try to make it big enough. */
rc = fsFileSetSize(&f, size); R_TRY(fsFileSetSize(&f, size));
if (R_FAILED(rc)) {
return rc;
}
/* Try to write the data. */ /* Try to write the data. */
rc = fsFileWrite(&f, 0, data, size, FS_WRITEOPTION_FLUSH); R_TRY(fsFileWrite(&f, 0, data, size, FS_WRITEOPTION_FLUSH));
return rc; return ResultSuccess;
} }
bool Utils::IsHblTid(u64 tid) { bool Utils::IsHblTid(u64 tid) {
@@ -728,13 +710,12 @@ Result Utils::GetSettingsItemValue(const char *name, const char *key, void *out,
Result Utils::GetSettingsItemBooleanValue(const char *name, const char *key, bool *out) { Result Utils::GetSettingsItemBooleanValue(const char *name, const char *key, bool *out) {
u8 val = 0; u8 val = 0;
u64 out_size; u64 out_size;
Result rc = Utils::GetSettingsItemValue(name, key, &val, sizeof(val), &out_size); R_TRY(Utils::GetSettingsItemValue(name, key, &val, sizeof(val), &out_size));
if (R_SUCCEEDED(rc)) {
if (out) { if (out) {
*out = val != 0; *out = val != 0;
}
} }
return rc; return ResultSuccess;
} }
void Utils::RebootToFatalError(AtmosphereFatalErrorContext *ctx) { void Utils::RebootToFatalError(AtmosphereFatalErrorContext *ctx) {

View File

@@ -33,12 +33,12 @@ endef
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR)) TARGET := $(notdir $(CURDIR))
BUILD := build BUILD := build
SOURCES := source source/i2c_driver source/updater SOURCES := source source/i2c source/i2c/driver source/i2c/driver/impl source/gpio source/pinmux
DATA := data DATA := data
INCLUDES := include ../../common/include INCLUDES := include ../../common/include
EXEFS_SRC := exefs_src EXEFS_SRC := exefs_src
DEFINES := -DDISABLE_IPC -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\" DEFINES := -DRESULT_ABORT_ON_ASSERT -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\"
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# options for code generation # options for code generation

View File

@@ -14,361 +14,286 @@
* 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 <switch.h>
#include <stratosphere.hpp>
#include "boot_functions.hpp"
#include "boot_battery_driver.hpp" #include "boot_battery_driver.hpp"
#include "boot_calibration.hpp"
#include "boot_i2c_utils.hpp"
const Max17050Parameters *BatteryDriver::GetBatteryParameters() { namespace sts::boot {
const u32 battery_version = Boot::GetBatteryVersion();
const u32 battery_vendor = Boot::GetBatteryVendor();
if (battery_version == 2) { /* Include configuration into anonymous namespace. */
if (battery_vendor == 'M') { namespace {
return &Max17050Params2M;
#include "boot_battery_parameters.inc"
const Max17050Parameters *GetBatteryParameters() {
const u32 battery_version = GetBatteryVersion();
const u32 battery_vendor = GetBatteryVendor();
if (battery_version == 2) {
if (battery_vendor == 'M') {
return &Max17050Params2M;
} else {
return &Max17050Params2;
}
} else if (battery_version == 1) {
return &Max17050Params1;
} else {
switch (battery_vendor) {
case 'M':
return &Max17050ParamsM;
case 'R':
return &Max17050ParamsR;
case 'A':
default:
return &Max17050ParamsA;
}
}
}
}
Result BatteryDriver::Read(u8 addr, u16 *out) {
return ReadI2cRegister(this->i2c_session, reinterpret_cast<u8 *>(out), sizeof(*out), &addr, sizeof(addr));
}
Result BatteryDriver::Write(u8 addr, u16 val) {
return WriteI2cRegister(this->i2c_session, reinterpret_cast<u8 *>(&val), sizeof(val), &addr, sizeof(addr));
}
Result BatteryDriver::ReadWrite(u8 addr, u16 mask, u16 val) {
u16 cur_val;
R_TRY(this->Read(addr, &cur_val));
const u16 new_val = (cur_val & ~mask) | val;
R_TRY(this->Write(addr, new_val));
return ResultSuccess;
}
bool BatteryDriver::WriteValidate(u8 addr, u16 val) {
/* Nintendo doesn't seem to check errors when doing this? */
/* It's probably okay, since the value does get validated. */
/* That said, we will validate the read to avoid uninit data problems. */
this->Write(addr, val);
svcSleepThread(3'000'000ul);
u16 new_val;
return R_SUCCEEDED(this->Read(addr, &new_val)) && new_val == val;
}
bool BatteryDriver::IsPowerOnReset() {
/* N doesn't check result... */
u16 val = 0;
this->Read(Max17050Status, &val);
return (val & 0x0002) == 0x0002;
}
Result BatteryDriver::LockVfSoc() {
return this->Write(Max17050SocVfAccess, 0x0000);
}
Result BatteryDriver::UnlockVfSoc() {
return this->Write(Max17050SocVfAccess, 0x0080);
}
Result BatteryDriver::LockModelTable() {
R_TRY(this->Write(Max17050ModelAccess0, 0x0000));
R_TRY(this->Write(Max17050ModelAccess1, 0x0000));
return ResultSuccess;
}
Result BatteryDriver::UnlockModelTable() {
R_TRY(this->Write(Max17050ModelAccess0, 0x0059));
R_TRY(this->Write(Max17050ModelAccess1, 0x00C4));
return ResultSuccess;
}
Result BatteryDriver::SetModelTable(const u16 *model_table) {
for (size_t i = 0; i < Max17050ModelChrTblSize; i++) {
R_TRY(this->Write(Max17050ModelChrTblStart + i, model_table[i]));
}
return ResultSuccess;
}
bool BatteryDriver::IsModelTableLocked() {
bool locked = true;
u16 cur_val = 0;
for (size_t i = 0; i < Max17050ModelChrTblSize; i++) {
this->Read(Max17050ModelChrTblStart + i, &cur_val);
locked &= (cur_val == 0);
}
return locked;
}
bool BatteryDriver::IsModelTableSet(const u16 *model_table) {
bool set = true;
u16 cur_val = 0;
for (size_t i = 0; i < Max17050ModelChrTblSize; i++) {
this->Read(Max17050ModelChrTblStart + i, &cur_val);
set &= (cur_val == model_table[i]);
}
return set;
}
Result BatteryDriver::InitializeBatteryParameters() {
const Max17050Parameters *params = GetBatteryParameters();
if (IsPowerOnReset()) {
/* Do initial config. */
R_TRY(this->ReadWrite(Max17050MiscCfg, 0x8000, 0x8000));
svcSleepThread(500'000'000ul);
R_TRY(this->Write(Max17050Config, 0x7210));
R_TRY(this->Write(Max17050FilterCfg, 0x8784));
R_TRY(this->Write(Max17050RelaxCfg, params->relaxcfg));
R_TRY(this->Write(Max17050LearnCfg, 0x2603));
R_TRY(this->Write(Max17050FullSocThr, params->fullsocthr));
R_TRY(this->Write(Max17050IAvgEmpty, params->iavgempty));
/* Unlock model table, write model table. */
do {
R_TRY(this->UnlockModelTable());
R_TRY(this->SetModelTable(params->modeltbl));
} while (!this->IsModelTableSet(params->modeltbl));
/* Lock model table. */
size_t lock_i = 0;
while (true) {
lock_i++;
R_TRY(this->LockModelTable());
if (this->IsModelTableLocked()) {
break;
}
if (lock_i >= 8) {
/* This is regarded as guaranteed success. */
return ResultSuccess;
}
}
/* Write custom parameters. */
while (!this->WriteValidate(Max17050RComp0, params->rcomp0)) { /* ... */ }
while (!this->WriteValidate(Max17050TempCo, params->tempco)) { /* ... */ }
R_TRY(this->Write(Max17050IChgTerm, params->ichgterm));
R_TRY(this->Write(Max17050TGain, params->tgain));
R_TRY(this->Write(Max17050TOff, params->toff));
while (!this->WriteValidate(Max17050VEmpty, params->vempty)) { /* ... */ }
while (!this->WriteValidate(Max17050QResidual00, params->qresidual00)) { /* ... */ }
while (!this->WriteValidate(Max17050QResidual10, params->qresidual10)) { /* ... */ }
while (!this->WriteValidate(Max17050QResidual20, params->qresidual20)) { /* ... */ }
while (!this->WriteValidate(Max17050QResidual30, params->qresidual30)) { /* ... */ }
/* Write full capacity parameters. */
while (!this->WriteValidate(Max17050FullCap, params->fullcap)) { /* ... */ }
R_TRY(this->Write(Max17050DesignCap, params->vffullcap));
while (!this->WriteValidate(Max17050FullCapNom, params->vffullcap)) { /* ... */ }
svcSleepThread(350'000'000ul);
/* Write VFSOC to VFSOC 0. */
u16 vfsoc, qh;
{
R_TRY(this->Read(Max17050SocVf, &vfsoc));
R_TRY(this->UnlockVfSoc());
R_TRY(this->Write(Max17050SocVf0, vfsoc));
R_TRY(this->Read(Max17050Qh, &qh));
R_TRY(this->Write(Max17050Qh0, qh));
R_TRY(this->LockVfSoc());
}
/* Write cycles. */
while (!this->WriteValidate(Max17050Cycles, 0x0060)) { /* ... */ }
/* Load new capacity parameters. */
const u16 remcap = static_cast<u16>((vfsoc * params->vffullcap) / 0x6400);
const u16 repcap = static_cast<u16>(remcap * (params->fullcap / params->vffullcap));
const u16 dqacc = params->vffullcap / 0x10;
while (!this->WriteValidate(Max17050RemCapMix, remcap)) { /* ... */ }
while (!this->WriteValidate(Max17050RemCapRep, repcap)) { /* ... */ }
while (!this->WriteValidate(Max17050DPAcc, 0x0C80)) { /* ... */ }
while (!this->WriteValidate(Max17050DQAcc, dqacc)) { /* ... */ }
while (!this->WriteValidate(Max17050FullCap, params->fullcap)) { /* ... */ }
R_TRY(this->Write(Max17050DesignCap, params->vffullcap));
while (!this->WriteValidate(Max17050FullCapNom, params->vffullcap)) { /* ... */ }
R_TRY(this->Write(Max17050SocRep, vfsoc));
/* Finish initialization. */
{
u16 status;
R_TRY(this->Read(Max17050Status, &status));
while (!this->WriteValidate(Max17050Status, status & 0xFFFD)) { /* ... */ }
}
R_TRY(this->Write(Max17050CGain, 0x7FFF));
}
return ResultSuccess;
}
Result BatteryDriver::IsBatteryRemoved(bool *out) {
/* N doesn't check result, but we will. */
u16 val = 0;
R_TRY(this->Read(Max17050Status, &val));
*out = (val & 0x0008) == 0x0008;
return ResultSuccess;
}
Result BatteryDriver::GetTemperature(double *out) {
u16 val = 0;
R_TRY(this->Read(Max17050Temperature, &val));
*out = static_cast<double>(val) * double(0.00390625);
return ResultSuccess;
}
Result BatteryDriver::GetAverageVCell(u32 *out) {
u16 val = 0;
R_TRY(this->Read(Max17050AverageVCell, &val));
*out = (625 * u32(val >> 3)) / 1000;
return ResultSuccess;
}
Result BatteryDriver::GetSocRep(double *out) {
u16 val = 0;
R_TRY(this->Read(Max17050SocRep, &val));
*out = static_cast<double>(val) * double(0.00390625);
return ResultSuccess;
}
Result BatteryDriver::GetBatteryPercentage(size_t *out) {
double raw_charge;
R_TRY(this->GetSocRep(&raw_charge));
int converted_percentage = (((raw_charge - 3.93359375) * 98.0) / 94.2304688) + 2.0;
if (converted_percentage < 1) {
*out = 1;
} else if (converted_percentage > 100) {
*out = 100;
} else { } else {
return &Max17050Params2; *out = static_cast<size_t>(converted_percentage);
} }
} else if (battery_version == 1) { return ResultSuccess;
return &Max17050Params1;
} else {
switch (battery_vendor) {
case 'M':
return &Max17050ParamsM;
case 'R':
return &Max17050ParamsR;
case 'A':
default:
return &Max17050ParamsA;
}
}
}
Result BatteryDriver::Read(u8 addr, u16 *out) {
return Boot::ReadI2cRegister(this->i2c_session, reinterpret_cast<u8 *>(out), sizeof(*out), &addr, sizeof(addr));
}
Result BatteryDriver::Write(u8 addr, u16 val) {
return Boot::WriteI2cRegister(this->i2c_session, reinterpret_cast<u8 *>(&val), sizeof(val), &addr, sizeof(addr));
}
Result BatteryDriver::ReadWrite(u8 addr, u16 mask, u16 val) {
Result rc;
u16 cur_val;
if (R_FAILED((rc = this->Read(addr, &cur_val)))) {
return rc;
} }
const u16 new_val = (cur_val & ~mask) | val; Result BatteryDriver::SetShutdownTimer() {
if (R_FAILED((rc = this->Write(addr, new_val)))) { return this->Write(Max17050ShdnTimer, 0xE000);
return rc;
}
return ResultSuccess;
}
bool BatteryDriver::WriteValidate(u8 addr, u16 val) {
/* Nintendo doesn't seem to check errors when doing this? */
/* It's probably okay, since the value does get validated. */
/* That said, we will validate the read to avoid uninit data problems. */
this->Write(addr, val);
svcSleepThread(3'000'000ul);
u16 new_val;
return R_SUCCEEDED(this->Read(addr, &new_val)) && new_val == val;
}
bool BatteryDriver::IsPowerOnReset() {
/* N doesn't check result... */
u16 val = 0;
this->Read(Max17050Status, &val);
return (val & 0x0002) == 0x0002;
}
Result BatteryDriver::LockVfSoc() {
return this->Write(Max17050SocVfAccess, 0x0000);
}
Result BatteryDriver::UnlockVfSoc() {
return this->Write(Max17050SocVfAccess, 0x0080);
}
Result BatteryDriver::LockModelTable() {
Result rc;
if (R_FAILED((rc = this->Write(Max17050ModelAccess0, 0x0000)))) {
return rc;
}
if (R_FAILED((rc = this->Write(Max17050ModelAccess1, 0x0000)))) {
return rc;
}
return ResultSuccess;
}
Result BatteryDriver::UnlockModelTable() {
Result rc;
if (R_FAILED((rc = this->Write(Max17050ModelAccess0, 0x0059)))) {
return rc;
}
if (R_FAILED((rc = this->Write(Max17050ModelAccess1, 0x00C4)))) {
return rc;
}
return ResultSuccess;
}
Result BatteryDriver::SetModelTable(const u16 *model_table) {
Result rc;
for (size_t i = 0; i < Max17050ModelChrTblSize; i++) {
if (R_FAILED((rc = this->Write(Max17050ModelChrTblStart + i, model_table[i])))) {
return rc;
}
} }
return ResultSuccess; Result BatteryDriver::GetShutdownEnabled(bool *out) {
} u16 val = 0;
R_TRY(this->Read(Max17050Config, &val));
bool BatteryDriver::IsModelTableLocked() { *out = (val & 0x0040) != 0;
bool locked = true; return ResultSuccess;
u16 cur_val = 0;
for (size_t i = 0; i < Max17050ModelChrTblSize; i++) {
this->Read(Max17050ModelChrTblStart + i, &cur_val);
locked &= (cur_val == 0);
} }
return locked; Result BatteryDriver::SetShutdownEnabled(bool enabled) {
} return this->ReadWrite(Max17050Config, 0x0040, enabled ? 0x0040 : 0x0000);
bool BatteryDriver::IsModelTableSet(const u16 *model_table) {
bool set = true;
u16 cur_val = 0;
for (size_t i = 0; i < Max17050ModelChrTblSize; i++) {
this->Read(Max17050ModelChrTblStart + i, &cur_val);
set &= (cur_val == model_table[i]);
} }
return set;
}
Result BatteryDriver::InitializeBatteryParameters() {
const Max17050Parameters *params = GetBatteryParameters();
Result rc = ResultSuccess;
if (IsPowerOnReset()) {
/* Do initial config. */
if (R_FAILED((rc = this->ReadWrite(Max17050MiscCfg, 0x8000, 0x8000)))) {
return rc;
}
svcSleepThread(500'000'000ul);
if (R_FAILED((rc = this->Write(Max17050Config, 0x7210)))) {
return rc;
}
if (R_FAILED((rc = this->Write(Max17050FilterCfg, 0x8784)))) {
return rc;
}
if (R_FAILED((rc = this->Write(Max17050RelaxCfg, params->relaxcfg)))) {
return rc;
}
if (R_FAILED((rc = this->Write(Max17050LearnCfg, 0x2603)))) {
return rc;
}
if (R_FAILED((rc = this->Write(Max17050FullSocThr, params->fullsocthr)))) {
return rc;
}
if (R_FAILED((rc = this->Write(Max17050IAvgEmpty, params->iavgempty)))) {
return rc;
}
/* Unlock model table, write model table. */
do {
if (R_FAILED((rc = this->UnlockModelTable()))) {
return rc;
}
if (R_FAILED((rc = this->SetModelTable(params->modeltbl)))) {
return rc;
}
} while (!this->IsModelTableSet(params->modeltbl));
/* Lock model table. */
size_t lock_i = 0;
while (true) {
lock_i++;
if (R_FAILED((rc = this->LockModelTable()))) {
return rc;
}
if (this->IsModelTableLocked()) {
break;
}
if (lock_i >= 8) {
/* This is regarded as guaranteed success. */
return ResultSuccess;
}
}
/* Write custom parameters. */
while (!this->WriteValidate(Max17050RComp0, params->rcomp0)) { /* ... */ }
while (!this->WriteValidate(Max17050TempCo, params->tempco)) { /* ... */ }
if (R_FAILED((rc = this->Write(Max17050IChgTerm, params->ichgterm)))) {
return rc;
}
if (R_FAILED((rc = this->Write(Max17050TGain, params->tgain)))) {
return rc;
}
if (R_FAILED((rc = this->Write(Max17050TOff, params->toff)))) {
return rc;
}
while (!this->WriteValidate(Max17050VEmpty, params->vempty)) { /* ... */ }
while (!this->WriteValidate(Max17050QResidual00, params->qresidual00)) { /* ... */ }
while (!this->WriteValidate(Max17050QResidual10, params->qresidual10)) { /* ... */ }
while (!this->WriteValidate(Max17050QResidual20, params->qresidual20)) { /* ... */ }
while (!this->WriteValidate(Max17050QResidual30, params->qresidual30)) { /* ... */ }
/* Write full capacity parameters. */
while (!this->WriteValidate(Max17050FullCap, params->fullcap)) { /* ... */ }
if (R_FAILED((rc = this->Write(Max17050DesignCap, params->vffullcap)))) {
return rc;
}
while (!this->WriteValidate(Max17050FullCapNom, params->vffullcap)) { /* ... */ }
svcSleepThread(350'000'000ul);
/* Write VFSOC to VFSOC 0. */
u16 vfsoc, qh;
{
if (R_FAILED((rc = this->Read(Max17050SocVf, &vfsoc)))) {
return rc;
}
if (R_FAILED((rc = this->UnlockVfSoc()))) {
return rc;
}
if (R_FAILED((rc = this->Write(Max17050SocVf0, vfsoc)))) {
return rc;
}
if (R_FAILED((rc = this->Read(Max17050Qh, &qh)))) {
return rc;
}
if (R_FAILED((rc = this->Write(Max17050Qh0, qh)))) {
return rc;
}
if (R_FAILED((rc = this->LockVfSoc()))) {
return rc;
}
}
/* Write cycles. */
while (!this->WriteValidate(Max17050Cycles, 0x0060)) { /* ... */ }
/* Load new capacity parameters. */
const u16 remcap = static_cast<u16>((vfsoc * params->vffullcap) / 0x6400);
const u16 repcap = static_cast<u16>(remcap * (params->fullcap / params->vffullcap));
const u16 dqacc = params->vffullcap / 0x10;
while (!this->WriteValidate(Max17050RemCapMix, remcap)) { /* ... */ }
while (!this->WriteValidate(Max17050RemCapRep, repcap)) { /* ... */ }
while (!this->WriteValidate(Max17050DPAcc, 0x0C80)) { /* ... */ }
while (!this->WriteValidate(Max17050DQAcc, dqacc)) { /* ... */ }
while (!this->WriteValidate(Max17050FullCap, params->fullcap)) { /* ... */ }
if (R_FAILED((rc = this->Write(Max17050DesignCap, params->vffullcap)))) {
return rc;
}
while (!this->WriteValidate(Max17050FullCapNom, params->vffullcap)) { /* ... */ }
if (R_FAILED((rc = this->Write(Max17050SocRep, vfsoc)))) {
return rc;
}
/* Finish initialization. */
{
u16 status;
if (R_FAILED((rc = this->Read(Max17050Status, &status)))) {
return rc;
}
while (!this->WriteValidate(Max17050Status, status & 0xFFFD)) { /* ... */ }
}
if (R_FAILED((rc = this->Write(Max17050CGain, 0x7FFF)))) {
return rc;
}
}
return ResultSuccess;
}
Result BatteryDriver::IsBatteryRemoved(bool *out) {
/* N doesn't check result, but we will. */
u16 val = 0;
Result rc = this->Read(Max17050Status, &val);
if (R_FAILED(rc)) {
return rc;
}
*out = (val & 0x0008) == 0x0008;
return ResultSuccess;
}
Result BatteryDriver::GetTemperature(double *out) {
u16 val = 0;
Result rc = this->Read(Max17050Temperature, &val);
if (R_FAILED(rc)) {
return rc;
}
*out = static_cast<double>(val) * double(0.00390625);
return ResultSuccess;
}
Result BatteryDriver::GetAverageVCell(u32 *out) {
u16 val = 0;
Result rc = this->Read(Max17050AverageVCell, &val);
if (R_FAILED(rc)) {
return rc;
}
*out = (625 * u32(val >> 3)) / 1000;
return ResultSuccess;
}
Result BatteryDriver::GetSocRep(double *out) {
u16 val = 0;
Result rc = this->Read(Max17050SocRep, &val);
if (R_FAILED(rc)) {
return rc;
}
*out = static_cast<double>(val) * double(0.00390625);
return ResultSuccess;
}
Result BatteryDriver::GetBatteryPercentage(size_t *out) {
double raw_charge;
Result rc = this->GetSocRep(&raw_charge);
if (R_FAILED(rc)) {
return rc;
}
int converted_percentage = (((raw_charge - 3.93359375) * 98.0) / 94.2304688) + 2.0;
if (converted_percentage < 1) {
*out = 1;
} else if (converted_percentage > 100) {
*out = 100;
} else {
*out = static_cast<size_t>(converted_percentage);
}
return ResultSuccess;
}
Result BatteryDriver::SetShutdownTimer() {
return this->Write(Max17050ShdnTimer, 0xE000);
}
Result BatteryDriver::GetShutdownEnabled(bool *out) {
u16 val = 0;
Result rc = this->Read(Max17050Config, &val);
if (R_FAILED(rc)) {
return rc;
}
*out = (val & 0x0040) != 0;
return ResultSuccess;
}
Result BatteryDriver::SetShutdownEnabled(bool enabled) {
return this->ReadWrite(Max17050Config, 0x0040, enabled ? 0x0040 : 0x0000);
} }

View File

@@ -18,47 +18,48 @@
#include <switch.h> #include <switch.h>
#include <stratosphere.hpp> #include <stratosphere.hpp>
#include "i2c_driver/i2c_api.hpp" #include "i2c/driver/i2c_api.hpp"
#include "boot_battery_parameters.hpp"
class BatteryDriver { namespace sts::boot {
private:
I2cSessionImpl i2c_session;
public:
BatteryDriver() {
I2cDriver::Initialize();
I2cDriver::OpenSession(&this->i2c_session, I2cDevice_Max17050);
}
~BatteryDriver() { class BatteryDriver {
I2cDriver::CloseSession(this->i2c_session); private:
I2cDriver::Finalize(); i2c::driver::Session i2c_session;
} public:
private: BatteryDriver() {
static const Max17050Parameters *GetBatteryParameters(); i2c::driver::Initialize();
i2c::driver::OpenSession(&this->i2c_session, I2cDevice_Max17050);
}
Result Read(u8 addr, u16 *out_data); ~BatteryDriver() {
Result Write(u8 addr, u16 val); i2c::driver::CloseSession(this->i2c_session);
Result ReadWrite(u8 addr, u16 mask, u16 val); i2c::driver::Finalize();
bool WriteValidate(u8 addr, u16 val); }
private:
Result Read(u8 addr, u16 *out_data);
Result Write(u8 addr, u16 val);
Result ReadWrite(u8 addr, u16 mask, u16 val);
bool WriteValidate(u8 addr, u16 val);
bool IsPowerOnReset(); bool IsPowerOnReset();
Result LockVfSoc(); Result LockVfSoc();
Result UnlockVfSoc(); Result UnlockVfSoc();
Result LockModelTable(); Result LockModelTable();
Result UnlockModelTable(); Result UnlockModelTable();
bool IsModelTableLocked(); bool IsModelTableLocked();
Result SetModelTable(const u16 *model_table); Result SetModelTable(const u16 *model_table);
bool IsModelTableSet(const u16 *model_table); bool IsModelTableSet(const u16 *model_table);
public: public:
Result InitializeBatteryParameters(); Result InitializeBatteryParameters();
Result IsBatteryRemoved(bool *out); Result IsBatteryRemoved(bool *out);
Result GetTemperature(double *out); Result GetTemperature(double *out);
Result GetAverageVCell(u32 *out); Result GetAverageVCell(u32 *out);
Result GetSocRep(double *out); Result GetSocRep(double *out);
Result GetBatteryPercentage(size_t *out); Result GetBatteryPercentage(size_t *out);
Result SetShutdownTimer(); Result SetShutdownTimer();
Result GetShutdownEnabled(bool *out); Result GetShutdownEnabled(bool *out);
Result SetShutdownEnabled(bool enabled); Result SetShutdownEnabled(bool enabled);
}; };
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More