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( 35 not(any(target_vendor = "apple", target_os = "windows")), 36 link_section = ".init_array" 37 )] 38 #[cfg_attr(target_vendor = "apple", link_section = "__DATA,__mod_init_func")] 39 #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")] 40 pub static LOAD_MODULE: extern "C" fn() = { 41 extern "C" fn __load() { 42 unsafe { 43 $crate::bindings::register_module_init(Some($func), $type); 44 } 45 } 46 47 __load 48 }; 49 }; 50 (qom: $func:ident => $body:block) => { 51 // NOTE: To have custom identifiers for the ctor func we need to either supply 52 // them directly as a macro argument or create them with a proc macro. 53 #[used] 54 #[cfg_attr( 55 not(any(target_vendor = "apple", target_os = "windows")), 56 link_section = ".init_array" 57 )] 58 #[cfg_attr(target_vendor = "apple", link_section = "__DATA,__mod_init_func")] 59 #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")] 60 pub static LOAD_MODULE: extern "C" fn() = { 61 extern "C" fn __load() { 62 unsafe extern "C" fn $func() { 63 $body 64 } 65 66 unsafe { 67 $crate::bindings::register_module_init( 68 Some($func), 69 $crate::bindings::module_init_type::MODULE_INIT_QOM, 70 ); 71 } 72 } 73 74 __load 75 }; 76 }; 77 } 78 79 #[macro_export] 80 macro_rules! type_info { 81 ($t:ty) => { 82 $crate::bindings::TypeInfo { 83 name: <$t as $crate::definitions::ObjectImpl>::TYPE_NAME.as_ptr(), 84 parent: if let Some(pname) = <$t as $crate::definitions::ObjectImpl>::PARENT_TYPE_NAME { 85 pname.as_ptr() 86 } else { 87 ::core::ptr::null_mut() 88 }, 89 instance_size: ::core::mem::size_of::<$t>(), 90 instance_align: ::core::mem::align_of::<$t>(), 91 instance_init: <$t as $crate::definitions::ObjectImpl>::INSTANCE_INIT, 92 instance_post_init: <$t as $crate::definitions::ObjectImpl>::INSTANCE_POST_INIT, 93 instance_finalize: <$t as $crate::definitions::ObjectImpl>::INSTANCE_FINALIZE, 94 abstract_: <$t as $crate::definitions::ObjectImpl>::ABSTRACT, 95 class_size: ::core::mem::size_of::<<$t as $crate::definitions::ObjectImpl>::Class>(), 96 class_init: <<$t as $crate::definitions::ObjectImpl>::Class as $crate::definitions::Class>::CLASS_INIT, 97 class_base_init: <<$t as $crate::definitions::ObjectImpl>::Class as $crate::definitions::Class>::CLASS_BASE_INIT, 98 class_data: ::core::ptr::null_mut(), 99 interfaces: ::core::ptr::null_mut(), 100 }; 101 } 102 } 103