Compare commits

..

32 Commits

Author SHA1 Message Date
Michael Scire
883b3968bc loader: update usb3 patches for 16.0.0 2023-02-22 18:19:14 -07:00
Michael Scire
dd7539a905 ncm: alignment was changed for PlaceHolderId/ContentId in 16.0.0 2023-02-22 18:03:03 -07:00
Michael Scire
6e2d435b6b ncm: fix inversion in activation skipping 2023-02-22 15:29:04 -07:00
Michael Scire
605206bb97 ncm: Add IntegratedContent*Impl 2023-02-22 15:16:30 -07:00
Michael Scire
3cb3b24b4a ncm: first pass at ContentManagerImpl refactor (missing the IntegratedImpls, won't link) 2023-02-22 13:59:05 -07:00
Michael Scire
ad3da922ef kern: 16.x web applet crashes on exit with 48 MB stolen (rip) 2023-02-21 23:31:31 -07:00
Michael Scire
3b6a4ab12f ncm: fix copy/paste error in switch case 2023-02-21 23:19:18 -07:00
Michael Scire
2fa8a57f27 strat: fix sysmodule building, bump version so I don't forget later 2023-02-21 23:09:47 -07:00
Michael Scire
5e82e72411 libstrat: make build with new ncm/fs api changes (sysmodules probably fail to build) 2023-02-21 22:51:05 -07:00
Michael Scire
83701210c7 erpt: update for new ids 2023-02-21 16:11:21 -07:00
Michael Scire
528191b50e boot2: update for 16.0.0 2023-02-21 16:06:21 -07:00
Michael Scire
5b3420e9d6 emummc: update for 16.0.0 2023-02-21 15:33:33 -07:00
Michael Scire
21fa82d74b fusee/exo: implement the usual changes for new firmware support 2023-02-21 15:12:27 -07:00
Michael Scire
c75a17b5a8 kern: bump supported version to 16.x 2023-02-21 14:03:39 -07:00
Michael Scire
255a0083a1 kern: better divide non-secure size, don't waste fatal memory unless necessary 2023-02-21 14:02:13 -07:00
Michael Scire
2e7491f605 kern: delete creation time field from KProcess 2023-02-21 13:51:56 -07:00
Michael Scire
08672fd422 kern: add InfoType_IoRegionHint 2023-02-21 13:28:14 -07:00
Michael Scire
adfaee0f46 kern: refactor priority inheritance to represent locks as C++ objects 2023-02-21 13:15:01 -07:00
Michael Scire
4f6ecf138b kern: remove unnecessary interrupt disables from arbiter/condvar 2023-02-21 10:58:02 -07:00
Michael Scire
819f7edc70 kern: KConditionVariable::SignalToAddress now emits dmb before userspace write 2023-02-21 10:42:24 -07:00
Michael Scire
709e1969bb kern: refactor init (kill identity map, merge cpu on logic) 2023-02-21 10:38:48 -07:00
Michael Scire
42e6c1fd59 kern: use variable-count parameter arrays for DebugEvents 2023-02-21 09:16:15 -07:00
Michael Scire
89f8bee3b6 kern: update KSystemControl::InitializePhase1, dynamically scale 39-bit address space regions 2023-02-21 08:53:17 -07:00
Michael Scire
afa4a50d99 kern: update for new ChangePermissions page table operation 2023-02-21 08:39:21 -07:00
Michael Scire
1690cfd766 kern: adjust pool allocations 2023-02-21 08:16:39 -07:00
Michael Scire
b484f27530 kern: simplify KSchedulerLock::Lock 2023-02-21 08:08:08 -07:00
Michael Scire
88520f8b6a kern: allow QueryIoMapping to find Static mappings 2023-02-21 08:06:12 -07:00
Michael Scire
ba483dea8a kern: update UnmapIoRegion for new Mapping_Memory handling 2023-02-21 08:02:59 -07:00
Michael Scire
8eef019e3d kern: use tree for IoPool regions instead of list 2023-02-21 07:54:57 -07:00
Michael Scire
b7846247aa kern: optimize userspace access asm to use cheaper instruction in io memory loops 2023-02-21 03:25:55 -07:00
Michael Scire
154d61f55f kern: use different psr masks for 64 and 32-bit El0 threads 2023-02-21 03:20:49 -07:00
Michael Scire
fd7a93a15f kern: increase stack parameter size by 0x10 2023-02-21 03:15:09 -07:00
36 changed files with 84 additions and 544 deletions

View File

@@ -67,10 +67,6 @@
; Note that this setting is ignored (and treated as 1) when htc is enabled.
; 0 = Disabled, 1 = Enabled
; 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]
; Controls the size of the homebrew heap when running as applet.
; If set to zero, all available applet memory is used as heap.

View File

@@ -1,26 +1,4 @@
# 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
+ 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.
@@ -37,7 +15,7 @@
## 1.4.0
+ Support was added for 15.0.0.
+ `mesosphère` was updated to reflect the latest official kernel behavior.
+ `ncm` was updated to reflect the latest official behavior.
+ `ncm` was updated to reflect the latest official kernel behavior.
+ 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.
+ An off-by-one was fixed in mesosphere when computing the new value for an address arbiter signaled with ModifyByWaitingCountIfEqual.

4
emummc/.gitrepo vendored
View File

@@ -6,7 +6,7 @@
[subrepo]
remote = https://github.com/m4xw/emummc
branch = develop
commit = bba1f1fb65f75721caf6d023a35d75d3c9aafd0f
parent = 1ab8b234447864503e21c600681219a96962e6c1
commit = 4714b2df9eaf68fb85516b35f7f4265ab0413825
parent = 99f6a96845b6097d50f5059eea9245d27876f26a
method = merge
cmdver = 0.4.1

View File

@@ -6,7 +6,7 @@
[subrepo]
remote = https://github.com/Atmosphere-NX/Atmosphere-libs
branch = master
commit = b1607dc8a3d85bc8c859c60d70ebb4a3dcbb85b8
parent = f1ad26ce844ab7a63b948281b50c12e5d1dac8ce
commit = b7711b8fbcec5013e1738218267d69b2cb44f85e
parent = 590f22933db38f089ab2224f7fd86658a9533e8d
method = merge
cmdver = 0.4.1

View File

@@ -1,5 +1,5 @@
export ATMOSPHERE_DEFINES += -DATMOSPHERE_OS_WINDOWS
export ATMOSPHERE_SETTINGS += -fno-omit-frame-pointer -fno-data-sections
export ATMOSPHERE_SETTINGS += -fno-omit-frame-pointer
export ATMOSPHERE_CFLAGS +=
export ATMOSPHERE_CXXFLAGS +=
export ATMOSPHERE_ASFLAGS +=

View File

@@ -58,7 +58,7 @@ export CXXWRAPS := -Wl,--wrap,__cxa_pure_virtual \
-Wl,--wrap,exit
else ifeq ($(ATMOSPHERE_BOARD),generic_windows)
export CXXREQUIRED :=
export CXXWRAPS := -Wl,--wrap,__p__acmdln -Wl,--wrap,_set_invalid_parameter_handler
export CXXWRAPS := -Wl,--wrap,__p__acmdln
else
export CXXREQUIRED :=
export CXXWRAPS :=

View File

@@ -48,7 +48,7 @@ namespace ams::kern {
/* Check that the object is closed. */
R_UNLESS(derived->IsServerClosed(), svc::ResultInvalidState());
R_RETURN(Delete(obj.GetPointerUnsafe(), name));
return Delete(obj.GetPointerUnsafe(), name);
}
template<typename Derived> requires std::derived_from<Derived, KAutoObject>

View File

@@ -234,11 +234,11 @@ namespace ams::kern {
KPriorityQueueImpl m_scheduled_queue;
KPriorityQueueImpl m_suggested_queue;
private:
static constexpr ALWAYS_INLINE void ClearAffinityBit(u64 &affinity, s32 core) {
constexpr ALWAYS_INLINE void ClearAffinityBit(u64 &affinity, s32 core) {
affinity &= ~(UINT64_C(1) << core);
}
static constexpr ALWAYS_INLINE s32 GetNextCore(u64 &affinity) {
constexpr ALWAYS_INLINE s32 GetNextCore(u64 &affinity) {
const s32 core = __builtin_ctzll(static_cast<unsigned long long>(affinity));
ClearAffinityBit(affinity, core);
return core;

View File

@@ -214,7 +214,7 @@ namespace ams::kern {
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) {
if (lhs.GetPriority() < rhs.GetPriority()) {
/* Sort by priority. */
/* And then by priority. */
return -1;
} else {
return 1;

View File

@@ -51,7 +51,7 @@ namespace ams::kern {
/* Sleep the thread. */
{
KScopedSchedulerLockAndSleep lk(std::addressof(timer), owner, timeout);
KScopedSchedulerLockAndSleep lk(&timer, owner, timeout);
if (!allow_terminating_thread && owner->IsTerminationRequested()) {
lk.CancelSleep();

View File

@@ -29,7 +29,6 @@
#include <stratosphere/os/os_process_memory_api.hpp>
#include <stratosphere/os/os_process_code_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_mutex.hpp>
#include <stratosphere/os/os_condition_variable.hpp>

View File

@@ -1,25 +0,0 @@
/*
* 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);
}

View File

@@ -235,31 +235,4 @@ namespace ams::settings {
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
}

View File

@@ -154,12 +154,10 @@ 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
ifeq ($(ATMOSPHERE_OS_NAME),windows)
# I do not remember why these had fno-lto, but it appears to
# work without no-lto (2023/03/09), so I am disabling these. I may regret this later.
#os_%.o: CXXFLAGS += -fno-lto
#fssystem_%.o: CXXFLAGS += -fno-lto
#fssrv_%.o: CXXFLAGS += -fno-lto
#fs_%.o: CXXFLAGS += -fno-lto
os_%.o: CXXFLAGS += -fno-lto
fssystem_%.o: CXXFLAGS += -fno-lto
fssrv_%.o: CXXFLAGS += -fno-lto
fs_%.o: CXXFLAGS += -fno-lto
endif
#---------------------------------------------------------------------------------

View File

@@ -16,7 +16,6 @@
#include <stratosphere.hpp>
extern "C" char **__real___p__acmdln(void);
extern "C" _invalid_parameter_handler __real__set_invalid_parameter_handler(_invalid_parameter_handler);
namespace ams {
@@ -66,11 +65,4 @@ extern "C" {
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);
}
}

View File

@@ -29,7 +29,7 @@ namespace ams::erpt::srv {
}
Context::Context(CategoryId cat) : m_category(cat) {
Context::Context(CategoryId cat, u32 max_records) : m_category(cat), m_max_record_count(max_records), m_record_count(0) {
g_category_list.push_front(*this);
}
@@ -38,11 +38,12 @@ namespace ams::erpt::srv {
}
Result Context::AddCategoryToReport(Report *report) {
if (m_record != nullptr) {
const auto *entry = m_record->GetContextEntryPtr();
for (u32 i = 0; i < entry->field_count; i++) {
auto *field = std::addressof(entry->fields[i]);
u8 *arr_buf = entry->array_buffer;
R_SUCCEED_IF(m_record_list.empty());
for (auto it = m_record_list.begin(); it != m_record_list.end(); it++) {
for (u32 i = 0; i < it->m_ctx.field_count; i++) {
auto *field = std::addressof(it->m_ctx.fields[i]);
u8 *arr_buf = it->m_ctx.array_buffer;
switch (field->type) {
case FieldType_Bool: R_TRY(Cipher::AddField(report, field->id, field->value_bool)); break;
@@ -69,23 +70,46 @@ namespace ams::erpt::srv {
R_SUCCEED();
}
Result Context::SubmitContext(const ContextEntry *entry, const u8 *data, u32 data_size) {
Result Context::AddContextToCategory(const ContextEntry *entry, const u8 *data, u32 data_size) {
auto record = std::make_unique<ContextRecord>();
R_UNLESS(record != nullptr, erpt::ResultOutOfMemory());
R_TRY(record->Initialize(entry, data, data_size));
R_RETURN(SubmitContextRecord(std::move(record)));
this->AddContextRecordToCategory(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) {
auto it = util::range::find_if(g_category_list, [&](const Context &cur) {
return cur.m_category == record->GetContextEntryPtr()->category;
return cur.m_category == record->m_ctx.category;
});
R_UNLESS(it != g_category_list.end(), erpt::ResultCategoryNotFound());
it->m_record = std::move(record);
R_SUCCEED();
R_RETURN(it->AddContextRecordToCategory(std::move(record)));
}
Result Context::WriteContextsToReport(Report *report) {

View File

@@ -26,12 +26,16 @@ namespace ams::erpt::srv {
class Context : public Allocator, public util::IntrusiveListBaseNode<Context> {
private:
const CategoryId m_category;
std::unique_ptr<ContextRecord> m_record;
const u32 m_max_record_count;
u32 m_record_count;
util::IntrusiveListBaseTraits<ContextRecord>::ListType m_record_list;
public:
Context(CategoryId cat);
Context(CategoryId cat, u32 max_records);
~Context();
Result AddCategoryToReport(Report *report);
Result AddContextToCategory(const ContextEntry *entry, const u8 *data, u32 data_size);
Result AddContextRecordToCategory(std::unique_ptr<ContextRecord> record);
public:
static Result SubmitContext(const ContextEntry *entry, const u8 *data, u32 data_size);
static Result SubmitContextRecord(std::unique_ptr<ContextRecord> record);

View File

@@ -21,7 +21,8 @@ namespace ams::erpt::srv {
class Context;
class ContextRecord : public Allocator {
class ContextRecord : public Allocator, public util::IntrusiveListBaseNode<ContextRecord> {
friend class Context;
private:
static u32 s_record_count;
public:

View File

@@ -106,7 +106,7 @@ namespace ams::erpt::srv {
g_sf_allocator.Attach(g_heap_handle);
for (auto i = 0; i < CategoryId_Count; i++) {
Context *ctx = new Context(static_cast<CategoryId>(i));
Context *ctx = new Context(static_cast<CategoryId>(i), 1);
AMS_ABORT_UNLESS(ctx != nullptr);
}

View File

@@ -24,7 +24,6 @@ namespace ams::os::impl {
R_RETURN(impl::GetAslrSpaceManager().MapAtRandomAddress(out_address,
[](uintptr_t map_address, size_t map_size) -> Result {
R_TRY_CATCH(svc::MapInsecureMemory(map_address, map_size)) {
R_CONVERT(svc::ResultOutOfMemory, os::ResultOutOfMemory())
R_CONVERT(svc::ResultInvalidCurrentMemory, os::ResultInvalidCurrentMemoryState())
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;

View File

@@ -1,27 +0,0 @@
/*
* 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);
};
}

View File

@@ -1,54 +0,0 @@
/*
* 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();
}
}

View File

@@ -1,39 +0,0 @@
/*
* 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));
}
}

View File

@@ -17,7 +17,7 @@
#define ATMOSPHERE_RELEASE_VERSION_MAJOR 1
#define ATMOSPHERE_RELEASE_VERSION_MINOR 5
#define ATMOSPHERE_RELEASE_VERSION_MICRO 1
#define ATMOSPHERE_RELEASE_VERSION_MICRO 0
#define ATMOSPHERE_RELEASE_VERSION ATMOSPHERE_RELEASE_VERSION_MAJOR, ATMOSPHERE_RELEASE_VERSION_MINOR, ATMOSPHERE_RELEASE_VERSION_MICRO

View File

@@ -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)
#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_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())
#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())
#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(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, 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)))
#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_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))
#endif
/// Evaluates an expression that returns a result, and asserts the result if it would fail.

View File

@@ -27,11 +27,11 @@ namespace ams::svc {
constexpr inline size_t AddressMemoryRegionSmall36Size = 2_GB;
constexpr inline size_t AddressMemoryRegionLarge36Size = 64_GB - AddressMemoryRegionSmall36Size;
constexpr inline size_t AddressMemoryRegionHeap36Size = 8_GB;
constexpr inline size_t AddressMemoryRegionHeap36Size = 6_GB;
constexpr inline size_t AddressMemoryRegionAlias36Size = 6_GB;
constexpr inline size_t AddressMemoryRegionSmall39Size = 64_GB;
constexpr inline size_t AddressMemoryRegionHeap39Size = 8_GB;
constexpr inline size_t AddressMemoryRegionHeap39Size = 6_GB;
constexpr inline size_t AddressMemoryRegionAlias39Size = 64_GB;
constexpr inline size_t AddressMemoryRegionStack39Size = 2_GB;

View File

@@ -29,6 +29,7 @@ _ZN3ams4kern10KScheduler12ScheduleImplEv:
mov x1, x0
/* 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]
dmb ish

View File

@@ -16,7 +16,6 @@
#include <stratosphere.hpp>
#include "setsys_mitm_service.hpp"
#include "settings_sd_kvs.hpp"
#include "setsys_shim.h"
namespace ams::mitm::settings {
@@ -24,8 +23,6 @@ namespace ams::mitm::settings {
namespace {
constexpr const char ExternalBluetoothDatabasePath[] = "@Sdcard:/atmosphere/bluetooth_devices.db";
constinit os::SdkMutex g_firmware_version_lock;
constinit bool g_cached_firmware_version;
constinit settings::FirmwareVersion g_firmware_version;
@@ -80,7 +77,7 @@ namespace ams::mitm::settings {
CacheFirmwareVersion();
/* 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) {
*out = g_ams_firmware_version;
} else {
@@ -90,99 +87,6 @@ namespace ams::mitm::settings {
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) {
@@ -198,47 +102,6 @@ namespace ams::mitm::settings {
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) {
R_TRY_CATCH(settings::fwdbg::GetSdCardKeyValueStoreSettingsItemValueSize(out_size.GetPointer(), name.value, key.value)) {
R_CATCH_RETHROW(sf::impl::ResultRequestContextChanged)

View File

@@ -16,14 +16,12 @@
#pragma once
#include <stratosphere.hpp>
#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, 4, Result, GetFirmwareVersion2, (sf::Out<ams::settings::FirmwareVersion> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 11, Result, SetBluetoothDevicesSettings, (const sf::InMapAliasArray<ams::settings::BluetoothDevicesSettings> &settings), (settings)) \
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, 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))
#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, 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, 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)
@@ -43,8 +41,6 @@ namespace ams::mitm::settings {
public:
Result GetFirmwareVersion(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 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);

View File

@@ -1,30 +0,0 @@
/*
* 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) } },
);
}

View File

@@ -1,20 +0,0 @@
/**
* @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

View File

@@ -393,11 +393,6 @@ namespace ams::settings::fwdbg {
/* 0 = Disabled, 1 = Enabled */
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. */
/* Controls the size of the homebrew heap when running as applet. */

View File

@@ -78,9 +78,6 @@
"svcReplyAndReceive": "0x43",
"svcReplyAndReceiveWithUserBuffer": "0x44",
"svcCreateEvent": "0x45",
"svcMapPhysicalMemoryUnsafe": "0x48",
"svcUnmapPhysicalMemoryUnsafe": "0x48",
"svcSetUnsafeLimit": "0x4A",
"svcReadWriteRegister": "0x4E",
"svcDebugActiveProcess": "0x60",
"svcGetDebugEvent": "0x63",
@@ -89,9 +86,7 @@
"svcQueryDebugProcessMemory": "0x69",
"svcReadDebugProcessMemory": "0x6a",
"svcGetDebugThreadParam": "0x6d",
"svcCallSecureMonitor": "0x7f",
"svcMapInsecureMemory": "0x90",
"svcUnmapInsecureMemory": "0x91"
"svcCallSecureMonitor": "0x7f"
}
}, {
"type": "min_kernel_version",

View File

@@ -99,41 +99,6 @@ namespace ams {
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() {
/* Initialize heap. */
fatal::srv::InitializeFsHeap();
@@ -161,7 +126,7 @@ namespace ams {
R_ABORT_UNLESS(psmInitialize());
R_ABORT_UNLESS(spsmInitialize());
R_ABORT_UNLESS(InitializePlatformServiceWithoutSessionCountForHomebrewCompatibility());
R_ABORT_UNLESS(plInitialize(::PlServiceType_User));
gpio::Initialize();
/* Mount the SD card. */

View File

@@ -42,46 +42,7 @@ namespace ams::fatal::srv {
alignas(os::MemoryPageSize) constinit u8 g_nv_transfer_memory[0x40000];
/* There should only be a single (1280*768) framebuffer. */
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;
}
}
}
alignas(os::MemoryPageSize) constinit u8 g_framebuffer_memory[FatalScreenWidthAlignedBytes * util::AlignUp(FatalScreenHeight, 128)];
}
@@ -241,12 +202,8 @@ namespace ams::fatal::srv {
void ShowFatalTask::PreRenderFrameBuffer() {
const FatalConfig &config = GetFatalConfig();
/* Allocate a frame buffer. */
InitializeFrameBufferPointer();
AMS_ABORT_UNLESS(g_framebuffer_pointer != nullptr);
/* Pre-render the image into the static framebuffer. */
u16 *tiled_buf = reinterpret_cast<u16 *>(g_framebuffer_pointer);
u16 *tiled_buf = reinterpret_cast<u16 *>(g_framebuffer_memory);
/* Temporarily use the NV transfer memory as font backing heap. */
font::SetHeapMemory(g_nv_transfer_memory, sizeof(g_nv_transfer_memory));
@@ -257,7 +214,7 @@ namespace ams::fatal::srv {
font::SetFontColor(0xFFFF);
/* Draw a background. */
for (size_t i = 0; i < FrameBufferRequiredSizeBytes / sizeof(*tiled_buf); i++) {
for (size_t i = 0; i < sizeof(g_framebuffer_memory) / sizeof(*tiled_buf); i++) {
tiled_buf[i] = 0x39C9;
}
@@ -482,7 +439,7 @@ namespace ams::fatal::srv {
R_TRY(nvFenceInit());
/* Create nvmap. */
R_TRY(nvMapCreate(std::addressof(m_map), g_framebuffer_pointer, FrameBufferRequiredSizeBytes, 0x20000, NvKind_Pitch, true));
R_TRY(nvMapCreate(std::addressof(m_map), g_framebuffer_memory, sizeof(g_framebuffer_memory), 0x20000, NvKind_Pitch, true));
/* Setup graphics buffer. */
{
@@ -503,9 +460,9 @@ namespace ams::fatal::srv {
grbuf.planes[0].block_height_log2 = 4;
grbuf.nvmap_id = nvMapGetId(std::addressof(m_map));
grbuf.stride = FatalScreenWidthAligned;
grbuf.total_size = FrameBufferRequiredSizeBytes;
grbuf.total_size = sizeof(g_framebuffer_memory);
grbuf.planes[0].pitch = FatalScreenWidthAlignedBytes;
grbuf.planes[0].size = FrameBufferRequiredSizeBytes;
grbuf.planes[0].size = sizeof(g_framebuffer_memory);
grbuf.planes[0].offset = 0;
R_TRY(nwindowConfigureBuffer(std::addressof(m_win), 0, std::addressof(grbuf)));
@@ -517,7 +474,7 @@ namespace ams::fatal::srv {
void ShowFatalTask::DisplayPreRenderedFrame() {
s32 slot;
R_ABORT_UNLESS(nwindowDequeueBuffer(std::addressof(m_win), std::addressof(slot), nullptr));
dd::FlushDataCache(g_framebuffer_pointer, FrameBufferRequiredSizeBytes);
dd::FlushDataCache(g_framebuffer_memory, sizeof(g_framebuffer_memory));
R_ABORT_UNLESS(nwindowQueueBuffer(std::addressof(m_win), m_win.cur_slot, NULL));
}

View File

@@ -16,7 +16,6 @@
#include "ui_util.hpp"
#include <cstdio>
#include <math.h>
#include <cstring>
namespace dbk {
@@ -74,7 +73,7 @@ namespace dbk {
nvgFill(vg);
/* Setup the font. */
nvgFontSize(vg, std::min(32.0f, -(strlen(title)*0.5f) + 47.0f));
nvgFontSize(vg, 32.0f);
nvgFontFace(vg, SwitchStandardFont);
nvgTextAlign(vg, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE);
nvgFillColor(vg, nvgRGB(0, 0, 0));