partition_table: Extend the get_partition_info command

A manufactory tool needs to retrieve info about partitions.  With a new flag - "--part_list" we can get a list of partitions with the same type/subtype and easily iterate by it.

- name and flag arguments
- added flag "--part_list" to get a list of partitions with the same type/subtype
- save prev behavior of the get_partition_info command (return the only first item)
- added host test
This commit is contained in:
KonstantinKondrashov 2020-10-01 15:10:00 +08:00
parent 48baf1294a
commit 55dc1524ee
4 changed files with 64 additions and 26 deletions

View File

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

View File

@ -44,10 +44,11 @@ def status(msg):
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.type = type
self.type = p_type
self.subtype = subtype
self.part_list = part_list
class PartitionName(_PartitionId):
@ -58,8 +59,8 @@ class PartitionName(_PartitionId):
class PartitionType(_PartitionId):
def __init__(self, type, subtype):
_PartitionId.__init__(self, type=type, subtype=subtype)
def __init__(self, p_type, subtype, part_list):
_PartitionId.__init__(self, p_type=p_type, subtype=subtype, part_list=part_list)
PARTITION_BOOT_DEFAULT = _PartitionId()
@ -144,11 +145,13 @@ class ParttoolTarget():
if partition_id.name:
partition = self.partition_table.find_by_name(partition_id.name)
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
search = ["factory"] + ["ota_{}".format(d) for d in range(16)]
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:
break
@ -200,20 +203,24 @@ def _erase_partition(target, partition_id):
def _get_partition_info(target, partition_id, info):
try:
partition = target.get_partition_info(partition_id)
partitions = target.get_partition_info(partition_id)
if not isinstance(partitions, list):
partitions = [partitions]
except Exception:
return
info_dict = {
"offset": '0x{:x}'.format(partition.offset),
"size": '0x{:x}'.format(partition.size)
}
infos = []
try:
for i in info:
infos += [info_dict[i]]
for p in partitions:
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:
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.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()
quiet = args.quiet
@ -286,7 +294,7 @@ def main():
elif args.partition_type:
if not args.partition_subtype:
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:
partition_id = PARTITION_BOOT_DEFAULT
else:

View File

@ -8,7 +8,6 @@ import subprocess
import tempfile
import os
import io
import re
try:
import gen_esp32part
@ -412,17 +411,20 @@ class PartToolTests(Py23TestCase):
csvpath, "get_partition_info"] + args,
stderr=subprocess.STDOUT)
self.assertNotIn(b"WARNING", output)
m = re.search(b"0x[0-9a-fA-F]+", output)
return m.group(0) if m else ""
return output.strip()
finally:
os.remove(csvpath)
def test_find_basic(self):
csv = """
nvs, data, nvs, 0x9000, 0x4000
otadata, data, ota, 0xd000, 0x2000
phy_init, data, phy, 0xf000, 0x1000
factory, app, factory, 0x10000, 1M
nvs, data, nvs, 0x9000, 0x4000
otadata, data, ota, 0xd000, 0x2000
phy_init, data, phy, 0xf000, 0x1000
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):
@ -436,6 +438,34 @@ factory, app, factory, 0x10000, 1M
rpt(["--partition-name", "otadata", "--info", "offset"]), b"0xd000")
self.assertEqual(
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):
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)
- writing the contents of a file to a partition (write_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
and command-line interface, respectively.