OPAL: Difference between revisions
[unchecked revision] | [unchecked revision] |
No edit summary |
|||
Line 74: | Line 74: | ||
=== External Links === |
=== External Links === |
||
* [https://github.com/streaksu/microski A complete example of a Hello World OS using OPAL] |
|||
* [https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html PowerPC64 SysV API] |
* [https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html PowerPC64 SysV API] |
||
* [https://github.com/open-power/skiboot/tree/master/doc/opal-api 1987 Skiboot's OPAL API documentation] |
* [https://github.com/open-power/skiboot/tree/master/doc/opal-api 1987 Skiboot's OPAL API documentation] |
Revision as of 13:07, 5 November 2020
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:
.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
.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
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.