162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * PlanetCore configuration data support functions
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Author: Scott Wood <scottwood@freescale.com>
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Copyright (c) 2007 Freescale Semiconductor, Inc.
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include "stdio.h"
1162306a36Sopenharmony_ci#include "stdlib.h"
1262306a36Sopenharmony_ci#include "ops.h"
1362306a36Sopenharmony_ci#include "planetcore.h"
1462306a36Sopenharmony_ci#include "io.h"
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci/* PlanetCore passes information to the OS in the form of
1762306a36Sopenharmony_ci * a table of key=value strings, separated by newlines.
1862306a36Sopenharmony_ci *
1962306a36Sopenharmony_ci * The list is terminated by an empty string (i.e. two
2062306a36Sopenharmony_ci * consecutive newlines).
2162306a36Sopenharmony_ci *
2262306a36Sopenharmony_ci * To make it easier to parse, we first convert all the
2362306a36Sopenharmony_ci * newlines into null bytes.
2462306a36Sopenharmony_ci */
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_civoid planetcore_prepare_table(char *table)
2762306a36Sopenharmony_ci{
2862306a36Sopenharmony_ci	do {
2962306a36Sopenharmony_ci		if (*table == '\n')
3062306a36Sopenharmony_ci			*table = 0;
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci		table++;
3362306a36Sopenharmony_ci	} while (*(table - 1) || *table != '\n');
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	*table = 0;
3662306a36Sopenharmony_ci}
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ciconst char *planetcore_get_key(const char *table, const char *key)
3962306a36Sopenharmony_ci{
4062306a36Sopenharmony_ci	int keylen = strlen(key);
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	do {
4362306a36Sopenharmony_ci		if (!strncmp(table, key, keylen) && table[keylen] == '=')
4462306a36Sopenharmony_ci			return table + keylen + 1;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci		table += strlen(table) + 1;
4762306a36Sopenharmony_ci	} while (strlen(table) != 0);
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	return NULL;
5062306a36Sopenharmony_ci}
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ciint planetcore_get_decimal(const char *table, const char *key, u64 *val)
5362306a36Sopenharmony_ci{
5462306a36Sopenharmony_ci	const char *str = planetcore_get_key(table, key);
5562306a36Sopenharmony_ci	if (!str)
5662306a36Sopenharmony_ci		return 0;
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	*val = strtoull(str, NULL, 10);
5962306a36Sopenharmony_ci	return 1;
6062306a36Sopenharmony_ci}
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ciint planetcore_get_hex(const char *table, const char *key, u64 *val)
6362306a36Sopenharmony_ci{
6462306a36Sopenharmony_ci	const char *str = planetcore_get_key(table, key);
6562306a36Sopenharmony_ci	if (!str)
6662306a36Sopenharmony_ci		return 0;
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	*val = strtoull(str, NULL, 16);
6962306a36Sopenharmony_ci	return 1;
7062306a36Sopenharmony_ci}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_cistatic u64 mac_table[4] = {
7362306a36Sopenharmony_ci	0x000000000000,
7462306a36Sopenharmony_ci	0x000000800000,
7562306a36Sopenharmony_ci	0x000000400000,
7662306a36Sopenharmony_ci	0x000000c00000,
7762306a36Sopenharmony_ci};
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_civoid planetcore_set_mac_addrs(const char *table)
8062306a36Sopenharmony_ci{
8162306a36Sopenharmony_ci	u8 addr[4][6];
8262306a36Sopenharmony_ci	u64 int_addr;
8362306a36Sopenharmony_ci	u32 i;
8462306a36Sopenharmony_ci	int j;
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	if (!planetcore_get_hex(table, PLANETCORE_KEY_MAC_ADDR, &int_addr))
8762306a36Sopenharmony_ci		return;
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	for (i = 0; i < 4; i++) {
9062306a36Sopenharmony_ci		u64 this_dev_addr = (int_addr & ~0x000000c00000) |
9162306a36Sopenharmony_ci		                    mac_table[i];
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci		for (j = 5; j >= 0; j--) {
9462306a36Sopenharmony_ci			addr[i][j] = this_dev_addr & 0xff;
9562306a36Sopenharmony_ci			this_dev_addr >>= 8;
9662306a36Sopenharmony_ci		}
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci		dt_fixup_mac_address(i, addr[i]);
9962306a36Sopenharmony_ci	}
10062306a36Sopenharmony_ci}
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_cistatic char prop_buf[MAX_PROP_LEN];
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_civoid planetcore_set_stdout_path(const char *table)
10562306a36Sopenharmony_ci{
10662306a36Sopenharmony_ci	char *path;
10762306a36Sopenharmony_ci	const char *label;
10862306a36Sopenharmony_ci	void *node, *chosen;
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci	label = planetcore_get_key(table, PLANETCORE_KEY_SERIAL_PORT);
11162306a36Sopenharmony_ci	if (!label)
11262306a36Sopenharmony_ci		return;
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	node = find_node_by_prop_value_str(NULL, "linux,planetcore-label",
11562306a36Sopenharmony_ci	                                   label);
11662306a36Sopenharmony_ci	if (!node)
11762306a36Sopenharmony_ci		return;
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	path = get_path(node, prop_buf, MAX_PROP_LEN);
12062306a36Sopenharmony_ci	if (!path)
12162306a36Sopenharmony_ci		return;
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	chosen = finddevice("/chosen");
12462306a36Sopenharmony_ci	if (!chosen)
12562306a36Sopenharmony_ci		chosen = create_node(NULL, "chosen");
12662306a36Sopenharmony_ci	if (!chosen)
12762306a36Sopenharmony_ci		return;
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci	setprop_str(chosen, "linux,stdout-path", path);
13062306a36Sopenharmony_ci}
131