Skip to content

Commit

Permalink
Add support for version_check command, fixes nxp-mcuxpresso#48 (nxp-m…
Browse files Browse the repository at this point in the history
…cuxpresso#50)

Co-authored-by: Marek Vitula <marek.vitula@nxp.com>
  • Loading branch information
marekvi95 and marekvi95 authored Sep 26, 2022
1 parent d30ad4e commit 6fc1c7b
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 2 deletions.
4 changes: 2 additions & 2 deletions spsdk/sbfile/sb2/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -831,8 +831,8 @@ def version(self) -> int:

def __str__(self) -> str:
return (
super().__str__()
+ f" type={VersionCheckType.name(self.type)}, version={str(self.version)}"
f"CVER: Type={VersionCheckType.name(self.type)}, Version={str(self.version)}, "
f"Flags=0x{self.header.flags:08X}"
)

@classmethod
Expand Down
20 changes: 20 additions & 0 deletions spsdk/sbfile/sb2/sb_21_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
CmdLoad,
CmdMemEnable,
CmdProg,
CmdVersionCheck,
)
from spsdk.utils.crypto import KeyBlob
from spsdk.utils.misc import (
Expand Down Expand Up @@ -299,6 +300,24 @@ def _keystore_from_nv(cmd_args: dict) -> CmdKeyStoreBackup:
return CmdKeyStoreBackup(address, mem_opt)


def _version_check(cmd_args: dict) -> CmdVersionCheck:
"""Returns a CmdVersionCheck object initialized with version check type and version.
Validates version of secure or non-secure firmware.
The command fails if version is < expected.
section (0) {
version_check sec 0x2;
version_check nsec 2;
:param cmd_args: dictionary holding the version type and fw version.
:return: CmdKeyStoreRestore object.
"""
ver_type = cmd_args["ver_type"]
fw_version = cmd_args["fw_version"]
return CmdVersionCheck(ver_type, fw_version)


def _validate_keyblob(keyblobs: List, keyblob_id: Number) -> Optional[Dict]:
"""Checks, whether a keyblob is valid.
Expand Down Expand Up @@ -337,4 +356,5 @@ def _validate_keyblob(keyblobs: List, keyblob_id: Number) -> Optional[Dict]:
"keywrap": _keywrap,
"keystore_to_nv": _keystore_to_nv,
"keystore_from_nv": _keystore_from_nv,
"version_check": _version_check,
}
3 changes: 3 additions & 0 deletions spsdk/sbfile/sb2/sly_bd_lexer.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ def add_source(self, source: Variable) -> None:
"keyblob": "KEYBLOB",
"reset": "RESET",
"encrypt": "ENCRYPT",
"version_check": "VERSION_CHECK",
"sec": "SEC",
"nsec": "NSEC",
}

# List of token names. This is always required
Expand Down
43 changes: 43 additions & 0 deletions spsdk/sbfile/sb2/sly_bd_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,7 @@ def encrypt_block(self, token: YaccProduction) -> Dict: # type: ignore
"enable_stmt",
"reset_stmt",
"keystore_stmt",
"version_stmt",
)
def basic_stmt(self, token: YaccProduction) -> Dict: # type: ignore
"""Parser rule.
Expand Down Expand Up @@ -1183,6 +1184,48 @@ def mem_opt(self, token: YaccProduction) -> None: # type: ignore
"""
self.error(token, ": empty memory option is not supported.")

@_("VERSION_CHECK sec_or_nsec fw_version") # type: ignore
def version_stmt(self, token: YaccProduction) -> Dict: # type: ignore
"""Parser rule.
:param token: object holding the content defined in decorator.
:return: dictionary holding the content of version check statement.
"""
dictionary: Dict = {token.VERSION_CHECK: {}}
dictionary[token.VERSION_CHECK].update(token.sec_or_nsec)
dictionary[token.VERSION_CHECK].update(token.fw_version)
return dictionary

@_("SEC") # type: ignore
def sec_or_nsec(self, token: YaccProduction) -> Dict: # type: ignore
"""Parser rule.
:param token: object holding the content defined in decorator.
:return: dictionary holding the content of version check type.
"""
dictionary = {"ver_type": 0}
return dictionary

@_("NSEC") # type: ignore
def sec_or_nsec(self, token: YaccProduction) -> Dict: # type: ignore
"""Parser rule.
:param token: object holding the content defined in decorator.
:return: dictionary holding the content of version check type.
"""
dictionary = {"ver_type": 1}
return dictionary

@_("int_const_expr") # type: ignore
def fw_version(self, token: YaccProduction) -> Dict: # type: ignore
"""Parser rule.
:param token: object holding the content defined in decorator.
:return: dictionary holding the content of fw version.
"""
dictionary = {"fw_version": token.int_const_expr}
return dictionary

@_("IF bool_expr LBRACE statement RBRACE else_stmt") # type: ignore
def if_stmt(self, token: YaccProduction) -> List: # type: ignore
"""Parser rule.
Expand Down
4 changes: 4 additions & 0 deletions tests/elftosb/data/sb_sources/BD_files/real_example3.bd
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ sources {
myImage = "sb_sources/output_images/application_signed.bin"; // Put location of Signed or UnSigned image input
}
section (0) {
// Check FW version
version_check sec 0xafbc;
version_check nsec 1;

// FUSES: user_otp_config
// USER_BANK1_0 = 00000001
load fuse 1 > 0x01000188;
Expand Down
Binary file modified tests/elftosb/data/sb_sources/SB_files/legacy_real_example3.sb
Binary file not shown.

0 comments on commit 6fc1c7b

Please sign in to comment.