1
0
Fork 0
mirror of https://github.com/Atmosphere-NX/Atmosphere.git synced 2024-12-18 16:32:05 +00:00

uart.mitm: comments, etc.

This commit is contained in:
yellows8 2020-12-22 21:48:18 -05:00
parent d7adef3810
commit 6e1b0abf1d
No known key found for this signature in database
GPG key ID: 0AF90DA3F1E60E43
2 changed files with 52 additions and 23 deletions

View file

@ -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)) { UartPortService::UartPortService(const sm::MitmProcessInfo &cl, std::unique_ptr<::UartPortSession> s) : client_info(cl), srv(std::move(s)) {
Result rc=0; Result rc=0;
/* Get a timestamp. */ /* Get a timestamp. */
u64 timestamp0, timestamp1; u64 timestamp0=0, timestamp1;
this->TryGetCurrentTimestamp(&timestamp0); this->TryGetCurrentTimestamp(&timestamp0);
timestamp1 = svcGetSystemTick(); 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<u64>(this->client_info.program_id)); std::snprintf(this->base_path, sizeof(this->base_path), "uart_logs/%011lu_%011lu_%016lx", timestamp0, timestamp1, static_cast<u64>(this->client_info.program_id));
ams::mitm::fs::CreateAtmosphereSdDirectory("uart_logs"); ams::mitm::fs::CreateAtmosphereSdDirectory("uart_logs");
ams::mitm::fs::CreateAtmosphereSdDirectory(this->base_path); ams::mitm::fs::CreateAtmosphereSdDirectory(this->base_path);
/* Create/initialize the text cmd_log. */
char tmp_path[256]; char tmp_path[256];
std::snprintf(tmp_path, sizeof(tmp_path), "%s/%s", this->base_path, "cmd_log"); std::snprintf(tmp_path, sizeof(tmp_path), "%s/%s", this->base_path, "cmd_log");
ams::mitm::fs::CreateAtmosphereSdFile(tmp_path, 0, 0); ams::mitm::fs::CreateAtmosphereSdFile(tmp_path, 0, 0);
this->cmdlog_pos = 0; this->cmdlog_pos = 0;
/* Initialize the Send cache-buffer. */
this->send_cache_buffer = static_cast<u8 *>(std::malloc(this->CacheBufferSize)); this->send_cache_buffer = static_cast<u8 *>(std::malloc(this->CacheBufferSize));
if (this->send_cache_buffer != nullptr) { if (this->send_cache_buffer != nullptr) {
std::memset(this->send_cache_buffer, 0, this->CacheBufferSize); std::memset(this->send_cache_buffer, 0, this->CacheBufferSize);
} }
this->send_cache_pos = 0; this->send_cache_pos = 0;
/* Initialize the Receive cache-buffer. */
this->receive_cache_buffer = static_cast<u8 *>(std::malloc(this->CacheBufferSize)); this->receive_cache_buffer = static_cast<u8 *>(std::malloc(this->CacheBufferSize));
if (this->receive_cache_buffer != nullptr) { if (this->receive_cache_buffer != nullptr) {
std::memset(this->receive_cache_buffer, 0, this->CacheBufferSize); std::memset(this->receive_cache_buffer, 0, this->CacheBufferSize);
} }
this->receive_cache_pos = 0; this->receive_cache_pos = 0;
/* When the above is successful, initialize the datalog. */
if (this->send_cache_buffer != nullptr && this->receive_cache_buffer != nullptr) { 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"); std::snprintf(tmp_path, sizeof(tmp_path), "%s/%s", this->base_path, "btsnoop_hci.log");
ams::mitm::fs::CreateAtmosphereSdFile(tmp_path, 0, 0); ams::mitm::fs::CreateAtmosphereSdFile(tmp_path, 0, 0);
rc = ams::mitm::fs::OpenAtmosphereSdFile(&this->datalog_file, tmp_path, FsOpenMode_Read | FsOpenMode_Write | FsOpenMode_Append); 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_ready = R_SUCCEEDED(rc);
} }
this->datalog_pos = 0; this->datalog_pos = 0;
/* Setup the btsnoop header. */
struct { struct {
char id[8]; char id[8];
u32 version; u32 version;
@ -89,26 +97,18 @@ namespace ams::mitm::uart {
ams::util::StoreBigEndian(&btsnoop_header.version, version); ams::util::StoreBigEndian(&btsnoop_header.version, version);
ams::util::StoreBigEndian(&btsnoop_header.datalink_type, datalink_type); ams::util::StoreBigEndian(&btsnoop_header.datalink_type, datalink_type);
/* Enable data-logging, required for WriteLog() to write anything. */
this->data_logging_enabled = true; this->data_logging_enabled = true;
/* Write the btsnoop header to the datalog. */
this->WriteLog(&btsnoop_header, sizeof(btsnoop_header)); this->WriteLog(&btsnoop_header, sizeof(btsnoop_header));
/* This will be re-enabled by WriteUartData once a certain command is detected. */ /* 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. */ /* 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; this->data_logging_enabled = false;
} }
void UartPortService::SaveFile(const char *path, const void* buffer, size_t size) { /* Append the specified string to the text cmd_log file. */
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);
}
void UartPortService::WriteCmdLog(const char *str) { void UartPortService::WriteCmdLog(const char *str) {
Result rc=0; Result rc=0;
FsFile file={}; FsFile file={};
@ -125,7 +125,9 @@ namespace ams::mitm::uart {
fsFileClose(&file); fsFileClose(&file);
} }
/* Append the specified data to the datalog file. */
void UartPortService::WriteLog(const void* buffer, size_t size) { 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 (this->data_logging_enabled && this->datalog_ready) {
if (R_SUCCEEDED(fsFileWrite(&this->datalog_file, this->datalog_pos, buffer, size, FsWriteOption_None))) { if (R_SUCCEEDED(fsFileWrite(&this->datalog_file, this->datalog_pos, buffer, size, FsWriteOption_None))) {
this->datalog_pos += size; 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) { void UartPortService::WriteLogPacket(bool dir, const void* buffer, size_t size) {
struct { struct {
u32 original_length; u32 original_length;
@ -150,13 +154,20 @@ namespace ams::mitm::uart {
ams::util::StoreBigEndian(&pkt_hdr.included_length, static_cast<u32>(size)); ams::util::StoreBigEndian(&pkt_hdr.included_length, static_cast<u32>(size));
ams::util::StoreBigEndian(&pkt_hdr.packet_flags, flags); 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(&pkt_hdr, sizeof(pkt_hdr));
this->WriteLog(buffer, size); 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) { 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; 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; 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) { if (size && *cache_pos + size <= this->CacheBufferSize) {
struct { struct {
u8 opcode[0x2]; u8 opcode[0x2];
@ -189,54 +200,64 @@ namespace ams::mitm::uart {
} *hci_iso_data = reinterpret_cast<decltype(hci_iso_data)>(&cache_buffer[0x1]); } *hci_iso_data = reinterpret_cast<decltype(hci_iso_data)>(&cache_buffer[0x1]);
static_assert(sizeof(*hci_iso_data) == 0x4); 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); std::memcpy(&cache_buffer[*cache_pos], buffer, size);
(*cache_pos)+= size; (*cache_pos)+= size;
/* Process the packets in the cache. */
do { do {
size_t orig_pkt_len = 0x0; size_t orig_pkt_len = 0x0;
size_t pkt_len = 0x1; 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)) { if (*cache_pos >= 0x1+sizeof(*hci_cmd)) {
orig_pkt_len = sizeof(*hci_cmd) + hci_cmd->param_len; 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) { if (!this->data_logging_enabled && hci_cmd->opcode[1] == 0xFC && hci_cmd->opcode[0] == 0x16) {
this->data_logging_enabled = true; 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)) { if (*cache_pos >= 0x1+sizeof(*hci_acl_data)) {
orig_pkt_len = sizeof(*hci_acl_data) + hci_acl_data->data_len; 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)) { if (*cache_pos >= 0x1+sizeof(*hci_sco_data)) {
orig_pkt_len = sizeof(*hci_sco_data) + hci_sco_data->data_len; 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)) { if (*cache_pos >= 0x1+sizeof(*hci_event)) {
orig_pkt_len = sizeof(*hci_event) + hci_event->param_len; 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)) { if (*cache_pos >= 0x1+sizeof(*hci_iso_data)) {
orig_pkt_len = sizeof(*hci_iso_data) + hci_iso_data->data_load_len; orig_pkt_len = sizeof(*hci_iso_data) + hci_iso_data->data_load_len;
} }
} }
else { else { /* Unknown HCI packet */
char str[256]; 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]); 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); this->WriteCmdLog(str);
*cache_pos = 0; *cache_pos = 0;
} }
/* If a full packet is available in the cache, update pkt_len. */
if (orig_pkt_len) { if (orig_pkt_len) {
if (*cache_pos >= 0x1+orig_pkt_len) { if (*cache_pos >= 0x1+orig_pkt_len) {
pkt_len+= orig_pkt_len; pkt_len+= orig_pkt_len;
} }
} }
/* If a packet is available, log it and update the cache. */
if (pkt_len>0x1) { if (pkt_len>0x1) {
this->WriteLogPacket(dir, cache_buffer, pkt_len); this->WriteLogPacket(dir, cache_buffer, pkt_len);
(*cache_pos)-= pkt_len; (*cache_pos)-= pkt_len;
@ -244,11 +265,13 @@ namespace ams::mitm::uart {
std::memmove(cache_buffer, &cache_buffer[pkt_len], *cache_pos); std::memmove(cache_buffer, &cache_buffer[pkt_len], *cache_pos);
} }
} }
/* Otherwise, exit the loop. */
else break; else break;
} while(*cache_pos); } while(*cache_pos);
} }
} }
/* Forward OpenPort and write to the cmd_log. */
Result UartPortService::OpenPort(sf::Out<bool> 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 UartPortService::OpenPort(sf::Out<bool> 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<bool *>(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); Result rc = uartPortSessionOpenPortFwd(this->srv.get(), reinterpret_cast<bool *>(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()); svcCloseHandle(send_handle.GetValue());
@ -260,6 +283,7 @@ namespace ams::mitm::uart {
return rc; return rc;
} }
/* Forward OpenPortForDev and write to the cmd_log. */
Result UartPortService::OpenPortForDev(sf::Out<bool> 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 UartPortService::OpenPortForDev(sf::Out<bool> 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<bool *>(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); Result rc = uartPortSessionOpenPortForDevFwd(this->srv.get(), reinterpret_cast<bool *>(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()); svcCloseHandle(send_handle.GetValue());
@ -271,6 +295,7 @@ namespace ams::mitm::uart {
return rc; return rc;
} }
/* Forward GetWritableLength and write to the cmd_log. */
Result UartPortService::GetWritableLength(sf::Out<u64> out) { Result UartPortService::GetWritableLength(sf::Out<u64> out) {
Result rc = uartPortSessionGetWritableLength(this->srv.get(), reinterpret_cast<u64 *>(out.GetPointer())); Result rc = uartPortSessionGetWritableLength(this->srv.get(), reinterpret_cast<u64 *>(out.GetPointer()));
@ -281,6 +306,7 @@ namespace ams::mitm::uart {
return rc; return rc;
} }
/* Forward Send and log the data if the out_size is non-zero. */
Result UartPortService::Send(sf::Out<u64> out_size, const sf::InAutoSelectBuffer &data) { Result UartPortService::Send(sf::Out<u64> out_size, const sf::InAutoSelectBuffer &data) {
Result rc = uartPortSessionSend(this->srv.get(), data.GetPointer(), data.GetSize(), reinterpret_cast<u64 *>(out_size.GetPointer())); Result rc = uartPortSessionSend(this->srv.get(), data.GetPointer(), data.GetSize(), reinterpret_cast<u64 *>(out_size.GetPointer()));
@ -290,16 +316,18 @@ namespace ams::mitm::uart {
return rc; return rc;
} }
/* Forward GetReadableLength and write to the cmd_log. */
Result UartPortService::GetReadableLength(sf::Out<u64> out) { Result UartPortService::GetReadableLength(sf::Out<u64> out) {
Result rc = uartPortSessionGetReadableLength(this->srv.get(), reinterpret_cast<u64 *>(out.GetPointer())); Result rc = uartPortSessionGetReadableLength(this->srv.get(), reinterpret_cast<u64 *>(out.GetPointer()));
char str[256]; 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); this->WriteCmdLog(str);
return rc; return rc;
} }
/* Forward Receive and log the data if the out_size is non-zero. */
Result UartPortService::Receive(sf::Out<u64> out_size, const sf::OutAutoSelectBuffer &data) { Result UartPortService::Receive(sf::Out<u64> out_size, const sf::OutAutoSelectBuffer &data) {
Result rc = uartPortSessionReceive(this->srv.get(), data.GetPointer(), data.GetSize(), reinterpret_cast<u64 *>(out_size.GetPointer())); Result rc = uartPortSessionReceive(this->srv.get(), data.GetPointer(), data.GetSize(), reinterpret_cast<u64 *>(out_size.GetPointer()));
@ -309,6 +337,7 @@ namespace ams::mitm::uart {
return rc; return rc;
} }
/* Forward BindPortEvent and write to the cmd_log. */
Result UartPortService::BindPortEvent(sf::Out<bool> out, sf::OutCopyHandle out_event_handle, UartPortEventType port_event_type, s64 threshold) { Result UartPortService::BindPortEvent(sf::Out<bool> out, sf::OutCopyHandle out_event_handle, UartPortEventType port_event_type, s64 threshold) {
Result rc = uartPortSessionBindPortEventFwd(this->srv.get(), port_event_type, threshold, reinterpret_cast<bool *>(out.GetPointer()), out_event_handle.GetHandlePointer()); Result rc = uartPortSessionBindPortEventFwd(this->srv.get(), port_event_type, threshold, reinterpret_cast<bool *>(out.GetPointer()), out_event_handle.GetHandlePointer());
@ -318,6 +347,7 @@ namespace ams::mitm::uart {
return rc; return rc;
} }
/* Forward UnbindPortEvent and write to the cmd_log. */
Result UartPortService::UnbindPortEvent(sf::Out<bool> out, UartPortEventType port_event_type) { Result UartPortService::UnbindPortEvent(sf::Out<bool> out, UartPortEventType port_event_type) {
Result rc = uartPortSessionUnbindPortEvent(this->srv.get(), port_event_type, reinterpret_cast<bool *>(out.GetPointer())); Result rc = uartPortSessionUnbindPortEvent(this->srv.get(), port_event_type, reinterpret_cast<bool *>(out.GetPointer()));

View file

@ -64,7 +64,6 @@ namespace ams::mitm::uart {
size_t receive_cache_pos; size_t receive_cache_pos;
bool TryGetCurrentTimestamp(u64 *out); bool TryGetCurrentTimestamp(u64 *out);
void SaveFile(const char *path, const void* buffer, size_t size);
void WriteCmdLog(const char *str); void WriteCmdLog(const char *str);
void WriteLog(const void* buffer, size_t size); void WriteLog(const void* buffer, size_t size);
void WriteLogPacket(bool dir, const void* buffer, size_t size); void WriteLogPacket(bool dir, const void* buffer, size_t size);