Open Firmware has a concept of environment configuration variables that are used to control the boot flow and other behavior of the firmware. On ppc64 systems, these variables are normally stored in the NVRAM of the machine (as defined in the LoPAPR specification, chapter, “System NVRAM Partition”), so that they are persistent between reboots - at least on real systems. With QEMU, the emulated NVRAM has got to be backed with a real file on the host, of course, to make the contents persistent. This can be done with the parameter -drive if=pflash,file=filename,format=raw of QEMU, for example.

Now, if the backing file via pflash is not used, the contents of the NVRAM can be created by QEMU dynamically. QEMU features a dedicated parameter called -prom-env for setting the configuration variables in NVRAM. This works with all the OpenBIOS based machines in QEMU (like the mac99 or g3beige machine) since a long time already, but since version 2.8 has been released in last December, QEMU now also supports this option for the pseries machine, i.e. it can now also be used to control the boot behavior of the SLOF firmware of an sPAPR guest. So this is a good point in time to have a closer look at this parameter to explain how it can be used with the pseries machine…

The supported environment variables and their values can be listed by typing printenv at the SLOF firmware prompt:

0 > printenv  
---environment variable--------current value-------------default value------
   load-base                   4000                      4000 
   real-mode?                  true                      true
   direct-serial?              false                     false
   use-nvramrc?                false                     false
   selftest-#megs              0                         0 
   security-mode               0                         0 
   security-#badlogins         0                         0 
   screen-#rows                200                       200 
   screen-#columns             200                       200 
   oem-logo?                   false                     false
   oem-logo                    1e762bb0 0                1e762110 0 
   oem-banner?                 false                     false
   fcode-debug?                true                      true
   diag-switch?                false                     false
   boot-command                boot                      boot
   auto-boot?                  false                     true

Many of the configuration variables are either only useful for debugging (like “fcode-debug?”), or even only there without real functionality since the IEEE 1275 standard mandates that they’ve got to be available (like “oem-logo”), but the implementation of the intended functionality did not make much sense in SLOF.

Some other configuration variables are really useful, though. For example, if you want to avoid that SLOF boots automatically (so you can do some things at the firmware prompt before running the OS), you can start QEMU with -prom-env 'auto-boot?=false' to disable the auto-boot feature. Of course you could also hit the “s” key during boot to drop to the firmware prompt, but this can be quite annoying if you’re doing multiple things in parallel and thus you easily miss the very right point in time. Using the configuration variable is much more convenient.

Another very useful trick is that you can execute arbitrary Forth code during the boot process with the -prom-env parameter! The likely obvious way is to use the “nvramrc” variable. For example, if you start QEMU with the parameters -prom-env 'use-nvramrc?=true' -prom-env 'nvramrc=." Hello World!" cr', SLOF will print “Hello World!” during the boot process, followed by a carriage return. But there is another way for executing Forth code, which I personally prefer if I do not have to boot an OS afterwards (since you do not have to set two variables in this case): You can override the boot-command variable, which also contains Forth code. For example using the parameters -prom-env 'boot-command=." Hello World!" cr' will print “Hello World” during the boot process, too, just at a little bit later point in time. This can also be useful to run firmware reboot tests: When you run QEMU with -prom-env 'boot-command=reset-all', the firmware will reboot automatically each time instead of booting an operating system. Or use -prom-env 'boot-command=power-off' to shut down the VM automatically at the end of the firmware boot process.

Something else that bugged me for a long time was the behavior of the input selection in SLOF. When you boot your pseries guest with a VGA graphics card, SLOF always automatically uses the emulated USB keyboard as input device. But if you want to debug the VGA or USB code in the firmware for example, it is much more convenient if you can interact with the firwmare via the serial console (aka. hvterm). So now that QEMU supports the -prom-env parameter for the pseries machine, too, I’ve recently added some code to SLOF that forces the firmware to stay with the serial input instead of switching to the emulated USB keyboard. You can control the behavior now with the “direct-serial?” configuration variable. If you start QEMU with the parameters -nographic -vga std -prom-env 'direct-serial?=true' for example, you can still interact with the firmware in the terminal window even though the firmware detected a graphics card and USB keyboard. (Note: This new feature is currently only available in the development version of SLOF, but it will be part of the SLOF release that will be shipped with QEMU version 2.9)