blob: 3f21391c8c336c72ec4319d1bccf0a917c191ace [file] [log] [blame]
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001/*
2 * Copyright (C) 1999 by Andries Brouwer
3 * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
4 * Copyright (C) 2001 by Andreas Dilger
5 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
6 * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
7 *
8 * This file may be redistributed under the terms of the
9 * GNU Lesser General Public License.
10 */
11#include <stdio.h>
12#include <stdlib.h>
13#include <unistd.h>
14#include <string.h>
15#include <errno.h>
16#include <ctype.h>
17#include <stdint.h>
18
19#include "superblocks.h"
20
21/* linux-2.6/include/linux/swap.h */
22struct swap_header_v1_2 {
23 /* char bootbits[1024]; */ /* Space for disklabel etc. */
24 uint32_t version;
25 uint32_t lastpage;
26 uint32_t nr_badpages;
27 unsigned char uuid[16];
28 unsigned char volume[16];
29 uint32_t padding[117];
30 uint32_t badpages[1];
31} __attribute__((packed));
32
33#define PAGESIZE_MIN 0xff6 /* 4086 (arm, i386, ...) */
34#define PAGESIZE_MAX 0xfff6 /* 65526 (ia64) */
35
36#define TOI_MAGIC_STRING "\xed\xc3\x02\xe9\x98\x56\xe5\x0c"
37#define TOI_MAGIC_STRLEN (sizeof(TOI_MAGIC_STRING) - 1)
38
39static int swap_set_info(blkid_probe pr, const char *version)
40{
41 struct swap_header_v1_2 *hdr;
42
43 /* Swap header always located at offset of 1024 bytes */
44 hdr = (struct swap_header_v1_2 *) blkid_probe_get_buffer(pr, 1024,
45 sizeof(struct swap_header_v1_2));
46 if (!hdr)
bigbiff7b4c7a62015-01-01 19:44:14 -050047 return errno ? -errno : 1;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050048
49 /* SWAPSPACE2 - check for wrong version or zeroed pagecount */
bigbiff7b4c7a62015-01-01 19:44:14 -050050 if (strcmp(version, "1") == 0) {
51 if (hdr->version != 1 && swab32(hdr->version) != 1) {
52 DBG(LOWPROBE, ul_debug("incorrect swap version"));
53 return 1;
54 }
55 if (hdr->lastpage == 0) {
56 DBG(LOWPROBE, ul_debug("not set last swap page"));
57 return 1;
58 }
59 }
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050060
61 /* arbitrary sanity check.. is there any garbage down there? */
62 if (hdr->padding[32] == 0 && hdr->padding[33] == 0) {
63 if (hdr->volume[0] && blkid_probe_set_label(pr, hdr->volume,
64 sizeof(hdr->volume)) < 0)
bigbiff7b4c7a62015-01-01 19:44:14 -050065 return 1;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050066 if (blkid_probe_set_uuid(pr, hdr->uuid) < 0)
bigbiff7b4c7a62015-01-01 19:44:14 -050067 return 1;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050068 }
69
70 blkid_probe_set_version(pr, version);
71 return 0;
72}
73
74static int probe_swap(blkid_probe pr, const struct blkid_idmag *mag)
75{
76 unsigned char *buf;
77
78 if (!mag)
bigbiff7b4c7a62015-01-01 19:44:14 -050079 return 1;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050080
81 /* TuxOnIce keeps valid swap header at the end of the 1st page */
82 buf = blkid_probe_get_buffer(pr, 0, TOI_MAGIC_STRLEN);
83 if (!buf)
bigbiff7b4c7a62015-01-01 19:44:14 -050084 return errno ? -errno : 1;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050085
86 if (memcmp(buf, TOI_MAGIC_STRING, TOI_MAGIC_STRLEN) == 0)
87 return 1; /* Ignore swap signature, it's TuxOnIce */
88
89 if (!memcmp(mag->magic, "SWAP-SPACE", mag->len)) {
90 /* swap v0 doesn't support LABEL or UUID */
bigbiff7b4c7a62015-01-01 19:44:14 -050091 blkid_probe_set_version(pr, "0");
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050092 return 0;
93
94 } else if (!memcmp(mag->magic, "SWAPSPACE2", mag->len))
bigbiff7b4c7a62015-01-01 19:44:14 -050095 return swap_set_info(pr, "1");
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050096
bigbiff7b4c7a62015-01-01 19:44:14 -050097 return 1;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050098}
99
100static int probe_swsuspend(blkid_probe pr, const struct blkid_idmag *mag)
101{
102 if (!mag)
bigbiff7b4c7a62015-01-01 19:44:14 -0500103 return 1;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500104 if (!memcmp(mag->magic, "S1SUSPEND", mag->len))
105 return swap_set_info(pr, "s1suspend");
106 if (!memcmp(mag->magic, "S2SUSPEND", mag->len))
107 return swap_set_info(pr, "s2suspend");
108 if (!memcmp(mag->magic, "ULSUSPEND", mag->len))
109 return swap_set_info(pr, "ulsuspend");
110 if (!memcmp(mag->magic, TOI_MAGIC_STRING, mag->len))
111 return swap_set_info(pr, "tuxonice");
112 if (!memcmp(mag->magic, "LINHIB0001", mag->len))
113 return swap_set_info(pr, "linhib0001");
114
bigbiff7b4c7a62015-01-01 19:44:14 -0500115 return 1; /* no signature detected */
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500116}
117
118const struct blkid_idinfo swap_idinfo =
119{
120 .name = "swap",
121 .usage = BLKID_USAGE_OTHER,
122 .probefunc = probe_swap,
123 .minsz = 10 * 4096, /* 10 pages */
124 .magics =
125 {
126 { "SWAP-SPACE", 10, 0, 0xff6 },
127 { "SWAPSPACE2", 10, 0, 0xff6 },
128 { "SWAP-SPACE", 10, 0, 0x1ff6 },
129 { "SWAPSPACE2", 10, 0, 0x1ff6 },
130 { "SWAP-SPACE", 10, 0, 0x3ff6 },
131 { "SWAPSPACE2", 10, 0, 0x3ff6 },
132 { "SWAP-SPACE", 10, 0, 0x7ff6 },
133 { "SWAPSPACE2", 10, 0, 0x7ff6 },
134 { "SWAP-SPACE", 10, 0, 0xfff6 },
135 { "SWAPSPACE2", 10, 0, 0xfff6 },
136 { NULL }
137 }
138};
139
140
141const struct blkid_idinfo swsuspend_idinfo =
142{
143 .name = "swsuspend",
144 .usage = BLKID_USAGE_OTHER,
145 .probefunc = probe_swsuspend,
146 .minsz = 10 * 4096, /* 10 pages */
147 .magics =
148 {
149 { TOI_MAGIC_STRING, TOI_MAGIC_STRLEN, 0, 0 },
150 { "S1SUSPEND", 9, 0, 0xff6 },
151 { "S2SUSPEND", 9, 0, 0xff6 },
152 { "ULSUSPEND", 9, 0, 0xff6 },
153 { "LINHIB0001",10,0, 0xff6 },
154
155 { "S1SUSPEND", 9, 0, 0x1ff6 },
156 { "S2SUSPEND", 9, 0, 0x1ff6 },
157 { "ULSUSPEND", 9, 0, 0x1ff6 },
158 { "LINHIB0001",10,0, 0x1ff6 },
159
160 { "S1SUSPEND", 9, 0, 0x3ff6 },
161 { "S2SUSPEND", 9, 0, 0x3ff6 },
162 { "ULSUSPEND", 9, 0, 0x3ff6 },
163 { "LINHIB0001",10,0, 0x3ff6 },
164
165 { "S1SUSPEND", 9, 0, 0x7ff6 },
166 { "S2SUSPEND", 9, 0, 0x7ff6 },
167 { "ULSUSPEND", 9, 0, 0x7ff6 },
168 { "LINHIB0001",10,0, 0x7ff6 },
169
170 { "S1SUSPEND", 9, 0, 0xfff6 },
171 { "S2SUSPEND", 9, 0, 0xfff6 },
172 { "ULSUSPEND", 9, 0, 0xfff6 },
173 { "LINHIB0001",10,0, 0xfff6 },
174
175 { NULL }
176 }
177};
178