libdrm_amdgpu_sys/amdgpu/
vbios.rs

1use crate::AMDGPU::*;
2use crate::*;
3
4use core::mem::{size_of, MaybeUninit};
5use core::ptr;
6
7use bindings::{AMDGPU_INFO_VBIOS, DRM_AMDGPU_INFO, drm_amdgpu_info};
8
9/// VBIOS information
10#[derive(Debug, Clone)]
11pub struct VbiosInfo {
12    pub name: String,
13    pub pn: String,
14    pub ver: String,
15    pub date: String,
16    pub size: u32,
17}
18
19impl DeviceHandle {
20    pub fn get_vbios_info(&self) -> Result<VbiosInfo, i32> {
21        let vbios = self.vbios_info()?;
22        let size = self.vbios_size()?;
23
24        let [name, pn, ver, date] = [
25            vbios.name.to_vec(),
26            vbios.vbios_pn.to_vec(),
27            vbios.vbios_ver_str.to_vec(),
28            vbios.date.to_vec(),
29        ]
30        .map(|v| {
31            if let Some(index) = v.iter().position(|&x| x == 0) {
32                String::from_utf8(v.get(..index).unwrap_or_default().to_vec())
33            } else {
34                String::from_utf8(v)
35            }.unwrap_or_default()
36        });
37
38        Ok(VbiosInfo { name, pn, ver, date, size })
39    }
40
41    unsafe fn query_vbios<T>(
42        &self,
43        info_id: ::core::ffi::c_uint,
44    ) -> Result<T, i32> { unsafe {
45        #[cfg(not(feature = "dynamic_loading"))]
46        let func = bindings::drmCommandWrite;
47        #[cfg(feature = "dynamic_loading")]
48        let func = self.libdrm.drmCommandWrite;
49
50        let mut vbios: MaybeUninit<T> = MaybeUninit::zeroed();
51        let mut device_info: MaybeUninit<drm_amdgpu_info> = MaybeUninit::zeroed();
52
53        {
54            let ptr = device_info.as_mut_ptr();
55
56            ptr::addr_of_mut!((*ptr).return_pointer).write(vbios.as_mut_ptr() as u64);
57            ptr::addr_of_mut!((*ptr).return_size).write(size_of::<T>() as u32);
58            ptr::addr_of_mut!((*ptr).query).write(AMDGPU_INFO_VBIOS);
59
60            ptr::addr_of_mut!((*ptr).__bindgen_anon_1.vbios_info.type_).write(info_id);
61        }
62
63        let r = func(
64            self.fd,
65            DRM_AMDGPU_INFO as ::core::ffi::c_ulong,
66            device_info.as_mut_ptr() as *mut ::core::ffi::c_void,
67            size_of::<drm_amdgpu_info>() as ::core::ffi::c_ulong,
68        );
69
70        let (_, vbios) = (device_info.assume_init(), vbios.assume_init());
71
72        query_error!(r);
73
74        Ok(vbios)
75    }}
76
77    pub fn vbios_info(&self) -> Result<bindings::drm_amdgpu_info_vbios, i32> {
78        use bindings::AMDGPU_INFO_VBIOS_INFO;
79
80        unsafe { Self::query_vbios(self, AMDGPU_INFO_VBIOS_INFO) }
81    }
82
83    pub fn vbios_size(&self) -> Result<u32, i32> {
84        use bindings::AMDGPU_INFO_VBIOS_SIZE;
85
86        unsafe { Self::query_vbios(self, AMDGPU_INFO_VBIOS_SIZE) }
87    }
88
89    unsafe fn get_vbios_image_with_size(&self, vbios_size: u32) -> Result<Vec<u8>, i32> { unsafe {
90        use bindings::AMDGPU_INFO_VBIOS_IMAGE;
91
92        #[cfg(not(feature = "dynamic_loading"))]
93        let func = bindings::drmCommandWrite;
94        #[cfg(feature = "dynamic_loading")]
95        let func = self.libdrm.drmCommandWrite;
96
97        let mut vbios_image = vec![0; vbios_size as usize];
98        let mut device_info: MaybeUninit<drm_amdgpu_info> = MaybeUninit::zeroed();
99
100        {
101            let ptr = device_info.as_mut_ptr();
102
103            ptr::addr_of_mut!((*ptr).return_pointer).write(vbios_image.as_mut_ptr() as u64);
104            ptr::addr_of_mut!((*ptr).return_size).write(vbios_size);
105            ptr::addr_of_mut!((*ptr).query).write(AMDGPU_INFO_VBIOS);
106
107            ptr::addr_of_mut!((*ptr).__bindgen_anon_1.vbios_info.type_)
108                .write(AMDGPU_INFO_VBIOS_IMAGE);
109        }
110
111        let r = func(
112            self.fd,
113            DRM_AMDGPU_INFO as ::core::ffi::c_ulong,
114            device_info.as_mut_ptr() as *mut ::core::ffi::c_void,
115            size_of::<drm_amdgpu_info>() as ::core::ffi::c_ulong,
116        );
117
118        let _ = device_info.assume_init();
119
120        query_error!(r);
121
122        Ok(vbios_image)
123    }}
124
125
126    pub fn get_vbios_image(&self) -> Result<Vec<u8>, i32> {
127        let size = self.vbios_size()?;
128
129        unsafe { self.get_vbios_image_with_size(size) }
130    }
131}