qemu/pc-bios/vof/ci.c
Alexey Kardashevskiy 21bde1ecb6 spapr: Fix implementation of Open Firmware client interface
This addresses the comments from v22.

The functional changes are (the VOF ones need retesting with Pegasos2):

(VOF) setprop will start failing if the machine class callback
did not handle it;
(VOF) unit addresses are lowered in path_offset();
(SPAPR) /chosen/bootargs is initialized from kernel_cmdline if
the client did not change it.

Fixes: 5c991e5d4378 ("spapr: Implement Open Firmware client interface")
Cc: BALATON Zoltan <balaton@eik.bme.hu>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Message-Id: <20210708065625.548396-1-aik@ozlabs.ru>
Tested-by: BALATON Zoltan <balaton@eik.bme.hu>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-07-09 10:55:11 +10:00

91 lines
1.8 KiB
C

#include "vof.h"
struct prom_args {
uint32_t service;
uint32_t nargs;
uint32_t nret;
uint32_t args[10];
};
typedef unsigned long prom_arg_t;
#define ADDR(x) (uint32_t)(x)
static int prom_handle(struct prom_args *pargs)
{
void *rtasbase;
uint32_t rtassize = 0;
phandle rtas;
if (strcmp("call-method", (void *)(unsigned long)pargs->service)) {
return -1;
}
if (strcmp("instantiate-rtas", (void *)(unsigned long)pargs->args[0])) {
return -1;
}
rtas = ci_finddevice("/rtas");
/* rtas-size is set by QEMU depending of FWNMI support */
ci_getprop(rtas, "rtas-size", &rtassize, sizeof(rtassize));
if (rtassize < hv_rtas_size) {
return -1;
}
rtasbase = (void *)(unsigned long) pargs->args[2];
memcpy(rtasbase, hv_rtas, hv_rtas_size);
pargs->args[pargs->nargs] = 0;
pargs->args[pargs->nargs + 1] = pargs->args[2];
return 0;
}
void prom_entry(uint32_t args)
{
if (prom_handle((void *)(unsigned long) args)) {
ci_entry(args);
}
}
static int call_ci(const char *service, int nargs, int nret, ...)
{
int i;
struct prom_args args;
va_list list;
args.service = ADDR(service);
args.nargs = nargs;
args.nret = nret;
va_start(list, nret);
for (i = 0; i < nargs; i++) {
args.args[i] = va_arg(list, prom_arg_t);
}
va_end(list);
for (i = 0; i < nret; i++) {
args.args[nargs + i] = 0;
}
if (ci_entry((uint32_t)(&args)) < 0) {
return -1;
}
return (nret > 0) ? args.args[nargs] : 0;
}
void ci_panic(const char *str)
{
call_ci("exit", 0, 0);
}
phandle ci_finddevice(const char *path)
{
return call_ci("finddevice", 1, 1, path);
}
uint32_t ci_getprop(phandle ph, const char *propname, void *prop, int len)
{
return call_ci("getprop", 4, 1, ph, propname, prop, len);
}