4
0
Эх сурвалжийг харах

feat: split optional parameters from stdin- and stdout-path

Moritz Meier 1 жил өмнө
parent
commit
2319fd3374

+ 1 - 1
README.md

@@ -31,7 +31,7 @@ fn main() {
     }
     }
 
 
     if let Some(stdout) = chosen.stdout() {
     if let Some(stdout) = chosen.stdout() {
-        println!("It would write stdout to: {}", stdout.name);
+        println!("It would write stdout to: {}", stdout.node().name);
     }
     }
 
 
     let soc = fdt.find_node("/soc");
     let soc = fdt.find_node("/soc");

BIN
dtb/test.dtb


+ 2 - 1
dts/test.dts

@@ -8,7 +8,8 @@
 
 
 	chosen {
 	chosen {
 		bootargs = [00];
 		bootargs = [00];
-		stdout-path = "/soc/uart@10000000";
+		stdout-path = "/soc/uart@10000000:115200";
+		stdin-path = "/soc/uart@10000000";
 	};
 	};
 
 
 	memory@80000000 {
 	memory@80000000 {

+ 5 - 1
examples/basic_info.rs

@@ -17,7 +17,11 @@ fn main() {
     }
     }
 
 
     if let Some(stdout) = chosen.stdout() {
     if let Some(stdout) = chosen.stdout() {
-        println!("It would write stdout to: {}", stdout.name);
+        println!(
+            "It would write stdout to: {} with params: {:?}",
+            stdout.node().name,
+            stdout.params()
+        );
     }
     }
 
 
     let soc = fdt.find_node("/soc");
     let soc = fdt.find_node("/soc");

+ 40 - 4
src/standard_nodes.rs

@@ -25,26 +25,62 @@ impl<'b, 'a: 'b> Chosen<'b, 'a> {
 
 
     /// Searches for the node representing `stdout`, if the property exists,
     /// Searches for the node representing `stdout`, if the property exists,
     /// attempting to resolve aliases if the node name doesn't exist as-is
     /// attempting to resolve aliases if the node name doesn't exist as-is
-    pub fn stdout(self) -> Option<FdtNode<'b, 'a>> {
+    pub fn stdout(self) -> Option<StdInOutPath<'b, 'a>> {
         self.node
         self.node
             .properties()
             .properties()
             .find(|n| n.name == "stdout-path")
             .find(|n| n.name == "stdout-path")
             .and_then(|n| core::str::from_utf8(&n.value[..n.value.len() - 1]).ok())
             .and_then(|n| core::str::from_utf8(&n.value[..n.value.len() - 1]).ok())
-            .and_then(|name| self.node.header.find_node(name))
+            .map(Self::split_stdinout_property)
+            .and_then(|(name, params)| {
+                self.node.header.find_node(name).map(|node| StdInOutPath::new(node, params))
+            })
     }
     }
 
 
     /// Searches for the node representing `stdout`, if the property exists,
     /// Searches for the node representing `stdout`, if the property exists,
     /// attempting to resolve aliases if the node name doesn't exist as-is. If
     /// attempting to resolve aliases if the node name doesn't exist as-is. If
     /// no `stdin` property exists, but `stdout` is present, it will return the
     /// no `stdin` property exists, but `stdout` is present, it will return the
     /// node specified by the `stdout` property.
     /// node specified by the `stdout` property.
-    pub fn stdin(self) -> Option<FdtNode<'b, 'a>> {
+    pub fn stdin(self) -> Option<StdInOutPath<'b, 'a>> {
         self.node
         self.node
             .properties()
             .properties()
             .find(|n| n.name == "stdin-path")
             .find(|n| n.name == "stdin-path")
             .and_then(|n| core::str::from_utf8(&n.value[..n.value.len() - 1]).ok())
             .and_then(|n| core::str::from_utf8(&n.value[..n.value.len() - 1]).ok())
-            .and_then(|name| self.node.header.find_node(name))
+            .map(Self::split_stdinout_property)
+            .and_then(|(name, params)| {
+                self.node.header.find_node(name).map(|node| StdInOutPath::new(node, params))
+            })
             .or_else(|| self.stdout())
             .or_else(|| self.stdout())
     }
     }
+
+    /// Splits a stdout-path or stdin-path property into its node path and optional parameters which are seperated by a colon ':'.
+    /// see https://devicetree-specification.readthedocs.io/en/latest/chapter3-devicenodes.html#chosen-node
+    /// example "/soc/uart@10000000" => ("/soc/uart@10000000", None)
+    /// example "/soc/uart@10000000:115200" => ("/soc/uart@10000000", Some("115200"))
+    /// example "/soc/uart@10000000:115200n8r" => ("/soc/uart@10000000", Some("115200n8r"))
+    fn split_stdinout_property(property: &str) -> (&str, Option<&str>) {
+        property
+            .split_once(':')
+            .map_or_else(|| (property, None), |(name, params)| (name, Some(params)))
+    }
+}
+
+pub struct StdInOutPath<'b, 'a> {
+    pub(crate) node: FdtNode<'b, 'a>,
+    pub(crate) params: Option<&'a str>,
+}
+
+impl<'b, 'a> StdInOutPath<'b, 'a> {
+    fn new(node: FdtNode<'b, 'a>, params: Option<&'a str>) -> Self {
+        Self { node, params }
+    }
+
+    pub fn node(&self) -> FdtNode<'b, 'a> {
+        self.node
+    }
+
+    pub fn params(&self) -> Option<&'a str> {
+        self.params
+    }
 }
 }
 
 
 /// Represents the root (`/`) node with specific helper methods
 /// Represents the root (`/`) node with specific helper methods

+ 16 - 0
src/tests.rs

@@ -197,6 +197,22 @@ fn aliases() {
     }
     }
 }
 }
 
 
+#[test]
+fn stdout() {
+    let fdt = Fdt::new(TEST).unwrap();
+    let stdout = fdt.chosen().stdout().unwrap();
+    assert!(stdout.node().name == "uart@10000000");
+    assert!(stdout.params() == Some("115200"));
+}
+
+#[test]
+fn stdin() {
+    let fdt = Fdt::new(TEST).unwrap();
+    let stdin = fdt.chosen().stdin().unwrap();
+    assert!(stdin.node().name == "uart@10000000");
+    assert!(stdin.params().is_none());
+}
+
 #[test]
 #[test]
 fn node_property_str_value() {
 fn node_property_str_value() {
     let fdt = Fdt::new(TEST).unwrap();
     let fdt = Fdt::new(TEST).unwrap();