18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * PlanetCore configuration data support functions
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Author: Scott Wood <scottwood@freescale.com>
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Copyright (c) 2007 Freescale Semiconductor, Inc.
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include "stdio.h"
118c2ecf20Sopenharmony_ci#include "stdlib.h"
128c2ecf20Sopenharmony_ci#include "ops.h"
138c2ecf20Sopenharmony_ci#include "planetcore.h"
148c2ecf20Sopenharmony_ci#include "io.h"
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci/* PlanetCore passes information to the OS in the form of
178c2ecf20Sopenharmony_ci * a table of key=value strings, separated by newlines.
188c2ecf20Sopenharmony_ci *
198c2ecf20Sopenharmony_ci * The list is terminated by an empty string (i.e. two
208c2ecf20Sopenharmony_ci * consecutive newlines).
218c2ecf20Sopenharmony_ci *
228c2ecf20Sopenharmony_ci * To make it easier to parse, we first convert all the
238c2ecf20Sopenharmony_ci * newlines into null bytes.
248c2ecf20Sopenharmony_ci */
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_civoid planetcore_prepare_table(char *table)
278c2ecf20Sopenharmony_ci{
288c2ecf20Sopenharmony_ci	do {
298c2ecf20Sopenharmony_ci		if (*table == '\n')
308c2ecf20Sopenharmony_ci			*table = 0;
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci		table++;
338c2ecf20Sopenharmony_ci	} while (*(table - 1) || *table != '\n');
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	*table = 0;
368c2ecf20Sopenharmony_ci}
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ciconst char *planetcore_get_key(const char *table, const char *key)
398c2ecf20Sopenharmony_ci{
408c2ecf20Sopenharmony_ci	int keylen = strlen(key);
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	do {
438c2ecf20Sopenharmony_ci		if (!strncmp(table, key, keylen) && table[keylen] == '=')
448c2ecf20Sopenharmony_ci			return table + keylen + 1;
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci		table += strlen(table) + 1;
478c2ecf20Sopenharmony_ci	} while (strlen(table) != 0);
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	return NULL;
508c2ecf20Sopenharmony_ci}
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ciint planetcore_get_decimal(const char *table, const char *key, u64 *val)
538c2ecf20Sopenharmony_ci{
548c2ecf20Sopenharmony_ci	const char *str = planetcore_get_key(table, key);
558c2ecf20Sopenharmony_ci	if (!str)
568c2ecf20Sopenharmony_ci		return 0;
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	*val = strtoull(str, NULL, 10);
598c2ecf20Sopenharmony_ci	return 1;
608c2ecf20Sopenharmony_ci}
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ciint planetcore_get_hex(const char *table, const char *key, u64 *val)
638c2ecf20Sopenharmony_ci{
648c2ecf20Sopenharmony_ci	const char *str = planetcore_get_key(table, key);
658c2ecf20Sopenharmony_ci	if (!str)
668c2ecf20Sopenharmony_ci		return 0;
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	*val = strtoull(str, NULL, 16);
698c2ecf20Sopenharmony_ci	return 1;
708c2ecf20Sopenharmony_ci}
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_cistatic u64 mac_table[4] = {
738c2ecf20Sopenharmony_ci	0x000000000000,
748c2ecf20Sopenharmony_ci	0x000000800000,
758c2ecf20Sopenharmony_ci	0x000000400000,
768c2ecf20Sopenharmony_ci	0x000000c00000,
778c2ecf20Sopenharmony_ci};
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_civoid planetcore_set_mac_addrs(const char *table)
808c2ecf20Sopenharmony_ci{
818c2ecf20Sopenharmony_ci	u8 addr[4][6];
828c2ecf20Sopenharmony_ci	u64 int_addr;
838c2ecf20Sopenharmony_ci	u32 i;
848c2ecf20Sopenharmony_ci	int j;
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	if (!planetcore_get_hex(table, PLANETCORE_KEY_MAC_ADDR, &int_addr))
878c2ecf20Sopenharmony_ci		return;
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	for (i = 0; i < 4; i++) {
908c2ecf20Sopenharmony_ci		u64 this_dev_addr = (int_addr & ~0x000000c00000) |
918c2ecf20Sopenharmony_ci		                    mac_table[i];
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci		for (j = 5; j >= 0; j--) {
948c2ecf20Sopenharmony_ci			addr[i][j] = this_dev_addr & 0xff;
958c2ecf20Sopenharmony_ci			this_dev_addr >>= 8;
968c2ecf20Sopenharmony_ci		}
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci		dt_fixup_mac_address(i, addr[i]);
998c2ecf20Sopenharmony_ci	}
1008c2ecf20Sopenharmony_ci}
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_cistatic char prop_buf[MAX_PROP_LEN];
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_civoid planetcore_set_stdout_path(const char *table)
1058c2ecf20Sopenharmony_ci{
1068c2ecf20Sopenharmony_ci	char *path;
1078c2ecf20Sopenharmony_ci	const char *label;
1088c2ecf20Sopenharmony_ci	void *node, *chosen;
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	label = planetcore_get_key(table, PLANETCORE_KEY_SERIAL_PORT);
1118c2ecf20Sopenharmony_ci	if (!label)
1128c2ecf20Sopenharmony_ci		return;
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	node = find_node_by_prop_value_str(NULL, "linux,planetcore-label",
1158c2ecf20Sopenharmony_ci	                                   label);
1168c2ecf20Sopenharmony_ci	if (!node)
1178c2ecf20Sopenharmony_ci		return;
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	path = get_path(node, prop_buf, MAX_PROP_LEN);
1208c2ecf20Sopenharmony_ci	if (!path)
1218c2ecf20Sopenharmony_ci		return;
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	chosen = finddevice("/chosen");
1248c2ecf20Sopenharmony_ci	if (!chosen)
1258c2ecf20Sopenharmony_ci		chosen = create_node(NULL, "chosen");
1268c2ecf20Sopenharmony_ci	if (!chosen)
1278c2ecf20Sopenharmony_ci		return;
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	setprop_str(chosen, "linux,stdout-path", path);
1308c2ecf20Sopenharmony_ci}
131