VirtualBox

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

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

SSM.cpp: assertion instead of bulky code.

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