VirtualBox

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

Last change on this file since 39034 was 37026, checked in by vboxsync, 14 years ago

SSM: pointers aren't UL everywhere.

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