Skip to content

Commit 78b65d0

Browse files
authored
Merge pull request ARMmbed#5818 from sarahmarshy/bootloader-align-sectors
Enforce sector alignmnent for managed bootloader builds
2 parents 10e67e6 + 695dc00 commit 78b65d0

File tree

6 files changed

+86
-17
lines changed

6 files changed

+86
-17
lines changed

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ mbed-host-tests>=1.1.2
1111
mbed-greentea>=0.2.24
1212
beautifulsoup4>=4
1313
fuzzywuzzy>=0.11
14+
pyelftools>=0.24

tools/arm_pack_manager/__init__.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
import warnings
1616
from distutils.version import LooseVersion
1717

18+
from tools.flash_algo import PackFlashAlgo
19+
1820
warnings.filterwarnings("ignore")
1921

2022
from fuzzywuzzy import process
@@ -145,12 +147,33 @@ def get_urls(self):
145147
for pdsc in root_data.find_all("pdsc")]
146148
return self.urls
147149

150+
def _get_sectors(self, device):
151+
"""Extract sector sizes from device FLM algorithm
152+
153+
Will return None if there is no algorithm, pdsc URL formatted in correctly
154+
155+
:return: A list tuples of sector start and size
156+
:rtype: [list]
157+
"""
158+
try:
159+
pack = self.pack_from_cache(device)
160+
algo_itr = (pack.open(path) for path in device['algorithm'].keys())
161+
algo_bin = algo_itr.next()
162+
flm_file = algo_bin.read()
163+
return PackFlashAlgo(flm_file).sector_sizes
164+
except Exception:
165+
return None
166+
148167
def _extract_dict(self, device, filename, pack) :
149168
to_ret = dict(pdsc_file=filename, pack_file=pack)
150169
try : to_ret["memory"] = dict([(m["id"], dict(start=m["start"],
151170
size=m["size"]))
152171
for m in device("memory")])
153-
except (KeyError, TypeError, IndexError) as e : pass
172+
except (KeyError, TypeError, IndexError) as e:
173+
try : to_ret["memory"] = dict([(m["name"], dict(start=m["start"],
174+
size=m["size"]))
175+
for m in device("memory")])
176+
except (KeyError, TypeError, IndexError) as e : pass
154177
try: algorithms = device("algorithm")
155178
except:
156179
try: algorithms = device.parent("algorithm")
@@ -219,6 +242,7 @@ def _extract_dict(self, device, filename, pack) :
219242
del to_ret["compile"]
220243

221244
to_ret['debug-interface'] = []
245+
to_ret['sectors'] = self._get_sectors(to_ret)
222246

223247
return to_ret
224248

@@ -445,4 +469,3 @@ def cache_and_parse(self, url) :
445469
"""
446470
self.cache_file(url)
447471
return self.pdsc_from_cache(url)
448-

tools/arm_pack_manager/index.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

tools/config/__init__.py

Lines changed: 57 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,20 @@ def has_regions(self):
498498
else:
499499
return False
500500

501+
@property
502+
def sectors(self):
503+
"""Return a list of tuples of sector start,size"""
504+
cache = Cache(False, False)
505+
if self.target.device_name not in cache.index:
506+
raise ConfigException("Bootloader not supported on this target: "
507+
"targets.json `device_name` not found in "
508+
"arm_pack_manager index.")
509+
cmsis_part = cache.index[self.target.device_name]
510+
sectors = cmsis_part['sectors']
511+
if sectors:
512+
return sectors
513+
raise ConfigException("No sector info available")
514+
501515
@property
502516
def regions(self):
503517
"""Generate a list of regions from the config"""
@@ -526,12 +540,16 @@ def regions(self):
526540
rom_size = int(cmsis_part['memory']['IROM1']['size'], 0)
527541
rom_start = int(cmsis_part['memory']['IROM1']['start'], 0)
528542
except KeyError:
529-
raise ConfigException("Not enough information in CMSIS packs to "
530-
"build a bootloader project")
543+
try:
544+
rom_size = int(cmsis_part['memory']['PROGRAM_FLASH']['size'], 0)
545+
rom_start = int(cmsis_part['memory']['PROGRAM_FLASH']['start'], 0)
546+
except KeyError:
547+
raise ConfigException("Not enough information in CMSIS packs to "
548+
"build a bootloader project")
531549
if ('target.bootloader_img' in target_overrides or
532550
'target.restrict_size' in target_overrides):
533-
return self._generate_booloader_build(target_overrides,
534-
rom_start, rom_size)
551+
return self._generate_bootloader_build(target_overrides,
552+
rom_start, rom_size)
535553
elif ('target.mbed_app_start' in target_overrides or
536554
'target.mbed_app_size' in target_overrides):
537555
return self._generate_linker_overrides(target_overrides,
@@ -540,8 +558,8 @@ def regions(self):
540558
raise ConfigException(
541559
"Bootloader build requested but no bootlader configuration")
542560

543-
def _generate_booloader_build(self, target_overrides, rom_start, rom_size):
544-
start = 0
561+
def _generate_bootloader_build(self, target_overrides, rom_start, rom_size):
562+
start = rom_start
545563
if 'target.bootloader_img' in target_overrides:
546564
basedir = abspath(dirname(self.app_config_location))
547565
filename = join(basedir, target_overrides['target.bootloader_img'])
@@ -552,21 +570,48 @@ def _generate_booloader_build(self, target_overrides, rom_start, rom_size):
552570
raise ConfigException("bootloader executable does not "
553571
"start at 0x%x" % rom_start)
554572
part_size = (part.maxaddr() - part.minaddr()) + 1
555-
yield Region("bootloader", rom_start + start, part_size, False,
573+
part_size = Config._align_ceiling(rom_start + part_size, self.sectors) - rom_start
574+
yield Region("bootloader", rom_start, part_size, False,
556575
filename)
557-
start += part_size
576+
start = rom_start + part_size
558577
if 'target.restrict_size' in target_overrides:
559578
new_size = int(target_overrides['target.restrict_size'], 0)
560-
yield Region("application", rom_start + start, new_size, True, None)
579+
new_size = Config._align_floor(start + new_size, self.sectors) - start
580+
yield Region("application", start, new_size, True, None)
561581
start += new_size
562-
yield Region("post_application", rom_start +start, rom_size - start,
582+
yield Region("post_application", start, rom_size - start,
563583
False, None)
564584
else:
565-
yield Region("application", rom_start + start, rom_size - start,
585+
yield Region("application", start, rom_size - start,
566586
True, None)
567-
if start > rom_size:
587+
if start > rom_start + rom_size:
568588
raise ConfigException("Not enough memory on device to fit all "
569589
"application regions")
590+
591+
@staticmethod
592+
def _find_sector(address, sectors):
593+
target_size = -1
594+
target_start = -1
595+
for (start, size) in sectors:
596+
if address < start:
597+
break
598+
target_start = start
599+
target_size = size
600+
if (target_size < 0):
601+
raise ConfigException("No valid sector found")
602+
return target_start, target_size
603+
604+
@staticmethod
605+
def _align_floor(address, sectors):
606+
target_start, target_size = Config._find_sector(address, sectors)
607+
sector_num = (address - target_start) // target_size
608+
return target_start + (sector_num * target_size)
609+
610+
@staticmethod
611+
def _align_ceiling(address, sectors):
612+
target_start, target_size = Config._find_sector(address, sectors)
613+
sector_num = ((address - target_start) + target_size - 1) // target_size
614+
return target_start + (sector_num * target_size)
570615

571616
@property
572617
def report(self):
File renamed without changes.

tools/flash_algo/extract.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import os
2222
import argparse
2323
from os.path import join, abspath, dirname
24-
from flash_algo import PackFlashAlgo
24+
from tools.flash_algo import PackFlashAlgo
2525

2626
# Be sure that the tools directory is in the search path
2727
ROOT = abspath(join(dirname(__file__), "..", ".."))
@@ -98,7 +98,7 @@ def filter_algos(dev, algos):
9898
except ValueError:
9999
return algos
100100

101-
matching_algos = [algo for algo in algos if
101+
matching_algos = [algo for algo in algos if
102102
algo.flash_start == start and algo.flash_size == size]
103103
return matching_algos if len(matching_algos) == 1 else algos
104104

0 commit comments

Comments
 (0)