lib.rs 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174
  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, MemoryAreaType, MemoryAreaIter};
  9. pub use module::{ModuleTag, ModuleIter};
  10. pub use command_line::CommandLineTag;
  11. pub use rsdp::{RsdpV1Tag, RsdpV2Tag};
  12. pub use vbe_info::{VBEInfoTag, VBEControlInfo, VBEModeInfo, VBEField, VBECapabilities,
  13. VBEModeAttributes, VBEWindowAttributes, VBEDirectColorAttributes, VBEMemoryModel};
  14. #[macro_use]
  15. extern crate bitflags;
  16. mod header;
  17. mod boot_loader_name;
  18. mod elf_sections;
  19. mod memory_map;
  20. mod module;
  21. mod command_line;
  22. mod rsdp;
  23. mod framebuffer;
  24. mod vbe_info;
  25. pub unsafe fn load(address: usize) -> BootInformation {
  26. assert_eq!(0, address & 0b111);
  27. let multiboot = &*(address as *const BootInformationInner);
  28. assert_eq!(0, multiboot.total_size & 0b111);
  29. assert!(multiboot.has_valid_end_tag());
  30. BootInformation { inner: multiboot, offset: 0 }
  31. }
  32. pub unsafe fn load_with_offset(address: usize, offset: usize) -> BootInformation {
  33. if !cfg!(test) {
  34. assert_eq!(0, address & 0b111);
  35. assert_eq!(0, offset & 0b111);
  36. }
  37. let multiboot = &*((address + offset) as *const BootInformationInner);
  38. assert_eq!(0, multiboot.total_size & 0b111);
  39. assert!(multiboot.has_valid_end_tag());
  40. BootInformation { inner: multiboot, offset: offset }
  41. }
  42. pub struct BootInformation {
  43. inner: *const BootInformationInner,
  44. offset: usize,
  45. }
  46. #[repr(C, packed)]
  47. struct BootInformationInner {
  48. total_size: u32,
  49. _reserved: u32,
  50. }
  51. impl BootInformation {
  52. pub fn start_address(&self) -> usize {
  53. self.inner as usize
  54. }
  55. pub fn end_address(&self) -> usize {
  56. self.start_address() + self.total_size()
  57. }
  58. pub fn total_size(&self) -> usize {
  59. self.get().total_size as usize
  60. }
  61. pub fn elf_sections_tag(&self) -> Option<ElfSectionsTag> {
  62. self.get_tag(9).map(|tag| unsafe {
  63. elf_sections::elf_sections_tag(tag, self.offset)
  64. })
  65. }
  66. pub fn memory_map_tag<'a>(&'a self) -> Option<&'a MemoryMapTag> {
  67. self.get_tag(6).map(|tag| unsafe { &*(tag as *const Tag as *const MemoryMapTag) })
  68. }
  69. pub fn module_tags(&self) -> ModuleIter {
  70. module::module_iter(self.tags())
  71. }
  72. pub fn boot_loader_name_tag<'a>(&'a self) -> Option<&'a BootLoaderNameTag> {
  73. self.get_tag(2).map(|tag| unsafe { &*(tag as *const Tag as *const BootLoaderNameTag) })
  74. }
  75. pub fn command_line_tag<'a>(&'a self) -> Option<&'a CommandLineTag> {
  76. self.get_tag(1).map(|tag| unsafe { &*(tag as *const Tag as *const CommandLineTag) })
  77. }
  78. pub fn framebuffer_tag<'a>(&'a self) -> Option<FramebufferTag<'a>> {
  79. self.get_tag(8).map(|tag| framebuffer::framebuffer_tag(tag))
  80. }
  81. pub fn rsdp_v1_tag<'a>(&self) -> Option<&'a RsdpV1Tag> {
  82. self.get_tag(14).map(|tag| unsafe { &*(tag as *const Tag as *const RsdpV1Tag) })
  83. }
  84. pub fn rsdp_v2_tag<'a>(&'a self) -> Option<&'a RsdpV2Tag> {
  85. self.get_tag(15).map(|tag| unsafe { &*(tag as *const Tag as *const RsdpV2Tag) })
  86. }
  87. pub fn vbe_info_tag(&self) -> Option<&'static VBEInfoTag> {
  88. self.get_tag(7).map(|tag| unsafe { &*(tag as *const Tag as *const VBEInfoTag) })
  89. }
  90. fn get(&self) -> &BootInformationInner {
  91. unsafe { &*self.inner }
  92. }
  93. fn get_tag<'a>(&'a self, typ: u32) -> Option<&'a Tag> {
  94. self.tags().find(|tag| tag.typ == typ)
  95. }
  96. fn tags(&self) -> TagIter {
  97. TagIter::new(unsafe { self.inner.offset(1) } as *const _)
  98. }
  99. }
  100. impl BootInformationInner {
  101. fn has_valid_end_tag(&self) -> bool {
  102. const END_TAG: Tag = Tag { typ: 0, size: 8 };
  103. let self_ptr = self as *const _;
  104. let end_tag_addr = self_ptr as usize + (self.total_size - END_TAG.size) as usize;
  105. let end_tag = unsafe { &*(end_tag_addr as *const Tag) };
  106. end_tag.typ == END_TAG.typ && end_tag.size == END_TAG.size
  107. }
  108. }
  109. impl fmt::Debug for BootInformation {
  110. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  111. writeln!(f, "multiboot information")?;
  112. writeln!(f, "S: {:#010X}, E: {:#010X}, L: {:#010X}",
  113. self.start_address(), self.end_address(), self.total_size())?;
  114. if let Some(boot_loader_name_tag) = self.boot_loader_name_tag() {
  115. writeln!(f, "boot loader name: {}", boot_loader_name_tag.name())?;
  116. }
  117. if let Some(command_line_tag) = self.command_line_tag() {
  118. writeln!(f, "command line: {}", command_line_tag.command_line())?;
  119. }
  120. if let Some(memory_map_tag) = self.memory_map_tag() {
  121. writeln!(f, "memory areas:")?;
  122. for area in memory_map_tag.memory_areas() {
  123. writeln!(f, " S: {:#010X}, E: {:#010X}, L: {:#010X}",
  124. area.start_address(), area.end_address(), area.size())?;
  125. }
  126. }
  127. if let Some(elf_sections_tag) = self.elf_sections_tag() {
  128. writeln!(f, "kernel sections:")?;
  129. for s in elf_sections_tag.sections() {
  130. writeln!(f, " name: {:15}, S: {:#08X}, E: {:#08X}, L: {:#08X}, F: {:#04X}",
  131. s.name(), s.start_address(),
  132. s.start_address() + s.size(), s.size(), s.flags().bits())?;
  133. }
  134. }
  135. writeln!(f, "module tags:")?;
  136. for mt in self.module_tags() {
  137. writeln!(f, " name: {:15}, S: {:#010X}, E: {:#010X}",
  138. mt.name(), mt.start_address(), mt.end_address())?;
  139. }
  140. Ok(())
  141. }
  142. }
  143. pub(crate) struct Reader {
  144. pub(crate) ptr: *const u8,
  145. pub(crate) off: usize
  146. }
  147. impl Reader {
  148. pub(crate) fn new<T>(ptr: *const T) -> Reader {
  149. Reader {
  150. ptr: ptr as *const u8,
  151. off: 0
  152. }
  153. }
  154. pub(crate) fn read_u8(&mut self) -> u8 {
  155. self.off += 1;
  156. unsafe {
  157. core::ptr::read(self.ptr.offset((self.off - 1) as isize))
  158. }
  159. }
  160. pub(crate) fn read_u16(&mut self) -> u16 {
  161. self.read_u8() as u16 | (self.read_u8() as u16) << 8
  162. }
  163. pub(crate) fn read_u32(&mut self) -> u32 {
  164. self.read_u16() as u32 | (self.read_u16() as u32) << 16
  165. }
  166. pub(crate) fn read_u64(&mut self) -> u64 {
  167. self.read_u32() as u64 | (self.read_u32() as u64) << 32
  168. }
  169. pub(crate) fn skip(&mut self, n: usize) {
  170. self.off += n;
  171. }
  172. pub(crate) fn current_address(&self) -> usize {
  173. unsafe {
  174. self.ptr.offset(self.off as isize) as usize
  175. }
  176. }
  177. }
  178. #[cfg(test)]
  179. mod tests {
  180. use super::{load, load_with_offset};
  181. use super::{BootInformation, ElfSectionFlags, ElfSectionType};
  182. use super::FramebufferType;
  183. #[test]
  184. fn no_tags() {
  185. #[repr(C, align(8))]
  186. struct Bytes([u8; 16]);
  187. let bytes: Bytes = Bytes([
  188. 16, 0, 0, 0, // total_size
  189. 0, 0, 0, 0, // reserved
  190. 0, 0, 0, 0, // end tag type
  191. 8, 0, 0, 0, // end tag size
  192. ]);
  193. let addr = bytes.0.as_ptr() as usize;
  194. let bi = unsafe { load(addr) };
  195. assert_eq!(addr, bi.start_address());
  196. assert_eq!(addr + bytes.0.len(), bi.end_address());
  197. assert_eq!(bytes.0.len(), bi.total_size());
  198. assert!(bi.elf_sections_tag().is_none());
  199. assert!(bi.memory_map_tag().is_none());
  200. assert!(bi.module_tags().next().is_none());
  201. assert!(bi.boot_loader_name_tag().is_none());
  202. assert!(bi.command_line_tag().is_none());
  203. }
  204. #[test]
  205. #[should_panic]
  206. fn invalid_total_size() {
  207. #[repr(C, align(8))]
  208. struct Bytes([u8; 15]);
  209. let bytes: Bytes = Bytes([
  210. 15, 0, 0, 0, // total_size
  211. 0, 0, 0, 0, // reserved
  212. 0, 0, 0, 0, // end tag type
  213. 8, 0, 0, // end tag size
  214. ]);
  215. let addr = bytes.0.as_ptr() as usize;
  216. let bi = unsafe { load(addr) };
  217. assert_eq!(addr, bi.start_address());
  218. assert_eq!(addr + bytes.0.len(), bi.end_address());
  219. assert_eq!(bytes.0.len(), bi.total_size());
  220. assert!(bi.elf_sections_tag().is_none());
  221. assert!(bi.memory_map_tag().is_none());
  222. assert!(bi.module_tags().next().is_none());
  223. assert!(bi.boot_loader_name_tag().is_none());
  224. assert!(bi.command_line_tag().is_none());
  225. }
  226. #[test]
  227. #[should_panic]
  228. fn invalid_end_tag() {
  229. #[repr(C, align(8))]
  230. struct Bytes([u8; 16]);
  231. let bytes: Bytes = Bytes([
  232. 16, 0, 0, 0, // total_size
  233. 0, 0, 0, 0, // reserved
  234. 0, 0, 0, 0, // end tag type
  235. 9, 0, 0, 0, // end tag size
  236. ]);
  237. let addr = bytes.0.as_ptr() as usize;
  238. let bi = unsafe { load(addr) };
  239. assert_eq!(addr, bi.start_address());
  240. assert_eq!(addr + bytes.0.len(), bi.end_address());
  241. assert_eq!(bytes.0.len(), bi.total_size());
  242. assert!(bi.elf_sections_tag().is_none());
  243. assert!(bi.memory_map_tag().is_none());
  244. assert!(bi.module_tags().next().is_none());
  245. assert!(bi.boot_loader_name_tag().is_none());
  246. assert!(bi.command_line_tag().is_none());
  247. }
  248. #[test]
  249. fn name_tag() {
  250. #[repr(C, align(8))]
  251. struct Bytes([u8; 32]);
  252. let bytes: Bytes = Bytes([
  253. 32, 0, 0, 0, // total_size
  254. 0, 0, 0, 0, // reserved
  255. 2, 0, 0, 0, // boot loader name tag type
  256. 13, 0, 0, 0, // boot loader name tag size
  257. 110, 97, 109, 101, // boot loader name 'name'
  258. 0, 0, 0, 0, // boot loader name null + padding
  259. 0, 0, 0, 0, // end tag type
  260. 8, 0, 0, 0, // end tag size
  261. ]);
  262. let addr = bytes.0.as_ptr() as usize;
  263. let bi = unsafe { load(addr) };
  264. assert_eq!(addr, bi.start_address());
  265. assert_eq!(addr + bytes.0.len(), bi.end_address());
  266. assert_eq!(bytes.0.len(), bi.total_size());
  267. assert!(bi.elf_sections_tag().is_none());
  268. assert!(bi.memory_map_tag().is_none());
  269. assert!(bi.module_tags().next().is_none());
  270. assert_eq!("name", bi.boot_loader_name_tag().unwrap().name());
  271. assert!(bi.command_line_tag().is_none());
  272. }
  273. #[test]
  274. fn framebuffer_tag_rgb() {
  275. // direct RGB mode test:
  276. // taken from GRUB2 running in QEMU at
  277. // 1280x720 with 32bpp in BGRA format.
  278. #[repr(C, align(8))]
  279. struct Bytes([u8; 56]);
  280. let bytes: Bytes = Bytes([
  281. 56, 0, 0, 0, // total size
  282. 0, 0, 0, 0, // reserved
  283. 8, 0, 0, 0, // framebuffer tag type
  284. 40, 0, 0, 0, // framebuffer tag size
  285. 0, 0, 0, 253, // framebuffer low dword of address
  286. 0, 0, 0, 0, // framebuffer high dword of address
  287. 0, 20, 0, 0, // framebuffer pitch
  288. 0, 5, 0, 0, // framebuffer width
  289. 208, 2, 0, 0, // framebuffer height
  290. 32, 1, 0, 0, // framebuffer bpp, type, reserved word
  291. 16, 8, 8, 8, // framebuffer red pos/size, green pos/size
  292. 0, 8, 0, 0, // framebuffer blue pos/size, padding word
  293. 0, 0, 0, 0, // end tag type
  294. 8, 0, 0, 0 // end tag size
  295. ]);
  296. let addr = bytes.0.as_ptr() as usize;
  297. let bi = unsafe { load(addr) };
  298. assert_eq!(addr, bi.start_address());
  299. assert_eq!(addr + bytes.0.len(), bi.end_address());
  300. assert_eq!(bytes.0.len(), bi.total_size());
  301. use framebuffer::{FramebufferTag, FramebufferField, FramebufferType};
  302. assert_eq!(bi.framebuffer_tag(), Some(FramebufferTag {
  303. address: 4244635648,
  304. pitch: 5120,
  305. width: 1280,
  306. height: 720,
  307. bpp: 32,
  308. buffer_type: FramebufferType::RGB {
  309. red: FramebufferField {
  310. position: 16, size: 8
  311. },
  312. green: FramebufferField {
  313. position: 8, size: 8
  314. },
  315. blue: FramebufferField {
  316. position: 0, size: 8
  317. }
  318. }
  319. }))
  320. }
  321. #[test]
  322. fn framebuffer_tag_indexed() {
  323. // indexed mode test:
  324. // this is synthetic, as I can't get QEMU
  325. // to run in indexed color mode.
  326. #[repr(C, align(8))]
  327. struct Bytes([u8; 64]);
  328. let bytes: Bytes = Bytes([
  329. 64, 0, 0, 0, // total size
  330. 0, 0, 0, 0, // reserved
  331. 8, 0, 0, 0, // framebuffer tag type
  332. 48, 0, 0, 0, // framebuffer tag size
  333. 0, 0, 0, 253, // framebuffer low dword of address
  334. 0, 0, 0, 0, // framebuffer high dword of address
  335. 0, 20, 0, 0, // framebuffer pitch
  336. 0, 5, 0, 0, // framebuffer width
  337. 208, 2, 0, 0, // framebuffer height
  338. 32, 0, 0, 0, // framebuffer bpp, type, reserved word
  339. 4, 0, 0, 0, // framebuffer palette length
  340. 255, 0, 0, 0, // framebuffer palette
  341. 255, 0, 0, 0,
  342. 255, 0, 0, 0,
  343. 0, 0, 0, 0, // end tag type
  344. 8, 0, 0, 0 // end tag size
  345. ]);
  346. let addr = bytes.0.as_ptr() as usize;
  347. let bi = unsafe { load(addr) };
  348. assert_eq!(addr, bi.start_address());
  349. assert_eq!(addr + bytes.0.len(), bi.end_address());
  350. assert_eq!(bytes.0.len(), bi.total_size());
  351. use framebuffer::{FramebufferType, FramebufferColor};
  352. assert!(bi.framebuffer_tag().is_some());
  353. let fbi = bi.framebuffer_tag().unwrap();
  354. assert_eq!(fbi.address, 4244635648);
  355. assert_eq!(fbi.pitch, 5120);
  356. assert_eq!(fbi.width, 1280);
  357. assert_eq!(fbi.height, 720);
  358. assert_eq!(fbi.bpp, 32);
  359. match fbi.buffer_type {
  360. FramebufferType::Indexed { palette } => assert_eq!(palette, [
  361. FramebufferColor { red: 255, green: 0, blue: 0 },
  362. FramebufferColor { red: 0, green: 255, blue: 0 },
  363. FramebufferColor { red: 0, green: 0, blue: 255 },
  364. FramebufferColor { red: 0, green: 0, blue: 0}
  365. ]),
  366. _ => panic!("Expected indexed framebuffer type.")
  367. }
  368. }
  369. #[test]
  370. fn vbe_info_tag() {
  371. //Taken from GRUB2 running in QEMU.
  372. #[repr(C, align(8))]
  373. struct Bytes([u8; 800]);
  374. let bytes = Bytes([
  375. 32, 3, 0, 0, // Total size.
  376. 0, 0, 0, 0, // Reserved
  377. 7, 0, 0, 0, // Tag type.
  378. 16, 3, 0, 0, // Tag size.
  379. 122, 65, 255, 255, // VBE mode, protected mode interface segment,
  380. 0, 96, 79, 0, // protected mode interface offset, and length.
  381. 86, 69, 83, 65, // "VESA" signature.
  382. 0, 3, 220, 87, // VBE version, lower half of OEM string ptr,
  383. 0, 192, 1, 0, // upper half of OEM string ptr, lower half of capabilities
  384. 0, 0, 34, 128, // upper half of capabilities, lower half of vide mode ptr,
  385. 0, 96, 0, 1, // upper half of video mode ptr, number of 64kb memory blocks
  386. 0, 0, 240, 87, // OEM software revision, lower half of OEM vendor string ptr,
  387. 0, 192, 3, 88, // upper half of OEM vendor string ptr, lower half of OEM product string ptr,
  388. 0, 192, 23, 88, // upper half of OEM product string ptr, lower half of OEM revision string ptr,
  389. 0, 192, 0, 1, // upper half of OEM revision string ptr.
  390. 1, 1, 2, 1, // Reserved data....
  391. 3, 1, 4, 1,
  392. 5, 1, 6, 1,
  393. 7, 1, 13, 1,
  394. 14, 1, 15, 1,
  395. 16, 1, 17, 1,
  396. 18, 1, 19, 1,
  397. 20, 1, 21, 1,
  398. 22, 1, 23, 1,
  399. 24, 1, 25, 1,
  400. 26, 1, 27, 1,
  401. 28, 1, 29, 1,
  402. 30, 1, 31, 1,
  403. 64, 1, 65, 1,
  404. 66, 1, 67, 1,
  405. 68, 1, 69, 1,
  406. 70, 1, 71, 1,
  407. 72, 1, 73, 1,
  408. 74, 1, 75, 1,
  409. 76, 1, 117, 1,
  410. 118, 1, 119, 1,
  411. 120, 1, 121, 1,
  412. 122, 1, 123, 1,
  413. 124, 1, 125, 1,
  414. 126, 1, 127, 1,
  415. 128, 1, 129, 1,
  416. 130, 1, 131, 1,
  417. 132, 1, 133, 1,
  418. 134, 1, 135, 1,
  419. 136, 1, 137, 1,
  420. 138, 1, 139, 1,
  421. 140, 1, 141, 1,
  422. 142, 1, 143, 1,
  423. 144, 1, 145, 1,
  424. 146, 1, 0, 0,
  425. 1, 0, 2, 0,
  426. 3, 0, 4, 0,
  427. 5, 0, 6, 0,
  428. 7, 0, 13, 0,
  429. 14, 0, 15, 0,
  430. 16, 0, 17, 0,
  431. 18, 0, 19, 0,
  432. 106, 0, 255, 255,
  433. 0, 0, 0, 0,
  434. 0, 0, 0, 0,
  435. 0, 0, 0, 0,
  436. 0, 0, 0, 0,
  437. 0, 0, 0, 0,
  438. 0, 0, 0, 0,
  439. 0, 0, 0, 0,
  440. 0, 0, 0, 0,
  441. 0, 0, 0, 0,
  442. 0, 0, 0, 0,
  443. 0, 0, 0, 0,
  444. 0, 0, 0, 0,
  445. 0, 0, 0, 0,
  446. 0, 0, 0, 0,
  447. 0, 0, 0, 0,
  448. 0, 0, 0, 0,
  449. 0, 0, 0, 0,
  450. 0, 0, 0, 0,
  451. 0, 0, 0, 0,
  452. 0, 0, 0, 0,
  453. 0, 0, 0, 0,
  454. 0, 0, 0, 0,
  455. 0, 0, 0, 0,
  456. 0, 0, 0, 0,
  457. 0, 0, 0, 0,
  458. 0, 0, 0, 0,
  459. 0, 0, 0, 0,
  460. 0, 0, 0, 0,
  461. 0, 0, 0, 0,
  462. 0, 0, 0, 0,
  463. 0, 0, 0, 0,
  464. 0, 0, 0, 0,
  465. 0, 0, 0, 0,
  466. 0, 0, 0, 0,
  467. 0, 0, 0, 0,
  468. 0, 0, 0, 0,
  469. 0, 0, 0, 0,
  470. 0, 0, 0, 0,
  471. 0, 0, 0, 0,
  472. 0, 0, 0, 0,
  473. 0, 0, 0, 0,
  474. 0, 0, 0, 0,
  475. 0, 0, 0, 0,
  476. 0, 0, 0, 0,
  477. 0, 0, 0, 0,
  478. 0, 0, 0, 0,
  479. 0, 0, 0, 0,
  480. 0, 0, 0, 0,
  481. 0, 0, 0, 0,
  482. 0, 0, 0, 0,
  483. 0, 0, 0, 0,
  484. 0, 0, 0, 0,
  485. 0, 0, 0, 0,
  486. 0, 0, 0, 0,
  487. 0, 0, 0, 0,
  488. 0, 0, 0, 0,
  489. 0, 0, 0, 0,
  490. 0, 0, 0, 0,
  491. 0, 0, 0, 0,
  492. 0, 0, 0, 0,
  493. 0, 0, 0, 0,
  494. 0, 0, 0, 0,
  495. 0, 0, 0, 0,
  496. 0, 0, 0, 0,
  497. 0, 0, 0, 0,
  498. 0, 0, 0, 0,
  499. 0, 0, 0, 0,
  500. 0, 0, 0, 0,
  501. 0, 0, 0, 0,
  502. 0, 0, 0, 0,
  503. 0, 0, 0, 0,
  504. 0, 0, 0, 0,
  505. 0, 0, 0, 0,
  506. 0, 0, 0, 0,
  507. 0, 0, 0, 0,
  508. 0, 0, 0, 0, // Until Here
  509. 187, 0, 7, 0, // Mode attributes, window A and B attributes
  510. 64, 0, 64, 0, // Window granularity and size.
  511. 0, 160, 0, 0, // Window A and B segments.
  512. 186, 84, 0, 192, // Window relocation function pointer.
  513. 0, 20, 0, 5, // Pitch, X resolution.
  514. 32, 3, 8, 16, // Y resolution, X char size, Y char size.
  515. 1, 32, 1, 6, // Number of planes, BPP, number of banks, memory model.
  516. 0, 3, 1, 8, // Bank size, number of images, reserved, red mask size.
  517. 16, 8, 8, 8, // Red mask position, green mask size, green mask position, blue mask size,
  518. 0, 8, 24, 2, // blue mask position, reserved mask size, reserved mask position, color attributes.
  519. 0, 0, 0, 253, // Frame buffer base address.
  520. 0, 0, 0, 0, // Off screen memory offset.
  521. 0, 0, 0, 20, // Off screen memory size, reserved data...
  522. 0, 0, 8, 16,
  523. 8, 8, 8, 0,
  524. 8, 24, 0, 0,
  525. 0, 0, 0, 0,
  526. 0, 0, 0, 0,
  527. 0, 0, 0, 0,
  528. 0, 0, 0, 0,
  529. 0, 0, 0, 0,
  530. 0, 0, 0, 0,
  531. 0, 0, 0, 0,
  532. 0, 0, 0, 0,
  533. 0, 0, 0, 0,
  534. 0, 0, 0, 0,
  535. 0, 0, 0, 0,
  536. 0, 0, 0, 0,
  537. 0, 0, 0, 0,
  538. 0, 0, 0, 0,
  539. 0, 0, 0, 0,
  540. 0, 0, 0, 0,
  541. 0, 0, 0, 0,
  542. 0, 0, 0, 0,
  543. 0, 0, 0, 0,
  544. 0, 0, 0, 0,
  545. 0, 0, 0, 0,
  546. 0, 0, 0, 0,
  547. 0, 0, 0, 0,
  548. 0, 0, 0, 0,
  549. 0, 0, 0, 0,
  550. 0, 0, 0, 0,
  551. 0, 0, 0, 0,
  552. 0, 0, 0, 0,
  553. 0, 0, 0, 0,
  554. 0, 0, 0, 0,
  555. 0, 0, 0, 0,
  556. 0, 0, 0, 0,
  557. 0, 0, 0, 0,
  558. 0, 0, 0, 0,
  559. 0, 0, 0, 0,
  560. 0, 0, 0, 0,
  561. 0, 0, 0, 0,
  562. 0, 0, 0, 0,
  563. 0, 0, 0, 0,
  564. 0, 0, 0, 0,
  565. 0, 0, 0, 0,
  566. 0, 0, 0, 0,
  567. 0, 0, 0, 0,
  568. 0, 0, 0, 0,
  569. 0, 0, 0, 0,
  570. 0, 0, 0, 0,
  571. 0, 0, 0, 0,
  572. 0, 0, 0, 0, // Until here.
  573. 0, 0, 0, 0, // End tag type.
  574. 8, 0, 0, 0 // End tag size.
  575. ]);
  576. let addr = bytes.0.as_ptr() as usize;
  577. let bi = unsafe { load(addr) };
  578. assert_eq!(addr, bi.start_address());
  579. assert_eq!(addr + bytes.0.len(), bi.end_address());
  580. assert_eq!(bytes.0.len(), bi.total_size());
  581. assert!(bi.vbe_info_tag().is_some());
  582. let vbe = bi.vbe_info_tag().unwrap();
  583. use vbe_info::*;
  584. unsafe {
  585. assert_eq!(vbe.mode, 16762);
  586. assert_eq!(vbe.interface_segment, 65535);
  587. assert_eq!(vbe.interface_offset, 24576);
  588. assert_eq!(vbe.interface_length, 79);
  589. assert_eq!(vbe.control_info.signature, [86, 69, 83, 65]);
  590. assert_eq!(vbe.control_info.version, 768);
  591. assert_eq!(vbe.control_info.oem_string_ptr, 3221247964);
  592. assert_eq!(vbe.control_info.capabilities, VBECapabilities::SWITCHABLE_DAC);
  593. assert_eq!(vbe.control_info.mode_list_ptr, 1610645538);
  594. assert_eq!(vbe.control_info.total_memory, 256);
  595. assert_eq!(vbe.control_info.oem_software_revision, 0);
  596. assert_eq!(vbe.control_info.oem_vendor_name_ptr, 3221247984);
  597. assert_eq!(vbe.control_info.oem_product_name_ptr, 3221248003);
  598. assert_eq!(vbe.control_info.oem_product_revision_ptr, 3221248023);
  599. assert!(vbe.mode_info.mode_attributes.contains(
  600. VBEModeAttributes::SUPPORTED
  601. | VBEModeAttributes::COLOR
  602. | VBEModeAttributes::GRAPHICS
  603. | VBEModeAttributes::NOT_VGA_COMPATIBLE
  604. | VBEModeAttributes::LINEAR_FRAMEBUFFER
  605. ));
  606. assert!(vbe.mode_info.window_a_attributes.contains(
  607. VBEWindowAttributes::RELOCATABLE
  608. | VBEWindowAttributes::READABLE
  609. | VBEWindowAttributes::WRITEABLE
  610. ));
  611. assert_eq!(vbe.mode_info.window_granularity, 64);
  612. assert_eq!(vbe.mode_info.window_size, 64);
  613. assert_eq!(vbe.mode_info.window_a_segment, 40960);
  614. assert_eq!(vbe.mode_info.window_function_ptr, 3221247162);
  615. assert_eq!(vbe.mode_info.pitch, 5120);
  616. assert_eq!(vbe.mode_info.resolution, (1280, 800));
  617. assert_eq!(vbe.mode_info.character_size, (8, 16));
  618. assert_eq!(vbe.mode_info.number_of_planes, 1);
  619. assert_eq!(vbe.mode_info.bpp, 32);
  620. assert_eq!(vbe.mode_info.number_of_banks, 1);
  621. assert_eq!(vbe.mode_info.memory_model, VBEMemoryModel::DirectColor);
  622. assert_eq!(vbe.mode_info.bank_size, 0);
  623. assert_eq!(vbe.mode_info.number_of_image_pages, 3);
  624. assert_eq!(vbe.mode_info.red_field, VBEField {
  625. position: 16, size: 8
  626. });
  627. assert_eq!(vbe.mode_info.green_field, VBEField {
  628. position: 8, size: 8
  629. });
  630. assert_eq!(vbe.mode_info.blue_field, VBEField {
  631. position: 0, size: 8
  632. });
  633. assert_eq!(vbe.mode_info.reserved_field, VBEField {
  634. position: 24, size: 8
  635. });
  636. assert_eq!(vbe.mode_info.direct_color_attributes, VBEDirectColorAttributes::RESERVED_USABLE);
  637. assert_eq!(vbe.mode_info.framebuffer_base_ptr, 4244635648);
  638. assert_eq!(vbe.mode_info.offscreen_memory_offset, 0);
  639. assert_eq!(vbe.mode_info.offscreen_memory_size, 0);
  640. }
  641. }
  642. #[test]
  643. fn grub2() {
  644. #[repr(C, align(8))]
  645. struct Bytes([u8; 960]);
  646. let mut bytes: Bytes = Bytes([
  647. 192, 3, 0, 0, // total_size
  648. 0, 0, 0, 0, // reserved
  649. 1, 0, 0, 0, // boot command tag type
  650. 9, 0, 0, 0, // boot command tag size
  651. 0, 0, 0, 0, // boot command null + padding
  652. 0, 0, 0, 0, // boot command padding
  653. 2, 0, 0, 0, // boot loader name tag type
  654. 26, 0, 0, 0, // boot loader name tag size
  655. 71, 82, 85, 66, // boot loader name
  656. 32, 50, 46, 48, // boot loader name
  657. 50, 126, 98, 101, // boot loader name
  658. 116, 97, 51, 45, // boot loader name
  659. 53, 0, 0, 0, // boot loader name null + padding
  660. 0, 0, 0, 0, // boot loader name padding
  661. 10, 0, 0, 0, // APM tag type
  662. 28, 0, 0, 0, // APM tag size
  663. 2, 1, 0, 240, // APM version, cseg
  664. 207, 212, 0, 0, // APM offset
  665. 0, 240, 0, 240, // APM cseg_16, dseg
  666. 3, 0, 240, 255, // APM flags, cseg_len
  667. 240, 255, 240, 255, // APM cseg_16_len, dseg_len
  668. 0, 0, 0, 0, // APM padding
  669. 6, 0, 0, 0, // memory map tag type
  670. 160, 0, 0, 0, // memory map tag size
  671. 24, 0, 0, 0, // memory map entry_size
  672. 0, 0, 0, 0, // memory map entry_version
  673. 0, 0, 0, 0, // memory map entry 0 base_addr
  674. 0, 0, 0, 0, // memory map entry 0 base_addr
  675. 0, 252, 9, 0, // memory map entry 0 length
  676. 0, 0, 0, 0, // memory map entry 0 length
  677. 1, 0, 0, 0, // memory map entry 0 type
  678. 0, 0, 0, 0, // memory map entry 0 reserved
  679. 0, 252, 9, 0, // memory map entry 1 base_addr
  680. 0, 0, 0, 0, // memory map entry 1 base_addr
  681. 0, 4, 0, 0, // memory map entry 1 length
  682. 0, 0, 0, 0, // memory map entry 1 length
  683. 2, 0, 0, 0, // memory map entry 1 type
  684. 0, 0, 0, 0, // memory map entry 1 reserved
  685. 0, 0, 15, 0, // memory map entry 2 base_addr
  686. 0, 0, 0, 0, // memory map entry 2 base_addr
  687. 0, 0, 1, 0, // memory map entry 2 length
  688. 0, 0, 0, 0, // memory map entry 2 length
  689. 2, 0, 0, 0, // memory map entry 2 type
  690. 0, 0, 0, 0, // memory map entry 2 reserved
  691. 0, 0, 16, 0, // memory map entry 3 base_addr
  692. 0, 0, 0, 0, // memory map entry 3 base_addr
  693. 0, 0, 238, 7, // memory map entry 3 length
  694. 0, 0, 0, 0, // memory map entry 3 length
  695. 1, 0, 0, 0, // memory map entry 3 type
  696. 0, 0, 0, 0, // memory map entry 3 reserved
  697. 0, 0, 254, 7, // memory map entry 4 base_addr
  698. 0, 0, 0, 0, // memory map entry 4 base_addr
  699. 0, 0, 2, 0, // memory map entry 4 length
  700. 0, 0, 0, 0, // memory map entry 4 length
  701. 2, 0, 0, 0, // memory map entry 4 type
  702. 0, 0, 0, 0, // memory map entry 4 reserved
  703. 0, 0, 252, 255, // memory map entry 5 base_addr
  704. 0, 0, 0, 0, // memory map entry 5 base_addr
  705. 0, 0, 4, 0, // memory map entry 5 length
  706. 0, 0, 0, 0, // memory map entry 5 length
  707. 2, 0, 0, 0, // memory map entry 5 type
  708. 0, 0, 0, 0, // memory map entry 5 reserved
  709. 9, 0, 0, 0, // elf symbols tag type
  710. 84, 2, 0, 0, // elf symbols tag size
  711. 9, 0, 0, 0, // elf symbols num
  712. 64, 0, 0, 0, // elf symbols entsize
  713. 8, 0, 0, 0, // elf symbols shndx
  714. 0, 0, 0, 0, // elf symbols entry 0 name
  715. 0, 0, 0, 0, // elf symbols entry 0 type
  716. 0, 0, 0, 0, // elf symbols entry 0 flags
  717. 0, 0, 0, 0, // elf symbols entry 0 flags
  718. 0, 0, 0, 0, // elf symbols entry 0 addr
  719. 0, 0, 0, 0, // elf symbols entry 0 addr
  720. 0, 0, 0, 0, // elf symbols entry 0 offset
  721. 0, 0, 0, 0, // elf symbols entry 0 offset
  722. 0, 0, 0, 0, // elf symbols entry 0 size
  723. 0, 0, 0, 0, // elf symbols entry 0 size
  724. 0, 0, 0, 0, // elf symbols entry 0 link
  725. 0, 0, 0, 0, // elf symbols entry 0 info
  726. 0, 0, 0, 0, // elf symbols entry 0 addralign
  727. 0, 0, 0, 0, // elf symbols entry 0 addralign
  728. 0, 0, 0, 0, // elf symbols entry 0 entsize
  729. 0, 0, 0, 0, // elf symbols entry 0 entsize
  730. 27, 0, 0, 0, // elf symbols entry 1 name
  731. 1, 0, 0, 0, // elf symbols entry 1 type
  732. 2, 0, 0, 0, // elf symbols entry 1 flags
  733. 0, 0, 0, 0, // elf symbols entry 1 flags
  734. 0, 0, 16, 0, // elf symbols entry 1 addr
  735. 0, 128, 255, 255, // elf symbols entry 1 addr
  736. 0, 16, 0, 0, // elf symbols entry 1 offset
  737. 0, 0, 0, 0, // elf symbols entry 1 offset
  738. 0, 48, 0, 0, // elf symbols entry 1 size
  739. 0, 0, 0, 0, // elf symbols entry 1 size
  740. 0, 0, 0, 0, // elf symbols entry 1 link
  741. 0, 0, 0, 0, // elf symbols entry 1 info
  742. 16, 0, 0, 0, // elf symbols entry 1 addralign
  743. 0, 0, 0, 0, // elf symbols entry 1 addralign
  744. 0, 0, 0, 0, // elf symbols entry 1 entsize
  745. 0, 0, 0, 0, // elf symbols entry 1 entsize
  746. 35, 0, 0, 0, // elf symbols entry 2 name
  747. 1, 0, 0, 0, // elf symbols entry 2 type
  748. 6, 0, 0, 0, // elf symbols entry 2 flags
  749. 0, 0, 0, 0, // elf symbols entry 2 flags
  750. 0, 48, 16, 0, // elf symbols entry 2 addr
  751. 0, 128, 255, 255, // elf symbols entry 2 addr
  752. 0, 64, 0, 0, // elf symbols entry 2 offset
  753. 0, 0, 0, 0, // elf symbols entry 2 offset
  754. 0, 144, 0, 0, // elf symbols entry 2 size
  755. 0, 0, 0, 0, // elf symbols entry 2 size
  756. 0, 0, 0, 0, // elf symbols entry 2 link
  757. 0, 0, 0, 0, // elf symbols entry 2 info
  758. 16, 0, 0, 0, // elf symbols entry 2 addralign
  759. 0, 0, 0, 0, // elf symbols entry 2 addralign
  760. 0, 0, 0, 0, // elf symbols entry 2 entsize
  761. 0, 0, 0, 0, // elf symbols entry 2 entsize
  762. 41, 0, 0, 0, // elf symbols entry 3 name
  763. 1, 0, 0, 0, // elf symbols entry 3 type
  764. 3, 0, 0, 0, // elf symbols entry 3 flags
  765. 0, 0, 0, 0, // elf symbols entry 3 flags
  766. 0, 192, 16, 0, // elf symbols entry 3 addr
  767. 0, 128, 255, 255, // elf symbols entry 3 addr
  768. 0, 208, 0, 0, // elf symbols entry 3 offset
  769. 0, 0, 0, 0, // elf symbols entry 3 offset
  770. 0, 32, 0, 0, // elf symbols entry 3 size
  771. 0, 0, 0, 0, // elf symbols entry 3 size
  772. 0, 0, 0, 0, // elf symbols entry 3 link
  773. 0, 0, 0, 0, // elf symbols entry 3 info
  774. 8, 0, 0, 0, // elf symbols entry 3 addralign
  775. 0, 0, 0, 0, // elf symbols entry 3 addralign
  776. 0, 0, 0, 0, // elf symbols entry 3 entsize
  777. 0, 0, 0, 0, // elf symbols entry 3 entsize
  778. 47, 0, 0, 0, // elf symbols entry 4 name
  779. 8, 0, 0, 0, // elf symbols entry 4 type
  780. 3, 0, 0, 0, // elf symbols entry 4 flags
  781. 0, 0, 0, 0, // elf symbols entry 4 flags
  782. 0, 224, 16, 0, // elf symbols entry 4 addr
  783. 0, 128, 255, 255, // elf symbols entry 4 addr
  784. 0, 240, 0, 0, // elf symbols entry 4 offset
  785. 0, 0, 0, 0, // elf symbols entry 4 offset
  786. 0, 80, 0, 0, // elf symbols entry 4 size
  787. 0, 0, 0, 0, // elf symbols entry 4 size
  788. 0, 0, 0, 0, // elf symbols entry 4 link
  789. 0, 0, 0, 0, // elf symbols entry 4 info
  790. 0, 16, 0, 0, // elf symbols entry 4 addralign
  791. 0, 0, 0, 0, // elf symbols entry 4 addralign
  792. 0, 0, 0, 0, // elf symbols entry 4 entsize
  793. 0, 0, 0, 0, // elf symbols entry 4 entsize
  794. 52, 0, 0, 0, // elf symbols entry 5 name
  795. 1, 0, 0, 0, // elf symbols entry 5 type
  796. 3, 0, 0, 0, // elf symbols entry 5 flags
  797. 0, 0, 0, 0, // elf symbols entry 5 flags
  798. 0, 48, 17, 0, // elf symbols entry 5 addr
  799. 0, 128, 255, 255, // elf symbols entry 5 addr
  800. 0, 240, 0, 0, // elf symbols entry 5 offset
  801. 0, 0, 0, 0, // elf symbols entry 5 offset
  802. 0, 0, 0, 0, // elf symbols entry 5 size
  803. 0, 0, 0, 0, // elf symbols entry 5 size
  804. 0, 0, 0, 0, // elf symbols entry 5 link
  805. 0, 0, 0, 0, // elf symbols entry 5 info
  806. 1, 0, 0, 0, // elf symbols entry 5 addralign
  807. 0, 0, 0, 0, // elf symbols entry 5 addralign
  808. 0, 0, 0, 0, // elf symbols entry 5 entsize
  809. 0, 0, 0, 0, // elf symbols entry 5 entsize
  810. 1, 0, 0, 0, // elf symbols entry 6 name
  811. 2, 0, 0, 0, // elf symbols entry 6 type
  812. 0, 0, 0, 0, // elf symbols entry 6 flags
  813. 0, 0, 0, 0, // elf symbols entry 6 flags
  814. 0, 48, 17, 0, // elf symbols entry 6 addr
  815. 0, 0, 0, 0, // elf symbols entry 6 addr
  816. 0, 240, 0, 0, // elf symbols entry 6 offset
  817. 0, 0, 0, 0, // elf symbols entry 6 offset
  818. 224, 43, 0, 0, // elf symbols entry 6 size
  819. 0, 0, 0, 0, // elf symbols entry 6 size
  820. 7, 0, 0, 0, // elf symbols entry 6 link
  821. 102, 1, 0, 0, // elf symbols entry 6 info
  822. 8, 0, 0, 0, // elf symbols entry 6 addralign
  823. 0, 0, 0, 0, // elf symbols entry 6 addralign
  824. 24, 0, 0, 0, // elf symbols entry 6 entsize
  825. 0, 0, 0, 0, // elf symbols entry 6 entsize
  826. 9, 0, 0, 0, // elf symbols entry 7 name
  827. 3, 0, 0, 0, // elf symbols entry 7 type
  828. 0, 0, 0, 0, // elf symbols entry 7 flags
  829. 0, 0, 0, 0, // elf symbols entry 7 flags
  830. 224, 91, 17, 0, // elf symbols entry 7 addr
  831. 0, 0, 0, 0, // elf symbols entry 7 addr
  832. 224, 27, 1, 0, // elf symbols entry 7 offset
  833. 0, 0, 0, 0, // elf symbols entry 7 offset
  834. 145, 55, 0, 0, // elf symbols entry 7 size
  835. 0, 0, 0, 0, // elf symbols entry 7 size
  836. 0, 0, 0, 0, // elf symbols entry 7 link
  837. 0, 0, 0, 0, // elf symbols entry 7 info
  838. 1, 0, 0, 0, // elf symbols entry 7 addralign
  839. 0, 0, 0, 0, // elf symbols entry 7 addralign
  840. 0, 0, 0, 0, // elf symbols entry 7 entsize
  841. 0, 0, 0, 0, // elf symbols entry 7 entsize
  842. 17, 0, 0, 0, // elf symbols entry 8 name
  843. 3, 0, 0, 0, // elf symbols entry 8 type
  844. 0, 0, 0, 0, // elf symbols entry 8 flags
  845. 0, 0, 0, 0, // elf symbols entry 8 flags
  846. 113, 147, 17, 0, // elf symbols entry 8 addr
  847. 0, 0, 0, 0, // elf symbols entry 8 addr
  848. 113, 83, 1, 0, // elf symbols entry 8 offset
  849. 0, 0, 0, 0, // elf symbols entry 8 offset
  850. 65, 0, 0, 0, // elf symbols entry 8 size
  851. 0, 0, 0, 0, // elf symbols entry 8 size
  852. 0, 0, 0, 0, // elf symbols entry 8 link
  853. 0, 0, 0, 0, // elf symbols entry 8 info
  854. 1, 0, 0, 0, // elf symbols entry 8 addralign
  855. 0, 0, 0, 0, // elf symbols entry 8 addralign
  856. 0, 0, 0, 0, // elf symbols entry 8 entsize
  857. 0, 0, 0, 0, // elf symbols entry 8 entsize
  858. 0, 0, 0, 0, // elf symbols padding
  859. 4, 0, 0, 0, // basic memory tag type
  860. 16, 0, 0, 0, // basic memory tag size
  861. 127, 2, 0, 0, // basic memory mem_lower
  862. 128, 251, 1, 0, // basic memory mem_upper
  863. 5, 0, 0, 0, // BIOS boot device tag type
  864. 20, 0, 0, 0, // BIOS boot device tag size
  865. 224, 0, 0, 0, // BIOS boot device biosdev
  866. 255, 255, 255, 255, // BIOS boot device partition
  867. 255, 255, 255, 255, // BIOS boot device subpartition
  868. 0, 0, 0, 0, // BIOS boot device padding
  869. 8, 0, 0, 0, // framebuffer info tag type
  870. 32, 0, 0, 0, // framebuffer info tag size
  871. 0, 128, 11, 0, // framebuffer info framebuffer_addr
  872. 0, 0, 0, 0, // framebuffer info framebuffer_addr
  873. 160, 0, 0, 0, // framebuffer info framebuffer_pitch
  874. 80, 0, 0, 0, // framebuffer info framebuffer_width
  875. 25, 0, 0, 0, // framebuffer info framebuffer_height
  876. 16, 2, 0, 0, // framebuffer info framebuffer_[bpp,type], reserved, color_info
  877. 14, 0, 0, 0, // ACPI old tag type
  878. 28, 0, 0, 0, // ACPI old tag size
  879. 82, 83, 68, 32, // ACPI old
  880. 80, 84, 82, 32, // ACPI old
  881. 89, 66, 79, 67, // ACPI old
  882. 72, 83, 32, 0, // ACPI old
  883. 220, 24, 254, 7, // ACPI old
  884. 0, 0, 0, 0, // ACPI old padding
  885. 0, 0, 0, 0, // end tag type
  886. 8, 0, 0, 0, // end tag size
  887. ]);
  888. #[repr(C, align(8))]
  889. struct StringBytes([u8; 65]);
  890. let string_bytes: StringBytes = StringBytes([
  891. 0, 46, 115, 121,
  892. 109, 116, 97, 98,
  893. 0, 46, 115, 116,
  894. 114, 116, 97, 98,
  895. 0, 46, 115, 104,
  896. 115, 116, 114, 116,
  897. 97, 98, 0, 46,
  898. 114, 111, 100, 97,
  899. 116, 97, 0, 46,
  900. 116, 101, 120, 116,
  901. 0, 46, 100, 97,
  902. 116, 97, 0, 46,
  903. 98, 115, 115, 0,
  904. 46, 100, 97, 116,
  905. 97, 46, 114, 101,
  906. 108, 46, 114, 111,
  907. 0,
  908. ]);
  909. let string_addr = string_bytes.0.as_ptr() as u64;
  910. for i in 0..8 {
  911. bytes.0[796 + i] = (string_addr >> (i * 8)) as u8;
  912. }
  913. let addr = bytes.0.as_ptr() as usize;
  914. test_grub2_boot_info(
  915. unsafe { load(addr) },
  916. addr,
  917. string_addr,
  918. &bytes.0,
  919. &string_bytes.0,
  920. );
  921. test_grub2_boot_info(
  922. unsafe { load_with_offset(addr, 0) },
  923. addr,
  924. string_addr,
  925. &bytes.0,
  926. &string_bytes.0,
  927. );
  928. let offset = 8usize;
  929. for i in 0..8 {
  930. bytes.0[796 + i] = ((string_addr - offset as u64) >> (i * 8)) as u8;
  931. }
  932. test_grub2_boot_info(
  933. unsafe { load_with_offset(addr - offset, offset) },
  934. addr,
  935. string_addr - offset as u64,
  936. &bytes.0,
  937. &string_bytes.0,
  938. );
  939. }
  940. fn test_grub2_boot_info(
  941. bi: BootInformation,
  942. addr: usize,
  943. string_addr: u64,
  944. bytes: &[u8],
  945. string_bytes: &[u8],
  946. ) {
  947. assert_eq!(addr, bi.start_address());
  948. assert_eq!(addr + bytes.len(), bi.end_address());
  949. assert_eq!(bytes.len(), bi.total_size());
  950. let es = bi.elf_sections_tag().unwrap();
  951. let mut s = es.sections();
  952. let s1 = s.next().unwrap();
  953. assert_eq!(".rodata", s1.name());
  954. assert_eq!(0xFFFF_8000_0010_0000, s1.start_address());
  955. assert_eq!(0xFFFF_8000_0010_3000, s1.end_address());
  956. assert_eq!(0x0000_0000_0000_3000, s1.size());
  957. assert_eq!(ElfSectionFlags::ALLOCATED, s1.flags());
  958. assert_eq!(ElfSectionType::ProgramSection, s1.section_type());
  959. let s2 = s.next().unwrap();
  960. assert_eq!(".text", s2.name());
  961. assert_eq!(0xFFFF_8000_0010_3000, s2.start_address());
  962. assert_eq!(0xFFFF_8000_0010_C000, s2.end_address());
  963. assert_eq!(0x0000_0000_0000_9000, s2.size());
  964. assert_eq!(ElfSectionFlags::EXECUTABLE | ElfSectionFlags::ALLOCATED, s2.flags());
  965. assert_eq!(ElfSectionType::ProgramSection, s2.section_type());
  966. let s3 = s.next().unwrap();
  967. assert_eq!(".data", s3.name());
  968. assert_eq!(0xFFFF_8000_0010_C000, s3.start_address());
  969. assert_eq!(0xFFFF_8000_0010_E000, s3.end_address());
  970. assert_eq!(0x0000_0000_0000_2000, s3.size());
  971. assert_eq!(ElfSectionFlags::ALLOCATED | ElfSectionFlags::WRITABLE, s3.flags());
  972. assert_eq!(ElfSectionType::ProgramSection, s3.section_type());
  973. let s4 = s.next().unwrap();
  974. assert_eq!(".bss", s4.name());
  975. assert_eq!(0xFFFF_8000_0010_E000, s4.start_address());
  976. assert_eq!(0xFFFF_8000_0011_3000, s4.end_address());
  977. assert_eq!(0x0000_0000_0000_5000, s4.size());
  978. assert_eq!(ElfSectionFlags::ALLOCATED | ElfSectionFlags::WRITABLE, s4.flags());
  979. assert_eq!(ElfSectionType::Uninitialized, s4.section_type());
  980. let s5 = s.next().unwrap();
  981. assert_eq!(".data.rel.ro", s5.name());
  982. assert_eq!(0xFFFF_8000_0011_3000, s5.start_address());
  983. assert_eq!(0xFFFF_8000_0011_3000, s5.end_address());
  984. assert_eq!(0x0000_0000_0000_0000, s5.size());
  985. assert_eq!(ElfSectionFlags::ALLOCATED | ElfSectionFlags::WRITABLE, s5.flags());
  986. assert_eq!(ElfSectionType::ProgramSection, s5.section_type());
  987. let s6 = s.next().unwrap();
  988. assert_eq!(".symtab", s6.name());
  989. assert_eq!(0x0000_0000_0011_3000, s6.start_address());
  990. assert_eq!(0x0000_0000_0011_5BE0, s6.end_address());
  991. assert_eq!(0x0000_0000_0000_2BE0, s6.size());
  992. assert_eq!(ElfSectionFlags::empty(), s6.flags());
  993. assert_eq!(ElfSectionType::LinkerSymbolTable, s6.section_type());
  994. let s7 = s.next().unwrap();
  995. assert_eq!(".strtab", s7.name());
  996. assert_eq!(0x0000_0000_0011_5BE0, s7.start_address());
  997. assert_eq!(0x0000_0000_0011_9371, s7.end_address());
  998. assert_eq!(0x0000_0000_0000_3791, s7.size());
  999. assert_eq!(ElfSectionFlags::empty(), s7.flags());
  1000. assert_eq!(ElfSectionType::StringTable, s7.section_type());
  1001. let s8 = s.next().unwrap();
  1002. assert_eq!(".shstrtab", s8.name());
  1003. assert_eq!(string_addr, s8.start_address());
  1004. assert_eq!(string_addr + string_bytes.len() as u64, s8.end_address());
  1005. assert_eq!(string_bytes.len() as u64, s8.size());
  1006. assert_eq!(ElfSectionFlags::empty(), s8.flags());
  1007. assert_eq!(ElfSectionType::StringTable, s8.section_type());
  1008. assert!(s.next().is_none());
  1009. let mut mm = bi.memory_map_tag().unwrap().memory_areas();
  1010. let mm1 = mm.next().unwrap();
  1011. assert_eq!(0x00000000, mm1.start_address());
  1012. assert_eq!(0x009_FC00, mm1.end_address());
  1013. assert_eq!(0x009_FC00, mm1.size());
  1014. let mm2 = mm.next().unwrap();
  1015. assert_eq!(0x010_0000, mm2.start_address());
  1016. assert_eq!(0x7FE_0000, mm2.end_address());
  1017. assert_eq!(0x7EE_0000, mm2.size());
  1018. assert!(mm.next().is_none());
  1019. // Test the RSDP tag
  1020. let rsdp_old = bi.rsdp_v1_tag().unwrap();
  1021. assert_eq!("RSD PTR ", rsdp_old.signature().unwrap());
  1022. assert_eq!(89, rsdp_old.checksum());
  1023. assert_eq!("BOCHS ", rsdp_old.oem_id().unwrap());
  1024. assert_eq!(0, rsdp_old.revision());
  1025. assert_eq!(0x7FE18DC, rsdp_old.rsdt_address());
  1026. assert!(bi.module_tags().next().is_none());
  1027. assert_eq!("GRUB 2.02~beta3-5", bi.boot_loader_name_tag().unwrap().name());
  1028. assert_eq!("", bi.command_line_tag().unwrap().command_line());
  1029. // Test the Framebuffer tag
  1030. let fbi = bi.framebuffer_tag().unwrap();
  1031. assert_eq!(fbi.address, 753664);
  1032. assert_eq!(fbi.pitch, 160);
  1033. assert_eq!(fbi.width, 80);
  1034. assert_eq!(fbi.height, 25);
  1035. assert_eq!(fbi.bpp, 16);
  1036. assert_eq!(fbi.buffer_type, FramebufferType::Text);
  1037. }
  1038. #[test]
  1039. fn elf_sections() {
  1040. #[repr(C, align(8))]
  1041. struct Bytes([u8; 168]);
  1042. let mut bytes: Bytes = Bytes([
  1043. 168, 0, 0, 0, // total_size
  1044. 0, 0, 0, 0, // reserved
  1045. 9, 0, 0, 0, // elf symbols tag type
  1046. 20, 2, 0, 0, // elf symbols tag size
  1047. 2, 0, 0, 0, // elf symbols num
  1048. 64, 0, 0, 0, // elf symbols entsize
  1049. 1, 0, 0, 0, // elf symbols shndx
  1050. 0, 0, 0, 0, // elf symbols entry 0 name
  1051. 0, 0, 0, 0, // elf symbols entry 0 type
  1052. 0, 0, 0, 0, // elf symbols entry 0 flags
  1053. 0, 0, 0, 0, // elf symbols entry 0 flags
  1054. 0, 0, 0, 0, // elf symbols entry 0 addr
  1055. 0, 0, 0, 0, // elf symbols entry 0 addr
  1056. 0, 0, 0, 0, // elf symbols entry 0 offset
  1057. 0, 0, 0, 0, // elf symbols entry 0 offset
  1058. 0, 0, 0, 0, // elf symbols entry 0 size
  1059. 0, 0, 0, 0, // elf symbols entry 0 size
  1060. 0, 0, 0, 0, // elf symbols entry 0 link
  1061. 0, 0, 0, 0, // elf symbols entry 0 info
  1062. 0, 0, 0, 0, // elf symbols entry 0 addralign
  1063. 0, 0, 0, 0, // elf symbols entry 0 addralign
  1064. 0, 0, 0, 0, // elf symbols entry 0 entsize
  1065. 0, 0, 0, 0, // elf symbols entry 0 entsize
  1066. 1, 0, 0, 0, // elf symbols entry 1 name
  1067. 3, 0, 0, 0, // elf symbols entry 1 type
  1068. 0, 0, 0, 0, // elf symbols entry 1 flags
  1069. 0, 0, 0, 0, // elf symbols entry 1 flags
  1070. 255, 255, 255, 255, // elf symbols entry 1 addr
  1071. 255, 255, 255, 255, // elf symbols entry 1 addr
  1072. 113, 83, 1, 0, // elf symbols entry 1 offset
  1073. 0, 0, 0, 0, // elf symbols entry 1 offset
  1074. 11, 0, 0, 0, // elf symbols entry 1 size
  1075. 0, 0, 0, 0, // elf symbols entry 1 size
  1076. 0, 0, 0, 0, // elf symbols entry 1 link
  1077. 0, 0, 0, 0, // elf symbols entry 1 info
  1078. 1, 0, 0, 0, // elf symbols entry 1 addralign
  1079. 0, 0, 0, 0, // elf symbols entry 1 addralign
  1080. 0, 0, 0, 0, // elf symbols entry 1 entsize
  1081. 0, 0, 0, 0, // elf symbols entry 1 entsize
  1082. 0, 0, 0, 0, // elf symbols padding
  1083. 0, 0, 0, 0, // end tag type
  1084. 8, 0, 0, 0, // end tag size
  1085. ]);
  1086. #[repr(C, align(8))]
  1087. struct StringBytes([u8; 11]);
  1088. let string_bytes: StringBytes = StringBytes([
  1089. 0, 46, 115, 104,
  1090. 115, 116, 114, 116,
  1091. 97, 98, 0,
  1092. ]);
  1093. let string_addr = string_bytes.0.as_ptr() as u64;
  1094. for i in 0..8 {
  1095. let offset = 108;
  1096. assert_eq!(255, bytes.0[offset + i]);
  1097. bytes.0[offset + i] = (string_addr >> (i * 8)) as u8;
  1098. }
  1099. let addr = bytes.0.as_ptr() as usize;
  1100. let bi = unsafe { load(addr) };
  1101. assert_eq!(addr, bi.start_address());
  1102. assert_eq!(addr + bytes.0.len(), bi.end_address());
  1103. assert_eq!(bytes.0.len(), bi.total_size() as usize);
  1104. let es = bi.elf_sections_tag().unwrap();
  1105. let mut s = es.sections();
  1106. let s1 = s.next().unwrap();
  1107. assert_eq!(".shstrtab", s1.name());
  1108. assert_eq!(string_addr, s1.start_address());
  1109. assert_eq!(string_addr + string_bytes.0.len() as u64, s1.end_address());
  1110. assert_eq!(string_bytes.0.len() as u64, s1.size());
  1111. assert_eq!(ElfSectionFlags::empty(), s1.flags());
  1112. assert_eq!(ElfSectionType::StringTable, s1.section_type());
  1113. assert!(s.next().is_none());
  1114. }
  1115. }