mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-30 16:39:35 +00:00
54841ab50c
The hush shell dynamically allocates (and re-allocates) memory for the argument strings in the "char *argv[]" argument vector passed to commands. Any code that modifies these pointers will cause serious corruption of the malloc data structures and crash U-Boot, so make sure the compiler can check that no such modifications are being done by changing the code into "char * const argv[]". This modification is the result of debugging a strange crash caused after adding a new command, which used the following argument processing code which has been working perfectly fine in all Unix systems since version 6 - but not so in U-Boot: int main (int argc, char **argv) { while (--argc > 0 && **++argv == '-') { /* ====> */ while (*++*argv) { switch (**argv) { case 'd': debug++; break; ... default: usage (); } } } ... } The line marked "====>" will corrupt the malloc data structures and usually cause U-Boot to crash when the next command gets executed by the shell. With the modification, the compiler will prevent this with an error: increment of read-only location '*argv' N.B.: The code above can be trivially rewritten like this: while (--argc > 0 && **++argv == '-') { char *arg = *argv; while (*++arg) { switch (*arg) { ... Signed-off-by: Wolfgang Denk <wd@denx.de> Acked-by: Mike Frysinger <vapier@gentoo.org>
280 lines
7.1 KiB
C
280 lines
7.1 KiB
C
/*
|
|
* (C) Copyright 2000 - 2002
|
|
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
|
*
|
|
* See file CREDITS for list of people who contributed to this
|
|
* project.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation; either version 2 of
|
|
* the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
* MA 02111-1307 USA
|
|
*/
|
|
|
|
#include <config.h>
|
|
#include <mpc824x.h>
|
|
#include <common.h>
|
|
#include <command.h>
|
|
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
int checkcpu (void)
|
|
{
|
|
unsigned int pvr = get_pvr ();
|
|
unsigned int version = pvr >> 16;
|
|
unsigned char revision;
|
|
ulong clock = gd->cpu_clk;
|
|
char buf[32];
|
|
|
|
puts ("CPU: ");
|
|
|
|
switch (version) {
|
|
case CPU_TYPE_8240:
|
|
puts ("MPC8240");
|
|
break;
|
|
|
|
case CPU_TYPE_8245:
|
|
puts ("MPC8245");
|
|
break;
|
|
|
|
default:
|
|
return -1; /*not valid for this source */
|
|
}
|
|
|
|
CONFIG_READ_BYTE (REVID, revision);
|
|
|
|
if (revision) {
|
|
printf (" Revision %d.%d",
|
|
(revision & 0xf0) >> 4,
|
|
(revision & 0x0f));
|
|
} else {
|
|
return -1; /* no valid CPU revision info */
|
|
}
|
|
|
|
printf (" at %s MHz:", strmhz (buf, clock));
|
|
|
|
printf (" %u kB I-Cache", checkicache () >> 10);
|
|
printf (" %u kB D-Cache", checkdcache () >> 10);
|
|
|
|
puts ("\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* L1 i-cache */
|
|
|
|
int checkicache (void)
|
|
{
|
|
/*TODO*/
|
|
return 128 * 4 * 32;
|
|
};
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* L1 d-cache */
|
|
|
|
int checkdcache (void)
|
|
{
|
|
/*TODO*/
|
|
return 128 * 4 * 32;
|
|
|
|
};
|
|
|
|
/*------------------------------------------------------------------- */
|
|
|
|
int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|
{
|
|
ulong msr, addr;
|
|
|
|
/* Interrupts and MMU off */
|
|
__asm__ ("mtspr 81, 0");
|
|
|
|
/* Interrupts and MMU off */
|
|
__asm__ __volatile__ ("mfmsr %0":"=r" (msr):);
|
|
|
|
msr &= ~0x1030;
|
|
__asm__ __volatile__ ("mtmsr %0"::"r" (msr));
|
|
|
|
/*
|
|
* Trying to execute the next instruction at a non-existing address
|
|
* should cause a machine check, resulting in reset
|
|
*/
|
|
#ifdef CONFIG_SYS_RESET_ADDRESS
|
|
addr = CONFIG_SYS_RESET_ADDRESS;
|
|
#else
|
|
/*
|
|
* note: when CONFIG_SYS_MONITOR_BASE points to a RAM address,
|
|
* CONFIG_SYS_MONITOR_BASE - sizeof (ulong) is usually a valid
|
|
* address. Better pick an address known to be invalid on
|
|
* your system and assign it to CONFIG_SYS_RESET_ADDRESS.
|
|
* "(ulong)-1" used to be a good choice for many systems...
|
|
*/
|
|
addr = CONFIG_SYS_MONITOR_BASE - sizeof (ulong);
|
|
#endif
|
|
((void (*)(void)) addr) ();
|
|
return 1;
|
|
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
/*
|
|
* Get timebase clock frequency (like cpu_clk in Hz)
|
|
* This is the sys_logic_clk (memory bus) divided by 4
|
|
*/
|
|
unsigned long get_tbclk (void)
|
|
{
|
|
return ((get_bus_freq (0) + 2L) / 4L);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
/*
|
|
* The MPC824x has an integrated PCI controller known as the MPC107.
|
|
* The following are MPC107 Bridge Controller and PCI Support functions
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* This procedure reads a 32-bit address MPC107 register, and returns
|
|
* a 32 bit value. It swaps the address to little endian before
|
|
* writing it to config address, and swaps the value to big endian
|
|
* before returning to the caller.
|
|
*/
|
|
unsigned int mpc824x_mpc107_getreg (unsigned int regNum)
|
|
{
|
|
unsigned int temp;
|
|
|
|
/* swap the addr. to little endian */
|
|
*(volatile unsigned int *) CHRP_REG_ADDR = PCISWAP (regNum);
|
|
temp = *(volatile unsigned int *) CHRP_REG_DATA;
|
|
return PCISWAP (temp); /* swap the data upon return */
|
|
}
|
|
|
|
/*
|
|
* This procedure writes a 32-bit address MPC107 register. It swaps
|
|
* the address to little endian before writing it to config address.
|
|
*/
|
|
|
|
void mpc824x_mpc107_setreg (unsigned int regNum, unsigned int regVal)
|
|
{
|
|
/* swap the addr. to little endian */
|
|
*(volatile unsigned int *) CHRP_REG_ADDR = PCISWAP (regNum);
|
|
*(volatile unsigned int *) CHRP_REG_DATA = PCISWAP (regVal);
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
* Write a byte (8 bits) to a memory location.
|
|
*/
|
|
void mpc824x_mpc107_write8 (unsigned int addr, unsigned char data)
|
|
{
|
|
*(unsigned char *) addr = data;
|
|
__asm__ ("sync");
|
|
}
|
|
|
|
/*
|
|
* Write a word (16 bits) to a memory location after the value
|
|
* has been byte swapped (big to little endian or vice versa)
|
|
*/
|
|
|
|
void mpc824x_mpc107_write16 (unsigned int address, unsigned short data)
|
|
{
|
|
*(volatile unsigned short *) address = BYTE_SWAP_16_BIT (data);
|
|
__asm__ ("sync");
|
|
}
|
|
|
|
/*
|
|
* Write a long word (32 bits) to a memory location after the value
|
|
* has been byte swapped (big to little endian or vice versa)
|
|
*/
|
|
|
|
void mpc824x_mpc107_write32 (unsigned int address, unsigned int data)
|
|
{
|
|
*(volatile unsigned int *) address = LONGSWAP (data);
|
|
__asm__ ("sync");
|
|
}
|
|
|
|
/*
|
|
* Read a byte (8 bits) from a memory location.
|
|
*/
|
|
unsigned char mpc824x_mpc107_read8 (unsigned int addr)
|
|
{
|
|
return *(volatile unsigned char *) addr;
|
|
}
|
|
|
|
|
|
/*
|
|
* Read a word (16 bits) from a memory location, and byte swap the
|
|
* value before returning to the caller.
|
|
*/
|
|
unsigned short mpc824x_mpc107_read16 (unsigned int address)
|
|
{
|
|
unsigned short retVal;
|
|
|
|
retVal = BYTE_SWAP_16_BIT (*(unsigned short *) address);
|
|
return retVal;
|
|
}
|
|
|
|
|
|
/*
|
|
* Read a long word (32 bits) from a memory location, and byte
|
|
* swap the value before returning to the caller.
|
|
*/
|
|
unsigned int mpc824x_mpc107_read32 (unsigned int address)
|
|
{
|
|
unsigned int retVal;
|
|
|
|
retVal = LONGSWAP (*(unsigned int *) address);
|
|
return (retVal);
|
|
}
|
|
|
|
|
|
/*
|
|
* Read a register in the Embedded Utilities Memory Block address
|
|
* space.
|
|
* Input: regNum - register number + utility base address. Example,
|
|
* the base address of EPIC is 0x40000, the register number
|
|
* being passed is 0x40000+the address of the target register.
|
|
* (See epic.h for register addresses).
|
|
* Output: The 32 bit little endian value of the register.
|
|
*/
|
|
|
|
unsigned int mpc824x_eummbar_read (unsigned int regNum)
|
|
{
|
|
unsigned int temp;
|
|
|
|
temp = *(volatile unsigned int *) (EUMBBAR_VAL + regNum);
|
|
temp = PCISWAP (temp);
|
|
return temp;
|
|
}
|
|
|
|
|
|
/*
|
|
* Write a value to a register in the Embedded Utilities Memory
|
|
* Block address space.
|
|
* Input: regNum - register number + utility base address. Example,
|
|
* the base address of EPIC is 0x40000, the register
|
|
* number is 0x40000+the address of the target register.
|
|
* (See epic.h for register addresses).
|
|
* regVal - value to be written to the register.
|
|
*/
|
|
|
|
void mpc824x_eummbar_write (unsigned int regNum, unsigned int regVal)
|
|
{
|
|
*(volatile unsigned int *) (EUMBBAR_VAL + regNum) = PCISWAP (regVal);
|
|
return;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|