up io error count if not exiting
[tridge/junkcode.git] / tphdisk.c
1 /*
2   this creates a save2dsk.bin hibernation file for phoenix netbios
3   laptops. I tested it on my IBM Thinkpad T20 but it should work on
4   other laptops.
5
6   Copyright 2002 Andrew Tridgell <tridge@samba.org> 
7   released under the GNU General Public License version 2 or later
8
9   Updated usage string to compile with gcc and to give better advice
10   Ian Hutchinson, 2005.
11
12 */
13
14 /*
15   This program was inspired by lphdisk which was written by Patrick
16   Ashmore and Alex Stewart. The main difference is that tphdisk
17   doesn't muck about with partition tables, which makes it easy to use
18   it for either a hibernation partition or a save2dsk.bin file.
19 */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24
25 typedef unsigned short u16;
26 typedef unsigned u32;
27
28 /*
29   write or die ...
30 */
31 static void x_write(int fd, void *data, size_t size)
32 {
33         if (write(fd, data, size) != (ssize_t)size) {
34                 fprintf(stderr,"Write failed!\n");
35                 exit(1);
36         }
37 }
38
39 /* 
40    the main function. The 'size' is in sectors (512 byte units) 
41
42    this writes a save2dsk.bin file to the given file descriptor
43 */
44 static void write_phdisk(int fd, u32 size)
45 {
46         unsigned char sector[512];
47         u16 checksum;
48         u32 i;
49
50         memset(sector, 0, 512);
51
52         /* form the header - this is x86 byte order dependent, but who
53            has a non-intel lapptop with a phoenix notebios? */
54         strcpy(sector, "TimO");
55         sector[12] = 2;
56         *(u32 *)&sector[16] = size;
57         for (checksum=0, i=8;i<512;i+=2) {
58                 checksum += *(u16 *)(&sector[i]);
59         }
60         *(u16 *)&sector[6] = ~checksum;
61
62         /* write two copies of the header */
63         x_write(fd, sector, 512);
64         x_write(fd, sector, 512);
65
66         /* rest is filled with 0x50 */
67         memset(sector, 0x50, 512);
68
69         for (i=2;i<size;i++) {
70                 x_write(fd, sector, 512);
71         }
72 }
73
74 /* main program */
75 int main(int argc, char *argv[])
76 {
77         int size;
78
79         if (argc < 2) {
80                 fprintf(stderr,"\n\
81 Usage: tphdisk <size in MB>\n\
82 \n\
83 written by Andrew Tridgell <tridge@samba.org>\n\
84 \n\
85 \n\
86 This program writes a 'save2dsk.bin' hibernation file to stdout. To\n\
87 use it you should do something like this:\n\
88 \n\
89 1) create a type c (FAT32) partition on your laptop\n\
90 2) format the partition with 'mkdosfs'\n\
91 3) mount the partition as VFAT\n\
92 4) create the 'save2dsk.bin' file on the partition using something like\n\
93       tphdisk 280 > save2dsk.bin\n\
94 5) Do a full reboot\n\
95 \n\
96 The only parameter is the size in megabytes of the save file. This\n\
97 needs to be at least as big as your main memory + video memory +2MB, but you\n\
98 can make it larger if you want to.\n\
99 \n\
100 You should also be able to use this to create a hibernation partition\n\
101 by directing the output to the right device (eg. /dev/hdaX) and\n\
102 setting the partition type to A0.  I haven't tried this as my thinkpad\n\
103 doesn't seem to support hibernation partitions.\n\
104 ");
105                 exit(1);
106         }
107
108         size = atoi(argv[1]) * 1024 * 2;
109
110         write_phdisk(1, size);
111         return 0;
112 }