mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-24 21:54:01 +00:00
Initial revision
This commit is contained in:
parent
e221174377
commit
47d1a6e1ed
10 changed files with 4431 additions and 0 deletions
302
board/cray/L1/L1.c
Normal file
302
board/cray/L1/L1.c
Normal file
|
@ -0,0 +1,302 @@
|
|||
/*
|
||||
* (C) Copyright 2000
|
||||
* 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 <common.h>
|
||||
#include <asm/processor.h>
|
||||
#include <405gp_i2c.h>
|
||||
#include <command.h>
|
||||
#include <cmd_nvedit.h>
|
||||
#include <cmd_bootm.h>
|
||||
#include <rtc.h>
|
||||
#include <net.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#define L1_MEMSIZE (32*1024*1024)
|
||||
|
||||
/* the std. DHCP stufff */
|
||||
#define DHCP_ROUTER 3
|
||||
#define DHCP_NETMASK 1
|
||||
#define DHCP_BOOTFILE 67
|
||||
#define DHCP_ROOTPATH 17
|
||||
#define DHCP_HOSTNAME 12
|
||||
|
||||
/* some extras used by CRAY
|
||||
*
|
||||
* on the server this looks like:
|
||||
*
|
||||
* option L1-initrd-image code 224 = string;
|
||||
* option L1-initrd-image "/opt/craysv2/craymcu/l1/flash/initrd.image"
|
||||
*/
|
||||
#define DHCP_L1_INITRD 224
|
||||
|
||||
/* new, [better?] way via official vendor-extensions, defining an option
|
||||
* space.
|
||||
* on the server this looks like:
|
||||
*
|
||||
* option space U-Boot;
|
||||
* option U-Boot.initrd code 3 = string;
|
||||
* option U-Boot.bootcmd code 4 = string;
|
||||
* option U-Boot.bootflags code 5 = string;
|
||||
* option U-Boot.rootdev code 6 = string;
|
||||
*/
|
||||
#define DHCP_VENDOR_SPECX 43
|
||||
#define DHCP_VX_INITRD 3
|
||||
#define DHCP_VX_BOOTCMD 4
|
||||
#define DHCP_VX_BOOTFLAGS 5
|
||||
#define DHCP_VX_ROOTDEV 6
|
||||
|
||||
/* Things DHCP server can tellme about. If there's no flash address, then
|
||||
* they dont participate in 'update' to flash, and we force their values
|
||||
* back to '0' every boot to be sure to get them fresh from DHCP. Yes, I
|
||||
* know this is a pain...
|
||||
*
|
||||
* If I get no bootfile, boot from flash. If rootpath, use that. If no
|
||||
* rootpath use initrd in flash.
|
||||
*/
|
||||
typedef struct dhcp_item_s {
|
||||
u8 dhcp_option;
|
||||
u8 dhcp_vendor_option;
|
||||
char *dhcpvalue;
|
||||
char *envname;
|
||||
} dhcp_item_t;
|
||||
static dhcp_item_t Things[] = {
|
||||
{DHCP_ROUTER, 0, NULL, "gateway"},
|
||||
{DHCP_NETMASK, 0, NULL, "netmask"},
|
||||
{DHCP_BOOTFILE, 0, NULL, "bootfile"},
|
||||
{DHCP_ROOTPATH, 0, NULL, "rootpath"},
|
||||
{DHCP_HOSTNAME, 0, NULL, "hostname"},
|
||||
{DHCP_L1_INITRD, 0, NULL, "initrd"},
|
||||
/* and the other way.. */
|
||||
{DHCP_VENDOR_SPECX, DHCP_VX_INITRD, NULL, "initrd"},
|
||||
{DHCP_VENDOR_SPECX, DHCP_VX_BOOTCMD, NULL, "bootcmd"},
|
||||
{DHCP_VENDOR_SPECX, DHCP_VX_BOOTFLAGS, NULL, NULL},
|
||||
{DHCP_VENDOR_SPECX, DHCP_VX_ROOTDEV, NULL, NULL},
|
||||
};
|
||||
|
||||
#define N_THINGS ((sizeof(Things))/(sizeof(dhcp_item_t)))
|
||||
|
||||
static void init_ecc_sdram (void);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
int board_pre_init (void)
|
||||
{
|
||||
init_ecc_sdram ();
|
||||
mtdcr (uicsr, 0xFFFFFFFF); /* clear all ints */
|
||||
mtdcr (uicer, 0x00000000); /* disable all ints */
|
||||
mtdcr (uiccr, 0x00000020); /* set all but FPGA SMI to be non-critical */
|
||||
mtdcr (uicpr, 0xFFFFFFE0); /* set int polarities */
|
||||
mtdcr (uictr, 0x10000000); /* set int trigger levels */
|
||||
mtdcr (uicvcr, 0x00000001); /* set vect base=0,INT0 highest priority */
|
||||
mtdcr (uicsr, 0xFFFFFFFF); /* clear all ints */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
int checkboard (void)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
int misc_init_r (void)
|
||||
{
|
||||
unsigned char *s, *e;
|
||||
image_header_t *hdr;
|
||||
time_t timestamp;
|
||||
struct rtc_time tm;
|
||||
|
||||
hdr = (image_header_t *) (CFG_MONITOR_BASE - sizeof (image_header_t));
|
||||
timestamp = (time_t) hdr->ih_time;
|
||||
to_tm (timestamp, &tm);
|
||||
printf ("Welcome to U-Boot on Cray L1. Compiled %4d-%02d-%02d %2d:%02d:%02d (UTC)\n", tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
|
||||
|
||||
#define FACTORY_SETTINGS 0xFFFC0000
|
||||
if ((s = getenv ("ethaddr")) == NULL) {
|
||||
e = (unsigned char *) (FACTORY_SETTINGS);
|
||||
if (*(e + 0) != '0'
|
||||
|| *(e + 1) != '0'
|
||||
|| *(e + 2) != ':'
|
||||
|| *(e + 3) != '4' || *(e + 4) != '0' || *(e + 17) != '\0') {
|
||||
printf ("No valid MAC address in flash location 0x3C0000!\n");
|
||||
} else {
|
||||
printf ("Factory MAC: %s\n", e);
|
||||
setenv ("ethaddr", e);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
long int initdram (int board_type)
|
||||
{
|
||||
return (L1_MEMSIZE);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* stubs so we can print dates w/o any nvram RTC.*/
|
||||
void rtc_get (struct rtc_time *tmp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
void rtc_set (struct rtc_time *tmp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
void rtc_reset (void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Do sdram bank init in C so I can read it..
|
||||
*/
|
||||
static void init_ecc_sdram (void)
|
||||
{
|
||||
unsigned long tmp, *p;
|
||||
|
||||
/* write SDRAM bank 0 register */
|
||||
mtdcr (memcfga, mem_mb0cf);
|
||||
mtdcr (memcfgd, 0x00062001);
|
||||
|
||||
/* Set the SDRAM Timing reg, SDTR1 and the refresh timer reg, RTR. */
|
||||
/* To set the appropriate timings, we need to know the SDRAM speed. */
|
||||
/* We can use the PLB speed since the SDRAM speed is the same as */
|
||||
/* the PLB speed. The PLB speed is the FBK divider times the */
|
||||
/* 405GP reference clock, which on the L1 is 25Mhz. */
|
||||
/* Thus, if FBK div is 2, SDRAM is 50Mhz; if FBK div is 3, SDRAM is */
|
||||
/* 150Mhz; if FBK is 3, SDRAM is 150Mhz. */
|
||||
|
||||
/* divisor = ((mfdcr(strap)>> 28) & 0x3); */
|
||||
|
||||
/* write SDRAM timing for 100Mhz. */
|
||||
mtdcr (memcfga, mem_sdtr1);
|
||||
mtdcr (memcfgd, 0x0086400D);
|
||||
|
||||
/* write SDRAM refresh interval register */
|
||||
mtdcr (memcfga, mem_rtr);
|
||||
mtdcr (memcfgd, 0x05F00000);
|
||||
udelay (200);
|
||||
|
||||
/* sdram controller.*/
|
||||
mtdcr (memcfga, mem_mcopt1);
|
||||
mtdcr (memcfgd, 0x90800000);
|
||||
udelay (200);
|
||||
|
||||
/* disable ECC on all banks */
|
||||
mtdcr (memcfga, mem_ecccf);
|
||||
tmp = mfdcr (memcfgd);
|
||||
tmp &= 0xff0fffff;
|
||||
mtdcr (memcfga, mem_ecccf);
|
||||
mtdcr (memcfgd, tmp);
|
||||
|
||||
/* set up SDRAM Controller with ECC enabled */
|
||||
mtdcr (memcfga, mem_mcopt1);
|
||||
tmp = (mfdcr (memcfgd) & ~0xFFE00000) | 0x90800000;
|
||||
mtdcr (memcfga, mem_mcopt1);
|
||||
mtdcr (memcfgd, tmp);
|
||||
udelay (600);
|
||||
|
||||
/* fill all the memory */
|
||||
for (p = (unsigned long) 0; ((unsigned long) p < L1_MEMSIZE);
|
||||
*p++ = 0L);
|
||||
udelay (400);
|
||||
mtdcr (memcfga, mem_ecccf);
|
||||
tmp = mfdcr (memcfgd);
|
||||
|
||||
/* enable ECC on bank 0 */
|
||||
tmp |= 0x00800000;
|
||||
mtdcr (memcfgd, tmp);
|
||||
udelay (400);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
static u8 *dhcp_env_update (u8 thing, u8 * pop)
|
||||
{
|
||||
u8 i, oplen;
|
||||
|
||||
oplen = *(pop + 1);
|
||||
|
||||
if ((Things[thing].dhcpvalue = malloc (oplen)) == NULL) {
|
||||
printf ("Whoops! failed to malloc space for DHCP thing %s\n",
|
||||
Things[thing].envname);
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; (i < oplen); i++)
|
||||
if ((*(Things[thing].dhcpvalue + i) = *(pop + 2 + i)) == ' ')
|
||||
break;
|
||||
*(Things[thing].dhcpvalue + i) = '\0';
|
||||
|
||||
/* set env. */
|
||||
if (Things[thing].envname)
|
||||
setenv (Things[thing].envname, Things[thing].dhcpvalue);
|
||||
return (Things[thing].dhcpvalue);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
u8 *dhcp_vendorex_prep (u8 * e)
|
||||
{
|
||||
u8 thing;
|
||||
|
||||
/* ask for the things I want. */
|
||||
*e++ = 55; /* Parameter Request List */
|
||||
*e++ = N_THINGS;
|
||||
for (thing = 0; thing < N_THINGS; thing++)
|
||||
*e++ = Things[thing].dhcp_option;
|
||||
*e++ = 255;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* .. return NULL means it wasnt mine, non-null means I got it..*/
|
||||
u8 *dhcp_vendorex_proc (u8 * pop)
|
||||
{
|
||||
u8 oplen, *sub_op, sub_oplen, *retval;
|
||||
u8 thing = 0;
|
||||
|
||||
retval = NULL;
|
||||
oplen = *(pop + 1);
|
||||
/* if pop is vender spec indicator, there are sub-options. */
|
||||
if (*pop == DHCP_VENDOR_SPECX) {
|
||||
for (sub_op = pop + 2;
|
||||
oplen && (sub_oplen = *(sub_op + 1));
|
||||
oplen -= sub_oplen, sub_op += (sub_oplen + 2)) {
|
||||
for (thing = 0; thing < N_THINGS; thing++) {
|
||||
if (*sub_op == Things[thing].dhcp_vendor_option) {
|
||||
if (!(retval = dhcp_env_update (thing, sub_op))) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (thing = 0; thing < N_THINGS; thing++) {
|
||||
if (*pop == Things[thing].dhcp_option)
|
||||
if (!(retval = dhcp_env_update (thing, pop)))
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return (thing >= N_THINGS ? NULL : pop);
|
||||
}
|
44
board/cray/L1/L1.h
Normal file
44
board/cray/L1/L1.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* (C) Copyright 2000
|
||||
* 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
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* FLASH Memory Map as used by CRAY L1, 4MB AMD29F032B flash chip
|
||||
*
|
||||
* Start Address Length
|
||||
* +++++++++++++++++++++++++ 0xFFC0_0000 Start of Flash -----------------
|
||||
* | Failsafe Linux Image | (1M)
|
||||
* +=======================+ 0xFFD0_0000
|
||||
* | (Reserved FlashFiles) | (1M)
|
||||
* +=======================+ 0xFFE0_0000
|
||||
* | Failsafe RootFS | (1M)
|
||||
* +=======================+ 0xFFF0_0000
|
||||
* | |
|
||||
* | U N U S E D |
|
||||
* | |
|
||||
* +-----------------------+ 0xFFFD_0000 U-Boot image header (64 bytes)
|
||||
* | environment settings | (64k)
|
||||
* +-----------------------+ 0xFFFE_0000 U-Boot image header (64 bytes)
|
||||
* | U-Boot | 0xFFFE_0040 _start of U-Boot
|
||||
* | | 0xFFFE_FFFC reset vector - branch to _start
|
||||
* +++++++++++++++++++++++++ 0xFFFF_FFFF End of Flash -----------------
|
||||
*****************************************************************************/
|
60
board/evb64260/local.h
Normal file
60
board/evb64260/local.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* include/local.h - local configuration options, board specific
|
||||
*/
|
||||
|
||||
#ifndef __LOCAL_H
|
||||
#define __LOCAL_H
|
||||
|
||||
/*
|
||||
* High Level Configuration Options
|
||||
* (easy to change)
|
||||
*/
|
||||
|
||||
/* This tells U-Boot that the config options are compiled in */
|
||||
/* #undef ENV_IS_EMBEDDED */
|
||||
/* Don't touch this! U-Boot figures this out based on other
|
||||
* magic. */
|
||||
|
||||
/* Uncomment and define any of the below options */
|
||||
|
||||
/* #define CONFIG_750CX */ /* The 750CX doesn't support as many things in L2CR */
|
||||
/* Note: If you defined CONFIG_EVB64260_750CX this */
|
||||
/* gets defined automatically. */
|
||||
|
||||
/* These want string arguments */
|
||||
/* #define CONFIG_BOOTARGS */
|
||||
/* #define CONFIG_BOOTCOMMAND */
|
||||
/* #define CONFIG_RAMBOOTCOMMAND */
|
||||
/* #define CONFIG_NFSBOOTCOMMAND */
|
||||
/* #define CFG_AUTOLOAD */
|
||||
/* #define CONFIG_PREBOOT */
|
||||
|
||||
/* These don't */
|
||||
|
||||
/* #define CONFIG_BOOTDELAY */
|
||||
/* #define CONFIG_BAUDRATE */
|
||||
/* #define CONFIG_LOADS_ECHO */
|
||||
/* #define CONFIG_ETHADDR */
|
||||
/* #define CONFIG_ETH2ADDR */
|
||||
/* #define CONFIG_ETH3ADDR */
|
||||
/* #define CONFIG_IPADDR */
|
||||
/* #define CONFIG_SERVERIP */
|
||||
/* #define CONFIG_ROOTPATH */
|
||||
/* #define CONFIG_GATEWAYIP */
|
||||
/* #define CONFIG_NETMASK */
|
||||
/* #define CONFIG_HOSTNAME */
|
||||
/* #define CONFIG_BOOTFILE */
|
||||
/* #define CONFIG_LOADADDR */
|
||||
|
||||
/* these hardware addresses are pretty bogus, please change them to
|
||||
suit your needs */
|
||||
|
||||
/* first ethernet */
|
||||
#define CONFIG_ETHADDR 00:11:22:33:44:55
|
||||
|
||||
/* next two ethernet hwaddrs */
|
||||
#define CONFIG_ETH1ADDR 00:11:22:33:44:66
|
||||
#define CONFIG_ETH2ADDR 00:11:22:33:44:77
|
||||
|
||||
#define CONFIG_ENV_OVERWRITE
|
||||
#endif /* __CONFIG_H */
|
25
board/genietv/genietv.h
Normal file
25
board/genietv/genietv.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* The GENIETV is using the following physical memorymap (copied from
|
||||
* the FADS configuration):
|
||||
*
|
||||
* ff020000 -> ff02ffff : pcmcia
|
||||
* ff010000 -> ff01ffff : BCSR connected to CS1, setup by 8xxROM
|
||||
* ff000000 -> ff00ffff : IMAP internal in the cpu
|
||||
* 02800000 -> 0287ffff : flash connected to CS0
|
||||
* 00000000 -> nnnnnnnn : sdram setup by U-Boot
|
||||
*
|
||||
* CS pins are connected as follows:
|
||||
*
|
||||
* CS0 -512Kb boot flash
|
||||
* CS1 - SDRAM #1
|
||||
* CS2 - SDRAM #2
|
||||
* CS3 - Flash #1
|
||||
* CS4 - Flash #2
|
||||
* CS5 - LON (if present)
|
||||
* CS6 - PCMCIA #1
|
||||
* CS7 - PCMCIA #2
|
||||
*
|
||||
* Ports are configured as follows:
|
||||
*
|
||||
* PA7 - SDRAM banks enable
|
||||
*/
|
161
board/pn62/pn62.h
Normal file
161
board/pn62/pn62.h
Normal file
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* (C) Copyright 2002 Wolfgang Grandegger <wg@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
|
||||
*/
|
||||
|
||||
#ifndef _PN62_H_
|
||||
#define _PN62_H_
|
||||
|
||||
/*
|
||||
* Definitions for the Intel Bridge 21554 or 21555.
|
||||
*/
|
||||
#define I2155X_VPD_ADDR 0xe6
|
||||
#define I2155X_VPD_DATA 0xe8
|
||||
|
||||
#define I2155X_VPD_START 0x80
|
||||
#define I2155X_VPD_SN_START 0x80
|
||||
#define I2155X_VPD_SN_SIZE 0x10
|
||||
#define I2155X_VPD_MAC0_START 0x90
|
||||
#define I2155X_VPD_MAC1_START 0x96
|
||||
|
||||
#define I2155X_SCRAPAD_ADDR 0xa8
|
||||
#define I2155X_SCRAPAD_MAX 8
|
||||
|
||||
#define I2155X_BAR2_BASE 0x98
|
||||
#define I2155X_BAR3_BASE 0x9c
|
||||
#define I2155X_BAR4_BASE 0xa0
|
||||
|
||||
#define I2155X_BAR2_SETUP 0xb0
|
||||
#define I2155X_BAR3_SETUP 0xb4
|
||||
#define I2155X_BAR4_SETUP 0xb8
|
||||
|
||||
/*
|
||||
* Interrupt request numbers
|
||||
*/
|
||||
#define PN62_IRQ_HOST 0x0
|
||||
#define PN62_IRQ_PLX9054 0x1
|
||||
#define PN62_IRQ_ETH0 0x2
|
||||
#define PN62_IRQ_ETH1 0x3
|
||||
#define PN62_IRQ_COM1 0x4
|
||||
#define PN62_IRQ_COM2 0x4
|
||||
|
||||
/*
|
||||
* Miscellaneous definitons.
|
||||
*/
|
||||
#define PN62_SMEM_DEFAULT 0x1f00000
|
||||
|
||||
/*
|
||||
* Definitions for boot protocol using Scratchpad registers.
|
||||
*/
|
||||
#define BOOT_DONE 0
|
||||
#define BOOT_DONE_CLEAR 0x00dead00
|
||||
#define BOOT_DONE_ERROR 0xbad0dead
|
||||
#define BOOT_DONE_U_BOOT 0x12345678
|
||||
#define BOOT_DONE_LINUX 0x87654321
|
||||
#define BOOT_CMD 1
|
||||
#define BOOT_CMD_MOVE 0x1
|
||||
#define BOOT_CMD_BOOT 0x2
|
||||
#define BOOT_DATA 2
|
||||
#define BOOT_PROTO 3
|
||||
#define BOOT_PROTO_READY 0x23456789
|
||||
#define BOOT_PROTO_CLEAR 0x00000000
|
||||
#define BOOT_STATUS 4
|
||||
|
||||
/*
|
||||
* LED Definitions:
|
||||
*/
|
||||
#define PN62_LED_BASE 0xff800300
|
||||
#define PN62_LED_MAX 12
|
||||
|
||||
/*
|
||||
* LED0 - 7 mounted on top of board, D1 - D8
|
||||
* LED8 - 11 upper four LEDs on the front panel of the board.
|
||||
*/
|
||||
#define LED_0 0x00 /* OFF */
|
||||
#define LED_1 0x01 /* ON */
|
||||
#define LED_SLOW_CLOCK 0x02 /* SLOW 1Hz ish */
|
||||
#define LED_nSLOW_CLOCK 0x03 /* inverse of above */
|
||||
#define LED_WATCHDOG_OUT 0x06 /* Reset Watchdog level */
|
||||
#define LED_WATCHDOG_CLOCK 0x07 /* clock to watchdog */
|
||||
|
||||
/*
|
||||
* LED's currently setup in AMD79C973 device as the following:
|
||||
* LED0 100Mbit
|
||||
* LED1 LNKSE
|
||||
* LED2 TX Activity
|
||||
* LED3 RX Activity
|
||||
*/
|
||||
#define LED_E0_LED0 0x08 /* Ethernet Port 0 LED 0 */
|
||||
#define LED_E0_LED1 0x09 /* Ethernet Port 0 LED 1 */
|
||||
#define LED_E0_LED2 0x0A /* Ethernet Port 0 LED 2 */
|
||||
#define LED_E0_LED3 0x0B /* Ethernet Port 0 LED 3 */
|
||||
#define LED_E1_LED0 0x0C /* Ethernet Port 1 LED 0 */
|
||||
#define LED_E1_LED1 0x0D /* Ethernet Port 1 LED 1 */
|
||||
#define LED_E1_LED2 0x0E /* Ethernet Port 1 LED 2 */
|
||||
#define LED_E1_LED3 0x0F /* Ethernet Port 1 LED 3 */
|
||||
#define LED_STROBE0 0x10 /* Processor Strobe 0 */
|
||||
#define LED_STROBE1 0x11 /* Processor Strobe 1 */
|
||||
#define LED_STROBE2 0x12 /* Processor Strobe 2 */
|
||||
#define LED_STROBE3 0x13 /* Processor Strobe 3 */
|
||||
#define LED_STROBE4 0x14 /* Processor Strobe 4 */
|
||||
#define LED_STROBE5 0x15 /* Processor Strobe 5 */
|
||||
#define LED_STROBE6 0x16 /* Processor Strobe 6 */
|
||||
#define LED_STROBE7 0x17 /* Processor Strobe 7 */
|
||||
#define LED_HOST_STROBE0 0x18 /* Host strobe 0 */
|
||||
#define LED_HOST_STROBE1 0x19 /* Host strobe 1 */
|
||||
#define LED_HOST_STROBE2 0x1A /* Host strobe 2 */
|
||||
#define LED_HOST_STROBE3 0x1B /* Host strobe 3 */
|
||||
#define LED_HOST_STROBE4 0x1C /* Host strobe 4 */
|
||||
#define LED_HOST_STROBE5 0x1D /* Host strobe 5 */
|
||||
#define LED_HOST_STROBE6 0x1E /* Host strobe 6 */
|
||||
#define LED_HOST_STROBE7 0x1F /* Host strobe 7 */
|
||||
#define LED_MPC_INT0 0x20 /* MPC8240 INT 0 */
|
||||
#define LED_MPC_INT1 0x21 /* MPC8240 INT 1 */
|
||||
#define LED_MPC_INT2 0x22 /* MPC8240 INT 2 */
|
||||
#define LED_MPC_INT3 0x23 /* MPC8240 INT 3 */
|
||||
#define LED_MPC_INT4 0x24 /* MPC8240 INT 4 */
|
||||
#define LED_UART0_CS 0x25 /* UART 0 Chip Select */
|
||||
#define LED_UART1_CS 0x26 /* UART 1 Chip Select */
|
||||
#define LED_SRAM_CS 0x27 /* SRAM Chip Select */
|
||||
#define LED_SRAM_WR 0x28 /* SRAM WR Signal */
|
||||
#define LED_SRAM_RD 0x29 /* SRAM RD Signal */
|
||||
#define LED_MPC_RCS0 0x2A /* MPC8240 RCS0 Signal */
|
||||
#define LED_S_PCI_FRAME 0x2B /* Secondary PCI Frame Signal */
|
||||
#define LED_MPC_CS0 0x2C /* MPC8240 CS0 Signal */
|
||||
#define LED_HOST_INT 0x2D /* MPC8240 to Host Interrupt signal */
|
||||
#define LED_LAST_FUNCTION LED_HOST_INT /* last function */
|
||||
|
||||
/*
|
||||
* Forward declarations
|
||||
*/
|
||||
int i2155x_init (void);
|
||||
void i2155x_write_scrapad(int idx, u32 val);
|
||||
u32 i2155x_read_scrapad (int idx);
|
||||
void i2155x_set_bar_base (int bar, u32 addr);
|
||||
int i2155x_read_vpd (int offset, int size, unsigned char *data);
|
||||
|
||||
int am79c95x_init (void);
|
||||
|
||||
void set_led (unsigned int number, unsigned int function);
|
||||
void fatal_error (unsigned int error_code);
|
||||
void show_startup_phase (int phase);
|
||||
|
||||
|
||||
#endif /* _PN62_H_ */
|
424
common/cmd_bedbug.c
Normal file
424
common/cmd_bedbug.c
Normal file
|
@ -0,0 +1,424 @@
|
|||
/*
|
||||
* BedBug Functions
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <net.h>
|
||||
|
||||
#include <cmd_bedbug.h>
|
||||
#include <bedbug/bedbug.h>
|
||||
#include <bedbug/regs.h>
|
||||
#include <bedbug/ppc.h>
|
||||
#include <elf.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
extern void show_regs __P((struct pt_regs*));
|
||||
extern int run_command __P((const char*, int));
|
||||
extern char console_buffer[];
|
||||
|
||||
ulong dis_last_addr = 0; /* Last address disassembled */
|
||||
ulong dis_last_len = 20; /* Default disassembler length */
|
||||
CPU_DEBUG_CTX bug_ctx; /* Bedbug context structure */
|
||||
|
||||
|
||||
/* ======================================================================
|
||||
* U-Boot's puts function does not append a newline, so the bedbug stuff
|
||||
* will use this for the output of the dis/assembler.
|
||||
* ====================================================================== */
|
||||
|
||||
int bedbug_puts(const char *str)
|
||||
{
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
printf( "%s\r\n", str );
|
||||
return 0;
|
||||
} /* bedbug_puts */
|
||||
|
||||
|
||||
|
||||
/* ======================================================================
|
||||
* Initialize the bug_ctx structure used by the bedbug debugger. This is
|
||||
* specific to the CPU since each has different debug registers and
|
||||
* settings.
|
||||
* ====================================================================== */
|
||||
|
||||
void bedbug_init( void )
|
||||
{
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
#if defined(CONFIG_4xx)
|
||||
void bedbug405_init( void );
|
||||
bedbug405_init();
|
||||
#elif defined(CONFIG_MPC860)
|
||||
void bedbug860_init( void );
|
||||
bedbug860_init();
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MPC824X) || defined(CONFIG_MPC8260)
|
||||
/* Processors that are 603e core based */
|
||||
void bedbug603e_init( void );
|
||||
|
||||
bedbug603e_init();
|
||||
#endif
|
||||
|
||||
return;
|
||||
} /* bedbug_init */
|
||||
|
||||
|
||||
|
||||
/* ======================================================================
|
||||
* Entry point from the interpreter to the disassembler. Repeated calls
|
||||
* will resume from the last disassembled address.
|
||||
* ====================================================================== */
|
||||
int do_bedbug_dis (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
ulong addr; /* Address to start disassembly from */
|
||||
ulong len; /* # of instructions to disassemble */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
/* Setup to go from the last address if none is given */
|
||||
addr = dis_last_addr;
|
||||
len = dis_last_len;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(( flag & CMD_FLAG_REPEAT ) == 0 )
|
||||
{
|
||||
/* New command */
|
||||
addr = simple_strtoul( argv[1], NULL, 16 );
|
||||
|
||||
/* If an extra param is given then it is the length */
|
||||
if( argc > 2 )
|
||||
len = simple_strtoul( argv[2], NULL, 16 );
|
||||
}
|
||||
|
||||
/* Run the disassembler */
|
||||
disppc( (unsigned char *)addr, 0, len, bedbug_puts, F_RADHEX );
|
||||
|
||||
dis_last_addr = addr + (len * 4);
|
||||
dis_last_len = len;
|
||||
return 0;
|
||||
} /* do_bedbug_dis */
|
||||
|
||||
|
||||
|
||||
/* ======================================================================
|
||||
* Entry point from the interpreter to the assembler. Assembles
|
||||
* instructions in consecutive memory locations until a '.' (period) is
|
||||
* entered on a line by itself.
|
||||
* ====================================================================== */
|
||||
int do_bedbug_asm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
long mem_addr; /* Address to assemble into */
|
||||
unsigned long instr; /* Machine code for text */
|
||||
char prompt[ 15 ]; /* Prompt string for user input */
|
||||
int asm_err; /* Error code from the assembler*/
|
||||
/* -------------------------------------------------- */
|
||||
int rcode = 0;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf( "\nEnter '.' when done\n" );
|
||||
mem_addr = simple_strtoul( argv[ 1 ], NULL, 16 );
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
putc( '\n' );
|
||||
disppc( (unsigned char *)mem_addr, 0, 1, bedbug_puts, F_RADHEX );
|
||||
|
||||
sprintf( prompt, "%08lx: ", mem_addr );
|
||||
readline( prompt );
|
||||
|
||||
if( console_buffer[ 0 ] && strcmp( console_buffer, "." ))
|
||||
{
|
||||
if(( instr = asmppc( mem_addr, console_buffer, &asm_err )) != 0 )
|
||||
{
|
||||
*(unsigned long *)mem_addr = instr;
|
||||
mem_addr += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf( "*** Error: %s ***\n", asm_error_str( asm_err ));
|
||||
rcode = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rcode;
|
||||
} /* do_bedbug_asm */
|
||||
|
||||
|
||||
|
||||
/* ======================================================================
|
||||
* Used to set a break point from the interpreter. Simply calls into the
|
||||
* CPU-specific break point set routine.
|
||||
* ====================================================================== */
|
||||
|
||||
int do_bedbug_break (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
/* -------------------------------------------------- */
|
||||
if( bug_ctx.do_break )
|
||||
(*bug_ctx.do_break)( cmdtp, flag, argc, argv );
|
||||
return 0;
|
||||
|
||||
} /* do_bedbug_break */
|
||||
|
||||
|
||||
|
||||
/* ======================================================================
|
||||
* Called from the debug interrupt routine. Simply calls the CPU-specific
|
||||
* breakpoint handling routine.
|
||||
* ====================================================================== */
|
||||
|
||||
void do_bedbug_breakpoint (struct pt_regs *regs)
|
||||
{
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
if( bug_ctx.break_isr )
|
||||
(*bug_ctx.break_isr)( regs );
|
||||
|
||||
return;
|
||||
} /* do_bedbug_breakpoint */
|
||||
|
||||
|
||||
|
||||
/* ======================================================================
|
||||
* Called from the CPU-specific breakpoint handling routine. Enter a
|
||||
* mini main loop until the stopped flag is cleared from the breakpoint
|
||||
* context.
|
||||
*
|
||||
* This handles the parts of the debugger that are common to all CPU's.
|
||||
* ====================================================================== */
|
||||
|
||||
void bedbug_main_loop( unsigned long addr, struct pt_regs *regs )
|
||||
{
|
||||
int len; /* Length of command line */
|
||||
int flag; /* Command flags */
|
||||
int rc = 0; /* Result from run_command*/
|
||||
char prompt_str[ 20 ]; /* Prompt string */
|
||||
static char lastcommand[ CFG_CBSIZE ] = {0}; /* previous command */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
if( bug_ctx.clear )
|
||||
(*bug_ctx.clear)( bug_ctx.current_bp );
|
||||
|
||||
printf( "Breakpoint %d: ", bug_ctx.current_bp );
|
||||
disppc( (unsigned char *)addr, 0, 1, bedbug_puts, F_RADHEX );
|
||||
|
||||
bug_ctx.stopped = 1;
|
||||
bug_ctx.regs = regs;
|
||||
|
||||
sprintf( prompt_str, "BEDBUG.%d =>", bug_ctx.current_bp );
|
||||
|
||||
/* A miniature main loop */
|
||||
while( bug_ctx.stopped )
|
||||
{
|
||||
len = readline( prompt_str );
|
||||
|
||||
flag = 0; /* assume no special flags for now */
|
||||
|
||||
if (len > 0)
|
||||
strcpy( lastcommand, console_buffer );
|
||||
else if( len == 0 )
|
||||
flag |= CMD_FLAG_REPEAT;
|
||||
|
||||
if (len == -1)
|
||||
printf ("<INTERRUPT>\n");
|
||||
else
|
||||
rc = run_command( lastcommand, flag );
|
||||
|
||||
if (rc <= 0) {
|
||||
/* invalid command or not repeatable, forget it */
|
||||
lastcommand[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bug_ctx.regs = NULL;
|
||||
bug_ctx.current_bp = 0;
|
||||
|
||||
return;
|
||||
} /* bedbug_main_loop */
|
||||
|
||||
|
||||
|
||||
/* ======================================================================
|
||||
* Interpreter command to continue from a breakpoint. Just clears the
|
||||
* stopped flag in the context so that the breakpoint routine will
|
||||
* return.
|
||||
* ====================================================================== */
|
||||
int do_bedbug_continue (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
|
||||
{
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
if( ! bug_ctx.stopped )
|
||||
{
|
||||
printf( "Not at a breakpoint\n" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
bug_ctx.stopped = 0;
|
||||
return 0;
|
||||
} /* do_bedbug_continue */
|
||||
|
||||
|
||||
|
||||
/* ======================================================================
|
||||
* Interpreter command to continue to the next instruction, stepping into
|
||||
* subroutines. Works by calling the find_next_addr() routine to compute
|
||||
* the address passes control to the CPU-specific set breakpoint routine
|
||||
* for the current breakpoint number.
|
||||
* ====================================================================== */
|
||||
int do_bedbug_step (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
unsigned long addr; /* Address to stop at */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
if( ! bug_ctx.stopped )
|
||||
{
|
||||
printf( "Not at a breakpoint\n" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( !find_next_address( (unsigned char *)&addr, FALSE, bug_ctx.regs ))
|
||||
return 1;
|
||||
|
||||
if( bug_ctx.set )
|
||||
(*bug_ctx.set)( bug_ctx.current_bp, addr );
|
||||
|
||||
bug_ctx.stopped = 0;
|
||||
return 0;
|
||||
} /* do_bedbug_step */
|
||||
|
||||
|
||||
|
||||
/* ======================================================================
|
||||
* Interpreter command to continue to the next instruction, stepping over
|
||||
* subroutines. Works by calling the find_next_addr() routine to compute
|
||||
* the address passes control to the CPU-specific set breakpoint routine
|
||||
* for the current breakpoint number.
|
||||
* ====================================================================== */
|
||||
int do_bedbug_next (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
unsigned long addr; /* Address to stop at */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
if( ! bug_ctx.stopped )
|
||||
{
|
||||
printf( "Not at a breakpoint\n" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( !find_next_address( (unsigned char *)&addr, TRUE, bug_ctx.regs ))
|
||||
return 1;
|
||||
|
||||
if( bug_ctx.set )
|
||||
(*bug_ctx.set)( bug_ctx.current_bp, addr );
|
||||
|
||||
bug_ctx.stopped = 0;
|
||||
return 0;
|
||||
} /* do_bedbug_next */
|
||||
|
||||
|
||||
|
||||
/* ======================================================================
|
||||
* Interpreter command to print the current stack. This assumes an EABI
|
||||
* architecture, so it starts with GPR R1 and works back up the stack.
|
||||
* ====================================================================== */
|
||||
int do_bedbug_stack (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
unsigned long sp; /* Stack pointer */
|
||||
unsigned long func; /* LR from stack */
|
||||
int depth; /* Stack iteration level */
|
||||
int skip = 1; /* Flag to skip the first entry */
|
||||
unsigned long top; /* Top of memory address */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
if( ! bug_ctx.stopped )
|
||||
{
|
||||
printf( "Not at a breakpoint\n" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
top = gd->bd->bi_memstart + gd->bd->bi_memsize;
|
||||
depth = 0;
|
||||
|
||||
printf( "Depth PC\n" );
|
||||
printf( "----- --------\n" );
|
||||
printf( "%5d %08lx\n", depth++, bug_ctx.regs->nip );
|
||||
|
||||
sp = bug_ctx.regs->gpr[ 1 ];
|
||||
func = *(unsigned long *)(sp+4);
|
||||
|
||||
while(( func < top ) && ( sp < top ))
|
||||
{
|
||||
if( !skip )
|
||||
printf( "%5d %08lx\n", depth++, func );
|
||||
else
|
||||
--skip;
|
||||
|
||||
sp = *(unsigned long *)sp;
|
||||
func = *(unsigned long *)(sp+4);
|
||||
}
|
||||
return 0;
|
||||
} /* do_bedbug_stack */
|
||||
|
||||
|
||||
|
||||
/* ======================================================================
|
||||
* Interpreter command to dump the registers. Calls the CPU-specific
|
||||
* show registers routine.
|
||||
* ====================================================================== */
|
||||
int do_bedbug_rdump (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
if( ! bug_ctx.stopped )
|
||||
{
|
||||
printf( "Not at a breakpoint\n" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
show_regs( bug_ctx.regs );
|
||||
return 0;
|
||||
} /* do_bedbug_rdump */
|
||||
|
||||
|
||||
/* ====================================================================== */
|
||||
#endif /* CFG_CMD_BEDBUG */
|
||||
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 William L. Pitts
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are freely
|
||||
* permitted provided that the above copyright notice and this
|
||||
* paragraph and the following disclaimer are duplicated in all
|
||||
* such forms.
|
||||
*
|
||||
* This software is provided "AS IS" and without any express or
|
||||
* implied warranties, including, without limitation, the implied
|
||||
* warranties of merchantability and fitness for a particular
|
||||
* purpose.
|
||||
*/
|
931
common/cmd_bootm.c
Normal file
931
common/cmd_bootm.c
Normal file
|
@ -0,0 +1,931 @@
|
|||
/*
|
||||
* (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
|
||||
*/
|
||||
|
||||
/*
|
||||
* Boot support
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <watchdog.h>
|
||||
#include <command.h>
|
||||
#include <cmd_boot.h>
|
||||
#include <image.h>
|
||||
#include <malloc.h>
|
||||
#include <zlib.h>
|
||||
#include <asm/byteorder.h>
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_DATE) || defined(CONFIG_TIMESTAMP)
|
||||
#include <rtc.h>
|
||||
#endif
|
||||
|
||||
#ifdef CFG_HUSH_PARSER
|
||||
#include <hush.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SHOW_BOOT_PROGRESS
|
||||
# include <status_led.h>
|
||||
# define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg)
|
||||
#else
|
||||
# define SHOW_BOOT_PROGRESS(arg)
|
||||
#endif
|
||||
|
||||
#ifdef CFG_INIT_RAM_LOCK
|
||||
#include <asm/cache.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Some systems (for example LWMON) have very short watchdog periods;
|
||||
* we must make sure to split long operations like memmove() or
|
||||
* crc32() into reasonable chunks.
|
||||
*/
|
||||
#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
|
||||
# define CHUNKSZ (64 * 1024)
|
||||
#endif
|
||||
|
||||
int gunzip (void *, int, unsigned char *, int *);
|
||||
|
||||
static void *zalloc(void *, unsigned, unsigned);
|
||||
static void zfree(void *, void *, unsigned);
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_IMI)
|
||||
static int image_info (unsigned long addr);
|
||||
#endif
|
||||
static void print_type (image_header_t *hdr);
|
||||
|
||||
/*
|
||||
* Continue booting an OS image; caller already has:
|
||||
* - copied image header to global variable `header'
|
||||
* - checked header magic number, checksums (both header & image),
|
||||
* - verified image architecture (PPC) and type (KERNEL or MULTI),
|
||||
* - loaded (first part of) image to header load address,
|
||||
* - disabled interrupts.
|
||||
*/
|
||||
typedef void boot_os_Fcn (cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char *argv[],
|
||||
ulong addr, /* of image to boot */
|
||||
ulong *len_ptr, /* multi-file image length table */
|
||||
int verify); /* getenv("verify")[0] != 'n' */
|
||||
|
||||
#ifndef CONFIG_ARM
|
||||
static boot_os_Fcn do_bootm_linux;
|
||||
#else
|
||||
extern boot_os_Fcn do_bootm_linux;
|
||||
#endif
|
||||
static boot_os_Fcn do_bootm_netbsd;
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_ELF)
|
||||
static boot_os_Fcn do_bootm_vxworks;
|
||||
static boot_os_Fcn do_bootm_qnxelf;
|
||||
int do_bootvx ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] );
|
||||
int do_bootelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] );
|
||||
#endif /* CFG_CMD_ELF */
|
||||
|
||||
image_header_t header;
|
||||
|
||||
ulong load_addr = CFG_LOAD_ADDR; /* Default Load Address */
|
||||
|
||||
int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
ulong iflag;
|
||||
ulong addr;
|
||||
ulong data, len, checksum;
|
||||
ulong *len_ptr;
|
||||
int i, verify;
|
||||
char *name, *s;
|
||||
int (*appl)(cmd_tbl_t *, int, int, char *[]);
|
||||
image_header_t *hdr = &header;
|
||||
|
||||
s = getenv ("verify");
|
||||
verify = (s && (*s == 'n')) ? 0 : 1;
|
||||
|
||||
if (argc < 2) {
|
||||
addr = load_addr;
|
||||
} else {
|
||||
addr = simple_strtoul(argv[1], NULL, 16);
|
||||
}
|
||||
|
||||
SHOW_BOOT_PROGRESS (1);
|
||||
printf ("## Booting image at %08lx ...\n", addr);
|
||||
|
||||
/* Copy header so we can blank CRC field for re-calculation */
|
||||
memmove (&header, (char *)addr, sizeof(image_header_t));
|
||||
|
||||
if (ntohl(hdr->ih_magic) != IH_MAGIC) {
|
||||
printf ("Bad Magic Number\n");
|
||||
SHOW_BOOT_PROGRESS (-1);
|
||||
return 1;
|
||||
}
|
||||
SHOW_BOOT_PROGRESS (2);
|
||||
|
||||
data = (ulong)&header;
|
||||
len = sizeof(image_header_t);
|
||||
|
||||
checksum = ntohl(hdr->ih_hcrc);
|
||||
hdr->ih_hcrc = 0;
|
||||
|
||||
if (crc32 (0, (char *)data, len) != checksum) {
|
||||
printf ("Bad Header Checksum\n");
|
||||
SHOW_BOOT_PROGRESS (-2);
|
||||
return 1;
|
||||
}
|
||||
SHOW_BOOT_PROGRESS (3);
|
||||
|
||||
/* for multi-file images we need the data part, too */
|
||||
print_image_hdr ((image_header_t *)addr);
|
||||
|
||||
data = addr + sizeof(image_header_t);
|
||||
len = ntohl(hdr->ih_size);
|
||||
|
||||
if (verify) {
|
||||
printf (" Verifying Checksum ... ");
|
||||
if (crc32 (0, (char *)data, len) != ntohl(hdr->ih_dcrc)) {
|
||||
printf ("Bad Data CRC\n");
|
||||
SHOW_BOOT_PROGRESS (-3);
|
||||
return 1;
|
||||
}
|
||||
printf ("OK\n");
|
||||
}
|
||||
SHOW_BOOT_PROGRESS (4);
|
||||
|
||||
len_ptr = (ulong *)data;
|
||||
|
||||
if (hdr->ih_arch != IH_CPU_PPC && hdr->ih_arch != IH_CPU_ARM) {
|
||||
printf ("Unsupported Architecture\n");
|
||||
SHOW_BOOT_PROGRESS (-4);
|
||||
return 1;
|
||||
}
|
||||
SHOW_BOOT_PROGRESS (5);
|
||||
|
||||
switch (hdr->ih_type) {
|
||||
case IH_TYPE_STANDALONE: name = "Standalone Application";
|
||||
break;
|
||||
case IH_TYPE_KERNEL: name = "Kernel Image";
|
||||
break;
|
||||
case IH_TYPE_MULTI: name = "Multi-File Image";
|
||||
len = ntohl(len_ptr[0]);
|
||||
/* OS kernel is always the first image */
|
||||
data += 8; /* kernel_len + terminator */
|
||||
for (i=1; len_ptr[i]; ++i)
|
||||
data += 4;
|
||||
break;
|
||||
default: printf ("Wrong Image Type for %s command\n", cmdtp->name);
|
||||
SHOW_BOOT_PROGRESS (-5);
|
||||
return 1;
|
||||
}
|
||||
SHOW_BOOT_PROGRESS (6);
|
||||
|
||||
/*
|
||||
* We have reached the point of no return: we are going to
|
||||
* overwrite all exception vector code, so we cannot easily
|
||||
* recover from any failures any more...
|
||||
*/
|
||||
|
||||
iflag = disable_interrupts();
|
||||
|
||||
switch (hdr->ih_comp) {
|
||||
case IH_COMP_NONE:
|
||||
if(hdr->ih_load == addr) {
|
||||
printf (" XIP %s ... ", name);
|
||||
} else {
|
||||
#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
|
||||
size_t l = len;
|
||||
void *to = (void *)ntohl(hdr->ih_load);
|
||||
void *from = (void *)data;
|
||||
|
||||
printf (" Loading %s ... ", name);
|
||||
|
||||
while (l > 0) {
|
||||
size_t tail = (l > CHUNKSZ) ? CHUNKSZ : l;
|
||||
WATCHDOG_RESET();
|
||||
memmove (to, from, tail);
|
||||
to += tail;
|
||||
from += tail;
|
||||
l -= tail;
|
||||
}
|
||||
#else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */
|
||||
memmove ((void *) ntohl(hdr->ih_load), (uchar *)data, len);
|
||||
#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
|
||||
}
|
||||
break;
|
||||
case IH_COMP_GZIP:
|
||||
printf (" Uncompressing %s ... ", name);
|
||||
if (gunzip ((void *)ntohl(hdr->ih_load), 0x400000,
|
||||
(uchar *)data, (int *)&len) != 0) {
|
||||
printf ("GUNZIP ERROR - must RESET board to recover\n");
|
||||
SHOW_BOOT_PROGRESS (-6);
|
||||
do_reset (cmdtp, flag, argc, argv);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (iflag)
|
||||
enable_interrupts();
|
||||
printf ("Unimplemented compression type %d\n", hdr->ih_comp);
|
||||
SHOW_BOOT_PROGRESS (-7);
|
||||
return 1;
|
||||
}
|
||||
printf ("OK\n");
|
||||
SHOW_BOOT_PROGRESS (7);
|
||||
|
||||
switch (hdr->ih_type) {
|
||||
case IH_TYPE_STANDALONE:
|
||||
appl = (int (*)(cmd_tbl_t *, int, int, char *[]))ntohl(hdr->ih_ep);
|
||||
if (iflag)
|
||||
enable_interrupts();
|
||||
|
||||
(*appl)(cmdtp, flag, argc-1, &argv[1]);
|
||||
break;
|
||||
case IH_TYPE_KERNEL:
|
||||
case IH_TYPE_MULTI:
|
||||
/* handled below */
|
||||
break;
|
||||
default:
|
||||
if (iflag)
|
||||
enable_interrupts();
|
||||
printf ("Can't boot image type %d\n", hdr->ih_type);
|
||||
SHOW_BOOT_PROGRESS (-8);
|
||||
return 1;
|
||||
}
|
||||
SHOW_BOOT_PROGRESS (8);
|
||||
|
||||
switch (hdr->ih_os) {
|
||||
default: /* handled by (original) Linux case */
|
||||
case IH_OS_LINUX:
|
||||
do_bootm_linux (cmdtp, flag, argc, argv,
|
||||
addr, len_ptr, verify);
|
||||
break;
|
||||
case IH_OS_NETBSD:
|
||||
do_bootm_netbsd (cmdtp, flag, argc, argv,
|
||||
addr, len_ptr, verify);
|
||||
break;
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_ELF)
|
||||
case IH_OS_VXWORKS:
|
||||
do_bootm_vxworks (cmdtp, flag, argc, argv,
|
||||
addr, len_ptr, verify);
|
||||
break;
|
||||
case IH_OS_QNX:
|
||||
do_bootm_qnxelf (cmdtp, flag, argc, argv,
|
||||
addr, len_ptr, verify);
|
||||
break;
|
||||
#endif /* CFG_CMD_ELF */
|
||||
}
|
||||
|
||||
SHOW_BOOT_PROGRESS (-9);
|
||||
#ifdef DEBUG
|
||||
printf ("\n## Control returned to monitor - resetting...\n");
|
||||
do_reset (cmdtp, flag, argc, argv);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_ARM
|
||||
static void
|
||||
do_bootm_linux (cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char *argv[],
|
||||
ulong addr,
|
||||
ulong *len_ptr,
|
||||
int verify)
|
||||
{
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
ulong sp;
|
||||
ulong len, checksum;
|
||||
ulong initrd_start, initrd_end;
|
||||
ulong cmd_start, cmd_end;
|
||||
ulong initrd_high;
|
||||
ulong data;
|
||||
char *cmdline;
|
||||
char *s;
|
||||
bd_t *kbd;
|
||||
void (*kernel)(bd_t *, ulong, ulong, ulong, ulong);
|
||||
image_header_t *hdr = &header;
|
||||
|
||||
if ((s = getenv ("initrd_high")) != NULL) {
|
||||
/* a value of "no" or a similar string will act like 0,
|
||||
* turning the "load high" feature off. This is intentional.
|
||||
*/
|
||||
initrd_high = simple_strtoul(s, NULL, 16);
|
||||
} else { /* not set, no restrictions to load high */
|
||||
initrd_high = ~0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Booting a (Linux) kernel image
|
||||
*
|
||||
* Allocate space for command line and board info - the
|
||||
* address should be as high as possible within the reach of
|
||||
* the kernel (see CFG_BOOTMAPSZ settings), but in unused
|
||||
* memory, which means far enough below the current stack
|
||||
* pointer.
|
||||
*/
|
||||
|
||||
asm( "mr %0,1": "=r"(sp) : );
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("## Current stack ends at 0x%08lX ", sp);
|
||||
#endif
|
||||
sp -= 2048; /* just to be sure */
|
||||
if (sp > CFG_BOOTMAPSZ)
|
||||
sp = CFG_BOOTMAPSZ;
|
||||
sp &= ~0xF;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("=> set upper limit to 0x%08lX\n", sp);
|
||||
#endif
|
||||
cmdline = (char *)((sp - CFG_BARGSIZE) & ~0xF);
|
||||
kbd = (bd_t *)(((ulong)cmdline - sizeof(bd_t)) & ~0xF);
|
||||
|
||||
if ((s = getenv("bootargs")) == NULL)
|
||||
s = "";
|
||||
|
||||
strcpy (cmdline, s);
|
||||
|
||||
cmd_start = (ulong)&cmdline[0];
|
||||
cmd_end = cmd_start + strlen(cmdline);
|
||||
|
||||
*kbd = *(gd->bd);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("## cmdline at 0x%08lX ... 0x%08lX\n", cmd_start, cmd_end);
|
||||
|
||||
do_bdinfo (NULL, 0, 0, NULL);
|
||||
#endif
|
||||
|
||||
if ((s = getenv ("clocks_in_mhz")) != NULL) {
|
||||
/* convert all clock information to MHz */
|
||||
kbd->bi_intfreq /= 1000000L;
|
||||
kbd->bi_busfreq /= 1000000L;
|
||||
#if defined(CONFIG_8260)
|
||||
kbd->bi_cpmfreq /= 1000000L;
|
||||
kbd->bi_brgfreq /= 1000000L;
|
||||
kbd->bi_sccfreq /= 1000000L;
|
||||
kbd->bi_vco /= 1000000L;
|
||||
#endif /* CONFIG_8260 */
|
||||
}
|
||||
|
||||
kernel = (void (*)(bd_t *, ulong, ulong, ulong, ulong))hdr->ih_ep;
|
||||
|
||||
/*
|
||||
* Check if there is an initrd image
|
||||
*/
|
||||
if (argc >= 3) {
|
||||
SHOW_BOOT_PROGRESS (9);
|
||||
|
||||
addr = simple_strtoul(argv[2], NULL, 16);
|
||||
|
||||
printf ("## Loading RAMDisk Image at %08lx ...\n", addr);
|
||||
|
||||
/* Copy header so we can blank CRC field for re-calculation */
|
||||
memmove (&header, (char *)addr, sizeof(image_header_t));
|
||||
|
||||
if (hdr->ih_magic != IH_MAGIC) {
|
||||
printf ("Bad Magic Number\n");
|
||||
SHOW_BOOT_PROGRESS (-10);
|
||||
do_reset (cmdtp, flag, argc, argv);
|
||||
}
|
||||
|
||||
data = (ulong)&header;
|
||||
len = sizeof(image_header_t);
|
||||
|
||||
checksum = hdr->ih_hcrc;
|
||||
hdr->ih_hcrc = 0;
|
||||
|
||||
if (crc32 (0, (char *)data, len) != checksum) {
|
||||
printf ("Bad Header Checksum\n");
|
||||
SHOW_BOOT_PROGRESS (-11);
|
||||
do_reset (cmdtp, flag, argc, argv);
|
||||
}
|
||||
|
||||
SHOW_BOOT_PROGRESS (10);
|
||||
|
||||
print_image_hdr (hdr);
|
||||
|
||||
data = addr + sizeof(image_header_t);
|
||||
len = hdr->ih_size;
|
||||
|
||||
if (verify) {
|
||||
ulong csum = 0;
|
||||
#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
|
||||
ulong cdata = data, edata = cdata + len;
|
||||
#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
|
||||
|
||||
printf (" Verifying Checksum ... ");
|
||||
|
||||
#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
|
||||
|
||||
while (cdata < edata) {
|
||||
ulong chunk = edata - cdata;
|
||||
|
||||
if (chunk > CHUNKSZ)
|
||||
chunk = CHUNKSZ;
|
||||
csum = crc32 (csum, (char *)cdata, chunk);
|
||||
cdata += chunk;
|
||||
|
||||
WATCHDOG_RESET();
|
||||
}
|
||||
#else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */
|
||||
csum = crc32 (0, (char *)data, len);
|
||||
#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
|
||||
|
||||
if (csum != hdr->ih_dcrc) {
|
||||
printf ("Bad Data CRC\n");
|
||||
SHOW_BOOT_PROGRESS (-12);
|
||||
do_reset (cmdtp, flag, argc, argv);
|
||||
}
|
||||
printf ("OK\n");
|
||||
}
|
||||
|
||||
SHOW_BOOT_PROGRESS (11);
|
||||
|
||||
if ((hdr->ih_os != IH_OS_LINUX) ||
|
||||
(hdr->ih_arch != IH_CPU_PPC) ||
|
||||
(hdr->ih_type != IH_TYPE_RAMDISK) ) {
|
||||
printf ("No Linux PPC Ramdisk Image\n");
|
||||
SHOW_BOOT_PROGRESS (-13);
|
||||
do_reset (cmdtp, flag, argc, argv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now check if we have a multifile image
|
||||
*/
|
||||
} else if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1])) {
|
||||
u_long tail = ntohl(len_ptr[0]) % 4;
|
||||
int i;
|
||||
|
||||
SHOW_BOOT_PROGRESS (13);
|
||||
|
||||
/* skip kernel length and terminator */
|
||||
data = (ulong)(&len_ptr[2]);
|
||||
/* skip any additional image length fields */
|
||||
for (i=1; len_ptr[i]; ++i)
|
||||
data += 4;
|
||||
/* add kernel length, and align */
|
||||
data += ntohl(len_ptr[0]);
|
||||
if (tail) {
|
||||
data += 4 - tail;
|
||||
}
|
||||
|
||||
len = ntohl(len_ptr[1]);
|
||||
|
||||
} else {
|
||||
/*
|
||||
* no initrd image
|
||||
*/
|
||||
SHOW_BOOT_PROGRESS (14);
|
||||
|
||||
len = data = 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!data) {
|
||||
printf ("No initrd\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (data) {
|
||||
initrd_start = (ulong)kbd - len;
|
||||
initrd_start &= ~(4096 - 1); /* align on page */
|
||||
|
||||
if (initrd_high) {
|
||||
ulong nsp;
|
||||
|
||||
/*
|
||||
* the inital ramdisk does not need to be within
|
||||
* CFG_BOOTMAPSZ as it is not accessed until after
|
||||
* the mm system is initialised.
|
||||
*
|
||||
* do the stack bottom calculation again and see if
|
||||
* the initrd will fit just below the monitor stack
|
||||
* bottom without overwriting the area allocated
|
||||
* above for command line args and board info.
|
||||
*/
|
||||
asm( "mr %0,1": "=r"(nsp) : );
|
||||
nsp -= 2048; /* just to be sure */
|
||||
nsp &= ~0xF;
|
||||
if (nsp > initrd_high) /* limit as specified */
|
||||
nsp = initrd_high;
|
||||
nsp -= len;
|
||||
nsp &= ~(4096 - 1); /* align on page */
|
||||
if (nsp >= sp)
|
||||
initrd_start = nsp;
|
||||
}
|
||||
|
||||
SHOW_BOOT_PROGRESS (12);
|
||||
#ifdef DEBUG
|
||||
printf ("## initrd at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n",
|
||||
data, data + len - 1, len, len);
|
||||
#endif
|
||||
initrd_end = initrd_start + len;
|
||||
printf (" Loading Ramdisk to %08lx, end %08lx ... ",
|
||||
initrd_start, initrd_end);
|
||||
#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
|
||||
{
|
||||
size_t l = len;
|
||||
void *to = (void *)initrd_start;
|
||||
void *from = (void *)data;
|
||||
|
||||
while (l > 0) {
|
||||
size_t tail = (l > CHUNKSZ) ? CHUNKSZ : l;
|
||||
WATCHDOG_RESET();
|
||||
memmove (to, from, tail);
|
||||
to += tail;
|
||||
from += tail;
|
||||
l -= tail;
|
||||
}
|
||||
}
|
||||
#else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */
|
||||
memmove ((void *)initrd_start, (void *)data, len);
|
||||
#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
|
||||
printf ("OK\n");
|
||||
} else {
|
||||
initrd_start = 0;
|
||||
initrd_end = 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("## Transferring control to Linux (at address %08lx) ...\n",
|
||||
(ulong)kernel);
|
||||
#endif
|
||||
SHOW_BOOT_PROGRESS (15);
|
||||
|
||||
#ifdef CFG_INIT_RAM_LOCK
|
||||
unlock_ram_in_cache();
|
||||
#endif
|
||||
/*
|
||||
* Linux Kernel Parameters:
|
||||
* r3: ptr to board info data
|
||||
* r4: initrd_start or 0 if no initrd
|
||||
* r5: initrd_end - unused if r4 is 0
|
||||
* r6: Start of command line string
|
||||
* r7: End of command line string
|
||||
*/
|
||||
(*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end);
|
||||
}
|
||||
#endif /* CONFIG_ARM */
|
||||
|
||||
static void
|
||||
do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char *argv[],
|
||||
ulong addr,
|
||||
ulong *len_ptr,
|
||||
int verify)
|
||||
{
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
image_header_t *hdr = &header;
|
||||
|
||||
void (*loader)(bd_t *, image_header_t *, char *, char *);
|
||||
image_header_t *img_addr;
|
||||
char *consdev;
|
||||
char *cmdline;
|
||||
|
||||
|
||||
/*
|
||||
* Booting a (NetBSD) kernel image
|
||||
*
|
||||
* This process is pretty similar to a standalone application:
|
||||
* The (first part of an multi-) image must be a stage-2 loader,
|
||||
* which in turn is responsible for loading & invoking the actual
|
||||
* kernel. The only differences are the parameters being passed:
|
||||
* besides the board info strucure, the loader expects a command
|
||||
* line, the name of the console device, and (optionally) the
|
||||
* address of the original image header.
|
||||
*/
|
||||
|
||||
img_addr = 0;
|
||||
if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1]))
|
||||
img_addr = (image_header_t *) addr;
|
||||
|
||||
|
||||
consdev = "";
|
||||
#if defined (CONFIG_8xx_CONS_SMC1)
|
||||
consdev = "smc1";
|
||||
#elif defined (CONFIG_8xx_CONS_SMC2)
|
||||
consdev = "smc2";
|
||||
#elif defined (CONFIG_8xx_CONS_SCC2)
|
||||
consdev = "scc2";
|
||||
#elif defined (CONFIG_8xx_CONS_SCC3)
|
||||
consdev = "scc3";
|
||||
#endif
|
||||
|
||||
if (argc > 2) {
|
||||
ulong len;
|
||||
int i;
|
||||
|
||||
for (i=2, len=0 ; i<argc ; i+=1)
|
||||
len += strlen (argv[i]) + 1;
|
||||
cmdline = malloc (len);
|
||||
|
||||
for (i=2, len=0 ; i<argc ; i+=1) {
|
||||
if (i > 2)
|
||||
cmdline[len++] = ' ';
|
||||
strcpy (&cmdline[len], argv[i]);
|
||||
len += strlen (argv[i]);
|
||||
}
|
||||
} else if ((cmdline = getenv("bootargs")) == NULL) {
|
||||
cmdline = "";
|
||||
}
|
||||
|
||||
loader = (void (*)(bd_t *, image_header_t *, char *, char *)) hdr->ih_ep;
|
||||
|
||||
printf ("## Transferring control to NetBSD stage-2 loader (at address %08lx) ...\n",
|
||||
(ulong)loader);
|
||||
|
||||
SHOW_BOOT_PROGRESS (15);
|
||||
|
||||
/*
|
||||
* NetBSD Stage-2 Loader Parameters:
|
||||
* r3: ptr to board info data
|
||||
* r4: image address
|
||||
* r5: console device
|
||||
* r6: boot args string
|
||||
*/
|
||||
(*loader) (gd->bd, img_addr, consdev, cmdline);
|
||||
}
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_BOOTD)
|
||||
int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
int rcode = 0;
|
||||
#ifndef CFG_HUSH_PARSER
|
||||
if (run_command (getenv ("bootcmd"), flag) < 0) rcode = 1;
|
||||
#else
|
||||
if (parse_string_outer(getenv("bootcmd"),
|
||||
FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) != 0 ) rcode = 1;
|
||||
#endif
|
||||
return rcode;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_IMI)
|
||||
int do_iminfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
int arg;
|
||||
ulong addr;
|
||||
int rcode=0;
|
||||
|
||||
if (argc < 2) {
|
||||
return image_info (load_addr);
|
||||
}
|
||||
|
||||
for (arg=1; arg <argc; ++arg) {
|
||||
addr = simple_strtoul(argv[arg], NULL, 16);
|
||||
if (image_info (addr) != 0) rcode = 1;
|
||||
}
|
||||
return rcode;
|
||||
}
|
||||
|
||||
static int image_info (ulong addr)
|
||||
{
|
||||
ulong data, len, checksum;
|
||||
image_header_t *hdr = &header;
|
||||
|
||||
printf ("\n## Checking Image at %08lx ...\n", addr);
|
||||
|
||||
/* Copy header so we can blank CRC field for re-calculation */
|
||||
memmove (&header, (char *)addr, sizeof(image_header_t));
|
||||
|
||||
if (ntohl(hdr->ih_magic) != IH_MAGIC) {
|
||||
printf (" Bad Magic Number\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
data = (ulong)&header;
|
||||
len = sizeof(image_header_t);
|
||||
|
||||
checksum = ntohl(hdr->ih_hcrc);
|
||||
hdr->ih_hcrc = 0;
|
||||
|
||||
if (crc32 (0, (char *)data, len) != checksum) {
|
||||
printf (" Bad Header Checksum\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* for multi-file images we need the data part, too */
|
||||
print_image_hdr ((image_header_t *)addr);
|
||||
|
||||
data = addr + sizeof(image_header_t);
|
||||
len = ntohl(hdr->ih_size);
|
||||
|
||||
printf (" Verifying Checksum ... ");
|
||||
if (crc32 (0, (char *)data, len) != ntohl(hdr->ih_dcrc)) {
|
||||
printf (" Bad Data CRC\n");
|
||||
return 1;
|
||||
}
|
||||
printf ("OK\n");
|
||||
return 0;
|
||||
}
|
||||
#endif /* CFG_CMD_IMI */
|
||||
|
||||
void
|
||||
print_image_hdr (image_header_t *hdr)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_DATE) || defined(CONFIG_TIMESTAMP)
|
||||
time_t timestamp = (time_t)ntohl(hdr->ih_time);
|
||||
struct rtc_time tm;
|
||||
#endif
|
||||
|
||||
printf (" Image Name: %.*s\n", IH_NMLEN, hdr->ih_name);
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_DATE) || defined(CONFIG_TIMESTAMP)
|
||||
to_tm (timestamp, &tm);
|
||||
printf (" Created: %4d-%02d-%02d %2d:%02d:%02d UTC\n",
|
||||
tm.tm_year, tm.tm_mon, tm.tm_mday,
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec);
|
||||
#endif /* CFG_CMD_DATE, CONFIG_TIMESTAMP */
|
||||
printf (" Image Type: "); print_type(hdr); printf ("\n");
|
||||
printf (" Data Size: %d Bytes = ", ntohl(hdr->ih_size));
|
||||
print_size (ntohl(hdr->ih_size), "\n");
|
||||
printf (" Load Address: %08x\n", ntohl(hdr->ih_load));
|
||||
printf (" Entry Point: %08x\n", ntohl(hdr->ih_ep));
|
||||
|
||||
if (hdr->ih_type == IH_TYPE_MULTI) {
|
||||
int i;
|
||||
ulong len;
|
||||
ulong *len_ptr = (ulong *)((ulong)hdr + sizeof(image_header_t));
|
||||
|
||||
printf (" Contents:\n");
|
||||
for (i=0; (len = ntohl(*len_ptr)); ++i, ++len_ptr) {
|
||||
printf (" Image %d: %8ld Bytes = ", i, len);
|
||||
print_size (len, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
print_type (image_header_t *hdr)
|
||||
{
|
||||
char *os, *arch, *type, *comp;
|
||||
|
||||
switch (hdr->ih_os) {
|
||||
case IH_OS_INVALID: os = "Invalid OS"; break;
|
||||
case IH_OS_NETBSD: os = "NetBSD"; break;
|
||||
case IH_OS_LINUX: os = "Linux"; break;
|
||||
case IH_OS_VXWORKS: os = "VxWorks"; break;
|
||||
case IH_OS_QNX: os = "QNX"; break;
|
||||
case IH_OS_U_BOOT: os = "U-Boot"; break;
|
||||
default: os = "Unknown OS"; break;
|
||||
}
|
||||
|
||||
switch (hdr->ih_arch) {
|
||||
case IH_CPU_INVALID: arch = "Invalid CPU"; break;
|
||||
case IH_CPU_ALPHA: arch = "Alpha"; break;
|
||||
case IH_CPU_ARM: arch = "ARM"; break;
|
||||
case IH_CPU_I386: arch = "Intel x86"; break;
|
||||
case IH_CPU_IA64: arch = "IA64"; break;
|
||||
case IH_CPU_MIPS: arch = "MIPS"; break;
|
||||
case IH_CPU_MIPS64: arch = "MIPS 64 Bit"; break;
|
||||
case IH_CPU_PPC: arch = "PowerPC"; break;
|
||||
case IH_CPU_S390: arch = "IBM S390"; break;
|
||||
case IH_CPU_SH: arch = "SuperH"; break;
|
||||
case IH_CPU_SPARC: arch = "SPARC"; break;
|
||||
case IH_CPU_SPARC64: arch = "SPARC 64 Bit"; break;
|
||||
default: arch = "Unknown Architecture"; break;
|
||||
}
|
||||
|
||||
switch (hdr->ih_type) {
|
||||
case IH_TYPE_INVALID: type = "Invalid Image"; break;
|
||||
case IH_TYPE_STANDALONE:type = "Standalone Program"; break;
|
||||
case IH_TYPE_KERNEL: type = "Kernel Image"; break;
|
||||
case IH_TYPE_RAMDISK: type = "RAMDisk Image"; break;
|
||||
case IH_TYPE_MULTI: type = "Multi-File Image"; break;
|
||||
case IH_TYPE_FIRMWARE: type = "Firmware"; break;
|
||||
case IH_TYPE_SCRIPT: type = "Script"; break;
|
||||
default: type = "Unknown Image"; break;
|
||||
}
|
||||
|
||||
switch (hdr->ih_comp) {
|
||||
case IH_COMP_NONE: comp = "uncompressed"; break;
|
||||
case IH_COMP_GZIP: comp = "gzip compressed"; break;
|
||||
case IH_COMP_BZIP2: comp = "bzip2 compressed"; break;
|
||||
default: comp = "unknown compression"; break;
|
||||
}
|
||||
|
||||
printf ("%s %s %s (%s)", arch, os, type, comp);
|
||||
}
|
||||
|
||||
#define ZALLOC_ALIGNMENT 16
|
||||
|
||||
static void *zalloc(void *x, unsigned items, unsigned size)
|
||||
{
|
||||
void *p;
|
||||
|
||||
size *= items;
|
||||
size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1);
|
||||
|
||||
p = malloc (size);
|
||||
|
||||
return (p);
|
||||
}
|
||||
|
||||
static void zfree(void *x, void *addr, unsigned nb)
|
||||
{
|
||||
free (addr);
|
||||
}
|
||||
|
||||
#define HEAD_CRC 2
|
||||
#define EXTRA_FIELD 4
|
||||
#define ORIG_NAME 8
|
||||
#define COMMENT 0x10
|
||||
#define RESERVED 0xe0
|
||||
|
||||
#define DEFLATED 8
|
||||
|
||||
int gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
|
||||
{
|
||||
z_stream s;
|
||||
int r, i, flags;
|
||||
|
||||
/* skip header */
|
||||
i = 10;
|
||||
flags = src[3];
|
||||
if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
|
||||
printf ("Error: Bad gzipped data\n");
|
||||
return (-1);
|
||||
}
|
||||
if ((flags & EXTRA_FIELD) != 0)
|
||||
i = 12 + src[10] + (src[11] << 8);
|
||||
if ((flags & ORIG_NAME) != 0)
|
||||
while (src[i++] != 0)
|
||||
;
|
||||
if ((flags & COMMENT) != 0)
|
||||
while (src[i++] != 0)
|
||||
;
|
||||
if ((flags & HEAD_CRC) != 0)
|
||||
i += 2;
|
||||
if (i >= *lenp) {
|
||||
printf ("Error: gunzip out of data in header\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
s.zalloc = zalloc;
|
||||
s.zfree = zfree;
|
||||
#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
|
||||
s.outcb = (cb_func)WATCHDOG_RESET;
|
||||
#else
|
||||
s.outcb = Z_NULL;
|
||||
#endif /* CONFIG_HW_WATCHDOG */
|
||||
|
||||
r = inflateInit2(&s, -MAX_WBITS);
|
||||
if (r != Z_OK) {
|
||||
printf ("Error: inflateInit2() returned %d\n", r);
|
||||
return (-1);
|
||||
}
|
||||
s.next_in = src + i;
|
||||
s.avail_in = *lenp - i;
|
||||
s.next_out = dst;
|
||||
s.avail_out = dstlen;
|
||||
r = inflate(&s, Z_FINISH);
|
||||
if (r != Z_OK && r != Z_STREAM_END) {
|
||||
printf ("Error: inflate() returned %d\n", r);
|
||||
return (-1);
|
||||
}
|
||||
*lenp = s.next_out - (unsigned char *) dst;
|
||||
inflateEnd(&s);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_ELF)
|
||||
static void
|
||||
do_bootm_vxworks (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
|
||||
ulong addr, ulong *len_ptr, int verify)
|
||||
{
|
||||
image_header_t *hdr = &header;
|
||||
char str[80];
|
||||
|
||||
sprintf(str, "%x", hdr->ih_ep); /* write entry-point into string */
|
||||
setenv("loadaddr", str);
|
||||
do_bootvx(cmdtp, 0, 0, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
do_bootm_qnxelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
|
||||
ulong addr, ulong *len_ptr, int verify)
|
||||
{
|
||||
image_header_t *hdr = &header;
|
||||
char *local_args[2];
|
||||
char str[16];
|
||||
|
||||
sprintf(str, "%x", hdr->ih_ep); /* write entry-point into string */
|
||||
local_args[0] = argv[0];
|
||||
local_args[1] = str; /* and provide it via the arguments */
|
||||
do_bootelf(cmdtp, 0, 2, local_args);
|
||||
}
|
||||
#endif /* CFG_CMD_ELF */
|
532
common/console.c
Normal file
532
common/console.c
Normal file
|
@ -0,0 +1,532 @@
|
|||
/*
|
||||
* (C) Copyright 2000
|
||||
* Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
|
||||
*
|
||||
* 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 <common.h>
|
||||
#include <stdarg.h>
|
||||
#include <malloc.h>
|
||||
#include <console.h>
|
||||
#include <syscall.h>
|
||||
|
||||
void **syscall_tbl;
|
||||
|
||||
#ifdef CFG_CONSOLE_IS_IN_ENV
|
||||
/*
|
||||
* if overwrite_console returns 1, the stdin, stderr and stdout
|
||||
* are switched to the serial port, else the settings in the
|
||||
* environment are used
|
||||
*/
|
||||
#ifdef CFG_CONSOLE_OVERWRITE_ROUTINE
|
||||
extern int overwrite_console (void);
|
||||
#else
|
||||
int overwrite_console (void)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
#endif /* CFG_CONSOLE_OVERWRITE_ROUTINE */
|
||||
|
||||
#endif /* CFG_CONSOLE_IS_IN_ENV */
|
||||
|
||||
static int console_setfile (int file, device_t * dev)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
if (dev == NULL)
|
||||
return -1;
|
||||
|
||||
switch (file) {
|
||||
case stdin:
|
||||
case stdout:
|
||||
case stderr:
|
||||
/* Start new device */
|
||||
if (dev->start) {
|
||||
error = dev->start ();
|
||||
/* If it's not started dont use it */
|
||||
if (error < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Assign the new device (leaving the existing one started) */
|
||||
stdio_devices[file] = dev;
|
||||
|
||||
/*
|
||||
* Update monitor functions
|
||||
* (to use the console stuff by other applications)
|
||||
*/
|
||||
switch (file) {
|
||||
case stdin:
|
||||
syscall_tbl[SYSCALL_GETC] = dev->getc;
|
||||
syscall_tbl[SYSCALL_TSTC] = dev->tstc;
|
||||
break;
|
||||
case stdout:
|
||||
syscall_tbl[SYSCALL_PUTC] = dev->putc;
|
||||
syscall_tbl[SYSCALL_PUTS] = dev->puts;
|
||||
syscall_tbl[SYSCALL_PRINTF] = printf;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default: /* Invalid file ID */
|
||||
error = -1;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
/** U-Boot INITIAL CONSOLE-NOT COMPATIBLE FUNCTIONS *************************/
|
||||
|
||||
void serial_printf (const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
uint i;
|
||||
char printbuffer[CFG_PBSIZE];
|
||||
|
||||
va_start (args, fmt);
|
||||
|
||||
/* For this to work, printbuffer must be larger than
|
||||
* anything we ever want to print.
|
||||
*/
|
||||
i = vsprintf (printbuffer, fmt, args);
|
||||
va_end (args);
|
||||
|
||||
serial_puts (printbuffer);
|
||||
}
|
||||
|
||||
int fgetc (int file)
|
||||
{
|
||||
if (file < MAX_FILES)
|
||||
return stdio_devices[file]->getc ();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ftstc (int file)
|
||||
{
|
||||
if (file < MAX_FILES)
|
||||
return stdio_devices[file]->tstc ();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void fputc (int file, const char c)
|
||||
{
|
||||
if (file < MAX_FILES)
|
||||
stdio_devices[file]->putc (c);
|
||||
}
|
||||
|
||||
void fputs (int file, const char *s)
|
||||
{
|
||||
if (file < MAX_FILES)
|
||||
stdio_devices[file]->puts (s);
|
||||
}
|
||||
|
||||
void fprintf (int file, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
uint i;
|
||||
char printbuffer[CFG_PBSIZE];
|
||||
|
||||
va_start (args, fmt);
|
||||
|
||||
/* For this to work, printbuffer must be larger than
|
||||
* anything we ever want to print.
|
||||
*/
|
||||
i = vsprintf (printbuffer, fmt, args);
|
||||
va_end (args);
|
||||
|
||||
/* Send to desired file */
|
||||
fputs (file, printbuffer);
|
||||
}
|
||||
|
||||
/** U-Boot INITIAL CONSOLE-COMPATIBLE FUNCTION *****************************/
|
||||
|
||||
int getc (void)
|
||||
{
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
if (gd->flags & GD_FLG_DEVINIT) {
|
||||
/* Get from the standard input */
|
||||
return fgetc (stdin);
|
||||
}
|
||||
|
||||
/* Send directly to the handler */
|
||||
return serial_getc ();
|
||||
}
|
||||
|
||||
int tstc (void)
|
||||
{
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
if (gd->flags & GD_FLG_DEVINIT) {
|
||||
/* Test the standard input */
|
||||
return ftstc (stdin);
|
||||
}
|
||||
|
||||
/* Send directly to the handler */
|
||||
return serial_tstc ();
|
||||
}
|
||||
|
||||
void putc (const char c)
|
||||
{
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
if (gd->flags & GD_FLG_DEVINIT) {
|
||||
/* Send to the standard output */
|
||||
fputc (stdout, c);
|
||||
} else {
|
||||
/* Send directly to the handler */
|
||||
serial_putc (c);
|
||||
}
|
||||
}
|
||||
|
||||
void puts (const char *s)
|
||||
{
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
if (gd->flags & GD_FLG_DEVINIT) {
|
||||
/* Send to the standard output */
|
||||
fputs (stdout, s);
|
||||
} else {
|
||||
/* Send directly to the handler */
|
||||
serial_puts (s);
|
||||
}
|
||||
}
|
||||
|
||||
void printf (const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
uint i;
|
||||
char printbuffer[CFG_PBSIZE];
|
||||
|
||||
va_start (args, fmt);
|
||||
|
||||
/* For this to work, printbuffer must be larger than
|
||||
* anything we ever want to print.
|
||||
*/
|
||||
i = vsprintf (printbuffer, fmt, args);
|
||||
va_end (args);
|
||||
|
||||
/* Print the string */
|
||||
puts (printbuffer);
|
||||
}
|
||||
|
||||
/* test if ctrl-c was pressed */
|
||||
static int ctrlc_disabled = 0; /* see disable_ctrl() */
|
||||
static int ctrlc_was_pressed = 0;
|
||||
int ctrlc (void)
|
||||
{
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
if (!ctrlc_disabled && gd->have_console) {
|
||||
if (tstc ()) {
|
||||
switch (getc ()) {
|
||||
case 0x03: /* ^C - Control C */
|
||||
ctrlc_was_pressed = 1;
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* pass 1 to disable ctrlc() checking, 0 to enable.
|
||||
* returns previous state
|
||||
*/
|
||||
int disable_ctrlc (int disable)
|
||||
{
|
||||
int prev = ctrlc_disabled; /* save previous state */
|
||||
|
||||
ctrlc_disabled = disable;
|
||||
return prev;
|
||||
}
|
||||
|
||||
int had_ctrlc (void)
|
||||
{
|
||||
return ctrlc_was_pressed;
|
||||
}
|
||||
|
||||
void clear_ctrlc (void)
|
||||
{
|
||||
ctrlc_was_pressed = 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MODEM_SUPPORT_DEBUG
|
||||
char screen[1024];
|
||||
char *cursor = screen;
|
||||
int once = 0;
|
||||
inline void dbg(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
uint i;
|
||||
char printbuffer[CFG_PBSIZE];
|
||||
|
||||
if (!once) {
|
||||
memset(screen, 0, sizeof(screen));
|
||||
once++;
|
||||
}
|
||||
|
||||
va_start(args, fmt);
|
||||
|
||||
/* For this to work, printbuffer must be larger than
|
||||
* anything we ever want to print.
|
||||
*/
|
||||
i = vsprintf(printbuffer, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if ((screen + sizeof(screen) - 1 - cursor) < strlen(printbuffer)+1) {
|
||||
memset(screen, 0, sizeof(screen));
|
||||
cursor = screen;
|
||||
}
|
||||
sprintf(cursor, printbuffer);
|
||||
cursor += strlen(printbuffer);
|
||||
|
||||
}
|
||||
#else
|
||||
inline void dbg(const char *fmt, ...)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/** U-Boot INIT FUNCTIONS *************************************************/
|
||||
|
||||
int console_assign (int file, char *devname)
|
||||
{
|
||||
int flag, i;
|
||||
|
||||
/* Check for valid file */
|
||||
switch (file) {
|
||||
case stdin:
|
||||
flag = DEV_FLAGS_INPUT;
|
||||
break;
|
||||
case stdout:
|
||||
case stderr:
|
||||
flag = DEV_FLAGS_OUTPUT;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check for valid device name */
|
||||
|
||||
for (i = 1; i <= ListNumItems (devlist); i++) {
|
||||
device_t *dev = ListGetPtrToItem (devlist, i);
|
||||
|
||||
if (strcmp (devname, dev->name) == 0) {
|
||||
if (dev->flags & flag)
|
||||
return console_setfile (file, dev);
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Called before relocation - use serial functions */
|
||||
int console_init_f (void)
|
||||
{
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
gd->have_console = 1;
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifdef CFG_CONSOLE_IS_IN_ENV
|
||||
/* search a device */
|
||||
device_t *search_device (int flags, char *name)
|
||||
{
|
||||
int i, items;
|
||||
device_t *dev = NULL;
|
||||
|
||||
items = ListNumItems (devlist);
|
||||
if (name == NULL)
|
||||
return dev;
|
||||
|
||||
for (i = 1; i <= items; i++) {
|
||||
dev = ListGetPtrToItem (devlist, i);
|
||||
if ((dev->flags & flags) && (strcmp (name, dev->name) == 0)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return dev;
|
||||
}
|
||||
#endif /* CFG_CONSOLE_IS_IN_ENV */
|
||||
|
||||
#ifdef CFG_CONSOLE_IS_IN_ENV
|
||||
/* Called after the relocation - use desired console functions */
|
||||
int console_init_r (void)
|
||||
{
|
||||
char *stdinname, *stdoutname, *stderrname;
|
||||
device_t *inputdev = NULL, *outputdev = NULL, *errdev = NULL;
|
||||
|
||||
/* set default handlers at first */
|
||||
syscall_tbl[SYSCALL_GETC] = serial_getc;
|
||||
syscall_tbl[SYSCALL_TSTC] = serial_tstc;
|
||||
syscall_tbl[SYSCALL_PUTC] = serial_putc;
|
||||
syscall_tbl[SYSCALL_PUTS] = serial_puts;
|
||||
syscall_tbl[SYSCALL_PRINTF] = serial_printf;
|
||||
|
||||
/* stdin stdout and stderr are in environment */
|
||||
/* scan for it */
|
||||
stdinname = getenv ("stdin");
|
||||
stdoutname = getenv ("stdout");
|
||||
stderrname = getenv ("stderr");
|
||||
|
||||
if (overwrite_console () == 0) { /* if not overwritten by config switch */
|
||||
inputdev = search_device (DEV_FLAGS_INPUT, stdinname);
|
||||
outputdev = search_device (DEV_FLAGS_OUTPUT, stdoutname);
|
||||
errdev = search_device (DEV_FLAGS_OUTPUT, stderrname);
|
||||
}
|
||||
/* if the devices are overwritten or not found, use default device */
|
||||
if (inputdev == NULL) {
|
||||
inputdev = search_device (DEV_FLAGS_INPUT, "serial");
|
||||
}
|
||||
if (outputdev == NULL) {
|
||||
outputdev = search_device (DEV_FLAGS_OUTPUT, "serial");
|
||||
}
|
||||
if (errdev == NULL) {
|
||||
errdev = search_device (DEV_FLAGS_OUTPUT, "serial");
|
||||
}
|
||||
/* Initializes output console first */
|
||||
if (outputdev != NULL) {
|
||||
console_setfile (stdout, outputdev);
|
||||
}
|
||||
if (errdev != NULL) {
|
||||
console_setfile (stderr, errdev);
|
||||
}
|
||||
if (inputdev != NULL) {
|
||||
console_setfile (stdin, inputdev);
|
||||
}
|
||||
|
||||
#ifndef CFG_CONSOLE_INFO_QUIET
|
||||
/* Print information */
|
||||
printf ("In: ");
|
||||
if (stdio_devices[stdin] == NULL) {
|
||||
printf ("No input devices available!\n");
|
||||
} else {
|
||||
printf ("%s\n", stdio_devices[stdin]->name);
|
||||
}
|
||||
|
||||
printf ("Out: ");
|
||||
if (stdio_devices[stdout] == NULL) {
|
||||
printf ("No output devices available!\n");
|
||||
} else {
|
||||
printf ("%s\n", stdio_devices[stdout]->name);
|
||||
}
|
||||
|
||||
printf ("Err: ");
|
||||
if (stdio_devices[stderr] == NULL) {
|
||||
printf ("No error devices available!\n");
|
||||
} else {
|
||||
printf ("%s\n", stdio_devices[stderr]->name);
|
||||
}
|
||||
#endif /* CFG_CONSOLE_INFO_QUIET */
|
||||
|
||||
#ifdef CFG_CONSOLE_ENV_OVERWRITE
|
||||
/* set the environment variables (will overwrite previous env settings) */
|
||||
for (i = 0; i < 3; i++) {
|
||||
setenv (stdio_names[i], stdio_devices[i]->name);
|
||||
}
|
||||
#endif /* CFG_CONSOLE_ENV_OVERWRITE */
|
||||
|
||||
#if 0
|
||||
/* If nothing usable installed, use only the initial console */
|
||||
if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
|
||||
return (0);
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
#else /* CFG_CONSOLE_IS_IN_ENV */
|
||||
|
||||
/* Called after the relocation - use desired console functions */
|
||||
int console_init_r (void)
|
||||
{
|
||||
device_t *inputdev = NULL, *outputdev = NULL;
|
||||
int i, items = ListNumItems (devlist);
|
||||
|
||||
/* Scan devices looking for input and output devices */
|
||||
for (i = 1;
|
||||
(i <= items) && ((inputdev == NULL) || (outputdev == NULL));
|
||||
i++
|
||||
) {
|
||||
device_t *dev = ListGetPtrToItem (devlist, i);
|
||||
|
||||
if ((dev->flags & DEV_FLAGS_INPUT) && (inputdev == NULL)) {
|
||||
inputdev = dev;
|
||||
}
|
||||
if ((dev->flags & DEV_FLAGS_OUTPUT) && (outputdev == NULL)) {
|
||||
outputdev = dev;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initializes output console first */
|
||||
if (outputdev != NULL) {
|
||||
console_setfile (stdout, outputdev);
|
||||
console_setfile (stderr, outputdev);
|
||||
}
|
||||
|
||||
/* Initializes input console */
|
||||
if (inputdev != NULL) {
|
||||
console_setfile (stdin, inputdev);
|
||||
}
|
||||
|
||||
#ifndef CFG_CONSOLE_INFO_QUIET
|
||||
/* Print informations */
|
||||
printf ("In: ");
|
||||
if (stdio_devices[stdin] == NULL) {
|
||||
printf ("No input devices available!\n");
|
||||
} else {
|
||||
printf ("%s\n", stdio_devices[stdin]->name);
|
||||
}
|
||||
|
||||
printf ("Out: ");
|
||||
if (stdio_devices[stdout] == NULL) {
|
||||
printf ("No output devices available!\n");
|
||||
} else {
|
||||
printf ("%s\n", stdio_devices[stdout]->name);
|
||||
}
|
||||
|
||||
printf ("Err: ");
|
||||
if (stdio_devices[stderr] == NULL) {
|
||||
printf ("No error devices available!\n");
|
||||
} else {
|
||||
printf ("%s\n", stdio_devices[stderr]->name);
|
||||
}
|
||||
#endif /* CFG_CONSOLE_INFO_QUIET */
|
||||
|
||||
/* Setting environment variables */
|
||||
for (i = 0; i < 3; i++) {
|
||||
setenv (stdio_names[i], stdio_devices[i]->name);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* If nothing usable installed, use only the initial console */
|
||||
if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
|
||||
return (0);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#endif /* CFG_CONSOLE_IS_IN_ENV */
|
860
cpu/74xx_7xx/start.S
Normal file
860
cpu/74xx_7xx/start.S
Normal file
|
@ -0,0 +1,860 @@
|
|||
/*
|
||||
* Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
|
||||
* Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
|
||||
* Copyright (C) 2000,2001,2002 Wolfgang Denk <wd@denx.de>
|
||||
* Copyright (C) 2001 Josh Huber <huber@mclx.com>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* U-Boot - Startup Code for PowerPC based Embedded Boards
|
||||
*
|
||||
*
|
||||
* The processor starts at 0xfff00100 and the code is executed
|
||||
* from flash. The code is organized to be at an other address
|
||||
* in memory, but as long we don't jump around before relocating.
|
||||
* board_init lies at a quite high address and when the cpu has
|
||||
* jumped there, everything is ok.
|
||||
*/
|
||||
#include <config.h>
|
||||
#include <74xx_7xx.h>
|
||||
#include <version.h>
|
||||
|
||||
#include <ppc_asm.tmpl>
|
||||
#include <ppc_defs.h>
|
||||
|
||||
#include <asm/cache.h>
|
||||
#include <asm/mmu.h>
|
||||
|
||||
#include <galileo/gt64260R.h>
|
||||
|
||||
#ifndef CONFIG_IDENT_STRING
|
||||
#define CONFIG_IDENT_STRING ""
|
||||
#endif
|
||||
|
||||
/* We don't want the MMU yet.
|
||||
*/
|
||||
#undef MSR_KERNEL
|
||||
/* Machine Check and Recoverable Interr. */
|
||||
#define MSR_KERNEL ( MSR_ME | MSR_RI )
|
||||
|
||||
/*
|
||||
* Set up GOT: Global Offset Table
|
||||
*
|
||||
* Use r14 to access the GOT
|
||||
*/
|
||||
START_GOT
|
||||
GOT_ENTRY(_GOT2_TABLE_)
|
||||
GOT_ENTRY(_FIXUP_TABLE_)
|
||||
|
||||
GOT_ENTRY(_start)
|
||||
GOT_ENTRY(_start_of_vectors)
|
||||
GOT_ENTRY(_end_of_vectors)
|
||||
GOT_ENTRY(transfer_to_handler)
|
||||
|
||||
GOT_ENTRY(_end)
|
||||
GOT_ENTRY(.bss)
|
||||
END_GOT
|
||||
|
||||
/*
|
||||
* r3 - 1st arg to board_init(): IMMP pointer
|
||||
* r4 - 2nd arg to board_init(): boot flag
|
||||
*/
|
||||
.text
|
||||
.long 0x27051956 /* U-Boot Magic Number */
|
||||
.globl version_string
|
||||
version_string:
|
||||
.ascii U_BOOT_VERSION
|
||||
.ascii " (", __DATE__, " - ", __TIME__, ")"
|
||||
.ascii CONFIG_IDENT_STRING, "\0"
|
||||
|
||||
. = EXC_OFF_SYS_RESET
|
||||
.globl _start
|
||||
_start:
|
||||
li r21, BOOTFLAG_COLD /* Normal Power-On: Boot from FLASH */
|
||||
b boot_cold
|
||||
sync
|
||||
|
||||
. = EXC_OFF_SYS_RESET + 0x10
|
||||
|
||||
.globl _start_warm
|
||||
_start_warm:
|
||||
li r21, BOOTFLAG_WARM /* Software reboot */
|
||||
b boot_warm
|
||||
sync
|
||||
|
||||
/* the boot code is located below the exception table */
|
||||
|
||||
.globl _start_of_vectors
|
||||
_start_of_vectors:
|
||||
|
||||
/* Machine check */
|
||||
STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
|
||||
|
||||
/* Data Storage exception. "Never" generated on the 860. */
|
||||
STD_EXCEPTION(0x300, DataStorage, UnknownException)
|
||||
|
||||
/* Instruction Storage exception. "Never" generated on the 860. */
|
||||
STD_EXCEPTION(0x400, InstStorage, UnknownException)
|
||||
|
||||
/* External Interrupt exception. */
|
||||
STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
|
||||
|
||||
/* Alignment exception. */
|
||||
. = 0x600
|
||||
Alignment:
|
||||
EXCEPTION_PROLOG
|
||||
mfspr r4,DAR
|
||||
stw r4,_DAR(r21)
|
||||
mfspr r5,DSISR
|
||||
stw r5,_DSISR(r21)
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
li r20,MSR_KERNEL
|
||||
rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
|
||||
lwz r6,GOT(transfer_to_handler)
|
||||
mtlr r6
|
||||
blrl
|
||||
.L_Alignment:
|
||||
.long AlignmentException - _start + EXC_OFF_SYS_RESET
|
||||
.long int_return - _start + EXC_OFF_SYS_RESET
|
||||
|
||||
/* Program check exception */
|
||||
. = 0x700
|
||||
ProgramCheck:
|
||||
EXCEPTION_PROLOG
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
li r20,MSR_KERNEL
|
||||
rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
|
||||
lwz r6,GOT(transfer_to_handler)
|
||||
mtlr r6
|
||||
blrl
|
||||
.L_ProgramCheck:
|
||||
.long ProgramCheckException - _start + EXC_OFF_SYS_RESET
|
||||
.long int_return - _start + EXC_OFF_SYS_RESET
|
||||
|
||||
/* No FPU on MPC8xx. This exception is not supposed to happen.
|
||||
*/
|
||||
STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
|
||||
|
||||
/* I guess we could implement decrementer, and may have
|
||||
* to someday for timekeeping.
|
||||
*/
|
||||
STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
|
||||
STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
|
||||
STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
|
||||
|
||||
. = 0xc00
|
||||
/*
|
||||
* r0 - SYSCALL number
|
||||
* r3-... arguments
|
||||
*/
|
||||
SystemCall:
|
||||
addis r11,r0,0 /* get functions table addr */
|
||||
ori r11,r11,0 /* Note: this code is patched in trap_init */
|
||||
addis r12,r0,0 /* get number of functions */
|
||||
ori r12,r12,0
|
||||
|
||||
cmplw 0, r0, r12
|
||||
bge 1f
|
||||
|
||||
rlwinm r0,r0,2,0,31 /* fn_addr = fn_tbl[r0] */
|
||||
add r11,r11,r0
|
||||
lwz r11,0(r11)
|
||||
|
||||
li r12,0xd00-4*3 /* save LR & SRRx */
|
||||
mflr r0
|
||||
stw r0,0(r12)
|
||||
mfspr r0,SRR0
|
||||
stw r0,4(r12)
|
||||
mfspr r0,SRR1
|
||||
stw r0,8(r12)
|
||||
|
||||
li r12,0xc00+_back-SystemCall
|
||||
mtlr r12
|
||||
mtspr SRR0,r11
|
||||
|
||||
1: SYNC
|
||||
rfi
|
||||
|
||||
_back:
|
||||
|
||||
mfmsr r11 /* Disable interrupts */
|
||||
li r12,0
|
||||
ori r12,r12,MSR_EE
|
||||
andc r11,r11,r12
|
||||
SYNC /* Some chip revs need this... */
|
||||
mtmsr r11
|
||||
SYNC
|
||||
|
||||
li r12,0xd00-4*3 /* restore regs */
|
||||
lwz r11,0(r12)
|
||||
mtlr r11
|
||||
lwz r11,4(r12)
|
||||
mtspr SRR0,r11
|
||||
lwz r11,8(r12)
|
||||
mtspr SRR1,r11
|
||||
|
||||
SYNC
|
||||
rfi
|
||||
|
||||
STD_EXCEPTION(0xd00, SingleStep, UnknownException)
|
||||
|
||||
STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
|
||||
STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
|
||||
|
||||
/*
|
||||
* On the MPC8xx, this is a software emulation interrupt. It
|
||||
* occurs for all unimplemented and illegal instructions.
|
||||
*/
|
||||
STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
|
||||
|
||||
STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
|
||||
STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
|
||||
STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
|
||||
STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
|
||||
|
||||
STD_EXCEPTION(0x1500, Reserved5, UnknownException)
|
||||
STD_EXCEPTION(0x1600, Reserved6, UnknownException)
|
||||
STD_EXCEPTION(0x1700, Reserved7, UnknownException)
|
||||
STD_EXCEPTION(0x1800, Reserved8, UnknownException)
|
||||
STD_EXCEPTION(0x1900, Reserved9, UnknownException)
|
||||
STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
|
||||
STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
|
||||
|
||||
STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
|
||||
STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
|
||||
STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
|
||||
STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
|
||||
|
||||
.globl _end_of_vectors
|
||||
_end_of_vectors:
|
||||
|
||||
. = 0x2000
|
||||
|
||||
boot_cold:
|
||||
boot_warm:
|
||||
/* disable everything */
|
||||
li r0, 0
|
||||
mtspr HID0, r0
|
||||
sync
|
||||
mtmsr 0
|
||||
bl invalidate_bats
|
||||
sync
|
||||
|
||||
#ifdef CFG_L2
|
||||
/* init the L2 cache */
|
||||
addis r3, r0, L2_INIT@h
|
||||
ori r3, r3, L2_INIT@l
|
||||
sync
|
||||
mtspr l2cr, r3
|
||||
#endif
|
||||
#if defined(CONFIG_ALTIVEC) && defined(CONFIG_74xx)
|
||||
.long 0x7e00066c
|
||||
/*
|
||||
* dssall instruction, gas doesn't have it yet
|
||||
* ...for altivec, data stream stop all this probably
|
||||
* isn't needed unless we warm (software) reboot U-Boot
|
||||
*/
|
||||
#endif
|
||||
|
||||
#ifdef CFG_L2
|
||||
/* invalidate the L2 cache */
|
||||
bl l2cache_invalidate
|
||||
sync
|
||||
#endif
|
||||
#ifdef CFG_BOARD_ASM_INIT
|
||||
/* do early init */
|
||||
bl board_asm_init
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Calculate absolute address in FLASH and jump there
|
||||
*------------------------------------------------------*/
|
||||
lis r3, CFG_MONITOR_BASE@h
|
||||
ori r3, r3, CFG_MONITOR_BASE@l
|
||||
addi r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
|
||||
mtlr r3
|
||||
blr
|
||||
|
||||
in_flash:
|
||||
/* let the C-code set up the rest */
|
||||
/* */
|
||||
/* Be careful to keep code relocatable ! */
|
||||
/*------------------------------------------------------*/
|
||||
|
||||
/* perform low-level init */
|
||||
/* sdram init, galileo init, etc */
|
||||
/* r3: NHR bit from HID0 */
|
||||
|
||||
/* setup the bats */
|
||||
bl setup_bats
|
||||
sync
|
||||
|
||||
/*
|
||||
* Cache must be enabled here for stack-in-cache trick.
|
||||
* This means we need to enable the BATS.
|
||||
* This means:
|
||||
* 1) for the EVB, original gt regs need to be mapped
|
||||
* 2) need to have an IBAT for the 0xf region,
|
||||
* we are running there!
|
||||
* Cache should be turned on after BATs, since by default
|
||||
* everything is write-through.
|
||||
* The init-mem BAT can be reused after reloc. The old
|
||||
* gt-regs BAT can be reused after board_init_f calls
|
||||
* board_pre_init (EVB only).
|
||||
*/
|
||||
#if !defined(CONFIG_BAB7xx) && !defined(CONFIG_ELPPC)
|
||||
/* enable address translation */
|
||||
bl enable_addr_trans
|
||||
sync
|
||||
|
||||
/* enable and invalidate the data cache */
|
||||
bl l1dcache_enable
|
||||
sync
|
||||
#endif
|
||||
#ifdef CFG_INIT_RAM_LOCK
|
||||
bl lock_ram_in_cache
|
||||
sync
|
||||
#endif
|
||||
|
||||
/* set up the stack pointer in our newly created
|
||||
* cache-ram (r1) */
|
||||
lis r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@h
|
||||
ori r1, r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@l
|
||||
|
||||
li r0, 0 /* Make room for stack frame header and */
|
||||
stwu r0, -4(r1) /* clear final stack frame so that */
|
||||
stwu r0, -4(r1) /* stack backtraces terminate cleanly */
|
||||
|
||||
GET_GOT /* initialize GOT access */
|
||||
|
||||
/* run low-level CPU init code (from Flash) */
|
||||
bl cpu_init_f
|
||||
sync
|
||||
|
||||
mr r3, r21
|
||||
|
||||
/* r3: BOOTFLAG */
|
||||
/* run 1st part of board init code (from Flash) */
|
||||
bl board_init_f
|
||||
sync
|
||||
|
||||
/* NOTREACHED */
|
||||
|
||||
.globl invalidate_bats
|
||||
invalidate_bats:
|
||||
/* invalidate BATs */
|
||||
mtspr IBAT0U, r0
|
||||
mtspr IBAT1U, r0
|
||||
mtspr IBAT2U, r0
|
||||
mtspr IBAT3U, r0
|
||||
isync
|
||||
mtspr DBAT0U, r0
|
||||
mtspr DBAT1U, r0
|
||||
mtspr DBAT2U, r0
|
||||
mtspr DBAT3U, r0
|
||||
isync
|
||||
sync
|
||||
blr
|
||||
|
||||
/* setup_bats - set them up to some initial state */
|
||||
.globl setup_bats
|
||||
setup_bats:
|
||||
addis r0, r0, 0x0000
|
||||
|
||||
/* IBAT 0 */
|
||||
addis r4, r0, CFG_IBAT0L@h
|
||||
ori r4, r4, CFG_IBAT0L@l
|
||||
addis r3, r0, CFG_IBAT0U@h
|
||||
ori r3, r3, CFG_IBAT0U@l
|
||||
mtspr IBAT0L, r4
|
||||
mtspr IBAT0U, r3
|
||||
isync
|
||||
|
||||
/* DBAT 0 */
|
||||
addis r4, r0, CFG_DBAT0L@h
|
||||
ori r4, r4, CFG_DBAT0L@l
|
||||
addis r3, r0, CFG_DBAT0U@h
|
||||
ori r3, r3, CFG_DBAT0U@l
|
||||
mtspr DBAT0L, r4
|
||||
mtspr DBAT0U, r3
|
||||
isync
|
||||
|
||||
/* IBAT 1 */
|
||||
addis r4, r0, CFG_IBAT1L@h
|
||||
ori r4, r4, CFG_IBAT1L@l
|
||||
addis r3, r0, CFG_IBAT1U@h
|
||||
ori r3, r3, CFG_IBAT1U@l
|
||||
mtspr IBAT1L, r4
|
||||
mtspr IBAT1U, r3
|
||||
isync
|
||||
|
||||
/* DBAT 1 */
|
||||
addis r4, r0, CFG_DBAT1L@h
|
||||
ori r4, r4, CFG_DBAT1L@l
|
||||
addis r3, r0, CFG_DBAT1U@h
|
||||
ori r3, r3, CFG_DBAT1U@l
|
||||
mtspr DBAT1L, r4
|
||||
mtspr DBAT1U, r3
|
||||
isync
|
||||
|
||||
/* IBAT 2 */
|
||||
addis r4, r0, CFG_IBAT2L@h
|
||||
ori r4, r4, CFG_IBAT2L@l
|
||||
addis r3, r0, CFG_IBAT2U@h
|
||||
ori r3, r3, CFG_IBAT2U@l
|
||||
mtspr IBAT2L, r4
|
||||
mtspr IBAT2U, r3
|
||||
isync
|
||||
|
||||
/* DBAT 2 */
|
||||
addis r4, r0, CFG_DBAT2L@h
|
||||
ori r4, r4, CFG_DBAT2L@l
|
||||
addis r3, r0, CFG_DBAT2U@h
|
||||
ori r3, r3, CFG_DBAT2U@l
|
||||
mtspr DBAT2L, r4
|
||||
mtspr DBAT2U, r3
|
||||
isync
|
||||
|
||||
/* IBAT 3 */
|
||||
addis r4, r0, CFG_IBAT3L@h
|
||||
ori r4, r4, CFG_IBAT3L@l
|
||||
addis r3, r0, CFG_IBAT3U@h
|
||||
ori r3, r3, CFG_IBAT3U@l
|
||||
mtspr IBAT3L, r4
|
||||
mtspr IBAT3U, r3
|
||||
isync
|
||||
|
||||
/* DBAT 3 */
|
||||
addis r4, r0, CFG_DBAT3L@h
|
||||
ori r4, r4, CFG_DBAT3L@l
|
||||
addis r3, r0, CFG_DBAT3U@h
|
||||
ori r3, r3, CFG_DBAT3U@l
|
||||
mtspr DBAT3L, r4
|
||||
mtspr DBAT3U, r3
|
||||
isync
|
||||
|
||||
/* bats are done, now invalidate the TLBs */
|
||||
|
||||
addis r3, 0, 0x0000
|
||||
addis r5, 0, 0x4 /* upper bound of 0x00040000 for 7400/750 */
|
||||
|
||||
isync
|
||||
|
||||
tlblp:
|
||||
tlbie r3
|
||||
sync
|
||||
addi r3, r3, 0x1000
|
||||
cmp 0, 0, r3, r5
|
||||
blt tlblp
|
||||
|
||||
blr
|
||||
|
||||
.globl enable_addr_trans
|
||||
enable_addr_trans:
|
||||
/* enable address translation */
|
||||
mfmsr r5
|
||||
ori r5, r5, (MSR_IR | MSR_DR)
|
||||
mtmsr r5
|
||||
isync
|
||||
blr
|
||||
|
||||
.globl disable_addr_trans
|
||||
disable_addr_trans:
|
||||
/* disable address translation */
|
||||
mflr r4
|
||||
mfmsr r3
|
||||
andi. r0, r3, (MSR_IR | MSR_DR)
|
||||
beqlr
|
||||
andc r3, r3, r0
|
||||
mtspr SRR0, r4
|
||||
mtspr SRR1, r3
|
||||
rfi
|
||||
|
||||
/*
|
||||
* This code finishes saving the registers to the exception frame
|
||||
* and jumps to the appropriate handler for the exception.
|
||||
* Register r21 is pointer into trap frame, r1 has new stack pointer.
|
||||
*/
|
||||
.globl transfer_to_handler
|
||||
transfer_to_handler:
|
||||
stw r22,_NIP(r21)
|
||||
lis r22,MSR_POW@h
|
||||
andc r23,r23,r22
|
||||
stw r23,_MSR(r21)
|
||||
SAVE_GPR(7, r21)
|
||||
SAVE_4GPRS(8, r21)
|
||||
SAVE_8GPRS(12, r21)
|
||||
SAVE_8GPRS(24, r21)
|
||||
mflr r23
|
||||
andi. r24,r23,0x3f00 /* get vector offset */
|
||||
stw r24,TRAP(r21)
|
||||
li r22,0
|
||||
stw r22,RESULT(r21)
|
||||
mtspr SPRG2,r22 /* r1 is now kernel sp */
|
||||
lwz r24,0(r23) /* virtual address of handler */
|
||||
lwz r23,4(r23) /* where to go when done */
|
||||
mtspr SRR0,r24
|
||||
mtspr SRR1,r20
|
||||
mtlr r23
|
||||
SYNC
|
||||
rfi /* jump to handler, enable MMU */
|
||||
|
||||
int_return:
|
||||
mfmsr r28 /* Disable interrupts */
|
||||
li r4,0
|
||||
ori r4,r4,MSR_EE
|
||||
andc r28,r28,r4
|
||||
SYNC /* Some chip revs need this... */
|
||||
mtmsr r28
|
||||
SYNC
|
||||
lwz r2,_CTR(r1)
|
||||
lwz r0,_LINK(r1)
|
||||
mtctr r2
|
||||
mtlr r0
|
||||
lwz r2,_XER(r1)
|
||||
lwz r0,_CCR(r1)
|
||||
mtspr XER,r2
|
||||
mtcrf 0xFF,r0
|
||||
REST_10GPRS(3, r1)
|
||||
REST_10GPRS(13, r1)
|
||||
REST_8GPRS(23, r1)
|
||||
REST_GPR(31, r1)
|
||||
lwz r2,_NIP(r1) /* Restore environment */
|
||||
lwz r0,_MSR(r1)
|
||||
mtspr SRR0,r2
|
||||
mtspr SRR1,r0
|
||||
lwz r0,GPR0(r1)
|
||||
lwz r2,GPR2(r1)
|
||||
lwz r1,GPR1(r1)
|
||||
SYNC
|
||||
rfi
|
||||
|
||||
.globl dc_read
|
||||
dc_read:
|
||||
blr
|
||||
|
||||
.globl get_pvr
|
||||
get_pvr:
|
||||
mfspr r3, PVR
|
||||
blr
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/*
|
||||
* void relocate_code (addr_sp, gd, addr_moni)
|
||||
*
|
||||
* This "function" does not return, instead it continues in RAM
|
||||
* after relocating the monitor code.
|
||||
*
|
||||
* r3 = dest
|
||||
* r4 = src
|
||||
* r5 = length in bytes
|
||||
* r6 = cachelinesize
|
||||
*/
|
||||
.globl relocate_code
|
||||
relocate_code:
|
||||
mr r1, r3 /* Set new stack pointer */
|
||||
mr r9, r4 /* Save copy of Global Data pointer */
|
||||
mr r10, r5 /* Save copy of Destination Address */
|
||||
|
||||
mr r3, r5 /* Destination Address */
|
||||
lis r4, CFG_MONITOR_BASE@h /* Source Address */
|
||||
ori r4, r4, CFG_MONITOR_BASE@l
|
||||
lis r5, CFG_MONITOR_LEN@h /* Length in Bytes */
|
||||
ori r5, r5, CFG_MONITOR_LEN@l
|
||||
li r6, CFG_CACHELINE_SIZE /* Cache Line Size */
|
||||
|
||||
/*
|
||||
* Fix GOT pointer:
|
||||
*
|
||||
* New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
|
||||
*
|
||||
* Offset:
|
||||
*/
|
||||
sub r15, r10, r4
|
||||
|
||||
/* First our own GOT */
|
||||
add r14, r14, r15
|
||||
/* then the one used by the C code */
|
||||
add r30, r30, r15
|
||||
|
||||
/*
|
||||
* Now relocate code
|
||||
*/
|
||||
#ifdef CONFIG_ECC
|
||||
bl board_relocate_rom
|
||||
sync
|
||||
mr r3, r10 /* Destination Address */
|
||||
lis r4, CFG_MONITOR_BASE@h /* Source Address */
|
||||
ori r4, r4, CFG_MONITOR_BASE@l
|
||||
lis r5, CFG_MONITOR_LEN@h /* Length in Bytes */
|
||||
ori r5, r5, CFG_MONITOR_LEN@l
|
||||
li r6, CFG_CACHELINE_SIZE /* Cache Line Size */
|
||||
#else
|
||||
cmplw cr1,r3,r4
|
||||
addi r0,r5,3
|
||||
srwi. r0,r0,2
|
||||
beq cr1,4f /* In place copy is not necessary */
|
||||
beq 7f /* Protect against 0 count */
|
||||
mtctr r0
|
||||
bge cr1,2f
|
||||
|
||||
la r8,-4(r4)
|
||||
la r7,-4(r3)
|
||||
1: lwzu r0,4(r8)
|
||||
stwu r0,4(r7)
|
||||
bdnz 1b
|
||||
b 4f
|
||||
|
||||
2: slwi r0,r0,2
|
||||
add r8,r4,r0
|
||||
add r7,r3,r0
|
||||
3: lwzu r0,-4(r8)
|
||||
stwu r0,-4(r7)
|
||||
bdnz 3b
|
||||
#endif
|
||||
/*
|
||||
* Now flush the cache: note that we must start from a cache aligned
|
||||
* address. Otherwise we might miss one cache line.
|
||||
*/
|
||||
4: cmpwi r6,0
|
||||
add r5,r3,r5
|
||||
beq 7f /* Always flush prefetch queue in any case */
|
||||
subi r0,r6,1
|
||||
andc r3,r3,r0
|
||||
mr r4,r3
|
||||
5: dcbst 0,r4
|
||||
add r4,r4,r6
|
||||
cmplw r4,r5
|
||||
blt 5b
|
||||
sync /* Wait for all dcbst to complete on bus */
|
||||
mr r4,r3
|
||||
6: icbi 0,r4
|
||||
add r4,r4,r6
|
||||
cmplw r4,r5
|
||||
blt 6b
|
||||
7: sync /* Wait for all icbi to complete on bus */
|
||||
isync
|
||||
|
||||
/*
|
||||
* We are done. Do not return, instead branch to second part of board
|
||||
* initialization, now running from RAM.
|
||||
*/
|
||||
addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
|
||||
mtlr r0
|
||||
blr
|
||||
|
||||
in_ram:
|
||||
#ifdef CONFIG_ECC
|
||||
bl board_init_ecc
|
||||
#endif
|
||||
/*
|
||||
* Relocation Function, r14 point to got2+0x8000
|
||||
*
|
||||
* Adjust got2 pointers, no need to check for 0, this code
|
||||
* already puts a few entries in the table.
|
||||
*/
|
||||
li r0,__got2_entries@sectoff@l
|
||||
la r3,GOT(_GOT2_TABLE_)
|
||||
lwz r11,GOT(_GOT2_TABLE_)
|
||||
mtctr r0
|
||||
sub r11,r3,r11
|
||||
addi r3,r3,-4
|
||||
1: lwzu r0,4(r3)
|
||||
add r0,r0,r11
|
||||
stw r0,0(r3)
|
||||
bdnz 1b
|
||||
|
||||
/*
|
||||
* Now adjust the fixups and the pointers to the fixups
|
||||
* in case we need to move ourselves again.
|
||||
*/
|
||||
2: li r0,__fixup_entries@sectoff@l
|
||||
lwz r3,GOT(_FIXUP_TABLE_)
|
||||
cmpwi r0,0
|
||||
mtctr r0
|
||||
addi r3,r3,-4
|
||||
beq 4f
|
||||
3: lwzu r4,4(r3)
|
||||
lwzux r0,r4,r11
|
||||
add r0,r0,r11
|
||||
stw r10,0(r3)
|
||||
stw r0,0(r4)
|
||||
bdnz 3b
|
||||
4:
|
||||
/* clear_bss: */
|
||||
/*
|
||||
* Now clear BSS segment
|
||||
*/
|
||||
lwz r3,GOT(.bss)
|
||||
lwz r4,GOT(_end)
|
||||
|
||||
cmplw 0, r3, r4
|
||||
beq 6f
|
||||
|
||||
li r0, 0
|
||||
5:
|
||||
stw r0, 0(r3)
|
||||
addi r3, r3, 4
|
||||
cmplw 0, r3, r4
|
||||
bne 5b
|
||||
6:
|
||||
mr r3, r10 /* Destination Address */
|
||||
bl after_reloc
|
||||
|
||||
/* not reached - end relocate_code */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
/* Problems accessing "end" in C, so do it here */
|
||||
.globl get_endaddr
|
||||
get_endaddr:
|
||||
lwz r3,GOT(_end)
|
||||
blr
|
||||
|
||||
/*
|
||||
* Copy exception vector code to low memory
|
||||
*
|
||||
* r3: dest_addr
|
||||
* r7: source address, r8: end address, r9: target address
|
||||
*/
|
||||
.globl trap_init
|
||||
trap_init:
|
||||
lwz r7, GOT(_start)
|
||||
lwz r8, GOT(_end_of_vectors)
|
||||
|
||||
rlwinm r9, r7, 0, 18, 31 /* _start & 0x3FFF */
|
||||
|
||||
cmplw 0, r7, r8
|
||||
bgelr /* return if r7>=r8 - just in case */
|
||||
|
||||
mflr r4 /* save link register */
|
||||
1:
|
||||
lwz r0, 0(r7)
|
||||
stw r0, 0(r9)
|
||||
addi r7, r7, 4
|
||||
addi r9, r9, 4
|
||||
cmplw 0, r7, r8
|
||||
bne 1b
|
||||
|
||||
/*
|
||||
* relocate `hdlr' and `int_return' entries
|
||||
*/
|
||||
li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
|
||||
li r8, Alignment - _start + EXC_OFF_SYS_RESET
|
||||
2:
|
||||
bl trap_reloc
|
||||
addi r7, r7, 0x100 /* next exception vector */
|
||||
cmplw 0, r7, r8
|
||||
blt 2b
|
||||
|
||||
li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
|
||||
bl trap_reloc
|
||||
|
||||
li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
|
||||
bl trap_reloc
|
||||
|
||||
li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
|
||||
li r8, SystemCall - _start + EXC_OFF_SYS_RESET
|
||||
3:
|
||||
bl trap_reloc
|
||||
addi r7, r7, 0x100 /* next exception vector */
|
||||
cmplw 0, r7, r8
|
||||
blt 3b
|
||||
|
||||
li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
|
||||
li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
|
||||
4:
|
||||
bl trap_reloc
|
||||
addi r7, r7, 0x100 /* next exception vector */
|
||||
cmplw 0, r7, r8
|
||||
blt 4b
|
||||
|
||||
/* enable execptions from RAM vectors */
|
||||
mfmsr r7
|
||||
li r8,MSR_IP
|
||||
andc r7,r7,r8
|
||||
mtmsr r7
|
||||
|
||||
mtlr r4 /* restore link register */
|
||||
blr
|
||||
|
||||
/*
|
||||
* Function: relocate entries for one exception vector
|
||||
*/
|
||||
trap_reloc:
|
||||
lwz r0, 0(r7) /* hdlr ... */
|
||||
add r0, r0, r3 /* ... += dest_addr */
|
||||
stw r0, 0(r7)
|
||||
|
||||
lwz r0, 4(r7) /* int_return ... */
|
||||
add r0, r0, r3 /* ... += dest_addr */
|
||||
stw r0, 4(r7)
|
||||
|
||||
sync
|
||||
isync
|
||||
|
||||
blr
|
||||
|
||||
#ifdef CFG_INIT_RAM_LOCK
|
||||
lock_ram_in_cache:
|
||||
/* Allocate Initial RAM in data cache.
|
||||
*/
|
||||
lis r3, (CFG_INIT_RAM_ADDR & ~31)@h
|
||||
ori r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
|
||||
li r2, ((CFG_INIT_RAM_END & ~31) + \
|
||||
(CFG_INIT_RAM_ADDR & 31) + 31) / 32
|
||||
mtctr r2
|
||||
1:
|
||||
dcbz r0, r3
|
||||
addi r3, r3, 32
|
||||
bdnz 1b
|
||||
|
||||
/* Lock the data cache */
|
||||
mfspr r0, HID0
|
||||
ori r0, r0, 0x1000
|
||||
sync
|
||||
mtspr HID0, r0
|
||||
sync
|
||||
blr
|
||||
|
||||
.globl unlock_ram_in_cache
|
||||
unlock_ram_in_cache:
|
||||
/* invalidate the INIT_RAM section */
|
||||
lis r3, (CFG_INIT_RAM_ADDR & ~31)@h
|
||||
ori r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
|
||||
li r2, ((CFG_INIT_RAM_END & ~31) + \
|
||||
(CFG_INIT_RAM_ADDR & 31) + 31) / 32
|
||||
mtctr r2
|
||||
1: icbi r0, r3
|
||||
addi r3, r3, 32
|
||||
bdnz 1b
|
||||
sync /* Wait for all icbi to complete on bus */
|
||||
isync
|
||||
|
||||
/* Unlock the data cache and invalidate it */
|
||||
mfspr r0, HID0
|
||||
li r3,0x1000
|
||||
andc r0,r0,r3
|
||||
li r3,0x0400
|
||||
or r0,r0,r3
|
||||
sync
|
||||
mtspr HID0, r0
|
||||
sync
|
||||
blr
|
||||
#endif
|
1092
cpu/mpc8260/start.S
Normal file
1092
cpu/mpc8260/start.S
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue