ferrix_lib/
dmi.rs

1/* dmi.rs
2 *
3 * Copyright 2025 Michail Krasnov <mskrasnov07@ya.ru>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 *
18 * SPDX-License-Identifier: GPL-3.0-or-later
19 */
20
21//! DMI table parser. Uses `smbios-lib` to data provider
22//!
23//! ## Usage
24//!
25//! ```no-test
26//! use ferrix::dmi::DMITable;
27//! let dmi = DMITable::new().unwrap();
28//! dbg!(dmi);
29//! ```
30
31use crate::traits::ToJson;
32use anyhow::{Result, anyhow};
33use serde::Serialize;
34use smbioslib::SMBiosData;
35
36/// A structure containing data from the DMI table
37///
38/// ## Usage
39///
40/// ```no-test
41/// use ferrix::dmi::DMITable;
42/// let dmi = DMITable::new().unwrap();
43/// dbg!(dmi);
44/// ```
45#[derive(Debug, Serialize)]
46pub struct DMITable {
47    /// Information about BIOS (Type 0)
48    pub bios: Bios,
49
50    /// Information about system (Type 1)
51    pub system: System,
52
53    /// Information about baseboard (or module) - Type 2
54    pub baseboard: Baseboard,
55
56    /// Information about system enclosure or chassis - Type 3
57    pub chassis: Chassis,
58
59    /// Information about processor - Type 4
60    pub processor: Processor,
61
62    // /// Information about memory controller (Type 5)
63    // pub memory_controller: MemoryController,
64    //
65    // /// Information about memory module (Type 6)
66    // pub memory_module: MemoryModule,
67    /// Information about CPU cache (Type 7)
68    pub caches: Caches,
69
70    /// Information about port connectors (Type 8)
71    pub ports: PortConnectors,
72
73    /// Information about physical memory array (Type 16)
74    pub mem_array: MemoryArray,
75
76    /// Information about installed memory devices (Type 17)
77    pub mem_devices: MemoryDevices,
78}
79
80/* TODO:
81 * - Type 5, 6, 10, 14m 15, 22, 23, 25, 27, 28, 29, 30, 31, 33, 34,
82 *        35, 36, 37, 38, 39, 41, ... - в последнюю очередь
83 * - Type 7i, 8i, 9i, 11, 12, 13, 16, 17i, 18i, 19, 20i, 21, 24, 26,
84 *        32, 40, 41i, 133, 200, 248, 127 - в первую очередь
85 */
86
87impl DMITable {
88    /// Get information from DMI table
89    ///
90    /// > **NOTE:** This data DOES NOT NEED to be updated periodically!
91    pub fn new() -> Result<Self> {
92        let table = smbioslib::table_load_from_device()?;
93        Ok(Self {
94            bios: Bios::new_from_table(&table)?,
95            system: System::new_from_table(&table)?,
96            baseboard: Baseboard::new_from_table(&table)?,
97            chassis: Chassis::new_from_table(&table)?,
98            processor: Processor::new_from_table(&table)?,
99            caches: Caches::new_from_table(&table)?,
100            ports: PortConnectors::new_from_table(&table)?,
101            mem_array: MemoryArray::new_from_table(&table)?,
102            mem_devices: MemoryDevices::new_from_table(&table)?,
103        })
104    }
105
106    /// Performs serialization of structure data in JSON.
107    ///
108    /// The returned value will be a SINGLE LINE of JSON data
109    /// intended for reading by third-party software or for
110    /// transmission over the network.
111    pub fn to_json(&self) -> Result<String> {
112        Ok(serde_json::to_string(&self)?)
113    }
114
115    /// Performs serialization in "pretty" JSON
116    ///
117    /// JSON will contain unnecessary newline transitions and spaces
118    /// to visually separate the blocks. It is well suited for human
119    /// reading and analysis.
120    pub fn to_json_pretty(&self) -> Result<String> {
121        Ok(serde_json::to_string_pretty(&self)?)
122    }
123
124    /// Performs data serialization in XML format
125    pub fn to_xml(&self) -> Result<String> {
126        let xml = DMITableXml::from(self);
127        xml.to_xml()
128    }
129}
130
131impl ToJson for DMITable {}
132
133/****************************** NOTE *********************************
134 * Дичайший костыль для того, чтобы структура XML была корректной    *
135 * Если не обернуть данные в поле "hardware" (тег <hardware> в XML), *
136 * то итоговый XML просто не распарсится.                            *
137 *********************************************************************/
138#[derive(Serialize)]
139pub struct DMITableXml<'a> {
140    pub hardware: &'a DMITable,
141}
142
143impl<'a> DMITableXml<'a> {
144    pub fn to_xml(&self) -> Result<String> {
145        Ok(xml_serde::to_string(&self)?)
146    }
147}
148
149impl<'a> From<&'a DMITable> for DMITableXml<'a> {
150    fn from(value: &'a DMITable) -> Self {
151        Self { hardware: value }
152    }
153}
154
155/// Information about BIOS/UEFI
156#[derive(Debug, Serialize)]
157pub struct Bios {
158    /// BIOS vendor's name
159    pub vendor: Option<String>,
160
161    /// BIOS version
162    pub version: Option<String>,
163
164    /// BIOS starting address segment
165    pub starting_address_segment: Option<u16>,
166
167    /// BIOS release date
168    pub release_date: Option<String>,
169
170    /// BIOS ROM size
171    pub rom_size: Option<smbioslib::RomSize>,
172
173    /// BIOS characteristics
174    pub characteristics: Option<BiosCharacteristics>,
175
176    /// BIOS vendor reserved characteristics
177    pub bios_vendor_reserved_characteristics: Option<u16>,
178
179    /// System vendor reserved characteristics
180    pub system_vendor_reserved_characteristics: Option<u16>,
181
182    /// Characteristics extension byte 0
183    pub characteristics_extension0: Option<BiosCharacteristicsExtension0>,
184
185    /// Characteristics extension byte 1
186    pub characteristics_extension1: Option<BiosCharacteristicsExtension1>,
187
188    /// System BIOS major release
189    pub system_bios_major_release: Option<u8>,
190
191    /// System BIOS minor release
192    pub system_bios_minor_release: Option<u8>,
193
194    /// Embedded controller firmware major release
195    pub e_c_firmware_major_release: Option<u8>,
196
197    /// Embedded controller firmware minor release
198    pub e_c_firmware_minor_release: Option<u8>,
199
200    /// Extended BIOS ROM size
201    pub extended_rom_size: Option<smbioslib::RomSize>,
202}
203
204impl Bios {
205    /// Creates a new instance of `Self`
206    ///
207    /// It is usually not required, since an instance of this
208    /// structure will be created using the method
209    /// [`Self::new_from_table(table: &SMBiosData)`] in the constructor
210    /// [`DMITable::new()`].
211    pub fn new() -> Result<Self> {
212        let table = smbioslib::table_load_from_device()?;
213        Self::new_from_table(&table)
214    }
215
216    pub fn new_from_table(table: &SMBiosData) -> Result<Self> {
217        let t = table
218            .find_map(|f: smbioslib::SMBiosInformation| Some(f))
219            .ok_or(anyhow!("Failed to get information about BIOS (type 0)!"))?;
220
221        Ok(Self {
222            vendor: t.vendor().ok(),
223            version: t.version().ok(),
224            starting_address_segment: t.starting_address_segment(),
225            release_date: t.release_date().ok(),
226            rom_size: t.rom_size(),
227            characteristics: match t.characteristics() {
228                Some(c) => Some(BiosCharacteristics::from(c)),
229                None => None,
230            },
231            bios_vendor_reserved_characteristics: t.bios_vendor_reserved_characteristics(),
232            system_vendor_reserved_characteristics: t.system_vendor_reserved_characteristics(),
233            characteristics_extension0: match t.characteristics_extension0() {
234                Some(ce0) => Some(BiosCharacteristicsExtension0::from(ce0)),
235                None => None,
236            },
237            characteristics_extension1: match t.characteristics_extension1() {
238                Some(ce1) => Some(BiosCharacteristicsExtension1::from(ce1)),
239                None => None,
240            },
241            system_bios_major_release: t.system_bios_major_release(),
242            system_bios_minor_release: t.system_bios_minor_release(),
243            e_c_firmware_major_release: t.e_c_firmware_major_release(),
244            e_c_firmware_minor_release: t.e_c_firmware_minor_release(),
245            extended_rom_size: t.extended_rom_size(),
246        })
247    }
248}
249
250impl ToJson for Bios {}
251
252/// BIOS characteristics
253#[derive(Debug, Serialize)]
254pub struct BiosCharacteristics {
255    /// Unknown
256    pub unknown: bool,
257
258    /// BIOS Characteristics aren't supported
259    pub bios_characteristics_not_supported: bool,
260
261    /// ISA is supported
262    pub isa_supported: bool,
263
264    /// MCA is supported
265    pub mca_supported: bool,
266
267    /// EISA is supported
268    pub eisa_supported: bool,
269
270    /// PCI is supported
271    pub pci_supported: bool,
272
273    /// PCMCIA is supported
274    pub pcmcia_supported: bool,
275
276    /// Plug-n-play is supported
277    pub plug_and_play_supported: bool,
278
279    /// APM is supported
280    pub apm_supported: bool,
281
282    /// BIOS is upgradeable (Flash)
283    pub bios_upgradeable: bool,
284
285    /// BIOS shadowing is allowed
286    pub bios_shadowing_allowed: bool,
287
288    /// VL-VESA is supported
289    pub vlvesa_supported: bool,
290
291    /// ESCD support is available
292    pub escd_support_available: bool,
293
294    /// Boot from CD is supported
295    pub boot_from_cdsupported: bool,
296
297    /// Selectable boot is supported
298    pub selectable_boot_supported: bool,
299
300    /// BIOS ROM is socketed (e.g. PLCC or SOP socket)
301    pub bios_rom_socketed: bool,
302
303    /// Boot from PCMCIA is supported
304    pub boot_from_pcmcia_supported: bool,
305
306    /// EDD specification is supported
307    pub edd_specification_supported: bool,
308
309    /// Japanese floppy for NEC 9800 1.2 MB (3.5", 1K bytes/sector,
310    /// 360 RPM) is supported
311    pub floppy_nec_japanese_supported: bool,
312
313    /// Japanese floppy for Toshiba 1.2 MB (3.5", 360 RPM) is
314    /// supported
315    pub floppy_toshiba_japanese_supported: bool,
316
317    /// 5.25" / 360 KB floppy services are supported
318    pub floppy_525_360_supported: bool,
319
320    /// 5.25" / 1.2 MB floppy services are supported
321    pub floppy_525_12_supported: bool,
322
323    /// 3.5" / 720 KB floppy services are supported
324    pub floppy_35_720_supported: bool,
325
326    /// 3.5" 2.88 MB floppy services are supported
327    pub floppy_35_288_supported: bool,
328
329    /// PrintScreen service is supported
330    pub print_screen_service_supported: bool,
331
332    /// 8042 keyboard services are supported
333    pub keyboard_8042services_supported: bool,
334
335    /// Serial services are supported
336    pub serial_services_supported: bool,
337
338    /// Printer services are supported
339    pub printer_services_supported: bool,
340
341    /// CGA/Mono Video Services are supported
342    pub cga_mono_video_services_supported: bool,
343
344    /// NEC PC-98 supported
345    pub nec_pc_98supported: bool,
346}
347
348impl From<smbioslib::BiosCharacteristics> for BiosCharacteristics {
349    fn from(value: smbioslib::BiosCharacteristics) -> Self {
350        Self {
351            unknown: value.unknown(),
352            bios_characteristics_not_supported: value.bios_characteristics_not_supported(),
353            isa_supported: value.isa_supported(),
354            mca_supported: value.mca_supported(),
355            eisa_supported: value.eisa_supported(),
356            pci_supported: value.pci_supported(),
357            pcmcia_supported: value.pcmcia_supported(),
358            plug_and_play_supported: value.plug_and_play_supported(),
359            apm_supported: value.apm_supported(),
360            bios_upgradeable: value.bios_upgradeable(),
361            bios_shadowing_allowed: value.bios_shadowing_allowed(),
362            vlvesa_supported: value.vlvesa_supported(),
363            escd_support_available: value.escd_support_available(),
364            boot_from_cdsupported: value.boot_from_cdsupported(),
365            selectable_boot_supported: value.selectable_boot_supported(),
366            bios_rom_socketed: value.bios_rom_socketed(),
367            boot_from_pcmcia_supported: value.boot_from_pcmcia_supported(),
368            edd_specification_supported: value.edd_specification_supported(),
369            floppy_nec_japanese_supported: value.floppy_nec_japanese_supported(),
370            floppy_toshiba_japanese_supported: value.floppy_toshiba_japanese_supported(),
371            floppy_525_360_supported: value.floppy_525_360_supported(),
372            floppy_525_12_supported: value.floppy_525_12_supported(),
373            floppy_35_720_supported: value.floppy_35_720_supported(),
374            floppy_35_288_supported: value.floppy_35_288_supported(),
375            print_screen_service_supported: value.print_screen_service_supported(),
376            keyboard_8042services_supported: value.keyboard_8042services_supported(),
377            serial_services_supported: value.serial_services_supported(),
378            printer_services_supported: value.printer_services_supported(),
379            cga_mono_video_services_supported: value.cga_mono_video_services_supported(),
380            nec_pc_98supported: value.nec_pc_98supported(),
381        }
382    }
383}
384impl ToJson for BiosCharacteristics {}
385
386/// Characteristics extension byte 0
387#[derive(Debug, Serialize)]
388pub struct BiosCharacteristicsExtension0 {
389    /// ACPI is supported
390    pub acpi_is_supported: bool,
391
392    /// USB Legacy is supported
393    pub usb_legacy_is_supported: bool,
394
395    /// AGP is supported
396    pub agp_is_supported: bool,
397
398    /// I2O boot is supported
399    pub i2oboot_is_supported: bool,
400
401    /// LS-120 SuperDisk boot is supported
402    pub ls120super_disk_boot_is_supported: bool,
403
404    /// ATAPI ZIP drive boot is supported
405    pub atapi_zip_drive_boot_is_supported: bool,
406
407    /// 1394 boot is supported
408    pub boot_1394is_supported: bool,
409
410    /// Smart battery is supported
411    pub smart_battery_is_supported: bool,
412}
413
414impl From<smbioslib::BiosCharacteristicsExtension0> for BiosCharacteristicsExtension0 {
415    fn from(value: smbioslib::BiosCharacteristicsExtension0) -> Self {
416        Self {
417            acpi_is_supported: value.acpi_is_supported(),
418            usb_legacy_is_supported: value.usb_legacy_is_supported(),
419            agp_is_supported: value.agp_is_supported(),
420            i2oboot_is_supported: value.i2oboot_is_supported(),
421            ls120super_disk_boot_is_supported: value.ls120super_disk_boot_is_supported(),
422            atapi_zip_drive_boot_is_supported: value.atapi_zip_drive_boot_is_supported(),
423            boot_1394is_supported: value.boot_1394is_supported(),
424            smart_battery_is_supported: value.smart_battery_is_supported(),
425        }
426    }
427}
428impl ToJson for BiosCharacteristicsExtension0 {}
429
430/// Characteristics extension byte 0
431#[derive(Debug, Serialize)]
432pub struct BiosCharacteristicsExtension1 {
433    /// BIOS Boot Specification is supported
434    pub bios_boot_specification_is_supported: bool,
435
436    /// Function key-initiated network service boot is supported.
437    /// When function key-uninitiated network service boot is not
438    /// supported, a network adapter option ROM may choose to offer
439    /// this functionality on its own, thus offering this capability
440    /// to legacy systems. When the function is supported, the
441    /// network adapter option ROM shall not offer this capability
442    pub fkey_initiated_network_boot_is_supported: bool,
443
444    /// Enable targeted content distribution. The manufacturer has
445    /// ensured that the SMBIOS data is useful in identifying the
446    /// computer for targeted delivery of model-specific software
447    /// and firmware content through third-party content
448    /// distribution services
449    pub targeted_content_distribution_is_supported: bool,
450
451    /// UEFI Specification is supported
452    pub uefi_specification_is_supported: bool,
453
454    /// SMBIOS table describes a virtual machine
455    pub smbios_table_describes_avirtual_machine: bool,
456
457    /// Manufacturing mode is supported. (Manufacturing mode is a
458    /// special boot mode, not normally available to end users, that
459    /// modifies BIOS features and settings for use while the
460    /// computer is being manufactured and tested)
461    pub manufacturing_mode_is_supported: bool,
462
463    /// Manufacturing mode is enabled
464    pub manufacturing_mode_is_enabled: bool,
465}
466
467impl From<smbioslib::BiosCharacteristicsExtension1> for BiosCharacteristicsExtension1 {
468    fn from(value: smbioslib::BiosCharacteristicsExtension1) -> Self {
469        Self {
470            bios_boot_specification_is_supported: value.bios_boot_specification_is_supported(),
471            fkey_initiated_network_boot_is_supported: value
472                .fkey_initiated_network_boot_is_supported(),
473            targeted_content_distribution_is_supported: value
474                .targeted_content_distribution_is_supported(),
475            uefi_specification_is_supported: value.uefi_specification_is_supported(),
476            smbios_table_describes_avirtual_machine: value
477                .smbios_table_describes_avirtual_machine(),
478            manufacturing_mode_is_supported: value.manufacturing_mode_is_supported(),
479            manufacturing_mode_is_enabled: value.manufacturing_mode_is_enabled(),
480        }
481    }
482}
483impl ToJson for BiosCharacteristicsExtension1 {}
484
485/// Attributes of the overall system
486#[derive(Debug, Serialize)]
487pub struct System {
488    /// System manufacturer
489    pub manufacturer: Option<String>,
490
491    /// System product name
492    pub product_name: Option<String>,
493
494    /// System version
495    pub version: Option<String>,
496
497    /// Serial number
498    pub serial_number: Option<String>,
499
500    /// System UUID
501    pub uuid: Option<smbioslib::SystemUuidData>,
502
503    /// Wake-up type
504    ///
505    /// Identifies the event that caused the system to power up
506    pub wakeup_type: Option<smbioslib::SystemWakeUpTypeData>,
507
508    /// SKU Number (particular computer information for sale.
509    /// Also called a product ID or purchase order number.
510    /// Typically for a given system board from a given OEM,
511    /// there are tens of unique processor, memory, hard
512    /// drive, and optical drive configurations).
513    pub sku_number: Option<String>,
514
515    /// Family to which a particular computer belongs
516    pub family: Option<String>,
517}
518
519impl System {
520    /// Creates a new instance of `Self`
521    ///
522    /// It is usually not required, since an instance of this
523    /// structure will be created using the method
524    /// `Self::new_from_table(table: &SMBiosData)` in the constructor
525    /// [`DMITable::new()`].
526    pub fn new() -> Result<Self> {
527        let table = smbioslib::table_load_from_device()?;
528        Self::new_from_table(&table)
529    }
530
531    pub fn new_from_table(table: &SMBiosData) -> Result<Self> {
532        let t = table
533            .find_map(|f: smbioslib::SMBiosSystemInformation| Some(f))
534            .ok_or(anyhow!("Failed to get information about system (type 1)!"))?;
535
536        Ok(Self {
537            manufacturer: t.manufacturer().ok(),
538            product_name: t.product_name().ok(),
539            version: t.version().ok(),
540            serial_number: t.serial_number().ok(),
541            uuid: t.uuid(),
542            wakeup_type: t.wakeup_type(),
543            sku_number: t.sku_number().ok(),
544            family: t.family().ok(),
545        })
546    }
547}
548
549impl ToJson for System {}
550
551/// Information about baseboard/module
552#[derive(Debug, Serialize)]
553pub struct Baseboard {
554    /// Baseboard manufacturer
555    pub manufacturer: Option<String>,
556
557    /// Baseboard product
558    pub product: Option<String>,
559
560    /// Baseboard serial number
561    pub serial_number: Option<String>,
562
563    /// Asset tag
564    pub asset_tag: Option<String>,
565
566    /// Baseboard feature flags
567    pub feature_flags: Option<BaseboardFeatures>,
568
569    /// The board's location within the chassis
570    pub location_in_chassis: Option<String>,
571
572    /// Handle, or instance number, associated with the chassis in
573    /// which this board resides.
574    pub chassis_handle: Option<smbioslib::Handle>,
575
576    /// Type of baseboard
577    pub board_type: Option<smbioslib::BoardTypeData>,
578}
579
580impl Baseboard {
581    /// Creates a new instance of `Self`
582    ///
583    /// It is usually not required, since an instance of this
584    /// structure will be created using the method
585    /// `Self::new_from_table(table: &SMBiosData)` in the constructor
586    /// [`DMITable::new()`].
587    pub fn new() -> Result<Self> {
588        let table = smbioslib::table_load_from_device()?;
589        Self::new_from_table(&table)
590    }
591
592    pub fn new_from_table(table: &SMBiosData) -> Result<Self> {
593        let t = table
594            .find_map(|f: smbioslib::SMBiosBaseboardInformation| Some(f))
595            .ok_or(anyhow!(
596                "Failed to get information about baseboard/module (type 2)!"
597            ))?;
598        Ok(Self {
599            manufacturer: t.manufacturer().ok(),
600            product: t.product().ok(),
601            serial_number: t.serial_number().ok(),
602            asset_tag: t.asset_tag().ok(),
603            feature_flags: match t.feature_flags() {
604                Some(ff) => Some(BaseboardFeatures::from(ff)),
605                None => None,
606            },
607            location_in_chassis: t.location_in_chassis().ok(),
608            chassis_handle: t.chassis_handle(),
609            board_type: t.board_type(),
610        })
611    }
612}
613
614impl ToJson for Baseboard {}
615
616/// Baseboard feature flags
617///
618/// Collection of flags that identify features of this board
619#[derive(Debug, Serialize)]
620pub struct BaseboardFeatures {
621    /// Set if the board is a hosting board (e.g. motherboard)
622    pub hosting_board: bool,
623
624    /// Set if the board requires at least one daughter board or
625    /// auxiliary card to function properly
626    pub requires_daughterboard: bool,
627
628    /// Set if the board is removable; it is designed to be taken in
629    /// and out of the chassis without impairing the function of
630    /// the chassis
631    pub is_removable: bool,
632
633    /// Set if the board is replaceable; it is possible to replace
634    /// (either as a field repair or as an upgrade) the board with a
635    /// physically different board. The board is inherently removable
636    pub is_replaceable: bool,
637
638    /// Set if the board if hot swappable; it is possible to replace
639    /// the board with a physically different but equivalent board
640    /// while power is applied to the board. The board is
641    /// inherently replaceable and removable.
642    pub is_hot_swappable: bool,
643}
644
645impl From<smbioslib::BaseboardFeatures> for BaseboardFeatures {
646    fn from(value: smbioslib::BaseboardFeatures) -> Self {
647        Self {
648            hosting_board: value.hosting_board(),
649            requires_daughterboard: value.requires_daughterboard(),
650            is_removable: value.is_removable(),
651            is_replaceable: value.is_replaceable(),
652            is_hot_swappable: value.is_hot_swappable(),
653        }
654    }
655}
656impl ToJson for BaseboardFeatures {}
657
658/// Information about system enclosure or chassis
659#[derive(Debug, Serialize)]
660pub struct Chassis {
661    /// Enclosure/chassis manufacturer
662    pub manufacturer: Option<String>,
663
664    /// Chassis type
665    pub chassis_type: Option<smbioslib::ChassisTypeData>,
666
667    /// Version
668    pub version: Option<String>,
669
670    /// Serial number
671    pub serial_number: Option<String>,
672
673    /// Asset tag number
674    pub asset_tag_number: Option<String>,
675
676    /// State of the enclosure whet it was last booted
677    pub bootup_state: Option<smbioslib::ChassisStateData>,
678
679    /// State of the enclosure's power supply when last booted
680    pub power_supply_state: Option<smbioslib::ChassisStateData>,
681
682    /// Thermal state of the enclosure when last booted
683    pub thermal_state: Option<smbioslib::ChassisStateData>,
684
685    /// Physical security status of the enclosure when last booted
686    pub security_status: Option<smbioslib::ChassisSecurityStatusData>,
687
688    /// OEM- or BIOS vendor-specific information
689    pub oem_defined: Option<u32>,
690
691    /// Height of the enclosure, in 'U's
692    ///
693    /// A U is a standard unit of measure for the height of a rack
694    /// or rack-mountable component and is equal to 1.75 inches or
695    /// 4.445 cm
696    pub height: Option<smbioslib::ChassisHeight>,
697
698    /// Number of power cords associated with the enclosure/chassis
699    pub number_of_power_cords: Option<smbioslib::PowerCords>,
700
701    /// Number of Contained Element records that follow, in the
702    /// range 0 to 255 Each Contained Element group comprises m
703    /// bytes, as specified by the Contained Element Record Length
704    /// field that follows. If no Contained Elements are included,
705    /// this field is set to 0.
706    pub contained_element_count: Option<u8>,
707
708    /// Byte length of eact Contained Element record that follows,
709    /// in the range 0 to 255. If no Contained Elements are included,
710    /// this field is set to 0
711    pub contained_element_record_length: Option<u8>,
712
713    // TODO: this struct doesn't included ContainedElements<'_> iter!
714    /// Chassis or enclosure SKU number
715    pub sku_number: Option<String>,
716}
717
718impl Chassis {
719    /// Creates a new instance of `Self`
720    ///
721    /// It is usually not required, since an instance of this
722    /// structure will be created using the method
723    /// `Self::new_from_table(table: &SMBiosData)` in the constructor
724    /// [`DMITable::new()`].
725    pub fn new() -> Result<Self> {
726        let table = smbioslib::table_load_from_device()?;
727        Self::new_from_table(&table)
728    }
729
730    pub fn new_from_table(table: &SMBiosData) -> Result<Self> {
731        let t = table
732            .find_map(|f: smbioslib::SMBiosSystemChassisInformation| Some(f))
733            .ok_or(anyhow!(
734                "Failed to get information about system enclosure/chassis (type 3)!"
735            ))?;
736
737        Ok(Self {
738            manufacturer: t.manufacturer().ok(),
739            chassis_type: t.chassis_type(),
740            version: t.version().ok(),
741            serial_number: t.serial_number().ok(),
742            asset_tag_number: t.asset_tag_number().ok(),
743            bootup_state: t.bootup_state(),
744            power_supply_state: t.power_supply_state(),
745            thermal_state: t.thermal_state(),
746            security_status: t.security_status(),
747            oem_defined: t.oem_defined(),
748            height: t.height(),
749            number_of_power_cords: t.number_of_power_cords(),
750            contained_element_count: t.contained_element_count(),
751            contained_element_record_length: t.contained_element_record_length(),
752            sku_number: t.sku_number().ok(),
753        })
754    }
755}
756
757impl ToJson for Chassis {}
758
759/// Information about processor
760#[derive(Debug, Serialize)]
761pub struct Processor {
762    /// Socket reference designation
763    pub socked_designation: Option<String>,
764
765    /// Processor type
766    pub processor_type: Option<smbioslib::ProcessorTypeData>,
767
768    /// Processor family
769    pub processor_family: Option<smbioslib::ProcessorFamilyData>,
770
771    /// Processor manufacturer
772    pub processor_manufacturer: Option<String>,
773
774    /// Raw processor identification data
775    pub processor_id: Option<[u8; 8]>,
776
777    /// Processor version
778    pub processor_version: Option<String>,
779
780    /// Processor voltage
781    pub voltage: Option<smbioslib::ProcessorVoltage>,
782
783    /// External clock frequency, MHz. If the value is unknown,
784    /// the field is set to 0
785    pub external_clock: Option<smbioslib::ProcessorExternalClock>,
786
787    /// Maximum CPU speed (in MHz) supported *by the system* for this
788    /// processor socket
789    pub max_speed: Option<smbioslib::ProcessorSpeed>,
790
791    /// Current speed
792    ///
793    /// This field identifies the processor's speed at system boot;
794    /// the processor may support more than one speed
795    pub current_speed: Option<smbioslib::ProcessorSpeed>,
796
797    /// Status bit field
798    pub status: Option<smbioslib::ProcessorStatus>,
799
800    /// Processor upgrade
801    pub processor_upgrade: Option<smbioslib::ProcessorUpgradeData>,
802
803    /// Attributes of the primary (Level 1) cache for this processor
804    pub l1cache_handle: Option<smbioslib::Handle>,
805
806    /// Attributes of the primary (Level 2) cache for this processor
807    pub l2cache_handle: Option<smbioslib::Handle>,
808
809    /// Attributes of the primary (Level 3) cache for this processor
810    pub l3cache_handle: Option<smbioslib::Handle>,
811
812    /// Serial number of this processor
813    pub serial_number: Option<String>,
814
815    /// Asset tag of this proc
816    pub asset_tag: Option<String>,
817
818    /// Part number of this processor
819    pub part_number: Option<String>,
820
821    /// Number of cores per processor socket
822    pub core_count: Option<smbioslib::CoreCount>,
823
824    /// Number of enabled cores per processor socket
825    pub cores_enabled: Option<smbioslib::CoresEnabled>,
826
827    /// Number of threads per processor socket
828    pub thread_count: Option<smbioslib::ThreadCount>,
829
830    /// Function that processor supports
831    pub processors_characteristics: Option<ProcessorCharacteristics>,
832
833    /// Processor family 2
834    pub processor_family_2: Option<smbioslib::ProcessorFamilyData2>,
835
836    /// Number of cores per proc socket (if cores > 255)
837    pub core_count_2: Option<smbioslib::CoreCount2>,
838
839    /// Number of enabled cores per proc socket (if ecores > 255)
840    pub cores_enabled_2: Option<smbioslib::CoresEnabled2>,
841
842    /// Number of threads per proc socket (if threads > 255)
843    pub thread_count_2: Option<smbioslib::ThreadCount2>,
844
845    /// Number of threads the BIOS has enabled and available for
846    /// OS use
847    pub thread_enabled: Option<smbioslib::ThreadEnabled>,
848}
849
850impl Processor {
851    /// Creates a new instance of `Self`
852    ///
853    /// It is usually not required, since an instance of this
854    /// structure will be created using the method
855    /// `Self::new_from_table(table: &SMBiosData)` in the constructor
856    /// [`DMITable::new()`].
857    pub fn new() -> Result<Self> {
858        let table = smbioslib::table_load_from_device()?;
859        Self::new_from_table(&table)
860    }
861
862    pub fn new_from_table(table: &SMBiosData) -> Result<Self> {
863        let t = table
864            .find_map(|f: smbioslib::SMBiosProcessorInformation| Some(f))
865            .ok_or(anyhow!("Failed to get information about CPU (type 4)!"))?;
866
867        Ok(Self {
868            socked_designation: t.socket_designation().ok(),
869            processor_type: t.processor_type(),
870            processor_family: t.processor_family(),
871            processor_manufacturer: t.processor_manufacturer().ok(),
872            processor_id: match t.processor_id() {
873                Some(p_id) => Some(*p_id),
874                None => None,
875            },
876            processor_version: t.processor_version().ok(),
877            voltage: t.voltage(),
878            external_clock: t.external_clock(),
879            max_speed: t.max_speed(),
880            current_speed: t.current_speed(),
881            status: t.status(),
882            processor_upgrade: t.processor_upgrade(),
883            l1cache_handle: t.l1cache_handle(),
884            l2cache_handle: t.l2cache_handle(),
885            l3cache_handle: t.l3cache_handle(),
886            serial_number: t.serial_number().ok(),
887            asset_tag: t.asset_tag().ok(),
888            part_number: t.part_number().ok(),
889            core_count: t.core_count(),
890            cores_enabled: t.cores_enabled(),
891            thread_count: t.thread_count(),
892            processors_characteristics: match t.processor_characteristics() {
893                Some(pc) => Some(ProcessorCharacteristics::from(pc)),
894                None => None,
895            },
896            processor_family_2: t.processor_family_2(),
897            core_count_2: t.core_count_2(),
898            cores_enabled_2: t.cores_enabled_2(),
899            thread_count_2: t.thread_count_2(),
900            thread_enabled: t.thread_enabled(),
901        })
902    }
903}
904
905impl ToJson for Processor {}
906
907/// Defines which functions the processor supports
908#[derive(Debug, Serialize)]
909pub struct ProcessorCharacteristics {
910    /// Bit 1 unknown
911    pub unknown: bool,
912
913    /// 64-bit capable
914    pub bit_64capable: bool,
915
916    /// Multi-core
917    pub multi_core: bool,
918
919    /// Hardware thread
920    pub hardware_thread: bool,
921
922    /// Execute protection
923    pub execute_protection: bool,
924
925    /// Enhanced Virtualization
926    pub enhanced_virtualization: bool,
927
928    /// Power/perfomance control
929    pub power_perfomance_control: bool,
930
931    /// 128-bit capable
932    pub bit_128capable: bool,
933
934    /// Arm64 SoC ID
935    pub arm_64soc_id: bool,
936}
937
938impl From<smbioslib::ProcessorCharacteristics> for ProcessorCharacteristics {
939    fn from(value: smbioslib::ProcessorCharacteristics) -> Self {
940        Self {
941            unknown: value.unknown(),
942            bit_64capable: value.bit_64capable(),
943            multi_core: value.multi_core(),
944            hardware_thread: value.hardware_thread(),
945            execute_protection: value.execute_protection(),
946            enhanced_virtualization: value.enhanced_virtualization(),
947            power_perfomance_control: value.power_performance_control(),
948            bit_128capable: value.bit_128capable(),
949            arm_64soc_id: value.arm_64soc_id(),
950        }
951    }
952}
953impl ToJson for ProcessorCharacteristics {}
954
955/// Attributes of each CPU cache device in the system
956#[derive(Debug, Serialize)]
957pub struct Caches {
958    pub caches: Vec<Cache>,
959}
960
961impl Caches {
962    /// Creates a new instance of `Self`
963    ///
964    /// It is usually not required, since an instance of this
965    /// structure will be created using the method
966    /// `Self::new_from_table(table: &SMBiosData)` in the constructor
967    /// [`DMITable::new()`].
968    pub fn new() -> Result<Self> {
969        let table = smbioslib::table_load_from_device()?;
970        Self::new_from_table(&table)
971    }
972
973    pub fn new_from_table(table: &SMBiosData) -> Result<Self> {
974        let mut caches = vec![];
975
976        for cache_device in table.collect::<smbioslib::SMBiosCacheInformation>() {
977            caches.push(Cache::from(cache_device));
978        }
979
980        Ok(Self { caches })
981    }
982}
983
984impl ToJson for Caches {}
985
986/// This structure defines the attributes of CPU cache device in the
987/// system. One structure is specified for each such device, whether
988/// the device is internal to or external to the CPU module.
989#[derive(Debug, Serialize)]
990pub struct Cache {
991    /// String number for reference designation
992    pub socket_designation: Option<String>,
993
994    /// Bit fields describing the cache configuration
995    pub cache_configuration: Option<smbioslib::CacheConfiguaration>,
996
997    /// Maximum size that can be installed
998    pub maximum_cache_size: Option<smbioslib::CacheMemorySize>,
999
1000    /// Same format as Max Cache Size field; set 0 if no cache
1001    /// is installed.
1002    pub installed_size: Option<smbioslib::CacheMemorySize>,
1003
1004    /// Supported SRAM type
1005    pub supported_sram_type: Option<smbioslib::SramTypes>,
1006
1007    /// Current SRAM type
1008    pub current_sram_type: Option<smbioslib::SramTypes>,
1009
1010    /// Cache module speed, in nanosecs. The value is 0 if the
1011    /// speed is unknown
1012    pub cache_speed: Option<u8>,
1013
1014    /// Error-correction scheme supported by this cache component
1015    pub error_correction_type: Option<smbioslib::ErrorCorrectionTypeData>,
1016
1017    /// Logical type of cache
1018    pub system_cache_type: Option<smbioslib::SystemCacheTypeData>,
1019
1020    /// Associativity of the cache
1021    pub associativity: Option<smbioslib::CacheAssociativityData>,
1022
1023    /// Maximum cache size
1024    pub maximum_cache_size_2: Option<smbioslib::CacheMemorySize>,
1025
1026    /// Installed cache size
1027    pub installed_cache_size_2: Option<smbioslib::CacheMemorySize>,
1028}
1029
1030impl<'a> From<smbioslib::SMBiosCacheInformation<'a>> for Cache {
1031    fn from(value: smbioslib::SMBiosCacheInformation) -> Self {
1032        Self {
1033            socket_designation: value.socket_designation().ok(),
1034            cache_configuration: value.cache_configuration(),
1035            maximum_cache_size: value.maximum_cache_size(),
1036            installed_size: value.installed_size(),
1037            supported_sram_type: value.supported_sram_type(),
1038            current_sram_type: value.current_sram_type(),
1039            cache_speed: value.cache_speed(),
1040            error_correction_type: value.error_correction_type(),
1041            system_cache_type: value.system_cache_type(),
1042            associativity: value.associativity(),
1043            maximum_cache_size_2: value.maximum_cache_size_2(),
1044            installed_cache_size_2: value.installed_cache_size_2(),
1045        }
1046    }
1047}
1048impl ToJson for Cache {}
1049
1050/// Attributes of a system port connectors
1051#[derive(Debug, Serialize)]
1052pub struct PortConnectors {
1053    pub ports: Vec<Port>,
1054}
1055
1056impl PortConnectors {
1057    /// Creates a new instance of `Self`
1058    ///
1059    /// It is usually not required, since an instance of this
1060    /// structure will be created using the method
1061    /// `Self::new_from_table(table: &SMBiosData)` in the constructor
1062    /// [`DMITable::new()`].
1063    pub fn new() -> Result<Self> {
1064        let table = smbioslib::table_load_from_device()?;
1065        Self::new_from_table(&table)
1066    }
1067
1068    pub fn new_from_table(table: &SMBiosData) -> Result<Self> {
1069        let mut ports = vec![];
1070
1071        for port in table.collect::<smbioslib::SMBiosPortConnectorInformation>() {
1072            ports.push(Port::from(port));
1073        }
1074
1075        Ok(Self { ports })
1076    }
1077}
1078
1079impl ToJson for PortConnectors {}
1080
1081/// Attributes of a system port connector (serial, parallel,
1082/// keyboard or mouse ports)
1083#[derive(Debug, Serialize)]
1084pub struct Port {
1085    /// Internal reference designator, that is, internal to the
1086    /// system enclosure
1087    pub internal_reference_designator: Option<String>,
1088
1089    /// Internal connector type
1090    pub internal_connector_type: Option<smbioslib::PortInformationConnectorTypeData>,
1091
1092    /// External reference designation, external to the system
1093    /// enclosure
1094    pub external_reference_designator: Option<String>,
1095
1096    /// External connector type
1097    pub external_connector_type: Option<smbioslib::PortInformationConnectorTypeData>,
1098
1099    /// Function of the port
1100    pub port_type: Option<smbioslib::PortInformationPortTypeData>,
1101}
1102
1103impl<'a> From<smbioslib::SMBiosPortConnectorInformation<'a>> for Port {
1104    fn from(value: smbioslib::SMBiosPortConnectorInformation) -> Self {
1105        Self {
1106            internal_reference_designator: value.internal_reference_designator().ok(),
1107            internal_connector_type: value.internal_connector_type(),
1108            external_reference_designator: value.external_reference_designator().ok(),
1109            external_connector_type: value.external_connector_type(),
1110            port_type: value.port_type(),
1111        }
1112    }
1113}
1114impl ToJson for Port {}
1115
1116/// Collection of memory devices that operate together to form a memory address space
1117#[derive(Debug, Serialize)]
1118pub struct MemoryArray {
1119    /// Physical location of the Memory Array, whether on the system
1120    /// board or an add-in board
1121    pub location: Option<smbioslib::MemoryArrayLocationData>,
1122
1123    /// Which the array is used
1124    pub usage: Option<smbioslib::MemoryArrayUseData>,
1125
1126    /// Primary hardware error correction or detection method
1127    /// supported by this memory array
1128    pub memory_error_correction: Option<smbioslib::MemoryArrayErrorCorrectionData>,
1129
1130    /// Maximum memory capacity, in kbytes, for this array
1131    pub maximum_capacity: Option<smbioslib::MaximumMemoryCapacity>,
1132
1133    /// Handle, or instance number, associated with any error that
1134    /// was previously detected for the array
1135    pub memory_error_information_handle: Option<smbioslib::Handle>,
1136
1137    /// Number of slots/sockets available for memory devices in
1138    /// this array
1139    pub number_of_memory_devices: Option<u16>,
1140
1141    /// Maximum memory capacity, in bytes, for this array. This
1142    /// field is only valid when the Maximum Capacity field
1143    /// contains 8000 0000h.
1144    pub extended_maximum_capacity: Option<u64>,
1145}
1146
1147impl MemoryArray {
1148    /// Creates a new instance of `Self`
1149    ///
1150    /// It is usually not required, since an instance of this
1151    /// structure will be created using the method
1152    /// `Self::new_from_table(table: &SMBiosData)` in the constructor
1153    /// [`DMITable::new()`].
1154    pub fn new() -> Result<Self> {
1155        let table = smbioslib::table_load_from_device()?;
1156        Self::new_from_table(&table)
1157    }
1158
1159    pub fn new_from_table(table: &SMBiosData) -> Result<Self> {
1160        let t = table
1161            .find_map(|f: smbioslib::SMBiosPhysicalMemoryArray| Some(f))
1162            .ok_or(anyhow!(
1163                "Failed to get information about memory array (type 16)!"
1164            ))?;
1165
1166        Ok(Self {
1167            location: t.location(),
1168            usage: t.usage(),
1169            memory_error_correction: t.memory_error_correction(),
1170            maximum_capacity: t.maximum_capacity(),
1171            memory_error_information_handle: t.memory_error_information_handle(),
1172            number_of_memory_devices: t.number_of_memory_devices(),
1173            extended_maximum_capacity: t.extended_maximum_capacity(),
1174        })
1175    }
1176}
1177
1178impl ToJson for MemoryArray {}
1179
1180/// Information about all installed memory devices
1181#[derive(Debug, Serialize)]
1182pub struct MemoryDevices {
1183    pub memory: Vec<MemoryDevice>,
1184}
1185
1186impl MemoryDevices {
1187    /// Creates a new instance of `Self`
1188    ///
1189    /// It is usually not required, since an instance of this
1190    /// structure will be created using the method
1191    /// `Self::new_from_table(table: &SMBiosData)` in the constructor
1192    /// [`DMITable::new()`].
1193    pub fn new() -> Result<Self> {
1194        let table = smbioslib::table_load_from_device()?;
1195        Self::new_from_table(&table)
1196    }
1197
1198    pub fn new_from_table(table: &SMBiosData) -> Result<Self> {
1199        let mut memory = vec![];
1200
1201        for mem in table.collect::<smbioslib::SMBiosMemoryDevice>() {
1202            memory.push(MemoryDevice::from(mem));
1203        }
1204
1205        Ok(Self { memory })
1206    }
1207}
1208
1209impl ToJson for MemoryDevices {}
1210
1211/// Information about single memory device
1212#[derive(Debug, Serialize)]
1213pub struct MemoryDevice {
1214    /// Handle or instance number, associated with the physical
1215    /// memory array to which this device belongs
1216    pub physical_memory_array_handle: Option<smbioslib::Handle>,
1217
1218    /// Handle or instance number, associated with any error that
1219    /// was previously detected for the device. If the system does
1220    /// not provide the error information structure, the field
1221    /// containes FFFEH
1222    pub memory_error_information_handle: Option<smbioslib::Handle>,
1223
1224    /// Total width, in bits, of this memory device, including any
1225    /// check or error-correction bits
1226    pub total_width: Option<u16>,
1227
1228    /// Data width, in bits, of this memory device
1229    pub data_width: Option<u16>,
1230
1231    /// Size of memory device
1232    pub size: Option<smbioslib::MemorySize>,
1233
1234    /// Form factor for this memory device
1235    pub form_factor: Option<smbioslib::MemoryFormFactorData>,
1236
1237    /// Identifies when the Memory Device is one of a set of
1238    /// Memory Devices that must be populated with all devices
1239    /// of the same type and size, and the set to which this
1240    /// device belongs A value of 0 indicates that the device
1241    /// is not part of a set; a value of FFh indicates that the
1242    /// attribute is unknown
1243    pub device_set: Option<u8>,
1244
1245    /// Physically-labeled socket or board position where the
1246    /// memory device is located
1247    pub device_locator: Option<String>,
1248
1249    /// Physically-labeled bank where the memory device is located
1250    pub bank_locator: Option<String>,
1251
1252    /// Type of memory used in this device
1253    pub memory_type: Option<smbioslib::MemoryDeviceTypeData>,
1254
1255    /// Additional detail on the memory device type
1256    pub type_detail: Option<smbioslib::MemoryTypeDetails>,
1257
1258    /// The maximum capable speed of the device (MT/s)
1259    pub speed: Option<smbioslib::MemorySpeed>,
1260
1261    /// Manufacturer of this memory device
1262    pub manufacturer: Option<String>,
1263
1264    /// Serial number of this memory device
1265    pub serial_number: Option<String>,
1266
1267    /// Asset tag of this memory device
1268    pub asset_tag: Option<String>,
1269
1270    /// Part number of this memory device
1271    pub part_number: Option<String>,
1272
1273    /// Bits 7-4: reserved Bits 3-0: rank Value=0 for unknown rank information
1274    pub attributes: Option<u8>,
1275
1276    /// Extended suze of the memory device in MB
1277    pub extended_size: Option<smbioslib::MemorySizeExtended>,
1278
1279    /// Configured speed of the memory device, in megatransfers per second (MT/s)
1280    pub configured_memory_speed: Option<smbioslib::MemorySpeed>,
1281
1282    /// Minimum operating voltage for this device, in millivolts
1283    pub minimum_voltage: Option<u16>,
1284
1285    /// Maximum operating voltage for this device, in millivolts
1286    pub maximum_voltage: Option<u16>,
1287
1288    /// Configured voltage for this device, in millivolts
1289    pub configured_voltage: Option<u16>,
1290
1291    /// Memory technology type for this memory device
1292    pub memory_technology: Option<smbioslib::MemoryDeviceTechnologyData>,
1293
1294    /// The operating modes supported by this memory device
1295    pub memory_operating_mode_capability: Option<smbioslib::MemoryOperatingModeCapabilities>,
1296
1297    /// Firmware version of this memory device
1298    pub firmware_version: Option<String>,
1299
1300    /// Two-byte module manufacturer ID found in the SPD of this
1301    /// memory device; LSB first
1302    pub module_manufacturer_id: Option<u16>,
1303
1304    /// Two-byte module product id found in the SPD of this memory
1305    /// device; LSB first
1306    pub module_product_id: Option<u16>,
1307
1308    /// Two-byte memory subsystem controller manufacturer ID found
1309    /// in the SPD of this memory device; LSB first
1310    pub memory_subsystem_controller_manufacturer_id: Option<u16>,
1311
1312    /// Two-byte memory subsystem controller product ID found in
1313    /// the SPD of this memory device; LSB first
1314    pub memory_subsystem_controller_product_id: Option<u16>,
1315
1316    /// Size of the Non-volatile portion of the memory device in
1317    /// Bytes, if any
1318    pub non_volatile_size: Option<smbioslib::MemoryIndicatedSize>,
1319
1320    /// Size of the Volatile portion of the memory device in
1321    /// Bytes, if any
1322    pub volatile_size: Option<smbioslib::MemoryIndicatedSize>,
1323
1324    /// Size of the Cache portion of the memory device in Bytes,
1325    /// if any
1326    pub cache_size: Option<smbioslib::MemoryIndicatedSize>,
1327
1328    /// Size of the Logical memory device in Bytes
1329    pub logical_size: Option<smbioslib::MemoryIndicatedSize>,
1330
1331    /// Extended speed of the memory device (complements the
1332    /// Speed field at offset 15h). Identifies the maximum capable
1333    /// speed of the device, in MT/s
1334    pub extended_speed: Option<smbioslib::MemorySpeedExtended>,
1335
1336    /// Extended configured memory speed of the memory device
1337    /// (complements the `configure_memory_speed` field at offset
1338    /// 20h). Identifies the configured speed of the memory device,
1339    /// in MT/s
1340    pub extended_configured_speed: Option<smbioslib::MemorySpeedExtended>,
1341
1342    /// Two-byte PMIC0 manufacturer ID found in the SPD of this
1343    /// memory device; LSB first
1344    pub pmic0_manufacturer_id: Option<u16>,
1345
1346    /// PMIC 0 Revision Number found in the SPD of this memory
1347    /// device
1348    pub pmic0_revision_number: Option<u16>,
1349
1350    /// Two-byte RCD manufacturer ID found in the SPD of this
1351    /// memory device; LSB first
1352    pub rcd_manufacturer_id: Option<u16>,
1353
1354    /// RCD 0 Revision Number found in the SPD of this memory
1355    /// device
1356    pub rcd_revision_number: Option<u16>,
1357}
1358
1359impl<'a> From<smbioslib::SMBiosMemoryDevice<'a>> for MemoryDevice {
1360    fn from(value: smbioslib::SMBiosMemoryDevice) -> Self {
1361        Self {
1362            physical_memory_array_handle: value.physical_memory_array_handle(),
1363            memory_error_information_handle: value.memory_error_information_handle(),
1364            total_width: value.total_width(),
1365            data_width: value.data_width(),
1366            size: value.size(),
1367            form_factor: value.form_factor(),
1368            device_set: value.device_set(),
1369            device_locator: value.device_locator().ok(),
1370            bank_locator: value.bank_locator().ok(),
1371            memory_type: value.memory_type(),
1372            type_detail: value.type_detail(),
1373            speed: value.speed(),
1374            manufacturer: value.manufacturer().ok(),
1375            serial_number: value.serial_number().ok(),
1376            asset_tag: value.asset_tag().ok(),
1377            part_number: value.part_number().ok(),
1378            attributes: value.attributes(),
1379            extended_size: value.extended_size(),
1380            configured_memory_speed: value.configured_memory_speed(),
1381            minimum_voltage: value.minimum_voltage(),
1382            maximum_voltage: value.maximum_voltage(),
1383            configured_voltage: value.configured_voltage(),
1384            memory_technology: value.memory_technology(),
1385            memory_operating_mode_capability: value.memory_operating_mode_capability(),
1386            firmware_version: value.firmware_version().ok(),
1387            module_manufacturer_id: value.module_manufacturer_id(),
1388            module_product_id: value.module_product_id(),
1389            memory_subsystem_controller_manufacturer_id: value
1390                .memory_subsystem_controller_manufacturer_id(),
1391            memory_subsystem_controller_product_id: value.memory_subsystem_controller_product_id(),
1392            non_volatile_size: value.non_volatile_size(),
1393            volatile_size: value.volatile_size(),
1394            cache_size: value.cache_size(),
1395            logical_size: value.logical_size(),
1396            extended_speed: value.extended_speed(),
1397            extended_configured_speed: value.extended_speed(),
1398            pmic0_manufacturer_id: value.pmic0_manufacturer_id(),
1399            pmic0_revision_number: value.pmic0_revision_number(),
1400            rcd_manufacturer_id: value.rcd_manufacturer_id(),
1401            rcd_revision_number: value.rcd_revision_number(),
1402        }
1403    }
1404}
1405impl ToJson for MemoryDevice {}