1#!/bin/bash
2#
3# Create an initrd directory if one does not already exist.
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, you can access it online at
17# http://www.gnu.org/licenses/gpl-2.0.html.
18#
19# Copyright (C) IBM Corporation, 2013
20#
21# Author: Connor Shu <Connor.Shu@ibm.com>
22
23D=tools/testing/selftests/rcutorture
24
25# Prerequisite checks
26[ -z "$D" ] && echo >&2 "No argument supplied" && exit 1
27if [ ! -d "$D" ]; then
28    echo >&2 "$D does not exist: Malformed kernel source tree?"
29    exit 1
30fi
31if [ -d "$D/initrd" ]; then
32    echo "$D/initrd already exists, no need to create it"
33    exit 0
34fi
35
36T=${TMPDIR-/tmp}/mkinitrd.sh.$$
37trap 'rm -rf $T' 0 2
38mkdir $T
39
40cat > $T/init << '__EOF___'
41#!/bin/sh
42# Run in userspace a few milliseconds every second.  This helps to
43# exercise the NO_HZ_FULL portions of RCU.
44while :
45do
46	q=
47	for i in \
48		a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a \
49		a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a \
50		a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a \
51		a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a \
52		a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a \
53		a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
54	do
55		q="$q $i"
56	done
57	sleep 1
58done
59__EOF___
60
61# Try using dracut to create initrd
62if command -v dracut >/dev/null 2>&1
63then
64	echo Creating $D/initrd using dracut.
65	# Filesystem creation
66	dracut --force --no-hostonly --no-hostonly-cmdline --module "base" $T/initramfs.img
67	cd $D
68	mkdir initrd
69	cd initrd
70	zcat $T/initramfs.img | cpio -id
71	cp $T/init init
72	chmod +x init
73	echo Done creating $D/initrd using dracut
74	exit 0
75fi
76
77# No dracut, so create a C-language initrd/init program and statically
78# link it.  This results in a very small initrd, but might be a bit less
79# future-proof than dracut.
80echo "Could not find dracut, attempting C initrd"
81cd $D
82mkdir initrd
83cd initrd
84cat > init.c << '___EOF___'
85#include <unistd.h>
86#include <sys/time.h>
87
88volatile unsigned long delaycount;
89
90int main(int argc, int argv[])
91{
92	int i;
93	struct timeval tv;
94	struct timeval tvb;
95
96	for (;;) {
97		sleep(1);
98		/* Need some userspace time. */
99		if (gettimeofday(&tvb, NULL))
100			continue;
101		do {
102			for (i = 0; i < 1000 * 100; i++)
103				delaycount = i * i;
104			if (gettimeofday(&tv, NULL))
105				break;
106			tv.tv_sec -= tvb.tv_sec;
107			if (tv.tv_sec > 1)
108				break;
109			tv.tv_usec += tv.tv_sec * 1000 * 1000;
110			tv.tv_usec -= tvb.tv_usec;
111		} while (tv.tv_usec < 1000);
112	}
113	return 0;
114}
115___EOF___
116${CROSS_COMPILE}gcc -static -Os -o init init.c
117strip init
118rm init.c
119echo "Done creating a statically linked C-language initrd"
120
121exit 0
122