From f534d3498e61334c9176e77873968a66de3f0a7c Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 17 Jul 2019 20:04:00 -0700 Subject: [PATCH] git subrepo clone https://github.com/Atmosphere-NX/libstratosphere stratosphere/libstratosphere subrepo: subdir: "stratosphere/libstratosphere" merged: "0c5dab80" upstream: origin: "https://github.com/Atmosphere-NX/libstratosphere" branch: "master" commit: "0c5dab80" git-subrepo: version: "0.4.0" origin: "https://github.com/ingydotnet/git-subrepo" commit: "5d6aba9" --- stratosphere/libstratosphere/.gitignore | 74 + stratosphere/libstratosphere/.gitmodules | 0 stratosphere/libstratosphere/.gitrepo | 12 + stratosphere/libstratosphere/LICENSE | 339 +++ stratosphere/libstratosphere/Makefile | 152 ++ stratosphere/libstratosphere/README.md | 31 + .../include/freebsd/sys/tree.h | 812 +++++++ .../libstratosphere/include/stratosphere.hpp | 53 + .../include/stratosphere/auto_handle.hpp | 80 + .../include/stratosphere/cfg.hpp | 20 + .../include/stratosphere/cfg/cfg_api.hpp | 47 + .../include/stratosphere/defines.hpp | 50 + .../include/stratosphere/emummc_utilities.hpp | 28 + .../include/stratosphere/event.hpp | 139 ++ .../include/stratosphere/firmware_version.hpp | 49 + .../include/stratosphere/hid.hpp | 20 + .../include/stratosphere/hid/hid_api.hpp | 24 + .../include/stratosphere/hossynch.hpp | 286 +++ .../include/stratosphere/ipc.hpp | 22 + .../include/stratosphere/ipc/ipc_buffers.hpp | 117 ++ .../stratosphere/ipc/ipc_domain_object.hpp | 130 ++ .../include/stratosphere/ipc/ipc_out.hpp | 75 + .../stratosphere/ipc/ipc_response_context.hpp | 44 + .../stratosphere/ipc/ipc_serialization.hpp | 672 ++++++ .../stratosphere/ipc/ipc_service_object.hpp | 135 ++ .../stratosphere/ipc/ipc_service_session.hpp | 344 +++ .../ipc/ipc_session_manager_base.hpp | 34 + .../include/stratosphere/ipc/ipc_special.hpp | 152 ++ .../include/stratosphere/iwaitable.hpp | 79 + .../stratosphere/kvdb/kvdb_archive.hpp | 68 + .../stratosphere/kvdb/kvdb_auto_buffer.hpp | 94 + .../stratosphere/kvdb/kvdb_bounded_string.hpp | 152 ++ .../kvdb/kvdb_file_key_value_cache.hpp | 422 ++++ .../kvdb/kvdb_file_key_value_store.hpp | 127 ++ .../kvdb/kvdb_memory_key_value_store.hpp | 569 +++++ .../include/stratosphere/ldr.hpp | 20 + .../include/stratosphere/ldr/ldr_pm_api.hpp | 30 + .../include/stratosphere/ldr/ldr_types.hpp | 244 +++ .../include/stratosphere/map.hpp | 21 + .../include/stratosphere/map/map_api.hpp | 30 + .../include/stratosphere/map/map_types.hpp | 123 ++ .../include/stratosphere/message_queue.hpp | 73 + .../include/stratosphere/mitm.hpp | 26 + .../stratosphere/mitm/imitmserviceobject.hpp | 47 + .../stratosphere/mitm/mitm_query_service.hpp | 36 + .../include/stratosphere/mitm/mitm_server.hpp | 91 + .../stratosphere/mitm/mitm_session.hpp | 342 +++ .../include/stratosphere/ncm.hpp | 20 + .../include/stratosphere/ncm/ncm_types.hpp | 432 ++++ .../include/stratosphere/on_crash.hpp | 27 + .../include/stratosphere/patcher.hpp | 20 + .../stratosphere/patcher/patcher_api.hpp | 26 + .../include/stratosphere/pm.hpp | 23 + .../stratosphere/pm/pm_boot_mode_api.hpp | 27 + .../include/stratosphere/pm/pm_info_api.hpp | 32 + .../include/stratosphere/pm/pm_shell_api.hpp | 27 + .../include/stratosphere/pm/pm_types.hpp | 43 + .../include/stratosphere/reg.hpp | 70 + .../include/stratosphere/results.hpp | 47 + .../stratosphere/results/ams_results.hpp | 31 + .../stratosphere/results/creport_results.hpp | 33 + .../stratosphere/results/debug_results.hpp | 24 + .../stratosphere/results/dmnt_results.hpp | 38 + .../stratosphere/results/fatal_results.hpp | 27 + .../stratosphere/results/fs_results.hpp | 67 + .../stratosphere/results/hipc_results.hpp | 27 + .../stratosphere/results/i2c_results.hpp | 26 + .../stratosphere/results/kernel_results.hpp | 63 + .../stratosphere/results/kvdb_results.hpp | 29 + .../stratosphere/results/loader_results.hpp | 59 + .../stratosphere/results/lr_results.hpp | 30 + .../stratosphere/results/ncm_results.hpp | 51 + .../stratosphere/results/pm_results.hpp | 27 + .../stratosphere/results/ro_results.hpp | 40 + .../stratosphere/results/settings_results.hpp | 41 + .../stratosphere/results/sf_results.hpp | 28 + .../stratosphere/results/sm_results.hpp | 30 + .../stratosphere/results/spl_results.hpp | 39 + .../stratosphere/results/updater_results.hpp | 26 + .../include/stratosphere/results/utilities.h | 116 + .../stratosphere/results/vi_results.hpp | 24 + .../include/stratosphere/rnd.hpp | 20 + .../include/stratosphere/rnd/rnd_api.hpp | 28 + .../include/stratosphere/ro.hpp | 20 + .../include/stratosphere/ro/ro_types.hpp | 152 ++ .../include/stratosphere/scope_guard.hpp | 62 + .../include/stratosphere/servers.hpp | 83 + .../include/stratosphere/services.hpp | 21 + .../include/stratosphere/services/bpc_ams.h | 66 + .../include/stratosphere/services/dmntcht.h | 92 + .../include/stratosphere/sm.hpp | 22 + .../include/stratosphere/sm/sm_api.hpp | 32 + .../stratosphere/sm/sm_manager_api.hpp | 32 + .../include/stratosphere/sm/sm_mitm_api.hpp | 32 + .../include/stratosphere/sm/sm_types.hpp | 142 ++ .../include/stratosphere/spl.hpp | 22 + .../include/stratosphere/spl/smc/spl_smc.hpp | 57 + .../include/stratosphere/spl/spl_api.hpp | 30 + .../include/stratosphere/spl/spl_types.hpp | 179 ++ .../include/stratosphere/svc.hpp | 20 + .../include/stratosphere/svc/svc_types.hpp | 205 ++ .../include/stratosphere/updater.hpp | 21 + .../stratosphere/updater/updater_api.hpp | 29 + .../stratosphere/updater/updater_types.hpp | 44 + .../include/stratosphere/util.hpp | 23 + .../stratosphere/util/util_compression.hpp | 28 + .../include/stratosphere/util/util_ini.hpp | 32 + .../stratosphere/util/util_intrusive_list.hpp | 607 ++++++ .../util/util_intrusive_red_black_tree.hpp | 301 +++ .../util/util_parent_of_member.hpp | 78 + .../include/stratosphere/utilities.hpp | 128 ++ .../include/stratosphere/version_check.hpp | 75 + .../include/stratosphere/waitable_manager.hpp | 413 ++++ .../stratosphere/waitable_manager_base.hpp | 38 + stratosphere/libstratosphere/source/bpc_ams.c | 76 + .../libstratosphere/source/cfg/cfg_flags.cpp | 74 + .../source/cfg/cfg_override.cpp | 302 +++ .../source/cfg/cfg_privileged_process.cpp | 95 + .../source/cfg/cfg_sd_card.cpp | 82 + stratosphere/libstratosphere/source/dmntcht.c | 650 ++++++ .../source/emummc_utilities.cpp | 143 ++ .../source/firmware_version.cpp | 147 ++ .../libstratosphere/source/hid/hid_api.cpp | 70 + .../source/kvdb/kvdb_archive.cpp | 186 ++ .../source/kvdb/kvdb_file_key_value_store.cpp | 351 ++++ .../libstratosphere/source/ldr/ldr_ams.c | 68 + .../libstratosphere/source/ldr/ldr_ams.h | 19 + .../libstratosphere/source/ldr/ldr_pm_api.cpp | 48 + .../libstratosphere/source/map/map_api.cpp | 238 +++ .../libstratosphere/source/message_queue.cpp | 235 +++ .../libstratosphere/source/mitm_server.cpp | 47 + .../libstratosphere/source/on_crash.cpp | 142 ++ .../source/patcher/patcher_api.cpp | 256 +++ .../libstratosphere/source/pm/pm_ams.c | 96 + .../libstratosphere/source/pm/pm_ams.h | 19 + .../source/pm/pm_boot_mode_api.cpp | 34 + .../libstratosphere/source/pm/pm_info_api.cpp | 70 + .../source/pm/pm_shell_api.cpp | 28 + .../libstratosphere/source/rnd/rnd_api.cpp | 132 ++ .../libstratosphere/source/sm/sm_ams.c | 376 ++++ .../libstratosphere/source/sm/sm_ams.h | 29 + .../libstratosphere/source/sm/sm_api.cpp | 58 + .../source/sm/sm_manager_api.cpp | 44 + .../libstratosphere/source/sm/sm_mitm_api.cpp | 63 + .../libstratosphere/source/sm/sm_utils.cpp | 38 + .../libstratosphere/source/sm/sm_utils.hpp | 53 + .../libstratosphere/source/sm/smm_ams.c | 129 ++ .../libstratosphere/source/sm/smm_ams.h | 20 + .../source/spl/smc/spl_smc.cpp | 312 +++ .../libstratosphere/source/spl/spl_api.cpp | 78 + .../source/updater/updater_api.cpp | 562 +++++ .../source/updater/updater_bis_management.cpp | 168 ++ .../source/updater/updater_bis_management.hpp | 238 +++ .../source/updater/updater_bis_save.cpp | 66 + .../source/updater/updater_bis_save.hpp | 46 + .../source/updater/updater_files.cpp | 72 + .../source/updater/updater_files.hpp | 28 + .../source/updater/updater_paths.cpp | 119 ++ .../source/updater/updater_paths.hpp | 30 + .../libstratosphere/source/util/ini.c | 269 +++ .../libstratosphere/source/util/ini.h | 130 ++ .../libstratosphere/source/util/lz4.c | 1857 +++++++++++++++++ .../libstratosphere/source/util/lz4.h | 569 +++++ .../source/util/util_compression.cpp | 47 + .../libstratosphere/source/util/util_ini.cpp | 96 + .../libstratosphere/source/utilities.cpp | 30 + 166 files changed, 20474 insertions(+) create mode 100644 stratosphere/libstratosphere/.gitignore create mode 100644 stratosphere/libstratosphere/.gitmodules create mode 100644 stratosphere/libstratosphere/.gitrepo create mode 100644 stratosphere/libstratosphere/LICENSE create mode 100644 stratosphere/libstratosphere/Makefile create mode 100644 stratosphere/libstratosphere/README.md create mode 100644 stratosphere/libstratosphere/include/freebsd/sys/tree.h create mode 100644 stratosphere/libstratosphere/include/stratosphere.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/auto_handle.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/cfg.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/cfg/cfg_api.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/defines.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/emummc_utilities.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/event.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/firmware_version.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/hid.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/hid/hid_api.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/hossynch.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc/ipc_buffers.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc/ipc_domain_object.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc/ipc_out.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc/ipc_response_context.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_object.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_session.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc/ipc_session_manager_base.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc/ipc_special.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/iwaitable.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/kvdb/kvdb_archive.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/kvdb/kvdb_auto_buffer.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/kvdb/kvdb_bounded_string.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/kvdb/kvdb_file_key_value_cache.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/kvdb/kvdb_file_key_value_store.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/kvdb/kvdb_memory_key_value_store.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/ldr.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/ldr/ldr_pm_api.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/ldr/ldr_types.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/map.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/map/map_api.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/map/map_types.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/message_queue.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/mitm.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/mitm/imitmserviceobject.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/mitm/mitm_query_service.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/mitm/mitm_server.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/mitm/mitm_session.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/ncm.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/ncm/ncm_types.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/on_crash.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/patcher.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/patcher/patcher_api.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/pm.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/pm/pm_boot_mode_api.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/pm/pm_info_api.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/pm/pm_shell_api.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/pm/pm_types.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/reg.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/results.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/results/ams_results.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/results/creport_results.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/results/debug_results.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/results/dmnt_results.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/results/fatal_results.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/results/fs_results.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/results/hipc_results.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/results/i2c_results.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/results/kernel_results.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/results/kvdb_results.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/results/loader_results.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/results/lr_results.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/results/ncm_results.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/results/pm_results.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/results/ro_results.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/results/settings_results.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/results/sf_results.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/results/sm_results.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/results/spl_results.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/results/updater_results.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/results/utilities.h create mode 100644 stratosphere/libstratosphere/include/stratosphere/results/vi_results.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/rnd.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/rnd/rnd_api.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/ro.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/ro/ro_types.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/scope_guard.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/servers.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/services.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/services/bpc_ams.h create mode 100644 stratosphere/libstratosphere/include/stratosphere/services/dmntcht.h create mode 100644 stratosphere/libstratosphere/include/stratosphere/sm.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/sm/sm_api.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/sm/sm_manager_api.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/sm/sm_mitm_api.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/sm/sm_types.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/spl.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/spl/smc/spl_smc.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/spl/spl_api.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/spl/spl_types.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/svc.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/svc/svc_types.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/updater.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/updater/updater_api.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/updater/updater_types.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/util.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/util/util_compression.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/util/util_ini.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/util/util_intrusive_list.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/util/util_intrusive_red_black_tree.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/util/util_parent_of_member.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/utilities.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/version_check.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/waitable_manager_base.hpp create mode 100644 stratosphere/libstratosphere/source/bpc_ams.c create mode 100644 stratosphere/libstratosphere/source/cfg/cfg_flags.cpp create mode 100644 stratosphere/libstratosphere/source/cfg/cfg_override.cpp create mode 100644 stratosphere/libstratosphere/source/cfg/cfg_privileged_process.cpp create mode 100644 stratosphere/libstratosphere/source/cfg/cfg_sd_card.cpp create mode 100644 stratosphere/libstratosphere/source/dmntcht.c create mode 100644 stratosphere/libstratosphere/source/emummc_utilities.cpp create mode 100644 stratosphere/libstratosphere/source/firmware_version.cpp create mode 100644 stratosphere/libstratosphere/source/hid/hid_api.cpp create mode 100644 stratosphere/libstratosphere/source/kvdb/kvdb_archive.cpp create mode 100644 stratosphere/libstratosphere/source/kvdb/kvdb_file_key_value_store.cpp create mode 100644 stratosphere/libstratosphere/source/ldr/ldr_ams.c create mode 100644 stratosphere/libstratosphere/source/ldr/ldr_ams.h create mode 100644 stratosphere/libstratosphere/source/ldr/ldr_pm_api.cpp create mode 100644 stratosphere/libstratosphere/source/map/map_api.cpp create mode 100644 stratosphere/libstratosphere/source/message_queue.cpp create mode 100644 stratosphere/libstratosphere/source/mitm_server.cpp create mode 100644 stratosphere/libstratosphere/source/on_crash.cpp create mode 100644 stratosphere/libstratosphere/source/patcher/patcher_api.cpp create mode 100644 stratosphere/libstratosphere/source/pm/pm_ams.c create mode 100644 stratosphere/libstratosphere/source/pm/pm_ams.h create mode 100644 stratosphere/libstratosphere/source/pm/pm_boot_mode_api.cpp create mode 100644 stratosphere/libstratosphere/source/pm/pm_info_api.cpp create mode 100644 stratosphere/libstratosphere/source/pm/pm_shell_api.cpp create mode 100644 stratosphere/libstratosphere/source/rnd/rnd_api.cpp create mode 100644 stratosphere/libstratosphere/source/sm/sm_ams.c create mode 100644 stratosphere/libstratosphere/source/sm/sm_ams.h create mode 100644 stratosphere/libstratosphere/source/sm/sm_api.cpp create mode 100644 stratosphere/libstratosphere/source/sm/sm_manager_api.cpp create mode 100644 stratosphere/libstratosphere/source/sm/sm_mitm_api.cpp create mode 100644 stratosphere/libstratosphere/source/sm/sm_utils.cpp create mode 100644 stratosphere/libstratosphere/source/sm/sm_utils.hpp create mode 100644 stratosphere/libstratosphere/source/sm/smm_ams.c create mode 100644 stratosphere/libstratosphere/source/sm/smm_ams.h create mode 100644 stratosphere/libstratosphere/source/spl/smc/spl_smc.cpp create mode 100644 stratosphere/libstratosphere/source/spl/spl_api.cpp create mode 100644 stratosphere/libstratosphere/source/updater/updater_api.cpp create mode 100644 stratosphere/libstratosphere/source/updater/updater_bis_management.cpp create mode 100644 stratosphere/libstratosphere/source/updater/updater_bis_management.hpp create mode 100644 stratosphere/libstratosphere/source/updater/updater_bis_save.cpp create mode 100644 stratosphere/libstratosphere/source/updater/updater_bis_save.hpp create mode 100644 stratosphere/libstratosphere/source/updater/updater_files.cpp create mode 100644 stratosphere/libstratosphere/source/updater/updater_files.hpp create mode 100644 stratosphere/libstratosphere/source/updater/updater_paths.cpp create mode 100644 stratosphere/libstratosphere/source/updater/updater_paths.hpp create mode 100644 stratosphere/libstratosphere/source/util/ini.c create mode 100644 stratosphere/libstratosphere/source/util/ini.h create mode 100644 stratosphere/libstratosphere/source/util/lz4.c create mode 100644 stratosphere/libstratosphere/source/util/lz4.h create mode 100644 stratosphere/libstratosphere/source/util/util_compression.cpp create mode 100644 stratosphere/libstratosphere/source/util/util_ini.cpp create mode 100644 stratosphere/libstratosphere/source/utilities.cpp diff --git a/stratosphere/libstratosphere/.gitignore b/stratosphere/libstratosphere/.gitignore new file mode 100644 index 000000000..f55c55a62 --- /dev/null +++ b/stratosphere/libstratosphere/.gitignore @@ -0,0 +1,74 @@ +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp +*.lst + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Switch Executables +*.nso +*.nro +*.nacp +*.npdm +*.pfs0 +*.nsp +*.kip + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# Distribution files +*.tgz +*.zip + +.**/ + +# NOTE: make sure to make exceptions to this pattern when needed! +*.bin + +**/out +**/build diff --git a/stratosphere/libstratosphere/.gitmodules b/stratosphere/libstratosphere/.gitmodules new file mode 100644 index 000000000..e69de29bb diff --git a/stratosphere/libstratosphere/.gitrepo b/stratosphere/libstratosphere/.gitrepo new file mode 100644 index 000000000..bf506bd10 --- /dev/null +++ b/stratosphere/libstratosphere/.gitrepo @@ -0,0 +1,12 @@ +; DO NOT EDIT (unless you know what you are doing) +; +; This subdirectory is a git "subrepo", and this file is maintained by the +; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme +; +[subrepo] + remote = https://github.com/Atmosphere-NX/libstratosphere + branch = master + commit = 0c5dab8022aee28e8e22db7ca144471557a18ff2 + parent = 3ea9f444dbcd362dc0d07f350dac4898ad98cc83 + method = merge + cmdver = 0.4.0 diff --git a/stratosphere/libstratosphere/LICENSE b/stratosphere/libstratosphere/LICENSE new file mode 100644 index 000000000..ecbc05937 --- /dev/null +++ b/stratosphere/libstratosphere/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. \ No newline at end of file diff --git a/stratosphere/libstratosphere/Makefile b/stratosphere/libstratosphere/Makefile new file mode 100644 index 000000000..ea746be8b --- /dev/null +++ b/stratosphere/libstratosphere/Makefile @@ -0,0 +1,152 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITPRO)),) +$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=/devkitpro") +endif + +TOPDIR ?= $(CURDIR) +include $(DEVKITPRO)/libnx/switch_rules + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# SOURCES is a list of directories containing source code +# DATA is a list of directories containing data files +# INCLUDES is a list of directories containing header files +#--------------------------------------------------------------------------------- +TARGET := $(notdir $(CURDIR)) +SOURCES := source source/spl source/spl/smc source/updater source/patcher source/map source/rnd source/util source/sm source/cfg source/pm source/hid source/ldr source/kvdb +DATA := data +INCLUDES := include + +DEFINES := -DRESULT_ABORT_ON_ASSERT + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE + +CFLAGS := -g -Wall -O2 -ffunction-sections \ + $(ARCH) $(DEFINES) + +CFLAGS += $(INCLUDE) -D__SWITCH__ + +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17 + +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) + +LIBS := -lnx + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(PORTLIBS) $(LIBNX) + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES_BIN := $(addsuffix .o,$(BINFILES)) +export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) +export OFILES := $(OFILES_BIN) $(OFILES_SRC) +export HFILES := $(addsuffix .h,$(subst .,_,$(BINFILES))) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I. \ + -iquote $(CURDIR)/include/switch/ + +.PHONY: clean all + +#--------------------------------------------------------------------------------- +all: lib/$(TARGET).a lib/$(TARGET)d.a + +lib: + @[ -d $@ ] || mkdir -p $@ + +release: + @[ -d $@ ] || mkdir -p $@ + +debug: + @[ -d $@ ] || mkdir -p $@ + +lib/$(TARGET).a : lib release $(SOURCES) $(INCLUDES) + @$(MAKE) BUILD=release OUTPUT=$(CURDIR)/$@ \ + BUILD_CFLAGS="-DNDEBUG=1 -O2" \ + DEPSDIR=$(CURDIR)/release \ + --no-print-directory -C release \ + -f $(CURDIR)/Makefile + +lib/$(TARGET)d.a : lib debug $(SOURCES) $(INCLUDES) + @$(MAKE) BUILD=debug OUTPUT=$(CURDIR)/$@ \ + BUILD_CFLAGS="-DDEBUG=1 -Og" \ + DEPSDIR=$(CURDIR)/debug \ + --no-print-directory -C debug \ + -f $(CURDIR)/Makefile + +dist-bin: all + @tar --exclude=*~ -cjf $(TARGET).tar.bz2 include lib + +dist-src: + @tar --exclude=*~ -cjf $(TARGET)-src.tar.bz2 include source Makefile + +dist: dist-src dist-bin + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr release debug lib *.bz2 + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(OUTPUT) : $(OFILES) + +$(OFILES_SRC) : $(HFILES) + +#--------------------------------------------------------------------------------- +%_bin.h %.bin.o : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- + diff --git a/stratosphere/libstratosphere/README.md b/stratosphere/libstratosphere/README.md new file mode 100644 index 000000000..0dc7138b4 --- /dev/null +++ b/stratosphere/libstratosphere/README.md @@ -0,0 +1,31 @@ +![License](https://img.shields.io/badge/License-GPLv2-blue.svg) + +libstratosphere is a work-in-progress C++ library for development of system modules for the Nintendo Switch. + +It is built around extending [libnx](https://github.com/switchbrew/libnx). + +It also provides bindings for custom extensions to Horizon OS implemented by [Atmosphère](https://github.com/Atmosphere-NX). + +Licensing +===== + +This software is licensed under the terms of the GPLv2, with exemptions for specific projects noted below. + +You can find a copy of the license in the [LICENSE file](LICENSE). + +Exemptions: +* The [yuzu emulator project](https://github.com/yuzu-emu/yuzu) is exempt from GPLv2 licensing and may (at its option) instead license any source code authored for the libstratosphere project as GPLv2 or later. + +Credits +===== + +libstratosphere is currently being developed and maintained by __SciresM__.
+ +In addition to those credited in [Atmosphère's credits](https://github.com/Atmosphere-NX/Atmosphere/blob/master/README.md#Credits), we would like to thank for contributing to libstratosphere in some significant way: + +* __hthh__ +* __fincs__ +* __lioncash__ +* __misson20000__ +* __neobrain__ +* __yellows8__ diff --git a/stratosphere/libstratosphere/include/freebsd/sys/tree.h b/stratosphere/libstratosphere/include/freebsd/sys/tree.h new file mode 100644 index 000000000..fecde6913 --- /dev/null +++ b/stratosphere/libstratosphere/include/freebsd/sys/tree.h @@ -0,0 +1,812 @@ +/* $NetBSD: tree.h,v 1.8 2004/03/28 19:38:30 provos Exp $ */ +/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */ +/* $FreeBSD$ */ + +/*- + * Copyright 2002 Niels Provos + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_TREE_H_ +#define _SYS_TREE_H_ + +/* FreeBSD has a lot of defines we don't really want. */ +/* tree.h only actually uses __inline and __unused, so we'll just define those. */ + +/* #include */ + +#ifndef __inline +#define __inline inline +#endif + +#ifndef __unused +#define __unused __attribute__((__unused__)) +#endif + +/* + * This file defines data structures for different types of trees: + * splay trees and red-black trees. + * + * A splay tree is a self-organizing data structure. Every operation + * on the tree causes a splay to happen. The splay moves the requested + * node to the root of the tree and partly rebalances it. + * + * This has the benefit that request locality causes faster lookups as + * the requested nodes move to the top of the tree. On the other hand, + * every lookup causes memory writes. + * + * The Balance Theorem bounds the total access time for m operations + * and n inserts on an initially empty tree as O((m + n)lg n). The + * amortized cost for a sequence of m accesses to a splay tree is O(lg n); + * + * A red-black tree is a binary search tree with the node color as an + * extra attribute. It fulfills a set of conditions: + * - every search path from the root to a leaf consists of the + * same number of black nodes, + * - each red node (except for the root) has a black parent, + * - each leaf node is black. + * + * Every operation on a red-black tree is bounded as O(lg n). + * The maximum height of a red-black tree is 2lg (n+1). + */ + +#define SPLAY_HEAD(name, type) \ +struct name { \ + struct type *sph_root; /* root of the tree */ \ +} + +#define SPLAY_INITIALIZER(root) \ + { NULL } + +#define SPLAY_INIT(root) do { \ + (root)->sph_root = NULL; \ +} while (/*CONSTCOND*/ 0) + +#define SPLAY_ENTRY(type) \ +struct { \ + struct type *spe_left; /* left element */ \ + struct type *spe_right; /* right element */ \ +} + +#define SPLAY_LEFT(elm, field) (elm)->field.spe_left +#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right +#define SPLAY_ROOT(head) (head)->sph_root +#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL) + +/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */ +#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \ + SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ +} while (/*CONSTCOND*/ 0) + +#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \ + SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ +} while (/*CONSTCOND*/ 0) + +#define SPLAY_LINKLEFT(head, tmp, field) do { \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ +} while (/*CONSTCOND*/ 0) + +#define SPLAY_LINKRIGHT(head, tmp, field) do { \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \ +} while (/*CONSTCOND*/ 0) + +#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \ + SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \ + SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\ + SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \ + SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \ +} while (/*CONSTCOND*/ 0) + +/* Generates prototypes and inline functions */ + +#define SPLAY_PROTOTYPE(name, type, field, cmp) \ +void name##_SPLAY(struct name *, struct type *); \ +void name##_SPLAY_MINMAX(struct name *, int); \ +struct type *name##_SPLAY_INSERT(struct name *, struct type *); \ +struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \ + \ +/* Finds the node with the same key as elm */ \ +static __inline struct type * \ +name##_SPLAY_FIND(struct name *head, struct type *elm) \ +{ \ + if (SPLAY_EMPTY(head)) \ + return(NULL); \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) \ + return (head->sph_root); \ + return (NULL); \ +} \ + \ +static __inline struct type * \ +name##_SPLAY_NEXT(struct name *head, struct type *elm) \ +{ \ + name##_SPLAY(head, elm); \ + if (SPLAY_RIGHT(elm, field) != NULL) { \ + elm = SPLAY_RIGHT(elm, field); \ + while (SPLAY_LEFT(elm, field) != NULL) { \ + elm = SPLAY_LEFT(elm, field); \ + } \ + } else \ + elm = NULL; \ + return (elm); \ +} \ + \ +static __inline struct type * \ +name##_SPLAY_MIN_MAX(struct name *head, int val) \ +{ \ + name##_SPLAY_MINMAX(head, val); \ + return (SPLAY_ROOT(head)); \ +} + +/* Main splay operation. + * Moves node close to the key of elm to top + */ +#define SPLAY_GENERATE(name, type, field, cmp) \ +struct type * \ +name##_SPLAY_INSERT(struct name *head, struct type *elm) \ +{ \ + if (SPLAY_EMPTY(head)) { \ + SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \ + } else { \ + int __comp; \ + name##_SPLAY(head, elm); \ + __comp = (cmp)(elm, (head)->sph_root); \ + if(__comp < 0) { \ + SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\ + SPLAY_RIGHT(elm, field) = (head)->sph_root; \ + SPLAY_LEFT((head)->sph_root, field) = NULL; \ + } else if (__comp > 0) { \ + SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\ + SPLAY_LEFT(elm, field) = (head)->sph_root; \ + SPLAY_RIGHT((head)->sph_root, field) = NULL; \ + } else \ + return ((head)->sph_root); \ + } \ + (head)->sph_root = (elm); \ + return (NULL); \ +} \ + \ +struct type * \ +name##_SPLAY_REMOVE(struct name *head, struct type *elm) \ +{ \ + struct type *__tmp; \ + if (SPLAY_EMPTY(head)) \ + return (NULL); \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) { \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \ + (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\ + } else { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\ + name##_SPLAY(head, elm); \ + SPLAY_RIGHT((head)->sph_root, field) = __tmp; \ + } \ + return (elm); \ + } \ + return (NULL); \ +} \ + \ +void \ +name##_SPLAY(struct name *head, struct type *elm) \ +{ \ + struct type __node, *__left, *__right, *__tmp; \ + int __comp; \ +\ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ + __left = __right = &__node; \ +\ + while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) < 0){ \ + SPLAY_ROTATE_RIGHT(head, __tmp, field); \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) > 0){ \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ +} \ + \ +/* Splay with either the minimum or the maximum element \ + * Used to find minimum or maximum element in tree. \ + */ \ +void name##_SPLAY_MINMAX(struct name *head, int __comp) \ +{ \ + struct type __node, *__left, *__right, *__tmp; \ +\ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ + __left = __right = &__node; \ +\ + while (1) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp < 0){ \ + SPLAY_ROTATE_RIGHT(head, __tmp, field); \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp > 0) { \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ +} + +#define SPLAY_NEGINF -1 +#define SPLAY_INF 1 + +#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y) +#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y) +#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y) +#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y) +#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \ + : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) +#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \ + : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) + +#define SPLAY_FOREACH(x, name, head) \ + for ((x) = SPLAY_MIN(name, head); \ + (x) != NULL; \ + (x) = SPLAY_NEXT(name, head, x)) + +/* Macros that define a red-black tree */ +#define RB_HEAD(name, type) \ +struct name { \ + struct type *rbh_root; /* root of the tree */ \ +} + +#define RB_INITIALIZER(root) \ + { NULL } + +#define RB_INIT(root) do { \ + (root)->rbh_root = NULL; \ +} while (/*CONSTCOND*/ 0) + +#define RB_BLACK 0 +#define RB_RED 1 +#define RB_ENTRY(type) \ +struct { \ + struct type *rbe_left; /* left element */ \ + struct type *rbe_right; /* right element */ \ + struct type *rbe_parent; /* parent element */ \ + int rbe_color; /* node color */ \ +} + +#define RB_LEFT(elm, field) (elm)->field.rbe_left +#define RB_RIGHT(elm, field) (elm)->field.rbe_right +#define RB_PARENT(elm, field) (elm)->field.rbe_parent +#define RB_COLOR(elm, field) (elm)->field.rbe_color +#define RB_ROOT(head) (head)->rbh_root +#define RB_EMPTY(head) (RB_ROOT(head) == NULL) + +#define RB_SET(elm, parent, field) do { \ + RB_PARENT(elm, field) = parent; \ + RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \ + RB_COLOR(elm, field) = RB_RED; \ +} while (/*CONSTCOND*/ 0) + +#define RB_SET_BLACKRED(black, red, field) do { \ + RB_COLOR(black, field) = RB_BLACK; \ + RB_COLOR(red, field) = RB_RED; \ +} while (/*CONSTCOND*/ 0) + +#ifndef RB_AUGMENT +#define RB_AUGMENT(x) do {} while (0) +#endif + +#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \ + (tmp) = RB_RIGHT(elm, field); \ + if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \ + RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ + RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ + } else \ + (head)->rbh_root = (tmp); \ + RB_LEFT(tmp, field) = (elm); \ + RB_PARENT(elm, field) = (tmp); \ + RB_AUGMENT(tmp); \ + if ((RB_PARENT(tmp, field))) \ + RB_AUGMENT(RB_PARENT(tmp, field)); \ +} while (/*CONSTCOND*/ 0) + +#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \ + (tmp) = RB_LEFT(elm, field); \ + if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \ + RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ + RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ + } else \ + (head)->rbh_root = (tmp); \ + RB_RIGHT(tmp, field) = (elm); \ + RB_PARENT(elm, field) = (tmp); \ + RB_AUGMENT(tmp); \ + if ((RB_PARENT(tmp, field))) \ + RB_AUGMENT(RB_PARENT(tmp, field)); \ +} while (/*CONSTCOND*/ 0) + +/* Generates prototypes and inline functions */ +#define RB_PROTOTYPE(name, type, field, cmp) \ + RB_PROTOTYPE_INTERNAL(name, type, field, cmp,) +#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \ + RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static) +#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \ + RB_PROTOTYPE_INSERT_COLOR(name, type, attr); \ + RB_PROTOTYPE_REMOVE_COLOR(name, type, attr); \ + RB_PROTOTYPE_INSERT(name, type, attr); \ + RB_PROTOTYPE_REMOVE(name, type, attr); \ + RB_PROTOTYPE_FIND(name, type, attr); \ + RB_PROTOTYPE_NFIND(name, type, attr); \ + RB_PROTOTYPE_NEXT(name, type, attr); \ + RB_PROTOTYPE_PREV(name, type, attr); \ + RB_PROTOTYPE_MINMAX(name, type, attr); +#define RB_PROTOTYPE_INSERT_COLOR(name, type, attr) \ + attr void name##_RB_INSERT_COLOR(struct name *, struct type *) +#define RB_PROTOTYPE_REMOVE_COLOR(name, type, attr) \ + attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *) +#define RB_PROTOTYPE_REMOVE(name, type, attr) \ + attr struct type *name##_RB_REMOVE(struct name *, struct type *) +#define RB_PROTOTYPE_INSERT(name, type, attr) \ + attr struct type *name##_RB_INSERT(struct name *, struct type *) +#define RB_PROTOTYPE_FIND(name, type, attr) \ + attr struct type *name##_RB_FIND(struct name *, struct type *) +#define RB_PROTOTYPE_NFIND(name, type, attr) \ + attr struct type *name##_RB_NFIND(struct name *, struct type *) +#define RB_PROTOTYPE_NEXT(name, type, attr) \ + attr struct type *name##_RB_NEXT(struct type *) +#define RB_PROTOTYPE_PREV(name, type, attr) \ + attr struct type *name##_RB_PREV(struct type *) +#define RB_PROTOTYPE_MINMAX(name, type, attr) \ + attr struct type *name##_RB_MINMAX(struct name *, int) + +/* Main rb operation. + * Moves node close to the key of elm to top + */ +#define RB_GENERATE(name, type, field, cmp) \ + RB_GENERATE_INTERNAL(name, type, field, cmp,) +#define RB_GENERATE_STATIC(name, type, field, cmp) \ + RB_GENERATE_INTERNAL(name, type, field, cmp, __unused static) +#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \ + RB_GENERATE_INSERT_COLOR(name, type, field, attr) \ + RB_GENERATE_REMOVE_COLOR(name, type, field, attr) \ + RB_GENERATE_INSERT(name, type, field, cmp, attr) \ + RB_GENERATE_REMOVE(name, type, field, attr) \ + RB_GENERATE_FIND(name, type, field, cmp, attr) \ + RB_GENERATE_NFIND(name, type, field, cmp, attr) \ + RB_GENERATE_NEXT(name, type, field, attr) \ + RB_GENERATE_PREV(name, type, field, attr) \ + RB_GENERATE_MINMAX(name, type, field, attr) + +#define RB_GENERATE_INSERT_COLOR(name, type, field, attr) \ +attr void \ +name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \ +{ \ + struct type *parent, *gparent, *tmp; \ + while ((parent = RB_PARENT(elm, field)) != NULL && \ + RB_COLOR(parent, field) == RB_RED) { \ + gparent = RB_PARENT(parent, field); \ + if (parent == RB_LEFT(gparent, field)) { \ + tmp = RB_RIGHT(gparent, field); \ + if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ + RB_COLOR(tmp, field) = RB_BLACK; \ + RB_SET_BLACKRED(parent, gparent, field);\ + elm = gparent; \ + continue; \ + } \ + if (RB_RIGHT(parent, field) == elm) { \ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + tmp = parent; \ + parent = elm; \ + elm = tmp; \ + } \ + RB_SET_BLACKRED(parent, gparent, field); \ + RB_ROTATE_RIGHT(head, gparent, tmp, field); \ + } else { \ + tmp = RB_LEFT(gparent, field); \ + if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ + RB_COLOR(tmp, field) = RB_BLACK; \ + RB_SET_BLACKRED(parent, gparent, field);\ + elm = gparent; \ + continue; \ + } \ + if (RB_LEFT(parent, field) == elm) { \ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + tmp = parent; \ + parent = elm; \ + elm = tmp; \ + } \ + RB_SET_BLACKRED(parent, gparent, field); \ + RB_ROTATE_LEFT(head, gparent, tmp, field); \ + } \ + } \ + RB_COLOR(head->rbh_root, field) = RB_BLACK; \ +} + +#define RB_GENERATE_REMOVE_COLOR(name, type, field, attr) \ +attr void \ +name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \ +{ \ + struct type *tmp; \ + while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \ + elm != RB_ROOT(head)) { \ + if (RB_LEFT(parent, field) == elm) { \ + tmp = RB_RIGHT(parent, field); \ + if (RB_COLOR(tmp, field) == RB_RED) { \ + RB_SET_BLACKRED(tmp, parent, field); \ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + tmp = RB_RIGHT(parent, field); \ + } \ + if ((RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ + (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ + RB_COLOR(tmp, field) = RB_RED; \ + elm = parent; \ + parent = RB_PARENT(elm, field); \ + } else { \ + if (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\ + struct type *oleft; \ + if ((oleft = RB_LEFT(tmp, field)) \ + != NULL) \ + RB_COLOR(oleft, field) = RB_BLACK;\ + RB_COLOR(tmp, field) = RB_RED; \ + RB_ROTATE_RIGHT(head, tmp, oleft, field);\ + tmp = RB_RIGHT(parent, field); \ + } \ + RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ + RB_COLOR(parent, field) = RB_BLACK; \ + if (RB_RIGHT(tmp, field)) \ + RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + elm = RB_ROOT(head); \ + break; \ + } \ + } else { \ + tmp = RB_LEFT(parent, field); \ + if (RB_COLOR(tmp, field) == RB_RED) { \ + RB_SET_BLACKRED(tmp, parent, field); \ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + tmp = RB_LEFT(parent, field); \ + } \ + if ((RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ + (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ + RB_COLOR(tmp, field) = RB_RED; \ + elm = parent; \ + parent = RB_PARENT(elm, field); \ + } else { \ + if (RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\ + struct type *oright; \ + if ((oright = RB_RIGHT(tmp, field)) \ + != NULL) \ + RB_COLOR(oright, field) = RB_BLACK;\ + RB_COLOR(tmp, field) = RB_RED; \ + RB_ROTATE_LEFT(head, tmp, oright, field);\ + tmp = RB_LEFT(parent, field); \ + } \ + RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ + RB_COLOR(parent, field) = RB_BLACK; \ + if (RB_LEFT(tmp, field)) \ + RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + elm = RB_ROOT(head); \ + break; \ + } \ + } \ + } \ + if (elm) \ + RB_COLOR(elm, field) = RB_BLACK; \ +} + +#define RB_GENERATE_REMOVE(name, type, field, attr) \ +attr struct type * \ +name##_RB_REMOVE(struct name *head, struct type *elm) \ +{ \ + struct type *child, *parent, *old = elm; \ + int color; \ + if (RB_LEFT(elm, field) == NULL) \ + child = RB_RIGHT(elm, field); \ + else if (RB_RIGHT(elm, field) == NULL) \ + child = RB_LEFT(elm, field); \ + else { \ + struct type *left; \ + elm = RB_RIGHT(elm, field); \ + while ((left = RB_LEFT(elm, field)) != NULL) \ + elm = left; \ + child = RB_RIGHT(elm, field); \ + parent = RB_PARENT(elm, field); \ + color = RB_COLOR(elm, field); \ + if (child) \ + RB_PARENT(child, field) = parent; \ + if (parent) { \ + if (RB_LEFT(parent, field) == elm) \ + RB_LEFT(parent, field) = child; \ + else \ + RB_RIGHT(parent, field) = child; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = child; \ + if (RB_PARENT(elm, field) == old) \ + parent = elm; \ + (elm)->field = (old)->field; \ + if (RB_PARENT(old, field)) { \ + if (RB_LEFT(RB_PARENT(old, field), field) == old)\ + RB_LEFT(RB_PARENT(old, field), field) = elm;\ + else \ + RB_RIGHT(RB_PARENT(old, field), field) = elm;\ + RB_AUGMENT(RB_PARENT(old, field)); \ + } else \ + RB_ROOT(head) = elm; \ + RB_PARENT(RB_LEFT(old, field), field) = elm; \ + if (RB_RIGHT(old, field)) \ + RB_PARENT(RB_RIGHT(old, field), field) = elm; \ + if (parent) { \ + left = parent; \ + do { \ + RB_AUGMENT(left); \ + } while ((left = RB_PARENT(left, field)) != NULL); \ + } \ + goto color; \ + } \ + parent = RB_PARENT(elm, field); \ + color = RB_COLOR(elm, field); \ + if (child) \ + RB_PARENT(child, field) = parent; \ + if (parent) { \ + if (RB_LEFT(parent, field) == elm) \ + RB_LEFT(parent, field) = child; \ + else \ + RB_RIGHT(parent, field) = child; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = child; \ +color: \ + if (color == RB_BLACK) \ + name##_RB_REMOVE_COLOR(head, parent, child); \ + return (old); \ +} \ + +#define RB_GENERATE_INSERT(name, type, field, cmp, attr) \ +/* Inserts a node into the RB tree */ \ +attr struct type * \ +name##_RB_INSERT(struct name *head, struct type *elm) \ +{ \ + struct type *tmp; \ + struct type *parent = NULL; \ + int comp = 0; \ + tmp = RB_ROOT(head); \ + while (tmp) { \ + parent = tmp; \ + comp = (cmp)(elm, parent); \ + if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + RB_SET(elm, parent, field); \ + if (parent != NULL) { \ + if (comp < 0) \ + RB_LEFT(parent, field) = elm; \ + else \ + RB_RIGHT(parent, field) = elm; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = elm; \ + name##_RB_INSERT_COLOR(head, elm); \ + return (NULL); \ +} + +#define RB_GENERATE_FIND(name, type, field, cmp, attr) \ +/* Finds the node with the same key as elm */ \ +attr struct type * \ +name##_RB_FIND(struct name *head, struct type *elm) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + int comp; \ + while (tmp) { \ + comp = cmp(elm, tmp); \ + if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + return (NULL); \ +} + +#define RB_GENERATE_NFIND(name, type, field, cmp, attr) \ +/* Finds the first node greater than or equal to the search key */ \ +attr struct type * \ +name##_RB_NFIND(struct name *head, struct type *elm) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + struct type *res = NULL; \ + int comp; \ + while (tmp) { \ + comp = cmp(elm, tmp); \ + if (comp < 0) { \ + res = tmp; \ + tmp = RB_LEFT(tmp, field); \ + } \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + return (res); \ +} + +#define RB_GENERATE_NEXT(name, type, field, attr) \ +/* ARGSUSED */ \ +attr struct type * \ +name##_RB_NEXT(struct type *elm) \ +{ \ + if (RB_RIGHT(elm, field)) { \ + elm = RB_RIGHT(elm, field); \ + while (RB_LEFT(elm, field)) \ + elm = RB_LEFT(elm, field); \ + } else { \ + if (RB_PARENT(elm, field) && \ + (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ + elm = RB_PARENT(elm, field); \ + else { \ + while (RB_PARENT(elm, field) && \ + (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\ + elm = RB_PARENT(elm, field); \ + elm = RB_PARENT(elm, field); \ + } \ + } \ + return (elm); \ +} + +#define RB_GENERATE_PREV(name, type, field, attr) \ +/* ARGSUSED */ \ +attr struct type * \ +name##_RB_PREV(struct type *elm) \ +{ \ + if (RB_LEFT(elm, field)) { \ + elm = RB_LEFT(elm, field); \ + while (RB_RIGHT(elm, field)) \ + elm = RB_RIGHT(elm, field); \ + } else { \ + if (RB_PARENT(elm, field) && \ + (elm == RB_RIGHT(RB_PARENT(elm, field), field))) \ + elm = RB_PARENT(elm, field); \ + else { \ + while (RB_PARENT(elm, field) && \ + (elm == RB_LEFT(RB_PARENT(elm, field), field)))\ + elm = RB_PARENT(elm, field); \ + elm = RB_PARENT(elm, field); \ + } \ + } \ + return (elm); \ +} + +#define RB_GENERATE_MINMAX(name, type, field, attr) \ +attr struct type * \ +name##_RB_MINMAX(struct name *head, int val) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + struct type *parent = NULL; \ + while (tmp) { \ + parent = tmp; \ + if (val < 0) \ + tmp = RB_LEFT(tmp, field); \ + else \ + tmp = RB_RIGHT(tmp, field); \ + } \ + return (parent); \ +} + +#define RB_NEGINF -1 +#define RB_INF 1 + +#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y) +#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y) +#define RB_FIND(name, x, y) name##_RB_FIND(x, y) +#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y) +#define RB_NEXT(name, x, y) name##_RB_NEXT(y) +#define RB_PREV(name, x, y) name##_RB_PREV(y) +#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF) +#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF) + +#define RB_FOREACH(x, name, head) \ + for ((x) = RB_MIN(name, head); \ + (x) != NULL; \ + (x) = name##_RB_NEXT(x)) + +#define RB_FOREACH_FROM(x, name, y) \ + for ((x) = (y); \ + ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \ + (x) = (y)) + +#define RB_FOREACH_SAFE(x, name, head, y) \ + for ((x) = RB_MIN(name, head); \ + ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \ + (x) = (y)) + +#define RB_FOREACH_REVERSE(x, name, head) \ + for ((x) = RB_MAX(name, head); \ + (x) != NULL; \ + (x) = name##_RB_PREV(x)) + +#define RB_FOREACH_REVERSE_FROM(x, name, y) \ + for ((x) = (y); \ + ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \ + (x) = (y)) + +#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \ + for ((x) = RB_MAX(name, head); \ + ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \ + (x) = (y)) + +#endif /* _SYS_TREE_H_ */ diff --git a/stratosphere/libstratosphere/include/stratosphere.hpp b/stratosphere/libstratosphere/include/stratosphere.hpp new file mode 100644 index 000000000..000656cb6 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere.hpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "stratosphere/defines.hpp" + +#include "stratosphere/utilities.hpp" +#include "stratosphere/emummc_utilities.hpp" + +#include "stratosphere/scope_guard.hpp" + +#include "stratosphere/version_check.hpp" + +#include "stratosphere/auto_handle.hpp" +#include "stratosphere/hossynch.hpp" +#include "stratosphere/message_queue.hpp" +#include "stratosphere/iwaitable.hpp" +#include "stratosphere/event.hpp" + +#include "stratosphere/waitable_manager.hpp" + +#include "stratosphere/ipc.hpp" + +#include "stratosphere/mitm.hpp" + +#include "stratosphere/services.hpp" + +#include "stratosphere/results.hpp" + +#include "stratosphere/on_crash.hpp" + +#include "stratosphere/svc.hpp" +#include "stratosphere/cfg.hpp" +#include "stratosphere/hid.hpp" +#include "stratosphere/ncm.hpp" +#include "stratosphere/pm.hpp" +#include "stratosphere/rnd.hpp" +#include "stratosphere/sm.hpp" +#include "stratosphere/util.hpp" \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/auto_handle.hpp b/stratosphere/libstratosphere/include/stratosphere/auto_handle.hpp new file mode 100644 index 000000000..778465476 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/auto_handle.hpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include "defines.hpp" + +class AutoHandle { + NON_COPYABLE(AutoHandle); + private: + Handle hnd; + public: + AutoHandle() : hnd(INVALID_HANDLE) { /* ... */ } + AutoHandle(Handle h) : hnd(h) { /* ... */ } + ~AutoHandle() { + if (this->hnd != INVALID_HANDLE) { + svcCloseHandle(this->hnd); + this->hnd = INVALID_HANDLE; + } + } + + AutoHandle(AutoHandle&& rhs) { + this->hnd = rhs.hnd; + rhs.hnd = INVALID_HANDLE; + } + + AutoHandle& operator=(AutoHandle&& rhs) { + rhs.Swap(*this); + return *this; + } + + explicit operator bool() const { + return this->hnd != INVALID_HANDLE; + } + + void Swap(AutoHandle& rhs) { + std::swap(this->hnd, rhs.hnd); + } + + Handle Get() const { + return this->hnd; + } + + Handle *GetPointer() { + return &this->hnd; + } + + Handle *GetPointerAndClear() { + this->Clear(); + return this->GetPointer(); + } + + Handle Move() { + const Handle h = this->hnd; + this->hnd = INVALID_HANDLE; + return h; + } + + void Reset(Handle h) { + AutoHandle(h).Swap(*this); + } + + void Clear() { + this->Reset(INVALID_HANDLE); + } +}; diff --git a/stratosphere/libstratosphere/include/stratosphere/cfg.hpp b/stratosphere/libstratosphere/include/stratosphere/cfg.hpp new file mode 100644 index 000000000..e78dd8a17 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/cfg.hpp @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#include + +#include "cfg/cfg_api.hpp" diff --git a/stratosphere/libstratosphere/include/stratosphere/cfg/cfg_api.hpp b/stratosphere/libstratosphere/include/stratosphere/cfg/cfg_api.hpp new file mode 100644 index 000000000..9c5c8efe8 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/cfg/cfg_api.hpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#include +#include "../ncm/ncm_types.hpp" + +namespace sts::cfg { + + /* Privileged Process configuration. */ + bool IsInitialProcess(); + void GetInitialProcessRange(u64 *out_min, u64 *out_max); + + /* SD card configuration. */ + bool IsSdCardInitialized(); + void WaitSdCardInitialized(); + + /* Override key utilities. */ + bool IsTitleOverrideKeyHeld(ncm::TitleId title_id); + bool IsHblOverrideKeyHeld(ncm::TitleId title_id); + void GetOverrideKeyHeldStatus(bool *out_hbl, bool *out_title, ncm::TitleId title_id); + bool IsCheatEnableKeyHeld(ncm::TitleId title_id); + + /* Flag utilities. */ + bool HasFlag(ncm::TitleId title_id, const char *flag); + bool HasTitleSpecificFlag(ncm::TitleId title_id, const char *flag); + bool HasGlobalFlag(const char *flag); + + /* HBL Configuration utilities. */ + bool IsHblTitleId(ncm::TitleId title_id); + bool HasHblFlag(const char *flag); + const char *GetHblPath(); + +} diff --git a/stratosphere/libstratosphere/include/stratosphere/defines.hpp b/stratosphere/libstratosphere/include/stratosphere/defines.hpp new file mode 100644 index 000000000..5df9d6769 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/defines.hpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#include + +/* Any broadly useful language defines should go here. */ + +#define NON_COPYABLE(cls) \ + cls(const cls&) = delete; \ + cls& operator=(const cls&) = delete + +#define NON_MOVEABLE(cls) \ + cls(cls&&) = delete; \ + cls& operator=(cls&&) = delete + +#define ALIGNED(algn) __attribute__((aligned(algn))) +#define WEAK __attribute__((weak)) + +namespace sts::util { + + /* std::size() does not support zero-size C arrays. We're fixing that. */ + template + constexpr auto size(const C& c) -> decltype(c.size()) { + return std::size(c); + } + + template + constexpr std::size_t size(const C& c) { + if constexpr (sizeof(C) == 0) { + return 0; + } else { + return std::size(c); + } + } + +} \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/emummc_utilities.hpp b/stratosphere/libstratosphere/include/stratosphere/emummc_utilities.hpp new file mode 100644 index 000000000..d2b52e043 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/emummc_utilities.hpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#include +#include + +/* Get whether emummc is active. */ +bool IsEmummc(); + +/* Get Nintendo redirection path. */ +const char *GetEmummcNintendoDirPath(); + +/* Get Emummc folderpath, NULL if not file-based. */ +const char *GetEmummcFilePath(); diff --git a/stratosphere/libstratosphere/include/stratosphere/event.hpp b/stratosphere/libstratosphere/include/stratosphere/event.hpp new file mode 100644 index 000000000..aa33419cf --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/event.hpp @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#include +#include +#include + +#include "iwaitable.hpp" +#include "results.hpp" + +class IEvent : public IWaitable { + public: + /* Information members. */ + Handle r_h; + Handle w_h; + bool autoclear; + public: + IEvent(bool a = false) : r_h(INVALID_HANDLE), w_h(INVALID_HANDLE), autoclear(a) { } + IEvent(Handle r, bool a = false) : r_h(r), w_h(INVALID_HANDLE), autoclear(a) { } + IEvent(Handle r, Handle w, bool a = false) : r_h(r), w_h(w), autoclear(a) { } + + ~IEvent() { + if (r_h != INVALID_HANDLE) { + svcCloseHandle(r_h); + } + if (w_h != INVALID_HANDLE) { + svcCloseHandle(w_h); + } + } + + /* Make it non-copyable */ + IEvent() = delete; + IEvent(const IEvent &) = delete; + IEvent& operator=(const IEvent&) = delete; + + + bool IsAutoClear() { + return this->autoclear; + } + + void Clear() { + std::scoped_lock lock(this->sig_lock); + this->is_signaled = false; + if (this->w_h != INVALID_HANDLE) { + svcClearEvent(this->w_h); + } else if (this->r_h != INVALID_HANDLE) { + svcResetSignal(this->r_h); + } + } + + void Signal() { + std::scoped_lock lock(this->sig_lock); + + if (this->w_h == INVALID_HANDLE && this->r_h != INVALID_HANDLE) { + /* We can't signal an event if we only have a read handle. */ + std::abort(); + } + + if (this->w_h == INVALID_HANDLE && this->is_signaled) { + return; + } + + this->is_signaled = true; + + if (this->w_h != INVALID_HANDLE) { + svcSignalEvent(this->w_h); + } else { + this->NotifyManagerSignaled(); + } + } + + virtual Result HandleSignaled(u64 timeout) = 0; + + /* IWaitable */ + virtual Handle GetHandle() override { + return this->r_h; + } +}; + +template +class HosEvent : public IEvent { + private: + F callback; + public: + HosEvent(F f, bool a = false) : IEvent(a), callback(std::move(f)) { } + HosEvent(Handle r, F f, bool a = false) : IEvent(r, a), callback(std::move(f)) { } + HosEvent(Handle r, Handle w, F f, bool a = false) : IEvent(r, w, a), callback(std::move(f)) { } + + virtual Result HandleSignaled(u64 timeout) override { + if (this->IsAutoClear()) { + this->Clear(); + } + return this->callback(timeout); + } +}; + +template +static IEvent *CreateHosEvent(F f, bool autoclear = false) { + return new HosEvent(INVALID_HANDLE, INVALID_HANDLE, std::move(f), autoclear); +} + +template +static IEvent *CreateSystemEvent(F f, bool autoclear = false) { + Handle w_h, r_h; + R_ASSERT(svcCreateEvent(&w_h, &r_h)); + return new HosEvent(r_h, w_h, std::move(f), autoclear); +} + +template +static IEvent *CreateInterruptEvent(F f, u64 irq, bool autoclear = false) { + Handle r_h; + /* flag is "rising edge vs level". */ + R_ASSERT(svcCreateInterruptEvent(&r_h, irq, autoclear ? 0 : 1)); + return new HosEvent(r_h, INVALID_HANDLE, std::move(f), autoclear); +} + +template +static IEvent *CreateWriteOnlySystemEvent() { + return CreateSystemEvent([](u64 timeout) -> Result { std::abort(); }, a); +} + +template +static IEvent *LoadReadOnlySystemEvent(Handle r_h, F f, bool autoclear = false) { + return new HosEvent(r_h, f, autoclear); +} diff --git a/stratosphere/libstratosphere/include/stratosphere/firmware_version.hpp b/stratosphere/libstratosphere/include/stratosphere/firmware_version.hpp new file mode 100644 index 000000000..96fd89873 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/firmware_version.hpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +enum FirmwareVersion : u32 { + FirmwareVersion_Min = 0, + FirmwareVersion_100 = FirmwareVersion_Min, + FirmwareVersion_200 = 1, + FirmwareVersion_300 = 2, + FirmwareVersion_400 = 3, + FirmwareVersion_500 = 4, + FirmwareVersion_600 = 5, + FirmwareVersion_700 = 6, + FirmwareVersion_800 = 7, + FirmwareVersion_810 = 8, + FirmwareVersion_Current = FirmwareVersion_810, + FirmwareVersion_Max = 32, +}; + +enum AtmosphereTargetFirmware : u32 { + AtmosphereTargetFirmware_100 = 1, + AtmosphereTargetFirmware_200 = 2, + AtmosphereTargetFirmware_300 = 3, + AtmosphereTargetFirmware_400 = 4, + AtmosphereTargetFirmware_500 = 5, + AtmosphereTargetFirmware_600 = 6, + AtmosphereTargetFirmware_620 = 7, + AtmosphereTargetFirmware_700 = 8, + AtmosphereTargetFirmware_800 = 9, + AtmosphereTargetFirmware_810 = 10, +}; + +FirmwareVersion GetRuntimeFirmwareVersion(); + +void SetFirmwareVersionForLibnx(); \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/hid.hpp b/stratosphere/libstratosphere/include/stratosphere/hid.hpp new file mode 100644 index 000000000..bea31e2c9 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/hid.hpp @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#include + +#include "hid/hid_api.hpp" \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/hid/hid_api.hpp b/stratosphere/libstratosphere/include/stratosphere/hid/hid_api.hpp new file mode 100644 index 000000000..b1b97c63d --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/hid/hid_api.hpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +namespace sts::hid { + + /* Key API. */ + Result GetKeysHeld(u64 *out); + +} diff --git a/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp b/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp new file mode 100644 index 000000000..624dba803 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#include +#include +#include +#include "results.hpp" +#include "auto_handle.hpp" + +class HosMutex { + private: + Mutex m; + Mutex *GetMutex() { + return &this->m; + } + public: + HosMutex() { + mutexInit(GetMutex()); + } + + void lock() { + mutexLock(GetMutex()); + } + + void unlock() { + mutexUnlock(GetMutex()); + } + + bool try_lock() { + return mutexTryLock(GetMutex()); + } + + void Lock() { + lock(); + } + + void Unlock() { + unlock(); + } + + bool TryLock() { + return try_lock(); + } + + friend class HosCondVar; +}; + +class HosRecursiveMutex { + private: + RMutex m; + RMutex *GetMutex() { + return &this->m; + } + public: + HosRecursiveMutex() { + rmutexInit(GetMutex()); + } + + void lock() { + rmutexLock(GetMutex()); + } + + void unlock() { + rmutexUnlock(GetMutex()); + } + + bool try_lock() { + return rmutexTryLock(GetMutex()); + } + + void Lock() { + lock(); + } + + void Unlock() { + unlock(); + } + + bool TryLock() { + return try_lock(); + } +}; + +class HosCondVar { + private: + CondVar cv; + public: + HosCondVar() { + condvarInit(&cv); + } + + Result TimedWait(u64 timeout, HosMutex *hm) { + return TimedWait(timeout, hm->GetMutex()); + } + + Result Wait(HosMutex *hm) { + return Wait(hm->GetMutex()); + } + + Result TimedWait(u64 timeout, Mutex *m) { + return condvarWaitTimeout(&cv, m, timeout); + } + + Result Wait(Mutex *m) { + return condvarWait(&cv, m); + } + + Result Wake(int num) { + return condvarWake(&cv, num); + } + + Result WakeOne() { + return condvarWakeOne(&cv); + } + + Result WakeAll() { + return condvarWakeAll(&cv); + } +}; + +class HosSemaphore { + private: + Semaphore s; + public: + HosSemaphore() { + semaphoreInit(&s, 0); + } + + HosSemaphore(u64 c) { + semaphoreInit(&s, c); + } + + void Signal() { + semaphoreSignal(&s); + } + + void Wait() { + semaphoreWait(&s); + } + + bool TryWait() { + return semaphoreTryWait(&s); + } +}; + +class TimeoutHelper { + private: + u64 end_tick; + public: + TimeoutHelper(u64 ns) { + /* Special case zero-time timeouts. */ + if (ns == 0) { + end_tick = 0; + return; + } + + u64 cur_tick = armGetSystemTick(); + this->end_tick = cur_tick + NsToTick(ns) + 1; + } + + static inline u64 NsToTick(u64 ns) { + return (ns * 12) / 625; + } + + static inline u64 TickToNs(u64 tick) { + return (tick * 625) / 12; + } + + u64 NsUntilTimeout() { + u64 diff = TickToNs(this->end_tick - armGetSystemTick()); + + if (TimedOut()) { + return 0; + } + + return diff; + } + + bool TimedOut() { + if (this->end_tick == 0) { + return true; + } + + return armGetSystemTick() >= this->end_tick; + } +}; + +class HosSignal { + private: + CondVar cv; + Mutex m; + bool signaled; + public: + HosSignal() { + condvarInit(&cv); + mutexInit(&m); + signaled = false; + } + + void Signal() { + mutexLock(&m); + signaled = true; + condvarWakeAll(&cv); + mutexUnlock(&m); + } + + void Reset() { + mutexLock(&m); + signaled = false; + mutexUnlock(&m); + } + + void Wait() { + mutexLock(&m); + + while (!signaled) { + condvarWait(&cv, &m); + } + + mutexUnlock(&m); + } + + bool TryWait() { + mutexLock(&m); + bool success = signaled; + mutexUnlock(&m); + return success; + } + + Result TimedWait(u64 ns) { + mutexLock(&m); + TimeoutHelper timeout_helper(ns); + + while (!signaled) { + if (R_FAILED(condvarWaitTimeout(&cv, &m, timeout_helper.NsUntilTimeout()))) { + return false; + } + } + + mutexUnlock(&m); + return true; + } +}; + +class HosThread { + private: + Thread thr = {}; + public: + HosThread() {} + + Result Initialize(ThreadFunc entry, void *arg, size_t stack_sz, int prio, int cpuid = -2) { + return threadCreate(&this->thr, entry, arg, stack_sz, prio, cpuid); + } + + Handle GetHandle() const { + return this->thr.handle; + } + + Result Start() { + return threadStart(&this->thr); + } + + Result Join() { + R_TRY(threadWaitForExit(&this->thr)); + R_TRY(threadClose(&this->thr)); + return ResultSuccess; + } + + Result CancelSynchronization() { + return svcCancelSynchronization(this->thr.handle); + } +}; \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc.hpp new file mode 100644 index 000000000..09cdf25fb --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/ipc.hpp @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "ipc/ipc_service_object.hpp" +#include "ipc/ipc_serialization.hpp" + +#include "ipc/ipc_service_session.hpp" \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_buffers.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_buffers.hpp new file mode 100644 index 000000000..903ee4355 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_buffers.hpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#include +#include + +enum class IpcBufferType { + InBuffer, + OutBuffer, + InPointer, + OutPointer, +}; + +/* Base for In/Out Buffers. */ +struct IpcBufferBase {}; + +struct InOutBufferBase : public IpcBufferBase {}; + +/* Represents an A descriptor. */ +struct InBufferBase : public InOutBufferBase {}; + +template +struct InBuffer : public InBufferBase { + T *buffer; + size_t num_elements; + BufferType type; + static const BufferType expected_type = e_t; + + /* Convenience. */ + T& operator[](size_t i) const { + return buffer[i]; + } + + InBuffer(void *b, size_t n, BufferType t) : buffer((T *)b), num_elements(n/sizeof(T)), type(t) { } +}; + +/* Represents a B descriptor. */ +struct OutBufferBase : public InOutBufferBase {}; + +template +struct OutBuffer : OutBufferBase { + T *buffer; + size_t num_elements; + BufferType type; + static const BufferType expected_type = e_t; + + /* Convenience. */ + T& operator[](size_t i) const { + return buffer[i]; + } + + OutBuffer(void *b, size_t n, BufferType t) : buffer((T *)b), num_elements(n/sizeof(T)), type(t) { } +}; + +/* Represents an X descriptor. */ +struct InPointerBase : public IpcBufferBase {}; + +template +struct InPointer : public InPointerBase { + T *pointer; + size_t num_elements; + + /* Convenience. */ + T& operator[](size_t i) const { + return pointer[i]; + } + + InPointer(void *p, size_t n) : pointer((T *)p), num_elements(n/sizeof(T)) { } +}; + +/* Represents a C descriptor. */ +struct OutPointerWithServerSizeBase : public IpcBufferBase {}; + +template +struct OutPointerWithServerSize : public OutPointerWithServerSizeBase { + T *pointer; + static const size_t num_elements = N; + static const size_t element_size = sizeof(T); + + /* Convenience. */ + T& operator[](size_t i) const { + return pointer[i]; + } + + OutPointerWithServerSize(void *p) : pointer((T *)p) { } + OutPointerWithServerSize(void *p, size_t n) : pointer((T *)p) { } +}; + +struct OutPointerWithClientSizeBase : public IpcBufferBase {}; + +/* Represents a C descriptor with size in raw data. */ +template +struct OutPointerWithClientSize : public OutPointerWithClientSizeBase { + T *pointer; + size_t num_elements; + + /* Convenience. */ + T& operator[](size_t i) const { + return pointer[i]; + } + + OutPointerWithClientSize(void *p, size_t n) : pointer((T *)p), num_elements(n/sizeof(T)) { } +}; diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_domain_object.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_domain_object.hpp new file mode 100644 index 000000000..3cc9cbca2 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_domain_object.hpp @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#include +#include +#include +#include + +#include "ipc_service_object.hpp" + +class IDomainObject; + +class DomainManager { + public: + static constexpr u32 MinimumDomainId = 1; + public: + virtual std::shared_ptr AllocateDomain() = 0; + virtual void FreeDomain(IDomainObject *domain) = 0; + virtual Result ReserveObject(IDomainObject *domain, u32 *out_object_id) = 0; + virtual Result ReserveSpecificObject(IDomainObject *domain, u32 object_id) = 0; + virtual void SetObject(IDomainObject *domain, u32 object_id, ServiceObjectHolder&& holder) = 0; + virtual ServiceObjectHolder *GetObject(IDomainObject *domain, u32 object_id) = 0; + virtual Result FreeObject(IDomainObject *domain, u32 object_id) = 0; + virtual Result ForceFreeObject(u32 object_id) = 0; +}; + +class IDomainObject : public IServiceObject { + private: + DomainManager *manager; + public: + IDomainObject(DomainManager *m) : manager(m) {} + + virtual ~IDomainObject() override { + this->manager->FreeDomain(this); + } + + DomainManager *GetManager() { + return this->manager; + } + + ServiceObjectHolder *GetObject(u32 object_id) { + return this->manager->GetObject(this, object_id); + } + + Result ReserveObject(u32 *out_object_id) { + return this->manager->ReserveObject(this, out_object_id); + } + + Result ReserveSpecificObject(u32 object_id) { + return this->manager->ReserveSpecificObject(this, object_id); + } + + void SetObject(u32 object_id, ServiceObjectHolder&& holder) { + this->manager->SetObject(this, object_id, std::move(holder)); + } + + Result FreeObject(u32 object_id) { + return this->manager->FreeObject(this, object_id); + } + + Result ForceFreeObject(u32 object_id) { + return this->manager->ForceFreeObject(object_id); + } + + public: + DEFINE_SERVICE_DISPATCH_TABLE { + /* IDomainObject has no callable functions. */ + }; +}; + +static constexpr bool IsDomainObject(ServiceObjectHolder &holder) { + return holder.GetServiceId() == ServiceObjectId(); +} + +static constexpr bool IsDomainObject(ServiceObjectHolder *holder) { + return holder->GetServiceId() == ServiceObjectId(); +} + +/* Out for service impl. */ +template +class Out> : public OutSessionTag { + static_assert(std::is_base_of_v, "OutSessions must be shared_ptr!"); + + template + friend class Out; + + private: + std::shared_ptr *srv; + IDomainObject *domain = nullptr; + u32 *object_id = nullptr; + public: + Out>(std::shared_ptr *s, IDomainObject *dm, u32 *o) : srv(reinterpret_cast *>(s)), domain(dm), object_id(o) { } + + ServiceObjectHolder GetHolder() { + std::shared_ptr clone = *srv; + return ServiceObjectHolder(std::move(clone)); + } + + bool IsDomain() { + return domain != nullptr; + } + + u32 GetObjectId() { + return *object_id; + } + + void ChangeObjectId(u32 o) { + domain->ForceFreeObject(*object_id); + domain->ReserveSpecificObject(o); + *object_id = o; + } + + void SetValue(std::shared_ptr &&s) { + *this->srv = std::move(s); + } +}; diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_out.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_out.hpp new file mode 100644 index 000000000..aba2254ec --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_out.hpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#include +#include + +/* Declare false allowed struct. */ +template +struct AllowedOut : std::false_type {}; + +struct OutDataTag{}; +struct OutHandleTag{}; +struct OutSessionTag{}; + +/* Define out struct, so that we can get errors on enable_if */ +template +class Out { + static_assert(std::is_pod::value && !std::is_pod::value, "Invalid IPC Out Type!"); +}; + +template +class Out::value || AllowedOut::value>::type> : public OutDataTag { +private: + T *obj; +public: + Out(T *o) : obj(o) { } + + void SetValue(const T& t) { + *obj = t; + } + + const T& GetValue() { + return *obj; + } + + T *GetPointer() { + return obj; + } + + /* Convenience operators. */ + T& operator*() { + return *obj; + } + + T* operator->() { + return obj; + } +}; + +template +class Out { + static_assert(std::is_pod::value && !std::is_pod::value, "Invalid IPC Out Type (Raw Pointer)!"); +}; + +template +struct OutHelper; + +template +struct OutHelper> { + using type = T; +}; \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_response_context.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_response_context.hpp new file mode 100644 index 000000000..f1f874822 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_response_context.hpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#include + +#include "ipc_service_object.hpp" +#include "ipc_domain_object.hpp" + +#include "ipc_special.hpp" + +#include "ipc_session_manager_base.hpp" + +struct IpcResponseContext { + /* Request/Reply data. */ + IpcParsedCommand request; + IpcCommand reply; + u8 out_data[0x100]; + std::shared_ptr *out_objs[8]; + Handle out_object_server_handles[8]; + IpcHandle out_handles[8]; + u32 out_object_ids[8]; + IpcCommandType cmd_type; + u64 cmd_id; + Result rc; + /* Context. */ + SessionManagerBase *manager; + ServiceObjectHolder *obj_holder; + unsigned char *pb; + size_t pb_size; +}; \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp new file mode 100644 index 000000000..278626c30 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp @@ -0,0 +1,672 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#include +#include +#include +#include +#include +#include + +#include "../results.hpp" + +#include "ipc_out.hpp" +#include "ipc_buffers.hpp" +#include "ipc_special.hpp" + +#include "ipc_domain_object.hpp" + +#include "ipc_response_context.hpp" + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" + +template +struct TypeList{}; + +template +constexpr auto Concatenate(TypeList, TypeList) { + return TypeList{}; +} + +template