lib.rs 53 KB

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