firmware: preserve VPD in factory / incompatibe update modes (merge from ToT to R12)
Firmware updating should always preserve the content in RO/RW VPD area.
BUG=chrome-os-partner:3540
TEST=vpd -i RO_VPD -s ro=1; vpd -i RW_VPD -s rw=2;
vpd -l # put some value
flashrom -r bios_old.bin; # for backup
./updater --mode=factory; vpd -l # see values not changed
flashrom -r bios_new.bin; # new firmware
(mkdir old; cd old; dump_fmap -x ../bios_old.bin)
(mkdir new; cd new; dump_fmap -x ../bios_new.bin)
for X in old/*; do cmp "$X" "new/$(basnema $X)" || echo "diff"; done
# seeing only RO_VPD and RW_VPD are different
Change-Id: I4aeb6ba3096700b33d1734fcd15e784555ef3fcf
Cherry-Picked: http://gerrit.chromium.org/gerrit/#change,277
Reviewed-on: http://gerrit.chromium.org/gerrit/489
Reviewed-by: Hung-Te Lin <hungte@chromium.org>
Tested-by: Hung-Te Lin <hungte@chromium.org>
diff --git a/pack_dist/crosutil.sh b/pack_dist/crosutil.sh
index 870f5d0..2e8864d 100644
--- a/pack_dist/crosutil.sh
+++ b/pack_dist/crosutil.sh
@@ -17,6 +17,12 @@
[ -n "$hash1" ] && [ "$hash1" = "$hash2" ]
}
+# Gets file size.
+cros_get_file_size() {
+ [ -e "$1" ] || err_die "cros_get_file_size: invalid file: $1"
+ stat -c "%s" "$1" 2>/dev/null
+}
+
# Gets a Chrome OS system property (must exist).
cros_get_prop() {
crossystem "$@" || err_die "cannot get crossystem property: $@"
diff --git a/pack_dist/updater.sh b/pack_dist/updater.sh
index fd21b76..0bb6d31 100644
--- a/pack_dist/updater.sh
+++ b/pack_dist/updater.sh
@@ -171,10 +171,34 @@
# ----------------------------------------------------------------------------
# Helper functions
+# Preserve VPD data by merging sections from current system into target
+# firmware. Note this will change $IMAGE_MAIN so any processing to the file (ex,
+# prepare_image) must be invoked AFTER this call.
preserve_vpd() {
- # TODO(hungte) pull VPD from system live firmware and dupe into $IMAGE_MAIN.
- # NOTE: live may not have FMAP if it's not H2C, so backup+restore won't work.
- alert "Warning: VPD preserving is not implemented yet."
+ # Preserve VPD when updating an existing system (maya be legacy firmware or
+ # ChromeOS firmware). The system may not have FMAP, so we need to use
+ # emulation mode otherwise reading sections may fail.
+ if [ "${FLAGS_update_main}" = ${FLAGS_FALSE} ]; then
+ debug_msg "not updating main firmware, skip preserving VPD..."
+ return $FLAGS_TRUE
+ fi
+ debug_msg "preserving VPD..."
+ local temp_file="_vpd_temp.bin"
+ local vpd_list="-i RO_VPD -i RW_VPD"
+ silent_invoke "flashrom $TARGET_OPT_MAIN -r $temp_file" ||
+ die "Failed to read current main firmware."
+ local size_current="$(cros_get_file_size "$temp_file")"
+ local size_target="$(cros_get_file_size "$IMAGE_MAIN")"
+ if [ -z "$size_current" ] ||
+ [ "$size_current" = "0" ] ||
+ [ "$size_current" != "$size_target" ]; then
+ err_die "Failed to read preserve VPD content. Abort."
+ fi
+
+ local param="dummy:emulate=VARIABLE_SIZE,image=$IMAGE_MAIN,size=$size_current"
+ silent_invoke "flashrom -p $param $vpd_list -w $temp_file" ||
+ die "Failed to update VPD from existing system."
+ debug_msg "preserve_vpd: $IMAGE_MAIN updated."
}
preserve_hwid() {
@@ -572,8 +596,8 @@
err_die "You need to first disable hardware write protection switch."
fi
if [ "${FLAGS_update_main}" = "${FLAGS_TRUE}" ]; then
- prepare_main_image
preserve_vpd
+ prepare_main_image
# Preserve BMPFV
obtain_bmpfv
preserve_bmpfv