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