Hi all

On most modern x86 systems a lot of the silicon init happens as part of
blob (FSP, binaryPI)
or some reference code (AGESA). Very often that silicon init enables or
hides
PCI devices. This means that this code needs to run before coreboot device
enumeration code.
With coreboot's current ramstage state machine running this binary can only
happen as part of
chip_ops->init or with a bootstate hook.

As a quick reminder about the coreboot ramstage state machine:
 *        start
 *          |
 *    BS_PRE_DEVICE
 *          |
 *    BS_DEV_INIT_CHIPS
 *          |
 *    BS_DEV_ENUMERATE
 *          |
         the rest (device resource allocation, device init, ...)

BS_DEV_INIT_CHIPS:
- Call the .init from all the chip_ops from each "chip" once.
  FSP-S loading, configuring and calling is currently set up
  as a monolithic call inside such chip_ops->init. It has a lot of
  callbacks for soc and mainboard and consumes the devicetree in one big
  soc specific function, with little reuse between socs.
  All the silicon configuration can only be put into a monolithic soc
chip_info and is translated
  into FSP UPDs.

BS_DEV_ENUMERATE:
- call static chip_ops->enable_dev on each static device on the devicetree.
On older
  non-RC using code enabling or hiding PCI devices is done here.
- scan the actual hardware (e.g. PCI bus) for what is there. What will be
  found is depends on the params passed to the reference code which will
hide/enable
  devices

Both the monolithic configuration, one big chip_info, and code flow don't
follow coreboot's
state machine philosophy, where the devicetree nodes drive the
configuration process and codeflow.
It would be nicer if device enabling and other configuration would be
structured on a per node basis.
So for instance all the USB configuration options would be below the xhci
device node and
not globally available to all nodes.

Based on a discussion on IRC there are a few options, which are generally
not mutually exclusive or share similar ideas:
1) Split up the DEV_ENUMERATE into a static devicetree part and a scan part.
  In combination with calling FSP between those two parts this would allow
  the chip_ops->enable_dev to be called on each device and so UPD setup
could
  be modularised. This is still rather monolithic as the enable_dev is the
same
  function callback for each device but it could be more modularised
because the
  struct device is passed as an argument.
  So something like:

  switch (dev->path.pci.devfn) {
  case PCI_DEV(0, 0):
         do_something()
  case PCI_DEV(0x1f, 0):
         do_something_else()
  }
  is possible. So this at least removes all the current callbacks.

2) Move devices below separate chips and split up FSP loading, configuring
and calling.
  Then then devicetree looks like this

  chip soc/intel/.../usb
     device ref xhci on end
     register "config_option_1" = "A"
     register "config_option_2" = "B"
  end

  If the FSP loading is separated from the calling, for instance by moving
it earlier in
 a cbmem init hook or bootstate ENTRY hook, then each chip_ops .init could
configure FSP UPDs based.  The calling of FSP can then happen as part of
bootstate EXIT hook.
  A disadvantage here would be that this would add a lot of "chips" which
is not recommended
  for things that are not a separate physical chip.

3) Allow for a per device configuration.
  https://review.coreboot.org/c/coreboot/+/41745 implements this.
  This would easily allow per device configuration without introducing new
chips.

4) Since it is now possible to hook up device ops directly in the devicetree
  we could add a new device specific entry to ops that a new bootstate
executes
  before scanning buses. A enable_dev, but not on the chip_ops level but
device level.
  One thing to note is that scan_bus will not give default PCI ops to
devices anymore
  if ops is !NULL. This can be worked around by setting ops to NULL after
calling this
  new ops on devices where the default pci ops are desirable. Another way
  would be to allow more finegrained control when writing the devicetree
about which ops can be set directly in the devicetree.

It looks like 3 + 4 would be the cleanest, but it should maybe not block
trying out 1 and 2.
The splitting of device specific configuration is possible in 1 and 2 and
migrating to
solutions of 3 and 4 would be rather trivial.

Any thoughts on this?

Arthur
_______________________________________________
coreboot mailing list -- coreboot@coreboot.org
To unsubscribe send an email to coreboot-le...@coreboot.org

Reply via email to