diff --git a/tools/build_api.py b/tools/build_api.py index 54c39e59d7..b8b3c19eae 100644 --- a/tools/build_api.py +++ b/tools/build_api.py @@ -411,7 +411,7 @@ def _fill_header(region_list, current_region): return header -def merge_region_list(region_list, destination, notify, padding=b'\xFF'): +def merge_region_list(region_list, destination, notify, config, padding=b'\xFF'): """Merge the region_list into a single image Positional Arguments: @@ -435,6 +435,13 @@ def merge_region_list(region_list, destination, notify, padding=b'\xFF'): notify.info(" Filling region %s with %s" % (region.name, region.filename)) part = intelhex_offset(region.filename, offset=region.start) part.start_addr = None + # Normally, we assume that part.maxddr() can be beyond + # end of rom. However, if the size is restricted with config, do check. + if config.target.restrict_size is not None: + part_size = (part.maxaddr() - part.minaddr()) + 1 + if part_size > region.size: + raise ToolException("Contents of region %s does not fit" + % region.name) merged.merge(part) # Hex file can have gaps, so no padding needed. While other formats may @@ -555,13 +562,13 @@ def build_project(src_paths, build_path, target, toolchain_name, for r in region_list] res = "%s.%s" % (join(build_path, name), getattr(toolchain.target, "OUTPUT_EXT", "bin")) - merge_region_list(region_list, res, notify) + merge_region_list(region_list, res, notify, toolchain.config) update_regions = [ r for r in region_list if r.name in UPDATE_WHITELIST ] if update_regions: update_res = join(build_path, generate_update_filename(name, toolchain.target)) - merge_region_list(update_regions, update_res, notify) + merge_region_list(update_regions, update_res, notify, toolchain.config) res = (res, update_res) else: res = (res, None) diff --git a/tools/test/build_api/build_api_test.py b/tools/test/build_api/build_api_test.py index 2fcfc947b8..cc397df839 100644 --- a/tools/test/build_api/build_api_test.py +++ b/tools/test/build_api/build_api_test.py @@ -18,11 +18,14 @@ limitations under the License. import unittest from collections import namedtuple from mock import patch, MagicMock -from tools.build_api import prepare_toolchain, build_project, build_library +from tools.build_api import prepare_toolchain, build_project, build_library, merge_region_list from tools.resources import Resources from tools.toolchains import TOOLCHAINS from tools.notifier.mock import MockNotifier - +from tools.config import Region +from tools.utils import ToolException +from intelhex import IntelHex +import intelhex """ Tests for build_api.py """ @@ -240,5 +243,36 @@ class BuildApiTests(unittest.TestCase): self.assertEqual(args[1]['app_config'], None, "prepare_toolchain was called with an incorrect app_config") + @patch('tools.build_api.intelhex_offset') + @patch('tools.config') + def test_merge_region_no_fit(self, mock_config, mock_intelhex_offset): + """ + Test that merge region fails as expected when part size overflows region size. + """ + max_addr = 87444 + # create a dummy hex file with above max_addr + mock_intelhex_offset.return_value = IntelHex({0:2, max_addr:0}) + + # create application and post-application regions and merge. + region_application = Region("application", 10000, 86000, True, "random.hex") + region_post_application = Region("postapplication", 100000, 90000, False, None) + + notify = MockNotifier() + region_list = [region_application, region_post_application] + # path to store the result in, should not get used as we expect exception. + res = "./" + mock_config.target.restrict_size = 90000 + toolexception = False + + try: + merge_region_list(region_list, res, notify, mock_config) + except ToolException: + toolexception = True + except Exception as e: + print("%s %s" % (e.message, e.args)) + + self.assertTrue(toolexception, "Expected ToolException not raised") + + if __name__ == '__main__': unittest.main()