Skip to content

Commit

Permalink
feat!: introduce machine init and entrypoint config and options
Browse files Browse the repository at this point in the history
  • Loading branch information
edubart committed Oct 6, 2023
1 parent 48be7e3 commit 259282d
Show file tree
Hide file tree
Showing 13 changed files with 199 additions and 17 deletions.
2 changes: 1 addition & 1 deletion lib/grpc-interfaces
166 changes: 151 additions & 15 deletions src/cartesi-machine.lua
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ where options are:
start:<number>
length:<number>
shared
mount:<string>
user:<string>
label (mandatory)
identifies the flash drive. init attempts to mount it as /mnt/<label>.
Expand All @@ -119,6 +121,17 @@ where options are:
target modifications to flash drive modify image file as well.
by default, image files are not modified and changes are lost.
mount (optional)
whether the flash drive should be mounted automatically in init.
by default, the drive is mounted if there is an image file backing it,
you can use "mount:false" to disables auto mounting,
you can also use "mount:<path>" to choose a custom mount point.
user (optional)
changes the user ownership of the mounted directory when mount is true,
otherwise changes the user ownership of the respective /dev/pmemX device,
this option is useful to allow dapp's user access the flash drive.
(an option "--flash-drive=label:root,filename:rootfs.ext2" is implicit)
--replace-flash-drive=<key>:<value>[,<key>:<value>[,...]...]
Expand Down Expand Up @@ -341,6 +354,25 @@ where options are:
suppress cartesi-machine.lua output.
exceptions: --initial-hash, --final-hash and text emitted from the target.
--no-init-splash
don't show cartesi machine splash on boot.
--append-init=<string>
append a command to machine's init script to be executed with root privilege,
the command is executed on boot after mounting flash drives and before running the entrypoint,
you can pass this option multiple times.
--append-init-script=<filename>
like --append-init, but use contents from a script file.
--append-entrypoint=<string>
append a command to machine's entrypoint script to be executed with dapp privilege,
the command is executed after the machine is initialized and before the final entrypoint command,
you can pass this option multiple times.
--append-entrypoint-script=<filename>
like --append-entrypoint, but use contents from a script file.
--gdb[=<address>]
listen at <address> and wait for a GDB connection to debug the machine.
If <address> is omitted, '127.0.0.1:1234' is used by default.
Expand Down Expand Up @@ -395,6 +427,8 @@ local images_path = adjust_images_path(os.getenv("CARTESI_IMAGES_PATH"))
local flash_image_filename = { root = images_path .. "rootfs.ext2" }
local flash_label_order = { "root" }
local flash_shared = {}
local flash_mount = {}
local flash_user = {}
local flash_start = {}
local flash_length = {}
local memory_range_replace = {}
Expand All @@ -403,6 +437,9 @@ local ram_length = 64 << 20
local dtb_image_filename = nil
local dtb_bootargs = "console=hvc0 rootfstype=ext2 root=/dev/pmem0 rw quiet \z
swiotlb=noforce init=/opt/cartesi/bin/init"
local init_splash = true
local append_init = ""
local append_entrypoint = ""
local rollup
local uarch
local rollup_advance
Expand Down Expand Up @@ -434,7 +471,6 @@ local store_config = false
local load_config = false
local gdb_address
local exec_arguments = {}
local quiet = false
local assert_rolling_template = false

local function parse_memory_range(opts, what, all)
Expand Down Expand Up @@ -645,6 +681,8 @@ local options = {
label = true,
filename = true,
shared = true,
mount = true,
user = true,
length = true,
start = true,
})
Expand All @@ -653,6 +691,18 @@ local options = {
f.filename = nil
if f.image_filename == true then f.image_filename = "" end
assert(not f.shared or f.shared == true, "invalid flash drive shared value in " .. all)
if f.mount == nil then
-- mount only if there is a file backing
if f.image_filename and f.image_filename ~= "" then
f.mount = "/mnt/" .. f.label
else
f.mount = false
end
elseif f.mount == "true" then
f.mount = "/mnt/" .. f.label
elseif f.mount == "false" then
f.mount = false
end
if f.start then f.start = assert(util.parse_number(f.start), "invalid flash drive start in " .. all) end
if f.length then f.length = assert(util.parse_number(f.length), "invalid flash drive length in " .. all) end
local d = f.label
Expand All @@ -664,6 +714,8 @@ local options = {
flash_start[d] = f.start or flash_start[d]
flash_length[d] = f.length or flash_length[d]
flash_shared[d] = f.shared or flash_shared[d]
flash_mount[d] = f.mount or flash_mount[d]
flash_user[d] = f.user or flash_user[d]
return true
end,
},
Expand Down Expand Up @@ -849,7 +901,6 @@ local options = {
function(all)
if not all then return false end
stderr = function() end
quiet = true
return true
end,
},
Expand Down Expand Up @@ -1056,6 +1107,52 @@ local options = {
return true
end,
},
{
"^%-%-no%-init%-splash$",
function(all)
if not all then return false end
init_splash = false
return true
end,
},
{
"^%-%-append%-init%=(.*)$",
function(o)
if not o or #o < 1 then return false end
append_init = append_init .. o .. "\n"
return true
end,
},
{
"^%-%-append%-init%-script%=(.*)$",
function(o)
if not o or #o < 1 then return false end
local f <close> = assert(io.open(o, "rb"))
local contents = assert(f:read("*a"))
if not contents:find("\n$") then contents = contents .. "\n" end
append_init = append_init .. contents
return true
end,
},
{
"^%-%-append%-entrypoint%=(.*)$",
function(o)
if not o or #o < 1 then return false end
append_entrypoint = append_entrypoint .. o .. "\n"
return true
end,
},
{
"^%-%-append%-entrypoint%-script%=(.*)$",
function(o)
if not o or #o < 1 then return false end
local f <close> = assert(io.open(o, "rb"))
local contents = assert(f:read("*a"))
if not contents:find("\n$") then contents = contents .. "\n" end
append_entrypoint = append_entrypoint .. contents
return true
end,
},
{
"^%-%-gdb(%=?)(.*)$",
function(o, address)
Expand Down Expand Up @@ -1168,6 +1265,10 @@ local function store_machine_config(config, output)
comment_default(dtb.image_filename, def.dtb.image_filename)
output(" bootargs = %q,", dtb.bootargs or def.dtb.bootargs)
comment_default(dtb.bootargs, def.dtb.bootargs)
output(" init = %q,", dtb.init or def.dtb.init)
comment_default(dtb.init, def.dtb.init)
output(" entrypoint = %q,", dtb.entrypoint or def.dtb.entrypoint)
comment_default(dtb.entrypoint, def.dtb.entrypoint)
output(" },\n")
local tlb = config.tlb or {}
output(" tlb = {\n")
Expand Down Expand Up @@ -1277,14 +1378,6 @@ local function dump_value_proofs(machine, desired_proofs, has_htif_console_getch
end
end

local function append(a, b)
a = a or ""
b = b or ""
if a == "" then return b end
if b == "" then return a end
return a .. " " .. b
end

local function create_machine(config_or_dir, runtime)
if remote then return remote.machine(config_or_dir, runtime) end
return cartesi.machine(config_or_dir, runtime)
Expand Down Expand Up @@ -1344,6 +1437,8 @@ else
dtb = {
image_filename = dtb_image_filename,
bootargs = dtb_bootargs,
init = "",
entrypoint = "",
},
ram = {
image_filename = ram_image_filename,
Expand All @@ -1358,20 +1453,61 @@ else
uarch = uarch,
flash_drive = {},
}

-- show splash on init
if init_splash then
config.dtb.init = config.dtb.init
.. ([[
echo "
.
/ \
/ \
\---/---\ /----\
\ X \
\----/ \---/---\
\ / CARTESI
\ / MACHINE
'
"
]]):gsub("\\", "\\\\")
end

for _, label in ipairs(flash_label_order) do
local devname = "pmem" .. #config.flash_drive
config.flash_drive[#config.flash_drive + 1] = {
image_filename = flash_image_filename[label],
shared = flash_shared[label],
start = flash_start[label],
length = flash_length[label] or -1,
}
-- auto mount
local mount = flash_mount[label]
local chownpath = "/dev/" .. devname
if label ~= "root" and mount then
local cmd = ([[busybox mkdir -p "MOUNT" && busybox mount /dev/DEVNAME "MOUNT"]])
:gsub("MOUNT", mount)
:gsub("DEVNAME", devname)
config.dtb.init = config.dtb.init .. cmd .. "\n"
chownpath = mount
end
-- change permission
local user = flash_user[label]
if label ~= "root" and user then
local cmd = ("busybox chown USER: PATH"):gsub("USER", user or ""):gsub("PATH", chownpath)
config.dtb.init = config.dtb.init .. cmd .. "\n"
end
do -- create a map of the label in /run/drive-label for flashdrive tool
local cmd = ([[busybox mkdir -p /run/drive-label && echo "LABEL" > /run/drive-label/DEVNAME]])
:gsub("LABEL", label)
:gsub("DEVNAME", devname)
config.dtb.init = config.dtb.init .. cmd .. "\n"
end
end

config.dtb.bootargs = append(append(config.dtb.bootargs, append_dtb_bootargs), quiet and " splash=no" or "")

if #exec_arguments > 0 then
config.dtb.bootargs = append(config.dtb.bootargs, "-- " .. table.concat(exec_arguments, " "))
end
if #append_dtb_bootargs > 0 then config.dtb.bootargs = config.dtb.bootargs .. " " .. append_dtb_bootargs end
if #append_init > 0 then config.dtb.init = config.dtb.init .. append_init end
if #append_entrypoint > 0 then config.dtb.entrypoint = config.dtb.entrypoint .. append_entrypoint end
if #exec_arguments > 0 then config.dtb.entrypoint = config.dtb.entrypoint .. table.concat(exec_arguments, " ") end

if load_config then
local env = {}
Expand Down
8 changes: 8 additions & 0 deletions src/clua-machine-util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,12 @@ static void push_cm_dtb_config(lua_State *L, const cm_dtb_config *r) {
if (r->bootargs != nullptr) {
clua_setstringfield(L, r->bootargs, "bootargs", -1);
}
if (r->init != nullptr) {
clua_setstringfield(L, r->init, "init", -1);
}
if (r->entrypoint != nullptr) {
clua_setstringfield(L, r->entrypoint, "entrypoint", -1);
}
if (r->image_filename != nullptr) {
clua_setstringfield(L, r->image_filename, "image_filename", -1);
}
Expand Down Expand Up @@ -952,6 +958,8 @@ static void check_cm_dtb_config(lua_State *L, int tabidx, cm_dtb_config *r) {
}
r->image_filename = opt_copy_string_field(L, -1, "image_filename");
r->bootargs = opt_copy_string_field(L, -1, "bootargs");
r->init = opt_copy_string_field(L, -1, "init");
r->entrypoint = opt_copy_string_field(L, -1, "entrypoint");
lua_pop(L, 1);
}

Expand Down
2 changes: 2 additions & 0 deletions src/dtb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ void dtb_init(const machine_config &c, unsigned char *dtb_start, uint64_t dtb_le
{ // cartesi-machine
fdt.begin_node("cartesi-machine");
fdt.prop_string("version", CM_VERSION);
fdt.prop_string_data("init", c.dtb.init);
fdt.prop_string_data("entrypoint", c.dtb.entrypoint);
fdt.end_node();
}

Expand Down
5 changes: 5 additions & 0 deletions src/fdt-builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,11 @@ class FDTBuilder {
prop(name, reinterpret_cast<const uint8_t *>(v.c_str()), v.length() + 1);
}

void prop_string_data(const std::string &name, const std::string &v) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
prop(name, reinterpret_cast<const uint8_t *>(v.c_str()), v.length());
}

template <uint32_t N>
void prop_u32_list(const std::string &name, const std::array<uint32_t, N> &vs) {
put_u32(FDT_PROP);
Expand Down
4 changes: 4 additions & 0 deletions src/json-util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -787,6 +787,8 @@ void ju_get_opt_field(const nlohmann::json &j, const K &key, dtb_config &value,
const auto &jconfig = j[key];
const auto new_path = path + to_string(key) + "/";
ju_get_opt_field(jconfig, "bootargs"s, value.bootargs, new_path);
ju_get_opt_field(jconfig, "init"s, value.init, new_path);
ju_get_opt_field(jconfig, "entrypoint"s, value.entrypoint, new_path);
ju_get_opt_field(jconfig, "image_filename"s, value.image_filename, new_path);
}

Expand Down Expand Up @@ -1129,6 +1131,8 @@ void to_json(nlohmann::json &j, const ram_config &config) {
void to_json(nlohmann::json &j, const dtb_config &config) {
j = nlohmann::json{
{"bootargs", config.bootargs},
{"init", config.init},
{"entrypoint", config.entrypoint},
{"image_filename", config.image_filename},
};
}
Expand Down
6 changes: 6 additions & 0 deletions src/jsonrpc-discover.json
Original file line number Diff line number Diff line change
Expand Up @@ -1458,6 +1458,12 @@
"bootargs": {
"type": "string"
},
"init": {
"type": "string"
},
"entrypoint": {
"type": "string"
},
"image_filename": {
"type": "string"
}
Expand Down
6 changes: 6 additions & 0 deletions src/machine-c-api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,13 +190,17 @@ static cm_ram_config convert_to_c(const cartesi::ram_config &cpp_config) {
static cartesi::dtb_config convert_from_c(const cm_dtb_config *c_config) {
cartesi::dtb_config new_cpp_dtb_config{};
new_cpp_dtb_config.bootargs = null_to_empty(c_config->bootargs);
new_cpp_dtb_config.init = null_to_empty(c_config->init);
new_cpp_dtb_config.entrypoint = null_to_empty(c_config->entrypoint);
new_cpp_dtb_config.image_filename = null_to_empty(c_config->image_filename);
return new_cpp_dtb_config;
}

static cm_dtb_config convert_to_c(const cartesi::dtb_config &cpp_config) {
cm_dtb_config new_c_dtb_config{};
new_c_dtb_config.bootargs = convert_to_c(cpp_config.bootargs);
new_c_dtb_config.init = convert_to_c(cpp_config.init);
new_c_dtb_config.entrypoint = convert_to_c(cpp_config.entrypoint);
new_c_dtb_config.image_filename = convert_to_c(cpp_config.image_filename);
return new_c_dtb_config;
}
Expand Down Expand Up @@ -704,6 +708,8 @@ void cm_delete_machine_config(const cm_machine_config *config) {
delete[] config->flash_drive.entry;
delete[] config->dtb.image_filename;
delete[] config->dtb.bootargs;
delete[] config->dtb.init;
delete[] config->dtb.entrypoint;
delete[] config->ram.image_filename;
delete[] config->tlb.image_filename;
delete[] config->rollup.rx_buffer.image_filename;
Expand Down
2 changes: 2 additions & 0 deletions src/machine-c-api.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ typedef struct { // NOLINT(modernize-use-using)
/// \brief DTB state configuration
typedef struct { // NOLINT(modernize-use-using)
const char *bootargs; ///< Bootargs to pass to kernel
const char *init; ///< Initialization commands to be executed as root on boot
const char *entrypoint; ///< Commands to execute the main application
const char *image_filename; ///< ROM image file
} cm_dtb_config;

Expand Down
Loading

0 comments on commit 259282d

Please sign in to comment.