strat: use m_ for member variables
This commit is contained in:
@@ -20,50 +20,50 @@ namespace ams::capsrv::server {
|
||||
|
||||
Result DecoderControlServerManager::Initialize() {
|
||||
/* Create the objects. */
|
||||
this->service_holder.emplace();
|
||||
this->server_manager_holder.emplace();
|
||||
m_service_holder.emplace();
|
||||
m_server_manager_holder.emplace();
|
||||
|
||||
/* Register the service. */
|
||||
R_ABORT_UNLESS((this->server_manager_holder->RegisterObjectForServer(this->service_holder->GetShared(), ServiceName, MaxSessions)));
|
||||
R_ABORT_UNLESS((m_server_manager_holder->RegisterObjectForServer(m_service_holder->GetShared(), ServiceName, MaxSessions)));
|
||||
|
||||
/* Initialize the idle event, we're idle initially. */
|
||||
os::InitializeEvent(std::addressof(this->idle_event), true, os::EventClearMode_ManualClear);
|
||||
os::InitializeEvent(std::addressof(m_idle_event), true, os::EventClearMode_ManualClear);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void DecoderControlServerManager::Finalize() {
|
||||
/* Check that the server is idle. */
|
||||
AMS_ASSERT(os::TryWaitEvent(std::addressof(this->idle_event)));
|
||||
AMS_ASSERT(os::TryWaitEvent(std::addressof(m_idle_event)));
|
||||
|
||||
/* Destroy the server. */
|
||||
os::FinalizeEvent(std::addressof(this->idle_event));
|
||||
this->server_manager_holder = util::nullopt;
|
||||
this->service_holder = util::nullopt;
|
||||
os::FinalizeEvent(std::addressof(m_idle_event));
|
||||
m_server_manager_holder = util::nullopt;
|
||||
m_service_holder = util::nullopt;
|
||||
}
|
||||
|
||||
void DecoderControlServerManager::StartServer() {
|
||||
this->server_manager_holder->ResumeProcessing();
|
||||
m_server_manager_holder->ResumeProcessing();
|
||||
}
|
||||
|
||||
void DecoderControlServerManager::StopServer() {
|
||||
/* Request the server stop, and wait until it does. */
|
||||
this->server_manager_holder->RequestStopProcessing();
|
||||
os::WaitEvent(std::addressof(this->idle_event));
|
||||
m_server_manager_holder->RequestStopProcessing();
|
||||
os::WaitEvent(std::addressof(m_idle_event));
|
||||
}
|
||||
|
||||
void DecoderControlServerManager::RunServer() {
|
||||
/* Ensure that we are allowed to run. */
|
||||
AMS_ABORT_UNLESS(os::TryWaitEvent(std::addressof(this->idle_event)));
|
||||
AMS_ABORT_UNLESS(os::TryWaitEvent(std::addressof(m_idle_event)));
|
||||
|
||||
/* Clear the event. */
|
||||
os::ClearEvent(std::addressof(this->idle_event));
|
||||
os::ClearEvent(std::addressof(m_idle_event));
|
||||
|
||||
/* Process forever. */
|
||||
this->server_manager_holder->LoopProcess();
|
||||
m_server_manager_holder->LoopProcess();
|
||||
|
||||
/* Signal that we're idle again. */
|
||||
os::SignalEvent(std::addressof(this->idle_event));
|
||||
os::SignalEvent(std::addressof(m_idle_event));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,11 +31,11 @@ namespace ams::capsrv::server {
|
||||
using ServerOptions = sf::hipc::DefaultServerManagerOptions;
|
||||
using ServerManager = sf::hipc::ServerManager<NumServers, ServerOptions, MaxSessions>;
|
||||
private:
|
||||
util::optional<ServiceHolderType> service_holder;
|
||||
util::optional<ServerManager> server_manager_holder;
|
||||
os::EventType idle_event;
|
||||
util::optional<ServiceHolderType> m_service_holder;
|
||||
util::optional<ServerManager> m_server_manager_holder;
|
||||
os::EventType m_idle_event;
|
||||
public:
|
||||
constexpr DecoderControlServerManager() : service_holder(), server_manager_holder(), idle_event{} { /* ... */ }
|
||||
constexpr DecoderControlServerManager() : m_service_holder(), m_server_manager_holder(), m_idle_event{} { /* ... */ }
|
||||
|
||||
Result Initialize();
|
||||
void Finalize();
|
||||
|
||||
@@ -23,17 +23,17 @@ namespace ams::ddsf {
|
||||
AMS_ASSERT(device->IsDriverAttached());
|
||||
|
||||
/* Acquire exclusive access to the manager. */
|
||||
std::scoped_lock lk(this->entry_list_lock);
|
||||
std::scoped_lock lk(m_entry_list_lock);
|
||||
|
||||
/* Check that we don't already have an entry with the code. */
|
||||
for (const auto &holder : this->entry_list) {
|
||||
for (const auto &holder : m_entry_list) {
|
||||
AMS_ASSERT(holder.IsConstructed());
|
||||
AMS_ASSERT(holder.Get().GetDeviceCode() != device_code);
|
||||
AMS_UNUSED(holder);
|
||||
}
|
||||
|
||||
/* Allocate memory for a new device code entry holder. */
|
||||
void *holder_storage = this->memory_resource->Allocate(sizeof(DeviceCodeEntryHolder));
|
||||
void *holder_storage = m_memory_resource->Allocate(sizeof(DeviceCodeEntryHolder));
|
||||
R_UNLESS(holder_storage != nullptr, ddsf::ResultOutOfResource());
|
||||
|
||||
/* Initialize the new holder. */
|
||||
@@ -41,18 +41,18 @@ namespace ams::ddsf {
|
||||
holder->Construct(device_code, device);
|
||||
|
||||
/* Link the new holder. */
|
||||
holder->AddTo(this->entry_list);
|
||||
holder->AddTo(m_entry_list);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
bool DeviceCodeEntryManager::Remove(DeviceCode device_code) {
|
||||
/* Acquire exclusive access to the manager. */
|
||||
std::scoped_lock lk(this->entry_list_lock);
|
||||
std::scoped_lock lk(m_entry_list_lock);
|
||||
|
||||
/* Find and erase the entry. */
|
||||
bool erased = false;
|
||||
for (auto it = this->entry_list.begin(); it != this->entry_list.end(); /* ... */) {
|
||||
for (auto it = m_entry_list.begin(); it != m_entry_list.end(); /* ... */) {
|
||||
/* Get the current entry, and advance the iterator. */
|
||||
DeviceCodeEntryHolder *cur = std::addressof(*(it++));
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace ams::ddsf {
|
||||
/* Destroy and deallocate the holder. */
|
||||
cur->Destroy();
|
||||
std::destroy_at(cur);
|
||||
this->memory_resource->Deallocate(cur, sizeof(*cur));
|
||||
m_memory_resource->Deallocate(cur, sizeof(*cur));
|
||||
|
||||
erased = true;
|
||||
}
|
||||
|
||||
@@ -38,63 +38,63 @@ namespace ams::ddsf {
|
||||
|
||||
void EventHandlerManager::Initialize() {
|
||||
/* Check that we're not already initialized. */
|
||||
if (this->is_initialized) {
|
||||
if (m_is_initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialize multi wait/holder. */
|
||||
os::InitializeMultiWait(std::addressof(this->multi_wait));
|
||||
os::InitializeMultiWaitHolder(std::addressof(this->loop_control_event_holder), this->loop_control_event.GetBase());
|
||||
os::LinkMultiWaitHolder(std::addressof(this->multi_wait), std::addressof(this->loop_control_event_holder));
|
||||
os::InitializeMultiWait(std::addressof(m_multi_wait));
|
||||
os::InitializeMultiWaitHolder(std::addressof(m_loop_control_event_holder), m_loop_control_event.GetBase());
|
||||
os::LinkMultiWaitHolder(std::addressof(m_multi_wait), std::addressof(m_loop_control_event_holder));
|
||||
|
||||
this->is_initialized = true;
|
||||
m_is_initialized = true;
|
||||
}
|
||||
|
||||
void EventHandlerManager::Finalize() {
|
||||
/* Check that we're initialized and not looping. */
|
||||
AMS_ASSERT(!this->is_looping);
|
||||
AMS_ASSERT(this->is_initialized);
|
||||
if (!this->is_initialized) {
|
||||
AMS_ASSERT(!m_is_looping);
|
||||
AMS_ASSERT(m_is_initialized);
|
||||
if (!m_is_initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Finalize multi wait/holder. */
|
||||
os::UnlinkMultiWaitHolder(std::addressof(this->loop_control_event_holder));
|
||||
os::FinalizeMultiWaitHolder(std::addressof(this->loop_control_event_holder));
|
||||
os::FinalizeMultiWait(std::addressof(this->multi_wait));
|
||||
os::UnlinkMultiWaitHolder(std::addressof(m_loop_control_event_holder));
|
||||
os::FinalizeMultiWaitHolder(std::addressof(m_loop_control_event_holder));
|
||||
os::FinalizeMultiWait(std::addressof(m_multi_wait));
|
||||
|
||||
this->is_initialized = false;
|
||||
m_is_initialized = false;
|
||||
}
|
||||
|
||||
void EventHandlerManager::ProcessControlCommand(LoopControlCommandParameters *params) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(this->is_initialized);
|
||||
AMS_ASSERT(m_is_initialized);
|
||||
AMS_ASSERT(params != nullptr);
|
||||
|
||||
/* Acquire exclusive access. */
|
||||
std::scoped_lock lk(this->loop_control_lock);
|
||||
std::scoped_lock lk(m_loop_control_lock);
|
||||
|
||||
/* If we're processing for the loop thread, we can directly handle. */
|
||||
if (!this->is_looping || this->IsRunningOnLoopThread()) {
|
||||
if (!m_is_looping || this->IsRunningOnLoopThread()) {
|
||||
this->ProcessControlCommandImpl(params);
|
||||
} else {
|
||||
/* Otherwise, signal to the loop thread. */
|
||||
this->loop_control_command_params = params;
|
||||
this->loop_control_event.Signal();
|
||||
this->loop_control_command_done_event.Wait();
|
||||
m_loop_control_command_params = params;
|
||||
m_loop_control_event.Signal();
|
||||
m_loop_control_command_done_event.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
void EventHandlerManager::ProcessControlCommandImpl(LoopControlCommandParameters *params) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(this->loop_control_lock.IsLockedByCurrentThread() || !this->loop_control_lock.TryLock());
|
||||
AMS_ASSERT(m_loop_control_lock.IsLockedByCurrentThread() || !m_loop_control_lock.TryLock());
|
||||
AMS_ASSERT(params != nullptr);
|
||||
AMS_ASSERT(params->target != nullptr);
|
||||
|
||||
/* Process the command. */
|
||||
switch (params->command) {
|
||||
case LoopControlCommand::Register:
|
||||
params->target->Link(std::addressof(this->multi_wait));
|
||||
params->target->Link(std::addressof(m_multi_wait));
|
||||
break;
|
||||
case LoopControlCommand::Unregister:
|
||||
params->target->Unlink();
|
||||
@@ -125,74 +125,74 @@ namespace ams::ddsf {
|
||||
|
||||
void EventHandlerManager::WaitLoopEnter() {
|
||||
/* Acquire exclusive access. */
|
||||
std::scoped_lock lk(this->loop_control_lock);
|
||||
std::scoped_lock lk(m_loop_control_lock);
|
||||
|
||||
/* Wait until we're looping. */
|
||||
while (!this->is_looping) {
|
||||
this->is_looping_cv.Wait(this->loop_control_lock);
|
||||
while (!m_is_looping) {
|
||||
m_is_looping_cv.Wait(m_loop_control_lock);
|
||||
}
|
||||
}
|
||||
|
||||
void EventHandlerManager::WaitLoopExit() {
|
||||
/* Acquire exclusive access. */
|
||||
std::scoped_lock lk(this->loop_control_lock);
|
||||
std::scoped_lock lk(m_loop_control_lock);
|
||||
|
||||
/* Wait until we're not looping. */
|
||||
while (this->is_looping) {
|
||||
this->is_looping_cv.Wait(this->loop_control_lock);
|
||||
while (m_is_looping) {
|
||||
m_is_looping_cv.Wait(m_loop_control_lock);
|
||||
}
|
||||
}
|
||||
|
||||
void EventHandlerManager::RequestStop() {
|
||||
/* Check that we're looping and not the loop thread. */
|
||||
AMS_ASSERT(this->is_looping);
|
||||
AMS_ASSERT(m_is_looping);
|
||||
AMS_ASSERT(!this->IsRunningOnLoopThread());
|
||||
|
||||
if (this->is_looping) {
|
||||
if (m_is_looping) {
|
||||
/* Acquire exclusive access. */
|
||||
std::scoped_lock lk(this->loop_control_lock);
|
||||
std::scoped_lock lk(m_loop_control_lock);
|
||||
|
||||
/* Signal to the loop thread. */
|
||||
LoopControlCommandParameters params(LoopControlCommand::Terminate, nullptr);
|
||||
this->loop_control_command_params = std::addressof(params);
|
||||
this->loop_control_event.Signal();
|
||||
this->loop_control_command_done_event.Wait();
|
||||
m_loop_control_command_params = std::addressof(params);
|
||||
m_loop_control_event.Signal();
|
||||
m_loop_control_command_done_event.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
void EventHandlerManager::LoopAuto() {
|
||||
/* Check that we're not already looping. */
|
||||
AMS_ASSERT(!this->is_looping);
|
||||
AMS_ASSERT(!m_is_looping);
|
||||
|
||||
/* Begin looping with the current thread. */
|
||||
this->loop_thread = os::GetCurrentThread();
|
||||
this->is_looping = true;
|
||||
this->is_looping_cv.Broadcast();
|
||||
m_loop_thread = os::GetCurrentThread();
|
||||
m_is_looping = true;
|
||||
m_is_looping_cv.Broadcast();
|
||||
|
||||
/* Whenever we're done looping, clean up. */
|
||||
ON_SCOPE_EXIT {
|
||||
this->loop_thread = nullptr;
|
||||
this->is_looping = false;
|
||||
this->is_looping_cv.Broadcast();
|
||||
m_loop_thread = nullptr;
|
||||
m_is_looping = false;
|
||||
m_is_looping_cv.Broadcast();
|
||||
};
|
||||
|
||||
/* Loop until we're asked to stop. */
|
||||
bool should_terminate = false;
|
||||
while (!should_terminate) {
|
||||
/* Wait for a holder to be signaled. */
|
||||
os::MultiWaitHolderType *event_holder = os::WaitAny(std::addressof(this->multi_wait));
|
||||
os::MultiWaitHolderType *event_holder = os::WaitAny(std::addressof(m_multi_wait));
|
||||
AMS_ASSERT(event_holder != nullptr);
|
||||
|
||||
/* Check if we have a request to handle. */
|
||||
if (event_holder == std::addressof(this->loop_control_event_holder)) {
|
||||
if (event_holder == std::addressof(m_loop_control_event_holder)) {
|
||||
/* Check that the request hasn't already been handled. */
|
||||
if (this->loop_control_event.TryWait()) {
|
||||
if (m_loop_control_event.TryWait()) {
|
||||
/* Handle the request. */
|
||||
AMS_ASSERT(this->loop_control_command_params != nullptr);
|
||||
switch (this->loop_control_command_params->command) {
|
||||
AMS_ASSERT(m_loop_control_command_params != nullptr);
|
||||
switch (m_loop_control_command_params->command) {
|
||||
case LoopControlCommand::Register:
|
||||
case LoopControlCommand::Unregister:
|
||||
this->ProcessControlCommandImpl(this->loop_control_command_params);
|
||||
this->ProcessControlCommandImpl(m_loop_control_command_params);
|
||||
break;
|
||||
case LoopControlCommand::Terminate:
|
||||
should_terminate = true;
|
||||
@@ -201,8 +201,8 @@ namespace ams::ddsf {
|
||||
}
|
||||
|
||||
/* Clear the request, and signal that it's done. */
|
||||
this->loop_control_command_params = nullptr;
|
||||
this->loop_control_command_done_event.Signal();
|
||||
m_loop_control_command_params = nullptr;
|
||||
m_loop_control_command_done_event.Signal();
|
||||
}
|
||||
} else {
|
||||
/* Handle the event. */
|
||||
|
||||
@@ -28,20 +28,20 @@ namespace ams::erpt::srv {
|
||||
return attachment_name;
|
||||
}
|
||||
|
||||
Attachment::Attachment(JournalRecord<AttachmentInfo> *r) : record(r) {
|
||||
this->record->AddReference();
|
||||
Attachment::Attachment(JournalRecord<AttachmentInfo> *r) : m_record(r) {
|
||||
m_record->AddReference();
|
||||
}
|
||||
|
||||
Attachment::~Attachment() {
|
||||
this->CloseStream();
|
||||
if (this->record->RemoveReference()) {
|
||||
if (m_record->RemoveReference()) {
|
||||
this->DeleteStream(this->FileName().name);
|
||||
delete this->record;
|
||||
delete m_record;
|
||||
}
|
||||
}
|
||||
|
||||
AttachmentFileName Attachment::FileName() const {
|
||||
return FileName(this->record->info.attachment_id);
|
||||
return FileName(m_record->m_info.attachment_id);
|
||||
}
|
||||
|
||||
Result Attachment::Open(AttachmentOpenType type) {
|
||||
@@ -65,13 +65,13 @@ namespace ams::erpt::srv {
|
||||
}
|
||||
|
||||
Result Attachment::GetFlags(AttachmentFlagSet *out) const {
|
||||
*out = this->record->info.flags;
|
||||
*out = m_record->m_info.flags;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result Attachment::SetFlags(AttachmentFlagSet flags) {
|
||||
if (((~this->record->info.flags) & flags).IsAnySet()) {
|
||||
this->record->info.flags |= flags;
|
||||
if (((~m_record->m_info.flags) & flags).IsAnySet()) {
|
||||
m_record->m_info.flags |= flags;
|
||||
return Journal::Commit();
|
||||
}
|
||||
return ResultSuccess();
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace ams::erpt::srv {
|
||||
|
||||
class Attachment : public Allocator, public Stream {
|
||||
private:
|
||||
JournalRecord<AttachmentInfo> *record;
|
||||
JournalRecord<AttachmentInfo> *m_record;
|
||||
private:
|
||||
AttachmentFileName FileName() const;
|
||||
public:
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
namespace ams::erpt::srv {
|
||||
|
||||
AttachmentImpl::AttachmentImpl() : attachment(nullptr) {
|
||||
AttachmentImpl::AttachmentImpl() : m_attachment(nullptr) {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
@@ -28,52 +28,52 @@ namespace ams::erpt::srv {
|
||||
}
|
||||
|
||||
Result AttachmentImpl::Open(const AttachmentId &attachment_id) {
|
||||
R_UNLESS(this->attachment == nullptr, erpt::ResultAlreadyInitialized());
|
||||
R_UNLESS(m_attachment == nullptr, erpt::ResultAlreadyInitialized());
|
||||
|
||||
JournalRecord<AttachmentInfo> *record = Journal::Retrieve(attachment_id);
|
||||
R_UNLESS(record != nullptr, erpt::ResultNotFound());
|
||||
|
||||
this->attachment = new Attachment(record);
|
||||
R_UNLESS(this->attachment != nullptr, erpt::ResultOutOfMemory());
|
||||
auto attachment_guard = SCOPE_GUARD { delete this->attachment; this->attachment = nullptr; };
|
||||
m_attachment = new Attachment(record);
|
||||
R_UNLESS(m_attachment != nullptr, erpt::ResultOutOfMemory());
|
||||
auto attachment_guard = SCOPE_GUARD { delete m_attachment; m_attachment = nullptr; };
|
||||
|
||||
R_TRY(this->attachment->Open(AttachmentOpenType_Read));
|
||||
R_TRY(m_attachment->Open(AttachmentOpenType_Read));
|
||||
attachment_guard.Cancel();
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result AttachmentImpl::Read(ams::sf::Out<u32> out_count, const ams::sf::OutBuffer &out_buffer) {
|
||||
R_UNLESS(this->attachment != nullptr, erpt::ResultNotInitialized());
|
||||
R_UNLESS(m_attachment != nullptr, erpt::ResultNotInitialized());
|
||||
|
||||
return this->attachment->Read(out_count.GetPointer(), static_cast<u8 *>(out_buffer.GetPointer()), static_cast<u32>(out_buffer.GetSize()));
|
||||
return m_attachment->Read(out_count.GetPointer(), static_cast<u8 *>(out_buffer.GetPointer()), static_cast<u32>(out_buffer.GetSize()));
|
||||
}
|
||||
|
||||
Result AttachmentImpl::SetFlags(AttachmentFlagSet flags) {
|
||||
R_UNLESS(this->attachment != nullptr, erpt::ResultNotInitialized());
|
||||
R_UNLESS(m_attachment != nullptr, erpt::ResultNotInitialized());
|
||||
|
||||
return this->attachment->SetFlags(flags);
|
||||
return m_attachment->SetFlags(flags);
|
||||
}
|
||||
|
||||
Result AttachmentImpl::GetFlags(ams::sf::Out<AttachmentFlagSet> out) {
|
||||
R_UNLESS(this->attachment != nullptr, erpt::ResultNotInitialized());
|
||||
R_UNLESS(m_attachment != nullptr, erpt::ResultNotInitialized());
|
||||
|
||||
return this->attachment->GetFlags(out.GetPointer());
|
||||
return m_attachment->GetFlags(out.GetPointer());
|
||||
}
|
||||
|
||||
Result AttachmentImpl::Close() {
|
||||
if (this->attachment != nullptr) {
|
||||
this->attachment->Close();
|
||||
delete this->attachment;
|
||||
this->attachment = nullptr;
|
||||
if (m_attachment != nullptr) {
|
||||
m_attachment->Close();
|
||||
delete m_attachment;
|
||||
m_attachment = nullptr;
|
||||
}
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result AttachmentImpl::GetSize(ams::sf::Out<s64> out) {
|
||||
R_UNLESS(this->attachment != nullptr, erpt::ResultNotInitialized());
|
||||
R_UNLESS(m_attachment != nullptr, erpt::ResultNotInitialized());
|
||||
|
||||
return this->attachment->GetSize(out.GetPointer());
|
||||
return m_attachment->GetSize(out.GetPointer());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace ams::erpt::srv {
|
||||
|
||||
class AttachmentImpl {
|
||||
private:
|
||||
Attachment *attachment;
|
||||
Attachment *m_attachment;
|
||||
public:
|
||||
AttachmentImpl();
|
||||
~AttachmentImpl();
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
namespace ams::erpt::srv {
|
||||
|
||||
u8 Cipher::s_key[crypto::Aes128CtrEncryptor::KeySize + crypto::Aes128CtrEncryptor::IvSize + crypto::Aes128CtrEncryptor::BlockSize];
|
||||
bool Cipher::s_need_to_store_cipher = false;
|
||||
constinit u8 Cipher::s_key[crypto::Aes128CtrEncryptor::KeySize + crypto::Aes128CtrEncryptor::IvSize + crypto::Aes128CtrEncryptor::BlockSize];
|
||||
constinit bool Cipher::s_need_to_store_cipher = false;
|
||||
|
||||
}
|
||||
|
||||
@@ -25,11 +25,11 @@ namespace ams::erpt::srv {
|
||||
|
||||
using ContextList = util::IntrusiveListBaseTraits<Context>::ListType;
|
||||
|
||||
ContextList g_category_list;
|
||||
constinit ContextList g_category_list;
|
||||
|
||||
}
|
||||
|
||||
Context::Context(CategoryId cat, u32 max_records) : category(cat), max_record_count(max_records), record_count(0) {
|
||||
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,12 +38,12 @@ namespace ams::erpt::srv {
|
||||
}
|
||||
|
||||
Result Context::AddCategoryToReport(Report *report) {
|
||||
R_SUCCEED_IF(this->record_list.empty());
|
||||
R_SUCCEED_IF(m_record_list.empty());
|
||||
|
||||
for (auto it = this->record_list.begin(); it != this->record_list.end(); it++) {
|
||||
for (u32 i = 0; i < it->ctx.field_count; i++) {
|
||||
auto *field = std::addressof(it->ctx.fields[i]);
|
||||
u8 *arr_buf = it->ctx.array_buffer;
|
||||
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;
|
||||
@@ -81,13 +81,13 @@ namespace ams::erpt::srv {
|
||||
}
|
||||
|
||||
Result Context::AddContextRecordToCategory(std::unique_ptr<ContextRecord> record) {
|
||||
if (this->record_count < this->max_record_count) {
|
||||
this->record_list.push_front(*record.release());
|
||||
this->record_count++;
|
||||
if (m_record_count < m_max_record_count) {
|
||||
m_record_list.push_front(*record.release());
|
||||
m_record_count++;
|
||||
} else {
|
||||
ContextRecord *back = std::addressof(this->record_list.back());
|
||||
this->record_list.pop_back();
|
||||
this->record_list.push_front(*record.release());
|
||||
ContextRecord *back = std::addressof(m_record_list.back());
|
||||
m_record_list.pop_back();
|
||||
m_record_list.push_front(*record.release());
|
||||
delete back;
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace ams::erpt::srv {
|
||||
|
||||
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.category == entry->category;
|
||||
return cur.m_category == entry->category;
|
||||
});
|
||||
R_UNLESS(it != g_category_list.end(), erpt::ResultCategoryNotFound());
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace ams::erpt::srv {
|
||||
|
||||
Result Context::SubmitContextRecord(std::unique_ptr<ContextRecord> record) {
|
||||
auto it = util::range::find_if(g_category_list, [&](const Context &cur) {
|
||||
return cur.category == record->ctx.category;
|
||||
return cur.m_category == record->m_ctx.category;
|
||||
});
|
||||
R_UNLESS(it != g_category_list.end(), erpt::ResultCategoryNotFound());
|
||||
|
||||
|
||||
@@ -25,10 +25,10 @@ namespace ams::erpt::srv {
|
||||
|
||||
class Context : public Allocator, public util::IntrusiveListBaseNode<Context> {
|
||||
private:
|
||||
const CategoryId category;
|
||||
const u32 max_record_count;
|
||||
u32 record_count;
|
||||
util::IntrusiveListBaseTraits<ContextRecord>::ListType record_list;
|
||||
const CategoryId m_category;
|
||||
const u32 m_max_record_count;
|
||||
u32 m_record_count;
|
||||
util::IntrusiveListBaseTraits<ContextRecord>::ListType m_record_list;
|
||||
public:
|
||||
Context(CategoryId cat, u32 max_records);
|
||||
~Context();
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
namespace ams::erpt::srv {
|
||||
|
||||
u32 ContextRecord::s_record_count = 0;
|
||||
constinit u32 ContextRecord::s_record_count = 0;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -34,56 +34,56 @@ namespace ams::erpt::srv {
|
||||
}
|
||||
|
||||
ContextRecord::ContextRecord() {
|
||||
this->ctx = {};
|
||||
m_ctx = {};
|
||||
}
|
||||
|
||||
ContextRecord::ContextRecord(CategoryId category, u32 array_buf_size) {
|
||||
this->ctx = {
|
||||
m_ctx = {
|
||||
.category = category,
|
||||
.array_buffer = static_cast<u8 *>(Allocate(array_buf_size)),
|
||||
};
|
||||
if (this->ctx.array_buffer != nullptr) {
|
||||
this->ctx.array_buffer_size = array_buf_size;
|
||||
this->ctx.array_free_count = array_buf_size;
|
||||
if (m_ctx.array_buffer != nullptr) {
|
||||
m_ctx.array_buffer_size = array_buf_size;
|
||||
m_ctx.array_free_count = array_buf_size;
|
||||
}
|
||||
}
|
||||
|
||||
ContextRecord::~ContextRecord() {
|
||||
if (this->ctx.array_buffer != nullptr) {
|
||||
Deallocate(this->ctx.array_buffer);
|
||||
if (m_ctx.array_buffer != nullptr) {
|
||||
Deallocate(m_ctx.array_buffer);
|
||||
}
|
||||
|
||||
AMS_ABORT_UNLESS(s_record_count >= this->ctx.field_count);
|
||||
s_record_count -= this->ctx.field_count;
|
||||
AMS_ABORT_UNLESS(s_record_count >= m_ctx.field_count);
|
||||
s_record_count -= m_ctx.field_count;
|
||||
}
|
||||
|
||||
Result ContextRecord::Initialize(const ContextEntry *ctx_ptr, const u8 *data, u32 data_size) {
|
||||
R_UNLESS(data_size <= ArrayBufferSizeMax, erpt::ResultInvalidArgument());
|
||||
|
||||
this->ctx.version = ctx_ptr->version;
|
||||
this->ctx.field_count = ctx_ptr->field_count;
|
||||
this->ctx.category = ctx_ptr->category;
|
||||
this->ctx.array_buffer = nullptr;
|
||||
this->ctx.array_buffer_size = data_size;
|
||||
this->ctx.array_free_count = 0;
|
||||
m_ctx.version = ctx_ptr->version;
|
||||
m_ctx.field_count = ctx_ptr->field_count;
|
||||
m_ctx.category = ctx_ptr->category;
|
||||
m_ctx.array_buffer = nullptr;
|
||||
m_ctx.array_buffer_size = data_size;
|
||||
m_ctx.array_free_count = 0;
|
||||
|
||||
auto guard = SCOPE_GUARD { this->ctx.field_count = 0; };
|
||||
auto guard = SCOPE_GUARD { m_ctx.field_count = 0; };
|
||||
|
||||
R_UNLESS(this->ctx.field_count <= FieldsPerContext, erpt::ResultInvalidArgument());
|
||||
R_UNLESS(0 <= this->ctx.category && this->ctx.category < CategoryId_Count, erpt::ResultInvalidArgument());
|
||||
R_UNLESS(m_ctx.field_count <= FieldsPerContext, erpt::ResultInvalidArgument());
|
||||
R_UNLESS(0 <= m_ctx.category && m_ctx.category < CategoryId_Count, erpt::ResultInvalidArgument());
|
||||
|
||||
for (u32 i = 0; i < this->ctx.field_count; i++) {
|
||||
this->ctx.fields[i] = ctx_ptr->fields[i];
|
||||
for (u32 i = 0; i < m_ctx.field_count; i++) {
|
||||
m_ctx.fields[i] = ctx_ptr->fields[i];
|
||||
|
||||
R_UNLESS(0 <= this->ctx.fields[i].id && this->ctx.fields[i].id < FieldId_Count, erpt::ResultInvalidArgument());
|
||||
R_UNLESS(0 <= this->ctx.fields[i].type && this->ctx.fields[i].type < FieldType_Count, erpt::ResultInvalidArgument());
|
||||
R_UNLESS(0 <= m_ctx.fields[i].id && m_ctx.fields[i].id < FieldId_Count, erpt::ResultInvalidArgument());
|
||||
R_UNLESS(0 <= m_ctx.fields[i].type && m_ctx.fields[i].type < FieldType_Count, erpt::ResultInvalidArgument());
|
||||
|
||||
R_UNLESS(this->ctx.fields[i].type == FieldToTypeMap[this->ctx.fields[i].id], erpt::ResultFieldTypeMismatch());
|
||||
R_UNLESS(this->ctx.category == FieldToCategoryMap[this->ctx.fields[i].id], erpt::ResultFieldCategoryMismatch());
|
||||
R_UNLESS(m_ctx.fields[i].type == FieldToTypeMap[m_ctx.fields[i].id], erpt::ResultFieldTypeMismatch());
|
||||
R_UNLESS(m_ctx.category == FieldToCategoryMap[m_ctx.fields[i].id], erpt::ResultFieldCategoryMismatch());
|
||||
|
||||
if (IsArrayFieldType(this->ctx.fields[i].type)) {
|
||||
const u32 start_idx = this->ctx.fields[i].value_array.start_idx;
|
||||
const u32 size = this->ctx.fields[i].value_array.size;
|
||||
if (IsArrayFieldType(m_ctx.fields[i].type)) {
|
||||
const u32 start_idx = m_ctx.fields[i].value_array.start_idx;
|
||||
const u32 size = m_ctx.fields[i].value_array.size;
|
||||
const u32 end_idx = start_idx + size;
|
||||
|
||||
R_UNLESS(start_idx <= data_size, erpt::ResultInvalidArgument());
|
||||
@@ -95,25 +95,25 @@ namespace ams::erpt::srv {
|
||||
|
||||
if (data_size > 0) {
|
||||
/* If array buffer isn't nullptr, we'll leak memory here, so verify that it is. */
|
||||
AMS_ABORT_UNLESS(this->ctx.array_buffer == nullptr);
|
||||
AMS_ABORT_UNLESS(m_ctx.array_buffer == nullptr);
|
||||
|
||||
this->ctx.array_buffer = static_cast<u8 *>(AllocateWithAlign(data_size, alignof(u64)));
|
||||
R_UNLESS(this->ctx.array_buffer != nullptr, erpt::ResultOutOfMemory());
|
||||
m_ctx.array_buffer = static_cast<u8 *>(AllocateWithAlign(data_size, alignof(u64)));
|
||||
R_UNLESS(m_ctx.array_buffer != nullptr, erpt::ResultOutOfMemory());
|
||||
|
||||
std::memcpy(this->ctx.array_buffer, data, data_size);
|
||||
std::memcpy(m_ctx.array_buffer, data, data_size);
|
||||
}
|
||||
|
||||
guard.Cancel();
|
||||
s_record_count += this->ctx.field_count;
|
||||
s_record_count += m_ctx.field_count;
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ContextRecord::Add(FieldId field_id, bool value_bool) {
|
||||
R_UNLESS(this->ctx.field_count < FieldsPerContext, erpt::ResultOutOfFieldSpace());
|
||||
R_UNLESS(m_ctx.field_count < FieldsPerContext, erpt::ResultOutOfFieldSpace());
|
||||
|
||||
s_record_count++;
|
||||
auto &field = this->ctx.fields[this->ctx.field_count++];
|
||||
auto &field = m_ctx.fields[m_ctx.field_count++];
|
||||
|
||||
field.id = field_id;
|
||||
field.type = FieldType_Bool;
|
||||
@@ -124,10 +124,10 @@ namespace ams::erpt::srv {
|
||||
}
|
||||
|
||||
Result ContextRecord::Add(FieldId field_id, u32 value_u32) {
|
||||
R_UNLESS(this->ctx.field_count < FieldsPerContext, erpt::ResultOutOfFieldSpace());
|
||||
R_UNLESS(m_ctx.field_count < FieldsPerContext, erpt::ResultOutOfFieldSpace());
|
||||
|
||||
s_record_count++;
|
||||
auto &field = this->ctx.fields[this->ctx.field_count++];
|
||||
auto &field = m_ctx.fields[m_ctx.field_count++];
|
||||
|
||||
field.id = field_id;
|
||||
field.type = FieldType_NumericU32;
|
||||
@@ -138,10 +138,10 @@ namespace ams::erpt::srv {
|
||||
}
|
||||
|
||||
Result ContextRecord::Add(FieldId field_id, u64 value_u64) {
|
||||
R_UNLESS(this->ctx.field_count < FieldsPerContext, erpt::ResultOutOfFieldSpace());
|
||||
R_UNLESS(m_ctx.field_count < FieldsPerContext, erpt::ResultOutOfFieldSpace());
|
||||
|
||||
s_record_count++;
|
||||
auto &field = this->ctx.fields[this->ctx.field_count++];
|
||||
auto &field = m_ctx.fields[m_ctx.field_count++];
|
||||
|
||||
field.id = field_id;
|
||||
field.type = FieldType_NumericU64;
|
||||
@@ -152,10 +152,10 @@ namespace ams::erpt::srv {
|
||||
}
|
||||
|
||||
Result ContextRecord::Add(FieldId field_id, s32 value_i32) {
|
||||
R_UNLESS(this->ctx.field_count < FieldsPerContext, erpt::ResultOutOfFieldSpace());
|
||||
R_UNLESS(m_ctx.field_count < FieldsPerContext, erpt::ResultOutOfFieldSpace());
|
||||
|
||||
s_record_count++;
|
||||
auto &field = this->ctx.fields[this->ctx.field_count++];
|
||||
auto &field = m_ctx.fields[m_ctx.field_count++];
|
||||
|
||||
field.id = field_id;
|
||||
field.type = FieldType_NumericI32;
|
||||
@@ -166,10 +166,10 @@ namespace ams::erpt::srv {
|
||||
}
|
||||
|
||||
Result ContextRecord::Add(FieldId field_id, s64 value_i64) {
|
||||
R_UNLESS(this->ctx.field_count < FieldsPerContext, erpt::ResultOutOfFieldSpace());
|
||||
R_UNLESS(m_ctx.field_count < FieldsPerContext, erpt::ResultOutOfFieldSpace());
|
||||
|
||||
s_record_count++;
|
||||
auto &field = this->ctx.fields[this->ctx.field_count++];
|
||||
auto &field = m_ctx.fields[m_ctx.field_count++];
|
||||
|
||||
field.id = field_id;
|
||||
field.type = FieldType_NumericI64;
|
||||
@@ -180,14 +180,14 @@ namespace ams::erpt::srv {
|
||||
}
|
||||
|
||||
Result ContextRecord::Add(FieldId field_id, const void *arr, u32 size, FieldType type) {
|
||||
R_UNLESS(this->ctx.field_count < FieldsPerContext, erpt::ResultOutOfFieldSpace());
|
||||
R_UNLESS(size <= this->ctx.array_free_count, erpt::ResultOutOfArraySpace());
|
||||
R_UNLESS(m_ctx.field_count < FieldsPerContext, erpt::ResultOutOfFieldSpace());
|
||||
R_UNLESS(size <= m_ctx.array_free_count, erpt::ResultOutOfArraySpace());
|
||||
|
||||
const u32 start_idx = this->ctx.array_buffer_size - this->ctx.array_free_count;
|
||||
this->ctx.array_free_count -= size;
|
||||
const u32 start_idx = m_ctx.array_buffer_size - m_ctx.array_free_count;
|
||||
m_ctx.array_free_count -= size;
|
||||
|
||||
s_record_count++;
|
||||
auto &field = this->ctx.fields[this->ctx.field_count++];
|
||||
auto &field = m_ctx.fields[m_ctx.field_count++];
|
||||
|
||||
field.id = field_id;
|
||||
field.type = type;
|
||||
@@ -197,7 +197,7 @@ namespace ams::erpt::srv {
|
||||
.size = size,
|
||||
};
|
||||
|
||||
std::memcpy(this->ctx.array_buffer + start_idx, arr, size);
|
||||
std::memcpy(m_ctx.array_buffer + start_idx, arr, size);
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace ams::erpt::srv {
|
||||
return s_record_count;
|
||||
}
|
||||
private:
|
||||
ContextEntry ctx;
|
||||
ContextEntry m_ctx;
|
||||
private:
|
||||
Result Add(FieldId field_id, const void *arr, u32 size, FieldType type);
|
||||
public:
|
||||
@@ -39,7 +39,7 @@ namespace ams::erpt::srv {
|
||||
~ContextRecord();
|
||||
|
||||
const ContextEntry *GetContextEntryPtr() const {
|
||||
return std::addressof(this->ctx);
|
||||
return std::addressof(m_ctx);
|
||||
}
|
||||
|
||||
Result Initialize(const ContextEntry *ctx_ptr, const u8 *data, u32 data_size);
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
|
||||
namespace ams::erpt::srv {
|
||||
|
||||
util::IntrusiveListBaseTraits<JournalRecord<AttachmentInfo>>::ListType JournalForAttachments::s_attachment_list;
|
||||
u32 JournalForAttachments::s_attachment_count = 0;
|
||||
u32 JournalForAttachments::s_used_storage = 0;
|
||||
constinit util::IntrusiveListBaseTraits<JournalRecord<AttachmentInfo>>::ListType JournalForAttachments::s_attachment_list;
|
||||
constinit u32 JournalForAttachments::s_attachment_count = 0;
|
||||
constinit u32 JournalForAttachments::s_used_storage = 0;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace ams::erpt::srv {
|
||||
auto *record = std::addressof(*it);
|
||||
it = s_attachment_list.erase(s_attachment_list.iterator_to(*record));
|
||||
if (record->RemoveReference()) {
|
||||
Stream::DeleteStream(Attachment::FileName(record->info.attachment_id).name);
|
||||
Stream::DeleteStream(Attachment::FileName(record->m_info.attachment_id).name);
|
||||
delete record;
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ namespace ams::erpt::srv {
|
||||
Result JournalForAttachments::CommitJournal(Stream *stream) {
|
||||
R_TRY(stream->WriteStream(reinterpret_cast<const u8 *>(std::addressof(s_attachment_count)), sizeof(s_attachment_count)));
|
||||
for (auto it = s_attachment_list.crbegin(); it != s_attachment_list.crend(); it++) {
|
||||
R_TRY(stream->WriteStream(reinterpret_cast<const u8 *>(std::addressof(it->info)), sizeof(it->info)));
|
||||
R_TRY(stream->WriteStream(reinterpret_cast<const u8 *>(std::addressof(it->m_info)), sizeof(it->m_info)));
|
||||
}
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -56,17 +56,17 @@ namespace ams::erpt::srv {
|
||||
Result JournalForAttachments::DeleteAttachments(ReportId report_id) {
|
||||
for (auto it = s_attachment_list.begin(); it != s_attachment_list.end(); /* ... */) {
|
||||
auto *record = std::addressof(*it);
|
||||
if (record->info.owner_report_id == report_id) {
|
||||
if (record->m_info.owner_report_id == report_id) {
|
||||
/* Erase from the list. */
|
||||
it = s_attachment_list.erase(s_attachment_list.iterator_to(*record));
|
||||
|
||||
/* Update storage tracking counts. */
|
||||
--s_attachment_count;
|
||||
s_used_storage -= static_cast<u32>(record->info.attachment_size);
|
||||
s_used_storage -= static_cast<u32>(record->m_info.attachment_size);
|
||||
|
||||
/* Delete the object, if we should. */
|
||||
if (record->RemoveReference()) {
|
||||
Stream::DeleteStream(Attachment::FileName(record->info.attachment_id).name);
|
||||
Stream::DeleteStream(Attachment::FileName(record->m_info.attachment_id).name);
|
||||
delete record;
|
||||
}
|
||||
} else {
|
||||
@@ -80,8 +80,8 @@ namespace ams::erpt::srv {
|
||||
Result JournalForAttachments::GetAttachmentList(AttachmentList *out, ReportId report_id) {
|
||||
u32 count = 0;
|
||||
for (auto it = s_attachment_list.cbegin(); it != s_attachment_list.cend() && count < util::size(out->attachments); it++) {
|
||||
if (report_id == it->info.owner_report_id) {
|
||||
out->attachments[count++] = it->info;
|
||||
if (report_id == it->m_info.owner_report_id) {
|
||||
out->attachments[count++] = it->m_info;
|
||||
}
|
||||
}
|
||||
out->attachment_count = count;
|
||||
@@ -118,17 +118,17 @@ namespace ams::erpt::srv {
|
||||
|
||||
auto record_guard = SCOPE_GUARD { delete record; };
|
||||
|
||||
if (R_FAILED(Stream::GetStreamSize(std::addressof(record->info.attachment_size), Attachment::FileName(record->info.attachment_id).name))) {
|
||||
if (R_FAILED(Stream::GetStreamSize(std::addressof(record->m_info.attachment_size), Attachment::FileName(record->m_info.attachment_id).name))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (record->info.flags.Test<AttachmentFlag::HasOwner>() && JournalForReports::RetrieveRecord(record->info.owner_report_id) != nullptr) {
|
||||
if (record->m_info.flags.Test<AttachmentFlag::HasOwner>() && JournalForReports::RetrieveRecord(record->m_info.owner_report_id) != nullptr) {
|
||||
/* NOTE: Nintendo does not check the result of storing the new record... */
|
||||
record_guard.Cancel();
|
||||
StoreRecord(record);
|
||||
} else {
|
||||
/* If the attachment has no owner (or we deleted the report), delete the file associated with it. */
|
||||
Stream::DeleteStream(Attachment::FileName(record->info.attachment_id).name);
|
||||
Stream::DeleteStream(Attachment::FileName(record->m_info.attachment_id).name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ namespace ams::erpt::srv {
|
||||
|
||||
JournalRecord<AttachmentInfo> *JournalForAttachments::RetrieveRecord(AttachmentId attachment_id) {
|
||||
for (auto it = s_attachment_list.begin(); it != s_attachment_list.end(); it++) {
|
||||
if (auto *record = std::addressof(*it); record->info.attachment_id == attachment_id) {
|
||||
if (auto *record = std::addressof(*it); record->m_info.attachment_id == attachment_id) {
|
||||
return record;
|
||||
}
|
||||
}
|
||||
@@ -148,11 +148,11 @@ namespace ams::erpt::srv {
|
||||
Result JournalForAttachments::SetOwner(AttachmentId attachment_id, ReportId report_id) {
|
||||
for (auto it = s_attachment_list.begin(); it != s_attachment_list.end(); it++) {
|
||||
auto *record = std::addressof(*it);
|
||||
if (record->info.attachment_id == attachment_id) {
|
||||
R_UNLESS(!record->info.flags.Test<AttachmentFlag::HasOwner>(), erpt::ResultAlreadyOwned());
|
||||
if (record->m_info.attachment_id == attachment_id) {
|
||||
R_UNLESS(!record->m_info.flags.Test<AttachmentFlag::HasOwner>(), erpt::ResultAlreadyOwned());
|
||||
|
||||
record->info.owner_report_id = report_id;
|
||||
record->info.flags.Set<AttachmentFlag::HasOwner>();
|
||||
record->m_info.owner_report_id = report_id;
|
||||
record->m_info.flags.Set<AttachmentFlag::HasOwner>();
|
||||
return ResultSuccess();
|
||||
}
|
||||
}
|
||||
@@ -162,7 +162,7 @@ namespace ams::erpt::srv {
|
||||
Result JournalForAttachments::StoreRecord(JournalRecord<AttachmentInfo> *record) {
|
||||
/* Check if the record already exists. */
|
||||
for (auto it = s_attachment_list.begin(); it != s_attachment_list.end(); it++) {
|
||||
R_UNLESS(it->info.attachment_id != record->info.attachment_id, erpt::ResultAlreadyExists());
|
||||
R_UNLESS(it->m_info.attachment_id != record->m_info.attachment_id, erpt::ResultAlreadyExists());
|
||||
}
|
||||
|
||||
/* Add a reference to the new record. */
|
||||
@@ -171,7 +171,7 @@ namespace ams::erpt::srv {
|
||||
/* Push the record into the list. */
|
||||
s_attachment_list.push_front(*record);
|
||||
s_attachment_count++;
|
||||
s_used_storage += static_cast<u32>(record->info.attachment_size);
|
||||
s_used_storage += static_cast<u32>(record->m_info.attachment_size);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
namespace ams::erpt::srv {
|
||||
|
||||
JournalMeta JournalForMeta::s_journal_meta;
|
||||
constinit JournalMeta JournalForMeta::s_journal_meta;
|
||||
|
||||
void JournalForMeta::InitializeJournal() {
|
||||
std::memset(std::addressof(s_journal_meta), 0, sizeof(s_journal_meta));
|
||||
|
||||
@@ -19,17 +19,17 @@
|
||||
|
||||
namespace ams::erpt::srv {
|
||||
|
||||
util::IntrusiveListBaseTraits<JournalRecord<ReportInfo>>::ListType JournalForReports::s_record_list;
|
||||
u32 JournalForReports::s_record_count = 0;
|
||||
u32 JournalForReports::s_record_count_by_type[ReportType_Count] = {};
|
||||
u32 JournalForReports::s_used_storage = 0;
|
||||
constinit util::IntrusiveListBaseTraits<JournalRecord<ReportInfo>>::ListType JournalForReports::s_record_list;
|
||||
constinit u32 JournalForReports::s_record_count = 0;
|
||||
constinit u32 JournalForReports::s_record_count_by_type[ReportType_Count] = {};
|
||||
constinit u32 JournalForReports::s_used_storage = 0;
|
||||
|
||||
void JournalForReports::CleanupReports() {
|
||||
for (auto it = s_record_list.begin(); it != s_record_list.end(); /* ... */) {
|
||||
auto *record = std::addressof(*it);
|
||||
it = s_record_list.erase(s_record_list.iterator_to(*record));
|
||||
if (record->RemoveReference()) {
|
||||
Stream::DeleteStream(Report::FileName(record->info.id, false).name);
|
||||
Stream::DeleteStream(Report::FileName(record->m_info.id, false).name);
|
||||
delete record;
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,7 @@ namespace ams::erpt::srv {
|
||||
Result JournalForReports::CommitJournal(Stream *stream) {
|
||||
R_TRY(stream->WriteStream(reinterpret_cast<const u8 *>(std::addressof(s_record_count)), sizeof(s_record_count)));
|
||||
for (auto it = s_record_list.crbegin(); it != s_record_list.crend(); it++) {
|
||||
R_TRY(stream->WriteStream(reinterpret_cast<const u8 *>(std::addressof(it->info)), sizeof(it->info)));
|
||||
R_TRY(stream->WriteStream(reinterpret_cast<const u8 *>(std::addressof(it->m_info)), sizeof(it->m_info)));
|
||||
}
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -55,22 +55,22 @@ namespace ams::erpt::srv {
|
||||
|
||||
/* Update storage tracking counts. */
|
||||
--s_record_count;
|
||||
--s_record_count_by_type[record->info.type];
|
||||
s_used_storage -= static_cast<u32>(record->info.report_size);
|
||||
--s_record_count_by_type[record->m_info.type];
|
||||
s_used_storage -= static_cast<u32>(record->m_info.report_size);
|
||||
|
||||
/* If we should increment count, do so. */
|
||||
if (increment_count) {
|
||||
JournalForMeta::IncrementCount(record->info.flags.Test<ReportFlag::Transmitted>(), record->info.type);
|
||||
JournalForMeta::IncrementCount(record->m_info.flags.Test<ReportFlag::Transmitted>(), record->m_info.type);
|
||||
}
|
||||
|
||||
/* Delete any attachments. */
|
||||
if (force_delete_attachments || record->info.flags.Test<ReportFlag::HasAttachment>()) {
|
||||
JournalForAttachments::DeleteAttachments(record->info.id);
|
||||
if (force_delete_attachments || record->m_info.flags.Test<ReportFlag::HasAttachment>()) {
|
||||
JournalForAttachments::DeleteAttachments(record->m_info.id);
|
||||
}
|
||||
|
||||
/* Delete the object, if we should. */
|
||||
if (record->RemoveReference()) {
|
||||
Stream::DeleteStream(Report::FileName(record->info.id, false).name);
|
||||
Stream::DeleteStream(Report::FileName(record->m_info.id, false).name);
|
||||
delete record;
|
||||
}
|
||||
}
|
||||
@@ -78,7 +78,7 @@ namespace ams::erpt::srv {
|
||||
Result JournalForReports::DeleteReport(ReportId report_id) {
|
||||
for (auto it = s_record_list.begin(); it != s_record_list.end(); it++) {
|
||||
auto *record = std::addressof(*it);
|
||||
if (record->info.id == report_id) {
|
||||
if (record->m_info.id == report_id) {
|
||||
EraseReportImpl(record, false, false);
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -89,7 +89,7 @@ namespace ams::erpt::srv {
|
||||
Result JournalForReports::DeleteReportWithAttachments() {
|
||||
for (auto it = s_record_list.rbegin(); it != s_record_list.rend(); it++) {
|
||||
auto *record = std::addressof(*it);
|
||||
if (record->info.flags.Test<ReportFlag::HasAttachment>()) {
|
||||
if (record->m_info.flags.Test<ReportFlag::HasAttachment>()) {
|
||||
EraseReportImpl(record, true, true);
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -100,7 +100,7 @@ namespace ams::erpt::srv {
|
||||
s64 JournalForReports::GetMaxReportSize() {
|
||||
s64 max_size = 0;
|
||||
for (auto it = s_record_list.begin(); it != s_record_list.end(); it++) {
|
||||
max_size = std::max(max_size, it->info.report_size);
|
||||
max_size = std::max(max_size, it->m_info.report_size);
|
||||
}
|
||||
return max_size;
|
||||
}
|
||||
@@ -108,8 +108,8 @@ namespace ams::erpt::srv {
|
||||
Result JournalForReports::GetReportList(ReportList *out, ReportType type_filter) {
|
||||
u32 count = 0;
|
||||
for (auto it = s_record_list.cbegin(); it != s_record_list.cend() && count < util::size(out->reports); it++) {
|
||||
if (type_filter == ReportType_Any || type_filter == it->info.type) {
|
||||
out->reports[count++] = it->info;
|
||||
if (type_filter == ReportType_Any || type_filter == it->m_info.type) {
|
||||
out->reports[count++] = it->m_info;
|
||||
}
|
||||
}
|
||||
out->report_count = count;
|
||||
@@ -158,8 +158,8 @@ namespace ams::erpt::srv {
|
||||
/* We will ensure it is freed if we early error. */
|
||||
auto record_guard = SCOPE_GUARD { delete record; };
|
||||
|
||||
if (record->info.report_size == 0) {
|
||||
R_UNLESS(R_SUCCEEDED(Stream::GetStreamSize(std::addressof(record->info.report_size), Report::FileName(record->info.id, false).name)), erpt::ResultCorruptJournal());
|
||||
if (record->m_info.report_size == 0) {
|
||||
R_UNLESS(R_SUCCEEDED(Stream::GetStreamSize(std::addressof(record->m_info.report_size), Report::FileName(record->m_info.id, false).name)), erpt::ResultCorruptJournal());
|
||||
}
|
||||
|
||||
record_guard.Cancel();
|
||||
@@ -174,7 +174,7 @@ namespace ams::erpt::srv {
|
||||
|
||||
JournalRecord<ReportInfo> *JournalForReports::RetrieveRecord(ReportId report_id) {
|
||||
for (auto it = s_record_list.begin(); it != s_record_list.end(); it++) {
|
||||
if (auto *record = std::addressof(*it); record->info.id == report_id) {
|
||||
if (auto *record = std::addressof(*it); record->m_info.id == report_id) {
|
||||
return record;
|
||||
}
|
||||
}
|
||||
@@ -185,14 +185,14 @@ namespace ams::erpt::srv {
|
||||
Result JournalForReports::StoreRecord(JournalRecord<ReportInfo> *record) {
|
||||
/* Check if the record already exists. */
|
||||
for (auto it = s_record_list.begin(); it != s_record_list.end(); it++) {
|
||||
R_UNLESS(it->info.id != record->info.id, erpt::ResultAlreadyExists());
|
||||
R_UNLESS(it->m_info.id != record->m_info.id, erpt::ResultAlreadyExists());
|
||||
}
|
||||
|
||||
/* Delete an older report if we need to. */
|
||||
if (s_record_count >= ReportCountMax) {
|
||||
/* Nintendo deletes the oldest report from the type with the most reports. */
|
||||
/* This is an approximation of FIFO. */
|
||||
ReportType most_used_type = record->info.type;
|
||||
ReportType most_used_type = record->m_info.type;
|
||||
u32 most_used_count = s_record_count_by_type[most_used_type];
|
||||
|
||||
for (int i = ReportType_Start; i < ReportType_End; i++) {
|
||||
@@ -203,7 +203,7 @@ namespace ams::erpt::srv {
|
||||
}
|
||||
|
||||
for (auto it = s_record_list.rbegin(); it != s_record_list.rend(); it++) {
|
||||
if (it->info.type != most_used_type) {
|
||||
if (it->m_info.type != most_used_type) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -219,8 +219,8 @@ namespace ams::erpt::srv {
|
||||
/* Push the record into the list. */
|
||||
s_record_list.push_front(*record);
|
||||
s_record_count++;
|
||||
s_record_count_by_type[record->info.type]++;
|
||||
s_used_storage += static_cast<u32>(record->info.report_size);
|
||||
s_record_count_by_type[record->m_info.type]++;
|
||||
s_used_storage += static_cast<u32>(record->m_info.report_size);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
@@ -23,13 +23,13 @@ namespace ams::erpt::srv {
|
||||
template<typename Info>
|
||||
class JournalRecord : public Allocator, public RefCount, public util::IntrusiveListBaseNode<JournalRecord<Info>> {
|
||||
public:
|
||||
Info info;
|
||||
Info m_info;
|
||||
|
||||
JournalRecord() {
|
||||
std::memset(std::addressof(this->info), 0, sizeof(this->info));
|
||||
std::memset(std::addressof(m_info), 0, sizeof(m_info));
|
||||
}
|
||||
|
||||
explicit JournalRecord(Info info) : info(info) { /* ... */ }
|
||||
explicit JournalRecord(Info info) : m_info(info) { /* ... */ }
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
|
||||
namespace ams::erpt::srv {
|
||||
|
||||
lmem::HeapHandle g_heap_handle;
|
||||
ams::sf::ExpHeapAllocator g_sf_allocator;
|
||||
constinit lmem::HeapHandle g_heap_handle;
|
||||
constinit ams::sf::ExpHeapAllocator g_sf_allocator;
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
@@ -23,11 +23,11 @@ namespace ams::erpt::srv {
|
||||
|
||||
using ManagerList = util::IntrusiveListBaseTraits<ManagerImpl>::ListType;
|
||||
|
||||
ManagerList g_manager_list;
|
||||
constinit ManagerList g_manager_list;
|
||||
|
||||
}
|
||||
|
||||
ManagerImpl::ManagerImpl() : system_event(os::EventClearMode_AutoClear, true) {
|
||||
ManagerImpl::ManagerImpl() : m_system_event(os::EventClearMode_AutoClear, true) {
|
||||
g_manager_list.push_front(*this);
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace ams::erpt::srv {
|
||||
}
|
||||
|
||||
void ManagerImpl::NotifyOne() {
|
||||
this->system_event.Signal();
|
||||
m_system_event.Signal();
|
||||
}
|
||||
|
||||
Result ManagerImpl::NotifyAll() {
|
||||
@@ -53,7 +53,7 @@ namespace ams::erpt::srv {
|
||||
}
|
||||
|
||||
Result ManagerImpl::GetEvent(ams::sf::OutCopyHandle out) {
|
||||
out.SetValue(this->system_event.GetReadableHandle(), false);
|
||||
out.SetValue(m_system_event.GetReadableHandle(), false);
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace ams::erpt::srv {
|
||||
|
||||
class ManagerImpl : public util::IntrusiveListBaseNode<ManagerImpl> {
|
||||
private:
|
||||
os::SystemEvent system_event;
|
||||
os::SystemEvent m_system_event;
|
||||
public:
|
||||
ManagerImpl();
|
||||
~ManagerImpl();
|
||||
|
||||
@@ -21,17 +21,17 @@ namespace ams::erpt::srv {
|
||||
class RefCount {
|
||||
private:
|
||||
static constexpr u32 MaxReferenceCount = 1000;
|
||||
std::atomic<u32> ref_count;
|
||||
std::atomic<u32> m_ref_count;
|
||||
public:
|
||||
RefCount() : ref_count(0) { /* ... */ }
|
||||
RefCount() : m_ref_count(0) { /* ... */ }
|
||||
|
||||
void AddReference() {
|
||||
const auto prev = this->ref_count.fetch_add(1);
|
||||
const auto prev = m_ref_count.fetch_add(1);
|
||||
AMS_ABORT_UNLESS(prev <= MaxReferenceCount);
|
||||
}
|
||||
|
||||
bool RemoveReference() {
|
||||
auto prev = this->ref_count.fetch_sub(1);
|
||||
auto prev = m_ref_count.fetch_sub(1);
|
||||
AMS_ABORT_UNLESS(prev != 0);
|
||||
return prev == 1;
|
||||
}
|
||||
|
||||
@@ -34,20 +34,20 @@ namespace ams::erpt::srv {
|
||||
return report_name;
|
||||
}
|
||||
|
||||
Report::Report(JournalRecord<ReportInfo> *r, bool redirect_to_sd) : record(r), redirect_to_sd_card(redirect_to_sd) {
|
||||
this->record->AddReference();
|
||||
Report::Report(JournalRecord<ReportInfo> *r, bool redirect_to_sd) : m_record(r), m_redirect_to_sd_card(redirect_to_sd) {
|
||||
m_record->AddReference();
|
||||
}
|
||||
|
||||
Report::~Report() {
|
||||
this->CloseStream();
|
||||
if (this->record->RemoveReference()) {
|
||||
if (m_record->RemoveReference()) {
|
||||
this->DeleteStream(this->FileName().name);
|
||||
delete this->record;
|
||||
delete m_record;
|
||||
}
|
||||
}
|
||||
|
||||
ReportFileName Report::FileName() const {
|
||||
return FileName(this->record->info.id, this->redirect_to_sd_card);
|
||||
return FileName(m_record->m_info.id, m_redirect_to_sd_card);
|
||||
}
|
||||
|
||||
Result Report::Open(ReportOpenType type) {
|
||||
@@ -71,13 +71,13 @@ namespace ams::erpt::srv {
|
||||
}
|
||||
|
||||
Result Report::GetFlags(ReportFlagSet *out) const {
|
||||
*out = this->record->info.flags;
|
||||
*out = m_record->m_info.flags;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result Report::SetFlags(ReportFlagSet flags) {
|
||||
if (((~this->record->info.flags) & flags).IsAnySet()) {
|
||||
this->record->info.flags |= flags;
|
||||
if (((~m_record->m_info.flags) & flags).IsAnySet()) {
|
||||
m_record->m_info.flags |= flags;
|
||||
return Journal::Commit();
|
||||
}
|
||||
return ResultSuccess();
|
||||
|
||||
@@ -30,8 +30,8 @@ namespace ams::erpt::srv {
|
||||
|
||||
class Report : public Allocator, public Stream {
|
||||
private:
|
||||
JournalRecord<ReportInfo> *record;
|
||||
bool redirect_to_sd_card;
|
||||
JournalRecord<ReportInfo> *m_record;
|
||||
bool m_redirect_to_sd_card;
|
||||
private:
|
||||
ReportFileName FileName() const;
|
||||
public:
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
namespace ams::erpt::srv {
|
||||
|
||||
ReportImpl::ReportImpl() : report(nullptr) {
|
||||
ReportImpl::ReportImpl() : m_report(nullptr) {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
@@ -28,52 +28,52 @@ namespace ams::erpt::srv {
|
||||
}
|
||||
|
||||
Result ReportImpl::Open(const ReportId &report_id) {
|
||||
R_UNLESS(this->report == nullptr, erpt::ResultAlreadyInitialized());
|
||||
R_UNLESS(m_report == nullptr, erpt::ResultAlreadyInitialized());
|
||||
|
||||
JournalRecord<ReportInfo> *record = Journal::Retrieve(report_id);
|
||||
R_UNLESS(record != nullptr, erpt::ResultNotFound());
|
||||
|
||||
this->report = new Report(record, false);
|
||||
R_UNLESS(this->report != nullptr, erpt::ResultOutOfMemory());
|
||||
auto report_guard = SCOPE_GUARD { delete this->report; this->report = nullptr; };
|
||||
m_report = new Report(record, false);
|
||||
R_UNLESS(m_report != nullptr, erpt::ResultOutOfMemory());
|
||||
auto report_guard = SCOPE_GUARD { delete m_report; m_report = nullptr; };
|
||||
|
||||
R_TRY(this->report->Open(ReportOpenType_Read));
|
||||
R_TRY(m_report->Open(ReportOpenType_Read));
|
||||
report_guard.Cancel();
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ReportImpl::Read(ams::sf::Out<u32> out_count, const ams::sf::OutBuffer &out_buffer) {
|
||||
R_UNLESS(this->report != nullptr, erpt::ResultNotInitialized());
|
||||
R_UNLESS(m_report != nullptr, erpt::ResultNotInitialized());
|
||||
|
||||
return this->report->Read(out_count.GetPointer(), static_cast<u8 *>(out_buffer.GetPointer()), static_cast<u32>(out_buffer.GetSize()));
|
||||
return m_report->Read(out_count.GetPointer(), static_cast<u8 *>(out_buffer.GetPointer()), static_cast<u32>(out_buffer.GetSize()));
|
||||
}
|
||||
|
||||
Result ReportImpl::SetFlags(ReportFlagSet flags) {
|
||||
R_UNLESS(this->report != nullptr, erpt::ResultNotInitialized());
|
||||
R_UNLESS(m_report != nullptr, erpt::ResultNotInitialized());
|
||||
|
||||
return this->report->SetFlags(flags);
|
||||
return m_report->SetFlags(flags);
|
||||
}
|
||||
|
||||
Result ReportImpl::GetFlags(ams::sf::Out<ReportFlagSet> out) {
|
||||
R_UNLESS(this->report != nullptr, erpt::ResultNotInitialized());
|
||||
R_UNLESS(m_report != nullptr, erpt::ResultNotInitialized());
|
||||
|
||||
return this->report->GetFlags(out.GetPointer());
|
||||
return m_report->GetFlags(out.GetPointer());
|
||||
}
|
||||
|
||||
Result ReportImpl::Close() {
|
||||
if (this->report != nullptr) {
|
||||
this->report->Close();
|
||||
delete this->report;
|
||||
this->report = nullptr;
|
||||
if (m_report != nullptr) {
|
||||
m_report->Close();
|
||||
delete m_report;
|
||||
m_report = nullptr;
|
||||
}
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ReportImpl::GetSize(ams::sf::Out<s64> out) {
|
||||
R_UNLESS(this->report != nullptr, erpt::ResultNotInitialized());
|
||||
R_UNLESS(m_report != nullptr, erpt::ResultNotInitialized());
|
||||
|
||||
return this->report->GetSize(out.GetPointer());
|
||||
return m_report->GetSize(out.GetPointer());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace ams::erpt::srv {
|
||||
|
||||
class ReportImpl {
|
||||
private:
|
||||
Report *report;
|
||||
Report *m_report;
|
||||
public:
|
||||
ReportImpl();
|
||||
~ReportImpl();
|
||||
|
||||
@@ -356,16 +356,16 @@ namespace ams::erpt::srv {
|
||||
R_UNLESS(record != nullptr, erpt::ResultOutOfMemory());
|
||||
record->AddReference();
|
||||
|
||||
record->info.type = type;
|
||||
record->info.id = report_id;
|
||||
record->info.flags = erpt::srv::MakeNoReportFlags();
|
||||
record->info.timestamp_user = timestamp_user;
|
||||
record->info.timestamp_network = timestamp_network;
|
||||
record->m_info.type = type;
|
||||
record->m_info.id = report_id;
|
||||
record->m_info.flags = erpt::srv::MakeNoReportFlags();
|
||||
record->m_info.timestamp_user = timestamp_user;
|
||||
record->m_info.timestamp_network = timestamp_network;
|
||||
if (meta != nullptr) {
|
||||
record->info.meta_data = *meta;
|
||||
record->m_info.meta_data = *meta;
|
||||
}
|
||||
if (num_attachments > 0) {
|
||||
record->info.flags.Set<ReportFlag::HasAttachment>();
|
||||
record->m_info.flags.Set<ReportFlag::HasAttachment>();
|
||||
}
|
||||
|
||||
auto report = std::make_unique<Report>(record.get(), redirect_new_reports);
|
||||
@@ -373,7 +373,7 @@ namespace ams::erpt::srv {
|
||||
auto report_guard = SCOPE_GUARD { report->Delete(); };
|
||||
|
||||
R_TRY(Context::WriteContextsToReport(report.get()));
|
||||
R_TRY(report->GetSize(std::addressof(record->info.report_size)));
|
||||
R_TRY(report->GetSize(std::addressof(record->m_info.report_size)));
|
||||
|
||||
if (!redirect_new_reports) {
|
||||
/* If we're not redirecting new reports, then we want to store the report in the journal. */
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace ams::erpt::srv {
|
||||
constexpr inline sm::ServiceName ErrorReportContextServiceName = sm::ServiceName::Encode("erpt:c");
|
||||
constexpr inline sm::ServiceName ErrorReportReportServiceName = sm::ServiceName::Encode("erpt:r");
|
||||
|
||||
alignas(os::ThreadStackAlignment) u8 g_server_thread_stack[16_KB];
|
||||
alignas(os::ThreadStackAlignment) constinit u8 g_server_thread_stack[16_KB];
|
||||
|
||||
enum PortIndex {
|
||||
PortIndex_Report,
|
||||
@@ -49,8 +49,8 @@ namespace ams::erpt::srv {
|
||||
|
||||
class ErrorReportServiceManager : public ams::sf::hipc::ServerManager<ErrorReportNumServers, ErrorReportServerOptions, ErrorReportMaxSessions> {
|
||||
private:
|
||||
os::ThreadType thread;
|
||||
ams::sf::UnmanagedServiceObject<erpt::sf::IContext, erpt::srv::ContextImpl> context_session_object;
|
||||
os::ThreadType m_thread;
|
||||
ams::sf::UnmanagedServiceObject<erpt::sf::IContext, erpt::srv::ContextImpl> m_context_session_object;
|
||||
private:
|
||||
static void ThreadFunction(void *_this) {
|
||||
reinterpret_cast<ErrorReportServiceManager *>(_this)->SetupAndLoopProcess();
|
||||
@@ -67,7 +67,7 @@ namespace ams::erpt::srv {
|
||||
return this->AcceptImpl(server, intf);
|
||||
}
|
||||
case PortIndex_Context:
|
||||
return AcceptImpl(server, this->context_session_object.GetShared());
|
||||
return AcceptImpl(server, m_context_session_object.GetShared());
|
||||
default:
|
||||
return erpt::ResultNotSupported();
|
||||
}
|
||||
@@ -79,16 +79,16 @@ namespace ams::erpt::srv {
|
||||
|
||||
this->ResumeProcessing();
|
||||
|
||||
R_ABORT_UNLESS(os::CreateThread(std::addressof(this->thread), ThreadFunction, this, g_server_thread_stack, sizeof(g_server_thread_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(erpt, IpcServer)));
|
||||
os::SetThreadNamePointer(std::addressof(this->thread), AMS_GET_SYSTEM_THREAD_NAME(erpt, IpcServer));
|
||||
R_ABORT_UNLESS(os::CreateThread(std::addressof(m_thread), ThreadFunction, this, g_server_thread_stack, sizeof(g_server_thread_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(erpt, IpcServer)));
|
||||
os::SetThreadNamePointer(std::addressof(m_thread), AMS_GET_SYSTEM_THREAD_NAME(erpt, IpcServer));
|
||||
|
||||
os::StartThread(std::addressof(this->thread));
|
||||
os::StartThread(std::addressof(m_thread));
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void Wait() {
|
||||
os::WaitThread(std::addressof(this->thread));
|
||||
os::WaitThread(std::addressof(m_thread));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -136,16 +136,17 @@ namespace ams::erpt::srv {
|
||||
}
|
||||
}
|
||||
|
||||
ErrorReportServiceManager g_erpt_server_manager;
|
||||
constinit util::TypedStorage<ErrorReportServiceManager> g_erpt_server_manager;
|
||||
|
||||
}
|
||||
|
||||
Result InitializeService() {
|
||||
return g_erpt_server_manager.Initialize();
|
||||
util::ConstructAt(g_erpt_server_manager);
|
||||
return util::GetReference(g_erpt_server_manager).Initialize();
|
||||
}
|
||||
|
||||
void WaitService() {
|
||||
return g_erpt_server_manager.Wait();
|
||||
return util::GetReference(g_erpt_server_manager).Wait();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace ams::erpt::srv {
|
||||
return fs::GetFileSize(out, file);
|
||||
}
|
||||
|
||||
Stream::Stream() : buffer_size(0), file_position(0), buffer_count(0), buffer(nullptr), stream_mode(StreamMode_Invalid), initialized(false) {
|
||||
Stream::Stream() : m_buffer_size(0), m_file_position(0), m_buffer_count(0), m_buffer(nullptr), m_stream_mode(StreamMode_Invalid), m_initialized(false) {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
@@ -60,8 +60,8 @@ namespace ams::erpt::srv {
|
||||
}
|
||||
|
||||
Result Stream::OpenStream(const char *path, StreamMode mode, u32 buffer_size) {
|
||||
R_UNLESS(s_can_access_fs, erpt::ResultInvalidPowerState());
|
||||
R_UNLESS(!this->initialized, erpt::ResultAlreadyInitialized());
|
||||
R_UNLESS(s_can_access_fs, erpt::ResultInvalidPowerState());
|
||||
R_UNLESS(!m_initialized, erpt::ResultAlreadyInitialized());
|
||||
|
||||
auto lock_guard = SCOPE_GUARD {
|
||||
if (s_fs_commit_mutex.IsLockedByCurrentThread()) {
|
||||
@@ -73,7 +73,7 @@ namespace ams::erpt::srv {
|
||||
s_fs_commit_mutex.Lock();
|
||||
|
||||
while (true) {
|
||||
R_TRY_CATCH(fs::OpenFile(std::addressof(this->file_handle), path, fs::OpenMode_Write | fs::OpenMode_AllowAppend)) {
|
||||
R_TRY_CATCH(fs::OpenFile(std::addressof(m_file_handle), path, fs::OpenMode_Write | fs::OpenMode_AllowAppend)) {
|
||||
R_CATCH(fs::ResultPathNotFound) {
|
||||
R_TRY(fs::CreateFile(path, 0));
|
||||
continue;
|
||||
@@ -81,31 +81,31 @@ namespace ams::erpt::srv {
|
||||
} R_END_TRY_CATCH;
|
||||
break;
|
||||
}
|
||||
fs::SetFileSize(this->file_handle, 0);
|
||||
fs::SetFileSize(m_file_handle, 0);
|
||||
} else {
|
||||
R_UNLESS(mode == StreamMode_Read, erpt::ResultInvalidArgument());
|
||||
|
||||
R_TRY(fs::OpenFile(std::addressof(this->file_handle), path, fs::OpenMode_Read));
|
||||
R_TRY(fs::OpenFile(std::addressof(m_file_handle), path, fs::OpenMode_Read));
|
||||
}
|
||||
auto file_guard = SCOPE_GUARD { fs::CloseFile(this->file_handle); };
|
||||
auto file_guard = SCOPE_GUARD { fs::CloseFile(m_file_handle); };
|
||||
|
||||
std::strncpy(this->file_name, path, sizeof(this->file_name));
|
||||
this->file_name[sizeof(this->file_name) - 1] = '\x00';
|
||||
std::strncpy(m_file_name, path, sizeof(m_file_name));
|
||||
m_file_name[sizeof(m_file_name) - 1] = '\x00';
|
||||
|
||||
if (buffer_size > 0) {
|
||||
this->buffer = reinterpret_cast<u8 *>(Allocate(buffer_size));
|
||||
AMS_ASSERT(this->buffer != nullptr);
|
||||
m_buffer = reinterpret_cast<u8 *>(Allocate(buffer_size));
|
||||
AMS_ASSERT(m_buffer != nullptr);
|
||||
} else {
|
||||
this->buffer = nullptr;
|
||||
m_buffer = nullptr;
|
||||
}
|
||||
|
||||
|
||||
this->buffer_size = this->buffer != nullptr ? buffer_size : 0;
|
||||
this->buffer_count = 0;
|
||||
this->buffer_position = 0;
|
||||
this->file_position = 0;
|
||||
this->stream_mode = mode;
|
||||
this->initialized = true;
|
||||
m_buffer_size = m_buffer != nullptr ? buffer_size : 0;
|
||||
m_buffer_count = 0;
|
||||
m_buffer_position = 0;
|
||||
m_file_position = 0;
|
||||
m_stream_mode = mode;
|
||||
m_initialized = true;
|
||||
|
||||
file_guard.Cancel();
|
||||
lock_guard.Cancel();
|
||||
@@ -113,11 +113,11 @@ namespace ams::erpt::srv {
|
||||
}
|
||||
|
||||
Result Stream::ReadStream(u32 *out, u8 *dst, u32 dst_size) {
|
||||
R_UNLESS(s_can_access_fs, erpt::ResultInvalidPowerState());
|
||||
R_UNLESS(this->initialized, erpt::ResultNotInitialized());
|
||||
R_UNLESS(this->stream_mode == StreamMode_Read, erpt::ResultNotInitialized());
|
||||
R_UNLESS(out != nullptr, erpt::ResultInvalidArgument());
|
||||
R_UNLESS(dst != nullptr, erpt::ResultInvalidArgument());
|
||||
R_UNLESS(s_can_access_fs, erpt::ResultInvalidPowerState());
|
||||
R_UNLESS(m_initialized, erpt::ResultNotInitialized());
|
||||
R_UNLESS(m_stream_mode == StreamMode_Read, erpt::ResultNotInitialized());
|
||||
R_UNLESS(out != nullptr, erpt::ResultInvalidArgument());
|
||||
R_UNLESS(dst != nullptr, erpt::ResultInvalidArgument());
|
||||
|
||||
size_t fs_read_size;
|
||||
u32 read_count = 0;
|
||||
@@ -126,30 +126,30 @@ namespace ams::erpt::srv {
|
||||
*out = read_count;
|
||||
};
|
||||
|
||||
if (this->buffer != nullptr) {
|
||||
if (m_buffer != nullptr) {
|
||||
while (dst_size > 0) {
|
||||
if (u32 cur = std::min<u32>(this->buffer_count - this->buffer_position, dst_size); cur > 0) {
|
||||
std::memcpy(dst, this->buffer + this->buffer_position, cur);
|
||||
this->buffer_position += cur;
|
||||
dst += cur;
|
||||
dst_size -= cur;
|
||||
read_count += cur;
|
||||
if (u32 cur = std::min<u32>(m_buffer_count - m_buffer_position, dst_size); cur > 0) {
|
||||
std::memcpy(dst, m_buffer + m_buffer_position, cur);
|
||||
m_buffer_position += cur;
|
||||
dst += cur;
|
||||
dst_size -= cur;
|
||||
read_count += cur;
|
||||
} else {
|
||||
R_TRY(fs::ReadFile(std::addressof(fs_read_size), this->file_handle, this->file_position, this->buffer, this->buffer_size));
|
||||
R_TRY(fs::ReadFile(std::addressof(fs_read_size), m_file_handle, m_file_position, m_buffer, m_buffer_size));
|
||||
|
||||
this->buffer_position = 0;
|
||||
this->file_position += static_cast<u32>(fs_read_size);
|
||||
this->buffer_count = static_cast<u32>(fs_read_size);
|
||||
m_buffer_position = 0;
|
||||
m_file_position += static_cast<u32>(fs_read_size);
|
||||
m_buffer_count = static_cast<u32>(fs_read_size);
|
||||
|
||||
if (this->buffer_count == 0) {
|
||||
if (m_buffer_count == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
R_TRY(fs::ReadFile(std::addressof(fs_read_size), this->file_handle, this->file_position, dst, dst_size));
|
||||
R_TRY(fs::ReadFile(std::addressof(fs_read_size), m_file_handle, m_file_position, dst, dst_size));
|
||||
|
||||
this->file_position += static_cast<u32>(fs_read_size);
|
||||
m_file_position += static_cast<u32>(fs_read_size);
|
||||
read_count = static_cast<u32>(fs_read_size);
|
||||
}
|
||||
|
||||
@@ -157,47 +157,47 @@ namespace ams::erpt::srv {
|
||||
}
|
||||
|
||||
Result Stream::WriteStream(const u8 *src, u32 src_size) {
|
||||
R_UNLESS(s_can_access_fs, erpt::ResultInvalidPowerState());
|
||||
R_UNLESS(this->initialized, erpt::ResultNotInitialized());
|
||||
R_UNLESS(this->stream_mode == StreamMode_Write, erpt::ResultNotInitialized());
|
||||
R_UNLESS(src != nullptr || src_size == 0, erpt::ResultInvalidArgument());
|
||||
R_UNLESS(s_can_access_fs, erpt::ResultInvalidPowerState());
|
||||
R_UNLESS(m_initialized, erpt::ResultNotInitialized());
|
||||
R_UNLESS(m_stream_mode == StreamMode_Write, erpt::ResultNotInitialized());
|
||||
R_UNLESS(src != nullptr || src_size == 0, erpt::ResultInvalidArgument());
|
||||
|
||||
if (this->buffer != nullptr) {
|
||||
if (m_buffer != nullptr) {
|
||||
while (src_size > 0) {
|
||||
if (u32 cur = std::min<u32>(this->buffer_size - this->buffer_count, src_size); cur > 0) {
|
||||
std::memcpy(this->buffer + this->buffer_count, src, cur);
|
||||
this->buffer_count += cur;
|
||||
src += cur;
|
||||
src_size -= cur;
|
||||
if (u32 cur = std::min<u32>(m_buffer_size - m_buffer_count, src_size); cur > 0) {
|
||||
std::memcpy(m_buffer + m_buffer_count, src, cur);
|
||||
m_buffer_count += cur;
|
||||
src += cur;
|
||||
src_size -= cur;
|
||||
}
|
||||
|
||||
if (this->buffer_count == this->buffer_size) {
|
||||
if (m_buffer_count == m_buffer_size) {
|
||||
R_TRY(this->Flush());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
R_TRY(fs::WriteFile(this->file_handle, this->file_position, src, src_size, fs::WriteOption::None));
|
||||
this->file_position += src_size;
|
||||
R_TRY(fs::WriteFile(m_file_handle, m_file_position, src, src_size, fs::WriteOption::None));
|
||||
m_file_position += src_size;
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void Stream::CloseStream() {
|
||||
if (this->initialized) {
|
||||
if (m_initialized) {
|
||||
if (s_can_access_fs) {
|
||||
if (this->stream_mode == StreamMode_Write) {
|
||||
if (m_stream_mode == StreamMode_Write) {
|
||||
this->Flush();
|
||||
fs::FlushFile(this->file_handle);
|
||||
fs::FlushFile(m_file_handle);
|
||||
}
|
||||
fs::CloseFile(this->file_handle);
|
||||
fs::CloseFile(m_file_handle);
|
||||
}
|
||||
|
||||
if (this->buffer != nullptr) {
|
||||
Deallocate(this->buffer);
|
||||
if (m_buffer != nullptr) {
|
||||
Deallocate(m_buffer);
|
||||
}
|
||||
|
||||
this->initialized = false;
|
||||
m_initialized = false;
|
||||
|
||||
if (s_fs_commit_mutex.IsLockedByCurrentThread()) {
|
||||
s_fs_commit_mutex.Unlock();
|
||||
@@ -206,17 +206,17 @@ namespace ams::erpt::srv {
|
||||
}
|
||||
|
||||
Result Stream::GetStreamSize(s64 *out) const {
|
||||
return GetStreamSize(out, this->file_name);
|
||||
return GetStreamSize(out, m_file_name);
|
||||
}
|
||||
|
||||
Result Stream::Flush() {
|
||||
AMS_ASSERT(s_fs_commit_mutex.IsLockedByCurrentThread());
|
||||
|
||||
R_SUCCEED_IF(this->buffer_count == 0);
|
||||
R_TRY(fs::WriteFile(this->file_handle, this->file_position, this->buffer, this->buffer_count, fs::WriteOption::None));
|
||||
R_SUCCEED_IF(m_buffer_count == 0);
|
||||
R_TRY(fs::WriteFile(m_file_handle, m_file_position, m_buffer, m_buffer_count, fs::WriteOption::None));
|
||||
|
||||
this->file_position += this->buffer_count;
|
||||
this->buffer_count = 0;
|
||||
m_file_position += m_buffer_count;
|
||||
m_buffer_count = 0;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
|
||||
@@ -29,15 +29,15 @@ namespace ams::erpt::srv {
|
||||
static bool s_can_access_fs;
|
||||
static os::SdkMutex s_fs_commit_mutex;
|
||||
private:
|
||||
u32 buffer_size;
|
||||
u32 file_position;
|
||||
u32 buffer_position;
|
||||
u32 buffer_count;
|
||||
u8 *buffer;
|
||||
StreamMode stream_mode;
|
||||
bool initialized;
|
||||
fs::FileHandle file_handle;
|
||||
char file_name[ReportFileNameLength];
|
||||
u32 m_buffer_size;
|
||||
u32 m_file_position;
|
||||
u32 m_buffer_position;
|
||||
u32 m_buffer_count;
|
||||
u8 *m_buffer;
|
||||
StreamMode m_stream_mode;
|
||||
bool m_initialized;
|
||||
fs::FileHandle m_file_handle;
|
||||
char m_file_name[ReportFileNameLength];
|
||||
public:
|
||||
Stream();
|
||||
~Stream();
|
||||
|
||||
@@ -50,18 +50,18 @@ namespace ams::fs {
|
||||
Result HierarchicalRomFileTable::Initialize(SubStorage dir_bucket, SubStorage dir_entry, SubStorage file_bucket, SubStorage file_entry) {
|
||||
s64 dir_bucket_size;
|
||||
R_TRY(dir_bucket.GetSize(std::addressof(dir_bucket_size)));
|
||||
R_TRY(this->dir_table.Initialize(dir_bucket, DirectoryEntryMapTable::QueryBucketCount(dir_bucket_size), dir_entry));
|
||||
R_TRY(m_dir_table.Initialize(dir_bucket, DirectoryEntryMapTable::QueryBucketCount(dir_bucket_size), dir_entry));
|
||||
|
||||
s64 file_bucket_size;
|
||||
R_TRY(file_bucket.GetSize(std::addressof(file_bucket_size)));
|
||||
R_TRY(this->file_table.Initialize(file_bucket, FileEntryMapTable::QueryBucketCount(file_bucket_size), file_entry));
|
||||
R_TRY(m_file_table.Initialize(file_bucket, FileEntryMapTable::QueryBucketCount(file_bucket_size), file_entry));
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void HierarchicalRomFileTable::Finalize() {
|
||||
this->dir_table.Finalize();
|
||||
this->file_table.Finalize();
|
||||
m_dir_table.Finalize();
|
||||
m_file_table.Finalize();
|
||||
}
|
||||
|
||||
Result HierarchicalRomFileTable::CreateRootDirectory() {
|
||||
@@ -74,7 +74,7 @@ namespace ams::fs {
|
||||
.dir = InvalidPosition,
|
||||
.file = InvalidPosition,
|
||||
};
|
||||
return this->dir_table.Add(std::addressof(root_pos), root_key, root_entry);
|
||||
return m_dir_table.Add(std::addressof(root_pos), root_key, root_entry);
|
||||
}
|
||||
|
||||
Result HierarchicalRomFileTable::CreateDirectory(RomDirectoryId *out, const RomPathChar *path, const DirectoryInfo &info) {
|
||||
@@ -95,7 +95,7 @@ namespace ams::fs {
|
||||
AMS_UNUSED(info);
|
||||
|
||||
Position new_pos = 0;
|
||||
R_TRY_CATCH(this->dir_table.Add(std::addressof(new_pos), new_key, new_entry)) {
|
||||
R_TRY_CATCH(m_dir_table.Add(std::addressof(new_pos), new_key, new_entry)) {
|
||||
R_CONVERT(fs::ResultDbmKeyFull, fs::ResultDbmDirectoryEntryFull())
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
@@ -104,18 +104,18 @@ namespace ams::fs {
|
||||
if (parent_entry.dir == InvalidPosition) {
|
||||
parent_entry.dir = new_pos;
|
||||
|
||||
R_TRY(this->dir_table.SetByPosition(new_key.key.parent, parent_entry));
|
||||
R_TRY(m_dir_table.SetByPosition(new_key.key.parent, parent_entry));
|
||||
} else {
|
||||
Position cur_pos = parent_entry.dir;
|
||||
while (true) {
|
||||
RomEntryKey cur_key = {};
|
||||
RomDirectoryEntry cur_entry = {};
|
||||
R_TRY(this->dir_table.GetByPosition(std::addressof(cur_key), std::addressof(cur_entry), cur_pos));
|
||||
R_TRY(m_dir_table.GetByPosition(std::addressof(cur_key), std::addressof(cur_entry), cur_pos));
|
||||
|
||||
if (cur_entry.next == InvalidPosition) {
|
||||
cur_entry.next = new_pos;
|
||||
|
||||
R_TRY(this->dir_table.SetByPosition(cur_pos, cur_entry));
|
||||
R_TRY(m_dir_table.SetByPosition(cur_pos, cur_entry));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ namespace ams::fs {
|
||||
};
|
||||
|
||||
Position new_pos = 0;
|
||||
R_TRY_CATCH(this->file_table.Add(std::addressof(new_pos), new_key, new_entry)) {
|
||||
R_TRY_CATCH(m_file_table.Add(std::addressof(new_pos), new_key, new_entry)) {
|
||||
R_CONVERT(fs::ResultDbmKeyFull, fs::ResultDbmFileEntryFull())
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
@@ -151,18 +151,18 @@ namespace ams::fs {
|
||||
if (parent_entry.file == InvalidPosition) {
|
||||
parent_entry.file = new_pos;
|
||||
|
||||
R_TRY(this->dir_table.SetByPosition(new_key.key.parent, parent_entry));
|
||||
R_TRY(m_dir_table.SetByPosition(new_key.key.parent, parent_entry));
|
||||
} else {
|
||||
Position cur_pos = parent_entry.file;
|
||||
while (true) {
|
||||
RomEntryKey cur_key = {};
|
||||
RomFileEntry cur_entry = {};
|
||||
R_TRY(this->file_table.GetByPosition(std::addressof(cur_key), std::addressof(cur_entry), cur_pos));
|
||||
R_TRY(m_file_table.GetByPosition(std::addressof(cur_key), std::addressof(cur_entry), cur_pos));
|
||||
|
||||
if (cur_entry.next == InvalidPosition) {
|
||||
cur_entry.next = new_pos;
|
||||
|
||||
R_TRY(this->file_table.SetByPosition(cur_pos, cur_entry));
|
||||
R_TRY(m_file_table.SetByPosition(cur_pos, cur_entry));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -285,7 +285,7 @@ namespace ams::fs {
|
||||
RomEntryKey key = {};
|
||||
RomDirectoryEntry entry = {};
|
||||
size_t aux_size = 0;
|
||||
R_TRY(this->dir_table.GetByPosition(std::addressof(key), std::addressof(entry), out, std::addressof(aux_size), find->next_dir));
|
||||
R_TRY(m_dir_table.GetByPosition(std::addressof(key), std::addressof(entry), out, std::addressof(aux_size), find->next_dir));
|
||||
AMS_ASSERT(aux_size / sizeof(RomPathChar) <= RomPathTool::MaxPathLength);
|
||||
|
||||
out[aux_size / sizeof(RomPathChar)] = RomStringTraits::NullTerminator;
|
||||
@@ -305,7 +305,7 @@ namespace ams::fs {
|
||||
RomEntryKey key = {};
|
||||
RomFileEntry entry = {};
|
||||
size_t aux_size = 0;
|
||||
R_TRY(this->file_table.GetByPosition(std::addressof(key), std::addressof(entry), out, std::addressof(aux_size), find->next_file));
|
||||
R_TRY(m_file_table.GetByPosition(std::addressof(key), std::addressof(entry), out, std::addressof(aux_size), find->next_file));
|
||||
AMS_ASSERT(aux_size / sizeof(RomPathChar) <= RomPathTool::MaxPathLength);
|
||||
|
||||
out[aux_size / sizeof(RomPathChar)] = RomStringTraits::NullTerminator;
|
||||
@@ -318,8 +318,8 @@ namespace ams::fs {
|
||||
AMS_ASSERT(out_dir_entry_size != nullptr);
|
||||
AMS_ASSERT(out_file_entry_size != nullptr);
|
||||
|
||||
*out_dir_entry_size = this->dir_table.GetTotalEntrySize();
|
||||
*out_file_entry_size = this->file_table.GetTotalEntrySize();
|
||||
*out_dir_entry_size = m_dir_table.GetTotalEntrySize();
|
||||
*out_file_entry_size = m_file_table.GetTotalEntrySize();
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
@@ -331,7 +331,7 @@ namespace ams::fs {
|
||||
|
||||
RomEntryKey gp_key = {};
|
||||
RomDirectoryEntry gp_entry = {};
|
||||
R_TRY(this->dir_table.GetByPosition(std::addressof(gp_key), std::addressof(gp_entry), pos));
|
||||
R_TRY(m_dir_table.GetByPosition(std::addressof(gp_key), std::addressof(gp_entry), pos));
|
||||
out_dir_key->key.parent = gp_key.parent;
|
||||
|
||||
R_TRY(RomPathTool::GetParentDirectoryName(std::addressof(out_dir_key->name), name, path));
|
||||
@@ -458,7 +458,7 @@ namespace ams::fs {
|
||||
{
|
||||
Position pos = InvalidPosition;
|
||||
RomDirectoryEntry entry = {};
|
||||
const Result get_res = this->dir_table.Get(std::addressof(pos), std::addressof(entry), key);
|
||||
const Result get_res = m_dir_table.Get(std::addressof(pos), std::addressof(entry), key);
|
||||
if (!fs::ResultDbmKeyNotFound::Includes(get_res)) {
|
||||
R_TRY(get_res);
|
||||
return if_exists;
|
||||
@@ -469,7 +469,7 @@ namespace ams::fs {
|
||||
{
|
||||
Position pos = InvalidPosition;
|
||||
RomFileEntry entry = {};
|
||||
const Result get_res = this->file_table.Get(std::addressof(pos), std::addressof(entry), key);
|
||||
const Result get_res = m_file_table.Get(std::addressof(pos), std::addressof(entry), key);
|
||||
if (!fs::ResultDbmKeyNotFound::Includes(get_res)) {
|
||||
R_TRY(get_res);
|
||||
return if_exists;
|
||||
@@ -482,13 +482,13 @@ namespace ams::fs {
|
||||
AMS_ASSERT(out_pos != nullptr);
|
||||
AMS_ASSERT(out_entry != nullptr);
|
||||
|
||||
const Result dir_res = this->dir_table.Get(out_pos, out_entry, key);
|
||||
const Result dir_res = m_dir_table.Get(out_pos, out_entry, key);
|
||||
R_UNLESS(R_FAILED(dir_res), dir_res);
|
||||
R_UNLESS(fs::ResultDbmKeyNotFound::Includes(dir_res), dir_res);
|
||||
|
||||
Position pos = 0;
|
||||
RomFileEntry entry = {};
|
||||
const Result file_res = this->file_table.Get(std::addressof(pos), std::addressof(entry), key);
|
||||
const Result file_res = m_file_table.Get(std::addressof(pos), std::addressof(entry), key);
|
||||
R_UNLESS(R_FAILED(file_res), fs::ResultDbmInvalidOperation());
|
||||
R_UNLESS(!fs::ResultDbmKeyNotFound::Includes(file_res), fs::ResultDbmDirectoryNotFound());
|
||||
return file_res;
|
||||
@@ -499,12 +499,12 @@ namespace ams::fs {
|
||||
Position pos = DirectoryIdToPosition(id);
|
||||
|
||||
RomEntryKey key = {};
|
||||
const Result dir_res = this->dir_table.GetByPosition(std::addressof(key), out_entry, pos);
|
||||
const Result dir_res = m_dir_table.GetByPosition(std::addressof(key), out_entry, pos);
|
||||
R_UNLESS(R_FAILED(dir_res), dir_res);
|
||||
R_UNLESS(fs::ResultDbmKeyNotFound::Includes(dir_res), dir_res);
|
||||
|
||||
RomFileEntry entry = {};
|
||||
const Result file_res = this->file_table.GetByPosition(std::addressof(key), std::addressof(entry), pos);
|
||||
const Result file_res = m_file_table.GetByPosition(std::addressof(key), std::addressof(entry), pos);
|
||||
R_UNLESS(R_FAILED(file_res), fs::ResultDbmInvalidOperation());
|
||||
R_UNLESS(!fs::ResultDbmKeyNotFound::Includes(file_res), fs::ResultDbmDirectoryNotFound());
|
||||
return file_res;
|
||||
@@ -514,13 +514,13 @@ namespace ams::fs {
|
||||
AMS_ASSERT(out_pos != nullptr);
|
||||
AMS_ASSERT(out_entry != nullptr);
|
||||
|
||||
const Result file_res = this->file_table.Get(out_pos, out_entry, key);
|
||||
const Result file_res = m_file_table.Get(out_pos, out_entry, key);
|
||||
R_UNLESS(R_FAILED(file_res), file_res);
|
||||
R_UNLESS(fs::ResultDbmKeyNotFound::Includes(file_res), file_res);
|
||||
|
||||
Position pos = 0;
|
||||
RomDirectoryEntry entry = {};
|
||||
const Result dir_res = this->dir_table.Get(std::addressof(pos), std::addressof(entry), key);
|
||||
const Result dir_res = m_dir_table.Get(std::addressof(pos), std::addressof(entry), key);
|
||||
R_UNLESS(R_FAILED(dir_res), fs::ResultDbmInvalidOperation());
|
||||
R_UNLESS(!fs::ResultDbmKeyNotFound::Includes(dir_res), fs::ResultDbmFileNotFound());
|
||||
return dir_res;
|
||||
@@ -531,12 +531,12 @@ namespace ams::fs {
|
||||
Position pos = FileIdToPosition(id);
|
||||
|
||||
RomEntryKey key = {};
|
||||
const Result file_res = this->file_table.GetByPosition(std::addressof(key), out_entry, pos);
|
||||
const Result file_res = m_file_table.GetByPosition(std::addressof(key), out_entry, pos);
|
||||
R_UNLESS(R_FAILED(file_res), file_res);
|
||||
R_UNLESS(fs::ResultDbmKeyNotFound::Includes(file_res), file_res);
|
||||
|
||||
RomDirectoryEntry entry = {};
|
||||
const Result dir_res = this->dir_table.GetByPosition(std::addressof(key), std::addressof(entry), pos);
|
||||
const Result dir_res = m_dir_table.GetByPosition(std::addressof(key), std::addressof(entry), pos);
|
||||
R_UNLESS(R_FAILED(dir_res), fs::ResultDbmInvalidOperation());
|
||||
R_UNLESS(!fs::ResultDbmKeyNotFound::Includes(dir_res), fs::ResultDbmFileNotFound());
|
||||
return dir_res;
|
||||
|
||||
@@ -26,9 +26,9 @@ namespace ams::fs::RomPathTool {
|
||||
path++;
|
||||
}
|
||||
|
||||
this->prev_path_start = path;
|
||||
this->prev_path_end = path;
|
||||
for (this->next_path = path + 1; IsSeparator(this->next_path[0]); ++this->next_path) {
|
||||
m_prev_path_start = path;
|
||||
m_prev_path_end = path;
|
||||
for (m_next_path = path + 1; IsSeparator(m_next_path[0]); ++m_next_path) {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
@@ -36,63 +36,63 @@ namespace ams::fs::RomPathTool {
|
||||
}
|
||||
|
||||
void PathParser::Finalize() {
|
||||
this->prev_path_start = nullptr;
|
||||
this->prev_path_end = nullptr;
|
||||
this->next_path = nullptr;
|
||||
this->finished = false;
|
||||
m_prev_path_start = nullptr;
|
||||
m_prev_path_end = nullptr;
|
||||
m_next_path = nullptr;
|
||||
m_finished = false;
|
||||
}
|
||||
|
||||
bool PathParser::IsParseFinished() const {
|
||||
return this->finished;
|
||||
return m_finished;
|
||||
}
|
||||
|
||||
bool PathParser::IsDirectoryPath() const {
|
||||
AMS_ASSERT(this->next_path != nullptr);
|
||||
AMS_ASSERT(m_next_path != nullptr);
|
||||
|
||||
if (IsNullTerminator(this->next_path[0]) && IsSeparator(this->next_path[-1])) {
|
||||
if (IsNullTerminator(m_next_path[0]) && IsSeparator(m_next_path[-1])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IsCurrentDirectory(this->next_path)) {
|
||||
if (IsCurrentDirectory(m_next_path)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return IsParentDirectory(this->next_path);
|
||||
return IsParentDirectory(m_next_path);
|
||||
}
|
||||
|
||||
Result PathParser::GetNextDirectoryName(RomEntryName *out) {
|
||||
AMS_ASSERT(out != nullptr);
|
||||
AMS_ASSERT(this->prev_path_start != nullptr);
|
||||
AMS_ASSERT(this->prev_path_end != nullptr);
|
||||
AMS_ASSERT(this->next_path != nullptr);
|
||||
AMS_ASSERT(m_prev_path_start != nullptr);
|
||||
AMS_ASSERT(m_prev_path_end != nullptr);
|
||||
AMS_ASSERT(m_next_path != nullptr);
|
||||
|
||||
/* Set the current path to output. */
|
||||
out->length = this->prev_path_end - this->prev_path_start;
|
||||
out->path = this->prev_path_start;
|
||||
out->length = m_prev_path_end - m_prev_path_start;
|
||||
out->path = m_prev_path_start;
|
||||
|
||||
/* Parse the next path. */
|
||||
this->prev_path_start = this->next_path;
|
||||
const RomPathChar *cur = this->next_path;
|
||||
m_prev_path_start = m_next_path;
|
||||
const RomPathChar *cur = m_next_path;
|
||||
for (size_t name_len = 0; true; name_len++) {
|
||||
if (IsSeparator(cur[name_len])) {
|
||||
R_UNLESS(name_len < MaxPathLength, fs::ResultDbmDirectoryNameTooLong());
|
||||
|
||||
this->prev_path_end = cur + name_len;
|
||||
this->next_path = this->prev_path_end + 1;
|
||||
m_prev_path_end = cur + name_len;
|
||||
m_next_path = m_prev_path_end + 1;
|
||||
|
||||
while (IsSeparator(this->next_path[0])) {
|
||||
++this->next_path;
|
||||
while (IsSeparator(m_next_path[0])) {
|
||||
++m_next_path;
|
||||
}
|
||||
if (IsNullTerminator(this->next_path[0])) {
|
||||
this->finished = true;
|
||||
if (IsNullTerminator(m_next_path[0])) {
|
||||
m_finished = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (IsNullTerminator(cur[name_len])) {
|
||||
this->finished = true;
|
||||
this->next_path = cur + name_len;
|
||||
this->prev_path_end = cur + name_len;
|
||||
m_finished = true;
|
||||
m_next_path = cur + name_len;
|
||||
m_prev_path_end = cur + name_len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -102,29 +102,29 @@ namespace ams::fs::RomPathTool {
|
||||
|
||||
Result PathParser::GetAsDirectoryName(RomEntryName *out) const {
|
||||
AMS_ASSERT(out != nullptr);
|
||||
AMS_ASSERT(this->prev_path_start != nullptr);
|
||||
AMS_ASSERT(this->prev_path_end != nullptr);
|
||||
AMS_ASSERT(this->next_path != nullptr);
|
||||
AMS_ASSERT(m_prev_path_start != nullptr);
|
||||
AMS_ASSERT(m_prev_path_end != nullptr);
|
||||
AMS_ASSERT(m_next_path != nullptr);
|
||||
|
||||
const size_t len = this->prev_path_end - this->prev_path_start;
|
||||
const size_t len = m_prev_path_end - m_prev_path_start;
|
||||
R_UNLESS(len <= MaxPathLength, fs::ResultDbmDirectoryNameTooLong());
|
||||
|
||||
out->length = len;
|
||||
out->path = this->prev_path_start;
|
||||
out->path = m_prev_path_start;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result PathParser::GetAsFileName(RomEntryName *out) const {
|
||||
AMS_ASSERT(out != nullptr);
|
||||
AMS_ASSERT(this->prev_path_start != nullptr);
|
||||
AMS_ASSERT(this->prev_path_end != nullptr);
|
||||
AMS_ASSERT(this->next_path != nullptr);
|
||||
AMS_ASSERT(m_prev_path_start != nullptr);
|
||||
AMS_ASSERT(m_prev_path_end != nullptr);
|
||||
AMS_ASSERT(m_next_path != nullptr);
|
||||
|
||||
const size_t len = this->prev_path_end - this->prev_path_start;
|
||||
const size_t len = m_prev_path_end - m_prev_path_start;
|
||||
R_UNLESS(len <= MaxPathLength, fs::ResultDbmFileNameTooLong());
|
||||
|
||||
out->length = len;
|
||||
out->path = this->prev_path_start;
|
||||
out->path = m_prev_path_start;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
namespace ams::fs {
|
||||
|
||||
Result FileStorage::UpdateSize() {
|
||||
R_SUCCEED_IF(this->size != InvalidSize);
|
||||
return this->base_file->GetSize(std::addressof(this->size));
|
||||
R_SUCCEED_IF(m_size != InvalidSize);
|
||||
return m_base_file->GetSize(std::addressof(m_size));
|
||||
}
|
||||
|
||||
Result FileStorage::Read(s64 offset, void *buffer, size_t size) {
|
||||
@@ -33,10 +33,10 @@ namespace ams::fs {
|
||||
R_TRY(this->UpdateSize());
|
||||
|
||||
/* Ensure our access is valid. */
|
||||
R_UNLESS(IStorage::CheckAccessRange(offset, size, this->size), fs::ResultOutOfRange());
|
||||
R_UNLESS(IStorage::CheckAccessRange(offset, size, m_size), fs::ResultOutOfRange());
|
||||
|
||||
size_t read_size;
|
||||
return this->base_file->Read(std::addressof(read_size), offset, buffer, size);
|
||||
return m_base_file->Read(std::addressof(read_size), offset, buffer, size);
|
||||
}
|
||||
|
||||
Result FileStorage::Write(s64 offset, const void *buffer, size_t size) {
|
||||
@@ -50,24 +50,24 @@ namespace ams::fs {
|
||||
R_TRY(this->UpdateSize());
|
||||
|
||||
/* Ensure our access is valid. */
|
||||
R_UNLESS(IStorage::CheckAccessRange(offset, size, this->size), fs::ResultOutOfRange());
|
||||
R_UNLESS(IStorage::CheckAccessRange(offset, size, m_size), fs::ResultOutOfRange());
|
||||
|
||||
return this->base_file->Write(offset, buffer, size, fs::WriteOption());
|
||||
return m_base_file->Write(offset, buffer, size, fs::WriteOption());
|
||||
}
|
||||
|
||||
Result FileStorage::Flush() {
|
||||
return this->base_file->Flush();
|
||||
return m_base_file->Flush();
|
||||
}
|
||||
|
||||
Result FileStorage::GetSize(s64 *out_size) {
|
||||
R_TRY(this->UpdateSize());
|
||||
*out_size = this->size;
|
||||
*out_size = m_size;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result FileStorage::SetSize(s64 size) {
|
||||
this->size = InvalidSize;
|
||||
return this->base_file->SetSize(size);
|
||||
m_size = InvalidSize;
|
||||
return m_base_file->SetSize(size);
|
||||
}
|
||||
|
||||
Result FileStorage::OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) {
|
||||
@@ -84,7 +84,7 @@ namespace ams::fs {
|
||||
}
|
||||
R_TRY(this->UpdateSize());
|
||||
R_UNLESS(IStorage::CheckOffsetAndSize(offset, size), fs::ResultOutOfRange());
|
||||
return this->base_file->OperateRange(dst, dst_size, op_id, offset, size, src, src_size);
|
||||
return m_base_file->OperateRange(dst, dst_size, op_id, offset, size, src, src_size);
|
||||
default:
|
||||
return fs::ResultUnsupportedOperationInFileStorageA();
|
||||
}
|
||||
@@ -97,19 +97,19 @@ namespace ams::fs {
|
||||
|
||||
/* Set the file. */
|
||||
this->SetFile(std::move(base_file));
|
||||
this->base_file_system = std::move(base_file_system);
|
||||
m_base_file_system = std::move(base_file_system);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result FileHandleStorage::UpdateSize() {
|
||||
R_SUCCEED_IF(this->size != InvalidSize);
|
||||
return GetFileSize(std::addressof(this->size), this->handle);
|
||||
R_SUCCEED_IF(m_size != InvalidSize);
|
||||
return GetFileSize(std::addressof(m_size), m_handle);
|
||||
}
|
||||
|
||||
Result FileHandleStorage::Read(s64 offset, void *buffer, size_t size) {
|
||||
/* Lock the mutex. */
|
||||
std::scoped_lock lk(this->mutex);
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
/* Immediately succeed if there's nothing to read. */
|
||||
R_SUCCEED_IF(size == 0);
|
||||
@@ -121,14 +121,14 @@ namespace ams::fs {
|
||||
R_TRY(this->UpdateSize());
|
||||
|
||||
/* Ensure our access is valid. */
|
||||
R_UNLESS(IStorage::CheckAccessRange(offset, size, this->size), fs::ResultOutOfRange());
|
||||
R_UNLESS(IStorage::CheckAccessRange(offset, size, m_size), fs::ResultOutOfRange());
|
||||
|
||||
return ReadFile(this->handle, offset, buffer, size, fs::ReadOption());
|
||||
return ReadFile(m_handle, offset, buffer, size, fs::ReadOption());
|
||||
}
|
||||
|
||||
Result FileHandleStorage::Write(s64 offset, const void *buffer, size_t size) {
|
||||
/* Lock the mutex. */
|
||||
std::scoped_lock lk(this->mutex);
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
/* Immediately succeed if there's nothing to write. */
|
||||
R_SUCCEED_IF(size == 0);
|
||||
@@ -140,24 +140,24 @@ namespace ams::fs {
|
||||
R_TRY(this->UpdateSize());
|
||||
|
||||
/* Ensure our access is valid. */
|
||||
R_UNLESS(IStorage::CheckAccessRange(offset, size, this->size), fs::ResultOutOfRange());
|
||||
R_UNLESS(IStorage::CheckAccessRange(offset, size, m_size), fs::ResultOutOfRange());
|
||||
|
||||
return WriteFile(this->handle, offset, buffer, size, fs::WriteOption());
|
||||
return WriteFile(m_handle, offset, buffer, size, fs::WriteOption());
|
||||
}
|
||||
|
||||
Result FileHandleStorage::Flush() {
|
||||
return FlushFile(this->handle);
|
||||
return FlushFile(m_handle);
|
||||
}
|
||||
|
||||
Result FileHandleStorage::GetSize(s64 *out_size) {
|
||||
R_TRY(this->UpdateSize());
|
||||
*out_size = this->size;
|
||||
*out_size = m_size;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result FileHandleStorage::SetSize(s64 size) {
|
||||
this->size = InvalidSize;
|
||||
return SetFileSize(this->handle, size);
|
||||
m_size = InvalidSize;
|
||||
return SetFileSize(m_handle, size);
|
||||
}
|
||||
|
||||
Result FileHandleStorage::OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) {
|
||||
@@ -169,7 +169,7 @@ namespace ams::fs {
|
||||
R_UNLESS(dst != nullptr, fs::ResultNullptrArgument());
|
||||
R_UNLESS(dst_size == sizeof(QueryRangeInfo), fs::ResultInvalidSize());
|
||||
|
||||
return QueryRange(static_cast<QueryRangeInfo *>(dst), this->handle, offset, size);
|
||||
return QueryRange(static_cast<QueryRangeInfo *>(dst), m_handle, offset, size);
|
||||
default:
|
||||
return fs::ResultUnsupportedOperationInFileStorageB();
|
||||
}
|
||||
|
||||
@@ -82,10 +82,10 @@ namespace ams::fs {
|
||||
namespace ams::fs::impl {
|
||||
|
||||
const char *IdString::ToValueString(int id) {
|
||||
const int len = util::SNPrintf(this->buffer, sizeof(this->buffer), "%d", id);
|
||||
AMS_ASSERT(static_cast<size_t>(len) < sizeof(this->buffer));
|
||||
const int len = util::SNPrintf(m_buffer, sizeof(m_buffer), "%d", id);
|
||||
AMS_ASSERT(static_cast<size_t>(len) < sizeof(m_buffer));
|
||||
AMS_UNUSED(len);
|
||||
return this->buffer;
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
template<> const char *IdString::ToString<fs::Priority>(fs::Priority id) {
|
||||
@@ -171,20 +171,20 @@ namespace ams::fs::impl {
|
||||
|
||||
class AccessLogPrinterCallbackManager {
|
||||
private:
|
||||
AccessLogPrinterCallback callback;
|
||||
AccessLogPrinterCallback m_callback;
|
||||
public:
|
||||
constexpr AccessLogPrinterCallbackManager() : callback(nullptr) { /* ... */ }
|
||||
constexpr AccessLogPrinterCallbackManager() : m_callback(nullptr) { /* ... */ }
|
||||
|
||||
constexpr bool IsRegisteredCallback() const { return this->callback != nullptr; }
|
||||
constexpr bool IsRegisteredCallback() const { return m_callback != nullptr; }
|
||||
|
||||
constexpr void RegisterCallback(AccessLogPrinterCallback c) {
|
||||
AMS_ASSERT(this->callback == nullptr);
|
||||
this->callback = c;
|
||||
AMS_ASSERT(m_callback == nullptr);
|
||||
m_callback = c;
|
||||
}
|
||||
|
||||
constexpr int InvokeCallback(char *buf, size_t size) const {
|
||||
AMS_ASSERT(this->callback != nullptr);
|
||||
return this->callback(buf, size);
|
||||
AMS_ASSERT(m_callback != nullptr);
|
||||
return m_callback(buf, size);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -22,13 +22,13 @@ namespace ams::fs {
|
||||
|
||||
class BisCommonMountNameGenerator : public fsa::ICommonMountNameGenerator, public impl::Newable {
|
||||
private:
|
||||
const BisPartitionId id;
|
||||
const BisPartitionId m_id;
|
||||
public:
|
||||
explicit BisCommonMountNameGenerator(BisPartitionId i) : id(i) { /* ... */ }
|
||||
explicit BisCommonMountNameGenerator(BisPartitionId i) : m_id(i) { /* ... */ }
|
||||
|
||||
virtual Result GenerateCommonMountName(char *dst, size_t dst_size) override {
|
||||
/* Determine how much space we need. */
|
||||
const char *bis_mount_name = GetBisMountName(this->id);
|
||||
const char *bis_mount_name = GetBisMountName(m_id);
|
||||
const size_t needed_size = util::Strnlen(bis_mount_name, MountNameLengthMax) + 2;
|
||||
AMS_ABORT_UNLESS(dst_size >= needed_size);
|
||||
|
||||
|
||||
@@ -251,11 +251,11 @@ namespace ams::fs {
|
||||
|
||||
class SdCardRedirectionCodeFileSystem : public OpenFileOnlyFileSystem {
|
||||
private:
|
||||
util::optional<ReadOnlyFileSystem> sd_content_fs;
|
||||
ReadOnlyFileSystem code_fs;
|
||||
bool is_redirect;
|
||||
util::optional<ReadOnlyFileSystem> m_sd_content_fs;
|
||||
ReadOnlyFileSystem m_code_fs;
|
||||
bool m_is_redirect;
|
||||
public:
|
||||
SdCardRedirectionCodeFileSystem(std::unique_ptr<fsa::IFileSystem> &&code, ncm::ProgramId program_id, bool redirect) : code_fs(std::move(code)), is_redirect(redirect) {
|
||||
SdCardRedirectionCodeFileSystem(std::unique_ptr<fsa::IFileSystem> &&code, ncm::ProgramId program_id, bool redirect) : m_code_fs(std::move(code)), m_is_redirect(redirect) {
|
||||
if (!cfg::IsSdCardInitialized()) {
|
||||
return;
|
||||
}
|
||||
@@ -275,12 +275,12 @@ namespace ams::fs {
|
||||
return;
|
||||
}
|
||||
|
||||
sd_content_fs.emplace(std::move(subdir_fs));
|
||||
m_sd_content_fs.emplace(std::move(subdir_fs));
|
||||
}
|
||||
private:
|
||||
bool IsFileStubbed(const char *path) {
|
||||
/* If we don't have an sd content fs, nothing is stubbed. */
|
||||
if (!this->sd_content_fs) {
|
||||
if (!m_sd_content_fs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -290,7 +290,7 @@ namespace ams::fs {
|
||||
|
||||
/* Query whether we have the file. */
|
||||
bool has_file;
|
||||
if (R_FAILED(fssystem::HasFile(std::addressof(has_file), std::addressof(*this->sd_content_fs), stub_path))) {
|
||||
if (R_FAILED(fssystem::HasFile(std::addressof(has_file), std::addressof(*m_sd_content_fs), stub_path))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -302,70 +302,70 @@ namespace ams::fs {
|
||||
R_UNLESS((mode & fs::OpenMode_All) == fs::OpenMode_Read, fs::ResultInvalidOpenMode());
|
||||
|
||||
/* If we support redirection, we'd like to prefer a file from the sd card. */
|
||||
if (this->is_redirect) {
|
||||
R_SUCCEED_IF(R_SUCCEEDED(this->sd_content_fs->OpenFile(out_file, path, mode)));
|
||||
if (m_is_redirect) {
|
||||
R_SUCCEED_IF(R_SUCCEEDED(m_sd_content_fs->OpenFile(out_file, path, mode)));
|
||||
}
|
||||
|
||||
/* Otherwise, check if the file is stubbed. */
|
||||
R_UNLESS(!this->IsFileStubbed(path), fs::ResultPathNotFound());
|
||||
|
||||
/* Open a file from the base code fs. */
|
||||
return this->code_fs.OpenFile(out_file, path, mode);
|
||||
return m_code_fs.OpenFile(out_file, path, mode);
|
||||
}
|
||||
};
|
||||
|
||||
class AtmosphereCodeFileSystem : public OpenFileOnlyFileSystem {
|
||||
private:
|
||||
util::optional<SdCardRedirectionCodeFileSystem> code_fs;
|
||||
util::optional<ReadOnlyFileSystem> hbl_fs;
|
||||
ncm::ProgramId program_id;
|
||||
bool initialized;
|
||||
util::optional<SdCardRedirectionCodeFileSystem> m_code_fs;
|
||||
util::optional<ReadOnlyFileSystem> m_hbl_fs;
|
||||
ncm::ProgramId m_program_id;
|
||||
bool m_initialized;
|
||||
public:
|
||||
AtmosphereCodeFileSystem() : initialized(false) { /* ... */ }
|
||||
AtmosphereCodeFileSystem() : m_initialized(false) { /* ... */ }
|
||||
|
||||
Result Initialize(CodeVerificationData *out_verification_data, const char *path, ncm::ProgramId program_id, bool is_hbl, bool is_specific) {
|
||||
AMS_ABORT_UNLESS(!this->initialized);
|
||||
AMS_ABORT_UNLESS(!m_initialized);
|
||||
|
||||
/* If we're hbl, we need to open a hbl fs. */
|
||||
if (is_hbl) {
|
||||
std::unique_ptr<fsa::IFileSystem> fsa;
|
||||
R_TRY(OpenHblCodeFileSystemImpl(std::addressof(fsa)));
|
||||
this->hbl_fs.emplace(std::move(fsa));
|
||||
m_hbl_fs.emplace(std::move(fsa));
|
||||
}
|
||||
|
||||
/* Open the code filesystem. */
|
||||
std::unique_ptr<fsa::IFileSystem> fsa;
|
||||
R_TRY(OpenSdCardCodeOrStratosphereCodeOrCodeFileSystemImpl(out_verification_data, std::addressof(fsa), path, program_id));
|
||||
this->code_fs.emplace(std::move(fsa), program_id, is_specific);
|
||||
m_code_fs.emplace(std::move(fsa), program_id, is_specific);
|
||||
|
||||
this->program_id = program_id;
|
||||
this->initialized = true;
|
||||
m_program_id = program_id;
|
||||
m_initialized = true;
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
private:
|
||||
virtual Result DoOpenFile(std::unique_ptr<fsa::IFile> *out_file, const char *path, OpenMode mode) override final {
|
||||
/* Ensure that we're initialized. */
|
||||
R_UNLESS(this->initialized, fs::ResultNotInitialized());
|
||||
R_UNLESS(m_initialized, fs::ResultNotInitialized());
|
||||
|
||||
/* Only allow opening files with mode = read. */
|
||||
R_UNLESS((mode & fs::OpenMode_All) == fs::OpenMode_Read, fs::ResultInvalidOpenMode());
|
||||
|
||||
/* First, check if there's an external code. */
|
||||
{
|
||||
fsa::IFileSystem *ecs = fssystem::GetExternalCodeFileSystem(this->program_id);
|
||||
fsa::IFileSystem *ecs = fssystem::GetExternalCodeFileSystem(m_program_id);
|
||||
if (ecs != nullptr) {
|
||||
return ecs->OpenFile(out_file, path, mode);
|
||||
}
|
||||
}
|
||||
|
||||
/* If we're hbl, open from the hbl fs. */
|
||||
if (this->hbl_fs) {
|
||||
return this->hbl_fs->OpenFile(out_file, path, mode);
|
||||
if (m_hbl_fs) {
|
||||
return m_hbl_fs->OpenFile(out_file, path, mode);
|
||||
}
|
||||
|
||||
/* If we're not hbl, fall back to our code filesystem. */
|
||||
return this->code_fs->OpenFile(out_file, path, mode);
|
||||
return m_code_fs->OpenFile(out_file, path, mode);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace ams::fs {
|
||||
g_context_tls.SetValue(reinterpret_cast<uintptr_t>(context));
|
||||
}
|
||||
|
||||
ScopedAutoAbortDisabler::ScopedAutoAbortDisabler() : prev_context(GetCurrentThreadFsContext()) {
|
||||
ScopedAutoAbortDisabler::ScopedAutoAbortDisabler() : m_prev_context(GetCurrentThreadFsContext()) {
|
||||
SetCurrentThreadFsContext(std::addressof(g_always_return_context));
|
||||
}
|
||||
|
||||
|
||||
@@ -31,18 +31,18 @@ namespace ams::fs {
|
||||
|
||||
class GameCardCommonMountNameGenerator : public fsa::ICommonMountNameGenerator, public impl::Newable {
|
||||
private:
|
||||
const GameCardHandle handle;
|
||||
const GameCardPartition partition;
|
||||
const GameCardHandle m_handle;
|
||||
const GameCardPartition m_partition;
|
||||
public:
|
||||
explicit GameCardCommonMountNameGenerator(GameCardHandle h, GameCardPartition p) : handle(h), partition(p) { /* ... */ }
|
||||
explicit GameCardCommonMountNameGenerator(GameCardHandle h, GameCardPartition p) : m_handle(h), m_partition(p) { /* ... */ }
|
||||
|
||||
virtual Result GenerateCommonMountName(char *dst, size_t dst_size) override {
|
||||
/* Determine how much space we need. */
|
||||
const size_t needed_size = strnlen(impl::GameCardFileSystemMountName, MountNameLengthMax) + strnlen(GetGameCardMountNameSuffix(this->partition), MountNameLengthMax) + sizeof(GameCardHandle) * 2 + 2;
|
||||
const size_t needed_size = strnlen(impl::GameCardFileSystemMountName, MountNameLengthMax) + strnlen(GetGameCardMountNameSuffix(m_partition), MountNameLengthMax) + sizeof(GameCardHandle) * 2 + 2;
|
||||
AMS_ABORT_UNLESS(dst_size >= needed_size);
|
||||
|
||||
/* Generate the name. */
|
||||
const auto size = util::SNPrintf(dst, dst_size, "%s%s%08x:", impl::GameCardFileSystemMountName, GetGameCardMountNameSuffix(this->partition), this->handle);
|
||||
const auto size = util::SNPrintf(dst, dst_size, "%s%s%08x:", impl::GameCardFileSystemMountName, GetGameCardMountNameSuffix(m_partition), m_handle);
|
||||
AMS_ASSERT(static_cast<size_t>(size) == needed_size - 1);
|
||||
AMS_UNUSED(size);
|
||||
|
||||
|
||||
@@ -21,14 +21,14 @@ namespace ams::fs {
|
||||
|
||||
class PathVerifier {
|
||||
private:
|
||||
u32 invalid_chars[6];
|
||||
u32 separators[2];
|
||||
u32 m_invalid_chars[6];
|
||||
u32 m_separators[2];
|
||||
public:
|
||||
PathVerifier() {
|
||||
/* Convert all invalid characters. */
|
||||
u32 *dst_invalid = this->invalid_chars;
|
||||
u32 *dst_invalid = m_invalid_chars;
|
||||
for (const char *cur = ":*?<>|"; *cur != '\x00'; ++cur) {
|
||||
AMS_ASSERT(dst_invalid < std::end(this->invalid_chars));
|
||||
AMS_ASSERT(dst_invalid < std::end(m_invalid_chars));
|
||||
|
||||
const auto result = util::ConvertCharacterUtf8ToUtf32(dst_invalid, cur);
|
||||
AMS_ASSERT(result == util::CharacterEncodingResult_Success);
|
||||
@@ -36,12 +36,12 @@ namespace ams::fs {
|
||||
|
||||
++dst_invalid;
|
||||
}
|
||||
AMS_ASSERT(dst_invalid == std::end(this->invalid_chars));
|
||||
AMS_ASSERT(dst_invalid == std::end(m_invalid_chars));
|
||||
|
||||
/* Convert all separators. */
|
||||
u32 *dst_sep = this->separators;
|
||||
u32 *dst_sep = m_separators;
|
||||
for (const char *cur = "/\\"; *cur != '\x00'; ++cur) {
|
||||
AMS_ASSERT(dst_sep < std::end(this->separators));
|
||||
AMS_ASSERT(dst_sep < std::end(m_separators));
|
||||
|
||||
const auto result = util::ConvertCharacterUtf8ToUtf32(dst_sep, cur);
|
||||
AMS_ASSERT(result == util::CharacterEncodingResult_Success);
|
||||
@@ -49,7 +49,7 @@ namespace ams::fs {
|
||||
|
||||
++dst_sep;
|
||||
}
|
||||
AMS_ASSERT(dst_sep == std::end(this->separators));
|
||||
AMS_ASSERT(dst_sep == std::end(m_separators));
|
||||
}
|
||||
|
||||
Result Verify(const char *path, int max_path_len, int max_name_len) const {
|
||||
@@ -74,7 +74,7 @@ namespace ams::fs {
|
||||
R_UNLESS(result == util::CharacterEncodingResult_Success, fs::ResultInvalidCharacter());
|
||||
|
||||
/* Check if the character is invalid. */
|
||||
for (const auto invalid : this->invalid_chars) {
|
||||
for (const auto invalid : m_invalid_chars) {
|
||||
R_UNLESS(path_char != invalid, fs::ResultInvalidCharacter());
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace ams::fs {
|
||||
++name_len;
|
||||
|
||||
/* Check for separator. */
|
||||
for (const auto sep : this->separators) {
|
||||
for (const auto sep : m_separators) {
|
||||
if (path_char == sep) {
|
||||
name_len = 0;
|
||||
break;
|
||||
|
||||
@@ -166,11 +166,11 @@ namespace ams::fs {
|
||||
|
||||
class RomFsFile : public fsa::IFile, public impl::Newable {
|
||||
private:
|
||||
RomFsFileSystem *parent;
|
||||
s64 start;
|
||||
s64 end;
|
||||
RomFsFileSystem *m_parent;
|
||||
s64 m_start;
|
||||
s64 m_end;
|
||||
public:
|
||||
RomFsFile(RomFsFileSystem *p, s64 s, s64 e) : parent(p), start(s), end(e) { /* ... */ }
|
||||
RomFsFile(RomFsFileSystem *p, s64 s, s64 e) : m_parent(p), m_start(s), m_end(e) { /* ... */ }
|
||||
virtual ~RomFsFile() { /* ... */ }
|
||||
|
||||
Result VerifyArguments(size_t *out, s64 offset, void *buf, size_t size, const fs::ReadOption &option) {
|
||||
@@ -189,22 +189,22 @@ namespace ams::fs {
|
||||
}
|
||||
|
||||
s64 GetOffset() const {
|
||||
return this->start;
|
||||
return m_start;
|
||||
}
|
||||
|
||||
s64 GetSize() const {
|
||||
return this->end - this->start;
|
||||
return m_end - m_start;
|
||||
}
|
||||
|
||||
IStorage *GetStorage() {
|
||||
return this->parent->GetBaseStorage();
|
||||
return m_parent->GetBaseStorage();
|
||||
}
|
||||
public:
|
||||
virtual Result DoRead(size_t *out, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) override {
|
||||
size_t read_size = 0;
|
||||
R_TRY(this->VerifyArguments(std::addressof(read_size), offset, buffer, size, option));
|
||||
|
||||
R_TRY(this->ConvertResult(this->GetStorage()->Read(offset + this->start, buffer, size)));
|
||||
R_TRY(this->ConvertResult(this->GetStorage()->Read(offset + m_start, buffer, size)));
|
||||
*out = read_size;
|
||||
|
||||
return ResultSuccess();
|
||||
@@ -242,7 +242,7 @@ namespace ams::fs {
|
||||
operate_size = this->GetSize() - offset;
|
||||
}
|
||||
|
||||
return this->GetStorage()->OperateRange(dst, dst_size, op_id, this->start + offset, operate_size, src, src_size);
|
||||
return this->GetStorage()->OperateRange(dst, dst_size, op_id, m_start + offset, operate_size, src, src_size);
|
||||
}
|
||||
default:
|
||||
return fs::ResultUnsupportedOperationInRomFsFileB();
|
||||
@@ -258,20 +258,20 @@ namespace ams::fs {
|
||||
private:
|
||||
using FindPosition = RomFsFileSystem::RomFileTable::FindPosition;
|
||||
private:
|
||||
RomFsFileSystem *parent;
|
||||
FindPosition current_find;
|
||||
FindPosition first_find;
|
||||
fs::OpenDirectoryMode mode;
|
||||
RomFsFileSystem *m_parent;
|
||||
FindPosition m_current_find;
|
||||
FindPosition m_first_find;
|
||||
fs::OpenDirectoryMode m_mode;
|
||||
public:
|
||||
RomFsDirectory(RomFsFileSystem *p, const FindPosition &f, fs::OpenDirectoryMode m) : parent(p), current_find(f), first_find(f), mode(m) { /* ... */ }
|
||||
RomFsDirectory(RomFsFileSystem *p, const FindPosition &f, fs::OpenDirectoryMode m) : m_parent(p), m_current_find(f), m_first_find(f), m_mode(m) { /* ... */ }
|
||||
virtual ~RomFsDirectory() override { /* ... */ }
|
||||
public:
|
||||
virtual Result DoRead(s64 *out_count, DirectoryEntry *out_entries, s64 max_entries) {
|
||||
return this->ReadInternal(out_count, std::addressof(this->current_find), out_entries, max_entries);
|
||||
return this->ReadInternal(out_count, std::addressof(m_current_find), out_entries, max_entries);
|
||||
}
|
||||
|
||||
virtual Result DoGetEntryCount(s64 *out) {
|
||||
FindPosition find = this->first_find;
|
||||
FindPosition find = m_first_find;
|
||||
return this->ReadInternal(out, std::addressof(find), nullptr, 0);
|
||||
}
|
||||
private:
|
||||
@@ -286,9 +286,9 @@ namespace ams::fs {
|
||||
|
||||
s32 i = 0;
|
||||
|
||||
if (this->mode & fs::OpenDirectoryMode_Directory) {
|
||||
if (m_mode & fs::OpenDirectoryMode_Directory) {
|
||||
while (i < max_entries || out_entries == nullptr) {
|
||||
R_TRY_CATCH(this->parent->GetRomFileTable()->FindNextDirectory(name_buf, find, NameBufferSize)) {
|
||||
R_TRY_CATCH(m_parent->GetRomFileTable()->FindNextDirectory(name_buf, find, NameBufferSize)) {
|
||||
R_CATCH(fs::ResultDbmFindFinished) { break; }
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
@@ -304,11 +304,11 @@ namespace ams::fs {
|
||||
}
|
||||
}
|
||||
|
||||
if (this->mode & fs::OpenDirectoryMode_File) {
|
||||
if (m_mode & fs::OpenDirectoryMode_File) {
|
||||
while (i < max_entries || out_entries == nullptr) {
|
||||
auto file_pos = find->next_file;
|
||||
|
||||
R_TRY_CATCH(this->parent->GetRomFileTable()->FindNextFile(name_buf, find, NameBufferSize)) {
|
||||
R_TRY_CATCH(m_parent->GetRomFileTable()->FindNextFile(name_buf, find, NameBufferSize)) {
|
||||
R_CATCH(fs::ResultDbmFindFinished) { break; }
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
@@ -319,7 +319,7 @@ namespace ams::fs {
|
||||
out_entries[i].type = fs::DirectoryEntryType_File;
|
||||
|
||||
RomFsFileSystem::RomFileTable::FileInfo file_info;
|
||||
R_TRY(this->parent->GetRomFileTable()->OpenFile(std::addressof(file_info), this->parent->GetRomFileTable()->PositionToFileId(file_pos)));
|
||||
R_TRY(m_parent->GetRomFileTable()->OpenFile(std::addressof(file_info), m_parent->GetRomFileTable()->PositionToFileId(file_pos)));
|
||||
out_entries[i].file_size = file_info.size.Get();
|
||||
}
|
||||
|
||||
@@ -339,7 +339,7 @@ namespace ams::fs {
|
||||
}
|
||||
|
||||
|
||||
RomFsFileSystem::RomFsFileSystem() : base_storage() {
|
||||
RomFsFileSystem::RomFsFileSystem() : m_base_storage() {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
@@ -379,46 +379,46 @@ namespace ams::fs {
|
||||
R_TRY(ReadFile(base, header.file_bucket_offset, file_bucket_buf, header.file_bucket_size));
|
||||
R_TRY(ReadFile(base, header.file_entry_offset, file_entry_buf, header.file_entry_size));
|
||||
|
||||
this->dir_bucket_storage.reset(new MemoryStorage(dir_bucket_buf, header.directory_bucket_size));
|
||||
this->dir_entry_storage.reset(new MemoryStorage(dir_entry_buf, header.directory_entry_size));
|
||||
this->file_bucket_storage.reset(new MemoryStorage(file_bucket_buf, header.file_bucket_size));
|
||||
this->file_entry_storage.reset(new MemoryStorage(file_entry_buf, header.file_entry_size));
|
||||
m_dir_bucket_storage.reset(new MemoryStorage(dir_bucket_buf, header.directory_bucket_size));
|
||||
m_dir_entry_storage.reset(new MemoryStorage(dir_entry_buf, header.directory_entry_size));
|
||||
m_file_bucket_storage.reset(new MemoryStorage(file_bucket_buf, header.file_bucket_size));
|
||||
m_file_entry_storage.reset(new MemoryStorage(file_entry_buf, header.file_entry_size));
|
||||
} else {
|
||||
this->dir_bucket_storage.reset(new SubStorage(base, header.directory_bucket_offset, header.directory_bucket_size));
|
||||
this->dir_entry_storage.reset(new SubStorage(base, header.directory_entry_offset, header.directory_entry_size));
|
||||
this->file_bucket_storage.reset(new SubStorage(base, header.file_bucket_offset, header.file_bucket_size));
|
||||
this->file_entry_storage.reset(new SubStorage(base, header.file_entry_offset, header.file_entry_size));
|
||||
m_dir_bucket_storage.reset(new SubStorage(base, header.directory_bucket_offset, header.directory_bucket_size));
|
||||
m_dir_entry_storage.reset(new SubStorage(base, header.directory_entry_offset, header.directory_entry_size));
|
||||
m_file_bucket_storage.reset(new SubStorage(base, header.file_bucket_offset, header.file_bucket_size));
|
||||
m_file_entry_storage.reset(new SubStorage(base, header.file_entry_offset, header.file_entry_size));
|
||||
}
|
||||
|
||||
/* Ensure we allocated storages successfully. */
|
||||
R_UNLESS(this->dir_bucket_storage != nullptr, fs::ResultAllocationFailureInRomFsFileSystemA());
|
||||
R_UNLESS(this->dir_entry_storage != nullptr, fs::ResultAllocationFailureInRomFsFileSystemA());
|
||||
R_UNLESS(this->file_bucket_storage != nullptr, fs::ResultAllocationFailureInRomFsFileSystemA());
|
||||
R_UNLESS(this->file_entry_storage != nullptr, fs::ResultAllocationFailureInRomFsFileSystemA());
|
||||
R_UNLESS(m_dir_bucket_storage != nullptr, fs::ResultAllocationFailureInRomFsFileSystemA());
|
||||
R_UNLESS(m_dir_entry_storage != nullptr, fs::ResultAllocationFailureInRomFsFileSystemA());
|
||||
R_UNLESS(m_file_bucket_storage != nullptr, fs::ResultAllocationFailureInRomFsFileSystemA());
|
||||
R_UNLESS(m_file_entry_storage != nullptr, fs::ResultAllocationFailureInRomFsFileSystemA());
|
||||
|
||||
/* Initialize the rom table. */
|
||||
{
|
||||
|
||||
SubStorage db(this->dir_bucket_storage.get(), 0, header.directory_bucket_size);
|
||||
SubStorage de(this->dir_entry_storage.get(), 0, header.directory_entry_size);
|
||||
SubStorage fb(this->file_bucket_storage.get(), 0, header.file_bucket_size);
|
||||
SubStorage fe(this->file_entry_storage.get(), 0, header.file_entry_size);
|
||||
R_TRY(this->rom_file_table.Initialize(db, de, fb, fe));
|
||||
SubStorage db(m_dir_bucket_storage.get(), 0, header.directory_bucket_size);
|
||||
SubStorage de(m_dir_entry_storage.get(), 0, header.directory_entry_size);
|
||||
SubStorage fb(m_file_bucket_storage.get(), 0, header.file_bucket_size);
|
||||
SubStorage fe(m_file_entry_storage.get(), 0, header.file_entry_size);
|
||||
R_TRY(m_rom_file_table.Initialize(db, de, fb, fe));
|
||||
}
|
||||
|
||||
/* Set members. */
|
||||
this->entry_size = header.body_offset;
|
||||
this->base_storage = base;
|
||||
m_entry_size = header.body_offset;
|
||||
m_base_storage = base;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result RomFsFileSystem::Initialize(std::unique_ptr<IStorage>&& base, void *work, size_t work_size, bool use_cache) {
|
||||
this->unique_storage = std::move(base);
|
||||
return this->Initialize(this->unique_storage.get(), work, work_size, use_cache);
|
||||
m_unique_storage = std::move(base);
|
||||
return this->Initialize(m_unique_storage.get(), work, work_size, use_cache);
|
||||
}
|
||||
|
||||
Result RomFsFileSystem::GetFileInfo(RomFileTable::FileInfo *out, const char *path) {
|
||||
R_TRY_CATCH(this->rom_file_table.OpenFile(out, path)) {
|
||||
R_TRY_CATCH(m_rom_file_table.OpenFile(out, path)) {
|
||||
R_CONVERT(fs::ResultDbmNotFound, fs::ResultPathNotFound());
|
||||
R_CONVERT(fs::ResultDbmInvalidOperation, fs::ResultPathNotFound());
|
||||
} R_END_TRY_CATCH;
|
||||
@@ -426,11 +426,11 @@ namespace ams::fs {
|
||||
}
|
||||
|
||||
IStorage *RomFsFileSystem::GetBaseStorage() {
|
||||
return this->base_storage;
|
||||
return m_base_storage;
|
||||
}
|
||||
|
||||
RomFsFileSystem::RomFileTable *RomFsFileSystem::GetRomFileTable() {
|
||||
return std::addressof(this->rom_file_table);
|
||||
return std::addressof(m_rom_file_table);
|
||||
}
|
||||
|
||||
Result RomFsFileSystem::GetFileBaseOffset(s64 *out, const char *path) {
|
||||
@@ -439,7 +439,7 @@ namespace ams::fs {
|
||||
|
||||
RomFileTable::FileInfo info;
|
||||
R_TRY(this->GetFileInfo(std::addressof(info), path));
|
||||
*out = this->entry_size + info.offset.Get();
|
||||
*out = m_entry_size + info.offset.Get();
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
@@ -480,7 +480,7 @@ namespace ams::fs {
|
||||
|
||||
Result RomFsFileSystem::DoGetEntryType(fs::DirectoryEntryType *out, const char *path) {
|
||||
RomDirectoryInfo dir_info;
|
||||
R_TRY_CATCH(this->rom_file_table.GetDirectoryInformation(std::addressof(dir_info), path)) {
|
||||
R_TRY_CATCH(m_rom_file_table.GetDirectoryInformation(std::addressof(dir_info), path)) {
|
||||
R_CONVERT(fs::ResultDbmNotFound, fs::ResultPathNotFound())
|
||||
R_CATCH(fs::ResultDbmInvalidOperation) {
|
||||
RomFileTable::FileInfo file_info;
|
||||
@@ -503,7 +503,7 @@ namespace ams::fs {
|
||||
RomFileTable::FileInfo file_info;
|
||||
R_TRY(this->GetFileInfo(std::addressof(file_info), path));
|
||||
|
||||
auto file = std::make_unique<RomFsFile>(this, this->entry_size + file_info.offset.Get(), this->entry_size + file_info.offset.Get() + file_info.size.Get());
|
||||
auto file = std::make_unique<RomFsFile>(this, m_entry_size + file_info.offset.Get(), m_entry_size + file_info.offset.Get() + file_info.size.Get());
|
||||
R_UNLESS(file != nullptr, fs::ResultAllocationFailureInRomFsFileSystemB());
|
||||
|
||||
*out_file = std::move(file);
|
||||
@@ -515,7 +515,7 @@ namespace ams::fs {
|
||||
AMS_ASSERT(path != nullptr);
|
||||
|
||||
RomFileTable::FindPosition find;
|
||||
R_TRY_CATCH(this->rom_file_table.FindOpen(std::addressof(find), path)) {
|
||||
R_TRY_CATCH(m_rom_file_table.FindOpen(std::addressof(find), path)) {
|
||||
R_CONVERT(fs::ResultDbmNotFound, fs::ResultPathNotFound())
|
||||
R_CONVERT(fs::ResultDbmInvalidOperation, fs::ResultPathNotFound())
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
@@ -22,33 +22,33 @@ namespace ams::fs {
|
||||
class ScopedSetter {
|
||||
NON_COPYABLE(ScopedSetter);
|
||||
private:
|
||||
T *ptr;
|
||||
T value;
|
||||
T *m_ptr;
|
||||
T m_value;
|
||||
public:
|
||||
constexpr ALWAYS_INLINE ScopedSetter(T &p, T v) : ptr(std::addressof(p)), value(v) { /* ... */ }
|
||||
constexpr ALWAYS_INLINE ScopedSetter(T &p, T v) : m_ptr(std::addressof(p)), m_value(v) { /* ... */ }
|
||||
ALWAYS_INLINE ~ScopedSetter() {
|
||||
if (this->ptr) {
|
||||
*this->ptr = this->value;
|
||||
if (m_ptr) {
|
||||
*m_ptr = m_value;
|
||||
}
|
||||
}
|
||||
|
||||
ALWAYS_INLINE ScopedSetter(ScopedSetter &&rhs) {
|
||||
this->ptr = rhs.ptr;
|
||||
this->value = rhs.value;
|
||||
m_ptr = rhs.ptr;
|
||||
m_value = rhs.value;
|
||||
rhs.Reset();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE ScopedSetter &operator=(ScopedSetter &&rhs) {
|
||||
this->ptr = rhs.ptr;
|
||||
this->value = rhs.value;
|
||||
m_ptr = rhs.ptr;
|
||||
m_value = rhs.value;
|
||||
rhs.Reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void Set(T v) { this->value = v; }
|
||||
ALWAYS_INLINE void Set(T v) { m_value = v; }
|
||||
private:
|
||||
ALWAYS_INLINE void Reset() {
|
||||
this->ptr = nullptr;
|
||||
m_ptr = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -19,21 +19,21 @@
|
||||
|
||||
namespace ams::fs::impl {
|
||||
|
||||
DirectoryAccessor::DirectoryAccessor(std::unique_ptr<fsa::IDirectory>&& d, FileSystemAccessor &p) : impl(std::move(d)), parent(p) {
|
||||
DirectoryAccessor::DirectoryAccessor(std::unique_ptr<fsa::IDirectory>&& d, FileSystemAccessor &p) : m_impl(std::move(d)), m_parent(p) {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
DirectoryAccessor::~DirectoryAccessor() {
|
||||
this->impl.reset();
|
||||
this->parent.NotifyCloseDirectory(this);
|
||||
m_impl.reset();
|
||||
m_parent.NotifyCloseDirectory(this);
|
||||
}
|
||||
|
||||
Result DirectoryAccessor::Read(s64 *out_count, DirectoryEntry *out_entries, s64 max_entries) {
|
||||
return this->impl->Read(out_count, out_entries, max_entries);
|
||||
return m_impl->Read(out_count, out_entries, max_entries);
|
||||
}
|
||||
|
||||
Result DirectoryAccessor::GetEntryCount(s64 *out) {
|
||||
return this->impl->GetEntryCount(out);
|
||||
return m_impl->GetEntryCount(out);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@ namespace ams::fs::impl {
|
||||
class DirectoryAccessor : public util::IntrusiveListBaseNode<DirectoryAccessor>, public Newable {
|
||||
NON_COPYABLE(DirectoryAccessor);
|
||||
private:
|
||||
std::unique_ptr<fsa::IDirectory> impl;
|
||||
FileSystemAccessor &parent;
|
||||
std::unique_ptr<fsa::IDirectory> m_impl;
|
||||
FileSystemAccessor &m_parent;
|
||||
public:
|
||||
DirectoryAccessor(std::unique_ptr<fsa::IDirectory>&& d, FileSystemAccessor &p);
|
||||
~DirectoryAccessor();
|
||||
@@ -32,7 +32,7 @@ namespace ams::fs::impl {
|
||||
Result Read(s64 *out_count, DirectoryEntry *out_entries, s64 max_entries);
|
||||
Result GetEntryCount(s64 *out);
|
||||
|
||||
FileSystemAccessor *GetParent() const { return std::addressof(this->parent); }
|
||||
FileSystemAccessor *GetParent() const { return std::addressof(m_parent); }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -22,20 +22,20 @@
|
||||
namespace ams::fs::impl {
|
||||
|
||||
FileAccessor::FileAccessor(std::unique_ptr<fsa::IFile>&& f, FileSystemAccessor *p, OpenMode mode)
|
||||
: impl(std::move(f)), parent(p), write_state(WriteState::None), write_result(ResultSuccess()), open_mode(mode)
|
||||
: m_impl(std::move(f)), m_parent(p), m_write_state(WriteState::None), m_write_result(ResultSuccess()), m_open_mode(mode)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
FileAccessor::~FileAccessor() {
|
||||
/* Ensure that all files are flushed. */
|
||||
if (R_SUCCEEDED(this->write_result)) {
|
||||
AMS_FS_ABORT_UNLESS_WITH_RESULT(this->write_state != WriteState::NeedsFlush, fs::ResultNeedFlush());
|
||||
if (R_SUCCEEDED(m_write_result)) {
|
||||
AMS_FS_ABORT_UNLESS_WITH_RESULT(m_write_state != WriteState::NeedsFlush, fs::ResultNeedFlush());
|
||||
}
|
||||
this->impl.reset();
|
||||
m_impl.reset();
|
||||
|
||||
if (this->parent != nullptr) {
|
||||
this->parent->NotifyCloseFile(this);
|
||||
if (m_parent != nullptr) {
|
||||
m_parent->NotifyCloseFile(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace ams::fs::impl {
|
||||
}
|
||||
|
||||
Result FileAccessor::ReadWithoutCacheAccessLog(size_t *out, s64 offset, void *buf, size_t size, const ReadOption &option) {
|
||||
return this->impl->Read(out, offset, buf, size, option);
|
||||
return m_impl->Read(out, offset, buf, size, option);
|
||||
}
|
||||
|
||||
Result FileAccessor::Read(size_t *out, s64 offset, void *buf, size_t size, const ReadOption &option) {
|
||||
@@ -54,11 +54,11 @@ namespace ams::fs::impl {
|
||||
FileHandle handle = { this };
|
||||
|
||||
/* Fail after a write fails. */
|
||||
R_UNLESS(R_SUCCEEDED(this->write_result), AMS_FS_IMPL_ACCESS_LOG_WITH_NAME(this->write_result, handle, "ReadFile", AMS_FS_IMPL_ACCESS_LOG_FORMAT_READ_FILE(out, offset, size)));
|
||||
R_UNLESS(R_SUCCEEDED(m_write_result), AMS_FS_IMPL_ACCESS_LOG_WITH_NAME(m_write_result, handle, "ReadFile", AMS_FS_IMPL_ACCESS_LOG_FORMAT_READ_FILE(out, offset, size)));
|
||||
|
||||
/* TODO: Support cache. */
|
||||
const bool use_path_cache = this->parent != nullptr && this->file_path_hash != nullptr;
|
||||
const bool use_data_cache = /* TODO */false && this->parent != nullptr && this->parent->IsFileDataCacheAttachable();
|
||||
const bool use_path_cache = m_parent != nullptr && m_file_path_hash != nullptr;
|
||||
const bool use_data_cache = /* TODO */false && m_parent != nullptr && m_parent->IsFileDataCacheAttachable();
|
||||
|
||||
if (use_path_cache && use_data_cache && false) {
|
||||
/* TODO */
|
||||
@@ -70,14 +70,14 @@ namespace ams::fs::impl {
|
||||
|
||||
Result FileAccessor::Write(s64 offset, const void *buf, size_t size, const WriteOption &option) {
|
||||
/* Fail after a write fails. */
|
||||
R_TRY(this->write_result);
|
||||
R_TRY(m_write_result);
|
||||
|
||||
auto setter = MakeScopedSetter(this->write_state, WriteState::Failed);
|
||||
if (this->file_path_hash != nullptr && /* TODO */ false) {
|
||||
auto setter = MakeScopedSetter(m_write_state, WriteState::Failed);
|
||||
if (m_file_path_hash != nullptr && /* TODO */ false) {
|
||||
/* TODO */
|
||||
AMS_ABORT();
|
||||
} else {
|
||||
R_TRY(this->UpdateLastResult(this->impl->Write(offset, buf, size, option)));
|
||||
R_TRY(this->UpdateLastResult(m_impl->Write(offset, buf, size, option)));
|
||||
}
|
||||
|
||||
setter.Set(option.HasFlushFlag() ? WriteState::None : WriteState::NeedsFlush);
|
||||
@@ -87,10 +87,10 @@ namespace ams::fs::impl {
|
||||
|
||||
Result FileAccessor::Flush() {
|
||||
/* Fail after a write fails. */
|
||||
R_TRY(this->write_result);
|
||||
R_TRY(m_write_result);
|
||||
|
||||
auto setter = MakeScopedSetter(this->write_state, WriteState::Failed);
|
||||
R_TRY(this->UpdateLastResult(this->impl->Flush()));
|
||||
auto setter = MakeScopedSetter(m_write_state, WriteState::Failed);
|
||||
R_TRY(this->UpdateLastResult(m_impl->Flush()));
|
||||
setter.Set(WriteState::None);
|
||||
|
||||
return ResultSuccess();
|
||||
@@ -98,14 +98,14 @@ namespace ams::fs::impl {
|
||||
|
||||
Result FileAccessor::SetSize(s64 size) {
|
||||
/* Fail after a write fails. */
|
||||
R_TRY(this->write_result);
|
||||
R_TRY(m_write_result);
|
||||
|
||||
const WriteState old_write_state = this->write_state;
|
||||
auto setter = MakeScopedSetter(this->write_state, WriteState::Failed);
|
||||
const WriteState old_write_state = m_write_state;
|
||||
auto setter = MakeScopedSetter(m_write_state, WriteState::Failed);
|
||||
|
||||
R_TRY(this->UpdateLastResult(this->impl->SetSize(size)));
|
||||
R_TRY(this->UpdateLastResult(m_impl->SetSize(size)));
|
||||
|
||||
if (this->file_path_hash != nullptr) {
|
||||
if (m_file_path_hash != nullptr) {
|
||||
/* TODO: invalidate path cache */
|
||||
}
|
||||
|
||||
@@ -115,13 +115,13 @@ namespace ams::fs::impl {
|
||||
|
||||
Result FileAccessor::GetSize(s64 *out) {
|
||||
/* Fail after a write fails. */
|
||||
R_TRY(this->write_result);
|
||||
R_TRY(m_write_result);
|
||||
|
||||
return this->impl->GetSize(out);
|
||||
return m_impl->GetSize(out);
|
||||
}
|
||||
|
||||
Result FileAccessor::OperateRange(void *dst, size_t dst_size, OperationId operation, s64 offset, s64 size, const void *src, size_t src_size) {
|
||||
return this->impl->OperateRange(dst, dst_size, operation, offset, size, src, src_size);
|
||||
return m_impl->OperateRange(dst, dst_size, operation, offset, size, src, src_size);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -30,13 +30,13 @@ namespace ams::fs::impl {
|
||||
class FileAccessor : public util::IntrusiveListBaseNode<FileAccessor>, public Newable {
|
||||
NON_COPYABLE(FileAccessor);
|
||||
private:
|
||||
std::unique_ptr<fsa::IFile> impl;
|
||||
FileSystemAccessor * const parent;
|
||||
WriteState write_state;
|
||||
Result write_result;
|
||||
const OpenMode open_mode;
|
||||
std::unique_ptr<FilePathHash> file_path_hash;
|
||||
s32 path_hash_index;
|
||||
std::unique_ptr<fsa::IFile> m_impl;
|
||||
FileSystemAccessor * const m_parent;
|
||||
WriteState m_write_state;
|
||||
Result m_write_result;
|
||||
const OpenMode m_open_mode;
|
||||
std::unique_ptr<FilePathHash> m_file_path_hash;
|
||||
s32 m_path_hash_index;
|
||||
public:
|
||||
FileAccessor(std::unique_ptr<fsa::IFile>&& f, FileSystemAccessor *p, OpenMode mode);
|
||||
~FileAccessor();
|
||||
@@ -48,9 +48,9 @@ namespace ams::fs::impl {
|
||||
Result GetSize(s64 *out);
|
||||
Result OperateRange(void *dst, size_t dst_size, OperationId operation, s64 offset, s64 size, const void *src, size_t src_size);
|
||||
|
||||
OpenMode GetOpenMode() const { return this->open_mode; }
|
||||
WriteState GetWriteState() const { return this->write_state; }
|
||||
FileSystemAccessor *GetParent() const { return this->parent; }
|
||||
OpenMode GetOpenMode() const { return m_open_mode; }
|
||||
WriteState GetWriteState() const { return m_write_state; }
|
||||
FileSystemAccessor *GetParent() const { return m_parent; }
|
||||
|
||||
void SetFilePathHash(std::unique_ptr<FilePathHash>&& file_path_hash, s32 index);
|
||||
Result ReadWithoutCacheAccessLog(size_t *out, s64 offset, void *buf, size_t size, const ReadOption &option);
|
||||
@@ -59,7 +59,7 @@ namespace ams::fs::impl {
|
||||
|
||||
ALWAYS_INLINE Result UpdateLastResult(Result r) {
|
||||
if (!fs::ResultNotEnoughFreeSpace::Includes(r)) {
|
||||
this->write_result = r;
|
||||
m_write_result = r;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -60,34 +60,34 @@ namespace ams::fs::impl {
|
||||
}
|
||||
|
||||
FileSystemAccessor::FileSystemAccessor(const char *n, std::unique_ptr<fsa::IFileSystem> &&fs, std::unique_ptr<fsa::ICommonMountNameGenerator> &&generator)
|
||||
: impl(std::move(fs)), open_list_lock(), mount_name_generator(std::move(generator)),
|
||||
access_log_enabled(false), data_cache_attachable(false), path_cache_attachable(false), path_cache_attached(false), multi_commit_supported(false)
|
||||
: m_impl(std::move(fs)), m_open_list_lock(), m_mount_name_generator(std::move(generator)),
|
||||
m_access_log_enabled(false), m_data_cache_attachable(false), m_path_cache_attachable(false), m_path_cache_attached(false), m_multi_commit_supported(false)
|
||||
{
|
||||
R_ABORT_UNLESS(ValidateMountName(n));
|
||||
std::strncpy(this->name.str, n, MountNameLengthMax);
|
||||
this->name.str[MountNameLengthMax] = 0;
|
||||
std::strncpy(m_name.str, n, MountNameLengthMax);
|
||||
m_name.str[MountNameLengthMax] = 0;
|
||||
}
|
||||
|
||||
FileSystemAccessor::~FileSystemAccessor() {
|
||||
std::scoped_lock lk(this->open_list_lock);
|
||||
std::scoped_lock lk(m_open_list_lock);
|
||||
|
||||
/* TODO: Iterate over list entries. */
|
||||
|
||||
if (!this->open_file_list.empty()) { R_ABORT_UNLESS(fs::ResultFileNotClosed()); }
|
||||
if (!this->open_dir_list.empty()) { R_ABORT_UNLESS(fs::ResultDirectoryNotClosed()); }
|
||||
if (!m_open_file_list.empty()) { R_ABORT_UNLESS(fs::ResultFileNotClosed()); }
|
||||
if (!m_open_dir_list.empty()) { R_ABORT_UNLESS(fs::ResultDirectoryNotClosed()); }
|
||||
|
||||
if (this->path_cache_attached) {
|
||||
if (m_path_cache_attached) {
|
||||
/* TODO: Invalidate path cache */
|
||||
}
|
||||
}
|
||||
|
||||
Result FileSystemAccessor::GetCommonMountName(char *dst, size_t dst_size) const {
|
||||
R_UNLESS(this->mount_name_generator != nullptr, fs::ResultPreconditionViolation());
|
||||
return this->mount_name_generator->GenerateCommonMountName(dst, dst_size);
|
||||
R_UNLESS(m_mount_name_generator != nullptr, fs::ResultPreconditionViolation());
|
||||
return m_mount_name_generator->GenerateCommonMountName(dst, dst_size);
|
||||
}
|
||||
|
||||
std::shared_ptr<fssrv::impl::FileSystemInterfaceAdapter> FileSystemAccessor::GetMultiCommitTarget() {
|
||||
if (this->multi_commit_supported) {
|
||||
if (m_multi_commit_supported) {
|
||||
/* TODO: Support multi commit. */
|
||||
AMS_ABORT();
|
||||
}
|
||||
@@ -95,90 +95,90 @@ namespace ams::fs::impl {
|
||||
}
|
||||
|
||||
void FileSystemAccessor::NotifyCloseFile(FileAccessor *f) {
|
||||
std::scoped_lock lk(this->open_list_lock);
|
||||
Remove(this->open_file_list, f);
|
||||
std::scoped_lock lk(m_open_list_lock);
|
||||
Remove(m_open_file_list, f);
|
||||
}
|
||||
|
||||
void FileSystemAccessor::NotifyCloseDirectory(DirectoryAccessor *d) {
|
||||
std::scoped_lock lk(this->open_list_lock);
|
||||
Remove(this->open_dir_list, d);
|
||||
std::scoped_lock lk(m_open_list_lock);
|
||||
Remove(m_open_dir_list, d);
|
||||
}
|
||||
|
||||
Result FileSystemAccessor::CreateFile(const char *path, s64 size, int option) {
|
||||
R_TRY(ValidatePath(this->name.str, path));
|
||||
if (this->path_cache_attached) {
|
||||
R_TRY(ValidatePath(m_name.str, path));
|
||||
if (m_path_cache_attached) {
|
||||
/* TODO: Path cache */
|
||||
R_TRY(this->impl->CreateFile(path, size, option));
|
||||
R_TRY(m_impl->CreateFile(path, size, option));
|
||||
} else {
|
||||
R_TRY(this->impl->CreateFile(path, size, option));
|
||||
R_TRY(m_impl->CreateFile(path, size, option));
|
||||
}
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result FileSystemAccessor::DeleteFile(const char *path) {
|
||||
R_TRY(ValidatePath(this->name.str, path));
|
||||
return this->impl->DeleteFile(path);
|
||||
R_TRY(ValidatePath(m_name.str, path));
|
||||
return m_impl->DeleteFile(path);
|
||||
}
|
||||
|
||||
Result FileSystemAccessor::CreateDirectory(const char *path) {
|
||||
R_TRY(ValidatePath(this->name.str, path));
|
||||
return this->impl->CreateDirectory(path);
|
||||
R_TRY(ValidatePath(m_name.str, path));
|
||||
return m_impl->CreateDirectory(path);
|
||||
}
|
||||
|
||||
Result FileSystemAccessor::DeleteDirectory(const char *path) {
|
||||
R_TRY(ValidatePath(this->name.str, path));
|
||||
return this->impl->DeleteDirectory(path);
|
||||
R_TRY(ValidatePath(m_name.str, path));
|
||||
return m_impl->DeleteDirectory(path);
|
||||
}
|
||||
|
||||
Result FileSystemAccessor::DeleteDirectoryRecursively(const char *path) {
|
||||
R_TRY(ValidatePath(this->name.str, path));
|
||||
return this->impl->DeleteDirectoryRecursively(path);
|
||||
R_TRY(ValidatePath(m_name.str, path));
|
||||
return m_impl->DeleteDirectoryRecursively(path);
|
||||
}
|
||||
|
||||
Result FileSystemAccessor::RenameFile(const char *old_path, const char *new_path) {
|
||||
R_TRY(ValidatePath(this->name.str, old_path));
|
||||
R_TRY(ValidatePath(this->name.str, new_path));
|
||||
if (this->path_cache_attached) {
|
||||
R_TRY(ValidatePath(m_name.str, old_path));
|
||||
R_TRY(ValidatePath(m_name.str, new_path));
|
||||
if (m_path_cache_attached) {
|
||||
/* TODO: Path cache */
|
||||
R_TRY(this->impl->RenameFile(old_path, new_path));
|
||||
R_TRY(m_impl->RenameFile(old_path, new_path));
|
||||
} else {
|
||||
R_TRY(this->impl->RenameFile(old_path, new_path));
|
||||
R_TRY(m_impl->RenameFile(old_path, new_path));
|
||||
}
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result FileSystemAccessor::RenameDirectory(const char *old_path, const char *new_path) {
|
||||
R_TRY(ValidatePath(this->name.str, old_path));
|
||||
R_TRY(ValidatePath(this->name.str, new_path));
|
||||
if (this->path_cache_attached) {
|
||||
R_TRY(ValidatePath(m_name.str, old_path));
|
||||
R_TRY(ValidatePath(m_name.str, new_path));
|
||||
if (m_path_cache_attached) {
|
||||
/* TODO: Path cache */
|
||||
R_TRY(this->impl->RenameDirectory(old_path, new_path));
|
||||
R_TRY(m_impl->RenameDirectory(old_path, new_path));
|
||||
} else {
|
||||
R_TRY(this->impl->RenameDirectory(old_path, new_path));
|
||||
R_TRY(m_impl->RenameDirectory(old_path, new_path));
|
||||
}
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result FileSystemAccessor::GetEntryType(DirectoryEntryType *out, const char *path) {
|
||||
R_TRY(ValidatePath(this->name.str, path));
|
||||
return this->impl->GetEntryType(out, path);
|
||||
R_TRY(ValidatePath(m_name.str, path));
|
||||
return m_impl->GetEntryType(out, path);
|
||||
}
|
||||
|
||||
Result FileSystemAccessor::OpenFile(std::unique_ptr<FileAccessor> *out_file, const char *path, OpenMode mode) {
|
||||
R_TRY(ValidatePath(this->name.str, path));
|
||||
R_TRY(ValidatePath(m_name.str, path));
|
||||
|
||||
std::unique_ptr<fsa::IFile> file;
|
||||
R_TRY(this->impl->OpenFile(std::addressof(file), path, mode));
|
||||
R_TRY(m_impl->OpenFile(std::addressof(file), path, mode));
|
||||
|
||||
auto accessor = new FileAccessor(std::move(file), this, mode);
|
||||
R_UNLESS(accessor != nullptr, fs::ResultAllocationFailureInFileSystemAccessorA());
|
||||
|
||||
{
|
||||
std::scoped_lock lk(this->open_list_lock);
|
||||
this->open_file_list.push_back(*accessor);
|
||||
std::scoped_lock lk(m_open_list_lock);
|
||||
m_open_file_list.push_back(*accessor);
|
||||
}
|
||||
|
||||
if (this->path_cache_attached) {
|
||||
if (m_path_cache_attached) {
|
||||
if (mode & OpenMode_AllowAppend) {
|
||||
/* TODO: Append Path cache */
|
||||
} else {
|
||||
@@ -191,17 +191,17 @@ namespace ams::fs::impl {
|
||||
}
|
||||
|
||||
Result FileSystemAccessor::OpenDirectory(std::unique_ptr<DirectoryAccessor> *out_dir, const char *path, OpenDirectoryMode mode) {
|
||||
R_TRY(ValidatePath(this->name.str, path));
|
||||
R_TRY(ValidatePath(m_name.str, path));
|
||||
|
||||
std::unique_ptr<fsa::IDirectory> dir;
|
||||
R_TRY(this->impl->OpenDirectory(std::addressof(dir), path, mode));
|
||||
R_TRY(m_impl->OpenDirectory(std::addressof(dir), path, mode));
|
||||
|
||||
auto accessor = new DirectoryAccessor(std::move(dir), *this);
|
||||
R_UNLESS(accessor != nullptr, fs::ResultAllocationFailureInFileSystemAccessorB());
|
||||
|
||||
{
|
||||
std::scoped_lock lk(this->open_list_lock);
|
||||
this->open_dir_list.push_back(*accessor);
|
||||
std::scoped_lock lk(m_open_list_lock);
|
||||
m_open_dir_list.push_back(*accessor);
|
||||
}
|
||||
|
||||
out_dir->reset(accessor);
|
||||
@@ -210,33 +210,33 @@ namespace ams::fs::impl {
|
||||
|
||||
Result FileSystemAccessor::Commit() {
|
||||
{
|
||||
std::scoped_lock lk(this->open_list_lock);
|
||||
R_ABORT_UNLESS(ValidateNoOpenWriteModeFiles(this->open_file_list));
|
||||
std::scoped_lock lk(m_open_list_lock);
|
||||
R_ABORT_UNLESS(ValidateNoOpenWriteModeFiles(m_open_file_list));
|
||||
}
|
||||
return this->impl->Commit();
|
||||
return m_impl->Commit();
|
||||
}
|
||||
|
||||
Result FileSystemAccessor::GetFreeSpaceSize(s64 *out, const char *path) {
|
||||
R_TRY(ValidatePath(this->name.str, path));
|
||||
return this->impl->GetFreeSpaceSize(out, path);
|
||||
R_TRY(ValidatePath(m_name.str, path));
|
||||
return m_impl->GetFreeSpaceSize(out, path);
|
||||
}
|
||||
|
||||
Result FileSystemAccessor::GetTotalSpaceSize(s64 *out, const char *path) {
|
||||
R_TRY(ValidatePath(this->name.str, path));
|
||||
return this->impl->GetTotalSpaceSize(out, path);
|
||||
R_TRY(ValidatePath(m_name.str, path));
|
||||
return m_impl->GetTotalSpaceSize(out, path);
|
||||
}
|
||||
|
||||
Result FileSystemAccessor::CleanDirectoryRecursively(const char *path) {
|
||||
R_TRY(ValidatePath(this->name.str, path));
|
||||
return this->impl->CleanDirectoryRecursively(path);
|
||||
R_TRY(ValidatePath(m_name.str, path));
|
||||
return m_impl->CleanDirectoryRecursively(path);
|
||||
}
|
||||
|
||||
Result FileSystemAccessor::GetFileTimeStampRaw(FileTimeStampRaw *out, const char *path) {
|
||||
return this->impl->GetFileTimeStampRaw(out, path);
|
||||
return m_impl->GetFileTimeStampRaw(out, path);
|
||||
}
|
||||
|
||||
Result FileSystemAccessor::QueryEntry(char *dst, size_t dst_size, const char *src, size_t src_size, fsa::QueryId query, const char *path) {
|
||||
return this->impl->QueryEntry(dst, dst_size, src, src_size, query, path);
|
||||
return m_impl->QueryEntry(dst, dst_size, src, src_size, query, path);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -31,17 +31,17 @@ namespace ams::fs::impl {
|
||||
using FileList = util::IntrusiveListBaseTraits<FileAccessor>::ListType;
|
||||
using DirList = util::IntrusiveListBaseTraits<DirectoryAccessor>::ListType;
|
||||
private:
|
||||
MountName name;
|
||||
std::unique_ptr<fsa::IFileSystem> impl;
|
||||
FileList open_file_list;
|
||||
DirList open_dir_list;
|
||||
os::SdkMutex open_list_lock;
|
||||
std::unique_ptr<fsa::ICommonMountNameGenerator> mount_name_generator;
|
||||
bool access_log_enabled;
|
||||
bool data_cache_attachable;
|
||||
bool path_cache_attachable;
|
||||
bool path_cache_attached;
|
||||
bool multi_commit_supported;
|
||||
MountName m_name;
|
||||
std::unique_ptr<fsa::IFileSystem> m_impl;
|
||||
FileList m_open_file_list;
|
||||
DirList m_open_dir_list;
|
||||
os::SdkMutex m_open_list_lock;
|
||||
std::unique_ptr<fsa::ICommonMountNameGenerator> m_mount_name_generator;
|
||||
bool m_access_log_enabled;
|
||||
bool m_data_cache_attachable;
|
||||
bool m_path_cache_attachable;
|
||||
bool m_path_cache_attached;
|
||||
bool m_multi_commit_supported;
|
||||
public:
|
||||
FileSystemAccessor(const char *name, std::unique_ptr<fsa::IFileSystem> &&fs, std::unique_ptr<fsa::ICommonMountNameGenerator> &&generator = nullptr);
|
||||
virtual ~FileSystemAccessor();
|
||||
@@ -63,32 +63,32 @@ namespace ams::fs::impl {
|
||||
Result GetFileTimeStampRaw(FileTimeStampRaw *out, const char *path);
|
||||
Result QueryEntry(char *dst, size_t dst_size, const char *src, size_t src_size, fsa::QueryId query, const char *path);
|
||||
|
||||
const char *GetName() const { return this->name.str; }
|
||||
const char *GetName() const { return m_name.str; }
|
||||
Result GetCommonMountName(char *dst, size_t dst_size) const;
|
||||
|
||||
void SetAccessLogEnabled(bool en) { this->access_log_enabled = en; }
|
||||
void SetFileDataCacheAttachable(bool en) { this->data_cache_attachable = en; }
|
||||
void SetPathBasedFileDataCacheAttachable(bool en) { this->path_cache_attachable = en; }
|
||||
void SetMultiCommitSupported(bool en) { this->multi_commit_supported = en; }
|
||||
void SetAccessLogEnabled(bool en) { m_access_log_enabled = en; }
|
||||
void SetFileDataCacheAttachable(bool en) { m_data_cache_attachable = en; }
|
||||
void SetPathBasedFileDataCacheAttachable(bool en) { m_path_cache_attachable = en; }
|
||||
void SetMultiCommitSupported(bool en) { m_multi_commit_supported = en; }
|
||||
|
||||
bool IsEnabledAccessLog() const { return this->access_log_enabled; }
|
||||
bool IsFileDataCacheAttachable() const { return this->data_cache_attachable; }
|
||||
bool IsPathBasedFileDataCacheAttachable() const { return this->path_cache_attachable; }
|
||||
bool IsEnabledAccessLog() const { return m_access_log_enabled; }
|
||||
bool IsFileDataCacheAttachable() const { return m_data_cache_attachable; }
|
||||
bool IsPathBasedFileDataCacheAttachable() const { return m_path_cache_attachable; }
|
||||
|
||||
void AttachPathBasedFileDataCache() {
|
||||
if (this->IsPathBasedFileDataCacheAttachable()) {
|
||||
this->path_cache_attached = true;
|
||||
m_path_cache_attached = true;
|
||||
}
|
||||
}
|
||||
|
||||
void DetachPathBasedFileDataCache() {
|
||||
this->path_cache_attached = false;
|
||||
m_path_cache_attached = false;
|
||||
}
|
||||
|
||||
std::shared_ptr<fssrv::impl::FileSystemInterfaceAdapter> GetMultiCommitTarget();
|
||||
|
||||
fsa::IFileSystem *GetRawFileSystemUnsafe() {
|
||||
return this->impl.get();
|
||||
return m_impl.get();
|
||||
}
|
||||
private:
|
||||
void NotifyCloseFile(FileAccessor *f);
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace ams::fs::impl {
|
||||
}
|
||||
|
||||
bool MountTable::CanAcceptMountName(const char *name) {
|
||||
for (const auto &fs : this->fs_list) {
|
||||
for (const auto &fs : m_fs_list) {
|
||||
if (MatchesName(fs, name)) {
|
||||
return false;
|
||||
}
|
||||
@@ -36,18 +36,18 @@ namespace ams::fs::impl {
|
||||
}
|
||||
|
||||
Result MountTable::Mount(std::unique_ptr<FileSystemAccessor> &&fs) {
|
||||
std::scoped_lock lk(this->mutex);
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
R_UNLESS(this->CanAcceptMountName(fs->GetName()), fs::ResultMountNameAlreadyExists());
|
||||
|
||||
this->fs_list.push_back(*fs.release());
|
||||
m_fs_list.push_back(*fs.release());
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result MountTable::Find(FileSystemAccessor **out, const char *name) {
|
||||
std::scoped_lock lk(this->mutex);
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
for (auto &fs : this->fs_list) {
|
||||
for (auto &fs : m_fs_list) {
|
||||
if (MatchesName(fs, name)) {
|
||||
*out = std::addressof(fs);
|
||||
return ResultSuccess();
|
||||
@@ -58,12 +58,12 @@ namespace ams::fs::impl {
|
||||
}
|
||||
|
||||
void MountTable::Unmount(const char *name) {
|
||||
std::scoped_lock lk(this->mutex);
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
for (auto it = this->fs_list.cbegin(); it != this->fs_list.cend(); it++) {
|
||||
for (auto it = m_fs_list.cbegin(); it != m_fs_list.cend(); it++) {
|
||||
if (MatchesName(*it, name)) {
|
||||
auto p = std::addressof(*it);
|
||||
this->fs_list.erase(it);
|
||||
m_fs_list.erase(it);
|
||||
delete p;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -25,10 +25,10 @@ namespace ams::fs::impl {
|
||||
private:
|
||||
using FileSystemList = util::IntrusiveListBaseTraits<FileSystemAccessor>::ListType;
|
||||
private:
|
||||
FileSystemList fs_list;
|
||||
os::SdkMutex mutex;
|
||||
FileSystemList m_fs_list;
|
||||
os::SdkMutex m_mutex;
|
||||
public:
|
||||
constexpr MountTable() : fs_list(), mutex() { /* ... */ }
|
||||
constexpr MountTable() : m_fs_list(), m_mutex() { /* ... */ }
|
||||
private:
|
||||
bool CanAcceptMountName(const char *name);
|
||||
public:
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace ams::fs::impl {
|
||||
|
||||
namespace {
|
||||
|
||||
MountTable g_mount_table;
|
||||
constinit MountTable g_mount_table;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -21,15 +21,15 @@ namespace ams::fssrv::fscreator {
|
||||
|
||||
class RomFileSystemWithBuffer : public ::ams::fssystem::RomFsFileSystem {
|
||||
private:
|
||||
void *meta_cache_buffer;
|
||||
size_t meta_cache_buffer_size;
|
||||
MemoryResource *allocator;
|
||||
void *m_meta_cache_buffer;
|
||||
size_t m_meta_cache_buffer_size;
|
||||
MemoryResource *m_allocator;
|
||||
public:
|
||||
explicit RomFileSystemWithBuffer(MemoryResource *mr) : meta_cache_buffer(nullptr), allocator(mr) { /* ... */ }
|
||||
explicit RomFileSystemWithBuffer(MemoryResource *mr) : m_meta_cache_buffer(nullptr), m_allocator(mr) { /* ... */ }
|
||||
|
||||
~RomFileSystemWithBuffer() {
|
||||
if (this->meta_cache_buffer != nullptr) {
|
||||
this->allocator->Deallocate(this->meta_cache_buffer, this->meta_cache_buffer_size);
|
||||
if (m_meta_cache_buffer != nullptr) {
|
||||
m_allocator->Deallocate(m_meta_cache_buffer, m_meta_cache_buffer_size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,14 +41,14 @@ namespace ams::fssrv::fscreator {
|
||||
}
|
||||
|
||||
/* Allocate a buffer. */
|
||||
this->meta_cache_buffer = this->allocator->Allocate(buffer_size);
|
||||
if (this->meta_cache_buffer == nullptr) {
|
||||
m_meta_cache_buffer = m_allocator->Allocate(buffer_size);
|
||||
if (m_meta_cache_buffer == nullptr) {
|
||||
return RomFsFileSystem::Initialize(std::move(storage), nullptr, 0, false);
|
||||
}
|
||||
|
||||
/* Initialize with cache buffer. */
|
||||
this->meta_cache_buffer_size = buffer_size;
|
||||
return RomFsFileSystem::Initialize(std::move(storage), this->meta_cache_buffer, this->meta_cache_buffer_size, true);
|
||||
m_meta_cache_buffer_size = buffer_size;
|
||||
return RomFsFileSystem::Initialize(std::move(storage), m_meta_cache_buffer, m_meta_cache_buffer_size, true);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace ams::fssrv::fscreator {
|
||||
|
||||
Result RomFileSystemCreator::Create(std::shared_ptr<fs::fsa::IFileSystem> *out, std::shared_ptr<fs::IStorage> storage) {
|
||||
/* Allocate a filesystem. */
|
||||
std::shared_ptr fs = fssystem::AllocateShared<RomFileSystemWithBuffer>(this->allocator);
|
||||
std::shared_ptr fs = fssystem::AllocateShared<RomFileSystemWithBuffer>(m_allocator);
|
||||
R_UNLESS(fs != nullptr, fs::ResultAllocationFailureInRomFileSystemCreatorA());
|
||||
|
||||
/* Initialize the filesystem. */
|
||||
|
||||
@@ -44,9 +44,9 @@ namespace ams::fssrv::fscreator {
|
||||
R_UNLESS(size == sizeof(acid_size), fs::ResultInvalidAcidFileSize());
|
||||
|
||||
/* Allocate memory for the acid. */
|
||||
u8 *acid = static_cast<u8 *>(this->allocator->Allocate(acid_size));
|
||||
u8 *acid = static_cast<u8 *>(m_allocator->Allocate(acid_size));
|
||||
R_UNLESS(acid != nullptr, fs::ResultAllocationFailureInStorageOnNcaCreatorA());
|
||||
ON_SCOPE_EXIT { this->allocator->Deallocate(acid, acid_size); };
|
||||
ON_SCOPE_EXIT { m_allocator->Deallocate(acid, acid_size); };
|
||||
|
||||
/* Read the acid. */
|
||||
R_TRY(file->Read(std::addressof(size), acid_offset, acid, acid_size, fs::ReadOption()));
|
||||
@@ -72,7 +72,7 @@ namespace ams::fssrv::fscreator {
|
||||
{
|
||||
const u8 *sig = acid + AcidSignOffset;
|
||||
const size_t sig_size = static_cast<size_t>(AcidSignSize);
|
||||
const u8 *mod = fssystem::GetAcidSignatureKeyModulus(this->is_prod, acid_signature_key_generation);
|
||||
const u8 *mod = fssystem::GetAcidSignatureKeyModulus(m_is_prod, acid_signature_key_generation);
|
||||
const size_t mod_size = fssystem::AcidSignatureKeyModulusSize;
|
||||
const u8 *exp = fssystem::GetAcidSignatureKeyPublicExponent();
|
||||
const size_t exp_size = fssystem::AcidSignatureKeyPublicExponentSize;
|
||||
@@ -81,7 +81,7 @@ namespace ams::fssrv::fscreator {
|
||||
const bool is_signature_valid = crypto::VerifyRsa2048PssSha256(sig, sig_size, mod, mod_size, exp, exp_size, msg, msg_size);
|
||||
if (!is_signature_valid) {
|
||||
/* If the signature is invalid, then unless program verification is disabled error out. */
|
||||
R_UNLESS(!this->is_enabled_program_verification, fs::ResultAcidVerificationFailed());
|
||||
R_UNLESS(!m_is_enabled_program_verification, fs::ResultAcidVerificationFailed());
|
||||
|
||||
/* If program verification is disabled, then we're fine. */
|
||||
return ResultSuccess();
|
||||
@@ -104,7 +104,7 @@ namespace ams::fssrv::fscreator {
|
||||
|
||||
Result StorageOnNcaCreator::Create(std::shared_ptr<fs::IStorage> *out, fssystem::NcaFsHeaderReader *out_header_reader, std::shared_ptr<fssystem::NcaReader> nca_reader, s32 index, bool verify_header_sign_2) {
|
||||
/* Create a fs driver. */
|
||||
fssystem::NcaFileSystemDriver nca_fs_driver(nca_reader, this->allocator, this->buffer_manager);
|
||||
fssystem::NcaFileSystemDriver nca_fs_driver(nca_reader, m_allocator, m_buffer_manager);
|
||||
|
||||
/* Open the storage. */
|
||||
std::shared_ptr<fs::IStorage> storage;
|
||||
@@ -122,7 +122,7 @@ namespace ams::fssrv::fscreator {
|
||||
|
||||
Result StorageOnNcaCreator::CreateWithPatch(std::shared_ptr<fs::IStorage> *out, fssystem::NcaFsHeaderReader *out_header_reader, std::shared_ptr<fssystem::NcaReader> original_nca_reader, std::shared_ptr<fssystem::NcaReader> current_nca_reader, s32 index, bool verify_header_sign_2) {
|
||||
/* Create a fs driver. */
|
||||
fssystem::NcaFileSystemDriver nca_fs_driver(original_nca_reader, current_nca_reader, this->allocator, this->buffer_manager);
|
||||
fssystem::NcaFileSystemDriver nca_fs_driver(original_nca_reader, current_nca_reader, m_allocator, m_buffer_manager);
|
||||
|
||||
/* Open the storage. */
|
||||
std::shared_ptr<fs::IStorage> storage;
|
||||
@@ -144,7 +144,7 @@ namespace ams::fssrv::fscreator {
|
||||
R_UNLESS(reader != nullptr, fs::ResultAllocationFailureInStorageOnNcaCreatorB());
|
||||
|
||||
/* Initialize the reader. */
|
||||
R_TRY(reader->Initialize(std::move(storage), this->nca_crypto_cfg));
|
||||
R_TRY(reader->Initialize(std::move(storage), m_nca_crypto_cfg));
|
||||
|
||||
/* Set the output. */
|
||||
*out = std::move(reader);
|
||||
@@ -152,8 +152,8 @@ namespace ams::fssrv::fscreator {
|
||||
}
|
||||
|
||||
void StorageOnNcaCreator::SetEnabledProgramVerification(bool en) {
|
||||
if (!this->is_prod) {
|
||||
this->is_enabled_program_verification = en;
|
||||
if (!m_is_prod) {
|
||||
m_is_enabled_program_verification = en;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
namespace ams::fssrv::impl {
|
||||
|
||||
FileInterfaceAdapter::FileInterfaceAdapter(std::unique_ptr<fs::fsa::IFile> &&file, FileSystemInterfaceAdapter *parent, util::unique_lock<fssystem::SemaphoreAdapter> &&sema)
|
||||
: parent_filesystem(parent, true), base_file(std::move(file)), open_count_semaphore(std::move(sema))
|
||||
: m_parent_filesystem(parent, true), m_base_file(std::move(file)), m_open_count_semaphore(std::move(sema))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
@@ -30,9 +30,9 @@ namespace ams::fssrv::impl {
|
||||
}
|
||||
|
||||
void FileInterfaceAdapter::InvalidateCache() {
|
||||
AMS_ABORT_UNLESS(this->parent_filesystem->IsDeepRetryEnabled());
|
||||
std::scoped_lock<os::ReaderWriterLock> scoped_write_lock(this->parent_filesystem->GetReaderWriterLockForCacheInvalidation());
|
||||
this->base_file->OperateRange(nullptr, 0, fs::OperationId::Invalidate, 0, std::numeric_limits<s64>::max(), nullptr, 0);
|
||||
AMS_ABORT_UNLESS(m_parent_filesystem->IsDeepRetryEnabled());
|
||||
std::scoped_lock<os::ReaderWriterLock> scoped_write_lock(m_parent_filesystem->GetReaderWriterLockForCacheInvalidation());
|
||||
m_base_file->OperateRange(nullptr, 0, fs::OperationId::Invalidate, 0, std::numeric_limits<s64>::max(), nullptr, 0);
|
||||
}
|
||||
|
||||
Result FileInterfaceAdapter::Read(ams::sf::Out<s64> out, s64 offset, const ams::sf::OutNonSecureBuffer &buffer, s64 size, fs::ReadOption option) {
|
||||
@@ -42,7 +42,7 @@ namespace ams::fssrv::impl {
|
||||
R_UNLESS(size >= 0, fs::ResultInvalidSize());
|
||||
|
||||
size_t read_size = 0;
|
||||
R_TRY(this->base_file->Read(std::addressof(read_size), offset, buffer.GetPointer(), static_cast<size_t>(size), option));
|
||||
R_TRY(m_base_file->Read(std::addressof(read_size), offset, buffer.GetPointer(), static_cast<size_t>(size), option));
|
||||
|
||||
out.SetValue(read_size);
|
||||
return ResultSuccess();
|
||||
@@ -53,24 +53,24 @@ namespace ams::fssrv::impl {
|
||||
R_UNLESS(offset >= 0, fs::ResultInvalidOffset());
|
||||
R_UNLESS(size >= 0, fs::ResultInvalidSize());
|
||||
|
||||
auto read_lock = this->parent_filesystem->AcquireCacheInvalidationReadLock();
|
||||
return this->base_file->Write(offset, buffer.GetPointer(), size, option);
|
||||
auto read_lock = m_parent_filesystem->AcquireCacheInvalidationReadLock();
|
||||
return m_base_file->Write(offset, buffer.GetPointer(), size, option);
|
||||
}
|
||||
|
||||
Result FileInterfaceAdapter::Flush() {
|
||||
auto read_lock = this->parent_filesystem->AcquireCacheInvalidationReadLock();
|
||||
return this->base_file->Flush();
|
||||
auto read_lock = m_parent_filesystem->AcquireCacheInvalidationReadLock();
|
||||
return m_base_file->Flush();
|
||||
}
|
||||
|
||||
Result FileInterfaceAdapter::SetSize(s64 size) {
|
||||
R_UNLESS(size >= 0, fs::ResultInvalidSize());
|
||||
auto read_lock = this->parent_filesystem->AcquireCacheInvalidationReadLock();
|
||||
return this->base_file->SetSize(size);
|
||||
auto read_lock = m_parent_filesystem->AcquireCacheInvalidationReadLock();
|
||||
return m_base_file->SetSize(size);
|
||||
}
|
||||
|
||||
Result FileInterfaceAdapter::GetSize(ams::sf::Out<s64> out) {
|
||||
auto read_lock = this->parent_filesystem->AcquireCacheInvalidationReadLock();
|
||||
return this->base_file->GetSize(out.GetPointer());
|
||||
auto read_lock = m_parent_filesystem->AcquireCacheInvalidationReadLock();
|
||||
return m_base_file->GetSize(out.GetPointer());
|
||||
}
|
||||
|
||||
Result FileInterfaceAdapter::OperateRange(ams::sf::Out<fs::FileQueryRangeInfo> out, s32 op_id, s64 offset, s64 size) {
|
||||
@@ -79,10 +79,10 @@ namespace ams::fssrv::impl {
|
||||
|
||||
out->Clear();
|
||||
if (op_id == static_cast<s32>(fs::OperationId::QueryRange)) {
|
||||
auto read_lock = this->parent_filesystem->AcquireCacheInvalidationReadLock();
|
||||
auto read_lock = m_parent_filesystem->AcquireCacheInvalidationReadLock();
|
||||
|
||||
fs::FileQueryRangeInfo info;
|
||||
R_TRY(this->base_file->OperateRange(std::addressof(info), sizeof(info), fs::OperationId::QueryRange, offset, size, nullptr, 0));
|
||||
R_TRY(m_base_file->OperateRange(std::addressof(info), sizeof(info), fs::OperationId::QueryRange, offset, size, nullptr, 0));
|
||||
out->Merge(info);
|
||||
}
|
||||
|
||||
@@ -105,13 +105,13 @@ namespace ams::fssrv::impl {
|
||||
}
|
||||
|
||||
/* Perform the operation. */
|
||||
R_TRY(this->base_file->OperateRange(out_buf.GetPointer(), out_buf.GetSize(), static_cast<fs::OperationId>(op_id), offset, size, in_buf.GetPointer(), in_buf.GetSize()));
|
||||
R_TRY(m_base_file->OperateRange(out_buf.GetPointer(), out_buf.GetSize(), static_cast<fs::OperationId>(op_id), offset, size, in_buf.GetPointer(), in_buf.GetSize()));
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
DirectoryInterfaceAdapter::DirectoryInterfaceAdapter(std::unique_ptr<fs::fsa::IDirectory> &&dir, FileSystemInterfaceAdapter *parent, util::unique_lock<fssystem::SemaphoreAdapter> &&sema)
|
||||
: parent_filesystem(parent, true), base_dir(std::move(dir)), open_count_semaphore(std::move(sema))
|
||||
: m_parent_filesystem(parent, true), m_base_dir(std::move(dir)), m_open_count_semaphore(std::move(sema))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
@@ -121,22 +121,22 @@ namespace ams::fssrv::impl {
|
||||
}
|
||||
|
||||
Result DirectoryInterfaceAdapter::Read(ams::sf::Out<s64> out, const ams::sf::OutBuffer &out_entries) {
|
||||
auto read_lock = this->parent_filesystem->AcquireCacheInvalidationReadLock();
|
||||
auto read_lock = m_parent_filesystem->AcquireCacheInvalidationReadLock();
|
||||
|
||||
const s64 max_num_entries = out_entries.GetSize() / sizeof(fs::DirectoryEntry);
|
||||
R_UNLESS(max_num_entries >= 0, fs::ResultInvalidSize());
|
||||
|
||||
/* TODO: N retries on fs::ResultDataCorrupted, we may want to eventually. */
|
||||
return this->base_dir->Read(out.GetPointer(), reinterpret_cast<fs::DirectoryEntry *>(out_entries.GetPointer()), max_num_entries);
|
||||
return m_base_dir->Read(out.GetPointer(), reinterpret_cast<fs::DirectoryEntry *>(out_entries.GetPointer()), max_num_entries);
|
||||
}
|
||||
|
||||
Result DirectoryInterfaceAdapter::GetEntryCount(ams::sf::Out<s64> out) {
|
||||
auto read_lock = this->parent_filesystem->AcquireCacheInvalidationReadLock();
|
||||
return this->base_dir->GetEntryCount(out.GetPointer());
|
||||
auto read_lock = m_parent_filesystem->AcquireCacheInvalidationReadLock();
|
||||
return m_base_dir->GetEntryCount(out.GetPointer());
|
||||
}
|
||||
|
||||
FileSystemInterfaceAdapter::FileSystemInterfaceAdapter(std::shared_ptr<fs::fsa::IFileSystem> &&fs, bool open_limited)
|
||||
: base_fs(std::move(fs)), open_count_limited(open_limited), deep_retry_enabled(false)
|
||||
: m_base_fs(std::move(fs)), m_open_count_limited(open_limited), m_deep_retry_enabled(false)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
@@ -146,7 +146,7 @@ namespace ams::fssrv::impl {
|
||||
}
|
||||
|
||||
bool FileSystemInterfaceAdapter::IsDeepRetryEnabled() const {
|
||||
return this->deep_retry_enabled;
|
||||
return m_deep_retry_enabled;
|
||||
}
|
||||
|
||||
bool FileSystemInterfaceAdapter::IsAccessFailureDetectionObserved() const {
|
||||
@@ -156,14 +156,14 @@ namespace ams::fssrv::impl {
|
||||
|
||||
util::optional<std::shared_lock<os::ReaderWriterLock>> FileSystemInterfaceAdapter::AcquireCacheInvalidationReadLock() {
|
||||
util::optional<std::shared_lock<os::ReaderWriterLock>> lock;
|
||||
if (this->deep_retry_enabled) {
|
||||
lock.emplace(this->invalidation_lock);
|
||||
if (m_deep_retry_enabled) {
|
||||
lock.emplace(m_invalidation_lock);
|
||||
}
|
||||
return lock;
|
||||
}
|
||||
|
||||
os::ReaderWriterLock &FileSystemInterfaceAdapter::GetReaderWriterLockForCacheInvalidation() {
|
||||
return this->invalidation_lock;
|
||||
return m_invalidation_lock;
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::CreateFile(const fssrv::sf::Path &path, s64 size, s32 option) {
|
||||
@@ -174,7 +174,7 @@ namespace ams::fssrv::impl {
|
||||
PathNormalizer normalizer(path.str);
|
||||
R_UNLESS(normalizer.GetPath() != nullptr, normalizer.GetResult());
|
||||
|
||||
return this->base_fs->CreateFile(normalizer.GetPath(), size, option);
|
||||
return m_base_fs->CreateFile(normalizer.GetPath(), size, option);
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::DeleteFile(const fssrv::sf::Path &path) {
|
||||
@@ -183,7 +183,7 @@ namespace ams::fssrv::impl {
|
||||
PathNormalizer normalizer(path.str);
|
||||
R_UNLESS(normalizer.GetPath() != nullptr, normalizer.GetResult());
|
||||
|
||||
return this->base_fs->DeleteFile(normalizer.GetPath());
|
||||
return m_base_fs->DeleteFile(normalizer.GetPath());
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::CreateDirectory(const fssrv::sf::Path &path) {
|
||||
@@ -194,7 +194,7 @@ namespace ams::fssrv::impl {
|
||||
|
||||
R_UNLESS(strncmp(normalizer.GetPath(), "/", 2) != 0, fs::ResultPathAlreadyExists());
|
||||
|
||||
return this->base_fs->CreateDirectory(normalizer.GetPath());
|
||||
return m_base_fs->CreateDirectory(normalizer.GetPath());
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::DeleteDirectory(const fssrv::sf::Path &path) {
|
||||
@@ -205,7 +205,7 @@ namespace ams::fssrv::impl {
|
||||
|
||||
R_UNLESS(strncmp(normalizer.GetPath(), "/", 2) != 0, fs::ResultDirectoryNotDeletable());
|
||||
|
||||
return this->base_fs->DeleteDirectory(normalizer.GetPath());
|
||||
return m_base_fs->DeleteDirectory(normalizer.GetPath());
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::DeleteDirectoryRecursively(const fssrv::sf::Path &path) {
|
||||
@@ -216,7 +216,7 @@ namespace ams::fssrv::impl {
|
||||
|
||||
R_UNLESS(strncmp(normalizer.GetPath(), "/", 2) != 0, fs::ResultDirectoryNotDeletable());
|
||||
|
||||
return this->base_fs->DeleteDirectoryRecursively(normalizer.GetPath());
|
||||
return m_base_fs->DeleteDirectoryRecursively(normalizer.GetPath());
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::RenameFile(const fssrv::sf::Path &old_path, const fssrv::sf::Path &new_path) {
|
||||
@@ -227,7 +227,7 @@ namespace ams::fssrv::impl {
|
||||
R_UNLESS(old_normalizer.GetPath() != nullptr, old_normalizer.GetResult());
|
||||
R_UNLESS(new_normalizer.GetPath() != nullptr, new_normalizer.GetResult());
|
||||
|
||||
return this->base_fs->RenameFile(old_normalizer.GetPath(), new_normalizer.GetPath());
|
||||
return m_base_fs->RenameFile(old_normalizer.GetPath(), new_normalizer.GetPath());
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::RenameDirectory(const fssrv::sf::Path &old_path, const fssrv::sf::Path &new_path) {
|
||||
@@ -241,7 +241,7 @@ namespace ams::fssrv::impl {
|
||||
const bool is_subpath = fs::IsSubPath(old_normalizer.GetPath(), new_normalizer.GetPath());
|
||||
R_UNLESS(!is_subpath, fs::ResultDirectoryNotRenamable());
|
||||
|
||||
return this->base_fs->RenameFile(old_normalizer.GetPath(), new_normalizer.GetPath());
|
||||
return m_base_fs->RenameFile(old_normalizer.GetPath(), new_normalizer.GetPath());
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::GetEntryType(ams::sf::Out<u32> out, const fssrv::sf::Path &path) {
|
||||
@@ -251,14 +251,14 @@ namespace ams::fssrv::impl {
|
||||
R_UNLESS(normalizer.GetPath() != nullptr, normalizer.GetResult());
|
||||
|
||||
static_assert(sizeof(*out.GetPointer()) == sizeof(fs::DirectoryEntryType));
|
||||
return this->base_fs->GetEntryType(reinterpret_cast<fs::DirectoryEntryType *>(out.GetPointer()), normalizer.GetPath());
|
||||
return m_base_fs->GetEntryType(reinterpret_cast<fs::DirectoryEntryType *>(out.GetPointer()), normalizer.GetPath());
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::OpenFile(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFile>> out, const fssrv::sf::Path &path, u32 mode) {
|
||||
auto read_lock = this->AcquireCacheInvalidationReadLock();
|
||||
|
||||
util::unique_lock<fssystem::SemaphoreAdapter> open_count_semaphore;
|
||||
if (this->open_count_limited) {
|
||||
if (m_open_count_limited) {
|
||||
/* TODO: This calls into fssrv::FileSystemProxyImpl, which we don't have yet. */
|
||||
AMS_ABORT_UNLESS(false);
|
||||
}
|
||||
@@ -268,7 +268,7 @@ namespace ams::fssrv::impl {
|
||||
|
||||
/* TODO: N retries on fs::ResultDataCorrupted, we may want to eventually. */
|
||||
std::unique_ptr<fs::fsa::IFile> file;
|
||||
R_TRY(this->base_fs->OpenFile(std::addressof(file), normalizer.GetPath(), static_cast<fs::OpenMode>(mode)));
|
||||
R_TRY(m_base_fs->OpenFile(std::addressof(file), normalizer.GetPath(), static_cast<fs::OpenMode>(mode)));
|
||||
|
||||
/* TODO: This is a hack to get the mitm API to work. Better solution? */
|
||||
const auto target_object_id = file->GetDomainObjectId();
|
||||
@@ -286,7 +286,7 @@ namespace ams::fssrv::impl {
|
||||
auto read_lock = this->AcquireCacheInvalidationReadLock();
|
||||
|
||||
util::unique_lock<fssystem::SemaphoreAdapter> open_count_semaphore;
|
||||
if (this->open_count_limited) {
|
||||
if (m_open_count_limited) {
|
||||
/* TODO: This calls into fssrv::FileSystemProxyImpl, which we don't have yet. */
|
||||
AMS_ABORT_UNLESS(false);
|
||||
}
|
||||
@@ -296,7 +296,7 @@ namespace ams::fssrv::impl {
|
||||
|
||||
/* TODO: N retries on fs::ResultDataCorrupted, we may want to eventually. */
|
||||
std::unique_ptr<fs::fsa::IDirectory> dir;
|
||||
R_TRY(this->base_fs->OpenDirectory(std::addressof(dir), normalizer.GetPath(), static_cast<fs::OpenDirectoryMode>(mode)));
|
||||
R_TRY(m_base_fs->OpenDirectory(std::addressof(dir), normalizer.GetPath(), static_cast<fs::OpenDirectoryMode>(mode)));
|
||||
|
||||
/* TODO: This is a hack to get the mitm API to work. Better solution? */
|
||||
const auto target_object_id = dir->GetDomainObjectId();
|
||||
@@ -311,7 +311,7 @@ namespace ams::fssrv::impl {
|
||||
Result FileSystemInterfaceAdapter::Commit() {
|
||||
auto read_lock = this->AcquireCacheInvalidationReadLock();
|
||||
|
||||
return this->base_fs->Commit();
|
||||
return m_base_fs->Commit();
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::GetFreeSpaceSize(ams::sf::Out<s64> out, const fssrv::sf::Path &path) {
|
||||
@@ -320,7 +320,7 @@ namespace ams::fssrv::impl {
|
||||
PathNormalizer normalizer(path.str);
|
||||
R_UNLESS(normalizer.GetPath() != nullptr, normalizer.GetResult());
|
||||
|
||||
return this->base_fs->GetFreeSpaceSize(out.GetPointer(), normalizer.GetPath());
|
||||
return m_base_fs->GetFreeSpaceSize(out.GetPointer(), normalizer.GetPath());
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::GetTotalSpaceSize(ams::sf::Out<s64> out, const fssrv::sf::Path &path) {
|
||||
@@ -329,7 +329,7 @@ namespace ams::fssrv::impl {
|
||||
PathNormalizer normalizer(path.str);
|
||||
R_UNLESS(normalizer.GetPath() != nullptr, normalizer.GetResult());
|
||||
|
||||
return this->base_fs->GetTotalSpaceSize(out.GetPointer(), normalizer.GetPath());
|
||||
return m_base_fs->GetTotalSpaceSize(out.GetPointer(), normalizer.GetPath());
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::CleanDirectoryRecursively(const fssrv::sf::Path &path) {
|
||||
@@ -338,7 +338,7 @@ namespace ams::fssrv::impl {
|
||||
PathNormalizer normalizer(path.str);
|
||||
R_UNLESS(normalizer.GetPath() != nullptr, normalizer.GetResult());
|
||||
|
||||
return this->base_fs->CleanDirectoryRecursively(normalizer.GetPath());
|
||||
return m_base_fs->CleanDirectoryRecursively(normalizer.GetPath());
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::GetFileTimeStampRaw(ams::sf::Out<fs::FileTimeStampRaw> out, const fssrv::sf::Path &path) {
|
||||
@@ -347,7 +347,7 @@ namespace ams::fssrv::impl {
|
||||
PathNormalizer normalizer(path.str);
|
||||
R_UNLESS(normalizer.GetPath() != nullptr, normalizer.GetResult());
|
||||
|
||||
return this->base_fs->GetFileTimeStampRaw(out.GetPointer(), normalizer.GetPath());
|
||||
return m_base_fs->GetFileTimeStampRaw(out.GetPointer(), normalizer.GetPath());
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::QueryEntry(const ams::sf::OutBuffer &out_buf, const ams::sf::InBuffer &in_buf, s32 query_id, const fssrv::sf::Path &path) {
|
||||
@@ -357,7 +357,7 @@ namespace ams::fssrv::impl {
|
||||
|
||||
char *dst = reinterpret_cast< char *>(out_buf.GetPointer());
|
||||
const char *src = reinterpret_cast<const char *>(in_buf.GetPointer());
|
||||
return this->base_fs->QueryEntry(dst, out_buf.GetSize(), src, in_buf.GetSize(), static_cast<fs::fsa::QueryId>(query_id), path.str);
|
||||
return m_base_fs->QueryEntry(dst, out_buf.GetSize(), src, in_buf.GetSize(), static_cast<fs::fsa::QueryId>(query_id), path.str);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,8 +30,8 @@ namespace ams::fssrv {
|
||||
AMS_UNUSED(size);
|
||||
|
||||
if (p != nullptr) {
|
||||
this->current_free_size = GetUsedSize(p);
|
||||
this->peak_free_size = std::min(this->peak_free_size, this->current_free_size);
|
||||
m_current_free_size = GetUsedSize(p);
|
||||
m_peak_free_size = std::min(m_peak_free_size, m_current_free_size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,14 +39,14 @@ namespace ams::fssrv {
|
||||
AMS_UNUSED(size);
|
||||
|
||||
if (p != nullptr) {
|
||||
this->current_free_size += GetUsedSize(p);
|
||||
m_current_free_size += GetUsedSize(p);
|
||||
}
|
||||
}
|
||||
|
||||
void *PeakCheckableMemoryResourceFromExpHeap::AllocateImpl(size_t size, size_t align) {
|
||||
std::scoped_lock lk(this->mutex);
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
void *p = lmem::AllocateFromExpHeap(this->heap_handle, size, static_cast<s32>(align));
|
||||
void *p = lmem::AllocateFromExpHeap(m_heap_handle, size, static_cast<s32>(align));
|
||||
this->OnAllocate(p, size);
|
||||
return p;
|
||||
}
|
||||
@@ -54,10 +54,10 @@ namespace ams::fssrv {
|
||||
void PeakCheckableMemoryResourceFromExpHeap::DeallocateImpl(void *p, size_t size, size_t align) {
|
||||
AMS_UNUSED(align);
|
||||
|
||||
std::scoped_lock lk(this->mutex);
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
this->OnDeallocate(p, size);
|
||||
lmem::FreeToExpHeap(this->heap_handle, p);
|
||||
lmem::FreeToExpHeap(m_heap_handle, p);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,28 +17,28 @@
|
||||
|
||||
namespace ams::fssrv {
|
||||
|
||||
MemoryResourceFromStandardAllocator::MemoryResourceFromStandardAllocator(mem::StandardAllocator *allocator) : allocator(allocator), mutex() {
|
||||
this->current_free_size = this->allocator->GetTotalFreeSize();
|
||||
MemoryResourceFromStandardAllocator::MemoryResourceFromStandardAllocator(mem::StandardAllocator *allocator) : m_allocator(allocator), m_mutex() {
|
||||
m_current_free_size = m_allocator->GetTotalFreeSize();
|
||||
this->ClearPeak();
|
||||
}
|
||||
|
||||
void MemoryResourceFromStandardAllocator::ClearPeak() {
|
||||
std::scoped_lock lk(this->mutex);
|
||||
this->peak_free_size = this->current_free_size;
|
||||
this->peak_allocated_size = 0;
|
||||
std::scoped_lock lk(m_mutex);
|
||||
m_peak_free_size = m_current_free_size;
|
||||
m_peak_allocated_size = 0;
|
||||
}
|
||||
|
||||
void *MemoryResourceFromStandardAllocator::AllocateImpl(size_t size, size_t align) {
|
||||
std::scoped_lock lk(this->mutex);
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
void *p = this->allocator->Allocate(size, align);
|
||||
void *p = m_allocator->Allocate(size, align);
|
||||
|
||||
if (p != nullptr) {
|
||||
this->current_free_size -= this->allocator->GetSizeOf(p);
|
||||
this->peak_free_size = std::min(this->peak_free_size, this->current_free_size);
|
||||
m_current_free_size -= m_allocator->GetSizeOf(p);
|
||||
m_peak_free_size = std::min(m_peak_free_size, m_current_free_size);
|
||||
}
|
||||
|
||||
this->peak_allocated_size = std::max(this->peak_allocated_size, size);
|
||||
m_peak_allocated_size = std::max(m_peak_allocated_size, size);
|
||||
|
||||
return p;
|
||||
}
|
||||
@@ -46,10 +46,10 @@ namespace ams::fssrv {
|
||||
void MemoryResourceFromStandardAllocator::DeallocateImpl(void *p, size_t size, size_t align) {
|
||||
AMS_UNUSED(size, align);
|
||||
|
||||
std::scoped_lock lk(this->mutex);
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
this->current_free_size += this->allocator->GetSizeOf(p);
|
||||
this->allocator->Free(p);
|
||||
m_current_free_size += m_allocator->GetSizeOf(p);
|
||||
m_allocator->Free(p);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,15 +18,15 @@
|
||||
|
||||
namespace ams::fssrv::impl {
|
||||
|
||||
StorageInterfaceAdapter::StorageInterfaceAdapter(fs::IStorage *storage) : base_storage(storage) {
|
||||
StorageInterfaceAdapter::StorageInterfaceAdapter(fs::IStorage *storage) : m_base_storage(storage) {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
StorageInterfaceAdapter::StorageInterfaceAdapter(std::unique_ptr<fs::IStorage> storage) : base_storage(storage.release()) {
|
||||
StorageInterfaceAdapter::StorageInterfaceAdapter(std::unique_ptr<fs::IStorage> storage) : m_base_storage(storage.release()) {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
StorageInterfaceAdapter::StorageInterfaceAdapter(std::shared_ptr<fs::IStorage> storage) : base_storage(std::move(storage)) {
|
||||
StorageInterfaceAdapter::StorageInterfaceAdapter(std::shared_ptr<fs::IStorage> storage) : m_base_storage(std::move(storage)) {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
@@ -36,8 +36,8 @@ namespace ams::fssrv::impl {
|
||||
|
||||
util::optional<std::shared_lock<os::ReaderWriterLock>> StorageInterfaceAdapter::AcquireCacheInvalidationReadLock() {
|
||||
util::optional<std::shared_lock<os::ReaderWriterLock>> lock;
|
||||
if (this->deep_retry_enabled) {
|
||||
lock.emplace(this->invalidation_lock);
|
||||
if (m_deep_retry_enabled) {
|
||||
lock.emplace(m_invalidation_lock);
|
||||
}
|
||||
return lock;
|
||||
}
|
||||
@@ -47,7 +47,7 @@ namespace ams::fssrv::impl {
|
||||
/* TODO: Deep retry */
|
||||
R_UNLESS(offset >= 0, fs::ResultInvalidOffset());
|
||||
R_UNLESS(size >= 0, fs::ResultInvalidSize());
|
||||
return this->base_storage->Read(offset, buffer.GetPointer(), size);
|
||||
return m_base_storage->Read(offset, buffer.GetPointer(), size);
|
||||
}
|
||||
|
||||
Result StorageInterfaceAdapter::Write(s64 offset, const ams::sf::InNonSecureBuffer &buffer, s64 size) {
|
||||
@@ -56,23 +56,23 @@ namespace ams::fssrv::impl {
|
||||
R_UNLESS(size >= 0, fs::ResultInvalidSize());
|
||||
|
||||
auto read_lock = this->AcquireCacheInvalidationReadLock();
|
||||
return this->base_storage->Write(offset, buffer.GetPointer(), size);
|
||||
return m_base_storage->Write(offset, buffer.GetPointer(), size);
|
||||
}
|
||||
|
||||
Result StorageInterfaceAdapter::Flush() {
|
||||
auto read_lock = this->AcquireCacheInvalidationReadLock();
|
||||
return this->base_storage->Flush();
|
||||
return m_base_storage->Flush();
|
||||
}
|
||||
|
||||
Result StorageInterfaceAdapter::SetSize(s64 size) {
|
||||
R_UNLESS(size >= 0, fs::ResultInvalidSize());
|
||||
auto read_lock = this->AcquireCacheInvalidationReadLock();
|
||||
return this->base_storage->SetSize(size);
|
||||
return m_base_storage->SetSize(size);
|
||||
}
|
||||
|
||||
Result StorageInterfaceAdapter::GetSize(ams::sf::Out<s64> out) {
|
||||
auto read_lock = this->AcquireCacheInvalidationReadLock();
|
||||
return this->base_storage->GetSize(out.GetPointer());
|
||||
return m_base_storage->GetSize(out.GetPointer());
|
||||
}
|
||||
|
||||
Result StorageInterfaceAdapter::OperateRange(ams::sf::Out<fs::StorageQueryRangeInfo> out, s32 op_id, s64 offset, s64 size) {
|
||||
@@ -84,7 +84,7 @@ namespace ams::fssrv::impl {
|
||||
auto read_lock = this->AcquireCacheInvalidationReadLock();
|
||||
|
||||
fs::StorageQueryRangeInfo info;
|
||||
R_TRY(this->base_storage->OperateRange(std::addressof(info), sizeof(info), fs::OperationId::QueryRange, offset, size, nullptr, 0));
|
||||
R_TRY(m_base_storage->OperateRange(std::addressof(info), sizeof(info), fs::OperationId::QueryRange, offset, size, nullptr, 0));
|
||||
out->Merge(info);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,14 +23,14 @@ namespace ams::fssystem::buffers {
|
||||
|
||||
class ThreadLocalStorageWrapper {
|
||||
private:
|
||||
os::TlsSlot tls_slot;
|
||||
os::TlsSlot m_tls_slot;
|
||||
public:
|
||||
ThreadLocalStorageWrapper() { R_ABORT_UNLESS(os::AllocateTlsSlot(std::addressof(this->tls_slot), nullptr)); }
|
||||
~ThreadLocalStorageWrapper() { os::FreeTlsSlot(this->tls_slot); }
|
||||
ThreadLocalStorageWrapper() { R_ABORT_UNLESS(os::AllocateTlsSlot(std::addressof(m_tls_slot), nullptr)); }
|
||||
~ThreadLocalStorageWrapper() { os::FreeTlsSlot(m_tls_slot); }
|
||||
|
||||
void SetValue(uintptr_t value) { os::SetTlsValue(this->tls_slot, value); }
|
||||
uintptr_t GetValue() const { return os::GetTlsValue(this->tls_slot); }
|
||||
os::TlsSlot GetTlsSlot() const { return this->tls_slot; }
|
||||
void SetValue(uintptr_t value) { os::SetTlsValue(m_tls_slot, value); }
|
||||
uintptr_t GetValue() const { return os::GetTlsValue(m_tls_slot); }
|
||||
os::TlsSlot GetTlsSlot() const { return m_tls_slot; }
|
||||
} g_buffer_manager_context_tls_slot;
|
||||
|
||||
}
|
||||
|
||||
@@ -18,22 +18,22 @@
|
||||
namespace ams::fssystem {
|
||||
|
||||
FileSystemBuddyHeap::PageEntry *FileSystemBuddyHeap::PageList::PopFront() {
|
||||
AMS_ASSERT(this->entry_count > 0);
|
||||
AMS_ASSERT(m_entry_count > 0);
|
||||
|
||||
/* Get the first entry. */
|
||||
auto page_entry = this->first_page_entry;
|
||||
auto page_entry = m_first_page_entry;
|
||||
|
||||
/* Advance our list. */
|
||||
this->first_page_entry = page_entry->next;
|
||||
m_first_page_entry = page_entry->next;
|
||||
page_entry->next = nullptr;
|
||||
|
||||
/* Decrement our count. */
|
||||
--this->entry_count;
|
||||
AMS_ASSERT(this->entry_count >= 0);
|
||||
--m_entry_count;
|
||||
AMS_ASSERT(m_entry_count >= 0);
|
||||
|
||||
/* If this was our last page, clear our last entry. */
|
||||
if (this->entry_count == 0) {
|
||||
this->last_page_entry = nullptr;
|
||||
if (m_entry_count == 0) {
|
||||
m_last_page_entry = nullptr;
|
||||
}
|
||||
|
||||
return page_entry;
|
||||
@@ -44,20 +44,20 @@ namespace ams::fssystem {
|
||||
|
||||
/* If we're empty, we want to set the first page entry. */
|
||||
if (this->IsEmpty()) {
|
||||
this->first_page_entry = page_entry;
|
||||
m_first_page_entry = page_entry;
|
||||
} else {
|
||||
/* We're not empty, so push the page to the back. */
|
||||
AMS_ASSERT(this->last_page_entry != page_entry);
|
||||
this->last_page_entry->next = page_entry;
|
||||
AMS_ASSERT(m_last_page_entry != page_entry);
|
||||
m_last_page_entry->next = page_entry;
|
||||
}
|
||||
|
||||
/* Set our last page entry to be this one, and link it to the list. */
|
||||
this->last_page_entry = page_entry;
|
||||
this->last_page_entry->next = nullptr;
|
||||
m_last_page_entry = page_entry;
|
||||
m_last_page_entry->next = nullptr;
|
||||
|
||||
/* Increment our entry count. */
|
||||
++this->entry_count;
|
||||
AMS_ASSERT(this->entry_count > 0);
|
||||
++m_entry_count;
|
||||
AMS_ASSERT(m_entry_count > 0);
|
||||
}
|
||||
|
||||
bool FileSystemBuddyHeap::PageList::Remove(PageEntry *page_entry) {
|
||||
@@ -70,18 +70,18 @@ namespace ams::fssystem {
|
||||
|
||||
/* We're going to loop over all pages to find this one, then unlink it. */
|
||||
PageEntry *prev_entry = nullptr;
|
||||
PageEntry *cur_entry = this->first_page_entry;
|
||||
PageEntry *cur_entry = m_first_page_entry;
|
||||
|
||||
while (true) {
|
||||
/* Check if we found the page. */
|
||||
if (cur_entry == page_entry) {
|
||||
if (cur_entry == this->first_page_entry) {
|
||||
if (cur_entry == m_first_page_entry) {
|
||||
/* If it's the first page, we just set our first. */
|
||||
this->first_page_entry = cur_entry->next;
|
||||
} else if (cur_entry == this->last_page_entry) {
|
||||
m_first_page_entry = cur_entry->next;
|
||||
} else if (cur_entry == m_last_page_entry) {
|
||||
/* If it's the last page, we set our last. */
|
||||
this->last_page_entry = prev_entry;
|
||||
this->last_page_entry->next = nullptr;
|
||||
m_last_page_entry = prev_entry;
|
||||
m_last_page_entry->next = nullptr;
|
||||
} else {
|
||||
/* If it's in the middle, we just unlink. */
|
||||
prev_entry->next = cur_entry->next;
|
||||
@@ -91,8 +91,8 @@ namespace ams::fssystem {
|
||||
cur_entry->next = nullptr;
|
||||
|
||||
/* Update our entry count. */
|
||||
--this->entry_count;
|
||||
AMS_ASSERT(this->entry_count >= 0);
|
||||
--m_entry_count;
|
||||
AMS_ASSERT(m_entry_count >= 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -110,7 +110,7 @@ namespace ams::fssystem {
|
||||
|
||||
Result FileSystemBuddyHeap::Initialize(uintptr_t address, size_t size, size_t block_size, s32 order_max) {
|
||||
/* Ensure our preconditions. */
|
||||
AMS_ASSERT(this->free_lists == nullptr);
|
||||
AMS_ASSERT(m_free_lists == nullptr);
|
||||
AMS_ASSERT(address != 0);
|
||||
AMS_ASSERT(util::IsAligned(address, BufferAlignment));
|
||||
AMS_ASSERT(block_size >= BlockSizeMin);
|
||||
@@ -120,74 +120,74 @@ namespace ams::fssystem {
|
||||
AMS_ASSERT(order_max < OrderUpperLimit);
|
||||
|
||||
/* Set up our basic member variables */
|
||||
this->block_size = block_size;
|
||||
this->order_max = order_max;
|
||||
this->heap_start = address;
|
||||
this->heap_size = (size / this->block_size) * this->block_size;
|
||||
m_block_size = block_size;
|
||||
m_order_max = order_max;
|
||||
m_heap_start = address;
|
||||
m_heap_size = (size / m_block_size) * m_block_size;
|
||||
|
||||
this->total_free_size = 0;
|
||||
m_total_free_size = 0;
|
||||
|
||||
/* Determine page sizes. */
|
||||
const auto max_page_size = this->block_size << this->order_max;
|
||||
const auto max_page_count = util::AlignUp(this->heap_size, max_page_size) / max_page_size;
|
||||
const auto max_page_size = m_block_size << m_order_max;
|
||||
const auto max_page_count = util::AlignUp(m_heap_size, max_page_size) / max_page_size;
|
||||
AMS_ASSERT(max_page_count > 0);
|
||||
|
||||
/* Setup the free lists. */
|
||||
if (this->external_free_lists != nullptr) {
|
||||
AMS_ASSERT(this->internal_free_lists == nullptr);
|
||||
this->free_lists = this->external_free_lists;
|
||||
if (m_external_free_lists != nullptr) {
|
||||
AMS_ASSERT(m_internal_free_lists == nullptr);
|
||||
m_free_lists = m_external_free_lists;
|
||||
} else {
|
||||
this->internal_free_lists.reset(new PageList[this->order_max + 1]);
|
||||
this->free_lists = this->internal_free_lists.get();
|
||||
R_UNLESS(this->free_lists != nullptr, fs::ResultAllocationFailureInFileSystemBuddyHeapA());
|
||||
m_internal_free_lists.reset(new PageList[m_order_max + 1]);
|
||||
m_free_lists = m_internal_free_lists.get();
|
||||
R_UNLESS(m_free_lists != nullptr, fs::ResultAllocationFailureInFileSystemBuddyHeapA());
|
||||
}
|
||||
|
||||
/* All but the last page region should go to the max order. */
|
||||
for (size_t i = 0; i < max_page_count - 1; i++) {
|
||||
auto page_entry = this->GetPageEntryFromAddress(this->heap_start + i * max_page_size);
|
||||
this->free_lists[this->order_max].PushBack(page_entry);
|
||||
auto page_entry = this->GetPageEntryFromAddress(m_heap_start + i * max_page_size);
|
||||
m_free_lists[m_order_max].PushBack(page_entry);
|
||||
}
|
||||
this->total_free_size += this->free_lists[this->order_max].GetSize() * this->GetBytesFromOrder(this->order_max);
|
||||
m_total_free_size += m_free_lists[m_order_max].GetSize() * this->GetBytesFromOrder(m_order_max);
|
||||
|
||||
/* Allocate remaining space to smaller orders as possible. */
|
||||
{
|
||||
auto remaining = this->heap_size - (max_page_count - 1) * max_page_size;
|
||||
auto cur_address = this->heap_start + (max_page_count - 1) * max_page_size;
|
||||
AMS_ASSERT(util::IsAligned(remaining, this->block_size));
|
||||
auto remaining = m_heap_size - (max_page_count - 1) * max_page_size;
|
||||
auto cur_address = m_heap_start + (max_page_count - 1) * max_page_size;
|
||||
AMS_ASSERT(util::IsAligned(remaining, m_block_size));
|
||||
|
||||
do {
|
||||
/* Determine what order we can use. */
|
||||
auto order = GetOrderFromBytes(remaining + 1);
|
||||
if (order < 0) {
|
||||
AMS_ASSERT(GetOrderFromBytes(remaining) == this->order_max);
|
||||
order = this->order_max + 1;
|
||||
AMS_ASSERT(GetOrderFromBytes(remaining) == m_order_max);
|
||||
order = m_order_max + 1;
|
||||
}
|
||||
AMS_ASSERT(0 < order);
|
||||
AMS_ASSERT(order <= this->order_max + 1);
|
||||
AMS_ASSERT(order <= m_order_max + 1);
|
||||
|
||||
/* Add to the correct free list. */
|
||||
this->free_lists[order - 1].PushBack(GetPageEntryFromAddress(cur_address));
|
||||
this->total_free_size += GetBytesFromOrder(order - 1);
|
||||
m_free_lists[order - 1].PushBack(GetPageEntryFromAddress(cur_address));
|
||||
m_total_free_size += GetBytesFromOrder(order - 1);
|
||||
|
||||
/* Move on to the next order. */
|
||||
const auto page_size = GetBytesFromOrder(order - 1);
|
||||
cur_address += page_size;
|
||||
remaining -= page_size;
|
||||
} while (this->block_size <= remaining);
|
||||
} while (m_block_size <= remaining);
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void FileSystemBuddyHeap::Finalize() {
|
||||
AMS_ASSERT(this->free_lists != nullptr);
|
||||
this->free_lists = nullptr;
|
||||
this->external_free_lists = nullptr;
|
||||
this->internal_free_lists.reset();
|
||||
AMS_ASSERT(m_free_lists != nullptr);
|
||||
m_free_lists = nullptr;
|
||||
m_external_free_lists = nullptr;
|
||||
m_internal_free_lists.reset();
|
||||
}
|
||||
|
||||
void *FileSystemBuddyHeap::AllocateByOrder(s32 order) {
|
||||
AMS_ASSERT(this->free_lists != nullptr);
|
||||
AMS_ASSERT(m_free_lists != nullptr);
|
||||
AMS_ASSERT(order >= 0);
|
||||
AMS_ASSERT(order <= this->GetOrderMax());
|
||||
|
||||
@@ -204,7 +204,7 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
void FileSystemBuddyHeap::Free(void *ptr, s32 order) {
|
||||
AMS_ASSERT(this->free_lists != nullptr);
|
||||
AMS_ASSERT(m_free_lists != nullptr);
|
||||
AMS_ASSERT(order >= 0);
|
||||
AMS_ASSERT(order <= this->GetOrderMax());
|
||||
|
||||
@@ -214,7 +214,7 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
/* Ensure the pointer is block aligned. */
|
||||
AMS_ASSERT(util::IsAligned(reinterpret_cast<uintptr_t>(ptr) - this->heap_start, this->GetBlockSize()));
|
||||
AMS_ASSERT(util::IsAligned(reinterpret_cast<uintptr_t>(ptr) - m_heap_start, this->GetBlockSize()));
|
||||
|
||||
/* Get the page entry. */
|
||||
auto page_entry = this->GetPageEntryFromAddress(reinterpret_cast<uintptr_t>(ptr));
|
||||
@@ -225,16 +225,16 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
size_t FileSystemBuddyHeap::GetTotalFreeSize() const {
|
||||
AMS_ASSERT(this->free_lists != nullptr);
|
||||
return this->total_free_size;
|
||||
AMS_ASSERT(m_free_lists != nullptr);
|
||||
return m_total_free_size;
|
||||
}
|
||||
|
||||
size_t FileSystemBuddyHeap::GetAllocatableSizeMax() const {
|
||||
AMS_ASSERT(this->free_lists != nullptr);
|
||||
AMS_ASSERT(m_free_lists != nullptr);
|
||||
|
||||
/* The maximum allocatable size is a chunk from the biggest non-empty order. */
|
||||
for (s32 order = this->GetOrderMax(); order >= 0; --order) {
|
||||
if (!this->free_lists[order].IsEmpty()) {
|
||||
if (!m_free_lists[order].IsEmpty()) {
|
||||
return this->GetBytesFromOrder(order);
|
||||
}
|
||||
}
|
||||
@@ -244,7 +244,7 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
void FileSystemBuddyHeap::Dump() const {
|
||||
AMS_ASSERT(this->free_lists != nullptr);
|
||||
AMS_ASSERT(m_free_lists != nullptr);
|
||||
/* TODO: Support logging metrics. */
|
||||
}
|
||||
|
||||
@@ -263,8 +263,8 @@ namespace ams::fssystem {
|
||||
auto divided_entry = this->GetPageEntryFromAddress(address);
|
||||
|
||||
/* Push back to the list. */
|
||||
this->free_lists[order - 1].PushBack(divided_entry);
|
||||
this->total_free_size += this->GetBytesFromOrder(order - 1);
|
||||
m_free_lists[order - 1].PushBack(divided_entry);
|
||||
m_total_free_size += this->GetBytesFromOrder(order - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,8 +281,8 @@ namespace ams::fssystem {
|
||||
const auto buddy_entry = this->GetBuddy(cur_entry, cur_order);
|
||||
|
||||
/* Check whether the buddy is in the relevant free list. */
|
||||
if (buddy_entry != nullptr && this->free_lists[cur_order].Remove(buddy_entry)) {
|
||||
this->total_free_size -= GetBytesFromOrder(cur_order);
|
||||
if (buddy_entry != nullptr && m_free_lists[cur_order].Remove(buddy_entry)) {
|
||||
m_total_free_size -= GetBytesFromOrder(cur_order);
|
||||
|
||||
/* Ensure we coalesce with the correct buddy when page is aligned */
|
||||
if (!this->IsAlignedToOrder(cur_entry, cur_order + 1)) {
|
||||
@@ -297,8 +297,8 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
/* Insert the coalesced entry into the free list. */
|
||||
this->free_lists[cur_order].PushBack(cur_entry);
|
||||
this->total_free_size += this->GetBytesFromOrder(cur_order);
|
||||
m_free_lists[cur_order].PushBack(cur_entry);
|
||||
m_total_free_size += this->GetBytesFromOrder(cur_order);
|
||||
}
|
||||
|
||||
FileSystemBuddyHeap::PageEntry *FileSystemBuddyHeap::GetBuddy(PageEntry *page_entry, s32 order) {
|
||||
@@ -311,10 +311,10 @@ namespace ams::fssystem {
|
||||
|
||||
if (this->IsAlignedToOrder(page_entry, order + 1)) {
|
||||
/* If the page entry is aligned to the next order, return the buddy block to the right of the current entry. */
|
||||
return (address + offset < this->heap_start + this->heap_size) ? GetPageEntryFromAddress(address + offset) : nullptr;
|
||||
return (address + offset < m_heap_start + m_heap_size) ? GetPageEntryFromAddress(address + offset) : nullptr;
|
||||
} else {
|
||||
/* If the page entry isn't aligned, return the buddy block to the left of the current entry. */
|
||||
return (this->heap_start <= address - offset) ? GetPageEntryFromAddress(address - offset) : nullptr;
|
||||
return (m_heap_start <= address - offset) ? GetPageEntryFromAddress(address - offset) : nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,13 +324,13 @@ namespace ams::fssystem {
|
||||
|
||||
/* Try orders from low to high until we find a free page entry. */
|
||||
for (auto cur_order = order; cur_order <= this->GetOrderMax(); cur_order++) {
|
||||
if (auto &free_list = this->free_lists[cur_order]; !free_list.IsEmpty()) {
|
||||
if (auto &free_list = m_free_lists[cur_order]; !free_list.IsEmpty()) {
|
||||
/* The current list isn't empty, so grab an entry from it. */
|
||||
PageEntry *page_entry = free_list.PopFront();
|
||||
AMS_ASSERT(page_entry != nullptr);
|
||||
|
||||
/* Update size bookkeeping. */
|
||||
this->total_free_size -= GetBytesFromOrder(cur_order);
|
||||
m_total_free_size -= GetBytesFromOrder(cur_order);
|
||||
|
||||
/* If we allocated more memory than needed, free the unneeded portion. */
|
||||
this->DivideBuddies(page_entry, order, cur_order);
|
||||
|
||||
@@ -19,54 +19,54 @@ namespace ams::fssystem {
|
||||
|
||||
Result FileSystemBufferManager::CacheHandleTable::Initialize(s32 max_cache_count) {
|
||||
/* Validate pre-conditions. */
|
||||
AMS_ASSERT(this->entries == nullptr);
|
||||
AMS_ASSERT(this->internal_entry_buffer == nullptr);
|
||||
AMS_ASSERT(m_entries == nullptr);
|
||||
AMS_ASSERT(m_internal_entry_buffer == nullptr);
|
||||
|
||||
/* If we don't have an external buffer, try to allocate an internal one. */
|
||||
if (this->external_entry_buffer == nullptr) {
|
||||
this->entry_buffer_size = sizeof(Entry) * max_cache_count;
|
||||
this->internal_entry_buffer = fs::impl::MakeUnique<char[]>(this->entry_buffer_size);
|
||||
if (m_external_entry_buffer == nullptr) {
|
||||
m_entry_buffer_size = sizeof(Entry) * max_cache_count;
|
||||
m_internal_entry_buffer = fs::impl::MakeUnique<char[]>(m_entry_buffer_size);
|
||||
}
|
||||
|
||||
/* We need to have at least one entry buffer. */
|
||||
R_UNLESS(this->internal_entry_buffer != nullptr || this->external_entry_buffer != nullptr, fs::ResultAllocationFailureInFileSystemBufferManagerA());
|
||||
R_UNLESS(m_internal_entry_buffer != nullptr || m_external_entry_buffer != nullptr, fs::ResultAllocationFailureInFileSystemBufferManagerA());
|
||||
|
||||
/* Set entries. */
|
||||
this->entries = reinterpret_cast<Entry *>(this->external_entry_buffer != nullptr ? this->external_entry_buffer : this->internal_entry_buffer.get());
|
||||
this->entry_count = 0;
|
||||
this->entry_count_max = max_cache_count;
|
||||
AMS_ASSERT(this->entries != nullptr);
|
||||
m_entries = reinterpret_cast<Entry *>(m_external_entry_buffer != nullptr ? m_external_entry_buffer : m_internal_entry_buffer.get());
|
||||
m_entry_count = 0;
|
||||
m_entry_count_max = max_cache_count;
|
||||
AMS_ASSERT(m_entries != nullptr);
|
||||
|
||||
this->cache_count_min = max_cache_count / 16;
|
||||
this->cache_size_min = this->cache_count_min * 0x100;
|
||||
m_cache_count_min = max_cache_count / 16;
|
||||
m_cache_size_min = m_cache_count_min * 0x100;
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void FileSystemBufferManager::CacheHandleTable::Finalize() {
|
||||
if (this->entries != nullptr) {
|
||||
AMS_ASSERT(this->entry_count == 0);
|
||||
if (m_entries != nullptr) {
|
||||
AMS_ASSERT(m_entry_count == 0);
|
||||
|
||||
if (this->external_attr_info_buffer == nullptr) {
|
||||
auto it = this->attr_list.begin();
|
||||
while (it != this->attr_list.end()) {
|
||||
if (m_external_attr_info_buffer == nullptr) {
|
||||
auto it = m_attr_list.begin();
|
||||
while (it != m_attr_list.end()) {
|
||||
const auto attr_info = std::addressof(*it);
|
||||
it = this->attr_list.erase(it);
|
||||
it = m_attr_list.erase(it);
|
||||
delete attr_info;
|
||||
}
|
||||
}
|
||||
|
||||
this->internal_entry_buffer.reset();
|
||||
this->external_entry_buffer = nullptr;
|
||||
this->entry_buffer_size = 0;
|
||||
this->entries = nullptr;
|
||||
this->total_cache_size = 0;
|
||||
m_internal_entry_buffer.reset();
|
||||
m_external_entry_buffer = nullptr;
|
||||
m_entry_buffer_size = 0;
|
||||
m_entries = nullptr;
|
||||
m_total_cache_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool FileSystemBufferManager::CacheHandleTable::Register(CacheHandle *out, uintptr_t address, size_t size, const BufferAttribute &attr) {
|
||||
/* Validate pre-conditions. */
|
||||
AMS_ASSERT(this->entries != nullptr);
|
||||
AMS_ASSERT(m_entries != nullptr);
|
||||
AMS_ASSERT(out != nullptr);
|
||||
|
||||
/* Get the entry. */
|
||||
@@ -85,10 +85,10 @@ namespace ams::fssystem {
|
||||
/* Make a new attr info and add it to the list. */
|
||||
AttrInfo *new_info = nullptr;
|
||||
|
||||
if (this->external_attr_info_buffer == nullptr) {
|
||||
if (m_external_attr_info_buffer == nullptr) {
|
||||
new_info = new AttrInfo(attr.GetLevel(), 1, size);
|
||||
} else if (0 <= attr.GetLevel() && attr.GetLevel() < this->external_attr_info_count) {
|
||||
void *buffer = this->external_attr_info_buffer + attr.GetLevel() * sizeof(AttrInfo);
|
||||
} else if (0 <= attr.GetLevel() && attr.GetLevel() < m_external_attr_info_count) {
|
||||
void *buffer = m_external_attr_info_buffer + attr.GetLevel() * sizeof(AttrInfo);
|
||||
new_info = std::construct_at(reinterpret_cast<AttrInfo *>(buffer), attr.GetLevel(), 1, size);
|
||||
}
|
||||
|
||||
@@ -98,27 +98,27 @@ namespace ams::fssystem {
|
||||
return false;
|
||||
}
|
||||
|
||||
this->attr_list.push_back(*new_info);
|
||||
m_attr_list.push_back(*new_info);
|
||||
}
|
||||
|
||||
this->total_cache_size += size;
|
||||
m_total_cache_size += size;
|
||||
*out = entry->GetHandle();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileSystemBufferManager::CacheHandleTable::Unregister(uintptr_t *out_address, size_t *out_size, CacheHandle handle) {
|
||||
/* Validate pre-conditions. */
|
||||
AMS_ASSERT(this->entries != nullptr);
|
||||
AMS_ASSERT(m_entries != nullptr);
|
||||
AMS_ASSERT(out_address != nullptr);
|
||||
AMS_ASSERT(out_size != nullptr);
|
||||
|
||||
/* Find the lower bound for the entry. */
|
||||
const auto entry = std::lower_bound(this->entries, this->entries + this->entry_count, handle, [](const Entry &entry, CacheHandle handle) {
|
||||
const auto entry = std::lower_bound(m_entries, m_entries + m_entry_count, handle, [](const Entry &entry, CacheHandle handle) {
|
||||
return entry.GetHandle() < handle;
|
||||
});
|
||||
|
||||
/* If the entry is a match, unregister it. */
|
||||
if (entry != this->entries + this->entry_count && entry->GetHandle() == handle) {
|
||||
if (entry != m_entries + m_entry_count && entry->GetHandle() == handle) {
|
||||
this->UnregisterCore(out_address, out_size, entry);
|
||||
return true;
|
||||
} else {
|
||||
@@ -130,12 +130,12 @@ namespace ams::fssystem {
|
||||
AMS_UNUSED(attr, required_size);
|
||||
|
||||
/* Validate pre-conditions. */
|
||||
AMS_ASSERT(this->entries != nullptr);
|
||||
AMS_ASSERT(m_entries != nullptr);
|
||||
AMS_ASSERT(out_address != nullptr);
|
||||
AMS_ASSERT(out_size != nullptr);
|
||||
|
||||
/* If we have no entries, we can't unregister any. */
|
||||
if (this->entry_count == 0) {
|
||||
if (m_entry_count == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -150,19 +150,19 @@ namespace ams::fssystem {
|
||||
};
|
||||
|
||||
/* Find an entry, falling back to the first entry. */
|
||||
auto entry = std::find_if(this->entries, this->entries + this->entry_count, CanUnregister);
|
||||
if (entry == this->entries + this->entry_count) {
|
||||
entry = this->entries;
|
||||
auto entry = std::find_if(m_entries, m_entries + m_entry_count, CanUnregister);
|
||||
if (entry == m_entries + m_entry_count) {
|
||||
entry = m_entries;
|
||||
}
|
||||
|
||||
AMS_ASSERT(entry != this->entries + this->entry_count);
|
||||
AMS_ASSERT(entry != m_entries + m_entry_count);
|
||||
this->UnregisterCore(out_address, out_size, entry);
|
||||
return true;
|
||||
}
|
||||
|
||||
void FileSystemBufferManager::CacheHandleTable::UnregisterCore(uintptr_t *out_address, size_t *out_size, Entry *entry) {
|
||||
/* Validate pre-conditions. */
|
||||
AMS_ASSERT(this->entries != nullptr);
|
||||
AMS_ASSERT(m_entries != nullptr);
|
||||
AMS_ASSERT(out_address != nullptr);
|
||||
AMS_ASSERT(out_size != nullptr);
|
||||
AMS_ASSERT(entry != nullptr);
|
||||
@@ -178,8 +178,8 @@ namespace ams::fssystem {
|
||||
attr_info->SubtractCacheSize(entry->GetSize());
|
||||
|
||||
/* Release from cached size. */
|
||||
AMS_ASSERT(this->total_cache_size >= entry->GetSize());
|
||||
this->total_cache_size -= entry->GetSize();
|
||||
AMS_ASSERT(m_total_cache_size >= entry->GetSize());
|
||||
m_total_cache_size -= entry->GetSize();
|
||||
|
||||
/* Release the entry. */
|
||||
*out_address = entry->GetAddress();
|
||||
@@ -188,24 +188,24 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
FileSystemBufferManager::CacheHandle FileSystemBufferManager::CacheHandleTable::PublishCacheHandle() {
|
||||
AMS_ASSERT(this->entries != nullptr);
|
||||
return (++this->current_handle);
|
||||
AMS_ASSERT(m_entries != nullptr);
|
||||
return (++m_current_handle);
|
||||
}
|
||||
|
||||
size_t FileSystemBufferManager::CacheHandleTable::GetTotalCacheSize() const {
|
||||
return this->total_cache_size;
|
||||
return m_total_cache_size;
|
||||
}
|
||||
|
||||
FileSystemBufferManager::CacheHandleTable::Entry *FileSystemBufferManager::CacheHandleTable::AcquireEntry(uintptr_t address, size_t size, const BufferAttribute &attr) {
|
||||
/* Validate pre-conditions. */
|
||||
AMS_ASSERT(this->entries != nullptr);
|
||||
AMS_ASSERT(m_entries != nullptr);
|
||||
|
||||
Entry *entry = nullptr;
|
||||
if (this->entry_count < this->entry_count_max) {
|
||||
entry = this->entries + this->entry_count;
|
||||
if (m_entry_count < m_entry_count_max) {
|
||||
entry = m_entries + m_entry_count;
|
||||
entry->Initialize(this->PublishCacheHandle(), address, size, attr);
|
||||
++this->entry_count;
|
||||
AMS_ASSERT(this->entry_count == 1 || (entry-1)->GetHandle() < entry->GetHandle());
|
||||
++m_entry_count;
|
||||
AMS_ASSERT(m_entry_count == 1 || (entry-1)->GetHandle() < entry->GetHandle());
|
||||
}
|
||||
|
||||
return entry;
|
||||
@@ -213,52 +213,52 @@ namespace ams::fssystem {
|
||||
|
||||
void FileSystemBufferManager::CacheHandleTable::ReleaseEntry(Entry *entry) {
|
||||
/* Validate pre-conditions. */
|
||||
AMS_ASSERT(this->entries != nullptr);
|
||||
AMS_ASSERT(m_entries != nullptr);
|
||||
AMS_ASSERT(entry != nullptr);
|
||||
|
||||
/* Ensure the entry is valid. */
|
||||
{
|
||||
const auto entry_buffer = this->external_entry_buffer != nullptr ? this->external_entry_buffer : this->internal_entry_buffer.get();
|
||||
const auto entry_buffer = m_external_entry_buffer != nullptr ? m_external_entry_buffer : m_internal_entry_buffer.get();
|
||||
AMS_ASSERT(static_cast<void *>(entry_buffer) <= static_cast<void *>(entry));
|
||||
AMS_ASSERT(static_cast<void *>(entry) < static_cast<void *>(entry_buffer + this->entry_buffer_size));
|
||||
AMS_ASSERT(static_cast<void *>(entry) < static_cast<void *>(entry_buffer + m_entry_buffer_size));
|
||||
AMS_UNUSED(entry_buffer);
|
||||
}
|
||||
|
||||
/* Copy the entries back by one. */
|
||||
std::memmove(entry, entry + 1, sizeof(Entry) * (this->entry_count - ((entry + 1) - this->entries)));
|
||||
std::memmove(entry, entry + 1, sizeof(Entry) * (m_entry_count - ((entry + 1) - m_entries)));
|
||||
|
||||
/* Decrement our entry count. */
|
||||
--this->entry_count;
|
||||
--m_entry_count;
|
||||
}
|
||||
|
||||
FileSystemBufferManager::CacheHandleTable::AttrInfo *FileSystemBufferManager::CacheHandleTable::FindAttrInfo(const BufferAttribute &attr) {
|
||||
const auto it = std::find_if(this->attr_list.begin(), this->attr_list.end(), [&attr](const AttrInfo &info) {
|
||||
const auto it = std::find_if(m_attr_list.begin(), m_attr_list.end(), [&attr](const AttrInfo &info) {
|
||||
return attr.GetLevel() == info.GetLevel();
|
||||
});
|
||||
|
||||
return it != this->attr_list.end() ? std::addressof(*it) : nullptr;
|
||||
return it != m_attr_list.end() ? std::addressof(*it) : nullptr;
|
||||
}
|
||||
|
||||
const std::pair<uintptr_t, size_t> FileSystemBufferManager::AllocateBufferImpl(size_t size, const BufferAttribute &attr) {
|
||||
std::scoped_lock lk(this->mutex);
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
std::pair<uintptr_t, size_t> range = {};
|
||||
const auto order = this->buddy_heap.GetOrderFromBytes(size);
|
||||
const auto order = m_buddy_heap.GetOrderFromBytes(size);
|
||||
AMS_ASSERT(order >= 0);
|
||||
|
||||
while (true) {
|
||||
if (auto address = this->buddy_heap.AllocateByOrder(order); address != 0) {
|
||||
const auto allocated_size = this->buddy_heap.GetBytesFromOrder(order);
|
||||
if (auto address = m_buddy_heap.AllocateByOrder(order); address != 0) {
|
||||
const auto allocated_size = m_buddy_heap.GetBytesFromOrder(order);
|
||||
AMS_ASSERT(size <= allocated_size);
|
||||
|
||||
range.first = reinterpret_cast<uintptr_t>(address);
|
||||
range.second = allocated_size;
|
||||
|
||||
const size_t free_size = this->buddy_heap.GetTotalFreeSize();
|
||||
this->peak_free_size = std::min(this->peak_free_size, free_size);
|
||||
const size_t free_size = m_buddy_heap.GetTotalFreeSize();
|
||||
m_peak_free_size = std::min(m_peak_free_size, free_size);
|
||||
|
||||
const size_t total_allocatable_size = free_size + this->cache_handle_table.GetTotalCacheSize();
|
||||
this->peak_total_allocatable_size = std::min(this->peak_total_allocatable_size, total_allocatable_size);
|
||||
const size_t total_allocatable_size = free_size + m_cache_handle_table.GetTotalCacheSize();
|
||||
m_peak_total_allocatable_size = std::min(m_peak_total_allocatable_size, total_allocatable_size);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -266,8 +266,8 @@ namespace ams::fssystem {
|
||||
uintptr_t deallocate_address = 0;
|
||||
size_t deallocate_size = 0;
|
||||
|
||||
++this->retried_count;
|
||||
if (this->cache_handle_table.UnregisterOldest(std::addressof(deallocate_address), std::addressof(deallocate_size), attr, size)) {
|
||||
++m_retried_count;
|
||||
if (m_cache_handle_table.UnregisterOldest(std::addressof(deallocate_address), std::addressof(deallocate_size), attr, size)) {
|
||||
this->DeallocateBuffer(deallocate_address, deallocate_size);
|
||||
} else {
|
||||
break;
|
||||
@@ -280,18 +280,18 @@ namespace ams::fssystem {
|
||||
void FileSystemBufferManager::DeallocateBufferImpl(uintptr_t address, size_t size) {
|
||||
AMS_ASSERT(util::IsPowerOfTwo(size));
|
||||
|
||||
std::scoped_lock lk(this->mutex);
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
this->buddy_heap.Free(reinterpret_cast<void *>(address), this->buddy_heap.GetOrderFromBytes(size));
|
||||
m_buddy_heap.Free(reinterpret_cast<void *>(address), m_buddy_heap.GetOrderFromBytes(size));
|
||||
}
|
||||
|
||||
FileSystemBufferManager::CacheHandle FileSystemBufferManager::RegisterCacheImpl(uintptr_t address, size_t size, const BufferAttribute &attr) {
|
||||
std::scoped_lock lk(this->mutex);
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
CacheHandle handle = 0;
|
||||
while (true) {
|
||||
/* Try to register the handle. */
|
||||
if (this->cache_handle_table.Register(std::addressof(handle), address, size, attr)) {
|
||||
if (m_cache_handle_table.Register(std::addressof(handle), address, size, attr)) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -299,12 +299,12 @@ namespace ams::fssystem {
|
||||
uintptr_t deallocate_address = 0;
|
||||
size_t deallocate_size = 0;
|
||||
|
||||
++this->retried_count;
|
||||
if (this->cache_handle_table.UnregisterOldest(std::addressof(deallocate_address), std::addressof(deallocate_size), attr)) {
|
||||
++m_retried_count;
|
||||
if (m_cache_handle_table.UnregisterOldest(std::addressof(deallocate_address), std::addressof(deallocate_size), attr)) {
|
||||
this->DeallocateBuffer(deallocate_address, deallocate_size);
|
||||
} else {
|
||||
this->DeallocateBuffer(address, size);
|
||||
handle = this->cache_handle_table.PublishCacheHandle();
|
||||
handle = m_cache_handle_table.PublishCacheHandle();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -313,12 +313,12 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
const std::pair<uintptr_t, size_t> FileSystemBufferManager::AcquireCacheImpl(CacheHandle handle) {
|
||||
std::scoped_lock lk(this->mutex);
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
std::pair<uintptr_t, size_t> range = {};
|
||||
if (this->cache_handle_table.Unregister(std::addressof(range.first), std::addressof(range.second), handle)) {
|
||||
const size_t total_allocatable_size = this->buddy_heap.GetTotalFreeSize() + this->cache_handle_table.GetTotalCacheSize();
|
||||
this->peak_total_allocatable_size = std::min(this->peak_total_allocatable_size, total_allocatable_size);
|
||||
if (m_cache_handle_table.Unregister(std::addressof(range.first), std::addressof(range.second), handle)) {
|
||||
const size_t total_allocatable_size = m_buddy_heap.GetTotalFreeSize() + m_cache_handle_table.GetTotalCacheSize();
|
||||
m_peak_total_allocatable_size = std::min(m_peak_total_allocatable_size, total_allocatable_size);
|
||||
} else {
|
||||
range.first = 0;
|
||||
range.second = 0;
|
||||
@@ -328,34 +328,34 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
size_t FileSystemBufferManager::GetTotalSizeImpl() const {
|
||||
return this->total_size;
|
||||
return m_total_size;
|
||||
}
|
||||
|
||||
size_t FileSystemBufferManager::GetFreeSizeImpl() const {
|
||||
std::scoped_lock lk(this->mutex);
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
return this->buddy_heap.GetTotalFreeSize();
|
||||
return m_buddy_heap.GetTotalFreeSize();
|
||||
}
|
||||
|
||||
size_t FileSystemBufferManager::GetTotalAllocatableSizeImpl() const {
|
||||
return this->GetFreeSize() + this->cache_handle_table.GetTotalCacheSize();
|
||||
return this->GetFreeSize() + m_cache_handle_table.GetTotalCacheSize();
|
||||
}
|
||||
|
||||
size_t FileSystemBufferManager::GetPeakFreeSizeImpl() const {
|
||||
return this->peak_free_size;
|
||||
return m_peak_free_size;
|
||||
}
|
||||
|
||||
size_t FileSystemBufferManager::GetPeakTotalAllocatableSizeImpl() const {
|
||||
return this->peak_total_allocatable_size;
|
||||
return m_peak_total_allocatable_size;
|
||||
}
|
||||
|
||||
size_t FileSystemBufferManager::GetRetriedCountImpl() const {
|
||||
return this->retried_count;
|
||||
return m_retried_count;
|
||||
}
|
||||
|
||||
void FileSystemBufferManager::ClearPeakImpl() {
|
||||
this->peak_free_size = this->GetFreeSize();
|
||||
this->retried_count = 0;
|
||||
m_peak_free_size = this->GetFreeSize();
|
||||
m_retried_count = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,15 +31,15 @@ namespace ams::fssystem {
|
||||
static constexpr size_t KeySize = AesCtrCounterExtendedStorage::KeySize;
|
||||
static constexpr size_t IvSize = AesCtrCounterExtendedStorage::IvSize;
|
||||
private:
|
||||
AesCtrCounterExtendedStorage::DecryptFunction decrypt_function;
|
||||
s32 key_index;
|
||||
AesCtrCounterExtendedStorage::DecryptFunction m_decrypt_function;
|
||||
s32 m_key_index;
|
||||
public:
|
||||
ExternalDecryptor(AesCtrCounterExtendedStorage::DecryptFunction df, s32 key_idx) : decrypt_function(df), key_index(key_idx) {
|
||||
AMS_ASSERT(this->decrypt_function != nullptr);
|
||||
ExternalDecryptor(AesCtrCounterExtendedStorage::DecryptFunction df, s32 key_idx) : m_decrypt_function(df), m_key_index(key_idx) {
|
||||
AMS_ASSERT(m_decrypt_function != nullptr);
|
||||
}
|
||||
public:
|
||||
virtual void Decrypt(void *buf, size_t buf_size, const void *enc_key, size_t enc_key_size, void *iv, size_t iv_size) override final;
|
||||
virtual bool HasExternalDecryptionKey() const override final { return this->key_index < 0; }
|
||||
virtual bool HasExternalDecryptionKey() const override final { return m_key_index < 0; }
|
||||
};
|
||||
|
||||
}
|
||||
@@ -86,22 +86,22 @@ namespace ams::fssystem {
|
||||
AMS_ASSERT(decryptor != nullptr);
|
||||
|
||||
/* Initialize the bucket tree table. */
|
||||
R_TRY(this->table.Initialize(allocator, node_storage, entry_storage, NodeSize, sizeof(Entry), entry_count));
|
||||
R_TRY(m_table.Initialize(allocator, node_storage, entry_storage, NodeSize, sizeof(Entry), entry_count));
|
||||
|
||||
/* Set members. */
|
||||
this->data_storage = data_storage;
|
||||
std::memcpy(this->key, key, key_size);
|
||||
this->secure_value = secure_value;
|
||||
this->counter_offset = counter_offset;
|
||||
this->decryptor = std::move(decryptor);
|
||||
m_data_storage = data_storage;
|
||||
std::memcpy(m_key, key, key_size);
|
||||
m_secure_value = secure_value;
|
||||
m_counter_offset = counter_offset;
|
||||
m_decryptor = std::move(decryptor);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void AesCtrCounterExtendedStorage::Finalize() {
|
||||
if (this->IsInitialized()) {
|
||||
this->table.Finalize();
|
||||
this->data_storage = fs::SubStorage();
|
||||
m_table.Finalize();
|
||||
m_data_storage = fs::SubStorage();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,21 +117,21 @@ namespace ams::fssystem {
|
||||
R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument());
|
||||
R_UNLESS(util::IsAligned(offset, BlockSize), fs::ResultInvalidOffset());
|
||||
R_UNLESS(util::IsAligned(size, BlockSize), fs::ResultInvalidSize());
|
||||
R_UNLESS(this->table.Includes(offset, size), fs::ResultOutOfRange());
|
||||
R_UNLESS(m_table.Includes(offset, size), fs::ResultOutOfRange());
|
||||
|
||||
/* Read the data. */
|
||||
R_TRY(this->data_storage.Read(offset, buffer, size));
|
||||
R_TRY(m_data_storage.Read(offset, buffer, size));
|
||||
|
||||
/* Temporarily increase our thread priority. */
|
||||
ScopedThreadPriorityChanger cp(+1, ScopedThreadPriorityChanger::Mode::Relative);
|
||||
|
||||
/* Find the offset in our tree. */
|
||||
BucketTree::Visitor visitor;
|
||||
R_TRY(this->table.Find(std::addressof(visitor), offset));
|
||||
R_TRY(m_table.Find(std::addressof(visitor), offset));
|
||||
{
|
||||
const auto entry_offset = visitor.Get<Entry>()->GetOffset();
|
||||
R_UNLESS(util::IsAligned(entry_offset, BlockSize), fs::ResultInvalidAesCtrCounterExtendedEntryOffset());
|
||||
R_UNLESS(0 <= entry_offset && this->table.Includes(entry_offset), fs::ResultInvalidAesCtrCounterExtendedEntryOffset());
|
||||
R_UNLESS(util::IsAligned(entry_offset, BlockSize), fs::ResultInvalidAesCtrCounterExtendedEntryOffset());
|
||||
R_UNLESS(0 <= entry_offset && m_table.Includes(entry_offset), fs::ResultInvalidAesCtrCounterExtendedEntryOffset());
|
||||
}
|
||||
|
||||
/* Prepare to read in chunks. */
|
||||
@@ -152,9 +152,9 @@ namespace ams::fssystem {
|
||||
if (visitor.CanMoveNext()) {
|
||||
R_TRY(visitor.MoveNext());
|
||||
next_entry_offset = visitor.Get<Entry>()->GetOffset();
|
||||
R_UNLESS(this->table.Includes(next_entry_offset), fs::ResultInvalidAesCtrCounterExtendedEntryOffset());
|
||||
R_UNLESS(m_table.Includes(next_entry_offset), fs::ResultInvalidAesCtrCounterExtendedEntryOffset());
|
||||
} else {
|
||||
next_entry_offset = this->table.GetEnd();
|
||||
next_entry_offset = m_table.GetEnd();
|
||||
}
|
||||
R_UNLESS(util::IsAligned(next_entry_offset, BlockSize), fs::ResultInvalidAesCtrCounterExtendedEntryOffset());
|
||||
R_UNLESS(cur_offset < next_entry_offset, fs::ResultInvalidAesCtrCounterExtendedEntryOffset());
|
||||
@@ -170,14 +170,14 @@ namespace ams::fssystem {
|
||||
AMS_ASSERT(cur_size <= size);
|
||||
|
||||
/* Make the CTR for the data we're decrypting. */
|
||||
const auto counter_offset = this->counter_offset + cur_entry_offset + data_offset;
|
||||
NcaAesCtrUpperIv upper_iv = { .part = { .generation = static_cast<u32>(cur_entry.generation), .secure_value = this->secure_value } };
|
||||
const auto counter_offset = m_counter_offset + cur_entry_offset + data_offset;
|
||||
NcaAesCtrUpperIv upper_iv = { .part = { .generation = static_cast<u32>(cur_entry.generation), .secure_value = m_secure_value } };
|
||||
|
||||
u8 iv[IvSize];
|
||||
AesCtrStorage::MakeIv(iv, IvSize, upper_iv.value, counter_offset);
|
||||
|
||||
/* Decrypt. */
|
||||
this->decryptor->Decrypt(cur_data, cur_size, this->key, KeySize, iv, IvSize);
|
||||
m_decryptor->Decrypt(cur_data, cur_size, m_key, KeySize, iv, IvSize);
|
||||
|
||||
/* Advance. */
|
||||
cur_data += cur_size;
|
||||
@@ -201,13 +201,13 @@ namespace ams::fssystem {
|
||||
/* Validate arguments. */
|
||||
R_UNLESS(util::IsAligned(offset, BlockSize), fs::ResultInvalidOffset());
|
||||
R_UNLESS(util::IsAligned(size, BlockSize), fs::ResultInvalidSize());
|
||||
R_UNLESS(this->table.Includes(offset, size), fs::ResultOutOfRange());
|
||||
R_UNLESS(m_table.Includes(offset, size), fs::ResultOutOfRange());
|
||||
|
||||
/* Invalidate our table's cache. */
|
||||
R_TRY(this->table.InvalidateCache());
|
||||
R_TRY(m_table.InvalidateCache());
|
||||
|
||||
/* Operate on our data storage. */
|
||||
R_TRY(this->data_storage.OperateRange(dst, dst_size, op_id, offset, size, src, src_size));
|
||||
R_TRY(m_data_storage.OperateRange(dst, dst_size, op_id, offset, size, src, src_size));
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -230,15 +230,15 @@ namespace ams::fssystem {
|
||||
/* Validate arguments. */
|
||||
R_UNLESS(util::IsAligned(offset, BlockSize), fs::ResultInvalidOffset());
|
||||
R_UNLESS(util::IsAligned(size, BlockSize), fs::ResultInvalidSize());
|
||||
R_UNLESS(this->table.Includes(offset, size), fs::ResultOutOfRange());
|
||||
R_UNLESS(m_table.Includes(offset, size), fs::ResultOutOfRange());
|
||||
|
||||
/* Operate on our data storage. */
|
||||
R_TRY(this->data_storage.OperateRange(dst, dst_size, op_id, offset, size, src, src_size));
|
||||
R_TRY(m_data_storage.OperateRange(dst, dst_size, op_id, offset, size, src, src_size));
|
||||
|
||||
/* Add in new flags. */
|
||||
fs::QueryRangeInfo new_info;
|
||||
new_info.Clear();
|
||||
new_info.aes_ctr_key_type = static_cast<s32>(this->decryptor->HasExternalDecryptionKey() ? fs::AesCtrKeyTypeFlag::ExternalKeyForHardwareAes : fs::AesCtrKeyTypeFlag::InternalKeyForHardwareAes);
|
||||
new_info.aes_ctr_key_type = static_cast<s32>(m_decryptor->HasExternalDecryptionKey() ? fs::AesCtrKeyTypeFlag::ExternalKeyForHardwareAes : fs::AesCtrKeyTypeFlag::InternalKeyForHardwareAes);
|
||||
|
||||
/* Merge in the new info. */
|
||||
reinterpret_cast<fs::QueryRangeInfo *>(dst)->Merge(new_info);
|
||||
@@ -281,7 +281,7 @@ namespace ams::fssystem {
|
||||
size_t cur_size = std::min(pooled_buffer.GetSize(), remaining_size);
|
||||
u8 *dst = static_cast<u8 *>(buf) + cur_offset;
|
||||
|
||||
this->decrypt_function(pooled_buffer.GetBuffer(), cur_size, this->key_index, enc_key, enc_key_size, ctr, IvSize, dst, cur_size);
|
||||
m_decrypt_function(pooled_buffer.GetBuffer(), cur_size, m_key_index, enc_key, enc_key_size, ctr, IvSize, dst, cur_size);
|
||||
|
||||
std::memcpy(dst, pooled_buffer.GetBuffer(), cur_size);
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace ams::fssystem {
|
||||
util::StoreBigEndian(reinterpret_cast<s64 *>(out_addr + sizeof(u64)), static_cast<s64>(offset / BlockSize));
|
||||
}
|
||||
|
||||
AesCtrStorage::AesCtrStorage(IStorage *base, const void *key, size_t key_size, const void *iv, size_t iv_size) : base_storage(base) {
|
||||
AesCtrStorage::AesCtrStorage(IStorage *base, const void *key, size_t key_size, const void *iv, size_t iv_size) : m_base_storage(base) {
|
||||
AMS_ASSERT(base != nullptr);
|
||||
AMS_ASSERT(key != nullptr);
|
||||
AMS_ASSERT(iv != nullptr);
|
||||
@@ -38,8 +38,8 @@ namespace ams::fssystem {
|
||||
AMS_ASSERT(iv_size == IvSize);
|
||||
AMS_UNUSED(key_size, iv_size);
|
||||
|
||||
std::memcpy(this->key, key, KeySize);
|
||||
std::memcpy(this->iv, iv, IvSize);
|
||||
std::memcpy(m_key, key, KeySize);
|
||||
std::memcpy(m_iv, iv, IvSize);
|
||||
}
|
||||
|
||||
Result AesCtrStorage::Read(s64 offset, void *buffer, size_t size) {
|
||||
@@ -54,18 +54,18 @@ namespace ams::fssystem {
|
||||
R_UNLESS(util::IsAligned(size, BlockSize), fs::ResultInvalidArgument());
|
||||
|
||||
/* Read the data. */
|
||||
R_TRY(this->base_storage->Read(offset, buffer, size));
|
||||
R_TRY(m_base_storage->Read(offset, buffer, size));
|
||||
|
||||
/* Prepare to decrypt the data, with temporarily increased priority. */
|
||||
ScopedThreadPriorityChanger cp(+1, ScopedThreadPriorityChanger::Mode::Relative);
|
||||
|
||||
/* Setup the counter. */
|
||||
char ctr[IvSize];
|
||||
std::memcpy(ctr, this->iv, IvSize);
|
||||
std::memcpy(ctr, m_iv, IvSize);
|
||||
AddCounter(ctr, IvSize, offset / BlockSize);
|
||||
|
||||
/* Decrypt, ensure we decrypt correctly. */
|
||||
auto dec_size = crypto::DecryptAes128Ctr(buffer, size, this->key, KeySize, ctr, IvSize, buffer, size);
|
||||
auto dec_size = crypto::DecryptAes128Ctr(buffer, size, m_key, KeySize, ctr, IvSize, buffer, size);
|
||||
R_UNLESS(size == dec_size, fs::ResultUnexpectedInAesCtrStorageA());
|
||||
|
||||
return ResultSuccess();
|
||||
@@ -91,7 +91,7 @@ namespace ams::fssystem {
|
||||
|
||||
/* Setup the counter. */
|
||||
char ctr[IvSize];
|
||||
std::memcpy(ctr, this->iv, IvSize);
|
||||
std::memcpy(ctr, m_iv, IvSize);
|
||||
AddCounter(ctr, IvSize, offset / BlockSize);
|
||||
|
||||
/* Loop until all data is written. */
|
||||
@@ -106,12 +106,12 @@ namespace ams::fssystem {
|
||||
{
|
||||
ScopedThreadPriorityChanger cp(+1, ScopedThreadPriorityChanger::Mode::Relative);
|
||||
|
||||
auto enc_size = crypto::EncryptAes128Ctr(write_buf, write_size, this->key, KeySize, ctr, IvSize, reinterpret_cast<const char *>(buffer) + cur_offset, write_size);
|
||||
auto enc_size = crypto::EncryptAes128Ctr(write_buf, write_size, m_key, KeySize, ctr, IvSize, reinterpret_cast<const char *>(buffer) + cur_offset, write_size);
|
||||
R_UNLESS(enc_size == write_size, fs::ResultUnexpectedInAesCtrStorageA());
|
||||
}
|
||||
|
||||
/* Write the encrypted data. */
|
||||
R_TRY(this->base_storage->Write(offset + cur_offset, write_buf, write_size));
|
||||
R_TRY(m_base_storage->Write(offset + cur_offset, write_buf, write_size));
|
||||
|
||||
/* Advance. */
|
||||
cur_offset += write_size;
|
||||
@@ -125,7 +125,7 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
Result AesCtrStorage::Flush() {
|
||||
return this->base_storage->Flush();
|
||||
return m_base_storage->Flush();
|
||||
}
|
||||
|
||||
Result AesCtrStorage::SetSize(s64 size) {
|
||||
@@ -134,7 +134,7 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
Result AesCtrStorage::GetSize(s64 *out) {
|
||||
return this->base_storage->GetSize(out);
|
||||
return m_base_storage->GetSize(out);
|
||||
}
|
||||
|
||||
Result AesCtrStorage::OperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) {
|
||||
@@ -160,7 +160,7 @@ namespace ams::fssystem {
|
||||
R_UNLESS(dst != nullptr, fs::ResultNullptrArgument());
|
||||
R_UNLESS(dst_size == sizeof(fs::QueryRangeInfo), fs::ResultInvalidSize());
|
||||
|
||||
R_TRY(this->base_storage->OperateRange(dst, dst_size, op_id, offset, size, src, src_size));
|
||||
R_TRY(m_base_storage->OperateRange(dst, dst_size, op_id, offset, size, src, src_size));
|
||||
|
||||
fs::QueryRangeInfo info;
|
||||
info.Clear();
|
||||
@@ -171,7 +171,7 @@ namespace ams::fssystem {
|
||||
break;
|
||||
default:
|
||||
{
|
||||
R_TRY(this->base_storage->OperateRange(dst, dst_size, op_id, offset, size, src, src_size));
|
||||
R_TRY(m_base_storage->OperateRange(dst, dst_size, op_id, offset, size, src, src_size));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -17,19 +17,19 @@
|
||||
|
||||
namespace ams::fssystem {
|
||||
|
||||
AesXtsStorage::AesXtsStorage(IStorage *base, const void *key1, const void *key2, size_t key_size, const void *iv, size_t iv_size, size_t block_size) : base_storage(base), block_size(block_size), mutex() {
|
||||
AesXtsStorage::AesXtsStorage(IStorage *base, const void *key1, const void *key2, size_t key_size, const void *iv, size_t iv_size, size_t block_size) : m_base_storage(base), m_block_size(block_size), m_mutex() {
|
||||
AMS_ASSERT(base != nullptr);
|
||||
AMS_ASSERT(key1 != nullptr);
|
||||
AMS_ASSERT(key2 != nullptr);
|
||||
AMS_ASSERT(iv != nullptr);
|
||||
AMS_ASSERT(key_size == KeySize);
|
||||
AMS_ASSERT(iv_size == IvSize);
|
||||
AMS_ASSERT(util::IsAligned(this->block_size, AesBlockSize));
|
||||
AMS_ASSERT(util::IsAligned(m_block_size, AesBlockSize));
|
||||
AMS_UNUSED(key_size, iv_size);
|
||||
|
||||
std::memcpy(this->key[0], key1, KeySize);
|
||||
std::memcpy(this->key[1], key2, KeySize);
|
||||
std::memcpy(this->iv, iv, IvSize);
|
||||
std::memcpy(m_key[0], key1, KeySize);
|
||||
std::memcpy(m_key[1], key2, KeySize);
|
||||
std::memcpy(m_iv, iv, IvSize);
|
||||
}
|
||||
|
||||
Result AesXtsStorage::Read(s64 offset, void *buffer, size_t size) {
|
||||
@@ -44,48 +44,48 @@ namespace ams::fssystem {
|
||||
R_UNLESS(util::IsAligned(size, AesBlockSize), fs::ResultInvalidArgument());
|
||||
|
||||
/* Read the data. */
|
||||
R_TRY(this->base_storage->Read(offset, buffer, size));
|
||||
R_TRY(m_base_storage->Read(offset, buffer, size));
|
||||
|
||||
/* Prepare to decrypt the data, with temporarily increased priority. */
|
||||
ScopedThreadPriorityChanger cp(+1, ScopedThreadPriorityChanger::Mode::Relative);
|
||||
|
||||
/* Setup the counter. */
|
||||
char ctr[IvSize];
|
||||
std::memcpy(ctr, this->iv, IvSize);
|
||||
AddCounter(ctr, IvSize, offset / this->block_size);
|
||||
std::memcpy(ctr, m_iv, IvSize);
|
||||
AddCounter(ctr, IvSize, offset / m_block_size);
|
||||
|
||||
/* Handle any unaligned data before the start. */
|
||||
size_t processed_size = 0;
|
||||
if ((offset % this->block_size) != 0) {
|
||||
if ((offset % m_block_size) != 0) {
|
||||
/* Determine the size of the pre-data read. */
|
||||
const size_t skip_size = static_cast<size_t>(offset - util::AlignDown(offset, this->block_size));
|
||||
const size_t data_size = std::min(size, this->block_size - skip_size);
|
||||
const size_t skip_size = static_cast<size_t>(offset - util::AlignDown(offset, m_block_size));
|
||||
const size_t data_size = std::min(size, m_block_size - skip_size);
|
||||
|
||||
/* Decrypt into a pooled buffer. */
|
||||
{
|
||||
PooledBuffer tmp_buf(this->block_size, this->block_size);
|
||||
AMS_ASSERT(tmp_buf.GetSize() >= this->block_size);
|
||||
PooledBuffer tmp_buf(m_block_size, m_block_size);
|
||||
AMS_ASSERT(tmp_buf.GetSize() >= m_block_size);
|
||||
|
||||
std::memset(tmp_buf.GetBuffer(), 0, skip_size);
|
||||
std::memcpy(tmp_buf.GetBuffer() + skip_size, buffer, data_size);
|
||||
|
||||
const size_t dec_size = crypto::DecryptAes128Xts(tmp_buf.GetBuffer(), this->block_size, this->key[0], this->key[1], KeySize, ctr, IvSize, tmp_buf.GetBuffer(), this->block_size);
|
||||
R_UNLESS(dec_size == this->block_size, fs::ResultUnexpectedInAesXtsStorageA());
|
||||
const size_t dec_size = crypto::DecryptAes128Xts(tmp_buf.GetBuffer(), m_block_size, m_key[0], m_key[1], KeySize, ctr, IvSize, tmp_buf.GetBuffer(), m_block_size);
|
||||
R_UNLESS(dec_size == m_block_size, fs::ResultUnexpectedInAesXtsStorageA());
|
||||
|
||||
std::memcpy(buffer, tmp_buf.GetBuffer() + skip_size, data_size);
|
||||
}
|
||||
|
||||
AddCounter(ctr, IvSize, 1);
|
||||
processed_size += data_size;
|
||||
AMS_ASSERT(processed_size == std::min(size, this->block_size - skip_size));
|
||||
AMS_ASSERT(processed_size == std::min(size, m_block_size - skip_size));
|
||||
}
|
||||
|
||||
/* Decrypt aligned chunks. */
|
||||
char *cur = static_cast<char *>(buffer) + processed_size;
|
||||
size_t remaining = size - processed_size;
|
||||
while (remaining > 0) {
|
||||
const size_t cur_size = std::min(this->block_size, remaining);
|
||||
const size_t dec_size = crypto::DecryptAes128Xts(cur, cur_size, this->key[0], this->key[1], KeySize, ctr, IvSize, cur, cur_size);
|
||||
const size_t cur_size = std::min(m_block_size, remaining);
|
||||
const size_t dec_size = crypto::DecryptAes128Xts(cur, cur_size, m_key[0], m_key[1], KeySize, ctr, IvSize, cur, cur_size);
|
||||
R_UNLESS(cur_size == dec_size, fs::ResultUnexpectedInAesXtsStorageA());
|
||||
|
||||
remaining -= cur_size;
|
||||
@@ -112,45 +112,45 @@ namespace ams::fssystem {
|
||||
PooledBuffer pooled_buffer;
|
||||
const bool use_work_buffer = !IsDeviceAddress(buffer);
|
||||
if (use_work_buffer) {
|
||||
pooled_buffer.Allocate(size, this->block_size);
|
||||
pooled_buffer.Allocate(size, m_block_size);
|
||||
}
|
||||
|
||||
/* Setup the counter. */
|
||||
char ctr[IvSize];
|
||||
std::memcpy(ctr, this->iv, IvSize);
|
||||
AddCounter(ctr, IvSize, offset / this->block_size);
|
||||
std::memcpy(ctr, m_iv, IvSize);
|
||||
AddCounter(ctr, IvSize, offset / m_block_size);
|
||||
|
||||
/* Handle any unaligned data before the start. */
|
||||
size_t processed_size = 0;
|
||||
if ((offset % this->block_size) != 0) {
|
||||
if ((offset % m_block_size) != 0) {
|
||||
/* Determine the size of the pre-data read. */
|
||||
const size_t skip_size = static_cast<size_t>(offset - util::AlignDown(offset, this->block_size));
|
||||
const size_t data_size = std::min(size, this->block_size - skip_size);
|
||||
const size_t skip_size = static_cast<size_t>(offset - util::AlignDown(offset, m_block_size));
|
||||
const size_t data_size = std::min(size, m_block_size - skip_size);
|
||||
|
||||
/* Create an encryptor. */
|
||||
/* NOTE: This is completely unnecessary, because crypto::EncryptAes128Xts is used below. */
|
||||
/* However, Nintendo does it, so we will too. */
|
||||
crypto::Aes128XtsEncryptor xts;
|
||||
xts.Initialize(this->key[0], this->key[1], KeySize, ctr, IvSize);
|
||||
xts.Initialize(m_key[0], m_key[1], KeySize, ctr, IvSize);
|
||||
|
||||
/* Encrypt into a pooled buffer. */
|
||||
{
|
||||
/* NOTE: Nintendo allocates a second pooled buffer here despite having one already allocated above. */
|
||||
PooledBuffer tmp_buf(this->block_size, this->block_size);
|
||||
AMS_ASSERT(tmp_buf.GetSize() >= this->block_size);
|
||||
PooledBuffer tmp_buf(m_block_size, m_block_size);
|
||||
AMS_ASSERT(tmp_buf.GetSize() >= m_block_size);
|
||||
|
||||
std::memset(tmp_buf.GetBuffer(), 0, skip_size);
|
||||
std::memcpy(tmp_buf.GetBuffer() + skip_size, buffer, data_size);
|
||||
|
||||
const size_t enc_size = crypto::EncryptAes128Xts(tmp_buf.GetBuffer(), this->block_size, this->key[0], this->key[1], KeySize, ctr, IvSize, tmp_buf.GetBuffer(), this->block_size);
|
||||
R_UNLESS(enc_size == this->block_size, fs::ResultUnexpectedInAesXtsStorageA());
|
||||
const size_t enc_size = crypto::EncryptAes128Xts(tmp_buf.GetBuffer(), m_block_size, m_key[0], m_key[1], KeySize, ctr, IvSize, tmp_buf.GetBuffer(), m_block_size);
|
||||
R_UNLESS(enc_size == m_block_size, fs::ResultUnexpectedInAesXtsStorageA());
|
||||
|
||||
R_TRY(this->base_storage->Write(offset, tmp_buf.GetBuffer() + skip_size, data_size));
|
||||
R_TRY(m_base_storage->Write(offset, tmp_buf.GetBuffer() + skip_size, data_size));
|
||||
}
|
||||
|
||||
AddCounter(ctr, IvSize, 1);
|
||||
processed_size += data_size;
|
||||
AMS_ASSERT(processed_size == std::min(size, this->block_size - skip_size));
|
||||
AMS_ASSERT(processed_size == std::min(size, m_block_size - skip_size));
|
||||
}
|
||||
|
||||
/* Encrypt aligned chunks. */
|
||||
@@ -167,11 +167,11 @@ namespace ams::fssystem {
|
||||
size_t remaining_write = write_size;
|
||||
size_t encrypt_offset = 0;
|
||||
while (remaining_write > 0) {
|
||||
const size_t cur_size = std::min(remaining_write, this->block_size);
|
||||
const size_t cur_size = std::min(remaining_write, m_block_size);
|
||||
const void *src = static_cast<const char *>(buffer) + processed_size + encrypt_offset;
|
||||
void *dst = use_work_buffer ? pooled_buffer.GetBuffer() + encrypt_offset : const_cast<void *>(src);
|
||||
|
||||
const size_t enc_size = crypto::EncryptAes128Xts(dst, cur_size, this->key[0], this->key[1], KeySize, ctr, IvSize, src, cur_size);
|
||||
const size_t enc_size = crypto::EncryptAes128Xts(dst, cur_size, m_key[0], m_key[1], KeySize, ctr, IvSize, src, cur_size);
|
||||
R_UNLESS(enc_size == cur_size, fs::ResultUnexpectedInAesXtsStorageA());
|
||||
|
||||
AddCounter(ctr, IvSize, 1);
|
||||
@@ -183,7 +183,7 @@ namespace ams::fssystem {
|
||||
|
||||
/* Write the encrypted data. */
|
||||
const void *write_buf = use_work_buffer ? pooled_buffer.GetBuffer() : static_cast<const char *>(buffer) + processed_size;
|
||||
R_TRY(this->base_storage->Write(cur_offset, write_buf, write_size));
|
||||
R_TRY(m_base_storage->Write(cur_offset, write_buf, write_size));
|
||||
|
||||
/* Advance. */
|
||||
cur_offset += write_size;
|
||||
@@ -195,17 +195,17 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
Result AesXtsStorage::Flush() {
|
||||
return this->base_storage->Flush();
|
||||
return m_base_storage->Flush();
|
||||
}
|
||||
|
||||
Result AesXtsStorage::SetSize(s64 size) {
|
||||
R_UNLESS(util::IsAligned(size, AesBlockSize), fs::ResultUnexpectedInAesXtsStorageA());
|
||||
|
||||
return this->base_storage->SetSize(size);
|
||||
return m_base_storage->SetSize(size);
|
||||
}
|
||||
|
||||
Result AesXtsStorage::GetSize(s64 *out) {
|
||||
return this->base_storage->GetSize(out);
|
||||
return m_base_storage->GetSize(out);
|
||||
}
|
||||
|
||||
Result AesXtsStorage::OperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) {
|
||||
@@ -216,7 +216,7 @@ namespace ams::fssystem {
|
||||
R_UNLESS(util::IsAligned(offset, AesBlockSize), fs::ResultInvalidArgument());
|
||||
R_UNLESS(util::IsAligned(size, AesBlockSize), fs::ResultInvalidArgument());
|
||||
|
||||
return this->base_storage->OperateRange(dst, dst_size, op_id, offset, size, src, src_size);
|
||||
return m_base_storage->OperateRange(dst, dst_size, op_id, offset, size, src, src_size);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -203,39 +203,39 @@ namespace ams::fssystem {
|
||||
|
||||
/* Determine extents. */
|
||||
const auto offset_end = offset + static_cast<s64>(size);
|
||||
const auto aligned_offset = util::AlignDown(offset, this->data_align);
|
||||
const auto aligned_offset_end = util::AlignUp(offset_end, this->data_align);
|
||||
const auto aligned_offset = util::AlignDown(offset, m_data_align);
|
||||
const auto aligned_offset_end = util::AlignUp(offset_end, m_data_align);
|
||||
const auto aligned_size = static_cast<size_t>(aligned_offset_end - aligned_offset);
|
||||
|
||||
/* If we aren't aligned, we need to allocate a buffer. */
|
||||
PooledBuffer pooled_buffer;
|
||||
if (aligned_offset != offset || aligned_size != size) {
|
||||
if (aligned_size <= pooled_buffer.GetAllocatableSizeMax()) {
|
||||
pooled_buffer.Allocate(aligned_size, this->data_align);
|
||||
pooled_buffer.Allocate(aligned_size, m_data_align);
|
||||
|
||||
if (aligned_size <= pooled_buffer.GetSize()) {
|
||||
R_TRY(this->base_storage->Read(aligned_offset, pooled_buffer.GetBuffer(), aligned_size));
|
||||
R_TRY(m_base_storage->Read(aligned_offset, pooled_buffer.GetBuffer(), aligned_size));
|
||||
std::memcpy(buffer, pooled_buffer.GetBuffer() + (offset - aligned_offset), size);
|
||||
return ResultSuccess();
|
||||
} else {
|
||||
pooled_buffer.Shrink(this->data_align);
|
||||
pooled_buffer.Shrink(m_data_align);
|
||||
}
|
||||
} else {
|
||||
pooled_buffer.Allocate(this->data_align, this->data_align);
|
||||
pooled_buffer.Allocate(m_data_align, m_data_align);
|
||||
}
|
||||
|
||||
AMS_ASSERT(pooled_buffer.GetSize() >= static_cast<size_t>(this->data_align));
|
||||
AMS_ASSERT(pooled_buffer.GetSize() >= static_cast<size_t>(m_data_align));
|
||||
}
|
||||
|
||||
/* Determine read extents for the aligned portion. */
|
||||
const auto core_offset = util::AlignUp(offset, this->data_align);
|
||||
const auto core_offset_end = util::AlignDown(offset_end, this->data_align);
|
||||
const auto core_offset = util::AlignUp(offset, m_data_align);
|
||||
const auto core_offset_end = util::AlignDown(offset_end, m_data_align);
|
||||
|
||||
/* Handle any data before the aligned portion. */
|
||||
if (offset < core_offset) {
|
||||
const auto head_size = static_cast<size_t>(core_offset - offset);
|
||||
AMS_ASSERT(head_size < size);
|
||||
R_TRY(this->base_storage->Read(aligned_offset, pooled_buffer.GetBuffer(), this->data_align));
|
||||
R_TRY(m_base_storage->Read(aligned_offset, pooled_buffer.GetBuffer(), m_data_align));
|
||||
std::memcpy(buffer, pooled_buffer.GetBuffer() + (offset - aligned_offset), head_size);
|
||||
}
|
||||
|
||||
@@ -244,13 +244,13 @@ namespace ams::fssystem {
|
||||
const auto core_buffer = static_cast<char *>(buffer) + (core_offset - offset);
|
||||
const auto core_size = static_cast<size_t>(core_offset_end - core_offset);
|
||||
|
||||
R_TRY(this->base_storage->Read(core_offset, core_buffer, core_size));
|
||||
R_TRY(m_base_storage->Read(core_offset, core_buffer, core_size));
|
||||
}
|
||||
|
||||
/* Handle any data after the aligned portion. */
|
||||
if (core_offset_end < offset_end) {
|
||||
const auto tail_size = static_cast<size_t>(offset_end - core_offset_end);
|
||||
R_TRY(this->base_storage->Read(core_offset_end, pooled_buffer.GetBuffer(), this->data_align));
|
||||
R_TRY(m_base_storage->Read(core_offset_end, pooled_buffer.GetBuffer(), m_data_align));
|
||||
std::memcpy(buffer, pooled_buffer.GetBuffer(), tail_size);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,43 +31,43 @@ namespace ams::fssystem {
|
||||
public:
|
||||
using difference_type = s64;
|
||||
private:
|
||||
s64 offset;
|
||||
s32 stride;
|
||||
s64 m_offset;
|
||||
s32 m_stride;
|
||||
public:
|
||||
constexpr Offset(s64 offset, s32 stride) : offset(offset), stride(stride) { /* ... */ }
|
||||
constexpr Offset(s64 offset, s32 stride) : m_offset(offset), m_stride(stride) { /* ... */ }
|
||||
|
||||
constexpr Offset &operator++() { this->offset += this->stride; return *this; }
|
||||
constexpr Offset operator++(int) { Offset ret(*this); this->offset += this->stride; return ret; }
|
||||
constexpr Offset &operator++() { m_offset += m_stride; return *this; }
|
||||
constexpr Offset operator++(int) { Offset ret(*this); m_offset += m_stride; return ret; }
|
||||
|
||||
constexpr Offset &operator--() { this->offset -= this->stride; return *this; }
|
||||
constexpr Offset operator--(int) { Offset ret(*this); this->offset -= this->stride; return ret; }
|
||||
constexpr Offset &operator--() { m_offset -= m_stride; return *this; }
|
||||
constexpr Offset operator--(int) { Offset ret(*this); m_offset -= m_stride; return ret; }
|
||||
|
||||
constexpr difference_type operator-(const Offset &rhs) const { return (this->offset - rhs.offset) / this->stride; }
|
||||
constexpr difference_type operator-(const Offset &rhs) const { return (m_offset - rhs.m_offset) / m_stride; }
|
||||
|
||||
constexpr Offset operator+(difference_type ofs) const { return Offset(this->offset + ofs * this->stride, this->stride); }
|
||||
constexpr Offset operator-(difference_type ofs) const { return Offset(this->offset - ofs * this->stride, this->stride); }
|
||||
constexpr Offset operator+(difference_type ofs) const { return Offset(m_offset + ofs * m_stride, m_stride); }
|
||||
constexpr Offset operator-(difference_type ofs) const { return Offset(m_offset - ofs * m_stride, m_stride); }
|
||||
|
||||
constexpr Offset &operator+=(difference_type ofs) { this->offset += ofs * this->stride; return *this; }
|
||||
constexpr Offset &operator-=(difference_type ofs) { this->offset -= ofs * this->stride; return *this; }
|
||||
constexpr Offset &operator+=(difference_type ofs) { m_offset += ofs * m_stride; return *this; }
|
||||
constexpr Offset &operator-=(difference_type ofs) { m_offset -= ofs * m_stride; return *this; }
|
||||
|
||||
constexpr bool operator==(const Offset &rhs) const { return this->offset == rhs.offset; }
|
||||
constexpr bool operator!=(const Offset &rhs) const { return this->offset != rhs.offset; }
|
||||
constexpr bool operator==(const Offset &rhs) const { return m_offset == rhs.m_offset; }
|
||||
constexpr bool operator!=(const Offset &rhs) const { return m_offset != rhs.m_offset; }
|
||||
|
||||
constexpr s64 Get() const { return this->offset; }
|
||||
constexpr s64 Get() const { return m_offset; }
|
||||
};
|
||||
private:
|
||||
const Offset start;
|
||||
const s32 count;
|
||||
s32 index;
|
||||
const Offset m_start;
|
||||
const s32 m_count;
|
||||
s32 m_index;
|
||||
public:
|
||||
StorageNode(size_t size, s32 count) : start(NodeHeaderSize, static_cast<s32>(size)), count(count), index(-1) { /* ... */ }
|
||||
StorageNode(s64 ofs, size_t size, s32 count) : start(NodeHeaderSize + ofs, static_cast<s32>(size)), count(count), index(-1) { /* ... */ }
|
||||
StorageNode(size_t size, s32 count) : m_start(NodeHeaderSize, static_cast<s32>(size)), m_count(count), m_index(-1) { /* ... */ }
|
||||
StorageNode(s64 ofs, size_t size, s32 count) : m_start(NodeHeaderSize + ofs, static_cast<s32>(size)), m_count(count), m_index(-1) { /* ... */ }
|
||||
|
||||
s32 GetIndex() const { return this->index; }
|
||||
s32 GetIndex() const { return m_index; }
|
||||
|
||||
void Find(const char *buffer, s64 virtual_address) {
|
||||
s32 end = this->count;
|
||||
auto pos = this->start;
|
||||
s32 end = m_count;
|
||||
auto pos = m_start;
|
||||
|
||||
while (end > 0) {
|
||||
auto half = end / 2;
|
||||
@@ -84,12 +84,12 @@ namespace ams::fssystem {
|
||||
}
|
||||
}
|
||||
|
||||
this->index = static_cast<s32>(pos - this->start) - 1;
|
||||
m_index = static_cast<s32>(pos - m_start) - 1;
|
||||
}
|
||||
|
||||
Result Find(fs::SubStorage &storage, s64 virtual_address) {
|
||||
s32 end = this->count;
|
||||
auto pos = this->start;
|
||||
s32 end = m_count;
|
||||
auto pos = m_start;
|
||||
|
||||
while (end > 0) {
|
||||
auto half = end / 2;
|
||||
@@ -106,7 +106,7 @@ namespace ams::fssystem {
|
||||
}
|
||||
}
|
||||
|
||||
this->index = static_cast<s32>(pos - this->start) - 1;
|
||||
m_index = static_cast<s32>(pos - m_start) - 1;
|
||||
return ResultSuccess();
|
||||
}
|
||||
};
|
||||
@@ -153,19 +153,19 @@ namespace ams::fssystem {
|
||||
R_UNLESS(entry_count > 0, fs::ResultInvalidArgument());
|
||||
|
||||
/* Allocate node. */
|
||||
R_UNLESS(this->node_l1.Allocate(allocator, node_size), fs::ResultBufferAllocationFailed());
|
||||
auto node_guard = SCOPE_GUARD { this->node_l1.Free(node_size); };
|
||||
R_UNLESS(m_node_l1.Allocate(allocator, node_size), fs::ResultBufferAllocationFailed());
|
||||
auto node_guard = SCOPE_GUARD { m_node_l1.Free(node_size); };
|
||||
|
||||
/* Read node. */
|
||||
R_TRY(node_storage.Read(0, this->node_l1.Get(), node_size));
|
||||
R_TRY(node_storage.Read(0, m_node_l1.Get(), node_size));
|
||||
|
||||
/* Verify node. */
|
||||
R_TRY(this->node_l1->Verify(0, node_size, sizeof(s64)));
|
||||
R_TRY(m_node_l1->Verify(0, node_size, sizeof(s64)));
|
||||
|
||||
/* Validate offsets. */
|
||||
const auto offset_count = GetOffsetCount(node_size);
|
||||
const auto entry_set_count = GetEntrySetCount(node_size, entry_size, entry_count);
|
||||
const auto * const node = this->node_l1.Get<Node>();
|
||||
const auto * const node = m_node_l1.Get<Node>();
|
||||
|
||||
s64 start_offset;
|
||||
if (offset_count < entry_set_count && node->GetCount() < offset_count) {
|
||||
@@ -179,15 +179,15 @@ namespace ams::fssystem {
|
||||
R_UNLESS(start_offset < end_offset, fs::ResultInvalidBucketTreeEntryOffset());
|
||||
|
||||
/* Set member variables. */
|
||||
this->node_storage = node_storage;
|
||||
this->entry_storage = entry_storage;
|
||||
this->node_size = node_size;
|
||||
this->entry_size = entry_size;
|
||||
this->entry_count = entry_count;
|
||||
this->offset_count = offset_count;
|
||||
this->entry_set_count = entry_set_count;
|
||||
this->start_offset = start_offset;
|
||||
this->end_offset = end_offset;
|
||||
m_node_storage = node_storage;
|
||||
m_entry_storage = entry_storage;
|
||||
m_node_size = node_size;
|
||||
m_entry_size = entry_size;
|
||||
m_entry_count = entry_count;
|
||||
m_offset_count = offset_count;
|
||||
m_entry_set_count = entry_set_count;
|
||||
m_start_offset = start_offset;
|
||||
m_end_offset = end_offset;
|
||||
|
||||
/* Cancel guard. */
|
||||
node_guard.Cancel();
|
||||
@@ -200,22 +200,22 @@ namespace ams::fssystem {
|
||||
AMS_ASSERT(end_offset > 0);
|
||||
AMS_ASSERT(!this->IsInitialized());
|
||||
|
||||
this->node_size = node_size;
|
||||
this->end_offset = end_offset;
|
||||
m_node_size = node_size;
|
||||
m_end_offset = end_offset;
|
||||
}
|
||||
|
||||
void BucketTree::Finalize() {
|
||||
if (this->IsInitialized()) {
|
||||
this->node_storage = fs::SubStorage();
|
||||
this->entry_storage = fs::SubStorage();
|
||||
this->node_l1.Free(this->node_size);
|
||||
this->node_size = 0;
|
||||
this->entry_size = 0;
|
||||
this->entry_count = 0;
|
||||
this->offset_count = 0;
|
||||
this->entry_set_count = 0;
|
||||
this->start_offset = 0;
|
||||
this->end_offset = 0;
|
||||
m_node_storage = fs::SubStorage();
|
||||
m_entry_storage = fs::SubStorage();
|
||||
m_node_l1.Free(m_node_size);
|
||||
m_node_size = 0;
|
||||
m_entry_size = 0;
|
||||
m_entry_count = 0;
|
||||
m_offset_count = 0;
|
||||
m_entry_set_count = 0;
|
||||
m_start_offset = 0;
|
||||
m_end_offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,23 +235,23 @@ namespace ams::fssystem {
|
||||
/* Invalidate the node storage cache. */
|
||||
{
|
||||
s64 storage_size;
|
||||
R_TRY(this->node_storage.GetSize(std::addressof(storage_size)));
|
||||
R_TRY(this->node_storage.OperateRange(fs::OperationId::Invalidate, 0, storage_size));
|
||||
R_TRY(m_node_storage.GetSize(std::addressof(storage_size)));
|
||||
R_TRY(m_node_storage.OperateRange(fs::OperationId::Invalidate, 0, storage_size));
|
||||
}
|
||||
|
||||
/* Refresh start/end offsets. */
|
||||
{
|
||||
/* Read node. */
|
||||
R_TRY(node_storage.Read(0, this->node_l1.Get(), this->node_size));
|
||||
R_TRY(m_node_storage.Read(0, m_node_l1.Get(), m_node_size));
|
||||
|
||||
/* Verify node. */
|
||||
R_TRY(this->node_l1->Verify(0, this->node_size, sizeof(s64)));
|
||||
R_TRY(m_node_l1->Verify(0, m_node_size, sizeof(s64)));
|
||||
|
||||
/* Validate offsets. */
|
||||
const auto * const node = this->node_l1.Get<Node>();
|
||||
const auto * const node = m_node_l1.Get<Node>();
|
||||
|
||||
s64 start_offset;
|
||||
if (offset_count < this->entry_set_count && node->GetCount() < this->offset_count) {
|
||||
if (m_offset_count < m_entry_set_count && node->GetCount() < m_offset_count) {
|
||||
start_offset = *node->GetEnd();
|
||||
} else {
|
||||
start_offset = *node->GetBegin();
|
||||
@@ -262,15 +262,15 @@ namespace ams::fssystem {
|
||||
R_UNLESS(start_offset < end_offset, fs::ResultInvalidBucketTreeEntryOffset());
|
||||
|
||||
/* Set refreshed offsets. */
|
||||
this->start_offset = start_offset;
|
||||
this->end_offset = end_offset;
|
||||
m_start_offset = start_offset;
|
||||
m_end_offset = end_offset;
|
||||
}
|
||||
|
||||
/* Invalidate the entry storage cache. */
|
||||
{
|
||||
s64 storage_size;
|
||||
R_TRY(this->entry_storage.GetSize(std::addressof(storage_size)));
|
||||
R_TRY(this->entry_storage.OperateRange(fs::OperationId::Invalidate, 0, storage_size));
|
||||
R_TRY(m_entry_storage.GetSize(std::addressof(storage_size)));
|
||||
R_TRY(m_entry_storage.OperateRange(fs::OperationId::Invalidate, 0, storage_size));
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
@@ -278,13 +278,13 @@ namespace ams::fssystem {
|
||||
|
||||
Result BucketTree::Visitor::Initialize(const BucketTree *tree) {
|
||||
AMS_ASSERT(tree != nullptr);
|
||||
AMS_ASSERT(this->tree == nullptr || this->tree == tree);
|
||||
AMS_ASSERT(m_tree == nullptr || m_tree == tree);
|
||||
|
||||
if (this->entry == nullptr) {
|
||||
this->entry = tree->GetAllocator()->Allocate(tree->entry_size);
|
||||
R_UNLESS(this->entry != nullptr, fs::ResultBufferAllocationFailed());
|
||||
if (m_entry == nullptr) {
|
||||
m_entry = tree->GetAllocator()->Allocate(tree->m_entry_size);
|
||||
R_UNLESS(m_entry != nullptr, fs::ResultBufferAllocationFailed());
|
||||
|
||||
this->tree = tree;
|
||||
m_tree = tree;
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
@@ -294,35 +294,35 @@ namespace ams::fssystem {
|
||||
R_UNLESS(this->IsValid(), fs::ResultOutOfRange());
|
||||
|
||||
/* Invalidate our index, and read the header for the next index. */
|
||||
auto entry_index = this->entry_index + 1;
|
||||
if (entry_index == this->entry_set.info.count) {
|
||||
const auto entry_set_index = this->entry_set.info.index + 1;
|
||||
R_UNLESS(entry_set_index < this->entry_set_count, fs::ResultOutOfRange());
|
||||
auto entry_index = m_entry_index + 1;
|
||||
if (entry_index == m_entry_set.info.count) {
|
||||
const auto entry_set_index = m_entry_set.info.index + 1;
|
||||
R_UNLESS(entry_set_index < m_entry_set_count, fs::ResultOutOfRange());
|
||||
|
||||
this->entry_index = -1;
|
||||
m_entry_index = -1;
|
||||
|
||||
const auto end = this->entry_set.info.end;
|
||||
const auto end = m_entry_set.info.end;
|
||||
|
||||
const auto entry_set_size = this->tree->node_size;
|
||||
const auto entry_set_size = m_tree->m_node_size;
|
||||
const auto entry_set_offset = entry_set_index * static_cast<s64>(entry_set_size);
|
||||
|
||||
R_TRY(this->tree->entry_storage.Read(entry_set_offset, std::addressof(this->entry_set), sizeof(EntrySetHeader)));
|
||||
R_TRY(this->entry_set.header.Verify(entry_set_index, entry_set_size, this->tree->entry_size));
|
||||
R_TRY(m_tree->m_entry_storage.Read(entry_set_offset, std::addressof(m_entry_set), sizeof(EntrySetHeader)));
|
||||
R_TRY(m_entry_set.header.Verify(entry_set_index, entry_set_size, m_tree->m_entry_size));
|
||||
|
||||
R_UNLESS(this->entry_set.info.start == end && this->entry_set.info.start < this->entry_set.info.end, fs::ResultInvalidBucketTreeEntrySetOffset());
|
||||
R_UNLESS(m_entry_set.info.start == end && m_entry_set.info.start < m_entry_set.info.end, fs::ResultInvalidBucketTreeEntrySetOffset());
|
||||
|
||||
entry_index = 0;
|
||||
} else {
|
||||
this->entry_index = 1;
|
||||
m_entry_index = 1;
|
||||
}
|
||||
|
||||
/* Read the new entry. */
|
||||
const auto entry_size = this->tree->entry_size;
|
||||
const auto entry_offset = impl::GetBucketTreeEntryOffset(this->entry_set.info.index, this->tree->node_size, entry_size, entry_index);
|
||||
R_TRY(this->tree->entry_storage.Read(entry_offset, std::addressof(this->entry), entry_size));
|
||||
const auto entry_size = m_tree->m_entry_size;
|
||||
const auto entry_offset = impl::GetBucketTreeEntryOffset(m_entry_set.info.index, m_tree->m_node_size, entry_size, entry_index);
|
||||
R_TRY(m_tree->m_entry_storage.Read(entry_offset, std::addressof(m_entry), entry_size));
|
||||
|
||||
/* Note that we changed index. */
|
||||
this->entry_index = entry_index;
|
||||
m_entry_index = entry_index;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
@@ -330,52 +330,52 @@ namespace ams::fssystem {
|
||||
R_UNLESS(this->IsValid(), fs::ResultOutOfRange());
|
||||
|
||||
/* Invalidate our index, and read the heasder for the previous index. */
|
||||
auto entry_index = this->entry_index;
|
||||
auto entry_index = m_entry_index;
|
||||
if (entry_index == 0) {
|
||||
R_UNLESS(this->entry_set.info.index > 0, fs::ResultOutOfRange());
|
||||
R_UNLESS(m_entry_set.info.index > 0, fs::ResultOutOfRange());
|
||||
|
||||
this->entry_index = -1;
|
||||
m_entry_index = -1;
|
||||
|
||||
const auto start = this->entry_set.info.start;
|
||||
const auto start = m_entry_set.info.start;
|
||||
|
||||
const auto entry_set_size = this->tree->node_size;
|
||||
const auto entry_set_index = this->entry_set.info.index - 1;
|
||||
const auto entry_set_size = m_tree->m_node_size;
|
||||
const auto entry_set_index = m_entry_set.info.index - 1;
|
||||
const auto entry_set_offset = entry_set_index * static_cast<s64>(entry_set_size);
|
||||
|
||||
R_TRY(this->tree->entry_storage.Read(entry_set_offset, std::addressof(this->entry_set), sizeof(EntrySetHeader)));
|
||||
R_TRY(this->entry_set.header.Verify(entry_set_index, entry_set_size, this->tree->entry_size));
|
||||
R_TRY(m_tree->m_entry_storage.Read(entry_set_offset, std::addressof(m_entry_set), sizeof(EntrySetHeader)));
|
||||
R_TRY(m_entry_set.header.Verify(entry_set_index, entry_set_size, m_tree->m_entry_size));
|
||||
|
||||
R_UNLESS(this->entry_set.info.end == start && this->entry_set.info.start < this->entry_set.info.end, fs::ResultInvalidBucketTreeEntrySetOffset());
|
||||
R_UNLESS(m_entry_set.info.end == start && m_entry_set.info.start < m_entry_set.info.end, fs::ResultInvalidBucketTreeEntrySetOffset());
|
||||
|
||||
entry_index = this->entry_set.info.count;
|
||||
entry_index = m_entry_set.info.count;
|
||||
} else {
|
||||
this->entry_index = -1;
|
||||
m_entry_index = -1;
|
||||
}
|
||||
|
||||
--entry_index;
|
||||
|
||||
/* Read the new entry. */
|
||||
const auto entry_size = this->tree->entry_size;
|
||||
const auto entry_offset = impl::GetBucketTreeEntryOffset(this->entry_set.info.index, this->tree->node_size, entry_size, entry_index);
|
||||
R_TRY(this->tree->entry_storage.Read(entry_offset, std::addressof(this->entry), entry_size));
|
||||
const auto entry_size = m_tree->m_entry_size;
|
||||
const auto entry_offset = impl::GetBucketTreeEntryOffset(m_entry_set.info.index, m_tree->m_node_size, entry_size, entry_index);
|
||||
R_TRY(m_tree->m_entry_storage.Read(entry_offset, std::addressof(m_entry), entry_size));
|
||||
|
||||
/* Note that we changed index. */
|
||||
this->entry_index = entry_index;
|
||||
m_entry_index = entry_index;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result BucketTree::Visitor::Find(s64 virtual_address) {
|
||||
AMS_ASSERT(this->tree != nullptr);
|
||||
AMS_ASSERT(m_tree != nullptr);
|
||||
|
||||
/* Get the node. */
|
||||
const auto * const node = this->tree->node_l1.Get<Node>();
|
||||
const auto * const node = m_tree->m_node_l1.Get<Node>();
|
||||
R_UNLESS(virtual_address < node->GetEndOffset(), fs::ResultOutOfRange());
|
||||
|
||||
/* Get the entry set index. */
|
||||
s32 entry_set_index = -1;
|
||||
if (this->tree->IsExistOffsetL2OnL1() && virtual_address < node->GetBeginOffset()) {
|
||||
if (m_tree->IsExistOffsetL2OnL1() && virtual_address < node->GetBeginOffset()) {
|
||||
const auto start = node->GetEnd();
|
||||
const auto end = node->GetBegin() + tree->offset_count;
|
||||
const auto end = node->GetBegin() + m_tree->m_offset_count;
|
||||
|
||||
auto pos = std::upper_bound(start, end, virtual_address);
|
||||
R_UNLESS(start < pos, fs::ResultOutOfRange());
|
||||
@@ -390,9 +390,9 @@ namespace ams::fssystem {
|
||||
R_UNLESS(start < pos, fs::ResultOutOfRange());
|
||||
--pos;
|
||||
|
||||
if (this->tree->IsExistL2()) {
|
||||
if (m_tree->IsExistL2()) {
|
||||
const auto node_index = static_cast<s32>(pos - start);
|
||||
R_UNLESS(0 <= node_index && node_index < this->tree->offset_count, fs::ResultInvalidBucketTreeNodeOffset());
|
||||
R_UNLESS(0 <= node_index && node_index < m_tree->m_offset_count, fs::ResultInvalidBucketTreeNodeOffset());
|
||||
|
||||
R_TRY(this->FindEntrySet(std::addressof(entry_set_index), virtual_address, node_index));
|
||||
} else {
|
||||
@@ -401,18 +401,18 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
/* Validate the entry set index. */
|
||||
R_UNLESS(0 <= entry_set_index && entry_set_index < this->tree->entry_set_count, fs::ResultInvalidBucketTreeNodeOffset());
|
||||
R_UNLESS(0 <= entry_set_index && entry_set_index < m_tree->m_entry_set_count, fs::ResultInvalidBucketTreeNodeOffset());
|
||||
|
||||
/* Find the entry. */
|
||||
R_TRY(this->FindEntry(virtual_address, entry_set_index));
|
||||
|
||||
/* Set count. */
|
||||
this->entry_set_count = this->tree->entry_set_count;
|
||||
m_entry_set_count = m_tree->m_entry_set_count;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result BucketTree::Visitor::FindEntrySet(s32 *out_index, s64 virtual_address, s32 node_index) {
|
||||
const auto node_size = this->tree->node_size;
|
||||
const auto node_size = m_tree->m_node_size;
|
||||
|
||||
PooledBuffer pool(node_size, 1);
|
||||
if (node_size <= pool.GetSize()) {
|
||||
@@ -425,9 +425,9 @@ namespace ams::fssystem {
|
||||
|
||||
Result BucketTree::Visitor::FindEntrySetWithBuffer(s32 *out_index, s64 virtual_address, s32 node_index, char *buffer) {
|
||||
/* Calculate node extents. */
|
||||
const auto node_size = this->tree->node_size;
|
||||
const auto node_offset = (node_index + 1) * static_cast<s64>(node_size);
|
||||
fs::SubStorage &storage = tree->node_storage;
|
||||
const auto node_size = m_tree->m_node_size;
|
||||
const auto node_offset = (node_index + 1) * static_cast<s64>(node_size);
|
||||
fs::SubStorage &storage = m_tree->m_node_storage;
|
||||
|
||||
/* Read the node. */
|
||||
R_TRY(storage.Read(node_offset, buffer, node_size));
|
||||
@@ -443,15 +443,15 @@ namespace ams::fssystem {
|
||||
R_UNLESS(node.GetIndex() >= 0, fs::ResultInvalidBucketTreeVirtualOffset());
|
||||
|
||||
/* Return the index. */
|
||||
*out_index = this->tree->GetEntrySetIndex(header.index, node.GetIndex());
|
||||
*out_index = m_tree->GetEntrySetIndex(header.index, node.GetIndex());
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result BucketTree::Visitor::FindEntrySetWithoutBuffer(s32 *out_index, s64 virtual_address, s32 node_index) {
|
||||
/* Calculate node extents. */
|
||||
const auto node_size = this->tree->node_size;
|
||||
const auto node_offset = (node_index + 1) * static_cast<s64>(node_size);
|
||||
fs::SubStorage &storage = tree->node_storage;
|
||||
const auto node_size = m_tree->m_node_size;
|
||||
const auto node_offset = (node_index + 1) * static_cast<s64>(node_size);
|
||||
fs::SubStorage &storage = m_tree->m_node_storage;
|
||||
|
||||
/* Read and validate the header. */
|
||||
NodeHeader header;
|
||||
@@ -464,12 +464,12 @@ namespace ams::fssystem {
|
||||
R_UNLESS(node.GetIndex() >= 0, fs::ResultOutOfRange());
|
||||
|
||||
/* Return the index. */
|
||||
*out_index = this->tree->GetEntrySetIndex(header.index, node.GetIndex());
|
||||
*out_index = m_tree->GetEntrySetIndex(header.index, node.GetIndex());
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result BucketTree::Visitor::FindEntry(s64 virtual_address, s32 entry_set_index) {
|
||||
const auto entry_set_size = this->tree->node_size;
|
||||
const auto entry_set_size = m_tree->m_node_size;
|
||||
|
||||
PooledBuffer pool(entry_set_size, 1);
|
||||
if (entry_set_size <= pool.GetSize()) {
|
||||
@@ -482,10 +482,10 @@ namespace ams::fssystem {
|
||||
|
||||
Result BucketTree::Visitor::FindEntryWithBuffer(s64 virtual_address, s32 entry_set_index, char *buffer) {
|
||||
/* Calculate entry set extents. */
|
||||
const auto entry_size = this->tree->entry_size;
|
||||
const auto entry_set_size = this->tree->node_size;
|
||||
const auto entry_size = m_tree->m_entry_size;
|
||||
const auto entry_set_size = m_tree->m_node_size;
|
||||
const auto entry_set_offset = entry_set_index * static_cast<s64>(entry_set_size);
|
||||
fs::SubStorage &storage = tree->entry_storage;
|
||||
fs::SubStorage &storage = m_tree->m_entry_storage;
|
||||
|
||||
/* Read the entry set. */
|
||||
R_TRY(storage.Read(entry_set_offset, buffer, entry_set_size));
|
||||
@@ -503,21 +503,21 @@ namespace ams::fssystem {
|
||||
/* Copy the data into entry. */
|
||||
const auto entry_index = node.GetIndex();
|
||||
const auto entry_offset = impl::GetBucketTreeEntryOffset(0, entry_size, entry_index);
|
||||
std::memcpy(this->entry, buffer + entry_offset, entry_size);
|
||||
std::memcpy(m_entry, buffer + entry_offset, entry_size);
|
||||
|
||||
/* Set our entry set/index. */
|
||||
this->entry_set = entry_set;
|
||||
this->entry_index = entry_index;
|
||||
m_entry_set = entry_set;
|
||||
m_entry_index = entry_index;
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result BucketTree::Visitor::FindEntryWithoutBuffer(s64 virtual_address, s32 entry_set_index) {
|
||||
/* Calculate entry set extents. */
|
||||
const auto entry_size = this->tree->entry_size;
|
||||
const auto entry_set_size = this->tree->node_size;
|
||||
const auto entry_size = m_tree->m_entry_size;
|
||||
const auto entry_set_size = m_tree->m_node_size;
|
||||
const auto entry_set_offset = entry_set_index * static_cast<s64>(entry_set_size);
|
||||
fs::SubStorage &storage = tree->entry_storage;
|
||||
fs::SubStorage &storage = m_tree->m_entry_storage;
|
||||
|
||||
/* Read and validate the entry_set. */
|
||||
EntrySetHeader entry_set;
|
||||
@@ -532,11 +532,11 @@ namespace ams::fssystem {
|
||||
/* Copy the data into entry. */
|
||||
const auto entry_index = node.GetIndex();
|
||||
const auto entry_offset = impl::GetBucketTreeEntryOffset(entry_set_offset, entry_size, entry_index);
|
||||
R_TRY(storage.Read(entry_offset, this->entry, entry_size));
|
||||
R_TRY(storage.Read(entry_offset, m_entry, entry_size));
|
||||
|
||||
/* Set our entry set/index. */
|
||||
this->entry_set = entry_set;
|
||||
this->entry_index = entry_index;
|
||||
m_entry_set = entry_set;
|
||||
m_entry_index = entry_index;
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
@@ -20,25 +20,25 @@ namespace ams::fssystem {
|
||||
DirectoryRedirectionFileSystem::DirectoryRedirectionFileSystem(std::shared_ptr<fs::fsa::IFileSystem> fs, const char *before, const char *after, bool unc)
|
||||
: PathResolutionFileSystem(fs, unc)
|
||||
{
|
||||
this->before_dir = nullptr;
|
||||
this->after_dir = nullptr;
|
||||
m_before_dir = nullptr;
|
||||
m_after_dir = nullptr;
|
||||
R_ABORT_UNLESS(this->Initialize(before, after));
|
||||
}
|
||||
|
||||
DirectoryRedirectionFileSystem::DirectoryRedirectionFileSystem(std::unique_ptr<fs::fsa::IFileSystem> fs, const char *before, const char *after, bool unc)
|
||||
: PathResolutionFileSystem(std::move(fs), unc)
|
||||
{
|
||||
this->before_dir = nullptr;
|
||||
this->after_dir = nullptr;
|
||||
m_before_dir = nullptr;
|
||||
m_after_dir = nullptr;
|
||||
R_ABORT_UNLESS(this->Initialize(before, after));
|
||||
}
|
||||
|
||||
DirectoryRedirectionFileSystem::~DirectoryRedirectionFileSystem() {
|
||||
if (this->before_dir != nullptr) {
|
||||
fs::impl::Deallocate(this->before_dir, this->before_dir_len);
|
||||
if (m_before_dir != nullptr) {
|
||||
fs::impl::Deallocate(m_before_dir, m_before_dir_len);
|
||||
}
|
||||
if (this->after_dir != nullptr) {
|
||||
fs::impl::Deallocate(this->after_dir, this->after_dir_len);
|
||||
if (m_after_dir != nullptr) {
|
||||
fs::impl::Deallocate(m_after_dir, m_after_dir_len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,8 +82,8 @@ namespace ams::fssystem {
|
||||
|
||||
Result DirectoryRedirectionFileSystem::Initialize(const char *before, const char *after) {
|
||||
/* Normalize both directories. */
|
||||
this->GetNormalizedDirectoryPath(std::addressof(this->before_dir), std::addressof(this->before_dir_len), before);
|
||||
this->GetNormalizedDirectoryPath(std::addressof(this->after_dir), std::addressof(this->after_dir_len), after);
|
||||
this->GetNormalizedDirectoryPath(std::addressof(m_before_dir), std::addressof(m_before_dir_len), before);
|
||||
this->GetNormalizedDirectoryPath(std::addressof(m_after_dir), std::addressof(m_after_dir_len), after);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -91,29 +91,29 @@ namespace ams::fssystem {
|
||||
Result DirectoryRedirectionFileSystem::ResolveFullPath(char *out, size_t out_size, const char *relative_path) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(relative_path[0] == '/');
|
||||
AMS_ASSERT(this->before_dir_len >= 2);
|
||||
AMS_ASSERT(this->after_dir_len >= 2);
|
||||
AMS_ASSERT(this->after_dir_len <= out_size);
|
||||
AMS_ASSERT(fs::PathNormalizer::IsNullTerminator(this->before_dir[this->before_dir_len - 1]));
|
||||
AMS_ASSERT(fs::PathNormalizer::IsSeparator(this->before_dir[this->before_dir_len - 2]));
|
||||
AMS_ASSERT(fs::PathNormalizer::IsNullTerminator(this->after_dir[this->after_dir_len - 1]));
|
||||
AMS_ASSERT(fs::PathNormalizer::IsSeparator(this->after_dir[this->after_dir_len - 2]));
|
||||
AMS_ASSERT(m_before_dir_len >= 2);
|
||||
AMS_ASSERT(m_after_dir_len >= 2);
|
||||
AMS_ASSERT(m_after_dir_len <= out_size);
|
||||
AMS_ASSERT(fs::PathNormalizer::IsNullTerminator(m_before_dir[m_before_dir_len - 1]));
|
||||
AMS_ASSERT(fs::PathNormalizer::IsSeparator(m_before_dir[m_before_dir_len - 2]));
|
||||
AMS_ASSERT(fs::PathNormalizer::IsNullTerminator(m_after_dir[m_after_dir_len - 1]));
|
||||
AMS_ASSERT(fs::PathNormalizer::IsSeparator(m_after_dir[m_after_dir_len - 2]));
|
||||
|
||||
/* Normalize the relative path. */
|
||||
char normalized_rel_path[fs::EntryNameLengthMax + 1];
|
||||
size_t normalized_rel_path_len;
|
||||
R_TRY(fs::PathNormalizer::Normalize(normalized_rel_path, std::addressof(normalized_rel_path_len), relative_path, sizeof(normalized_rel_path), this->IsUncPreserved(), false));
|
||||
|
||||
const bool is_prefixed = std::memcmp(normalized_rel_path, this->before_dir, this->before_dir_len - 2) == 0 &&
|
||||
(fs::PathNormalizer::IsSeparator(normalized_rel_path[this->before_dir_len - 2]) || fs::PathNormalizer::IsNullTerminator(normalized_rel_path[this->before_dir_len - 2]));
|
||||
const bool is_prefixed = std::memcmp(normalized_rel_path, m_before_dir, m_before_dir_len - 2) == 0 &&
|
||||
(fs::PathNormalizer::IsSeparator(normalized_rel_path[m_before_dir_len - 2]) || fs::PathNormalizer::IsNullTerminator(normalized_rel_path[m_before_dir_len - 2]));
|
||||
if (is_prefixed) {
|
||||
const size_t before_prefix_len = this->before_dir_len - 2;
|
||||
const size_t after_prefix_len = this->after_dir_len - 2;
|
||||
const size_t before_prefix_len = m_before_dir_len - 2;
|
||||
const size_t after_prefix_len = m_after_dir_len - 2;
|
||||
const size_t final_str_len = after_prefix_len + normalized_rel_path_len - before_prefix_len;
|
||||
R_UNLESS(final_str_len < out_size, fs::ResultTooLongPath());
|
||||
|
||||
/* Copy normalized path. */
|
||||
std::memcpy(out, this->after_dir, after_prefix_len);
|
||||
std::memcpy(out, m_after_dir, after_prefix_len);
|
||||
std::memcpy(out + after_prefix_len, normalized_rel_path + before_prefix_len, normalized_rel_path_len - before_prefix_len);
|
||||
out[final_str_len] = fs::StringTraits::NullTerminator;
|
||||
} else {
|
||||
|
||||
@@ -27,60 +27,60 @@ namespace ams::fssystem {
|
||||
|
||||
class DirectorySaveDataFile : public fs::fsa::IFile {
|
||||
private:
|
||||
std::unique_ptr<fs::fsa::IFile> base_file;
|
||||
DirectorySaveDataFileSystem *parent_fs;
|
||||
fs::OpenMode open_mode;
|
||||
std::unique_ptr<fs::fsa::IFile> m_base_file;
|
||||
DirectorySaveDataFileSystem *m_parent_fs;
|
||||
fs::OpenMode m_open_mode;
|
||||
public:
|
||||
DirectorySaveDataFile(std::unique_ptr<fs::fsa::IFile> f, DirectorySaveDataFileSystem *p, fs::OpenMode m) : base_file(std::move(f)), parent_fs(p), open_mode(m) {
|
||||
DirectorySaveDataFile(std::unique_ptr<fs::fsa::IFile> f, DirectorySaveDataFileSystem *p, fs::OpenMode m) : m_base_file(std::move(f)), m_parent_fs(p), m_open_mode(m) {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
virtual ~DirectorySaveDataFile() {
|
||||
/* Observe closing of writable file. */
|
||||
if (this->open_mode & fs::OpenMode_Write) {
|
||||
this->parent_fs->OnWritableFileClose();
|
||||
if (m_open_mode & fs::OpenMode_Write) {
|
||||
m_parent_fs->OnWritableFileClose();
|
||||
}
|
||||
}
|
||||
public:
|
||||
virtual Result DoRead(size_t *out, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) override {
|
||||
return this->base_file->Read(out, offset, buffer, size, option);
|
||||
return m_base_file->Read(out, offset, buffer, size, option);
|
||||
}
|
||||
|
||||
virtual Result DoGetSize(s64 *out) override {
|
||||
return this->base_file->GetSize(out);
|
||||
return m_base_file->GetSize(out);
|
||||
}
|
||||
|
||||
virtual Result DoFlush() override {
|
||||
return this->base_file->Flush();
|
||||
return m_base_file->Flush();
|
||||
}
|
||||
|
||||
virtual Result DoWrite(s64 offset, const void *buffer, size_t size, const fs::WriteOption &option) override {
|
||||
return this->base_file->Write(offset, buffer, size, option);
|
||||
return m_base_file->Write(offset, buffer, size, option);
|
||||
}
|
||||
|
||||
virtual Result DoSetSize(s64 size) override {
|
||||
return this->base_file->SetSize(size);
|
||||
return m_base_file->SetSize(size);
|
||||
}
|
||||
|
||||
virtual Result DoOperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override {
|
||||
return this->base_file->OperateRange(dst, dst_size, op_id, offset, size, src, src_size);
|
||||
return m_base_file->OperateRange(dst, dst_size, op_id, offset, size, src, src_size);
|
||||
}
|
||||
public:
|
||||
virtual sf::cmif::DomainObjectId GetDomainObjectId() const override {
|
||||
return this->base_file->GetDomainObjectId();
|
||||
return m_base_file->GetDomainObjectId();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
DirectorySaveDataFileSystem::DirectorySaveDataFileSystem(std::shared_ptr<fs::fsa::IFileSystem> fs)
|
||||
: PathResolutionFileSystem(fs), accessor_mutex(), open_writable_files(0)
|
||||
: PathResolutionFileSystem(fs), m_accessor_mutex(), m_open_writable_files(0)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
DirectorySaveDataFileSystem::DirectorySaveDataFileSystem(std::unique_ptr<fs::fsa::IFileSystem> fs)
|
||||
: PathResolutionFileSystem(std::move(fs)), accessor_mutex(), open_writable_files(0)
|
||||
: PathResolutionFileSystem(std::move(fs)), m_accessor_mutex(), m_open_writable_files(0)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
@@ -91,25 +91,25 @@ namespace ams::fssystem {
|
||||
|
||||
Result DirectorySaveDataFileSystem::Initialize() {
|
||||
/* Nintendo does not acquire the lock here, but I think we probably should. */
|
||||
std::scoped_lock lk(this->accessor_mutex);
|
||||
std::scoped_lock lk(m_accessor_mutex);
|
||||
|
||||
fs::DirectoryEntryType type;
|
||||
|
||||
/* Check that the working directory exists. */
|
||||
R_TRY_CATCH(this->base_fs->GetEntryType(std::addressof(type), WorkingDirectoryPath)) {
|
||||
R_TRY_CATCH(m_base_fs->GetEntryType(std::addressof(type), WorkingDirectoryPath)) {
|
||||
/* If path isn't found, create working directory and committed directory. */
|
||||
R_CATCH(fs::ResultPathNotFound) {
|
||||
R_TRY(this->base_fs->CreateDirectory(WorkingDirectoryPath));
|
||||
R_TRY(this->base_fs->CreateDirectory(CommittedDirectoryPath));
|
||||
R_TRY(m_base_fs->CreateDirectory(WorkingDirectoryPath));
|
||||
R_TRY(m_base_fs->CreateDirectory(CommittedDirectoryPath));
|
||||
}
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
/* Now check for the committed directory. */
|
||||
R_TRY_CATCH(this->base_fs->GetEntryType(std::addressof(type), CommittedDirectoryPath)) {
|
||||
R_TRY_CATCH(m_base_fs->GetEntryType(std::addressof(type), CommittedDirectoryPath)) {
|
||||
/* Committed doesn't exist, so synchronize and rename. */
|
||||
R_CATCH(fs::ResultPathNotFound) {
|
||||
R_TRY(this->SynchronizeDirectory(SynchronizingDirectoryPath, WorkingDirectoryPath));
|
||||
R_TRY(this->base_fs->RenameDirectory(SynchronizingDirectoryPath, CommittedDirectoryPath));
|
||||
R_TRY(m_base_fs->RenameDirectory(SynchronizingDirectoryPath, CommittedDirectoryPath));
|
||||
return ResultSuccess();
|
||||
}
|
||||
} R_END_TRY_CATCH;
|
||||
@@ -139,11 +139,11 @@ namespace ams::fssystem {
|
||||
|
||||
Result DirectorySaveDataFileSystem::SynchronizeDirectory(const char *dst, const char *src) {
|
||||
/* Delete destination dir and recreate it. */
|
||||
R_TRY_CATCH(this->base_fs->DeleteDirectoryRecursively(dst)) {
|
||||
R_TRY_CATCH(m_base_fs->DeleteDirectoryRecursively(dst)) {
|
||||
R_CATCH(fs::ResultPathNotFound) { /* Nintendo returns error unconditionally, but I think that's a bug in their code. */}
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
R_TRY(this->base_fs->CreateDirectory(dst));
|
||||
R_TRY(m_base_fs->CreateDirectory(dst));
|
||||
|
||||
/* Get a work buffer to work with. */
|
||||
std::unique_ptr<u8[]> work_buf;
|
||||
@@ -151,7 +151,7 @@ namespace ams::fssystem {
|
||||
R_TRY(this->AllocateWorkBuffer(std::addressof(work_buf), std::addressof(work_buf_size), IdealWorkBufferSize));
|
||||
|
||||
/* Copy the directory recursively. */
|
||||
return fssystem::CopyDirectoryRecursively(this->base_fs, dst, src, work_buf.get(), work_buf_size);
|
||||
return fssystem::CopyDirectoryRecursively(m_base_fs, dst, src, work_buf.get(), work_buf_size);
|
||||
}
|
||||
|
||||
Result DirectorySaveDataFileSystem::ResolveFullPath(char *out, size_t out_size, const char *relative_path) {
|
||||
@@ -169,11 +169,11 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
void DirectorySaveDataFileSystem::OnWritableFileClose() {
|
||||
std::scoped_lock lk(this->accessor_mutex);
|
||||
this->open_writable_files--;
|
||||
std::scoped_lock lk(m_accessor_mutex);
|
||||
m_open_writable_files--;
|
||||
|
||||
/* Nintendo does not check this, but I think it's sensible to do so. */
|
||||
AMS_ABORT_UNLESS(this->open_writable_files >= 0);
|
||||
AMS_ABORT_UNLESS(m_open_writable_files >= 0);
|
||||
}
|
||||
|
||||
Result DirectorySaveDataFileSystem::CopySaveFromFileSystem(fs::fsa::IFileSystem *save_fs) {
|
||||
@@ -186,7 +186,7 @@ namespace ams::fssystem {
|
||||
R_TRY(this->AllocateWorkBuffer(std::addressof(work_buf), std::addressof(work_buf_size), IdealWorkBufferSize));
|
||||
|
||||
/* Copy the directory recursively. */
|
||||
R_TRY(fssystem::CopyDirectoryRecursively(this->base_fs, save_fs, fs::PathNormalizer::RootPath, fs::PathNormalizer::RootPath, work_buf.get(), work_buf_size));
|
||||
R_TRY(fssystem::CopyDirectoryRecursively(m_base_fs, save_fs, fs::PathNormalizer::RootPath, fs::PathNormalizer::RootPath, work_buf.get(), work_buf_size));
|
||||
|
||||
return this->Commit();
|
||||
}
|
||||
@@ -196,15 +196,15 @@ namespace ams::fssystem {
|
||||
char full_path[fs::EntryNameLengthMax + 1];
|
||||
R_TRY(this->ResolveFullPath(full_path, sizeof(full_path), path));
|
||||
|
||||
std::scoped_lock lk(this->accessor_mutex);
|
||||
std::scoped_lock lk(m_accessor_mutex);
|
||||
std::unique_ptr<fs::fsa::IFile> base_file;
|
||||
R_TRY(this->base_fs->OpenFile(std::addressof(base_file), full_path, mode));
|
||||
R_TRY(m_base_fs->OpenFile(std::addressof(base_file), full_path, mode));
|
||||
|
||||
std::unique_ptr<DirectorySaveDataFile> file(new (std::nothrow) DirectorySaveDataFile(std::move(base_file), this, mode));
|
||||
R_UNLESS(file != nullptr, fs::ResultAllocationFailureInDirectorySaveDataFileSystem());
|
||||
|
||||
if (mode & fs::OpenMode_Write) {
|
||||
this->open_writable_files++;
|
||||
m_open_writable_files++;
|
||||
}
|
||||
|
||||
*out_file = std::move(file);
|
||||
@@ -216,13 +216,13 @@ namespace ams::fssystem {
|
||||
/* - Rename Committed -> Synchronizing. */
|
||||
/* - Synchronize Working -> Synchronizing (deleting Synchronizing). */
|
||||
/* - Rename Synchronizing -> Committed. */
|
||||
std::scoped_lock lk(this->accessor_mutex);
|
||||
std::scoped_lock lk(m_accessor_mutex);
|
||||
|
||||
R_UNLESS(this->open_writable_files == 0, fs::ResultPreconditionViolation());
|
||||
R_UNLESS(m_open_writable_files == 0, fs::ResultPreconditionViolation());
|
||||
|
||||
const auto RenameCommitedDir = [&]() { return this->base_fs->RenameDirectory(CommittedDirectoryPath, SynchronizingDirectoryPath); };
|
||||
const auto RenameCommitedDir = [&]() { return m_base_fs->RenameDirectory(CommittedDirectoryPath, SynchronizingDirectoryPath); };
|
||||
const auto SynchronizeWorkingDir = [&]() { return this->SynchronizeDirectory(SynchronizingDirectoryPath, WorkingDirectoryPath); };
|
||||
const auto RenameSynchronizingDir = [&]() { return this->base_fs->RenameDirectory(SynchronizingDirectoryPath, CommittedDirectoryPath); };
|
||||
const auto RenameSynchronizingDir = [&]() { return m_base_fs->RenameDirectory(SynchronizingDirectoryPath, CommittedDirectoryPath); };
|
||||
|
||||
/* Rename Committed -> Synchronizing. */
|
||||
R_TRY(fssystem::RetryFinitelyForTargetLocked(std::move(RenameCommitedDir)));
|
||||
@@ -233,7 +233,7 @@ namespace ams::fssystem {
|
||||
/* - Rename Synchronizing -> Committed. */
|
||||
R_TRY(fssystem::RetryFinitelyForTargetLocked(std::move(RenameSynchronizingDir)));
|
||||
|
||||
/* TODO: Should I call this->base_fs->Commit()? Nintendo does not. */
|
||||
/* TODO: Should I call m_base_fs->Commit()? Nintendo does not. */
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
|
||||
@@ -41,21 +41,21 @@ namespace ams::fssystem {
|
||||
AMS_UNUSED(layer_count);
|
||||
|
||||
/* Set size tracking members. */
|
||||
this->hash_target_block_size = htbs;
|
||||
this->log_size_ratio = Log2(this->hash_target_block_size / HashSize);
|
||||
m_hash_target_block_size = htbs;
|
||||
m_log_size_ratio = Log2(m_hash_target_block_size / HashSize);
|
||||
|
||||
/* Get the base storage size. */
|
||||
R_TRY(base_storages[2]->GetSize(std::addressof(this->base_storage_size)));
|
||||
R_TRY(base_storages[2]->GetSize(std::addressof(m_base_storage_size)));
|
||||
{
|
||||
auto size_guard = SCOPE_GUARD { this->base_storage_size = 0; };
|
||||
R_UNLESS(this->base_storage_size <= static_cast<s64>(HashSize) << log_size_ratio << log_size_ratio, fs::ResultHierarchicalSha256BaseStorageTooLarge());
|
||||
auto size_guard = SCOPE_GUARD { m_base_storage_size = 0; };
|
||||
R_UNLESS(m_base_storage_size <= static_cast<s64>(HashSize) << m_log_size_ratio << m_log_size_ratio, fs::ResultHierarchicalSha256BaseStorageTooLarge());
|
||||
size_guard.Cancel();
|
||||
}
|
||||
|
||||
/* Set hash buffer tracking members. */
|
||||
this->base_storage = base_storages[2];
|
||||
this->hash_buffer = static_cast<char *>(hash_buf);
|
||||
this->hash_buffer_size = hash_buf_size;
|
||||
m_base_storage = base_storages[2];
|
||||
m_hash_buffer = static_cast<char *>(hash_buf);
|
||||
m_hash_buffer_size = hash_buf_size;
|
||||
|
||||
/* Read the master hash. */
|
||||
u8 master_hash[HashSize];
|
||||
@@ -65,14 +65,14 @@ namespace ams::fssystem {
|
||||
s64 hash_storage_size;
|
||||
R_TRY(base_storages[1]->GetSize(std::addressof(hash_storage_size)));
|
||||
AMS_ASSERT(util::IsAligned(hash_storage_size, HashSize));
|
||||
AMS_ASSERT(hash_storage_size <= this->hash_target_block_size);
|
||||
AMS_ASSERT(hash_storage_size <= static_cast<s64>(this->hash_buffer_size));
|
||||
AMS_ASSERT(hash_storage_size <= m_hash_target_block_size);
|
||||
AMS_ASSERT(hash_storage_size <= static_cast<s64>(m_hash_buffer_size));
|
||||
|
||||
R_TRY(base_storages[1]->Read(0, this->hash_buffer, static_cast<size_t>(hash_storage_size)));
|
||||
R_TRY(base_storages[1]->Read(0, m_hash_buffer, static_cast<size_t>(hash_storage_size)));
|
||||
|
||||
/* Calculate and verify the master hash. */
|
||||
u8 calc_hash[HashSize];
|
||||
crypto::GenerateSha256Hash(calc_hash, sizeof(calc_hash), this->hash_buffer, static_cast<size_t>(hash_storage_size));
|
||||
crypto::GenerateSha256Hash(calc_hash, sizeof(calc_hash), m_hash_buffer, static_cast<size_t>(hash_storage_size));
|
||||
R_UNLESS(crypto::IsSameBytes(master_hash, calc_hash, HashSize), fs::ResultHierarchicalSha256HashVerificationFailed());
|
||||
|
||||
return ResultSuccess();
|
||||
@@ -86,12 +86,12 @@ namespace ams::fssystem {
|
||||
R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument());
|
||||
|
||||
/* Validate preconditions. */
|
||||
R_UNLESS(util::IsAligned(offset, this->hash_target_block_size), fs::ResultInvalidArgument());
|
||||
R_UNLESS(util::IsAligned(size, this->hash_target_block_size), fs::ResultInvalidArgument());
|
||||
R_UNLESS(util::IsAligned(offset, m_hash_target_block_size), fs::ResultInvalidArgument());
|
||||
R_UNLESS(util::IsAligned(size, m_hash_target_block_size), fs::ResultInvalidArgument());
|
||||
|
||||
/* Read the data. */
|
||||
const size_t reduced_size = static_cast<size_t>(std::min<s64>(this->base_storage_size, util::AlignUp(offset + size, this->hash_target_block_size) - offset));
|
||||
R_TRY(this->base_storage->Read(offset, buffer, reduced_size));
|
||||
const size_t reduced_size = static_cast<size_t>(std::min<s64>(m_base_storage_size, util::AlignUp(offset + size, m_hash_target_block_size) - offset));
|
||||
R_TRY(m_base_storage->Read(offset, buffer, reduced_size));
|
||||
|
||||
/* Temporarily increase our thread priority. */
|
||||
ScopedThreadPriorityChanger cp(+1, ScopedThreadPriorityChanger::Mode::Relative);
|
||||
@@ -102,17 +102,17 @@ namespace ams::fssystem {
|
||||
while (remaining_size > 0) {
|
||||
/* Generate the hash of the region we're validating. */
|
||||
u8 hash[HashSize];
|
||||
const auto cur_size = static_cast<size_t>(std::min<s64>(this->hash_target_block_size, remaining_size));
|
||||
const auto cur_size = static_cast<size_t>(std::min<s64>(m_hash_target_block_size, remaining_size));
|
||||
crypto::GenerateSha256Hash(hash, sizeof(hash), static_cast<u8 *>(buffer) + (cur_offset - offset), cur_size);
|
||||
|
||||
AMS_ASSERT(static_cast<size_t>(cur_offset >> this->log_size_ratio) < this->hash_buffer_size);
|
||||
AMS_ASSERT(static_cast<size_t>(cur_offset >> m_log_size_ratio) < m_hash_buffer_size);
|
||||
|
||||
/* Check the hash. */
|
||||
{
|
||||
std::scoped_lock lk(this->mutex);
|
||||
std::scoped_lock lk(m_mutex);
|
||||
auto clear_guard = SCOPE_GUARD { std::memset(buffer, 0, size); };
|
||||
|
||||
R_UNLESS(crypto::IsSameBytes(hash, std::addressof(this->hash_buffer[cur_offset >> this->log_size_ratio]), HashSize), fs::ResultHierarchicalSha256HashVerificationFailed());
|
||||
R_UNLESS(crypto::IsSameBytes(hash, std::addressof(m_hash_buffer[cur_offset >> m_log_size_ratio]), HashSize), fs::ResultHierarchicalSha256HashVerificationFailed());
|
||||
|
||||
clear_guard.Cancel();
|
||||
}
|
||||
@@ -133,17 +133,17 @@ namespace ams::fssystem {
|
||||
R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument());
|
||||
|
||||
/* Validate preconditions. */
|
||||
R_UNLESS(util::IsAligned(offset, this->hash_target_block_size), fs::ResultInvalidArgument());
|
||||
R_UNLESS(util::IsAligned(size, this->hash_target_block_size), fs::ResultInvalidArgument());
|
||||
R_UNLESS(util::IsAligned(offset, m_hash_target_block_size), fs::ResultInvalidArgument());
|
||||
R_UNLESS(util::IsAligned(size, m_hash_target_block_size), fs::ResultInvalidArgument());
|
||||
|
||||
/* Setup tracking variables. */
|
||||
const size_t reduced_size = static_cast<size_t>(std::min<s64>(this->base_storage_size, util::AlignUp(offset + size, this->hash_target_block_size) - offset));
|
||||
const size_t reduced_size = static_cast<size_t>(std::min<s64>(m_base_storage_size, util::AlignUp(offset + size, m_hash_target_block_size) - offset));
|
||||
auto cur_offset = offset;
|
||||
auto remaining_size = reduced_size;
|
||||
while (remaining_size > 0) {
|
||||
/* Generate the hash of the region we're validating. */
|
||||
u8 hash[HashSize];
|
||||
const auto cur_size = static_cast<size_t>(std::min<s64>(this->hash_target_block_size, remaining_size));
|
||||
const auto cur_size = static_cast<size_t>(std::min<s64>(m_hash_target_block_size, remaining_size));
|
||||
{
|
||||
/* Temporarily increase our thread priority. */
|
||||
ScopedThreadPriorityChanger cp(+1, ScopedThreadPriorityChanger::Mode::Relative);
|
||||
@@ -151,12 +151,12 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
/* Write the data. */
|
||||
R_TRY(this->base_storage->Write(cur_offset, static_cast<const u8 *>(buffer) + (cur_offset - offset), cur_size));
|
||||
R_TRY(m_base_storage->Write(cur_offset, static_cast<const u8 *>(buffer) + (cur_offset - offset), cur_size));
|
||||
|
||||
/* Write the hash. */
|
||||
{
|
||||
std::scoped_lock lk(this->mutex);
|
||||
std::memcpy(std::addressof(this->hash_buffer[cur_offset >> this->log_size_ratio]), hash, HashSize);
|
||||
std::scoped_lock lk(m_mutex);
|
||||
std::memcpy(std::addressof(m_hash_buffer[cur_offset >> m_log_size_ratio]), hash, HashSize);
|
||||
}
|
||||
|
||||
/* Advance. */
|
||||
@@ -172,14 +172,14 @@ namespace ams::fssystem {
|
||||
R_SUCCEED_IF(size == 0);
|
||||
|
||||
/* Validate preconditions. */
|
||||
R_UNLESS(util::IsAligned(offset, this->hash_target_block_size), fs::ResultInvalidArgument());
|
||||
R_UNLESS(util::IsAligned(size, this->hash_target_block_size), fs::ResultInvalidArgument());
|
||||
R_UNLESS(util::IsAligned(offset, m_hash_target_block_size), fs::ResultInvalidArgument());
|
||||
R_UNLESS(util::IsAligned(size, m_hash_target_block_size), fs::ResultInvalidArgument());
|
||||
|
||||
/* Determine size to use. */
|
||||
const auto reduced_size = std::min<s64>(this->base_storage_size, util::AlignUp(offset + size, this->hash_target_block_size) - offset);
|
||||
const auto reduced_size = std::min<s64>(m_base_storage_size, util::AlignUp(offset + size, m_hash_target_block_size) - offset);
|
||||
|
||||
/* Operate on the base storage. */
|
||||
return this->base_storage->OperateRange(dst, dst_size, op_id, offset, reduced_size, src, src_size);
|
||||
return m_base_storage->OperateRange(dst, dst_size, op_id, offset, reduced_size, src, src_size);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,15 +25,15 @@ namespace ams::fssystem {
|
||||
static constexpr s32 LayerCount = 3;
|
||||
static constexpr size_t HashSize = crypto::Sha256Generator::HashSize;
|
||||
private:
|
||||
os::SdkMutex mutex;
|
||||
IStorage *base_storage;
|
||||
s64 base_storage_size;
|
||||
char *hash_buffer;
|
||||
size_t hash_buffer_size;
|
||||
s32 hash_target_block_size;
|
||||
s32 log_size_ratio;
|
||||
os::SdkMutex m_mutex;
|
||||
IStorage *m_base_storage;
|
||||
s64 m_base_storage_size;
|
||||
char *m_hash_buffer;
|
||||
size_t m_hash_buffer_size;
|
||||
s32 m_hash_target_block_size;
|
||||
s32 m_log_size_ratio;
|
||||
public:
|
||||
HierarchicalSha256Storage() : mutex() { /* ... */ }
|
||||
HierarchicalSha256Storage() : m_mutex() { /* ... */ }
|
||||
|
||||
Result Initialize(IStorage **base_storages, s32 layer_count, size_t htbs, void *hash_buf, size_t hash_buf_size);
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace ams::fssystem {
|
||||
virtual Result OperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override;
|
||||
|
||||
virtual Result GetSize(s64 *out) override {
|
||||
return this->base_storage->GetSize(out);
|
||||
return m_base_storage->GetSize(out);
|
||||
}
|
||||
|
||||
virtual Result Flush() override {
|
||||
|
||||
@@ -35,9 +35,9 @@ namespace ams::fssystem {
|
||||
|
||||
void IndirectStorage::Finalize() {
|
||||
if (this->IsInitialized()) {
|
||||
this->table.Finalize();
|
||||
m_table.Finalize();
|
||||
for (auto i = 0; i < StorageCount; i++) {
|
||||
this->data_storage[i] = fs::SubStorage();
|
||||
m_data_storage[i] = fs::SubStorage();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,14 +59,14 @@ namespace ams::fssystem {
|
||||
R_UNLESS(out_entries != nullptr || entry_count == 0, fs::ResultNullptrArgument());
|
||||
|
||||
/* Check that our range is valid. */
|
||||
R_UNLESS(this->table.Includes(offset, size), fs::ResultOutOfRange());
|
||||
R_UNLESS(m_table.Includes(offset, size), fs::ResultOutOfRange());
|
||||
|
||||
/* Find the offset in our tree. */
|
||||
BucketTree::Visitor visitor;
|
||||
R_TRY(this->table.Find(std::addressof(visitor), offset));
|
||||
R_TRY(m_table.Find(std::addressof(visitor), offset));
|
||||
{
|
||||
const auto entry_offset = visitor.Get<Entry>()->GetVirtualOffset();
|
||||
R_UNLESS(0 <= entry_offset && this->table.Includes(entry_offset), fs::ResultInvalidIndirectEntryOffset());
|
||||
R_UNLESS(0 <= entry_offset && m_table.Includes(entry_offset), fs::ResultInvalidIndirectEntryOffset());
|
||||
}
|
||||
|
||||
/* Prepare to loop over entries. */
|
||||
@@ -124,10 +124,10 @@ namespace ams::fssystem {
|
||||
{
|
||||
if (size > 0) {
|
||||
/* Validate arguments. */
|
||||
R_UNLESS(this->table.Includes(offset, size), fs::ResultOutOfRange());
|
||||
if (!this->table.IsEmpty()) {
|
||||
R_UNLESS(m_table.Includes(offset, size), fs::ResultOutOfRange());
|
||||
if (!m_table.IsEmpty()) {
|
||||
/* Invalidate our table's cache. */
|
||||
R_TRY(this->table.InvalidateCache());
|
||||
R_TRY(m_table.InvalidateCache());
|
||||
|
||||
/* Operate on our entries. */
|
||||
R_TRY(this->OperatePerEntry<false>(offset, size, [=](fs::IStorage *storage, s64 data_offset, s64 cur_offset, s64 cur_size) -> Result {
|
||||
@@ -148,8 +148,8 @@ namespace ams::fssystem {
|
||||
|
||||
if (size > 0) {
|
||||
/* Validate arguments. */
|
||||
R_UNLESS(this->table.Includes(offset, size), fs::ResultOutOfRange());
|
||||
if (!this->table.IsEmpty()) {
|
||||
R_UNLESS(m_table.Includes(offset, size), fs::ResultOutOfRange());
|
||||
if (!m_table.IsEmpty()) {
|
||||
/* Create a new info. */
|
||||
fs::QueryRangeInfo merged_info;
|
||||
merged_info.Clear();
|
||||
|
||||
@@ -22,24 +22,24 @@ namespace ams::fssystem {
|
||||
AMS_ASSERT(bm != nullptr);
|
||||
|
||||
/* Set master hash. */
|
||||
this->master_hash = master_hash;
|
||||
this->master_hash_storage = std::make_unique<fs::MemoryStorage>(std::addressof(this->master_hash), sizeof(Hash));
|
||||
R_UNLESS(this->master_hash_storage != nullptr, fs::ResultAllocationFailureInIntegrityRomFsStorageA());
|
||||
m_master_hash = master_hash;
|
||||
m_master_hash_storage = std::make_unique<fs::MemoryStorage>(std::addressof(m_master_hash), sizeof(Hash));
|
||||
R_UNLESS(m_master_hash_storage != nullptr, fs::ResultAllocationFailureInIntegrityRomFsStorageA());
|
||||
|
||||
/* Set the master hash storage. */
|
||||
storage_info[0] = fs::SubStorage(this->master_hash_storage.get(), 0, sizeof(Hash));
|
||||
storage_info[0] = fs::SubStorage(m_master_hash_storage.get(), 0, sizeof(Hash));
|
||||
|
||||
/* Set buffers. */
|
||||
for (size_t i = 0; i < util::size(this->buffers.buffers); ++i) {
|
||||
this->buffers.buffers[i] = bm;
|
||||
for (size_t i = 0; i < util::size(m_buffers.buffers); ++i) {
|
||||
m_buffers.buffers[i] = bm;
|
||||
}
|
||||
|
||||
/* Initialize our integrity storage. */
|
||||
return this->integrity_storage.Initialize(level_hash_info, storage_info, std::addressof(this->buffers), std::addressof(this->mutex), fs::StorageType_RomFs);
|
||||
return m_integrity_storage.Initialize(level_hash_info, storage_info, std::addressof(m_buffers), std::addressof(m_mutex), fs::StorageType_RomFs);
|
||||
}
|
||||
|
||||
void IntegrityRomFsStorage::Finalize() {
|
||||
this->integrity_storage.Finalize();
|
||||
m_integrity_storage.Finalize();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,12 +22,12 @@ namespace ams::fssystem {
|
||||
NON_COPYABLE(KeySlotCacheAccessor);
|
||||
NON_MOVEABLE(KeySlotCacheAccessor);
|
||||
private:
|
||||
util::unique_lock<os::SdkMutex> lk;
|
||||
const s32 slot_index;
|
||||
util::unique_lock<os::SdkMutex> m_lk;
|
||||
const s32 m_slot_index;
|
||||
public:
|
||||
KeySlotCacheAccessor(s32 idx, util::unique_lock<os::SdkMutex> &&l) : lk(std::move(l)), slot_index(idx) { /* ... */ }
|
||||
KeySlotCacheAccessor(s32 idx, util::unique_lock<os::SdkMutex> &&l) : m_lk(std::move(l)), m_slot_index(idx) { /* ... */ }
|
||||
|
||||
s32 GetKeySlotIndex() const { return this->slot_index; }
|
||||
s32 GetKeySlotIndex() const { return m_slot_index; }
|
||||
};
|
||||
|
||||
class KeySlotCacheEntry : public util::IntrusiveListBaseNode<KeySlotCacheEntry> {
|
||||
@@ -36,27 +36,27 @@ namespace ams::fssystem {
|
||||
public:
|
||||
static constexpr size_t KeySize = crypto::AesDecryptor128::KeySize;
|
||||
private:
|
||||
const s32 slot_index;
|
||||
u8 key1[KeySize];
|
||||
s32 key2;
|
||||
const s32 m_slot_index;
|
||||
u8 m_key1[KeySize];
|
||||
s32 m_key2;
|
||||
public:
|
||||
explicit KeySlotCacheEntry(s32 idx) : slot_index(idx), key2(-1) {
|
||||
std::memset(this->key1, 0, sizeof(this->key1));
|
||||
explicit KeySlotCacheEntry(s32 idx) : m_slot_index(idx), m_key2(-1) {
|
||||
std::memset(m_key1, 0, sizeof(m_key1));
|
||||
}
|
||||
|
||||
bool Contains(const void *key, size_t key_size, s32 key2) const {
|
||||
AMS_ASSERT(key_size == KeySize);
|
||||
AMS_UNUSED(key_size);
|
||||
|
||||
return key2 == this->key2 && std::memcmp(this->key1, key, KeySize) == 0;
|
||||
return key2 == m_key2 && std::memcmp(m_key1, key, KeySize) == 0;
|
||||
}
|
||||
|
||||
s32 GetKeySlotIndex() const { return this->slot_index; }
|
||||
s32 GetKeySlotIndex() const { return m_slot_index; }
|
||||
|
||||
void SetKey(const void *key, size_t key_size, s32 key2) {
|
||||
AMS_ASSERT(key_size == KeySize);
|
||||
std::memcpy(this->key1, key, key_size);
|
||||
this->key2 = key2;
|
||||
std::memcpy(m_key1, key, key_size);
|
||||
m_key2 = key2;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -66,24 +66,24 @@ namespace ams::fssystem {
|
||||
private:
|
||||
using KeySlotCacheEntryList = util::IntrusiveListBaseTraits<KeySlotCacheEntry>::ListType;
|
||||
private:
|
||||
os::SdkMutex mutex;
|
||||
KeySlotCacheEntryList high_priority_mru_list;
|
||||
KeySlotCacheEntryList low_priority_mru_list;
|
||||
os::SdkMutex m_mutex;
|
||||
KeySlotCacheEntryList m_high_priority_mru_list;
|
||||
KeySlotCacheEntryList m_low_priority_mru_list;
|
||||
public:
|
||||
constexpr KeySlotCache() : mutex(), high_priority_mru_list(), low_priority_mru_list() { /* ... */ }
|
||||
constexpr KeySlotCache() : m_mutex(), m_high_priority_mru_list(), m_low_priority_mru_list() { /* ... */ }
|
||||
|
||||
Result AllocateHighPriority(std::unique_ptr<KeySlotCacheAccessor> *out, const void *key, size_t key_size, s32 key2) {
|
||||
return this->AllocateFromLru(out, this->high_priority_mru_list, key, key_size, key2);
|
||||
return this->AllocateFromLru(out, m_high_priority_mru_list, key, key_size, key2);
|
||||
}
|
||||
|
||||
Result AllocateLowPriority(std::unique_ptr<KeySlotCacheAccessor> *out, const void *key, size_t key_size, s32 key2) {
|
||||
return this->AllocateFromLru(out, this->high_priority_mru_list, key, key_size, key2);
|
||||
return this->AllocateFromLru(out, m_high_priority_mru_list, key, key_size, key2);
|
||||
}
|
||||
|
||||
Result Find(std::unique_ptr<KeySlotCacheAccessor> *out, const void *key, size_t key_size, s32 key2) {
|
||||
util::unique_lock lk(this->mutex);
|
||||
util::unique_lock lk(m_mutex);
|
||||
|
||||
KeySlotCacheEntryList *lists[2] = { std::addressof(this->high_priority_mru_list), std::addressof(this->low_priority_mru_list) };
|
||||
KeySlotCacheEntryList *lists[2] = { std::addressof(m_high_priority_mru_list), std::addressof(m_low_priority_mru_list) };
|
||||
for (auto list : lists) {
|
||||
for (auto it = list->begin(); it != list->end(); ++it) {
|
||||
if (it->Contains(key, key_size, key2)) {
|
||||
@@ -102,14 +102,14 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
void AddEntry(KeySlotCacheEntry *entry) {
|
||||
util::unique_lock lk(this->mutex);
|
||||
this->low_priority_mru_list.push_front(*entry);
|
||||
util::unique_lock lk(m_mutex);
|
||||
m_low_priority_mru_list.push_front(*entry);
|
||||
}
|
||||
private:
|
||||
Result AllocateFromLru(std::unique_ptr<KeySlotCacheAccessor> *out, KeySlotCacheEntryList &dst_list, const void *key, size_t key_size, s32 key2) {
|
||||
util::unique_lock lk(this->mutex);
|
||||
util::unique_lock lk(m_mutex);
|
||||
|
||||
KeySlotCacheEntryList &src_list = this->low_priority_mru_list.empty() ? this->high_priority_mru_list : this->low_priority_mru_list;
|
||||
KeySlotCacheEntryList &src_list = m_low_priority_mru_list.empty() ? m_high_priority_mru_list : m_low_priority_mru_list;
|
||||
AMS_ASSERT(!src_list.empty());
|
||||
|
||||
auto it = src_list.rbegin();
|
||||
|
||||
@@ -27,26 +27,26 @@ namespace ams::fssystem {
|
||||
NON_COPYABLE(Node);
|
||||
NON_MOVEABLE(Node);
|
||||
public:
|
||||
Key key;
|
||||
Value value;
|
||||
util::IntrusiveListNode mru_list_node;
|
||||
Key m_key;
|
||||
Value m_value;
|
||||
util::IntrusiveListNode m_mru_list_node;
|
||||
public:
|
||||
explicit Node(const Value &value) : value(value) { /* ... */ }
|
||||
explicit Node(const Value &value) : m_value(value) { /* ... */ }
|
||||
};
|
||||
private:
|
||||
using MruList = typename util::IntrusiveListMemberTraits<&Node::mru_list_node>::ListType;
|
||||
using MruList = typename util::IntrusiveListMemberTraits<&Node::m_mru_list_node>::ListType;
|
||||
private:
|
||||
MruList mru_list;
|
||||
MruList m_mru_list;
|
||||
public:
|
||||
constexpr LruListCache() : mru_list() { /* ... */ }
|
||||
constexpr LruListCache() : m_mru_list() { /* ... */ }
|
||||
|
||||
bool FindValueAndUpdateMru(Value *out, const Key &key) {
|
||||
for (auto it = this->mru_list.begin(); it != this->mru_list.end(); ++it) {
|
||||
if (it->key == key) {
|
||||
*out = it->value;
|
||||
for (auto it = m_mru_list.begin(); it != m_mru_list.end(); ++it) {
|
||||
if (it->m_key == key) {
|
||||
*out = it->m_value;
|
||||
|
||||
this->mru_list.erase(it);
|
||||
this->mru_list.push_front(*it);
|
||||
m_mru_list.erase(it);
|
||||
m_mru_list.push_front(*it);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -56,33 +56,33 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
std::unique_ptr<Node> PopLruNode() {
|
||||
AMS_ABORT_UNLESS(!this->mru_list.empty());
|
||||
Node *lru = std::addressof(*this->mru_list.rbegin());
|
||||
this->mru_list.pop_back();
|
||||
AMS_ABORT_UNLESS(!m_mru_list.empty());
|
||||
Node *lru = std::addressof(*m_mru_list.rbegin());
|
||||
m_mru_list.pop_back();
|
||||
|
||||
return std::unique_ptr<Node>(lru);
|
||||
}
|
||||
|
||||
void PushMruNode(std::unique_ptr<Node> &&node, const Key &key) {
|
||||
node->key = key;
|
||||
this->mru_list.push_front(*node);
|
||||
node->m_key = key;
|
||||
m_mru_list.push_front(*node);
|
||||
node.release();
|
||||
}
|
||||
|
||||
void DeleteAllNodes() {
|
||||
while (!this->mru_list.empty()) {
|
||||
Node *lru = std::addressof(*this->mru_list.rbegin());
|
||||
this->mru_list.erase(this->mru_list.iterator_to(*lru));
|
||||
while (!m_mru_list.empty()) {
|
||||
Node *lru = std::addressof(*m_mru_list.rbegin());
|
||||
m_mru_list.erase(m_mru_list.iterator_to(*lru));
|
||||
delete lru;
|
||||
}
|
||||
}
|
||||
|
||||
size_t GetSize() const {
|
||||
return this->mru_list.size();
|
||||
return m_mru_list.size();
|
||||
}
|
||||
|
||||
bool IsEmpty() const {
|
||||
return this->mru_list.empty();
|
||||
return m_mru_list.empty();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -33,38 +33,38 @@ namespace ams::fssystem {
|
||||
class BufferHolder {
|
||||
NON_COPYABLE(BufferHolder);
|
||||
private:
|
||||
MemoryResource *allocator;
|
||||
char *buffer;
|
||||
size_t buffer_size;
|
||||
MemoryResource *m_allocator;
|
||||
char *m_buffer;
|
||||
size_t m_buffer_size;
|
||||
public:
|
||||
BufferHolder() : allocator(), buffer(), buffer_size() { /* ... */ }
|
||||
BufferHolder(MemoryResource *a, size_t sz) : allocator(a), buffer(static_cast<char *>(a->Allocate(sz))), buffer_size(sz) { /* ... */ }
|
||||
BufferHolder() : m_allocator(), m_buffer(), m_buffer_size() { /* ... */ }
|
||||
BufferHolder(MemoryResource *a, size_t sz) : m_allocator(a), m_buffer(static_cast<char *>(a->Allocate(sz))), m_buffer_size(sz) { /* ... */ }
|
||||
~BufferHolder() {
|
||||
if (this->buffer != nullptr) {
|
||||
this->allocator->Deallocate(this->buffer, this->buffer_size);
|
||||
this->buffer = nullptr;
|
||||
if (m_buffer != nullptr) {
|
||||
m_allocator->Deallocate(m_buffer, m_buffer_size);
|
||||
m_buffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
BufferHolder(BufferHolder &&rhs) : allocator(rhs.allocator), buffer(rhs.buffer), buffer_size(rhs.buffer_size) {
|
||||
rhs.buffer = nullptr;
|
||||
BufferHolder(BufferHolder &&rhs) : m_allocator(rhs.m_allocator), m_buffer(rhs.m_buffer), m_buffer_size(rhs.m_buffer_size) {
|
||||
rhs.m_buffer = nullptr;
|
||||
}
|
||||
|
||||
BufferHolder &operator=(BufferHolder &&rhs) {
|
||||
if (this != std::addressof(rhs)) {
|
||||
AMS_ASSERT(this->buffer == nullptr);
|
||||
this->allocator = rhs.allocator;
|
||||
this->buffer = rhs.buffer;
|
||||
this->buffer_size = rhs.buffer_size;
|
||||
AMS_ASSERT(m_buffer == nullptr);
|
||||
m_allocator = rhs.m_allocator;
|
||||
m_buffer = rhs.m_buffer;
|
||||
m_buffer_size = rhs.m_buffer_size;
|
||||
|
||||
rhs.buffer = nullptr;
|
||||
rhs.m_buffer = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool IsValid() const { return this->buffer != nullptr; }
|
||||
char *Get() const { return this->buffer; }
|
||||
size_t GetSize() const { return this->buffer_size; }
|
||||
bool IsValid() const { return m_buffer != nullptr; }
|
||||
char *Get() const { return m_buffer; }
|
||||
size_t GetSize() const { return m_buffer_size; }
|
||||
};
|
||||
|
||||
template<typename Base, typename Sequence>
|
||||
@@ -79,24 +79,24 @@ namespace ams::fssystem {
|
||||
template<size_t N>
|
||||
using IndexedStoragePointer = StoragePointer;
|
||||
private:
|
||||
std::shared_ptr<NcaReader> nca_reader;
|
||||
std::array<StoragePointer, sizeof...(Is)> storages;
|
||||
std::shared_ptr<NcaReader> m_nca_reader;
|
||||
std::array<StoragePointer, sizeof...(Is)> m_storages;
|
||||
private:
|
||||
|
||||
template<size_t N>
|
||||
void SetImpl(IndexedStoragePointer<N> &&ptr) {
|
||||
static_assert(N < sizeof...(Is));
|
||||
this->storages[N] = std::move(ptr);
|
||||
m_storages[N] = std::move(ptr);
|
||||
}
|
||||
public:
|
||||
DerivedStorageHolderImpl() : Base(), nca_reader(), storages() { /* ... */ }
|
||||
explicit DerivedStorageHolderImpl(std::shared_ptr<NcaReader> nr) : Base(), nca_reader(nr), storages() { /* ... */ }
|
||||
DerivedStorageHolderImpl() : Base(), m_nca_reader(), m_storages() { /* ... */ }
|
||||
explicit DerivedStorageHolderImpl(std::shared_ptr<NcaReader> nr) : Base(), m_nca_reader(nr), m_storages() { /* ... */ }
|
||||
|
||||
#define DEFINE_CONSTRUCTORS(n) \
|
||||
template<AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS##n (T)> \
|
||||
explicit DerivedStorageHolderImpl(AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS##n (T, t)) : Base(AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS##n (T, t)), nca_reader(), storages() { /* ... */ } \
|
||||
template<AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS##n (T)> \
|
||||
explicit DerivedStorageHolderImpl(AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS##n (T, t), std::shared_ptr<NcaReader> nr) : Base(AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS##n (T, t)), nca_reader(nr), storages() { /* ... */ }
|
||||
#define DEFINE_CONSTRUCTORS(n) \
|
||||
template<AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS##n (T)> \
|
||||
explicit DerivedStorageHolderImpl(AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS##n (T, t)) : Base(AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS##n (T, t)), m_nca_reader(), m_storages() { /* ... */ } \
|
||||
template<AMS_UTIL_VARIADIC_TEMPLATE_PARAMETERS##n (T)> \
|
||||
explicit DerivedStorageHolderImpl(AMS_UTIL_VARIADIC_TEMPLATE_ARGUMENTS##n (T, t), std::shared_ptr<NcaReader> nr) : Base(AMS_UTIL_VARIADIC_TEMPLATE_FORWARDS##n (T, t)), m_nca_reader(nr), m_storages() { /* ... */ }
|
||||
|
||||
AMS_UTIL_VARIADIC_INVOKE_MACRO(DEFINE_CONSTRUCTORS)
|
||||
|
||||
@@ -116,17 +116,17 @@ namespace ams::fssystem {
|
||||
private:
|
||||
using BaseHolder = DerivedStorageHolder<Base, N>;
|
||||
private:
|
||||
BufferHolder buffer;
|
||||
BufferHolder m_buffer;
|
||||
public:
|
||||
DerivedStorageHolderWithBuffer() : BaseHolder(), buffer() { /* ... */ }
|
||||
DerivedStorageHolderWithBuffer() : BaseHolder(), m_buffer() { /* ... */ }
|
||||
|
||||
template<typename... Args>
|
||||
DerivedStorageHolderWithBuffer(Args &&... args) : BaseHolder(std::forward<Args>(args)...), buffer() { /* ... */ }
|
||||
DerivedStorageHolderWithBuffer(Args &&... args) : BaseHolder(std::forward<Args>(args)...), m_buffer() { /* ... */ }
|
||||
|
||||
using BaseHolder::Set;
|
||||
|
||||
void Set(BufferHolder &&buf) {
|
||||
this->buffer = std::move(buf);
|
||||
m_buffer = std::move(buf);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -138,21 +138,21 @@ namespace ams::fssystem {
|
||||
static constexpr size_t KeySize = crypto::Aes128CtrEncryptor::KeySize;
|
||||
static constexpr size_t IvSize = crypto::Aes128CtrEncryptor::IvSize;
|
||||
private:
|
||||
IStorage * const base_storage;
|
||||
u8 iv[IvSize];
|
||||
DecryptAesCtrFunction decrypt_function;
|
||||
s32 key_index;
|
||||
u8 encrypted_key[KeySize];
|
||||
IStorage * const m_base_storage;
|
||||
u8 m_iv[IvSize];
|
||||
DecryptAesCtrFunction m_decrypt_function;
|
||||
s32 m_key_index;
|
||||
u8 m_encrypted_key[KeySize];
|
||||
public:
|
||||
AesCtrStorageExternal(fs::IStorage *bs, const void *enc_key, size_t enc_key_size, const void *iv, size_t iv_size, DecryptAesCtrFunction df, s32 kidx) : base_storage(bs), decrypt_function(df), key_index(kidx) {
|
||||
AesCtrStorageExternal(fs::IStorage *bs, const void *enc_key, size_t enc_key_size, const void *iv, size_t iv_size, DecryptAesCtrFunction df, s32 kidx) : m_base_storage(bs), m_decrypt_function(df), m_key_index(kidx) {
|
||||
AMS_ASSERT(bs != nullptr);
|
||||
AMS_ASSERT(enc_key_size == KeySize);
|
||||
AMS_ASSERT(iv != nullptr);
|
||||
AMS_ASSERT(iv_size == IvSize);
|
||||
AMS_UNUSED(iv_size);
|
||||
|
||||
std::memcpy(this->iv, iv, IvSize);
|
||||
std::memcpy(this->encrypted_key, enc_key, enc_key_size);
|
||||
std::memcpy(m_iv, iv, IvSize);
|
||||
std::memcpy(m_encrypted_key, enc_key, enc_key_size);
|
||||
}
|
||||
|
||||
virtual Result Read(s64 offset, void *buffer, size_t size) override {
|
||||
@@ -166,7 +166,7 @@ namespace ams::fssystem {
|
||||
R_UNLESS(util::IsAligned(size, BlockSize), fs::ResultInvalidArgument());
|
||||
|
||||
/* Read the data. */
|
||||
R_TRY(this->base_storage->Read(offset, buffer, size));
|
||||
R_TRY(m_base_storage->Read(offset, buffer, size));
|
||||
|
||||
/* Temporarily increase our thread priority. */
|
||||
ScopedThreadPriorityChanger cp(+1, ScopedThreadPriorityChanger::Mode::Relative);
|
||||
@@ -178,7 +178,7 @@ namespace ams::fssystem {
|
||||
|
||||
/* Setup the counter. */
|
||||
u8 ctr[IvSize];
|
||||
std::memcpy(ctr, this->iv, IvSize);
|
||||
std::memcpy(ctr, m_iv, IvSize);
|
||||
AddCounter(ctr, IvSize, offset / BlockSize);
|
||||
|
||||
/* Setup tracking. */
|
||||
@@ -191,7 +191,7 @@ namespace ams::fssystem {
|
||||
char *dst = static_cast<char *>(buffer) + cur_offset;
|
||||
|
||||
/* Decrypt into the temporary buffer */
|
||||
this->decrypt_function(pooled_buffer.GetBuffer(), cur_size, this->key_index, this->encrypted_key, KeySize, ctr, IvSize, dst, cur_size);
|
||||
m_decrypt_function(pooled_buffer.GetBuffer(), cur_size, m_key_index, m_encrypted_key, KeySize, ctr, IvSize, dst, cur_size);
|
||||
|
||||
/* Copy to the destination. */
|
||||
std::memcpy(dst, pooled_buffer.GetBuffer(), cur_size);
|
||||
@@ -216,12 +216,12 @@ namespace ams::fssystem {
|
||||
R_UNLESS(dst_size == sizeof(fs::QueryRangeInfo), fs::ResultInvalidSize());
|
||||
|
||||
/* Operate on our base storage. */
|
||||
R_TRY(this->base_storage->OperateRange(dst, dst_size, op_id, offset, size, src, src_size));
|
||||
R_TRY(m_base_storage->OperateRange(dst, dst_size, op_id, offset, size, src, src_size));
|
||||
|
||||
/* Add in new flags. */
|
||||
fs::QueryRangeInfo new_info;
|
||||
new_info.Clear();
|
||||
new_info.aes_ctr_key_type = static_cast<s32>(this->key_index >= 0 ? fs::AesCtrKeyTypeFlag::InternalKeyForHardwareAes : fs::AesCtrKeyTypeFlag::ExternalKeyForHardwareAes);
|
||||
new_info.aes_ctr_key_type = static_cast<s32>(m_key_index >= 0 ? fs::AesCtrKeyTypeFlag::InternalKeyForHardwareAes : fs::AesCtrKeyTypeFlag::ExternalKeyForHardwareAes);
|
||||
|
||||
/* Merge the new info in. */
|
||||
reinterpret_cast<fs::QueryRangeInfo *>(dst)->Merge(new_info);
|
||||
@@ -230,14 +230,14 @@ namespace ams::fssystem {
|
||||
default:
|
||||
{
|
||||
/* Operate on our base storage. */
|
||||
R_TRY(this->base_storage->OperateRange(dst, dst_size, op_id, offset, size, src, src_size));
|
||||
R_TRY(m_base_storage->OperateRange(dst, dst_size, op_id, offset, size, src, src_size));
|
||||
return ResultSuccess();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual Result GetSize(s64 *out) override {
|
||||
return this->base_storage->GetSize(out);
|
||||
return m_base_storage->GetSize(out);
|
||||
}
|
||||
|
||||
virtual Result Flush() override {
|
||||
@@ -260,15 +260,15 @@ namespace ams::fssystem {
|
||||
NON_COPYABLE(SwitchStorage);
|
||||
NON_MOVEABLE(SwitchStorage);
|
||||
private:
|
||||
std::unique_ptr<fs::IStorage> true_storage;
|
||||
std::unique_ptr<fs::IStorage> false_storage;
|
||||
F truth_function;
|
||||
std::unique_ptr<fs::IStorage> m_true_storage;
|
||||
std::unique_ptr<fs::IStorage> m_false_storage;
|
||||
F m_truth_function;
|
||||
private:
|
||||
ALWAYS_INLINE std::unique_ptr<fs::IStorage> &SelectStorage() {
|
||||
return this->truth_function() ? this->true_storage : this->false_storage;
|
||||
return m_truth_function() ? m_true_storage : m_false_storage;
|
||||
}
|
||||
public:
|
||||
SwitchStorage(std::unique_ptr<fs::IStorage> &&t, std::unique_ptr<fs::IStorage> &&f, F func) : true_storage(std::move(t)), false_storage(std::move(f)), truth_function(func) { /* ... */ }
|
||||
SwitchStorage(std::unique_ptr<fs::IStorage> &&t, std::unique_ptr<fs::IStorage> &&f, F func) : m_true_storage(std::move(t)), m_false_storage(std::move(f)), m_truth_function(func) { /* ... */ }
|
||||
|
||||
virtual Result Read(s64 offset, void *buffer, size_t size) override {
|
||||
return this->SelectStorage()->Read(offset, buffer, size);
|
||||
@@ -278,8 +278,8 @@ namespace ams::fssystem {
|
||||
switch (op_id) {
|
||||
case fs::OperationId::Invalidate:
|
||||
{
|
||||
R_TRY(this->true_storage->OperateRange(dst, dst_size, op_id, offset, size, src, src_size));
|
||||
R_TRY(this->false_storage->OperateRange(dst, dst_size, op_id, offset, size, src, src_size));
|
||||
R_TRY(m_true_storage->OperateRange(dst, dst_size, op_id, offset, size, src, src_size));
|
||||
R_TRY(m_false_storage->OperateRange(dst, dst_size, op_id, offset, size, src, src_size));
|
||||
return ResultSuccess();
|
||||
}
|
||||
case fs::OperationId::QueryRange:
|
||||
@@ -344,15 +344,15 @@ namespace ams::fssystem {
|
||||
/* Validate preconditions. */
|
||||
AMS_ASSERT(out != nullptr);
|
||||
AMS_ASSERT(0 <= fs_index && fs_index < NcaHeader::FsCountMax);
|
||||
AMS_ASSERT(this->reader != nullptr);
|
||||
AMS_ASSERT(m_reader != nullptr);
|
||||
|
||||
/* Get storage extents. */
|
||||
const auto storage_offset = GetFsOffset(*this->reader, fs_index);
|
||||
const auto storage_size = GetFsEndOffset(*this->reader, fs_index) - storage_offset;
|
||||
const auto storage_offset = GetFsOffset(*m_reader, fs_index);
|
||||
const auto storage_size = GetFsEndOffset(*m_reader, fs_index) - storage_offset;
|
||||
R_UNLESS(storage_size > 0, fs::ResultInvalidNcaHeader());
|
||||
|
||||
/* Allocate a substorage. */
|
||||
*out = AllocateShared<DerivedStorageHolder<fs::SubStorage, 0>>(this->reader->GetBodyStorage(), storage_offset, storage_size, this->reader);
|
||||
*out = AllocateShared<DerivedStorageHolder<fs::SubStorage, 0>>(m_reader->GetBodyStorage(), storage_offset, storage_size, m_reader);
|
||||
R_UNLESS(*out != nullptr, fs::ResultAllocationFailureInAllocateShared());
|
||||
|
||||
return ResultSuccess();
|
||||
@@ -375,15 +375,15 @@ namespace ams::fssystem {
|
||||
/* Validate preconditions. */
|
||||
AMS_ASSERT(out != nullptr);
|
||||
AMS_ASSERT(option != nullptr);
|
||||
AMS_ASSERT(this->reader != nullptr);
|
||||
AMS_ASSERT(m_reader != nullptr);
|
||||
|
||||
/* Get and validate fs index. */
|
||||
const auto fs_index = option->GetFsIndex();
|
||||
R_UNLESS(this->reader->HasFsInfo(fs_index), fs::ResultPartitionNotFound());
|
||||
R_UNLESS(m_reader->HasFsInfo(fs_index), fs::ResultPartitionNotFound());
|
||||
|
||||
/* Initialize a reader for the fs header. */
|
||||
auto &header_reader = option->GetHeaderReader();
|
||||
R_TRY(header_reader.Initialize(*this->reader, fs_index));
|
||||
R_TRY(header_reader.Initialize(*m_reader, fs_index));
|
||||
|
||||
/* Create the storage. */
|
||||
std::unique_ptr<fs::IStorage> storage;
|
||||
@@ -404,16 +404,16 @@ namespace ams::fssystem {
|
||||
/* Validate preconditions. */
|
||||
AMS_ASSERT(out != nullptr);
|
||||
AMS_ASSERT(option != nullptr);
|
||||
AMS_ASSERT(this->reader != nullptr);
|
||||
AMS_ASSERT(m_reader != nullptr);
|
||||
|
||||
/* Get and validate fs index. */
|
||||
const auto fs_index = option->GetFsIndex();
|
||||
R_UNLESS(this->reader->HasFsInfo(fs_index), fs::ResultPartitionNotFound());
|
||||
R_UNLESS(m_reader->HasFsInfo(fs_index), fs::ResultPartitionNotFound());
|
||||
|
||||
/* Initialize a reader for the fs header. */
|
||||
auto &header_reader = option->GetHeaderReader();
|
||||
if (!header_reader.IsInitialized()) {
|
||||
R_TRY(header_reader.Initialize(*this->reader, fs_index));
|
||||
R_TRY(header_reader.Initialize(*m_reader, fs_index));
|
||||
}
|
||||
|
||||
/* Create the storage. */
|
||||
@@ -476,8 +476,8 @@ namespace ams::fssystem {
|
||||
const auto &header_reader = option->GetHeaderReader();
|
||||
|
||||
/* Get storage extents. */
|
||||
const auto storage_offset = GetFsOffset(*this->reader, fs_index);
|
||||
const auto storage_size = GetFsEndOffset(*this->reader, fs_index) - storage_offset;
|
||||
const auto storage_offset = GetFsOffset(*m_reader, fs_index);
|
||||
const auto storage_size = GetFsEndOffset(*m_reader, fs_index) - storage_offset;
|
||||
R_UNLESS(storage_size > 0, fs::ResultInvalidNcaHeader());
|
||||
|
||||
/* Set up the sparse storage if we need to, otherwise use body storage directly. */
|
||||
@@ -490,7 +490,7 @@ namespace ams::fssystem {
|
||||
R_TRY(header.Verify());
|
||||
|
||||
/* Create a new holder for the storages. */
|
||||
std::unique_ptr storage = std::make_unique<DerivedStorageHolder<SparseStorage, 2>>(this->reader);
|
||||
std::unique_ptr storage = std::make_unique<DerivedStorageHolder<SparseStorage, 2>>(m_reader);
|
||||
R_UNLESS(storage != nullptr, fs::ResultAllocationFailureInNew());
|
||||
|
||||
/* If there are no entries, there's nothing to actually do. */
|
||||
@@ -498,7 +498,7 @@ namespace ams::fssystem {
|
||||
storage->Initialize(storage_size);
|
||||
} else {
|
||||
/* Prepare to create the decryptable storage. */
|
||||
const auto raw_storage = this->reader->GetBodyStorage();
|
||||
const auto raw_storage = m_reader->GetBodyStorage();
|
||||
const auto raw_storage_offset = sparse_info.physical_offset;
|
||||
const auto raw_storage_size = sparse_info.GetPhysicalSize();
|
||||
|
||||
@@ -521,7 +521,7 @@ namespace ams::fssystem {
|
||||
R_UNLESS(table_storage != nullptr, fs::ResultAllocationFailureInNew());
|
||||
|
||||
/* Initialize the table storage. */
|
||||
R_TRY(table_storage->Initialize(fs::SubStorage(decryptable_storage.get(), 0, raw_storage_size), this->buffer_manager, SparseTableCacheBlockSize, SparseTableCacheCount));
|
||||
R_TRY(table_storage->Initialize(fs::SubStorage(decryptable_storage.get(), 0, raw_storage_size), m_buffer_manager, SparseTableCacheBlockSize, SparseTableCacheCount));
|
||||
|
||||
/* Determine storage extents. */
|
||||
const auto node_offset = sparse_info.bucket.offset;
|
||||
@@ -530,7 +530,7 @@ namespace ams::fssystem {
|
||||
const auto entry_size = SparseStorage::QueryEntryStorageSize(header.entry_count);
|
||||
|
||||
/* Initialize the storage. */
|
||||
R_TRY(storage->Initialize(this->allocator, fs::SubStorage(table_storage.get(), node_offset, node_size), fs::SubStorage(table_storage.get(), entry_offset, entry_size), header.entry_count));
|
||||
R_TRY(storage->Initialize(m_allocator, fs::SubStorage(table_storage.get(), node_offset, node_size), fs::SubStorage(table_storage.get(), entry_offset, entry_size), header.entry_count));
|
||||
|
||||
/* Set the data/decryptable storage. */
|
||||
storage->SetDataStorage(raw_storage, raw_storage_offset, node_offset);
|
||||
@@ -545,11 +545,11 @@ namespace ams::fssystem {
|
||||
} else {
|
||||
/* Validate that we're within range. */
|
||||
s64 body_storage_size;
|
||||
R_TRY(this->reader->GetBodyStorage()->GetSize(std::addressof(body_storage_size)));
|
||||
R_TRY(m_reader->GetBodyStorage()->GetSize(std::addressof(body_storage_size)));
|
||||
R_UNLESS(storage_offset + storage_size <= body_storage_size, fs::ResultNcaBaseStorageOutOfRangeB());
|
||||
|
||||
/* Set the out storage. */
|
||||
out->SetStorage(this->reader->GetBodyStorage(), storage_offset, storage_size);
|
||||
out->SetStorage(m_reader->GetBodyStorage(), storage_offset, storage_size);
|
||||
}
|
||||
|
||||
/* Set the crypto variables. */
|
||||
@@ -604,13 +604,13 @@ namespace ams::fssystem {
|
||||
R_UNLESS(raw_storage != nullptr, fs::ResultAllocationFailureInNew());
|
||||
|
||||
/* Make the aes xts storage. */
|
||||
const auto *key1 = this->reader->GetDecryptionKey(NcaHeader::DecryptionKey_AesXts1);
|
||||
const auto *key2 = this->reader->GetDecryptionKey(NcaHeader::DecryptionKey_AesXts2);
|
||||
const auto *key1 = m_reader->GetDecryptionKey(NcaHeader::DecryptionKey_AesXts1);
|
||||
const auto *key2 = m_reader->GetDecryptionKey(NcaHeader::DecryptionKey_AesXts2);
|
||||
std::unique_ptr xts_storage = std::make_unique<AesXtsStorage>(raw_storage.get(), key1, key2, AesXtsStorage::KeySize, iv, AesXtsStorage::IvSize, NcaHeader::XtsBlockSize);
|
||||
R_UNLESS(xts_storage != nullptr, fs::ResultAllocationFailureInNew());
|
||||
|
||||
/* Make the out storage. */
|
||||
std::unique_ptr storage = std::make_unique<DerivedStorageHolder<AlignmentMatchingStorage<NcaHeader::XtsBlockSize, 1>, 2>>(xts_storage.get(), this->reader);
|
||||
std::unique_ptr storage = std::make_unique<DerivedStorageHolder<AlignmentMatchingStorage<NcaHeader::XtsBlockSize, 1>, 2>>(xts_storage.get(), m_reader);
|
||||
R_UNLESS(storage != nullptr, fs::ResultAllocationFailureInNew());
|
||||
|
||||
/* Set the substorages. */
|
||||
@@ -634,22 +634,22 @@ namespace ams::fssystem {
|
||||
std::unique_ptr raw_storage = base_storage->MakeStorage();
|
||||
|
||||
/* Create the decrypt storage. */
|
||||
const bool has_external_key = reader->HasExternalDecryptionKey();
|
||||
const bool has_external_key = m_reader->HasExternalDecryptionKey();
|
||||
std::unique_ptr<fs::IStorage> decrypt_storage;
|
||||
if (has_external_key) {
|
||||
decrypt_storage = std::make_unique<AesCtrStorageExternal>(raw_storage.get(), this->reader->GetExternalDecryptionKey(), AesCtrStorageExternal::KeySize, iv, AesCtrStorageExternal::IvSize, this->reader->GetExternalDecryptAesCtrFunctionForExternalKey(), -1);
|
||||
decrypt_storage = std::make_unique<AesCtrStorageExternal>(raw_storage.get(), m_reader->GetExternalDecryptionKey(), AesCtrStorageExternal::KeySize, iv, AesCtrStorageExternal::IvSize, m_reader->GetExternalDecryptAesCtrFunctionForExternalKey(), -1);
|
||||
R_UNLESS(decrypt_storage != nullptr, fs::ResultAllocationFailureInNew());
|
||||
} else {
|
||||
/* Check if we have a hardware key. */
|
||||
const bool has_hardware_key = this->reader->HasInternalDecryptionKeyForAesHardwareSpeedEmulation();
|
||||
const bool has_hardware_key = m_reader->HasInternalDecryptionKeyForAesHardwareSpeedEmulation();
|
||||
|
||||
/* Create the software decryption storage. */
|
||||
std::unique_ptr<fs::IStorage> aes_ctr_sw_storage = std::make_unique<AesCtrStorage>(raw_storage.get(), this->reader->GetDecryptionKey(NcaHeader::DecryptionKey_AesCtr), AesCtrStorage::KeySize, iv, AesCtrStorage::IvSize);
|
||||
std::unique_ptr<fs::IStorage> aes_ctr_sw_storage = std::make_unique<AesCtrStorage>(raw_storage.get(), m_reader->GetDecryptionKey(NcaHeader::DecryptionKey_AesCtr), AesCtrStorage::KeySize, iv, AesCtrStorage::IvSize);
|
||||
R_UNLESS(aes_ctr_sw_storage != nullptr, fs::ResultAllocationFailureInNew());
|
||||
|
||||
/* If we have a hardware key and should use it, make the hardware decryption storage. */
|
||||
if (has_hardware_key && !this->reader->IsSoftwareAesPrioritized()) {
|
||||
std::unique_ptr<fs::IStorage> aes_ctr_hw_storage = std::make_unique<AesCtrStorageExternal>(raw_storage.get(), this->reader->GetDecryptionKey(NcaHeader::DecryptionKey_AesCtrHw), AesCtrStorageExternal::KeySize, iv, AesCtrStorageExternal::IvSize, this->reader->GetExternalDecryptAesCtrFunction(), GetKeyTypeValue(this->reader->GetKeyIndex(), this->reader->GetKeyGeneration()));
|
||||
if (has_hardware_key && !m_reader->IsSoftwareAesPrioritized()) {
|
||||
std::unique_ptr<fs::IStorage> aes_ctr_hw_storage = std::make_unique<AesCtrStorageExternal>(raw_storage.get(), m_reader->GetDecryptionKey(NcaHeader::DecryptionKey_AesCtrHw), AesCtrStorageExternal::KeySize, iv, AesCtrStorageExternal::IvSize, m_reader->GetExternalDecryptAesCtrFunction(), GetKeyTypeValue(m_reader->GetKeyIndex(), m_reader->GetKeyGeneration()));
|
||||
R_UNLESS(aes_ctr_hw_storage != nullptr, fs::ResultAllocationFailureInNew());
|
||||
|
||||
/* Create the selection storage. */
|
||||
@@ -662,7 +662,7 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
/* Create the storage holder. */
|
||||
std::unique_ptr storage = std::make_unique<DerivedStorageHolder<AlignmentMatchingStorage<NcaHeader::CtrBlockSize, 1>, 2>>(decrypt_storage.get(), this->reader);
|
||||
std::unique_ptr storage = std::make_unique<DerivedStorageHolder<AlignmentMatchingStorage<NcaHeader::CtrBlockSize, 1>, 2>>(decrypt_storage.get(), m_reader);
|
||||
R_UNLESS(storage != nullptr, fs::ResultAllocationFailureInNew());
|
||||
|
||||
/* Set the storage holder's storages. */
|
||||
@@ -716,7 +716,7 @@ namespace ams::fssystem {
|
||||
R_UNLESS(buffered_storage != nullptr, fs::ResultAllocationFailureInNew());
|
||||
|
||||
/* Initialize the buffered storage. */
|
||||
R_TRY(buffered_storage->Initialize(fs::SubStorage(table_storage.get(), 0, table_size), this->buffer_manager, AesCtrExTableCacheBlockSize, AesCtrExTableCacheCount));
|
||||
R_TRY(buffered_storage->Initialize(fs::SubStorage(table_storage.get(), 0, table_size), m_buffer_manager, AesCtrExTableCacheBlockSize, AesCtrExTableCacheCount));
|
||||
|
||||
/* Create an aligned storage for the buffered storage. */
|
||||
using AlignedStorage = AlignmentMatchingStorage<NcaHeader::CtrBlockSize, 1>;
|
||||
@@ -742,18 +742,18 @@ namespace ams::fssystem {
|
||||
|
||||
/* Create the aes ctr ex storage. */
|
||||
std::unique_ptr<fs::IStorage> aes_ctr_ex_storage;
|
||||
const bool has_external_key = this->reader->HasExternalDecryptionKey();
|
||||
const bool has_external_key = m_reader->HasExternalDecryptionKey();
|
||||
if (has_external_key) {
|
||||
/* Create the decryptor. */
|
||||
std::unique_ptr<AesCtrCounterExtendedStorage::IDecryptor> decryptor;
|
||||
R_TRY(AesCtrCounterExtendedStorage::CreateExternalDecryptor(std::addressof(decryptor), this->reader->GetExternalDecryptAesCtrFunctionForExternalKey(), -1));
|
||||
R_TRY(AesCtrCounterExtendedStorage::CreateExternalDecryptor(std::addressof(decryptor), m_reader->GetExternalDecryptAesCtrFunctionForExternalKey(), -1));
|
||||
|
||||
/* Create the aes ctr ex storage. */
|
||||
std::unique_ptr impl_storage = std::make_unique<AesCtrCounterExtendedStorage>();
|
||||
R_UNLESS(impl_storage != nullptr, fs::ResultAllocationFailureInNew());
|
||||
|
||||
/* Initialize the aes ctr ex storage. */
|
||||
R_TRY(impl_storage->Initialize(this->allocator, this->reader->GetExternalDecryptionKey(), AesCtrStorage::KeySize, secure_value, base_storage_offset, data_storage, node_storage, entry_storage, entry_count, std::move(decryptor)));
|
||||
R_TRY(impl_storage->Initialize(m_allocator, m_reader->GetExternalDecryptionKey(), AesCtrStorage::KeySize, secure_value, base_storage_offset, data_storage, node_storage, entry_storage, entry_count, std::move(decryptor)));
|
||||
|
||||
/* Set the option's aes ctr ex storage. */
|
||||
option->SetAesCtrExStorageRaw(impl_storage.get());
|
||||
@@ -761,7 +761,7 @@ namespace ams::fssystem {
|
||||
aes_ctr_ex_storage = std::move(impl_storage);
|
||||
} else {
|
||||
/* Check if we have a hardware key. */
|
||||
const bool has_hardware_key = this->reader->HasInternalDecryptionKeyForAesHardwareSpeedEmulation();
|
||||
const bool has_hardware_key = m_reader->HasInternalDecryptionKeyForAesHardwareSpeedEmulation();
|
||||
|
||||
/* Create the software decryptor. */
|
||||
std::unique_ptr<AesCtrCounterExtendedStorage::IDecryptor> sw_decryptor;
|
||||
@@ -772,23 +772,23 @@ namespace ams::fssystem {
|
||||
R_UNLESS(sw_storage != nullptr, fs::ResultAllocationFailureInNew());
|
||||
|
||||
/* Initialize the software storage. */
|
||||
R_TRY(sw_storage->Initialize(this->allocator, this->reader->GetDecryptionKey(NcaHeader::DecryptionKey_AesCtr), AesCtrStorage::KeySize, secure_value, base_storage_offset, data_storage, node_storage, entry_storage, entry_count, std::move(sw_decryptor)));
|
||||
R_TRY(sw_storage->Initialize(m_allocator, m_reader->GetDecryptionKey(NcaHeader::DecryptionKey_AesCtr), AesCtrStorage::KeySize, secure_value, base_storage_offset, data_storage, node_storage, entry_storage, entry_count, std::move(sw_decryptor)));
|
||||
|
||||
/* Set the option's aes ctr ex storage. */
|
||||
option->SetAesCtrExStorageRaw(sw_storage.get());
|
||||
|
||||
/* If we have a hardware key and should use it, make the hardware decryption storage. */
|
||||
if (has_hardware_key && !this->reader->IsSoftwareAesPrioritized()) {
|
||||
if (has_hardware_key && !m_reader->IsSoftwareAesPrioritized()) {
|
||||
/* Create the hardware decryptor. */
|
||||
std::unique_ptr<AesCtrCounterExtendedStorage::IDecryptor> hw_decryptor;
|
||||
R_TRY(AesCtrCounterExtendedStorage::CreateExternalDecryptor(std::addressof(hw_decryptor), this->reader->GetExternalDecryptAesCtrFunction(), GetKeyTypeValue(this->reader->GetKeyIndex(), this->reader->GetKeyGeneration())));
|
||||
R_TRY(AesCtrCounterExtendedStorage::CreateExternalDecryptor(std::addressof(hw_decryptor), m_reader->GetExternalDecryptAesCtrFunction(), GetKeyTypeValue(m_reader->GetKeyIndex(), m_reader->GetKeyGeneration())));
|
||||
|
||||
/* Create the hardware storage. */
|
||||
std::unique_ptr hw_storage = std::make_unique<AesCtrCounterExtendedStorage>();
|
||||
R_UNLESS(hw_storage != nullptr, fs::ResultAllocationFailureInNew());
|
||||
|
||||
/* Initialize the hardware storage. */
|
||||
R_TRY(hw_storage->Initialize(this->allocator, this->reader->GetDecryptionKey(NcaHeader::DecryptionKey_AesCtrHw), AesCtrStorage::KeySize, secure_value, base_storage_offset, data_storage, node_storage, entry_storage, entry_count, std::move(hw_decryptor)));
|
||||
R_TRY(hw_storage->Initialize(m_allocator, m_reader->GetDecryptionKey(NcaHeader::DecryptionKey_AesCtrHw), AesCtrStorage::KeySize, secure_value, base_storage_offset, data_storage, node_storage, entry_storage, entry_count, std::move(hw_decryptor)));
|
||||
|
||||
/* Create the selection storage. */
|
||||
std::unique_ptr switch_storage = std::make_unique<SwitchStorage<bool (*)()>>(std::move(hw_storage), std::move(sw_storage), IsUsingHardwareAesCtrForSpeedEmulation);
|
||||
@@ -803,7 +803,7 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
/* Create the storage holder. */
|
||||
std::unique_ptr storage = std::make_unique<DerivedStorageHolder<AlignedStorage, 5>>(aes_ctr_ex_storage.get(), this->reader);
|
||||
std::unique_ptr storage = std::make_unique<DerivedStorageHolder<AlignedStorage, 5>>(aes_ctr_ex_storage.get(), m_reader);
|
||||
R_UNLESS(storage != nullptr, fs::ResultAllocationFailureInNew());
|
||||
|
||||
/* Set the aes ctr ex storages in the option. */
|
||||
@@ -848,11 +848,11 @@ namespace ams::fssystem {
|
||||
{
|
||||
const s32 fs_index = header_reader.GetFsIndex();
|
||||
|
||||
if (this->original_reader != nullptr && this->original_reader->HasFsInfo(fs_index)) {
|
||||
if (m_original_reader != nullptr && m_original_reader->HasFsInfo(fs_index)) {
|
||||
NcaFsHeaderReader original_header_reader;
|
||||
R_TRY(original_header_reader.Initialize(*this->original_reader, fs_index));
|
||||
R_TRY(original_header_reader.Initialize(*m_original_reader, fs_index));
|
||||
|
||||
NcaFileSystemDriver original_driver(this->original_reader, this->allocator, this->buffer_manager);
|
||||
NcaFileSystemDriver original_driver(m_original_reader, m_allocator, m_buffer_manager);
|
||||
StorageOption original_option(std::addressof(original_header_reader), fs_index);
|
||||
|
||||
BaseStorage original_base_storage;
|
||||
@@ -877,21 +877,21 @@ namespace ams::fssystem {
|
||||
R_UNLESS(indirect_table_storage != nullptr, fs::ResultAllocationFailureInNew());
|
||||
|
||||
/* Initialize the indirect table storage. */
|
||||
R_TRY(indirect_table_storage->Initialize(fs::SubStorage(base_storage.get(), indirect_data_size, node_size + entry_size), this->buffer_manager, IndirectTableCacheBlockSize, IndirectTableCacheCount));
|
||||
R_TRY(indirect_table_storage->Initialize(fs::SubStorage(base_storage.get(), indirect_data_size, node_size + entry_size), m_buffer_manager, IndirectTableCacheBlockSize, IndirectTableCacheCount));
|
||||
|
||||
/* Create the indirect data storage. */
|
||||
std::unique_ptr indirect_data_storage = std::make_unique<save::BufferedStorage>();
|
||||
R_UNLESS(indirect_data_storage != nullptr, fs::ResultAllocationFailureInNew());
|
||||
|
||||
/* Initialize the indirect data storage. */
|
||||
R_TRY(indirect_data_storage->Initialize(fs::SubStorage(base_storage.get(), 0, indirect_data_size), this->buffer_manager, IndirectDataCacheBlockSize, IndirectDataCacheCount));
|
||||
R_TRY(indirect_data_storage->Initialize(fs::SubStorage(base_storage.get(), 0, indirect_data_size), m_buffer_manager, IndirectDataCacheBlockSize, IndirectDataCacheCount));
|
||||
|
||||
/* Create the storage holder. */
|
||||
std::unique_ptr storage = std::make_unique<DerivedStorageHolder<IndirectStorage, 4>>(this->reader);
|
||||
std::unique_ptr storage = std::make_unique<DerivedStorageHolder<IndirectStorage, 4>>(m_reader);
|
||||
R_UNLESS(storage != nullptr, fs::ResultAllocationFailureInNew());
|
||||
|
||||
/* Initialize the storage holder. */
|
||||
R_TRY(storage->Initialize(this->allocator, fs::SubStorage(indirect_table_storage.get(), 0, node_size), fs::SubStorage(indirect_table_storage.get(), node_size, entry_size), header.entry_count));
|
||||
R_TRY(storage->Initialize(m_allocator, fs::SubStorage(indirect_table_storage.get(), 0, node_size), fs::SubStorage(indirect_table_storage.get(), node_size, entry_size), header.entry_count));
|
||||
|
||||
/* Set the storage holder's storages. */
|
||||
storage->SetStorage(0, original_storage.get(), 0, original_data_size);
|
||||
@@ -955,7 +955,7 @@ namespace ams::fssystem {
|
||||
const auto total_buffer_size = hash_buffer_size + cache_buffer_size;
|
||||
|
||||
/* Make a buffer holder. */
|
||||
BufferHolder buffer_holder(this->allocator, total_buffer_size);
|
||||
BufferHolder buffer_holder(m_allocator, total_buffer_size);
|
||||
R_UNLESS(buffer_holder.IsValid(), fs::ResultAllocationFailureInNcaFileSystemDriverI());
|
||||
|
||||
/* Make the data storage. */
|
||||
@@ -983,7 +983,7 @@ namespace ams::fssystem {
|
||||
R_UNLESS(cache_storage != nullptr, fs::ResultAllocationFailureInNew());
|
||||
|
||||
/* Make the storage holder. */
|
||||
std::unique_ptr storage = std::make_unique<StorageHolder>(cache_storage.get(), hash_data.hash_block_size, this->reader);
|
||||
std::unique_ptr storage = std::make_unique<StorageHolder>(cache_storage.get(), hash_data.hash_block_size, m_reader);
|
||||
R_UNLESS(storage != nullptr, fs::ResultAllocationFailureInNew());
|
||||
|
||||
/* Set the storage holder's data. */
|
||||
@@ -1026,11 +1026,11 @@ namespace ams::fssystem {
|
||||
storage_info.SetDataStorage(fs::SubStorage(base_storage.get(), layer_info.offset, layer_info.size));
|
||||
|
||||
/* Make the storage holder. */
|
||||
std::unique_ptr storage = std::make_unique<StorageHolder>(this->reader);
|
||||
std::unique_ptr storage = std::make_unique<StorageHolder>(m_reader);
|
||||
R_UNLESS(storage != nullptr, fs::ResultAllocationFailureInNew());
|
||||
|
||||
/* Initialize the integrity storage. */
|
||||
R_TRY(storage->Initialize(level_hash_info, hash_data.master_hash, storage_info, this->buffer_manager));
|
||||
R_TRY(storage->Initialize(level_hash_info, hash_data.master_hash, storage_info, m_buffer_manager));
|
||||
|
||||
/* Set the storage holder's data. */
|
||||
storage->Set(std::move(base_storage));
|
||||
|
||||
@@ -35,10 +35,10 @@ namespace ams::fssystem {
|
||||
|
||||
}
|
||||
|
||||
NcaReader::NcaReader() : shared_base_storage(), header_storage(), body_storage(), decrypt_aes_ctr(), decrypt_aes_ctr_external(), is_software_aes_prioritized(false), header_encryption_type(NcaHeader::EncryptionType::Auto) {
|
||||
std::memset(std::addressof(this->header), 0, sizeof(this->header));
|
||||
std::memset(std::addressof(this->decryption_keys), 0, sizeof(this->decryption_keys));
|
||||
std::memset(std::addressof(this->external_decryption_key), 0, sizeof(this->external_decryption_key));
|
||||
NcaReader::NcaReader() : m_shared_base_storage(), m_header_storage(), m_body_storage(), m_decrypt_aes_ctr(), m_decrypt_aes_ctr_external(), m_is_software_aes_prioritized(false), m_header_encryption_type(NcaHeader::EncryptionType::Auto) {
|
||||
std::memset(std::addressof(m_header), 0, sizeof(m_header));
|
||||
std::memset(std::addressof(m_decryption_keys), 0, sizeof(m_decryption_keys));
|
||||
std::memset(std::addressof(m_external_decryption_key), 0, sizeof(m_external_decryption_key));
|
||||
}
|
||||
|
||||
NcaReader::~NcaReader() {
|
||||
@@ -46,14 +46,14 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
Result NcaReader::Initialize(std::shared_ptr<fs::IStorage> base_storage, const NcaCryptoConfiguration &crypto_cfg) {
|
||||
this->shared_base_storage = base_storage;
|
||||
return this->Initialize(this->shared_base_storage.get(), crypto_cfg);
|
||||
m_shared_base_storage = base_storage;
|
||||
return this->Initialize(m_shared_base_storage.get(), crypto_cfg);
|
||||
}
|
||||
|
||||
Result NcaReader::Initialize(fs::IStorage *base_storage, const NcaCryptoConfiguration &crypto_cfg) {
|
||||
/* Validate preconditions. */
|
||||
AMS_ASSERT(base_storage != nullptr);
|
||||
AMS_ASSERT(this->body_storage == nullptr);
|
||||
AMS_ASSERT(m_body_storage == nullptr);
|
||||
R_UNLESS(crypto_cfg.generate_key != nullptr, fs::ResultInvalidArgument());
|
||||
|
||||
/* Generate keys for header. */
|
||||
@@ -68,16 +68,16 @@ namespace ams::fssystem {
|
||||
R_UNLESS(work_header_storage != nullptr, fs::ResultAllocationFailureInNcaReaderA());
|
||||
|
||||
/* Read the header. */
|
||||
R_TRY(work_header_storage->Read(0, std::addressof(this->header), sizeof(this->header)));
|
||||
R_TRY(work_header_storage->Read(0, std::addressof(m_header), sizeof(m_header)));
|
||||
|
||||
/* Validate the magic. */
|
||||
if (Result magic_result = CheckNcaMagic(this->header.magic); R_FAILED(magic_result)) {
|
||||
if (Result magic_result = CheckNcaMagic(m_header.magic); R_FAILED(magic_result)) {
|
||||
/* If we're not allowed to use plaintext headers, stop here. */
|
||||
R_UNLESS(crypto_cfg.is_plaintext_header_available, magic_result);
|
||||
|
||||
/* Try to use a plaintext header. */
|
||||
R_TRY(base_storage->Read(0, std::addressof(this->header), sizeof(this->header)));
|
||||
R_UNLESS(R_SUCCEEDED(CheckNcaMagic(this->header.magic)), magic_result);
|
||||
R_TRY(base_storage->Read(0, std::addressof(m_header), sizeof(m_header)));
|
||||
R_UNLESS(R_SUCCEEDED(CheckNcaMagic(m_header.magic)), magic_result);
|
||||
|
||||
/* Configure to use the plaintext header. */
|
||||
s64 base_storage_size;
|
||||
@@ -85,103 +85,103 @@ namespace ams::fssystem {
|
||||
work_header_storage.reset(new fs::SubStorage(base_storage, 0, base_storage_size));
|
||||
R_UNLESS(work_header_storage != nullptr, fs::ResultAllocationFailureInNcaReaderA());
|
||||
|
||||
this->header_encryption_type = NcaHeader::EncryptionType::None;
|
||||
m_header_encryption_type = NcaHeader::EncryptionType::None;
|
||||
}
|
||||
|
||||
/* Validate the fixed key signature. */
|
||||
R_UNLESS(this->header.header1_signature_key_generation <= NcaCryptoConfiguration::Header1SignatureKeyGenerationMax, fs::ResultInvalidNcaHeader1SignatureKeyGeneration());
|
||||
const u8 *header_1_sign_key_modulus = crypto_cfg.header_1_sign_key_moduli[this->header.header1_signature_key_generation];
|
||||
R_UNLESS(m_header.header1_signature_key_generation <= NcaCryptoConfiguration::Header1SignatureKeyGenerationMax, fs::ResultInvalidNcaHeader1SignatureKeyGeneration());
|
||||
const u8 *header_1_sign_key_modulus = crypto_cfg.header_1_sign_key_moduli[m_header.header1_signature_key_generation];
|
||||
AMS_ABORT_UNLESS(header_1_sign_key_modulus != nullptr);
|
||||
{
|
||||
const u8 *sig = this->header.header_sign_1;
|
||||
const u8 *sig = m_header.header_sign_1;
|
||||
const size_t sig_size = NcaHeader::HeaderSignSize;
|
||||
const u8 *mod = header_1_sign_key_modulus;
|
||||
const size_t mod_size = NcaCryptoConfiguration::Rsa2048KeyModulusSize;
|
||||
const u8 *exp = crypto_cfg.header_1_sign_key_public_exponent;
|
||||
const size_t exp_size = NcaCryptoConfiguration::Rsa2048KeyPublicExponentSize;
|
||||
const u8 *msg = static_cast<const u8 *>(static_cast<const void *>(std::addressof(this->header.magic)));
|
||||
const u8 *msg = static_cast<const u8 *>(static_cast<const void *>(std::addressof(m_header.magic)));
|
||||
const size_t msg_size = NcaHeader::Size - NcaHeader::HeaderSignSize * NcaHeader::HeaderSignCount;
|
||||
const bool is_signature_valid = crypto::VerifyRsa2048PssSha256(sig, sig_size, mod, mod_size, exp, exp_size, msg, msg_size);
|
||||
R_UNLESS(is_signature_valid, fs::ResultNcaHeaderSignature1VerificationFailed());
|
||||
}
|
||||
|
||||
/* Validate the sdk version. */
|
||||
R_UNLESS(this->header.sdk_addon_version >= SdkAddonVersionMin, fs::ResultUnsupportedSdkVersion());
|
||||
R_UNLESS(m_header.sdk_addon_version >= SdkAddonVersionMin, fs::ResultUnsupportedSdkVersion());
|
||||
|
||||
/* Validate the key index. */
|
||||
R_UNLESS(this->header.key_index < NcaCryptoConfiguration::KeyAreaEncryptionKeyIndexCount, fs::ResultInvalidNcaKeyIndex());
|
||||
R_UNLESS(m_header.key_index < NcaCryptoConfiguration::KeyAreaEncryptionKeyIndexCount, fs::ResultInvalidNcaKeyIndex());
|
||||
|
||||
/* Check if we have a rights id. */
|
||||
constexpr const u8 ZeroRightsId[NcaHeader::RightsIdSize] = {};
|
||||
if (crypto::IsSameBytes(ZeroRightsId, this->header.rights_id, NcaHeader::RightsIdSize)) {
|
||||
if (crypto::IsSameBytes(ZeroRightsId, m_header.rights_id, NcaHeader::RightsIdSize)) {
|
||||
/* If we do, then we don't have an external key, so we need to generate decryption keys. */
|
||||
crypto_cfg.generate_key(this->decryption_keys[NcaHeader::DecryptionKey_AesCtr], crypto::AesDecryptor128::KeySize, this->header.encrypted_key_area + NcaHeader::DecryptionKey_AesCtr * crypto::AesDecryptor128::KeySize, crypto::AesDecryptor128::KeySize, GetKeyTypeValue(this->header.key_index, this->header.GetProperKeyGeneration()), crypto_cfg);
|
||||
crypto_cfg.generate_key(m_decryption_keys[NcaHeader::DecryptionKey_AesCtr], crypto::AesDecryptor128::KeySize, m_header.encrypted_key_area + NcaHeader::DecryptionKey_AesCtr * crypto::AesDecryptor128::KeySize, crypto::AesDecryptor128::KeySize, GetKeyTypeValue(m_header.key_index, m_header.GetProperKeyGeneration()), crypto_cfg);
|
||||
|
||||
/* Copy the hardware speed emulation key. */
|
||||
std::memcpy(this->decryption_keys[NcaHeader::DecryptionKey_AesCtrHw], this->header.encrypted_key_area + NcaHeader::DecryptionKey_AesCtrHw * crypto::AesDecryptor128::KeySize, crypto::AesDecryptor128::KeySize);
|
||||
std::memcpy(m_decryption_keys[NcaHeader::DecryptionKey_AesCtrHw], m_header.encrypted_key_area + NcaHeader::DecryptionKey_AesCtrHw * crypto::AesDecryptor128::KeySize, crypto::AesDecryptor128::KeySize);
|
||||
}
|
||||
|
||||
/* Clear the external decryption key. */
|
||||
std::memset(this->external_decryption_key, 0, sizeof(this->external_decryption_key));
|
||||
std::memset(m_external_decryption_key, 0, sizeof(m_external_decryption_key));
|
||||
|
||||
/* Set our decryptor functions. */
|
||||
this->decrypt_aes_ctr = crypto_cfg.decrypt_aes_ctr;
|
||||
this->decrypt_aes_ctr_external = crypto_cfg.decrypt_aes_ctr_external;
|
||||
m_decrypt_aes_ctr = crypto_cfg.decrypt_aes_ctr;
|
||||
m_decrypt_aes_ctr_external = crypto_cfg.decrypt_aes_ctr_external;
|
||||
|
||||
/* Set our storages. */
|
||||
this->header_storage = std::move(work_header_storage);
|
||||
this->body_storage = base_storage;
|
||||
m_header_storage = std::move(work_header_storage);
|
||||
m_body_storage = base_storage;
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
fs::IStorage *NcaReader::GetBodyStorage() {
|
||||
return this->body_storage;
|
||||
return m_body_storage;
|
||||
}
|
||||
|
||||
u32 NcaReader::GetMagic() const {
|
||||
AMS_ASSERT(this->body_storage != nullptr);
|
||||
return this->header.magic;
|
||||
AMS_ASSERT(m_body_storage != nullptr);
|
||||
return m_header.magic;
|
||||
}
|
||||
|
||||
NcaHeader::DistributionType NcaReader::GetDistributionType() const {
|
||||
AMS_ASSERT(this->body_storage != nullptr);
|
||||
return this->header.distribution_type;
|
||||
AMS_ASSERT(m_body_storage != nullptr);
|
||||
return m_header.distribution_type;
|
||||
}
|
||||
|
||||
NcaHeader::ContentType NcaReader::GetContentType() const {
|
||||
AMS_ASSERT(this->body_storage != nullptr);
|
||||
return this->header.content_type;
|
||||
AMS_ASSERT(m_body_storage != nullptr);
|
||||
return m_header.content_type;
|
||||
}
|
||||
|
||||
u8 NcaReader::GetKeyGeneration() const {
|
||||
AMS_ASSERT(this->body_storage != nullptr);
|
||||
return this->header.GetProperKeyGeneration();
|
||||
AMS_ASSERT(m_body_storage != nullptr);
|
||||
return m_header.GetProperKeyGeneration();
|
||||
}
|
||||
|
||||
u8 NcaReader::GetKeyIndex() const {
|
||||
AMS_ASSERT(this->body_storage != nullptr);
|
||||
return this->header.key_index;
|
||||
AMS_ASSERT(m_body_storage != nullptr);
|
||||
return m_header.key_index;
|
||||
}
|
||||
|
||||
u64 NcaReader::GetContentSize() const {
|
||||
AMS_ASSERT(this->body_storage != nullptr);
|
||||
return this->header.content_size;
|
||||
AMS_ASSERT(m_body_storage != nullptr);
|
||||
return m_header.content_size;
|
||||
}
|
||||
|
||||
u64 NcaReader::GetProgramId() const {
|
||||
AMS_ASSERT(this->body_storage != nullptr);
|
||||
return this->header.program_id;
|
||||
AMS_ASSERT(m_body_storage != nullptr);
|
||||
return m_header.program_id;
|
||||
}
|
||||
|
||||
u32 NcaReader::GetContentIndex() const {
|
||||
AMS_ASSERT(this->body_storage != nullptr);
|
||||
return this->header.content_index;
|
||||
AMS_ASSERT(m_body_storage != nullptr);
|
||||
return m_header.content_index;
|
||||
}
|
||||
|
||||
u32 NcaReader::GetSdkAddonVersion() const {
|
||||
AMS_ASSERT(this->body_storage != nullptr);
|
||||
return this->header.sdk_addon_version;
|
||||
AMS_ASSERT(m_body_storage != nullptr);
|
||||
return m_header.sdk_addon_version;
|
||||
}
|
||||
|
||||
void NcaReader::GetRightsId(u8 *dst, size_t dst_size) const {
|
||||
@@ -189,16 +189,16 @@ namespace ams::fssystem {
|
||||
AMS_ASSERT(dst_size >= NcaHeader::RightsIdSize);
|
||||
AMS_UNUSED(dst_size);
|
||||
|
||||
std::memcpy(dst, this->header.rights_id, NcaHeader::RightsIdSize);
|
||||
std::memcpy(dst, m_header.rights_id, NcaHeader::RightsIdSize);
|
||||
}
|
||||
|
||||
bool NcaReader::HasFsInfo(s32 index) const {
|
||||
AMS_ASSERT(0 <= index && index < NcaHeader::FsCountMax);
|
||||
return this->header.fs_info[index].start_sector != 0 || this->header.fs_info[index].end_sector != 0;
|
||||
return m_header.fs_info[index].start_sector != 0 || m_header.fs_info[index].end_sector != 0;
|
||||
}
|
||||
|
||||
s32 NcaReader::GetFsCount() const {
|
||||
AMS_ASSERT(this->body_storage != nullptr);
|
||||
AMS_ASSERT(m_body_storage != nullptr);
|
||||
for (s32 i = 0; i < NcaHeader::FsCountMax; i++) {
|
||||
if (!this->HasFsInfo(i)) {
|
||||
return i;
|
||||
@@ -208,62 +208,62 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
const Hash &NcaReader::GetFsHeaderHash(s32 index) const {
|
||||
AMS_ASSERT(this->body_storage != nullptr);
|
||||
AMS_ASSERT(m_body_storage != nullptr);
|
||||
AMS_ASSERT(0 <= index && index < NcaHeader::FsCountMax);
|
||||
return this->header.fs_header_hash[index];
|
||||
return m_header.fs_header_hash[index];
|
||||
}
|
||||
|
||||
void NcaReader::GetFsHeaderHash(Hash *dst, s32 index) const {
|
||||
AMS_ASSERT(this->body_storage != nullptr);
|
||||
AMS_ASSERT(m_body_storage != nullptr);
|
||||
AMS_ASSERT(0 <= index && index < NcaHeader::FsCountMax);
|
||||
AMS_ASSERT(dst != nullptr);
|
||||
std::memcpy(dst, std::addressof(this->header.fs_header_hash[index]), sizeof(*dst));
|
||||
std::memcpy(dst, std::addressof(m_header.fs_header_hash[index]), sizeof(*dst));
|
||||
}
|
||||
|
||||
void NcaReader::GetFsInfo(NcaHeader::FsInfo *dst, s32 index) const {
|
||||
AMS_ASSERT(this->body_storage != nullptr);
|
||||
AMS_ASSERT(m_body_storage != nullptr);
|
||||
AMS_ASSERT(0 <= index && index < NcaHeader::FsCountMax);
|
||||
AMS_ASSERT(dst != nullptr);
|
||||
std::memcpy(dst, std::addressof(this->header.fs_info[index]), sizeof(*dst));
|
||||
std::memcpy(dst, std::addressof(m_header.fs_info[index]), sizeof(*dst));
|
||||
}
|
||||
|
||||
u64 NcaReader::GetFsOffset(s32 index) const {
|
||||
AMS_ASSERT(this->body_storage != nullptr);
|
||||
AMS_ASSERT(m_body_storage != nullptr);
|
||||
AMS_ASSERT(0 <= index && index < NcaHeader::FsCountMax);
|
||||
return NcaHeader::SectorToByte(this->header.fs_info[index].start_sector);
|
||||
return NcaHeader::SectorToByte(m_header.fs_info[index].start_sector);
|
||||
}
|
||||
|
||||
u64 NcaReader::GetFsEndOffset(s32 index) const {
|
||||
AMS_ASSERT(this->body_storage != nullptr);
|
||||
AMS_ASSERT(m_body_storage != nullptr);
|
||||
AMS_ASSERT(0 <= index && index < NcaHeader::FsCountMax);
|
||||
return NcaHeader::SectorToByte(this->header.fs_info[index].end_sector);
|
||||
return NcaHeader::SectorToByte(m_header.fs_info[index].end_sector);
|
||||
}
|
||||
|
||||
u64 NcaReader::GetFsSize(s32 index) const {
|
||||
AMS_ASSERT(this->body_storage != nullptr);
|
||||
AMS_ASSERT(m_body_storage != nullptr);
|
||||
AMS_ASSERT(0 <= index && index < NcaHeader::FsCountMax);
|
||||
return NcaHeader::SectorToByte(this->header.fs_info[index].end_sector - this->header.fs_info[index].start_sector);
|
||||
return NcaHeader::SectorToByte(m_header.fs_info[index].end_sector - m_header.fs_info[index].start_sector);
|
||||
}
|
||||
|
||||
void NcaReader::GetEncryptedKey(void *dst, size_t size) const {
|
||||
AMS_ASSERT(this->body_storage != nullptr);
|
||||
AMS_ASSERT(m_body_storage != nullptr);
|
||||
AMS_ASSERT(dst != nullptr);
|
||||
AMS_ASSERT(size >= NcaHeader::EncryptedKeyAreaSize);
|
||||
AMS_UNUSED(size);
|
||||
|
||||
std::memcpy(dst, this->header.encrypted_key_area, NcaHeader::EncryptedKeyAreaSize);
|
||||
std::memcpy(dst, m_header.encrypted_key_area, NcaHeader::EncryptedKeyAreaSize);
|
||||
}
|
||||
|
||||
const void *NcaReader::GetDecryptionKey(s32 index) const {
|
||||
AMS_ASSERT(this->body_storage != nullptr);
|
||||
AMS_ASSERT(m_body_storage != nullptr);
|
||||
AMS_ASSERT(0 <= index && index < NcaHeader::DecryptionKey_Count);
|
||||
return this->decryption_keys[index];
|
||||
return m_decryption_keys[index];
|
||||
}
|
||||
|
||||
bool NcaReader::HasValidInternalKey() const {
|
||||
constexpr const u8 ZeroKey[crypto::AesDecryptor128::KeySize] = {};
|
||||
for (s32 i = 0; i < NcaHeader::DecryptionKey_Count; i++) {
|
||||
if (!crypto::IsSameBytes(ZeroKey, this->header.encrypted_key_area + i * crypto::AesDecryptor128::KeySize, crypto::AesDecryptor128::KeySize)) {
|
||||
if (!crypto::IsSameBytes(ZeroKey, m_header.encrypted_key_area + i * crypto::AesDecryptor128::KeySize, crypto::AesDecryptor128::KeySize)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -276,11 +276,11 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
bool NcaReader::IsSoftwareAesPrioritized() const {
|
||||
return this->is_software_aes_prioritized;
|
||||
return m_is_software_aes_prioritized;
|
||||
}
|
||||
|
||||
void NcaReader::PrioritizeSoftwareAes() {
|
||||
this->is_software_aes_prioritized = true;
|
||||
m_is_software_aes_prioritized = true;
|
||||
}
|
||||
|
||||
bool NcaReader::HasExternalDecryptionKey() const {
|
||||
@@ -289,38 +289,38 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
const void *NcaReader::GetExternalDecryptionKey() const {
|
||||
return this->external_decryption_key;
|
||||
return m_external_decryption_key;
|
||||
}
|
||||
|
||||
void NcaReader::SetExternalDecryptionKey(const void *src, size_t size) {
|
||||
AMS_ASSERT(src != nullptr);
|
||||
AMS_ASSERT(size == sizeof(this->external_decryption_key));
|
||||
AMS_ASSERT(size == sizeof(m_external_decryption_key));
|
||||
AMS_UNUSED(size);
|
||||
|
||||
std::memcpy(this->external_decryption_key, src, sizeof(this->external_decryption_key));
|
||||
std::memcpy(m_external_decryption_key, src, sizeof(m_external_decryption_key));
|
||||
}
|
||||
|
||||
void NcaReader::GetRawData(void *dst, size_t dst_size) const {
|
||||
AMS_ASSERT(this->body_storage != nullptr);
|
||||
AMS_ASSERT(m_body_storage != nullptr);
|
||||
AMS_ASSERT(dst != nullptr);
|
||||
AMS_ASSERT(dst_size >= sizeof(NcaHeader));
|
||||
AMS_UNUSED(dst_size);
|
||||
|
||||
std::memcpy(dst, std::addressof(this->header), sizeof(NcaHeader));
|
||||
std::memcpy(dst, std::addressof(m_header), sizeof(NcaHeader));
|
||||
}
|
||||
|
||||
DecryptAesCtrFunction NcaReader::GetExternalDecryptAesCtrFunction() const {
|
||||
AMS_ASSERT(this->decrypt_aes_ctr != nullptr);
|
||||
return this->decrypt_aes_ctr;
|
||||
AMS_ASSERT(m_decrypt_aes_ctr != nullptr);
|
||||
return m_decrypt_aes_ctr;
|
||||
}
|
||||
|
||||
DecryptAesCtrFunction NcaReader::GetExternalDecryptAesCtrFunctionForExternalKey() const {
|
||||
AMS_ASSERT(this->decrypt_aes_ctr_external != nullptr);
|
||||
return this->decrypt_aes_ctr_external;
|
||||
AMS_ASSERT(m_decrypt_aes_ctr_external != nullptr);
|
||||
return m_decrypt_aes_ctr_external;
|
||||
}
|
||||
|
||||
NcaHeader::EncryptionType NcaReader::GetEncryptionType() const {
|
||||
return this->header_encryption_type;
|
||||
return m_header_encryption_type;
|
||||
}
|
||||
|
||||
Result NcaReader::ReadHeader(NcaFsHeader *dst, s32 index) const {
|
||||
@@ -328,18 +328,18 @@ namespace ams::fssystem {
|
||||
AMS_ASSERT(0 <= index && index < NcaHeader::FsCountMax);
|
||||
|
||||
const s64 offset = sizeof(NcaHeader) + sizeof(NcaFsHeader) * index;
|
||||
return this->header_storage->Read(offset, dst, sizeof(NcaFsHeader));
|
||||
return m_header_storage->Read(offset, dst, sizeof(NcaFsHeader));
|
||||
}
|
||||
|
||||
Result NcaReader::VerifyHeaderSign2(const void *mod, size_t mod_size) {
|
||||
AMS_ASSERT(this->body_storage != nullptr);
|
||||
AMS_ASSERT(m_body_storage != nullptr);
|
||||
constexpr const u8 HeaderSign2KeyPublicExponent[] = { 0x01, 0x00, 0x01 };
|
||||
|
||||
const u8 *sig = this->header.header_sign_2;
|
||||
const u8 *sig = m_header.header_sign_2;
|
||||
const size_t sig_size = NcaHeader::HeaderSignSize;
|
||||
const u8 *exp = HeaderSign2KeyPublicExponent;
|
||||
const size_t exp_size = sizeof(HeaderSign2KeyPublicExponent);
|
||||
const u8 *msg = static_cast<const u8 *>(static_cast<const void *>(std::addressof(this->header.magic)));
|
||||
const u8 *msg = static_cast<const u8 *>(static_cast<const void *>(std::addressof(m_header.magic)));
|
||||
const size_t msg_size = NcaHeader::Size - NcaHeader::HeaderSignSize * NcaHeader::HeaderSignCount;
|
||||
const bool is_signature_valid = crypto::VerifyRsa2048PssSha256(sig, sig_size, mod, mod_size, exp, exp_size, msg, msg_size);
|
||||
R_UNLESS(is_signature_valid, fs::ResultNcaHeaderSignature2VerificationFailed());
|
||||
@@ -349,20 +349,20 @@ namespace ams::fssystem {
|
||||
|
||||
Result NcaFsHeaderReader::Initialize(const NcaReader &reader, s32 index) {
|
||||
/* Reset ourselves to uninitialized. */
|
||||
this->fs_index = -1;
|
||||
m_fs_index = -1;
|
||||
|
||||
/* Read the header. */
|
||||
R_TRY(reader.ReadHeader(std::addressof(this->data), index));
|
||||
R_TRY(reader.ReadHeader(std::addressof(m_data), index));
|
||||
|
||||
/* Generate the hash. */
|
||||
Hash hash;
|
||||
crypto::GenerateSha256Hash(std::addressof(hash), sizeof(hash), std::addressof(this->data), sizeof(NcaFsHeader));
|
||||
crypto::GenerateSha256Hash(std::addressof(hash), sizeof(hash), std::addressof(m_data), sizeof(NcaFsHeader));
|
||||
|
||||
/* Validate the hash. */
|
||||
R_UNLESS(crypto::IsSameBytes(std::addressof(reader.GetFsHeaderHash(index)), std::addressof(hash), sizeof(Hash)), fs::ResultNcaFsHeaderHashVerificationFailed());
|
||||
|
||||
/* Set our index. */
|
||||
this->fs_index = index;
|
||||
m_fs_index = index;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
@@ -372,72 +372,72 @@ namespace ams::fssystem {
|
||||
AMS_ASSERT(dst_size >= sizeof(NcaFsHeader));
|
||||
AMS_UNUSED(dst_size);
|
||||
|
||||
std::memcpy(dst, std::addressof(this->data), sizeof(NcaFsHeader));
|
||||
std::memcpy(dst, std::addressof(m_data), sizeof(NcaFsHeader));
|
||||
}
|
||||
|
||||
NcaFsHeader::HashData &NcaFsHeaderReader::GetHashData() {
|
||||
AMS_ASSERT(this->IsInitialized());
|
||||
return this->data.hash_data;
|
||||
return m_data.hash_data;
|
||||
}
|
||||
|
||||
const NcaFsHeader::HashData &NcaFsHeaderReader::GetHashData() const {
|
||||
AMS_ASSERT(this->IsInitialized());
|
||||
return this->data.hash_data;
|
||||
return m_data.hash_data;
|
||||
}
|
||||
|
||||
u16 NcaFsHeaderReader::GetVersion() const {
|
||||
AMS_ASSERT(this->IsInitialized());
|
||||
return this->data.version;
|
||||
return m_data.version;
|
||||
}
|
||||
|
||||
s32 NcaFsHeaderReader::GetFsIndex() const {
|
||||
AMS_ASSERT(this->IsInitialized());
|
||||
return this->fs_index;
|
||||
return m_fs_index;
|
||||
}
|
||||
|
||||
NcaFsHeader::FsType NcaFsHeaderReader::GetFsType() const {
|
||||
AMS_ASSERT(this->IsInitialized());
|
||||
return this->data.fs_type;
|
||||
return m_data.fs_type;
|
||||
}
|
||||
|
||||
NcaFsHeader::HashType NcaFsHeaderReader::GetHashType() const {
|
||||
AMS_ASSERT(this->IsInitialized());
|
||||
return this->data.hash_type;
|
||||
return m_data.hash_type;
|
||||
}
|
||||
|
||||
NcaFsHeader::EncryptionType NcaFsHeaderReader::GetEncryptionType() const {
|
||||
AMS_ASSERT(this->IsInitialized());
|
||||
return this->data.encryption_type;
|
||||
return m_data.encryption_type;
|
||||
}
|
||||
|
||||
NcaPatchInfo &NcaFsHeaderReader::GetPatchInfo() {
|
||||
AMS_ASSERT(this->IsInitialized());
|
||||
return this->data.patch_info;
|
||||
return m_data.patch_info;
|
||||
}
|
||||
|
||||
const NcaPatchInfo &NcaFsHeaderReader::GetPatchInfo() const {
|
||||
AMS_ASSERT(this->IsInitialized());
|
||||
return this->data.patch_info;
|
||||
return m_data.patch_info;
|
||||
}
|
||||
|
||||
const NcaAesCtrUpperIv NcaFsHeaderReader::GetAesCtrUpperIv() const {
|
||||
AMS_ASSERT(this->IsInitialized());
|
||||
return this->data.aes_ctr_upper_iv;
|
||||
return m_data.aes_ctr_upper_iv;
|
||||
}
|
||||
|
||||
bool NcaFsHeaderReader::ExistsSparseLayer() const {
|
||||
AMS_ASSERT(this->IsInitialized());
|
||||
return this->data.sparse_info.generation != 0;
|
||||
return m_data.sparse_info.generation != 0;
|
||||
}
|
||||
|
||||
NcaSparseInfo &NcaFsHeaderReader::GetSparseInfo() {
|
||||
AMS_ASSERT(this->IsInitialized());
|
||||
return this->data.sparse_info;
|
||||
return m_data.sparse_info;
|
||||
}
|
||||
|
||||
const NcaSparseInfo &NcaFsHeaderReader::GetSparseInfo() const {
|
||||
AMS_ASSERT(this->IsInitialized());
|
||||
return this->data.sparse_info;
|
||||
return m_data.sparse_info;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -43,46 +43,46 @@ namespace ams::fssystem {
|
||||
template <typename MetaType>
|
||||
class PartitionFileSystemCore<MetaType>::PartitionFile : public fs::fsa::IFile, public fs::impl::Newable {
|
||||
private:
|
||||
const typename MetaType::PartitionEntry *partition_entry;
|
||||
const PartitionFileSystemCore<MetaType> *parent;
|
||||
const fs::OpenMode mode;
|
||||
const typename MetaType::PartitionEntry *m_partition_entry;
|
||||
const PartitionFileSystemCore<MetaType> *m_parent;
|
||||
const fs::OpenMode m_mode;
|
||||
public:
|
||||
PartitionFile(PartitionFileSystemCore<MetaType> *parent, const typename MetaType::PartitionEntry *partition_entry, fs::OpenMode mode) : partition_entry(partition_entry), parent(parent), mode(mode) { /* ... */ }
|
||||
PartitionFile(PartitionFileSystemCore<MetaType> *parent, const typename MetaType::PartitionEntry *partition_entry, fs::OpenMode mode) : m_partition_entry(partition_entry), m_parent(parent), m_mode(mode) { /* ... */ }
|
||||
private:
|
||||
virtual Result DoRead(size_t *out, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) override final;
|
||||
|
||||
virtual Result DoGetSize(s64 *out) override final {
|
||||
*out = this->partition_entry->size;
|
||||
*out = m_partition_entry->size;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
virtual Result DoFlush() override final {
|
||||
/* Nothing to do if writing disallowed. */
|
||||
R_SUCCEED_IF((this->mode & fs::OpenMode_Write) == 0);
|
||||
R_SUCCEED_IF((m_mode & fs::OpenMode_Write) == 0);
|
||||
|
||||
/* Flush base storage. */
|
||||
return this->parent->base_storage->Flush();
|
||||
return m_parent->m_base_storage->Flush();
|
||||
}
|
||||
|
||||
virtual Result DoWrite(s64 offset, const void *buffer, size_t size, const fs::WriteOption &option) override final {
|
||||
/* Ensure appending is not required. */
|
||||
bool needs_append;
|
||||
R_TRY(this->DryWrite(std::addressof(needs_append), offset, size, option, this->mode));
|
||||
R_TRY(this->DryWrite(std::addressof(needs_append), offset, size, option, m_mode));
|
||||
R_UNLESS(!needs_append, fs::ResultUnsupportedOperationInPartitionFileA());
|
||||
|
||||
/* Appending is prohibited. */
|
||||
AMS_ASSERT((this->mode & fs::OpenMode_AllowAppend) == 0);
|
||||
AMS_ASSERT((m_mode & fs::OpenMode_AllowAppend) == 0);
|
||||
|
||||
/* Validate offset and size. */
|
||||
R_UNLESS(offset <= static_cast<s64>(this->partition_entry->size), fs::ResultOutOfRange());
|
||||
R_UNLESS(static_cast<s64>(offset + size) <= static_cast<s64>(this->partition_entry->size), fs::ResultInvalidSize());
|
||||
R_UNLESS(offset <= static_cast<s64>(m_partition_entry->size), fs::ResultOutOfRange());
|
||||
R_UNLESS(static_cast<s64>(offset + size) <= static_cast<s64>(m_partition_entry->size), fs::ResultInvalidSize());
|
||||
|
||||
/* Write to the base storage. */
|
||||
return this->parent->base_storage->Write(this->parent->meta_data_size + this->partition_entry->offset + offset, buffer, size);
|
||||
return m_parent->m_base_storage->Write(m_parent->m_meta_data_size + m_partition_entry->offset + offset, buffer, size);
|
||||
}
|
||||
|
||||
virtual Result DoSetSize(s64 size) override final {
|
||||
R_TRY(this->DrySetSize(size, this->mode));
|
||||
R_TRY(this->DrySetSize(size, m_mode));
|
||||
return fs::ResultUnsupportedOperationInPartitionFileA();
|
||||
}
|
||||
|
||||
@@ -90,8 +90,8 @@ namespace ams::fssystem {
|
||||
/* Validate preconditions for operation. */
|
||||
switch (op_id) {
|
||||
case fs::OperationId::Invalidate:
|
||||
R_UNLESS((this->mode & fs::OpenMode_Read) != 0, fs::ResultReadNotPermitted());
|
||||
R_UNLESS((this->mode & fs::OpenMode_Write) == 0, fs::ResultUnsupportedOperationInPartitionFileB());
|
||||
R_UNLESS((m_mode & fs::OpenMode_Read) != 0, fs::ResultReadNotPermitted());
|
||||
R_UNLESS((m_mode & fs::OpenMode_Write) == 0, fs::ResultUnsupportedOperationInPartitionFileB());
|
||||
break;
|
||||
case fs::OperationId::QueryRange:
|
||||
break;
|
||||
@@ -100,12 +100,12 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
/* Validate offset and size. */
|
||||
R_UNLESS(offset >= 0, fs::ResultOutOfRange());
|
||||
R_UNLESS(offset <= static_cast<s64>(this->partition_entry->size), fs::ResultOutOfRange());
|
||||
R_UNLESS(static_cast<s64>(offset + size) <= static_cast<s64>(this->partition_entry->size), fs::ResultInvalidSize());
|
||||
R_UNLESS(static_cast<s64>(offset + size) >= offset, fs::ResultInvalidSize());
|
||||
R_UNLESS(offset >= 0, fs::ResultOutOfRange());
|
||||
R_UNLESS(offset <= static_cast<s64>(m_partition_entry->size), fs::ResultOutOfRange());
|
||||
R_UNLESS(static_cast<s64>(offset + size) <= static_cast<s64>(m_partition_entry->size), fs::ResultInvalidSize());
|
||||
R_UNLESS(static_cast<s64>(offset + size) >= offset, fs::ResultInvalidSize());
|
||||
|
||||
return this->parent->base_storage->OperateRange(dst, dst_size, op_id, this->parent->meta_data_size + this->partition_entry->offset + offset, size, src, src_size);
|
||||
return m_parent->m_base_storage->OperateRange(dst, dst_size, op_id, m_parent->m_meta_data_size + m_partition_entry->offset + offset, size, src, src_size);
|
||||
}
|
||||
public:
|
||||
virtual sf::cmif::DomainObjectId GetDomainObjectId() const override {
|
||||
@@ -118,10 +118,10 @@ namespace ams::fssystem {
|
||||
Result PartitionFileSystemCore<PartitionFileSystemMeta>::PartitionFile::DoRead(size_t *out, s64 offset, void *dst, size_t dst_size, const fs::ReadOption &option) {
|
||||
/* Perform a dry read. */
|
||||
size_t read_size = 0;
|
||||
R_TRY(this->DryRead(std::addressof(read_size), offset, dst_size, option, this->mode));
|
||||
R_TRY(this->DryRead(std::addressof(read_size), offset, dst_size, option, m_mode));
|
||||
|
||||
/* Read from the base storage. */
|
||||
R_TRY(this->parent->base_storage->Read(this->parent->meta_data_size + this->partition_entry->offset + offset, dst, read_size));
|
||||
R_TRY(m_parent->m_base_storage->Read(m_parent->m_meta_data_size + m_partition_entry->offset + offset, dst, read_size));
|
||||
|
||||
/* Set output size. */
|
||||
*out = read_size;
|
||||
@@ -132,22 +132,22 @@ namespace ams::fssystem {
|
||||
Result PartitionFileSystemCore<Sha256PartitionFileSystemMeta>::PartitionFile::DoRead(size_t *out, s64 offset, void *dst, size_t dst_size, const fs::ReadOption &option) {
|
||||
/* Perform a dry read. */
|
||||
size_t read_size = 0;
|
||||
R_TRY(this->DryRead(std::addressof(read_size), offset, dst_size, option, this->mode));
|
||||
R_TRY(this->DryRead(std::addressof(read_size), offset, dst_size, option, m_mode));
|
||||
|
||||
const s64 entry_start = this->parent->meta_data_size + this->partition_entry->offset;
|
||||
const s64 entry_start = m_parent->m_meta_data_size + m_partition_entry->offset;
|
||||
const s64 read_end = static_cast<s64>(offset + read_size);
|
||||
const s64 hash_start = static_cast<s64>(this->partition_entry->hash_target_offset);
|
||||
const s64 hash_end = hash_start + this->partition_entry->hash_target_size;
|
||||
const s64 hash_start = static_cast<s64>(m_partition_entry->hash_target_offset);
|
||||
const s64 hash_end = hash_start + m_partition_entry->hash_target_size;
|
||||
|
||||
if (read_end <= hash_start || hash_end <= offset) {
|
||||
/* We aren't reading hashed data, so we can just read from the base storage. */
|
||||
R_TRY(this->parent->base_storage->Read(entry_start + offset, dst, read_size));
|
||||
R_TRY(m_parent->m_base_storage->Read(entry_start + offset, dst, read_size));
|
||||
} else {
|
||||
/* Only hash target offset == 0 is supported. */
|
||||
R_UNLESS(hash_start == 0, fs::ResultInvalidSha256PartitionHashTarget());
|
||||
|
||||
/* Ensure that the hash region is valid. */
|
||||
R_UNLESS(this->partition_entry->hash_target_offset + this->partition_entry->hash_target_size <= this->partition_entry->size, fs::ResultInvalidSha256PartitionHashTarget());
|
||||
R_UNLESS(m_partition_entry->hash_target_offset + m_partition_entry->hash_target_size <= m_partition_entry->size, fs::ResultInvalidSha256PartitionHashTarget());
|
||||
|
||||
/* Validate our read offset. */
|
||||
const s64 read_offset = entry_start + offset;
|
||||
@@ -167,11 +167,11 @@ namespace ams::fssystem {
|
||||
|
||||
if (hash_in_read) {
|
||||
/* Easy case: hash region is contained within the bounds. */
|
||||
R_TRY(this->parent->base_storage->Read(entry_start + offset, dst, read_size));
|
||||
generator.Update(static_cast<u8 *>(dst) + hash_start - offset, this->partition_entry->hash_target_size);
|
||||
R_TRY(m_parent->m_base_storage->Read(entry_start + offset, dst, read_size));
|
||||
generator.Update(static_cast<u8 *>(dst) + hash_start - offset, m_partition_entry->hash_target_size);
|
||||
} else /* if (read_in_hash) */ {
|
||||
/* We're reading a portion of what's hashed. */
|
||||
s64 remaining_hash_size = this->partition_entry->hash_target_size;
|
||||
s64 remaining_hash_size = m_partition_entry->hash_target_size;
|
||||
s64 hash_offset = entry_start + hash_start;
|
||||
s64 remaining_size = read_size;
|
||||
s64 copy_offset = 0;
|
||||
@@ -180,7 +180,7 @@ namespace ams::fssystem {
|
||||
constexpr size_t HashBufferSize = 0x200;
|
||||
char hash_buffer[HashBufferSize];
|
||||
size_t cur_size = static_cast<size_t>(std::min(static_cast<s64>(HashBufferSize), remaining_hash_size));
|
||||
R_TRY(this->parent->base_storage->Read(hash_offset, hash_buffer, cur_size));
|
||||
R_TRY(m_parent->m_base_storage->Read(hash_offset, hash_buffer, cur_size));
|
||||
|
||||
/* Update the hash. */
|
||||
generator.Update(hash_buffer, cur_size);
|
||||
@@ -205,7 +205,7 @@ namespace ams::fssystem {
|
||||
|
||||
/* Validate the hash. */
|
||||
auto hash_guard = SCOPE_GUARD { std::memset(dst, 0, read_size); };
|
||||
R_UNLESS(crypto::IsSameBytes(this->partition_entry->hash, hash, sizeof(hash)), fs::ResultSha256PartitionHashVerificationFailed());
|
||||
R_UNLESS(crypto::IsSameBytes(m_partition_entry->hash, hash, sizeof(hash)), fs::ResultSha256PartitionHashVerificationFailed());
|
||||
|
||||
/* We successfully completed our read. */
|
||||
hash_guard.Cancel();
|
||||
@@ -219,30 +219,30 @@ namespace ams::fssystem {
|
||||
template <typename MetaType>
|
||||
class PartitionFileSystemCore<MetaType>::PartitionDirectory : public fs::fsa::IDirectory, public fs::impl::Newable {
|
||||
private:
|
||||
u32 cur_index;
|
||||
const PartitionFileSystemCore<MetaType> *parent;
|
||||
const fs::OpenDirectoryMode mode;
|
||||
u32 m_cur_index;
|
||||
const PartitionFileSystemCore<MetaType> *m_parent;
|
||||
const fs::OpenDirectoryMode m_mode;
|
||||
public:
|
||||
PartitionDirectory(PartitionFileSystemCore<MetaType> *parent, fs::OpenDirectoryMode mode) : cur_index(0), parent(parent), mode(mode) { /* ... */ }
|
||||
PartitionDirectory(PartitionFileSystemCore<MetaType> *parent, fs::OpenDirectoryMode mode) : m_cur_index(0), m_parent(parent), m_mode(mode) { /* ... */ }
|
||||
public:
|
||||
virtual Result DoRead(s64 *out_count, fs::DirectoryEntry *out_entries, s64 max_entries) override final {
|
||||
/* There are no subdirectories. */
|
||||
if ((this->mode & fs::OpenDirectoryMode_File) == 0) {
|
||||
if ((m_mode & fs::OpenDirectoryMode_File) == 0) {
|
||||
*out_count = 0;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
/* Calculate number of entries. */
|
||||
const s64 entry_count = std::min(max_entries, static_cast<s64>(this->parent->meta_data->GetEntryCount() - this->cur_index));
|
||||
const s64 entry_count = std::min(max_entries, static_cast<s64>(m_parent->m_meta_data->GetEntryCount() - m_cur_index));
|
||||
|
||||
/* Populate output directory entries. */
|
||||
for (auto i = 0; i < entry_count; i++, this->cur_index++) {
|
||||
for (auto i = 0; i < entry_count; i++, m_cur_index++) {
|
||||
fs::DirectoryEntry &dir_entry = out_entries[i];
|
||||
|
||||
/* Setup the output directory entry. */
|
||||
dir_entry.type = fs::DirectoryEntryType_File;
|
||||
dir_entry.file_size = this->parent->meta_data->GetEntry(this->cur_index)->size;
|
||||
std::strncpy(dir_entry.name, this->parent->meta_data->GetEntryName(this->cur_index), sizeof(dir_entry.name) - 1);
|
||||
dir_entry.file_size = m_parent->m_meta_data->GetEntry(m_cur_index)->size;
|
||||
std::strncpy(dir_entry.name, m_parent->m_meta_data->GetEntryName(m_cur_index), sizeof(dir_entry.name) - 1);
|
||||
dir_entry.name[sizeof(dir_entry.name) - 1] = fs::StringTraits::NullTerminator;
|
||||
}
|
||||
|
||||
@@ -252,8 +252,8 @@ namespace ams::fssystem {
|
||||
|
||||
virtual Result DoGetEntryCount(s64 *out) override final {
|
||||
/* Output the parent meta data entry count for files, otherwise 0. */
|
||||
if (this->mode & fs::OpenDirectoryMode_File) {
|
||||
*out = this->parent->meta_data->GetEntryCount();
|
||||
if (m_mode & fs::OpenDirectoryMode_File) {
|
||||
*out = m_parent->m_meta_data->GetEntryCount();
|
||||
} else {
|
||||
*out = 0;
|
||||
}
|
||||
@@ -268,7 +268,7 @@ namespace ams::fssystem {
|
||||
};
|
||||
|
||||
template <typename MetaType>
|
||||
PartitionFileSystemCore<MetaType>::PartitionFileSystemCore() : initialized(false) {
|
||||
PartitionFileSystemCore<MetaType>::PartitionFileSystemCore() : m_initialized(false) {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
@@ -280,40 +280,40 @@ namespace ams::fssystem {
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::Initialize(fs::IStorage *base_storage, MemoryResource *allocator) {
|
||||
/* Validate preconditions. */
|
||||
R_UNLESS(!this->initialized, fs::ResultPreconditionViolation());
|
||||
R_UNLESS(!m_initialized, fs::ResultPreconditionViolation());
|
||||
|
||||
/* Allocate meta data. */
|
||||
this->unique_meta_data = std::make_unique<MetaType>();
|
||||
R_UNLESS(this->unique_meta_data != nullptr, fs::ResultAllocationFailureInPartitionFileSystemA());
|
||||
m_unique_meta_data = std::make_unique<MetaType>();
|
||||
R_UNLESS(m_unique_meta_data != nullptr, fs::ResultAllocationFailureInPartitionFileSystemA());
|
||||
|
||||
/* Initialize meta data. */
|
||||
R_TRY(this->unique_meta_data->Initialize(base_storage, allocator));
|
||||
R_TRY(m_unique_meta_data->Initialize(base_storage, allocator));
|
||||
|
||||
/* Initialize members. */
|
||||
this->meta_data = this->unique_meta_data.get();
|
||||
this->base_storage = base_storage;
|
||||
this->meta_data_size = this->meta_data->GetMetaDataSize();
|
||||
this->initialized = true;
|
||||
m_meta_data = m_unique_meta_data.get();
|
||||
m_base_storage = base_storage;
|
||||
m_meta_data_size = m_meta_data->GetMetaDataSize();
|
||||
m_initialized = true;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::Initialize(std::unique_ptr<MetaType> &&meta_data, std::shared_ptr<fs::IStorage> base_storage) {
|
||||
this->unique_meta_data = std::move(meta_data);
|
||||
return this->Initialize(this->unique_meta_data.get(), base_storage);
|
||||
m_unique_meta_data = std::move(meta_data);
|
||||
return this->Initialize(m_unique_meta_data.get(), base_storage);
|
||||
}
|
||||
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::Initialize(MetaType *meta_data, std::shared_ptr<fs::IStorage> base_storage) {
|
||||
/* Validate preconditions. */
|
||||
R_UNLESS(!this->initialized, fs::ResultPreconditionViolation());
|
||||
R_UNLESS(!m_initialized, fs::ResultPreconditionViolation());
|
||||
|
||||
/* Initialize members. */
|
||||
this->shared_storage = std::move(base_storage);
|
||||
this->base_storage = this->shared_storage.get();
|
||||
this->meta_data = meta_data;
|
||||
this->meta_data_size = this->meta_data->GetMetaDataSize();
|
||||
this->initialized = true;
|
||||
m_shared_storage = std::move(base_storage);
|
||||
m_base_storage = m_shared_storage.get();
|
||||
m_meta_data = meta_data;
|
||||
m_meta_data_size = m_meta_data->GetMetaDataSize();
|
||||
m_initialized = true;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
@@ -324,34 +324,34 @@ namespace ams::fssystem {
|
||||
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::Initialize(std::shared_ptr<fs::IStorage> base_storage) {
|
||||
this->shared_storage = std::move(base_storage);
|
||||
return this->Initialize(this->shared_storage.get());
|
||||
m_shared_storage = std::move(base_storage);
|
||||
return this->Initialize(m_shared_storage.get());
|
||||
}
|
||||
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::Initialize(std::shared_ptr<fs::IStorage> base_storage, MemoryResource *allocator) {
|
||||
this->shared_storage = std::move(base_storage);
|
||||
return this->Initialize(this->shared_storage.get(), allocator);
|
||||
m_shared_storage = std::move(base_storage);
|
||||
return this->Initialize(m_shared_storage.get(), allocator);
|
||||
}
|
||||
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::GetFileBaseOffset(s64 *out_offset, const char *path) {
|
||||
/* Validate preconditions. */
|
||||
R_UNLESS(this->initialized, fs::ResultPreconditionViolation());
|
||||
R_UNLESS(m_initialized, fs::ResultPreconditionViolation());
|
||||
|
||||
/* Obtain and validate the entry index. */
|
||||
const s32 entry_index = this->meta_data->GetEntryIndex(path + 1);
|
||||
const s32 entry_index = m_meta_data->GetEntryIndex(path + 1);
|
||||
R_UNLESS(entry_index >= 0, fs::ResultPathNotFound());
|
||||
|
||||
/* Output offset. */
|
||||
*out_offset = this->meta_data_size + this->meta_data->GetEntry(entry_index)->offset;
|
||||
*out_offset = m_meta_data_size + m_meta_data->GetEntry(entry_index)->offset;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::DoGetEntryType(fs::DirectoryEntryType *out, const char *path) {
|
||||
/* Validate preconditions. */
|
||||
R_UNLESS(this->initialized, fs::ResultPreconditionViolation());
|
||||
R_UNLESS(m_initialized, fs::ResultPreconditionViolation());
|
||||
R_UNLESS(fs::PathNormalizer::IsSeparator(path[0]), fs::ResultInvalidPathFormat());
|
||||
|
||||
/* Check if the path is for a directory. */
|
||||
@@ -361,7 +361,7 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
/* Ensure that path is for a file. */
|
||||
R_UNLESS(this->meta_data->GetEntryIndex(path + 1) >= 0, fs::ResultPathNotFound());
|
||||
R_UNLESS(m_meta_data->GetEntryIndex(path + 1) >= 0, fs::ResultPathNotFound());
|
||||
|
||||
*out = fs::DirectoryEntryType_File;
|
||||
return ResultSuccess();
|
||||
@@ -370,14 +370,14 @@ namespace ams::fssystem {
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::DoOpenFile(std::unique_ptr<fs::fsa::IFile> *out_file, const char *path, fs::OpenMode mode) {
|
||||
/* Validate preconditions. */
|
||||
R_UNLESS(this->initialized, fs::ResultPreconditionViolation());
|
||||
R_UNLESS(m_initialized, fs::ResultPreconditionViolation());
|
||||
|
||||
/* Obtain and validate the entry index. */
|
||||
const s32 entry_index = this->meta_data->GetEntryIndex(path + 1);
|
||||
const s32 entry_index = m_meta_data->GetEntryIndex(path + 1);
|
||||
R_UNLESS(entry_index >= 0, fs::ResultPathNotFound());
|
||||
|
||||
/* Create and output the file directory. */
|
||||
std::unique_ptr file = std::make_unique<PartitionFile>(this, this->meta_data->GetEntry(entry_index), mode);
|
||||
std::unique_ptr file = std::make_unique<PartitionFile>(this, m_meta_data->GetEntry(entry_index), mode);
|
||||
R_UNLESS(file != nullptr, fs::ResultAllocationFailureInPartitionFileSystemB());
|
||||
*out_file = std::move(file);
|
||||
return ResultSuccess();
|
||||
@@ -386,7 +386,7 @@ namespace ams::fssystem {
|
||||
template <typename MetaType>
|
||||
Result PartitionFileSystemCore<MetaType>::DoOpenDirectory(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const char *path, fs::OpenDirectoryMode mode) {
|
||||
/* Validate preconditions. */
|
||||
R_UNLESS(this->initialized, fs::ResultPreconditionViolation());
|
||||
R_UNLESS(m_initialized, fs::ResultPreconditionViolation());
|
||||
R_UNLESS(std::strncmp(path, fs::PathNormalizer::RootPath, sizeof(fs::PathNormalizer::RootPath)) == 0, fs::ResultPathNotFound());
|
||||
|
||||
/* Create and output the partition directory. */
|
||||
|
||||
@@ -38,16 +38,16 @@ namespace ams::fssystem {
|
||||
AMS_ASSERT(allocator != nullptr);
|
||||
|
||||
/* Determine the meta data size. */
|
||||
R_TRY(this->QueryMetaDataSize(std::addressof(this->meta_data_size), storage));
|
||||
R_TRY(this->QueryMetaDataSize(std::addressof(m_meta_data_size), storage));
|
||||
|
||||
/* Deallocate any old meta buffer and allocate a new one. */
|
||||
this->DeallocateBuffer();
|
||||
this->allocator = allocator;
|
||||
this->buffer = static_cast<char *>(this->allocator->Allocate(this->meta_data_size));
|
||||
R_UNLESS(this->buffer != nullptr, fs::ResultAllocationFailureInPartitionFileSystemMetaA());
|
||||
m_allocator = allocator;
|
||||
m_buffer = static_cast<char *>(m_allocator->Allocate(m_meta_data_size));
|
||||
R_UNLESS(m_buffer != nullptr, fs::ResultAllocationFailureInPartitionFileSystemMetaA());
|
||||
|
||||
/* Perform regular initialization. */
|
||||
return this->Initialize(storage, this->buffer, this->meta_data_size);
|
||||
return this->Initialize(storage, m_buffer, m_meta_data_size);
|
||||
}
|
||||
|
||||
template <typename Format>
|
||||
@@ -59,46 +59,46 @@ namespace ams::fssystem {
|
||||
R_TRY(storage->Read(0, meta, sizeof(PartitionFileSystemHeader)));
|
||||
|
||||
/* Set and validate the header. */
|
||||
this->header = reinterpret_cast<PartitionFileSystemHeader *>(meta);
|
||||
R_UNLESS(crypto::IsSameBytes(this->header->signature, Format::VersionSignature, sizeof(Format::VersionSignature)), typename Format::ResultSignatureVerificationFailed());
|
||||
m_header = reinterpret_cast<PartitionFileSystemHeader *>(meta);
|
||||
R_UNLESS(crypto::IsSameBytes(m_header->signature, Format::VersionSignature, sizeof(Format::VersionSignature)), typename Format::ResultSignatureVerificationFailed());
|
||||
|
||||
/* Setup entries and name table. */
|
||||
const size_t entries_size = this->header->entry_count * sizeof(typename Format::PartitionEntry);
|
||||
this->entries = reinterpret_cast<PartitionEntry *>(static_cast<u8 *>(meta) + sizeof(PartitionFileSystemHeader));
|
||||
this->name_table = static_cast<char *>(meta) + sizeof(PartitionFileSystemHeader) + entries_size;
|
||||
const size_t entries_size = m_header->entry_count * sizeof(typename Format::PartitionEntry);
|
||||
m_entries = reinterpret_cast<PartitionEntry *>(static_cast<u8 *>(meta) + sizeof(PartitionFileSystemHeader));
|
||||
m_name_table = static_cast<char *>(meta) + sizeof(PartitionFileSystemHeader) + entries_size;
|
||||
|
||||
/* Validate size for header + entries + name table. */
|
||||
R_UNLESS(meta_size >= sizeof(PartitionFileSystemHeader) + entries_size + this->header->name_table_size, fs::ResultInvalidSize());
|
||||
R_UNLESS(meta_size >= sizeof(PartitionFileSystemHeader) + entries_size + m_header->name_table_size, fs::ResultInvalidSize());
|
||||
|
||||
/* Read entries and name table. */
|
||||
R_TRY(storage->Read(sizeof(PartitionFileSystemHeader), this->entries, entries_size + this->header->name_table_size));
|
||||
R_TRY(storage->Read(sizeof(PartitionFileSystemHeader), m_entries, entries_size + m_header->name_table_size));
|
||||
|
||||
/* Mark as initialized. */
|
||||
this->initialized = true;
|
||||
m_initialized = true;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
template <typename Format>
|
||||
void PartitionFileSystemMetaCore<Format>::DeallocateBuffer() {
|
||||
if (this->buffer != nullptr) {
|
||||
AMS_ABORT_UNLESS(this->allocator != nullptr);
|
||||
this->allocator->Deallocate(this->buffer, this->meta_data_size);
|
||||
this->buffer = nullptr;
|
||||
if (m_buffer != nullptr) {
|
||||
AMS_ABORT_UNLESS(m_allocator != nullptr);
|
||||
m_allocator->Deallocate(m_buffer, m_meta_data_size);
|
||||
m_buffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Format>
|
||||
const typename Format::PartitionEntry *PartitionFileSystemMetaCore<Format>::GetEntry(s32 index) const {
|
||||
if (this->initialized && 0 <= index && index < static_cast<s32>(this->header->entry_count)) {
|
||||
return std::addressof(this->entries[index]);
|
||||
if (m_initialized && 0 <= index && index < static_cast<s32>(m_header->entry_count)) {
|
||||
return std::addressof(m_entries[index]);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename Format>
|
||||
s32 PartitionFileSystemMetaCore<Format>::GetEntryCount() const {
|
||||
if (this->initialized) {
|
||||
return this->header->entry_count;
|
||||
if (m_initialized) {
|
||||
return m_header->entry_count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -106,21 +106,21 @@ namespace ams::fssystem {
|
||||
template <typename Format>
|
||||
s32 PartitionFileSystemMetaCore<Format>::GetEntryIndex(const char *name) const {
|
||||
/* Fail if not initialized. */
|
||||
if (!this->initialized) {
|
||||
if (!m_initialized) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (s32 i = 0; i < static_cast<s32>(this->header->entry_count); i++) {
|
||||
const auto &entry = this->entries[i];
|
||||
for (s32 i = 0; i < static_cast<s32>(m_header->entry_count); i++) {
|
||||
const auto &entry = m_entries[i];
|
||||
|
||||
/* Name offset is invalid. */
|
||||
if (entry.name_offset >= this->header->name_table_size) {
|
||||
if (entry.name_offset >= m_header->name_table_size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compare to input name. */
|
||||
const s32 max_name_len = this->header->name_table_size - entry.name_offset;
|
||||
if (std::strncmp(std::addressof(this->name_table[entry.name_offset]), name, max_name_len) == 0) {
|
||||
const s32 max_name_len = m_header->name_table_size - entry.name_offset;
|
||||
if (std::strncmp(std::addressof(m_name_table[entry.name_offset]), name, max_name_len) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@@ -131,8 +131,8 @@ namespace ams::fssystem {
|
||||
|
||||
template <typename Format>
|
||||
const char *PartitionFileSystemMetaCore<Format>::GetEntryName(s32 index) const {
|
||||
if (this->initialized && index < static_cast<s32>(this->header->entry_count)) {
|
||||
return std::addressof(this->name_table[this->GetEntry(index)->name_offset]);
|
||||
if (m_initialized && index < static_cast<s32>(m_header->entry_count)) {
|
||||
return std::addressof(m_name_table[this->GetEntry(index)->name_offset]);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -144,7 +144,7 @@ namespace ams::fssystem {
|
||||
|
||||
template <typename Format>
|
||||
size_t PartitionFileSystemMetaCore<Format>::GetMetaDataSize() const {
|
||||
return this->meta_data_size;
|
||||
return m_meta_data_size;
|
||||
}
|
||||
|
||||
template <typename Format>
|
||||
@@ -167,25 +167,25 @@ namespace ams::fssystem {
|
||||
R_UNLESS(hash_size == crypto::Sha256Generator::HashSize, fs::ResultPreconditionViolation());
|
||||
|
||||
/* Get metadata size. */
|
||||
R_TRY(QueryMetaDataSize(std::addressof(this->meta_data_size), base_storage));
|
||||
R_TRY(QueryMetaDataSize(std::addressof(m_meta_data_size), base_storage));
|
||||
|
||||
/* Ensure we have no buffer. */
|
||||
this->DeallocateBuffer();
|
||||
|
||||
/* Set allocator and allocate buffer. */
|
||||
this->allocator = allocator;
|
||||
this->buffer = static_cast<char *>(this->allocator->Allocate(this->meta_data_size));
|
||||
R_UNLESS(this->buffer != nullptr, fs::ResultAllocationFailureInPartitionFileSystemMetaB());
|
||||
m_allocator = allocator;
|
||||
m_buffer = static_cast<char *>(m_allocator->Allocate(m_meta_data_size));
|
||||
R_UNLESS(m_buffer != nullptr, fs::ResultAllocationFailureInPartitionFileSystemMetaB());
|
||||
|
||||
/* Read metadata. */
|
||||
R_TRY(base_storage->Read(0, this->buffer, this->meta_data_size));
|
||||
R_TRY(base_storage->Read(0, m_buffer, m_meta_data_size));
|
||||
|
||||
/* Calculate hash. */
|
||||
char calc_hash[crypto::Sha256Generator::HashSize];
|
||||
{
|
||||
crypto::Sha256Generator generator;
|
||||
generator.Initialize();
|
||||
generator.Update(this->buffer, this->meta_data_size);
|
||||
generator.Update(m_buffer, m_meta_data_size);
|
||||
if (suffix) {
|
||||
u8 suffix_val = *suffix;
|
||||
generator.Update(std::addressof(suffix_val), 1);
|
||||
@@ -200,19 +200,19 @@ namespace ams::fssystem {
|
||||
using Format = impl::Sha256PartitionFileSystemFormat;
|
||||
|
||||
/* Set header. */
|
||||
this->header = reinterpret_cast<PartitionFileSystemHeader *>(this->buffer);
|
||||
R_UNLESS(crypto::IsSameBytes(this->header->signature, Format::VersionSignature, sizeof(Format::VersionSignature)), typename Format::ResultSignatureVerificationFailed());
|
||||
m_header = reinterpret_cast<PartitionFileSystemHeader *>(m_buffer);
|
||||
R_UNLESS(crypto::IsSameBytes(m_header->signature, Format::VersionSignature, sizeof(Format::VersionSignature)), typename Format::ResultSignatureVerificationFailed());
|
||||
|
||||
/* Validate size for entries and name table. */
|
||||
const size_t entries_size = this->header->entry_count * sizeof(typename Format::PartitionEntry);
|
||||
R_UNLESS(this->meta_data_size >= sizeof(PartitionFileSystemHeader) + entries_size + this->header->name_table_size, fs::ResultInvalidSha256PartitionMetaDataSize());
|
||||
const size_t entries_size = m_header->entry_count * sizeof(typename Format::PartitionEntry);
|
||||
R_UNLESS(m_meta_data_size >= sizeof(PartitionFileSystemHeader) + entries_size + m_header->name_table_size, fs::ResultInvalidSha256PartitionMetaDataSize());
|
||||
|
||||
/* Set entries and name table. */
|
||||
this->entries = reinterpret_cast<PartitionEntry *>(this->buffer + sizeof(PartitionFileSystemHeader));
|
||||
this->name_table = this->buffer + sizeof(PartitionFileSystemHeader) + entries_size;
|
||||
m_entries = reinterpret_cast<PartitionEntry *>(m_buffer + sizeof(PartitionFileSystemHeader));
|
||||
m_name_table = m_buffer + sizeof(PartitionFileSystemHeader) + entries_size;
|
||||
|
||||
/* We initialized. */
|
||||
this->initialized = true;
|
||||
m_initialized = true;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
|
||||
@@ -21,40 +21,40 @@ namespace ams::fssystem {
|
||||
|
||||
class AdditionalDeviceAddressEntry {
|
||||
private:
|
||||
os::SdkMutex mutex;
|
||||
bool is_registered;
|
||||
uintptr_t address;
|
||||
size_t size;
|
||||
os::SdkMutex m_mutex;
|
||||
bool m_is_registered;
|
||||
uintptr_t m_address;
|
||||
size_t m_size;
|
||||
public:
|
||||
constexpr AdditionalDeviceAddressEntry() : mutex(), is_registered(), address(), size() { /* ... */ }
|
||||
constexpr AdditionalDeviceAddressEntry() : m_mutex(), m_is_registered(), m_address(), m_size() { /* ... */ }
|
||||
|
||||
void Register(uintptr_t addr, size_t sz) {
|
||||
std::scoped_lock lk(this->mutex);
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
AMS_ASSERT(!this->is_registered);
|
||||
if (!this->is_registered) {
|
||||
this->is_registered = true;
|
||||
this->address = addr;
|
||||
this->size = sz;
|
||||
AMS_ASSERT(!m_is_registered);
|
||||
if (!m_is_registered) {
|
||||
m_is_registered = true;
|
||||
m_address = addr;
|
||||
m_size = sz;
|
||||
}
|
||||
}
|
||||
|
||||
void Unregister(uintptr_t addr) {
|
||||
std::scoped_lock lk(this->mutex);
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
if (this->is_registered && this->address == addr) {
|
||||
this->is_registered = false;
|
||||
this->address = 0;
|
||||
this->size = 0;
|
||||
if (m_is_registered && m_address == addr) {
|
||||
m_is_registered = false;
|
||||
m_address = 0;
|
||||
m_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool Includes(const void *ptr) {
|
||||
std::scoped_lock lk(this->mutex);
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
if (this->is_registered) {
|
||||
if (m_is_registered) {
|
||||
const uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
|
||||
return this->address <= addr && addr < this->address + this->size;
|
||||
return m_address <= addr && addr < m_address + m_size;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -97,7 +97,7 @@ namespace ams::fssystem {
|
||||
void PooledBuffer::AllocateCore(size_t ideal_size, size_t required_size, bool large) {
|
||||
/* Ensure preconditions. */
|
||||
AMS_ASSERT(g_heap_buffer != nullptr);
|
||||
AMS_ASSERT(this->buffer == nullptr);
|
||||
AMS_ASSERT(m_buffer == nullptr);
|
||||
AMS_ASSERT(g_heap.GetBlockSize() == HeapBlockSize);
|
||||
|
||||
/* Check that we can allocate this size. */
|
||||
@@ -123,13 +123,13 @@ namespace ams::fssystem {
|
||||
const auto order = g_heap.GetOrderFromBytes(std::min(target_size, allocatable_size));
|
||||
|
||||
/* Allocate and get the size. */
|
||||
this->buffer = reinterpret_cast<char *>(g_heap.AllocateByOrder(order));
|
||||
this->size = g_heap.GetBytesFromOrder(order);
|
||||
m_buffer = reinterpret_cast<char *>(g_heap.AllocateByOrder(order));
|
||||
m_size = g_heap.GetBytesFromOrder(order);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we allocated. */
|
||||
if (this->buffer != nullptr) {
|
||||
if (m_buffer != nullptr) {
|
||||
/* If we need to trim the end, do so. */
|
||||
if (this->GetSize() >= target_size + HeapAllocatableSizeTrim) {
|
||||
this->Shrink(util::AlignUp(target_size, HeapAllocatableSizeTrim));
|
||||
@@ -163,9 +163,9 @@ namespace ams::fssystem {
|
||||
AMS_ASSERT(ideal_size <= GetAllocatableSizeMaxCore(true));
|
||||
|
||||
/* Check if we actually need to shrink. */
|
||||
if (this->size > ideal_size) {
|
||||
if (m_size > ideal_size) {
|
||||
/* If we do, we need to have a buffer allocated from the heap. */
|
||||
AMS_ASSERT(this->buffer != nullptr);
|
||||
AMS_ASSERT(m_buffer != nullptr);
|
||||
AMS_ASSERT(g_heap.GetBlockSize() == HeapBlockSize);
|
||||
|
||||
const size_t new_size = util::AlignUp(ideal_size, HeapBlockSize);
|
||||
@@ -174,10 +174,10 @@ namespace ams::fssystem {
|
||||
{
|
||||
std::scoped_lock lk(g_heap_mutex);
|
||||
|
||||
while (new_size < this->size) {
|
||||
while (new_size < m_size) {
|
||||
/* Determine the size and order to free. */
|
||||
const size_t tail_align = util::LeastSignificantOneBit(this->size);
|
||||
const size_t free_size = std::min(util::FloorPowerOfTwo(this->size - new_size), tail_align);
|
||||
const size_t tail_align = util::LeastSignificantOneBit(m_size);
|
||||
const size_t free_size = std::min(util::FloorPowerOfTwo(m_size - new_size), tail_align);
|
||||
const s32 free_order = g_heap.GetOrderFromBytes(free_size);
|
||||
|
||||
/* Ensure we determined size correctly. */
|
||||
@@ -185,14 +185,14 @@ namespace ams::fssystem {
|
||||
AMS_ASSERT(free_size == g_heap.GetBytesFromOrder(free_order));
|
||||
|
||||
/* Actually free the memory. */
|
||||
g_heap.Free(this->buffer + this->size - free_size, free_order);
|
||||
this->size -= free_size;
|
||||
g_heap.Free(m_buffer + m_size - free_size, free_order);
|
||||
m_size -= free_size;
|
||||
}
|
||||
}
|
||||
|
||||
/* Shrinking to zero means that we have no buffer. */
|
||||
if (this->size == 0) {
|
||||
this->buffer = nullptr;
|
||||
if (m_size == 0) {
|
||||
m_buffer = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,46 +25,46 @@ namespace ams::fssystem {
|
||||
private:
|
||||
using BlockCache = LruListCache<s64, char *>;
|
||||
private:
|
||||
os::SdkMutex mutex;
|
||||
BlockCache block_cache;
|
||||
fs::IStorage * const base_storage;
|
||||
s32 block_size;
|
||||
os::SdkMutex m_mutex;
|
||||
BlockCache m_block_cache;
|
||||
fs::IStorage * const m_base_storage;
|
||||
s32 m_block_size;
|
||||
public:
|
||||
ReadOnlyBlockCacheStorage(IStorage *bs, s32 bsz, char *buf, size_t buf_size, s32 cache_block_count) : mutex(), base_storage(bs), block_size(bsz) {
|
||||
ReadOnlyBlockCacheStorage(IStorage *bs, s32 bsz, char *buf, size_t buf_size, s32 cache_block_count) : m_mutex(), m_block_cache(), m_base_storage(bs), m_block_size(bsz) {
|
||||
/* Validate preconditions. */
|
||||
AMS_ASSERT(buf_size >= static_cast<size_t>(this->block_size));
|
||||
AMS_ASSERT(util::IsPowerOfTwo(this->block_size));
|
||||
AMS_ASSERT(buf_size >= static_cast<size_t>(m_block_size));
|
||||
AMS_ASSERT(util::IsPowerOfTwo(m_block_size));
|
||||
AMS_ASSERT(cache_block_count > 0);
|
||||
AMS_ASSERT(buf_size >= static_cast<size_t>(this->block_size * cache_block_count));
|
||||
AMS_ASSERT(buf_size >= static_cast<size_t>(m_block_size * cache_block_count));
|
||||
AMS_UNUSED(buf_size);
|
||||
|
||||
/* Create a node for each cache block. */
|
||||
for (auto i = 0; i < cache_block_count; i++) {
|
||||
std::unique_ptr node = std::make_unique<BlockCache::Node>(buf + this->block_size * i);
|
||||
std::unique_ptr node = std::make_unique<BlockCache::Node>(buf + m_block_size * i);
|
||||
AMS_ASSERT(node != nullptr);
|
||||
|
||||
if (node != nullptr) {
|
||||
this->block_cache.PushMruNode(std::move(node), -1);
|
||||
m_block_cache.PushMruNode(std::move(node), -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~ReadOnlyBlockCacheStorage() {
|
||||
this->block_cache.DeleteAllNodes();
|
||||
m_block_cache.DeleteAllNodes();
|
||||
}
|
||||
|
||||
virtual Result Read(s64 offset, void *buffer, size_t size) override {
|
||||
/* Validate preconditions. */
|
||||
AMS_ASSERT(util::IsAligned(offset, this->block_size));
|
||||
AMS_ASSERT(util::IsAligned(size, this->block_size));
|
||||
AMS_ASSERT(util::IsAligned(offset, m_block_size));
|
||||
AMS_ASSERT(util::IsAligned(size, m_block_size));
|
||||
|
||||
if (size == static_cast<size_t>(this->block_size)) {
|
||||
if (size == static_cast<size_t>(m_block_size)) {
|
||||
char *cached_buffer = nullptr;
|
||||
|
||||
/* Try to find a cached copy of the data. */
|
||||
{
|
||||
std::scoped_lock lk(this->mutex);
|
||||
bool found = this->block_cache.FindValueAndUpdateMru(std::addressof(cached_buffer), offset / this->block_size);
|
||||
std::scoped_lock lk(m_mutex);
|
||||
bool found = m_block_cache.FindValueAndUpdateMru(std::addressof(cached_buffer), offset / m_block_size);
|
||||
if (found) {
|
||||
std::memcpy(buffer, cached_buffer, size);
|
||||
return ResultSuccess();
|
||||
@@ -72,56 +72,56 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
/* We failed to get a cache hit, so read in the data. */
|
||||
R_TRY(this->base_storage->Read(offset, buffer, size));
|
||||
R_TRY(m_base_storage->Read(offset, buffer, size));
|
||||
|
||||
/* Add the block to the cache. */
|
||||
{
|
||||
std::scoped_lock lk(this->mutex);
|
||||
auto lru = this->block_cache.PopLruNode();
|
||||
std::memcpy(lru->value, buffer, this->block_size);
|
||||
this->block_cache.PushMruNode(std::move(lru), offset / this->block_size);
|
||||
std::scoped_lock lk(m_mutex);
|
||||
auto lru = m_block_cache.PopLruNode();
|
||||
std::memcpy(lru->m_value, buffer, m_block_size);
|
||||
m_block_cache.PushMruNode(std::move(lru), offset / m_block_size);
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
} else {
|
||||
return this->base_storage->Read(offset, buffer, size);
|
||||
return m_base_storage->Read(offset, buffer, size);
|
||||
}
|
||||
}
|
||||
virtual Result OperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override {
|
||||
/* Validate preconditions. */
|
||||
AMS_ASSERT(util::IsAligned(offset, this->block_size));
|
||||
AMS_ASSERT(util::IsAligned(size, this->block_size));
|
||||
AMS_ASSERT(util::IsAligned(offset, m_block_size));
|
||||
AMS_ASSERT(util::IsAligned(size, m_block_size));
|
||||
|
||||
/* If invalidating cache, invalidate our blocks. */
|
||||
if (op_id == fs::OperationId::Invalidate) {
|
||||
R_UNLESS(offset >= 0, fs::ResultInvalidOffset());
|
||||
|
||||
std::scoped_lock lk(this->mutex);
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
const size_t cache_block_count = this->block_cache.GetSize();
|
||||
const size_t cache_block_count = m_block_cache.GetSize();
|
||||
BlockCache valid_cache;
|
||||
|
||||
for (size_t count = 0; count < cache_block_count; ++count) {
|
||||
auto lru = this->block_cache.PopLruNode();
|
||||
if (offset <= lru->key && lru->key < offset + size) {
|
||||
this->block_cache.PushMruNode(std::move(lru), -1);
|
||||
auto lru = m_block_cache.PopLruNode();
|
||||
if (offset <= lru->m_key && lru->m_key < offset + size) {
|
||||
m_block_cache.PushMruNode(std::move(lru), -1);
|
||||
} else {
|
||||
valid_cache.PushMruNode(std::move(lru), lru->key);
|
||||
valid_cache.PushMruNode(std::move(lru), lru->m_key);
|
||||
}
|
||||
}
|
||||
|
||||
while (!valid_cache.IsEmpty()) {
|
||||
auto lru = valid_cache.PopLruNode();
|
||||
this->block_cache.PushMruNode(std::move(lru), lru->key);
|
||||
m_block_cache.PushMruNode(std::move(lru), lru->m_key);
|
||||
}
|
||||
}
|
||||
|
||||
/* Operate on the base storage. */
|
||||
return this->base_storage->OperateRange(dst, dst_size, op_id, offset, size, src, src_size);
|
||||
return m_base_storage->OperateRange(dst, dst_size, op_id, offset, size, src, src_size);
|
||||
}
|
||||
|
||||
virtual Result GetSize(s64 *out) override {
|
||||
return this->base_storage->GetSize(out);
|
||||
return m_base_storage->GetSize(out);
|
||||
}
|
||||
|
||||
virtual Result Flush() override {
|
||||
|
||||
@@ -25,15 +25,15 @@ namespace ams::fssystem {
|
||||
|
||||
class RomFsFile : public ams::fs::fsa::IFile, public ams::fs::impl::Newable {
|
||||
private:
|
||||
RomFsFileSystem *parent;
|
||||
s64 start;
|
||||
s64 end;
|
||||
RomFsFileSystem *m_parent;
|
||||
s64 m_start;
|
||||
s64 m_end;
|
||||
private:
|
||||
s64 GetSize() const {
|
||||
return this->end - this->start;
|
||||
return m_end - m_start;
|
||||
}
|
||||
public:
|
||||
RomFsFile(RomFsFileSystem *p, s64 s, s64 e) : parent(p), start(s), end(e) { /* ... */ }
|
||||
RomFsFile(RomFsFileSystem *p, s64 s, s64 e) : m_parent(p), m_start(s), m_end(e) { /* ... */ }
|
||||
virtual ~RomFsFile() { /* ... */ }
|
||||
public:
|
||||
virtual Result DoRead(size_t *out, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) override {
|
||||
@@ -41,7 +41,7 @@ namespace ams::fssystem {
|
||||
size_t read_size = 0;
|
||||
R_TRY(this->DryRead(std::addressof(read_size), offset, size, option, fs::OpenMode_Read));
|
||||
|
||||
R_TRY(this->parent->GetBaseStorage()->Read(offset + this->start, buffer, read_size));
|
||||
R_TRY(m_parent->GetBaseStorage()->Read(offset + m_start, buffer, read_size));
|
||||
*out = read_size;
|
||||
|
||||
return ResultSuccess();
|
||||
@@ -88,7 +88,7 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
R_TRY(buffers::DoContinuouslyUntilBufferIsAllocated([=, this]() -> Result {
|
||||
R_TRY(this->parent->GetBaseStorage()->OperateRange(dst, dst_size, op_id, this->start + offset, operate_size, src, src_size));
|
||||
R_TRY(m_parent->GetBaseStorage()->OperateRange(dst, dst_size, op_id, m_start + offset, operate_size, src, src_size));
|
||||
return ResultSuccess();
|
||||
}, AMS_CURRENT_FUNCTION_NAME));
|
||||
return ResultSuccess();
|
||||
@@ -107,23 +107,23 @@ namespace ams::fssystem {
|
||||
private:
|
||||
using FindPosition = RomFsFileSystem::RomFileTable::FindPosition;
|
||||
private:
|
||||
RomFsFileSystem *parent;
|
||||
FindPosition current_find;
|
||||
FindPosition first_find;
|
||||
fs::OpenDirectoryMode mode;
|
||||
RomFsFileSystem *m_parent;
|
||||
FindPosition m_current_find;
|
||||
FindPosition m_first_find;
|
||||
fs::OpenDirectoryMode m_mode;
|
||||
public:
|
||||
RomFsDirectory(RomFsFileSystem *p, const FindPosition &f, fs::OpenDirectoryMode m) : parent(p), current_find(f), first_find(f), mode(m) { /* ... */ }
|
||||
RomFsDirectory(RomFsFileSystem *p, const FindPosition &f, fs::OpenDirectoryMode m) : m_parent(p), m_current_find(f), m_first_find(f), m_mode(m) { /* ... */ }
|
||||
virtual ~RomFsDirectory() override { /* ... */ }
|
||||
public:
|
||||
virtual Result DoRead(s64 *out_count, fs::DirectoryEntry *out_entries, s64 max_entries) {
|
||||
R_TRY(buffers::DoContinuouslyUntilBufferIsAllocated([=, this]() -> Result {
|
||||
return this->ReadInternal(out_count, std::addressof(this->current_find), out_entries, max_entries);
|
||||
return this->ReadInternal(out_count, std::addressof(m_current_find), out_entries, max_entries);
|
||||
}, AMS_CURRENT_FUNCTION_NAME));
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
virtual Result DoGetEntryCount(s64 *out) {
|
||||
FindPosition find = this->first_find;
|
||||
FindPosition find = m_first_find;
|
||||
|
||||
R_TRY(buffers::DoContinuouslyUntilBufferIsAllocated([&]() -> Result {
|
||||
R_TRY(this->ReadInternal(out, std::addressof(find), nullptr, 0));
|
||||
@@ -137,9 +137,9 @@ namespace ams::fssystem {
|
||||
fs::RomPathChar name[NameBufferSize];
|
||||
s32 i = 0;
|
||||
|
||||
if (this->mode & fs::OpenDirectoryMode_Directory) {
|
||||
if (m_mode & fs::OpenDirectoryMode_Directory) {
|
||||
while (i < max_entries || out_entries == nullptr) {
|
||||
R_TRY_CATCH(this->parent->GetRomFileTable()->FindNextDirectory(name, find, NameBufferSize)) {
|
||||
R_TRY_CATCH(m_parent->GetRomFileTable()->FindNextDirectory(name, find, NameBufferSize)) {
|
||||
R_CATCH(fs::ResultDbmFindFinished) { break; }
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
@@ -155,11 +155,11 @@ namespace ams::fssystem {
|
||||
}
|
||||
}
|
||||
|
||||
if (this->mode & fs::OpenDirectoryMode_File) {
|
||||
if (m_mode & fs::OpenDirectoryMode_File) {
|
||||
while (i < max_entries || out_entries == nullptr) {
|
||||
auto file_pos = find->next_file;
|
||||
|
||||
R_TRY_CATCH(this->parent->GetRomFileTable()->FindNextFile(name, find, NameBufferSize)) {
|
||||
R_TRY_CATCH(m_parent->GetRomFileTable()->FindNextFile(name, find, NameBufferSize)) {
|
||||
R_CATCH(fs::ResultDbmFindFinished) { break; }
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
@@ -170,7 +170,7 @@ namespace ams::fssystem {
|
||||
out_entries[i].type = fs::DirectoryEntryType_File;
|
||||
|
||||
RomFsFileSystem::RomFileTable::FileInfo file_info;
|
||||
R_TRY(this->parent->GetRomFileTable()->OpenFile(std::addressof(file_info), this->parent->GetRomFileTable()->PositionToFileId(file_pos)));
|
||||
R_TRY(m_parent->GetRomFileTable()->OpenFile(std::addressof(file_info), m_parent->GetRomFileTable()->PositionToFileId(file_pos)));
|
||||
out_entries[i].file_size = file_info.size.Get();
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
|
||||
RomFsFileSystem::RomFsFileSystem() : base_storage() {
|
||||
RomFsFileSystem::RomFsFileSystem() : m_base_storage() {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
@@ -199,11 +199,11 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
fs::IStorage *RomFsFileSystem::GetBaseStorage() {
|
||||
return this->base_storage;
|
||||
return m_base_storage;
|
||||
}
|
||||
|
||||
RomFsFileSystem::RomFileTable *RomFsFileSystem::GetRomFileTable() {
|
||||
return std::addressof(this->rom_file_table);
|
||||
return std::addressof(m_rom_file_table);
|
||||
}
|
||||
|
||||
Result RomFsFileSystem::GetRequiredWorkingMemorySize(size_t *out, fs::IStorage *storage) {
|
||||
@@ -246,43 +246,43 @@ namespace ams::fssystem {
|
||||
R_TRY(base->Read(header.file_bucket_offset, file_bucket_buf, static_cast<size_t>(header.file_bucket_size)));
|
||||
R_TRY(base->Read(header.file_entry_offset, file_entry_buf, static_cast<size_t>(header.file_entry_size)));
|
||||
|
||||
this->dir_bucket_storage.reset(new fs::MemoryStorage(dir_bucket_buf, header.directory_bucket_size));
|
||||
this->dir_entry_storage.reset(new fs::MemoryStorage(dir_entry_buf, header.directory_entry_size));
|
||||
this->file_bucket_storage.reset(new fs::MemoryStorage(file_bucket_buf, header.file_bucket_size));
|
||||
this->file_entry_storage.reset(new fs::MemoryStorage(file_entry_buf, header.file_entry_size));
|
||||
m_dir_bucket_storage.reset(new fs::MemoryStorage(dir_bucket_buf, header.directory_bucket_size));
|
||||
m_dir_entry_storage.reset(new fs::MemoryStorage(dir_entry_buf, header.directory_entry_size));
|
||||
m_file_bucket_storage.reset(new fs::MemoryStorage(file_bucket_buf, header.file_bucket_size));
|
||||
m_file_entry_storage.reset(new fs::MemoryStorage(file_entry_buf, header.file_entry_size));
|
||||
} else {
|
||||
this->dir_bucket_storage.reset(new fs::SubStorage(base, header.directory_bucket_offset, header.directory_bucket_size));
|
||||
this->dir_entry_storage.reset(new fs::SubStorage(base, header.directory_entry_offset, header.directory_entry_size));
|
||||
this->file_bucket_storage.reset(new fs::SubStorage(base, header.file_bucket_offset, header.file_bucket_size));
|
||||
this->file_entry_storage.reset(new fs::SubStorage(base, header.file_entry_offset, header.file_entry_size));
|
||||
m_dir_bucket_storage.reset(new fs::SubStorage(base, header.directory_bucket_offset, header.directory_bucket_size));
|
||||
m_dir_entry_storage.reset(new fs::SubStorage(base, header.directory_entry_offset, header.directory_entry_size));
|
||||
m_file_bucket_storage.reset(new fs::SubStorage(base, header.file_bucket_offset, header.file_bucket_size));
|
||||
m_file_entry_storage.reset(new fs::SubStorage(base, header.file_entry_offset, header.file_entry_size));
|
||||
}
|
||||
|
||||
/* Ensure we allocated storages successfully. */
|
||||
R_UNLESS(this->dir_bucket_storage != nullptr, fs::ResultAllocationFailureInRomFsFileSystemB());
|
||||
R_UNLESS(this->dir_entry_storage != nullptr, fs::ResultAllocationFailureInRomFsFileSystemB());
|
||||
R_UNLESS(this->file_bucket_storage != nullptr, fs::ResultAllocationFailureInRomFsFileSystemB());
|
||||
R_UNLESS(this->file_entry_storage != nullptr, fs::ResultAllocationFailureInRomFsFileSystemB());
|
||||
R_UNLESS(m_dir_bucket_storage != nullptr, fs::ResultAllocationFailureInRomFsFileSystemB());
|
||||
R_UNLESS(m_dir_entry_storage != nullptr, fs::ResultAllocationFailureInRomFsFileSystemB());
|
||||
R_UNLESS(m_file_bucket_storage != nullptr, fs::ResultAllocationFailureInRomFsFileSystemB());
|
||||
R_UNLESS(m_file_entry_storage != nullptr, fs::ResultAllocationFailureInRomFsFileSystemB());
|
||||
|
||||
/* Initialize the rom table. */
|
||||
R_TRY(this->rom_file_table.Initialize(fs::SubStorage(this->dir_bucket_storage.get(), 0, static_cast<u32>(header.directory_bucket_size)),
|
||||
fs::SubStorage(this->dir_entry_storage.get(), 0, static_cast<u32>(header.directory_entry_size)),
|
||||
fs::SubStorage(this->file_bucket_storage.get(), 0, static_cast<u32>(header.file_bucket_size)),
|
||||
fs::SubStorage(this->file_entry_storage.get(), 0, static_cast<u32>(header.file_entry_size))));
|
||||
R_TRY(m_rom_file_table.Initialize(fs::SubStorage(m_dir_bucket_storage.get(), 0, static_cast<u32>(header.directory_bucket_size)),
|
||||
fs::SubStorage(m_dir_entry_storage.get(), 0, static_cast<u32>(header.directory_entry_size)),
|
||||
fs::SubStorage(m_file_bucket_storage.get(), 0, static_cast<u32>(header.file_bucket_size)),
|
||||
fs::SubStorage(m_file_entry_storage.get(), 0, static_cast<u32>(header.file_entry_size))));
|
||||
|
||||
/* Set members. */
|
||||
this->entry_size = header.body_offset;
|
||||
this->base_storage = base;
|
||||
m_entry_size = header.body_offset;
|
||||
m_base_storage = base;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result RomFsFileSystem::Initialize(std::shared_ptr<fs::IStorage> base, void *work, size_t work_size, bool use_cache) {
|
||||
this->shared_storage = std::move(base);
|
||||
return this->Initialize(this->shared_storage.get(), work, work_size, use_cache);
|
||||
m_shared_storage = std::move(base);
|
||||
return this->Initialize(m_shared_storage.get(), work, work_size, use_cache);
|
||||
}
|
||||
|
||||
Result RomFsFileSystem::GetFileInfo(RomFileTable::FileInfo *out, const char *path) {
|
||||
R_TRY(buffers::DoContinuouslyUntilBufferIsAllocated([=, this]() -> Result {
|
||||
R_TRY_CATCH(this->rom_file_table.OpenFile(out, path)) {
|
||||
R_TRY_CATCH(m_rom_file_table.OpenFile(out, path)) {
|
||||
R_CONVERT(fs::ResultDbmNotFound, fs::ResultPathNotFound());
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
@@ -295,7 +295,7 @@ namespace ams::fssystem {
|
||||
Result RomFsFileSystem::GetFileBaseOffset(s64 *out, const char *path) {
|
||||
RomFileTable::FileInfo info;
|
||||
R_TRY(this->GetFileInfo(std::addressof(info), path));
|
||||
*out = this->entry_size + info.offset.Get();
|
||||
*out = m_entry_size + info.offset.Get();
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
@@ -338,7 +338,7 @@ namespace ams::fssystem {
|
||||
R_TRY(buffers::DoContinuouslyUntilBufferIsAllocated([=, this]() -> Result {
|
||||
fs::RomDirectoryInfo dir_info;
|
||||
|
||||
R_TRY_CATCH(this->rom_file_table.GetDirectoryInformation(std::addressof(dir_info), path)) {
|
||||
R_TRY_CATCH(m_rom_file_table.GetDirectoryInformation(std::addressof(dir_info), path)) {
|
||||
R_CONVERT(fs::ResultDbmNotFound, fs::ResultPathNotFound())
|
||||
R_CATCH(fs::ResultDbmInvalidOperation) {
|
||||
RomFileTable::FileInfo file_info;
|
||||
@@ -362,7 +362,7 @@ namespace ams::fssystem {
|
||||
RomFileTable::FileInfo file_info;
|
||||
R_TRY(this->GetFileInfo(std::addressof(file_info), path));
|
||||
|
||||
auto file = std::make_unique<RomFsFile>(this, this->entry_size + file_info.offset.Get(), this->entry_size + file_info.offset.Get() + file_info.size.Get());
|
||||
auto file = std::make_unique<RomFsFile>(this, m_entry_size + file_info.offset.Get(), m_entry_size + file_info.offset.Get() + file_info.size.Get());
|
||||
R_UNLESS(file != nullptr, fs::ResultAllocationFailureInRomFsFileSystemC());
|
||||
|
||||
*out_file = std::move(file);
|
||||
@@ -372,7 +372,7 @@ namespace ams::fssystem {
|
||||
Result RomFsFileSystem::DoOpenDirectory(std::unique_ptr<fs::fsa::IDirectory> *out_dir, const char *path, fs::OpenDirectoryMode mode) {
|
||||
RomFileTable::FindPosition find;
|
||||
R_TRY(buffers::DoContinuouslyUntilBufferIsAllocated([&]() -> Result {
|
||||
R_TRY_CATCH(this->rom_file_table.FindOpen(std::addressof(find), path)) {
|
||||
R_TRY_CATCH(m_rom_file_table.FindOpen(std::addressof(find), path)) {
|
||||
R_CONVERT(fs::ResultDbmNotFound, fs::ResultPathNotFound())
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
|
||||
@@ -20,20 +20,20 @@ namespace ams::fssystem {
|
||||
SubDirectoryFileSystem::SubDirectoryFileSystem(std::shared_ptr<fs::fsa::IFileSystem> fs, const char *bp, bool unc)
|
||||
: PathResolutionFileSystem(fs, unc)
|
||||
{
|
||||
this->base_path = nullptr;
|
||||
m_base_path = nullptr;
|
||||
R_ABORT_UNLESS(this->Initialize(bp));
|
||||
}
|
||||
|
||||
SubDirectoryFileSystem::SubDirectoryFileSystem(std::unique_ptr<fs::fsa::IFileSystem> fs, const char *bp, bool unc)
|
||||
: PathResolutionFileSystem(std::move(fs), unc)
|
||||
{
|
||||
this->base_path = nullptr;
|
||||
m_base_path = nullptr;
|
||||
R_ABORT_UNLESS(this->Initialize(bp));
|
||||
}
|
||||
|
||||
SubDirectoryFileSystem::~SubDirectoryFileSystem() {
|
||||
if (this->base_path != nullptr) {
|
||||
fs::impl::Deallocate(this->base_path, this->base_path_len);
|
||||
if (m_base_path != nullptr) {
|
||||
fs::impl::Deallocate(m_base_path, m_base_path_len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,25 +56,25 @@ namespace ams::fssystem {
|
||||
}
|
||||
|
||||
/* Allocate new path. */
|
||||
this->base_path_len = normalized_path_len + 1;
|
||||
this->base_path = static_cast<char *>(fs::impl::Allocate(this->base_path_len));
|
||||
R_UNLESS(this->base_path != nullptr, fs::ResultAllocationFailureInSubDirectoryFileSystem());
|
||||
m_base_path_len = normalized_path_len + 1;
|
||||
m_base_path = static_cast<char *>(fs::impl::Allocate(m_base_path_len));
|
||||
R_UNLESS(m_base_path != nullptr, fs::ResultAllocationFailureInSubDirectoryFileSystem());
|
||||
|
||||
/* Copy path in. */
|
||||
std::memcpy(this->base_path, normalized_path, normalized_path_len);
|
||||
this->base_path[normalized_path_len] = fs::StringTraits::NullTerminator;
|
||||
std::memcpy(m_base_path, normalized_path, normalized_path_len);
|
||||
m_base_path[normalized_path_len] = fs::StringTraits::NullTerminator;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result SubDirectoryFileSystem::ResolveFullPath(char *out, size_t out_size, const char *relative_path) {
|
||||
/* Ensure path will fit. */
|
||||
R_UNLESS(this->base_path_len + strnlen(relative_path, fs::EntryNameLengthMax + 1) <= out_size, fs::ResultTooLongPath());
|
||||
R_UNLESS(m_base_path_len + strnlen(relative_path, fs::EntryNameLengthMax + 1) <= out_size, fs::ResultTooLongPath());
|
||||
|
||||
/* Copy base path. */
|
||||
std::memcpy(out, this->base_path, this->base_path_len);
|
||||
std::memcpy(out, m_base_path, m_base_path_len);
|
||||
|
||||
/* Normalize it. */
|
||||
const size_t prefix_size = this->base_path_len - 2;
|
||||
const size_t prefix_size = m_base_path_len - 2;
|
||||
size_t normalized_len;
|
||||
return fs::PathNormalizer::Normalize(out + prefix_size, std::addressof(normalized_len), relative_path, out_size - prefix_size, this->IsUncPreserved(), false);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
namespace ams::fssystem::save {
|
||||
|
||||
BlockCacheBufferedStorage::BlockCacheBufferedStorage()
|
||||
: buffer_manager(), mutex(), entries(), data_storage(), last_result(ResultSuccess()), data_size(), verification_block_size(), verification_block_shift(), invalidate_index(), max_cache_entry_count(), flags(), buffer_level(-1)
|
||||
: m_buffer_manager(), m_mutex(), m_entries(), m_data_storage(), m_last_result(ResultSuccess()), m_data_size(), m_verification_block_size(), m_verification_block_shift(), m_invalidate_index(), m_max_cache_entry_count(), m_flags(), m_buffer_level(-1)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
@@ -32,35 +32,35 @@ namespace ams::fssystem::save {
|
||||
AMS_ASSERT(data != nullptr);
|
||||
AMS_ASSERT(bm != nullptr);
|
||||
AMS_ASSERT(mtx != nullptr);
|
||||
AMS_ASSERT(this->buffer_manager == nullptr);
|
||||
AMS_ASSERT(this->mutex == nullptr);
|
||||
AMS_ASSERT(this->data_storage == nullptr);
|
||||
AMS_ASSERT(this->entries == nullptr);
|
||||
AMS_ASSERT(m_buffer_manager == nullptr);
|
||||
AMS_ASSERT(m_mutex == nullptr);
|
||||
AMS_ASSERT(m_data_storage == nullptr);
|
||||
AMS_ASSERT(m_entries == nullptr);
|
||||
AMS_ASSERT(max_cache_entries > 0);
|
||||
|
||||
/* Create the entry. */
|
||||
this->entries = fs::impl::MakeUnique<CacheEntry[]>(static_cast<size_t>(max_cache_entries));
|
||||
R_UNLESS(this->entries != nullptr, fs::ResultAllocationFailureInBlockCacheBufferedStorageA());
|
||||
m_entries = fs::impl::MakeUnique<CacheEntry[]>(static_cast<size_t>(max_cache_entries));
|
||||
R_UNLESS(m_entries != nullptr, fs::ResultAllocationFailureInBlockCacheBufferedStorageA());
|
||||
|
||||
/* Set members. */
|
||||
this->buffer_manager = bm;
|
||||
this->mutex = mtx;
|
||||
this->data_storage = data;
|
||||
this->data_size = data_size;
|
||||
this->verification_block_size = verif_block_size;
|
||||
this->last_result = ResultSuccess();
|
||||
this->invalidate_index = 0;
|
||||
this->max_cache_entry_count = max_cache_entries;
|
||||
this->flags = 0;
|
||||
this->buffer_level = buffer_level;
|
||||
this->storage_type = storage_type;
|
||||
m_buffer_manager = bm;
|
||||
m_mutex = mtx;
|
||||
m_data_storage = data;
|
||||
m_data_size = data_size;
|
||||
m_verification_block_size = verif_block_size;
|
||||
m_last_result = ResultSuccess();
|
||||
m_invalidate_index = 0;
|
||||
m_max_cache_entry_count = max_cache_entries;
|
||||
m_flags = 0;
|
||||
m_buffer_level = buffer_level;
|
||||
m_storage_type = storage_type;
|
||||
|
||||
/* Calculate block shift. */
|
||||
this->verification_block_shift = ILog2(static_cast<u32>(verif_block_size));
|
||||
AMS_ASSERT(static_cast<size_t>(1ull << this->verification_block_size) == this->verification_block_size);
|
||||
m_verification_block_shift = ILog2(static_cast<u32>(verif_block_size));
|
||||
AMS_ASSERT(static_cast<size_t>(1ull << m_verification_block_size) == m_verification_block_size);
|
||||
|
||||
/* Clear the entry. */
|
||||
std::memset(this->entries.get(), 0, sizeof(CacheEntry) * this->max_cache_entry_count);
|
||||
std::memset(m_entries.get(), 0, sizeof(CacheEntry) * m_max_cache_entry_count);
|
||||
|
||||
/* Set burst mode. */
|
||||
this->SetKeepBurstMode(is_keep_burst_mode);
|
||||
@@ -72,31 +72,31 @@ namespace ams::fssystem::save {
|
||||
}
|
||||
|
||||
void BlockCacheBufferedStorage::Finalize() {
|
||||
if (this->entries != nullptr) {
|
||||
if (m_entries != nullptr) {
|
||||
/* Invalidate all cache entries. */
|
||||
this->InvalidateAllCacheEntries();
|
||||
|
||||
/* Clear members. */
|
||||
this->buffer_manager = nullptr;
|
||||
this->mutex = nullptr;
|
||||
this->data_storage = nullptr;
|
||||
this->data_size = 0;
|
||||
this->verification_block_size = 0;
|
||||
this->verification_block_shift = 0;
|
||||
this->invalidate_index = 0;
|
||||
this->max_cache_entry_count = 0;
|
||||
m_buffer_manager = nullptr;
|
||||
m_mutex = nullptr;
|
||||
m_data_storage = nullptr;
|
||||
m_data_size = 0;
|
||||
m_verification_block_size = 0;
|
||||
m_verification_block_shift = 0;
|
||||
m_invalidate_index = 0;
|
||||
m_max_cache_entry_count = 0;
|
||||
|
||||
this->entries.reset();
|
||||
m_entries.reset();
|
||||
}
|
||||
}
|
||||
|
||||
Result BlockCacheBufferedStorage::Read(s64 offset, void *buffer, size_t size) {
|
||||
/* Validate pre-conditions. */
|
||||
AMS_ASSERT(this->data_storage != nullptr);
|
||||
AMS_ASSERT(this->buffer_manager != nullptr);
|
||||
AMS_ASSERT(m_data_storage != nullptr);
|
||||
AMS_ASSERT(m_buffer_manager != nullptr);
|
||||
|
||||
/* Ensure we aren't already in a failed state. */
|
||||
R_TRY(this->last_result);
|
||||
R_TRY(m_last_result);
|
||||
|
||||
/* Succeed if zero-size. */
|
||||
R_SUCCEED_IF(size == 0);
|
||||
@@ -108,18 +108,18 @@ namespace ams::fssystem::save {
|
||||
s64 read_offset = offset;
|
||||
size_t read_size = size;
|
||||
|
||||
R_UNLESS(read_offset < this->data_size, fs::ResultInvalidOffset());
|
||||
R_UNLESS(read_offset < m_data_size, fs::ResultInvalidOffset());
|
||||
|
||||
if (static_cast<s64>(read_offset + read_size) > this->data_size) {
|
||||
read_size = static_cast<size_t>(this->data_size - read_offset);
|
||||
if (static_cast<s64>(read_offset + read_size) > m_data_size) {
|
||||
read_size = static_cast<size_t>(m_data_size - read_offset);
|
||||
}
|
||||
|
||||
/* Determine the aligned range to read. */
|
||||
const size_t block_alignment = this->verification_block_size;
|
||||
const size_t block_alignment = m_verification_block_size;
|
||||
s64 aligned_offset = util::AlignDown(read_offset, block_alignment);
|
||||
s64 aligned_offset_end = util::AlignUp(read_offset + read_size, block_alignment);
|
||||
|
||||
AMS_ASSERT(0 <= aligned_offset && aligned_offset_end <= static_cast<s64>(util::AlignUp(this->data_size, block_alignment)));
|
||||
AMS_ASSERT(0 <= aligned_offset && aligned_offset_end <= static_cast<s64>(util::AlignUp(m_data_size, block_alignment)));
|
||||
|
||||
/* Try to read using cache. */
|
||||
char *dst = static_cast<char *>(buffer);
|
||||
@@ -183,7 +183,7 @@ namespace ams::fssystem::save {
|
||||
R_TRY(this->UpdateLastResult(this->FlushRangeCacheEntries(read_offset, aligned_size, false)));
|
||||
|
||||
/* Read the data. */
|
||||
R_TRY(this->UpdateLastResult(this->data_storage->Read(read_offset, dst, aligned_size)));
|
||||
R_TRY(this->UpdateLastResult(m_data_storage->Read(read_offset, dst, aligned_size)));
|
||||
|
||||
/* Advance. */
|
||||
dst += aligned_size;
|
||||
@@ -202,7 +202,7 @@ namespace ams::fssystem::save {
|
||||
|
||||
/* If the entry isn't cached, read the data. */
|
||||
if (!entry.is_cached) {
|
||||
if (Result result = this->data_storage->Read(entry.offset, src, entry.size); R_FAILED(result)) {
|
||||
if (Result result = m_data_storage->Read(entry.offset, src, entry.size); R_FAILED(result)) {
|
||||
this->DestroyBuffer(std::addressof(entry), range);
|
||||
return this->UpdateLastResult(result);
|
||||
}
|
||||
@@ -243,11 +243,11 @@ namespace ams::fssystem::save {
|
||||
|
||||
Result BlockCacheBufferedStorage::Write(s64 offset, const void *buffer, size_t size) {
|
||||
/* Validate pre-conditions. */
|
||||
AMS_ASSERT(this->data_storage != nullptr);
|
||||
AMS_ASSERT(this->buffer_manager != nullptr);
|
||||
AMS_ASSERT(m_data_storage != nullptr);
|
||||
AMS_ASSERT(m_buffer_manager != nullptr);
|
||||
|
||||
/* Ensure we aren't already in a failed state. */
|
||||
R_TRY(this->last_result);
|
||||
R_TRY(m_last_result);
|
||||
|
||||
/* Succeed if zero-size. */
|
||||
R_SUCCEED_IF(size == 0);
|
||||
@@ -256,21 +256,21 @@ namespace ams::fssystem::save {
|
||||
R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument());
|
||||
|
||||
/* Determine the extents to read. */
|
||||
R_UNLESS(offset < this->data_size, fs::ResultInvalidOffset());
|
||||
R_UNLESS(offset < m_data_size, fs::ResultInvalidOffset());
|
||||
|
||||
if (static_cast<s64>(offset + size) > this->data_size) {
|
||||
size = static_cast<size_t>(this->data_size - offset);
|
||||
if (static_cast<s64>(offset + size) > m_data_size) {
|
||||
size = static_cast<size_t>(m_data_size - offset);
|
||||
}
|
||||
|
||||
/* The actual extents may be zero-size, so succeed if that's the case. */
|
||||
R_SUCCEED_IF(size == 0);
|
||||
|
||||
/* Determine the aligned range to read. */
|
||||
const size_t block_alignment = this->verification_block_size;
|
||||
const size_t block_alignment = m_verification_block_size;
|
||||
s64 aligned_offset = util::AlignDown(offset, block_alignment);
|
||||
const s64 aligned_offset_end = util::AlignUp(offset + size, block_alignment);
|
||||
|
||||
AMS_ASSERT(0 <= aligned_offset && aligned_offset_end <= static_cast<s64>(util::AlignUp(this->data_size, block_alignment)));
|
||||
AMS_ASSERT(0 <= aligned_offset && aligned_offset_end <= static_cast<s64>(util::AlignUp(m_data_size, block_alignment)));
|
||||
|
||||
/* Write the data. */
|
||||
const u8 *src = static_cast<const u8 *>(buffer);
|
||||
@@ -283,7 +283,7 @@ namespace ams::fssystem::save {
|
||||
R_TRY(this->UpdateLastResult(this->FlushRangeCacheEntries(offset, aligned_size, true)));
|
||||
|
||||
/* Read the data. */
|
||||
R_TRY(this->UpdateLastResult(this->data_storage->Write(offset, src, aligned_size)));
|
||||
R_TRY(this->UpdateLastResult(m_data_storage->Write(offset, src, aligned_size)));
|
||||
|
||||
/* Set blocking buffer manager allocations. */
|
||||
buffers::EnableBlockingBufferManagerAllocation();
|
||||
@@ -304,7 +304,7 @@ namespace ams::fssystem::save {
|
||||
|
||||
/* If the entry isn't cached and we're writing a partial entry, read in the entry. */
|
||||
if (!entry.is_cached && ((offset != entry.offset) || (offset + size < entry.offset + entry.size))) {
|
||||
if (Result result = this->data_storage->Read(entry.offset, dst, entry.size); R_FAILED(result)) {
|
||||
if (Result result = m_data_storage->Read(entry.offset, dst, entry.size); R_FAILED(result)) {
|
||||
this->DestroyBuffer(std::addressof(entry), range);
|
||||
return this->UpdateLastResult(result);
|
||||
}
|
||||
@@ -349,7 +349,7 @@ namespace ams::fssystem::save {
|
||||
}
|
||||
|
||||
/* Ensure that didn't end up in a failure state. */
|
||||
R_TRY(this->last_result);
|
||||
R_TRY(m_last_result);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -357,26 +357,26 @@ namespace ams::fssystem::save {
|
||||
Result BlockCacheBufferedStorage::GetSize(s64 *out) {
|
||||
/* Validate pre-conditions. */
|
||||
AMS_ASSERT(out != nullptr);
|
||||
AMS_ASSERT(this->data_storage != nullptr);
|
||||
AMS_ASSERT(m_data_storage != nullptr);
|
||||
|
||||
/* Set the size. */
|
||||
*out = this->data_size;
|
||||
*out = m_data_size;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result BlockCacheBufferedStorage::Flush() {
|
||||
/* Validate pre-conditions. */
|
||||
AMS_ASSERT(this->data_storage != nullptr);
|
||||
AMS_ASSERT(this->buffer_manager != nullptr);
|
||||
AMS_ASSERT(m_data_storage != nullptr);
|
||||
AMS_ASSERT(m_buffer_manager != nullptr);
|
||||
|
||||
/* Ensure we aren't already in a failed state. */
|
||||
R_TRY(this->last_result);
|
||||
R_TRY(m_last_result);
|
||||
|
||||
/* Flush all cache entries. */
|
||||
R_TRY(this->UpdateLastResult(this->FlushAllCacheEntries()));
|
||||
|
||||
/* Flush the data storage. */
|
||||
R_TRY(this->UpdateLastResult(this->data_storage->Flush()));
|
||||
R_TRY(this->UpdateLastResult(m_data_storage->Flush()));
|
||||
|
||||
/* Set blocking buffer manager allocations. */
|
||||
buffers::EnableBlockingBufferManagerAllocation();
|
||||
@@ -388,7 +388,7 @@ namespace ams::fssystem::save {
|
||||
AMS_UNUSED(src, src_size);
|
||||
|
||||
/* Validate pre-conditions. */
|
||||
AMS_ASSERT(this->data_storage != nullptr);
|
||||
AMS_ASSERT(m_data_storage != nullptr);
|
||||
|
||||
switch (op_id) {
|
||||
case fs::OperationId::FillZero:
|
||||
@@ -403,7 +403,7 @@ namespace ams::fssystem::save {
|
||||
}
|
||||
case fs::OperationId::Invalidate:
|
||||
{
|
||||
R_UNLESS(this->storage_type != fs::StorageType_SaveData, fs::ResultUnsupportedOperationInBlockCacheBufferedStorageB());
|
||||
R_UNLESS(m_storage_type != fs::StorageType_SaveData, fs::ResultUnsupportedOperationInBlockCacheBufferedStorageB());
|
||||
R_TRY(this->InvalidateCacheImpl(offset, size));
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -419,11 +419,11 @@ namespace ams::fssystem::save {
|
||||
|
||||
Result BlockCacheBufferedStorage::Commit() {
|
||||
/* Validate pre-conditions. */
|
||||
AMS_ASSERT(this->data_storage != nullptr);
|
||||
AMS_ASSERT(this->buffer_manager != nullptr);
|
||||
AMS_ASSERT(m_data_storage != nullptr);
|
||||
AMS_ASSERT(m_buffer_manager != nullptr);
|
||||
|
||||
/* Ensure we aren't already in a failed state. */
|
||||
R_TRY(this->last_result);
|
||||
R_TRY(m_last_result);
|
||||
|
||||
/* Flush all cache entries. */
|
||||
R_TRY(this->UpdateLastResult(this->FlushAllCacheEntries()));
|
||||
@@ -433,38 +433,38 @@ namespace ams::fssystem::save {
|
||||
|
||||
Result BlockCacheBufferedStorage::OnRollback() {
|
||||
/* Validate pre-conditions. */
|
||||
AMS_ASSERT(this->buffer_manager != nullptr);
|
||||
AMS_ASSERT(m_buffer_manager != nullptr);
|
||||
|
||||
/* Ensure we aren't already in a failed state. */
|
||||
R_TRY(this->last_result);
|
||||
R_TRY(m_last_result);
|
||||
|
||||
/* Release all valid entries back to the buffer manager. */
|
||||
const auto max_cache_entry_count = this->GetMaxCacheEntryCount();
|
||||
for (s32 i = 0; i < max_cache_entry_count; i++) {
|
||||
const auto &entry = this->entries[i];
|
||||
const auto &entry = m_entries[i];
|
||||
if (entry.is_valid) {
|
||||
if (entry.is_write_back) {
|
||||
AMS_ASSERT(entry.memory_address != 0 && entry.handle == 0);
|
||||
this->buffer_manager->DeallocateBuffer(entry.memory_address, entry.memory_size);
|
||||
m_buffer_manager->DeallocateBuffer(entry.memory_address, entry.memory_size);
|
||||
} else {
|
||||
AMS_ASSERT(entry.memory_address == 0 && entry.handle != 0);
|
||||
const auto memory_range = this->buffer_manager->AcquireCache(entry.handle);
|
||||
const auto memory_range = m_buffer_manager->AcquireCache(entry.handle);
|
||||
if (memory_range.first != 0) {
|
||||
this->buffer_manager->DeallocateBuffer(memory_range.first, memory_range.second);
|
||||
m_buffer_manager->DeallocateBuffer(memory_range.first, memory_range.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear all entries. */
|
||||
std::memset(this->entries.get(), 0, sizeof(CacheEntry) * max_cache_entry_count);
|
||||
std::memset(m_entries.get(), 0, sizeof(CacheEntry) * max_cache_entry_count);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result BlockCacheBufferedStorage::ClearImpl(s64 offset, s64 size) {
|
||||
/* Ensure we aren't already in a failed state. */
|
||||
R_TRY(this->last_result);
|
||||
R_TRY(m_last_result);
|
||||
|
||||
/* Get our storage size. */
|
||||
s64 storage_size = 0;
|
||||
@@ -474,8 +474,8 @@ namespace ams::fssystem::save {
|
||||
R_UNLESS(0 <= offset && offset < storage_size, fs::ResultInvalidOffset());
|
||||
|
||||
/* Determine the extents to data signature for. */
|
||||
auto start_offset = util::AlignDown(offset, this->verification_block_size);
|
||||
auto end_offset = util::AlignUp(std::min(offset + size, storage_size), this->verification_block_size);
|
||||
auto start_offset = util::AlignDown(offset, m_verification_block_size);
|
||||
auto end_offset = util::AlignUp(std::min(offset + size, storage_size), m_verification_block_size);
|
||||
|
||||
/* Flush the entries. */
|
||||
R_TRY(this->UpdateLastResult(this->FlushRangeCacheEntries(offset, size, true)));
|
||||
@@ -483,26 +483,26 @@ namespace ams::fssystem::save {
|
||||
/* Handle any data before or after the aligned range. */
|
||||
if (start_offset < offset || offset + size < end_offset) {
|
||||
/* Allocate a work buffer. */
|
||||
std::unique_ptr<char[], fs::impl::Deleter> work = fs::impl::MakeUnique<char[]>(this->verification_block_size);
|
||||
std::unique_ptr<char[], fs::impl::Deleter> work = fs::impl::MakeUnique<char[]>(m_verification_block_size);
|
||||
R_UNLESS(work != nullptr, fs::ResultAllocationFailureInBlockCacheBufferedStorageB());
|
||||
|
||||
/* Handle data before the aligned range. */
|
||||
if (start_offset < offset) {
|
||||
/* Read the block. */
|
||||
R_TRY(this->UpdateLastResult(this->data_storage->Read(start_offset, work.get(), this->verification_block_size)));
|
||||
R_TRY(this->UpdateLastResult(m_data_storage->Read(start_offset, work.get(), m_verification_block_size)));
|
||||
|
||||
/* Determine the partial extents to clear. */
|
||||
const auto clear_offset = static_cast<size_t>(offset - start_offset);
|
||||
const auto clear_size = static_cast<size_t>(std::min(static_cast<s64>(this->verification_block_size - clear_offset), size));
|
||||
const auto clear_size = static_cast<size_t>(std::min(static_cast<s64>(m_verification_block_size - clear_offset), size));
|
||||
|
||||
/* Clear the partial block. */
|
||||
std::memset(work.get() + clear_offset, 0, clear_size);
|
||||
|
||||
/* Write the partially cleared block. */
|
||||
R_TRY(this->UpdateLastResult(this->data_storage->Write(start_offset, work.get(), this->verification_block_size)));
|
||||
R_TRY(this->UpdateLastResult(m_data_storage->Write(start_offset, work.get(), m_verification_block_size)));
|
||||
|
||||
/* Update the start offset. */
|
||||
start_offset += this->verification_block_size;
|
||||
start_offset += m_verification_block_size;
|
||||
|
||||
/* Set blocking buffer manager allocations. */
|
||||
buffers::EnableBlockingBufferManagerAllocation();
|
||||
@@ -511,18 +511,18 @@ namespace ams::fssystem::save {
|
||||
/* Handle data after the aligned range. */
|
||||
if (start_offset < offset + size && offset + size < end_offset) {
|
||||
/* Read the block. */
|
||||
const auto last_offset = end_offset - this->verification_block_size;
|
||||
R_TRY(this->UpdateLastResult(this->data_storage->Read(last_offset, work.get(), this->verification_block_size)));
|
||||
const auto last_offset = end_offset - m_verification_block_size;
|
||||
R_TRY(this->UpdateLastResult(m_data_storage->Read(last_offset, work.get(), m_verification_block_size)));
|
||||
|
||||
/* Clear the partial block. */
|
||||
const auto clear_size = static_cast<size_t>((offset + size) - last_offset);
|
||||
std::memset(work.get(), 0, clear_size);
|
||||
|
||||
/* Write the partially cleared block. */
|
||||
R_TRY(this->UpdateLastResult(this->data_storage->Write(last_offset, work.get(), this->verification_block_size)));
|
||||
R_TRY(this->UpdateLastResult(m_data_storage->Write(last_offset, work.get(), m_verification_block_size)));
|
||||
|
||||
/* Update the end offset. */
|
||||
end_offset -= this->verification_block_size;
|
||||
end_offset -= m_verification_block_size;
|
||||
|
||||
/* Set blocking buffer manager allocations. */
|
||||
buffers::EnableBlockingBufferManagerAllocation();
|
||||
@@ -533,7 +533,7 @@ namespace ams::fssystem::save {
|
||||
R_SUCCEED_IF(start_offset == end_offset);
|
||||
|
||||
/* Clear the signature for the aligned range. */
|
||||
R_TRY(this->UpdateLastResult(this->data_storage->OperateRange(fs::OperationId::FillZero, start_offset, end_offset - start_offset)));
|
||||
R_TRY(this->UpdateLastResult(m_data_storage->OperateRange(fs::OperationId::FillZero, start_offset, end_offset - start_offset)));
|
||||
|
||||
/* Set blocking buffer manager allocations. */
|
||||
buffers::EnableBlockingBufferManagerAllocation();
|
||||
@@ -543,7 +543,7 @@ namespace ams::fssystem::save {
|
||||
|
||||
Result BlockCacheBufferedStorage::ClearSignatureImpl(s64 offset, s64 size) {
|
||||
/* Ensure we aren't already in a failed state. */
|
||||
R_TRY(this->last_result);
|
||||
R_TRY(m_last_result);
|
||||
|
||||
/* Get our storage size. */
|
||||
s64 storage_size = 0;
|
||||
@@ -553,14 +553,14 @@ namespace ams::fssystem::save {
|
||||
R_UNLESS(0 <= offset && offset < storage_size, fs::ResultInvalidOffset());
|
||||
|
||||
/* Determine the extents to clear signature for. */
|
||||
const auto start_offset = util::AlignUp(offset, this->verification_block_size);
|
||||
const auto end_offset = util::AlignDown(std::min(offset + size, storage_size), this->verification_block_size);
|
||||
const auto start_offset = util::AlignUp(offset, m_verification_block_size);
|
||||
const auto end_offset = util::AlignDown(std::min(offset + size, storage_size), m_verification_block_size);
|
||||
|
||||
/* Flush the entries. */
|
||||
R_TRY(this->UpdateLastResult(this->FlushRangeCacheEntries(offset, size, true)));
|
||||
|
||||
/* Clear the signature for the aligned range. */
|
||||
R_TRY(this->UpdateLastResult(this->data_storage->OperateRange(fs::OperationId::DestroySignature, start_offset, end_offset - start_offset)));
|
||||
R_TRY(this->UpdateLastResult(m_data_storage->OperateRange(fs::OperationId::DestroySignature, start_offset, end_offset - start_offset)));
|
||||
|
||||
/* Set blocking buffer manager allocations. */
|
||||
buffers::EnableBlockingBufferManagerAllocation();
|
||||
@@ -579,20 +579,20 @@ namespace ams::fssystem::save {
|
||||
|
||||
/* Determine the extents we can actually query. */
|
||||
const auto actual_size = std::min(size, storage_size - offset);
|
||||
const auto aligned_offset = util::AlignDown(offset, this->verification_block_size);
|
||||
const auto aligned_offset_end = util::AlignUp(offset + actual_size, this->verification_block_size);
|
||||
const auto aligned_offset = util::AlignDown(offset, m_verification_block_size);
|
||||
const auto aligned_offset_end = util::AlignUp(offset + actual_size, m_verification_block_size);
|
||||
const auto aligned_size = aligned_offset_end - aligned_offset;
|
||||
|
||||
/* Invalidate the aligned range. */
|
||||
{
|
||||
Result result = this->data_storage->OperateRange(fs::OperationId::Invalidate, aligned_offset, aligned_size);
|
||||
Result result = m_data_storage->OperateRange(fs::OperationId::Invalidate, aligned_offset, aligned_size);
|
||||
AMS_ASSERT(!fs::ResultBufferAllocationFailed::Includes(result));
|
||||
R_TRY(result);
|
||||
}
|
||||
|
||||
/* Clear our last result if we should. */
|
||||
if (fs::ResultIntegrityVerificationStorageCorrupted::Includes(this->last_result)) {
|
||||
this->last_result = ResultSuccess();
|
||||
if (fs::ResultIntegrityVerificationStorageCorrupted::Includes(m_last_result)) {
|
||||
m_last_result = ResultSuccess();
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
@@ -605,12 +605,12 @@ namespace ams::fssystem::save {
|
||||
|
||||
/* Determine the extents we can actually query. */
|
||||
const auto actual_size = std::min(size, storage_size - offset);
|
||||
const auto aligned_offset = util::AlignDown(offset, this->verification_block_size);
|
||||
const auto aligned_offset_end = util::AlignUp(offset + actual_size, this->verification_block_size);
|
||||
const auto aligned_offset = util::AlignDown(offset, m_verification_block_size);
|
||||
const auto aligned_offset_end = util::AlignUp(offset + actual_size, m_verification_block_size);
|
||||
const auto aligned_size = aligned_offset_end - aligned_offset;
|
||||
|
||||
/* Query the aligned range. */
|
||||
R_TRY(this->UpdateLastResult(this->data_storage->OperateRange(dst, dst_size, fs::OperationId::QueryRange, aligned_offset, aligned_size, nullptr, 0)));
|
||||
R_TRY(this->UpdateLastResult(m_data_storage->OperateRange(dst, dst_size, fs::OperationId::QueryRange, aligned_offset, aligned_size, nullptr, 0)));
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -621,12 +621,12 @@ namespace ams::fssystem::save {
|
||||
const size_t size = entry.size;
|
||||
|
||||
/* Lock our mutex. */
|
||||
std::scoped_lock lk(*this->mutex);
|
||||
std::scoped_lock lk(*m_mutex);
|
||||
|
||||
/* Iterate over all entries, checking if any overlap our extents. */
|
||||
const auto max_cache_entry_count = this->GetMaxCacheEntryCount();
|
||||
for (auto i = 0; i < max_cache_entry_count; ++i) {
|
||||
const auto &entry = this->entries[i];
|
||||
const auto &entry = m_entries[i];
|
||||
if (entry.is_valid && (entry.is_write_back ? entry.memory_address != 0 : entry.handle != 0)) {
|
||||
if (entry.offset < static_cast<s64>(offset + size) && offset < static_cast<s64>(entry.offset + entry.size)) {
|
||||
return true;
|
||||
@@ -641,13 +641,13 @@ namespace ams::fssystem::save {
|
||||
AMS_UNUSED(is_allocate_for_write);
|
||||
|
||||
/* Validate pre-conditions. */
|
||||
AMS_ASSERT(this->data_storage != nullptr);
|
||||
AMS_ASSERT(this->buffer_manager != nullptr);
|
||||
AMS_ASSERT(m_data_storage != nullptr);
|
||||
AMS_ASSERT(m_buffer_manager != nullptr);
|
||||
AMS_ASSERT(out_range != nullptr);
|
||||
AMS_ASSERT(out_entry != nullptr);
|
||||
|
||||
/* Lock our mutex. */
|
||||
std::scoped_lock lk(*this->mutex);
|
||||
std::scoped_lock lk(*m_mutex);
|
||||
|
||||
/* Get the maximum cache entry count. */
|
||||
const CacheIndex max_cache_entry_count = static_cast<CacheIndex>(this->GetMaxCacheEntryCount());
|
||||
@@ -656,7 +656,7 @@ namespace ams::fssystem::save {
|
||||
CacheIndex index;
|
||||
size_t actual_size = ideal_size;
|
||||
for (index = 0; index < max_cache_entry_count; ++index) {
|
||||
const auto &entry = this->entries[index];
|
||||
const auto &entry = m_entries[index];
|
||||
if (entry.is_valid && (entry.is_write_back ? entry.memory_address != 0 : entry.handle != 0)) {
|
||||
const s64 entry_offset = entry.offset;
|
||||
if (entry_offset <= offset && offset < static_cast<s64>(entry_offset + entry.size)) {
|
||||
@@ -675,13 +675,13 @@ namespace ams::fssystem::save {
|
||||
|
||||
/* If we located an entry, use it. */
|
||||
if (index != max_cache_entry_count) {
|
||||
auto &entry = this->entries[index];
|
||||
auto &entry = m_entries[index];
|
||||
|
||||
/* Get the range of the found entry. */
|
||||
if (entry.is_write_back) {
|
||||
*out_range = std::make_pair(entry.memory_address, entry.memory_size);
|
||||
} else {
|
||||
*out_range = this->buffer_manager->AcquireCache(entry.handle);
|
||||
*out_range = m_buffer_manager->AcquireCache(entry.handle);
|
||||
}
|
||||
|
||||
/* Get the found entry. */
|
||||
@@ -705,13 +705,13 @@ namespace ams::fssystem::save {
|
||||
/* If we don't have an out entry, allocate one. */
|
||||
if (out_range->first == 0) {
|
||||
/* Ensure that the allocatable size is above a threshold. */
|
||||
const auto size_threshold = this->buffer_manager->GetTotalSize() / 8;
|
||||
if (this->buffer_manager->GetTotalAllocatableSize() < size_threshold) {
|
||||
const auto size_threshold = m_buffer_manager->GetTotalSize() / 8;
|
||||
if (m_buffer_manager->GetTotalAllocatableSize() < size_threshold) {
|
||||
R_TRY(this->FlushAllCacheEntries());
|
||||
}
|
||||
|
||||
/* Decide in advance on a block alignment. */
|
||||
const size_t block_alignment = this->verification_block_size;
|
||||
const size_t block_alignment = m_verification_block_size;
|
||||
|
||||
/* Ensure that the size we request is valid. */
|
||||
{
|
||||
@@ -721,7 +721,7 @@ namespace ams::fssystem::save {
|
||||
AMS_ASSERT(actual_size >= block_alignment);
|
||||
|
||||
/* Allocate a buffer. */
|
||||
R_TRY(buffers::AllocateBufferUsingBufferManagerContext(out_range, this->buffer_manager, actual_size, IBufferManager::BufferAttribute(this->buffer_level), [=](const MemoryRange &buffer) {
|
||||
R_TRY(buffers::AllocateBufferUsingBufferManagerContext(out_range, m_buffer_manager, actual_size, IBufferManager::BufferAttribute(m_buffer_level), [=](const MemoryRange &buffer) {
|
||||
return buffer.first != 0 && block_alignment <= buffer.second;
|
||||
}, AMS_CURRENT_FUNCTION_NAME));
|
||||
|
||||
@@ -748,7 +748,7 @@ namespace ams::fssystem::save {
|
||||
|
||||
void BlockCacheBufferedStorage::DestroyBuffer(CacheEntry *entry, const MemoryRange &range) {
|
||||
/* Validate pre-conditions. */
|
||||
AMS_ASSERT(this->buffer_manager != nullptr);
|
||||
AMS_ASSERT(m_buffer_manager != nullptr);
|
||||
AMS_ASSERT(entry != nullptr);
|
||||
|
||||
/* Set the entry as invalid and not cached. */
|
||||
@@ -756,7 +756,7 @@ namespace ams::fssystem::save {
|
||||
entry->is_valid = false;
|
||||
|
||||
/* Release the entry. */
|
||||
this->buffer_manager->DeallocateBuffer(range.first, range.second);
|
||||
m_buffer_manager->DeallocateBuffer(range.first, range.second);
|
||||
}
|
||||
|
||||
Result BlockCacheBufferedStorage::StoreAssociateBuffer(CacheIndex *out, const MemoryRange &range, const CacheEntry &entry) {
|
||||
@@ -764,7 +764,7 @@ namespace ams::fssystem::save {
|
||||
AMS_ASSERT(out != nullptr);
|
||||
|
||||
/* Lock our mutex. */
|
||||
std::scoped_lock lk(*this->mutex);
|
||||
std::scoped_lock lk(*m_mutex);
|
||||
|
||||
/* If the entry is write-back, ensure we don't exceed certain dirtiness thresholds. */
|
||||
if (entry.is_write_back) {
|
||||
@@ -778,7 +778,7 @@ namespace ams::fssystem::save {
|
||||
/* Locate the index of an unused cache entry. */
|
||||
CacheIndex index;
|
||||
for (index = 0; index < max_cache_entry_count; ++index) {
|
||||
if (!this->entries[index].is_valid) {
|
||||
if (!m_entries[index].is_valid) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -786,10 +786,10 @@ namespace ams::fssystem::save {
|
||||
/* If all entries are valid, we need to invalidate one. */
|
||||
if (index == max_cache_entry_count) {
|
||||
/* Increment the index to invalidate. */
|
||||
this->invalidate_index = (this->invalidate_index + 1) % max_cache_entry_count;
|
||||
m_invalidate_index = (m_invalidate_index + 1) % max_cache_entry_count;
|
||||
|
||||
/* Get the entry to invalidate. */
|
||||
const CacheEntry *entry_to_invalidate = std::addressof(this->entries[this->invalidate_index]);
|
||||
const CacheEntry *entry_to_invalidate = std::addressof(m_entries[m_invalidate_index]);
|
||||
AMS_UNUSED(entry_to_invalidate);
|
||||
|
||||
/* Ensure that the entry can be invalidated. */
|
||||
@@ -797,17 +797,17 @@ namespace ams::fssystem::save {
|
||||
AMS_ASSERT(!entry_to_invalidate->is_flushing);
|
||||
|
||||
/* Invalidate the entry. */
|
||||
R_TRY(this->FlushCacheEntry(this->invalidate_index, true));
|
||||
R_TRY(this->FlushCacheEntry(m_invalidate_index, true));
|
||||
|
||||
/* Check that the entry was invalidated successfully. */
|
||||
AMS_ASSERT(!entry_to_invalidate->is_valid);
|
||||
AMS_ASSERT(!entry_to_invalidate->is_flushing);
|
||||
|
||||
index = this->invalidate_index;
|
||||
index = m_invalidate_index;
|
||||
}
|
||||
|
||||
/* Store the entry. */
|
||||
CacheEntry *entry_ptr = std::addressof(this->entries[index]);
|
||||
CacheEntry *entry_ptr = std::addressof(m_entries[index]);
|
||||
*entry_ptr = entry;
|
||||
|
||||
/* Assert that the entry is valid to store. */
|
||||
@@ -824,7 +824,7 @@ namespace ams::fssystem::save {
|
||||
entry_ptr->memory_address = range.first;
|
||||
entry_ptr->memory_size = range.second;
|
||||
} else {
|
||||
entry_ptr->handle = this->buffer_manager->RegisterCache(range.first, range.second, IBufferManager::BufferAttribute(this->buffer_level));
|
||||
entry_ptr->handle = m_buffer_manager->RegisterCache(range.first, range.second, IBufferManager::BufferAttribute(m_buffer_level));
|
||||
entry_ptr->memory_address = 0;
|
||||
entry_ptr->memory_size = 0;
|
||||
}
|
||||
@@ -832,10 +832,10 @@ namespace ams::fssystem::save {
|
||||
/* Set the out index. */
|
||||
AMS_ASSERT(entry_ptr->is_valid);
|
||||
*out = index;
|
||||
this->invalidate_index = index;
|
||||
m_invalidate_index = index;
|
||||
} else {
|
||||
/* If a redundant entry exists, we don't need the newly stored entry. */
|
||||
this->buffer_manager->DeallocateBuffer(range.first, range.second);
|
||||
m_buffer_manager->DeallocateBuffer(range.first, range.second);
|
||||
entry_ptr->is_valid = false;
|
||||
*out = -1;
|
||||
}
|
||||
@@ -845,10 +845,10 @@ namespace ams::fssystem::save {
|
||||
|
||||
Result BlockCacheBufferedStorage::FlushCacheEntry(CacheIndex index, bool invalidate) {
|
||||
/* Lock our mutex. */
|
||||
std::scoped_lock lk(*this->mutex);
|
||||
std::scoped_lock lk(*m_mutex);
|
||||
|
||||
/* Get the entry. */
|
||||
CacheEntry *entry = std::addressof(this->entries[index]);
|
||||
CacheEntry *entry = std::addressof(m_entries[index]);
|
||||
MemoryRange memory_range;
|
||||
|
||||
/* Check that the entry's state allows for flush. */
|
||||
@@ -860,9 +860,9 @@ namespace ams::fssystem::save {
|
||||
AMS_ASSERT(invalidate);
|
||||
|
||||
/* Get and release the buffer. */
|
||||
memory_range = this->buffer_manager->AcquireCache(entry->handle);
|
||||
memory_range = m_buffer_manager->AcquireCache(entry->handle);
|
||||
if (memory_range.first != 0) {
|
||||
this->buffer_manager->DeallocateBuffer(memory_range.first, memory_range.second);
|
||||
m_buffer_manager->DeallocateBuffer(memory_range.first, memory_range.second);
|
||||
}
|
||||
|
||||
/* The entry is no longer valid. */
|
||||
@@ -881,20 +881,20 @@ namespace ams::fssystem::save {
|
||||
|
||||
/* Validate the entry's offset. */
|
||||
AMS_ASSERT(entry->offset >= 0);
|
||||
AMS_ASSERT(entry->offset < this->data_size);
|
||||
AMS_ASSERT(util::IsAligned(entry->offset, this->verification_block_size));
|
||||
AMS_ASSERT(entry->offset < m_data_size);
|
||||
AMS_ASSERT(util::IsAligned(entry->offset, m_verification_block_size));
|
||||
|
||||
/* Write back the data. */
|
||||
Result result = ResultSuccess();
|
||||
size_t write_size = entry->size;
|
||||
if (R_SUCCEEDED(this->last_result)) {
|
||||
if (R_SUCCEEDED(m_last_result)) {
|
||||
/* Set blocking buffer manager allocations. */
|
||||
result = this->data_storage->Write(entry->offset, reinterpret_cast<const void *>(memory_range.first), write_size);
|
||||
result = m_data_storage->Write(entry->offset, reinterpret_cast<const void *>(memory_range.first), write_size);
|
||||
|
||||
/* Check the result. */
|
||||
AMS_ASSERT(!fs::ResultBufferAllocationFailed::Includes(result));
|
||||
} else {
|
||||
result = this->last_result;
|
||||
result = m_last_result;
|
||||
}
|
||||
|
||||
/* Set that we're not write-back. */
|
||||
@@ -902,13 +902,13 @@ namespace ams::fssystem::save {
|
||||
|
||||
/* If we're invalidating, release the buffer. Otherwise, register the flushed data. */
|
||||
if (invalidate) {
|
||||
this->buffer_manager->DeallocateBuffer(memory_range.first, memory_range.second);
|
||||
m_buffer_manager->DeallocateBuffer(memory_range.first, memory_range.second);
|
||||
entry->is_valid = false;
|
||||
entry->is_flushing = false;
|
||||
} else {
|
||||
AMS_ASSERT(entry->is_valid);
|
||||
|
||||
entry->handle = this->buffer_manager->RegisterCache(memory_range.first, memory_range.second, IBufferManager::BufferAttribute(this->buffer_level));
|
||||
entry->handle = m_buffer_manager->RegisterCache(memory_range.first, memory_range.second, IBufferManager::BufferAttribute(m_buffer_level));
|
||||
|
||||
entry->memory_address = 0;
|
||||
entry->memory_size = 0;
|
||||
@@ -924,14 +924,14 @@ namespace ams::fssystem::save {
|
||||
|
||||
Result BlockCacheBufferedStorage::FlushRangeCacheEntries(s64 offset, s64 size, bool invalidate) {
|
||||
/* Validate pre-conditions. */
|
||||
AMS_ASSERT(this->data_storage != nullptr);
|
||||
AMS_ASSERT(this->buffer_manager != nullptr);
|
||||
AMS_ASSERT(m_data_storage != nullptr);
|
||||
AMS_ASSERT(m_buffer_manager != nullptr);
|
||||
|
||||
/* Iterate over all entries that fall within the range. */
|
||||
Result result = ResultSuccess();
|
||||
const auto max_cache_entry_count = this->GetMaxCacheEntryCount();
|
||||
for (auto i = 0; i < max_cache_entry_count; ++i) {
|
||||
auto &entry = this->entries[i];
|
||||
auto &entry = m_entries[i];
|
||||
if (entry.is_valid && (entry.is_write_back || invalidate) && (entry.offset < (offset + size)) && (offset < static_cast<s64>(entry.offset + entry.size))) {
|
||||
const auto cur_result = this->FlushCacheEntry(i, invalidate);
|
||||
if (R_FAILED(cur_result) && R_SUCCEEDED(result)) {
|
||||
@@ -949,22 +949,22 @@ namespace ams::fssystem::save {
|
||||
|
||||
void BlockCacheBufferedStorage::InvalidateRangeCacheEntries(s64 offset, s64 size) {
|
||||
/* Validate pre-conditions. */
|
||||
AMS_ASSERT(this->data_storage != nullptr);
|
||||
AMS_ASSERT(this->buffer_manager != nullptr);
|
||||
AMS_ASSERT(m_data_storage != nullptr);
|
||||
AMS_ASSERT(m_buffer_manager != nullptr);
|
||||
|
||||
/* Iterate over all entries that fall within the range. */
|
||||
const auto max_cache_entry_count = this->GetMaxCacheEntryCount();
|
||||
for (auto i = 0; i < max_cache_entry_count; ++i) {
|
||||
auto &entry = this->entries[i];
|
||||
auto &entry = m_entries[i];
|
||||
if (entry.is_valid && (entry.offset < (offset + size)) && (offset < static_cast<s64>(entry.offset + entry.size))) {
|
||||
if (entry.is_write_back) {
|
||||
AMS_ASSERT(entry.memory_address != 0 && entry.handle == 0);
|
||||
this->buffer_manager->DeallocateBuffer(entry.memory_address, entry.memory_size);
|
||||
m_buffer_manager->DeallocateBuffer(entry.memory_address, entry.memory_size);
|
||||
} else {
|
||||
AMS_ASSERT(entry.memory_address == 0 && entry.handle != 0);
|
||||
const auto memory_range = this->buffer_manager->AcquireCache(entry.handle);
|
||||
const auto memory_range = m_buffer_manager->AcquireCache(entry.handle);
|
||||
if (memory_range.first != 0) {
|
||||
this->buffer_manager->DeallocateBuffer(memory_range.first, memory_range.second);
|
||||
m_buffer_manager->DeallocateBuffer(memory_range.first, memory_range.second);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -992,8 +992,8 @@ namespace ams::fssystem::save {
|
||||
AMS_ASSERT(max_cache_entry_count > 0);
|
||||
|
||||
/* Get size metrics from the buffer manager. */
|
||||
const auto total_size = this->buffer_manager->GetTotalSize();
|
||||
const auto allocatable_size = this->buffer_manager->GetTotalAllocatableSize();
|
||||
const auto total_size = m_buffer_manager->GetTotalSize();
|
||||
const auto allocatable_size = m_buffer_manager->GetTotalAllocatableSize();
|
||||
|
||||
/* If we have enough allocatable space, we don't need to do anything. */
|
||||
R_SUCCEED_IF(allocatable_size >= total_size / 4);
|
||||
@@ -1001,12 +1001,12 @@ namespace ams::fssystem::save {
|
||||
/* Setup for flushing dirty entries. */
|
||||
auto threshold = 2;
|
||||
auto dirty_count = 0;
|
||||
auto flushed_index = this->invalidate_index;
|
||||
auto flushed_index = m_invalidate_index;
|
||||
|
||||
/* Iterate over all entries (starting with the invalidate index), and flush dirty entries once threshold is met. */
|
||||
for (auto i = 0; i < max_cache_entry_count; ++i) {
|
||||
auto index = (this->invalidate_index + 1 + i) % max_cache_entry_count;
|
||||
if (this->entries[index].is_valid && this->entries[index].is_write_back) {
|
||||
auto index = (m_invalidate_index + 1 + i) % max_cache_entry_count;
|
||||
if (m_entries[index].is_valid && m_entries[index].is_write_back) {
|
||||
++dirty_count;
|
||||
if (threshold <= dirty_count) {
|
||||
R_TRY(this->FlushCacheEntry(index, false));
|
||||
@@ -1016,15 +1016,15 @@ namespace ams::fssystem::save {
|
||||
}
|
||||
|
||||
/* Update the invalidate index. */
|
||||
this->invalidate_index = flushed_index;
|
||||
m_invalidate_index = flushed_index;
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result BlockCacheBufferedStorage::UpdateLastResult(Result result) {
|
||||
/* Update the last result. */
|
||||
if (R_FAILED(result) && !fs::ResultBufferAllocationFailed::Includes(result) && R_SUCCEEDED(this->last_result)) {
|
||||
this->last_result = result;
|
||||
if (R_FAILED(result) && !fs::ResultBufferAllocationFailed::Includes(result) && R_SUCCEEDED(m_last_result)) {
|
||||
m_last_result = result;
|
||||
}
|
||||
|
||||
/* Try to succeed with the result. */
|
||||
@@ -1054,7 +1054,7 @@ namespace ams::fssystem::save {
|
||||
|
||||
while (*aligned_offset < aligned_offset_end) {
|
||||
/* Get the associated buffer for the offset. */
|
||||
R_TRY(this->UpdateLastResult(this->GetAssociateBuffer(std::addressof(memory_range), std::addressof(entry), *aligned_offset, this->verification_block_size, true)));
|
||||
R_TRY(this->UpdateLastResult(this->GetAssociateBuffer(std::addressof(memory_range), std::addressof(entry), *aligned_offset, m_verification_block_size, true)));
|
||||
|
||||
/* If the entry isn't cached, we're done. */
|
||||
if (!entry.is_cached) {
|
||||
@@ -1106,7 +1106,7 @@ namespace ams::fssystem::save {
|
||||
|
||||
while (aligned_offset < *aligned_offset_end) {
|
||||
/* Get the associated buffer for the offset. */
|
||||
R_TRY(this->UpdateLastResult(this->GetAssociateBuffer(std::addressof(memory_range), std::addressof(entry), *aligned_offset_end - this->verification_block_size, this->verification_block_size, true)));
|
||||
R_TRY(this->UpdateLastResult(this->GetAssociateBuffer(std::addressof(memory_range), std::addressof(entry), *aligned_offset_end - m_verification_block_size, m_verification_block_size, true)));
|
||||
|
||||
/* If the entry isn't cached, we're done. */
|
||||
if (!entry.is_cached) {
|
||||
@@ -1149,8 +1149,8 @@ namespace ams::fssystem::save {
|
||||
/* Determine bulk read offsets. */
|
||||
const s64 read_offset = offset;
|
||||
const size_t read_size = size;
|
||||
const s64 aligned_offset = util::AlignDown(read_offset, this->verification_block_size);
|
||||
const s64 aligned_offset_end = util::AlignUp(read_offset + read_size, this->verification_block_size);
|
||||
const s64 aligned_offset = util::AlignDown(read_offset, m_verification_block_size);
|
||||
const s64 aligned_offset_end = util::AlignUp(read_offset + read_size, m_verification_block_size);
|
||||
char *dst = static_cast<char *>(buffer);
|
||||
|
||||
/* Prepare to do our reads. */
|
||||
@@ -1177,7 +1177,7 @@ namespace ams::fssystem::save {
|
||||
}
|
||||
|
||||
/* Read the data. */
|
||||
R_TRY(this->data_storage->Read(aligned_offset, read_buffer, buffer_size));
|
||||
R_TRY(m_data_storage->Read(aligned_offset, read_buffer, buffer_size));
|
||||
|
||||
/* Copy the data out. */
|
||||
if (dst != read_buffer) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -56,7 +56,7 @@ namespace ams::fssystem::save {
|
||||
}
|
||||
|
||||
/* Instantiate the global random generation function. */
|
||||
HierarchicalIntegrityVerificationStorage::GenerateRandomFunction HierarchicalIntegrityVerificationStorage::s_generate_random = nullptr;
|
||||
constinit HierarchicalIntegrityVerificationStorage::GenerateRandomFunction HierarchicalIntegrityVerificationStorage::s_generate_random = nullptr;
|
||||
|
||||
Result HierarchicalIntegrityVerificationStorageControlArea::QuerySize(HierarchicalIntegrityVerificationSizeSet *out, const InputParam &input_param, s32 layer_count, s64 data_size) {
|
||||
/* Validate preconditions. */
|
||||
@@ -130,24 +130,24 @@ namespace ams::fssystem::save {
|
||||
{
|
||||
s64 meta_size = 0;
|
||||
R_TRY(meta_storage.GetSize(std::addressof(meta_size)));
|
||||
R_UNLESS(meta_size >= static_cast<s64>(sizeof(this->meta)), fs::ResultInvalidSize());
|
||||
R_UNLESS(meta_size >= static_cast<s64>(sizeof(m_meta)), fs::ResultInvalidSize());
|
||||
}
|
||||
|
||||
/* Set the storage and read the meta. */
|
||||
this->storage = meta_storage;
|
||||
R_TRY(this->storage.Read(0, std::addressof(this->meta), sizeof(this->meta)));
|
||||
m_storage = meta_storage;
|
||||
R_TRY(m_storage.Read(0, std::addressof(m_meta), sizeof(m_meta)));
|
||||
|
||||
/* Validate the meta magic. */
|
||||
R_UNLESS(this->meta.magic == IntegrityVerificationStorageMagic, fs::ResultIncorrectIntegrityVerificationMagic());
|
||||
R_UNLESS(m_meta.magic == IntegrityVerificationStorageMagic, fs::ResultIncorrectIntegrityVerificationMagic());
|
||||
|
||||
/* Validate the meta version. */
|
||||
R_UNLESS((this->meta.version & IntegrityVerificationStorageVersionMask) == (IntegrityVerificationStorageVersion & IntegrityVerificationStorageVersionMask), fs::ResultUnsupportedVersion());
|
||||
R_UNLESS((m_meta.version & IntegrityVerificationStorageVersionMask) == (IntegrityVerificationStorageVersion & IntegrityVerificationStorageVersionMask), fs::ResultUnsupportedVersion());
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void HierarchicalIntegrityVerificationStorageControlArea::Finalize() {
|
||||
this->storage = fs::SubStorage();
|
||||
m_storage = fs::SubStorage();
|
||||
}
|
||||
|
||||
Result HierarchicalIntegrityVerificationStorage::Initialize(const HierarchicalIntegrityVerificationInformation &info, HierarchicalStorageInformation storage, FileSystemBufferManagerSet *bufs, os::SdkRecursiveMutex *mtx, fs::StorageType storage_type) {
|
||||
@@ -156,9 +156,9 @@ namespace ams::fssystem::save {
|
||||
AMS_ASSERT(IntegrityMinLayerCount <= info.max_layers && info.max_layers <= IntegrityMaxLayerCount);
|
||||
|
||||
/* Set member variables. */
|
||||
this->max_layers = info.max_layers;
|
||||
this->buffers = bufs;
|
||||
this->mutex = mtx;
|
||||
m_max_layers = info.max_layers;
|
||||
m_buffers = bufs;
|
||||
m_mutex = mtx;
|
||||
|
||||
/* Determine our cache counts. */
|
||||
const auto max_data_cache_entry_count = (storage_type == fs::StorageType_SaveData) ? MaxSaveDataFsDataCacheEntryCount : MaxRomFsDataCacheEntryCount;
|
||||
@@ -168,64 +168,64 @@ namespace ams::fssystem::save {
|
||||
{
|
||||
fs::HashSalt mac;
|
||||
crypto::GenerateHmacSha256Mac(mac.value, sizeof(mac), info.seed.value, sizeof(info.seed), KeyArray[0].key, KeyArray[0].size);
|
||||
this->verify_storages[0].Initialize(storage[HierarchicalStorageInformation::MasterStorage], storage[HierarchicalStorageInformation::Layer1Storage], static_cast<s64>(1) << info.info[0].block_order, HashSize, this->buffers->buffers[this->max_layers - 2], mac, false, storage_type);
|
||||
m_verify_storages[0].Initialize(storage[HierarchicalStorageInformation::MasterStorage], storage[HierarchicalStorageInformation::Layer1Storage], static_cast<s64>(1) << info.info[0].block_order, HashSize, m_buffers->buffers[m_max_layers - 2], mac, false, storage_type);
|
||||
}
|
||||
|
||||
/* Ensure we don't leak state if further initialization goes wrong. */
|
||||
auto top_verif_guard = SCOPE_GUARD {
|
||||
this->verify_storages[0].Finalize();
|
||||
m_verify_storages[0].Finalize();
|
||||
|
||||
this->data_size = -1;
|
||||
this->buffers = nullptr;
|
||||
this->mutex = nullptr;
|
||||
m_data_size = -1;
|
||||
m_buffers = nullptr;
|
||||
m_mutex = nullptr;
|
||||
};
|
||||
|
||||
/* Initialize the top level buffer storage. */
|
||||
R_TRY(this->buffer_storages[0].Initialize(this->buffers->buffers[0], this->mutex, std::addressof(this->verify_storages[0]), info.info[0].size, static_cast<s64>(1) << info.info[0].block_order, max_hash_cache_entry_count, false, 0x10, false, storage_type));
|
||||
auto top_buffer_guard = SCOPE_GUARD { this->buffer_storages[0].Finalize(); };
|
||||
R_TRY(m_buffer_storages[0].Initialize(m_buffers->buffers[0], m_mutex, std::addressof(m_verify_storages[0]), info.info[0].size, static_cast<s64>(1) << info.info[0].block_order, max_hash_cache_entry_count, false, 0x10, false, storage_type));
|
||||
auto top_buffer_guard = SCOPE_GUARD { m_buffer_storages[0].Finalize(); };
|
||||
|
||||
/* Prepare to initialize the level storages. */
|
||||
s32 level = 0;
|
||||
|
||||
/* Ensure we don't leak state if further initialization goes wrong. */
|
||||
auto level_guard = SCOPE_GUARD {
|
||||
this->verify_storages[level + 1].Finalize();
|
||||
m_verify_storages[level + 1].Finalize();
|
||||
for (/* ... */; level > 0; --level) {
|
||||
this->buffer_storages[level].Finalize();
|
||||
this->verify_storages[level].Finalize();
|
||||
m_buffer_storages[level].Finalize();
|
||||
m_verify_storages[level].Finalize();
|
||||
}
|
||||
};
|
||||
|
||||
/* Initialize the level storages. */
|
||||
for (/* ... */; level < this->max_layers - 3; ++level) {
|
||||
for (/* ... */; level < m_max_layers - 3; ++level) {
|
||||
/* Initialize the verification storage. */
|
||||
{
|
||||
fs::SubStorage buffer_storage(std::addressof(this->buffer_storages[level]), 0, info.info[level].size);
|
||||
fs::SubStorage buffer_storage(std::addressof(m_buffer_storages[level]), 0, info.info[level].size);
|
||||
fs::HashSalt mac;
|
||||
crypto::GenerateHmacSha256Mac(mac.value, sizeof(mac), info.seed.value, sizeof(info.seed), KeyArray[level + 1].key, KeyArray[level + 1].size);
|
||||
this->verify_storages[level + 1].Initialize(buffer_storage, storage[level + 2], static_cast<s64>(1) << info.info[level + 1].block_order, static_cast<s64>(1) << info.info[level].block_order, this->buffers->buffers[this->max_layers - 2], mac, false, storage_type);
|
||||
m_verify_storages[level + 1].Initialize(buffer_storage, storage[level + 2], static_cast<s64>(1) << info.info[level + 1].block_order, static_cast<s64>(1) << info.info[level].block_order, m_buffers->buffers[m_max_layers - 2], mac, false, storage_type);
|
||||
}
|
||||
|
||||
/* Initialize the buffer storage. */
|
||||
R_TRY(this->buffer_storages[level + 1].Initialize(this->buffers->buffers[level + 1], this->mutex, std::addressof(this->verify_storages[level + 1]), info.info[level + 1].size, static_cast<s64>(1) << info.info[level + 1].block_order, max_hash_cache_entry_count, false, 0x11 + static_cast<s8>(level), false, storage_type));
|
||||
R_TRY(m_buffer_storages[level + 1].Initialize(m_buffers->buffers[level + 1], m_mutex, std::addressof(m_verify_storages[level + 1]), info.info[level + 1].size, static_cast<s64>(1) << info.info[level + 1].block_order, max_hash_cache_entry_count, false, 0x11 + static_cast<s8>(level), false, storage_type));
|
||||
}
|
||||
|
||||
/* Initialize the final level storage. */
|
||||
{
|
||||
/* Initialize the verification storage. */
|
||||
{
|
||||
fs::SubStorage buffer_storage(std::addressof(this->buffer_storages[level]), 0, info.info[level].size);
|
||||
fs::SubStorage buffer_storage(std::addressof(m_buffer_storages[level]), 0, info.info[level].size);
|
||||
fs::HashSalt mac;
|
||||
crypto::GenerateHmacSha256Mac(mac.value, sizeof(mac), info.seed.value, sizeof(info.seed), KeyArray[level + 1].key, KeyArray[level + 1].size);
|
||||
this->verify_storages[level + 1].Initialize(buffer_storage, storage[level + 2], static_cast<s64>(1) << info.info[level + 1].block_order, static_cast<s64>(1) << info.info[level].block_order, this->buffers->buffers[this->max_layers - 2], mac, true, storage_type);
|
||||
m_verify_storages[level + 1].Initialize(buffer_storage, storage[level + 2], static_cast<s64>(1) << info.info[level + 1].block_order, static_cast<s64>(1) << info.info[level].block_order, m_buffers->buffers[m_max_layers - 2], mac, true, storage_type);
|
||||
}
|
||||
|
||||
/* Initialize the buffer storage. */
|
||||
R_TRY(this->buffer_storages[level + 1].Initialize(this->buffers->buffers[level + 1], this->mutex, std::addressof(this->verify_storages[level + 1]), info.info[level + 1].size, static_cast<s64>(1) << info.info[level + 1].block_order, max_data_cache_entry_count, true, 0x11 + static_cast<s8>(level), true, storage_type));
|
||||
R_TRY(m_buffer_storages[level + 1].Initialize(m_buffers->buffers[level + 1], m_mutex, std::addressof(m_verify_storages[level + 1]), info.info[level + 1].size, static_cast<s64>(1) << info.info[level + 1].block_order, max_data_cache_entry_count, true, 0x11 + static_cast<s8>(level), true, storage_type));
|
||||
}
|
||||
|
||||
/* Set the data size. */
|
||||
this->data_size = info.info[level + 1].size;
|
||||
m_data_size = info.info[level + 1].size;
|
||||
|
||||
/* We succeeded. */
|
||||
level_guard.Cancel();
|
||||
@@ -235,24 +235,24 @@ namespace ams::fssystem::save {
|
||||
}
|
||||
|
||||
void HierarchicalIntegrityVerificationStorage::Finalize() {
|
||||
if (this->data_size >= 0) {
|
||||
this->data_size = 0;
|
||||
if (m_data_size >= 0) {
|
||||
m_data_size = 0;
|
||||
|
||||
this->buffers = nullptr;
|
||||
this->mutex = nullptr;
|
||||
m_buffers = nullptr;
|
||||
m_mutex = nullptr;
|
||||
|
||||
for (s32 level = this->max_layers - 2; level >= 0; --level) {
|
||||
this->buffer_storages[level].Finalize();
|
||||
this->verify_storages[level].Finalize();
|
||||
for (s32 level = m_max_layers - 2; level >= 0; --level) {
|
||||
m_buffer_storages[level].Finalize();
|
||||
m_verify_storages[level].Finalize();
|
||||
}
|
||||
|
||||
this->data_size = -1;
|
||||
m_data_size = -1;
|
||||
}
|
||||
}
|
||||
|
||||
Result HierarchicalIntegrityVerificationStorage::Read(s64 offset, void *buffer, size_t size) {
|
||||
/* Validate preconditions. */
|
||||
AMS_ASSERT(this->data_size >= 0);
|
||||
AMS_ASSERT(m_data_size >= 0);
|
||||
|
||||
/* Succeed if zero-size. */
|
||||
R_SUCCEED_IF(size == 0);
|
||||
@@ -262,8 +262,8 @@ namespace ams::fssystem::save {
|
||||
|
||||
/* Acquire access to the read semaphore. */
|
||||
if (!g_read_semaphore.TimedAcquire(AccessTimeout)) {
|
||||
for (auto level = this->max_layers - 2; level >= 0; --level) {
|
||||
R_TRY(this->buffer_storages[level].Flush());
|
||||
for (auto level = m_max_layers - 2; level >= 0; --level) {
|
||||
R_TRY(m_buffer_storages[level].Flush());
|
||||
}
|
||||
g_read_semaphore.Acquire();
|
||||
}
|
||||
@@ -272,13 +272,13 @@ namespace ams::fssystem::save {
|
||||
ON_SCOPE_EXIT { g_read_semaphore.Release(); };
|
||||
|
||||
/* Read the data. */
|
||||
R_TRY(this->buffer_storages[this->max_layers - 2].Read(offset, buffer, size));
|
||||
R_TRY(m_buffer_storages[m_max_layers - 2].Read(offset, buffer, size));
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result HierarchicalIntegrityVerificationStorage::Write(s64 offset, const void *buffer, size_t size) {
|
||||
/* Validate preconditions. */
|
||||
AMS_ASSERT(this->data_size >= 0);
|
||||
AMS_ASSERT(m_data_size >= 0);
|
||||
|
||||
/* Succeed if zero-size. */
|
||||
R_SUCCEED_IF(size == 0);
|
||||
@@ -288,8 +288,8 @@ namespace ams::fssystem::save {
|
||||
|
||||
/* Acquire access to the write semaphore. */
|
||||
if (!g_write_semaphore.TimedAcquire(AccessTimeout)) {
|
||||
for (auto level = this->max_layers - 2; level >= 0; --level) {
|
||||
R_TRY(this->buffer_storages[level].Flush());
|
||||
for (auto level = m_max_layers - 2; level >= 0; --level) {
|
||||
R_TRY(m_buffer_storages[level].Flush());
|
||||
}
|
||||
g_write_semaphore.Acquire();
|
||||
}
|
||||
@@ -298,15 +298,15 @@ namespace ams::fssystem::save {
|
||||
ON_SCOPE_EXIT { g_write_semaphore.Release(); };
|
||||
|
||||
/* Write the data. */
|
||||
R_TRY(this->buffer_storages[this->max_layers - 2].Write(offset, buffer, size));
|
||||
this->is_written_for_rollback = true;
|
||||
R_TRY(m_buffer_storages[m_max_layers - 2].Write(offset, buffer, size));
|
||||
m_is_written_for_rollback = true;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result HierarchicalIntegrityVerificationStorage::GetSize(s64 *out) {
|
||||
AMS_ASSERT(out != nullptr);
|
||||
AMS_ASSERT(this->data_size >= 0);
|
||||
*out = this->data_size;
|
||||
AMS_ASSERT(m_data_size >= 0);
|
||||
*out = m_data_size;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
@@ -319,14 +319,14 @@ namespace ams::fssystem::save {
|
||||
case fs::OperationId::FillZero:
|
||||
case fs::OperationId::DestroySignature:
|
||||
{
|
||||
R_TRY(this->buffer_storages[this->max_layers - 2].OperateRange(dst, dst_size, op_id, offset, size, src, src_size));
|
||||
this->is_written_for_rollback = true;
|
||||
R_TRY(m_buffer_storages[m_max_layers - 2].OperateRange(dst, dst_size, op_id, offset, size, src, src_size));
|
||||
m_is_written_for_rollback = true;
|
||||
return ResultSuccess();
|
||||
}
|
||||
case fs::OperationId::Invalidate:
|
||||
case fs::OperationId::QueryRange:
|
||||
{
|
||||
R_TRY(this->buffer_storages[this->max_layers - 2].OperateRange(dst, dst_size, op_id, offset, size, src, src_size));
|
||||
R_TRY(m_buffer_storages[m_max_layers - 2].OperateRange(dst, dst_size, op_id, offset, size, src, src_size));
|
||||
return ResultSuccess();
|
||||
}
|
||||
default:
|
||||
@@ -335,17 +335,17 @@ namespace ams::fssystem::save {
|
||||
}
|
||||
|
||||
Result HierarchicalIntegrityVerificationStorage::Commit() {
|
||||
for (s32 level = this->max_layers - 2; level >= 0; --level) {
|
||||
R_TRY(this->buffer_storages[level].Commit());
|
||||
for (s32 level = m_max_layers - 2; level >= 0; --level) {
|
||||
R_TRY(m_buffer_storages[level].Commit());
|
||||
}
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result HierarchicalIntegrityVerificationStorage::OnRollback() {
|
||||
for (s32 level = this->max_layers - 2; level >= 0; --level) {
|
||||
R_TRY(this->buffer_storages[level].OnRollback());
|
||||
for (s32 level = m_max_layers - 2; level >= 0; --level) {
|
||||
R_TRY(m_buffer_storages[level].OnRollback());
|
||||
}
|
||||
this->is_written_for_rollback = false;
|
||||
m_is_written_for_rollback = false;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
|
||||
@@ -23,47 +23,47 @@ namespace ams::fssystem::save {
|
||||
AMS_ASSERT(bm != nullptr);
|
||||
|
||||
/* Set storages. */
|
||||
this->hash_storage = hs;
|
||||
this->data_storage = ds;
|
||||
m_hash_storage = hs;
|
||||
m_data_storage = ds;
|
||||
|
||||
/* Set verification block sizes. */
|
||||
this->verification_block_size = verif_block_size;
|
||||
this->verification_block_order = ILog2(static_cast<u32>(verif_block_size));
|
||||
AMS_ASSERT(this->verification_block_size == (1l << this->verification_block_order));
|
||||
m_verification_block_size = verif_block_size;
|
||||
m_verification_block_order = ILog2(static_cast<u32>(verif_block_size));
|
||||
AMS_ASSERT(m_verification_block_size == (1l << m_verification_block_order));
|
||||
|
||||
/* Set buffer manager. */
|
||||
this->buffer_manager = bm;
|
||||
m_buffer_manager = bm;
|
||||
|
||||
/* Set upper layer block sizes. */
|
||||
upper_layer_verif_block_size = std::max(upper_layer_verif_block_size, HashSize);
|
||||
this->upper_layer_verification_block_size = upper_layer_verif_block_size;
|
||||
this->upper_layer_verification_block_order = ILog2(static_cast<u32>(upper_layer_verif_block_size));
|
||||
AMS_ASSERT(this->upper_layer_verification_block_size == (1l << this->upper_layer_verification_block_order));
|
||||
m_upper_layer_verification_block_size = upper_layer_verif_block_size;
|
||||
m_upper_layer_verification_block_order = ILog2(static_cast<u32>(upper_layer_verif_block_size));
|
||||
AMS_ASSERT(m_upper_layer_verification_block_size == (1l << m_upper_layer_verification_block_order));
|
||||
|
||||
/* Validate sizes. */
|
||||
{
|
||||
s64 hash_size = 0;
|
||||
s64 data_size = 0;
|
||||
R_ASSERT(hash_storage.GetSize(std::addressof(hash_size)));
|
||||
R_ASSERT(data_storage.GetSize(std::addressof(hash_size)));
|
||||
AMS_ASSERT(((hash_size / HashSize) * this->verification_block_size) >= data_size);
|
||||
AMS_ASSERT(R_SUCCEEDED(m_hash_storage.GetSize(std::addressof(hash_size))));
|
||||
AMS_ASSERT(R_SUCCEEDED(m_data_storage.GetSize(std::addressof(hash_size))));
|
||||
AMS_ASSERT(((hash_size / HashSize) * m_verification_block_size) >= data_size);
|
||||
AMS_UNUSED(hash_size, data_size);
|
||||
}
|
||||
|
||||
/* Set salt. */
|
||||
std::memcpy(this->salt.value, salt.value, fs::HashSalt::Size);
|
||||
std::memcpy(m_salt.value, salt.value, fs::HashSalt::Size);
|
||||
|
||||
/* Set data and storage type. */
|
||||
this->is_real_data = is_real_data;
|
||||
this->storage_type = storage_type;
|
||||
m_is_real_data = is_real_data;
|
||||
m_storage_type = storage_type;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void IntegrityVerificationStorage::Finalize() {
|
||||
if (this->buffer_manager != nullptr) {
|
||||
this->hash_storage = fs::SubStorage();
|
||||
this->data_storage = fs::SubStorage();
|
||||
this->buffer_manager = nullptr;
|
||||
if (m_buffer_manager != nullptr) {
|
||||
m_hash_storage = fs::SubStorage();
|
||||
m_data_storage = fs::SubStorage();
|
||||
m_buffer_manager = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,8 +72,8 @@ namespace ams::fssystem::save {
|
||||
AMS_ASSERT(size != 0);
|
||||
|
||||
/* Validate other preconditions. */
|
||||
AMS_ASSERT(util::IsAligned(offset, static_cast<size_t>(this->verification_block_size)));
|
||||
AMS_ASSERT(util::IsAligned(size, static_cast<size_t>(this->verification_block_size)));
|
||||
AMS_ASSERT(util::IsAligned(offset, static_cast<size_t>(m_verification_block_size)));
|
||||
AMS_ASSERT(util::IsAligned(size, static_cast<size_t>(m_verification_block_size)));
|
||||
|
||||
/* Succeed if zero size. */
|
||||
R_SUCCEED_IF(size == 0);
|
||||
@@ -83,19 +83,19 @@ namespace ams::fssystem::save {
|
||||
|
||||
/* Validate the offset. */
|
||||
s64 data_size;
|
||||
R_TRY(this->data_storage.GetSize(std::addressof(data_size)));
|
||||
R_TRY(m_data_storage.GetSize(std::addressof(data_size)));
|
||||
R_UNLESS(offset <= data_size, fs::ResultInvalidOffset());
|
||||
|
||||
/* Validate the access range. */
|
||||
R_UNLESS(IStorage::CheckAccessRange(offset, size, util::AlignUp(data_size, static_cast<size_t>(this->verification_block_size))), fs::ResultOutOfRange());
|
||||
R_UNLESS(IStorage::CheckAccessRange(offset, size, util::AlignUp(data_size, static_cast<size_t>(m_verification_block_size))), fs::ResultOutOfRange());
|
||||
|
||||
/* Determine the read extents. */
|
||||
size_t read_size = size;
|
||||
if (static_cast<s64>(offset + read_size) > data_size) {
|
||||
/* Determine the padding sizes. */
|
||||
s64 padding_offset = data_size - offset;
|
||||
size_t padding_size = static_cast<size_t>(this->verification_block_size - (padding_offset & (this->verification_block_size - 1)));
|
||||
AMS_ASSERT(static_cast<s64>(padding_size) < this->verification_block_size);
|
||||
size_t padding_size = static_cast<size_t>(m_verification_block_size - (padding_offset & (m_verification_block_size - 1)));
|
||||
AMS_ASSERT(static_cast<s64>(padding_size) < m_verification_block_size);
|
||||
|
||||
/* Clear the padding. */
|
||||
std::memset(static_cast<u8 *>(buffer) + padding_offset, 0, padding_size);
|
||||
@@ -107,12 +107,12 @@ namespace ams::fssystem::save {
|
||||
/* Perform the read. */
|
||||
{
|
||||
auto clear_guard = SCOPE_GUARD { std::memset(buffer, 0, size); };
|
||||
R_TRY(this->data_storage.Read(offset, buffer, read_size));
|
||||
R_TRY(m_data_storage.Read(offset, buffer, read_size));
|
||||
clear_guard.Cancel();
|
||||
}
|
||||
|
||||
/* Prepare to validate the signatures. */
|
||||
const auto signature_count = size >> this->verification_block_order;
|
||||
const auto signature_count = size >> m_verification_block_order;
|
||||
PooledBuffer signature_buffer(signature_count * sizeof(BlockHash), sizeof(BlockHash));
|
||||
const auto buffer_count = std::min(signature_count, signature_buffer.GetSize() / sizeof(BlockHash));
|
||||
|
||||
@@ -123,23 +123,23 @@ namespace ams::fssystem::save {
|
||||
while (verified_count < signature_count) {
|
||||
/* Read the current signatures. */
|
||||
const auto cur_count = std::min(buffer_count, signature_count - verified_count);
|
||||
auto cur_result = this->ReadBlockSignature(signature_buffer.GetBuffer(), signature_buffer.GetSize(), offset + (verified_count << this->verification_block_order), cur_count << this->verification_block_order);
|
||||
auto cur_result = this->ReadBlockSignature(signature_buffer.GetBuffer(), signature_buffer.GetSize(), offset + (verified_count << m_verification_block_order), cur_count << m_verification_block_order);
|
||||
|
||||
/* Temporarily increase our priority. */
|
||||
ScopedThreadPriorityChanger cp(+1, ScopedThreadPriorityChanger::Mode::Relative);
|
||||
|
||||
/* Loop over each signature we read. */
|
||||
for (size_t i = 0; i < cur_count && R_SUCCEEDED(cur_result); ++i) {
|
||||
const auto verified_size = (verified_count + i) << this->verification_block_order;
|
||||
const auto verified_size = (verified_count + i) << m_verification_block_order;
|
||||
u8 *cur_buf = static_cast<u8 *>(buffer) + verified_size;
|
||||
cur_result = this->VerifyHash(cur_buf, reinterpret_cast<BlockHash *>(signature_buffer.GetBuffer()) + i);
|
||||
|
||||
/* If the data is corrupted, clear the corrupted parts. */
|
||||
if (fs::ResultIntegrityVerificationStorageCorrupted::Includes(cur_result)) {
|
||||
std::memset(cur_buf, 0, this->verification_block_size);
|
||||
std::memset(cur_buf, 0, m_verification_block_size);
|
||||
|
||||
/* Set the result if we should. */
|
||||
if (!fs::ResultClearedRealDataVerificationFailed::Includes(cur_result) && this->storage_type != fs::StorageType_Authoring) {
|
||||
if (!fs::ResultClearedRealDataVerificationFailed::Includes(cur_result) && m_storage_type != fs::StorageType_Authoring) {
|
||||
verify_hash_result = cur_result;
|
||||
}
|
||||
|
||||
@@ -170,17 +170,17 @@ namespace ams::fssystem::save {
|
||||
|
||||
/* Validate the offset. */
|
||||
s64 data_size;
|
||||
R_TRY(this->data_storage.GetSize(std::addressof(data_size)));
|
||||
R_TRY(m_data_storage.GetSize(std::addressof(data_size)));
|
||||
R_UNLESS(offset < data_size, fs::ResultInvalidOffset());
|
||||
|
||||
/* Validate the access range. */
|
||||
R_UNLESS(IStorage::CheckAccessRange(offset, size, util::AlignUp(data_size, static_cast<size_t>(this->verification_block_size))), fs::ResultOutOfRange());
|
||||
R_UNLESS(IStorage::CheckAccessRange(offset, size, util::AlignUp(data_size, static_cast<size_t>(m_verification_block_size))), fs::ResultOutOfRange());
|
||||
|
||||
/* Validate preconditions. */
|
||||
AMS_ASSERT(util::IsAligned(offset, this->verification_block_size));
|
||||
AMS_ASSERT(util::IsAligned(size, this->verification_block_size));
|
||||
AMS_ASSERT(util::IsAligned(offset, m_verification_block_size));
|
||||
AMS_ASSERT(util::IsAligned(size, m_verification_block_size));
|
||||
AMS_ASSERT(offset <= data_size);
|
||||
AMS_ASSERT(static_cast<s64>(offset + size) < data_size + this->verification_block_size);
|
||||
AMS_ASSERT(static_cast<s64>(offset + size) < data_size + m_verification_block_size);
|
||||
|
||||
/* Validate that if writing past the end, all extra data is zero padding. */
|
||||
if (static_cast<s64>(offset + size) > data_size) {
|
||||
@@ -201,13 +201,13 @@ namespace ams::fssystem::save {
|
||||
}
|
||||
|
||||
/* Determine the size we're writing in blocks. */
|
||||
const auto aligned_write_size = util::AlignUp(write_size, this->verification_block_size);
|
||||
const auto aligned_write_size = util::AlignUp(write_size, m_verification_block_size);
|
||||
|
||||
/* Write the updated block signatures. */
|
||||
Result update_result = ResultSuccess();
|
||||
size_t updated_count = 0;
|
||||
{
|
||||
const auto signature_count = aligned_write_size >> this->verification_block_order;
|
||||
const auto signature_count = aligned_write_size >> m_verification_block_order;
|
||||
PooledBuffer signature_buffer(signature_count * sizeof(BlockHash), sizeof(BlockHash));
|
||||
const auto buffer_count = std::min(signature_count, signature_buffer.GetSize() / sizeof(BlockHash));
|
||||
|
||||
@@ -219,13 +219,13 @@ namespace ams::fssystem::save {
|
||||
ScopedThreadPriorityChanger cp(+1, ScopedThreadPriorityChanger::Mode::Relative);
|
||||
|
||||
for (size_t i = 0; i < cur_count; ++i) {
|
||||
const auto updated_size = (updated_count + i) << this->verification_block_order;
|
||||
const auto updated_size = (updated_count + i) << m_verification_block_order;
|
||||
this->CalcBlockHash(reinterpret_cast<BlockHash *>(signature_buffer.GetBuffer()) + i, reinterpret_cast<const u8 *>(buffer) + updated_size);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the new block signatures. */
|
||||
if (R_FAILED((update_result = this->WriteBlockSignature(signature_buffer.GetBuffer(), signature_buffer.GetSize(), offset + (updated_count << this->verification_block_order), cur_count << this->verification_block_order)))) {
|
||||
if (R_FAILED((update_result = this->WriteBlockSignature(signature_buffer.GetBuffer(), signature_buffer.GetSize(), offset + (updated_count << m_verification_block_order), cur_count << m_verification_block_order)))) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -235,44 +235,44 @@ namespace ams::fssystem::save {
|
||||
}
|
||||
|
||||
/* Write the data. */
|
||||
R_TRY(this->data_storage.Write(offset, buffer, std::min(write_size, updated_count << this->verification_block_order)));
|
||||
R_TRY(m_data_storage.Write(offset, buffer, std::min(write_size, updated_count << m_verification_block_order)));
|
||||
|
||||
return update_result;
|
||||
}
|
||||
|
||||
Result IntegrityVerificationStorage::GetSize(s64 *out) {
|
||||
return this->data_storage.GetSize(out);
|
||||
return m_data_storage.GetSize(out);
|
||||
}
|
||||
|
||||
Result IntegrityVerificationStorage::Flush() {
|
||||
/* Flush both storages. */
|
||||
R_TRY(this->hash_storage.Flush());
|
||||
R_TRY(this->data_storage.Flush());
|
||||
R_TRY(m_hash_storage.Flush());
|
||||
R_TRY(m_data_storage.Flush());
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result IntegrityVerificationStorage::OperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) {
|
||||
/* Validate preconditions. */
|
||||
AMS_ASSERT(util::IsAligned(offset, static_cast<size_t>(this->verification_block_size)));
|
||||
AMS_ASSERT(util::IsAligned(size, static_cast<size_t>(this->verification_block_size)));
|
||||
AMS_ASSERT(util::IsAligned(offset, static_cast<size_t>(m_verification_block_size)));
|
||||
AMS_ASSERT(util::IsAligned(size, static_cast<size_t>(m_verification_block_size)));
|
||||
|
||||
switch (op_id) {
|
||||
case fs::OperationId::FillZero:
|
||||
{
|
||||
/* Clear should only be called for save data. */
|
||||
AMS_ASSERT(this->storage_type == fs::StorageType_SaveData);
|
||||
AMS_ASSERT(m_storage_type == fs::StorageType_SaveData);
|
||||
|
||||
/* Validate the range. */
|
||||
s64 data_size = 0;
|
||||
R_TRY(this->data_storage.GetSize(std::addressof(data_size)));
|
||||
R_TRY(m_data_storage.GetSize(std::addressof(data_size)));
|
||||
R_UNLESS(0 <= offset && offset <= data_size, fs::ResultInvalidOffset());
|
||||
|
||||
/* Determine the extents to clear. */
|
||||
const auto sign_offset = (offset >> this->verification_block_order) * HashSize;
|
||||
const auto sign_size = (std::min(size, data_size - offset) >> this->verification_block_order) * HashSize;
|
||||
const auto sign_offset = (offset >> m_verification_block_order) * HashSize;
|
||||
const auto sign_size = (std::min(size, data_size - offset) >> m_verification_block_order) * HashSize;
|
||||
|
||||
/* Allocate a work buffer. */
|
||||
const auto buf_size = static_cast<size_t>(std::min(sign_size, static_cast<s64>(1) << (this->upper_layer_verification_block_order + 2)));
|
||||
const auto buf_size = static_cast<size_t>(std::min(sign_size, static_cast<s64>(1) << (m_upper_layer_verification_block_order + 2)));
|
||||
std::unique_ptr<char[], fs::impl::Deleter> buf = fs::impl::MakeUnique<char[]>(buf_size);
|
||||
R_UNLESS(buf != nullptr, fs::ResultAllocationFailureInIntegrityVerificationStorageA());
|
||||
|
||||
@@ -284,7 +284,7 @@ namespace ams::fssystem::save {
|
||||
|
||||
while (remaining_size > 0) {
|
||||
const auto cur_size = static_cast<size_t>(std::min(remaining_size, static_cast<s64>(buf_size)));
|
||||
R_TRY(this->hash_storage.Write(sign_offset + sign_size - remaining_size, buf.get(), cur_size));
|
||||
R_TRY(m_hash_storage.Write(sign_offset + sign_size - remaining_size, buf.get(), cur_size));
|
||||
remaining_size -= cur_size;
|
||||
}
|
||||
|
||||
@@ -293,23 +293,23 @@ namespace ams::fssystem::save {
|
||||
case fs::OperationId::DestroySignature:
|
||||
{
|
||||
/* Clear Signature should only be called for save data. */
|
||||
AMS_ASSERT(this->storage_type == fs::StorageType_SaveData);
|
||||
AMS_ASSERT(m_storage_type == fs::StorageType_SaveData);
|
||||
|
||||
/* Validate the range. */
|
||||
s64 data_size = 0;
|
||||
R_TRY(this->data_storage.GetSize(std::addressof(data_size)));
|
||||
R_TRY(m_data_storage.GetSize(std::addressof(data_size)));
|
||||
R_UNLESS(0 <= offset && offset <= data_size, fs::ResultInvalidOffset());
|
||||
|
||||
/* Determine the extents to clear the signature for. */
|
||||
const auto sign_offset = (offset >> this->verification_block_order) * HashSize;
|
||||
const auto sign_size = (std::min(size, data_size - offset) >> this->verification_block_order) * HashSize;
|
||||
const auto sign_offset = (offset >> m_verification_block_order) * HashSize;
|
||||
const auto sign_size = (std::min(size, data_size - offset) >> m_verification_block_order) * HashSize;
|
||||
|
||||
/* Allocate a work buffer. */
|
||||
std::unique_ptr<char[], fs::impl::Deleter> buf = fs::impl::MakeUnique<char[]>(sign_size);
|
||||
R_UNLESS(buf != nullptr, fs::ResultAllocationFailureInIntegrityVerificationStorageB());
|
||||
|
||||
/* Read the existing signature. */
|
||||
R_TRY(this->hash_storage.Read(sign_offset, buf.get(), sign_size));
|
||||
R_TRY(m_hash_storage.Read(sign_offset, buf.get(), sign_size));
|
||||
|
||||
/* Clear the signature. */
|
||||
/* This sets all bytes to FF, with the verification bit cleared. */
|
||||
@@ -318,25 +318,25 @@ namespace ams::fssystem::save {
|
||||
}
|
||||
|
||||
/* Write the cleared signature. */
|
||||
return this->hash_storage.Write(sign_offset, buf.get(), sign_size);
|
||||
return m_hash_storage.Write(sign_offset, buf.get(), sign_size);
|
||||
}
|
||||
case fs::OperationId::Invalidate:
|
||||
{
|
||||
/* Only allow cache invalidation for RomFs. */
|
||||
R_UNLESS(this->storage_type != fs::StorageType_SaveData, fs::ResultUnsupportedOperationInIntegrityVerificationStorageB());
|
||||
R_UNLESS(m_storage_type != fs::StorageType_SaveData, fs::ResultUnsupportedOperationInIntegrityVerificationStorageB());
|
||||
|
||||
/* Validate the range. */
|
||||
s64 data_size = 0;
|
||||
R_TRY(this->data_storage.GetSize(std::addressof(data_size)));
|
||||
R_TRY(m_data_storage.GetSize(std::addressof(data_size)));
|
||||
R_UNLESS(0 <= offset && offset <= data_size, fs::ResultInvalidOffset());
|
||||
|
||||
/* Determine the extents to invalidate. */
|
||||
const auto sign_offset = (offset >> this->verification_block_order) * HashSize;
|
||||
const auto sign_size = (std::min(size, data_size - offset) >> this->verification_block_order) * HashSize;
|
||||
const auto sign_offset = (offset >> m_verification_block_order) * HashSize;
|
||||
const auto sign_size = (std::min(size, data_size - offset) >> m_verification_block_order) * HashSize;
|
||||
|
||||
/* Operate on our storages. */
|
||||
R_TRY(this->hash_storage.OperateRange(dst, dst_size, op_id, sign_offset, sign_size, src, src_size));
|
||||
R_TRY(this->data_storage.OperateRange(dst, dst_size, op_id, sign_offset, sign_size, src, src_size));
|
||||
R_TRY(m_hash_storage.OperateRange(dst, dst_size, op_id, sign_offset, sign_size, src, src_size));
|
||||
R_TRY(m_data_storage.OperateRange(dst, dst_size, op_id, sign_offset, sign_size, src, src_size));
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -344,14 +344,14 @@ namespace ams::fssystem::save {
|
||||
{
|
||||
/* Validate the range. */
|
||||
s64 data_size = 0;
|
||||
R_TRY(this->data_storage.GetSize(std::addressof(data_size)));
|
||||
R_TRY(m_data_storage.GetSize(std::addressof(data_size)));
|
||||
R_UNLESS(0 <= offset && offset <= data_size, fs::ResultInvalidOffset());
|
||||
|
||||
/* Determine the real size to query. */
|
||||
const auto actual_size = std::min(size, data_size - offset);
|
||||
|
||||
/* Query the data storage. */
|
||||
R_TRY(this->data_storage.OperateRange(dst, dst_size, op_id, offset, actual_size, src, src_size));
|
||||
R_TRY(m_data_storage.OperateRange(dst, dst_size, op_id, offset, actual_size, src, src_size));
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -366,8 +366,8 @@ namespace ams::fssystem::save {
|
||||
sha.Initialize();
|
||||
|
||||
/* If calculating for save data, hash the salt. */
|
||||
if (this->storage_type == fs::StorageType_SaveData) {
|
||||
sha.Update(this->salt.value, sizeof(this->salt));
|
||||
if (m_storage_type == fs::StorageType_SaveData) {
|
||||
sha.Update(m_salt.value, sizeof(m_salt));
|
||||
}
|
||||
|
||||
/* Update with the buffer and get the hash. */
|
||||
@@ -375,7 +375,7 @@ namespace ams::fssystem::save {
|
||||
sha.GetHash(out, sizeof(*out));
|
||||
|
||||
/* Set the validation bit, if the hash is for save data. */
|
||||
if (this->storage_type == fs::StorageType_SaveData) {
|
||||
if (m_storage_type == fs::StorageType_SaveData) {
|
||||
SetValidationBit(out);
|
||||
}
|
||||
}
|
||||
@@ -383,12 +383,12 @@ namespace ams::fssystem::save {
|
||||
Result IntegrityVerificationStorage::ReadBlockSignature(void *dst, size_t dst_size, s64 offset, size_t size) {
|
||||
/* Validate preconditions. */
|
||||
AMS_ASSERT(dst != nullptr);
|
||||
AMS_ASSERT(util::IsAligned(offset, static_cast<size_t>(this->verification_block_size)));
|
||||
AMS_ASSERT(util::IsAligned(size, static_cast<size_t>(this->verification_block_size)));
|
||||
AMS_ASSERT(util::IsAligned(offset, static_cast<size_t>(m_verification_block_size)));
|
||||
AMS_ASSERT(util::IsAligned(size, static_cast<size_t>(m_verification_block_size)));
|
||||
|
||||
/* Determine where to read the signature. */
|
||||
const s64 sign_offset = (offset >> this->verification_block_order) * HashSize;
|
||||
const auto sign_size = static_cast<size_t>((size >> this->verification_block_order) * HashSize);
|
||||
const s64 sign_offset = (offset >> m_verification_block_order) * HashSize;
|
||||
const auto sign_size = static_cast<size_t>((size >> m_verification_block_order) * HashSize);
|
||||
AMS_ASSERT(dst_size >= sign_size);
|
||||
AMS_UNUSED(dst_size);
|
||||
|
||||
@@ -397,13 +397,13 @@ namespace ams::fssystem::save {
|
||||
|
||||
/* Validate that we can read the signature. */
|
||||
s64 hash_size;
|
||||
R_TRY(this->hash_storage.GetSize(std::addressof(hash_size)));
|
||||
R_TRY(m_hash_storage.GetSize(std::addressof(hash_size)));
|
||||
const bool range_valid = static_cast<s64>(sign_offset + sign_size) <= hash_size;
|
||||
AMS_ASSERT(range_valid);
|
||||
R_UNLESS(range_valid, fs::ResultOutOfRange());
|
||||
|
||||
/* Read the signature. */
|
||||
R_TRY(this->hash_storage.Read(sign_offset, dst, sign_size));
|
||||
R_TRY(m_hash_storage.Read(sign_offset, dst, sign_size));
|
||||
|
||||
/* We succeeded. */
|
||||
clear_guard.Cancel();
|
||||
@@ -413,16 +413,16 @@ namespace ams::fssystem::save {
|
||||
Result IntegrityVerificationStorage::WriteBlockSignature(const void *src, size_t src_size, s64 offset, size_t size) {
|
||||
/* Validate preconditions. */
|
||||
AMS_ASSERT(src != nullptr);
|
||||
AMS_ASSERT(util::IsAligned(offset, static_cast<size_t>(this->verification_block_size)));
|
||||
AMS_ASSERT(util::IsAligned(offset, static_cast<size_t>(m_verification_block_size)));
|
||||
|
||||
/* Determine where to write the signature. */
|
||||
const s64 sign_offset = (offset >> this->verification_block_order) * HashSize;
|
||||
const auto sign_size = static_cast<size_t>((size >> this->verification_block_order) * HashSize);
|
||||
const s64 sign_offset = (offset >> m_verification_block_order) * HashSize;
|
||||
const auto sign_size = static_cast<size_t>((size >> m_verification_block_order) * HashSize);
|
||||
AMS_ASSERT(src_size >= sign_size);
|
||||
AMS_UNUSED(src_size);
|
||||
|
||||
/* Write the signature. */
|
||||
R_TRY(this->hash_storage.Write(sign_offset, src, sign_size));
|
||||
R_TRY(m_hash_storage.Write(sign_offset, src, sign_size));
|
||||
|
||||
/* We succeeded. */
|
||||
return ResultSuccess();
|
||||
@@ -437,7 +437,7 @@ namespace ams::fssystem::save {
|
||||
auto &cmp_hash = *hash;
|
||||
|
||||
/* If save data, check if the data is uninitialized. */
|
||||
if (this->storage_type == fs::StorageType_SaveData) {
|
||||
if (m_storage_type == fs::StorageType_SaveData) {
|
||||
bool is_cleared = false;
|
||||
R_TRY(this->IsCleared(std::addressof(is_cleared), cmp_hash));
|
||||
R_UNLESS(!is_cleared, fs::ResultClearedRealDataVerificationFailed());
|
||||
@@ -453,7 +453,7 @@ namespace ams::fssystem::save {
|
||||
std::memset(std::addressof(cmp_hash), 0, sizeof(cmp_hash));
|
||||
|
||||
/* Return the appropriate result. */
|
||||
if (this->is_real_data) {
|
||||
if (m_is_real_data) {
|
||||
return fs::ResultUnclearedRealDataVerificationFailed();
|
||||
} else {
|
||||
return fs::ResultNonRealDataVerificationFailed();
|
||||
@@ -466,7 +466,7 @@ namespace ams::fssystem::save {
|
||||
Result IntegrityVerificationStorage::IsCleared(bool *is_cleared, const BlockHash &hash) {
|
||||
/* Validate preconditions. */
|
||||
AMS_ASSERT(is_cleared != nullptr);
|
||||
AMS_ASSERT(this->storage_type == fs::StorageType_SaveData);
|
||||
AMS_ASSERT(m_storage_type == fs::StorageType_SaveData);
|
||||
|
||||
/* Default to uncleared. */
|
||||
*is_cleared = false;
|
||||
|
||||
@@ -21,30 +21,30 @@ namespace ams::gpio::driver::board::nintendo::nx::impl {
|
||||
|
||||
void InterruptEventHandler::Initialize(DriverImpl *drv, os::InterruptName intr, int ctlr) {
|
||||
/* Set fields. */
|
||||
this->driver = drv;
|
||||
this->interrupt_name = intr;
|
||||
this->controller_number = ctlr;
|
||||
m_driver = drv;
|
||||
m_interrupt_name = intr;
|
||||
m_controller_number = ctlr;
|
||||
|
||||
/* Initialize interrupt event. */
|
||||
os::InitializeInterruptEvent(std::addressof(this->interrupt_event), intr, os::EventClearMode_ManualClear);
|
||||
os::InitializeInterruptEvent(std::addressof(m_interrupt_event), intr, os::EventClearMode_ManualClear);
|
||||
|
||||
/* Initialize base. */
|
||||
IEventHandler::Initialize(std::addressof(this->interrupt_event));
|
||||
IEventHandler::Initialize(std::addressof(m_interrupt_event));
|
||||
}
|
||||
|
||||
void InterruptEventHandler::HandleEvent() {
|
||||
/* Lock the driver's interrupt mutex. */
|
||||
std::scoped_lock lk(this->driver->interrupt_control_mutex);
|
||||
std::scoped_lock lk(m_driver->m_interrupt_control_mutex);
|
||||
|
||||
/* Check each pad. */
|
||||
bool found = false;
|
||||
for (auto it = this->driver->interrupt_pad_list.begin(); !found && it != this->driver->interrupt_pad_list.end(); ++it) {
|
||||
for (auto it = m_driver->m_interrupt_pad_list.begin(); !found && it != m_driver->m_interrupt_pad_list.end(); ++it) {
|
||||
found = this->CheckAndHandleInterrupt(*it);
|
||||
}
|
||||
|
||||
/* If we didn't find a pad, clear the interrupt event. */
|
||||
if (!found) {
|
||||
os::ClearInterruptEvent(std::addressof(this->interrupt_event));
|
||||
os::ClearInterruptEvent(std::addressof(m_interrupt_event));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,13 +53,13 @@ namespace ams::gpio::driver::board::nintendo::nx::impl {
|
||||
const InternalGpioPadNumber pad_number = static_cast<InternalGpioPadNumber>(pad.GetPadNumber());
|
||||
|
||||
/* Check if the pad matches our controller number. */
|
||||
if (this->controller_number != ConvertInternalGpioPadNumberToController(pad_number)) {
|
||||
if (m_controller_number != ConvertInternalGpioPadNumberToController(pad_number)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Get the addresses of INT_STA, INT_ENB. */
|
||||
const uintptr_t sta_address = GetGpioRegisterAddress(this->driver->gpio_virtual_address, GpioRegisterType_GPIO_INT_STA, pad_number);
|
||||
const uintptr_t enb_address = GetGpioRegisterAddress(this->driver->gpio_virtual_address, GpioRegisterType_GPIO_INT_STA, pad_number);
|
||||
const uintptr_t sta_address = GetGpioRegisterAddress(m_driver->m_gpio_virtual_address, GpioRegisterType_GPIO_INT_STA, pad_number);
|
||||
const uintptr_t enb_address = GetGpioRegisterAddress(m_driver->m_gpio_virtual_address, GpioRegisterType_GPIO_INT_STA, pad_number);
|
||||
const uintptr_t pad_index = ConvertInternalGpioPadNumberToBitIndex(pad_number);
|
||||
|
||||
/* Check if both STA and ENB are set. */
|
||||
@@ -73,10 +73,10 @@ namespace ams::gpio::driver::board::nintendo::nx::impl {
|
||||
|
||||
/* Disable the interrupt on the pad. */
|
||||
pad.SetInterruptEnabled(false);
|
||||
this->driver->RemoveInterruptPad(std::addressof(pad));
|
||||
m_driver->RemoveInterruptPad(std::addressof(pad));
|
||||
|
||||
/* Clear the interrupt event. */
|
||||
os::ClearInterruptEvent(std::addressof(this->interrupt_event));
|
||||
os::ClearInterruptEvent(std::addressof(m_interrupt_event));
|
||||
|
||||
/* Signal the pad's bound event. */
|
||||
pad.SignalInterruptBoundEvent();
|
||||
@@ -84,15 +84,15 @@ namespace ams::gpio::driver::board::nintendo::nx::impl {
|
||||
return true;
|
||||
}
|
||||
|
||||
DriverImpl::DriverImpl(dd::PhysicalAddress reg_paddr, size_t size) : gpio_physical_address(reg_paddr), gpio_virtual_address(), suspend_handler(this), interrupt_pad_list(), interrupt_control_mutex() {
|
||||
DriverImpl::DriverImpl(dd::PhysicalAddress reg_paddr, size_t size) : m_gpio_physical_address(reg_paddr), m_gpio_virtual_address(), m_suspend_handler(this), m_interrupt_pad_list(), m_interrupt_control_mutex() {
|
||||
/* Get the corresponding virtual address for our physical address. */
|
||||
this->gpio_virtual_address = dd::QueryIoMapping(reg_paddr, size);
|
||||
AMS_ABORT_UNLESS(this->gpio_virtual_address != 0);
|
||||
m_gpio_virtual_address = dd::QueryIoMapping(reg_paddr, size);
|
||||
AMS_ABORT_UNLESS(m_gpio_virtual_address != 0);
|
||||
}
|
||||
|
||||
void DriverImpl::InitializeDriver() {
|
||||
/* Initialize our suspend handler. */
|
||||
this->suspend_handler.Initialize(this->gpio_virtual_address);
|
||||
m_suspend_handler.Initialize(m_gpio_virtual_address);
|
||||
}
|
||||
|
||||
void DriverImpl::FinalizeDriver() {
|
||||
@@ -107,7 +107,7 @@ namespace ams::gpio::driver::board::nintendo::nx::impl {
|
||||
const InternalGpioPadNumber pad_number = pad->GetPadNumber();
|
||||
|
||||
/* Configure the pad as GPIO by modifying the appropriate bit in CNF. */
|
||||
const uintptr_t pad_address = GetGpioRegisterAddress(this->gpio_virtual_address, GpioRegisterType_GPIO_CNF, pad_number);
|
||||
const uintptr_t pad_address = GetGpioRegisterAddress(m_gpio_virtual_address, GpioRegisterType_GPIO_CNF, pad_number);
|
||||
const uintptr_t pad_index = ConvertInternalGpioPadNumberToBitIndex(pad_number);
|
||||
SetMaskedBit(pad_address, pad_index, 1);
|
||||
|
||||
@@ -134,7 +134,7 @@ namespace ams::gpio::driver::board::nintendo::nx::impl {
|
||||
const InternalGpioPadNumber pad_number = pad->GetPadNumber();
|
||||
|
||||
/* Get the pad direction by reading the appropriate bit in OE */
|
||||
const uintptr_t pad_address = GetGpioRegisterAddress(this->gpio_virtual_address, GpioRegisterType_GPIO_OE, pad_number);
|
||||
const uintptr_t pad_address = GetGpioRegisterAddress(m_gpio_virtual_address, GpioRegisterType_GPIO_OE, pad_number);
|
||||
const uintptr_t pad_index = ConvertInternalGpioPadNumberToBitIndex(pad_number);
|
||||
|
||||
if (reg::Read(pad_address, 1u << pad_index) != 0) {
|
||||
@@ -155,7 +155,7 @@ namespace ams::gpio::driver::board::nintendo::nx::impl {
|
||||
const InternalGpioPadNumber pad_number = pad->GetPadNumber();
|
||||
|
||||
/* Configure the pad direction by modifying the appropriate bit in OE */
|
||||
const uintptr_t pad_address = GetGpioRegisterAddress(this->gpio_virtual_address, GpioRegisterType_GPIO_OE, pad_number);
|
||||
const uintptr_t pad_address = GetGpioRegisterAddress(m_gpio_virtual_address, GpioRegisterType_GPIO_OE, pad_number);
|
||||
const uintptr_t pad_index = ConvertInternalGpioPadNumberToBitIndex(pad_number);
|
||||
SetMaskedBit(pad_address, pad_index, direction);
|
||||
|
||||
@@ -174,7 +174,7 @@ namespace ams::gpio::driver::board::nintendo::nx::impl {
|
||||
const InternalGpioPadNumber pad_number = pad->GetPadNumber();
|
||||
|
||||
/* Get the pad value by reading the appropriate bit in IN */
|
||||
const uintptr_t pad_address = GetGpioRegisterAddress(this->gpio_virtual_address, GpioRegisterType_GPIO_IN, pad_number);
|
||||
const uintptr_t pad_address = GetGpioRegisterAddress(m_gpio_virtual_address, GpioRegisterType_GPIO_IN, pad_number);
|
||||
const uintptr_t pad_index = ConvertInternalGpioPadNumberToBitIndex(pad_number);
|
||||
|
||||
if (reg::Read(pad_address, 1u << pad_index) != 0) {
|
||||
@@ -194,7 +194,7 @@ namespace ams::gpio::driver::board::nintendo::nx::impl {
|
||||
const InternalGpioPadNumber pad_number = pad->GetPadNumber();
|
||||
|
||||
/* Configure the pad value by modifying the appropriate bit in IN */
|
||||
const uintptr_t pad_address = GetGpioRegisterAddress(this->gpio_virtual_address, GpioRegisterType_GPIO_IN, pad_number);
|
||||
const uintptr_t pad_address = GetGpioRegisterAddress(m_gpio_virtual_address, GpioRegisterType_GPIO_IN, pad_number);
|
||||
const uintptr_t pad_index = ConvertInternalGpioPadNumberToBitIndex(pad_number);
|
||||
SetMaskedBit(pad_address, pad_index, value);
|
||||
|
||||
@@ -213,7 +213,7 @@ namespace ams::gpio::driver::board::nintendo::nx::impl {
|
||||
const InternalGpioPadNumber pad_number = pad->GetPadNumber();
|
||||
|
||||
/* Get the pad mode by reading the appropriate bits in INT_LVL */
|
||||
const uintptr_t pad_address = GetGpioRegisterAddress(this->gpio_virtual_address, GpioRegisterType_GPIO_INT_LVL, pad_number);
|
||||
const uintptr_t pad_address = GetGpioRegisterAddress(m_gpio_virtual_address, GpioRegisterType_GPIO_INT_LVL, pad_number);
|
||||
const uintptr_t pad_index = ConvertInternalGpioPadNumberToBitIndex(pad_number);
|
||||
|
||||
switch ((reg::Read(pad_address) >> pad_index) & InternalInterruptMode_Mask) {
|
||||
@@ -236,7 +236,7 @@ namespace ams::gpio::driver::board::nintendo::nx::impl {
|
||||
const InternalGpioPadNumber pad_number = pad->GetPadNumber();
|
||||
|
||||
/* Configure the pad mode by modifying the appropriate bits in INT_LVL */
|
||||
const uintptr_t pad_address = GetGpioRegisterAddress(this->gpio_virtual_address, GpioRegisterType_GPIO_INT_LVL, pad_number);
|
||||
const uintptr_t pad_address = GetGpioRegisterAddress(m_gpio_virtual_address, GpioRegisterType_GPIO_INT_LVL, pad_number);
|
||||
const uintptr_t pad_index = ConvertInternalGpioPadNumberToBitIndex(pad_number);
|
||||
|
||||
switch (mode) {
|
||||
|
||||
@@ -26,14 +26,14 @@ namespace ams::gpio::driver::board::nintendo::nx::impl {
|
||||
|
||||
class InterruptEventHandler : public ddsf::IEventHandler {
|
||||
private:
|
||||
DriverImpl *driver;
|
||||
os::InterruptName interrupt_name;
|
||||
os::InterruptEventType interrupt_event;
|
||||
int controller_number;
|
||||
DriverImpl *m_driver;
|
||||
os::InterruptName m_interrupt_name;
|
||||
os::InterruptEventType m_interrupt_event;
|
||||
int m_controller_number;
|
||||
private:
|
||||
bool CheckAndHandleInterrupt(TegraPad &pad);
|
||||
public:
|
||||
InterruptEventHandler() : IEventHandler(), driver(nullptr), interrupt_name(), interrupt_event(), controller_number() { /* ... */ }
|
||||
InterruptEventHandler() : IEventHandler(), m_driver(nullptr), m_interrupt_name(), m_interrupt_event(), m_controller_number() { /* ... */ }
|
||||
|
||||
void Initialize(DriverImpl *drv, os::InterruptName intr, int ctlr);
|
||||
|
||||
@@ -46,11 +46,11 @@ namespace ams::gpio::driver::board::nintendo::nx::impl {
|
||||
AMS_DDSF_CASTABLE_TRAITS(ams::gpio::driver::board::nintendo::nx::impl::DriverImpl, ::ams::gpio::driver::IGpioDriver);
|
||||
friend class InterruptEventHandler;
|
||||
private:
|
||||
dd::PhysicalAddress gpio_physical_address;
|
||||
uintptr_t gpio_virtual_address;
|
||||
SuspendHandler suspend_handler;
|
||||
TegraPad::InterruptList interrupt_pad_list;
|
||||
mutable os::SdkMutex interrupt_control_mutex;
|
||||
dd::PhysicalAddress m_gpio_physical_address;
|
||||
uintptr_t m_gpio_virtual_address;
|
||||
SuspendHandler m_suspend_handler;
|
||||
TegraPad::InterruptList m_interrupt_pad_list;
|
||||
mutable os::SdkMutex m_interrupt_control_mutex;
|
||||
public:
|
||||
DriverImpl(dd::PhysicalAddress reg_paddr, size_t size);
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace ams::gpio::driver::board::nintendo::nx::impl {
|
||||
|
||||
virtual os::SdkMutex &GetInterruptControlMutex(const Pad &pad) const override {
|
||||
AMS_UNUSED(pad);
|
||||
return this->interrupt_control_mutex;
|
||||
return m_interrupt_control_mutex;
|
||||
}
|
||||
|
||||
virtual Result GetDebounceEnabled(bool *out, Pad *pad) const override;
|
||||
@@ -114,14 +114,14 @@ namespace ams::gpio::driver::board::nintendo::nx::impl {
|
||||
void AddInterruptPad(TegraPad *pad) {
|
||||
AMS_ASSERT(pad != nullptr);
|
||||
if (!pad->IsLinkedToInterruptBoundPadList()) {
|
||||
this->interrupt_pad_list.push_back(*pad);
|
||||
m_interrupt_pad_list.push_back(*pad);
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveInterruptPad(TegraPad *pad) {
|
||||
AMS_ASSERT(pad != nullptr);
|
||||
if (pad->IsLinkedToInterruptBoundPadList()) {
|
||||
this->interrupt_pad_list.erase(this->interrupt_pad_list.iterator_to(*pad));
|
||||
m_interrupt_pad_list.erase(m_interrupt_pad_list.iterator_to(*pad));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace ams::gpio::driver::board::nintendo::nx::impl {
|
||||
|
||||
void SuspendHandler::Initialize(uintptr_t gpio_vaddr) {
|
||||
/* Set our gpio virtual address. */
|
||||
this->gpio_virtual_address = gpio_vaddr;
|
||||
m_gpio_virtual_address = gpio_vaddr;
|
||||
|
||||
/* Ensure that we can use the wec library. */
|
||||
ams::wec::Initialize();
|
||||
|
||||
@@ -54,21 +54,21 @@ namespace ams::gpio::driver::board::nintendo::nx::impl {
|
||||
}
|
||||
};
|
||||
private:
|
||||
ddsf::IDriver &driver;
|
||||
uintptr_t gpio_virtual_address;
|
||||
RegisterValues register_values[GpioPadPort_Count];
|
||||
ValuesForSleepState values_for_sleep_state[GpioPadPort_Count];
|
||||
ddsf::IDriver &m_driver;
|
||||
uintptr_t m_gpio_virtual_address;
|
||||
RegisterValues m_register_values[GpioPadPort_Count];
|
||||
ValuesForSleepState m_values_for_sleep_state[GpioPadPort_Count];
|
||||
private:
|
||||
uintptr_t GetGpioVirtualAddress() const {
|
||||
AMS_ASSERT(this->gpio_virtual_address != 0);
|
||||
return this->gpio_virtual_address;
|
||||
AMS_ASSERT(m_gpio_virtual_address != 0);
|
||||
return m_gpio_virtual_address;
|
||||
}
|
||||
public:
|
||||
explicit SuspendHandler(ddsf::IDriver *drv) : driver(*drv), gpio_virtual_address(0) {
|
||||
for (auto &rv : this->register_values) {
|
||||
explicit SuspendHandler(ddsf::IDriver *drv) : m_driver(*drv), m_gpio_virtual_address(0) {
|
||||
for (auto &rv : m_register_values) {
|
||||
rv.Reset();
|
||||
}
|
||||
for (auto &v : this->values_for_sleep_state) {
|
||||
for (auto &v : m_values_for_sleep_state) {
|
||||
v.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,26 +351,26 @@ namespace ams::gpio::driver::board::nintendo::nx::impl {
|
||||
private:
|
||||
using Base = ::ams::gpio::driver::Pad;
|
||||
private:
|
||||
util::IntrusiveListNode interrupt_list_node;
|
||||
PadInfo info;
|
||||
PadStatus status;
|
||||
util::IntrusiveListNode m_interrupt_list_node;
|
||||
PadInfo m_info;
|
||||
PadStatus m_status;
|
||||
public:
|
||||
using InterruptListTraits = util::IntrusiveListMemberTraitsDeferredAssert<&TegraPad::interrupt_list_node>;
|
||||
using InterruptListTraits = util::IntrusiveListMemberTraitsDeferredAssert<&TegraPad::m_interrupt_list_node>;
|
||||
using InterruptList = typename InterruptListTraits::ListType;
|
||||
friend class util::IntrusiveList<TegraPad, util::IntrusiveListMemberTraitsDeferredAssert<&TegraPad::interrupt_list_node>>;
|
||||
friend class util::IntrusiveList<TegraPad, util::IntrusiveListMemberTraitsDeferredAssert<&TegraPad::m_interrupt_list_node>>;
|
||||
public:
|
||||
TegraPad() : Pad(), interrupt_list_node(), info(), status() { /* ... */ }
|
||||
TegraPad() : Pad(), m_interrupt_list_node(), m_info(), m_status() { /* ... */ }
|
||||
|
||||
const PadInfo &GetInfo() const { return this->info; }
|
||||
PadStatus &GetStatus() { return this->status; }
|
||||
const PadInfo &GetInfo() const { return m_info; }
|
||||
PadStatus &GetStatus() { return m_status; }
|
||||
|
||||
void SetParameters(int pad, const PadInfo &i) {
|
||||
Base::SetPadNumber(pad);
|
||||
this->info = i;
|
||||
m_info = i;
|
||||
}
|
||||
|
||||
bool IsLinkedToInterruptBoundPadList() const {
|
||||
return this->interrupt_list_node.IsLinked();
|
||||
return m_interrupt_list_node.IsLinked();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -73,8 +73,8 @@ namespace ams::gpio::driver::impl {
|
||||
auto ev_guard = SCOPE_GUARD { os::DestroySystemEvent(event); };
|
||||
|
||||
/* Attach the event to our holder. */
|
||||
this->event_holder.AttachEvent(event);
|
||||
auto hl_guard = SCOPE_GUARD { this->event_holder.DetachEvent(); };
|
||||
m_event_holder.AttachEvent(event);
|
||||
auto hl_guard = SCOPE_GUARD { m_event_holder.DetachEvent(); };
|
||||
|
||||
/* Update interrupt needed. */
|
||||
R_TRY(this->UpdateDriverInterruptEnabled());
|
||||
@@ -97,7 +97,7 @@ namespace ams::gpio::driver::impl {
|
||||
}
|
||||
|
||||
/* Detach and destroy the event */
|
||||
os::DestroySystemEvent(this->event_holder.DetachEvent());
|
||||
os::DestroySystemEvent(m_event_holder.DetachEvent());
|
||||
|
||||
/* Update interrupt needed. */
|
||||
R_ABORT_UNLESS(this->UpdateDriverInterruptEnabled());
|
||||
@@ -143,7 +143,7 @@ namespace ams::gpio::driver::impl {
|
||||
AMS_ASSERT(driver.GetInterruptControlMutex(pad).IsLockedByCurrentThread());
|
||||
AMS_UNUSED(pad, driver);
|
||||
|
||||
if (auto *event = this->event_holder.GetSystemEvent(); event != nullptr) {
|
||||
if (auto *event = m_event_holder.GetSystemEvent(); event != nullptr) {
|
||||
os::SignalSystemEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,82 +20,82 @@ namespace ams::gpio {
|
||||
|
||||
class RemotePadSessionImpl {
|
||||
private:
|
||||
::GpioPadSession srv;
|
||||
::GpioPadSession m_srv;
|
||||
public:
|
||||
RemotePadSessionImpl(::GpioPadSession &p) : srv(p) { /* ... */ }
|
||||
RemotePadSessionImpl(::GpioPadSession &p) : m_srv(p) { /* ... */ }
|
||||
|
||||
~RemotePadSessionImpl() { ::gpioPadClose(std::addressof(this->srv)); }
|
||||
~RemotePadSessionImpl() { ::gpioPadClose(std::addressof(m_srv)); }
|
||||
public:
|
||||
/* Actual commands. */
|
||||
Result SetDirection(gpio::Direction direction) {
|
||||
return ::gpioPadSetDirection(std::addressof(this->srv), static_cast<::GpioDirection>(static_cast<u32>(direction)));
|
||||
return ::gpioPadSetDirection(std::addressof(m_srv), static_cast<::GpioDirection>(static_cast<u32>(direction)));
|
||||
}
|
||||
|
||||
Result GetDirection(ams::sf::Out<gpio::Direction> out) {
|
||||
static_assert(sizeof(gpio::Direction) == sizeof(::GpioDirection));
|
||||
return ::gpioPadGetDirection(std::addressof(this->srv), reinterpret_cast<::GpioDirection *>(out.GetPointer()));
|
||||
return ::gpioPadGetDirection(std::addressof(m_srv), reinterpret_cast<::GpioDirection *>(out.GetPointer()));
|
||||
}
|
||||
|
||||
Result SetInterruptMode(gpio::InterruptMode mode) {
|
||||
return ::gpioPadSetInterruptMode(std::addressof(this->srv), static_cast<::GpioInterruptMode>(static_cast<u32>(mode)));
|
||||
return ::gpioPadSetInterruptMode(std::addressof(m_srv), static_cast<::GpioInterruptMode>(static_cast<u32>(mode)));
|
||||
}
|
||||
|
||||
Result GetInterruptMode(ams::sf::Out<gpio::InterruptMode> out) {
|
||||
static_assert(sizeof(gpio::InterruptMode) == sizeof(::GpioInterruptMode));
|
||||
return ::gpioPadGetInterruptMode(std::addressof(this->srv), reinterpret_cast<::GpioInterruptMode *>(out.GetPointer()));
|
||||
return ::gpioPadGetInterruptMode(std::addressof(m_srv), reinterpret_cast<::GpioInterruptMode *>(out.GetPointer()));
|
||||
}
|
||||
|
||||
Result SetInterruptEnable(bool enable) {
|
||||
return ::gpioPadSetInterruptEnable(std::addressof(this->srv), enable);
|
||||
return ::gpioPadSetInterruptEnable(std::addressof(m_srv), enable);
|
||||
}
|
||||
|
||||
Result GetInterruptEnable(ams::sf::Out<bool> out) {
|
||||
return ::gpioPadGetInterruptEnable(std::addressof(this->srv), out.GetPointer());
|
||||
return ::gpioPadGetInterruptEnable(std::addressof(m_srv), out.GetPointer());
|
||||
}
|
||||
|
||||
Result GetInterruptStatus(ams::sf::Out<gpio::InterruptStatus> out) {
|
||||
static_assert(sizeof(gpio::InterruptStatus) == sizeof(::GpioInterruptStatus));
|
||||
return ::gpioPadGetInterruptStatus(std::addressof(this->srv), reinterpret_cast<::GpioInterruptStatus *>(out.GetPointer()));
|
||||
return ::gpioPadGetInterruptStatus(std::addressof(m_srv), reinterpret_cast<::GpioInterruptStatus *>(out.GetPointer()));
|
||||
}
|
||||
|
||||
Result ClearInterruptStatus() {
|
||||
return ::gpioPadClearInterruptStatus(std::addressof(this->srv));
|
||||
return ::gpioPadClearInterruptStatus(std::addressof(m_srv));
|
||||
}
|
||||
|
||||
Result SetValue(gpio::GpioValue value) {
|
||||
return ::gpioPadSetValue(std::addressof(this->srv), static_cast<::GpioValue>(static_cast<u32>(value)));
|
||||
return ::gpioPadSetValue(std::addressof(m_srv), static_cast<::GpioValue>(static_cast<u32>(value)));
|
||||
}
|
||||
|
||||
Result GetValue(ams::sf::Out<gpio::GpioValue> out) {
|
||||
static_assert(sizeof(gpio::GpioValue) == sizeof(::GpioValue));
|
||||
return ::gpioPadGetValue(std::addressof(this->srv), reinterpret_cast<::GpioValue *>(out.GetPointer()));
|
||||
return ::gpioPadGetValue(std::addressof(m_srv), reinterpret_cast<::GpioValue *>(out.GetPointer()));
|
||||
}
|
||||
|
||||
Result BindInterrupt(ams::sf::OutCopyHandle out) {
|
||||
::Event ev;
|
||||
R_TRY(::gpioPadBindInterrupt(std::addressof(this->srv), std::addressof(ev)));
|
||||
R_TRY(::gpioPadBindInterrupt(std::addressof(m_srv), std::addressof(ev)));
|
||||
out.SetValue(ev.revent, true);
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result UnbindInterrupt() {
|
||||
return ::gpioPadUnbindInterrupt(std::addressof(this->srv));
|
||||
return ::gpioPadUnbindInterrupt(std::addressof(m_srv));
|
||||
}
|
||||
|
||||
Result SetDebounceEnabled(bool enable) {
|
||||
return ::gpioPadSetDebounceEnabled(std::addressof(this->srv), enable);
|
||||
return ::gpioPadSetDebounceEnabled(std::addressof(m_srv), enable);
|
||||
}
|
||||
|
||||
Result GetDebounceEnabled(ams::sf::Out<bool> out) {
|
||||
return ::gpioPadGetDebounceEnabled(std::addressof(this->srv), out.GetPointer());
|
||||
return ::gpioPadGetDebounceEnabled(std::addressof(m_srv), out.GetPointer());
|
||||
}
|
||||
|
||||
Result SetDebounceTime(s32 ms) {
|
||||
return ::gpioPadSetDebounceTime(std::addressof(this->srv), ms);
|
||||
return ::gpioPadSetDebounceTime(std::addressof(m_srv), ms);
|
||||
}
|
||||
|
||||
Result GetDebounceTime(ams::sf::Out<s32> out) {
|
||||
return ::gpioPadGetDebounceTime(std::addressof(this->srv), out.GetPointer());
|
||||
return ::gpioPadGetDebounceTime(std::addressof(m_srv), out.GetPointer());
|
||||
}
|
||||
|
||||
Result SetValueForSleepState(gpio::GpioValue value) {
|
||||
|
||||
@@ -19,12 +19,12 @@
|
||||
namespace ams::gpio::server {
|
||||
|
||||
ManagerImpl::ManagerImpl() {
|
||||
this->heap_handle = lmem::CreateExpHeap(this->heap_buffer, sizeof(this->heap_buffer), lmem::CreateOption_None);
|
||||
this->pad_allocator.Attach(this->heap_handle);
|
||||
m_heap_handle = lmem::CreateExpHeap(m_heap_buffer, sizeof(m_heap_buffer), lmem::CreateOption_None);
|
||||
m_pad_allocator.Attach(m_heap_handle);
|
||||
}
|
||||
|
||||
ManagerImpl::~ManagerImpl() {
|
||||
lmem::DestroyExpHeap(this->heap_handle);
|
||||
lmem::DestroyExpHeap(m_heap_handle);
|
||||
}
|
||||
|
||||
Result ManagerImpl::OpenSessionForDev(ams::sf::Out<ams::sf::SharedPointer<gpio::sf::IPadSession>> out, s32 pad_descriptor) {
|
||||
@@ -69,7 +69,7 @@ namespace ams::gpio::server {
|
||||
|
||||
Result ManagerImpl::OpenSession2(ams::sf::Out<ams::sf::SharedPointer<gpio::sf::IPadSession>> out, DeviceCode device_code, ddsf::AccessMode access_mode) {
|
||||
/* Allocate a session. */
|
||||
auto session = Factory::CreateSharedEmplaced<gpio::sf::IPadSession, PadSessionImpl>(std::addressof(this->pad_allocator), this);
|
||||
auto session = Factory::CreateSharedEmplaced<gpio::sf::IPadSession, PadSessionImpl>(std::addressof(m_pad_allocator), this);
|
||||
|
||||
/* Open the session. */
|
||||
R_TRY(session.GetImpl().OpenSession(device_code, access_mode));
|
||||
|
||||
@@ -24,9 +24,9 @@ namespace ams::gpio::server {
|
||||
using Allocator = ams::sf::ExpHeapAllocator;
|
||||
using Factory = ams::sf::ObjectFactory<Allocator::Policy>;
|
||||
private:
|
||||
lmem::HeapHandle heap_handle;
|
||||
Allocator pad_allocator;
|
||||
u8 heap_buffer[12_KB];
|
||||
lmem::HeapHandle m_heap_handle;
|
||||
Allocator m_pad_allocator;
|
||||
u8 m_heap_buffer[12_KB];
|
||||
public:
|
||||
ManagerImpl();
|
||||
|
||||
|
||||
@@ -22,54 +22,54 @@ namespace ams::gpio::server {
|
||||
|
||||
class PadSessionImpl {
|
||||
private:
|
||||
ManagerImpl *parent; /* NOTE: this is an sf::SharedPointer<> in Nintendo's code. */
|
||||
gpio::driver::GpioPadSession internal_pad_session;
|
||||
bool has_session;
|
||||
os::SystemEvent system_event;
|
||||
ManagerImpl *m_parent; /* NOTE: this is an sf::SharedPointer<> in Nintendo's code. */
|
||||
gpio::driver::GpioPadSession m_internal_pad_session;
|
||||
bool m_has_session;
|
||||
os::SystemEvent m_system_event;
|
||||
public:
|
||||
explicit PadSessionImpl(ManagerImpl *p) : parent(p), has_session(false) { /* ... */ }
|
||||
explicit PadSessionImpl(ManagerImpl *p) : m_parent(p), m_has_session(false) { /* ... */ }
|
||||
|
||||
~PadSessionImpl() {
|
||||
if (this->has_session) {
|
||||
gpio::driver::CloseSession(std::addressof(this->internal_pad_session));
|
||||
if (m_has_session) {
|
||||
gpio::driver::CloseSession(std::addressof(m_internal_pad_session));
|
||||
}
|
||||
}
|
||||
|
||||
Result OpenSession(DeviceCode device_code, ddsf::AccessMode access_mode) {
|
||||
AMS_ABORT_UNLESS(!this->has_session);
|
||||
AMS_ABORT_UNLESS(!m_has_session);
|
||||
|
||||
R_TRY(gpio::driver::OpenSession(std::addressof(this->internal_pad_session), device_code, access_mode));
|
||||
this->has_session = true;
|
||||
R_TRY(gpio::driver::OpenSession(std::addressof(m_internal_pad_session), device_code, access_mode));
|
||||
m_has_session = true;
|
||||
return ResultSuccess();
|
||||
}
|
||||
public:
|
||||
/* Actual commands. */
|
||||
Result SetDirection(gpio::Direction direction) {
|
||||
/* Validate our state. */
|
||||
AMS_ASSERT(this->has_session);
|
||||
AMS_ASSERT(m_has_session);
|
||||
|
||||
/* Validate the direction. */
|
||||
R_UNLESS((direction == Direction_Input || direction == Direction_Output), gpio::ResultInvalidArgument());
|
||||
|
||||
/* Invoke the driver library. */
|
||||
R_TRY(gpio::driver::SetDirection(std::addressof(this->internal_pad_session), direction));
|
||||
R_TRY(gpio::driver::SetDirection(std::addressof(m_internal_pad_session), direction));
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result GetDirection(ams::sf::Out<gpio::Direction> out) {
|
||||
/* Validate our state. */
|
||||
AMS_ASSERT(this->has_session);
|
||||
AMS_ASSERT(m_has_session);
|
||||
|
||||
/* Invoke the driver library. */
|
||||
R_TRY(gpio::driver::GetDirection(out.GetPointer(), std::addressof(this->internal_pad_session)));
|
||||
R_TRY(gpio::driver::GetDirection(out.GetPointer(), std::addressof(m_internal_pad_session)));
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result SetInterruptMode(gpio::InterruptMode mode) {
|
||||
/* Validate our state. */
|
||||
AMS_ASSERT(this->has_session);
|
||||
AMS_ASSERT(m_has_session);
|
||||
|
||||
/* TODO */
|
||||
AMS_UNUSED(mode);
|
||||
@@ -78,7 +78,7 @@ namespace ams::gpio::server {
|
||||
|
||||
Result GetInterruptMode(ams::sf::Out<gpio::InterruptMode> out) {
|
||||
/* Validate our state. */
|
||||
AMS_ASSERT(this->has_session);
|
||||
AMS_ASSERT(m_has_session);
|
||||
|
||||
/* TODO */
|
||||
AMS_UNUSED(out);
|
||||
@@ -87,7 +87,7 @@ namespace ams::gpio::server {
|
||||
|
||||
Result SetInterruptEnable(bool enable) {
|
||||
/* Validate our state. */
|
||||
AMS_ASSERT(this->has_session);
|
||||
AMS_ASSERT(m_has_session);
|
||||
|
||||
/* TODO */
|
||||
AMS_UNUSED(enable);
|
||||
@@ -96,7 +96,7 @@ namespace ams::gpio::server {
|
||||
|
||||
Result GetInterruptEnable(ams::sf::Out<bool> out) {
|
||||
/* Validate our state. */
|
||||
AMS_ASSERT(this->has_session);
|
||||
AMS_ASSERT(m_has_session);
|
||||
|
||||
/* TODO */
|
||||
AMS_UNUSED(out);
|
||||
@@ -105,7 +105,7 @@ namespace ams::gpio::server {
|
||||
|
||||
Result GetInterruptStatus(ams::sf::Out<gpio::InterruptStatus> out) {
|
||||
/* Validate our state. */
|
||||
AMS_ASSERT(this->has_session);
|
||||
AMS_ASSERT(m_has_session);
|
||||
|
||||
/* TODO */
|
||||
AMS_UNUSED(out);
|
||||
@@ -114,7 +114,7 @@ namespace ams::gpio::server {
|
||||
|
||||
Result ClearInterruptStatus() {
|
||||
/* Validate our state. */
|
||||
AMS_ASSERT(this->has_session);
|
||||
AMS_ASSERT(m_has_session);
|
||||
|
||||
/* TODO */
|
||||
AMS_ABORT();
|
||||
@@ -122,30 +122,30 @@ namespace ams::gpio::server {
|
||||
|
||||
Result SetValue(gpio::GpioValue value) {
|
||||
/* Validate our state. */
|
||||
AMS_ASSERT(this->has_session);
|
||||
AMS_ASSERT(m_has_session);
|
||||
|
||||
/* Validate the value. */
|
||||
R_UNLESS((value == GpioValue_Low || value == GpioValue_High), gpio::ResultInvalidArgument());
|
||||
|
||||
/* Invoke the driver library. */
|
||||
R_TRY(gpio::driver::SetValue(std::addressof(this->internal_pad_session), value));
|
||||
R_TRY(gpio::driver::SetValue(std::addressof(m_internal_pad_session), value));
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result GetValue(ams::sf::Out<gpio::GpioValue> out) {
|
||||
/* Validate our state. */
|
||||
AMS_ASSERT(this->has_session);
|
||||
AMS_ASSERT(m_has_session);
|
||||
|
||||
/* Invoke the driver library. */
|
||||
R_TRY(gpio::driver::GetValue(out.GetPointer(), std::addressof(this->internal_pad_session)));
|
||||
R_TRY(gpio::driver::GetValue(out.GetPointer(), std::addressof(m_internal_pad_session)));
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result BindInterrupt(ams::sf::OutCopyHandle out) {
|
||||
/* Validate our state. */
|
||||
AMS_ASSERT(this->has_session);
|
||||
AMS_ASSERT(m_has_session);
|
||||
|
||||
/* TODO */
|
||||
AMS_UNUSED(out);
|
||||
@@ -154,7 +154,7 @@ namespace ams::gpio::server {
|
||||
|
||||
Result UnbindInterrupt() {
|
||||
/* Validate our state. */
|
||||
AMS_ASSERT(this->has_session);
|
||||
AMS_ASSERT(m_has_session);
|
||||
|
||||
/* TODO */
|
||||
AMS_ABORT();
|
||||
@@ -162,7 +162,7 @@ namespace ams::gpio::server {
|
||||
|
||||
Result SetDebounceEnabled(bool enable) {
|
||||
/* Validate our state. */
|
||||
AMS_ASSERT(this->has_session);
|
||||
AMS_ASSERT(m_has_session);
|
||||
|
||||
/* TODO */
|
||||
AMS_UNUSED(enable);
|
||||
@@ -171,7 +171,7 @@ namespace ams::gpio::server {
|
||||
|
||||
Result GetDebounceEnabled(ams::sf::Out<bool> out) {
|
||||
/* Validate our state. */
|
||||
AMS_ASSERT(this->has_session);
|
||||
AMS_ASSERT(m_has_session);
|
||||
|
||||
/* TODO */
|
||||
AMS_UNUSED(out);
|
||||
@@ -180,7 +180,7 @@ namespace ams::gpio::server {
|
||||
|
||||
Result SetDebounceTime(s32 ms) {
|
||||
/* Validate our state. */
|
||||
AMS_ASSERT(this->has_session);
|
||||
AMS_ASSERT(m_has_session);
|
||||
|
||||
/* TODO */
|
||||
AMS_UNUSED(ms);
|
||||
@@ -189,7 +189,7 @@ namespace ams::gpio::server {
|
||||
|
||||
Result GetDebounceTime(ams::sf::Out<s32> out) {
|
||||
/* Validate our state. */
|
||||
AMS_ASSERT(this->has_session);
|
||||
AMS_ASSERT(m_has_session);
|
||||
|
||||
/* TODO */
|
||||
AMS_UNUSED(out);
|
||||
@@ -198,7 +198,7 @@ namespace ams::gpio::server {
|
||||
|
||||
Result SetValueForSleepState(gpio::GpioValue value) {
|
||||
/* Validate our state. */
|
||||
AMS_ASSERT(this->has_session);
|
||||
AMS_ASSERT(m_has_session);
|
||||
|
||||
/* TODO */
|
||||
AMS_UNUSED(value);
|
||||
@@ -207,7 +207,7 @@ namespace ams::gpio::server {
|
||||
|
||||
Result GetValueForSleepState(ams::sf::Out<gpio::GpioValue> out) {
|
||||
/* Validate our state. */
|
||||
AMS_ASSERT(this->has_session);
|
||||
AMS_ASSERT(m_has_session);
|
||||
|
||||
/* TODO */
|
||||
AMS_UNUSED(out);
|
||||
|
||||
@@ -1301,7 +1301,7 @@ namespace ams::htcfs {
|
||||
Header request, response;
|
||||
|
||||
/* Create header for the request. */
|
||||
m_header_factory.MakeWriteFileHeader(std::addressof(request), buffer_size, handle, option.value, offset);
|
||||
m_header_factory.MakeWriteFileHeader(std::addressof(request), buffer_size, handle, option._value, offset);
|
||||
|
||||
/* Send the request to the host. */
|
||||
R_TRY(this->SendRequest(request, buffer, buffer_size));
|
||||
@@ -1335,7 +1335,7 @@ namespace ams::htcfs {
|
||||
Header request, response;
|
||||
|
||||
/* Create header for the request. */
|
||||
m_header_factory.MakeWriteFileLargeHeader(std::addressof(request), handle, option.value, offset, buffer_size, DataChannelId);
|
||||
m_header_factory.MakeWriteFileLargeHeader(std::addressof(request), handle, option._value, offset, buffer_size, DataChannelId);
|
||||
|
||||
/* Send the request to the host. */
|
||||
R_TRY(this->SendRequest(request));
|
||||
|
||||
@@ -55,56 +55,56 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
}
|
||||
|
||||
void I2cBusAccessor::Initialize(dd::PhysicalAddress reg_paddr, size_t reg_size, os::InterruptName intr, bool pb, SpeedMode sm) {
|
||||
AMS_ASSERT(this->state == State::NotInitialized);
|
||||
AMS_ASSERT(m_state == State::NotInitialized);
|
||||
|
||||
this->is_power_bus = pb;
|
||||
this->speed_mode = sm;
|
||||
this->interrupt_name = intr;
|
||||
this->registers_phys_addr = reg_paddr;
|
||||
this->registers_size = reg_size;
|
||||
this->state = State::Initializing;
|
||||
m_is_power_bus = pb;
|
||||
m_speed_mode = sm;
|
||||
m_interrupt_name = intr;
|
||||
m_registers_phys_addr = reg_paddr;
|
||||
m_registers_size = reg_size;
|
||||
m_state = State::Initializing;
|
||||
}
|
||||
|
||||
void I2cBusAccessor::RegisterDeviceCode(DeviceCode dc) {
|
||||
AMS_ASSERT(this->state == State::Initializing);
|
||||
AMS_ASSERT(m_state == State::Initializing);
|
||||
|
||||
this->device_code = dc;
|
||||
m_device_code = dc;
|
||||
}
|
||||
|
||||
void I2cBusAccessor::InitializeDriver() {
|
||||
AMS_ASSERT(this->state == State::Initializing);
|
||||
AMS_ASSERT(m_state == State::Initializing);
|
||||
|
||||
this->registers = reinterpret_cast<volatile I2cRegisters *>(dd::QueryIoMapping(this->registers_phys_addr, this->registers_size));
|
||||
AMS_ABORT_UNLESS(this->registers != nullptr);
|
||||
m_registers = reinterpret_cast<volatile I2cRegisters *>(dd::QueryIoMapping(m_registers_phys_addr, m_registers_size));
|
||||
AMS_ABORT_UNLESS(m_registers != nullptr);
|
||||
|
||||
this->state = State::Initialized;
|
||||
m_state = State::Initialized;
|
||||
}
|
||||
|
||||
void I2cBusAccessor::FinalizeDriver() {
|
||||
AMS_ASSERT(this->state == State::Initialized);
|
||||
this->state = State::Initializing;
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
m_state = State::Initializing;
|
||||
}
|
||||
|
||||
Result I2cBusAccessor::InitializeDevice(I2cDeviceProperty *device) {
|
||||
/* Check that the device is valid. */
|
||||
AMS_ASSERT(device != nullptr);
|
||||
AMS_ASSERT(this->state == State::Initialized);
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
AMS_UNUSED(device);
|
||||
|
||||
/* Acquire exclusive access. */
|
||||
std::scoped_lock lk(this->user_count_mutex);
|
||||
std::scoped_lock lk(m_user_count_mutex);
|
||||
|
||||
/* Increment our user count -- if we're already open, we're done. */
|
||||
AMS_ASSERT(this->user_count >= 0);
|
||||
++this->user_count;
|
||||
R_SUCCEED_IF(this->user_count > 1);
|
||||
AMS_ASSERT(m_user_count >= 0);
|
||||
++m_user_count;
|
||||
R_SUCCEED_IF(m_user_count > 1);
|
||||
|
||||
/* Initialize our interrupt event. */
|
||||
os::InitializeInterruptEvent(std::addressof(this->interrupt_event), this->interrupt_name, os::EventClearMode_ManualClear);
|
||||
os::ClearInterruptEvent(std::addressof(this->interrupt_event));
|
||||
os::InitializeInterruptEvent(std::addressof(m_interrupt_event), m_interrupt_name, os::EventClearMode_ManualClear);
|
||||
os::ClearInterruptEvent(std::addressof(m_interrupt_event));
|
||||
|
||||
/* If we're not power bus, perform power management init. */
|
||||
if (!this->is_power_bus) {
|
||||
if (!m_is_power_bus) {
|
||||
/* Initialize regulator library. */
|
||||
regulator::Initialize();
|
||||
|
||||
@@ -112,9 +112,9 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
R_TRY(this->TryOpenRegulatorSession());
|
||||
|
||||
/* If we have a regulator session, set voltage to 2.9V. */
|
||||
if (this->has_regulator_session) {
|
||||
if (m_has_regulator_session) {
|
||||
/* NOTE: Nintendo does not check the result, here. */
|
||||
regulator::SetVoltageValue(std::addressof(this->regulator_session), 2'900'000u);
|
||||
regulator::SetVoltageValue(std::addressof(m_regulator_session), 2'900'000u);
|
||||
}
|
||||
|
||||
/* Initialize clock/reset library. */
|
||||
@@ -125,12 +125,12 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
this->ExecuteInitialConfig();
|
||||
|
||||
/* If we have a regulator session, enable voltage. */
|
||||
if (!this->is_power_bus && this->has_regulator_session) {
|
||||
if (!m_is_power_bus && m_has_regulator_session) {
|
||||
/* Check whether voltage was already enabled. */
|
||||
const bool was_enabled = regulator::GetVoltageEnabled(std::addressof(this->regulator_session));
|
||||
const bool was_enabled = regulator::GetVoltageEnabled(std::addressof(m_regulator_session));
|
||||
|
||||
/* NOTE: Nintendo does not check the result of this call. */
|
||||
regulator::SetVoltageEnabled(std::addressof(this->regulator_session), true);
|
||||
regulator::SetVoltageEnabled(std::addressof(m_regulator_session), true);
|
||||
|
||||
/* If we enabled voltage, delay to give our enable time to take. */
|
||||
if (!was_enabled) {
|
||||
@@ -144,35 +144,35 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
void I2cBusAccessor::FinalizeDevice(I2cDeviceProperty *device) {
|
||||
/* Check that the device is valid. */
|
||||
AMS_ASSERT(device != nullptr);
|
||||
AMS_ASSERT(this->state == State::Initialized);
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
AMS_UNUSED(device);
|
||||
|
||||
/* Acquire exclusive access. */
|
||||
std::scoped_lock lk(this->user_count_mutex);
|
||||
std::scoped_lock lk(m_user_count_mutex);
|
||||
|
||||
/* Increment our user count -- if we're not the last user, we're done. */
|
||||
AMS_ASSERT(this->user_count > 0);
|
||||
--this->user_count;
|
||||
if (this->user_count > 0) {
|
||||
AMS_ASSERT(m_user_count > 0);
|
||||
--m_user_count;
|
||||
if (m_user_count > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Finalize our interrupt event. */
|
||||
os::FinalizeInterruptEvent(std::addressof(this->interrupt_event));
|
||||
os::FinalizeInterruptEvent(std::addressof(m_interrupt_event));
|
||||
|
||||
/* If we have a regulator session, disable voltage. */
|
||||
if (this->has_regulator_session) {
|
||||
if (m_has_regulator_session) {
|
||||
/* NOTE: Nintendo does not check the result of this call. */
|
||||
regulator::SetVoltageEnabled(std::addressof(this->regulator_session), false);
|
||||
regulator::SetVoltageEnabled(std::addressof(m_regulator_session), false);
|
||||
}
|
||||
|
||||
/* Finalize the clock/reset library. */
|
||||
clkrst::Finalize();
|
||||
|
||||
/* If we have a regulator session, close it. */
|
||||
if (this->has_regulator_session) {
|
||||
regulator::CloseSession(std::addressof(this->regulator_session));
|
||||
this->has_regulator_session = false;
|
||||
if (m_has_regulator_session) {
|
||||
regulator::CloseSession(std::addressof(m_regulator_session));
|
||||
m_has_regulator_session = false;
|
||||
}
|
||||
|
||||
/* Finalize the regulator library. */
|
||||
@@ -185,10 +185,10 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
AMS_ASSERT(src != nullptr);
|
||||
AMS_ASSERT(src_size > 0);
|
||||
|
||||
if (this->is_power_bus) {
|
||||
AMS_ASSERT(this->state == State::Initialized || this->state == State::Suspended);
|
||||
if (m_is_power_bus) {
|
||||
AMS_ASSERT(m_state == State::Initialized || m_state == State::Suspended);
|
||||
} else {
|
||||
AMS_ASSERT(this->state == State::Initialized);
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
}
|
||||
|
||||
/* Send the data. */
|
||||
@@ -201,10 +201,10 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
AMS_ASSERT(dst != nullptr);
|
||||
AMS_ASSERT(dst_size > 0);
|
||||
|
||||
if (this->is_power_bus) {
|
||||
AMS_ASSERT(this->state == State::Initialized || this->state == State::Suspended);
|
||||
if (m_is_power_bus) {
|
||||
AMS_ASSERT(m_state == State::Initialized || m_state == State::Suspended);
|
||||
} else {
|
||||
AMS_ASSERT(this->state == State::Initialized);
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
}
|
||||
|
||||
/* Send the data. */
|
||||
@@ -213,18 +213,18 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
|
||||
void I2cBusAccessor::SuspendBus() {
|
||||
/* Check that state is valid. */
|
||||
AMS_ASSERT(this->state == State::Initialized);
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
|
||||
/* Acquire exclusive access. */
|
||||
std::scoped_lock lk(this->user_count_mutex);
|
||||
std::scoped_lock lk(m_user_count_mutex);
|
||||
|
||||
/* If we need to, disable clock/voltage appropriately. */
|
||||
if (!this->is_power_bus && this->user_count > 0) {
|
||||
if (!m_is_power_bus && m_user_count > 0) {
|
||||
/* Disable clock. */
|
||||
{
|
||||
/* Open a clkrst session. */
|
||||
clkrst::ClkRstSession clkrst_session;
|
||||
R_ABORT_UNLESS(clkrst::OpenSession(std::addressof(clkrst_session), this->device_code));
|
||||
R_ABORT_UNLESS(clkrst::OpenSession(std::addressof(clkrst_session), m_device_code));
|
||||
ON_SCOPE_EXIT { clkrst::CloseSession(std::addressof(clkrst_session)); };
|
||||
|
||||
/* Set clock disabled for the session. */
|
||||
@@ -232,47 +232,47 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
}
|
||||
|
||||
/* Disable voltage. */
|
||||
if (this->has_regulator_session) {
|
||||
regulator::SetVoltageEnabled(std::addressof(this->regulator_session), false);
|
||||
if (m_has_regulator_session) {
|
||||
regulator::SetVoltageEnabled(std::addressof(m_regulator_session), false);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update state. */
|
||||
this->state = State::Suspended;
|
||||
m_state = State::Suspended;
|
||||
}
|
||||
|
||||
void I2cBusAccessor::SuspendPowerBus() {
|
||||
/* Check that state is valid. */
|
||||
AMS_ASSERT(this->state == State::Suspended);
|
||||
AMS_ASSERT(m_state == State::Suspended);
|
||||
|
||||
/* Acquire exclusive access. */
|
||||
std::scoped_lock lk(this->user_count_mutex);
|
||||
std::scoped_lock lk(m_user_count_mutex);
|
||||
|
||||
/* If we need to, disable clock/voltage appropriately. */
|
||||
if (this->is_power_bus && this->user_count > 0) {
|
||||
if (m_is_power_bus && m_user_count > 0) {
|
||||
/* Nothing should actually be done here. */
|
||||
}
|
||||
|
||||
/* Update state. */
|
||||
this->state = State::PowerBusSuspended;
|
||||
m_state = State::PowerBusSuspended;
|
||||
}
|
||||
|
||||
void I2cBusAccessor::ResumeBus() {
|
||||
/* Check that state is valid. */
|
||||
AMS_ASSERT(this->state == State::Suspended);
|
||||
AMS_ASSERT(m_state == State::Suspended);
|
||||
|
||||
/* Acquire exclusive access. */
|
||||
std::scoped_lock lk(this->user_count_mutex);
|
||||
std::scoped_lock lk(m_user_count_mutex);
|
||||
|
||||
/* If we need to, enable clock/voltage appropriately. */
|
||||
if (!this->is_power_bus && this->user_count > 0) {
|
||||
if (!m_is_power_bus && m_user_count > 0) {
|
||||
/* Enable voltage. */
|
||||
if (this->has_regulator_session) {
|
||||
if (m_has_regulator_session) {
|
||||
/* Check whether voltage was already enabled. */
|
||||
const bool was_enabled = regulator::GetVoltageEnabled(std::addressof(this->regulator_session));
|
||||
const bool was_enabled = regulator::GetVoltageEnabled(std::addressof(m_regulator_session));
|
||||
|
||||
/* NOTE: Nintendo does not check the result of this call. */
|
||||
regulator::SetVoltageEnabled(std::addressof(this->regulator_session), true);
|
||||
regulator::SetVoltageEnabled(std::addressof(m_regulator_session), true);
|
||||
|
||||
/* If we enabled voltage, delay to give our enable time to take. */
|
||||
if (!was_enabled) {
|
||||
@@ -285,36 +285,36 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
}
|
||||
|
||||
/* Update state. */
|
||||
this->state = State::Initialized;
|
||||
m_state = State::Initialized;
|
||||
}
|
||||
|
||||
void I2cBusAccessor::ResumePowerBus() {
|
||||
/* Check that state is valid. */
|
||||
AMS_ASSERT(this->state == State::PowerBusSuspended);
|
||||
AMS_ASSERT(m_state == State::PowerBusSuspended);
|
||||
|
||||
/* Acquire exclusive access. */
|
||||
std::scoped_lock lk(this->user_count_mutex);
|
||||
std::scoped_lock lk(m_user_count_mutex);
|
||||
|
||||
/* If we need to, enable clock/voltage appropriately. */
|
||||
if (this->is_power_bus && this->user_count > 0) {
|
||||
if (m_is_power_bus && m_user_count > 0) {
|
||||
/* Execute initial config, which will enable clock as relevant. */
|
||||
this->ExecuteInitialConfig();
|
||||
}
|
||||
|
||||
/* Update state. */
|
||||
this->state = State::Suspended;
|
||||
m_state = State::Suspended;
|
||||
}
|
||||
|
||||
Result I2cBusAccessor::TryOpenRegulatorSession() {
|
||||
/* Ensure we track the session. */
|
||||
this->has_regulator_session = true;
|
||||
auto s_guard = SCOPE_GUARD { this->has_regulator_session = false; };
|
||||
m_has_regulator_session = true;
|
||||
auto s_guard = SCOPE_GUARD { m_has_regulator_session = false; };
|
||||
|
||||
/* Try to open the session. */
|
||||
R_TRY_CATCH(regulator::OpenSession(std::addressof(this->regulator_session), this->device_code)) {
|
||||
R_TRY_CATCH(regulator::OpenSession(std::addressof(m_regulator_session), m_device_code)) {
|
||||
R_CATCH(ddsf::ResultDeviceCodeNotFound) {
|
||||
/* It's okay if the device isn't found, but we don't have a session if so. */
|
||||
this->has_regulator_session = false;
|
||||
m_has_regulator_session = false;
|
||||
}
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
@@ -325,13 +325,13 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
|
||||
void I2cBusAccessor::ExecuteInitialConfig() {
|
||||
/* Lock exclusive access to registers. */
|
||||
std::scoped_lock lk(this->register_mutex);
|
||||
std::scoped_lock lk(m_register_mutex);
|
||||
|
||||
/* Reset the controller. */
|
||||
this->ResetController();
|
||||
|
||||
/* Set clock registers. */
|
||||
this->SetClockRegisters(this->speed_mode);
|
||||
this->SetClockRegisters(m_speed_mode);
|
||||
|
||||
/* Set packet mode registers. */
|
||||
this->SetPacketModeRegisters();
|
||||
@@ -342,20 +342,20 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
|
||||
Result I2cBusAccessor::Send(const u8 *src, size_t src_size, TransactionOption option, u16 slave_address, AddressingMode addressing_mode) {
|
||||
/* Acquire exclusive access to the registers. */
|
||||
std::scoped_lock lk(this->register_mutex);
|
||||
std::scoped_lock lk(m_register_mutex);
|
||||
|
||||
/* Configure interrupt mask, clear interrupt status. */
|
||||
reg::Write(this->registers->interrupt_mask_register, I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_TFIFO_DATA_REQ_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_ARB_LOST_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_NOACK_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_PACKET_XFER_COMPLETE_INT_EN, ENABLE));
|
||||
reg::Write(m_registers->interrupt_mask_register, I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_TFIFO_DATA_REQ_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_ARB_LOST_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_NOACK_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_PACKET_XFER_COMPLETE_INT_EN, ENABLE));
|
||||
|
||||
reg::Write(this->registers->interrupt_status_register, I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_ARB_LOST, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_NOACK, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_RFIFO_UNF, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_TFIFO_OVF, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_PACKET_XFER_COMPLETE, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_ALL_PACKETS_XFER_COMPLETE, SET));
|
||||
reg::Write(m_registers->interrupt_status_register, I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_ARB_LOST, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_NOACK, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_RFIFO_UNF, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_TFIFO_OVF, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_PACKET_XFER_COMPLETE, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_ALL_PACKETS_XFER_COMPLETE, SET));
|
||||
|
||||
/* Write the header. */
|
||||
this->WriteHeader(Xfer_Write, src_size, option, slave_address, addressing_mode);
|
||||
@@ -366,7 +366,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
|
||||
while (true) {
|
||||
/* Get the number of empty bytes in the fifo status. */
|
||||
const u32 empty = reg::GetValue(this->registers->fifo_status, I2C_REG_BITS_MASK(FIFO_STATUS_TX_FIFO_EMPTY_CNT));
|
||||
const u32 empty = reg::GetValue(m_registers->fifo_status, I2C_REG_BITS_MASK(FIFO_STATUS_TX_FIFO_EMPTY_CNT));
|
||||
|
||||
/* Write up to (empty) bytes to the fifo. */
|
||||
for (u32 i = 0; remaining > 0 && i < empty; ++i) {
|
||||
@@ -379,7 +379,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
}
|
||||
|
||||
/* Write the data word. */
|
||||
reg::Write(this->registers->tx_packet_fifo, word);
|
||||
reg::Write(m_registers->tx_packet_fifo, word);
|
||||
|
||||
/* Advance. */
|
||||
cur += cur_bytes;
|
||||
@@ -392,13 +392,13 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
}
|
||||
|
||||
/* Wait for our current data to send. */
|
||||
os::ClearInterruptEvent(std::addressof(this->interrupt_event));
|
||||
if (!os::TimedWaitInterruptEvent(std::addressof(this->interrupt_event), Timeout)) {
|
||||
os::ClearInterruptEvent(std::addressof(m_interrupt_event));
|
||||
if (!os::TimedWaitInterruptEvent(std::addressof(m_interrupt_event), Timeout)) {
|
||||
/* We timed out. */
|
||||
this->HandleTransactionError(i2c::ResultBusBusy());
|
||||
|
||||
this->DisableInterruptMask();
|
||||
os::ClearInterruptEvent(std::addressof(this->interrupt_event));
|
||||
os::ClearInterruptEvent(std::addressof(m_interrupt_event));
|
||||
return i2c::ResultTimeout();
|
||||
}
|
||||
|
||||
@@ -407,9 +407,9 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
}
|
||||
|
||||
/* Configure interrupt mask to not care about tfifo data req. */
|
||||
reg::Write(this->registers->interrupt_mask_register, I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_ARB_LOST_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_NOACK_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_PACKET_XFER_COMPLETE_INT_EN, ENABLE));
|
||||
reg::Write(m_registers->interrupt_mask_register, I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_ARB_LOST_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_NOACK_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_PACKET_XFER_COMPLETE_INT_EN, ENABLE));
|
||||
|
||||
/* Wait for the packet transfer to complete. */
|
||||
while (true) {
|
||||
@@ -417,18 +417,18 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
R_TRY(this->CheckAndHandleError());
|
||||
|
||||
/* Check if packet transfer is done. */
|
||||
if (reg::HasValue(this->registers->interrupt_status_register, I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_PACKET_XFER_COMPLETE, SET))) {
|
||||
if (reg::HasValue(m_registers->interrupt_status_register, I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_PACKET_XFER_COMPLETE, SET))) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Wait for our the packet to transfer. */
|
||||
os::ClearInterruptEvent(std::addressof(this->interrupt_event));
|
||||
if (!os::TimedWaitInterruptEvent(std::addressof(this->interrupt_event), Timeout)) {
|
||||
os::ClearInterruptEvent(std::addressof(m_interrupt_event));
|
||||
if (!os::TimedWaitInterruptEvent(std::addressof(m_interrupt_event), Timeout)) {
|
||||
/* We timed out. */
|
||||
this->HandleTransactionError(i2c::ResultBusBusy());
|
||||
|
||||
this->DisableInterruptMask();
|
||||
os::ClearInterruptEvent(std::addressof(this->interrupt_event));
|
||||
os::ClearInterruptEvent(std::addressof(m_interrupt_event));
|
||||
return i2c::ResultTimeout();
|
||||
}
|
||||
}
|
||||
@@ -443,20 +443,20 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
|
||||
Result I2cBusAccessor::Receive(u8 *dst, size_t dst_size, TransactionOption option, u16 slave_address, AddressingMode addressing_mode) {
|
||||
/* Acquire exclusive access to the registers. */
|
||||
std::scoped_lock lk(this->register_mutex);
|
||||
std::scoped_lock lk(m_register_mutex);
|
||||
|
||||
/* Configure interrupt mask, clear interrupt status. */
|
||||
reg::Write(this->registers->interrupt_mask_register, I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_RFIFO_DATA_REQ_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_ARB_LOST_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_NOACK_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_PACKET_XFER_COMPLETE_INT_EN, ENABLE));
|
||||
reg::Write(m_registers->interrupt_mask_register, I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_RFIFO_DATA_REQ_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_ARB_LOST_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_NOACK_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_PACKET_XFER_COMPLETE_INT_EN, ENABLE));
|
||||
|
||||
reg::Write(this->registers->interrupt_status_register, I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_ARB_LOST, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_NOACK, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_RFIFO_UNF, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_TFIFO_OVF, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_PACKET_XFER_COMPLETE, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_ALL_PACKETS_XFER_COMPLETE, SET));
|
||||
reg::Write(m_registers->interrupt_status_register, I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_ARB_LOST, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_NOACK, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_RFIFO_UNF, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_TFIFO_OVF, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_PACKET_XFER_COMPLETE, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_ALL_PACKETS_XFER_COMPLETE, SET));
|
||||
|
||||
/* Write the header. */
|
||||
this->WriteHeader(Xfer_Read, dst_size, option, slave_address, addressing_mode);
|
||||
@@ -467,13 +467,13 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
|
||||
while (remaining > 0) {
|
||||
/* Wait for data to come in. */
|
||||
os::ClearInterruptEvent(std::addressof(this->interrupt_event));
|
||||
if (!os::TimedWaitInterruptEvent(std::addressof(this->interrupt_event), Timeout)) {
|
||||
os::ClearInterruptEvent(std::addressof(m_interrupt_event));
|
||||
if (!os::TimedWaitInterruptEvent(std::addressof(m_interrupt_event), Timeout)) {
|
||||
/* We timed out. */
|
||||
this->HandleTransactionError(i2c::ResultBusBusy());
|
||||
|
||||
this->DisableInterruptMask();
|
||||
os::ClearInterruptEvent(std::addressof(this->interrupt_event));
|
||||
os::ClearInterruptEvent(std::addressof(m_interrupt_event));
|
||||
return i2c::ResultTimeout();
|
||||
}
|
||||
|
||||
@@ -481,7 +481,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
R_TRY(this->CheckAndHandleError());
|
||||
|
||||
/* Get the number of full bytes in the fifo status. */
|
||||
const u32 full = reg::GetValue(this->registers->fifo_status, I2C_REG_BITS_MASK(FIFO_STATUS_RX_FIFO_FULL_CNT));
|
||||
const u32 full = reg::GetValue(m_registers->fifo_status, I2C_REG_BITS_MASK(FIFO_STATUS_RX_FIFO_FULL_CNT));
|
||||
|
||||
/* Determine how many words we can read. */
|
||||
const size_t cur_words = std::min(util::DivideUp(remaining, sizeof(u32)), static_cast<size_t>(full));
|
||||
@@ -489,7 +489,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
/* Read the correct number of words from the fifo. */
|
||||
for (size_t i = 0; i < cur_words; ++i) {
|
||||
/* Read the word from the fifo. */
|
||||
const u32 word = reg::Read(this->registers->rx_fifo);
|
||||
const u32 word = reg::Read(m_registers->rx_fifo);
|
||||
|
||||
/* Copy bytes from the word. */
|
||||
const size_t cur_bytes = std::min(remaining, sizeof(u32));
|
||||
@@ -512,41 +512,41 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
const bool is_read = xfer == Xfer_Read;
|
||||
const bool is_7_bit = addressing_mode == AddressingMode_SevenBit;
|
||||
const bool is_stop = (option & TransactionOption_StopCondition) != 0;
|
||||
const bool is_hs = this->speed_mode == SpeedMode_HighSpeed;
|
||||
const bool is_hs = m_speed_mode == SpeedMode_HighSpeed;
|
||||
const u32 slave_addr = ((static_cast<u32>(slave_address) & 0x7F) << 1) | (is_read ? 1 : 0);
|
||||
|
||||
/* Flush fifos. */
|
||||
this->FlushFifos();
|
||||
|
||||
/* Enqueue the first header word. */
|
||||
reg::Write(this->registers->tx_packet_fifo, IO_PACKET_BITS_ENUM (HEADER_WORD0_PROT_HDR_SZ, 1_WORD),
|
||||
IO_PACKET_BITS_VALUE(HEADER_WORD0_PKT_ID, 0),
|
||||
IO_PACKET_BITS_VALUE(HEADER_WORD0_CONTROLLER_ID, 0),
|
||||
IO_PACKET_BITS_ENUM (HEADER_WORD0_PROTOCOL, I2C),
|
||||
IO_PACKET_BITS_ENUM (HEADER_WORD0_PKT_TYPE, REQUEST));
|
||||
reg::Write(m_registers->tx_packet_fifo, IO_PACKET_BITS_ENUM (HEADER_WORD0_PROT_HDR_SZ, 1_WORD),
|
||||
IO_PACKET_BITS_VALUE(HEADER_WORD0_PKT_ID, 0),
|
||||
IO_PACKET_BITS_VALUE(HEADER_WORD0_CONTROLLER_ID, 0),
|
||||
IO_PACKET_BITS_ENUM (HEADER_WORD0_PROTOCOL, I2C),
|
||||
IO_PACKET_BITS_ENUM (HEADER_WORD0_PKT_TYPE, REQUEST));
|
||||
|
||||
/* Enqueue the second header word. */
|
||||
reg::Write(this->registers->tx_packet_fifo, IO_PACKET_BITS_VALUE(HEADER_WORD1_PAYLOAD_SIZE, static_cast<u32>(size - 1)));
|
||||
reg::Write(m_registers->tx_packet_fifo, IO_PACKET_BITS_VALUE(HEADER_WORD1_PAYLOAD_SIZE, static_cast<u32>(size - 1)));
|
||||
|
||||
/* Enqueue the protocol header word. */
|
||||
reg::Write(this->registers->tx_packet_fifo, IO_PACKET_BITS_ENUM_SEL(PROTOCOL_HEADER_HS_MODE, is_hs, ENABLE, DISABLE),
|
||||
IO_PACKET_BITS_ENUM (PROTOCOL_HEADER_CONTINUE_ON_NACK, DISABLE),
|
||||
IO_PACKET_BITS_ENUM (PROTOCOL_HEADER_SEND_START_BYTE, DISABLE),
|
||||
IO_PACKET_BITS_ENUM_SEL(PROTOCOL_HEADER_READ_WRITE, is_read, READ, WRITE),
|
||||
IO_PACKET_BITS_ENUM_SEL(PROTOCOL_HEADER_ADDRESS_MODE, is_7_bit, SEVEN_BIT, TEN_BIT),
|
||||
IO_PACKET_BITS_ENUM (PROTOCOL_HEADER_IE, ENABLE),
|
||||
IO_PACKET_BITS_ENUM_SEL(PROTOCOL_HEADER_REPEAT_START_STOP, is_stop, STOP_CONDITION, REPEAT_START_CONDITION),
|
||||
IO_PACKET_BITS_ENUM (PROTOCOL_HEADER_CONTINUE_XFER, USE_REPEAT_START_TOP),
|
||||
IO_PACKET_BITS_VALUE (PROTOCOL_HEADER_HS_MASTER_ADDR, 0),
|
||||
IO_PACKET_BITS_VALUE (PROTOCOL_HEADER_SLAVE_ADDR, slave_addr));
|
||||
reg::Write(m_registers->tx_packet_fifo, IO_PACKET_BITS_ENUM_SEL(PROTOCOL_HEADER_HS_MODE, is_hs, ENABLE, DISABLE),
|
||||
IO_PACKET_BITS_ENUM (PROTOCOL_HEADER_CONTINUE_ON_NACK, DISABLE),
|
||||
IO_PACKET_BITS_ENUM (PROTOCOL_HEADER_SEND_START_BYTE, DISABLE),
|
||||
IO_PACKET_BITS_ENUM_SEL(PROTOCOL_HEADER_READ_WRITE, is_read, READ, WRITE),
|
||||
IO_PACKET_BITS_ENUM_SEL(PROTOCOL_HEADER_ADDRESS_MODE, is_7_bit, SEVEN_BIT, TEN_BIT),
|
||||
IO_PACKET_BITS_ENUM (PROTOCOL_HEADER_IE, ENABLE),
|
||||
IO_PACKET_BITS_ENUM_SEL(PROTOCOL_HEADER_REPEAT_START_STOP, is_stop, STOP_CONDITION, REPEAT_START_CONDITION),
|
||||
IO_PACKET_BITS_ENUM (PROTOCOL_HEADER_CONTINUE_XFER, USE_REPEAT_START_TOP),
|
||||
IO_PACKET_BITS_VALUE (PROTOCOL_HEADER_HS_MASTER_ADDR, 0),
|
||||
IO_PACKET_BITS_VALUE (PROTOCOL_HEADER_SLAVE_ADDR, slave_addr));
|
||||
}
|
||||
|
||||
void I2cBusAccessor::ResetController() const {
|
||||
/* Reset the controller. */
|
||||
if (!this->is_power_bus) {
|
||||
if (!m_is_power_bus) {
|
||||
/* Open a clkrst session. */
|
||||
clkrst::ClkRstSession clkrst_session;
|
||||
R_ABORT_UNLESS(clkrst::OpenSession(std::addressof(clkrst_session), this->device_code));
|
||||
R_ABORT_UNLESS(clkrst::OpenSession(std::addressof(clkrst_session), m_device_code));
|
||||
ON_SCOPE_EXIT { clkrst::CloseSession(std::addressof(clkrst_session)); };
|
||||
|
||||
/* Reset the controller, setting clock rate to 408 MHz / 5 (to account for clock divisor). */
|
||||
@@ -573,17 +573,17 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
this->ResetController();
|
||||
|
||||
/* Configure the sclk threshold for bus clear config. */
|
||||
reg::Write(this->registers->bus_clear_config, I2C_REG_BITS_VALUE(BUS_CLEAR_CONFIG_BC_SCLK_THRESHOLD, 9));
|
||||
reg::Write(m_registers->bus_clear_config, I2C_REG_BITS_VALUE(BUS_CLEAR_CONFIG_BC_SCLK_THRESHOLD, 9));
|
||||
|
||||
/* Set stop cond and terminate in bus clear config. */
|
||||
reg::ReadWrite(this->registers->bus_clear_config, I2C_REG_BITS_ENUM(BUS_CLEAR_CONFIG_BC_STOP_COND, STOP));
|
||||
reg::ReadWrite(this->registers->bus_clear_config, I2C_REG_BITS_ENUM(BUS_CLEAR_CONFIG_BC_TERMINATE, IMMEDIATE));
|
||||
reg::ReadWrite(m_registers->bus_clear_config, I2C_REG_BITS_ENUM(BUS_CLEAR_CONFIG_BC_STOP_COND, STOP));
|
||||
reg::ReadWrite(m_registers->bus_clear_config, I2C_REG_BITS_ENUM(BUS_CLEAR_CONFIG_BC_TERMINATE, IMMEDIATE));
|
||||
|
||||
/* Set master config load, busy loop up to 1ms for it to take. */
|
||||
reg::ReadWrite(this->registers->config_load, I2C_REG_BITS_ENUM(CONFIG_LOAD_MSTR_CONFIG_LOAD, ENABLE));
|
||||
reg::ReadWrite(m_registers->config_load, I2C_REG_BITS_ENUM(CONFIG_LOAD_MSTR_CONFIG_LOAD, ENABLE));
|
||||
|
||||
const os::Tick start_tick_a = os::GetSystemTick();
|
||||
while (reg::HasValue(this->registers->config_load, I2C_REG_BITS_ENUM(CONFIG_LOAD_MSTR_CONFIG_LOAD, ENABLE))) {
|
||||
while (reg::HasValue(m_registers->config_load, I2C_REG_BITS_ENUM(CONFIG_LOAD_MSTR_CONFIG_LOAD, ENABLE))) {
|
||||
if ((os::GetSystemTick() - start_tick_a).ToTimeSpan().GetMicroSeconds() > BusyLoopMicroSeconds) {
|
||||
need_retry = true;
|
||||
break;
|
||||
@@ -595,10 +595,10 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
}
|
||||
|
||||
/* Set bus clear enable, wait up to 1ms for it to take. */
|
||||
reg::ReadWrite(this->registers->bus_clear_config, I2C_REG_BITS_ENUM(BUS_CLEAR_CONFIG_BC_ENABLE, ENABLE));
|
||||
reg::ReadWrite(m_registers->bus_clear_config, I2C_REG_BITS_ENUM(BUS_CLEAR_CONFIG_BC_ENABLE, ENABLE));
|
||||
|
||||
const os::Tick start_tick_b = os::GetSystemTick();
|
||||
while (reg::HasValue(this->registers->bus_clear_config, I2C_REG_BITS_ENUM(BUS_CLEAR_CONFIG_BC_ENABLE, ENABLE))) {
|
||||
while (reg::HasValue(m_registers->bus_clear_config, I2C_REG_BITS_ENUM(BUS_CLEAR_CONFIG_BC_ENABLE, ENABLE))) {
|
||||
if ((os::GetSystemTick() - start_tick_b).ToTimeSpan().GetMicroSeconds() > BusyLoopMicroSeconds) {
|
||||
need_retry = true;
|
||||
break;
|
||||
@@ -611,7 +611,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
|
||||
/* Wait up to 1ms for the bus clear to complete. */
|
||||
const os::Tick start_tick_c = os::GetSystemTick();
|
||||
while (reg::HasValue(this->registers->bus_clear_status, I2C_REG_BITS_ENUM(BUS_CLEAR_STATUS_BC_STATUS, NOT_CLEARED))) {
|
||||
while (reg::HasValue(m_registers->bus_clear_status, I2C_REG_BITS_ENUM(BUS_CLEAR_STATUS_BC_STATUS, NOT_CLEARED))) {
|
||||
if ((os::GetSystemTick() - start_tick_c).ToTimeSpan().GetMicroSeconds() > BusyLoopMicroSeconds) {
|
||||
need_retry = true;
|
||||
break;
|
||||
@@ -629,7 +629,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
u32 t_high, t_low, clk_div, debounce, src_div;
|
||||
bool high_speed = false;
|
||||
|
||||
if (this->is_power_bus) {
|
||||
if (m_is_power_bus) {
|
||||
t_high = 0x02;
|
||||
t_low = 0x04;
|
||||
clk_div = 0x05;
|
||||
@@ -672,26 +672,26 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
|
||||
/* Write the clock divisors. */
|
||||
if (high_speed) {
|
||||
reg::Write(this->registers->hs_interface_timing_0, I2C_REG_BITS_VALUE(HS_INTERFACE_TIMING_0_HS_THIGH, t_high),
|
||||
I2C_REG_BITS_VALUE(HS_INTERFACE_TIMING_0_HS_TLOW, t_low));
|
||||
reg::Write(m_registers->hs_interface_timing_0, I2C_REG_BITS_VALUE(HS_INTERFACE_TIMING_0_HS_THIGH, t_high),
|
||||
I2C_REG_BITS_VALUE(HS_INTERFACE_TIMING_0_HS_TLOW, t_low));
|
||||
|
||||
reg::Write(this->registers->clk_divisor_register, I2C_REG_BITS_VALUE(CLK_DIVISOR_REGISTER_HSMODE, clk_div));
|
||||
reg::Write(m_registers->clk_divisor_register, I2C_REG_BITS_VALUE(CLK_DIVISOR_REGISTER_HSMODE, clk_div));
|
||||
} else {
|
||||
reg::Write(this->registers->interface_timing_0, I2C_REG_BITS_VALUE(INTERFACE_TIMING_0_THIGH, t_high),
|
||||
I2C_REG_BITS_VALUE(INTERFACE_TIMING_0_TLOW, t_low));
|
||||
reg::Write(m_registers->interface_timing_0, I2C_REG_BITS_VALUE(INTERFACE_TIMING_0_THIGH, t_high),
|
||||
I2C_REG_BITS_VALUE(INTERFACE_TIMING_0_TLOW, t_low));
|
||||
|
||||
reg::Write(this->registers->clk_divisor_register, I2C_REG_BITS_VALUE(CLK_DIVISOR_REGISTER_STD_FAST_MODE, clk_div));
|
||||
reg::Write(m_registers->clk_divisor_register, I2C_REG_BITS_VALUE(CLK_DIVISOR_REGISTER_STD_FAST_MODE, clk_div));
|
||||
}
|
||||
|
||||
/* Configure debounce. */
|
||||
reg::Write(this->registers->cnfg, I2C_REG_BITS_VALUE(I2C_CNFG_DEBOUNCE_CNT, debounce));
|
||||
reg::Read(this->registers->cnfg);
|
||||
reg::Write(m_registers->cnfg, I2C_REG_BITS_VALUE(I2C_CNFG_DEBOUNCE_CNT, debounce));
|
||||
reg::Read(m_registers->cnfg);
|
||||
|
||||
/* Set the clock rate, if we should. */
|
||||
if (!this->is_power_bus) {
|
||||
if (!m_is_power_bus) {
|
||||
/* Open a clkrst session. */
|
||||
clkrst::ClkRstSession clkrst_session;
|
||||
R_ABORT_UNLESS(clkrst::OpenSession(std::addressof(clkrst_session), this->device_code));
|
||||
R_ABORT_UNLESS(clkrst::OpenSession(std::addressof(clkrst_session), m_device_code));
|
||||
ON_SCOPE_EXIT { clkrst::CloseSession(std::addressof(clkrst_session)); };
|
||||
|
||||
/* Reset the controller, setting clock rate to 408 MHz / (src_div + 1). */
|
||||
@@ -704,26 +704,26 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
|
||||
void I2cBusAccessor::SetPacketModeRegisters() {
|
||||
/* Set packet mode enable. */
|
||||
reg::ReadWrite(this->registers->cnfg, I2C_REG_BITS_ENUM(I2C_CNFG_PACKET_MODE_EN, GO));
|
||||
reg::ReadWrite(m_registers->cnfg, I2C_REG_BITS_ENUM(I2C_CNFG_PACKET_MODE_EN, GO));
|
||||
|
||||
/* Set master config load. */
|
||||
reg::ReadWrite(this->registers->config_load, I2C_REG_BITS_ENUM(CONFIG_LOAD_MSTR_CONFIG_LOAD, ENABLE));
|
||||
reg::ReadWrite(m_registers->config_load, I2C_REG_BITS_ENUM(CONFIG_LOAD_MSTR_CONFIG_LOAD, ENABLE));
|
||||
|
||||
/* Set tx/fifo triggers to default (maximum values). */
|
||||
reg::Write(this->registers->fifo_control, I2C_REG_BITS_VALUE(FIFO_CONTROL_RX_FIFO_TRIG, 7),
|
||||
I2C_REG_BITS_VALUE(FIFO_CONTROL_TX_FIFO_TRIG, 7));
|
||||
reg::Write(m_registers->fifo_control, I2C_REG_BITS_VALUE(FIFO_CONTROL_RX_FIFO_TRIG, 7),
|
||||
I2C_REG_BITS_VALUE(FIFO_CONTROL_TX_FIFO_TRIG, 7));
|
||||
}
|
||||
|
||||
Result I2cBusAccessor::FlushFifos() {
|
||||
/* Flush the fifo. */
|
||||
reg::Write(this->registers->fifo_control, I2C_REG_BITS_VALUE(FIFO_CONTROL_RX_FIFO_TRIG, 7),
|
||||
I2C_REG_BITS_VALUE(FIFO_CONTROL_TX_FIFO_TRIG, 7),
|
||||
I2C_REG_BITS_ENUM (FIFO_CONTROL_RX_FIFO_FLUSH, SET),
|
||||
I2C_REG_BITS_ENUM (FIFO_CONTROL_TX_FIFO_FLUSH, SET));
|
||||
reg::Write(m_registers->fifo_control, I2C_REG_BITS_VALUE(FIFO_CONTROL_RX_FIFO_TRIG, 7),
|
||||
I2C_REG_BITS_VALUE(FIFO_CONTROL_TX_FIFO_TRIG, 7),
|
||||
I2C_REG_BITS_ENUM (FIFO_CONTROL_RX_FIFO_FLUSH, SET),
|
||||
I2C_REG_BITS_ENUM (FIFO_CONTROL_TX_FIFO_FLUSH, SET));
|
||||
|
||||
/* Wait up to 5 ms for the flush to complete. */
|
||||
int count = 0;
|
||||
while (!reg::HasValue(this->registers->fifo_control, I2C_REG_BITS_ENUM(FIFO_CONTROL_FIFO_FLUSH, RX_UNSET_TX_UNSET))) {
|
||||
while (!reg::HasValue(m_registers->fifo_control, I2C_REG_BITS_ENUM(FIFO_CONTROL_FIFO_FLUSH, RX_UNSET_TX_UNSET))) {
|
||||
R_UNLESS((++count < 5), i2c::ResultBusBusy());
|
||||
os::SleepThread(TimeSpan::FromMilliSeconds(1));
|
||||
}
|
||||
@@ -733,8 +733,8 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
|
||||
Result I2cBusAccessor::GetTransactionResult() const {
|
||||
/* Get packet status/interrupt status. */
|
||||
volatile u32 packet_status = reg::Read(this->registers->packet_transfer_status);
|
||||
volatile u32 interrupt_status = reg::Read(this->registers->interrupt_status_register);
|
||||
volatile u32 packet_status = reg::Read(m_registers->packet_transfer_status);
|
||||
volatile u32 interrupt_status = reg::Read(m_registers->interrupt_status_register);
|
||||
|
||||
/* Check for ack. */
|
||||
R_UNLESS(reg::HasValue(packet_status, I2C_REG_BITS_ENUM(PACKET_TRANSFER_STATUS_NOACK_FOR_DATA, UNSET)), i2c::ResultNoAck());
|
||||
@@ -759,7 +759,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
this->ResetController();
|
||||
|
||||
/* Set clock registers. */
|
||||
this->SetClockRegisters(this->speed_mode);
|
||||
this->SetClockRegisters(m_speed_mode);
|
||||
|
||||
/* Set packet mode registers. */
|
||||
this->SetPacketModeRegisters();
|
||||
|
||||
@@ -37,31 +37,31 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
Xfer_Read = 1,
|
||||
};
|
||||
private:
|
||||
volatile I2cRegisters *registers;
|
||||
SpeedMode speed_mode;
|
||||
os::InterruptEventType interrupt_event;
|
||||
int user_count;
|
||||
os::SdkMutex user_count_mutex;
|
||||
os::SdkMutex register_mutex;
|
||||
regulator::RegulatorSession regulator_session;
|
||||
bool has_regulator_session;
|
||||
State state;
|
||||
os::SdkMutex transaction_order_mutex;
|
||||
bool is_power_bus;
|
||||
dd::PhysicalAddress registers_phys_addr;
|
||||
size_t registers_size;
|
||||
os::InterruptName interrupt_name;
|
||||
DeviceCode device_code;
|
||||
util::IntrusiveListNode bus_accessor_list_node;
|
||||
volatile I2cRegisters *m_registers;
|
||||
SpeedMode m_speed_mode;
|
||||
os::InterruptEventType m_interrupt_event;
|
||||
int m_user_count;
|
||||
os::SdkMutex m_user_count_mutex;
|
||||
os::SdkMutex m_register_mutex;
|
||||
regulator::RegulatorSession m_regulator_session;
|
||||
bool m_has_regulator_session;
|
||||
State m_state;
|
||||
os::SdkMutex m_transaction_order_mutex;
|
||||
bool m_is_power_bus;
|
||||
dd::PhysicalAddress m_registers_phys_addr;
|
||||
size_t m_registers_size;
|
||||
os::InterruptName m_interrupt_name;
|
||||
DeviceCode m_device_code;
|
||||
util::IntrusiveListNode m_bus_accessor_list_node;
|
||||
public:
|
||||
using BusAccessorListTraits = util::IntrusiveListMemberTraitsDeferredAssert<&I2cBusAccessor::bus_accessor_list_node>;
|
||||
using BusAccessorListTraits = util::IntrusiveListMemberTraitsDeferredAssert<&I2cBusAccessor::m_bus_accessor_list_node>;
|
||||
using BusAccessorList = typename BusAccessorListTraits::ListType;
|
||||
friend class util::IntrusiveList<I2cBusAccessor, util::IntrusiveListMemberTraitsDeferredAssert<&I2cBusAccessor::bus_accessor_list_node>>;
|
||||
friend class util::IntrusiveList<I2cBusAccessor, util::IntrusiveListMemberTraitsDeferredAssert<&I2cBusAccessor::m_bus_accessor_list_node>>;
|
||||
public:
|
||||
I2cBusAccessor()
|
||||
: registers(nullptr), speed_mode(SpeedMode_Fast), user_count(0), user_count_mutex(),
|
||||
register_mutex(), has_regulator_session(false), state(State::NotInitialized), transaction_order_mutex(),
|
||||
is_power_bus(false), registers_phys_addr(0), registers_size(0), interrupt_name(), device_code(-1), bus_accessor_list_node()
|
||||
: m_registers(nullptr), m_speed_mode(SpeedMode_Fast), m_user_count(0), m_user_count_mutex(),
|
||||
m_register_mutex(), m_has_regulator_session(false), m_state(State::NotInitialized), m_transaction_order_mutex(),
|
||||
m_is_power_bus(false), m_registers_phys_addr(0), m_registers_size(0), m_interrupt_name(), m_device_code(-1), m_bus_accessor_list_node()
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
@@ -69,10 +69,10 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
void Initialize(dd::PhysicalAddress reg_paddr, size_t reg_size, os::InterruptName intr, bool pb, SpeedMode sm);
|
||||
void RegisterDeviceCode(DeviceCode device_code);
|
||||
|
||||
SpeedMode GetSpeedMode() const { return this->speed_mode; }
|
||||
dd::PhysicalAddress GetRegistersPhysicalAddress() const { return this->registers_phys_addr; }
|
||||
size_t GetRegistersSize() const { return this->registers_size; }
|
||||
os::InterruptName GetInterruptName() const { return this->interrupt_name; }
|
||||
SpeedMode GetSpeedMode() const { return m_speed_mode; }
|
||||
dd::PhysicalAddress GetRegistersPhysicalAddress() const { return m_registers_phys_addr; }
|
||||
size_t GetRegistersSize() const { return m_registers_size; }
|
||||
os::InterruptName GetInterruptName() const { return m_interrupt_name; }
|
||||
private:
|
||||
Result TryOpenRegulatorSession();
|
||||
|
||||
@@ -94,8 +94,8 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
void HandleTransactionError(Result result);
|
||||
|
||||
void DisableInterruptMask() {
|
||||
reg::Write(this->registers->interrupt_mask_register, 0);
|
||||
reg::Read(this->registers->interrupt_mask_register);
|
||||
reg::Write(m_registers->interrupt_mask_register, 0);
|
||||
reg::Read(m_registers->interrupt_mask_register);
|
||||
}
|
||||
|
||||
Result CheckAndHandleError() {
|
||||
@@ -103,7 +103,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
this->HandleTransactionError(result);
|
||||
if (R_FAILED(result)) {
|
||||
this->DisableInterruptMask();
|
||||
os::ClearInterruptEvent(std::addressof(this->interrupt_event));
|
||||
os::ClearInterruptEvent(std::addressof(m_interrupt_event));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
virtual Result Receive(void *dst, size_t dst_size, I2cDeviceProperty *device, TransactionOption option) override;
|
||||
|
||||
virtual os::SdkMutex &GetTransactionOrderMutex() override {
|
||||
return this->transaction_order_mutex;
|
||||
return m_transaction_order_mutex;
|
||||
}
|
||||
|
||||
virtual void SuspendBus() override;
|
||||
@@ -130,7 +130,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
virtual void ResumePowerBus() override;
|
||||
|
||||
virtual const DeviceCode &GetDeviceCode() const override {
|
||||
return this->device_code;
|
||||
return m_device_code;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -25,48 +25,48 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
private:
|
||||
using T = typename ListType::value_type;
|
||||
private:
|
||||
ams::MemoryResource *memory_resource;
|
||||
ListType list;
|
||||
mutable os::SdkMutex list_lock;
|
||||
ams::MemoryResource *m_memory_resource;
|
||||
ListType m_list;
|
||||
mutable os::SdkMutex m_list_lock;
|
||||
public:
|
||||
IAllocator(ams::MemoryResource *mr) : memory_resource(mr), list(), list_lock() { /* ... */ }
|
||||
IAllocator(ams::MemoryResource *mr) : m_memory_resource(mr), m_list(), m_list_lock() { /* ... */ }
|
||||
|
||||
~IAllocator() {
|
||||
std::scoped_lock lk(this->list_lock);
|
||||
std::scoped_lock lk(m_list_lock);
|
||||
|
||||
/* Remove all entries. */
|
||||
auto it = this->list.begin();
|
||||
while (it != this->list.end()) {
|
||||
auto it = m_list.begin();
|
||||
while (it != m_list.end()) {
|
||||
T *obj = std::addressof(*it);
|
||||
it = this->list.erase(it);
|
||||
it = m_list.erase(it);
|
||||
|
||||
std::destroy_at(obj);
|
||||
this->memory_resource->Deallocate(obj, sizeof(T));
|
||||
m_memory_resource->Deallocate(obj, sizeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ...Args>
|
||||
T *Allocate(Args &&...args) {
|
||||
std::scoped_lock lk(this->list_lock);
|
||||
std::scoped_lock lk(m_list_lock);
|
||||
|
||||
/* Allocate space for the object. */
|
||||
void *storage = this->memory_resource->Allocate(sizeof(T), alignof(T));
|
||||
void *storage = m_memory_resource->Allocate(sizeof(T), alignof(T));
|
||||
AMS_ABORT_UNLESS(storage != nullptr);
|
||||
|
||||
/* Construct the object. */
|
||||
T *t = std::construct_at(static_cast<T *>(storage), std::forward<Args>(args)...);
|
||||
|
||||
/* Link the object into our list. */
|
||||
this->list.push_back(*t);
|
||||
m_list.push_back(*t);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
T *Find(F f) {
|
||||
std::scoped_lock lk(this->list_lock);
|
||||
std::scoped_lock lk(m_list_lock);
|
||||
|
||||
for (T &it : this->list) {
|
||||
for (T &it : m_list) {
|
||||
if (f(static_cast<const T &>(it))) {
|
||||
return std::addressof(it);
|
||||
}
|
||||
|
||||
@@ -144,8 +144,8 @@ namespace ams::i2c::driver::impl {
|
||||
/* If we timed out, retry up to our max retry count. */
|
||||
R_TRY_CATCH(result) {
|
||||
R_CATCH(i2c::ResultTimeout) {
|
||||
if ((++retry_count) <= this->max_retry_count) {
|
||||
os::SleepThread(this->retry_interval);
|
||||
if ((++retry_count) <= m_max_retry_count) {
|
||||
os::SleepThread(m_retry_interval);
|
||||
continue;
|
||||
}
|
||||
return i2c::ResultBusBusy();
|
||||
@@ -197,8 +197,8 @@ namespace ams::i2c::driver::impl {
|
||||
}
|
||||
|
||||
Result I2cSessionImpl::SetRetryPolicy(int mr, int interval_us) {
|
||||
this->max_retry_count = mr;
|
||||
this->retry_interval = TimeSpan::FromMicroSeconds(interval_us);
|
||||
m_max_retry_count = mr;
|
||||
m_retry_interval = TimeSpan::FromMicroSeconds(interval_us);
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
namespace ams::i2c {
|
||||
|
||||
Result CommandListFormatter::IsEnqueueAble(size_t sz) const {
|
||||
R_UNLESS(this->command_list_length - this->current_index >= sz, i2c::ResultCommandListFull());
|
||||
R_UNLESS(m_command_list_length - m_current_index >= sz, i2c::ResultCommandListFull());
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
@@ -29,11 +29,11 @@ namespace ams::i2c {
|
||||
R_TRY(this->IsEnqueueAble(CommandLength));
|
||||
|
||||
/* Get the command list. */
|
||||
util::BitPack8 *cmd_list = static_cast<util::BitPack8 *>(this->command_list);
|
||||
util::BitPack8 *cmd_list = static_cast<util::BitPack8 *>(m_command_list);
|
||||
|
||||
/* Get references to the header. */
|
||||
auto &header0 = cmd_list[this->current_index++];
|
||||
auto &header1 = cmd_list[this->current_index++];
|
||||
auto &header0 = cmd_list[m_current_index++];
|
||||
auto &header1 = cmd_list[m_current_index++];
|
||||
|
||||
/* Set the header. */
|
||||
header0 = {};
|
||||
@@ -53,11 +53,11 @@ namespace ams::i2c {
|
||||
R_TRY(this->IsEnqueueAble(CommandLength + size));
|
||||
|
||||
/* Get the command list. */
|
||||
util::BitPack8 *cmd_list = static_cast<util::BitPack8 *>(this->command_list);
|
||||
util::BitPack8 *cmd_list = static_cast<util::BitPack8 *>(m_command_list);
|
||||
|
||||
/* Get references to the header. */
|
||||
auto &header0 = cmd_list[this->current_index++];
|
||||
auto &header1 = cmd_list[this->current_index++];
|
||||
auto &header0 = cmd_list[m_current_index++];
|
||||
auto &header1 = cmd_list[m_current_index++];
|
||||
|
||||
/* Set the header. */
|
||||
header0 = {};
|
||||
@@ -69,8 +69,8 @@ namespace ams::i2c {
|
||||
header1.Set<impl::SendCommandFormat::Size>(size);
|
||||
|
||||
/* Copy the data we're sending. */
|
||||
std::memcpy(cmd_list + this->current_index, src, size);
|
||||
this->current_index += size;
|
||||
std::memcpy(cmd_list + m_current_index, src, size);
|
||||
m_current_index += size;
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -81,11 +81,11 @@ namespace ams::i2c {
|
||||
R_TRY(this->IsEnqueueAble(CommandLength));
|
||||
|
||||
/* Get the command list. */
|
||||
util::BitPack8 *cmd_list = static_cast<util::BitPack8 *>(this->command_list);
|
||||
util::BitPack8 *cmd_list = static_cast<util::BitPack8 *>(m_command_list);
|
||||
|
||||
/* Get references to the header. */
|
||||
auto &header0 = cmd_list[this->current_index++];
|
||||
auto &header1 = cmd_list[this->current_index++];
|
||||
auto &header0 = cmd_list[m_current_index++];
|
||||
auto &header1 = cmd_list[m_current_index++];
|
||||
|
||||
/* Set the header. */
|
||||
header0 = {};
|
||||
|
||||
@@ -19,12 +19,12 @@
|
||||
namespace ams::i2c::server {
|
||||
|
||||
ManagerImpl::ManagerImpl() {
|
||||
this->heap_handle = lmem::CreateExpHeap(this->heap_buffer, sizeof(this->heap_buffer), lmem::CreateOption_None);
|
||||
this->allocator.Attach(this->heap_handle);
|
||||
m_heap_handle = lmem::CreateExpHeap(m_heap_buffer, sizeof(m_heap_buffer), lmem::CreateOption_None);
|
||||
m_allocator.Attach(m_heap_handle);
|
||||
}
|
||||
|
||||
ManagerImpl::~ManagerImpl() {
|
||||
lmem::DestroyExpHeap(this->heap_handle);
|
||||
lmem::DestroyExpHeap(m_heap_handle);
|
||||
}
|
||||
|
||||
Result ManagerImpl::OpenSessionForDev(ams::sf::Out<ams::sf::SharedPointer<i2c::sf::ISession>> out, s32 bus_idx, u16 slave_address, i2c::AddressingMode addressing_mode, i2c::SpeedMode speed_mode) {
|
||||
@@ -51,7 +51,7 @@ namespace ams::i2c::server {
|
||||
|
||||
Result ManagerImpl::OpenSession2(ams::sf::Out<ams::sf::SharedPointer<i2c::sf::ISession>> out, DeviceCode device_code) {
|
||||
/* Allocate a session. */
|
||||
auto session = Factory::CreateSharedEmplaced<i2c::sf::ISession, SessionImpl>(std::addressof(this->allocator), this);
|
||||
auto session = Factory::CreateSharedEmplaced<i2c::sf::ISession, SessionImpl>(std::addressof(m_allocator), this);
|
||||
|
||||
/* Open the session. */
|
||||
R_TRY(session.GetImpl().OpenSession(device_code));
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user