4
* A simple user space resume handler for swsusp.
6
* Copyright (C) 2005 Rafael J. Wysocki <rjw@sisk.pl>
8
* This file is released under the GPLv2.
13
#include <sys/types.h>
15
#include <sys/ioctl.h>
27
#ifdef CONFIG_COMPRESS
28
#include <lzo/lzo1x.h>
32
#include "config_parser.h"
37
static char snapshot_dev_name[MAX_STR_LEN] = SNAPSHOT_DEVICE;
38
static char resume_dev_name[MAX_STR_LEN] = RESUME_DEVICE;
39
static loff_t resume_offset;
40
static int suspend_loglevel = SUSPEND_LOGLEVEL;
41
static int max_loglevel = MAX_LOGLEVEL;
42
static char verify_checksum;
43
#ifdef CONFIG_COMPRESS
44
static char do_decompress;
46
#define do_decompress 0
49
static char do_decrypt;
53
static char splash_param;
54
#ifdef CONFIG_FBSPLASH
55
char fbsplash_theme[MAX_STR_LEN] = "";
57
static int use_platform_suspend;
59
static struct splash splash;
62
static struct config_par parameters[] = {
64
.name = "snapshot device",
66
.ptr = snapshot_dev_name,
70
.name = "resume device",
72
.ptr = resume_dev_name,
76
.name = "resume offset",
78
.ptr = &resume_offset,
81
.name = "suspend loglevel",
83
.ptr = &suspend_loglevel,
86
.name = "max loglevel",
96
.name = "compute checksum",
100
#ifdef CONFIG_COMPRESS
107
#ifdef CONFIG_ENCRYPT
114
.name = "RSA key file",
120
.name = "early writeout",
127
.ptr = &splash_param,
130
.name = "shutdown method",
134
#ifdef CONFIG_FBSPLASH
136
.name = "fbsplash theme",
138
.ptr = fbsplash_theme,
150
static unsigned int page_size;
151
static unsigned int buffer_size;
152
static void *mem_pool;
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
162
static int read_area(int fd, void *buf, loff_t offset, unsigned int size)
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;
179
* The swap_map_handle structure is used for handling the swap map in
183
struct swap_map_handle {
186
struct swap_area *areas;
187
unsigned short areas_per_page;
189
unsigned int area_size;
190
unsigned int cur_size;
194
#ifdef CONFIG_ENCRYPT
195
char *decrypt_buffer;
196
gcry_cipher_hd_t cipher_handle;
200
#define READ_AHEAD_SIZE (8*1024*1024)
203
* The following functions allow us to read data using a swap map
204
* in a file-alike way
207
static int fill_buffer(struct swap_map_handle *handle)
209
void *dst = handle->read_buffer;
212
int read_ahead_areas = READ_AHEAD_SIZE/buffer_size;
213
int advise_first, advise_last, i;
216
/* we've got a new map page */
218
advise_last = read_ahead_areas;
220
advise_first = handle->k + read_ahead_areas;
221
advise_last = advise_first;
224
for (i = advise_first;
225
i <= advise_last && i < handle->areas_per_page;
227
if (handle->areas[i].offset == 0)
230
error = posix_fadvise(handle->fd, handle->areas[i].offset,
231
handle->areas[i].size, POSIX_FADV_NOREUSE);
233
perror("posix_fadvise");
238
handle->area_size = handle->areas[handle->k].size;
239
if (handle->area_size > buffer_size)
241
#ifdef CONFIG_ENCRYPT
243
dst = handle->decrypt_buffer;
245
error = read_area(handle->fd, dst,
246
handle->areas[handle->k].offset,
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);
257
static int init_swap_reader(struct swap_map_handle *handle, int fd, loff_t start, void *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;
272
error = read_area(fd, handle->areas, start, page_size);
277
error = fill_buffer(handle);
280
handle->cur_size = 0;
282
md5_init_ctx(&handle->ctx);
286
static int restore(struct swap_map_handle *handle, int disp)
288
struct buf_block *block;
289
void *buf = handle->page_buffer;
291
block = (struct buf_block *)(handle->read_buffer + disp);
292
#ifdef CONFIG_COMPRESS
295
lzo_uint cnt = page_size;
297
error = lzo1x_decompress_safe((lzo_bytep)block->data,
302
return cnt == page_size ?
303
block->size + sizeof(short) : -ENODATA;
306
memcpy(buf, block, page_size);
310
static int swap_read_page(struct swap_map_handle *handle)
316
if (handle->cur_size < handle->area_size) {
317
/* Get the data from the read buffer */
318
size = restore(handle, handle->cur_size);
321
handle->cur_size += size;
325
/* There are no more data in the read buffer. Read more */
326
if (++handle->k >= handle->areas_per_page) {
328
offset = *handle->next_swap;
330
read_area(handle->fd, handle->areas, offset, page_size)
334
error = fill_buffer(handle);
338
size = restore(handle, 0);
341
handle->cur_size = size;
345
md5_process_block(handle->page_buffer, page_size, &handle->ctx);
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)
356
static int load_image(struct swap_map_handle *handle, int dev,
357
unsigned int nr_pages)
362
char message[SPLASH_GENERIC_MESSAGE_SIZE];
364
sprintf(message, "Loading image data pages (%u pages)...", nr_pages);
365
splash.set_caption(message);
366
printf("%s ", message);
373
error = swap_read_page(handle);
376
ret = write(dev, handle->page_buffer, page_size);
377
if (ret < (int)page_size) {
378
error = ret < 0 ? -errno : -ENOSPC;
382
printf("\b\b\b\b%3d%%", n / m);
384
splash.progress(n / m);
387
} while (n < nr_pages);
393
static char *print_checksum(char * buf, unsigned char *checksum)
397
for (j = 0; j < 16; j++)
398
buf += sprintf(buf, "%02hhx ", checksum[j]);
403
#ifdef CONFIG_ENCRYPT
404
static int decrypt_key(struct swsusp_info *header, unsigned char *key,
405
unsigned char *ivec, void *buffer)
407
gcry_ac_handle_t rsa_hd;
408
gcry_ac_data_t rsa_data_set, key_set;
409
gcry_ac_key_t rsa_priv;
411
unsigned char *buf, *out, *key_buf, *ivec_buf;
414
struct RSA_data *rsa;
415
gcry_cipher_hd_t sym_hd;
420
ret = gcry_ac_open(&rsa_hd, GCRY_AC_RSA, 0);
425
ret = gcry_cipher_open(&sym_hd, PK_CIPHER,
426
GCRY_CIPHER_MODE_CFB, GCRY_CIPHER_SECURE);
432
key_buf = (unsigned char *)pass_buf + PASS_SIZE;
433
ivec_buf = key_buf + PK_KEY_SIZE;
434
out = ivec_buf + PK_CIPHER_BLOCK;
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);
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);
444
ret = gcry_cipher_setiv(sym_hd, ivec_buf,
448
ret = gcry_cipher_encrypt(sym_hd,
450
KEY_TEST_DATA, KEY_TEST_SIZE);
455
ret = memcmp(out, rsa->key_test, KEY_TEST_SIZE);
458
printf("%s: Wrong passphrase, try again.\n", my_name);
461
gcry_cipher_close(sym_hd);
463
ret = gcry_cipher_open(&sym_hd, PK_CIPHER,
464
GCRY_CIPHER_MODE_CFB, GCRY_CIPHER_SECURE);
468
ret = gcry_cipher_setkey(sym_hd, key_buf, PK_KEY_SIZE);
470
ret = gcry_cipher_setiv(sym_hd, ivec_buf, PK_CIPHER_BLOCK);
472
ret = gcry_ac_data_new(&rsa_data_set);
477
for (j = 0; j < RSA_FIELDS; j++) {
478
size_t s = rsa->size[j];
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);
488
gcry_mpi_scan(&mpi, GCRYMPI_FMT_USG, buf, s, NULL);
489
ret = gcry_ac_data_set(rsa_data_set, GCRY_AC_FLAG_COPY,
491
gcry_mpi_release(mpi);
498
ret = gcry_ac_key_init(&rsa_priv, rsa_hd,
499
GCRY_AC_KEY_SECRET, rsa_data_set);
501
goto Destroy_data_set;
503
ret = gcry_ac_data_new(&key_set);
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);
511
goto Destroy_key_set;
513
gcry_mpi_release(mpi);
514
ret = gcry_ac_data_decrypt(rsa_hd, 0, rsa_priv, &mpi, key_set);
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);
530
gcry_mpi_release(mpi);
531
gcry_ac_data_destroy(key_set);
534
gcry_ac_key_destroy(rsa_priv);
537
gcry_ac_data_destroy(rsa_data_set);
540
gcry_cipher_close(sym_hd);
543
gcry_ac_close(rsa_hd);
549
static int open_resume_dev(char *resume_dev_name,
550
struct swsusp_header *swsusp_header)
552
unsigned int size = sizeof(struct swsusp_header);
553
unsigned int shift = (resume_offset + 1) * page_size - size;
556
fd = open(resume_dev_name, O_RDWR);
559
fprintf(stderr, "%s: Could not open the resume device\n",
563
if (lseek(fd, shift, SEEK_SET) != shift)
565
ret = read(fd, swsusp_header, size);
567
if (memcmp(SWSUSP_SIG, swsusp_header->sig, 10)) {
572
ret = ret < 0 ? ret : -EIO;
579
static int read_image(int dev, int fd, struct swsusp_header *swsusp_header)
581
static struct swap_map_handle handle;
582
static unsigned char orig_checksum[16], checksum[16];
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;
591
error = read_area(fd, header, swsusp_header->image, page_size);
593
goto Reboot_question;
595
if (header->image_flags & PLATFORM_SUSPEND)
596
use_platform_suspend = 1;
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);
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) {
611
fprintf(stderr, "%s: Failed to initialize LZO\n",
616
fprintf(stderr, "%s: Compression not supported\n", my_name);
621
goto Reboot_question;
623
if (header->image_flags & IMAGE_ENCRYPTED) {
624
#ifdef CONFIG_ENCRYPT
625
static unsigned char key[KEY_SIZE], ivec[CIPHER_BLOCK];
627
printf("%s: Encrypted image\n", my_name);
628
if (header->image_flags & IMAGE_USE_RSA) {
629
error = decrypt_key(header, key, ivec, buffer);
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];
640
error = gcry_cipher_open(&handle.cipher_handle,
641
IMAGE_CIPHER, GCRY_CIPHER_MODE_CFB,
645
error = gcry_cipher_setkey(handle.cipher_handle,
649
error = gcry_cipher_setiv(handle.cipher_handle,
654
gcry_cipher_close(handle.cipher_handle);
656
fprintf(stderr, "%s: libgcrypt error: %s\n",
658
gcry_strerror(error));
661
fprintf(stderr, "%s: Encryption not supported\n",
668
goto Reboot_question;
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;
677
struct timeval begin, end;
678
double delta, mb = header->size / (1024.0 * 1024.0);
680
gettimeofday(&begin, NULL);
681
error = load_image(&handle, dev, nr_pages);
682
gettimeofday(&end, NULL);
684
timersub(&end, &begin, &end);
685
delta = end.tv_usec / 1000000.0 + end.tv_sec;
687
printf("wrote %0.1lf MB in %0.1lf seconds (%0.1lf MB/s)\n",
688
mb, header->writeout_time, mb / header->writeout_time);
690
printf("read %0.1lf MB in %0.1lf seconds (%0.1lf MB/s)\n",
691
mb, delta, mb / delta);
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);
702
"\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"
707
"\tThis might be a result of booting a wrong kernel.\n\n"
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');
719
fprintf(stderr, "%s: Reboot failed, please reboot manually.\n",
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",
733
print_checksum(buffer, checksum);
734
fprintf(stderr, "%s: Computed MD5 checksum %s\n",
739
/* Reset swap signature now */
740
memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10);
741
if (lseek(fd, shift, SEEK_SET) != shift) {
744
ret = write(fd, swsusp_header, size);
746
error = ret < 0 ? -errno : -EIO;
748
"%s: Could not restore the partition header\n",
755
#ifdef CONFIG_ENCRYPT
757
gcry_cipher_close(handle.cipher_handle);
761
sprintf(buffer, "%s: Error %d loading the image\n"
762
"\nPress ENTER to continue\n", my_name, error);
763
splash.dialog(buffer);
765
printf("%s: Image successfully loaded\n", my_name);
771
/* Parse the command line and/or configuration file */
772
static inline int get_config(int argc, char *argv[])
774
static struct option options[] = {
776
"help\0\t\t\tthis text",
777
no_argument, NULL, 'h'
780
"version\0\t\t\tversion information",
781
no_argument, NULL, 'V'
784
"config\0\t\talternative configuration file.",
785
required_argument, NULL, 'f'
788
"resume_device\0device that contains swap area",
789
required_argument, NULL, 'r'
792
"resume_offset\0offset of swap file in resume device.",
793
required_argument, NULL, 'o'
796
"parameter\0\toverride config file parameter.",
797
required_argument, NULL, 'P'
802
char *conf_name = CONFIG_FILE;
803
const char *optstring = "hVf:o:r:P:";
804
struct stat stat_buf;
805
int fail_missing_config = 0;
807
/* parse only config file argument */
808
while ((i = getopt_long(argc, argv, optstring, options, NULL)) != -1) {
811
usage(my_name, options, optstring);
814
version(my_name, NULL);
818
fail_missing_config = 1;
823
if (stat(conf_name, &stat_buf)) {
824
if (fail_missing_config) {
825
fprintf(stderr, "%s: Could not stat configuration file\n",
831
error = parse(my_name, conf_name, parameters);
833
fprintf(stderr, "%s: Could not parse config file\n", my_name);
839
while ((i = getopt_long(argc, argv, optstring, options, NULL)) != -1) {
842
/* already handled */
845
resume_offset = atoll(optarg);
848
strncpy(resume_dev_name, optarg, MAX_STR_LEN -1);
851
error = parse_line(optarg, parameters);
854
"%s: Could not parse config string '%s'\n",
860
usage(my_name, options, optstring);
866
strncpy(resume_dev_name, argv[optind], MAX_STR_LEN - 1);
871
int main(int argc, char *argv[])
873
unsigned int mem_size;
874
struct stat stat_buf;
876
int n, error, orig_loglevel;
877
static struct swsusp_header swsusp_header;
879
my_name = basename(argv[0]);
881
error = get_config(argc, argv);
885
if (splash_param != 'y' && splash_param != 'Y')
888
splash_param = SPL_RESUME;
890
page_size = getpagesize();
891
buffer_size = BUFFER_PAGES * page_size;
892
#ifdef CONFIG_ENCRYPT
893
printf("%s: libgcrypt version: %s\n", my_name,
894
gcry_check_version(NULL));
895
gcry_control(GCRYCTL_INIT_SECMEM, page_size, 0);
896
mem_size = 3 * page_size + 2 * buffer_size;
898
mem_size = 3 * page_size + buffer_size;
900
mem_pool = malloc(mem_size);
903
fprintf(stderr, "%s: Could not allocate memory\n", my_name);
908
orig_loglevel = get_kernel_console_loglevel();
909
set_kernel_console_loglevel(suspend_loglevel);
911
while (stat(resume_dev_name, &stat_buf)) {
913
"%s: Could not stat the resume device file '%s'\n"
914
"\tPlease type in the full path name to try again\n"
915
"\tor press ENTER to boot the system: ", my_name,
917
fgets(resume_dev_name, MAX_STR_LEN - 1, stdin);
918
n = strlen(resume_dev_name) - 1;
924
if (resume_dev_name[n] == '\n')
925
resume_dev_name[n] = '\0';
928
setvbuf(stdout, NULL, _IONBF, 0);
929
setvbuf(stderr, NULL, _IONBF, 0);
931
if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
933
fprintf(stderr, "%s: Could not lock myself\n", my_name);
938
dev = open(snapshot_dev_name, O_WRONLY);
944
resume_dev = open_resume_dev(resume_dev_name, &swsusp_header);
945
if (resume_dev == -ENOMEDIUM) {
948
} else if (resume_dev < 0) {
953
splash_prepare(&splash, splash_param);
956
error = read_image(dev, resume_dev, &swsusp_header);
958
fprintf(stderr, "%s: Could not read the image\n", my_name);
965
fprintf(stderr, "%s: Could not freeze processes\n", my_name);
968
if (use_platform_suspend) {
969
int ret = platform_prepare(dev);
971
fprintf(stderr, "%s: pm_ops->prepare returned "
972
"error %d\n", my_name, ret);
973
use_platform_suspend = 0;
977
/* We only get here if the atomic restore fails. Clean up. */
978
if (use_platform_suspend)
979
platform_finish(dev);
989
set_kernel_console_loglevel(max_loglevel);
990
else if (orig_loglevel >= 0)
991
set_kernel_console_loglevel(orig_loglevel);