Compare commits
59 Commits
1600_suppo
...
1.5.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8274081e39 | ||
|
|
f1ad26ce84 | ||
|
|
e4c314146e | ||
|
|
52f00731d9 | ||
|
|
476d658a79 | ||
|
|
7263022bac | ||
|
|
e0e7aa1e2f | ||
|
|
bd9d8fff46 | ||
|
|
61e3f0b391 | ||
|
|
cd9b173318 | ||
|
|
a8df400825 | ||
|
|
68040e2922 | ||
|
|
8da4d14e15 | ||
|
|
e2ebf9c0ff | ||
|
|
5fb6f52b9e | ||
|
|
982389dceb | ||
|
|
f636596ee2 | ||
|
|
0a2440522f | ||
|
|
3292ea5970 | ||
|
|
33d42f4831 | ||
|
|
46094cfb3e | ||
|
|
618691a500 | ||
|
|
356d89244f | ||
|
|
1ce3611695 | ||
|
|
1ab8b23444 | ||
|
|
06b4738d54 | ||
|
|
b92c614347 | ||
|
|
99175c1149 | ||
|
|
8876eedfb0 | ||
|
|
bbcee8c77c | ||
|
|
f7915c2c05 | ||
|
|
668cabd4a2 | ||
|
|
d64ab354ad | ||
|
|
59b518783d | ||
|
|
6462101b6f | ||
|
|
0ea5dbcfbb | ||
|
|
bb6446aada | ||
|
|
e46e7e0eb1 | ||
|
|
cb89c66bd8 | ||
|
|
e85a512cf4 | ||
|
|
7d9fea01c3 | ||
|
|
406320f6ec | ||
|
|
aad2be0a01 | ||
|
|
25383db524 | ||
|
|
48f4c526f3 | ||
|
|
1279d236f3 | ||
|
|
008eb974d4 | ||
|
|
035cebef9d | ||
|
|
8db22967bf | ||
|
|
db510f96c3 | ||
|
|
6e2dd791b2 | ||
|
|
bff61c68ab | ||
|
|
ca7734ffaf | ||
|
|
ed22f802ee | ||
|
|
8ffc177b44 | ||
|
|
c058376b3b | ||
|
|
d5ebf13094 | ||
|
|
695c125721 | ||
|
|
e7e3e7b374 |
@@ -67,6 +67,10 @@
|
|||||||
; Note that this setting is ignored (and treated as 1) when htc is enabled.
|
; Note that this setting is ignored (and treated as 1) when htc is enabled.
|
||||||
; 0 = Disabled, 1 = Enabled
|
; 0 = Disabled, 1 = Enabled
|
||||||
; enable_log_manager = u8!0x0
|
; enable_log_manager = u8!0x0
|
||||||
|
; Controls whether the bluetooth pairing database is redirected to the SD card (shared across sysmmc/all emummcs)
|
||||||
|
; NOTE: On <13.0.0, the database size was 10 instead of 20; booting pre-13.0.0 will truncate the database.
|
||||||
|
; 0 = Disabled, 1 = Enabled
|
||||||
|
; enable_external_bluetooth_db = u8!0x0
|
||||||
[hbloader]
|
[hbloader]
|
||||||
; Controls the size of the homebrew heap when running as applet.
|
; Controls the size of the homebrew heap when running as applet.
|
||||||
; If set to zero, all available applet memory is used as heap.
|
; If set to zero, all available applet memory is used as heap.
|
||||||
|
|||||||
@@ -1,4 +1,26 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
## 1.5.1
|
||||||
|
+ `fatal` was updated to reduce memory footprint.
|
||||||
|
+ Starting in 16.0.0, official `fatal` has no framebuffer or rendering logic, and instead calls other system service commands to draw the screen.
|
||||||
|
+ However, these commands aren't usable by atmosphère (too small rendering window, bad color support).
|
||||||
|
+ To reduce the relative memory footprint differential between atmosphère and official code, the framebuffer (2 MB) is now dynamically allocated when needed.
|
||||||
|
+ This will try to allocate from multiple pools (preferring System > System_NonSecure > Application).
|
||||||
|
+ This technically requires that 2 MB be available in at least one of these pools for the fatal screen to render (otherwise, a reboot-to-black-and-white-fatal will occur), but this should be a non-issue in almost all cases.
|
||||||
|
+ A feature was added to optionally mirror the bluetooth pairing database to the SD card (thanks @ndeadly).
|
||||||
|
+ This allows device pairings to be automatically kept in-sync across sysmmc/all emummcs.
|
||||||
|
+ This is opt-in, and can be controlled by setting `atmosphere!enable_external_bluetooth_db = u8!0x1`.
|
||||||
|
+ When enabled, the pairing database will be synchronized to `/atmosphere/bluetooth_devices.db`.
|
||||||
|
+ General system stability improvements to enhance the user's experience.
|
||||||
|
## 1.5.0
|
||||||
|
+ Support was added for 16.0.0
|
||||||
|
+ `mesosphère` was updated to reflect the latest official kernel behavior.
|
||||||
|
+ `ncm` was updated to reflect the latest official behavior.
|
||||||
|
+ Many FS apis were updated under the hood to reflect the latest official behavior.
|
||||||
|
+ **Please Note**: 16.0.0 made breaking changes to a number of system APIs, including in FS/NCM/Shared Font commands that some homebrew programs may use.
|
||||||
|
+ These programs may encounter strange errors, and may need to be recompiled with a libnx updated to support 16.0.0's changes to function properly.
|
||||||
|
+ A number of minor issues were fixed and improvements were made, including:
|
||||||
|
+ An issue was fixed that could cause GPIO outputs to be misconfigured under certain circumstances.
|
||||||
|
+ General system stability improvements to enhance the user's experience.
|
||||||
## 1.4.1
|
## 1.4.1
|
||||||
+ A number of minor issues were fixed and improvements were made, including:
|
+ A number of minor issues were fixed and improvements were made, including:
|
||||||
+ `dmnt` cheat toggle files are no longer ignored when they are missing a trailing newline.
|
+ `dmnt` cheat toggle files are no longer ignored when they are missing a trailing newline.
|
||||||
@@ -15,7 +37,7 @@
|
|||||||
## 1.4.0
|
## 1.4.0
|
||||||
+ Support was added for 15.0.0.
|
+ Support was added for 15.0.0.
|
||||||
+ `mesosphère` was updated to reflect the latest official kernel behavior.
|
+ `mesosphère` was updated to reflect the latest official kernel behavior.
|
||||||
+ `ncm` was updated to reflect the latest official kernel behavior.
|
+ `ncm` was updated to reflect the latest official behavior.
|
||||||
+ A number of minor issues were fixed and improvements were made, including:
|
+ A number of minor issues were fixed and improvements were made, including:
|
||||||
+ The capacity limit on registered add-on contents was fixed in NCM to reflect the increase that occurred in 12.0.0.
|
+ The capacity limit on registered add-on contents was fixed in NCM to reflect the increase that occurred in 12.0.0.
|
||||||
+ An off-by-one was fixed in mesosphere when computing the new value for an address arbiter signaled with ModifyByWaitingCountIfEqual.
|
+ An off-by-one was fixed in mesosphere when computing the new value for an address arbiter signaled with ModifyByWaitingCountIfEqual.
|
||||||
|
|||||||
4
emummc/.gitrepo
vendored
4
emummc/.gitrepo
vendored
@@ -6,7 +6,7 @@
|
|||||||
[subrepo]
|
[subrepo]
|
||||||
remote = https://github.com/m4xw/emummc
|
remote = https://github.com/m4xw/emummc
|
||||||
branch = develop
|
branch = develop
|
||||||
commit = 4714b2df9eaf68fb85516b35f7f4265ab0413825
|
commit = bba1f1fb65f75721caf6d023a35d75d3c9aafd0f
|
||||||
parent = 99f6a96845b6097d50f5059eea9245d27876f26a
|
parent = 1ab8b234447864503e21c600681219a96962e6c1
|
||||||
method = merge
|
method = merge
|
||||||
cmdver = 0.4.1
|
cmdver = 0.4.1
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
[subrepo]
|
[subrepo]
|
||||||
remote = https://github.com/Atmosphere-NX/Atmosphere-libs
|
remote = https://github.com/Atmosphere-NX/Atmosphere-libs
|
||||||
branch = master
|
branch = master
|
||||||
commit = b7711b8fbcec5013e1738218267d69b2cb44f85e
|
commit = b1607dc8a3d85bc8c859c60d70ebb4a3dcbb85b8
|
||||||
parent = 590f22933db38f089ab2224f7fd86658a9533e8d
|
parent = f1ad26ce844ab7a63b948281b50c12e5d1dac8ce
|
||||||
method = merge
|
method = merge
|
||||||
cmdver = 0.4.1
|
cmdver = 0.4.1
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
export ATMOSPHERE_DEFINES += -DATMOSPHERE_OS_WINDOWS
|
export ATMOSPHERE_DEFINES += -DATMOSPHERE_OS_WINDOWS
|
||||||
export ATMOSPHERE_SETTINGS += -fno-omit-frame-pointer
|
export ATMOSPHERE_SETTINGS += -fno-omit-frame-pointer -fno-data-sections
|
||||||
export ATMOSPHERE_CFLAGS +=
|
export ATMOSPHERE_CFLAGS +=
|
||||||
export ATMOSPHERE_CXXFLAGS +=
|
export ATMOSPHERE_CXXFLAGS +=
|
||||||
export ATMOSPHERE_ASFLAGS +=
|
export ATMOSPHERE_ASFLAGS +=
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export CXXWRAPS := -Wl,--wrap,__cxa_pure_virtual \
|
|||||||
-Wl,--wrap,exit
|
-Wl,--wrap,exit
|
||||||
else ifeq ($(ATMOSPHERE_BOARD),generic_windows)
|
else ifeq ($(ATMOSPHERE_BOARD),generic_windows)
|
||||||
export CXXREQUIRED :=
|
export CXXREQUIRED :=
|
||||||
export CXXWRAPS := -Wl,--wrap,__p__acmdln
|
export CXXWRAPS := -Wl,--wrap,__p__acmdln -Wl,--wrap,_set_invalid_parameter_handler
|
||||||
else
|
else
|
||||||
export CXXREQUIRED :=
|
export CXXREQUIRED :=
|
||||||
export CXXWRAPS :=
|
export CXXWRAPS :=
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ namespace ams::kern {
|
|||||||
/* Check that the object is closed. */
|
/* Check that the object is closed. */
|
||||||
R_UNLESS(derived->IsServerClosed(), svc::ResultInvalidState());
|
R_UNLESS(derived->IsServerClosed(), svc::ResultInvalidState());
|
||||||
|
|
||||||
return Delete(obj.GetPointerUnsafe(), name);
|
R_RETURN(Delete(obj.GetPointerUnsafe(), name));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived> requires std::derived_from<Derived, KAutoObject>
|
template<typename Derived> requires std::derived_from<Derived, KAutoObject>
|
||||||
|
|||||||
@@ -234,11 +234,11 @@ namespace ams::kern {
|
|||||||
KPriorityQueueImpl m_scheduled_queue;
|
KPriorityQueueImpl m_scheduled_queue;
|
||||||
KPriorityQueueImpl m_suggested_queue;
|
KPriorityQueueImpl m_suggested_queue;
|
||||||
private:
|
private:
|
||||||
constexpr ALWAYS_INLINE void ClearAffinityBit(u64 &affinity, s32 core) {
|
static constexpr ALWAYS_INLINE void ClearAffinityBit(u64 &affinity, s32 core) {
|
||||||
affinity &= ~(UINT64_C(1) << core);
|
affinity &= ~(UINT64_C(1) << core);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE s32 GetNextCore(u64 &affinity) {
|
static constexpr ALWAYS_INLINE s32 GetNextCore(u64 &affinity) {
|
||||||
const s32 core = __builtin_ctzll(static_cast<unsigned long long>(affinity));
|
const s32 core = __builtin_ctzll(static_cast<unsigned long long>(affinity));
|
||||||
ClearAffinityBit(affinity, core);
|
ClearAffinityBit(affinity, core);
|
||||||
return core;
|
return core;
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ namespace ams::kern {
|
|||||||
template<typename T> requires (std::same_as<T, KThread> || std::same_as<T, RedBlackKeyType>)
|
template<typename T> requires (std::same_as<T, KThread> || std::same_as<T, RedBlackKeyType>)
|
||||||
static constexpr ALWAYS_INLINE int Compare(const T &lhs, const KThread &rhs) {
|
static constexpr ALWAYS_INLINE int Compare(const T &lhs, const KThread &rhs) {
|
||||||
if (lhs.GetPriority() < rhs.GetPriority()) {
|
if (lhs.GetPriority() < rhs.GetPriority()) {
|
||||||
/* And then by priority. */
|
/* Sort by priority. */
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ namespace ams::kern {
|
|||||||
|
|
||||||
/* Sleep the thread. */
|
/* Sleep the thread. */
|
||||||
{
|
{
|
||||||
KScopedSchedulerLockAndSleep lk(&timer, owner, timeout);
|
KScopedSchedulerLockAndSleep lk(std::addressof(timer), owner, timeout);
|
||||||
|
|
||||||
if (!allow_terminating_thread && owner->IsTerminationRequested()) {
|
if (!allow_terminating_thread && owner->IsTerminationRequested()) {
|
||||||
lk.CancelSleep();
|
lk.CancelSleep();
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#include <stratosphere/os/os_process_memory_api.hpp>
|
#include <stratosphere/os/os_process_memory_api.hpp>
|
||||||
#include <stratosphere/os/os_process_code_memory_api.hpp>
|
#include <stratosphere/os/os_process_code_memory_api.hpp>
|
||||||
#include <stratosphere/os/os_insecure_memory_api.hpp>
|
#include <stratosphere/os/os_insecure_memory_api.hpp>
|
||||||
|
#include <stratosphere/os/os_unsafe_memory_api.hpp>
|
||||||
#include <stratosphere/os/os_random.hpp>
|
#include <stratosphere/os/os_random.hpp>
|
||||||
#include <stratosphere/os/os_mutex.hpp>
|
#include <stratosphere/os/os_mutex.hpp>
|
||||||
#include <stratosphere/os/os_condition_variable.hpp>
|
#include <stratosphere/os/os_condition_variable.hpp>
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <stratosphere/os/os_memory_common.hpp>
|
||||||
|
|
||||||
|
namespace ams::os {
|
||||||
|
|
||||||
|
Result AllocateUnsafeMemory(uintptr_t *out_address, size_t size);
|
||||||
|
Result FreeUnsafeMemory(uintptr_t address, size_t size);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -235,4 +235,31 @@ namespace ams::settings {
|
|||||||
return !(lhs <= rhs);
|
return !(lhs <= rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct BluetoothDevicesSettings : public sf::LargeData {
|
||||||
|
u8 address[0x6];
|
||||||
|
char name[0x20];
|
||||||
|
u8 class_of_device[0x3];
|
||||||
|
u8 link_key[0x10];
|
||||||
|
u8 link_key_present;
|
||||||
|
u16 version;
|
||||||
|
u32 trusted_services;
|
||||||
|
u16 vid;
|
||||||
|
u16 pid;
|
||||||
|
u8 sub_class;
|
||||||
|
u8 attribute_mask;
|
||||||
|
u16 descriptor_length;
|
||||||
|
u8 descriptor[0x80];
|
||||||
|
u8 key_type;
|
||||||
|
u8 device_type;
|
||||||
|
u16 brr_size;
|
||||||
|
u8 brr[0x9];
|
||||||
|
u8 reserved0;
|
||||||
|
char name2[0xF9];
|
||||||
|
u8 reserved1[0x31];
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(ATMOSPHERE_OS_HORIZON)
|
||||||
|
static_assert(sizeof(BluetoothDevicesSettings) == sizeof(::SetSysBluetoothDevicesSettings));
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -154,10 +154,12 @@ spl_secure_monitor_api.os.generic.o: CXXFLAGS += -I$(ATMOSPHERE_LIBRARIES_DIR)/l
|
|||||||
fs_id_string_impl.os.generic.o: CXXFLAGS += -I$(ATMOSPHERE_LIBRARIES_DIR)/libexosphere/include
|
fs_id_string_impl.os.generic.o: CXXFLAGS += -I$(ATMOSPHERE_LIBRARIES_DIR)/libexosphere/include
|
||||||
|
|
||||||
ifeq ($(ATMOSPHERE_OS_NAME),windows)
|
ifeq ($(ATMOSPHERE_OS_NAME),windows)
|
||||||
os_%.o: CXXFLAGS += -fno-lto
|
# I do not remember why these had fno-lto, but it appears to
|
||||||
fssystem_%.o: CXXFLAGS += -fno-lto
|
# work without no-lto (2023/03/09), so I am disabling these. I may regret this later.
|
||||||
fssrv_%.o: CXXFLAGS += -fno-lto
|
#os_%.o: CXXFLAGS += -fno-lto
|
||||||
fs_%.o: CXXFLAGS += -fno-lto
|
#fssystem_%.o: CXXFLAGS += -fno-lto
|
||||||
|
#fssrv_%.o: CXXFLAGS += -fno-lto
|
||||||
|
#fs_%.o: CXXFLAGS += -fno-lto
|
||||||
endif
|
endif
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include <stratosphere.hpp>
|
#include <stratosphere.hpp>
|
||||||
|
|
||||||
extern "C" char **__real___p__acmdln(void);
|
extern "C" char **__real___p__acmdln(void);
|
||||||
|
extern "C" _invalid_parameter_handler __real__set_invalid_parameter_handler(_invalid_parameter_handler);
|
||||||
|
|
||||||
namespace ams {
|
namespace ams {
|
||||||
|
|
||||||
@@ -65,4 +66,11 @@ extern "C" {
|
|||||||
return __real___p__acmdln();
|
return __real___p__acmdln();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* On some mingw gcc versions, acmdln isn't used, so we need to hook a different part of crt init. */
|
||||||
|
_invalid_parameter_handler __wrap__set_invalid_parameter_handler(_invalid_parameter_handler handler) {
|
||||||
|
::ams::os::Initialize();
|
||||||
|
return __real__set_invalid_parameter_handler(handler);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace ams::erpt::srv {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Context::Context(CategoryId cat, u32 max_records) : m_category(cat), m_max_record_count(max_records), m_record_count(0) {
|
Context::Context(CategoryId cat) : m_category(cat) {
|
||||||
g_category_list.push_front(*this);
|
g_category_list.push_front(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,12 +38,11 @@ namespace ams::erpt::srv {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result Context::AddCategoryToReport(Report *report) {
|
Result Context::AddCategoryToReport(Report *report) {
|
||||||
R_SUCCEED_IF(m_record_list.empty());
|
if (m_record != nullptr) {
|
||||||
|
const auto *entry = m_record->GetContextEntryPtr();
|
||||||
for (auto it = m_record_list.begin(); it != m_record_list.end(); it++) {
|
for (u32 i = 0; i < entry->field_count; i++) {
|
||||||
for (u32 i = 0; i < it->m_ctx.field_count; i++) {
|
auto *field = std::addressof(entry->fields[i]);
|
||||||
auto *field = std::addressof(it->m_ctx.fields[i]);
|
u8 *arr_buf = entry->array_buffer;
|
||||||
u8 *arr_buf = it->m_ctx.array_buffer;
|
|
||||||
|
|
||||||
switch (field->type) {
|
switch (field->type) {
|
||||||
case FieldType_Bool: R_TRY(Cipher::AddField(report, field->id, field->value_bool)); break;
|
case FieldType_Bool: R_TRY(Cipher::AddField(report, field->id, field->value_bool)); break;
|
||||||
@@ -70,46 +69,23 @@ namespace ams::erpt::srv {
|
|||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Context::AddContextToCategory(const ContextEntry *entry, const u8 *data, u32 data_size) {
|
Result Context::SubmitContext(const ContextEntry *entry, const u8 *data, u32 data_size) {
|
||||||
auto record = std::make_unique<ContextRecord>();
|
auto record = std::make_unique<ContextRecord>();
|
||||||
R_UNLESS(record != nullptr, erpt::ResultOutOfMemory());
|
R_UNLESS(record != nullptr, erpt::ResultOutOfMemory());
|
||||||
|
|
||||||
R_TRY(record->Initialize(entry, data, data_size));
|
R_TRY(record->Initialize(entry, data, data_size));
|
||||||
|
|
||||||
this->AddContextRecordToCategory(std::move(record));
|
R_RETURN(SubmitContextRecord(std::move(record)));
|
||||||
R_SUCCEED();
|
|
||||||
}
|
|
||||||
|
|
||||||
Result Context::AddContextRecordToCategory(std::unique_ptr<ContextRecord> record) {
|
|
||||||
if (m_record_count < m_max_record_count) {
|
|
||||||
m_record_list.push_front(*record.release());
|
|
||||||
m_record_count++;
|
|
||||||
} else {
|
|
||||||
ContextRecord *back = std::addressof(m_record_list.back());
|
|
||||||
m_record_list.pop_back();
|
|
||||||
m_record_list.push_front(*record.release());
|
|
||||||
delete back;
|
|
||||||
}
|
|
||||||
|
|
||||||
R_SUCCEED();
|
|
||||||
}
|
|
||||||
|
|
||||||
Result Context::SubmitContext(const ContextEntry *entry, const u8 *data, u32 data_size) {
|
|
||||||
auto it = util::range::find_if(g_category_list, [&](const Context &cur) {
|
|
||||||
return cur.m_category == entry->category;
|
|
||||||
});
|
|
||||||
R_UNLESS(it != g_category_list.end(), erpt::ResultCategoryNotFound());
|
|
||||||
|
|
||||||
R_RETURN(it->AddContextToCategory(entry, data, data_size));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Context::SubmitContextRecord(std::unique_ptr<ContextRecord> record) {
|
Result Context::SubmitContextRecord(std::unique_ptr<ContextRecord> record) {
|
||||||
auto it = util::range::find_if(g_category_list, [&](const Context &cur) {
|
auto it = util::range::find_if(g_category_list, [&](const Context &cur) {
|
||||||
return cur.m_category == record->m_ctx.category;
|
return cur.m_category == record->GetContextEntryPtr()->category;
|
||||||
});
|
});
|
||||||
R_UNLESS(it != g_category_list.end(), erpt::ResultCategoryNotFound());
|
R_UNLESS(it != g_category_list.end(), erpt::ResultCategoryNotFound());
|
||||||
|
|
||||||
R_RETURN(it->AddContextRecordToCategory(std::move(record)));
|
it->m_record = std::move(record);
|
||||||
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Context::WriteContextsToReport(Report *report) {
|
Result Context::WriteContextsToReport(Report *report) {
|
||||||
|
|||||||
@@ -26,16 +26,12 @@ namespace ams::erpt::srv {
|
|||||||
class Context : public Allocator, public util::IntrusiveListBaseNode<Context> {
|
class Context : public Allocator, public util::IntrusiveListBaseNode<Context> {
|
||||||
private:
|
private:
|
||||||
const CategoryId m_category;
|
const CategoryId m_category;
|
||||||
const u32 m_max_record_count;
|
std::unique_ptr<ContextRecord> m_record;
|
||||||
u32 m_record_count;
|
|
||||||
util::IntrusiveListBaseTraits<ContextRecord>::ListType m_record_list;
|
|
||||||
public:
|
public:
|
||||||
Context(CategoryId cat, u32 max_records);
|
Context(CategoryId cat);
|
||||||
~Context();
|
~Context();
|
||||||
|
|
||||||
Result AddCategoryToReport(Report *report);
|
Result AddCategoryToReport(Report *report);
|
||||||
Result AddContextToCategory(const ContextEntry *entry, const u8 *data, u32 data_size);
|
|
||||||
Result AddContextRecordToCategory(std::unique_ptr<ContextRecord> record);
|
|
||||||
public:
|
public:
|
||||||
static Result SubmitContext(const ContextEntry *entry, const u8 *data, u32 data_size);
|
static Result SubmitContext(const ContextEntry *entry, const u8 *data, u32 data_size);
|
||||||
static Result SubmitContextRecord(std::unique_ptr<ContextRecord> record);
|
static Result SubmitContextRecord(std::unique_ptr<ContextRecord> record);
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ namespace ams::erpt::srv {
|
|||||||
|
|
||||||
class Context;
|
class Context;
|
||||||
|
|
||||||
class ContextRecord : public Allocator, public util::IntrusiveListBaseNode<ContextRecord> {
|
class ContextRecord : public Allocator {
|
||||||
friend class Context;
|
|
||||||
private:
|
private:
|
||||||
static u32 s_record_count;
|
static u32 s_record_count;
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ namespace ams::erpt::srv {
|
|||||||
g_sf_allocator.Attach(g_heap_handle);
|
g_sf_allocator.Attach(g_heap_handle);
|
||||||
|
|
||||||
for (auto i = 0; i < CategoryId_Count; i++) {
|
for (auto i = 0; i < CategoryId_Count; i++) {
|
||||||
Context *ctx = new Context(static_cast<CategoryId>(i), 1);
|
Context *ctx = new Context(static_cast<CategoryId>(i));
|
||||||
AMS_ABORT_UNLESS(ctx != nullptr);
|
AMS_ABORT_UNLESS(ctx != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ namespace ams::os::impl {
|
|||||||
R_RETURN(impl::GetAslrSpaceManager().MapAtRandomAddress(out_address,
|
R_RETURN(impl::GetAslrSpaceManager().MapAtRandomAddress(out_address,
|
||||||
[](uintptr_t map_address, size_t map_size) -> Result {
|
[](uintptr_t map_address, size_t map_size) -> Result {
|
||||||
R_TRY_CATCH(svc::MapInsecureMemory(map_address, map_size)) {
|
R_TRY_CATCH(svc::MapInsecureMemory(map_address, map_size)) {
|
||||||
|
R_CONVERT(svc::ResultOutOfMemory, os::ResultOutOfMemory())
|
||||||
R_CONVERT(svc::ResultInvalidCurrentMemory, os::ResultInvalidCurrentMemoryState())
|
R_CONVERT(svc::ResultInvalidCurrentMemory, os::ResultInvalidCurrentMemoryState())
|
||||||
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;
|
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <stratosphere.hpp>
|
||||||
|
|
||||||
|
namespace ams::os::impl {
|
||||||
|
|
||||||
|
class UnsafeMemoryImpl {
|
||||||
|
public:
|
||||||
|
static Result AllocateUnsafeMemoryImpl(uintptr_t *out_address, size_t size);
|
||||||
|
static Result FreeUnsafeMemoryImpl(uintptr_t address, size_t size);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <stratosphere.hpp>
|
||||||
|
#include "os_unsafe_memory_impl.hpp"
|
||||||
|
#include "os_aslr_space_manager.hpp"
|
||||||
|
|
||||||
|
namespace ams::os::impl {
|
||||||
|
|
||||||
|
Result UnsafeMemoryImpl::AllocateUnsafeMemoryImpl(uintptr_t *out_address, size_t size) {
|
||||||
|
/* Map at a random address. */
|
||||||
|
R_RETURN(impl::GetAslrSpaceManager().MapAtRandomAddress(out_address,
|
||||||
|
[](uintptr_t map_address, size_t map_size) -> Result {
|
||||||
|
R_TRY_CATCH(svc::MapPhysicalMemoryUnsafe(map_address, map_size)) {
|
||||||
|
R_CONVERT(svc::ResultOutOfResource, os::ResultOutOfResource())
|
||||||
|
R_CONVERT(svc::ResultOutOfMemory, os::ResultOutOfMemory())
|
||||||
|
R_CONVERT(svc::ResultInvalidCurrentMemory, os::ResultInvalidCurrentMemoryState())
|
||||||
|
R_CONVERT(svc::ResultLimitReached, os::ResultOutOfMemory())
|
||||||
|
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
},
|
||||||
|
[](uintptr_t map_address, size_t map_size) -> void {
|
||||||
|
R_ABORT_UNLESS(UnsafeMemoryImpl::FreeUnsafeMemoryImpl(map_address, map_size));
|
||||||
|
},
|
||||||
|
size,
|
||||||
|
0
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result UnsafeMemoryImpl::FreeUnsafeMemoryImpl(uintptr_t address, size_t size) {
|
||||||
|
R_TRY_CATCH(svc::UnmapPhysicalMemoryUnsafe(address, size)) {
|
||||||
|
R_CONVERT(svc::ResultOutOfResource, os::ResultOutOfResource())
|
||||||
|
R_CONVERT(svc::ResultOutOfMemory, os::ResultOutOfResource())
|
||||||
|
R_CONVERT(svc::ResultInvalidCurrentMemory, os::ResultBusy())
|
||||||
|
R_CONVERT(svc::ResultInvalidMemoryRegion, os::ResultInvalidParameter())
|
||||||
|
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
39
libraries/libstratosphere/source/os/os_unsafe_memory.cpp
Normal file
39
libraries/libstratosphere/source/os/os_unsafe_memory.cpp
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <stratosphere.hpp>
|
||||||
|
#include "impl/os_unsafe_memory_impl.hpp"
|
||||||
|
|
||||||
|
namespace ams::os {
|
||||||
|
|
||||||
|
Result AllocateUnsafeMemory(uintptr_t *out_address, size_t size) {
|
||||||
|
/* Check arguments. */
|
||||||
|
AMS_ASSERT(size > 0);
|
||||||
|
AMS_ASSERT(util::IsAligned(size, os::MemoryPageSize));
|
||||||
|
|
||||||
|
/* Allocate memory. */
|
||||||
|
R_RETURN(impl::UnsafeMemoryImpl::AllocateUnsafeMemoryImpl(out_address, size));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result FreeUnsafeMemory(uintptr_t address, size_t size) {
|
||||||
|
/* Check arguments. */
|
||||||
|
AMS_ASSERT(util::IsAligned(address, os::MemoryPageSize));
|
||||||
|
AMS_ASSERT(util::IsAligned(size, os::MemoryPageSize));
|
||||||
|
|
||||||
|
/* Free memory. */
|
||||||
|
R_RETURN(impl::UnsafeMemoryImpl::FreeUnsafeMemoryImpl(address, size));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
#define ATMOSPHERE_RELEASE_VERSION_MAJOR 1
|
#define ATMOSPHERE_RELEASE_VERSION_MAJOR 1
|
||||||
#define ATMOSPHERE_RELEASE_VERSION_MINOR 5
|
#define ATMOSPHERE_RELEASE_VERSION_MINOR 5
|
||||||
#define ATMOSPHERE_RELEASE_VERSION_MICRO 0
|
#define ATMOSPHERE_RELEASE_VERSION_MICRO 1
|
||||||
|
|
||||||
#define ATMOSPHERE_RELEASE_VERSION ATMOSPHERE_RELEASE_VERSION_MAJOR, ATMOSPHERE_RELEASE_VERSION_MINOR, ATMOSPHERE_RELEASE_VERSION_MICRO
|
#define ATMOSPHERE_RELEASE_VERSION ATMOSPHERE_RELEASE_VERSION_MAJOR, ATMOSPHERE_RELEASE_VERSION_MINOR, ATMOSPHERE_RELEASE_VERSION_MICRO
|
||||||
|
|
||||||
|
|||||||
@@ -457,10 +457,10 @@ namespace ams::result::impl {
|
|||||||
#define AMS_CALL_ON_RESULT_ABORT_IMPL(cond, val) do { ::ams::diag::impl::FatalErrorByResultForNx(val); AMS_INFINITE_LOOP(); AMS_ASSUME(false); } while (false)
|
#define AMS_CALL_ON_RESULT_ABORT_IMPL(cond, val) do { ::ams::diag::impl::FatalErrorByResultForNx(val); AMS_INFINITE_LOOP(); AMS_ASSUME(false); } while (false)
|
||||||
#elif defined(ATMOSPHERE_OS_HORIZON)
|
#elif defined(ATMOSPHERE_OS_HORIZON)
|
||||||
#define AMS_CALL_ON_RESULT_ASSERTION_IMPL(cond, val) AMS_CALL_ASSERT_FAIL_IMPL(::ams::diag::AssertionType_Assert, "ams::Result::IsSuccess()", "Failed: %s\n Module: %d\n Description: %d\n InnerValue: 0x%08" PRIX32, cond, val.GetModule(), val.GetDescription(), static_cast<::ams::Result>(val).GetInnerValue())
|
#define AMS_CALL_ON_RESULT_ASSERTION_IMPL(cond, val) AMS_CALL_ASSERT_FAIL_IMPL(::ams::diag::AssertionType_Assert, "ams::Result::IsSuccess()", "Failed: %s\n Module: %d\n Description: %d\n InnerValue: 0x%08" PRIX32, cond, val.GetModule(), val.GetDescription(), static_cast<::ams::Result>(val).GetInnerValue())
|
||||||
#define AMS_CALL_ON_RESULT_ABORT_IMPL(cond, val) AMS_CALL_ABORT_IMPL("ams::Result::IsSuccess()", "Failed: %s\n Module: %d\n Description: %d\n InnerValue: 0x%08" PRIX32, cond, val.GetModule(), val.GetDescription(), static_cast<::ams::Result>(val).GetInnerValue())
|
#define AMS_CALL_ON_RESULT_ABORT_IMPL(cond, val) AMS_CALL_ABORT_IMPL("ams::Result::IsSuccess()", "Failed: %s\n Module: %d\n Description: %d\n InnerValue: 0x%08" PRIX32, cond, static_cast<::ams::Result>(val).GetModule(), static_cast<::ams::Result>(val).GetDescription(), static_cast<::ams::Result>(val).GetInnerValue())
|
||||||
#else
|
#else
|
||||||
#define AMS_CALL_ON_RESULT_ASSERTION_IMPL(cond, val) AMS_CALL_ASSERT_FAIL_IMPL(::ams::diag::AssertionType_Assert, "ams::Result::IsSuccess()", "Failed: %s\n Module: %d\n Description: %d\n InnerValue: 0x%08" PRIX32 "\n Name: %s", cond, val.GetModule(), val.GetDescription(), static_cast<::ams::Result>(val).GetInnerValue(), ::ams::GetResultName(val))
|
#define AMS_CALL_ON_RESULT_ASSERTION_IMPL(cond, val) AMS_CALL_ASSERT_FAIL_IMPL(::ams::diag::AssertionType_Assert, "ams::Result::IsSuccess()", "Failed: %s\n Module: %d\n Description: %d\n InnerValue: 0x%08" PRIX32 "\n Name: %s", cond, val.GetModule(), val.GetDescription(), static_cast<::ams::Result>(val).GetInnerValue(), ::ams::GetResultName(static_cast<::ams::Result>(val)))
|
||||||
#define AMS_CALL_ON_RESULT_ABORT_IMPL(cond, val) AMS_CALL_ABORT_IMPL("ams::Result::IsSuccess()", "Failed: %s\n Module: %d\n Description: %d\n InnerValue: 0x%08" PRIX32 "\n Name: %s", cond, val.GetModule(), val.GetDescription(), static_cast<::ams::Result>(val).GetInnerValue(), ::ams::GetResultName(val))
|
#define AMS_CALL_ON_RESULT_ABORT_IMPL(cond, val) AMS_CALL_ABORT_IMPL("ams::Result::IsSuccess()", "Failed: %s\n Module: %d\n Description: %d\n InnerValue: 0x%08" PRIX32 "\n Name: %s", cond, static_cast<::ams::Result>(val).GetModule(), static_cast<::ams::Result>(val).GetDescription(), static_cast<::ams::Result>(val).GetInnerValue(), ::ams::GetResultName(static_cast<::ams::Result>(val)))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// Evaluates an expression that returns a result, and asserts the result if it would fail.
|
/// Evaluates an expression that returns a result, and asserts the result if it would fail.
|
||||||
|
|||||||
@@ -27,11 +27,11 @@ namespace ams::svc {
|
|||||||
|
|
||||||
constexpr inline size_t AddressMemoryRegionSmall36Size = 2_GB;
|
constexpr inline size_t AddressMemoryRegionSmall36Size = 2_GB;
|
||||||
constexpr inline size_t AddressMemoryRegionLarge36Size = 64_GB - AddressMemoryRegionSmall36Size;
|
constexpr inline size_t AddressMemoryRegionLarge36Size = 64_GB - AddressMemoryRegionSmall36Size;
|
||||||
constexpr inline size_t AddressMemoryRegionHeap36Size = 6_GB;
|
constexpr inline size_t AddressMemoryRegionHeap36Size = 8_GB;
|
||||||
constexpr inline size_t AddressMemoryRegionAlias36Size = 6_GB;
|
constexpr inline size_t AddressMemoryRegionAlias36Size = 6_GB;
|
||||||
|
|
||||||
constexpr inline size_t AddressMemoryRegionSmall39Size = 64_GB;
|
constexpr inline size_t AddressMemoryRegionSmall39Size = 64_GB;
|
||||||
constexpr inline size_t AddressMemoryRegionHeap39Size = 6_GB;
|
constexpr inline size_t AddressMemoryRegionHeap39Size = 8_GB;
|
||||||
constexpr inline size_t AddressMemoryRegionAlias39Size = 64_GB;
|
constexpr inline size_t AddressMemoryRegionAlias39Size = 64_GB;
|
||||||
constexpr inline size_t AddressMemoryRegionStack39Size = 2_GB;
|
constexpr inline size_t AddressMemoryRegionStack39Size = 2_GB;
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ _ZN3ams4kern10KScheduler12ScheduleImplEv:
|
|||||||
mov x1, x0
|
mov x1, x0
|
||||||
|
|
||||||
/* First, clear the need's scheduling bool (and dmb ish after, as it's an atomic). */
|
/* First, clear the need's scheduling bool (and dmb ish after, as it's an atomic). */
|
||||||
/* TODO: Should this be a stlrb? Nintendo does not do one. */
|
|
||||||
strb wzr, [x1]
|
strb wzr, [x1]
|
||||||
dmb ish
|
dmb ish
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include <stratosphere.hpp>
|
#include <stratosphere.hpp>
|
||||||
#include "setsys_mitm_service.hpp"
|
#include "setsys_mitm_service.hpp"
|
||||||
#include "settings_sd_kvs.hpp"
|
#include "settings_sd_kvs.hpp"
|
||||||
|
#include "setsys_shim.h"
|
||||||
|
|
||||||
namespace ams::mitm::settings {
|
namespace ams::mitm::settings {
|
||||||
|
|
||||||
@@ -23,6 +24,8 @@ namespace ams::mitm::settings {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
constexpr const char ExternalBluetoothDatabasePath[] = "@Sdcard:/atmosphere/bluetooth_devices.db";
|
||||||
|
|
||||||
constinit os::SdkMutex g_firmware_version_lock;
|
constinit os::SdkMutex g_firmware_version_lock;
|
||||||
constinit bool g_cached_firmware_version;
|
constinit bool g_cached_firmware_version;
|
||||||
constinit settings::FirmwareVersion g_firmware_version;
|
constinit settings::FirmwareVersion g_firmware_version;
|
||||||
@@ -77,7 +80,7 @@ namespace ams::mitm::settings {
|
|||||||
CacheFirmwareVersion();
|
CacheFirmwareVersion();
|
||||||
|
|
||||||
/* We want to give a special firmware version to the home menu title, and nothing else. */
|
/* We want to give a special firmware version to the home menu title, and nothing else. */
|
||||||
/* This means Qlaunch + Maintenance Menu, and nothing else. */
|
/* This means qlaunch + maintenance menu, and nothing else. */
|
||||||
if (client_info.program_id == ncm::SystemAppletId::Qlaunch || client_info.program_id == ncm::SystemAppletId::MaintenanceMenu) {
|
if (client_info.program_id == ncm::SystemAppletId::Qlaunch || client_info.program_id == ncm::SystemAppletId::MaintenanceMenu) {
|
||||||
*out = g_ams_firmware_version;
|
*out = g_ams_firmware_version;
|
||||||
} else {
|
} else {
|
||||||
@@ -87,6 +90,99 @@ namespace ams::mitm::settings {
|
|||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsExternalBluetoothDatabaseEnabled() {
|
||||||
|
u8 en = 0;
|
||||||
|
settings::fwdbg::GetSettingsItemValue(std::addressof(en), sizeof(en), "atmosphere", "enable_external_bluetooth_db");
|
||||||
|
return en;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasExternalBluetoothDatabase() {
|
||||||
|
bool file_exists;
|
||||||
|
R_ABORT_UNLESS(fs::HasFile(std::addressof(file_exists), ExternalBluetoothDatabasePath));
|
||||||
|
return file_exists;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ReadExternalBluetoothDatabase(s32 *entries_read, settings::BluetoothDevicesSettings *db, size_t db_max_size) {
|
||||||
|
/* Open the external database file. */
|
||||||
|
fs::FileHandle file;
|
||||||
|
R_TRY(fs::OpenFile(std::addressof(file), ExternalBluetoothDatabasePath, fs::OpenMode_Read));
|
||||||
|
ON_SCOPE_EXIT { fs::CloseFile(file); };
|
||||||
|
|
||||||
|
/* Read the number of database entries stored in external database. */
|
||||||
|
u64 total_entries;
|
||||||
|
R_TRY(fs::ReadFile(file, 0, std::addressof(total_entries), sizeof(total_entries)));
|
||||||
|
|
||||||
|
u64 db_offset = sizeof(total_entries);
|
||||||
|
if (total_entries > db_max_size) {
|
||||||
|
/* Pairings are stored from least to most recent. Add offset to skip the older entries that won't fit. */
|
||||||
|
db_offset += (total_entries - db_max_size) * sizeof(settings::BluetoothDevicesSettings);
|
||||||
|
|
||||||
|
/* Cap number of database entries read to size of database on this firmware. */
|
||||||
|
total_entries = db_max_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read database entries. */
|
||||||
|
R_TRY(fs::ReadFile(file, db_offset, db, total_entries * sizeof(settings::BluetoothDevicesSettings)));
|
||||||
|
|
||||||
|
/* Convert entries to the old format if running on a firmware below 13.0.0. */
|
||||||
|
if (hos::GetVersion() < hos::Version_13_0_0) {
|
||||||
|
for (size_t i = 0; i < total_entries; ++i) {
|
||||||
|
/* Copy the newer name field to the older one. */
|
||||||
|
util::TSNPrintf(db[i].name, sizeof(db[i].name), "%s", db[i].name2);
|
||||||
|
|
||||||
|
/* Clear the newer name field. */
|
||||||
|
std::memset(db[i].name2, 0, sizeof(db[i].name2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the output. */
|
||||||
|
*entries_read = static_cast<s32>(total_entries);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result StoreExternalBluetoothDatabase(const settings::BluetoothDevicesSettings *db, u64 total_entries) {
|
||||||
|
/* Open the external database file. */
|
||||||
|
fs::FileHandle file;
|
||||||
|
R_TRY(fs::OpenFile(std::addressof(file), ExternalBluetoothDatabasePath, fs::OpenMode_Write));
|
||||||
|
ON_SCOPE_EXIT { fs::CloseFile(file); };
|
||||||
|
|
||||||
|
/* Ensure the file is the appropriate size for the number of entries. */
|
||||||
|
R_TRY(fs::SetFileSize(file, sizeof(total_entries) + total_entries * sizeof(settings::BluetoothDevicesSettings)));
|
||||||
|
|
||||||
|
/* Write the number of database entries. */
|
||||||
|
R_TRY(fs::WriteFile(file, 0, std::addressof(total_entries), sizeof(total_entries), fs::WriteOption::None));
|
||||||
|
|
||||||
|
/* Write the database entries. */
|
||||||
|
u64 db_offset = sizeof(total_entries);
|
||||||
|
if (hos::GetVersion() < hos::Version_13_0_0) {
|
||||||
|
/* Convert entries to the new format if running on a firmware below 13.0.0. */
|
||||||
|
for (size_t i = 0; i < total_entries; ++i) {
|
||||||
|
/* Make a copy of the current database entry. */
|
||||||
|
settings::BluetoothDevicesSettings tmp = db[i];
|
||||||
|
|
||||||
|
/* Copy the older name field to the newer one. */
|
||||||
|
util::TSNPrintf(tmp.name2, sizeof(tmp.name2), "%s", tmp.name);
|
||||||
|
|
||||||
|
/* Clear the original name field. */
|
||||||
|
std::memset(tmp.name, 0, sizeof(tmp.name));
|
||||||
|
|
||||||
|
/* Write the converted database entry. */
|
||||||
|
R_TRY(fs::WriteFile(file, db_offset, std::addressof(tmp), sizeof(settings::BluetoothDevicesSettings), fs::WriteOption::None));
|
||||||
|
|
||||||
|
/* Advance to the next database entry. */
|
||||||
|
db_offset += sizeof(settings::BluetoothDevicesSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Flush the data we've written. */
|
||||||
|
R_TRY(fs::FlushFile(file));
|
||||||
|
} else {
|
||||||
|
/* We can just write the database to the file. */
|
||||||
|
R_TRY(fs::WriteFile(file, db_offset, db, total_entries * sizeof(settings::BluetoothDevicesSettings), fs::WriteOption::Flush));
|
||||||
|
}
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result SetSysMitmService::GetFirmwareVersion(sf::Out<settings::FirmwareVersion> out) {
|
Result SetSysMitmService::GetFirmwareVersion(sf::Out<settings::FirmwareVersion> out) {
|
||||||
@@ -102,6 +198,47 @@ namespace ams::mitm::settings {
|
|||||||
R_RETURN(GetFirmwareVersionImpl(out.GetPointer(), m_client_info));
|
R_RETURN(GetFirmwareVersionImpl(out.GetPointer(), m_client_info));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result SetSysMitmService::SetBluetoothDevicesSettings(const sf::InMapAliasArray<settings::BluetoothDevicesSettings> &settings) {
|
||||||
|
/* We only want to perform additional logic when the external database setting is enabled. */
|
||||||
|
R_UNLESS(IsExternalBluetoothDatabaseEnabled(), sm::mitm::ResultShouldForwardToSession());
|
||||||
|
|
||||||
|
/* Create the external database if it doesn't exist. */
|
||||||
|
if (!HasExternalBluetoothDatabase()) {
|
||||||
|
R_TRY(fs::CreateFile(ExternalBluetoothDatabasePath, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Backup the local database to the sd card. */
|
||||||
|
R_TRY(StoreExternalBluetoothDatabase(settings.GetPointer(), settings.GetSize()));
|
||||||
|
|
||||||
|
/* Ensure that the updated database is stored to the system save as usual. */
|
||||||
|
static_assert(sizeof(settings::BluetoothDevicesSettings) == sizeof(::SetSysBluetoothDevicesSettings));
|
||||||
|
R_TRY(setsysSetBluetoothDevicesSettingsFwd(m_forward_service.get(), reinterpret_cast<const ::SetSysBluetoothDevicesSettings *>(settings.GetPointer()), settings.GetSize()));
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result SetSysMitmService::GetBluetoothDevicesSettings(sf::Out<s32> out_count, const sf::OutMapAliasArray<settings::BluetoothDevicesSettings> &out) {
|
||||||
|
/* We only want to perform additional logic when the external database setting is enabled. */
|
||||||
|
R_UNLESS(IsExternalBluetoothDatabaseEnabled(), sm::mitm::ResultShouldForwardToSession());
|
||||||
|
|
||||||
|
if (!HasExternalBluetoothDatabase()) {
|
||||||
|
/* Fetch the local database from the system save. */
|
||||||
|
static_assert(sizeof(settings::BluetoothDevicesSettings) == sizeof(::SetSysBluetoothDevicesSettings));
|
||||||
|
R_TRY(setsysGetBluetoothDevicesSettingsFwd(m_forward_service.get(), out_count.GetPointer(), reinterpret_cast<::SetSysBluetoothDevicesSettings *>(out.GetPointer()), out.GetSize()));
|
||||||
|
|
||||||
|
/* Create the external database file. */
|
||||||
|
R_TRY(fs::CreateFile(ExternalBluetoothDatabasePath, 0));
|
||||||
|
|
||||||
|
/* Backup the local database to the sd card. */
|
||||||
|
R_TRY(StoreExternalBluetoothDatabase(out.GetPointer(), out_count.GetValue()));
|
||||||
|
} else {
|
||||||
|
/* Read the external database from the sd card. */
|
||||||
|
R_TRY(ReadExternalBluetoothDatabase(out_count.GetPointer(), out.GetPointer(), out.GetSize()));
|
||||||
|
}
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
Result SetSysMitmService::GetSettingsItemValueSize(sf::Out<u64> out_size, const settings::SettingsName &name, const settings::SettingsItemKey &key) {
|
Result SetSysMitmService::GetSettingsItemValueSize(sf::Out<u64> out_size, const settings::SettingsName &name, const settings::SettingsItemKey &key) {
|
||||||
R_TRY_CATCH(settings::fwdbg::GetSdCardKeyValueStoreSettingsItemValueSize(out_size.GetPointer(), name.value, key.value)) {
|
R_TRY_CATCH(settings::fwdbg::GetSdCardKeyValueStoreSettingsItemValueSize(out_size.GetPointer(), name.value, key.value)) {
|
||||||
R_CATCH_RETHROW(sf::impl::ResultRequestContextChanged)
|
R_CATCH_RETHROW(sf::impl::ResultRequestContextChanged)
|
||||||
|
|||||||
@@ -16,12 +16,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <stratosphere.hpp>
|
#include <stratosphere.hpp>
|
||||||
|
|
||||||
#define AMS_SETTINGS_SYSTEM_MITM_INTERFACE_INFO(C, H) \
|
#define AMS_SETTINGS_SYSTEM_MITM_INTERFACE_INFO(C, H) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 3, Result, GetFirmwareVersion, (sf::Out<ams::settings::FirmwareVersion> out), (out)) \
|
AMS_SF_METHOD_INFO(C, H, 3, Result, GetFirmwareVersion, (sf::Out<ams::settings::FirmwareVersion> out), (out)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 4, Result, GetFirmwareVersion2, (sf::Out<ams::settings::FirmwareVersion> out), (out)) \
|
AMS_SF_METHOD_INFO(C, H, 4, Result, GetFirmwareVersion2, (sf::Out<ams::settings::FirmwareVersion> out), (out)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 37, Result, GetSettingsItemValueSize, (sf::Out<u64> out_size, const ams::settings::SettingsName &name, const ams::settings::SettingsItemKey &key), (out_size, name, key)) \
|
AMS_SF_METHOD_INFO(C, H, 11, Result, SetBluetoothDevicesSettings, (const sf::InMapAliasArray<ams::settings::BluetoothDevicesSettings> &settings), (settings)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 38, Result, GetSettingsItemValue, (sf::Out<u64> out_size, const sf::OutBuffer &out, const ams::settings::SettingsName &name, const ams::settings::SettingsItemKey &key), (out_size, out, name, key)) \
|
AMS_SF_METHOD_INFO(C, H, 12, Result, GetBluetoothDevicesSettings, (sf::Out<s32> out_count, const sf::OutMapAliasArray<ams::settings::BluetoothDevicesSettings> &out), (out_count, out)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 62, Result, GetDebugModeFlag, (sf::Out<bool> out), (out))
|
AMS_SF_METHOD_INFO(C, H, 37, Result, GetSettingsItemValueSize, (sf::Out<u64> out_size, const ams::settings::SettingsName &name, const ams::settings::SettingsItemKey &key), (out_size, name, key)) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 38, Result, GetSettingsItemValue, (sf::Out<u64> out_size, const sf::OutBuffer &out, const ams::settings::SettingsName &name, const ams::settings::SettingsItemKey &key), (out_size, out, name, key)) \
|
||||||
|
AMS_SF_METHOD_INFO(C, H, 62, Result, GetDebugModeFlag, (sf::Out<bool> out), (out))
|
||||||
|
|
||||||
AMS_SF_DEFINE_MITM_INTERFACE(ams::mitm::settings, ISetSysMitmInterface, AMS_SETTINGS_SYSTEM_MITM_INTERFACE_INFO, 0x0E82ED13)
|
AMS_SF_DEFINE_MITM_INTERFACE(ams::mitm::settings, ISetSysMitmInterface, AMS_SETTINGS_SYSTEM_MITM_INTERFACE_INFO, 0x0E82ED13)
|
||||||
|
|
||||||
@@ -41,6 +43,8 @@ namespace ams::mitm::settings {
|
|||||||
public:
|
public:
|
||||||
Result GetFirmwareVersion(sf::Out<ams::settings::FirmwareVersion> out);
|
Result GetFirmwareVersion(sf::Out<ams::settings::FirmwareVersion> out);
|
||||||
Result GetFirmwareVersion2(sf::Out<ams::settings::FirmwareVersion> out);
|
Result GetFirmwareVersion2(sf::Out<ams::settings::FirmwareVersion> out);
|
||||||
|
Result SetBluetoothDevicesSettings(const sf::InMapAliasArray<ams::settings::BluetoothDevicesSettings> &settings);
|
||||||
|
Result GetBluetoothDevicesSettings(sf::Out<s32> out_count, const sf::OutMapAliasArray<ams::settings::BluetoothDevicesSettings> &out);
|
||||||
Result GetSettingsItemValueSize(sf::Out<u64> out_size, const ams::settings::SettingsName &name, const ams::settings::SettingsItemKey &key);
|
Result GetSettingsItemValueSize(sf::Out<u64> out_size, const ams::settings::SettingsName &name, const ams::settings::SettingsItemKey &key);
|
||||||
Result GetSettingsItemValue(sf::Out<u64> out_size, const sf::OutBuffer &out, const ams::settings::SettingsName &name, const ams::settings::SettingsItemKey &key);
|
Result GetSettingsItemValue(sf::Out<u64> out_size, const sf::OutBuffer &out, const ams::settings::SettingsName &name, const ams::settings::SettingsItemKey &key);
|
||||||
Result GetDebugModeFlag(sf::Out<bool> out);
|
Result GetDebugModeFlag(sf::Out<bool> out);
|
||||||
|
|||||||
30
stratosphere/ams_mitm/source/set_mitm/setsys_shim.c
Normal file
30
stratosphere/ams_mitm/source/set_mitm/setsys_shim.c
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include "setsys_shim.h"
|
||||||
|
|
||||||
|
Result setsysSetBluetoothDevicesSettingsFwd(Service *s, const SetSysBluetoothDevicesSettings *settings, s32 count) {
|
||||||
|
return serviceDispatch(s, 11,
|
||||||
|
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
|
||||||
|
.buffers = { { settings, count * sizeof(SetSysBluetoothDevicesSettings) } },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result setsysGetBluetoothDevicesSettingsFwd(Service *s, s32 *total_out, SetSysBluetoothDevicesSettings *settings, s32 count) {
|
||||||
|
return serviceDispatchOut(s, 12, *total_out,
|
||||||
|
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
||||||
|
.buffers = { { settings, count * sizeof(SetSysBluetoothDevicesSettings) } },
|
||||||
|
);
|
||||||
|
}
|
||||||
20
stratosphere/ams_mitm/source/set_mitm/setsys_shim.h
Normal file
20
stratosphere/ams_mitm/source/set_mitm/setsys_shim.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* @file setsys_shim.h
|
||||||
|
* @brief Settings Services (fs) IPC wrapper for setsys.mitm.
|
||||||
|
* @author ndeadly
|
||||||
|
* @copyright libnx Authors
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <switch.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Forwarding shims. */
|
||||||
|
Result setsysSetBluetoothDevicesSettingsFwd(Service *s, const SetSysBluetoothDevicesSettings *settings, s32 count);
|
||||||
|
Result setsysGetBluetoothDevicesSettingsFwd(Service *s, s32 *total_out, SetSysBluetoothDevicesSettings *settings, s32 count);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -393,6 +393,11 @@ namespace ams::settings::fwdbg {
|
|||||||
/* 0 = Disabled, 1 = Enabled */
|
/* 0 = Disabled, 1 = Enabled */
|
||||||
R_ABORT_UNLESS(ParseSettingsItemValue("atmosphere", "enable_log_manager", "u8!0x0"));
|
R_ABORT_UNLESS(ParseSettingsItemValue("atmosphere", "enable_log_manager", "u8!0x0"));
|
||||||
|
|
||||||
|
/* Controls whether the bluetooth pairing database is redirected to the SD card (shared across sysmmc/all emummcs) */
|
||||||
|
/* NOTE: On <13.0.0, the database size was 10 instead of 20; booting pre-13.0.0 will truncate the database. */
|
||||||
|
/* 0 = Disabled, 1 = Enabled */
|
||||||
|
R_ABORT_UNLESS(ParseSettingsItemValue("atmosphere", "enable_external_bluetooth_db", "u8!0x0"));
|
||||||
|
|
||||||
/* Hbloader custom settings. */
|
/* Hbloader custom settings. */
|
||||||
|
|
||||||
/* Controls the size of the homebrew heap when running as applet. */
|
/* Controls the size of the homebrew heap when running as applet. */
|
||||||
|
|||||||
@@ -78,6 +78,9 @@
|
|||||||
"svcReplyAndReceive": "0x43",
|
"svcReplyAndReceive": "0x43",
|
||||||
"svcReplyAndReceiveWithUserBuffer": "0x44",
|
"svcReplyAndReceiveWithUserBuffer": "0x44",
|
||||||
"svcCreateEvent": "0x45",
|
"svcCreateEvent": "0x45",
|
||||||
|
"svcMapPhysicalMemoryUnsafe": "0x48",
|
||||||
|
"svcUnmapPhysicalMemoryUnsafe": "0x48",
|
||||||
|
"svcSetUnsafeLimit": "0x4A",
|
||||||
"svcReadWriteRegister": "0x4E",
|
"svcReadWriteRegister": "0x4E",
|
||||||
"svcDebugActiveProcess": "0x60",
|
"svcDebugActiveProcess": "0x60",
|
||||||
"svcGetDebugEvent": "0x63",
|
"svcGetDebugEvent": "0x63",
|
||||||
@@ -86,7 +89,9 @@
|
|||||||
"svcQueryDebugProcessMemory": "0x69",
|
"svcQueryDebugProcessMemory": "0x69",
|
||||||
"svcReadDebugProcessMemory": "0x6a",
|
"svcReadDebugProcessMemory": "0x6a",
|
||||||
"svcGetDebugThreadParam": "0x6d",
|
"svcGetDebugThreadParam": "0x6d",
|
||||||
"svcCallSecureMonitor": "0x7f"
|
"svcCallSecureMonitor": "0x7f",
|
||||||
|
"svcMapInsecureMemory": "0x90",
|
||||||
|
"svcUnmapInsecureMemory": "0x91"
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
"type": "min_kernel_version",
|
"type": "min_kernel_version",
|
||||||
|
|||||||
@@ -99,6 +99,41 @@ namespace ams {
|
|||||||
|
|
||||||
namespace init {
|
namespace init {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
Result InitializePlatformServiceWithoutSessionCountForHomebrewCompatibility() {
|
||||||
|
/* NOTE: This implements a hack, to keep a session to pl:u without counting against the global limit. */
|
||||||
|
/* This is done because as of 16.0.0, pl:u is the only way to get shared font access, and there are */
|
||||||
|
/* not enough sessions for all reasonable the clients when homebrew gets involved. */
|
||||||
|
/* Please do not do similar things for other services; this is a hack which may not always work, */
|
||||||
|
/* and which could cause problems in other contexts where the ServerManager doesn't have enough */
|
||||||
|
/* slots in truth. */
|
||||||
|
|
||||||
|
/* Initialize pl. */
|
||||||
|
R_ABORT_UNLESS(plInitialize(::PlServiceType_User));
|
||||||
|
|
||||||
|
/* Get the service session for pl. */
|
||||||
|
Service *srv = plGetServiceSession();
|
||||||
|
|
||||||
|
/* Next, create a clone. */
|
||||||
|
/* Because this doesn't go through sm, this does not count against the session limit. */
|
||||||
|
Service clone;
|
||||||
|
R_TRY(serviceClone(srv, std::addressof(clone)));
|
||||||
|
|
||||||
|
/* Next, close the pl service session from sm. */
|
||||||
|
/* This decrements the used session count by one, since the session is from sm. */
|
||||||
|
serviceClose(srv);
|
||||||
|
|
||||||
|
/* HACK: replace the session with the clone we made, to restore functionality. */
|
||||||
|
*srv = clone;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void InitializeSystemModule() {
|
void InitializeSystemModule() {
|
||||||
/* Initialize heap. */
|
/* Initialize heap. */
|
||||||
fatal::srv::InitializeFsHeap();
|
fatal::srv::InitializeFsHeap();
|
||||||
@@ -126,7 +161,7 @@ namespace ams {
|
|||||||
|
|
||||||
R_ABORT_UNLESS(psmInitialize());
|
R_ABORT_UNLESS(psmInitialize());
|
||||||
R_ABORT_UNLESS(spsmInitialize());
|
R_ABORT_UNLESS(spsmInitialize());
|
||||||
R_ABORT_UNLESS(plInitialize(::PlServiceType_User));
|
R_ABORT_UNLESS(InitializePlatformServiceWithoutSessionCountForHomebrewCompatibility());
|
||||||
gpio::Initialize();
|
gpio::Initialize();
|
||||||
|
|
||||||
/* Mount the SD card. */
|
/* Mount the SD card. */
|
||||||
|
|||||||
@@ -42,7 +42,46 @@ namespace ams::fatal::srv {
|
|||||||
alignas(os::MemoryPageSize) constinit u8 g_nv_transfer_memory[0x40000];
|
alignas(os::MemoryPageSize) constinit u8 g_nv_transfer_memory[0x40000];
|
||||||
|
|
||||||
/* There should only be a single (1280*768) framebuffer. */
|
/* There should only be a single (1280*768) framebuffer. */
|
||||||
alignas(os::MemoryPageSize) constinit u8 g_framebuffer_memory[FatalScreenWidthAlignedBytes * util::AlignUp(FatalScreenHeight, 128)];
|
constexpr size_t FrameBufferRequiredSizeBytes = FatalScreenWidthAlignedBytes * util::AlignUp(FatalScreenHeight, 128);
|
||||||
|
constexpr size_t FrameBufferRequiredSizePageAligned = util::AlignUp(FrameBufferRequiredSizeBytes, os::MemoryPageSize);
|
||||||
|
constexpr size_t FrameBufferRequiredSizeHeapAligned = util::AlignUp(FrameBufferRequiredSizeBytes, os::MemoryHeapUnitSize);
|
||||||
|
|
||||||
|
constinit u8 *g_framebuffer_pointer = nullptr;
|
||||||
|
|
||||||
|
void InitializeFrameBufferPointer() {
|
||||||
|
/* Try to get a framebuffer from heap. */
|
||||||
|
{
|
||||||
|
if (R_SUCCEEDED(os::SetMemoryHeapSize(FrameBufferRequiredSizeHeapAligned))) {
|
||||||
|
g_framebuffer_pointer = reinterpret_cast<u8 *>(os::GetMemoryHeapAddress());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We couldn't use heap, so try insecure memory, from the system nonsecure pool. */
|
||||||
|
{
|
||||||
|
uintptr_t address = 0;
|
||||||
|
if (R_SUCCEEDED(os::AllocateInsecureMemory(std::addressof(address), FrameBufferRequiredSizePageAligned))) {
|
||||||
|
g_framebuffer_pointer = reinterpret_cast<u8 *>(address);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Neither heap nor insecure is available, so we're going to have to try to raid the unsafe pool. */
|
||||||
|
{
|
||||||
|
/* First, increase the limit to an extremely high value. */
|
||||||
|
size_t large_size = std::max(64_MB, FrameBufferRequiredSizeHeapAligned);
|
||||||
|
while (svc::ResultLimitReached::Includes(svc::SetUnsafeLimit(large_size))) {
|
||||||
|
large_size *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Next, map some unsafe memory. */
|
||||||
|
uintptr_t address = 0;
|
||||||
|
if (R_SUCCEEDED(os::AllocateUnsafeMemory(std::addressof(address), FrameBufferRequiredSizePageAligned))) {
|
||||||
|
g_framebuffer_pointer = reinterpret_cast<u8 *>(address);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,8 +241,12 @@ namespace ams::fatal::srv {
|
|||||||
void ShowFatalTask::PreRenderFrameBuffer() {
|
void ShowFatalTask::PreRenderFrameBuffer() {
|
||||||
const FatalConfig &config = GetFatalConfig();
|
const FatalConfig &config = GetFatalConfig();
|
||||||
|
|
||||||
|
/* Allocate a frame buffer. */
|
||||||
|
InitializeFrameBufferPointer();
|
||||||
|
AMS_ABORT_UNLESS(g_framebuffer_pointer != nullptr);
|
||||||
|
|
||||||
/* Pre-render the image into the static framebuffer. */
|
/* Pre-render the image into the static framebuffer. */
|
||||||
u16 *tiled_buf = reinterpret_cast<u16 *>(g_framebuffer_memory);
|
u16 *tiled_buf = reinterpret_cast<u16 *>(g_framebuffer_pointer);
|
||||||
|
|
||||||
/* Temporarily use the NV transfer memory as font backing heap. */
|
/* Temporarily use the NV transfer memory as font backing heap. */
|
||||||
font::SetHeapMemory(g_nv_transfer_memory, sizeof(g_nv_transfer_memory));
|
font::SetHeapMemory(g_nv_transfer_memory, sizeof(g_nv_transfer_memory));
|
||||||
@@ -214,7 +257,7 @@ namespace ams::fatal::srv {
|
|||||||
font::SetFontColor(0xFFFF);
|
font::SetFontColor(0xFFFF);
|
||||||
|
|
||||||
/* Draw a background. */
|
/* Draw a background. */
|
||||||
for (size_t i = 0; i < sizeof(g_framebuffer_memory) / sizeof(*tiled_buf); i++) {
|
for (size_t i = 0; i < FrameBufferRequiredSizeBytes / sizeof(*tiled_buf); i++) {
|
||||||
tiled_buf[i] = 0x39C9;
|
tiled_buf[i] = 0x39C9;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,7 +482,7 @@ namespace ams::fatal::srv {
|
|||||||
R_TRY(nvFenceInit());
|
R_TRY(nvFenceInit());
|
||||||
|
|
||||||
/* Create nvmap. */
|
/* Create nvmap. */
|
||||||
R_TRY(nvMapCreate(std::addressof(m_map), g_framebuffer_memory, sizeof(g_framebuffer_memory), 0x20000, NvKind_Pitch, true));
|
R_TRY(nvMapCreate(std::addressof(m_map), g_framebuffer_pointer, FrameBufferRequiredSizeBytes, 0x20000, NvKind_Pitch, true));
|
||||||
|
|
||||||
/* Setup graphics buffer. */
|
/* Setup graphics buffer. */
|
||||||
{
|
{
|
||||||
@@ -460,9 +503,9 @@ namespace ams::fatal::srv {
|
|||||||
grbuf.planes[0].block_height_log2 = 4;
|
grbuf.planes[0].block_height_log2 = 4;
|
||||||
grbuf.nvmap_id = nvMapGetId(std::addressof(m_map));
|
grbuf.nvmap_id = nvMapGetId(std::addressof(m_map));
|
||||||
grbuf.stride = FatalScreenWidthAligned;
|
grbuf.stride = FatalScreenWidthAligned;
|
||||||
grbuf.total_size = sizeof(g_framebuffer_memory);
|
grbuf.total_size = FrameBufferRequiredSizeBytes;
|
||||||
grbuf.planes[0].pitch = FatalScreenWidthAlignedBytes;
|
grbuf.planes[0].pitch = FatalScreenWidthAlignedBytes;
|
||||||
grbuf.planes[0].size = sizeof(g_framebuffer_memory);
|
grbuf.planes[0].size = FrameBufferRequiredSizeBytes;
|
||||||
grbuf.planes[0].offset = 0;
|
grbuf.planes[0].offset = 0;
|
||||||
|
|
||||||
R_TRY(nwindowConfigureBuffer(std::addressof(m_win), 0, std::addressof(grbuf)));
|
R_TRY(nwindowConfigureBuffer(std::addressof(m_win), 0, std::addressof(grbuf)));
|
||||||
@@ -474,7 +517,7 @@ namespace ams::fatal::srv {
|
|||||||
void ShowFatalTask::DisplayPreRenderedFrame() {
|
void ShowFatalTask::DisplayPreRenderedFrame() {
|
||||||
s32 slot;
|
s32 slot;
|
||||||
R_ABORT_UNLESS(nwindowDequeueBuffer(std::addressof(m_win), std::addressof(slot), nullptr));
|
R_ABORT_UNLESS(nwindowDequeueBuffer(std::addressof(m_win), std::addressof(slot), nullptr));
|
||||||
dd::FlushDataCache(g_framebuffer_memory, sizeof(g_framebuffer_memory));
|
dd::FlushDataCache(g_framebuffer_pointer, FrameBufferRequiredSizeBytes);
|
||||||
R_ABORT_UNLESS(nwindowQueueBuffer(std::addressof(m_win), m_win.cur_slot, NULL));
|
R_ABORT_UNLESS(nwindowQueueBuffer(std::addressof(m_win), m_win.cur_slot, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "ui_util.hpp"
|
#include "ui_util.hpp"
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
namespace dbk {
|
namespace dbk {
|
||||||
|
|
||||||
@@ -73,7 +74,7 @@ namespace dbk {
|
|||||||
nvgFill(vg);
|
nvgFill(vg);
|
||||||
|
|
||||||
/* Setup the font. */
|
/* Setup the font. */
|
||||||
nvgFontSize(vg, 32.0f);
|
nvgFontSize(vg, std::min(32.0f, -(strlen(title)*0.5f) + 47.0f));
|
||||||
nvgFontFace(vg, SwitchStandardFont);
|
nvgFontFace(vg, SwitchStandardFont);
|
||||||
nvgTextAlign(vg, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE);
|
nvgTextAlign(vg, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE);
|
||||||
nvgFillColor(vg, nvgRGB(0, 0, 0));
|
nvgFillColor(vg, nvgRGB(0, 0, 0));
|
||||||
|
|||||||
Reference in New Issue
Block a user