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: ClassInitImpl + Sized { 13 type Class; 14 const TYPE_NAME: &'static CStr; 15 const PARENT_TYPE_NAME: Option<&'static CStr>; 16 const ABSTRACT: bool = false; 17 const INSTANCE_INIT: Option<unsafe extern "C" fn(obj: *mut Object)> = None; 18 const INSTANCE_POST_INIT: Option<unsafe extern "C" fn(obj: *mut Object)> = None; 19 const INSTANCE_FINALIZE: Option<unsafe extern "C" fn(obj: *mut Object)> = None; 20 21 const TYPE_INFO: TypeInfo = TypeInfo { 22 name: Self::TYPE_NAME.as_ptr(), 23 parent: if let Some(pname) = Self::PARENT_TYPE_NAME { 24 pname.as_ptr() 25 } else { 26 core::ptr::null_mut() 27 }, 28 instance_size: core::mem::size_of::<Self>(), 29 instance_align: core::mem::align_of::<Self>(), 30 instance_init: Self::INSTANCE_INIT, 31 instance_post_init: Self::INSTANCE_POST_INIT, 32 instance_finalize: Self::INSTANCE_FINALIZE, 33 abstract_: Self::ABSTRACT, 34 class_size: core::mem::size_of::<Self::Class>(), 35 class_init: <Self as ClassInitImpl>::CLASS_INIT, 36 class_base_init: <Self as ClassInitImpl>::CLASS_BASE_INIT, 37 class_data: core::ptr::null_mut(), 38 interfaces: core::ptr::null_mut(), 39 }; 40 } 41 42 /// Trait used to fill in a class struct. 43 /// 44 /// Each QOM class that has virtual methods describes them in a 45 /// _class struct_. Class structs include a parent field corresponding 46 /// to the vtable of the parent class, all the way up to [`ObjectClass`]. 47 /// Each QOM type has one such class struct. 48 /// 49 /// The Rust implementation of methods will usually come from a trait 50 /// like [`ObjectImpl`] or [`DeviceImpl`](crate::device_class::DeviceImpl). 51 pub trait ClassInitImpl { 52 /// Function that is called after all parent class initialization 53 /// has occurred. On entry, the virtual method pointers are set to 54 /// the default values coming from the parent classes; the function 55 /// can change them to override virtual methods of a parent class. 56 const CLASS_INIT: Option<unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut c_void)>; 57 58 /// Called on descendent classes after all parent class initialization 59 /// has occurred, but before the class itself is initialized. This 60 /// is only useful if a class is not a leaf, and can be used to undo 61 /// the effects of copying the contents of the parent's class struct 62 /// to the descendants. 63 const CLASS_BASE_INIT: Option< 64 unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut c_void), 65 >; 66 } 67 68 #[macro_export] 69 macro_rules! module_init { 70 ($type:ident => $body:block) => { 71 const _: () = { 72 #[used] 73 #[cfg_attr( 74 not(any(target_vendor = "apple", target_os = "windows")), 75 link_section = ".init_array" 76 )] 77 #[cfg_attr(target_vendor = "apple", link_section = "__DATA,__mod_init_func")] 78 #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")] 79 pub static LOAD_MODULE: extern "C" fn() = { 80 extern "C" fn init_fn() { 81 $body 82 } 83 84 extern "C" fn ctor_fn() { 85 unsafe { 86 $crate::bindings::register_module_init( 87 Some(init_fn), 88 $crate::bindings::module_init_type::$type, 89 ); 90 } 91 } 92 93 ctor_fn 94 }; 95 }; 96 }; 97 98 // shortcut because it's quite common that $body needs unsafe {} 99 ($type:ident => unsafe $body:block) => { 100 $crate::module_init! { 101 $type => { unsafe { $body } } 102 } 103 }; 104 } 105