VirtualBox

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

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

SSM: Better tracking of load errors.

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