aboutsummaryrefslogtreecommitdiff
path: root/images/raspberry-pi-2/scripts/mkrootimg
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"