VirtualBox

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

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

SSM: Generalizing the file handling.

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

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