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,
|
symbol_out: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum ImageHeader {
|
||||||
|
Riscv(u64),
|
||||||
|
}
|
||||||
|
|
||||||
pub struct GenData {
|
pub struct GenData {
|
||||||
pub kernel_start: u64,
|
pub kernel_start: u64,
|
||||||
pub kernel_end: u64,
|
pub kernel_end: u64,
|
||||||
@ -65,6 +69,13 @@ pub struct GenData {
|
|||||||
pub kernel_virt_offset: u64,
|
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>(
|
fn kernel_image_range<F: Read + Seek>(
|
||||||
elf: &mut ElfStream<AnyEndian, F>,
|
elf: &mut ElfStream<AnyEndian, F>,
|
||||||
kernel_virt_offset: u64,
|
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"))
|
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 {
|
let section_size = match elf.ehdr.e_machine {
|
||||||
EM_AARCH64 => size_of::<memtables::aarch64::FixedTables>(),
|
EM_AARCH64 => size_of::<memtables::aarch64::FixedTables>(),
|
||||||
EM_X86_64 => size_of::<memtables::x86_64::FixedTables>(),
|
EM_X86_64 => size_of::<memtables::x86_64::FixedTables>(),
|
||||||
EM_RISCV => size_of::<memtables::riscv64::FixedTables>(),
|
EM_RISCV => size_of::<memtables::riscv64::FixedTables>(),
|
||||||
_ => unimplemented!(),
|
_ => 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 (shdrs, strtab) = elf.section_headers_with_strtab()?;
|
||||||
let strtab = strtab.ok_or_else(|| GenError::MissingSection(".strtab"))?;
|
let strtab = strtab.ok_or_else(|| GenError::MissingSection(".strtab"))?;
|
||||||
|
|
||||||
|
let mut tables = None;
|
||||||
|
|
||||||
for shdr in shdrs {
|
for shdr in shdrs {
|
||||||
let name = strtab.get(shdr.sh_name as _)?;
|
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
|
// 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>(
|
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)
|
(x.into(), y, z)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_tables<F: Read + Seek>(
|
fn build_tables<F: Read + Seek>(file: F) -> Result<BuiltTables, GenError> {
|
||||||
file: F,
|
|
||||||
) -> Result<(Option<(AnyTables, u64)>, HashMap<String, usize>), GenError> {
|
|
||||||
let mut elf = ElfStream::<AnyEndian, F>::open_stream(file)?;
|
let mut elf = ElfStream::<AnyEndian, F>::open_stream(file)?;
|
||||||
|
|
||||||
if elf.ehdr.e_machine == EM_386 {
|
if elf.ehdr.e_machine == EM_386 {
|
||||||
// Locate symbol table
|
// Locate symbol table
|
||||||
let symbol_table = extract_symbols(&mut elf)?;
|
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_virt_offset = kernel_virt_offset(&mut elf)?;
|
||||||
let (kernel_start, kernel_end) = kernel_image_range(&mut elf, kernel_virt_offset)?;
|
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
|
let table_physical_address = table_virt_addr
|
||||||
.checked_sub(kernel_virt_offset)
|
.checked_sub(kernel_virt_offset)
|
||||||
.ok_or_else(|| GenError::IncorrectTablesPlacement(table_virt_addr))?;
|
.ok_or_else(|| GenError::IncorrectTablesPlacement(table_virt_addr))?;
|
||||||
@ -230,7 +271,12 @@ fn build_tables<F: Read + Seek>(
|
|||||||
_ => todo!(),
|
_ => 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>(
|
fn write_tables<F: Write + Seek>(
|
||||||
@ -243,6 +289,22 @@ fn write_tables<F: Write + Seek>(
|
|||||||
Ok(())
|
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(
|
fn write_symbol_table(
|
||||||
out: impl AsRef<Path>,
|
out: impl AsRef<Path>,
|
||||||
table: HashMap<String, usize>,
|
table: HashMap<String, usize>,
|
||||||
@ -268,9 +330,12 @@ fn gentables(image: impl AsRef<Path>, symbol_out: impl AsRef<Path>) -> Result<()
|
|||||||
.truncate(false)
|
.truncate(false)
|
||||||
.open(image)?;
|
.open(image)?;
|
||||||
|
|
||||||
let (tables, symbol_table) = build_tables(&mut file)?;
|
let built = build_tables(&mut file)?;
|
||||||
write_symbol_table(symbol_out, symbol_table)?;
|
write_symbol_table(symbol_out, built.symbol_table)?;
|
||||||
if let Some((tables, file_offset)) = tables {
|
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)?;
|
write_tables(file, file_offset, tables)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user