tools: write riscv image size to header in gentables
This commit is contained in:
parent
5d406feb07
commit
24f1f41217
@ -56,6 +56,10 @@ struct Args {
|
||||
symbol_out: PathBuf,
|
||||
}
|
||||
|
||||
pub enum ImageHeader {
|
||||
Riscv(u64),
|
||||
}
|
||||
|
||||
pub struct GenData {
|
||||
pub kernel_start: u64,
|
||||
pub kernel_end: u64,
|
||||
@ -65,6 +69,13 @@ pub struct GenData {
|
||||
pub kernel_virt_offset: u64,
|
||||
}
|
||||
|
||||
pub struct BuiltTables {
|
||||
pub image_size: u64,
|
||||
pub image_header: Option<ImageHeader>,
|
||||
pub tables: Option<(AnyTables, u64)>,
|
||||
pub symbol_table: HashMap<String, usize>,
|
||||
}
|
||||
|
||||
fn kernel_image_range<F: Read + Seek>(
|
||||
elf: &mut ElfStream<AnyEndian, F>,
|
||||
kernel_virt_offset: u64,
|
||||
@ -113,16 +124,41 @@ fn kernel_virt_offset<F: Read + Seek>(elf: &mut ElfStream<AnyEndian, F>) -> Resu
|
||||
Err(GenError::MissingSymbol("KERNEL_VIRT_OFFSET"))
|
||||
}
|
||||
|
||||
fn find_tables<F: Read + Seek>(elf: &mut ElfStream<AnyEndian, F>) -> Result<(u64, u64), GenError> {
|
||||
fn find_tables<F: Read + Seek>(
|
||||
elf: &mut ElfStream<AnyEndian, F>,
|
||||
) -> Result<(Option<ImageHeader>, u64, u64), GenError> {
|
||||
let section_size = match elf.ehdr.e_machine {
|
||||
EM_AARCH64 => size_of::<memtables::aarch64::FixedTables>(),
|
||||
EM_X86_64 => size_of::<memtables::x86_64::FixedTables>(),
|
||||
EM_RISCV => size_of::<memtables::riscv64::FixedTables>(),
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
|
||||
let image_header = if let Some(text_entry) = elf.section_header_by_name(".text.entry")? {
|
||||
let header = text_entry.clone();
|
||||
let section_offset = header.sh_offset;
|
||||
let (data, _) = elf.section_data(&header)?;
|
||||
if data.len() >= 64 {
|
||||
let version = u32::from_le_bytes(data[32..36].try_into().unwrap());
|
||||
let magic0 = &data[48..56];
|
||||
let magic1 = &data[56..60];
|
||||
|
||||
match (version, magic0, magic1) {
|
||||
(2, b"RISCV\x00\x00\x00", b"RSC\x05") => Some(ImageHeader::Riscv(section_offset)),
|
||||
(_, _, _) => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let (shdrs, strtab) = elf.section_headers_with_strtab()?;
|
||||
let strtab = strtab.ok_or_else(|| GenError::MissingSection(".strtab"))?;
|
||||
|
||||
let mut tables = None;
|
||||
|
||||
for shdr in shdrs {
|
||||
let name = strtab.get(shdr.sh_name as _)?;
|
||||
|
||||
@ -135,11 +171,13 @@ fn find_tables<F: Read + Seek>(elf: &mut ElfStream<AnyEndian, F>) -> Result<(u64
|
||||
}
|
||||
|
||||
// TODO section checks
|
||||
return Ok((shdr.sh_offset, shdr.sh_addr));
|
||||
tables = Some((shdr.sh_offset, shdr.sh_addr));
|
||||
}
|
||||
}
|
||||
|
||||
Err(GenError::MissingSection(".data.tables"))
|
||||
let (tables_offset, tables_addr) = tables.ok_or(GenError::MissingSection(".data.tables"))?;
|
||||
|
||||
Ok((image_header, tables_offset, tables_addr))
|
||||
}
|
||||
|
||||
fn extract_symbols<F: Read + Seek>(
|
||||
@ -194,20 +232,23 @@ fn into_any<T: Into<AnyTables>, U, V>((x, y, z): (T, U, V)) -> (AnyTables, U, V)
|
||||
(x.into(), y, z)
|
||||
}
|
||||
|
||||
fn build_tables<F: Read + Seek>(
|
||||
file: F,
|
||||
) -> Result<(Option<(AnyTables, u64)>, HashMap<String, usize>), GenError> {
|
||||
fn build_tables<F: Read + Seek>(file: F) -> Result<BuiltTables, GenError> {
|
||||
let mut elf = ElfStream::<AnyEndian, F>::open_stream(file)?;
|
||||
|
||||
if elf.ehdr.e_machine == EM_386 {
|
||||
// Locate symbol table
|
||||
let symbol_table = extract_symbols(&mut elf)?;
|
||||
return Ok((None, symbol_table));
|
||||
return Ok(BuiltTables {
|
||||
image_size: 0,
|
||||
image_header: None,
|
||||
tables: None,
|
||||
symbol_table,
|
||||
});
|
||||
}
|
||||
|
||||
let kernel_virt_offset = kernel_virt_offset(&mut elf)?;
|
||||
let (kernel_start, kernel_end) = kernel_image_range(&mut elf, kernel_virt_offset)?;
|
||||
let (table_offset, table_virt_addr) = find_tables(&mut elf)?;
|
||||
let (image_header, table_offset, table_virt_addr) = find_tables(&mut elf)?;
|
||||
let table_physical_address = table_virt_addr
|
||||
.checked_sub(kernel_virt_offset)
|
||||
.ok_or_else(|| GenError::IncorrectTablesPlacement(table_virt_addr))?;
|
||||
@ -230,7 +271,12 @@ fn build_tables<F: Read + Seek>(
|
||||
_ => todo!(),
|
||||
}?;
|
||||
|
||||
Ok((Some((tables, table_offset)), symbol_table))
|
||||
Ok(BuiltTables {
|
||||
image_size: kernel_end - kernel_start,
|
||||
image_header,
|
||||
tables: Some((tables, table_offset)),
|
||||
symbol_table,
|
||||
})
|
||||
}
|
||||
|
||||
fn write_tables<F: Write + Seek>(
|
||||
@ -243,6 +289,22 @@ fn write_tables<F: Write + Seek>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_image_header<F: Write + Seek>(
|
||||
file: &mut F,
|
||||
header: ImageHeader,
|
||||
image_size: u64,
|
||||
) -> Result<(), GenError> {
|
||||
match header {
|
||||
ImageHeader::Riscv(offset) => {
|
||||
let size_bytes = image_size.to_le_bytes();
|
||||
println!("Writing RISC-V image header: image_size={image_size}");
|
||||
file.seek(SeekFrom::Start(offset + 16))?;
|
||||
file.write_all(&size_bytes)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn write_symbol_table(
|
||||
out: impl AsRef<Path>,
|
||||
table: HashMap<String, usize>,
|
||||
@ -268,9 +330,12 @@ fn gentables(image: impl AsRef<Path>, symbol_out: impl AsRef<Path>) -> Result<()
|
||||
.truncate(false)
|
||||
.open(image)?;
|
||||
|
||||
let (tables, symbol_table) = build_tables(&mut file)?;
|
||||
write_symbol_table(symbol_out, symbol_table)?;
|
||||
if let Some((tables, file_offset)) = tables {
|
||||
let built = build_tables(&mut file)?;
|
||||
write_symbol_table(symbol_out, built.symbol_table)?;
|
||||
if let Some(header) = built.image_header {
|
||||
write_image_header(&mut file, header, built.image_size)?;
|
||||
}
|
||||
if let Some((tables, file_offset)) = built.tables {
|
||||
write_tables(file, file_offset, tables)?;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user