VirtualBox

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

Last change on this file since 23594 was 23593, checked in by vboxsync, 15 years ago

SSM: Fixed bug causing invalid/unnecessary directory entries. Made SSMR3Load also accept a stream method table.

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