VirtualBox

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

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

SSM: Moved the LivePrep phase to the worker thread.

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