~ubuntu-branches/debian/stretch/uswsusp/stretch

« back to all changes in this revision

Viewing changes to load.c

  • Committer: Bazaar Package Importer
  • Author(s): Rodolfo García Peñas (kix), Rodolfo García Peñas (kix), Closes: #552484, #576803, #528483, Closes: #495111, #595125, #486352, #433872, #590233, Closes: #550725, #549118, Closes: #437094, #586674, #547158, #567604, Closes: #520705, Anibal Monsalve Salazar
  • Date: 2011-03-14 08:26:16 UTC
  • mfrom: (0.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20110314082616-7mjcl6tfzsv22arm
Tags: 1.0-1
[ Rodolfo García Peñas (kix) ]
* New 1.0 version [Closes: #589743, #578496, #617534]
* A lot of new machines. 
  [Closes: #552484, #576803, #528483] 
  [Closes: #495111, #595125, #486352, #433872, #590233] 
* A new length for addressing 
  [Closes: #550725, #549118]
  (http://lkml.org/lkml/2009/11/3/377)
* Support for Kernel Mode Set (KMS) 
  [Closes: #437094, #586674, #547158, #567604]
* Switch to dpkg-source 3.0 (quilt) format
* Compiled without splash support. 
  libsplash is not included in stable, many bugs.
* Moved the manpage file "suspend.conf.8" to manual section 5.
  [Closes: #520705]

[ Anibal Monsalve Salazar ]
* Update uploaders list

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * load.c
 
3
 *
 
4
 * Image loading for s2disk/s2both and resume.
 
5
 *
 
6
 * Copyright (C) 2008 Rafael J. Wysocki <rjw@sisk.pl>
 
7
 *
 
8
 * This file is released under the GPLv2.
 
9
 */
 
10
 
 
11
#include "config.h"
 
12
#include <sys/types.h>
 
13
#include <sys/stat.h>
 
14
#include <sys/ioctl.h>
 
15
#include <sys/mman.h>
 
16
#include <sys/time.h>
 
17
#include <time.h>
 
18
#include <syscall.h>
 
19
#include <libgen.h>
 
20
#include <fcntl.h>
 
21
#include <unistd.h>
 
22
#include <stdio.h>
 
23
#include <stdlib.h>
 
24
#include <string.h>
 
25
#include <errno.h>
 
26
#ifdef CONFIG_COMPRESS
 
27
#include <lzo/lzo1x.h>
 
28
#endif
 
29
 
 
30
#include "swsusp.h"
 
31
#include "memalloc.h"
 
32
#include "md5.h"
 
33
#include "splash.h"
 
34
 
 
35
char *my_name;
 
36
 
 
37
static char verify_checksum;
 
38
#ifdef CONFIG_COMPRESS
 
39
unsigned int compress_buf_size;
 
40
static char do_decompress;
 
41
#else
 
42
#define do_decompress 0
 
43
#endif
 
44
#ifdef CONFIG_ENCRYPT
 
45
static char do_decrypt;
 
46
static char password[PASSBUF_SIZE];
 
47
#else
 
48
#define do_decrypt 0
 
49
#endif
 
50
 
 
51
/**
 
52
 *      read_page - Read data from a swap location
 
53
 *      @fd:            File handle of the resume partition.
 
54
 *      @buf:           Pointer to the area we're reading into.
 
55
 *      @offset:        Swap offset of the place to read from.
 
56
 */
 
57
static int read_page(int fd, void *buf, loff_t offset)
 
58
{
 
59
        int res = 0;
 
60
        ssize_t cnt = 0;
 
61
 
 
62
        if (!offset)
 
63
                return 0;
 
64
 
 
65
        if (lseek(fd, offset, SEEK_SET) == offset)
 
66
                cnt = read(fd, buf, page_size);
 
67
        if (cnt < (ssize_t)page_size)
 
68
                res = -EIO;
 
69
 
 
70
        return res;
 
71
}
 
72
 
 
73
/*
 
74
 * The swap_reader structure is used for handling swap in a file-alike way.
 
75
 *
 
76
 * @extents:    Array of extents used for trackig swap allocations.  It is
 
77
 *              page_size bytes large and holds at most
 
78
 *              (page_size / sizeof(struct extent) - 1) extents.  The last slot
 
79
 *              must be all zeros and is the end marker.
 
80
 *
 
81
 * @cur_extent:         The extent currently used as the source of swap pages.
 
82
 *
 
83
 * @cur_offset:         The offset of the swap page that will be used next.
 
84
 *
 
85
 * @total_size:         The amount of data to read.
 
86
 *
 
87
 * @buffer:             Buffer used for storing image data pages.
 
88
 *
 
89
 * @read_buffer:        If compression is used, the compressed contents of
 
90
 *                      @buffer are stored here.  Otherwise, it is equal to
 
91
 *                      @buffer.
 
92
 *
 
93
 * @fd:                 File handle associated with the swap.
 
94
 *
 
95
 * @ctx:                Used for checksum computing, if so configured.
 
96
 *
 
97
 * @lzo_work_buffer:    Work buffer used for decompression.
 
98
 *
 
99
 * @decrypt_buffer:     Buffer for storing encrypted pages (page_size bytes).
 
100
 */
 
101
struct swap_reader {
 
102
        struct extent *extents;
 
103
        struct extent *cur_extent;
 
104
        loff_t cur_offset;
 
105
        loff_t next_extents;
 
106
        loff_t total_size;
 
107
        void *buffer;
 
108
        void *read_buffer;
 
109
        int fd;
 
110
        struct md5_ctx ctx;
 
111
        void *lzo_work_buffer;
 
112
        char *decrypt_buffer;
 
113
};
 
114
 
 
115
/**
 
116
 *      load_extents_page - load the array of extents
 
117
 *      handle: Structure holding the pointer to the array of extents etc.
 
118
 *
 
119
 *      Read the table of extents from the swap location pointed to by
 
120
 *      @handle->next_extents and store it at the address in @handle->extents.
 
121
 *      Read the swap location of the next array of extents from the last
 
122
 *      element of the array and fill this element with zeros.  Initialize
 
123
 *      @handle->cur_extent and @handle->cur_offset as appropriate.
 
124
 */
 
125
static int load_extents_page(struct swap_reader *handle)
 
126
{
 
127
        int error, n;
 
128
 
 
129
        error = read_page(handle->fd, handle->extents, handle->next_extents);
 
130
        if (error)
 
131
                return error;
 
132
        n = page_size / sizeof(struct extent) - 1;
 
133
        handle->next_extents = handle->extents[n].start;
 
134
        memset(handle->extents + n, 0, sizeof(struct extent));
 
135
        handle->cur_extent = handle->extents;
 
136
        handle->cur_offset = handle->cur_extent->start;
 
137
        if (posix_fadvise(handle->fd, handle->cur_offset,
 
138
                        handle->cur_extent->end - handle->cur_offset,
 
139
                        POSIX_FADV_NOREUSE))
 
140
                perror("posix_fadvise");
 
141
        return 0;
 
142
}
 
143
 
 
144
/**
 
145
 *      free_swap_reader - free memory allocated for loading the image
 
146
 *      @handle:        Structure containing pointers to memory buffers to free.
 
147
 */
 
148
static void free_swap_reader(struct swap_reader *handle)
 
149
{
 
150
        if (do_decompress) {
 
151
                freemem(handle->lzo_work_buffer);
 
152
                freemem(handle->read_buffer);
 
153
        }
 
154
        if (do_decrypt)
 
155
                 freemem(handle->decrypt_buffer);
 
156
        freemem(handle->buffer);
 
157
        freemem(handle->extents);
 
158
}
 
159
 
 
160
/**
 
161
 *      init_swap_reader - initialize the structure used for loading the image
 
162
 *      @handle:        Structure to initialize.
 
163
 *      @fd:            File descriptor associated with the swap.
 
164
 *      @start:         Swap location (offset) of the first image page.
 
165
 *      @image_size:    Total size of the image data.
 
166
 *
 
167
 *      Initialize buffers and related fields of @handle and load the first
 
168
 *      array of extents.
 
169
 */
 
170
static int init_swap_reader(struct swap_reader *handle, int fd, loff_t start,
 
171
                            loff_t image_size)
 
172
{
 
173
        int error;
 
174
 
 
175
        if (!start)
 
176
                return -EINVAL;
 
177
 
 
178
        handle->fd = fd;
 
179
        handle->total_size = image_size;
 
180
 
 
181
        handle->extents = getmem(page_size);
 
182
 
 
183
        handle->buffer = getmem(buffer_size);
 
184
        handle->read_buffer = handle->buffer;
 
185
 
 
186
        if (do_decrypt)
 
187
                handle->decrypt_buffer = getmem(page_size);
 
188
 
 
189
        if (do_decompress) {
 
190
                handle->read_buffer = getmem(compress_buf_size);
 
191
                handle->lzo_work_buffer = getmem(LZO1X_1_MEM_COMPRESS);
 
192
        }
 
193
 
 
194
        /* Read the table of extents */
 
195
        handle->next_extents = start;
 
196
        error = load_extents_page(handle);
 
197
        if (error) {
 
198
                free_swap_reader(handle);
 
199
                return error;
 
200
        }
 
201
 
 
202
        if (verify_checksum)
 
203
                md5_init_ctx(&handle->ctx);
 
204
 
 
205
        return 0;
 
206
}
 
207
 
 
208
/**
 
209
 *      find_next_image_page - find the next swap location holding image data
 
210
 */
 
211
static void find_next_image_page(struct swap_reader *handle)
 
212
{
 
213
        int error;
 
214
 
 
215
        handle->cur_offset += page_size;
 
216
        if (handle->cur_offset < handle->cur_extent->end)
 
217
                return;
 
218
        /* We have exhausted the current extent.  Forward to the next one */
 
219
        handle->cur_extent++;
 
220
        if (handle->cur_extent->start < handle->cur_extent->end) {
 
221
                handle->cur_offset = handle->cur_extent->start;
 
222
                if (posix_fadvise(handle->fd, handle->cur_offset,
 
223
                                handle->cur_extent->end - handle->cur_offset,
 
224
                                POSIX_FADV_NOREUSE))
 
225
                        perror("posix_fadvise");
 
226
                return;
 
227
        }
 
228
        /* No more extents.  Load the next extents page. */
 
229
        error = load_extents_page(handle);
 
230
        if (error)
 
231
                handle->cur_offset = 0;
 
232
}
 
233
 
 
234
/**
 
235
 *      load_and_decrypt_page - load a page of data from swap and decrypt it,
 
236
 *                      if necessary.
 
237
 */
 
238
static int load_and_decrypt_page(struct swap_reader *handle, void *dst)
 
239
{
 
240
        int error;
 
241
        void *buf = dst;
 
242
 
 
243
        if (!handle->cur_offset)
 
244
                return -EINVAL;
 
245
 
 
246
        if (do_decrypt)
 
247
                buf = handle->decrypt_buffer;
 
248
 
 
249
        error = read_page(handle->fd, buf, handle->cur_offset);
 
250
 
 
251
#ifdef CONFIG_ENCRYPT
 
252
        if (!error && do_decrypt)
 
253
                error = gcry_cipher_decrypt(cipher_handle, dst, page_size,
 
254
                                                        buf, page_size);
 
255
#endif
 
256
 
 
257
        if (!error) {
 
258
                handle->total_size -= page_size;
 
259
                find_next_image_page(handle);
 
260
        }
 
261
        return error;
 
262
}
 
263
 
 
264
/**
 
265
 *      load_buffer - load (and decrypt, if necessary) a block od data from the
 
266
 *                      swap, decompress it if necessary and store it in the
 
267
 *                      image data buffer.
 
268
 */
 
269
static ssize_t load_buffer(struct swap_reader *handle)
 
270
{
 
271
        void *dst;
 
272
        ssize_t size;
 
273
        int error;
 
274
 
 
275
#ifdef CONFIG_COMPRESS
 
276
        if (do_decompress) {
 
277
                struct buf_block *block = handle->read_buffer;
 
278
                lzo_uint cnt;
 
279
 
 
280
                /* Read the block size from the first block page. */
 
281
                error = load_and_decrypt_page(handle, block);
 
282
                if (error)
 
283
                        return 0;
 
284
                size = page_size;
 
285
                dst = block;
 
286
                dst += page_size;
 
287
                /* Load the rest of the block pages */
 
288
                while (size < block->size + sizeof(size_t)) {
 
289
                        error = load_and_decrypt_page(handle, dst);
 
290
                        if (error)
 
291
                                return 0;
 
292
                        size += page_size;
 
293
                        dst += page_size;
 
294
                }
 
295
                /* Decompress block */
 
296
                error = lzo1x_decompress((lzo_bytep)block->data, block->size,
 
297
                                                handle->buffer, &cnt,
 
298
                                                handle->lzo_work_buffer);
 
299
                if (error)
 
300
                        return 0;
 
301
                size = cnt;
 
302
                goto Checksum;
 
303
        }
 
304
#endif
 
305
        dst = handle->buffer;
 
306
        size = 0;
 
307
        while (size < buffer_size && handle->total_size > 0) {
 
308
                error = load_and_decrypt_page(handle, dst);
 
309
                if (error)
 
310
                        return 0;
 
311
                size += page_size;
 
312
                dst += page_size;
 
313
        }
 
314
 
 
315
 Checksum:
 
316
        if (verify_checksum)
 
317
                md5_process_block(handle->buffer, size, &handle->ctx);
 
318
 
 
319
        return size;
 
320
}
 
321
 
 
322
/**
 
323
 *      load_image - load a hibernation image
 
324
 *      @handle:        Structure containing image information.
 
325
 *      @dev:           Special device file to write image data pages to.
 
326
 *      @nr_pages:      Number of image data pages.
 
327
 */
 
328
static int load_image(struct swap_reader *handle, int dev,
 
329
                      unsigned int nr_pages, int verify_only)
 
330
{
 
331
        unsigned int m, n;
 
332
        ssize_t buf_size;
 
333
        ssize_t ret;
 
334
        void *buf = 0;
 
335
        int error = 0;
 
336
        char message[SPLASH_GENERIC_MESSAGE_SIZE];
 
337
 
 
338
        sprintf(message, "Loading image data pages (%u pages)...", nr_pages);
 
339
        splash.set_caption(message);
 
340
        printf("%s     ", message);
 
341
 
 
342
        m = nr_pages / 100;
 
343
        if (!m)
 
344
                m = 1;
 
345
        n = 0;
 
346
        buf_size = 0;
 
347
        do {
 
348
                if (buf_size <= 0) {
 
349
                        buf_size = load_buffer(handle);
 
350
                        if (buf_size <= 0) {
 
351
                                printf("\n");
 
352
                                return -EIO;
 
353
                        }
 
354
                        buf = handle->buffer;
 
355
                }
 
356
                ret = verify_only ? page_size : write(dev, buf, page_size);
 
357
                if (ret < page_size) {
 
358
                        if (ret < 0)
 
359
                                perror("\nError while writing an image page");
 
360
                        else
 
361
                                printf("\n");
 
362
                        return -EIO;
 
363
                }
 
364
                buf += page_size;
 
365
                buf_size -= page_size;
 
366
 
 
367
                if (!(n % m)) {
 
368
                        printf("\b\b\b\b%3d%%", n / m);
 
369
                        if (n / m > 15)
 
370
                                splash.progress(n / m);
 
371
                }
 
372
                n++;
 
373
        } while (n < nr_pages);
 
374
        if (!error)
 
375
                printf(" done\n");
 
376
        return error;
 
377
}
 
378
 
 
379
static char *print_checksum(char * buf, unsigned char *checksum)
 
380
{
 
381
        int j;
 
382
 
 
383
        for (j = 0; j < 16; j++)
 
384
                buf += sprintf(buf, "%02hhx ", checksum[j]);
 
385
 
 
386
        return buf;
 
387
}
 
388
 
 
389
#ifdef CONFIG_ENCRYPT
 
390
static int decrypt_key(struct image_header_info *header, unsigned char *key,
 
391
                        unsigned char *ivec)
 
392
{
 
393
        gcry_ac_handle_t rsa_hd;
 
394
        gcry_ac_data_t rsa_data_set, key_set;
 
395
        gcry_ac_key_t rsa_priv;
 
396
        gcry_mpi_t mpi;
 
397
        unsigned char *buf, *out, *key_buf, *ivec_buf;
 
398
        struct md5_ctx ctx;
 
399
        struct RSA_data *rsa;
 
400
        gcry_cipher_hd_t sym_hd;
 
401
        int j, ret;
 
402
 
 
403
        rsa = &header->rsa;
 
404
 
 
405
        ret = gcry_ac_open(&rsa_hd, GCRY_AC_RSA, 0);
 
406
        if (ret)
 
407
                return ret;
 
408
 
 
409
        ret = gcry_cipher_open(&sym_hd, PK_CIPHER, GCRY_CIPHER_MODE_CFB,
 
410
                                        GCRY_CIPHER_SECURE);
 
411
        if (ret)
 
412
                goto Free_rsa;
 
413
 
 
414
        key_buf = getmem(PK_KEY_SIZE);
 
415
        ivec_buf = getmem(PK_CIPHER_BLOCK);
 
416
        out = getmem(KEY_TEST_SIZE);
 
417
        do {
 
418
                splash.read_password(password, 0);
 
419
                memset(ivec_buf, 0, PK_CIPHER_BLOCK);
 
420
                strncpy(ivec_buf, password, PK_CIPHER_BLOCK);
 
421
                md5_init_ctx(&ctx);
 
422
                md5_process_bytes(password, strlen(password), &ctx);
 
423
                md5_finish_ctx(&ctx, key_buf);
 
424
                ret = gcry_cipher_setkey(sym_hd, key_buf, PK_KEY_SIZE);
 
425
                if (!ret)
 
426
                        ret = gcry_cipher_setiv(sym_hd, ivec_buf,
 
427
                                                PK_CIPHER_BLOCK);
 
428
 
 
429
                if (!ret)
 
430
                        ret = gcry_cipher_encrypt(sym_hd,
 
431
                                                out, KEY_TEST_SIZE,
 
432
                                                KEY_TEST_DATA, KEY_TEST_SIZE);
 
433
 
 
434
                if (ret) {
 
435
                        fprintf(stderr, "%s: libgcrypt error: %s\n", my_name,
 
436
                                        gcry_strerror(ret));
 
437
                        break;
 
438
                }
 
439
 
 
440
                ret = memcmp(out, rsa->key_test, KEY_TEST_SIZE);
 
441
 
 
442
                if (ret)
 
443
                        printf("%s: Wrong passphrase, try again.\n", my_name);
 
444
        } while (ret);
 
445
 
 
446
        gcry_cipher_close(sym_hd);
 
447
        if (!ret)
 
448
                ret = gcry_cipher_open(&sym_hd, PK_CIPHER,
 
449
                                GCRY_CIPHER_MODE_CFB, GCRY_CIPHER_SECURE);
 
450
        if (ret)
 
451
                goto Free_buffers;
 
452
 
 
453
        ret = gcry_cipher_setkey(sym_hd, key_buf, PK_KEY_SIZE);
 
454
        if (!ret)
 
455
                ret = gcry_cipher_setiv(sym_hd, ivec_buf, PK_CIPHER_BLOCK);
 
456
        if (!ret)
 
457
                ret = gcry_ac_data_new(&rsa_data_set);
 
458
        if (ret)
 
459
                goto Close_cypher;
 
460
 
 
461
        buf = rsa->data;
 
462
        for (j = 0; j < RSA_FIELDS; j++) {
 
463
                size_t s = rsa->size[j];
 
464
 
 
465
                /* We need to decrypt some components */
 
466
                if (j >= RSA_FIELDS_PUB) {
 
467
                        /* We use the in-place decryption */
 
468
                        ret = gcry_cipher_decrypt(sym_hd, buf, s, NULL, 0);
 
469
                        if (ret)
 
470
                                break;
 
471
                }
 
472
 
 
473
                gcry_mpi_scan(&mpi, GCRYMPI_FMT_USG, buf, s, NULL);
 
474
                ret = gcry_ac_data_set(rsa_data_set, GCRY_AC_FLAG_COPY,
 
475
                                        rsa->field[j], mpi);
 
476
                gcry_mpi_release(mpi);
 
477
                if (ret)
 
478
                        break;
 
479
 
 
480
                buf += s;
 
481
        }
 
482
        if (!ret)
 
483
                ret = gcry_ac_key_init(&rsa_priv, rsa_hd,
 
484
                                        GCRY_AC_KEY_SECRET, rsa_data_set);
 
485
        if (ret)
 
486
                goto Destroy_data_set;
 
487
 
 
488
        ret = gcry_ac_data_new(&key_set);
 
489
        if (ret)
 
490
                goto Destroy_key;
 
491
 
 
492
        gcry_mpi_scan(&mpi, GCRYMPI_FMT_USG, header->key.data,
 
493
                        header->key.size, NULL);
 
494
        ret = gcry_ac_data_set(key_set, GCRY_AC_FLAG_COPY, "a", mpi);
 
495
        if (ret)
 
496
                goto Destroy_key_set;
 
497
 
 
498
        gcry_mpi_release(mpi);
 
499
        ret = gcry_ac_data_decrypt(rsa_hd, 0, rsa_priv, &mpi, key_set);
 
500
        if (!ret) {
 
501
                unsigned char *res;
 
502
                size_t s;
 
503
 
 
504
                gcry_mpi_aprint(GCRYMPI_FMT_USG, &res, &s, mpi);
 
505
                if (s == KEY_SIZE + CIPHER_BLOCK) {
 
506
                        memcpy(key, res, KEY_SIZE);
 
507
                        memcpy(ivec, res + KEY_SIZE, CIPHER_BLOCK);
 
508
                } else {
 
509
                        ret = -ENODATA;
 
510
                }
 
511
                gcry_free(res);
 
512
        }
 
513
 
 
514
Destroy_key_set:
 
515
        gcry_mpi_release(mpi);
 
516
        gcry_ac_data_destroy(key_set);
 
517
 
 
518
Destroy_key:
 
519
        gcry_ac_key_destroy(rsa_priv);
 
520
 
 
521
Destroy_data_set:
 
522
        gcry_ac_data_destroy(rsa_data_set);
 
523
 
 
524
Close_cypher:
 
525
        gcry_cipher_close(sym_hd);
 
526
 
 
527
Free_buffers:
 
528
        freemem(out);
 
529
        freemem(ivec_buf);
 
530
        freemem(key_buf);
 
531
 
 
532
Free_rsa:
 
533
        gcry_ac_close(rsa_hd);
 
534
 
 
535
        return ret;
 
536
}
 
537
 
 
538
static int restore_key(struct image_header_info *header)
 
539
{
 
540
        static unsigned char key[KEY_SIZE], ivec[CIPHER_BLOCK];
 
541
        int error;
 
542
 
 
543
        if (header->flags & IMAGE_USE_RSA) {
 
544
                error = decrypt_key(header, key, ivec);
 
545
        } else {
 
546
                int j;
 
547
 
 
548
                splash.read_password(password, 0);
 
549
                encrypt_init(key, ivec, password);
 
550
                for (j = 0; j < CIPHER_BLOCK; j++)
 
551
                        ivec[j] ^= header->salt[j];
 
552
        }
 
553
        if (!error)
 
554
                error = gcry_cipher_open(&cipher_handle,
 
555
                                        IMAGE_CIPHER, GCRY_CIPHER_MODE_CFB,
 
556
                                        GCRY_CIPHER_SECURE);
 
557
        if (!error) {
 
558
                error = gcry_cipher_setkey(cipher_handle, key, KEY_SIZE);
 
559
                if (!error)
 
560
                        error = gcry_cipher_setiv(cipher_handle, ivec,
 
561
                                                        CIPHER_BLOCK);
 
562
                if (error)
 
563
                        gcry_cipher_close(cipher_handle);
 
564
        }
 
565
        return error;
 
566
}
 
567
#endif
 
568
 
 
569
int read_or_verify(int dev, int fd, struct image_header_info *header,
 
570
                   loff_t start, int verify, int test)
 
571
{
 
572
        static struct swap_reader handle;
 
573
        static unsigned char orig_checksum[16], checksum[16];
 
574
        static char csum_buf[48];
 
575
        int error = 0, test_mode = (verify || test);
 
576
 
 
577
        error = read_page(fd, header, start);
 
578
        if (error)
 
579
                return error;
 
580
 
 
581
        if ((header->flags & IMAGE_CHECKSUM) || verify) {
 
582
                memcpy(orig_checksum, header->checksum, 16);
 
583
                print_checksum(csum_buf, orig_checksum);
 
584
                printf("%s: MD5 checksum %s\n", my_name, csum_buf);
 
585
                verify_checksum = 1;
 
586
        }
 
587
        splash.progress(10);
 
588
        if (header->flags & IMAGE_COMPRESSED) {
 
589
                printf("%s: Compressed image\n", my_name);
 
590
#ifdef CONFIG_COMPRESS
 
591
                if (lzo_init() == LZO_E_OK) {
 
592
                        do_decompress = 1;
 
593
                } else {
 
594
                        fprintf(stderr, "%s: Failed to initialize LZO\n",
 
595
                                        my_name);
 
596
                        error = -EFAULT;
 
597
                }
 
598
#else
 
599
                fprintf(stderr, "%s: Compression not supported\n", my_name);
 
600
                error = -EINVAL;
 
601
#endif
 
602
        }
 
603
        if (error)
 
604
                return error;
 
605
 
 
606
        if (header->flags & IMAGE_ENCRYPTED) {
 
607
#ifdef CONFIG_ENCRYPT
 
608
                printf("%s: Encrypted image\n", my_name);
 
609
                error = test_mode ?
 
610
                        gcry_cipher_setiv(cipher_handle, key_data.ivec,
 
611
                                                CIPHER_BLOCK) :
 
612
                        restore_key(header);
 
613
                if (error) {
 
614
                        fprintf(stderr, "%s: libgcrypt error: %s\n", my_name,
 
615
                                        gcry_strerror(error));
 
616
                } else {
 
617
                        do_decrypt = 1;
 
618
                        splash.progress(15);
 
619
                }
 
620
#else
 
621
                fprintf(stderr, "%s: Encryption not supported\n", my_name);
 
622
                error = -EINVAL;
 
623
#endif
 
624
        }
 
625
        if (error)
 
626
                goto Exit_encrypt;
 
627
 
 
628
        error = init_swap_reader(&handle, fd, header->map_start,
 
629
                                        header->image_data_size);
 
630
        if (!error) {
 
631
                struct timeval begin, end;
 
632
                double delta, mb;
 
633
 
 
634
                gettimeofday(&begin, NULL);
 
635
                error = load_image(&handle, dev, header->pages, test_mode);
 
636
                if (!error && verify_checksum) {
 
637
                        md5_finish_ctx(&handle.ctx, checksum);
 
638
                        if (memcmp(orig_checksum, checksum, 16)) {
 
639
                                fprintf(stderr,
 
640
                                        "%s: MD5 checksum does not match\n",
 
641
                                        my_name);
 
642
                                print_checksum(csum_buf, checksum);
 
643
                                fprintf(stderr,
 
644
                                        "%s: Computed MD5 checksum %s\n",
 
645
                                        my_name, csum_buf);
 
646
                                error = -EINVAL;
 
647
                        }
 
648
                }
 
649
                free_swap_reader(&handle);
 
650
                if (error)
 
651
                        goto Exit_encrypt;
 
652
                gettimeofday(&end, NULL);
 
653
 
 
654
                timersub(&end, &begin, &end);
 
655
                delta = end.tv_usec / 1000000.0 + end.tv_sec;
 
656
                mb = (header->pages * (page_size / 1024.0)) / 1024.0;
 
657
 
 
658
                printf("wrote %0.1lf MB in %0.1lf seconds (%0.1lf MB/s)\n",
 
659
                        mb, header->writeout_time, mb / header->writeout_time);
 
660
 
 
661
                printf("read %0.1lf MB in %0.1lf seconds (%0.1lf MB/s)\n",
 
662
                        mb, delta, mb / delta);
 
663
 
 
664
                mb *= 2.0;
 
665
                delta += header->writeout_time;
 
666
                printf("total image i/o: %0.1lf MB in %0.1lf seconds "
 
667
                        "(%0.1lf MB/s)\n", mb, delta, mb / delta);
 
668
 
 
669
                if (do_decompress) {
 
670
                        double real_size = header->image_data_size;
 
671
 
 
672
                        printf("%s: Compression ratio %4.2lf\n", my_name,
 
673
                                real_size / (header->pages * page_size));
 
674
                        real_size /= (1024.0 * 1024.0);
 
675
                        delta -= header->writeout_time;
 
676
 
 
677
                        printf("wrote %0.1lf MB of compressed data in %0.1lf "
 
678
                                "seconds (%0.1lf MB/s)\n", real_size,
 
679
                                header->writeout_time,
 
680
                                real_size / header->writeout_time);
 
681
 
 
682
                        printf("read %0.1lf MB of compressed data in %0.1lf "
 
683
                                "seconds (%0.1lf MB/s)\n", real_size,
 
684
                                delta, real_size / delta);
 
685
 
 
686
                        real_size *= 2.0;
 
687
                        delta += header->writeout_time;
 
688
                        printf("total compressed data i/o: %0.1lf MB in %0.1lf "
 
689
                                "seconds (%0.1lf MB/s)\n", real_size, delta,
 
690
                                real_size / delta);
 
691
                }
 
692
        }
 
693
 
 
694
 Exit_encrypt:
 
695
#ifdef CONFIG_ENCRYPT
 
696
        if (do_decrypt && !test_mode)
 
697
                gcry_cipher_close(cipher_handle);
 
698
#endif
 
699
 
 
700
        return error;
 
701
}