Skip to content

Commit acf9c21

Browse files
Alexandra Iordachealexandruag
authored andcommitted
cmdline: specify multiple values in k=v pairs
This allows extensible kernel command line parameter specification. One possible application is configuring the console device, with key="console" and vals=name of the console device in the guest, plus options. Signed-off-by: Alexandra Iordache <aghecen@amazon.com>
1 parent ea74b2b commit acf9c21

File tree

3 files changed

+74
-1
lines changed

3 files changed

+74
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
- Added functions for specifying virtio MMIO devices when building the kernel
66
command line.
7+
- Added a function to specify multiple values in `key=values` pairs when
8+
building the kernel command line.
79

810
# [v0.2.0]
911

coverage_config_x86_64.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"coverage_score": 79.2,
2+
"coverage_score": 80.1,
33
"exclude_path": "",
44
"crate_features": "bzimage,elf",
55
"exclude_path": "benches/,loader_gen/"

src/cmdline/mod.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ pub enum Error {
2424
HasSpace,
2525
/// Key/Value Operation would have had an equals sign in it.
2626
HasEquals,
27+
/// Key/Value Operation was not passed a value.
28+
MissingVal(String),
2729
/// 0-sized virtio MMIO device passed to the kernel command line builder.
2830
MmioSize,
2931
/// Operation would have made the command line too large.
@@ -41,6 +43,7 @@ impl fmt::Display for Error {
4143
),
4244
Error::HasSpace => write!(f, "String contains a space."),
4345
Error::HasEquals => write!(f, "String contains an equals sign."),
46+
Error::MissingVal(ref k) => write!(f, "Missing value for key {}.", k),
4447
Error::MmioSize => write!(
4548
f,
4649
"0-sized virtio MMIO device passed to the kernel command line builder."
@@ -178,6 +181,46 @@ impl Cmdline {
178181
Ok(())
179182
}
180183

184+
/// Validates and inserts a key-value1,...,valueN pair into this command line.
185+
///
186+
/// # Arguments
187+
///
188+
/// * `key` - Key to be inserted in the command line string.
189+
/// * `vals` - Values corresponding to `key`.
190+
///
191+
/// # Examples
192+
///
193+
/// ```rust
194+
/// # use linux_loader::cmdline::*;
195+
/// # use std::ffi::CString;
196+
/// let mut cl = Cmdline::new(100);
197+
/// cl.insert_multiple("foo", &["bar", "baz"]);
198+
/// let cl_cstring = CString::new(cl).unwrap();
199+
/// assert_eq!(cl_cstring.to_str().unwrap(), "foo=bar,baz");
200+
/// ```
201+
pub fn insert_multiple<T: AsRef<str>>(&mut self, key: T, vals: &[T]) -> Result<()> {
202+
let k = key.as_ref();
203+
204+
valid_element(k)?;
205+
if vals.is_empty() {
206+
return Err(Error::MissingVal(k.to_string()));
207+
}
208+
209+
let kv_str = format!(
210+
"{}={}",
211+
k,
212+
vals.iter()
213+
.map(|v| -> Result<&str> {
214+
valid_element(v.as_ref())?;
215+
Ok(v.as_ref())
216+
})
217+
.collect::<Result<Vec<&str>>>()?
218+
.join(",")
219+
);
220+
221+
self.insert_str(kv_str)
222+
}
223+
181224
/// Validates and inserts a string to the end of the current command line.
182225
///
183226
/// # Arguments
@@ -414,4 +457,32 @@ mod tests {
414457
expected_str.push_str(" virtio_mmio.device=4G@0x10000:4:42");
415458
assert_eq!(cl.as_str(), &expected_str);
416459
}
460+
461+
#[test]
462+
fn test_insert_kv() {
463+
let mut cl = Cmdline::new(10);
464+
465+
let no_vals: Vec<&str> = vec![];
466+
assert_eq!(cl.insert_multiple("foo=", &no_vals), Err(Error::HasEquals));
467+
assert_eq!(
468+
cl.insert_multiple("foo", &no_vals),
469+
Err(Error::MissingVal("foo".to_string()))
470+
);
471+
assert_eq!(
472+
cl.insert_multiple("foo", &vec!["bar "]),
473+
Err(Error::HasSpace)
474+
);
475+
assert_eq!(
476+
cl.insert_multiple("foo", &vec!["bar", "baz"]),
477+
Err(Error::TooLarge)
478+
);
479+
480+
let mut cl = Cmdline::new(100);
481+
assert!(cl.insert_multiple("foo", &vec!["bar"]).is_ok());
482+
assert_eq!(cl.as_str(), "foo=bar");
483+
484+
let mut cl = Cmdline::new(100);
485+
assert!(cl.insert_multiple("foo", &vec!["bar", "baz"]).is_ok());
486+
assert_eq!(cl.as_str(), "foo=bar,baz");
487+
}
417488
}

0 commit comments

Comments
 (0)