* "last user address" is set even if bootp is used without parameters
(and it uses default address).
+======================================================================
+Modifications for 1.1.0:
+======================================================================
+
+* Extend LWMON keyboard driver to allow for more than one key-coded
+ pre-boot command (we now support an unlimited number of keys)
+
+* Added "hush" shell (from Busybox) as alternative command line
+ interpreter, thus enabling powerful command line syntax like
+ if...then...else...fi conditionals or `&&' and '||' constructs
+ ("shell scripts").
+
+* Modified all commands to provide return codes that can be used for
+ conditional command execution
+
======================================================================
Modifications for 1.0.6:
======================================================================
useful during development since you can try to debug
the conditions that lead to the situation.
+- Command Interpreter:
+ CFG_HUSH_PARSER
+
+ Define this variable to enable the "hush" shell (from
+ Busybox) as command line interpreter, thus enabling
+ powerful command line syntax like
+ if...then...else...fi conditionals or `&&' and '||'
+ constructs ("shell scripts").
+
+ If undefined, you get the old, much simpler behaviour
+ with a somewhat smapper memory footprint.
+
+
+ CFG_PROMPT_HUSH_PS2
+
+ This defines the secondary prompt string, which is
+ printed when the command interpreter needs more input
+ to complete a command. Usually "> ".
+
Configuration Settings:
-----------------------
);
}
printf ("\n");
+ return;
}
/*-----------------------------------------------------------------------
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
vu_long *addr = (vu_long*)(info->start[0]);
int flag, prot, sect, l_sect;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
if ((info->flash_id == FLASH_UNKNOWN) ||
(info->flash_id > FLASH_AMD_COMP)) {
printf ("Can't erase unknown flash type %08lx - aborted\n",
info->flash_id);
- return;
+ return 1;
}
prot = 0;
while ((addr[0] & 0x80808080) != 0x80808080) {
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
- return;
+ return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
addr[0] = 0xF0F0F0F0; /* reset bank */
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
);
}
printf ("\n");
+ return;
}
/*-----------------------------------------------------------------------
* The following code cannot be run from FLASH!
*/
-void
+int
flash_erase(flash_info_t *info, int s_first, int s_last)
{
int prot, sect, haderr;
void (*erase_init)(flash_info_t *, int);
int (*erase_poll)(flash_info_t *, int);
void (*reset)(flash_info_t *, int);
+ int rcode = 0;
#ifdef FLASH_DEBUG
printf("\nflash_erase: erase %d sectors (%d to %d incl.) from\n"
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
switch (info->flash_id) {
default:
printf ("Flash type %08lx not supported - aborted\n",
info->flash_id);
- return;
+ return 1;
}
prot = 0;
}
}
- if (haderr > 0)
+ if (haderr > 0) {
printf (" failed\n");
+ rcode = 1;
+ }
else
printf (" done\n");
(*reset)(info, sect);
}
}
+ return rcode;
}
/*-----------------------------------------------------------------------
/* ------------------------------------------------------------------------- */
-void do_crayL1(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_crayL1(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
unsigned long addr, valu,old;
u8 thing,need_save=0,only, *ptr;
for ( thing=0; thing < N_THINGS; thing++)
printf ("%s ",Things[thing].envname);
printf ("]\n");
- return;
+ return 1;
}
else
printf ("Update %s\n",Things[only].envname);
}
if (need_save)
do_saveenv (NULL,NULL,0,0,NULL);
- return;
+ return 0;
}
if (strcmp(argv[1], "boot") == 0) // boot ourselves up.
addr = load_addr;
do_bootm (cmdtp, bd, 0, 1, NULL);
- return;
+ return 0;
}
if (strcmp(argv[1], "regs") == 0) // Dump DCRs
{
printf("cray regs command..UNIMPLEMENTED.\n");
- return;
+ return 1;
}
if (strcmp(argv[1], "mfdcr") == 0) // read a DCR from argv[2] (HEX!)
{
addr = simple_strtoul(argv[2], NULL, 16);
printf("cray mfcdr command: read from DCR 0x%lx UNIMPLEMENTED.\n",addr);
- return;
+ return 1;
}
if (strcmp(argv[1], "mtdcr") == 0) // write a DCR from argv[2] (HEX!)
{
valu = simple_strtoul(argv[3], NULL, 16);
printf("cray mtcdr command: write 0x%lx to DCR 0x%lx UNIMPLEMENTED\n",
valu, addr);
- return;
+ return 1;
}
printf("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]);
volatile FLASH_WORD_SIZE *addr2;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
if (info->flash_id == FLASH_UNKNOWN) {
printf ("Can't erase unknown flash type - aborted\n");
- return;
+ return 1;
}
prot = 0;
addr[0] = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
printf ("\n");
Done:
+ return;
}
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
int flag, prot, sect;
ulong start, now, last;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
if ((info->flash_id & FLASH_VENDMASK) !=
(INTEL_MANUFACT & FLASH_VENDMASK)) {
printf ("Can erase only Intel flash types - aborted\n");
- return;
+ return 1;
}
prot = 0;
printf ("Timeout\n");
*addr = 0x00B000B0; /* suspend erase */
*addr = 0x00FF00FF; /* to read mode */
- return;
+ return 1;
}
/* show that we're waiting */
}
}
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
);
}
printf ("\n");
+ return;
}
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
volatile FLASH_WORD_SIZE *addr=(volatile FLASH_WORD_SIZE*)(info->start[0]);
int flag, prot, sect, l_sect, barf;
ulong start, now, last;
+ int rcode = 0;
if ((s_first < 0) || (s_first > s_last)) {
if (info->flash_id == FLASH_UNKNOWN) {
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
if ((info->flash_id == FLASH_UNKNOWN) ||
((info->flash_id > FLASH_AMD_COMP) &&
( (info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL ) ) ){
printf ("Can't erase unknown flash type - aborted\n");
- return;
+ return 1;
}
prot = 0;
{
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
- return;
+ return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
if((barf & 0x0030) == 0x0020)
printf("Block Erase error.\n");
if(barf & 0x0008) printf("Vpp Low error.\n");
+ rcode = 1;
} else printf(".");
l_sect = sect;
}
}
printf (" done\n");
+ return rcode;
}
/*-----------------------------------------------------------------------
}
printf ("\n");
+ return;
}
/*-----------------------------------------------------------------------
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
volatile CFG_FLASH_WORD_SIZE *addr = (CFG_FLASH_WORD_SIZE *)(info->start[0]);
volatile CFG_FLASH_WORD_SIZE *addr2;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
if (info->flash_id == FLASH_UNKNOWN) {
printf ("Can't erase unknown flash type - aborted\n");
- return;
+ return 1;
}
prot = 0;
while ((addr[0] & (CFG_FLASH_WORD_SIZE)0x00800080) != (CFG_FLASH_WORD_SIZE)0x00800080) {
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
- return;
+ return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
addr[0] = (CFG_FLASH_WORD_SIZE)0x00F000F0; /* reset bank */
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
/* ------------------------------------------------------------------------- */
-
-void do_pci9054(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_pci9054(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
pci9054_init();
if (strcmp(argv[1], "info") == 0)
{
showPci9054();
- return;
+ return 0;
}
if (strcmp(argv[1], "update") == 0)
{
updatePci9054();
- return;
+ return 0;
}
if (strcmp(argv[1], "clear") == 0)
{
clearPci9054();
- return;
+ return 0;
}
printf("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
+
}
/* ------------------------------------------------------------------------- */
);
}
printf ("\n");
+ return;
}
/*-----------------------------------------------------------------------
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
volatile FLASH_WORD_SIZE *addr=(volatile FLASH_WORD_SIZE*)(info->start[0]);
int flag, prot, sect, l_sect, barf;
ulong start, now, last;
+ int rcode = 0;
if ((s_first < 0) || (s_first > s_last)) {
if (info->flash_id == FLASH_UNKNOWN) {
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
if ((info->flash_id == FLASH_UNKNOWN) ||
((info->flash_id > FLASH_AMD_COMP) &&
( (info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL ) ) ){
printf ("Can't erase unknown flash type - aborted\n");
- return;
+ return 1;
}
prot = 0;
{
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
- return;
+ return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
if((barf & 0x0030) == 0x0020)
printf("Block Erase error.\n");
if(barf & 0x0008) printf("Vpp Low error.\n");
+ rcode = 1;
} else printf(".");
l_sect = sect;
}
}
printf (" done\n");
+ return rcode;
}
/*-----------------------------------------------------------------------
);
}
printf ("\n");
+ return;
}
/*-----------------------------------------------------------------------
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
vu_long *addr = (vu_long*)(info->start[0]);
int flag, prot, sect;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
/*#ifndef CONFIG_FLASH_16BIT
ulong type;
#endif
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
- return;
+ return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
#endif
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
);
}
printf ("\n");
+ return;
}
/*-----------------------------------------------------------------------
return (info->size);
}
-void
+int
flash_erase (flash_info_t *info, int s_first, int s_last)
{
volatile unsigned char *addr = (char *)(info->start[0]);
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
if ((info->flash_id == FLASH_UNKNOWN) ||
(info->flash_id > FLASH_AMD_COMP)) {
printf ("Can't erase unknown flash type %08lx - aborted\n",
info->flash_id);
- return;
+ return 1;
}
prot = 0;
while ((addr[0] & 0x80) != 0x80) {
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
- return;
+ return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
addr[0] = 0xF0; /* reset bank */
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
}
printf ("\n");
+ return;
}
/*-----------------------------------------------------------------------
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
vu_long *addr = (vu_long*)(info->start[0]);
int flag, prot, sect, l_sect;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
if ((info->flash_id == FLASH_UNKNOWN) ||
(info->flash_id > FLASH_AMD_COMP)) {
printf ("Can't erase unknown flash type - aborted\n");
- return;
+ return 1;
}
prot = 0;
{
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
- return;
+ return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
#endif
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
if (info->flash_id == FLASH_UNKNOWN) {
printf ("missing or unknown FLASH type\n");
- return;
+ return ;
}
switch (info->flash_id & FLASH_VENDMASK) {
);
}
printf ("\n");
+ return ;
}
/*-----------------------------------------------------------------------
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
vu_short *addr;
int flag, prot, sect;
ulong start, now, last;
+ int rcode = 0;
if ((s_first < 0) || (s_first > s_last)) {
if (info->flash_id == FLASH_UNKNOWN) {
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL) {
printf ("Can't erase unknown flash type %08lx - aborted\n",
info->flash_id);
- return;
+ return 1;
}
prot = 0;
if ((now=get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
*addr = 0xFFFF; /* reset bank */
- return;
+ return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
if(flash_decode_status_bits(tmp|INTEL_FLASH_STATUS_WSMS)==-1
&& (tmp & INTEL_FLASH_STATUS_WSMS)) {
printf("Error erasing\n");
+ rcode++;
break;
}
}
*addr = 0xFFFF; /* reset bank */
printf (" done\n");
+ return rcode;
}
void sector_protect (flash_info_t *info, int on, int s_first, int s_last)
}
putc ('\n');
+ return;
}
/*-----------------------------------------------------------------------
*/
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
volatile unsigned char *addr = (volatile unsigned char *)(info->start[0]);
int flag, prot, sect, l_sect;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
if ((info->flash_id == FLASH_UNKNOWN) ||
(info->flash_id > FLASH_AMD_COMP)) {
printf ("Can't erase unknown flash type - aborted\n");
- return;
+ return 1;
}
prot = 0;
{
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
- return;
+ return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
addr[0] = 0xF0; /* reset bank */
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
}
printf ("\n");
+ return;
}
/*-----------------------------------------------------------------------
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
vu_long *addr = (vu_long*)(info->start[0]);
int flag, prot, sect, l_sect;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
if ((info->flash_id == FLASH_UNKNOWN) ||
(info->flash_id > FLASH_AMD_COMP)) {
printf ("Can't erase unknown flash type - aborted\n");
- return;
+ return 1;
}
prot = 0;
{
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
- return;
+ return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
#endif
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
);
}
printf ("\n");
+ return;
}
/*-----------------------------------------------------------------------
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
vu_char *addr = (vu_char*)(info->start[0]);
int flag, prot, sect, l_sect;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
if ((info->flash_id == FLASH_UNKNOWN) ||
(info->flash_id > FLASH_AMD_COMP)) {
printf ("Can't erase unknown flash type %08lx - aborted\n",
info->flash_id);
- return;
+ return 1;
}
prot = 0;
while ((addr[0] & 0x80) != 0x80) {
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
- return;
+ return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
addr[0] = 0xF0; /* reset bank */
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
}
/* ------------------------------------------------------------------------- */
-
-void
+int
do_fpga(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
uchar *addr, *save_addr;
FPGA_MAIN_PORT_BASE, FPGA_MAIN_PORT_SIZE);
printf(" Mezz Configuration: 0x%08x %d\n",
FPGA_MEZZ_CFG_BASE, FPGA_MEZZ_CFG_SIZE);
- return;
+ return 0;
}
break;
#else
result = 0;
#endif
-
- if (result == STORE_SUCCESS)
+ if (result == STORE_SUCCESS) {
printf("SUCCEEDED (%d bytes)\n", addr - save_addr);
+ return 0;
+ }
else
printf("FAILED (%d bytes)\n", addr - save_addr);
- return;
+ return 1;
}
break;
if (NetLoop(bd, TFTP) == 0) {
printf("tftp transfer failed - aborting fgpa load\n");
- return;
+ return 1;
}
if (NetBootFileXferSize == 0) {
printf("can't determine file size - aborting fpga load\n");
- return;
+ return 1;
}
printf("File transfer succeeded - beginning fpga load...");
result = fpga_load(bd, 0, (uchar *)load_addr, NetBootFileXferSize);
-
- if (result == LOAD_SUCCESS)
+ if (result == LOAD_SUCCESS) {
printf("SUCCEEDED\n");
+ return 0;
+ }
else if (result == LOAD_FAIL_NOINIT)
printf("FAILED (no INIT)\n");
else
printf("FAILED (no DONE)\n");
- return;
+ return 1;
+
}
/* fall through ... */
mezz = 1;
else {
printf("FPGA type must be either `main' or `mezz'\n");
- return;
+ return 1;
}
arg = 3;
}
size = (ulong)simple_strtoul(argv[arg], NULL, 16);
result = fpga_load(bd, mezz, addr, size);
-
- if (result == LOAD_SUCCESS)
+ if (result == LOAD_SUCCESS) {
printf("SUCCEEDED\n");
+ return 0;
+ }
else if (result == LOAD_FAIL_NOINIT)
printf("FAILED (no INIT)\n");
else
printf("FAILED (no DONE)\n");
- return;
+ return 1;
}
break;
}
printf("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
/* ------------------------------------------------------------------------- */
-
-void
+int
do_eecl(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
uchar data[HYMOD_EEPROM_SIZE];
uint offset;
+ int rcode = 0;
switch (argc) {
default:
printf("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
-
+
memset(data, 0, HYMOD_EEPROM_SIZE);
-
- eeprom_write(offset, data, HYMOD_EEPROM_SIZE);
+ if (eeprom_write(offset, data, HYMOD_EEPROM_SIZE) != 0) rcode = 1;
+ return rcode;
}
#endif /* CFG_CMD_BSP */
);
}
printf ("\n");
+ return;
}
/*-----------------------------------------------------------------------
/*-----------------------------------------------------------------------
*/
-void
+int
flash_erase(flash_info_t *info, int s_first, int s_last)
{
int prot, sect, haderr;
ulong start, now, last;
+ int rcode = 0;
#ifdef FLASH_DEBUG
printf("\nflash_erase: erase %d sectors (%d to %d incl.) from\n"
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
prot = 0;
if (now - estart > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout (sect %d)\n", sect);
haderr = 1;
+ rcode = 1;
break;
}
if (sectdone < 0) {
haderr = 1;
+ rcode = 1;
break;
}
bank_reset(info, sect);
}
}
+ return rcode;
}
/*-----------------------------------------------------------------------
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
vu_long *addr = (vu_long*)(info->start[0]);
int flag, prot, sect, l_sect;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
if ((info->flash_id == FLASH_UNKNOWN) ||
(info->flash_id > FLASH_AMD_COMP)) {
printf ("Can't erase unknown flash type - aborted\n");
- return;
+ return 1;
}
prot = 0;
{
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
- return;
+ return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
#endif
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
);
}
printf ("\n");
+ return;
}
/*-----------------------------------------------------------------------
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
vu_long *addr;
int flag, prot, sect;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL) {
printf ("Can't erase unknown flash type %08lx - aborted\n",
info->flash_id);
- return;
+ return 1;
}
prot = 0;
if ((now=get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
*addr = 0xFFFFFFFF; /* reset bank */
- return;
+ return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
*addr = 0xFFFFFFFF; /* reset bank */
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
);
}
printf ("\n");
+ return;
}
/*-----------------------------------------------------------------------
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
int flag, prot, sect;
ulong start, now, last;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_MT) {
printf ("Can erase only MT flash types - aborted\n");
- return;
+ return 1;
}
prot = 0;
if ((now=get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
*addr = 0x00FF; /* reset to read mode */
- return;
+ return 1;
}
/* show that we're waiting */
}
}
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
);
}
printf ("\n");
+ return;
}
/*-----------------------------------------------------------------------
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
vu_long *addr = (vu_long*)(info->start[0]);
int flag, prot, sect, l_sect;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
if ((info->flash_id == FLASH_UNKNOWN) ||
(info->flash_id > FLASH_AMD_COMP)) {
printf ("Can't erase unknown flash type %08lx - aborted\n",
info->flash_id);
- return;
+ return 1;
}
prot = 0;
while ((addr[0] & 0x00800080) != 0x00800080) {
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
- return;
+ return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
addr[0] = 0x00F000F0; /* reset bank */
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
--- /dev/null
+
+Tastaturabfrage:
+
+Die Implementierung / Decodierung beruht auf den Angaben aus dem Do-
+kument "PIC LWE-Tastatur" in der Fassung vom 9. 3. 2001, insbesonde-
+re Tabelle 3 im Kapitel 4.3 Tastencodes. In PPCBoot werden die vom
+Keyboard-Controller gelesenen Daten hexadezimal codiert in der auto-
+matisch angelegten Environment-Variablen "keybd" übergeben. Ist kei-
+ne Taste gedrückt worden, steht dort:
+
+ keybd=000000000000000000
+
+Der decodierte Tastencode ("keybd") kann mit den "bootargs" an den
+Linux-Kernel übergeben und dort z. B. in einem Device-Treiber oder
+einer Applikation ausgewertet werden.
+
+
+
+Sonderfunktionen beim Booten:
+
+Es lassen sich eine oder mehrere (beliebig viele) Tasten oder Tasten-
+kombinationen definieren, die Sonderfunktionen auslösen, wenn diese
+Tasten beim Booten (Reset) gedrückt sind.
+
+Wird eine eingestellte Taste bzw. Tastenkombination erkannt, so wird
+in PPCBoot noch vor dem Start des "Countdown" und somit vor jedem
+anderen Kommando der Inhalt einer dieser Taste bzw. Tastenkombination
+zugeordneten Environment-Variablen ausführen.
+
+
+Die Environment-Variable "magic_keys" wird als Liste von Zeichen ver-
+standen, die als Suffix an den Namen "key_magic" angefügt werden und
+so die Namen der Environment-Variablen definieren, mit denen die
+Tasten (-kombinationen) festgelegt werden:
+
+Ist "magic_keys" NICHT definiert, so wird nur die in der Environment-
+Variablen "key_magic" codierte Tasten (-kombination) geprüft, und
+ggf. der Inhalt der Environment-Variablen "key_cmd" ausgeführt.
+
+Enthält "magic_keys" z. B. die Zeichenkette "0123CB*", so werden
+nacheinander folgende Aktionen ausgeführt:
+
+ prüfe Tastencode ggf. führe aus Kommando
+ in Variable in Variable
+ -----------------------------------
+ key_magic0 ==> key_cmd0
+ key_magic1 ==> key_cmd1
+ key_magic2 ==> key_cmd2
+ key_magic3 ==> key_cmd3
+ key_magicC ==> key_cmdC
+ key_magicB ==> key_cmdB
+ key_magicA ==> key_cmdA
+ key_magic* ==> key_cmd*
+
+Die Codierung der Tasten, die beim Booten gedrückt werden müssen, um
+eine Funktion auszulösen, erfolgt nach der Tastaturtabelle.
+
+Die Definitionen
+
+ => setenv key_magic0 3a+3b
+ => setenv key_cmd0 setenv bootdelay 30
+
+bedeuten dementsprechend, daß die Tasten mit den Codes 0x3A (Taste
+"F1") und 0x3B (Taste "F2") gleichzeitig gedrückt werden müssen. Sie
+können dort eine beliebige Tastenkombination eintragen (jeweils 2
+Zeichen für die Hex-Codes der Tasten, und '+' als Trennzeichen).
+
+Wird die eingestellte Tastenkombination erkannt, so wird in PPCBoot
+noch vor dem Start des "Countdown" und somit vor jedem anderen Kom-
+mando das angebene Kommando ausgeführt und somit ein langes Boot-
+Delay eingetragen.
+
+Praktisch könnten Sie also in PPCBoot "bootdelay" auf 0 setzen und
+somit stets ohne jede User-Interaktion automatisch booten, außer,
+wenn die beiden Tasten "F1" und "F2" beim Booten gedrückt werden:
+dann würde ein Boot-Delay von 30 Sekunden eingefügt.
);
}
printf ("\n");
+ return;
}
/*-----------------------------------------------------------------------
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
int flag, prot, sect;
ulong start, now, last;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL) {
printf ("Can erase only Intel flash types - aborted\n");
- return;
+ return 1;
}
prot = 0;
printf ("Timeout\n");
*addr = 0x00B000B0; /* suspend erase */
*addr = 0x00FF00FF; /* reset to read mode */
- return;
+ return 1;
}
/* show that we're waiting */
}
}
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
#include <i2c.h>
#include <command.h>
#include <cmd_bsp.h>
+#include <malloc.h>
+
+#include <linux/types.h>
+#include <linux/string.h> /* for strdup */
/* ------------------------------------------------------------------------- */
#define KEYBD_VERSIONLEN 2 /* version information */
#define KEYBD_DATALEN 9 /* normal key scan data */
+/* maximum number of "magic" key codes that can be assigned */
+
static uchar kbd_addr = CFG_I2C_KEYBD_ADDR;
-static uchar kbd_data[KEYBD_DATALEN];
-uchar keybd_env[2*KEYBD_DATALEN+1];
+static uchar kbd_data [KEYBD_DATALEN];
+static uchar keybd_env[2*KEYBD_DATALEN+1];
#ifdef CONFIG_PREBOOT
-static int key_match (uchar *);
+static uchar *key_match (uchar *);
#endif
void misc_init_r (bd_t *bd)
{
uchar val, errcd;
+ uchar *str;
int i;
i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
setenv ("keybd", keybd_env);
#ifdef CONFIG_PREBOOT /* automatically configure "preboot" command on key match */
- if (key_match(kbd_data)) {
- char *s = getenv ("key_cmd");
- setenv ("preboot", s);
- } else {
- setenv ("preboot", NULL); /* delete any existing definition */
+ str = strdup (key_match(kbd_data));
+ setenv ("preboot", str); /* set or delete definition */
+ if (str != NULL) {
+ free (str);
}
#endif /* CONFIG_PREBOOT */
}
/*-----------------------------------------------------------------------
- * Check if pressed key(s) match magic sequence
+ * Check if pressed key(s) match magic sequence,
+ * and return the command string associated with that key(s).
+ *
+ * Note: the string points to static environment data and must be
+ * saved before you call any function that modifies the environment.
*/
#ifdef CONFIG_PREBOOT
-static int key_match (uchar *kbd_data)
+
+static uchar kbd_magic_prefix[] = "key_magic";
+static uchar kbd_command_prefix[] = "key_cmd";
+
+static uchar *key_match (uchar *kbd_data)
{
uchar compare[KEYBD_DATALEN];
+ uchar magic[sizeof(kbd_magic_prefix) + 1];
uchar extra;
- uchar *str, *nxt;
+ uchar *str, *nxt, *suffix;
+ uchar *kbd_magic_keys;
int i;
- memcpy (compare, kbd_data, KEYBD_DATALEN);
+ /*
+ * The following string defines the characters that can pe appended
+ * to "key_magic" to form the names of environment variables that
+ * hold "magic" key codes, i. e. such key codes that can cause
+ * pre-boot actions. If the string is empty (""), then only
+ * "key_magic" is checked (old behaviour); the string "125" causes
+ * checks for "key_magic1", "key_magic2" and "key_magic5", etc.
+ */
+ if ((kbd_magic_keys = getenv("magic_keys")) == NULL)
+ kbd_magic_keys = "";
- extra = 0;
+ /* loop over all magic keys;
+ * use '\0' suffix in case of empty string
+ */
+ for (suffix=kbd_magic_keys; *suffix || suffix==kbd_magic_keys; ++suffix) {
+ sprintf (magic, "%s%c", kbd_magic_prefix, *suffix);
+#if 0
+ printf ("### Check magic \"%s\"\n", magic);
+#endif
+ memcpy (compare, kbd_data, KEYBD_DATALEN);
- for (str=getenv ("key_magic"); str != NULL; str = (*nxt) ? nxt+1 : nxt) {
- uchar c;
- int k;
+ extra = 0;
- c = (uchar)simple_strtoul(str, (char **)(&nxt), 16);
+ for (str=getenv (magic); str != NULL; str = (*nxt) ? nxt+1 : nxt) {
+ uchar c;
+ int k;
- if (str == nxt) { /* invalid character */
- break;
+ c = (uchar)simple_strtoul(str, (char **)(&nxt), 16);
+
+ if (str == nxt) { /* invalid character */
+ break;
+ }
+
+ /*
+ * Check if this key matches the input.
+ * Set matches to zero, so they match only once
+ * and we can find duplicates or extra keys
+ */
+ for (k=0; k<KEYBD_DATALEN; ++k) {
+ if (compare[k] == '\0') /* only non-zero entries */
+ continue;
+ if (c == compare[k]) { /* found matching key */
+ compare[k] = '\0';
+ break;
+ }
+ }
+ if (k == KEYBD_DATALEN) {
+ extra = 1; /* unmatched key */
+ }
}
/*
- * Check if this key matches the input.
- * Set matches to zero, so they match only once
- * and we can find duplicates or extra keys
+ * A full match leaves no keys in the `compare' array,
+ * and has no extra keys
*/
- for (k=0; k<KEYBD_DATALEN; ++k) {
- if (compare[k] == '\0') /* only non-zero entries */
- continue;
- if (c == compare[k]) { /* found matching key */
- compare[k] = '\0';
+
+ for (i=0; i<KEYBD_DATALEN; ++i) {
+ if (compare[i])
break;
- }
- }
- if (k == KEYBD_DATALEN) {
- extra = 1; /* unmatched key */
}
- }
- /*
- * A full match leaves no keys in the `compare' array,
- * and has no extra keys
- */
-
- for (i=0; i<KEYBD_DATALEN; ++i) {
- if (compare[i])
- break;
- }
+ if ((i == KEYBD_DATALEN) && (extra == 0)) {
+ uchar cmd_name[sizeof(kbd_command_prefix) + 1];
+ char *cmd;
- return ((i == KEYBD_DATALEN) && (extra == 0));
-}
+ sprintf (cmd_name, "%s%c", kbd_command_prefix, *suffix);
+
+ cmd = getenv (cmd_name);
+#if 0
+ printf ("### Set PREBOOT to $(%s): \"%s\"\n",
+ cmd_name, cmd ? cmd : "<<NULL>>");
+#endif
+ return (cmd);
+ }
+ }
+#if 0
+ printf ("### Delete PREBOOT\n");
#endif
+ return (NULL);
+}
+#endif /* CONFIG_PREBOOT */
/*-----------------------------------------------------------------------
* Board Special Commands: PIC read/write
*/
#if (CONFIG_COMMANDS & CFG_CMD_BSP)
-
-void do_pic (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_pic (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
uchar reg, val;
printf ("PIC read: reg %02x: %02x\n\n", reg, pic_read (reg));
- return;
+ return 0;
case 4: /* PIC write reg val */
if (strcmp(argv[1],"write") != 0)
break;
reg, val, pic_read (reg));
pic_write (reg, val);
printf ("%02x\n\n", pic_read (reg));
-
- return;
+ return 0;
default:
break;
}
printf ("Usage:\n%s\n", cmdtp->usage);
+ return 1;
}
+/* Read Keyboard status */
+int do_kbd (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+{
+ uchar val;
+ int i;
+
+ i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
+
+ /* Read keys */
+ val = KEYBD_CMD_READ_KEYS;
+ i2c_write (&kbd_addr, 1, &val, 1);
+ i2c_read (&kbd_addr, 1, kbd_data, KEYBD_DATALEN);
+
+ puts ("Keys:");
+ for (i=0; i<KEYBD_DATALEN; ++i) {
+ sprintf(keybd_env+i+i, "%02X", kbd_data[i]);
+ printf (" %02x", kbd_data[i]);
+ }
+ putc ('\n');
+ setenv ("keybd", keybd_env);
+ return 0;
+}
#endif /* CFG_CMD_BSP */
/*-----------------------------------------------------------------------
);
}
printf ("\n");
+ return;
}
/*
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
vu_long *addr = (vu_long*)(info->start[0]);
int flag, prot, sect, l_sect;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
prot = 0;
while ((addr[0] & 0x80808080) != 0x80808080) {
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
- return;
+ return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
addr[0] = 0xF0F0F0F0; /* reset bank */
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
/*
* Erase a range of flash sectors.
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
vu_long *addr = (vu_long*)(info->start[0]);
int prot, sect, l_sect;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
prot = 0;
if(ERROR == flashEraseSector(dev, sect)){
printf("ERROR: could not erase sector %d on FLASH[%s]\n",
sect, dev->name);
- return;
+ return 1;
}
}
}
}
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
ulong flash_get_size (vu_long *addr, flash_info_t *info);
void flash_print_info (flash_info_t *info);
-void flash_erase (flash_info_t *info, int s_first, int s_last);
-int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt);
+int flash_erase (flash_info_t *info, int s_first, int s_last);
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt);
/*
* Flash info indices.
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
vu_long *addr;
int flag, prot, sect;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
if ( ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL)
&& ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_SHARP) ) {
printf ("Can't erase unknown flash type %08lx - aborted\n",
info->flash_id);
- return;
+ return 1;
}
prot = 0;
if ((now=get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
*addr = 0xFFFFFFFF; /* reset bank */
- return;
+ return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
*addr = 0xFFFFFFFF; /* reset bank */
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
);
}
printf ("\n");
+ return;
}
/*-----------------------------------------------------------------------
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
int flag, prot, sect;
ulong type, start, now, last;
+ int rcode = 0;
if ((s_first < 0) || (s_first > s_last)) {
if (info->flash_id == FLASH_UNKNOWN) {
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
type = (info->flash_id & FLASH_VENDMASK);
if ((type != FLASH_MAN_INTEL)) {
printf ("Can't erase unknown flash type %08lx - aborted\n",
info->flash_id);
- return;
+ return 1;
}
prot = 0;
printf ("Timeout\n");
*addr = (FPW)0x00B000B0; /* suspend erase */
*addr = (FPW)0x00FF00FF; /* reset to read mode */
+ rcode = 1;
break;
}
printf (" done\n");
}
}
+ return rcode;
}
/*-----------------------------------------------------------------------
/* ------------------------------------------------------------------------- */
-void do_pip405(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_pip405(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
ulong size,src,device,function,load_addr;
if (strcmp(argv[2], "floppy") == 0) {
char *local_args[3];
- extern void do_fdcboot (cmd_tbl_t *, bd_t *, int, int, char *[]);
+ extern int do_fdcboot (cmd_tbl_t *, bd_t *, int, int, char *[]);
printf ("\nupdating bootloader image from floppy\n");
local_args[0] = argv[0];
if(argc==4) {
do_fdcboot(cmdtp, bd, 0, 1, local_args);
}
pip405_prg_image(load_addr);
- return;
+ return 0;
}
if (strcmp(argv[2], "mem") == 0) {
if(argc==4) {
}
printf ("\nupdating bootloader image from memory at %lX\n",load_addr);
pip405_prg_image(load_addr);
- return;
+ return 0;
}
if (strcmp(argv[2], "mps") == 0) {
printf ("\nupdating bootloader image from MSP\n");
pip405_prg(src,size);
- return;
+ return 0;
}
}
if (strcmp(argv[1], "prg") == 0)
printf("image size is 0x%lx\n",size);
}
pip405_prg(src,size);
- return;
+ return 0;
}
if (strcmp(argv[1], "info") == 0)
{
printf("argc %d\n",argc);
print_pip405_info();
- return;
+ return 0;
}
if (strcmp(argv[1], "i2c") == 0)
{
i2c[1]=0;
i2c[2]=0;
i2c_read(&i2c[0],3,(unsigned char *)CFG_LOAD_ADDR,512);
- return;
+ return 0;
}
if (strcmp(argv[1], "led") == 0)
{
user_led0((function==1));
else
user_led1((function==1));
- return;
+ return 0;
}
printf("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
/* ------------------------------------------------------------------------- */
);
}
printf ("\n");
+ return;
}
/*-----------------------------------------------------------------------
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]);
volatile FLASH_WORD_SIZE *addr2;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
if (info->flash_id == FLASH_UNKNOWN) {
printf ("Can't erase unknown flash type - aborted\n");
- return;
+ return 1;
}
prot = 0;
addr[0] = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */
printf (" done\n");
+ return 0;
}
void unlock_intel_sectors(flash_info_t *info,ulong addr,ulong cnt)
#if (CONFIG_COMMANDS & CFG_CMD_PCI)
-void
+int
do_pciinfo(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
int bus_no = 0;
}
pciinfo(bus_no);
+ return 0;
}
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
int flag, prot, sect;
ulong start, now, last;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
prot = 0;
addr[0] = 0x00FF00FF;
addr[1] = 0x00FF00FF;
- return;
+ return 0;
}
static int write_word (flash_info_t *, volatile unsigned long *, ulong);
);
}
printf ("\n");
+ return;
}
/*
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
vu_long *addr = (vu_long*)(info->start[0]);
int flag, prot, sect, l_sect;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
prot = 0;
(addr[1] & 0x80808080) != 0x80808080) {
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
- return;
+ return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
addr[1] = 0xF0F0F0F0; /* reset bank */
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
);
}
printf ("\n");
+ return;
}
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
int flag, prot, sect, l_sect;
ulong start;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
prot = 0;
f_command = 0x00F000F000F000F0ULL;
ull_write(f_addr, &f_command);
printf (" timeout\n");
- return;
+ return 1;
}
} while(*f_addr != 0xFFFFFFFFFFFFFFFFULL);
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
* MA 02111-1307 USA
*/
-#define __ASSEMBLY__
+#ifndef __ASSEMBLY__
+#define __ASSEMBLY__ 1
+#endif
#include <config.h>
#include <asm/processor.h>
}
puts("\n");
+ return;
}
#if 0
#endif
-void
+int
flash_erase(flash_info_t *info, int s_first, int s_last)
{
volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]);
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
if ((info->flash_id == FLASH_UNKNOWN) ||
(info->flash_id > FLASH_AMD_COMP)) {
printf ("Can't erase unknown flash type - aborted\n");
- return;
+ return 1;
}
prot = 0;
while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) {
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
- return;
+ return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
addr[0] = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
);
}
printf ("\n");
+ return;
}
/*
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
vu_long *addr = (vu_long*)(info->start[0]);
int flag, prot, sect, l_sect;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
prot = 0;
while ((addr[0] & 0x80808080) != 0x80808080) {
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
- return;
+ return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
addr[0] = 0xF0F0F0F0; /* reset bank */
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
#if (CONFIG_COMMANDS & CFG_CMD_BSP)
-void do_puma (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_puma (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
ulong addr, len;
case 2: /* PUMA reset */
if (strncmp(argv[1], "stat", 4) == 0) { /* Reset */
puma_status ();
- return;
+ return 0;
}
break;
case 4: /* PUMA load addr len */
addr, len, len);
puma_load (addr, len);
- return;
+ return 0;
default:
break;
}
printf ("Usage:\n%s\n", cmdtp->usage);
+ return 1;
}
#endif /* CFG_CMD_BSP */
);
}
printf ("\n");
+ return;
}
/*-----------------------------------------------------------------------
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
vu_long *addr = (vu_long*)(info->start[0]);
int flag, prot, sect, l_sect;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
if ((info->flash_id == FLASH_UNKNOWN) ||
(info->flash_id > FLASH_AMD_COMP)) {
printf ("Can't erase unknown flash type %08lx - aborted\n",
info->flash_id);
- return;
+ return 1;
}
prot = 0;
while ((addr[0] & 0x00800080) != 0x00800080) {
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
- return;
+ return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
addr[0] = 0x00F000F0; /* reset bank */
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
);
}
printf ("\n");
+ return;
}
/*-----------------------------------------------------------------------
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
vu_short *addr = (vu_short*)(info->start[0]);
int flag, prot, sect, l_sect;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
if ((info->flash_id == FLASH_UNKNOWN) ||
(info->flash_id > FLASH_AMD_COMP)) {
printf ("Can't erase unknown flash type %08lx - aborted\n",
info->flash_id);
- return;
+ return 1;
}
prot = 0;
while ((addr[0] & 0x0080) != 0x0080) {
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
- return;
+ return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
addr[0] = 0x00F0; /* reset bank */
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
#define PUMA_READ_MODE 0
#define PUMA_LOAD_MODE 1
-void do_puma (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_puma (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
ulong addr, len;
case 2: /* PUMA reset */
if (strncmp(argv[1], "stat", 4) == 0) { /* Reset */
puma_status ();
- return;
+ return 0;
}
break;
case 4: /* PUMA load addr len */
addr, len, len);
puma_load (addr, len);
- return;
+ return 0;
default:
break;
}
printf ("Usage:\n%s\n", cmdtp->usage);
+ return 1;
}
#endif /* CFG_CMD_BSP */
}
printf ("\n");
+ return;
}
/*-----------------------------------------------------------------------
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
vu_long *addr = (vu_long*)(info->start[0]);
int flag, prot, sect, l_sect;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
if ((info->flash_id == FLASH_UNKNOWN) ||
(info->flash_id > FLASH_AMD_COMP)) {
printf ("Can't erase unknown flash type - aborted\n");
- return;
+ return 1;
}
prot = 0;
while ((addr[0] & 0xFFFFFFFF) != 0xFFFFFFFF) {
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
- return;
+ return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
addr[0] = 0xF0F0F0F0; /* reset bank */
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
return;
}
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
- return;
+ return 1;
}
/*-----------------------------------------------------------------------
);
}
printf ("\n");
+ return;
}
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
int flag, prot, sect, l_sect;
ulong start, now, last;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
prot = 0;
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT)
{
printf ("Timeout\n");
- return;
+ return 1;
}
/* show that we're waiting */
if ((now - last) > 1000)
flash_reset ();
printf (" done\n");
+ return 0;
}
static int write_dword (flash_info_t *, ulong, unsigned char *);
);
}
printf ("\n");
+ return;
}
/*-----------------------------------------------------------------------
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
vu_long *addr = (vu_long*)(info->start[0]);
int flag, prot, sect, l_sect;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
if ((info->flash_id == FLASH_UNKNOWN) ||
(info->flash_id > FLASH_AMD_COMP)) {
printf ("Can't erase unknown flash type %08lx - aborted\n",
info->flash_id);
- return;
+ return 1;
}
prot = 0;
while ((addr[0] & 0x00800080) != 0x00800080) {
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
- return;
+ return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
addr[0] = 0x00F000F0; /* reset bank */
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
);
}
printf ("\n");
+ return;
}
/*-----------------------------------------------------------------------
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]);
volatile FLASH_WORD_SIZE *addr2;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
if (info->flash_id == FLASH_UNKNOWN) {
printf ("Can't erase unknown flash type - aborted\n");
- return;
+ return 1;
}
prot = 0;
addr[0] = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
/*-----------------------------------------------------------------------
*/
-void flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
{
vu_long *addr = (vu_long*)(info->start[0]);
int flag, prot, sect, l_sect;
} else {
printf ("- no sectors to erase\n");
}
- return;
+ return 1;
}
if ((info->flash_id == FLASH_UNKNOWN) ||
(info->flash_id > FLASH_AMD_COMP)) {
printf ("Can't erase unknown flash type %08lx - aborted\n",
info->flash_id);
- return;
+ return 1;
}
prot = 0;
start = get_timer (0);
last = start;
addr = (vu_long*)(info->start[l_sect]);
-// while ((addr[0] & 0xFFFFFFFF) != 0xFFFFFFFF) {
while ((addr[0] & 0x00800080) != 0x00800080) {
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
- return;
+ return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
addr[0] = 0x00F000F0; /* reset bank */
printf (" done\n");
+ return 0;
}
/*-----------------------------------------------------------------------
cmd_fdc.o cmd_scsi.o cmd_autoscript.o \
cmd_bedbug.o bedbug.o s_record.o dlmalloc.o \
kgdb.o console.o lists.o devices.o flash.o cmd_i2c.o \
- cmd_immap.o miiphyutil.o miiphybb.o cmd_mii.o
+ cmd_immap.o miiphyutil.o miiphybb.o cmd_mii.o \
+ hush.o
OBJS = $(AOBJS) $(COBJS)
printf ("Command \"%s\": 0x%08lx => 0x%08lx\n",
cmdtp->name, (ulong)(cmdtp->cmd), addr);
#endif
- cmdtp->cmd = (void (*)(struct cmd_tbl_s*,bd_t*,int,int,char*[]))addr;
+ cmdtp->cmd = (int (*)(struct cmd_tbl_s*,bd_t*,int,int,char*[]))addr;
addr = (ulong)(cmdtp->name) + reloc_off;
cmdtp->name = (char *)addr;
(CONFIG_COMMANDS & CFG_CMD_AUTOSCRIPT)
extern image_header_t header; /* from cmd_bootm.c */
-
-void
+int
autoscript(bd_t *bd, ulong addr)
{
ulong crc, data, len;
image_header_t *hdr = &header;
ulong *len_ptr;
char *cmd;
+ int rcode = 0;
memcpy (hdr, (char *)addr, sizeof(image_header_t));
if (hdr->ih_magic != IH_MAGIC)
{
printf("Bad magic number\n");
- return;
+ return 1;
}
crc = hdr->ih_hcrc;
if (crc32(0, (char *)data, len) != crc)
{
printf("Bad header crc\n");
- return;
+ return 1;
}
data = addr + sizeof(image_header_t);
if (crc32(0, (char *)data, len) != hdr->ih_dcrc)
{
printf("Bad data crc\n");
- return;
+ return 1;
}
if (hdr->ih_type != IH_TYPE_SCRIPT)
{
printf("Bad image type\n");
- return;
+ return 1;
}
/* get len of script and make sure cmd is null terminated */
cmd = malloc (len + 1);
if (!cmd)
{
- return;
+ return 1;
}
while (*len_ptr++);
memcpy(cmd,(char *)len_ptr,len);
}
}
}
- run_command(cmd, bd, 0);
+ rcode = run_command(cmd, bd, 0);
free(cmd);
+ return rcode;
}
#endif
#if (CONFIG_COMMANDS & CFG_CMD_AUTOSCRIPT)
-
-void
+int
do_autoscript (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
ulong addr;
+ int rcode;
if (argc < 2)
{
}
printf("## Executing script at %08lx\n",addr);
-
- autoscript(bd,addr);
-
+ rcode = autoscript(bd,addr);
+ return rcode;
}
#endif
* Entry point from the interpreter to the disassembler. Repeated calls
* will resume from the last disassembled address.
* ====================================================================== */
-
-void do_bedbug_dis (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
+int do_bedbug_dis (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
char *argv[])
{
ulong addr; /* Address to start disassembly from */
if (argc < 2)
{
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
if(( flag & CMD_FLAG_REPEAT ) == 0 )
dis_last_addr = addr + (len * 4);
dis_last_len = len;
+ return 0;
} /* do_bedbug_dis */
* instructions in consecutive memory locations until a '.' (period) is
* entered on a line by itself.
* ====================================================================== */
-
-void do_bedbug_asm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
+int do_bedbug_asm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
char *argv[])
{
long mem_addr; /* Address to assemble into */
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;
+ return 1;
}
printf( "\nEnter '.' when done\n" );
else
{
printf( "*** Error: %s ***\n", asm_error_str( asm_err ));
+ rcode = 1;
}
}
else
break;
}
}
+ return rcode;
} /* do_bedbug_asm */
* CPU-specific break point set routine.
* ====================================================================== */
-void do_bedbug_break (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
+int do_bedbug_break (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
char *argv[])
{
/* -------------------------------------------------- */
-
if( bug_ctx.do_break )
(*bug_ctx.do_break)( cmdtp, bd, flag, argc, argv );
+ return 0;
+
} /* do_bedbug_break */
if( bug_ctx.break_isr )
(*bug_ctx.break_isr)( regs );
+
+ return;
} /* do_bedbug_breakpoint */
* stopped flag in the context so that the breakpoint routine will
* return.
* ====================================================================== */
-
-void do_bedbug_continue (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
+int do_bedbug_continue (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
char *argv[])
+
{
/* -------------------------------------------------- */
if( ! bug_ctx.stopped )
{
printf( "Not at a breakpoint\n" );
- return;
+ return 1;
}
bug_ctx.stopped = 0;
- return;
+ return 0;
} /* do_bedbug_continue */
* the address passes control to the CPU-specific set breakpoint routine
* for the current breakpoint number.
* ====================================================================== */
-
-void do_bedbug_step (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
+int do_bedbug_step (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
char *argv[])
{
unsigned long addr; /* Address to stop at */
if( ! bug_ctx.stopped )
{
printf( "Not at a breakpoint\n" );
- return;
+ return 1;
}
if( !find_next_address( (unsigned char *)&addr, FALSE, bug_ctx.regs ))
- return;
+ return 1;
if( bug_ctx.set )
(*bug_ctx.set)( bug_ctx.current_bp, addr );
bug_ctx.stopped = 0;
- return;
+ return 0;
} /* do_bedbug_step */
* the address passes control to the CPU-specific set breakpoint routine
* for the current breakpoint number.
* ====================================================================== */
-
-void do_bedbug_next (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
+int do_bedbug_next (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
char *argv[])
{
unsigned long addr; /* Address to stop at */
if( ! bug_ctx.stopped )
{
printf( "Not at a breakpoint\n" );
- return;
+ return 1;
}
if( !find_next_address( (unsigned char *)&addr, TRUE, bug_ctx.regs ))
- return;
+ return 1;
if( bug_ctx.set )
(*bug_ctx.set)( bug_ctx.current_bp, addr );
bug_ctx.stopped = 0;
- return;
+ 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.
* ====================================================================== */
-
-void do_bedbug_stack (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
+int do_bedbug_stack (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
char *argv[])
{
unsigned long sp; /* Stack pointer */
if( ! bug_ctx.stopped )
{
printf( "Not at a breakpoint\n" );
- return;
+ return 1;
}
top = bd->bi_memstart + bd->bi_memsize;
sp = *(unsigned long *)sp;
func = *(unsigned long *)(sp+4);
}
-
- return;
+ return 0;
} /* do_bedbug_stack */
* Interpreter command to dump the registers. Calls the CPU-specific
* show registers routine.
* ====================================================================== */
-
-void do_bedbug_rdump (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
+int do_bedbug_rdump (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
char *argv[])
{
/* -------------------------------------------------- */
if( ! bug_ctx.stopped )
{
printf( "Not at a breakpoint\n" );
- return;
+ return 1;
}
show_regs( bug_ctx.regs );
- return;
+ return 0;
} /* do_bedbug_rdump */
/* ======================================================================
* Interpreter command to boot an arbitrary ELF image from memory.
* ====================================================================== */
-
-void do_bootelf( cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[] )
+int do_bootelf( cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[] )
{
unsigned long addr; /* Address of the ELF image */
unsigned long rc; /* Return value from user code */
/* -------------------------------------------------- */
+ int rcode = 0;
if (argc < 2)
addr = load_addr;
addr = simple_strtoul( argv[ 1 ], NULL, 16 );
if( ! valid_elf_image( addr ))
- return;
+ return 1;
addr = load_elf_image( addr );
* and all remaining args
*/
rc = ((ulong (*)(bd_t *, int, char *[]))addr) (bd, --argc, &argv[1]);
+ if (rc != 0) rcode = 1;
printf ("## Application terminated, rc = 0x%lx\n", rc);
+ return rcode;
} /* do_bootelf */
* be either an ELF image or a raw binary. Will attempt to setup the
* bootline and other parameters correctly.
* ====================================================================== */
-
-void do_bootvx( cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[] )
+int do_bootvx( cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[] )
{
unsigned long addr; /* Address of image */
unsigned long bootaddr; /* Address to put the bootline */
else
{
printf( "No load address provided\n" );
- return;
+ return 1;
}
/* Check to see if we need to tftp the image ourselves before starting */
if(( argc == 2 ) && ( strcmp( argv[ 1 ], "tftp" ) == 0 ))
{
if( NetLoop( bd, TFTP ) == 0 )
- return;
-
+ return 1;
printf( "Automatic boot of VxWorks image at address 0x%08lx ... \n",
addr );
}
PPC flavors, the hostname and ipaddr should be ok to just copy */
printf( "No bootargs defined\n" );
- return;
+ return 1;
#endif
}
((void (*)(void))addr)();
printf ("## vxWorks terminated\n" );
+ return 1;
} /* do_bootvx */
#if (CONFIG_COMMANDS & CFG_CMD_BDI)
static void print_num(const char *, ulong);
static void print_str(const char *, const char *);
-
-void do_bdinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_bdinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
int i;
char buf[32];
print_num ("free_hdlr", (ulong)bd->bi_mon_fnc->free_hdlr);
print_num ("malloc", (ulong)bd->bi_mon_fnc->malloc);
print_num ("free", (ulong)bd->bi_mon_fnc->free);
+ return 0;
}
static void print_num(const char *name, ulong value)
}
#endif /* CFG_CMD_BDI */
-void do_go (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_go (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
ulong addr, rc;
+ int rcode = 0;
if (argc < 2) {
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
addr = simple_strtoul(argv[1], NULL, 16);
* and all remaining args
*/
rc = ((ulong (*)(bd_t *, int, char *[]))addr) (bd, --argc, &argv[1]);
+ if (rc != 0) rcode = 1;
printf ("## Application terminated, rc = 0x%lx\n", rc);
+ return rcode;
}
#if (CONFIG_COMMANDS & CFG_CMD_LOADS)
-void do_load_serial (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_load_serial (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
ulong offset = 0;
ulong addr;
#ifdef CFG_LOADS_BAUD_CHANGE
int loads_baudrate = bd->bi_baudrate;
#endif
+ int rcode = 0;
if (((env_echo = getenv("loads_echo")) != NULL) && (*env_echo == '1')) {
do_echo = 1;
if (addr == ~0) {
printf ("## S-Record download aborted\n");
+ rcode = 1;
} else {
printf ("## Start Addr = 0x%08lx\n", addr);
load_addr = addr;
}
}
#endif
+ return rcode;
}
static ulong
char his_pad_char; /* pad chars he needs */
char his_quote; /* quote chars he'll use */
-
-void do_load_serial_bin (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_load_serial_bin (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
ulong offset = 0;
ulong addr;
int i;
int loadb_baudrate = bd->bi_baudrate;
+ int rcode = 0;
if (argc >= 2) {
offset = simple_strtoul(argv[1], NULL, 16);
if (addr == ~0) {
load_addr = 0;
printf ("## Binary (kermit) download aborted\n");
+ rcode = 1;
} else {
printf ("## Start Addr = 0x%08lx\n", addr);
load_addr = addr;
if (((s = getenv("autoscript")) != NULL) && (strcmp(s,"yes") == 0)) {
printf("Running autoscript at addr 0x%08lX ...\n", load_addr);
- autoscript (bd, load_addr);
+ rcode = autoscript (bd, load_addr);
}
}
#endif
+ return rcode;
}
static void zfree(void *, void *, unsigned);
#if (CONFIG_COMMANDS & CFG_CMD_IMI)
-static void image_info (unsigned long addr);
+static int image_info (unsigned long addr);
#endif
static void print_type (image_header_t *hdr);
image_header_t header;
ulong load_addr = CFG_LOAD_ADDR; /* Default Load Address */
-
-void do_bootm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_bootm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
ulong iflag;
ulong addr;
if (hdr->ih_magic != IH_MAGIC) {
printf ("Bad Magic Number\n");
- return;
+ return 1;
}
#ifdef CONFIG_HERMES
hermes_set_led (2);
if (crc32 (0, (char *)data, len) != checksum) {
printf ("Bad Header Checksum\n");
- return;
+ return 1;
}
#ifdef CONFIG_HERMES
hermes_set_led (3);
printf (" Verifying Checksum ... ");
if (crc32 (0, (char *)data, len) != hdr->ih_dcrc) {
printf ("Bad Data CRC\n");
- return;
+ return 1;
}
printf ("OK\n");
}
if (hdr->ih_arch != IH_CPU_PPC) {
printf ("Unsupported Architecture\n");
- return;
+ return 1;
}
#ifdef CONFIG_HERMES
hermes_set_led (5);
data += 4;
break;
default: printf ("Wrong Image Type for %s command\n", cmdtp->name);
- return;
+ return 1;
}
#ifdef CONFIG_HERMES
hermes_set_led (6);
if (iflag)
enable_interrupts();
printf ("Unimplemented compression type %d\n", hdr->ih_comp);
- return;
+ return 1;
}
printf ("OK\n");
#ifdef CONFIG_HERMES
if (iflag)
enable_interrupts();
printf ("Can't boot image type %d\n", hdr->ih_type);
- return;
+ return 1;
}
#ifdef CONFIG_HERMES
hermes_set_led (8);
printf ("\n## Control returned to monitor - resetting...\n");
do_reset (cmdtp, bd, flag, argc, argv);
#endif
+ return 1;
}
static void
}
#if (CONFIG_COMMANDS & CFG_CMD_BOOTD)
-void do_bootd (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
-{
- run_command (getenv ("bootcmd"), bd, flag);
+int do_bootd (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+{
+ int rcode = 0;
+
+ if (run_command (getenv ("bootcmd"), bd, flag) == -1) rcode = 1;
+ return rcode;
}
#endif
-
#if (CONFIG_COMMANDS & CFG_CMD_IMI)
-void do_iminfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_iminfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
int arg;
ulong addr;
+ int rcode=0;
if (argc < 2) {
- image_info (load_addr);
- return;
+ return image_info (load_addr);
}
for (arg=1; arg <argc; ++arg) {
addr = simple_strtoul(argv[arg], NULL, 16);
- image_info (addr);
+ if (image_info (addr) != 0) rcode = 1;
}
+ return rcode;
}
-static void image_info (ulong addr)
+static int image_info (ulong addr)
{
ulong data, len, checksum;
image_header_t *hdr = &header;
if (hdr->ih_magic != IH_MAGIC) {
printf (" Bad Magic Number\n");
- return;
+ return 1;
}
data = (ulong)&header;
if (crc32 (0, (char *)data, len) != checksum) {
printf (" Bad Header Checksum\n");
- return;
+ return 1;
}
/* for multi-file images we need the data part, too */
printf (" Verifying Checksum ... ");
if (crc32 (0, (char *)data, len) != hdr->ih_dcrc) {
printf (" Bad Data CRC\n");
- return;
+ return 1;
}
printf ("OK\n");
+ return 0;
}
#endif /* CFG_CMD_IMI */
static int on_off (const char *);
-void do_icache (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_icache (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
switch (argc) {
case 2: /* on / off */
case 1: /* get status */
printf ("Instruction Cache is %s\n",
icache_status() ? "ON" : "OFF");
- return;
+ return 0;
default:
printf ("Usage:\n%s\n", cmdtp->usage);
+ return 1;
}
+ return 0;
}
-void do_dcache (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_dcache (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
switch (argc) {
case 2: /* on / off */
case 1: /* get status */
printf ("Data (writethrough) Cache is %s\n",
dcache_status() ? "ON" : "OFF");
- return;
+ return 0;
default:
printf ("Usage:\n%s\n", cmdtp->usage);
+ return 1;
}
+ return 0;
+
}
static int on_off (const char *s)
#if (CONFIG_COMMANDS & CFG_CMD_CONSOLE)
extern void _do_coninfo (void) ;
-
-void do_coninfo (cmd_tbl_t *cmd, bd_t *bd, int flag, int argc, char *argv[])
+int do_coninfo (cmd_tbl_t *cmd, bd_t *bd, int flag, int argc, char *argv[])
{
int i,l ;
putc('\n');
}
+ return 0;
}
#endif /* CFG_CMD_CONSOLE */
int mk_date (char *, struct rtc_time *);
-void do_date (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_date (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
struct rtc_time tm;
+ int rcode = 0;
switch (argc) {
case 2: /* set date & time */
/* insert new date & time */
if (mk_date (argv[1], &tm) != 0) {
printf ("## Bad date format\n");
- return;
+ return 1;
}
/* and write to RTC */
rtc_set (&tm);
"unknown " : weekdays[tm.tm_wday],
tm.tm_hour, tm.tm_min, tm.tm_sec);
- return;
+ return 0;
default:
printf ("Usage:\n%s\n", cmdtp->usage);
+ rcode = 1;
}
+ return rcode;
}
/*
#if (CONFIG_COMMANDS & CFG_CMD_EEPROM) || defined(CFG_ENV_IS_IN_EEPROM)
extern void eeprom_init (void);
-extern void eeprom_read (unsigned offset, uchar *buffer, unsigned cnt);
-extern void eeprom_write (unsigned offset, uchar *buffer, unsigned cnt);
+extern int eeprom_read (unsigned offset, uchar *buffer, unsigned cnt);
+extern int eeprom_write (unsigned offset, uchar *buffer, unsigned cnt);
#endif
/* ------------------------------------------------------------------------- */
#if (CONFIG_COMMANDS & CFG_CMD_EEPROM)
-
-void do_eeprom (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_eeprom (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
+ int rcode = 0;
+
switch (argc) {
default:
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
case 5:
/* 4 args */
#ifndef CONFIG_SPI
eeprom_init ();
#endif
- eeprom_read (off, (uchar *)addr, cnt);
+ rcode = eeprom_read (off, (uchar *)addr, cnt);
printf ("done\n");
- return;
+ return rcode;
} else if (strcmp(argv[1],"write") == 0) {
ulong addr = simple_strtoul(argv[2], NULL, 16);
#ifndef CONFIG_SPI
eeprom_init ();
#endif
- eeprom_write(off, (uchar *)addr, cnt);
+ rcode = eeprom_write(off, (uchar *)addr, cnt);
printf ("done\n");
- return;
+ return rcode;
} else {
printf ("Usage:\n%s\n", cmdtp->usage);
}
-
- return;
+ return 1;
}
}
#endif /* CFG_CMD_EEPROM */
#if (CONFIG_COMMANDS & CFG_CMD_EEPROM) || defined(CFG_ENV_IS_IN_EEPROM)
-void eeprom_read (unsigned offset, uchar *buffer, unsigned cnt)
+int eeprom_read (unsigned offset, uchar *buffer, unsigned cnt)
{
unsigned end = offset + cnt;
unsigned blk_off;
+ int rcode = 0;
/* Read data until done or would cross a page boundary.
* We must write the address again when changing pages
len = end - offset;
if (len > maxlen)
len = maxlen;
-
#ifdef CONFIG_SPI
spi_read (addr, alen, buffer, len);
#else
- i2c_read (addr, alen, buffer, len);
+ if (i2c_read (addr, alen, buffer, len) != 0) rcode = 1;
#endif
buffer += len;
offset += len;
}
+ return rcode;
}
/*-----------------------------------------------------------------------
* 0x00000nxx for EEPROM address selectors and page number at n.
*/
-void eeprom_write (unsigned offset, uchar *buffer, unsigned cnt)
+int eeprom_write (unsigned offset, uchar *buffer, unsigned cnt)
{
unsigned end = offset + cnt;
unsigned blk_off;
+ int rcode = 0;
+
/* Write data until done or would cross a write page boundary.
* We must write the address again when changing pages
len = end - offset;
if (len > maxlen)
len = maxlen;
-
#ifdef CONFIG_SPI
spi_write (addr, alen, buffer, len);
#else
- i2c_write (addr, alen, buffer, len);
+ if (i2c_write (addr, alen, buffer, len) != 0) rcode = 1;
#endif
buffer += len;
offset += len;
udelay(CFG_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
#endif
}
+ return rcode;
}
/*-----------------------------------------------------------------------
/****************************************************************************
* main routine do_fdcboot
*/
-
-void do_fdcboot(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_fdcboot(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
FD_GEO_STRUCT *pFG = (FD_GEO_STRUCT *)floppy_type;
FDC_COMMAND_STRUCT *pCMD = &cmd;
unsigned char boot_drive;
int i,nrofblk;
char *ep;
+ int rcode = 0;
switch (argc) {
case 1:
break;
default:
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
/* setup FDC and scan for drives */
if(fdc_setup(pCMD,pFG)==FALSE) {
printf("\n** Error in setup FDC **\n");
- return;
+ return 1;
}
if(fdc_check_drive(pCMD,pFG)==FALSE) {
printf("\n** Error in check_drives **\n");
- return;
+ return 1;
}
if((pCMD->flags&(1<<boot_drive))==0) {
/* drive not available */
printf("\n** Drive %d not availabe **\n",boot_drive);
- return;
+ return 1;
}
if((pCMD->flags&(0x10<<boot_drive))==0) {
/* no disk inserted */
printf("\n** No disk inserted in drive %d **\n",boot_drive);
- return;
+ return 1;
}
/* ok, we have a valid source */
pCMD->drive=boot_drive;
printf("\nRead error:");
for(i=0;i<7;i++)
printf("result%d: 0x%02X\n",i,pCMD->result[i]);
- return;
+ return 1;
}
hdr = (image_header_t *)addr;
if (hdr->ih_magic != IH_MAGIC) {
printf ("Bad Magic Number\n");
- return;
+ return 1;
}
print_image_hdr(hdr);
printf("\nRead error:");
for(i=0;i<7;i++)
printf("result%d: 0x%02X\n",i,pCMD->result[i]);
- return;
+ return 1;
}
printf("OK %ld Bytes loaded.\n",imsize);
/* Loading ok, update default load address */
/* Check if we should attempt an auto-start */
if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) {
char *local_args[2];
- extern void do_bootm (cmd_tbl_t *, bd_t *, int, int, char *[]);
+ extern int do_bootm (cmd_tbl_t *, bd_t *, int, int, char *[]);
local_args[0] = argv[0];
local_args[1] = NULL;
printf ("Automatic boot of image at addr 0x%08lX ...\n", addr);
do_bootm (cmdtp, bd, 0, 1, local_args);
+ rcode ++;
}
}
+ return rcode;
}
return 1;
}
-
-void do_flinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_flinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
ulong bank;
flash_print_info (&flash_info[bank]);
}
- return;
+ return 0;
}
bank = simple_strtoul(argv[1], NULL, 16);
if ((bank < 1) || (bank > CFG_MAX_FLASH_BANKS)) {
printf ("Only FLASH Banks # 1 ... # %d supported\n",
CFG_MAX_FLASH_BANKS);
- return;
+ return 1;
}
printf ("\nBank # %ld: ", bank);
flash_print_info (&flash_info[bank-1]);
+ return 0;
}
-
-void do_flerase(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_flerase(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
flash_info_t *info;
ulong bank, addr_first, addr_last;
int n, sect_first, sect_last;
+ int rcode = 0;
if (argc < 2) {
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
if (strcmp(argv[1], "all") == 0) {
for (bank=1; bank<=CFG_MAX_FLASH_BANKS; ++bank) {
printf ("Erase Flash Bank # %ld ", bank);
info = &flash_info[bank-1];
- flash_erase (info, 0, info->sector_count-1);
+ rcode = flash_erase (info, 0, info->sector_count-1);
}
- return;
+ return rcode;
}
if ((n = abbrev_spec(argv[1], &info, §_first, §_last)) != 0) {
if (n < 0) {
printf("Bad sector specification\n");
- return;
+ return 1;
}
printf ("Erase Flash Sectors %d-%d in Bank # %d ",
sect_first, sect_last, (info-flash_info)+1);
- flash_erase(info, sect_first, sect_last);
- return;
+ rcode = flash_erase(info, sect_first, sect_last);
+ return rcode;
}
if (argc != 3) {
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
if (strcmp(argv[1], "bank") == 0) {
if ((bank < 1) || (bank > CFG_MAX_FLASH_BANKS)) {
printf ("Only FLASH Banks # 1 ... # %d supported\n",
CFG_MAX_FLASH_BANKS);
- return;
+ return 1;
}
printf ("Erase Flash Bank # %ld ", bank);
info = &flash_info[bank-1];
- flash_erase (info, 0, info->sector_count-1);
- return;
+ rcode = flash_erase (info, 0, info->sector_count-1);
+ return rcode;
}
addr_first = simple_strtoul(argv[1], NULL, 16);
if (addr_first >= addr_last) {
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
printf ("Erase Flash from 0x%08lx to 0x%08lx ", addr_first, addr_last);
- flash_sect_erase(addr_first, addr_last);
+ rcode = flash_sect_erase(addr_first, addr_last);
+ return rcode;
}
-void flash_sect_erase (ulong addr_first, ulong addr_last)
+int flash_sect_erase (ulong addr_first, ulong addr_last)
{
flash_info_t *info;
ulong bank;
int s_first, s_last;
int erased;
+ int rcode = 0;
erased = 0;
}
if (s_first>=0 && s_first<=s_last) {
erased += s_last - s_first + 1;
- flash_erase (info, s_first, s_last);
+ rcode = flash_erase (info, s_first, s_last);
}
}
if (erased) {
} else {
printf ("Error: start and/or end address"
" not on sector boundary\n");
+ rcode = 1;
}
+ return rcode;
}
-void do_protect(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_protect(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
flash_info_t *info;
ulong bank, addr_first, addr_last;
int i, p, n, sect_first, sect_last;
+ int rcode = 0;
if (argc < 3) {
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
if (strcmp(argv[1], "off") == 0)
p = 1;
else {
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
if (strcmp(argv[2], "all") == 0) {
info->protect[i] = p;
}
}
- return;
+ return 0;
}
if ((n = abbrev_spec(argv[2], &info, §_first, §_last)) != 0) {
if (n < 0) {
printf("Bad sector specification\n");
- return;
+ return 1;
}
printf("%sProtect Flash Sectors %d-%d in Bank # %d\n",
p ? "" : "Un-", sect_first, sect_last,
for (i = sect_first; i <= sect_last; i++) {
info->protect[i] = p;
}
- return;
+ return 0;
}
if (argc != 4) {
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
if (strcmp(argv[2], "bank") == 0) {
if ((bank < 1) || (bank > CFG_MAX_FLASH_BANKS)) {
printf ("Only FLASH Banks # 1 ... # %d supported\n",
CFG_MAX_FLASH_BANKS);
- return;
+ return 1;
}
printf ("%sProtect Flash Bank # %ld\n",
p ? "" : "Un-", bank);
if (info->flash_id == FLASH_UNKNOWN) {
printf ("missing or unknown FLASH type\n");
- return;
+ return 1;
}
for (i=0; i<info->sector_count; ++i) {
info->protect[i] = p;
}
- return;
+ return 0;
}
addr_first = simple_strtoul(argv[2], NULL, 16);
if (addr_first >= addr_last) {
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
-
- flash_sect_protect (p, addr_first, addr_last);
+ rcode = flash_sect_protect (p, addr_first, addr_last);
+ return rcode;
}
-
-void flash_sect_protect (int p, ulong addr_first, ulong addr_last)
+int flash_sect_protect (int p, ulong addr_first, ulong addr_last)
{
flash_info_t *info;
ulong bank;
int s_first, s_last;
int protected, i;
+ int rcode = 0;
protected = 0;
} else {
printf ("Error: start and/or end address"
" not on sector boundary\n");
+ rcode = 1;
}
+ return rcode;
}
#endif /* CFG_CMD_FLASH */
/* ------------------------------------------------------------------------- */
-void
+int
do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
unsigned char i2c_addr, sec_addr, *data_addr;
i2c_init (50000, 0xfe); /* use all one's as slave address */
#endif
printf ("DONE\n");
- return;
+ return 0;
}
break;
i2c_init (speed, 0xfe); /* use all one's as slave address */
#endif
printf ("DONE\n");
- return;
+ return 0;
}
break;
if (rc) {
printf ("i2c_receive FAILED rc=%d\n", rc);
- return;
+ return 1;
}
#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
if (rc) {
printf ("i2c_doio FAILED rc=%d\n", rc);
- return;
+ return 1;
}
printf ("DONE\n");
- return;
+ return 0;
} else if (strncmp(argv[1], "send",4) == 0) {
i2c_addr = (unsigned char)simple_strtoul(argv[2], NULL, 16);
data_addr = (unsigned char *)simple_strtoul(argv[3], NULL, 16);
#endif
if (rc) {
printf ("i2c_receive FAILED rc=%d\n", rc);
- return;
+ return 1;
}
#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
if (rc) {
printf ("i2c_doio FAILED rc=%d\n", rc);
- return;
+ return 1;
}
printf ("DONE\n");
- return;
+ return 0;
}
break;
if (rc) {
printf ("i2c_receive FAILED rc=%d\n", rc);
- return;
+ return 1;
}
#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
if (rc) {
printf ("i2c_doio FAILED rc=%d\n", rc);
- return;
+ return 1;
}
printf ("DONE\n");
- return;
+ return 0;
}
else if (strncmp(argv[1], "snds",4) == 0) {
i2c_addr = (unsigned char)simple_strtoul(argv[2], NULL, 16);
if (rc) {
printf ("i2c_send FAILED rc=%d\n", rc);
- return;
+ return 1;
}
#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
if (rc) {
printf ("i2c_doio FAILED rc=%d\n", rc);
- return;
+ return 1;
}
printf ("DONE\n");
- return;
+ return 0;
}
break;
}
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
-void do_ide (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_ide (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
+ int rcode = 0;
+
switch (argc) {
case 0:
case 1:
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
case 2:
if (strncmp(argv[1],"res",3) == 0) {
puts ("\nReset IDE"
": ");
ide_init(bd);
- return;
+ return 0;
} else if (strncmp(argv[1],"inf",3) == 0) {
int i;
printf ("IDE device %d: ", i);
dev_print(&ide_dev_desc[i]);
}
- return;
+ return 0;
} else if (strncmp(argv[1],"dev",3) == 0) {
if ((curr_device < 0) || (curr_device >= CFG_IDE_MAXDEVICE)) {
puts ("\nno IDE devices available\n");
- return;
+ return 1;
}
printf ("\nIDE device %d: ", curr_device);
dev_print(&ide_dev_desc[curr_device]);
- return;
+ return 0;
} else if (strncmp(argv[1],"part",4) == 0) {
int dev, ok;
print_part(&ide_dev_desc[dev]);
}
}
- if (!ok)
+ if (!ok) {
puts ("\nno IDE devices available\n");
- return;
+ rcode ++;
+ }
+ return rcode;
}
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
case 3:
if (strncmp(argv[1],"dev",3) == 0) {
int dev = (int)simple_strtoul(argv[2], NULL, 10);
printf ("\nIDE device %d: ", dev);
if (dev >= CFG_IDE_MAXDEVICE) {
puts ("unknown device\n");
- return;
+ return 1;
}
dev_print(&ide_dev_desc[dev]);
/*ide_print (dev);*/
if (ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN) {
- return;
+ return 1;
}
curr_device = dev;
puts ("... is now current device\n");
- return;
+ return 0;
} else if (strncmp(argv[1],"part",4) == 0) {
int dev = (int)simple_strtoul(argv[2], NULL, 10);
print_part(&ide_dev_desc[dev]);
} else {
printf ("\nIDE device %d not available\n", dev);
+ rcode = 1;
}
- return;
+ return rcode;
#if 0
} else if (strncmp(argv[1],"pio",4) == 0) {
int mode = (int)simple_strtoul(argv[2], NULL, 10);
}
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
default:
/* at least 4 args */
printf ("%ld blocks read: %s\n",
n, (n==cnt) ? "OK" : "ERROR");
-
- return;
-
+ if (n==cnt) {
+ return 0;
+ } else {
+ return 1;
+ }
} else if (strcmp(argv[1],"write") == 0) {
ulong addr = simple_strtoul(argv[2], NULL, 16);
ulong blk = simple_strtoul(argv[3], NULL, 16);
printf ("%ld blocks written: %s\n",
n, (n==cnt) ? "OK" : "ERROR");
-
- return;
+ if (n==cnt) {
+ return 0;
+ } else {
+ return 1;
+ }
} else {
printf ("Usage:\n%s\n", cmdtp->usage);
+ rcode = 1;
}
- return;
+ return rcode;
}
}
-void do_diskboot (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_diskboot (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
char *boot_device = NULL;
char *ep;
ulong addr;
disk_partition_t info;
image_header_t *hdr;
+ int rcode = 0;
switch (argc) {
case 1:
break;
default:
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
if (!boot_device) {
puts ("\n** No boot device **\n");
- return;
+ return 1;
}
dev = simple_strtoul(boot_device, &ep, 16);
if (ide_dev_desc[dev].type==DEV_TYPE_UNKNOWN) {
printf ("\n** Device %d not available\n", dev);
- return;
+ return 1;
}
if (*ep) {
if (*ep != ':') {
puts ("\n** Invalid boot device, use `dev[:part]' **\n");
- return;
+ return 1;
}
part = simple_strtoul(++ep, NULL, 16);
}
if (get_partition_info (&ide_dev_desc[dev], part, &info)) {
- return;
+ return 1;
}
if (strncmp(info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0) {
printf ("\n** Invalid partition type \"%.32s\""
" (expect \"" BOOT_PART_TYPE "\")\n",
info.type);
- return;
+ return 1;
}
printf ("\nLoading from IDE device %d, partition %d: "
if (ide_dev_desc[dev].block_read (dev, info.start, 1, (ulong *)addr) != 1) {
printf ("** Read error on %d:%d\n", dev, part);
- return;
+ return 1;
}
hdr = (image_header_t *)addr;
cnt -= 1;
} else {
printf("\n** Bad Magic Number **\n");
- return;
+ return 1;
}
if (ide_dev_desc[dev].block_read (dev, info.start+1, cnt,
(ulong *)(addr+info.blksz)) != cnt) {
printf ("** Read error on %d:%d\n", dev, part);
- return;
+ return 1;
}
/* Check if we should attempt an auto-start */
if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) {
char *local_args[2];
- extern void do_bootm (cmd_tbl_t *, bd_t *, int, int, char *[]);
+ extern int do_bootm (cmd_tbl_t *, bd_t *, int, int, char *[]);
local_args[0] = argv[0];
local_args[1] = NULL;
printf ("Automatic boot of image at addr 0x%08lX ...\n", addr);
do_bootm (cmdtp, bd, 0, 1, local_args);
+ rcode = 1;
}
+ return rcode;
}
/* ------------------------------------------------------------------------- */
cmdtp->name);
}
-void
+int
do_siuinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
volatile immap_t *immap = (immap_t *)CFG_IMMR;
printf("PDTEA = %08x PDTEM = %02x\n", sc->sc_pdtea, sc->sc_pdtem);
printf("LDTEA = %08x LDTEM = %02x\n", sc->sc_ldtea, sc->sc_ldtem);
#endif
+ return 0;
}
-void
+int
do_memcinfo(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
volatile immap_t *immap = (immap_t *)CFG_IMMR;
memctl->memc_lurt, memctl->memc_lsrt);
printf("IMMR = %08x\n", memctl->memc_immr);
#endif
+ return 0;
}
-void
+int
do_sitinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
unimplemented(cmdtp, bd, flag, argc, argv);
+ return 0;
}
#ifdef CONFIG_8260
-void
+int
do_icinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
unimplemented(cmdtp, bd, flag, argc, argv);
+ return 0;
}
#endif
-void
+int
do_carinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
unimplemented(cmdtp, bd, flag, argc, argv);
+ return 0;
}
static int counter;
#define PD_NBITS 28
#endif
-void
+int
do_iopinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
volatile immap_t *immap = (immap_t *)CFG_IMMR;
#endif
header();
+ return 0;
}
-void
+int
do_dmainfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
unimplemented(cmdtp, bd, flag, argc, argv);
+ return 0;
}
-void
+int
do_fccinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
unimplemented(cmdtp, bd, flag, argc, argv);
+ return 0;
}
static void
putc('\n');
}
-void
+int
do_brginfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
volatile immap_t *immap = (immap_t *)CFG_IMMR;
while (i <= 8)
prbrg(i++, *p++);
#endif
+ return 0;
}
-void
+int
do_i2cinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
volatile immap_t *immap = (immap_t *)CFG_IMMR;
iip->iic_tbptr, iip->iic_tbc);
printf("TXTMP = %08x\n", iip->iic_txtmp);
}
+ return 0;
}
-void
+int
do_sccinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
unimplemented(cmdtp, bd, flag, argc, argv);
+ return 0;
}
-void
+int
do_smcinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
unimplemented(cmdtp, bd, flag, argc, argv);
+ return 0;
}
-void
+int
do_spiinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
unimplemented(cmdtp, bd, flag, argc, argv);
+ return 0;
}
-void
+int
do_muxinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
unimplemented(cmdtp, bd, flag, argc, argv);
+ return 0;
}
-void
+int
do_siinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
unimplemented(cmdtp, bd, flag, argc, argv);
+ return 0;
}
-void
+int
do_mccinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
unimplemented(cmdtp, bd, flag, argc, argv);
+ return 0;
}
#endif /* CFG_CMD_IMMAP && (CONFIG_8xx || CONFIG_8260) */
#include <cmd_mem.h>
#if (CONFIG_COMMANDS & CFG_CMD_MEMORY)
-
-static void mod_mem(cmd_tbl_t *, int, int, int, char *[]);
+static int mod_mem(cmd_tbl_t *, int, int, int, char *[]);
/* Display values from last command.
* Memory modify remembered values are different from display memory.
* md{.b, .w, .l} {addr} {len}
*/
#define DISP_LINE_LEN 16
-
-void do_mem_md (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_mem_md (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
ulong addr, size, length;
ulong i, nbytes, linebytes;
if (argc < 2) {
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
if ((flag & CMD_FLAG_REPEAT) == 0) {
dp_last_addr = addr;
dp_last_length = length;
dp_last_size = size;
+ return 0;
}
-
-void do_mem_mm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_mem_mm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
- mod_mem (cmdtp, 1, flag, argc, argv);
+ return mod_mem (cmdtp, 1, flag, argc, argv);
}
-
-
-void do_mem_nm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_mem_nm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
- mod_mem (cmdtp, 0, flag, argc, argv);
+ return mod_mem (cmdtp, 0, flag, argc, argv);
}
-
-void do_mem_mw (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_mem_mw (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
ulong addr, size, writeval, count;
if ((argc < 3) || (argc > 4)) {
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
/* Check for size specification.
*((u_char *)addr) = (u_char)writeval;
addr += size;
}
+ return 0;
}
-
-void do_mem_cmp (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_mem_cmp (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
ulong size, addr1, addr2, count, ngood;
+ int rcode = 0;
if (argc != 4) {
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
/* Check for size specification.
printf("word at 0x%08lx (0x%08lx) "
"!= word at 0x%08lx (0x%08lx)\n",
addr1, word1, addr2, word2);
+ rcode = 1;
break;
}
}
printf("halfword at 0x%08lx (0x%04x) "
"!= halfword at 0x%08lx (0x%04x)\n",
addr1, hword1, addr2, hword2);
+ rcode = 1;
break;
}
}
printf("byte at 0x%08lx (0x%02x) "
"!= byte at 0x%08lx (0x%02x)\n",
addr1, byte1, addr2, byte2);
+ rcode = 1;
break;
}
}
printf("Total of %ld %s%s were the same\n",
ngood, size == 4 ? "word" : size == 2 ? "halfword" : "byte",
ngood == 1 ? "" : "s");
+ return rcode;
}
-
-void do_mem_cp (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_mem_cp (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
ulong addr, size, dest, count;
if (argc != 4) {
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
/* Check for size specification.
printf ("Copy to Flash... ");
switch (rc = flash_write ((uchar *)addr, dest, count*size)) {
case 0: printf ("done\n");
- return;
+ return 0;
case 1: printf ("Timeout writing to Flash\n");
- return;
+ return 1;
case 2: printf ("Flash not Erased\n");
- return;
+ return 1;
case 4: printf ("Can't write to protected Flash sectors\n");
- return;
+ return 1;
case 8: printf ("Outside available Flash\n");
- return;
+ return 1;
default:
printf ("%s[%d] FIXME: rc=%d\n",__FILE__,__LINE__,rc);
- return;
+ return 1;
}
}
addr += size;
dest += size;
}
+ return 0;
}
-
-void do_mem_base (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_mem_base (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
if (argc > 1) {
/* Set new base address.
/* Print the current base address.
*/
printf("Base Address: 0x%08lx\n", base_address);
+ return 0;
}
-
-void do_mem_loop (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_mem_loop (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
ulong addr, size, length, i, junk;
volatile uint *longp;
if (argc < 3) {
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
/* Check for a size spefication.
/* Just a quickie to walk through some memory.
*/
-void do_mem_mtest (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_mem_mtest (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
ulong *addr, *start, *end;
ulong val;
ulong pattern;
+ int rcode = 0;
if (argc > 1) {
start = (ulong *)simple_strtoul(argv[1], NULL, 16);
for (;;) {
if (ctrlc()) {
putc ('\n');
- return;
+ return 1;
}
printf ("\rPattern %08lX Writing..."
printf ("\nMem error @ 0x%08X: "
"found %08lX, expected 0x%08lX\n",
(uint)addr, *addr, val);
+ rcode = 1;
}
val++;
}
pattern++;
}
+ return rcode;
+
}
* mm{.b, .w, .l} {addr}
* nm{.b, .w, .l} {addr}
*/
-
-static void
+static int
mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char *argv[])
{
ulong addr, size, i;
if (argc != 2) {
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
#ifdef CONFIG_BOOT_RETRY_TIME
mm_last_addr = addr;
mm_last_size = size;
+ return 0;
}
-
-void do_mem_crc (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_mem_crc (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
ulong addr, length;
ulong crc;
if (argc < 3) {
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
addr = simple_strtoul(argv[1], NULL, 16);
printf ("CRC32 for %08lx ... %08lx ==> %08lx\n",
addr, addr + length -1, crc);
+ return 0;
}
#endif /* CFG_CMD_MEMORY */
* mii write {addr} {reg} {data}
*/
-void do_mii (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_mii (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
char op;
unsigned char addr, reg;
unsigned short data;
+ int rcode = 0;
/*
* We use the last specified parameters, unless new ones are
}
else if(op == 'r')
{
- if(miiphy_read(addr, reg, &data) != 0)
+ if(miiphy_read(addr, reg, &data) != 0) {
printf("Error reading from the PHY\n");
+ rcode = 1;
+ }
printf("%04X\n", data & 0x0000FFFF);
}
else if(op == 'w')
{
- if(miiphy_write(addr, reg, data) != 0)
+ if(miiphy_write(addr, reg, data) != 0) {
printf("Error writing to the PHY\n");
+ rcode = 1;
+ }
}
else
{
printf("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
/*
last_op = op;
last_addr = addr;
last_data = data;
+
+ return rcode;
}
#endif /* CFG_CMD_MII */
# include <cmd_autoscript.h>
# endif
-extern void do_bootm (cmd_tbl_t *, bd_t *, int, int, char *[]);
+extern int do_bootm (cmd_tbl_t *, bd_t *, int, int, char *[]);
-static void netboot_common (int, cmd_tbl_t *, bd_t *, int , char *[]);
+static int netboot_common (int, cmd_tbl_t *, bd_t *, int , char *[]);
-void do_bootp (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_bootp (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
- netboot_common (BOOTP, cmdtp, bd, argc, argv);
+ return netboot_common (BOOTP, cmdtp, bd, argc, argv);
}
-void do_tftpb (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_tftpb (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
- netboot_common (TFTP, cmdtp, bd, argc, argv);
+ return netboot_common (TFTP, cmdtp, bd, argc, argv);
}
-void do_rarpb (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_rarpb (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
- netboot_common (RARP, cmdtp, bd, argc, argv);
+ return netboot_common (RARP, cmdtp, bd, argc, argv);
}
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
-void do_dhcp (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_dhcp (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
- netboot_common(DHCP, cmdtp, bd, argc, argv);
+ return netboot_common(DHCP, cmdtp, bd, argc, argv);
}
#endif /* CFG_CMD_DHCP */
setenv("dnsip", tmp);
}
}
-
-static void
+static int
netboot_common (int proto, cmd_tbl_t *cmdtp, bd_t *bd, int argc, char *argv[])
{
char *s;
+ int rcode = 0;
switch (argc) {
case 1:
break;
default: printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
if (NetLoop(bd, proto) == 0)
- return;
+ return 1;
/* NetLoop ok, update environment */
netboot_update_env();
printf ("Automatic boot of image at addr 0x%08lX ...\n",
load_addr);
-
- do_bootm (cmdtp, bd, 0, 1, local_args);
+ rcode = do_bootm (cmdtp, bd, 0, 1, local_args);
}
#ifdef CONFIG_AUTOSCRIPT
if (((s = getenv("autoscript")) != NULL) && (strcmp(s,"yes") == 0)) {
printf("Running autoscript at addr 0x%08lX ...\n", load_addr);
- autoscript (bd, load_addr);
+ rcode = autoscript (bd, load_addr);
}
#endif
-
+ return rcode;
}
#endif /* CFG_CMD_NET */
* Command interface: print one or all environment variables
*/
-void do_printenv (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_printenv (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
int i, j, k, nxt;
+ int rcode = 0;
if (argc == 1) { /* Print all env variables */
for (i=0; get_env_char(i) != '\0'; i=nxt+1) {
if (ctrlc()) {
printf ("\n ** Abort\n");
- return;
+ return 1;
}
}
printf("\nEnvironment size: %d/%d bytes\n", i, ENV_SIZE);
- return;
+ return 0;
}
for (i=1; i<argc; ++i) { /* print single env variables */
putc ('\n');
break;
}
- if (k < 0)
+ if (k < 0) {
printf ("## Error: \"%s\" not defined\n", name);
+ rcode ++;
+ }
}
+ return rcode;
}
/************************************************************************
* This function will ONLY work with a in-RAM copy of the environment
*/
-void _do_setenv (bd_t *bd, int flag, int argc, char *argv[])
+int _do_setenv (bd_t *bd, int flag, int argc, char *argv[])
{
int i, len, oldval;
int console = -1;
uchar *env_data = get_env_addr(0);
if (!env_data) /* need copy in RAM */
- return;
+ return 1;
name = argv[1];
#endif /* CONFIG_OVERWRITE_ETHADDR_ONCE && CONFIG_ETHADDR */
) ) {
printf ("Can't overwrite \"%s\"\n", name);
- return;
+ return 1;
}
#endif
if (console != -1) {
if (argc < 3) { /* Cannot delete it! */
printf("Can't delete \"%s\"\n", name);
- return;
+ return 1;
}
/* Try assigning specified device */
if (console_assign (console, argv[2]) < 0)
- return;
+ return 1;
}
/*
if (i == N_BAUDRATES) {
printf ("## Baudrate %d bps not supported\n",
baudrate);
- return;
+ return 1;
}
printf ("## Switch baudrate to %d bps and press ENTER ...\n",
baudrate);
/* Update CRC */
env_ptr->crc = crc32(0, env_ptr->data, ENV_SIZE);
- return;
+ return 0;
}
/*
}
if (len > (&env_data[ENV_SIZE]-env)) {
printf ("## Error: environment overflow, \"%s\" deleted\n", name);
- return;
+ return 1;
}
while ((*env = *name++) != '\0')
env++;
bd->bi_enetaddr[i] = s ? simple_strtoul(s, &e, 16) : 0;
if (s) s = (*e) ? e+1 : e;
}
- return;
+ return 0;
}
if (strcmp(argv[1],"ipaddr") == 0) {
bd->bi_ip_addr |= (val & 0xFF);
if (s) s = (*e) ? e+1 : e;
}
- return;
+ return 0;
}
if (strcmp(argv[1],"loadaddr") == 0) {
load_addr = simple_strtoul(argv[2], NULL, 16);
- return;
+ return 0;
}
#if (CONFIG_COMMANDS & CFG_CMD_NET)
if (strcmp(argv[1],"bootfile") == 0) {
copy_filename (BootFile, argv[2], sizeof(BootFile));
- return;
+ return 0;
}
#endif /* CFG_CMD_NET */
+ return 0;
}
void setenv (char *varname, char *varvalue)
_do_setenv (bd_ptr, 0, 3, argv);
}
-void do_setenv (cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc,
+int do_setenv (cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc,
char *argv[])
{
if (argc < 2) {
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
- _do_setenv (bd, flag, argc, argv);
+ return _do_setenv (bd, flag, argc, argv);
}
/************************************************************************
*/
#if (CONFIG_COMMANDS & CFG_CMD_ASKENV)
-void do_askenv (cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc,
+int do_askenv (cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc,
char *argv[])
{
extern char console_buffer[CFG_CBSIZE];
if (argc < 2) {
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
/* Check the syntax */
switch (argc) {
case 1:
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
case 2: /* askenv envname */
sprintf (message, "Please enter '%s':", argv[1]);
size = CFG_CBSIZE - 1;
if (size <= 0)
- return;
+ return 1;
/* prompt for input */
len = readline (message);
}
// Continue calling setenv code
- _do_setenv (bd, flag, len, local_args);
+ return _do_setenv (bd, flag, len, local_args);
}
#endif /* CFG_CMD_ASKENV */
#ifdef CFG_ENV_IS_IN_NVRAM
-void do_saveenv (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_saveenv (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
+ int rcode = 0;
printf ("Saving Environment to NVRAM...\n");
- memcpy ((char *)CFG_ENV_ADDR, env_ptr, CFG_ENV_SIZE);
+ if (memcpy ((char *)CFG_ENV_ADDR, env_ptr, CFG_ENV_SIZE) == NULL)
+ rcode = 1 ;
+ return rcode;
}
#elif CFG_ENV_IS_IN_EEPROM
-void do_saveenv (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_saveenv (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
printf ("Saving Environment to EEPROM...\n");
- eeprom_write (CFG_ENV_OFFSET, (uchar *)env_ptr, CFG_ENV_SIZE);
+ return eeprom_write (CFG_ENV_OFFSET, (uchar *)env_ptr, CFG_ENV_SIZE);
}
#else /* !CFG_ENV_IS_IN_NVRAM, !CFG_ENV_IS_IN_EEPROM => Must be flash, then */
/* need both ENV and flash */
#if ((CONFIG_COMMANDS & (CFG_CMD_ENV|CFG_CMD_FLASH)) == (CFG_CMD_ENV|CFG_CMD_FLASH))
-void do_saveenv (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_saveenv (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
int len, rc;
ulong end_addr;
#else
uchar *env_buffer = (char *)env_ptr;
#endif /* CFG_ENV_SECT_SIZE */
+ int rcode = 0;
#if defined(CFG_ENV_SECT_SIZE) && (CFG_ENV_SECT_SIZE > CFG_ENV_SIZE)
end_addr = (ulong)flash_sect_addr + len - 1;
- flash_sect_protect (0, (ulong)flash_sect_addr, end_addr);
+ if (flash_sect_protect (0, (ulong)flash_sect_addr, end_addr))
+ return 1;
printf ("Erasing Flash...");
- flash_sect_erase ((ulong)flash_sect_addr, end_addr);
+ if (flash_sect_erase ((ulong)flash_sect_addr, end_addr))
+ return 1;
printf ("Saving Environment to Flash...\n");
switch (rc = flash_write(env_buffer, (ulong)flash_sect_addr, len)) {
case 0: break;
case 1: printf ("Timeout writing to Flash\n");
+ rcode = 1;
break;
case 2: printf ("Flash not Erased\n");
+ rcode = 1;
break;
case 4: printf ("Can't write to protected Flash sectors\n");
+ rcode = 1;
break;
case 8: printf ("Outside available Flash\n");
- return;
+ return 1;
default:
printf ("%s[%d] FIXME: rc=%d\n",__FILE__,__LINE__,rc);
+ rcode = 1;
}
- flash_sect_protect (1, (ulong)flash_sect_addr, end_addr);
+ /* try to re-protect */
+ (void) flash_sect_protect (1, (ulong)flash_sect_addr, end_addr);
+ return rcode;
}
#endif /* CFG_CMD_ENV + CFG_CMD_FLASH */
#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
-void do_pinit (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_pinit (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
-
+ int rcode = 0;
+
if (argc != 2) {
printf ("Usage: pinit {on | off}\n");
- return;
+ return 1;
}
if (strcmp(argv[1],"on") == 0) {
- pcmcia_on ();
+ rcode = pcmcia_on ();
} else if (strcmp(argv[1],"off") == 0) {
- pcmcia_off ();
+ rcode = pcmcia_off ();
} else {
printf ("Usage: pinit {on | off}\n");
- return;
+ return 1;
}
- return;
+ return rcode;
}
#endif /* CFG_CMD_PCMCIA */
/* disable external hardware */
printf ("Shutdown and Poweroff " PCMCIA_SLOT_MSG "\n");
hardware_disable(_slot_);
+ return 0;
}
#endif /* CFG_CMD_PCMCIA */
#endif
#if (CONFIG_COMMANDS & CFG_CMD_REGINFO)
-void do_reginfo(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_reginfo(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
#if defined(CONFIG_8xx)
volatile immap_t *immap = (immap_t *)CFG_IMMR;
printf ("\n\n");
#endif /*(CONFIG_405GP)*/
+
+ return 0;
}
#endif /* CONFIG_8xx && CFG_CMD_REGINFO */
/******************************************************************************
* scsi boot command intepreter. Derived from diskboot
*/
-void do_scsiboot (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_scsiboot (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
char *boot_device = NULL;
char *ep;
ulong addr;
disk_partition_t info;
image_header_t *hdr;
+ int rcode = 0;
switch (argc) {
case 1:
break;
default:
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
if (!boot_device) {
puts ("\n** No boot device **\n");
- return;
+ return 1;
}
dev = simple_strtoul(boot_device, &ep, 16);
printf("booting from dev %d\n",dev);
if (scsi_dev_desc[dev].type == DEV_TYPE_UNKNOWN) {
printf ("\n** Device %d not available\n", dev);
- return;
+ return 1;
}
if (*ep) {
if (*ep != ':') {
puts ("\n** Invalid boot device, use `dev[:part]' **\n");
- return;
+ return 1;
}
part = simple_strtoul(++ep, NULL, 16);
}
if (get_partition_info (&scsi_dev_desc[dev], part, &info)) {
printf("error reading partinfo\n");
- return;
+ return 1;
}
if (strncmp(info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0) {
printf ("\n** Invalid partition type \"%.32s\""
" (expect \"" BOOT_PART_TYPE "\")\n",
info.type);
- return;
+ return 1;
}
printf ("\nLoading from SCSI device %d, partition %d: "
if (scsi_read (dev, info.start, 1, (ulong *)addr) != 1) {
printf ("** Read error on %d:%d\n", dev, part);
- return;
+ return 1;
}
hdr = (image_header_t *)addr;
if (scsi_read (dev, info.start+1, cnt,
(ulong *)(addr+info.blksz)) != cnt) {
printf ("** Read error on %d:%d\n", dev, part);
- return;
+ return 1;
}
/* Loading ok, update default load address */
load_addr = addr;
/* Check if we should attempt an auto-start */
if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) {
char *local_args[2];
- extern void do_bootm (cmd_tbl_t *, bd_t *, int, int, char *[]);
+ extern int do_bootm (cmd_tbl_t *, bd_t *, int, int, char *[]);
local_args[0] = argv[0];
local_args[1] = NULL;
printf ("Automatic boot of image at addr 0x%08lX ...\n", addr);
- do_bootm (cmdtp, bd, 0, 1, local_args);
+ rcode = do_bootm (cmdtp, bd, 0, 1, local_args);
}
+ return rcode;
}
/*********************************************************************************
* scsi command intepreter
*/
-void do_scsi (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_scsi (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
switch (argc) {
case 0:
- case 1: printf ("Usage:\n%s\n", cmdtp->usage); return;
+ case 1: printf ("Usage:\n%s\n", cmdtp->usage); return 1;
case 2:
if (strncmp(argv[1],"res",3) == 0) {
printf("\nReset SCSI\n");
scsi_bus_reset();
scsi_scan(1);
- return;
+ return 0;
}
if (strncmp(argv[1],"inf",3) == 0) {
int i;
printf ("SCSI dev. %d: ", i);
dev_print(&scsi_dev_desc[i]);
}
- return;
+ return 0;
}
if (strncmp(argv[1],"dev",3) == 0) {
if ((scsi_curr_dev < 0) || (scsi_curr_dev >= CFG_SCSI_MAX_DEVICE)) {
printf("\nno SCSI devices available\n");
- return;
+ return 1;
}
printf ("\n Device %d: ", scsi_curr_dev);
dev_print(&scsi_dev_desc[scsi_curr_dev]);
- return;
+ return 0;
}
if (strncmp(argv[1],"scan",4) == 0) {
scsi_scan(1);
- return;
+ return 0;
}
if (strncmp(argv[1],"part",4) == 0) {
int dev, ok;
}
if (!ok)
printf("\nno SCSI devices available\n");
- return;
+ return 1;
}
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
case 3:
if (strncmp(argv[1],"dev",3) == 0) {
int dev = (int)simple_strtoul(argv[2], NULL, 10);
printf ("\nSCSI device %d: ", dev);
if (dev >= CFG_SCSI_MAX_DEVICE) {
printf("unknown device\n");
- return;
+ return 1;
}
printf ("\n Device %d: ", dev);
dev_print(&scsi_dev_desc[dev]);
if(scsi_dev_desc[dev].type == DEV_TYPE_UNKNOWN) {
- return;
+ return 1;
}
scsi_curr_dev = dev;
printf("... is now current device\n");
- return;
+ return 0;
}
if (strncmp(argv[1],"part",4) == 0) {
int dev = (int)simple_strtoul(argv[2], NULL, 10);
else {
printf ("\nSCSI device %d not available\n", dev);
}
- return;
+ return 1;
}
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
default:
/* at least 4 args */
if (strcmp(argv[1],"read") == 0) {
scsi_curr_dev, blk, cnt);
n = scsi_read(scsi_curr_dev, blk, cnt, (ulong *)addr);
printf ("%ld blocks read: %s\n",n,(n==cnt) ? "OK" : "ERROR");
- return;
+ return 0;
}
} /* switch */
printf ("Usage:\n%s\n", cmdtp->usage);
+ return 1;
}
/****************************************************************************************
" - echo args to console; \\c suppresses newline\n" \
),
-void
+int
do_version (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
extern char version_string[];
printf ("\n%s\n", version_string);
+ return 0;
}
-void
+int
do_echo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
int i, putnl = 1;
if (putnl)
putc('\n');
+ return 0;
}
/*
* Use puts() instead of printf() to avoid printf buffer overflow
* for long help messages
*/
-void
+int
do_help (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
int i;
+ int rcode = 0;
if (argc == 1) { /* print short help (usage) */
for (cmdtp=&cmd_tbl[0]; cmdtp->name; cmdtp++) {
/* allow user abort */
if (ctrlc())
- return;
+ return 1;
if (cmdtp->usage == NULL)
continue;
puts (cmdtp->usage);
}
- return;
+ return 0;
}
/*
puts (cmdtp->help);
} else {
puts ("- No help available.\n");
+ rcode = 1;
}
putc ('\n');
#else /* no long help available */
" known commands\n\n",
argv[i]
);
+ rcode = 1;
}
}
+ return rcode;
}
/***************************************************************************
--- /dev/null
+/* vi: set sw=4 ts=4: */
+/*
+ * sh.c -- a prototype Bourne shell grammar parser
+ * Intended to follow the original Thompson and Ritchie
+ * "small and simple is beautiful" philosophy, which
+ * incidentally is a good match to today's BusyBox.
+ *
+ * Copyright (C) 2000,2001 Larry Doolittle <larry@doolittle.boa.org>
+ *
+ * Credits:
+ * The parser routines proper are all original material, first
+ * written Dec 2000 and Jan 2001 by Larry Doolittle.
+ * The execution engine, the builtins, and much of the underlying
+ * support has been adapted from busybox-0.49pre's lash,
+ * which is Copyright (C) 2000 by Lineo, Inc., and
+ * written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>.
+ * That, in turn, is based in part on ladsh.c, by Michael K. Johnson and
+ * Erik W. Troan, which they placed in the public domain. I don't know
+ * how much of the Johnson/Troan code has survived the repeated rewrites.
+ * Other credits:
+ * simple_itoa() was lifted from boa-0.93.15
+ * b_addchr() derived from similar w_addchar function in glibc-2.2
+ * setup_redirect(), redirect_opt_num(), and big chunks of main()
+ * and many builtins derived from contributions by Erik Andersen
+ * miscellaneous bugfixes from Matt Kraai
+ *
+ * There are two big (and related) architecture differences between
+ * this parser and the lash parser. One is that this version is
+ * actually designed from the ground up to understand nearly all
+ * of the Bourne grammar. The second, consequential change is that
+ * the parser and input reader have been turned inside out. Now,
+ * the parser is in control, and asks for input as needed. The old
+ * way had the input reader in control, and it asked for parsing to
+ * take place as needed. The new way makes it much easier to properly
+ * handle the recursion implicit in the various substitutions, especially
+ * across continuation lines.
+ *
+ * Bash grammar not implemented: (how many of these were in original sh?)
+ * $@ (those sure look like weird quoting rules)
+ * $_
+ * ! negation operator for pipes
+ * &> and >& redirection of stdout+stderr
+ * Brace Expansion
+ * Tilde Expansion
+ * fancy forms of Parameter Expansion
+ * aliases
+ * Arithmetic Expansion
+ * <(list) and >(list) Process Substitution
+ * reserved words: case, esac, select, function
+ * Here Documents ( << word )
+ * Functions
+ * Major bugs:
+ * job handling woefully incomplete and buggy
+ * reserved word execution woefully incomplete and buggy
+ * to-do:
+ * port selected bugfixes from post-0.49 busybox lash - done?
+ * finish implementing reserved words: for, while, until, do, done
+ * change { and } from special chars to reserved words
+ * builtins: break, continue, eval, return, set, trap, ulimit
+ * test magic exec
+ * handle children going into background
+ * clean up recognition of null pipes
+ * check setting of global_argc and global_argv
+ * control-C handling, probably with longjmp
+ * follow IFS rules more precisely, including update semantics
+ * figure out what to do with backslash-newline
+ * explain why we use signal instead of sigaction
+ * propagate syntax errors, die on resource errors?
+ * continuation lines, both explicit and implicit - done?
+ * memory leak finding and plugging - done?
+ * more testing, especially quoting rules and redirection
+ * document how quoting rules not precisely followed for variable assignments
+ * maybe change map[] to use 2-bit entries
+ * (eventually) remove all the printf's
+ *
+ * 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
+ */
+#define __PPCBOOT__
+#ifdef __PPCBOOT__
+#include <malloc.h> /* malloc, free, realloc*/
+#include <linux/ctype.h> /* isalpha, isdigit */
+#include <ppcboot.h> /* readline */
+#include <command.h> /* find_cmd */
+#include <cmd_bootm.h> /* do_bootd */
+#endif
+#ifdef CFG_HUSH_PARSER
+#ifndef __PPCBOOT__
+#include <ctype.h> /* isalpha, isdigit */
+#include <unistd.h> /* getpid */
+#include <stdlib.h> /* getenv, atoi */
+#include <string.h> /* strchr */
+#include <stdio.h> /* popen etc. */
+#include <glob.h> /* glob, of course */
+#include <stdarg.h> /* va_list */
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h> /* should be pretty obvious */
+
+#include <sys/stat.h> /* ulimit */
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+
+/* #include <dmalloc.h> */
+#define DEBUG_SHELL
+
+#ifdef BB_VER
+#include "busybox.h"
+#include "cmdedit.h"
+#else
+#define applet_name "hush"
+#include "standalone.h"
+#define hush_main main
+#undef BB_FEATURE_SH_FANCY_PROMPT
+#endif
+#endif
+
+#ifdef __PPCBOOT__
+#define EXIT_SUCCESS 0
+#define EOF -1
+#define syntax() syntax_err()
+#define xstrdup strdup
+#define xmalloc malloc
+#define xrealloc realloc
+#define error_msg printf
+#else
+typedef enum {
+ REDIRECT_INPUT = 1,
+ REDIRECT_OVERWRITE = 2,
+ REDIRECT_APPEND = 3,
+ REDIRECT_HEREIS = 4,
+ REDIRECT_IO = 5
+} redir_type;
+/* The descrip member of this structure is only used to make debugging
+ * output pretty */
+struct {int mode; int default_fd; char *descrip;} redir_table[] = {
+ { 0, 0, "()" },
+ { O_RDONLY, 0, "<" },
+ { O_CREAT|O_TRUNC|O_WRONLY, 1, ">" },
+ { O_CREAT|O_APPEND|O_WRONLY, 1, ">>" },
+ { O_RDONLY, -1, "<<" },
+ { O_RDWR, 1, "<>" }
+};
+#endif
+
+typedef enum {
+ PIPE_SEQ = 1,
+ PIPE_AND = 2,
+ PIPE_OR = 3,
+ PIPE_BG = 4,
+} pipe_style;
+
+/* might eventually control execution */
+typedef enum {
+ RES_NONE = 0,
+ RES_IF = 1,
+ RES_THEN = 2,
+ RES_ELIF = 3,
+ RES_ELSE = 4,
+ RES_FI = 5,
+ RES_FOR = 6,
+ RES_WHILE = 7,
+ RES_UNTIL = 8,
+ RES_DO = 9,
+ RES_DONE = 10,
+ RES_XXXX = 11,
+ RES_SNTX = 12
+} reserved_style;
+#define FLAG_END (1<<RES_NONE)
+#define FLAG_IF (1<<RES_IF)
+#define FLAG_THEN (1<<RES_THEN)
+#define FLAG_ELIF (1<<RES_ELIF)
+#define FLAG_ELSE (1<<RES_ELSE)
+#define FLAG_FI (1<<RES_FI)
+#define FLAG_FOR (1<<RES_FOR)
+#define FLAG_WHILE (1<<RES_WHILE)
+#define FLAG_UNTIL (1<<RES_UNTIL)
+#define FLAG_DO (1<<RES_DO)
+#define FLAG_DONE (1<<RES_DONE)
+#define FLAG_START (1<<RES_XXXX)
+
+/* This holds pointers to the various results of parsing */
+struct p_context {
+ struct child_prog *child;
+ struct pipe *list_head;
+ struct pipe *pipe;
+#ifndef __PPCBOOT__
+ struct redir_struct *pending_redirect;
+#endif
+ reserved_style w;
+ int old_flag; /* for figuring out valid reserved words */
+ struct p_context *stack;
+ /* How about quoting status? */
+};
+#ifndef __PPCBOOT__
+struct redir_struct {
+ redir_type type; /* type of redirection */
+ int fd; /* file descriptor being redirected */
+ int dup; /* -1, or file descriptor being duplicated */
+ struct redir_struct *next; /* pointer to the next redirect in the list */
+ glob_t word; /* *word.gl_pathv is the filename */
+};
+#endif
+struct child_prog {
+#ifndef __PPCBOOT__
+ pid_t pid; /* 0 if exited */
+#endif
+ char **argv; /* program name and arguments */
+#ifdef __PPCBOOT__
+ int argc; /* number of program arguments */
+#endif
+ struct pipe *group; /* if non-NULL, first in group or subshell */
+#ifndef __PPCBOOT__
+ int subshell; /* flag, non-zero if group must be forked */
+ struct redir_struct *redirects; /* I/O redirections */
+ glob_t glob_result; /* result of parameter globbing */
+ int is_stopped; /* is the program currently running? */
+ struct pipe *family; /* pointer back to the child's parent pipe */
+#endif
+};
+
+struct pipe {
+#ifndef __PPCBOOT__
+ int jobid; /* job number */
+#endif
+ int num_progs; /* total number of programs in job */
+#ifndef __PPCBOOT__
+ int running_progs; /* number of programs running */
+ char *text; /* name of job */
+ char *cmdbuf; /* buffer various argv's point into */
+ pid_t pgrp; /* process group ID for the job */
+#endif
+ struct child_prog *progs; /* array of commands in pipe */
+ struct pipe *next; /* to track background commands */
+#ifndef __PPCBOOT__
+ int stopped_progs; /* number of programs alive, but stopped */
+ int job_context; /* bitmask defining current context */
+#endif
+ pipe_style followup; /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */
+ reserved_style r_mode; /* supports if, for, while, until */
+};
+#ifndef __PPCBOOT__
+struct close_me {
+ int fd;
+ struct close_me *next;
+};
+#endif
+struct variables {
+ char *name;
+ char *value;
+ int flg_export;
+ int flg_read_only;
+ struct variables *next;
+};
+
+/* globals, connect us to the outside world
+ * the first three support $?, $#, and $1 */
+#ifndef __PPCBOOT__
+char **global_argv;
+unsigned int global_argc;
+#endif
+unsigned int last_return_code;
+#ifndef __PPCBOOT__
+extern char **environ; /* This is in <unistd.h>, but protected with __USE_GNU */
+#endif
+
+/* "globals" within this file */
+static char *ifs;
+static char map[256];
+#ifndef __PPCBOOT__
+static int fake_mode;
+static int interactive;
+static struct close_me *close_me_head;
+static const char *cwd;
+static struct pipe *job_list;
+static unsigned int last_bg_pid;
+static unsigned int last_jobid;
+static unsigned int shell_terminal;
+static char *PS1;
+static char *PS2;
+#else
+static bd_t *BD;
+#endif
+struct variables shell_ver = { "HUSH_VERSION", "0.01", 1, 1, 0 };
+struct variables *top_vars = &shell_ver;
+
+#define B_CHUNK (100)
+#define B_NOSPAC 1
+
+typedef struct {
+ char *data;
+ int length;
+ int maxlen;
+ int quote;
+ int nonnull;
+} o_string;
+#define NULL_O_STRING {NULL,0,0,0,0}
+/* used for initialization:
+ o_string foo = NULL_O_STRING; */
+
+/* I can almost use ordinary FILE *. Is open_memstream() universally
+ * available? Where is it documented? */
+struct in_str {
+ const char *p;
+#ifndef __PPCBOOT__
+ char peek_buf[2];
+#endif
+ int __promptme;
+ int promptmode;
+#ifndef __PPCBOOT__
+ FILE *file;
+#endif
+ int (*get) (struct in_str *);
+ int (*peek) (struct in_str *);
+};
+#define b_getch(input) ((input)->get(input))
+#define b_peek(input) ((input)->peek(input))
+#ifndef __PPCBOOT__
+#define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
+struct built_in_command {
+ char *cmd; /* name */
+ char *descr; /* description */
+ int (*function) (struct child_prog *); /* function ptr */
+};
+#endif
+/* belongs in busybox.h */
+static inline int max(int a, int b) {
+ return (a>b)?a:b;
+}
+/* This should be in utility.c */
+
+#ifdef DEBUG_SHELL
+#ifndef __PPCBOOT__
+static void debug_printf(const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ printf(stderr, format, args);\r
+ va_end(args);
+}
+#else
+#define debug_printf printf /* ppcboot debug flag */
+#endif
+#else
+static inline void debug_printf(const char *format, ...) { }
+#endif
+#define final_printf debug_printf
+#ifdef __PPCBOOT__
+static void syntax_err(void) {
+ printf("syntax error\n");
+}
+#else
+static void __syntax(char *file, int line) {
+ error_msg("syntax error %s:%d", file, line);
+}
+#define syntax() __syntax(__FILE__, __LINE__)
+/* Index of subroutines: */
+/* function prototypes for builtins */
+static int builtin_cd(struct child_prog *child);
+static int builtin_env(struct child_prog *child);
+static int builtin_exec(struct child_prog *child);
+static int builtin_exit(struct child_prog *child);
+static int builtin_export(struct child_prog *child);
+static int builtin_fg_bg(struct child_prog *child);
+static int builtin_help(struct child_prog *child);
+static int builtin_jobs(struct child_prog *child);
+static int builtin_pwd(struct child_prog *child);
+static int builtin_read(struct child_prog *child);
+static int builtin_set(struct child_prog *child);
+static int builtin_shift(struct child_prog *child);
+static int builtin_source(struct child_prog *child);
+static int builtin_umask(struct child_prog *child);
+static int builtin_unset(struct child_prog *child);
+static int builtin_not_written(struct child_prog *child);
+#endif
+/* o_string manipulation: */
+static int b_check_space(o_string *o, int len);
+static int b_addchr(o_string *o, int ch);
+static void b_reset(o_string *o);
+static int b_addqchr(o_string *o, int ch, int quote);
+static int b_adduint(o_string *o, unsigned int i);
+/* in_str manipulations: */
+static int static_get(struct in_str *i);
+static int static_peek(struct in_str *i);
+static int file_get(struct in_str *i);
+static int file_peek(struct in_str *i);
+#ifndef __PPCBOOT__
+static void setup_file_in_str(struct in_str *i, FILE *f);
+#else
+static void setup_file_in_str(struct in_str *i);
+#endif
+static void setup_string_in_str(struct in_str *i, const char *s);
+#ifndef __PPCBOOT__
+/* close_me manipulations: */
+static void mark_open(int fd);
+static void mark_closed(int fd);
+static void close_all();
+#endif
+/* "run" the final data structures: */
+static char *indenter(int i);
+static int free_pipe_list(struct pipe *head, int indent);
+static int free_pipe(struct pipe *pi, int indent);
+/* really run the final data structures: */
+#ifndef __PPCBOOT__
+static int setup_redirects(struct child_prog *prog, int squirrel[]);
+#endif
+static int run_list_real(struct pipe *pi);
+#ifndef __PPCBOOT__
+static void pseudo_exec(struct child_prog *child) __attribute__ ((noreturn));
+#endif
+static int run_pipe_real(struct pipe *pi);
+/* extended glob support: */
+#ifndef __PPCBOOT__
+static int globhack(const char *src, int flags, glob_t *pglob);
+static int glob_needed(const char *s);
+static int xglob(o_string *dest, int flags, glob_t *pglob);
+#endif
+/* variable assignment: */
+static int is_assignment(const char *s);
+/* data structure manipulation: */
+#ifndef __PPCBOOT__
+static int setup_redirect(struct p_context *ctx, int fd, redir_type style, struct in_str *input);
+#endif
+static void initialize_context(struct p_context *ctx);
+static int done_word(o_string *dest, struct p_context *ctx);
+static int done_command(struct p_context *ctx);
+static int done_pipe(struct p_context *ctx, pipe_style type);
+/* primary string parsing: */
+#ifndef __PPCBOOT__
+static int redirect_dup_num(struct in_str *input);
+static int redirect_opt_num(o_string *o);
+static int process_command_subs(o_string *dest, struct p_context *ctx, struct in_str *input, int subst_end);
+static int parse_group(o_string *dest, struct p_context *ctx, struct in_str *input, int ch);
+#endif
+static void lookup_param(o_string *dest, struct p_context *ctx, o_string *src);
+static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *input);
+static int parse_string(o_string *dest, struct p_context *ctx, const char *src);
+static int parse_stream(o_string *dest, struct p_context *ctx, struct in_str *input0, int end_trigger);
+/* setup: */
+static int parse_stream_outer(struct in_str *inp);
+#ifndef __PPCBOOT__
+static int parse_string_outer(const char *s);
+static int parse_file_outer(FILE *f);
+#else
+int ppcboot_hush_start(bd_t *bd);
+static int parse_file_outer(void);
+#endif
+#ifndef __PPCBOOT__
+/* job management: */
+static int checkjobs(struct pipe* fg_pipe);
+static void insert_bg_job(struct pipe *pi);
+static void remove_bg_job(struct pipe *pi);
+#endif
+/* local variable support */
+static char *get_local_var(const char *var);
+#ifndef __PPCBOOT__
+static void unset_local_var(const char *name);
+#endif
+static int set_local_var(const char *s, int flg_export);
+#ifndef __PPCBOOT__
+/* Table of built-in functions. They can be forked or not, depending on
+ * context: within pipes, they fork. As simple commands, they do not.
+ * When used in non-forking context, they can change global variables
+ * in the parent shell process. If forked, of course they can not.
+ * For example, 'unset foo | whatever' will parse and run, but foo will
+ * still be set at the end. */
+static struct built_in_command bltins[] = {
+ {"bg", "Resume a job in the background", builtin_fg_bg},
+ {"break", "Exit for, while or until loop", builtin_not_written},
+ {"cd", "Change working directory", builtin_cd},
+ {"continue", "Continue for, while or until loop", builtin_not_written},
+ {"env", "Print all environment variables", builtin_env},
+ {"eval", "Construct and run shell command", builtin_not_written},
+ {"exec", "Exec command, replacing this shell with the exec'd process",
+ builtin_exec},
+ {"exit", "Exit from shell()", builtin_exit},
+ {"export", "Set environment variable", builtin_export},
+ {"fg", "Bring job into the foreground", builtin_fg_bg},
+ {"jobs", "Lists the active jobs", builtin_jobs},
+ {"pwd", "Print current directory", builtin_pwd},
+ {"read", "Input environment variable", builtin_read},
+ {"return", "Return from a function", builtin_not_written},
+ {"set", "Set/unset shell local variables", builtin_set},
+ {"shift", "Shift positional parameters", builtin_shift},
+ {"trap", "Trap signals", builtin_not_written},
+ {"ulimit","Controls resource limits", builtin_not_written},
+ {"umask","Sets file creation mask", builtin_umask},
+ {"unset", "Unset environment variable", builtin_unset},
+ {".", "Source-in and run commands in a file", builtin_source},
+ {"help", "List shell built-in commands", builtin_help},
+ {NULL, NULL, NULL}
+};
+
+static const char *set_cwd(void)
+{
+ if(cwd==unknown)
+ cwd = NULL; /* xgetcwd(arg) called free(arg) */
+ cwd = xgetcwd((char *)cwd);
+ if (!cwd)
+ cwd = unknown;
+ return cwd;
+}
+
+
+/* built-in 'cd <path>' handler */
+static int builtin_cd(struct child_prog *child)
+{
+ char *newdir;
+ if (child->argv[1] == NULL)
+ newdir = getenv("HOME");
+ else
+ newdir = child->argv[1];
+ if (chdir(newdir)) {
+ printf("cd: %s: %s\n", newdir, strerror(errno));
+ return EXIT_FAILURE;
+ }
+ set_cwd();
+ return EXIT_SUCCESS;
+}
+
+/* built-in 'env' handler */
+static int builtin_env(struct child_prog *dummy)
+{
+ char **e = environ;
+ if (e == NULL) return EXIT_FAILURE;
+ for (; *e; e++) {
+ puts(*e);
+ }
+ return EXIT_SUCCESS;
+}
+
+/* built-in 'exec' handler */
+static int builtin_exec(struct child_prog *child)
+{
+ if (child->argv[1] == NULL)
+ return EXIT_SUCCESS; /* Really? */
+ child->argv++;
+ pseudo_exec(child);
+ /* never returns */
+}
+
+/* built-in 'exit' handler */
+static int builtin_exit(struct child_prog *child)
+{
+ if (child->argv[1] == NULL)
+ exit(last_return_code);
+ exit (atoi(child->argv[1]));
+}
+
+/* built-in 'export VAR=value' handler */
+static int builtin_export(struct child_prog *child)
+{
+ int res = 0;
+ char *name = child->argv[1];
+
+ if (name == NULL) {
+ return (builtin_env(child));
+ }
+
+ name = strdup(name);
+
+ if(name) {
+ char *value = strchr(name, '=');
+
+ if (!value) {
+ char *tmp;
+ /* They are exporting something without an =VALUE */
+
+ value = get_local_var(name);
+ if (value) {
+ size_t ln = strlen(name);
+
+ tmp = realloc(name, ln+strlen(value)+2);
+ if(tmp==NULL)
+ res = -1;
+ else {
+ sprintf(tmp+ln, "=%s", value);
+ name = tmp;
+ }
+ } else {
+ /* bash does not return an error when trying to export
+ * an undefined variable. Do likewise. */
+ res = 1;
+ }
+ }
+ }
+ if (res<0)
+ perror_msg("export");
+ else if(res==0)
+ res = set_local_var(name, 1);
+ else
+ res = 0;
+ free(name);
+ return res;
+}
+
+/* built-in 'fg' and 'bg' handler */
+static int builtin_fg_bg(struct child_prog *child)
+{
+ int i, jobnum;
+ struct pipe *pi=NULL;
+
+ if (!interactive)
+ return EXIT_FAILURE;
+ /* If they gave us no args, assume they want the last backgrounded task */
+ if (!child->argv[1]) {
+ for (pi = job_list; pi; pi = pi->next) {
+ if (pi->jobid == last_jobid) {
+ break;
+ }
+ }
+ if (!pi) {
+ error_msg("%s: no current job", child->argv[0]);
+ return EXIT_FAILURE;
+ }
+ } else {
+ if (sscanf(child->argv[1], "%%%d", &jobnum) != 1) {
+ error_msg("%s: bad argument '%s'", child->argv[0], child->argv[1]);
+ return EXIT_FAILURE;
+ }
+ for (pi = job_list; pi; pi = pi->next) {
+ if (pi->jobid == jobnum) {
+ break;
+ }
+ }
+ if (!pi) {
+ error_msg("%s: %d: no such job", child->argv[0], jobnum);
+ return EXIT_FAILURE;
+ }
+ }
+
+ if (*child->argv[0] == 'f') {
+ /* Put the job into the foreground. */
+ tcsetpgrp(shell_terminal, pi->pgrp);
+ }
+
+ /* Restart the processes in the job */
+ for (i = 0; i < pi->num_progs; i++)
+ pi->progs[i].is_stopped = 0;
+
+ if ( (i=kill(- pi->pgrp, SIGCONT)) < 0) {
+ if (i == ESRCH) {
+ remove_bg_job(pi);
+ } else {
+ perror_msg("kill (SIGCONT)");
+ }
+ }
+
+ pi->stopped_progs = 0;
+ return EXIT_SUCCESS;
+}
+
+/* built-in 'help' handler */
+static int builtin_help(struct child_prog *dummy)
+{
+ struct built_in_command *x;
+
+ printf("\nBuilt-in commands:\n");
+ printf("-------------------\n");
+ for (x = bltins; x->cmd; x++) {
+ if (x->descr==NULL)
+ continue;
+ printf("%s\t%s\n", x->cmd, x->descr);
+ }
+ printf("\n\n");
+ return EXIT_SUCCESS;
+}
+
+/* built-in 'jobs' handler */
+static int builtin_jobs(struct child_prog *child)
+{
+ struct pipe *job;
+ char *status_string;
+
+ for (job = job_list; job; job = job->next) {
+ if (job->running_progs == job->stopped_progs)
+ status_string = "Stopped";
+ else
+ status_string = "Running";
+
+ printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->text);
+ }
+ return EXIT_SUCCESS;
+}
+
+
+/* built-in 'pwd' handler */
+static int builtin_pwd(struct child_prog *dummy)
+{
+ puts(set_cwd());
+ return EXIT_SUCCESS;
+}
+
+/* built-in 'read VAR' handler */
+static int builtin_read(struct child_prog *child)
+{
+ int res;
+
+ if (child->argv[1]) {
+ char string[BUFSIZ];
+ char *var = 0;
+
+ string[0] = 0; /* In case stdin has only EOF */
+ /* read string */
+ fgets(string, sizeof(string), stdin);
+ chomp(string);
+ var = malloc(strlen(child->argv[1])+strlen(string)+2);
+ if(var) {
+ sprintf(var, "%s=%s", child->argv[1], string);
+ res = set_local_var(var, 0);
+ } else
+ res = -1;
+ if (res)
+ fprintf(stderr, "read: %m\n");
+ free(var); /* So not move up to avoid breaking errno */
+ return res;
+ } else {
+ do res=getchar(); while(res!='\n' && res!=EOF);
+ return 0;
+ }
+}
+
+/* built-in 'set VAR=value' handler */
+static int builtin_set(struct child_prog *child)
+{
+ char *temp = child->argv[1];
+ struct variables *e;
+
+ if (temp == NULL)
+ for(e = top_vars; e; e=e->next)
+ printf("%s=%s\n", e->name, e->value);
+ else
+ set_local_var(temp, 0);
+
+ return EXIT_SUCCESS;
+}
+
+
+/* Built-in 'shift' handler */
+static int builtin_shift(struct child_prog *child)
+{
+ int n=1;
+ if (child->argv[1]) {
+ n=atoi(child->argv[1]);
+ }
+ if (n>=0 && n<global_argc) {
+ /* XXX This probably breaks $0 */
+ global_argc -= n;
+ global_argv += n;
+ return EXIT_SUCCESS;
+ } else {
+ return EXIT_FAILURE;
+ }
+}
+
+/* Built-in '.' handler (read-in and execute commands from file) */
+static int builtin_source(struct child_prog *child)
+{
+ FILE *input;
+ int status;
+
+ if (child->argv[1] == NULL)
+ return EXIT_FAILURE;
+
+ /* XXX search through $PATH is missing */
+ input = fopen(child->argv[1], "r");
+ if (!input) {
+ error_msg("Couldn't open file '%s'", child->argv[1]);
+ return EXIT_FAILURE;
+ }
+
+ /* Now run the file */
+ /* XXX argv and argc are broken; need to save old global_argv
+ * (pointer only is OK!) on this stack frame,
+ * set global_argv=child->argv+1, recurse, and restore. */
+ mark_open(fileno(input));
+ status = parse_file_outer(input);
+ mark_closed(fileno(input));
+ fclose(input);
+ return (status);
+}
+
+static int builtin_umask(struct child_prog *child)
+{
+ mode_t new_umask;
+ const char *arg = child->argv[1];
+ char *end;
+ if (arg) {
+ new_umask=strtoul(arg, &end, 8);
+ if (*end!='\0' || end == arg) {
+ return EXIT_FAILURE;
+ }
+ } else {
+ printf("%.3o\n", (unsigned int) (new_umask=umask(0)));
+ }
+ umask(new_umask);
+ return EXIT_SUCCESS;
+}
+
+/* built-in 'unset VAR' handler */
+static int builtin_unset(struct child_prog *child)
+{
+ /* bash returned already true */
+ unset_local_var(child->argv[1]);
+ return EXIT_SUCCESS;
+}
+
+static int builtin_not_written(struct child_prog *child)
+{
+ printf("builtin_%s not written\n",child->argv[0]);
+ return EXIT_FAILURE;
+}
+#endif
+static int b_check_space(o_string *o, int len)
+{
+ /* It would be easy to drop a more restrictive policy
+ * in here, such as setting a maximum string length */
+ if (o->length + len > o->maxlen) {
+ char *old_data = o->data;
+ /* assert (data == NULL || o->maxlen != 0); */
+ o->maxlen += max(2*len, B_CHUNK);
+ o->data = realloc(o->data, 1 + o->maxlen);
+ if (o->data == NULL) {
+ free(old_data);
+ }
+ }
+ return o->data == NULL;
+}
+
+static int b_addchr(o_string *o, int ch)
+{
+ debug_printf("b_addchr: %c %d %p\n", ch, o->length, o);
+ if (b_check_space(o, 1)) return B_NOSPAC;
+ o->data[o->length] = ch;
+ o->length++;
+ o->data[o->length] = '\0';
+ return 0;
+}
+
+static void b_reset(o_string *o)
+{
+ o->length = 0;
+ o->nonnull = 0;
+ if (o->data != NULL) *o->data = '\0';
+}
+
+static void b_free(o_string *o)
+{
+ b_reset(o);
+ if (o->data != NULL) free(o->data);
+ o->data = NULL;
+ o->maxlen = 0;
+}
+
+/* My analysis of quoting semantics tells me that state information
+ * is associated with a destination, not a source.
+ */
+static int b_addqchr(o_string *o, int ch, int quote)
+{
+ if (quote && strchr("*?[\\",ch)) {
+ int rc;
+ rc = b_addchr(o, '\\');
+ if (rc) return rc;
+ }
+ return b_addchr(o, ch);
+}
+
+/* belongs in utility.c */
+char *simple_itoa(unsigned int i)
+{
+ /* 21 digits plus null terminator, good for 64-bit or smaller ints */
+ static char local[22];
+ char *p = &local[21];
+ *p-- = '\0';
+ do {
+ *p-- = '0' + i % 10;
+ i /= 10;
+ } while (i > 0);
+ return p + 1;
+}
+
+static int b_adduint(o_string *o, unsigned int i)
+{
+ int r;
+ char *p = simple_itoa(i);
+ /* no escape checking necessary */
+ do r=b_addchr(o, *p++); while (r==0 && *p);
+ return r;
+}
+
+static int static_get(struct in_str *i)
+{
+ int ch=*i->p++;
+ if (ch=='\0') return EOF;
+ return ch;
+}
+
+static int static_peek(struct in_str *i)
+{
+ return *i->p;
+}
+#ifndef __PPCBOOT__
+static inline void cmdedit_set_initial_prompt(void)
+{
+#ifndef BB_FEATURE_SH_FANCY_PROMPT
+ PS1 = NULL;
+#else
+ PS1 = getenv("PS1");
+ if(PS1==0)
+ PS1 = "\\w \\$ ";
+#endif
+}
+
+static inline void setup_prompt_string(int promptmode, char **prompt_str)
+{
+ debug_printf("setup_prompt_string %d ",promptmode);
+#ifndef BB_FEATURE_SH_FANCY_PROMPT
+ /* Set up the prompt */
+ if (promptmode == 1) {
+ if (PS1)
+ free(PS1);
+ PS1=xmalloc(strlen(cwd)+4);
+ sprintf(PS1, "%s %s", cwd, ( geteuid() != 0 ) ? "$ ":"# ");
+ *prompt_str = PS1;
+ } else {
+ *prompt_str = PS2;
+ }
+#else
+ *prompt_str = (promptmode==1)? PS1 : PS2;
+#endif
+ debug_printf("result %s\n",*prompt_str);
+}
+#endif
+static void get_user_input(struct in_str *i)
+{
+
+#ifndef __PPCBOOT__
+ char *prompt_str;
+ static char the_command[BUFSIZ];
+
+ setup_prompt_string(i->promptmode, &prompt_str);
+#ifdef BB_FEATURE_COMMAND_EDITING
+ /*
+ ** enable command line editing only while a command line
+ ** is actually being read; otherwise, we'll end up bequeathing
+ ** atexit() handlers and other unwanted stuff to our
+ ** child processes (rob@sysgo.de)
+ */
+ cmdedit_read_input(prompt_str, the_command);
+#else
+ fputs(prompt_str, stdout);
+ fflush(stdout);
+ the_command[0]=fgetc(i->file);
+ the_command[1]='\0';
+#endif
+ fflush(stdout);
+ i->p = the_command;
+#else
+ extern char console_buffer[CFG_CBSIZE];
+ int n;
+ static int flag_repeat = 0;
+ static char the_command[CFG_CBSIZE];
+
+ if (i->promptmode == 1) {
+ readline(CFG_PROMPT);
+ } else {
+ readline(CFG_PROMPT_HUSH_PS2);
+ }
+ n = strlen(console_buffer);
+ console_buffer[n] = '\n';
+ console_buffer[n+1]= '\0';
+ if (i->promptmode == 1) {
+ if (console_buffer[0] == '\n'&& flag_repeat == 0) {
+ i->p = console_buffer;
+ }
+ else {
+ if (console_buffer[0] != '\n') {
+ strcpy(the_command,console_buffer);
+ flag_repeat = 1;
+ }
+ else {
+ flag_repeat = 0;
+ }
+ i->p = the_command;
+ }
+ }
+ else {
+ if (console_buffer[0] != '\n') {
+ if (strlen(the_command) + strlen(console_buffer)
+ < CFG_CBSIZE) {
+ n = strlen(the_command);
+ the_command[n-1] = ' ';
+ strcpy(&the_command[n],console_buffer);
+ }
+ else {
+ the_command[0] = '\n';
+ the_command[1] = '\0';
+ }
+ }
+ i->p = console_buffer;
+ }
+#endif
+}
+
+/* This is the magic location that prints prompts
+ * and gets data back from the user */
+static int file_get(struct in_str *i)
+{
+ int ch;
+ ch = 0;
+
+ /* If there is data waiting, eat it up */
+ if (i->p && *i->p) {
+ ch=*i->p++;
+ } else {
+ /* need to double check i->file because we might be doing something
+ * more complicated by now, like sourcing or substituting. */
+#ifndef __PPCBOOT__
+ if (i->__promptme && interactive && i->file == stdin) {
+ while(! i->p || (interactive && strlen(i->p)==0) ) {
+#else
+ while(! i->p || strlen(i->p)==0 ) {
+#endif
+ get_user_input(i);
+ }
+ i->promptmode=2;
+ i->__promptme = 0;
+ if (i->p && *i->p) {
+ ch=*i->p++;
+ }
+#ifndef __PPCBOOT__
+ } else {
+ ch = fgetc(i->file);
+ }
+#endif
+ debug_printf("b_getch: got a %d\n", ch);
+ }
+ if (ch == '\n') i->__promptme=1;
+ return ch;
+}
+
+/* All the callers guarantee this routine will never be
+ * used right after a newline, so prompting is not needed.
+ */
+static int file_peek(struct in_str *i)
+{
+#ifndef __PPCBOOT__
+ if (i->p && *i->p) {
+#endif
+ return *i->p;
+#ifndef __PPCBOOT__
+ } else {
+ i->peek_buf[0] = fgetc(i->file);
+ i->peek_buf[1] = '\0';
+ i->p = i->peek_buf;
+ debug_printf("b_peek: got a %d\n", *i->p);
+ return *i->p;
+ }
+#endif
+}
+#ifndef __PPCBOOT__
+static void setup_file_in_str(struct in_str *i, FILE *f)
+#else
+static void setup_file_in_str(struct in_str *i)
+#endif
+{
+ i->peek = file_peek;
+ i->get = file_get;
+ i->__promptme=1;
+ i->promptmode=1;
+#ifndef __PPCBOOT__
+ i->file = f;
+#endif
+ i->p = NULL;
+}
+
+static void setup_string_in_str(struct in_str *i, const char *s)
+{
+ i->peek = static_peek;
+ i->get = static_get;
+ i->__promptme=1;
+ i->promptmode=1;
+ i->p = s;
+}
+#ifndef __PPCBOOT__
+static void mark_open(int fd)
+{
+ struct close_me *new = xmalloc(sizeof(struct close_me));
+ new->fd = fd;
+ new->next = close_me_head;
+ close_me_head = new;
+}
+
+static void mark_closed(int fd)
+{
+ struct close_me *tmp;
+ if (close_me_head == NULL || close_me_head->fd != fd)
+ error_msg_and_die("corrupt close_me");
+ tmp = close_me_head;
+ close_me_head = close_me_head->next;
+ free(tmp);
+}
+
+static void close_all()
+{
+ struct close_me *c;
+ for (c=close_me_head; c; c=c->next) {
+ close(c->fd);
+ }
+ close_me_head = NULL;
+}
+/* squirrel != NULL means we squirrel away copies of stdin, stdout,
+ * and stderr if they are redirected. */
+static int setup_redirects(struct child_prog *prog, int squirrel[])
+{
+ int openfd, mode;
+ struct redir_struct *redir;
+
+ for (redir=prog->redirects; redir; redir=redir->next) {
+ if (redir->dup == -1 && redir->word.gl_pathv == NULL) {
+ /* something went wrong in the parse. Pretend it didn't happen */
+ continue;
+ }
+ if (redir->dup == -1) {
+ mode=redir_table[redir->type].mode;
+ openfd = open(redir->word.gl_pathv[0], mode, 0666);
+ if (openfd < 0) {
+ /* this could get lost if stderr has been redirected, but
+ bash and ash both lose it as well (though zsh doesn't!) */
+ perror_msg("error opening %s", redir->word.gl_pathv[0]);
+ return 1;
+ }
+ } else {
+ openfd = redir->dup;
+ }
+
+ if (openfd != redir->fd) {
+ if (squirrel && redir->fd < 3) {
+ squirrel[redir->fd] = dup(redir->fd);
+ }
+ if (openfd == -3) {
+ close(openfd);
+ } else {
+ dup2(openfd, redir->fd);
+ if (redir->dup == -1)
+ close (openfd);
+ }
+ }
+ }
+ return 0;
+}
+
+static void restore_redirects(int squirrel[])
+{
+ int i, fd;
+ for (i=0; i<3; i++) {
+ fd = squirrel[i];
+ if (fd != -1) {
+ /* No error checking. I sure wouldn't know what
+ * to do with an error if I found one! */
+ dup2(fd, i);
+ close(fd);
+ }
+ }
+}
+
+/* never returns */
+/* XXX no exit() here. If you don't exec, use _exit instead.
+ * The at_exit handlers apparently confuse the calling process,
+ * in particular stdin handling. Not sure why? */
+static void pseudo_exec(struct child_prog *child)
+{
+ int i, rcode;
+ struct built_in_command *x;
+ if (child->argv) {
+ for (i=0; is_assignment(child->argv[i]); i++) {
+ debug_printf("pid %d environment modification: %s\n",getpid(),child->argv[i]);
+ putenv(strdup(child->argv[i]));
+ }
+ child->argv+=i; /* XXX this hack isn't so horrible, since we are about
+ to exit, and therefore don't need to keep data
+ structures consistent for free() use. */
+ /* If a variable is assigned in a forest, and nobody listens,
+ * was it ever really set?
+ */
+ if (child->argv[0] == NULL) {
+ _exit(EXIT_SUCCESS);
+ }
+
+ /*
+ * Check if the command matches any of the builtins.
+ * Depending on context, this might be redundant. But it's
+ * easier to waste a few CPU cycles than it is to figure out
+ * if this is one of those cases.
+ */
+ for (x = bltins; x->cmd; x++) {
+ if (strcmp(child->argv[0], x->cmd) == 0 ) {
+ debug_printf("builtin exec %s\n", child->argv[0]);
+ rcode = x->function(child);
+ fflush(stdout);
+ _exit(rcode);
+ }
+ }
+
+ /* Check if the command matches any busybox internal commands
+ * ("applets") here.
+ * FIXME: This feature is not 100% safe, since
+ * BusyBox is not fully reentrant, so we have no guarantee the things
+ * from the .bss are still zeroed, or that things from .data are still
+ * at their defaults. We could exec ourself from /proc/self/exe, but I
+ * really dislike relying on /proc for things. We could exec ourself
+ * from global_argv[0], but if we are in a chroot, we may not be able
+ * to find ourself... */
+#ifdef BB_FEATURE_SH_STANDALONE_SHELL
+ {
+ int argc_l;
+ char** argv_l=child->argv;
+ char *name = child->argv[0];
+
+#ifdef BB_FEATURE_SH_APPLETS_ALWAYS_WIN
+ /* Following discussions from November 2000 on the busybox mailing
+ * list, the default configuration, (without
+ * get_last_path_component()) lets the user force use of an
+ * external command by specifying the full (with slashes) filename.
+ * If you enable BB_FEATURE_SH_APPLETS_ALWAYS_WIN, then applets
+ * _aways_ override external commands, so if you want to run
+ * /bin/cat, it will use BusyBox cat even if /bin/cat exists on the
+ * filesystem and is _not_ busybox. Some systems may want this,
+ * most do not. */
+ name = get_last_path_component(name);
+#endif
+ /* Count argc for use in a second... */
+ for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++);
+ optind = 1;
+ debug_printf("running applet %s\n", name);
+ run_applet_by_name(name, argc_l, child->argv);
+ }
+#endif
+ debug_printf("exec of %s\n",child->argv[0]);
+ execvp(child->argv[0],child->argv);
+ perror_msg("couldn't exec: %s",child->argv[0]);
+ _exit(1);
+ } else if (child->group) {
+ debug_printf("runtime nesting to group\n");
+ interactive=0; /* crucial!!!! */
+ rcode = run_list_real(child->group);
+ /* OK to leak memory by not calling free_pipe_list,
+ * since this process is about to exit */
+ _exit(rcode);
+ } else {
+ /* Can happen. See what bash does with ">foo" by itself. */
+ debug_printf("trying to pseudo_exec null command\n");
+ _exit(EXIT_SUCCESS);
+ }
+}
+
+static void insert_bg_job(struct pipe *pi)
+{
+ struct pipe *thejob;
+
+ /* Linear search for the ID of the job to use */
+ pi->jobid = 1;
+ for (thejob = job_list; thejob; thejob = thejob->next)
+ if (thejob->jobid >= pi->jobid)
+ pi->jobid = thejob->jobid + 1;
+
+ /* add thejob to the list of running jobs */
+ if (!job_list) {
+ thejob = job_list = xmalloc(sizeof(*thejob));
+ } else {
+ for (thejob = job_list; thejob->next; thejob = thejob->next) /* nothing */;
+ thejob->next = xmalloc(sizeof(*thejob));
+ thejob = thejob->next;
+ }
+
+ /* physically copy the struct job */
+ memcpy(thejob, pi, sizeof(struct pipe));
+ thejob->next = NULL;
+ thejob->running_progs = thejob->num_progs;
+ thejob->stopped_progs = 0;
+ thejob->text = xmalloc(BUFSIZ); /* cmdedit buffer size */
+
+ //if (pi->progs[0] && pi->progs[0].argv && pi->progs[0].argv[0])
+ {
+ char *bar=thejob->text;
+ char **foo=pi->progs[0].argv;
+ while(foo && *foo) {
+ bar += sprintf(bar, "%s ", *foo++);
+ }
+ }
+
+ /* we don't wait for background thejobs to return -- append it
+ to the list of backgrounded thejobs and leave it alone */
+ printf("[%d] %d\n", thejob->jobid, thejob->progs[0].pid);
+ last_bg_pid = thejob->progs[0].pid;
+ last_jobid = thejob->jobid;
+}
+
+/* remove a backgrounded job */
+static void remove_bg_job(struct pipe *pi)
+{
+ struct pipe *prev_pipe;
+
+ if (pi == job_list) {
+ job_list = pi->next;
+ } else {
+ prev_pipe = job_list;
+ while (prev_pipe->next != pi)
+ prev_pipe = prev_pipe->next;
+ prev_pipe->next = pi->next;
+ }
+ if (job_list)
+ last_jobid = job_list->jobid;
+ else
+ last_jobid = 0;
+
+ pi->stopped_progs = 0;
+ free_pipe(pi, 0);
+ free(pi);
+}
+
+/* Checks to see if any processes have exited -- if they
+ have, figure out why and see if a job has completed */
+static int checkjobs(struct pipe* fg_pipe)
+{
+ int attributes;
+ int status;
+ int prognum = 0;
+ struct pipe *pi;
+ pid_t childpid;
+
+ attributes = WUNTRACED;
+ if (fg_pipe==NULL) {
+ attributes |= WNOHANG;
+ }
+
+ while ((childpid = waitpid(-1, &status, attributes)) > 0) {
+ if (fg_pipe) {
+ int i, rcode = 0;
+ for (i=0; i < fg_pipe->num_progs; i++) {
+ if (fg_pipe->progs[i].pid == childpid) {
+ if (i==fg_pipe->num_progs-1)
+ rcode=WEXITSTATUS(status);
+ (fg_pipe->num_progs)--;
+ return(rcode);
+ }
+ }
+ }
+
+ for (pi = job_list; pi; pi = pi->next) {
+ prognum = 0;
+ while (prognum < pi->num_progs && pi->progs[prognum].pid != childpid) {
+ prognum++;
+ }
+ if (prognum < pi->num_progs)
+ break;
+ }
+
+ if(pi==NULL) {
+ debug_printf("checkjobs: pid %d was not in our list!\n", childpid);
+ continue;
+ }
+
+ if (WIFEXITED(status) || WIFSIGNALED(status)) {
+ /* child exited */
+ pi->running_progs--;
+ pi->progs[prognum].pid = 0;
+
+ if (!pi->running_progs) {
+ printf(JOB_STATUS_FORMAT, pi->jobid, "Done", pi->text);
+ remove_bg_job(pi);
+ }
+ } else {
+ /* child stopped */
+ pi->stopped_progs++;
+ pi->progs[prognum].is_stopped = 1;
+
+#if 0
+ /* Printing this stuff is a pain, since it tends to
+ * overwrite the prompt an inconveinient moments. So
+ * don't do that. */
+ if (pi->stopped_progs == pi->num_progs) {
+ printf("\n"JOB_STATUS_FORMAT, pi->jobid, "Stopped", pi->text);
+ }
+#endif
+ }
+ }
+
+ if (childpid == -1 && errno != ECHILD)
+ perror_msg("waitpid");
+
+ /* move the shell to the foreground */
+ //if (interactive && tcsetpgrp(shell_terminal, getpgid(0)))
+ // perror_msg("tcsetpgrp-2");
+ return -1;
+}
+
+/* Figure out our controlling tty, checking in order stderr,
+ * stdin, and stdout. If check_pgrp is set, also check that
+ * we belong to the foreground process group associated with
+ * that tty. The value of shell_terminal is needed in order to call
+ * tcsetpgrp(shell_terminal, ...); */
+void controlling_tty(int check_pgrp)
+{
+ pid_t curpgrp;
+
+ if ((curpgrp = tcgetpgrp(shell_terminal = 2)) < 0
+ && (curpgrp = tcgetpgrp(shell_terminal = 0)) < 0
+ && (curpgrp = tcgetpgrp(shell_terminal = 1)) < 0)
+ goto shell_terminal_error;
+
+ if (check_pgrp && curpgrp != getpgid(0))
+ goto shell_terminal_error;
+
+ return;
+
+shell_terminal_error:
+ shell_terminal = -1;
+ return;
+}
+#endif
+/* run_pipe_real() starts all the jobs, but doesn't wait for anything
+ * to finish. See checkjobs().
+ *
+ * return code is normally -1, when the caller has to wait for children
+ * to finish to determine the exit status of the pipe. If the pipe
+ * is a simple builtin command, however, the action is done by the
+ * time run_pipe_real returns, and the exit code is provided as the
+ * return value.
+ *
+ * The input of the pipe is always stdin, the output is always
+ * stdout. The outpipe[] mechanism in BusyBox-0.48 lash is bogus,
+ * because it tries to avoid running the command substitution in
+ * subshell, when that is in fact necessary. The subshell process
+ * now has its stdout directed to the input of the appropriate pipe,
+ * so this routine is noticeably simpler.
+ */
+
+static int run_pipe_real(struct pipe *pi)
+{
+
+ int i;
+#ifndef __PPCBOOT__
+ int nextin, nextout;
+ int pipefds[2]; /* pipefds[0] is for reading */
+ struct child_prog *child;
+ struct built_in_command *x;
+#else
+ int nextin;
+ int flag = 0;
+ struct child_prog *child;
+ cmd_tbl_t *cmdtp;
+#endif
+
+ nextin = 0;
+#ifndef __PPCBOOT__
+ pi->pgrp = -1;
+#endif
+ /* Check if this is a simple builtin (not part of a pipe).
+ * Builtins within pipes have to fork anyway, and are handled in
+ * pseudo_exec. "echo foo | read bar" doesn't work on bash, either.
+ */
+ if (pi->num_progs == 1) child = & (pi->progs[0]);
+#ifndef __PPCBOOT__
+ if (pi->num_progs == 1 && child->group && child->subshell == 0) {
+ int squirrel[] = {-1, -1, -1};
+ int rcode;
+ debug_printf("non-subshell grouping\n");
+ setup_redirects(child, squirrel);
+ /* XXX could we merge code with following builtin case,
+ * by creating a pseudo builtin that calls run_list_real? */
+ rcode = run_list_real(child->group);
+ restore_redirects(squirrel);
+#else
+ if (pi->num_progs == 1 && child->group) {
+ int rcode;
+ debug_printf("non-subshell grouping\n");
+ rcode = run_list_real(child->group);
+#endif
+ return rcode;
+ } else if (pi->num_progs == 1 && pi->progs[0].argv != NULL) {
+ for (i=0; is_assignment(child->argv[i]); i++) { /* nothing */ }
+ if (i!=0 && child->argv[i]==NULL) {
+ /* assignments, but no command: set the local environment */
+ for (i=0; child->argv[i]!=NULL; i++) {
+ /* Ok, this case is tricky. We have to decide if this is a
+ * local variable, or an already exported variable. If it is
+ * already exported, we have to export the new value. If it is
+ * not exported, we need only set this as a local variable.
+ * This junk is all to decide whether or not to export this
+ * variable. */
+ int export_me=0;
+ char *name, *value;
+ name = xstrdup(child->argv[i]);
+ debug_printf("Local environment set: %s\n", name);
+ value = strchr(name, '=');
+ if (value)
+ *value=0;
+ if ( get_local_var(name)) {
+ export_me=1;
+ }
+ free(name);
+ set_local_var(child->argv[i], export_me);
+ }
+ return EXIT_SUCCESS; /* don't worry about errors in set_local_var() yet */
+ }
+#ifndef __PPCBOOT__
+ for (x = bltins; x->cmd; x++) {
+ if (strcmp(child->argv[i], x->cmd) == 0 ) {
+
+ int squirrel[] = {-1, -1, -1};
+ int rcode;
+ if (x->function == builtin_exec && child->argv[i+1]==NULL) {
+ debug_printf("magic exec\n");
+ setup_redirects(child,NULL);
+ return EXIT_SUCCESS;
+ }
+ debug_printf("builtin inline %s\n", child->argv[0]);
+ /* XXX setup_redirects acts on file descriptors, not FILEs.
+ * This is perfect for work that comes after exec().
+ * Is it really safe for inline use? Experimentally,
+ * things seem to work with glibc. */
+ setup_redirects(child, squirrel);
+#else
+ /* Look up command in command table */
+ if ((cmdtp = find_cmd(child->argv[i])) == NULL) {
+ printf ("Unknown command '%s' - try 'help'\n", child->argv[i]);
+ return 1; /* give up after bad command */
+ } else {
+ int rcode;
+#if (CONFIG_COMMANDS & CFG_CMD_BOOTD)
+ /* avoid "bootd" recursion */
+ if (cmdtp->cmd == do_bootd) {
+ if (flag & CMD_FLAG_BOOTD) {
+ printf ("'bootd' recursion detected\n");
+ return 1;
+ }
+ else
+ flag |= CMD_FLAG_BOOTD;
+ }
+#endif /* CFG_CMD_BOOTD */
+ /* found - check max args */
+ if ((child->argc - i) > cmdtp->maxargs) {
+ printf ("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+ }
+#endif
+ for (i=0; is_assignment(child->argv[i]); i++) {
+#ifndef __PPCBOOT__
+ putenv(strdup(child->argv[i]));
+#else
+ set_local_var(child->argv[i], 0);
+#endif
+ }
+ child->argv+=i; /* XXX horrible hack */
+#ifndef __PPCBOOT__
+ rcode = x->function(child);
+#else
+ /* OK - call function to do the command */
+ rcode = (cmdtp->cmd)
+ (cmdtp, BD, flag,child->argc-i,&child->argv[i]);
+#endif
+ child->argv-=i; /* XXX restore hack so free() can work right */
+#ifndef __PPCBOOT__
+ restore_redirects(squirrel);
+#endif
+ return rcode;
+ }
+ }
+#ifndef __PPCBOOT__
+ }
+
+ for (i = 0; i < pi->num_progs; i++) {
+ child = & (pi->progs[i]);
+
+ /* pipes are inserted between pairs of commands */
+ if ((i + 1) < pi->num_progs) {
+ if (pipe(pipefds)<0) perror_msg_and_die("pipe");
+ nextout = pipefds[1];
+ } else {
+ nextout=1;
+ pipefds[0] = -1;
+ }
+
+ /* XXX test for failed fork()? */
+ if (!(child->pid = fork())) {
+ /* Set the handling for job control signals back to the default. */
+ signal(SIGINT, SIG_DFL);
+ signal(SIGQUIT, SIG_DFL);
+ signal(SIGTERM, SIG_DFL);
+ signal(SIGTSTP, SIG_DFL);
+ signal(SIGTTIN, SIG_DFL);
+ signal(SIGTTOU, SIG_DFL);
+ signal(SIGCHLD, SIG_DFL);
+
+ close_all();
+
+ if (nextin != 0) {
+ dup2(nextin, 0);
+ close(nextin);
+ }
+ if (nextout != 1) {
+ dup2(nextout, 1);
+ close(nextout);
+ }
+ if (pipefds[0]!=-1) {
+ close(pipefds[0]); /* opposite end of our output pipe */
+ }
+
+ /* Like bash, explicit redirects override pipes,
+ * and the pipe fd is available for dup'ing. */
+ setup_redirects(child,NULL);
+
+ if (interactive && pi->followup!=PIPE_BG) {
+ /* If we (the child) win the race, put ourselves in the process
+ * group whose leader is the first process in this pipe. */
+ if (pi->pgrp < 0) {
+ pi->pgrp = getpid();
+ }
+ if (setpgid(0, pi->pgrp) == 0) {
+ tcsetpgrp(2, pi->pgrp);
+ }
+ }
+
+ pseudo_exec(child);
+ }
+
+
+ /* put our child in the process group whose leader is the
+ first process in this pipe */
+ if (pi->pgrp < 0) {
+ pi->pgrp = child->pid;
+ }
+ /* Don't check for errors. The child may be dead already,
+ * in which case setpgid returns error code EACCES. */
+ setpgid(child->pid, pi->pgrp);
+
+ if (nextin != 0)
+ close(nextin);
+ if (nextout != 1)
+ close(nextout);
+
+ /* If there isn't another process, nextin is garbage
+ but it doesn't matter */
+ nextin = pipefds[0];
+ }
+#endif
+ return -1;
+}
+
+static int run_list_real(struct pipe *pi)
+{
+ int rcode=0;
+ int if_code=0, next_if_code=0; /* need double-buffer to handle elif */
+ reserved_style rmode, skip_more_in_this_rmode=RES_XXXX;
+ for (;pi;pi=pi->next) {
+ rmode = pi->r_mode;
+ debug_printf("rmode=%d if_code=%d next_if_code=%d skip_more=%d\n", rmode, if_code, next_if_code, skip_more_in_this_rmode);
+ if (rmode == skip_more_in_this_rmode) continue;
+ skip_more_in_this_rmode = RES_XXXX;
+ if (rmode == RES_THEN || rmode == RES_ELSE) if_code = next_if_code;
+ if (rmode == RES_THEN && if_code) continue;
+ if (rmode == RES_ELSE && !if_code) continue;
+ if (rmode == RES_ELIF && !if_code) continue;
+ if (pi->num_progs == 0) continue;
+ rcode = run_pipe_real(pi);
+ debug_printf("run_pipe_real returned %d\n",rcode);
+#ifndef __PPCBOOT__
+ if (rcode!=-1) {
+ /* We only ran a builtin: rcode was set by the return value
+ * of run_pipe_real(), and we don't need to wait for anything. */
+ } else if (pi->followup==PIPE_BG) {
+ /* XXX check bash's behavior with nontrivial pipes */
+ /* XXX compute jobid */
+ /* XXX what does bash do with attempts to background builtins? */
+ insert_bg_job(pi);
+ rcode = EXIT_SUCCESS;
+ } else {
+ if (interactive) {
+ /* move the new process group into the foreground */
+ if (tcsetpgrp(shell_terminal, pi->pgrp) && errno != ENOTTY)
+ perror_msg("tcsetpgrp-3");
+ rcode = checkjobs(pi);
+ /* move the shell to the foreground */
+ if (tcsetpgrp(shell_terminal, getpgid(0)) && errno != ENOTTY)
+ perror_msg("tcsetpgrp-4");
+ } else {
+ rcode = checkjobs(pi);
+ }
+ debug_printf("checkjobs returned %d\n",rcode);
+ }
+#endif
+ last_return_code=rcode;
+ if ( rmode == RES_IF || rmode == RES_ELIF )
+ next_if_code=rcode; /* can be overwritten a number of times */
+ if ( (rcode==EXIT_SUCCESS && pi->followup==PIPE_OR) ||
+ (rcode!=EXIT_SUCCESS && pi->followup==PIPE_AND) )
+ skip_more_in_this_rmode=rmode;
+#ifndef __PPCBOOT__
+ checkjobs(NULL);
+#endif
+ }
+ return rcode;
+}
+
+/* broken, of course, but OK for testing */
+static char *indenter(int i)
+{
+ static char blanks[]=" ";
+ return &blanks[sizeof(blanks)-i-1];
+}
+
+/* return code is the exit status of the pipe */
+static int free_pipe(struct pipe *pi, int indent)
+{
+ char **p;
+ struct child_prog *child;
+#ifndef __PPCBOOT__
+ struct redir_struct *r, *rnext;
+#endif
+ int a, i, ret_code=0;
+ char *ind = indenter(indent);
+#ifndef __PPCBOOT__
+ if (pi->stopped_progs > 0)
+ return ret_code;
+ final_printf("%s run pipe: (pid %d)\n",ind,getpid());
+#endif
+ for (i=0; i<pi->num_progs; i++) {
+ child = &pi->progs[i];
+ final_printf("%s command %d:\n",ind,i);
+ if (child->argv) {
+ for (a=0,p=child->argv; *p; a++,p++) {
+ final_printf("%s argv[%d] = %s\n",ind,a,*p);
+ }
+#ifndef __PPCBOOT__
+ globfree(&child->glob_result);
+#else
+ for (a = child->argc;a >= 0;a--) {
+ free(child->argv[a]);
+ }
+ free(child->argv);
+ child->argc = 0;
+#endif
+ child->argv=NULL;
+ } else if (child->group) {
+#ifndef __PPCBOOT__
+ final_printf("%s begin group (subshell:%d)\n",ind, child->subshell);
+#endif
+ ret_code = free_pipe_list(child->group,indent+3);
+ final_printf("%s end group\n",ind);
+ } else {
+ final_printf("%s (nil)\n",ind);
+ }
+#ifndef __PPCBOOT__
+ for (r=child->redirects; r; r=rnext) {
+
+ final_printf("%s redirect %d%s", ind, r->fd, redir_table[r->type].descrip);
+
+ if (r->dup == -1) {
+ /* guard against the case >$FOO, where foo is unset or blank */
+ if (r->word.gl_pathv) {
+ final_printf(" %s\n", *r->word.gl_pathv);
+ globfree(&r->word);
+ }
+ } else {
+ final_printf("&%d\n", r->dup);
+ }
+ rnext=r->next;
+ free(r);
+ }
+ child->redirects=NULL;
+#endif
+ }
+ free(pi->progs); /* children are an array, they get freed all at once */
+ pi->progs=NULL;
+ return ret_code;
+}
+
+static int free_pipe_list(struct pipe *head, int indent)
+{
+ int rcode=0; /* if list has no members */
+ struct pipe *pi, *next;
+ char *ind = indenter(indent);
+ for (pi=head; pi; pi=next) {
+ final_printf("%s pipe reserved mode %d\n", ind, pi->r_mode);
+ rcode = free_pipe(pi, indent);
+ final_printf("%s pipe followup code %d\n", ind, pi->followup);
+ next=pi->next;
+ pi->next=NULL;
+ free(pi);
+ }
+ return rcode;
+}
+
+/* Select which version we will use */
+static int run_list(struct pipe *pi)
+{
+ int rcode=0;
+#ifndef __PPCBOOT__
+ if (fake_mode==0) {
+#endif
+ rcode = run_list_real(pi);
+#ifndef __PPCBOOT__
+ }
+#endif
+ /* free_pipe_list has the side effect of clearing memory
+ * In the long run that function can be merged with run_list_real,
+ * but doing that now would hobble the debugging effort. */
+ free_pipe_list(pi,0);
+ return rcode;
+}
+
+/* The API for glob is arguably broken. This routine pushes a non-matching
+ * string into the output structure, removing non-backslashed backslashes.
+ * If someone can prove me wrong, by performing this function within the
+ * original glob(3) api, feel free to rewrite this routine into oblivion.
+ * Return code (0 vs. GLOB_NOSPACE) matches glob(3).
+ * XXX broken if the last character is '\\', check that before calling.
+ */
+#ifndef __PPCBOOT__
+static int globhack(const char *src, int flags, glob_t *pglob)
+{
+ int cnt=0, pathc;
+ const char *s;
+ char *dest;
+ for (cnt=1, s=src; s && *s; s++) {
+ if (*s == '\\') s++;
+ cnt++;
+ }
+ dest = malloc(cnt);
+ if (!dest) return GLOB_NOSPACE;
+ if (!(flags & GLOB_APPEND)) {
+ pglob->gl_pathv=NULL;
+ pglob->gl_pathc=0;
+ pglob->gl_offs=0;
+ pglob->gl_offs=0;
+ }
+ pathc = ++pglob->gl_pathc;
+ pglob->gl_pathv = realloc(pglob->gl_pathv, (pathc+1)*sizeof(*pglob->gl_pathv));
+ if (pglob->gl_pathv == NULL) return GLOB_NOSPACE;
+ pglob->gl_pathv[pathc-1]=dest;
+ pglob->gl_pathv[pathc]=NULL;
+ for (s=src; s && *s; s++, dest++) {
+ if (*s == '\\') s++;
+ *dest = *s;
+ }
+ *dest='\0';
+ return 0;
+}
+
+/* XXX broken if the last character is '\\', check that before calling */
+static int glob_needed(const char *s)
+{
+ for (; *s; s++) {
+ if (*s == '\\') s++;
+ if (strchr("*[?",*s)) return 1;
+ }
+ return 0;
+}
+
+#if 0
+static void globprint(glob_t *pglob)
+{
+ int i;
+ debug_printf("glob_t at %p:\n", pglob);
+ debug_printf(" gl_pathc=%d gl_pathv=%p gl_offs=%d gl_flags=%d\n",
+ pglob->gl_pathc, pglob->gl_pathv, pglob->gl_offs, pglob->gl_flags);
+ for (i=0; i<pglob->gl_pathc; i++)
+ debug_printf("pglob->gl_pathv[%d] = %p = %s\n", i,
+ pglob->gl_pathv[i], pglob->gl_pathv[i]);
+}
+#endif
+static int xglob(o_string *dest, int flags, glob_t *pglob)
+{
+ int gr;
+
+ /* short-circuit for null word */
+ /* we can code this better when the debug_printf's are gone */
+ if (dest->length == 0) {
+ if (dest->nonnull) {
+ /* bash man page calls this an "explicit" null */
+ gr = globhack(dest->data, flags, pglob);
+ debug_printf("globhack returned %d\n",gr);
+ } else {
+ return 0;
+ }
+ } else if (glob_needed(dest->data)) {
+ gr = glob(dest->data, flags, NULL, pglob);
+ debug_printf("glob returned %d\n",gr);
+ if (gr == GLOB_NOMATCH) {
+ /* quote removal, or more accurately, backslash removal */
+ gr = globhack(dest->data, flags, pglob);
+ debug_printf("globhack returned %d\n",gr);
+ }
+ } else {
+ gr = globhack(dest->data, flags, pglob);
+ debug_printf("globhack returned %d\n",gr);
+ }
+ if (gr == GLOB_NOSPACE)
+ error_msg_and_die("out of memory during glob");
+ if (gr != 0) { /* GLOB_ABORTED ? */
+ error_msg("glob(3) error %d",gr);
+ }
+ /* globprint(glob_target); */
+ return gr;
+}
+#endif
+/* This is used to get/check local shell variables */
+static char *get_local_var(const char *s)
+{
+ struct variables *cur;
+
+ if (!s)
+ return NULL;
+ for (cur = top_vars; cur; cur=cur->next)
+ if(strcmp(cur->name, s)==0)
+ return cur->value;
+ return NULL;
+}
+
+/* This is used to set local shell variables
+ flg_export==0 if only local (not exporting) variable
+ flg_export==1 if "new" exporting environ
+ flg_export>1 if current startup environ (not call putenv()) */
+static int set_local_var(const char *s, int flg_export)
+{
+ char *name, *value;
+ int result=0;
+ struct variables *cur;
+
+ name=strdup(s);
+
+ /* Assume when we enter this function that we are already in
+ * NAME=VALUE format. So the first order of business is to
+ * split 's' on the '=' into 'name' and 'value' */
+ value = strchr(name, '=');
+ if (value==0 && ++value==0) {
+ free(name);
+ return -1;
+ }
+ *value++ = 0;
+
+ for(cur = top_vars; cur; cur = cur->next) {
+ if(strcmp(cur->name, name)==0)
+ break;
+ }
+
+ if(cur) {
+ if(strcmp(cur->value, value)==0) {
+ if(flg_export>0 && cur->flg_export==0)
+ cur->flg_export=flg_export;
+ else
+ result++;
+ } else {
+ if(cur->flg_read_only) {
+ error_msg("%s: readonly variable", name);
+ result = -1;
+ } else {
+ if(flg_export>0 || cur->flg_export>1)
+ cur->flg_export=1;
+ free(cur->value);
+
+ cur->value = strdup(value);
+ }
+ }
+ } else {
+ cur = malloc(sizeof(struct variables));
+ if(!cur) {
+ result = -1;
+ } else {
+ cur->name = strdup(name);
+ if(cur->name == 0) {
+ free(cur);
+ result = -1;
+ } else {
+ struct variables *bottom = top_vars;
+ cur->value = strdup(value);
+ cur->next = 0;
+ cur->flg_export = flg_export;
+ cur->flg_read_only = 0;
+ while(bottom->next) bottom=bottom->next;
+ bottom->next = cur;
+ }
+ }
+ }
+#ifndef __PPCBOOT__
+ if(result==0 && cur->flg_export==1) {
+ *(value-1) = '=';
+ result = putenv(name);
+ } else {
+#endif
+ free(name);
+#ifndef __PPCBOOT__
+ if(result>0) /* equivalent to previous set */
+ result = 0;
+ }
+#endif
+ return result;
+}
+#ifndef __PPCBOOT__
+static void unset_local_var(const char *name)
+{
+ struct variables *cur;
+
+ if (name) {
+ for (cur = top_vars; cur; cur=cur->next) {
+ if(strcmp(cur->name, name)==0)
+ break;
+ }
+ if(cur!=0) {
+ struct variables *next = top_vars;
+ if(cur->flg_read_only) {
+ error_msg("%s: readonly variable", name);
+ return;
+ } else {
+ if(cur->flg_export)
+ unsetenv(cur->name);
+ free(cur->name);
+ free(cur->value);
+ while (next->next != cur)
+ next = next->next;
+ next->next = cur->next;
+ }
+ free(cur);
+ }
+ }
+}
+#endif
+static int is_assignment(const char *s)
+{
+ if (s==NULL || !isalpha(*s)) return 0;
+ ++s;
+ while(isalnum(*s) || *s=='_') ++s;
+ return *s=='=';
+}
+#ifndef __PPCBOOT__
+/* the src parameter allows us to peek forward to a possible &n syntax
+ * for file descriptor duplication, e.g., "2>&1".
+ * Return code is 0 normally, 1 if a syntax error is detected in src.
+ * Resource errors (in xmalloc) cause the process to exit */
+static int setup_redirect(struct p_context *ctx, int fd, redir_type style,
+ struct in_str *input)
+{
+ struct child_prog *child=ctx->child;
+ struct redir_struct *redir = child->redirects;
+ struct redir_struct *last_redir=NULL;
+
+ /* Create a new redir_struct and drop it onto the end of the linked list */
+ while(redir) {
+ last_redir=redir;
+ redir=redir->next;
+ }
+ redir = xmalloc(sizeof(struct redir_struct));
+ redir->next=NULL;
+ redir->word.gl_pathv=NULL;
+ if (last_redir) {
+ last_redir->next=redir;
+ } else {
+ child->redirects=redir;
+ }
+
+ redir->type=style;
+ redir->fd= (fd==-1) ? redir_table[style].default_fd : fd ;
+
+ debug_printf("Redirect type %d%s\n", redir->fd, redir_table[style].descrip);
+
+ /* Check for a '2>&1' type redirect */
+ redir->dup = redirect_dup_num(input);
+ if (redir->dup == -2) return 1; /* syntax error */
+ if (redir->dup != -1) {
+ /* Erik had a check here that the file descriptor in question
+ * is legit; I postpone that to "run time"
+ * A "-" representation of "close me" shows up as a -3 here */
+ debug_printf("Duplicating redirect '%d>&%d'\n", redir->fd, redir->dup);
+ } else {
+ /* We do _not_ try to open the file that src points to,
+ * since we need to return and let src be expanded first.
+ * Set ctx->pending_redirect, so we know what to do at the
+ * end of the next parsed word.
+ */
+ ctx->pending_redirect = redir;
+ }
+ return 0;
+}
+#endif
+struct pipe *new_pipe(void) {
+ struct pipe *pi;
+ pi = xmalloc(sizeof(struct pipe));
+ pi->num_progs = 0;
+ pi->progs = NULL;
+ pi->next = NULL;
+ pi->followup = 0; /* invalid */
+ return pi;
+}
+
+static void initialize_context(struct p_context *ctx)
+{
+ ctx->pipe=NULL;
+#ifndef __PPCBOOT__
+ ctx->pending_redirect=NULL;
+#endif
+ ctx->child=NULL;
+ ctx->list_head=new_pipe();
+ ctx->pipe=ctx->list_head;
+ ctx->w=RES_NONE;
+ ctx->stack=NULL;
+#ifdef __PPCBOOT__
+ ctx->old_flag=0;
+#endif
+ done_command(ctx); /* creates the memory for working child */
+}
+
+/* normal return is 0
+ * if a reserved word is found, and processed, return 1
+ * should handle if, then, elif, else, fi, for, while, until, do, done.
+ * case, function, and select are obnoxious, save those for later.
+ */
+int reserved_word(o_string *dest, struct p_context *ctx)
+{
+ struct reserved_combo {
+ char *literal;
+ int code;
+ long flag;
+ };
+ /* Mostly a list of accepted follow-up reserved words.
+ * FLAG_END means we are done with the sequence, and are ready
+ * to turn the compound list into a command.
+ * FLAG_START means the word must start a new compound list.
+ */
+ static struct reserved_combo reserved_list[] = {
+ { "if", RES_IF, FLAG_THEN | FLAG_START },
+ { "then", RES_THEN, FLAG_ELIF | FLAG_ELSE | FLAG_FI },
+ { "elif", RES_ELIF, FLAG_THEN },
+ { "else", RES_ELSE, FLAG_FI },
+ { "fi", RES_FI, FLAG_END },
+#ifndef __PPCBOOT__
+ { "for", RES_FOR, FLAG_DO | FLAG_START },
+ { "while", RES_WHILE, FLAG_DO | FLAG_START },
+ { "until", RES_UNTIL, FLAG_DO | FLAG_START },
+ { "do", RES_DO, FLAG_DONE },
+ { "done", RES_DONE, FLAG_END }
+#endif
+ };
+ struct reserved_combo *r;
+ for (r=reserved_list;
+#define NRES sizeof(reserved_list)/sizeof(struct reserved_combo)
+ r<reserved_list+NRES; r++) {
+ if (strcmp(dest->data, r->literal) == 0) {
+ debug_printf("found reserved word %s, code %d\n",r->literal,r->code);
+ if (r->flag & FLAG_START) {
+ struct p_context *new = xmalloc(sizeof(struct p_context));
+ debug_printf("push stack\n");
+ *new = *ctx; /* physical copy */
+ initialize_context(ctx);
+ ctx->stack=new;
+ } else if ( ctx->w == RES_NONE || ! (ctx->old_flag & (1<<r->code))) {
+ syntax();
+ ctx->w = RES_SNTX;
+ b_reset (dest);
+ return 1;
+ }
+ ctx->w=r->code;
+ ctx->old_flag = r->flag;
+ if (ctx->old_flag & FLAG_END) {
+ struct p_context *old;
+ debug_printf("pop stack\n");
+ old = ctx->stack;
+ old->child->group = ctx->list_head;
+#ifndef __PPCBOOT__
+ old->child->subshell = 0;
+#endif
+ *ctx = *old; /* physical copy */
+ free(old);
+ }
+ b_reset (dest);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* normal return is 0.
+ * Syntax or xglob errors return 1. */
+static int done_word(o_string *dest, struct p_context *ctx)
+{
+ struct child_prog *child=ctx->child;
+#ifndef __PPCBOOT__
+ glob_t *glob_target;
+ int gr, flags = 0;
+#else
+ char *str;
+ int argc;
+#endif
+
+ debug_printf("done_word: %s %p\n", dest->data, child);
+ if (dest->length == 0 && !dest->nonnull) {
+ debug_printf(" true null, ignored\n");
+ return 0;
+ }
+#ifndef __PPCBOOT__
+ if (ctx->pending_redirect) {
+ glob_target = &ctx->pending_redirect->word;
+ } else {
+#endif
+ if (child->group) {
+ syntax();
+ return 1; /* syntax error, groups and arglists don't mix */
+ }
+ if (!child->argv) {
+ debug_printf("checking %s for reserved-ness\n",dest->data);
+ if (reserved_word(dest,ctx)) return ctx->w==RES_SNTX;
+ }
+#ifndef __PPCBOOT__
+ glob_target = &child->glob_result;
+ if (child->argv) flags |= GLOB_APPEND;
+#else
+ str = malloc((strlen(dest->data) + 1));
+ if (!str) return 1;
+ if ( child->argv == NULL) {
+ child->argc=0;
+ }
+ argc = ++child->argc;
+ child->argv = realloc(child->argv, (argc+1)*sizeof(*child->argv));
+ if (child->argv == NULL) return 1;
+ child->argv[argc-1]=str;
+ child->argv[argc]=NULL;
+ strcpy(str,dest->data);
+#endif
+#ifndef __PPCBOOT__
+ }
+ gr = xglob(dest, flags, glob_target);
+ if (gr != 0) return 1;
+#endif
+ b_reset(dest);
+#ifndef __PPCBOOT__
+ if (ctx->pending_redirect) {
+ ctx->pending_redirect=NULL;
+ if (glob_target->gl_pathc != 1) {
+ error_msg("ambiguous redirect");
+ return 1;
+ }
+ } else {
+ child->argv = glob_target->gl_pathv;
+ }
+#endif
+ return 0;
+}
+
+/* The only possible error here is out of memory, in which case
+ * xmalloc exits. */
+static int done_command(struct p_context *ctx)
+{
+ /* The child is really already in the pipe structure, so
+ * advance the pipe counter and make a new, null child.
+ * Only real trickiness here is that the uncommitted
+ * child structure, to which ctx->child points, is not
+ * counted in pi->num_progs. */
+ struct pipe *pi=ctx->pipe;
+ struct child_prog *prog=ctx->child;
+
+ if (prog && prog->group == NULL
+ && prog->argv == NULL
+#ifndef __PPCBOOT__
+ && prog->redirects == NULL) {
+#else
+ ) {
+#endif
+ debug_printf("done_command: skipping null command\n");
+ return 0;
+ } else if (prog) {
+ pi->num_progs++;
+ debug_printf("done_command: num_progs incremented to %d\n",pi->num_progs);
+ } else {
+ debug_printf("done_command: initializing\n");
+ }
+ pi->progs = xrealloc(pi->progs, sizeof(*pi->progs) * (pi->num_progs+1));
+ prog = pi->progs + pi->num_progs;
+#ifndef __PPCBOOT__
+ prog->redirects = NULL;
+#endif
+ prog->argv = NULL;
+#ifndef __PPCBOOT__
+ prog->is_stopped = 0;
+#endif
+ prog->group = NULL;
+#ifndef __PPCBOOT__
+ prog->glob_result.gl_pathv = NULL;
+ prog->family = pi;
+#endif
+ ctx->child=prog;
+ /* but ctx->pipe and ctx->list_head remain unchanged */
+ return 0;
+}
+
+static int done_pipe(struct p_context *ctx, pipe_style type)
+{
+ struct pipe *new_p;
+ done_command(ctx); /* implicit closure of previous command */
+ debug_printf("done_pipe, type %d\n", type);
+ ctx->pipe->followup = type;
+ ctx->pipe->r_mode = ctx->w;
+ new_p=new_pipe();
+ ctx->pipe->next = new_p;
+ ctx->pipe = new_p;
+ ctx->child = NULL;
+ done_command(ctx); /* set up new pipe to accept commands */
+ return 0;
+}
+#ifndef __PPCBOOT__
+/* peek ahead in the in_str to find out if we have a "&n" construct,
+ * as in "2>&1", that represents duplicating a file descriptor.
+ * returns either -2 (syntax error), -1 (no &), or the number found.
+ */
+static int redirect_dup_num(struct in_str *input)
+{
+ int ch, d=0, ok=0;
+ ch = b_peek(input);
+ if (ch != '&') return -1;
+
+ b_getch(input); /* get the & */
+ ch=b_peek(input);
+ if (ch == '-') {
+ b_getch(input);
+ return -3; /* "-" represents "close me" */
+ }
+ while (isdigit(ch)) {
+ d = d*10+(ch-'0');
+ ok=1;
+ b_getch(input);
+ ch = b_peek(input);
+ }
+ if (ok) return d;
+
+ error_msg("ambiguous redirect");
+ return -2;
+}
+
+/* If a redirect is immediately preceded by a number, that number is
+ * supposed to tell which file descriptor to redirect. This routine
+ * looks for such preceding numbers. In an ideal world this routine
+ * needs to handle all the following classes of redirects...
+ * echo 2>foo # redirects fd 2 to file "foo", nothing passed to echo
+ * echo 49>foo # redirects fd 49 to file "foo", nothing passed to echo
+ * echo -2>foo # redirects fd 1 to file "foo", "-2" passed to echo
+ * echo 49x>foo # redirects fd 1 to file "foo", "49x" passed to echo
+ * A -1 output from this program means no valid number was found, so the
+ * caller should use the appropriate default for this redirection.
+ */
+static int redirect_opt_num(o_string *o)
+{
+ int num;
+
+ if (o->length==0) return -1;
+ for(num=0; num<o->length; num++) {
+ if (!isdigit(*(o->data+num))) {
+ return -1;
+ }
+ }
+ /* reuse num (and save an int) */
+ num=atoi(o->data);
+ b_reset(o);
+ return num;
+}
+
+FILE *generate_stream_from_list(struct pipe *head)
+{
+ FILE *pf;
+#if 1
+ int pid, channel[2];
+ if (pipe(channel)<0) perror_msg_and_die("pipe");
+ pid=fork();
+ if (pid<0) {
+ perror_msg_and_die("fork");
+ } else if (pid==0) {
+ close(channel[0]);
+ if (channel[1] != 1) {
+ dup2(channel[1],1);
+ close(channel[1]);
+ }
+#if 0
+#define SURROGATE "surrogate response"
+ write(1,SURROGATE,sizeof(SURROGATE));
+ _exit(run_list(head));
+#else
+ _exit(run_list_real(head)); /* leaks memory */
+#endif
+ }
+ debug_printf("forked child %d\n",pid);
+ close(channel[1]);
+ pf = fdopen(channel[0],"r");
+ debug_printf("pipe on FILE *%p\n",pf);
+#else
+ free_pipe_list(head,0);
+ pf=popen("echo surrogate response","r");
+ debug_printf("started fake pipe on FILE *%p\n",pf);
+#endif
+ return pf;
+}
+
+/* this version hacked for testing purposes */
+/* return code is exit status of the process that is run. */
+static int process_command_subs(o_string *dest, struct p_context *ctx, struct in_str *input, int subst_end)
+{
+ int retcode;
+ o_string result=NULL_O_STRING;
+ struct p_context inner;
+ FILE *p;
+ struct in_str pipe_str;
+ initialize_context(&inner);
+
+ /* recursion to generate command */
+ retcode = parse_stream(&result, &inner, input, subst_end);
+ if (retcode != 0) return retcode; /* syntax error or EOF */
+ done_word(&result, &inner);
+ done_pipe(&inner, PIPE_SEQ);
+ b_free(&result);
+
+ p=generate_stream_from_list(inner.list_head);
+ if (p==NULL) return 1;
+ mark_open(fileno(p));
+ setup_file_in_str(&pipe_str, p);
+
+ /* now send results of command back into original context */
+ retcode = parse_stream(dest, ctx, &pipe_str, '\0');
+ /* XXX In case of a syntax error, should we try to kill the child?
+ * That would be tough to do right, so just read until EOF. */
+ if (retcode == 1) {
+ while (b_getch(&pipe_str)!=EOF) { /* discard */ };
+ }
+
+ debug_printf("done reading from pipe, pclose()ing\n");
+ /* This is the step that wait()s for the child. Should be pretty
+ * safe, since we just read an EOF from its stdout. We could try
+ * to better, by using wait(), and keeping track of background jobs
+ * at the same time. That would be a lot of work, and contrary
+ * to the KISS philosophy of this program. */
+ mark_closed(fileno(p));
+ retcode=pclose(p);
+ free_pipe_list(inner.list_head,0);
+ debug_printf("pclosed, retcode=%d\n",retcode);
+ /* XXX this process fails to trim a single trailing newline */
+ return retcode;
+}
+
+static int parse_group(o_string *dest, struct p_context *ctx,
+ struct in_str *input, int ch)
+{
+ int rcode, endch=0;
+ struct p_context sub;
+ struct child_prog *child = ctx->child;
+ if (child->argv) {
+ syntax();
+ return 1; /* syntax error, groups and arglists don't mix */
+ }
+ initialize_context(&sub);
+ switch(ch) {
+ case '(': endch=')'; child->subshell=1; break;
+ case '{': endch='}'; break;
+ default: syntax(); /* really logic error */
+ }
+ rcode=parse_stream(dest,&sub,input,endch);
+ done_word(dest,&sub); /* finish off the final word in the subcontext */
+ done_pipe(&sub, PIPE_SEQ); /* and the final command there, too */
+ child->group = sub.list_head;
+ return rcode;
+ /* child remains "open", available for possible redirects */
+}
+#endif
+
+/* basically useful version until someone wants to get fancier,
+ * see the bash man page under "Parameter Expansion" */
+static void lookup_param(o_string *dest, struct p_context *ctx, o_string *src)
+{
+ const char *p=NULL;
+#ifndef __PPCBOOT__
+ if (src->data) {
+ p = getenv(src->data);
+ if (!p)
+#endif
+ p = get_local_var(src->data);
+#ifndef __PPCBOOT__
+ }
+#endif
+ if (p) parse_string(dest, ctx, p); /* recursion */
+ b_free(src);
+}
+
+/* return code: 0 for OK, 1 for syntax error */
+static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *input)
+{
+#ifndef __PPCBOOT__
+ int i, advance=0;
+#else
+ int advance=0;
+#endif
+ o_string alt=NULL_O_STRING;
+#ifndef __PPCBOOT__
+ char sep[]=" ";
+#endif
+ int ch = input->peek(input); /* first character after the $ */
+ debug_printf("handle_dollar: ch=%c\n",ch);
+ if (isalpha(ch)) {
+ while(ch=b_peek(input),isalnum(ch) || ch=='_') {
+ b_getch(input);
+ b_addchr(&alt,ch);
+ }
+ lookup_param(dest, ctx, &alt);
+#ifndef __PPCBOOT__
+ } else if (isdigit(ch)) {
+ i = ch-'0'; /* XXX is $0 special? */
+ if (i<global_argc) {
+ parse_string(dest, ctx, global_argv[i]); /* recursion */
+ }
+ advance = 1;
+#endif
+ } else switch (ch) {
+#ifndef __PPCBOOT__
+ case '$':
+ b_adduint(dest,getpid());
+ advance = 1;
+ break;
+ case '!':
+ if (last_bg_pid > 0) b_adduint(dest, last_bg_pid);
+ advance = 1;
+ break;
+#endif
+ case '?':
+ b_adduint(dest,last_return_code);
+ advance = 1;
+ break;
+#ifndef __PPCBOOT__
+ case '#':
+ b_adduint(dest,global_argc ? global_argc-1 : 0);
+ advance = 1;
+ break;
+#endif
+ case '{':
+ b_getch(input);
+ /* XXX maybe someone will try to escape the '}' */
+ while(ch=b_getch(input),ch!=EOF && ch!='}') {
+ b_addchr(&alt,ch);
+ }
+ if (ch != '}') {
+ syntax();
+ return 1;
+ }
+ lookup_param(dest, ctx, &alt);
+ break;
+#ifndef __PPCBOOT__
+ case '(':
+ b_getch(input);
+ process_command_subs(dest, ctx, input, ')');
+ break;
+ case '*':
+ sep[0]=ifs[0];
+ for (i=1; i<global_argc; i++) {
+ parse_string(dest, ctx, global_argv[i]);
+ if (i+1 < global_argc) parse_string(dest, ctx, sep);
+ }
+ break;
+ case '@':
+ case '-':
+ case '_':
+ /* still unhandled, but should be eventually */
+ error_msg("unhandled syntax: $%c",ch);
+ return 1;
+ break;
+#endif
+ default:
+ b_addqchr(dest,'$',dest->quote);
+ }
+ /* Eat the character if the flag was set. If the compiler
+ * is smart enough, we could substitute "b_getch(input);"
+ * for all the "advance = 1;" above, and also end up with
+ * a nice size-optimized program. Hah! That'll be the day.
+ */
+ if (advance) b_getch(input);
+ return 0;
+}
+
+int parse_string(o_string *dest, struct p_context *ctx, const char *src)
+{
+ struct in_str foo;
+ setup_string_in_str(&foo, src);
+ return parse_stream(dest, ctx, &foo, '\0');
+}
+
+/* return code is 0 for normal exit, 1 for syntax error */
+int parse_stream(o_string *dest, struct p_context *ctx,
+ struct in_str *input, int end_trigger)
+{
+ unsigned int ch, m;
+#ifndef __PPCBOOT__
+ int redir_fd;
+ redir_type redir_style;
+#endif
+ int next;
+
+ /* Only double-quote state is handled in the state variable dest->quote.
+ * A single-quote triggers a bypass of the main loop until its mate is
+ * found. When recursing, quote state is passed in via dest->quote. */
+
+ debug_printf("parse_stream, end_trigger=%d\n",end_trigger);
+ while ((ch=b_getch(input))!=EOF) {
+ m = map[ch];
+ next = (ch == '\n') ? 0 : b_peek(input);
+ debug_printf("parse_stream: ch=%c (%d) m=%d quote=%d\n",
+ ch,ch,m,dest->quote);
+ if (m==0 || ((m==1 || m==2) && dest->quote)) {
+ b_addqchr(dest, ch, dest->quote);
+ } else {
+ if (m==2) { /* unquoted IFS */
+#ifndef __PPCBOOT__
+ done_word(dest, ctx);
+#else
+ if (done_word(dest, ctx)) {
+ return 1;
+ }
+#endif
+ /* If we aren't performing a substitution, treat a newline as a
+ * command separator. */
+ if (end_trigger != '\0' && ch=='\n')
+ done_pipe(ctx,PIPE_SEQ);
+ }
+ if (ch == end_trigger && !dest->quote && ctx->w==RES_NONE) {
+ debug_printf("leaving parse_stream (triggered)\n");
+ return 0;
+ }
+#if 0
+ if (ch=='\n') {
+ /* Yahoo! Time to run with it! */
+ done_pipe(ctx,PIPE_SEQ);
+ run_list(ctx->list_head);
+ initialize_context(ctx);
+ }
+#endif
+ if (m!=2) switch (ch) {
+ case '#':
+ if (dest->length == 0 && !dest->quote) {
+ while(ch=b_peek(input),ch!=EOF && ch!='\n') { b_getch(input); }
+ } else {
+ b_addqchr(dest, ch, dest->quote);
+ }
+ break;
+#ifndef __PPCBOOT__
+ case '\\':
+ if (next == EOF) {
+ syntax();
+ return 1;
+ }
+ b_addqchr(dest, '\\', dest->quote);
+ b_addqchr(dest, b_getch(input), dest->quote);
+ break;
+#endif
+ case '$':
+ if (handle_dollar(dest, ctx, input)!=0) return 1;
+ break;
+#ifndef __PPCBOOT__
+ case '\'':
+ dest->nonnull = 1;
+ while(ch=b_getch(input),ch!=EOF && ch!='\'') {
+ b_addchr(dest,ch);
+ }
+ if (ch==EOF) {
+ syntax();
+ return 1;
+ }
+ break;
+#endif
+ case '"':
+ dest->nonnull = 1;
+ dest->quote = !dest->quote;
+ break;
+#ifndef __PPCBOOT__
+ case '`':
+ process_command_subs(dest, ctx, input, '`');
+ break;
+ case '>':
+ redir_fd = redirect_opt_num(dest);
+ done_word(dest, ctx);
+ redir_style=REDIRECT_OVERWRITE;
+ if (next == '>') {
+ redir_style=REDIRECT_APPEND;
+ b_getch(input);
+ } else if (next == '(') {
+ syntax(); /* until we support >(list) Process Substitution */
+ return 1;
+ }
+ setup_redirect(ctx, redir_fd, redir_style, input);
+ break;
+ case '<':
+ redir_fd = redirect_opt_num(dest);
+ done_word(dest, ctx);
+ redir_style=REDIRECT_INPUT;
+ if (next == '<') {
+ redir_style=REDIRECT_HEREIS;
+ b_getch(input);
+ } else if (next == '>') {
+ redir_style=REDIRECT_IO;
+ b_getch(input);
+ } else if (next == '(') {
+ syntax(); /* until we support <(list) Process Substitution */
+ return 1;
+ }
+ setup_redirect(ctx, redir_fd, redir_style, input);
+ break;
+#endif
+ case ';':
+ done_word(dest, ctx);
+ done_pipe(ctx,PIPE_SEQ);
+ break;
+ case '&':
+ done_word(dest, ctx);
+ if (next=='&') {
+ b_getch(input);
+ done_pipe(ctx,PIPE_AND);
+ } else {
+#ifndef __PPCBOOT__
+ done_pipe(ctx,PIPE_BG);
+#else
+ syntax_err();
+ return 1;
+
+#endif
+ }
+ break;
+ case '|':
+ done_word(dest, ctx);
+ if (next=='|') {
+ b_getch(input);
+ done_pipe(ctx,PIPE_OR);
+ } else {
+ /* we could pick up a file descriptor choice here
+ * with redirect_opt_num(), but bash doesn't do it.
+ * "echo foo 2| cat" yields "foo 2". */
+#ifndef __PPCBOOT__
+ done_command(ctx);
+#else
+ syntax_err();
+ return 1;
+#endif
+ }
+ break;
+#ifndef __PPCBOOT__
+ case '(':
+ case '{':
+ if (parse_group(dest, ctx, input, ch)!=0) return 1;
+ break;
+ case ')':
+ case '}':
+ syntax(); /* Proper use of this character caught by end_trigger */
+ return 1;
+ break;
+#endif
+ default:
+ syntax(); /* this is really an internal logic error */
+ return 1;
+ }
+ }
+ }
+ /* complain if quote? No, maybe we just finished a command substitution
+ * that was quoted. Example:
+ * $ echo "`cat foo` plus more"
+ * and we just got the EOF generated by the subshell that ran "cat foo"
+ * The only real complaint is if we got an EOF when end_trigger != '\0',
+ * that is, we were really supposed to get end_trigger, and never got
+ * one before the EOF. Can't use the standard "syntax error" return code,
+ * so that parse_stream_outer can distinguish the EOF and exit smoothly. */
+ debug_printf("leaving parse_stream (EOF)\n");
+ if (end_trigger != '\0') return -1;
+ return 0;
+}
+
+void mapset(const unsigned char *set, int code)
+{
+ const unsigned char *s;
+ for (s=set; *s; s++) map[*s] = code;
+}
+
+void update_ifs_map(void)
+{
+ /* char *ifs and char map[256] are both globals. */
+ ifs = getenv("IFS");
+ if (ifs == NULL) ifs=" \t\n";
+ /* Precompute a list of 'flow through' behavior so it can be treated
+ * quickly up front. Computation is necessary because of IFS.
+ * Special case handling of IFS == " \t\n" is not implemented.
+ * The map[] array only really needs two bits each, and on most machines
+ * that would be faster because of the reduced L1 cache footprint.
+ */
+ memset(map,0,sizeof(map)); /* most characters flow through always */
+#ifndef __PPCBOOT__
+ mapset("\\$'\"`", 3); /* never flow through */
+ mapset("<>;&|(){}#", 1); /* flow through if quoted */
+#else
+ mapset("$'\"", 3); /* never flow through */
+ mapset(";&|#", 1); /* flow through if quoted */
+#endif
+ mapset(ifs, 2); /* also flow through if quoted */
+}
+
+/* most recursion does not come through here, the exeception is
+ * from builtin_source() */
+int parse_stream_outer(struct in_str *inp)
+{
+
+ struct p_context ctx;
+ o_string temp=NULL_O_STRING;
+ int rcode;
+ do {
+ initialize_context(&ctx);
+ update_ifs_map();
+ inp->promptmode=1;
+ rcode = parse_stream(&temp, &ctx, inp, '\n');
+#ifdef __PPCBOOT__
+ if (rcode != 1) {
+#endif
+ done_word(&temp, &ctx);
+ done_pipe(&ctx,PIPE_SEQ);
+ run_list(ctx.list_head);
+ b_free(&temp);
+#ifdef __PPCBOOT__
+ } else {
+ if (ctx.old_flag != 0) {
+ free(ctx.stack);
+ b_reset(&temp);
+ }
+ inp->p = NULL;
+ free_pipe_list(ctx.list_head,0);
+ b_free(&temp);
+ }
+#endif
+ } while (rcode != -1); /* loop on syntax errors, return on EOF */
+ return 0;
+}
+#ifndef __PPCBOOT__
+static int parse_string_outer(const char *s)
+{
+ struct in_str input;
+ setup_string_in_str(&input, s);
+ return parse_stream_outer(&input);
+}
+#endif
+#ifndef __PPCBOOT__
+static int parse_file_outer(FILE *f)
+#else
+static int parse_file_outer(void)
+#endif
+{
+ int rcode;
+ struct in_str input;
+#ifndef __PPCBOOT__
+ setup_file_in_str(&input, f);
+#else
+ setup_file_in_str(&input);
+#endif
+ rcode = parse_stream_outer(&input);
+ return rcode;
+}
+#ifdef __PPCBOOT__
+
+int ppcboot_hush_start(bd_t *bd)
+{
+ extern bd_t *BD;
+
+ BD = bd;
+ parse_file_outer();
+ return 1;
+}
+#endif
+#ifndef __PPCBOOT__
+/* Make sure we have a controlling tty. If we get started under a job
+ * aware app (like bash for example), make sure we are now in charge so
+ * we don't fight over who gets the foreground */
+static void setup_job_control()
+{
+ static pid_t shell_pgrp;
+ /* Loop until we are in the foreground. */
+ while (tcgetpgrp (shell_terminal) != (shell_pgrp = getpgrp ()))
+ kill (- shell_pgrp, SIGTTIN);
+
+ /* Ignore interactive and job-control signals. */
+ signal(SIGINT, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+ signal(SIGTERM, SIG_IGN);
+ signal(SIGTSTP, SIG_IGN);
+ signal(SIGTTIN, SIG_IGN);
+ signal(SIGTTOU, SIG_IGN);
+ signal(SIGCHLD, SIG_IGN);
+
+ /* Put ourselves in our own process group. */
+ setsid();
+ shell_pgrp = getpid ();
+ setpgid (shell_pgrp, shell_pgrp);
+
+ /* Grab control of the terminal. */
+ tcsetpgrp(shell_terminal, shell_pgrp);
+}
+
+int hush_main(int argc, char **argv)
+{
+ int opt;
+ FILE *input;
+ char **e = environ;
+
+ /* XXX what should these be while sourcing /etc/profile? */
+ global_argc = argc;
+ global_argv = argv;
+
+ /* (re?) initialize globals. Sometimes hush_main() ends up calling
+ * hush_main(), therefore we cannot rely on the BSS to zero out this
+ * stuff. Reset these to 0 every time. */
+ ifs = NULL;
+ /* map[] is taken care of with call to update_ifs_map() */
+ fake_mode = 0;
+ interactive = 0;
+ close_me_head = NULL;
+ last_bg_pid = 0;
+ job_list = NULL;
+ last_jobid = 0;
+
+ /* Initialize some more globals to non-zero values */
+ set_cwd();
+#ifdef BB_FEATURE_COMMAND_EDITING
+ cmdedit_set_initial_prompt();
+#else
+ PS1 = NULL;
+#endif
+ PS2 = "> ";
+
+ /* initialize our shell local variables with the values
+ * currently living in the environment */
+ if (e) {
+ for (; *e; e++)
+ set_local_var(*e, 2); /* without call putenv() */
+ }
+
+ last_return_code=EXIT_SUCCESS;
+
+
+ if (argv[0] && argv[0][0] == '-') {
+ debug_printf("\nsourcing /etc/profile\n");
+ if ((input = fopen("/etc/profile", "r")) != NULL) {
+ mark_open(fileno(input));
+ parse_file_outer(input);
+ mark_closed(fileno(input));
+ fclose(input);
+ }
+ }
+ input=stdin;
+
+ while ((opt = getopt(argc, argv, "c:xif")) > 0) {
+ switch (opt) {
+ case 'c':
+ {
+ global_argv = argv+optind;
+ global_argc = argc-optind;
+ opt = parse_string_outer(optarg);
+ goto final_return;
+ }
+ break;
+ case 'i':
+ interactive++;
+ break;
+ case 'f':
+ fake_mode++;
+ break;
+ default:
+#ifndef BB_VER
+ fprintf(stderr, "Usage: sh [FILE]...\n"
+ " or: sh -c command [args]...\n\n");
+ exit(EXIT_FAILURE);
+#else
+ show_usage();
+#endif
+ }
+ }
+ /* A shell is interactive if the `-i' flag was given, or if all of
+ * the following conditions are met:
+ * no -c command
+ * no arguments remaining or the -s flag given
+ * standard input is a terminal
+ * standard output is a terminal
+ * Refer to Posix.2, the description of the `sh' utility. */
+ if (argv[optind]==NULL && input==stdin &&
+ isatty(fileno(stdin)) && isatty(fileno(stdout))) {
+ interactive++;
+ }
+
+ debug_printf("\ninteractive=%d\n", interactive);
+ if (interactive) {
+ /* Looks like they want an interactive shell */
+ fprintf(stdout, "\nhush -- the humble shell v0.01 (testing)\n\n");
+ setup_job_control();
+ }
+
+ if (argv[optind]==NULL) {
+ opt=parse_file_outer(stdin);
+ goto final_return;
+ }
+
+ debug_printf("\nrunning script '%s'\n", argv[optind]);
+ global_argv = argv+optind;
+ global_argc = argc-optind;
+ input = xfopen(argv[optind], "r");
+ opt = parse_file_outer(input);
+
+#ifdef BB_FEATURE_CLEAN_UP
+ fclose(input);
+ if (cwd && cwd != unknown)
+ free((char*)cwd);
+ {
+ struct variables *cur, *tmp;
+ for(cur = top_vars; cur; cur = tmp) {
+ tmp = cur->next;
+ if (!cur->flg_read_only) {
+ free(cur->name);
+ free(cur->value);
+ free(cur);
+ }
+ }
+ }
+#endif
+
+final_return:
+ return(opt?opt:last_return_code);
+}
+#endif
+#endif /* CFG_HUSH_PARSER */
+/****************************************************************************/
kgdb_breakpoint(bd_ptr, 0, 0);
}
-void
+int
do_kgdb(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
printf("Entering KGDB mode via exception handler...\n\n");
kgdb_breakpoint(bd, argc - 1, argv + 1);
printf("\nReturned from KGDB mode\n");
+ return 0;
}
#else
#include <cmd_boot.h> /* for do_reset() prototype */
#endif
+#ifdef CFG_HUSH_PARSER
+int ppcboot_hush_start(bd_t *bd);
+#endif
+
static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen);
static int parse_line (char *, char *[]);
#if (CONFIG_BOOTDELAY >= 0)
void main_loop(bd_t *bd)
{
+#ifndef CFG_HUSH_PARSER
static char lastcommand[CFG_CBSIZE] = { 0, };
int len;
int rc = 1;
int flag;
+#endif
#if (CONFIG_BOOTDELAY >= 0)
char *s;
/*
* Main Loop for Monitor Command Processing
*/
+#ifdef CFG_HUSH_PARSER
+ ppcboot_hush_start(bd);
+ /* This point is never reached */
+ for (;;);
+#else
for (;;) {
#ifdef CONFIG_BOOT_RETRY_TIME
if (rc >= 0) {
lastcommand[0] = 0;
}
}
+#endif /*CFG_HUSH_PARSER*/
}
/***************************************************************************
/****************************************************************************/
#if (CONFIG_COMMANDS & CFG_CMD_RUN)
-void do_run (cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char *argv[])
+int do_run (cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char *argv[])
{
int i;
+ int rcode = 1;
if (argc < 2) {
printf ("Usage:\n%s\n", cmdtp->usage);
- return;
+ return 1;
}
for (i=1; i<argc; ++i) {
- run_command (getenv (argv[i]), bd, flag);
+ if (run_command (getenv (argv[i]), bd, flag) != -1) rcode = 1;
}
+ if (rcode == i) return 0;
+ return rcode;
}
#endif
/*------------------------------------------------------------------- */
-void do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
ulong msr, addr;
addr = CFG_MONITOR_BASE - sizeof (ulong);
#endif
((void (*)(void ))addr)();
+ return 1;
}
/* ------------------------------------------------------------------------- */
-void
+int
do_reset(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
ulong msr, addr;
addr = CFG_MONITOR_BASE - sizeof (ulong);
#endif
((void (*)(void ))addr)();
+ return 1;
}
return (j >= TOUT_LOOP) ? I2CERR_TIMEOUT : 0;
}
-void
+int
i2c_read(uchar *addr, int alen, uchar *buffer, int len)
{
i2c_state_t state;
rc = i2c_send(&state, *addr, 0, I2CF_START_COND, alen - 1, addr + 1);
if (rc != 0) {
printf("i2c_read: i2c_send failed (%d)\n", rc);
- return;
+ return 1;
}
rc = i2c_receive(&state, *addr, 0, I2CF_STOP_COND, len, buffer);
if (rc != 0) {
printf("i2c_read: i2c_receive failed (%d)\n", rc);
- return;
+ return 1;
}
rc = i2c_doio(&state);
if (rc != 0) {
printf("i2c_read: i2c_doio failed (%d)\n", rc);
- return;
+ return 1;
}
+ return 0;
}
-void
+int
i2c_write(uchar *addr, int alen, uchar *buffer, int len)
{
i2c_state_t state;
rc = i2c_send(&state, *addr, 0, I2CF_START_COND, alen - 1, addr + 1);
if (rc != 0) {
printf("i2c_write: first i2c_send failed (%d)\n", rc);
- return;
+ return 1;
}
rc = i2c_send(&state, 0, 0, I2CF_STOP_COND, len, buffer);
if (rc != 0) {
printf("i2c_write: second i2c_send failed (%d)\n", rc);
- return;
+ return 1;
}
rc = i2c_doio(&state);
if (rc != 0) {
printf("i2c_write: i2c_doio failed (%d)\n", rc);
- return;
+ return 1;
}
+ return 0;
}
uchar
* capable of reading `len' sequential bytes; no
* checking is doen here
*/
-void i2c_read (uchar *addr, int alen, uchar *buffer, int len)
+int i2c_read (uchar *addr, int alen, uchar *buffer, int len)
{
uchar *ap = addr;
*buffer++ = read_byte (len==0);
}
send_stop ();
+ return (0); /* No error handling yet */
}
-void i2c_write (uchar *addr, int alen, uchar *buffer, int len)
+int i2c_write (uchar *addr, int alen, uchar *buffer, int len)
{
uchar *ap = addr;
write_byte (*buffer++);
}
send_stop ();
+ return (0); /* No error handling yet */
}
uchar i2c_reg_read (uchar i2c_addr, uchar reg)
/* ------------------------------------------------------------------------- */
-void do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
ulong msr, addr;
addr = CFG_MONITOR_BASE - sizeof (ulong);
#endif
((void (*)(void ))addr)();
-
+ return 1;
}
/* ------------------------------------------------------------------------- */
return (j >= TOUT_LOOP) ? I2CERR_TIMEOUT : 0;
}
-void
+int
i2c_read(uchar *addr, int alen, uchar *buffer, int len)
{
i2c_state_t state;
rc = i2c_send(&state, *addr, 0, I2CF_START_COND, alen - 1, addr + 1);
if (rc != 0) {
printf("i2c_read: i2c_send failed (%d)\n", rc);
- return;
+ return 1;
}
rc = i2c_receive(&state, *addr, 0, I2CF_STOP_COND, len, buffer);
if (rc != 0) {
printf("i2c_read: i2c_receive failed (%d)\n", rc);
- return;
+ return 1;
}
rc = i2c_doio(&state);
if (rc != 0) {
printf("i2c_read: i2c_doio failed (%d)\n", rc);
- return;
+ return 1;
}
+ return 0;
}
-void
+int
i2c_write(uchar *addr, int alen, uchar *buffer, int len)
{
i2c_state_t state;
rc = i2c_send(&state, *addr, 0, I2CF_START_COND, alen - 1, addr + 1);
if (rc != 0) {
printf("i2c_write: first i2c_send failed (%d)\n", rc);
- return;
+ return 1;
}
rc = i2c_send(&state, 0, 0, I2CF_STOP_COND, len, buffer);
if (rc != 0) {
printf("i2c_write: second i2c_send failed (%d)\n", rc);
- return;
+ return 1;
}
rc = i2c_doio(&state);
if (rc != 0) {
printf("i2c_write: i2c_doio failed (%d)\n", rc);
- return;
+ return 1;
}
+ return 0;
}
uchar
* capable of reading `len' sequential bytes; no
* checking is done here
*/
-void i2c_read (uchar *addr, int alen, uchar *buffer, int len)
+int i2c_read (uchar *addr, int alen, uchar *buffer, int len)
{
uchar *ap = addr;
*buffer++ = read_byte (len==0);
}
send_stop ();
+ return (0); /* No error handling yet */
}
-void i2c_write (uchar *addr, int alen, uchar *buffer, int len)
+int i2c_write (uchar *addr, int alen, uchar *buffer, int len)
{
uchar *ap = addr;
write_byte (*buffer++);
}
send_stop ();
+ return (0); /* No error handling yet */
}
uchar i2c_reg_read (uchar i2c_addr, uchar reg)
#if (CONFIG_COMMANDS & CFG_CMD_PCI)
-void
+int
do_pciinfo(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
int bus_no = 0;
}
pciinfo(bus_no);
+ return 0;
}
/* ------------------------------------------------------------------------- */
-void do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+int do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
/*
* Initiate system reset in debug control register DBCR
*/
__asm__ __volatile__(" lis 3, 0x3000
mtspr 0x3f2, 3");
+ return 1;
}
}
-void i2c_read (uchar *addr, int alen, uchar *buffer, int len)
+int i2c_read (uchar *addr, int alen, uchar *buffer, int len)
{
-
+ int rcode = 0;
+
if ((alen != 2) && (alen != 3)) {
printf ("I2C read: addr len %d not supported\n", alen);
- return;
+ return 1;
}
- i2c_send (addr[0] << 1, alen-1, addr+1);
- i2c_receive ((addr[0] << 1) | 0x01, len, buffer);
+ if (i2c_send (addr[0] << 1, alen-1, addr+1) != 0) rcode = 1;
+ if (i2c_receive ((addr[0] << 1) | 0x01, len, buffer) != 0) rcode = 1;
+ return rcode;
}
#ifndef CFG_EEPROM_PAGE_WRITE_ENABLE
-void i2c_write (uchar *addr, int alen, uchar *buffer, int len)
+int i2c_write (uchar *addr, int alen, uchar *buffer, int len)
{
uchar xbuf[3];
unsigned short paddr;
udelay(100);
}
}
- return;
+ return 0;
}
paddr=(addr[1]<<8)+addr[2];
udelay(100);
}
}
- return;
+ return 0;
}
printf ("I2C write: addr len %d not supported\n", alen);
+ return 1;
}
#else /* CFG_EEPROM_PAGE_WRITE_ENABLE */
-void i2c_write (uchar *addr, int alen, uchar *buffer, int len)
+int i2c_write (uchar *addr, int alen, uchar *buffer, int len)
{
/* buffer for one page + addresses */
uchar wbuffer[(1<<CFG_EEPROM_PAGE_WRITE_BITS)+2];
while (i2c_send (addr[0] << 1, len+1, wbuffer) != 0) {
udelay(100);
}
- return;
+ return 0;
}
if (alen == 3) {
/* fill in the address first */
while (i2c_send (addr[0] << 1, len+2, wbuffer) != 0) {
udelay(100);
}
- return;
+ return 0;
}
printf ("I2C write: addr len %d not supported\n", alen);
+ return 1;
}
#endif /* CFG_EEPROM_PAGE_WRITE_ENABLE */
* irqinfo - print information about PCI devices
*
*/
-void
+int
do_irqinfo(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
int vec;
vec, (ulong)irq_vecs[vec].handler, (ulong)irq_vecs[vec].arg,
irq_vecs[vec].count);
}
+ return 0;
}
"A valid autoscr header must be present\n" \
),
-void autoscript (bd_t *bd, ulong addr);
-void do_autoscript (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int autoscript (bd_t *bd, ulong addr);
+int do_autoscript (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#else
"bootvx - Boot vxWorks from an ELF image\n", \
" [address] - load address of vxWorks ELF image.\n" \
),
-
-extern void do_bedbug_dis (cmd_tbl_t *, bd_t *, int, int, char *[]);
-extern void do_bedbug_asm (cmd_tbl_t *, bd_t *, int, int, char *[]);
-extern void do_bedbug_break (cmd_tbl_t *, bd_t *, int, int, char *[]);
-extern void do_bedbug_continue (cmd_tbl_t *, bd_t *, int, int, char *[]);
-extern void do_bedbug_step (cmd_tbl_t *, bd_t *, int, int, char *[]);
-extern void do_bedbug_next (cmd_tbl_t *, bd_t *, int, int, char *[]);
-extern void do_bedbug_stack (cmd_tbl_t *, bd_t *, int, int, char *[]);
-extern void do_bedbug_rdump (cmd_tbl_t *, bd_t *, int, int, char *[]);
-
-extern void do_bootelf (cmd_tbl_t *, bd_t *, int, int, char *[]);
-extern void do_bootvx (cmd_tbl_t *, bd_t *, int, int, char *[]);
+extern int do_bedbug_dis (cmd_tbl_t *, bd_t *, int, int, char *[]);
+extern int do_bedbug_asm (cmd_tbl_t *, bd_t *, int, int, char *[]);
+extern int do_bedbug_break (cmd_tbl_t *, bd_t *, int, int, char *[]);
+extern int do_bedbug_continue (cmd_tbl_t *, bd_t *, int, int, char *[]);
+extern int do_bedbug_step (cmd_tbl_t *, bd_t *, int, int, char *[]);
+extern int do_bedbug_next (cmd_tbl_t *, bd_t *, int, int, char *[]);
+extern int do_bedbug_stack (cmd_tbl_t *, bd_t *, int, int, char *[]);
+extern int do_bedbug_rdump (cmd_tbl_t *, bd_t *, int, int, char *[]);
+
+extern int do_bootelf (cmd_tbl_t *, bd_t *, int, int, char *[]);
+extern int do_bootvx (cmd_tbl_t *, bd_t *, int, int, char *[]);
/* Supporting routines */
extern int bedbug_puts (const char *);
"bdinfo - print Board Info structure\n", \
NULL \
),
-
-void do_bdinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_bdinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#else
#define CMD_TBL_BDINFO
"addr [arg ...]\n - start application at address 'addr'\n" \
" passing 'arg' as arguments\n" \
),
-
-void do_go (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_go (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#if (CONFIG_COMMANDS & CFG_CMD_LOADS)
#ifdef CFG_LOADS_BAUD_CHANGE
" - load S-Record file over serial line with offset 'off'\n" \
),
#endif /* CFG_LOADS_BAUD_CHANGE */
-
-void do_load_serial (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_load_serial (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#else /* ! CFG_CMD_LOADS */
#define CMD_TBL_LOADS
" - load binary file over serial line" \
" with offset 'off' and baudrate 'baud'\n" \
),
-
-void do_load_serial_bin (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_load_serial_bin (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#else
#define CMD_TBL_LOADB
),
/* Implemented in $(CPU)/cpu.c */
-void do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#endif /* _CMD_BOOT_H */
*/
#ifndef _CMD_BOOTM_H
#define _CMD_BOOTM_H
-
-void do_bootm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_bootm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#define CMD_TBL_BOOTM MK_CMD_TBL_ENTRY( \
"bootm", 5, CFG_MAXARGS, 1, do_bootm, \
),
#if (CONFIG_COMMANDS & CFG_CMD_BOOTD)
-void do_bootd (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_bootd (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#define CMD_TBL_BOOTD MK_CMD_TBL_ENTRY( \
"bootd", 4, 1, 1, do_bootd, \
#endif
#if (CONFIG_COMMANDS & CFG_CMD_IMI)
-void do_iminfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-
+int do_iminfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#define CMD_TBL_IMINFO MK_CMD_TBL_ENTRY( \
"iminfo", 3, CFG_MAXARGS, 1, do_iminfo, \
"iminfo - print header information for application image\n", \
"pic - read and write PIC registers\n", \
"read reg - read PIC register `reg'\n" \
"pic write reg val - write value `val' to PIC register `reg'\n" \
+), MK_CMD_TBL_ENTRY( \
+ "kbd", 3, 1, 1, do_kbd, \
+ "kbd - read keyboard status\n", \
+ NULL \
),
-
-void do_pic (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_pic (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_kbd (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#endif /* CONFIG_LWMON */
/* ----------------------------------------------------------------------------*/
"status - print PUMA status\n" \
"puma load addr len - load PUMA configuration data\n" \
),
-
-void do_puma (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_puma (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#endif /* CONFIG_PCU_E, CONFIG_CCM */
/* ----------------------------------------------------------------------------*/
"pip405 flash floppy [SrcAddr] - updates PPCBOOT with image from floppy\n" \
"pip405 flash mps - updates PPCBOOT with image from MPS\n" \
),
-
-void do_pip405 (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_pip405 (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#endif /* CONFIG_PIP405 */
/* ----------------------------------------------------------------------------*/
"pci9054 info - print EEPROM values\n" \
"pci9054 update - updates EEPROM with default values\n" \
),
-
-void do_pci9054 (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_pci9054 (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#endif /* CONFIG_DASA_SIM */
/* ----------------------------------------------------------------------------*/
" (`type' is either `main' or `mezz' - default `main')\n" \
" Note: the EEPROM write enable jumper must be installed\n" \
),
-
-void do_fpga (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_eecl (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_fpga (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_eecl (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#endif /* CONFIG_HYMOD */
/* ----------------------------------------------------------------------------*/
"L1cmd update - update flash images from host\n" \
"L1cmd boot - nfs or ramboot L1\n" \
),
-void do_crayL1 (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_crayL1 (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#endif /* CONFIG_CRAY405 */
/* ----------------------------------------------------------------------------*/
"[on, off]\n" \
" - enable or disable data (writethrough) cache\n" \
),
-
-void do_icache (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_dcache (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_icache (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_dcache (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#else
#define CMD_TBL_ICACHE
#define CMD_TBL_DCACHE
"coninfo - print console devices and informations\n", \
"" \
),
-
-void do_coninfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_coninfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#else
#define CMD_TBL_CONINFO
"eeprom write addr off cnt\n" \
" - read/write `cnt' bytes at EEPROM offset `off'\n" \
),
-
-void do_eeprom (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-
+int do_eeprom (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#else
#define CMD_TBL_EEPROM
"fdcboot - boot from floppy device\n", \
"loadAddr drive\n" \
),
-void do_fdcboot (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_fdcboot (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#else
#define CMD_TBL_FDC
"protect off bank N\n - make FLASH bank # N writable\n" \
"protect off all\n - make all FLASH banks writable\n" \
),
-
-void do_flinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_flerase(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_protect(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_flinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_flerase(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_protect(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#else
#define CMD_TBL_FLINFO
#define CMD_TBL_FLERASE
" `i2c_addr' and secondary address `sec_addr'\n" \
),
-void do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#else
#define CMD_TBL_I2C
"loadAddr dev:part\n" \
),
-void do_ide (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_diskboot (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_ide (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_diskboot (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#else
#define CMD_TBL_IDE
NULL \
),
-void do_siuinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_memcinfo(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_sitinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_siuinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_memcinfo(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_sitinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#ifdef CONFIG_8260
-void do_icinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_icinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#endif
-void do_carinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_iopinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_dmainfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_fccinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_brginfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_i2cinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_sccinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_smcinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_spiinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_muxinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_siinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_mccinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_carinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_iopinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_dmainfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_fccinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_brginfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_i2cinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_sccinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_smcinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_spiinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_muxinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_siinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_mccinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#else
" example program in the ppcboot examples directory)." \
),
-void do_kgdb (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_kgdb (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#else
#define CMD_TBL_KGDB
#endif
"[start [end [pattern]]]\n" \
" - simple RAM read/write test\n" \
),
-
-void do_mem_md (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_mem_mm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_mem_nm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_mem_mw (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_mem_cp (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_mem_cmp (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_mem_crc (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_mem_base (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_mem_loop (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_mem_mtest (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_mem_md (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_mem_mm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_mem_nm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_mem_mw (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_mem_cp (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_mem_cmp (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_mem_crc (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_mem_base (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_mem_loop (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_mem_mtest (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#else
#define CMD_TBL_MD
mii write <addr> <reg> <data> - write MII PHY <addr> register <reg>\n" \
),
-void do_mii (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_mii (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#else
#define CMD_TBL_MII
),
/* Implemented in $(BOARD)/pci.c */
-void do_pciinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_pciinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#else
#define CMD_TBL_PCIINFO
),
/* Implemented in $(CPU)/interrupts.c */
-void do_irqinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_irqinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#else
#define CMD_TBL_IRQINFO
"bootp - boot image via network using BootP/TFTP protocol\n", \
"[loadAddress] [bootfilename]\n" \
),
-
-void do_bootp (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-
+int do_bootp (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#define CMD_TBL_TFTPB MK_CMD_TBL_ENTRY( \
"tftpboot", 4, 3, 1, do_tftpb, \
"tftpboot- boot image via network using TFTP protocol\n" \
"[loadAddress] [bootfilename]\n" \
),
-
-void do_tftpb (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_tftpb (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#define CMD_TBL_RARPB MK_CMD_TBL_ENTRY( \
"[loadAddress] [bootfilename]\n" \
),
-
-void do_rarpb (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_rarpb (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
#define CMD_TBL_DHCP MK_CMD_TBL_ENTRY( \
"\n" \
),
-
-void do_dhcp (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_dhcp (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#else
#define CMD_TBL_DHCP
#endif /* CFG_CMD_DHCP */
"printenv name ...\n" \
" - print value of environment variable 'name'\n" \
),
-void do_printenv (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_printenv (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#define CMD_TBL_SETENV MK_CMD_TBL_ENTRY( \
"setenv", 6, CFG_MAXARGS, 0, do_setenv, \
"setenv name\n" \
" - delete environment variable 'name'\n" \
),
-void do_setenv (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_setenv (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#if ((CONFIG_COMMANDS & (CFG_CMD_ENV|CFG_CMD_FLASH)) == (CFG_CMD_ENV|CFG_CMD_FLASH))
#define CMD_TBL_SAVEENV MK_CMD_TBL_ENTRY( \
"saveenv - save environment variables to persistent storage\n", \
NULL \
),
-void do_saveenv (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_saveenv (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#else
#define CMD_TBL_SAVEENV
#endif /* CFG_CMD_ENV */
" - display 'message' string and get environment variable 'name'" \
"from stdin (max 'size' chars)\n" \
),
-void do_askenv (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_askenv (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#else
#define CMD_TBL_ASKENV
#endif /* CFG_CMD_ASKENV */
"var [...]\n" \
" - run the commands in the environment variable(s) 'var'\n" \
),
-void do_run (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_run (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#else
#define CMD_TBL_RUN
#endif /* CFG_CMD_RUN */
"pinit off - power off PCMCIA socket\n" \
),
-void do_pinit (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_pinit (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#else
#define CMD_TBL_PINIT
#endif
"reginfo - print register information\n", \
),
-void do_reginfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_reginfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#else
#define CMD_TBL_REGINFO
" - with argument: set the system date & time\n" \
),
-void do_date (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_date (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#else
"loadAddr dev:part\n" \
),
-void do_scsi (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
-void do_scsiboot (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_scsi (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_scsiboot (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
#else
int maxargs; /* maximum number of arguments */
int repeatable; /* autorepeat allowed? */
/* Implementation function */
- void (*cmd)(struct cmd_tbl_s *, bd_t *, int, int, char *[]);
+ int (*cmd)(struct cmd_tbl_s *, bd_t *, int, int, char *[]);
char *usage; /* Usage message (short) */
#ifdef CFG_LONGHELP
char *help; /* Help message (long) */
*/
#define CFG_LONGHELP /* undef to save memory */
#define CFG_PROMPT "=> " /* Monitor Command Prompt */
+#define CFG_HUSH_PARSER /* Hush parse for ppcboot */
+#ifdef CFG_HUSH_PARSER
+#define CFG_PROMPT_HUSH_PS2 "> "
+#endif
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */
#else
* Miscellaneous configurable options
*/
#define CFG_LONGHELP /* undef to save memory */
-#define CFG_PROMPT "=> " /* Monitor Command Prompt */
+#define CFG_PROMPT "=> " /* Monitor Command Prompt */
+
+#define CFG_HUSH_PARSER
+#ifdef CFG_HUSH_PARSER
+#define CFG_PROMPT_HUSH_PS2 "> "
+#endif
+
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
-#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */
+#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */
#else
-#define CFG_CBSIZE 256 /* Console I/O Buffer Size */
+#define CFG_CBSIZE 256 /* Console I/O Buffer Size */
#endif
#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
-#define CFG_MAXARGS 16 /* max number of command args */
+#define CFG_MAXARGS 16 /* max number of command args */
#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */
#define CFG_MEMTEST_START 0x0400000 /* memtest works on */
#define CFG_LOAD_ADDR 0x100000 /* default load address */
-#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */
+#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */
#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
*/
#define CFG_LONGHELP /* undef to save memory */
#define CFG_PROMPT "=> " /* Monitor Command Prompt */
+
+#undef CFG_HUSH_PARSER /* enable "hush" shell */
+#ifdef CFG_HUSH_PARSER
+#define CFG_PROMPT_HUSH_PS2 "> "
+#endif
+
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */
#else
/* Prototypes */
unsigned long flash_init (void);
-void flash_print_info (flash_info_t *);
-void flash_erase (flash_info_t *, int, int);
-void flash_sect_erase (ulong addr_first, ulong addr_last);
-void flash_sect_protect (int flag, ulong addr_first, ulong addr_last);
+void flash_print_info (flash_info_t *);
+int flash_erase (flash_info_t *, int, int);
+int flash_sect_erase (ulong addr_first, ulong addr_last);
+int flash_sect_protect (int flag, ulong addr_first, ulong addr_last);
/* common/flash.c */
void flash_protect (int flag, ulong from, ulong to, flash_info_t *info);
#ifndef _I2C_H_
#define _I2C_H_
-void i2c_read (uchar *addr, int alen, uchar *buffer, int len);
-void i2c_write (uchar *addr, int alen, uchar *buffer, int len);
+int i2c_read (uchar *addr, int alen, uchar *buffer, int len);
+int i2c_write (uchar *addr, int alen, uchar *buffer, int len);
#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC) || \
#ifndef __HAVE_ARCH_STRNLEN
extern __kernel_size_t strnlen(const char *,__kernel_size_t);
#endif
+#ifndef __HAVE_ARCH_STRDUP
+extern char * strdup(const char *);
+#endif
#ifndef __HAVE_ARCH_MEMSET
extern void * memset(void *,int,__kernel_size_t);
defined(CONFIG_HYMOD)
/* $(BOARD)/eeprom.c */
void eeprom_init (void);
-void eeprom_read (unsigned offset, uchar *buffer, unsigned cnt);
-void eeprom_write (unsigned offset, uchar *buffer, unsigned cnt);
+int eeprom_read (unsigned offset, uchar *buffer, unsigned cnt);
+int eeprom_write (unsigned offset, uchar *buffer, unsigned cnt);
# ifdef CONFIG_LWMON
extern uchar pic_read (uchar reg);
extern void pic_write (uchar reg, uchar val);
#ifndef __VERSION_H__
#define __VERSION_H__
-#define PPCBOOT_VERSION "PPCBoot 1.0.6"
+#define PPCBOOT_VERSION "PPCBoot 1.1.0"
#endif /* __VERSION_H__ */
#include <linux/types.h>
#include <linux/string.h>
+#include <malloc.h>
#define __HAVE_ARCH_BCOPY
#define __HAVE_ARCH_MEMCMP
}
#endif
+#ifndef __HAVE_ARCH_STRDUP
+char * strdup(const char *s)
+{
+ char *new;
+
+ if ((s == NULL) ||
+ ((new = malloc (strlen(s) + 1)) == NULL) ) {
+ return NULL;
+ }
+
+ strcpy (new, s);
+ return new;
+}
+#endif
+
#ifndef __HAVE_ARCH_STRSPN
size_t strspn(const char *s, const char *accept)
{