File: tuxonice

package info (click to toggle)
hibernate 2.0%2B15%2Bg88d54a8-1
  • links: PTS, VCS
  • area: main
  • in suites: buster, jessie, jessie-kfreebsd, stretch, wheezy
  • size: 740 kB
  • ctags: 114
  • sloc: sh: 1,223; makefile: 17
file content (821 lines) | stat: -rw-r--r-- 30,980 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
# -*- sh -*-
# vim:ft=sh:ts=8:sw=4:noet


AddTerminationHandler TuxOnIceTermination
AddConfigHandler TuxOnIceConfigEnabler
AddOptionHandler TuxOnIceOptionHandler

AddConfigHelp "UseTuxOnIce <boolean>" "Enable/disable the use of TuxOnIce to hibernate."

AddConfigHelp "Reboot <boolean> (requires UseTuxOnIce on)" "Controls whether or not TuxOnIce should reboot after hibernating. Setting this to yes will force a reboot. Setting this to no will force shutting down. Omitting this option will leave rebooting behaviour unchanged."
AddShortOption "r::"
AddLongOption "reboot::"
AddOptionHelp "-r[0|1], --reboot[=<0|1>] (requires UseTuxOnIce on)" "If 0 is specified, disables rebooting after writing the image, regardless of the Reboot option in the configuration file. If 1 or omitted, will force a reboot after writing the image."

AddConfigHelp "EnableEscape <boolean> (requires UseTuxOnIce on)" "If specified, allows (or disallows) the use of the escape key to abort a hibernation cycle. If this line is not specified, the Escape key's behaviour is unchanged."

AddConfigHelp "DefaultConsoleLevel <N> (requires UseTuxOnIce on)" "If specified, sets the default console level. 0 gives a progress bar. 1 gives a progress bar with numbers. 2 or higher give increasing amounts of debugging. If this line is not specified, the default console level is unchanged."

AddConfigHelp "ImageSizeLimit nocache|<NN> (requires UseTuxOnIce on)" "If specified, sets an upper limit on the size of the hibernation image written (in megabytes). If set to \"nocache\", caches and buffers will not be saved - resulting in a faster hibernation and resume at the possible expense of system responsiveness immediately after resuming. If set to 0, no limit is imposed. If this line is not specified, the existing image size limit is unchanged."

AddConfigHelp "AsyncIOLimit <N> (requires UseTuxOnIce on)" "Deprecated since 2.1.5.11 (hence won't do anything if set). Limit the number of I/O operations that TuxOnIce will have queued at once. Lowering this value has resolved hangs when reading or writing caches for some people. Try values like 64, 32 and 8."

AddConfigHelp "SuspendDevice <device> (requires UseTuxOnIce on)" "If specified, sets the hibernation device by writing to the resume[2] entry in $TUXONICE_ROOT. This does not automatically set the resuming device - you will need to make sure your bootloader or initrd script does this."

AddConfigHelp "FilewriterLocation <filename> <size in MB> (requires UseTuxOnIce on)" "This option sets up the given filename to act as a destination file for writing the hibernation image to, and verifies that it can act as a valid destination. If the file does not exist, the file is created. This option is only relevant if you are using the filewriter plugin for TuxOnIce."

AddConfigHelp "VerifyFilewriterResume2 <boolean> (requires UseTuxOnIce on)" "When this option is on, you will be prompted if your current kernel command-line does not match the correct resume[2] for the filewriter. This option is on by default."

AddConfigHelp "LoadSuspendModules <module name> [...] (requires UseTuxOnIce on)" "Loads the given modules before even detecting TuxOnIce. This may be required when TuxOnIce is compiled as modules that need to be loaded prior to hibernating."
AddConfigHelp "UnloadSuspendModulesAfterResume <boolean> (requires UseTuxOnIce on)" "If yes, will unload the TuxOnIce modules mentioned above after resuming."

AddConfigHelp "PowerdownMethod <0|3|4|5> (requires UseTuxOnIce on)" "Allows you to choose what TuxOnIce should do after writing its image to disk. 3/4/5 will only work if you have ACPI enabled in your kernel. 3/4/5 correspond to the ACPI states S3 (suspend-to-RAM), S4 (hibernate-to-disk), and S5 (power off). Choosing 3 will request your machine to enter the S3 Suspend-to-RAM state if it is supported - this allows you drastically cut the resume time waiting for your BIOS but still consumes power whilst hibernated (though the image is not lost should power run out). Choosing 4 will cause your machine to enter an S4 sleep state which may also reduce the resume time without using any power whilst hibernated. Choosing 5 will cause your machine to switch off after hibernating (traditional method) but might still cause your machine to resume when you open the lid. 0 bypasses ACPI and shuts off the machine completely."

AddConfigHelp "Compressor none|<compressor name> (requires UseTuxOnIce on)" "Sets the compression algorithm to use for compressing the memory image. If set to \"none\", disables compression. Otherwise, the compressor name must be listed in /proc/crypto. This will also try to load the module if not available. (Only for TuxOnIce.1.9.5 or newer)."

AddConfigHelp "Encryptor none|<encryptor name> (requires UseTuxOnIce on)" "Sets the encryption algorithm to use for encrypting the memory image. If set to \"none\", disables encryption. Otherwise, the cipher name must be listed in /proc/crypto. This will also try to load the module if not available. You will probably require more options than just this to fully use encryption. These will be introduced in the next version of hibernate, but for now you can set them using the \"ProcSetting\" option if you know what you are doing. (Only for TuxOnIce.1.9.5 or newer)."

AddConfigHelp "ProcSetting <entry name> <value> (requires UseTuxOnIce on)" "Sets the value of $TUXONICE_ROOT/<entry_name> to <value> upon hibernating. You can use this setting to set parameters that can't be configured anywhere else in this script. This is executed after all other settings have been set."

AddShortOption "n"
AddLongOption "no-suspend"

AddLongOption "bug-report"
AddOptionHelp "--bug-report (requires UseTuxOnIce on)" "Gathers a bunch of information about your machine and writes it to standard output. Please attach this information along with any bug reports to the TuxOnIce mailing list."

if [ -f "/sys/power/tuxonice/binary_signature" ]; then
    TUXONICE_BINARY_SIG=`cat /sys/power/tuxonice/binary_signature`
elif [ -f "/usr/local/share/hibernate/tuxonice-binary-signature.bin" ]; then
    TUXONICE_BINARY_SIG=`cat /usr/local/share/hibernate/tuxonice-binary-signature.bin`
elif [ -f "/usr/share/hibernate/tuxonice-binary-signature.bin" ]; then
    TUXONICE_BINARY_SIG=`cat /usr/share/hibernate/tuxonice-binary-signature.bin`
else
     vecho 0 "$EXE:Warning: Tuxonice binary signature file not found."
fi

TuxOnIceTermination() {
    # rmmod rather than modprobe -r because the later might
    # remove more modules than we want to remove.
    for mod in ${TUXONICE_RMOD} ; do
	/sbin/rmmod ${mod}
    done

    return 0
}

TuxOnIceConfigEnabler() {
    [ "$1" != "usesuspend2" ] && [ "$1" != "useswsusp2" ] && [ "$1" != "usetuxonice" ] && return 1
    BoolIsOn "$1" "$2" || return 0
    [ -n "$USING_TUXONICE" ] && return 0

    # Load the TuxOnIce modules if necessary
    # Order is important - dependent modules later than what they depend on.
    TUXONICE_MODS="suspend_core suspend_block_io suspend_file suspend_swap suspend_compress suspend_userui tuxonice_core tuxonice_block_io tuxonice_file tuxonice_swap tuxonice_compress tuxonice_userui"
    TUXONICE_RMOD=
    for mod in ${TUXONICE_MODS} ; do
	/sbin/modprobe --first-time "${mod}" >/dev/null 2>&1  && TUXONICE_RMOD="${mod} ${TUXONICE_RMOD}"
    done

    # signature for filewriter
    FILEWRITER_SIGNATURE="Suspend2"

    # Detect where TuxOnIce is these days.
    if [ -d "/sys/power/tuxonice/" ] ; then
	TUXONICE_ROOT="/sys/power/tuxonice"
	FILEWRITER_SIGNATURE="TuxOnIce"
    elif [ -d "/sys/power/suspend2/" ] ; then
	TUXONICE_ROOT="/sys/power/suspend2"
    elif [ -d "/proc/swsusp/" ] ; then
	TUXONICE_ROOT="/proc/swsusp"
    elif [ -d "/proc/software_suspend" ] ; then
	TUXONICE_ROOT="/proc/software_suspend"
    else
	TUXONICE_ROOT="/proc/suspend2"
    fi
    
    COMPRESSION_ROOT="$TUXONICE_ROOT"
    ENCRYPTION_ROOT="$TUXONICE_ROOT"
    FILEWRITER_ROOT="$TUXONICE_ROOT"
    SWAPWRITER_ROOT="$TUXONICE_ROOT"
    UI_ROOT="$TUXONICE_ROOT"
    STORAGEMAN_ROOT="$TUXONICE_ROOT"
    [ -d "$TUXONICE_ROOT/compression/" ] && COMPRESSION_ROOT="$TUXONICE_ROOT/compression"
    [ -d "$TUXONICE_ROOT/encryption/" ] && ENCRYPTION_ROOT="$TUXONICE_ROOT/encryption"
    [ -d "$TUXONICE_ROOT/filewriter/" ] && FILE_DIR="filewriter"
    [ -d "$TUXONICE_ROOT/swapwriter/" ] && SWAP_DIR_ROOT="swapwriter"
    [ -d "$TUXONICE_ROOT/file/" ] && FILE_DIR="file"
    [ -d "$TUXONICE_ROOT/swap/" ] && SWAP_DIR="swap"
    [ -d "$TUXONICE_ROOT/user_interface/" ] && UI_ROOT="$TUXONICE_ROOT/user_interface"
    [ -d "$TUXONICE_ROOT/storage_manager/" ] && STORAGEMAN_ROOT="$TUXONICE_ROOT/storage_manager"

    [ -n "$FILE_DIR" ] && FILEWRITER_ROOT="$TUXONICE_ROOT/$FILE_DIR"    
    [ -n "$SWAP_DIR" ] && SWAPWRITER_ROOT="$TUXONICE_ROOT/$SWAP_DIR"    
    HIBERNATE_FILEWRITER_TRAIL="/var/run/TuxOnIce_filewriter_image_exists"

    if [ -n "$NO_COMPLAIN_UNSUPPORTED" ] ; then
	# Just bail silently if we don't detect it.
	[ -d "$TUXONICE_ROOT" ] || return 0
    fi
    UsingSuspendMethod TuxOnIce
    AddConfigHandler TuxOnIceConfigOptions
    AddSuspendHook 10 EnsureTuxOnIceCapable
    AddSuspendHook 97 ChangeToTuxOnIceVT
    AddSuspendHook 99 DoTuxOnIce
    AddResumeHook 97 ChangeFromTuxOnIceVT
    USING_TUXONICE=1
    return 0
}

TuxOnIceOptionHandler() {
    # Don't parse options if we're not being used.
    [ -z "$USING_TUXONICE" ] && return 1

    case $1 in
	-r|--reboot)
	    if [ -z "$2" ] ; then
		# Cmd-line options will always override config file
		OPT_REBOOT=1
	    else
		BoolIsOn "-r" "$2" && OPT_REBOOT=1 || OPT_REBOOT=0
	    fi
	    ;;
	-n|--no-suspend)
	    TUXONICE_NO_SUSPEND=1
	    ;;
	--bug-report)
	    TUXONICE_BUG_REPORT=1
	    ;;
	*)
	    return 1
    esac
    return 0
}

TuxOnIceConfigOptions() {
    case $1 in
	reboot)
	    if [ -z "$OPT_REBOOT" ] ; then
		BoolIsOn "$1" "$2" && OPT_REBOOT=1 || OPT_REBOOT=0
	    fi
	    ;;
	enableescape)
	    if [ -z "$OPT_ESCAPE" ] ; then
		BoolIsOn "$1" "$2" && OPT_ESCAPE=1 || OPT_ESCAPE=0
	    fi
	    ;;
	defaultconsolelevel)
	    OPT_CONSOLELEVEL=$2
	    ;;
	imagesizelimit)
	    TUXONICE_IMAGE_SIZE_LIMIT=$2
	    ;;
	asynciolimit)
	    TUXONICE_ASYNC_IO_LIMIT=$2
	    ;;
	suspenddevice)
	    TUXONICE_RESUME2=$2
	    ;;
	filewriterlocation)
	    TUXONICE_FILEWRITER_LOC=$2
	    TUXONICE_FILEWRITER_SIZE=$3
	    if [ -z "$TUXONICE_FILEWRITER_LOC" ] ; then
		vecho 0 "$EXE: Empty filewriter location given!"
		exit 1
	    fi
	    if [ -e "$TUXONICE_FILEWRITER_LOC" ] && [ -d "$TUXONICE_FILEWRITER_LOC" ] ; then
		vecho 0 "$EXE: Filewriter location given is a directory!"
		exit 1
	    fi
	    if [ -e "$TUXONICE_FILEWRITER_LOC" ] && ! [ -w "$TUXONICE_FILEWRITER_LOC" ] ; then
		vecho 0 "$EXE: Filewriter location is unwritable!"
		exit 1
	    fi
	    if ! IsANumber "$TUXONICE_FILEWRITER_SIZE" ; then
		vecho 0 "$EXE: Filewriter size is not numeric!"
		exit 1
	    fi
	    AddSuspendHook 11 TuxOnIceSetupFilewriter
	    AddResumeHook 11 TuxOnIceCleanupFilewriter
	    ;;
	verifyfilewriterresume2)
	    BoolIsOn "$1" "$2" && return 0
	    TUXONICE_FILEWRITER_NOVERIFY=1
	    ;;
	loadsuspendmodules)
	    AddSuspendHook 05 TuxOnIceLoadModules
	    shift
	    TUXONICE_LOAD_MODULES=$@
	    ;;
	unloadsuspendmodulesafterresume)
	    BoolIsOn "$1" "$2" || return 0
	    AddResumeHook 05 TuxOnIceUnloadModules
	    ;;
	powerdownmethod)
	    case $2 in
		[03-5])
		    TUXONICE_POWERDOWN_METHOD=$2
		    ;;
		*)
		    echo "$EXE: Invalid value for $1 ($2). Must be 0 3 4 or 5."
		    return 0
		    ;;
	    esac
	    ;;
	compressor|compression)
	    TUXONICE_COMPRESSOR=$2
	    ;;
	encryptor|encryption)
	    TUXONICE_ENCRYPTOR=$2
	    ;;
	procsetting)
	    if [ -z "$OPT_DRY_RUN" ] ; then
		if [ -z "$TUXONICE_EXTRA_PROC_SETTINGS" ] ; then
		    TUXONICE_EXTRA_PROC_SETTINGS=`mktemp /tmp/tmp.hibernate.XXXXXX`
		    cat <<EOT > $TUXONICE_EXTRA_PROC_SETTINGS
# Temporary file for hibernate script.
# If you're reading this then it's probably safe to delete.

EOT
		    AddResumeHook 00 RemoveTuxOnIceProcCruft
		fi
		shift
		FILE="$1"
		shift
		TARGET="$TUXONICE_ROOT/$FILE"
		if ! [ -f "$TARGET" ] ; then
		    TARGET="`echo $TUXONICE_ROOT/*/$FILE | awk '{print $1}'`"
		    if ! [ -f "$TARGET" ] ; then
			nfile=$FILE
			[ $FILE != ${FILE#userui_} ] && \
			    nfile=user_interface/${FILE#userui_}
			[ $FILE = "storage_manager" ] && \
			    nfile=storage_manager/program
			[ $FILE != ${FILE#filewriter_} ] && \
			    nfile=$FILE_DIR/${FILE#filewriter_}
			[ $FILE != ${FILE#swapwriter_} ] && \
			    nfile=$SWAP_DIR/${FILE#swapwriter_}
			[ $FILE != ${FILE#encryption_} ] && \
			    nfile=encryption/${FILE#encryption_}
			if [ $FILE != ${FILE#disable_} ] ; then
			    nfile=${FILE#disable_}/enabled
			    val=$(($1^1))
			    set -- $val
			fi
			TARGET=$TUXONICE_ROOT/$nfile
		    fi
		fi
		if ! [ -f "$TARGET" ] ; then
		    vecho 0 "TuxOnIce: No $FILE entry available. Not setting."
		else
		    echo "echo \"$*\" > $TARGET" >> $TUXONICE_EXTRA_PROC_SETTINGS
		fi
	    fi
	    ;;
	*)
	    return 1
    esac
    if [ -z "$TUXONICE_HOOKED" ] ; then
	AddSuspendHook 98 TuxOnIceConfigSet
	TUXONICE_HOOKED=1
    fi
    return 0
}

RemoveTuxOnIceProcCruft() {
    [ -f "$TUXONICE_EXTRA_PROC_SETTINGS" ] && rm -f $TUXONICE_EXTRA_PROC_SETTINGS
    return 0
}

TuxOnIceSetupCryptoAPI() {
    TuxOnIceIsAtLeastVersion $((0x02010905)) || return

    TUXONICE_MODULES_LOADED=
    if [ -n "$TUXONICE_COMPRESSOR" ] ; then
	if [ "$TUXONICE_COMPRESSOR" != "none" ] ; then
	    if ! grep -q "^name.*: $TUXONICE_COMPRESSOR\$" /proc/crypto ; then
		modprobe $TUXONICE_COMPRESSOR 2>/dev/null 2>&1
		if ! grep -q "^name.*: $TUXONICE_COMPRESSOR\$" /proc/crypto ; then
		    vecho 0 "Warning: Chosen TuxOnIce compressor ($TUXONICE_COMPRESSOR) is not available. Compression disabled."
		    TUXONICE_COMPRESSOR=none
		else
		    TUXONICE_MODULES_LOADED="$TUXONICE_COMPRESSOR"
		fi
	    fi
	fi
	if [ "$TUXONICE_COMPRESSOR" != "none" ] ; then
	    compression_algorithm=$TUXONICE_COMPRESSOR
	    disable_value=0
	else
	    compression_algorithm=""
	    disable_value=1
	fi
	if [ -f "$COMPRESSION_ROOT/disable_compression" ] ; then
	    echo $disable_value > $COMPRESSION_ROOT/disable_compression
	elif [ -f "$COMPRESSION_ROOT/enabled" ] ; then
	    echo $(($disable_value^1)) > $COMPRESSION_ROOT/enabled
	fi
	if [ -f "$COMPRESSION_ROOT/compressor" ] ; then
	    echo $compression_algorithm > $COMPRESSION_ROOT/compressor
	elif [ -f "$COMPRESSION_ROOT/algorithm" ] ; then
	    echo $compression_algorithm > $COMPRESSION_ROOT/algorithm
	fi
    fi

    if [ -n "$TUXONICE_ENCRYPTOR" ] ; then
	if [ "$TUXONICE_ENCRYPTOR" != "none" ] ; then
	    if ! grep -q "^name.*: $TUXONICE_ENCRYPTOR\$" /proc/crypto ; then
		modprobe $TUXONICE_ENCRYPTOR 2>/dev/null 2>&1
		if ! grep -q "^name.*: $TUXONICE_ENCRYPTOR\$" /proc/crypto ; then
		    vecho 0 "Warning: Chosen TuxOnIce encryptor ($TUXONICE_ENCRYPTOR) is not available. Encryption disabled."
		    TUXONICE_ENCRYPTOR=none
		else
		    TUXONICE_MODULES_LOADED="$TUXONICE_MODULES_LOADED $TUXONICE_ENCRYPTOR"
		fi
	    fi
	fi
	if [ "$TUXONICE_ENCRYPTOR" != "none" ] ; then
	    encryption_algorithm=$TUXONICE_ENCRYPTOR
	    disable_value=0
	else
	    encryption_algorithm=""
	    disable_value=1
	fi
	if [ -f "$ENCRYPTION_ROOT/disable_encryption" ] ; then
	    echo $disable_value > $ENCRYPTION_ROOT/disable_encryption
	elif [ -f "$ENCRYPTION_ROOT/enabled" ] ; then
	    echo $(($disable_value^1)) > $ENCRYPTION_ROOT/enabled
	fi
	if [ -f "$ENCRYPTION_ROOT/encryptor" ] ; then
	    echo $encryption_algorithm > $ENCRYPTION_ROOT/encryptor
	elif [ -f "$ENCRYPTION_ROOT/algorithm" ] ; then
	    echo $encryption_algorithm > $ENCRYPTION_ROOT/algorithm
	fi
    fi
}

TuxOnIceConfigSet() {
    if [ "x$TUXONICE_IMAGE_SIZE_LIMIT" = "xnocache" ] ; then
	local field val units result
	local total=0 cached=0 buffers=0 free=0
	while read field val units ; do
	    [ "x$field" = "xMemTotal:" ] && total=$val
	    [ "x$field" = "xMemFree:" ] && free=$val
	    [ "x$field" = "xBuffers:" ] && buffers=$val
	    [ "x$field" = "xCached:" ] && cached=$val
	done < /proc/meminfo
	result=$((($total-$cached-$buffers-$free+10240)/1024))
	vecho 2 "Setting image size limit to $result."
	echo $result > $TUXONICE_ROOT/image_size_limit
    else
	[ -n "$TUXONICE_IMAGE_SIZE_LIMIT" ] && echo $TUXONICE_IMAGE_SIZE_LIMIT > $TUXONICE_ROOT/image_size_limit
    fi

    [ -n "$OPT_REBOOT" ] && [ -f "$TUXONICE_ROOT/reboot" ] && \
	echo $OPT_REBOOT > $TUXONICE_ROOT/reboot

    [ -n "$OPT_ESCAPE" ] && [ -f $UI_ROOT/enable_escape ] && \
	echo $OPT_ESCAPE > $UI_ROOT/enable_escape

    [ -n "$OPT_CONSOLELEVEL" ] && [ -f $UI_ROOT/default_console_level ] && \
	echo $OPT_CONSOLELEVEL > $UI_ROOT/default_console_level

    [ -n "$TUXONICE_ASYNC_IO_LIMIT" ] && [ -f $TUXONICE_ROOT/async_io_limit ] && \
    	echo $TUXONICE_ASYNC_IO_LIMIT > $TUXONICE_ROOT/async_io_limit

    [ -n "$TUXONICE_RESUME2" ] && [ -f $TUXONICE_ROOT/resume ] && \
    	echo $TUXONICE_RESUME2 > $TUXONICE_ROOT/resume

    [ -n "$TUXONICE_RESUME2" ] && [ -f $TUXONICE_ROOT/resume2 ] && \
    	echo $TUXONICE_RESUME2 > $TUXONICE_ROOT/resume2

    [ -n "$TUXONICE_POWERDOWN_METHOD" ] && [ -f $TUXONICE_ROOT/powerdown_method ] && \
	echo $TUXONICE_POWERDOWN_METHOD > $TUXONICE_ROOT/powerdown_method

    TuxOnIceSetupCryptoAPI

    [ -n "$TUXONICE_EXTRA_PROC_SETTINGS" ] && [ -f "$TUXONICE_EXTRA_PROC_SETTINGS" ] && \
	. $TUXONICE_EXTRA_PROC_SETTINGS

    return 0
}

TuxOnIceIsAtLeastVersion() {
    ver=`awk 'BEGIN{FS="[^0-9]"}{print($1*16777216)+($2*65536)+($3*256)+$4}' $TUXONICE_ROOT/version`
    [ $ver -ge $1 ] && return 0
    return 1
}

DoTuxOnIce() {
    local error
    if [ -n "$TUXONICE_BUG_REPORT" ] ; then
	# Dump our debug info now.
	vecho 0 "System information follows. (Please include with bug reports)."
	vecho 0 "--- Hibernate script version: $VERSION"
	[ -f /proc/config.gz ] || vecho 0 "--- kernel config not compiled into kernel. Please attach this separately."
	vecho 0 "--- Modules loaded: "`lsmod|awk 'BEGIN{getline}{print $1}'`
	vecho 0 "--- Active swaps: "
	vcat 0 /proc/swaps
	vecho 0 "--- /proc/cmdline: "`cat /proc/cmdline`
	vecho 0 "--- /proc/cpuinfo:"
	vcat 0 /proc/cpuinfo
	vecho 0 "--- lspci:"
	lspci | vcat 0
	if [ -f /proc/config.gz ] ; then
	    vecho 0 "--- kernel config:"
	    zcat /proc/config.gz | vcat 0
	fi

	# Use a freezer test if we can. Otherwise, just don't hibernate.
	if [ -f "$TUXONICE_ROOT/freezer_test" ] ; then
	    /bin/echo 1 > $TUXONICE_ROOT/freezer_test
	    # We'll obtain debug_info from dmesg
	else
	    TUXONICE_NO_SUSPEND=1
	    if [ -f "$TUXONICE_ROOT/debug_info" ] ; then
		vecho 0 "--- $TUXONICE_ROOT/debug_info:"
		vcat 0 $TUXONICE_ROOT/debug_info
	    fi
	fi
	vecho 1 "$EXE: Performing a freezer_test..."
    fi
    if [ -z "$TUXONICE_NO_SUSPEND" ] ; then
	vecho 1 "$EXE: Activating TuxOnIce ..."
	SaveDmesg
	error=`DoSuspend`
	[ -n "$error" ] && [ $error -ne 0 ] && EXIT_CODE=4
	if ! PrintErrors $error || [ -n "$TUXONICE_BUG_REPORT" ]; then
	    OutputDmesgChanges
	fi
	CleanupDmesg
    else
	vecho 1 "$EXE: Not actually hibernating (--no-suspend given)"
    fi
    [ -f "$TUXONICE_ROOT/freezer_test" ] && echo 0 > $TUXONICE_ROOT/freezer_test
    [ -n "$TUXONICE_MODULES_LOADED" ] && rmmod $TUXONICE_MODULES_LOADED 2>/dev/null
    return 0
}

ChangeToTuxOnIceVT() {
    if [ -n "$TUXONICE_FORCE_CHVT" ] ; then
	if command -v fgconsole > /dev/null 2>&1 ; then
	    TUXONICE_ORIGINAL_VT=`fgconsole`
	else
	    TUXONICE_ORIGINAL_VT=1
	fi
	vecho 3 "TuxOnIce: changing console from $TUXONICE_ORIGINAL_VT to 63"
	chvt 63
	# Turn off unicode on this VT, as it makes TuxOnIce output ugly.
	/bin/echo -ne '\033%@' > /dev/tty63
    fi
    return 0
}

ChangeFromTuxOnIceVT() {
    if [ -n "$TUXONICE_ORIGINAL_VT" ] ; then
	vecho 3 "TuxOnIce: changing console back to $TUXONICE_ORIGINAL_VT"
	chvt $TUXONICE_ORIGINAL_VT
    fi
    return 0
}

SaveDmesg() {
    # Save dmesg for later diffing.
    DMESG_ORIG=`mktemp /tmp/tmp.hibernate.XXXXXX`
    if ! dmesg > $DMESG_ORIG ; then
	rm -f $DMESG_ORIG
	DMESG_ORIG=
    fi
    return 0
}

OutputDmesgChanges() {
    [ -z "$DMESG_ORIG" ] && return 0
    local DMESG_CMP

    DMESG_CMP=`mktemp /tmp/tmp.hibernate.XXXXXX`
    # Rip out the relevant bits from the diff
    if dmesg | diff $DMESG_ORIG - | \
	awk 'BEGIN { chunks = 0 } 
            /^[0-9]/ { chunks += 1 }
	    /^> / { if (chunks == 2) print(substr($0, 2)) }
	    END { if (chunks == 2) exit 0; else exit 1 }' > $DMESG_CMP
    then
	# Exit code indicates the diff was useful. Log it (manually for speed).
	local diff_loglevel=1
	[ -n "$TUXONICE_BUG_REPORT" ] && diff_loglevel=0
	vecho $diff_loglevel "---- Output from dmesg: ----"
	vcat $diff_loglevel $DMESG_CMP
	vecho $diff_loglevel "---- End of dmesg output ----"
    else
	vecho 1 "Couldn't extract useful information from dmesg. Not logging here."
    fi
    rm -f $DMESG_CMP

    return 0
}

CleanupDmesg() {
    [ -n "$DMESG_ORIG" ] && rm -f $DMESG_ORIG
    return 0
}

# DoSuspend: activates the hibernation cycle and echo's the error code to be processed by
# PrintErrors. We can't just return it, because error codes may be > 255
DoSuspend() {
    if [ -f $TUXONICE_ROOT/do_hibernate ]; then
	echo > $TUXONICE_ROOT/do_hibernate
    elif [ -f $TUXONICE_ROOT/do_suspend ] ; then
	echo > $TUXONICE_ROOT/do_suspend
    else
	echo > $TUXONICE_ROOT/activate
    fi
    read REPLY < $TUXONICE_ROOT/last_result
    echo $REPLY

    return 0
}

# PrintAnErrorString <bit value>: prints a string corresponding to the relevant
# bit in an error code. These match up with the SUSPEND_* values in
# kernel/power/power.h.
PrintAnErrorString() {
    case "$1" in
	0) ERROR_TEXT="${ERROR_TEXT}TuxOnIce was aborted (see dmesg).\n"
	;;
	1) ERROR_TEXT="${ERROR_TEXT}TuxOnIce was aborted by user (see dmesg if unexpected).\n"
	;;
	2) ERROR_TEXT="${ERROR_TEXT}No swapspace was available. Try swapon?\n"
	;;
	3) ERROR_TEXT="${ERROR_TEXT}Not enough swapspace available. Free some memory?\n"
	;;
	4) ERROR_TEXT="${ERROR_TEXT}Freezing processes failed. Wacky driver problems :( (see dmesg)\n"
	;;
	5) ERROR_TEXT="${ERROR_TEXT}Image has been kept as requested.\n"
	;;
	6) ERROR_TEXT="${ERROR_TEXT}TuxOnIce would have eaten memory. Yumm....\n"
	;;
	7) ERROR_TEXT="${ERROR_TEXT}Unable to free enough memory.\n"
	;;
	8) ERROR_TEXT="${ERROR_TEXT}Failed to acquire power management semaphore.\n"
	;;
	9) ERROR_TEXT="${ERROR_TEXT}Some devices refused to suspend (see dmesg).\n"
	;;
	10) ERROR_TEXT="${ERROR_TEXT}Extra pages allowance is too small. (see dmesg).\n"
	;;
	11) ERROR_TEXT="${ERROR_TEXT}Unable to meet all constraints when preparing the image. (see dmesg).\n"
	;;
	12) ERROR_TEXT="${ERROR_TEXT}Failed to initialise all modules.\n"
	;;
	13) ERROR_TEXT="${ERROR_TEXT}Failed to clean up all modules.\n"
	;;
	14) ERROR_TEXT="${ERROR_TEXT}Out of memory.\n"
	;;
	15) ERROR_TEXT="${ERROR_TEXT}Image error.\n"
	;;
	16) ERROR_TEXT="${ERROR_TEXT}Platform preparation failed.\n"
	;;
	17) ERROR_TEXT="${ERROR_TEXT}CPU hotplugging failed.\n"
	;;
	18) ERROR_TEXT="${ERROR_TEXT}Architecture specific preparation failed.\n"
	;;
	19) ERROR_TEXT="${ERROR_TEXT}Needed to resave pages.\n"
	;;
	20) ERROR_TEXT="${ERROR_TEXT}Unable to hibernate at the moment.\n"
	;;
	21) ERROR_TEXT="${ERROR_TEXT}Notifier chain rejected hibernating.\n"
	;;
	*) ERROR_TEXT="${ERROR_TEXT}Unknown error! (see dmesg?)\n"
	;;
    esac
    return 0
}

# PrintErrors <last_result value>: prints the list of errors associated with a
# given result code. Returns 1 if dmesg output should be given (for failure
# cases)
PrintErrors() {
    local code bit_num

    code="$1"
    [ -n "$code" ] && [ "$code" -eq 0 ] && return 0

    ERROR_TEXT="${ERROR_TEXT}$EXE: TuxOnIce reported the following errors:\n"

    if [ -z "$code" ] ; then
	ERROR_TEXT="${ERROR_TEXT}\n - No status was returned. Might be a buggy or incompatible kernel?"
	/bin/echo -ne $ERROR_TEXT
	return 1
    fi

    # A special case for "TuxOnIce aborted" and "TuxOnIce aborted by user"
    # because it'd look silly to have both.
    aborted=$(($code & 3))
    if [ $aborted -eq 3 ] ; then
	ERROR_TEXT="${ERROR_TEXT} - "
	PrintAnErrorString 1 # aborted by user
	/bin/echo -ne $ERROR_TEXT
	return 0
    fi

    bit_num=0
    while [ "$code" -ne 0 ] ; do
	[ $(($code & 1)) -eq 1 ] && ERROR_TEXT="${ERROR_TEXT} - " && PrintAnErrorString "$bit_num"

	bit_num=$(($bit_num + 1))
	code=$(($code >> 1))
    done
    /bin/echo -ne "$ERROR_TEXT"
    return 1
}

# EnsureTuxOnIceCapable: makes sure we have a TuxOnIce-capable kernel. Stops the
# script with an error message if we don't. Also ensure's we have root -
# (even though the actual hibernation might not need it, everything else will)
EnsureTuxOnIceCapable() {
    # Test for *any* recent TuxOnIce support
    local ver
    if ! [ -d "$TUXONICE_ROOT" ] ; then
	cat <<EOT
Your kernel does not appear to have TuxOnIce support compiled in.
Please follow the HOWTO linked from http://www.tuxonice.net/ for instructions
on how to compile TuxOnIce into your kernel.
EOT
	return 2
    fi

    if [ -f "$TUXONICE_ROOT/activate" ] || [ -f "$TUXONICE_ROOT/do_suspend" ] || [ -f "$TUXONICE_ROOT/do_hibernate" ]; then
	if [ ! -f "$TUXONICE_ROOT/version" ] ; then
	    cat <<EOT
Can not find $TUXONICE_ROOT/version. Have you loaded the tuxonice_core
module?

EOT
	    return 1 # abort unless forced
	fi
    fi

    # Figure out if we need to handle VT switching ourselves (if version
    # >= 2.0.0.103, and the xhacks scriptlet didn't do it for us)
    TuxOnIceIsAtLeastVersion $((0x02000067)) && [ x"$XHACKS_LEAVE_X" != "x1" ] && \
	TUXONICE_FORCE_CHVT=1

    # If we have the resume2 proc entry, we can do some further tests
    # Otherwise, bail gracefully
    if [ -f $TUXONICE_ROOT/resume2 ]; then
        RESUME2_FILE=resume2
    elif [ -f $TUXONICE_ROOT/resume ]; then
        RESUME2_FILE=resume
    fi

    [ -n $RESUME2_FILE ] || return 0

    # If we're going to set resume2, we needn't care about this.
    [ -n "$TUXONICE_RESUME2" ] && return 0

    # See if we have been given a resume2 line
    read REPLY < $TUXONICE_ROOT/$RESUME2_FILE
    if [ -z "$REPLY" -a -z "$TUXONICE_FILEWRITER_NOVERIFY" ] ; then
	cat <<EOT
You haven't specified a resume=/resume2= parameter on your kernel command line

Your GRUB or LILO config should have something like $RESUME2_FILE=swap:/dev/hdaX
where /dev/hdaX is your swap partition. You will then need to either reboot
after doing so or set it manually (this time only) using:
    echo swap:/dev/hdaX > $TUXONICE_ROOT/$RESUME2_FILE
EOT
	return 2
    fi
    return 0
}

TuxOnIceLoadModules() {
    local i
    local ret
    ret=0
    for i in $TUXONICE_LOAD_MODULES ; do
	vecho 2 -n "Loading TuxOnIce module $i ... "
	if modprobe $i > /dev/null 2>&1 ; then
	    vecho 2
	else
	    vecho 2 "failed."
	    ret=1
	    # Don't abort immediately, because we might be using force.
	    # So we may as well load all the modules.
	fi
    done
    # Ensure we really have loaded the modules (avoid race conditions)
    i=0
    while ! [ -f $TUXONICE_ROOT/$RESUME2_FILE ] && [ $i -lt 3 ] ; do
	sleep 1
	i=$(($i+1))
    done
    return $ret
}

TuxOnIceUnloadModules() {
    for i in $TUXONICE_LOAD_MODULES ; do
	vecho 2 "Unloading TuxOnIce module $i ... "
	rmmod `FindModuleDeps $i` > /dev/null 2>&1
    done
    return 0
}

TuxOnIceSetupFilewriter() {
    local ft_entry
    ft_entry=
    [ -f "$FILEWRITER_ROOT/filewriter_target" ] && \
	ft_entry="$FILEWRITER_ROOT/filewriter_target"
    [ -f "$FILEWRITER_ROOT/target" ] && \
	ft_entry="$FILEWRITER_ROOT/target"

    if [ -z $ft_entry ] ; then
	vecho 0 "$EXE: WARNING: Filewriter location given, but kernel does not have filewriter"
	vecho 0 "$EXE: support. Ignoring."
	return 0
    fi

    if ! [ -e "$TUXONICE_FILEWRITER_LOC" ] ; then
	vecho 0 "$EXE: Creating $TUXONICE_FILEWRITER_SIZE MB filewriter target."
	{
	    echo $FILEWRITER_SIGNATURE
	    dd if=/dev/zero bs=1M count=$TUXONICE_FILEWRITER_SIZE 2>/dev/null
	} > $TUXONICE_FILEWRITER_LOC
	sync
    fi

    case "`dd \"if=$TUXONICE_FILEWRITER_LOC\" bs=8 count=1 2>/dev/null`" in
	$FILEWRITER_SIGNATURE|${TUXONICE_BINARY_SIG})
	    # We're good to go.
	    vecho 1 "$EXE: Detected filewriter image ready for use."
	    ;;
	Suspend2|TuxOnIce)
	    # Eeek! This is an incompatible image
	    # reliably preserve the starting block.
	    vecho 1 "$EXE: Killing incompatible filewriter image."
	    if ! /bin/echo -ne "$FILEWRITER_SIGNATURE\n\0\0" | dd "of=$TUXONICE_FILEWRITER_LOC" bs=11 count=1 conv=notrunc 2>/dev/null ; then
		vecho 0 "$EXE: Failed to kill incompatible image!"
		return 2 # Abort even with force
	    fi
	    ;;
	HaveImag)
	    # Eeek! There's already an image here. Erase it using dd to
	    # reliably preserve the starting block.
	    vecho 1 "$EXE: Killing existing filewriter image."
	    if ! /bin/echo -ne "$FILEWRITER_SIGNATURE\n\0\0" | dd "of=$TUXONICE_FILEWRITER_LOC" bs=11 count=1 conv=notrunc 2>/dev/null ; then
		vecho 0 "$EXE: Failed to kill existing image!"
		return 2 # Abort even with force
	    fi
	    ;;
	*)
	    # Something entirely different. We probably don't want to use this file!
	    vecho 0 "$EXE: Filewriter image ($TUXONICE_FILEWRITER_LOC) is unrecognised."
	    vecho 0 "$EXE: I'm not even going to attempt to use this file to hibernate to."
	    vecho 0 "$EXE: Please erase the contents of the existing file if you believe it"
	    vecho 0 "$EXE: to be safe, otherwise, please specify a new file."
	    return 2 # Abort even with force
	    ;;
    esac

    if ! echo "$TUXONICE_FILEWRITER_LOC" > $ft_entry ; then
	vecho 0 "$EXE: Failed to set filewriter location! Aborting."
	return 2 # abort even if forced
    fi

    # Leave a note so that the file can be cleaned up on a fresh reboot.
    echo "$TUXONICE_FILEWRITER_LOC" > $HIBERNATE_FILEWRITER_TRAIL
    chmod 600 $HIBERNATE_FILEWRITER_TRAIL

    # Now verify our resume2 is correct unless told otherwise.
    [ x"$TUXONICE_FILEWRITER_NOVERIFY" = "x1" ] && return 0

    local new_resume2
    if [ -f $TUXONICE_ROOT/resume2 ]; then
        RESUME2_FILE=resume2
    elif [ -f $TUXONICE_ROOT/resume ]; then
        RESUME2_FILE=resume
    fi

    new_resume2="`cat $TUXONICE_ROOT/$RESUME2_FILE`"
    if [ -z "$new_resume2" ] ; then
	vecho 0 "ABORTING: $TUXONICE_ROOT/$RESUME2_FILE did not return a valid result."
	return 2 # abort even if forced
    fi

    if ! grep "$new_resume2" /proc/cmdline ; then
	filewriter_target=`cat $TUXONICE_ROOT/$RESUME2_FILE`
	vecho 0 "ABORTING: $RESUME2_FILE is not setup correctly. Unless you have setup your bootloader"
	vecho 0 "          correctly, resuming will most likely fail. To correct this, add"
	vecho 0 "          \"$RESUME2_FILE=$filewriter_target\" to your kernel command line in your"
	vecho 0 "          LILO or GRUB configuration file and reboot."
	return 2 # abort even if forced
    fi

    return 0
}

TuxOnIceCleanupFilewriter() {
    rm -f $HIBERNATE_FILEWRITER_TRAIL
}

# $Id: tuxonice 1200 2008-11-06 21:57:00Z nigel $