VirtualBox

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

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

SSM: Do the SaveDone round on live failure.

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