VirtualBox

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

Last change on this file since 23722 was 23714, checked in by vboxsync, 16 years ago

SSM,VBox/err.*: VINF_SSM_DONT_CALL_AGAIN from pfnLiveExec.

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

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