sparse/
format.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// Copyright 2023 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use serde::{Deserialize, Serialize};
use static_assertions::const_assert_eq;

/// `SparseHeader` represents the header section of a `SparseFile`
#[derive(Debug, Serialize, Deserialize)]
#[repr(C)]
pub struct SparseHeader {
    /// Magic Number.
    pub magic: u32,
    /// Highest Major Version number supported.
    pub major_version: u16,
    /// Lowest Minor Version number supported.
    pub minor_version: u16,
    /// Size of the Header. (Defaults to 0)
    pub file_hdr_sz: u16,
    /// Size of the Header per-chunk. (Defaults to 0)
    pub chunk_hdr_sz: u16,
    /// Size of each block (Defaults to 4096)
    pub blk_sz: u32,
    /// Total number of blocks in the output image
    pub total_blks: u32,
    /// Total number of chunks.
    pub total_chunks: u32,
    /// Image Checksum... unused
    pub image_checksum: u32,
}

pub const SPARSE_HEADER_SIZE: usize = std::mem::size_of::<SparseHeader>();
const_assert_eq!(SPARSE_HEADER_SIZE, 28);

impl SparseHeader {
    pub fn new(blk_sz: u32, total_blks: u32, total_chunks: u32) -> SparseHeader {
        SparseHeader {
            magic: SPARSE_HEADER_MAGIC,
            major_version: MAJOR_VERSION,
            minor_version: MINOR_VERSION,
            file_hdr_sz: std::mem::size_of::<SparseHeader>() as u16,
            chunk_hdr_sz: std::mem::size_of::<ChunkHeader>() as u16,
            blk_sz,
            total_blks,
            total_chunks,
            image_checksum: CHECKSUM, // Checksum verification unused
        }
    }

    pub fn valid(&self) -> bool {
        self.magic == SPARSE_HEADER_MAGIC
            && self.major_version == MAJOR_VERSION
            && self.minor_version == MINOR_VERSION
    }
}

/// `ChunkHeader` represents the header portion of a Chunk.
#[derive(Debug, Serialize, Deserialize)]
#[repr(C)]
pub struct ChunkHeader {
    pub chunk_type: u16,
    reserved1: u16,
    pub chunk_sz: u32,
    pub total_sz: u32,
}

pub const CHUNK_HEADER_SIZE: usize = std::mem::size_of::<ChunkHeader>();
const_assert_eq!(CHUNK_HEADER_SIZE, 12);

pub const CHUNK_TYPE_RAW: u16 = 0xCAC1;
pub const CHUNK_TYPE_FILL: u16 = 0xCAC2;
pub const CHUNK_TYPE_DONT_CARE: u16 = 0xCAC3;
pub const CHUNK_TYPE_CRC32: u16 = 0xCAC4;

impl ChunkHeader {
    pub fn new(chunk_type: u16, reserved1: u16, chunk_sz: u32, total_sz: u32) -> ChunkHeader {
        ChunkHeader { chunk_type, reserved1, chunk_sz, total_sz }
    }

    pub fn valid(&self) -> bool {
        self.chunk_type == CHUNK_TYPE_RAW
            || self.chunk_type == CHUNK_TYPE_FILL
            || self.chunk_type == CHUNK_TYPE_DONT_CARE
            || self.chunk_type == CHUNK_TYPE_CRC32
    }
}

// Header constants.
pub const SPARSE_HEADER_MAGIC: u32 = 0xED26FF3A;
/// Maximum Major Version Supported.
const MAJOR_VERSION: u16 = 0x1;
// Minimum Minor Version Supported.
const MINOR_VERSION: u16 = 0x0;
/// The Checksum... hardcoded not used.
const CHECKSUM: u32 = 0xCAFED00D;