VirtualBox

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

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

Main,VMM,VBoxManage: Added a parameter to IConsole::Teleport for specifying a max downtime and made PGM compare this against a rough estimate of the time it would take to deal with the rest of the pages.

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