cxx_header = "arch/arm/semihosting.hh"
cmd_line = Param.String("", "Command line to report to guest");
+ stdin = Param.String("stdin",
+ "Standard input (stdin for gem5's terminal)")
+ stdout = Param.String("stdout",
+ "Standard output (stdout for gem5's terminal)")
+ stderr = Param.String("stderr",
+ "Standard error (stderr for gem5's terminal)")
mem_reserve = Param.MemorySize("32MB",
"Amount of memory to reserve at the start of the address map. This "
0x3, // EXT_EXIT_EXTENDED, EXT_STDOUT_STDERR
};
+const std::map<const std::string, FILE *> ArmSemihosting::stdioMap{
+ {"cin", ::stdin},
+ {"stdin", ::stdin},
+ {"cout", ::stdout},
+ {"stdout", ::stdout},
+ {"cerr", ::stderr},
+ {"stderr", ::stderr},
+};
+
ArmSemihosting::ArmSemihosting(const ArmSemihostingParams *p)
: SimObject(p),
cmdLine(p->cmd_line),
stackSize(p->stack_size),
timeBase([p]{ struct tm t = p->time; return mkutctime(&t); }()),
tickShift(calcTickShift()),
- semiErrno(0)
+ semiErrno(0),
+ stdin(getSTDIO("stdin", p->stdin, "r")),
+ stdout(getSTDIO("stdout", p->stdout, "w")),
+ stderr(p->stderr == p->stdout ?
+ stdout : getSTDIO("stderr", p->stderr, "w"))
{
// Create an empty place-holder file for position 0 as semi-hosting
// calls typically expect non-zero file handles.
}
}
+FILE *
+ArmSemihosting::getSTDIO(const char *stream_name,
+ const std::string &name, const char *mode)
+{
+ auto it = stdioMap.find(name);
+ if (it == stdioMap.end()) {
+ FILE *f = fopen(name.c_str(), mode);
+ if (!f) {
+ fatal("Failed to open %s (%s): %s\n",
+ stream_name, name, strerror(errno));
+ }
+ return f;
+ } else {
+ return it->second;
+ }
+}
+
std::unique_ptr<ArmSemihosting::FileBase>
ArmSemihosting::FileBase::create(
ArmSemihosting &parent, const std::string &fname, const char *mode)
if (_name == ":tt") {
if (mode[0] == 'r') {
- file = stdin;
+ file = parent.stdin;
} else if (mode[0] == 'w') {
- file = stdout;
+ file = parent.stdout;
} else if (mode[0] == 'a') {
- file = stderr;
+ file = parent.stderr;
} else {
warn("Unknown file mode for the ':tt' special file");
return -EINVAL;
bool
ArmSemihosting::File::isTTY() const
{
- return file == stdout || file == stderr || file == stdin;
+ return file == parent.stdout ||
+ file == parent.stderr ||
+ file == parent.stdin;
}
int64_t
};
std::vector<std::unique_ptr<FileBase>> files;
+ FILE *stdin;
+ FILE *stdout;
+ FILE *stderr;
protected: // Helper functions
unsigned calcTickShift() const {
#undef SEMI_CALL
static const SemiCall *getCall(uint32_t op, bool aarch64);
+ static FILE *getSTDIO(const char *stream_name,
+ const std::string &name, const char *mode);
static const std::map<uint32_t, SemiCall> calls;
static const std::vector<const char *> fmodes;
static const std::map<uint64_t, const char *> exitCodes;
static const std::vector<uint8_t> features;
+ static const std::map<const std::string, FILE *> stdioMap;
};
#endif // __ARCH_ARM_SEMIHOSTING_HH__