VirtualBox

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

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

SSM: Added SSMR3SetLoadError[V] and SSMR3SetCfgError for setting log errors.

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