Skip to content

Instantly share code, notes, and snippets.

@novafacing
Created August 28, 2024 05:54
Show Gist options
  • Save novafacing/5abc08052fab671a0fb26547810b4c55 to your computer and use it in GitHub Desktop.
Save novafacing/5abc08052fab671a0fb26547810b4c55 to your computer and use it in GitHub Desktop.
Demo QEMU plugin that dumps the first 256 bytes of firmware when booting a BIOS on RISC-V
/*
* Copyright (C) 2018, Emilio G. Cota <[email protected]>
*
* License: GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#include <inttypes.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <qemu-plugin.h>
QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
static bool did_dump = false;
/*
* Hex-dump a GByteArray to the QEMU plugin output in the format:
* 61 63 63 65 6c 09 09 20 20 20 66 70 75 09 09 09 | accel.....fpu...
* 20 6d 6f 64 75 6c 65 2d 63 6f 6d 6d 6f 6e 2e 63 | .module-common.c
*/
static void hexdump(const GByteArray *data)
{
g_autoptr(GString) out = g_string_new("");
for (guint index = 0; index < data->len; index += 16) {
for (guint col = 0; col < 16; col++) {
if (index + col < data->len) {
g_string_append_printf(out, "%02x ", data->data[index + col]);
} else {
g_string_append(out, " ");
}
}
g_string_append(out, " | ");
for (guint col = 0; col < 16; col++) {
if (index + col >= data->len) {
break;
}
if (g_ascii_isgraph(data->data[index + col])) {
g_string_append_printf(out, "%c", data->data[index + col]);
} else {
g_string_append(out, ".");
}
}
g_string_append(out, "\n");
}
qemu_plugin_outs(out->str);
}
static void vcpu_insn_exec_before(unsigned int cpu_index, void *udata)
{
g_autoptr(GByteArray) mem = g_byte_array_new();
if (!did_dump && qemu_plugin_read_cpu_memory_hwaddr(0x80000000, mem, 256)) {
hexdump(mem);
did_dump = true;
}
}
static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
{
size_t n = qemu_plugin_tb_n_insns(tb);
for (size_t i = 0; i < n; i++) {
struct qemu_plugin_insn *insn = qemu_plugin_tb_get_insn(tb, i);
qemu_plugin_register_vcpu_insn_exec_cb(insn, vcpu_insn_exec_before, QEMU_PLUGIN_CB_NO_REGS, NULL);
}
}
QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
const qemu_info_t *info,
int argc, char **argv)
{
qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment