diff --git a/docs/en/espefuse/summary-cmd.rst b/docs/en/espefuse/summary-cmd.rst index 5e5d46962..195083ebd 100644 --- a/docs/en/espefuse/summary-cmd.rst +++ b/docs/en/espefuse/summary-cmd.rst @@ -3,12 +3,16 @@ Summary ======= -The ``espefuse.py summary`` command reads all eFuses from the chip and outputs them in text or json format. It is also possible to save it to a file. +The ``espefuse.py summary`` command reads the eFuses from the chip and outputs them in text or json format. It is also possible to save it to a file. The command also supports eFuse filtering by name. Optional arguments: -- ``--format`` - Select the summary format: ``summary`` - text format (default option), ``json`` - json format. Usage ``--format json``. +- ``--format`` - Select the summary format: + - ``summary`` - text format (default option). + - ``json`` - json format. Usage ``--format json``. + - ``value_only`` - only the value of the eFuse specified as an argument will be displayed. For more information, refer to the :ref:`Filtering eFuses ` section. - ``--file`` - File to save the efuse summary. Usage ``--file efuses.json``. +- List of eFuses to filter. For more information, refer to the :ref:`Filtering eFuses ` section. Text Format Summary ------------------- @@ -112,3 +116,31 @@ Save Json Format Summary To File === Run "summary" command === Saving efuse values to efuses.json + +.. _filtering-eFuses: + +Filtering Efuses and Displaying Only the Value +---------------------------------------------- + +The ``espefuse.py summary`` command supports filtering eFuses by name. The eFuses to filter needs to be specified as positional arguments. If no eFuses are specified, complete summary will be displayed. Example: + +.. code-block:: none + + > espefuse.py summary ABS_DONE_0 BLOCK1 + + === Run "summary" command === + EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value) + ---------------------------------------------------------------------------------------- + Security fuses: + ABS_DONE_0 (BLOCK0) Secure boot V1 is enabled for bootloader image = False R/W (0b0) + BLOCK1 (BLOCK1) Flash encryption key + = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W + +If ``--format value_only`` is specified, only the value of the eFuse specified as an argument will be displayed. Only one eFuse can be specified as an argument for this format. Example: + +.. code-block:: none + + > espefuse.py summary --format value_only MAC + + === Run "summary" command === + 00:00:00:00:00:00 (CRC 0x00 OK) diff --git a/espefuse/efuse/base_operations.py b/espefuse/efuse/base_operations.py index ccf7efe21..8ee667810 100644 --- a/espefuse/efuse/base_operations.py +++ b/espefuse/efuse/base_operations.py @@ -182,7 +182,7 @@ def check_efuse_name(efuse_name, efuse_list): summary_cmd.add_argument( "--format", help="Select the summary format", - choices=["summary", "json"], + choices=["summary", "json", "value_only"], default="summary", ) summary_cmd.add_argument( @@ -191,6 +191,11 @@ def check_efuse_name(efuse_name, efuse_list): type=argparse.FileType("w"), default=sys.stdout, ) + summary_cmd.add_argument( + "efuses_to_show", + help="The efuses to show. If not provided, all efuses will be shown.", + nargs="*", + ) execute_scripts = subparsers.add_parser( "execute_scripts", help="Executes scripts to burn at one time." @@ -245,14 +250,21 @@ def add_show_sensitive_info_option(p): def summary(esp, efuses, args): - """Print a human-readable summary of efuse contents""" + """Print a human-readable or json summary of efuse contents""" ROW_FORMAT = "%-50s %-50s%s = %s %s %s" - human_output = args.format == "summary" + human_output = args.format in ["summary", "value_only"] + value_only = args.format == "value_only" + if value_only and len(args.efuses_to_show) != 1: + raise esptool.FatalError( + "The 'value_only' format can be used exactly for one efuse." + ) + do_filtering = bool(args.efuses_to_show) json_efuse = {} + summary_efuse = [] if args.file != sys.stdout: print("Saving efuse values to " + args.file.name) - if human_output: - print( + if human_output and not value_only: + summary_efuse.append( ROW_FORMAT.replace("-50", "-12") % ( "EFUSE_NAME (Block)", @@ -261,13 +273,12 @@ def summary(esp, efuses, args): "[Meaningful Value]", "[Readable/Writeable]", "(Hex Value)", - ), - file=args.file, + ) ) - print("-" * 88, file=args.file) + summary_efuse.append("-" * 88) for category in sorted(set(e.category for e in efuses), key=lambda c: c.title()): - if human_output: - print("%s fuses:" % category.title(), file=args.file) + if human_output and not value_only: + summary_efuse.append(f"{category.title()} fuses:") for e in (e for e in efuses if e.category == category): if e.efuse_type.startswith("bytes"): raw = "" @@ -296,8 +307,12 @@ def summary(esp, efuses, args): value = "".join(v) else: value = value.replace("0", "?") - if human_output: - print( + if ( + human_output + and (not do_filtering or e.name in args.efuses_to_show) + and not value_only + ): + summary_efuse.append( ROW_FORMAT % ( e.get_info(), @@ -306,18 +321,20 @@ def summary(esp, efuses, args): value, perms, raw, - ), - file=args.file, + ) ) desc_len = len(e.description[50:]) if desc_len: desc_len += 50 for i in range(50, desc_len, 50): - print( - "%-50s %-50s" % ("", e.description[i : (50 + i)]), - file=args.file, + summary_efuse.append( + f"{'':<50} {e.description[i : (50 + i)]:<50}" ) - if args.format == "json": + elif human_output and value_only and e.name in args.efuses_to_show: + summary_efuse.append(f"{value}") + elif args.format == "json" and ( + not do_filtering or e.name in args.efuses_to_show + ): json_efuse[e.name] = { "name": e.name, "value": base_value if readable else value, @@ -331,19 +348,26 @@ def summary(esp, efuses, args): "efuse_type": e.efuse_type, "bit_len": e.bit_len, } - if human_output: - print("", file=args.file) - if human_output: - print(efuses.summary(), file=args.file) + if human_output and not value_only: + # Remove empty category if efuses are filtered and there are none to show + if do_filtering and summary_efuse[-1] == f"{category.title()} fuses:": + summary_efuse.pop() + else: + summary_efuse.append("") + if human_output and not value_only: + summary_efuse.append(efuses.summary()) warnings = efuses.get_coding_scheme_warnings() if warnings: - print( - "WARNING: Coding scheme has encoding bit error warnings", file=args.file + summary_efuse.append( + "WARNING: Coding scheme has encoding bit error warnings" ) + if human_output: + for line in summary_efuse: + print(line, file=args.file) if args.file != sys.stdout: args.file.close() print("Done") - if args.format == "json": + elif args.format == "json": json.dump(json_efuse, args.file, sort_keys=True, indent=4) print("") diff --git a/test/test_espefuse.py b/test/test_espefuse.py index 78ddffeef..2388dc94f 100755 --- a/test/test_espefuse.py +++ b/test/test_espefuse.py @@ -184,6 +184,15 @@ def test_summary(self): def test_summary_json(self): self.espefuse_py("summary --format json") + def test_summary_filter(self): + self.espefuse_py("summary MAC") + self.espefuse_py("summary --format value_only MAC") + self.espefuse_py( + "summary --format value_only MAC WR_DIS", + check_msg="The 'value_only' format can be used exactly for one efuse.", + ret_code=2, + ) + @pytest.mark.skipif( arg_chip == "esp32p4", reason="No Custom MAC Address defined yet" )