浏览代码

Add tag iterator and `get_tag` method

Philipp Oppermann 9 年之前
父节点
当前提交
320b96e570
共有 1 个文件被更改,包括 35 次插入0 次删除
  1. 35 0
      src/lib.rs

+ 35 - 0
src/lib.rs

@@ -1,6 +1,8 @@
 #![feature(no_std)]
 #![no_std]
 
+use core::mem::size_of;
+
 pub unsafe fn load(address: usize) -> &'static Multiboot {
     let multiboot = &*(address as *const Multiboot);
     assert!(multiboot.has_valid_end_tag());
@@ -24,6 +26,16 @@ impl Multiboot {
 
         end_tag.typ == END_TAG.typ && end_tag.size == END_TAG.size
     }
+
+    fn get_tag(&self, typ: u32) -> Option<&'static Tag> {
+        self.tags().find(|tag| tag.typ == typ)
+    }
+
+    fn tags(&self) -> TagIter {
+        let self_addr = self as *const _ as usize;
+        let first_tag = (self_addr + size_of::<Multiboot>()) as *const Tag;
+        TagIter{current: first_tag}
+    }
 }
 
 #[repr(C)]
@@ -32,3 +44,26 @@ struct Tag {
     size: u32,
     // tag specific fields
 }
+
+struct TagIter {
+    current: *const Tag,
+}
+
+impl Iterator for TagIter {
+    type Item = &'static Tag;
+
+    fn next(&mut self) -> Option<&'static Tag> {
+        match unsafe{&*self.current} {
+            &Tag{typ:0, size:8} => None, // end tag
+            tag => {
+                // go to next tag
+                let mut tag_addr = self.current as usize;
+                tag_addr += tag.size as usize;
+                tag_addr = ((tag_addr-1) & !0x7) + 0x8; //align at 8 byte
+                self.current = tag_addr as *const _;
+
+                Some(tag)
+            },
+        }
+    }
+}