lib.rs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. #![no_std]
  2. use core::fmt;
  3. use header::{Tag, TagIter};
  4. pub use boot_loader_name::BootLoaderNameTag;
  5. pub use elf_sections::{ElfSectionsTag, ElfSection, ElfSectionIter, ElfSectionType, ElfSectionFlags, StringTable};
  6. pub use elf_sections::{ELF_SECTION_WRITABLE, ELF_SECTION_ALLOCATED, ELF_SECTION_EXECUTABLE};
  7. pub use memory_map::{MemoryMapTag, MemoryArea, MemoryAreaIter};
  8. pub use module::{ModuleTag, ModuleIter};
  9. pub use command_line::CommandLineTag;
  10. #[macro_use]
  11. extern crate bitflags;
  12. mod header;
  13. mod boot_loader_name;
  14. mod elf_sections;
  15. mod memory_map;
  16. mod module;
  17. mod command_line;
  18. pub unsafe fn load(address: usize) -> &'static BootInformation {
  19. if !cfg!(test) {
  20. assert!(address & 0b111 == 0);
  21. }
  22. let multiboot = &*(address as *const BootInformation);
  23. assert!(multiboot.total_size & 0b111 == 0);
  24. assert!(multiboot.has_valid_end_tag());
  25. multiboot
  26. }
  27. #[repr(C)]
  28. pub struct BootInformation {
  29. pub total_size: u32,
  30. _reserved: u32,
  31. first_tag: Tag,
  32. }
  33. impl BootInformation {
  34. pub fn start_address(&self) -> usize {
  35. self as *const _ as usize
  36. }
  37. pub fn end_address(&self) -> usize {
  38. self.start_address() + self.total_size as usize
  39. }
  40. pub fn elf_sections_tag(&self) -> Option<&'static ElfSectionsTag> {
  41. self.get_tag(9).map(|tag| unsafe{&*(tag as *const Tag as *const ElfSectionsTag)})
  42. }
  43. pub fn memory_map_tag(&self) -> Option<&'static MemoryMapTag> {
  44. self.get_tag(6).map(|tag| unsafe{&*(tag as *const Tag as *const MemoryMapTag)})
  45. }
  46. pub fn module_tags(&self) -> ModuleIter {
  47. ModuleIter{ iter: self.tags() }
  48. }
  49. pub fn boot_loader_name_tag(&self) -> Option<&'static BootLoaderNameTag> {
  50. self.get_tag(2).map(|tag| unsafe{&*(tag as *const Tag as *const BootLoaderNameTag)})
  51. }
  52. pub fn command_line_tag(&self) -> Option<&'static CommandLineTag> {
  53. self.get_tag(1).map(|tag| unsafe{&*(tag as *const Tag as *const CommandLineTag)})
  54. }
  55. fn has_valid_end_tag(&self) -> bool {
  56. const END_TAG: Tag = Tag{typ:0, size:8};
  57. let self_ptr = self as *const _;
  58. let end_tag_addr = self_ptr as usize + (self.total_size - END_TAG.size) as usize;
  59. let end_tag = unsafe{&*(end_tag_addr as *const Tag)};
  60. end_tag.typ == END_TAG.typ && end_tag.size == END_TAG.size
  61. }
  62. fn get_tag(&self, typ: u32) -> Option<&'static Tag> {
  63. self.tags().find(|tag| tag.typ == typ)
  64. }
  65. fn tags(&self) -> TagIter {
  66. TagIter{current: &self.first_tag as *const _}
  67. }
  68. }
  69. impl fmt::Debug for BootInformation {
  70. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  71. writeln!(f, "multiboot information")?;
  72. writeln!(f, "S: {:#010X}, E: {:#010X}, L: {:#010X}",
  73. self.start_address(), self.end_address(), self.total_size)?;
  74. if let Some(boot_loader_name_tag) = self.boot_loader_name_tag() {
  75. writeln!(f, "boot loader name: {}", boot_loader_name_tag.name())?;
  76. }
  77. if let Some(command_line_tag) = self.command_line_tag() {
  78. writeln!(f, "command line: {}", command_line_tag.command_line())?;
  79. }
  80. if let Some(memory_map_tag) = self.memory_map_tag() {
  81. writeln!(f, "memory areas:")?;
  82. for area in memory_map_tag.memory_areas() {
  83. writeln!(f, " S: {:#010X}, E: {:#010X}, L: {:#010X}",
  84. area.base_addr, area.base_addr + area.length, area.length)?;
  85. }
  86. }
  87. if let Some(elf_sections_tag) = self.elf_sections_tag() {
  88. let string_table = elf_sections_tag.string_table();
  89. writeln!(f, "kernel sections:")?;
  90. for s in elf_sections_tag.sections() {
  91. writeln!(f, " name: {:15}, S: {:#08X}, E: {:#08X}, L: {:#08X}, F: {:#04X}",
  92. string_table.section_name(s), s.addr, s.addr + s.size, s.size, s.flags)?;
  93. }
  94. }
  95. writeln!(f, "module tags:")?;
  96. for mt in self.module_tags() {
  97. writeln!(f, " name: {:15}, S: {:#010X}, E: {:#010X}",
  98. mt.name(), mt.start_address(), mt.end_address())?;
  99. }
  100. Ok(())
  101. }
  102. }
  103. #[cfg(test)]
  104. mod tests {
  105. use super::load;
  106. #[test]
  107. fn no_tags() {
  108. let bytes: [u8; 16] = [
  109. 16, 0, 0, 0, // total_size
  110. 0, 0, 0, 0, // reserved
  111. 0, 0, 0, 0, // end tag type
  112. 8, 0, 0, 0, // end tag size
  113. ];
  114. let addr = bytes.as_ptr() as usize;
  115. let bi = unsafe { load(addr) };
  116. assert_eq!(addr, bi.start_address());
  117. assert_eq!(addr + bytes.len(), bi.end_address());
  118. assert_eq!(bytes.len(), bi.total_size as usize);
  119. assert!(bi.elf_sections_tag().is_none());
  120. assert!(bi.memory_map_tag().is_none());
  121. assert!(bi.module_tags().next().is_none());
  122. assert!(bi.boot_loader_name_tag().is_none());
  123. assert!(bi.command_line_tag().is_none());
  124. }
  125. #[test]
  126. #[should_panic]
  127. fn invalid_total_size() {
  128. let bytes: [u8; 15] = [
  129. 15, 0, 0, 0, // total_size
  130. 0, 0, 0, 0, // reserved
  131. 0, 0, 0, 0, // end tag type
  132. 8, 0, 0, // end tag size
  133. ];
  134. let addr = bytes.as_ptr() as usize;
  135. let bi = unsafe { load(addr) };
  136. assert_eq!(addr, bi.start_address());
  137. assert_eq!(addr + bytes.len(), bi.end_address());
  138. assert_eq!(bytes.len(), bi.total_size as usize);
  139. assert!(bi.elf_sections_tag().is_none());
  140. assert!(bi.memory_map_tag().is_none());
  141. assert!(bi.module_tags().next().is_none());
  142. assert!(bi.boot_loader_name_tag().is_none());
  143. assert!(bi.command_line_tag().is_none());
  144. }
  145. #[test]
  146. #[should_panic]
  147. fn invalid_end_tag() {
  148. let bytes: [u8; 16] = [
  149. 16, 0, 0, 0, // total_size
  150. 0, 0, 0, 0, // reserved
  151. 0, 0, 0, 0, // end tag type
  152. 9, 0, 0, 0, // end tag size
  153. ];
  154. let addr = bytes.as_ptr() as usize;
  155. let bi = unsafe { load(addr) };
  156. assert_eq!(addr, bi.start_address());
  157. assert_eq!(addr + bytes.len(), bi.end_address());
  158. assert_eq!(bytes.len(), bi.total_size as usize);
  159. assert!(bi.elf_sections_tag().is_none());
  160. assert!(bi.memory_map_tag().is_none());
  161. assert!(bi.module_tags().next().is_none());
  162. assert!(bi.boot_loader_name_tag().is_none());
  163. assert!(bi.command_line_tag().is_none());
  164. }
  165. #[test]
  166. fn name_tag() {
  167. let bytes: [u8; 32] = [
  168. 32, 0, 0, 0, // total_size
  169. 0, 0, 0, 0, // reserved
  170. 2, 0, 0, 0, // boot loader name tag type
  171. 13, 0, 0, 0, // boot loader name tag size
  172. 110, 97, 109, 101, // boot loader name 'name'
  173. 0, 0, 0, 0, // boot loader name null + padding
  174. 0, 0, 0, 0, // end tag type
  175. 8, 0, 0, 0, // end tag size
  176. ];
  177. let addr = bytes.as_ptr() as usize;
  178. let bi = unsafe { load(addr) };
  179. assert_eq!(addr, bi.start_address());
  180. assert_eq!(addr + bytes.len(), bi.end_address());
  181. assert_eq!(bytes.len(), bi.total_size as usize);
  182. assert!(bi.elf_sections_tag().is_none());
  183. assert!(bi.memory_map_tag().is_none());
  184. assert!(bi.module_tags().next().is_none());
  185. assert_eq!("name", bi.boot_loader_name_tag().unwrap().name());
  186. assert!(bi.command_line_tag().is_none());
  187. }
  188. }