hermit_entry/
note.rs

1use core::mem;
2
3use crate::HermitVersion;
4
5/// Defines the hermit entry version in the note section.
6///
7/// This macro must be used in a module that is guaranteed to be linked.
8/// See <https://github.com/rust-lang/rust/issues/99721>.
9#[cfg_attr(docsrs, doc(cfg(feature = "kernel")))]
10#[macro_export]
11macro_rules! define_entry_version {
12    () => {
13        #[used]
14        #[unsafe(link_section = ".note.hermit.entry-version")]
15        static ENTRY_VERSION: $crate::_Note<1> = $crate::_Note::entry_version();
16    };
17}
18
19/// Defines the Uhyve interface version in the note section.
20///
21/// This macro must be used in a module that is guaranteed to be linked.
22/// See <https://github.com/rust-lang/rust/issues/99721>.
23///
24/// # Examples
25///
26/// ```
27/// # mod uhyve_interface {
28/// #     pub const UHYVE_INTERFACE_VERSION: u32 = 1;
29/// # }
30/// #
31/// hermit_entry::define_uhyve_interface_version!(uhyve_interface::UHYVE_INTERFACE_VERSION);
32/// ```
33#[cfg_attr(docsrs, doc(cfg(feature = "kernel")))]
34#[macro_export]
35macro_rules! define_uhyve_interface_version {
36    ($version:expr) => {
37        #[used]
38        #[unsafe(link_section = ".note.hermit.uhyve-interface-version")]
39        static INTERFACE_VERSION: $crate::_Note<4> = $crate::_Note::uhyveif_version($version);
40    };
41}
42
43#[repr(C)]
44#[doc(hidden)]
45pub struct _Note<const N: usize> {
46    header: Nhdr32,
47    name: [u8; 8],
48    data: [u8; N],
49}
50
51impl _Note<1> {
52    pub const fn entry_version() -> Self {
53        Self {
54            header: Nhdr32 {
55                n_namesz: 7,
56                n_descsz: 1,
57                n_type: crate::NT_HERMIT_ENTRY_VERSION,
58            },
59            name: *b"HERMIT\0\0",
60            data: [crate::HERMIT_ENTRY_VERSION],
61        }
62    }
63}
64
65impl _Note<4> {
66    pub const fn uhyveif_version(ver: u32) -> Self {
67        Self {
68            header: Nhdr32 {
69                n_namesz: 8,
70                n_descsz: 4,
71                n_type: crate::NT_UHYVE_INTERFACE_VERSION,
72            },
73            name: *b"UHYVEIF\0",
74            data: ver.to_be_bytes(),
75        }
76    }
77}
78
79#[repr(C)]
80struct Nhdr32 {
81    n_namesz: u32,
82    n_descsz: u32,
83    n_type: u32,
84}
85
86/// Defines the current Hermit kernel version in the note section.
87///
88/// The version is saved in `.note.ABI-tag` in accordance with [LSB].
89///
90/// [LSB]: https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/noteabitag.html
91#[cfg_attr(docsrs, doc(cfg(feature = "kernel")))]
92#[macro_export]
93macro_rules! define_abi_tag {
94    () => {
95        #[used]
96        #[unsafe(link_section = ".note.ABI-tag")]
97        static ABI_TAG: $crate::_AbiTag = $crate::_AbiTag::new($crate::HermitVersion {
98            major: $crate::_parse_u128(::core::env!("CARGO_PKG_VERSION_MAJOR")) as u32,
99            minor: $crate::_parse_u128(::core::env!("CARGO_PKG_VERSION_MINOR")) as u32,
100            patch: $crate::_parse_u128(::core::env!("CARGO_PKG_VERSION_PATCH")) as u32,
101        });
102    };
103}
104
105#[repr(C)]
106#[doc(hidden)]
107pub struct _AbiTag {
108    header: Nhdr32,
109    name: [u8; 4],
110    data: [u32; 4],
111}
112
113impl _AbiTag {
114    pub const fn new(version: HermitVersion) -> Self {
115        Self {
116            header: Nhdr32 {
117                n_namesz: mem::size_of::<[u8; 4]>() as u32,
118                n_descsz: mem::size_of::<[u32; 4]>() as u32,
119                n_type: crate::NT_GNU_ABI_TAG,
120            },
121            name: *b"GNU\0",
122            data: [
123                crate::ELF_NOTE_OS_HERMIT,
124                version.major,
125                version.minor,
126                version.patch,
127            ],
128        }
129    }
130}