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
@@ -477,8 +499,10 @@ impl fmt::Debug for BootInformation<'_> {
477
499
478
500
let mut debug = f. debug_struct ( "Multiboot2BootInformation" ) ;
479
501
debug
480
- . field ( "start_address" , & self . start_address ( ) )
481
- . field ( "end_address" , & self . end_address ( ) )
502
+ . field ( "start_address" , & self . as_ptr ( ) )
503
+ . field ( "end_address" , unsafe {
504
+ & self . as_ptr ( ) . cast :: < u8 > ( ) . add ( self . total_size ( ) )
505
+ } )
482
506
. field ( "total_size" , & self . total_size ( ) )
483
507
// now tags in alphabetical order
484
508
. field ( "basic_memory_info" , & ( self . basic_memory_info_tag ( ) ) )
@@ -560,7 +584,7 @@ mod tests {
560
584
] ) ;
561
585
let ptr = bytes. 0 . as_ptr ( ) ;
562
586
let addr = ptr as usize ;
563
- let bi = unsafe { BootInformation :: load ( ptr. cast ( ) ) } ;
587
+ let bi = unsafe { BootInformation :: load ( ptr. cast_mut ( ) . cast ( ) ) } ;
564
588
let bi = bi. unwrap ( ) ;
565
589
assert_eq ! ( addr, bi. start_address( ) ) ;
566
590
assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
@@ -585,7 +609,7 @@ mod tests {
585
609
] ) ;
586
610
let ptr = bytes. 0 . as_ptr ( ) ;
587
611
let addr = ptr as usize ;
588
- let bi = unsafe { BootInformation :: load ( ptr. cast ( ) ) } ;
612
+ let bi = unsafe { BootInformation :: load ( ptr. cast_mut ( ) . cast ( ) ) } ;
589
613
let bi = bi. unwrap ( ) ;
590
614
assert_eq ! ( addr, bi. start_address( ) ) ;
591
615
assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
@@ -610,7 +634,7 @@ mod tests {
610
634
] ) ;
611
635
let ptr = bytes. 0 . as_ptr ( ) ;
612
636
let addr = ptr as usize ;
613
- let bi = unsafe { BootInformation :: load ( ptr. cast ( ) ) } ;
637
+ let bi = unsafe { BootInformation :: load ( ptr. cast_mut ( ) . cast ( ) ) } ;
614
638
let bi = bi. unwrap ( ) ;
615
639
assert_eq ! ( addr, bi. start_address( ) ) ;
616
640
assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
@@ -639,7 +663,7 @@ mod tests {
639
663
] ) ;
640
664
let ptr = bytes. 0 . as_ptr ( ) ;
641
665
let addr = ptr as usize ;
642
- let bi = unsafe { BootInformation :: load ( ptr. cast ( ) ) } ;
666
+ let bi = unsafe { BootInformation :: load ( ptr. cast_mut ( ) . cast ( ) ) } ;
643
667
let bi = bi. unwrap ( ) ;
644
668
assert_eq ! ( addr, bi. start_address( ) ) ;
645
669
assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
@@ -683,7 +707,7 @@ mod tests {
683
707
] ) ;
684
708
let ptr = bytes. 0 . as_ptr ( ) ;
685
709
let addr = ptr as usize ;
686
- let bi = unsafe { BootInformation :: load ( ptr. cast ( ) ) } ;
710
+ let bi = unsafe { BootInformation :: load ( ptr. cast_mut ( ) . cast ( ) ) } ;
687
711
let bi = bi. unwrap ( ) ;
688
712
assert_eq ! ( addr, bi. start_address( ) ) ;
689
713
assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
@@ -744,7 +768,7 @@ mod tests {
744
768
] ) ;
745
769
let ptr = bytes. 0 . as_ptr ( ) ;
746
770
let addr = ptr as usize ;
747
- let bi = unsafe { BootInformation :: load ( ptr. cast ( ) ) } ;
771
+ let bi = unsafe { BootInformation :: load ( ptr. cast_mut ( ) . cast ( ) ) } ;
748
772
let bi = bi. unwrap ( ) ;
749
773
assert_eq ! ( addr, bi. start_address( ) ) ;
750
774
assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
@@ -862,7 +886,7 @@ mod tests {
862
886
863
887
let ptr = bytes. 0 . as_ptr ( ) ;
864
888
let addr = ptr as usize ;
865
- let bi = unsafe { BootInformation :: load ( ptr. cast ( ) ) } ;
889
+ let bi = unsafe { BootInformation :: load ( ptr. cast_mut ( ) . cast ( ) ) } ;
866
890
let bi = bi. unwrap ( ) ;
867
891
assert_eq ! ( addr, bi. start_address( ) ) ;
868
892
assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
@@ -1222,7 +1246,7 @@ mod tests {
1222
1246
}
1223
1247
let ptr = bytes. 0 . as_ptr ( ) ;
1224
1248
let addr = ptr as usize ;
1225
- let bi = unsafe { BootInformation :: load ( ptr. cast ( ) ) } ;
1249
+ let bi = unsafe { BootInformation :: load ( ptr. cast_mut ( ) . cast ( ) ) } ;
1226
1250
let bi = bi. unwrap ( ) ;
1227
1251
test_grub2_boot_info ( & bi, addr, string_addr, & bytes. 0 , & string_bytes. 0 ) ;
1228
1252
@@ -1429,7 +1453,7 @@ mod tests {
1429
1453
}
1430
1454
let ptr = bytes. 0 . as_ptr ( ) ;
1431
1455
let addr = ptr as usize ;
1432
- let bi = unsafe { BootInformation :: load ( ptr. cast ( ) ) } ;
1456
+ let bi = unsafe { BootInformation :: load ( ptr. cast_mut ( ) . cast ( ) ) } ;
1433
1457
let bi = bi. unwrap ( ) ;
1434
1458
assert_eq ! ( addr, bi. start_address( ) ) ;
1435
1459
assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
@@ -1473,7 +1497,7 @@ mod tests {
1473
1497
] ) ;
1474
1498
let ptr = bytes. 0 . as_ptr ( ) ;
1475
1499
let addr = ptr as usize ;
1476
- let bi = unsafe { BootInformation :: load ( ptr. cast ( ) ) } ;
1500
+ let bi = unsafe { BootInformation :: load ( ptr. cast_mut ( ) . cast ( ) ) } ;
1477
1501
let bi = bi. unwrap ( ) ;
1478
1502
assert_eq ! ( addr, bi. start_address( ) ) ;
1479
1503
assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
@@ -1509,7 +1533,7 @@ mod tests {
1509
1533
0 , 0 , 0 , 0 , // end tag type.
1510
1534
8 , 0 , 0 , 0 , // end tag size.
1511
1535
] ) ;
1512
- let bi = unsafe { BootInformation :: load ( bytes2. 0 . as_ptr ( ) . cast ( ) ) } ;
1536
+ let bi = unsafe { BootInformation :: load ( bytes2. 0 . as_ptr ( ) . cast_mut ( ) . cast ( ) ) } ;
1513
1537
let bi = bi. unwrap ( ) ;
1514
1538
let efi_mmap = bi. efi_memory_map_tag ( ) ;
1515
1539
assert ! ( efi_mmap. is_none( ) ) ;
@@ -1579,7 +1603,7 @@ mod tests {
1579
1603
] ) ;
1580
1604
let ptr = bytes. 0 . as_ptr ( ) ;
1581
1605
let addr = ptr as usize ;
1582
- let bi = unsafe { BootInformation :: load ( ptr. cast ( ) ) } ;
1606
+ let bi = unsafe { BootInformation :: load ( ptr. cast_mut ( ) . cast ( ) ) } ;
1583
1607
let bi = bi. unwrap ( ) ;
1584
1608
assert_eq ! ( addr, bi. start_address( ) ) ;
1585
1609
assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
@@ -1657,7 +1681,7 @@ mod tests {
1657
1681
] ) ;
1658
1682
let ptr = bytes. 0 . as_ptr ( ) ;
1659
1683
let addr = ptr as usize ;
1660
- let bi = unsafe { BootInformation :: load ( ptr. cast ( ) ) } ;
1684
+ let bi = unsafe { BootInformation :: load ( ptr. cast_mut ( ) . cast ( ) ) } ;
1661
1685
let bi = bi. unwrap ( ) ;
1662
1686
assert_eq ! ( addr, bi. start_address( ) ) ;
1663
1687
assert_eq ! ( addr + bytes. 0 . len( ) , bi. end_address( ) ) ;
@@ -1709,7 +1733,7 @@ mod tests {
1709
1733
] ) ;
1710
1734
1711
1735
let ptr = bytes. 0 . as_ptr ( ) ;
1712
- let bi = unsafe { BootInformation :: load ( ptr. cast ( ) ) } ;
1736
+ let bi = unsafe { BootInformation :: load ( ptr. cast_mut ( ) . cast ( ) ) } ;
1713
1737
let bi = bi. unwrap ( ) ;
1714
1738
1715
1739
let _tag = bi. get_tag :: < CommandLineTag > ( ) . unwrap ( ) ;
0 commit comments