You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
178 lines
5.7 KiB
Ruby
178 lines
5.7 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# SPDX-License-Identifier: MIT OR Apache-2.0
|
|
#
|
|
# Copyright (c) 2021 Andre Richter <andre.o.richter@gmail.com>
|
|
|
|
# Raspberry Pi 3 + 4
|
|
class RaspberryPi
|
|
attr_reader :kernel_granule, :kernel_virt_addr_space_size, :kernel_virt_start_addr
|
|
|
|
NM_BINARY = 'aarch64-none-elf-nm'
|
|
READELF_BINARY = 'aarch64-none-elf-readelf'
|
|
MEMORY_SRC = File.read('src/bsp/raspberrypi/memory.rs').split("\n")
|
|
|
|
def initialize(kernel_elf)
|
|
@kernel_granule = Granule64KiB
|
|
|
|
@virt_addresses = {
|
|
boot_core_stack_start: /__boot_core_stack_start/,
|
|
boot_core_stack_end_exclusive: /__boot_core_stack_end_exclusive/,
|
|
|
|
rx_start: /__rx_start/,
|
|
rx_end_exclusive: /__rx_end_exclusive/,
|
|
|
|
rw_start: /__rw_start/,
|
|
rw_end_exclusive: /__rw_end_exclusive/,
|
|
|
|
table_struct_start_addr: /bsp::.*::memory::mmu::KERNEL_TABLES/,
|
|
phys_tables_base_addr: /PHYS_KERNEL_TABLES_BASE_ADDR/
|
|
}
|
|
|
|
symbols = `#{NM_BINARY} --demangle #{kernel_elf}`.split("\n")
|
|
@kernel_virt_addr_space_size = parse_from_symbols(symbols, /__kernel_virt_addr_space_size/)
|
|
@kernel_virt_start_addr = parse_from_symbols(symbols, /__kernel_virt_start_addr/)
|
|
@virt_addresses = parse_from_symbols(symbols, @virt_addresses)
|
|
@phys_addresses = virt_to_phys(@virt_addresses)
|
|
|
|
@descriptors = parse_descriptors
|
|
update_max_descriptor_name_length
|
|
|
|
@text_section_offset_in_elf = parse_text_section_offset_in_elf(kernel_elf)
|
|
end
|
|
|
|
def rw_end_exclusive
|
|
@virt_addresses[:rw_end_exclusive]
|
|
end
|
|
|
|
def phys_table_struct_start_addr
|
|
@phys_addresses[:table_struct_start_addr]
|
|
end
|
|
|
|
def table_struct_offset_in_kernel_elf
|
|
(@virt_addresses[:table_struct_start_addr] - @virt_addresses[:rx_start]) +
|
|
@text_section_offset_in_elf
|
|
end
|
|
|
|
def phys_tables_base_addr
|
|
@phys_addresses[:phys_tables_base_addr]
|
|
end
|
|
|
|
def phys_tables_base_addr_offset_in_kernel_elf
|
|
(@virt_addresses[:phys_tables_base_addr] - @virt_addresses[:rx_start]) +
|
|
@text_section_offset_in_elf
|
|
end
|
|
|
|
def phys_addr_space_end_page
|
|
x = MEMORY_SRC.grep(/pub const END/)
|
|
x = case BSP_TYPE
|
|
when :rpi3
|
|
x[0]
|
|
when :rpi4
|
|
x[1]
|
|
else
|
|
raise
|
|
end
|
|
|
|
x.scan(/\d+/).join.to_i(16)
|
|
end
|
|
|
|
def kernel_map_binary
|
|
MappingDescriptor.print_header
|
|
|
|
@descriptors.each do |i|
|
|
print 'Generating'.rjust(12).green.bold
|
|
print ' '
|
|
puts i.to_s
|
|
|
|
TRANSLATION_TABLES.map_pages_at(i.virt_pages, i.phys_pages, i.attributes)
|
|
end
|
|
|
|
MappingDescriptor.print_divider
|
|
end
|
|
|
|
private
|
|
|
|
def parse_from_symbols(symbols, input)
|
|
case input.class.to_s
|
|
when 'Regexp'
|
|
symbols.grep(input).first.split.first.to_i(16)
|
|
when 'Hash'
|
|
input.transform_values do |val|
|
|
symbols.grep(val).first.split.first.to_i(16)
|
|
end
|
|
else
|
|
raise
|
|
end
|
|
end
|
|
|
|
def parse_text_section_offset_in_elf(kernel_elf)
|
|
`#{READELF_BINARY} --sections #{kernel_elf}`.scan(/.text.*/).first.split.last.to_i(16)
|
|
end
|
|
|
|
def virt_to_phys(input)
|
|
case input.class.to_s
|
|
when 'Integer'
|
|
input - @kernel_virt_start_addr
|
|
when 'Hash'
|
|
input.transform_values do |val|
|
|
val - @kernel_virt_start_addr
|
|
end
|
|
else
|
|
raise
|
|
end
|
|
end
|
|
|
|
def descriptor_ro
|
|
name = 'Code and RO data'
|
|
|
|
ro_size = @virt_addresses[:rx_end_exclusive] -
|
|
@virt_addresses[:rx_start]
|
|
|
|
virt_ro_pages = PageArray.new(@virt_addresses[:rx_start], ro_size, @kernel_granule::SIZE)
|
|
phys_ro_pages = PageArray.new(@phys_addresses[:rx_start], ro_size, @kernel_granule::SIZE)
|
|
ro_attribues = AttributeFields.new(:CacheableDRAM, :ReadOnly, :X)
|
|
|
|
MappingDescriptor.new(name, virt_ro_pages, phys_ro_pages, ro_attribues)
|
|
end
|
|
|
|
def descriptor_data
|
|
name = 'Data and bss'
|
|
|
|
data_size = @virt_addresses[:rw_end_exclusive] -
|
|
@virt_addresses[:rw_start]
|
|
|
|
virt_data_pages = PageArray.new(@virt_addresses[:rw_start], data_size,
|
|
@kernel_granule::SIZE)
|
|
phys_data_pages = PageArray.new(@phys_addresses[:rw_start], data_size,
|
|
@kernel_granule::SIZE)
|
|
data_attribues = AttributeFields.new(:CacheableDRAM, :ReadWrite, :XN)
|
|
|
|
MappingDescriptor.new(name, virt_data_pages, phys_data_pages, data_attribues)
|
|
end
|
|
|
|
def descriptor_boot_core_stack
|
|
name = 'Boot-core stack'
|
|
|
|
boot_core_stack_size = @virt_addresses[:boot_core_stack_end_exclusive] -
|
|
@virt_addresses[:boot_core_stack_start]
|
|
|
|
virt_boot_core_stack_pages = PageArray.new(@virt_addresses[:boot_core_stack_start],
|
|
boot_core_stack_size, @kernel_granule::SIZE)
|
|
phys_boot_core_stack_pages = PageArray.new(@phys_addresses[:boot_core_stack_start],
|
|
boot_core_stack_size, @kernel_granule::SIZE)
|
|
boot_core_stack_attribues = AttributeFields.new(:CacheableDRAM, :ReadWrite, :XN)
|
|
|
|
MappingDescriptor.new(name, virt_boot_core_stack_pages, phys_boot_core_stack_pages,
|
|
boot_core_stack_attribues)
|
|
end
|
|
|
|
def parse_descriptors
|
|
[descriptor_ro, descriptor_data, descriptor_boot_core_stack]
|
|
end
|
|
|
|
def update_max_descriptor_name_length
|
|
MappingDescriptor.max_descriptor_name_length = @descriptors.map { |i| i.name.size }.max
|
|
end
|
|
end
|