Skip to main content

get_protocol/
lib.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Protocol used to interact between the Guest and Host via the
5//! GET (Guest Emulation Transport)
6
7#![expect(missing_docs)]
8#![forbid(unsafe_code)]
9
10use bitfield_struct::bitfield;
11use guid::Guid;
12use open_enum::open_enum;
13use static_assertions::const_assert;
14use static_assertions::const_assert_eq;
15use std::fmt::Debug;
16use zerocopy::FromBytes;
17use zerocopy::Immutable;
18use zerocopy::IntoBytes;
19use zerocopy::KnownLayout;
20
21pub mod crash;
22pub mod dps_json; // TODO: split into separate crate, so get_protocol can be no_std
23
24/// The vmbus max response size is INCOMING_PACKET_BUFFER_PAGES (currently 12K)
25pub const MAX_MESSAGE_SIZE: usize = 12288;
26
27pub const MAX_HEADER_SIZE: usize = 256;
28
29// Maximum payload size for fragmenting VMGS read/writes and saved state.
30// (required due to underlying vmbus pipe message size constraints)
31pub const MAX_PAYLOAD_SIZE: usize = 8192;
32
33const_assert!(MAX_MESSAGE_SIZE >= MAX_HEADER_SIZE + MAX_PAYLOAD_SIZE);
34
35/// {455C0F1B-D51B-40B1-BEAC-87377FE6E041}
36pub const GUEST_EMULATION_DEVICE_ID: Guid = guid::guid!("455c0f1b-d51b-40b1-beac-87377fe6e041");
37
38/// {8DEDD1AA-9056-49E4-BFD6-1BF90DC38EF0}
39pub const GUEST_EMULATION_INTERFACE_TYPE: Guid =
40    guid::guid!("8dedd1aa-9056-49e4-bfd6-1bf90dc38ef0");
41
42/// {D3E4454D-62AF-44EC-B851-3170915E5F56}
43pub const GUEST_EMULATION_INTERFACE_INSTANCE: Guid =
44    guid::guid!("d3e4454d-62af-44ec-b851-3170915e5f56");
45
46/// Make protocol version
47const fn make_version(major: u16, minor: u16) -> u32 {
48    (minor as u32) | ((major as u32) << 16)
49}
50
51open_enum! {
52    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
53    pub enum ProtocolVersion: u32 {
54        INVALID = 0,
55        RS5 = make_version(1, 0),
56        IRON = make_version(3, 0),
57        NICKEL_REV2 = make_version(4, 2),
58    }
59}
60
61open_enum! {
62    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
63    pub enum MessageVersions: u8 {
64        INVALID          = 0,
65        HEADER_VERSION_1 = 1,
66    }
67}
68
69open_enum! {
70    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
71    pub enum MessageTypes: u8 {
72        INVALID            = 0,
73        HOST_NOTIFICATION  = 1,
74        HOST_REQUEST       = 2,
75        HOST_RESPONSE      = 3,
76        GUEST_NOTIFICATION = 4,
77    }
78}
79
80open_enum! {
81    /// Guest notification messages.
82    ///
83    /// These are intended to be "fire-and-forget" messages sent from the Host
84    /// to the Guest, without requiring a response.
85    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
86    pub enum GuestNotifications: u16 {
87        INVALID              = 0,
88        UPDATE_GENERATION_ID = 1,
89        // --- NI ---
90        SAVE_GUEST_VTL2_STATE = 2,
91        _RESERVED_DO_NOT_USE_3 = 3,
92        VPCI_DEVICE_NOTIFICATION = 4,
93        MODIFY_VTL2_SETTINGS = 5,
94        MODIFY_VTL2_SETTINGS_REV1 = 6,
95        // --- GE ---
96        BATTERY_STATUS = 7,
97        INJECT_DEBUG_INTERRUPT = 8,
98        NOTIFY_POST_LIVE_MIGRATION = 9,
99    }
100}
101
102open_enum! {
103    /// Host notification messages.
104    ///
105    /// These are intended to be "fire-and-forget" messages sent from the Guest
106    /// to the Host, without requiring a response.
107    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
108    pub enum HostNotifications: u16 {
109        INVALID   = 0,
110        POWER_OFF = 1,
111        RESET     = 2,
112        EVENT_LOG = 3,
113        LOG_TRACE = 4,
114        // --- NI ---
115        RESTORE_GUEST_VTL2_STATE_COMPLETED = 5,
116        MODIFY_VTL2_SETTINGS_COMPLETED     = 6,
117        START_VTL0_COMPLETED               = 7,
118        VTL_CRASH                          = 8,
119        TRIPLE_FAULT                       = 9,
120    }
121}
122
123open_enum! {
124    /// Header ids (Each request has a response of the same ID).
125    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
126    pub enum HostRequests: u16 {
127        INVALID                      = 0,
128        VERSION                      = 1,
129        TIME                         = 2,
130        BIOS_BOOT_FINALIZE           = 3,
131        VMGS_GET_DEVICE_INFO         = 4,
132        VMGS_READ                    = 5,
133        VMGS_WRITE                   = 6,
134        VMGS_FLUSH                   = 7,
135        IGVM_ATTEST                  = 8,
136        // --- RS ---
137        GUEST_STATE_PROTECTION_BY_ID = 9,
138        VMGS_KEYS_READ               = 10,
139        LOG_TRACE                    = 11, // deprecated
140        ACTIVITY_TRACE_START         = 12,
141        ACTIVITY_TRACE_OP            = 13,
142        EVENT_TRACE                  = 14,
143        // --- MN ---
144        DEVICE_PLATFORM_SETTINGS     = 15, // deprecated in favor of DEVICE_PLATFORM_SETTINGS_V2
145        // --- FE ---
146        ADVISORY_PLATFORM_SETTINGS   = 16, // deprecated in favor of DEVICE_PLATFORM_SETTINGS_V2
147        GUEST_STATE_PROTECTION       = 17,
148        // --- NI ---
149        DEVICE_PLATFORM_SETTINGS_V2      = 18, // wart: sent in request, but responses comes back as DEVICE_PLATFORM_SETTINGS_V2_REV1
150        VPCI_DEVICE_CONTROL              = 19,
151        SAVE_GUEST_VTL2_STATE            = 20,
152        RESTORE_GUEST_VTL2_STATE         = 21,
153        VPCI_DEVICE_BINDING_CHANGE       = 22,
154        VGA_PROXY_PCI_READ               = 23,
155        VGA_PROXY_PCI_WRITE              = 24,
156        _RESERVED_DO_NOT_USE_25          = 25,
157        _RESERVED_DO_NOT_USE_26          = 26,
158        DEVICE_PLATFORM_SETTINGS_V2_REV1 = 27, // wart: only sent back in *response* to DEVICE_PLATFORM_SETTINGS
159        CREATE_RAM_GPA_RANGE             = 28,
160        RESET_RAM_GPA_RANGE              = 29,
161        LOAD_FIRMWARE                    = 30,
162
163        // --- Experimental (not yet in Hyper-V) ---
164        MAP_FRAMEBUFFER              = 0xFFFF,
165        UNMAP_FRAMEBUFFER            = 0xFFFE,
166    }
167}
168
169pub use header::*;
170pub mod header {
171    use super::MessageTypes;
172    use super::MessageVersions;
173    use static_assertions::const_assert_eq;
174    use zerocopy::FromBytes;
175    use zerocopy::Immutable;
176    use zerocopy::IntoBytes;
177    use zerocopy::KnownLayout;
178
179    use super::GuestNotifications;
180    use super::HostNotifications;
181    use super::HostRequests;
182
183    /// The raw header pulled off the wire.
184    #[repr(C)]
185    #[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout, PartialEq, Eq)]
186    pub struct HeaderRaw {
187        pub message_version: MessageVersions,
188        pub message_type: MessageTypes,
189        pub message_id: u16,
190    }
191
192    // this trait cannot be implemented outside `mod get_protocol::header`, as
193    // there are several safety guarantees that must be upheld when specifying
194    // the `MessageId` associated type.
195    pub trait HeaderMeta: private::Sealed {
196        const MESSAGE_TYPE: MessageTypes;
197        type MessageId: Copy + IntoBytes + FromBytes + Immutable + KnownLayout + Sized;
198    }
199
200    macro_rules! defn_header_meta {
201        (
202            $(($header_alias:ident => $name:ident, $message_type:ident, $message_id:ident)$(,)*)*
203        ) => {
204            mod private {
205                pub trait Sealed {}
206                $(
207                    impl Sealed for super::$name {}
208                )*
209            }
210
211            $(
212                #[derive(Copy, Clone, Debug)]
213                pub enum $name {}
214
215                impl HeaderMeta for $name {
216                    const MESSAGE_TYPE: MessageTypes = MessageTypes::$message_type;
217                    type MessageId = $message_id;
218                }
219
220                // ensure that all message_ids are u16 sized
221                const_assert_eq!(size_of::<u16>(), size_of::<$message_id>());
222                // ensure that the resulting header is sized correctly
223                const_assert_eq!(4, size_of::<HeaderGeneric<$name>>());
224
225                impl TryFrom<HeaderRaw> for HeaderGeneric<$name> {
226                    type Error = ();
227
228                    fn try_from(raw: HeaderRaw) -> Result<HeaderGeneric<$name>, ()> {
229                        if raw.message_type != MessageTypes::$message_type {
230                            return Err(());
231                        }
232
233                        Ok(HeaderGeneric {
234                            message_version: raw.message_version,
235                            message_type: raw.message_type,
236                            message_id: $message_id(raw.message_id),
237                        })
238                    }
239                }
240
241                pub type $header_alias = HeaderGeneric<$name>;
242            )*
243
244        };
245    }
246
247    defn_header_meta! {
248        (HeaderGuestNotification => GuestNotification, GUEST_NOTIFICATION, GuestNotifications),
249        (HeaderHostNotification => HostNotification, HOST_NOTIFICATION, HostNotifications),
250        (HeaderHostResponse => HostResponse, HOST_RESPONSE, HostRequests),
251        (HeaderHostRequest => HostRequest, HOST_REQUEST, HostRequests),
252    }
253
254    // TODO: repr(packed) is only needed here to make zerocopy's IntoBytes
255    // derive happy. Ideally it wouldn't be needed. We know this type has no
256    // padding bytes because of the asserts inside `defn_header_meta!`, and
257    // HeaderMeta is sealed, but zerocopy can't see all of that yet.
258    #[repr(C, packed)]
259    #[derive(Copy, Clone, Debug, FromBytes, Immutable, KnownLayout, PartialEq, IntoBytes)]
260    pub struct HeaderGeneric<Meta: HeaderMeta> {
261        pub message_version: MessageVersions,
262        pub message_type: MessageTypes,
263        message_id: Meta::MessageId,
264    }
265
266    impl<Meta: HeaderMeta> HeaderGeneric<Meta> {
267        pub fn new(message_id: Meta::MessageId) -> Self {
268            Self {
269                message_version: MessageVersions::HEADER_VERSION_1,
270                message_type: Meta::MESSAGE_TYPE,
271                message_id,
272            }
273        }
274
275        // This method is only needed to force a copy of the message_id field to
276        // avoid references to potentially unaligned packed fields. message_id
277        // will never actually be unaligned in practice, but the compiler can't
278        // prove that. This can go away and message_id can be made `pub` when
279        // repr(packed) goes away.
280        pub fn message_id(&self) -> Meta::MessageId {
281            self.message_id
282        }
283    }
284}
285
286open_enum! {
287    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
288    pub enum LargePayloadState : u32 {
289        END = 0,
290        MORE = 1,
291    }
292}
293
294#[repr(C)]
295#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
296pub struct PowerOffNotification {
297    pub message_header: HeaderHostNotification,
298    pub hibernate: ProtocolBool,
299    pub _pad: u8,
300}
301
302const_assert_eq!(6, size_of::<PowerOffNotification>());
303
304impl PowerOffNotification {
305    pub fn new(hibernate: bool) -> Self {
306        Self {
307            message_header: HeaderGeneric::new(HostNotifications::POWER_OFF),
308
309            hibernate: hibernate.into(),
310            _pad: 0,
311        }
312    }
313}
314
315#[repr(C)]
316#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
317pub struct ResetNotification {
318    pub message_header: HeaderHostNotification,
319}
320
321const_assert_eq!(4, size_of::<ResetNotification>());
322
323impl ResetNotification {
324    pub fn new() -> Self {
325        Self {
326            message_header: HeaderGeneric::new(HostNotifications::RESET),
327        }
328    }
329}
330
331open_enum! {
332    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
333    pub enum EventLogId: u32 {
334        INVALID_ID = 0,
335        BOOT_SUCCESS = 1,
336        BOOT_SUCCESS_SECURE_BOOT_FAILED = 2,
337        BOOT_FAILURE = 3,
338        BOOT_FAILURE_SECURE_BOOT_FAILED = 4,
339        NO_BOOT_DEVICE = 5,
340        ATTESTATION_FAILED = 6,
341        VMGS_FILE_CLEAR = 7,
342        VMGS_INIT_FAILED = 8,
343        VMGS_INVALID_FORMAT = 9,
344        VMGS_CORRUPT_FORMAT = 10,
345        KEY_NOT_RELEASED = 11,
346        DEK_DECRYPTION_FAILED = 12,
347        WATCHDOG_TIMEOUT_RESET = 13,
348        BOOT_ATTEMPT = 14,
349        VMGS_ACCESS_FAILED = 15,
350        CERTIFICATE_RENEWAL_FAILED = 16,
351        TPM_INVALID_STATE = 17,
352        TPM_IDENTITY_CHANGE_FAILED = 18,
353        WRAPPED_KEY_REQUIRED_BUT_INVALID = 19,
354        DEK_HARDWARE_SEALING_INVALID_KEY = 20,
355        DEK_HARDWARE_SEALING_FAILED = 21,
356        DEK_HARDWARE_UNSEALING_SKIPPED = 23,
357    }
358}
359
360#[repr(C)]
361#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
362pub struct EventLogNotification {
363    pub message_header: HeaderHostNotification,
364    pub event_log_id: EventLogId,
365}
366
367const_assert_eq!(8, size_of::<EventLogNotification>());
368
369impl EventLogNotification {
370    pub fn new(event_log_id: EventLogId) -> Self {
371        Self {
372            message_header: HeaderGeneric::new(HostNotifications::EVENT_LOG),
373            event_log_id,
374        }
375    }
376}
377
378pub const TRACE_MSG_MAX_SIZE: usize = 256;
379open_enum! {
380    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
381    pub enum LogLevel: u32 {
382        INVALID = 0,
383        CRITICAL = 1,
384        ERROR = 2,
385        WARNING = 3,
386        INFORMATION = 4,
387        VERBOSE = 5,
388    }
389}
390
391impl From<LogLevel> for u8 {
392    fn from(level: LogLevel) -> Self {
393        match level {
394            LogLevel::INVALID => 0,
395            LogLevel::CRITICAL => 1,
396            LogLevel::ERROR => 2,
397            LogLevel::WARNING => 3,
398            LogLevel::INFORMATION => 4,
399            LogLevel::VERBOSE => 5,
400            _ => {
401                unreachable!();
402            }
403        }
404    }
405}
406
407open_enum! {
408    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
409    pub enum GuestVtl2SaveRestoreStatus : u16 {
410        SUCCESS = 0,
411        FAILURE = 1,
412        MORE_DATA = 2,
413        REQUEST_DATA = 3,
414    }
415}
416
417#[repr(C)]
418#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
419pub struct LogTraceNotification {
420    pub message_header: HeaderHostNotification,
421    pub level: LogLevel,
422    pub message: [u16; TRACE_MSG_MAX_SIZE],
423}
424
425const_assert_eq!(520, size_of::<LogTraceNotification>());
426
427pub const VTL_CRASH_PARAMETERS: usize = 5;
428
429/// The transport level VTL crash data to send to the host.
430#[repr(C)]
431#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
432pub struct VtlCrashNotification {
433    pub message_header: HeaderHostNotification,
434    pub vp_index: u32,
435    pub last_vtl: u8,
436    pub reserved0: u8,
437    pub reserved1: u16,
438    pub reserved2: u32,
439    pub control: u64,
440    pub parameters: [u64; VTL_CRASH_PARAMETERS],
441}
442
443const_assert_eq!(64, size_of::<VtlCrashNotification>());
444
445impl VtlCrashNotification {
446    pub fn new(
447        vp_index: u32,
448        last_vtl: u8,
449        control: u64,
450        parameters: [u64; VTL_CRASH_PARAMETERS],
451    ) -> Self {
452        Self {
453            message_header: HeaderGeneric::new(HostNotifications::VTL_CRASH),
454            vp_index,
455            last_vtl,
456            reserved0: 0,
457            reserved1: 0,
458            reserved2: 0,
459            control,
460            parameters,
461        }
462    }
463}
464
465open_enum! {
466    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
467    pub enum TripleFaultType: u32 {
468        UNRECOVERABLE_EXCEPTION = 1,
469    }
470}
471
472#[repr(C)]
473#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
474pub struct RegisterState {
475    pub name: u32,
476    pub value: [u8; 16],
477}
478const_assert_eq!(20, size_of::<RegisterState>());
479
480/// Triple fault notification to send to the host.
481#[repr(C)]
482#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
483pub struct TripleFaultNotification {
484    pub message_header: HeaderHostNotification,
485    pub vp_index: u32,
486    pub fault_type: TripleFaultType,
487    pub register_count: u32,
488}
489const_assert_eq!(16, size_of::<TripleFaultNotification>());
490
491impl TripleFaultNotification {
492    pub fn new(vp_index: u32, fault_type: TripleFaultType, register_count: u32) -> Self {
493        Self {
494            message_header: HeaderGeneric::new(HostNotifications::TRIPLE_FAULT),
495            vp_index,
496            fault_type,
497            register_count,
498        }
499    }
500}
501
502#[repr(C)]
503#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
504pub struct VersionRequest {
505    pub message_header: HeaderHostRequest,
506    pub version: ProtocolVersion,
507}
508
509impl VersionRequest {
510    /// Creates new `VersionRequest` message
511    pub fn new(version: ProtocolVersion) -> Self {
512        Self {
513            message_header: HeaderGeneric::new(HostRequests::VERSION),
514            version,
515        }
516    }
517}
518
519const_assert_eq!(8, size_of::<VersionRequest>());
520
521#[repr(C)]
522#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
523pub struct VersionResponse {
524    pub message_header: HeaderHostResponse,
525    pub version_accepted: ProtocolBool,
526    pub _pad: u8,
527}
528
529impl VersionResponse {
530    pub fn new(version_accepted: bool) -> Self {
531        Self {
532            message_header: HeaderGeneric::new(HostRequests::VERSION),
533            version_accepted: version_accepted.into(),
534            _pad: 0,
535        }
536    }
537}
538
539const_assert_eq!(6, size_of::<VersionResponse>());
540
541#[repr(C)]
542#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
543pub struct TimeRequest {
544    pub message_header: HeaderHostRequest,
545}
546
547const_assert_eq!(4, size_of::<TimeRequest>());
548
549impl TimeRequest {
550    pub fn new() -> Self {
551        Self {
552            message_header: HeaderGeneric::new(HostRequests::TIME),
553        }
554    }
555}
556
557#[repr(C)]
558#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
559pub struct TimeResponse {
560    pub message_header: HeaderHostResponse,
561    pub _pad: u32,
562
563    pub vm_reference_time: u64,
564    pub utc: i64,
565    pub time_zone: i16,
566    pub daylight_savings: ProtocolBool,
567    pub _pad1: [u8; 5],
568}
569
570impl TimeResponse {
571    pub fn new(vm_reference_time: u64, utc: i64, time_zone: i16, daylight_savings: bool) -> Self {
572        Self {
573            message_header: HeaderGeneric::new(HostRequests::TIME),
574            _pad: 0,
575
576            vm_reference_time,
577            utc,
578            time_zone,
579            daylight_savings: daylight_savings.into(),
580            _pad1: [0; 5],
581        }
582    }
583}
584
585const_assert_eq!(32, size_of::<TimeResponse>());
586
587/// Maximum agent data size
588pub const IGVM_ATTEST_MSG_REQ_AGENT_DATA_MAX_SIZE: usize = 2048;
589/// Maximum attestation report size
590pub const IGVM_ATTEST_MSG_REQ_REPORT_MAX_SIZE: usize = 4096;
591
592/// Maximum return pages
593pub const IGVM_ATTEST_MSG_MAX_SHARED_GPA: usize = 16;
594
595// Error from the VM worker process in the host when sending an
596// attestation request.
597pub const IGVM_ATTEST_VMWP_GENERIC_ERROR_CODE: usize = 0xFFFFFFFF;
598
599/// The response payload could be quite large, so pass host
600/// previously shared pages to use for response.
601/// Use GET response packet to serialize and convey response length.
602#[repr(C)]
603#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
604pub struct IgvmAttestRequest {
605    pub message_header: HeaderHostRequest,
606    /// Number of GPA
607    pub number_gpa: u32,
608    /// GPA addresses
609    pub shared_gpa: [u64; IGVM_ATTEST_MSG_MAX_SHARED_GPA],
610    /// Agent data length
611    pub agent_data_length: u32,
612    /// Report length
613    pub report_length: u32,
614    /// Agent data
615    pub agent_data: [u8; IGVM_ATTEST_MSG_REQ_AGENT_DATA_MAX_SIZE],
616    /// Report
617    pub report: [u8; IGVM_ATTEST_MSG_REQ_REPORT_MAX_SIZE],
618}
619
620const_assert_eq!(6288, size_of::<IgvmAttestRequest>());
621
622impl IgvmAttestRequest {
623    pub fn new(
624        shared_gpa: [u64; IGVM_ATTEST_MSG_MAX_SHARED_GPA],
625        number_gpa: u32,
626        agent_data: [u8; IGVM_ATTEST_MSG_REQ_AGENT_DATA_MAX_SIZE],
627        agent_data_length: u32,
628        report: [u8; IGVM_ATTEST_MSG_REQ_REPORT_MAX_SIZE],
629        report_length: u32,
630    ) -> Self {
631        Self {
632            message_header: HeaderGeneric::new(HostRequests::IGVM_ATTEST),
633            number_gpa,
634            shared_gpa,
635            agent_data_length,
636            report_length,
637            agent_data,
638            report,
639        }
640    }
641}
642
643#[repr(C)]
644#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
645pub struct IgvmAttestResponse {
646    pub message_header: HeaderHostResponse,
647    pub length: u32,
648}
649
650const_assert_eq!(8, size_of::<IgvmAttestResponse>());
651
652/// This can only be used in PROTOCOL_VERSION_RS5
653#[repr(C)]
654#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
655pub struct BiosBootFinalizeRequest {
656    pub message_header: HeaderHostRequest,
657    pub value: u8,
658    pub _pad: u8,
659}
660
661const_assert_eq!(6, size_of::<BiosBootFinalizeRequest>());
662
663#[repr(C)]
664#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
665pub struct BiosBootFinalizeResponse {
666    pub message_header: HeaderHostResponse,
667}
668
669impl BiosBootFinalizeResponse {
670    pub fn new() -> BiosBootFinalizeResponse {
671        BiosBootFinalizeResponse {
672            message_header: HeaderGeneric::new(HostRequests::BIOS_BOOT_FINALIZE),
673        }
674    }
675}
676
677const_assert_eq!(4, size_of::<BiosBootFinalizeResponse>());
678
679#[repr(C)]
680#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
681pub struct VmgsGetDeviceInfoRequest {
682    pub message_header: HeaderHostRequest,
683}
684
685impl VmgsGetDeviceInfoRequest {
686    pub fn new() -> Self {
687        Self {
688            message_header: HeaderGeneric::new(HostRequests::VMGS_GET_DEVICE_INFO),
689        }
690    }
691}
692
693const_assert_eq!(4, size_of::<VmgsGetDeviceInfoRequest>());
694
695open_enum! {
696    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
697    pub enum VmgsIoStatus: u32 {
698        SUCCESS         = 0,
699        INVALID_COMMAND = 1,
700        DEVICE_ERROR    = 2,
701        RETRY           = 3,
702    }
703}
704
705open_enum! {
706    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
707    pub enum VmgsWriteFlags: u32 {
708        NONE          = 0,
709        WRITE_THROUGH = 0x00000001,
710    }
711}
712
713open_enum! {
714    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
715    pub enum VmgsReadFlags: u32 {
716        NONE = 0,
717    }
718}
719
720#[repr(C)]
721#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
722pub struct VmgsGetDeviceInfoResponse {
723    pub message_header: HeaderHostResponse,
724    pub status: VmgsIoStatus,
725    pub capacity: u64, // logical sectors
726    pub bytes_per_logical_sector: u16,
727    pub bytes_per_physical_sector: u16,
728    pub maximum_transfer_size_bytes: u32,
729}
730
731impl VmgsGetDeviceInfoResponse {
732    pub fn new(
733        status: VmgsIoStatus,
734        capacity: u64,
735        bytes_per_logical_sector: u16,
736        bytes_per_physical_sector: u16,
737        maximum_transfer_size_bytes: u32,
738    ) -> VmgsGetDeviceInfoResponse {
739        VmgsGetDeviceInfoResponse {
740            message_header: HeaderGeneric::new(HostRequests::VMGS_GET_DEVICE_INFO),
741
742            status,
743            capacity,
744            bytes_per_logical_sector,
745            bytes_per_physical_sector,
746            maximum_transfer_size_bytes,
747        }
748    }
749}
750
751const_assert_eq!(24, size_of::<VmgsGetDeviceInfoResponse>());
752
753#[repr(C)]
754#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
755pub struct VmgsWriteRequest {
756    pub message_header: HeaderHostRequest,
757    pub flags: VmgsWriteFlags,
758    pub sector_offset: u64, // logical sectors
759    pub sector_count: u32,  // logical sectors
760    pub _pad: u32,
761    // Variable size payload follows
762}
763
764const_assert_eq!(24, size_of::<VmgsWriteRequest>());
765
766impl VmgsWriteRequest {
767    pub fn new(flags: VmgsWriteFlags, sector_offset: u64, sector_count: u32) -> Self {
768        Self {
769            message_header: HeaderGeneric::new(HostRequests::VMGS_WRITE),
770            flags,
771            sector_offset,
772            sector_count,
773            _pad: 0,
774        }
775    }
776}
777
778#[repr(C)]
779#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
780pub struct VmgsWriteResponse {
781    pub message_header: HeaderHostResponse,
782    pub status: VmgsIoStatus,
783}
784
785impl VmgsWriteResponse {
786    pub fn new(status: VmgsIoStatus) -> VmgsWriteResponse {
787        VmgsWriteResponse {
788            message_header: HeaderGeneric::new(HostRequests::VMGS_WRITE),
789            status,
790        }
791    }
792}
793
794const_assert_eq!(8, size_of::<VmgsWriteResponse>());
795
796#[repr(C)]
797#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
798pub struct VmgsReadRequest {
799    pub message_header: HeaderHostRequest,
800    pub flags: VmgsReadFlags,
801    pub sector_offset: u64, // logical sectors
802    pub sector_count: u32,  // logical sectors
803    pub _pad: u32,
804}
805
806const_assert_eq!(24, size_of::<VmgsReadRequest>());
807
808impl VmgsReadRequest {
809    pub fn new(flags: VmgsReadFlags, sector_offset: u64, sector_count: u32) -> Self {
810        Self {
811            message_header: HeaderGeneric::new(HostRequests::VMGS_READ),
812            flags,
813            sector_offset,
814            sector_count,
815            _pad: 0,
816        }
817    }
818}
819
820#[repr(C)]
821#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
822pub struct VmgsReadResponse {
823    pub message_header: HeaderHostResponse,
824    pub status: VmgsIoStatus,
825    // Variable size payload follows
826}
827
828impl VmgsReadResponse {
829    pub fn new(status: VmgsIoStatus) -> VmgsReadResponse {
830        VmgsReadResponse {
831            message_header: HeaderGeneric::new(HostRequests::VMGS_READ),
832            status,
833        }
834    }
835}
836
837const_assert_eq!(8, size_of::<VmgsReadResponse>());
838
839#[repr(C)]
840#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
841pub struct VmgsFlushRequest {
842    pub message_header: HeaderHostRequest,
843}
844
845impl VmgsFlushRequest {
846    pub fn new() -> Self {
847        Self {
848            message_header: HeaderGeneric::new(HostRequests::VMGS_FLUSH),
849        }
850    }
851}
852
853const_assert_eq!(4, size_of::<VmgsFlushRequest>());
854
855#[repr(C)]
856#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
857pub struct VmgsFlushResponse {
858    pub message_header: HeaderHostResponse,
859    pub status: VmgsIoStatus,
860}
861
862impl VmgsFlushResponse {
863    pub fn new(status: VmgsIoStatus) -> VmgsFlushResponse {
864        VmgsFlushResponse {
865            message_header: HeaderGeneric::new(HostRequests::VMGS_FLUSH),
866            status,
867        }
868    }
869}
870
871const_assert_eq!(8, size_of::<VmgsFlushResponse>());
872
873const VMGS_MAX_IO_MSG_HEADER_SIZE: usize = size_of::<VmgsReadRequest>();
874const_assert!(VMGS_MAX_IO_MSG_HEADER_SIZE >= size_of::<VmgsReadResponse>());
875const_assert!(VMGS_MAX_IO_MSG_HEADER_SIZE >= size_of::<VmgsWriteRequest>());
876const_assert!(VMGS_MAX_IO_MSG_HEADER_SIZE >= size_of::<VmgsWriteResponse>());
877const_assert!(VMGS_MAX_IO_MSG_HEADER_SIZE <= MAX_HEADER_SIZE);
878
879pub const MAX_TRANSFER_SIZE: usize = u32::MAX as usize - VMGS_MAX_IO_MSG_HEADER_SIZE;
880
881open_enum! {
882    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
883    pub enum ActivityClassId: u32 {
884        INVALID = 0,
885        VMGS_INITIALIZE_DEVICE = 1,
886        VMGS_INITIALIZE_STORE = 2,
887        VMGS_OPEN_STORE = 3,
888        VMGS_FORMAT = 4,
889        VMGS_SEND_RECEIVE = 5,
890        VMGS_DEVICE_READ = 6,
891        VMGS_DEVICE_WRITE = 7,
892        VMGS_DEVICE_FLUSH = 8,
893    }
894}
895
896open_enum! {
897    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
898    pub enum ActivityOpCode: u32 {
899        INFO = 0,
900        START = 1,
901        STOP = 2,
902    }
903}
904
905open_enum! {
906    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
907    pub enum EventId: u32 {
908        INVALID = 0,
909        VMGS_INFO = 1,
910        VMGS_WARNING = 2,
911        VMGS_ERROR = 3,
912        VMGS_CRITICAL = 4,
913    }
914}
915
916#[repr(C)]
917#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
918pub struct LogTraceRequest {
919    pub message_header: HeaderHostRequest,
920    pub level: LogLevel,
921    pub message: [u16; TRACE_MSG_MAX_SIZE],
922}
923
924const_assert_eq!(520, size_of::<LogTraceRequest>());
925
926#[repr(C)]
927#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
928pub struct LogTraceResponse {
929    pub message_header: HeaderHostResponse,
930}
931
932const_assert_eq!(4, size_of::<LogTraceResponse>());
933
934#[repr(C)]
935#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
936pub struct ActivityTraceStartRequest {
937    pub message_header: HeaderHostRequest,
938    pub activity_class: ActivityClassId,
939    pub related_activity_id: Guid,
940    pub size: u32, // Size of payload
941                   // Variable size payload follows, maximum TRACE_MSG_MAX_SIZE WCHAR
942}
943
944const_assert_eq!(28, size_of::<ActivityTraceStartRequest>());
945
946#[repr(C)]
947#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
948pub struct ActivityTraceStartResponse {
949    pub message_header: HeaderHostResponse,
950    pub activity_id: Guid,
951}
952
953const_assert_eq!(20, size_of::<ActivityTraceStartResponse>());
954
955#[repr(C)]
956#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
957pub struct ActivityTraceOpRequest {
958    pub message_header: HeaderHostRequest,
959    pub activity_class: ActivityClassId,
960    pub activity_id: Guid,
961    pub related_activity_id: Guid,
962    pub op_code: ActivityOpCode,
963    pub size: u32, // Size of payload
964                   // Variable size payload follows, maximum TRACE_MSG_MAX_SIZE_WCHAR
965}
966
967const_assert_eq!(48, size_of::<ActivityTraceOpRequest>());
968
969#[repr(C)]
970#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
971pub struct ActivityTraceOpResponse {
972    pub message_header: HeaderHostResponse,
973}
974
975const_assert_eq!(4, size_of::<ActivityTraceOpResponse>());
976
977#[repr(C)]
978#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
979pub struct EventTraceRequest {
980    pub message_header: HeaderHostRequest,
981    pub event: EventId,
982    pub size: u32, // Size of payload
983                   // Variable size payload follows, maximum TRACE_MSG_MAX_SIZE WCHAR
984}
985
986const_assert_eq!(12, size_of::<EventTraceRequest>());
987
988#[repr(C)]
989#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
990pub struct EventTraceResponse {
991    pub message_header: HeaderHostResponse,
992}
993
994const_assert_eq!(4, size_of::<EventTraceResponse>());
995
996open_enum! {
997    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
998    pub enum SecureBootTemplateType: u32 {
999        SECURE_BOOT_DISABLED = 0,
1000        MICROSOFT_WINDOWS = 1,
1001        MICROSOFT_UEFI_CERTIFICATE_AUTHORITY = 2,
1002        OPEN_SOURCE_SHIELDED_VM = 3,
1003    }
1004}
1005
1006open_enum! {
1007    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
1008    pub enum UefiConsoleMode: u8 {
1009        DEFAULT = 0,
1010        COM1 = 1,
1011        COM2 = 2,
1012        NONE = 3,
1013    }
1014}
1015
1016pub const HCL_DEVICE_PLATFORM_MAX_SMBIOS_LENGTH: usize = 64;
1017
1018#[repr(C)]
1019#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1020pub struct DevicePlatformSettingsRequestV2 {
1021    pub message_header: HeaderHostRequest,
1022}
1023
1024impl DevicePlatformSettingsRequestV2 {
1025    pub fn new() -> Self {
1026        Self {
1027            message_header: HeaderGeneric::new(HostRequests::DEVICE_PLATFORM_SETTINGS_V2),
1028        }
1029    }
1030}
1031
1032const_assert_eq!(4, size_of::<DevicePlatformSettingsRequestV2>());
1033
1034/// This represents a boolean value sent over the protocol as a u8. The only
1035/// valid values are 0 or 1.
1036#[repr(transparent)]
1037#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1038pub struct ProtocolBool(pub u8);
1039
1040impl From<bool> for ProtocolBool {
1041    fn from(value: bool) -> Self {
1042        ProtocolBool(if value { 1 } else { 0 })
1043    }
1044}
1045
1046#[repr(C)]
1047#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1048pub struct DevicePlatformSettingsResponseV2 {
1049    pub message_header: HeaderHostResponse,
1050
1051    pub size: u32,
1052    // variable length JSON payload
1053}
1054
1055#[repr(C)]
1056#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1057pub struct DevicePlatformSettingsResponseV2Rev1 {
1058    pub message_header: HeaderHostResponse,
1059
1060    pub size: u32,
1061
1062    pub payload_state: LargePayloadState,
1063    // variable length JSON payload
1064}
1065
1066pub const GSP_CLEARTEXT_MAX: u32 = 32;
1067pub const GSP_CIPHERTEXT_MAX: u32 = 512;
1068pub const NUMBER_GSP: u32 = 2;
1069
1070#[bitfield(u32)]
1071#[derive(IntoBytes, FromBytes, Immutable, KnownLayout, PartialEq, Eq)]
1072pub struct GspExtendedStatusFlags {
1073    pub state_refresh_request: bool,
1074    pub no_registry_file: bool,
1075    pub no_rpc_server: bool,
1076    pub allow_ak_cert_renewal: bool,
1077    pub requires_rpc_server: bool,
1078
1079    #[bits(27)]
1080    _reserved: u32,
1081}
1082
1083#[repr(C)]
1084#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1085pub struct GspCleartextContent {
1086    pub length: u32,
1087    pub buffer: [u8; GSP_CLEARTEXT_MAX as usize * 2],
1088}
1089
1090const_assert_eq!(68, size_of::<GspCleartextContent>());
1091
1092#[repr(C)]
1093#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1094pub struct GspCiphertextContent {
1095    pub length: u32,
1096    pub buffer: [u8; GSP_CIPHERTEXT_MAX as usize],
1097}
1098
1099const_assert_eq!(516, size_of::<GspCiphertextContent>());
1100
1101/// This can only be used in PROTOCOL_VERSION_RS5
1102#[repr(C)]
1103#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1104pub struct GuestStateProtectionByIdRequest {
1105    pub message_header: HeaderHostRequest,
1106}
1107
1108const_assert_eq!(4, size_of::<GuestStateProtectionByIdRequest>());
1109
1110impl GuestStateProtectionByIdRequest {
1111    pub fn new() -> Self {
1112        Self {
1113            message_header: HeaderGeneric::new(HostRequests::GUEST_STATE_PROTECTION_BY_ID),
1114        }
1115    }
1116}
1117
1118#[repr(C)]
1119#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1120pub struct GuestStateProtectionByIdResponse {
1121    pub message_header: HeaderHostResponse,
1122    pub seed: GspCleartextContent,
1123    pub extended_status_flags: GspExtendedStatusFlags,
1124}
1125
1126const_assert_eq!(76, size_of::<GuestStateProtectionByIdResponse>());
1127
1128#[repr(C)]
1129#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1130pub struct GuestStateProtectionRequest {
1131    pub message_header: HeaderHostRequest,
1132    pub new_gsp: GspCleartextContent,
1133    pub encrypted_gsp: [GspCiphertextContent; NUMBER_GSP as usize],
1134    pub extended_status_support_flags: GspExtendedStatusFlags,
1135}
1136
1137const_assert_eq!(1108, size_of::<GuestStateProtectionRequest>());
1138
1139impl GuestStateProtectionRequest {
1140    pub fn new(
1141        buffer: [u8; GSP_CLEARTEXT_MAX as usize * 2],
1142        encrypted_gsp: [GspCiphertextContent; NUMBER_GSP as usize],
1143        extended_status_support_flags: GspExtendedStatusFlags,
1144    ) -> Self {
1145        Self {
1146            message_header: HeaderGeneric::new(HostRequests::GUEST_STATE_PROTECTION),
1147            new_gsp: GspCleartextContent {
1148                length: GSP_CLEARTEXT_MAX,
1149                buffer,
1150            },
1151            encrypted_gsp,
1152            extended_status_support_flags,
1153        }
1154    }
1155}
1156
1157#[repr(C)]
1158#[derive(Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1159pub struct GuestStateProtectionResponse {
1160    pub message_header: HeaderHostResponse,
1161    pub encrypted_gsp: GspCiphertextContent,
1162    pub decrypted_gsp: [GspCleartextContent; NUMBER_GSP as usize],
1163    pub extended_status_flags: GspExtendedStatusFlags,
1164}
1165
1166const_assert_eq!(660, size_of::<GuestStateProtectionResponse>());
1167
1168#[repr(C)]
1169#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1170pub struct UpdateGenerationId {
1171    pub message_header: HeaderGuestNotification,
1172    pub _pad: u32,
1173    pub generation_id: [u8; 16],
1174}
1175
1176const_assert_eq!(24, size_of::<UpdateGenerationId>());
1177
1178impl UpdateGenerationId {
1179    pub fn new(generation_id: [u8; 16]) -> Self {
1180        Self {
1181            message_header: HeaderGeneric::new(GuestNotifications::UPDATE_GENERATION_ID),
1182            _pad: 0,
1183            generation_id,
1184        }
1185    }
1186}
1187
1188/// Bitfield describing SaveGuestVtl2StateNotification::capabilities_flags
1189#[bitfield(u64)]
1190#[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
1191pub struct SaveGuestVtl2StateFlags {
1192    /// Explicitly allow nvme_keepalive feature when servicing.
1193    #[bits(1)]
1194    pub enable_nvme_keepalive: bool,
1195
1196    /// Explicitly allow mana_keepalive feature when servicing.
1197    #[bits(1)]
1198    pub enable_mana_keepalive: bool,
1199
1200    /// Reserved, must be zero.
1201    #[bits(62)]
1202    _rsvd1: u64,
1203}
1204
1205#[repr(C, packed)]
1206#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1207pub struct SaveGuestVtl2StateNotification {
1208    pub message_header: HeaderGuestNotification,
1209    pub correlation_id: Guid,
1210    pub capabilities_flags: SaveGuestVtl2StateFlags,
1211    pub timeout_hint_secs: u16,
1212}
1213
1214const_assert_eq!(30, size_of::<SaveGuestVtl2StateNotification>());
1215
1216#[repr(C)]
1217#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1218pub struct SaveGuestVtl2StateRequest {
1219    pub message_header: HeaderHostRequest,
1220    pub save_status: GuestVtl2SaveRestoreStatus,
1221    // Variable-length payload follows
1222}
1223
1224const_assert_eq!(6, size_of::<SaveGuestVtl2StateRequest>());
1225
1226impl SaveGuestVtl2StateRequest {
1227    pub fn new(status: GuestVtl2SaveRestoreStatus) -> Self {
1228        Self {
1229            message_header: HeaderGeneric::new(HostRequests::SAVE_GUEST_VTL2_STATE),
1230            save_status: status,
1231        }
1232    }
1233}
1234
1235#[repr(C)]
1236#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1237pub struct SaveGuestVtl2StateResponse {
1238    pub message_header: HeaderHostResponse,
1239    pub save_status: GuestVtl2SaveRestoreStatus,
1240}
1241
1242const_assert_eq!(6, size_of::<SaveGuestVtl2StateResponse>());
1243
1244impl SaveGuestVtl2StateResponse {
1245    pub fn new(status: GuestVtl2SaveRestoreStatus) -> Self {
1246        Self {
1247            message_header: HeaderGeneric::new(HostRequests::SAVE_GUEST_VTL2_STATE),
1248            save_status: status,
1249        }
1250    }
1251}
1252
1253#[repr(C)]
1254#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1255pub struct RestoreGuestVtl2StateHostNotification {
1256    pub message_header: HeaderHostNotification,
1257    pub status: GuestVtl2SaveRestoreStatus,
1258}
1259
1260const_assert_eq!(6, size_of::<RestoreGuestVtl2StateHostNotification>());
1261
1262impl RestoreGuestVtl2StateHostNotification {
1263    pub fn new(stat: GuestVtl2SaveRestoreStatus) -> Self {
1264        Self {
1265            message_header: HeaderGeneric::new(
1266                HostNotifications::RESTORE_GUEST_VTL2_STATE_COMPLETED,
1267            ),
1268            status: stat,
1269        }
1270    }
1271}
1272
1273#[repr(C)]
1274#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1275pub struct RestoreGuestVtl2StateRequest {
1276    pub message_header: HeaderHostRequest,
1277    pub restore_status: GuestVtl2SaveRestoreStatus,
1278}
1279
1280const_assert_eq!(6, size_of::<RestoreGuestVtl2StateRequest>());
1281
1282impl RestoreGuestVtl2StateRequest {
1283    pub fn new(status: GuestVtl2SaveRestoreStatus) -> Self {
1284        Self {
1285            message_header: HeaderGeneric::new(HostRequests::RESTORE_GUEST_VTL2_STATE),
1286            restore_status: status,
1287        }
1288    }
1289}
1290
1291#[repr(C, packed)]
1292#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1293pub struct RestoreGuestVtl2StateResponse {
1294    pub message_header: HeaderHostResponse,
1295    pub data_length: u32,
1296    pub restore_status: GuestVtl2SaveRestoreStatus,
1297    // Variable-length payload follows
1298}
1299
1300const_assert_eq!(10, size_of::<RestoreGuestVtl2StateResponse>());
1301
1302impl RestoreGuestVtl2StateResponse {
1303    pub fn new(length: u32, status: GuestVtl2SaveRestoreStatus) -> Self {
1304        Self {
1305            message_header: HeaderGeneric::new(HostRequests::RESTORE_GUEST_VTL2_STATE),
1306            data_length: length,
1307            restore_status: status,
1308        }
1309    }
1310}
1311
1312open_enum! {
1313    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
1314    pub enum VpciDeviceControlCode: u32 {
1315        UNDEFINED = 0,
1316        OFFER = 1,
1317        REVOKE = 2,
1318        RESET = 3,
1319    }
1320}
1321
1322open_enum! {
1323    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
1324    pub enum VpciDeviceControlStatus: u32 {
1325        SUCCESS = 0,
1326        INVALID_REQUEST = 1,
1327        DEVICE_NOT_FOUND = 2,
1328        INVALID_DEVICE_STATE = 3,
1329        GENERIC_FAILURE = 4,
1330    }
1331}
1332
1333#[repr(C)]
1334#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1335pub struct VpciDeviceControlRequest {
1336    pub message_header: HeaderHostRequest,
1337    pub code: VpciDeviceControlCode,
1338    pub bus_instance_id: Guid,
1339}
1340
1341const_assert_eq!(24, size_of::<VpciDeviceControlRequest>());
1342
1343impl VpciDeviceControlRequest {
1344    pub fn new(code: VpciDeviceControlCode, bus_instance_id: Guid) -> Self {
1345        Self {
1346            message_header: HeaderGeneric::new(HostRequests::VPCI_DEVICE_CONTROL),
1347            code,
1348            bus_instance_id,
1349        }
1350    }
1351}
1352
1353#[repr(C)]
1354#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1355pub struct VpciDeviceControlResponse {
1356    pub message_header: HeaderHostResponse,
1357    pub status: VpciDeviceControlStatus,
1358}
1359
1360const_assert_eq!(8, size_of::<VpciDeviceControlResponse>());
1361
1362impl VpciDeviceControlResponse {
1363    pub fn new(status: VpciDeviceControlStatus) -> Self {
1364        Self {
1365            message_header: HeaderGeneric::new(HostRequests::VPCI_DEVICE_CONTROL),
1366            status,
1367        }
1368    }
1369}
1370
1371open_enum! {
1372    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
1373    pub enum VpciDeviceNotificationCode : u32 {
1374        UNDEFINED = 0,
1375        ENUMERATED = 1,
1376        PREPARE_FOR_REMOVAL = 2,
1377    }
1378}
1379
1380#[repr(C)]
1381#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1382pub struct VpciDeviceNotification {
1383    pub message_header: HeaderGuestNotification,
1384    pub bus_instance_id: Guid,
1385    pub code: VpciDeviceNotificationCode,
1386}
1387
1388const_assert_eq!(24, size_of::<VpciDeviceNotification>());
1389
1390#[repr(C, packed)]
1391#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1392pub struct VpciDeviceBindingChangeRequest {
1393    pub message_header: HeaderHostRequest,
1394    pub bus_instance_id: [u8; 16], // Guid
1395    pub binding_state: u8,
1396}
1397
1398const_assert_eq!(21, size_of::<VpciDeviceBindingChangeRequest>());
1399
1400impl VpciDeviceBindingChangeRequest {
1401    pub fn new(bus_instance_id: Guid, binding_state: bool) -> Self {
1402        let mut guid: [u8; 16] = [0; 16];
1403        guid.copy_from_slice(bus_instance_id.as_bytes());
1404        Self {
1405            message_header: HeaderGeneric::new(HostRequests::VPCI_DEVICE_BINDING_CHANGE),
1406            bus_instance_id: guid,
1407            binding_state: binding_state as u8,
1408        }
1409    }
1410}
1411
1412#[repr(C)]
1413#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1414pub struct VpciDeviceBindingChangeResponse {
1415    pub message_header: HeaderHostResponse,
1416    pub bus_instance_id: Guid,
1417    pub status: VpciDeviceControlStatus,
1418}
1419
1420const_assert_eq!(24, size_of::<VpciDeviceBindingChangeResponse>());
1421
1422impl VpciDeviceBindingChangeResponse {
1423    pub fn new(bus_instance_id: Guid, status: VpciDeviceControlStatus) -> Self {
1424        Self {
1425            message_header: HeaderGeneric::new(HostRequests::VPCI_DEVICE_BINDING_CHANGE),
1426            bus_instance_id,
1427            status,
1428        }
1429    }
1430}
1431
1432#[repr(C, packed)]
1433#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1434pub struct VgaProxyPciReadRequest {
1435    pub message_header: HeaderHostRequest,
1436    pub offset: u16,
1437}
1438
1439const_assert_eq!(6, size_of::<VgaProxyPciReadRequest>());
1440
1441impl VgaProxyPciReadRequest {
1442    pub fn new(offset: u16) -> Self {
1443        Self {
1444            message_header: HeaderGeneric::new(HostRequests::VGA_PROXY_PCI_READ),
1445            offset,
1446        }
1447    }
1448}
1449
1450#[repr(C)]
1451#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1452pub struct VgaProxyPciReadResponse {
1453    pub message_header: HeaderHostResponse,
1454    pub value: u32,
1455}
1456
1457const_assert_eq!(8, size_of::<VgaProxyPciReadResponse>());
1458
1459impl VgaProxyPciReadResponse {
1460    pub fn new(value: u32) -> Self {
1461        Self {
1462            message_header: HeaderGeneric::new(HostRequests::VGA_PROXY_PCI_READ),
1463            value,
1464        }
1465    }
1466}
1467
1468#[repr(C, packed)]
1469#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1470pub struct VgaProxyPciWriteRequest {
1471    pub message_header: HeaderHostRequest,
1472    pub value: u32,
1473    pub offset: u16,
1474}
1475
1476const_assert_eq!(10, size_of::<VgaProxyPciWriteRequest>());
1477
1478impl VgaProxyPciWriteRequest {
1479    pub fn new(offset: u16, value: u32) -> Self {
1480        Self {
1481            message_header: HeaderGeneric::new(HostRequests::VGA_PROXY_PCI_WRITE),
1482            offset,
1483            value,
1484        }
1485    }
1486}
1487
1488#[repr(C)]
1489#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1490pub struct VgaProxyPciWriteResponse {
1491    pub message_header: HeaderHostResponse,
1492}
1493
1494const_assert_eq!(4, size_of::<VgaProxyPciWriteResponse>());
1495
1496impl VgaProxyPciWriteResponse {
1497    pub fn new() -> Self {
1498        Self {
1499            message_header: HeaderGeneric::new(HostRequests::VGA_PROXY_PCI_WRITE),
1500        }
1501    }
1502}
1503
1504open_enum! {
1505    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
1506    pub enum ModifyVtl2SettingsStatus : u32 {
1507        SUCCESS = 0,
1508        FAILURE = 1,
1509    }
1510}
1511
1512#[repr(C)]
1513#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1514pub struct ModifyVtl2SettingsNotification {
1515    pub message_header: HeaderGuestNotification,
1516
1517    pub size: u32,
1518    // variable length JSON payload
1519}
1520
1521const_assert_eq!(8, size_of::<ModifyVtl2SettingsNotification>());
1522
1523#[repr(C)]
1524#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1525pub struct ModifyVtl2SettingsRev1Notification {
1526    pub message_header: HeaderGuestNotification,
1527
1528    pub size: u32,
1529
1530    pub payload_state: LargePayloadState,
1531    // variable length JSON payload
1532}
1533
1534const_assert_eq!(12, size_of::<ModifyVtl2SettingsRev1Notification>());
1535
1536#[repr(C, packed)]
1537#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1538pub struct ModifyVtl2SettingsCompleteNotification {
1539    pub message_header: HeaderHostNotification,
1540    pub modify_status: ModifyVtl2SettingsStatus,
1541    pub result_document_size: u32,
1542}
1543
1544const_assert_eq!(12, size_of::<ModifyVtl2SettingsCompleteNotification>());
1545
1546impl ModifyVtl2SettingsCompleteNotification {
1547    pub fn new(status: ModifyVtl2SettingsStatus, result_document_size: u32) -> Self {
1548        Self {
1549            message_header: HeaderGeneric::new(HostNotifications::MODIFY_VTL2_SETTINGS_COMPLETED),
1550            modify_status: status,
1551            result_document_size,
1552        }
1553    }
1554}
1555
1556pub const GET_LOG_INTERFACE_GUID: Guid = guid::guid!("AA5DE534-D149-487A-9053-05972BA20A7C");
1557
1558open_enum! {
1559    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
1560    pub enum LogType: u8 {
1561        EVENT = 0,
1562        SPAN_ENTER = 1,
1563        SPAN_EXIT = 2,
1564    }
1565}
1566
1567#[bitfield(u16)]
1568#[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
1569pub struct LogFlags {
1570    pub kmsg: bool,
1571    #[bits(15)]
1572    pub mbz0: u16,
1573}
1574
1575pub const TRACE_LOGGING_NAME_MAX_SIZE: usize = 128;
1576pub const TRACE_LOGGING_TARGET_MAX_SIZE: usize = 128;
1577pub const TRACE_LOGGING_FIELDS_MAX_SIZE: usize = 256;
1578pub const TRACE_LOGGING_MESSAGE_MAX_SIZE: usize = 4096;
1579pub const TRACE_LOGGING_NOTIFICATION_MAX_SIZE: usize = TRACE_LOGGING_NAME_MAX_SIZE
1580    + TRACE_LOGGING_TARGET_MAX_SIZE
1581    + TRACE_LOGGING_FIELDS_MAX_SIZE
1582    + TRACE_LOGGING_MESSAGE_MAX_SIZE
1583    + size_of::<TraceLoggingNotificationHeader>();
1584
1585#[repr(C)]
1586#[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
1587pub struct TraceLoggingBufferOffset {
1588    pub size: u16,
1589    pub offset: u16,
1590}
1591
1592// The header is followed by a buffer which holds the string fields.
1593//
1594//  ---------------------------------------------------------
1595//  |  Header | Buffer [ name | target | fields | message ] |
1596//  ---------------------------------------------------------
1597#[repr(C)]
1598#[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
1599pub struct TraceLoggingNotificationHeader {
1600    pub log_type: LogType,
1601    pub level: u8,
1602    pub flags: LogFlags,
1603    pub name: TraceLoggingBufferOffset,
1604    pub target: TraceLoggingBufferOffset,
1605    pub fields: TraceLoggingBufferOffset,
1606    pub message: TraceLoggingBufferOffset,
1607    pub mbz0: u32,
1608    pub activity_id: Guid,
1609    pub related_activity_id: Guid,
1610    pub correlation_id: Guid,
1611    pub timestamp: u64,
1612}
1613const_assert_eq!(80, size_of::<TraceLoggingNotificationHeader>());
1614
1615/// MAP_FRAMEBUFFER_REQUEST
1616#[repr(C, packed)]
1617#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1618pub struct MapFramebufferRequest {
1619    pub message_header: HeaderHostRequest,
1620    pub gpa: u64,
1621}
1622
1623const_assert_eq!(12, size_of::<MapFramebufferRequest>());
1624
1625impl MapFramebufferRequest {
1626    pub fn new(gpa: u64) -> Self {
1627        Self {
1628            message_header: HeaderGeneric::new(HostRequests::MAP_FRAMEBUFFER),
1629            gpa,
1630        }
1631    }
1632}
1633
1634open_enum! {
1635    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
1636    pub enum MapFramebufferStatus : u32 {
1637        SUCCESS = 0,
1638        FAILURE = 1,
1639    }
1640}
1641
1642/// MAP_FRAMEBUFFER_RESPONSE
1643#[repr(C, packed)]
1644#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1645pub struct MapFramebufferResponse {
1646    pub message_header: HeaderHostResponse,
1647    pub status: MapFramebufferStatus,
1648}
1649
1650const_assert_eq!(8, size_of::<MapFramebufferResponse>());
1651
1652impl MapFramebufferResponse {
1653    pub fn new(status: MapFramebufferStatus) -> Self {
1654        Self {
1655            message_header: HeaderGeneric::new(HostRequests::MAP_FRAMEBUFFER),
1656            status,
1657        }
1658    }
1659}
1660
1661/// UNMAP_FRAMEBUFFER
1662#[repr(C, packed)]
1663#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1664pub struct UnmapFramebufferRequest {
1665    pub message_header: HeaderHostRequest,
1666}
1667
1668const_assert_eq!(4, size_of::<UnmapFramebufferRequest>());
1669
1670impl UnmapFramebufferRequest {
1671    pub fn new() -> Self {
1672        Self {
1673            message_header: HeaderGeneric::new(HostRequests::UNMAP_FRAMEBUFFER),
1674        }
1675    }
1676}
1677
1678open_enum! {
1679    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
1680    pub enum UnmapFramebufferStatus : u32 {
1681        SUCCESS = 0,
1682        FAILURE = 1,
1683    }
1684}
1685
1686/// UNMAP_FRAMEBUFFER_RESPONSE
1687#[repr(C, packed)]
1688#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1689pub struct UnmapFramebufferResponse {
1690    pub message_header: HeaderHostResponse,
1691    pub status: UnmapFramebufferStatus,
1692}
1693
1694const_assert_eq!(8, size_of::<UnmapFramebufferResponse>());
1695
1696impl UnmapFramebufferResponse {
1697    pub fn new(status: UnmapFramebufferStatus) -> Self {
1698        Self {
1699            message_header: HeaderGeneric::new(HostRequests::UNMAP_FRAMEBUFFER),
1700            status,
1701        }
1702    }
1703}
1704
1705open_enum! {
1706    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
1707    pub enum StartVtl0Status : u32 {
1708        SUCCESS = 0,
1709        FAILURE = 1,
1710    }
1711}
1712
1713#[repr(C, packed)]
1714#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1715pub struct StartVtl0CompleteNotification {
1716    pub message_header: HeaderHostNotification,
1717    pub status: StartVtl0Status,
1718    pub result_document_size: u32,
1719    // result_document is a variable size raw string because the Error is anyhow::Error
1720    // TODO: use specific Errors for "start VM"
1721}
1722
1723const_assert_eq!(12, size_of::<StartVtl0CompleteNotification>());
1724
1725impl StartVtl0CompleteNotification {
1726    pub fn new(status: StartVtl0Status, result_document_size: u32) -> Self {
1727        Self {
1728            message_header: HeaderGeneric::new(HostNotifications::START_VTL0_COMPLETED),
1729            status,
1730            result_document_size,
1731        }
1732    }
1733}
1734
1735#[repr(C)]
1736#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1737pub struct BatteryStatusNotification {
1738    pub message_header: HeaderGuestNotification,
1739    pub flags: BatteryStatusFlags,
1740    pub max_capacity: u32,
1741    pub remaining_capacity: u32,
1742    pub rate: u32,
1743}
1744
1745#[bitfield(u32)]
1746#[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
1747pub struct BatteryStatusFlags {
1748    pub ac_online: bool,
1749    pub battery_present: bool,
1750    pub charging: bool,
1751    pub discharging: bool,
1752    #[bits(28)]
1753    pub reserved: u32,
1754}
1755
1756impl BatteryStatusNotification {
1757    pub fn new(
1758        flags: BatteryStatusFlags,
1759        max_capacity: u32,
1760        remaining_capacity: u32,
1761        rate: u32,
1762    ) -> Self {
1763        Self {
1764            message_header: HeaderGeneric::new(GuestNotifications::BATTERY_STATUS),
1765            flags,
1766            max_capacity,
1767            remaining_capacity,
1768            rate,
1769        }
1770    }
1771}
1772
1773#[repr(C)]
1774#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1775pub struct InjectDebugInterruptNotification {
1776    pub message_header: HeaderGuestNotification,
1777    pub vtl: u8,
1778    pub _pad: u8,
1779}
1780const_assert_eq!(6, size_of::<InjectDebugInterruptNotification>());
1781
1782#[repr(C)]
1783#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1784pub struct PostLiveMigrationNotification {
1785    pub message_header: HeaderGuestNotification,
1786}
1787const_assert_eq!(4, size_of::<PostLiveMigrationNotification>());
1788
1789#[bitfield(u64)]
1790#[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
1791pub struct CreateRamGpaRangeFlags {
1792    _reserved1: bool,
1793
1794    /// Writes are discarded
1795    pub rom_mb: bool,
1796
1797    #[bits(62)]
1798    _reserved: u64,
1799}
1800
1801#[repr(C, packed)]
1802#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1803pub struct CreateRamGpaRangeRequest {
1804    pub message_header: HeaderHostRequest,
1805    pub slot: u32,
1806    pub gpa_start: u64,
1807    pub gpa_count: u64,
1808    pub gpa_offset: u64,
1809    pub flags: CreateRamGpaRangeFlags,
1810}
1811
1812const_assert_eq!(40, size_of::<CreateRamGpaRangeRequest>());
1813
1814impl CreateRamGpaRangeRequest {
1815    pub fn new(
1816        slot: u32,
1817        gpa_start: u64,
1818        gpa_count: u64,
1819        gpa_offset: u64,
1820        flags: CreateRamGpaRangeFlags,
1821    ) -> Self {
1822        Self {
1823            message_header: HeaderGeneric::new(HostRequests::CREATE_RAM_GPA_RANGE),
1824            slot,
1825            gpa_start,
1826            gpa_count,
1827            gpa_offset,
1828            flags,
1829        }
1830    }
1831}
1832
1833open_enum! {
1834    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
1835    pub enum CreateRamGpaRangeStatus : u32 {
1836        SUCCESS = 0,
1837        /// slot index out of bounds
1838        SLOT_OUT_OF_BOUNDS = 1,
1839        /// slot is already occupied. needs to be reset first
1840        SLOT_OCCUPIED = 2,
1841        /// invalid flag
1842        INVALID_FLAG = 3,
1843        /// invalid GPA
1844        INVALID_GPA = 4,
1845        /// call to CreateRamGpaRange failed
1846        FAILED = 5,
1847    }
1848}
1849
1850#[repr(C)]
1851#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1852pub struct CreateRamGpaRangeResponse {
1853    pub message_header: HeaderHostResponse,
1854    pub status: CreateRamGpaRangeStatus,
1855}
1856
1857const_assert_eq!(8, size_of::<CreateRamGpaRangeResponse>());
1858
1859impl CreateRamGpaRangeResponse {
1860    pub fn new(status: CreateRamGpaRangeStatus) -> Self {
1861        Self {
1862            message_header: HeaderGeneric::new(HostRequests::CREATE_RAM_GPA_RANGE),
1863            status,
1864        }
1865    }
1866}
1867
1868#[repr(C)]
1869#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1870pub struct ResetRamGpaRangeRequest {
1871    pub message_header: HeaderHostRequest,
1872    pub slot: u32,
1873}
1874
1875const_assert_eq!(8, size_of::<ResetRamGpaRangeRequest>());
1876
1877impl ResetRamGpaRangeRequest {
1878    pub fn new(slot: u32) -> Self {
1879        Self {
1880            message_header: HeaderGeneric::new(HostRequests::RESET_RAM_GPA_RANGE),
1881            slot,
1882        }
1883    }
1884}
1885
1886#[repr(C)]
1887#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1888pub struct ResetRamGpaRangeResponse {
1889    pub message_header: HeaderHostResponse,
1890}
1891
1892const_assert_eq!(4, size_of::<ResetRamGpaRangeResponse>());
1893
1894impl ResetRamGpaRangeResponse {
1895    pub fn new() -> Self {
1896        Self {
1897            message_header: HeaderGeneric::new(HostRequests::RESET_RAM_GPA_RANGE),
1898        }
1899    }
1900}
1901
1902/// Requests that the host load a firmware image into VTL0 guest RAM (memory
1903/// only; the guest/paravisor remains responsible for VP state). Host support is
1904/// advertised via the `load_firmware_supported` bit in
1905/// [`dps_json::ManagementVtlFeatures`].
1906#[repr(C, packed)]
1907#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1908pub struct LoadFirmwareRequest {
1909    pub message_header: HeaderHostRequest,
1910    /// Opaque token identifying the firmware resource to load.
1911    pub firmware_token: u64,
1912}
1913
1914const_assert_eq!(12, size_of::<LoadFirmwareRequest>());
1915
1916impl LoadFirmwareRequest {
1917    pub fn new(firmware_token: u64) -> Self {
1918        Self {
1919            message_header: HeaderGeneric::new(HostRequests::LOAD_FIRMWARE),
1920            firmware_token,
1921        }
1922    }
1923}
1924
1925open_enum! {
1926    #[derive(IntoBytes, FromBytes, Immutable, KnownLayout)]
1927    pub enum LoadFirmwareStatus: u32 {
1928        SUCCESS = 0,
1929        /// The supplied firmware token did not map to a known resource.
1930        INVALID_TOKEN = 1,
1931        /// The firmware image could not be loaded or written into guest RAM.
1932        FAILED = 2,
1933    }
1934}
1935
1936#[repr(C)]
1937#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
1938pub struct LoadFirmwareResponse {
1939    pub message_header: HeaderHostResponse,
1940    pub status: LoadFirmwareStatus,
1941    /// Offset from the firmware image base to the firmware entry point (SEC
1942    /// entry on x64), computed by the host. Valid only when `status` is
1943    /// [`LoadFirmwareStatus::SUCCESS`]; the guest/paravisor programs VTL0's RIP
1944    /// to `image_base + entry_point_image_offset`.
1945    pub entry_point_image_offset: u64,
1946}
1947
1948const_assert_eq!(16, size_of::<LoadFirmwareResponse>());
1949
1950impl LoadFirmwareResponse {
1951    pub fn new(status: LoadFirmwareStatus, entry_point_image_offset: u64) -> Self {
1952        Self {
1953            message_header: HeaderGeneric::new(HostRequests::LOAD_FIRMWARE),
1954            status,
1955            entry_point_image_offset,
1956        }
1957    }
1958}
1959
1960pub mod test_utilities {
1961    // These constants are shared across GED and GET testing
1962    pub const TEST_VMGS_SECTOR_SIZE: u32 = 512;
1963    pub const TEST_VMGS_CAPACITY: usize = 4194816; // 4 MB
1964}