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

« back to all changes in this revision

Viewing changes to resume.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:
29
29
#endif
30
30
 
31
31
#include "swsusp.h"
 
32
#include "memalloc.h"
32
33
#include "config_parser.h"
33
34
#include "md5.h"
34
35
#include "splash.h"
39
40
static loff_t resume_offset;
40
41
static int suspend_loglevel = SUSPEND_LOGLEVEL;
41
42
static int max_loglevel = MAX_LOGLEVEL;
42
 
static char verify_checksum;
43
 
#ifdef CONFIG_COMPRESS
44
 
static char do_decompress;
45
 
#else
46
 
#define do_decompress 0
47
 
#endif
48
 
#ifdef CONFIG_ENCRYPT
49
 
static char do_decrypt;
50
 
#else
51
 
#define do_decrypt 0
52
 
#endif
53
43
static char splash_param;
54
44
#ifdef CONFIG_FBSPLASH
55
45
char fbsplash_theme[MAX_STR_LEN] = "";
56
46
#endif
57
47
static int use_platform_suspend;
58
48
 
59
 
static struct splash splash;
60
 
static char *my_name;
61
 
 
62
49
static struct config_par parameters[] = {
63
50
        {
64
51
                .name = "snapshot device",
140
127
        },
141
128
#endif
142
129
        {
 
130
                .name = "resume pause",
 
131
                .fmt = "%d",
 
132
                .ptr = NULL,
 
133
        },
 
134
#ifdef CONFIG_THREADS
 
135
        {
 
136
                .name = "threads",
 
137
                .fmt = "%c",
 
138
                .ptr = NULL,
 
139
        },
 
140
#endif
 
141
        {
 
142
                .name = "debug test file",
 
143
                .fmt = "%s",
 
144
                .ptr = NULL,
 
145
        },
 
146
        {
 
147
                .name = "debug verify image",
 
148
                .fmt = "%c",
 
149
                .ptr = NULL,
 
150
        },
 
151
#ifdef CONFIG_THREADS
 
152
        {
 
153
                .name = "threads",
 
154
                .fmt = "%c",
 
155
                .ptr = NULL,
 
156
        },
 
157
#endif
 
158
        {
143
159
                .name = NULL,
144
160
                .fmt = NULL,
145
161
                .ptr = NULL,
147
163
        }
148
164
};
149
165
 
150
 
static unsigned int page_size;
151
 
static unsigned int buffer_size;
152
 
static void *mem_pool;
153
 
 
154
 
/**
155
 
 *      read_area - Read data from a swap location.
156
 
 *      @fd:            File handle of the resume partition
157
 
 *      @buf:           Pointer to the area we're reading into
158
 
 *      @offset:        Swap offset of the place to read from
159
 
 *      @size:          The number of bytes to read
160
 
 */
161
 
 
162
 
static int read_area(int fd, void *buf, loff_t offset, unsigned int size)
 
166
static inline int atomic_restore(int dev)
163
167
{
164
 
        int res = 0;
165
 
        ssize_t cnt = 0;
166
 
 
167
 
        if (!offset)
168
 
                return 0;
169
 
 
170
 
        if (lseek(fd, offset, SEEK_SET) == offset)
171
 
                cnt = read(fd, buf, size);
172
 
        if (cnt < (ssize_t)size)
173
 
                res = cnt < 0 ? cnt : -EIO;
174
 
 
175
 
        return res;
 
168
        return ioctl(dev, SNAPSHOT_ATOMIC_RESTORE, 0);
176
169
}
177
170
 
178
 
/*
179
 
 *      The swap_map_handle structure is used for handling the swap map in
180
 
 *      a file-alike way
181
 
 */
182
 
 
183
 
struct swap_map_handle {
184
 
        char *page_buffer;
185
 
        char *read_buffer;
186
 
        struct swap_area *areas;
187
 
        unsigned short areas_per_page;
188
 
        loff_t *next_swap;
189
 
        unsigned int area_size;
190
 
        unsigned int cur_size;
191
 
        unsigned int k;
 
171
static int open_resume_dev(char *resume_dev_name,
 
172
                           struct swsusp_header *swsusp_header)
 
173
{
 
174
        ssize_t size = sizeof(struct swsusp_header);
 
175
        off64_t shift = ((off64_t)resume_offset + 1) * page_size - size;
 
176
        ssize_t ret;
192
177
        int fd;
193
 
        struct md5_ctx ctx;
194
 
#ifdef CONFIG_ENCRYPT
195
 
        char *decrypt_buffer;
196
 
        gcry_cipher_hd_t cipher_handle;
197
 
#endif
198
 
};
199
 
 
200
 
#define READ_AHEAD_SIZE (8*1024*1024)
201
 
 
202
 
/**
203
 
 *      The following functions allow us to read data using a swap map
204
 
 *      in a file-alike way
205
 
 */
206
 
 
207
 
static int fill_buffer(struct swap_map_handle *handle)
208
 
{
209
 
        void *dst = handle->read_buffer;
210
 
        int error;
211
 
 
212
 
        int read_ahead_areas = READ_AHEAD_SIZE/buffer_size;
213
 
        int advise_first, advise_last, i;
214
 
 
215
 
        if (!handle->k) {
216
 
                /* we've got a new map page */
217
 
                advise_first = 0;
218
 
                advise_last  = read_ahead_areas;
219
 
        } else {
220
 
                advise_first = handle->k + read_ahead_areas;
221
 
                advise_last  = advise_first;
222
 
        }
223
 
 
224
 
        for (i = advise_first;
225
 
             i <= advise_last && i < handle->areas_per_page;
226
 
             i++) {
227
 
                if (handle->areas[i].offset == 0)
228
 
                        break;
229
 
 
230
 
                error = posix_fadvise(handle->fd, handle->areas[i].offset,
231
 
                                handle->areas[i].size, POSIX_FADV_NOREUSE);
232
 
                if (error) {
233
 
                        perror("posix_fadvise");
234
 
                        break;
235
 
                }
236
 
        }
237
 
 
238
 
        handle->area_size = handle->areas[handle->k].size;
239
 
        if (handle->area_size > buffer_size)
240
 
                return -ENOMEM;
241
 
#ifdef CONFIG_ENCRYPT
242
 
        if (do_decrypt)
243
 
                dst = handle->decrypt_buffer;
244
 
#endif
245
 
        error = read_area(handle->fd, dst,
246
 
                        handle->areas[handle->k].offset,
247
 
                        handle->area_size);
248
 
#ifdef CONFIG_ENCRYPT
249
 
        if (!error && do_decrypt)
250
 
                error = gcry_cipher_decrypt(handle->cipher_handle,
251
 
                                (void *)handle->read_buffer, handle->area_size,
252
 
                                dst, handle->area_size);
253
 
#endif
254
 
        return error;
255
 
}
256
 
 
257
 
static int init_swap_reader(struct swap_map_handle *handle, int fd, loff_t start, void *buf)
258
 
{
259
 
        int error;
260
 
 
261
 
        if (!start || !buf)
262
 
                return -EINVAL;
263
 
        handle->areas = buf;
264
 
        handle->areas_per_page = (page_size - sizeof(loff_t)) /
265
 
                        sizeof(struct swap_area);
266
 
        handle->next_swap = (loff_t *)(handle->areas + handle->areas_per_page);
267
 
        handle->page_buffer = (char *)buf + page_size;
268
 
        handle->read_buffer = handle->page_buffer + page_size;
269
 
#ifdef CONFIG_ENCRYPT
270
 
        handle->decrypt_buffer = handle->read_buffer + buffer_size;
271
 
#endif
272
 
        error = read_area(fd, handle->areas, start, page_size);
273
 
        if (error)
274
 
                return error;
275
 
        handle->fd = fd;
276
 
        handle->k = 0;
277
 
        error = fill_buffer(handle);
278
 
        if (error)
279
 
                return error;
280
 
        handle->cur_size = 0;
281
 
        if (verify_checksum)
282
 
                md5_init_ctx(&handle->ctx);
283
 
        return 0;
284
 
}
285
 
 
286
 
static int restore(struct swap_map_handle *handle, int disp)
287
 
{
288
 
        struct buf_block *block;
289
 
        void *buf = handle->page_buffer;
290
 
 
291
 
        block = (struct buf_block *)(handle->read_buffer + disp);
292
 
#ifdef CONFIG_COMPRESS
293
 
        if (do_decompress) {
294
 
                int error;
295
 
                lzo_uint cnt = page_size;
296
 
 
297
 
                error = lzo1x_decompress_safe((lzo_bytep)block->data,
298
 
                                                block->size,
299
 
                                                buf, &cnt, NULL);
300
 
                if (error)
301
 
                        return -EINVAL;
302
 
                return cnt == page_size ?
303
 
                                block->size + sizeof(short) : -ENODATA;
304
 
        }
305
 
#endif
306
 
        memcpy(buf, block, page_size);
307
 
        return page_size;
308
 
}
309
 
 
310
 
static int swap_read_page(struct swap_map_handle *handle)
311
 
{
312
 
        loff_t offset;
313
 
        size_t size;
314
 
        int error = 0;
315
 
 
316
 
        if (handle->cur_size < handle->area_size) {
317
 
                /* Get the data from the read buffer */
318
 
                size = restore(handle, handle->cur_size);
319
 
                if (size < 0)
320
 
                        return size;
321
 
                handle->cur_size += size;
322
 
                goto MD5;
323
 
        }
324
 
 
325
 
        /* There are no more data in the read buffer.  Read more */
326
 
        if (++handle->k >= handle->areas_per_page) {
327
 
                handle->k = 0;
328
 
                offset = *handle->next_swap;
329
 
                error = offset ?
330
 
                        read_area(handle->fd, handle->areas, offset, page_size)
331
 
                        : -EINVAL;
332
 
        }
333
 
        if (!error)
334
 
                error = fill_buffer(handle);
335
 
        if (error)
336
 
                return error;
337
 
 
338
 
        size = restore(handle, 0);
339
 
        if (size < 0)
340
 
                return size;
341
 
        handle->cur_size = size;
342
 
 
343
 
MD5:
344
 
        if (verify_checksum)
345
 
                md5_process_block(handle->page_buffer, page_size, &handle->ctx);
346
 
 
347
 
        return 0;
348
 
}
349
 
 
350
 
/**
351
 
 *      load_image - load the image using the swap map handle
352
 
 *      @handle and the snapshot handle @snapshot
353
 
 *      (assume there are @nr_pages pages to load)
354
 
 */
355
 
 
356
 
static int load_image(struct swap_map_handle *handle, int dev,
357
 
                      unsigned int nr_pages)
358
 
{
359
 
        unsigned int m, n;
360
 
        int ret;
361
 
        int error = 0;
362
 
        char message[SPLASH_GENERIC_MESSAGE_SIZE];
363
 
 
364
 
        sprintf(message, "Loading image data pages (%u pages)...", nr_pages);
365
 
        splash.set_caption(message);
366
 
        printf("%s     ", message);
367
 
 
368
 
        m = nr_pages / 100;
369
 
        if (!m)
370
 
                m = 1;
371
 
        n = 0;
372
 
        do {
373
 
                error = swap_read_page(handle);
374
 
                if (error)
375
 
                        break;
376
 
                ret = write(dev, handle->page_buffer, page_size);
377
 
                if (ret < (int)page_size) {
378
 
                        error = ret < 0 ? -errno : -ENOSPC;
379
 
                        break;
380
 
                }
381
 
                if (!(n % m)) {
382
 
                        printf("\b\b\b\b%3d%%", n / m);
383
 
                        if (n / m > 15)
384
 
                                splash.progress(n / m);
385
 
                }
386
 
                n++;
387
 
        } while (n < nr_pages);
388
 
        if (!error)
389
 
                printf(" done\n");
390
 
        return error;
391
 
}
392
 
 
393
 
static char *print_checksum(char * buf, unsigned char *checksum)
394
 
{
395
 
        int j;
396
 
 
397
 
        for (j = 0; j < 16; j++)
398
 
                buf += sprintf(buf, "%02hhx ", checksum[j]);
399
 
 
400
 
        return buf;
401
 
}
402
 
 
403
 
#ifdef CONFIG_ENCRYPT
404
 
static int decrypt_key(struct swsusp_info *header, unsigned char *key,
405
 
                        unsigned char *ivec, void *buffer)
406
 
{
407
 
        gcry_ac_handle_t rsa_hd;
408
 
        gcry_ac_data_t rsa_data_set, key_set;
409
 
        gcry_ac_key_t rsa_priv;
410
 
        gcry_mpi_t mpi;
411
 
        unsigned char *buf, *out, *key_buf, *ivec_buf;
412
 
        char *pass_buf;
413
 
        struct md5_ctx ctx;
414
 
        struct RSA_data *rsa;
415
 
        gcry_cipher_hd_t sym_hd;
416
 
        int j, ret = 0;
417
 
 
418
 
        rsa = &header->rsa;
419
 
 
420
 
        ret = gcry_ac_open(&rsa_hd, GCRY_AC_RSA, 0);
421
 
        if (ret)
422
 
                return ret;
423
 
 
424
 
        if (!ret)
425
 
                ret = gcry_cipher_open(&sym_hd, PK_CIPHER,
426
 
                                GCRY_CIPHER_MODE_CFB, GCRY_CIPHER_SECURE);
427
 
 
428
 
        if (ret)
429
 
                goto Free_rsa;
430
 
 
431
 
        pass_buf = buffer;
432
 
        key_buf = (unsigned char *)pass_buf + PASS_SIZE;
433
 
        ivec_buf = key_buf + PK_KEY_SIZE;
434
 
        out = ivec_buf + PK_CIPHER_BLOCK;
435
 
        do {
436
 
                splash.read_password(pass_buf, 0);
437
 
                memset(ivec_buf, 0, PK_CIPHER_BLOCK);
438
 
                strncpy((char *)ivec_buf, pass_buf, PK_CIPHER_BLOCK);
439
 
                md5_init_ctx(&ctx);
440
 
                md5_process_bytes(pass_buf, strlen(pass_buf), &ctx);
441
 
                md5_finish_ctx(&ctx, key_buf);
442
 
                ret = gcry_cipher_setkey(sym_hd, key_buf, PK_KEY_SIZE);
443
 
                if (!ret)
444
 
                        ret = gcry_cipher_setiv(sym_hd, ivec_buf,
445
 
                                                PK_CIPHER_BLOCK);
446
 
 
447
 
                if (!ret)
448
 
                        ret = gcry_cipher_encrypt(sym_hd,
449
 
                                        out, KEY_TEST_SIZE,
450
 
                                        KEY_TEST_DATA, KEY_TEST_SIZE);
451
 
 
452
 
                if (ret)
453
 
                        break;
454
 
 
455
 
                ret = memcmp(out, rsa->key_test, KEY_TEST_SIZE);
456
 
 
457
 
                if (ret)
458
 
                        printf("%s: Wrong passphrase, try again.\n", my_name);
459
 
        } while (ret);
460
 
 
461
 
        gcry_cipher_close(sym_hd);
462
 
        if (!ret)
463
 
                ret = gcry_cipher_open(&sym_hd, PK_CIPHER,
464
 
                                GCRY_CIPHER_MODE_CFB, GCRY_CIPHER_SECURE);
465
 
        if (ret)
466
 
                goto Free_rsa;
467
 
 
468
 
        ret = gcry_cipher_setkey(sym_hd, key_buf, PK_KEY_SIZE);
469
 
        if (!ret)
470
 
                ret = gcry_cipher_setiv(sym_hd, ivec_buf, PK_CIPHER_BLOCK);
471
 
        if (!ret)
472
 
                ret = gcry_ac_data_new(&rsa_data_set);
473
 
        if (ret)
474
 
                goto Close_cypher;
475
 
 
476
 
        buf = rsa->data;
477
 
        for (j = 0; j < RSA_FIELDS; j++) {
478
 
                size_t s = rsa->size[j];
479
 
 
480
 
                /* We need to decrypt some components */
481
 
                if (j >= RSA_FIELDS_PUB) {
482
 
                        /* We use the in-place decryption */
483
 
                        ret = gcry_cipher_decrypt(sym_hd, buf, s, NULL, 0);
484
 
                        if (ret)
485
 
                                break;
486
 
                }
487
 
 
488
 
                gcry_mpi_scan(&mpi, GCRYMPI_FMT_USG, buf, s, NULL);
489
 
                ret = gcry_ac_data_set(rsa_data_set, GCRY_AC_FLAG_COPY,
490
 
                                        rsa->field[j], mpi);
491
 
                gcry_mpi_release(mpi);
492
 
                if (ret)
493
 
                        break;
494
 
 
495
 
                buf += s;
496
 
        }
497
 
        if (!ret)
498
 
                ret = gcry_ac_key_init(&rsa_priv, rsa_hd,
499
 
                                        GCRY_AC_KEY_SECRET, rsa_data_set);
500
 
        if (ret)
501
 
                goto Destroy_data_set;
502
 
 
503
 
        ret = gcry_ac_data_new(&key_set);
504
 
        if (ret)
505
 
                goto Destroy_key;
506
 
 
507
 
        gcry_mpi_scan(&mpi, GCRYMPI_FMT_USG, header->key.data,
508
 
                        header->key.size, NULL);
509
 
        ret = gcry_ac_data_set(key_set, GCRY_AC_FLAG_COPY, "a", mpi);
510
 
        if (ret)
511
 
                goto Destroy_key_set;
512
 
 
513
 
        gcry_mpi_release(mpi);
514
 
        ret = gcry_ac_data_decrypt(rsa_hd, 0, rsa_priv, &mpi, key_set);
515
 
        if (!ret) {
516
 
                unsigned char *res;
517
 
                size_t s;
518
 
 
519
 
                gcry_mpi_aprint(GCRYMPI_FMT_USG, &res, &s, mpi);
520
 
                if (s == KEY_SIZE + CIPHER_BLOCK) {
521
 
                        memcpy(key, res, KEY_SIZE);
522
 
                        memcpy(ivec, res + KEY_SIZE, CIPHER_BLOCK);
523
 
                } else {
524
 
                        ret = -ENODATA;
525
 
                }
526
 
                gcry_free(res);
527
 
        }
528
 
 
529
 
Destroy_key_set:
530
 
        gcry_mpi_release(mpi);
531
 
        gcry_ac_data_destroy(key_set);
532
 
 
533
 
Destroy_key:
534
 
        gcry_ac_key_destroy(rsa_priv);
535
 
 
536
 
Destroy_data_set:
537
 
        gcry_ac_data_destroy(rsa_data_set);
538
 
 
539
 
Close_cypher:
540
 
        gcry_cipher_close(sym_hd);
541
 
 
542
 
Free_rsa:
543
 
        gcry_ac_close(rsa_hd);
544
 
 
545
 
        return ret;
546
 
}
547
 
#endif
548
 
 
549
 
static int open_resume_dev(char *resume_dev_name, 
550
 
                            struct swsusp_header *swsusp_header)
551
 
{
552
 
        unsigned int size = sizeof(struct swsusp_header);
553
 
        unsigned int shift = (resume_offset + 1) * page_size - size;
554
 
        int fd, ret;
555
178
 
556
179
        fd = open(resume_dev_name, O_RDWR);
557
180
        if (fd < 0) {
560
183
                                my_name);
561
184
                return ret;
562
185
        }
563
 
        if (lseek(fd, shift, SEEK_SET) != shift)
 
186
        if (lseek64(fd, shift, SEEK_SET) != shift)
564
187
                return -EIO;
565
188
        ret = read(fd, swsusp_header, size);
566
189
        if (ret == size) {
576
199
        return fd;
577
200
}
578
201
 
579
 
static int read_image(int dev, int fd, struct swsusp_header *swsusp_header)
580
 
{
581
 
        static struct swap_map_handle handle;
582
 
        static unsigned char orig_checksum[16], checksum[16];
583
 
        int ret, error = 0;
584
 
        struct swsusp_info *header = mem_pool;
585
 
        char *buffer = (char *)mem_pool + page_size;
586
 
        unsigned int nr_pages = 0;
587
 
        unsigned int size = sizeof(struct swsusp_header);
588
 
        unsigned int shift = (resume_offset + 1) * page_size - size;
 
202
static void pause_resume(int pause)
 
203
{
 
204
        struct termios newtrm, savedtrm;
 
205
        char message[SPLASH_GENERIC_MESSAGE_SIZE];
 
206
        int wait_possible = !splash.prepare_abort(&savedtrm, &newtrm);
 
207
 
 
208
        if (!wait_possible)
 
209
                pause = -1;
 
210
 
 
211
        sprintf(message, "Image successfully loaded\nPress " ENTER_KEY_NAME
 
212
                        " to continue\n");
 
213
        splash.set_caption(message);
 
214
        printf("%s: %s", my_name, message);
 
215
 
 
216
        if (pause > 0)
 
217
                printf("%s: Continuing automatically in %2d seconds",
 
218
                        my_name, pause);
 
219
 
 
220
        while (pause) {
 
221
                if (splash.key_pressed() == ENTER_KEY_CODE)
 
222
                        break;
 
223
                sleep(1);
 
224
                if (pause > 0)
 
225
                        printf("\b\b\b\b\b\b\b\b\b\b%2d seconds", --pause);
 
226
        }
 
227
        printf("\n");
 
228
 
 
229
        if (wait_possible)
 
230
                splash.restore_abort(&savedtrm);
 
231
}
 
232
 
 
233
static void reboot_question(char *message)
 
234
{
589
235
        char c;
590
 
 
591
 
        error = read_area(fd, header, swsusp_header->image, page_size);
592
 
        if (error)
593
 
                goto Reboot_question;
594
 
 
595
 
        if (header->image_flags & PLATFORM_SUSPEND)
596
 
                use_platform_suspend = 1;
597
 
 
598
 
        if (header->image_flags & IMAGE_CHECKSUM) {
599
 
                memcpy(orig_checksum, header->checksum, 16);
600
 
                print_checksum(buffer, orig_checksum);
601
 
                printf("%s: MD5 checksum %s\n", my_name, buffer);
602
 
                verify_checksum = 1;
603
 
        }
604
 
        splash.progress(10);
605
 
        if (header->image_flags & IMAGE_COMPRESSED) {
606
 
                printf("%s: Compressed image\n", my_name);
607
 
#ifdef CONFIG_COMPRESS
608
 
                if (lzo_init() == LZO_E_OK) {
609
 
                        do_decompress = 1;
610
 
                } else {
611
 
                        fprintf(stderr, "%s: Failed to initialize LZO\n",
612
 
                                        my_name);
613
 
                        error = -EFAULT;
614
 
                }
615
 
#else
616
 
                fprintf(stderr, "%s: Compression not supported\n", my_name);
617
 
                error = -EINVAL;
618
 
#endif
619
 
        }
620
 
        if (error)
621
 
                goto Reboot_question;
622
 
 
623
 
        if (header->image_flags & IMAGE_ENCRYPTED) {
624
 
#ifdef CONFIG_ENCRYPT
625
 
                static unsigned char key[KEY_SIZE], ivec[CIPHER_BLOCK];
626
 
 
627
 
                printf("%s: Encrypted image\n", my_name);
628
 
                if (header->image_flags & IMAGE_USE_RSA) {
629
 
                        error = decrypt_key(header, key, ivec, buffer);
630
 
                } else {
631
 
                        int j;
632
 
 
633
 
                        splash.read_password(buffer, 0);
634
 
                        encrypt_init(key, ivec, buffer);
635
 
                        for (j = 0; j < CIPHER_BLOCK; j++)
636
 
                                ivec[j] ^= header->salt[j];
637
 
                }
638
 
                splash.progress(15);
639
 
                if (!error)
640
 
                        error = gcry_cipher_open(&handle.cipher_handle,
641
 
                                IMAGE_CIPHER, GCRY_CIPHER_MODE_CFB,
642
 
                                GCRY_CIPHER_SECURE);
643
 
                if (!error) {
644
 
                        do_decrypt = 1;
645
 
                        error = gcry_cipher_setkey(handle.cipher_handle,
646
 
                                                key, KEY_SIZE);
647
 
                }
648
 
                if (!error)
649
 
                        error = gcry_cipher_setiv(handle.cipher_handle,
650
 
                                                ivec, CIPHER_BLOCK);
651
 
 
652
 
                if (error) {
653
 
                        if (do_decrypt)
654
 
                                gcry_cipher_close(handle.cipher_handle);
655
 
                        do_decrypt = 0;
656
 
                        fprintf(stderr, "%s: libgcrypt error: %s\n",
657
 
                                        my_name,
658
 
                                        gcry_strerror(error));
659
 
                }
660
 
#else
661
 
                fprintf(stderr, "%s: Encryption not supported\n",
662
 
                                my_name);
663
 
                error = -EINVAL;
664
 
#endif
665
 
        }
666
 
 
667
 
        if (error)
668
 
                goto Reboot_question;
669
 
 
670
 
        error = init_swap_reader(&handle, fd, header->map_start, buffer);
671
 
        nr_pages = header->pages - 1;
672
 
        ret = write(dev, header, page_size);
673
 
        if (ret < (int)page_size)
674
 
                error = ret < 0 ? ret : -EIO;
675
 
 
676
 
        if (!error) {
677
 
                struct timeval begin, end;
678
 
                double delta, mb = header->size / (1024.0 * 1024.0);
679
 
 
680
 
                gettimeofday(&begin, NULL);
681
 
                error = load_image(&handle, dev, nr_pages);
682
 
                gettimeofday(&end, NULL);
683
 
 
684
 
                timersub(&end, &begin, &end);
685
 
                delta = end.tv_usec / 1000000.0 + end.tv_sec;
686
 
 
687
 
                printf("wrote %0.1lf MB in %0.1lf seconds (%0.1lf MB/s)\n",
688
 
                        mb, header->writeout_time, mb / header->writeout_time);
689
 
 
690
 
                printf("read %0.1lf MB in %0.1lf seconds (%0.1lf MB/s)\n",
691
 
                        mb, delta, mb / delta);
692
 
 
693
 
                mb *= 2.0;
694
 
                delta += header->writeout_time;
695
 
                printf("total image i/o %0.1lf MB in %0.1lf seconds (%0.1lf MB/s)\n",
696
 
                        mb, delta, mb / delta);
697
 
        }
698
 
 
699
 
Reboot_question:
 
236
        char full_message[SPLASH_GENERIC_MESSAGE_SIZE];
 
237
        char *warning =
 
238
                "\n\tYou can now boot the system and lose the saved state\n"
 
239
                "\tor reboot and try again.\n\n"
 
240
                "\t[Notice that if you decide to reboot, you MUST NOT mount\n"
 
241
                "\tany filesystems before a successful resume.\n"
 
242
                "\tResuming after some filesystems have been mounted\n"
 
243
                "\twill badly damage these filesystems.]\n\n"
 
244
                "\tDo you want to continue booting (Y/n)?";
 
245
 
 
246
        snprintf(full_message, SPLASH_GENERIC_MESSAGE_SIZE, "%s\n%s",
 
247
                        message, warning);
 
248
        c = splash.dialog(full_message);
 
249
        if (c == 'n' || c == 'N') {
 
250
                reboot();
 
251
                fprintf(stderr, "%s: Reboot failed, please reboot manually.\n",
 
252
                        my_name);
 
253
                while(1)
 
254
                        sleep(10);
 
255
        }
 
256
}
 
257
 
 
258
static int read_image(int dev, int fd, loff_t start)
 
259
{
 
260
        struct image_header_info *header;
 
261
        int error;
 
262
 
 
263
        header = getmem(page_size);
 
264
 
 
265
        error = read_or_verify(dev, fd, header, start, 0, 0);
700
266
        if (error) {
701
 
                c = splash.dialog(
 
267
                reboot_question(
702
268
                        "\nThe system snapshot image could not be read.\n\n"
703
 
#ifdef CONFIG_ENCRYPT
704
 
                        "\tThis might be a result of booting a wrong kernel\n"
705
 
                        "\tor typing in a wrong passphrase.\n\n"
706
 
#else
707
 
                        "\tThis might be a result of booting a wrong kernel.\n\n"
708
 
#endif
709
 
                        "\tYou can continue to boot the system and lose the saved state\n"
710
 
                        "\tor reboot and try again.\n\n"
711
 
                        "\t[Notice that you may not mount any filesystem between\n"
712
 
                        "\tnow and successful resume. That would badly damage\n"
713
 
                        "\taffected filesystems.]\n\n"
714
 
                        "\tDo you want to continue boot (Y/n)? ");
715
 
                ret = (c == 'n' || c == 'N');
716
 
                if (ret) {
717
 
                        close(fd);
718
 
                        reboot();
719
 
                        fprintf(stderr, "%s: Reboot failed, please reboot manually.\n",
720
 
                                        my_name);
721
 
                       while(1)
722
 
                           sleep(1);
723
 
                }
724
 
        }
725
 
 
726
 
        /* I guess this is after the 'continue boot'-question because
727
 
         * there is no sense in not reseting the signature on error */
728
 
        if (!error && verify_checksum) {
729
 
                md5_finish_ctx(&handle.ctx, checksum);
730
 
                if (memcmp(orig_checksum, checksum, 16)) {
731
 
                        fprintf(stderr,"%s: MD5 checksum does not match\n",
732
 
                                        my_name);
733
 
                        print_checksum(buffer, checksum);
734
 
                        fprintf(stderr, "%s: Computed MD5 checksum %s\n",
735
 
                                        my_name, buffer);
736
 
                        error = -EINVAL;
737
 
                }
738
 
        }
 
269
                        "\tThis might be a result of booting a wrong "
 
270
                        "kernel.\n"
 
271
                );
 
272
        } else {
 
273
                if (header->flags & PLATFORM_SUSPEND)
 
274
                        use_platform_suspend = 1;
 
275
        }
 
276
 
 
277
        if (error) {
 
278
                char message[SPLASH_GENERIC_MESSAGE_SIZE];
 
279
 
 
280
                sprintf(message, "%s: Error %d loading the image\nPress "
 
281
                        ENTER_KEY_NAME " to continue\n", my_name, error);
 
282
                splash.dialog(message);
 
283
        } else if (header->resume_pause != 0) {
 
284
                pause_resume(header->resume_pause);
 
285
        } else {
 
286
                printf("%s: Image successfully loaded\n", my_name);
 
287
        }
 
288
 
 
289
        freemem(header);
 
290
 
 
291
        return error;
 
292
}
 
293
 
 
294
static int reset_signature(int fd, struct swsusp_header *swsusp_header)
 
295
{
 
296
        ssize_t ret, size = sizeof(struct swsusp_header);
 
297
        off64_t shift = ((off64_t)resume_offset + 1) * page_size - size;
 
298
        int error = 0;
 
299
 
739
300
        /* Reset swap signature now */
740
301
        memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10);
741
 
        if (lseek(fd, shift, SEEK_SET) != shift) {
 
302
 
 
303
        if (lseek64(fd, shift, SEEK_SET) != shift) {
 
304
                fprintf(stderr, "%s: Could not lseek() to the swap header",
 
305
                                my_name);
 
306
                return -EIO;
 
307
        }
 
308
 
 
309
        ret = write(fd, swsusp_header, size);
 
310
        if (ret == size) {
 
311
                fsync(fd);
 
312
        } else {
 
313
                fprintf(stderr, "%s: Could not restore the swap header",
 
314
                                my_name);
742
315
                error = -EIO;
743
 
        } else {
744
 
                ret = write(fd, swsusp_header, size);
745
 
                if (ret != size) {
746
 
                        error = ret < 0 ? -errno : -EIO;
747
 
                        fprintf(stderr,
748
 
                                "%s: Could not restore the partition header\n",
749
 
                                my_name);
750
 
                }
751
 
        }
752
 
 
753
 
        fsync(fd);
754
 
        close(fd);
755
 
#ifdef CONFIG_ENCRYPT
756
 
        if (do_decrypt)
757
 
                gcry_cipher_close(handle.cipher_handle);
758
 
#endif
759
 
 
760
 
        if (error) {
761
 
                sprintf(buffer, "%s: Error %d loading the image\n"
762
 
                        "\nPress ENTER to continue\n", my_name, error);
763
 
                splash.dialog(buffer);
764
 
        } else {
765
 
                printf("%s: Image successfully loaded\n", my_name);
766
316
        }
767
317
 
768
318
        return error;
887
437
        else
888
438
                splash_param = SPL_RESUME;
889
439
 
890
 
        page_size = getpagesize();
891
 
        buffer_size = BUFFER_PAGES * page_size;
 
440
        get_page_and_buffer_sizes();
 
441
 
 
442
        mem_size = 2 * page_size + buffer_size;
892
443
#ifdef CONFIG_ENCRYPT
893
444
        printf("%s: libgcrypt version: %s\n", my_name,
894
445
                gcry_check_version(NULL));
895
446
        gcry_control(GCRYCTL_INIT_SECMEM, page_size, 0);
896
 
        mem_size = 3 * page_size + 2 * buffer_size;
897
 
#else
898
 
        mem_size = 3 * page_size + buffer_size;
899
 
#endif
900
 
        mem_pool = malloc(mem_size);
901
 
        if (!mem_pool) {
902
 
                error = errno;
 
447
        mem_size += page_size;
 
448
#endif
 
449
#ifdef CONFIG_COMPRESS
 
450
        /*
 
451
         * The formula below follows from the worst-case expansion calculation
 
452
         * for LZO1 (size / 16 + 67) and the fact that the size of the
 
453
         * compressed data must be stored in the buffer (sizeof(size_t)).
 
454
         */
 
455
        compress_buf_size = buffer_size +
 
456
                        round_up_page_size((buffer_size >> 4) + 67 +
 
457
                                                sizeof(size_t));
 
458
        mem_size += compress_buf_size +
 
459
                        round_up_page_size(LZO1X_1_MEM_COMPRESS);
 
460
#endif
 
461
 
 
462
        error = init_memalloc(page_size, mem_size);
 
463
        if (error) {
903
464
                fprintf(stderr, "%s: Could not allocate memory\n", my_name);
904
465
                return error;
905
466
        }
953
514
        splash_prepare(&splash, splash_param);
954
515
        splash.progress(5);
955
516
 
956
 
        error = read_image(dev, resume_dev, &swsusp_header);
 
517
        error = read_image(dev, resume_dev, swsusp_header.image);
957
518
        if (error) {
 
519
                error = -error;
958
520
                fprintf(stderr, "%s: Could not read the image\n", my_name);
959
 
                error = -error;
960
 
                goto Close_splash;
961
 
        }
962
 
 
963
 
        if (freeze(dev)) {
 
521
        } else if (freeze(dev)) {
964
522
                error = errno;
965
 
                fprintf(stderr, "%s: Could not freeze processes\n", my_name);
 
523
                reboot_question("Processes could not be frozen, "
 
524
                                "cannot continue resuming.\n");
 
525
        }
 
526
 
 
527
        if (reset_signature(resume_dev, &swsusp_header))
 
528
                fprintf(stderr, "%s: Swap signature has not been restored.\n"
 
529
                        "\tRun mkswap on the resume partition/file.\n",
 
530
                        my_name);
 
531
 
 
532
        close(resume_dev);
 
533
 
 
534
        if (error)
966
535
                goto Close_splash;
967
 
        }
 
536
 
968
537
        if (use_platform_suspend) {
969
 
                int ret = platform_prepare(dev);
970
 
                if (ret < 0) {
971
 
                        fprintf(stderr, "%s: pm_ops->prepare returned "
972
 
                                        "error %d\n", my_name, ret);
 
538
                int err = platform_prepare(dev);
 
539
 
 
540
                if (err) {
 
541
                        fprintf(stderr, "%s: Unable to use platform "
 
542
                                        "hibernation support, error code %d\n",
 
543
                                        my_name, err);
973
544
                        use_platform_suspend = 0;
974
545
                }
975
546
        }
992
563
 
993
564
        close_printk();
994
565
 
995
 
        free(mem_pool);
 
566
        free_memalloc();
996
567
 
997
568
        return error;
998
569
}