xref: /openbmc/qemu/tests/qemu-iotests/qcow2.py (revision d5262c712488674fba74a749e81894e098226bfa)
1903cb1bfSPhilippe Mathieu-Daudé#!/usr/bin/env python3
216306a7bSVladimir Sementsov-Ogievskiy#
316306a7bSVladimir Sementsov-Ogievskiy# Manipulations with qcow2 image
416306a7bSVladimir Sementsov-Ogievskiy#
516306a7bSVladimir Sementsov-Ogievskiy# This program is free software; you can redistribute it and/or modify
616306a7bSVladimir Sementsov-Ogievskiy# it under the terms of the GNU General Public License as published by
716306a7bSVladimir Sementsov-Ogievskiy# the Free Software Foundation; either version 2 of the License, or
816306a7bSVladimir Sementsov-Ogievskiy# (at your option) any later version.
916306a7bSVladimir Sementsov-Ogievskiy#
1016306a7bSVladimir Sementsov-Ogievskiy# This program is distributed in the hope that it will be useful,
1116306a7bSVladimir Sementsov-Ogievskiy# but WITHOUT ANY WARRANTY; without even the implied warranty of
1216306a7bSVladimir Sementsov-Ogievskiy# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1316306a7bSVladimir Sementsov-Ogievskiy# GNU General Public License for more details.
1416306a7bSVladimir Sementsov-Ogievskiy#
1516306a7bSVladimir Sementsov-Ogievskiy# You should have received a copy of the GNU General Public License
1616306a7bSVladimir Sementsov-Ogievskiy# along with this program.  If not, see <http://www.gnu.org/licenses/>.
1716306a7bSVladimir Sementsov-Ogievskiy#
186e19b3c4SKevin Wolf
196e19b3c4SKevin Wolfimport sys
206e19b3c4SKevin Wolf
21*d5262c71SVladimir Sementsov-Ogievskiyfrom qcow2_format import (
22*d5262c71SVladimir Sementsov-Ogievskiy    QcowHeader,
23*d5262c71SVladimir Sementsov-Ogievskiy    QcowHeaderExtension
24*d5262c71SVladimir Sementsov-Ogievskiy)
256e19b3c4SKevin Wolf
266e19b3c4SKevin Wolf
276e19b3c4SKevin Wolfdef cmd_dump_header(fd):
286e19b3c4SKevin Wolf    h = QcowHeader(fd)
296e19b3c4SKevin Wolf    h.dump()
306e19b3c4SKevin Wolf    h.dump_extensions()
316e19b3c4SKevin Wolf
3202756054SVladimir Sementsov-Ogievskiy
331aa6630eSMax Reitzdef cmd_dump_header_exts(fd):
341aa6630eSMax Reitz    h = QcowHeader(fd)
351aa6630eSMax Reitz    h.dump_extensions()
361aa6630eSMax Reitz
3702756054SVladimir Sementsov-Ogievskiy
38c93331c9SKevin Wolfdef cmd_set_header(fd, name, value):
39c93331c9SKevin Wolf    try:
40c93331c9SKevin Wolf        value = int(value, 0)
4102756054SVladimir Sementsov-Ogievskiy    except ValueError:
42f03868bdSEduardo Habkost        print("'%s' is not a valid number" % value)
43c93331c9SKevin Wolf        sys.exit(1)
44c93331c9SKevin Wolf
45c93331c9SKevin Wolf    fields = (field[2] for field in QcowHeader.fields)
4602756054SVladimir Sementsov-Ogievskiy    if name not in fields:
47f03868bdSEduardo Habkost        print("'%s' is not a known header field" % name)
48c93331c9SKevin Wolf        sys.exit(1)
49c93331c9SKevin Wolf
50c93331c9SKevin Wolf    h = QcowHeader(fd)
51c93331c9SKevin Wolf    h.__dict__[name] = value
52c93331c9SKevin Wolf    h.update(fd)
53c93331c9SKevin Wolf
5402756054SVladimir Sementsov-Ogievskiy
556e19b3c4SKevin Wolfdef cmd_add_header_ext(fd, magic, data):
566e19b3c4SKevin Wolf    try:
576e19b3c4SKevin Wolf        magic = int(magic, 0)
5802756054SVladimir Sementsov-Ogievskiy    except ValueError:
59f03868bdSEduardo Habkost        print("'%s' is not a valid magic number" % magic)
606e19b3c4SKevin Wolf        sys.exit(1)
616e19b3c4SKevin Wolf
626e19b3c4SKevin Wolf    h = QcowHeader(fd)
6302756054SVladimir Sementsov-Ogievskiy    h.extensions.append(QcowHeaderExtension.create(magic,
6402756054SVladimir Sementsov-Ogievskiy                                                   data.encode('ascii')))
656e19b3c4SKevin Wolf    h.update(fd)
666e19b3c4SKevin Wolf
6702756054SVladimir Sementsov-Ogievskiy
6812ac6d3dSKevin Wolfdef cmd_add_header_ext_stdio(fd, magic):
6912ac6d3dSKevin Wolf    data = sys.stdin.read()
7012ac6d3dSKevin Wolf    cmd_add_header_ext(fd, magic, data)
7112ac6d3dSKevin Wolf
7202756054SVladimir Sementsov-Ogievskiy
736e19b3c4SKevin Wolfdef cmd_del_header_ext(fd, magic):
746e19b3c4SKevin Wolf    try:
756e19b3c4SKevin Wolf        magic = int(magic, 0)
7602756054SVladimir Sementsov-Ogievskiy    except ValueError:
77f03868bdSEduardo Habkost        print("'%s' is not a valid magic number" % magic)
786e19b3c4SKevin Wolf        sys.exit(1)
796e19b3c4SKevin Wolf
806e19b3c4SKevin Wolf    h = QcowHeader(fd)
816e19b3c4SKevin Wolf    found = False
826e19b3c4SKevin Wolf
836e19b3c4SKevin Wolf    for ex in h.extensions:
846e19b3c4SKevin Wolf        if ex.magic == magic:
856e19b3c4SKevin Wolf            found = True
866e19b3c4SKevin Wolf            h.extensions.remove(ex)
876e19b3c4SKevin Wolf
886e19b3c4SKevin Wolf    if not found:
89f03868bdSEduardo Habkost        print("No such header extension")
906e19b3c4SKevin Wolf        return
916e19b3c4SKevin Wolf
926e19b3c4SKevin Wolf    h.update(fd)
936e19b3c4SKevin Wolf
9402756054SVladimir Sementsov-Ogievskiy
951b2eff62SStefan Hajnoczidef cmd_set_feature_bit(fd, group, bit):
961b2eff62SStefan Hajnoczi    try:
971b2eff62SStefan Hajnoczi        bit = int(bit, 0)
981b2eff62SStefan Hajnoczi        if bit < 0 or bit >= 64:
991b2eff62SStefan Hajnoczi            raise ValueError
10002756054SVladimir Sementsov-Ogievskiy    except ValueError:
101f03868bdSEduardo Habkost        print("'%s' is not a valid bit number in range [0, 64)" % bit)
1021b2eff62SStefan Hajnoczi        sys.exit(1)
1031b2eff62SStefan Hajnoczi
1041b2eff62SStefan Hajnoczi    h = QcowHeader(fd)
1051b2eff62SStefan Hajnoczi    if group == 'incompatible':
1061b2eff62SStefan Hajnoczi        h.incompatible_features |= 1 << bit
1071b2eff62SStefan Hajnoczi    elif group == 'compatible':
1081b2eff62SStefan Hajnoczi        h.compatible_features |= 1 << bit
1091b2eff62SStefan Hajnoczi    elif group == 'autoclear':
1101b2eff62SStefan Hajnoczi        h.autoclear_features |= 1 << bit
1111b2eff62SStefan Hajnoczi    else:
11202756054SVladimir Sementsov-Ogievskiy        print("'%s' is not a valid group, try "
11302756054SVladimir Sementsov-Ogievskiy              "'incompatible', 'compatible', or 'autoclear'" % group)
1141b2eff62SStefan Hajnoczi        sys.exit(1)
1151b2eff62SStefan Hajnoczi
1161b2eff62SStefan Hajnoczi    h.update(fd)
1171b2eff62SStefan Hajnoczi
11802756054SVladimir Sementsov-Ogievskiy
1196e19b3c4SKevin Wolfcmds = [
12002756054SVladimir Sementsov-Ogievskiy    ['dump-header', cmd_dump_header, 0,
12102756054SVladimir Sementsov-Ogievskiy     'Dump image header and header extensions'],
12202756054SVladimir Sementsov-Ogievskiy    ['dump-header-exts', cmd_dump_header_exts, 0,
12302756054SVladimir Sementsov-Ogievskiy     'Dump image header extensions'],
124c93331c9SKevin Wolf    ['set-header', cmd_set_header, 2, 'Set a field in the header'],
1256e19b3c4SKevin Wolf    ['add-header-ext', cmd_add_header_ext, 2, 'Add a header extension'],
12602756054SVladimir Sementsov-Ogievskiy    ['add-header-ext-stdio', cmd_add_header_ext_stdio, 1,
12702756054SVladimir Sementsov-Ogievskiy     'Add a header extension, data from stdin'],
1286e19b3c4SKevin Wolf    ['del-header-ext', cmd_del_header_ext, 1, 'Delete a header extension'],
1291b2eff62SStefan Hajnoczi    ['set-feature-bit', cmd_set_feature_bit, 2, 'Set a feature bit'],
1306e19b3c4SKevin Wolf]
1316e19b3c4SKevin Wolf
13202756054SVladimir Sementsov-Ogievskiy
1336e19b3c4SKevin Wolfdef main(filename, cmd, args):
1346e19b3c4SKevin Wolf    fd = open(filename, "r+b")
1356e19b3c4SKevin Wolf    try:
1366e19b3c4SKevin Wolf        for name, handler, num_args, desc in cmds:
1376e19b3c4SKevin Wolf            if name != cmd:
1386e19b3c4SKevin Wolf                continue
1396e19b3c4SKevin Wolf            elif len(args) != num_args:
1406e19b3c4SKevin Wolf                usage()
1416e19b3c4SKevin Wolf                return
1426e19b3c4SKevin Wolf            else:
1436e19b3c4SKevin Wolf                handler(fd, *args)
1446e19b3c4SKevin Wolf                return
145f03868bdSEduardo Habkost        print("Unknown command '%s'" % cmd)
1466e19b3c4SKevin Wolf    finally:
1476e19b3c4SKevin Wolf        fd.close()
1486e19b3c4SKevin Wolf
14902756054SVladimir Sementsov-Ogievskiy
1506e19b3c4SKevin Wolfdef usage():
151f03868bdSEduardo Habkost    print("Usage: %s <file> <cmd> [<arg>, ...]" % sys.argv[0])
152f03868bdSEduardo Habkost    print("")
153f03868bdSEduardo Habkost    print("Supported commands:")
1546e19b3c4SKevin Wolf    for name, handler, num_args, desc in cmds:
155f03868bdSEduardo Habkost        print("    %-20s - %s" % (name, desc))
1566e19b3c4SKevin Wolf
15702756054SVladimir Sementsov-Ogievskiy
158d2ef210cSKevin Wolfif __name__ == '__main__':
1596e19b3c4SKevin Wolf    if len(sys.argv) < 3:
1606e19b3c4SKevin Wolf        usage()
1616e19b3c4SKevin Wolf        sys.exit(1)
1626e19b3c4SKevin Wolf
1636e19b3c4SKevin Wolf    main(sys.argv[1], sys.argv[2], sys.argv[3:])
164