### Build and Parse Multiboot2 Header at Runtime Source: https://github.com/rust-osdev/multiboot2/blob/main/multiboot2-header/README.md This example demonstrates constructing a Multiboot2 header dynamically at runtime using the `Multiboot2HeaderBuilder` and then parsing the resulting byte array. This is useful for scenarios where the header is received from a file or other dynamic source. ```rust use multiboot2_header::builder::{InformationRequestHeaderTagBuilder, Multiboot2HeaderBuilder}; use multiboot2_header::{HeaderTagFlag, HeaderTagISA, MbiTagType, RelocatableHeaderTag, RelocatableHeaderTagPreference, Multiboot2Header}; /// Small example that creates a Multiboot2 header and parses it afterwards. fn main() { // We create a Multiboot2 header during runtime here. A practical example is that your // program gets the header from a file and parses it afterwards. let mb2_hdr_bytes = Multiboot2HeaderBuilder::new(HeaderTagISA::I386) .relocatable_tag(RelocatableHeaderTag::new( HeaderTagFlag::Required, 0x1337, 0xdeadbeef, 4096, RelocatableHeaderTagPreference::None, )) .information_request_tag( InformationRequestHeaderTagBuilder::new(HeaderTagFlag::Required) .add_irs(&[MbiTagType::Cmdline, MbiTagType::BootLoaderName]), ) .build(); // Cast bytes in vector to Multiboot2 information structure let mb2_hdr = unsafe { Multiboot2Header::from_addr(mb2_hdr_bytes.as_ptr().cast()) }; println!("{:#?}", mb2_hdr); } ``` -------------------------------- ### Setup Display with Framebuffer Information Source: https://context7.com/rust-osdev/multiboot2/llms.txt Retrieves and prints framebuffer details including address, resolution, pitch, bits per pixel, and color mode. Requires a framebuffer tag in the boot information. ```rust use multiboot2::{BootInformation, FramebufferType, FramebufferTag}; fn setup_display(boot_info: &BootInformation) { if let Some(Ok(fb_tag)) = boot_info.framebuffer_tag() { println!("Framebuffer at: 0x{:x}", fb_tag.address()); println!("Resolution: {}x{}", fb_tag.width(), fb_tag.height()); println!("Pitch: {} bytes per line", fb_tag.pitch()); println!("Bits per pixel: {}", fb_tag.bpp()); match fb_tag.buffer_type() { Ok(FramebufferType::RGB { red, green, blue }) => { println!("RGB mode:"); println!(" Red: position {}, size {}", red.position, red.size); println!(" Green: position {}, size {}", green.position, green.size); println!(" Blue: position {}, size {}", blue.position, blue.size); } Ok(FramebufferType::Indexed { palette }) => { println!("Indexed mode with {} colors", palette.len()); } Ok(FramebufferType::Text) => { println!("Text mode framebuffer"); } Err(e) => println!("Unknown framebuffer type: {:?}", e), } } } ``` -------------------------------- ### Include Multiboot2 Header as Static Data Source: https://github.com/rust-osdev/multiboot2/blob/main/multiboot2-header/README.md This example shows how to include a pre-built Multiboot2 header as static data within a Rust file. This requires using `include_bytes!` and potentially a custom linker script to ensure the data is placed correctly in memory. ```rust #[used] #[unsafe(no_mangle)] #[link_section = ".text.multiboot2_header"] static MULTIBOOT2_HDR: [u8; 64] = *include_bytes!("mb2_hdr_dump.bin"); ``` -------------------------------- ### Load Boot Modules Source: https://context7.com/rust-osdev/multiboot2/llms.txt Iterates through boot modules loaded by the bootloader, printing their name, start address, end address, and size. Allows access to module data. ```rust use multiboot2::BootInformation; fn load_modules(boot_info: &BootInformation) { for module in boot_info.module_tags() { let name = module.cmdline().unwrap_or(""); let start = module.start_address(); let end = module.end_address(); let size = end - start; println!("Module '{}' loaded at 0x{:x} - 0x{:x} ({} bytes)", name, start, end, size); // Access module data // let data = unsafe { // core::slice::from_raw_parts(start as *const u8, size as usize) // }; } } ``` -------------------------------- ### Construct Multiboot2 Boot Information Source: https://context7.com/rust-osdev/multiboot2/llms.txt Uses the Builder pattern to programmatically create boot information structures. Useful for testing or custom bootloader development. ```rust use multiboot2::{ Builder, BootInformation, CommandLineTag, BootLoaderNameTag, ModuleTag, MemoryMapTag, MemoryArea, MemoryAreaType, BasicMemoryInfoTag, FramebufferTag, FramebufferType }; fn create_boot_info() { let mbi = Builder::new() // Set command line .cmdline(CommandLineTag::new("console=ttyS0 debug")) // Set bootloader name .bootloader(BootLoaderNameTag::new("My Custom Bootloader v1.0")) // Add loaded modules .add_module(ModuleTag::new(0x100000, 0x200000, "initramfs.cpio")) .add_module(ModuleTag::new(0x200000, 0x210000, "config.bin")) // Set basic memory info .meminfo(BasicMemoryInfoTag::new(639, 130048)) // lower, upper in KB // Add memory map .mmap(MemoryMapTag::new(&[ MemoryArea::new(0x0, 0x9FC00, MemoryAreaType::Available), MemoryArea::new(0x9FC00, 0x400, MemoryAreaType::Reserved), MemoryArea::new(0x100000, 0x7EE0000, MemoryAreaType::Available), MemoryArea::new(0x7FE0000, 0x20000, MemoryAreaType::Reserved), ])) // Set framebuffer info .framebuffer(FramebufferTag::new( 0xFD000000, // address 5120, // pitch 1280, // width 720, // height 32, // bpp FramebufferType::RGB { red: multiboot2::FramebufferField { position: 16, size: 8 }, green: multiboot2::FramebufferField { position: 8, size: 8 }, blue: multiboot2::FramebufferField { position: 0, size: 8 }, } )) .build(); // Parse the constructed boot info let boot_info = unsafe { BootInformation::load(mbi.as_bytes().as_ptr().cast()) }.unwrap(); println!("Created MBI with {} bytes", boot_info.total_size()); } ``` -------------------------------- ### Parse Boot Information from Pointer Source: https://context7.com/rust-osdev/multiboot2/llms.txt Initializes the BootInformation structure from a raw pointer provided by the bootloader. Requires verifying the magic number before loading. ```rust use multiboot2::{BootInformation, BootInformationHeader, MAGIC}; // Entry point called by bootloader (e.g., GRUB) fn kernel_entry(mb_magic: u32, mbi_ptr: u32) { // Verify the magic number matches Multiboot2 specification if mb_magic == MAGIC { // Safety: mbi_ptr must be a valid pointer to Multiboot2 boot info let boot_info = unsafe { BootInformation::load(mbi_ptr as *const BootInformationHeader) }.expect("Failed to parse boot information"); // Access boot information properties println!("MBI start: 0x{:x}", boot_info.start_address()); println!("MBI end: 0x{:x}", boot_info.end_address()); println!("MBI total size: {} bytes", boot_info.total_size()); } } ``` -------------------------------- ### Construct Multiboot2 Header Source: https://context7.com/rust-osdev/multiboot2/llms.txt Uses the Builder pattern to create a new Multiboot2 header with specific requirements like framebuffer, console, and relocation settings. ```rust use multiboot2_header::{ Builder, HeaderTagISA, HeaderTagFlag, InformationRequestHeaderTag, EntryAddressHeaderTag, FramebufferHeaderTag, ConsoleHeaderTag, ConsoleHeaderTagFlags, RelocatableHeaderTag, RelocatableHeaderTagPreference, MbiTagType, Multiboot2Header }; fn create_kernel_header() { let header = Builder::new(HeaderTagISA::I386) // Request specific boot information tags .information_request_tag(InformationRequestHeaderTag::new( HeaderTagFlag::Required, &[ MbiTagType::Cmdline.into(), MbiTagType::BootLoaderName.into(), MbiTagType::Mmap.into(), MbiTagType::Framebuffer.into(), MbiTagType::ElfSections.into(), MbiTagType::AcpiV2.into(), ], )) // Specify kernel entry point .entry_tag(EntryAddressHeaderTag::new( HeaderTagFlag::Required, 0x100000 // Entry address )) // Request framebuffer mode .framebuffer_tag(FramebufferHeaderTag::new( HeaderTagFlag::Optional, 1280, // width 720, // height 32 // bpp )) // Require console support .console_tag(ConsoleHeaderTag::new( HeaderTagFlag::Required, ConsoleHeaderTagFlags::ConsoleRequired )) // Allow relocation .relocatable_tag(RelocatableHeaderTag::new( HeaderTagFlag::Optional, 0x100000, // min address 0xFFFFFFFF, // max address 4096, // alignment RelocatableHeaderTagPreference::None )) .build(); // Verify the header let parsed = unsafe { Multiboot2Header::load(header.as_bytes().as_ptr().cast()) }.unwrap(); assert!(parsed.verify_checksum()); println!("Created valid Multiboot2 header ({} bytes)", parsed.length()); } ``` -------------------------------- ### Find ACPI Tables (RSDP v2 and v1) Source: https://context7.com/rust-osdev/multiboot2/llms.txt Searches for ACPI Root System Description Pointer (RSDP) information, prioritizing ACPI 2.0+ (RSDP v2) and falling back to ACPI 1.0 (RSDP v1). Prints details like signature, OEM ID, revision, and checksum validity. ```rust use multiboot2::BootInformation; fn find_acpi_tables(boot_info: &BootInformation) { // Try ACPI 2.0+ first (RSDP v2) if let Some(rsdp) = boot_info.rsdp_v2_tag() { println!("ACPI 2.0+ RSDP found"); println!(" Signature: {}", rsdp.signature().unwrap_or("")); println!(" OEM ID: {}", rsdp.oem_id().unwrap_or("")); println!(" Revision: {}", rsdp.revision()); println!(" XSDT Address: 0x{:x}", rsdp.xsdt_address()); println!(" Checksum valid: {}", rsdp.checksum_is_valid()); } // Fall back to ACPI 1.0 (RSDP v1) else if let Some(rsdp) = boot_info.rsdp_v1_tag() { println!("ACPI 1.0 RSDP found"); println!(" Signature: {}", rsdp.signature().unwrap_or("")); println!(" OEM ID: {}", rsdp.oem_id().unwrap_or("")); println!(" RSDT Address: 0x{:x}", rsdp.rsdt_address()); println!(" Checksum valid: {}", rsdp.checksum_is_valid()); } } ``` -------------------------------- ### Iterate and Print All Multiboot2 Tags Source: https://context7.com/rust-osdev/multiboot2/llms.txt Iterate over all tags in the boot information for discovery or debugging. This function prints the type and size of each tag, and specifically notes custom tags. ```rust use multiboot2::{BootInformation, TagType}; fn dump_all_tags(boot_info: &BootInformation) { println!("Boot Information Tags:"); for tag in boot_info.tags() { let header = tag.header(); let tag_type: TagType = header.typ.into(); println!(" Type: {:?} (0x{:x}), Size: {} bytes", tag_type, header.typ.val(), header.size ); // Count custom tags if matches!(tag_type, TagType::Custom(_)) { println!(" -> Custom tag detected"); } } } ``` -------------------------------- ### Access Command Line Tag Source: https://context7.com/rust-osdev/multiboot2/llms.txt Retrieves and parses kernel command line arguments passed by the bootloader. Handles potential errors during string conversion. ```rust use multiboot2::{BootInformation, BootInformationHeader}; fn get_kernel_cmdline(boot_info: &BootInformation) { if let Some(cmdline_tag) = boot_info.command_line_tag() { match cmdline_tag.cmdline() { Ok(cmdline) => { println!("Kernel command line: {}", cmdline); // Parse arguments, e.g., "console=ttyS0 debug" for arg in cmdline.split_whitespace() { if arg.starts_with("console=") { let console = &arg[8..]; println!("Console device: {}", console); } } } Err(e) => println!("Invalid command line: {:?}", e), } } } ``` -------------------------------- ### Cargo.toml Dependencies for multiboot2-header Source: https://github.com/rust-osdev/multiboot2/blob/main/multiboot2-header/README.md Specify the multiboot2-header dependency in your Cargo.toml file. Use `default-features = false` to exclude the `builder` feature and `alloc`-crate dependency for no_std environments without allocation. ```toml # without `builder`-feature (and without `alloc`-crate) multiboot2-header = { version = "", default-features = false } # else (requires `alloc`-crate) multiboot2-header = "" ``` -------------------------------- ### Define and Parse Custom Tags Source: https://context7.com/rust-osdev/multiboot2/llms.txt Implements custom Multiboot2 tags by defining a struct and implementing the MaybeDynSized and Tag traits. This allows for extending boot information with application-specific data. ```rust use multiboot2::{ BootInformation, BootInformationHeader, TagHeader, TagType, parse_slice_as_string, StringError }; use multiboot2_common::{MaybeDynSized, Tag}; use core::mem; // Define a custom tag with dynamic content #[repr(C)] #[derive(ptr_meta::Pointee)] struct MyCustomTag { header: TagHeader, version: u32, name: [u8], // DST field must be last } impl MyCustomTag { fn version(&self) -> u32 { self.version } fn name(&self) -> Result<&str, StringError> { parse_slice_as_string(&self.name) } } impl MaybeDynSized for MyCustomTag { type Header = TagHeader; const BASE_SIZE: usize = mem::size_of::() + mem::size_of::(); fn dst_len(header: &TagHeader) -> usize { assert!(header.size as usize >= Self::BASE_SIZE); header.size as usize - Self::BASE_SIZE } } impl Tag for MyCustomTag { type IDType = TagType; const ID: TagType = TagType::Custom(0x1337); } fn use_custom_tag(boot_info: &BootInformation) { if let Some(custom) = boot_info.get_tag::() { println!("Custom tag version: {}", custom.version()); println!("Custom tag name: {:?}", custom.name()); } } ``` -------------------------------- ### Print ELF Sections Source: https://context7.com/rust-osdev/multiboot2/llms.txt Iterates through ELF sections and prints details like name, address, size, and flags. Useful for debugging and symbol resolution. ```rust use multiboot2::{BootInformation, ElfSectionFlags, ElfSectionType}; fn print_elf_sections(boot_info: &BootInformation) { if let Some(elf_tag) = boot_info.elf_sections_tag() { println!("ELF Sections (shndx: {})", elf_tag.shndx()); for section in elf_tag.sections() { let name = section.name().unwrap_or(""); let flags = section.flags(); // Filter for important sections if section.section_type() != ElfSectionType::Null { println!(" {} at 0x{:x} - 0x{:x} (size: {})", name, section.start_address(), section.end_address(), section.size() ); // Check section properties if flags.contains(ElfSectionFlags::EXECUTABLE) { println!(" -> Executable code section"); } if flags.contains(ElfSectionFlags::WRITABLE) { println!(" -> Writable data section"); } } } } } ``` -------------------------------- ### Enumerate EFI Memory Map and System Tables Source: https://context7.com/rust-osdev/multiboot2/llms.txt Accesses the EFI memory map and system table pointers from the BootInformation structure. Returns None if EFI boot services are still active. ```rust use multiboot2::{BootInformation, EFIMemoryAreaType}; fn enumerate_efi_memory(boot_info: &BootInformation) { // Note: Returns None if EFI boot services are still active if let Some(efi_mmap) = boot_info.efi_memory_map_tag() { println!("EFI Memory Map:"); for desc in efi_mmap.memory_areas() { let type_name = match desc.ty { EFIMemoryAreaType::CONVENTIONAL => "Conventional", EFIMemoryAreaType::LOADER_DATA => "Loader Data", EFIMemoryAreaType::BOOT_SERVICES_CODE => "Boot Services Code", EFIMemoryAreaType::BOOT_SERVICES_DATA => "Boot Services Data", EFIMemoryAreaType::RUNTIME_SERVICES_CODE => "Runtime Services Code", EFIMemoryAreaType::RUNTIME_SERVICES_DATA => "Runtime Services Data", EFIMemoryAreaType::ACPI_RECLAIM => "ACPI Reclaim", _ => "Other", }; println!(" 0x{:012x} - {} pages - {}", desc.phys_start, desc.page_count, type_name ); } } // Check for EFI system table pointers if let Some(efi64) = boot_info.efi_sdt64_tag() { println!("EFI 64-bit System Table at: 0x{:x}", efi64.sdt_address()); } if let Some(efi32) = boot_info.efi_sdt32_tag() { println!("EFI 32-bit System Table at: 0x{:x}", efi32.sdt_address()); } } ``` -------------------------------- ### Read Memory Map Source: https://context7.com/rust-osdev/multiboot2/llms.txt Enumerates system memory areas to identify available RAM. Useful for initializing kernel memory management systems. ```rust use multiboot2::{BootInformation, MemoryAreaType}; fn enumerate_memory(boot_info: &BootInformation) { if let Some(mmap_tag) = boot_info.memory_map_tag() { println!("Memory map (entry size: {}, version: {})", mmap_tag.entry_size(), mmap_tag.entry_version()); let mut total_available = 0u64; for area in mmap_tag.memory_areas() { let area_type = MemoryAreaType::from(area.typ()); println!(" 0x{:08x} - 0x{:08x} ({} bytes) - {:?}", area.start_address(), area.end_address(), area.size(), area_type ); if area_type == MemoryAreaType::Available { total_available += area.size(); } } println!("Total available memory: {} MB", total_available / 1024 / 1024); } } ``` -------------------------------- ### Parse Multiboot2 Header Source: https://context7.com/rust-osdev/multiboot2/llms.txt Locates and validates a Multiboot2 header within a kernel binary slice. Requires the header to be properly aligned and present in the provided byte slice. ```rust use multiboot2_header::{Multiboot2Header, Multiboot2BasicHeader, MAGIC, HeaderTagISA}; fn parse_kernel_header(kernel_bytes: &[u8]) { // Find and parse the Multiboot2 header in kernel binary match Multiboot2Header::find_header(kernel_bytes) { Ok(Some((header_bytes, offset))) => { println!("Found Multiboot2 header at offset {}", offset); let header = unsafe { Multiboot2Header::load(header_bytes.as_ptr().cast()) }.expect("Invalid header"); println!("Header magic: 0x{:x}", header.header_magic()); println!("Architecture: {:?}", header.arch()); println!("Header length: {} bytes", header.length()); println!("Checksum valid: {}", header.verify_checksum()); // Check for specific header tags if let Some(entry) = header.entry_address_tag() { println!("Entry point: 0x{:x}", entry.entry_addr()); } if let Some(fb) = header.framebuffer_tag() { println!("Requested framebuffer: {}x{} @ {} bpp", fb.width(), fb.height(), fb.depth()); } if let Some(info_req) = header.information_request_tag() { println!("Requested info tags: {:?}", info_req.requests()); } } Ok(None) => println!("No Multiboot2 header found"), Err(e) => println!("Error finding header: {:?}", e), } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.