OPAL

From OSDev Wiki
Jump to navigation Jump to search

OPAL (OpenPower Abstraction Layer) is an ongoing project created by IBM in an effort of standardizing the boot environment and low-level services available across POWER systems, it was introduced with POWER8.

These low-level services are meant to be used both in boot and runtime, they consist of a series of calls that can be realized for managing different hardware-related and basic Input/Output tasks, all from getting device trees to flashing devices to a console with read/write capabilities.

Calling the functions

To access an OPAL routine, the system is required to be in big endian mode.

Each OPAL routine has a number associated to it, this number is to be loaded in R0, from there only a trampoline has to be calculated using the OPAL base and entrypoint, passed to the loaded payload in R8 and R9 respectively.

The OPAL routines use the SysV ABI.

A really simple example of a trampoline routine and a hello world using it would be:

.section .text
.align 2
.globl opal_call
opal_call:
	/* OPAL calls must be in big-endian mode */
	/* On call, r0, r3 ... should already be set to the desired values*/
	/* Assume OPAL base is in r13 and the entrypoint in r14 */

	/* Save current MSR in non-volatile r15 */
	mfmsr	%r15
	/* Save return address in non-volatile r16 */
	mflr	%r16

	/* Turn off the LE bit in MSR (ordinarily also do DR, IR and EE) */
	li	%r11, 0x01
	andc	%r11, %r15, %r11

	/* Get address of trampoline */
	bl	.+4
	mflr	%r12 /* 0 */
	addi	%r12, %r12, 28 /* 32 bytes between the mflr and the return */
	mtlr	%r12
	
	/* 12 */
	/* We need a return trampoline to return to little endian mode */
	/* Put the trampoline address in LR, OPAL entry in SRR0, MSR in SRR1 */
	mr %r2, %r13
	mtsrr0 	%r14
	mtsrr1	%r11

	/* 24 */
	/* Do it */
	rfid

	/* 28 */
	/* Trampoline here returns us to LE and restores MSR and LR */
	GO_LITTLE_ENDIAN
	mtmsr	%r15
	mtlr	%r16
	blr

.align 2
.globl main
main:
	li	%r0, 1 /* OPAL_CONSOLE_WRITE */
	li	%r3, 0 /* terminal 0 */
	addi	%r4, %r8, len - here /* ptr to length of string */
	addi	%r5, %r8, str - here /* ptr to string start */
	bl opal_call

.section .data
len:
	/* This value is read by OPAL so it must be big-endian in both modes */
	.long 0x00
	/* byte-universal form of BE .long (strend - str) */
	.byte 0
	.byte 0
	.byte 0
	.byte (strend - str)

str:
	.string "Hello World!\n"
strend:

Function listing

A complete listing can be found here, but this is a list of the most useful functions.

  • OPAL_CEC_POWER_DOWN - Powers down the system.
  • OPAL_CONSOLE_WRITE, OPAL_CONSOLE_READ, OPAL_CONSOLE_FLUSH, OPAL_CONSOLE_WRITE_BUFFER_SPACE - Console management, from printing to reading.
  • OPAL_GET_DEVICE_TREE - Fetching a flattened device tree (FDT) for kernel use.
  • OPAL_START_CPU and OPAL_RETURN_CPU - Secondary CPU management.

See Also

External Links