-
Notifications
You must be signed in to change notification settings - Fork 13
/
mkpart.sh
executable file
·214 lines (167 loc) · 5.2 KB
/
mkpart.sh
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
#!/bin/sh
#
# Chimera Linux device partitioning and filesystem tool
#
# This script is usually used as a part of device image creation and partitions
# a device or with a known layout, and creates appropriate filesystems. The
# result is mounted in a way that can be accepted by the other stages.
#
# Copyright 2023 q66 <[email protected]>
#
# License: BSD-2-Clause
#
readonly PROGNAME=$(basename "$0")
do_cleanup() {
if [ -n "$TARGET_MNT" -a -d "$TARGET_MNT" ]; then
umount -fR "$TARGET_MNT" > /dev/null 2>&1
fi
}
error_sig() {
do_cleanup
exit ${1:=0}
}
trap 'error_sig $? $LINENO' INT TERM 0
msg() {
printf "\033[1m$@\n\033[m"
}
die() {
msg "ERROR: $@"
error_sig 1 $LINENO
}
TARGET_MNT=
BOOT_FSTYPE=vfat
BOOT_FSSIZE=256MiB
ROOT_FSTYPE=ext4
BOOT_MKARGS=
ROOT_MKARGS=
ROOT_JOURNAL=1
if [ "$(id -u)" != "0" ]; then
die "must be run as root"
fi
if ! command -v findmnt > /dev/null 2>&1; then
die "findmnt is required"
fi
if ! command -v sfdisk > /dev/null 2>&1; then
die "sfdisk is required"
fi
usage() {
cat <<EOF
Usage: $PROGNAME [opts] DEVICE PLATFORM MNTPT
The FILE_OR_DEVICE is a block device (whole, either physical or one set
up with 'losetup -fP'). The PLATFORM must match a device layout file in
sfdisk/. The MNTPT is a directory to mount the resulting structure in.
Options:
-b FSTYPE The /boot file system type (current: ${BOOT_FSTYPE})
-B FSSIZE The /boot file system size (current: ${BOOT_FSSIZE})
-r FSTYPE The / file system type (current: ${ROOT_FSTYPE})
-m ARGS Additional arguments for /boot mkfs.
-M ARGS Additional arguments for / mkfs.
-j Disable journal for /.
-h Print this message.
EOF
exit ${1:=1}
}
while getopts "b:B:r:m:M:jh" opt; do
case "$opt" in
b) BOOT_FSTYPE="$OPTARG";;
B) BOOT_FSSIZE="$OPTARG";;
r) ROOT_FSTYPE="$OPTARG";;
m) BOOT_MKARGS="$OPTARG";;
M) ROOT_MKARGS="$OPTARG";;
j) ROOT_JOURNAL=0;;
h) usage 0;;
*) usage;;
esac
done
if ! command -v mkfs.${BOOT_FSTYPE} > /dev/null 2>&1; then
die "mkfs.${BOOT_FSTYPE} is required"
fi
if ! command -v mkfs.${ROOT_FSTYPE} > /dev/null 2>&1; then
die "mkfs.${ROOT_FSTYPE} is required"
fi
shift $((OPTIND - 1))
BDEV=$1
shift
PLATFORM=$1
shift
MNTPT=$(readlink -f "$1")
shift
[ -b "$BDEV" ] || die "input must be a block device"
# We need a partition layout file for each platform
#
# In general, U-Boot targets use GPT with 4 partitions, the first two holding
# the U-Boot SPL and U-Boot itself (and typically having the "Linux reserved"
# partition type except when something else is necessary) and the other
# two holding /boot and the actual root file system
#
# Raspberry Pi uses MBR for best compatibility and has two partitions,
# one for /boot and one for the root filesystem
#
# All devices default to FAT32 /boot and ext4 /, for best compatibility
#
[ -r "sfdisk/${PLATFORM}" ] || die "unknown platform ${PLATFORM}"
[ -n "$MNTPT" -a -d "$MNTPT" ] || die "unknown or invalid mount point"
TARGET_MNT="$MNTPT"
# we need to figure these out to know where to create filesystems
BOOT_PARTN=
ROOT_PARTN=
seqn=1
for part in $(grep name= "sfdisk/${PLATFORM}" | sed 's/,.*//'); do
case "$part" in
name=boot) BOOT_PARTN=$seqn ;;
name=root) ROOT_PARTN=$seqn ;;
*) ;;
esac
seqn=$(($seqn + 1))
done
[ -n "$BOOT_PARTN" -a -n "$ROOT_PARTN" ] || \
die "could not locate partition numbers"
sed "s,@BOOT_SIZE@,${BOOT_FSSIZE},g" "sfdisk/${PLATFORM}" | sfdisk "${BDEV}"
if [ $? -ne 0 ]; then
die "could not partition ${BDEV}"
fi
# locate partitions; try FOOnN as well as fooN, as both may appear, whole
# devices that end with numbers will include the 'p' (e.g. loopN and nvmeNnM)
ROOT_DEV="${BDEV}p${ROOT_PARTN}"
[ -b "$ROOT_DEV" ] || ROOT_DEV="${BDEV}${ROOT_PARTN}"
[ -b "$ROOT_DEV" ] || die "unknown root partition"
BOOT_DEV="${BDEV}p${BOOT_PARTN}"
[ -b "$BOOT_DEV" ] || BOOT_DEV="${BDEV}${BOOT_PARTN}"
[ -b "$BOOT_DEV" ] || die "unknown boot partition"
# filesystem parameters
if [ "$BOOT_FSTYPE" = "vfat" ]; then
BOOT_MKARGS="-I -F16 $BOOT_MKARGS"
fi
case "$ROOT_FSTYPE" in
# disable journal on ext3/4 to improve lifespan of flash memory
ext[34])
if [ "$ROOT_JOURNAL" -eq 0 ]; then
ROOT_MKARGS="-O ^has_journal $ROOT_MKARGS"
fi
;;
esac
# label the partitions
add_fslabel() {
case "$1" in
ext*|xfs|btrfs) echo "-L $2" ;;
f2fs) echo "-l $2" ;;
vfat) echo "-n "$(echo $2|tr 'a-z' 'A-Z') ;;
esac
}
BOOT_LABEL=$(add_fslabel "$BOOT_FSTYPE" boot)
ROOT_LABEL=$(add_fslabel "$ROOT_FSTYPE" root)
BOOT_MKARGS="$BOOT_LABEL $BOOT_MKARGS"
ROOT_MKARGS="$ROOT_LABEL $ROOT_MKARGS"
# create filesystems
mkfs.${BOOT_FSTYPE} ${BOOT_MKARGS} "${BOOT_DEV}" \
|| die "failed to create boot file system"
mkfs.${ROOT_FSTYPE} ${ROOT_MKARGS} "${ROOT_DEV}" \
|| die "failed to create root file system"
# mount filesystems
mount "${ROOT_DEV}" "${TARGET_MNT}" || die "failed to mount root"
mkdir -p "${TARGET_MNT}/boot" || die "failed to create boot mount"
mount "${BOOT_DEV}" "${TARGET_MNT}/boot" || die "failed to mount boot"
echo "Mounted '${ROOT_DEV}' at '${TARGET_MNT}'."
# ensure this remains mounted
TARGET_MNT=
exit 0