summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Zach Hilman2019-04-28 18:55:56 -0400
committerGravatar Zach Hilman2019-09-30 17:23:26 -0400
commitcb7c96b96a0ad781d5bb4387072d5d0becd74dd7 (patch)
tree2397b6633887e61a6885039acecedd8488e3db96 /src
parentbcat: Implement IDeliveryCacheFileService commands (diff)
downloadyuzu-cb7c96b96a0ad781d5bb4387072d5d0becd74dd7.tar.gz
yuzu-cb7c96b96a0ad781d5bb4387072d5d0becd74dd7.tar.xz
yuzu-cb7c96b96a0ad781d5bb4387072d5d0becd74dd7.zip
bcat: Implement IDeliveryCacheProgressService commands
Used to query completion status and events for the current delivery task.
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/service/bcat/module.cpp131
1 files changed, 131 insertions, 0 deletions
diff --git a/src/core/hle/service/bcat/module.cpp b/src/core/hle/service/bcat/module.cpp
index 25f68ed63..1459fab11 100644
--- a/src/core/hle/service/bcat/module.cpp
+++ b/src/core/hle/service/bcat/module.cpp
@@ -2,13 +2,144 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cctype>
6#include <mbedtls/md5.h>
7#include "backend/boxcat.h"
8#include "common/hex_util.h"
5#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "common/string_util.h"
11#include "core/file_sys/vfs.h"
6#include "core/hle/ipc_helpers.h" 12#include "core/hle/ipc_helpers.h"
13#include "core/hle/kernel/process.h"
14#include "core/hle/kernel/readable_event.h"
15#include "core/hle/kernel/writable_event.h"
16#include "core/hle/service/bcat/backend/backend.h"
7#include "core/hle/service/bcat/bcat.h" 17#include "core/hle/service/bcat/bcat.h"
8#include "core/hle/service/bcat/module.h" 18#include "core/hle/service/bcat/module.h"
19#include "core/hle/service/filesystem/filesystem.h"
20#include "core/settings.h"
9 21
10namespace Service::BCAT { 22namespace Service::BCAT {
11 23
24constexpr ResultCode ERROR_INVALID_ARGUMENT{ErrorModule::BCAT, 1};
25constexpr ResultCode ERROR_FAILED_OPEN_ENTITY{ErrorModule::BCAT, 2};
26constexpr ResultCode ERROR_ENTITY_ALREADY_OPEN{ErrorModule::BCAT, 6};
27constexpr ResultCode ERROR_NO_OPEN_ENTITY{ErrorModule::BCAT, 7};
28
29// The command to clear the delivery cache just calls fs IFileSystem DeleteFile on all of the files
30// and if any of them have a non-zero result it just forwards that result. This is the FS error code
31// for permission denied, which is the closest approximation of this scenario.
32constexpr ResultCode ERROR_FAILED_CLEAR_CACHE{ErrorModule::FS, 6400};
33
34using BCATDigest = std::array<u8, 0x10>;
35
36struct DeliveryCacheProgressImpl {
37 enum class Status : u8 {
38 Incomplete = 0x1,
39 Complete = 0x9,
40 };
41
42 Status status = Status::Incomplete;
43 INSERT_PADDING_BYTES(
44 0x1FF); ///< TODO(DarkLordZach): RE this structure. It just seems to convey info about the
45 ///< progress of the BCAT sync, but for us just setting completion works.
46};
47static_assert(sizeof(DeliveryCacheProgressImpl) == 0x200,
48 "DeliveryCacheProgressImpl has incorrect size.");
49
50namespace {
51
52u64 GetCurrentBuildID() {
53 const auto& id = Core::System::GetInstance().GetCurrentProcessBuildID();
54 u64 out{};
55 std::memcpy(&out, id.data(), sizeof(u64));
56 return out;
57}
58
59// The digest is only used to determine if a file is unique compared to others of the same name.
60// Since the algorithm isn't ever checked in game, MD5 is safe.
61BCATDigest DigestFile(const FileSys::VirtualFile& file) {
62 BCATDigest out{};
63 const auto bytes = file->ReadAllBytes();
64 mbedtls_md5(bytes.data(), bytes.size(), out.data());
65 return out;
66}
67
68// For a name to be valid it must be non-empty, must have a null terminating character as the final
69// char, can only contain numbers, letters, underscores and a hyphen if directory and a period if
70// file.
71bool VerifyNameValidInternal(Kernel::HLERequestContext& ctx, std::array<char, 0x20> name,
72 char match_char) {
73 const auto null_chars = std::count(name.begin(), name.end(), 0);
74 const auto bad_chars = std::count_if(name.begin(), name.end(), [match_char](char c) {
75 return !std::isalnum(static_cast<u8>(c)) && c != '_' && c != match_char && c != '\0';
76 });
77 if (null_chars == 0x20 || null_chars == 0 || bad_chars != 0 || name[0x1F] != '\0') {
78 LOG_ERROR(Service_BCAT, "Name passed was invalid!");
79 IPC::ResponseBuilder rb{ctx, 2};
80 rb.Push(ERROR_INVALID_ARGUMENT);
81 return false;
82 }
83
84 return true;
85}
86
87bool VerifyNameValidDir(Kernel::HLERequestContext& ctx, std::array<char, 0x20> name) {
88 return VerifyNameValidInternal(ctx, name, '-');
89}
90
91bool VerifyNameValidFile(Kernel::HLERequestContext& ctx, std::array<char, 0x20> name) {
92 return VerifyNameValidInternal(ctx, name, '.');
93}
94
95} // Anonymous namespace
96
97using DirectoryName = std::array<char, 0x20>;
98using FileName = std::array<char, 0x20>;
99
100struct DeliveryCacheDirectoryEntry {
101 FileName name;
102 u64 size;
103 BCATDigest digest;
104};
105
106class IDeliveryCacheProgressService final : public ServiceFramework<IDeliveryCacheProgressService> {
107public:
108 IDeliveryCacheProgressService(Kernel::SharedPtr<Kernel::ReadableEvent> event,
109 const DeliveryCacheProgressImpl& impl)
110 : ServiceFramework{"IDeliveryCacheProgressService"}, event(std::move(event)), impl(impl) {
111 // clang-format off
112 static const FunctionInfo functions[] = {
113 {0, &IDeliveryCacheProgressService::GetEvent, "GetEvent"},
114 {1, &IDeliveryCacheProgressService::GetImpl, "GetImpl"},
115 };
116 // clang-format on
117
118 RegisterHandlers(functions);
119 }
120
121private:
122 void GetEvent(Kernel::HLERequestContext& ctx) {
123 LOG_DEBUG(Service_BCAT, "called");
124
125 IPC::ResponseBuilder rb{ctx, 2, 1};
126 rb.Push(RESULT_SUCCESS);
127 rb.PushCopyObjects(event);
128 }
129
130 void GetImpl(Kernel::HLERequestContext& ctx) {
131 LOG_DEBUG(Service_BCAT, "called");
132
133 ctx.WriteBuffer(&impl, sizeof(DeliveryCacheProgressImpl));
134
135 IPC::ResponseBuilder rb{ctx, 2};
136 rb.Push(RESULT_SUCCESS);
137 }
138
139 Kernel::SharedPtr<Kernel::ReadableEvent> event;
140 const DeliveryCacheProgressImpl& impl;
141};
142
12class IBcatService final : public ServiceFramework<IBcatService> { 143class IBcatService final : public ServiceFramework<IBcatService> {
13public: 144public:
14 IBcatService(Backend& backend) : ServiceFramework("IBcatService"), backend(backend) { 145 IBcatService(Backend& backend) : ServiceFramework("IBcatService"), backend(backend) {