VirtualBox

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

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

SSM: docs.

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

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