information_request.rs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. use crate::{HeaderTagFlag, HeaderTagHeader};
  2. use crate::{HeaderTagType, MbiTagTypeId};
  3. use core::fmt;
  4. use core::fmt::{Debug, Formatter};
  5. use core::mem;
  6. #[cfg(feature = "builder")]
  7. use multiboot2_common::new_boxed;
  8. use multiboot2_common::{MaybeDynSized, Tag};
  9. #[cfg(feature = "builder")]
  10. use {
  11. alloc::boxed::Box,
  12. core::{ptr, slice},
  13. };
  14. /// Specifies what specific tag types the bootloader should provide
  15. /// inside the mbi.
  16. #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, ptr_meta::Pointee)]
  17. #[repr(C, align(8))]
  18. pub struct InformationRequestHeaderTag {
  19. header: HeaderTagHeader,
  20. requests: [MbiTagTypeId],
  21. }
  22. impl InformationRequestHeaderTag {
  23. /// Creates a new object.
  24. #[cfg(feature = "builder")]
  25. #[must_use]
  26. pub fn new(flags: HeaderTagFlag, requests: &[MbiTagTypeId]) -> Box<Self> {
  27. let header = HeaderTagHeader::new(HeaderTagType::InformationRequest, flags, 0);
  28. let requests = unsafe {
  29. let ptr = ptr::addr_of!(*requests);
  30. slice::from_raw_parts(ptr.cast::<u8>(), mem::size_of_val(requests))
  31. };
  32. new_boxed(header, &[requests])
  33. }
  34. /// Returns the [`HeaderTagType`].
  35. #[must_use]
  36. pub const fn typ(&self) -> HeaderTagType {
  37. self.header.typ()
  38. }
  39. /// Returns the [`HeaderTagFlag`]s.
  40. #[must_use]
  41. pub const fn flags(&self) -> HeaderTagFlag {
  42. self.header.flags()
  43. }
  44. /// Returns the size.
  45. #[must_use]
  46. pub const fn size(&self) -> u32 {
  47. self.header.size()
  48. }
  49. /// Returns the requests as array
  50. #[must_use]
  51. pub const fn requests(&self) -> &[MbiTagTypeId] {
  52. &self.requests
  53. }
  54. }
  55. impl Debug for InformationRequestHeaderTag {
  56. fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
  57. f.debug_struct("InformationRequestHeaderTag")
  58. .field("type", &self.typ())
  59. .field("flags", &self.flags())
  60. .field("size", &self.size())
  61. .field("requests", &self.requests())
  62. .finish()
  63. }
  64. }
  65. impl MaybeDynSized for InformationRequestHeaderTag {
  66. type Header = HeaderTagHeader;
  67. const BASE_SIZE: usize = mem::size_of::<HeaderTagHeader>();
  68. fn dst_len(header: &Self::Header) -> Self::Metadata {
  69. let dst_size = header.size() as usize - Self::BASE_SIZE;
  70. assert_eq!(dst_size % mem::size_of::<MbiTagTypeId>(), 0);
  71. dst_size / mem::size_of::<MbiTagTypeId>()
  72. }
  73. }
  74. impl Tag for InformationRequestHeaderTag {
  75. type IDType = HeaderTagType;
  76. const ID: HeaderTagType = HeaderTagType::InformationRequest;
  77. }
  78. #[cfg(test)]
  79. #[cfg(feature = "builder")]
  80. mod tests {
  81. use super::*;
  82. use crate::MbiTagType;
  83. #[test]
  84. fn creation() {
  85. // Main objective here is to satisfy Miri.
  86. let _ir = InformationRequestHeaderTag::new(
  87. HeaderTagFlag::Optional,
  88. &[
  89. MbiTagType::Cmdline.into(),
  90. MbiTagType::BootLoaderName.into(),
  91. MbiTagType::Module.into(),
  92. MbiTagType::BasicMeminfo.into(),
  93. MbiTagType::Bootdev.into(),
  94. MbiTagType::Mmap.into(),
  95. MbiTagType::Vbe.into(),
  96. MbiTagType::Framebuffer.into(),
  97. MbiTagType::ElfSections.into(),
  98. MbiTagType::Apm.into(),
  99. MbiTagType::Efi32.into(),
  100. MbiTagType::Efi64.into(),
  101. MbiTagType::Smbios.into(),
  102. MbiTagType::AcpiV1.into(),
  103. MbiTagType::AcpiV2.into(),
  104. MbiTagType::Network.into(),
  105. MbiTagType::EfiMmap.into(),
  106. MbiTagType::EfiBs.into(),
  107. MbiTagType::Efi32Ih.into(),
  108. MbiTagType::Efi64Ih.into(),
  109. MbiTagType::LoadBaseAddr.into(),
  110. MbiTagType::Custom(0x1337).into(),
  111. ],
  112. );
  113. }
  114. }