Skip to content

Commit 7c1feac

Browse files
author
Juerg Haefliger
committedJun 6, 2016
Initial commit
Signed-off-by: Juerg Haefliger <[email protected]>
0 parents  commit 7c1feac

File tree

4 files changed

+797
-0
lines changed

4 files changed

+797
-0
lines changed
 

‎.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*~
2+
*.pyc

‎LICENSE

+339
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,339 @@
1+
GNU GENERAL PUBLIC LICENSE
2+
Version 2, June 1991
3+
4+
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6+
Everyone is permitted to copy and distribute verbatim copies
7+
of this license document, but changing it is not allowed.
8+
9+
Preamble
10+
11+
The licenses for most software are designed to take away your
12+
freedom to share and change it. By contrast, the GNU General Public
13+
License is intended to guarantee your freedom to share and change free
14+
software--to make sure the software is free for all its users. This
15+
General Public License applies to most of the Free Software
16+
Foundation's software and to any other program whose authors commit to
17+
using it. (Some other Free Software Foundation software is covered by
18+
the GNU Lesser General Public License instead.) You can apply it to
19+
your programs, too.
20+
21+
When we speak of free software, we are referring to freedom, not
22+
price. Our General Public Licenses are designed to make sure that you
23+
have the freedom to distribute copies of free software (and charge for
24+
this service if you wish), that you receive source code or can get it
25+
if you want it, that you can change the software or use pieces of it
26+
in new free programs; and that you know you can do these things.
27+
28+
To protect your rights, we need to make restrictions that forbid
29+
anyone to deny you these rights or to ask you to surrender the rights.
30+
These restrictions translate to certain responsibilities for you if you
31+
distribute copies of the software, or if you modify it.
32+
33+
For example, if you distribute copies of such a program, whether
34+
gratis or for a fee, you must give the recipients all the rights that
35+
you have. You must make sure that they, too, receive or can get the
36+
source code. And you must show them these terms so they know their
37+
rights.
38+
39+
We protect your rights with two steps: (1) copyright the software, and
40+
(2) offer you this license which gives you legal permission to copy,
41+
distribute and/or modify the software.
42+
43+
Also, for each author's protection and ours, we want to make certain
44+
that everyone understands that there is no warranty for this free
45+
software. If the software is modified by someone else and passed on, we
46+
want its recipients to know that what they have is not the original, so
47+
that any problems introduced by others will not reflect on the original
48+
authors' reputations.
49+
50+
Finally, any free program is threatened constantly by software
51+
patents. We wish to avoid the danger that redistributors of a free
52+
program will individually obtain patent licenses, in effect making the
53+
program proprietary. To prevent this, we have made it clear that any
54+
patent must be licensed for everyone's free use or not licensed at all.
55+
56+
The precise terms and conditions for copying, distribution and
57+
modification follow.
58+
59+
GNU GENERAL PUBLIC LICENSE
60+
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61+
62+
0. This License applies to any program or other work which contains
63+
a notice placed by the copyright holder saying it may be distributed
64+
under the terms of this General Public License. The "Program", below,
65+
refers to any such program or work, and a "work based on the Program"
66+
means either the Program or any derivative work under copyright law:
67+
that is to say, a work containing the Program or a portion of it,
68+
either verbatim or with modifications and/or translated into another
69+
language. (Hereinafter, translation is included without limitation in
70+
the term "modification".) Each licensee is addressed as "you".
71+
72+
Activities other than copying, distribution and modification are not
73+
covered by this License; they are outside its scope. The act of
74+
running the Program is not restricted, and the output from the Program
75+
is covered only if its contents constitute a work based on the
76+
Program (independent of having been made by running the Program).
77+
Whether that is true depends on what the Program does.
78+
79+
1. You may copy and distribute verbatim copies of the Program's
80+
source code as you receive it, in any medium, provided that you
81+
conspicuously and appropriately publish on each copy an appropriate
82+
copyright notice and disclaimer of warranty; keep intact all the
83+
notices that refer to this License and to the absence of any warranty;
84+
and give any other recipients of the Program a copy of this License
85+
along with the Program.
86+
87+
You may charge a fee for the physical act of transferring a copy, and
88+
you may at your option offer warranty protection in exchange for a fee.
89+
90+
2. You may modify your copy or copies of the Program or any portion
91+
of it, thus forming a work based on the Program, and copy and
92+
distribute such modifications or work under the terms of Section 1
93+
above, provided that you also meet all of these conditions:
94+
95+
a) You must cause the modified files to carry prominent notices
96+
stating that you changed the files and the date of any change.
97+
98+
b) You must cause any work that you distribute or publish, that in
99+
whole or in part contains or is derived from the Program or any
100+
part thereof, to be licensed as a whole at no charge to all third
101+
parties under the terms of this License.
102+
103+
c) If the modified program normally reads commands interactively
104+
when run, you must cause it, when started running for such
105+
interactive use in the most ordinary way, to print or display an
106+
announcement including an appropriate copyright notice and a
107+
notice that there is no warranty (or else, saying that you provide
108+
a warranty) and that users may redistribute the program under
109+
these conditions, and telling the user how to view a copy of this
110+
License. (Exception: if the Program itself is interactive but
111+
does not normally print such an announcement, your work based on
112+
the Program is not required to print an announcement.)
113+
114+
These requirements apply to the modified work as a whole. If
115+
identifiable sections of that work are not derived from the Program,
116+
and can be reasonably considered independent and separate works in
117+
themselves, then this License, and its terms, do not apply to those
118+
sections when you distribute them as separate works. But when you
119+
distribute the same sections as part of a whole which is a work based
120+
on the Program, the distribution of the whole must be on the terms of
121+
this License, whose permissions for other licensees extend to the
122+
entire whole, and thus to each and every part regardless of who wrote it.
123+
124+
Thus, it is not the intent of this section to claim rights or contest
125+
your rights to work written entirely by you; rather, the intent is to
126+
exercise the right to control the distribution of derivative or
127+
collective works based on the Program.
128+
129+
In addition, mere aggregation of another work not based on the Program
130+
with the Program (or with a work based on the Program) on a volume of
131+
a storage or distribution medium does not bring the other work under
132+
the scope of this License.
133+
134+
3. You may copy and distribute the Program (or a work based on it,
135+
under Section 2) in object code or executable form under the terms of
136+
Sections 1 and 2 above provided that you also do one of the following:
137+
138+
a) Accompany it with the complete corresponding machine-readable
139+
source code, which must be distributed under the terms of Sections
140+
1 and 2 above on a medium customarily used for software interchange; or,
141+
142+
b) Accompany it with a written offer, valid for at least three
143+
years, to give any third party, for a charge no more than your
144+
cost of physically performing source distribution, a complete
145+
machine-readable copy of the corresponding source code, to be
146+
distributed under the terms of Sections 1 and 2 above on a medium
147+
customarily used for software interchange; or,
148+
149+
c) Accompany it with the information you received as to the offer
150+
to distribute corresponding source code. (This alternative is
151+
allowed only for noncommercial distribution and only if you
152+
received the program in object code or executable form with such
153+
an offer, in accord with Subsection b above.)
154+
155+
The source code for a work means the preferred form of the work for
156+
making modifications to it. For an executable work, complete source
157+
code means all the source code for all modules it contains, plus any
158+
associated interface definition files, plus the scripts used to
159+
control compilation and installation of the executable. However, as a
160+
special exception, the source code distributed need not include
161+
anything that is normally distributed (in either source or binary
162+
form) with the major components (compiler, kernel, and so on) of the
163+
operating system on which the executable runs, unless that component
164+
itself accompanies the executable.
165+
166+
If distribution of executable or object code is made by offering
167+
access to copy from a designated place, then offering equivalent
168+
access to copy the source code from the same place counts as
169+
distribution of the source code, even though third parties are not
170+
compelled to copy the source along with the object code.
171+
172+
4. You may not copy, modify, sublicense, or distribute the Program
173+
except as expressly provided under this License. Any attempt
174+
otherwise to copy, modify, sublicense or distribute the Program is
175+
void, and will automatically terminate your rights under this License.
176+
However, parties who have received copies, or rights, from you under
177+
this License will not have their licenses terminated so long as such
178+
parties remain in full compliance.
179+
180+
5. You are not required to accept this License, since you have not
181+
signed it. However, nothing else grants you permission to modify or
182+
distribute the Program or its derivative works. These actions are
183+
prohibited by law if you do not accept this License. Therefore, by
184+
modifying or distributing the Program (or any work based on the
185+
Program), you indicate your acceptance of this License to do so, and
186+
all its terms and conditions for copying, distributing or modifying
187+
the Program or works based on it.
188+
189+
6. Each time you redistribute the Program (or any work based on the
190+
Program), the recipient automatically receives a license from the
191+
original licensor to copy, distribute or modify the Program subject to
192+
these terms and conditions. You may not impose any further
193+
restrictions on the recipients' exercise of the rights granted herein.
194+
You are not responsible for enforcing compliance by third parties to
195+
this License.
196+
197+
7. If, as a consequence of a court judgment or allegation of patent
198+
infringement or for any other reason (not limited to patent issues),
199+
conditions are imposed on you (whether by court order, agreement or
200+
otherwise) that contradict the conditions of this License, they do not
201+
excuse you from the conditions of this License. If you cannot
202+
distribute so as to satisfy simultaneously your obligations under this
203+
License and any other pertinent obligations, then as a consequence you
204+
may not distribute the Program at all. For example, if a patent
205+
license would not permit royalty-free redistribution of the Program by
206+
all those who receive copies directly or indirectly through you, then
207+
the only way you could satisfy both it and this License would be to
208+
refrain entirely from distribution of the Program.
209+
210+
If any portion of this section is held invalid or unenforceable under
211+
any particular circumstance, the balance of the section is intended to
212+
apply and the section as a whole is intended to apply in other
213+
circumstances.
214+
215+
It is not the purpose of this section to induce you to infringe any
216+
patents or other property right claims or to contest validity of any
217+
such claims; this section has the sole purpose of protecting the
218+
integrity of the free software distribution system, which is
219+
implemented by public license practices. Many people have made
220+
generous contributions to the wide range of software distributed
221+
through that system in reliance on consistent application of that
222+
system; it is up to the author/donor to decide if he or she is willing
223+
to distribute software through any other system and a licensee cannot
224+
impose that choice.
225+
226+
This section is intended to make thoroughly clear what is believed to
227+
be a consequence of the rest of this License.
228+
229+
8. If the distribution and/or use of the Program is restricted in
230+
certain countries either by patents or by copyrighted interfaces, the
231+
original copyright holder who places the Program under this License
232+
may add an explicit geographical distribution limitation excluding
233+
those countries, so that distribution is permitted only in or among
234+
countries not thus excluded. In such case, this License incorporates
235+
the limitation as if written in the body of this License.
236+
237+
9. The Free Software Foundation may publish revised and/or new versions
238+
of the General Public License from time to time. Such new versions will
239+
be similar in spirit to the present version, but may differ in detail to
240+
address new problems or concerns.
241+
242+
Each version is given a distinguishing version number. If the Program
243+
specifies a version number of this License which applies to it and "any
244+
later version", you have the option of following the terms and conditions
245+
either of that version or of any later version published by the Free
246+
Software Foundation. If the Program does not specify a version number of
247+
this License, you may choose any version ever published by the Free Software
248+
Foundation.
249+
250+
10. If you wish to incorporate parts of the Program into other free
251+
programs whose distribution conditions are different, write to the author
252+
to ask for permission. For software which is copyrighted by the Free
253+
Software Foundation, write to the Free Software Foundation; we sometimes
254+
make exceptions for this. Our decision will be guided by the two goals
255+
of preserving the free status of all derivatives of our free software and
256+
of promoting the sharing and reuse of software generally.
257+
258+
NO WARRANTY
259+
260+
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261+
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262+
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263+
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264+
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265+
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266+
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267+
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268+
REPAIR OR CORRECTION.
269+
270+
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271+
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272+
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273+
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274+
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275+
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276+
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277+
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278+
POSSIBILITY OF SUCH DAMAGES.
279+
280+
END OF TERMS AND CONDITIONS
281+
282+
How to Apply These Terms to Your New Programs
283+
284+
If you develop a new program, and you want it to be of the greatest
285+
possible use to the public, the best way to achieve this is to make it
286+
free software which everyone can redistribute and change under these terms.
287+
288+
To do so, attach the following notices to the program. It is safest
289+
to attach them to the start of each source file to most effectively
290+
convey the exclusion of warranty; and each file should have at least
291+
the "copyright" line and a pointer to where the full notice is found.
292+
293+
<one line to give the program's name and a brief idea of what it does.>
294+
Copyright (C) <year> <name of author>
295+
296+
This program is free software; you can redistribute it and/or modify
297+
it under the terms of the GNU General Public License as published by
298+
the Free Software Foundation; either version 2 of the License, or
299+
(at your option) any later version.
300+
301+
This program is distributed in the hope that it will be useful,
302+
but WITHOUT ANY WARRANTY; without even the implied warranty of
303+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304+
GNU General Public License for more details.
305+
306+
You should have received a copy of the GNU General Public License along
307+
with this program; if not, write to the Free Software Foundation, Inc.,
308+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309+
310+
Also add information on how to contact you by electronic and paper mail.
311+
312+
If the program is interactive, make it output a short notice like this
313+
when it starts in an interactive mode:
314+
315+
Gnomovision version 69, Copyright (C) year name of author
316+
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317+
This is free software, and you are welcome to redistribute it
318+
under certain conditions; type `show c' for details.
319+
320+
The hypothetical commands `show w' and `show c' should show the appropriate
321+
parts of the General Public License. Of course, the commands you use may
322+
be called something other than `show w' and `show c'; they could even be
323+
mouse-clicks or menu items--whatever suits your program.
324+
325+
You should also get your employer (if you work as a programmer) or your
326+
school, if any, to sign a "copyright disclaimer" for the program, if
327+
necessary. Here is a sample; alter the names:
328+
329+
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330+
`Gnomovision' (which makes passes at compilers) written by James Hacker.
331+
332+
<signature of Ty Coon>, 1 April 1989
333+
Ty Coon, President of Vice
334+
335+
This General Public License does not permit incorporating your program into
336+
proprietary programs. If your program is a subroutine library, you may
337+
consider it more useful to permit linking proprietary applications with the
338+
library. If this is what you want to do, use the GNU Lesser General
339+
Public License instead of this License.

‎Makefile

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
all: pep8 pyflakes pylint
2+
3+
pep8:
4+
pep8 --ignore=E221 lqs2mem.py
5+
6+
pyflakes:
7+
pyflakes lqs2mem.py
8+
9+
pylint:
10+
pylint --disable=C0103,C0111,C0326,R0911,R0912,R0914,W0603 \
11+
--reports=n lqs2mem.py

‎lqs2mem.py

+445
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,445 @@
1+
#!/usr/bin/env python
2+
#
3+
# lqs2mem.py - Convert libvirt save files or qemu savevm dumps into raw
4+
# physical memory images
5+
#
6+
# Copyright (C) 2016 Hewlett Packard Enterprise Development, L.P.
7+
#
8+
# Authors: Juerg Haefliger <juerg.haefliger@hpe.com>
9+
#
10+
# Based on lqs2mem originally written by Andrew Tappert <andrew@pikewerks.com>
11+
#
12+
# This program is free software; you can redistribute it and/or
13+
# modify it under the terms of the GNU General Public License
14+
# as published by the Free Software Foundation; either version 2
15+
# of the License, or (at your option) any later version.
16+
#
17+
# This program is distributed in the hope that it will be useful,
18+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
# GNU General Public License for more details.
21+
#
22+
# You should have received a copy of the GNU General Public License
23+
# along with this program; if not, write to the Free Software
24+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
25+
# USA.
26+
27+
from __future__ import print_function
28+
29+
import argparse
30+
import struct
31+
import sys
32+
33+
QEMU_SAVE_MAGIC = "LibvirtQemudSave"
34+
QEMU_SAVE_PARTIAL = "LibvirtQemudPart"
35+
QEMU_SAVE_VERSION = 2
36+
37+
# struct _virQEMUSaveHeader {
38+
# char magic[sizeof(QEMU_SAVE_MAGIC)-1];
39+
# uint32_t version;
40+
# uint32_t xml_len;
41+
# uint32_t was_running;
42+
# uint32_t compressed;
43+
# uint32_t unused[15];
44+
# };
45+
46+
QEMU_VM_FILE_MAGIC = 0x5145564d
47+
QEMU_VM_FILE_VERSION_COMPAT = 0x00000002
48+
QEMU_VM_FILE_VERSION = 0x00000003
49+
QEMU_VM_EOF = 0x00
50+
QEMU_VM_SECTION_START = 0x01
51+
QEMU_VM_SECTION_PART = 0x02
52+
QEMU_VM_SECTION_END = 0x03
53+
QEMU_VM_SECTION_FULL = 0x04
54+
QEMU_VM_SUBSECTION = 0x05
55+
QEMU_VM_VMDESCRIPTION = 0x06
56+
QEMU_VM_CONFIGURATION = 0x07
57+
QEMU_VM_COMMAND = 0x08
58+
QEMU_VM_SECTION_FOOTER = 0x7e
59+
60+
SEC_TYPE_NAME = (
61+
'EOF',
62+
'SECTION_START',
63+
'SECTION_PART',
64+
'SECTION_END',
65+
'SECTION_FULL',
66+
'SUBSECTION',
67+
'VMDESCRIPTION',
68+
'CONIGURATION',
69+
'COMMAND',
70+
)
71+
72+
RAM_SAVE_FLAG_FULL = 0x01 # Obsolete, not used anymore
73+
RAM_SAVE_FLAG_COMPRESS = 0x02
74+
RAM_SAVE_FLAG_MEM_SIZE = 0x04
75+
RAM_SAVE_FLAG_PAGE = 0x08
76+
RAM_SAVE_FLAG_EOS = 0x10
77+
RAM_SAVE_FLAG_CONTINUE = 0x20
78+
RAM_SAVE_FLAG_XBZRLE = 0x40
79+
# 0x80 is reserved in migration.h start with 0x100 next
80+
RAM_SAVE_FLAG_COMPRESS_PAGE = 0x100
81+
82+
83+
# -----------------------------------------------------------------------------
84+
# From migration/qemu-file.c
85+
86+
def qemu_get_byte(fhi):
87+
'''
88+
Read one byte from file
89+
'''
90+
return struct.unpack('B', fhi.read(1))[0]
91+
92+
93+
def qemu_get_be32(fhi):
94+
'''
95+
Read an unsigned int (32 bit, big endian) from file
96+
'''
97+
return struct.unpack('>I', fhi.read(4))[0]
98+
99+
100+
def qemu_get_be64(fhi):
101+
'''
102+
Read an unsigned long (64 bit, big endian) from file
103+
'''
104+
return struct.unpack('>Q', fhi.read(8))[0]
105+
106+
107+
# -----------------------------------------------------------------------------
108+
# Globals
109+
110+
# Assuming 4k page sizes
111+
PAGE_SIZE = 4096
112+
PAGE_MASK = 0xfffffffffffff000
113+
114+
# Defines for seek()
115+
SEEK_SET = 0
116+
SEEK_CUR = 1
117+
SEEK_END = 2
118+
119+
# Verbosity level
120+
VERBOSE = 0
121+
122+
# Write-to-disk flag and number of pages written to disk
123+
DO_WRITE = False
124+
PAGE_COUNT = 0
125+
126+
127+
# -----------------------------------------------------------------------------
128+
# Function declarations
129+
130+
def dprint(level, *args):
131+
'''
132+
Debug print
133+
'''
134+
if level <= VERBOSE:
135+
print(str(args[0]) % args[1:])
136+
137+
138+
def check_libvirt(fhi, fho):
139+
'''
140+
Check for libvirt's QEMU save header
141+
'''
142+
# Read the header magic
143+
magic = fhi.read(len(QEMU_SAVE_MAGIC))
144+
if magic != QEMU_SAVE_MAGIC:
145+
print('Invalid Libvirt-QEMU-save magic')
146+
fhi.seek(0, SEEK_SET)
147+
if fho is None:
148+
return 0
149+
else:
150+
return 1
151+
152+
# Read the rest of the header struct (19 4-byte unsigned integers)
153+
header = struct.unpack('<' + 'I' * 19, fhi.read(4 * 19))
154+
version, xml_len, dummy_was_running, dummy_compressed = header[0:4]
155+
156+
if version != QEMU_VM_FILE_VERSION_COMPAT:
157+
print('Invalid Libvirt-QEMU-save version (%x)' % version)
158+
return 1
159+
160+
print('Valid Libvirt-QEMU-save magic and version')
161+
162+
# Read (skip over) libvirt's config XML
163+
xml = fhi.read(xml_len)
164+
165+
# Write the XML to file
166+
if fho is not None:
167+
fho.write(xml)
168+
169+
return 0
170+
171+
172+
def check_qemu(fhi):
173+
'''
174+
Check for QEMU's save VM header
175+
'''
176+
val = qemu_get_be32(fhi)
177+
if val != QEMU_VM_FILE_MAGIC:
178+
print('Invalid QEMU-savevm magic')
179+
return 1
180+
181+
val = qemu_get_be32(fhi)
182+
if val != QEMU_VM_FILE_VERSION:
183+
print('Unsupported QEMU-savevm version')
184+
return 1
185+
186+
print('Valid QEMU-savevm magic and version')
187+
return 0
188+
189+
190+
def write_page(fho, addr, data):
191+
'''
192+
Write a memory page to file
193+
'''
194+
global PAGE_COUNT
195+
196+
# Account for the 512 MB 'hole' from 3.5 GB to 4 GB for the memory mapped
197+
# PCI devices
198+
if addr >= 0xe0000000:
199+
addr += 0x20000000
200+
201+
fho.seek(addr, SEEK_SET)
202+
203+
if isinstance(data, int):
204+
fho.write(struct.pack('B', data) * PAGE_SIZE)
205+
else:
206+
fho.write(data)
207+
208+
PAGE_COUNT += 1
209+
210+
211+
def process_section_ram(fhi, fho, sec_version, dump_name):
212+
'''
213+
Process a 'ram' section
214+
'''
215+
global DO_WRITE
216+
217+
if sec_version != 4:
218+
print('Unsupported \'ram\' section version: %d' % sec_version)
219+
return 1
220+
221+
while True:
222+
offset = fhi.tell()
223+
addr = qemu_get_be64(fhi)
224+
flags = addr & ~PAGE_MASK
225+
addr &= PAGE_MASK
226+
227+
dprint(3, ' offset: %x' % offset)
228+
dprint(3, ' addr: %x' % addr)
229+
dprint(3, ' flags: %x' % flags)
230+
231+
if flags & RAM_SAVE_FLAG_MEM_SIZE:
232+
total_ram = addr
233+
dprint(2, ' total ram: %d (%d MB)' % (addr, addr / (1 << 20)))
234+
235+
dump_ram_exists = False
236+
while total_ram > 0:
237+
ram_name_len = qemu_get_byte(fhi)
238+
ram_name = fhi.read(ram_name_len)
239+
240+
ram_len = qemu_get_be64(fhi)
241+
kb = ram_len >> 10 if (ram_len >> 10) > 0 else 0
242+
mb = ram_len >> 20 if (ram_len >> 20) > 0 else 0
243+
244+
print('section = %-32s size = %5d [%s] %12d [bytes]' %
245+
(ram_name,
246+
mb if mb > 0 else kb if kb > 0 else ram_len,
247+
"MB" if mb > 0 else "KB" if kb > 0 else "bytes",
248+
ram_len))
249+
250+
if dump_name is not None and ram_name == dump_name:
251+
dump_ram_exists = True
252+
253+
total_ram -= ram_len
254+
255+
if dump_name is not None and not dump_ram_exists:
256+
print('Section not found: %s' % dump_name)
257+
return 1
258+
259+
if flags & RAM_SAVE_FLAG_COMPRESS or \
260+
flags & RAM_SAVE_FLAG_PAGE:
261+
262+
if not flags & RAM_SAVE_FLAG_CONTINUE:
263+
ram_name_len = qemu_get_byte(fhi)
264+
ram_name = fhi.read(ram_name_len)
265+
266+
dprint(2, ' ram name: %s' % ram_name)
267+
268+
DO_WRITE = bool(ram_name == dump_name)
269+
270+
if flags & RAM_SAVE_FLAG_COMPRESS:
271+
fill_byte = qemu_get_byte(fhi)
272+
273+
dprint(3, ' fill byte: %02x' % fill_byte)
274+
275+
if DO_WRITE:
276+
write_page(fho, addr, fill_byte)
277+
278+
if flags & RAM_SAVE_FLAG_PAGE:
279+
page = fhi.read(PAGE_SIZE)
280+
281+
dprint(3, ' page data: ' +
282+
' '.join('%02x' % ord(x) for x in page[0:16]) + ' ...')
283+
284+
if DO_WRITE:
285+
write_page(fho, addr, page)
286+
287+
if flags & RAM_SAVE_FLAG_EOS:
288+
return 0
289+
290+
291+
# def process_section_block(fhi, fho, sec_version, dump_name):
292+
# '''
293+
# Process a 'block' section
294+
# '''
295+
# return 0
296+
297+
298+
SECTION_OPS = {
299+
'ram': process_section_ram,
300+
# 'block': process_section_block,
301+
}
302+
303+
304+
def process_infile(fhi, fho, dump_name):
305+
'''
306+
Process the input file
307+
'''
308+
# Verify the file format
309+
if check_libvirt(fhi, None) or check_qemu(fhi):
310+
print('Unrecognized file format')
311+
return 1
312+
313+
sec_count = 0
314+
sec_header = {}
315+
while True:
316+
sec_count += 1
317+
offset = fhi.tell()
318+
sec_type = qemu_get_byte(fhi)
319+
320+
dprint(1, 'section %d:' % sec_count)
321+
dprint(1, ' file offset: %d' % offset)
322+
dprint(1, ' section type: %d (%s)' % (sec_type,
323+
SEC_TYPE_NAME[sec_type]))
324+
325+
if sec_type == QEMU_VM_EOF:
326+
return 0
327+
328+
elif sec_type == QEMU_VM_CONFIGURATION:
329+
size = qemu_get_be32(fhi)
330+
text = fhi.read(size)
331+
332+
dprint(1, ' text: %s' % text)
333+
return 0
334+
335+
elif (sec_type == QEMU_VM_SECTION_START or
336+
sec_type == QEMU_VM_SECTION_FULL):
337+
# Read the section header
338+
sec_id = qemu_get_be32(fhi)
339+
sec_name_len = qemu_get_byte(fhi)
340+
sec_name = fhi.read(sec_name_len)
341+
sec_inst_id = qemu_get_be32(fhi)
342+
sec_version = qemu_get_be32(fhi)
343+
344+
dprint(1, ' section id: %d (%s)' % (sec_id, sec_name))
345+
dprint(1, ' instance id: %d' % sec_inst_id)
346+
dprint(1, ' version: %d' % sec_version)
347+
348+
# Store the section header in a hash for later lookups
349+
sec_header[sec_id] = {'id': sec_id,
350+
'name': sec_name,
351+
'version': sec_version}
352+
353+
# Process the section
354+
if SECTION_OPS[sec_name](fhi, fho, sec_version, dump_name):
355+
return 1
356+
357+
# Short-cycle the pocessing of the input file if we're only listing
358+
# RAM sections
359+
if ((sec_type == QEMU_VM_SECTION_START and sec_name == 'ram' and
360+
dump_name is None)):
361+
return 0
362+
363+
elif (sec_type == QEMU_VM_SECTION_PART or
364+
sec_type == QEMU_VM_SECTION_END):
365+
# Read the section id and lookup the header
366+
sec_id = qemu_get_be32(fhi)
367+
sec_name = sec_header[sec_id]['name']
368+
sec_version = sec_header[sec_id]['version']
369+
370+
dprint(1, ' section id: %d (%s)' % (sec_id, sec_name))
371+
372+
# Process the section
373+
if SECTION_OPS[sec_name](fhi, fho, sec_version, dump_name):
374+
return 1
375+
376+
# We're only interested (and fully support) RAM sections, so short-
377+
# cycle the processing of the input file if we're done with them
378+
if sec_type == QEMU_VM_SECTION_END and sec_name == 'ram':
379+
return 0
380+
381+
else:
382+
print('Unsupported section type: %d' % sec_type)
383+
return 1
384+
385+
386+
# -----------------------------------------------------------------------------
387+
# Main entry point
388+
389+
def main():
390+
'''
391+
Main entry point
392+
'''
393+
global VERBOSE
394+
395+
aparser = argparse.ArgumentParser()
396+
aparser.add_argument('infile', metavar='INFILE', help='input file to '
397+
'process')
398+
aparser.add_argument('-x', '--xml', action='store_true', help='write the '
399+
'libvirt XML config to OUTFILE')
400+
aparser.add_argument('-s', '--section', metavar='SECTION', help='write '
401+
'section SECTION to OUTFILE')
402+
aparser.add_argument('outfile', nargs='?', metavar='OUTFILE',
403+
help='output file to write data to')
404+
aparser.add_argument('-v', '--verbose', action='count', help='increase '
405+
'verbosity (can be specified multiple times)')
406+
407+
aargs = aparser.parse_args()
408+
if aargs.verbose is not None:
409+
VERBOSE = aargs.verbose
410+
411+
# Validate the arguments
412+
if aargs.xml and aargs.section is not None:
413+
aparser.error('conflicting arguments')
414+
if (aargs.xml or aargs.section is not None) and aargs.outfile is None:
415+
aparser.error('too few arguments')
416+
if not aargs.xml and aargs.section is None and aargs.outfile is not None:
417+
aparser.error('unrecognized arguments: %s' % aargs.outfile)
418+
419+
# Dump the XML and exit
420+
if aargs.xml:
421+
with open(aargs.infile, 'rb') as fhi:
422+
with open(aargs.outfile, 'wb') as fho:
423+
retval = check_libvirt(fhi, fho)
424+
if not retval:
425+
print('XML config written to %s' % aargs.outfile)
426+
return retval
427+
428+
# Dump the selected section and exit
429+
if aargs.section is not None:
430+
with open(aargs.infile, 'rb') as fhi:
431+
with open(aargs.outfile, 'wb') as fho:
432+
retval = process_infile(fhi, fho, aargs.section)
433+
if not retval:
434+
print('Section \'%s\' (%d pages, %d bytes) written to %s' %
435+
(aargs.section, PAGE_COUNT, PAGE_COUNT * PAGE_SIZE,
436+
aargs.outfile))
437+
return retval
438+
439+
# List sections and exit
440+
with open(aargs.infile, 'rb') as fhi:
441+
process_infile(fhi, None, None)
442+
return 0
443+
444+
if __name__ == '__main__':
445+
sys.exit(main())

0 commit comments

Comments
 (0)
Please sign in to comment.