add port e9 hack support for all rings (#64)

By enabling the 'all_rings' option, you can utilize the port e9 hack
from ring3

IMO very useful for:
- user-mode sandbox (ex Cuckoo)
- malware analysis
- API/SYSCALL logger with a simple hook from ring3
- automation + instrumentation from user mode code
- ...

So yes, from this PR a user-mode-sandbox can display on the console of
the system running Bochs anything that is written to 0xE9 port


![porte9hackallrings](https://github.com/bochs-emu/Bochs/assets/9882181/ddbca3fa-729b-4a3e-95ad-078e44c7a17a)

**This PR is 100% backward compatibility**

btw, @stlintel I'm not certain if **bochs/config.cc** is the ideal
location to define **bool port_e9_hack_all_rings** (unmapped io/dev is
better?)
This commit is contained in:
Dreg 2023-08-26 17:37:55 +02:00 committed by GitHub
parent 253882589d
commit da43cc4580
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 49 additions and 10 deletions

View File

@ -1310,10 +1310,12 @@ speaker: enabled=1, mode=sound, volume=15
# very early when writing BIOS or OS code for example, without having to
# bother with setting up a serial port or etc. Reading from port 0xE9 will
# will return 0xe9 to let you know if the feature is available.
# Leave this 0 unless you have a reason to use it.
# Leave this 0 unless you have a reason to use it. By enabling the
# 'all_rings' option, you can utilize the port e9 hack from ring3.
#
# Example:
# port_e9_hack: enabled=1
# port_e9_hack: enabled=1, all_rings=1
#=======================================================================
#port_e9_hack: enabled=1

View File

@ -285,6 +285,7 @@ sound
misc
port_e9_hack
port_e9_hack_all_rings
gdbstub
port
text_base

View File

@ -1679,6 +1679,13 @@ void bx_init_options()
"Debug messages written to i/o port 0xE9 will be displayed on console",
0);
// port e9 hack all rings
new bx_param_bool_c(misc,
"port_e9_hack_all_rings",
"Enable port 0xE9 hack for all rings",
"Debug messages written to i/o port 0xE9 from ring3 will be displayed on console",
0);
// GDB stub
menu = new bx_list_c(misc, "gdbstub", "GDB Stub Options");
menu->set_options(menu->SHOW_PARENT | menu->USE_BOX_TITLE);
@ -1763,6 +1770,7 @@ void bx_init_options()
misc->add(SIM->get_param(BXPN_KBD_PASTE_DELAY));
misc->add(SIM->get_param(BXPN_USER_SHORTCUT));
misc->add(SIM->get_param(BXPN_PORT_E9_HACK));
misc->add(SIM->get_param(BXPN_PORT_E9_HACK_ALL_RINGS));
misc->set_options(misc->SHOW_PARENT | misc->SHOW_GROUP_NAME);
}
@ -2237,6 +2245,30 @@ static int parse_param_bool(const char *input, int len, const char *param)
return -1;
}
static int parse_port_e9_hack(const char *context, const char **params, int num_params)
{
if (num_params > 2) {
PARSE_ERR(("%s: port_e9_hack directive: wrong # args.", context));
}
if (strncmp(params[0], "enabled=", 8)) {
PARSE_ERR(("%s: port_e9_hack directive malformed.", context));
}
if (parse_param_bool(params[0], 8, BXPN_PORT_E9_HACK) < 0) {
PARSE_ERR(("%s: port_e9_hack directive malformed.", context));
}
if (num_params == 2) {
if (!strncmp(params[1], "all_rings=", 10)) {
if (parse_param_bool(params[1], 10, BXPN_PORT_E9_HACK_ALL_RINGS) < 0) {
PARSE_ERR(("%s: all_rings option malformed.", context));
}
} else {
PARSE_ERR(("%s: port_e9_hack: invalid parameter %s", context, params[1]));
}
}
return 0;
}
int bx_parse_param_from_list(const char *context, const char *input, bx_list_c *list)
{
char *propval, *property, *value;
@ -3186,14 +3218,8 @@ static int parse_line_formatted(const char *context, int num_params, char *param
PARSE_ERR(("%s: print_timestamps directive malformed.", context));
}
} else if (!strcmp(params[0], "port_e9_hack")) {
if (num_params != 2) {
PARSE_ERR(("%s: port_e9_hack directive: wrong # args.", context));
}
if (strncmp(params[1], "enabled=", 8)) {
PARSE_ERR(("%s: port_e9_hack directive malformed.", context));
}
if (parse_param_bool(params[1], 8, BXPN_PORT_E9_HACK) < 0) {
PARSE_ERR(("%s: port_e9_hack directive malformed.", context));
if (parse_port_e9_hack(context, (const char **)(params + 1), num_params - 1) < 0) {
return -1;
}
} else if (!strcmp(params[0], "load32bitOSImage")) {
PARSE_ERR(("%s: load32bitOSImage: This legacy feature is no longer supported.", context));
@ -3550,6 +3576,7 @@ int bx_write_configuration(const char *rc, int overwrite)
fprintf(fp, "print_timestamps: enabled=%d\n", bx_dbg.print_timestamps);
bx_write_debugger_options(fp);
fprintf(fp, "port_e9_hack: enabled=%d\n", SIM->get_param_bool(BXPN_PORT_E9_HACK)->get());
fprintf(fp, "port_e9_hack_all_rings: enabled=%d\n", SIM->get_param_bool(BXPN_PORT_E9_HACK_ALL_RINGS)->get());
fprintf(fp, "private_colormap: enabled=%d\n", SIM->get_param_bool(BXPN_PRIVATE_COLORMAP)->get());
#if BX_WITH_AMIGAOS
fprintf(fp, "fullscreen: enabled=%d\n", SIM->get_param_bool(BXPN_FULLSCREEN)->get());

View File

@ -864,6 +864,10 @@ bool BX_CPP_AttrRegparmN(3) BX_CPU_C::allow_io(bxInstruction_c *i, Bit16u port,
/* If CPL <= IOPL, then all IO portesses are accessible.
* Otherwise, must check the IO permission map on >286.
* On the 286, there is no IO permissions map */
static bool port_e9_hack_all_rings = SIM->get_param_bool(BXPN_PORT_E9_HACK_ALL_RINGS)->get();
if (0xe9 == port && port_e9_hack_all_rings)
return(1); // port e9 hack can be used by unprivileged code
if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL > BX_CPU_THIS_PTR get_IOPL())))
{

View File

@ -5204,13 +5204,17 @@ Example:
<screen>
port_e9_hack: enabled=1
</screen>
<screen>
port_e9_hack: enabled=1, all_rings=1
</screen>
The 0xE9 port doesn't exists in normal ISA architecture. However, we
define a convention here, to display on the console of the system running
Bochs anything that is written to it. The idea is to provide debug output
very early when writing BIOS or OS code for example, without having to
bother with setting up a serial port or etc. Reading from port 0xE9 will
will return 0xe9 to let you know if the feature is available. Leave
this 0 unless you have a reason to use it.
this 0 unless you have a reason to use it. By enabling the 'all_rings'
option, you can utilize the port e9 hack from ring3.
</para>
</section>

View File

@ -175,6 +175,7 @@
#define BXPN_SOUND_SB16 "sound.sb16"
#define BXPN_SOUND_ES1370 "sound.es1370"
#define BXPN_PORT_E9_HACK "misc.port_e9_hack"
#define BXPN_PORT_E9_HACK_ALL_RINGS "misc.port_e9_hack_all_rings"
#define BXPN_GDBSTUB "misc.gdbstub"
#define BXPN_LOG_FILENAME "log.filename"
#define BXPN_LOG_PREFIX "log.prefix"