您的位置:首页 > 运维架构 > Linux

marvell pxa2128 uboot/linux kernel fast ethernet development documentary No.2

2013-01-07 17:24 525 查看

1. uboot dhcp's issue analysis

Issue the following command:
# dhcp 0x1100000 serverip:uImage
Error Log:
Marvell>> dhcp 0x1100000 10.66.130.110:uImage

pxa2128-eth Waiting for PHY auto negotiation to complete. done

pxa2128-eth: link up, 100 Mb/s, full duplex

BOOTP broadcast 1

DHCP client bound to address 10.66.130.251

Using pxa2128-eth device

TFTP from server 10.66.130.4; our IP address is 10.66.130.251

Filename 'pxelinux.0'.

Load address: 0x1100000

Loading: #

done

Bytes transferred = 14146 (3742 hex)

Automatic boot of image at addr 0x01100000 ...

Wrong Image Format for dhcp command

ERROR: can't get kernel image!

The image name is changed from uImage topxelinux.0. And the TFTP serverip 10.66.130.4 actually is a DHCP serverip. So TFTP downloads image unsuccessfully! Let's track the code.

1). dhcp command implementation
#if defined(CONFIG_CMD_DHCP)
int do_dhcp (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
return netboot_common(DHCP, cmdtp, argc, argv);
}

U_BOOT_CMD(
dhcp,	3,	1,	do_dhcp,
"boot image via network using DHCP/TFTP protocol",
"[loadAddress] [[hostIPaddr:]bootfilename]"
);
#endif
static int
netboot_common (proto_t proto, cmd_tbl_t *cmdtp, int argc, char * const argv[])
{
char *s;
char *end;
int   rcode = 0;
int   size;
ulong addr;

/* pre-set load_addr */
if ((s = getenv("loadaddr")) != NULL) {
load_addr = simple_strtoul(s, NULL, 16);
}

switch (argc) {
case 1:
break;

case 2:	/*
* Only one arg - accept two forms:
* Just load address, or just boot file name. The latter
* form must be written in a format which can not be
* mis-interpreted as a valid number.
*/
addr = simple_strtoul(argv[1], &end, 16);
if (end == (argv[1] + strlen(argv[1])))
load_addr = addr;
else
copy_filename(BootFile, argv[1], sizeof(BootFile));
break;

case 3:	load_addr = simple_strtoul(argv[1], NULL, 16);  // argc is 3. so this is point.
copy_filename (BootFile, argv[2], sizeof(BootFile));

break;

default:
show_boot_progress (-80);
return cmd_usage(cmdtp);
}

show_boot_progress (80);
if ((size = NetLoop(proto)) < 0) {   // This function is important!
show_boot_progress (-81);
return 1;
}

show_boot_progress (81);
/* NetLoop ok, update environment */
netboot_update_env();   // update the env related to net device.

/* done if no file was loaded (no errors though) */
if (size == 0) {
show_boot_progress (-82);
return 0;
}

/* flush cache */
flush_cache(load_addr, size);

show_boot_progress(82);
rcode = bootm_maybe_autostart(cmdtp, argv[0]);

if (rcode < 0)
show_boot_progress (-83);
else
show_boot_progress (84);
return rcode;
}

Coming into NetLoop, we focus on DHCP:(net.c)
#if defined(CONFIG_CMD_DHCP)
case DHCP:
BootpTry = 0;
NetOurIP = 0;
DhcpRequest();		/* Basically same as BOOTP */
break;
#endif
Now we come into bootp.c, and the function would send out DHCP request using broadcast.
When the DHCP request is done, the function DhcpHandler would be called.
/*
*	Handle DHCP received packets.
*/
static void
DhcpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
unsigned len)
{
Bootp_t *bp = (Bootp_t *)pkt;

debug("DHCPHandler: got packet: (src=%d, dst=%d, len=%d) state: %d\n",
src, dest, len, dhcp_state);

if (BootpCheckPkt(pkt, dest, src, len)) /* Filter out pkts we don't want */
return;

debug("DHCPHandler: got DHCP packet: (src=%d, dst=%d, len=%d) state: %d\n",
src, dest, len, dhcp_state);

switch (dhcp_state) {
case SELECTING:
/*
* Wait an appropriate time for any potential DHCPOFFER packets
* to arrive.  Then select one, and generate DHCPREQUEST response.
* If filename is in format we recognize, assume it is a valid
* OFFER from a server we want.
*/
debug("DHCP: state=SELECTING bp_file: \"%s\"\n", bp->bp_file);
#ifdef CONFIG_SYS_BOOTFILE_PREFIX
if (strncmp(bp->bp_file,
CONFIG_SYS_BOOTFILE_PREFIX,
strlen(CONFIG_SYS_BOOTFILE_PREFIX)) == 0 ) {
#endif	/* CONFIG_SYS_BOOTFILE_PREFIX */

debug("TRANSITIONING TO REQUESTING STATE\n");
dhcp_state = REQUESTING;

if (NetReadLong((ulong*)&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC))
DhcpOptionsProcess((u8 *)&bp->bp_vend[4], bp);

NetSetTimeout(TIMEOUT, BootpTimeout);
DhcpSendRequestPkt(bp);
#ifdef CONFIG_SYS_BOOTFILE_PREFIX
}
#endif	/* CONFIG_SYS_BOOTFILE_PREFIX */

return;
break;
case REQUESTING:
debug("DHCP State: REQUESTING\n");

if ( DhcpMessageType((u8 *)bp->bp_vend) == DHCP_ACK ) {
if (NetReadLong((ulong*)&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC))
DhcpOptionsProcess((u8 *)&bp->bp_vend[4], bp);
BootpCopyNetParams(bp); /* Store net params from reply */
dhcp_state = BOUND;
printf ("DHCP client bound to address %pI4\n", &NetOurIP);

auto_load();
return;
}
break;
case BOUND:
/* DHCP client bound to address */
break;
default:
puts ("DHCP: INVALID STATE\n");
break;
}

}
The function BootpCopyNetParams would handle bootfile and serverip, sometimes issue would be happened here!
So the function should be modified, as follow:
/*
* Copy parameters of interest from BOOTP_REPLY/DHCP_OFFER packet
*/
static void BootpCopyNetParams(Bootp_t *bp)
{
IPaddr_t tmp_ip;

NetCopyIP(&NetOurIP, &bp->bp_yiaddr);
#if !defined(CONFIG_BOOTP_SERVERIP)
NetCopyIP(&tmp_ip, &bp->bp_siaddr);
if (tmp_ip != 0)
NetCopyIP(&NetServerIP, &bp->bp_siaddr);
memcpy (NetServerEther, ((Ethernet_t *)NetRxPacket)->et_src, 6);
#endif
if (strlen(bp->bp_file) > 0 && !BootFile[0]) // If BootFile has no data, then copy
copy_filename (BootFile, bp->bp_file, sizeof(BootFile));

debug("Bootfile: %s\n", BootFile);

/* Propagate to environment:
* don't delete exising entry when BOOTP / DHCP reply does
* not contain a new value
*/
if (*BootFile) {
setenv ("bootfile", BootFile);
}
}


Then make tftp serverip as serverip, not dhcp server ip!

2. Capturing with tcpdump for viewing with Wireshark


D.3. tcpdump: Capturing with tcpdump for viewing with Wireshark

There are occasions when you want to capture packets using tcpdump rather than wireshark, especially when you want to do a remote
capture and do not want the network load associated with running Wireshark remotely (not to mention all the X traffic polluting your capture).
However, the default tcpdump parameters result in a capture file where each packet is truncated, because most versions of tcpdump,
will, by default, only capture the first 68 or 96 bytes of each packet.
To ensure that you capture complete packets, use the following command:
tcpdump -i <interface> -s 65535 -w <some-file>

You will have to specify the correct interface and the name of a file to save into. In addition, you will have to terminate
the capture with ^C when you believe you have captured enough packets.

Note!
tcpdump is not part of the Wireshark distribution. You can get it from: http://www.tcpdump.org for various platforms.

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: