Skip to content

Commit 1c6775f

Browse files
committed
better support for mimxrt1052
1 parent 0857869 commit 1c6775f

File tree

1 file changed

+125
-80
lines changed

1 file changed

+125
-80
lines changed
+125-80
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
import copy
1+
from elftools.construct.lib import Container
22

3-
from ..components.allocation_managers.allocation_manager import MappedBlock, MemoryFlag
3+
from ..components.allocation_managers.allocation_manager import (
4+
FileBlock,
5+
MemoryBlock,
6+
)
47
from ..components.binfmt_tools.elf import ELF
58
from .elf_arm_linux import ElfArmLinux
69

@@ -9,7 +12,14 @@ class CustomElf(ELF):
912
def _init_memory_analysis(self):
1013
"""
1114
Information from NXP's MCUXpresso IDE:
12-
Flash is code, RAM4 is data
15+
Flash is code, RAM4 is where data being loaded to
16+
17+
* For additional code, we can just put them in the free flash space
18+
* For additional data, we also put them in the free flash space, but
19+
we need to update ResetISR to copy them to RAM4
20+
21+
* The flasher (LinkServer) seems only care about segment headers, so
22+
we can safely ignore the section headers.
1323
1424
Type | Name | Alias | Location | Size
1525
-------|---------------|-------|------------|----------
@@ -20,86 +30,123 @@ def _init_memory_analysis(self):
2030
RAM | BOARD_SDRAM | RAM4 | 0x80000000 | 0x1e00000
2131
RAM | NCACHE_REGION | RAM5 | 0x81e00000 | 0x200000
2232
"""
23-
# Extend LOAD (0x60000000) segment
24-
# Extend LOAD (0x80000000) segment
33+
34+
# add free flash space to allocation manager
35+
flash_start = 0x60000000
36+
flash_end = 0x64000000
37+
highest_flash_addr = 0x60000000
38+
highest_file_offset = 0
2539
for segment in self._segments:
26-
if segment["p_vaddr"] == 0x60000000:
27-
block = MappedBlock(
28-
segment["p_offset"],
29-
segment["p_vaddr"],
30-
segment["p_memsz"],
31-
is_free=False,
32-
flag=MemoryFlag.RX,
33-
)
34-
self.p.allocation_manager.add_block(block)
35-
36-
round_up = (segment["p_memsz"] + 0xFFFF) & ~0xFFFF
37-
block = MappedBlock(
38-
segment["p_offset"] + segment["p_memsz"],
39-
segment["p_vaddr"] + segment["p_memsz"],
40-
round_up - segment["p_memsz"],
41-
is_free=True,
42-
flag=MemoryFlag.RX,
43-
)
44-
self.p.allocation_manager.add_block(block)
45-
self.p.allocation_manager.new_mapped_blocks.append(copy.deepcopy(block))
46-
# segment["p_memsz"] = round_up
47-
# segment["p_filesz"] = round_up
48-
if segment["p_vaddr"] == 0x80000000:
49-
block = MappedBlock(
50-
segment["p_offset"],
51-
segment["p_vaddr"],
52-
segment["p_memsz"],
53-
is_free=False,
54-
flag=MemoryFlag.RW,
55-
)
56-
self.p.allocation_manager.add_block(block)
57-
58-
round_up = (segment["p_memsz"] + 0xFFFF) & ~0xFFFF
59-
block = MappedBlock(
60-
segment["p_offset"] + segment["p_memsz"],
61-
segment["p_vaddr"] + segment["p_memsz"],
62-
round_up - segment["p_memsz"],
63-
is_free=True,
64-
flag=MemoryFlag.RW,
65-
)
66-
self.p.allocation_manager.add_block(block)
67-
self.p.allocation_manager.new_mapped_blocks.append(copy.deepcopy(block))
68-
# segment["p_memsz"] = round_up
69-
# segment["p_filesz"] = round_up
40+
seg_start = segment["p_paddr"]
41+
seg_end = segment["p_paddr"] + segment["p_memsz"]
42+
if (
43+
flash_start <= seg_start < flash_end
44+
and flash_start <= seg_end < flash_end
45+
and seg_end > highest_flash_addr
46+
):
47+
highest_flash_addr = seg_end
48+
49+
if segment["p_offset"] + segment["p_filesz"] > highest_file_offset:
50+
highest_file_offset = segment["p_offset"] + segment["p_filesz"]
51+
52+
highest_file_offset = (highest_file_offset + 0xFFFF) & ~0xFFFF
53+
block = FileBlock(highest_file_offset, -1)
54+
self.p.allocation_manager.add_block(block)
55+
block = MemoryBlock(highest_flash_addr, -1)
56+
self.p.allocation_manager.add_block(block)
57+
58+
return
7059

7160
def finalize(self):
72-
# remove EXIDX segment
73-
self._segments = [s for s in self._segments if s["p_type"] != "PT_ARM_EXIDX"]
74-
super().finalize()
61+
self.p.allocation_manager.finalize()
62+
if len(self.p.allocation_manager.new_mapped_blocks) == 0:
63+
return
7564

76-
# extend .text, .data section
77-
code_size, data_size = None, None
78-
for segment in self._segments:
79-
if segment["p_vaddr"] == 0x60000000:
80-
code_size = segment["p_memsz"]
81-
if segment["p_vaddr"] == 0x80000000:
82-
data_size = segment["p_memsz"]
83-
assert code_size is not None and data_size is not None
84-
for idx, section in enumerate(self._elf.iter_sections()):
85-
if section.name == ".text":
86-
section_header = section.header
87-
section_header["sh_size"] = (
88-
code_size + 0x60000000 - section_header["sh_addr"]
89-
)
90-
self.p.binfmt_tool.update_binary_content(
91-
self._elf.header["e_shoff"] + idx * self._elf.header["e_shentsize"],
92-
self._elf.structs.Elf_Shdr.build(section_header),
93-
)
94-
if section.name == ".data":
95-
section_header = section.header
96-
section_header["sh_size"] = (
97-
data_size + 0x80000000 - section_header["sh_addr"]
98-
)
99-
self.p.binfmt_tool.update_binary_content(
100-
self._elf.header["e_shoff"] + idx * self._elf.header["e_shentsize"],
101-
self._elf.structs.Elf_Shdr.build(section_header),
65+
max_align = max([segment["p_align"] for segment in self._segments] + [0])
66+
67+
# create new load segment for each new mapped block
68+
for block in self.p.allocation_manager.new_mapped_blocks:
69+
self._segments.append(
70+
Container(
71+
**{
72+
"p_type": "PT_LOAD",
73+
"p_offset": block.file_addr,
74+
"p_filesz": block.size,
75+
"p_vaddr": block.mem_addr,
76+
"p_paddr": block.mem_addr,
77+
"p_memsz": block.size,
78+
"p_flags": block.flag,
79+
"p_align": max_align,
80+
}
10281
)
82+
)
83+
84+
# sort segments by p_offset
85+
self._segments = sorted(self._segments, key=lambda x: x["p_offset"])
86+
87+
# try to merge load segments if they are adjacent and have the same flags and same alignment
88+
# new size = sum of sizes of the two segments + gap between them
89+
while True:
90+
new_segments = []
91+
i = 0
92+
while i < len(self._segments) - 1:
93+
prev_seg = self._segments[i]
94+
next_seg = self._segments[i + 1]
95+
if (
96+
prev_seg["p_type"] == next_seg["p_type"] == "PT_LOAD"
97+
and prev_seg["p_offset"] + prev_seg["p_filesz"]
98+
== next_seg["p_offset"]
99+
and prev_seg["p_vaddr"] + prev_seg["p_memsz"] == next_seg["p_vaddr"]
100+
and prev_seg["p_flags"] == next_seg["p_flags"]
101+
and prev_seg["p_align"] == next_seg["p_align"]
102+
):
103+
new_segments.append(
104+
Container(
105+
**{
106+
"p_type": "PT_LOAD",
107+
"p_offset": prev_seg["p_offset"],
108+
"p_filesz": prev_seg["p_filesz"]
109+
+ next_seg["p_filesz"]
110+
+ (
111+
next_seg["p_offset"]
112+
- (prev_seg["p_offset"] + prev_seg["p_filesz"])
113+
),
114+
"p_vaddr": prev_seg["p_vaddr"],
115+
"p_paddr": prev_seg["p_paddr"],
116+
"p_memsz": prev_seg["p_memsz"]
117+
+ next_seg["p_memsz"]
118+
+ (
119+
next_seg["p_vaddr"]
120+
- (prev_seg["p_vaddr"] + prev_seg["p_memsz"])
121+
),
122+
"p_flags": prev_seg["p_flags"],
123+
"p_align": prev_seg["p_align"],
124+
}
125+
)
126+
)
127+
i += 2
128+
else:
129+
new_segments.append(prev_seg)
130+
i += 1
131+
if i == len(self._segments) - 1:
132+
new_segments.append(self._segments[i])
133+
if new_segments == self._segments:
134+
break
135+
self._segments = new_segments
136+
137+
# generate new phdr at end of the file and update ehdr
138+
last_seg = sorted(self._segments, key=lambda x: x["p_offset"])[-1]
139+
phdr_start = last_seg["p_offset"] + last_seg["p_filesz"]
140+
new_phdr = b""
141+
for segment in self._segments:
142+
new_phdr += self._elf.structs.Elf_Phdr.build(segment)
143+
self.p.binfmt_tool.update_binary_content(phdr_start, new_phdr)
144+
145+
ehdr = self._elf.header
146+
ehdr["e_phnum"] = len(self._segments)
147+
ehdr["e_phoff"] = phdr_start
148+
new_ehdr = self._elf.structs.Elf_Ehdr.build(ehdr)
149+
self.p.binfmt_tool.update_binary_content(0, new_ehdr)
103150

104151

105152
class ElfArmMimxrt1052(ElfArmLinux):
@@ -110,7 +157,5 @@ def detect_target(binary_path):
110157
def get_binfmt_tool(self, binfmt_tool):
111158
binfmt_tool = binfmt_tool or "default"
112159
if binfmt_tool == "default":
113-
return ELF(self.p, self.binary_path)
114-
if binfmt_tool == "custom":
115160
return CustomElf(self.p, self.binary_path)
116161
raise NotImplementedError()

0 commit comments

Comments
 (0)