A tool for deriving PKG packet encryption keys for ps4 written in c++
| 1 | // SPDX-FileCopyrightText: Copyright 2014 Citra Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | |
| 4 | #include <algorithm> |
| 5 | |
| 6 | #include "common/assert.h" |
| 7 | #include "common/logging/filter.h" |
| 8 | |
| 9 | namespace Common::Log { |
| 10 | namespace { |
| 11 | template <typename It> |
| 12 | Level GetLevelByName(const It begin, const It end) { |
| 13 | for (u8 i = 0; i < static_cast<u8>(Level::Count); ++i) { |
| 14 | const char* level_name = GetLevelName(static_cast<Level>(i)); |
| 15 | if (std::string_view(begin, end).compare(level_name) == 0) { |
| 16 | return static_cast<Level>(i); |
| 17 | } |
| 18 | } |
| 19 | return Level::Count; |
| 20 | } |
| 21 | |
| 22 | template <typename It> |
| 23 | Class GetClassByName(const It begin, const It end) { |
| 24 | for (u8 i = 0; i < static_cast<u8>(Class::Count); ++i) { |
| 25 | const char* level_name = GetLogClassName(static_cast<Class>(i)); |
| 26 | if (std::string_view(begin, end).compare(level_name) == 0) { |
| 27 | return static_cast<Class>(i); |
| 28 | } |
| 29 | } |
| 30 | return Class::Count; |
| 31 | } |
| 32 | |
| 33 | template <typename Iterator> |
| 34 | bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) { |
| 35 | auto level_separator = std::find(begin, end, ':'); |
| 36 | if (level_separator == end) { |
| 37 | LOG_ERROR(Log, "Invalid log filter. Must specify a log level after `:`: {}", |
| 38 | std::string_view(begin, end)); |
| 39 | return false; |
| 40 | } |
| 41 | |
| 42 | const Level level = GetLevelByName(level_separator + 1, end); |
| 43 | if (level == Level::Count) { |
| 44 | LOG_ERROR(Log, "Unknown log level in filter: {}", std::string_view(begin, end)); |
| 45 | return false; |
| 46 | } |
| 47 | |
| 48 | if (std::string_view(begin, level_separator).compare("*") == 0) { |
| 49 | instance.ResetAll(level); |
| 50 | return true; |
| 51 | } |
| 52 | |
| 53 | const Class log_class = GetClassByName(begin, level_separator); |
| 54 | if (log_class == Class::Count) { |
| 55 | LOG_ERROR(Log, "Unknown log class in filter: {}", std::string(begin, end)); |
| 56 | return false; |
| 57 | } |
| 58 | |
| 59 | instance.SetClassLevel(log_class, level); |
| 60 | return true; |
| 61 | } |
| 62 | } // Anonymous namespace |
| 63 | |
| 64 | /// Macro listing all log classes. Code should define CLS and SUB as desired before invoking this. |
| 65 | #define ALL_LOG_CLASSES() \ |
| 66 | CLS(Log) \ |
| 67 | CLS(Common) \ |
| 68 | SUB(Common, Filesystem) \ |
| 69 | SUB(Common, Memory) \ |
| 70 | CLS(Core) \ |
| 71 | SUB(Core, Linker) \ |
| 72 | SUB(Core, Devices) \ |
| 73 | CLS(Config) \ |
| 74 | CLS(Debug) \ |
| 75 | CLS(Kernel) \ |
| 76 | SUB(Kernel, Pthread) \ |
| 77 | SUB(Kernel, Vmm) \ |
| 78 | SUB(Kernel, Fs) \ |
| 79 | SUB(Kernel, Event) \ |
| 80 | SUB(Kernel, Sce) \ |
| 81 | CLS(Lib) \ |
| 82 | SUB(Lib, LibC) \ |
| 83 | SUB(Lib, Kernel) \ |
| 84 | SUB(Lib, Pad) \ |
| 85 | SUB(Lib, GnmDriver) \ |
| 86 | SUB(Lib, SystemService) \ |
| 87 | SUB(Lib, UserService) \ |
| 88 | SUB(Lib, VideoOut) \ |
| 89 | SUB(Lib, CommonDlg) \ |
| 90 | SUB(Lib, MsgDlg) \ |
| 91 | SUB(Lib, AudioOut) \ |
| 92 | SUB(Lib, AudioIn) \ |
| 93 | SUB(Lib, Net) \ |
| 94 | SUB(Lib, NetCtl) \ |
| 95 | SUB(Lib, SaveData) \ |
| 96 | SUB(Lib, SaveDataDialog) \ |
| 97 | SUB(Lib, Http) \ |
| 98 | SUB(Lib, Http2) \ |
| 99 | SUB(Lib, Ssl) \ |
| 100 | SUB(Lib, Ssl2) \ |
| 101 | SUB(Lib, SysModule) \ |
| 102 | SUB(Lib, Move) \ |
| 103 | SUB(Lib, NpCommon) \ |
| 104 | SUB(Lib, NpManager) \ |
| 105 | SUB(Lib, NpScore) \ |
| 106 | SUB(Lib, NpTrophy) \ |
| 107 | SUB(Lib, NpWebApi) \ |
| 108 | SUB(Lib, Screenshot) \ |
| 109 | SUB(Lib, LibCInternal) \ |
| 110 | SUB(Lib, AppContent) \ |
| 111 | SUB(Lib, Rtc) \ |
| 112 | SUB(Lib, DiscMap) \ |
| 113 | SUB(Lib, Png) \ |
| 114 | SUB(Lib, Jpeg) \ |
| 115 | SUB(Lib, PlayGo) \ |
| 116 | SUB(Lib, PlayGoDialog) \ |
| 117 | SUB(Lib, Random) \ |
| 118 | SUB(Lib, Usbd) \ |
| 119 | SUB(Lib, Ajm) \ |
| 120 | SUB(Lib, ErrorDialog) \ |
| 121 | SUB(Lib, ImeDialog) \ |
| 122 | SUB(Lib, AvPlayer) \ |
| 123 | SUB(Lib, Ngs2) \ |
| 124 | SUB(Lib, Audio3d) \ |
| 125 | SUB(Lib, Ime) \ |
| 126 | SUB(Lib, GameLiveStreaming) \ |
| 127 | SUB(Lib, Remoteplay) \ |
| 128 | SUB(Lib, SharePlay) \ |
| 129 | SUB(Lib, Fiber) \ |
| 130 | SUB(Lib, Vdec2) \ |
| 131 | SUB(Lib, Videodec) \ |
| 132 | SUB(Lib, RazorCpu) \ |
| 133 | SUB(Lib, Mouse) \ |
| 134 | SUB(Lib, WebBrowserDialog) \ |
| 135 | SUB(Lib, NpParty) \ |
| 136 | SUB(Lib, Zlib) \ |
| 137 | CLS(Frontend) \ |
| 138 | CLS(Render) \ |
| 139 | SUB(Render, Vulkan) \ |
| 140 | SUB(Render, Recompiler) \ |
| 141 | CLS(ImGui) \ |
| 142 | CLS(Input) \ |
| 143 | CLS(Tty) \ |
| 144 | CLS(Loader) |
| 145 | |
| 146 | // GetClassName is a macro defined by Windows.h, grrr... |
| 147 | const char* GetLogClassName(Class log_class) { |
| 148 | switch (log_class) { |
| 149 | #define CLS(x) \ |
| 150 | case Class::x: \ |
| 151 | return #x; |
| 152 | #define SUB(x, y) \ |
| 153 | case Class::x##_##y: \ |
| 154 | return #x "." #y; |
| 155 | ALL_LOG_CLASSES() |
| 156 | #undef CLS |
| 157 | #undef SUB |
| 158 | case Class::Count: |
| 159 | default: |
| 160 | break; |
| 161 | } |
| 162 | UNREACHABLE(); |
| 163 | } |
| 164 | |
| 165 | const char* GetLevelName(Level log_level) { |
| 166 | #define LVL(x) \ |
| 167 | case Level::x: \ |
| 168 | return #x |
| 169 | switch (log_level) { |
| 170 | LVL(Trace); |
| 171 | LVL(Debug); |
| 172 | LVL(Info); |
| 173 | LVL(Warning); |
| 174 | LVL(Error); |
| 175 | LVL(Critical); |
| 176 | case Level::Count: |
| 177 | default: |
| 178 | break; |
| 179 | } |
| 180 | #undef LVL |
| 181 | UNREACHABLE(); |
| 182 | } |
| 183 | |
| 184 | Filter::Filter(Level default_level) { |
| 185 | ResetAll(default_level); |
| 186 | } |
| 187 | |
| 188 | void Filter::ResetAll(Level level) { |
| 189 | class_levels.fill(level); |
| 190 | } |
| 191 | |
| 192 | void Filter::SetClassLevel(Class log_class, Level level) { |
| 193 | class_levels[static_cast<std::size_t>(log_class)] = level; |
| 194 | } |
| 195 | |
| 196 | void Filter::ParseFilterString(std::string_view filter_view) { |
| 197 | auto clause_begin = filter_view.cbegin(); |
| 198 | while (clause_begin != filter_view.cend()) { |
| 199 | auto clause_end = std::find(clause_begin, filter_view.cend(), ' '); |
| 200 | |
| 201 | // If clause isn't empty |
| 202 | if (clause_end != clause_begin) { |
| 203 | ParseFilterRule(*this, clause_begin, clause_end); |
| 204 | } |
| 205 | |
| 206 | if (clause_end != filter_view.cend()) { |
| 207 | // Skip over the whitespace |
| 208 | ++clause_end; |
| 209 | } |
| 210 | clause_begin = clause_end; |
| 211 | } |
| 212 | } |
| 213 | |
| 214 | bool Filter::CheckMessage(Class log_class, Level level) const { |
| 215 | return static_cast<u8>(level) >= |
| 216 | static_cast<u8>(class_levels[static_cast<std::size_t>(log_class)]); |
| 217 | } |
| 218 | |
| 219 | bool Filter::IsDebug() const { |
| 220 | return std::any_of(class_levels.begin(), class_levels.end(), [](const Level& l) { |
| 221 | return static_cast<u8>(l) <= static_cast<u8>(Level::Debug); |
| 222 | }); |
| 223 | } |
| 224 | |
| 225 | } // namespace Common::Log |
| 226 |