I've written what I believe is a minimal custom device to test my understanding of the QOM and QEMU in general. Below is the relevant code with comments omitted. Unfortunately, when I start the guest and pass my device name as a command line argument, it fails to find my device and exits. I am issuing:
qemu-system-x86_64 -device hello-world-device ...
How can I make QEMU aware of my device? What steps do I need to take to properly build my device?
I can see an objects list in the folder I placed my source into (qemu/hw/misc), but I can't find where the other targets are defined to add in a target for my new device. The code:
#include "qom/object.h"
#include "hw/qdev-core.h"
#define TYPE_HELLO "hello-world-device"
#define HELLO(obj) OBJECT_CHECK(HelloState, (obj), TYPE_HELLO)
typedef struct{
DeviceClass parent_obj;
uint8_t member0, member1;
} HelloState;
static const TypeInfo hello_info = {
.name = TYPE_HELLO,
.parent = TYPE_DEVICE,
.instance_size = sizeof(HelloState),
.class_init = class_init,
};
static void class_init(ObjectClass *klass, void *data){
DeviceClass *dc = DEVICE_CLASS(klass);
}
static void hello_register_types(void){
type_register_static(&hello_info);
}
type_init(hello_register_types)
The documentation is unclear or missing on how this ought to be done, but I did find a solution that worked in the interim.
In the directory where the source file is stored (here, qemu/hw/misc/), there is a file called Makefile.objs with a list of object file targets to create. Adding the following line will induce the main Makefile (in the QEMU root directory) to create a target whenever the configuration flag CONFIG_HELLO is defined:
common-obj-$(CONFIG_HELLO) += hello-world-device.o
To define this custom flag, an entry can be added to the target architecture of choice. Here, I add it to my configuration for x86_64 in qemu/default-configs/x86_64-softmmu.mak:
CONFIG_HELLO=y
After making the above changes, running make creates a rule to build the custom device, and runs it at the appropriate time when building the architecture. This revealed an includes bug in the existing code, repeated here with the corrections for convenience:
#include "qemu/osdeps.h"
#include "hw/hw.h"
#define TYPE_HELLO "hello-world-device"
#define HELLO(obj) OBJECT_CHECK(HelloState, (obj), TYPE_HELLO)
typedef struct{
DeviceClass parent_obj;
uint8_t member0, member1;
} HelloState;
static const TypeInfo hello_info = {
.name = TYPE_HELLO,
.parent = TYPE_DEVICE,
.instance_size = sizeof(HelloState),
.class_init = class_init,
};
static void class_init(ObjectClass *klass, void *data){
DeviceClass *dc = DEVICE_CLASS(klass);
}
static void hello_register_types(void){
type_register_static(&hello_info);
}
type_init(hello_register_types)