Implement OutputAccessLogToSdCard and expose an FS access log option (#700)

* Add OutputAccessLogToSdCard

* Add config options for the FS access log
This commit is contained in:
Alex Barney 2019-06-15 20:31:18 -05:00 committed by Ac_K
parent 5c1bc52409
commit 350a3667f7
9 changed files with 136 additions and 20 deletions

View file

@ -6,6 +6,8 @@ namespace Ryujinx.Common.Logging
Stub, Stub,
Info, Info,
Warning, Warning,
Error Error,
Guest,
AccessLog
} }
} }

View file

@ -22,10 +22,12 @@ namespace Ryujinx.Common.Logging
m_EnabledLevels = new bool[Enum.GetNames(typeof(LogLevel)).Length]; m_EnabledLevels = new bool[Enum.GetNames(typeof(LogLevel)).Length];
m_EnabledClasses = new bool[Enum.GetNames(typeof(LogClass)).Length]; m_EnabledClasses = new bool[Enum.GetNames(typeof(LogClass)).Length];
m_EnabledLevels[(int)LogLevel.Stub] = true; m_EnabledLevels[(int)LogLevel.Stub] = true;
m_EnabledLevels[(int)LogLevel.Info] = true; m_EnabledLevels[(int)LogLevel.Info] = true;
m_EnabledLevels[(int)LogLevel.Warning] = true; m_EnabledLevels[(int)LogLevel.Warning] = true;
m_EnabledLevels[(int)LogLevel.Error] = true; m_EnabledLevels[(int)LogLevel.Error] = true;
m_EnabledLevels[(int)LogLevel.Guest] = true;
m_EnabledLevels[(int)LogLevel.AccessLog] = true;
for (int index = 0; index < m_EnabledClasses.Length; index++) for (int index = 0; index < m_EnabledClasses.Length; index++)
{ {
@ -101,6 +103,16 @@ namespace Ryujinx.Common.Logging
Print(LogLevel.Stub, logClass, GetFormattedMessage(logClass, "Stubbed. " + message, caller), obj); Print(LogLevel.Stub, logClass, GetFormattedMessage(logClass, "Stubbed. " + message, caller), obj);
} }
public static void PrintGuest(LogClass logClass, string message, [CallerMemberName] string caller = "")
{
Print(LogLevel.Guest, logClass, GetFormattedMessage(logClass, message, caller));
}
public static void PrintAccessLog(LogClass logClass, string message)
{
Print(LogLevel.AccessLog, logClass, message);
}
private static void Print(LogLevel logLevel, LogClass logClass, string message) private static void Print(LogLevel logLevel, LogClass logClass, string message)
{ {
if (m_EnabledLevels[(int)logLevel] && m_EnabledClasses[(int)logClass]) if (m_EnabledLevels[(int)logLevel] && m_EnabledClasses[(int)logClass])

View file

@ -105,6 +105,8 @@ namespace Ryujinx.HLE.HOS
public IntegrityCheckLevel FsIntegrityCheckLevel { get; set; } public IntegrityCheckLevel FsIntegrityCheckLevel { get; set; }
public int GlobalAccessLogMode { get; set; }
internal long HidBaseAddress { get; private set; } internal long HidBaseAddress { get; private set; }
public Horizon(Switch device) public Horizon(Switch device)

View file

@ -1,6 +1,7 @@
using LibHac; using LibHac;
using LibHac.Fs; using LibHac.Fs;
using LibHac.Fs.NcaUtils; using LibHac.Fs.NcaUtils;
using Ryujinx.Common.Logging;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS.Ipc; using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.Utilities; using Ryujinx.HLE.Utilities;
@ -32,7 +33,8 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
{ 200, OpenDataStorageByCurrentProcess }, { 200, OpenDataStorageByCurrentProcess },
{ 202, OpenDataStorageByDataId }, { 202, OpenDataStorageByDataId },
{ 203, OpenPatchDataStorageByCurrentProcess }, { 203, OpenPatchDataStorageByCurrentProcess },
{ 1005, GetGlobalAccessLogMode } { 1005, GetGlobalAccessLogMode },
{ 1006, OutputAccessLogToSdCard }
}; };
} }
@ -208,7 +210,20 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
// GetGlobalAccessLogMode() -> u32 logMode // GetGlobalAccessLogMode() -> u32 logMode
public long GetGlobalAccessLogMode(ServiceCtx context) public long GetGlobalAccessLogMode(ServiceCtx context)
{ {
context.ResponseData.Write(0); int mode = context.Device.System.GlobalAccessLogMode;
context.ResponseData.Write(mode);
return 0;
}
// OutputAccessLogToSdCard(buffer<bytes, 5> log_text)
public long OutputAccessLogToSdCard(ServiceCtx context)
{
string message = ReadUtf8StringSend(context);
// FS ends each line with a newline. Remove it because Ryujinx logging adds its own newline
Logger.PrintAccessLog(LogClass.ServiceFs, message.TrimEnd('\n'));
return 0; return 0;
} }

View file

@ -41,6 +41,8 @@ namespace Ryujinx.HLE.HOS.Services.Lm
sb.AppendLine("Guest log:"); sb.AppendLine("Guest log:");
sb.AppendLine($" Log level: {(LmLogLevel)level}");
while (ms.Position < ms.Length) while (ms.Position < ms.Length)
{ {
byte type = reader.ReadByte(); byte type = reader.ReadByte();
@ -86,14 +88,7 @@ namespace Ryujinx.HLE.HOS.Services.Lm
string text = sb.ToString(); string text = sb.ToString();
switch((LmLogLevel)level) Logger.PrintGuest(LogClass.ServiceLm, text);
{
case LmLogLevel.Trace: Logger.PrintDebug (LogClass.ServiceLm, text); break;
case LmLogLevel.Info: Logger.PrintInfo (LogClass.ServiceLm, text); break;
case LmLogLevel.Warning: Logger.PrintWarning(LogClass.ServiceLm, text); break;
case LmLogLevel.Error: Logger.PrintError (LogClass.ServiceLm, text); break;
case LmLogLevel.Critical: Logger.PrintError (LogClass.ServiceLm, text); break;
}
} }
return 0; return 0;

View file

@ -72,5 +72,28 @@ namespace Ryujinx.HLE.Utilities
return Encoding.UTF8.GetString(ms.ToArray()); return Encoding.UTF8.GetString(ms.ToArray());
} }
} }
public static string ReadUtf8StringSend(ServiceCtx context, int index = 0)
{
long position = context.Request.SendBuff[index].Position;
long size = context.Request.SendBuff[index].Size;
using (MemoryStream ms = new MemoryStream())
{
while (size-- > 0)
{
byte value = context.Memory.ReadByte(position++);
if (value == 0)
{
break;
}
ms.WriteByte(value);
}
return Encoding.UTF8.GetString(ms.ToArray());
}
}
} }
} }

View file

@ -19,6 +19,12 @@
// Enable print error logs // Enable print error logs
"logging_enable_error": true, "logging_enable_error": true,
// Enable printing guest logs
"logging_enable_guest": true,
// Enable printing FS access logs. fs_global_access_log_mode must be 2 or 3
"logging_enable_fs_access_log": false,
// Filtered log classes, in a JSON array, eg. `[ "Loader", "ServiceFs" ]` // Filtered log classes, in a JSON array, eg. `[ "Loader", "ServiceFs" ]`
"logging_filtered_classes": [ ], "logging_filtered_classes": [ ],
@ -44,6 +50,9 @@
// Enable integrity checks on Switch content files // Enable integrity checks on Switch content files
"enable_fs_integrity_checks": true, "enable_fs_integrity_checks": true,
// Sets the "GlobalAccessLogMode". Possible modes are 0-3
"fs_global_access_log_mode": 0,
// Enable or disable aggressive CPU optimizations // Enable or disable aggressive CPU optimizations
"enable_aggressive_cpu_opts": true, "enable_aggressive_cpu_opts": true,

View file

@ -52,6 +52,16 @@ namespace Ryujinx
/// </summary> /// </summary>
public bool LoggingEnableError { get; private set; } public bool LoggingEnableError { get; private set; }
/// <summary>
/// Enables printing guest log messages
/// </summary>
public bool LoggingEnableGuest { get; private set; }
/// <summary>
/// Enables printing FS access log messages
/// </summary>
public bool LoggingEnableFsAccessLog { get; private set; }
/// <summary> /// <summary>
/// Controls which log messages are written to the log targets /// Controls which log messages are written to the log targets
/// </summary> /// </summary>
@ -92,6 +102,11 @@ namespace Ryujinx
/// </summary> /// </summary>
public bool EnableFsIntegrityChecks { get; private set; } public bool EnableFsIntegrityChecks { get; private set; }
/// <summary>
/// Enables FS access log output to the console. Possible modes are 0-3
/// </summary>
public int FsGlobalAccessLogMode { get; private set; }
/// <summary> /// <summary>
/// Enable or Disable aggressive CPU optimizations /// Enable or Disable aggressive CPU optimizations
/// </summary> /// </summary>
@ -184,11 +199,13 @@ namespace Ryujinx
)); ));
} }
Logger.SetEnable(LogLevel.Debug, Instance.LoggingEnableDebug); Logger.SetEnable(LogLevel.Debug, Instance.LoggingEnableDebug);
Logger.SetEnable(LogLevel.Stub, Instance.LoggingEnableStub); Logger.SetEnable(LogLevel.Stub, Instance.LoggingEnableStub);
Logger.SetEnable(LogLevel.Info, Instance.LoggingEnableInfo); Logger.SetEnable(LogLevel.Info, Instance.LoggingEnableInfo);
Logger.SetEnable(LogLevel.Warning, Instance.LoggingEnableWarn); Logger.SetEnable(LogLevel.Warning, Instance.LoggingEnableWarn);
Logger.SetEnable(LogLevel.Error, Instance.LoggingEnableError); Logger.SetEnable(LogLevel.Error, Instance.LoggingEnableError);
Logger.SetEnable(LogLevel.Guest, Instance.LoggingEnableGuest);
Logger.SetEnable(LogLevel.AccessLog, Instance.LoggingEnableFsAccessLog);
if (Instance.LoggingFilteredClasses.Length > 0) if (Instance.LoggingFilteredClasses.Length > 0)
{ {
@ -220,6 +237,8 @@ namespace Ryujinx
? IntegrityCheckLevel.ErrorOnInvalid ? IntegrityCheckLevel.ErrorOnInvalid
: IntegrityCheckLevel.None; : IntegrityCheckLevel.None;
device.System.GlobalAccessLogMode = Instance.FsGlobalAccessLogMode;
if (Instance.EnableAggressiveCpuOpts) if (Instance.EnableAggressiveCpuOpts)
{ {
Optimizations.AssumeStrictAbiCompliance = true; Optimizations.AssumeStrictAbiCompliance = true;

View file

@ -10,6 +10,8 @@
"logging_enable_info", "logging_enable_info",
"logging_enable_warn", "logging_enable_warn",
"logging_enable_error", "logging_enable_error",
"logging_enable_guest",
"logging_enable_fs_access_log",
"logging_filtered_classes", "logging_filtered_classes",
"enable_file_log", "enable_file_log",
"system_language", "system_language",
@ -17,6 +19,7 @@
"enable_vsync", "enable_vsync",
"enable_multicore_scheduling", "enable_multicore_scheduling",
"enable_fs_integrity_checks", "enable_fs_integrity_checks",
"fs_global_access_log_mode",
"enable_aggressive_cpu_opts", "enable_aggressive_cpu_opts",
"controller_type", "controller_type",
"enable_keyboard", "enable_keyboard",
@ -265,6 +268,28 @@
false false
] ]
}, },
"logging_enable_guest": {
"$id": "#/properties/logging_enable_guest",
"type": "boolean",
"title": "Logging Enable Guest",
"description": "Enables printing guest log messages",
"default": true,
"examples": [
true,
false
]
},
"logging_enable_fs_access": {
"$id": "#/properties/logging_enable_fs_access_log",
"type": "boolean",
"title": "Logging Enable FS Access Log",
"description": "Enables printing FS access log messages",
"default": true,
"examples": [
true,
false
]
},
"logging_filtered_classes": { "logging_filtered_classes": {
"$id": "#/properties/logging_filtered_classes", "$id": "#/properties/logging_filtered_classes",
"type": "array", "type": "array",
@ -412,6 +437,20 @@
false false
] ]
}, },
"fs_global_access_log_mode": {
"$id": "#/properties/fs_global_access_log_mode",
"type": "integer",
"title": "Enable FS access log",
"description": "Enables FS access log output. Possible modes are 0-3. Modes 2 and 3 output to the console.",
"default": 0,
"minimum": 0,
"examples": [
0,
1,
2,
3
]
},
"enable_aggressive_cpu_opts": { "enable_aggressive_cpu_opts": {
"$id": "#/properties/enable_aggressive_cpu_opts", "$id": "#/properties/enable_aggressive_cpu_opts",
"type": "boolean", "type": "boolean",