blob: 05d4f958c6034c2e523a164db5fbe10b5112de1c [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright 2021 Google LLC
*/
#include <blk.h>
#include <chromecast/factory.h>
#include <common.h>
#include <linux/ctype.h>
#include <part.h>
#include <stdio.h>
#include <string.h>
#include <fs.h>
// same as PROPERTY_VALUE_MAX in Android
#define CHROMECAST_FACTORY_CONFIG_VALUE_MAX 92
static const struct {
const char *sku;
const char *region_code;
const char *locales;
} SKU_LIST[] = {
// default to use the first one
{ "US", "US", "en-US,es-US" },
{ "CA", "CA", "en-CA,fr-CA" },
{ "GB", "EU", "en-GB,en-IE" },
{ "DE", "EU", "de-DE" },
{ "FR", "EU", "fr-FR" },
{ "NL", "EU", "nl-NL,de-BE,fr-BE,nl-BE,de-AT" },
{ "NO", "EU", "nb-NO,fi-FI,sv-SE,da-DK,en-FI,en-GB" },
{ "IT", "EU", "it-IT,es-ES,fr-CH,de-CH,it-CH" },
{ "AU", "AU", "en-AU,en-NZ" },
{ "JP", "JP", "ja-JP" },
{ "KR", "KR", "ko-KR" },
{ "IN", "US", "en-IN,hi-IN" },
{ "LA", "MX", "es-MX,es-PE,es-CO,es-GT,es-HN,es-SV,es-NI,es-CR,es-PA,es-EC" },
{ "TW", "US", "zh-TW" },
{ "BR", "BR", "pt-BR" },
};
static loff_t get_factory_config(struct blk_desc *dev_desc, int part,
const char *name, char *buf,
const char *default_value)
{
int ret;
loff_t read_size;
char config_path[128];
snprintf(config_path, sizeof(config_path), "/configs/%s", name);
// NOTE: fs_read closes the device, so we need to reset the device
// for every fs_read.
ret = fs_set_blk_dev_with_part(dev_desc, part);
if (ret == 0) {
ret = fs_read(config_path, (ulong) buf, 0,
CHROMECAST_FACTORY_CONFIG_VALUE_MAX - 1,
&read_size);
}
if (ret) {
strlcpy(buf, default_value,
CHROMECAST_FACTORY_CONFIG_VALUE_MAX);
read_size = strlen(buf);
}
// There could be end of lines behind the value, remove them.
while (read_size > 0 && isspace(buf[read_size - 1])) {
read_size--;
}
buf[read_size] = '\0';
return read_size;
}
int load_chromecast_factory_configs(struct blk_desc *dev_desc)
{
disk_partition_t info;
int part;
int i;
char buf[CHROMECAST_FACTORY_CONFIG_VALUE_MAX];
int sku_id;
part = part_get_info_by_name(dev_desc, "factory", &info);
if (part == -1) {
printf("%s: factory partition not found\n", __func__);
return 1;
}
get_factory_config(dev_desc, part, "serial", buf,
"1234567890");
env_set("serial#", buf);
// Set the default value to Google owned local mac address.
get_factory_config(dev_desc, part, "mac_wifi", buf,
"02:1A:11:00:00:00");
env_set("mac_wifi", buf);
// Set the default value to Google owned local mac address.
get_factory_config(dev_desc, part, "mac_bt", buf,
"02:1A:11:00:00:11");
env_set("mac_bt", buf);
get_factory_config(dev_desc, part, "sku", buf,
SKU_LIST[0].sku);
sku_id = -1;
for (i = 0; i < sizeof(SKU_LIST) / sizeof(SKU_LIST[0]); i++) {
if (strcmp(buf, SKU_LIST[i].sku) == 0) {
sku_id = i;
break;
}
}
if (sku_id == -1) {
printf("unknown sku: %s, use the default: %s", buf,
SKU_LIST[0].sku);
strlcpy(buf, SKU_LIST[0].sku, sizeof(buf));
sku_id = 0;
}
env_set("sku", buf);
// Allow overwriting the default region_code and locales by factory
// config for testing.
get_factory_config(dev_desc, part, "region_code", buf,
SKU_LIST[sku_id].region_code);
env_set("region_code", buf);
get_factory_config(dev_desc, part, "locales", buf,
SKU_LIST[sku_id].locales);
env_set("locales", buf);
return 0;
}