| 
									
										
										
										
											2018-01-13 16:22:39 -05:00
										 |  |  | // Copyright 2018 yuzu emulator team
 | 
					
						
							| 
									
										
										
										
											2017-10-14 22:18:42 -04:00
										 |  |  | // Licensed under GPLv2 or any later version
 | 
					
						
							|  |  |  | // Refer to the license.txt file included.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-13 09:44:53 +03:00
										 |  |  | #include <sstream>
 | 
					
						
							| 
									
										
										
										
											2017-10-18 21:41:24 -04:00
										 |  |  | #include <string>
 | 
					
						
							| 
									
										
										
										
											2017-10-14 22:18:42 -04:00
										 |  |  | #include "common/logging/log.h"
 | 
					
						
							|  |  |  | #include "core/hle/ipc_helpers.h"
 | 
					
						
							| 
									
										
										
										
											2017-10-18 21:41:24 -04:00
										 |  |  | #include "core/hle/kernel/client_session.h"
 | 
					
						
							| 
									
										
										
										
											2017-10-14 22:18:42 -04:00
										 |  |  | #include "core/hle/service/lm/lm.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-19 21:41:44 -04:00
										 |  |  | namespace Service::LM { | 
					
						
							| 
									
										
										
										
											2017-10-14 22:18:42 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-18 21:41:24 -04:00
										 |  |  | class Logger final : public ServiceFramework<Logger> { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     Logger() : ServiceFramework("Logger") { | 
					
						
							|  |  |  |         static const FunctionInfo functions[] = { | 
					
						
							|  |  |  |             {0x00000000, &Logger::Log, "Log"}, | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |         RegisterHandlers(functions); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ~Logger() = default; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     struct MessageHeader { | 
					
						
							| 
									
										
										
										
											2018-01-05 00:45:13 -05:00
										 |  |  |         enum Flags : u32_le { | 
					
						
							|  |  |  |             IsHead = 1, | 
					
						
							|  |  |  |             IsTail = 2, | 
					
						
							|  |  |  |         }; | 
					
						
							| 
									
										
										
										
											2018-02-13 09:44:53 +03:00
										 |  |  |         enum Severity : u32_le { | 
					
						
							|  |  |  |             Trace, | 
					
						
							|  |  |  |             Info, | 
					
						
							|  |  |  |             Warning, | 
					
						
							|  |  |  |             Error, | 
					
						
							|  |  |  |             Critical, | 
					
						
							|  |  |  |         }; | 
					
						
							| 
									
										
										
										
											2018-01-05 00:45:13 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-18 21:41:24 -04:00
										 |  |  |         u64_le pid; | 
					
						
							|  |  |  |         u64_le threadContext; | 
					
						
							|  |  |  |         union { | 
					
						
							| 
									
										
										
										
											2018-01-05 00:45:13 -05:00
										 |  |  |             BitField<0, 16, Flags> flags; | 
					
						
							| 
									
										
										
										
											2018-02-13 09:44:53 +03:00
										 |  |  |             BitField<16, 8, Severity> severity; | 
					
						
							| 
									
										
										
										
											2017-10-18 21:41:24 -04:00
										 |  |  |             BitField<24, 8, u32_le> verbosity; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |         u32_le payload_size; | 
					
						
							| 
									
										
										
										
											2018-01-06 14:41:56 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-13 09:44:53 +03:00
										 |  |  |         bool IsHeadLog() const { | 
					
						
							|  |  |  |             return flags & Flags::IsHead; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         bool IsTailLog() const { | 
					
						
							|  |  |  |             return flags & Flags::IsTail; | 
					
						
							| 
									
										
										
										
											2018-01-06 14:41:56 -05:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-10-18 21:41:24 -04:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2018-01-05 00:45:13 -05:00
										 |  |  |     static_assert(sizeof(MessageHeader) == 0x18, "MessageHeader is incorrect size"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /// Log field type
 | 
					
						
							|  |  |  |     enum class Field : u8 { | 
					
						
							| 
									
										
										
										
											2018-01-18 00:08:38 -05:00
										 |  |  |         Skip = 1, | 
					
						
							| 
									
										
										
										
											2018-01-05 00:45:13 -05:00
										 |  |  |         Message = 2, | 
					
						
							|  |  |  |         Line = 3, | 
					
						
							|  |  |  |         Filename = 4, | 
					
						
							|  |  |  |         Function = 5, | 
					
						
							|  |  |  |         Module = 6, | 
					
						
							|  |  |  |         Thread = 7, | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2017-10-18 21:41:24 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							| 
									
										
										
										
											2018-02-13 09:44:53 +03:00
										 |  |  |      * LM::Log service function | 
					
						
							| 
									
										
										
										
											2017-10-18 21:41:24 -04:00
										 |  |  |      *  Inputs: | 
					
						
							|  |  |  |      *      0: 0x00000000 | 
					
						
							|  |  |  |      *  Outputs: | 
					
						
							|  |  |  |      *      0: ResultCode | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     void Log(Kernel::HLERequestContext& ctx) { | 
					
						
							| 
									
										
										
										
											2018-01-05 00:45:13 -05:00
										 |  |  |         // This function only succeeds - Get that out of the way
 | 
					
						
							| 
									
										
										
										
											2018-01-23 19:52:18 -05:00
										 |  |  |         IPC::ResponseBuilder rb{ctx, 2}; | 
					
						
							| 
									
										
										
										
											2018-01-05 00:45:13 -05:00
										 |  |  |         rb.Push(RESULT_SUCCESS); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Read MessageHeader, despite not doing anything with it right now
 | 
					
						
							| 
									
										
										
										
											2017-10-18 21:41:24 -04:00
										 |  |  |         MessageHeader header{}; | 
					
						
							| 
									
										
										
										
											2018-01-05 00:45:13 -05:00
										 |  |  |         VAddr addr{ctx.BufferDescriptorX()[0].Address()}; | 
					
						
							|  |  |  |         const VAddr end_addr{addr + ctx.BufferDescriptorX()[0].size}; | 
					
						
							|  |  |  |         Memory::ReadBlock(addr, &header, sizeof(MessageHeader)); | 
					
						
							|  |  |  |         addr += sizeof(MessageHeader); | 
					
						
							| 
									
										
										
										
											2017-10-18 21:41:24 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-13 09:44:53 +03:00
										 |  |  |         if (header.IsHeadLog()) { | 
					
						
							|  |  |  |             log_stream.str(""); | 
					
						
							|  |  |  |             log_stream.clear(); | 
					
						
							| 
									
										
										
										
											2018-01-06 14:41:56 -05:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-05 00:45:13 -05:00
										 |  |  |         // Parse out log metadata
 | 
					
						
							|  |  |  |         u32 line{}; | 
					
						
							|  |  |  |         std::string message, filename, function; | 
					
						
							|  |  |  |         while (addr < end_addr) { | 
					
						
							|  |  |  |             const Field field{static_cast<Field>(Memory::Read8(addr++))}; | 
					
						
							| 
									
										
										
										
											2018-02-13 09:44:53 +03:00
										 |  |  |             const size_t length{Memory::Read8(addr++)}; | 
					
						
							| 
									
										
										
										
											2018-01-18 00:08:38 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if (static_cast<Field>(Memory::Read8(addr)) == Field::Skip) { | 
					
						
							|  |  |  |                 ++addr; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-05 00:45:13 -05:00
										 |  |  |             switch (field) { | 
					
						
							|  |  |  |             case Field::Message: | 
					
						
							|  |  |  |                 message = Memory::ReadCString(addr, length); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case Field::Line: | 
					
						
							|  |  |  |                 line = Memory::Read32(addr); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case Field::Filename: | 
					
						
							|  |  |  |                 filename = Memory::ReadCString(addr, length); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case Field::Function: | 
					
						
							|  |  |  |                 function = Memory::ReadCString(addr, length); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2018-01-18 00:08:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-05 00:45:13 -05:00
										 |  |  |             addr += length; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-10-18 21:41:24 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-05 00:45:13 -05:00
										 |  |  |         // Empty log - nothing to do here
 | 
					
						
							| 
									
										
										
										
											2018-02-13 09:44:53 +03:00
										 |  |  |         if (log_stream.str().empty() && message.empty()) { | 
					
						
							| 
									
										
										
										
											2018-01-05 00:45:13 -05:00
										 |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Format a nicely printable string out of the log metadata
 | 
					
						
							| 
									
										
										
										
											2018-02-13 09:44:53 +03:00
										 |  |  |         if (!filename.empty()) { | 
					
						
							|  |  |  |             log_stream << filename << ':'; | 
					
						
							| 
									
										
										
										
											2018-01-05 00:45:13 -05:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-02-13 09:44:53 +03:00
										 |  |  |         if (!function.empty()) { | 
					
						
							|  |  |  |             log_stream << function << ':'; | 
					
						
							| 
									
										
										
										
											2018-01-05 00:45:13 -05:00
										 |  |  |         } | 
					
						
							|  |  |  |         if (line) { | 
					
						
							| 
									
										
										
										
											2018-02-13 09:44:53 +03:00
										 |  |  |             log_stream << std::to_string(line) << ':'; | 
					
						
							| 
									
										
										
										
											2018-01-05 00:45:13 -05:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-02-13 09:44:53 +03:00
										 |  |  |         if (log_stream.str().length() > 0 && log_stream.str().back() == ':') { | 
					
						
							|  |  |  |             log_stream << ' '; | 
					
						
							| 
									
										
										
										
											2018-01-05 00:45:13 -05:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-02-13 09:44:53 +03:00
										 |  |  |         log_stream << message; | 
					
						
							| 
									
										
										
										
											2018-01-05 00:45:13 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-13 09:44:53 +03:00
										 |  |  |         if (header.IsTailLog()) { | 
					
						
							|  |  |  |             switch (header.severity) { | 
					
						
							|  |  |  |             case MessageHeader::Severity::Trace: | 
					
						
							| 
									
										
										
										
											2018-07-02 10:13:26 -06:00
										 |  |  |                 LOG_TRACE(Debug_Emulated, "{}", log_stream.str()); | 
					
						
							| 
									
										
										
										
											2018-02-13 09:44:53 +03:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             case MessageHeader::Severity::Info: | 
					
						
							| 
									
										
										
										
											2018-07-02 10:13:26 -06:00
										 |  |  |                 LOG_INFO(Debug_Emulated, "{}", log_stream.str()); | 
					
						
							| 
									
										
										
										
											2018-02-13 09:44:53 +03:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             case MessageHeader::Severity::Warning: | 
					
						
							| 
									
										
										
										
											2018-07-02 10:13:26 -06:00
										 |  |  |                 LOG_WARNING(Debug_Emulated, "{}", log_stream.str()); | 
					
						
							| 
									
										
										
										
											2018-02-13 09:44:53 +03:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             case MessageHeader::Severity::Error: | 
					
						
							| 
									
										
										
										
											2018-07-02 10:13:26 -06:00
										 |  |  |                 LOG_ERROR(Debug_Emulated, "{}", log_stream.str()); | 
					
						
							| 
									
										
										
										
											2018-02-13 09:44:53 +03:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             case MessageHeader::Severity::Critical: | 
					
						
							| 
									
										
										
										
											2018-07-02 10:13:26 -06:00
										 |  |  |                 LOG_CRITICAL(Debug_Emulated, "{}", log_stream.str()); | 
					
						
							| 
									
										
										
										
											2018-02-13 09:44:53 +03:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-10-18 21:41:24 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-02-13 09:44:53 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     std::ostringstream log_stream; | 
					
						
							| 
									
										
										
										
											2017-10-18 21:41:24 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-14 22:18:42 -04:00
										 |  |  | void InstallInterfaces(SM::ServiceManager& service_manager) { | 
					
						
							|  |  |  |     std::make_shared<LM>()->InstallAsService(service_manager); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2017-10-14 22:50:04 -04:00
										 |  |  |  * LM::Initialize service function | 
					
						
							| 
									
										
										
										
											2017-10-14 22:18:42 -04:00
										 |  |  |  *  Inputs: | 
					
						
							|  |  |  |  *      0: 0x00000000 | 
					
						
							|  |  |  |  *  Outputs: | 
					
						
							| 
									
										
										
										
											2017-10-15 01:24:22 -04:00
										 |  |  |  *      0: ResultCode | 
					
						
							| 
									
										
										
										
											2017-10-14 22:18:42 -04:00
										 |  |  |  */ | 
					
						
							|  |  |  | void LM::Initialize(Kernel::HLERequestContext& ctx) { | 
					
						
							| 
									
										
										
										
											2018-01-23 19:52:18 -05:00
										 |  |  |     IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 
					
						
							| 
									
										
										
										
											2018-01-22 17:35:40 -05:00
										 |  |  |     rb.Push(RESULT_SUCCESS); | 
					
						
							| 
									
										
										
										
											2018-01-23 19:43:59 -05:00
										 |  |  |     rb.PushIpcInterface<Logger>(); | 
					
						
							| 
									
										
										
										
											2017-10-18 21:41:24 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-02 10:13:26 -06:00
										 |  |  |     LOG_DEBUG(Service_LM, "called"); | 
					
						
							| 
									
										
										
										
											2017-10-14 22:18:42 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | LM::LM() : ServiceFramework("lm") { | 
					
						
							|  |  |  |     static const FunctionInfo functions[] = { | 
					
						
							|  |  |  |         {0x00000000, &LM::Initialize, "Initialize"}, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     RegisterHandlers(functions); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-19 21:41:44 -04:00
										 |  |  | } // namespace Service::LM
 |