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