VirtualBox

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

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

Automated rebranding to Oracle copyright/license strings via filemuncher

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