lib.rs 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883
  1. #![no_std]
  2. #![deny(missing_debug_implementations)]
  3. use core::fmt;
  4. use header::{Tag, TagIter};
  5. pub use boot_loader_name::BootLoaderNameTag;
  6. pub use elf_sections::{ElfSectionsTag, ElfSection, ElfSectionIter, ElfSectionType, ElfSectionFlags};
  7. pub use framebuffer::{FramebufferTag, FramebufferType, FramebufferField, FramebufferColor};
  8. pub use memory_map::{MemoryMapTag, MemoryArea, MemoryAreaIter};
  9. pub use module::{ModuleTag, ModuleIter};
  10. pub use command_line::CommandLineTag;
  11. pub use rsdp::{RsdpV1Tag, RsdpV2Tag};
  12. #[macro_use]
  13. extern crate bitflags;
  14. mod header;
  15. mod boot_loader_name;
  16. mod elf_sections;
  17. mod memory_map;
  18. mod module;
  19. mod command_line;
  20. mod rsdp;
  21. mod framebuffer;
  22. pub unsafe fn load(address: usize) -> BootInformation {
  23. assert_eq!(0, address & 0b111);
  24. let multiboot = &*(address as *const BootInformationInner);
  25. assert_eq!(0, multiboot.total_size & 0b111);
  26. assert!(multiboot.has_valid_end_tag());
  27. BootInformation { inner: multiboot, offset: 0 }
  28. }
  29. pub unsafe fn load_with_offset(address: usize, offset: usize) -> BootInformation {
  30. if !cfg!(test) {
  31. assert_eq!(0, address & 0b111);
  32. assert_eq!(0, offset & 0b111);
  33. }
  34. let multiboot = &*((address + offset) as *const BootInformationInner);
  35. assert_eq!(0, multiboot.total_size & 0b111);
  36. assert!(multiboot.has_valid_end_tag());
  37. BootInformation { inner: multiboot, offset: offset }
  38. }
  39. pub struct BootInformation {
  40. inner: *const BootInformationInner,
  41. offset: usize,
  42. }
  43. #[repr(C, packed)]
  44. struct BootInformationInner {
  45. total_size: u32,
  46. _reserved: u32,
  47. }
  48. impl BootInformation {
  49. pub fn start_address(&self) -> usize {
  50. self.inner as usize
  51. }
  52. pub fn end_address(&self) -> usize {
  53. self.start_address() + self.total_size()
  54. }
  55. pub fn total_size(&self) -> usize {
  56. self.get().total_size as usize
  57. }
  58. pub fn elf_sections_tag(&self) -> Option<ElfSectionsTag> {
  59. self.get_tag(9).map(|tag| unsafe {
  60. elf_sections::elf_sections_tag(tag, self.offset)
  61. })
  62. }
  63. pub fn memory_map_tag<'a>(&'a self) -> Option<&'a MemoryMapTag> {
  64. self.get_tag(6).map(|tag| unsafe { &*(tag as *const Tag as *const MemoryMapTag) })
  65. }
  66. pub fn module_tags(&self) -> ModuleIter {
  67. module::module_iter(self.tags())
  68. }
  69. pub fn boot_loader_name_tag<'a>(&'a self) -> Option<&'a BootLoaderNameTag> {
  70. self.get_tag(2).map(|tag| unsafe { &*(tag as *const Tag as *const BootLoaderNameTag) })
  71. }
  72. pub fn command_line_tag<'a>(&'a self) -> Option<&'a CommandLineTag> {
  73. self.get_tag(1).map(|tag| unsafe { &*(tag as *const Tag as *const CommandLineTag) })
  74. }
  75. pub fn framebuffer_tag<'a>(&'a self) -> Option<FramebufferTag<'a>> {
  76. self.get_tag(8).map(|tag| framebuffer::framebuffer_tag(tag))
  77. }
  78. pub fn rsdp_v1_tag<'a>(&self) -> Option<&'a RsdpV1Tag> {
  79. self.get_tag(14).map(|tag| unsafe { &*(tag as *const Tag as *const RsdpV1Tag) })
  80. }
  81. pub fn rsdp_v2_tag<'a>(&'a self) -> Option<&'a RsdpV2Tag> {
  82. self.get_tag(15).map(|tag| unsafe { &*(tag as *const Tag as *const RsdpV2Tag) })
  83. }
  84. fn get(&self) -> &BootInformationInner {
  85. unsafe { &*self.inner }
  86. }
  87. fn get_tag<'a>(&'a self, typ: u32) -> Option<&'a Tag> {
  88. self.tags().find(|tag| tag.typ == typ)
  89. }
  90. fn tags(&self) -> TagIter {
  91. TagIter::new(unsafe { self.inner.offset(1) } as *const _)
  92. }
  93. }
  94. impl BootInformationInner {
  95. fn has_valid_end_tag(&self) -> bool {
  96. const END_TAG: Tag = Tag { typ: 0, size: 8 };
  97. let self_ptr = self as *const _;
  98. let end_tag_addr = self_ptr as usize + (self.total_size - END_TAG.size) as usize;
  99. let end_tag = unsafe { &*(end_tag_addr as *const Tag) };
  100. end_tag.typ == END_TAG.typ && end_tag.size == END_TAG.size
  101. }
  102. }
  103. impl fmt::Debug for BootInformation {
  104. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  105. writeln!(f, "multiboot information")?;
  106. writeln!(f, "S: {:#010X}, E: {:#010X}, L: {:#010X}",
  107. self.start_address(), self.end_address(), self.total_size())?;
  108. if let Some(boot_loader_name_tag) = self.boot_loader_name_tag() {
  109. writeln!(f, "boot loader name: {}", boot_loader_name_tag.name())?;
  110. }
  111. if let Some(command_line_tag) = self.command_line_tag() {
  112. writeln!(f, "command line: {}", command_line_tag.command_line())?;
  113. }
  114. if let Some(memory_map_tag) = self.memory_map_tag() {
  115. writeln!(f, "memory areas:")?;
  116. for area in memory_map_tag.memory_areas() {
  117. writeln!(f, " S: {:#010X}, E: {:#010X}, L: {:#010X}",
  118. area.start_address(), area.end_address(), area.size())?;
  119. }
  120. }
  121. if let Some(elf_sections_tag) = self.elf_sections_tag() {
  122. writeln!(f, "kernel sections:")?;
  123. for s in elf_sections_tag.sections() {
  124. writeln!(f, " name: {:15}, S: {:#08X}, E: {:#08X}, L: {:#08X}, F: {:#04X}",
  125. s.name(), s.start_address(),
  126. s.start_address() + s.size(), s.size(), s.flags().bits())?;
  127. }
  128. }
  129. writeln!(f, "module tags:")?;
  130. for mt in self.module_tags() {
  131. writeln!(f, " name: {:15}, S: {:#010X}, E: {:#010X}",
  132. mt.name(), mt.start_address(), mt.end_address())?;
  133. }
  134. Ok(())
  135. }
  136. }
  137. pub(crate) struct Reader {
  138. pub(crate) ptr: *const u8,
  139. pub(crate) off: usize
  140. }
  141. impl Reader {
  142. pub(crate) fn new<T>(ptr: *const T) -> Reader {
  143. Reader {
  144. ptr: ptr as *const u8,
  145. off: 0
  146. }
  147. }
  148. pub(crate) fn read_u8(&mut self) -> u8 {
  149. self.off += 1;
  150. unsafe {
  151. core::ptr::read(self.ptr.offset((self.off - 1) as isize))
  152. }
  153. }
  154. pub(crate) fn read_u16(&mut self) -> u16 {
  155. self.read_u8() as u16 | (self.read_u8() as u16) << 8
  156. }
  157. pub(crate) fn read_u32(&mut self) -> u32 {
  158. self.read_u16() as u32 | (self.read_u16() as u32) << 16
  159. }
  160. pub(crate) fn read_u64(&mut self) -> u64 {
  161. self.read_u32() as u64 | (self.read_u32() as u64) << 32
  162. }
  163. pub(crate) fn skip(&mut self, n: usize) {
  164. self.off += n;
  165. }
  166. }
  167. #[cfg(test)]
  168. mod tests {
  169. use super::{load, load_with_offset};
  170. use super::{BootInformation, ElfSectionFlags, ElfSectionType};
  171. use super::FramebufferType;
  172. #[test]
  173. fn no_tags() {
  174. #[repr(C, align(8))]
  175. struct Bytes([u8; 16]);
  176. let bytes: Bytes = Bytes([
  177. 16, 0, 0, 0, // total_size
  178. 0, 0, 0, 0, // reserved
  179. 0, 0, 0, 0, // end tag type
  180. 8, 0, 0, 0, // end tag size
  181. ]);
  182. let addr = bytes.0.as_ptr() as usize;
  183. let bi = unsafe { load(addr) };
  184. assert_eq!(addr, bi.start_address());
  185. assert_eq!(addr + bytes.0.len(), bi.end_address());
  186. assert_eq!(bytes.0.len(), bi.total_size());
  187. assert!(bi.elf_sections_tag().is_none());
  188. assert!(bi.memory_map_tag().is_none());
  189. assert!(bi.module_tags().next().is_none());
  190. assert!(bi.boot_loader_name_tag().is_none());
  191. assert!(bi.command_line_tag().is_none());
  192. }
  193. #[test]
  194. #[should_panic]
  195. fn invalid_total_size() {
  196. #[repr(C, align(8))]
  197. struct Bytes([u8; 15]);
  198. let bytes: Bytes = Bytes([
  199. 15, 0, 0, 0, // total_size
  200. 0, 0, 0, 0, // reserved
  201. 0, 0, 0, 0, // end tag type
  202. 8, 0, 0, // end tag size
  203. ]);
  204. let addr = bytes.0.as_ptr() as usize;
  205. let bi = unsafe { load(addr) };
  206. assert_eq!(addr, bi.start_address());
  207. assert_eq!(addr + bytes.0.len(), bi.end_address());
  208. assert_eq!(bytes.0.len(), bi.total_size());
  209. assert!(bi.elf_sections_tag().is_none());
  210. assert!(bi.memory_map_tag().is_none());
  211. assert!(bi.module_tags().next().is_none());
  212. assert!(bi.boot_loader_name_tag().is_none());
  213. assert!(bi.command_line_tag().is_none());
  214. }
  215. #[test]
  216. #[should_panic]
  217. fn invalid_end_tag() {
  218. #[repr(C, align(8))]
  219. struct Bytes([u8; 16]);
  220. let bytes: Bytes = Bytes([
  221. 16, 0, 0, 0, // total_size
  222. 0, 0, 0, 0, // reserved
  223. 0, 0, 0, 0, // end tag type
  224. 9, 0, 0, 0, // end tag size
  225. ]);
  226. let addr = bytes.0.as_ptr() as usize;
  227. let bi = unsafe { load(addr) };
  228. assert_eq!(addr, bi.start_address());
  229. assert_eq!(addr + bytes.0.len(), bi.end_address());
  230. assert_eq!(bytes.0.len(), bi.total_size());
  231. assert!(bi.elf_sections_tag().is_none());
  232. assert!(bi.memory_map_tag().is_none());
  233. assert!(bi.module_tags().next().is_none());
  234. assert!(bi.boot_loader_name_tag().is_none());
  235. assert!(bi.command_line_tag().is_none());
  236. }
  237. #[test]
  238. fn name_tag() {
  239. #[repr(C, align(8))]
  240. struct Bytes([u8; 32]);
  241. let bytes: Bytes = Bytes([
  242. 32, 0, 0, 0, // total_size
  243. 0, 0, 0, 0, // reserved
  244. 2, 0, 0, 0, // boot loader name tag type
  245. 13, 0, 0, 0, // boot loader name tag size
  246. 110, 97, 109, 101, // boot loader name 'name'
  247. 0, 0, 0, 0, // boot loader name null + padding
  248. 0, 0, 0, 0, // end tag type
  249. 8, 0, 0, 0, // end tag size
  250. ]);
  251. let addr = bytes.0.as_ptr() as usize;
  252. let bi = unsafe { load(addr) };
  253. assert_eq!(addr, bi.start_address());
  254. assert_eq!(addr + bytes.0.len(), bi.end_address());
  255. assert_eq!(bytes.0.len(), bi.total_size());
  256. assert!(bi.elf_sections_tag().is_none());
  257. assert!(bi.memory_map_tag().is_none());
  258. assert!(bi.module_tags().next().is_none());
  259. assert_eq!("name", bi.boot_loader_name_tag().unwrap().name());
  260. assert!(bi.command_line_tag().is_none());
  261. }
  262. #[test]
  263. fn framebuffer_tag_rgb() {
  264. // direct RGB mode test:
  265. // taken from GRUB2 running in QEMU at
  266. // 1280x720 with 32bpp in BGRA format.
  267. #[repr(C, align(8))]
  268. struct Bytes([u8; 56]);
  269. let bytes: Bytes = Bytes([
  270. 56, 0, 0, 0, // total size
  271. 0, 0, 0, 0, // reserved
  272. 8, 0, 0, 0, // framebuffer tag type
  273. 40, 0, 0, 0, // framebuffer tag size
  274. 0, 0, 0, 253, // framebuffer low dword of address
  275. 0, 0, 0, 0, // framebuffer high dword of address
  276. 0, 20, 0, 0, // framebuffer pitch
  277. 0, 5, 0, 0, // framebuffer width
  278. 208, 2, 0, 0, // framebuffer height
  279. 32, 1, 0, 0, // framebuffer bpp, type, reserved word
  280. 16, 8, 8, 8, // framebuffer red pos/size, green pos/size
  281. 0, 8, 0, 0, // framebuffer blue pos/size, padding word
  282. 0, 0, 0, 0, // end tag type
  283. 8, 0, 0, 0 // end tag size
  284. ]);
  285. let addr = bytes.0.as_ptr() as usize;
  286. let bi = unsafe { load(addr) };
  287. assert_eq!(addr, bi.start_address());
  288. assert_eq!(addr + bytes.0.len(), bi.end_address());
  289. assert_eq!(bytes.0.len(), bi.total_size());
  290. use framebuffer::{FramebufferTag, FramebufferField, FramebufferType};
  291. assert_eq!(bi.framebuffer_tag(), Some(FramebufferTag {
  292. address: 4244635648,
  293. pitch: 5120,
  294. width: 1280,
  295. height: 720,
  296. bpp: 32,
  297. buffer_type: FramebufferType::RGB {
  298. red: FramebufferField {
  299. position: 16, size: 8
  300. },
  301. green: FramebufferField {
  302. position: 8, size: 8
  303. },
  304. blue: FramebufferField {
  305. position: 0, size: 8
  306. }
  307. }
  308. }))
  309. }
  310. #[test]
  311. fn framebuffer_tag_indexed() {
  312. // indexed mode test:
  313. // this is synthetic, as I can't get QEMU
  314. // to run in indexed color mode.
  315. #[repr(C, align(8))]
  316. struct Bytes([u8; 56]);
  317. let bytes: Bytes = Bytes([
  318. 56, 0, 0, 0, // total size
  319. 0, 0, 0, 0, // reserved
  320. 8, 0, 0, 0, // framebuffer tag type
  321. 40, 0, 0, 0, // framebuffer tag size
  322. 0, 0, 0, 253, // framebuffer low dword of address
  323. 0, 0, 0, 0, // framebuffer high dword of address
  324. 0, 20, 0, 0, // framebuffer pitch
  325. 0, 5, 0, 0, // framebuffer width
  326. 208, 2, 0, 0, // framebuffer height
  327. 32, 0, 0, 0, // framebuffer bpp, type, reserved word
  328. 0, 1, 0, 0, // framebuffer palette length
  329. 0, 24, 1, 0, // framebuffer palette address
  330. 0, 0, 0, 0, // end tag type
  331. 8, 0, 0, 0 // end tag size
  332. ]);
  333. let addr = bytes.0.as_ptr() as usize;
  334. let bi = unsafe { load(addr) };
  335. assert_eq!(addr, bi.start_address());
  336. assert_eq!(addr + bytes.0.len(), bi.end_address());
  337. assert_eq!(bytes.0.len(), bi.total_size());
  338. use framebuffer::FramebufferType;
  339. assert!(bi.framebuffer_tag().is_some());
  340. let fbi = bi.framebuffer_tag().unwrap();
  341. assert_eq!(fbi.address, 4244635648);
  342. assert_eq!(fbi.pitch, 5120);
  343. assert_eq!(fbi.width, 1280);
  344. assert_eq!(fbi.height, 720);
  345. assert_eq!(fbi.bpp, 32);
  346. match fbi.buffer_type {
  347. FramebufferType::Indexed { palette } => {
  348. assert_eq!(palette.as_ptr() as usize, 71680);
  349. assert_eq!(palette.len(), 256);
  350. },
  351. _ => panic!("Expected indexed framebuffer type.")
  352. }
  353. }
  354. #[test]
  355. fn grub2() {
  356. #[repr(C, align(8))]
  357. struct Bytes([u8; 960]);
  358. let mut bytes: Bytes = Bytes([
  359. 192, 3, 0, 0, // total_size
  360. 0, 0, 0, 0, // reserved
  361. 1, 0, 0, 0, // boot command tag type
  362. 9, 0, 0, 0, // boot command tag size
  363. 0, 0, 0, 0, // boot command null + padding
  364. 0, 0, 0, 0, // boot command padding
  365. 2, 0, 0, 0, // boot loader name tag type
  366. 26, 0, 0, 0, // boot loader name tag size
  367. 71, 82, 85, 66, // boot loader name
  368. 32, 50, 46, 48, // boot loader name
  369. 50, 126, 98, 101, // boot loader name
  370. 116, 97, 51, 45, // boot loader name
  371. 53, 0, 0, 0, // boot loader name null + padding
  372. 0, 0, 0, 0, // boot loader name padding
  373. 10, 0, 0, 0, // APM tag type
  374. 28, 0, 0, 0, // APM tag size
  375. 2, 1, 0, 240, // APM version, cseg
  376. 207, 212, 0, 0, // APM offset
  377. 0, 240, 0, 240, // APM cseg_16, dseg
  378. 3, 0, 240, 255, // APM flags, cseg_len
  379. 240, 255, 240, 255, // APM cseg_16_len, dseg_len
  380. 0, 0, 0, 0, // APM padding
  381. 6, 0, 0, 0, // memory map tag type
  382. 160, 0, 0, 0, // memory map tag size
  383. 24, 0, 0, 0, // memory map entry_size
  384. 0, 0, 0, 0, // memory map entry_version
  385. 0, 0, 0, 0, // memory map entry 0 base_addr
  386. 0, 0, 0, 0, // memory map entry 0 base_addr
  387. 0, 252, 9, 0, // memory map entry 0 length
  388. 0, 0, 0, 0, // memory map entry 0 length
  389. 1, 0, 0, 0, // memory map entry 0 type
  390. 0, 0, 0, 0, // memory map entry 0 reserved
  391. 0, 252, 9, 0, // memory map entry 1 base_addr
  392. 0, 0, 0, 0, // memory map entry 1 base_addr
  393. 0, 4, 0, 0, // memory map entry 1 length
  394. 0, 0, 0, 0, // memory map entry 1 length
  395. 2, 0, 0, 0, // memory map entry 1 type
  396. 0, 0, 0, 0, // memory map entry 1 reserved
  397. 0, 0, 15, 0, // memory map entry 2 base_addr
  398. 0, 0, 0, 0, // memory map entry 2 base_addr
  399. 0, 0, 1, 0, // memory map entry 2 length
  400. 0, 0, 0, 0, // memory map entry 2 length
  401. 2, 0, 0, 0, // memory map entry 2 type
  402. 0, 0, 0, 0, // memory map entry 2 reserved
  403. 0, 0, 16, 0, // memory map entry 3 base_addr
  404. 0, 0, 0, 0, // memory map entry 3 base_addr
  405. 0, 0, 238, 7, // memory map entry 3 length
  406. 0, 0, 0, 0, // memory map entry 3 length
  407. 1, 0, 0, 0, // memory map entry 3 type
  408. 0, 0, 0, 0, // memory map entry 3 reserved
  409. 0, 0, 254, 7, // memory map entry 4 base_addr
  410. 0, 0, 0, 0, // memory map entry 4 base_addr
  411. 0, 0, 2, 0, // memory map entry 4 length
  412. 0, 0, 0, 0, // memory map entry 4 length
  413. 2, 0, 0, 0, // memory map entry 4 type
  414. 0, 0, 0, 0, // memory map entry 4 reserved
  415. 0, 0, 252, 255, // memory map entry 5 base_addr
  416. 0, 0, 0, 0, // memory map entry 5 base_addr
  417. 0, 0, 4, 0, // memory map entry 5 length
  418. 0, 0, 0, 0, // memory map entry 5 length
  419. 2, 0, 0, 0, // memory map entry 5 type
  420. 0, 0, 0, 0, // memory map entry 5 reserved
  421. 9, 0, 0, 0, // elf symbols tag type
  422. 84, 2, 0, 0, // elf symbols tag size
  423. 9, 0, 0, 0, // elf symbols num
  424. 64, 0, 0, 0, // elf symbols entsize
  425. 8, 0, 0, 0, // elf symbols shndx
  426. 0, 0, 0, 0, // elf symbols entry 0 name
  427. 0, 0, 0, 0, // elf symbols entry 0 type
  428. 0, 0, 0, 0, // elf symbols entry 0 flags
  429. 0, 0, 0, 0, // elf symbols entry 0 flags
  430. 0, 0, 0, 0, // elf symbols entry 0 addr
  431. 0, 0, 0, 0, // elf symbols entry 0 addr
  432. 0, 0, 0, 0, // elf symbols entry 0 offset
  433. 0, 0, 0, 0, // elf symbols entry 0 offset
  434. 0, 0, 0, 0, // elf symbols entry 0 size
  435. 0, 0, 0, 0, // elf symbols entry 0 size
  436. 0, 0, 0, 0, // elf symbols entry 0 link
  437. 0, 0, 0, 0, // elf symbols entry 0 info
  438. 0, 0, 0, 0, // elf symbols entry 0 addralign
  439. 0, 0, 0, 0, // elf symbols entry 0 addralign
  440. 0, 0, 0, 0, // elf symbols entry 0 entsize
  441. 0, 0, 0, 0, // elf symbols entry 0 entsize
  442. 27, 0, 0, 0, // elf symbols entry 1 name
  443. 1, 0, 0, 0, // elf symbols entry 1 type
  444. 2, 0, 0, 0, // elf symbols entry 1 flags
  445. 0, 0, 0, 0, // elf symbols entry 1 flags
  446. 0, 0, 16, 0, // elf symbols entry 1 addr
  447. 0, 128, 255, 255, // elf symbols entry 1 addr
  448. 0, 16, 0, 0, // elf symbols entry 1 offset
  449. 0, 0, 0, 0, // elf symbols entry 1 offset
  450. 0, 48, 0, 0, // elf symbols entry 1 size
  451. 0, 0, 0, 0, // elf symbols entry 1 size
  452. 0, 0, 0, 0, // elf symbols entry 1 link
  453. 0, 0, 0, 0, // elf symbols entry 1 info
  454. 16, 0, 0, 0, // elf symbols entry 1 addralign
  455. 0, 0, 0, 0, // elf symbols entry 1 addralign
  456. 0, 0, 0, 0, // elf symbols entry 1 entsize
  457. 0, 0, 0, 0, // elf symbols entry 1 entsize
  458. 35, 0, 0, 0, // elf symbols entry 2 name
  459. 1, 0, 0, 0, // elf symbols entry 2 type
  460. 6, 0, 0, 0, // elf symbols entry 2 flags
  461. 0, 0, 0, 0, // elf symbols entry 2 flags
  462. 0, 48, 16, 0, // elf symbols entry 2 addr
  463. 0, 128, 255, 255, // elf symbols entry 2 addr
  464. 0, 64, 0, 0, // elf symbols entry 2 offset
  465. 0, 0, 0, 0, // elf symbols entry 2 offset
  466. 0, 144, 0, 0, // elf symbols entry 2 size
  467. 0, 0, 0, 0, // elf symbols entry 2 size
  468. 0, 0, 0, 0, // elf symbols entry 2 link
  469. 0, 0, 0, 0, // elf symbols entry 2 info
  470. 16, 0, 0, 0, // elf symbols entry 2 addralign
  471. 0, 0, 0, 0, // elf symbols entry 2 addralign
  472. 0, 0, 0, 0, // elf symbols entry 2 entsize
  473. 0, 0, 0, 0, // elf symbols entry 2 entsize
  474. 41, 0, 0, 0, // elf symbols entry 3 name
  475. 1, 0, 0, 0, // elf symbols entry 3 type
  476. 3, 0, 0, 0, // elf symbols entry 3 flags
  477. 0, 0, 0, 0, // elf symbols entry 3 flags
  478. 0, 192, 16, 0, // elf symbols entry 3 addr
  479. 0, 128, 255, 255, // elf symbols entry 3 addr
  480. 0, 208, 0, 0, // elf symbols entry 3 offset
  481. 0, 0, 0, 0, // elf symbols entry 3 offset
  482. 0, 32, 0, 0, // elf symbols entry 3 size
  483. 0, 0, 0, 0, // elf symbols entry 3 size
  484. 0, 0, 0, 0, // elf symbols entry 3 link
  485. 0, 0, 0, 0, // elf symbols entry 3 info
  486. 8, 0, 0, 0, // elf symbols entry 3 addralign
  487. 0, 0, 0, 0, // elf symbols entry 3 addralign
  488. 0, 0, 0, 0, // elf symbols entry 3 entsize
  489. 0, 0, 0, 0, // elf symbols entry 3 entsize
  490. 47, 0, 0, 0, // elf symbols entry 4 name
  491. 8, 0, 0, 0, // elf symbols entry 4 type
  492. 3, 0, 0, 0, // elf symbols entry 4 flags
  493. 0, 0, 0, 0, // elf symbols entry 4 flags
  494. 0, 224, 16, 0, // elf symbols entry 4 addr
  495. 0, 128, 255, 255, // elf symbols entry 4 addr
  496. 0, 240, 0, 0, // elf symbols entry 4 offset
  497. 0, 0, 0, 0, // elf symbols entry 4 offset
  498. 0, 80, 0, 0, // elf symbols entry 4 size
  499. 0, 0, 0, 0, // elf symbols entry 4 size
  500. 0, 0, 0, 0, // elf symbols entry 4 link
  501. 0, 0, 0, 0, // elf symbols entry 4 info
  502. 0, 16, 0, 0, // elf symbols entry 4 addralign
  503. 0, 0, 0, 0, // elf symbols entry 4 addralign
  504. 0, 0, 0, 0, // elf symbols entry 4 entsize
  505. 0, 0, 0, 0, // elf symbols entry 4 entsize
  506. 52, 0, 0, 0, // elf symbols entry 5 name
  507. 1, 0, 0, 0, // elf symbols entry 5 type
  508. 3, 0, 0, 0, // elf symbols entry 5 flags
  509. 0, 0, 0, 0, // elf symbols entry 5 flags
  510. 0, 48, 17, 0, // elf symbols entry 5 addr
  511. 0, 128, 255, 255, // elf symbols entry 5 addr
  512. 0, 240, 0, 0, // elf symbols entry 5 offset
  513. 0, 0, 0, 0, // elf symbols entry 5 offset
  514. 0, 0, 0, 0, // elf symbols entry 5 size
  515. 0, 0, 0, 0, // elf symbols entry 5 size
  516. 0, 0, 0, 0, // elf symbols entry 5 link
  517. 0, 0, 0, 0, // elf symbols entry 5 info
  518. 1, 0, 0, 0, // elf symbols entry 5 addralign
  519. 0, 0, 0, 0, // elf symbols entry 5 addralign
  520. 0, 0, 0, 0, // elf symbols entry 5 entsize
  521. 0, 0, 0, 0, // elf symbols entry 5 entsize
  522. 1, 0, 0, 0, // elf symbols entry 6 name
  523. 2, 0, 0, 0, // elf symbols entry 6 type
  524. 0, 0, 0, 0, // elf symbols entry 6 flags
  525. 0, 0, 0, 0, // elf symbols entry 6 flags
  526. 0, 48, 17, 0, // elf symbols entry 6 addr
  527. 0, 0, 0, 0, // elf symbols entry 6 addr
  528. 0, 240, 0, 0, // elf symbols entry 6 offset
  529. 0, 0, 0, 0, // elf symbols entry 6 offset
  530. 224, 43, 0, 0, // elf symbols entry 6 size
  531. 0, 0, 0, 0, // elf symbols entry 6 size
  532. 7, 0, 0, 0, // elf symbols entry 6 link
  533. 102, 1, 0, 0, // elf symbols entry 6 info
  534. 8, 0, 0, 0, // elf symbols entry 6 addralign
  535. 0, 0, 0, 0, // elf symbols entry 6 addralign
  536. 24, 0, 0, 0, // elf symbols entry 6 entsize
  537. 0, 0, 0, 0, // elf symbols entry 6 entsize
  538. 9, 0, 0, 0, // elf symbols entry 7 name
  539. 3, 0, 0, 0, // elf symbols entry 7 type
  540. 0, 0, 0, 0, // elf symbols entry 7 flags
  541. 0, 0, 0, 0, // elf symbols entry 7 flags
  542. 224, 91, 17, 0, // elf symbols entry 7 addr
  543. 0, 0, 0, 0, // elf symbols entry 7 addr
  544. 224, 27, 1, 0, // elf symbols entry 7 offset
  545. 0, 0, 0, 0, // elf symbols entry 7 offset
  546. 145, 55, 0, 0, // elf symbols entry 7 size
  547. 0, 0, 0, 0, // elf symbols entry 7 size
  548. 0, 0, 0, 0, // elf symbols entry 7 link
  549. 0, 0, 0, 0, // elf symbols entry 7 info
  550. 1, 0, 0, 0, // elf symbols entry 7 addralign
  551. 0, 0, 0, 0, // elf symbols entry 7 addralign
  552. 0, 0, 0, 0, // elf symbols entry 7 entsize
  553. 0, 0, 0, 0, // elf symbols entry 7 entsize
  554. 17, 0, 0, 0, // elf symbols entry 8 name
  555. 3, 0, 0, 0, // elf symbols entry 8 type
  556. 0, 0, 0, 0, // elf symbols entry 8 flags
  557. 0, 0, 0, 0, // elf symbols entry 8 flags
  558. 113, 147, 17, 0, // elf symbols entry 8 addr
  559. 0, 0, 0, 0, // elf symbols entry 8 addr
  560. 113, 83, 1, 0, // elf symbols entry 8 offset
  561. 0, 0, 0, 0, // elf symbols entry 8 offset
  562. 65, 0, 0, 0, // elf symbols entry 8 size
  563. 0, 0, 0, 0, // elf symbols entry 8 size
  564. 0, 0, 0, 0, // elf symbols entry 8 link
  565. 0, 0, 0, 0, // elf symbols entry 8 info
  566. 1, 0, 0, 0, // elf symbols entry 8 addralign
  567. 0, 0, 0, 0, // elf symbols entry 8 addralign
  568. 0, 0, 0, 0, // elf symbols entry 8 entsize
  569. 0, 0, 0, 0, // elf symbols entry 8 entsize
  570. 0, 0, 0, 0, // elf symbols padding
  571. 4, 0, 0, 0, // basic memory tag type
  572. 16, 0, 0, 0, // basic memory tag size
  573. 127, 2, 0, 0, // basic memory mem_lower
  574. 128, 251, 1, 0, // basic memory mem_upper
  575. 5, 0, 0, 0, // BIOS boot device tag type
  576. 20, 0, 0, 0, // BIOS boot device tag size
  577. 224, 0, 0, 0, // BIOS boot device biosdev
  578. 255, 255, 255, 255, // BIOS boot device partition
  579. 255, 255, 255, 255, // BIOS boot device subpartition
  580. 0, 0, 0, 0, // BIOS boot device padding
  581. 8, 0, 0, 0, // framebuffer info tag type
  582. 32, 0, 0, 0, // framebuffer info tag size
  583. 0, 128, 11, 0, // framebuffer info framebuffer_addr
  584. 0, 0, 0, 0, // framebuffer info framebuffer_addr
  585. 160, 0, 0, 0, // framebuffer info framebuffer_pitch
  586. 80, 0, 0, 0, // framebuffer info framebuffer_width
  587. 25, 0, 0, 0, // framebuffer info framebuffer_height
  588. 16, 2, 0, 0, // framebuffer info framebuffer_[bpp,type], reserved, color_info
  589. 14, 0, 0, 0, // ACPI old tag type
  590. 28, 0, 0, 0, // ACPI old tag size
  591. 82, 83, 68, 32, // ACPI old
  592. 80, 84, 82, 32, // ACPI old
  593. 89, 66, 79, 67, // ACPI old
  594. 72, 83, 32, 0, // ACPI old
  595. 220, 24, 254, 7, // ACPI old
  596. 0, 0, 0, 0, // ACPI old padding
  597. 0, 0, 0, 0, // end tag type
  598. 8, 0, 0, 0, // end tag size
  599. ]);
  600. #[repr(C, align(8))]
  601. struct StringBytes([u8; 65]);
  602. let string_bytes: StringBytes = StringBytes([
  603. 0, 46, 115, 121,
  604. 109, 116, 97, 98,
  605. 0, 46, 115, 116,
  606. 114, 116, 97, 98,
  607. 0, 46, 115, 104,
  608. 115, 116, 114, 116,
  609. 97, 98, 0, 46,
  610. 114, 111, 100, 97,
  611. 116, 97, 0, 46,
  612. 116, 101, 120, 116,
  613. 0, 46, 100, 97,
  614. 116, 97, 0, 46,
  615. 98, 115, 115, 0,
  616. 46, 100, 97, 116,
  617. 97, 46, 114, 101,
  618. 108, 46, 114, 111,
  619. 0,
  620. ]);
  621. let string_addr = string_bytes.0.as_ptr() as u64;
  622. for i in 0..8 {
  623. bytes.0[796 + i] = (string_addr >> (i * 8)) as u8;
  624. }
  625. let addr = bytes.0.as_ptr() as usize;
  626. test_grub2_boot_info(
  627. unsafe { load(addr) },
  628. addr,
  629. string_addr,
  630. &bytes.0,
  631. &string_bytes.0,
  632. );
  633. test_grub2_boot_info(
  634. unsafe { load_with_offset(addr, 0) },
  635. addr,
  636. string_addr,
  637. &bytes.0,
  638. &string_bytes.0,
  639. );
  640. let offset = 8usize;
  641. for i in 0..8 {
  642. bytes.0[796 + i] = ((string_addr - offset as u64) >> (i * 8)) as u8;
  643. }
  644. test_grub2_boot_info(
  645. unsafe { load_with_offset(addr - offset, offset) },
  646. addr,
  647. string_addr - offset as u64,
  648. &bytes.0,
  649. &string_bytes.0,
  650. );
  651. }
  652. fn test_grub2_boot_info(
  653. bi: BootInformation,
  654. addr: usize,
  655. string_addr: u64,
  656. bytes: &[u8],
  657. string_bytes: &[u8],
  658. ) {
  659. assert_eq!(addr, bi.start_address());
  660. assert_eq!(addr + bytes.len(), bi.end_address());
  661. assert_eq!(bytes.len(), bi.total_size());
  662. let es = bi.elf_sections_tag().unwrap();
  663. let mut s = es.sections();
  664. let s1 = s.next().unwrap();
  665. assert_eq!(".rodata", s1.name());
  666. assert_eq!(0xFFFF_8000_0010_0000, s1.start_address());
  667. assert_eq!(0xFFFF_8000_0010_3000, s1.end_address());
  668. assert_eq!(0x0000_0000_0000_3000, s1.size());
  669. assert_eq!(ElfSectionFlags::ALLOCATED, s1.flags());
  670. assert_eq!(ElfSectionType::ProgramSection, s1.section_type());
  671. let s2 = s.next().unwrap();
  672. assert_eq!(".text", s2.name());
  673. assert_eq!(0xFFFF_8000_0010_3000, s2.start_address());
  674. assert_eq!(0xFFFF_8000_0010_C000, s2.end_address());
  675. assert_eq!(0x0000_0000_0000_9000, s2.size());
  676. assert_eq!(ElfSectionFlags::EXECUTABLE | ElfSectionFlags::ALLOCATED, s2.flags());
  677. assert_eq!(ElfSectionType::ProgramSection, s2.section_type());
  678. let s3 = s.next().unwrap();
  679. assert_eq!(".data", s3.name());
  680. assert_eq!(0xFFFF_8000_0010_C000, s3.start_address());
  681. assert_eq!(0xFFFF_8000_0010_E000, s3.end_address());
  682. assert_eq!(0x0000_0000_0000_2000, s3.size());
  683. assert_eq!(ElfSectionFlags::ALLOCATED | ElfSectionFlags::WRITABLE, s3.flags());
  684. assert_eq!(ElfSectionType::ProgramSection, s3.section_type());
  685. let s4 = s.next().unwrap();
  686. assert_eq!(".bss", s4.name());
  687. assert_eq!(0xFFFF_8000_0010_E000, s4.start_address());
  688. assert_eq!(0xFFFF_8000_0011_3000, s4.end_address());
  689. assert_eq!(0x0000_0000_0000_5000, s4.size());
  690. assert_eq!(ElfSectionFlags::ALLOCATED | ElfSectionFlags::WRITABLE, s4.flags());
  691. assert_eq!(ElfSectionType::Uninitialized, s4.section_type());
  692. let s5 = s.next().unwrap();
  693. assert_eq!(".data.rel.ro", s5.name());
  694. assert_eq!(0xFFFF_8000_0011_3000, s5.start_address());
  695. assert_eq!(0xFFFF_8000_0011_3000, s5.end_address());
  696. assert_eq!(0x0000_0000_0000_0000, s5.size());
  697. assert_eq!(ElfSectionFlags::ALLOCATED | ElfSectionFlags::WRITABLE, s5.flags());
  698. assert_eq!(ElfSectionType::ProgramSection, s5.section_type());
  699. let s6 = s.next().unwrap();
  700. assert_eq!(".symtab", s6.name());
  701. assert_eq!(0x0000_0000_0011_3000, s6.start_address());
  702. assert_eq!(0x0000_0000_0011_5BE0, s6.end_address());
  703. assert_eq!(0x0000_0000_0000_2BE0, s6.size());
  704. assert_eq!(ElfSectionFlags::empty(), s6.flags());
  705. assert_eq!(ElfSectionType::LinkerSymbolTable, s6.section_type());
  706. let s7 = s.next().unwrap();
  707. assert_eq!(".strtab", s7.name());
  708. assert_eq!(0x0000_0000_0011_5BE0, s7.start_address());
  709. assert_eq!(0x0000_0000_0011_9371, s7.end_address());
  710. assert_eq!(0x0000_0000_0000_3791, s7.size());
  711. assert_eq!(ElfSectionFlags::empty(), s7.flags());
  712. assert_eq!(ElfSectionType::StringTable, s7.section_type());
  713. let s8 = s.next().unwrap();
  714. assert_eq!(".shstrtab", s8.name());
  715. assert_eq!(string_addr, s8.start_address());
  716. assert_eq!(string_addr + string_bytes.len() as u64, s8.end_address());
  717. assert_eq!(string_bytes.len() as u64, s8.size());
  718. assert_eq!(ElfSectionFlags::empty(), s8.flags());
  719. assert_eq!(ElfSectionType::StringTable, s8.section_type());
  720. assert!(s.next().is_none());
  721. let mut mm = bi.memory_map_tag().unwrap().memory_areas();
  722. let mm1 = mm.next().unwrap();
  723. assert_eq!(0x00000000, mm1.start_address());
  724. assert_eq!(0x009_FC00, mm1.end_address());
  725. assert_eq!(0x009_FC00, mm1.size());
  726. let mm2 = mm.next().unwrap();
  727. assert_eq!(0x010_0000, mm2.start_address());
  728. assert_eq!(0x7FE_0000, mm2.end_address());
  729. assert_eq!(0x7EE_0000, mm2.size());
  730. assert!(mm.next().is_none());
  731. // Test the RSDP tag
  732. let rsdp_old = bi.rsdp_v1_tag().unwrap();
  733. assert_eq!("RSD PTR ", rsdp_old.signature().unwrap());
  734. assert_eq!(89, rsdp_old.checksum());
  735. assert_eq!("BOCHS ", rsdp_old.oem_id().unwrap());
  736. assert_eq!(0, rsdp_old.revision());
  737. assert_eq!(0x7FE18DC, rsdp_old.rsdt_address());
  738. assert!(bi.module_tags().next().is_none());
  739. assert_eq!("GRUB 2.02~beta3-5", bi.boot_loader_name_tag().unwrap().name());
  740. assert_eq!("", bi.command_line_tag().unwrap().command_line());
  741. // Test the Framebuffer tag
  742. let fbi = bi.framebuffer_tag().unwrap();
  743. assert_eq!(fbi.address, 753664);
  744. assert_eq!(fbi.pitch, 160);
  745. assert_eq!(fbi.width, 80);
  746. assert_eq!(fbi.height, 25);
  747. assert_eq!(fbi.bpp, 16);
  748. assert_eq!(fbi.buffer_type, FramebufferType::Text);
  749. }
  750. #[test]
  751. fn elf_sections() {
  752. #[repr(C, align(8))]
  753. struct Bytes([u8; 168]);
  754. let mut bytes: Bytes = Bytes([
  755. 168, 0, 0, 0, // total_size
  756. 0, 0, 0, 0, // reserved
  757. 9, 0, 0, 0, // elf symbols tag type
  758. 20, 2, 0, 0, // elf symbols tag size
  759. 2, 0, 0, 0, // elf symbols num
  760. 64, 0, 0, 0, // elf symbols entsize
  761. 1, 0, 0, 0, // elf symbols shndx
  762. 0, 0, 0, 0, // elf symbols entry 0 name
  763. 0, 0, 0, 0, // elf symbols entry 0 type
  764. 0, 0, 0, 0, // elf symbols entry 0 flags
  765. 0, 0, 0, 0, // elf symbols entry 0 flags
  766. 0, 0, 0, 0, // elf symbols entry 0 addr
  767. 0, 0, 0, 0, // elf symbols entry 0 addr
  768. 0, 0, 0, 0, // elf symbols entry 0 offset
  769. 0, 0, 0, 0, // elf symbols entry 0 offset
  770. 0, 0, 0, 0, // elf symbols entry 0 size
  771. 0, 0, 0, 0, // elf symbols entry 0 size
  772. 0, 0, 0, 0, // elf symbols entry 0 link
  773. 0, 0, 0, 0, // elf symbols entry 0 info
  774. 0, 0, 0, 0, // elf symbols entry 0 addralign
  775. 0, 0, 0, 0, // elf symbols entry 0 addralign
  776. 0, 0, 0, 0, // elf symbols entry 0 entsize
  777. 0, 0, 0, 0, // elf symbols entry 0 entsize
  778. 1, 0, 0, 0, // elf symbols entry 1 name
  779. 3, 0, 0, 0, // elf symbols entry 1 type
  780. 0, 0, 0, 0, // elf symbols entry 1 flags
  781. 0, 0, 0, 0, // elf symbols entry 1 flags
  782. 255, 255, 255, 255, // elf symbols entry 1 addr
  783. 255, 255, 255, 255, // elf symbols entry 1 addr
  784. 113, 83, 1, 0, // elf symbols entry 1 offset
  785. 0, 0, 0, 0, // elf symbols entry 1 offset
  786. 11, 0, 0, 0, // elf symbols entry 1 size
  787. 0, 0, 0, 0, // elf symbols entry 1 size
  788. 0, 0, 0, 0, // elf symbols entry 1 link
  789. 0, 0, 0, 0, // elf symbols entry 1 info
  790. 1, 0, 0, 0, // elf symbols entry 1 addralign
  791. 0, 0, 0, 0, // elf symbols entry 1 addralign
  792. 0, 0, 0, 0, // elf symbols entry 1 entsize
  793. 0, 0, 0, 0, // elf symbols entry 1 entsize
  794. 0, 0, 0, 0, // elf symbols padding
  795. 0, 0, 0, 0, // end tag type
  796. 8, 0, 0, 0, // end tag size
  797. ]);
  798. #[repr(C, align(8))]
  799. struct StringBytes([u8; 11]);
  800. let string_bytes: StringBytes = StringBytes([
  801. 0, 46, 115, 104,
  802. 115, 116, 114, 116,
  803. 97, 98, 0,
  804. ]);
  805. let string_addr = string_bytes.0.as_ptr() as u64;
  806. for i in 0..8 {
  807. let offset = 108;
  808. assert_eq!(255, bytes.0[offset + i]);
  809. bytes.0[offset + i] = (string_addr >> (i * 8)) as u8;
  810. }
  811. let addr = bytes.0.as_ptr() as usize;
  812. let bi = unsafe { load(addr) };
  813. assert_eq!(addr, bi.start_address());
  814. assert_eq!(addr + bytes.0.len(), bi.end_address());
  815. assert_eq!(bytes.0.len(), bi.total_size() as usize);
  816. let es = bi.elf_sections_tag().unwrap();
  817. let mut s = es.sections();
  818. let s1 = s.next().unwrap();
  819. assert_eq!(".shstrtab", s1.name());
  820. assert_eq!(string_addr, s1.start_address());
  821. assert_eq!(string_addr + string_bytes.0.len() as u64, s1.end_address());
  822. assert_eq!(string_bytes.0.len() as u64, s1.size());
  823. assert_eq!(ElfSectionFlags::empty(), s1.flags());
  824. assert_eq!(ElfSectionType::StringTable, s1.section_type());
  825. assert!(s.next().is_none());
  826. }
  827. }