1/* vi: set sw=4 ts=4: */
2/*
3 * mkswap.c - set up a linux swap device
4 *
5 * (C) 1991 Linus Torvalds. This file may be redistributed as per
6 * the Linux copyright.
7 */
8
9/*
10 * 20.12.91  -	time began. Got VM working yesterday by doing this by hand.
11 *
12 * Usage: mkswap [-c] [-vN] [-f] device [size-in-blocks]
13 *
14 *	-c   for readability checking. (Use it unless you are SURE!)
15 *	-vN  for swap areas version N. (Only N=0,1 known today.)
16 *      -f   for forcing swap creation even if it would smash partition table.
17 *
18 * The device may be a block device or an image of one, but this isn't
19 * enforced (but it's not much fun on a character device :-).
20 *
21 * Patches from jaggy@purplet.demon.co.uk (Mike Jagdis) to make the
22 * size-in-blocks parameter optional added Wed Feb  8 10:33:43 1995.
23 *
24 * Version 1 swap area code (for kernel 2.1.117), aeb, 981010.
25 *
26 * Sparc fixes, jj@ultra.linux.cz (Jakub Jelinek), 981201 - mangled by aeb.
27 * V1_MAX_PAGES fixes, jj, 990325.
28 *
29 * 1999-02-22 Arkadiusz Mi�kiewicz <misiek@misiek.eu.org>
30 * - added Native Language Support
31 *
32 *  from util-linux -- adapted for busybox by
33 *  Erik Andersen <andersee@debian.org>. I ripped out Native Language
34 *  Support, made some stuff smaller, and fitted for life in busybox.
35 *
36 */
37
38#include <stdio.h>
39#include <unistd.h>
40#include <string.h>
41#include <fcntl.h>
42#include <stdlib.h>
43#include <sys/ioctl.h>			/* for _IO */
44#include <sys/utsname.h>
45#include <asm/page.h>			/* for PAGE_SIZE and PAGE_SHIFT */
46				/* we also get PAGE_SIZE via getpagesize() */
47#include "busybox.h"
48
49#ifndef _IO
50/* pre-1.3.45 */
51static const int BLKGETSIZE = 0x1260;
52#else
53/* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */
54#define BLKGETSIZE _IO(0x12,96)
55#endif
56
57static char *device_name = NULL;
58static int DEV = -1;
59static long PAGES = 0;
60static int check = 0;
61static int badpages = 0;
62static int version = -1;
63
64#define MAKE_VERSION(p,q,r)	(65536*(p) + 256*(q) + (r))
65
66/*
67 * The definition of the union swap_header uses the constant PAGE_SIZE.
68 * Unfortunately, on some architectures this depends on the hardware model,
69 * and can only be found at run time -- we use getpagesize().
70 */
71
72static int pagesize;
73static int *signature_page;
74
75static struct swap_header_v1 {
76	char bootbits[1024];		/* Space for disklabel etc. */
77	unsigned int version;
78	unsigned int last_page;
79	unsigned int nr_badpages;
80	unsigned int padding[125];
81	unsigned int badpages[1];
82} *p;
83
84static void init_signature_page()
85{
86	pagesize = getpagesize();
87
88#ifdef PAGE_SIZE
89	if (pagesize != PAGE_SIZE)
90		error_msg("Assuming pages of size %d", pagesize);
91#endif
92	signature_page = (int *) xmalloc(pagesize);
93	memset(signature_page, 0, pagesize);
94	p = (struct swap_header_v1 *) signature_page;
95}
96
97static void write_signature(char *sig)
98{
99	char *sp = (char *) signature_page;
100
101	strncpy(sp + pagesize - 10, sig, 10);
102}
103
104#define V0_MAX_PAGES	(8 * (pagesize - 10))
105/* Before 2.2.0pre9 */
106#define V1_OLD_MAX_PAGES	((0x7fffffff / pagesize) - 1)
107/* Since 2.2.0pre9:
108   error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
109   with variations on
110	#define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
111	#define SWP_OFFSET(entry) ((entry) >> 8)
112   on the various architectures. Below the result - yuk.
113
114   Machine	pagesize	SWP_ENTRY	SWP_OFFSET	bound+1	oldbound+2
115   i386		2^12		o<<8		e>>8		1<<24	1<<19
116   mips		2^12		o<<15		e>>15		1<<17	1<<19
117   alpha	2^13		o<<40		e>>40		1<<24	1<<18
118   m68k		2^12		o<<12		e>>12		1<<20	1<<19
119   sparc	2^{12,13}	(o&0x3ffff)<<9	(e>>9)&0x3ffff	1<<18	1<<{19,18}
120   sparc64	2^13		o<<13		e>>13		1<<51	1<<18
121   ppc		2^12		o<<8		e>>8		1<<24	1<<19
122   armo		2^{13,14,15}	o<<8		e>>8		1<<24	1<<{18,17,16}
123   armv		2^12		o<<9		e>>9		1<<23	1<<19
124
125   assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
126
127   The bad part is that we need to know this since the kernel will
128   refuse a swap space if it is too large.
129*/
130/* patch from jj - why does this differ from the above? */
131#if defined(__alpha__)
132#define V1_MAX_PAGES           ((1 << 24) - 1)
133#elif defined(__mips__)
134#define V1_MAX_PAGES           ((1 << 17) - 1)
135#elif defined(__sparc_v9__)
136#define V1_MAX_PAGES           ((3 << 29) - 1)
137#elif defined(__sparc__)
138#define V1_MAX_PAGES           (pagesize == 8192 ? ((3 << 29) - 1) : ((1 << 18) - 1))
139#else
140#define V1_MAX_PAGES           V1_OLD_MAX_PAGES
141#endif
142/* man page now says:
143The maximum useful size of a swap area now depends on the architecture.
144It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
145128GB on alpha and 3TB on sparc64.
146*/
147
148#define MAX_BADPAGES	((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
149
150static void bit_set(unsigned int *addr, unsigned int nr)
151{
152	unsigned int r, m;
153
154	addr += nr / (8 * sizeof(int));
155
156	r = *addr;
157	m = 1 << (nr & (8 * sizeof(int) - 1));
158
159	*addr = r | m;
160}
161
162static int bit_test_and_clear(unsigned int *addr, unsigned int nr)
163{
164	unsigned int r, m;
165
166	addr += nr / (8 * sizeof(int));
167
168	r = *addr;
169	m = 1 << (nr & (8 * sizeof(int) - 1));
170
171	*addr = r & ~m;
172	return (r & m) != 0;
173}
174
175
176static void page_ok(int page)
177{
178	if (version == 0)
179		bit_set(signature_page, page);
180}
181
182static void page_bad(int page)
183{
184	if (version == 0)
185		bit_test_and_clear(signature_page, page);
186	else {
187		if (badpages == MAX_BADPAGES)
188			error_msg_and_die("too many bad pages");
189		p->badpages[badpages] = page;
190	}
191	badpages++;
192}
193
194static void check_blocks(void)
195{
196	unsigned int current_page;
197	int do_seek = 1;
198	char *buffer;
199
200	buffer = xmalloc(pagesize);
201	current_page = 0;
202	while (current_page < PAGES) {
203		if (!check) {
204			page_ok(current_page++);
205			continue;
206		}
207		if (do_seek && lseek(DEV, current_page * pagesize, SEEK_SET) !=
208			current_page * pagesize)
209			error_msg_and_die("seek failed in check_blocks");
210		if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) {
211			page_bad(current_page++);
212			continue;
213		}
214		page_ok(current_page++);
215	}
216	if (badpages == 1)
217		printf("one bad page\n");
218	else if (badpages > 1)
219		printf("%d bad pages\n", badpages);
220}
221
222static long valid_offset(int fd, int offset)
223{
224	char ch;
225
226	if (lseek(fd, offset, 0) < 0)
227		return 0;
228	if (read(fd, &ch, 1) < 1)
229		return 0;
230	return 1;
231}
232
233static int find_size(int fd)
234{
235	unsigned int high, low;
236
237	low = 0;
238	for (high = 1; high > 0 && valid_offset(fd, high); high *= 2)
239		low = high;
240	while (low < high - 1) {
241		const int mid = (low + high) / 2;
242
243		if (valid_offset(fd, mid))
244			low = mid;
245		else
246			high = mid;
247	}
248	return (low + 1);
249}
250
251/* return size in pages, to avoid integer overflow */
252static long get_size(const char *file)
253{
254	int fd;
255	long size;
256
257	if ((fd = open(file, O_RDONLY)) < 0)
258		perror_msg_and_die("%s", file);
259	if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
260		int sectors_per_page = pagesize / 512;
261
262		size /= sectors_per_page;
263	} else {
264		size = find_size(fd) / pagesize;
265	}
266	close(fd);
267	return size;
268}
269
270int mkswap_main(int argc, char **argv)
271{
272	char *tmp;
273	struct stat statbuf;
274	int sz;
275	int maxpages;
276	int goodpages;
277	int offset;
278	int force = 0;
279
280	init_signature_page();		/* get pagesize */
281
282	while (argc-- > 1) {
283		argv++;
284		if (argv[0][0] != '-') {
285			if (device_name) {
286				int blocks_per_page = pagesize / 1024;
287
288				PAGES = strtol(argv[0], &tmp, 0) / blocks_per_page;
289				if (*tmp)
290					show_usage();
291			} else
292				device_name = argv[0];
293		} else {
294			switch (argv[0][1]) {
295			case 'c':
296				check = 1;
297				break;
298			case 'f':
299				force = 1;
300				break;
301			case 'v':
302				version = atoi(argv[0] + 2);
303				break;
304			default:
305				show_usage();
306			}
307		}
308	}
309	if (!device_name) {
310		error_msg("error: Nowhere to set up swap on?");
311		show_usage();
312	}
313	sz = get_size(device_name);
314	if (!PAGES) {
315		PAGES = sz;
316	} else if (PAGES > sz && !force) {
317		error_msg("error: size %ld is larger than device size %d",
318				PAGES * (pagesize / 1024), sz * (pagesize / 1024));
319		return EXIT_FAILURE;
320	}
321
322	if (version == -1) {
323		if (PAGES <= V0_MAX_PAGES)
324			version = 0;
325		else if (get_kernel_revision() < MAKE_VERSION(2, 1, 117))
326			version = 0;
327		else if (pagesize < 2048)
328			version = 0;
329		else
330			version = 1;
331	}
332	if (version != 0 && version != 1) {
333		error_msg("error: unknown version %d", version);
334		show_usage();
335	}
336	if (PAGES < 10) {
337		error_msg("error: swap area needs to be at least %ldkB",
338				(long) (10 * pagesize / 1024));
339		show_usage();
340	}
341	if (!version)
342		maxpages = V0_MAX_PAGES;
343	else if (get_kernel_revision() >= MAKE_VERSION(2, 2, 1))
344		maxpages = V1_MAX_PAGES;
345	else {
346		maxpages = V1_OLD_MAX_PAGES;
347		if (maxpages > V1_MAX_PAGES)
348			maxpages = V1_MAX_PAGES;
349	}
350	if (PAGES > maxpages) {
351		PAGES = maxpages;
352		error_msg("warning: truncating swap area to %ldkB",
353				PAGES * pagesize / 1024);
354	}
355
356	DEV = open(device_name, O_RDWR);
357	if (DEV < 0 || fstat(DEV, &statbuf) < 0)
358		perror_msg_and_die("%s", device_name);
359	if (!S_ISBLK(statbuf.st_mode))
360		check = 0;
361	else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
362		error_msg_and_die("Will not try to make swapdevice on '%s'", device_name);
363
364#ifdef __sparc__
365	if (!force && version == 0) {
366		/* Don't overwrite partition table unless forced */
367		unsigned char *buffer = (unsigned char *) signature_page;
368		unsigned short *q, sum;
369
370		if (read(DEV, buffer, 512) != 512)
371			error_msg_and_die("fatal: first page unreadable");
372		if (buffer[508] == 0xDA && buffer[509] == 0xBE) {
373			q = (unsigned short *) (buffer + 510);
374			for (sum = 0; q >= (unsigned short *) buffer;)
375				sum ^= *q--;
376			if (!sum) {
377				error_msg("Device '%s' contains a valid Sun disklabel.\n"
378"This probably means creating v0 swap would destroy your partition table\n"
379"No swap created. If you really want to create swap v0 on that device, use\n"
380"the -f option to force it.", device_name);
381				return EXIT_FAILURE;
382			}
383		}
384	}
385#endif
386
387	if (version == 0 || check)
388		check_blocks();
389	if (version == 0 && !bit_test_and_clear(signature_page, 0))
390		error_msg_and_die("fatal: first page unreadable");
391	if (version == 1) {
392		p->version = version;
393		p->last_page = PAGES - 1;
394		p->nr_badpages = badpages;
395	}
396
397	goodpages = PAGES - badpages - 1;
398	if (goodpages <= 0)
399		error_msg_and_die("Unable to set up swap-space: unreadable");
400	printf("Setting up swapspace version %d, size = %ld bytes\n",
401		   version, (long) (goodpages * pagesize));
402	write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2");
403
404	offset = ((version == 0) ? 0 : 1024);
405	if (lseek(DEV, offset, SEEK_SET) != offset)
406		error_msg_and_die("unable to rewind swap-device");
407	if (write(DEV, (char *) signature_page + offset, pagesize - offset)
408		!= pagesize - offset)
409		error_msg_and_die("unable to write signature page");
410
411	/*
412	 * A subsequent swapon() will fail if the signature
413	 * is not actually on disk. (This is a kernel bug.)
414	 */
415	if (fsync(DEV))
416		error_msg_and_die("fsync failed");
417	return EXIT_SUCCESS;
418}
419