diff --git a/uefi-raw/CHANGELOG.md b/uefi-raw/CHANGELOG.md index 1e5c30e5e..a2e8aefea 100644 --- a/uefi-raw/CHANGELOG.md +++ b/uefi-raw/CHANGELOG.md @@ -3,6 +3,7 @@ ## Added - Added `DeviceType` and `DeviceSubType` enums. +- Added device path node types in the `protocol::device_path` module. # uefi-raw - 0.8.0 (2024-09-09) diff --git a/uefi-raw/src/protocol/device_path.rs b/uefi-raw/src/protocol/device_path.rs index 3e1462d14..a6c2addd0 100644 --- a/uefi-raw/src/protocol/device_path.rs +++ b/uefi-raw/src/protocol/device_path.rs @@ -1,5 +1,9 @@ +mod device_path_gen; + use crate::{guid, Char16, Guid}; +pub use device_path_gen::{acpi, bios_boot_spec, end, hardware, media, messaging}; + /// Device path protocol. /// /// A device path contains one or more device path instances made of up diff --git a/uefi-raw/src/protocol/device_path/device_path_gen.rs b/uefi-raw/src/protocol/device_path/device_path_gen.rs new file mode 100644 index 000000000..33c6dc4b0 --- /dev/null +++ b/uefi-raw/src/protocol/device_path/device_path_gen.rs @@ -0,0 +1,505 @@ +// DO NOT EDIT +// +// This file was automatically generated with: +// `cargo xtask gen-code` +// +// See `/xtask/src/device_path/README.md` for more details. +#![allow(clippy::missing_const_for_fn)] +#![allow(missing_debug_implementations)] +use crate::protocol::device_path; +use crate::table::boot::MemoryType; +use crate::{guid, Guid, IpAddress}; +use bitflags::bitflags; +use device_path::DevicePathProtocol as DevicePathHeader; +#[cfg(doc)] +use device_path::DeviceType; +/// Device path nodes for [`DeviceType::END`]. +pub mod end { + use super::*; + #[repr(C, packed)] + pub struct Instance { + pub header: DevicePathHeader, + } + + #[repr(C, packed)] + pub struct Entire { + pub header: DevicePathHeader, + } +} + +/// Device path nodes for [`DeviceType::HARDWARE`]. +pub mod hardware { + use super::*; + #[repr(C, packed)] + pub struct Pci { + pub header: DevicePathHeader, + pub function: u8, + pub device: u8, + } + + #[repr(C, packed)] + pub struct Pccard { + pub header: DevicePathHeader, + pub function: u8, + } + + #[repr(C, packed)] + pub struct MemoryMapped { + pub header: DevicePathHeader, + pub memory_type: MemoryType, + pub start_address: u64, + pub end_address: u64, + } + + #[repr(C, packed)] + pub struct Vendor { + pub header: DevicePathHeader, + pub vendor_guid: Guid, + pub vendor_defined_data: [u8; 0usize], + } + + #[repr(C, packed)] + pub struct Controller { + pub header: DevicePathHeader, + pub controller_number: u32, + } + + #[repr(C, packed)] + pub struct Bmc { + pub header: DevicePathHeader, + pub interface_type: device_path::hardware::BmcInterfaceType, + pub base_address: u64, + } + + newtype_enum! { # [doc = " Baseboard Management Controller (BMC) host interface type."] pub enum BmcInterfaceType : u8 => { # [doc = " Unknown."] UNKNOWN = 0x00 , # [doc = " Keyboard controller style."] KEYBOARD_CONTROLLER_STYLE = 0x01 , # [doc = " Server management interface chip."] SERVER_MANAGEMENT_INTERFACE_CHIP = 0x02 , # [doc = " Block transfer."] BLOCK_TRANSFER = 0x03 , } + + } +} + +/// Device path nodes for [`DeviceType::ACPI`]. +pub mod acpi { + use super::*; + #[repr(C, packed)] + pub struct Acpi { + pub header: DevicePathHeader, + pub hid: u32, + pub uid: u32, + } + + #[repr(C, packed)] + pub struct Expanded { + pub header: DevicePathHeader, + pub hid: u32, + pub uid: u32, + pub cid: u32, + pub data: [u8; 0], + } + + #[repr(C, packed)] + pub struct Adr { + pub header: DevicePathHeader, + pub adr: [u32; 0usize], + } + + #[repr(C, packed)] + pub struct Nvdimm { + pub header: DevicePathHeader, + pub nfit_device_handle: u32, + } +} + +/// Device path nodes for [`DeviceType::MESSAGING`]. +pub mod messaging { + use super::*; + #[repr(C, packed)] + pub struct Atapi { + pub header: DevicePathHeader, + pub primary_secondary: device_path::messaging::PrimarySecondary, + pub master_slave: device_path::messaging::MasterSlave, + pub logical_unit_number: u16, + } + + #[repr(C, packed)] + pub struct Scsi { + pub header: DevicePathHeader, + pub target_id: u16, + pub logical_unit_number: u16, + } + + #[repr(C, packed)] + pub struct FibreChannel { + pub header: DevicePathHeader, + pub _reserved: u32, + pub world_wide_name: u64, + pub logical_unit_number: u64, + } + + #[repr(C, packed)] + pub struct FibreChannelEx { + pub header: DevicePathHeader, + pub _reserved: u32, + pub world_wide_name: [u8; 8usize], + pub logical_unit_number: [u8; 8usize], + } + + #[repr(C, packed)] + pub struct Ieee1394 { + pub header: DevicePathHeader, + pub _reserved: u32, + pub guid: [u8; 8usize], + } + + #[repr(C, packed)] + pub struct Usb { + pub header: DevicePathHeader, + pub parent_port_number: u8, + pub interface: u8, + } + + #[repr(C, packed)] + pub struct Sata { + pub header: DevicePathHeader, + pub hba_port_number: u16, + pub port_multiplier_port_number: u16, + pub logical_unit_number: u16, + } + + #[repr(C, packed)] + pub struct UsbWwid { + pub header: DevicePathHeader, + pub interface_number: u16, + pub device_vendor_id: u16, + pub device_product_id: u16, + pub serial_number: [u16; 0usize], + } + + #[repr(C, packed)] + pub struct DeviceLogicalUnit { + pub header: DevicePathHeader, + pub logical_unit_number: u8, + } + + #[repr(C, packed)] + pub struct UsbClass { + pub header: DevicePathHeader, + pub vendor_id: u16, + pub product_id: u16, + pub device_class: u8, + pub device_subclass: u8, + pub device_protocol: u8, + } + + #[repr(C, packed)] + pub struct I2o { + pub header: DevicePathHeader, + pub target_id: u32, + } + + #[repr(C, packed)] + pub struct MacAddress { + pub header: DevicePathHeader, + pub mac_address: [u8; 32usize], + pub interface_type: u8, + } + + #[repr(C, packed)] + pub struct Ipv4 { + pub header: DevicePathHeader, + pub local_ip_address: [u8; 4usize], + pub remote_ip_address: [u8; 4usize], + pub local_port: u16, + pub remote_port: u16, + pub protocol: u16, + pub ip_address_origin: device_path::messaging::Ipv4AddressOrigin, + pub gateway_ip_address: [u8; 4usize], + pub subnet_mask: [u8; 4usize], + } + + #[repr(C, packed)] + pub struct Ipv6 { + pub header: DevicePathHeader, + pub local_ip_address: [u8; 16usize], + pub remote_ip_address: [u8; 16usize], + pub local_port: u16, + pub remote_port: u16, + pub protocol: u16, + pub ip_address_origin: device_path::messaging::Ipv6AddressOrigin, + pub prefix_length: u8, + pub gateway_ip_address: [u8; 16usize], + } + + #[repr(C, packed)] + pub struct Vlan { + pub header: DevicePathHeader, + pub vlan_id: u16, + } + + #[repr(C, packed)] + pub struct Infiniband { + pub header: DevicePathHeader, + pub resource_flags: device_path::messaging::InfinibandResourceFlags, + pub port_gid: [u8; 16usize], + pub ioc_guid_or_service_id: u64, + pub target_port_id: u64, + pub device_id: u64, + } + + #[repr(C, packed)] + pub struct Uart { + pub header: DevicePathHeader, + pub _reserved: u32, + pub baud_rate: u64, + pub data_bits: u8, + pub parity: device_path::messaging::Parity, + pub stop_bits: device_path::messaging::StopBits, + } + + #[repr(C, packed)] + pub struct Vendor { + pub header: DevicePathHeader, + pub vendor_guid: Guid, + pub vendor_defined_data: [u8; 0usize], + } + + #[repr(C, packed)] + pub struct SasEx { + pub header: DevicePathHeader, + pub sas_address: [u8; 8usize], + pub logical_unit_number: [u8; 8usize], + pub info: u16, + pub relative_target_port: u16, + } + + #[repr(C, packed)] + pub struct Iscsi { + pub header: DevicePathHeader, + pub protocol: device_path::messaging::IscsiProtocol, + pub options: device_path::messaging::IscsiLoginOptions, + pub logical_unit_number: [u8; 8usize], + pub target_portal_group_tag: u16, + pub iscsi_target_name: [u8; 0usize], + } + + #[repr(C, packed)] + pub struct NvmeNamespace { + pub header: DevicePathHeader, + pub namespace_identifier: u32, + pub ieee_extended_unique_identifier: u64, + } + + #[repr(C, packed)] + pub struct Uri { + pub header: DevicePathHeader, + pub value: [u8; 0usize], + } + + #[repr(C, packed)] + pub struct Ufs { + pub header: DevicePathHeader, + pub target_id: u8, + pub logical_unit_number: u8, + } + + #[repr(C, packed)] + pub struct Sd { + pub header: DevicePathHeader, + pub slot_number: u8, + } + + #[repr(C, packed)] + pub struct Bluetooth { + pub header: DevicePathHeader, + pub device_address: [u8; 6usize], + } + + #[repr(C, packed)] + pub struct Wifi { + pub header: DevicePathHeader, + pub ssid: [u8; 32usize], + } + + #[repr(C, packed)] + pub struct Emmc { + pub header: DevicePathHeader, + pub slot_number: u8, + } + + #[repr(C, packed)] + pub struct BluetoothLe { + pub header: DevicePathHeader, + pub device_address: [u8; 6usize], + pub address_type: device_path::messaging::BluetoothLeAddressType, + } + + #[repr(C, packed)] + pub struct Dns { + pub header: DevicePathHeader, + pub address_type: device_path::messaging::DnsAddressType, + pub addresses: [IpAddress; 0usize], + } + + #[repr(C, packed)] + pub struct NvdimmNamespace { + pub header: DevicePathHeader, + pub uuid: [u8; 16usize], + } + + #[repr(C, packed)] + pub struct RestService { + pub header: DevicePathHeader, + pub service_type: device_path::messaging::RestServiceType, + pub access_mode: device_path::messaging::RestServiceAccessMode, + pub vendor_guid_and_data: [u8; 0usize], + } + + #[repr(C, packed)] + pub struct NvmeOfNamespace { + pub header: DevicePathHeader, + pub nidt: u8, + pub nid: [u8; 16usize], + pub subsystem_nqn: [u8; 0usize], + } + + newtype_enum! { # [doc = " Whether the ATAPI device is primary or secondary."] pub enum PrimarySecondary : u8 => { # [doc = " Primary."] PRIMARY = 0x00 , # [doc = " Secondary."] SECONDARY = 0x01 , } + + } + + newtype_enum! { # [doc = " Whether the ATAPI device is master or slave."] pub enum MasterSlave : u8 => { # [doc = " Master mode."] MASTER = 0x00 , # [doc = " Slave mode."] SLAVE = 0x01 , } + + } + + newtype_enum! { # [doc = " Origin of the source IP address."] pub enum Ipv4AddressOrigin : u8 => { # [doc = " Source IP address was assigned through DHCP."] DHCP = 0x00 , # [doc = " Source IP address is statically bound."] STATIC = 0x01 , } + + } + + newtype_enum! { # [doc = " Origin of the local IP address."] pub enum Ipv6AddressOrigin : u8 => { # [doc = " Local IP address was manually configured."] MANUAL = 0x00 , # [doc = " Local IP address assigned through IPv6 stateless"] # [doc = " auto-configuration."] STATELESS_AUTO_CONFIGURATION = 0x01 , # [doc = " Local IP address assigned through IPv6 stateful"] # [doc = " configuration."] STATEFUL_CONFIGURATION = 0x02 , } + + } + + bitflags! { # [doc = " Flags to identify/manage InfiniBand elements."] # [derive (Clone , Copy , Debug , Default , PartialEq , Eq , PartialOrd , Ord)] # [repr (transparent)] pub struct InfinibandResourceFlags : u32 { # [doc = " Set = service, unset = IOC."] const SERVICE = 0x0000_0001 ; # [doc = " Extended boot environment."] const EXTENDED_BOOT_ENVIRONMENT = 0x0000_0002 ; # [doc = " Console protocol."] const CONSOLE_PROTOCOL = 0x0000_0004 ; # [doc = " Storage protocol."] const STORAGE_PROTOCOL = 0x0000_0008 ; # [doc = " Network protocol."] const NETWORK_PROTOCOL = 0x0000_0010 ; } + + } + + newtype_enum! { # [doc = " UART parity setting."] pub enum Parity : u8 => { # [doc = " Default parity."] DEFAULT = 0x00 , # [doc = " No parity."] NO = 0x01 , # [doc = " Even parity."] EVEN = 0x02 , # [doc = " Odd parity."] ODD = 0x03 , # [doc = " Mark parity."] MARK = 0x04 , # [doc = " Space parity."] SPACE = 0x05 , } + + } + + newtype_enum! { # [doc = " UART number of stop bits."] pub enum StopBits : u8 => { # [doc = " Default number of stop bits."] DEFAULT = 0x00 , # [doc = " 1 stop bit."] ONE = 0x01 , # [doc = " 1.5 stop bits."] ONE_POINT_FIVE = 0x02 , # [doc = " 2 stop bits."] TWO = 0x03 , } + + } + + newtype_enum! { # [doc = " iSCSI network protocol."] pub enum IscsiProtocol : u16 => { # [doc = " TCP."] TCP = 0x0000 , } + + } + + bitflags! { # [doc = " iSCSI login options."] # [derive (Clone , Copy , Debug , Default , PartialEq , Eq , PartialOrd , Ord)] # [repr (transparent)] pub struct IscsiLoginOptions : u16 { # [doc = " Header digest using CRC32. If not set, no header digest."] const HEADER_DIGEST_USING_CRC32 = 0x0002 ; # [doc = " Data digest using CRC32. If not set, no data digest."] const DATA_DIGEST_USING_CRC32 = 0x0008 ; # [doc = " Auth method none. If not set, auth method CHAP."] const AUTH_METHOD_NONE = 0x0800 ; # [doc = " CHAP UNI. If not set, CHAP BI."] const CHAP_UNI = 0x1000 ; } + + } + + newtype_enum! { # [doc = " BluetoothLE address type."] pub enum BluetoothLeAddressType : u8 => { # [doc = " Public device address."] PUBLIC = 0x00 , # [doc = " Random device address."] RANDOM = 0x01 , } + + } + + newtype_enum! { # [doc = " Whether the address is IPv4 or IPv6."] pub enum DnsAddressType : u8 => { # [doc = " DNS server address is IPv4."] IPV4 = 0x00 , # [doc = " DNS server address is IPv6."] IPV6 = 0x01 , } + + } + + newtype_enum! { # [doc = " Type of REST service."] pub enum RestServiceType : u8 => { # [doc = " Redfish REST service."] REDFISH = 0x01 , # [doc = " OData REST service."] ODATA = 0x02 , # [doc = " Vendor-specific REST service."] VENDOR = 0xff , } + + } + + newtype_enum! { # [doc = " Whether the service is in-band or out-of-band."] pub enum RestServiceAccessMode : u8 => { # [doc = " In-band REST service."] IN_BAND = 0x01 , # [doc = " Out-of-band REST service."] OUT_OF_BAND = 0x02 , } + + } +} + +/// Device path nodes for [`DeviceType::MEDIA`]. +pub mod media { + use super::*; + #[repr(C, packed)] + pub struct HardDrive { + pub header: DevicePathHeader, + pub partition_number: u32, + pub partition_start: u64, + pub partition_size: u64, + pub partition_signature: [u8; 16usize], + pub partition_format: device_path::media::PartitionFormat, + pub signature_type: u8, + } + + #[repr(C, packed)] + pub struct CdRom { + pub header: DevicePathHeader, + pub boot_entry: u32, + pub partition_start: u64, + pub partition_size: u64, + } + + #[repr(C, packed)] + pub struct Vendor { + pub header: DevicePathHeader, + pub vendor_guid: Guid, + pub vendor_defined_data: [u8; 0usize], + } + + #[repr(C, packed)] + pub struct FilePath { + pub header: DevicePathHeader, + pub path_name: [u16; 0usize], + } + + #[repr(C, packed)] + pub struct Protocol { + pub header: DevicePathHeader, + pub protocol_guid: Guid, + } + + #[repr(C, packed)] + pub struct PiwgFirmwareFile { + pub header: DevicePathHeader, + pub data: [u8; 0usize], + } + + #[repr(C, packed)] + pub struct PiwgFirmwareVolume { + pub header: DevicePathHeader, + pub data: [u8; 0usize], + } + + #[repr(C, packed)] + pub struct RelativeOffsetRange { + pub header: DevicePathHeader, + pub _reserved: u32, + pub starting_offset: u64, + pub ending_offset: u64, + } + + #[repr(C, packed)] + pub struct RamDisk { + pub header: DevicePathHeader, + pub starting_address: u64, + pub ending_address: u64, + pub disk_type: device_path::media::RamDiskType, + pub disk_instance: u16, + } + + newtype_enum! { # [doc = " Hard drive partition format."] pub enum PartitionFormat : u8 => { # [doc = " MBR (PC-AT compatible Master Boot Record) format."] MBR = 0x01 , # [doc = " GPT (GUID Partition Table) format."] GPT = 0x02 , } + + } + + newtype_enum! { # [doc = " RAM disk type."] pub enum RamDiskType : Guid => { # [doc = " RAM disk with a raw disk format in volatile memory."] VIRTUAL_DISK = guid ! ("77ab535a-45fc-624b-5560-f7b281d1f96e") , # [doc = " RAM disk of an ISO image in volatile memory."] VIRTUAL_CD = guid ! ("3d5abd30-4175-87ce-6d64-d2ade523c4bb") , # [doc = " RAM disk with a raw disk format in persistent memory."] PERSISTENT_VIRTUAL_DISK = guid ! ("5cea02c9-4d07-69d3-269f-4496fbe096f9") , # [doc = " RAM disk of an ISO image in persistent memory."] PERSISTENT_VIRTUAL_CD = guid ! ("08018188-42cd-bb48-100f-5387d53ded3d") , } + + } +} + +/// Device path nodes for [`DeviceType::BIOS_BOOT_SPEC`]. +pub mod bios_boot_spec { + use super::*; + #[repr(C, packed)] + pub struct BootSpecification { + pub header: DevicePathHeader, + pub device_type: u16, + pub status_flag: u16, + pub description_string: [u8; 0usize], + } +} diff --git a/uefi/src/proto/device_path/device_path_gen.rs b/uefi/src/proto/device_path/device_path_gen.rs index 9dc098c1c..f669f08df 100644 --- a/uefi/src/proto/device_path/device_path_gen.rs +++ b/uefi/src/proto/device_path/device_path_gen.rs @@ -10,7 +10,7 @@ use crate::data_types::UnalignedSlice; use crate::mem::memory_map::MemoryType; use crate::polyfill::maybe_uninit_slice_as_mut_ptr; use crate::proto::device_path::{ - DevicePathHeader, DevicePathNode, DeviceSubType, DeviceType, NodeConversionError, + self, DevicePathHeader, DevicePathNode, DeviceSubType, DeviceType, NodeConversionError, }; use crate::proto::network::IpAddress; use crate::{guid, Guid}; @@ -24,7 +24,7 @@ pub mod end { use super::*; /// Node that terminates a [`DevicePathInstance`]. /// - /// [`DevicePathInstance`]: crate::proto::device_path::DevicePathInstance + /// [`DevicePathInstance`]: device_path::DevicePathInstance #[repr(C, packed)] pub struct Instance { pub(super) header: DevicePathHeader, @@ -53,7 +53,7 @@ pub mod end { /// Node that terminates an entire [`DevicePath`]. /// - /// [`DevicePath`]: crate::proto::device_path::DevicePath + /// [`DevicePath`]: device_path::DevicePath #[repr(C, packed)] pub struct Entire { pub(super) header: DevicePathHeader, @@ -312,14 +312,14 @@ pub mod hardware { #[repr(C, packed)] pub struct Bmc { pub(super) header: DevicePathHeader, - pub(super) interface_type: crate::proto::device_path::hardware::BmcInterfaceType, + pub(super) interface_type: device_path::hardware::BmcInterfaceType, pub(super) base_address: u64, } impl Bmc { /// Host interface type. #[must_use] - pub fn interface_type(&self) -> crate::proto::device_path::hardware::BmcInterfaceType { + pub fn interface_type(&self) -> device_path::hardware::BmcInterfaceType { self.interface_type } @@ -706,21 +706,21 @@ pub mod messaging { #[repr(C, packed)] pub struct Atapi { pub(super) header: DevicePathHeader, - pub(super) primary_secondary: crate::proto::device_path::messaging::PrimarySecondary, - pub(super) master_slave: crate::proto::device_path::messaging::MasterSlave, + pub(super) primary_secondary: device_path::messaging::PrimarySecondary, + pub(super) master_slave: device_path::messaging::MasterSlave, pub(super) logical_unit_number: u16, } impl Atapi { /// Whether the ATAPI device is primary or secondary. #[must_use] - pub fn primary_secondary(&self) -> crate::proto::device_path::messaging::PrimarySecondary { + pub fn primary_secondary(&self) -> device_path::messaging::PrimarySecondary { self.primary_secondary } /// Whether the ATAPI device is master or slave. #[must_use] - pub fn master_slave(&self) -> crate::proto::device_path::messaging::MasterSlave { + pub fn master_slave(&self) -> device_path::messaging::MasterSlave { self.master_slave } @@ -1297,7 +1297,7 @@ pub mod messaging { pub(super) local_port: u16, pub(super) remote_port: u16, pub(super) protocol: u16, - pub(super) ip_address_origin: crate::proto::device_path::messaging::Ipv4AddressOrigin, + pub(super) ip_address_origin: device_path::messaging::Ipv4AddressOrigin, pub(super) gateway_ip_address: [u8; 4usize], pub(super) subnet_mask: [u8; 4usize], } @@ -1336,7 +1336,7 @@ pub mod messaging { /// Whether the source IP address is static or assigned via DHCP. #[must_use] - pub fn ip_address_origin(&self) -> crate::proto::device_path::messaging::Ipv4AddressOrigin { + pub fn ip_address_origin(&self) -> device_path::messaging::Ipv4AddressOrigin { self.ip_address_origin } @@ -1390,7 +1390,7 @@ pub mod messaging { pub(super) local_port: u16, pub(super) remote_port: u16, pub(super) protocol: u16, - pub(super) ip_address_origin: crate::proto::device_path::messaging::Ipv6AddressOrigin, + pub(super) ip_address_origin: device_path::messaging::Ipv6AddressOrigin, pub(super) prefix_length: u8, pub(super) gateway_ip_address: [u8; 16usize], } @@ -1429,7 +1429,7 @@ pub mod messaging { /// Origin of the local IP address. #[must_use] - pub fn ip_address_origin(&self) -> crate::proto::device_path::messaging::Ipv6AddressOrigin { + pub fn ip_address_origin(&self) -> device_path::messaging::Ipv6AddressOrigin { self.ip_address_origin } @@ -1514,7 +1514,7 @@ pub mod messaging { #[repr(C, packed)] pub struct Infiniband { pub(super) header: DevicePathHeader, - pub(super) resource_flags: crate::proto::device_path::messaging::InfinibandResourceFlags, + pub(super) resource_flags: device_path::messaging::InfinibandResourceFlags, pub(super) port_gid: [u8; 16usize], pub(super) ioc_guid_or_service_id: u64, pub(super) target_port_id: u64, @@ -1524,9 +1524,7 @@ pub mod messaging { impl Infiniband { /// Flags to identify/manage InfiniBand elements. #[must_use] - pub fn resource_flags( - &self, - ) -> crate::proto::device_path::messaging::InfinibandResourceFlags { + pub fn resource_flags(&self) -> device_path::messaging::InfinibandResourceFlags { self.resource_flags } @@ -1589,8 +1587,8 @@ pub mod messaging { pub(super) _reserved: u32, pub(super) baud_rate: u64, pub(super) data_bits: u8, - pub(super) parity: crate::proto::device_path::messaging::Parity, - pub(super) stop_bits: crate::proto::device_path::messaging::StopBits, + pub(super) parity: device_path::messaging::Parity, + pub(super) stop_bits: device_path::messaging::StopBits, } impl Uart { @@ -1608,13 +1606,13 @@ pub mod messaging { /// Parity setting. #[must_use] - pub fn parity(&self) -> crate::proto::device_path::messaging::Parity { + pub fn parity(&self) -> device_path::messaging::Parity { self.parity } /// Number of stop bits. #[must_use] - pub fn stop_bits(&self) -> crate::proto::device_path::messaging::StopBits { + pub fn stop_bits(&self) -> device_path::messaging::StopBits { self.stop_bits } } @@ -1764,8 +1762,8 @@ pub mod messaging { #[derive(Pointee)] pub struct Iscsi { pub(super) header: DevicePathHeader, - pub(super) protocol: crate::proto::device_path::messaging::IscsiProtocol, - pub(super) options: crate::proto::device_path::messaging::IscsiLoginOptions, + pub(super) protocol: device_path::messaging::IscsiProtocol, + pub(super) options: device_path::messaging::IscsiLoginOptions, pub(super) logical_unit_number: [u8; 8usize], pub(super) target_portal_group_tag: u16, pub(super) iscsi_target_name: [u8], @@ -1774,13 +1772,13 @@ pub mod messaging { impl Iscsi { /// Network protocol. #[must_use] - pub fn protocol(&self) -> crate::proto::device_path::messaging::IscsiProtocol { + pub fn protocol(&self) -> device_path::messaging::IscsiProtocol { self.protocol } /// iSCSI login options (bitfield). #[must_use] - pub fn options(&self) -> crate::proto::device_path::messaging::IscsiLoginOptions { + pub fn options(&self) -> device_path::messaging::IscsiLoginOptions { self.options } @@ -2131,7 +2129,7 @@ pub mod messaging { pub struct BluetoothLe { pub(super) header: DevicePathHeader, pub(super) device_address: [u8; 6usize], - pub(super) address_type: crate::proto::device_path::messaging::BluetoothLeAddressType, + pub(super) address_type: device_path::messaging::BluetoothLeAddressType, } impl BluetoothLe { @@ -2143,7 +2141,7 @@ pub mod messaging { /// Address type. #[must_use] - pub fn address_type(&self) -> crate::proto::device_path::messaging::BluetoothLeAddressType { + pub fn address_type(&self) -> device_path::messaging::BluetoothLeAddressType { self.address_type } } @@ -2175,14 +2173,14 @@ pub mod messaging { #[derive(Pointee)] pub struct Dns { pub(super) header: DevicePathHeader, - pub(super) address_type: crate::proto::device_path::messaging::DnsAddressType, + pub(super) address_type: device_path::messaging::DnsAddressType, pub(super) addresses: [IpAddress], } impl Dns { /// Whether the addresses are IPv4 or IPv6. #[must_use] - pub fn address_type(&self) -> crate::proto::device_path::messaging::DnsAddressType { + pub fn address_type(&self) -> device_path::messaging::DnsAddressType { self.address_type } @@ -2268,21 +2266,21 @@ pub mod messaging { #[derive(Pointee)] pub struct RestService { pub(super) header: DevicePathHeader, - pub(super) service_type: crate::proto::device_path::messaging::RestServiceType, - pub(super) access_mode: crate::proto::device_path::messaging::RestServiceAccessMode, + pub(super) service_type: device_path::messaging::RestServiceType, + pub(super) access_mode: device_path::messaging::RestServiceAccessMode, pub(super) vendor_guid_and_data: [u8], } impl RestService { /// Type of REST service. #[must_use] - pub fn service_type(&self) -> crate::proto::device_path::messaging::RestServiceType { + pub fn service_type(&self) -> device_path::messaging::RestServiceType { self.service_type } /// Whether the service is in-band or out-of-band. #[must_use] - pub fn access_mode(&self) -> crate::proto::device_path::messaging::RestServiceAccessMode { + pub fn access_mode(&self) -> device_path::messaging::RestServiceAccessMode { self.access_mode } } @@ -2480,7 +2478,7 @@ pub mod media { pub(super) partition_start: u64, pub(super) partition_size: u64, pub(super) partition_signature: [u8; 16usize], - pub(super) partition_format: crate::proto::device_path::media::PartitionFormat, + pub(super) partition_format: device_path::media::PartitionFormat, pub(super) signature_type: u8, } @@ -2505,7 +2503,7 @@ pub mod media { /// Partition format. #[must_use] - pub fn partition_format(&self) -> crate::proto::device_path::media::PartitionFormat { + pub fn partition_format(&self) -> device_path::media::PartitionFormat { self.partition_format } } @@ -2877,7 +2875,7 @@ pub mod media { pub(super) header: DevicePathHeader, pub(super) starting_address: u64, pub(super) ending_address: u64, - pub(super) disk_type: crate::proto::device_path::media::RamDiskType, + pub(super) disk_type: device_path::media::RamDiskType, pub(super) disk_instance: u16, } @@ -2896,7 +2894,7 @@ pub mod media { /// Type of RAM disk. #[must_use] - pub fn disk_type(&self) -> crate::proto::device_path::media::RamDiskType { + pub fn disk_type(&self) -> device_path::media::RamDiskType { self.disk_type } @@ -3054,11 +3052,11 @@ pub mod bios_boot_spec { pub enum DevicePathNodeEnum<'a> { /// Node that terminates a [`DevicePathInstance`]. /// - /// [`DevicePathInstance`]: crate::proto::device_path::DevicePathInstance + /// [`DevicePathInstance`]: device_path::DevicePathInstance EndInstance(&'a end::Instance), /// Node that terminates an entire [`DevicePath`]. /// - /// [`DevicePath`]: crate::proto::device_path::DevicePath + /// [`DevicePath`]: device_path::DevicePath EndEntire(&'a end::Entire), /// PCI hardware device path node. HardwarePci(&'a hardware::Pci), @@ -3336,7 +3334,7 @@ pub mod build { use super::*; /// Node that terminates a [`DevicePathInstance`]. /// - /// [`DevicePathInstance`]: crate::proto::device_path::DevicePathInstance + /// [`DevicePathInstance`]: device_path::DevicePathInstance #[derive(Debug)] pub struct Instance; unsafe impl BuildNode for Instance { @@ -3363,7 +3361,7 @@ pub mod build { /// Node that terminates an entire [`DevicePath`]. /// - /// [`DevicePath`]: crate::proto::device_path::DevicePath + /// [`DevicePath`]: device_path::DevicePath #[derive(Debug)] pub struct Entire; unsafe impl BuildNode for Entire { @@ -3589,7 +3587,7 @@ pub mod build { #[derive(Debug)] pub struct Bmc { /// Host interface type. - pub interface_type: crate::proto::device_path::hardware::BmcInterfaceType, + pub interface_type: device_path::hardware::BmcInterfaceType, /// Base address of the BMC. If the least-significant bit of the /// field is a 1 then the address is in I/O space, otherwise the /// address is memory-mapped. @@ -3616,7 +3614,7 @@ pub mod build { }); out_ptr .add(4usize) - .cast::() + .cast::() .write_unaligned(self.interface_type); out_ptr .add(5usize) @@ -3836,9 +3834,9 @@ pub mod build { #[derive(Debug)] pub struct Atapi { /// Whether the ATAPI device is primary or secondary. - pub primary_secondary: crate::proto::device_path::messaging::PrimarySecondary, + pub primary_secondary: device_path::messaging::PrimarySecondary, /// Whether the ATAPI device is master or slave. - pub master_slave: crate::proto::device_path::messaging::MasterSlave, + pub master_slave: device_path::messaging::MasterSlave, /// Logical Unit Number (LUN). pub logical_unit_number: u16, } @@ -3863,11 +3861,11 @@ pub mod build { }); out_ptr .add(4usize) - .cast::() + .cast::() .write_unaligned(self.primary_secondary); out_ptr .add(5usize) - .cast::() + .cast::() .write_unaligned(self.master_slave); out_ptr .add(6usize) @@ -4350,7 +4348,7 @@ pub mod build { /// pub protocol: u16, /// Whether the source IP address is static or assigned via DHCP. - pub ip_address_origin: crate::proto::device_path::messaging::Ipv4AddressOrigin, + pub ip_address_origin: device_path::messaging::Ipv4AddressOrigin, /// Gateway IP address. pub gateway_ip_address: [u8; 4usize], /// Subnet mask. @@ -4397,7 +4395,7 @@ pub mod build { .write_unaligned(self.protocol); out_ptr .add(18usize) - .cast::() + .cast::() .write_unaligned(self.ip_address_origin); out_ptr .add(19usize) @@ -4426,7 +4424,7 @@ pub mod build { /// pub protocol: u16, /// Origin of the local IP address. - pub ip_address_origin: crate::proto::device_path::messaging::Ipv6AddressOrigin, + pub ip_address_origin: device_path::messaging::Ipv6AddressOrigin, /// Prefix length. pub prefix_length: u8, /// Gateway IP address. @@ -4473,7 +4471,7 @@ pub mod build { .write_unaligned(self.protocol); out_ptr .add(42usize) - .cast::() + .cast::() .write_unaligned(self.ip_address_origin); out_ptr .add(43usize) @@ -4524,7 +4522,7 @@ pub mod build { #[derive(Debug)] pub struct Infiniband { /// Flags to identify/manage InfiniBand elements. - pub resource_flags: crate::proto::device_path::messaging::InfinibandResourceFlags, + pub resource_flags: device_path::messaging::InfinibandResourceFlags, /// 128-bit Global Identifier for remote fabric port. Note that /// this is not the same as a UEFI GUID. pub port_gid: [u8; 16usize], @@ -4557,7 +4555,7 @@ pub mod build { }); out_ptr .add(4usize) - .cast::() + .cast::() .write_unaligned(self.resource_flags); out_ptr .add(8usize) @@ -4587,9 +4585,9 @@ pub mod build { /// Number of data bits, or 0 to use the device's default. pub data_bits: u8, /// Parity setting. - pub parity: crate::proto::device_path::messaging::Parity, + pub parity: device_path::messaging::Parity, /// Number of stop bits. - pub stop_bits: crate::proto::device_path::messaging::StopBits, + pub stop_bits: device_path::messaging::StopBits, } unsafe impl BuildNode for Uart { @@ -4621,11 +4619,11 @@ pub mod build { .write_unaligned(self.data_bits); out_ptr .add(17usize) - .cast::() + .cast::() .write_unaligned(self.parity); out_ptr .add(18usize) - .cast::() + .cast::() .write_unaligned(self.stop_bits); } } @@ -4728,9 +4726,9 @@ pub mod build { #[derive(Debug)] pub struct Iscsi<'a> { /// Network protocol. - pub protocol: crate::proto::device_path::messaging::IscsiProtocol, + pub protocol: device_path::messaging::IscsiProtocol, /// iSCSI login options (bitfield). - pub options: crate::proto::device_path::messaging::IscsiLoginOptions, + pub options: device_path::messaging::IscsiLoginOptions, /// iSCSI Logical Unit Number. pub logical_unit_number: [u8; 8usize], /// iSCSI Target Portal group tag the initiator intends to @@ -4764,11 +4762,11 @@ pub mod build { }); out_ptr .add(4usize) - .cast::() + .cast::() .write_unaligned(self.protocol); out_ptr .add(6usize) - .cast::() + .cast::() .write_unaligned(self.options); out_ptr .add(8usize) @@ -5040,7 +5038,7 @@ pub mod build { /// 48-bit bluetooth device address. pub device_address: [u8; 6usize], /// Address type. - pub address_type: crate::proto::device_path::messaging::BluetoothLeAddressType, + pub address_type: device_path::messaging::BluetoothLeAddressType, } unsafe impl BuildNode for BluetoothLe { @@ -5067,7 +5065,7 @@ pub mod build { .write_unaligned(self.device_address); out_ptr .add(10usize) - .cast::() + .cast::() .write_unaligned(self.address_type); } } @@ -5077,7 +5075,7 @@ pub mod build { #[derive(Debug)] pub struct Dns<'a> { /// Whether the addresses are IPv4 or IPv6. - pub address_type: crate::proto::device_path::messaging::DnsAddressType, + pub address_type: device_path::messaging::DnsAddressType, /// One or more instances of the DNS server address. pub addresses: &'a [IpAddress], } @@ -5102,7 +5100,7 @@ pub mod build { }); out_ptr .add(4usize) - .cast::() + .cast::() .write_unaligned(self.address_type); self.addresses .as_ptr() @@ -5149,9 +5147,9 @@ pub mod build { #[derive(Debug)] pub struct RestService<'a> { /// Type of REST service. - pub service_type: crate::proto::device_path::messaging::RestServiceType, + pub service_type: device_path::messaging::RestServiceType, /// Whether the service is in-band or out-of-band. - pub access_mode: crate::proto::device_path::messaging::RestServiceAccessMode, + pub access_mode: device_path::messaging::RestServiceAccessMode, /// Vendor-specific data. Only used if the service type is [`VENDOR`]. /// /// [`VENDOR`]: uefi::proto::device_path::messaging::RestServiceType @@ -5178,11 +5176,11 @@ pub mod build { }); out_ptr .add(4usize) - .cast::() + .cast::() .write_unaligned(self.service_type); out_ptr .add(5usize) - .cast::() + .cast::() .write_unaligned(self.access_mode); self.build_vendor_guid_and_data(&mut out[6usize..]) } @@ -5249,10 +5247,7 @@ pub mod build { impl<'a> RestService<'a> { fn build_size_vendor_guid_and_data(&self) -> usize { if let Some(src) = &self.vendor_guid_and_data { - assert!( - self.service_type - == crate::proto::device_path::messaging::RestServiceType::VENDOR - ); + assert!(self.service_type == device_path::messaging::RestServiceType::VENDOR); size_of::() + size_of_val(src.vendor_defined_data) } else { 0 @@ -5261,10 +5256,7 @@ pub mod build { fn build_vendor_guid_and_data(&self, out: &mut [MaybeUninit]) { if let Some(src) = &self.vendor_guid_and_data { - assert!( - self.service_type - == crate::proto::device_path::messaging::RestServiceType::VENDOR - ); + assert!(self.service_type == device_path::messaging::RestServiceType::VENDOR); let (guid_out, data_out) = out.split_at_mut(size_of::()); let guid_out_ptr: *mut Guid = maybe_uninit_slice_as_mut_ptr(guid_out).cast(); unsafe { @@ -5295,9 +5287,9 @@ pub mod build { /// Size of the partition in blocks. pub partition_size: u64, /// Partition signature. - pub partition_signature: crate::proto::device_path::media::PartitionSignature, + pub partition_signature: device_path::media::PartitionSignature, /// Partition format. - pub partition_format: crate::proto::device_path::media::PartitionFormat, + pub partition_format: device_path::media::PartitionFormat, } unsafe impl BuildNode for HardDrive { @@ -5336,7 +5328,7 @@ pub mod build { .write_unaligned(self.build_partition_signature()); out_ptr .add(40usize) - .cast::() + .cast::() .write_unaligned(self.partition_format); out_ptr .add(41usize) @@ -5614,7 +5606,7 @@ pub mod build { /// Ending memory address. pub ending_address: u64, /// Type of RAM disk. - pub disk_type: crate::proto::device_path::media::RamDiskType, + pub disk_type: device_path::media::RamDiskType, /// RAM disk instance number if supported, otherwise 0. pub disk_instance: u16, } @@ -5647,7 +5639,7 @@ pub mod build { .write_unaligned(self.ending_address); out_ptr .add(20usize) - .cast::() + .cast::() .write_unaligned(self.disk_type); out_ptr .add(36usize) @@ -5659,7 +5651,7 @@ pub mod build { impl HardDrive { fn build_partition_signature(&self) -> [u8; 16] { - use crate::proto::device_path::media::PartitionSignature::*; + use device_path::media::PartitionSignature::*; match self.partition_signature { None => [0u8; 16], Mbr(mbr) => { @@ -5674,7 +5666,7 @@ pub mod build { } fn build_signature_type(&self) -> u8 { - use crate::proto::device_path::media::PartitionSignature::*; + use device_path::media::PartitionSignature::*; match self.partition_signature { None => 0, Mbr(_) => 1, diff --git a/xtask/src/device_path/field.rs b/xtask/src/device_path/field.rs index 095f75e69..009a60bdd 100644 --- a/xtask/src/device_path/field.rs +++ b/xtask/src/device_path/field.rs @@ -14,6 +14,7 @@ use syn::{Attribute, Expr, ExprLit, Field, Ident, Lit, Path, Type, TypeArray}; /// /// To add a new base type, verify that it meets the above requirement, /// then add it to the list in `BaseType::new` along with its size. +#[derive(Clone)] pub struct BaseType { path: Path, size_in_bytes: usize, @@ -39,25 +40,25 @@ impl BaseType { "IpAddress" => 16, "MemoryType" => 4, - "crate::proto::device_path::hardware::BmcInterfaceType" => 1, - - "crate::proto::device_path::messaging::BluetoothLeAddressType" => 1, - "crate::proto::device_path::messaging::DnsAddressType" => 1, - "crate::proto::device_path::messaging::InfinibandResourceFlags" => 4, - "crate::proto::device_path::messaging::Ipv4AddressOrigin" => 1, - "crate::proto::device_path::messaging::Ipv6AddressOrigin" => 1, - "crate::proto::device_path::messaging::IscsiLoginOptions" => 2, - "crate::proto::device_path::messaging::IscsiProtocol" => 2, - "crate::proto::device_path::messaging::MasterSlave" => 1, - "crate::proto::device_path::messaging::Parity" => 1, - "crate::proto::device_path::messaging::PrimarySecondary" => 1, - "crate::proto::device_path::messaging::RestServiceAccessMode" => 1, - "crate::proto::device_path::messaging::RestServiceType" => 1, - "crate::proto::device_path::messaging::StopBits" => 1, - - "crate::proto::device_path::media::PartitionFormat" => 1, - "crate::proto::device_path::media::RamDiskType" => 16, - "crate::proto::device_path::media::SignatureType" => 1, + "device_path::hardware::BmcInterfaceType" => 1, + + "device_path::messaging::BluetoothLeAddressType" => 1, + "device_path::messaging::DnsAddressType" => 1, + "device_path::messaging::InfinibandResourceFlags" => 4, + "device_path::messaging::Ipv4AddressOrigin" => 1, + "device_path::messaging::Ipv6AddressOrigin" => 1, + "device_path::messaging::IscsiLoginOptions" => 2, + "device_path::messaging::IscsiProtocol" => 2, + "device_path::messaging::MasterSlave" => 1, + "device_path::messaging::Parity" => 1, + "device_path::messaging::PrimarySecondary" => 1, + "device_path::messaging::RestServiceAccessMode" => 1, + "device_path::messaging::RestServiceType" => 1, + "device_path::messaging::StopBits" => 1, + + "device_path::media::PartitionFormat" => 1, + "device_path::media::RamDiskType" => 16, + "device_path::media::SignatureType" => 1, _ => panic!("unsupported base type: {path_str}"), }; @@ -86,6 +87,7 @@ impl ToTokens for BaseType { } /// Storage type for a field in the packed struct. +#[derive(Clone)] pub enum PackedType { /// A fixed-size non-array type. Base(BaseType), @@ -198,6 +200,18 @@ impl NodeField { } } + /// Get the field type for a uefi-raw node. + /// + /// This is mostly the same as `packed_ty`, except that DST slices are + /// converted to zero-length arrays. + pub fn raw_ty(&self) -> PackedType { + if let PackedType::Slice(ty) = &self.packed_ty { + PackedType::Array(ty.clone(), 0) + } else { + self.packed_ty.clone() + } + } + /// Whether the field is internal-only, e.g. a reserved field. No /// accessor will be generated for the field and the builder will /// initialize it with zeros. diff --git a/xtask/src/device_path/group.rs b/xtask/src/device_path/group.rs index c727b4120..9dbbb65bf 100644 --- a/xtask/src/device_path/group.rs +++ b/xtask/src/device_path/group.rs @@ -72,6 +72,32 @@ impl NodeGroup { group } + pub fn gen_raw_module(&self) -> TokenStream { + let module_ident = &self.device_type.module_ident(); + let nodes = self.nodes.iter().map(Node::gen_raw_struct); + let friends = &self.friends; + let doc = format!( + " Device path nodes for [`DeviceType::{}`].", + self.device_type.const_ident() + ); + + // Filter out non-node items except for structs and macro invocations + // (i.e. `bitflags`). + let friends = friends + .iter() + .filter(|f| matches!(f, Item::Struct(_) | Item::Macro(_))); + + quote!( + #[doc = #doc] + pub mod #module_ident { + use super::*; + + #(#nodes)* + #(#friends)* + } + ) + } + pub fn gen_packed_module(&self) -> TokenStream { let module_ident = &self.device_type.module_ident(); let nodes = self.nodes.iter().map(Node::gen_packed_code); diff --git a/xtask/src/device_path/mod.rs b/xtask/src/device_path/mod.rs index 698c41c8c..7211e66e8 100644 --- a/xtask/src/device_path/mod.rs +++ b/xtask/src/device_path/mod.rs @@ -7,14 +7,62 @@ use crate::opt::GenCodeOpt; use anyhow::{bail, Result}; use fs_err as fs; use group::NodeGroup; +use proc_macro2::TokenStream; use quote::quote; use syn::{File, Item}; use util::rustfmt_string; const INPUT_PATH: &str = "xtask/src/device_path/spec.rs"; -const OUTPUT_PATH: &str = "uefi/src/proto/device_path/device_path_gen.rs"; +const UEFI_RAW_OUTPUT_PATH: &str = "uefi-raw/src/protocol/device_path/device_path_gen.rs"; +const UEFI_OUTPUT_PATH: &str = "uefi/src/proto/device_path/device_path_gen.rs"; -fn gen_code_as_string(groups: &[NodeGroup]) -> Result { +fn code_to_string(code: TokenStream) -> Result { + // Insert some blank lines to make the output a bit more readable, + // otherwise everything is entirely squished together. `rustfmt` + // doesn't currently handle inserting blank lines very well, even + // with the unstable options. + let code = code.to_string().replace('}', "}\n\n"); + + let output = format!( + " +// DO NOT EDIT +// +// This file was automatically generated with: +// `cargo xtask gen-code` +// +// See `/xtask/src/device_path/README.md` for more details. +#![allow(clippy::missing_const_for_fn)] + +{code}" + ); + + let formatted = rustfmt_string(output)?; + + Ok(formatted) +} + +fn gen_uefi_raw_code_as_string(groups: &[NodeGroup]) -> Result { + let modules = groups.iter().map(NodeGroup::gen_raw_module); + + let code = quote!( + // This module contains many structures that cannot derive `Debug`. + #![allow(missing_debug_implementations)] + + use bitflags::bitflags; + use crate::protocol::device_path; + use crate::table::boot::MemoryType; + use crate::{guid, Guid, IpAddress}; + use device_path::DevicePathProtocol as DevicePathHeader; + #[cfg(doc)] + use device_path::DeviceType; + + #(#modules)* + ); + + code_to_string(code) +} + +fn gen_uefi_code_as_string(groups: &[NodeGroup]) -> Result { let packed_modules = groups.iter().map(NodeGroup::gen_packed_module); let node_enum = NodeGroup::gen_node_enum(groups); let build_modules = groups.iter().map(NodeGroup::gen_builder_module); @@ -25,7 +73,7 @@ fn gen_code_as_string(groups: &[NodeGroup]) -> Result { use crate::{guid, Guid}; use crate::polyfill::maybe_uninit_slice_as_mut_ptr; use crate::proto::device_path::{ - DevicePathHeader, DevicePathNode, DeviceSubType, DeviceType, + self, DevicePathHeader, DevicePathNode, DeviceSubType, DeviceType, NodeConversionError, }; use crate::proto::network::IpAddress; @@ -52,28 +100,7 @@ fn gen_code_as_string(groups: &[NodeGroup]) -> Result { } ); - // Insert some blank lines to make the output a bit more readable, - // otherwise everything is entirely squished together. `rustfmt` - // doesn't currently handle inserting blank lines very well, even - // with the unstable options. - let code = code.to_string().replace('}', "}\n\n"); - - let output = format!( - " -// DO NOT EDIT -// -// This file was automatically generated with: -// `cargo xtask gen-code` -// -// See `/xtask/src/device_path/README.md` for more details. -#![allow(clippy::missing_const_for_fn)] - -{code}" - ); - - let formatted = rustfmt_string(output)?; - - Ok(formatted) + code_to_string(code) } fn parse_spec(spec_str: &str) -> Vec { @@ -95,14 +122,17 @@ pub fn gen_code(opt: &GenCodeOpt) -> Result<()> { let spec_str = include_str!("spec.rs"); let groups = parse_spec(spec_str); - let output_string = gen_code_as_string(&groups)?; + let uefi_raw_output_string = gen_uefi_raw_code_as_string(&groups)?; + let uefi_output_string = gen_uefi_code_as_string(&groups)?; if opt.check { // Implementation note: we don't use `rustfmt --check` because // it always exits zero when reading from stdin: // https://github.com/rust-lang/rustfmt/issues/5376 - if output_string != fs::read_to_string(OUTPUT_PATH)? { + if uefi_raw_output_string != fs::read_to_string(UEFI_RAW_OUTPUT_PATH)? + || uefi_output_string != fs::read_to_string(UEFI_OUTPUT_PATH)? + { bail!("generated code is stale"); } @@ -111,7 +141,8 @@ pub fn gen_code(opt: &GenCodeOpt) -> Result<()> { bail!("spec.rs needs formatting"); } } else { - fs::write(OUTPUT_PATH, output_string)?; + fs::write(UEFI_RAW_OUTPUT_PATH, uefi_raw_output_string)?; + fs::write(UEFI_OUTPUT_PATH, uefi_output_string)?; // Also format the input file. It's valid rust, but not included // via `mod` anywhere, so the usual `cargo fmt --all` doesn't diff --git a/xtask/src/device_path/node.rs b/xtask/src/device_path/node.rs index abd5aef11..2ee1ed83b 100644 --- a/xtask/src/device_path/node.rs +++ b/xtask/src/device_path/node.rs @@ -98,6 +98,36 @@ impl Node { size } + /// Generate struct for uefi-raw. + pub fn gen_raw_struct(&self) -> TokenStream { + let struct_ident = &self.struct_ident; + + let mut fields = vec![quote!(header: DevicePathHeader)]; + fields.extend(self.fields.iter().filter_map(|field| { + // For a DST group, all the slice fields will be added as + // one `data` slice below. + if field.is_slice() && self.has_dst_group() { + return None; + } + + let field_name = &field.name; + let field_ty = field.raw_ty(); + Some(quote!(#field_name: #field_ty)) + })); + + // Combined `data` field for a DST group. + if self.has_dst_group() { + fields.push(quote!(data: [u8; 0])); + } + + quote!( + #[repr(C, packed)] + pub struct #struct_ident { + #(pub #fields),* + } + ) + } + fn gen_packed_struct(&self) -> TokenStream { let struct_docs = &self.docs; let struct_ident = &self.struct_ident; diff --git a/xtask/src/device_path/spec.rs b/xtask/src/device_path/spec.rs index e85cebec2..564b676ef 100644 --- a/xtask/src/device_path/spec.rs +++ b/xtask/src/device_path/spec.rs @@ -5,13 +5,13 @@ mod end { /// Node that terminates a [`DevicePathInstance`]. /// - /// [`DevicePathInstance`]: crate::proto::device_path::DevicePathInstance + /// [`DevicePathInstance`]: device_path::DevicePathInstance #[node(static_size = 4)] struct Instance; /// Node that terminates an entire [`DevicePath`]. /// - /// [`DevicePath`]: crate::proto::device_path::DevicePath + /// [`DevicePath`]: device_path::DevicePath #[node(static_size = 4)] struct Entire; } @@ -69,7 +69,7 @@ mod hardware { #[node(static_size = 13)] struct Bmc { /// Host interface type. - interface_type: crate::proto::device_path::hardware::BmcInterfaceType, + interface_type: device_path::hardware::BmcInterfaceType, /// Base address of the BMC. If the least-significant bit of the /// field is a 1 then the address is in I/O space, otherwise the @@ -324,10 +324,10 @@ mod messaging { #[node(static_size = 8)] struct Atapi { /// Whether the ATAPI device is primary or secondary. - primary_secondary: crate::proto::device_path::messaging::PrimarySecondary, + primary_secondary: device_path::messaging::PrimarySecondary, /// Whether the ATAPI device is master or slave. - master_slave: crate::proto::device_path::messaging::MasterSlave, + master_slave: device_path::messaging::MasterSlave, /// Logical Unit Number (LUN). logical_unit_number: u16, @@ -503,7 +503,7 @@ mod messaging { protocol: u16, /// Whether the source IP address is static or assigned via DHCP. - ip_address_origin: crate::proto::device_path::messaging::Ipv4AddressOrigin, + ip_address_origin: device_path::messaging::Ipv4AddressOrigin, /// Gateway IP address. gateway_ip_address: [u8; 4], @@ -543,7 +543,7 @@ mod messaging { protocol: u16, /// Origin of the local IP address. - ip_address_origin: crate::proto::device_path::messaging::Ipv6AddressOrigin, + ip_address_origin: device_path::messaging::Ipv6AddressOrigin, /// Prefix length. prefix_length: u8, @@ -579,7 +579,7 @@ mod messaging { #[node(static_size = 48)] struct Infiniband { /// Flags to identify/manage InfiniBand elements. - resource_flags: crate::proto::device_path::messaging::InfinibandResourceFlags, + resource_flags: device_path::messaging::InfinibandResourceFlags, /// 128-bit Global Identifier for remote fabric port. Note that /// this is not the same as a UEFI GUID. @@ -630,10 +630,10 @@ mod messaging { data_bits: u8, /// Parity setting. - parity: crate::proto::device_path::messaging::Parity, + parity: device_path::messaging::Parity, /// Number of stop bits. - stop_bits: crate::proto::device_path::messaging::StopBits, + stop_bits: device_path::messaging::StopBits, } newtype_enum! { @@ -727,10 +727,10 @@ mod messaging { #[node(static_size = 18)] struct Iscsi { /// Network protocol. - protocol: crate::proto::device_path::messaging::IscsiProtocol, + protocol: device_path::messaging::IscsiProtocol, /// iSCSI login options (bitfield). - options: crate::proto::device_path::messaging::IscsiLoginOptions, + options: device_path::messaging::IscsiLoginOptions, /// iSCSI Logical Unit Number. logical_unit_number: [u8; 8], @@ -838,7 +838,7 @@ mod messaging { device_address: [u8; 6], /// Address type. - address_type: crate::proto::device_path::messaging::BluetoothLeAddressType, + address_type: device_path::messaging::BluetoothLeAddressType, } newtype_enum! { @@ -856,7 +856,7 @@ mod messaging { #[node(static_size = 5)] struct Dns { /// Whether the addresses are IPv4 or IPv6. - address_type: crate::proto::device_path::messaging::DnsAddressType, + address_type: device_path::messaging::DnsAddressType, /// One or more instances of the DNS server address. addresses: [IpAddress], @@ -892,10 +892,10 @@ mod messaging { #[node(static_size = 6)] struct RestService { /// Type of REST service. - service_type: crate::proto::device_path::messaging::RestServiceType, + service_type: device_path::messaging::RestServiceType, /// Whether the service is in-band or out-of-band. - access_mode: crate::proto::device_path::messaging::RestServiceAccessMode, + access_mode: device_path::messaging::RestServiceAccessMode, /// Vendor-specific data. Only used if the service type is [`VENDOR`]. /// @@ -971,10 +971,7 @@ mod messaging { impl<'a> RestService<'a> { fn build_size_vendor_guid_and_data(&self) -> usize { if let Some(src) = &self.vendor_guid_and_data { - assert!( - self.service_type - == crate::proto::device_path::messaging::RestServiceType::VENDOR - ); + assert!(self.service_type == device_path::messaging::RestServiceType::VENDOR); size_of::() + size_of_val(src.vendor_defined_data) } else { @@ -984,10 +981,7 @@ mod messaging { fn build_vendor_guid_and_data(&self, out: &mut [MaybeUninit]) { if let Some(src) = &self.vendor_guid_and_data { - assert!( - self.service_type - == crate::proto::device_path::messaging::RestServiceType::VENDOR - ); + assert!(self.service_type == device_path::messaging::RestServiceType::VENDOR); let (guid_out, data_out) = out.split_at_mut(size_of::()); @@ -1039,12 +1033,12 @@ mod media { #[node( no_get_func, custom_build_impl, - build_type = "crate::proto::device_path::media::PartitionSignature" + build_type = "device_path::media::PartitionSignature" )] partition_signature: [u8; 16], /// Partition format. - partition_format: crate::proto::device_path::media::PartitionFormat, + partition_format: device_path::media::PartitionFormat, #[node(no_get_func, custom_build_impl, build_type = false)] signature_type: u8, @@ -1074,7 +1068,7 @@ mod media { #[build] impl HardDrive { fn build_partition_signature(&self) -> [u8; 16] { - use crate::proto::device_path::media::PartitionSignature::*; + use device_path::media::PartitionSignature::*; match self.partition_signature { None => [0u8; 16], Mbr(mbr) => { @@ -1088,7 +1082,7 @@ mod media { } fn build_signature_type(&self) -> u8 { - use crate::proto::device_path::media::PartitionSignature::*; + use device_path::media::PartitionSignature::*; match self.partition_signature { None => 0, Mbr(_) => 1, @@ -1205,7 +1199,7 @@ mod media { ending_address: u64, /// Type of RAM disk. - disk_type: crate::proto::device_path::media::RamDiskType, + disk_type: device_path::media::RamDiskType, /// RAM disk instance number if supported, otherwise 0. disk_instance: u16,