HOWTO: Add a Platform

Platforms are created as subdirectories of src/platforms. They require a few pieces:

  • A configure.py file, to describe the build.
  • A linker script, linker.ld.
  • One or more assembly files, to implement some platform-specific functions.
  • Optionally, some number of Forth files, to add code to the root process.

The configure.py file used to define a platform relies on the currently undocumented build system. You only need a small subset of the available functionality to define most platforms, though. An example is:

# This corresponds to the kernel/configure.py file.
import stahl_build.kernel as kernel

# This defines the root subcomponent of the component for the directory.
# It depends on the kernel.common component, which all platforms should.
@configure("root", ["kernel.common"])
def configure(ctx):
	# We call out to the kernel configuration helper.
	kernel.configure(
		# We pass the build context.
		ctx,
		# The name of our platform. This should be the same as
		# the name of the directory the platform is defined in.
		"my-cool-target",
		# The kernel subcomponents to include. This should always
		# include "common", as well as whatever drivers are useful
		# for the platform. The "debug" subcomponent is useful when
		# initially bringing up a target; it enables self-tests,
		# and in the future may enable other goodies.
		["common", "debug", "drivers/gicv3", "drivers/psci"],
	)

For an example of a more complicated platform, see the js platform. It injects custom Forth code, and builds extra files. Note that since it depends on external files, it also requires them to be passed in via default.nix.

Assembly Files

The assembly files currently need to implement the following functions:

platform.init

Inputs

  • x0: A pointer to the FDT.

Outputs

None.

Side Effects

Can trash x0-x15.

Simplest Implementation

.global platform.init
platform.init:
	ret

platform.debug_print

Prints a string for debugging purposes.

Inputs

  • x0: The address of the string to print
  • x1: The length of the string to print

Outputs

None.

Side Effects

Can trash x0-x15.

Simplest Implementation

.global platform.debug_print
platform.debug_print:
	ret

platform.idle

Waits until an interrupt is received.

This is overridable in case extra actions need to be taken, for example power management functionality.

Inputs

None.

Outputs

None.

Side Effects

Can trash x0-x15.

Simplest Implementation

.global platform.idle
platform.idle:
	wfi
	ret