Skip to content

Commit 856aae8

Browse files
committed
Add support for multiboot information at an offset.
1 parent 7de1603 commit 856aae8

File tree

2 files changed

+66
-12
lines changed

2 files changed

+66
-12
lines changed

src/elf_sections.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ use header::Tag;
33
#[derive(Debug)]
44
pub struct ElfSectionsTag {
55
inner: *const ElfSectionsTagInner,
6+
offset: usize,
67
}
78

8-
pub fn elf_sections_tag(tag: &Tag) -> ElfSectionsTag {
9+
pub unsafe fn elf_sections_tag(tag: &Tag, offset: usize) -> ElfSectionsTag {
910
assert_eq!(9, tag.typ);
1011
let es = ElfSectionsTag {
11-
inner: unsafe { (tag as *const Tag).offset(1) } as *const ElfSectionsTagInner,
12+
inner: (tag as *const Tag).offset(1) as *const ElfSectionsTagInner,
13+
offset: offset,
1214
};
1315
assert!((es.get().entry_size * es.get().shndx) <= tag.size);
1416
es
@@ -33,6 +35,7 @@ impl ElfSectionsTag {
3335
remaining_sections: self.get().number_of_sections,
3436
entry_size: self.get().entry_size,
3537
string_section: string_section_ptr,
38+
offset: self.offset,
3639
}
3740
}
3841

@@ -51,6 +54,7 @@ pub struct ElfSectionIter {
5154
remaining_sections: u32,
5255
entry_size: u32,
5356
string_section: *const u8,
57+
offset: usize,
5458
}
5559

5660
impl Iterator for ElfSectionIter {
@@ -62,6 +66,7 @@ impl Iterator for ElfSectionIter {
6266
inner: self.current_section,
6367
string_section: self.string_section,
6468
entry_size: self.entry_size,
69+
offset: self.offset,
6570
};
6671

6772
self.current_section = unsafe { self.current_section.offset(self.entry_size as isize) };
@@ -80,6 +85,7 @@ pub struct ElfSection {
8085
inner: *const u8,
8186
string_section: *const u8,
8287
entry_size: u32,
88+
offset: usize,
8389
}
8490

8591
#[derive(Debug)]
@@ -187,11 +193,12 @@ impl ElfSection {
187193
}
188194

189195
unsafe fn string_table(&self) -> *const u8 {
190-
match self.entry_size {
191-
40 => (*(self.string_section as *const ElfSectionInner32)).addr as *const _,
192-
64 => (*(self.string_section as *const ElfSectionInner64)).addr as *const _,
196+
let addr = match self.entry_size {
197+
40 => (*(self.string_section as *const ElfSectionInner32)).addr as usize,
198+
64 => (*(self.string_section as *const ElfSectionInner64)).addr as usize,
193199
_ => panic!(),
194-
}
200+
};
201+
(addr + self.offset) as *const _
195202
}
196203
}
197204

src/lib.rs

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,23 @@ pub unsafe fn load(address: usize) -> BootInformation {
3232
let multiboot = &*(address as *const BootInformationInner);
3333
assert_eq!(0, multiboot.total_size & 0b111);
3434
assert!(multiboot.has_valid_end_tag());
35-
BootInformation { inner: multiboot }
35+
BootInformation { inner: multiboot, offset: 0 }
36+
}
37+
38+
pub unsafe fn load_with_offset(address: usize, offset: usize) -> BootInformation {
39+
if !cfg!(test) {
40+
assert_eq!(0, address & 0b111);
41+
assert_eq!(0, offset & 0b111);
42+
}
43+
let multiboot = &*((address + offset) as *const BootInformationInner);
44+
assert_eq!(0, multiboot.total_size & 0b111);
45+
assert!(multiboot.has_valid_end_tag());
46+
BootInformation { inner: multiboot, offset: offset }
3647
}
3748

3849
pub struct BootInformation {
3950
inner: *const BootInformationInner,
51+
offset: usize,
4052
}
4153

4254
#[repr(C, packed)]
@@ -59,7 +71,9 @@ impl BootInformation {
5971
}
6072

6173
pub fn elf_sections_tag(&self) -> Option<ElfSectionsTag> {
62-
self.get_tag(9).map(|tag| elf_sections::elf_sections_tag(tag))
74+
self.get_tag(9).map(|tag| unsafe {
75+
elf_sections::elf_sections_tag(tag, self.offset)
76+
})
6377
}
6478

6579
pub fn memory_map_tag(&self) -> Option<&'static MemoryMapTag> {
@@ -196,8 +210,8 @@ impl Reader {
196210

197211
#[cfg(test)]
198212
mod tests {
199-
use super::load;
200-
use super::{ElfSectionFlags, ElfSectionType};
213+
use super::{load, load_with_offset};
214+
use super::{BootInformation, ElfSectionFlags, ElfSectionType};
201215
use super::FramebufferType;
202216

203217
#[test]
@@ -646,10 +660,43 @@ mod tests {
646660
bytes[796 + i] = (string_addr >> (i * 8)) as u8;
647661
}
648662
let addr = bytes.as_ptr() as usize;
649-
let bi = unsafe { load(addr) };
663+
test_grub2_boot_info(
664+
unsafe { load(addr) },
665+
addr,
666+
string_addr,
667+
&bytes,
668+
&string_bytes,
669+
);
670+
test_grub2_boot_info(
671+
unsafe { load_with_offset(addr, 0) },
672+
addr,
673+
string_addr,
674+
&bytes,
675+
&string_bytes,
676+
);
677+
let offset = 8usize;
678+
for i in 0..8 {
679+
bytes[796 + i] = ((string_addr - offset as u64) >> (i * 8)) as u8;
680+
}
681+
test_grub2_boot_info(
682+
unsafe { load_with_offset(addr - offset, offset) },
683+
addr,
684+
string_addr - offset as u64,
685+
&bytes,
686+
&string_bytes,
687+
);
688+
}
689+
690+
fn test_grub2_boot_info(
691+
bi: BootInformation,
692+
addr: usize,
693+
string_addr: u64,
694+
bytes: &[u8],
695+
string_bytes: &[u8],
696+
) {
650697
assert_eq!(addr, bi.start_address());
651698
assert_eq!(addr + bytes.len(), bi.end_address());
652-
assert_eq!(bytes.len(), bi.total_size() as usize);
699+
assert_eq!(bytes.len(), bi.total_size());
653700
let es = bi.elf_sections_tag().unwrap();
654701
let mut s = es.sections();
655702
let s1 = s.next().unwrap();

0 commit comments

Comments
 (0)