blob: 6865ecb06abcec66bcc4e46703b23ab85d501ece [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/
#include <netlib/tftp.h>
#include <netlib/dhcp.h>
#include <netlib/ethernet.h>
#include <netlib/ipv4.h>
#include <rtas.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
int netflash(int argc, char * argv[])
{
char buf[256];
int rc;
int manage_mode = 0;
static int len = 0x800000; //max flash size
char * buffer = NULL;
short arp_failed = 0;
filename_ip_t fn_ip;
int fd_device;
tftp_err_t tftp_err;
char * ptr;
uint8_t own_mac[6];
printf("\n Flasher 1.4 \n");
memset(&fn_ip, 0, sizeof(filename_ip_t));
if (argc == 3 && argv[2][0] == '-' && argv[2][1] == 'c' && argv[2][2] == 0)
manage_mode = 1;
else if (argc == 3 &&
argv[2][0] == '-' && argv[2][1] == 'r' && argv[2][2] == 0)
manage_mode = 1;
else if (argc == 4 &&
argv[2][0] == '-' && argv[2][1] == 'f' && argv[2][2] == 0)
{
manage_mode = 0;
buffer = (char *)strtol(argv[1],0,16);
if ((long)buffer == -1) {
printf(" Bad buffer address. Exiting...\n");
return -1;
}
}
else
{
printf(" Usage: netflash [options] [<filename>]\n");
printf(" Options:\n");
printf(" -f <filename> flash temporary image\n");
printf(" -c commit temporary image\n");
printf(" -r reject temporary image\n");
printf(" Bad arguments. Exiting...\n\n");
return -1;
}
if (manage_mode == 1) {
if (argv[2][1] == 99)
return rtas_ibm_manage_flash(1);
else
return rtas_ibm_manage_flash(0);
}
/* Get mac_addr from device */
printf(" Reading MAC address from device: ");
fd_device = socket(0, 0, 0, (char *) own_mac);
if (fd_device == -1) {
printf("\nE3000: Could not read MAC address\n");
return -100;
}
else if (fd_device == -2) {
printf("\nE3006: Could not initialize network device\n");
return -101;
}
printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
own_mac[0], own_mac[1], own_mac[2],
own_mac[3], own_mac[4], own_mac[5]);
// init ethernet layer
set_mac_address(own_mac);
// identify the BOOTP/DHCP server via broadcasts
// don't do this, when using DHCP !!!
// fn_ip.server_ip = 0xFFFFFFFF;
// memset(fn_ip.server_mac, 0xff, 6);
/* Get ip address for our mac address */
printf(" Requesting IP address via DHCP: ");
arp_failed = dhcp(0, &fn_ip, 30);
if(arp_failed >= 0) {
// reinit network stack
set_ipv4_address(fn_ip.own_ip);
}
if (arp_failed == -1) {
printf("\n DHCP: Could not get ip address\n");
return 1;
}
if (arp_failed == -2) {
sprintf
(buf,"\n ARP request to TFTP server (%d.%d.%d.%d) failed",
((fn_ip.server_ip >> 24) & 0xFF), ((fn_ip.server_ip >> 16) & 0xFF),
((fn_ip.server_ip >> 8) & 0xFF), ( fn_ip.server_ip & 0xFF));
return 1;
}
printf("%d.%d.%d.%d\n",
((fn_ip.own_ip >> 24) & 0xFF), ((fn_ip.own_ip >> 16) & 0xFF),
((fn_ip.own_ip >> 8) & 0xFF), (fn_ip.own_ip & 0xFF));
/* Load file via TFTP into buffer provided by OpenFirmware */
for(ptr = argv[3]; *ptr != 0; ++ptr)
if(*ptr == '\\')
*ptr = '/';
printf(" Requesting file \"%s\" via TFTP\n",argv[3]);
strcpy((char *) fn_ip.filename,argv[3]);
rc = tftp(&fn_ip, (unsigned char*) buffer, len, 20, &tftp_err, 0, 512, 4);
dhcp_send_release();
if (rc > 0)
{
printf (" TFTP: Received %s (%d KBytes)\n", fn_ip.filename, rc/1024);
printf (" Now flashing:\n");
rc = rtas_ibm_update_flash_64((long long)buffer, rc);
return rc;
}
else if (rc == -1)
{
printf (" Tftp: Could not load file %s\n", fn_ip.filename);
return 1;
}
else if (rc == -2)
{
printf (" Tftp: Buffer to small for %s\n", fn_ip.filename);
return 1;
}
else if (rc <= -10 && rc >= -15)
{
printf("\n ICMP ERROR: Destination unreachable: ");
switch(rc) {
case -ICMP_NET_UNREACHABLE-10:
printf("net unreachable");
break;
case -ICMP_HOST_UNREACHABLE-10:
printf("host unreachable");
break;
case -ICMP_PROTOCOL_UNREACHABLE-10:
printf("protocol unreachable");
break;
case -ICMP_PORT_UNREACHABLE-10:
printf("port unreachable");
break;
case -ICMP_FRAGMENTATION_NEEDED-10:
printf("fragmentation needed and DF set");
break;
case -ICMP_SOURCE_ROUTE_FAILED-10:
printf("source route failed");
break;
default:
printf(" UNKNOWN: this should not happen!");
break;
}
printf("\n");
return 1;
}
else if(rc < 0)
printf(" UNKNOWN: rc = %d!", rc);
return 0;
}