relocatable.rs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. use crate::{HeaderTagFlag, HeaderTagHeader, HeaderTagType};
  2. use core::fmt;
  3. use core::fmt::{Debug, Formatter};
  4. use core::mem;
  5. use multiboot2_common::{MaybeDynSized, Tag};
  6. /// It contains load address placement suggestion for boot loader. Boot loader
  7. /// should follow it. ‘0’ means none, ‘1’ means load image at lowest possible address
  8. /// but not lower than min addr and ‘2’ means load image at highest possible
  9. /// address but not higher than max addr.
  10. #[repr(u32)]
  11. #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
  12. pub enum RelocatableHeaderTagPreference {
  13. /// Let boot loader decide.
  14. None = 0,
  15. /// Locate at lower end of possible address space.
  16. Low = 1,
  17. /// Locate at higher end of possible address space.
  18. High = 2,
  19. }
  20. /// This tag indicates that the image is relocatable.
  21. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
  22. #[repr(C, align(8))]
  23. pub struct RelocatableHeaderTag {
  24. header: HeaderTagHeader,
  25. /// Lowest possible physical address at which image should be loaded. The bootloader cannot load any part of image below this address
  26. min_addr: u32,
  27. /// Highest possible physical address at which loaded image should end. The bootloader cannot load any part of image above this address.
  28. max_addr: u32,
  29. /// Image alignment in memory, e.g. 4096.
  30. align: u32,
  31. preference: RelocatableHeaderTagPreference,
  32. }
  33. impl RelocatableHeaderTag {
  34. /// Constructs a new tag.
  35. #[must_use]
  36. pub const fn new(
  37. flags: HeaderTagFlag,
  38. min_addr: u32,
  39. max_addr: u32,
  40. align: u32,
  41. preference: RelocatableHeaderTagPreference,
  42. ) -> Self {
  43. let header = HeaderTagHeader::new(
  44. HeaderTagType::Relocatable,
  45. flags,
  46. mem::size_of::<Self>() as u32,
  47. );
  48. Self {
  49. header,
  50. min_addr,
  51. max_addr,
  52. align,
  53. preference,
  54. }
  55. }
  56. /// Returns the [`HeaderTagType`].
  57. #[must_use]
  58. pub const fn typ(&self) -> HeaderTagType {
  59. self.header.typ()
  60. }
  61. /// Returns the [`HeaderTagFlag`]s.
  62. #[must_use]
  63. pub const fn flags(&self) -> HeaderTagFlag {
  64. self.header.flags()
  65. }
  66. /// Returns the size.
  67. #[must_use]
  68. pub const fn size(&self) -> u32 {
  69. self.header.size()
  70. }
  71. /// Return the minimum address.
  72. #[must_use]
  73. pub const fn min_addr(&self) -> u32 {
  74. self.min_addr
  75. }
  76. /// Return the maximum address.
  77. #[must_use]
  78. pub const fn max_addr(&self) -> u32 {
  79. self.max_addr
  80. }
  81. /// Return the alignment.
  82. #[must_use]
  83. pub const fn align(&self) -> u32 {
  84. self.align
  85. }
  86. /// Return the preference.
  87. #[must_use]
  88. pub const fn preference(&self) -> RelocatableHeaderTagPreference {
  89. self.preference
  90. }
  91. }
  92. impl Debug for RelocatableHeaderTag {
  93. fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
  94. f.debug_struct("RelocatableHeaderTag")
  95. .field("type", &self.typ())
  96. .field("flags", &self.flags())
  97. .field("size", &self.size())
  98. // trick to print this as hexadecimal pointer
  99. .field("min_addr", &(self.min_addr as *const u32))
  100. .field("max_addr", &(self.max_addr as *const u32))
  101. .field("align", &{ self.align })
  102. .field("preference", &{ self.preference })
  103. .finish()
  104. }
  105. }
  106. impl MaybeDynSized for RelocatableHeaderTag {
  107. type Header = HeaderTagHeader;
  108. const BASE_SIZE: usize = mem::size_of::<Self>();
  109. fn dst_len(_header: &Self::Header) -> Self::Metadata {}
  110. }
  111. impl Tag for RelocatableHeaderTag {
  112. type IDType = HeaderTagType;
  113. const ID: HeaderTagType = HeaderTagType::Relocatable;
  114. }
  115. #[cfg(test)]
  116. mod tests {
  117. use crate::RelocatableHeaderTag;
  118. #[test]
  119. fn test_assert_size() {
  120. assert_eq!(
  121. core::mem::size_of::<RelocatableHeaderTag>(),
  122. 2 + 2 + 4 + 4 + 4 + 4 + 4
  123. );
  124. }
  125. }