disable usb and ftp installs

This commit is contained in:
ITotalJustice
2025-07-21 10:17:27 +01:00
parent 97dc39620c
commit 8381446a69
17 changed files with 83 additions and 21 deletions

View File

@@ -8,7 +8,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest] os: [ubuntu-latest]
preset: [MinSizeRel] preset: [Release]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
container: devkitpro/devkita64:latest container: devkitpro/devkita64:latest

View File

@@ -16,19 +16,19 @@
"name": "Release", "name": "Release",
"displayName": "Release", "displayName": "Release",
"inherits":["core"], "inherits":["core"],
"cacheVariables": { "CMAKE_BUILD_TYPE": "Release" } "cacheVariables": {
"CMAKE_BUILD_TYPE": "MinSizeRel",
"ENABLE_NETWORK_INSTALL": false
}
}, },
{ {
"name": "RelWithDebInfo", "name": "ReleaseWithInstall",
"displayName": "RelWithDebInfo", "displayName": "ReleaseWithInstall",
"inherits":["core"], "inherits":["core"],
"cacheVariables": { "CMAKE_BUILD_TYPE":"RelWithDebInfo" } "cacheVariables": {
}, "CMAKE_BUILD_TYPE": "MinSizeRel",
{ "ENABLE_NETWORK_INSTALL": true
"name": "MinSizeRel", }
"displayName": "MinSizeRel",
"inherits":["core"],
"cacheVariables": { "CMAKE_BUILD_TYPE":"MinSizeRel" }
}, },
{ {
"name": "Debug", "name": "Debug",
@@ -44,13 +44,8 @@
"jobs": 16 "jobs": 16
}, },
{ {
"name": "RelWithDebInfo", "name": "ReleaseWithInstall",
"configurePreset": "RelWithDebInfo", "configurePreset": "ReleaseWithInstall",
"jobs": 16
},
{
"name": "MinSizeRel",
"configurePreset": "MinSizeRel",
"jobs": 16 "jobs": 16
}, },
{ {

View File

@@ -8,13 +8,13 @@ build_preset() {
cmake --build --preset $1 cmake --build --preset $1
} }
build_preset MinSizeRel build_preset Release
rm -rf out rm -rf out
# --- SWITCH --- # # --- SWITCH --- #
mkdir -p out/switch/sphaira/ mkdir -p out/switch/sphaira/
cp -r build/MinSizeRel/*.nro out/switch/sphaira/sphaira.nro cp -r build/Release/*.nro out/switch/sphaira/sphaira.nro
pushd out pushd out
zip -r9 sphaira.zip switch zip -r9 sphaira.zip switch
popd popd

View File

@@ -111,6 +111,7 @@ target_compile_definitions(sphaira PRIVATE
-DAPP_VERSION="${sphaira_VERSION}" -DAPP_VERSION="${sphaira_VERSION}"
-DAPP_VERSION_HASH="${sphaira_VERSION_HASH}" -DAPP_VERSION_HASH="${sphaira_VERSION_HASH}"
-DCURL_NO_OLDIES=1 -DCURL_NO_OLDIES=1
-DENABLE_NETWORK_INSTALL=$<BOOL:${ENABLE_NETWORK_INSTALL}>
) )
target_compile_options(sphaira PRIVATE target_compile_options(sphaira PRIVATE

View File

@@ -30,10 +30,13 @@ struct DumpLocationEntry {
constexpr DumpLocationEntry DUMP_LOCATIONS[]{ constexpr DumpLocationEntry DUMP_LOCATIONS[]{
{ DumpLocationType_SdCard, "microSD card (/dumps/)" }, { DumpLocationType_SdCard, "microSD card (/dumps/)" },
#if ENABLE_NETWORK_INSTALL
{ DumpLocationType_UsbS2S, "USB transfer (Switch 2 Switch)" }, { DumpLocationType_UsbS2S, "USB transfer (Switch 2 Switch)" },
#endif
{ DumpLocationType_DevNull, "/dev/null (Speed Test)" }, { DumpLocationType_DevNull, "/dev/null (Speed Test)" },
}; };
#if ENABLE_NETWORK_INSTALL
struct UsbTest final : usb::upload::Usb, yati::source::Stream { struct UsbTest final : usb::upload::Usb, yati::source::Stream {
UsbTest(ui::ProgressBox* pbox, BaseSource* source) : Usb{UINT64_MAX} { UsbTest(ui::ProgressBox* pbox, BaseSource* source) : Usb{UINT64_MAX} {
m_pbox = pbox; m_pbox = pbox;
@@ -97,6 +100,7 @@ private:
s64 m_progress{}; s64 m_progress{};
s64 m_pull_offset{}; s64 m_pull_offset{};
}; };
#endif
Result DumpToFile(ui::ProgressBox* pbox, fs::Fs* fs, const fs::FsPath& root, BaseSource* source, std::span<const fs::FsPath> paths) { Result DumpToFile(ui::ProgressBox* pbox, fs::Fs* fs, const fs::FsPath& root, BaseSource* source, std::span<const fs::FsPath> paths) {
const auto is_file_based_emummc = App::IsFileBaseEmummc(); const auto is_file_based_emummc = App::IsFileBaseEmummc();
@@ -150,6 +154,7 @@ Result DumpToStdio(ui::ProgressBox* pbox, const location::StdioEntry& loc, BaseS
return DumpToFile(pbox, &fs, loc.mount, source, paths); return DumpToFile(pbox, &fs, loc.mount, source, paths);
} }
#if ENABLE_NETWORK_INSTALL
Result DumpToUsbS2SStream(ui::ProgressBox* pbox, UsbTest* usb, std::span<const fs::FsPath> paths) { Result DumpToUsbS2SStream(ui::ProgressBox* pbox, UsbTest* usb, std::span<const fs::FsPath> paths) {
auto source = usb->GetSource(); auto source = usb->GetSource();
@@ -239,6 +244,7 @@ Result DumpToUsbS2S(ui::ProgressBox* pbox, BaseSource* source, std::span<const f
R_THROW(0xFFFF); R_THROW(0xFFFF);
} }
#endif
Result DumpToDevNull(ui::ProgressBox* pbox, BaseSource* source, std::span<const fs::FsPath> paths) { Result DumpToDevNull(ui::ProgressBox* pbox, BaseSource* source, std::span<const fs::FsPath> paths) {
for (auto path : paths) { for (auto path : paths) {
@@ -357,7 +363,9 @@ void Dump(const std::shared_ptr<BaseSource>& source, const DumpLocation& locatio
} else if (location.entry.type == DumpLocationType_SdCard) { } else if (location.entry.type == DumpLocationType_SdCard) {
R_TRY(DumpToFileNative(pbox, source.get(), paths)); R_TRY(DumpToFileNative(pbox, source.get(), paths));
} else if (location.entry.type == DumpLocationType_UsbS2S) { } else if (location.entry.type == DumpLocationType_UsbS2S) {
#if ENABLE_NETWORK_INSTALL
R_TRY(DumpToUsbS2S(pbox, source.get(), paths)); R_TRY(DumpToUsbS2S(pbox, source.get(), paths));
#endif
} else if (location.entry.type == DumpLocationType_DevNull) { } else if (location.entry.type == DumpLocationType_DevNull) {
R_TRY(DumpToDevNull(pbox, source.get(), paths)); R_TRY(DumpToDevNull(pbox, source.get(), paths));
} }

View File

@@ -14,6 +14,7 @@
namespace sphaira::ftpsrv { namespace sphaira::ftpsrv {
namespace { namespace {
#if ENABLE_NETWORK_INSTALL
struct InstallSharedData { struct InstallSharedData {
Mutex mutex; Mutex mutex;
std::deque<std::string> queued_files; std::deque<std::string> queued_files;
@@ -26,6 +27,7 @@ struct InstallSharedData {
bool in_progress; bool in_progress;
bool enabled; bool enabled;
}; };
#endif
const char* INI_PATH = "/config/ftpsrv/config.ini"; const char* INI_PATH = "/config/ftpsrv/config.ini";
constexpr int THREAD_PRIO = PRIO_PREEMPTIVE; constexpr int THREAD_PRIO = PRIO_PREEMPTIVE;
@@ -35,7 +37,6 @@ std::atomic_bool g_should_exit = false;
bool g_is_running{false}; bool g_is_running{false};
Thread g_thread; Thread g_thread;
Mutex g_mutex{}; Mutex g_mutex{};
InstallSharedData g_shared_data{};
void ftp_log_callback(enum FTP_API_LOG_TYPE type, const char* msg) { void ftp_log_callback(enum FTP_API_LOG_TYPE type, const char* msg) {
sphaira::App::NotifyFlashLed(); sphaira::App::NotifyFlashLed();
@@ -45,6 +46,9 @@ void ftp_progress_callback(void) {
sphaira::App::NotifyFlashLed(); sphaira::App::NotifyFlashLed();
} }
#if ENABLE_NETWORK_INSTALL
InstallSharedData g_shared_data{};
const char* SUPPORTED_EXT[] = { const char* SUPPORTED_EXT[] = {
".nsp", ".xci", ".nsz", ".xcz", ".nsp", ".xci", ".nsz", ".xcz",
}; };
@@ -273,6 +277,7 @@ FtpVfs g_vfs_install = {
.rmdir = vfs_install_rmdir, .rmdir = vfs_install_rmdir,
.rename = vfs_install_rename, .rename = vfs_install_rename,
}; };
#endif
void loop(void* arg) { void loop(void* arg) {
log_write("[FTP] loop entered\n"); log_write("[FTP] loop entered\n");
@@ -348,6 +353,7 @@ bool Init() {
g_ftpsrv_config.anon = true; g_ftpsrv_config.anon = true;
} }
#if ENABLE_NETWORK_INSTALL
const VfsNxCustomPath custom = { const VfsNxCustomPath custom = {
.name = "install", .name = "install",
.user = NULL, .user = NULL,
@@ -355,6 +361,9 @@ bool Init() {
}; };
vfs_nx_init(&custom, mount_devices, save_writable, mount_bis); vfs_nx_init(&custom, mount_devices, save_writable, mount_bis);
#else
vfs_nx_init(NULL, mount_devices, save_writable, mount_bis);
#endif
Result rc; Result rc;
if (R_FAILED(rc = threadCreate(&g_thread, loop, nullptr, nullptr, 1024*16, THREAD_PRIO, THREAD_CORE))) { if (R_FAILED(rc = threadCreate(&g_thread, loop, nullptr, nullptr, 1024*16, THREAD_PRIO, THREAD_CORE))) {
@@ -396,6 +405,7 @@ void Exit() {
log_write("[FTP] exitied\n"); log_write("[FTP] exitied\n");
} }
#if ENABLE_NETWORK_INSTALL
void InitInstallMode(OnInstallStart on_start, OnInstallWrite on_write, OnInstallClose on_close) { void InitInstallMode(OnInstallStart on_start, OnInstallWrite on_write, OnInstallClose on_close) {
SCOPED_MUTEX(&g_shared_data.mutex); SCOPED_MUTEX(&g_shared_data.mutex);
g_shared_data.on_start = on_start; g_shared_data.on_start = on_start;
@@ -408,6 +418,7 @@ void DisableInstallMode() {
SCOPED_MUTEX(&g_shared_data.mutex); SCOPED_MUTEX(&g_shared_data.mutex);
g_shared_data.enabled = false; g_shared_data.enabled = false;
} }
#endif
unsigned GetPort() { unsigned GetPort() {
SCOPED_MUTEX(&g_mutex); SCOPED_MUTEX(&g_mutex);

View File

@@ -12,6 +12,7 @@
namespace sphaira::haze { namespace sphaira::haze {
namespace { namespace {
#if ENABLE_NETWORK_INSTALL
struct InstallSharedData { struct InstallSharedData {
Mutex mutex; Mutex mutex;
std::string current_file; std::string current_file;
@@ -24,12 +25,15 @@ struct InstallSharedData {
bool in_progress; bool in_progress;
bool enabled; bool enabled;
}; };
#endif
constexpr int THREAD_PRIO = PRIO_PREEMPTIVE; constexpr int THREAD_PRIO = PRIO_PREEMPTIVE;
constexpr int THREAD_CORE = 2; constexpr int THREAD_CORE = 2;
std::atomic_bool g_should_exit = false; std::atomic_bool g_should_exit = false;
bool g_is_running{false}; bool g_is_running{false};
Mutex g_mutex{}; Mutex g_mutex{};
#if ENABLE_NETWORK_INSTALL
InstallSharedData g_shared_data{}; InstallSharedData g_shared_data{};
const char* SUPPORTED_EXT[] = { const char* SUPPORTED_EXT[] = {
@@ -54,6 +58,7 @@ void on_thing() {
} }
} }
} }
#endif
struct FsProxyBase : ::haze::FileSystemProxyImpl { struct FsProxyBase : ::haze::FileSystemProxyImpl {
FsProxyBase(const char* name, const char* display_name) : m_name{name}, m_display_name{display_name} { FsProxyBase(const char* name, const char* display_name) : m_name{name}, m_display_name{display_name} {
@@ -406,6 +411,7 @@ struct FsDevNullProxy final : FsProxyVfs {
} }
}; };
#if ENABLE_NETWORK_INSTALL
struct FsInstallProxy final : FsProxyVfs { struct FsInstallProxy final : FsProxyVfs {
using FsProxyVfs::FsProxyVfs; using FsProxyVfs::FsProxyVfs;
@@ -531,6 +537,7 @@ struct FsInstallProxy final : FsProxyVfs {
return false; return false;
} }
}; };
#endif
::haze::FsEntries g_fs_entries{}; ::haze::FsEntries g_fs_entries{};
@@ -575,7 +582,9 @@ bool Init() {
g_fs_entries.emplace_back(std::make_shared<FsProxy>(std::make_unique<fs::FsNativeImage>(FsImageDirectoryId_Nand), "image_nand", "Image nand")); g_fs_entries.emplace_back(std::make_shared<FsProxy>(std::make_unique<fs::FsNativeImage>(FsImageDirectoryId_Nand), "image_nand", "Image nand"));
g_fs_entries.emplace_back(std::make_shared<FsProxy>(std::make_unique<fs::FsNativeImage>(FsImageDirectoryId_Sd), "image_sd", "Image sd")); g_fs_entries.emplace_back(std::make_shared<FsProxy>(std::make_unique<fs::FsNativeImage>(FsImageDirectoryId_Sd), "image_sd", "Image sd"));
g_fs_entries.emplace_back(std::make_shared<FsDevNullProxy>("DevNull", "DevNull (Speed Test)")); g_fs_entries.emplace_back(std::make_shared<FsDevNullProxy>("DevNull", "DevNull (Speed Test)"));
#if ENABLE_NETWORK_INSTALL
g_fs_entries.emplace_back(std::make_shared<FsInstallProxy>("install", "Install (NSP, XCI, NSZ, XCZ)")); g_fs_entries.emplace_back(std::make_shared<FsInstallProxy>("install", "Install (NSP, XCI, NSZ, XCZ)"));
#endif
g_should_exit = false; g_should_exit = false;
if (!::haze::Initialize(haze_callback, THREAD_PRIO, THREAD_CORE, g_fs_entries)) { if (!::haze::Initialize(haze_callback, THREAD_PRIO, THREAD_CORE, g_fs_entries)) {
@@ -600,6 +609,7 @@ void Exit() {
log_write("[MTP] exitied\n"); log_write("[MTP] exitied\n");
} }
#if ENABLE_NETWORK_INSTALL
void InitInstallMode(OnInstallStart on_start, OnInstallWrite on_write, OnInstallClose on_close) { void InitInstallMode(OnInstallStart on_start, OnInstallWrite on_write, OnInstallClose on_close) {
SCOPED_MUTEX(&g_shared_data.mutex); SCOPED_MUTEX(&g_shared_data.mutex);
g_shared_data.on_start = on_start; g_shared_data.on_start = on_start;
@@ -612,5 +622,6 @@ void DisableInstallMode() {
SCOPED_MUTEX(&g_shared_data.mutex); SCOPED_MUTEX(&g_shared_data.mutex);
g_shared_data.enabled = false; g_shared_data.enabled = false;
} }
#endif
} // namespace sphaira::haze } // namespace sphaira::haze

View File

@@ -1,3 +1,5 @@
#if ENABLE_NETWORK_INSTALL
#include "ui/menus/ftp_menu.hpp" #include "ui/menus/ftp_menu.hpp"
#include "app.hpp" #include "app.hpp"
#include "defines.hpp" #include "defines.hpp"
@@ -101,3 +103,5 @@ void Menu::OnDisableInstallMode() {
} }
} // namespace sphaira::ui::menu::ftp } // namespace sphaira::ui::menu::ftp
#endif

View File

@@ -1,3 +1,5 @@
#if ENABLE_NETWORK_INSTALL
#include "ui/menus/install_stream_menu_base.hpp" #include "ui/menus/install_stream_menu_base.hpp"
#include "yati/yati.hpp" #include "yati/yati.hpp"
#include "app.hpp" #include "app.hpp"
@@ -273,3 +275,5 @@ void Menu::OnInstallClose() {
} }
} // namespace sphaira::ui::menu::stream } // namespace sphaira::ui::menu::stream
#endif

View File

@@ -54,9 +54,11 @@ const MiscMenuEntry MISC_MENU_ENTRIES[] = {
{ .name = "Saves", .title = "Saves", .func = MiscMenuFuncGenerator<ui::menu::save::Menu>, .flag = MiscMenuFlag_Shortcut }, { .name = "Saves", .title = "Saves", .func = MiscMenuFuncGenerator<ui::menu::save::Menu>, .flag = MiscMenuFlag_Shortcut },
{ .name = "Themezer", .title = "Themezer", .func = MiscMenuFuncGenerator<ui::menu::themezer::Menu>, .flag = MiscMenuFlag_Shortcut }, { .name = "Themezer", .title = "Themezer", .func = MiscMenuFuncGenerator<ui::menu::themezer::Menu>, .flag = MiscMenuFlag_Shortcut },
{ .name = "GitHub", .title = "GitHub", .func = MiscMenuFuncGenerator<ui::menu::gh::Menu>, .flag = MiscMenuFlag_Shortcut }, { .name = "GitHub", .title = "GitHub", .func = MiscMenuFuncGenerator<ui::menu::gh::Menu>, .flag = MiscMenuFlag_Shortcut },
#if ENABLE_NETWORK_INSTALL
{ .name = "FTP", .title = "FTP Install", .func = MiscMenuFuncGenerator<ui::menu::ftp::Menu>, .flag = MiscMenuFlag_Install }, { .name = "FTP", .title = "FTP Install", .func = MiscMenuFuncGenerator<ui::menu::ftp::Menu>, .flag = MiscMenuFlag_Install },
{ .name = "MTP", .title = "MTP Install", .func = MiscMenuFuncGenerator<ui::menu::mtp::Menu>, .flag = MiscMenuFlag_Install }, { .name = "MTP", .title = "MTP Install", .func = MiscMenuFuncGenerator<ui::menu::mtp::Menu>, .flag = MiscMenuFlag_Install },
{ .name = "USB", .title = "USB Install", .func = MiscMenuFuncGenerator<ui::menu::usb::Menu>, .flag = MiscMenuFlag_Install }, { .name = "USB", .title = "USB Install", .func = MiscMenuFuncGenerator<ui::menu::usb::Menu>, .flag = MiscMenuFlag_Install },
#endif
{ .name = "GameCard", .title = "GameCard", .func = MiscMenuFuncGenerator<ui::menu::gc::Menu>, .flag = MiscMenuFlag_Shortcut }, { .name = "GameCard", .title = "GameCard", .func = MiscMenuFuncGenerator<ui::menu::gc::Menu>, .flag = MiscMenuFlag_Shortcut },
{ .name = "IRS", .title = "IRS (Infrared Joycon Camera)", .func = MiscMenuFuncGenerator<ui::menu::irs::Menu>, .flag = MiscMenuFlag_Shortcut }, { .name = "IRS", .title = "IRS (Infrared Joycon Camera)", .func = MiscMenuFuncGenerator<ui::menu::irs::Menu>, .flag = MiscMenuFlag_Shortcut },
}; };

View File

@@ -1,3 +1,5 @@
#if ENABLE_NETWORK_INSTALL
#include "ui/menus/mtp_menu.hpp" #include "ui/menus/mtp_menu.hpp"
#include "usb/usbds.hpp" #include "usb/usbds.hpp"
#include "app.hpp" #include "app.hpp"
@@ -57,3 +59,5 @@ void Menu::OnDisableInstallMode() {
} }
} // namespace sphaira::ui::menu::mtp } // namespace sphaira::ui::menu::mtp
#endif

View File

@@ -1,3 +1,5 @@
#if ENABLE_NETWORK_INSTALL
#include "ui/menus/usb_menu.hpp" #include "ui/menus/usb_menu.hpp"
#include "yati/yati.hpp" #include "yati/yati.hpp"
#include "app.hpp" #include "app.hpp"
@@ -189,3 +191,5 @@ void Menu::ThreadFunction() {
} }
} // namespace sphaira::ui::menu::usb } // namespace sphaira::ui::menu::usb
#endif

View File

@@ -16,6 +16,8 @@
// The USB transfer code was taken from Haze (part of Atmosphere). // The USB transfer code was taken from Haze (part of Atmosphere).
#if ENABLE_NETWORK_INSTALL
#include "usb/base.hpp" #include "usb/base.hpp"
#include "log.hpp" #include "log.hpp"
#include "defines.hpp" #include "defines.hpp"
@@ -98,3 +100,5 @@ Result Base::TransferAll(bool read, void *data, u32 size, u64 timeout) {
} }
} // namespace sphaira::usb } // namespace sphaira::usb
#endif

View File

@@ -1,4 +1,5 @@
// The USB protocol was taken from Tinfoil, by Adubbz. // The USB protocol was taken from Tinfoil, by Adubbz.
#if ENABLE_NETWORK_INSTALL
#include "usb/usb_uploader.hpp" #include "usb/usb_uploader.hpp"
#include "usb/tinfoil.hpp" #include "usb/tinfoil.hpp"
@@ -109,3 +110,5 @@ Result Usb::FileRangeCmd(u64 data_size) {
} }
} // namespace sphaira::usb::upload } // namespace sphaira::usb::upload
#endif

View File

@@ -1,3 +1,5 @@
#if ENABLE_NETWORK_INSTALL
#include "usb/usbds.hpp" #include "usb/usbds.hpp"
#include "log.hpp" #include "log.hpp"
#include "defines.hpp" #include "defines.hpp"
@@ -342,3 +344,5 @@ Result UsbDs::GetTransferResult(UsbSessionEndpoint ep, u32 urb_id, u32 *out_requ
} }
} // namespace sphaira::usb } // namespace sphaira::usb
#endif

View File

@@ -1,3 +1,5 @@
#if ENABLE_NETWORK_INSTALL
#include "usb/usbhs.hpp" #include "usb/usbhs.hpp"
#include "log.hpp" #include "log.hpp"
#include "defines.hpp" #include "defines.hpp"
@@ -200,3 +202,5 @@ Result UsbHs::GetTransferResult(UsbSessionEndpoint ep, u32 xfer_id, u32 *out_req
} }
} // namespace sphaira::usb } // namespace sphaira::usb
#endif

View File

@@ -1,4 +1,5 @@
// The USB protocol was taken from Tinfoil, by Adubbz. // The USB protocol was taken from Tinfoil, by Adubbz.
#if ENABLE_NETWORK_INSTALL
#include "yati/source/usb.hpp" #include "yati/source/usb.hpp"
#include "usb/tinfoil.hpp" #include "usb/tinfoil.hpp"
@@ -97,3 +98,5 @@ Result Usb::Read(void* buf, s64 off, s64 size, u64* bytes_read) {
} }
} // namespace sphaira::yati::source } // namespace sphaira::yati::source
#endif