def get_base_segment(self, elf, segs, image): """Return the base segment, check for XIP and patch accordingly.""" if get_symbol(elf, '__phys_addr_rom', True) != None: (addr, size) = get_symbol(elf, '__phys_addr_ram') image.patch(addr, size, segs[1]) base_segment = segs[1] (addr, size) = get_symbol(elf, '__phys_addr_rom') image.patch(addr, size, segs[0]) if get_symbol(elf, '__phys_addr_stack', True) != None: stack_sym = elf.find_symbol('__stack') if stack_sym is not None: offset = stack_sym.value - segs[1].segment.vaddr (addr, size) = get_symbol(elf, '__phys_addr_stack') image.patch(addr, size, segs[1], offset) else: sdata = get_symbol(elf, '__phys_addr_ram', may_not_exist=True) if sdata is not None: (addr, size) = sdata image.patch(addr, size, segs[0]) if get_symbol(elf, '__phys_addr_stack', True) != None: stack_sym = elf.find_symbol('__stack') if stack_sym is not None: offset = stack_sym.value - segs[0].segment.vaddr (addr, size) = get_symbol(elf, '__phys_addr_stack') image.patch(addr, size, segs[0], offset) base_segment = segs[0] return base_segment
def get_base_segment(self, elf, segs, image): """Return the base segment, check for XIP and patch accordingly.""" if get_symbol(elf, "__phys_addr_rom", True) != None: (addr, size) = get_symbol(elf, "__phys_addr_ram") image.patch(addr, size, segs[1]) base_segment = segs[1] (addr, size) = get_symbol(elf, "__phys_addr_rom") image.patch(addr, size, segs[0]) if get_symbol(elf, "__phys_addr_stack", True) != None: stack_sym = elf.find_symbol("__stack") if stack_sym is not None: offset = stack_sym.value - segs[1].segment.vaddr (addr, size) = get_symbol(elf, "__phys_addr_stack") image.patch(addr, size, segs[1], offset) else: sdata = get_symbol(elf, "__phys_addr_ram", may_not_exist=True) if sdata is not None: (addr, size) = sdata image.patch(addr, size, segs[0]) if get_symbol(elf, "__phys_addr_stack", True) != None: stack_sym = elf.find_symbol("__stack") if stack_sym is not None: offset = stack_sym.value - segs[0].segment.vaddr (addr, size) = get_symbol(elf, "__phys_addr_stack") image.patch(addr, size, segs[0], offset) base_segment = segs[0] return base_segment
def get_kernel_version(kernel_el, machine): (elf, _, _) = get_kernel_file(kernel_el, machine) (addr, size) = get_symbol(elf, "kernel_api_version") kern_ver = elf.get_value(addr, size, elf.endianess) if kern_ver == None: raise MergeError("Unable to locate kernel api symbol") return kern_ver
def check_api_versions(kernel): """ Return the kernel API version number. """ kern_ver = get_symbol(kernel, "kernel_api_version", True) if kern_ver: addr = kern_ver[0] size = kern_ver[1] else: return None kern_ver = kernel.get_value(addr, size, kernel.endianess) # Check that both the kernel and soc api versions match if kern_ver == MICRO_KERNEL_API_VERSION: (addr, size) = get_symbol(kernel, "soc_api_version") soc_ver = kernel.get_value(addr, size, kernel.endianess) if soc_ver == None: raise MergeError("Unable to locate soc api symbol") if kern_ver != soc_ver: raise MergeError("Kernel api version %d doesn't match soc api version %d" % (kern_ver, soc_ver)) return kern_ver
def check_api_versions(kernel): """ Return the kernel API version number. """ kern_ver = get_symbol(kernel, "kernel_api_version", False) if kern_ver: addr = kern_ver[0] size = kern_ver[1] else: return None kern_ver = kernel.get_value(addr, size, kernel.endianess) return kern_ver
def check_api_versions(kernel): """ Return the kernel API version number. """ kern_ver = get_symbol(kernel, "kernel_api_version", True) if kern_ver: addr = kern_ver[0] size = kern_ver[1] else: return None kern_ver = kernel.get_value(addr, size, kernel.endianess) # Check that both the kernel and soc api versions match if kern_ver == MICRO_KERNEL_API_VERSION: (addr, size) = get_symbol(kernel, "soc_api_version") soc_ver = kernel.get_value(addr, size, kernel.endianess) if soc_ver == None: raise MergeError("Unable to locate soc api symbol") if kern_ver != soc_ver: raise MergeError( "Kernel api version %d doesn't match soc api version %d" % (kern_ver, soc_ver)) return kern_ver
def collect_xml(self, kernel_el, kernel_heap_size, namespace, image, machine, pools): """Collect the attributes of the kernel element.""" (elf, kernel_file, kernel_tmp) = get_kernel_file(kernel_el, machine) if elf.elf_type != ET_EXEC: raise MergeError, \ "All the merged ELF files must be of EXEC type." # New namespace for objects living in the kernel. kernel_namespace = namespace.add_namespace('kernel') # We setup our kernel type depending on the api version number kern_ver = check_api_versions(elf) if kern_ver == NANO_KERNEL_API_VERSION: self.kernel = NanoKernel(elf, kernel_namespace, machine) else: self.kernel = MicroKernel(kernel_namespace) assert self.total_threads is None self.total_threads = self.kernel.ABSOLUTE_MAX_THREADS # Record the default pools for cells to use if they don't have # defaults set. virtpool = getattr(kernel_el, "virtpool", None) physpool = getattr(kernel_el, "physpool", None) image.set_attrs_stack(def_virt=virtpool, def_phys=physpool) pools.set_default_pools(virtpool, physpool) segment_els = kernel_el.find_children("segment") patch_els = kernel_el.find_children("patch") machine.set_cache_attributes(elf) image.set_kernel(elf) segs = collect_elf_segments(elf, image.KERNEL, segment_els, 'kernel', self.kernel.segment_drops, kernel_namespace, image, machine, pools) # Set base segment self.base_segment = self.kernel.get_base_segment(elf, segs, image) if self.base_segment.attrs.phys_addr is not None and \ (self.base_segment.attrs.phys_addr & ((1024 * 1024) - 1)) != 0: raise MergeError("Physical address of %s must be 1MB aligned!" % self.base_segment.attrs.abs_name()) elf = elf.prepare(elf.wordsize, elf.endianess) # The extra_patches attr may be added by a plugin. for patch in getattr(Kernel_el, "extra_patches", []): addr = get_symbol(elf, patch[0], True) if addr != None: addr = int(addr[0]) + int(patch[1]) new_patch = Patch_el(address=hex(addr), bytes=patch[2], value=patch[3]) patch_els.append(new_patch) collect_patches(elf, patch_els, kernel_file, image) # Collect the config elements, some of these relate to # heap and thread array, so do it first config_el = kernel_el.find_child("config") if config_el is not None: for option in config_el.find_children("option"): self.add_config(option.key, option.value) heap_attrs = image.new_attrs( namespace.root.add_namespace("kernel_heap")) heap_attrs.align = machine.kernel_heap_align heap_el = kernel_el.find_child("heap") if heap_el is not None: heap_attrs.phys_addr = getattr(heap_el, 'phys_addr', heap_attrs.phys_addr) heap_attrs.size = getattr(heap_el, 'size', heap_attrs.size) heap_attrs.align = getattr(heap_el, 'align', heap_attrs.align) # Override the size with the command line value, if present. if kernel_heap_size != 0: heap_attrs.size = kernel_heap_size # Nano needs a heap size set early on # Micro remains unassigned since it will get dynamically calculated later if not heap_attrs.size and isinstance(self.kernel, NanoKernel): heap_attrs.size = self.kernel.DEFAULT_KERNEL_HEAP_SIZE self.heap = image.set_kernel_heap(heap_attrs, machine, pools, self.base_segment.segment, isinstance(self.kernel, NanoKernel)) image.add_group(machine.kernel_heap_proximity, (self.base_segment, self.heap)) self.register_heap(heap_attrs) if isinstance(self.kernel, MicroKernel): image.utcb_size = self.kernel.get_utcb_size(elf, image) self.collect_use_devices(kernel_el, image, machine, pools) if kernel_tmp: kernel_tmp.close()
def collect_xml(self, kernel_el, kernel_heap_size, namespace, image, machine, pools): """Collect the attributes of the kernel element.""" (elf, kernel_file, kernel_tmp) = get_kernel_file(kernel_el, machine) if elf.elf_type != ET_EXEC: raise MergeError, \ "All the merged ELF files must be of EXEC type." # New namespace for objects living in the kernel. kernel_namespace = namespace.add_namespace('kernel') # We setup our kernel type depending on the api version number kern_ver = check_api_versions(elf) if kern_ver == NANO_KERNEL_API_VERSION: self.kernel = NanoKernel(elf, kernel_namespace, machine) else: self.kernel = MicroKernel(kernel_namespace) assert self.total_threads is None self.total_threads = self.kernel.ABSOLUTE_MAX_THREADS # Record the default pools for cells to use if they don't have # defaults set. virtpool = getattr(kernel_el, "virtpool", None) physpool = getattr(kernel_el, "physpool", None) image.set_attrs_stack(def_virt = virtpool, def_phys = physpool) pools.set_default_pools(virtpool, physpool) segment_els = kernel_el.find_children("segment") patch_els = kernel_el.find_children("patch") machine.set_cache_attributes(elf) image.set_kernel(elf) segs = collect_elf_segments(elf, image.KERNEL, segment_els, 'kernel', self.kernel.segment_drops, kernel_namespace, image, machine, pools) # Set base segment self.base_segment = self.kernel.get_base_segment(elf, segs, image) if self.base_segment.attrs.phys_addr is not None and \ (self.base_segment.attrs.phys_addr & ((1024 * 1024) - 1)) != 0: raise MergeError("Physical address of %s must be 1MB aligned!" % self.base_segment.attrs.abs_name()) elf = elf.prepare(elf.wordsize, elf.endianess) # The extra_patches attr may be added by a plugin. for patch in getattr(Kernel_el, "extra_patches", []): addr = get_symbol(elf, patch[0], True) if addr != None: addr = int(addr[0])+ int(patch[1]) new_patch = Patch_el(address=hex(addr), bytes=patch[2], value=patch[3]) patch_els.append(new_patch) collect_patches(elf, patch_els, kernel_file, image) # Collect the config elements, some of these relate to # heap and thread array, so do it first config_el = kernel_el.find_child("config") if config_el is not None: for option in config_el.find_children("option"): self.add_config(option.key, option.value) heap_attrs = image.new_attrs(namespace.root.add_namespace("kernel_heap")) heap_attrs.align = machine.kernel_heap_align heap_el = kernel_el.find_child("heap") if heap_el is not None: heap_attrs.phys_addr = getattr(heap_el, 'phys_addr', heap_attrs.phys_addr) heap_attrs.size = getattr(heap_el, 'size', heap_attrs.size) heap_attrs.align = getattr(heap_el, 'align', heap_attrs.align) # Override the size with the command line value, if present. if kernel_heap_size != 0: heap_attrs.size = kernel_heap_size # Nano needs a heap size set early on # Micro remains unassigned since it will get dynamically calculated later if not heap_attrs.size and isinstance(self.kernel, NanoKernel): heap_attrs.size = self.kernel.DEFAULT_KERNEL_HEAP_SIZE self.heap = image.set_kernel_heap(heap_attrs, machine, pools, self.base_segment.segment, isinstance(self.kernel, NanoKernel)) image.add_group(machine.kernel_heap_proximity, (self.base_segment, self.heap)) self.register_heap(heap_attrs) if isinstance(self.kernel, MicroKernel): image.utcb_size = self.kernel.get_utcb_size(elf, image) self.collect_use_devices(kernel_el, image, machine, pools) if kernel_tmp: kernel_tmp.close()