26
26
//!
27
27
//! fn kernel_entry(mb_magic: u32, mbi_ptr: u32) {
28
28
//! if mb_magic == multiboot2::MAGIC {
29
- //! let boot_info = unsafe { BootInformation::load(mbi_ptr as *const BootInformationHeader).unwrap() };
29
+ //! let boot_info = unsafe { BootInformation::load(mbi_ptr as *mut BootInformationHeader).unwrap() };
30
30
//! let _cmd = boot_info.command_line_tag();
31
31
//! } else { /* Panic or use multiboot1 flow. */ }
32
32
//! }
@@ -91,7 +91,9 @@ pub use vbe_info::{
91
91
} ;
92
92
93
93
use core:: fmt;
94
+ use core:: marker:: PhantomData ;
94
95
use core:: mem:: size_of;
96
+ use core:: ptr:: NonNull ;
95
97
use derive_more:: Display ;
96
98
// Must be public so that custom tags can be DSTs.
97
99
#[ cfg( feature = "builder" ) ]
@@ -177,8 +179,16 @@ impl BootInformationInner {
177
179
}
178
180
179
181
/// A Multiboot 2 Boot Information (MBI) accessor.
182
+ ///
183
+ /// This type acts like it owns the memory of the MBI. It allows reading all
184
+ /// kind of tags. Furthermore, it gives you mutable access to a certain degree
185
+ /// to some tags, in case you want to modify them. The latter is most likely
186
+ /// only relevant in niche cases.
180
187
#[ repr( transparent) ]
181
- pub struct BootInformation < ' a > ( & ' a BootInformationInner ) ;
188
+ pub struct BootInformation < ' a > {
189
+ ptr : NonNull < BootInformationInner > ,
190
+ _phantom : PhantomData < & ' a mut BootInformationInner > ,
191
+ }
182
192
183
193
impl < ' a > BootInformation < ' a > {
184
194
/// Loads the [`BootInformation`] from a pointer. The pointer must be valid
@@ -191,7 +201,7 @@ impl<'a> BootInformation<'a> {
191
201
///
192
202
/// fn kernel_entry(mb_magic: u32, mbi_ptr: u32) {
193
203
/// if mb_magic == multiboot2::MAGIC {
194
- /// let boot_info = unsafe { BootInformation::load(mbi_ptr as *const BootInformationHeader).unwrap() };
204
+ /// let boot_info = unsafe { BootInformation::load(mbi_ptr as *mut BootInformationHeader).unwrap() };
195
205
/// let _cmd = boot_info.command_line_tag();
196
206
/// } else { /* Panic or use multiboot1 flow. */ }
197
207
/// }
@@ -204,7 +214,7 @@ impl<'a> BootInformation<'a> {
204
214
/// boot environments, such as UEFI.
205
215
/// * The memory at `ptr` must not be modified after calling `load` or the
206
216
/// program may observe unsynchronized mutation.
207
- pub unsafe fn load ( ptr : * const BootInformationHeader ) -> Result < Self , MbiLoadError > {
217
+ pub unsafe fn load ( ptr : * mut BootInformationHeader ) -> Result < Self , MbiLoadError > {
208
218
// null or not aligned
209
219
if ptr. is_null ( ) || ptr. align_offset ( 8 ) != 0 {
210
220
return Err ( MbiLoadError :: IllegalAddress ) ;
@@ -220,24 +230,36 @@ impl<'a> BootInformation<'a> {
220
230
221
231
let slice_size = mbi. total_size as usize - size_of :: < BootInformationHeader > ( ) ;
222
232
// mbi: reference to full mbi
223
- let mbi = ptr_meta:: from_raw_parts :: < BootInformationInner > ( ptr. cast ( ) , slice_size) ;
224
- let mbi = & * mbi ;
233
+ let mbi_ptr = ptr_meta:: from_raw_parts_mut :: < BootInformationInner > ( ptr. cast ( ) , slice_size) ;
234
+ let mbi_ref = & * mbi_ptr ;
225
235
226
- if !mbi . has_valid_end_tag ( ) {
236
+ if !mbi_ref . has_valid_end_tag ( ) {
227
237
return Err ( MbiLoadError :: NoEndTag ) ;
228
238
}
229
239
230
- Ok ( Self ( mbi) )
240
+ Ok ( Self {
241
+ // Safety: checked earlier that this is not null
242
+ ptr : NonNull :: new_unchecked ( mbi_ptr) ,
243
+ _phantom : PhantomData ,
244
+ } )
231
245
}
232
246
233
- /// Get the start address of the boot info.
234
- pub fn start_address ( & self ) -> usize {
235
- self . as_ptr ( ) as usize
247
+ fn inner ( & self ) -> & BootInformationInner {
248
+ unsafe { self . ptr . as_ref ( ) }
249
+ }
250
+
251
+ fn inner_mut ( & mut self ) -> & mut BootInformationInner {
252
+ unsafe { self . ptr . as_mut ( ) }
236
253
}
237
254
238
255
/// Get the start address of the boot info as pointer.
239
- pub fn as_ptr ( & self ) -> * const ( ) {
240
- core:: ptr:: addr_of!( * self . 0 ) . cast ( )
256
+ pub fn as_ptr ( & self ) -> * const BootInformationHeader {
257
+ self . ptr . as_ptr ( ) . cast ( )
258
+ }
259
+
260
+ /// Get the start address of the boot info.
261
+ pub fn start_address ( & self ) -> usize {
262
+ self . as_ptr ( ) as usize
241
263
}
242
264
243
265
/// Get the end address of the boot info.
@@ -246,7 +268,7 @@ impl<'a> BootInformation<'a> {
246
268
///
247
269
/// ```rust,no_run
248
270
/// # use multiboot2::{BootInformation, BootInformationHeader};
249
- /// # let ptr = 0xdeadbeef as *const BootInformationHeader;
271
+ /// # let ptr = 0xdeadbeef as *mut BootInformationHeader;
250
272
/// # let boot_info = unsafe { BootInformation::load(ptr).unwrap() };
251
273
/// let end_addr = boot_info.start_address() + boot_info.total_size();
252
274
/// ```
@@ -256,7 +278,7 @@ impl<'a> BootInformation<'a> {
256
278
257
279
/// Get the total size of the boot info struct.
258
280
pub fn total_size ( & self ) -> usize {
259
- self . 0 . header . total_size as usize
281
+ self . inner ( ) . header . total_size as usize
260
282
}
261
283
262
284
// ######################################################
@@ -332,7 +354,7 @@ impl<'a> BootInformation<'a> {
332
354
///
333
355
/// ```rust,no_run
334
356
/// # use multiboot2::{BootInformation, BootInformationHeader};
335
- /// # let ptr = 0xdeadbeef as *const BootInformationHeader;
357
+ /// # let ptr = 0xdeadbeef as *mut BootInformationHeader;
336
358
/// # let boot_info = unsafe { BootInformation::load(ptr).unwrap() };
337
359
/// if let Some(sections) = boot_info.elf_sections() {
338
360
/// let mut total = 0;
@@ -448,7 +470,7 @@ impl<'a> BootInformation<'a> {
448
470
/// Tag::get_dst_str_slice(&self.name)
449
471
/// }
450
472
/// }
451
- /// let mbi_ptr = 0xdeadbeef as *const BootInformationHeader;
473
+ /// let mbi_ptr = 0xdeadbeef as *mut BootInformationHeader;
452
474
/// let mbi = unsafe { BootInformation::load(mbi_ptr).unwrap() };
453
475
///
454
476
/// let tag = mbi
@@ -464,7 +486,7 @@ impl<'a> BootInformation<'a> {
464
486
465
487
/// Returns an iterator over all tags.
466
488
fn tags ( & self ) -> TagIter {
467
- TagIter :: new ( & self . 0 . tags )
489
+ TagIter :: new ( & self . inner ( ) . tags )
468
490
}
469
491
}
470
492
@@ -481,8 +503,10 @@ impl fmt::Debug for BootInformation<'_> {
481
503
482
504
let mut debug = f. debug_struct ( "Multiboot2BootInformation" ) ;
483
505
debug
484
- . field ( "start_address" , & self . start_address ( ) )
485
- . field ( "end_address" , & self . end_address ( ) )
506
+ . field ( "start_address" , & self . as_ptr ( ) )
507
+ . field ( "end_address" , unsafe {
508
+ & self . as_ptr ( ) . cast :: < u8 > ( ) . add ( self . total_size ( ) )
509
+ } )
486
510
. field ( "total_size" , & self . total_size ( ) )
487
511
// now tags in alphabetical order
488
512
. field ( "basic_memory_info" , & ( self . basic_memory_info_tag ( ) ) )
@@ -540,7 +564,7 @@ mod tests {
540
564
] ) ;
541
565
let ptr = bytes. 0 . as_ptr ( ) ;
542
566
let addr = ptr as usize ;
543
- let bi = unsafe { BootInformation :: load ( ptr. cast ( ) ) } ;
567
+ let bi = unsafe { BootInformation :: load ( ptr. cast_mut ( ) . cast ( ) ) } ;
544
568
let bi = bi. unwrap ( ) ;
545
569
assert_eq ! ( addr, bi. start_address( ) ) ;
546
570
assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
@@ -565,7 +589,7 @@ mod tests {
565
589
] ) ;
566
590
let ptr = bytes. 0 . as_ptr ( ) ;
567
591
let addr = ptr as usize ;
568
- let bi = unsafe { BootInformation :: load ( ptr. cast ( ) ) } ;
592
+ let bi = unsafe { BootInformation :: load ( ptr. cast_mut ( ) . cast ( ) ) } ;
569
593
let bi = bi. unwrap ( ) ;
570
594
assert_eq ! ( addr, bi. start_address( ) ) ;
571
595
assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
@@ -590,7 +614,7 @@ mod tests {
590
614
] ) ;
591
615
let ptr = bytes. 0 . as_ptr ( ) ;
592
616
let addr = ptr as usize ;
593
- let bi = unsafe { BootInformation :: load ( ptr. cast ( ) ) } ;
617
+ let bi = unsafe { BootInformation :: load ( ptr. cast_mut ( ) . cast ( ) ) } ;
594
618
let bi = bi. unwrap ( ) ;
595
619
assert_eq ! ( addr, bi. start_address( ) ) ;
596
620
assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
@@ -619,7 +643,7 @@ mod tests {
619
643
] ) ;
620
644
let ptr = bytes. 0 . as_ptr ( ) ;
621
645
let addr = ptr as usize ;
622
- let bi = unsafe { BootInformation :: load ( ptr. cast ( ) ) } ;
646
+ let bi = unsafe { BootInformation :: load ( ptr. cast_mut ( ) . cast ( ) ) } ;
623
647
let bi = bi. unwrap ( ) ;
624
648
assert_eq ! ( addr, bi. start_address( ) ) ;
625
649
assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
@@ -663,7 +687,7 @@ mod tests {
663
687
] ) ;
664
688
let ptr = bytes. 0 . as_ptr ( ) ;
665
689
let addr = ptr as usize ;
666
- let bi = unsafe { BootInformation :: load ( ptr. cast ( ) ) } ;
690
+ let bi = unsafe { BootInformation :: load ( ptr. cast_mut ( ) . cast ( ) ) } ;
667
691
let bi = bi. unwrap ( ) ;
668
692
assert_eq ! ( addr, bi. start_address( ) ) ;
669
693
assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
@@ -724,7 +748,7 @@ mod tests {
724
748
] ) ;
725
749
let ptr = bytes. 0 . as_ptr ( ) ;
726
750
let addr = ptr as usize ;
727
- let bi = unsafe { BootInformation :: load ( ptr. cast ( ) ) } ;
751
+ let bi = unsafe { BootInformation :: load ( ptr. cast_mut ( ) . cast ( ) ) } ;
728
752
let bi = bi. unwrap ( ) ;
729
753
assert_eq ! ( addr, bi. start_address( ) ) ;
730
754
assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
@@ -842,7 +866,7 @@ mod tests {
842
866
843
867
let ptr = bytes. 0 . as_ptr ( ) ;
844
868
let addr = ptr as usize ;
845
- let bi = unsafe { BootInformation :: load ( ptr. cast ( ) ) } ;
869
+ let bi = unsafe { BootInformation :: load ( ptr. cast_mut ( ) . cast ( ) ) } ;
846
870
let bi = bi. unwrap ( ) ;
847
871
assert_eq ! ( addr, bi. start_address( ) ) ;
848
872
assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
@@ -1202,7 +1226,7 @@ mod tests {
1202
1226
}
1203
1227
let ptr = bytes. 0 . as_ptr ( ) ;
1204
1228
let addr = ptr as usize ;
1205
- let bi = unsafe { BootInformation :: load ( ptr. cast ( ) ) } ;
1229
+ let bi = unsafe { BootInformation :: load ( ptr. cast_mut ( ) . cast ( ) ) } ;
1206
1230
let bi = bi. unwrap ( ) ;
1207
1231
test_grub2_boot_info ( & bi, addr, string_addr, & bytes. 0 , & string_bytes. 0 ) ;
1208
1232
@@ -1409,7 +1433,7 @@ mod tests {
1409
1433
}
1410
1434
let ptr = bytes. 0 . as_ptr ( ) ;
1411
1435
let addr = ptr as usize ;
1412
- let bi = unsafe { BootInformation :: load ( ptr. cast ( ) ) } ;
1436
+ let bi = unsafe { BootInformation :: load ( ptr. cast_mut ( ) . cast ( ) ) } ;
1413
1437
let bi = bi. unwrap ( ) ;
1414
1438
assert_eq ! ( addr, bi. start_address( ) ) ;
1415
1439
assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
@@ -1453,7 +1477,7 @@ mod tests {
1453
1477
] ) ;
1454
1478
let ptr = bytes. 0 . as_ptr ( ) ;
1455
1479
let addr = ptr as usize ;
1456
- let bi = unsafe { BootInformation :: load ( ptr. cast ( ) ) } ;
1480
+ let bi = unsafe { BootInformation :: load ( ptr. cast_mut ( ) . cast ( ) ) } ;
1457
1481
let bi = bi. unwrap ( ) ;
1458
1482
assert_eq ! ( addr, bi. start_address( ) ) ;
1459
1483
assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
@@ -1489,7 +1513,7 @@ mod tests {
1489
1513
0 , 0 , 0 , 0 , // end tag type.
1490
1514
8 , 0 , 0 , 0 , // end tag size.
1491
1515
] ) ;
1492
- let bi = unsafe { BootInformation :: load ( bytes2. 0 . as_ptr ( ) . cast ( ) ) } ;
1516
+ let bi = unsafe { BootInformation :: load ( bytes2. 0 . as_ptr ( ) . cast_mut ( ) . cast ( ) ) } ;
1493
1517
let bi = bi. unwrap ( ) ;
1494
1518
let efi_mmap = bi. efi_memory_map_tag ( ) ;
1495
1519
assert ! ( efi_mmap. is_none( ) ) ;
@@ -1559,7 +1583,7 @@ mod tests {
1559
1583
] ) ;
1560
1584
let ptr = bytes. 0 . as_ptr ( ) ;
1561
1585
let addr = ptr as usize ;
1562
- let bi = unsafe { BootInformation :: load ( ptr. cast ( ) ) } ;
1586
+ let bi = unsafe { BootInformation :: load ( ptr. cast_mut ( ) . cast ( ) ) } ;
1563
1587
let bi = bi. unwrap ( ) ;
1564
1588
assert_eq ! ( addr, bi. start_address( ) ) ;
1565
1589
assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
@@ -1637,7 +1661,7 @@ mod tests {
1637
1661
] ) ;
1638
1662
let ptr = bytes. 0 . as_ptr ( ) ;
1639
1663
let addr = ptr as usize ;
1640
- let bi = unsafe { BootInformation :: load ( ptr. cast ( ) ) } ;
1664
+ let bi = unsafe { BootInformation :: load ( ptr. cast_mut ( ) . cast ( ) ) } ;
1641
1665
let bi = bi. unwrap ( ) ;
1642
1666
assert_eq ! ( addr, bi. start_address( ) ) ;
1643
1667
assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
@@ -1689,7 +1713,7 @@ mod tests {
1689
1713
] ) ;
1690
1714
1691
1715
let ptr = bytes. 0 . as_ptr ( ) ;
1692
- let bi = unsafe { BootInformation :: load ( ptr. cast ( ) ) } ;
1716
+ let bi = unsafe { BootInformation :: load ( ptr. cast_mut ( ) . cast ( ) ) } ;
1693
1717
let bi = bi. unwrap ( ) ;
1694
1718
1695
1719
let _tag = bi. get_tag :: < CommandLineTag > ( ) . unwrap ( ) ;
0 commit comments