VirtualBox

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

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

SSM: Reduce the number of ifndef SSM_STANDALONE checks by moving code.

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