Kaynağa Gözat

Provide method for applying search rules to a level

Isaac Woods 4 yıl önce
ebeveyn
işleme
2b00b02b34
2 değiştirilmiş dosya ile 47 ekleme ve 7 silme
  1. 45 5
      aml/src/namespace.rs
  2. 2 2
      aml/src/pci_routing.rs

+ 45 - 5
aml/src/namespace.rs

@@ -186,13 +186,28 @@ impl Namespace {
             loop {
                 // Search for the name at this namespace level. If we find it, we're done.
                 let name = path.resolve(&scope)?;
-                let (level, last_seg) = self.get_level_for_path(&name)?;
-                if let Some(&handle) = level.values.get(&last_seg) {
-                    return Ok((name, handle));
+                match self.get_level_for_path(&name) {
+                    Ok((level, last_seg)) => {
+                        if let Some(&handle) = level.values.get(&last_seg) {
+                            return Ok((name, handle));
+                        }
+                    }
+
+                    /*
+                     * This error is caught specially to avoid a case that seems bizzare but is quite useful - when
+                     * the passed starting scope doesn't exist. Certain methods return values that reference names
+                     * from the point of view of the method, so it makes sense for the starting scope to be inside
+                     * the method.  However, because we have destroyed all the objects created by the method
+                     * dynamically, the level no longer exists.
+                     *
+                     * To avoid erroring here, we simply continue to the parent scope. If the whole scope doesn't
+                     * exist, this will error when we get to the root, so this seems unlikely to introduce bugs.
+                     */
+                    Err(AmlError::LevelDoesNotExist(_)) => (),
+                    Err(err) => return Err(err),
                 }
 
-                // If we don't find it, go up a level in the namespace and search for it there,
-                // recursively.
+                // If we don't find it, go up a level in the namespace and search for it there recursively
                 match scope.parent() {
                     Ok(parent) => scope = parent,
                     // If we still haven't found the value and have run out of parents, return `None`.
@@ -213,6 +228,31 @@ impl Namespace {
         }
     }
 
+    pub fn search_for_level(&self, level_name: &AmlName, starting_scope: &AmlName) -> Result<AmlName, AmlError> {
+        if level_name.search_rules_apply() {
+            let mut scope = starting_scope.clone().normalize()?;
+            assert!(scope.is_absolute());
+
+            loop {
+                let name = level_name.resolve(&scope)?;
+                if let Ok((level, last_seg)) = self.get_level_for_path(&name) {
+                    if let Some(_) = level.children.get(&last_seg) {
+                        return Ok(name);
+                    }
+                }
+
+                // If we don't find it, move the scope up a level and search for it there recursively
+                match scope.parent() {
+                    Ok(parent) => scope = parent,
+                    Err(AmlError::RootHasNoParent) => return Err(AmlError::LevelDoesNotExist(level_name.clone())),
+                    Err(err) => return Err(err),
+                }
+            }
+        } else {
+            Ok(level_name.clone())
+        }
+    }
+
     fn get_level_for_path(&self, path: &AmlName) -> Result<(&NamespaceLevel, NameSeg), AmlError> {
         let (last_seg, levels) = path.0[1..].split_last().unwrap();
         let last_seg = last_seg.as_segment().unwrap();

+ 2 - 2
aml/src/pci_routing.rs

@@ -117,8 +117,8 @@ impl PciRoutingTable {
                             });
                         }
                         AmlValue::String(ref name) => {
-                            let (link_object_name, _) =
-                                context.namespace.search(&AmlName::from_str(name)?, &prt_path)?;
+                            let link_object_name =
+                                context.namespace.search_for_level(&AmlName::from_str(name)?, &prt_path)?;
                             entries.push(PciRoute {
                                 device,
                                 function,