Skip to content

Instantly share code, notes, and snippets.

@edubart
Created November 20, 2025 13:19
Show Gist options
  • Select an option

  • Save edubart/21c04097af49b5ec3961ee5a38e4b2da to your computer and use it in GitHub Desktop.

Select an option

Save edubart/21c04097af49b5ec3961ee5a38e4b2da to your computer and use it in GitHub Desktop.
local cartesi = require("cartesi")
local jsonrpc = require("cartesi.jsonrpc")
local poll = require("posix.poll")
local unistd = require("posix.unistd")
local termio = require("posix.termio")
local fcntl = require("posix.fcntl")
-- set terminal to raw mode
local ttyname = assert(unistd.ttyname())
local tty_fd = assert(fcntl.open(ttyname, fcntl.O_RDWR | fcntl.O_NOCTTY | fcntl.O_NONBLOCK))
local tty_size = assert(termio.tcgetwinsize(tty_fd))
local tty_old_mode = assert(termio.tcgetattr(tty_fd))
local tty_raw_mode = {
lflag = tty_old_mode.lflag & ~(termio.ECHO | termio.ICANON | termio.ECHONL | termio.ISIG | termio.IEXTEN),
iflag = tty_old_mode.iflag
& ~(
termio.IGNBRK
| termio.BRKINT
| termio.PARMRK
| termio.ICRNL
| termio.ISTRIP
| termio.INLCR
| termio.IGNCR
| termio.IXON
),
cflag = (tty_old_mode.cflag & ~(termio.CSIZE | termio.PARENB)) | termio.CS8,
oflag = tty_old_mode.oflag | termio.OPOST,
cc = {
[termio.VTIME] = 0,
[termio.VMIN] = 1,
},
}
assert(termio.tcsetattr(tty_fd, termio.TCSANOW, tty_raw_mode))
local _ = setmetatable({}, {
__gc = function() -- reset terminal on exit
termio.tcsetattr(tty_fd, termio.TCSANOW, tty_old_mode)
unistd.close(tty_fd)
end,
})
-- interactive machine config with VirtIO console
local config = {
ram = {
length = 128 * 1024 * 1024,
backing_store = {
data_filename = os.getenv("CARTESI_IMAGES_PATH") .. "/linux.bin",
},
},
dtb = {
bootargs = cartesi.machine:get_default_config().dtb.bootargs:gsub("console=hvc0", "console=hvc1"),
entrypoint = "bash",
},
flash_drive = {
{
backing_store = {
data_filename = os.getenv("CARTESI_IMAGES_PATH") .. "/rootfs.ext2",
},
},
},
virtio = {
{ type = "console" },
},
processor = {
registers = {
iunrep = 1,
htif = {
iconsole = cartesi.HTIF_CONSOLE_CMD_PUTCHAR_MASK | cartesi.HTIF_CONSOLE_CMD_GETCHAR_MASK,
},
},
},
}
-- machine runtime config will console buffering mode
local runtime_config = {
console = {
output_destination = "to_buffer",
output_flush_mode = "every_char",
input_source = "from_buffer",
tty_rows = tty_size.ws_row,
tty_cols = tty_size.ws_col,
},
}
local machine <close> = jsonrpc.spawn_server():set_cleanup_call(jsonrpc.SHUTDOWN):create(config, runtime_config)
-- To do use an existing server:
-- local machine <close> = jsonrpc.connect_server("127.0.0.1:8888"):set_cleanup_call(jsonrpc.DESTROY):create(config, runtime_config)
-- Main loop
repeat
local break_reason = machine:run()
if break_reason == cartesi.BREAK_REASON_CONSOLE_INPUT then -- waiting for input
if poll.rpoll(unistd.STDIN_FILENO, 0) ~= 0 then -- stdin has input characerters ready
local avail_len = machine:write_console_input()
local data = unistd.read(unistd.STDIN_FILENO, avail_len)
if data then
machine:write_console_input(data)
else
local EOF_CHAR = "\x04"
machine:write_console_input(string.rep(EOF_CHAR, avail_len))
end
end
elseif break_reason == cartesi.BREAK_REASON_CONSOLE_OUTPUT then
unistd.write(unistd.STDOUT_FILENO, machine:read_console_output())
end
until break_reason == cartesi.BREAK_REASON_HALTED
print("Halted")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment