VirtualBox

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

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

SSM: the right way around. duh.

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