xref: /aosp_15_r20/external/crosvm/devices/src/virtio/scsi/mod.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1 // Copyright 2023 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use std::path::PathBuf;
6 
7 use serde::Deserialize;
8 use serde::Serialize;
9 
10 pub(crate) mod sys;
11 
12 pub mod commands;
13 pub mod constants;
14 mod device;
15 
16 pub use device::Controller;
17 pub use device::DiskConfig;
18 
scsi_option_lock_default() -> bool19 fn scsi_option_lock_default() -> bool {
20     true
21 }
scsi_option_block_size_default() -> u3222 fn scsi_option_block_size_default() -> u32 {
23     512
24 }
25 
26 /// Parameters for setting up a SCSI device.
27 #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, serde_keyvalue::FromKeyValues)]
28 #[serde(deny_unknown_fields, rename_all = "kebab-case")]
29 pub struct ScsiOption {
30     // Path to the SCSI image.
31     pub path: PathBuf,
32     // Indicates whether the device is ready only.
33     #[serde(default, rename = "ro")]
34     pub read_only: bool,
35     /// Whether to lock the disk files. Uses flock on Unix and FILE_SHARE_* flags on Windows.
36     #[serde(default = "scsi_option_lock_default")]
37     pub lock: bool,
38     // The block size of the device.
39     #[serde(default = "scsi_option_block_size_default")]
40     pub block_size: u32,
41     /// Whether this scsi device should be the root device. Can only be set once. Only useful for
42     /// adding specific command-line options.
43     #[serde(default)]
44     pub root: bool,
45 }
46 
47 #[cfg(test)]
48 mod tests {
49     use std::path::Path;
50 
51     use serde_keyvalue::from_key_values;
52 
53     use super::*;
54 
55     #[test]
parse_scsi_options()56     fn parse_scsi_options() {
57         let scsi_option = from_key_values::<ScsiOption>("/path/to/image").unwrap();
58         assert_eq!(
59             scsi_option,
60             ScsiOption {
61                 path: Path::new("/path/to/image").to_path_buf(),
62                 read_only: false,
63                 lock: scsi_option_lock_default(),
64                 block_size: 512,
65                 root: false,
66             }
67         );
68 
69         let scsi_option = from_key_values::<ScsiOption>("/path/to/image,ro").unwrap();
70         assert_eq!(
71             scsi_option,
72             ScsiOption {
73                 path: Path::new("/path/to/image").to_path_buf(),
74                 read_only: true,
75                 lock: scsi_option_lock_default(),
76                 block_size: 512,
77                 root: false,
78             }
79         );
80 
81         let scsi_option = from_key_values::<ScsiOption>("/path/to/image,block-size=1024").unwrap();
82         assert_eq!(
83             scsi_option,
84             ScsiOption {
85                 path: Path::new("/path/to/image").to_path_buf(),
86                 read_only: false,
87                 lock: scsi_option_lock_default(),
88                 block_size: 1024,
89                 root: false,
90             }
91         );
92 
93         let scsi_option =
94             from_key_values::<ScsiOption>("/path/to/image,block-size=1024,root").unwrap();
95         assert_eq!(
96             scsi_option,
97             ScsiOption {
98                 path: Path::new("/path/to/image").to_path_buf(),
99                 read_only: false,
100                 lock: scsi_option_lock_default(),
101                 block_size: 1024,
102                 root: true,
103             }
104         );
105     }
106 }
107