From 6e1b0abf1d72a8342d722f4c3e829dabc4e71cb2 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Tue, 22 Dec 2020 21:48:18 -0500 Subject: [PATCH] uart.mitm: comments, etc. --- .../source/uart_mitm/uart_mitm_service.cpp | 74 +++++++++++++------ .../source/uart_mitm/uart_mitm_service.hpp | 1 - 2 files changed, 52 insertions(+), 23 deletions(-) diff --git a/stratosphere/ams_mitm/source/uart_mitm/uart_mitm_service.cpp b/stratosphere/ams_mitm/source/uart_mitm/uart_mitm_service.cpp index 0531cf776..4f9f4ea56 100644 --- a/stratosphere/ams_mitm/source/uart_mitm/uart_mitm_service.cpp +++ b/stratosphere/ams_mitm/source/uart_mitm/uart_mitm_service.cpp @@ -45,39 +45,47 @@ namespace ams::mitm::uart { UartPortService::UartPortService(const sm::MitmProcessInfo &cl, std::unique_ptr<::UartPortSession> s) : client_info(cl), srv(std::move(s)) { Result rc=0; /* Get a timestamp. */ - u64 timestamp0, timestamp1; + u64 timestamp0=0, timestamp1; this->TryGetCurrentTimestamp(×tamp0); timestamp1 = svcGetSystemTick(); + /* Setup/create the logging directory. */ std::snprintf(this->base_path, sizeof(this->base_path), "uart_logs/%011lu_%011lu_%016lx", timestamp0, timestamp1, static_cast(this->client_info.program_id)); ams::mitm::fs::CreateAtmosphereSdDirectory("uart_logs"); ams::mitm::fs::CreateAtmosphereSdDirectory(this->base_path); + /* Create/initialize the text cmd_log. */ char tmp_path[256]; std::snprintf(tmp_path, sizeof(tmp_path), "%s/%s", this->base_path, "cmd_log"); ams::mitm::fs::CreateAtmosphereSdFile(tmp_path, 0, 0); this->cmdlog_pos = 0; + /* Initialize the Send cache-buffer. */ this->send_cache_buffer = static_cast(std::malloc(this->CacheBufferSize)); if (this->send_cache_buffer != nullptr) { std::memset(this->send_cache_buffer, 0, this->CacheBufferSize); } this->send_cache_pos = 0; + /* Initialize the Receive cache-buffer. */ this->receive_cache_buffer = static_cast(std::malloc(this->CacheBufferSize)); if (this->receive_cache_buffer != nullptr) { std::memset(this->receive_cache_buffer, 0, this->CacheBufferSize); } this->receive_cache_pos = 0; + /* When the above is successful, initialize the datalog. */ if (this->send_cache_buffer != nullptr && this->receive_cache_buffer != nullptr) { std::snprintf(tmp_path, sizeof(tmp_path), "%s/%s", this->base_path, "btsnoop_hci.log"); ams::mitm::fs::CreateAtmosphereSdFile(tmp_path, 0, 0); rc = ams::mitm::fs::OpenAtmosphereSdFile(&this->datalog_file, tmp_path, FsOpenMode_Read | FsOpenMode_Write | FsOpenMode_Append); + /* Set datalog_ready to whether initialization was successful. */ this->datalog_ready = R_SUCCEEDED(rc); } this->datalog_pos = 0; + /* Setup the btsnoop header. */ + struct { char id[8]; u32 version; @@ -89,26 +97,18 @@ namespace ams::mitm::uart { ams::util::StoreBigEndian(&btsnoop_header.version, version); ams::util::StoreBigEndian(&btsnoop_header.datalink_type, datalink_type); + /* Enable data-logging, required for WriteLog() to write anything. */ this->data_logging_enabled = true; + + /* Write the btsnoop header to the datalog. */ this->WriteLog(&btsnoop_header, sizeof(btsnoop_header)); + /* This will be re-enabled by WriteUartData once a certain command is detected. */ /* If you want to log all HCI traffic during system-boot initialization, you can comment out the below line, however there will be a slowdown. */ this->data_logging_enabled = false; } - void UartPortService::SaveFile(const char *path, const void* buffer, size_t size) { - Result rc=0; - FsFile file={}; - char tmp_path[256]; - std::snprintf(tmp_path, sizeof(tmp_path), "%s/%s", this->base_path, path); - ams::mitm::fs::CreateAtmosphereSdFile(tmp_path, 0, 0); - rc = ams::mitm::fs::OpenAtmosphereSdFile(&file, tmp_path, FsOpenMode_Read | FsOpenMode_Write | FsOpenMode_Append); - if (R_SUCCEEDED(rc)) { - rc = fsFileWrite(&file, 0, buffer, size, FsWriteOption_None); - } - fsFileClose(&file); - } - + /* Append the specified string to the text cmd_log file. */ void UartPortService::WriteCmdLog(const char *str) { Result rc=0; FsFile file={}; @@ -125,7 +125,9 @@ namespace ams::mitm::uart { fsFileClose(&file); } + /* Append the specified data to the datalog file. */ void UartPortService::WriteLog(const void* buffer, size_t size) { + /* Only write to the file if data-logging is enabled and initialized. */ if (this->data_logging_enabled && this->datalog_ready) { if (R_SUCCEEDED(fsFileWrite(&this->datalog_file, this->datalog_pos, buffer, size, FsWriteOption_None))) { this->datalog_pos += size; @@ -133,6 +135,8 @@ namespace ams::mitm::uart { } } + /* Append the specified packet to the datalog via WriteLog. */ + /* dir: false = Send (host->controller), true = Receive (controller->host). */ void UartPortService::WriteLogPacket(bool dir, const void* buffer, size_t size) { struct { u32 original_length; @@ -150,13 +154,20 @@ namespace ams::mitm::uart { ams::util::StoreBigEndian(&pkt_hdr.included_length, static_cast(size)); ams::util::StoreBigEndian(&pkt_hdr.packet_flags, flags); + /* Currently we leave the timestamp at value 0. */ + this->WriteLog(&pkt_hdr, sizeof(pkt_hdr)); this->WriteLog(buffer, size); } + /* Log data from Send/Receive. */ + /* dir: false = Send (host->controller), true = Receive (controller->host). */ void UartPortService::WriteUartData(bool dir, const void* buffer, size_t size) { + /* Select which cache buffer/pos to use via dir. */ u8 *cache_buffer = !dir ? this->send_cache_buffer : this->receive_cache_buffer; size_t *cache_pos = !dir ? &this->send_cache_pos : &this->receive_cache_pos; + + /* Verify that the input size is non-zero, and within cache buffer bounds. */ if (size && *cache_pos + size <= this->CacheBufferSize) { struct { u8 opcode[0x2]; @@ -189,54 +200,64 @@ namespace ams::mitm::uart { } *hci_iso_data = reinterpret_cast(&cache_buffer[0x1]); static_assert(sizeof(*hci_iso_data) == 0x4); + /* Copy the input data into the cache and update the pos. */ std::memcpy(&cache_buffer[*cache_pos], buffer, size); (*cache_pos)+= size; + /* Process the packets in the cache. */ do { size_t orig_pkt_len = 0x0; size_t pkt_len = 0x1; - if (cache_buffer[0] == 0x1) { + + /* Determine which HCI packet this is, via the packet indicator. */ + /* These are supported regardless of whether the official bluetooth-sysmodule supports it. */ + + if (cache_buffer[0] == 0x1) { /* HCI Command */ if (*cache_pos >= 0x1+sizeof(*hci_cmd)) { orig_pkt_len = sizeof(*hci_cmd) + hci_cmd->param_len; - /* Check for the first cmd used in the port which is opened last. */ + /* Check for the first command used in the port which is opened last by bluetooth-sysmodule. */ + /* This is a vendor command. */ + /* Once detected, data-logging will be enabled. */ if (!this->data_logging_enabled && hci_cmd->opcode[1] == 0xFC && hci_cmd->opcode[0] == 0x16) { this->data_logging_enabled = true; } } } - else if (cache_buffer[0] == 0x2) { + else if (cache_buffer[0] == 0x2) { /* HCI ACL Data */ if (*cache_pos >= 0x1+sizeof(*hci_acl_data)) { orig_pkt_len = sizeof(*hci_acl_data) + hci_acl_data->data_len; } } - else if (cache_buffer[0] == 0x3) { + else if (cache_buffer[0] == 0x3) { /* HCI Synchronous Data (SCO) */ if (*cache_pos >= 0x1+sizeof(*hci_sco_data)) { orig_pkt_len = sizeof(*hci_sco_data) + hci_sco_data->data_len; } } - else if (cache_buffer[0] == 0x4) { + else if (cache_buffer[0] == 0x4) { /* HCI Event */ if (*cache_pos >= 0x1+sizeof(*hci_event)) { orig_pkt_len = sizeof(*hci_event) + hci_event->param_len; } } - else if (cache_buffer[0] == 0x5) { + else if (cache_buffer[0] == 0x5) { /* HCI ISO Data */ if (*cache_pos >= 0x1+sizeof(*hci_iso_data)) { orig_pkt_len = sizeof(*hci_iso_data) + hci_iso_data->data_load_len; } } - else { + else { /* Unknown HCI packet */ char str[256]; std::snprintf(str, sizeof(str), "WriteUartData(dir = %s): Unknown HCI packet indicator 0x%x, ignoring the packet and emptying the cache.\n", !dir ? "send" : "receive", cache_buffer[0]); this->WriteCmdLog(str); *cache_pos = 0; } + /* If a full packet is available in the cache, update pkt_len. */ if (orig_pkt_len) { if (*cache_pos >= 0x1+orig_pkt_len) { pkt_len+= orig_pkt_len; } } + /* If a packet is available, log it and update the cache. */ if (pkt_len>0x1) { this->WriteLogPacket(dir, cache_buffer, pkt_len); (*cache_pos)-= pkt_len; @@ -244,11 +265,13 @@ namespace ams::mitm::uart { std::memmove(cache_buffer, &cache_buffer[pkt_len], *cache_pos); } } + /* Otherwise, exit the loop. */ else break; } while(*cache_pos); } } + /* Forward OpenPort and write to the cmd_log. */ Result UartPortService::OpenPort(sf::Out out, u32 port, u32 baud_rate, UartFlowControlMode flow_control_mode, u32 device_variation, bool is_invert_tx, bool is_invert_rx, bool is_invert_rts, bool is_invert_cts, sf::CopyHandle send_handle, sf::CopyHandle receive_handle, u64 send_buffer_length, u64 receive_buffer_length) { Result rc = uartPortSessionOpenPortFwd(this->srv.get(), reinterpret_cast(out.GetPointer()), port, baud_rate, flow_control_mode, device_variation, is_invert_tx, is_invert_rx, is_invert_rts, is_invert_cts, send_handle.GetValue(), receive_handle.GetValue(), send_buffer_length, receive_buffer_length); svcCloseHandle(send_handle.GetValue()); @@ -260,6 +283,7 @@ namespace ams::mitm::uart { return rc; } + /* Forward OpenPortForDev and write to the cmd_log. */ Result UartPortService::OpenPortForDev(sf::Out out, u32 port, u32 baud_rate, UartFlowControlMode flow_control_mode, u32 device_variation, bool is_invert_tx, bool is_invert_rx, bool is_invert_rts, bool is_invert_cts, sf::CopyHandle send_handle, sf::CopyHandle receive_handle, u64 send_buffer_length, u64 receive_buffer_length) { Result rc = uartPortSessionOpenPortForDevFwd(this->srv.get(), reinterpret_cast(out.GetPointer()), port, baud_rate, flow_control_mode, device_variation, is_invert_tx, is_invert_rx, is_invert_rts, is_invert_cts, send_handle.GetValue(), receive_handle.GetValue(), send_buffer_length, receive_buffer_length); svcCloseHandle(send_handle.GetValue()); @@ -271,6 +295,7 @@ namespace ams::mitm::uart { return rc; } + /* Forward GetWritableLength and write to the cmd_log. */ Result UartPortService::GetWritableLength(sf::Out out) { Result rc = uartPortSessionGetWritableLength(this->srv.get(), reinterpret_cast(out.GetPointer())); @@ -281,6 +306,7 @@ namespace ams::mitm::uart { return rc; } + /* Forward Send and log the data if the out_size is non-zero. */ Result UartPortService::Send(sf::Out out_size, const sf::InAutoSelectBuffer &data) { Result rc = uartPortSessionSend(this->srv.get(), data.GetPointer(), data.GetSize(), reinterpret_cast(out_size.GetPointer())); @@ -290,16 +316,18 @@ namespace ams::mitm::uart { return rc; } + /* Forward GetReadableLength and write to the cmd_log. */ Result UartPortService::GetReadableLength(sf::Out out) { Result rc = uartPortSessionGetReadableLength(this->srv.get(), reinterpret_cast(out.GetPointer())); char str[256]; - std::snprintf(str, sizeof(str), "GetWritableLength(): rc = 0x%x, out = 0x%lx\n", rc.GetValue(), out.GetValue()); + std::snprintf(str, sizeof(str), "GetReadableLength(): rc = 0x%x, out = 0x%lx\n", rc.GetValue(), out.GetValue()); this->WriteCmdLog(str); return rc; } + /* Forward Receive and log the data if the out_size is non-zero. */ Result UartPortService::Receive(sf::Out out_size, const sf::OutAutoSelectBuffer &data) { Result rc = uartPortSessionReceive(this->srv.get(), data.GetPointer(), data.GetSize(), reinterpret_cast(out_size.GetPointer())); @@ -309,6 +337,7 @@ namespace ams::mitm::uart { return rc; } + /* Forward BindPortEvent and write to the cmd_log. */ Result UartPortService::BindPortEvent(sf::Out out, sf::OutCopyHandle out_event_handle, UartPortEventType port_event_type, s64 threshold) { Result rc = uartPortSessionBindPortEventFwd(this->srv.get(), port_event_type, threshold, reinterpret_cast(out.GetPointer()), out_event_handle.GetHandlePointer()); @@ -318,6 +347,7 @@ namespace ams::mitm::uart { return rc; } + /* Forward UnbindPortEvent and write to the cmd_log. */ Result UartPortService::UnbindPortEvent(sf::Out out, UartPortEventType port_event_type) { Result rc = uartPortSessionUnbindPortEvent(this->srv.get(), port_event_type, reinterpret_cast(out.GetPointer())); diff --git a/stratosphere/ams_mitm/source/uart_mitm/uart_mitm_service.hpp b/stratosphere/ams_mitm/source/uart_mitm/uart_mitm_service.hpp index b162e14f3..53e7a0885 100644 --- a/stratosphere/ams_mitm/source/uart_mitm/uart_mitm_service.hpp +++ b/stratosphere/ams_mitm/source/uart_mitm/uart_mitm_service.hpp @@ -64,7 +64,6 @@ namespace ams::mitm::uart { size_t receive_cache_pos; bool TryGetCurrentTimestamp(u64 *out); - void SaveFile(const char *path, const void* buffer, size_t size); void WriteCmdLog(const char *str); void WriteLog(const void* buffer, size_t size); void WriteLogPacket(bool dir, const void* buffer, size_t size);