forked from coreos/dev-util
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcros_generate_update_payload
executable file
·226 lines (191 loc) · 6.65 KB
/
cros_generate_update_payload
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
215
216
217
218
219
220
221
222
223
224
225
226
#!/bin/bash
# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Script to generate a Chromium OS update for use by the update engine.
# If a source .bin is specified, the update is assumed to be a delta update.
# Load common CrOS utilities. Inside the chroot this file is installed in
# /usr/lib/crosutils. This script may also be called from a zipfile, in which
# case common.sh will be in the current directory.
find_common_sh() {
local thisdir="$(dirname "$(readlink -f "$0")")"
local common_paths=(/usr/lib/crosutils "${thisdir}")
local path
SCRIPT_ROOT="${common_paths[0]}"
for path in "${common_paths[@]}"; do
if [ -r "${path}/common.sh" ]; then
SCRIPT_ROOT="${path}"
break
fi
done
# HACK(zbehan): We have to fake GCLIENT_ROOT in case we're running inside
# au_zip enviroment. GCLIENT_ROOT detection became fatal...
[ "${SCRIPT_ROOT}" == "${thisdir}" ] && export GCLIENT_ROOT="."
}
find_common_sh
. "${SCRIPT_ROOT}/common.sh" || exit 1
# Load functions and constants for chromeos-install
# NOTE: Needs to be called from outside the chroot.
. "/usr/lib/installer/chromeos-common.sh" &> /dev/null || \
. "${SRC_ROOT}/platform/installer/chromeos-common.sh" &> /dev/null || \
. "./chromeos-common.sh" || \
die "Unable to load /usr/lib/installer/chromeos-common.sh"
ESP_MNT=""
SRC_MNT=""
DST_MNT=""
SRC_KERNEL=""
SRC_ROOT=""
DST_KERNEL=""
DST_ROOT=""
STATE_MNT=""
# Pass an arg to not exit 1 at the end
cleanup() {
set +e
if [ -n "$ESP_MNT" ]; then
sudo umount "$ESP_MNT"
[ -d "$ESP_MNT" ] && rmdir "$ESP_MNT"
ESP_MNT=""
fi
if [ -n "$SRC_MNT" ]; then
sudo umount "$SRC_MNT"
[ -d "$SRC_MNT" ] && rmdir "$SRC_MNT"
SRC_MNT=""
fi
if [ -n "$DST_MNT" ]; then
sudo umount "$DST_MNT"
[ -d "$DST_MNT" ] && rmdir "$DST_MNT"
DST_MNT=""
fi
if [ -n "$STATE_MNT" ]; then
sudo umount "$STATE_MNT" || true
[ -d "$STATE_MNT" ] && rmdir "$STATE_MNT"
STATE_MNT=""
fi
rm -f "$SRC_KERNEL"
rm -f "$SRC_ROOT"
rm -f "$DST_KERNEL"
rm -f "$DST_ROOT"
[ -n "$1" ] || exit 1
}
extract_partition_to_temp_file() {
local filename="$1"
local partition="$2"
local temp_file="$3"
if [ -z "$temp_file" ]; then
temp_file=$(mktemp /tmp/cros_generate_update_payload.XXXXXX)
echo "$temp_file"
fi
local offset=$(partoffset "${filename}" ${partition}) # 512-byte sectors
local length=$(partsize "${filename}" ${partition}) # 512-byte sectors
local bs=512
local sectors_per_two_mib=$((2 * 1024 * 1024 / 512))
if [ $(( $offset % $sectors_per_two_mib )) -eq 0 -a \
$(( $length % $sectors_per_two_mib )) -eq 0 ]; then
bs=$((2 * 1024 * 1024))
offset=$(($offset / $sectors_per_two_mib))
length=$(($length / $sectors_per_two_mib))
else
warn "partition offset or length not at 2MiB boundary"
fi
dd if="$filename" of="$temp_file" bs=$bs count="$length" \
skip="$offset" 2>/dev/null
}
extract_root() {
local bin_file="$1"
local root_out="$2"
if [ -z "$root_out" ]; then
die "missing root output filename"
fi
# TODOBP: Patch
extract_partition_to_temp_file "$bin_file" 3 "$root_out"
}
DEFINE_string image "" "The image that should be sent to clients."
DEFINE_string src_image "" "Optional: a source image. If specified, this makes\
a delta update."
DEFINE_string output "" "Output file"
DEFINE_boolean include_kernel "$FLAGS_FALSE" "Include the kernel as a payload object"
DEFINE_string metadata_output "" "Output file for metadata payload"
DEFINE_boolean outside_chroot "$FLAGS_FALSE" "Running outside of chroot."
DEFINE_string private_key "" "Path to private key in .pem format."
DEFINE_string public_key "" "Path to public key in .pem format."
DEFINE_boolean extract "$FLAGS_FALSE" "If set, extract old/new kernel/rootfs \
to [old|new]_[kern|root].dat. Useful for debugging (default: false)"
# Parse command line
FLAGS "$@" || exit 1
eval set -- "${FLAGS_ARGV}"
set -e
if [ -n "$FLAGS_src_image" ] && \
[ "$FLAGS_outside_chroot" -eq "$FLAGS_FALSE" ]; then
# We need to be in the chroot for generating delta images.
# by specifying --outside_chroot you can choose not to assert
# this will allow us to run this script outside chroot.
# Running this script outside chroot requires copying delta_generator binary
# and also copying few shared libraries with it.
assert_inside_chroot
fi
locate_gpt
if [ "$FLAGS_extract" -eq "$FLAGS_TRUE" ]; then
if [ -n "$FLAGS_src_image" ]; then
extract_root "$FLAGS_src_image" old_root.dat
fi
if [ -n "$FLAGS_image" ]; then
extract_root "$FLAGS_image" new_root.dat
fi
echo Done extracting kernel/root
exit 0
fi
[ -n "$FLAGS_output" ] ||
die "Error: you must specify an output filename with --output FILENAME"
DELTA=$FLAGS_TRUE
[ -z "$FLAGS_src_image" ] && DELTA=$FLAGS_FALSE
echo "Generating an update"
# Sanity check that the real generator exists:
GENERATOR="$(which delta_generator)"
[ -x "$GENERATOR" ] || die "can't find delta_generator"
trap cleanup INT TERM EXIT
if [ "$DELTA" -eq "$FLAGS_TRUE" ]; then
SRC_ROOT=$(extract_partition_to_temp_file "$FLAGS_src_image" 3)
echo md5sum of src root:
md5sum "$SRC_ROOT"
fi
ESP_MNT=$(mktemp -d /tmp/esp_root.XXXXXX)
sudo mount -o loop,offset=2097152 "$FLAGS_image" "$ESP_MNT"
DST_ROOT=$(extract_partition_to_temp_file "$FLAGS_image" 3)
if [ "$DELTA" -eq "$FLAGS_TRUE" ]; then
SRC_MNT=$(mktemp -d /tmp/src_root.XXXXXX)
sudo mount -o loop,ro "$SRC_ROOT" "$SRC_MNT"
DST_MNT=$(mktemp -d /tmp/src_root.XXXXXX)
sudo mount -o loop,ro "$DST_ROOT" "$DST_MNT"
sudo LD_LIBRARY_PATH=${LD_LIBRARY_PATH} PATH=${PATH} "$GENERATOR" \
-new_dir "$DST_MNT" -new_image "$DST_ROOT" \
-old_dir "$SRC_MNT" -old_image "$SRC_ROOT" -old_kernel "$SRC_KERNEL" \
-out_file "$FLAGS_output" -private_key "$FLAGS_private_key"
else
if [ "$FLAGS_include_kernel" -eq "$FLAGS_TRUE" ]; then
"$GENERATOR" \
-new_image "$DST_ROOT" -new_kernel "$ESP_MNT/coreos/vmlinuz-a" \
-out_file "$FLAGS_output" -private_key "$FLAGS_private_key"
else
"$GENERATOR" \
-new_image "$DST_ROOT" \
-out_file "$FLAGS_output" -private_key "$FLAGS_private_key"
fi
fi
# Optionally verify the signature we just made
if [ -n "$FLAGS_public_key" ]; then
"$GENERATOR" -in_file "$FLAGS_output" -public_key "$FLAGS_public_key"
fi
# Generate the metadata payload
if [ -n "$FLAGS_metadata_output" ]; then
"$GENERATOR" \
-out_metadata "$FLAGS_metadata_output" \
-private_key "$FLAGS_private_key" \
-in_file "$FLAGS_output"
fi
trap - INT TERM EXIT
cleanup noexit
if [ "$DELTA" -eq "$FLAGS_TRUE" ]; then
echo "Done generating delta."
else
echo "Done generating full update."
fi