Add very simple "network port UART" component to Renode. Change-Id: I74c61847d25f26e4534cb410b9a943467bb4b71c
diff --git a/platforms/secure.repl b/platforms/secure.repl index 2cbb2fe..68705f2 100644 --- a/platforms/secure.repl +++ b/platforms/secure.repl
@@ -95,6 +95,11 @@ // PATGEN [‘h400E_0000 - ‘h400E_0FFF) 4KB PATGEN +// Fake network-port-backed UART for testing in Renode +net_uart: NetUart @ sysbus 0x400F0000 + name: "NetUart" + port: 31415 + // RV_TIMER [‘h4010_0000 - ‘h4010_0FFF) 4KB RV Timer for Security Core timer: Timers.OpenTitan_Timer@ sysbus 0x40100000 frequency: 24000000
diff --git a/shodan.resc b/shodan.resc index d2bfb53..4c49ea7 100644 --- a/shodan.resc +++ b/shodan.resc
@@ -14,6 +14,7 @@ include @sim/config/shodan_infrastructure/Mailbox.cs include @sim/renode/tools/sel4_extensions/seL4Extensions.cs include @sim/config/shodan_infrastructure/AddressRangeStub.cs +include @sim/config/shodan_infrastructure/NetUart.cs machine LoadPlatformDescription @sim/config/platforms/shodan.repl
diff --git a/shodan_infrastructure/NetUart.cs b/shodan_infrastructure/NetUart.cs new file mode 100644 index 0000000..d557345 --- /dev/null +++ b/shodan_infrastructure/NetUart.cs
@@ -0,0 +1,115 @@ +// +// Copyright (c) 2021 Google LLC +// +// This file is licensed under the MIT License. +// Full license text is available in 'licenses/MIT.txt'. +// +using Antmicro.Renode.Core; +using Antmicro.Renode.Logging; +using Antmicro.Renode.Peripherals.Bus; + +using System; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using System.Collections.Concurrent; + +// This is a very simple Renode periperal that provides a byte-oriented +// communication port to the simulated SOC that's backed by a network port on +// the host workstation. The port is intended for debugging only - it has no +// real flow control, no interrupts, no error checking - but it should be around +// 5x faster than using a real UART model to communicate with your SOC. +// +// Add this to your SOC .repl file: +// +// net_uart: NetUart @ sysbus <base_address> +// name: "NetUart" +// port: <network_port> +// +// Communicate with the port in your firmware like this: +// +// struct NetUart { +// uint32_t avail; +// uint32_t read; +// uint32_t write; +// }; +// volatile NetUart* net_uart = reinterpret_cast<NetUart*>(base_address); +// +// uint8_t get_byte() { +// while (!net_uart->avail) {} +// return net_uart->read; +// }; +// +// void set_byte(uint8_t b) { +// net_uart->write = b; +// }; +// +// And then you can run "telnet localhost <network_port>" on your workstation to +// communicate with your SOC. +namespace Antmicro.Renode.Peripherals +{ + public class NetUart : IDoubleWordPeripheral, IKnownSize + { + public long Size => 0x12; + + TcpListener listener = null; + Socket client = null; + byte[] buffer = null; + Thread accept_thread; + string name; + + public NetUart(string name, int port) { + this.name = name; + + listener = new TcpListener(port); + listener.Start(); + + this.Log(LogLevel.Info, "NetUart '{0}' starting at {1}", name, listener.LocalEndpoint); + + buffer = new byte[4096]; + accept_thread = new Thread(Accept); + accept_thread.Start(); + } + + public void Accept() { + while(true) { + Socket new_client = listener.AcceptSocket(); + this.Log(LogLevel.Info, "NetUart '{0}' got connection from {1}", name, new_client.RemoteEndPoint); + lock (this) { + client = new_client; + } + } + } + + public void Reset() { + } + + public uint ReadDoubleWord(long offset) { + lock(this) { + if (client == null) { + return 0; + } + else if (offset == 0) { + return (uint)client.Available; + } + else if (offset == 4 && client.Available > 0) { + client.Receive(buffer, 1, 0); + return buffer[0]; + } + else { + return 0; + } + } + } + + public void WriteDoubleWord(long offset, uint value) { + lock(this) { + if (client != null && offset == 8) { + buffer[0] = (byte)value; + client.Send(buffer, 1, 0); + } + } + } + } +}