1 // Copyright 2024, Linaro Limited 2 // Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org> 3 // SPDX-License-Identifier: GPL-2.0-or-later 4 5 //! Definitions required by QEMU when registering a device. 6 7 use ::core::ffi::{c_void, CStr}; 8 9 use crate::bindings::{Object, ObjectClass, TypeInfo}; 10 11 /// Trait a type must implement to be registered with QEMU. 12 pub trait ObjectImpl { 13 type Class; 14 const TYPE_INFO: TypeInfo; 15 const TYPE_NAME: &'static CStr; 16 const PARENT_TYPE_NAME: Option<&'static CStr>; 17 const ABSTRACT: bool; 18 const INSTANCE_INIT: Option<unsafe extern "C" fn(obj: *mut Object)>; 19 const INSTANCE_POST_INIT: Option<unsafe extern "C" fn(obj: *mut Object)>; 20 const INSTANCE_FINALIZE: Option<unsafe extern "C" fn(obj: *mut Object)>; 21 } 22 23 pub trait Class { 24 const CLASS_INIT: Option<unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut c_void)>; 25 const CLASS_BASE_INIT: Option< 26 unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut c_void), 27 >; 28 } 29 30 #[macro_export] 31 macro_rules! module_init { 32 ($func:expr, $type:expr) => { 33 #[used] 34 #[cfg_attr(target_os = "linux", link_section = ".ctors")] 35 #[cfg_attr(target_os = "macos", link_section = "__DATA,__mod_init_func")] 36 #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")] 37 pub static LOAD_MODULE: extern "C" fn() = { 38 extern "C" fn __load() { 39 unsafe { 40 $crate::bindings::register_module_init(Some($func), $type); 41 } 42 } 43 44 __load 45 }; 46 }; 47 (qom: $func:ident => $body:block) => { 48 // NOTE: To have custom identifiers for the ctor func we need to either supply 49 // them directly as a macro argument or create them with a proc macro. 50 #[used] 51 #[cfg_attr(target_os = "linux", link_section = ".ctors")] 52 #[cfg_attr(target_os = "macos", link_section = "__DATA,__mod_init_func")] 53 #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")] 54 pub static LOAD_MODULE: extern "C" fn() = { 55 extern "C" fn __load() { 56 #[no_mangle] 57 unsafe extern "C" fn $func() { 58 $body 59 } 60 61 unsafe { 62 $crate::bindings::register_module_init( 63 Some($func), 64 $crate::bindings::module_init_type::MODULE_INIT_QOM, 65 ); 66 } 67 } 68 69 __load 70 }; 71 }; 72 } 73 74 #[macro_export] 75 macro_rules! type_info { 76 ($t:ty) => { 77 $crate::bindings::TypeInfo { 78 name: <$t as $crate::definitions::ObjectImpl>::TYPE_NAME.as_ptr(), 79 parent: if let Some(pname) = <$t as $crate::definitions::ObjectImpl>::PARENT_TYPE_NAME { 80 pname.as_ptr() 81 } else { 82 ::core::ptr::null_mut() 83 }, 84 instance_size: ::core::mem::size_of::<$t>() as $crate::bindings::size_t, 85 instance_align: ::core::mem::align_of::<$t>() as $crate::bindings::size_t, 86 instance_init: <$t as $crate::definitions::ObjectImpl>::INSTANCE_INIT, 87 instance_post_init: <$t as $crate::definitions::ObjectImpl>::INSTANCE_POST_INIT, 88 instance_finalize: <$t as $crate::definitions::ObjectImpl>::INSTANCE_FINALIZE, 89 abstract_: <$t as $crate::definitions::ObjectImpl>::ABSTRACT, 90 class_size: ::core::mem::size_of::<<$t as $crate::definitions::ObjectImpl>::Class>() as $crate::bindings::size_t, 91 class_init: <<$t as $crate::definitions::ObjectImpl>::Class as $crate::definitions::Class>::CLASS_INIT, 92 class_base_init: <<$t as $crate::definitions::ObjectImpl>::Class as $crate::definitions::Class>::CLASS_BASE_INIT, 93 class_data: ::core::ptr::null_mut(), 94 interfaces: ::core::ptr::null_mut(), 95 }; 96 } 97 } 98