Table of Contents
gPXE Network Driver Initialization
What happens when gPXE starts up?
How does a network driver get initialized?
Let's follow the call stack at key points from instantiation.
Reaching probe
- src/core/main.c »
main()
– Entry point. - src/core/init.c »
startup()
- src/core/device.c »
probe_devices()
– Probe buses sequentially. - src/core/device.c »
rootdev_probe()
– Probe this bus. {struct root_device}->driver->probe()
== src/drivers/bus/pci.c »pcibus_probe()
– Probe PCI devices sequentially.- src/drivers/bus/pci.c »
pci_probe()
– Probe this device. {struct pci_driver}->probe()
== src/drivers/net/NAME.c »NAME_probe()
– The network driver'sprobe()
routine is finally reached.
At this point netdev_init()
associates netdev with driver functions.
register_netdev()
adds to the device list.
We return up the call stack to main().
Reaching close
- src/core/main.c »
main()
- src/usr/autoboot.c »
autoboot()
– Boot network devices sequentially. - src/usr/autoboot.c »
close_all_netdevs()
- src/usr/ifmgmt.c »
ifclose()
- src/net/netdevice.c »
netdev_close()
{struct net_device}->op->close()
== src/drivers/net/NAME.c »NAME_close()
– The network driver'sclose()
routine is reached.
All network devices are closed before attempting to boot each network device.
We return up the call stack to autoboot().
Reaching open
- src/usr/autoboot.c »
autoboot()
– Still booting network devices sequentially. - src/usr/autoboot.c »
netboot()
– Boot this network device - src/usr/ifmgmt.c »
ifopen()
- src/net/netdevice.c »
netdev_open()
{struct net_device}->op->open()
== src/drivers/net/NAME.c »NAME_open()
– The network driver'sopen()
routine is reached.
At this point transmit and receive are enabled.
root_device and pci_device structs
Both struct root_device
and struct pci_device
have a special function in gPXE. Bus drivers are root_device
s, thus there is one for PCI, ISA, etc. PCI devices are self-explanatory. Both root_device
and pci_device
structs are defined within their respective driver code. These structs hold function pointers to essential interface routines, such as probe()
and remove()
. The __pci_driver
and __root_driver
tags cause the drivers to be added to a list of modules, resulting in their probe()
routines being called during initialization.