| #!/bin/sh | |
| # Copyright 2015 The ChromiumOS Authors | |
| # Use of this source code is governed by a BSD-style license that can be | |
| # found in the LICENSE file. | |
| # This script provides easy access to data contained in cros-regions.json (the | |
| # region database for Chromium OS). | |
| : ${CROS_VPD_SYS_RO:=/sys/firmware/vpd/ro} | |
| : ${CROS_REGIONS_DATABASE=/usr/share/misc/cros-regions.json} | |
| get_data_from_vpd() { | |
| local name="$1" | |
| # Use sysfs. All keys used by cros_region_data should live in RO partition. | |
| local value_file="${CROS_VPD_SYS_RO}/${name}" | |
| if [ -f "${value_file}" ]; then | |
| cat "${value_file}" | |
| fi | |
| } | |
| get_legacy_value_from_vpd() { | |
| local data_name="$1" | |
| local select_first="$2" | |
| local name value entry | |
| # There are some legacy VPD values that should override region data. | |
| local legacy_map=" | |
| locales=initial_locale | |
| time_zones=initial_timezone | |
| keyboards=keyboard_layout" | |
| for entry in ${legacy_map}; do | |
| name="${entry%=*}" | |
| if [ "${name}" != "${data_name}" ]; then | |
| continue | |
| fi | |
| name="${entry#*=}" | |
| value="$(get_data_from_vpd "${name}")" | |
| if [ -n "${value}" ]; then | |
| # Legacy values were defined in CSV so we have to convert output. | |
| if ${select_first}; then | |
| echo "${value%%,*}" | |
| else | |
| echo "${value}" | tr ',' '\n' | |
| fi | |
| return 0 | |
| fi | |
| done | |
| return 1 | |
| } | |
| lookup_data() { | |
| local name="$1" | |
| local region="$2" | |
| local select_first="$3" | |
| local output="" | |
| local pattern='.[$region][$name]' | |
| # Check value type and modify pattern for array. | |
| output="$(jq -c -r --arg region "${region}" --arg name "${name}" \ | |
| "${pattern}|arrays" "${CROS_REGIONS_DATABASE}")" | |
| if [ -n "${output}" ]; then | |
| if ${select_first}; then | |
| pattern="${pattern}[0]" | |
| else | |
| pattern="${pattern}[]" | |
| fi | |
| fi | |
| output="$(jq -c -r --arg region "${region}" --arg name "${name}" \ | |
| "${pattern}" "${CROS_REGIONS_DATABASE}")" | |
| if [ "${output}" != "null" ]; then | |
| echo "${output}" | |
| fi | |
| } | |
| # Use legacy VPD data to look up region code. | |
| reverse_lookup_region_by_timezone() { | |
| local value="$1" | |
| local region="$(jq -c -r --arg "timezone" "${value}" \ | |
| 'map(select(.time_zones == [$timezone]).region_code)[0]' \ | |
| "${CROS_REGIONS_DATABASE}")" | |
| if [ "${region}" != "null" ]; then | |
| echo "${region}" | |
| fi | |
| } | |
| report_available_fields() { | |
| if [ ! -f "${CROS_REGIONS_DATABASE}" ]; then | |
| return | |
| fi | |
| echo "Available fields in current system:" | |
| # Region 'us' should be always available. | |
| jq -c -r ".us|keys[]" "${CROS_REGIONS_DATABASE}" | sed 's/^/\t/' | |
| } | |
| usage() { | |
| echo "Usage: $1 [-s] data_name [region] | |
| -s: Selects only the first element (if value is list). | |
| data_name: Name of field inside ${CROS_REGIONS_DATABASE}. | |
| region: Region code to query. Read from VPD if omitted. | |
| " >&2 | |
| report_available_fields >&2 | |
| } | |
| main() { | |
| local region="" data_name="" | |
| local value="" | |
| local select_first=false | |
| local myname="$0" | |
| if [ "$1" = "-s" ]; then | |
| select_first=true | |
| shift | |
| fi | |
| case "$#" in | |
| 1) | |
| data_name="$1" | |
| ;; | |
| 2) | |
| data_name="$1" | |
| region="$2" | |
| ;; | |
| *) | |
| usage "${myname}" | |
| exit 1 | |
| ;; | |
| esac | |
| if [ -z "${region}" ]; then | |
| region="$(get_data_from_vpd region)" | |
| if get_legacy_value_from_vpd "${data_name}" ${select_first} ; then | |
| # Already printed. | |
| exit 0 | |
| fi | |
| if [ -z "${region}" ]; then | |
| region="$(reverse_lookup_region_by_timezone \ | |
| "$(get_data_from_vpd initial_timezone)")" | |
| fi | |
| fi | |
| lookup_data "${data_name}" "${region}" ${select_first} | |
| } | |
| set -e | |
| main "$@" |