Skip to content

Commit 17ba816

Browse files
committed
WIP: try to get higher half PIC working
1 parent c242c84 commit 17ba816

File tree

5 files changed

+58
-20
lines changed

5 files changed

+58
-20
lines changed

Diff for: Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ rustflags = [
9696
"-C",
9797
"link-args=--image-base 0xFFFF800000000000",
9898
"-C",
99-
"relocation-model=static", # pic in higher half not supported yet
99+
"relocation-model=pie", # pic in higher half not supported yet
100100
"-C",
101101
"code-model=large",
102102
]

Diff for: build.rs

+5
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ fn build_uefi_bootloader(out_dir: &Path) -> PathBuf {
5555
// local build
5656
cmd.arg("--path").arg("uefi");
5757
println!("cargo:rerun-if-changed=uefi");
58+
println!("cargo:rerun-if-changed=common");
5859
} else {
5960
cmd.arg("--version").arg(BOOTLOADER_X86_64_UEFI_VERSION);
6061
}
@@ -135,6 +136,10 @@ fn build_bios_stage_2(out_dir: &Path) -> PathBuf {
135136
// local build
136137
cmd.arg("--path").arg(&local_path);
137138
println!("cargo:rerun-if-changed={}", local_path.display());
139+
println!(
140+
"cargo:rerun-if-changed={}",
141+
local_path.with_file_name("common").display()
142+
);
138143
} else {
139144
cmd.arg("--version")
140145
.arg(BOOTLOADER_X86_64_BIOS_STAGE_2_VERSION);

Diff for: common/src/level_4_entries.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,11 @@ impl UsedLevel4Entries {
126126
pub fn mark_segments<'a>(
127127
&mut self,
128128
segments: impl Iterator<Item = ProgramHeader<'a>>,
129-
virtual_address_offset: u64,
129+
virtual_address_offset: i128,
130130
) {
131131
for segment in segments.filter(|s| s.mem_size() > 0) {
132132
self.mark_range_as_used(
133-
segment.virtual_addr() + virtual_address_offset,
133+
u64::try_from(i128::from(segment.virtual_addr()) + virtual_address_offset).unwrap(),
134134
segment.mem_size(),
135135
);
136136
}
@@ -158,7 +158,8 @@ impl UsedLevel4Entries {
158158
// Choose the first index.
159159
free_entries.next()
160160
};
161-
let idx = idx_opt.expect("no usable level 4 entries found");
161+
let idx = idx_opt
162+
.unwrap_or_else(|| panic!("no usable level 4 entries found ({num} entries requested)"));
162163

163164
// Mark the entries as used.
164165
for i in 0..num.into_usize() {

Diff for: common/src/load_kernel.rs

+46-14
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ struct Loader<'a, M, F> {
2929

3030
struct Inner<'a, M, F> {
3131
kernel_offset: PhysAddr,
32-
virtual_address_offset: u64,
32+
virtual_address_offset: i128,
3333
page_table: &'a mut M,
3434
frame_allocator: &'a mut F,
3535
}
@@ -65,18 +65,26 @@ where
6565
let load_program_headers = elf_file
6666
.program_iter()
6767
.filter(|h| matches!(h.get_type(), Ok(Type::Load)));
68-
let size = load_program_headers
68+
let max_addr = load_program_headers
6969
.clone()
7070
.map(|h| h.virtual_addr() + h.mem_size())
7171
.max()
7272
.unwrap_or(0);
73+
let min_addr = load_program_headers
74+
.clone()
75+
.map(|h| h.virtual_addr())
76+
.min()
77+
.unwrap_or(0);
78+
let size = max_addr - min_addr;
7379
let align = load_program_headers.map(|h| h.align()).max().unwrap_or(1);
7480

75-
used_entries.get_free_address(size, align).as_u64()
81+
let offset = used_entries.get_free_address(size, align).as_u64();
82+
offset as i128 - min_addr as i128
7683
}
7784
header::Type::Core => unimplemented!(),
7885
header::Type::ProcessorSpecific(_) => unimplemented!(),
7986
};
87+
log::info!("virtual_address_offset: {virtual_address_offset:#x}");
8088

8189
used_entries.mark_segments(elf_file.program_iter(), virtual_address_offset);
8290

@@ -141,7 +149,13 @@ where
141149
}
142150

143151
fn entry_point(&self) -> VirtAddr {
144-
VirtAddr::new(self.elf_file.header.pt2.entry_point() + self.inner.virtual_address_offset)
152+
VirtAddr::new(
153+
u64::try_from(
154+
i128::from(self.elf_file.header.pt2.entry_point())
155+
+ self.inner.virtual_address_offset,
156+
)
157+
.unwrap(),
158+
)
145159
}
146160
}
147161

@@ -158,7 +172,10 @@ where
158172
let end_frame: PhysFrame =
159173
PhysFrame::containing_address(phys_start_addr + segment.file_size() - 1u64);
160174

161-
let virt_start_addr = VirtAddr::new(segment.virtual_addr()) + self.virtual_address_offset;
175+
let virt_start_addr = VirtAddr::new(
176+
u64::try_from(i128::from(segment.virtual_addr()) + self.virtual_address_offset)
177+
.unwrap(),
178+
);
162179
let start_page: Page = Page::containing_address(virt_start_addr);
163180

164181
let mut segment_flags = Flags::PRESENT;
@@ -198,7 +215,10 @@ where
198215
) -> Result<(), &'static str> {
199216
log::info!("Mapping bss section");
200217

201-
let virt_start_addr = VirtAddr::new(segment.virtual_addr()) + self.virtual_address_offset;
218+
let virt_start_addr = VirtAddr::new(
219+
u64::try_from(i128::from(segment.virtual_addr()) + self.virtual_address_offset)
220+
.unwrap(),
221+
);
202222
let mem_size = segment.mem_size();
203223
let file_size = segment.file_size();
204224

@@ -343,7 +363,10 @@ where
343363
fn remove_copied_flags(&mut self, elf_file: &ElfFile) -> Result<(), &'static str> {
344364
for program_header in elf_file.program_iter() {
345365
if let Type::Load = program_header.get_type()? {
346-
let start = self.virtual_address_offset + program_header.virtual_addr();
366+
let start = u64::try_from(
367+
self.virtual_address_offset + i128::from(program_header.virtual_addr()),
368+
)
369+
.unwrap();
347370
let end = start + program_header.mem_size();
348371
let start = VirtAddr::new(start);
349372
let end = VirtAddr::new(end);
@@ -380,7 +403,10 @@ where
380403

381404
fn handle_tls_segment(&mut self, segment: ProgramHeader) -> Result<TlsTemplate, &'static str> {
382405
Ok(TlsTemplate {
383-
start_addr: segment.virtual_addr() + self.virtual_address_offset,
406+
start_addr: u64::try_from(
407+
i128::from(segment.virtual_addr()) + self.virtual_address_offset,
408+
)
409+
.unwrap(),
384410
mem_size: segment.mem_size(),
385411
file_size: segment.file_size(),
386412
})
@@ -476,11 +502,15 @@ where
476502
// R_AMD64_RELATIVE
477503
8 => {
478504
check_is_in_load(elf_file, rela.get_offset())?;
479-
let addr = self.virtual_address_offset + rela.get_offset();
480-
let value = self
481-
.virtual_address_offset
482-
.checked_add(rela.get_addend())
483-
.unwrap();
505+
let addr =
506+
u64::try_from(self.virtual_address_offset + i128::from(rela.get_offset()))
507+
.unwrap();
508+
let value = u64::try_from(
509+
self.virtual_address_offset
510+
.checked_add(i128::from(rela.get_addend()))
511+
.unwrap(),
512+
)
513+
.unwrap();
484514

485515
let ptr = addr as *mut u64;
486516
if ptr as usize % align_of::<u64>() != 0 {
@@ -511,7 +541,9 @@ where
511541
/// need to be writable while applying relocations, but should never be
512542
/// written to after relocations have been applied.
513543
fn handle_relro_segment(&mut self, program_header: ProgramHeader) {
514-
let start = self.virtual_address_offset + program_header.virtual_addr();
544+
let start =
545+
u64::try_from(self.virtual_address_offset + i128::from(program_header.virtual_addr()))
546+
.unwrap();
515547
let end = start + program_header.mem_size();
516548
let start = VirtAddr::new(start);
517549
let end = VirtAddr::new(end);

Diff for: tests/runner/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ const QEMU_ARGS: &[&str] = &[
55
"isa-debug-exit,iobase=0xf4,iosize=0x04",
66
"-serial",
77
"stdio",
8-
"-display",
9-
"none",
8+
// "-display",
9+
// "none",
1010
"--no-reboot",
1111
];
1212

0 commit comments

Comments
 (0)