Changes

Jump to navigation Jump to search
6,267 bytes added ,  19:45, 1 December 2020
no edit summary
Line 1: Line 1:  
= lm =
 
= lm =
 
This is "nn::lm::ILogService".
 
This is "nn::lm::ILogService".
 +
 +
This service is stubbed on retail, with all the commands/interfaces being present but returning success and doing anything.
    
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Line 13: Line 15:  
Takes an input u64 value representing a process ID and returns an [[#ILogger]] instance.
 
Takes an input u64 value representing a process ID and returns an [[#ILogger]] instance.
   −
== ILogger ==
+
= lm:get =
 +
This is "nn::lm::ILogGetter". This service doesn't exist on retail.
 +
 
 +
This service can be used to retrieve log messages (only the TextLog field, see [[#Logging]])
 +
 
 +
{| class="wikitable" border="1"
 +
|-
 +
! Cmd || Name
 +
|-
 +
| 0 || [[#StartLogging]]
 +
|-
 +
| 1 || [[#StopLogging]]
 +
|-
 +
| 2 || [[#GetLog]]
 +
|}
 +
 
 +
== StartLogging ==
 +
Takes no input and no output, and just sets a global flag to true.
 +
 
 +
== StopLogging ==
 +
Same as above, but the flag is set to false.
 +
 
 +
== GetLog ==
 +
Takes an output type-0x22 buffer, returns two output u64s (read size and packet drop count)
 +
The flag mentioned above is not checked here, as it is used in a different place (see [[#Logging]])
 +
 
 +
= ILogger =
 
This is "nn::lm::ILogger".
 
This is "nn::lm::ILogger".
   Line 27: Line 55:  
== Log ==
 
== Log ==
   −
Takes an input buffer containing the message to log.
+
Takes a type-0x21 input buffer containing the message to log.
 
Will always return successfully.
 
Will always return successfully.
   Line 38: Line 66:  
! Value || Description
 
! Value || Description
 
|-
 
|-
| 1 || TMA
+
| 1 || Log to SD card / HTCS
 
|-
 
|-
| 2 || UART
+
| 2 || Disable something (?)
 +
|}
 +
 
 +
= LogPacketHeader =
 +
This is "nn::lm::detail::LogPacketHeader"
 +
 
 +
{| class="wikitable" border="1"
 
|-
 
|-
| 4 || UART when sleeping
+
! Offset || Size || Description
 
|-
 
|-
| 0xFFFF || Log to all destinations
+
| 0x0 || 0x8 || Process ID
 +
|-
 +
| 0x8 || 0x8 || Thread ID
 +
|-
 +
| 0x10 || 0x1 || [[#LogPacketFlags]]
 +
|-
 +
| 0x11 || 0x1 || Padding/reserved
 +
|-
 +
| 0x12 || 0x1 || [[#LogSeverity]]
 +
|-
 +
| 0x13 || 0x1 || Verbosity
 +
|-
 +
| 0x14 || 0x4 || Payload size
 
|}
 
|}
   −
= lm:get =
+
= LogPacketFlags =
This is "nn::lm::ILogGetter".
+
 
 +
{| class="wikitable" border="1"
 +
|-
 +
! Value || Name
 +
|-
 +
| 1 || Head
 +
|-
 +
| 2 || Tail
 +
|-
 +
| 4 || LittleEndian
 +
|}
 +
 
 +
= Binary header =
 +
Binary log files saved in SD card have this extra header (see [[#Logging]])
 +
 
 +
{| class="wikitable" border="1"
 +
|-
 +
! Offset || Size || Description
 +
|-
 +
| 0x0 || 0x4 || Magic ("hphp")
 +
|-
 +
| 0x4 || 0x1 || Version (1)
 +
|-
 +
| 0x5 || 0x3 || Padding/reserved
 +
|}
 +
 
 +
= LogSeverity =
 +
This is "nn::diag::LogSeverity"
 +
 
 +
{| class="wikitable" border="1"
 +
|-
 +
! Value || Name
 +
|-
 +
| 0 || Trace
 +
|-
 +
| 1 || Info
 +
|-
 +
| 2 || Warn
 +
|-
 +
| 3 || Error
 +
|-
 +
| 4 || Fatal
 +
|}
 +
 
 +
= LogDataChunkKey =
 +
 
 +
{| class="wikitable" border="1"
 +
|-
 +
! Value || Name || Description
 +
|-
 +
| 0 || LogSessionBegin || Special field sent when a process starts logging (see [[#Logging]])
 +
|-
 +
| 1 || LogSessionEnd || Special field sent when a process finishes logging (see [[#Logging]])
 +
|-
 +
| 2 || TextLog || Actual log text.
 +
|-
 +
| 3 || LineNumber || Line number.
 +
|-
 +
| 4 || FileName || File name.
 +
|-
 +
| 5 || FunctionName || Function name.
 +
|-
 +
| 6 || ModuleName || Module name.
 +
|-
 +
| 7 || ThreadName || Thread name.
 +
|-
 +
| 8 || LogPacketDropCount || Special field containing the amount of packets missed (failed to log/flush, see [[#Logging]])
 +
|-
 +
| 9 || UserSystemClock  || Time value.
 +
|-
 +
| 10 || ProcessName || Process name.
 +
|}
 +
 
 +
= Data chunks =
 +
Data chunks (log packet data fields) follow this format:
    
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
! Cmd || Name
+
! Offset || Size || Description
 +
|-
 +
| 0x0 || Variable (normally 0x1) || [[#LogDataChunkKey]] in LEB128 format
 +
|-
 +
| Variable || Variable (normally 0x1) || Chunk size in LEB128 format
 +
|-
 +
| Variable || Chunk size || Chunk data
 +
|}
 +
 
 +
= Log packet =
 +
 
 +
{| class="wikitable" border="1"
 
|-
 
|-
| 0 || StartLogging
+
! Offset || Size || Description
 
|-
 
|-
| 1 || StopLogging
+
| 0x0 || 0x18 || [[#LogPacketHeader]]
 
|-
 
|-
| 2 || GetLog
+
| 0x18 || Variable || Data chunks
 
|}
 
|}
   −
This service doesn't normally exist on retail.
+
= Logging =
 +
 
 +
LogManager uses two separate threads: a flushing thread and a htcs thread (main thread is handling both IPC and PM module requests):
 +
 
 +
* The flushing calls Flush() on the "LogBuffer" object, which is the object responsible for flushing logged data though the other objects, and sends a LogPacketDropCount packet via the "EventLogTransmitter" object (see below) if there any dropped packets and the flushing succeeds - this is done in a loop, waiting until the process starts finalization.
 +
 
 +
* The htcs thread continously reads from the server connection, and will close and reopen the client socket if the connection happened to be lost - this is done in a loop, waiting until the process starts finalization.
 +
 
 +
Different global objects are used for different purposes:
 +
 
 +
* SdCardLogging object - saves logs on the SD card, if both <code>lm!sd_card_log_output_directory</code> and <code>lm!enable_sd_card_logging</code> are present and the last one is true:
 +
** The file name format used is <code>sd:/<log_output_directory>/<serial_no>_<year><month><day><hour><min><sec>[_<extra_index>].nxbinlog</code>, where the extra index is added if the file is already present (several logs being saved at the same time), with a maximum value of 100 (otherwise the saving fails).
 +
** These binary files contain multiple log packets, always preceded by a binary header (see above).
 +
** A single file is used for all the log packets, if the SD card gets ejected or something similar happens the code will re-mount it when it's ready and create a new file.
 +
 
 +
* LogServerProxy object - sends log data via HTCS (see [[TMA_services]])
 +
 
 +
* LogGetterLogger object - retains log data which can be later retrieved by [[#lm:get]]:
 +
** When processes log via [[#lm]] service, some code analyzes the log packet, locates the TextLog ([[#LogDataChunkKey]]) chunk (if present) and saves it's contents in a global buffer (therefore, only the actual log message gets retained).
 +
** Log packets are only analyzed/retained after enabling it (by calling [[#StartLogging]]), and the [[#GetLog]] command just reads data from the global buffer.
 +
** The analyzing code also keeps track of which packets are "missed" (skipped/not properly logged), and that missed packet count can be also retrieved on the [[#GetLog]] command.
 +
** When the global buffer is full, nothing will get logged until a process reads the logged data, cleaning the buffer.
 +
 
 +
* EventLogTransmitter object - sends special log packets (event logs):
 +
** When an [[#ILogger]] gets created, this object will send a packet containing the logger's process ID and a LogSessionBegin chunk, telling the remote connection that a new process has started logging. Analogously, when the logger gets destroyed, a simple packet with the process ID and a LogSessionEnd chunk gets sent, telling the remote connection that the process has stopped logging.
 +
** As mentioned above, the flush thread will tell this object to send a simple packet with a LogPacketDropCount chunk after flushing succeeds (and if there any dropped packets).
 +
** These event log packets are logged via the LogBuffer object, like process logs, but they are not analized by the LogGetterLogger object since they have no text to be saved.
 +
 
 +
* LogBuffer object - responsible for flushing log packets:
 +
** It internally calls the SdCardLogging and LogServerProxy objects when flushing, so that log packets get flushed to both SD card (if enabled) and HTCS.
 +
** It uses a secondary object to flush, alternating between itself and that secondary object when flushing.
    
[[Category:Services]]
 
[[Category:Services]]
17

edits

Navigation menu