VirtualBox

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

Last change on this file since 23673 was 23668, checked in by vboxsync, 16 years ago

VMM: Live migration fixes.

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