@@ -55,12 +55,17 @@ pub use memory_map::{
55
55
} ;
56
56
pub use module:: { ModuleIter , ModuleTag } ;
57
57
pub use rsdp:: { RsdpV1Tag , RsdpV2Tag } ;
58
- pub use tag_type:: TagType ;
59
- use tag_type:: { Tag , TagIter } ;
58
+ pub use tag_type:: Tag ;
60
59
pub use vbe_info:: {
61
60
VBECapabilities , VBEControlInfo , VBEDirectColorAttributes , VBEField , VBEInfoTag ,
62
61
VBEMemoryModel , VBEModeAttributes , VBEModeInfo , VBEWindowAttributes ,
63
62
} ;
63
+ pub use {
64
+ tag_type:: SpecifiedOrCustomTagType , tag_type:: SpecifiedOrCustomTagTypeSerialized ,
65
+ tag_type:: TagType ,
66
+ } ;
67
+
68
+ use tag_type:: TagIter ;
64
69
65
70
#[ macro_use]
66
71
extern crate bitflags;
@@ -308,8 +313,41 @@ impl BootInformation {
308
313
unsafe { & * self . inner }
309
314
}
310
315
311
- fn get_tag ( & self , typ : TagType ) -> Option < & Tag > {
312
- self . tags ( ) . find ( |tag| tag. typ == typ)
316
+ /// Public getter to find any tag type you are looking for.
317
+ ///
318
+ /// # Specified or Custom Tags
319
+ /// The Multiboot2 specification specifies a list of tags, see [`TagType`]. However, it doesn't
320
+ /// forbid to use custom tags. Because of this, there exists the [`SpecifiedOrCustomTagType`]
321
+ /// abstraction. **It is recommended** to use this getter only for custom tags. For specified
322
+ /// tags, use getters, such as [`Self::efi_64_ih`].
323
+ ///
324
+ /// ## Use Custom Tags
325
+ /// The following example shows how you may use this interface to parse custom tags from
326
+ /// the MBI.
327
+ ///
328
+ /// ```ignore
329
+ /// use multiboot2::SpecifiedOrCustomTagTypeSerialized;
330
+ /// #[repr(C, align(8))]
331
+ /// struct CustomTag {
332
+ /// // new type from the lib: has repr(u32)
333
+ /// tag: SpecifiedOrCustomTagTypeSerialized,
334
+ /// size: u32,
335
+ /// // begin of inline string
336
+ /// name: u8,
337
+ /// }
338
+ ///
339
+ /// let tag = bi
340
+ /// // this function is now public!
341
+ /// .get_tag(0x1337.into())
342
+ /// .unwrap()
343
+ /// // type definition from end user. must be Sized!
344
+ /// .cast_tag::<CustomTag>();
345
+ /// let name = &tag.name as *const u8 as *const c_char;
346
+ /// let str = unsafe { CStr::from_ptr(name).to_str().unwrap() };
347
+ /// assert_eq!(str, "name");
348
+ /// ```
349
+ pub fn get_tag ( & self , typ : SpecifiedOrCustomTagType ) -> Option < & Tag > {
350
+ self . tags ( ) . find ( |tag : & & Tag | tag. typ == typ)
313
351
}
314
352
315
353
fn tags ( & self ) -> TagIter {
@@ -319,16 +357,16 @@ impl BootInformation {
319
357
320
358
impl BootInformationInner {
321
359
fn has_valid_end_tag ( & self ) -> bool {
322
- const END_TAG : Tag = Tag {
323
- typ : TagType :: End ,
360
+ let end_tag_prototype : Tag = Tag {
361
+ typ : TagType :: End . into ( ) ,
324
362
size : 8 ,
325
363
} ;
326
364
327
365
let self_ptr = self as * const _ ;
328
- let end_tag_addr = self_ptr as usize + ( self . total_size - END_TAG . size ) as usize ;
366
+ let end_tag_addr = self_ptr as usize + ( self . total_size - end_tag_prototype . size ) as usize ;
329
367
let end_tag = unsafe { & * ( end_tag_addr as * const Tag ) } ;
330
368
331
- end_tag. typ == END_TAG . typ && end_tag. size == END_TAG . size
369
+ end_tag. typ == end_tag_prototype . typ && end_tag. size == end_tag_prototype . size
332
370
}
333
371
}
334
372
@@ -437,6 +475,7 @@ impl Reader {
437
475
#[ cfg( test) ]
438
476
mod tests {
439
477
use super :: * ;
478
+ use std:: ffi:: { c_char, CStr } ;
440
479
441
480
#[ test]
442
481
fn no_tags ( ) {
0 commit comments