VirtualBox

source: vbox/trunk/src/VBox/VMM/SSM.cpp@ 23448

Last change on this file since 23448 was 23448, checked in by vboxsync, 15 years ago

SSM: Live snapshot bugfix.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 241.8 KB
Line 
1/* $Id: SSM.cpp 23448 2009-09-30 17:11:34Z vboxsync $ */
2/** @file
3 * SSM - Saved State Manager.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22
23/** @page pg_ssm SSM - The Saved State Manager
24 *
25 * The Saved State Manager (SSM) implements facilities for saving and loading a
26 * VM state in a structural manner using callbacks for named data units.
27 *
28 * At init time each of the VMM components, Devices, Drivers and one or two
29 * other things will register data units which they need to save and restore.
30 * Each unit have a unique name (ascii), instance number, and a set of callbacks
31 * associated with it. The name will be used to identify the unit during
32 * restore. The callbacks are for the two operations, save and restore. There
33 * are three callbacks for each of the two - a prepare, a execute and a complete
34 * - giving each component ample opportunity to perform actions both before and
35 * afterwards.
36 *
37 * The SSM provides a number of APIs for encoding and decoding the data: @see
38 * grp_ssm
39 *
40 *
41 *
42 * @section sec_ssm_live_snapshots Live Snapshots
43 *
44 * The live snapshots feature (LS) is similar to live migration (LM) and was a
45 * natural first step when implementing LM. The main differences between LS and
46 * LM are that after a live snapshot we will have a saved state file, disk image
47 * snapshots, and the VM will still be running.
48 *
49 * Compared to normal saved stated and snapshots, the difference is in that the
50 * VM is running while we do most of the saving. Prior to LS, there was only
51 * one round of callbacks during saving and the VM was paused during it. With
52 * LS there are 1 or more passes while the VM is still running and a final one
53 * after it has been paused. The runtime passes are executed on a dedicated
54 * thread running at at the same priority as the EMTs so that the saving doesn't
55 * starve or lose in scheduling questions (note: not implemented yet). The final
56 * pass is done on EMT(0).
57 *
58 * There are a couple of common reasons why LS and LM will fail:
59 * - Memory configuration changed (PCI memory mappings).
60 * - Takes too long (LM) / Too much output (LS).
61 *
62 *
63 * The live saving sequence is something like this:
64 *
65 * -# SSMR3LiveToFile is called on EMT0. It returns a saved state
66 * handle.
67 * -# SSMR3LiveDoStep1 is called on a non-EMT. This will save the major
68 * parts of the state while the VM may still be running.
69 * -# The VM is suspended.
70 * -# SSMR3LiveDoStep2 is called on EMT0 to save the remainder of the state
71 * in the normal way.
72 * -# The client does any necessary reconfiguration of harddisks and
73 * similar.
74 * -# SSMR3LiveDone is called on EMT0 to close the handle.
75 * -# The VM is resumed or powered off and destroyed.
76 *
77 *
78 * @section sec_ssm_live_migration Live Migration
79 *
80 * As mentioned in the previous section, the main differences between this and
81 * live snapshots are in where the saved state is written and what state the
82 * local VM is in afterwards - at least from the VMM point of view. The
83 * necessary administrative work - establishing the connection to the remote
84 * machine, cloning the VM config on it and doing lowlevel saved state data
85 * transfer - is taken care of by layer above the VMM (i.e. Main).
86 *
87 * The SSM data format was made streamable for the purpose of live migration
88 * (v1.2 was the last non-streamable version).
89 *
90 *
91 * @section sec_ssm_format Saved State Format
92 *
93 * The stream format starts with a header (SSMFILEHDR) that indicates the
94 * version and such things, it is followed by zero or more saved state units
95 * (name + instance + pass), and the stream concludes with a footer
96 * (SSMFILEFTR) that contains unit counts and optionally a checksum for the
97 * entire file. (In version 1.2 and earlier, the checksum was in the header and
98 * there was no footer. This meant that the header was updated after the entire
99 * file was written.)
100 *
101 * The saved state units each starts with a variable sized header
102 * (SSMFILEUNITHDRV2) that contains the name, instance and pass. The data
103 * follows the header and is encoded as records with a 2-8 byte record header
104 * indicating the type, flags and size. The first byte in the record header
105 * indicates the type and flags:
106 *
107 * - bits 0..3: Record type:
108 * - type 0: Invalid.
109 * - type 1: Terminator with CRC-32 and unit size.
110 * - type 2: Raw data record.
111 * - type 3: Raw data compressed by LZF. The data is prefixed by a 8-bit
112 * field countining the length of the uncompressed data given in
113 * 1KB units.
114 * - type 4: Zero data. The record header is followed by a 8-bit field
115 * counting the length of the zero data given in 1KB units.
116 * - type 5: Named data - length prefixed name followed by the data. This
117 * type is not implemented yet as we're missing the API part, so
118 * the type assignment is tentative.
119 * - types 6 thru 15 are current undefined.
120 * - bit 4: Important (set), can be skipped (clear).
121 * - bit 5: Undefined flag, must be zero.
122 * - bit 6: Undefined flag, must be zero.
123 * - bit 7: "magic" bit, always set.
124 *
125 * Record header byte 2 (optionally thru 7) is the size of the following data
126 * encoded in UTF-8 style. To make buffering simpler and more efficient during
127 * the save operation, the strict checks enforcing optimal encoding has been
128 * relaxed for the 2 and 3 byte encodings.
129 *
130 * (In version 1.2 and earlier the unit data was compressed and not record
131 * based. The unit header contained the compressed size of the data, i.e. it
132 * needed updating after the data was written.)
133 *
134 *
135 * @section sec_ssm_future Future Changes
136 *
137 * There are plans to extend SSM to make it easier to be both backwards and
138 * (somewhat) forwards compatible. One of the new features will be being able
139 * to classify units and data items as unimportant (added to the format in
140 * v2.0). Another suggested feature is naming data items (also added to the
141 * format in v2.0), perhaps by extending the SSMR3PutStruct API. Both features
142 * will require API changes, the naming may possibly require both buffering of
143 * the stream as well as some helper managing them.
144 */
145
146
147/*******************************************************************************
148* Header Files *
149*******************************************************************************/
150#define LOG_GROUP LOG_GROUP_SSM
151#include <VBox/ssm.h>
152#include <VBox/dbgf.h>
153#include <VBox/mm.h>
154#include "SSMInternal.h"
155#include <VBox/vm.h>
156#include <VBox/err.h>
157#include <VBox/log.h>
158#include <VBox/version.h>
159
160#include <iprt/alloc.h>
161#include <iprt/assert.h>
162#include <iprt/crc32.h>
163#include <iprt/file.h>
164#include <iprt/param.h>
165#include <iprt/thread.h>
166#include <iprt/semaphore.h>
167#include <iprt/string.h>
168#include <iprt/uuid.h>
169#include <iprt/zip.h>
170
171
172/*******************************************************************************
173* Defined Constants And Macros *
174*******************************************************************************/
175/** The max length of a unit name. */
176#define SSM_MAX_NAME_SIZE 48
177
178/** Saved state file magic base string. */
179#define SSMFILEHDR_MAGIC_BASE "\177VirtualBox SavedState "
180/** Saved state file magic indicating version 1.x. */
181#define SSMFILEHDR_MAGIC_V1_X "\177VirtualBox SavedState V1."
182/** Saved state file v1.1 magic. */
183#define SSMFILEHDR_MAGIC_V1_1 "\177VirtualBox SavedState V1.1\n"
184/** Saved state file v1.2 magic. */
185#define SSMFILEHDR_MAGIC_V1_2 "\177VirtualBox SavedState V1.2\n\0\0\0"
186/** Saved state file v2.0 magic. */
187#define SSMFILEHDR_MAGIC_V2_0 "\177VirtualBox SavedState V2.0\n\0\0\0"
188
189/** @name SSMFILEHDR::fFlags
190 * @{ */
191/** The stream is checkesummed up to the footer using CRC-32. */
192#define SSMFILEHDR_FLAGS_STREAM_CRC32 RT_BIT_32(0)
193/** @} */
194
195/** The directory magic. */
196#define SSMFILEDIR_MAGIC "\nDir\n\0\0"
197
198/** Saved state file v2.0 magic. */
199#define SSMFILEFTR_MAGIC "\nFooter"
200
201/** Data unit magic. */
202#define SSMFILEUNITHDR_MAGIC "\nUnit\n\0"
203/** Data end marker magic. */
204#define SSMFILEUNITHDR_END "\nTheEnd"
205
206
207/** @name Record Types (data unit)
208 * @{ */
209/** The record type mask. */
210#define SSM_REC_TYPE_MASK UINT8_C(0x0f)
211/** Invalid record. */
212#define SSM_REC_TYPE_INVALID 0
213/** Normal termination record, see SSMRECTERM. */
214#define SSM_REC_TYPE_TERM 1
215/** Raw data. The data follows the size field without further ado. */
216#define SSM_REC_TYPE_RAW 2
217/** Raw data compressed by LZF.
218 * The record header is followed by a 8-bit field containing the size of the
219 * uncompressed data in 1KB units. The compressed data is after it. */
220#define SSM_REC_TYPE_RAW_LZF 3
221/** Raw zero data.
222 * The record header is followed by a 8-bit field containing the size of the
223 * zero data in 1KB units. */
224#define SSM_REC_TYPE_RAW_ZERO 4
225/** Named data items.
226 * A length prefix zero terminated string (i.e. max 255) followed by the data. */
227#define SSM_REC_TYPE_NAMED 5
228/** Macro for validating the record type.
229 * This can be used with the flags+type byte, no need to mask out the type first. */
230#define SSM_REC_TYPE_IS_VALID(u8Type) ( ((u8Type) & SSM_REC_TYPE_MASK) > SSM_REC_TYPE_INVALID \
231 && ((u8Type) & SSM_REC_TYPE_MASK) <= SSM_REC_TYPE_NAMED )
232/** @} */
233
234/** The flag mask. */
235#define SSM_REC_FLAGS_MASK UINT8_C(0xf0)
236/** The record is important if this flag is set, if clear it can be omitted. */
237#define SSM_REC_FLAGS_IMPORTANT UINT8_C(0x10)
238/** This flag is always set. */
239#define SSM_REC_FLAGS_FIXED UINT8_C(0x80)
240/** Macro for validating the flags.
241 * No need to mask the flags out of the flags+type byte before invoking this macro. */
242#define SSM_REC_FLAGS_ARE_VALID(fFlags) ( ((fFlags) & UINT8_C(0xe0)) == UINT8_C(0x80) )
243
244/** Macro for validating the type and flags byte in a data record. */
245#define SSM_REC_ARE_TYPE_AND_FLAGS_VALID(u8) ( SSM_REC_FLAGS_ARE_VALID(u8) && SSM_REC_TYPE_IS_VALID(u8) )
246
247/** @name SSMRECTERM::fFlags
248 * @{ */
249/** There is a CRC-32 value for the stream. */
250#define SSMRECTERM_FLAGS_CRC32 UINT16_C(0x0001)
251/** @} */
252
253/** Start structure magic. (Isacc Asimov) */
254#define SSMR3STRUCT_BEGIN UINT32_C(0x19200102)
255/** End structure magic. (Isacc Asimov) */
256#define SSMR3STRUCT_END UINT32_C(0x19920406)
257
258
259/** Number of bytes to log in Log2 and Log4 statements. */
260#define SSM_LOG_BYTES 16
261
262/** SSMHANDLE::fCancelled value indicating that the operation has been
263 * cancelled. */
264#define SSMHANDLE_CANCELLED UINT32_C(0xdeadbeef)
265/** SSMHANDLE::fCancelled value indicating no cancellation. */
266#define SSMHANDLE_OK UINT32_C(0x77777777)
267
268
269/** Macro for checking the u32CRC field of a structure.
270 * The Msg can assume there are u32ActualCRC and u32CRC in the context. */
271#define SSM_CHECK_CRC32_RET(p, cb, Msg) \
272 do \
273 { \
274 uint32_t u32CRC = (p)->u32CRC; \
275 (p)->u32CRC = 0; \
276 uint32_t u32ActualCRC = RTCrc32((p), (cb)); \
277 (p)->u32CRC = u32CRC; \
278 AssertLogRelMsgReturn(u32ActualCRC == u32CRC, Msg, VERR_SSM_INTEGRITY_CRC); \
279 } while (0)
280
281/** The number of bytes to compress is one block.
282 * Must be a multiple of 1KB. */
283#define SSM_ZIP_BLOCK_SIZE _4K
284AssertCompile(SSM_ZIP_BLOCK_SIZE / _1K * _1K == SSM_ZIP_BLOCK_SIZE);
285
286
287/**
288 * Asserts that the handle is writable and returns with VERR_SSM_INVALID_STATE
289 * if it isn't.
290 */
291#define SSM_ASSERT_WRITEABLE_RET(pSSM) \
292 AssertMsgReturn( pSSM->enmOp == SSMSTATE_SAVE_EXEC \
293 || pSSM->enmOp == SSMSTATE_LIVE_EXEC,\
294 ("Invalid state %d\n", pSSM->enmOp), VERR_SSM_INVALID_STATE);
295
296/**
297 * Asserts that the handle is readable and returns with VERR_SSM_INVALID_STATE
298 * if it isn't.
299 */
300#define SSM_ASSERT_READABLE_RET(pSSM) \
301 AssertMsgReturn( pSSM->enmOp == SSMSTATE_LOAD_EXEC \
302 || pSSM->enmOp == SSMSTATE_OPEN_READ,\
303 ("Invalid state %d\n", pSSM->enmOp), VERR_SSM_INVALID_STATE);
304
305/** Checks for cancellation and returns if pending.
306 * Sets SSMHANDLE::rc to VERR_SSM_CANCELLED (if it still indicates success) and
307 * then returns SSMHANDLE::rc. (Debug logging only.) */
308#define SSM_CHECK_CANCELLED_RET(pSSM) \
309 do \
310 { \
311 if (RT_UNLIKELY(ASMAtomicUoReadU32(&(pSSM)->fCancelled) == SSMHANDLE_CANCELLED)) \
312 { \
313 LogFlow(("%Rfn: Cancelled -> VERR_SSM_CANCELLED\n", __PRETTY_FUNCTION__)); \
314 if (RT_SUCCESS((pSSM)->rc)) \
315 (pSSM)->rc = VERR_SSM_CANCELLED; \
316 return (pSSM)->rc; \
317 } \
318 } while (0)
319
320
321/*******************************************************************************
322* Structures and Typedefs *
323*******************************************************************************/
324/** SSM state. */
325typedef enum SSMSTATE
326{
327 SSMSTATE_INVALID = 0,
328 SSMSTATE_LIVE_PREP,
329 SSMSTATE_LIVE_STEP1,
330 SSMSTATE_LIVE_EXEC,
331 SSMSTATE_LIVE_VOTE,
332 SSMSTATE_LIVE_STEP2,
333 SSMSTATE_SAVE_PREP,
334 SSMSTATE_SAVE_EXEC,
335 SSMSTATE_SAVE_DONE,
336 SSMSTATE_LOAD_PREP,
337 SSMSTATE_LOAD_EXEC,
338 SSMSTATE_LOAD_DONE,
339 SSMSTATE_OPEN_READ
340} SSMSTATE;
341
342/** Pointer to a SSM stream buffer. */
343typedef struct SSMSTRMBUF *PSSMSTRMBUF;
344/**
345 * A SSM stream buffer.
346 */
347typedef struct SSMSTRMBUF
348{
349 /** The buffer data. */
350 uint8_t abData[_64K];
351
352 /** The stream position of this buffer. */
353 uint64_t offStream;
354 /** The amount of buffered data. */
355 uint32_t cb;
356 /** End of stream indicator (for read streams only). */
357 bool fEndOfStream;
358 /** Pointer to the next buffer in the chain. */
359 PSSMSTRMBUF volatile pNext;
360} SSMSTRMBUF;
361
362/**
363 * SSM stream.
364 *
365 * This is a typical producer / consumer setup with a dedicated I/O thread and
366 * fixed number of buffers for read ahead and write back.
367 */
368typedef struct SSMSTRM
369{
370 /** The file handle. */
371 RTFILE hFile;
372
373 /** Write (set) or read (clear) stream. */
374 bool fWrite;
375 /** Termination indicator. */
376 bool volatile fTerminating;
377 /** Indicates whether it is necessary to seek before the next buffer is
378 * read from the stream. This is used to avoid a seek in ssmR3StrmPeekAt. */
379 bool fNeedSeek;
380 /** Stream error status. */
381 int32_t volatile rc;
382 /** The handle of the I/O thread. This is set to nil when not active. */
383 RTTHREAD hIoThread;
384 /** Where to seek to. */
385 uint64_t offNeedSeekTo;
386
387 /** The head of the consumer queue.
388 * For save the consumer is the I/O thread. For load the I/O thread is the
389 * producer. */
390 PSSMSTRMBUF volatile pHead;
391 /** Chain of free buffers.
392 * The consumer/producer roles are the inverse of pHead. */
393 PSSMSTRMBUF volatile pFree;
394 /** Event that's signalled when pHead is updated. */
395 RTSEMEVENT hEvtHead;
396 /** Event that's signalled when pFree is updated. */
397 RTSEMEVENT hEvtFree;
398
399 /** List of pending buffers that has been dequeued from pHead and reversed. */
400 PSSMSTRMBUF pPending;
401 /** Pointer to the current buffer. */
402 PSSMSTRMBUF pCur;
403 /** The stream offset of the current buffer. */
404 uint64_t offCurStream;
405 /** The current buffer offset. */
406 uint32_t off;
407 /** Whether we're checksumming reads/writes. */
408 bool fChecksummed;
409 /** The stream CRC if fChecksummed is set. */
410 uint32_t u32StreamCRC;
411 /** How far into the buffer u32StreamCRC is up-to-date.
412 * This may lag behind off as it's desirable to checksum as large blocks as
413 * possible. */
414 uint32_t offStreamCRC;
415} SSMSTRM;
416/** Pointer to a SSM stream. */
417typedef SSMSTRM *PSSMSTRM;
418
419
420/**
421 * Handle structure.
422 */
423typedef struct SSMHANDLE
424{
425 /** Stream/buffer manager. */
426 SSMSTRM Strm;
427
428 /** The VM handle. */
429 PVM pVM;
430 /** The current operation. */
431 SSMSTATE enmOp;
432 /** What to do after save completes. (move the enum) */
433 SSMAFTER enmAfter;
434 /** Flag indicating that the operation has been cancelled. */
435 uint32_t volatile fCancelled;
436 /** The current rc of the save operation. */
437 int32_t rc;
438 /** Number of compressed bytes left in the current data unit (V1). */
439 uint64_t cbUnitLeftV1;
440 /** The current uncompressed offset into the data unit. */
441 uint64_t offUnit;
442
443 /** Pointer to the progress callback function. */
444 PFNVMPROGRESS pfnProgress;
445 /** User specified arguemnt to the callback function. */
446 void *pvUser;
447 /** Next completion percentage. (corresponds to offEstProgress) */
448 unsigned uPercent;
449 /** The position of the next progress callback in the estimated file. */
450 uint64_t offEstProgress;
451 /** The estimated total byte count.
452 * (Only valid after the prep.) */
453 uint64_t cbEstTotal;
454 /** Current position in the estimated file. */
455 uint64_t offEst;
456 /** End of current unit in the estimated file. */
457 uint64_t offEstUnitEnd;
458 /** the amount of % we reserve for the 'prepare' phase */
459 unsigned uPercentPrepare;
460 /** the amount of % we reserve for the 'done' stage */
461 unsigned uPercentDone;
462 /** The filename, NULL if remote stream. */
463 const char *pszFilename;
464
465 union
466 {
467 /** Write data. */
468 struct
469 {
470 /** Offset into the databuffer. */
471 uint32_t offDataBuffer;
472 /** Space for the record header. */
473 uint8_t abRecHdr[1+7];
474 /** Data buffer. */
475 uint8_t abDataBuffer[4096];
476 } Write;
477
478 /** Read data. */
479 struct
480 {
481 /** V1: The decompressor of the current data unit. */
482 PRTZIPDECOMP pZipDecompV1;
483 /** The major format version number. */
484 uint32_t uFmtVerMajor;
485 /** The minor format version number. */
486 uint32_t uFmtVerMinor;
487
488 /** V2: Unread bytes in the current record. */
489 uint32_t cbRecLeft;
490 /** V2: Bytes in the data buffer. */
491 uint32_t cbDataBuffer;
492 /** V2: Current buffer position. */
493 uint32_t offDataBuffer;
494 /** V2: End of data indicator. */
495 bool fEndOfData;
496 /** V2: The type and flags byte fo the current record. */
497 uint8_t u8TypeAndFlags;
498
499 /** RTGCPHYS size in bytes. (Only applicable when loading/reading.) */
500 unsigned cbGCPhys;
501 /** RTGCPTR size in bytes. (Only applicable when loading/reading.) */
502 unsigned cbGCPtr;
503 /** Whether cbGCPtr is fixed or settable. */
504 bool fFixedGCPtrSize;
505
506
507 /** @name Header info (set by ssmR3ValidateFile)
508 * @{ */
509 /** The size of the file header. */
510 size_t cbFileHdr;
511 /** The major version number. */
512 uint16_t u16VerMajor;
513 /** The minor version number. */
514 uint16_t u16VerMinor;
515 /** The build number. */
516 uint32_t u32VerBuild;
517 /** The SVN revision. */
518 uint32_t u32SvnRev;
519 /** 32 or 64 depending on the host. */
520 uint8_t cHostBits;
521 /** The CRC of the loaded file. */
522 uint32_t u32LoadCRC;
523 /** The size of the load file. */
524 uint64_t cbLoadFile;
525 /** @} */
526
527 /** V2: Data buffer.
528 * @remarks Be extremely careful when changing the size of this buffer! */
529 uint8_t abDataBuffer[4096];
530
531 /** V2: Decompression buffer for when we cannot use the stream buffer. */
532 uint8_t abComprBuffer[4096];
533 } Read;
534 } u;
535} SSMHANDLE;
536
537
538/**
539 * Header of the saved state file.
540 *
541 * Added in r5xxxx on 2009-07-2?, VirtualBox v3.0.51.
542 */
543typedef struct SSMFILEHDR
544{
545 /** Magic string which identifies this file as a version of VBox saved state
546 * file format (SSMFILEHDR_MAGIC_V2_0). */
547 char szMagic[32];
548 /** The major version number. */
549 uint16_t u16VerMajor;
550 /** The minor version number. */
551 uint16_t u16VerMinor;
552 /** The build number. */
553 uint32_t u32VerBuild;
554 /** The SVN revision. */
555 uint32_t u32SvnRev;
556 /** 32 or 64 depending on the host. */
557 uint8_t cHostBits;
558 /** The size of RTGCPHYS. */
559 uint8_t cbGCPhys;
560 /** The size of RTGCPTR. */
561 uint8_t cbGCPtr;
562 /** Reserved header space - must be zero. */
563 uint8_t u8Reserved;
564 /** The number of units that (may) have stored data in the file. */
565 uint32_t cUnits;
566 /** Flags, see SSMFILEHDR_FLAGS_XXX. */
567 uint32_t fFlags;
568 /** The maximum size of decompressed data. */
569 uint32_t cbMaxDecompr;
570 /** The checksum of this header.
571 * This field is set to zero when calculating the checksum. */
572 uint32_t u32CRC;
573} SSMFILEHDR;
574AssertCompileSize(SSMFILEHDR, 64);
575AssertCompileMemberOffset(SSMFILEHDR, u32CRC, 60);
576AssertCompileMemberSize(SSMFILEHDR, szMagic, sizeof(SSMFILEHDR_MAGIC_V2_0));
577/** Pointer to a saved state file header. */
578typedef SSMFILEHDR *PSSMFILEHDR;
579/** Pointer to a const saved state file header. */
580typedef SSMFILEHDR const *PCSSMFILEHDR;
581
582
583/**
584 * Header of the saved state file.
585 *
586 * Added in r40980 on 2008-12-15, VirtualBox v2.0.51.
587 *
588 * @remarks This is a superset of SSMFILEHDRV11.
589 */
590typedef struct SSMFILEHDRV12
591{
592 /** Magic string which identifies this file as a version of VBox saved state
593 * file format (SSMFILEHDR_MAGIC_V1_2). */
594 char achMagic[32];
595 /** The size of this file. Used to check
596 * whether the save completed and that things are fine otherwise. */
597 uint64_t cbFile;
598 /** File checksum. The actual calculation skips past the u32CRC field. */
599 uint32_t u32CRC;
600 /** Padding. */
601 uint32_t u32Reserved;
602 /** The machine UUID. (Ignored if NIL.) */
603 RTUUID MachineUuid;
604
605 /** The major version number. */
606 uint16_t u16VerMajor;
607 /** The minor version number. */
608 uint16_t u16VerMinor;
609 /** The build number. */
610 uint32_t u32VerBuild;
611 /** The SVN revision. */
612 uint32_t u32SvnRev;
613
614 /** 32 or 64 depending on the host. */
615 uint8_t cHostBits;
616 /** The size of RTGCPHYS. */
617 uint8_t cbGCPhys;
618 /** The size of RTGCPTR. */
619 uint8_t cbGCPtr;
620 /** Padding. */
621 uint8_t au8Reserved;
622} SSMFILEHDRV12;
623AssertCompileSize(SSMFILEHDRV12, 64+16);
624AssertCompileMemberOffset(SSMFILEHDRV12, u32CRC, 40);
625AssertCompileMemberSize(SSMFILEHDRV12, achMagic, sizeof(SSMFILEHDR_MAGIC_V1_2));
626/** Pointer to a saved state file header. */
627typedef SSMFILEHDRV12 *PSSMFILEHDRV12;
628
629
630/**
631 * Header of the saved state file, version 1.1.
632 *
633 * Added in r23677 on 2007-08-17, VirtualBox v1.4.1.
634 */
635typedef struct SSMFILEHDRV11
636{
637 /** Magic string which identifies this file as a version of VBox saved state
638 * file format (SSMFILEHDR_MAGIC_V1_1). */
639 char achMagic[32];
640 /** The size of this file. Used to check
641 * whether the save completed and that things are fine otherwise. */
642 uint64_t cbFile;
643 /** File checksum. The actual calculation skips past the u32CRC field. */
644 uint32_t u32CRC;
645 /** Padding. */
646 uint32_t u32Reserved;
647 /** The machine UUID. (Ignored if NIL.) */
648 RTUUID MachineUuid;
649} SSMFILEHDRV11;
650AssertCompileSize(SSMFILEHDRV11, 64);
651AssertCompileMemberOffset(SSMFILEHDRV11, u32CRC, 40);
652/** Pointer to a saved state file header. */
653typedef SSMFILEHDRV11 *PSSMFILEHDRV11;
654
655
656/**
657 * Data unit header.
658 */
659typedef struct SSMFILEUNITHDRV2
660{
661 /** Magic (SSMFILEUNITHDR_MAGIC or SSMFILEUNITHDR_END). */
662 char szMagic[8];
663 /** The offset in the saved state stream of the start of this unit.
664 * This is mainly intended for sanity checking. */
665 uint64_t offStream;
666 /** The CRC-in-progress value this unit starts at. */
667 uint32_t u32CurStreamCRC;
668 /** The checksum of this structure, including the whole name.
669 * Calculated with this field set to zero. */
670 uint32_t u32CRC;
671 /** Data version. */
672 uint32_t u32Version;
673 /** Instance number. */
674 uint32_t u32Instance;
675 /** Data pass number. */
676 uint32_t u32Pass;
677 /** Flags reserved for future extensions. Must be zero. */
678 uint32_t fFlags;
679 /** Size of the data unit name including the terminator. (bytes) */
680 uint32_t cbName;
681 /** Data unit name, variable size. */
682 char szName[SSM_MAX_NAME_SIZE];
683} SSMFILEUNITHDRV2;
684AssertCompileMemberOffset(SSMFILEUNITHDRV2, szName, 44);
685AssertCompileMemberSize(SSMFILEUNITHDRV2, szMagic, sizeof(SSMFILEUNITHDR_MAGIC));
686AssertCompileMemberSize(SSMFILEUNITHDRV2, szMagic, sizeof(SSMFILEUNITHDR_END));
687/** Pointer to SSMFILEUNITHDRV2. */
688typedef SSMFILEUNITHDRV2 *PSSMFILEUNITHDRV2;
689
690
691/**
692 * Data unit header.
693 *
694 * This is used by v1.0, v1.1 and v1.2 of the format.
695 */
696typedef struct SSMFILEUNITHDRV1
697{
698 /** Magic (SSMFILEUNITHDR_MAGIC or SSMFILEUNITHDR_END). */
699 char achMagic[8];
700 /** Number of bytes in this data unit including the header. */
701 uint64_t cbUnit;
702 /** Data version. */
703 uint32_t u32Version;
704 /** Instance number. */
705 uint32_t u32Instance;
706 /** Size of the data unit name including the terminator. (bytes) */
707 uint32_t cchName;
708 /** Data unit name. */
709 char szName[1];
710} SSMFILEUNITHDRV1;
711/** Pointer to SSMFILEUNITHDR. */
712typedef SSMFILEUNITHDRV1 *PSSMFILEUNITHDRV1;
713
714
715/**
716 * Termination data record.
717 */
718typedef struct SSMRECTERM
719{
720 uint8_t u8TypeAndFlags;
721 /** The record size (sizeof(SSMRECTERM) - 2). */
722 uint8_t cbRec;
723 /** Flags, see SSMRECTERM_FLAGS_CRC32. */
724 uint16_t fFlags;
725 /** The checksum of the stream up to fFlags (exclusive). */
726 uint32_t u32StreamCRC;
727 /** The length of this data unit in bytes (including this record). */
728 uint64_t cbUnit;
729} SSMRECTERM;
730AssertCompileSize(SSMRECTERM, 16);
731AssertCompileMemberAlignment(SSMRECTERM, cbUnit, 8);
732/** Pointer to a termination record. */
733typedef SSMRECTERM *PSSMRECTERM;
734/** Pointer to a const termination record. */
735typedef SSMRECTERM const *PCSSMRECTERM;
736
737
738/**
739 * Directory entry.
740 */
741typedef struct SSMFILEDIRENTRY
742{
743 /** The offset of the data unit. */
744 uint64_t off;
745 /** The instance number. */
746 uint32_t u32Instance;
747 /** The CRC-32 of the name excluding the terminator. (lazy bird) */
748 uint32_t u32NameCRC;
749} SSMFILEDIRENTRY;
750AssertCompileSize(SSMFILEDIRENTRY, 16);
751/** Pointer to a directory entry. */
752typedef SSMFILEDIRENTRY *PSSMFILEDIRENTRY;
753/** Pointer to a const directory entry. */
754typedef SSMFILEDIRENTRY const *PCSSMFILEDIRENTRY;
755
756/**
757 * Directory for the data units from the final pass.
758 *
759 * This is used to speed up SSMR3Seek (it would have to decompress and parse the
760 * whole stream otherwise).
761 */
762typedef struct SSMFILEDIR
763{
764 /** Magic string (SSMFILEDIR_MAGIC). */
765 char szMagic[8];
766 /** The CRC-32 for the whole directory.
767 * Calculated with this field set to zero. */
768 uint32_t u32CRC;
769 /** The number of directory entries. */
770 uint32_t cEntries;
771 /** The directory entries (variable size). */
772 SSMFILEDIRENTRY aEntries[1];
773} SSMFILEDIR;
774AssertCompileSize(SSMFILEDIR, 32);
775/** Pointer to a directory. */
776typedef SSMFILEDIR *PSSMFILEDIR;
777/** Pointer to a const directory. */
778typedef SSMFILEDIR *PSSMFILEDIR;
779
780
781/**
782 * Footer structure
783 */
784typedef struct SSMFILEFTR
785{
786 /** Magic string (SSMFILEFTR_MAGIC). */
787 char szMagic[8];
788 /** The offset of this record in the stream. */
789 uint64_t offStream;
790 /** The CRC for the stream.
791 * This is set to zero if SSMFILEHDR_FLAGS_STREAM_CRC32 is clear. */
792 uint32_t u32StreamCRC;
793 /** Number directory entries. */
794 uint32_t cDirEntries;
795 /** Reserved footer space - must be zero. */
796 uint32_t u32Reserved;
797 /** The CRC-32 for this structure.
798 * Calculated with this field set to zero. */
799 uint32_t u32CRC;
800} SSMFILEFTR;
801AssertCompileSize(SSMFILEFTR, 32);
802/** Pointer to a footer. */
803typedef SSMFILEFTR *PSSMFILEFTR;
804/** Pointer to a const footer. */
805typedef SSMFILEFTR const *PCSSMFILEFTR;
806
807
808/*******************************************************************************
809* Internal Functions *
810*******************************************************************************/
811static int ssmR3LazyInit(PVM pVM);
812static DECLCALLBACK(int) ssmR3SelfLiveExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uPass);
813static DECLCALLBACK(int) ssmR3SelfSaveExec(PVM pVM, PSSMHANDLE pSSM);
814static DECLCALLBACK(int) ssmR3SelfLoadExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
815static int ssmR3Register(PVM pVM, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess, const char *pszBefore, PSSMUNIT *ppUnit);
816
817static int ssmR3StrmWriteBuffers(PSSMSTRM pStrm);
818static int ssmR3StrmReadMore(PSSMSTRM pStrm);
819
820static int ssmR3DataFlushBuffer(PSSMHANDLE pSSM);
821static int ssmR3DataReadRecHdrV2(PSSMHANDLE pSSM);
822
823
824
825/**
826 * Cleans up resources allocated by SSM on VM termination.
827 *
828 * @param pVM The VM handle.
829 */
830VMMR3_INT_DECL(void) SSMR3Term(PVM pVM)
831{
832 if (pVM->ssm.s.fInitialized)
833 {
834 pVM->ssm.s.fInitialized = false;
835 RTCritSectDelete(&pVM->ssm.s.CancelCritSect);
836 }
837}
838
839
840/**
841 * Performs lazy initialization of the SSM.
842 *
843 * @returns VBox status code.
844 * @param pVM The VM.
845 */
846static int ssmR3LazyInit(PVM pVM)
847{
848 /*
849 * Register a saved state unit which we use to put the VirtualBox version,
850 * revision and similar stuff in.
851 */
852 pVM->ssm.s.fInitialized = true;
853 int rc = SSMR3RegisterInternal(pVM, "SSM", 0 /*uInstance*/, 1 /*uVersion*/, 64 /*cbGuess*/,
854 NULL /*pfnLivePrep*/, ssmR3SelfLiveExec, NULL /*pfnLiveVote*/,
855 NULL /*pfnSavePrep*/, ssmR3SelfSaveExec, NULL /*pfnSaveDone*/,
856 NULL /*pfnSavePrep*/, ssmR3SelfLoadExec, NULL /*pfnSaveDone*/);
857
858 /*
859 * Initialize the cancellation critsect now.
860 */
861 if (RT_SUCCESS(rc))
862 rc = RTCritSectInit(&pVM->ssm.s.CancelCritSect);
863
864 pVM->ssm.s.fInitialized = RT_SUCCESS(rc);
865 return rc;
866}
867
868
869/**
870 * Do ssmR3SelfSaveExec in pass 0.
871 *
872 * @returns VBox status code.
873 * @param pVM Pointer to the shared VM structure.
874 * @param pSSM The SSM handle.
875 * @param uPass The data pass number.
876 */
877static DECLCALLBACK(int) ssmR3SelfLiveExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uPass)
878{
879 if (uPass == 0)
880 return ssmR3SelfSaveExec(pVM, pSSM);
881 return VINF_SUCCESS;
882}
883
884
885/**
886 * For saving usful things without having to go thru the tedious process of
887 * adding it to the header.
888 *
889 * @returns VBox status code.
890 * @param pVM Pointer to the shared VM structure.
891 * @param pSSM The SSM handle.
892 */
893static DECLCALLBACK(int) ssmR3SelfSaveExec(PVM pVM, PSSMHANDLE pSSM)
894{
895 /*
896 * String table containg pairs of variable and value string.
897 * Terminated by two empty strings.
898 */
899 SSMR3PutStrZ(pSSM, "Build Type");
900 SSMR3PutStrZ(pSSM, KBUILD_TYPE);
901 SSMR3PutStrZ(pSSM, "Host OS");
902 SSMR3PutStrZ(pSSM, KBUILD_TARGET "." KBUILD_TARGET_ARCH);
903#ifdef VBOX_OSE
904 SSMR3PutStrZ(pSSM, "OSE");
905 SSMR3PutStrZ(pSSM, "true");
906#endif
907
908 /* terminator */
909 SSMR3PutStrZ(pSSM, "");
910 return SSMR3PutStrZ(pSSM, "");
911}
912
913
914/**
915 * For load the version + revision and stuff.
916 *
917 * @returns VBox status code.
918 * @param pVM Pointer to the shared VM structure.
919 * @param pSSM The SSM handle.
920 * @param uVersion The version (1).
921 * @param uPass The pass.
922 */
923static DECLCALLBACK(int) ssmR3SelfLoadExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
924{
925 AssertLogRelMsgReturn(uVersion == 1, ("%d", uVersion), VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION);
926
927 /*
928 * The first and last passes contains a {name, value} string table that is
929 * terminated by two emptry strings. It contains useful informal build
930 * info and can be very handy when something goes wrong after restore.
931 */
932 if ( uPass == 0
933 || uPass == SSM_PASS_FINAL)
934 {
935 for (unsigned i = 0; ; i++)
936 {
937 char szVar[128];
938 char szValue[1024];
939 int rc = SSMR3GetStrZ(pSSM, szVar, sizeof(szVar));
940 AssertRCReturn(rc, rc);
941 rc = SSMR3GetStrZ(pSSM, szValue, sizeof(szValue));
942 AssertRCReturn(rc, rc);
943 if (!szVar[0] && !szValue[0])
944 break;
945 if (i == 0)
946 LogRel(("SSM: Saved state info:\n"));
947 LogRel(("SSM: %s: %s\n", szVar, szValue));
948 }
949 }
950 return VINF_SUCCESS;
951}
952
953
954/**
955 * Internal registration worker.
956 *
957 * @returns VBox status code.
958 * @param pVM The VM handle.
959 * @param pszName Data unit name.
960 * @param uInstance The instance id.
961 * @param uVersion The data unit version.
962 * @param cbGuess The guessed data unit size.
963 * @param pszBefore Name of data unit to be placed in front of.
964 * Optional.
965 * @param ppUnit Where to store the insterted unit node.
966 * Caller must fill in the missing details.
967 */
968static int ssmR3Register(PVM pVM, const char *pszName, uint32_t uInstance,
969 uint32_t uVersion, size_t cbGuess, const char *pszBefore, PSSMUNIT *ppUnit)
970{
971 /*
972 * Validate input.
973 */
974 AssertPtr(pszName);
975 AssertReturn(*pszName, VERR_INVALID_PARAMETER);
976 size_t cchName = strlen(pszName);
977 AssertMsgReturn(cchName < SSM_MAX_NAME_SIZE, ("%zu >= %u: %s\n", cchName, SSM_MAX_NAME_SIZE, pszName), VERR_OUT_OF_RANGE);
978
979 AssertReturn(!pszBefore || *pszBefore, VERR_INVALID_PARAMETER);
980 size_t cchBefore = pszBefore ? strlen(pszBefore) : 0;
981 AssertMsgReturn(cchBefore < SSM_MAX_NAME_SIZE, ("%zu >= %u: %s\n", cchBefore, SSM_MAX_NAME_SIZE, pszBefore), VERR_OUT_OF_RANGE);
982
983 /*
984 * Lazy init.
985 */
986 if (!pVM->ssm.s.fInitialized)
987 {
988 int rc = ssmR3LazyInit(pVM);
989 AssertRCReturn(rc, rc);
990 }
991
992 /*
993 * Walk to the end of the list checking for duplicates as we go.
994 */
995 PSSMUNIT pUnitBeforePrev = NULL;
996 PSSMUNIT pUnitBefore = NULL;
997 PSSMUNIT pUnitPrev = NULL;
998 PSSMUNIT pUnit = pVM->ssm.s.pHead;
999 while (pUnit)
1000 {
1001 if ( pUnit->u32Instance == uInstance
1002 && pUnit->cchName == cchName
1003 && !memcmp(pUnit->szName, pszName, cchName))
1004 {
1005 AssertMsgFailed(("Duplicate registration %s\n", pszName));
1006 return VERR_SSM_UNIT_EXISTS;
1007 }
1008 if ( pUnit->cchName == cchBefore
1009 && !pUnitBefore
1010 && !memcmp(pUnit->szName, pszBefore, cchBefore))
1011 {
1012 pUnitBeforePrev = pUnitPrev;
1013 pUnitBefore = pUnit;
1014 }
1015
1016 /* next */
1017 pUnitPrev = pUnit;
1018 pUnit = pUnit->pNext;
1019 }
1020
1021 /*
1022 * Allocate new node.
1023 */
1024 pUnit = (PSSMUNIT)MMR3HeapAllocZ(pVM, MM_TAG_SSM, RT_OFFSETOF(SSMUNIT, szName[cchName + 1]));
1025 if (!pUnit)
1026 return VERR_NO_MEMORY;
1027
1028 /*
1029 * Fill in (some) data. (Stuff is zero'ed.)
1030 */
1031 pUnit->u32Version = uVersion;
1032 pUnit->u32Instance = uInstance;
1033 pUnit->cbGuess = cbGuess;
1034 pUnit->cchName = cchName;
1035 memcpy(pUnit->szName, pszName, cchName);
1036
1037 /*
1038 * Insert
1039 */
1040 if (pUnitBefore)
1041 {
1042 pUnit->pNext = pUnitBefore;
1043 if (pUnitBeforePrev)
1044 pUnitBeforePrev->pNext = pUnit;
1045 else
1046 pVM->ssm.s.pHead = pUnit;
1047 }
1048 else if (pUnitPrev)
1049 pUnitPrev->pNext = pUnit;
1050 else
1051 pVM->ssm.s.pHead = pUnit;
1052 pVM->ssm.s.cUnits++;
1053
1054 *ppUnit = pUnit;
1055 return VINF_SUCCESS;
1056}
1057
1058
1059/**
1060 * Register a PDM Devices data unit.
1061 *
1062 * @returns VBox status.
1063 *
1064 * @param pVM The VM handle.
1065 * @param pDevIns Device instance.
1066 * @param pszName Data unit name.
1067 * @param uInstance The instance identifier of the data unit.
1068 * This must together with the name be unique.
1069 * @param uVersion Data layout version number.
1070 * @param cbGuess The approximate amount of data in the unit.
1071 * Only for progress indicators.
1072 * @param pszBefore Name of data unit which we should be put in front
1073 * of. Optional (NULL).
1074 *
1075 * @param pfnLivePrep Prepare live save callback, optional.
1076 * @param pfnLiveExec Execute live save callback, optional.
1077 * @param pfnLiveVote Vote live save callback, optional.
1078 *
1079 * @param pfnSavePrep Prepare save callback, optional.
1080 * @param pfnSaveExec Execute save callback, optional.
1081 * @param pfnSaveDone Done save callback, optional.
1082 *
1083 * @param pfnLoadPrep Prepare load callback, optional.
1084 * @param pfnLoadExec Execute load callback, optional.
1085 * @param pfnLoadDone Done load callback, optional.
1086 */
1087VMMR3DECL(int) SSMR3RegisterDevice(PVM pVM, PPDMDEVINS pDevIns, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess, const char *pszBefore,
1088 PFNSSMDEVLIVEPREP pfnLivePrep, PFNSSMDEVLIVEEXEC pfnLiveExec, PFNSSMDEVLIVEVOTE pfnLiveVote,
1089 PFNSSMDEVSAVEPREP pfnSavePrep, PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVSAVEDONE pfnSaveDone,
1090 PFNSSMDEVLOADPREP pfnLoadPrep, PFNSSMDEVLOADEXEC pfnLoadExec, PFNSSMDEVLOADDONE pfnLoadDone)
1091{
1092 PSSMUNIT pUnit;
1093 int rc = ssmR3Register(pVM, pszName, uInstance, uVersion, cbGuess, pszBefore, &pUnit);
1094 if (RT_SUCCESS(rc))
1095 {
1096 pUnit->enmType = SSMUNITTYPE_DEV;
1097 pUnit->u.Dev.pfnLivePrep = pfnLivePrep;
1098 pUnit->u.Dev.pfnLiveExec = pfnLiveExec;
1099 pUnit->u.Dev.pfnLiveVote = pfnLiveVote;
1100 pUnit->u.Dev.pfnSavePrep = pfnSavePrep;
1101 pUnit->u.Dev.pfnSaveExec = pfnSaveExec;
1102 pUnit->u.Dev.pfnSaveDone = pfnSaveDone;
1103 pUnit->u.Dev.pfnLoadPrep = pfnLoadPrep;
1104 pUnit->u.Dev.pfnLoadExec = pfnLoadExec;
1105 pUnit->u.Dev.pfnLoadDone = pfnLoadDone;
1106 pUnit->u.Dev.pDevIns = pDevIns;
1107 }
1108 return rc;
1109}
1110
1111
1112/**
1113 * Register a PDM driver data unit.
1114 *
1115 * @returns VBox status.
1116 *
1117 * @param pVM The VM handle.
1118 * @param pDrvIns Driver instance.
1119 * @param pszName Data unit name.
1120 * @param uInstance The instance identifier of the data unit.
1121 * This must together with the name be unique.
1122 * @param uVersion Data layout version number.
1123 * @param cbGuess The approximate amount of data in the unit.
1124 * Only for progress indicators.
1125 *
1126 * @param pfnLivePrep Prepare live save callback, optional.
1127 * @param pfnLiveExec Execute live save callback, optional.
1128 * @param pfnLiveVote Vote live save callback, optional.
1129 *
1130 * @param pfnSavePrep Prepare save callback, optional.
1131 * @param pfnSaveExec Execute save callback, optional.
1132 * @param pfnSaveDone Done save callback, optional.
1133 *
1134 * @param pfnLoadPrep Prepare load callback, optional.
1135 * @param pfnLoadExec Execute load callback, optional.
1136 * @param pfnLoadDone Done load callback, optional.
1137 */
1138VMMR3DECL(int) SSMR3RegisterDriver(PVM pVM, PPDMDRVINS pDrvIns, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess,
1139 PFNSSMDRVLIVEPREP pfnLivePrep, PFNSSMDRVLIVEEXEC pfnLiveExec, PFNSSMDRVLIVEVOTE pfnLiveVote,
1140 PFNSSMDRVSAVEPREP pfnSavePrep, PFNSSMDRVSAVEEXEC pfnSaveExec, PFNSSMDRVSAVEDONE pfnSaveDone,
1141 PFNSSMDRVLOADPREP pfnLoadPrep, PFNSSMDRVLOADEXEC pfnLoadExec, PFNSSMDRVLOADDONE pfnLoadDone)
1142{
1143 PSSMUNIT pUnit;
1144 int rc = ssmR3Register(pVM, pszName, uInstance, uVersion, cbGuess, NULL, &pUnit);
1145 if (RT_SUCCESS(rc))
1146 {
1147 pUnit->enmType = SSMUNITTYPE_DRV;
1148 pUnit->u.Drv.pfnSavePrep = pfnSavePrep;
1149 pUnit->u.Drv.pfnSaveExec = pfnSaveExec;
1150 pUnit->u.Drv.pfnSaveDone = pfnSaveDone;
1151 pUnit->u.Drv.pfnLoadPrep = pfnLoadPrep;
1152 pUnit->u.Drv.pfnLoadExec = pfnLoadExec;
1153 pUnit->u.Drv.pfnLoadDone = pfnLoadDone;
1154 pUnit->u.Drv.pDrvIns = pDrvIns;
1155 }
1156 return rc;
1157}
1158
1159
1160/**
1161 * Register a internal data unit.
1162 *
1163 * @returns VBox status.
1164 *
1165 * @param pVM The VM handle.
1166 * @param pszName Data unit name.
1167 * @param uInstance The instance identifier of the data unit.
1168 * This must together with the name be unique.
1169 * @param uVersion Data layout version number.
1170 * @param cbGuess The approximate amount of data in the unit.
1171 * Only for progress indicators.
1172 *
1173 * @param pfnLivePrep Prepare live save callback, optional.
1174 * @param pfnLiveExec Execute live save callback, optional.
1175 * @param pfnLiveVote Vote live save callback, optional.
1176 *
1177 * @param pfnSavePrep Prepare save callback, optional.
1178 * @param pfnSaveExec Execute save callback, optional.
1179 * @param pfnSaveDone Done save callback, optional.
1180 *
1181 * @param pfnLoadPrep Prepare load callback, optional.
1182 * @param pfnLoadExec Execute load callback, optional.
1183 * @param pfnLoadDone Done load callback, optional.
1184 */
1185VMMR3DECL(int) SSMR3RegisterInternal(PVM pVM, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess,
1186 PFNSSMINTLIVEPREP pfnLivePrep, PFNSSMINTLIVEEXEC pfnLiveExec, PFNSSMINTLIVEVOTE pfnLiveVote,
1187 PFNSSMINTSAVEPREP pfnSavePrep, PFNSSMINTSAVEEXEC pfnSaveExec, PFNSSMINTSAVEDONE pfnSaveDone,
1188 PFNSSMINTLOADPREP pfnLoadPrep, PFNSSMINTLOADEXEC pfnLoadExec, PFNSSMINTLOADDONE pfnLoadDone)
1189{
1190 PSSMUNIT pUnit;
1191 int rc = ssmR3Register(pVM, pszName, uInstance, uVersion, cbGuess, NULL, &pUnit);
1192 if (RT_SUCCESS(rc))
1193 {
1194 pUnit->enmType = SSMUNITTYPE_INTERNAL;
1195 pUnit->u.Internal.pfnLivePrep = pfnLivePrep;
1196 pUnit->u.Internal.pfnLiveExec = pfnLiveExec;
1197 pUnit->u.Internal.pfnLiveVote = pfnLiveVote;
1198 pUnit->u.Internal.pfnSavePrep = pfnSavePrep;
1199 pUnit->u.Internal.pfnSaveExec = pfnSaveExec;
1200 pUnit->u.Internal.pfnSaveDone = pfnSaveDone;
1201 pUnit->u.Internal.pfnLoadPrep = pfnLoadPrep;
1202 pUnit->u.Internal.pfnLoadExec = pfnLoadExec;
1203 pUnit->u.Internal.pfnLoadDone = pfnLoadDone;
1204 }
1205 return rc;
1206}
1207
1208
1209/**
1210 * Register an external data unit.
1211 *
1212 * @returns VBox status.
1213 *
1214 * @param pVM The VM handle.
1215 * @param pszName Data unit name.
1216 * @param uInstance The instance identifier of the data unit.
1217 * This must together with the name be unique.
1218 * @param uVersion Data layout version number.
1219 * @param cbGuess The approximate amount of data in the unit.
1220 * Only for progress indicators.
1221 *
1222 * @param pfnLivePrep Prepare live save callback, optional.
1223 * @param pfnLiveExec Execute live save callback, optional.
1224 * @param pfnLiveVote Vote live save callback, optional.
1225 *
1226 * @param pfnSavePrep Prepare save callback, optional.
1227 * @param pfnSaveExec Execute save callback, optional.
1228 * @param pfnSaveDone Done save callback, optional.
1229 *
1230 * @param pfnLoadPrep Prepare load callback, optional.
1231 * @param pfnLoadExec Execute load callback, optional.
1232 * @param pfnLoadDone Done load callback, optional.
1233 * @param pvUser User argument.
1234 */
1235VMMR3DECL(int) SSMR3RegisterExternal(PVM pVM, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess,
1236 PFNSSMEXTLIVEPREP pfnLivePrep, PFNSSMEXTLIVEEXEC pfnLiveExec, PFNSSMEXTLIVEVOTE pfnLiveVote,
1237 PFNSSMEXTSAVEPREP pfnSavePrep, PFNSSMEXTSAVEEXEC pfnSaveExec, PFNSSMEXTSAVEDONE pfnSaveDone,
1238 PFNSSMEXTLOADPREP pfnLoadPrep, PFNSSMEXTLOADEXEC pfnLoadExec, PFNSSMEXTLOADDONE pfnLoadDone, void *pvUser)
1239{
1240 PSSMUNIT pUnit;
1241 int rc = ssmR3Register(pVM, pszName, uInstance, uVersion, cbGuess, NULL, &pUnit);
1242 if (RT_SUCCESS(rc))
1243 {
1244 pUnit->enmType = SSMUNITTYPE_EXTERNAL;
1245 pUnit->u.External.pfnLivePrep = pfnLivePrep;
1246 pUnit->u.External.pfnLiveExec = pfnLiveExec;
1247 pUnit->u.External.pfnLiveVote = pfnLiveVote;
1248 pUnit->u.External.pfnSavePrep = pfnSavePrep;
1249 pUnit->u.External.pfnSaveExec = pfnSaveExec;
1250 pUnit->u.External.pfnSaveDone = pfnSaveDone;
1251 pUnit->u.External.pfnLoadPrep = pfnLoadPrep;
1252 pUnit->u.External.pfnLoadExec = pfnLoadExec;
1253 pUnit->u.External.pfnLoadDone = pfnLoadDone;
1254 pUnit->u.External.pvUser = pvUser;
1255 }
1256 return rc;
1257}
1258
1259
1260/**
1261 * Deregister one or more PDM Device data units.
1262 *
1263 * @returns VBox status.
1264 *
1265 * @param pVM The VM handle.
1266 * @param pDevIns Device instance.
1267 * @param pszName Data unit name.
1268 * Use NULL to deregister all data units for that device instance.
1269 * @param uInstance The instance identifier of the data unit.
1270 * This must together with the name be unique.
1271 * @remark Only for dynmaic data units and dynamic unloaded modules.
1272 */
1273VMMR3_INT_DECL(int) SSMR3DeregisterDevice(PVM pVM, PPDMDEVINS pDevIns, const char *pszName, uint32_t uInstance)
1274{
1275 /*
1276 * Validate input.
1277 */
1278 if (!pDevIns)
1279 {
1280 AssertMsgFailed(("pDevIns is NULL!\n"));
1281 return VERR_INVALID_PARAMETER;
1282 }
1283
1284 /*
1285 * Search the list.
1286 */
1287 size_t cchName = pszName ? strlen(pszName) : 0;
1288 int rc = pszName ? VERR_SSM_UNIT_NOT_FOUND : VINF_SUCCESS;
1289 PSSMUNIT pUnitPrev = NULL;
1290 PSSMUNIT pUnit = pVM->ssm.s.pHead;
1291 while (pUnit)
1292 {
1293 if ( pUnit->enmType == SSMUNITTYPE_DEV
1294 && ( !pszName
1295 || ( pUnit->cchName == cchName
1296 && !memcmp(pUnit->szName, pszName, cchName)))
1297 && pUnit->u32Instance == uInstance
1298 )
1299 {
1300 if (pUnit->u.Dev.pDevIns == pDevIns)
1301 {
1302 /*
1303 * Unlink it, advance pointer, and free the node.
1304 */
1305 PSSMUNIT pFree = pUnit;
1306 pUnit = pUnit->pNext;
1307 if (pUnitPrev)
1308 pUnitPrev->pNext = pUnit;
1309 else
1310 pVM->ssm.s.pHead = pUnit;
1311 pVM->ssm.s.cUnits--;
1312 Log(("SSM: Removed data unit '%s' (pdm dev).\n", pFree->szName));
1313 MMR3HeapFree(pFree);
1314
1315 if (pszName)
1316 return VINF_SUCCESS;
1317 rc = VINF_SUCCESS;
1318 continue;
1319 }
1320 else if (pszName)
1321 {
1322 AssertMsgFailed(("Caller is not owner! Owner=%p Caller=%p %s\n",
1323 pUnit->u.Dev.pDevIns, pDevIns, pszName));
1324 return VERR_SSM_UNIT_NOT_OWNER;
1325 }
1326 }
1327
1328 /* next */
1329 pUnitPrev = pUnit;
1330 pUnit = pUnit->pNext;
1331 }
1332
1333 return rc;
1334}
1335
1336
1337/**
1338 * Deregister one ore more PDM Driver data units.
1339 *
1340 * @returns VBox status.
1341 * @param pVM The VM handle.
1342 * @param pDrvIns Driver instance.
1343 * @param pszName Data unit name.
1344 * Use NULL to deregister all data units for that driver instance.
1345 * @param uInstance The instance identifier of the data unit.
1346 * This must together with the name be unique. Ignored if pszName is NULL.
1347 * @remark Only for dynmaic data units and dynamic unloaded modules.
1348 */
1349VMMR3_INT_DECL(int) SSMR3DeregisterDriver(PVM pVM, PPDMDRVINS pDrvIns, const char *pszName, uint32_t uInstance)
1350{
1351 /*
1352 * Validate input.
1353 */
1354 if (!pDrvIns)
1355 {
1356 AssertMsgFailed(("pDrvIns is NULL!\n"));
1357 return VERR_INVALID_PARAMETER;
1358 }
1359
1360 /*
1361 * Search the list.
1362 */
1363 size_t cchName = pszName ? strlen(pszName) : 0;
1364 int rc = pszName ? VERR_SSM_UNIT_NOT_FOUND : VINF_SUCCESS;
1365 PSSMUNIT pUnitPrev = NULL;
1366 PSSMUNIT pUnit = pVM->ssm.s.pHead;
1367 while (pUnit)
1368 {
1369 if ( pUnit->enmType == SSMUNITTYPE_DRV
1370 && ( !pszName
1371 || ( pUnit->cchName == cchName
1372 && !memcmp(pUnit->szName, pszName, cchName)
1373 && pUnit->u32Instance == uInstance))
1374 )
1375 {
1376 if (pUnit->u.Drv.pDrvIns == pDrvIns)
1377 {
1378 /*
1379 * Unlink it, advance pointer, and free the node.
1380 */
1381 PSSMUNIT pFree = pUnit;
1382 pUnit = pUnit->pNext;
1383 if (pUnitPrev)
1384 pUnitPrev->pNext = pUnit;
1385 else
1386 pVM->ssm.s.pHead = pUnit;
1387 pVM->ssm.s.cUnits--;
1388 Log(("SSM: Removed data unit '%s' (pdm drv).\n", pFree->szName));
1389 MMR3HeapFree(pFree);
1390
1391 if (pszName)
1392 return VINF_SUCCESS;
1393 rc = VINF_SUCCESS;
1394 continue;
1395 }
1396 else if (pszName)
1397 {
1398 AssertMsgFailed(("Caller is not owner! Owner=%p Caller=%p %s\n",
1399 pUnit->u.Drv.pDrvIns, pDrvIns, pszName));
1400 return VERR_SSM_UNIT_NOT_OWNER;
1401 }
1402 }
1403
1404 /* next */
1405 pUnitPrev = pUnit;
1406 pUnit = pUnit->pNext;
1407 }
1408
1409 return rc;
1410}
1411
1412
1413/**
1414 * Deregister a data unit.
1415 *
1416 * @returns VBox status.
1417 * @param pVM The VM handle.
1418 * @param enmType Unit type
1419 * @param pszName Data unit name.
1420 * @remark Only for dynmaic data units.
1421 */
1422static int ssmR3DeregisterByNameAndType(PVM pVM, const char *pszName, SSMUNITTYPE enmType)
1423{
1424 /*
1425 * Validate input.
1426 */
1427 if (!pszName)
1428 {
1429 AssertMsgFailed(("pszName is NULL!\n"));
1430 return VERR_INVALID_PARAMETER;
1431 }
1432
1433 /*
1434 * Search the list.
1435 */
1436 size_t cchName = strlen(pszName);
1437 int rc = VERR_SSM_UNIT_NOT_FOUND;
1438 PSSMUNIT pUnitPrev = NULL;
1439 PSSMUNIT pUnit = pVM->ssm.s.pHead;
1440 while (pUnit)
1441 {
1442 if ( pUnit->enmType == enmType
1443 && pUnit->cchName == cchName
1444 && !memcmp(pUnit->szName, pszName, cchName))
1445 {
1446 /*
1447 * Unlink it, advance pointer, and free the node.
1448 */
1449 PSSMUNIT pFree = pUnit;
1450 pUnit = pUnit->pNext;
1451 if (pUnitPrev)
1452 pUnitPrev->pNext = pUnit;
1453 else
1454 pVM->ssm.s.pHead = pUnit;
1455 pVM->ssm.s.cUnits--;
1456 Log(("SSM: Removed data unit '%s' (type=%d).\n", pFree->szName, enmType));
1457 MMR3HeapFree(pFree);
1458 return VINF_SUCCESS;
1459 }
1460
1461 /* next */
1462 pUnitPrev = pUnit;
1463 pUnit = pUnit->pNext;
1464 }
1465
1466 return rc;
1467}
1468
1469
1470/**
1471 * Deregister an internal data unit.
1472 *
1473 * @returns VBox status.
1474 * @param pVM The VM handle.
1475 * @param pszName Data unit name.
1476 * @remark Only for dynmaic data units.
1477 */
1478VMMR3DECL(int) SSMR3DeregisterInternal(PVM pVM, const char *pszName)
1479{
1480 return ssmR3DeregisterByNameAndType(pVM, pszName, SSMUNITTYPE_INTERNAL);
1481}
1482
1483
1484/**
1485 * Deregister an external data unit.
1486 *
1487 * @returns VBox status.
1488 * @param pVM The VM handle.
1489 * @param pszName Data unit name.
1490 * @remark Only for dynmaic data units.
1491 */
1492VMMR3DECL(int) SSMR3DeregisterExternal(PVM pVM, const char *pszName)
1493{
1494 return ssmR3DeregisterByNameAndType(pVM, pszName, SSMUNITTYPE_EXTERNAL);
1495}
1496
1497
1498/**
1499 * Initializes the stream after/before opening the file/whatever.
1500 *
1501 * @returns VINF_SUCCESS or VERR_NO_MEMORY.
1502 * @param pStrm The stream handle.
1503 * @param fChecksummed Whether the stream is to be checksummed while
1504 * written/read.
1505 * @param cBuffers The number of buffers.
1506 */
1507static int ssmR3StrmInit(PSSMSTRM pStrm, bool fChecksummed, uint32_t cBuffers)
1508{
1509 Assert(cBuffers > 0);
1510
1511 /*
1512 * Init the common data members.
1513 */
1514 pStrm->fTerminating = false;
1515 pStrm->fNeedSeek = false;
1516 pStrm->rc = VINF_SUCCESS;
1517 pStrm->hIoThread = NIL_RTTHREAD;
1518 pStrm->offNeedSeekTo= UINT64_MAX;
1519
1520 pStrm->pHead = NULL;
1521 pStrm->pFree = NULL;
1522 pStrm->hEvtHead = NIL_RTSEMEVENT;
1523 pStrm->hEvtFree = NIL_RTSEMEVENT;
1524
1525 pStrm->pPending = NULL;
1526 pStrm->pCur = NULL;
1527 pStrm->offCurStream = 0;
1528 pStrm->off = 0;
1529 pStrm->fChecksummed = fChecksummed;
1530 pStrm->u32StreamCRC = fChecksummed ? RTCrc32Start() : 0;
1531 pStrm->offStreamCRC = 0;
1532
1533 /*
1534 * Allocate the buffers. Page align them in case that makes the kernel
1535 * and/or cpu happier in some way.
1536 */
1537 int rc = VINF_SUCCESS;
1538 for (uint32_t i = 0; i < cBuffers; i++)
1539 {
1540 PSSMSTRMBUF pBuf = (PSSMSTRMBUF)RTMemPageAllocZ(sizeof(*pBuf));
1541 if (!pBuf)
1542 {
1543 if (i > 2)
1544 {
1545 LogRel(("ssmR3StrmAllocBuffer: WARNING: Could only get %d stream buffers.\n", i));
1546 break;
1547 }
1548 LogRel(("ssmR3StrmAllocBuffer: Failed to allocate stream buffers. (i=%d)\n", i));
1549 return VERR_NO_MEMORY;
1550 }
1551
1552 /* link it */
1553 pBuf->pNext = pStrm->pFree;
1554 pStrm->pFree = pBuf;
1555 }
1556
1557 /*
1558 * Create the event semaphores.
1559 */
1560 rc = RTSemEventCreate(&pStrm->hEvtHead);
1561 if (RT_FAILURE(rc))
1562 return rc;
1563 rc = RTSemEventCreate(&pStrm->hEvtFree);
1564 if (RT_FAILURE(rc))
1565 return rc;
1566
1567 return VINF_SUCCESS;
1568}
1569
1570
1571/**
1572 * Destroys a list of buffers.
1573 *
1574 * @param pHead Pointer to the head.
1575 */
1576static void ssmR3StrmDestroyBufList(PSSMSTRMBUF pHead)
1577{
1578 while (pHead)
1579 {
1580 PSSMSTRMBUF pCur = pHead;
1581 pHead = pCur->pNext;
1582 pCur->pNext = NULL;
1583 RTMemPageFree(pCur);
1584 }
1585}
1586
1587
1588/**
1589 * Cleans up a stream after ssmR3StrmInit has been called (regardless of it
1590 * succeeded or not).
1591 *
1592 * @param pStrm The stream handle.
1593 */
1594static void ssmR3StrmDelete(PSSMSTRM pStrm)
1595{
1596 RTMemPageFree(pStrm->pCur);
1597 pStrm->pCur = NULL;
1598 ssmR3StrmDestroyBufList(pStrm->pHead);
1599 pStrm->pHead = NULL;
1600 ssmR3StrmDestroyBufList(pStrm->pPending);
1601 pStrm->pPending = NULL;
1602 ssmR3StrmDestroyBufList(pStrm->pFree);
1603 pStrm->pFree = NULL;
1604
1605 RTSemEventDestroy(pStrm->hEvtHead);
1606 pStrm->hEvtHead = NIL_RTSEMEVENT;
1607
1608 RTSemEventDestroy(pStrm->hEvtFree);
1609 pStrm->hEvtFree = NIL_RTSEMEVENT;
1610}
1611
1612
1613/**
1614 * Opens a file stream.
1615 *
1616 * @returns VBox status code.
1617 * @param pStrm The stream manager structure.
1618 * @param pszFilename The file to open or create.
1619 * @param fWrite Whether to open for writing or reading.
1620 * @param fChecksummed Whether the stream is to be checksummed while
1621 * written/read.
1622 * @param cBuffers The number of buffers.
1623 */
1624static int ssmR3StrmOpenFile(PSSMSTRM pStrm, const char *pszFilename, bool fWrite, bool fChecksummed, uint32_t cBuffers)
1625{
1626 int rc = ssmR3StrmInit(pStrm, fChecksummed, cBuffers);
1627 if (RT_SUCCESS(rc))
1628 {
1629 uint32_t fFlags = fWrite
1630 ? RTFILE_O_READWRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_WRITE
1631 : RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE;
1632 rc = RTFileOpen(&pStrm->hFile, pszFilename, fFlags);
1633 if (RT_SUCCESS(rc))
1634 {
1635 pStrm->fWrite = fWrite;
1636 return VINF_SUCCESS;
1637 }
1638 }
1639
1640 ssmR3StrmDelete(pStrm);
1641 pStrm->rc = rc;
1642 return rc;
1643}
1644
1645
1646/**
1647 * Raise an error condition on the stream.
1648 *
1649 * @returns true if we raised the error condition, false if the stream already
1650 * had an error condition set.
1651 *
1652 * @param pStrm The stream handle.
1653 * @param rc The VBox error status code.
1654 *
1655 * @thread Any.
1656 */
1657DECLINLINE(bool) ssmR3StrmSetError(PSSMSTRM pStrm, int rc)
1658{
1659 Assert(RT_FAILURE_NP(rc));
1660 return ASMAtomicCmpXchgS32(&pStrm->rc, rc, VINF_SUCCESS);
1661}
1662
1663
1664/**
1665 * Puts a buffer into the free list.
1666 *
1667 * @param pStrm The stream handle.
1668 * @param pBuf The buffer.
1669 *
1670 * @thread The consumer.
1671 */
1672static void ssmR3StrmPutFreeBuf(PSSMSTRM pStrm, PSSMSTRMBUF pBuf)
1673{
1674 for (;;)
1675 {
1676 PSSMSTRMBUF pCurFreeHead = (PSSMSTRMBUF)ASMAtomicUoReadPtr((void * volatile *)&pStrm->pFree);
1677 ASMAtomicUoWritePtr((void * volatile *)&pBuf->pNext, pCurFreeHead);
1678 if (ASMAtomicCmpXchgPtr((void * volatile *)&pStrm->pFree, pBuf, pCurFreeHead))
1679 {
1680 int rc = RTSemEventSignal(pStrm->hEvtFree);
1681 AssertRC(rc);
1682 return;
1683 }
1684 }
1685}
1686
1687
1688/**
1689 * Gets a free buffer, waits for one if necessary.
1690 *
1691 * @returns Pointer to the buffer on success. NULL if we're terminating.
1692 * @param pStrm The stream handle.
1693 *
1694 * @thread The producer.
1695 */
1696static PSSMSTRMBUF ssmR3StrmGetFreeBuf(PSSMSTRM pStrm)
1697{
1698 for (;;)
1699 {
1700 PSSMSTRMBUF pMine = (PSSMSTRMBUF)ASMAtomicUoReadPtr((void * volatile *)&pStrm->pFree);
1701 if (!pMine)
1702 {
1703 if (pStrm->fTerminating)
1704 return NULL;
1705 if (RT_FAILURE(pStrm->rc))
1706 return NULL;
1707 if ( pStrm->fWrite
1708 && pStrm->hIoThread == NIL_RTTHREAD)
1709 {
1710 int rc = ssmR3StrmWriteBuffers(pStrm);
1711 if (RT_FAILURE(rc))
1712 return NULL;
1713 }
1714 int rc = RTSemEventWaitNoResume(pStrm->hEvtFree, 30000);
1715 if ( rc == VERR_SEM_DESTROYED
1716 || pStrm->fTerminating)
1717 return NULL;
1718 continue;
1719 }
1720
1721 if (ASMAtomicCmpXchgPtr((void * volatile *)&pStrm->pFree, pMine->pNext, pMine))
1722 {
1723 pMine->offStream = UINT64_MAX;
1724 pMine->cb = 0;
1725 pMine->pNext = NULL;
1726 pMine->fEndOfStream = false;
1727 return pMine;
1728 }
1729 }
1730}
1731
1732
1733/**
1734 * Puts a buffer onto the queue.
1735 *
1736 * @param pBuf The buffer.
1737 *
1738 * @thread The producer.
1739 */
1740static void ssmR3StrmPutBuf(PSSMSTRM pStrm, PSSMSTRMBUF pBuf)
1741{
1742 for (;;)
1743 {
1744 PSSMSTRMBUF pCurHead = (PSSMSTRMBUF)ASMAtomicUoReadPtr((void * volatile *)&pStrm->pHead);
1745 ASMAtomicUoWritePtr((void * volatile *)&pBuf->pNext, pCurHead);
1746 if (ASMAtomicCmpXchgPtr((void * volatile *)&pStrm->pHead, pBuf, pCurHead))
1747 {
1748 int rc = RTSemEventSignal(pStrm->hEvtHead);
1749 AssertRC(rc);
1750 return;
1751 }
1752 }
1753}
1754
1755
1756/**
1757 * Reverses the list.
1758 *
1759 * @returns The head of the reversed list.
1760 * @param pHead The head of the list to reverse.
1761 */
1762static PSSMSTRMBUF ssmR3StrmReverseList(PSSMSTRMBUF pHead)
1763{
1764 PSSMSTRMBUF pRevHead = NULL;
1765 while (pHead)
1766 {
1767 PSSMSTRMBUF pCur = pHead;
1768 pHead = pCur->pNext;
1769 pCur->pNext = pRevHead;
1770 pRevHead = pCur;
1771 }
1772 return pRevHead;
1773}
1774
1775
1776/**
1777 * Gets one buffer from the queue, will wait for one to become ready if
1778 * necessary.
1779 *
1780 * @returns Pointer to the buffer on success. NULL if we're terminating.
1781 * @param pBuf The buffer.
1782 *
1783 * @thread The consumer.
1784 */
1785static PSSMSTRMBUF ssmR3StrmGetBuf(PSSMSTRM pStrm)
1786{
1787 for (;;)
1788 {
1789 PSSMSTRMBUF pMine = pStrm->pPending;
1790 if (pMine)
1791 {
1792 pStrm->pPending = pMine->pNext;
1793 pMine->pNext = NULL;
1794 return pMine;
1795 }
1796
1797 pMine = (PSSMSTRMBUF)ASMAtomicXchgPtr((void * volatile *)&pStrm->pHead, NULL);
1798 if (pMine)
1799 pStrm->pPending = ssmR3StrmReverseList(pMine);
1800 else
1801 {
1802 if (pStrm->fTerminating)
1803 return NULL;
1804 if (RT_FAILURE(pStrm->rc))
1805 return NULL;
1806 if ( !pStrm->fWrite
1807 && pStrm->hIoThread == NIL_RTTHREAD)
1808 {
1809 int rc = ssmR3StrmReadMore(pStrm);
1810 if (RT_FAILURE(rc))
1811 return NULL;
1812 continue;
1813 }
1814
1815 int rc = RTSemEventWaitNoResume(pStrm->hEvtHead, 30000);
1816 if ( rc == VERR_SEM_DESTROYED
1817 || pStrm->fTerminating)
1818 return NULL;
1819 }
1820 }
1821}
1822
1823
1824/**
1825 * Flushes the current buffer (both write and read streams).
1826 *
1827 * @param pStrm The stream handle.
1828 */
1829static void ssmR3StrmFlushCurBuf(PSSMSTRM pStrm)
1830{
1831 if (pStrm->pCur)
1832 {
1833 PSSMSTRMBUF pBuf = pStrm->pCur;
1834 pStrm->pCur = NULL;
1835
1836 if (pStrm->fWrite)
1837 {
1838 uint32_t cb = pStrm->off;
1839 pBuf->cb = cb;
1840 pBuf->offStream = pStrm->offCurStream;
1841 if ( pStrm->fChecksummed
1842 && pStrm->offStreamCRC < cb)
1843 pStrm->u32StreamCRC = RTCrc32Process(pStrm->u32StreamCRC,
1844 &pBuf->abData[pStrm->offStreamCRC],
1845 cb - pStrm->offStreamCRC);
1846 pStrm->offCurStream += cb;
1847 pStrm->off = 0;
1848 pStrm->offStreamCRC = 0;
1849
1850 ssmR3StrmPutBuf(pStrm, pBuf);
1851 }
1852 else
1853 {
1854 uint32_t cb = pBuf->cb;
1855 if ( pStrm->fChecksummed
1856 && pStrm->offStreamCRC < cb)
1857 pStrm->u32StreamCRC = RTCrc32Process(pStrm->u32StreamCRC,
1858 &pBuf->abData[pStrm->offStreamCRC],
1859 cb - pStrm->offStreamCRC);
1860 pStrm->offCurStream += cb;
1861 pStrm->off = 0;
1862 pStrm->offStreamCRC = 0;
1863
1864 ssmR3StrmPutFreeBuf(pStrm, pBuf);
1865 }
1866 }
1867}
1868
1869
1870/**
1871 * Flush buffered data.
1872 *
1873 * @returns VBox status code. Returns VINF_EOF if we encounter a buffer with the
1874 * fEndOfStream indicator set.
1875 * @param pStrm The stream handle.
1876 *
1877 * @thread The producer thread.
1878 */
1879static int ssmR3StrmWriteBuffers(PSSMSTRM pStrm)
1880{
1881 Assert(pStrm->fWrite);
1882
1883 /*
1884 * Just return if the stream has a pending error condition.
1885 */
1886 int rc = pStrm->rc;
1887 if (RT_FAILURE(rc))
1888 return rc;
1889
1890 /*
1891 * Grab the pending list and write it out.
1892 */
1893 PSSMSTRMBUF pHead = (PSSMSTRMBUF)ASMAtomicXchgPtr((void * volatile *)&pStrm->pHead, NULL);
1894 if (!pHead)
1895 return VINF_SUCCESS;
1896 pHead = ssmR3StrmReverseList(pHead);
1897
1898 while (pHead)
1899 {
1900 /* pop */
1901 PSSMSTRMBUF pCur = pHead;
1902 pHead = pCur->pNext;
1903
1904 /* flush */
1905 int rc = RTFileWriteAt(pStrm->hFile, pCur->offStream, &pCur->abData[0], pCur->cb, NULL);
1906 if ( RT_FAILURE(rc)
1907 && ssmR3StrmSetError(pStrm, rc))
1908 LogRel(("ssmR3StrmWriteBuffers: RTFileWriteAt failed with rc=%Rrc at offStream=%#llx\n", rc, pCur->offStream));
1909
1910 /* free */
1911 bool fEndOfStream = pCur->fEndOfStream;
1912 ssmR3StrmPutFreeBuf(pStrm, pCur);
1913 if (fEndOfStream)
1914 {
1915 Assert(!pHead);
1916 return VINF_EOF;
1917 }
1918 }
1919
1920 return pStrm->rc;
1921}
1922
1923
1924/**
1925 * Closes the stream after first flushing any pending write.
1926 *
1927 * @returns VBox status code.
1928 * @param pStrm The stream handle.
1929 */
1930static int ssmR3StrmClose(PSSMSTRM pStrm)
1931{
1932 /*
1933 * Flush, terminate the I/O thread, and close the stream.
1934 */
1935 if (pStrm->fWrite)
1936 {
1937 ssmR3StrmFlushCurBuf(pStrm);
1938 if (pStrm->hIoThread == NIL_RTTHREAD)
1939 ssmR3StrmWriteBuffers(pStrm);
1940 }
1941
1942 if (pStrm->hIoThread != NIL_RTTHREAD)
1943 {
1944 ASMAtomicWriteBool(&pStrm->fTerminating, true);
1945 int rc2 = RTSemEventSignal(pStrm->fWrite ? pStrm->hEvtHead : pStrm->hEvtFree); AssertLogRelRC(rc2);
1946 int rc3 = RTThreadWait(pStrm->hIoThread, RT_INDEFINITE_WAIT, NULL); AssertLogRelRC(rc3);
1947 pStrm->hIoThread = NIL_RTTHREAD;
1948 }
1949
1950 int rc = RTFileClose(pStrm->hFile);
1951 if (RT_FAILURE(rc))
1952 ssmR3StrmSetError(pStrm, rc);
1953 pStrm->hFile = NIL_RTFILE;
1954
1955 rc = pStrm->rc;
1956 ssmR3StrmDelete(pStrm);
1957
1958 return rc;
1959}
1960
1961
1962/**
1963 * Stream output routine.
1964 *
1965 * @returns VBox status code.
1966 * @param pStrm The stream handle.
1967 * @param pvBuf What to write.
1968 * @param cbToWrite How much to write.
1969 *
1970 * @thread The producer in a write stream (never the I/O thread).
1971 */
1972static int ssmR3StrmWrite(PSSMSTRM pStrm, const void *pvBuf, size_t cbToWrite)
1973{
1974 AssertReturn(cbToWrite > 0, VINF_SUCCESS);
1975 Assert(pStrm->fWrite);
1976
1977 /*
1978 * Squeeze as much as possible into the current buffer.
1979 */
1980 PSSMSTRMBUF pBuf = pStrm->pCur;
1981 if (RT_LIKELY(pBuf))
1982 {
1983 uint32_t cbLeft = RT_SIZEOFMEMB(SSMSTRMBUF, abData) - pStrm->off;
1984 if (RT_LIKELY(cbLeft >= cbToWrite))
1985 {
1986 memcpy(&pBuf->abData[pStrm->off], pvBuf, cbToWrite);
1987 pStrm->off += (uint32_t)cbToWrite;
1988 return VINF_SUCCESS;
1989 }
1990
1991 if (cbLeft > 0)
1992 {
1993 memcpy(&pBuf->abData[pStrm->off], pvBuf, cbLeft);
1994 pStrm->off += cbLeft;
1995 cbToWrite -= cbLeft;
1996 pvBuf = (uint8_t const *)pvBuf + cbLeft;
1997 }
1998 Assert(pStrm->off == RT_SIZEOFMEMB(SSMSTRMBUF, abData));
1999 }
2000
2001 /*
2002 * Need one or more new buffers.
2003 */
2004 do
2005 {
2006 /*
2007 * Flush the current buffer and replace it with a new one.
2008 */
2009 ssmR3StrmFlushCurBuf(pStrm);
2010 pBuf = ssmR3StrmGetFreeBuf(pStrm);
2011 if (!pBuf)
2012 break;
2013 pStrm->pCur = pBuf;
2014 Assert(pStrm->off == 0);
2015
2016 /*
2017 * Copy data to the buffer.
2018 */
2019 uint32_t cbCopy = RT_SIZEOFMEMB(SSMSTRMBUF, abData);
2020 if (cbCopy > cbToWrite)
2021 cbCopy = (uint32_t)cbToWrite;
2022 memcpy(&pBuf->abData[0], pvBuf, cbCopy);
2023 pStrm->off = cbCopy;
2024 cbToWrite -= cbCopy;
2025 pvBuf = (uint8_t const *)pvBuf + cbCopy;
2026 } while (cbToWrite > 0);
2027
2028 return pStrm->rc;
2029}
2030
2031
2032/**
2033 * Reserves space in the current buffer so the caller can write directly to the
2034 * buffer instead of doing double buffering.
2035 *
2036 * @returns VBox status code
2037 * @param pStrm The stream handle.
2038 * @param cb The amount of buffer space to reserve.
2039 * @param ppb Where to return the pointer.
2040 */
2041static int ssmR3StrmReserveWriteBufferSpace(PSSMSTRM pStrm, size_t cb, uint8_t **ppb)
2042{
2043 Assert(pStrm->fWrite);
2044 Assert(RT_SIZEOFMEMB(SSMSTRMBUF, abData) / 4 >= cb);
2045
2046 /*
2047 * Check if there is room in the current buffer, it not flush it.
2048 */
2049 PSSMSTRMBUF pBuf = pStrm->pCur;
2050 if (pBuf)
2051 {
2052 uint32_t cbLeft = RT_SIZEOFMEMB(SSMSTRMBUF, abData) - pStrm->off;
2053 if (cbLeft >= cb)
2054 {
2055 *ppb = &pBuf->abData[pStrm->off];
2056 return VINF_SUCCESS;
2057 }
2058
2059 ssmR3StrmFlushCurBuf(pStrm);
2060 }
2061
2062 /*
2063 * Get a fresh buffer and return a pointer into it.
2064 */
2065 pBuf = ssmR3StrmGetFreeBuf(pStrm);
2066 if (pBuf)
2067 {
2068 pStrm->pCur = pBuf;
2069 Assert(pStrm->off == 0);
2070 *ppb = &pBuf->abData[0];
2071 }
2072 else
2073 *ppb = NULL; /* make gcc happy. */
2074 return pStrm->rc;
2075}
2076
2077
2078/**
2079 * Commits buffer space reserved by ssmR3StrmReserveWriteBufferSpace.
2080 *
2081 * @returns VBox status code.
2082 * @param pStrm The stream handle.
2083 * @param cb The amount of buffer space to commit. This can be less
2084 * that what was reserved initially.
2085 */
2086static int ssmR3StrmCommitWriteBufferSpace(PSSMSTRM pStrm, size_t cb)
2087{
2088 Assert(pStrm->pCur);
2089 Assert(pStrm->off + cb <= RT_SIZEOFMEMB(SSMSTRMBUF, abData));
2090 pStrm->off += cb;
2091 return VINF_SUCCESS;
2092}
2093
2094
2095/**
2096 * Marks the end of the stream.
2097 *
2098 * This will cause the I/O thread to quit waiting for more buffers.
2099 *
2100 * @returns VBox status code.
2101 * @param pStrm The stream handle.
2102 */
2103static int ssmR3StrmSetEnd(PSSMSTRM pStrm)
2104{
2105 Assert(pStrm->fWrite);
2106 PSSMSTRMBUF pBuf = pStrm->pCur;
2107 if (RT_UNLIKELY(!pStrm->pCur))
2108 {
2109 pBuf = ssmR3StrmGetFreeBuf(pStrm);
2110 if (!pBuf)
2111 return pStrm->rc;
2112 pStrm->pCur = pBuf;
2113 Assert(pStrm->off == 0);
2114 }
2115 pBuf->fEndOfStream = true;
2116 ssmR3StrmFlushCurBuf(pStrm);
2117 return VINF_SUCCESS;
2118}
2119
2120
2121/**
2122 * Read more from the stream.
2123 *
2124 * @returns VBox status code. VERR_EOF gets translated into VINF_EOF.
2125 * @param pStrm The stream handle.
2126 *
2127 * @thread The I/O thread when we got one, otherwise the stream user.
2128 */
2129static int ssmR3StrmReadMore(PSSMSTRM pStrm)
2130{
2131 int rc;
2132 Log6(("ssmR3StrmReadMore:\n"));
2133
2134 /*
2135 * Undo seek done by ssmR3StrmPeekAt.
2136 */
2137 if (pStrm->fNeedSeek)
2138 {
2139 rc = RTFileSeek(pStrm->hFile, pStrm->offNeedSeekTo, RTFILE_SEEK_BEGIN, NULL);
2140 if (RT_FAILURE(rc))
2141 {
2142 if (ssmR3StrmSetError(pStrm, rc))
2143 LogRel(("ssmR3StrmReadMore: RTFileSeek(,%#llx,) failed with rc=%Rrc\n", pStrm->offNeedSeekTo, rc));
2144 return rc;
2145 }
2146 pStrm->fNeedSeek = false;
2147 pStrm->offNeedSeekTo = UINT64_MAX;
2148 }
2149
2150 /*
2151 * Get a free buffer and try fill it up.
2152 */
2153 PSSMSTRMBUF pBuf = ssmR3StrmGetFreeBuf(pStrm);
2154 if (!pBuf)
2155 return pStrm->rc;
2156
2157 pBuf->offStream = RTFileTell(pStrm->hFile);
2158 size_t cbRead = sizeof(pBuf->abData);
2159 rc = RTFileRead(pStrm->hFile, &pBuf->abData[0], cbRead, &cbRead);
2160 if ( RT_SUCCESS(rc)
2161 && cbRead > 0)
2162 {
2163 pBuf->cb = (uint32_t)cbRead;
2164 pBuf->fEndOfStream = false;
2165 Log6(("ssmR3StrmReadMore: %#010llx %#x\n", pBuf->offStream, pBuf->cb));
2166 ssmR3StrmPutBuf(pStrm, pBuf);
2167 }
2168 else if ( ( RT_SUCCESS_NP(rc)
2169 && cbRead == 0)
2170 || rc == VERR_EOF)
2171 {
2172 pBuf->cb = 0;
2173 pBuf->fEndOfStream = true;
2174 Log6(("ssmR3StrmReadMore: %#010llx 0 EOF!\n", pBuf->offStream));
2175 ssmR3StrmPutBuf(pStrm, pBuf);
2176 rc = VINF_EOF;
2177 }
2178 else
2179 {
2180 Log6(("ssmR3StrmReadMore: %#010llx rc=%Rrc!\n", pBuf->offStream, rc));
2181 if (ssmR3StrmSetError(pStrm, rc))
2182 LogRel(("ssmR3StrmReadMore: RTFileRead(,,%#x,) -> %Rrc at offset %#llx\n",
2183 sizeof(pBuf->abData), rc, pBuf->offStream));
2184 ssmR3StrmPutFreeBuf(pStrm, pBuf);
2185 }
2186 return rc;
2187}
2188
2189
2190/**
2191 * Stream input routine.
2192 *
2193 * @returns VBox status code.
2194 * @param pStrm The stream handle.
2195 * @param pvBuf Where to put what we read.
2196 * @param cbToRead How much to read.
2197 */
2198static int ssmR3StrmRead(PSSMSTRM pStrm, void *pvBuf, size_t cbToRead)
2199{
2200 AssertReturn(cbToRead > 0, VINF_SUCCESS);
2201 Assert(!pStrm->fWrite);
2202
2203 /*
2204 * Read from the current buffer if we got one.
2205 */
2206 PSSMSTRMBUF pBuf = pStrm->pCur;
2207 if (RT_LIKELY(pBuf))
2208 {
2209 Assert(pStrm->off <= pBuf->cb);
2210 uint32_t cbLeft = pBuf->cb - pStrm->off;
2211 if (cbLeft >= cbToRead)
2212 {
2213 memcpy(pvBuf, &pBuf->abData[pStrm->off], cbToRead);
2214 pStrm->off += (uint32_t)cbToRead;
2215 Assert(pStrm->off <= pBuf->cb);
2216 return VINF_SUCCESS;
2217 }
2218 if (cbLeft)
2219 {
2220 memcpy(pvBuf, &pBuf->abData[pStrm->off], cbLeft);
2221 pStrm->off += cbLeft;
2222 cbToRead -= cbLeft;
2223 pvBuf = (uint8_t *)pvBuf + cbLeft;
2224 }
2225 else if (pBuf->fEndOfStream)
2226 return VERR_EOF;
2227 Assert(pStrm->off == pBuf->cb);
2228 }
2229
2230 /*
2231 * Get more buffers from the stream.
2232 */
2233 int rc = VINF_SUCCESS;
2234 do
2235 {
2236 /*
2237 * Check for EOF first - never flush the EOF buffer.
2238 */
2239 if ( pBuf
2240 && pBuf->fEndOfStream)
2241 return VERR_EOF;
2242
2243 /*
2244 * Flush the current buffer and get the next one.
2245 */
2246 ssmR3StrmFlushCurBuf(pStrm);
2247 PSSMSTRMBUF pBuf = ssmR3StrmGetBuf(pStrm);
2248 if (!pBuf)
2249 {
2250 rc = pStrm->rc;
2251 break;
2252 }
2253 pStrm->pCur = pBuf;
2254 Assert(pStrm->off == 0);
2255 Assert(pStrm->offCurStream == pBuf->offStream);
2256 if (!pBuf->cb)
2257 {
2258 Assert(pBuf->fEndOfStream);
2259 return VERR_EOF;
2260 }
2261
2262 /*
2263 * Read data from the buffer.
2264 */
2265 uint32_t cbCopy = pBuf->cb;
2266 if (cbCopy > cbToRead)
2267 cbCopy = (uint32_t)cbToRead;
2268 memcpy(pvBuf, &pBuf->abData[0], cbCopy);
2269 pStrm->off = cbCopy;
2270 cbToRead -= cbCopy;
2271 pvBuf = (uint8_t *)pvBuf + cbCopy;
2272 Assert(!pStrm->pCur || pStrm->off <= pStrm->pCur->cb);
2273 } while (cbToRead > 0);
2274
2275 return rc;
2276}
2277
2278
2279/**
2280 * Reads data from the stream but instead of copying it to some output buffer
2281 * the caller gets a pointer to into the current stream buffer.
2282 *
2283 * The returned pointer becomes invalid after the next stream operation!
2284 *
2285 * @returns Pointer to the read data residing in the stream buffer. NULL is
2286 * returned if the request amount of data isn't available in the
2287 * buffer. The caller must fall back on ssmR3StrmRead when this
2288 * happens.
2289 *
2290 * @param pStrm The stream handle.
2291 * @param cbToRead The number of bytes to tread.
2292 */
2293static uint8_t const *ssmR3StrmReadDirect(PSSMSTRM pStrm, size_t cbToRead)
2294{
2295 AssertReturn(cbToRead > 0, VINF_SUCCESS);
2296 Assert(!pStrm->fWrite);
2297
2298 /*
2299 * Too lazy to fetch more data for the odd case that we're
2300 * exactly at the boundrary between two buffers.
2301 */
2302 PSSMSTRMBUF pBuf = pStrm->pCur;
2303 if (RT_LIKELY(pBuf))
2304 {
2305 Assert(pStrm->off <= pBuf->cb);
2306 uint32_t cbLeft = pBuf->cb - pStrm->off;
2307 if (cbLeft >= cbToRead)
2308 {
2309 uint8_t const *pb = &pBuf->abData[pStrm->off];
2310 pStrm->off += (uint32_t)cbToRead;
2311 Assert(pStrm->off <= pBuf->cb);
2312 return pb;
2313 }
2314 }
2315 return NULL;
2316}
2317
2318
2319/**
2320 * Tell current stream position.
2321 *
2322 * @returns stream position.
2323 * @param pStrm The stream handle.
2324 */
2325static uint64_t ssmR3StrmTell(PSSMSTRM pStrm)
2326{
2327 return pStrm->offCurStream + pStrm->off;
2328}
2329
2330
2331/**
2332 * Gets the intermediate stream CRC up to the current position.
2333 *
2334 * @returns CRC.
2335 * @param pStrm The stream handle.
2336 */
2337static uint32_t ssmR3StrmCurCRC(PSSMSTRM pStrm)
2338{
2339 if (!pStrm->fChecksummed)
2340 return 0;
2341 if (pStrm->offStreamCRC < pStrm->off)
2342 {
2343 PSSMSTRMBUF pBuf = pStrm->pCur; Assert(pBuf);
2344 pStrm->u32StreamCRC = RTCrc32Process(pStrm->u32StreamCRC, &pBuf->abData[pStrm->offStreamCRC], pStrm->off - pStrm->offStreamCRC);
2345 pStrm->offStreamCRC = pStrm->off;
2346 }
2347 else
2348 Assert(pStrm->offStreamCRC == pStrm->off);
2349 return pStrm->u32StreamCRC;
2350}
2351
2352
2353/**
2354 * Gets the final stream CRC up to the current position.
2355 *
2356 * @returns CRC.
2357 * @param pStrm The stream handle.
2358 */
2359static uint32_t ssmR3StrmFinalCRC(PSSMSTRM pStrm)
2360{
2361 if (!pStrm->fChecksummed)
2362 return 0;
2363 return RTCrc32Finish(ssmR3StrmCurCRC(pStrm));
2364}
2365
2366
2367/**
2368 * Disables checksumming of the stream.
2369 *
2370 * @param pStrm The stream handle.
2371 */
2372static void ssmR3StrmDisableChecksumming(PSSMSTRM pStrm)
2373{
2374 pStrm->fChecksummed = false;
2375}
2376
2377
2378/**
2379 * Used by SSMR3Seek to position the stream at the new unit.
2380 *
2381 * @returns VBox stutus code.
2382 * @param pStrm The strem handle.
2383 * @param off The seek offset.
2384 * @param uMethod The seek method.
2385 * @param u32CurCRC The current CRC at the seek position.
2386 */
2387static int ssmR3StrmSeek(PSSMSTRM pStrm, int64_t off, uint32_t uMethod, uint32_t u32CurCRC)
2388{
2389 AssertReturn(!pStrm->fWrite, VERR_NOT_SUPPORTED);
2390 AssertReturn(pStrm->hIoThread == NIL_RTTHREAD, VERR_WRONG_ORDER);
2391
2392 uint64_t offStream;
2393 int rc = RTFileSeek(pStrm->hFile, off, uMethod, &offStream);
2394 if (RT_SUCCESS(rc))
2395 {
2396 pStrm->fNeedSeek = false;
2397 pStrm->offNeedSeekTo= UINT64_MAX;
2398 pStrm->offCurStream = offStream;
2399 pStrm->off = 0;
2400 pStrm->offStreamCRC = 0;
2401 if (pStrm->fChecksummed)
2402 pStrm->u32StreamCRC = u32CurCRC;
2403 if (pStrm->pCur)
2404 {
2405 ssmR3StrmPutFreeBuf(pStrm, pStrm->pCur);
2406 pStrm->pCur = NULL;
2407 }
2408 }
2409 return rc;
2410}
2411
2412
2413/**
2414 * Skip some bytes in the stream.
2415 *
2416 * This is only used if someone didn't read all of their data in the V1 format,
2417 * so don't bother making this very efficient yet.
2418 *
2419 * @returns VBox status code.
2420 * @param pStrm The stream handle.
2421 * @param offDst The destination offset.
2422 */
2423static int ssmR3StrmSkipTo(PSSMSTRM pStrm, uint64_t offDst)
2424{
2425 /* dead simple - lazy bird! */
2426 for (;;)
2427 {
2428 uint64_t offCur = ssmR3StrmTell(pStrm);
2429 AssertReturn(offCur <= offDst, VERR_INTERNAL_ERROR_4);
2430 if (offCur == offDst)
2431 return VINF_SUCCESS;
2432
2433 uint8_t abBuf[4096];
2434 size_t cbToRead = RT_MIN(sizeof(abBuf), offDst - offCur);
2435 int rc = ssmR3StrmRead(pStrm, abBuf, cbToRead);
2436 if (RT_FAILURE(rc))
2437 return rc;
2438 }
2439}
2440
2441
2442/**
2443 * Get the size of the file.
2444 *
2445 * This does not work for non-file streams!
2446 *
2447 * @returns The file size, or UINT64_MAX if not a file stream.
2448 * @param pStrm The stream handle.
2449 */
2450static uint64_t ssmR3StrmGetSize(PSSMSTRM pStrm)
2451{
2452 uint64_t cbFile;
2453 int rc = RTFileGetSize(pStrm->hFile, &cbFile);
2454 AssertLogRelRCReturn(rc, UINT64_MAX);
2455 return cbFile;
2456}
2457
2458
2459/***
2460 * Tests if the stream is a file stream or not.
2461 *
2462 * @returns true / false.
2463 * @param pStrm The stream handle.
2464 */
2465static bool ssmR3StrmIsFile(PSSMSTRM pStrm)
2466{
2467 return pStrm->hFile != NIL_RTFILE;
2468}
2469
2470
2471/**
2472 * Peeks at data in a file stream without buffering anything (or upsetting
2473 * the buffering for that matter).
2474 *
2475 * @returns VBox status code.
2476 * @param pStrm The stream handle
2477 * @param off The offset to start peeking at. Use a negative offset to
2478 * peek at something relative to the end of the file.
2479 * @param pvBuf Output buffer.
2480 * @param cbToRead How much to read.
2481 * @param poff Where to optionally store the position. Useful when
2482 * using a negative off.
2483 *
2484 * @remarks Failures occuring while peeking will not be raised on the stream.
2485 */
2486static int ssmR3StrmPeekAt(PSSMSTRM pStrm, RTFOFF off, void *pvBuf, size_t cbToRead, uint64_t *poff)
2487{
2488 AssertReturn(!pStrm->fWrite && pStrm->hFile != NIL_RTFILE, VERR_NOT_SUPPORTED);
2489 AssertReturn(pStrm->hIoThread == NIL_RTTHREAD, VERR_WRONG_ORDER);
2490
2491 if (!pStrm->fNeedSeek)
2492 {
2493 pStrm->fNeedSeek = true;
2494 pStrm->offNeedSeekTo = pStrm->offCurStream + (pStrm->pCur ? pStrm->pCur->cb : 0);
2495 }
2496
2497 int rc = RTFileSeek(pStrm->hFile, off, off >= 0 ? RTFILE_SEEK_BEGIN : RTFILE_SEEK_END, poff);
2498 if (RT_SUCCESS(rc))
2499 rc = RTFileRead(pStrm->hFile, pvBuf, cbToRead, NULL);
2500
2501 return rc;
2502}
2503
2504
2505/**
2506 * The I/O thread.
2507 *
2508 * @returns VINF_SUCCESS (ignored).
2509 * @param hSelf The thread handle.
2510 * @param pvStrm The stream handle.
2511 */
2512static DECLCALLBACK(int) ssmR3StrmIoThread(RTTHREAD hSelf, void *pvStrm)
2513{
2514 PSSMSTRM pStrm = (PSSMSTRM)pvStrm;
2515 ASMAtomicWriteHandle(&pStrm->hIoThread, hSelf); /* paranoia */
2516
2517 Log(("ssmR3StrmIoThread: starts working\n"));
2518 if (pStrm->fWrite)
2519 {
2520 /*
2521 * Write until error or terminated.
2522 */
2523 for (;;)
2524 {
2525 int rc = ssmR3StrmWriteBuffers(pStrm);
2526 if ( RT_FAILURE(rc)
2527 || rc == VINF_EOF)
2528 {
2529 Log(("ssmR3StrmIoThread: quitting writing with rc=%Rrc.\n", rc));
2530 break;
2531 }
2532 if (RT_FAILURE(pStrm->rc))
2533 {
2534 Log(("ssmR3StrmIoThread: quitting writing with stream rc=%Rrc\n", pStrm->rc));
2535 break;
2536 }
2537
2538 if (ASMAtomicReadBool(&pStrm->fTerminating))
2539 {
2540 if (!ASMAtomicReadPtr((void * volatile *)&pStrm->pHead))
2541 {
2542 Log(("ssmR3StrmIoThread: quitting writing because of pending termination.\n"));
2543 break;
2544 }
2545 Log(("ssmR3StrmIoThread: postponing termination because of pending buffers.\n"));
2546 }
2547 else if (!ASMAtomicReadPtr((void * volatile *)&pStrm->pHead))
2548 {
2549 rc = RTSemEventWait(pStrm->hEvtHead, RT_INDEFINITE_WAIT);
2550 AssertLogRelRC(rc);
2551 }
2552 }
2553 }
2554 else
2555 {
2556 /*
2557 * Read until end of file, error or termination.
2558 */
2559 for (;;)
2560 {
2561 if (ASMAtomicReadBool(&pStrm->fTerminating))
2562 {
2563 Log(("ssmR3StrmIoThread: quitting reading because of pending termination.\n"));
2564 break;
2565 }
2566
2567 int rc = ssmR3StrmReadMore(pStrm);
2568 if ( RT_FAILURE(rc)
2569 || rc == VINF_EOF)
2570 {
2571 Log(("ssmR3StrmIoThread: quitting reading with rc=%Rrc\n", rc));
2572 break;
2573 }
2574 if (RT_FAILURE(pStrm->rc))
2575 {
2576 Log(("ssmR3StrmIoThread: quitting reading with stream rc=%Rrc\n", pStrm->rc));
2577 break;
2578 }
2579 }
2580 }
2581
2582 return VINF_SUCCESS;
2583}
2584
2585
2586/**
2587 * Starts the I/O thread for the specified stream.
2588 *
2589 * @param pStrm The stream handle.
2590 */
2591static void ssmR3StrmStartIoThread(PSSMSTRM pStrm)
2592{
2593 Assert(pStrm->hIoThread == NIL_RTTHREAD);
2594
2595 RTTHREAD hThread;
2596 int rc = RTThreadCreate(&hThread, ssmR3StrmIoThread, pStrm, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SSM-IO");
2597 AssertRCReturnVoid(rc);
2598 ASMAtomicWriteHandle(&pStrm->hIoThread, hThread); /* paranoia */
2599}
2600
2601
2602/**
2603 * Works the progress calculation.
2604 *
2605 * @param pSSM The SSM handle.
2606 * @param cbAdvance Number of bytes to advance
2607 */
2608static void ssmR3Progress(PSSMHANDLE pSSM, uint64_t cbAdvance)
2609{
2610 /* Can't advance it beyond the estimated end of the unit. */
2611 uint64_t cbLeft = pSSM->offEstUnitEnd - pSSM->offEst;
2612 if (cbAdvance > cbLeft)
2613 cbAdvance = cbLeft;
2614 pSSM->offEst += cbAdvance;
2615
2616 /* uPercentPrepare% prepare, xx% exec, uPercentDone% done+crc */
2617 while ( pSSM->offEst >= pSSM->offEstProgress
2618 && pSSM->uPercent <= 100-pSSM->uPercentDone)
2619 {
2620 if (pSSM->pfnProgress)
2621 pSSM->pfnProgress(pSSM->pVM, pSSM->uPercent, pSSM->pvUser);
2622 pSSM->uPercent++;
2623 pSSM->offEstProgress = (pSSM->uPercent - pSSM->uPercentPrepare) * pSSM->cbEstTotal
2624 / (100 - pSSM->uPercentDone - pSSM->uPercentPrepare);
2625 }
2626}
2627
2628
2629/**
2630 * Makes the SSM operation cancellable or not (via SSMR3Cancel).
2631 *
2632 * @param pVM The VM handle.
2633 * @param pSSM The saved state handle. (SSMHANDLE::rc may be set.)
2634 * @param fCancellable The new state.
2635 */
2636static void ssmR3SetCancellable(PVM pVM, PSSMHANDLE pSSM, bool fCancellable)
2637{
2638 RTCritSectEnter(&pVM->ssm.s.CancelCritSect);
2639 if (fCancellable)
2640 {
2641 Assert(!pVM->ssm.s.pSSM);
2642 pVM->ssm.s.pSSM = pSSM;
2643 }
2644 else
2645 {
2646 if (pVM->ssm.s.pSSM == pSSM)
2647 pVM->ssm.s.pSSM = NULL;
2648
2649 uint32_t fCancelled = ASMAtomicUoReadU32(&pSSM->fCancelled);
2650 if ( fCancelled == SSMHANDLE_CANCELLED
2651 && RT_SUCCESS(pSSM->rc))
2652 pSSM->rc = VERR_SSM_CANCELLED;
2653 }
2654
2655 RTCritSectLeave(&pVM->ssm.s.CancelCritSect);
2656}
2657
2658
2659/**
2660 * Finishes a data unit.
2661 * All buffers and compressor instances are flushed and destroyed.
2662 *
2663 * @returns VBox status.
2664 * @param pSSM SSM operation handle.
2665 */
2666static int ssmR3DataWriteFinish(PSSMHANDLE pSSM)
2667{
2668 //Log2(("ssmR3DataWriteFinish: %#010llx start\n", ssmR3StrmTell(&pSSM->Strm)));
2669 int rc = ssmR3DataFlushBuffer(pSSM);
2670 if (RT_SUCCESS(rc))
2671 {
2672 pSSM->offUnit = UINT64_MAX;
2673 return VINF_SUCCESS;
2674 }
2675
2676 if (RT_SUCCESS(pSSM->rc))
2677 pSSM->rc = rc;
2678 Log2(("ssmR3DataWriteFinish: failure rc=%Rrc\n", rc));
2679 return rc;
2680}
2681
2682
2683/**
2684 * Begins writing the data of a data unit.
2685 *
2686 * Errors are signalled via pSSM->rc.
2687 *
2688 * @param pSSM The saved state handle.
2689 */
2690static void ssmR3DataWriteBegin(PSSMHANDLE pSSM)
2691{
2692 pSSM->offUnit = 0;
2693}
2694
2695
2696/**
2697 * Writes a record to the current data item in the saved state file.
2698 *
2699 * @returns VBox status code. Sets pSSM->rc on failure.
2700 * @param pSSM The saved state handle.
2701 * @param pvBuf The bits to write.
2702 * @param cbBuf The number of bytes to write.
2703 */
2704static int ssmR3DataWriteRaw(PSSMHANDLE pSSM, const void *pvBuf, size_t cbBuf)
2705{
2706 Log2(("ssmR3DataWriteRaw: %08llx|%08llx: pvBuf=%p cbBuf=%#x %.*Rhxs%s\n",
2707 ssmR3StrmTell(&pSSM->Strm), pSSM->offUnit, pvBuf, cbBuf, RT_MIN(cbBuf, SSM_LOG_BYTES), pvBuf, cbBuf > SSM_LOG_BYTES ? "..." : ""));
2708
2709 /*
2710 * Check that everything is fine.
2711 */
2712 if (RT_FAILURE(pSSM->rc))
2713 return pSSM->rc;
2714
2715 /*
2716 * Write the data item in 1MB chunks for progress indicator reasons.
2717 */
2718 while (cbBuf > 0)
2719 {
2720 size_t cbChunk = RT_MIN(cbBuf, _1M);
2721 int rc = ssmR3StrmWrite(&pSSM->Strm, pvBuf, cbChunk);
2722 if (RT_FAILURE(rc))
2723 return rc;
2724 pSSM->offUnit += cbChunk;
2725 cbBuf -= cbChunk;
2726 pvBuf = (char *)pvBuf + cbChunk;
2727 }
2728
2729 return VINF_SUCCESS;
2730}
2731
2732
2733/**
2734 * Writes a record header for the specified amount of data.
2735 *
2736 * @returns VBox status code. Sets pSSM->rc on failure.
2737 * @param pSSM The saved state handle
2738 * @param cb The amount of data.
2739 * @param u8TypeAndFlags The record type and flags.
2740 */
2741static int ssmR3DataWriteRecHdr(PSSMHANDLE pSSM, size_t cb, uint8_t u8TypeAndFlags)
2742{
2743 size_t cbHdr;
2744 uint8_t abHdr[8];
2745 abHdr[0] = u8TypeAndFlags;
2746 if (cb < 0x80)
2747 {
2748 cbHdr = 2;
2749 abHdr[1] = (uint8_t)cb;
2750 }
2751 else if (cb < 0x00000800)
2752 {
2753 cbHdr = 3;
2754 abHdr[1] = (uint8_t)(0xc0 | (cb >> 6));
2755 abHdr[2] = (uint8_t)(0x80 | (cb & 0x3f));
2756 }
2757 else if (cb < 0x00010000)
2758 {
2759 cbHdr = 4;
2760 abHdr[1] = (uint8_t)(0xe0 | (cb >> 12));
2761 abHdr[2] = (uint8_t)(0x80 | ((cb >> 6) & 0x3f));
2762 abHdr[3] = (uint8_t)(0x80 | (cb & 0x3f));
2763 }
2764 else if (cb < 0x00200000)
2765 {
2766 cbHdr = 5;
2767 abHdr[1] = (uint8_t)(0xf0 | (cb >> 18));
2768 abHdr[2] = (uint8_t)(0x80 | ((cb >> 12) & 0x3f));
2769 abHdr[3] = (uint8_t)(0x80 | ((cb >> 6) & 0x3f));
2770 abHdr[4] = (uint8_t)(0x80 | (cb & 0x3f));
2771 }
2772 else if (cb < 0x04000000)
2773 {
2774 cbHdr = 6;
2775 abHdr[1] = (uint8_t)(0xf8 | (cb >> 24));
2776 abHdr[2] = (uint8_t)(0x80 | ((cb >> 18) & 0x3f));
2777 abHdr[3] = (uint8_t)(0x80 | ((cb >> 12) & 0x3f));
2778 abHdr[4] = (uint8_t)(0x80 | ((cb >> 6) & 0x3f));
2779 abHdr[5] = (uint8_t)(0x80 | (cb & 0x3f));
2780 }
2781 else if (cb <= 0x7fffffff)
2782 {
2783 cbHdr = 7;
2784 abHdr[1] = (uint8_t)(0xfc | (cb >> 30));
2785 abHdr[2] = (uint8_t)(0x80 | ((cb >> 24) & 0x3f));
2786 abHdr[3] = (uint8_t)(0x80 | ((cb >> 18) & 0x3f));
2787 abHdr[4] = (uint8_t)(0x80 | ((cb >> 12) & 0x3f));
2788 abHdr[5] = (uint8_t)(0x80 | ((cb >> 6) & 0x3f));
2789 abHdr[6] = (uint8_t)(0x80 | (cb & 0x3f));
2790 }
2791 else
2792 AssertLogRelMsgFailedReturn(("cb=%#x\n", cb), pSSM->rc = VERR_INTERNAL_ERROR);
2793
2794 Log3(("ssmR3DataWriteRecHdr: %08llx|%08llx/%08x: Type=%02x fImportant=%RTbool cbHdr=%u\n",
2795 ssmR3StrmTell(&pSSM->Strm) + cbHdr, pSSM->offUnit + cbHdr, cb, u8TypeAndFlags & SSM_REC_TYPE_MASK, !!(u8TypeAndFlags & SSM_REC_FLAGS_IMPORTANT), cbHdr));
2796
2797 return ssmR3DataWriteRaw(pSSM, &abHdr[0], cbHdr);
2798}
2799
2800
2801/**
2802 * Worker that flushes the buffered data.
2803 *
2804 * @returns VBox status code. Will set pSSM->rc on error.
2805 * @param pSSM The saved state handle.
2806 */
2807static int ssmR3DataFlushBuffer(PSSMHANDLE pSSM)
2808{
2809 /*
2810 * Check how much there current is in the buffer.
2811 */
2812 uint32_t cb = pSSM->u.Write.offDataBuffer;
2813 if (!cb)
2814 return pSSM->rc;
2815 pSSM->u.Write.offDataBuffer = 0;
2816
2817 /*
2818 * Write a record header and then the data.
2819 * (No need for fancy optimizations here any longer since the stream is
2820 * fully buffered.)
2821 */
2822 int rc = ssmR3DataWriteRecHdr(pSSM, cb, SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW);
2823 if (RT_SUCCESS(rc))
2824 rc = ssmR3DataWriteRaw(pSSM, pSSM->u.Write.abDataBuffer, cb);
2825 ssmR3Progress(pSSM, cb);
2826 return rc;
2827}
2828
2829
2830/**
2831 * ssmR3DataWrite worker that writes big stuff.
2832 *
2833 * @returns VBox status code
2834 * @param pSSM The saved state handle.
2835 * @param pvBuf The bits to write.
2836 * @param cbBuf The number of bytes to write.
2837 */
2838static int ssmR3DataWriteBig(PSSMHANDLE pSSM, const void *pvBuf, size_t cbBuf)
2839{
2840 int rc = ssmR3DataFlushBuffer(pSSM);
2841 if (RT_SUCCESS(rc))
2842 {
2843 /*
2844 * Split it up into compression blocks.
2845 */
2846 for (;;)
2847 {
2848 AssertCompile(SSM_ZIP_BLOCK_SIZE == PAGE_SIZE);
2849 if ( cbBuf >= SSM_ZIP_BLOCK_SIZE
2850 && ( ((uintptr_t)pvBuf & 0xf)
2851 || !ASMMemIsZeroPage(pvBuf))
2852 )
2853 {
2854 /*
2855 * Compress it.
2856 */
2857 AssertCompile(1 + 3 + 1 + SSM_ZIP_BLOCK_SIZE < 0x00010000);
2858 uint8_t *pb;
2859 rc = ssmR3StrmReserveWriteBufferSpace(&pSSM->Strm, 1 + 3 + 1 + SSM_ZIP_BLOCK_SIZE, &pb);
2860 if (RT_FAILURE(rc))
2861 break;
2862 size_t cbRec = SSM_ZIP_BLOCK_SIZE - (SSM_ZIP_BLOCK_SIZE / 16);
2863 rc = RTZipBlockCompress(RTZIPTYPE_LZF, RTZIPLEVEL_FAST, 0 /*fFlags*/,
2864 pvBuf, SSM_ZIP_BLOCK_SIZE,
2865 pb + 1 + 3 + 1, cbRec, &cbRec);
2866 if (RT_SUCCESS(rc))
2867 {
2868 pb[0] = SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW_LZF;
2869 pb[4] = SSM_ZIP_BLOCK_SIZE / _1K;
2870 cbRec += 1;
2871 }
2872 else
2873 {
2874 pb[0] = SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW;
2875 memcpy(&pb[4], pvBuf, SSM_ZIP_BLOCK_SIZE);
2876 cbRec = SSM_ZIP_BLOCK_SIZE;
2877 }
2878 pb[1] = (uint8_t)(0xe0 | ( cbRec >> 12));
2879 pb[2] = (uint8_t)(0x80 | ((cbRec >> 6) & 0x3f));
2880 pb[3] = (uint8_t)(0x80 | ( cbRec & 0x3f));
2881 cbRec += 1 + 3;
2882 rc = ssmR3StrmCommitWriteBufferSpace(&pSSM->Strm, cbRec);
2883 if (RT_FAILURE(rc))
2884 break;
2885
2886 pSSM->offUnit += cbRec;
2887 ssmR3Progress(pSSM, SSM_ZIP_BLOCK_SIZE);
2888
2889 /* advance */
2890 if (cbBuf == SSM_ZIP_BLOCK_SIZE)
2891 return VINF_SUCCESS;
2892 cbBuf -= SSM_ZIP_BLOCK_SIZE;
2893 pvBuf = (uint8_t const*)pvBuf + SSM_ZIP_BLOCK_SIZE;
2894 }
2895 else if (cbBuf >= SSM_ZIP_BLOCK_SIZE)
2896 {
2897 /*
2898 * Zero block.
2899 */
2900 uint8_t abRec[3];
2901 abRec[0] = SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW_ZERO;
2902 abRec[1] = 1;
2903 abRec[2] = SSM_ZIP_BLOCK_SIZE / _1K;
2904 Log3(("ssmR3DataWriteBig: %08llx|%08llx/%08x: ZERO\n", ssmR3StrmTell(&pSSM->Strm) + 2, pSSM->offUnit + 2, 1));
2905 rc = ssmR3DataWriteRaw(pSSM, &abRec[0], sizeof(abRec));
2906 if (RT_FAILURE(rc))
2907 break;
2908
2909 /* advance */
2910 ssmR3Progress(pSSM, SSM_ZIP_BLOCK_SIZE);
2911 if (cbBuf == SSM_ZIP_BLOCK_SIZE)
2912 return VINF_SUCCESS;
2913 cbBuf -= SSM_ZIP_BLOCK_SIZE;
2914 pvBuf = (uint8_t const*)pvBuf + SSM_ZIP_BLOCK_SIZE;
2915 }
2916 else
2917 {
2918 /*
2919 * Less than one block left, store it the simple way.
2920 */
2921 rc = ssmR3DataWriteRecHdr(pSSM, cbBuf, SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW);
2922 if (RT_SUCCESS(rc))
2923 rc = ssmR3DataWriteRaw(pSSM, pvBuf, cbBuf);
2924 ssmR3Progress(pSSM, cbBuf);
2925 break;
2926 }
2927 }
2928 }
2929 return rc;
2930}
2931
2932
2933/**
2934 * ssmR3DataWrite worker that is called when there isn't enough room in the
2935 * buffer for the current chunk of data.
2936 *
2937 * This will first flush the buffer and then add the new bits to it.
2938 *
2939 * @returns VBox status code
2940 * @param pSSM The saved state handle.
2941 * @param pvBuf The bits to write.
2942 * @param cbBuf The number of bytes to write.
2943 */
2944static int ssmR3DataWriteFlushAndBuffer(PSSMHANDLE pSSM, const void *pvBuf, size_t cbBuf)
2945{
2946 int rc = ssmR3DataFlushBuffer(pSSM);
2947 if (RT_SUCCESS(rc))
2948 {
2949 memcpy(&pSSM->u.Write.abDataBuffer[0], pvBuf, cbBuf);
2950 pSSM->u.Write.offDataBuffer = (uint32_t)cbBuf;
2951 }
2952 return rc;
2953}
2954
2955
2956/**
2957 * Writes data to the current data unit.
2958 *
2959 * This is an inlined wrapper that optimizes the small writes that so many of
2960 * the APIs make.
2961 *
2962 * @returns VBox status code
2963 * @param pSSM The saved state handle.
2964 * @param pvBuf The bits to write.
2965 * @param cbBuf The number of bytes to write.
2966 */
2967DECLINLINE(int) ssmR3DataWrite(PSSMHANDLE pSSM, const void *pvBuf, size_t cbBuf)
2968{
2969 if (cbBuf > sizeof(pSSM->u.Write.abDataBuffer) / 8)
2970 return ssmR3DataWriteBig(pSSM, pvBuf, cbBuf);
2971 if (!cbBuf)
2972 return VINF_SUCCESS;
2973
2974 uint32_t off = pSSM->u.Write.offDataBuffer;
2975 if (RT_UNLIKELY(cbBuf + off > sizeof(pSSM->u.Write.abDataBuffer)))
2976 return ssmR3DataWriteFlushAndBuffer(pSSM, pvBuf, cbBuf);
2977
2978 memcpy(&pSSM->u.Write.abDataBuffer[off], pvBuf, cbBuf);
2979 pSSM->u.Write.offDataBuffer = off + (uint32_t)cbBuf;
2980 return VINF_SUCCESS;
2981}
2982
2983
2984/**
2985 * Puts a structure.
2986 *
2987 * @returns VBox status code.
2988 * @param pSSM The saved state handle.
2989 * @param pvStruct The structure address.
2990 * @param paFields The array of structure fields descriptions.
2991 * The array must be terminated by a SSMFIELD_ENTRY_TERM().
2992 */
2993VMMR3DECL(int) SSMR3PutStruct(PSSMHANDLE pSSM, const void *pvStruct, PCSSMFIELD paFields)
2994{
2995 /* begin marker. */
2996 int rc = SSMR3PutU32(pSSM, SSMR3STRUCT_BEGIN);
2997 if (RT_FAILURE(rc))
2998 return rc;
2999
3000 /* put the fields */
3001 for (PCSSMFIELD pCur = paFields;
3002 pCur->cb != UINT32_MAX && pCur->off != UINT32_MAX;
3003 pCur++)
3004 {
3005 rc = ssmR3DataWrite(pSSM, (uint8_t *)pvStruct + pCur->off, pCur->cb);
3006 if (RT_FAILURE(rc))
3007 return rc;
3008 }
3009
3010 /* end marker */
3011 return SSMR3PutU32(pSSM, SSMR3STRUCT_END);
3012}
3013
3014
3015/**
3016 * Saves a boolean item to the current data unit.
3017 *
3018 * @returns VBox status.
3019 * @param pSSM SSM operation handle.
3020 * @param fBool Item to save.
3021 */
3022VMMR3DECL(int) SSMR3PutBool(PSSMHANDLE pSSM, bool fBool)
3023{
3024 SSM_ASSERT_WRITEABLE_RET(pSSM);
3025 SSM_CHECK_CANCELLED_RET(pSSM);
3026 uint8_t u8 = fBool; /* enforce 1 byte size */
3027 return ssmR3DataWrite(pSSM, &u8, sizeof(u8));
3028}
3029
3030
3031/**
3032 * Saves a 8-bit unsigned integer item to the current data unit.
3033 *
3034 * @returns VBox status.
3035 * @param pSSM SSM operation handle.
3036 * @param u8 Item to save.
3037 */
3038VMMR3DECL(int) SSMR3PutU8(PSSMHANDLE pSSM, uint8_t u8)
3039{
3040 SSM_ASSERT_WRITEABLE_RET(pSSM);
3041 SSM_CHECK_CANCELLED_RET(pSSM);
3042 return ssmR3DataWrite(pSSM, &u8, sizeof(u8));
3043}
3044
3045
3046/**
3047 * Saves a 8-bit signed integer item to the current data unit.
3048 *
3049 * @returns VBox status.
3050 * @param pSSM SSM operation handle.
3051 * @param i8 Item to save.
3052 */
3053VMMR3DECL(int) SSMR3PutS8(PSSMHANDLE pSSM, int8_t i8)
3054{
3055 SSM_ASSERT_WRITEABLE_RET(pSSM);
3056 SSM_CHECK_CANCELLED_RET(pSSM);
3057 return ssmR3DataWrite(pSSM, &i8, sizeof(i8));
3058}
3059
3060
3061/**
3062 * Saves a 16-bit unsigned integer item to the current data unit.
3063 *
3064 * @returns VBox status.
3065 * @param pSSM SSM operation handle.
3066 * @param u16 Item to save.
3067 */
3068VMMR3DECL(int) SSMR3PutU16(PSSMHANDLE pSSM, uint16_t u16)
3069{
3070 SSM_ASSERT_WRITEABLE_RET(pSSM);
3071 SSM_CHECK_CANCELLED_RET(pSSM);
3072 return ssmR3DataWrite(pSSM, &u16, sizeof(u16));
3073}
3074
3075
3076/**
3077 * Saves a 16-bit signed integer item to the current data unit.
3078 *
3079 * @returns VBox status.
3080 * @param pSSM SSM operation handle.
3081 * @param i16 Item to save.
3082 */
3083VMMR3DECL(int) SSMR3PutS16(PSSMHANDLE pSSM, int16_t i16)
3084{
3085 SSM_ASSERT_WRITEABLE_RET(pSSM);
3086 SSM_CHECK_CANCELLED_RET(pSSM);
3087 return ssmR3DataWrite(pSSM, &i16, sizeof(i16));
3088}
3089
3090
3091/**
3092 * Saves a 32-bit unsigned integer item to the current data unit.
3093 *
3094 * @returns VBox status.
3095 * @param pSSM SSM operation handle.
3096 * @param u32 Item to save.
3097 */
3098VMMR3DECL(int) SSMR3PutU32(PSSMHANDLE pSSM, uint32_t u32)
3099{
3100 SSM_ASSERT_WRITEABLE_RET(pSSM);
3101 SSM_CHECK_CANCELLED_RET(pSSM);
3102 return ssmR3DataWrite(pSSM, &u32, sizeof(u32));
3103}
3104
3105
3106/**
3107 * Saves a 32-bit signed integer item to the current data unit.
3108 *
3109 * @returns VBox status.
3110 * @param pSSM SSM operation handle.
3111 * @param i32 Item to save.
3112 */
3113VMMR3DECL(int) SSMR3PutS32(PSSMHANDLE pSSM, int32_t i32)
3114{
3115 SSM_ASSERT_WRITEABLE_RET(pSSM);
3116 SSM_CHECK_CANCELLED_RET(pSSM);
3117 return ssmR3DataWrite(pSSM, &i32, sizeof(i32));
3118}
3119
3120
3121/**
3122 * Saves a 64-bit unsigned integer item to the current data unit.
3123 *
3124 * @returns VBox status.
3125 * @param pSSM SSM operation handle.
3126 * @param u64 Item to save.
3127 */
3128VMMR3DECL(int) SSMR3PutU64(PSSMHANDLE pSSM, uint64_t u64)
3129{
3130 SSM_ASSERT_WRITEABLE_RET(pSSM);
3131 SSM_CHECK_CANCELLED_RET(pSSM);
3132 return ssmR3DataWrite(pSSM, &u64, sizeof(u64));
3133}
3134
3135
3136/**
3137 * Saves a 64-bit signed integer item to the current data unit.
3138 *
3139 * @returns VBox status.
3140 * @param pSSM SSM operation handle.
3141 * @param i64 Item to save.
3142 */
3143VMMR3DECL(int) SSMR3PutS64(PSSMHANDLE pSSM, int64_t i64)
3144{
3145 SSM_ASSERT_WRITEABLE_RET(pSSM);
3146 SSM_CHECK_CANCELLED_RET(pSSM);
3147 return ssmR3DataWrite(pSSM, &i64, sizeof(i64));
3148}
3149
3150
3151/**
3152 * Saves a 128-bit unsigned integer item to the current data unit.
3153 *
3154 * @returns VBox status.
3155 * @param pSSM SSM operation handle.
3156 * @param u128 Item to save.
3157 */
3158VMMR3DECL(int) SSMR3PutU128(PSSMHANDLE pSSM, uint128_t u128)
3159{
3160 SSM_ASSERT_WRITEABLE_RET(pSSM);
3161 SSM_CHECK_CANCELLED_RET(pSSM);
3162 return ssmR3DataWrite(pSSM, &u128, sizeof(u128));
3163}
3164
3165
3166/**
3167 * Saves a 128-bit signed integer item to the current data unit.
3168 *
3169 * @returns VBox status.
3170 * @param pSSM SSM operation handle.
3171 * @param i128 Item to save.
3172 */
3173VMMR3DECL(int) SSMR3PutS128(PSSMHANDLE pSSM, int128_t i128)
3174{
3175 SSM_ASSERT_WRITEABLE_RET(pSSM);
3176 SSM_CHECK_CANCELLED_RET(pSSM);
3177 return ssmR3DataWrite(pSSM, &i128, sizeof(i128));
3178}
3179
3180
3181/**
3182 * Saves a VBox unsigned integer item to the current data unit.
3183 *
3184 * @returns VBox status.
3185 * @param pSSM SSM operation handle.
3186 * @param u Item to save.
3187 */
3188VMMR3DECL(int) SSMR3PutUInt(PSSMHANDLE pSSM, RTUINT u)
3189{
3190 SSM_ASSERT_WRITEABLE_RET(pSSM);
3191 SSM_CHECK_CANCELLED_RET(pSSM);
3192 return ssmR3DataWrite(pSSM, &u, sizeof(u));
3193}
3194
3195
3196/**
3197 * Saves a VBox signed integer item to the current data unit.
3198 *
3199 * @returns VBox status.
3200 * @param pSSM SSM operation handle.
3201 * @param i Item to save.
3202 */
3203VMMR3DECL(int) SSMR3PutSInt(PSSMHANDLE pSSM, RTINT i)
3204{
3205 SSM_ASSERT_WRITEABLE_RET(pSSM);
3206 SSM_CHECK_CANCELLED_RET(pSSM);
3207 return ssmR3DataWrite(pSSM, &i, sizeof(i));
3208}
3209
3210
3211/**
3212 * Saves a GC natural unsigned integer item to the current data unit.
3213 *
3214 * @returns VBox status.
3215 * @param pSSM SSM operation handle.
3216 * @param u Item to save.
3217 *
3218 * @deprecated Silly type, don't use it.
3219 */
3220VMMR3DECL(int) SSMR3PutGCUInt(PSSMHANDLE pSSM, RTGCUINT u)
3221{
3222 SSM_ASSERT_WRITEABLE_RET(pSSM);
3223 SSM_CHECK_CANCELLED_RET(pSSM);
3224 return ssmR3DataWrite(pSSM, &u, sizeof(u));
3225}
3226
3227
3228/**
3229 * Saves a GC unsigned integer register item to the current data unit.
3230 *
3231 * @returns VBox status.
3232 * @param pSSM SSM operation handle.
3233 * @param u Item to save.
3234 */
3235VMMR3DECL(int) SSMR3PutGCUIntReg(PSSMHANDLE pSSM, RTGCUINTREG u)
3236{
3237 SSM_ASSERT_WRITEABLE_RET(pSSM);
3238 SSM_CHECK_CANCELLED_RET(pSSM);
3239 return ssmR3DataWrite(pSSM, &u, sizeof(u));
3240}
3241
3242
3243/**
3244 * Saves a 32 bits GC physical address item to the current data unit.
3245 *
3246 * @returns VBox status.
3247 * @param pSSM SSM operation handle.
3248 * @param GCPhys The item to save
3249 */
3250VMMR3DECL(int) SSMR3PutGCPhys32(PSSMHANDLE pSSM, RTGCPHYS32 GCPhys)
3251{
3252 SSM_ASSERT_WRITEABLE_RET(pSSM);
3253 SSM_CHECK_CANCELLED_RET(pSSM);
3254 return ssmR3DataWrite(pSSM, &GCPhys, sizeof(GCPhys));
3255}
3256
3257
3258/**
3259 * Saves a 64 bits GC physical address item to the current data unit.
3260 *
3261 * @returns VBox status.
3262 * @param pSSM SSM operation handle.
3263 * @param GCPhys The item to save
3264 */
3265VMMR3DECL(int) SSMR3PutGCPhys64(PSSMHANDLE pSSM, RTGCPHYS64 GCPhys)
3266{
3267 SSM_ASSERT_WRITEABLE_RET(pSSM);
3268 SSM_CHECK_CANCELLED_RET(pSSM);
3269 return ssmR3DataWrite(pSSM, &GCPhys, sizeof(GCPhys));
3270}
3271
3272
3273/**
3274 * Saves a GC physical address item to the current data unit.
3275 *
3276 * @returns VBox status.
3277 * @param pSSM SSM operation handle.
3278 * @param GCPhys The item to save
3279 */
3280VMMR3DECL(int) SSMR3PutGCPhys(PSSMHANDLE pSSM, RTGCPHYS GCPhys)
3281{
3282 SSM_ASSERT_WRITEABLE_RET(pSSM);
3283 SSM_CHECK_CANCELLED_RET(pSSM);
3284 return ssmR3DataWrite(pSSM, &GCPhys, sizeof(GCPhys));
3285}
3286
3287
3288/**
3289 * Saves a GC virtual address item to the current data unit.
3290 *
3291 * @returns VBox status.
3292 * @param pSSM SSM operation handle.
3293 * @param GCPtr The item to save.
3294 */
3295VMMR3DECL(int) SSMR3PutGCPtr(PSSMHANDLE pSSM, RTGCPTR GCPtr)
3296{
3297 SSM_ASSERT_WRITEABLE_RET(pSSM);
3298 SSM_CHECK_CANCELLED_RET(pSSM);
3299 return ssmR3DataWrite(pSSM, &GCPtr, sizeof(GCPtr));
3300}
3301
3302
3303/**
3304 * Saves an RC virtual address item to the current data unit.
3305 *
3306 * @returns VBox status.
3307 * @param pSSM SSM operation handle.
3308 * @param RCPtr The item to save.
3309 */
3310VMMR3DECL(int) SSMR3PutRCPtr(PSSMHANDLE pSSM, RTRCPTR RCPtr)
3311{
3312 SSM_ASSERT_WRITEABLE_RET(pSSM);
3313 SSM_CHECK_CANCELLED_RET(pSSM);
3314 return ssmR3DataWrite(pSSM, &RCPtr, sizeof(RCPtr));
3315}
3316
3317
3318/**
3319 * Saves a GC virtual address (represented as an unsigned integer) item to the current data unit.
3320 *
3321 * @returns VBox status.
3322 * @param pSSM SSM operation handle.
3323 * @param GCPtr The item to save.
3324 */
3325VMMR3DECL(int) SSMR3PutGCUIntPtr(PSSMHANDLE pSSM, RTGCUINTPTR GCPtr)
3326{
3327 SSM_ASSERT_WRITEABLE_RET(pSSM);
3328 SSM_CHECK_CANCELLED_RET(pSSM);
3329 return ssmR3DataWrite(pSSM, &GCPtr, sizeof(GCPtr));
3330}
3331
3332
3333/**
3334 * Saves a I/O port address item to the current data unit.
3335 *
3336 * @returns VBox status.
3337 * @param pSSM SSM operation handle.
3338 * @param IOPort The item to save.
3339 */
3340VMMR3DECL(int) SSMR3PutIOPort(PSSMHANDLE pSSM, RTIOPORT IOPort)
3341{
3342 SSM_ASSERT_WRITEABLE_RET(pSSM);
3343 SSM_CHECK_CANCELLED_RET(pSSM);
3344 return ssmR3DataWrite(pSSM, &IOPort, sizeof(IOPort));
3345}
3346
3347
3348/**
3349 * Saves a selector item to the current data unit.
3350 *
3351 * @returns VBox status.
3352 * @param pSSM SSM operation handle.
3353 * @param Sel The item to save.
3354 */
3355VMMR3DECL(int) SSMR3PutSel(PSSMHANDLE pSSM, RTSEL Sel)
3356{
3357 SSM_ASSERT_WRITEABLE_RET(pSSM);
3358 SSM_CHECK_CANCELLED_RET(pSSM);
3359 return ssmR3DataWrite(pSSM, &Sel, sizeof(Sel));
3360}
3361
3362
3363/**
3364 * Saves a memory item to the current data unit.
3365 *
3366 * @returns VBox status.
3367 * @param pSSM SSM operation handle.
3368 * @param pv Item to save.
3369 * @param cb Size of the item.
3370 */
3371VMMR3DECL(int) SSMR3PutMem(PSSMHANDLE pSSM, const void *pv, size_t cb)
3372{
3373 SSM_ASSERT_WRITEABLE_RET(pSSM);
3374 SSM_CHECK_CANCELLED_RET(pSSM);
3375 return ssmR3DataWrite(pSSM, pv, cb);
3376}
3377
3378
3379/**
3380 * Saves a zero terminated string item to the current data unit.
3381 *
3382 * @returns VBox status.
3383 * @param pSSM SSM operation handle.
3384 * @param psz Item to save.
3385 */
3386VMMR3DECL(int) SSMR3PutStrZ(PSSMHANDLE pSSM, const char *psz)
3387{
3388 SSM_ASSERT_WRITEABLE_RET(pSSM);
3389 SSM_CHECK_CANCELLED_RET(pSSM);
3390
3391 size_t cch = strlen(psz);
3392 if (cch > _1M)
3393 {
3394 AssertMsgFailed(("a %d byte long string, what's this!?!\n"));
3395 return VERR_TOO_MUCH_DATA;
3396 }
3397 uint32_t u32 = (uint32_t)cch;
3398 int rc = ssmR3DataWrite(pSSM, &u32, sizeof(u32));
3399 if (rc)
3400 return rc;
3401 return ssmR3DataWrite(pSSM, psz, cch);
3402}
3403
3404
3405/**
3406 * Worker for SSMR3LiveDone and SSMR3Save that closes the handle and deletes the
3407 * saved state file on failure.
3408 *
3409 * @returns VBox status code (pSSM->rc).
3410 * @param pVM The VM handle.
3411 * @param pSSM The saved state handle.
3412 */
3413static int ssmR3SaveDoClose(PVM pVM, PSSMHANDLE pSSM)
3414{
3415 VM_ASSERT_EMT0(pVM);
3416
3417 /*
3418 * Make it non-cancellable, close the stream and delete the file on failure.
3419 */
3420 ssmR3SetCancellable(pVM, pSSM, false);
3421 int rc = ssmR3StrmClose(&pSSM->Strm);
3422 if (RT_SUCCESS(rc))
3423 rc = pSSM->rc;
3424 if (RT_SUCCESS(rc))
3425 {
3426 if (pSSM->pfnProgress)
3427 pSSM->pfnProgress(pVM, 100, pSSM->pvUser);
3428 LogRel(("SSM: Successfully saved the VM state to '%s'\n",
3429 pSSM->pszFilename ? pSSM->pszFilename : "<remote-machine>"));
3430 }
3431 else
3432 {
3433 if (pSSM->pszFilename)
3434 {
3435 int rc2 = RTFileDelete(pSSM->pszFilename);
3436 AssertRC(rc2);
3437 if (RT_SUCCESS(rc2))
3438 LogRel(("SSM: Failed to save the VM state to '%s' (file deleted): %Rrc\n",
3439 pSSM->pszFilename, rc));
3440 else
3441 LogRel(("SSM: Failed to save the VM state to '%s' (file deletion failed, rc2=%Rrc): %Rrc\n",
3442 pSSM->pszFilename, rc2, rc));
3443 }
3444 else
3445 LogRel(("SSM: Failed to save the VM state.\n"));
3446 }
3447
3448 /*
3449 * Trash the handle before freeing it.
3450 */
3451 ASMAtomicWriteU32(&pSSM->fCancelled, 0);
3452 pSSM->pVM = NULL;
3453 pSSM->enmAfter = SSMAFTER_INVALID;
3454 pSSM->enmOp = SSMSTATE_INVALID;
3455 RTMemFree(pSSM);
3456
3457 return rc;
3458}
3459
3460
3461/**
3462 * Closes the SSM handle.
3463 *
3464 * This must always be called on a handled returned by SSMR3LiveToFile or
3465 * SSMR3LiveToRemote.
3466 *
3467 * @returns VBox status.
3468 *
3469 * @param pSSM The SSM handle returned by SSMR3LiveToFile or
3470 * SSMR3LiveToRemote.
3471 *
3472 * @thread EMT(0).
3473 */
3474VMMR3_INT_DECL(int) SSMR3LiveDone(PSSMHANDLE pSSM)
3475{
3476 LogFlow(("SSMR3LiveDone: pSSM=%p\n", pSSM));
3477
3478 /*
3479 * Validate input.
3480 */
3481 AssertPtrReturn(pSSM, VERR_INVALID_POINTER);
3482 PVM pVM = pSSM->pVM;
3483 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
3484 VM_ASSERT_EMT0(pVM);
3485 AssertMsgReturn( pSSM->enmAfter == SSMAFTER_DESTROY
3486 || pSSM->enmAfter == SSMAFTER_CONTINUE,
3487 ("%d\n", pSSM->enmAfter),
3488 VERR_INVALID_PARAMETER);
3489 AssertMsgReturn( pSSM->enmOp >= SSMSTATE_LIVE_PREP
3490 && pSSM->enmOp <= SSMSTATE_SAVE_DONE,
3491 ("%d\n", pSSM->enmOp), VERR_INVALID_STATE);
3492
3493 /*
3494 * Join paths with SSMR3Save again.
3495 */
3496 return ssmR3SaveDoClose(pVM, pSSM);
3497}
3498
3499
3500/**
3501 * Do the pfnSaveDone run.
3502 *
3503 * @returns VBox status code (pSSM->rc).
3504 * @param pVM The VM handle.
3505 * @param pSSM The saved state handle.
3506 */
3507static int ssmR3SaveDoDoneRun(PVM pVM, PSSMHANDLE pSSM)
3508{
3509 VM_ASSERT_EMT0(pVM);
3510
3511 /*
3512 * Do the done run.
3513 */
3514 pSSM->enmOp = SSMSTATE_SAVE_DONE;
3515 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
3516 {
3517 if ( pUnit->u.Common.pfnSaveDone
3518 && ( pUnit->fCalled
3519 || (!pUnit->u.Common.pfnSavePrep && !pUnit->u.Common.pfnSaveExec)))
3520 {
3521 int rcOld = pSSM->rc;
3522 int rc;
3523 switch (pUnit->enmType)
3524 {
3525 case SSMUNITTYPE_DEV:
3526 rc = pUnit->u.Dev.pfnSaveDone(pUnit->u.Dev.pDevIns, pSSM);
3527 break;
3528 case SSMUNITTYPE_DRV:
3529 rc = pUnit->u.Drv.pfnSaveDone(pUnit->u.Drv.pDrvIns, pSSM);
3530 break;
3531 case SSMUNITTYPE_INTERNAL:
3532 rc = pUnit->u.Internal.pfnSaveDone(pVM, pSSM);
3533 break;
3534 case SSMUNITTYPE_EXTERNAL:
3535 rc = pUnit->u.External.pfnSaveDone(pSSM, pUnit->u.External.pvUser);
3536 break;
3537 default:
3538 rc = VERR_INTERNAL_ERROR;
3539 break;
3540 }
3541 if (RT_SUCCESS(rc) && pSSM->rc != rcOld)
3542 rc = pSSM->rc;
3543 if (RT_FAILURE(rc))
3544 {
3545 LogRel(("SSM: Done save failed with rc=%Rrc for data unit '%s.\n", rc, pUnit->szName));
3546 if (RT_SUCCESS_NP(pSSM->rc))
3547 pSSM->rc = rc;
3548 }
3549 }
3550 }
3551 return pSSM->rc;
3552}
3553
3554
3555/**
3556 * Writes the directory.
3557 *
3558 * @returns VBox status code.
3559 * @param pVM The VM handle.
3560 * @param pSSM The SSM handle.
3561 * @param pcEntries Where to return the number of directory entries.
3562 */
3563static int ssmR3WriteDirectory(PVM pVM, PSSMHANDLE pSSM, uint32_t *pcEntries)
3564{
3565 VM_ASSERT_EMT0(pVM);
3566
3567 /*
3568 * Grab some temporary memory for the dictionary.
3569 */
3570 size_t cbDir = RT_OFFSETOF(SSMFILEDIR, aEntries[pVM->ssm.s.cUnits]);
3571 PSSMFILEDIR pDir = (PSSMFILEDIR)RTMemTmpAlloc(cbDir);
3572 if (!pDir)
3573 {
3574 LogRel(("ssmR3WriteDirectory: failed to allocate %zu bytes!\n", cbDir));
3575 return VERR_NO_TMP_MEMORY;
3576 }
3577
3578 /*
3579 * Initialize it.
3580 */
3581 memcpy(pDir->szMagic, SSMFILEDIR_MAGIC, sizeof(pDir->szMagic));
3582 pDir->u32CRC = 0;
3583 pDir->cEntries = 0;
3584
3585 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
3586 if (pUnit->offStream != RTFOFF_MIN)
3587 {
3588 PSSMFILEDIRENTRY pEntry = &pDir->aEntries[pDir->cEntries++];
3589 Assert(pDir->cEntries <= pVM->ssm.s.cUnits);
3590 pEntry->off = pUnit->offStream;
3591 pEntry->u32Instance = pUnit->u32Instance;
3592 pEntry->u32NameCRC = RTCrc32(pUnit->szName, pUnit->cchName);
3593 }
3594
3595 /*
3596 * Calculate the actual size and CRC-32, then write the directory
3597 * out to the stream.
3598 */
3599 *pcEntries = pDir->cEntries;
3600 cbDir = RT_OFFSETOF(SSMFILEDIR, aEntries[pDir->cEntries]);
3601 pDir->u32CRC = RTCrc32(pDir, cbDir);
3602 int rc = ssmR3StrmWrite(&pSSM->Strm, pDir, cbDir);
3603 RTMemTmpFree(pDir);
3604 return rc;
3605}
3606
3607
3608/**
3609 * Finalize the saved state stream, i.e. add the end unit, directory
3610 * and footer.
3611 *
3612 * @returns VBox status code (pSSM->rc).
3613 * @param pVM The VM handle.
3614 * @param pSSM The saved state handle.
3615 */
3616static int ssmR3SaveDoFinalization(PVM pVM, PSSMHANDLE pSSM)
3617{
3618 VM_ASSERT_EMT0(pVM);
3619 Assert(RT_SUCCESS(pSSM->rc));
3620
3621 /*
3622 * Write the end unit.
3623 */
3624 SSMFILEUNITHDRV2 UnitHdr;
3625 memcpy(&UnitHdr.szMagic[0], SSMFILEUNITHDR_END, sizeof(UnitHdr.szMagic));
3626 UnitHdr.offStream = ssmR3StrmTell(&pSSM->Strm);
3627 UnitHdr.u32CurStreamCRC = ssmR3StrmCurCRC(&pSSM->Strm);
3628 UnitHdr.u32CRC = 0;
3629 UnitHdr.u32Version = 0;
3630 UnitHdr.u32Instance = 0;
3631 UnitHdr.u32Pass = SSM_PASS_FINAL;
3632 UnitHdr.fFlags = 0;
3633 UnitHdr.cbName = 0;
3634 UnitHdr.u32CRC = RTCrc32(&UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[0]));
3635 Log(("SSM: Unit at %#9llx: END UNIT\n", UnitHdr.offStream));
3636 int rc = ssmR3StrmWrite(&pSSM->Strm, &UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[0]));
3637 if (RT_FAILURE(rc))
3638 {
3639 LogRel(("SSM: Failed writing the end unit: %Rrc\n", rc));
3640 return pSSM->rc = rc;
3641 }
3642
3643 /*
3644 * Write the directory for the final units and then the footer.
3645 */
3646 SSMFILEFTR Footer;
3647 rc = ssmR3WriteDirectory(pVM, pSSM, &Footer.cDirEntries);
3648 if (RT_FAILURE(rc))
3649 {
3650 LogRel(("SSM: Failed writing the directory: %Rrc\n", rc));
3651 return pSSM->rc = rc;
3652 }
3653
3654 memcpy(Footer.szMagic, SSMFILEFTR_MAGIC, sizeof(Footer.szMagic));
3655 Footer.offStream = ssmR3StrmTell(&pSSM->Strm);
3656 Footer.u32StreamCRC = ssmR3StrmFinalCRC(&pSSM->Strm);
3657 Footer.u32Reserved = 0;
3658 Footer.u32CRC = 0;
3659 Footer.u32CRC = RTCrc32(&Footer, sizeof(Footer));
3660 Log(("SSM: Footer at %#9llx: \n", Footer.offStream));
3661 rc = ssmR3StrmWrite(&pSSM->Strm, &Footer, sizeof(Footer));
3662 if (RT_SUCCESS(rc))
3663 rc = ssmR3StrmSetEnd(&pSSM->Strm);
3664 if (RT_FAILURE(rc))
3665 {
3666 LogRel(("SSM: Failed writing the footer: %Rrc\n", rc));
3667 return pSSM->rc = rc;
3668 }
3669
3670 LogRel(("SSM: Footer at %#llx (%lld), %u directory entries.\n",
3671 Footer.offStream, Footer.offStream, Footer.cDirEntries));
3672 return VINF_SUCCESS;
3673}
3674
3675
3676/**
3677 * Do the pfnSaveExec run.
3678 *
3679 * @returns VBox status code (pSSM->rc).
3680 * @param pVM The VM handle.
3681 * @param pSSM The saved state handle.
3682 */
3683static int ssmR3SaveDoExecRun(PVM pVM, PSSMHANDLE pSSM)
3684{
3685 VM_ASSERT_EMT0(pVM);
3686 AssertRC(pSSM->rc);
3687 pSSM->rc = VINF_SUCCESS;
3688 pSSM->enmOp = SSMSTATE_SAVE_EXEC;
3689 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
3690 {
3691 /*
3692 * Not all unit have a callback. Skip those which don't and
3693 * make sure to keep the progress indicator up to date.
3694 */
3695 pSSM->offEstUnitEnd += pUnit->cbGuess;
3696 if (!pUnit->u.Common.pfnSaveExec)
3697 {
3698 pUnit->fCalled = true;
3699 if (pUnit->cbGuess)
3700 ssmR3Progress(pSSM, pSSM->offEstUnitEnd - pSSM->offEst);
3701 continue;
3702 }
3703 pUnit->offStream = ssmR3StrmTell(&pSSM->Strm);
3704
3705 /*
3706 * Check for cancellation.
3707 */
3708 if (RT_UNLIKELY(ASMAtomicUoReadU32(&(pSSM)->fCancelled) == SSMHANDLE_CANCELLED))
3709 {
3710 LogRel(("SSM: Cancelled!\n"));
3711 AssertRC(pSSM->rc);
3712 return pSSM->rc = VERR_SSM_CANCELLED;
3713 }
3714
3715 /*
3716 * Write data unit header
3717 */
3718 SSMFILEUNITHDRV2 UnitHdr;
3719 memcpy(&UnitHdr.szMagic[0], SSMFILEUNITHDR_MAGIC, sizeof(UnitHdr.szMagic));
3720 UnitHdr.offStream = pUnit->offStream;
3721 UnitHdr.u32CurStreamCRC = ssmR3StrmCurCRC(&pSSM->Strm);
3722 UnitHdr.u32CRC = 0;
3723 UnitHdr.u32Version = pUnit->u32Version;
3724 UnitHdr.u32Instance = pUnit->u32Instance;
3725 UnitHdr.u32Pass = SSM_PASS_FINAL;
3726 UnitHdr.fFlags = 0;
3727 UnitHdr.cbName = (uint32_t)pUnit->cchName + 1;
3728 memcpy(&UnitHdr.szName[0], &pUnit->szName[0], UnitHdr.cbName);
3729 UnitHdr.u32CRC = RTCrc32(&UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]));
3730 Log(("SSM: Unit at %#9llx: '%s', instance %u, pass %#x, version %u\n",
3731 UnitHdr.offStream, UnitHdr.szName, UnitHdr.u32Instance, UnitHdr.u32Pass, UnitHdr.u32Version));
3732 int rc = ssmR3StrmWrite(&pSSM->Strm, &UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]));
3733 if (RT_FAILURE(rc))
3734 {
3735 LogRel(("SSM: Failed to write unit header. rc=%Rrc\n", rc));
3736 return pSSM->rc = rc;
3737 }
3738
3739 /*
3740 * Call the execute handler.
3741 */
3742 ssmR3DataWriteBegin(pSSM);
3743 switch (pUnit->enmType)
3744 {
3745 case SSMUNITTYPE_DEV:
3746 rc = pUnit->u.Dev.pfnSaveExec(pUnit->u.Dev.pDevIns, pSSM);
3747 break;
3748 case SSMUNITTYPE_DRV:
3749 rc = pUnit->u.Drv.pfnSaveExec(pUnit->u.Drv.pDrvIns, pSSM);
3750 break;
3751 case SSMUNITTYPE_INTERNAL:
3752 rc = pUnit->u.Internal.pfnSaveExec(pVM, pSSM);
3753 break;
3754 case SSMUNITTYPE_EXTERNAL:
3755 pUnit->u.External.pfnSaveExec(pSSM, pUnit->u.External.pvUser);
3756 rc = pSSM->rc;
3757 break;
3758 default:
3759 rc = VERR_INTERNAL_ERROR;
3760 break;
3761 }
3762 pUnit->fCalled = true;
3763 if (RT_FAILURE(rc) && RT_SUCCESS_NP(pSSM->rc))
3764 pSSM->rc = rc;
3765 else
3766 rc = ssmR3DataFlushBuffer(pSSM); /* will return SSMHANDLE::rc if it is set */
3767 if (RT_FAILURE(rc))
3768 {
3769 LogRel(("SSM: Execute save failed with rc=%Rrc for data unit '%s'/#%u.\n", rc, pUnit->szName, pUnit->u32Instance));
3770 return rc;
3771 }
3772
3773 /*
3774 * Write the termination record and flush the compression stream.
3775 */
3776 SSMRECTERM TermRec;
3777 TermRec.u8TypeAndFlags = SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_TERM;
3778 TermRec.cbRec = sizeof(TermRec) - 2;
3779 if (pSSM->Strm.fChecksummed)
3780 {
3781 TermRec.fFlags = SSMRECTERM_FLAGS_CRC32;
3782 TermRec.u32StreamCRC = RTCrc32Finish(RTCrc32Process(ssmR3StrmCurCRC(&pSSM->Strm), &TermRec, 2));
3783 }
3784 else
3785 {
3786 TermRec.fFlags = 0;
3787 TermRec.u32StreamCRC = 0;
3788 }
3789 TermRec.cbUnit = pSSM->offUnit + sizeof(TermRec);
3790 rc = ssmR3DataWriteRaw(pSSM, &TermRec, sizeof(TermRec));
3791 if (RT_SUCCESS(rc))
3792 rc = ssmR3DataWriteFinish(pSSM);
3793 if (RT_FAILURE(rc))
3794 {
3795 LogRel(("SSM: Failed terminating unit: %Rrc\n", rc));
3796 return pSSM->rc = rc;
3797 }
3798
3799 /*
3800 * Advance the progress indicator to the end of the current unit.
3801 */
3802 ssmR3Progress(pSSM, pSSM->offEstUnitEnd - pSSM->offEst);
3803 } /* for each unit */
3804
3805
3806 /* (progress should be pending 99% now) */
3807 AssertMsg(pSSM->uPercent == (101 - pSSM->uPercentDone), ("%d\n", pSSM->uPercent));
3808 return VINF_SUCCESS;
3809}
3810
3811
3812/**
3813 * Do the pfnSavePrep run.
3814 *
3815 * @returns VBox status code (pSSM->rc).
3816 * @param pVM The VM handle.
3817 * @param pSSM The saved state handle.
3818 */
3819static int ssmR3SaveDoPrepRun(PVM pVM, PSSMHANDLE pSSM)
3820{
3821 VM_ASSERT_EMT0(pVM);
3822 Assert(RT_SUCCESS(pSSM->rc));
3823 pSSM->enmOp = SSMSTATE_SAVE_PREP;
3824 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
3825 {
3826 if (pUnit->u.Common.pfnSavePrep)
3827 {
3828 int rc;
3829 switch (pUnit->enmType)
3830 {
3831 case SSMUNITTYPE_DEV:
3832 rc = pUnit->u.Dev.pfnSavePrep(pUnit->u.Dev.pDevIns, pSSM);
3833 break;
3834 case SSMUNITTYPE_DRV:
3835 rc = pUnit->u.Drv.pfnSavePrep(pUnit->u.Drv.pDrvIns, pSSM);
3836 break;
3837 case SSMUNITTYPE_INTERNAL:
3838 rc = pUnit->u.Internal.pfnSavePrep(pVM, pSSM);
3839 break;
3840 case SSMUNITTYPE_EXTERNAL:
3841 rc = pUnit->u.External.pfnSavePrep(pSSM, pUnit->u.External.pvUser);
3842 break;
3843 default:
3844 rc = VERR_INTERNAL_ERROR;
3845 break;
3846 }
3847 pUnit->fCalled = true;
3848 if (RT_FAILURE(rc) && RT_SUCCESS_NP(pSSM->rc))
3849 pSSM->rc = rc;
3850 else
3851 rc = pSSM->rc;
3852 if (RT_FAILURE(rc))
3853 {
3854 LogRel(("SSM: Prepare save failed with rc=%Rrc for data unit '%s.\n", rc, pUnit->szName));
3855 return rc;
3856 }
3857 }
3858
3859 pSSM->cbEstTotal += pUnit->cbGuess;
3860 }
3861
3862 /*
3863 * Work the progress indicator if we got one.
3864 */
3865 if (pSSM->pfnProgress)
3866 pSSM->pfnProgress(pVM, pSSM->uPercentPrepare-1, pSSM->pvUser);
3867 pSSM->uPercent = pSSM->uPercentPrepare;
3868
3869 return VINF_SUCCESS;
3870}
3871
3872
3873/**
3874 * Common worker for SSMR3Save and SSMR3Migrate.
3875 *
3876 * @returns VBox status code (no need to check pSSM->rc).
3877 * @param pVM The VM handle.
3878 * @param pSSM The state handle.
3879 *
3880 * @thread EMT(0)
3881 */
3882static int ssmR3SaveDoCommon(PVM pVM, PSSMHANDLE pSSM)
3883{
3884 VM_ASSERT_EMT0(pVM);
3885
3886 /*
3887 * Do the work.
3888 */
3889 int rc = ssmR3SaveDoPrepRun(pVM, pSSM);
3890 if (RT_SUCCESS(rc))
3891 {
3892 rc = ssmR3SaveDoExecRun(pVM, pSSM);
3893 if (RT_SUCCESS(rc))
3894 rc = ssmR3SaveDoFinalization(pVM, pSSM);
3895 }
3896 Assert(pSSM->rc == rc);
3897 int rc2 = ssmR3SaveDoDoneRun(pVM, pSSM);
3898 if (RT_SUCCESS(rc))
3899 rc = rc2;
3900
3901 return rc;
3902}
3903
3904
3905/**
3906 * Saves the rest of the state on EMT0.
3907 *
3908 * @returns VBox status.
3909 *
3910 * @param pSSM The SSM handle returned by SSMR3LiveToFile or
3911 * SSMR3LiveToRemote.
3912 *
3913 * @thread Non-EMT thread. Will involve the EMT at the end of the operation.
3914 */
3915VMMR3_INT_DECL(int) SSMR3LiveDoStep2(PSSMHANDLE pSSM)
3916{
3917 LogFlow(("SSMR3LiveDoStep2: pSSM=%p\n", pSSM));
3918
3919 /*
3920 * Validate input.
3921 */
3922 AssertPtrReturn(pSSM, VERR_INVALID_POINTER);
3923 PVM pVM = pSSM->pVM;
3924 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
3925 VM_ASSERT_EMT0(pVM);
3926 AssertMsgReturn( pSSM->enmAfter == SSMAFTER_DESTROY
3927 || pSSM->enmAfter == SSMAFTER_CONTINUE,
3928 ("%d\n", pSSM->enmAfter),
3929 VERR_INVALID_PARAMETER);
3930 AssertMsgReturn(pSSM->enmOp == SSMSTATE_LIVE_STEP2, ("%d\n", pSSM->enmOp), VERR_INVALID_STATE);
3931 AssertRCReturn(pSSM->rc, pSSM->rc);
3932
3933 /*
3934 * Join paths with VMMR3Save.
3935 */
3936 return ssmR3SaveDoCommon(pVM, pSSM);
3937}
3938
3939
3940/**
3941 * Writes the file header and clear the per-unit data.
3942 *
3943 * @returns VBox status code.
3944 * @param pVM The VM handle.
3945 * @param pSSM The SSM handle.
3946 */
3947static int ssmR3WriteHeaderAndClearPerUnitData(PVM pVM, PSSMHANDLE pSSM)
3948{
3949 /*
3950 * Write the header.
3951 */
3952 SSMFILEHDR FileHdr;
3953 memcpy(&FileHdr.szMagic, SSMFILEHDR_MAGIC_V2_0, sizeof(FileHdr.szMagic));
3954 FileHdr.u16VerMajor = VBOX_VERSION_MAJOR;
3955 FileHdr.u16VerMinor = VBOX_VERSION_MINOR;
3956 FileHdr.u32VerBuild = VBOX_VERSION_BUILD;
3957 FileHdr.u32SvnRev = VMMGetSvnRev(),
3958 FileHdr.cHostBits = HC_ARCH_BITS;
3959 FileHdr.cbGCPhys = sizeof(RTGCPHYS);
3960 FileHdr.cbGCPtr = sizeof(RTGCPTR);
3961 FileHdr.u8Reserved = 0;
3962 FileHdr.cUnits = pVM->ssm.s.cUnits;
3963 FileHdr.fFlags = SSMFILEHDR_FLAGS_STREAM_CRC32;
3964 FileHdr.cbMaxDecompr = RT_SIZEOFMEMB(SSMHANDLE, u.Read.abDataBuffer);
3965 FileHdr.u32CRC = 0;
3966 FileHdr.u32CRC = RTCrc32(&FileHdr, sizeof(FileHdr));
3967 int rc = ssmR3StrmWrite(&pSSM->Strm, &FileHdr, sizeof(FileHdr));
3968 if (RT_SUCCESS(rc))
3969 return rc;
3970
3971 /*
3972 * Clear the per unit flags and offsets.
3973 */
3974 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
3975 {
3976 pUnit->fCalled = false;
3977 pUnit->offStream = RTFOFF_MIN;
3978 }
3979
3980 return VINF_SUCCESS;
3981}
3982
3983
3984/**
3985 * Creates a new saved state file.
3986 *
3987 * @returns VBox status code.
3988 * @param pVM The VM handle.
3989 * @param pszFilename The name of the file.
3990 * @param enmAfter What to do afterwards.
3991 * @param pfnProgress The progress callback.
3992 * @param pvUser The progress callback user argument.
3993 * @param ppSSM Where to return the pointer to the saved state
3994 * handle upon successful return. Free it using
3995 * RTMemFree after closing the stream.
3996 */
3997static int ssmR3SaveDoCreateFile(PVM pVM, const char *pszFilename, SSMAFTER enmAfter,
3998 PFNVMPROGRESS pfnProgress, void *pvUser, PSSMHANDLE *ppSSM)
3999{
4000 PSSMHANDLE pSSM = (PSSMHANDLE)RTMemAllocZ(sizeof(*pSSM));
4001 if (!pSSM)
4002 return VERR_NO_MEMORY;
4003
4004 pSSM->pVM = pVM;
4005 pSSM->enmOp = SSMSTATE_INVALID;
4006 pSSM->enmAfter = enmAfter;
4007 pSSM->fCancelled = SSMHANDLE_OK;
4008 pSSM->rc = VINF_SUCCESS;
4009 pSSM->cbUnitLeftV1 = 0;
4010 pSSM->offUnit = UINT64_MAX;
4011 pSSM->pfnProgress = pfnProgress;
4012 pSSM->pvUser = pvUser;
4013 pSSM->uPercent = 0;
4014 pSSM->offEstProgress = 0;
4015 pSSM->cbEstTotal = 0;
4016 pSSM->offEst = 0;
4017 pSSM->offEstUnitEnd = 0;
4018 pSSM->uPercentPrepare = 0;
4019 pSSM->uPercentDone = 0;
4020 pSSM->pszFilename = pszFilename;
4021 pSSM->u.Write.offDataBuffer = 0;
4022
4023 int rc = ssmR3StrmOpenFile(&pSSM->Strm, pszFilename, true /*fWrite*/, true /*fChecksummed*/, 8 /*cBuffers*/);
4024 if (RT_FAILURE(rc))
4025 {
4026 LogRel(("SSM: Failed to create save state file '%s', rc=%Rrc.\n", pszFilename, rc));
4027 RTMemFree(pSSM);
4028 return rc;
4029 }
4030
4031 *ppSSM = pSSM;
4032 return VINF_SUCCESS;
4033}
4034
4035
4036/**
4037 * Start VM save operation.
4038 *
4039 * @returns VBox status.
4040 *
4041 * @param pVM The VM handle.
4042 * @param pszFilename Name of the file to save the state in.
4043 * @param enmAfter What is planned after a successful save operation.
4044 * @param pfnProgress Progress callback. Optional.
4045 * @param pvUser User argument for the progress callback.
4046 *
4047 * @thread EMT
4048 */
4049VMMR3DECL(int) SSMR3Save(PVM pVM, const char *pszFilename, SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvUser)
4050{
4051 LogFlow(("SSMR3Save: pszFilename=%p:{%s} enmAfter=%d pfnProgress=%p pvUser=%p\n", pszFilename, pszFilename, enmAfter, pfnProgress, pvUser));
4052 VM_ASSERT_EMT0(pVM);
4053
4054 /*
4055 * Validate input.
4056 */
4057 AssertMsgReturn( enmAfter == SSMAFTER_DESTROY
4058 || enmAfter == SSMAFTER_CONTINUE,
4059 ("%d\n", enmAfter),
4060 VERR_INVALID_PARAMETER);
4061
4062 /*
4063 * Create the saved state file and handle.
4064 *
4065 * Note that there might be quite some work to do after executing the saving,
4066 * so we reserve 20% for the 'Done' period.
4067 */
4068 PSSMHANDLE pSSM;
4069 int rc = ssmR3SaveDoCreateFile(pVM, pszFilename, enmAfter, pfnProgress, pvUser, &pSSM);
4070 if (RT_FAILURE(rc))
4071 return rc;
4072 pSSM->uPercentPrepare = 20;
4073 pSSM->uPercentDone = 2;
4074
4075 /*
4076 * Write the saved state stream header and join paths with
4077 * the other save methods for the rest of the job.
4078 */
4079 Log(("SSM: Starting state save to file '%s'...\n", pszFilename));
4080 ssmR3StrmStartIoThread(&pSSM->Strm);
4081 rc = ssmR3WriteHeaderAndClearPerUnitData(pVM, pSSM);
4082 if (RT_SUCCESS(rc))
4083 {
4084 ssmR3SetCancellable(pVM, pSSM, true);
4085 ssmR3SaveDoCommon(pVM, pSSM);
4086 }
4087
4088 return ssmR3SaveDoClose(pVM, pSSM);
4089}
4090
4091
4092/**
4093 * Calls pfnLiveVote for all units.
4094 *
4095 * @returns VBox status code (no need to check pSSM->rc).
4096 * @retval VINF_SUCCESS if we can pass on to step 2.
4097 * @retval VINF_SSM_VOTE_FOR_ANOTHER_PASS if we need another pass.
4098 *
4099 * @param pVM The VM handle.
4100 * @param pSSM The saved state handle.
4101 * @param uPass The current pass.
4102 */
4103static int ssmR3LiveDoVoteRun(PVM pVM, PSSMHANDLE pSSM, uint32_t uPass)
4104{
4105 AssertRC(pSSM->rc);
4106 pSSM->rc = VINF_SUCCESS;
4107 pSSM->enmOp = SSMSTATE_LIVE_VOTE;
4108 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
4109 {
4110 if (pUnit->u.Common.pfnLiveVote)
4111 {
4112 int rc;
4113 switch (pUnit->enmType)
4114 {
4115 case SSMUNITTYPE_DEV:
4116 rc = pUnit->u.Dev.pfnLiveVote(pUnit->u.Dev.pDevIns, pSSM);
4117 break;
4118 case SSMUNITTYPE_DRV:
4119 rc = pUnit->u.Drv.pfnLiveVote(pUnit->u.Drv.pDrvIns, pSSM);
4120 break;
4121 case SSMUNITTYPE_INTERNAL:
4122 rc = pUnit->u.Internal.pfnLiveVote(pVM, pSSM);
4123 break;
4124 case SSMUNITTYPE_EXTERNAL:
4125 rc = pUnit->u.External.pfnLiveVote(pSSM, pUnit->u.External.pvUser);
4126 break;
4127 default:
4128 rc = VERR_INTERNAL_ERROR;
4129 break;
4130 }
4131 pUnit->fCalled = true;
4132 Assert(pSSM->rc == VINF_SUCCESS);
4133 if (rc != VINF_SUCCESS)
4134 {
4135 if (rc == VINF_SSM_VOTE_FOR_ANOTHER_PASS)
4136 {
4137 Log(("ssmR3DoLiveVoteRun: '%s'/#%u -> VINF_SSM_VOTE_FOR_ANOTHER_PASS (pass=%u)\n", pUnit->szName, pUnit->u32Instance, uPass));
4138 return VINF_SSM_VOTE_FOR_ANOTHER_PASS;
4139 }
4140
4141 /*
4142 * rc is usually VERR_SSM_VOTE_FOR_GIVING_UP here, but we allow
4143 * other status codes for better user feed back. However, no
4144 * other non-error status is allowed.
4145 */
4146 LogRel(("SSM: Error - '%s'/#%u voted %Rrc! (pass=%u)\n", pUnit->szName, pUnit->u32Instance, rc, uPass));
4147 AssertMsgReturn(RT_FAILURE(rc), ("%Rrc; '%s'\n", rc, pUnit->szName), pSSM->rc = VERR_IPE_UNEXPECTED_INFO_STATUS);
4148 return pSSM->rc = rc;
4149 }
4150 }
4151 }
4152
4153 LogRel(("SSM: Step 1 completed after pass %u.\n", uPass));
4154 return VINF_SUCCESS;
4155}
4156
4157
4158/**
4159 * Calls pfnLiveExec for all units.
4160 *
4161 * @returns VBox status code (no need to check pSSM->rc).
4162 *
4163 * @param pVM The VM handle.
4164 * @param pSSM The saved state handle.
4165 * @param uPass The current pass.
4166 */
4167static int ssmR3LiveDoExecRun(PVM pVM, PSSMHANDLE pSSM, uint32_t uPass)
4168{
4169 AssertRC(pSSM->rc);
4170 pSSM->rc = VINF_SUCCESS;
4171 pSSM->enmOp = SSMSTATE_LIVE_EXEC;
4172 for (PSSMUNIT pUnit = pVM->ssm.s.pHead;
4173 /** @todo VMR3GetState(pVM) == VMSTATE_LIVE_SAVING &&*/ pUnit;
4174 pUnit = pUnit->pNext)
4175 {
4176 /*
4177 * Skip units without a callback (this is most).
4178 */
4179 if (!pUnit->u.Common.pfnLiveExec)
4180 continue;
4181 pUnit->offStream = ssmR3StrmTell(&pSSM->Strm);
4182
4183 /*
4184 * Check for cancellation.
4185 */
4186 if (RT_UNLIKELY(ASMAtomicUoReadU32(&(pSSM)->fCancelled) == SSMHANDLE_CANCELLED))
4187 {
4188 LogRel(("SSM: Cancelled!\n"));
4189 AssertRC(pSSM->rc);
4190 return pSSM->rc = VERR_SSM_CANCELLED;
4191 }
4192
4193 /*
4194 * Write data unit header.
4195 */
4196 SSMFILEUNITHDRV2 UnitHdr;
4197 memcpy(&UnitHdr.szMagic[0], SSMFILEUNITHDR_MAGIC, sizeof(UnitHdr.szMagic));
4198 UnitHdr.offStream = pUnit->offStream;
4199 UnitHdr.u32CurStreamCRC = ssmR3StrmCurCRC(&pSSM->Strm);
4200 UnitHdr.u32CRC = 0;
4201 UnitHdr.u32Version = pUnit->u32Version;
4202 UnitHdr.u32Instance = pUnit->u32Instance;
4203 UnitHdr.u32Pass = uPass;
4204 UnitHdr.fFlags = 0;
4205 UnitHdr.cbName = (uint32_t)pUnit->cchName + 1;
4206 memcpy(&UnitHdr.szName[0], &pUnit->szName[0], UnitHdr.cbName);
4207 UnitHdr.u32CRC = RTCrc32(&UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]));
4208 Log(("SSM: Unit at %#9llx: '%s', instance %u, pass %#x, version %u\n",
4209 UnitHdr.offStream, UnitHdr.szName, UnitHdr.u32Instance, UnitHdr.u32Pass, UnitHdr.u32Version));
4210 int rc = ssmR3StrmWrite(&pSSM->Strm, &UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]));
4211 if (RT_FAILURE(rc))
4212 {
4213 LogRel(("SSM: Failed to write unit header. rc=%Rrc\n", rc));
4214 return pSSM->rc = rc;
4215 }
4216
4217 /*
4218 * Call the execute handler.
4219 */
4220 ssmR3DataWriteBegin(pSSM);
4221 switch (pUnit->enmType)
4222 {
4223 case SSMUNITTYPE_DEV:
4224 rc = pUnit->u.Dev.pfnLiveExec(pUnit->u.Dev.pDevIns, pSSM, uPass);
4225 break;
4226 case SSMUNITTYPE_DRV:
4227 rc = pUnit->u.Drv.pfnLiveExec(pUnit->u.Drv.pDrvIns, pSSM, uPass);
4228 break;
4229 case SSMUNITTYPE_INTERNAL:
4230 rc = pUnit->u.Internal.pfnLiveExec(pVM, pSSM, uPass);
4231 break;
4232 case SSMUNITTYPE_EXTERNAL:
4233 rc = pUnit->u.External.pfnLiveExec(pSSM, pUnit->u.External.pvUser, uPass);
4234 break;
4235 default:
4236 rc = VERR_INTERNAL_ERROR;
4237 break;
4238 }
4239 pUnit->fCalled = true;
4240 if (RT_FAILURE(rc) && RT_SUCCESS_NP(pSSM->rc))
4241 pSSM->rc = rc;
4242 else
4243 rc = ssmR3DataFlushBuffer(pSSM); /* will return SSMHANDLE::rc if it is set */
4244 if (RT_FAILURE(rc))
4245 {
4246 LogRel(("SSM: Execute save failed with rc=%Rrc for data unit '%s'/#%u.\n", rc, pUnit->szName, pUnit->u32Instance));
4247 if (RT_SUCCESS(pSSM->rc))
4248 pSSM->rc = rc;
4249 return rc;
4250 }
4251
4252 /*
4253 * Write the termination record and flush the compression stream.
4254 */
4255 SSMRECTERM TermRec;
4256 TermRec.u8TypeAndFlags = SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_TERM;
4257 TermRec.cbRec = sizeof(TermRec) - 2;
4258 if (pSSM->Strm.fChecksummed)
4259 {
4260 TermRec.fFlags = SSMRECTERM_FLAGS_CRC32;
4261 TermRec.u32StreamCRC = RTCrc32Finish(RTCrc32Process(ssmR3StrmCurCRC(&pSSM->Strm), &TermRec, 2));
4262 }
4263 else
4264 {
4265 TermRec.fFlags = 0;
4266 TermRec.u32StreamCRC = 0;
4267 }
4268 TermRec.cbUnit = pSSM->offUnit + sizeof(TermRec);
4269 rc = ssmR3DataWriteRaw(pSSM, &TermRec, sizeof(TermRec));
4270 if (RT_SUCCESS(rc))
4271 rc = ssmR3DataWriteFinish(pSSM);
4272 if (RT_FAILURE(rc))
4273 {
4274 LogRel(("SSM: Failed terminating unit: %Rrc (pass=%u)\n", rc, uPass));
4275 return pSSM->rc = rc;
4276 }
4277 } /* for each unit */
4278
4279 return VINF_SUCCESS;
4280}
4281
4282
4283
4284/**
4285 * Continue a live state saving operation on the worker thread.
4286 *
4287 * @returns VBox status.
4288 *
4289 * @param pSSM The SSM handle returned by SSMR3LiveToFile or
4290 * SSMR3LiveToRemote.
4291 *
4292 * @thread Non-EMT thread. Will involve the EMT at the end of the operation.
4293 */
4294VMMR3_INT_DECL(int) SSMR3LiveDoStep1(PSSMHANDLE pSSM)
4295{
4296 LogFlow(("SSMR3LiveDoStep1: pSSM=%p\n", pSSM));
4297
4298 /*
4299 * Validate input.
4300 */
4301 AssertPtrReturn(pSSM, VERR_INVALID_POINTER);
4302 PVM pVM = pSSM->pVM;
4303 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
4304 VM_ASSERT_OTHER_THREAD(pVM);
4305 AssertMsgReturn( pSSM->enmAfter == SSMAFTER_DESTROY
4306 || pSSM->enmAfter == SSMAFTER_CONTINUE,
4307 ("%d\n", pSSM->enmAfter),
4308 VERR_INVALID_PARAMETER);
4309 AssertMsgReturn(pSSM->enmOp == SSMSTATE_LIVE_STEP1, ("%d\n", pSSM->enmOp), VERR_INVALID_STATE);
4310 AssertRCReturn(pSSM->rc, pSSM->rc);
4311
4312 /*
4313 * Calc the max saved state size before we should give up because of insane
4314 * amounts of data.
4315 */
4316#define SSM_MAX_GROWTH_FILE 10000
4317#define SSM_MAX_GROWTH_REMOTE 100000
4318 uint64_t cbSum = 0;
4319 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
4320 cbSum += pUnit->cbGuess;
4321 uint64_t cbMax = cbSum * (pSSM->pszFilename ? SSM_MAX_GROWTH_FILE : SSM_MAX_GROWTH_REMOTE);
4322 AssertLogRelMsgReturn(cbMax > cbSum, ("cbMax=%#RX64, cbSum=%#RX64\n", cbMax, cbSum), pSSM->rc = VERR_OUT_OF_RANGE);
4323 if (cbMax < _1G)
4324 cbMax = _1G;
4325
4326 /*
4327 * The pass loop.
4328 *
4329 * The number of interations is restricted for two reasons, first
4330 * to make sure
4331 */
4332#define SSM_MAX_PASSES _1M
4333 for (uint32_t uPass = 0; uPass < SSM_MAX_PASSES; uPass++)
4334 {
4335 /*
4336 * Save state and vote on whether we need more passes or not.
4337 */
4338 int rc = ssmR3LiveDoExecRun(pVM, pSSM, uPass);
4339 if (RT_FAILURE(rc))
4340 return rc;
4341 rc = ssmR3LiveDoVoteRun(pVM, pSSM, uPass);
4342 if (rc == VINF_SUCCESS)
4343 {
4344 pSSM->enmOp = SSMSTATE_LIVE_STEP2;
4345 return VINF_SUCCESS;
4346 }
4347 if (RT_FAILURE(rc))
4348 return rc;
4349
4350 /*
4351 * Check that we're still within sane data amounts.
4352 */
4353 uint64_t cbSaved = ssmR3StrmTell(&pSSM->Strm);
4354 if (cbSaved > cbMax)
4355 {
4356 LogRel(("SSM: Giving up: Exceeded max state size. (cbSaved=%#RX64, cbMax=%#RX64)\n", cbSaved, cbMax));
4357 return pSSM->rc = VERR_SSM_STATE_GREW_TOO_BIG;
4358 }
4359
4360 /*
4361 * Check that there is still some space left on the disk.
4362 */
4363 /** @todo move this to the stream flushing code? It's not perfect when done
4364 * here, it could be way better if we did it there. */
4365 if (pSSM->pszFilename)
4366 {
4367 RTFOFF cbFree;
4368 rc = RTFsQuerySizes(pSSM->pszFilename, NULL, &cbFree, NULL, NULL);
4369 AssertRC(rc);
4370#define SSM_MIN_DISK_FREE ((RTFOFF)( 10 * _1M ))
4371 if ( RT_SUCCESS(rc)
4372 && cbFree < SSM_MIN_DISK_FREE)
4373 {
4374 LogRel(("SSM: Giving up: Low on disk space. (cbFree=%RTfoff, SSM_MIN_DISK_FREE=%RTfoff).\n",
4375 cbFree, SSM_MIN_DISK_FREE));
4376 return pSSM->rc = VERR_SSM_LOW_ON_DISK_SPACE;
4377 }
4378 }
4379#if 0
4380 /*
4381 * Check the VM state to see if it has changed.
4382 */
4383 VMSTATE enmState = VMR3GetState(pVM);
4384 if (enmState != VMSTATE_LIVE_SAVING)
4385 {
4386 switch (enmState)
4387 {
4388 case VMSTATE_LIVE_CANCELLED:
4389 LogRel(("SSM: Cancelled\n"));
4390 return pSSM->rc = VERR_SSM_LIVE_CANCELLED;
4391 case VMSTATE_LIVE_POWERED_OFF:
4392 LogRel(("SSM: Powered off, no state to save, aborting.\n"));
4393 return pSSM->rc = VERR_SSM_LIVE_POWERED_OFF;
4394 case VMSTATE_GURU_MEDITATION:
4395 LogRel(("SSM: Guru meditation, aborting.\n"));
4396 return pSSM->rc = VERR_SSM_LIVE_GURU_MEDITATION;
4397 default:
4398 LogRel(("SSM: Invalid VM state transition: %d->%d\n", VMSTATE_LIVE_SAVING, enmState));
4399 return pSSM->rc = VERR_INTERNAL_ERROR_3;
4400 }
4401 }
4402#endif
4403 }
4404
4405 LogRel(("SSM: Giving up: Too many passes! (%u)\n", SSM_MAX_PASSES));
4406 return pSSM->rc = VERR_SSM_TOO_MANY_PASSES;
4407}
4408
4409
4410/**
4411 * Calls pfnLivePrep for all units.
4412 *
4413 * @returns VBox status code (no need to check pSSM->rc).
4414 * @param pVM The VM handle.
4415 * @param pSSM The saved state handle.
4416 */
4417static int ssmR3DoLivePrepRun(PVM pVM, PSSMHANDLE pSSM)
4418{
4419 /*
4420 * Do the prepare run.
4421 */
4422 pSSM->rc = VINF_SUCCESS;
4423 pSSM->enmOp = SSMSTATE_SAVE_PREP;
4424 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
4425 {
4426 if (pUnit->u.Common.pfnLivePrep)
4427 {
4428 int rc;
4429 switch (pUnit->enmType)
4430 {
4431 case SSMUNITTYPE_DEV:
4432 rc = pUnit->u.Dev.pfnLivePrep(pUnit->u.Dev.pDevIns, pSSM);
4433 break;
4434 case SSMUNITTYPE_DRV:
4435 rc = pUnit->u.Drv.pfnLivePrep(pUnit->u.Drv.pDrvIns, pSSM);
4436 break;
4437 case SSMUNITTYPE_INTERNAL:
4438 rc = pUnit->u.Internal.pfnLivePrep(pVM, pSSM);
4439 break;
4440 case SSMUNITTYPE_EXTERNAL:
4441 rc = pUnit->u.External.pfnLivePrep(pSSM, pUnit->u.External.pvUser);
4442 break;
4443 default:
4444 rc = VERR_INTERNAL_ERROR;
4445 break;
4446 }
4447 pUnit->fCalled = true;
4448 if (RT_FAILURE(rc) && RT_SUCCESS_NP(pSSM->rc))
4449 pSSM->rc = rc;
4450 else
4451 rc = pSSM->rc;
4452 if (RT_FAILURE(rc))
4453 {
4454 LogRel(("SSM: Prepare save failed with rc=%Rrc for data unit '%s.\n", rc, pUnit->szName));
4455 return rc;
4456 }
4457 }
4458
4459 pSSM->cbEstTotal += pUnit->cbGuess;
4460 }
4461
4462 /*
4463 * Work the progress indicator if we got one.
4464 */
4465 if (pSSM->pfnProgress)
4466 pSSM->pfnProgress(pVM, 2, pSSM->pvUser);
4467 pSSM->uPercent = 2;
4468
4469 return VINF_SUCCESS;
4470}
4471
4472
4473/**
4474 * Start saving the live state to a file.
4475 *
4476 * Call SSMR3LiveDoStep1, SSMR3LiveDoStep2 and finally SSMR3LiveDone on success.
4477 * SSMR3LiveDone should be called even if SSMR3LiveDoStep1 or SSMR3LiveDoStep2
4478 * fails.
4479 *
4480 * @returns VBox status.
4481 *
4482 * @param pVM The VM handle.
4483 * @param pszFilename Name of the file to save the state in. This string
4484 * must remain valid until SSMR3LiveDone is called.
4485 * @param enmAfter What is planned after a successful save operation.
4486 * @param pfnProgress Progress callback. Optional.
4487 * @param pvUser User argument for the progress callback.
4488 *
4489 * @thread EMT0
4490 */
4491VMMR3_INT_DECL(int) SSMR3LiveToFile(PVM pVM, const char *pszFilename, SSMAFTER enmAfter,
4492 PFNVMPROGRESS pfnProgress, void *pvUser, PSSMHANDLE *ppSSM)
4493{
4494 LogFlow(("SSMR3LiveToFile: pszFilename=%p:{%s} enmAfter=%d pfnProgress=%p pvUser=%p\n", pszFilename, pszFilename, enmAfter, pfnProgress, pvUser));
4495 VM_ASSERT_EMT0(pVM);
4496
4497 /*
4498 * Validate input.
4499 */
4500 AssertMsgReturn( enmAfter == SSMAFTER_DESTROY
4501 || enmAfter == SSMAFTER_CONTINUE,
4502 ("%d\n", enmAfter),
4503 VERR_INVALID_PARAMETER);
4504
4505 /*
4506 * Create the saved state file and handle.
4507 *
4508 * Note that there might be quite some work to do after executing the saving,
4509 * so we reserve 20% for the 'Done' period.
4510 */
4511 PSSMHANDLE pSSM;
4512 int rc = ssmR3SaveDoCreateFile(pVM, pszFilename, enmAfter, pfnProgress, pvUser, &pSSM);
4513 if (RT_FAILURE(rc))
4514 return rc;
4515 pSSM->uPercentPrepare = 20; /** @todo fix these. */
4516 pSSM->uPercentDone = 2;
4517
4518 /*
4519 * Write the saved state stream header and do the prep run for live saving.
4520 */
4521 Log(("SSM: Starting state save to file '%s'...\n", pszFilename));
4522 ssmR3StrmStartIoThread(&pSSM->Strm);
4523 rc = ssmR3WriteHeaderAndClearPerUnitData(pVM, pSSM);
4524 if (RT_SUCCESS(rc))
4525 {
4526/** @todo If it turns out we don't need to do ssmR3DoLivePrepRun on EMT0,
4527 * simply move the code to SSMR3LiveDoStep1. */
4528 rc = ssmR3DoLivePrepRun(pVM, pSSM);
4529 if (RT_SUCCESS(rc))
4530 {
4531 /*
4532 * Return and let the requstor thread do the pfnLiveExec/Vote part
4533 * via SSMR3SaveFinishLive
4534 */
4535 pSSM->enmOp = SSMSTATE_LIVE_STEP1;
4536 ssmR3SetCancellable(pVM, pSSM, true);
4537 *ppSSM = pSSM;
4538 return VINF_SUCCESS;
4539 }
4540 }
4541 /* bail out. */
4542 int rc2 = ssmR3StrmClose(&pSSM->Strm);
4543 RTMemFree(pSSM);
4544 rc2 = RTFileDelete(pszFilename);
4545 AssertRC(rc2);
4546 return rc;
4547}
4548
4549
4550VMMR3DECL(int) SSMR3LiveToRemote(PVM pVM, PFNVMPROGRESS pfnProgress, void *pvUser /*,
4551 invent stream interface and stuff */)
4552{
4553 return VERR_NOT_IMPLEMENTED;
4554}
4555
4556
4557/* ... Loading and reading starts here ... */
4558/* ... Loading and reading starts here ... */
4559/* ... Loading and reading starts here ... */
4560/* ... Loading and reading starts here ... */
4561/* ... Loading and reading starts here ... */
4562/* ... Loading and reading starts here ... */
4563/* ... Loading and reading starts here ... */
4564/* ... Loading and reading starts here ... */
4565/* ... Loading and reading starts here ... */
4566/* ... Loading and reading starts here ... */
4567/* ... Loading and reading starts here ... */
4568/* ... Loading and reading starts here ... */
4569/* ... Loading and reading starts here ... */
4570/* ... Loading and reading starts here ... */
4571/* ... Loading and reading starts here ... */
4572/* ... Loading and reading starts here ... */
4573/* ... Loading and reading starts here ... */
4574
4575
4576/**
4577 * Closes the decompressor of a data unit.
4578 *
4579 * @returns pSSM->rc.
4580 * @param pSSM SSM operation handle.
4581 */
4582static int ssmR3DataReadFinishV1(PSSMHANDLE pSSM)
4583{
4584 if (pSSM->u.Read.pZipDecompV1)
4585 {
4586 int rc = RTZipDecompDestroy(pSSM->u.Read.pZipDecompV1);
4587 AssertRC(rc);
4588 pSSM->u.Read.pZipDecompV1 = NULL;
4589 }
4590 return pSSM->rc;
4591}
4592
4593
4594/**
4595 * Callback for reading compressed data into the input buffer of the
4596 * decompressor, for saved file format version 1.
4597 *
4598 * @returns VBox status code.
4599 * @param pvSSM The SSM handle.
4600 * @param pvBuf Where to store the compressed data.
4601 * @param cbBuf Size of the buffer.
4602 * @param pcbRead Number of bytes actually stored in the buffer.
4603 */
4604static DECLCALLBACK(int) ssmR3ReadInV1(void *pvSSM, void *pvBuf, size_t cbBuf, size_t *pcbRead)
4605{
4606 PSSMHANDLE pSSM = (PSSMHANDLE)pvSSM;
4607 size_t cbRead = cbBuf;
4608 if (pSSM->cbUnitLeftV1 < cbBuf)
4609 cbRead = (size_t)pSSM->cbUnitLeftV1;
4610 if (cbRead)
4611 {
4612 //Log2(("ssmR3ReadInV1: %#010llx cbBug=%#x cbRead=%#x\n", ssmR3StrmTell(&pSSM->Strm), cbBuf, cbRead));
4613 int rc = ssmR3StrmRead(&pSSM->Strm, pvBuf, cbRead);
4614 if (RT_SUCCESS(rc))
4615 {
4616 pSSM->cbUnitLeftV1 -= cbRead;
4617 if (pcbRead)
4618 *pcbRead = cbRead;
4619 ssmR3Progress(pSSM, cbRead);
4620 return VINF_SUCCESS;
4621 }
4622 return rc;
4623 }
4624
4625 if (pSSM->enmAfter != SSMAFTER_DEBUG_IT)
4626 AssertMsgFailed(("SSM: attempted reading more than the unit!\n"));
4627 return VERR_SSM_LOADED_TOO_MUCH;
4628}
4629
4630
4631/**
4632 * Internal read worker for reading data from a version 1 unit.
4633 *
4634 * @param pSSM SSM operation handle.
4635 * @param pvBuf Where to store the read data.
4636 * @param cbBuf Number of bytes to read.
4637 */
4638static int ssmR3DataReadV1(PSSMHANDLE pSSM, void *pvBuf, size_t cbBuf)
4639{
4640 /*
4641 * Open the decompressor on the first read.
4642 */
4643 if (!pSSM->u.Read.pZipDecompV1)
4644 {
4645 pSSM->rc = RTZipDecompCreate(&pSSM->u.Read.pZipDecompV1, pSSM, ssmR3ReadInV1);
4646 if (RT_FAILURE(pSSM->rc))
4647 return pSSM->rc;
4648 }
4649
4650 /*
4651 * Do the requested read.
4652 */
4653 int rc = pSSM->rc = RTZipDecompress(pSSM->u.Read.pZipDecompV1, pvBuf, cbBuf, NULL);
4654 if (RT_SUCCESS(rc))
4655 {
4656 Log2(("ssmR3DataRead: pvBuf=%p cbBuf=%#x offUnit=%#llx %.*Rhxs%s\n", pvBuf, cbBuf, pSSM->offUnit, RT_MIN(cbBuf, SSM_LOG_BYTES), pvBuf, cbBuf > SSM_LOG_BYTES ? "..." : ""));
4657 pSSM->offUnit += cbBuf;
4658 return VINF_SUCCESS;
4659 }
4660 AssertMsgFailed(("rc=%Rrc cbBuf=%#x\n", rc, cbBuf));
4661 return rc;
4662}
4663
4664
4665/**
4666 * Creates the decompressor for the data unit.
4667 *
4668 * pSSM->rc will be set on error.
4669 *
4670 * @param pSSM SSM operation handle.
4671 */
4672static void ssmR3DataReadBeginV2(PSSMHANDLE pSSM)
4673{
4674 Assert(!pSSM->u.Read.cbDataBuffer || pSSM->u.Read.cbDataBuffer == pSSM->u.Read.offDataBuffer);
4675 Assert(!pSSM->u.Read.cbRecLeft);
4676
4677 pSSM->offUnit = 0;
4678 pSSM->u.Read.cbRecLeft = 0;
4679 pSSM->u.Read.cbDataBuffer = 0;
4680 pSSM->u.Read.offDataBuffer = 0;
4681 pSSM->u.Read.fEndOfData = false;
4682 pSSM->u.Read.u8TypeAndFlags = 0;
4683}
4684
4685
4686/**
4687 * Checks for the termination record and closes the decompressor.
4688 *
4689 * pSSM->rc will be set on error.
4690 *
4691 * @returns pSSM->rc.
4692 * @param pSSM SSM operation handle.
4693 */
4694static int ssmR3DataReadFinishV2(PSSMHANDLE pSSM)
4695{
4696 /*
4697 * If we haven't encountered the end of the record, it must be the next one.
4698 */
4699 int rc = pSSM->rc;
4700 if ( !pSSM->u.Read.fEndOfData
4701 && RT_SUCCESS(rc))
4702 {
4703 rc = ssmR3DataReadRecHdrV2(pSSM);
4704 if ( RT_SUCCESS(rc)
4705 && !pSSM->u.Read.fEndOfData)
4706 {
4707 rc = VERR_SSM_LOADED_TOO_LITTLE;
4708 AssertFailed();
4709 }
4710 pSSM->rc = rc;
4711 }
4712 return rc;
4713}
4714
4715
4716/**
4717 * Read reader that keep works the progress indicator and unit offset.
4718 *
4719 * Does not set SSM::rc.
4720 *
4721 * @returns VBox status code.
4722 * @param pSSM The saved state handle.
4723 * @param pvBuf Where to put the bits
4724 * @param cbBuf How many bytes to read.
4725 */
4726DECLINLINE(int) ssmR3DataReadV2Raw(PSSMHANDLE pSSM, void *pvBuf, size_t cbToRead)
4727{
4728 int rc = ssmR3StrmRead(&pSSM->Strm, pvBuf, cbToRead);
4729 if (RT_SUCCESS(rc))
4730 {
4731 pSSM->offUnit += cbToRead;
4732 ssmR3Progress(pSSM, cbToRead);
4733 return VINF_SUCCESS;
4734 }
4735
4736 /** @todo weed out lazy saving */
4737 if (pSSM->enmAfter != SSMAFTER_DEBUG_IT)
4738 AssertMsgFailed(("SSM: attempted reading more than the unit!\n"));
4739 return VERR_SSM_LOADED_TOO_MUCH;
4740}
4741
4742
4743/**
4744 * Reads and checks the LZF "header".
4745 *
4746 * @returns VBox status code.
4747 * @param pSSM The saved state handle..
4748 * @param pcbDecompr Where to store the size of the decompressed data.
4749 */
4750DECLINLINE(int) ssmR3DataReadV2RawLzfHdr(PSSMHANDLE pSSM, uint32_t *pcbDecompr)
4751{
4752 *pcbDecompr = 0; /* shuts up gcc. */
4753 AssertLogRelMsgReturn( pSSM->u.Read.cbRecLeft > 1
4754 && pSSM->u.Read.cbRecLeft <= RT_SIZEOFMEMB(SSMHANDLE, u.Read.abComprBuffer) + 2,
4755 ("%#x\n", pSSM->u.Read.cbRecLeft),
4756 VERR_SSM_INTEGRITY_DECOMPRESSION);
4757
4758 uint8_t cKB;
4759 int rc = ssmR3DataReadV2Raw(pSSM, &cKB, 1);
4760 if (RT_FAILURE(rc))
4761 return rc;
4762 pSSM->u.Read.cbRecLeft -= sizeof(cKB);
4763
4764 uint32_t cbDecompr = (uint32_t)cKB * _1K;
4765 AssertLogRelMsgReturn( cbDecompr >= pSSM->u.Read.cbRecLeft
4766 && cbDecompr <= RT_SIZEOFMEMB(SSMHANDLE, u.Read.abDataBuffer),
4767 ("%#x\n", cbDecompr),
4768 VERR_SSM_INTEGRITY_DECOMPRESSION);
4769
4770 *pcbDecompr = cbDecompr;
4771 return VINF_SUCCESS;
4772}
4773
4774
4775/**
4776 * Reads an LZF block from the stream and decompresses into the specified
4777 * buffer.
4778 *
4779 * @returns VBox status code.
4780 * @param SSM The saved state handle.
4781 * @param pvDst Pointer to the output buffer.
4782 * @param cbDecompr The size of the decompressed data.
4783 */
4784static int ssmR3DataReadV2RawLzf(PSSMHANDLE pSSM, void *pvDst, size_t cbDecompr)
4785{
4786 int rc;
4787 uint32_t cbCompr = pSSM->u.Read.cbRecLeft;
4788 pSSM->u.Read.cbRecLeft = 0;
4789
4790 /*
4791 * Try use the stream buffer directly to avoid copying things around.
4792 */
4793 uint8_t const *pb = ssmR3StrmReadDirect(&pSSM->Strm, cbCompr);
4794 if (pb)
4795 {
4796 pSSM->offUnit += cbCompr;
4797 ssmR3Progress(pSSM, cbCompr);
4798 }
4799 else
4800 {
4801 rc = ssmR3DataReadV2Raw(pSSM, &pSSM->u.Read.abComprBuffer[0], cbCompr);
4802 if (RT_FAILURE(rc))
4803 return rc;
4804 pb = &pSSM->u.Read.abComprBuffer[0];
4805 }
4806
4807 /*
4808 * Decompress it.
4809 */
4810 size_t cbDstActual;
4811 rc = RTZipBlockDecompress(RTZIPTYPE_LZF, 0 /*fFlags*/,
4812 pb, cbCompr, NULL /*pcbSrcActual*/,
4813 pvDst, cbDecompr, &cbDstActual);
4814 if (RT_SUCCESS(rc))
4815 {
4816 AssertLogRelMsgReturn(cbDstActual == cbDecompr, ("%#x %#x\n", cbDstActual, cbDecompr), VERR_SSM_INTEGRITY_DECOMPRESSION);
4817 return VINF_SUCCESS;
4818 }
4819
4820 AssertLogRelMsgFailed(("cbCompr=%#x cbDecompr=%#x rc=%Rrc\n", cbCompr, cbDecompr, rc));
4821 return VERR_SSM_INTEGRITY_DECOMPRESSION;
4822}
4823
4824
4825/**
4826 * Reads and checks the raw zero "header".
4827 *
4828 * @returns VBox status code.
4829 * @param pSSM The saved state handle..
4830 * @param pcbDecompr Where to store the size of the zero data.
4831 */
4832DECLINLINE(int) ssmR3DataReadV2RawZeroHdr(PSSMHANDLE pSSM, uint32_t *pcbZero)
4833{
4834 *pcbZero = 0; /* shuts up gcc. */
4835 AssertLogRelMsgReturn(pSSM->u.Read.cbRecLeft == 1, ("%#x\n", pSSM->u.Read.cbRecLeft), VERR_SSM_INTEGRITY_DECOMPRESSION);
4836
4837 uint8_t cKB;
4838 int rc = ssmR3DataReadV2Raw(pSSM, &cKB, 1);
4839 if (RT_FAILURE(rc))
4840 return rc;
4841 pSSM->u.Read.cbRecLeft = 0;
4842
4843 uint32_t cbZero = (uint32_t)cKB * _1K;
4844 AssertLogRelMsgReturn(cbZero <= RT_SIZEOFMEMB(SSMHANDLE, u.Read.abDataBuffer),
4845 ("%#x\n", cbZero), VERR_SSM_INTEGRITY_DECOMPRESSION);
4846
4847 *pcbZero = cbZero;
4848 return VINF_SUCCESS;
4849}
4850
4851
4852/**
4853 * Worker for reading the record header.
4854 *
4855 * It sets pSSM->u.Read.cbRecLeft, pSSM->u.Read.u8TypeAndFlags and
4856 * pSSM->u.Read.fEndOfData. When a termination record is encounter, it will be
4857 * read in full and validated, the fEndOfData indicator is set, and VINF_SUCCESS
4858 * is returned.
4859 *
4860 * @returns VBox status code.
4861 * @param pSSM The saved state handle.
4862 */
4863static int ssmR3DataReadRecHdrV2(PSSMHANDLE pSSM)
4864{
4865 AssertLogRelReturn(!pSSM->u.Read.fEndOfData, VERR_SSM_LOADED_TOO_MUCH);
4866
4867 /*
4868 * Read the two mandatory bytes.
4869 */
4870 uint8_t abHdr[8];
4871 int rc = ssmR3DataReadV2Raw(pSSM, abHdr, 2);
4872 if (RT_FAILURE(rc))
4873 return rc;
4874
4875 /*
4876 * Validate the first byte and check for the termination records.
4877 */
4878 pSSM->u.Read.u8TypeAndFlags = abHdr[0];
4879 AssertLogRelMsgReturn(SSM_REC_ARE_TYPE_AND_FLAGS_VALID(abHdr[0]), ("%#x %#x\n", abHdr[0], abHdr[1]), VERR_SSM_INTEGRITY_REC_HDR);
4880 if ((abHdr[0] & SSM_REC_TYPE_MASK) == SSM_REC_TYPE_TERM)
4881 {
4882 pSSM->u.Read.cbRecLeft = 0;
4883 pSSM->u.Read.fEndOfData = true;
4884 AssertLogRelMsgReturn(abHdr[1] == sizeof(SSMRECTERM) - 2, ("%#x\n", abHdr[1]), VERR_SSM_INTEGRITY_REC_TERM);
4885 AssertLogRelMsgReturn(abHdr[0] & SSM_REC_FLAGS_IMPORTANT, ("%#x\n", abHdr[0]), VERR_SSM_INTEGRITY_REC_TERM);
4886
4887 /* get the rest */
4888 uint32_t u32StreamCRC = ssmR3StrmFinalCRC(&pSSM->Strm);
4889 SSMRECTERM TermRec;
4890 int rc = ssmR3DataReadV2Raw(pSSM, (uint8_t *)&TermRec + 2, sizeof(SSMRECTERM) - 2);
4891 if (RT_FAILURE(rc))
4892 return rc;
4893
4894 /* validate integrity */
4895 AssertLogRelMsgReturn(TermRec.cbUnit == pSSM->offUnit,
4896 ("cbUnit=%#llx offUnit=%#llx\n", TermRec.cbUnit, pSSM->offUnit),
4897 VERR_SSM_INTEGRITY_REC_TERM);
4898 AssertLogRelMsgReturn(!(TermRec.fFlags & ~SSMRECTERM_FLAGS_CRC32), ("%#x\n", TermRec.fFlags), VERR_SSM_INTEGRITY_REC_TERM);
4899 if (!(TermRec.fFlags & SSMRECTERM_FLAGS_CRC32))
4900 AssertLogRelMsgReturn(TermRec.u32StreamCRC == 0, ("%#x\n", TermRec.u32StreamCRC), VERR_SSM_INTEGRITY_REC_TERM);
4901 else if (pSSM->Strm.fChecksummed)
4902 AssertLogRelMsgReturn(TermRec.u32StreamCRC == u32StreamCRC, ("%#x, %#x\n", TermRec.u32StreamCRC, u32StreamCRC),
4903 VERR_SSM_INTEGRITY_REC_TERM_CRC);
4904
4905 Log3(("ssmR3DataReadRecHdrV2: %08llx|%08llx: TERM\n", ssmR3StrmTell(&pSSM->Strm) - sizeof(SSMRECTERM), pSSM->offUnit));
4906 return VINF_SUCCESS;
4907 }
4908
4909 /*
4910 * Figure the size. The 2nd byte is encoded in UTF-8 fashion, so this
4911 * is can be highly enjoyable.
4912 */
4913 uint32_t cbHdr = 2;
4914 uint32_t cb = abHdr[1];
4915 if (!(cb & 0x80))
4916 pSSM->u.Read.cbRecLeft = cb;
4917 else
4918 {
4919 /*
4920 * Need more data. Figure how much and read it.
4921 */
4922 if (!(cb & RT_BIT(5)))
4923 cb = 2;
4924 else if (!(cb & RT_BIT(4)))
4925 cb = 3;
4926 else if (!(cb & RT_BIT(3)))
4927 cb = 4;
4928 else if (!(cb & RT_BIT(2)))
4929 cb = 5;
4930 else if (!(cb & RT_BIT(1)))
4931 cb = 6;
4932 else
4933 AssertLogRelMsgFailedReturn(("Invalid record size byte: %#x\n", cb), VERR_SSM_INTEGRITY_REC_HDR);
4934 cbHdr = cb + 1;
4935
4936 rc = ssmR3DataReadV2Raw(pSSM, &abHdr[2], cb - 1);
4937 if (RT_FAILURE(rc))
4938 return rc;
4939
4940 /*
4941 * Validate what we've read.
4942 */
4943 switch (cb)
4944 {
4945 case 6:
4946 AssertLogRelMsgReturn((abHdr[6] & 0xc0) == 0x80, ("6/%u: %.*Rhxs\n", cb, cb + 1, &abHdr[0]), VERR_SSM_INTEGRITY_REC_HDR);
4947 case 5:
4948 AssertLogRelMsgReturn((abHdr[5] & 0xc0) == 0x80, ("5/%u: %.*Rhxs\n", cb, cb + 1, &abHdr[0]), VERR_SSM_INTEGRITY_REC_HDR);
4949 case 4:
4950 AssertLogRelMsgReturn((abHdr[4] & 0xc0) == 0x80, ("4/%u: %.*Rhxs\n", cb, cb + 1, &abHdr[0]), VERR_SSM_INTEGRITY_REC_HDR);
4951 case 3:
4952 AssertLogRelMsgReturn((abHdr[3] & 0xc0) == 0x80, ("3/%u: %.*Rhxs\n", cb, cb + 1, &abHdr[0]), VERR_SSM_INTEGRITY_REC_HDR);
4953 case 2:
4954 AssertLogRelMsgReturn((abHdr[2] & 0xc0) == 0x80, ("2/%u: %.*Rhxs\n", cb, cb + 1, &abHdr[0]), VERR_SSM_INTEGRITY_REC_HDR);
4955 break;
4956 default:
4957 return VERR_INTERNAL_ERROR;
4958 }
4959
4960 /*
4961 * Decode it and validate the range.
4962 */
4963 switch (cb)
4964 {
4965 case 6:
4966 cb = (abHdr[6] & 0x3f)
4967 | ((uint32_t)(abHdr[5] & 0x3f) << 6)
4968 | ((uint32_t)(abHdr[4] & 0x3f) << 12)
4969 | ((uint32_t)(abHdr[3] & 0x3f) << 18)
4970 | ((uint32_t)(abHdr[2] & 0x3f) << 24)
4971 | ((uint32_t)(abHdr[1] & 0x01) << 30);
4972 AssertLogRelMsgReturn(cb >= 0x04000000 && cb <= 0x7fffffff, ("cb=%#x\n", cb), VERR_SSM_INTEGRITY_REC_HDR);
4973 break;
4974 case 5:
4975 cb = (abHdr[5] & 0x3f)
4976 | ((uint32_t)(abHdr[4] & 0x3f) << 6)
4977 | ((uint32_t)(abHdr[3] & 0x3f) << 12)
4978 | ((uint32_t)(abHdr[2] & 0x3f) << 18)
4979 | ((uint32_t)(abHdr[1] & 0x03) << 24);
4980 AssertLogRelMsgReturn(cb >= 0x00200000 && cb <= 0x03ffffff, ("cb=%#x\n", cb), VERR_SSM_INTEGRITY_REC_HDR);
4981 break;
4982 case 4:
4983 cb = (abHdr[4] & 0x3f)
4984 | ((uint32_t)(abHdr[3] & 0x3f) << 6)
4985 | ((uint32_t)(abHdr[2] & 0x3f) << 12)
4986 | ((uint32_t)(abHdr[1] & 0x07) << 18);
4987 AssertLogRelMsgReturn(cb >= 0x00010000 && cb <= 0x001fffff, ("cb=%#x\n", cb), VERR_SSM_INTEGRITY_REC_HDR);
4988 break;
4989 case 3:
4990 cb = (abHdr[3] & 0x3f)
4991 | ((uint32_t)(abHdr[2] & 0x3f) << 6)
4992 | ((uint32_t)(abHdr[1] & 0x0f) << 12);
4993#if 0 /* disabled to optimize buffering */
4994 AssertLogRelMsgReturn(cb >= 0x00000800 && cb <= 0x0000ffff, ("cb=%#x\n", cb), VERR_SSM_INTEGRITY_REC_HDR);
4995#endif
4996 break;
4997 case 2:
4998 cb = (abHdr[2] & 0x3f)
4999 | ((uint32_t)(abHdr[1] & 0x1f) << 6);
5000#if 0 /* disabled to optimize buffering */
5001 AssertLogRelMsgReturn(cb >= 0x00000080 && cb <= 0x000007ff, ("cb=%#x\n", cb), VERR_SSM_INTEGRITY_REC_HDR);
5002#endif
5003 break;
5004 default:
5005 return VERR_INTERNAL_ERROR;
5006 }
5007
5008 pSSM->u.Read.cbRecLeft = cb;
5009 }
5010
5011 Log3(("ssmR3DataReadRecHdrV2: %08llx|%08llx/%08x: Type=%02x fImportant=%RTbool cbHdr=%u\n",
5012 ssmR3StrmTell(&pSSM->Strm), pSSM->offUnit, pSSM->u.Read.cbRecLeft,
5013 pSSM->u.Read.u8TypeAndFlags & SSM_REC_TYPE_MASK,
5014 !!(pSSM->u.Read.u8TypeAndFlags & SSM_REC_FLAGS_IMPORTANT),
5015 cbHdr
5016 )); NOREF(cbHdr);
5017 return VINF_SUCCESS;
5018}
5019
5020
5021/**
5022 * Buffer miss, do an unbuffered read.
5023 *
5024 * @param pSSM SSM operation handle.
5025 * @param pvBuf Where to store the read data.
5026 * @param cbBuf Number of bytes to read.
5027 */
5028static int ssmR3DataReadUnbufferedV2(PSSMHANDLE pSSM, void *pvBuf, size_t cbBuf)
5029{
5030 void const *pvBufOrg = pvBuf; NOREF(pvBufOrg);
5031 size_t const cbBufOrg = cbBuf; NOREF(cbBufOrg);
5032
5033 /*
5034 * Copy out what we've got in the buffer.
5035 */
5036 uint32_t off = pSSM->u.Read.offDataBuffer;
5037 int32_t cbInBuffer = pSSM->u.Read.cbDataBuffer - off;
5038 Log4(("ssmR3DataReadUnbufferedV2: %08llx|%08llx/%08x/%08x: cbBuf=%#x\n", ssmR3StrmTell(&pSSM->Strm), pSSM->offUnit, pSSM->u.Read.cbRecLeft, cbInBuffer, cbBufOrg));
5039 if (cbInBuffer > 0)
5040 {
5041 uint32_t const cbToCopy = (uint32_t)cbInBuffer;
5042 Assert(cbBuf > cbToCopy);
5043 memcpy(pvBuf, &pSSM->u.Read.abDataBuffer[off], cbToCopy);
5044 pvBuf = (uint8_t *)pvBuf + cbToCopy;
5045 cbBuf -= cbToCopy;
5046 pSSM->u.Read.cbDataBuffer = 0;
5047 pSSM->u.Read.offDataBuffer = 0;
5048 }
5049
5050 /*
5051 * Read data.
5052 */
5053 do
5054 {
5055 /*
5056 * Read the next record header if no more data.
5057 */
5058 if (!pSSM->u.Read.cbRecLeft)
5059 {
5060 int rc = ssmR3DataReadRecHdrV2(pSSM);
5061 if (RT_FAILURE(rc))
5062 return pSSM->rc = rc;
5063 }
5064 AssertLogRelMsgReturn(!pSSM->u.Read.fEndOfData, ("cbBuf=%zu", cbBuf), pSSM->rc = VERR_SSM_LOADED_TOO_MUCH);
5065
5066 /*
5067 * Read data from the current record.
5068 */
5069 uint32_t cbToRead;
5070 switch (pSSM->u.Read.u8TypeAndFlags & SSM_REC_TYPE_MASK)
5071 {
5072 case SSM_REC_TYPE_RAW:
5073 {
5074 cbToRead = (uint32_t)RT_MIN(cbBuf, pSSM->u.Read.cbRecLeft);
5075 int rc = ssmR3DataReadV2Raw(pSSM, pvBuf, cbToRead);
5076 if (RT_FAILURE(rc))
5077 return pSSM->rc = rc;
5078 pSSM->u.Read.cbRecLeft -= cbToRead;
5079 break;
5080 }
5081
5082 case SSM_REC_TYPE_RAW_LZF:
5083 {
5084 int rc = ssmR3DataReadV2RawLzfHdr(pSSM, &cbToRead);
5085 if (RT_FAILURE(rc))
5086 return rc;
5087 if (cbToRead <= cbBuf)
5088 {
5089 rc = ssmR3DataReadV2RawLzf(pSSM, pvBuf, cbToRead);
5090 if (RT_FAILURE(rc))
5091 return rc;
5092 }
5093 else
5094 {
5095 /* The output buffer is too small, use the data buffer. */
5096 rc = ssmR3DataReadV2RawLzf(pSSM, &pSSM->u.Read.abDataBuffer[0], cbToRead);
5097 if (RT_FAILURE(rc))
5098 return rc;
5099 pSSM->u.Read.cbDataBuffer = cbToRead;
5100 cbToRead = (uint32_t)cbBuf;
5101 pSSM->u.Read.offDataBuffer = cbToRead;
5102 memcpy(pvBuf, &pSSM->u.Read.abDataBuffer[0], cbToRead);
5103 }
5104 break;
5105 }
5106
5107 case SSM_REC_TYPE_RAW_ZERO:
5108 {
5109 int rc = ssmR3DataReadV2RawZeroHdr(pSSM, &cbToRead);
5110 if (RT_FAILURE(rc))
5111 return rc;
5112 if (cbToRead > cbBuf)
5113 {
5114 /* Spill the remainer into the data buffer. */
5115 memset(&pSSM->u.Read.abDataBuffer[0], 0, cbToRead - cbBuf);
5116 pSSM->u.Read.cbDataBuffer = cbToRead - cbBuf;
5117 pSSM->u.Read.offDataBuffer = 0;
5118 cbToRead = (uint32_t)cbBuf;
5119 }
5120 memset(pvBuf, 0, cbToRead);
5121 break;
5122 }
5123
5124 default:
5125 AssertMsgFailedReturn(("%x\n", pSSM->u.Read.u8TypeAndFlags), VERR_INTERNAL_ERROR_5);
5126 }
5127
5128 cbBuf -= cbToRead;
5129 pvBuf = (uint8_t *)pvBuf + cbToRead;
5130 } while (cbBuf > 0);
5131
5132 Log4(("ssmR3DataReadUnBufferedV2: %08llx|%08llx/%08x/%08x: cbBuf=%#x %.*Rhxs%s\n",
5133 ssmR3StrmTell(&pSSM->Strm), pSSM->offUnit, pSSM->u.Read.cbRecLeft, 0, cbBufOrg, RT_MIN(SSM_LOG_BYTES, cbBufOrg), pvBufOrg, cbBufOrg > SSM_LOG_BYTES ? "..." : ""));
5134 return VINF_SUCCESS;
5135}
5136
5137
5138/**
5139 * Buffer miss, do a buffered read.
5140 *
5141 * @param pSSM SSM operation handle.
5142 * @param pvBuf Where to store the read data.
5143 * @param cbBuf Number of bytes to read.
5144 */
5145static int ssmR3DataReadBufferedV2(PSSMHANDLE pSSM, void *pvBuf, size_t cbBuf)
5146{
5147 void const *pvBufOrg = pvBuf; NOREF(pvBufOrg);
5148 size_t const cbBufOrg = cbBuf; NOREF(cbBufOrg);
5149
5150 /*
5151 * Copy out what we've got in the buffer.
5152 */
5153 uint32_t off = pSSM->u.Read.offDataBuffer;
5154 int32_t cbInBuffer = pSSM->u.Read.cbDataBuffer - off;
5155 Log4(("ssmR3DataReadBufferedV2: %08llx|%08llx/%08x/%08x: cbBuf=%#x\n", ssmR3StrmTell(&pSSM->Strm), pSSM->offUnit, pSSM->u.Read.cbRecLeft, cbInBuffer, cbBufOrg));
5156 if (cbInBuffer > 0)
5157 {
5158 uint32_t const cbToCopy = (uint32_t)cbInBuffer;
5159 Assert(cbBuf > cbToCopy);
5160 memcpy(pvBuf, &pSSM->u.Read.abDataBuffer[off], cbToCopy);
5161 pvBuf = (uint8_t *)pvBuf + cbToCopy;
5162 cbBuf -= cbToCopy;
5163 pSSM->u.Read.cbDataBuffer = 0;
5164 pSSM->u.Read.offDataBuffer = 0;
5165 }
5166
5167 /*
5168 * Buffer more data.
5169 */
5170 do
5171 {
5172 /*
5173 * Read the next record header if no more data.
5174 */
5175 if (!pSSM->u.Read.cbRecLeft)
5176 {
5177 int rc = ssmR3DataReadRecHdrV2(pSSM);
5178 if (RT_FAILURE(rc))
5179 return pSSM->rc = rc;
5180 }
5181 AssertLogRelMsgReturn(!pSSM->u.Read.fEndOfData, ("cbBuf=%zu", cbBuf), pSSM->rc = VERR_SSM_LOADED_TOO_MUCH);
5182
5183 /*
5184 * Read data from the current record.
5185 * LATER: optimize by reading directly into the output buffer for some cases.
5186 */
5187 uint32_t cbToRead;
5188 switch (pSSM->u.Read.u8TypeAndFlags & SSM_REC_TYPE_MASK)
5189 {
5190 case SSM_REC_TYPE_RAW:
5191 {
5192 cbToRead = RT_MIN(sizeof(pSSM->u.Read.abDataBuffer), pSSM->u.Read.cbRecLeft);
5193 int rc = ssmR3DataReadV2Raw(pSSM, &pSSM->u.Read.abDataBuffer[0], cbToRead);
5194 if (RT_FAILURE(rc))
5195 return pSSM->rc = rc;
5196 pSSM->u.Read.cbRecLeft -= cbToRead;
5197 pSSM->u.Read.cbDataBuffer = cbToRead;
5198 break;
5199 }
5200
5201 case SSM_REC_TYPE_RAW_LZF:
5202 {
5203 int rc = ssmR3DataReadV2RawLzfHdr(pSSM, &cbToRead);
5204 if (RT_FAILURE(rc))
5205 return rc;
5206 rc = ssmR3DataReadV2RawLzf(pSSM, &pSSM->u.Read.abDataBuffer[0], cbToRead);
5207 if (RT_FAILURE(rc))
5208 return rc;
5209 pSSM->u.Read.cbDataBuffer = cbToRead;
5210 break;
5211 }
5212
5213 case SSM_REC_TYPE_RAW_ZERO:
5214 {
5215 int rc = ssmR3DataReadV2RawZeroHdr(pSSM, &cbToRead);
5216 if (RT_FAILURE(rc))
5217 return rc;
5218 memset(&pSSM->u.Read.abDataBuffer[0], 0, cbToRead);
5219 pSSM->u.Read.cbDataBuffer = cbToRead;
5220 break;
5221 }
5222
5223 default:
5224 AssertMsgFailedReturn(("%x\n", pSSM->u.Read.u8TypeAndFlags), VERR_INTERNAL_ERROR_5);
5225 }
5226 /*pSSM->u.Read.offDataBuffer = 0;*/
5227
5228 /*
5229 * Copy data from the buffer.
5230 */
5231 uint32_t cbToCopy = (uint32_t)RT_MIN(cbBuf, cbToRead);
5232 memcpy(pvBuf, &pSSM->u.Read.abDataBuffer[0], cbToCopy);
5233 cbBuf -= cbToCopy;
5234 pvBuf = (uint8_t *)pvBuf + cbToCopy;
5235 pSSM->u.Read.offDataBuffer = cbToCopy;
5236 } while (cbBuf > 0);
5237
5238 Log4(("ssmR3DataReadBufferedV2: %08llx|%08llx/%08x/%08x: cbBuf=%#x %.*Rhxs%s\n",
5239 ssmR3StrmTell(&pSSM->Strm), pSSM->offUnit, pSSM->u.Read.cbRecLeft, pSSM->u.Read.cbDataBuffer - pSSM->u.Read.offDataBuffer,
5240 cbBufOrg, RT_MIN(SSM_LOG_BYTES, cbBufOrg), pvBufOrg, cbBufOrg > SSM_LOG_BYTES ? "..." : ""));
5241 return VINF_SUCCESS;
5242}
5243
5244
5245/**
5246 * Inlined worker that handles format checks and buffered reads.
5247 *
5248 * @param pSSM SSM operation handle.
5249 * @param pvBuf Where to store the read data.
5250 * @param cbBuf Number of bytes to read.
5251 */
5252DECLINLINE(int) ssmR3DataRead(PSSMHANDLE pSSM, void *pvBuf, size_t cbBuf)
5253{
5254 /*
5255 * Fend off previous errors and V1 data units.
5256 */
5257 if (RT_FAILURE(pSSM->rc))
5258 return pSSM->rc;
5259 if (RT_UNLIKELY(pSSM->u.Read.uFmtVerMajor == 1))
5260 return ssmR3DataReadV1(pSSM, pvBuf, cbBuf);
5261
5262 /*
5263 * Check if the requested data is buffered.
5264 */
5265 uint32_t off = pSSM->u.Read.offDataBuffer;
5266 if ( off + cbBuf > pSSM->u.Read.cbDataBuffer
5267 || cbBuf > sizeof(pSSM->u.Read.abDataBuffer))
5268 {
5269 if (cbBuf <= sizeof(pSSM->u.Read.abDataBuffer) / 8)
5270 return ssmR3DataReadBufferedV2(pSSM, pvBuf, cbBuf);
5271 return ssmR3DataReadUnbufferedV2(pSSM, pvBuf, cbBuf);
5272 }
5273
5274 memcpy(pvBuf, &pSSM->u.Read.abDataBuffer[off], cbBuf);
5275 pSSM->u.Read.offDataBuffer = off + (uint32_t)cbBuf;
5276 Log4((cbBuf
5277 ? "ssmR3DataRead: %08llx|%08llx/%08x/%08x: cbBuf=%#x %.*Rhxs%s\n"
5278 : "ssmR3DataRead: %08llx|%08llx/%08x/%08x: cbBuf=%#x\n",
5279 ssmR3StrmTell(&pSSM->Strm), pSSM->offUnit, pSSM->u.Read.cbRecLeft, pSSM->u.Read.cbDataBuffer - pSSM->u.Read.offDataBuffer,
5280 cbBuf, RT_MIN(SSM_LOG_BYTES, cbBuf), pvBuf, cbBuf > SSM_LOG_BYTES ? "..." : ""));
5281
5282 return VINF_SUCCESS;
5283}
5284
5285
5286/**
5287 * Gets a structure.
5288 *
5289 * @returns VBox status code.
5290 * @param pSSM The saved state handle.
5291 * @param pvStruct The structure address.
5292 * @param paFields The array of structure fields descriptions.
5293 * The array must be terminated by a SSMFIELD_ENTRY_TERM().
5294 */
5295VMMR3DECL(int) SSMR3GetStruct(PSSMHANDLE pSSM, void *pvStruct, PCSSMFIELD paFields)
5296{
5297 /* begin marker. */
5298 uint32_t u32Magic;
5299 int rc = SSMR3GetU32(pSSM, &u32Magic);
5300 if (RT_FAILURE(rc))
5301 return rc;
5302 if (u32Magic != SSMR3STRUCT_BEGIN)
5303 AssertMsgFailedReturn(("u32Magic=%#RX32\n", u32Magic), VERR_SSM_STRUCTURE_MAGIC);
5304
5305 /* put the fields */
5306 for (PCSSMFIELD pCur = paFields;
5307 pCur->cb != UINT32_MAX && pCur->off != UINT32_MAX;
5308 pCur++)
5309 {
5310 rc = ssmR3DataRead(pSSM, (uint8_t *)pvStruct + pCur->off, pCur->cb);
5311 if (RT_FAILURE(rc))
5312 return rc;
5313 }
5314
5315 /* end marker */
5316 rc = SSMR3GetU32(pSSM, &u32Magic);
5317 if (RT_FAILURE(rc))
5318 return rc;
5319 if (u32Magic != SSMR3STRUCT_END)
5320 AssertMsgFailedReturn(("u32Magic=%#RX32\n", u32Magic), VERR_SSM_STRUCTURE_MAGIC);
5321 return rc;
5322}
5323
5324
5325/**
5326 * Loads a boolean item from the current data unit.
5327 *
5328 * @returns VBox status.
5329 * @param pSSM SSM operation handle.
5330 * @param pfBool Where to store the item.
5331 */
5332VMMR3DECL(int) SSMR3GetBool(PSSMHANDLE pSSM, bool *pfBool)
5333{
5334 SSM_ASSERT_READABLE_RET(pSSM);
5335 SSM_CHECK_CANCELLED_RET(pSSM);
5336 uint8_t u8; /* see SSMR3PutBool */
5337 int rc = ssmR3DataRead(pSSM, &u8, sizeof(u8));
5338 if (RT_SUCCESS(rc))
5339 {
5340 Assert(u8 <= 1);
5341 *pfBool = !!u8;
5342 }
5343 return rc;
5344}
5345
5346
5347/**
5348 * Loads a 8-bit unsigned integer item from the current data unit.
5349 *
5350 * @returns VBox status.
5351 * @param pSSM SSM operation handle.
5352 * @param pu8 Where to store the item.
5353 */
5354VMMR3DECL(int) SSMR3GetU8(PSSMHANDLE pSSM, uint8_t *pu8)
5355{
5356 SSM_ASSERT_READABLE_RET(pSSM);
5357 SSM_CHECK_CANCELLED_RET(pSSM);
5358 return ssmR3DataRead(pSSM, pu8, sizeof(*pu8));
5359}
5360
5361
5362/**
5363 * Loads a 8-bit signed integer item from the current data unit.
5364 *
5365 * @returns VBox status.
5366 * @param pSSM SSM operation handle.
5367 * @param pi8 Where to store the item.
5368 */
5369VMMR3DECL(int) SSMR3GetS8(PSSMHANDLE pSSM, int8_t *pi8)
5370{
5371 SSM_ASSERT_READABLE_RET(pSSM);
5372 SSM_CHECK_CANCELLED_RET(pSSM);
5373 return ssmR3DataRead(pSSM, pi8, sizeof(*pi8));
5374}
5375
5376
5377/**
5378 * Loads a 16-bit unsigned integer item from the current data unit.
5379 *
5380 * @returns VBox status.
5381 * @param pSSM SSM operation handle.
5382 * @param pu16 Where to store the item.
5383 */
5384VMMR3DECL(int) SSMR3GetU16(PSSMHANDLE pSSM, uint16_t *pu16)
5385{
5386 SSM_ASSERT_READABLE_RET(pSSM);
5387 SSM_CHECK_CANCELLED_RET(pSSM);
5388 return ssmR3DataRead(pSSM, pu16, sizeof(*pu16));
5389}
5390
5391
5392/**
5393 * Loads a 16-bit signed integer item from the current data unit.
5394 *
5395 * @returns VBox status.
5396 * @param pSSM SSM operation handle.
5397 * @param pi16 Where to store the item.
5398 */
5399VMMR3DECL(int) SSMR3GetS16(PSSMHANDLE pSSM, int16_t *pi16)
5400{
5401 SSM_ASSERT_READABLE_RET(pSSM);
5402 SSM_CHECK_CANCELLED_RET(pSSM);
5403 return ssmR3DataRead(pSSM, pi16, sizeof(*pi16));
5404}
5405
5406
5407/**
5408 * Loads a 32-bit unsigned integer item from the current data unit.
5409 *
5410 * @returns VBox status.
5411 * @param pSSM SSM operation handle.
5412 * @param pu32 Where to store the item.
5413 */
5414VMMR3DECL(int) SSMR3GetU32(PSSMHANDLE pSSM, uint32_t *pu32)
5415{
5416 SSM_ASSERT_READABLE_RET(pSSM);
5417 SSM_CHECK_CANCELLED_RET(pSSM);
5418 return ssmR3DataRead(pSSM, pu32, sizeof(*pu32));
5419}
5420
5421
5422/**
5423 * Loads a 32-bit signed integer item from the current data unit.
5424 *
5425 * @returns VBox status.
5426 * @param pSSM SSM operation handle.
5427 * @param pi32 Where to store the item.
5428 */
5429VMMR3DECL(int) SSMR3GetS32(PSSMHANDLE pSSM, int32_t *pi32)
5430{
5431 SSM_ASSERT_READABLE_RET(pSSM);
5432 SSM_CHECK_CANCELLED_RET(pSSM);
5433 return ssmR3DataRead(pSSM, pi32, sizeof(*pi32));
5434}
5435
5436
5437/**
5438 * Loads a 64-bit unsigned integer item from the current data unit.
5439 *
5440 * @returns VBox status.
5441 * @param pSSM SSM operation handle.
5442 * @param pu64 Where to store the item.
5443 */
5444VMMR3DECL(int) SSMR3GetU64(PSSMHANDLE pSSM, uint64_t *pu64)
5445{
5446 SSM_ASSERT_READABLE_RET(pSSM);
5447 SSM_CHECK_CANCELLED_RET(pSSM);
5448 return ssmR3DataRead(pSSM, pu64, sizeof(*pu64));
5449}
5450
5451
5452/**
5453 * Loads a 64-bit signed integer item from the current data unit.
5454 *
5455 * @returns VBox status.
5456 * @param pSSM SSM operation handle.
5457 * @param pi64 Where to store the item.
5458 */
5459VMMR3DECL(int) SSMR3GetS64(PSSMHANDLE pSSM, int64_t *pi64)
5460{
5461 SSM_ASSERT_READABLE_RET(pSSM);
5462 SSM_CHECK_CANCELLED_RET(pSSM);
5463 return ssmR3DataRead(pSSM, pi64, sizeof(*pi64));
5464}
5465
5466
5467/**
5468 * Loads a 128-bit unsigned integer item from the current data unit.
5469 *
5470 * @returns VBox status.
5471 * @param pSSM SSM operation handle.
5472 * @param pu128 Where to store the item.
5473 */
5474VMMR3DECL(int) SSMR3GetU128(PSSMHANDLE pSSM, uint128_t *pu128)
5475{
5476 SSM_ASSERT_READABLE_RET(pSSM);
5477 SSM_CHECK_CANCELLED_RET(pSSM);
5478 return ssmR3DataRead(pSSM, pu128, sizeof(*pu128));
5479}
5480
5481
5482/**
5483 * Loads a 128-bit signed integer item from the current data unit.
5484 *
5485 * @returns VBox status.
5486 * @param pSSM SSM operation handle.
5487 * @param pi128 Where to store the item.
5488 */
5489VMMR3DECL(int) SSMR3GetS128(PSSMHANDLE pSSM, int128_t *pi128)
5490{
5491 SSM_ASSERT_READABLE_RET(pSSM);
5492 SSM_CHECK_CANCELLED_RET(pSSM);
5493 return ssmR3DataRead(pSSM, pi128, sizeof(*pi128));
5494}
5495
5496
5497/**
5498 * Loads a VBox unsigned integer item from the current data unit.
5499 *
5500 * @returns VBox status.
5501 * @param pSSM SSM operation handle.
5502 * @param pu Where to store the integer.
5503 */
5504VMMR3DECL(int) SSMR3GetUInt(PSSMHANDLE pSSM, PRTUINT pu)
5505{
5506 SSM_ASSERT_READABLE_RET(pSSM);
5507 SSM_CHECK_CANCELLED_RET(pSSM);
5508 return ssmR3DataRead(pSSM, pu, sizeof(*pu));
5509}
5510
5511
5512/**
5513 * Loads a VBox signed integer item from the current data unit.
5514 *
5515 * @returns VBox status.
5516 * @param pSSM SSM operation handle.
5517 * @param pi Where to store the integer.
5518 */
5519VMMR3DECL(int) SSMR3GetSInt(PSSMHANDLE pSSM, PRTINT pi)
5520{
5521 SSM_ASSERT_READABLE_RET(pSSM);
5522 SSM_CHECK_CANCELLED_RET(pSSM);
5523 return ssmR3DataRead(pSSM, pi, sizeof(*pi));
5524}
5525
5526
5527/**
5528 * Loads a GC natural unsigned integer item from the current data unit.
5529 *
5530 * @returns VBox status.
5531 * @param pSSM SSM operation handle.
5532 * @param pu Where to store the integer.
5533 *
5534 * @deprecated Silly type with an incorrect size, don't use it.
5535 */
5536VMMR3DECL(int) SSMR3GetGCUInt(PSSMHANDLE pSSM, PRTGCUINT pu)
5537{
5538 AssertCompile(sizeof(RTGCPTR) == sizeof(*pu));
5539 return SSMR3GetGCPtr(pSSM, (PRTGCPTR)pu);
5540}
5541
5542
5543/**
5544 * Loads a GC unsigned integer register item from the current data unit.
5545 *
5546 * @returns VBox status.
5547 * @param pSSM SSM operation handle.
5548 * @param pu Where to store the integer.
5549 */
5550VMMR3DECL(int) SSMR3GetGCUIntReg(PSSMHANDLE pSSM, PRTGCUINTREG pu)
5551{
5552 AssertCompile(sizeof(RTGCPTR) == sizeof(*pu));
5553 return SSMR3GetGCPtr(pSSM, (PRTGCPTR)pu);
5554}
5555
5556
5557/**
5558 * Loads a 32 bits GC physical address item from the current data unit.
5559 *
5560 * @returns VBox status.
5561 * @param pSSM SSM operation handle.
5562 * @param pGCPhys Where to store the GC physical address.
5563 */
5564VMMR3DECL(int) SSMR3GetGCPhys32(PSSMHANDLE pSSM, PRTGCPHYS32 pGCPhys)
5565{
5566 SSM_ASSERT_READABLE_RET(pSSM);
5567 SSM_CHECK_CANCELLED_RET(pSSM);
5568 return ssmR3DataRead(pSSM, pGCPhys, sizeof(*pGCPhys));
5569}
5570
5571
5572/**
5573 * Loads a 64 bits GC physical address item from the current data unit.
5574 *
5575 * @returns VBox status.
5576 * @param pSSM SSM operation handle.
5577 * @param pGCPhys Where to store the GC physical address.
5578 */
5579VMMR3DECL(int) SSMR3GetGCPhys64(PSSMHANDLE pSSM, PRTGCPHYS64 pGCPhys)
5580{
5581 SSM_ASSERT_READABLE_RET(pSSM);
5582 SSM_CHECK_CANCELLED_RET(pSSM);
5583 return ssmR3DataRead(pSSM, pGCPhys, sizeof(*pGCPhys));
5584}
5585
5586
5587/**
5588 * Loads a GC physical address item from the current data unit.
5589 *
5590 * @returns VBox status.
5591 * @param pSSM SSM operation handle.
5592 * @param pGCPhys Where to store the GC physical address.
5593 */
5594VMMR3DECL(int) SSMR3GetGCPhys(PSSMHANDLE pSSM, PRTGCPHYS pGCPhys)
5595{
5596 SSM_ASSERT_READABLE_RET(pSSM);
5597 SSM_CHECK_CANCELLED_RET(pSSM);
5598
5599 /*
5600 * Default size?
5601 */
5602 if (RT_LIKELY(sizeof(*pGCPhys) == pSSM->u.Read.cbGCPhys))
5603 return ssmR3DataRead(pSSM, pGCPhys, sizeof(*pGCPhys));
5604
5605 /*
5606 * Fiddly.
5607 */
5608 Assert(sizeof(*pGCPhys) == sizeof(uint64_t) || sizeof(*pGCPhys) == sizeof(uint32_t));
5609 Assert(pSSM->u.Read.cbGCPhys == sizeof(uint64_t) || pSSM->u.Read.cbGCPhys == sizeof(uint32_t));
5610 if (pSSM->u.Read.cbGCPhys == sizeof(uint64_t))
5611 {
5612 /* 64-bit saved, 32-bit load: try truncate it. */
5613 uint64_t u64;
5614 int rc = ssmR3DataRead(pSSM, &u64, sizeof(uint64_t));
5615 if (RT_FAILURE(rc))
5616 return rc;
5617 if (u64 >= _4G)
5618 return VERR_SSM_GCPHYS_OVERFLOW;
5619 *pGCPhys = (RTGCPHYS)u64;
5620 return rc;
5621 }
5622
5623 /* 32-bit saved, 64-bit load: clear the high part. */
5624 *pGCPhys = 0;
5625 return ssmR3DataRead(pSSM, pGCPhys, sizeof(uint32_t));
5626}
5627
5628
5629/**
5630 * Loads a GC virtual address item from the current data unit.
5631 *
5632 * Only applies to in the 1.1 format:
5633 * - SSMR3GetGCPtr
5634 * - SSMR3GetGCUIntPtr
5635 * - SSMR3GetGCUInt
5636 * - SSMR3GetGCUIntReg
5637 *
5638 * Put functions are not affected.
5639 *
5640 * @returns VBox status.
5641 * @param pSSM SSM operation handle.
5642 * @param cbGCPtr Size of RTGCPTR
5643 *
5644 * @remarks This interface only works with saved state version 1.1, if the
5645 * format isn't 1.1 the call will be ignored.
5646 */
5647VMMR3_INT_DECL(int) SSMR3SetGCPtrSize(PSSMHANDLE pSSM, unsigned cbGCPtr)
5648{
5649 Assert(cbGCPtr == sizeof(RTGCPTR32) || cbGCPtr == sizeof(RTGCPTR64));
5650 if (!pSSM->u.Read.fFixedGCPtrSize)
5651 {
5652 Log(("SSMR3SetGCPtrSize: %u -> %u bytes\n", pSSM->u.Read.cbGCPtr, cbGCPtr));
5653 pSSM->u.Read.cbGCPtr = cbGCPtr;
5654 pSSM->u.Read.fFixedGCPtrSize = true;
5655 }
5656 else if ( pSSM->u.Read.cbGCPtr != cbGCPtr
5657 && pSSM->u.Read.uFmtVerMajor == 1
5658 && pSSM->u.Read.uFmtVerMinor == 1)
5659 AssertMsgFailed(("SSMR3SetGCPtrSize: already fixed at %u bytes; requested %u bytes\n", pSSM->u.Read.cbGCPtr, cbGCPtr));
5660
5661 return VINF_SUCCESS;
5662}
5663
5664
5665/**
5666 * Loads a GC virtual address item from the current data unit.
5667 *
5668 * @returns VBox status.
5669 * @param pSSM SSM operation handle.
5670 * @param pGCPtr Where to store the GC virtual address.
5671 */
5672VMMR3DECL(int) SSMR3GetGCPtr(PSSMHANDLE pSSM, PRTGCPTR pGCPtr)
5673{
5674 SSM_ASSERT_READABLE_RET(pSSM);
5675 SSM_CHECK_CANCELLED_RET(pSSM);
5676
5677 /*
5678 * Default size?
5679 */
5680 if (RT_LIKELY(sizeof(*pGCPtr) == pSSM->u.Read.cbGCPtr))
5681 return ssmR3DataRead(pSSM, pGCPtr, sizeof(*pGCPtr));
5682
5683 /*
5684 * Fiddly.
5685 */
5686 Assert(sizeof(*pGCPtr) == sizeof(uint64_t) || sizeof(*pGCPtr) == sizeof(uint32_t));
5687 Assert(pSSM->u.Read.cbGCPtr == sizeof(uint64_t) || pSSM->u.Read.cbGCPtr == sizeof(uint32_t));
5688 if (pSSM->u.Read.cbGCPtr == sizeof(uint64_t))
5689 {
5690 /* 64-bit saved, 32-bit load: try truncate it. */
5691 uint64_t u64;
5692 int rc = ssmR3DataRead(pSSM, &u64, sizeof(uint64_t));
5693 if (RT_FAILURE(rc))
5694 return rc;
5695 if (u64 >= _4G)
5696 return VERR_SSM_GCPTR_OVERFLOW;
5697 *pGCPtr = (RTGCPTR)u64;
5698 return rc;
5699 }
5700
5701 /* 32-bit saved, 64-bit load: clear the high part. */
5702 *pGCPtr = 0;
5703 return ssmR3DataRead(pSSM, pGCPtr, sizeof(uint32_t));
5704}
5705
5706
5707/**
5708 * Loads a GC virtual address (represented as unsigned integer) item from the current data unit.
5709 *
5710 * @returns VBox status.
5711 * @param pSSM SSM operation handle.
5712 * @param pGCPtr Where to store the GC virtual address.
5713 */
5714VMMR3DECL(int) SSMR3GetGCUIntPtr(PSSMHANDLE pSSM, PRTGCUINTPTR pGCPtr)
5715{
5716 AssertCompile(sizeof(RTGCPTR) == sizeof(*pGCPtr));
5717 return SSMR3GetGCPtr(pSSM, (PRTGCPTR)pGCPtr);
5718}
5719
5720
5721/**
5722 * Loads an RC virtual address item from the current data unit.
5723 *
5724 * @returns VBox status.
5725 * @param pSSM SSM operation handle.
5726 * @param pRCPtr Where to store the RC virtual address.
5727 */
5728VMMR3DECL(int) SSMR3GetRCPtr(PSSMHANDLE pSSM, PRTRCPTR pRCPtr)
5729{
5730 SSM_ASSERT_READABLE_RET(pSSM);
5731 SSM_CHECK_CANCELLED_RET(pSSM);
5732 return ssmR3DataRead(pSSM, pRCPtr, sizeof(*pRCPtr));
5733}
5734
5735
5736/**
5737 * Loads a I/O port address item from the current data unit.
5738 *
5739 * @returns VBox status.
5740 * @param pSSM SSM operation handle.
5741 * @param pIOPort Where to store the I/O port address.
5742 */
5743VMMR3DECL(int) SSMR3GetIOPort(PSSMHANDLE pSSM, PRTIOPORT pIOPort)
5744{
5745 SSM_ASSERT_READABLE_RET(pSSM);
5746 SSM_CHECK_CANCELLED_RET(pSSM);
5747 return ssmR3DataRead(pSSM, pIOPort, sizeof(*pIOPort));
5748}
5749
5750
5751/**
5752 * Loads a selector item from the current data unit.
5753 *
5754 * @returns VBox status.
5755 * @param pSSM SSM operation handle.
5756 * @param pSel Where to store the selector.
5757 */
5758VMMR3DECL(int) SSMR3GetSel(PSSMHANDLE pSSM, PRTSEL pSel)
5759{
5760 SSM_ASSERT_READABLE_RET(pSSM);
5761 SSM_CHECK_CANCELLED_RET(pSSM);
5762 return ssmR3DataRead(pSSM, pSel, sizeof(*pSel));
5763}
5764
5765
5766/**
5767 * Loads a memory item from the current data unit.
5768 *
5769 * @returns VBox status.
5770 * @param pSSM SSM operation handle.
5771 * @param pv Where to store the item.
5772 * @param cb Size of the item.
5773 */
5774VMMR3DECL(int) SSMR3GetMem(PSSMHANDLE pSSM, void *pv, size_t cb)
5775{
5776 SSM_ASSERT_READABLE_RET(pSSM);
5777 SSM_CHECK_CANCELLED_RET(pSSM);
5778 return ssmR3DataRead(pSSM, pv, cb);
5779}
5780
5781
5782/**
5783 * Loads a string item from the current data unit.
5784 *
5785 * @returns VBox status.
5786 * @param pSSM SSM operation handle.
5787 * @param psz Where to store the item.
5788 * @param cbMax Max size of the item (including '\\0').
5789 */
5790VMMR3DECL(int) SSMR3GetStrZ(PSSMHANDLE pSSM, char *psz, size_t cbMax)
5791{
5792 return SSMR3GetStrZEx(pSSM, psz, cbMax, NULL);
5793}
5794
5795
5796/**
5797 * Loads a string item from the current data unit.
5798 *
5799 * @returns VBox status.
5800 * @param pSSM SSM operation handle.
5801 * @param psz Where to store the item.
5802 * @param cbMax Max size of the item (including '\\0').
5803 * @param pcbStr The length of the loaded string excluding the '\\0'. (optional)
5804 */
5805VMMR3DECL(int) SSMR3GetStrZEx(PSSMHANDLE pSSM, char *psz, size_t cbMax, size_t *pcbStr)
5806{
5807 SSM_ASSERT_READABLE_RET(pSSM);
5808 SSM_CHECK_CANCELLED_RET(pSSM);
5809
5810 /* read size prefix. */
5811 uint32_t u32;
5812 int rc = SSMR3GetU32(pSSM, &u32);
5813 if (RT_SUCCESS(rc))
5814 {
5815 if (pcbStr)
5816 *pcbStr = u32;
5817 if (u32 < cbMax)
5818 {
5819 /* terminate and read string content. */
5820 psz[u32] = '\0';
5821 return ssmR3DataRead(pSSM, psz, u32);
5822 }
5823 return VERR_TOO_MUCH_DATA;
5824 }
5825 return rc;
5826}
5827
5828
5829/**
5830 * Skips a number of bytes in the current data unit.
5831 *
5832 * @returns VBox status code.
5833 * @param pSSM The SSM handle.
5834 * @param cb The number of bytes to skip.
5835 */
5836VMMR3DECL(int) SSMR3Skip(PSSMHANDLE pSSM, size_t cb)
5837{
5838 SSM_ASSERT_READABLE_RET(pSSM);
5839 SSM_CHECK_CANCELLED_RET(pSSM);
5840 while (cb > 0)
5841 {
5842 uint8_t abBuf[8192];
5843 size_t cbCur = RT_MIN(sizeof(abBuf), cb);
5844 cb -= cbCur;
5845 int rc = ssmR3DataRead(pSSM, abBuf, cbCur);
5846 if (RT_FAILURE(rc))
5847 return rc;
5848 }
5849
5850 return VINF_SUCCESS;
5851}
5852
5853
5854/**
5855 * Skips to the end of the current data unit.
5856 *
5857 * Since version 2 of the format, the load exec callback have to explicitly call
5858 * this API if it wish to be lazy for some reason. This is because there seldom
5859 * is a good reason to not read your entire data unit and it was hiding bugs.
5860 *
5861 * @returns VBox status code.
5862 * @param pSSM The saved state handle.
5863 */
5864VMMR3DECL(int) SSMR3SkipToEndOfUnit(PSSMHANDLE pSSM)
5865{
5866 SSM_ASSERT_READABLE_RET(pSSM);
5867 SSM_CHECK_CANCELLED_RET(pSSM);
5868 if (pSSM->u.Read.uFmtVerMajor >= 2)
5869 {
5870 /*
5871 * Read until we the end of data condition is raised.
5872 */
5873 pSSM->u.Read.cbDataBuffer = 0;
5874 pSSM->u.Read.offDataBuffer = 0;
5875 if (!pSSM->u.Read.fEndOfData)
5876 {
5877 do
5878 {
5879 /* read the rest of the current record */
5880 while (pSSM->u.Read.cbRecLeft)
5881 {
5882 uint8_t abBuf[8192];
5883 size_t cbToRead = RT_MIN(pSSM->u.Read.cbRecLeft, sizeof(abBuf));
5884 int rc = ssmR3DataReadV2Raw(pSSM, abBuf, cbToRead);
5885 if (RT_FAILURE(rc))
5886 return pSSM->rc = rc;
5887 pSSM->u.Read.cbRecLeft -= cbToRead;
5888 }
5889
5890 /* read the next header. */
5891 int rc = ssmR3DataReadRecHdrV2(pSSM);
5892 if (RT_FAILURE(rc))
5893 return pSSM->rc = rc;
5894 } while (!pSSM->u.Read.fEndOfData);
5895 }
5896 }
5897 /* else: Doesn't matter for the version 1 loading. */
5898
5899 return VINF_SUCCESS;
5900}
5901
5902
5903/**
5904 * Calculate the checksum of a file portion.
5905 *
5906 * @returns VBox status.
5907 * @param pStrm The stream handle
5908 * @param off Where to start checksumming.
5909 * @param cb How much to checksum.
5910 * @param pu32CRC Where to store the calculated checksum.
5911 */
5912static int ssmR3CalcChecksum(PSSMSTRM pStrm, uint64_t off, uint64_t cb, uint32_t *pu32CRC)
5913{
5914 /*
5915 * Allocate a buffer.
5916 */
5917 const size_t cbBuf = _32K;
5918 void *pvBuf = RTMemTmpAlloc(cbBuf);
5919 if (!pvBuf)
5920 return VERR_NO_TMP_MEMORY;
5921
5922 /*
5923 * Loop reading and calculating CRC32.
5924 */
5925 int rc = VINF_SUCCESS;
5926 uint32_t u32CRC = RTCrc32Start();
5927 while (cb > 0)
5928 {
5929 /* read chunk */
5930 size_t cbToRead = cbBuf;
5931 if (cb < cbBuf)
5932 cbToRead = cb;
5933 rc = ssmR3StrmPeekAt(pStrm, off, pvBuf, cbToRead, NULL);
5934 if (RT_FAILURE(rc))
5935 {
5936 AssertMsgFailed(("Failed with rc=%Rrc while calculating crc.\n", rc));
5937 RTMemTmpFree(pvBuf);
5938 return rc;
5939 }
5940
5941 /* advance */
5942 cb -= cbToRead;
5943 off += cbToRead;
5944
5945 /* calc crc32. */
5946 u32CRC = RTCrc32Process(u32CRC, pvBuf, cbToRead);
5947 }
5948 RTMemTmpFree(pvBuf);
5949
5950 /* store the calculated crc */
5951 u32CRC = RTCrc32Finish(u32CRC);
5952 Log(("SSM: u32CRC=0x%08x\n", u32CRC));
5953 *pu32CRC = u32CRC;
5954
5955 return VINF_SUCCESS;
5956}
5957
5958
5959/**
5960 * Validates the header information stored in the handle.
5961 *
5962 * @returns VBox status code.
5963 *
5964 * @param pSSM The handle.
5965 * @param fHaveHostBits Set if the host bits field is valid.
5966 * @param fHaveVersion Set if we have a version.
5967 */
5968static int ssmR3ValidateHeaderInfo(PSSMHANDLE pSSM, bool fHaveHostBits, bool fHaveVersion)
5969{
5970 Assert(pSSM->u.Read.cbFileHdr < 256 && pSSM->u.Read.cbFileHdr > 32);
5971 Assert(pSSM->u.Read.uFmtVerMajor == 1 || pSSM->u.Read.uFmtVerMajor == 2);
5972 Assert(pSSM->u.Read.uFmtVerMinor <= 2);
5973
5974 if (fHaveVersion)
5975 {
5976 if ( pSSM->u.Read.u16VerMajor == 0
5977 || pSSM->u.Read.u16VerMajor > 1000
5978 || pSSM->u.Read.u16VerMinor > 1000
5979 || pSSM->u.Read.u32VerBuild > _1M
5980 || pSSM->u.Read.u32SvnRev == 0
5981 || pSSM->u.Read.u32SvnRev > 10000000 /*100M*/)
5982 {
5983 LogRel(("SSM: Incorrect version values: %u.%u.%u.r%u\n",
5984 pSSM->u.Read.u16VerMajor, pSSM->u.Read.u16VerMinor, pSSM->u.Read.u32VerBuild, pSSM->u.Read.u32SvnRev));
5985 return VERR_SSM_INTEGRITY_VBOX_VERSION;
5986 }
5987 }
5988 else
5989 AssertLogRelReturn( pSSM->u.Read.u16VerMajor == 0
5990 && pSSM->u.Read.u16VerMinor == 0
5991 && pSSM->u.Read.u32VerBuild == 0
5992 && pSSM->u.Read.u32SvnRev == 0,
5993 VERR_SSM_INTEGRITY_VBOX_VERSION);
5994
5995 if (fHaveHostBits)
5996 {
5997 if ( pSSM->u.Read.cHostBits != 32
5998 && pSSM->u.Read.cHostBits != 64)
5999 {
6000 LogRel(("SSM: Incorrect cHostBits value: %u\n", pSSM->u.Read.cHostBits));
6001 return VERR_SSM_INTEGRITY_HEADER;
6002 }
6003 }
6004 else
6005 AssertLogRelReturn(pSSM->u.Read.cHostBits == 0, VERR_SSM_INTEGRITY_HEADER);
6006
6007 if ( pSSM->u.Read.cbGCPhys != sizeof(uint32_t)
6008 && pSSM->u.Read.cbGCPhys != sizeof(uint64_t))
6009 {
6010 LogRel(("SSM: Incorrect cbGCPhys value: %d\n", pSSM->u.Read.cbGCPhys));
6011 return VERR_SSM_INTEGRITY_HEADER;
6012 }
6013 if ( pSSM->u.Read.cbGCPtr != sizeof(uint32_t)
6014 && pSSM->u.Read.cbGCPtr != sizeof(uint64_t))
6015 {
6016 LogRel(("SSM: Incorrect cbGCPtr value: %d\n", pSSM->u.Read.cbGCPtr));
6017 return VERR_SSM_INTEGRITY_HEADER;
6018 }
6019
6020 return VINF_SUCCESS;
6021}
6022
6023
6024/**
6025 * Reads the header, detects the format version and performs integrity
6026 * validations.
6027 *
6028 * @returns VBox status.
6029 * @param File File to validate.
6030 * The file position is undefined on return.
6031 * @param fChecksumIt Whether to checksum the file or not. This will
6032 * be ignored if it the stream isn't a file.
6033 * @param fChecksumOnRead Whether to validate the checksum while reading
6034 * the stream instead of up front. If not possible,
6035 * verify the checksum up front.
6036 * @param pHdr Where to store the file header.
6037 */
6038static int ssmR3HeaderAndValidate(PSSMHANDLE pSSM, bool fChecksumIt, bool fChecksumOnRead)
6039{
6040 /*
6041 * Read and check the header magic.
6042 */
6043 union
6044 {
6045 SSMFILEHDR v2_0;
6046 SSMFILEHDRV12 v1_2;
6047 SSMFILEHDRV11 v1_1;
6048 } uHdr;
6049 int rc = ssmR3StrmRead(&pSSM->Strm, &uHdr, sizeof(uHdr.v2_0.szMagic));
6050 if (RT_FAILURE(rc))
6051 {
6052 LogRel(("SSM: Failed to read file magic header. rc=%Rrc\n", rc));
6053 return rc;
6054 }
6055 if (memcmp(uHdr.v2_0.szMagic, SSMFILEHDR_MAGIC_BASE, sizeof(SSMFILEHDR_MAGIC_BASE) - 1))
6056 {
6057 Log(("SSM: Not a saved state file. magic=%.*s\n", sizeof(uHdr.v2_0.szMagic) - 1, uHdr.v2_0.szMagic));
6058 return VERR_SSM_INTEGRITY_MAGIC;
6059 }
6060
6061 /*
6062 * Find the header size and read the rest.
6063 */
6064 static const struct
6065 {
6066 char szMagic[sizeof(SSMFILEHDR_MAGIC_V2_0)];
6067 size_t cbHdr;
6068 unsigned uFmtVerMajor;
6069 unsigned uFmtVerMinor;
6070 } s_aVers[] =
6071 {
6072 { SSMFILEHDR_MAGIC_V2_0, sizeof(SSMFILEHDR), 2, 0 },
6073 { SSMFILEHDR_MAGIC_V1_2, sizeof(SSMFILEHDRV12), 1, 2 },
6074 { SSMFILEHDR_MAGIC_V1_1, sizeof(SSMFILEHDRV11), 1, 1 },
6075 };
6076 int iVer = RT_ELEMENTS(s_aVers);
6077 while (iVer-- > 0)
6078 if (!memcmp(uHdr.v2_0.szMagic, s_aVers[iVer].szMagic, sizeof(uHdr.v2_0.szMagic)))
6079 break;
6080 if (iVer < 0)
6081 {
6082 Log(("SSM: Unknown file format version. magic=%.*s\n", sizeof(uHdr.v2_0.szMagic) - 1, uHdr.v2_0.szMagic));
6083 return VERR_SSM_INTEGRITY_VERSION;
6084 }
6085 pSSM->u.Read.uFmtVerMajor = s_aVers[iVer].uFmtVerMajor;
6086 pSSM->u.Read.uFmtVerMinor = s_aVers[iVer].uFmtVerMinor;
6087 pSSM->u.Read.cbFileHdr = s_aVers[iVer].cbHdr;
6088
6089 rc = ssmR3StrmRead(&pSSM->Strm, (uint8_t *)&uHdr + sizeof(uHdr.v2_0.szMagic), pSSM->u.Read.cbFileHdr - sizeof(uHdr.v2_0.szMagic));
6090 if (RT_FAILURE(rc))
6091 {
6092 LogRel(("SSM: Failed to read the file header. rc=%Rrc\n", rc));
6093 return rc;
6094 }
6095
6096 /*
6097 * Make version specific adjustments.
6098 */
6099 if (pSSM->u.Read.uFmtVerMajor >= 2)
6100 {
6101 /*
6102 * Version 2.0 and later.
6103 */
6104 bool fChecksummed;
6105 if (pSSM->u.Read.uFmtVerMinor == 0)
6106 {
6107 /* validate the header. */
6108 SSM_CHECK_CRC32_RET(&uHdr.v2_0, sizeof(uHdr.v2_0), ("Header CRC mismatch: %08x, correct is %08x\n", u32CRC, u32ActualCRC));
6109 if (uHdr.v2_0.u8Reserved)
6110 {
6111 LogRel(("SSM: Reserved header field isn't zero: %02x\n", uHdr.v2_0.u8Reserved));
6112 return VERR_SSM_INTEGRITY;
6113 }
6114 if ((uHdr.v2_0.fFlags & ~SSMFILEHDR_FLAGS_STREAM_CRC32))
6115 {
6116 LogRel(("SSM: Unknown header flags: %08x\n", uHdr.v2_0.fFlags));
6117 return VERR_SSM_INTEGRITY;
6118 }
6119 if ( uHdr.v2_0.cbMaxDecompr > sizeof(pSSM->u.Read.abDataBuffer)
6120 || uHdr.v2_0.cbMaxDecompr < _1K
6121 || (uHdr.v2_0.cbMaxDecompr & 0xff) != 0)
6122 {
6123 LogRel(("SSM: The cbMaxDecompr header field is out of range: %#x\n", uHdr.v2_0.cbMaxDecompr));
6124 return VERR_SSM_INTEGRITY;
6125 }
6126
6127 /* set the header info. */
6128 pSSM->u.Read.cHostBits = uHdr.v2_0.cHostBits;
6129 pSSM->u.Read.u16VerMajor = uHdr.v2_0.u16VerMajor;
6130 pSSM->u.Read.u16VerMinor = uHdr.v2_0.u16VerMinor;
6131 pSSM->u.Read.u32VerBuild = uHdr.v2_0.u32VerBuild;
6132 pSSM->u.Read.u32SvnRev = uHdr.v2_0.u32SvnRev;
6133 pSSM->u.Read.cbGCPhys = uHdr.v2_0.cbGCPhys;
6134 pSSM->u.Read.cbGCPtr = uHdr.v2_0.cbGCPtr;
6135 pSSM->u.Read.fFixedGCPtrSize = true;
6136 fChecksummed = !!(uHdr.v2_0.fFlags & SSMFILEHDR_FLAGS_STREAM_CRC32);
6137 }
6138 else
6139 AssertFailedReturn(VERR_INTERNAL_ERROR);
6140 if (!fChecksummed)
6141 ssmR3StrmDisableChecksumming(&pSSM->Strm);
6142
6143 /*
6144 * Read and validate the footer if it's a file.
6145 */
6146 if (ssmR3StrmIsFile(&pSSM->Strm))
6147 {
6148 SSMFILEFTR Footer;
6149 uint64_t offFooter;
6150 rc = ssmR3StrmPeekAt(&pSSM->Strm, -(RTFOFF)sizeof(SSMFILEFTR), &Footer, sizeof(Footer), &offFooter);
6151 AssertLogRelRCReturn(rc, rc);
6152 if (memcmp(Footer.szMagic, SSMFILEFTR_MAGIC, sizeof(Footer.szMagic)))
6153 {
6154 LogRel(("SSM: Bad footer magic: %.*Rhxs\n", sizeof(Footer.szMagic), &Footer.szMagic[0]));
6155 return VERR_SSM_INTEGRITY_FOOTER;
6156 }
6157 SSM_CHECK_CRC32_RET(&Footer, sizeof(Footer), ("Footer CRC mismatch: %08x, correct is %08x\n", u32CRC, u32ActualCRC));
6158 if (Footer.offStream != offFooter)
6159 {
6160 LogRel(("SSM: SSMFILEFTR::offStream is wrong: %llx, expected %llx\n", Footer.offStream, offFooter));
6161 return VERR_SSM_INTEGRITY_FOOTER;
6162 }
6163 if (Footer.u32Reserved)
6164 {
6165 LogRel(("SSM: Reserved footer field isn't zero: %08x\n", Footer.u32Reserved));
6166 return VERR_SSM_INTEGRITY_FOOTER;
6167 }
6168 if ( !fChecksummed
6169 && Footer.u32StreamCRC)
6170 {
6171 LogRel(("SSM: u32StreamCRC field isn't zero, but header says stream checksumming is disabled.\n"));
6172 return VERR_SSM_INTEGRITY_FOOTER;
6173 }
6174
6175 pSSM->u.Read.cbLoadFile = offFooter + sizeof(Footer);
6176 pSSM->u.Read.u32LoadCRC = Footer.u32StreamCRC;
6177 }
6178 else
6179 {
6180 pSSM->u.Read.cbLoadFile = UINT64_MAX;
6181 pSSM->u.Read.u32LoadCRC = 0;
6182 }
6183
6184 /*
6185 * Validate the header info we've set in the handle.
6186 */
6187 rc = ssmR3ValidateHeaderInfo(pSSM, true /*fHaveHostBits*/, true /*fHaveVersion*/);
6188 if (RT_FAILURE(rc))
6189 return rc;
6190
6191 /*
6192 * Check the checksum if that's called for and possible.
6193 */
6194 if ( fChecksummed
6195 && fChecksumIt
6196 && !fChecksumOnRead
6197 && ssmR3StrmIsFile(&pSSM->Strm))
6198 {
6199 uint32_t u32CRC;
6200 rc = ssmR3CalcChecksum(&pSSM->Strm, 0, pSSM->u.Read.cbLoadFile - sizeof(SSMFILEFTR), &u32CRC);
6201 if (RT_FAILURE(rc))
6202 return rc;
6203 if (u32CRC != pSSM->u.Read.u32LoadCRC)
6204 {
6205 LogRel(("SSM: Invalid CRC! Calculated %#010x, in footer %#010x\n", u32CRC, pSSM->u.Read.u32LoadCRC));
6206 return VERR_SSM_INTEGRITY_CRC;
6207 }
6208 }
6209 }
6210 else
6211 {
6212 /*
6213 * Version 1.x of the format.
6214 */
6215 bool fHaveHostBits = true;
6216 bool fHaveVersion = false;
6217 RTUUID MachineUuidFromHdr;
6218
6219 ssmR3StrmDisableChecksumming(&pSSM->Strm);
6220 if (pSSM->u.Read.uFmtVerMinor == 1)
6221 {
6222 pSSM->u.Read.cHostBits = 0; /* unknown */
6223 pSSM->u.Read.u16VerMajor = 0;
6224 pSSM->u.Read.u16VerMinor = 0;
6225 pSSM->u.Read.u32VerBuild = 0;
6226 pSSM->u.Read.u32SvnRev = 0;
6227 pSSM->u.Read.cbLoadFile = uHdr.v1_1.cbFile;
6228 pSSM->u.Read.u32LoadCRC = uHdr.v1_1.u32CRC;
6229 pSSM->u.Read.cbGCPhys = sizeof(RTGCPHYS);
6230 pSSM->u.Read.cbGCPtr = sizeof(RTGCPTR);
6231 pSSM->u.Read.fFixedGCPtrSize = false; /* settable */
6232
6233 MachineUuidFromHdr = uHdr.v1_1.MachineUuid;
6234 fHaveHostBits = false;
6235 }
6236 else if (pSSM->u.Read.uFmtVerMinor == 2)
6237 {
6238 pSSM->u.Read.cHostBits = uHdr.v1_2.cHostBits;
6239 pSSM->u.Read.u16VerMajor = uHdr.v1_2.u16VerMajor;
6240 pSSM->u.Read.u16VerMinor = uHdr.v1_2.u16VerMinor;
6241 pSSM->u.Read.u32VerBuild = uHdr.v1_2.u32VerBuild;
6242 pSSM->u.Read.u32SvnRev = uHdr.v1_2.u32SvnRev;
6243 pSSM->u.Read.cbLoadFile = uHdr.v1_2.cbFile;
6244 pSSM->u.Read.u32LoadCRC = uHdr.v1_2.u32CRC;
6245 pSSM->u.Read.cbGCPhys = uHdr.v1_2.cbGCPhys;
6246 pSSM->u.Read.cbGCPtr = uHdr.v1_2.cbGCPtr;
6247 pSSM->u.Read.fFixedGCPtrSize = true;
6248
6249 MachineUuidFromHdr = uHdr.v1_2.MachineUuid;
6250 fHaveVersion = true;
6251 }
6252 else
6253 AssertFailedReturn(VERR_INTERNAL_ERROR);
6254
6255 /*
6256 * The MachineUuid must be NULL (was never used).
6257 */
6258 if (!RTUuidIsNull(&MachineUuidFromHdr))
6259 {
6260 LogRel(("SSM: The UUID of the saved state doesn't match the running VM.\n"));
6261 return VERR_SMM_INTEGRITY_MACHINE;
6262 }
6263
6264 /*
6265 * Verify the file size.
6266 */
6267 uint64_t cbFile = ssmR3StrmGetSize(&pSSM->Strm);
6268 if (cbFile != pSSM->u.Read.cbLoadFile)
6269 {
6270 LogRel(("SSM: File size mismatch. hdr.cbFile=%lld actual %lld\n", pSSM->u.Read.cbLoadFile, cbFile));
6271 return VERR_SSM_INTEGRITY_SIZE;
6272 }
6273
6274 /*
6275 * Validate the header info we've set in the handle.
6276 */
6277 rc = ssmR3ValidateHeaderInfo(pSSM, fHaveHostBits, fHaveVersion);
6278 if (RT_FAILURE(rc))
6279 return rc;
6280
6281 /*
6282 * Verify the checksum if requested.
6283 *
6284 * Note! The checksum is not actually generated for the whole file,
6285 * this is of course a bug in the v1.x code that we cannot do
6286 * anything about.
6287 */
6288 if ( fChecksumIt
6289 || fChecksumOnRead)
6290 {
6291 uint32_t u32CRC;
6292 rc = ssmR3CalcChecksum(&pSSM->Strm,
6293 RT_OFFSETOF(SSMFILEHDRV11, u32CRC) + sizeof(uHdr.v1_1.u32CRC),
6294 cbFile - pSSM->u.Read.cbFileHdr,
6295 &u32CRC);
6296 if (RT_FAILURE(rc))
6297 return rc;
6298 if (u32CRC != pSSM->u.Read.u32LoadCRC)
6299 {
6300 LogRel(("SSM: Invalid CRC! Calculated %#010x, in header %#010x\n", u32CRC, pSSM->u.Read.u32LoadCRC));
6301 return VERR_SSM_INTEGRITY_CRC;
6302 }
6303 }
6304 }
6305
6306 return VINF_SUCCESS;
6307}
6308
6309
6310/**
6311 * Open a saved state for reading.
6312 *
6313 * The file will be positioned at the first data unit upon successful return.
6314 *
6315 * @returns VBox status code.
6316 *
6317 * @param pVM The VM handle.
6318 * @param pszFilename The filename.
6319 * @param fChecksumIt Check the checksum for the entire file.
6320 * @param fChecksumOnRead Whether to validate the checksum while reading
6321 * the stream instead of up front. If not possible,
6322 * verify the checksum up front.
6323 * @param pSSM Pointer to the handle structure. This will be
6324 * completely initialized on success.
6325 * @param cBuffers The number of stream buffers.
6326 */
6327static int ssmR3OpenFile(PVM pVM, const char *pszFilename, bool fChecksumIt, bool fChecksumOnRead,
6328 uint32_t cBuffers, PSSMHANDLE pSSM)
6329{
6330 /*
6331 * Initialize the handle.
6332 */
6333 pSSM->pVM = pVM;
6334 pSSM->enmOp = SSMSTATE_INVALID;
6335 pSSM->enmAfter = SSMAFTER_INVALID;
6336 pSSM->fCancelled = SSMHANDLE_OK;
6337 pSSM->rc = VINF_SUCCESS;
6338 pSSM->cbUnitLeftV1 = 0;
6339 pSSM->offUnit = UINT64_MAX;
6340 pSSM->pfnProgress = NULL;
6341 pSSM->pvUser = NULL;
6342 pSSM->uPercent = 0;
6343 pSSM->offEstProgress = 0;
6344 pSSM->cbEstTotal = 0;
6345 pSSM->offEst = 0;
6346 pSSM->offEstUnitEnd = 0;
6347 pSSM->uPercentPrepare = 5;
6348 pSSM->uPercentDone = 2;
6349 pSSM->pszFilename = pszFilename;
6350
6351 pSSM->u.Read.pZipDecompV1 = NULL;
6352 pSSM->u.Read.uFmtVerMajor = UINT32_MAX;
6353 pSSM->u.Read.uFmtVerMinor = UINT32_MAX;
6354 pSSM->u.Read.cbFileHdr = UINT32_MAX;
6355 pSSM->u.Read.cbGCPhys = UINT8_MAX;
6356 pSSM->u.Read.cbGCPtr = UINT8_MAX;
6357 pSSM->u.Read.fFixedGCPtrSize= false;
6358 pSSM->u.Read.u16VerMajor = UINT16_MAX;
6359 pSSM->u.Read.u16VerMinor = UINT16_MAX;
6360 pSSM->u.Read.u32VerBuild = UINT32_MAX;
6361 pSSM->u.Read.u32SvnRev = UINT32_MAX;
6362 pSSM->u.Read.cHostBits = UINT8_MAX;
6363 pSSM->u.Read.cbLoadFile = UINT64_MAX;
6364
6365 pSSM->u.Read.cbRecLeft = 0;
6366 pSSM->u.Read.cbDataBuffer = 0;
6367 pSSM->u.Read.offDataBuffer = 0;
6368 pSSM->u.Read.fEndOfData = 0;
6369 pSSM->u.Read.u8TypeAndFlags = 0;
6370
6371 /*
6372 * Try open and validate the file.
6373 */
6374 int rc = ssmR3StrmOpenFile(&pSSM->Strm, pszFilename, false /*fWrite*/, fChecksumOnRead, cBuffers);
6375 if (RT_SUCCESS(rc))
6376 {
6377 rc = ssmR3HeaderAndValidate(pSSM, fChecksumIt, fChecksumOnRead);
6378 if (RT_SUCCESS(rc))
6379 return rc;
6380
6381 /* failure path */
6382 ssmR3StrmClose(&pSSM->Strm);
6383 }
6384 else
6385 Log(("SSM: Failed to open save state file '%s', rc=%Rrc.\n", pszFilename, rc));
6386 return rc;
6387}
6388
6389
6390/**
6391 * Find a data unit by name.
6392 *
6393 * @returns Pointer to the unit.
6394 * @returns NULL if not found.
6395 *
6396 * @param pVM VM handle.
6397 * @param pszName Data unit name.
6398 * @param uInstance The data unit instance id.
6399 */
6400static PSSMUNIT ssmR3Find(PVM pVM, const char *pszName, uint32_t uInstance)
6401{
6402 size_t cchName = strlen(pszName);
6403 PSSMUNIT pUnit = pVM->ssm.s.pHead;
6404 while ( pUnit
6405 && ( pUnit->u32Instance != uInstance
6406 || pUnit->cchName != cchName
6407 || memcmp(pUnit->szName, pszName, cchName)))
6408 pUnit = pUnit->pNext;
6409 return pUnit;
6410}
6411
6412
6413/**
6414 * Executes the loading of a V1.X file.
6415 *
6416 * @returns VBox status code.
6417 * @param pVM The VM handle.
6418 * @param pSSM The saved state handle.
6419 */
6420static int ssmR3LoadExecV1(PVM pVM, PSSMHANDLE pSSM)
6421{
6422 int rc;
6423 char *pszName = NULL;
6424 size_t cchName = 0;
6425 pSSM->enmOp = SSMSTATE_LOAD_EXEC;
6426 for (;;)
6427 {
6428 /*
6429 * Save the current file position and read the data unit header.
6430 */
6431 uint64_t offUnit = ssmR3StrmTell(&pSSM->Strm);
6432 SSMFILEUNITHDRV1 UnitHdr;
6433 rc = ssmR3StrmRead(&pSSM->Strm, &UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV1, szName));
6434 if (RT_SUCCESS(rc))
6435 {
6436 /*
6437 * Check the magic and see if it's valid and whether it is a end header or not.
6438 */
6439 if (memcmp(&UnitHdr.achMagic[0], SSMFILEUNITHDR_MAGIC, sizeof(SSMFILEUNITHDR_MAGIC)))
6440 {
6441 if (!memcmp(&UnitHdr.achMagic[0], SSMFILEUNITHDR_END, sizeof(SSMFILEUNITHDR_END)))
6442 {
6443 Log(("SSM: EndOfFile: offset %#9llx size %9d\n", offUnit, UnitHdr.cbUnit));
6444 /* Complete the progress bar (pending 99% afterwards). */
6445 ssmR3Progress(pSSM, pSSM->cbEstTotal - pSSM->offEst);
6446 break;
6447 }
6448 LogRel(("SSM: Invalid unit magic at offset %#llx (%lld), '%.*s'!\n",
6449 offUnit, offUnit, sizeof(UnitHdr.achMagic) - 1, &UnitHdr.achMagic[0]));
6450 rc = VERR_SSM_INTEGRITY_UNIT_MAGIC;
6451 break;
6452 }
6453
6454 /*
6455 * Read the name.
6456 * Adjust the name buffer first.
6457 */
6458 if (cchName < UnitHdr.cchName)
6459 {
6460 if (pszName)
6461 RTMemTmpFree(pszName);
6462 cchName = RT_ALIGN_Z(UnitHdr.cchName, 64);
6463 pszName = (char *)RTMemTmpAlloc(cchName);
6464 }
6465 if (pszName)
6466 {
6467 rc = ssmR3StrmRead(&pSSM->Strm, pszName, UnitHdr.cchName);
6468 if (RT_SUCCESS(rc))
6469 {
6470 if (pszName[UnitHdr.cchName - 1])
6471 {
6472 LogRel(("SSM: Unit name '%.*s' was not properly terminated.\n", UnitHdr.cchName, pszName));
6473 rc = VERR_SSM_INTEGRITY_UNIT;
6474 break;
6475 }
6476 Log(("SSM: Data unit: offset %#9llx size %9lld '%s'\n", offUnit, UnitHdr.cbUnit, pszName));
6477
6478 /*
6479 * Find the data unit in our internal table.
6480 */
6481 PSSMUNIT pUnit = ssmR3Find(pVM, pszName, UnitHdr.u32Instance);
6482 if (pUnit)
6483 {
6484 /*
6485 * Call the execute handler.
6486 */
6487 pSSM->cbUnitLeftV1 = UnitHdr.cbUnit - RT_OFFSETOF(SSMFILEUNITHDRV1, szName[UnitHdr.cchName]);
6488 pSSM->offUnit = 0;
6489 if (!pUnit->u.Common.pfnLoadExec)
6490 {
6491 LogRel(("SSM: No load exec callback for unit '%s'!\n", pszName));
6492 pSSM->rc = rc = VERR_SSM_NO_LOAD_EXEC;
6493 break;
6494 }
6495 switch (pUnit->enmType)
6496 {
6497 case SSMUNITTYPE_DEV:
6498 rc = pUnit->u.Dev.pfnLoadExec(pUnit->u.Dev.pDevIns, pSSM, UnitHdr.u32Version, SSM_PASS_FINAL);
6499 break;
6500 case SSMUNITTYPE_DRV:
6501 rc = pUnit->u.Drv.pfnLoadExec(pUnit->u.Drv.pDrvIns, pSSM, UnitHdr.u32Version, SSM_PASS_FINAL);
6502 break;
6503 case SSMUNITTYPE_INTERNAL:
6504 rc = pUnit->u.Internal.pfnLoadExec(pVM, pSSM, UnitHdr.u32Version, SSM_PASS_FINAL);
6505 break;
6506 case SSMUNITTYPE_EXTERNAL:
6507 rc = pUnit->u.External.pfnLoadExec(pSSM, pUnit->u.External.pvUser, UnitHdr.u32Version, SSM_PASS_FINAL);
6508 break;
6509 default:
6510 rc = VERR_INTERNAL_ERROR;
6511 break;
6512 }
6513 pUnit->fCalled = true;
6514 if (RT_FAILURE(rc) && RT_SUCCESS_NP(pSSM->rc))
6515 pSSM->rc = rc;
6516
6517 /*
6518 * Close the reader stream.
6519 */
6520 rc = ssmR3DataReadFinishV1(pSSM);
6521 if (RT_SUCCESS(rc))
6522 {
6523 /*
6524 * Now, we'll check the current position to see if all, or
6525 * more than all, the data was read.
6526 *
6527 * Note! Because of buffering / compression we'll only see the
6528 * really bad ones here.
6529 */
6530 uint64_t off = ssmR3StrmTell(&pSSM->Strm);
6531 int64_t i64Diff = off - (offUnit + UnitHdr.cbUnit);
6532 if (i64Diff < 0)
6533 {
6534 Log(("SSM: Unit '%s' left %lld bytes unread!\n", pszName, -i64Diff));
6535 rc = ssmR3StrmSkipTo(&pSSM->Strm, offUnit + UnitHdr.cbUnit);
6536 ssmR3Progress(pSSM, offUnit + UnitHdr.cbUnit - pSSM->offEst);
6537 }
6538 else if (i64Diff > 0)
6539 {
6540 LogRel(("SSM: Unit '%s' read %lld bytes too much!\n", pszName, i64Diff));
6541 rc = VMSetError(pVM, VERR_SSM_LOADED_TOO_MUCH, RT_SRC_POS,
6542 N_("Unit '%s' read %lld bytes too much"), pszName, i64Diff);
6543 break;
6544 }
6545
6546 pSSM->offUnit = UINT64_MAX;
6547 }
6548 else
6549 {
6550 LogRel(("SSM: Load exec failed for '%s' instance #%u ! (version %u)\n",
6551 pszName, UnitHdr.u32Instance, UnitHdr.u32Version));
6552 VMSetError(pVM, rc, RT_SRC_POS, N_("Load exec failed for '%s' instance #%u (version %u)"),
6553 pszName, UnitHdr.u32Instance, UnitHdr.u32Version);
6554 break;
6555 }
6556 }
6557 else
6558 {
6559 /*
6560 * SSM unit wasn't found - ignore this when loading for the debugger.
6561 */
6562 LogRel(("SSM: Found no handler for unit '%s'!\n", pszName));
6563 rc = VERR_SSM_INTEGRITY_UNIT_NOT_FOUND;
6564 if (pSSM->enmAfter != SSMAFTER_DEBUG_IT)
6565 break;
6566 rc = ssmR3StrmSkipTo(&pSSM->Strm, offUnit + UnitHdr.cbUnit);
6567 }
6568 }
6569 }
6570 else
6571 rc = VERR_NO_TMP_MEMORY;
6572 }
6573
6574 /*
6575 * I/O errors ends up here (yea, I know, very nice programming).
6576 */
6577 if (RT_FAILURE(rc))
6578 {
6579 LogRel(("SSM: I/O error. rc=%Rrc\n", rc));
6580 break;
6581 }
6582
6583 /*
6584 * Check for cancellation.
6585 */
6586 if (RT_UNLIKELY(ASMAtomicUoReadU32(&(pSSM)->fCancelled) == SSMHANDLE_CANCELLED))
6587 {
6588 LogRel(("SSM: Cancelled!n"));
6589 rc = pSSM->rc;
6590 if (RT_SUCCESS(pSSM->rc))
6591 pSSM->rc = rc = VERR_SSM_CANCELLED;
6592 break;
6593 }
6594 }
6595
6596 RTMemTmpFree(pszName);
6597 return rc;
6598}
6599
6600
6601/**
6602 * Executes the loading of a V2.X file.
6603 *
6604 * @returns VBox status code.
6605 * @param pVM The VM handle.
6606 * @param pSSM The saved state handle.
6607 */
6608static int ssmR3LoadExecV2(PVM pVM, PSSMHANDLE pSSM)
6609{
6610 pSSM->enmOp = SSMSTATE_LOAD_EXEC;
6611 for (;;)
6612 {
6613 /*
6614 * Read the unit header and check its integrity.
6615 */
6616 uint64_t offUnit = ssmR3StrmTell(&pSSM->Strm);
6617 uint32_t u32CurStreamCRC = ssmR3StrmCurCRC(&pSSM->Strm);
6618 SSMFILEUNITHDRV2 UnitHdr;
6619 int rc = ssmR3StrmRead(&pSSM->Strm, &UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName));
6620 if (RT_FAILURE(rc))
6621 return rc;
6622 if (RT_UNLIKELY( memcmp(&UnitHdr.szMagic[0], SSMFILEUNITHDR_MAGIC, sizeof(UnitHdr.szMagic))
6623 && memcmp(&UnitHdr.szMagic[0], SSMFILEUNITHDR_END, sizeof(UnitHdr.szMagic))))
6624 {
6625 LogRel(("SSM: Unit at %#llx (%lld): Invalid unit magic: %.*Rhxs!\n",
6626 offUnit, offUnit, sizeof(UnitHdr.szMagic) - 1, &UnitHdr.szMagic[0]));
6627 return VMSetError(pVM, VERR_SSM_INTEGRITY_UNIT_MAGIC, RT_SRC_POS,
6628 N_("Unit at %#llx (%lld): Invalid unit magic"), offUnit, offUnit);
6629 }
6630 if (UnitHdr.cbName)
6631 {
6632 AssertLogRelMsgReturn(UnitHdr.cbName <= sizeof(UnitHdr.szName),
6633 ("Unit at %#llx (%lld): UnitHdr.cbName=%u > %u\n",
6634 offUnit, offUnit, UnitHdr.cbName, sizeof(UnitHdr.szName)),
6635 VERR_SSM_INTEGRITY_UNIT);
6636 rc = ssmR3StrmRead(&pSSM->Strm, &UnitHdr.szName[0], UnitHdr.cbName);
6637 if (RT_FAILURE(rc))
6638 return rc;
6639 AssertLogRelMsgReturn(!UnitHdr.szName[UnitHdr.cbName - 1],
6640 ("Unit at %#llx (%lld): Name %.*Rhxs was not properly terminated.\n",
6641 offUnit, offUnit, UnitHdr.cbName, UnitHdr.szName),
6642 VERR_SSM_INTEGRITY_UNIT);
6643 }
6644 SSM_CHECK_CRC32_RET(&UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]),
6645 ("Unit at %#llx (%lld): CRC mismatch: %08x, correct is %08x\n", offUnit, offUnit, u32CRC, u32ActualCRC));
6646 AssertLogRelMsgReturn(UnitHdr.offStream == offUnit,
6647 ("Unit at %#llx (%lld): offStream=%#llx, expected %#llx\n", offUnit, offUnit, UnitHdr.offStream, offUnit),
6648 VERR_SSM_INTEGRITY_UNIT);
6649 AssertLogRelMsgReturn(UnitHdr.u32CurStreamCRC == u32CurStreamCRC || !pSSM->Strm.fChecksummed,
6650 ("Unit at %#llx (%lld): Stream CRC mismatch: %08x, correct is %08x\n", offUnit, offUnit, UnitHdr.u32CurStreamCRC, u32CurStreamCRC),
6651 VERR_SSM_INTEGRITY_UNIT);
6652 AssertLogRelMsgReturn(!UnitHdr.fFlags, ("Unit at %#llx (%lld): fFlags=%08x\n", offUnit, offUnit, UnitHdr.fFlags),
6653 VERR_SSM_INTEGRITY_UNIT);
6654 if (!memcmp(&UnitHdr.szMagic[0], SSMFILEUNITHDR_END, sizeof(UnitHdr.szMagic)))
6655 {
6656 AssertLogRelMsgReturn( UnitHdr.cbName == 0
6657 && UnitHdr.u32Instance == 0
6658 && UnitHdr.u32Version == 0
6659 && UnitHdr.u32Pass == SSM_PASS_FINAL,
6660 ("Unit at %#llx (%lld): Malformed END unit\n", offUnit, offUnit),
6661 VERR_SSM_INTEGRITY_UNIT);
6662
6663 /*
6664 * Complete the progress bar (pending 99% afterwards) and RETURN.
6665 */
6666 Log(("SSM: Unit at %#9llx: END UNIT\n", offUnit));
6667 ssmR3Progress(pSSM, pSSM->cbEstTotal - pSSM->offEst);
6668 return VINF_SUCCESS;
6669 }
6670 AssertLogRelMsgReturn(UnitHdr.cbName > 1, ("Unit at %#llx (%lld): No name\n", offUnit, offUnit), VERR_SSM_INTEGRITY);
6671
6672 Log(("SSM: Unit at %#9llx: '%s', instance %u, pass %#x, version %u\n",
6673 offUnit, UnitHdr.szName, UnitHdr.u32Instance, UnitHdr.u32Pass, UnitHdr.u32Version));
6674
6675 /*
6676 * Find the data unit in our internal table.
6677 */
6678 PSSMUNIT pUnit = ssmR3Find(pVM, UnitHdr.szName, UnitHdr.u32Instance);
6679 if (pUnit)
6680 {
6681 /*
6682 * Call the execute handler.
6683 */
6684 AssertLogRelMsgReturn(pUnit->u.Common.pfnLoadExec,
6685 ("SSM: No load exec callback for unit '%s'!\n", UnitHdr.szName),
6686 VERR_SSM_NO_LOAD_EXEC);
6687 ssmR3DataReadBeginV2(pSSM);
6688 switch (pUnit->enmType)
6689 {
6690 case SSMUNITTYPE_DEV:
6691 rc = pUnit->u.Dev.pfnLoadExec(pUnit->u.Dev.pDevIns, pSSM, UnitHdr.u32Version, UnitHdr.u32Pass);
6692 break;
6693 case SSMUNITTYPE_DRV:
6694 rc = pUnit->u.Drv.pfnLoadExec(pUnit->u.Drv.pDrvIns, pSSM, UnitHdr.u32Version, UnitHdr.u32Pass);
6695 break;
6696 case SSMUNITTYPE_INTERNAL:
6697 rc = pUnit->u.Internal.pfnLoadExec(pVM, pSSM, UnitHdr.u32Version, UnitHdr.u32Pass);
6698 break;
6699 case SSMUNITTYPE_EXTERNAL:
6700 rc = pUnit->u.External.pfnLoadExec(pSSM, pUnit->u.External.pvUser, UnitHdr.u32Version, UnitHdr.u32Pass);
6701 break;
6702 default:
6703 rc = VERR_INTERNAL_ERROR;
6704 break;
6705 }
6706 pUnit->fCalled = true;
6707 if (RT_FAILURE(rc) && RT_SUCCESS_NP(pSSM->rc))
6708 pSSM->rc = rc;
6709 rc = ssmR3DataReadFinishV2(pSSM);
6710 if (RT_SUCCESS(rc))
6711 pSSM->offUnit = UINT64_MAX;
6712 else
6713 {
6714 LogRel(("SSM: LoadExec failed for '%s' instance #%u (version %u, pass %#x): %Rrc\n",
6715 UnitHdr.szName, UnitHdr.u32Instance, UnitHdr.u32Version, UnitHdr.u32Pass, rc));
6716 return VMSetError(pVM, rc, RT_SRC_POS, N_("Failed to load unit '%s'"), UnitHdr.szName);
6717 }
6718 }
6719 else
6720 {
6721 /*
6722 * SSM unit wasn't found - ignore this when loading for the debugger.
6723 */
6724 LogRel(("SSM: Found no handler for unit '%s' instance #%u!\n", UnitHdr.szName, UnitHdr.u32Instance));
6725 if (pSSM->enmAfter != SSMAFTER_DEBUG_IT)
6726 return VMSetError(pVM, VERR_SSM_INTEGRITY_UNIT_NOT_FOUND, RT_SRC_POS,
6727 N_("Found no handler for unit '%s' instance #%u"), UnitHdr.szName, UnitHdr.u32Instance);
6728 SSMR3SkipToEndOfUnit(pSSM);
6729 ssmR3DataReadFinishV2(pSSM);
6730 }
6731
6732 /*
6733 * Check for cancellation.
6734 */
6735 if (RT_UNLIKELY(ASMAtomicUoReadU32(&(pSSM)->fCancelled) == SSMHANDLE_CANCELLED))
6736 {
6737 LogRel(("SSM: Cancelled!\n"));
6738 if (RT_SUCCESS(pSSM->rc))
6739 pSSM->rc = VERR_SSM_CANCELLED;
6740 return pSSM->rc;
6741 }
6742 }
6743 /* won't get here */
6744}
6745
6746
6747
6748
6749/**
6750 * Load VM save operation.
6751 *
6752 * @returns VBox status.
6753 *
6754 * @param pVM The VM handle.
6755 * @param pszFilename Name of the file to save the state in.
6756 * @param enmAfter What is planned after a successful load operation.
6757 * Only acceptable values are SSMAFTER_RESUME and SSMAFTER_DEBUG_IT.
6758 * @param pfnProgress Progress callback. Optional.
6759 * @param pvUser User argument for the progress callback.
6760 *
6761 * @thread EMT
6762 */
6763VMMR3DECL(int) SSMR3Load(PVM pVM, const char *pszFilename, SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvUser)
6764{
6765 LogFlow(("SSMR3Load: pszFilename=%p:{%s} enmAfter=%d pfnProgress=%p pvUser=%p\n", pszFilename, pszFilename, enmAfter, pfnProgress, pvUser));
6766 VM_ASSERT_EMT0(pVM);
6767
6768 /*
6769 * Validate input.
6770 */
6771 AssertMsgReturn( enmAfter == SSMAFTER_RESUME
6772 || enmAfter == SSMAFTER_MIGRATE
6773 || enmAfter == SSMAFTER_DEBUG_IT,
6774 ("%d\n", enmAfter),
6775 VERR_INVALID_PARAMETER);
6776
6777 /*
6778 * Create the handle and open the file.
6779 */
6780 SSMHANDLE Handle;
6781 int rc = ssmR3OpenFile(pVM, pszFilename, false /* fChecksumIt */, true /* fChecksumOnRead */, 8 /*cBuffers*/, &Handle);
6782 if (RT_SUCCESS(rc))
6783 {
6784 ssmR3StrmStartIoThread(&Handle.Strm);
6785 ssmR3SetCancellable(pVM, &Handle, true);
6786
6787 Handle.enmAfter = enmAfter;
6788 Handle.pfnProgress = pfnProgress;
6789 Handle.pvUser = pvUser;
6790
6791 if (Handle.u.Read.u16VerMajor)
6792 LogRel(("SSM: File header: Format %u.%u, VirtualBox Version %u.%u.%u r%u, %u-bit host, cbGCPhys=%u, cbGCPtr=%u\n",
6793 Handle.u.Read.uFmtVerMajor, Handle.u.Read.uFmtVerMinor,
6794 Handle.u.Read.u16VerMajor, Handle.u.Read.u16VerMinor, Handle.u.Read.u32VerBuild, Handle.u.Read.u32SvnRev,
6795 Handle.u.Read.cHostBits, Handle.u.Read.cbGCPhys, Handle.u.Read.cbGCPtr));
6796 else
6797 LogRel(("SSM: File header: Format %u.%u, %u-bit host, cbGCPhys=%u, cbGCPtr=%u\n" ,
6798 Handle.u.Read.uFmtVerMajor, Handle.u.Read.uFmtVerMinor,
6799 Handle.u.Read.cHostBits, Handle.u.Read.cbGCPhys, Handle.u.Read.cbGCPtr));
6800
6801 if (pfnProgress)
6802 pfnProgress(pVM, Handle.uPercent, pvUser);
6803
6804 /*
6805 * Clear the per unit flags.
6806 */
6807 PSSMUNIT pUnit;
6808 for (pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
6809 pUnit->fCalled = false;
6810
6811 /*
6812 * Do the prepare run.
6813 */
6814 Handle.rc = VINF_SUCCESS;
6815 Handle.enmOp = SSMSTATE_LOAD_PREP;
6816 for (pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
6817 {
6818 if (pUnit->u.Common.pfnLoadPrep)
6819 {
6820 pUnit->fCalled = true;
6821 switch (pUnit->enmType)
6822 {
6823 case SSMUNITTYPE_DEV:
6824 rc = pUnit->u.Dev.pfnLoadPrep(pUnit->u.Dev.pDevIns, &Handle);
6825 break;
6826 case SSMUNITTYPE_DRV:
6827 rc = pUnit->u.Drv.pfnLoadPrep(pUnit->u.Drv.pDrvIns, &Handle);
6828 break;
6829 case SSMUNITTYPE_INTERNAL:
6830 rc = pUnit->u.Internal.pfnLoadPrep(pVM, &Handle);
6831 break;
6832 case SSMUNITTYPE_EXTERNAL:
6833 rc = pUnit->u.External.pfnLoadPrep(&Handle, pUnit->u.External.pvUser);
6834 break;
6835 default:
6836 rc = VERR_INTERNAL_ERROR;
6837 break;
6838 }
6839 if (RT_FAILURE(rc) && RT_SUCCESS_NP(Handle.rc))
6840 Handle.rc = rc;
6841 else
6842 rc = Handle.rc;
6843 if (RT_FAILURE(rc))
6844 {
6845 LogRel(("SSM: Prepare load failed with rc=%Rrc for data unit '%s.\n", rc, pUnit->szName));
6846 break;
6847 }
6848 }
6849 }
6850
6851 /* pending 2% */
6852 if (pfnProgress)
6853 pfnProgress(pVM, Handle.uPercentPrepare-1, pvUser);
6854 Handle.uPercent = Handle.uPercentPrepare;
6855 Handle.cbEstTotal = Handle.u.Read.cbLoadFile;
6856 Handle.offEstUnitEnd = Handle.u.Read.cbLoadFile;
6857
6858 /*
6859 * Do the execute run.
6860 */
6861 if (RT_SUCCESS(rc))
6862 {
6863 if (Handle.u.Read.uFmtVerMajor >= 2)
6864 rc = ssmR3LoadExecV2(pVM, &Handle);
6865 else
6866 rc = ssmR3LoadExecV1(pVM, &Handle);
6867 /* (progress should be pending 99% now) */
6868 AssertMsg(RT_FAILURE(rc) || Handle.uPercent == (101-Handle.uPercentDone), ("%d\n", Handle.uPercent));
6869 }
6870
6871 /*
6872 * Do the done run.
6873 */
6874 Handle.rc = rc;
6875 Handle.enmOp = SSMSTATE_LOAD_DONE;
6876 for (pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
6877 {
6878 if ( pUnit->u.Common.pfnLoadDone
6879 && ( pUnit->fCalled
6880 || (!pUnit->u.Common.pfnLoadPrep && !pUnit->u.Common.pfnLoadExec)))
6881 {
6882 int const rcOld = Handle.rc;
6883 rc = VINF_SUCCESS;
6884 switch (pUnit->enmType)
6885 {
6886 case SSMUNITTYPE_DEV:
6887 rc = pUnit->u.Dev.pfnLoadDone(pUnit->u.Dev.pDevIns, &Handle);
6888 break;
6889 case SSMUNITTYPE_DRV:
6890 rc = pUnit->u.Drv.pfnLoadDone(pUnit->u.Drv.pDrvIns, &Handle);
6891 break;
6892 case SSMUNITTYPE_INTERNAL:
6893 rc = pUnit->u.Internal.pfnLoadDone(pVM, &Handle);
6894 break;
6895 case SSMUNITTYPE_EXTERNAL:
6896 rc = pUnit->u.External.pfnLoadDone(&Handle, pUnit->u.External.pvUser);
6897 break;
6898 default:
6899 rc = VERR_INTERNAL_ERROR;
6900 break;
6901 }
6902 if (RT_SUCCESS(rc) && Handle.rc != rcOld)
6903 rc = Handle.rc;
6904 if (RT_FAILURE(rc))
6905 {
6906 LogRel(("SSM: LoadDone failed with rc=%Rrc for data unit '%s' instance #%u.\n",
6907 rc, pUnit->szName, pUnit->u32Instance));
6908 if (RT_SUCCESS_NP(Handle.rc))
6909 Handle.rc = rc;
6910 }
6911 }
6912 }
6913 rc = Handle.rc;
6914
6915 /* progress */
6916 if (pfnProgress)
6917 pfnProgress(pVM, 99, pvUser);
6918
6919 ssmR3SetCancellable(pVM, &Handle, false);
6920 ssmR3StrmClose(&Handle.Strm);
6921 }
6922
6923 /*
6924 * Done
6925 */
6926 if (RT_SUCCESS(rc))
6927 {
6928 /* progress */
6929 if (pfnProgress)
6930 pfnProgress(pVM, 100, pvUser);
6931 Log(("SSM: Load of '%s' completed!\n", pszFilename));
6932 }
6933 return rc;
6934}
6935
6936
6937/**
6938 * Validates a file as a validate SSM saved state.
6939 *
6940 * This will only verify the file format, the format and content of individual
6941 * data units are not inspected.
6942 *
6943 * @returns VINF_SUCCESS if valid.
6944 * @returns VBox status code on other failures.
6945 *
6946 * @param pszFilename The path to the file to validate.
6947 * @param fChecksumIt Whether to checksum the file or not.
6948 *
6949 * @thread Any.
6950 */
6951VMMR3DECL(int) SSMR3ValidateFile(const char *pszFilename, bool fChecksumIt)
6952{
6953 LogFlow(("SSMR3ValidateFile: pszFilename=%p:{%s} fChecksumIt=%RTbool\n", pszFilename, pszFilename, fChecksumIt));
6954
6955 /*
6956 * Try open the file and validate it.
6957 */
6958 SSMHANDLE Handle;
6959 int rc = ssmR3OpenFile(NULL, pszFilename, fChecksumIt, false /*fChecksumOnRead*/, 1 /*cBuffers*/, &Handle);
6960 if (RT_SUCCESS(rc))
6961 ssmR3StrmClose(&Handle.Strm);
6962 else
6963 Log(("SSM: Failed to open saved state file '%s', rc=%Rrc.\n", pszFilename, rc));
6964 return rc;
6965}
6966
6967
6968/**
6969 * Opens a saved state file for reading.
6970 *
6971 * @returns VBox status code.
6972 *
6973 * @param pszFilename The path to the saved state file.
6974 * @param fFlags Open flags. Reserved, must be 0.
6975 * @param ppSSM Where to store the SSM handle.
6976 *
6977 * @thread Any.
6978 */
6979VMMR3DECL(int) SSMR3Open(const char *pszFilename, unsigned fFlags, PSSMHANDLE *ppSSM)
6980{
6981 LogFlow(("SSMR3Open: pszFilename=%p:{%s} fFlags=%#x ppSSM=%p\n", pszFilename, pszFilename, fFlags, ppSSM));
6982
6983 /*
6984 * Validate input.
6985 */
6986 AssertMsgReturn(VALID_PTR(pszFilename), ("%p\n", pszFilename), VERR_INVALID_PARAMETER);
6987 AssertMsgReturn(!fFlags, ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
6988 AssertMsgReturn(VALID_PTR(ppSSM), ("%p\n", ppSSM), VERR_INVALID_PARAMETER);
6989
6990 /*
6991 * Allocate a handle.
6992 */
6993 PSSMHANDLE pSSM = (PSSMHANDLE)RTMemAllocZ(sizeof(*pSSM));
6994 AssertReturn(pSSM, VERR_NO_MEMORY);
6995
6996 /*
6997 * Try open the file and validate it.
6998 */
6999 int rc = ssmR3OpenFile(NULL, pszFilename, false /*fChecksumIt*/, true /*fChecksumOnRead*/, 1 /*cBuffers*/, pSSM);
7000 if (RT_SUCCESS(rc))
7001 {
7002 pSSM->enmAfter = SSMAFTER_OPENED;
7003 pSSM->enmOp = SSMSTATE_OPEN_READ;
7004 *ppSSM = pSSM;
7005 LogFlow(("SSMR3Open: returns VINF_SUCCESS *ppSSM=%p\n", *ppSSM));
7006 return VINF_SUCCESS;
7007 }
7008
7009 Log(("SSMR3Open: Failed to open saved state file '%s', rc=%Rrc.\n", pszFilename, rc));
7010 RTMemFree(pSSM);
7011 return rc;
7012
7013}
7014
7015
7016/**
7017 * Closes a saved state file opened by SSMR3Open().
7018 *
7019 * @returns VBox status code.
7020 *
7021 * @param pSSM The SSM handle returned by SSMR3Open().
7022 *
7023 * @thread Any, but the caller is responsible for serializing calls per handle.
7024 */
7025VMMR3DECL(int) SSMR3Close(PSSMHANDLE pSSM)
7026{
7027 LogFlow(("SSMR3Close: pSSM=%p\n", pSSM));
7028
7029 /*
7030 * Validate input.
7031 */
7032 AssertMsgReturn(VALID_PTR(pSSM), ("%p\n", pSSM), VERR_INVALID_PARAMETER);
7033 AssertMsgReturn(pSSM->enmAfter == SSMAFTER_OPENED, ("%d\n", pSSM->enmAfter),VERR_INVALID_PARAMETER);
7034 AssertMsgReturn(pSSM->enmOp == SSMSTATE_OPEN_READ, ("%d\n", pSSM->enmOp), VERR_INVALID_PARAMETER);
7035 Assert(pSSM->fCancelled == SSMHANDLE_OK);
7036
7037 /*
7038 * Close the stream and free the handle.
7039 */
7040 int rc = ssmR3StrmClose(&pSSM->Strm);
7041 if (pSSM->u.Read.pZipDecompV1)
7042 {
7043 RTZipDecompDestroy(pSSM->u.Read.pZipDecompV1);
7044 pSSM->u.Read.pZipDecompV1 = NULL;
7045 }
7046 RTMemFree(pSSM);
7047 return rc;
7048}
7049
7050
7051/**
7052 * Worker for SSMR3Seek that seeks version 1 saved state files.
7053 *
7054 * @returns VBox status code.
7055 * @param pSSM The SSM handle.
7056 * @param pszUnit The unit to seek to.
7057 * @param iInstance The particulart insance we seek.
7058 * @param piVersion Where to store the unit version number.
7059 */
7060static int ssmR3FileSeekV1(PSSMHANDLE pSSM, const char *pszUnit, uint32_t iInstance, uint32_t *piVersion)
7061{
7062 /*
7063 * Walk the data units until we find EOF or a match.
7064 */
7065 size_t cbUnitNm = strlen(pszUnit) + 1;
7066 AssertLogRelReturn(cbUnitNm <= SSM_MAX_NAME_SIZE, VERR_SSM_UNIT_NOT_FOUND);
7067 char szName[SSM_MAX_NAME_SIZE];
7068 SSMFILEUNITHDRV1 UnitHdr;
7069 for (RTFOFF off = pSSM->u.Read.cbFileHdr; ; off += UnitHdr.cbUnit)
7070 {
7071 /*
7072 * Read the unit header and verify it.
7073 */
7074 int rc = ssmR3StrmPeekAt(&pSSM->Strm, off, &UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV1, szName), NULL);
7075 AssertRCReturn(rc, rc);
7076 if (!memcmp(&UnitHdr.achMagic[0], SSMFILEUNITHDR_MAGIC, sizeof(SSMFILEUNITHDR_MAGIC)))
7077 {
7078 /*
7079 * Does what we've got match, if so read the name.
7080 */
7081 if ( UnitHdr.u32Instance == iInstance
7082 && UnitHdr.cchName == cbUnitNm)
7083 {
7084 rc = ssmR3StrmPeekAt(&pSSM->Strm, off + RT_OFFSETOF(SSMFILEUNITHDRV1, szName), szName, cbUnitNm, NULL);
7085 AssertRCReturn(rc, rc);
7086 AssertLogRelMsgReturn(!szName[UnitHdr.cchName - 1],
7087 (" Unit name '%.*s' was not properly terminated.\n", cbUnitNm, szName),
7088 VERR_SSM_INTEGRITY_UNIT);
7089
7090 /*
7091 * Does the name match?
7092 */
7093 if (!memcmp(szName, pszUnit, cbUnitNm))
7094 {
7095 rc = ssmR3StrmSeek(&pSSM->Strm, off + RT_OFFSETOF(SSMFILEUNITHDRV1, szName) + cbUnitNm, RTFILE_SEEK_BEGIN, 0);
7096 pSSM->cbUnitLeftV1 = UnitHdr.cbUnit - RT_OFFSETOF(SSMFILEUNITHDRV1, szName[cbUnitNm]);
7097 pSSM->offUnit = 0;
7098 if (piVersion)
7099 *piVersion = UnitHdr.u32Version;
7100 return VINF_SUCCESS;
7101 }
7102 }
7103 }
7104 else if (!memcmp(&UnitHdr.achMagic[0], SSMFILEUNITHDR_END, sizeof(SSMFILEUNITHDR_END)))
7105 return VERR_SSM_UNIT_NOT_FOUND;
7106 else
7107 AssertLogRelMsgFailedReturn(("Invalid unit magic at offset %RTfoff, '%.*s'!\n",
7108 off, sizeof(UnitHdr.achMagic) - 1, &UnitHdr.achMagic[0]),
7109 VERR_SSM_INTEGRITY_UNIT_MAGIC);
7110 }
7111 /* won't get here. */
7112}
7113
7114
7115/**
7116 * Worker for ssmR3FileSeekV2 for simplifying memory cleanup.
7117 *
7118 * @returns VBox status code.
7119 * @param pSSM The SSM handle.
7120 * @param pDir The directory buffer.
7121 * @param cbDir The size of the directory.
7122 * @param cDirEntries The number of directory entries.
7123 * @param offDir The directory offset in the file.
7124 * @param pszUnit The unit to seek to.
7125 * @param iInstance The particulart insance we seek.
7126 * @param piVersion Where to store the unit version number.
7127 */
7128static int ssmR3FileSeekSubV2(PSSMHANDLE pSSM, PSSMFILEDIR pDir, size_t cbDir, uint32_t cDirEntries, uint64_t offDir,
7129 const char *pszUnit, uint32_t iInstance, uint32_t *piVersion)
7130{
7131 /*
7132 * Read it.
7133 */
7134 int rc = ssmR3StrmPeekAt(&pSSM->Strm, offDir, pDir, cbDir, NULL);
7135 AssertLogRelRCReturn(rc, rc);
7136 AssertLogRelReturn(!memcmp(pDir->szMagic, SSMFILEDIR_MAGIC, sizeof(pDir->szMagic)), VERR_SSM_INTEGRITY_DIR_MAGIC);
7137 SSM_CHECK_CRC32_RET(pDir, cbDir, ("Bad directory CRC: %08x, actual %08x\n", u32CRC, u32ActualCRC));
7138 AssertLogRelMsgReturn(pDir->cEntries == cDirEntries,
7139 ("Bad directory entry count: %#x, expected %#x (from the footer)\n", pDir->cEntries, cDirEntries),
7140 VERR_SSM_INTEGRITY_DIR);
7141 for (uint32_t i = 0; i < cDirEntries; i++)
7142 AssertLogRelMsgReturn(pDir->aEntries[i].off < offDir,
7143 ("i=%u off=%lld offDir=%lld\n", i, pDir->aEntries[i].off, offDir),
7144 VERR_SSM_INTEGRITY_DIR);
7145
7146 /*
7147 * Search the directory.
7148 */
7149 size_t cbUnitNm = strlen(pszUnit) + 1;
7150 uint32_t const u32NameCRC = RTCrc32(pszUnit, cbUnitNm - 1);
7151 for (uint32_t i = 0; i < cDirEntries; i++)
7152 {
7153 if ( pDir->aEntries[i].u32NameCRC == u32NameCRC
7154 && pDir->aEntries[i].u32Instance == iInstance)
7155 {
7156 /*
7157 * Read and validate the unit header.
7158 */
7159 SSMFILEUNITHDRV2 UnitHdr;
7160 size_t cbToRead = sizeof(UnitHdr);
7161 if (pDir->aEntries[i].off + cbToRead > offDir)
7162 {
7163 cbToRead = offDir - pDir->aEntries[i].off;
7164 RT_ZERO(UnitHdr);
7165 }
7166 rc = ssmR3StrmPeekAt(&pSSM->Strm, pDir->aEntries[i].off, &UnitHdr, cbToRead, NULL);
7167 AssertLogRelRCReturn(rc, rc);
7168
7169 AssertLogRelMsgReturn(!memcmp(UnitHdr.szMagic, SSMFILEUNITHDR_MAGIC, sizeof(UnitHdr.szMagic)),
7170 ("Bad unit header or dictionary offset: i=%u off=%lld\n", i, pDir->aEntries[i].off),
7171 VERR_SSM_INTEGRITY_UNIT);
7172 AssertLogRelMsgReturn(UnitHdr.offStream == pDir->aEntries[i].off,
7173 ("Bad unit header: i=%d off=%lld offStream=%lld\n", i, pDir->aEntries[i].off, UnitHdr.offStream),
7174 VERR_SSM_INTEGRITY_UNIT);
7175 AssertLogRelMsgReturn(UnitHdr.u32Instance == pDir->aEntries[i].u32Instance,
7176 ("Bad unit header: i=%d off=%lld u32Instance=%u Dir.u32Instance=%u\n",
7177 i, pDir->aEntries[i].off, UnitHdr.u32Instance, pDir->aEntries[i].u32Instance),
7178 VERR_SSM_INTEGRITY_UNIT);
7179 uint32_t cbUnitHdr = RT_UOFFSETOF(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]);
7180 AssertLogRelMsgReturn( UnitHdr.cbName > 0
7181 && UnitHdr.cbName < sizeof(UnitHdr)
7182 && cbUnitHdr <= cbToRead,
7183 ("Bad unit header: i=%u off=%lld cbName=%#x cbToRead=%#x\n", i, pDir->aEntries[i].off, UnitHdr.cbName, cbToRead),
7184 VERR_SSM_INTEGRITY_UNIT);
7185 SSM_CHECK_CRC32_RET(&UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]),
7186 ("Bad unit header CRC: i=%u off=%lld u32CRC=%#x u32ActualCRC=%#x\n",
7187 i, pDir->aEntries[i].off, u32CRC, u32ActualCRC));
7188
7189 /*
7190 * Ok, it is valid, get on with the comparing now.
7191 */
7192 if ( UnitHdr.cbName == cbUnitNm
7193 && !memcmp(UnitHdr.szName, pszUnit, cbUnitNm))
7194 {
7195 if (piVersion)
7196 *piVersion = UnitHdr.u32Version;
7197 rc = ssmR3StrmSeek(&pSSM->Strm, pDir->aEntries[i].off + cbUnitHdr, RTFILE_SEEK_BEGIN,
7198 RTCrc32Process(UnitHdr.u32CurStreamCRC, &UnitHdr, cbUnitHdr));
7199 AssertLogRelRCReturn(rc, rc);
7200 ssmR3DataReadBeginV2(pSSM);
7201 return VINF_SUCCESS;
7202 }
7203 }
7204 }
7205
7206 return VERR_SSM_UNIT_NOT_FOUND;
7207}
7208
7209
7210/**
7211 * Worker for SSMR3Seek that seeks version 2 saved state files.
7212 *
7213 * @returns VBox status code.
7214 * @param pSSM The SSM handle.
7215 * @param pszUnit The unit to seek to.
7216 * @param iInstance The particulart insance we seek.
7217 * @param piVersion Where to store the unit version number.
7218 */
7219static int ssmR3FileSeekV2(PSSMHANDLE pSSM, const char *pszUnit, uint32_t iInstance, uint32_t *piVersion)
7220{
7221 /*
7222 * Read the footer, allocate a temporary buffer for the dictionary and
7223 * pass it down to a worker to simplify cleanup.
7224 */
7225 uint64_t offFooter;
7226 SSMFILEFTR Footer;
7227 int rc = ssmR3StrmPeekAt(&pSSM->Strm, -(RTFOFF)sizeof(Footer), &Footer, sizeof(Footer), &offFooter);
7228 AssertLogRelRCReturn(rc, rc);
7229 AssertLogRelReturn(!memcmp(Footer.szMagic, SSMFILEFTR_MAGIC, sizeof(Footer.szMagic)), VERR_SSM_INTEGRITY);
7230 SSM_CHECK_CRC32_RET(&Footer, sizeof(Footer), ("Bad footer CRC: %08x, actual %08x\n", u32CRC, u32ActualCRC));
7231
7232 size_t const cbDir = RT_OFFSETOF(SSMFILEDIR, aEntries[Footer.cDirEntries]);
7233 PSSMFILEDIR pDir = (PSSMFILEDIR)RTMemTmpAlloc(cbDir);
7234 if (RT_UNLIKELY(!pDir))
7235 return VERR_NO_TMP_MEMORY;
7236 rc = ssmR3FileSeekSubV2(pSSM, pDir, cbDir, Footer.cDirEntries, offFooter - cbDir,
7237 pszUnit, iInstance, piVersion);
7238 RTMemTmpFree(pDir);
7239
7240 return rc;
7241}
7242
7243
7244/**
7245 * Seeks to a specific data unit.
7246 *
7247 * After seeking it's possible to use the getters to on
7248 * that data unit.
7249 *
7250 * @returns VBox status code.
7251 * @returns VERR_SSM_UNIT_NOT_FOUND if the unit+instance wasn't found.
7252 *
7253 * @param pSSM The SSM handle returned by SSMR3Open().
7254 * @param pszUnit The name of the data unit.
7255 * @param iInstance The instance number.
7256 * @param piVersion Where to store the version number. (Optional)
7257 *
7258 * @thread Any, but the caller is responsible for serializing calls per handle.
7259 */
7260VMMR3DECL(int) SSMR3Seek(PSSMHANDLE pSSM, const char *pszUnit, uint32_t iInstance, uint32_t *piVersion)
7261{
7262 LogFlow(("SSMR3Seek: pSSM=%p pszUnit=%p:{%s} iInstance=%RU32 piVersion=%p\n",
7263 pSSM, pszUnit, pszUnit, iInstance, piVersion));
7264
7265 /*
7266 * Validate input.
7267 */
7268 AssertPtrReturn(pSSM, VERR_INVALID_PARAMETER);
7269 AssertMsgReturn(pSSM->enmAfter == SSMAFTER_OPENED, ("%d\n", pSSM->enmAfter),VERR_INVALID_PARAMETER);
7270 AssertMsgReturn(pSSM->enmOp == SSMSTATE_OPEN_READ, ("%d\n", pSSM->enmOp), VERR_INVALID_PARAMETER);
7271 AssertPtrReturn(pszUnit, VERR_INVALID_POINTER);
7272 AssertMsgReturn(!piVersion || VALID_PTR(piVersion), ("%p\n", piVersion), VERR_INVALID_POINTER);
7273
7274 /*
7275 * Reset the state.
7276 */
7277 if (pSSM->u.Read.pZipDecompV1)
7278 {
7279 RTZipDecompDestroy(pSSM->u.Read.pZipDecompV1);
7280 pSSM->u.Read.pZipDecompV1 = NULL;
7281 }
7282 pSSM->cbUnitLeftV1 = 0;
7283 pSSM->offUnit = UINT64_MAX;
7284
7285 /*
7286 * Call the version specific workers.
7287 */
7288 if (pSSM->u.Read.uFmtVerMajor >= 2)
7289 pSSM->rc = ssmR3FileSeekV2(pSSM, pszUnit, iInstance, piVersion);
7290 else
7291 pSSM->rc = ssmR3FileSeekV1(pSSM, pszUnit, iInstance, piVersion);
7292 return pSSM->rc;
7293}
7294
7295
7296
7297/* ... Misc APIs ... */
7298/* ... Misc APIs ... */
7299/* ... Misc APIs ... */
7300/* ... Misc APIs ... */
7301/* ... Misc APIs ... */
7302/* ... Misc APIs ... */
7303/* ... Misc APIs ... */
7304/* ... Misc APIs ... */
7305/* ... Misc APIs ... */
7306/* ... Misc APIs ... */
7307/* ... Misc APIs ... */
7308
7309
7310
7311/**
7312 * Query what the VBox status code of the operation is.
7313 *
7314 * This can be used for putting and getting a batch of values
7315 * without bother checking the result till all the calls have
7316 * been made.
7317 *
7318 * @returns SSMAFTER enum value.
7319 * @param pSSM SSM operation handle.
7320 */
7321VMMR3DECL(int) SSMR3HandleGetStatus(PSSMHANDLE pSSM)
7322{
7323 return pSSM->rc;
7324}
7325
7326
7327/**
7328 * Fail the load operation.
7329 *
7330 * This is mainly intended for sub item loaders (like timers) which
7331 * return code isn't necessarily heeded by the caller but is important
7332 * to SSM.
7333 *
7334 * @returns VBox status code of the handle, or VERR_INVALID_PARAMETER.
7335 * @param pSSM SSM operation handle.
7336 * @param iStatus Failure status code. This MUST be a VERR_*.
7337 */
7338VMMR3DECL(int) SSMR3HandleSetStatus(PSSMHANDLE pSSM, int iStatus)
7339{
7340 Assert(pSSM->enmOp != SSMSTATE_LIVE_VOTE);
7341 if (RT_FAILURE(iStatus))
7342 {
7343 int rc = pSSM->rc;
7344 if (RT_SUCCESS(rc))
7345 pSSM->rc = rc = iStatus;
7346 return rc;
7347 }
7348 AssertMsgFailed(("iStatus=%d %Rrc\n", iStatus, iStatus));
7349 return VERR_INVALID_PARAMETER;
7350}
7351
7352
7353/**
7354 * Get what to do after this operation.
7355 *
7356 * @returns SSMAFTER enum value.
7357 * @param pSSM SSM operation handle.
7358 */
7359VMMR3DECL(SSMAFTER) SSMR3HandleGetAfter(PSSMHANDLE pSSM)
7360{
7361 return pSSM->enmAfter;
7362}
7363
7364
7365/**
7366 * Get the current unit byte offset (uncompressed).
7367 *
7368 * @returns The offset. UINT64_MAX if called at a wrong time.
7369 * @param pSSM SSM operation handle.
7370 */
7371VMMR3DECL(uint64_t) SSMR3HandleGetUnitOffset(PSSMHANDLE pSSM)
7372{
7373 AssertMsgFailed(("/** @todo this isn't correct any longer. */"));
7374 return pSSM->offUnit;
7375}
7376
7377
7378/**
7379 * Asynchronously cancels the current SSM operation ASAP.
7380 *
7381 * @returns VBox status code.
7382 * @retval VINF_SUCCESS on success.
7383 * @retval VERR_SSM_NO_PENDING_OPERATION if nothing around that can be
7384 * cancelled.
7385 * @retval VERR_SSM_ALREADY_CANCELLED if the operation as already been
7386 * cancelled.
7387 *
7388 * @param pVM The VM handle.
7389 *
7390 * @thread Any.
7391 */
7392VMMR3DECL(int) SSMR3Cancel(PVM pVM)
7393{
7394 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
7395
7396 int rc = RTCritSectEnter(&pVM->ssm.s.CancelCritSect);
7397 AssertRCReturn(rc, rc);
7398
7399 PSSMHANDLE pSSM = pVM->ssm.s.pSSM;
7400 if (pSSM)
7401 {
7402 uint32_t u32Old;
7403 if (ASMAtomicCmpXchgExU32(&pSSM->fCancelled, SSMHANDLE_CANCELLED, SSMHANDLE_OK, &u32Old))
7404 {
7405 LogRel(("SSM: Cancelled pending operation\n"));
7406 rc = VINF_SUCCESS;
7407 }
7408 else if (u32Old == SSMHANDLE_CANCELLED)
7409 rc = VERR_SSM_ALREADY_CANCELLED;
7410 else
7411 {
7412 AssertLogRelMsgFailed(("fCancelled=%RX32 enmOp=%d\n", u32Old, pSSM->enmOp));
7413 rc = VERR_INTERNAL_ERROR_2;
7414 }
7415 }
7416 else
7417 rc = VERR_SSM_NO_PENDING_OPERATION;
7418
7419 RTCritSectLeave(&pVM->ssm.s.CancelCritSect);
7420 return rc;
7421}
7422
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette