lib.rs 57 KB

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