Uboot之tftp流程

 int tftp_download(char *filename, ulong msec_max, int cnt_max, ulong addr)

{

  ...

  TftpRRQTimeoutMSecs = msec_max;   //100

  TftpRRQTimeoutCountMax = cnt_max;  //0

  setenv("netretry", "no");

  load_addr = addr;             //下载到内存的地址

  copy_filename(BootFile, filename, sizeof(BootFile));

  size = NetLoop(TFTP);

  if(size < 0)

    return ERROR;

  else

    flush_cache(addr,size);

  ...

}

int NetLoop(proto_t protocol)

{

  ...

  switch (protocol)
  {

    case TFTP:
      TftpStart();
      break;

    case DHCP:
      BootpTry = 0;
      NetOurIP = 0;
      DhcpRequest(); 
      break;
    case BOOTP:

      BootpTry = 0;
      NetOurIP = 0;
      BootpRequest ();
      break;

    case RARP:
      RarpTry = 0;
      NetOurIP = 0;
      RarpRequest ();
      break;
    case PING:
      PingStart();
      break;
    case NFS:
      NfsStart();
      break;
    case CDP:
      CDPStart();
      break;
    case NETCONS:
      NcStart();
      break;
    case SNTP:
      SntpStart();
      break;
    case DNS:
      DnsStart();
      break;

  }

  ...

}

void TftpStart (void)

{

  ...

  //设置参数

  NetSetTimeout (TftpTimeoutMSecs * CFG_HZ, TftpTimeout);
  NetSetHandler (TftpHandler);

  ...

  //发送

  TftpSend ();

  ...

}

static void TftpSend (void)

{

  ...

  //容错

  //开始组包

  pkt = NetTxPacket + NetEthHdrSize() + IP_HDR_SIZE;

  //针对各种状态组包

  switch (TftpState) 

  {

    case STATE_RRQ:

      xp = pkt;

      s = (ushort *)pkt;
      if(TftpState == STATE_WRQ)
        *s++ = htons(TFTP_WRQ);
      else

        *s++ = htons(TFTP_RRQ);
      pkt = (uchar *)s;
      strcpy ((char *)pkt, tftp_filename);
      pkt += strlen(tftp_filename) + 1;
      strcpy ((char *)pkt, "octet");
      pkt += 5 /*strlen("octet")*/ + 1;
      strcpy ((char *)pkt, "timeout");
      pkt += 7 /*strlen("timeout")*/ + 1;
      sprintf((char *)pkt, "%lu", TftpTimeoutMSecs / 1000);
      pkt += strlen((char *)pkt) + 1;
      memcpy((char *)pkt, "tsize000", 8);
      pkt += 8;
      if(TftpState == STATE_WRQ)
        pkt += sprintf((char *)pkt,"blksize%c%d%c", 0,TftpBlkSizeOption,0);
      else
        pkt += sprintf((char *)pkt,"blksize%c%d%c", 0,TftpBlkSizeOption,0);
      if (!ProhibitMcast && (Bitmap=malloc(Mapsize)) && eth_get_dev()->mcast)
      {
        free(Bitmap);
        Bitmap=NULL;
        pkt += sprintf((char *)pkt,"multicast%c%c",0,0);
      }
      len = pkt - xp;
      break;

    case STATE_WRQ:

      ...

    case STATE_OACK:

      ...

    case STATE_DATA:

      ...

    case STATE_TOO_LARGE:

      ...

    case STATE_BAD_MAGIC:

      ...

    case STATE_ACK:

      ...

  }

  //发送

  NetSendUDPPacket(NetServerEther, TftpServerIP, TftpServerPort, TftpOurPort, len);

}

int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len)

{

  //容错:目标IP 

  //容错:ether 发ARP

  if (memcmp(ether, NetEtherNullAddr, 6) == 0) 

  {

    NetArpWaitPacketIP = dest;
    NetArpWaitPacketMAC = ether;

    pkt = NetArpWaitTxPacket;
    pkt += NetSetEther (pkt, NetArpWaitPacketMAC, PROT_IP);

    NetSetIP (pkt, dest, dport, sport, len);
    memcpy(pkt + IP_HDR_SIZE, (uchar *)NetTxPacket + (pkt - (uchar *)NetArpWaitTxPacket) + IP_HDR_SIZE, len);

    NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE + len;

    NetArpWaitTry = 1;
    NetArpWaitTimerStart = get_timer(0);
    ArpRequest();
    return 1; 

  }

  //容错:time 发ARP

  if (times == 10000)
  {
    times = 0;

    NetArpWaitPacketIP = dest;

    NetArpWaitPacketMAC = ether;

    pkt = NetArpWaitTxPacket;
    pkt += NetSetEther(pkt, NetArpWaitPacketMAC, PROT_IP);

    NetSetIP(pkt, dest, dport, sport, len);
    memcpy(pkt + IP_HDR_SIZE, (uchar *)NetTxPacket + (pkt - (uchar *)NetArpWaitTxPacket) + IP_HDR_SIZE, len);

    NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE + len;

    NetArpWaitTry = 1;
    NetArpWaitTimerStart = get_timer(0);
    ArpRequest();
  }

  //组包发送

  times++;

  pkt = (uchar *)NetTxPacket;

  pkt += NetSetEther (pkt, ether, PROT_IP);
  NetSetIP (pkt, dest, dport, sport, len);
  (void) eth_send(NetTxPacket, (pkt - NetTxPacket) + IP_HDR_SIZE + len);

  ...

}

至此,(void) eth_send(NetTxPacket, (pkt - NetTxPacket) + IP_HDR_SIZE + len);开始转向各个网卡驱动的发送函数。

原文地址:https://www.cnblogs.com/pokerface/p/6770220.html