util: Improve robustness of sfdisk parsing in util/gem5img.py
authorRichard Cooper <richard.cooper@arm.com>
Fri, 21 Aug 2020 18:16:09 +0000 (19:16 +0100)
committerRichard Cooper <richard.cooper@arm.com>
Mon, 1 Feb 2021 09:48:02 +0000 (09:48 +0000)
The format of the output of sfdisk can change between versions, and
can also change depending on the details of the disk image being
analysed. For example, extra attributes like grain size in the
preamble have been observed.

The current output parsing is quite brittle, expecting a specific
number of lines of preamble. This change switches to a regular
expression based method which searches the output for the line of
interest. The parsing will still be sensitive to changes in the output
of sfdisk, but hopefully less so than the current method.

Change-Id: If03fe999a4986049ae20709895ec1d1b42166023
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/39896
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
Maintainer: Jason Lowe-Power <power.jg@gmail.com>

util/gem5img.py

index 26f398e57ee6ee66aafb2a16fce13a533d1a9b2f..616dd7259bda00c3cee2f0ef1849ee3315f31254 100755 (executable)
@@ -2,6 +2,18 @@
 #
 # Copyright 2020 Google, Inc.
 #
+# Copyright (c) 2020 ARM Limited
+# All rights reserved
+#
+# The license below extends only to copyright in the software and shall
+# not be construed as granting a license to any other intellectual
+# property including but not limited to intellectual property relating
+# to a hardware implementation of the functionality of the software
+# licensed hereunder.  You may use the software subject to the license
+# terms below provided that you ensure that this notice is replicated
+# unmodified and in its entirety in all distributions of the software,
+# modified or unmodified, in source code or in binary form.
+#
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions are
 # met: redistributions of source code must retain the above copyright
@@ -36,7 +48,7 @@ from os import environ as env
 import string
 from subprocess import CalledProcessError, Popen, PIPE, STDOUT
 from sys import exit, argv
-
+import re
 
 # Some constants.
 MaxLBACylinders = 16383
@@ -159,22 +171,31 @@ def findPartOffset(devFile, fileName, partition):
     if returncode != 0:
         print(out)
         exit(returncode)
+
+    # Parse each line of the sfdisk output looking for the first
+    # partition description.
+    SFDISK_PARTITION_INFO_RE = re.compile(
+        r"^\s*"                        # Start of line
+        r"(?P<name>\S+)"               # Name
+        r"\s*:\s*"                     # Separator
+        r"start=\s*(?P<start>\d+),\s*" # Partition start record
+        r"size=\s*(?P<size>\d+),\s*"   # Partition size record
+        r"type=(?P<type>\d+)"          # Partition type record
+        r"\s*$"                        # End of line
+    )
     lines = out.splitlines()
-    # Make sure the first few lines of the output look like what we expect.
-    assert(lines[0][0] == '#' or lines[0].startswith('label:'))
-    assert(lines[1] == 'unit: sectors' or lines[1].startswith('label-id:'))
-    assert(lines[2] == '' or lines[2].startswith('device:'))
-    if lines[0][0] == '#' :
-        # Parsing an 'old style' dump oputput
-        # Line 4 has information about the first partition.
-        chunks = lines[3].split()
-    else :
-        # Parsing a 'new style' dump oputput
-        # Line 6 has information about the first partition.
-        chunks = lines[5].split()
-    # The fourth chunk is the offset of the partition in sectors followed by
-    # a comma. We drop the comma and convert that to an integer.
-    sectors = int(chunks[3][:-1])
+    for line in lines :
+        match = SFDISK_PARTITION_INFO_RE.match(line)
+        if match:
+            sectors = int(match.group("start"))
+            break
+    else:
+        # No partition description was found
+        print("No partition description was found in sfdisk output:")
+        print("\n".join("  {}".format(line.rstrip()) for line in lines))
+        print("Could not determine size of first partition.")
+        exit(1)
+
     # Free the loopback device and return an answer.
     dev.destroy()
     return sectors * BlockSize