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 std::{ffi::CStr, os::raw::c_void}; 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 ($type:ident => $body:block) => { 33 const _: () = { 34 #[used] 35 #[cfg_attr( 36 not(any(target_vendor = "apple", target_os = "windows")), 37 link_section = ".init_array" 38 )] 39 #[cfg_attr(target_vendor = "apple", link_section = "__DATA,__mod_init_func")] 40 #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")] 41 pub static LOAD_MODULE: extern "C" fn() = { 42 extern "C" fn init_fn() { 43 $body 44 } 45 46 extern "C" fn ctor_fn() { 47 unsafe { 48 $crate::bindings::register_module_init( 49 Some(init_fn), 50 $crate::bindings::module_init_type::$type, 51 ); 52 } 53 } 54 55 ctor_fn 56 }; 57 }; 58 }; 59 60 // shortcut because it's quite common that $body needs unsafe {} 61 ($type:ident => unsafe $body:block) => { 62 $crate::module_init! { 63 $type => { unsafe { $body } } 64 } 65 }; 66 } 67 68 #[macro_export] 69 macro_rules! type_info { 70 ($t:ty) => { 71 $crate::bindings::TypeInfo { 72 name: <$t as $crate::definitions::ObjectImpl>::TYPE_NAME.as_ptr(), 73 parent: if let Some(pname) = <$t as $crate::definitions::ObjectImpl>::PARENT_TYPE_NAME { 74 pname.as_ptr() 75 } else { 76 ::core::ptr::null_mut() 77 }, 78 instance_size: ::core::mem::size_of::<$t>(), 79 instance_align: ::core::mem::align_of::<$t>(), 80 instance_init: <$t as $crate::definitions::ObjectImpl>::INSTANCE_INIT, 81 instance_post_init: <$t as $crate::definitions::ObjectImpl>::INSTANCE_POST_INIT, 82 instance_finalize: <$t as $crate::definitions::ObjectImpl>::INSTANCE_FINALIZE, 83 abstract_: <$t as $crate::definitions::ObjectImpl>::ABSTRACT, 84 class_size: ::core::mem::size_of::<<$t as $crate::definitions::ObjectImpl>::Class>(), 85 class_init: <<$t as $crate::definitions::ObjectImpl>::Class as $crate::definitions::Class>::CLASS_INIT, 86 class_base_init: <<$t as $crate::definitions::ObjectImpl>::Class as $crate::definitions::Class>::CLASS_BASE_INIT, 87 class_data: ::core::ptr::null_mut(), 88 interfaces: ::core::ptr::null_mut(), 89 }; 90 } 91 } 92