Merge branch 'feature/parttool_add_options_to_info_cmd' into 'master'

partition_table: Extend the get_partition_info command

See merge request espressif/esp-idf!10537
This commit is contained in:
Angus Gratton
2020-10-06 07:35:32 +08:00
4 changed files with 64 additions and 26 deletions

View File

@@ -166,8 +166,8 @@ class PartitionTable(list):
for p in self: for p in self:
if p.type == ptype and p.subtype == subtype: if p.type == ptype and p.subtype == subtype:
return p yield p
return None return
def find_by_name(self, name): def find_by_name(self, name):
for p in self: for p in self:

View File

@@ -44,10 +44,11 @@ def status(msg):
class _PartitionId(): class _PartitionId():
def __init__(self, name=None, type=None, subtype=None): def __init__(self, name=None, p_type=None, subtype=None, part_list=None):
self.name = name self.name = name
self.type = type self.type = p_type
self.subtype = subtype self.subtype = subtype
self.part_list = part_list
class PartitionName(_PartitionId): class PartitionName(_PartitionId):
@@ -58,8 +59,8 @@ class PartitionName(_PartitionId):
class PartitionType(_PartitionId): class PartitionType(_PartitionId):
def __init__(self, type, subtype): def __init__(self, p_type, subtype, part_list):
_PartitionId.__init__(self, type=type, subtype=subtype) _PartitionId.__init__(self, p_type=p_type, subtype=subtype, part_list=part_list)
PARTITION_BOOT_DEFAULT = _PartitionId() PARTITION_BOOT_DEFAULT = _PartitionId()
@@ -144,11 +145,13 @@ class ParttoolTarget():
if partition_id.name: if partition_id.name:
partition = self.partition_table.find_by_name(partition_id.name) partition = self.partition_table.find_by_name(partition_id.name)
elif partition_id.type and partition_id.subtype: elif partition_id.type and partition_id.subtype:
partition = self.partition_table.find_by_type(partition_id.type, partition_id.subtype) partition = list(self.partition_table.find_by_type(partition_id.type, partition_id.subtype))
if not partition_id.part_list:
partition = partition[0]
else: # default boot partition else: # default boot partition
search = ["factory"] + ["ota_{}".format(d) for d in range(16)] search = ["factory"] + ["ota_{}".format(d) for d in range(16)]
for subtype in search: for subtype in search:
partition = self.partition_table.find_by_type("app", subtype) partition = next(self.partition_table.find_by_type("app", subtype), None)
if partition: if partition:
break break
@@ -200,20 +203,24 @@ def _erase_partition(target, partition_id):
def _get_partition_info(target, partition_id, info): def _get_partition_info(target, partition_id, info):
try: try:
partition = target.get_partition_info(partition_id) partitions = target.get_partition_info(partition_id)
if not isinstance(partitions, list):
partitions = [partitions]
except Exception: except Exception:
return return
info_dict = {
"offset": '0x{:x}'.format(partition.offset),
"size": '0x{:x}'.format(partition.size)
}
infos = [] infos = []
try: try:
for i in info: for p in partitions:
infos += [info_dict[i]] info_dict = {
"name": '{}'.format(p.name),
"offset": '0x{:x}'.format(p.offset),
"size": '0x{:x}'.format(p.size),
"encrypted": '{}'.format(p.encrypted)
}
for i in info:
infos += [info_dict[i]]
except KeyError: except KeyError:
raise RuntimeError("Request for unknown partition info {}".format(i)) raise RuntimeError("Request for unknown partition info {}".format(i))
@@ -269,7 +276,8 @@ def main():
print_partition_info_subparser = subparsers.add_parser("get_partition_info", help="get partition information", parents=[partition_selection_parser]) print_partition_info_subparser = subparsers.add_parser("get_partition_info", help="get partition information", parents=[partition_selection_parser])
print_partition_info_subparser.add_argument("--info", help="type of partition information to get", print_partition_info_subparser.add_argument("--info", help="type of partition information to get",
choices=["offset", "size"], default=["offset", "size"], nargs="+") choices=["name", "offset", "size", "encrypted"], default=["offset", "size"], nargs="+")
print_partition_info_subparser.add_argument('--part_list', help="Get a list of partitions suitable for a given type", action='store_true')
args = parser.parse_args() args = parser.parse_args()
quiet = args.quiet quiet = args.quiet
@@ -286,7 +294,7 @@ def main():
elif args.partition_type: elif args.partition_type:
if not args.partition_subtype: if not args.partition_subtype:
raise RuntimeError("--partition-subtype should be defined when --partition-type is defined") raise RuntimeError("--partition-subtype should be defined when --partition-type is defined")
partition_id = PartitionType(args.partition_type, args.partition_subtype) partition_id = PartitionType(args.partition_type, args.partition_subtype, args.part_list)
elif args.partition_boot_default: elif args.partition_boot_default:
partition_id = PARTITION_BOOT_DEFAULT partition_id = PARTITION_BOOT_DEFAULT
else: else:

View File

@@ -8,7 +8,6 @@ import subprocess
import tempfile import tempfile
import os import os
import io import io
import re
try: try:
import gen_esp32part import gen_esp32part
@@ -412,17 +411,20 @@ class PartToolTests(Py23TestCase):
csvpath, "get_partition_info"] + args, csvpath, "get_partition_info"] + args,
stderr=subprocess.STDOUT) stderr=subprocess.STDOUT)
self.assertNotIn(b"WARNING", output) self.assertNotIn(b"WARNING", output)
m = re.search(b"0x[0-9a-fA-F]+", output) return output.strip()
return m.group(0) if m else ""
finally: finally:
os.remove(csvpath) os.remove(csvpath)
def test_find_basic(self): def test_find_basic(self):
csv = """ csv = """
nvs, data, nvs, 0x9000, 0x4000 nvs, data, nvs, 0x9000, 0x4000
otadata, data, ota, 0xd000, 0x2000 otadata, data, ota, 0xd000, 0x2000
phy_init, data, phy, 0xf000, 0x1000 phy_init, data, phy, 0xf000, 0x1000
factory, app, factory, 0x10000, 1M factory, app, factory, 0x10000, 1M
nvs1_user, data, nvs, 0x110000, 0x4000
nvs2_user, data, nvs, 0x114000, 0x4000
nvs_key1, data, nvs_keys, 0x118000, 0x1000, encrypted
nvs_key2, data, nvs_keys, 0x119000, 0x1000, encrypted
""" """
def rpt(args): def rpt(args):
@@ -436,6 +438,34 @@ factory, app, factory, 0x10000, 1M
rpt(["--partition-name", "otadata", "--info", "offset"]), b"0xd000") rpt(["--partition-name", "otadata", "--info", "offset"]), b"0xd000")
self.assertEqual( self.assertEqual(
rpt(["--partition-boot-default", "--info", "offset"]), b"0x10000") rpt(["--partition-boot-default", "--info", "offset"]), b"0x10000")
self.assertEqual(
rpt(["--partition-type", "data", "--partition-subtype", "nvs", "--info", "name", "offset", "size", "encrypted"]),
b"nvs 0x9000 0x4000 False")
self.assertEqual(
rpt(["--partition-type", "data", "--partition-subtype", "nvs", "--info", "name", "offset", "size", "encrypted", "--part_list"]),
b"nvs 0x9000 0x4000 False nvs1_user 0x110000 0x4000 False nvs2_user 0x114000 0x4000 False")
self.assertEqual(
rpt(["--partition-type", "data", "--partition-subtype", "nvs", "--info", "name", "--part_list"]),
b"nvs nvs1_user nvs2_user")
self.assertEqual(
rpt(["--partition-type", "data", "--partition-subtype", "nvs_keys", "--info", "name", "--part_list"]),
b"nvs_key1 nvs_key2")
self.assertEqual(
rpt(["--partition-name", "nvs", "--info", "encrypted"]), b"False")
self.assertEqual(
rpt(["--partition-name", "nvs1_user", "--info", "encrypted"]), b"False")
self.assertEqual(
rpt(["--partition-name", "nvs2_user", "--info", "encrypted"]), b"False")
self.assertEqual(
rpt(["--partition-name", "nvs_key1", "--info", "encrypted"]), b"True")
self.assertEqual(
rpt(["--partition-name", "nvs_key2", "--info", "encrypted"]), b"True")
self.assertEqual(
rpt(["--partition-type", "data", "--partition-subtype", "nvs_keys", "--info", "name", "encrypted", "--part_list"]),
b"nvs_key1 True nvs_key2 True")
self.assertEqual(
rpt(["--partition-type", "data", "--partition-subtype", "nvs", "--info", "name", "encrypted", "--part_list"]),
b"nvs False nvs1_user False nvs2_user False")
def test_fallback(self): def test_fallback(self):
csv = """ csv = """

View File

@@ -191,7 +191,7 @@ The component `partition_table` provides a tool :component_file:`parttool.py<par
- reading a partition and saving the contents to a file (read_partition) - reading a partition and saving the contents to a file (read_partition)
- writing the contents of a file to a partition (write_partition) - writing the contents of a file to a partition (write_partition)
- erasing a partition (erase_partition) - erasing a partition (erase_partition)
- retrieving info such as offset and size of a given partition (get_partition_info) - retrieving info such as name, offset, size and flag ("encrypted") of a given partition (get_partition_info)
The tool can either be imported and used from another Python script or invoked from shell script for users wanting to perform operation programmatically. This is facilitated by the tool's Python API The tool can either be imported and used from another Python script or invoked from shell script for users wanting to perform operation programmatically. This is facilitated by the tool's Python API
and command-line interface, respectively. and command-line interface, respectively.