blob: ff4f07c734b25b9fff5d3d2e6f61e7e731f0d9f6 (
plain) (
blame)
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
|
#!/bin/bash
set -e
print_usage() {
cat 1>&2 <<EOF
Usage: $0 <rootfs_directory> <image_file>
Package the contents of a debian root filesystem into a binary image file, ready to be burned onto an sd card.
This script will create an image with two partitions, the first one for /boot/firmware and the second one for /.
EOF
}
fail() {
echo "$1" >&2
exit 1
}
log() {
echo "mkrootimg: $1" >&2
}
# Directory to package
rootfs="$1"
# Binary image file
image="$2"
# Contains temporary build files
builddir=$(mktemp -d)
([ -n "$rootfs" ] && [ -n "$image" ]) || fail "$(print_usage)"
[ -d "$rootfs" ] || fail "$rootfs does not exist or is not a directory"
[ "$EUID" -eq 0 ] || fail "$0 must be run as root"
cleanup() {
set +e
umount --lazy "$builddir/mount/boot/firmware" 2> /dev/null
umount --lazy "$builddir/mount" 2> /dev/null
sync
losetup --detach "$bootfs_loop" 2> /dev/null
losetup --detach "$rootfs_loop" 2> /dev/null
rm -rf "$builddir"
trap - 0 1 2 3 6
}
trap cleanup 0 1 2 3 6
# Partition layout
#
# Content Size
# ---------------------------------------------
# reserved 1024k (1M, for e.g. a bootloader)
# bootfs 100*1024k (100M)
# rootfs as required
# calculate minimum required space for root partition
# (with 25% overhead for reserved blocks and journaling)
rootfs_raw_size_min=$(du --block-size=1M -s "$rootfs" | awk '{ print $1 }')
rootfs_size_min=$(( rootfs_raw_size_min + rootfs_raw_size_min * 25 / 100 ))
# create and partition image file
truncate --size $(( 1 + 100 + rootfs_size_min ))M "$image"
parted "$image" --script mklabel msdos
parted "$image" --script mkpart primary fat32 1M 100M
parted "$image" --script mkpart primary ext4 100M 100%
# get actual byte offsets of the partitions within the image
bootfs_start=$(parted --machine --script "$image" unit B print | grep '^1:' | cut -d ':' -f 2 | sed 's/B//g')
bootfs_size=$(parted --machine --script "$image" unit B print | grep '^1:' | cut -d ':' -f 4 | sed 's/B//g')
rootfs_start=$(parted --machine --script "$image" unit B print | grep '^2:' | cut -d ':' -f 2 | sed 's/B//g')
rootfs_size=$(parted --machine --script "$image" unit B print | grep '^2:' | cut -d ':' -f 4 | sed 's/B//g')
# set up temporary loop devices
log "setting up image loop devices"
bootfs_loop=$(losetup \
--offset "$bootfs_start" \
--sizelimit "$bootfs_size" \
--find \
--show \
"$image")
rootfs_loop=$(losetup \
--offset "$rootfs_start" \
--sizelimit "$rootfs_size" \
--find \
--show \
"$image")
# format partitions
log "formatting partitions"
mkfs.vfat -F 32 "$bootfs_loop" &> /dev/null
mkfs.ext4 -O^64bit "$rootfs_loop" &> /dev/null
# mount partitions
log "mounting partitions"
mkdir -p "$builddir/mount"
mount "$rootfs_loop" "$builddir/mount"
mkdir -p "$builddir/mount/boot/firmware"
mount "$bootfs_loop" "$builddir/mount/boot/firmware"
# copy root filesystem to image
log "copying root filesystem"
rsync -a "$rootfs/" "$builddir/mount/"
log "cleaning up"
cleanup
log "done"
|