-
Notifications
You must be signed in to change notification settings - Fork 3k
TF-M: Python script to clone TF-M #11651
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
#!/usr/bin/env python | ||
""" | ||
Copyright (c) 2019 ARM Limited. All rights reserved. | ||
|
||
SPDX-License-Identifier: Apache-2.0 | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
|
||
http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
""" | ||
|
||
import os | ||
from os.path import join, abspath, dirname, isdir | ||
import sys | ||
import shutil | ||
import subprocess | ||
import logging | ||
|
||
logger = logging.getLogger('TF-M-Builder') | ||
logging.basicConfig(level=logging.INFO, | ||
format='[%(name)s] %(asctime)s: %(message)s.', | ||
datefmt='%H:%M:%S') | ||
|
||
ROOT = abspath(join(dirname(__file__), os.pardir, os.pardir)) | ||
sys.path.insert(0, ROOT) | ||
|
||
TF_M_BUILD_DIR = join(ROOT, os.pardir, 'tfm_build_dir') | ||
VERSION_FILE_PATH = join(ROOT, 'features/FEATURE_PSA/FEATURE_TFM') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The commit message needs updating. It still says "components". There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Patater fixed. |
||
|
||
dependencies = { | ||
"trusted-firmware-m": | ||
['https://git.trustedfirmware.org/trusted-firmware-m.git', | ||
'feature-twincpu'], | ||
"mbedtls": ['https://github.com/ARMmbed/mbedtls.git', | ||
'mbedtls-2.7.9'], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wow, that's a really old Mbed TLS. |
||
"mbed-crypto": ['https://github.com/ARMmbed/mbed-crypto.git', | ||
'mbedcrypto-1.1.0'], | ||
"CMSIS_5": ['https://github.com/ARM-software/CMSIS_5.git', '5.5.0'], | ||
} | ||
|
||
def is_git_installed(): | ||
""" | ||
Check if git is installed | ||
""" | ||
command = ['git', '--version'] | ||
try: | ||
with open(os.devnull, 'w') as fnull: | ||
return subprocess.call(command, stdout=fnull, stderr=fnull) | ||
except OSError as e: | ||
return e.errno | ||
|
||
def is_git_lfs_installed(): | ||
""" | ||
Check if git-lfs is installed | ||
""" | ||
command = ['git-lfs', '--version'] | ||
try: | ||
with open(os.devnull, 'w') as fnull: | ||
return subprocess.call(command, stdout=fnull, stderr=fnull) | ||
except OSError as e: | ||
return e.errno | ||
|
||
def run_cmd_and_return_output(command): | ||
""" | ||
Run the command in the sytem and return output. | ||
Commands are passed as a list of tokens. | ||
E.g. The command 'git remote -v' would be passed in as: | ||
['git', 'remote', '-v'] | ||
|
||
:param command: System command as a list of tokens | ||
""" | ||
output = '' | ||
logger.debug('[Exec] %s', ' '.join(command)) | ||
try: | ||
with open(os.devnull, 'w') as fnull: | ||
output = subprocess.check_output(command, stderr=fnull) | ||
except subprocess.CalledProcessError as e: | ||
logger.error("The command %s failed with return code: %s", | ||
(' '.join(command)), e.returncode) | ||
clean_up_cloned_repos() | ||
return output.decode("utf-8") | ||
|
||
def detect_and_write_tfm_version(tfm_dir): | ||
""" | ||
Identify the version of TF-M and write it to VERSION.txt | ||
:param tfm_dir: The filesystem path where TF-M repo is cloned | ||
""" | ||
cmd = ['git', '-C', tfm_dir, 'describe', '--tags', | ||
'--abbrev=12', '--dirty', '--always'] | ||
tfm_version = run_cmd_and_return_output(cmd) | ||
logger.info('TF-M version: %s', tfm_version.strip('\n')) | ||
if not isdir(VERSION_FILE_PATH): | ||
os.makedirs(VERSION_FILE_PATH) | ||
with open(join(VERSION_FILE_PATH, 'VERSION.txt'), 'w') as f: | ||
f.write(tfm_version) | ||
|
||
def check_repo_version(name, deps): | ||
""" | ||
Compare the version of cloned and expected and exit if they dont match | ||
:param name: Name of the git repository | ||
:param deps: Dictionary containing dependency details | ||
""" | ||
basedir = TF_M_BUILD_DIR | ||
if name == 'trusted-firmware-m': | ||
cmd = ['git', '-C', join(basedir, name), | ||
'rev-parse', '--abbrev-ref', 'HEAD'] | ||
else: | ||
cmd = ['git', '-C', join(basedir, name), | ||
'describe', '--tags'] | ||
_out = run_cmd_and_return_output(cmd) | ||
if _out.strip('\n') != deps.get(name)[1]: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Getting an error when executing this script Is it related to python3, if yes are we not supporting Python 3 as Python 2.7 support will be ending soon? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jainvikas8 Added support for python3 |
||
logger.error('Conflict: cloned "%s" and expected "%s"', | ||
_out.strip('\n'), deps.get(name)[1]) | ||
logger.error('check and remove folder %s', | ||
join(basedir, name)) | ||
sys.exit(1) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do not call sys.exit(1). This will crash out of the program and will do no cleanup. It also will fail in the online system. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mark-edgeworth In this case we need to exit from the script without doing any cleanup since the cloned repos might contain user changes. Therefore, the only thing we do here is to warn the user and let them take the action. |
||
else: | ||
logger.info('%s: version check OK', name) | ||
|
||
def check_and_clone_repo(name, deps): | ||
""" | ||
Test if the repositories are already cloned. If not clone them | ||
:param name: Name of the git repository | ||
:param deps: Dictionary containing dependency details | ||
""" | ||
basedir = TF_M_BUILD_DIR | ||
if not isdir(join(basedir, name)): | ||
logger.info('Cloning %s repo', name) | ||
cmd = ['git', '-C', basedir, 'clone', '-b', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This (and other command calls to git) make assumptions that git is installed on the user's machine. None of this will work in the online build system either. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added is_git_installed() and is_git_lfs_installed() method to check the availability of required tools. |
||
deps.get(name)[1], deps.get(name)[0]] | ||
_out = run_cmd_and_return_output(cmd) | ||
logger.info('Cloned %s repo successfully', name) | ||
else: | ||
logger.info('%s repo exists, checking git version...', name) | ||
check_repo_version(name, deps) | ||
|
||
def clone_tfm_repo(): | ||
""" | ||
Clone TF-M git repos and it's dependencies | ||
""" | ||
check_and_clone_repo('trusted-firmware-m', dependencies) | ||
check_and_clone_repo('mbedtls', dependencies) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So, this puts tf-m and all dependencies side by side into a single directly. How does TF-M pick up the dependencies and use them? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, that's the preferred way of building TF-M. The dependencies are cloned outside the TF-M source tree and the cmake scripts handle the inclusion of dependent modules. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, so we can point TF-M's build system to any filesystem location for the dependencies. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I need to check the cmake files but I think it is parent folder of tf-m is where the cmake will look for dependencies. |
||
check_and_clone_repo('mbed-crypto', dependencies) | ||
check_and_clone_repo('CMSIS_5', dependencies) | ||
detect_and_write_tfm_version(join(TF_M_BUILD_DIR, 'trusted-firmware-m')) | ||
|
||
def clean_up_cloned_repos(): | ||
""" | ||
Clean up cloned repos in case of any errors | ||
""" | ||
try: | ||
shutil.rmtree(TF_M_BUILD_DIR) | ||
except OSError as e: | ||
logger.error('Unable to cleanup cloned repos') | ||
logger.error('"%s" occured', e.strerror) | ||
|
||
def main(): | ||
""" | ||
Build Trusted Firmware M (TF-M) image for mbed-os supported TF-M targets. | ||
Current version of the script only clones TF-M git repo and dependencies | ||
and creates a VERSION.txt file under 'features/FEATURE_PSA/FEATURE_TFM' | ||
""" | ||
if not isdir(TF_M_BUILD_DIR): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be ideal to delete all the files if the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jainvikas8 It might be possible that users might have changes in the tf-m build directory. So it is not safe to assume that it can be deleted. Added a check to verify the version of cloned repos with the expected ones if the tf-m build directory already exists and warn the user if the versions don't match. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, this would imply users can only have their changes saved locally, but can't pull in their git branches as the tag/version would change to a different HEAD. Is my understanding right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes |
||
os.mkdir(TF_M_BUILD_DIR) | ||
clone_tfm_repo() | ||
|
||
if __name__ == '__main__': | ||
if is_git_installed() != 0: | ||
logger.error('"git" is not installed. Exiting...') | ||
elif is_git_lfs_installed() != 0: | ||
logger.error('"git-lfs" is not installed. Exiting...') | ||
else: | ||
main() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it be good to use the
mbed-os/BUILD
directory to have everything there, as it is a dedicated build folder?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are planning to use the mbed-os importer to bring in TF-M PSA APIs for non-secure side. Therefore we cannot use mbed-os/BUILD directory. The importer script expects the source to be outside of mbed-os.
Another reason is not be interfere with mbed-cli building non-secure side (mbed-os). If we use mbed-os/BUILD then mbed-cli will try to compie tf-m sources when non-secure side is being built.