VirtualBox

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

Last change on this file since 23844 was 23816, checked in by vboxsync, 16 years ago

SSM: Added flag for indicating that we're not using SSMR3PutStructEx and therefor shouldn't be too uptight about some things (HCPTR_HACK_U32).

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette