xref: /openbmc/qemu/tests/qemu-iotests/qcow2.py (revision eeafed5f6e76a98d3b640f003b96b1490d2281b1)
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
21d5262c71SVladimir Sementsov-Ogievskiyfrom qcow2_format import (
22d5262c71SVladimir Sementsov-Ogievskiy    QcowHeader,
23d5262c71SVladimir Sementsov-Ogievskiy    QcowHeaderExtension
24d5262c71SVladimir Sementsov-Ogievskiy)
256e19b3c4SKevin Wolf
266e19b3c4SKevin Wolf
276e19b3c4SKevin Wolfdef cmd_dump_header(fd):
286e19b3c4SKevin Wolf    h = QcowHeader(fd)
296e19b3c4SKevin Wolf    h.dump()
30*eeafed5fSVladimir Sementsov-Ogievskiy    print()
316e19b3c4SKevin Wolf    h.dump_extensions()
326e19b3c4SKevin Wolf
3302756054SVladimir Sementsov-Ogievskiy
341aa6630eSMax Reitzdef cmd_dump_header_exts(fd):
351aa6630eSMax Reitz    h = QcowHeader(fd)
361aa6630eSMax Reitz    h.dump_extensions()
371aa6630eSMax Reitz
3802756054SVladimir Sementsov-Ogievskiy
39c93331c9SKevin Wolfdef cmd_set_header(fd, name, value):
40c93331c9SKevin Wolf    try:
41c93331c9SKevin Wolf        value = int(value, 0)
4202756054SVladimir Sementsov-Ogievskiy    except ValueError:
43f03868bdSEduardo Habkost        print("'%s' is not a valid number" % value)
44c93331c9SKevin Wolf        sys.exit(1)
45c93331c9SKevin Wolf
46c93331c9SKevin Wolf    fields = (field[2] for field in QcowHeader.fields)
4702756054SVladimir Sementsov-Ogievskiy    if name not in fields:
48f03868bdSEduardo Habkost        print("'%s' is not a known header field" % name)
49c93331c9SKevin Wolf        sys.exit(1)
50c93331c9SKevin Wolf
51c93331c9SKevin Wolf    h = QcowHeader(fd)
52c93331c9SKevin Wolf    h.__dict__[name] = value
53c93331c9SKevin Wolf    h.update(fd)
54c93331c9SKevin Wolf
5502756054SVladimir Sementsov-Ogievskiy
566e19b3c4SKevin Wolfdef cmd_add_header_ext(fd, magic, data):
576e19b3c4SKevin Wolf    try:
586e19b3c4SKevin Wolf        magic = int(magic, 0)
5902756054SVladimir Sementsov-Ogievskiy    except ValueError:
60f03868bdSEduardo Habkost        print("'%s' is not a valid magic number" % magic)
616e19b3c4SKevin Wolf        sys.exit(1)
626e19b3c4SKevin Wolf
636e19b3c4SKevin Wolf    h = QcowHeader(fd)
6402756054SVladimir Sementsov-Ogievskiy    h.extensions.append(QcowHeaderExtension.create(magic,
6502756054SVladimir Sementsov-Ogievskiy                                                   data.encode('ascii')))
666e19b3c4SKevin Wolf    h.update(fd)
676e19b3c4SKevin Wolf
6802756054SVladimir Sementsov-Ogievskiy
6912ac6d3dSKevin Wolfdef cmd_add_header_ext_stdio(fd, magic):
7012ac6d3dSKevin Wolf    data = sys.stdin.read()
7112ac6d3dSKevin Wolf    cmd_add_header_ext(fd, magic, data)
7212ac6d3dSKevin Wolf
7302756054SVladimir Sementsov-Ogievskiy
746e19b3c4SKevin Wolfdef cmd_del_header_ext(fd, magic):
756e19b3c4SKevin Wolf    try:
766e19b3c4SKevin Wolf        magic = int(magic, 0)
7702756054SVladimir Sementsov-Ogievskiy    except ValueError:
78f03868bdSEduardo Habkost        print("'%s' is not a valid magic number" % magic)
796e19b3c4SKevin Wolf        sys.exit(1)
806e19b3c4SKevin Wolf
816e19b3c4SKevin Wolf    h = QcowHeader(fd)
826e19b3c4SKevin Wolf    found = False
836e19b3c4SKevin Wolf
846e19b3c4SKevin Wolf    for ex in h.extensions:
856e19b3c4SKevin Wolf        if ex.magic == magic:
866e19b3c4SKevin Wolf            found = True
876e19b3c4SKevin Wolf            h.extensions.remove(ex)
886e19b3c4SKevin Wolf
896e19b3c4SKevin Wolf    if not found:
90f03868bdSEduardo Habkost        print("No such header extension")
916e19b3c4SKevin Wolf        return
926e19b3c4SKevin Wolf
936e19b3c4SKevin Wolf    h.update(fd)
946e19b3c4SKevin Wolf
9502756054SVladimir Sementsov-Ogievskiy
961b2eff62SStefan Hajnoczidef cmd_set_feature_bit(fd, group, bit):
971b2eff62SStefan Hajnoczi    try:
981b2eff62SStefan Hajnoczi        bit = int(bit, 0)
991b2eff62SStefan Hajnoczi        if bit < 0 or bit >= 64:
1001b2eff62SStefan Hajnoczi            raise ValueError
10102756054SVladimir Sementsov-Ogievskiy    except ValueError:
102f03868bdSEduardo Habkost        print("'%s' is not a valid bit number in range [0, 64)" % bit)
1031b2eff62SStefan Hajnoczi        sys.exit(1)
1041b2eff62SStefan Hajnoczi
1051b2eff62SStefan Hajnoczi    h = QcowHeader(fd)
1061b2eff62SStefan Hajnoczi    if group == 'incompatible':
1071b2eff62SStefan Hajnoczi        h.incompatible_features |= 1 << bit
1081b2eff62SStefan Hajnoczi    elif group == 'compatible':
1091b2eff62SStefan Hajnoczi        h.compatible_features |= 1 << bit
1101b2eff62SStefan Hajnoczi    elif group == 'autoclear':
1111b2eff62SStefan Hajnoczi        h.autoclear_features |= 1 << bit
1121b2eff62SStefan Hajnoczi    else:
11302756054SVladimir Sementsov-Ogievskiy        print("'%s' is not a valid group, try "
11402756054SVladimir Sementsov-Ogievskiy              "'incompatible', 'compatible', or 'autoclear'" % group)
1151b2eff62SStefan Hajnoczi        sys.exit(1)
1161b2eff62SStefan Hajnoczi
1171b2eff62SStefan Hajnoczi    h.update(fd)
1181b2eff62SStefan Hajnoczi
11902756054SVladimir Sementsov-Ogievskiy
1206e19b3c4SKevin Wolfcmds = [
12102756054SVladimir Sementsov-Ogievskiy    ['dump-header', cmd_dump_header, 0,
12202756054SVladimir Sementsov-Ogievskiy     'Dump image header and header extensions'],
12302756054SVladimir Sementsov-Ogievskiy    ['dump-header-exts', cmd_dump_header_exts, 0,
12402756054SVladimir Sementsov-Ogievskiy     'Dump image header extensions'],
125c93331c9SKevin Wolf    ['set-header', cmd_set_header, 2, 'Set a field in the header'],
1266e19b3c4SKevin Wolf    ['add-header-ext', cmd_add_header_ext, 2, 'Add a header extension'],
12702756054SVladimir Sementsov-Ogievskiy    ['add-header-ext-stdio', cmd_add_header_ext_stdio, 1,
12802756054SVladimir Sementsov-Ogievskiy     'Add a header extension, data from stdin'],
1296e19b3c4SKevin Wolf    ['del-header-ext', cmd_del_header_ext, 1, 'Delete a header extension'],
1301b2eff62SStefan Hajnoczi    ['set-feature-bit', cmd_set_feature_bit, 2, 'Set a feature bit'],
1316e19b3c4SKevin Wolf]
1326e19b3c4SKevin Wolf
13302756054SVladimir Sementsov-Ogievskiy
1346e19b3c4SKevin Wolfdef main(filename, cmd, args):
1356e19b3c4SKevin Wolf    fd = open(filename, "r+b")
1366e19b3c4SKevin Wolf    try:
1376e19b3c4SKevin Wolf        for name, handler, num_args, desc in cmds:
1386e19b3c4SKevin Wolf            if name != cmd:
1396e19b3c4SKevin Wolf                continue
1406e19b3c4SKevin Wolf            elif len(args) != num_args:
1416e19b3c4SKevin Wolf                usage()
1426e19b3c4SKevin Wolf                return
1436e19b3c4SKevin Wolf            else:
1446e19b3c4SKevin Wolf                handler(fd, *args)
1456e19b3c4SKevin Wolf                return
146f03868bdSEduardo Habkost        print("Unknown command '%s'" % cmd)
1476e19b3c4SKevin Wolf    finally:
1486e19b3c4SKevin Wolf        fd.close()
1496e19b3c4SKevin Wolf
15002756054SVladimir Sementsov-Ogievskiy
1516e19b3c4SKevin Wolfdef usage():
152f03868bdSEduardo Habkost    print("Usage: %s <file> <cmd> [<arg>, ...]" % sys.argv[0])
153f03868bdSEduardo Habkost    print("")
154f03868bdSEduardo Habkost    print("Supported commands:")
1556e19b3c4SKevin Wolf    for name, handler, num_args, desc in cmds:
156f03868bdSEduardo Habkost        print("    %-20s - %s" % (name, desc))
1576e19b3c4SKevin Wolf
15802756054SVladimir Sementsov-Ogievskiy
159d2ef210cSKevin Wolfif __name__ == '__main__':
1606e19b3c4SKevin Wolf    if len(sys.argv) < 3:
1616e19b3c4SKevin Wolf        usage()
1626e19b3c4SKevin Wolf        sys.exit(1)
1636e19b3c4SKevin Wolf
1646e19b3c4SKevin Wolf    main(sys.argv[1], sys.argv[2], sys.argv[3:])
165