lib.rs 55 KB

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