今天调试BIOS会发生注册ethernet_register_protocol函数里发生注册失败的问题。
内核代码:
/* netman_start_monitor_device - start the monitor device and all protocol handlers for it */
int netman_start_monitor_device(void)
{
if (!ether_device_init(monitor_ether_device)) return FALSE;
PRTRACE2("device started, device:%d\n", monitor_ether_device);
arp_init(monitor_ether_device);
PRTRACE2("ARP initialised, device:%d\n", monitor_ether_device);
ip_init(monitor_ether_device);
PRTRACE2("IP initialised, device:%d\n", monitor_ether_device);
udp_init(monitor_ether_device);
PRTRACE2("UDP initialised, device:%d\n", monitor_ether_device);
device_initialised[monitor_ether_device] = TRUE;
return TRUE;
}
现象:
device started, device:0
Failed to register ethernet protocol 8,6
ARP initialised, device:0
Failed to register ethernet protocol 8,0
IP initialised, device:0
UDP initialised, device:0
Successed to start network.
Waiting for link......
OK!
定位文件</bios/net/ethernet.c>发现:
代码申请的局部变量
static struct
{
int in_use;
ethernet_packet_handler processing_function;
ethernet_protocol_id protocol_id;
void * protocol_data;
} protocol_table[MAX_ETHER_DEVICES][MAX_REGISTERED_ETHERNET_PROTOCOLS];
会发生初始值不为0的情况,导致数据结构使用中发生错误。
C语言规定全局变量和static变量(不管是函数里的还是函数外的)如果不初始化则初值为0,未初始化的和明确初始化为0的全局变量、static变量都会分配在bss段。
解决这个问题,只需要专门在BIOS main函数里初始化BSS段为0,步骤如下:
(1) 查找到代码编译生成的链接规则文件<bios/lds/console.lds0.S>文件,里面可以找到BSS段的内存区间。
(2) 初始化BSS段方法</bios/init/main.c>里添加代码:
void start_kernel(void)
{
#if 1
extern char _edata, _end;
unsigned long pro_len = &_end - &_edata;
memset (&_edata, 0, pro_len);
printk("bss_start: %p\nbss_end: %p\n", &_edata, &_end);
#endif
local_irq_disable();
// omitted
}