fxos/shell/v.cpp

213 lines
5.5 KiB
C++

#include "shell.h"
#include "theme.h"
#include "parser.h"
#include "commands.h"
#include "errors.h"
#include <fmt/core.h>
#include <fmt/color.h>
#include <fxos/memory.h>
using namespace FxOS;
//---
// vl
//---
static std::vector<std::string> parse_vl(Session &, Parser &parser)
{
std::vector<std::string> spaces;
while(!parser.at_end())
spaces.push_back(parser.symbol("vspace_name"));
parser.end();
return spaces;
}
static void show_vspace(std::string name, VirtualSpace &s, Session &session)
{
bool is_current = (&s == session.current_space);
int total_claim_size = 0;
for(Claim const &c: s.disasm.claims)
total_claim_size += c.size;
if(is_current)
fmt::print("* ");
fmt::print(theme(11), "{}\n", name);
fmt::print(" Symbol table: {} symbols\n", s.symbols.symbols.size());
fmt::print(
" Main disassembly: {} instructions\n", s.disasm.instructions.size());
fmt::print(" Functions: {}\n", s.disasm.functions.size());
fmt::print(" Claims: {} (totalling {} bytes)\n", s.disasm.claims.size(),
total_claim_size);
fmt::print(" Region--Start---------End---------File------------------\n");
if(s.bindings.size() == 0) {
fmt::print(" (no bindings)\n");
return;
}
for(auto &b: s.bindings) {
MemoryRegion const *ref = MemoryRegion::region_for(b.region);
fmt::print(" {:<7s} 0x{:08x} .. 0x{:08x}", (ref ? ref->name : ""),
b.region.start, b.region.end);
if(b.buffer.path != "")
fmt::print(" {}", b.buffer.path);
fmt::print("\n");
}
}
void _vl(Session &session, std::vector<std::string> const &args)
{
if(!args.size()) {
for(auto &it: session.spaces)
show_vspace(it.first, *it.second, session);
}
else
for(auto &name: args) {
VirtualSpace *s = session.get_space(name);
if(s != nullptr)
show_vspace(name, *session.spaces[name], session);
else
fmt::print("Virtual space '{}' does not exist", name);
}
}
//---
// vs
//---
static std::string parse_vs(Session &, Parser &parser)
{
std::string name = parser.symbol("vspace_name");
parser.end();
return name;
}
void _vs(Session &session, std::string const &name)
{
VirtualSpace *s = session.get_space(name);
if(!s)
return;
session.current_space = session.spaces[name].get();
}
//---
// vc
//---
static std::string parse_vc(Session &, Parser &parser)
{
std::string name = "";
if(!parser.at_end())
name = parser.symbol();
parser.end();
return name;
}
void _vc(Session &session, std::string name)
{
if(name == "")
name = session.generate_space_name("space", true);
else
name = session.generate_space_name(name, false);
/* Create an empty space and select it */
std::unique_ptr<VirtualSpace> space = std::make_unique<VirtualSpace>();
session.spaces.emplace(name, std::move(space));
_vs(session, name);
_g(session, 0x80000000);
}
//---
// vm
//---
struct _vm_args
{
std::string path;
std::vector<MemoryRegion> regions;
};
static _vm_args parse_vm(Session &session, Parser &parser)
{
_vm_args args {};
args.path = parser.str();
/* TODO: vm: Allow specifying address without a size */
do
args.regions.push_back(parser.region(session.current_space));
while(!parser.at_end());
parser.end();
return args;
}
void _vm(Session &session, std::string file, std::vector<MemoryRegion> regions)
{
if(!session.current_space)
return;
std::string path = session.file(file);
Buffer contents(path);
/* If no files are loaded yet, set the PC to the first loaded region */
if(!session.current_space->bindings.size())
session.pc = regions[0].start;
for(auto &r: regions)
session.current_space->bind_region(r, contents);
}
//---
// Command registration
//---
static ShellCommand _vl_cmd(
"vl", [](Session &s, Parser &p) { _vl(s, parse_vl(s, p)); },
[](Session &s, Parser &p) { parse_vl(s, p); }, "Virtual space List", R"(
vl [<space_name>...]
Shows the bound regions of each specified virtual space. If none is specified,
shows all the virtual spaces.
)");
static ShellCommand _vs_cmd(
"vs", [](Session &s, Parser &p) { _vs(s, parse_vs(s, p)); },
[](Session &s, Parser &p) { parse_vs(s, p); }, "Virtual space Select", R"(
vs <space_name>
Selects the specified virtual space.
)");
static ShellCommand _vc_cmd(
"vc", [](Session &s, Parser &p) { _vc(s, parse_vc(s, p)); },
[](Session &s, Parser &p) { parse_vc(s, p); }, "Virtual space Create", R"(
vc [<name>]
Creates a new virtual space under the specified name. If such a space already
exists, adds a numerical suffix like _0 until a fresh name is found. The space
is created with no bindings and automatically selected.
)");
static ShellCommand _vm_cmd(
"vm",
[](Session &s, Parser &p) {
auto const &args = parse_vm(s, p);
_vm(s, args.path, args.regions);
},
[](Session &s, Parser &p) { parse_vm(s, p); }, "Virtual space Map file", R"(
vm "<file>" <region>...
Maps the named file into all the specified regions of the current virtual
space. If the file is smaller than the region, it is zero-padded; if the region
is smaller, the extra data is ignored. The amount of data mapped is always
exactly the size of the requested region.
vm "/os/fx/3.10/3.10.bin" ROM ROM_P2
Maps a binary file 3.10.bin to ROM, through both P1 and P2.
)");