util: Add new utility 'vpd_icc' for per-device ICC management
Some devices will have each panel calibrated in factory and should have
device-specific ICC profile. This script helps to store and provision
ICC using VPD as backend storage.
To store:
vpd_icc [product_id].icc # product_id is panel ID in 8 hex digits
To provision:
vpd_icc
BUG=b:141297270
TEST=(set) vpd_icc 0080e000.icc
vpd -l # see 'display_profiles'
(get) vpd_icc
ls /var/cache/display_profiles # see 0080e000.icc
BRANCH=none
Change-Id: Ia913594c5fc517ea52632fe3ca6278407cbe6fa8
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vpd/+/2058225
Reviewed-by: Stimim Chen <stimim@chromium.org>
Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>
Commit-Queue: Agnes Cheng <agnescheng@google.com>
Tested-by: Agnes Cheng <agnescheng@google.com>
Auto-Submit: Agnes Cheng <agnescheng@google.com>
diff --git a/util/vpd_icc b/util/vpd_icc
new file mode 100755
index 0000000..aac0e07
--- /dev/null
+++ b/util/vpd_icc
@@ -0,0 +1,79 @@
+#!/bin/sh
+# Copyright 2020 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.
+#
+# Packs ICC profiles to VPD, or to create local ICC profile files from VPD.
+
+VPD_KEY="display_profiles"
+CACHE_DIR="/var/cache/display_profiles"
+ICC_EXT=".icc"
+
+error() {
+ echo "ERROR: $*" >&2
+}
+
+die() {
+ local msg="${1:-Aborted Execution.}"
+ error "${msg}"
+ exit 1
+}
+
+is_valid_product_id() {
+ local name="$1"
+ if [ "${#name}" = 8 ] && [ "$((0x${name}))" -gt 0 ]; then
+ return 0
+ fi
+ return 1
+}
+
+extract_from_vpd() {
+ local raw_value="$(vpd_get_value "${VPD_KEY}")"
+ if [ -z "${raw_value}" ]; then
+ return
+ fi
+ # raw_value format: product_id:base64(gzip(icc))
+ local product_id="${raw_value%%:*}"
+ local content="${raw_value#*:}"
+ if ! is_valid_product_id "${product_id}"; then
+ return
+ fi
+ local icc_path="${CACHE_DIR}/${product_id}${ICC_EXT}"
+ echo "${content}" | base64 -d | gzip -cd >"${icc_path}" ||
+ rm -f "${icc_path}"
+ if [ -s "${icc_path}" ]; then
+ echo "Exported ICC profile for ${product_id}"
+ fi
+}
+
+import_from_file() {
+ local path="$1"
+ local base="$(basename "${path}")"
+ local product_id="${base%%.*}"
+
+ if ! is_valid_product_id "${product_id}"; then
+ die "Invalid input file name (must be 8-digits hex): ${path}"
+ fi
+ local content="$(gzip -c <"${path}" | base64 -w 0)"
+ if [ -z "${content}" ]; then
+ die "Failed to encode from ${path}."
+ fi
+ local cmd="${VPD_KEY}=${product_id}:${content}"
+ echo "New VPD: ${cmd}"
+ vpd -i RO_VPD -s "${cmd}"
+}
+
+main() {
+ case "$#" in
+ 0)
+ extract_from_vpd
+ ;;
+ 1)
+ import_from_file "$1"
+ ;;
+ *)
+ die "Usage: $0 [ICCFile]"
+ ;;
+ esac
+}
+main "$@"