qcow/
wire.rs

1// Copyright 2022 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Allow dead code here so we can retain some definitions from the spec that are not yet used.
6#![allow(dead_code)]
7
8use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
9
10pub use zerocopy::byteorder::big_endian::{U32 as BE32, U64 as BE64};
11
12#[derive(Debug, Copy, Clone, IntoBytes, KnownLayout, FromBytes, Immutable)]
13#[repr(C, packed)]
14pub struct Header {
15    pub magic: BE32,
16    pub version: BE32,
17    pub backing_file_offset: BE64,
18    pub backing_file_size: BE32,
19    pub cluster_bits: BE32,
20    pub size: BE64,
21    pub crypt_method: BE32,
22    pub l1_size: BE32,
23    pub l1_table_offset: BE64,
24    pub refcount_table_offset: BE64,
25    pub nb_snapshots: BE32,
26    pub snapshots_offset: BE64,
27    pub incompatible_features: BE64,
28    pub compatible_features: BE64,
29    pub autoclear_features: BE64,
30    pub refcount_order: BE32,
31    pub header_length: BE32,
32}
33
34// Known values for ExtensionHeader::extension_type.
35pub const QCOW_EXT_END: u32 = 0x00000000;
36pub const QCOW_EXT_BACKING_FILE_FORMAT_NAME: u32 = 0xE2792AC;
37pub const QCOW_EXT_FEATURE_NAME_TABLE: u32 = 0x6803f857;
38pub const QCOW_EXT_BITMAPS: u32 = 0x23852875;
39
40pub const QCOW_CRYPT_NONE: u32 = 0;
41pub const QCOW_CRYPT_AES: u32 = 1;
42
43#[derive(Debug, Copy, Clone, IntoBytes, KnownLayout, FromBytes, Immutable)]
44#[repr(C, packed)]
45pub struct ExtensionHeader {
46    pub extension_type: BE32,
47    pub extension_size: BE32,
48}
49
50#[derive(Default, Debug, Copy, Clone, IntoBytes, KnownLayout, FromBytes, Immutable)]
51#[repr(C, packed)]
52pub struct L1Entry(pub BE64);
53
54const fn lut_entry_to_offset(entry: u64) -> Option<u64> {
55    const QCOW_LUT_OFFSET_MASK: u64 = 0xfffffffffffe00;
56    let offset = entry & QCOW_LUT_OFFSET_MASK;
57    if offset == 0 {
58        return None;
59    }
60    Some(offset)
61}
62
63impl L1Entry {
64    pub fn offset(&self) -> Option<u64> {
65        lut_entry_to_offset(self.0.get())
66    }
67}
68
69#[derive(Default, Debug, Copy, Clone, IntoBytes, KnownLayout, FromBytes, Immutable)]
70#[repr(C, packed)]
71pub struct L2Entry(pub BE64);
72
73impl L2Entry {
74    pub fn compressed(&self) -> bool {
75        const QCOW_L2_COMPRESSED: u64 = 1 << 62;
76        self.0.get() & QCOW_L2_COMPRESSED != 0
77    }
78
79    pub fn offset(&self) -> Option<u64> {
80        lut_entry_to_offset(self.0.get())
81    }
82}