162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * 362306a36Sopenharmony_ci * BRIEF MODULE DESCRIPTION 462306a36Sopenharmony_ci * PROM library initialisation code, supports YAMON and U-Boot. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright 2000-2001, 2006, 2008 MontaVista Software Inc. 762306a36Sopenharmony_ci * Author: MontaVista Software, Inc. <source@mvista.com> 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * This file was derived from Carsten Langgaard's 1062306a36Sopenharmony_ci * arch/mips/mips-boards/xx files. 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * Carsten Langgaard, carstenl@mips.com 1362306a36Sopenharmony_ci * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * This program is free software; you can redistribute it and/or modify it 1662306a36Sopenharmony_ci * under the terms of the GNU General Public License as published by the 1762306a36Sopenharmony_ci * Free Software Foundation; either version 2 of the License, or (at your 1862306a36Sopenharmony_ci * option) any later version. 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 2162306a36Sopenharmony_ci * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 2262306a36Sopenharmony_ci * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 2362306a36Sopenharmony_ci * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2462306a36Sopenharmony_ci * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2562306a36Sopenharmony_ci * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 2662306a36Sopenharmony_ci * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 2762306a36Sopenharmony_ci * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2862306a36Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2962306a36Sopenharmony_ci * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3062306a36Sopenharmony_ci * 3162306a36Sopenharmony_ci * You should have received a copy of the GNU General Public License along 3262306a36Sopenharmony_ci * with this program; if not, write to the Free Software Foundation, Inc., 3362306a36Sopenharmony_ci * 675 Mass Ave, Cambridge, MA 02139, USA. 3462306a36Sopenharmony_ci */ 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#include <linux/init.h> 3762306a36Sopenharmony_ci#include <linux/kernel.h> 3862306a36Sopenharmony_ci#include <linux/memblock.h> 3962306a36Sopenharmony_ci#include <linux/sizes.h> 4062306a36Sopenharmony_ci#include <linux/string.h> 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#include <asm/bootinfo.h> 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ciint prom_argc; 4562306a36Sopenharmony_cichar **prom_argv; 4662306a36Sopenharmony_cichar **prom_envp; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_civoid __init prom_init_cmdline(void) 4962306a36Sopenharmony_ci{ 5062306a36Sopenharmony_ci int i; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci for (i = 1; i < prom_argc; i++) { 5362306a36Sopenharmony_ci strlcat(arcs_cmdline, prom_argv[i], COMMAND_LINE_SIZE); 5462306a36Sopenharmony_ci if (i < (prom_argc - 1)) 5562306a36Sopenharmony_ci strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE); 5662306a36Sopenharmony_ci } 5762306a36Sopenharmony_ci} 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_cichar *prom_getenv(char *envname) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci /* 6262306a36Sopenharmony_ci * Return a pointer to the given environment variable. 6362306a36Sopenharmony_ci * YAMON uses "name", "value" pairs, while U-Boot uses "name=value". 6462306a36Sopenharmony_ci */ 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci char **env = prom_envp; 6762306a36Sopenharmony_ci int i = strlen(envname); 6862306a36Sopenharmony_ci int yamon = (*env && strchr(*env, '=') == NULL); 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci while (*env) { 7162306a36Sopenharmony_ci if (yamon) { 7262306a36Sopenharmony_ci if (strcmp(envname, *env++) == 0) 7362306a36Sopenharmony_ci return *env; 7462306a36Sopenharmony_ci } else if (strncmp(envname, *env, i) == 0 && (*env)[i] == '=') 7562306a36Sopenharmony_ci return *env + i + 1; 7662306a36Sopenharmony_ci env++; 7762306a36Sopenharmony_ci } 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci return NULL; 8062306a36Sopenharmony_ci} 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_civoid __init prom_init(void) 8362306a36Sopenharmony_ci{ 8462306a36Sopenharmony_ci unsigned char *memsize_str; 8562306a36Sopenharmony_ci unsigned long memsize; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci prom_argc = (int)fw_arg0; 8862306a36Sopenharmony_ci prom_argv = (char **)fw_arg1; 8962306a36Sopenharmony_ci prom_envp = (char **)fw_arg2; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci prom_init_cmdline(); 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci memsize_str = prom_getenv("memsize"); 9462306a36Sopenharmony_ci if (!memsize_str || kstrtoul(memsize_str, 0, &memsize)) 9562306a36Sopenharmony_ci memsize = SZ_64M; /* minimum memsize is 64MB RAM */ 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci memblock_add(0, memsize); 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_cistatic inline unsigned char str2hexnum(unsigned char c) 10162306a36Sopenharmony_ci{ 10262306a36Sopenharmony_ci if (c >= '0' && c <= '9') 10362306a36Sopenharmony_ci return c - '0'; 10462306a36Sopenharmony_ci if (c >= 'a' && c <= 'f') 10562306a36Sopenharmony_ci return c - 'a' + 10; 10662306a36Sopenharmony_ci if (c >= 'A' && c <= 'F') 10762306a36Sopenharmony_ci return c - 'A' + 10; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci return 0; /* foo */ 11062306a36Sopenharmony_ci} 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistatic inline void str2eaddr(unsigned char *ea, unsigned char *str) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci int i; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci for (i = 0; i < 6; i++) { 11762306a36Sopenharmony_ci unsigned char num; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci if ((*str == '.') || (*str == ':')) 12062306a36Sopenharmony_ci str++; 12162306a36Sopenharmony_ci num = str2hexnum(*str++) << 4; 12262306a36Sopenharmony_ci num |= str2hexnum(*str++); 12362306a36Sopenharmony_ci ea[i] = num; 12462306a36Sopenharmony_ci } 12562306a36Sopenharmony_ci} 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ciint __init prom_get_ethernet_addr(char *ethernet_addr) 12862306a36Sopenharmony_ci{ 12962306a36Sopenharmony_ci char *ethaddr_str; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci /* Check the environment variables first */ 13262306a36Sopenharmony_ci ethaddr_str = prom_getenv("ethaddr"); 13362306a36Sopenharmony_ci if (!ethaddr_str) { 13462306a36Sopenharmony_ci /* Check command line */ 13562306a36Sopenharmony_ci ethaddr_str = strstr(arcs_cmdline, "ethaddr="); 13662306a36Sopenharmony_ci if (!ethaddr_str) 13762306a36Sopenharmony_ci return -1; 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci ethaddr_str += strlen("ethaddr="); 14062306a36Sopenharmony_ci } 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci str2eaddr(ethernet_addr, ethaddr_str); 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci return 0; 14562306a36Sopenharmony_ci} 146