-
Notifications
You must be signed in to change notification settings - Fork 0
/
compile_image
executable file
·124 lines (100 loc) · 3.79 KB
/
compile_image
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
#!/bin/sh -e
dev_or_file="$1"
shift
sudo_or_not() {
if [ -w "$dev_or_file" ]; then
"$@"
else
sudo "$@"
fi
}
pad_align_size_mb() {
local mb="$(( 1024 * 1024 ))"
local size="$1"
local size_mb="$(( (size + mb - 1) / mb ))"
local pad_mb="$2"
local align_mb="$3"
echo "$(( (size_mb + pad_mb + align_mb - 1) / align_mb * align_mb ))"
}
pad_align_file_size_mb() {
local size="$(stat -c '%s' "$1")"
shift
pad_align_size_mb "$size" "$@"
}
offset_mb=2 # enough space for gpt header
spl_mb="$(pad_align_file_size_mb "$UBOOT_SPL" 1 2)"
itb_mb="$(pad_align_file_size_mb "$UBOOT_ITB" 2 2)"
rootfs_mb="$(pad_align_file_size_mb "$ROOTFS_IMG" 0 2)"
# TODO this isn't necessarily 1 MB
secondary_gpt_mb=1
img_size=$(( (offset_mb + spl_mb + itb_mb + rootfs_mb + secondary_gpt_mb) * 1024 * 1024 ))
if [ -b "$dev_or_file" ]; then
if [ "$(sudo_or_not blockdev --getsize64 "$dev_or_file")" -lt "$img_size" ]; then
echo "$dev_or_file is too small (need at least $img_size bytes)" >&2
exit 1
fi
else
truncate -s "$img_size" "$dev_or_file"
fi
# just to get rid of warnings about overwriting partition tables
sudo_or_not dd "if=/dev/zero" "of=$dev_or_file" count=4 bs=4096 conv=notrunc
# ROM firmware boots the secondary program loader from this GPT partition
SPL_PARTITION_TYPE_UUID=2E54B353-1271-4842-806F-E436D6AF6985
UBOOT_PARTITION_TYPE_UUID=BC13C2FF-59E6-4262-A352-B275FD6F7172
# u-boot uses the second partition
# TODO might want to patch selection by GPT partition type selection into u-boot
# similar to what CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION_TYPE does
# the visionfive2 board-specific partitioning from u-boot uses this:
# MS_BASIC_DATA_PARTITION_TYPE_UUID=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7
# but that partition won't be detected as being bootable.
# the generic boot code in u-boot looks for this:
# EFI_SYSTEM_PARTITION_TYPE_UUID=C12A7328-F81F-11D2-BA4B-00A0C93EC93B
# that works.
# but for now, rely on the 'legacy BIOS bootable' attribute instead and be modest:
LINUX_FS_PARTITION_TYPE_UUID=0FC63DAF-8483-4772-8E79-3D69D8477DE4
# TODO -w always
sudo_or_not sfdisk -X gpt "$dev_or_file" <<EOF
name=spl, start=${offset_mb}MiB, size=${spl_mb}MiB, type=$SPL_PARTITION_TYPE_UUID
name=uboot, size=${itb_mb}MiB, type=$UBOOT_PARTITION_TYPE_UUID
name=system, attrs=LegacyBIOSBootable, type=$LINUX_FS_PARTITION_TYPE_UUID
EOF
# boot partition-type = 0xC
# rootfs partition-type = 0x83
sudo_or_not sfdisk --bytes -o "Device,Start,Size,Sectors,Name" -q -l "$dev_or_file" | tail -n +2 |\
while read part_dev part_start_sector part_size part_sectors name; do
# there's this silly game with disk interfaces where you really want to do sectors-only but you can't.
# divide part_size by part_sectors to get the sector size
part_offset="$(( part_size / part_sectors * part_start_sector ))"
case "$name" in
spl)
file="$UBOOT_SPL"
;;
uboot)
file="$UBOOT_ITB"
;;
system)
file="$ROOTFS_IMG"
;;
*)
[ -z "$name" ] || echo "ignoring unknown partition: $name" >&2
continue
esac
file_size="$(stat -c '%s' "$file")"
if [ ! "$file_size" -le "$part_size" ]; then
echo "$file doesn't fit $name ($file_size > $part_size)" >&2
exit 1
fi
if [ $(( part_offset % 4096 )) -ne 0 ] || [ $(( part_size % 4096 )) -ne 0 ]; then
echo "partition $name size ($part_size) or offset ($part_offset) not a multiple of 4096" >&2
exit 1
fi
sudo_or_not dd "if=$file" "of=$dev_or_file" seek=$(( part_offset / 4096 )) bs=4096 conv=notrunc
# use all available space for the root filsystem
# resizing a file first and then writing it can take forever
# do the resize afterwards 'live'
if [ -b "$dev_or_file" ] && [ "$name" = system ] && [ "$file_size" != "$part_size" ]; then
sync
sudo_or_not resize2fs "$part_dev"
fi
done
[ ! -b "$dev_or_file" ] || sync