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's probe() 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's close() 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's open() 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_devices, 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.

QR Code
QR Code soc:2008:mdeck:notes:initialization (generated for current page)